(no commit message)
authorSapan Bhatia <sapanb@cs.princeton.edu>
Thu, 24 Jan 2008 04:18:23 +0000 (04:18 +0000)
committerSapan Bhatia <sapanb@cs.princeton.edu>
Thu, 24 Jan 2008 04:18:23 +0000 (04:18 +0000)
linux-2.6-590-trellis-mm1-netns.patch

index 7311dac..22a0b86 100644 (file)
-diff -Nurb linux-2.6.22-570/.config.orig linux-2.6.22-590/.config.orig
---- linux-2.6.22-570/.config.orig      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/.config.orig      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,1693 @@
-+#
-+# Automatically generated make config: don't edit
-+# Linux kernel version: 2.6.22-prep
-+# Fri Dec 21 15:54:46 2007
-+#
-+CONFIG_X86_32=y
-+CONFIG_GENERIC_TIME=y
-+CONFIG_CLOCKSOURCE_WATCHDOG=y
-+CONFIG_GENERIC_CLOCKEVENTS=y
-+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
-+CONFIG_LOCKDEP_SUPPORT=y
-+CONFIG_STACKTRACE_SUPPORT=y
-+CONFIG_SEMAPHORE_SLEEPERS=y
-+CONFIG_X86=y
-+CONFIG_MMU=y
-+CONFIG_ZONE_DMA=y
-+CONFIG_QUICKLIST=y
-+CONFIG_GENERIC_ISA_DMA=y
-+CONFIG_GENERIC_IOMAP=y
-+CONFIG_GENERIC_BUG=y
-+CONFIG_GENERIC_HWEIGHT=y
-+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-+CONFIG_DMI=y
-+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+CONFIG_LOCK_KERNEL=y
-+CONFIG_INIT_ENV_ARG_LIMIT=32
-+
-+#
-+# General setup
-+#
-+CONFIG_LOCALVERSION=""
-+CONFIG_LOCALVERSION_AUTO=y
-+CONFIG_SWAP=y
-+CONFIG_SYSVIPC=y
-+CONFIG_SYSVIPC_SYSCTL=y
-+CONFIG_POSIX_MQUEUE=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+# CONFIG_TASKSTATS is not set
-+# CONFIG_USER_NS is not set
-+# CONFIG_AUDIT is not set
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
-+CONFIG_LOG_BUF_SHIFT=18
-+CONFIG_OOM_PANIC=y
-+# CONFIG_CONTAINER_DEBUG is not set
-+# CONFIG_CPUSETS is not set
-+CONFIG_SYSFS_DEPRECATED=y
-+# CONFIG_CONTAINER_CPUACCT is not set
-+# CONFIG_CONTAINER_NS is not set
-+# CONFIG_RELAY is not set
-+CONFIG_BLK_DEV_INITRD=y
-+CONFIG_INITRAMFS_SOURCE=""
-+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-+CONFIG_SYSCTL=y
-+# CONFIG_EMBEDDED is not set
-+CONFIG_UID16=y
-+CONFIG_SYSCTL_SYSCALL=y
-+CONFIG_KALLSYMS=y
-+CONFIG_KALLSYMS_ALL=y
-+# 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_ANON_INODES=y
-+CONFIG_EPOLL=y
-+CONFIG_SIGNALFD=y
-+CONFIG_EVENTFD=y
-+CONFIG_SHMEM=y
-+CONFIG_VM_EVENT_COUNTERS=y
-+CONFIG_SLAB=y
-+# CONFIG_SLUB is not set
-+# CONFIG_SLOB is not set
-+CONFIG_PROC_SMAPS=y
-+CONFIG_PROC_CLEAR_REFS=y
-+CONFIG_PROC_PAGEMAP=y
-+CONFIG_RT_MUTEXES=y
-+# CONFIG_TINY_SHMEM is not set
-+CONFIG_BASE_SMALL=0
-+CONFIG_PAGE_GROUP_BY_MOBILITY=y
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+CONFIG_MODULE_UNLOAD=y
-+CONFIG_MODULE_FORCE_UNLOAD=y
-+# CONFIG_MODVERSIONS is not set
-+# CONFIG_MODULE_SRCVERSION_ALL is not set
-+# CONFIG_KMOD is not set
-+CONFIG_STOP_MACHINE=y
-+
-+#
-+# Block layer
-+#
-+CONFIG_BLOCK=y
-+CONFIG_LBD=y
-+# CONFIG_BLK_DEV_IO_TRACE is not set
-+# CONFIG_LSF is not set
-+
-+#
-+# 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"
-+
-+#
-+# Processor type and features
-+#
-+# CONFIG_TICK_ONESHOT is not set
-+# CONFIG_NO_HZ is not set
-+# CONFIG_HIGH_RES_TIMERS is not set
-+CONFIG_SMP=y
-+# CONFIG_X86_PC is not set
-+# CONFIG_X86_ELAN is not set
-+# CONFIG_X86_VOYAGER is not set
-+# CONFIG_X86_NUMAQ is not set
-+# CONFIG_X86_SUMMIT is not set
-+# CONFIG_X86_BIGSMP is not set
-+# CONFIG_X86_VISWS is not set
-+CONFIG_X86_GENERICARCH=y
-+# CONFIG_X86_ES7000 is not set
-+# CONFIG_PARAVIRT is not set
-+CONFIG_X86_CYCLONE_TIMER=y
-+# CONFIG_M386 is not set
-+# CONFIG_M486 is not set
-+# CONFIG_M586 is not set
-+# CONFIG_M586TSC is not set
-+# CONFIG_M586MMX is not set
-+# CONFIG_M686 is not set
-+# CONFIG_MPENTIUMII is not set
-+CONFIG_MPENTIUMIII=y
-+# CONFIG_MPENTIUMM is not set
-+# CONFIG_MCORE2 is not set
-+# CONFIG_MPENTIUM4 is not set
-+# CONFIG_MK6 is not set
-+# CONFIG_MK7 is not set
-+# CONFIG_MK8 is not set
-+# CONFIG_MCRUSOE is not set
-+# CONFIG_MEFFICEON is not set
-+# CONFIG_MWINCHIPC6 is not set
-+# CONFIG_MWINCHIP2 is not set
-+# CONFIG_MWINCHIP3D is not set
-+# CONFIG_MGEODEGX1 is not set
-+# CONFIG_MGEODE_LX is not set
-+# CONFIG_MCYRIXIII is not set
-+# CONFIG_MVIAC3_2 is not set
-+# CONFIG_MVIAC7 is not set
-+CONFIG_X86_GENERIC=y
-+CONFIG_X86_CMPXCHG=y
-+CONFIG_X86_L1_CACHE_SHIFT=7
-+CONFIG_X86_XADD=y
-+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-+CONFIG_GENERIC_CALIBRATE_DELAY=y
-+CONFIG_X86_WP_WORKS_OK=y
-+CONFIG_X86_INVLPG=y
-+CONFIG_X86_BSWAP=y
-+CONFIG_X86_POPAD_OK=y
-+CONFIG_X86_GOOD_APIC=y
-+CONFIG_X86_INTEL_USERCOPY=y
-+CONFIG_X86_USE_PPRO_CHECKSUM=y
-+CONFIG_X86_TSC=y
-+CONFIG_X86_CMOV=y
-+CONFIG_X86_MINIMUM_CPU_MODEL=4
-+CONFIG_HPET_TIMER=y
-+CONFIG_HPET_EMULATE_RTC=y
-+CONFIG_NR_CPUS=32
-+CONFIG_SCHED_SMT=y
-+CONFIG_SCHED_MC=y
-+# CONFIG_PREEMPT_NONE is not set
-+CONFIG_PREEMPT_VOLUNTARY=y
-+# CONFIG_PREEMPT is not set
-+CONFIG_PREEMPT_BKL=y
-+CONFIG_X86_LOCAL_APIC=y
-+CONFIG_X86_IO_APIC=y
-+CONFIG_X86_MCE=y
-+CONFIG_X86_MCE_NONFATAL=y
-+CONFIG_X86_MCE_P4THERMAL=y
-+CONFIG_VM86=y
-+# CONFIG_TOSHIBA is not set
-+# CONFIG_I8K is not set
-+# CONFIG_X86_REBOOTFIXUPS is not set
-+CONFIG_MICROCODE=y
-+CONFIG_MICROCODE_OLD_INTERFACE=y
-+CONFIG_X86_MSR=y
-+CONFIG_X86_CPUID=y
-+
-+#
-+# Firmware Drivers
-+#
-+# CONFIG_EDD is not set
-+# CONFIG_DELL_RBU is not set
-+# CONFIG_DCDBAS is not set
-+# CONFIG_NOHIGHMEM is not set
-+CONFIG_HIGHMEM4G=y
-+# CONFIG_HIGHMEM64G is not set
-+CONFIG_PAGE_OFFSET=0xC0000000
-+CONFIG_HIGHMEM=y
-+CONFIG_ARCH_POPULATES_NODE_MAP=y
-+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=4
-+CONFIG_RESOURCES_64BIT=y
-+CONFIG_ZONE_DMA_FLAG=1
-+CONFIG_NR_QUICK=1
-+# CONFIG_HIGHPTE is not set
-+# CONFIG_MATH_EMULATION is not set
-+CONFIG_MTRR=y
-+# CONFIG_EFI is not set
-+# CONFIG_IRQBALANCE is not set
-+CONFIG_SECCOMP=y
-+# CONFIG_HZ_100 is not set
-+CONFIG_HZ_250=y
-+# CONFIG_HZ_300 is not set
-+# CONFIG_HZ_1000 is not set
-+CONFIG_HZ=250
-+CONFIG_KEXEC=y
-+# CONFIG_CRASH_DUMP is not set
-+CONFIG_PHYSICAL_START=0x100000
-+# CONFIG_RELOCATABLE is not set
-+CONFIG_PHYSICAL_ALIGN=0x100000
-+# CONFIG_HOTPLUG_CPU is not set
-+CONFIG_COMPAT_VDSO=y
-+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-+
-+#
-+# Power management options (ACPI, APM)
-+#
-+CONFIG_PM=y
-+CONFIG_PM_LEGACY=y
-+# CONFIG_PM_DEBUG is not set
-+CONFIG_PM_SYSFS_DEPRECATED=y
-+
-+#
-+# ACPI (Advanced Configuration and Power Interface) Support
-+#
-+CONFIG_ACPI=y
-+CONFIG_ACPI_PROCFS=y
-+CONFIG_ACPI_AC=y
-+CONFIG_ACPI_BATTERY=y
-+CONFIG_ACPI_BUTTON=y
-+CONFIG_ACPI_FAN=y
-+# CONFIG_ACPI_DOCK is not set
-+CONFIG_ACPI_PROCESSOR=y
-+CONFIG_ACPI_THERMAL=y
-+# CONFIG_ACPI_ASUS is not set
-+# CONFIG_ACPI_TOSHIBA is not set
-+CONFIG_ACPI_BLACKLIST_YEAR=2001
-+CONFIG_ACPI_DEBUG=y
-+# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
-+CONFIG_ACPI_EC=y
-+CONFIG_ACPI_POWER=y
-+CONFIG_ACPI_SYSTEM=y
-+CONFIG_X86_PM_TIMER=y
-+# CONFIG_ACPI_CONTAINER is not set
-+# CONFIG_ACPI_SBS is not set
-+# CONFIG_APM 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 is not set
-+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-+CONFIG_CPU_FREQ_GOV_USERSPACE=y
-+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
-+
-+#
-+# CPUFreq processor drivers
-+#
-+CONFIG_X86_ACPI_CPUFREQ=y
-+# CONFIG_X86_POWERNOW_K6 is not set
-+# CONFIG_X86_POWERNOW_K7 is not set
-+CONFIG_X86_POWERNOW_K8=y
-+CONFIG_X86_POWERNOW_K8_ACPI=y
-+# CONFIG_X86_GX_SUSPMOD is not set
-+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
-+# CONFIG_X86_SPEEDSTEP_ICH is not set
-+# CONFIG_X86_SPEEDSTEP_SMI is not set
-+# CONFIG_X86_P4_CLOCKMOD is not set
-+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
-+# CONFIG_X86_LONGRUN is not set
-+# CONFIG_X86_LONGHAUL is not set
-+# CONFIG_X86_E_POWERSAVER is not set
-+
-+#
-+# shared options
-+#
-+CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y
-+# CONFIG_X86_SPEEDSTEP_LIB is not set
-+
-+#
-+# CPU idle PM support
-+#
-+# CONFIG_CPU_IDLE is not set
-+
-+#
-+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-+#
-+CONFIG_PCI=y
-+# CONFIG_PCI_GOBIOS is not set
-+# CONFIG_PCI_GOMMCONFIG is not set
-+# CONFIG_PCI_GODIRECT is not set
-+CONFIG_PCI_GOANY=y
-+CONFIG_PCI_BIOS=y
-+CONFIG_PCI_DIRECT=y
-+CONFIG_PCI_MMCONFIG=y
-+# CONFIG_PCIEPORTBUS is not set
-+CONFIG_ARCH_SUPPORTS_MSI=y
-+CONFIG_PCI_MSI=y
-+# CONFIG_PCI_DEBUG is not set
-+# CONFIG_HT_IRQ is not set
-+CONFIG_ISA_DMA_API=y
-+# CONFIG_ISA is not set
-+# CONFIG_MCA is not set
-+# CONFIG_SCx200 is not set
-+
-+#
-+# PCCARD (PCMCIA/CardBus) support
-+#
-+# CONFIG_PCCARD is not set
-+# CONFIG_HOTPLUG_PCI is not set
-+
-+#
-+# Executable file formats
-+#
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_AOUT is not set
-+# CONFIG_BINFMT_MISC is not set
-+
-+#
-+# Networking
-+#
-+CONFIG_NET=y
-+
-+#
-+# Networking options
-+#
-+# CONFIG_NET_NS is not set
-+CONFIG_PACKET=y
-+# CONFIG_PACKET_MMAP is not set
-+CONFIG_UNIX=y
-+CONFIG_XFRM=y
-+# CONFIG_XFRM_USER is not set
-+# CONFIG_XFRM_SUB_POLICY is not set
-+# CONFIG_XFRM_MIGRATE is not set
-+# 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 is not set
-+# CONFIG_IP_PNP_RARP is not set
-+# 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 is not set
-+# CONFIG_INET_AH is not set
-+# CONFIG_INET_ESP is not set
-+# CONFIG_INET_IPCOMP is not set
-+# CONFIG_INET_XFRM_TUNNEL is not set
-+CONFIG_INET_TUNNEL=y
-+CONFIG_INET_XFRM_MODE_TRANSPORT=y
-+CONFIG_INET_XFRM_MODE_TUNNEL=y
-+# CONFIG_INET_XFRM_MODE_BEET is not set
-+CONFIG_INET_DIAG=y
-+CONFIG_INET_TCP_DIAG=y
-+# CONFIG_TCP_CONG_ADVANCED is not set
-+CONFIG_TCP_CONG_CUBIC=y
-+CONFIG_DEFAULT_TCP_CONG="cubic"
-+# CONFIG_TCP_MD5SIG is not set
-+# CONFIG_IP_VS is not set
-+# CONFIG_ICMP_IPOD is not set
-+CONFIG_IPV6=y
-+# CONFIG_IPV6_PRIVACY is not set
-+# CONFIG_IPV6_ROUTER_PREF is not set
-+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
-+# CONFIG_INET6_AH is not set
-+# CONFIG_INET6_ESP is not set
-+# CONFIG_INET6_IPCOMP is not set
-+# CONFIG_IPV6_MIP6 is not set
-+# CONFIG_INET6_XFRM_TUNNEL is not set
-+# CONFIG_INET6_TUNNEL is not set
-+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
-+CONFIG_INET6_XFRM_MODE_TUNNEL=y
-+# CONFIG_INET6_XFRM_MODE_BEET is not set
-+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
-+CONFIG_IPV6_SIT=y
-+# CONFIG_IPV6_TUNNEL is not set
-+# CONFIG_IPV6_MULTIPLE_TABLES is not set
-+# CONFIG_NETWORK_SECMARK is not set
-+CONFIG_NETFILTER=y
-+# CONFIG_NETFILTER_DEBUG is not set
-+
-+#
-+# Core Netfilter Configuration
-+#
-+# CONFIG_NETFILTER_NETLINK is not set
-+CONFIG_NF_CONNTRACK_ENABLED=m
-+CONFIG_NF_CONNTRACK=m
-+# CONFIG_NF_CT_ACCT is not set
-+# CONFIG_NF_CONNTRACK_MARK is not set
-+# CONFIG_NF_CONNTRACK_EVENTS is not set
-+# CONFIG_NF_CT_PROTO_SCTP is not set
-+# CONFIG_NF_CONNTRACK_AMANDA is not set
-+# CONFIG_NF_CONNTRACK_FTP is not set
-+# CONFIG_NF_CONNTRACK_H323 is not set
-+# CONFIG_NF_CONNTRACK_IRC is not set
-+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
-+# CONFIG_NF_CONNTRACK_PPTP is not set
-+# CONFIG_NF_CONNTRACK_SANE is not set
-+# CONFIG_NF_CONNTRACK_SIP is not set
-+# CONFIG_NF_CONNTRACK_TFTP is not set
-+CONFIG_NETFILTER_XTABLES=m
-+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
-+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
-+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
-+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
-+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
-+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
-+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
-+# CONFIG_NETFILTER_XT_TARGET_SETXID is not set
-+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
-+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
-+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
-+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
-+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
-+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
-+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
-+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
-+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
-+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
-+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
-+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
-+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
-+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
-+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
-+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
-+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
-+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
-+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
-+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
-+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
-+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
-+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
-+
-+#
-+# IP: Netfilter Configuration
-+#
-+CONFIG_NF_CONNTRACK_IPV4=m
-+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
-+# CONFIG_IP_NF_QUEUE is not set
-+CONFIG_IP_NF_IPTABLES=m
-+# CONFIG_IP_NF_MATCH_IPRANGE is not set
-+# CONFIG_IP_NF_MATCH_TOS is not set
-+# CONFIG_IP_NF_MATCH_RECENT is not set
-+# CONFIG_IP_NF_MATCH_ECN is not set
-+# CONFIG_IP_NF_MATCH_AH is not set
-+# CONFIG_IP_NF_MATCH_TTL is not set
-+# CONFIG_IP_NF_MATCH_OWNER is not set
-+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-+CONFIG_IP_NF_FILTER=m
-+# CONFIG_IP_NF_TARGET_REJECT is not set
-+# CONFIG_IP_NF_TARGET_LOG is not set
-+# CONFIG_IP_NF_TARGET_ULOG is not set
-+CONFIG_NF_NAT=m
-+CONFIG_NF_NAT_NEEDED=y
-+# CONFIG_IP_NF_TARGET_MASQUERADE is not set
-+# CONFIG_IP_NF_TARGET_REDIRECT is not set
-+# CONFIG_IP_NF_TARGET_NETMAP is not set
-+# CONFIG_IP_NF_TARGET_SAME is not set
-+# CONFIG_NF_NAT_SNMP_BASIC is not set
-+# CONFIG_NF_NAT_FTP is not set
-+# CONFIG_NF_NAT_IRC is not set
-+# CONFIG_NF_NAT_TFTP is not set
-+# CONFIG_NF_NAT_AMANDA is not set
-+# CONFIG_NF_NAT_PPTP is not set
-+# CONFIG_NF_NAT_H323 is not set
-+# CONFIG_NF_NAT_SIP is not set
-+CONFIG_IP_NF_MANGLE=m
-+# CONFIG_IP_NF_TARGET_TOS is not set
-+# CONFIG_IP_NF_TARGET_ECN is not set
-+# CONFIG_IP_NF_TARGET_TTL is not set
-+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
-+# CONFIG_IP_NF_RAW is not set
-+# CONFIG_IP_NF_ARPTABLES is not set
-+# CONFIG_IP_NF_SET is not set
-+
-+#
-+# IPv6: Netfilter Configuration (EXPERIMENTAL)
-+#
-+# CONFIG_NF_CONNTRACK_IPV6 is not set
-+# CONFIG_IP6_NF_QUEUE is not set
-+# CONFIG_IP6_NF_IPTABLES is not set
-+# CONFIG_IP_DCCP is not set
-+# CONFIG_IP_SCTP is not set
-+# CONFIG_TIPC is not set
-+# CONFIG_ATM is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_LLC2 is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+CONFIG_NET_PKTGEN=m
-+# CONFIG_NET_TCPPROBE is not set
-+# CONFIG_HAMRADIO is not set
-+# CONFIG_IRDA is not set
-+# CONFIG_BT is not set
-+# CONFIG_AF_RXRPC is not set
-+
-+#
-+# Wireless
-+#
-+# CONFIG_CFG80211 is not set
-+# CONFIG_WIRELESS_EXT is not set
-+# CONFIG_MAC80211 is not set
-+# CONFIG_IEEE80211 is not set
-+# CONFIG_RFKILL 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
-+# CONFIG_DEBUG_DEVRES is not set
-+# CONFIG_SYS_HYPERVISOR is not set
-+
-+#
-+# Connector - unified userspace <-> kernelspace linker
-+#
-+CONFIG_CONNECTOR=m
-+# CONFIG_MTD is not set
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Plug and Play support
-+#
-+CONFIG_PNP=y
-+# CONFIG_PNP_DEBUG is not set
-+
-+#
-+# Protocols
-+#
-+CONFIG_PNPACPI=y
-+
-+#
-+# Block devices
-+#
-+CONFIG_BLK_DEV_FD=y
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+# CONFIG_BLK_DEV_COW_COMMON is not set
-+CONFIG_BLK_DEV_LOOP=y
-+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-+# CONFIG_BLK_DEV_NBD is not set
-+# CONFIG_BLK_DEV_SX8 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=4096
-+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-+# CONFIG_CDROM_PKTCDVD is not set
-+# CONFIG_ATA_OVER_ETH is not set
-+
-+#
-+# Misc devices
-+#
-+# CONFIG_IBM_ASM is not set
-+# CONFIG_PHANTOM is not set
-+# CONFIG_SGI_IOC4 is not set
-+# CONFIG_TIFM_CORE is not set
-+# CONFIG_SONY_LAPTOP is not set
-+# CONFIG_THINKPAD_ACPI is not set
-+CONFIG_IDE=y
-+CONFIG_BLK_DEV_IDE=y
-+
-+#
-+# Please see Documentation/ide.txt for help/info on IDE drives
-+#
-+# CONFIG_BLK_DEV_IDE_SATA is not set
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+CONFIG_BLK_DEV_IDEDISK=y
-+CONFIG_IDEDISK_MULTI_MODE=y
-+CONFIG_BLK_DEV_IDECD=y
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_BLK_DEV_IDEACPI is not set
-+# CONFIG_IDE_TASK_IOCTL is not set
-+CONFIG_IDE_PROC_FS=y
-+
-+#
-+# IDE chipset support/bugfixes
-+#
-+CONFIG_IDE_GENERIC=y
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_IDEPNP is not set
-+CONFIG_BLK_DEV_IDEPCI=y
-+# CONFIG_IDEPCI_SHARE_IRQ is not set
-+CONFIG_IDEPCI_PCIBUS_ORDER=y
-+# CONFIG_BLK_DEV_OFFBOARD is not set
-+# CONFIG_BLK_DEV_GENERIC is not set
-+# CONFIG_BLK_DEV_OPTI621 is not set
-+# CONFIG_BLK_DEV_RZ1000 is not set
-+CONFIG_BLK_DEV_IDEDMA_PCI=y
-+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-+# CONFIG_IDEDMA_ONLYDISK is not set
-+# CONFIG_BLK_DEV_AEC62XX is not set
-+# CONFIG_BLK_DEV_ALI15X3 is not set
-+CONFIG_BLK_DEV_AMD74XX=y
-+# CONFIG_BLK_DEV_ATIIXP is not set
-+# CONFIG_BLK_DEV_CMD64X is not set
-+# CONFIG_BLK_DEV_TRIFLEX is not set
-+# CONFIG_BLK_DEV_CY82C693 is not set
-+# CONFIG_BLK_DEV_CS5520 is not set
-+# CONFIG_BLK_DEV_CS5530 is not set
-+# CONFIG_BLK_DEV_CS5535 is not set
-+# CONFIG_BLK_DEV_HPT34X is not set
-+# CONFIG_BLK_DEV_HPT366 is not set
-+# CONFIG_BLK_DEV_JMICRON is not set
-+# CONFIG_BLK_DEV_SC1200 is not set
-+CONFIG_BLK_DEV_PIIX=y
-+# CONFIG_BLK_DEV_IT8213 is not set
-+# CONFIG_BLK_DEV_IT821X is not set
-+# CONFIG_BLK_DEV_NS87415 is not set
-+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-+# CONFIG_BLK_DEV_SVWKS is not set
-+# CONFIG_BLK_DEV_SIIMAGE is not set
-+# CONFIG_BLK_DEV_SIS5513 is not set
-+# CONFIG_BLK_DEV_SLC90E66 is not set
-+# CONFIG_BLK_DEV_TRM290 is not set
-+# CONFIG_BLK_DEV_VIA82CXXX is not set
-+# CONFIG_BLK_DEV_TC86C001 is not set
-+# CONFIG_IDE_ARM is not set
-+CONFIG_BLK_DEV_IDEDMA=y
-+# CONFIG_IDEDMA_IVB is not set
-+# CONFIG_BLK_DEV_HD is not set
-+
-+#
-+# SCSI device support
-+#
-+# CONFIG_RAID_ATTRS is not set
-+CONFIG_SCSI=y
-+# CONFIG_SCSI_TGT is not set
-+CONFIG_SCSI_NETLINK=y
-+# CONFIG_SCSI_PROC_FS is not set
-+
-+#
-+# SCSI support type (disk, tape, CD-ROM)
-+#
-+CONFIG_BLK_DEV_SD=y
-+# CONFIG_CHR_DEV_ST is not set
-+# CONFIG_CHR_DEV_OSST is not set
-+CONFIG_BLK_DEV_SR=y
-+# CONFIG_BLK_DEV_SR_VENDOR is not set
-+CONFIG_CHR_DEV_SG=y
-+# CONFIG_CHR_DEV_SCH is not set
-+
-+#
-+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-+#
-+# CONFIG_SCSI_MULTI_LUN is not set
-+# CONFIG_SCSI_CONSTANTS is not set
-+# CONFIG_SCSI_LOGGING is not set
-+# CONFIG_SCSI_SCAN_ASYNC is not set
-+CONFIG_SCSI_WAIT_SCAN=m
-+
-+#
-+# SCSI Transports
-+#
-+CONFIG_SCSI_SPI_ATTRS=y
-+CONFIG_SCSI_FC_ATTRS=y
-+# CONFIG_SCSI_ISCSI_ATTRS is not set
-+# CONFIG_SCSI_SAS_ATTRS is not set
-+# CONFIG_SCSI_SAS_LIBSAS is not set
-+
-+#
-+# SCSI low-level drivers
-+#
-+# CONFIG_ISCSI_TCP is not set
-+CONFIG_BLK_DEV_3W_XXXX_RAID=y
-+# CONFIG_SCSI_3W_9XXX is not set
-+# CONFIG_SCSI_ACARD is not set
-+# CONFIG_SCSI_AACRAID is not set
-+CONFIG_SCSI_AIC7XXX=y
-+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
-+CONFIG_AIC7XXX_RESET_DELAY_MS=5000
-+CONFIG_AIC7XXX_DEBUG_ENABLE=y
-+CONFIG_AIC7XXX_DEBUG_MASK=0
-+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
-+# CONFIG_SCSI_AIC7XXX_OLD is not set
-+CONFIG_SCSI_AIC79XX=y
-+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
-+CONFIG_AIC79XX_RESET_DELAY_MS=4000
-+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
-+CONFIG_AIC79XX_DEBUG_MASK=0
-+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
-+# CONFIG_SCSI_AIC94XX is not set
-+# CONFIG_SCSI_DPT_I2O is not set
-+# CONFIG_SCSI_ADVANSYS is not set
-+# CONFIG_SCSI_ARCMSR is not set
-+# CONFIG_MEGARAID_NEWGEN is not set
-+# CONFIG_MEGARAID_LEGACY is not set
-+# CONFIG_MEGARAID_SAS is not set
-+# CONFIG_SCSI_HPTIOP is not set
-+# CONFIG_SCSI_BUSLOGIC is not set
-+# CONFIG_SCSI_DMX3191D is not set
-+# CONFIG_SCSI_EATA is not set
-+# CONFIG_SCSI_FUTURE_DOMAIN is not set
-+# CONFIG_SCSI_GDTH is not set
-+# CONFIG_SCSI_IPS is not set
-+# CONFIG_SCSI_INITIO is not set
-+# CONFIG_SCSI_INIA100 is not set
-+# CONFIG_SCSI_STEX is not set
-+# CONFIG_SCSI_SYM53C8XX_2 is not set
-+# CONFIG_SCSI_IPR is not set
-+# CONFIG_SCSI_QLOGIC_1280 is not set
-+# CONFIG_SCSI_QLA_FC is not set
-+# CONFIG_SCSI_QLA_ISCSI is not set
-+# CONFIG_SCSI_LPFC is not set
-+# CONFIG_SCSI_DC395x is not set
-+# CONFIG_SCSI_DC390T is not set
-+# CONFIG_SCSI_NSP32 is not set
-+# CONFIG_SCSI_DEBUG is not set
-+# CONFIG_SCSI_SRP is not set
-+CONFIG_ATA=y
-+# CONFIG_ATA_NONSTANDARD is not set
-+CONFIG_ATA_ACPI=y
-+CONFIG_SATA_AHCI=y
-+CONFIG_SATA_SVW=y
-+CONFIG_ATA_PIIX=y
-+# CONFIG_SATA_MV is not set
-+CONFIG_SATA_NV=y
-+# CONFIG_PDC_ADMA is not set
-+# CONFIG_SATA_QSTOR is not set
-+# CONFIG_SATA_PROMISE is not set
-+# CONFIG_SATA_SX4 is not set
-+CONFIG_SATA_SIL=y
-+# CONFIG_SATA_SIL24 is not set
-+# CONFIG_SATA_SIS is not set
-+# CONFIG_SATA_ULI is not set
-+CONFIG_SATA_VIA=y
-+# CONFIG_SATA_VITESSE is not set
-+# CONFIG_SATA_INIC162X is not set
-+# CONFIG_PATA_ALI is not set
-+# CONFIG_PATA_AMD is not set
-+# CONFIG_PATA_ARTOP is not set
-+# CONFIG_PATA_ATIIXP is not set
-+# CONFIG_PATA_CMD640_PCI is not set
-+# CONFIG_PATA_CMD64X is not set
-+# CONFIG_PATA_CS5520 is not set
-+# CONFIG_PATA_CS5530 is not set
-+# CONFIG_PATA_CS5535 is not set
-+# CONFIG_PATA_CYPRESS is not set
-+# CONFIG_PATA_EFAR is not set
-+# CONFIG_ATA_GENERIC is not set
-+# CONFIG_PATA_HPT366 is not set
-+# CONFIG_PATA_HPT37X is not set
-+# CONFIG_PATA_HPT3X2N is not set
-+# CONFIG_PATA_HPT3X3 is not set
-+# CONFIG_PATA_IT821X is not set
-+# CONFIG_PATA_IT8213 is not set
-+# CONFIG_PATA_JMICRON is not set
-+# CONFIG_PATA_TRIFLEX is not set
-+# CONFIG_PATA_MARVELL is not set
-+# CONFIG_PATA_MPIIX is not set
-+# CONFIG_PATA_OLDPIIX is not set
-+# CONFIG_PATA_NETCELL is not set
-+# CONFIG_PATA_NS87410 is not set
-+# CONFIG_PATA_OPTI is not set
-+# CONFIG_PATA_OPTIDMA is not set
-+# CONFIG_PATA_PDC_OLD is not set
-+# CONFIG_PATA_RADISYS is not set
-+# CONFIG_PATA_RZ1000 is not set
-+# CONFIG_PATA_SC1200 is not set
-+# CONFIG_PATA_SERVERWORKS is not set
-+# CONFIG_PATA_PDC2027X is not set
-+# CONFIG_PATA_SIL680 is not set
-+# CONFIG_PATA_SIS is not set
-+# CONFIG_PATA_VIA is not set
-+# CONFIG_PATA_WINBOND is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+CONFIG_MD=y
-+# CONFIG_BLK_DEV_MD is not set
-+CONFIG_BLK_DEV_DM=y
-+# CONFIG_DM_DEBUG is not set
-+# CONFIG_DM_CRYPT is not set
-+# CONFIG_DM_SNAPSHOT is not set
-+# CONFIG_DM_MIRROR is not set
-+# CONFIG_DM_ZERO is not set
-+# CONFIG_DM_MULTIPATH is not set
-+# CONFIG_DM_DELAY is not set
-+# CONFIG_DM_NETLINK is not set
-+
-+#
-+# Fusion MPT device support
-+#
-+CONFIG_FUSION=y
-+CONFIG_FUSION_SPI=y
-+# CONFIG_FUSION_FC is not set
-+# CONFIG_FUSION_SAS is not set
-+CONFIG_FUSION_MAX_SGE=128
-+# CONFIG_FUSION_CTL is not set
-+
-+#
-+# IEEE 1394 (FireWire) support
-+#
-+# CONFIG_FIREWIRE is not set
-+CONFIG_IEEE1394=y
-+
-+#
-+# Subsystem Options
-+#
-+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-+
-+#
-+# Controllers
-+#
-+
-+#
-+# Texas Instruments PCILynx requires I2C
-+#
-+CONFIG_IEEE1394_OHCI1394=y
-+
-+#
-+# Protocols
-+#
-+# CONFIG_IEEE1394_VIDEO1394 is not set
-+# CONFIG_IEEE1394_SBP2 is not set
-+# CONFIG_IEEE1394_ETH1394_ROM_ENTRY is not set
-+# CONFIG_IEEE1394_ETH1394 is not set
-+# CONFIG_IEEE1394_DV1394 is not set
-+CONFIG_IEEE1394_RAWIO=y
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_MACINTOSH_DRIVERS is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+CONFIG_TUN=m
-+# CONFIG_ETUN is not set
-+# CONFIG_NET_SB1000 is not set
-+# CONFIG_ARCNET is not set
-+# CONFIG_PHYLIB is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+CONFIG_MII=y
-+# CONFIG_HAPPYMEAL is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_CASSINI is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+
-+#
-+# Tulip family network device support
-+#
-+CONFIG_NET_TULIP=y
-+# CONFIG_DE2104X is not set
-+CONFIG_TULIP=y
-+# CONFIG_TULIP_MWI is not set
-+# CONFIG_TULIP_MMIO is not set
-+# CONFIG_TULIP_NAPI is not set
-+# CONFIG_DE4X5 is not set
-+# CONFIG_WINBOND_840 is not set
-+# CONFIG_DM9102 is not set
-+# CONFIG_ULI526X is not set
-+# CONFIG_HP100 is not set
-+CONFIG_NET_PCI=y
-+# CONFIG_PCNET32 is not set
-+# CONFIG_AMD8111_ETH is not set
-+# CONFIG_ADAPTEC_STARFIRE is not set
-+CONFIG_B44=y
-+CONFIG_FORCEDETH=y
-+# CONFIG_FORCEDETH_NAPI is not set
-+# CONFIG_DGRS is not set
-+# CONFIG_EEPRO100 is not set
-+CONFIG_E100=y
-+# CONFIG_FEALNX is not set
-+# CONFIG_NATSEMI is not set
-+# CONFIG_NE2K_PCI is not set
-+CONFIG_8139CP=y
-+CONFIG_8139TOO=y
-+# CONFIG_8139TOO_PIO is not set
-+# CONFIG_8139TOO_TUNE_TWISTER is not set
-+# CONFIG_8139TOO_8129 is not set
-+# CONFIG_8139_OLD_RX_RESET is not set
-+# CONFIG_SIS900 is not set
-+# CONFIG_EPIC100 is not set
-+# CONFIG_SUNDANCE is not set
-+# CONFIG_TLAN is not set
-+# CONFIG_VIA_RHINE is not set
-+# CONFIG_SC92031 is not set
-+CONFIG_NETDEV_1000=y
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+CONFIG_E1000=y
-+# CONFIG_E1000_NAPI is not set
-+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
-+# CONFIG_E1000E is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+CONFIG_R8169=y
-+# CONFIG_R8169_NAPI is not set
-+# CONFIG_SIS190 is not set
-+# CONFIG_SKGE is not set
-+CONFIG_SKY2=y
-+# CONFIG_SK98LIN is not set
-+# CONFIG_VIA_VELOCITY is not set
-+CONFIG_TIGON3=y
-+CONFIG_BNX2=y
-+# CONFIG_QLA3XXX is not set
-+# CONFIG_ATL1 is not set
-+CONFIG_NETDEV_10000=y
-+# CONFIG_CHELSIO_T1 is not set
-+# CONFIG_CHELSIO_T3 is not set
-+# CONFIG_IXGB is not set
-+# CONFIG_S2IO is not set
-+# CONFIG_MYRI10GE is not set
-+# CONFIG_NETXEN_NIC is not set
-+# CONFIG_MLX4_CORE is not set
-+# CONFIG_TR is not set
-+
-+#
-+# Wireless LAN
-+#
-+# CONFIG_WLAN_PRE80211 is not set
-+# CONFIG_WLAN_80211 is not set
-+
-+#
-+# USB Network Adapters
-+#
-+# CONFIG_USB_CATC is not set
-+# CONFIG_USB_KAWETH is not set
-+# CONFIG_USB_PEGASUS is not set
-+# CONFIG_USB_RTL8150 is not set
-+# CONFIG_USB_USBNET_MII is not set
-+# CONFIG_USB_USBNET is not set
-+# CONFIG_WAN is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+CONFIG_PPP=m
-+# CONFIG_PPP_MULTILINK is not set
-+# CONFIG_PPP_FILTER is not set
-+# CONFIG_PPP_ASYNC is not set
-+# CONFIG_PPP_SYNC_TTY is not set
-+# CONFIG_PPP_DEFLATE is not set
-+# CONFIG_PPP_BSDCOMP is not set
-+# CONFIG_PPP_MPPE is not set
-+# CONFIG_PPPOE is not set
-+# CONFIG_SLIP is not set
-+CONFIG_SLHC=m
-+# CONFIG_NET_FC is not set
-+# CONFIG_SHAPER is not set
-+CONFIG_NETCONSOLE=y
-+CONFIG_NETPOLL=y
-+# CONFIG_NETPOLL_TRAP is not set
-+CONFIG_NET_POLL_CONTROLLER=y
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Telephony Support
-+#
-+# CONFIG_PHONE is not set
-+
-+#
-+# Input device support
-+#
-+CONFIG_INPUT=y
-+# CONFIG_INPUT_FF_MEMLESS is not set
-+# CONFIG_INPUT_POLLDEV is not set
-+
-+#
-+# Userland interfaces
-+#
-+CONFIG_INPUT_MOUSEDEV=y
-+CONFIG_INPUT_MOUSEDEV_PSAUX=y
-+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_TSDEV is not set
-+CONFIG_INPUT_EVDEV=y
-+# CONFIG_INPUT_EVBUG is not set
-+
-+#
-+# Input Device Drivers
-+#
-+CONFIG_INPUT_KEYBOARD=y
-+CONFIG_KEYBOARD_ATKBD=y
-+# 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_STOWAWAY is not set
-+CONFIG_INPUT_MOUSE=y
-+CONFIG_MOUSE_PS2=y
-+CONFIG_MOUSE_PS2_ALPS=y
-+CONFIG_MOUSE_PS2_LOGIPS2PP=y
-+CONFIG_MOUSE_PS2_SYNAPTICS=y
-+CONFIG_MOUSE_PS2_LIFEBOOK=y
-+CONFIG_MOUSE_PS2_TRACKPOINT=y
-+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
-+# CONFIG_MOUSE_SERIAL is not set
-+# CONFIG_MOUSE_APPLETOUCH is not set
-+# CONFIG_MOUSE_VSXXXAA is not set
-+# CONFIG_INPUT_JOYSTICK is not set
-+# CONFIG_INPUT_TABLET is not set
-+# CONFIG_INPUT_TOUCHSCREEN is not set
-+# CONFIG_INPUT_MISC is not set
-+
-+#
-+# Hardware I/O ports
-+#
-+CONFIG_SERIO=y
-+CONFIG_SERIO_I8042=y
-+# CONFIG_SERIO_SERPORT is not set
-+# CONFIG_SERIO_CT82C710 is not set
-+# CONFIG_SERIO_PCIPS2 is not set
-+CONFIG_SERIO_LIBPS2=y
-+# CONFIG_SERIO_RAW is not set
-+# CONFIG_GAMEPORT is not set
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+CONFIG_VT_CONSOLE=y
-+CONFIG_HW_CONSOLE=y
-+# CONFIG_VT_HW_CONSOLE_BINDING is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+CONFIG_SERIAL_8250=y
-+CONFIG_SERIAL_8250_CONSOLE=y
-+CONFIG_SERIAL_8250_PCI=y
-+CONFIG_SERIAL_8250_PNP=y
-+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_SERIAL_CORE_CONSOLE=y
-+# CONFIG_SERIAL_JSM is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_LEGACY_PTYS=y
-+CONFIG_LEGACY_PTY_COUNT=256
-+
-+#
-+# IPMI
-+#
-+# CONFIG_IPMI_HANDLER is not set
-+# CONFIG_WATCHDOG is not set
-+CONFIG_HW_RANDOM=y
-+CONFIG_HW_RANDOM_INTEL=y
-+CONFIG_HW_RANDOM_AMD=y
-+CONFIG_HW_RANDOM_GEODE=y
-+CONFIG_HW_RANDOM_VIA=y
-+# CONFIG_NVRAM is not set
-+CONFIG_RTC=y
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+# CONFIG_SONYPI is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+# CONFIG_MWAVE is not set
-+# CONFIG_PC8736x_GPIO is not set
-+# CONFIG_NSC_GPIO is not set
-+# CONFIG_CS5535_GPIO is not set
-+CONFIG_RAW_DRIVER=y
-+CONFIG_MAX_RAW_DEVS=256
-+CONFIG_HPET=y
-+# CONFIG_HPET_RTC_IRQ is not set
-+CONFIG_HPET_MMAP=y
-+CONFIG_HANGCHECK_TIMER=y
-+
-+#
-+# TPM devices
-+#
-+# CONFIG_TCG_TPM is not set
-+# CONFIG_TELCLOCK is not set
-+CONFIG_DEVPORT=y
-+# CONFIG_I2C 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
-+# CONFIG_HWMON is not set
-+
-+#
-+# Multifunction device drivers
-+#
-+# CONFIG_MFD_SM501 is not set
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+# CONFIG_DVB_CORE is not set
-+CONFIG_DAB=y
-+# CONFIG_USB_DABUSB is not set
-+
-+#
-+# Graphics support
-+#
-+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-+
-+#
-+# Display device support
-+#
-+# CONFIG_DISPLAY_SUPPORT is not set
-+# CONFIG_VGASTATE is not set
-+CONFIG_VIDEO_OUTPUT_CONTROL=m
-+# CONFIG_FB is not set
-+
-+#
-+# Console display driver support
-+#
-+CONFIG_VGA_CONSOLE=y
-+CONFIG_VGACON_SOFT_SCROLLBACK=y
-+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=128
-+CONFIG_VIDEO_SELECT=y
-+CONFIG_DUMMY_CONSOLE=y
-+
-+#
-+# Sound
-+#
-+CONFIG_SOUND=y
-+
-+#
-+# Advanced Linux Sound Architecture
-+#
-+# CONFIG_SND is not set
-+
-+#
-+# Open Sound System
-+#
-+CONFIG_SOUND_PRIME=y
-+# CONFIG_OSS_OBSOLETE is not set
-+# CONFIG_SOUND_TRIDENT is not set
-+# CONFIG_SOUND_MSNDCLAS is not set
-+# CONFIG_SOUND_MSNDPIN is not set
-+# CONFIG_SOUND_OSS is not set
-+
-+#
-+# HID Devices
-+#
-+CONFIG_HID=y
-+# CONFIG_HID_DEBUG is not set
-+
-+#
-+# USB Input Devices
-+#
-+CONFIG_USB_HID=y
-+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-+# CONFIG_HID_FF is not set
-+# CONFIG_USB_HIDDEV is not set
-+
-+#
-+# USB support
-+#
-+CONFIG_USB_ARCH_HAS_HCD=y
-+CONFIG_USB_ARCH_HAS_OHCI=y
-+CONFIG_USB_ARCH_HAS_EHCI=y
-+CONFIG_USB=y
-+# CONFIG_USB_DEBUG is not set
-+
-+#
-+# Miscellaneous USB options
-+#
-+CONFIG_USB_DEVICEFS=y
-+CONFIG_USB_DEVICE_CLASS=y
-+# 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_EHCI_HCD=y
-+# CONFIG_USB_EHCI_SPLIT_ISO is not set
-+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
-+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
-+# CONFIG_USB_ISP116X_HCD is not set
-+CONFIG_USB_OHCI_HCD=y
-+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
-+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
-+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-+CONFIG_USB_UHCI_HCD=y
-+# CONFIG_USB_SL811_HCD is not set
-+
-+#
-+# USB Device Class drivers
-+#
-+# CONFIG_USB_ACM is not set
-+CONFIG_USB_PRINTER=y
-+
-+#
-+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-+#
-+
-+#
-+# may also be needed; see USB_STORAGE Help for more information
-+#
-+CONFIG_USB_STORAGE=y
-+# CONFIG_USB_STORAGE_DEBUG is not set
-+# CONFIG_USB_STORAGE_DATAFAB is not set
-+# CONFIG_USB_STORAGE_FREECOM is not set
-+# CONFIG_USB_STORAGE_ISD200 is not set
-+# CONFIG_USB_STORAGE_DPCM is not set
-+# CONFIG_USB_STORAGE_USBAT is not set
-+# CONFIG_USB_STORAGE_SDDR09 is not set
-+# CONFIG_USB_STORAGE_SDDR55 is not set
-+# CONFIG_USB_STORAGE_JUMPSHOT is not set
-+# CONFIG_USB_STORAGE_ALAUDA is not set
-+# CONFIG_USB_STORAGE_KARMA is not set
-+# CONFIG_USB_LIBUSUAL is not set
-+
-+#
-+# USB Imaging devices
-+#
-+# CONFIG_USB_MDC800 is not set
-+# CONFIG_USB_MICROTEK is not set
-+CONFIG_USB_MON=y
-+
-+#
-+# USB port drivers
-+#
-+
-+#
-+# USB Serial Converter support
-+#
-+# CONFIG_USB_SERIAL is not set
-+
-+#
-+# USB Miscellaneous drivers
-+#
-+# CONFIG_USB_EMI62 is not set
-+# CONFIG_USB_EMI26 is not set
-+# CONFIG_USB_ADUTUX is not set
-+# CONFIG_USB_AUERSWALD is not set
-+# CONFIG_USB_RIO500 is not set
-+# CONFIG_USB_LEGOTOWER is not set
-+# CONFIG_USB_LCD is not set
-+# CONFIG_USB_BERRY_CHARGE is not set
-+# CONFIG_USB_LED is not set
-+# CONFIG_USB_CYPRESS_CY7C63 is not set
-+# CONFIG_USB_CYTHERM is not set
-+# CONFIG_USB_PHIDGET is not set
-+# CONFIG_USB_IDMOUSE is not set
-+# CONFIG_USB_FTDI_ELAN is not set
-+# CONFIG_USB_APPLEDISPLAY is not set
-+# CONFIG_USB_SISUSBVGA is not set
-+# CONFIG_USB_LD is not set
-+# CONFIG_USB_TRANCEVIBRATOR is not set
-+# CONFIG_USB_IOWARRIOR is not set
-+# CONFIG_USB_TEST is not set
-+
-+#
-+# USB DSL modem support
-+#
-+
-+#
-+# USB Gadget Support
-+#
-+# CONFIG_USB_GADGET is not set
-+# CONFIG_MMC is not set
-+
-+#
-+# LED devices
-+#
-+# CONFIG_NEW_LEDS is not set
-+
-+#
-+# LED drivers
-+#
-+
-+#
-+# LED Triggers
-+#
-+
-+#
-+# InfiniBand support
-+#
-+# CONFIG_INFINIBAND is not set
-+
-+#
-+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-+#
-+# CONFIG_EDAC is not set
-+
-+#
-+# Real Time Clock
-+#
-+# CONFIG_RTC_CLASS is not set
-+
-+#
-+# DMA Engine support
-+#
-+# CONFIG_DMA_ENGINE is not set
-+
-+#
-+# DMA Clients
-+#
-+
-+#
-+# DMA Devices
-+#
-+
-+#
-+# Virtualization
-+#
-+# CONFIG_KVM is not set
-+
-+#
-+# File systems
-+#
-+CONFIG_EXT2_FS=y
-+CONFIG_EXT2_FS_XATTR=y
-+CONFIG_EXT2_FS_POSIX_ACL=y
-+# CONFIG_EXT2_FS_SECURITY is not set
-+# CONFIG_EXT2_FS_XIP is not set
-+CONFIG_EXT3_FS=y
-+CONFIG_EXT3_FS_XATTR=y
-+CONFIG_EXT3_FS_POSIX_ACL=y
-+# CONFIG_EXT3_FS_SECURITY is not set
-+# CONFIG_EXT4DEV_FS is not set
-+CONFIG_JBD=y
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FS_MBCACHE=y
-+CONFIG_REISERFS_FS=y
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+CONFIG_REISERFS_FS_XATTR=y
-+CONFIG_REISERFS_FS_POSIX_ACL=y
-+# CONFIG_REISERFS_FS_SECURITY is not set
-+# CONFIG_JFS_FS is not set
-+CONFIG_FS_POSIX_ACL=y
-+# CONFIG_XFS_FS is not set
-+# CONFIG_GFS2_FS is not set
-+# CONFIG_OCFS2_FS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_ROMFS_FS is not set
-+CONFIG_INOTIFY=y
-+CONFIG_INOTIFY_USER=y
-+# CONFIG_QUOTA is not set
-+CONFIG_DNOTIFY=y
-+# CONFIG_AUTOFS_FS is not set
-+CONFIG_AUTOFS4_FS=y
-+CONFIG_FUSE_FS=m
-+CONFIG_GENERIC_ACL=y
-+
-+#
-+# CD-ROM/DVD Filesystems
-+#
-+CONFIG_ISO9660_FS=y
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+CONFIG_UDF_FS=m
-+CONFIG_UDF_NLS=y
-+
-+#
-+# 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=m
-+# CONFIG_NTFS_DEBUG is not set
-+CONFIG_NTFS_RW=y
-+
-+#
-+# Pseudo filesystems
-+#
-+CONFIG_PROC_FS=y
-+CONFIG_PROC_KCORE=y
-+CONFIG_PROC_SYSCTL=y
-+CONFIG_SYSFS=y
-+CONFIG_TMPFS=y
-+CONFIG_TMPFS_POSIX_ACL=y
-+CONFIG_HUGETLBFS=y
-+CONFIG_HUGETLB_PAGE=y
-+CONFIG_RAMFS=y
-+# CONFIG_CONFIGFS_FS is not set
-+
-+#
-+# Layered filesystems
-+#
-+# CONFIG_UNION_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_CRAMFS is not set
-+# 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 is not set
-+# CONFIG_NFS_DIRECTIO is not set
-+CONFIG_NFSD=y
-+CONFIG_NFSD_V3=y
-+# CONFIG_NFSD_V3_ACL is not set
-+# CONFIG_NFSD_V4 is not set
-+CONFIG_NFSD_TCP=y
-+CONFIG_ROOT_NFS=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+CONFIG_EXPORTFS=y
-+CONFIG_NFS_COMMON=y
-+CONFIG_SUNRPC=y
-+# CONFIG_SUNRPC_BIND34 is not set
-+# CONFIG_RPCSEC_GSS_KRB5 is not set
-+# CONFIG_RPCSEC_GSS_SPKM3 is not set
-+CONFIG_SMB_FS=m
-+# CONFIG_SMB_NLS_DEFAULT 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 is not set
-+CONFIG_MSDOS_PARTITION=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS=y
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+CONFIG_NLS_CODEPAGE_437=y
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+CONFIG_NLS_CODEPAGE_850=y
-+CONFIG_NLS_CODEPAGE_852=y
-+# 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=y
-+CONFIG_NLS_ISO8859_1=y
-+CONFIG_NLS_ISO8859_2=y
-+# 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=y
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+CONFIG_NLS_UTF8=y
-+
-+#
-+# Distributed Lock Manager
-+#
-+# CONFIG_DLM is not set
-+
-+#
-+# Instrumentation Support
-+#
-+CONFIG_PROFILING=y
-+CONFIG_OPROFILE=y
-+CONFIG_KPROBES=y
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-+CONFIG_PRINTK_TIME=y
-+# CONFIG_ENABLE_MUST_CHECK is not set
-+CONFIG_MAGIC_SYSRQ=y
-+CONFIG_UNUSED_SYMBOLS=y
-+# CONFIG_DEBUG_FS is not set
-+# CONFIG_HEADERS_CHECK is not set
-+CONFIG_DEBUG_KERNEL=y
-+# CONFIG_DEBUG_SHIRQ is not set
-+CONFIG_DETECT_SOFTLOCKUP=y
-+# CONFIG_SCHEDSTATS is not set
-+# CONFIG_TIMER_STATS is not set
-+# CONFIG_DEBUG_SLAB is not set
-+# CONFIG_DEBUG_RT_MUTEXES is not set
-+# CONFIG_RT_MUTEX_TESTER is not set
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_MUTEXES is not set
-+# CONFIG_DEBUG_LOCK_ALLOC is not set
-+# CONFIG_PROVE_LOCKING is not set
-+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-+# CONFIG_DEBUG_KOBJECT is not set
-+# CONFIG_DEBUG_HIGHMEM is not set
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_DEBUG_VM is not set
-+# CONFIG_DEBUG_LIST is not set
-+# CONFIG_FRAME_POINTER is not set
-+# CONFIG_UNWIND_INFO is not set
-+# CONFIG_FORCED_INLINING is not set
-+# CONFIG_RCU_TORTURE_TEST is not set
-+# CONFIG_LKDTM is not set
-+# CONFIG_FAULT_INJECTION is not set
-+# CONFIG_WANT_EXTRA_DEBUG_INFORMATION is not set
-+# CONFIG_KGDB is not set
-+CONFIG_EARLY_PRINTK=y
-+CONFIG_DEBUG_STACKOVERFLOW=y
-+# CONFIG_DEBUG_STACK_USAGE is not set
-+# CONFIG_DEBUG_RODATA is not set
-+# CONFIG_4KSTACKS is not set
-+CONFIG_X86_FIND_SMP_CONFIG=y
-+CONFIG_X86_MPPARSE=y
-+CONFIG_DOUBLEFAULT=y
-+
-+#
-+# Linux VServer
-+#
-+CONFIG_VSERVER_FILESHARING=y
-+CONFIG_VSERVER_AUTO_LBACK=y
-+CONFIG_VSERVER_AUTO_SINGLE=y
-+CONFIG_VSERVER_COWBL=y
-+# CONFIG_VSERVER_VTIME is not set
-+# CONFIG_VSERVER_DEVICE is not set
-+CONFIG_VSERVER_PROC_SECURE=y
-+CONFIG_VSERVER_HARDCPU=y
-+CONFIG_VSERVER_IDLETIME=y
-+# CONFIG_VSERVER_IDLELIMIT is not set
-+# CONFIG_TAGGING_NONE is not set
-+# CONFIG_TAGGING_UID16 is not set
-+# CONFIG_TAGGING_GID16 is not set
-+CONFIG_TAGGING_ID24=y
-+# CONFIG_TAGGING_INTERN is not set
-+# CONFIG_TAG_NFSD is not set
-+# CONFIG_VSERVER_PRIVACY is not set
-+CONFIG_VSERVER_CONTEXTS=256
-+CONFIG_VSERVER_WARN=y
-+# CONFIG_VSERVER_DEBUG is not set
-+CONFIG_VSERVER=y
-+
-+#
-+# Security options
-+#
-+# CONFIG_KEYS is not set
-+# CONFIG_SECURITY is not set
-+
-+#
-+# Cryptographic options
-+#
-+# CONFIG_CRYPTO is not set
-+
-+#
-+# Library routines
-+#
-+CONFIG_BITREVERSE=y
-+CONFIG_CRC_CCITT=y
-+CONFIG_CRC16=y
-+# CONFIG_CRC_ITU_T is not set
-+CONFIG_CRC32=y
-+CONFIG_LIBCRC32C=y
-+CONFIG_ZLIB_INFLATE=y
-+CONFIG_PLIST=y
-+CONFIG_HAS_IOMEM=y
-+CONFIG_HAS_IOPORT=y
-+CONFIG_HAS_DMA=y
-+CONFIG_GENERIC_HARDIRQS=y
-+CONFIG_GENERIC_IRQ_PROBE=y
-+CONFIG_GENERIC_PENDING_IRQ=y
-+CONFIG_X86_SMP=y
-+CONFIG_X86_HT=y
-+CONFIG_X86_BIOS_REBOOT=y
-+CONFIG_X86_TRAMPOLINE=y
-+CONFIG_KTIME_SCALAR=y
-diff -Nurb linux-2.6.22-570/Documentation/DocBook/Makefile linux-2.6.22-590/Documentation/DocBook/Makefile
---- linux-2.6.22-570/Documentation/DocBook/Makefile    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/DocBook/Makefile    2008-01-02 13:56:37.000000000 -0500
-@@ -11,7 +11,7 @@
-           procfs-guide.xml writing_usb_driver.xml \
-           kernel-api.xml filesystems.xml lsm.xml usb.xml \
-           gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
--          genericirq.xml
-+          genericirq.xml kgdb.xml
- ###
- # The build process is as follows (targets):
-diff -Nurb linux-2.6.22-570/Documentation/DocBook/kgdb.tmpl linux-2.6.22-590/Documentation/DocBook/kgdb.tmpl
---- linux-2.6.22-570/Documentation/DocBook/kgdb.tmpl   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/DocBook/kgdb.tmpl   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,250 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-+      "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-+
-+<book id="kgdbInternals">
-+ <bookinfo>
-+  <title>KGDB Internals</title>
-+
-+  <authorgroup>
-+   <author>
-+    <firstname>Tom</firstname>
-+    <surname>Rini</surname>
-+    <affiliation>
-+     <address>
-+      <email>trini@kernel.crashing.org</email>
-+     </address>
-+    </affiliation>
-+   </author>
-+  </authorgroup>
-+
-+  <authorgroup>
-+   <author>
-+    <firstname>Amit S.</firstname>
-+    <surname>Kale</surname>
-+    <affiliation>
-+     <address>
-+      <email>amitkale@linsyssoft.com</email>
-+     </address>
-+    </affiliation>
-+   </author>
-+  </authorgroup>
-+
-+  <copyright>
-+   <year>2004-2005</year>
-+   <holder>MontaVista Software, Inc.</holder>
-+  </copyright>
-+  <copyright>
-+   <year>2004</year>
-+   <holder>Amit S. Kale</holder>
-+  </copyright>
-+
-+  <legalnotice>
-+   <para>
-+   This file is licensed under the terms of the GNU General Public License
-+   version 2. This program is licensed "as is" without any warranty of any
-+   kind, whether express or implied.
-+   </para>
-+
-+  </legalnotice>
-+ </bookinfo>
-+
-+<toc></toc>
-+  <chapter id="Introduction">
-+    <title>Introduction</title>
-+    <para>
-+    kgdb is a source level debugger for linux kernel. It is used along
-+    with gdb to debug a linux kernel. Kernel developers can debug a kernel
-+    similar to application programs with the use of kgdb. It makes it
-+    possible to place breakpoints in kernel code, step through the code
-+    and observe variables.
-+    </para>
-+    <para>
-+    Two machines are required for using kgdb. One of these machines is a
-+    development machine and the other is a test machine. The machines are
-+    typically connected through a serial line, a null-modem cable which
-+    connects their serial ports.  It is also possible however, to use an
-+    ethernet connection between the machines.  The kernel to be debugged
-+    runs on the test machine. gdb runs on the development machine. The
-+    serial line or ethernet connection is used by gdb to communicate to
-+    the kernel being debugged.
-+    </para>
-+  </chapter>
-+  <chapter id="CompilingAKernel">
-+    <title>Compiling a kernel</title>
-+    <para>
-+    To enable <symbol>CONFIG_KGDB</symbol>, look under the "Kernel debugging"
-+    and then select "KGDB: kernel debugging with remote gdb".
-+    </para>
-+    <para>
-+    The first choice for I/O is <symbol>CONFIG_KGDB_ONLY_MODULES</symbol>.
-+    This means that you will only be able to use KGDB after loading a
-+    kernel module that defines how you want to be able to talk with
-+    KGDB.  There are two other choices (more on some architectures) that
-+    can be enabled as modules later, if not picked here.
-+    </para>
-+    <para>The first of these is <symbol>CONFIG_KGDB_8250_NOMODULE</symbol>.
-+    This has sub-options such as <symbol>CONFIG_KGDB_SIMPLE_SERIAL</symbol>
-+    which toggles choosing the serial port by ttyS number or by specifying
-+    a port and IRQ number.
-+    </para>
-+    <para>
-+    The second of these choices on most systems for I/O is
-+    <symbol>CONFIG_KGDBOE</symbol>. This requires that the machine to be
-+    debugged has an ethernet card which supports the netpoll API, such as
-+    the cards supported by <symbol>CONFIG_E100</symbol>.  There are no
-+    sub-options for this, but a kernel command line option is required.
-+    </para>
-+  </chapter>
-+  <chapter id="BootingTheKernel">
-+    <title>Booting the kernel</title>
-+    <para>
-+    The Kernel command line option <constant>kgdbwait</constant> makes kgdb
-+    wait for gdb connection during booting of a kernel.  If the
-+    <symbol>CONFIG_KGDB_8250</symbol> driver is used (or if applicable,
-+    another serial driver) this breakpoint will happen very early on, before
-+    console output.  If you wish to change serial port information and you
-+    have enabled both <symbol>CONFIG_KGDB_8250</symbol> and
-+    <symbol>CONFIG_KGDB_SIMPLE_SERIAL</symbol> then you must pass the option
-+    <constant>kgdb8250=&lt;io or mmio&gt;,&lt;address&gt;,&lt;baud
-+    rate&gt;,&lt;irq&gt;</constant> before <constant>kgdbwait</constant>.
-+    The values <constant>io</constant> or <constant>mmio</constant> refer to
-+    if the address being passed next needs to be memory mapped
-+    (<constant>mmio</constant>) or not. The <constant>address</constant> must
-+    be passed in hex and is the hardware address and will be remapped if
-+    passed as <constant>mmio</constant>. The value
-+    <constant>baud rate</constant> and <constant>irq</constant> are base-10.
-+    The supported values for <constant>baud rate</constant> are
-+    <constant>9600</constant>, <constant>19200</constant>,
-+    <constant>38400</constant>, <constant>57600</constant>, and
-+    <constant>115200</constant>.
-+    </para>
-+    <para>
-+    To have KGDB stop the kernel and wait, with the compiled values for the
-+    serial driver, pass in: <constant>kgdbwait</constant>.
-+    </para>
-+    <para>
-+    To specify the values of the SH SCI(F) serial port at boot:
-+    <constant>kgdbsci=0,115200</constant>.
-+    </para>
-+    <para>
-+    To specify the values of the serial port at boot:
-+    <constant>kgdb8250=io,3f8,115200,3</constant>.
-+    On IA64 this could also be:
-+    <constant>kgdb8250=mmio,0xff5e0000,115200,74</constant>
-+    And to have KGDB also stop the kernel and wait for GDB to connect, pass in
-+    <constant>kgdbwait</constant> after this arguement.
-+    </para>
-+    <para>
-+    To configure the <symbol>CONFIG_KGDBOE</symbol> driver, pass in
-+    <constant>kgdboe=[src-port]@&lt;src-ip&gt;/[dev],[tgt-port]@&lt;tgt-ip&gt;/[tgt-macaddr]</constant>
-+    where:
-+    <itemizedlist>
-+      <listitem><para>src-port (optional): source for UDP packets (defaults to <constant>6443</constant>)</para></listitem>
-+      <listitem><para>src-ip: source IP to use (interface address)</para></listitem>
-+      <listitem><para>dev (optional): network interface (<constant>eth0</constant>)</para></listitem>
-+      <listitem><para>tgt-port (optional): port GDB will use (defaults to <constant>6442</constant>)</para></listitem>
-+      <listitem><para>tgt-ip: IP address GDB will be connecting from</para></listitem>
-+      <listitem><para>tgt-macaddr (optional): ethernet MAC address for logging agent (default is broadcast)</para></listitem>
-+    </itemizedlist>
-+    </para>
-+    <para>
-+    The <symbol>CONFIG_KGDBOE</symbol> driver can be reconfigured at run
-+    time, if <symbol>CONFIG_SYSFS</symbol> and
-+    <symbol>CONFIG_MODULES</symbol> by echo'ing a new config string to
-+    <constant>/sys/module/kgdboe/parameter/kgdboe</constant>.  The
-+    driver can be unconfigured with the special string
-+    <constant>not_configured</constant>.
-+    </para>
-+  </chapter>
-+  <chapter id="ConnectingGDB">
-+  <title>Connecting gdb</title>
-+    <para>
-+    If you have used any of the methods to have KGDB stop and create
-+    an initial breakpoint described in the previous chapter, kgdb prints
-+    the message "Waiting for connection from remote gdb..." on the console
-+    and waits for connection from gdb. At this point you connect gdb to kgdb.
-+    </para>
-+    <para>
-+    Example (serial):
-+    </para>
-+    <programlisting>
-+    % gdb ./vmlinux
-+    (gdb) set remotebaud 115200
-+    (gdb) target remote /dev/ttyS0
-+    </programlisting>
-+    <para>
-+    Example (ethernet):
-+    </para>
-+    <programlisting>
-+    % gdb ./vmlinux
-+    (gdb) target remote udp:192.168.2.2:6443
-+    </programlisting>
-+    <para>
-+    Once connected, you can debug a kernel the way you would debug an
-+    application program.
-+    </para>
-+  </chapter>
-+  <chapter id="ArchitectureNotes">
-+    <title>Architecture specific notes</title>
-+      <para>
-+      SuperH: The NMI switch found on some boards can be used to trigger an
-+      initial breakpoint.  Subsequent triggers do nothing.  If console
-+      is enabled on the SCI(F) serial port, and that is the port being used
-+      for KGDB, then you must trigger a breakpoint via sysrq, NMI, or
-+      some other method prior to connecting, or echo a control-c to the
-+      serial port.  Also, to use the SCI(F) port for KGDB, the
-+      <symbol>CONFIG_SERIAL_SH_SCI</symbol> driver must be enabled.
-+      </para>
-+  </chapter>
-+  <chapter id="CommonBackEndReq">
-+    <title>The common backend (required)</title>
-+      <para>
-+      There are a few flags which must be set on every architecture in
-+      their &lt;asm/kgdb.h&gt; file.  These are:
-+      <itemizedlist>
-+        <listitem>
-+        <para>
-+        NUMREGBYTES: The size in bytes of all of the registers, so
-+        that we can ensure they will all fit into a packet.
-+        </para>
-+        <para>
-+        BUFMAX: The size in bytes of the buffer GDB will read into.
-+        This must be larger than NUMREGBYTES.
-+        </para>
-+        <para>
-+        CACHE_FLUSH_IS_SAFE: Set to one if it always safe to call
-+        flush_cache_range or flush_icache_range.  On some architectures,
-+        these functions may not be safe to call on SMP since we keep other
-+        CPUs in a holding pattern.
-+        </para>
-+      </listitem>
-+      </itemizedlist>
-+      </para>
-+      <para>
-+      There are also the following functions for the common backend,
-+      found in kernel/kgdb.c that must be supplied by the
-+      architecture-specific backend.  No weak version of these is provided.
-+      </para>
-+!Iinclude/linux/kgdb.h
-+  </chapter>
-+  <chapter id="CommonBackEndOpt">
-+    <title>The common backend (optional)</title>
-+      <para>
-+      These functions are part of the common backend, found in kernel/kgdb.c
-+      and are optionally implemented.  Some functions (with _hw_ in the name)
-+      end up being required on arches which use hardware breakpoints.
-+      </para>
-+!Ikernel/kgdb.c
-+  </chapter>
-+  <chapter id="DriverSpecificFunctions">
-+    <title>Driver-Specific Functions</title>
-+      <para>
-+      Some of the I/O drivers have additional functions that can be
-+      called, that are specific to the driver.  Calls from other places
-+      to these functions must be wrapped in #ifdefs for the driver in
-+      question.
-+      </para>
-+!Idrivers/serial/8250_kgdb.c
-+   </chapter>
-+</book>
-diff -Nurb linux-2.6.22-570/Documentation/accounting/getdelays.c linux-2.6.22-590/Documentation/accounting/getdelays.c
---- linux-2.6.22-570/Documentation/accounting/getdelays.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/accounting/getdelays.c      2008-01-02 13:56:37.000000000 -0500
-@@ -49,6 +49,7 @@
- int dbg;
- int print_delays;
- int print_io_accounting;
-+int print_task_context_switch_counts;
- __u64 stime, utime;
- #define PRINTF(fmt, arg...) {                 \
-@@ -195,7 +196,7 @@
-              "IO    %15s%15s\n"
-              "      %15llu%15llu\n"
-              "MEM   %15s%15s\n"
--             "      %15llu%15llu\n\n",
-+             "      %15llu%15llu\n"
-              "count", "real total", "virtual total", "delay total",
-              t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total,
-              t->cpu_delay_total,
-@@ -204,6 +205,14 @@
-              "count", "delay total", t->swapin_count, t->swapin_delay_total);
- }
-+void task_context_switch_counts(struct taskstats *t)
-+{
-+      printf("\n\nTask   %15s%15s\n"
-+             "       %15lu%15lu\n",
-+             "voluntary", "nonvoluntary",
-+             t->nvcsw, t->nivcsw);
-+}
-+
- void print_ioacct(struct taskstats *t)
- {
-       printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
-@@ -235,7 +244,7 @@
-       struct msgtemplate msg;
-       while (1) {
--              c = getopt(argc, argv, "diw:r:m:t:p:vl");
-+              c = getopt(argc, argv, "qdiw:r:m:t:p:vl");
-               if (c < 0)
-                       break;
-@@ -248,6 +257,10 @@
-                       printf("printing IO accounting\n");
-                       print_io_accounting = 1;
-                       break;
-+              case 'q':
-+                      printf("printing task/process context switch rates\n");
-+                      print_task_context_switch_counts = 1;
-+                      break;
-               case 'w':
-                       logfile = strdup(optarg);
-                       printf("write to file %s\n", logfile);
-@@ -389,6 +402,8 @@
-                                                       print_delayacct((struct taskstats *) NLA_DATA(na));
-                                               if (print_io_accounting)
-                                                       print_ioacct((struct taskstats *) NLA_DATA(na));
-+                                              if (print_task_context_switch_counts)
-+                                                      task_context_switch_counts((struct taskstats *) NLA_DATA(na));
-                                               if (fd) {
-                                                       if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
-                                                               err(1,"write error\n");
-diff -Nurb linux-2.6.22-570/Documentation/accounting/taskstats-struct.txt linux-2.6.22-590/Documentation/accounting/taskstats-struct.txt
---- linux-2.6.22-570/Documentation/accounting/taskstats-struct.txt     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/accounting/taskstats-struct.txt     2008-01-02 13:56:37.000000000 -0500
-@@ -22,6 +22,8 @@
-     /* Extended accounting fields end */
-     Their values are collected if CONFIG_TASK_XACCT is set.
-+4) Per-task and per-thread context switch count statistics
-+
- Future extension should add fields to the end of the taskstats struct, and
- should not change the relative position of each field within the struct.
-@@ -158,4 +160,8 @@
-       /* Extended accounting fields end */
-+4) Per-task and per-thread statistics
-+      __u64   nvcsw;                  /* Context voluntary switch counter */
-+      __u64   nivcsw;                 /* Context involuntary switch counter */
-+
- }
-diff -Nurb linux-2.6.22-570/Documentation/cachetlb.txt linux-2.6.22-590/Documentation/cachetlb.txt
---- linux-2.6.22-570/Documentation/cachetlb.txt        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/cachetlb.txt        2008-01-02 13:56:37.000000000 -0500
-@@ -253,7 +253,7 @@
-       The first of these two routines is invoked after map_vm_area()
-       has installed the page table entries.  The second is invoked
--      before unmap_vm_area() deletes the page table entries.
-+      before unmap_kernel_range() deletes the page table entries.
- There exists another whole class of cpu cache issues which currently
- require a whole different set of interfaces to handle properly.
-diff -Nurb linux-2.6.22-570/Documentation/containers.txt linux-2.6.22-590/Documentation/containers.txt
---- linux-2.6.22-570/Documentation/containers.txt      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/containers.txt      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,543 @@
-+                              CONTAINERS
-+                              -------
-+
-+Written by Paul Menage <menage@google.com> based on Documentation/cpusets.txt
-+
-+Original copyright statements from cpusets.txt:
-+Portions Copyright (C) 2004 BULL SA.
-+Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
-+Modified by Paul Jackson <pj@sgi.com>
-+Modified by Christoph Lameter <clameter@sgi.com>
-+
-+CONTENTS:
-+=========
-+
-+1. Containers
-+  1.1 What are containers ?
-+  1.2 Why are containers needed ?
-+  1.3 How are containers implemented ?
-+  1.4 What does notify_on_release do ?
-+  1.5 How do I use containers ?
-+2. Usage Examples and Syntax
-+  2.1 Basic Usage
-+  2.2 Attaching processes
-+3. Kernel API
-+  3.1 Overview
-+  3.2 Synchronization
-+  3.3 Subsystem API
-+4. Questions
-+
-+1. Containers
-+==========
-+
-+1.1 What are containers ?
-+----------------------
-+
-+Containers provide a mechanism for aggregating/partitioning sets of
-+tasks, and all their future children, into hierarchical groups with
-+specialized behaviour.
-+
-+Definitions:
-+
-+A *container* associates a set of tasks with a set of parameters for one
-+or more subsystems.
-+
-+A *subsystem* is a module that makes use of the task grouping
-+facilities provided by containers to treat groups of tasks in
-+particular ways. A subsystem is typically a "resource controller" that
-+schedules a resource or applies per-container limits, but it may be
-+anything that wants to act on a group of processes, e.g. a
-+virtualization subsystem.
-+
-+A *hierarchy* is a set of containers arranged in a tree, such that
-+every task in the system is in exactly one of the containers in the
-+hierarchy, and a set of subsystems; each subsystem has system-specific
-+state attached to each container in the hierarchy.  Each hierarchy has
-+an instance of the container virtual filesystem associated with it.
-+
-+At any one time there may be multiple active hierachies of task
-+containers. Each hierarchy is a partition of all tasks in the system.
-+
-+User level code may create and destroy containers by name in an
-+instance of the container virtual file system, specify and query to
-+which container a task is assigned, and list the task pids assigned to
-+a container. Those creations and assignments only affect the hierarchy
-+associated with that instance of the container file system.
-+
-+On their own, the only use for containers is for simple job
-+tracking. The intention is that other subsystems hook into the generic
-+container support to provide new attributes for containers, such as
-+accounting/limiting the resources which processes in a container can
-+access. For example, cpusets (see Documentation/cpusets.txt) allows
-+you to associate a set of CPUs and a set of memory nodes with the
-+tasks in each container.
-+
-+1.2 Why are containers needed ?
-+----------------------------
-+
-+There are multiple efforts to provide process aggregations in the
-+Linux kernel, mainly for resource tracking purposes. Such efforts
-+include cpusets, CKRM/ResGroups, UserBeanCounters, and virtual server
-+namespaces. These all require the basic notion of a
-+grouping/partitioning of processes, with newly forked processes ending
-+in the same group (container) as their parent process.
-+
-+The kernel container patch provides the minimum essential kernel
-+mechanisms required to efficiently implement such groups. It has
-+minimal impact on the system fast paths, and provides hooks for
-+specific subsystems such as cpusets to provide additional behaviour as
-+desired.
-+
-+Multiple hierarchy support is provided to allow for situations where
-+the division of tasks into containers is distinctly different for
-+different subsystems - having parallel hierarchies allows each
-+hierarchy to be a natural division of tasks, without having to handle
-+complex combinations of tasks that would be present if several
-+unrelated subsystems needed to be forced into the same tree of
-+containers.
-+
-+At one extreme, each resource controller or subsystem could be in a
-+separate hierarchy; at the other extreme, all subsystems
-+would be attached to the same hierarchy.
-+
-+As an example of a scenario (originally proposed by vatsa@in.ibm.com)
-+that can benefit from multiple hierarchies, consider a large
-+university server with various users - students, professors, system
-+tasks etc. The resource planning for this server could be along the
-+following lines:
-+
-+       CPU :           Top cpuset
-+                       /       \
-+               CPUSet1         CPUSet2
-+                  |              |
-+               (Profs)         (Students)
-+
-+               In addition (system tasks) are attached to topcpuset (so
-+               that they can run anywhere) with a limit of 20%
-+
-+       Memory : Professors (50%), students (30%), system (20%)
-+
-+       Disk : Prof (50%), students (30%), system (20%)
-+
-+       Network : WWW browsing (20%), Network File System (60%), others (20%)
-+                               / \
-+                       Prof (15%) students (5%)
-+
-+Browsers like firefox/lynx go into the WWW network class, while (k)nfsd go
-+into NFS network class.
-+
-+At the same time firefox/lynx will share an appropriate CPU/Memory class
-+depending on who launched it (prof/student).
-+
-+With the ability to classify tasks differently for different resources
-+(by putting those resource subsystems in different hierarchies) then
-+the admin can easily set up a script which receives exec notifications
-+and depending on who is launching the browser he can
-+
-+       # echo browser_pid > /mnt/<restype>/<userclass>/tasks
-+
-+With only a single hierarchy, he now would potentially have to create
-+a separate container for every browser launched and associate it with
-+approp network and other resource class.  This may lead to
-+proliferation of such containers.
-+
-+Also lets say that the administrator would like to give enhanced network
-+access temporarily to a student's browser (since it is night and the user
-+wants to do online gaming :)  OR give one of the students simulation
-+apps enhanced CPU power,
-+
-+With ability to write pids directly to resource classes, its just a
-+matter of :
-+
-+       # echo pid > /mnt/network/<new_class>/tasks
-+       (after some time)
-+       # echo pid > /mnt/network/<orig_class>/tasks
-+
-+Without this ability, he would have to split the container into
-+multiple separate ones and then associate the new containers with the
-+new resource classes.
-+
-+
-+
-+1.3 How are containers implemented ?
-+---------------------------------
-+
-+Containers extends the kernel as follows:
-+
-+ - Each task in the system has a reference-counted pointer to a
-+   css_group.
-+
-+ - A css_group contains a set of reference-counted pointers to
-+   container_subsys_state objects, one for each container subsystem
-+   registered in the system. There is no direct link from a task to
-+   the container of which it's a member in each hierarchy, but this
-+   can be determined by following pointers through the
-+   container_subsys_state objects. This is because accessing the
-+   subsystem state is something that's expected to happen frequently
-+   and in performance-critical code, whereas operations that require a
-+   task's actual container assignments (in particular, moving between
-+   containers) are less common. A linked list runs through the cg_list
-+   field of each task_struct using the css_group, anchored at
-+   css_group->tasks.
-+
-+ - A container hierarchy filesystem can be mounted  for browsing and
-+   manipulation from user space.
-+
-+ - You can list all the tasks (by pid) attached to any container.
-+
-+The implementation of containers requires a few, simple hooks
-+into the rest of the kernel, none in performance critical paths:
-+
-+ - in init/main.c, to initialize the root containers and initial
-+   css_group at system boot.
-+
-+ - in fork and exit, to attach and detach a task from its css_group.
-+
-+In addition a new file system, of type "container" may be mounted, to
-+enable browsing and modifying the containers presently known to the
-+kernel.  When mounting a container hierarchy, you may specify a
-+comma-separated list of subsystems to mount as the filesystem mount
-+options.  By default, mounting the container filesystem attempts to
-+mount a hierarchy containing all registered subsystems.
-+
-+If an active hierarchy with exactly the same set of subsystems already
-+exists, it will be reused for the new mount. If no existing hierarchy
-+matches, and any of the requested subsystems are in use in an existing
-+hierarchy, the mount will fail with -EBUSY. Otherwise, a new hierarchy
-+is activated, associated with the requested subsystems.
-+
-+It's not currently possible to bind a new subsystem to an active
-+container hierarchy, or to unbind a subsystem from an active container
-+hierarchy. This may be possible in future, but is fraught with nasty
-+error-recovery issues.
-+
-+When a container filesystem is unmounted, if there are any
-+subcontainers created below the top-level container, that hierarchy
-+will remain active even though unmounted; if there are no
-+subcontainers then the hierarchy will be deactivated.
-+
-+No new system calls are added for containers - all support for
-+querying and modifying containers is via this container file system.
-+
-+Each task under /proc has an added file named 'container' displaying,
-+for each active hierarchy, the subsystem names and the container name
-+as the path relative to the root of the container file system.
-+
-+Each container is represented by a directory in the container file system
-+containing the following files describing that container:
-+
-+ - tasks: list of tasks (by pid) attached to that container
-+ - notify_on_release flag: run /sbin/container_release_agent on exit?
-+
-+Other subsystems such as cpusets may add additional files in each
-+container dir
-+
-+New containers are created using the mkdir system call or shell
-+command.  The properties of a container, such as its flags, are
-+modified by writing to the appropriate file in that containers
-+directory, as listed above.
-+
-+The named hierarchical structure of nested containers allows partitioning
-+a large system into nested, dynamically changeable, "soft-partitions".
-+
-+The attachment of each task, automatically inherited at fork by any
-+children of that task, to a container allows organizing the work load
-+on a system into related sets of tasks.  A task may be re-attached to
-+any other container, if allowed by the permissions on the necessary
-+container file system directories.
-+
-+When a task is moved from one container to another, it gets a new
-+css_group pointer - if there's an already existing css_group with the
-+desired collection of containers then that group is reused, else a new
-+css_group is allocated. Note that the current implementation uses a
-+linear search to locate an appropriate existing css_group, so isn't
-+very efficient. A future version will use a hash table for better
-+performance.
-+
-+To allow access from a container to the css_groups (and hence tasks)
-+that comprise it, a set of cg_container_link objects form a lattice;
-+each cg_container_link is linked into a list of cg_container_links for
-+a single container on its cont_link_list field, and a list of
-+cg_container_links for a single css_group on its cg_link_list.
-+
-+Thus the set of tasks in a container can be listed by iterating over
-+each css_group that references the container, and sub-iterating over
-+each css_group's task set.
-+
-+The use of a Linux virtual file system (vfs) to represent the
-+container hierarchy provides for a familiar permission and name space
-+for containers, with a minimum of additional kernel code.
-+
-+1.4 What does notify_on_release do ?
-+------------------------------------
-+
-+*** notify_on_release is disabled in the current patch set. It will be
-+*** reactivated in a future patch in a less-intrusive manner
-+
-+If the notify_on_release flag is enabled (1) in a container, then
-+whenever the last task in the container leaves (exits or attaches to
-+some other container) and the last child container of that container
-+is removed, then the kernel runs the command specified by the contents
-+of the "release_agent" file in that hierarchy's root directory,
-+supplying the pathname (relative to the mount point of the container
-+file system) of the abandoned container.  This enables automatic
-+removal of abandoned containers.  The default value of
-+notify_on_release in the root container at system boot is disabled
-+(0).  The default value of other containers at creation is the current
-+value of their parents notify_on_release setting. The default value of
-+a container hierarchy's release_agent path is empty.
-+
-+1.5 How do I use containers ?
-+--------------------------
-+
-+To start a new job that is to be contained within a container, using
-+the "cpuset" container subsystem, the steps are something like:
-+
-+ 1) mkdir /dev/container
-+ 2) mount -t container -ocpuset cpuset /dev/container
-+ 3) Create the new container by doing mkdir's and write's (or echo's) in
-+    the /dev/container virtual file system.
-+ 4) Start a task that will be the "founding father" of the new job.
-+ 5) Attach that task to the new container by writing its pid to the
-+    /dev/container tasks file for that container.
-+ 6) fork, exec or clone the job tasks from this founding father task.
-+
-+For example, the following sequence of commands will setup a container
-+named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
-+and then start a subshell 'sh' in that container:
-+
-+  mount -t container cpuset -ocpuset /dev/container
-+  cd /dev/container
-+  mkdir Charlie
-+  cd Charlie
-+  /bin/echo $$ > tasks
-+  sh
-+  # The subshell 'sh' is now running in container Charlie
-+  # The next line should display '/Charlie'
-+  cat /proc/self/container
-+
-+2. Usage Examples and Syntax
-+============================
-+
-+2.1 Basic Usage
-+---------------
-+
-+Creating, modifying, using the containers can be done through the container
-+virtual filesystem.
-+
-+To mount a container hierarchy will all available subsystems, type:
-+# mount -t container xxx /dev/container
-+
-+The "xxx" is not interpreted by the container code, but will appear in
-+/proc/mounts so may be any useful identifying string that you like.
-+
-+To mount a container hierarchy with just the cpuset and numtasks
-+subsystems, type:
-+# mount -t container -o cpuset,numtasks hier1 /dev/container
-+
-+To change the set of subsystems bound to a mounted hierarchy, just
-+remount with different options:
-+
-+# mount -o remount,cpuset,ns  /dev/container
-+
-+Note that changing the set of subsystems is currently only supported
-+when the hierarchy consists of a single (root) container. Supporting
-+the ability to arbitrarily bind/unbind subsystems from an existing
-+container hierarchy is intended to be implemented in the future.
-+
-+Then under /dev/container you can find a tree that corresponds to the
-+tree of the containers in the system. For instance, /dev/container
-+is the container that holds the whole system.
-+
-+If you want to create a new container under /dev/container:
-+# cd /dev/container
-+# mkdir my_container
-+
-+Now you want to do something with this container.
-+# cd my_container
-+
-+In this directory you can find several files:
-+# ls
-+notify_on_release release_agent tasks
-+(plus whatever files are added by the attached subsystems)
-+
-+Now attach your shell to this container:
-+# /bin/echo $$ > tasks
-+
-+You can also create containers inside your container by using mkdir in this
-+directory.
-+# mkdir my_sub_cs
-+
-+To remove a container, just use rmdir:
-+# rmdir my_sub_cs
-+
-+This will fail if the container is in use (has containers inside, or
-+has processes attached, or is held alive by other subsystem-specific
-+reference).
-+
-+2.2 Attaching processes
-+-----------------------
-+
-+# /bin/echo PID > tasks
-+
-+Note that it is PID, not PIDs. You can only attach ONE task at a time.
-+If you have several tasks to attach, you have to do it one after another:
-+
-+# /bin/echo PID1 > tasks
-+# /bin/echo PID2 > tasks
-+      ...
-+# /bin/echo PIDn > tasks
-+
-+3. Kernel API
-+=============
-+
-+3.1 Overview
-+------------
-+
-+Each kernel subsystem that wants to hook into the generic container
-+system needs to create a container_subsys object. This contains
-+various methods, which are callbacks from the container system, along
-+with a subsystem id which will be assigned by the container system.
-+
-+Other fields in the container_subsys object include:
-+
-+- subsys_id: a unique array index for the subsystem, indicating which
-+  entry in container->subsys[] this subsystem should be
-+  managing. Initialized by container_register_subsys(); prior to this
-+  it should be initialized to -1
-+
-+- hierarchy: an index indicating which hierarchy, if any, this
-+  subsystem is currently attached to. If this is -1, then the
-+  subsystem is not attached to any hierarchy, and all tasks should be
-+  considered to be members of the subsystem's top_container. It should
-+  be initialized to -1.
-+
-+- name: should be initialized to a unique subsystem name prior to
-+  calling container_register_subsystem. Should be no longer than
-+  MAX_CONTAINER_TYPE_NAMELEN
-+
-+Each container object created by the system has an array of pointers,
-+indexed by subsystem id; this pointer is entirely managed by the
-+subsystem; the generic container code will never touch this pointer.
-+
-+3.2 Synchronization
-+-------------------
-+
-+There is a global mutex, container_mutex, used by the container
-+system. This should be taken by anything that wants to modify a
-+container. It may also be taken to prevent containers from being
-+modified, but more specific locks may be more appropriate in that
-+situation.
-+
-+See kernel/container.c for more details.
-+
-+Subsystems can take/release the container_mutex via the functions
-+container_lock()/container_unlock(), and can
-+take/release the callback_mutex via the functions
-+container_lock()/container_unlock().
-+
-+Accessing a task's container pointer may be done in the following ways:
-+- while holding container_mutex
-+- while holding the task's alloc_lock (via task_lock())
-+- inside an rcu_read_lock() section via rcu_dereference()
-+
-+3.3 Subsystem API
-+--------------------------
-+
-+Each subsystem should:
-+
-+- add an entry in linux/container_subsys.h
-+- define a container_subsys object called <name>_subsys
-+
-+Each subsystem may export the following methods. The only mandatory
-+methods are create/destroy. Any others that are null are presumed to
-+be successful no-ops.
-+
-+int create(struct container *cont)
-+LL=container_mutex
-+
-+Called to create a subsystem state object for a container. The
-+subsystem should set its subsystem pointer for the passed container,
-+returning 0 on success or a negative error code. On success, the
-+subsystem pointer should point to a structure of type
-+container_subsys_state (typically embedded in a larger
-+subsystem-specific object), which will be initialized by the container
-+system. Note that this will be called at initialization to create the
-+root subsystem state for this subsystem; this case can be identified
-+by the passed container object having a NULL parent (since it's the
-+root of the hierarchy) and may be an appropriate place for
-+initialization code.
-+
-+void destroy(struct container *cont)
-+LL=container_mutex
-+
-+The container system is about to destroy the passed container; the
-+subsystem should do any necessary cleanup
-+
-+int can_attach(struct container_subsys *ss, struct container *cont,
-+             struct task_struct *task)
-+LL=container_mutex
-+
-+Called prior to moving a task into a container; if the subsystem
-+returns an error, this will abort the attach operation.  If a NULL
-+task is passed, then a successful result indicates that *any*
-+unspecified task can be moved into the container. Note that this isn't
-+called on a fork. If this method returns 0 (success) then this should
-+remain valid while the caller holds container_mutex.
-+
-+void attach(struct container_subsys *ss, struct container *cont,
-+          struct container *old_cont, struct task_struct *task)
-+LL=container_mutex
-+
-+
-+Called after the task has been attached to the container, to allow any
-+post-attachment activity that requires memory allocations or blocking.
-+
-+void fork(struct container_subsy *ss, struct task_struct *task)
-+LL=callback_mutex, maybe read_lock(tasklist_lock)
-+
-+Called when a task is forked into a container. Also called during
-+registration for all existing tasks.
-+
-+void exit(struct container_subsys *ss, struct task_struct *task)
-+LL=callback_mutex
-+
-+Called during task exit
-+
-+int populate(struct container_subsys *ss, struct container *cont)
-+LL=none
-+
-+Called after creation of a container to allow a subsystem to populate
-+the container directory with file entries.  The subsystem should make
-+calls to container_add_file() with objects of type cftype (see
-+include/linux/container.h for details).  Note that although this
-+method can return an error code, the error code is currently not
-+always handled well.
-+
-+void post_clone(struct container_subsys *ss, struct container *cont)
-+
-+Called at the end of container_clone() to do any paramater
-+initialization which might be required before a task could attach.  For
-+example in cpusets, no task may attach before 'cpus' and 'mems' are set
-+up.
-+
-+void bind(struct container_subsys *ss, struct container *root)
-+LL=callback_mutex
-+
-+Called when a container subsystem is rebound to a different hierarchy
-+and root container. Currently this will only involve movement between
-+the default hierarchy (which never has sub-containers) and a hierarchy
-+that is being created/destroyed (and hence has no sub-containers).
-+
-+4. Questions
-+============
-+
-+Q: what's up with this '/bin/echo' ?
-+A: bash's builtin 'echo' command does not check calls to write() against
-+   errors. If you use it in the container file system, you won't be
-+   able to tell whether a command succeeded or failed.
-+
-+Q: When I attach processes, only the first of the line gets really attached !
-+A: We can only return one error code per call to write(). So you should also
-+   put only ONE pid.
-+
-diff -Nurb linux-2.6.22-570/Documentation/cpuidle/core.txt linux-2.6.22-590/Documentation/cpuidle/core.txt
---- linux-2.6.22-570/Documentation/cpuidle/core.txt    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/cpuidle/core.txt    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,17 @@
-+
-+              Supporting multiple CPU idle levels in kernel
-+
-+                              cpuidle
-+
-+General Information:
-+
-+Various CPUs today support multiple idle levels that are differentiated
-+by varying exit latencies and power consumption during idle.
-+cpuidle is a generic in-kernel infrastructure that separates
-+idle policy (governor) from idle mechanism (driver) and provides a
-+standardized infrastructure to support independent development of
-+governors and drivers.
-+
-+cpuidle resides under /drivers/cpuidle.
-+
-+
-diff -Nurb linux-2.6.22-570/Documentation/cpuidle/driver.txt linux-2.6.22-590/Documentation/cpuidle/driver.txt
---- linux-2.6.22-570/Documentation/cpuidle/driver.txt  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/cpuidle/driver.txt  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,24 @@
-+
-+
-+              Supporting multiple CPU idle levels in kernel
-+
-+                              cpuidle drivers
-+
-+
-+
-+
-+cpuidle driver supports capability detection for a particular system. The
-+init and exit routines will be called for each online CPU, with a percpu
-+cpuidle_driver object and driver should fill in cpuidle_states inside
-+cpuidle_driver depending on the CPU capability.
-+
-+Driver can handle dynamic state changes (like battery<->AC), by calling
-+force_redetect interface.
-+
-+It is possible to have more than one driver registered at the same time and
-+user can switch between drivers using /sysfs interface.
-+
-+Interfaces:
-+int cpuidle_register_driver(struct cpuidle_driver *drv);
-+void cpuidle_unregister_driver(struct cpuidle_driver *drv);
-+int cpuidle_force_redetect(struct cpuidle_device *dev);
-diff -Nurb linux-2.6.22-570/Documentation/cpuidle/governor.txt linux-2.6.22-590/Documentation/cpuidle/governor.txt
---- linux-2.6.22-570/Documentation/cpuidle/governor.txt        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/cpuidle/governor.txt        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,24 @@
-+
-+
-+
-+              Supporting multiple CPU idle levels in kernel
-+
-+                              cpuidle governors
-+
-+
-+
-+
-+cpuidle governor is policy routine that decides what idle state to enter at
-+any given time. cpuidle core uses different callbacks to governor while
-+handling idle entry.
-+* select_state callback where governor can determine next idle state to enter
-+* prepare_idle callback is called before entering an idle state
-+* scan callback is called after a driver forces redetection of the states
-+
-+More than one governor can be registered at the same time and
-+user can switch between drivers using /sysfs interface.
-+
-+Interfaces:
-+int cpuidle_register_governor(struct cpuidle_governor *gov);
-+void cpuidle_unregister_governor(struct cpuidle_governor *gov);
-+
-diff -Nurb linux-2.6.22-570/Documentation/cpuidle/sysfs.txt linux-2.6.22-590/Documentation/cpuidle/sysfs.txt
---- linux-2.6.22-570/Documentation/cpuidle/sysfs.txt   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/cpuidle/sysfs.txt   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,27 @@
-+
-+
-+              Supporting multiple CPU idle levels in kernel
-+
-+                              cpuidle sysfs
-+
-+System global cpuidle information are under
-+/sys/devices/system/cpu/cpuidle
-+
-+The current interfaces in this directory has self-explanatory names:
-+* available_drivers
-+* available_governors
-+* current_driver
-+* current_governor
-+
-+Per logical CPU specific cpuidle information are under
-+/sys/devices/system/cpu/cpuX/cpuidle
-+for each online cpu X
-+
-+Under this percpu directory, there is a directory for each idle state supported
-+by the driver, which in turn has
-+* latency
-+* power
-+* time
-+* usage
-+
-+
-diff -Nurb linux-2.6.22-570/Documentation/cpusets.txt linux-2.6.22-590/Documentation/cpusets.txt
---- linux-2.6.22-570/Documentation/cpusets.txt 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/cpusets.txt 2008-01-02 13:56:37.000000000 -0500
-@@ -7,6 +7,7 @@
- Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
- Modified by Paul Jackson <pj@sgi.com>
- Modified by Christoph Lameter <clameter@sgi.com>
-+Modified by Paul Menage <menage@google.com>
- CONTENTS:
- =========
-@@ -16,10 +17,9 @@
-   1.2 Why are cpusets needed ?
-   1.3 How are cpusets implemented ?
-   1.4 What are exclusive cpusets ?
--  1.5 What does notify_on_release do ?
--  1.6 What is memory_pressure ?
--  1.7 What is memory spread ?
--  1.8 How do I use cpusets ?
-+  1.5 What is memory_pressure ?
-+  1.6 What is memory spread ?
-+  1.7 How do I use cpusets ?
- 2. Usage Examples and Syntax
-   2.1 Basic Usage
-   2.2 Adding/removing cpus
-@@ -43,18 +43,19 @@
- hooks, beyond what is already present, required to manage dynamic
- job placement on large systems.
--Each task has a pointer to a cpuset.  Multiple tasks may reference
--the same cpuset.  Requests by a task, using the sched_setaffinity(2)
--system call to include CPUs in its CPU affinity mask, and using the
--mbind(2) and set_mempolicy(2) system calls to include Memory Nodes
--in its memory policy, are both filtered through that tasks cpuset,
--filtering out any CPUs or Memory Nodes not in that cpuset.  The
--scheduler will not schedule a task on a CPU that is not allowed in
--its cpus_allowed vector, and the kernel page allocator will not
--allocate a page on a node that is not allowed in the requesting tasks
--mems_allowed vector.
-+Cpusets use the generic container subsystem described in
-+Documentation/container.txt.
--User level code may create and destroy cpusets by name in the cpuset
-+Requests by a task, using the sched_setaffinity(2) system call to
-+include CPUs in its CPU affinity mask, and using the mbind(2) and
-+set_mempolicy(2) system calls to include Memory Nodes in its memory
-+policy, are both filtered through that tasks cpuset, filtering out any
-+CPUs or Memory Nodes not in that cpuset.  The scheduler will not
-+schedule a task on a CPU that is not allowed in its cpus_allowed
-+vector, and the kernel page allocator will not allocate a page on a
-+node that is not allowed in the requesting tasks mems_allowed vector.
-+
-+User level code may create and destroy cpusets by name in the container
- virtual file system, manage the attributes and permissions of these
- cpusets and which CPUs and Memory Nodes are assigned to each cpuset,
- specify and query to which cpuset a task is assigned, and list the
-@@ -86,9 +87,6 @@
-       and a database), or
-     * NUMA systems running large HPC applications with demanding
-       performance characteristics.
--    * Also cpu_exclusive cpusets are useful for servers running orthogonal
--      workloads such as RT applications requiring low latency and HPC
--      applications that are throughput sensitive
- These subsets, or "soft partitions" must be able to be dynamically
- adjusted, as the job mix changes, without impacting other concurrently
-@@ -117,7 +115,7 @@
-  - Cpusets are sets of allowed CPUs and Memory Nodes, known to the
-    kernel.
-  - Each task in the system is attached to a cpuset, via a pointer
--   in the task structure to a reference counted cpuset structure.
-+   in the task structure to a reference counted container structure.
-  - Calls to sched_setaffinity are filtered to just those CPUs
-    allowed in that tasks cpuset.
-  - Calls to mbind and set_mempolicy are filtered to just
-@@ -131,8 +129,6 @@
-  - A cpuset may be marked exclusive, which ensures that no other
-    cpuset (except direct ancestors and descendents) may contain
-    any overlapping CPUs or Memory Nodes.
--   Also a cpu_exclusive cpuset would be associated with a sched
--   domain.
-  - You can list all the tasks (by pid) attached to any cpuset.
- The implementation of cpusets requires a few, simple hooks
-@@ -144,23 +140,15 @@
-    allowed in that tasks cpuset.
-  - in sched.c migrate_all_tasks(), to keep migrating tasks within
-    the CPUs allowed by their cpuset, if possible.
-- - in sched.c, a new API partition_sched_domains for handling
--   sched domain changes associated with cpu_exclusive cpusets
--   and related changes in both sched.c and arch/ia64/kernel/domain.c
-  - in the mbind and set_mempolicy system calls, to mask the requested
-    Memory Nodes by what's allowed in that tasks cpuset.
-  - in page_alloc.c, to restrict memory to allowed nodes.
-  - in vmscan.c, to restrict page recovery to the current cpuset.
--In addition a new file system, of type "cpuset" may be mounted,
--typically at /dev/cpuset, to enable browsing and modifying the cpusets
--presently known to the kernel.  No new system calls are added for
--cpusets - all support for querying and modifying cpusets is via
--this cpuset file system.
--
--Each task under /proc has an added file named 'cpuset', displaying
--the cpuset name, as the path relative to the root of the cpuset file
--system.
-+You should mount the "container" filesystem type in order to enable
-+browsing and modifying the cpusets presently known to the kernel.  No
-+new system calls are added for cpusets - all support for querying and
-+modifying cpusets is via this cpuset file system.
- The /proc/<pid>/status file for each task has two added lines,
- displaying the tasks cpus_allowed (on which CPUs it may be scheduled)
-@@ -170,16 +158,15 @@
-   Cpus_allowed:   ffffffff,ffffffff,ffffffff,ffffffff
-   Mems_allowed:   ffffffff,ffffffff
--Each cpuset is represented by a directory in the cpuset file system
--containing the following files describing that cpuset:
-+Each cpuset is represented by a directory in the container file system
-+containing (on top of the standard container files) the following
-+files describing that cpuset:
-  - cpus: list of CPUs in that cpuset
-  - mems: list of Memory Nodes in that cpuset
-  - memory_migrate flag: if set, move pages to cpusets nodes
-  - cpu_exclusive flag: is cpu placement exclusive?
-  - mem_exclusive flag: is memory placement exclusive?
-- - tasks: list of tasks (by pid) attached to that cpuset
-- - notify_on_release flag: run /sbin/cpuset_release_agent on exit?
-  - memory_pressure: measure of how much paging pressure in cpuset
- In addition, the root cpuset only has the following file:
-@@ -231,15 +218,6 @@
- a direct ancestor or descendent, may share any of the same CPUs or
- Memory Nodes.
--A cpuset that is cpu_exclusive has a scheduler (sched) domain
--associated with it.  The sched domain consists of all CPUs in the
--current cpuset that are not part of any exclusive child cpusets.
--This ensures that the scheduler load balancing code only balances
--against the CPUs that are in the sched domain as defined above and
--not all of the CPUs in the system. This removes any overhead due to
--load balancing code trying to pull tasks outside of the cpu_exclusive
--cpuset only to be prevented by the tasks' cpus_allowed mask.
--
- A cpuset that is mem_exclusive restricts kernel allocations for
- page, buffer and other data commonly shared by the kernel across
- multiple users.  All cpusets, whether mem_exclusive or not, restrict
-@@ -253,21 +231,7 @@
- outside even a mem_exclusive cpuset.
--1.5 What does notify_on_release do ?
--------------------------------------
--
--If the notify_on_release flag is enabled (1) in a cpuset, then whenever
--the last task in the cpuset leaves (exits or attaches to some other
--cpuset) and the last child cpuset of that cpuset is removed, then
--the kernel runs the command /sbin/cpuset_release_agent, supplying the
--pathname (relative to the mount point of the cpuset file system) of the
--abandoned cpuset.  This enables automatic removal of abandoned cpusets.
--The default value of notify_on_release in the root cpuset at system
--boot is disabled (0).  The default value of other cpusets at creation
--is the current value of their parents notify_on_release setting.
--
--
--1.6 What is memory_pressure ?
-+1.5 What is memory_pressure ?
- -----------------------------
- The memory_pressure of a cpuset provides a simple per-cpuset metric
- of the rate that the tasks in a cpuset are attempting to free up in
-@@ -324,7 +288,7 @@
- times 1000.
--1.7 What is memory spread ?
-+1.6 What is memory spread ?
- ---------------------------
- There are two boolean flag files per cpuset that control where the
- kernel allocates pages for the file system buffers and related in
-@@ -395,7 +359,7 @@
- can become very uneven.
--1.8 How do I use cpusets ?
-+1.7 How do I use cpusets ?
- --------------------------
- In order to minimize the impact of cpusets on critical kernel
-@@ -485,7 +449,7 @@
- To start a new job that is to be contained within a cpuset, the steps are:
-  1) mkdir /dev/cpuset
-- 2) mount -t cpuset none /dev/cpuset
-+ 2) mount -t container -ocpuset cpuset /dev/cpuset
-  3) Create the new cpuset by doing mkdir's and write's (or echo's) in
-     the /dev/cpuset virtual file system.
-  4) Start a task that will be the "founding father" of the new job.
-@@ -497,7 +461,7 @@
- named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
- and then start a subshell 'sh' in that cpuset:
--  mount -t cpuset none /dev/cpuset
-+  mount -t container -ocpuset cpuset /dev/cpuset
-   cd /dev/cpuset
-   mkdir Charlie
-   cd Charlie
-@@ -529,7 +493,7 @@
- virtual filesystem.
- To mount it, type:
--# mount -t cpuset none /dev/cpuset
-+# mount -t container -o cpuset cpuset /dev/cpuset
- Then under /dev/cpuset you can find a tree that corresponds to the
- tree of the cpusets in the system. For instance, /dev/cpuset
-@@ -572,6 +536,18 @@
- This will fail if the cpuset is in use (has cpusets inside, or has
- processes attached).
-+Note that for legacy reasons, the "cpuset" filesystem exists as a
-+wrapper around the container filesystem.
-+
-+The command
-+
-+mount -t cpuset X /dev/cpuset
-+
-+is equivalent to
-+
-+mount -t container -ocpuset X /dev/cpuset
-+echo "/sbin/cpuset_release_agent" > /dev/cpuset/release_agent
-+
- 2.2 Adding/removing cpus
- ------------------------
-diff -Nurb linux-2.6.22-570/Documentation/feature-removal-schedule.txt linux-2.6.22-590/Documentation/feature-removal-schedule.txt
---- linux-2.6.22-570/Documentation/feature-removal-schedule.txt        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/feature-removal-schedule.txt        2008-01-02 13:56:37.000000000 -0500
-@@ -162,6 +162,33 @@
- ---------------------------
-+What: filemap_nopage, filemap_populate
-+When: April 2007
-+Why:  These legacy interfaces no longer have any callers in the kernel and
-+      any functionality provided can be provided with filemap_fault. The
-+      removal schedule is short because they are a big maintainence burden
-+      and have some bugs.
-+Who:  Nick Piggin <npiggin@suse.de>
-+
-+---------------------------
-+
-+What: vm_ops.populate, install_page
-+When: April 2007
-+Why:  These legacy interfaces no longer have any callers in the kernel and
-+      any functionality provided can be provided with vm_ops.fault.
-+Who:  Nick Piggin <npiggin@suse.de>
-+
-+---------------------------
-+
-+What: vm_ops.nopage
-+When: February 2008, provided in-kernel callers have been converted
-+Why:  This interface is replaced by vm_ops.fault, but it has been around
-+      forever, is used by a lot of drivers, and doesn't cost much to
-+      maintain.
-+Who:  Nick Piggin <npiggin@suse.de>
-+
-+---------------------------
-+
- What: Interrupt only SA_* flags
- When: September 2007
- Why:  The interrupt related SA_* flags are replaced by IRQF_* to move them
-@@ -280,25 +307,6 @@
- ---------------------------
--What: Multipath cached routing support in ipv4
--When: in 2.6.23
--Why:  Code was merged, then submitter immediately disappeared leaving
--      us with no maintainer and lots of bugs.  The code should not have
--      been merged in the first place, and many aspects of it's
--      implementation are blocking more critical core networking
--      development.  It's marked EXPERIMENTAL and no distribution
--      enables it because it cause obscure crashes due to unfixable bugs
--      (interfaces don't return errors so memory allocation can't be
--      handled, calling contexts of these interfaces make handling
--      errors impossible too because they get called after we've
--      totally commited to creating a route object, for example).
--      This problem has existed for years and no forward progress
--      has ever been made, and nobody steps up to try and salvage
--      this code, so we're going to finally just get rid of it.
--Who:  David S. Miller <davem@davemloft.net>
--
-----------------------------
--
- What: read_dev_chars(), read_conf_data{,_lpm}() (s390 common I/O layer)
- When: December 2007
- Why:  These functions are a leftover from 2.4 times. They have several
-diff -Nurb linux-2.6.22-570/Documentation/filesystems/00-INDEX linux-2.6.22-590/Documentation/filesystems/00-INDEX
---- linux-2.6.22-570/Documentation/filesystems/00-INDEX        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/filesystems/00-INDEX        2008-01-02 13:56:37.000000000 -0500
-@@ -84,6 +84,8 @@
-       - info and mount options for the UDF filesystem.
- ufs.txt
-       - info on the ufs filesystem.
-+unionfs/
-+      - info on the unionfs filesystem
- vfat.txt
-       - info on using the VFAT filesystem used in Windows NT and Windows 95
- vfs.txt
-diff -Nurb linux-2.6.22-570/Documentation/filesystems/Locking linux-2.6.22-590/Documentation/filesystems/Locking
---- linux-2.6.22-570/Documentation/filesystems/Locking 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/filesystems/Locking 2008-01-02 13:56:37.000000000 -0500
-@@ -510,12 +510,14 @@
- prototypes:
-       void (*open)(struct vm_area_struct*);
-       void (*close)(struct vm_area_struct*);
-+      struct page *(*fault)(struct vm_area_struct*, struct fault_data *);
-       struct page *(*nopage)(struct vm_area_struct*, unsigned long, int *);
- locking rules:
-               BKL     mmap_sem
- open:         no      yes
- close:                no      yes
-+fault:                no      yes
- nopage:               no      yes
- ================================================================================
-diff -Nurb linux-2.6.22-570/Documentation/filesystems/configfs/configfs.txt linux-2.6.22-590/Documentation/filesystems/configfs/configfs.txt
---- linux-2.6.22-570/Documentation/filesystems/configfs/configfs.txt   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/filesystems/configfs/configfs.txt   2008-01-02 13:56:37.000000000 -0500
-@@ -238,6 +238,8 @@
-               struct config_group *(*make_group)(struct config_group *group,
-                                                  const char *name);
-               int (*commit_item)(struct config_item *item);
-+              void (*disconnect_notify)(struct config_group *group,
-+                                        struct config_item *item);
-               void (*drop_item)(struct config_group *group,
-                                 struct config_item *item);
-       };
-@@ -268,6 +270,16 @@
- for the item to actually disappear from the subsystem's usage.  But it
- is gone from configfs.
-+When drop_item() is called, the item's linkage has already been torn
-+down.  It no longer has a reference on its parent and has no place in
-+the item hierarchy.  If a client needs to do some cleanup before this
-+teardown happens, the subsystem can implement the
-+ct_group_ops->disconnect_notify() method.  The method is called after
-+configfs has removed the item from the filesystem view but before the
-+item is removed from its parent group.  Like drop_item(),
-+disconnect_notify() is void and cannot fail.  Client subsystems should
-+not drop any references here, as they still must do it in drop_item().
-+
- A config_group cannot be removed while it still has child items.  This
- is implemented in the configfs rmdir(2) code.  ->drop_item() will not be
- called, as the item has not been dropped.  rmdir(2) will fail, as the
-@@ -386,6 +398,33 @@
- rmdir(2).  They also are not considered when rmdir(2) on the parent
- group is checking for children.
-+[Dependant Subsystems]
-+
-+Sometimes other drivers depend on particular configfs items.  For
-+example, ocfs2 mounts depend on a heartbeat region item.  If that
-+region item is removed with rmdir(2), the ocfs2 mount must BUG or go
-+readonly.  Not happy.
-+    
-+configfs provides two additional API calls: configfs_depend_item() and
-+configfs_undepend_item().  A client driver can call
-+configfs_depend_item() on an existing item to tell configfs that it is
-+depended on.  configfs will then return -EBUSY from rmdir(2) for that
-+item.  When the item is no longer depended on, the client driver calls
-+configfs_undepend_item() on it.
-+
-+These API cannot be called underneath any configfs callbacks, as
-+they will conflict.  They can block and allocate.  A client driver
-+probably shouldn't calling them of its own gumption.  Rather it should
-+be providing an API that external subsystems call.
-+
-+How does this work?  Imagine the ocfs2 mount process.  When it mounts,
-+it asks for a heartbeat region item.  This is done via a call into the
-+heartbeat code.  Inside the heartbeat code, the region item is looked
-+up.  Here, the heartbeat code calls configfs_depend_item().  If it
-+succeeds, then heartbeat knows the region is safe to give to ocfs2.
-+If it fails, it was being torn down anyway, and heartbeat can gracefully
-+pass up an error.
-+
- [Committable Items]
- NOTE: Committable items are currently unimplemented.
-diff -Nurb linux-2.6.22-570/Documentation/filesystems/unionfs/00-INDEX linux-2.6.22-590/Documentation/filesystems/unionfs/00-INDEX
---- linux-2.6.22-570/Documentation/filesystems/unionfs/00-INDEX        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/filesystems/unionfs/00-INDEX        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,10 @@
-+00-INDEX
-+      - this file.
-+concepts.txt
-+      - A brief introduction of concepts.
-+issues.txt
-+      - A summary of known issues with unionfs.
-+rename.txt
-+      - Information regarding rename operations.
-+usage.txt
-+      - Usage information and examples.
-diff -Nurb linux-2.6.22-570/Documentation/filesystems/unionfs/concepts.txt linux-2.6.22-590/Documentation/filesystems/unionfs/concepts.txt
---- linux-2.6.22-570/Documentation/filesystems/unionfs/concepts.txt    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/filesystems/unionfs/concepts.txt    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,75 @@
-+Unionfs 2.0 CONCEPTS:
-+=====================
-+
-+This file describes the concepts needed by a namespace unification file
-+system.
-+
-+Branch Priority:
-+================
-+
-+Each branch is assigned a unique priority - starting from 0 (highest
-+priority).  No two branches can have the same priority.
-+
-+
-+Branch Mode:
-+============
-+
-+Each branch is assigned a mode - read-write or read-only. This allows
-+directories on media mounted read-write to be used in a read-only manner.
-+
-+
-+Whiteouts:
-+==========
-+
-+A whiteout removes a file name from the namespace. Whiteouts are needed when
-+one attempts to remove a file on a read-only branch.
-+
-+Suppose we have a two-branch union, where branch 0 is read-write and branch
-+1 is read-only. And a file 'foo' on branch 1:
-+
-+./b0/
-+./b1/
-+./b1/foo
-+
-+The unified view would simply be:
-+
-+./union/
-+./union/foo
-+
-+Since 'foo' is stored on a read-only branch, it cannot be removed. A
-+whiteout is used to remove the name 'foo' from the unified namespace. Again,
-+since branch 1 is read-only, the whiteout cannot be created there. So, we
-+try on a higher priority (lower numerically) branch and create the whiteout
-+there.
-+
-+./b0/
-+./b0/.wh.foo
-+./b1/
-+./b1/foo
-+
-+Later, when Unionfs traverses branches (due to lookup or readdir), it
-+eliminate 'foo' from the namespace (as well as the whiteout itself.)
-+
-+
-+Duplicate Elimination:
-+======================
-+
-+It is possible for files on different branches to have the same name.
-+Unionfs then has to select which instance of the file to show to the user.
-+Given the fact that each branch has a priority associated with it, the
-+simplest solution is to take the instance from the highest priority
-+(numerically lowest value) and "hide" the others.
-+
-+
-+Copyup:
-+=======
-+
-+When a change is made to the contents of a file's data or meta-data, they
-+have to be stored somewhere. The best way is to create a copy of the
-+original file on a branch that is writable, and then redirect the write
-+though to this copy. The copy must be made on a higher priority branch so
-+that lookup and readdir return this newer "version" of the file rather than
-+the original (see duplicate elimination).
-+
-+
-+For more information, see <http://unionfs.filesystems.org/>.
-diff -Nurb linux-2.6.22-570/Documentation/filesystems/unionfs/issues.txt linux-2.6.22-590/Documentation/filesystems/unionfs/issues.txt
---- linux-2.6.22-570/Documentation/filesystems/unionfs/issues.txt      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/filesystems/unionfs/issues.txt      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,39 @@
-+KNOWN Unionfs 2.0 ISSUES:
-+=========================
-+
-+1. The NFS server returns -EACCES for read-only exports, instead of -EROFS.
-+   This means we can't reliably detect a read-only NFS export.
-+
-+2. Modifying a Unionfs branch directly, while the union is mounted, is
-+   currently unsupported, because it could cause a cache incoherency between
-+   the union layer and the lower file systems (for that reason, Unionfs
-+   currently prohibits using branches which overlap with each other, even
-+   partially).  We have tested Unionfs under such conditions, and fixed any
-+   bugs we found (Unionfs comes with an extensive regression test suite).
-+   However, it may still be possible that changes made to lower branches
-+   directly could cause cache incoherency which, in the worst case, may case
-+   an oops.
-+
-+   Unionfs 2.0 has a temporary workaround for this.  You can force Unionfs
-+   to increase the superblock generation number, and hence purge all cached
-+   Unionfs objects, which would then  be re-gotten from the lower branches.
-+   This should ensure cache consistency.  To increase the generation number,
-+   executed the command:
-+
-+      mount -t unionfs -o remount,incgen none MOUNTPOINT
-+
-+   Note that the older way of incrementing the generation number using an
-+   ioctl, is no longer supported in Unionfs 2.0.  Ioctls in general are not
-+   encouraged.  Plus, an ioctl is per-file concept, whereas the generation
-+   number is a per-file-system concept.  Worse, such an ioctl requires an
-+   open file, which then has to be invalidated by the very nature of the
-+   generation number increase (read: the old generation increase ioctl was
-+   pretty racy).
-+
-+3. Unionfs should not use lookup_one_len() on the underlying f/s as it
-+   confuses NFS.  Currently, unionfs_lookup() passes lookup intents to the
-+   lower file-system, this eliminates part of the problem.  The remaining
-+   calls to lookup_one_len may need to be changed to pass an intent.
-+
-+
-+For more information, see <http://unionfs.filesystems.org/>.
-diff -Nurb linux-2.6.22-570/Documentation/filesystems/unionfs/rename.txt linux-2.6.22-590/Documentation/filesystems/unionfs/rename.txt
---- linux-2.6.22-570/Documentation/filesystems/unionfs/rename.txt      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/filesystems/unionfs/rename.txt      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,31 @@
-+Rename is a complex beast. The following table shows which rename(2) operations
-+should succeed and which should fail.
-+
-+o: success
-+E: error (either unionfs or vfs)
-+X: EXDEV
-+
-+none = file does not exist
-+file = file is a file
-+dir  = file is a empty directory
-+child= file is a non-empty directory
-+wh   = file is a directory containing only whiteouts; this makes it logically
-+              empty
-+
-+                      none    file    dir     child   wh
-+file                  o       o       E       E       E
-+dir                   o       E       o       E       o
-+child                 X       E       X       E       X
-+wh                    o       E       o       E       o
-+
-+
-+Renaming directories:
-+=====================
-+
-+Whenever a empty (either physically or logically) directory is being renamed,
-+the following sequence of events should take place:
-+
-+1) Remove whiteouts from both source and destination directory
-+2) Rename source to destination
-+3) Make destination opaque to prevent anything under it from showing up
-+
-diff -Nurb linux-2.6.22-570/Documentation/filesystems/unionfs/usage.txt linux-2.6.22-590/Documentation/filesystems/unionfs/usage.txt
---- linux-2.6.22-570/Documentation/filesystems/unionfs/usage.txt       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/filesystems/unionfs/usage.txt       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,90 @@
-+Unionfs is a stackable unification file system, which can appear to merge
-+the contents of several directories (branches), while keeping their physical
-+content separate.  Unionfs is useful for unified source tree management,
-+merged contents of split CD-ROM, merged separate software package
-+directories, data grids, and more.  Unionfs allows any mix of read-only and
-+read-write branches, as well as insertion and deletion of branches anywhere
-+in the fan-out.  To maintain Unix semantics, Unionfs handles elimination of
-+duplicates, partial-error conditions, and more.
-+
-+# mount -t unionfs -o branch-option[,union-options[,...]] none MOUNTPOINT
-+
-+The available branch-option for the mount command is:
-+
-+      dirs=branch[=ro|=rw][:...]
-+
-+specifies a separated list of which directories compose the union.
-+Directories that come earlier in the list have a higher precedence than
-+those which come later. Additionally, read-only or read-write permissions of
-+the branch can be specified by appending =ro or =rw (default) to each
-+directory.
-+
-+Syntax:
-+
-+      dirs=/branch1[=ro|=rw]:/branch2[=ro|=rw]:...:/branchN[=ro|=rw]
-+
-+Example:
-+
-+      dirs=/writable_branch=rw:/read-only_branch=ro
-+
-+
-+DYNAMIC BRANCH MANAGEMENT AND REMOUNTS
-+======================================
-+
-+You can remount a union and change its overall mode, or reconfigure the
-+branches, as follows.
-+
-+To downgrade a union from read-write to read-only:
-+
-+# mount -t unionfs -o remount,ro none MOUNTPOINT
-+
-+To upgrade a union from read-only to read-write:
-+
-+# mount -t unionfs -o remount,rw none MOUNTPOINT
-+
-+To delete a branch /foo, regardless where it is in the current union:
-+
-+# mount -t unionfs -o del=/foo none MOUNTPOINT
-+
-+To insert (add) a branch /foo before /bar:
-+
-+# mount -t unionfs -o remount,add=/bar:/foo none MOUNTPOINT
-+
-+To insert (add) a branch /foo (with the "rw" mode flag) before /bar:
-+
-+# mount -t unionfs -o remount,add=/bar:/foo=rw none MOUNTPOINT
-+
-+To insert (add) a branch /foo (in "rw" mode) at the very beginning (i.e., a
-+new highest-priority branch), you can use the above syntax, or use a short
-+hand version as follows:
-+
-+# mount -t unionfs -o remount,add=/foo none MOUNTPOINT
-+
-+To append a branch to the very end (new lowest-priority branch):
-+
-+# mount -t unionfs -o remount,add=:/foo none MOUNTPOINT
-+
-+To append a branch to the very end (new lowest-priority branch), in
-+read-only mode:
-+
-+# mount -t unionfs -o remount,add=:/foo:ro none MOUNTPOINT
-+
-+Finally, to change the mode of one existing branch, say /foo, from read-only
-+to read-write, and change /bar from read-write to read-only:
-+
-+# mount -t unionfs -o remount,mode=/foo=rw,mode=/bar=ro none MOUNTPOINT
-+
-+
-+CACHE CONSISTENCY
-+=================
-+
-+If you modify any file on any of the lower branches directly, while there is
-+a Unionfs 2.0 mounted above any of those branches, you should tell Unionfs
-+to purge its caches and re-get the objects.  To do that, you have to
-+increment the generation number of the superblock using the following
-+command:
-+
-+# mount -t unionfs -o remount,incgen none MOUNTPOINT
-+
-+
-+For more information, see <http://unionfs.filesystems.org/>.
-diff -Nurb linux-2.6.22-570/Documentation/firmware_class/firmware_sample_firmware_class.c linux-2.6.22-590/Documentation/firmware_class/firmware_sample_firmware_class.c
---- linux-2.6.22-570/Documentation/firmware_class/firmware_sample_firmware_class.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/firmware_class/firmware_sample_firmware_class.c     2008-01-02 13:56:37.000000000 -0500
-@@ -78,6 +78,7 @@
-                        firmware_loading_show, firmware_loading_store);
- static ssize_t firmware_data_read(struct kobject *kobj,
-+                                struct bin_attribute *bin_attr,
-                                 char *buffer, loff_t offset, size_t count)
- {
-       struct class_device *class_dev = to_class_dev(kobj);
-@@ -88,6 +89,7 @@
-       return count;
- }
- static ssize_t firmware_data_write(struct kobject *kobj,
-+                                 struct bin_attribute *bin_attr,
-                                  char *buffer, loff_t offset, size_t count)
- {
-       struct class_device *class_dev = to_class_dev(kobj);
-diff -Nurb linux-2.6.22-570/Documentation/power/freezing-of-tasks.txt linux-2.6.22-590/Documentation/power/freezing-of-tasks.txt
---- linux-2.6.22-570/Documentation/power/freezing-of-tasks.txt 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/power/freezing-of-tasks.txt 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,160 @@
-+Freezing of tasks
-+      (C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL
-+
-+I. What is the freezing of tasks?
-+
-+The freezing of tasks is a mechanism by which user space processes and some
-+kernel threads are controlled during hibernation or system-wide suspend (on some
-+architectures).
-+
-+II. How does it work?
-+
-+There are four per-task flags used for that, PF_NOFREEZE, PF_FROZEN, TIF_FREEZE
-+and PF_FREEZER_SKIP (the last one is auxiliary).  The tasks that have
-+PF_NOFREEZE unset (all user space processes and some kernel threads) are
-+regarded as 'freezable' and treated in a special way before the system enters a
-+suspend state as well as before a hibernation image is created (in what follows
-+we only consider hibernation, but the description also applies to suspend).
-+
-+Namely, as the first step of the hibernation procedure the function
-+freeze_processes() (defined in kernel/power/process.c) is called.  It executes
-+try_to_freeze_tasks() that sets TIF_FREEZE for all of the freezable tasks and
-+sends a fake signal to each of them.  A task that receives such a signal and has
-+TIF_FREEZE set, should react to it by calling the refrigerator() function
-+(defined in kernel/power/process.c), which sets the task's PF_FROZEN flag,
-+changes its state to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is
-+cleared for it.  Then, we say that the task is 'frozen' and therefore the set of
-+functions handling this mechanism is called 'the freezer' (these functions are
-+defined in kernel/power/process.c and include/linux/freezer.h).  User space
-+processes are generally frozen before kernel threads.
-+
-+It is not recommended to call refrigerator() directly.  Instead, it is
-+recommended to use the try_to_freeze() function (defined in
-+include/linux/freezer.h), that checks the task's TIF_FREEZE flag and makes the
-+task enter refrigerator() if the flag is set.
-+
-+For user space processes try_to_freeze() is called automatically from the
-+signal-handling code, but the freezable kernel threads need to call it
-+explicitly in suitable places.  The code to do this may look like the following:
-+
-+      do {
-+              hub_events();
-+              wait_event_interruptible(khubd_wait,
-+                                      !list_empty(&hub_event_list));
-+              try_to_freeze();
-+      } while (!signal_pending(current));
-+
-+(from drivers/usb/core/hub.c::hub_thread()).
-+
-+If a freezable kernel thread fails to call try_to_freeze() after the freezer has
-+set TIF_FREEZE for it, the freezing of tasks will fail and the entire
-+hibernation operation will be cancelled.  For this reason, freezable kernel
-+threads must call try_to_freeze() somewhere.
-+
-+After the system memory state has been restored from a hibernation image and
-+devices have been reinitialized, the function thaw_processes() is called in
-+order to clear the PF_FROZEN flag for each frozen task.  Then, the tasks that
-+have been frozen leave refrigerator() and continue running.
-+
-+III. Which kernel threads are freezable?
-+
-+Kernel threads are not freezable by default.  However, a kernel thread may clear
-+PF_NOFREEZE for itself by calling set_freezable() (the resetting of PF_NOFREEZE
-+directly is strongly discouraged).  From this point it is regarded as freezable
-+and must call try_to_freeze() in a suitable place.
-+
-+IV. Why do we do that?
-+
-+Generally speaking, there is a couple of reasons to use the freezing of tasks:
-+
-+1. The principal reason is to prevent filesystems from being damaged after
-+hibernation.  At the moment we have no simple means of checkpointing
-+filesystems, so if there are any modifications made to filesystem data and/or
-+metadata on disks, we cannot bring them back to the state from before the
-+modifications.  At the same time each hibernation image contains some
-+filesystem-related information that must be consistent with the state of the
-+on-disk data and metadata after the system memory state has been restored from
-+the image (otherwise the filesystems will be damaged in a nasty way, usually
-+making them almost impossible to repair).  We therefore freeze tasks that might
-+cause the on-disk filesystems' data and metadata to be modified after the
-+hibernation image has been created and before the system is finally powered off.
-+The majority of these are user space processes, but if any of the kernel threads
-+may cause something like this to happen, they have to be freezable.
-+
-+2. The second reason is to prevent user space processes and some kernel threads
-+from interfering with the suspending and resuming of devices.  A user space
-+process running on a second CPU while we are suspending devices may, for
-+example, be troublesome and without the freezing of tasks we would need some
-+safeguards against race conditions that might occur in such a case.
-+
-+Although Linus Torvalds doesn't like the freezing of tasks, he said this in one
-+of the discussions on LKML (http://lkml.org/lkml/2007/4/27/608):
-+
-+"RJW:> Why we freeze tasks at all or why we freeze kernel threads?
-+
-+Linus: In many ways, 'at all'.
-+
-+I _do_ realize the IO request queue issues, and that we cannot actually do
-+s2ram with some devices in the middle of a DMA.  So we want to be able to
-+avoid *that*, there's no question about that.  And I suspect that stopping
-+user threads and then waiting for a sync is practically one of the easier
-+ways to do so.
-+
-+So in practice, the 'at all' may become a 'why freeze kernel threads?' and
-+freezing user threads I don't find really objectionable."
-+
-+Still, there are kernel threads that may want to be freezable.  For example, if
-+a kernel that belongs to a device driver accesses the device directly, it in
-+principle needs to know when the device is suspended, so that it doesn't try to
-+access it at that time.  However, if the kernel thread is freezable, it will be
-+frozen before the driver's .suspend() callback is executed and it will be
-+thawed after the driver's .resume() callback has run, so it won't be accessing
-+the device while it's suspended.
-+
-+3. Another reason for freezing tasks is to prevent user space processes from
-+realizing that hibernation (or suspend) operation takes place.  Ideally, user
-+space processes should not notice that such a system-wide operation has occurred
-+and should continue running without any problems after the restore (or resume
-+from suspend).  Unfortunately, in the most general case this is quite difficult
-+to achieve without the freezing of tasks.  Consider, for example, a process
-+that depends on all CPUs being online while it's running.  Since we need to
-+disable nonboot CPUs during the hibernation, if this process is not frozen, it
-+may notice that the number of CPUs has changed and may start to work incorrectly
-+because of that.
-+
-+V. Are there any problems related to the freezing of tasks?
-+
-+Yes, there are.
-+
-+First of all, the freezing of kernel threads may be tricky if they depend one
-+on another.  For example, if kernel thread A waits for a completion (in the
-+TASK_UNINTERRUPTIBLE state) that needs to be done by freezable kernel thread B
-+and B is frozen in the meantime, then A will be blocked until B is thawed, which
-+may be undesirable.  That's why kernel threads are not freezable by default.
-+
-+Second, there are the following two problems related to the freezing of user
-+space processes:
-+1. Putting processes into an uninterruptible sleep distorts the load average.
-+2. Now that we have FUSE, plus the framework for doing device drivers in
-+userspace, it gets even more complicated because some userspace processes are
-+now doing the sorts of things that kernel threads do
-+(https://lists.linux-foundation.org/pipermail/linux-pm/2007-May/012309.html).
-+
-+The problem 1. seems to be fixable, although it hasn't been fixed so far.  The
-+other one is more serious, but it seems that we can work around it by using
-+hibernation (and suspend) notifiers (in that case, though, we won't be able to
-+avoid the realization by the user space processes that the hibernation is taking
-+place).
-+
-+There are also problems that the freezing of tasks tends to expose, although
-+they are not directly related to it.  For example, if request_firmware() is
-+called from a device driver's .resume() routine, it will timeout and eventually
-+fail, because the user land process that should respond to the request is frozen
-+at this point.  So, seemingly, the failure is due to the freezing of tasks.
-+Suppose, however, that the firmware file is located on a filesystem accessible
-+only through another device that hasn't been resumed yet.  In that case,
-+request_firmware() will fail regardless of whether or not the freezing of tasks
-+is used.  Consequently, the problem is not really related to the freezing of
-+tasks, since it generally exists anyway.  [The solution to this particular
-+problem is to keep the firmware in memory after it's loaded for the first time
-+and upload if from memory to the device whenever necessary.]
-diff -Nurb linux-2.6.22-570/Documentation/power/kernel_threads.txt linux-2.6.22-590/Documentation/power/kernel_threads.txt
---- linux-2.6.22-570/Documentation/power/kernel_threads.txt    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/power/kernel_threads.txt    1969-12-31 19:00:00.000000000 -0500
-@@ -1,40 +0,0 @@
--KERNEL THREADS
--
--
--Freezer
--
--Upon entering a suspended state the system will freeze all
--tasks. This is done by delivering pseudosignals. This affects
--kernel threads, too. To successfully freeze a kernel thread
--the thread has to check for the pseudosignal and enter the
--refrigerator. Code to do this looks like this:
--
--      do {
--              hub_events();
--              wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
--              try_to_freeze();
--      } while (!signal_pending(current));
--
--from drivers/usb/core/hub.c::hub_thread()
--
--
--The Unfreezable
--
--Some kernel threads however, must not be frozen. The kernel must
--be able to finish pending IO operations and later on be able to
--write the memory image to disk. Kernel threads needed to do IO
--must stay awake. Such threads must mark themselves unfreezable
--like this:
--
--      /*
--       * This thread doesn't need any user-level access,
--       * so get rid of all our resources.
--       */
--      daemonize("usb-storage");
--
--      current->flags |= PF_NOFREEZE;
--
--from drivers/usb/storage/usb.c::usb_stor_control_thread()
--
--Such drivers are themselves responsible for staying quiet during
--the actual snapshotting.
-diff -Nurb linux-2.6.22-570/Documentation/power/swsusp.txt linux-2.6.22-590/Documentation/power/swsusp.txt
---- linux-2.6.22-570/Documentation/power/swsusp.txt    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/power/swsusp.txt    2008-01-02 13:56:37.000000000 -0500
-@@ -140,21 +140,11 @@
- website, and not to the Linux Kernel Mailing List. We are working
- toward merging suspend2 into the mainline kernel.
--Q: A kernel thread must voluntarily freeze itself (call 'refrigerator').
--I found some kernel threads that don't do it, and they don't freeze
--so the system can't sleep. Is this a known behavior?
--
--A: All such kernel threads need to be fixed, one by one. Select the
--place where the thread is safe to be frozen (no kernel semaphores
--should be held at that point and it must be safe to sleep there), and
--add:
--
--       try_to_freeze();
--
--If the thread is needed for writing the image to storage, you should
--instead set the PF_NOFREEZE process flag when creating the thread (and
--be very careful).
-+Q: What is the freezing of tasks and why are we using it?
-+A: The freezing of tasks is a mechanism by which user space processes and some
-+kernel threads are controlled during hibernation or system-wide suspend (on some
-+architectures).  See freezing-of-tasks.txt for details.
- Q: What is the difference between "platform" and "shutdown"?
-diff -Nurb linux-2.6.22-570/Documentation/scsi/scsi_fc_transport.txt linux-2.6.22-590/Documentation/scsi/scsi_fc_transport.txt
---- linux-2.6.22-570/Documentation/scsi/scsi_fc_transport.txt  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/scsi/scsi_fc_transport.txt  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,450 @@
-+                             SCSI FC Tansport
-+                 =============================================
-+
-+Date:  4/12/2007
-+Kernel Revisions for features:
-+  rports : <<TBS>>
-+  vports : 2.6.22 (? TBD)
-+
-+
-+Introduction
-+============
-+This file documents the features and components of the SCSI FC Transport.
-+It also provides documents the API between the transport and FC LLDDs.
-+The FC transport can be found at:
-+  drivers/scsi/scsi_transport_fc.c
-+  include/scsi/scsi_transport_fc.h
-+  include/scsi/scsi_netlink_fc.h
-+
-+This file is found at Documentation/scsi/scsi_fc_transport.txt
-+
-+
-+FC Remote Ports (rports)
-+========================================================================
-+<< To Be Supplied >>
-+
-+
-+FC Virtual Ports (vports)
-+========================================================================
-+
-+Overview:
-+-------------------------------
-+
-+  New FC standards have defined mechanisms which allows for a single physical
-+  port to appear on as multiple communication ports. Using the N_Port Id
-+  Virtualization (NPIV) mechanism, a point-to-point connection to a Fabric
-+  can be assigned more than 1 N_Port_ID.  Each N_Port_ID appears as a
-+  separate port to other endpoints on the fabric, even though it shares one
-+  physical link to the switch for communication. Each N_Port_ID can have a
-+  unique view of the fabric based on fabric zoning and array lun-masking
-+  (just like a normal non-NPIV adapter).  Using the Virtual Fabric (VF)
-+  mechanism, adding a fabric header to each frame allows the port to
-+  interact with the Fabric Port to join multiple fabrics. The port will
-+  obtain an N_Port_ID on each fabric it joins. Each fabric will have its
-+  own unique view of endpoints and configuration parameters.  NPIV may be
-+  used together with VF so that the port can obtain multiple N_Port_IDs
-+  on each virtual fabric.
-+
-+  The FC transport is now recognizing a new object - a vport.  A vport is
-+  an entity that has a world-wide unique World Wide Port Name (wwpn) and
-+  World Wide Node Name (wwnn). The transport also allows for the FC4's to
-+  be specified for the vport, with FCP_Initiator being the primary role
-+  expected. Once instantiated by one of the above methods, it will have a
-+  distinct N_Port_ID and view of fabric endpoints and storage entities.
-+  The fc_host associated with the physical adapter will export the ability
-+  to create vports. The transport will create the vport object within the
-+  Linux device tree, and instruct the fc_host's driver to instantiate the
-+  virtual port. Typically, the driver will create a new scsi_host instance
-+  on the vport, resulting in a unique <H,C,T,L> namespace for the vport.
-+  Thus, whether a FC port is based on a physical port or on a virtual port,
-+  each will appear as a unique scsi_host with its own target and lun space.
-+
-+  Note: At this time, the transport is written to create only NPIV-based
-+    vports. However, consideration was given to VF-based vports and it
-+    should be a minor change to add support if needed.  The remaining
-+    discussion will concentrate on NPIV.
-+
-+  Note: World Wide Name assignment (and uniqueness guarantees) are left
-+    up to an administrative entity controling the vport. For example,
-+    if vports are to be associated with virtual machines, a XEN mgmt
-+    utility would be responsible for creating wwpn/wwnn's for the vport,
-+    using it's own naming authority and OUI. (Note: it already does this
-+    for virtual MAC addresses).
-+
-+
-+Device Trees and Vport Objects:
-+-------------------------------
-+
-+  Today, the device tree typically contains the scsi_host object,
-+  with rports and scsi target objects underneath it. Currently the FC
-+  transport creates the vport object and places it under the scsi_host
-+  object corresponding to the physical adapter.  The LLDD will allocate
-+  a new scsi_host for the vport and link it's object under the vport.
-+  The remainder of the tree under the vports scsi_host is the same
-+  as the non-NPIV case. The transport is written currently to easily
-+  allow the parent of the vport to be something other than the scsi_host.
-+  This could be used in the future to link the object onto a vm-specific
-+  device tree. If the vport's parent is not the physical port's scsi_host,
-+  a symbolic link to the vport object will be placed in the physical
-+  port's scsi_host.
-+
-+  Here's what to expect in the device tree :
-+   The typical Physical Port's Scsi_Host:
-+     /sys/devices/.../host17/
-+   and it has the typical decendent tree:
-+     /sys/devices/.../host17/rport-17:0-0/target17:0:0/17:0:0:0:
-+   and then the vport is created on the Physical Port:
-+     /sys/devices/.../host17/vport-17:0-0
-+   and the vport's Scsi_Host is then created:
-+     /sys/devices/.../host17/vport-17:0-0/host18
-+   and then the rest of the tree progresses, such as:
-+     /sys/devices/.../host17/vport-17:0-0/host18/rport-18:0-0/target18:0:0/18:0:0:0:
-+
-+  Here's what to expect in the sysfs tree :
-+   scsi_hosts:
-+     /sys/class/scsi_host/host17                physical port's scsi_host
-+     /sys/class/scsi_host/host18                vport's scsi_host
-+   fc_hosts:
-+     /sys/class/fc_host/host17                  physical port's fc_host
-+     /sys/class/fc_host/host18                  vport's fc_host
-+   fc_vports:
-+     /sys/class/fc_vports/vport-17:0-0          the vport's fc_vport
-+   fc_rports:
-+     /sys/class/fc_remote_ports/rport-17:0-0    rport on the physical port
-+     /sys/class/fc_remote_ports/rport-18:0-0    rport on the vport
-+
-+
-+Vport Attributes:
-+-------------------------------
-+
-+  The new fc_vport class object has the following attributes
-+
-+     node_name:                                                 Read_Only
-+       The WWNN of the vport
-+
-+     port_name:                                                 Read_Only
-+       The WWPN of the vport
-+
-+     roles:                                                     Read_Only
-+       Indicates the FC4 roles enabled on the vport.
-+
-+     symbolic_name:                                             Read_Write
-+       A string, appended to the driver's symbolic port name string, which
-+       is registered with the switch to identify the vport. For example,
-+       a hypervisor could set this string to "Xen Domain 2 VM 5 Vport 2",
-+       and this set of identifiers can be seen on switch management screens
-+       to identify the port.
-+
-+     vport_delete:                                              Write_Only
-+       When written with a "1", will tear down the vport.
-+
-+     vport_disable:                                             Write_Only
-+       When written with a "1", will transition the vport to a disabled.
-+       state.  The vport will still be instantiated with the Linux kernel,
-+       but it will not be active on the FC link.
-+       When written with a "0", will enable the vport.
-+
-+     vport_last_state:                                          Read_Only
-+       Indicates the previous state of the vport.  See the section below on
-+       "Vport States".
-+
-+     vport_state:                                               Read_Only
-+       Indicates the state of the vport.  See the section below on
-+       "Vport States".
-+
-+     vport_type:                                                Read_Only
-+       Reflects the FC mechanism used to create the virtual port.
-+       Only NPIV is supported currently.
-+
-+
-+  For the fc_host class object, the following attributes are added for vports:
-+
-+     max_npiv_vports:                                           Read_Only
-+       Indicates the maximum number of NPIV-based vports that the
-+       driver/adapter can support on the fc_host.
-+
-+     npiv_vports_inuse:                                         Read_Only
-+       Indicates how many NPIV-based vports have been instantiated on the
-+       fc_host.
-+
-+     vport_create:                                              Write_Only
-+       A "simple" create interface to instantiate a vport on an fc_host.
-+       A "<WWPN>:<WWNN>" string is written to the attribute. The transport
-+       then instantiates the vport object and calls the LLDD to create the
-+       vport with the role of FCP_Initiator.  Each WWN is specified as 16
-+       hex characters and may *not* contain any prefixes (e.g. 0x, x, etc).
-+
-+     vport_delete:                                              Write_Only
-+        A "simple" delete interface to teardown a vport. A "<WWPN>:<WWNN>"
-+        string is written to the attribute. The transport will locate the
-+        vport on the fc_host with the same WWNs and tear it down.  Each WWN
-+        is specified as 16 hex characters and may *not* contain any prefixes
-+        (e.g. 0x, x, etc).
-+
-+
-+Vport States:
-+-------------------------------
-+
-+  Vport instantiation consists of two parts:
-+    - Creation with the kernel and LLDD. This means all transport and
-+      driver data structures are built up, and device objects created.
-+      This is equivalent to a driver "attach" on an adapter, which is
-+      independent of the adapter's link state.
-+    - Instantiation of the vport on the FC link via ELS traffic, etc.
-+      This is equivalent to a "link up" and successfull link initialization.
-+  Futher information can be found in the interfaces section below for
-+  Vport Creation.
-+
-+  Once a vport has been instantiated with the kernel/LLDD, a vport state
-+  can be reported via the sysfs attribute. The following states exist:
-+
-+    FC_VPORT_UNKNOWN            - Unknown
-+      An temporary state, typically set only while the vport is being
-+      instantiated with the kernel and LLDD.
-+
-+    FC_VPORT_ACTIVE             - Active
-+      The vport has been successfully been created on the FC link.
-+      It is fully functional.
-+
-+    FC_VPORT_DISABLED           - Disabled
-+      The vport instantiated, but "disabled". The vport is not instantiated
-+      on the FC link. This is equivalent to a physical port with the
-+      link "down".
-+
-+    FC_VPORT_LINKDOWN           - Linkdown
-+      The vport is not operational as the physical link is not operational.
-+
-+    FC_VPORT_INITIALIZING       - Initializing
-+      The vport is in the process of instantiating on the FC link.
-+      The LLDD will set this state just prior to starting the ELS traffic
-+      to create the vport. This state will persist until the vport is
-+      successfully created (state becomes FC_VPORT_ACTIVE) or it fails
-+      (state is one of the values below).  As this state is transitory,
-+      it will not be preserved in the "vport_last_state".
-+
-+    FC_VPORT_NO_FABRIC_SUPP     - No Fabric Support
-+      The vport is not operational. One of the following conditions were
-+      encountered:
-+       - The FC topology is not Point-to-Point
-+       - The FC port is not connected to an F_Port
-+       - The F_Port has indicated that NPIV is not supported.
-+
-+    FC_VPORT_NO_FABRIC_RSCS     - No Fabric Resources
-+      The vport is not operational. The Fabric failed FDISC with a status
-+      indicating that it does not have sufficient resources to complete
-+      the operation.
-+
-+    FC_VPORT_FABRIC_LOGOUT      - Fabric Logout
-+      The vport is not operational. The Fabric has LOGO'd the N_Port_ID
-+      associated with the vport.
-+
-+    FC_VPORT_FABRIC_REJ_WWN     - Fabric Rejected WWN
-+      The vport is not operational. The Fabric failed FDISC with a status
-+      indicating that the WWN's are not valid.
-+
-+    FC_VPORT_FAILED             - VPort Failed
-+      The vport is not operational. This is a catchall for all other
-+      error conditions.
-+
-+
-+  The following state table indicates the different state transitions:
-+
-+    State              Event                            New State
-+    --------------------------------------------------------------------
-+     n/a                Initialization                  Unknown
-+    Unknown:            Link Down                       Linkdown
-+                        Link Up & Loop                  No Fabric Support
-+                        Link Up & no Fabric             No Fabric Support
-+                        Link Up & FLOGI response        No Fabric Support
-+                          indicates no NPIV support
-+                        Link Up & FDISC being sent      Initializing
-+                        Disable request                 Disable
-+    Linkdown:           Link Up                         Unknown
-+    Initializing:       FDISC ACC                       Active
-+                        FDISC LS_RJT w/ no resources    No Fabric Resources
-+                        FDISC LS_RJT w/ invalid         Fabric Rejected WWN
-+                          pname or invalid nport_id
-+                        FDISC LS_RJT failed for         Vport Failed
-+                          other reasons
-+                        Link Down                       Linkdown
-+                        Disable request                 Disable
-+    Disable:            Enable request                  Unknown
-+    Active:             LOGO received from fabric       Fabric Logout
-+                        Link Down                       Linkdown
-+                        Disable request                 Disable
-+    Fabric Logout:      Link still up                   Unknown
-+
-+         The following 4 error states all have the same transitions:
-+    No Fabric Support:
-+    No Fabric Resources:
-+    Fabric Rejected WWN:
-+    Vport Failed:
-+                        Disable request                 Disable
-+                        Link goes down                  Linkdown
-+
-+
-+Transport <-> LLDD Interfaces :
-+-------------------------------
-+
-+Vport support by LLDD:
-+
-+  The LLDD indicates support for vports by supplying a vport_create()
-+  function in the transport template.  The presense of this function will
-+  cause the creation of the new attributes on the fc_host.  As part of
-+  the physical port completing its initialization relative to the
-+  transport, it should set the max_npiv_vports attribute to indicate the
-+  maximum number of vports the driver and/or adapter supports.
-+
-+
-+Vport Creation:
-+
-+  The LLDD vport_create() syntax is:
-+
-+      int vport_create(struct fc_vport *vport, bool disable)
-+
-+    where:
-+      vport:    Is the newly allocated vport object
-+      disable:  If "true", the vport is to be created in a disabled stated.
-+                If "false", the vport is to be enabled upon creation.
-+
-+  When a request is made to create a new vport (via sgio/netlink, or the
-+  vport_create fc_host attribute), the transport will validate that the LLDD
-+  can support another vport (e.g. max_npiv_vports > npiv_vports_inuse).
-+  If not, the create request will be failed.  If space remains, the transport
-+  will increment the vport count, create the vport object, and then call the
-+  LLDD's vport_create() function with the newly allocated vport object.
-+
-+  As mentioned above, vport creation is divided into two parts:
-+    - Creation with the kernel and LLDD. This means all transport and
-+      driver data structures are built up, and device objects created.
-+      This is equivalent to a driver "attach" on an adapter, which is
-+      independent of the adapter's link state.
-+    - Instantiation of the vport on the FC link via ELS traffic, etc.
-+      This is equivalent to a "link up" and successfull link initialization.
-+
-+  The LLDD's vport_create() function will not synchronously wait for both
-+  parts to be fully completed before returning. It must validate that the
-+  infrastructure exists to support NPIV, and complete the first part of
-+  vport creation (data structure build up) before returning.  We do not
-+  hinge vport_create() on the link-side operation mainly because:
-+    - The link may be down. It is not a failure if it is. It simply
-+      means the vport is in an inoperable state until the link comes up.
-+      This is consistent with the link bouncing post vport creation.
-+    - The vport may be created in a disabled state.
-+    - This is consistent with a model where:  the vport equates to a
-+      FC adapter. The vport_create is synonymous with driver attachment
-+      to the adapter, which is independent of link state.
-+
-+    Note: special error codes have been defined to delineate infrastructure
-+      failure cases for quicker resolution.
-+
-+  The expected behavior for the LLDD's vport_create() function is:
-+    - Validate Infrastructure:
-+        - If the driver or adapter cannot support another vport, whether
-+            due to improper firmware, (a lie about) max_npiv, or a lack of
-+            some other resource - return VPCERR_UNSUPPORTED.
-+        - If the driver validates the WWN's against those already active on
-+            the adapter and detects an overlap - return VPCERR_BAD_WWN.
-+        - If the driver detects the topology is loop, non-fabric, or the
-+            FLOGI did not support NPIV - return VPCERR_NO_FABRIC_SUPP.
-+    - Allocate data structures. If errors are encountered, such as out
-+        of memory conditions, return the respective negative Exxx error code.
-+    - If the role is FCP Initiator, the LLDD is to :
-+        - Call scsi_host_alloc() to allocate a scsi_host for the vport.
-+        - Call scsi_add_host(new_shost, &vport->dev) to start the scsi_host
-+          and bind it as a child of the vport device.
-+        - Initializes the fc_host attribute values.
-+    - Kick of further vport state transitions based on the disable flag and
-+        link state - and return success (zero).
-+
-+  LLDD Implementers Notes:
-+  - It is suggested that there be a different fc_function_templates for
-+    the physical port and the virtual port.  The physical port's template
-+    would have the vport_create, vport_delete, and vport_disable functions,
-+    while the vports would not.
-+  - It is suggested that there be different scsi_host_templates
-+    for the physical port and virtual port. Likely, there are driver
-+    attributes, embedded into the scsi_host_template, that are applicable
-+    for the physical port only (link speed, topology setting, etc). This
-+    ensures that the attributes are applicable to the respective scsi_host.
-+
-+
-+Vport Disable/Enable:
-+
-+  The LLDD vport_disable() syntax is:
-+
-+      int vport_disable(struct fc_vport *vport, bool disable)
-+
-+    where:
-+      vport:    Is vport to to be enabled or disabled
-+      disable:  If "true", the vport is to be disabled.
-+                If "false", the vport is to be enabled.
-+
-+  When a request is made to change the disabled state on a vport, the
-+  transport will validate the request against the existing vport state.
-+  If the request is to disable and the vport is already disabled, the
-+  request will fail. Similarly, if the request is to enable, and the
-+  vport is not in a disabled state, the request will fail.  If the request
-+  is valid for the vport state, the transport will call the LLDD to
-+  change the vport's state.
-+
-+  Within the LLDD, if a vport is disabled, it remains instantiated with
-+  the kernel and LLDD, but it is not active or visible on the FC link in
-+  any way. (see Vport Creation and the 2 part instantiation discussion).
-+  The vport will remain in this state until it is deleted or re-enabled.
-+  When enabling a vport, the LLDD reinstantiates the vport on the FC
-+  link - essentially restarting the LLDD statemachine (see Vport States
-+  above).
-+
-+
-+Vport Deletion:
-+
-+  The LLDD vport_delete() syntax is:
-+
-+      int vport_delete(struct fc_vport *vport)
-+
-+    where:
-+      vport:    Is vport to delete
-+
-+  When a request is made to delete a vport (via sgio/netlink, or via the
-+  fc_host or fc_vport vport_delete attributes), the transport will call
-+  the LLDD to terminate the vport on the FC link, and teardown all other
-+  datastructures and references.  If the LLDD completes successfully,
-+  the transport will teardown the vport objects and complete the vport
-+  removal.  If the LLDD delete request fails, the vport object will remain,
-+  but will be in an indeterminate state.
-+
-+  Within the LLDD, the normal code paths for a scsi_host teardown should
-+  be followed. E.g. If the vport has a FCP Initiator role, the LLDD
-+  will call fc_remove_host() for the vports scsi_host, followed by
-+  scsi_remove_host() and scsi_host_put() for the vports scsi_host.
-+
-+
-+Other:
-+  fc_host port_type attribute:
-+    There is a new fc_host port_type value - FC_PORTTYPE_NPIV. This value
-+    must be set on all vport-based fc_hosts.  Normally, on a physical port,
-+    the port_type attribute would be set to NPORT, NLPORT, etc based on the
-+    topology type and existence of the fabric. As this is not applicable to
-+    a vport, it makes more sense to report the FC mechanism used to create
-+    the vport.
-+
-+  Driver unload:
-+    FC drivers are required to call fc_remove_host() prior to calling
-+    scsi_remove_host().  This allows the fc_host to tear down all remote
-+    ports prior the scsi_host being torn down.  The fc_remove_host() call
-+    was updated to remove all vports for the fc_host as well.
-+
-+
-+Credits
-+=======
-+The following people have contributed to this document:
-+
-+
-+
-+
-+
-+
-+James Smart
-+james.smart@emulex.com
-+
-diff -Nurb linux-2.6.22-570/Documentation/sysctl/kernel.txt linux-2.6.22-590/Documentation/sysctl/kernel.txt
---- linux-2.6.22-570/Documentation/sysctl/kernel.txt   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/Documentation/sysctl/kernel.txt   2008-01-02 13:56:37.000000000 -0500
-@@ -29,6 +29,7 @@
- - java-interpreter            [ binfmt_java, obsolete ]
- - kstack_depth_to_print       [ X86 only ]
- - l2cr                        [ PPC only ]
-+- mmap_min_addr
- - modprobe                    ==> Documentation/kmod.txt
- - msgmax
- - msgmnb
-@@ -178,6 +179,19 @@
- ==============================================================
-+mmap_min_addr
-+
-+This file indicates the amount of address space  which a user process will be
-+restricted from mmaping.  Since kernel null dereference bugs could
-+accidentally operate based on the information in the first couple of pages of
-+memory userspace processes should not be allowed to write to them.  By default
-+this value is set to 0 and no protections will be enforced by the security
-+module.  Setting this value to something like 64k will allow the vast majority
-+of applications to work correctly and provide defense in depth against future
-+potential kernel bugs.
-+
-+==============================================================
-+
- osrelease, ostype & version:
- # cat osrelease
-diff -Nurb linux-2.6.22-570/Documentation/sysfs-rules.txt linux-2.6.22-590/Documentation/sysfs-rules.txt
---- linux-2.6.22-570/Documentation/sysfs-rules.txt     1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/Documentation/sysfs-rules.txt     2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,166 @@
-+Rules on how to access information in the Linux kernel sysfs
-+
-+The kernel exported sysfs exports internal kernel implementation-details
-+and depends on internal kernel structures and layout. It is agreed upon
-+by the kernel developers that the Linux kernel does not provide a stable
-+internal API. As sysfs is a direct export of kernel internal
-+structures, the sysfs interface can not provide a stable interface eighter,
-+it may always change along with internal kernel changes.
-+
-+To minimize the risk of breaking users of sysfs, which are in most cases
-+low-level userspace applications, with a new kernel release, the users
-+of sysfs must follow some rules to use an as abstract-as-possible way to
-+access this filesystem. The current udev and HAL programs already
-+implement this and users are encouraged to plug, if possible, into the
-+abstractions these programs provide instead of accessing sysfs
-+directly.
-+
-+But if you really do want or need to access sysfs directly, please follow
-+the following rules and then your programs should work with future
-+versions of the sysfs interface.
-+
-+- Do not use libsysfs
-+  It makes assumptions about sysfs which are not true. Its API does not
-+  offer any abstraction, it exposes all the kernel driver-core
-+  implementation details in its own API. Therefore it is not better than
-+  reading directories and opening the files yourself.
-+  Also, it is not actively maintained, in the sense of reflecting the
-+  current kernel-development. The goal of providing a stable interface
-+  to sysfs has failed, it causes more problems, than it solves. It
-+  violates many of the rules in this document.
-+
-+- sysfs is always at /sys
-+  Parsing /proc/mounts is a waste of time. Other mount points are a
-+  system configuration bug you should not try to solve. For test cases,
-+  possibly support a SYSFS_PATH environment variable to overwrite the
-+  applications behavior, but never try to search for sysfs. Never try
-+  to mount it, if you are not an early boot script.
-+
-+- devices are only "devices"
-+  There is no such thing like class-, bus-, physical devices,
-+  interfaces, and such that you can rely on in userspace. Everything is
-+  just simply a "device". Class-, bus-, physical, ... types are just
-+  kernel implementation details, which should not be expected by
-+  applications that look for devices in sysfs.
-+
-+  The properties of a device are:
-+    o devpath (/devices/pci0000:00/0000:00:1d.1/usb2/2-2/2-2:1.0)
-+      - identical to the DEVPATH value in the event sent from the kernel
-+        at device creation and removal
-+      - the unique key to the device at that point in time
-+      - the kernels path to the device-directory without the leading
-+        /sys, and always starting with with a slash
-+      - all elements of a devpath must be real directories. Symlinks
-+        pointing to /sys/devices must always be resolved to their real
-+        target, and the target path must be used to access the device.
-+        That way the devpath to the device matches the devpath of the
-+        kernel used at event time.
-+      - using or exposing symlink values as elements in a devpath string
-+        is a bug in the application
-+
-+    o kernel name (sda, tty, 0000:00:1f.2, ...)
-+      - a directory name, identical to the last element of the devpath
-+      - applications need to handle spaces and characters like '!' in
-+        the name
-+
-+    o subsystem (block, tty, pci, ...)
-+      - simple string, never a path or a link
-+      - retrieved by reading the "subsystem"-link and using only the
-+        last element of the target path
-+
-+    o driver (tg3, ata_piix, uhci_hcd)
-+      - a simple string, which may contain spaces, never a path or a
-+        link
-+      - it is retrieved by reading the "driver"-link and using only the
-+        last element of the target path
-+      - devices which do not have "driver"-link, just do not have a
-+        driver; copying the driver value in a child device context, is a
-+        bug in the application
-+
-+    o attributes
-+      - the files in the device directory or files below a subdirectories
-+        of the same device directory
-+      - accessing attributes reached by a symlink pointing to another device,
-+        like the "device"-link, is a bug in the application
-+
-+  Everything else is just a kernel driver-core implementation detail,
-+  that should not be assumed to be stable across kernel releases.
-+
-+- Properties of parent devices never belong into a child device.
-+  Always look at the parent devices themselves for determining device
-+  context properties. If the device 'eth0' or 'sda' does not have a
-+  "driver"-link, then this device does not have a driver. Its value is empty.
-+  Never copy any property of the parent-device into a child-device. Parent
-+  device-properties may change dynamically without any notice to the
-+  child device.
-+
-+- Hierarchy in a single device-tree
-+  There is only one valid place in sysfs where hierarchy can be examined
-+  and this is below: /sys/devices.
-+  It is planned, that all device directories will end up in the tree
-+  below this directory.
-+
-+- Classification by subsystem
-+  There are currently three places for classification of devices:
-+  /sys/block, /sys/class and /sys/bus. It is planned that these will
-+  not contain any device-directories themselves, but only flat lists of
-+  symlinks pointing to the unified /sys/devices tree.
-+  All three places have completely different rules on how to access
-+  device information. It is planned to merge all three
-+  classification-directories into one place at /sys/subsystem,
-+  following the layout of the bus-directories. All buses and
-+  classes, including the converted block-subsystem, will show up
-+  there.
-+  The devices belonging to a subsystem will create a symlink in the
-+  "devices" directory at /sys/subsystem/<name>/devices.
-+
-+  If /sys/subsystem exists, /sys/bus, /sys/class and /sys/block can be
-+  ignored. If it does not exist, you have always to scan all three
-+  places, as the kernel is free to move a subsystem from one place to
-+  the other, as long as the devices are still reachable by the same
-+  subsystem name.
-+
-+  Assuming /sys/class/<subsystem> and /sys/bus/<subsystem>, or
-+  /sys/block and /sys/class/block are not interchangeable, is a bug in
-+  the application.
-+
-+- Block
-+  The converted block-subsystem at /sys/class/block, or
-+  /sys/subsystem/block will contain the links for disks and partitions
-+  at the same level, never in a hierarchy. Assuming the block-subsytem to
-+  contain only disks and not partition-devices in the same flat list is
-+  a bug in the application.
-+
-+- "device"-link and <subsystem>:<kernel name>-links
-+  Never depend on the "device"-link. The "device"-link is a workaround
-+  for the old layout, where class-devices are not created in
-+  /sys/devices/ like the bus-devices. If the link-resolving of a
-+  device-directory does not end in /sys/devices/, you can use the
-+  "device"-link to find the parent devices in /sys/devices/. That is the
-+  single valid use of the "device"-link, it must never appear in any
-+  path as an element. Assuming the existence of the "device"-link for
-+  a device in /sys/devices/ is a bug in the application.
-+  Accessing /sys/class/net/eth0/device is a bug in the application.
-+
-+  Never depend on the class-specific links back to the /sys/class
-+  directory.  These links are also a workaround for the design mistake
-+  that class-devices are not created in /sys/devices. If a device
-+  directory does not contain directories for child devices, these links
-+  may be used to find the child devices in /sys/class. That is the single
-+  valid use of these links, they must never appear in any path as an
-+  element. Assuming the existence of these links for devices which are
-+  real child device directories in the /sys/devices tree, is a bug in
-+  the application.
-+
-+  It is planned to remove all these links when when all class-device
-+  directories live in /sys/devices.
-+
-+- Position of devices along device chain can change.
-+  Never depend on a specific parent device position in the devpath,
-+  or the chain of parent devices. The kernel is free to insert devices into
-+  the chain. You must always request the parent device you are looking for
-+  by its subsystem value. You need to walk up the chain until you find
-+  the device that matches the expected subsystem. Depending on a specific
-+  position of a parent device, or exposing relative paths, using "../" to
-+  access the chain of parents, is a bug in the application.
-+
-diff -Nurb linux-2.6.22-570/MAINTAINERS linux-2.6.22-590/MAINTAINERS
---- linux-2.6.22-570/MAINTAINERS       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/MAINTAINERS       2008-01-02 13:56:37.000000000 -0500
-@@ -232,15 +232,15 @@
- S:    Supported
- ACPI BATTERY DRIVERS
--P:    Vladimir P. Lebedev
--M:    vladimir.p.lebedev@intel.com
-+P:    Alexey Starikovskiy
-+M:    astarikovskiy@suse.de
- L:    linux-acpi@vger.kernel.org
- W:    http://acpi.sourceforge.net/
- S:    Supported
- ACPI EC DRIVER
- P:    Alexey Starikovskiy
--M:    alexey.y.starikovskiy@linux.intel.com
-+M:    astarikovskiy@suse.de
- L:    linux-acpi@vger.kernel.org
- W:    http://acpi.sourceforge.net/
- S:    Supported
-@@ -2127,6 +2127,15 @@
- L:    kexec@lists.infradead.org
- S:    Maintained
-+KGDB
-+P:    Jason Wessel
-+M:    jason.wessel@windriver.com
-+P:    Amit S. Kale
-+M:    amitkale@linsyssoft.com
-+W:    http://sourceforge.net/projects/kgdb
-+L:    kgdb-bugreport@lists.sourceforge.net
-+S:    Maintained
-+
- KPROBES
- P:    Prasanna S Panchamukhi
- M:    prasanna@in.ibm.com
-@@ -3593,6 +3602,15 @@
- W:    http://www.kernel.dk
- S:    Maintained
-+UNIONFS
-+P:    Erez Zadok
-+M:    ezk@cs.sunysb.edu
-+P:    Josef "Jeff" Sipek
-+M:    jsipek@cs.sunysb.edu
-+L:    unionfs@filesystems.org
-+W:    http://unionfs.filesystems.org
-+S:    Maintained
-+
- USB ACM DRIVER
- P:    Oliver Neukum
- M:    oliver@neukum.name
-diff -Nurb linux-2.6.22-570/Makefile linux-2.6.22-590/Makefile
---- linux-2.6.22-570/Makefile  2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/Makefile  2008-01-02 13:56:40.000000000 -0500
-@@ -1,7 +1,7 @@
- VERSION = 2
- PATCHLEVEL = 6
- SUBLEVEL = 22
--EXTRAVERSION = .14-vs2.3.0.29
-+EXTRAVERSION = -prep
- NAME = Holy Dancing Manatees, Batman!
- # *DOCUMENTATION*
-@@ -496,6 +496,11 @@
- CFLAGS                += -fomit-frame-pointer
- endif
-+ifdef CONFIG_UNWIND_INFO
-+CFLAGS                += -fasynchronous-unwind-tables
-+LDFLAGS_vmlinux       += --eh-frame-hdr
-+endif
-+
- ifdef CONFIG_DEBUG_INFO
- CFLAGS                += -g
- endif
-diff -Nurb linux-2.6.22-570/Makefile.orig linux-2.6.22-590/Makefile.orig
---- linux-2.6.22-570/Makefile.orig     2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/Makefile.orig     1969-12-31 19:00:00.000000000 -0500
-@@ -1,1493 +0,0 @@
--VERSION = 2
--PATCHLEVEL = 6
--SUBLEVEL = 22
--EXTRAVERSION = .14
--NAME = Holy Dancing Manatees, Batman!
--
--# *DOCUMENTATION*
--# To see a list of typical targets execute "make help"
--# More info can be located in ./README
--# Comments in this file are targeted only to the developer, do not
--# expect to learn how to build the kernel reading this file.
--
--# Do not:
--# o  use make's built-in rules and variables
--#    (this increases performance and avoid hard-to-debug behavour);
--# o  print "Entering directory ...";
--MAKEFLAGS += -rR --no-print-directory
--
--# We are using a recursive build, so we need to do a little thinking
--# to get the ordering right.
--#
--# Most importantly: sub-Makefiles should only ever modify files in
--# their own directory. If in some directory we have a dependency on
--# a file in another dir (which doesn't happen often, but it's often
--# unavoidable when linking the built-in.o targets which finally
--# turn into vmlinux), we will call a sub make in that other dir, and
--# after that we are sure that everything which is in that other dir
--# is now up to date.
--#
--# The only cases where we need to modify files which have global
--# effects are thus separated out and done before the recursive
--# descending is started. They are now explicitly listed as the
--# prepare rule.
--
--# To put more focus on warnings, be less verbose as default
--# Use 'make V=1' to see the full commands
--
--ifdef V
--  ifeq ("$(origin V)", "command line")
--    KBUILD_VERBOSE = $(V)
--  endif
--endif
--ifndef KBUILD_VERBOSE
--  KBUILD_VERBOSE = 0
--endif
--
--# Call a source code checker (by default, "sparse") as part of the
--# C compilation.
--#
--# Use 'make C=1' to enable checking of only re-compiled files.
--# Use 'make C=2' to enable checking of *all* source files, regardless
--# of whether they are re-compiled or not.
--#
--# See the file "Documentation/sparse.txt" for more details, including
--# where to get the "sparse" utility.
--
--ifdef C
--  ifeq ("$(origin C)", "command line")
--    KBUILD_CHECKSRC = $(C)
--  endif
--endif
--ifndef KBUILD_CHECKSRC
--  KBUILD_CHECKSRC = 0
--endif
--
--# Use make M=dir to specify directory of external module to build
--# Old syntax make ... SUBDIRS=$PWD is still supported
--# Setting the environment variable KBUILD_EXTMOD take precedence
--ifdef SUBDIRS
--  KBUILD_EXTMOD ?= $(SUBDIRS)
--endif
--ifdef M
--  ifeq ("$(origin M)", "command line")
--    KBUILD_EXTMOD := $(M)
--  endif
--endif
--
--
--# kbuild supports saving output files in a separate directory.
--# To locate output files in a separate directory two syntaxes are supported.
--# In both cases the working directory must be the root of the kernel src.
--# 1) O=
--# Use "make O=dir/to/store/output/files/"
--#
--# 2) Set KBUILD_OUTPUT
--# Set the environment variable KBUILD_OUTPUT to point to the directory
--# where the output files shall be placed.
--# export KBUILD_OUTPUT=dir/to/store/output/files/
--# make
--#
--# The O= assignment takes precedence over the KBUILD_OUTPUT environment
--# variable.
--
--
--# KBUILD_SRC is set on invocation of make in OBJ directory
--# KBUILD_SRC is not intended to be used by the regular user (for now)
--ifeq ($(KBUILD_SRC),)
--
--# OK, Make called in directory where kernel src resides
--# Do we want to locate output files in a separate directory?
--ifdef O
--  ifeq ("$(origin O)", "command line")
--    KBUILD_OUTPUT := $(O)
--  endif
--endif
--
--# That's our default target when none is given on the command line
--PHONY := _all
--_all:
--
--ifneq ($(KBUILD_OUTPUT),)
--# Invoke a second make in the output directory, passing relevant variables
--# check that the output directory actually exists
--saved-output := $(KBUILD_OUTPUT)
--KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
--$(if $(KBUILD_OUTPUT),, \
--     $(error output directory "$(saved-output)" does not exist))
--
--PHONY += $(MAKECMDGOALS)
--
--$(filter-out _all,$(MAKECMDGOALS)) _all:
--      $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
--      KBUILD_SRC=$(CURDIR) \
--      KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@
--
--# Leave processing to above invocation of make
--skip-makefile := 1
--endif # ifneq ($(KBUILD_OUTPUT),)
--endif # ifeq ($(KBUILD_SRC),)
--
--# We process the rest of the Makefile if this is the final invocation of make
--ifeq ($(skip-makefile),)
--
--# If building an external module we do not care about the all: rule
--# but instead _all depend on modules
--PHONY += all
--ifeq ($(KBUILD_EXTMOD),)
--_all: all
--else
--_all: modules
--endif
--
--srctree               := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))
--TOPDIR                := $(srctree)
--# FIXME - TOPDIR is obsolete, use srctree/objtree
--objtree               := $(CURDIR)
--src           := $(srctree)
--obj           := $(objtree)
--
--VPATH         := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
--
--export srctree objtree VPATH TOPDIR
--
--
--# SUBARCH tells the usermode build what the underlying arch is.  That is set
--# first, and if a usermode build is happening, the "ARCH=um" on the command
--# line overrides the setting of ARCH below.  If a native build is happening,
--# then ARCH is assigned, getting whatever value it gets normally, and 
--# SUBARCH is subsequently ignored.
--
--SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
--                                -e s/arm.*/arm/ -e s/sa110/arm/ \
--                                -e s/s390x/s390/ -e s/parisc64/parisc/ \
--                                -e s/ppc.*/powerpc/ -e s/mips.*/mips/ )
--
--# Cross compiling and selecting different set of gcc/bin-utils
--# ---------------------------------------------------------------------------
--#
--# When performing cross compilation for other architectures ARCH shall be set
--# to the target architecture. (See arch/* for the possibilities).
--# ARCH can be set during invocation of make:
--# make ARCH=ia64
--# Another way is to have ARCH set in the environment.
--# The default ARCH is the host where make is executed.
--
--# CROSS_COMPILE specify the prefix used for all executables used
--# during compilation. Only gcc and related bin-utils executables
--# are prefixed with $(CROSS_COMPILE).
--# CROSS_COMPILE can be set on the command line
--# make CROSS_COMPILE=ia64-linux-
--# Alternatively CROSS_COMPILE can be set in the environment.
--# Default value for CROSS_COMPILE is not to prefix executables
--# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
--
--ARCH          ?= $(SUBARCH)
--CROSS_COMPILE ?=
--
--# Architecture as present in compile.h
--UTS_MACHINE := $(ARCH)
--
--KCONFIG_CONFIG        ?= .config
--
--# SHELL used by kbuild
--CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
--        else if [ -x /bin/bash ]; then echo /bin/bash; \
--        else echo sh; fi ; fi)
--
--HOSTCC       = gcc
--HOSTCXX      = g++
--HOSTCFLAGS   = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
--HOSTCXXFLAGS = -O2
--
--# Decide whether to build built-in, modular, or both.
--# Normally, just do built-in.
--
--KBUILD_MODULES :=
--KBUILD_BUILTIN := 1
--
--#     If we have only "make modules", don't compile built-in objects.
--#     When we're building modules with modversions, we need to consider
--#     the built-in objects during the descend as well, in order to
--#     make sure the checksums are up to date before we record them.
--
--ifeq ($(MAKECMDGOALS),modules)
--  KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
--endif
--
--#     If we have "make <whatever> modules", compile modules
--#     in addition to whatever we do anyway.
--#     Just "make" or "make all" shall build modules as well
--
--ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
--  KBUILD_MODULES := 1
--endif
--
--ifeq ($(MAKECMDGOALS),)
--  KBUILD_MODULES := 1
--endif
--
--export KBUILD_MODULES KBUILD_BUILTIN
--export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
--
--# Beautify output
--# ---------------------------------------------------------------------------
--#
--# Normally, we echo the whole command before executing it. By making
--# that echo $($(quiet)$(cmd)), we now have the possibility to set
--# $(quiet) to choose other forms of output instead, e.g.
--#
--#         quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
--#         cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<
--#
--# If $(quiet) is empty, the whole command will be printed.
--# If it is set to "quiet_", only the short version will be printed. 
--# If it is set to "silent_", nothing will be printed at all, since
--# the variable $(silent_cmd_cc_o_c) doesn't exist.
--#
--# A simple variant is to prefix commands with $(Q) - that's useful
--# for commands that shall be hidden in non-verbose mode.
--#
--#     $(Q)ln $@ :<
--#
--# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
--# If KBUILD_VERBOSE equals 1 then the above command is displayed.
--
--ifeq ($(KBUILD_VERBOSE),1)
--  quiet =
--  Q =
--else
--  quiet=quiet_
--  Q = @
--endif
--
--# If the user is running make -s (silent mode), suppress echoing of
--# commands
--
--ifneq ($(findstring s,$(MAKEFLAGS)),)
--  quiet=silent_
--endif
--
--export quiet Q KBUILD_VERBOSE
--
--
--# Look for make include files relative to root of kernel src
--MAKEFLAGS += --include-dir=$(srctree)
--
--# We need some generic definitions.
--include $(srctree)/scripts/Kbuild.include
--
--# Make variables (CC, etc...)
--
--AS            = $(CROSS_COMPILE)as
--LD            = $(CROSS_COMPILE)ld
--CC            = $(CROSS_COMPILE)gcc
--CPP           = $(CC) -E
--AR            = $(CROSS_COMPILE)ar
--NM            = $(CROSS_COMPILE)nm
--STRIP         = $(CROSS_COMPILE)strip
--OBJCOPY               = $(CROSS_COMPILE)objcopy
--OBJDUMP               = $(CROSS_COMPILE)objdump
--AWK           = awk
--GENKSYMS      = scripts/genksyms/genksyms
--DEPMOD                = /sbin/depmod
--KALLSYMS      = scripts/kallsyms
--PERL          = perl
--CHECK         = sparse
--
--CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise $(CF)
--MODFLAGS      = -DMODULE
--CFLAGS_MODULE   = $(MODFLAGS)
--AFLAGS_MODULE   = $(MODFLAGS)
--LDFLAGS_MODULE  = -r
--CFLAGS_KERNEL =
--AFLAGS_KERNEL =
--
--
--# Use LINUXINCLUDE when you must reference the include/ directory.
--# Needed to be compatible with the O= option
--LINUXINCLUDE    := -Iinclude \
--                   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
--                 -include include/linux/autoconf.h
--
--CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
--
--CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
--                   -fno-strict-aliasing -fno-common
--AFLAGS          := -D__ASSEMBLY__
--
--# Read KERNELRELEASE from include/config/kernel.release (if it exists)
--KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
--KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
--
--export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
--export ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
--export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
--export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
--
--export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
--export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
--export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
--
--# When compiling out-of-tree modules, put MODVERDIR in the module
--# tree rather than in the kernel tree. The kernel tree might
--# even be read-only.
--export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
--
--# Files to ignore in find ... statements
--
--RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git \) -prune -o
--export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg --exclude .git
--
--# ===========================================================================
--# Rules shared between *config targets and build targets
--
--# Basic helpers built in scripts/
--PHONY += scripts_basic
--scripts_basic:
--      $(Q)$(MAKE) $(build)=scripts/basic
--
--# To avoid any implicit rule to kick in, define an empty command.
--scripts/basic/%: scripts_basic ;
--
--PHONY += outputmakefile
--# outputmakefile generates a Makefile in the output directory, if using a
--# separate output directory. This allows convenient use of make in the
--# output directory.
--outputmakefile:
--ifneq ($(KBUILD_SRC),)
--      $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
--          $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
--endif
--
--# To make sure we do not include .config for any of the *config targets
--# catch them early, and hand them over to scripts/kconfig/Makefile
--# It is allowed to specify more targets when calling make, including
--# mixing *config targets and build targets.
--# For example 'make oldconfig all'.
--# Detect when mixed targets is specified, and make a second invocation
--# of make so .config is not included in this case either (for *config).
--
--no-dot-config-targets := clean mrproper distclean \
--                       cscope TAGS tags help %docs check% \
--                       include/linux/version.h headers_% \
--                       kernelrelease kernelversion
--
--config-targets := 0
--mixed-targets  := 0
--dot-config     := 1
--
--ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
--      ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
--              dot-config := 0
--      endif
--endif
--
--ifeq ($(KBUILD_EXTMOD),)
--        ifneq ($(filter config %config,$(MAKECMDGOALS)),)
--                config-targets := 1
--                ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)
--                        mixed-targets := 1
--                endif
--        endif
--endif
--
--ifeq ($(mixed-targets),1)
--# ===========================================================================
--# We're called with mixed targets (*config and build targets).
--# Handle them one by one.
--
--%:: FORCE
--      $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@
--
--else
--ifeq ($(config-targets),1)
--# ===========================================================================
--# *config targets only - make sure prerequisites are updated, and descend
--# in scripts/kconfig to make the *config target
--
--# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
--# KBUILD_DEFCONFIG may point out an alternative default configuration
--# used for 'make defconfig'
--include $(srctree)/arch/$(ARCH)/Makefile
--export KBUILD_DEFCONFIG
--
--config %config: scripts_basic outputmakefile FORCE
--      $(Q)mkdir -p include/linux include/config
--      $(Q)$(MAKE) $(build)=scripts/kconfig $@
--
--else
--# ===========================================================================
--# Build targets only - this includes vmlinux, arch specific targets, clean
--# targets and others. In general all targets except *config targets.
--
--ifeq ($(KBUILD_EXTMOD),)
--# Additional helpers built in scripts/
--# Carefully list dependencies so we do not try to build scripts twice
--# in parallel
--PHONY += scripts
--scripts: scripts_basic include/config/auto.conf
--      $(Q)$(MAKE) $(build)=$(@)
--
--# Objects we will link into vmlinux / subdirs we need to visit
--init-y                := init/
--drivers-y     := drivers/ sound/
--net-y         := net/
--libs-y                := lib/
--core-y                := usr/
--endif # KBUILD_EXTMOD
--
--ifeq ($(dot-config),1)
--# Read in config
---include include/config/auto.conf
--
--ifeq ($(KBUILD_EXTMOD),)
--# Read in dependencies to all Kconfig* files, make sure to run
--# oldconfig if changes are detected.
---include include/config/auto.conf.cmd
--
--# To avoid any implicit rule to kick in, define an empty command
--$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
--
--# If .config is newer than include/config/auto.conf, someone tinkered
--# with it and forgot to run make oldconfig.
--# if auto.conf.cmd is missing then we are probably in a cleaned tree so
--# we execute the config step to be sure to catch updated Kconfig files
--include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
--      $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
--else
--# external modules needs include/linux/autoconf.h and include/config/auto.conf
--# but do not care if they are up-to-date. Use auto.conf to trigger the test
--PHONY += include/config/auto.conf
--
--include/config/auto.conf:
--      $(Q)test -e include/linux/autoconf.h -a -e $@ || (              \
--      echo;                                                           \
--      echo "  ERROR: Kernel configuration is invalid.";               \
--      echo "         include/linux/autoconf.h or $@ are missing.";    \
--      echo "         Run 'make oldconfig && make prepare' on kernel src to fix it.";  \
--      echo;                                                           \
--      /bin/false)
--
--endif # KBUILD_EXTMOD
--
--else
--# Dummy target needed, because used as prerequisite
--include/config/auto.conf: ;
--endif # $(dot-config)
--
--# The all: target is the default when no target is given on the
--# command line.
--# This allow a user to issue only 'make' to build a kernel including modules
--# Defaults vmlinux but it is usually overridden in the arch makefile
--all: vmlinux
--
--ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
--CFLAGS                += -Os
--else
--CFLAGS                += -O2
--endif
--
--include $(srctree)/arch/$(ARCH)/Makefile
--
--ifdef CONFIG_FRAME_POINTER
--CFLAGS                += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
--else
--CFLAGS                += -fomit-frame-pointer
--endif
--
--ifdef CONFIG_DEBUG_INFO
--CFLAGS                += -g
--endif
--
--# Force gcc to behave correct even for buggy distributions
--CFLAGS          += $(call cc-option, -fno-stack-protector)
--
--# arch Makefile may override CC so keep this after arch Makefile is included
--NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
--CHECKFLAGS     += $(NOSTDINC_FLAGS)
--
--# warn about C99 declaration after statement
--CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
--
--# disable pointer signed / unsigned warnings in gcc 4.0
--CFLAGS += $(call cc-option,-Wno-pointer-sign,)
--
--# Default kernel image to build when no specific target is given.
--# KBUILD_IMAGE may be overruled on the command line or
--# set in the environment
--# Also any assignments in arch/$(ARCH)/Makefile take precedence over
--# this default value
--export KBUILD_IMAGE ?= vmlinux
--
--#
--# INSTALL_PATH specifies where to place the updated kernel and system map
--# images. Default is /boot, but you can set it to other values
--export        INSTALL_PATH ?= /boot
--
--#
--# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
--# relocations required by build roots.  This is not defined in the
--# makefile but the argument can be passed to make if needed.
--#
--
--MODLIB        = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
--export MODLIB
--
--#
--#  INSTALL_MOD_STRIP, if defined, will cause modules to be
--#  stripped after they are installed.  If INSTALL_MOD_STRIP is '1', then
--#  the default option --strip-debug will be used.  Otherwise,
--#  INSTALL_MOD_STRIP will used as the options to the strip command.
--
--ifdef INSTALL_MOD_STRIP
--ifeq ($(INSTALL_MOD_STRIP),1)
--mod_strip_cmd = $(STRIP) --strip-debug
--else
--mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
--endif # INSTALL_MOD_STRIP=1
--else
--mod_strip_cmd = true
--endif # INSTALL_MOD_STRIP
--export mod_strip_cmd
--
--
--ifeq ($(KBUILD_EXTMOD),)
--core-y                += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
--
--vmlinux-dirs  := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
--                   $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
--                   $(net-y) $(net-m) $(libs-y) $(libs-m)))
--
--vmlinux-alldirs       := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
--                   $(init-n) $(init-) \
--                   $(core-n) $(core-) $(drivers-n) $(drivers-) \
--                   $(net-n)  $(net-)  $(libs-n)    $(libs-))))
--
--init-y                := $(patsubst %/, %/built-in.o, $(init-y))
--core-y                := $(patsubst %/, %/built-in.o, $(core-y))
--drivers-y     := $(patsubst %/, %/built-in.o, $(drivers-y))
--net-y         := $(patsubst %/, %/built-in.o, $(net-y))
--libs-y1               := $(patsubst %/, %/lib.a, $(libs-y))
--libs-y2               := $(patsubst %/, %/built-in.o, $(libs-y))
--libs-y                := $(libs-y1) $(libs-y2)
--
--# Build vmlinux
--# ---------------------------------------------------------------------------
--# vmlinux is built from the objects selected by $(vmlinux-init) and
--# $(vmlinux-main). Most are built-in.o files from top-level directories
--# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
--# Ordering when linking is important, and $(vmlinux-init) must be first.
--#
--# vmlinux
--#   ^
--#   |
--#   +-< $(vmlinux-init)
--#   |   +--< init/version.o + more
--#   |
--#   +--< $(vmlinux-main)
--#   |    +--< driver/built-in.o mm/built-in.o + more
--#   |
--#   +-< kallsyms.o (see description in CONFIG_KALLSYMS section)
--#
--# vmlinux version (uname -v) cannot be updated during normal
--# descending-into-subdirs phase since we do not yet know if we need to
--# update vmlinux.
--# Therefore this step is delayed until just before final link of vmlinux -
--# except in the kallsyms case where it is done just before adding the
--# symbols to the kernel.
--#
--# System.map is generated to document addresses of all kernel symbols
--
--vmlinux-init := $(head-y) $(init-y)
--vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
--vmlinux-all  := $(vmlinux-init) $(vmlinux-main)
--vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds
--export KBUILD_VMLINUX_OBJS := $(vmlinux-all)
--
--# Rule to link vmlinux - also used during CONFIG_KALLSYMS
--# May be overridden by arch/$(ARCH)/Makefile
--quiet_cmd_vmlinux__ ?= LD      $@
--      cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
--      -T $(vmlinux-lds) $(vmlinux-init)                          \
--      --start-group $(vmlinux-main) --end-group                  \
--      $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
--
--# Generate new vmlinux version
--quiet_cmd_vmlinux_version = GEN     .version
--      cmd_vmlinux_version = set -e;                     \
--      if [ ! -r .version ]; then                      \
--        rm -f .version;                               \
--        echo 1 >.version;                             \
--      else                                            \
--        mv .version .old_version;                     \
--        expr 0$$(cat .old_version) + 1 >.version;     \
--      fi;                                             \
--      $(MAKE) $(build)=init
--
--# Generate System.map
--quiet_cmd_sysmap = SYSMAP
--      cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
--
--# Link of vmlinux
--# If CONFIG_KALLSYMS is set .version is already updated
--# Generate System.map and verify that the content is consistent
--# Use + in front of the vmlinux_version rule to silent warning with make -j2
--# First command is ':' to allow us to use + in front of the rule
--define rule_vmlinux__
--      :
--      $(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
--
--      $(call cmd,vmlinux__)
--      $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
--
--      $(Q)$(if $($(quiet)cmd_sysmap),                                      \
--        echo '  $($(quiet)cmd_sysmap)  System.map' &&)                     \
--      $(cmd_sysmap) $@ System.map;                                         \
--      if [ $$? -ne 0 ]; then                                               \
--              rm -f $@;                                                    \
--              /bin/false;                                                  \
--      fi;
--      $(verify_kallsyms)
--endef
--
--
--ifdef CONFIG_KALLSYMS
--# Generate section listing all symbols and add it into vmlinux $(kallsyms.o)
--# It's a three stage process:
--# o .tmp_vmlinux1 has all symbols and sections, but __kallsyms is
--#   empty
--#   Running kallsyms on that gives us .tmp_kallsyms1.o with
--#   the right size - vmlinux version (uname -v) is updated during this step
--# o .tmp_vmlinux2 now has a __kallsyms section of the right size,
--#   but due to the added section, some addresses have shifted.
--#   From here, we generate a correct .tmp_kallsyms2.o
--# o The correct .tmp_kallsyms2.o is linked into the final vmlinux.
--# o Verify that the System.map from vmlinux matches the map from
--#   .tmp_vmlinux2, just in case we did not generate kallsyms correctly.
--# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using
--#   .tmp_vmlinux3 and .tmp_kallsyms3.o.  This is only meant as a
--#   temporary bypass to allow the kernel to be built while the
--#   maintainers work out what went wrong with kallsyms.
--
--ifdef CONFIG_KALLSYMS_EXTRA_PASS
--last_kallsyms := 3
--else
--last_kallsyms := 2
--endif
--
--kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
--
--define verify_kallsyms
--      $(Q)$(if $($(quiet)cmd_sysmap),                                      \
--        echo '  $($(quiet)cmd_sysmap)  .tmp_System.map' &&)                \
--        $(cmd_sysmap) .tmp_vmlinux$(last_kallsyms) .tmp_System.map
--      $(Q)cmp -s System.map .tmp_System.map ||                             \
--              (echo Inconsistent kallsyms data;                            \
--               echo Try setting CONFIG_KALLSYMS_EXTRA_PASS;                \
--               rm .tmp_kallsyms* ; /bin/false )
--endef
--
--# Update vmlinux version before link
--# Use + in front of this rule to silent warning about make -j1
--# First command is ':' to allow us to use + in front of this rule
--cmd_ksym_ld = $(cmd_vmlinux__)
--define rule_ksym_ld
--      : 
--      +$(call cmd,vmlinux_version)
--      $(call cmd,vmlinux__)
--      $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
--endef
--
--# Generate .S file with all kernel symbols
--quiet_cmd_kallsyms = KSYM    $@
--      cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \
--                     $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
--
--.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
--      $(call if_changed_dep,as_o_S)
--
--.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS)
--      $(call cmd,kallsyms)
--
--# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version
--.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
--      $(call if_changed_rule,ksym_ld)
--
--.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
--      $(call if_changed,vmlinux__)
--
--.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE
--      $(call if_changed,vmlinux__)
--
--# Needs to visit scripts/ before $(KALLSYMS) can be used.
--$(KALLSYMS): scripts ;
--
--# Generate some data for debugging strange kallsyms problems
--debug_kallsyms: .tmp_map$(last_kallsyms)
--
--.tmp_map%: .tmp_vmlinux% FORCE
--      ($(OBJDUMP) -h $< | $(AWK) '/^ +[0-9]/{print $$4 " 0 " $$2}'; $(NM) $<) | sort > $@
--
--.tmp_map3: .tmp_map2
--
--.tmp_map2: .tmp_map1
--
--endif # ifdef CONFIG_KALLSYMS
--
--# vmlinux image - including updated kernel symbols
--vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
--ifdef CONFIG_HEADERS_CHECK
--      $(Q)$(MAKE) -f $(srctree)/Makefile headers_check
--endif
--      $(call if_changed_rule,vmlinux__)
--      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
--      $(Q)rm -f .old_version
--
--# The actual objects are generated when descending, 
--# make sure no implicit rule kicks in
--$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
--
--# Handle descending into subdirectories listed in $(vmlinux-dirs)
--# Preset locale variables to speed up the build process. Limit locale
--# tweaks to this spot to avoid wrong language settings when running
--# make menuconfig etc.
--# Error messages still appears in the original language
--
--PHONY += $(vmlinux-dirs)
--$(vmlinux-dirs): prepare scripts
--      $(Q)$(MAKE) $(build)=$@
--
--# Build the kernel release string
--#
--# The KERNELRELEASE value built here is stored in the file
--# include/config/kernel.release, and is used when executing several
--# make targets, such as "make install" or "make modules_install."
--#
--# The eventual kernel release string consists of the following fields,
--# shown in a hierarchical format to show how smaller parts are concatenated
--# to form the larger and final value, with values coming from places like
--# the Makefile, kernel config options, make command line options and/or
--# SCM tag information.
--#
--#     $(KERNELVERSION)
--#       $(VERSION)                    eg, 2
--#       $(PATCHLEVEL)                 eg, 6
--#       $(SUBLEVEL)                   eg, 18
--#       $(EXTRAVERSION)               eg, -rc6
--#     $(localver-full)
--#       $(localver)
--#         localversion*               (files without backups, containing '~')
--#         $(CONFIG_LOCALVERSION)      (from kernel config setting)
--#       $(localver-auto)              (only if CONFIG_LOCALVERSION_AUTO is set)
--#         ./scripts/setlocalversion   (SCM tag, if one exists)
--#         $(LOCALVERSION)             (from make command line if provided)
--#
--#  Note how the final $(localver-auto) string is included *only* if the
--# kernel config option CONFIG_LOCALVERSION_AUTO is selected.  Also, at the
--# moment, only git is supported but other SCMs can edit the script
--# scripts/setlocalversion and add the appropriate checks as needed.
--
--pattern = ".*/localversion[^~]*"
--string  = $(shell cat /dev/null \
--         `find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort -u`)
--
--localver = $(subst $(space),, $(string) \
--                            $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
--
--# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
--# and if the SCM is know a tag from the SCM is appended.
--# The appended tag is determined by the SCM used.
--#
--# Currently, only git is supported.
--# Other SCMs can edit scripts/setlocalversion and add the appropriate
--# checks as needed.
--ifdef CONFIG_LOCALVERSION_AUTO
--      _localver-auto = $(shell $(CONFIG_SHELL) \
--                        $(srctree)/scripts/setlocalversion $(srctree))
--      localver-auto  = $(LOCALVERSION)$(_localver-auto)
--endif
--
--localver-full = $(localver)$(localver-auto)
--
--# Store (new) KERNELRELASE string in include/config/kernel.release
--kernelrelease = $(KERNELVERSION)$(localver-full)
--include/config/kernel.release: include/config/auto.conf FORCE
--      $(Q)rm -f $@
--      $(Q)echo $(kernelrelease) > $@
--
--
--# Things we need to do before we recursively start building the kernel
--# or the modules are listed in "prepare".
--# A multi level approach is used. prepareN is processed before prepareN-1.
--# archprepare is used in arch Makefiles and when processed asm symlink,
--# version.h and scripts_basic is processed / created.
--
--# Listed in dependency order
--PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
--
--# prepare3 is used to check if we are building in a separate output directory,
--# and if so do:
--# 1) Check that make has not been executed in the kernel src $(srctree)
--# 2) Create the include2 directory, used for the second asm symlink
--prepare3: include/config/kernel.release
--ifneq ($(KBUILD_SRC),)
--      @echo '  Using $(srctree) as source for kernel'
--      $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
--              echo "  $(srctree) is not clean, please run 'make mrproper'";\
--              echo "  in the '$(srctree)' directory.";\
--              /bin/false; \
--      fi;
--      $(Q)if [ ! -d include2 ]; then mkdir -p include2; fi;
--      $(Q)ln -fsn $(srctree)/include/asm-$(ARCH) include2/asm
--endif
--
--# prepare2 creates a makefile if using a separate output directory
--prepare2: prepare3 outputmakefile
--
--prepare1: prepare2 include/linux/version.h include/linux/utsrelease.h \
--                   include/asm include/config/auto.conf
--ifneq ($(KBUILD_MODULES),)
--      $(Q)mkdir -p $(MODVERDIR)
--      $(Q)rm -f $(MODVERDIR)/*
--endif
--
--archprepare: prepare1 scripts_basic
--
--prepare0: archprepare FORCE
--      $(Q)$(MAKE) $(build)=.
--      $(Q)$(MAKE) $(build)=. missing-syscalls
--
--# All the preparing..
--prepare: prepare0
--
--# Leave this as default for preprocessing vmlinux.lds.S, which is now
--# done in arch/$(ARCH)/kernel/Makefile
--
--export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
--
--# FIXME: The asm symlink changes when $(ARCH) changes. That's
--# hard to detect, but I suppose "make mrproper" is a good idea
--# before switching between archs anyway.
--
--include/asm:
--      @echo '  SYMLINK $@ -> include/asm-$(ARCH)'
--      $(Q)if [ ! -d include ]; then mkdir -p include; fi;
--      @ln -fsn asm-$(ARCH) $@
--
--# Generate some files
--# ---------------------------------------------------------------------------
--
--# KERNELRELEASE can change from a few different places, meaning version.h
--# needs to be updated, so this check is forced on all builds
--
--uts_len := 64
--define filechk_utsrelease.h
--      if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \
--        echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2;    \
--        exit 1;                                                         \
--      fi;                                                               \
--      (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";)
--endef
--
--define filechk_version.h
--      (echo \#define LINUX_VERSION_CODE $(shell                             \
--      expr $(VERSION) \* 65536 + $(PATCHLEVEL) \* 256 + $(SUBLEVEL));     \
--      echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
--endef
--
--include/linux/version.h: $(srctree)/Makefile FORCE
--      $(call filechk,version.h)
--
--include/linux/utsrelease.h: include/config/kernel.release FORCE
--      $(call filechk,utsrelease.h)
--
--# ---------------------------------------------------------------------------
--
--PHONY += depend dep
--depend dep:
--      @echo '*** Warning: make $@ is unnecessary now.'
--
--# ---------------------------------------------------------------------------
--# Kernel headers
--INSTALL_HDR_PATH=$(objtree)/usr
--export INSTALL_HDR_PATH
--
--HDRARCHES=$(filter-out generic,$(patsubst $(srctree)/include/asm-%/Kbuild,%,$(wildcard $(srctree)/include/asm-*/Kbuild)))
--
--PHONY += headers_install_all
--headers_install_all: include/linux/version.h scripts_basic FORCE
--      $(Q)$(MAKE) $(build)=scripts scripts/unifdef
--      $(Q)for arch in $(HDRARCHES); do \
--       $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch ;\
--       done
--
--PHONY += headers_install
--headers_install: include/linux/version.h scripts_basic FORCE
--      @if [ ! -r $(srctree)/include/asm-$(ARCH)/Kbuild ]; then \
--        echo '*** Error: Headers not exportable for this architecture ($(ARCH))'; \
--        exit 1 ; fi
--      $(Q)$(MAKE) $(build)=scripts scripts/unifdef
--      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst obj=include
--
--PHONY += headers_check_all
--headers_check_all: headers_install_all
--      $(Q)for arch in $(HDRARCHES); do \
--       $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch HDRCHECK=1 ;\
--       done
--
--PHONY += headers_check
--headers_check: headers_install
--      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst obj=include HDRCHECK=1
--
--# ---------------------------------------------------------------------------
--# Modules
--
--ifdef CONFIG_MODULES
--
--# By default, build modules as well
--
--all: modules
--
--#     Build modules
--
--PHONY += modules
--modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
--      @echo '  Building modules, stage 2.';
--      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
--
--
--# Target to prepare building external modules
--PHONY += modules_prepare
--modules_prepare: prepare scripts
--
--# Target to install modules
--PHONY += modules_install
--modules_install: _modinst_ _modinst_post
--
--PHONY += _modinst_
--_modinst_:
--      @if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
--              echo "Warning: you may need to install module-init-tools"; \
--              echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
--              sleep 1; \
--      fi
--      @rm -rf $(MODLIB)/kernel
--      @rm -f $(MODLIB)/source
--      @mkdir -p $(MODLIB)/kernel
--      @ln -s $(srctree) $(MODLIB)/source
--      @if [ ! $(objtree) -ef  $(MODLIB)/build ]; then \
--              rm -f $(MODLIB)/build ; \
--              ln -s $(objtree) $(MODLIB)/build ; \
--      fi
--      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
--
--# If System.map exists, run depmod.  This deliberately does not have a
--# dependency on System.map since that would run the dependency tree on
--# vmlinux.  This depmod is only for convenience to give the initial
--# boot a modules.dep even before / is mounted read-write.  However the
--# boot script depmod is the master version.
--ifeq "$(strip $(INSTALL_MOD_PATH))" ""
--depmod_opts   :=
--else
--depmod_opts   := -b $(INSTALL_MOD_PATH) -r
--endif
--PHONY += _modinst_post
--_modinst_post: _modinst_
--      if [ -r System.map -a -x $(DEPMOD) ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
--
--else # CONFIG_MODULES
--
--# Modules not configured
--# ---------------------------------------------------------------------------
--
--modules modules_install: FORCE
--      @echo
--      @echo "The present kernel configuration has modules disabled."
--      @echo "Type 'make config' and enable loadable module support."
--      @echo "Then build a kernel with module support enabled."
--      @echo
--      @exit 1
--
--endif # CONFIG_MODULES
--
--###
--# Cleaning is done on three levels.
--# make clean     Delete most generated files
--#                Leave enough to build external modules
--# make mrproper  Delete the current configuration, and all generated files
--# make distclean Remove editor backup files, patch leftover files and the like
--
--# Directories & files removed with 'make clean'
--CLEAN_DIRS  += $(MODVERDIR)
--CLEAN_FILES +=        vmlinux System.map \
--                .tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map
--
--# Directories & files removed with 'make mrproper'
--MRPROPER_DIRS  += include/config include2 usr/include
--MRPROPER_FILES += .config .config.old include/asm .version .old_version \
--                  include/linux/autoconf.h include/linux/version.h      \
--                  include/linux/utsrelease.h                            \
--                Module.symvers tags TAGS cscope*
--
--# clean - Delete most, but leave enough to build external modules
--#
--clean: rm-dirs  := $(CLEAN_DIRS)
--clean: rm-files := $(CLEAN_FILES)
--clean-dirs      := $(addprefix _clean_,$(srctree) $(vmlinux-alldirs))
--
--PHONY += $(clean-dirs) clean archclean
--$(clean-dirs):
--      $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
--
--clean: archclean $(clean-dirs)
--      $(call cmd,rmdirs)
--      $(call cmd,rmfiles)
--      @find . $(RCS_FIND_IGNORE) \
--              \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
--              -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
--              -o -name '*.symtypes' \) \
--              -type f -print | xargs rm -f
--
--# mrproper - Delete all generated files, including .config
--#
--mrproper: rm-dirs  := $(wildcard $(MRPROPER_DIRS))
--mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
--mrproper-dirs      := $(addprefix _mrproper_,Documentation/DocBook scripts)
--
--PHONY += $(mrproper-dirs) mrproper archmrproper
--$(mrproper-dirs):
--      $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
--
--mrproper: clean archmrproper $(mrproper-dirs)
--      $(call cmd,rmdirs)
--      $(call cmd,rmfiles)
--
--# distclean
--#
--PHONY += distclean
--
--distclean: mrproper
--      @find $(srctree) $(RCS_FIND_IGNORE) \
--              \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
--              -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
--              -o -name '.*.rej' -o -size 0 \
--              -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
--              -type f -print | xargs rm -f
--
--
--# Packaging of the kernel to various formats
--# ---------------------------------------------------------------------------
--# rpm target kept for backward compatibility
--package-dir   := $(srctree)/scripts/package
--
--%pkg: include/config/kernel.release FORCE
--      $(Q)$(MAKE) $(build)=$(package-dir) $@
--rpm: include/config/kernel.release FORCE
--      $(Q)$(MAKE) $(build)=$(package-dir) $@
--
--
--# Brief documentation of the typical targets used
--# ---------------------------------------------------------------------------
--
--boards := $(wildcard $(srctree)/arch/$(ARCH)/configs/*_defconfig)
--boards := $(notdir $(boards))
--
--help:
--      @echo  'Cleaning targets:'
--      @echo  '  clean           - Remove most generated files but keep the config and'
--      @echo  '                    enough build support to build external modules'
--      @echo  '  mrproper        - Remove all generated files + config + various backup files'
--      @echo  '  distclean       - mrproper + remove editor backup and patch files'
--      @echo  ''
--      @echo  'Configuration targets:'
--      @$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help
--      @echo  ''
--      @echo  'Other generic targets:'
--      @echo  '  all             - Build all targets marked with [*]'
--      @echo  '* vmlinux         - Build the bare kernel'
--      @echo  '* modules         - Build all modules'
--      @echo  '  modules_install - Install all modules to INSTALL_MOD_PATH (default: /)'
--      @echo  '  dir/            - Build all files in dir and below'
--      @echo  '  dir/file.[ois]  - Build specified target only'
--      @echo  '  dir/file.ko     - Build module including final link'
--      @echo  '  rpm             - Build a kernel as an RPM package'
--      @echo  '  tags/TAGS       - Generate tags file for editors'
--      @echo  '  cscope          - Generate cscope index'
--      @echo  '  kernelrelease   - Output the release version string'
--      @echo  '  kernelversion   - Output the version stored in Makefile'
--      @if [ -r $(srctree)/include/asm-$(ARCH)/Kbuild ]; then \
--       echo  '  headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
--       echo  '                    (default: $(INSTALL_HDR_PATH))'; \
--       fi
--      @echo  ''
--      @echo  'Static analysers'
--      @echo  '  checkstack      - Generate a list of stack hogs'
--      @echo  '  namespacecheck  - Name space analysis on compiled kernel'
--      @if [ -r $(srctree)/include/asm-$(ARCH)/Kbuild ]; then \
--       echo  '  headers_check   - Sanity check on exported headers'; \
--       fi
--      @echo  ''
--      @echo  'Kernel packaging:'
--      @$(MAKE) $(build)=$(package-dir) help
--      @echo  ''
--      @echo  'Documentation targets:'
--      @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp
--      @echo  ''
--      @echo  'Architecture specific targets ($(ARCH)):'
--      @$(if $(archhelp),$(archhelp),\
--              echo '  No architecture specific help defined for $(ARCH)')
--      @echo  ''
--      @$(if $(boards), \
--              $(foreach b, $(boards), \
--              printf "  %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \
--              echo '')
--
--      @echo  '  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
--      @echo  '  make V=2   [targets] 2 => give reason for rebuild of target'
--      @echo  '  make O=dir [targets] Locate all output files in "dir", including .config'
--      @echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse by default)'
--      @echo  '  make C=2   [targets] Force check of all c source with $$CHECK'
--      @echo  ''
--      @echo  'Execute "make" or "make all" to build all targets marked with [*] '
--      @echo  'For further info see the ./README file'
--
--
--# Documentation targets
--# ---------------------------------------------------------------------------
--%docs: scripts_basic FORCE
--      $(Q)$(MAKE) $(build)=Documentation/DocBook $@
--
--else # KBUILD_EXTMOD
--
--###
--# External module support.
--# When building external modules the kernel used as basis is considered
--# read-only, and no consistency checks are made and the make
--# system is not used on the basis kernel. If updates are required
--# in the basis kernel ordinary make commands (without M=...) must
--# be used.
--#
--# The following are the only valid targets when building external
--# modules.
--# make M=dir clean     Delete all automatically generated files
--# make M=dir modules   Make all modules in specified dir
--# make M=dir         Same as 'make M=dir modules'
--# make M=dir modules_install
--#                      Install the modules built in the module directory
--#                      Assumes install directory is already created
--
--# We are always building modules
--KBUILD_MODULES := 1
--PHONY += crmodverdir
--crmodverdir:
--      $(Q)mkdir -p $(MODVERDIR)
--      $(Q)rm -f $(MODVERDIR)/*
--
--PHONY += $(objtree)/Module.symvers
--$(objtree)/Module.symvers:
--      @test -e $(objtree)/Module.symvers || ( \
--      echo; \
--      echo "  WARNING: Symbol version dump $(objtree)/Module.symvers"; \
--      echo "           is missing; modules will have no dependencies and modversions."; \
--      echo )
--
--module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
--PHONY += $(module-dirs) modules
--$(module-dirs): crmodverdir $(objtree)/Module.symvers
--      $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@)
--
--modules: $(module-dirs)
--      @echo '  Building modules, stage 2.';
--      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
--
--PHONY += modules_install
--modules_install: _emodinst_ _emodinst_post
--
--install-dir := $(if $(INSTALL_MOD_DIR),$(INSTALL_MOD_DIR),extra)
--PHONY += _emodinst_
--_emodinst_:
--      $(Q)mkdir -p $(MODLIB)/$(install-dir)
--      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
--
--# Run depmod only is we have System.map and depmod is executable
--quiet_cmd_depmod = DEPMOD  $(KERNELRELEASE)
--      cmd_depmod = if [ -r System.map -a -x $(DEPMOD) ]; then \
--                      $(DEPMOD) -ae -F System.map             \
--                      $(if $(strip $(INSTALL_MOD_PATH)),      \
--                    -b $(INSTALL_MOD_PATH) -r)              \
--                    $(KERNELRELEASE);                       \
--                   fi
--
--PHONY += _emodinst_post
--_emodinst_post: _emodinst_
--      $(call cmd,depmod)
--
--clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD))
--
--PHONY += $(clean-dirs) clean
--$(clean-dirs):
--      $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
--
--clean:        rm-dirs := $(MODVERDIR)
--clean: $(clean-dirs)
--      $(call cmd,rmdirs)
--      @find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \
--              \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
--              -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
--              -type f -print | xargs rm -f
--
--help:
--      @echo  '  Building external modules.'
--      @echo  '  Syntax: make -C path/to/kernel/src M=$$PWD target'
--      @echo  ''
--      @echo  '  modules         - default target, build the module(s)'
--      @echo  '  modules_install - install the module'
--      @echo  '  clean           - remove generated files in module directory only'
--      @echo  ''
--
--# Dummies...
--PHONY += prepare scripts
--prepare: ;
--scripts: ;
--endif # KBUILD_EXTMOD
--
--# Generate tags for editors
--# ---------------------------------------------------------------------------
--
--#We want __srctree to totally vanish out when KBUILD_OUTPUT is not set
--#(which is the most common case IMHO) to avoid unneeded clutter in the big tags file.
--#Adding $(srctree) adds about 20M on i386 to the size of the output file!
--
--ifeq ($(src),$(obj))
--__srctree =
--else
--__srctree = $(srctree)/
--endif
--
--ifeq ($(ALLSOURCE_ARCHS),)
--ifeq ($(ARCH),um)
--ALLINCLUDE_ARCHS := $(ARCH) $(SUBARCH)
--else
--ALLINCLUDE_ARCHS := $(ARCH)
--endif
--else
--#Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behavour.
--ALLINCLUDE_ARCHS := $(ALLSOURCE_ARCHS)
--endif
--
--ALLSOURCE_ARCHS := $(ARCH)
--
--define find-sources
--        ( for ARCH in $(ALLSOURCE_ARCHS) ; do \
--             find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
--                  -name $1 -print; \
--        done ; \
--        find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
--             -name $1 -print; \
--        find $(__srctree)include $(RCS_FIND_IGNORE) \
--             \( -name config -o -name 'asm-*' \) -prune \
--             -o -name $1 -print; \
--        for ARCH in $(ALLINCLUDE_ARCHS) ; do \
--             find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
--                  -name $1 -print; \
--        done ; \
--        find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
--             -name $1 -print; \
--        find $(__srctree) $(RCS_FIND_IGNORE) \
--             \( -name include -o -name arch \) -prune -o \
--             -name $1 -print; \
--        )
--endef
--
--define all-sources
--      $(call find-sources,'*.[chS]')
--endef
--define all-kconfigs
--      $(call find-sources,'Kconfig*')
--endef
--define all-defconfigs
--      $(call find-sources,'defconfig')
--endef
--
--define xtags
--      if $1 --version 2>&1 | grep -iq exuberant; then \
--          $(all-sources) | xargs $1 -a \
--              -I __initdata,__exitdata,__acquires,__releases \
--              -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
--              --extra=+f --c-kinds=+px \
--              --regex-asm='/ENTRY\(([^)]*)\).*/\1/'; \
--          $(all-kconfigs) | xargs $1 -a \
--              --langdef=kconfig \
--              --language-force=kconfig \
--              --regex-kconfig='/^[[:blank:]]*config[[:blank:]]+([[:alnum:]_]+)/\1/'; \
--          $(all-defconfigs) | xargs -r $1 -a \
--              --langdef=dotconfig \
--              --language-force=dotconfig \
--              --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/'; \
--      elif $1 --version 2>&1 | grep -iq emacs; then \
--          $(all-sources) | xargs $1 -a; \
--          $(all-kconfigs) | xargs $1 -a \
--              --regex='/^[ \t]*config[ \t]+\([a-zA-Z0-9_]+\)/\1/'; \
--          $(all-defconfigs) | xargs -r $1 -a \
--              --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'; \
--      else \
--          $(all-sources) | xargs $1 -a; \
--      fi
--endef
--
--quiet_cmd_cscope-file = FILELST cscope.files
--      cmd_cscope-file = (echo \-k; echo \-q; $(all-sources)) > cscope.files
--
--quiet_cmd_cscope = MAKE    cscope.out
--      cmd_cscope = cscope -b
--
--cscope: FORCE
--      $(call cmd,cscope-file)
--      $(call cmd,cscope)
--
--quiet_cmd_TAGS = MAKE   $@
--define cmd_TAGS
--      rm -f $@; \
--      $(call xtags,etags)
--endef
--
--TAGS: FORCE
--      $(call cmd,TAGS)
--
--quiet_cmd_tags = MAKE   $@
--define cmd_tags
--      rm -f $@; \
--      $(call xtags,ctags)
--endef
--
--tags: FORCE
--      $(call cmd,tags)
--
--
--# Scripts to check various things for consistency
--# ---------------------------------------------------------------------------
--
--includecheck:
--      find * $(RCS_FIND_IGNORE) \
--              -name '*.[hcS]' -type f -print | sort \
--              | xargs $(PERL) -w scripts/checkincludes.pl
--
--versioncheck:
--      find * $(RCS_FIND_IGNORE) \
--              -name '*.[hcS]' -type f -print | sort \
--              | xargs $(PERL) -w scripts/checkversion.pl
--
--namespacecheck:
--      $(PERL) $(srctree)/scripts/namespace.pl
--
--endif #ifeq ($(config-targets),1)
--endif #ifeq ($(mixed-targets),1)
--
--PHONY += checkstack kernelrelease kernelversion
--
--# UML needs a little special treatment here.  It wants to use the host
--# toolchain, so needs $(SUBARCH) passed to checkstack.pl.  Everyone
--# else wants $(ARCH), including people doing cross-builds, which means
--# that $(SUBARCH) doesn't work here.
--ifeq ($(ARCH), um)
--CHECKSTACK_ARCH := $(SUBARCH)
--else
--CHECKSTACK_ARCH := $(ARCH)
--endif
--checkstack:
--      $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
--      $(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH)
--
--kernelrelease:
--      $(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \
--      $(error kernelrelease not valid - run 'make prepare' to update it))
--kernelversion:
--      @echo $(KERNELVERSION)
--
--# Single targets
--# ---------------------------------------------------------------------------
--# Single targets are compatible with:
--# - build whith mixed source and output
--# - build with separate output dir 'make O=...'
--# - external modules
--#
--#  target-dir => where to store outputfile
--#  build-dir  => directory in kernel source tree to use
--
--ifeq ($(KBUILD_EXTMOD),)
--        build-dir  = $(patsubst %/,%,$(dir $@))
--        target-dir = $(dir $@)
--else
--        zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
--        build-dir  = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
--        target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@))
--endif
--
--%.s: %.c prepare scripts FORCE
--      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
--%.i: %.c prepare scripts FORCE
--      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
--%.o: %.c prepare scripts FORCE
--      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
--%.lst: %.c prepare scripts FORCE
--      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
--%.s: %.S prepare scripts FORCE
--      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
--%.o: %.S prepare scripts FORCE
--      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
--%.symtypes: %.c prepare scripts FORCE
--      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
--
--# Modules
--/ %/: prepare scripts FORCE
--      $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
--      $(build)=$(build-dir)
--%.ko: prepare scripts FORCE
--      $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1)   \
--      $(build)=$(build-dir) $(@:.ko=.o)
--      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
--
--# FIXME Should go into a make.lib or something 
--# ===========================================================================
--
--quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN   $(wildcard $(rm-dirs)))
--      cmd_rmdirs = rm -rf $(rm-dirs)
--
--quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files)))
--      cmd_rmfiles = rm -f $(rm-files)
--
--
--a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(AFLAGS_KERNEL) \
--        $(NOSTDINC_FLAGS) $(CPPFLAGS) \
--        $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o)
--
--quiet_cmd_as_o_S = AS      $@
--cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
--
--# read all saved command lines
--
--targets := $(wildcard $(sort $(targets)))
--cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
--
--ifneq ($(cmd_files),)
--  $(cmd_files): ;     # Do not try to update included dependency files
--  include $(cmd_files)
--endif
--
--# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir
--# Usage:
--# $(Q)$(MAKE) $(clean)=dir
--clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
--
--endif # skip-makefile
--
--PHONY += FORCE
--FORCE:
--
--# Cancel implicit rules on top Makefile, `-rR' will apply to sub-makes.
--Makefile: ;
--
--# Declare the contents of the .PHONY variable as phony.  We keep that
--# information in a variable se we can use it in if_changed and friends.
--.PHONY: $(PHONY)
-diff -Nurb linux-2.6.22-570/arch/arm/Kconfig linux-2.6.22-590/arch/arm/Kconfig
---- linux-2.6.22-570/arch/arm/Kconfig  2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/arm/Kconfig  2008-01-02 13:56:37.000000000 -0500
-@@ -1034,6 +1034,8 @@
- source "drivers/rtc/Kconfig"
-+source "drivers/dma/Kconfig"
-+
- endmenu
- source "fs/Kconfig"
-diff -Nurb linux-2.6.22-570/arch/arm/boot/.gitignore.rej linux-2.6.22-590/arch/arm/boot/.gitignore.rej
---- linux-2.6.22-570/arch/arm/boot/.gitignore.rej      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/arm/boot/.gitignore.rej      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,10 @@
-+***************
-+*** 1,2 ****
-+  Image
-+  zImage
-+--- 1,5 ----
-+  Image
-+  zImage
-++ xipImage
-++ bootpImage
-++ uImage
-diff -Nurb linux-2.6.22-570/arch/arm/kernel/Makefile linux-2.6.22-590/arch/arm/kernel/Makefile
---- linux-2.6.22-570/arch/arm/kernel/Makefile  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/kernel/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -20,6 +20,7 @@
- obj-$(CONFIG_SMP)             += smp.o
- obj-$(CONFIG_KEXEC)           += machine_kexec.o relocate_kernel.o
- obj-$(CONFIG_OABI_COMPAT)     += sys_oabi-compat.o
-+obj-$(CONFIG_KGDB)            += kgdb.o kgdb-jmp.o
- obj-$(CONFIG_CRUNCH)          += crunch.o crunch-bits.o
- AFLAGS_crunch-bits.o          := -Wa,-mcpu=ep9312
-diff -Nurb linux-2.6.22-570/arch/arm/kernel/kgdb-jmp.S linux-2.6.22-590/arch/arm/kernel/kgdb-jmp.S
---- linux-2.6.22-570/arch/arm/kernel/kgdb-jmp.S        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/arm/kernel/kgdb-jmp.S        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,32 @@
-+/*
-+ * arch/arm/kernel/kgdb-jmp.S
-+ *
-+ * Trivial setjmp and longjmp procedures to support bus error recovery
-+ * which may occur during kgdb memory read/write operations.
-+ *
-+ * Author: MontaVista Software, Inc. <source@mvista.com>
-+ *         source@mvista.com
-+ *
-+ * 2002-2005 (c) MontaVista Software, Inc.  This file is licensed under the
-+ * terms of the GNU General Public License version 2. This program as licensed
-+ * "as is" without any warranty of any kind, whether express or implied.
-+ */
-+#include <linux/linkage.h>
-+
-+ENTRY (kgdb_fault_setjmp)
-+      /* Save registers */
-+      stmia   r0, {r0-r14}
-+      str     lr,[r0, #60]
-+      mrs     r1,cpsr
-+      str     r1,[r0,#64]
-+      ldr     r1,[r0,#4]
-+      mov     r0, #0
-+      mov     pc,lr
-+
-+ENTRY (kgdb_fault_longjmp)
-+      /* Restore registers */
-+      mov     r1,#1
-+      str     r1,[r0]
-+      ldr     r1,[r0, #64]
-+      msr     spsr,r1
-+      ldmia   r0,{r0-pc}^
-diff -Nurb linux-2.6.22-570/arch/arm/kernel/kgdb.c linux-2.6.22-590/arch/arm/kernel/kgdb.c
---- linux-2.6.22-570/arch/arm/kernel/kgdb.c    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/arm/kernel/kgdb.c    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,202 @@
-+/*
-+ * arch/arm/kernel/kgdb.c
-+ *
-+ * ARM KGDB support
-+ *
-+ * Copyright (c) 2002-2004 MontaVista Software, Inc
-+ *
-+ * Authors:  George Davis <davis_g@mvista.com>
-+ *           Deepak Saxena <dsaxena@plexity.net>
-+ */
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/mm.h>
-+#include <linux/spinlock.h>
-+#include <linux/personality.h>
-+#include <linux/ptrace.h>
-+#include <linux/elf.h>
-+#include <linux/interrupt.h>
-+#include <linux/init.h>
-+#include <linux/kgdb.h>
-+
-+#include <asm/atomic.h>
-+#include <asm/io.h>
-+#include <asm/pgtable.h>
-+#include <asm/system.h>
-+#include <asm/uaccess.h>
-+#include <asm/unistd.h>
-+#include <asm/ptrace.h>
-+#include <asm/traps.h>
-+
-+/* Make a local copy of the registers passed into the handler (bletch) */
-+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
-+{
-+      int regno;
-+
-+      /* Initialize all to zero (??) */
-+      for (regno = 0; regno < GDB_MAX_REGS; regno++)
-+              gdb_regs[regno] = 0;
-+
-+      gdb_regs[_R0] = kernel_regs->ARM_r0;
-+      gdb_regs[_R1] = kernel_regs->ARM_r1;
-+      gdb_regs[_R2] = kernel_regs->ARM_r2;
-+      gdb_regs[_R3] = kernel_regs->ARM_r3;
-+      gdb_regs[_R4] = kernel_regs->ARM_r4;
-+      gdb_regs[_R5] = kernel_regs->ARM_r5;
-+      gdb_regs[_R6] = kernel_regs->ARM_r6;
-+      gdb_regs[_R7] = kernel_regs->ARM_r7;
-+      gdb_regs[_R8] = kernel_regs->ARM_r8;
-+      gdb_regs[_R9] = kernel_regs->ARM_r9;
-+      gdb_regs[_R10] = kernel_regs->ARM_r10;
-+      gdb_regs[_FP] = kernel_regs->ARM_fp;
-+      gdb_regs[_IP] = kernel_regs->ARM_ip;
-+      gdb_regs[_SP] = kernel_regs->ARM_sp;
-+      gdb_regs[_LR] = kernel_regs->ARM_lr;
-+      gdb_regs[_PC] = kernel_regs->ARM_pc;
-+      gdb_regs[_CPSR] = kernel_regs->ARM_cpsr;
-+}
-+
-+/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
-+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
-+{
-+      kernel_regs->ARM_r0 = gdb_regs[_R0];
-+      kernel_regs->ARM_r1 = gdb_regs[_R1];
-+      kernel_regs->ARM_r2 = gdb_regs[_R2];
-+      kernel_regs->ARM_r3 = gdb_regs[_R3];
-+      kernel_regs->ARM_r4 = gdb_regs[_R4];
-+      kernel_regs->ARM_r5 = gdb_regs[_R5];
-+      kernel_regs->ARM_r6 = gdb_regs[_R6];
-+      kernel_regs->ARM_r7 = gdb_regs[_R7];
-+      kernel_regs->ARM_r8 = gdb_regs[_R8];
-+      kernel_regs->ARM_r9 = gdb_regs[_R9];
-+      kernel_regs->ARM_r10 = gdb_regs[_R10];
-+      kernel_regs->ARM_fp = gdb_regs[_FP];
-+      kernel_regs->ARM_ip = gdb_regs[_IP];
-+      kernel_regs->ARM_sp = gdb_regs[_SP];
-+      kernel_regs->ARM_lr = gdb_regs[_LR];
-+      kernel_regs->ARM_pc = gdb_regs[_PC];
-+      kernel_regs->ARM_cpsr = gdb_regs[_CPSR];
-+}
-+
-+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
-+                               struct task_struct *task)
-+{
-+      int regno;
-+      struct pt_regs *thread_regs;
-+
-+      /* Just making sure... */
-+      if (task == NULL)
-+              return;
-+
-+      /* Initialize to zero */
-+      for (regno = 0; regno < GDB_MAX_REGS; regno++)
-+              gdb_regs[regno] = 0;
-+
-+      /* Otherwise, we have only some registers from switch_to() */
-+      thread_regs = task_pt_regs(task);
-+      gdb_regs[_R0] = thread_regs->ARM_r0;    /* Not really valid? */
-+      gdb_regs[_R1] = thread_regs->ARM_r1;    /* "               " */
-+      gdb_regs[_R2] = thread_regs->ARM_r2;    /* "               " */
-+      gdb_regs[_R3] = thread_regs->ARM_r3;    /* "               " */
-+      gdb_regs[_R4] = thread_regs->ARM_r4;
-+      gdb_regs[_R5] = thread_regs->ARM_r5;
-+      gdb_regs[_R6] = thread_regs->ARM_r6;
-+      gdb_regs[_R7] = thread_regs->ARM_r7;
-+      gdb_regs[_R8] = thread_regs->ARM_r8;
-+      gdb_regs[_R9] = thread_regs->ARM_r9;
-+      gdb_regs[_R10] = thread_regs->ARM_r10;
-+      gdb_regs[_FP] = thread_regs->ARM_fp;
-+      gdb_regs[_IP] = thread_regs->ARM_ip;
-+      gdb_regs[_SP] = thread_regs->ARM_sp;
-+      gdb_regs[_LR] = thread_regs->ARM_lr;
-+      gdb_regs[_PC] = thread_regs->ARM_pc;
-+      gdb_regs[_CPSR] = thread_regs->ARM_cpsr;
-+}
-+
-+static int compiled_break;
-+
-+int kgdb_arch_handle_exception(int exception_vector, int signo,
-+                             int err_code, char *remcom_in_buffer,
-+                             char *remcom_out_buffer,
-+                             struct pt_regs *linux_regs)
-+{
-+      long addr;
-+      char *ptr;
-+
-+      switch (remcom_in_buffer[0]) {
-+      case 'D':
-+      case 'k':
-+      case 'c':
-+              kgdb_contthread = NULL;
-+
-+              /*
-+               * Try to read optional parameter, pc unchanged if no parm.
-+               * If this was a compiled breakpoint, we need to move
-+               * to the next instruction or we will just breakpoint
-+               * over and over again.
-+               */
-+              ptr = &remcom_in_buffer[1];
-+              if (kgdb_hex2long(&ptr, &addr)) {
-+                      linux_regs->ARM_pc = addr;
-+              } else if (compiled_break == 1) {
-+                      linux_regs->ARM_pc += 4;
-+              }
-+
-+              compiled_break = 0;
-+
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
-+{
-+      kgdb_handle_exception(1, SIGTRAP, 0, regs);
-+
-+      return 0;
-+}
-+
-+static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
-+{
-+      compiled_break = 1;
-+      kgdb_handle_exception(1, SIGTRAP, 0, regs);
-+
-+      return 0;
-+}
-+
-+static struct undef_hook kgdb_brkpt_hook = {
-+      .instr_mask = 0xffffffff,
-+      .instr_val = KGDB_BREAKINST,
-+      .fn = kgdb_brk_fn
-+};
-+
-+static struct undef_hook kgdb_compiled_brkpt_hook = {
-+      .instr_mask = 0xffffffff,
-+      .instr_val = KGDB_COMPILED_BREAK,
-+      .fn = kgdb_compiled_brk_fn
-+};
-+
-+/*
-+ * Register our undef instruction hooks with ARM undef core.
-+ * We regsiter a hook specifically looking for the KGB break inst
-+ * and we handle the normal undef case within the do_undefinstr
-+ * handler.
-+ */
-+int kgdb_arch_init(void)
-+{
-+      register_undef_hook(&kgdb_brkpt_hook);
-+      register_undef_hook(&kgdb_compiled_brkpt_hook);
-+
-+      return 0;
-+}
-+
-+struct kgdb_arch arch_kgdb_ops = {
-+#ifndef __ARMEB__
-+      .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7}
-+#else
-+      .gdb_bpt_instr = {0xe7, 0xff, 0xde, 0xfe}
-+#endif
-+};
-diff -Nurb linux-2.6.22-570/arch/arm/kernel/setup.c linux-2.6.22-590/arch/arm/kernel/setup.c
---- linux-2.6.22-570/arch/arm/kernel/setup.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/kernel/setup.c   2008-01-02 13:56:37.000000000 -0500
-@@ -832,6 +832,11 @@
-       conswitchp = &dummy_con;
- #endif
- #endif
-+
-+#if   defined(CONFIG_KGDB)
-+      extern void __init early_trap_init(void);
-+      early_trap_init();
-+#endif
- }
-diff -Nurb linux-2.6.22-570/arch/arm/kernel/traps.c linux-2.6.22-590/arch/arm/kernel/traps.c
---- linux-2.6.22-570/arch/arm/kernel/traps.c   2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/arm/kernel/traps.c   2008-01-02 13:56:37.000000000 -0500
-@@ -301,6 +301,7 @@
-       unsigned int instr;
-       struct undef_hook *hook;
-       siginfo_t info;
-+      mm_segment_t fs;
-       void __user *pc;
-       unsigned long flags;
-@@ -311,6 +312,8 @@
-        */
-       regs->ARM_pc -= correction;
-+      fs = get_fs();
-+      set_fs(KERNEL_DS);
-       pc = (void __user *)instruction_pointer(regs);
-       if (processor_mode(regs) == SVC_MODE) {
-@@ -320,6 +323,7 @@
-       } else {
-               get_user(instr, (u32 __user *)pc);
-       }
-+      set_fs(fs);
-       spin_lock_irqsave(&undef_lock, flags);
-       list_for_each_entry(hook, &undef_hook, node) {
-@@ -707,6 +711,13 @@
- void __init trap_init(void)
- {
-+#if   defined(CONFIG_KGDB)
-+      return;
-+}
-+
-+void __init early_trap_init(void)
-+{
-+#endif
-       unsigned long vectors = CONFIG_VECTORS_BASE;
-       extern char __stubs_start[], __stubs_end[];
-       extern char __vectors_start[], __vectors_end[];
-diff -Nurb linux-2.6.22-570/arch/arm/mach-iop13xx/setup.c linux-2.6.22-590/arch/arm/mach-iop13xx/setup.c
---- linux-2.6.22-570/arch/arm/mach-iop13xx/setup.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-iop13xx/setup.c     2008-01-02 13:56:37.000000000 -0500
-@@ -25,6 +25,7 @@
- #include <asm/hardware.h>
- #include <asm/irq.h>
- #include <asm/io.h>
-+#include <asm/hardware/iop_adma.h>
- #define IOP13XX_UART_XTAL 33334000
- #define IOP13XX_SETUP_DEBUG 0
-@@ -236,19 +237,143 @@
- }
- #endif
-+/* ADMA Channels */
-+static struct resource iop13xx_adma_0_resources[] = {
-+      [0] = {
-+              .start = IOP13XX_ADMA_PHYS_BASE(0),
-+              .end = IOP13XX_ADMA_UPPER_PA(0),
-+              .flags = IORESOURCE_MEM,
-+      },
-+      [1] = {
-+              .start = IRQ_IOP13XX_ADMA0_EOT,
-+              .end = IRQ_IOP13XX_ADMA0_EOT,
-+              .flags = IORESOURCE_IRQ
-+      },
-+      [2] = {
-+              .start = IRQ_IOP13XX_ADMA0_EOC,
-+              .end = IRQ_IOP13XX_ADMA0_EOC,
-+              .flags = IORESOURCE_IRQ
-+      },
-+      [3] = {
-+              .start = IRQ_IOP13XX_ADMA0_ERR,
-+              .end = IRQ_IOP13XX_ADMA0_ERR,
-+              .flags = IORESOURCE_IRQ
-+      }
-+};
-+
-+static struct resource iop13xx_adma_1_resources[] = {
-+      [0] = {
-+              .start = IOP13XX_ADMA_PHYS_BASE(1),
-+              .end = IOP13XX_ADMA_UPPER_PA(1),
-+              .flags = IORESOURCE_MEM,
-+      },
-+      [1] = {
-+              .start = IRQ_IOP13XX_ADMA1_EOT,
-+              .end = IRQ_IOP13XX_ADMA1_EOT,
-+              .flags = IORESOURCE_IRQ
-+      },
-+      [2] = {
-+              .start = IRQ_IOP13XX_ADMA1_EOC,
-+              .end = IRQ_IOP13XX_ADMA1_EOC,
-+              .flags = IORESOURCE_IRQ
-+      },
-+      [3] = {
-+              .start = IRQ_IOP13XX_ADMA1_ERR,
-+              .end = IRQ_IOP13XX_ADMA1_ERR,
-+              .flags = IORESOURCE_IRQ
-+      }
-+};
-+
-+static struct resource iop13xx_adma_2_resources[] = {
-+      [0] = {
-+              .start = IOP13XX_ADMA_PHYS_BASE(2),
-+              .end = IOP13XX_ADMA_UPPER_PA(2),
-+              .flags = IORESOURCE_MEM,
-+      },
-+      [1] = {
-+              .start = IRQ_IOP13XX_ADMA2_EOT,
-+              .end = IRQ_IOP13XX_ADMA2_EOT,
-+              .flags = IORESOURCE_IRQ
-+      },
-+      [2] = {
-+              .start = IRQ_IOP13XX_ADMA2_EOC,
-+              .end = IRQ_IOP13XX_ADMA2_EOC,
-+              .flags = IORESOURCE_IRQ
-+      },
-+      [3] = {
-+              .start = IRQ_IOP13XX_ADMA2_ERR,
-+              .end = IRQ_IOP13XX_ADMA2_ERR,
-+              .flags = IORESOURCE_IRQ
-+      }
-+};
-+
-+static u64 iop13xx_adma_dmamask = DMA_64BIT_MASK;
-+static struct iop_adma_platform_data iop13xx_adma_0_data = {
-+      .hw_id = 0,
-+      .pool_size = PAGE_SIZE,
-+};
-+
-+static struct iop_adma_platform_data iop13xx_adma_1_data = {
-+      .hw_id = 1,
-+      .pool_size = PAGE_SIZE,
-+};
-+
-+static struct iop_adma_platform_data iop13xx_adma_2_data = {
-+      .hw_id = 2,
-+      .pool_size = PAGE_SIZE,
-+};
-+
-+/* The ids are fixed up later in iop13xx_platform_init */
-+static struct platform_device iop13xx_adma_0_channel = {
-+      .name = "iop-adma",
-+      .id = 0,
-+      .num_resources = 4,
-+      .resource = iop13xx_adma_0_resources,
-+      .dev = {
-+              .dma_mask = &iop13xx_adma_dmamask,
-+              .coherent_dma_mask = DMA_64BIT_MASK,
-+              .platform_data = (void *) &iop13xx_adma_0_data,
-+      },
-+};
-+
-+static struct platform_device iop13xx_adma_1_channel = {
-+      .name = "iop-adma",
-+      .id = 0,
-+      .num_resources = 4,
-+      .resource = iop13xx_adma_1_resources,
-+      .dev = {
-+              .dma_mask = &iop13xx_adma_dmamask,
-+              .coherent_dma_mask = DMA_64BIT_MASK,
-+              .platform_data = (void *) &iop13xx_adma_1_data,
-+      },
-+};
-+
-+static struct platform_device iop13xx_adma_2_channel = {
-+      .name = "iop-adma",
-+      .id = 0,
-+      .num_resources = 4,
-+      .resource = iop13xx_adma_2_resources,
-+      .dev = {
-+              .dma_mask = &iop13xx_adma_dmamask,
-+              .coherent_dma_mask = DMA_64BIT_MASK,
-+              .platform_data = (void *) &iop13xx_adma_2_data,
-+      },
-+};
-+
- void __init iop13xx_map_io(void)
- {
-       /* Initialize the Static Page Table maps */
-       iotable_init(iop13xx_std_desc, ARRAY_SIZE(iop13xx_std_desc));
- }
--static int init_uart = 0;
--static int init_i2c = 0;
-+static int init_uart;
-+static int init_i2c;
-+static int init_adma;
- void __init iop13xx_platform_init(void)
- {
-       int i;
--      u32 uart_idx, i2c_idx, plat_idx;
-+      u32 uart_idx, i2c_idx, adma_idx, plat_idx;
-       struct platform_device *iop13xx_devices[IQ81340_MAX_PLAT_DEVICES];
-       /* set the bases so we can read the device id */
-@@ -294,6 +419,12 @@
-               }
-       }
-+      if (init_adma == IOP13XX_INIT_ADMA_DEFAULT) {
-+              init_adma |= IOP13XX_INIT_ADMA_0;
-+              init_adma |= IOP13XX_INIT_ADMA_1;
-+              init_adma |= IOP13XX_INIT_ADMA_2;
-+      }
-+
-       plat_idx = 0;
-       uart_idx = 0;
-       i2c_idx = 0;
-@@ -332,6 +463,56 @@
-               }
-       }
-+      /* initialize adma channel ids and capabilities */
-+      adma_idx = 0;
-+      for (i = 0; i < IQ81340_NUM_ADMA; i++) {
-+              struct iop_adma_platform_data *plat_data;
-+              if ((init_adma & (1 << i)) && IOP13XX_SETUP_DEBUG)
-+                      printk(KERN_INFO
-+                              "Adding adma%d to platform device list\n", i);
-+              switch (init_adma & (1 << i)) {
-+              case IOP13XX_INIT_ADMA_0:
-+                      iop13xx_adma_0_channel.id = adma_idx++;
-+                      iop13xx_devices[plat_idx++] = &iop13xx_adma_0_channel;
-+                      plat_data = &iop13xx_adma_0_data;
-+                      dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
-+                      dma_cap_set(DMA_XOR, plat_data->cap_mask);
-+                      dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
-+                      dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
-+                      dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
-+                      dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
-+                      dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
-+                      break;
-+              case IOP13XX_INIT_ADMA_1:
-+                      iop13xx_adma_1_channel.id = adma_idx++;
-+                      iop13xx_devices[plat_idx++] = &iop13xx_adma_1_channel;
-+                      plat_data = &iop13xx_adma_1_data;
-+                      dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
-+                      dma_cap_set(DMA_XOR, plat_data->cap_mask);
-+                      dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
-+                      dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
-+                      dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
-+                      dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
-+                      dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
-+                      break;
-+              case IOP13XX_INIT_ADMA_2:
-+                      iop13xx_adma_2_channel.id = adma_idx++;
-+                      iop13xx_devices[plat_idx++] = &iop13xx_adma_2_channel;
-+                      plat_data = &iop13xx_adma_2_data;
-+                      dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
-+                      dma_cap_set(DMA_XOR, plat_data->cap_mask);
-+                      dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
-+                      dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
-+                      dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
-+                      dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
-+                      dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
-+                      dma_cap_set(DMA_PQ_XOR, plat_data->cap_mask);
-+                      dma_cap_set(DMA_PQ_UPDATE, plat_data->cap_mask);
-+                      dma_cap_set(DMA_PQ_ZERO_SUM, plat_data->cap_mask);
-+                      break;
-+              }
-+      }
-+
- #ifdef CONFIG_MTD_PHYSMAP
-       iq8134x_flash_resource.end = iq8134x_flash_resource.start +
-                               iq8134x_probe_flash_size() - 1;
-@@ -399,5 +580,35 @@
-       return 1;
- }
-+static int __init iop13xx_init_adma_setup(char *str)
-+{
-+      if (str)        {
-+              while (*str != '\0') {
-+                      switch (*str) {
-+                      case '0':
-+                              init_adma |= IOP13XX_INIT_ADMA_0;
-+                              break;
-+                      case '1':
-+                              init_adma |= IOP13XX_INIT_ADMA_1;
-+                              break;
-+                      case '2':
-+                              init_adma |= IOP13XX_INIT_ADMA_2;
-+                              break;
-+                      case ',':
-+                      case '=':
-+                              break;
-+                      default:
-+                              PRINTK("\"iop13xx_init_adma\" malformed"
-+                                          " at character: \'%c\'", *str);
-+                              *(str + 1) = '\0';
-+                              init_adma = IOP13XX_INIT_ADMA_DEFAULT;
-+                      }
-+                      str++;
-+              }
-+      }
-+      return 1;
-+}
-+
-+__setup("iop13xx_init_adma", iop13xx_init_adma_setup);
- __setup("iop13xx_init_uart", iop13xx_init_uart_setup);
- __setup("iop13xx_init_i2c", iop13xx_init_i2c_setup);
-diff -Nurb linux-2.6.22-570/arch/arm/mach-iop32x/glantank.c linux-2.6.22-590/arch/arm/mach-iop32x/glantank.c
---- linux-2.6.22-570/arch/arm/mach-iop32x/glantank.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-iop32x/glantank.c   2008-01-02 13:56:37.000000000 -0500
-@@ -180,6 +180,8 @@
-       platform_device_register(&iop3xx_i2c1_device);
-       platform_device_register(&glantank_flash_device);
-       platform_device_register(&glantank_serial_device);
-+      platform_device_register(&iop3xx_dma_0_channel);
-+      platform_device_register(&iop3xx_dma_1_channel);
-       pm_power_off = glantank_power_off;
- }
-diff -Nurb linux-2.6.22-570/arch/arm/mach-iop32x/iq31244.c linux-2.6.22-590/arch/arm/mach-iop32x/iq31244.c
---- linux-2.6.22-570/arch/arm/mach-iop32x/iq31244.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-iop32x/iq31244.c    2008-01-02 13:56:37.000000000 -0500
-@@ -298,9 +298,14 @@
-       platform_device_register(&iop3xx_i2c1_device);
-       platform_device_register(&iq31244_flash_device);
-       platform_device_register(&iq31244_serial_device);
-+      platform_device_register(&iop3xx_dma_0_channel);
-+      platform_device_register(&iop3xx_dma_1_channel);
-       if (is_ep80219())
-               pm_power_off = ep80219_power_off;
-+
-+      if (!is_80219())
-+              platform_device_register(&iop3xx_aau_channel);
- }
- static int __init force_ep80219_setup(char *str)
-diff -Nurb linux-2.6.22-570/arch/arm/mach-iop32x/iq80321.c linux-2.6.22-590/arch/arm/mach-iop32x/iq80321.c
---- linux-2.6.22-570/arch/arm/mach-iop32x/iq80321.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-iop32x/iq80321.c    2008-01-02 13:56:37.000000000 -0500
-@@ -181,6 +181,9 @@
-       platform_device_register(&iop3xx_i2c1_device);
-       platform_device_register(&iq80321_flash_device);
-       platform_device_register(&iq80321_serial_device);
-+      platform_device_register(&iop3xx_dma_0_channel);
-+      platform_device_register(&iop3xx_dma_1_channel);
-+      platform_device_register(&iop3xx_aau_channel);
- }
- MACHINE_START(IQ80321, "Intel IQ80321")
-diff -Nurb linux-2.6.22-570/arch/arm/mach-iop32x/n2100.c linux-2.6.22-590/arch/arm/mach-iop32x/n2100.c
---- linux-2.6.22-570/arch/arm/mach-iop32x/n2100.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-iop32x/n2100.c      2008-01-02 13:56:37.000000000 -0500
-@@ -245,6 +245,8 @@
-       platform_device_register(&iop3xx_i2c0_device);
-       platform_device_register(&n2100_flash_device);
-       platform_device_register(&n2100_serial_device);
-+      platform_device_register(&iop3xx_dma_0_channel);
-+      platform_device_register(&iop3xx_dma_1_channel);
-       pm_power_off = n2100_power_off;
-diff -Nurb linux-2.6.22-570/arch/arm/mach-iop33x/iq80331.c linux-2.6.22-590/arch/arm/mach-iop33x/iq80331.c
---- linux-2.6.22-570/arch/arm/mach-iop33x/iq80331.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-iop33x/iq80331.c    2008-01-02 13:56:37.000000000 -0500
-@@ -136,6 +136,9 @@
-       platform_device_register(&iop33x_uart0_device);
-       platform_device_register(&iop33x_uart1_device);
-       platform_device_register(&iq80331_flash_device);
-+      platform_device_register(&iop3xx_dma_0_channel);
-+      platform_device_register(&iop3xx_dma_1_channel);
-+      platform_device_register(&iop3xx_aau_channel);
- }
- MACHINE_START(IQ80331, "Intel IQ80331")
-diff -Nurb linux-2.6.22-570/arch/arm/mach-iop33x/iq80332.c linux-2.6.22-590/arch/arm/mach-iop33x/iq80332.c
---- linux-2.6.22-570/arch/arm/mach-iop33x/iq80332.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-iop33x/iq80332.c    2008-01-02 13:56:37.000000000 -0500
-@@ -136,6 +136,9 @@
-       platform_device_register(&iop33x_uart0_device);
-       platform_device_register(&iop33x_uart1_device);
-       platform_device_register(&iq80332_flash_device);
-+      platform_device_register(&iop3xx_dma_0_channel);
-+      platform_device_register(&iop3xx_dma_1_channel);
-+      platform_device_register(&iop3xx_aau_channel);
- }
- MACHINE_START(IQ80332, "Intel IQ80332")
-diff -Nurb linux-2.6.22-570/arch/arm/mach-ixp2000/core.c linux-2.6.22-590/arch/arm/mach-ixp2000/core.c
---- linux-2.6.22-570/arch/arm/mach-ixp2000/core.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-ixp2000/core.c      2008-01-02 13:56:37.000000000 -0500
-@@ -34,6 +34,7 @@
- #include <asm/system.h>
- #include <asm/tlbflush.h>
- #include <asm/pgtable.h>
-+#include <asm/kgdb.h>
- #include <asm/mach/map.h>
- #include <asm/mach/time.h>
-@@ -184,6 +185,9 @@
- void __init ixp2000_uart_init(void)
- {
-       platform_device_register(&ixp2000_serial_device);
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_platform_port(0, &ixp2000_serial_port);
-+#endif
- }
-diff -Nurb linux-2.6.22-570/arch/arm/mach-ixp2000/ixdp2x01.c linux-2.6.22-590/arch/arm/mach-ixp2000/ixdp2x01.c
---- linux-2.6.22-570/arch/arm/mach-ixp2000/ixdp2x01.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-ixp2000/ixdp2x01.c  2008-01-02 13:56:37.000000000 -0500
-@@ -38,6 +38,7 @@
- #include <asm/system.h>
- #include <asm/hardware.h>
- #include <asm/mach-types.h>
-+#include <asm/kgdb.h>
- #include <asm/mach/pci.h>
- #include <asm/mach/map.h>
-@@ -413,6 +414,11 @@
-       platform_add_devices(ixdp2x01_devices, ARRAY_SIZE(ixdp2x01_devices));
-       ixp2000_uart_init();
-       ixdp2x01_uart_init();
-+
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_platform_port(0, ixdp2x01_serial_port1);
-+      kgdb8250_add_platform_port(1, ixdp2x01_serial_port1);
-+#endif
- }
-diff -Nurb linux-2.6.22-570/arch/arm/mach-ixp4xx/coyote-setup.c linux-2.6.22-590/arch/arm/mach-ixp4xx/coyote-setup.c
---- linux-2.6.22-570/arch/arm/mach-ixp4xx/coyote-setup.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-ixp4xx/coyote-setup.c       2008-01-02 13:56:37.000000000 -0500
-@@ -96,6 +96,10 @@
-       }
-       platform_add_devices(coyote_devices, ARRAY_SIZE(coyote_devices));
-+
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_platform_port(0, &coyote_uart_data);
-+#endif
- }
- #ifdef CONFIG_ARCH_ADI_COYOTE
-diff -Nurb linux-2.6.22-570/arch/arm/mach-ixp4xx/ixdp425-setup.c linux-2.6.22-590/arch/arm/mach-ixp4xx/ixdp425-setup.c
---- linux-2.6.22-570/arch/arm/mach-ixp4xx/ixdp425-setup.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-ixp4xx/ixdp425-setup.c      2008-01-02 13:56:37.000000000 -0500
-@@ -76,7 +76,8 @@
-               .mapbase        = IXP4XX_UART1_BASE_PHYS,
-               .membase        = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
-               .irq            = IRQ_IXP4XX_UART1,
--              .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
-+              .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
-+                                      UPF_SHARE_IRQ,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = IXP4XX_UART_XTAL,
-@@ -85,7 +86,8 @@
-               .mapbase        = IXP4XX_UART2_BASE_PHYS,
-               .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
-               .irq            = IRQ_IXP4XX_UART2,
--              .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
-+              .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
-+                                      UPF_SHARE_IRQ,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = IXP4XX_UART_XTAL,
-@@ -123,12 +125,22 @@
-       platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
- }
-+static void __init ixdp425_map_io(void)
-+{
-+      ixp4xx_map_io();
-+
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_platform_port(0, &ixdp425_uart_data[0]);
-+      kgdb8250_add_platform_port(1, &ixdp425_uart_data[1]);
-+#endif
-+}
-+
- #ifdef CONFIG_ARCH_IXDP425
- MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
-       /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
--      .map_io         = ixp4xx_map_io,
-+      .map_io         = ixdp425_map_io,
-       .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
-@@ -141,7 +153,7 @@
-       /* Maintainer: MontaVista Software, Inc. */
-       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
-       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
--      .map_io         = ixp4xx_map_io,
-+      .map_io         = ixdp425_map_io,
-       .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
-       .boot_params    = 0x0100,
-diff -Nurb linux-2.6.22-570/arch/arm/mach-omap1/serial.c linux-2.6.22-590/arch/arm/mach-omap1/serial.c
---- linux-2.6.22-570/arch/arm/mach-omap1/serial.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-omap1/serial.c      2008-01-02 13:56:37.000000000 -0500
-@@ -15,6 +15,7 @@
- #include <linux/delay.h>
- #include <linux/serial.h>
- #include <linux/tty.h>
-+#include <linux/kgdb.h>
- #include <linux/serial_8250.h>
- #include <linux/serial_reg.h>
- #include <linux/clk.h>
-@@ -199,6 +200,9 @@
-                       break;
-               }
-               omap_serial_reset(&serial_platform_data[i]);
-+#ifdef CONFIG_KGDB_8250
-+              kgdb8250_add_platform_port(i, &serial_platform_data[i]);
-+#endif
-       }
- }
-diff -Nurb linux-2.6.22-570/arch/arm/mach-pnx4008/core.c linux-2.6.22-590/arch/arm/mach-pnx4008/core.c
---- linux-2.6.22-570/arch/arm/mach-pnx4008/core.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-pnx4008/core.c      2008-01-02 13:56:37.000000000 -0500
-@@ -224,6 +224,10 @@
-       spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
-       /* Switch on the UART clocks */
-       pnx4008_uart_init();
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_platform_port(0, &platform_serial_ports[0]);
-+      kgdb8250_add_platform_port(1, &platform_serial_ports[1]);
-+#endif
- }
- static struct map_desc pnx4008_io_desc[] __initdata = {
-diff -Nurb linux-2.6.22-570/arch/arm/mach-pxa/Makefile linux-2.6.22-590/arch/arm/mach-pxa/Makefile
---- linux-2.6.22-570/arch/arm/mach-pxa/Makefile        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-pxa/Makefile        2008-01-02 13:56:37.000000000 -0500
-@@ -31,6 +31,7 @@
- # Misc features
- obj-$(CONFIG_PM) += pm.o sleep.o
- obj-$(CONFIG_PXA_SSP) += ssp.o
-+obj-$(CONFIG_KGDB_PXA_SERIAL) += kgdb-serial.o
- ifeq ($(CONFIG_PXA27x),y)
- obj-$(CONFIG_PM) += standby.o
-diff -Nurb linux-2.6.22-570/arch/arm/mach-pxa/kgdb-serial.c linux-2.6.22-590/arch/arm/mach-pxa/kgdb-serial.c
---- linux-2.6.22-570/arch/arm/mach-pxa/kgdb-serial.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/arm/mach-pxa/kgdb-serial.c   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,97 @@
-+/*
-+ * linux/arch/arm/mach-pxa/kgdb-serial.c
-+ *
-+ * Provides low level kgdb serial support hooks for PXA2xx boards
-+ *
-+ * Author:    Nicolas Pitre
-+ * Copyright: (C) 2002-2005 MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/serial_reg.h>
-+#include <linux/kgdb.h>
-+#include <asm/processor.h>
-+#include <asm/hardware.h>
-+#include <asm/arch/pxa-regs.h>
-+
-+#if   defined(CONFIG_KGDB_PXA_FFUART)
-+
-+#define UART          FFUART
-+#define CKEN_UART     CKEN6_FFUART
-+#define GPIO_RX_MD    GPIO34_FFRXD_MD
-+#define GPIO_TX_MD    GPIO39_FFTXD_MD
-+
-+#elif defined(CONFIG_KGDB_PXA_BTUART)
-+
-+#define UART          BTUART
-+#define CKEN_UART     CKEN7_BTUART
-+#define GPIO_RX_MD    GPIO42_BTRXD_MD
-+#define GPIO_TX_MD    GPIO43_BTTXD_MD
-+
-+#elif defined(CONFIG_KGDB_PXA_STUART)
-+
-+#define UART          STUART
-+#define CKEN_UART     CKEN5_STUART
-+#define GPIO_RX_MD    GPIO46_STRXD_MD
-+#define GPIO_TX_MD    GPIO47_STTXD_MD
-+
-+#endif
-+
-+#define UART_BAUDRATE (CONFIG_KGDB_BAUDRATE)
-+
-+static volatile unsigned long *port = (unsigned long *)&UART;
-+
-+static int kgdb_serial_init(void)
-+{
-+      pxa_set_cken(CKEN_UART, 1);
-+      pxa_gpio_mode(GPIO_RX_MD);
-+      pxa_gpio_mode(GPIO_TX_MD);
-+
-+      port[UART_IER] = 0;
-+      port[UART_LCR] = LCR_DLAB;
-+      port[UART_DLL] = ((921600 / UART_BAUDRATE) & 0xff);
-+      port[UART_DLM] = ((921600 / UART_BAUDRATE) >> 8);
-+      port[UART_LCR] = LCR_WLS1 | LCR_WLS0;
-+      port[UART_MCR] = 0;
-+      port[UART_IER] = IER_UUE;
-+      port[UART_FCR] = FCR_ITL_16;
-+
-+      return 0;
-+}
-+
-+static void kgdb_serial_putchar(u8 c)
-+{
-+      if (!(CKEN & CKEN_UART) || port[UART_IER] != IER_UUE)
-+              kgdb_serial_init();
-+      while (!(port[UART_LSR] & LSR_TDRQ))
-+              cpu_relax();
-+      port[UART_TX] = c;
-+}
-+
-+static void kgdb_serial_flush(void)
-+{
-+      if ((CKEN & CKEN_UART) && (port[UART_IER] & IER_UUE))
-+              while (!(port[UART_LSR] & LSR_TEMT))
-+                      cpu_relax();
-+}
-+
-+static int kgdb_serial_getchar(void)
-+{
-+      unsigned char c;
-+      if (!(CKEN & CKEN_UART) || port[UART_IER] != IER_UUE)
-+              kgdb_serial_init();
-+      while (!(port[UART_LSR] & UART_LSR_DR))
-+              cpu_relax();
-+      c = port[UART_RX];
-+      return c;
-+}
-+
-+struct kgdb_io kgdb_io_ops = {
-+      .init = kgdb_serial_init,
-+      .write_char = kgdb_serial_putchar,
-+      .flush = kgdb_serial_flush,
-+      .read_char = kgdb_serial_getchar,
-+};
-diff -Nurb linux-2.6.22-570/arch/arm/mach-versatile/core.c linux-2.6.22-590/arch/arm/mach-versatile/core.c
---- linux-2.6.22-570/arch/arm/mach-versatile/core.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mach-versatile/core.c    2008-01-02 13:56:37.000000000 -0500
-@@ -184,6 +184,14 @@
-               .type           = MT_DEVICE
-       },
- #endif
-+#ifdef CONFIG_KGDB_AMBA_PL011
-+      {
-+              .virtual        =  IO_ADDRESS(CONFIG_KGDB_AMBA_BASE),
-+              .pfn            = __phys_to_pfn(CONFIG_KGDB_AMBA_BASE),
-+              .length         = SZ_4K,
-+              .type           = MT_DEVICE
-+      },
-+#endif
- #ifdef CONFIG_PCI
-       {
-               .virtual        =  IO_ADDRESS(VERSATILE_PCI_CORE_BASE),
-diff -Nurb linux-2.6.22-570/arch/arm/mm/extable.c linux-2.6.22-590/arch/arm/mm/extable.c
---- linux-2.6.22-570/arch/arm/mm/extable.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/mm/extable.c     2008-01-02 13:56:37.000000000 -0500
-@@ -2,6 +2,7 @@
-  *  linux/arch/arm/mm/extable.c
-  */
- #include <linux/module.h>
-+#include <linux/kgdb.h>
- #include <asm/uaccess.h>
- int fixup_exception(struct pt_regs *regs)
-@@ -11,6 +12,12 @@
-       fixup = search_exception_tables(instruction_pointer(regs));
-       if (fixup)
-               regs->ARM_pc = fixup->fixup;
-+#ifdef CONFIG_KGDB
-+      if (atomic_read(&debugger_active) && kgdb_may_fault)
-+              /* Restore our previous state. */
-+              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
-+              /* Not reached. */
-+#endif
-       return fixup != NULL;
- }
-diff -Nurb linux-2.6.22-570/arch/arm/plat-iop/Makefile linux-2.6.22-590/arch/arm/plat-iop/Makefile
---- linux-2.6.22-570/arch/arm/plat-iop/Makefile        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/arm/plat-iop/Makefile        2008-01-02 13:56:37.000000000 -0500
-@@ -12,6 +12,7 @@
- obj-$(CONFIG_ARCH_IOP32X) += time.o
- obj-$(CONFIG_ARCH_IOP32X) += io.o
- obj-$(CONFIG_ARCH_IOP32X) += cp6.o
-+obj-$(CONFIG_ARCH_IOP32X) += adma.o
- # IOP33X
- obj-$(CONFIG_ARCH_IOP33X) += gpio.o
-@@ -21,6 +22,7 @@
- obj-$(CONFIG_ARCH_IOP33X) += time.o
- obj-$(CONFIG_ARCH_IOP33X) += io.o
- obj-$(CONFIG_ARCH_IOP33X) += cp6.o
-+obj-$(CONFIG_ARCH_IOP33X) += adma.o
- # IOP13XX
- obj-$(CONFIG_ARCH_IOP13XX) += cp6.o
-diff -Nurb linux-2.6.22-570/arch/arm/plat-iop/adma.c linux-2.6.22-590/arch/arm/plat-iop/adma.c
---- linux-2.6.22-570/arch/arm/plat-iop/adma.c  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/arm/plat-iop/adma.c  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,209 @@
-+/*
-+ * platform device definitions for the iop3xx dma/xor engines
-+ * Copyright Â© 2006, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ */
-+#include <linux/platform_device.h>
-+#include <asm/hardware/iop3xx.h>
-+#include <linux/dma-mapping.h>
-+#include <asm/arch/adma.h>
-+#include <asm/hardware/iop_adma.h>
-+
-+#ifdef CONFIG_ARCH_IOP32X
-+#define IRQ_DMA0_EOT IRQ_IOP32X_DMA0_EOT
-+#define IRQ_DMA0_EOC IRQ_IOP32X_DMA0_EOC
-+#define IRQ_DMA0_ERR IRQ_IOP32X_DMA0_ERR
-+
-+#define IRQ_DMA1_EOT IRQ_IOP32X_DMA1_EOT
-+#define IRQ_DMA1_EOC IRQ_IOP32X_DMA1_EOC
-+#define IRQ_DMA1_ERR IRQ_IOP32X_DMA1_ERR
-+
-+#define IRQ_AA_EOT IRQ_IOP32X_AA_EOT
-+#define IRQ_AA_EOC IRQ_IOP32X_AA_EOC
-+#define IRQ_AA_ERR IRQ_IOP32X_AA_ERR
-+#endif
-+#ifdef CONFIG_ARCH_IOP33X
-+#define IRQ_DMA0_EOT IRQ_IOP33X_DMA0_EOT
-+#define IRQ_DMA0_EOC IRQ_IOP33X_DMA0_EOC
-+#define IRQ_DMA0_ERR IRQ_IOP33X_DMA0_ERR
-+
-+#define IRQ_DMA1_EOT IRQ_IOP33X_DMA1_EOT
-+#define IRQ_DMA1_EOC IRQ_IOP33X_DMA1_EOC
-+#define IRQ_DMA1_ERR IRQ_IOP33X_DMA1_ERR
-+
-+#define IRQ_AA_EOT IRQ_IOP33X_AA_EOT
-+#define IRQ_AA_EOC IRQ_IOP33X_AA_EOC
-+#define IRQ_AA_ERR IRQ_IOP33X_AA_ERR
-+#endif
-+/* AAU and DMA Channels */
-+static struct resource iop3xx_dma_0_resources[] = {
-+      [0] = {
-+              .start = IOP3XX_DMA_PHYS_BASE(0),
-+              .end = IOP3XX_DMA_UPPER_PA(0),
-+              .flags = IORESOURCE_MEM,
-+      },
-+      [1] = {
-+              .start = IRQ_DMA0_EOT,
-+              .end = IRQ_DMA0_EOT,
-+              .flags = IORESOURCE_IRQ
-+      },
-+      [2] = {
-+              .start = IRQ_DMA0_EOC,
-+              .end = IRQ_DMA0_EOC,
-+              .flags = IORESOURCE_IRQ
-+      },
-+      [3] = {
-+              .start = IRQ_DMA0_ERR,
-+              .end = IRQ_DMA0_ERR,
-+              .flags = IORESOURCE_IRQ
-+      }
-+};
-+
-+static struct resource iop3xx_dma_1_resources[] = {
-+      [0] = {
-+              .start = IOP3XX_DMA_PHYS_BASE(1),
-+              .end = IOP3XX_DMA_UPPER_PA(1),
-+              .flags = IORESOURCE_MEM,
-+      },
-+      [1] = {
-+              .start = IRQ_DMA1_EOT,
-+              .end = IRQ_DMA1_EOT,
-+              .flags = IORESOURCE_IRQ
-+      },
-+      [2] = {
-+              .start = IRQ_DMA1_EOC,
-+              .end = IRQ_DMA1_EOC,
-+              .flags = IORESOURCE_IRQ
-+      },
-+      [3] = {
-+              .start = IRQ_DMA1_ERR,
-+              .end = IRQ_DMA1_ERR,
-+              .flags = IORESOURCE_IRQ
-+      }
-+};
-+
-+
-+static struct resource iop3xx_aau_resources[] = {
-+      [0] = {
-+              .start = IOP3XX_AAU_PHYS_BASE,
-+              .end = IOP3XX_AAU_UPPER_PA,
-+              .flags = IORESOURCE_MEM,
-+      },
-+      [1] = {
-+              .start = IRQ_AA_EOT,
-+              .end = IRQ_AA_EOT,
-+              .flags = IORESOURCE_IRQ
-+      },
-+      [2] = {
-+              .start = IRQ_AA_EOC,
-+              .end = IRQ_AA_EOC,
-+              .flags = IORESOURCE_IRQ
-+      },
-+      [3] = {
-+              .start = IRQ_AA_ERR,
-+              .end = IRQ_AA_ERR,
-+              .flags = IORESOURCE_IRQ
-+      }
-+};
-+
-+static u64 iop3xx_adma_dmamask = DMA_32BIT_MASK;
-+
-+static struct iop_adma_platform_data iop3xx_dma_0_data = {
-+      .hw_id = DMA0_ID,
-+      .pool_size = PAGE_SIZE,
-+};
-+
-+static struct iop_adma_platform_data iop3xx_dma_1_data = {
-+      .hw_id = DMA1_ID,
-+      .pool_size = PAGE_SIZE,
-+};
-+
-+static struct iop_adma_platform_data iop3xx_aau_data = {
-+      .hw_id = AAU_ID,
-+      .pool_size = 3 * PAGE_SIZE,
-+};
-+
-+struct platform_device iop3xx_dma_0_channel = {
-+      .name = "iop-adma",
-+      .id = 0,
-+      .num_resources = 4,
-+      .resource = iop3xx_dma_0_resources,
-+      .dev = {
-+              .dma_mask = &iop3xx_adma_dmamask,
-+              .coherent_dma_mask = DMA_64BIT_MASK,
-+              .platform_data = (void *) &iop3xx_dma_0_data,
-+      },
-+};
-+
-+struct platform_device iop3xx_dma_1_channel = {
-+      .name = "iop-adma",
-+      .id = 1,
-+      .num_resources = 4,
-+      .resource = iop3xx_dma_1_resources,
-+      .dev = {
-+              .dma_mask = &iop3xx_adma_dmamask,
-+              .coherent_dma_mask = DMA_64BIT_MASK,
-+              .platform_data = (void *) &iop3xx_dma_1_data,
-+      },
-+};
-+
-+struct platform_device iop3xx_aau_channel = {
-+      .name = "iop-adma",
-+      .id = 2,
-+      .num_resources = 4,
-+      .resource = iop3xx_aau_resources,
-+      .dev = {
-+              .dma_mask = &iop3xx_adma_dmamask,
-+              .coherent_dma_mask = DMA_64BIT_MASK,
-+              .platform_data = (void *) &iop3xx_aau_data,
-+      },
-+};
-+
-+static int __init iop3xx_adma_cap_init(void)
-+{
-+      #ifdef CONFIG_ARCH_IOP32X /* the 32x DMA does not perform CRC32C */
-+      dma_cap_set(DMA_MEMCPY, iop3xx_dma_0_data.cap_mask);
-+      dma_cap_set(DMA_INTERRUPT, iop3xx_dma_0_data.cap_mask);
-+      #else
-+      dma_cap_set(DMA_MEMCPY, iop3xx_dma_0_data.cap_mask);
-+      dma_cap_set(DMA_MEMCPY_CRC32C, iop3xx_dma_0_data.cap_mask);
-+      dma_cap_set(DMA_INTERRUPT, iop3xx_dma_0_data.cap_mask);
-+      #endif
-+
-+      #ifdef CONFIG_ARCH_IOP32X /* the 32x DMA does not perform CRC32C */
-+      dma_cap_set(DMA_MEMCPY, iop3xx_dma_1_data.cap_mask);
-+      dma_cap_set(DMA_INTERRUPT, iop3xx_dma_1_data.cap_mask);
-+      #else
-+      dma_cap_set(DMA_MEMCPY, iop3xx_dma_1_data.cap_mask);
-+      dma_cap_set(DMA_MEMCPY_CRC32C, iop3xx_dma_1_data.cap_mask);
-+      dma_cap_set(DMA_INTERRUPT, iop3xx_dma_1_data.cap_mask);
-+      #endif
-+
-+      #ifdef CONFIG_ARCH_IOP32X /* the 32x AAU does not perform zero sum */
-+      dma_cap_set(DMA_XOR, iop3xx_aau_data.cap_mask);
-+      dma_cap_set(DMA_MEMSET, iop3xx_aau_data.cap_mask);
-+      dma_cap_set(DMA_INTERRUPT, iop3xx_aau_data.cap_mask);
-+      #else
-+      dma_cap_set(DMA_XOR, iop3xx_aau_data.cap_mask);
-+      dma_cap_set(DMA_ZERO_SUM, iop3xx_aau_data.cap_mask);
-+      dma_cap_set(DMA_MEMSET, iop3xx_aau_data.cap_mask);
-+      dma_cap_set(DMA_INTERRUPT, iop3xx_aau_data.cap_mask);
-+      #endif
-+
-+      return 0;
-+}
-+
-+arch_initcall(iop3xx_adma_cap_init);
-diff -Nurb linux-2.6.22-570/arch/i386/Kconfig linux-2.6.22-590/arch/i386/Kconfig
---- linux-2.6.22-570/arch/i386/Kconfig 2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/i386/Kconfig 2008-01-02 13:56:37.000000000 -0500
-@@ -1053,6 +1053,8 @@
- source "arch/i386/kernel/cpu/cpufreq/Kconfig"
-+source "drivers/cpuidle/Kconfig"
-+
- endmenu
- menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
-diff -Nurb linux-2.6.22-570/arch/i386/kernel/Makefile linux-2.6.22-590/arch/i386/kernel/Makefile
---- linux-2.6.22-570/arch/i386/kernel/Makefile 2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/arch/i386/kernel/Makefile 2008-01-02 13:56:37.000000000 -0500
-@@ -39,6 +39,7 @@
- obj-$(CONFIG_EARLY_PRINTK)    += early_printk.o
- obj-$(CONFIG_HPET_TIMER)      += hpet.o
- obj-$(CONFIG_K8_NB)           += k8.o
-+obj-$(CONFIG_STACK_UNWIND)    += unwind.o
- obj-$(CONFIG_VMI)             += vmi.o vmiclock.o
- obj-$(CONFIG_PARAVIRT)                += paravirt.o
-diff -Nurb linux-2.6.22-570/arch/i386/kernel/acpi/boot.c linux-2.6.22-590/arch/i386/kernel/acpi/boot.c
---- linux-2.6.22-570/arch/i386/kernel/acpi/boot.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/i386/kernel/acpi/boot.c      2008-01-02 13:56:37.000000000 -0500
-@@ -950,14 +950,6 @@
-        },
-       {
-        .callback = force_acpi_ht,
--       .ident = "DELL GX240",
--       .matches = {
--                   DMI_MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
--                   DMI_MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
--                   },
--       },
--      {
--       .callback = force_acpi_ht,
-        .ident = "HP VISUALIZE NT Workstation",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
-diff -Nurb linux-2.6.22-570/arch/i386/kernel/apm.c linux-2.6.22-590/arch/i386/kernel/apm.c
---- linux-2.6.22-570/arch/i386/kernel/apm.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/i386/kernel/apm.c    2008-01-02 13:56:37.000000000 -0500
-@@ -222,6 +222,7 @@
- #include <linux/capability.h>
- #include <linux/device.h>
- #include <linux/kernel.h>
-+#include <linux/freezer.h>
- #include <linux/smp.h>
- #include <linux/dmi.h>
- #include <linux/suspend.h>
-@@ -2311,7 +2312,6 @@
-               remove_proc_entry("apm", NULL);
-               return err;
-       }
--      kapmd_task->flags |= PF_NOFREEZE;
-       wake_up_process(kapmd_task);
-       if (num_online_cpus() > 1 && !smp ) {
-diff -Nurb linux-2.6.22-570/arch/i386/kernel/io_apic.c linux-2.6.22-590/arch/i386/kernel/io_apic.c
---- linux-2.6.22-570/arch/i386/kernel/io_apic.c        2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/arch/i386/kernel/io_apic.c        2008-01-02 13:56:37.000000000 -0500
-@@ -667,6 +667,7 @@
-               set_pending_irq(i, cpumask_of_cpu(0));
-       }
-+      set_freezable();
-       for ( ; ; ) {
-               time_remaining = schedule_timeout_interruptible(time_remaining);
-               try_to_freeze();
-diff -Nurb linux-2.6.22-570/arch/i386/kernel/kgdb-jmp.S linux-2.6.22-590/arch/i386/kernel/kgdb-jmp.S
---- linux-2.6.22-570/arch/i386/kernel/kgdb-jmp.S       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/i386/kernel/kgdb-jmp.S       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,74 @@
-+/*
-+ * arch/i386/kernel/kgdb-jmp.S
-+ *
-+ * Save and restore system registers so that within a limited frame we
-+ * may have a fault and "jump back" to a known safe location.
-+ *
-+ * Author: George Anzinger <george@mvista.com>
-+ *
-+ * Cribbed from glibc, which carries the following:
-+ * Copyright (C) 1996, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
-+ * Copyright (C) 2005 by MontaVista Software.
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program as licensed "as is" without any warranty of
-+ * any kind, whether express or implied.
-+ */
-+
-+#include <linux/linkage.h>
-+
-+#define PCOFF         0
-+#define LINKAGE               4               /* just the return address */
-+#define PTR_SIZE      4
-+#define PARMS         LINKAGE         /* no space for saved regs */
-+#define JMPBUF                PARMS
-+#define VAL           JMPBUF+PTR_SIZE
-+
-+#define JB_BX         0
-+#define JB_SI         1
-+#define JB_DI         2
-+#define JB_BP         3
-+#define JB_SP         4
-+#define JB_PC         5
-+
-+/* This must be called prior to kgdb_fault_longjmp and
-+ * kgdb_fault_longjmp must not be called outside of the context of the
-+ * last call to kgdb_fault_setjmp.
-+ * kgdb_fault_setjmp(int *jmp_buf[6])
-+ */
-+ENTRY(kgdb_fault_setjmp)
-+      movl JMPBUF(%esp), %eax
-+
-+      /* Save registers.  */
-+      movl    %ebx, (JB_BX*4)(%eax)
-+      movl    %esi, (JB_SI*4)(%eax)
-+      movl    %edi, (JB_DI*4)(%eax)
-+      /* Save SP as it will be after we return.  */
-+      leal    JMPBUF(%esp), %ecx
-+      movl    %ecx, (JB_SP*4)(%eax)
-+      movl    PCOFF(%esp), %ecx       /* Save PC we are returning to now.  */
-+      movl    %ecx, (JB_PC*4)(%eax)
-+      movl    %ebp, (JB_BP*4)(%eax)   /* Save caller's frame pointer.  */
-+
-+      /* Restore state so we can now try the access. */
-+      movl    JMPBUF(%esp), %ecx      /* User's jmp_buf in %ecx.  */
-+      /* Save the return address now.  */
-+      movl    (JB_PC*4)(%ecx), %edx
-+      /* Restore registers.  */
-+      movl    $0, %eax
-+      movl    (JB_SP*4)(%ecx), %esp
-+      jmp     *%edx           /* Jump to saved PC. */
-+
-+/* kgdb_fault_longjmp(int *jmp_buf[6]) */
-+ENTRY(kgdb_fault_longjmp)
-+      movl    JMPBUF(%esp), %ecx      /* User's jmp_buf in %ecx.  */
-+      /* Save the return address now.  */
-+      movl    (JB_PC*4)(%ecx), %edx
-+      /* Restore registers.  */
-+      movl    (JB_BX*4)(%ecx), %ebx
-+      movl    (JB_SI*4)(%ecx), %esi
-+      movl    (JB_DI*4)(%ecx), %edi
-+      movl    (JB_BP*4)(%ecx), %ebp
-+      movl    $1, %eax
-+      movl    (JB_SP*4)(%ecx), %esp
-+      jmp     *%edx           /* Jump to saved PC. */
-diff -Nurb linux-2.6.22-570/arch/i386/kernel/kgdb.c linux-2.6.22-590/arch/i386/kernel/kgdb.c
---- linux-2.6.22-570/arch/i386/kernel/kgdb.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/i386/kernel/kgdb.c   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,388 @@
-+/*
-+ *
-+ * 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, 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.
-+ *
-+ */
-+
-+/*
-+ * Copyright (C) 2000-2001 VERITAS Software Corporation.
-+ * Copyright (C) 2007 Wind River Systems, Inc.
-+ */
-+/*
-+ *  Contributor:     Lake Stevens Instrument Division$
-+ *  Written by:      Glenn Engel $
-+ *  Updated by:            Amit Kale<akale@veritas.com>
-+ *  Updated by:            Tom Rini <trini@kernel.crashing.org>
-+ *  Updated by:            Jason Wessel <jason.wessel@windriver.com>
-+ *  Modified for 386 by Jim Kingdon, Cygnus Support.
-+ *  Origianl kgdb, compatibility with 2.1.xx kernel by
-+ *  David Grothe <dave@gcom.com>
-+ *  Additional support from Tigran Aivazian <tigran@sco.com>
-+ */
-+
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/smp.h>
-+#include <linux/spinlock.h>
-+#include <linux/delay.h>
-+#include <asm/vm86.h>
-+#include <asm/system.h>
-+#include <asm/ptrace.h>               /* for linux pt_regs struct */
-+#include <linux/kgdb.h>
-+#include <linux/init.h>
-+#include <linux/kdebug.h>
-+#include <asm/apicdef.h>
-+#include <asm/desc.h>
-+#include <asm/kdebug.h>
-+
-+#include "mach_ipi.h"
-+
-+/* Put the error code here just in case the user cares.  */
-+int gdb_i386errcode;
-+/* Likewise, the vector number here (since GDB only gets the signal
-+   number through the usual means, and that's not very specific).  */
-+int gdb_i386vector = -1;
-+
-+extern atomic_t cpu_doing_single_step;
-+
-+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-+{
-+      gdb_regs[_EAX] = regs->eax;
-+      gdb_regs[_EBX] = regs->ebx;
-+      gdb_regs[_ECX] = regs->ecx;
-+      gdb_regs[_EDX] = regs->edx;
-+      gdb_regs[_ESI] = regs->esi;
-+      gdb_regs[_EDI] = regs->edi;
-+      gdb_regs[_EBP] = regs->ebp;
-+      gdb_regs[_DS] = regs->xds;
-+      gdb_regs[_ES] = regs->xes;
-+      gdb_regs[_PS] = regs->eflags;
-+      gdb_regs[_CS] = regs->xcs;
-+      gdb_regs[_PC] = regs->eip;
-+      gdb_regs[_ESP] = (int)(&regs->esp);
-+      gdb_regs[_SS] = __KERNEL_DS;
-+      gdb_regs[_FS] = 0xFFFF;
-+      gdb_regs[_GS] = 0xFFFF;
-+}
-+
-+/*
-+ * Extracts ebp, esp and eip values understandable by gdb from the values
-+ * saved by switch_to.
-+ * thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp
-+ * prior to entering switch_to is 8 greater then the value that is saved.
-+ * If switch_to changes, change following code appropriately.
-+ */
-+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
-+{
-+      gdb_regs[_EAX] = 0;
-+      gdb_regs[_EBX] = 0;
-+      gdb_regs[_ECX] = 0;
-+      gdb_regs[_EDX] = 0;
-+      gdb_regs[_ESI] = 0;
-+      gdb_regs[_EDI] = 0;
-+      gdb_regs[_EBP] = *(unsigned long *)p->thread.esp;
-+      gdb_regs[_DS] = __KERNEL_DS;
-+      gdb_regs[_ES] = __KERNEL_DS;
-+      gdb_regs[_PS] = 0;
-+      gdb_regs[_CS] = __KERNEL_CS;
-+      gdb_regs[_PC] = p->thread.eip;
-+      gdb_regs[_ESP] = p->thread.esp;
-+      gdb_regs[_SS] = __KERNEL_DS;
-+      gdb_regs[_FS] = 0xFFFF;
-+      gdb_regs[_GS] = 0xFFFF;
-+}
-+
-+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-+{
-+      regs->eax = gdb_regs[_EAX];
-+      regs->ebx = gdb_regs[_EBX];
-+      regs->ecx = gdb_regs[_ECX];
-+      regs->edx = gdb_regs[_EDX];
-+      regs->esi = gdb_regs[_ESI];
-+      regs->edi = gdb_regs[_EDI];
-+      regs->ebp = gdb_regs[_EBP];
-+      regs->xds = gdb_regs[_DS];
-+      regs->xes = gdb_regs[_ES];
-+      regs->eflags = gdb_regs[_PS];
-+      regs->xcs = gdb_regs[_CS];
-+      regs->eip = gdb_regs[_PC];
-+}
-+
-+static struct hw_breakpoint {
-+      unsigned enabled;
-+      unsigned type;
-+      unsigned len;
-+      unsigned addr;
-+} breakinfo[4] = {
-+      { .enabled = 0 },
-+      { .enabled = 0 },
-+      { .enabled = 0 },
-+      { .enabled = 0 },
-+};
-+
-+static void kgdb_correct_hw_break(void)
-+{
-+      int breakno;
-+      int correctit;
-+      int breakbit;
-+      unsigned long dr7;
-+
-+      get_debugreg(dr7, 7);
-+      correctit = 0;
-+      for (breakno = 0; breakno < 3; breakno++) {
-+              breakbit = 2 << (breakno << 1);
-+              if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
-+                      correctit = 1;
-+                      dr7 |= breakbit;
-+                      dr7 &= ~(0xf0000 << (breakno << 2));
-+                      dr7 |= (((breakinfo[breakno].len << 2) |
-+                               breakinfo[breakno].type) << 16) <<
-+                          (breakno << 2);
-+                      switch (breakno) {
-+                      case 0:
-+                              set_debugreg(breakinfo[breakno].addr, 0);
-+                              break;
-+
-+                      case 1:
-+                              set_debugreg(breakinfo[breakno].addr, 1);
-+                              break;
-+
-+                      case 2:
-+                              set_debugreg(breakinfo[breakno].addr, 2);
-+                              break;
-+
-+                      case 3:
-+                              set_debugreg(breakinfo[breakno].addr, 3);
-+                              break;
-+                      }
-+              } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
-+                      correctit = 1;
-+                      dr7 &= ~breakbit;
-+                      dr7 &= ~(0xf0000 << (breakno << 2));
-+              }
-+      }
-+      if (correctit)
-+              set_debugreg(dr7, 7);
-+}
-+
-+static int kgdb_remove_hw_break(unsigned long addr, int len,
-+                                               enum kgdb_bptype bptype)
-+{
-+      int i, idx = -1;
-+      for (i = 0; i < 4; i++) {
-+              if (breakinfo[i].addr == addr && breakinfo[i].enabled) {
-+                      idx = i;
-+                      break;
-+              }
-+      }
-+      if (idx == -1)
-+              return -1;
-+
-+      breakinfo[idx].enabled = 0;
-+      return 0;
-+}
-+
-+static void kgdb_remove_all_hw_break(void)
-+{
-+      int i;
-+
-+      for (i = 0; i < 4; i++) {
-+              memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint));
-+      }
-+}
-+
-+static int kgdb_set_hw_break(unsigned long addr, int len,
-+                                        enum kgdb_bptype bptype)
-+{
-+      int i, idx = -1;
-+      for (i = 0; i < 4; i++) {
-+              if (!breakinfo[i].enabled) {
-+                      idx = i;
-+                      break;
-+              }
-+      }
-+      if (idx == -1)
-+              return -1;
-+      if (bptype == bp_hardware_breakpoint) {
-+              breakinfo[idx].type = 0;
-+              breakinfo[idx].len = 0;
-+      } else if (bptype == bp_write_watchpoint) {
-+              breakinfo[idx].type = 1;
-+              if (len == 1 || len == 2 || len == 4)
-+                      breakinfo[idx].len = len - 1;
-+              else
-+                      return -1;
-+      } else if (bptype == bp_access_watchpoint) {
-+              breakinfo[idx].type = 3;
-+              if (len == 1 || len == 2 || len == 4)
-+                      breakinfo[idx].len = len - 1;
-+              else
-+                      return -1;
-+      } else
-+              return -1;
-+      breakinfo[idx].enabled = 1;
-+      breakinfo[idx].addr = addr;
-+      return 0;
-+}
-+
-+void kgdb_disable_hw_debug(struct pt_regs *regs)
-+{
-+      /* Disable hardware debugging while we are in kgdb */
-+      set_debugreg(0, 7);
-+}
-+
-+void kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code)
-+{
-+      /* Master processor is completely in the debugger */
-+      gdb_i386vector = e_vector;
-+      gdb_i386errcode = err_code;
-+}
-+
-+#ifdef CONFIG_SMP
-+void kgdb_roundup_cpus(unsigned long flags)
-+{
-+      send_IPI_allbutself(APIC_DM_NMI);
-+}
-+#endif
-+
-+int kgdb_arch_handle_exception(int e_vector, int signo,
-+                             int err_code, char *remcom_in_buffer,
-+                             char *remcom_out_buffer,
-+                             struct pt_regs *linux_regs)
-+{
-+      long addr;
-+      char *ptr;
-+      int newPC, dr6;
-+
-+      switch (remcom_in_buffer[0]) {
-+      case 'c':
-+      case 's':
-+              /* try to read optional parameter, pc unchanged if no parm */
-+              ptr = &remcom_in_buffer[1];
-+              if (kgdb_hex2long(&ptr, &addr))
-+                      linux_regs->eip = addr;
-+              newPC = linux_regs->eip;
-+
-+              /* clear the trace bit */
-+              linux_regs->eflags &= ~TF_MASK;
-+              atomic_set(&cpu_doing_single_step, -1);
-+
-+              /* set the trace bit if we're stepping */
-+              if (remcom_in_buffer[0] == 's') {
-+                      linux_regs->eflags |= TF_MASK;
-+                      debugger_step = 1;
-+                      atomic_set(&cpu_doing_single_step,raw_smp_processor_id());
-+              }
-+
-+              get_debugreg(dr6, 6);
-+              if (!(dr6 & 0x4000)) {
-+                      long breakno;
-+                      for (breakno = 0; breakno < 4; ++breakno) {
-+                              if (dr6 & (1 << breakno) &&
-+                                  breakinfo[breakno].type == 0) {
-+                                      /* Set restore flag */
-+                                      linux_regs->eflags |= X86_EFLAGS_RF;
-+                                      break;
-+                              }
-+                      }
-+              }
-+              set_debugreg(0, 6);
-+              kgdb_correct_hw_break();
-+
-+              return (0);
-+      }                       /* switch */
-+      /* this means that we do not want to exit from the handler */
-+      return -1;
-+}
-+
-+/* Register KGDB with the i386die_chain so that we hook into all of the right
-+ * spots. */
-+static int kgdb_notify(struct notifier_block *self, unsigned long cmd,
-+                     void *ptr)
-+{
-+      struct die_args *args = ptr;
-+      struct pt_regs *regs = args->regs;
-+
-+      /* Bad memory access? */
-+      if (cmd == DIE_PAGE_FAULT_NO_CONTEXT && atomic_read(&debugger_active)
-+              && kgdb_may_fault) {
-+              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
-+              return NOTIFY_STOP;
-+      } else if (cmd == DIE_PAGE_FAULT)
-+              /* A normal page fault, ignore. */
-+              return NOTIFY_DONE;
-+      else if ((cmd == DIE_NMI || cmd == DIE_NMI_IPI ||
-+                        cmd == DIE_NMIWATCHDOG) && atomic_read(&debugger_active)) {
-+              /* CPU roundup */
-+              kgdb_nmihook(raw_smp_processor_id(), regs);
-+              return NOTIFY_STOP;
-+      } else if (cmd == DIE_DEBUG
-+                         && atomic_read(&cpu_doing_single_step) == raw_smp_processor_id()
-+                         && user_mode(regs)) {
-+              /* single step exception from kernel space to user space so
-+               * eat the exception and continue the process
-+               */
-+              printk(KERN_ERR "KGDB: trap/step from kernel to user space, resuming...\n");
-+              kgdb_arch_handle_exception(args->trapnr, args->signr, args->err, "c","",regs);
-+              return NOTIFY_STOP;
-+      } else if (cmd == DIE_NMI_IPI || cmd == DIE_NMI || user_mode(regs) ||
-+                         (cmd == DIE_DEBUG && atomic_read(&debugger_active)))
-+              /* Normal watchdog event or userspace debugging, or spurious
-+               * debug exception, ignore. */
-+              return NOTIFY_DONE;
-+
-+      kgdb_handle_exception(args->trapnr, args->signr, args->err, regs);
-+
-+      return NOTIFY_STOP;
-+}
-+
-+static struct notifier_block kgdb_notifier = {
-+      .notifier_call = kgdb_notify,
-+};
-+
-+int kgdb_arch_init(void)
-+{
-+      register_die_notifier(&kgdb_notifier);
-+      return 0;
-+}
-+
-+/*
-+ * Skip an int3 exception when it occurs after a breakpoint has been
-+ * removed. Backtrack eip by 1 since the int3 would have caused it to
-+ * increment by 1.
-+ */
-+
-+int kgdb_skipexception(int exception, struct pt_regs *regs)
-+{
-+      if (exception == 3 && kgdb_isremovedbreak(regs->eip - 1)) {
-+              regs->eip -= 1;
-+              return 1;
-+      }
-+      return 0;
-+}
-+
-+unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
-+{
-+      if (exception == 3) {
-+              return instruction_pointer(regs) - 1;
-+      }
-+      return instruction_pointer(regs);
-+}
-+
-+struct kgdb_arch arch_kgdb_ops = {
-+      .gdb_bpt_instr = {0xcc},
-+      .flags = KGDB_HW_BREAKPOINT,
-+      .set_hw_breakpoint = kgdb_set_hw_break,
-+      .remove_hw_breakpoint = kgdb_remove_hw_break,
-+      .remove_all_hw_break = kgdb_remove_all_hw_break,
-+      .correct_hw_break = kgdb_correct_hw_break,
-+};
-diff -Nurb linux-2.6.22-570/arch/i386/kernel/process.c linux-2.6.22-590/arch/i386/kernel/process.c
---- linux-2.6.22-570/arch/i386/kernel/process.c        2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/i386/kernel/process.c        2008-01-02 13:56:37.000000000 -0500
-@@ -179,13 +179,13 @@
-       /* endless idle loop with no priority at all */
-       while (1) {
--              tick_nohz_stop_sched_tick();
-               while (!need_resched()) {
-                       void (*idle)(void);
-                       if (__get_cpu_var(cpu_idle_state))
-                               __get_cpu_var(cpu_idle_state) = 0;
-+                      tick_nohz_stop_sched_tick();
-                       check_pgt_cache();
-                       rmb();
-                       idle = pm_idle;
-diff -Nurb linux-2.6.22-570/arch/i386/kernel/setup.c linux-2.6.22-590/arch/i386/kernel/setup.c
---- linux-2.6.22-570/arch/i386/kernel/setup.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/i386/kernel/setup.c  2008-01-02 13:56:37.000000000 -0500
-@@ -124,6 +124,7 @@
- #endif
- extern void early_cpu_init(void);
-+extern void early_trap_init(void);
- extern int root_mountflags;
- unsigned long saved_videomode;
-@@ -514,6 +515,7 @@
-       memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
-       pre_setup_arch_hook();
-       early_cpu_init();
-+      early_trap_init();
-       /*
-        * FIXME: This isn't an official loader_type right
-diff -Nurb linux-2.6.22-570/arch/i386/kernel/signal.c linux-2.6.22-590/arch/i386/kernel/signal.c
---- linux-2.6.22-570/arch/i386/kernel/signal.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/i386/kernel/signal.c 2008-01-02 13:56:37.000000000 -0500
-@@ -199,6 +199,13 @@
-       return eax;
- badframe:
-+      if (show_unhandled_signals && printk_ratelimit())
-+              printk("%s%s[%d] bad frame in sigreturn frame:%p eip:%lx"
-+                     " esp:%lx oeax:%lx\n",
-+                  current->pid > 1 ? KERN_INFO : KERN_EMERG,
-+                  current->comm, current->pid, frame, regs->eip,
-+                  regs->esp, regs->orig_eax);
-+
-       force_sig(SIGSEGV, current);
-       return 0;
- }     
-diff -Nurb linux-2.6.22-570/arch/i386/kernel/syscall_table.S linux-2.6.22-590/arch/i386/kernel/syscall_table.S
---- linux-2.6.22-570/arch/i386/kernel/syscall_table.S  2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/i386/kernel/syscall_table.S  2008-01-02 13:56:37.000000000 -0500
-@@ -323,3 +323,6 @@
-       .long sys_signalfd
-       .long sys_timerfd
-       .long sys_eventfd
-+      .long sys_revokeat
-+      .long sys_frevoke               /* 325 */
-+      .long sys_fallocate
-diff -Nurb linux-2.6.22-570/arch/i386/kernel/traps.c linux-2.6.22-590/arch/i386/kernel/traps.c
---- linux-2.6.22-570/arch/i386/kernel/traps.c  2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/i386/kernel/traps.c  2008-01-02 13:56:37.000000000 -0500
-@@ -97,6 +97,11 @@
- int kstack_depth_to_print = 24;
- static unsigned int code_bytes = 64;
-+#ifdef CONFIG_STACK_UNWIND
-+static int call_trace = 1;
-+#else
-+#define call_trace (-1)
-+#endif
- static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
- {
-@@ -136,6 +141,34 @@
-       return ebp;
- }
-+struct ops_and_data {
-+      struct stacktrace_ops *ops;
-+      void *data;
-+};
-+
-+static asmlinkage int
-+dump_trace_unwind(struct unwind_frame_info *info, void *data)
-+{
-+      struct ops_and_data *oad = (struct ops_and_data *)data;
-+      int n = 0;
-+      unsigned long sp = UNW_SP(info);
-+
-+      if (arch_unw_user_mode(info))
-+              return -1;
-+      while (unwind(info) == 0 && UNW_PC(info)) {
-+              n++;
-+              oad->ops->address(oad->data, UNW_PC(info));
-+              if (arch_unw_user_mode(info))
-+                      break;
-+              if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
-+                  && sp > UNW_SP(info))
-+                      break;
-+              sp = UNW_SP(info);
-+              touch_nmi_watchdog();
-+      }
-+      return n;
-+}
-+
- #define MSG(msg) ops->warning(data, msg)
- void dump_trace(struct task_struct *task, struct pt_regs *regs,
-@@ -147,6 +180,41 @@
-       if (!task)
-               task = current;
-+      if (call_trace >= 0) {
-+              int unw_ret = 0;
-+              struct unwind_frame_info info;
-+              struct ops_and_data oad = { .ops = ops, .data = data };
-+
-+              if (regs) {
-+                      if (unwind_init_frame_info(&info, task, regs) == 0)
-+                              unw_ret = dump_trace_unwind(&info, &oad);
-+              } else if (task == current)
-+                      unw_ret = unwind_init_running(&info, dump_trace_unwind,
-+                                                    &oad);
-+              else {
-+                      if (unwind_init_blocked(&info, task) == 0)
-+                              unw_ret = dump_trace_unwind(&info, &oad);
-+              }
-+              if (unw_ret > 0) {
-+                      if (call_trace == 1 && !arch_unw_user_mode(&info)) {
-+                              ops->warning_symbol(data,
-+                                           "DWARF2 unwinder stuck at %s",
-+                                           UNW_PC(&info));
-+                              if (UNW_SP(&info) >= PAGE_OFFSET) {
-+                                      MSG("Leftover inexact backtrace:");
-+                                      stack = (void *)UNW_SP(&info);
-+                                      if (!stack)
-+                                              return;
-+                                      ebp = UNW_FP(&info);
-+                              } else
-+                                      MSG("Full inexact backtrace again:");
-+                      } else if (call_trace >= 1)
-+                              return;
-+                      else
-+                              MSG("Full inexact backtrace again:");
-+              } else
-+                      MSG("Inexact backtrace:");
-+      }
-       if (!stack) {
-               unsigned long dummy;
-               stack = &dummy;
-@@ -614,6 +682,13 @@
-       current->thread.error_code = error_code;
-       current->thread.trap_no = 13;
-+      if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) &&
-+          printk_ratelimit())
-+              printk(KERN_INFO
-+                  "%s[%d] general protection eip:%lx esp:%lx error:%lx\n",
-+                  current->comm, current->pid,
-+                  regs->eip, regs->esp, error_code);
-+
-       force_sig(SIGSEGV, current);
-       return;
-@@ -854,6 +929,7 @@
-        */
- clear_dr7:
-       set_debugreg(0, 7);
-+      notify_die(DIE_DEBUG, "debug2", regs, condition, error_code, SIGTRAP);
-       return;
- debug_vm86:
-@@ -1118,6 +1194,12 @@
-       _set_gate(n, DESCTYPE_TASK, (void *)0, (gdt_entry<<3));
- }
-+/* Some traps need to be set early. */
-+void __init early_trap_init(void) {
-+      set_intr_gate(1,&debug);
-+      set_system_intr_gate(3, &int3); /* int3 can be called from all */
-+      set_intr_gate(14,&page_fault);
-+}
- void __init trap_init(void)
- {
-@@ -1134,10 +1216,8 @@
- #endif
-       set_trap_gate(0,&divide_error);
--      set_intr_gate(1,&debug);
-       set_intr_gate(2,&nmi);
--      set_system_intr_gate(3, &int3); /* int3/4 can be called from all */
--      set_system_gate(4,&overflow);
-+      set_system_gate(4,&overflow); /* int4/5 can be called from all */
-       set_trap_gate(5,&bounds);
-       set_trap_gate(6,&invalid_op);
-       set_trap_gate(7,&device_not_available);
-@@ -1147,7 +1227,6 @@
-       set_trap_gate(11,&segment_not_present);
-       set_trap_gate(12,&stack_segment);
-       set_trap_gate(13,&general_protection);
--      set_intr_gate(14,&page_fault);
-       set_trap_gate(15,&spurious_interrupt_bug);
-       set_trap_gate(16,&coprocessor_error);
-       set_trap_gate(17,&alignment_check);
-@@ -1204,3 +1283,19 @@
-       return 1;
- }
- __setup("code_bytes=", code_bytes_setup);
-+
-+#ifdef CONFIG_STACK_UNWIND
-+static int __init call_trace_setup(char *s)
-+{
-+      if (strcmp(s, "old") == 0)
-+              call_trace = -1;
-+      else if (strcmp(s, "both") == 0)
-+              call_trace = 0;
-+      else if (strcmp(s, "newfallback") == 0)
-+              call_trace = 1;
-+      else if (strcmp(s, "new") == 2)
-+              call_trace = 2;
-+      return 1;
-+}
-+__setup("call_trace=", call_trace_setup);
-+#endif
-diff -Nurb linux-2.6.22-570/arch/i386/kernel/unwind.S linux-2.6.22-590/arch/i386/kernel/unwind.S
---- linux-2.6.22-570/arch/i386/kernel/unwind.S 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/i386/kernel/unwind.S 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,36 @@
-+/* Assembler support code for dwarf2 unwinder */
-+#include <linux/linkage.h>
-+#include <asm/dwarf2.h>
-+#include <asm/ptrace-abi.h>
-+#include <asm/segment.h>
-+#include <asm/asm-offsets.h>
-+
-+ENTRY(arch_unwind_init_running)
-+      CFI_STARTPROC
-+      movl    4(%esp), %edx
-+      movl    (%esp), %ecx
-+      leal    4(%esp), %eax
-+      movl    %ebx, PT_EBX(%edx)
-+      xorl    %ebx, %ebx
-+      movl    %ebx, PT_ECX(%edx)
-+      movl    %ebx, PT_EDX(%edx)
-+      movl    %esi, PT_ESI(%edx)
-+      movl    %edi, PT_EDI(%edx)
-+      movl    %ebp, PT_EBP(%edx)
-+      movl    %ebx, PT_EAX(%edx)
-+      movl    $__USER_DS, PT_DS(%edx)
-+      movl    $__USER_DS, PT_ES(%edx)
-+      movl    $0, PT_FS(%edx)
-+      movl    %ebx, PT_ORIG_EAX(%edx)
-+      movl    %ecx, PT_EIP(%edx)
-+      movl    12(%esp), %ecx
-+      movl    $__KERNEL_CS, PT_CS(%edx)
-+      movl    %ebx, PT_EFLAGS(%edx)
-+      movl    %eax, PT_OLDESP(%edx)
-+      movl    8(%esp), %eax
-+      movl    %ecx, 8(%esp)
-+      movl    PT_EBX(%edx), %ebx
-+      movl    $__KERNEL_DS, PT_OLDSS(%edx)
-+      jmpl    *%eax
-+      CFI_ENDPROC
-+ENDPROC(arch_unwind_init_running)
-diff -Nurb linux-2.6.22-570/arch/i386/mach-voyager/voyager_thread.c linux-2.6.22-590/arch/i386/mach-voyager/voyager_thread.c
---- linux-2.6.22-570/arch/i386/mach-voyager/voyager_thread.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/i386/mach-voyager/voyager_thread.c   2008-01-02 13:56:37.000000000 -0500
-@@ -52,7 +52,7 @@
-               NULL,
-       };
--      if ((ret = call_usermodehelper(argv[0], argv, envp, 1)) != 0) {
-+      if ((ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC)) != 0) {
-               printk(KERN_ERR "Voyager failed to run \"%s\": %i\n",
-                      string, ret);
-       }
-diff -Nurb linux-2.6.22-570/arch/i386/mm/fault.c linux-2.6.22-590/arch/i386/mm/fault.c
---- linux-2.6.22-570/arch/i386/mm/fault.c      2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/i386/mm/fault.c      2008-01-02 13:56:37.000000000 -0500
-@@ -284,6 +284,8 @@
-       return 0;
- }
-+int show_unhandled_signals = 1;
-+
- /*
-  * This routine handles page faults.  It determines the address,
-  * and the problem, and then passes it off to one of the appropriate
-@@ -471,6 +473,14 @@
-               if (is_prefetch(regs, address, error_code))
-                       return;
-+              if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
-+                  printk_ratelimit()) {
-+                      printk("%s%s[%d]: segfault at %08lx eip %08lx "
-+                          "esp %08lx error %lx\n",
-+                          tsk->pid > 1 ? KERN_INFO : KERN_EMERG,
-+                          tsk->comm, tsk->pid, address, regs->eip,
-+                          regs->esp, error_code);
-+              }
-               tsk->thread.cr2 = address;
-               /* Kernel addresses are always protection faults */
-               tsk->thread.error_code = error_code | (address >= TASK_SIZE);
-@@ -508,6 +518,10 @@
-       if (is_prefetch(regs, address, error_code))
-               return;
-+      if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs,
-+                              error_code, 14, SIGSEGV) == NOTIFY_STOP)
-+              return;
-+
- /*
-  * Oops. The kernel tried to access some bad page. We'll have to
-  * terminate things with extreme prejudice.
-diff -Nurb linux-2.6.22-570/arch/ia64/hp/sim/simeth.c linux-2.6.22-590/arch/ia64/hp/sim/simeth.c
---- linux-2.6.22-570/arch/ia64/hp/sim/simeth.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ia64/hp/sim/simeth.c 2008-01-02 13:56:37.000000000 -0500
-@@ -300,6 +300,9 @@
-               return NOTIFY_DONE;
-       }
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE;
-       /*
-diff -Nurb linux-2.6.22-570/arch/ia64/kernel/Makefile linux-2.6.22-590/arch/ia64/kernel/Makefile
---- linux-2.6.22-570/arch/ia64/kernel/Makefile 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ia64/kernel/Makefile 2008-01-02 13:56:37.000000000 -0500
-@@ -35,6 +35,7 @@
- obj-$(CONFIG_PCI_MSI)         += msi_ia64.o
- mca_recovery-y                        += mca_drv.o mca_drv_asm.o
- obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o
-+obj-$(CONFIG_KGDB)            += kgdb.o kgdb-jmp.o
- obj-$(CONFIG_IA64_ESI)                += esi.o
- ifneq ($(CONFIG_IA64_ESI),)
-diff -Nurb linux-2.6.22-570/arch/ia64/kernel/kgdb-jmp.S linux-2.6.22-590/arch/ia64/kernel/kgdb-jmp.S
---- linux-2.6.22-570/arch/ia64/kernel/kgdb-jmp.S       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/ia64/kernel/kgdb-jmp.S       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,238 @@
-+/* setjmp() and longjmp() assembler support for kdb on ia64.
-+
-+   This code was copied from glibc CVS as of 2001-06-27 and modified where
-+   necessary to fit the kernel.
-+   Keith Owens <kaos@melbourne.sgi.com> 2001-06-27
-+ */
-+
-+/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
-+   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Library General Public License as
-+   published by the Free Software Foundation; either version 2 of the
-+   License, or (at your option) any later version.
-+
-+   The GNU C Library 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
-+   Library General Public License for more details.
-+
-+   You should have received a copy of the GNU Library General Public
-+   License along with the GNU C Library; see the file COPYING.LIB.  If
-+   not, write to the Free Software Foundation, Inc.,
-+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+*/
-+
-+#include <asm/asmmacro.h>
-+GLOBAL_ENTRY(kgdb_fault_setjmp)
-+      .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
-+      alloc loc1=ar.pfs,2,2,2,0
-+      mov r16=ar.unat
-+      ;;
-+      mov r17=ar.fpsr
-+      mov r2=in0
-+      add r3=8,in0
-+      ;;
-+.mem.offset 0,0;
-+      st8.spill.nta [r2]=sp,16        // r12 (sp)
-+.mem.offset 8,0;
-+      st8.spill.nta [r3]=gp,16        // r1 (gp)
-+      ;;
-+      st8.nta [r2]=r16,16             // save caller's unat
-+      st8.nta [r3]=r17,16             // save fpsr
-+      add r8=0xa0,in0
-+      ;;
-+.mem.offset 160,0;
-+      st8.spill.nta [r2]=r4,16        // r4
-+.mem.offset 168,0;
-+      st8.spill.nta [r3]=r5,16        // r5
-+      add r9=0xb0,in0
-+      ;;
-+      stf.spill.nta [r8]=f2,32
-+      stf.spill.nta [r9]=f3,32
-+      mov loc0=rp
-+      .body
-+      ;;
-+      stf.spill.nta [r8]=f4,32
-+      stf.spill.nta [r9]=f5,32
-+      mov r17=b1
-+      ;;
-+      stf.spill.nta [r8]=f16,32
-+      stf.spill.nta [r9]=f17,32
-+      mov r18=b2
-+      ;;
-+      stf.spill.nta [r8]=f18,32
-+      stf.spill.nta [r9]=f19,32
-+      mov r19=b3
-+      ;;
-+      stf.spill.nta [r8]=f20,32
-+      stf.spill.nta [r9]=f21,32
-+      mov r20=b4
-+      ;;
-+      stf.spill.nta [r8]=f22,32
-+      stf.spill.nta [r9]=f23,32
-+      mov r21=b5
-+      ;;
-+      stf.spill.nta [r8]=f24,32
-+      stf.spill.nta [r9]=f25,32
-+      mov r22=ar.lc
-+      ;;
-+      stf.spill.nta [r8]=f26,32
-+      stf.spill.nta [r9]=f27,32
-+      mov r24=pr
-+      ;;
-+      stf.spill.nta [r8]=f28,32
-+      stf.spill.nta [r9]=f29,32
-+      ;;
-+      stf.spill.nta [r8]=f30
-+      stf.spill.nta [r9]=f31
-+
-+.mem.offset 0,0;
-+      st8.spill.nta [r2]=r6,16        // r6
-+.mem.offset 8,0;
-+      st8.spill.nta [r3]=r7,16        // r7
-+      ;;
-+      mov r23=ar.bsp
-+      mov r25=ar.unat
-+      st8.nta [r2]=loc0,16            // b0
-+      st8.nta [r3]=r17,16             // b1
-+      ;;
-+      st8.nta [r2]=r18,16             // b2
-+      st8.nta [r3]=r19,16             // b3
-+      ;;
-+      st8.nta [r2]=r20,16             // b4
-+      st8.nta [r3]=r21,16             // b5
-+      ;;
-+      st8.nta [r2]=loc1,16            // ar.pfs
-+      st8.nta [r3]=r22,16             // ar.lc
-+      ;;
-+      st8.nta [r2]=r24,16             // pr
-+      st8.nta [r3]=r23,16             // ar.bsp
-+      ;;
-+      st8.nta [r2]=r25                // ar.unat
-+      st8.nta [r3]=in0                // &__jmp_buf
-+      mov r8=0
-+      mov rp=loc0
-+      mov ar.pfs=loc1
-+      br.ret.sptk.few rp
-+END(kdba_setjmp)
-+#define       pPos    p6      /* is rotate count positive? */
-+#define       pNeg    p7      /* is rotate count negative? */
-+GLOBAL_ENTRY(kgdb_fault_longjmp)
-+      alloc r8=ar.pfs,2,1,0,0
-+      mov r27=ar.rsc
-+      add r2=0x98,in0         // r2 <- &jmpbuf.orig_jmp_buf_addr
-+      ;;
-+      ld8 r8=[r2],-16         // r8 <- orig_jmp_buf_addr
-+      mov r10=ar.bsp
-+      and r11=~0x3,r27        // clear ar.rsc.mode
-+      ;;
-+      flushrs                 // flush dirty regs to backing store (must be first in insn grp)
-+      ld8 r23=[r2],8          // r23 <- jmpbuf.ar_bsp
-+      sub r8=r8,in0           // r8 <- &orig_jmpbuf - &jmpbuf
-+      ;;
-+      ld8 r25=[r2]            // r25 <- jmpbuf.ar_unat
-+      extr.u r8=r8,3,6        // r8 <- (&orig_jmpbuf - &jmpbuf)/8 & 0x3f
-+      ;;
-+      cmp.lt pNeg,pPos=r8,r0
-+      mov r2=in0
-+      ;;
-+(pPos)        mov r16=r8
-+(pNeg)        add r16=64,r8
-+(pPos)        sub r17=64,r8
-+(pNeg)        sub r17=r0,r8
-+      ;;
-+      mov ar.rsc=r11          // put RSE in enforced lazy mode
-+      shr.u r8=r25,r16
-+      add r3=8,in0            // r3 <- &jmpbuf.r1
-+      shl r9=r25,r17
-+      ;;
-+      or r25=r8,r9
-+      ;;
-+      mov r26=ar.rnat
-+      mov ar.unat=r25         // setup ar.unat (NaT bits for r1, r4-r7, and r12)
-+      ;;
-+      ld8.fill.nta sp=[r2],16 // r12 (sp)
-+      ld8.fill.nta gp=[r3],16         // r1 (gp)
-+      dep r11=-1,r23,3,6      // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp)
-+      ;;
-+      ld8.nta r16=[r2],16             // caller's unat
-+      ld8.nta r17=[r3],16             // fpsr
-+      ;;
-+      ld8.fill.nta r4=[r2],16 // r4
-+      ld8.fill.nta r5=[r3],16         // r5 (gp)
-+      cmp.geu p8,p0=r10,r11   // p8 <- (ar.bsp >= jmpbuf.ar_bsp)
-+      ;;
-+      ld8.fill.nta r6=[r2],16 // r6
-+      ld8.fill.nta r7=[r3],16         // r7
-+      ;;
-+      mov ar.unat=r16                 // restore caller's unat
-+      mov ar.fpsr=r17                 // restore fpsr
-+      ;;
-+      ld8.nta r16=[r2],16             // b0
-+      ld8.nta r17=[r3],16             // b1
-+      ;;
-+(p8)  ld8 r26=[r11]           // r26 <- *ia64_rse_rnat_addr(jmpbuf.ar_bsp)
-+      mov ar.bspstore=r23     // restore ar.bspstore
-+      ;;
-+      ld8.nta r18=[r2],16             // b2
-+      ld8.nta r19=[r3],16             // b3
-+      ;;
-+      ld8.nta r20=[r2],16             // b4
-+      ld8.nta r21=[r3],16             // b5
-+      ;;
-+      ld8.nta r11=[r2],16             // ar.pfs
-+      ld8.nta r22=[r3],56             // ar.lc
-+      ;;
-+      ld8.nta r24=[r2],32             // pr
-+      mov b0=r16
-+      ;;
-+      ldf.fill.nta f2=[r2],32
-+      ldf.fill.nta f3=[r3],32
-+      mov b1=r17
-+      ;;
-+      ldf.fill.nta f4=[r2],32
-+      ldf.fill.nta f5=[r3],32
-+      mov b2=r18
-+      ;;
-+      ldf.fill.nta f16=[r2],32
-+      ldf.fill.nta f17=[r3],32
-+      mov b3=r19
-+      ;;
-+      ldf.fill.nta f18=[r2],32
-+      ldf.fill.nta f19=[r3],32
-+      mov b4=r20
-+      ;;
-+      ldf.fill.nta f20=[r2],32
-+      ldf.fill.nta f21=[r3],32
-+      mov b5=r21
-+      ;;
-+      ldf.fill.nta f22=[r2],32
-+      ldf.fill.nta f23=[r3],32
-+      mov ar.lc=r22
-+      ;;
-+      ldf.fill.nta f24=[r2],32
-+      ldf.fill.nta f25=[r3],32
-+      cmp.eq p8,p9=0,in1
-+      ;;
-+      ldf.fill.nta f26=[r2],32
-+      ldf.fill.nta f27=[r3],32
-+      mov ar.pfs=r11
-+      ;;
-+      ldf.fill.nta f28=[r2],32
-+      ldf.fill.nta f29=[r3],32
-+      ;;
-+      ldf.fill.nta f30=[r2]
-+      ldf.fill.nta f31=[r3]
-+(p8)  mov r8=1
-+
-+      mov ar.rnat=r26         // restore ar.rnat
-+      ;;
-+      mov ar.rsc=r27          // restore ar.rsc
-+(p9)  mov r8=in1
-+
-+      invala                  // virt. -> phys. regnum mapping may change
-+      mov pr=r24,-1
-+      br.ret.sptk.few rp
-+END(kgdb_fault_longjmp)
-diff -Nurb linux-2.6.22-570/arch/ia64/kernel/kgdb.c linux-2.6.22-590/arch/ia64/kernel/kgdb.c
---- linux-2.6.22-570/arch/ia64/kernel/kgdb.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/ia64/kernel/kgdb.c   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,944 @@
-+/*
-+ *
-+ * 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, 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.
-+ *
-+ */
-+
-+/*
-+ * Copyright (C) 2000-2001 VERITAS Software Corporation.
-+ * (c) Copyright 2005 Hewlett-Packard Development Company, L.P.
-+ *     Bob Picco <bob.picco@hp.com>
-+ */
-+/*
-+ *  Contributor:     Lake Stevens Instrument Division$
-+ *  Written by:      Glenn Engel $
-+ *  Updated by:            Amit Kale<akale@veritas.com>
-+ *  Modified for 386 by Jim Kingdon, Cygnus Support.
-+ *  Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe <dave@gcom.com>
-+ */
-+
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/smp.h>
-+#include <linux/spinlock.h>
-+#include <linux/delay.h>
-+#include <asm/system.h>
-+#include <asm/ptrace.h>               /* for linux pt_regs struct */
-+#include <asm/unwind.h>
-+#include <asm/rse.h>
-+#include <linux/kgdb.h>
-+#include <linux/init.h>
-+#include <asm/cacheflush.h>
-+#include <asm/kdebug.h>
-+
-+#define NUM_REGS 590
-+#define REGISTER_BYTES (NUM_REGS*8+128*8)
-+#define REGISTER_BYTE(N) (((N) * 8)                                    \
-+      + ((N) <= IA64_FR0_REGNUM ?                                     \
-+      0 : 8 * (((N) > IA64_FR127_REGNUM) ? 128 : (N) - IA64_FR0_REGNUM)))
-+#define REGISTER_SIZE(N)                                               \
-+      (((N) >= IA64_FR0_REGNUM && (N) <= IA64_FR127_REGNUM) ? 16 : 8)
-+#define IA64_GR0_REGNUM         0
-+#define IA64_FR0_REGNUM         128
-+#define IA64_FR127_REGNUM       (IA64_FR0_REGNUM+127)
-+#define IA64_PR0_REGNUM         256
-+#define IA64_BR0_REGNUM         320
-+#define IA64_VFP_REGNUM         328
-+#define IA64_PR_REGNUM          330
-+#define IA64_IP_REGNUM          331
-+#define IA64_PSR_REGNUM         332
-+#define IA64_CFM_REGNUM         333
-+#define IA64_AR0_REGNUM         334
-+#define IA64_NAT0_REGNUM        462
-+#define IA64_NAT31_REGNUM       (IA64_NAT0_REGNUM+31)
-+#define IA64_NAT32_REGNUM       (IA64_NAT0_REGNUM+32)
-+#define IA64_RSC_REGNUM               (IA64_AR0_REGNUM+16)
-+#define IA64_BSP_REGNUM               (IA64_AR0_REGNUM+17)
-+#define IA64_BSPSTORE_REGNUM  (IA64_AR0_REGNUM+18)
-+#define IA64_RNAT_REGNUM      (IA64_AR0_REGNUM+19)
-+#define IA64_FCR_REGNUM               (IA64_AR0_REGNUM+21)
-+#define IA64_EFLAG_REGNUM     (IA64_AR0_REGNUM+24)
-+#define IA64_CSD_REGNUM               (IA64_AR0_REGNUM+25)
-+#define IA64_SSD_REGNUM               (IA64_AR0_REGNUM+26)
-+#define IA64_CFLG_REGNUM      (IA64_AR0_REGNUM+27)
-+#define IA64_FSR_REGNUM               (IA64_AR0_REGNUM+28)
-+#define IA64_FIR_REGNUM               (IA64_AR0_REGNUM+29)
-+#define IA64_FDR_REGNUM               (IA64_AR0_REGNUM+30)
-+#define IA64_CCV_REGNUM               (IA64_AR0_REGNUM+32)
-+#define IA64_UNAT_REGNUM      (IA64_AR0_REGNUM+36)
-+#define IA64_FPSR_REGNUM      (IA64_AR0_REGNUM+40)
-+#define IA64_ITC_REGNUM               (IA64_AR0_REGNUM+44)
-+#define IA64_PFS_REGNUM               (IA64_AR0_REGNUM+64)
-+#define IA64_LC_REGNUM                (IA64_AR0_REGNUM+65)
-+#define IA64_EC_REGNUM                (IA64_AR0_REGNUM+66)
-+
-+#define       REGISTER_INDEX(N)       (REGISTER_BYTE(N) / sizeof (unsigned long))
-+#define BREAK_INSTR_ALIGN     (~0xfULL)
-+
-+#define       ptoff(V)        ((unsigned int) &((struct pt_regs *)0x0)->V)
-+struct reg_to_ptreg_index {
-+      unsigned int reg;
-+      unsigned int ptregoff;
-+};
-+
-+static struct reg_to_ptreg_index gr_reg_to_ptreg_index[] = {
-+      {IA64_GR0_REGNUM + 1, ptoff(r1)},
-+      {IA64_GR0_REGNUM + 2, ptoff(r2)},
-+      {IA64_GR0_REGNUM + 3, ptoff(r3)},
-+      {IA64_GR0_REGNUM + 8, ptoff(r8)},
-+      {IA64_GR0_REGNUM + 9, ptoff(r9)},
-+      {IA64_GR0_REGNUM + 10, ptoff(r10)},
-+      {IA64_GR0_REGNUM + 11, ptoff(r11)},
-+      {IA64_GR0_REGNUM + 12, ptoff(r12)},
-+      {IA64_GR0_REGNUM + 13, ptoff(r13)},
-+      {IA64_GR0_REGNUM + 14, ptoff(r14)},
-+      {IA64_GR0_REGNUM + 15, ptoff(r15)},
-+      {IA64_GR0_REGNUM + 16, ptoff(r16)},
-+      {IA64_GR0_REGNUM + 17, ptoff(r17)},
-+      {IA64_GR0_REGNUM + 18, ptoff(r18)},
-+      {IA64_GR0_REGNUM + 19, ptoff(r19)},
-+      {IA64_GR0_REGNUM + 20, ptoff(r20)},
-+      {IA64_GR0_REGNUM + 21, ptoff(r21)},
-+      {IA64_GR0_REGNUM + 22, ptoff(r22)},
-+      {IA64_GR0_REGNUM + 23, ptoff(r23)},
-+      {IA64_GR0_REGNUM + 24, ptoff(r24)},
-+      {IA64_GR0_REGNUM + 25, ptoff(r25)},
-+      {IA64_GR0_REGNUM + 26, ptoff(r26)},
-+      {IA64_GR0_REGNUM + 27, ptoff(r27)},
-+      {IA64_GR0_REGNUM + 28, ptoff(r28)},
-+      {IA64_GR0_REGNUM + 29, ptoff(r29)},
-+      {IA64_GR0_REGNUM + 30, ptoff(r30)},
-+      {IA64_GR0_REGNUM + 31, ptoff(r31)},
-+};
-+
-+static struct reg_to_ptreg_index br_reg_to_ptreg_index[] = {
-+      {IA64_BR0_REGNUM, ptoff(b0)},
-+      {IA64_BR0_REGNUM + 6, ptoff(b6)},
-+      {IA64_BR0_REGNUM + 7, ptoff(b7)},
-+};
-+
-+static struct reg_to_ptreg_index ar_reg_to_ptreg_index[] = {
-+      {IA64_PFS_REGNUM, ptoff(ar_pfs)},
-+      {IA64_UNAT_REGNUM, ptoff(ar_unat)},
-+      {IA64_RNAT_REGNUM, ptoff(ar_rnat)},
-+      {IA64_BSPSTORE_REGNUM, ptoff(ar_bspstore)},
-+      {IA64_RSC_REGNUM, ptoff(ar_rsc)},
-+      {IA64_CSD_REGNUM, ptoff(ar_csd)},
-+      {IA64_SSD_REGNUM, ptoff(ar_ssd)},
-+      {IA64_FPSR_REGNUM, ptoff(ar_fpsr)},
-+      {IA64_CCV_REGNUM, ptoff(ar_ccv)},
-+};
-+
-+extern atomic_t cpu_doing_single_step;
-+
-+static int kgdb_gr_reg(int regnum, struct unw_frame_info *info,
-+      unsigned long *reg, int rw)
-+{
-+      char nat;
-+
-+      if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) ||
-+              (regnum >= (IA64_GR0_REGNUM + 4) &&
-+              regnum <= (IA64_GR0_REGNUM + 7)))
-+              return !unw_access_gr(info, regnum - IA64_GR0_REGNUM,
-+              reg, &nat, rw);
-+      else
-+              return 0;
-+}
-+static int kgdb_gr_ptreg(int regnum, struct pt_regs * ptregs,
-+      struct unw_frame_info *info, unsigned long *reg, int rw)
-+{
-+      int i, result = 1;
-+      char nat;
-+
-+      if (!((regnum >= (IA64_GR0_REGNUM + 2) &&
-+              regnum <= (IA64_GR0_REGNUM + 3)) ||
-+              (regnum >= (IA64_GR0_REGNUM + 8) &&
-+              regnum <= (IA64_GR0_REGNUM + 15)) ||
-+              (regnum >= (IA64_GR0_REGNUM + 16) &&
-+              regnum <= (IA64_GR0_REGNUM + 31))))
-+              return 0;
-+      else if (rw && ptregs) {
-+              for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++)
-+                      if (gr_reg_to_ptreg_index[i].reg == regnum) {
-+                              *((unsigned long *)(((void *)ptregs) +
-+                              gr_reg_to_ptreg_index[i].ptregoff)) = *reg;
-+                              break;
-+                      }
-+      } else if (!rw && ptregs) {
-+              for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++)
-+                      if (gr_reg_to_ptreg_index[i].reg == regnum) {
-+                              *reg = *((unsigned long *)
-+                              (((void *)ptregs) +
-+                               gr_reg_to_ptreg_index[i].ptregoff));
-+                              break;
-+                      }
-+      } else
-+              result = !unw_access_gr(info, regnum - IA64_GR0_REGNUM,
-+                                      reg, &nat, rw);
-+      return result;
-+}
-+
-+static int kgdb_br_reg(int regnum, struct pt_regs * ptregs,
-+      struct unw_frame_info *info, unsigned long *reg, int rw)
-+{
-+      int i, result = 1;
-+
-+      if (!(regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7)))
-+              return 0;
-+
-+      switch (regnum) {
-+      case IA64_BR0_REGNUM:
-+      case IA64_BR0_REGNUM + 6:
-+      case IA64_BR0_REGNUM + 7:
-+              if (rw) {
-+                      for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++)
-+                              if (br_reg_to_ptreg_index[i].reg == regnum) {
-+                                      *((unsigned long *)
-+                                      (((void *)ptregs) +
-+                                      br_reg_to_ptreg_index[i].ptregoff)) =
-+                                      *reg;
-+                                      break;
-+                              }
-+              } else
-+                      for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++)
-+                              if (br_reg_to_ptreg_index[i].reg == regnum) {
-+                                              *reg = *((unsigned long *)
-+                                              (((void *)ptregs) +
-+                                              br_reg_to_ptreg_index[i].
-+                                              ptregoff));
-+                                              break;
-+                              }
-+              break;
-+      case IA64_BR0_REGNUM + 1:
-+      case IA64_BR0_REGNUM + 2:
-+      case IA64_BR0_REGNUM + 3:
-+      case IA64_BR0_REGNUM + 4:
-+      case IA64_BR0_REGNUM + 5:
-+              result = !unw_access_br(info, regnum - IA64_BR0_REGNUM,
-+                              reg, rw);
-+              break;
-+      }
-+
-+      return result;
-+}
-+
-+static int kgdb_fr_reg(int regnum, char *inbuffer, struct pt_regs * ptregs,
-+      struct unw_frame_info *info, unsigned long *reg,
-+      struct ia64_fpreg *freg, int rw)
-+{
-+      int result = 1;
-+
-+      if (!(regnum >= IA64_FR0_REGNUM && regnum <= (IA64_FR0_REGNUM + 127)))
-+              return 0;
-+
-+      switch (regnum) {
-+      case IA64_FR0_REGNUM + 6:
-+      case IA64_FR0_REGNUM + 7:
-+      case IA64_FR0_REGNUM + 8:
-+      case IA64_FR0_REGNUM + 9:
-+      case IA64_FR0_REGNUM + 10:
-+      case IA64_FR0_REGNUM + 11:
-+      case IA64_FR0_REGNUM + 12:
-+              if (rw) {
-+                      char *ptr = inbuffer;
-+
-+                      freg->u.bits[0] = *reg;
-+                      kgdb_hex2long(&ptr, &freg->u.bits[1]);
-+                      *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) =
-+                              *freg;
-+                      break;
-+              } else if (!ptregs)
-+                      result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM,
-+                              freg, rw);
-+              else
-+                      *freg =
-+                      *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6)));
-+              break;
-+      default:
-+              if (!rw)
-+                      result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM,
-+                              freg, rw);
-+              else
-+                      result = 0;
-+              break;
-+      }
-+
-+      return result;
-+}
-+
-+static int kgdb_ar_reg(int regnum, struct pt_regs * ptregs,
-+      struct unw_frame_info *info, unsigned long *reg, int rw)
-+{
-+      int result = 0, i;
-+
-+      if (!(regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM))
-+              return 0;
-+
-+      if (rw && ptregs) {
-+              for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++)
-+                      if (ar_reg_to_ptreg_index[i].reg == regnum) {
-+                              *((unsigned long *) (((void *)ptregs) +
-+                              ar_reg_to_ptreg_index[i].ptregoff)) =
-+                                      *reg;
-+                              result = 1;
-+                              break;
-+                      }
-+      } else if (ptregs) {
-+              for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++)
-+                      if (ar_reg_to_ptreg_index[i].reg == regnum) {
-+                              *reg = *((unsigned long *) (((void *)ptregs) +
-+                                      ar_reg_to_ptreg_index[i].ptregoff));
-+                                      result = 1;
-+                              break;
-+                      }
-+      }
-+
-+      if (result)
-+              return result;
-+
-+       result = 1;
-+
-+      switch (regnum) {
-+      case IA64_CSD_REGNUM:
-+              result = !unw_access_ar(info, UNW_AR_CSD, reg, rw);
-+              break;
-+      case IA64_SSD_REGNUM:
-+              result = !unw_access_ar(info, UNW_AR_SSD, reg, rw);
-+              break;
-+      case IA64_UNAT_REGNUM:
-+              result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
-+              break;
-+              case IA64_RNAT_REGNUM:
-+              result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
-+              break;
-+      case IA64_BSPSTORE_REGNUM:
-+              result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
-+              break;
-+      case IA64_PFS_REGNUM:
-+              result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
-+              break;
-+      case IA64_LC_REGNUM:
-+              result = !unw_access_ar(info, UNW_AR_LC, reg, rw);
-+              break;
-+      case IA64_EC_REGNUM:
-+              result = !unw_access_ar(info, UNW_AR_EC, reg, rw);
-+              break;
-+      case IA64_FPSR_REGNUM:
-+              result = !unw_access_ar(info, UNW_AR_FPSR, reg, rw);
-+              break;
-+      case IA64_RSC_REGNUM:
-+              result = !unw_access_ar(info, UNW_AR_RSC, reg, rw);
-+              break;
-+      case IA64_CCV_REGNUM:
-+              result = !unw_access_ar(info, UNW_AR_CCV, reg, rw);
-+              break;
-+      default:
-+              result = 0;
-+      }
-+
-+      return result;
-+}
-+
-+void kgdb_get_reg(char *outbuffer, int regnum, struct unw_frame_info *info,
-+      struct pt_regs *ptregs)
-+{
-+      unsigned long reg, size = 0, *mem = &reg;
-+      struct ia64_fpreg freg;
-+
-+      if (kgdb_gr_reg(regnum, info, &reg, 0) ||
-+              kgdb_gr_ptreg(regnum, ptregs, info, &reg, 0) ||
-+              kgdb_br_reg(regnum, ptregs, info, &reg, 0) ||
-+              kgdb_ar_reg(regnum, ptregs, info, &reg, 0))
-+                      size = sizeof(reg);
-+      else if (kgdb_fr_reg(regnum, NULL, ptregs, info, &reg, &freg, 0)) {
-+              size = sizeof(freg);
-+              mem = (unsigned long *)&freg;
-+      } else if (regnum == IA64_IP_REGNUM) {
-+              if (!ptregs) {
-+                      unw_get_ip(info, &reg);
-+                      size = sizeof(reg);
-+              } else {
-+                      reg = ptregs->cr_iip;
-+                      size = sizeof(reg);
-+              }
-+      } else if (regnum == IA64_CFM_REGNUM) {
-+              if (!ptregs)
-+                      unw_get_cfm(info, &reg);
-+              else
-+                      reg = ptregs->cr_ifs;
-+              size = sizeof(reg);
-+      } else if (regnum == IA64_PSR_REGNUM) {
-+              if (!ptregs && kgdb_usethread)
-+                      ptregs = (struct pt_regs *)
-+                      ((unsigned long)kgdb_usethread +
-+                      IA64_STK_OFFSET) - 1;
-+              if (ptregs)
-+                      reg = ptregs->cr_ipsr;
-+              size = sizeof(reg);
-+      } else if (regnum == IA64_PR_REGNUM) {
-+              if (ptregs)
-+                      reg = ptregs->pr;
-+              else
-+                      unw_access_pr(info, &reg, 0);
-+              size = sizeof(reg);
-+      } else if (regnum == IA64_BSP_REGNUM) {
-+              unw_get_bsp(info, &reg);
-+              size = sizeof(reg);
-+      }
-+
-+      if (size) {
-+              kgdb_mem2hex((char *) mem, outbuffer, size);
-+              outbuffer[size*2] = 0;
-+      }
-+      else
-+              strcpy(outbuffer, "E0");
-+
-+      return;
-+}
-+
-+void kgdb_put_reg(char *inbuffer, char *outbuffer, int regnum,
-+                struct unw_frame_info *info, struct pt_regs *ptregs)
-+{
-+      unsigned long reg;
-+      struct ia64_fpreg freg;
-+      char *ptr = inbuffer;
-+
-+      kgdb_hex2long(&ptr, &reg);
-+      strcpy(outbuffer, "OK");
-+
-+      if (kgdb_gr_reg(regnum, info, &reg, 1) ||
-+              kgdb_gr_ptreg(regnum, ptregs, info, &reg, 1) ||
-+              kgdb_br_reg(regnum, ptregs, info, &reg, 1) ||
-+              kgdb_fr_reg(regnum, inbuffer, ptregs, info, &reg, &freg, 1) ||
-+              kgdb_ar_reg(regnum, ptregs, info, &reg, 1)) ;
-+      else if (regnum == IA64_IP_REGNUM)
-+              ptregs->cr_iip = reg;
-+      else if (regnum == IA64_CFM_REGNUM)
-+              ptregs->cr_ifs = reg;
-+      else if (regnum == IA64_PSR_REGNUM)
-+              ptregs->cr_ipsr = reg;
-+      else if (regnum == IA64_PR_REGNUM)
-+              ptregs->pr = reg;
-+      else
-+              strcpy(outbuffer, "E01");
-+      return;
-+}
-+
-+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-+{
-+}
-+
-+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
-+{
-+}
-+
-+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-+{
-+
-+}
-+
-+#define       MAX_HW_BREAKPOINT       (20)
-+long hw_break_total_dbr, hw_break_total_ibr;
-+#define       HW_BREAKPOINT   (hw_break_total_dbr + hw_break_total_ibr)
-+#define       WATCH_INSTRUCTION       0x0
-+#define WATCH_WRITE           0x1
-+#define       WATCH_READ              0x2
-+#define       WATCH_ACCESS            0x3
-+
-+#define       HWCAP_DBR       ((1 << WATCH_WRITE) | (1 << WATCH_READ))
-+#define       HWCAP_IBR       (1 << WATCH_INSTRUCTION)
-+struct hw_breakpoint {
-+      unsigned enabled;
-+      unsigned long capable;
-+      unsigned long type;
-+      unsigned long mask;
-+      unsigned long addr;
-+} *breakinfo;
-+
-+static struct hw_breakpoint hwbreaks[MAX_HW_BREAKPOINT];
-+
-+enum instruction_type { A, I, M, F, B, L, X, u };
-+
-+static enum instruction_type bundle_encoding[32][3] = {
-+      {M, I, I},              /* 00 */
-+      {M, I, I},              /* 01 */
-+      {M, I, I},              /* 02 */
-+      {M, I, I},              /* 03 */
-+      {M, L, X},              /* 04 */
-+      {M, L, X},              /* 05 */
-+      {u, u, u},              /* 06 */
-+      {u, u, u},              /* 07 */
-+      {M, M, I},              /* 08 */
-+      {M, M, I},              /* 09 */
-+      {M, M, I},              /* 0A */
-+      {M, M, I},              /* 0B */
-+      {M, F, I},              /* 0C */
-+      {M, F, I},              /* 0D */
-+      {M, M, F},              /* 0E */
-+      {M, M, F},              /* 0F */
-+      {M, I, B},              /* 10 */
-+      {M, I, B},              /* 11 */
-+      {M, B, B},              /* 12 */
-+      {M, B, B},              /* 13 */
-+      {u, u, u},              /* 14 */
-+      {u, u, u},              /* 15 */
-+      {B, B, B},              /* 16 */
-+      {B, B, B},              /* 17 */
-+      {M, M, B},              /* 18 */
-+      {M, M, B},              /* 19 */
-+      {u, u, u},              /* 1A */
-+      {u, u, u},              /* 1B */
-+      {M, F, B},              /* 1C */
-+      {M, F, B},              /* 1D */
-+      {u, u, u},              /* 1E */
-+      {u, u, u},              /* 1F */
-+};
-+
-+int kgdb_validate_break_address(unsigned long addr)
-+{
-+      int error;
-+      char tmp_variable[BREAK_INSTR_SIZE];
-+      error = kgdb_get_mem((char *)(addr & BREAK_INSTR_ALIGN), tmp_variable,
-+              BREAK_INSTR_SIZE);
-+      return error;
-+}
-+
-+int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
-+{
-+      extern unsigned long _start[];
-+      unsigned long slot = addr & BREAK_INSTR_ALIGN, bundle_addr;
-+      unsigned long template;
-+      struct bundle {
-+              struct {
-+                      unsigned long long template:5;
-+                      unsigned long long slot0:41;
-+                      unsigned long long slot1_p0:64 - 46;
-+              } quad0;
-+              struct {
-+                      unsigned long long slot1_p1:41 - (64 - 46);
-+                      unsigned long long slot2:41;
-+              } quad1;
-+      } bundle;
-+      int ret;
-+
-+      bundle_addr = addr & ~0xFULL;
-+
-+      if (bundle_addr == (unsigned long)_start)
-+              return 0;
-+
-+      ret = kgdb_get_mem((char *)bundle_addr, (char *)&bundle,
-+                         BREAK_INSTR_SIZE);
-+      if (ret < 0)
-+              return ret;
-+
-+      if (slot > 2)
-+              slot = 0;
-+
-+      memcpy(saved_instr, &bundle, BREAK_INSTR_SIZE);
-+      template = bundle.quad0.template;
-+
-+      if (slot == 1 && bundle_encoding[template][1] == L)
-+              slot = 2;
-+
-+      switch (slot) {
-+      case 0:
-+              bundle.quad0.slot0 = BREAKNUM;
-+              break;
-+      case 1:
-+              bundle.quad0.slot1_p0 = BREAKNUM;
-+              bundle.quad1.slot1_p1 = (BREAKNUM >> (64 - 46));
-+              break;
-+      case 2:
-+              bundle.quad1.slot2 = BREAKNUM;
-+              break;
-+      }
-+
-+      return kgdb_set_mem((char *)bundle_addr, (char *)&bundle,
-+                          BREAK_INSTR_SIZE);
-+}
-+
-+int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
-+{
-+      extern unsigned long _start[];
-+      
-+      addr = addr & BREAK_INSTR_ALIGN;
-+      if (addr == (unsigned long)_start)
-+              return 0;
-+      return kgdb_set_mem((char *)addr, (char *)bundle, BREAK_INSTR_SIZE);
-+}
-+
-+volatile static struct smp_unw {
-+      struct unw_frame_info *unw;
-+      struct task_struct *task;
-+} smp_unw[NR_CPUS];
-+
-+static int inline kgdb_get_blocked_state(struct task_struct *p,
-+                                       struct unw_frame_info *unw)
-+{
-+      unsigned long ip;
-+      int count = 0;
-+
-+      unw_init_from_blocked_task(unw, p);
-+      ip = 0UL;
-+      do {
-+              if (unw_unwind(unw) < 0)
-+                      return -1;
-+              unw_get_ip(unw, &ip);
-+              if (!in_sched_functions(ip))
-+                      break;
-+      } while (count++ < 16);
-+
-+      if (!ip)
-+              return -1;
-+      else
-+              return 0;
-+}
-+
-+static void inline kgdb_wait(struct pt_regs *regs)
-+{
-+      unsigned long hw_breakpoint_status = ia64_getreg(_IA64_REG_PSR);
-+      if (hw_breakpoint_status & IA64_PSR_DB)
-+              ia64_setreg(_IA64_REG_PSR_L,
-+                          hw_breakpoint_status ^ IA64_PSR_DB);
-+      kgdb_nmihook(smp_processor_id(), regs);
-+      if (hw_breakpoint_status & IA64_PSR_DB)
-+              ia64_setreg(_IA64_REG_PSR_L, hw_breakpoint_status);
-+
-+      return;
-+}
-+
-+static void inline normalize(struct unw_frame_info *running,
-+                           struct pt_regs *regs)
-+{
-+      unsigned long sp;
-+
-+      do {
-+              unw_get_sp(running, &sp);
-+              if ((sp + 0x10) >= (unsigned long)regs)
-+                      break;
-+      } while (unw_unwind(running) >= 0);
-+
-+      return;
-+}
-+
-+static void kgdb_init_running(struct unw_frame_info *unw, void *data)
-+{
-+      struct pt_regs *regs;
-+
-+      regs = data;
-+      normalize(unw, regs);
-+      smp_unw[smp_processor_id()].unw = unw;
-+      kgdb_wait(regs);
-+}
-+
-+void kgdb_wait_ipi(struct pt_regs *regs)
-+{
-+      struct unw_frame_info unw;
-+
-+      smp_unw[smp_processor_id()].task = current;
-+
-+      if (user_mode(regs)) {
-+              smp_unw[smp_processor_id()].unw = (struct unw_frame_info *)1;
-+              kgdb_wait(regs);
-+      } else {
-+              if (current->state == TASK_RUNNING)
-+                      unw_init_running(kgdb_init_running, regs);
-+              else {
-+                      if (kgdb_get_blocked_state(current, &unw))
-+                              smp_unw[smp_processor_id()].unw =
-+                                  (struct unw_frame_info *)1;
-+                      else
-+                              smp_unw[smp_processor_id()].unw = &unw;
-+                      kgdb_wait(regs);
-+              }
-+      }
-+
-+      smp_unw[smp_processor_id()].unw = NULL;
-+      return;
-+}
-+
-+void kgdb_roundup_cpus(unsigned long flags)
-+{
-+      if (num_online_cpus() > 1)
-+              smp_send_nmi_allbutself();
-+}
-+
-+static volatile int kgdb_hwbreak_sstep[NR_CPUS];
-+
-+static int kgdb_notify(struct notifier_block *self, unsigned long cmd,
-+      void *ptr)
-+{
-+      struct die_args *args = ptr;
-+      struct pt_regs *regs = args->regs;
-+      unsigned long err = args->err;
-+
-+      switch (cmd) {
-+      default:
-+              return NOTIFY_DONE;
-+      case DIE_PAGE_FAULT_NO_CONTEXT:
-+              if (atomic_read(&debugger_active) && kgdb_may_fault) {
-+                      kgdb_fault_longjmp(kgdb_fault_jmp_regs);
-+                      return NOTIFY_STOP;
-+              }
-+              break;
-+      case DIE_BREAK:
-+              if (user_mode(regs) || err == 0x80001)
-+                      return NOTIFY_DONE;
-+              break;
-+      case DIE_FAULT:
-+              if (user_mode(regs))
-+                      return NOTIFY_DONE;
-+              else if (err == 36 && kgdb_hwbreak_sstep[smp_processor_id()]) {
-+                      kgdb_hwbreak_sstep[smp_processor_id()] = 0;
-+                      regs->cr_ipsr &= ~IA64_PSR_SS;
-+                      return NOTIFY_STOP;
-+              }
-+      case DIE_MCA_MONARCH_PROCESS:
-+      case DIE_INIT_MONARCH_PROCESS:
-+              break;
-+      }
-+
-+      kgdb_handle_exception(args->trapnr, args->signr, args->err, regs);
-+      return NOTIFY_STOP;
-+}
-+
-+static struct notifier_block kgdb_notifier = {
-+      .notifier_call = kgdb_notify,
-+};
-+
-+int kgdb_arch_init(void)
-+{
-+      atomic_notifier_chain_register(&ia64die_chain, &kgdb_notifier);
-+      return 0;
-+}
-+
-+static void do_kgdb_handle_exception(struct unw_frame_info *, void *data);
-+
-+struct kgdb_state {
-+      int e_vector;
-+      int signo;
-+      unsigned long err_code;
-+      struct pt_regs *regs;
-+      struct unw_frame_info *unw;
-+      char *inbuf;
-+      char *outbuf;
-+      int unwind;
-+      int ret;
-+};
-+
-+static void inline kgdb_pc(struct pt_regs *regs, unsigned long pc)
-+{
-+      regs->cr_iip = pc & ~0xf;
-+      ia64_psr(regs)->ri = pc & 0x3;
-+      return;
-+}
-+
-+int kgdb_arch_handle_exception(int e_vector, int signo,
-+                             int err_code, char *remcom_in_buffer,
-+                             char *remcom_out_buffer,
-+                             struct pt_regs *linux_regs)
-+{
-+      struct kgdb_state info;
-+
-+      info.e_vector = e_vector;
-+      info.signo = signo;
-+      info.err_code = err_code;
-+      info.unw = (void *)0;
-+      info.inbuf = remcom_in_buffer;
-+      info.outbuf = remcom_out_buffer;
-+      info.unwind = 0;
-+      info.ret = -1;
-+
-+      if (remcom_in_buffer[0] == 'c' || remcom_in_buffer[0] == 's') {
-+              info.regs = linux_regs;
-+              do_kgdb_handle_exception(NULL, &info);
-+      } else if (kgdb_usethread == current) {
-+              info.regs = linux_regs;
-+              info.unwind = 1;
-+              unw_init_running(do_kgdb_handle_exception, &info);
-+      } else if (kgdb_usethread->state != TASK_RUNNING) {
-+              struct unw_frame_info unw_info;
-+
-+              if (kgdb_get_blocked_state(kgdb_usethread, &unw_info)) {
-+                      info.ret = 1;
-+                      goto bad;
-+              }
-+              info.regs = NULL;
-+              do_kgdb_handle_exception(&unw_info, &info);
-+      } else {
-+              int i;
-+
-+              for (i = 0; i < NR_CPUS; i++)
-+                      if (smp_unw[i].task == kgdb_usethread && smp_unw[i].unw
-+                          && smp_unw[i].unw != (struct unw_frame_info *)1) {
-+                              info.regs = NULL;
-+                              do_kgdb_handle_exception(smp_unw[i].unw, &info);
-+                              break;
-+                      } else {
-+                              info.ret = 1;
-+                              goto bad;
-+                      }
-+      }
-+
-+      bad:
-+      if (info.ret != -1 && remcom_in_buffer[0] == 'p') {
-+              unsigned long bad = 0xbad4badbadbadbadUL;
-+
-+              printk("kgdb_arch_handle_exception: p packet bad (%s)\n",
-+                     remcom_in_buffer);
-+              kgdb_mem2hex((char *)&bad, remcom_out_buffer, sizeof(bad));
-+              remcom_out_buffer[sizeof(bad) * 2] = 0;
-+              info.ret = -1;
-+      }
-+      return info.ret;
-+}
-+
-+/*
-+ * This is done because I evidently made an incorrect 'p' encoding
-+ * when my patch for gdb was committed. It was later corrected. This
-+ * check supports both my wrong encoding of the register number and
-+ * the correct encoding. Eventually this should be eliminated and
-+ * kgdb_hex2long should be demarshalling the regnum.
-+ */
-+static inline int check_packet(unsigned int regnum, char *packet)
-+{
-+      static int check_done, swap;
-+      unsigned long reglong;
-+
-+      if (likely(check_done)) {
-+              if (swap) {
-+                      kgdb_hex2long(&packet, &reglong);
-+                      regnum = (int) reglong;
-+              }
-+
-+      } else {
-+              if (regnum > NUM_REGS) {
-+                      kgdb_hex2long(&packet, &reglong);
-+                      regnum = (int) reglong;
-+                      swap = 1;
-+              }
-+              check_done = 1;
-+      }
-+      return regnum;
-+}
-+
-+static void do_kgdb_handle_exception(struct unw_frame_info *unw_info,
-+      void *data)
-+{
-+      long addr;
-+      char *ptr;
-+      unsigned long newPC;
-+      int e_vector, signo;
-+      unsigned long err_code;
-+      struct pt_regs *linux_regs;
-+      struct kgdb_state *info;
-+      char *remcom_in_buffer, *remcom_out_buffer;
-+
-+      info = data;
-+      info->unw = unw_info;
-+      e_vector = info->e_vector;
-+      signo = info->signo;
-+      err_code = info->err_code;
-+      remcom_in_buffer = info->inbuf;
-+      remcom_out_buffer = info->outbuf;
-+      linux_regs = info->regs;
-+
-+      if (info->unwind)
-+              normalize(unw_info, linux_regs);
-+
-+      switch (remcom_in_buffer[0]) {
-+      case 'p':
-+              {
-+                      unsigned int regnum;
-+
-+                      kgdb_hex2mem(&remcom_in_buffer[1], (char *)&regnum,
-+                                   sizeof(regnum));
-+                      regnum = check_packet(regnum, &remcom_in_buffer[1]);
-+                      if (regnum >= NUM_REGS) {
-+                              remcom_out_buffer[0] = 'E';
-+                              remcom_out_buffer[1] = 0;
-+                      } else
-+                              kgdb_get_reg(remcom_out_buffer, regnum,
-+                                           unw_info, linux_regs);
-+                      break;
-+              }
-+      case 'P':
-+              {
-+                      unsigned int regno;
-+                      long v;
-+                      char *ptr;
-+
-+                      ptr = &remcom_in_buffer[1];
-+                      if ((!kgdb_usethread || kgdb_usethread == current) &&
-+                          kgdb_hex2long(&ptr, &v) &&
-+                          *ptr++ == '=' && (v >= 0)) {
-+                              regno = (unsigned int)v;
-+                              regno = (regno >= NUM_REGS ? 0 : regno);
-+                              kgdb_put_reg(ptr, remcom_out_buffer, regno,
-+                                           unw_info, linux_regs);
-+                      } else
-+                              strcpy(remcom_out_buffer, "E01");
-+                      break;
-+              }
-+      case 'c':
-+      case 's':
-+              if (e_vector == TRAP_BRKPT && err_code == KGDBBREAKNUM) {
-+                      if (ia64_psr(linux_regs)->ri < 2)
-+                              kgdb_pc(linux_regs, linux_regs->cr_iip +
-+                                      ia64_psr(linux_regs)->ri + 1);
-+                      else
-+                              kgdb_pc(linux_regs, linux_regs->cr_iip + 16);
-+              }
-+
-+              /* try to read optional parameter, pc unchanged if no parm */
-+              ptr = &remcom_in_buffer[1];
-+              if (kgdb_hex2long(&ptr, &addr)) {
-+                      linux_regs->cr_iip = addr;
-+              }
-+              newPC = linux_regs->cr_iip;
-+
-+              /* clear the trace bit */
-+              linux_regs->cr_ipsr &= ~IA64_PSR_SS;
-+
-+              atomic_set(&cpu_doing_single_step, -1);
-+
-+              /* set the trace bit if we're stepping or took a hardware break */
-+              if (remcom_in_buffer[0] == 's' || e_vector == TRAP_HWBKPT) {
-+                      linux_regs->cr_ipsr |= IA64_PSR_SS;
-+                      debugger_step = 1;
-+                      if (kgdb_contthread)
-+                              atomic_set(&cpu_doing_single_step,
-+                                         smp_processor_id());
-+              }
-+
-+              kgdb_correct_hw_break();
-+
-+              /* if not hardware breakpoint, then reenable them */
-+              if (e_vector != TRAP_HWBKPT)
-+                      linux_regs->cr_ipsr |= IA64_PSR_DB;
-+              else {
-+                      kgdb_hwbreak_sstep[smp_processor_id()] = 1;
-+                      linux_regs->cr_ipsr &= ~IA64_PSR_DB;
-+              }
-+
-+              info->ret = 0;
-+              break;
-+      default:
-+              break;
-+      }
-+
-+      return;
-+}
-+
-+struct kgdb_arch arch_kgdb_ops = {
-+      .gdb_bpt_instr = {0xcc},
-+};
-diff -Nurb linux-2.6.22-570/arch/ia64/kernel/smp.c linux-2.6.22-590/arch/ia64/kernel/smp.c
---- linux-2.6.22-570/arch/ia64/kernel/smp.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ia64/kernel/smp.c    2008-01-02 13:56:37.000000000 -0500
-@@ -48,6 +48,7 @@
- #include <asm/tlbflush.h>
- #include <asm/unistd.h>
- #include <asm/mca.h>
-+#include <linux/kgdb.h>
- /*
-  * Note: alignment of 4 entries/cacheline was empirically determined
-@@ -79,6 +80,9 @@
- #define IPI_CALL_FUNC         0
- #define IPI_CPU_STOP          1
-+#ifdef        CONFIG_KGDB
-+#define       IPI_KGDB_INTERRUPT      2
-+#endif
- #define IPI_KDUMP_CPU_STOP    3
- /* This needs to be cacheline aligned because it is written to by *other* CPUs.  */
-@@ -169,6 +173,11 @@
-                             case IPI_CPU_STOP:
-                               stop_this_cpu();
-                               break;
-+#ifdef        CONFIG_KGDB
-+                            case IPI_KGDB_INTERRUPT:
-+                              kgdb_wait_ipi(get_irq_regs());
-+                              break;
-+#endif
- #ifdef CONFIG_KEXEC
-                             case IPI_KDUMP_CPU_STOP:
-                               unw_init_running(kdump_cpu_freeze, NULL);
-@@ -399,6 +408,14 @@
- }
- EXPORT_SYMBOL(smp_call_function_single);
-+#ifdef        CONFIG_KGDB
-+void
-+smp_send_nmi_allbutself(void)
-+{
-+      send_IPI_allbutself(IPI_KGDB_INTERRUPT);
-+}
-+#endif
-+
- /*
-  * this function sends a 'generic call function' IPI to all other CPUs
-  * in the system.
-diff -Nurb linux-2.6.22-570/arch/ia64/kernel/traps.c linux-2.6.22-590/arch/ia64/kernel/traps.c
---- linux-2.6.22-570/arch/ia64/kernel/traps.c  2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/ia64/kernel/traps.c  2008-01-02 13:56:37.000000000 -0500
-@@ -155,8 +155,12 @@
-               break;
-             default:
--              if (break_num < 0x40000 || break_num > 0x100000)
-+              if (break_num < 0x40000 || break_num > 0x100000) {
-+                      if (notify_die(DIE_BREAK, "bad break", regs,
-+                              break_num, TRAP_BRKPT, SIGTRAP) == NOTIFY_STOP)
-+                              return;
-                       die_if_kernel("Bad break", regs, break_num);
-+              }
-               if (break_num < 0x80000) {
-                       sig = SIGILL; code = __ILL_BREAK;
-diff -Nurb linux-2.6.22-570/arch/ia64/mm/extable.c linux-2.6.22-590/arch/ia64/mm/extable.c
---- linux-2.6.22-570/arch/ia64/mm/extable.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ia64/mm/extable.c    2008-01-02 13:56:37.000000000 -0500
-@@ -6,6 +6,7 @@
-  */
- #include <linux/sort.h>
-+#include <linux/kgdb.h>
- #include <asm/uaccess.h>
- #include <asm/module.h>
-@@ -73,6 +74,11 @@
-                 else
-                         last = mid - 1;
-         }
-+#ifdef CONFIG_KGDB
-+      if (atomic_read(&debugger_active) && kgdb_may_fault)
-+              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
-+              /* Not reached. */
-+#endif
-         return NULL;
- }
-diff -Nurb linux-2.6.22-570/arch/ia64/mm/fault.c linux-2.6.22-590/arch/ia64/mm/fault.c
---- linux-2.6.22-570/arch/ia64/mm/fault.c      2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/ia64/mm/fault.c      2008-01-02 13:56:37.000000000 -0500
-@@ -255,6 +255,10 @@
-        */
-       bust_spinlocks(1);
-+      if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs,
-+                      isr, 14, SIGSEGV) == NOTIFY_STOP)
-+              return;
-+
-       if (address < PAGE_SIZE)
-               printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference (address %016lx)\n", address);
-       else
-diff -Nurb linux-2.6.22-570/arch/mips/Kconfig linux-2.6.22-590/arch/mips/Kconfig
---- linux-2.6.22-570/arch/mips/Kconfig 2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/mips/Kconfig 2008-01-02 13:56:37.000000000 -0500
-@@ -30,7 +30,6 @@
-       select SYS_SUPPORTS_32BIT_KERNEL
-       select SYS_SUPPORTS_64BIT_KERNEL
-       select SYS_SUPPORTS_BIG_ENDIAN
--      select SYS_SUPPORTS_KGDB
-       help
-         The eXcite is a smart camera platform manufactured by
-         Basler Vision Technologies AG.
-@@ -98,7 +97,6 @@
-       select SYS_SUPPORTS_32BIT_KERNEL
-       select SYS_SUPPORTS_64BIT_KERNEL
-       select SYS_SUPPORTS_BIG_ENDIAN
--      select SYS_SUPPORTS_KGDB
-       help
-         This is an evaluation board based on the Galileo GT-64120
-         single-chip system controller that contains a MIPS R5000 compatible
-@@ -269,7 +267,6 @@
-       select SYS_SUPPORTS_32BIT_KERNEL
-       select SYS_SUPPORTS_64BIT_KERNEL
-       select SYS_SUPPORTS_BIG_ENDIAN
--      select SYS_SUPPORTS_KGDB
-       help
-         The Ocelot is a MIPS-based Single Board Computer (SBC) made by
-         Momentum Computer <http://www.momenco.com/>.
-@@ -331,8 +328,6 @@
-       select SYS_HAS_CPU_R5432
-       select SYS_SUPPORTS_32BIT_KERNEL
-       select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
--      select SYS_SUPPORTS_KGDB
--      select SYS_SUPPORTS_KGDB
-       select SYS_SUPPORTS_LITTLE_ENDIAN
-       help
-         This enables support for the R5432-based NEC DDB Vrc-5477,
-@@ -360,7 +355,6 @@
-       select SYS_SUPPORTS_64BIT_KERNEL
-       select SYS_SUPPORTS_BIG_ENDIAN
-       select SYS_SUPPORTS_HIGHMEM
--      select SYS_SUPPORTS_KGDB
-       select SYS_SUPPORTS_SMP
-       help
-         Yosemite is an evaluation board for the RM9000x2 processor
-@@ -440,7 +434,6 @@
-       select SYS_HAS_CPU_R10000
-       select SYS_SUPPORTS_64BIT_KERNEL
-       select SYS_SUPPORTS_BIG_ENDIAN
--      select SYS_SUPPORTS_KGDB
-       select SYS_SUPPORTS_NUMA
-       select SYS_SUPPORTS_SMP
-       select GENERIC_HARDIRQS_NO__DO_IRQ
-@@ -490,7 +483,6 @@
-       select SYS_HAS_CPU_SB1
-       select SYS_SUPPORTS_BIG_ENDIAN
-       select SYS_SUPPORTS_HIGHMEM
--      select SYS_SUPPORTS_KGDB
-       select SYS_SUPPORTS_LITTLE_ENDIAN
- config SIBYTE_SENTOSA
-@@ -631,7 +623,6 @@
-       select SYS_SUPPORTS_64BIT_KERNEL
-       select SYS_SUPPORTS_LITTLE_ENDIAN
-       select SYS_SUPPORTS_BIG_ENDIAN
--      select SYS_SUPPORTS_KGDB
-       select GENERIC_HARDIRQS_NO__DO_IRQ
-       help
-         This Toshiba board is based on the TX4927 processor. Say Y here to
-@@ -650,7 +641,6 @@
-       select SYS_SUPPORTS_32BIT_KERNEL
-       select SYS_SUPPORTS_LITTLE_ENDIAN
-       select SYS_SUPPORTS_BIG_ENDIAN
--      select SYS_SUPPORTS_KGDB
-       select GENERIC_HARDIRQS_NO__DO_IRQ
-       help
-         This Toshiba board is based on the TX4938 processor. Say Y here to
-@@ -826,7 +816,6 @@
- config DDB5XXX_COMMON
-       bool
--      select SYS_SUPPORTS_KGDB
- config MIPS_BOARDS_GEN
-       bool
-@@ -862,7 +851,6 @@
-       select SYS_HAS_EARLY_PRINTK
-       select SYS_SUPPORTS_32BIT_KERNEL
-       select GENERIC_HARDIRQS_NO__DO_IRQ
--      select SYS_SUPPORTS_KGDB
- config SWAP_IO_SPACE
-       bool
-diff -Nurb linux-2.6.22-570/arch/mips/Kconfig.debug linux-2.6.22-590/arch/mips/Kconfig.debug
---- linux-2.6.22-570/arch/mips/Kconfig.debug   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/Kconfig.debug   2008-01-02 13:56:37.000000000 -0500
-@@ -46,28 +46,6 @@
-         arch/mips/kernel/smtc.c.  This debugging option result in significant
-         overhead so should be disabled in production kernels.
--config KGDB
--      bool "Remote GDB kernel debugging"
--      depends on DEBUG_KERNEL && SYS_SUPPORTS_KGDB
--      select DEBUG_INFO
--      help
--        If you say Y here, it will be possible to remotely debug the MIPS
--        kernel using gdb. This enlarges your kernel image disk size by
--        several megabytes and requires a machine with more than 16 MB,
--        better 32 MB RAM to avoid excessive linking time. This is only
--        useful for kernel hackers. If unsure, say N.
--
--config SYS_SUPPORTS_KGDB
--      bool
--
--config GDB_CONSOLE
--      bool "Console output to GDB"
--      depends on KGDB
--      help
--        If you are using GDB for remote debugging over a serial port and
--        would like kernel messages to be formatted into GDB $O packets so
--        that GDB prints them as program output, say 'Y'.
--
- config SB1XXX_CORELIS
-       bool "Corelis Debugger"
-       depends on SIBYTE_SB1xxx_SOC
-diff -Nurb linux-2.6.22-570/arch/mips/au1000/common/Makefile linux-2.6.22-590/arch/mips/au1000/common/Makefile
---- linux-2.6.22-570/arch/mips/au1000/common/Makefile  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/au1000/common/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -10,5 +10,4 @@
-       au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
-       sleeper.o cputable.o dma.o dbdma.o gpio.o
--obj-$(CONFIG_KGDB)            += dbg_io.o
- obj-$(CONFIG_PCI)             += pci.o
-diff -Nurb linux-2.6.22-570/arch/mips/au1000/common/dbg_io.c linux-2.6.22-590/arch/mips/au1000/common/dbg_io.c
---- linux-2.6.22-570/arch/mips/au1000/common/dbg_io.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/au1000/common/dbg_io.c  1969-12-31 19:00:00.000000000 -0500
-@@ -1,121 +0,0 @@
--
--#include <asm/io.h>
--#include <asm/mach-au1x00/au1000.h>
--
--#ifdef CONFIG_KGDB
--
--/*
-- * FIXME the user should be able to select the
-- * uart to be used for debugging.
-- */
--#define DEBUG_BASE  UART_DEBUG_BASE
--/**/
--
--/* we need uint32 uint8 */
--/* #include "types.h" */
--typedef         unsigned char uint8;
--typedef         unsigned int  uint32;
--
--#define         UART16550_BAUD_2400             2400
--#define         UART16550_BAUD_4800             4800
--#define         UART16550_BAUD_9600             9600
--#define         UART16550_BAUD_19200            19200
--#define         UART16550_BAUD_38400            38400
--#define         UART16550_BAUD_57600            57600
--#define         UART16550_BAUD_115200           115200
--
--#define         UART16550_PARITY_NONE           0
--#define         UART16550_PARITY_ODD            0x08
--#define         UART16550_PARITY_EVEN           0x18
--#define         UART16550_PARITY_MARK           0x28
--#define         UART16550_PARITY_SPACE          0x38
--
--#define         UART16550_DATA_5BIT             0x0
--#define         UART16550_DATA_6BIT             0x1
--#define         UART16550_DATA_7BIT             0x2
--#define         UART16550_DATA_8BIT             0x3
--
--#define         UART16550_STOP_1BIT             0x0
--#define         UART16550_STOP_2BIT             0x4
--
--
--#define UART_RX               0       /* Receive buffer */
--#define UART_TX               4       /* Transmit buffer */
--#define UART_IER      8       /* Interrupt Enable Register */
--#define UART_IIR      0xC     /* Interrupt ID Register */
--#define UART_FCR      0x10    /* FIFO Control Register */
--#define UART_LCR      0x14    /* Line Control Register */
--#define UART_MCR      0x18    /* Modem Control Register */
--#define UART_LSR      0x1C    /* Line Status Register */
--#define UART_MSR      0x20    /* Modem Status Register */
--#define UART_CLK      0x28    /* Baud Rat4e Clock Divider */
--#define UART_MOD_CNTRL        0x100   /* Module Control */
--
--/* memory-mapped read/write of the port */
--#define UART16550_READ(y)    (au_readl(DEBUG_BASE + y) & 0xff)
--#define UART16550_WRITE(y,z) (au_writel(z&0xff, DEBUG_BASE + y))
--
--extern unsigned long get_au1x00_uart_baud_base(void);
--extern unsigned long cal_r4koff(void);
--
--void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
--{
--
--      if (UART16550_READ(UART_MOD_CNTRL) != 0x3) {
--              UART16550_WRITE(UART_MOD_CNTRL, 3);
--      }
--      cal_r4koff();
--
--      /* disable interrupts */
--      UART16550_WRITE(UART_IER, 0);
--
--      /* set up baud rate */
--      {
--              uint32 divisor;
--
--              /* set divisor */
--              divisor = get_au1x00_uart_baud_base() / baud;
--              UART16550_WRITE(UART_CLK, divisor & 0xffff);
--      }
--
--      /* set data format */
--      UART16550_WRITE(UART_LCR, (data | parity | stop));
--}
--
--static int remoteDebugInitialized = 0;
--
--uint8 getDebugChar(void)
--{
--      if (!remoteDebugInitialized) {
--              remoteDebugInitialized = 1;
--              debugInit(UART16550_BAUD_115200,
--                        UART16550_DATA_8BIT,
--                        UART16550_PARITY_NONE,
--                        UART16550_STOP_1BIT);
--      }
--
--      while((UART16550_READ(UART_LSR) & 0x1) == 0);
--      return UART16550_READ(UART_RX);
--}
--
--
--int putDebugChar(uint8 byte)
--{
--//    int i;
--
--      if (!remoteDebugInitialized) {
--              remoteDebugInitialized = 1;
--              debugInit(UART16550_BAUD_115200,
--                        UART16550_DATA_8BIT,
--                        UART16550_PARITY_NONE,
--                        UART16550_STOP_1BIT);
--      }
--
--      while ((UART16550_READ(UART_LSR)&0x40) == 0);
--      UART16550_WRITE(UART_TX, byte);
--      //for (i=0;i<0xfff;i++);
--
--      return 1;
--}
--
--#endif
-diff -Nurb linux-2.6.22-570/arch/mips/basler/excite/Makefile linux-2.6.22-590/arch/mips/basler/excite/Makefile
---- linux-2.6.22-570/arch/mips/basler/excite/Makefile  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/basler/excite/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -5,5 +5,4 @@
- obj-$(CONFIG_BASLER_EXCITE)   += excite_irq.o excite_prom.o excite_setup.o \
-                                  excite_device.o excite_procfs.o
--obj-$(CONFIG_KGDB)            += excite_dbg_io.o
- obj-m                         += excite_iodev.o
-diff -Nurb linux-2.6.22-570/arch/mips/basler/excite/excite_dbg_io.c linux-2.6.22-590/arch/mips/basler/excite/excite_dbg_io.c
---- linux-2.6.22-570/arch/mips/basler/excite/excite_dbg_io.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/basler/excite/excite_dbg_io.c   1969-12-31 19:00:00.000000000 -0500
-@@ -1,121 +0,0 @@
--/*
-- *  Copyright (C) 2004 by Basler Vision Technologies AG
-- *  Author: Thomas Koeller <thomas.koeller@baslerweb.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/linkage.h>
--#include <linux/init.h>
--#include <linux/kernel.h>
--#include <asm/gdb-stub.h>
--#include <asm/rm9k-ocd.h>
--#include <excite.h>
--
--#if defined(CONFIG_SERIAL_8250) && CONFIG_SERIAL_8250_NR_UARTS > 1
--#error Debug port used by serial driver
--#endif
--
--#define UART_CLK              25000000
--#define BASE_BAUD             (UART_CLK / 16)
--#define REGISTER_BASE_0               0x0208UL
--#define REGISTER_BASE_1               0x0238UL
--
--#define REGISTER_BASE_DBG     REGISTER_BASE_1
--
--#define CPRR  0x0004
--#define UACFG 0x0200
--#define UAINTS        0x0204
--#define UARBR (REGISTER_BASE_DBG + 0x0000)
--#define UATHR (REGISTER_BASE_DBG + 0x0004)
--#define UADLL (REGISTER_BASE_DBG + 0x0008)
--#define UAIER (REGISTER_BASE_DBG + 0x000c)
--#define UADLH (REGISTER_BASE_DBG + 0x0010)
--#define UAIIR (REGISTER_BASE_DBG + 0x0014)
--#define UAFCR (REGISTER_BASE_DBG + 0x0018)
--#define UALCR (REGISTER_BASE_DBG + 0x001c)
--#define UAMCR (REGISTER_BASE_DBG + 0x0020)
--#define UALSR (REGISTER_BASE_DBG + 0x0024)
--#define UAMSR (REGISTER_BASE_DBG + 0x0028)
--#define UASCR (REGISTER_BASE_DBG + 0x002c)
--
--#define       PARITY_NONE     0
--#define       PARITY_ODD      0x08
--#define       PARITY_EVEN     0x18
--#define       PARITY_MARK     0x28
--#define       PARITY_SPACE    0x38
--
--#define       DATA_5BIT       0x0
--#define       DATA_6BIT       0x1
--#define       DATA_7BIT       0x2
--#define       DATA_8BIT       0x3
--
--#define       STOP_1BIT       0x0
--#define       STOP_2BIT       0x4
--
--#define BAUD_DBG      57600
--#define       PARITY_DBG      PARITY_NONE
--#define       DATA_DBG        DATA_8BIT
--#define       STOP_DBG        STOP_1BIT
--
--/* Initialize the serial port for KGDB debugging */
--void __init excite_kgdb_init(void)
--{
--      const u32 divisor = BASE_BAUD / BAUD_DBG;
--
--      /* Take the UART out of reset */
--      titan_writel(0x00ff1cff, CPRR);
--      titan_writel(0x00000000, UACFG);
--      titan_writel(0x00000002, UACFG);
--
--      titan_writel(0x0, UALCR);
--      titan_writel(0x0, UAIER);
--
--      /* Disable FIFOs */
--      titan_writel(0x00, UAFCR);
--
--      titan_writel(0x80, UALCR);
--      titan_writel(divisor & 0xff, UADLL);
--      titan_writel((divisor & 0xff00) >> 8, UADLH);
--      titan_writel(0x0, UALCR);
--
--      titan_writel(DATA_DBG | PARITY_DBG | STOP_DBG, UALCR);
--
--      /* Enable receiver interrupt */
--      titan_readl(UARBR);
--      titan_writel(0x1, UAIER);
--}
--
--int getDebugChar(void)
--{
--      while (!(titan_readl(UALSR) & 0x1));
--      return titan_readl(UARBR);
--}
--
--int putDebugChar(int data)
--{
--      while (!(titan_readl(UALSR) & 0x20));
--      titan_writel(data, UATHR);
--      return 1;
--}
--
--/* KGDB interrupt handler */
--asmlinkage void excite_kgdb_inthdl(void)
--{
--      if (unlikely(
--              ((titan_readl(UAIIR) & 0x7) == 4)
--              && ((titan_readl(UARBR) & 0xff) == 0x3)))
--                      set_async_breakpoint(&regs->cp0_epc);
--}
-diff -Nurb linux-2.6.22-570/arch/mips/basler/excite/excite_irq.c linux-2.6.22-590/arch/mips/basler/excite/excite_irq.c
---- linux-2.6.22-570/arch/mips/basler/excite/excite_irq.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/basler/excite/excite_irq.c      2008-01-02 13:56:37.000000000 -0500
-@@ -50,10 +50,6 @@
-       mips_cpu_irq_init();
-       rm7k_cpu_irq_init();
-       rm9k_cpu_irq_init();
--
--#ifdef CONFIG_KGDB
--      excite_kgdb_init();
--#endif
- }
- asmlinkage void plat_irq_dispatch(void)
-@@ -90,9 +86,6 @@
-       msgint      = msgintflags & msgintmask & (0x1 << (TITAN_MSGINT % 0x20));
-       if ((pending & (1 << TITAN_IRQ)) && msgint) {
-               ocd_writel(msgint, INTP0Clear0 + (TITAN_MSGINT / 0x20 * 0x10));
--#if defined(CONFIG_KGDB)
--              excite_kgdb_inthdl();
--#endif
-               do_IRQ(TITAN_IRQ);
-               return;
-       }
-diff -Nurb linux-2.6.22-570/arch/mips/basler/excite/excite_setup.c linux-2.6.22-590/arch/mips/basler/excite/excite_setup.c
---- linux-2.6.22-570/arch/mips/basler/excite/excite_setup.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/basler/excite/excite_setup.c    2008-01-02 13:56:37.000000000 -0500
-@@ -95,13 +95,13 @@
-       /* Take the DUART out of reset */
-       titan_writel(0x00ff1cff, CPRR);
--#if defined(CONFIG_KGDB) || (CONFIG_SERIAL_8250_NR_UARTS > 1)
-+#if (CONFIG_SERIAL_8250_NR_UARTS > 1)
-       /* Enable both ports */
-       titan_writel(MASK_SER0 | MASK_SER1, UACFG);
- #else
-       /* Enable port #0 only */
-       titan_writel(MASK_SER0, UACFG);
--#endif        /* defined(CONFIG_KGDB) */
-+#endif
-       /*
-        * Set up serial port #0. Do not use autodetection; the result is
-diff -Nurb linux-2.6.22-570/arch/mips/ddb5xxx/ddb5477/Makefile linux-2.6.22-590/arch/mips/ddb5xxx/ddb5477/Makefile
---- linux-2.6.22-570/arch/mips/ddb5xxx/ddb5477/Makefile        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/ddb5xxx/ddb5477/Makefile        2008-01-02 13:56:37.000000000 -0500
-@@ -5,4 +5,3 @@
- obj-y                 += irq.o irq_5477.o setup.o lcd44780.o
- obj-$(CONFIG_RUNTIME_DEBUG)   += debug.o
--obj-$(CONFIG_KGDB)            += kgdb_io.o
-diff -Nurb linux-2.6.22-570/arch/mips/ddb5xxx/ddb5477/kgdb_io.c linux-2.6.22-590/arch/mips/ddb5xxx/ddb5477/kgdb_io.c
---- linux-2.6.22-570/arch/mips/ddb5xxx/ddb5477/kgdb_io.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/ddb5xxx/ddb5477/kgdb_io.c       1969-12-31 19:00:00.000000000 -0500
-@@ -1,136 +0,0 @@
--/*
-- * kgdb io functions for DDB5477.  We use the second serial port (upper one).
-- *
-- * Copyright (C) 2001 MontaVista Software Inc.
-- * Author: jsun@mvista.com or jsun@junsun.net
-- *
-- * 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.
-- *
-- */
--
--/* ======================= CONFIG ======================== */
--
--/* [jsun] we use the second serial port for kdb */
--#define         BASE                    0xbfa04240
--#define         MAX_BAUD                115200
--
--/* distance in bytes between two serial registers */
--#define         REG_OFFSET              8
--
--/*
-- * 0 - kgdb does serial init
-- * 1 - kgdb skip serial init
-- */
--static int remoteDebugInitialized = 0;
--
--/*
-- * the default baud rate *if* kgdb does serial init
-- */
--#define               BAUD_DEFAULT            UART16550_BAUD_38400
--
--/* ======================= END OF CONFIG ======================== */
--
--typedef unsigned char uint8;
--typedef unsigned int uint32;
--
--#define         UART16550_BAUD_2400             2400
--#define         UART16550_BAUD_4800             4800
--#define         UART16550_BAUD_9600             9600
--#define         UART16550_BAUD_19200            19200
--#define         UART16550_BAUD_38400            38400
--#define         UART16550_BAUD_57600            57600
--#define         UART16550_BAUD_115200           115200
--
--#define         UART16550_PARITY_NONE           0
--#define         UART16550_PARITY_ODD            0x08
--#define         UART16550_PARITY_EVEN           0x18
--#define         UART16550_PARITY_MARK           0x28
--#define         UART16550_PARITY_SPACE          0x38
--
--#define         UART16550_DATA_5BIT             0x0
--#define         UART16550_DATA_6BIT             0x1
--#define         UART16550_DATA_7BIT             0x2
--#define         UART16550_DATA_8BIT             0x3
--
--#define         UART16550_STOP_1BIT             0x0
--#define         UART16550_STOP_2BIT             0x4
--
--/* register offset */
--#define         OFS_RCV_BUFFER          0
--#define         OFS_TRANS_HOLD          0
--#define         OFS_SEND_BUFFER         0
--#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
--#define         OFS_INTR_ID             (2*REG_OFFSET)
--#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
--#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
--#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
--#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
--#define         OFS_LINE_STATUS         (5*REG_OFFSET)
--#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
--#define         OFS_RS232_INPUT         (6*REG_OFFSET)
--#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
--
--#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
--#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
--
--
--/* memory-mapped read/write of the port */
--#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
--#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
--
--void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
--{
--        /* disable interrupts */
--        UART16550_WRITE(OFS_INTR_ENABLE, 0);
--
--        /* set up baud rate */
--        {
--                uint32 divisor;
--
--                /* set DIAB bit */
--                UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
--
--                /* set divisor */
--                divisor = MAX_BAUD / baud;
--                UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
--                UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
--
--                /* clear DIAB bit */
--                UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
--        }
--
--        /* set data format */
--        UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
--}
--
--
--uint8 getDebugChar(void)
--{
--        if (!remoteDebugInitialized) {
--                remoteDebugInitialized = 1;
--                debugInit(BAUD_DEFAULT,
--                          UART16550_DATA_8BIT,
--                          UART16550_PARITY_NONE, UART16550_STOP_1BIT);
--        }
--
--        while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
--        return UART16550_READ(OFS_RCV_BUFFER);
--}
--
--
--int putDebugChar(uint8 byte)
--{
--        if (!remoteDebugInitialized) {
--                remoteDebugInitialized = 1;
--                debugInit(BAUD_DEFAULT,
--                          UART16550_DATA_8BIT,
--                          UART16550_PARITY_NONE, UART16550_STOP_1BIT);
--        }
--
--        while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
--        UART16550_WRITE(OFS_SEND_BUFFER, byte);
--        return 1;
--}
-diff -Nurb linux-2.6.22-570/arch/mips/gt64120/momenco_ocelot/Makefile linux-2.6.22-590/arch/mips/gt64120/momenco_ocelot/Makefile
---- linux-2.6.22-570/arch/mips/gt64120/momenco_ocelot/Makefile 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/gt64120/momenco_ocelot/Makefile 2008-01-02 13:56:37.000000000 -0500
-@@ -3,5 +3,3 @@
- #
- obj-y                 += irq.o prom.o reset.o setup.o
--
--obj-$(CONFIG_KGDB)    += dbg_io.o
-diff -Nurb linux-2.6.22-570/arch/mips/gt64120/momenco_ocelot/dbg_io.c linux-2.6.22-590/arch/mips/gt64120/momenco_ocelot/dbg_io.c
---- linux-2.6.22-570/arch/mips/gt64120/momenco_ocelot/dbg_io.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/gt64120/momenco_ocelot/dbg_io.c 1969-12-31 19:00:00.000000000 -0500
-@@ -1,121 +0,0 @@
--
--#include <asm/serial.h> /* For the serial port location and base baud */
--
--/* --- CONFIG --- */
--
--typedef unsigned char uint8;
--typedef unsigned int uint32;
--
--/* --- END OF CONFIG --- */
--
--#define         UART16550_BAUD_2400             2400
--#define         UART16550_BAUD_4800             4800
--#define         UART16550_BAUD_9600             9600
--#define         UART16550_BAUD_19200            19200
--#define         UART16550_BAUD_38400            38400
--#define         UART16550_BAUD_57600            57600
--#define         UART16550_BAUD_115200           115200
--
--#define         UART16550_PARITY_NONE           0
--#define         UART16550_PARITY_ODD            0x08
--#define         UART16550_PARITY_EVEN           0x18
--#define         UART16550_PARITY_MARK           0x28
--#define         UART16550_PARITY_SPACE          0x38
--
--#define         UART16550_DATA_5BIT             0x0
--#define         UART16550_DATA_6BIT             0x1
--#define         UART16550_DATA_7BIT             0x2
--#define         UART16550_DATA_8BIT             0x3
--
--#define         UART16550_STOP_1BIT             0x0
--#define         UART16550_STOP_2BIT             0x4
--
--/* ----------------------------------------------------- */
--
--/* === CONFIG === */
--
--/* [jsun] we use the second serial port for kdb */
--#define         BASE                    OCELOT_SERIAL1_BASE
--#define         MAX_BAUD                OCELOT_BASE_BAUD
--
--/* === END OF CONFIG === */
--
--#define         REG_OFFSET              4
--
--/* register offset */
--#define         OFS_RCV_BUFFER          0
--#define         OFS_TRANS_HOLD          0
--#define         OFS_SEND_BUFFER         0
--#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
--#define         OFS_INTR_ID             (2*REG_OFFSET)
--#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
--#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
--#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
--#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
--#define         OFS_LINE_STATUS         (5*REG_OFFSET)
--#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
--#define         OFS_RS232_INPUT         (6*REG_OFFSET)
--#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
--
--#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
--#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
--
--
--/* memory-mapped read/write of the port */
--#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
--#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
--
--void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
--{
--      /* disable interrupts */
--      UART16550_WRITE(OFS_INTR_ENABLE, 0);
--
--      /* set up baud rate */
--      {
--              uint32 divisor;
--
--              /* set DIAB bit */
--              UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
--
--              /* set divisor */
--              divisor = MAX_BAUD / baud;
--              UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
--              UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
--
--              /* clear DIAB bit */
--              UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
--      }
--
--      /* set data format */
--      UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
--}
--
--static int remoteDebugInitialized = 0;
--
--uint8 getDebugChar(void)
--{
--      if (!remoteDebugInitialized) {
--              remoteDebugInitialized = 1;
--              debugInit(UART16550_BAUD_38400,
--                        UART16550_DATA_8BIT,
--                        UART16550_PARITY_NONE, UART16550_STOP_1BIT);
--      }
--
--      while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
--      return UART16550_READ(OFS_RCV_BUFFER);
--}
--
--
--int putDebugChar(uint8 byte)
--{
--      if (!remoteDebugInitialized) {
--              remoteDebugInitialized = 1;
--              debugInit(UART16550_BAUD_38400,
--                        UART16550_DATA_8BIT,
--                        UART16550_PARITY_NONE, UART16550_STOP_1BIT);
--      }
--
--      while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
--      UART16550_WRITE(OFS_SEND_BUFFER, byte);
--      return 1;
--}
-diff -Nurb linux-2.6.22-570/arch/mips/jmr3927/rbhma3100/Makefile linux-2.6.22-590/arch/mips/jmr3927/rbhma3100/Makefile
---- linux-2.6.22-570/arch/mips/jmr3927/rbhma3100/Makefile      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/jmr3927/rbhma3100/Makefile      2008-01-02 13:56:37.000000000 -0500
-@@ -3,4 +3,3 @@
- #
- obj-y                         += init.o irq.o setup.o
--obj-$(CONFIG_KGDB)            += kgdb_io.o
-diff -Nurb linux-2.6.22-570/arch/mips/jmr3927/rbhma3100/kgdb_io.c linux-2.6.22-590/arch/mips/jmr3927/rbhma3100/kgdb_io.c
---- linux-2.6.22-570/arch/mips/jmr3927/rbhma3100/kgdb_io.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/jmr3927/rbhma3100/kgdb_io.c     1969-12-31 19:00:00.000000000 -0500
-@@ -1,105 +0,0 @@
--/*
-- * BRIEF MODULE DESCRIPTION
-- *    Low level uart routines to directly access a TX[34]927 SIO.
-- *
-- * Copyright 2001 MontaVista Software Inc.
-- * Author: MontaVista Software, Inc.
-- *            ahennessy@mvista.com or source@mvista.com
-- *
-- * Based on arch/mips/ddb5xxx/ddb5477/kgdb_io.c
-- *
-- * Copyright (C) 2000-2001 Toshiba Corporation
-- *
-- *  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.
-- */
--
--#include <asm/jmr3927/jmr3927.h>
--
--#define TIMEOUT       0xffffff
--
--static int remoteDebugInitialized = 0;
--static void debugInit(int baud);
--
--int putDebugChar(unsigned char c)
--{
--        int i = 0;
--
--      if (!remoteDebugInitialized) {
--              remoteDebugInitialized = 1;
--              debugInit(38400);
--      }
--
--        do {
--            slow_down();
--            i++;
--            if (i>TIMEOUT) {
--                break;
--            }
--        } while (!(tx3927_sioptr(0)->cisr & TXx927_SICISR_TXALS));
--      tx3927_sioptr(0)->tfifo = c;
--
--      return 1;
--}
--
--unsigned char getDebugChar(void)
--{
--        int i = 0;
--      int dicr;
--      char c;
--
--      if (!remoteDebugInitialized) {
--              remoteDebugInitialized = 1;
--              debugInit(38400);
--      }
--
--      /* diable RX int. */
--      dicr = tx3927_sioptr(0)->dicr;
--      tx3927_sioptr(0)->dicr = 0;
--
--        do {
--            slow_down();
--            i++;
--            if (i>TIMEOUT) {
--                break;
--            }
--        } while (tx3927_sioptr(0)->disr & TXx927_SIDISR_UVALID)
--              ;
--      c = tx3927_sioptr(0)->rfifo;
--
--      /* clear RX int. status */
--      tx3927_sioptr(0)->disr &= ~TXx927_SIDISR_RDIS;
--      /* enable RX int. */
--      tx3927_sioptr(0)->dicr = dicr;
--
--      return c;
--}
--
--static void debugInit(int baud)
--{
--      tx3927_sioptr(0)->lcr = 0x020;
--      tx3927_sioptr(0)->dicr = 0;
--      tx3927_sioptr(0)->disr = 0x4100;
--      tx3927_sioptr(0)->cisr = 0x014;
--      tx3927_sioptr(0)->fcr = 0;
--      tx3927_sioptr(0)->flcr = 0x02;
--      tx3927_sioptr(0)->bgr = ((JMR3927_BASE_BAUD + baud / 2) / baud) |
--              TXx927_SIBGR_BCLK_T0;
--}
-diff -Nurb linux-2.6.22-570/arch/mips/kernel/Makefile linux-2.6.22-590/arch/mips/kernel/Makefile
---- linux-2.6.22-570/arch/mips/kernel/Makefile 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/kernel/Makefile 2008-01-02 13:56:37.000000000 -0500
-@@ -57,7 +57,8 @@
- obj-$(CONFIG_MIPS32_N32)      += binfmt_elfn32.o scall64-n32.o signal_n32.o
- obj-$(CONFIG_MIPS32_O32)      += binfmt_elfo32.o scall64-o32.o
--obj-$(CONFIG_KGDB)            += gdb-low.o gdb-stub.o
-+obj-$(CONFIG_KGDB)            += kgdb_handler.o kgdb.o kgdb-jmp.o     \
-+                                      kgdb-setjmp.o
- obj-$(CONFIG_PROC_FS)         += proc.o
- obj-$(CONFIG_64BIT)           += cpu-bugs64.o
-diff -Nurb linux-2.6.22-570/arch/mips/kernel/cpu-probe.c linux-2.6.22-590/arch/mips/kernel/cpu-probe.c
---- linux-2.6.22-570/arch/mips/kernel/cpu-probe.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/kernel/cpu-probe.c      2008-01-02 13:56:37.000000000 -0500
-@@ -177,6 +177,17 @@
-               cpu_wait = r4k_wait;
-               break;
-+      case CPU_20KC:
-+              /*
-+               * WAIT on Rev1.0 has E1, E2, E3 and E16.
-+               * WAIT on Rev2.0 and Rev3.0 has E16.
-+               * Rev3.1 WAIT is nop, why bother
-+               */
-+              if ((c->processor_id & 0xff) <= 0x64)
-+                      break;
-+
-+              cpu_wait = r4k_wait;
-+              break;
-       case CPU_RM9000:
-               if ((c->processor_id & 0x00ff) >= 0x40)
-                       cpu_wait = r4k_wait;
-diff -Nurb linux-2.6.22-570/arch/mips/kernel/gdb-low.S linux-2.6.22-590/arch/mips/kernel/gdb-low.S
---- linux-2.6.22-570/arch/mips/kernel/gdb-low.S        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/kernel/gdb-low.S        1969-12-31 19:00:00.000000000 -0500
-@@ -1,394 +0,0 @@
--/*
-- * gdb-low.S contains the low-level trap handler for the GDB stub.
-- *
-- * Copyright (C) 1995 Andreas Busse
-- */
--#include <linux/sys.h>
--
--#include <asm/asm.h>
--#include <asm/errno.h>
--#include <asm/irqflags.h>
--#include <asm/mipsregs.h>
--#include <asm/regdef.h>
--#include <asm/stackframe.h>
--#include <asm/gdb-stub.h>
--
--#ifdef CONFIG_32BIT
--#define DMFC0 mfc0
--#define DMTC0 mtc0
--#define LDC1  lwc1
--#define SDC1  lwc1
--#endif
--#ifdef CONFIG_64BIT
--#define DMFC0 dmfc0
--#define DMTC0 dmtc0
--#define LDC1  ldc1
--#define SDC1  ldc1
--#endif
--
--/*
-- * [jsun] We reserves about 2x GDB_FR_SIZE in stack.  The lower (addressed)
-- * part is used to store registers and passed to exception handler.
-- * The upper part is reserved for "call func" feature where gdb client
-- * saves some of the regs, setups call frame and passes args.
-- *
-- * A trace shows about 200 bytes are used to store about half of all regs.
-- * The rest should be big enough for frame setup and passing args.
-- */
--
--/*
-- * The low level trap handler
-- */
--              .align  5
--              NESTED(trap_low, GDB_FR_SIZE, sp)
--              .set    noat
--              .set    noreorder
--
--              mfc0    k0, CP0_STATUS
--              sll     k0, 3                   /* extract cu0 bit */
--              bltz    k0, 1f
--              move    k1, sp
--
--              /*
--               * Called from user mode, go somewhere else.
--               */
--              mfc0    k0, CP0_CAUSE
--              andi    k0, k0, 0x7c
--#ifdef CONFIG_64BIT
--              dsll    k0, k0, 1
--#endif
--              PTR_L   k1, saved_vectors(k0)
--              jr      k1
--              nop
--1:
--              move    k0, sp
--              PTR_SUBU sp, k1, GDB_FR_SIZE*2  # see comment above
--              LONG_S  k0, GDB_FR_REG29(sp)
--              LONG_S  $2, GDB_FR_REG2(sp)
--
--/*
-- * First save the CP0 and special registers
-- */
--
--              mfc0    v0, CP0_STATUS
--              LONG_S  v0, GDB_FR_STATUS(sp)
--              mfc0    v0, CP0_CAUSE
--              LONG_S  v0, GDB_FR_CAUSE(sp)
--              DMFC0   v0, CP0_EPC
--              LONG_S  v0, GDB_FR_EPC(sp)
--              DMFC0   v0, CP0_BADVADDR
--              LONG_S  v0, GDB_FR_BADVADDR(sp)
--              mfhi    v0
--              LONG_S  v0, GDB_FR_HI(sp)
--              mflo    v0
--              LONG_S  v0, GDB_FR_LO(sp)
--
--/*
-- * Now the integer registers
-- */
--
--              LONG_S  zero, GDB_FR_REG0(sp)           /* I know... */
--              LONG_S  $1, GDB_FR_REG1(sp)
--              /* v0 already saved */
--              LONG_S  $3, GDB_FR_REG3(sp)
--              LONG_S  $4, GDB_FR_REG4(sp)
--              LONG_S  $5, GDB_FR_REG5(sp)
--              LONG_S  $6, GDB_FR_REG6(sp)
--              LONG_S  $7, GDB_FR_REG7(sp)
--              LONG_S  $8, GDB_FR_REG8(sp)
--              LONG_S  $9, GDB_FR_REG9(sp)
--              LONG_S  $10, GDB_FR_REG10(sp)
--              LONG_S  $11, GDB_FR_REG11(sp)
--              LONG_S  $12, GDB_FR_REG12(sp)
--              LONG_S  $13, GDB_FR_REG13(sp)
--              LONG_S  $14, GDB_FR_REG14(sp)
--              LONG_S  $15, GDB_FR_REG15(sp)
--              LONG_S  $16, GDB_FR_REG16(sp)
--              LONG_S  $17, GDB_FR_REG17(sp)
--              LONG_S  $18, GDB_FR_REG18(sp)
--              LONG_S  $19, GDB_FR_REG19(sp)
--              LONG_S  $20, GDB_FR_REG20(sp)
--              LONG_S  $21, GDB_FR_REG21(sp)
--              LONG_S  $22, GDB_FR_REG22(sp)
--              LONG_S  $23, GDB_FR_REG23(sp)
--              LONG_S  $24, GDB_FR_REG24(sp)
--              LONG_S  $25, GDB_FR_REG25(sp)
--              LONG_S  $26, GDB_FR_REG26(sp)
--              LONG_S  $27, GDB_FR_REG27(sp)
--              LONG_S  $28, GDB_FR_REG28(sp)
--              /* sp already saved */
--              LONG_S  $30, GDB_FR_REG30(sp)
--              LONG_S  $31, GDB_FR_REG31(sp)
--
--              CLI                             /* disable interrupts */
--              TRACE_IRQS_OFF
--
--/*
-- * Followed by the floating point registers
-- */
--              mfc0    v0, CP0_STATUS          /* FPU enabled? */
--              srl     v0, v0, 16
--              andi    v0, v0, (ST0_CU1 >> 16)
--
--              beqz    v0,2f                   /* disabled, skip */
--               nop
--
--              SDC1    $0, GDB_FR_FPR0(sp)
--              SDC1    $1, GDB_FR_FPR1(sp)
--              SDC1    $2, GDB_FR_FPR2(sp)
--              SDC1    $3, GDB_FR_FPR3(sp)
--              SDC1    $4, GDB_FR_FPR4(sp)
--              SDC1    $5, GDB_FR_FPR5(sp)
--              SDC1    $6, GDB_FR_FPR6(sp)
--              SDC1    $7, GDB_FR_FPR7(sp)
--              SDC1    $8, GDB_FR_FPR8(sp)
--              SDC1    $9, GDB_FR_FPR9(sp)
--              SDC1    $10, GDB_FR_FPR10(sp)
--              SDC1    $11, GDB_FR_FPR11(sp)
--              SDC1    $12, GDB_FR_FPR12(sp)
--              SDC1    $13, GDB_FR_FPR13(sp)
--              SDC1    $14, GDB_FR_FPR14(sp)
--              SDC1    $15, GDB_FR_FPR15(sp)
--              SDC1    $16, GDB_FR_FPR16(sp)
--              SDC1    $17, GDB_FR_FPR17(sp)
--              SDC1    $18, GDB_FR_FPR18(sp)
--              SDC1    $19, GDB_FR_FPR19(sp)
--              SDC1    $20, GDB_FR_FPR20(sp)
--              SDC1    $21, GDB_FR_FPR21(sp)
--              SDC1    $22, GDB_FR_FPR22(sp)
--              SDC1    $23, GDB_FR_FPR23(sp)
--              SDC1    $24, GDB_FR_FPR24(sp)
--              SDC1    $25, GDB_FR_FPR25(sp)
--              SDC1    $26, GDB_FR_FPR26(sp)
--              SDC1    $27, GDB_FR_FPR27(sp)
--              SDC1    $28, GDB_FR_FPR28(sp)
--              SDC1    $29, GDB_FR_FPR29(sp)
--              SDC1    $30, GDB_FR_FPR30(sp)
--              SDC1    $31, GDB_FR_FPR31(sp)
--
--/*
-- * FPU control registers
-- */
--
--              cfc1    v0, CP1_STATUS
--              LONG_S  v0, GDB_FR_FSR(sp)
--              cfc1    v0, CP1_REVISION
--              LONG_S  v0, GDB_FR_FIR(sp)
--
--/*
-- * Current stack frame ptr
-- */
--
--2:
--              LONG_S  sp, GDB_FR_FRP(sp)
--
--/*
-- * CP0 registers (R4000/R4400 unused registers skipped)
-- */
--
--              mfc0    v0, CP0_INDEX
--              LONG_S  v0, GDB_FR_CP0_INDEX(sp)
--              mfc0    v0, CP0_RANDOM
--              LONG_S  v0, GDB_FR_CP0_RANDOM(sp)
--              DMFC0   v0, CP0_ENTRYLO0
--              LONG_S  v0, GDB_FR_CP0_ENTRYLO0(sp)
--              DMFC0   v0, CP0_ENTRYLO1
--              LONG_S  v0, GDB_FR_CP0_ENTRYLO1(sp)
--              DMFC0   v0, CP0_CONTEXT
--              LONG_S  v0, GDB_FR_CP0_CONTEXT(sp)
--              mfc0    v0, CP0_PAGEMASK
--              LONG_S  v0, GDB_FR_CP0_PAGEMASK(sp)
--              mfc0    v0, CP0_WIRED
--              LONG_S  v0, GDB_FR_CP0_WIRED(sp)
--              DMFC0   v0, CP0_ENTRYHI
--              LONG_S  v0, GDB_FR_CP0_ENTRYHI(sp)
--              mfc0    v0, CP0_PRID
--              LONG_S  v0, GDB_FR_CP0_PRID(sp)
--
--              .set    at
--
--/*
-- * Continue with the higher level handler
-- */
--
--              move    a0,sp
--
--              jal     handle_exception
--               nop
--
--/*
-- * Restore all writable registers, in reverse order
-- */
--
--              .set    noat
--
--              LONG_L  v0, GDB_FR_CP0_ENTRYHI(sp)
--              LONG_L  v1, GDB_FR_CP0_WIRED(sp)
--              DMTC0   v0, CP0_ENTRYHI
--              mtc0    v1, CP0_WIRED
--              LONG_L  v0, GDB_FR_CP0_PAGEMASK(sp)
--              LONG_L  v1, GDB_FR_CP0_ENTRYLO1(sp)
--              mtc0    v0, CP0_PAGEMASK
--              DMTC0   v1, CP0_ENTRYLO1
--              LONG_L  v0, GDB_FR_CP0_ENTRYLO0(sp)
--              LONG_L  v1, GDB_FR_CP0_INDEX(sp)
--              DMTC0   v0, CP0_ENTRYLO0
--              LONG_L  v0, GDB_FR_CP0_CONTEXT(sp)
--              mtc0    v1, CP0_INDEX
--              DMTC0   v0, CP0_CONTEXT
--
--
--/*
-- * Next, the floating point registers
-- */
--              mfc0    v0, CP0_STATUS          /* check if the FPU is enabled */
--              srl     v0, v0, 16
--              andi    v0, v0, (ST0_CU1 >> 16)
--
--              beqz    v0, 3f                  /* disabled, skip */
--               nop
--
--              LDC1    $31, GDB_FR_FPR31(sp)
--              LDC1    $30, GDB_FR_FPR30(sp)
--              LDC1    $29, GDB_FR_FPR29(sp)
--              LDC1    $28, GDB_FR_FPR28(sp)
--              LDC1    $27, GDB_FR_FPR27(sp)
--              LDC1    $26, GDB_FR_FPR26(sp)
--              LDC1    $25, GDB_FR_FPR25(sp)
--              LDC1    $24, GDB_FR_FPR24(sp)
--              LDC1    $23, GDB_FR_FPR23(sp)
--              LDC1    $22, GDB_FR_FPR22(sp)
--              LDC1    $21, GDB_FR_FPR21(sp)
--              LDC1    $20, GDB_FR_FPR20(sp)
--              LDC1    $19, GDB_FR_FPR19(sp)
--              LDC1    $18, GDB_FR_FPR18(sp)
--              LDC1    $17, GDB_FR_FPR17(sp)
--              LDC1    $16, GDB_FR_FPR16(sp)
--              LDC1    $15, GDB_FR_FPR15(sp)
--              LDC1    $14, GDB_FR_FPR14(sp)
--              LDC1    $13, GDB_FR_FPR13(sp)
--              LDC1    $12, GDB_FR_FPR12(sp)
--              LDC1    $11, GDB_FR_FPR11(sp)
--              LDC1    $10, GDB_FR_FPR10(sp)
--              LDC1    $9, GDB_FR_FPR9(sp)
--              LDC1    $8, GDB_FR_FPR8(sp)
--              LDC1    $7, GDB_FR_FPR7(sp)
--              LDC1    $6, GDB_FR_FPR6(sp)
--              LDC1    $5, GDB_FR_FPR5(sp)
--              LDC1    $4, GDB_FR_FPR4(sp)
--              LDC1    $3, GDB_FR_FPR3(sp)
--              LDC1    $2, GDB_FR_FPR2(sp)
--              LDC1    $1, GDB_FR_FPR1(sp)
--              LDC1    $0, GDB_FR_FPR0(sp)
--
--/*
-- * Now the CP0 and integer registers
-- */
--
--3:
--#ifdef CONFIG_MIPS_MT_SMTC
--              /* Read-modify write of Status must be atomic */
--              mfc0    t2, CP0_TCSTATUS
--              ori     t1, t2, TCSTATUS_IXMT
--              mtc0    t1, CP0_TCSTATUS
--              andi    t2, t2, TCSTATUS_IXMT
--              _ehb
--              DMT     9                               # dmt   t1
--              jal     mips_ihb
--              nop
--#endif /* CONFIG_MIPS_MT_SMTC */
--              mfc0    t0, CP0_STATUS
--              ori     t0, 0x1f
--              xori    t0, 0x1f
--              mtc0    t0, CP0_STATUS
--#ifdef CONFIG_MIPS_MT_SMTC
--              andi    t1, t1, VPECONTROL_TE
--              beqz    t1, 9f
--              nop
--              EMT                                     # emt
--9:
--              mfc0    t1, CP0_TCSTATUS
--              xori    t1, t1, TCSTATUS_IXMT
--              or      t1, t1, t2
--              mtc0    t1, CP0_TCSTATUS
--              _ehb
--#endif /* CONFIG_MIPS_MT_SMTC */
--              LONG_L  v0, GDB_FR_STATUS(sp)
--              LONG_L  v1, GDB_FR_EPC(sp)
--              mtc0    v0, CP0_STATUS
--              DMTC0   v1, CP0_EPC
--              LONG_L  v0, GDB_FR_HI(sp)
--              LONG_L  v1, GDB_FR_LO(sp)
--              mthi    v0
--              mtlo    v1
--              LONG_L  $31, GDB_FR_REG31(sp)
--              LONG_L  $30, GDB_FR_REG30(sp)
--              LONG_L  $28, GDB_FR_REG28(sp)
--              LONG_L  $27, GDB_FR_REG27(sp)
--              LONG_L  $26, GDB_FR_REG26(sp)
--              LONG_L  $25, GDB_FR_REG25(sp)
--              LONG_L  $24, GDB_FR_REG24(sp)
--              LONG_L  $23, GDB_FR_REG23(sp)
--              LONG_L  $22, GDB_FR_REG22(sp)
--              LONG_L  $21, GDB_FR_REG21(sp)
--              LONG_L  $20, GDB_FR_REG20(sp)
--              LONG_L  $19, GDB_FR_REG19(sp)
--              LONG_L  $18, GDB_FR_REG18(sp)
--              LONG_L  $17, GDB_FR_REG17(sp)
--              LONG_L  $16, GDB_FR_REG16(sp)
--              LONG_L  $15, GDB_FR_REG15(sp)
--              LONG_L  $14, GDB_FR_REG14(sp)
--              LONG_L  $13, GDB_FR_REG13(sp)
--              LONG_L  $12, GDB_FR_REG12(sp)
--              LONG_L  $11, GDB_FR_REG11(sp)
--              LONG_L  $10, GDB_FR_REG10(sp)
--              LONG_L  $9, GDB_FR_REG9(sp)
--              LONG_L  $8, GDB_FR_REG8(sp)
--              LONG_L  $7, GDB_FR_REG7(sp)
--              LONG_L  $6, GDB_FR_REG6(sp)
--              LONG_L  $5, GDB_FR_REG5(sp)
--              LONG_L  $4, GDB_FR_REG4(sp)
--              LONG_L  $3, GDB_FR_REG3(sp)
--              LONG_L  $2, GDB_FR_REG2(sp)
--              LONG_L  $1, GDB_FR_REG1(sp)
--#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
--              LONG_L  k0, GDB_FR_EPC(sp)
--              LONG_L  $29, GDB_FR_REG29(sp)           /* Deallocate stack */
--              jr      k0
--              rfe
--#else
--              LONG_L  sp, GDB_FR_REG29(sp)            /* Deallocate stack */
--
--              .set    mips3
--              eret
--              .set    mips0
--#endif
--              .set    at
--              .set    reorder
--              END(trap_low)
--
--LEAF(kgdb_read_byte)
--4:            lb      t0, (a0)
--              sb      t0, (a1)
--              li      v0, 0
--              jr      ra
--              .section __ex_table,"a"
--              PTR     4b, kgdbfault
--              .previous
--              END(kgdb_read_byte)
--
--LEAF(kgdb_write_byte)
--5:            sb      a0, (a1)
--              li      v0, 0
--              jr      ra
--              .section __ex_table,"a"
--              PTR     5b, kgdbfault
--              .previous
--              END(kgdb_write_byte)
--
--              .type   kgdbfault@function
--              .ent    kgdbfault
--
--kgdbfault:    li      v0, -EFAULT
--              jr      ra
--              .end    kgdbfault
-diff -Nurb linux-2.6.22-570/arch/mips/kernel/gdb-stub.c linux-2.6.22-590/arch/mips/kernel/gdb-stub.c
---- linux-2.6.22-570/arch/mips/kernel/gdb-stub.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/kernel/gdb-stub.c       1969-12-31 19:00:00.000000000 -0500
-@@ -1,1154 +0,0 @@
--/*
-- *  arch/mips/kernel/gdb-stub.c
-- *
-- *  Originally written by Glenn Engel, Lake Stevens Instrument Division
-- *
-- *  Contributed by HP Systems
-- *
-- *  Modified for SPARC by Stu Grossman, Cygnus Support.
-- *
-- *  Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
-- *  Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
-- *
-- *  Copyright (C) 1995 Andreas Busse
-- *
-- *  Copyright (C) 2003 MontaVista Software Inc.
-- *  Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
-- */
--
--/*
-- *  To enable debugger support, two things need to happen.  One, a
-- *  call to set_debug_traps() is necessary in order to allow any breakpoints
-- *  or error conditions to be properly intercepted and reported to gdb.
-- *  Two, a breakpoint needs to be generated to begin communication.  This
-- *  is most easily accomplished by a call to breakpoint().  Breakpoint()
-- *  simulates a breakpoint by executing a BREAK instruction.
-- *
-- *
-- *    The following gdb commands are supported:
-- *
-- * command          function                               Return value
-- *
-- *    g             return the value of the CPU registers  hex data or ENN
-- *    G             set the value of the CPU registers     OK or ENN
-- *
-- *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
-- *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
-- *
-- *    c             Resume at current address              SNN   ( signal NN)
-- *    cAA..AA       Continue at address AA..AA             SNN
-- *
-- *    s             Step one instruction                   SNN
-- *    sAA..AA       Step one instruction from AA..AA       SNN
-- *
-- *    k             kill
-- *
-- *    ?             What was the last sigval ?             SNN   (signal NN)
-- *
-- *    bBB..BB     Set baud rate to BB..BB                OK or BNN, then sets
-- *                                                       baud rate
-- *
-- * All commands and responses are sent with a packet which includes a
-- * checksum.  A packet consists of
-- *
-- * $<packet info>#<checksum>.
-- *
-- * where
-- * <packet info> :: <characters representing the command or response>
-- * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
-- *
-- * When a packet is received, it is first acknowledged with either '+' or '-'.
-- * '+' indicates a successful transfer.  '-' indicates a failed transfer.
-- *
-- * Example:
-- *
-- * Host:                  Reply:
-- * $m0,10#2a               +$00010203040506070809101112131415#42
-- *
-- *
-- *  ==============
-- *  MORE EXAMPLES:
-- *  ==============
-- *
-- *  For reference -- the following are the steps that one
-- *  company took (RidgeRun Inc) to get remote gdb debugging
-- *  going. In this scenario the host machine was a PC and the
-- *  target platform was a Galileo EVB64120A MIPS evaluation
-- *  board.
-- *
-- *  Step 1:
-- *  First download gdb-5.0.tar.gz from the internet.
-- *  and then build/install the package.
-- *
-- *  Example:
-- *    $ tar zxf gdb-5.0.tar.gz
-- *    $ cd gdb-5.0
-- *    $ ./configure --target=mips-linux-elf
-- *    $ make
-- *    $ install
-- *    $ which mips-linux-elf-gdb
-- *    /usr/local/bin/mips-linux-elf-gdb
-- *
-- *  Step 2:
-- *  Configure linux for remote debugging and build it.
-- *
-- *  Example:
-- *    $ cd ~/linux
-- *    $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
-- *    $ make
-- *
-- *  Step 3:
-- *  Download the kernel to the remote target and start
-- *  the kernel running. It will promptly halt and wait
-- *  for the host gdb session to connect. It does this
-- *  since the "Kernel Hacking" option has defined
-- *  CONFIG_KGDB which in turn enables your calls
-- *  to:
-- *     set_debug_traps();
-- *     breakpoint();
-- *
-- *  Step 4:
-- *  Start the gdb session on the host.
-- *
-- *  Example:
-- *    $ mips-linux-elf-gdb vmlinux
-- *    (gdb) set remotebaud 115200
-- *    (gdb) target remote /dev/ttyS1
-- *    ...at this point you are connected to
-- *       the remote target and can use gdb
-- *       in the normal fasion. Setting
-- *       breakpoints, single stepping,
-- *       printing variables, etc.
-- */
--#include <linux/string.h>
--#include <linux/kernel.h>
--#include <linux/signal.h>
--#include <linux/sched.h>
--#include <linux/mm.h>
--#include <linux/console.h>
--#include <linux/init.h>
--#include <linux/smp.h>
--#include <linux/spinlock.h>
--#include <linux/slab.h>
--#include <linux/reboot.h>
--
--#include <asm/asm.h>
--#include <asm/cacheflush.h>
--#include <asm/mipsregs.h>
--#include <asm/pgtable.h>
--#include <asm/system.h>
--#include <asm/gdb-stub.h>
--#include <asm/inst.h>
--#include <asm/smp.h>
--
--/*
-- * external low-level support routines
-- */
--
--extern int putDebugChar(char c);    /* write a single character      */
--extern char getDebugChar(void);     /* read and return a single char */
--extern void trap_low(void);
--
--/*
-- * breakpoint and test functions
-- */
--extern void breakpoint(void);
--extern void breakinst(void);
--extern void async_breakpoint(void);
--extern void async_breakinst(void);
--extern void adel(void);
--
--/*
-- * local prototypes
-- */
--
--static void getpacket(char *buffer);
--static void putpacket(char *buffer);
--static int computeSignal(int tt);
--static int hex(unsigned char ch);
--static int hexToInt(char **ptr, int *intValue);
--static int hexToLong(char **ptr, long *longValue);
--static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
--void handle_exception(struct gdb_regs *regs);
--
--int kgdb_enabled;
--
--/*
-- * spin locks for smp case
-- */
--static DEFINE_SPINLOCK(kgdb_lock);
--static raw_spinlock_t kgdb_cpulock[NR_CPUS] = {
--      [0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED,
--};
--
--/*
-- * BUFMAX defines the maximum number of characters in inbound/outbound buffers
-- * at least NUMREGBYTES*2 are needed for register packets
-- */
--#define BUFMAX 2048
--
--static char input_buffer[BUFMAX];
--static char output_buffer[BUFMAX];
--static int initialized;       /* !0 means we've been initialized */
--static int kgdb_started;
--static const char hexchars[]="0123456789abcdef";
--
--/* Used to prevent crashes in memory access.  Note that they'll crash anyway if
--   we haven't set up fault handlers yet... */
--int kgdb_read_byte(unsigned char *address, unsigned char *dest);
--int kgdb_write_byte(unsigned char val, unsigned char *dest);
--
--/*
-- * Convert ch from a hex digit to an int
-- */
--static int hex(unsigned char ch)
--{
--      if (ch >= 'a' && ch <= 'f')
--              return ch-'a'+10;
--      if (ch >= '0' && ch <= '9')
--              return ch-'0';
--      if (ch >= 'A' && ch <= 'F')
--              return ch-'A'+10;
--      return -1;
--}
--
--/*
-- * scan for the sequence $<data>#<checksum>
-- */
--static void getpacket(char *buffer)
--{
--      unsigned char checksum;
--      unsigned char xmitcsum;
--      int i;
--      int count;
--      unsigned char ch;
--
--      do {
--              /*
--               * wait around for the start character,
--               * ignore all other characters
--               */
--              while ((ch = (getDebugChar() & 0x7f)) != '$') ;
--
--              checksum = 0;
--              xmitcsum = -1;
--              count = 0;
--
--              /*
--               * now, read until a # or end of buffer is found
--               */
--              while (count < BUFMAX) {
--                      ch = getDebugChar();
--                      if (ch == '#')
--                              break;
--                      checksum = checksum + ch;
--                      buffer[count] = ch;
--                      count = count + 1;
--              }
--
--              if (count >= BUFMAX)
--                      continue;
--
--              buffer[count] = 0;
--
--              if (ch == '#') {
--                      xmitcsum = hex(getDebugChar() & 0x7f) << 4;
--                      xmitcsum |= hex(getDebugChar() & 0x7f);
--
--                      if (checksum != xmitcsum)
--                              putDebugChar('-');      /* failed checksum */
--                      else {
--                              putDebugChar('+'); /* successful transfer */
--
--                              /*
--                               * if a sequence char is present,
--                               * reply the sequence ID
--                               */
--                              if (buffer[2] == ':') {
--                                      putDebugChar(buffer[0]);
--                                      putDebugChar(buffer[1]);
--
--                                      /*
--                                       * remove sequence chars from buffer
--                                       */
--                                      count = strlen(buffer);
--                                      for (i=3; i <= count; i++)
--                                              buffer[i-3] = buffer[i];
--                              }
--                      }
--              }
--      }
--      while (checksum != xmitcsum);
--}
--
--/*
-- * send the packet in buffer.
-- */
--static void putpacket(char *buffer)
--{
--      unsigned char checksum;
--      int count;
--      unsigned char ch;
--
--      /*
--       * $<packet info>#<checksum>.
--       */
--
--      do {
--              putDebugChar('$');
--              checksum = 0;
--              count = 0;
--
--              while ((ch = buffer[count]) != 0) {
--                      if (!(putDebugChar(ch)))
--                              return;
--                      checksum += ch;
--                      count += 1;
--              }
--
--              putDebugChar('#');
--              putDebugChar(hexchars[checksum >> 4]);
--              putDebugChar(hexchars[checksum & 0xf]);
--
--      }
--      while ((getDebugChar() & 0x7f) != '+');
--}
--
--
--/*
-- * Convert the memory pointed to by mem into hex, placing result in buf.
-- * Return a pointer to the last char put in buf (null), in case of mem fault,
-- * return 0.
-- * may_fault is non-zero if we are reading from arbitrary memory, but is currently
-- * not used.
-- */
--static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
--{
--      unsigned char ch;
--
--      while (count-- > 0) {
--              if (kgdb_read_byte(mem++, &ch) != 0)
--                      return 0;
--              *buf++ = hexchars[ch >> 4];
--              *buf++ = hexchars[ch & 0xf];
--      }
--
--      *buf = 0;
--
--      return buf;
--}
--
--/*
-- * convert the hex array pointed to by buf into binary to be placed in mem
-- * return a pointer to the character AFTER the last byte written
-- * may_fault is non-zero if we are reading from arbitrary memory, but is currently
-- * not used.
-- */
--static char *hex2mem(char *buf, char *mem, int count, int binary, int may_fault)
--{
--      int i;
--      unsigned char ch;
--
--      for (i=0; i<count; i++)
--      {
--              if (binary) {
--                      ch = *buf++;
--                      if (ch == 0x7d)
--                              ch = 0x20 ^ *buf++;
--              }
--              else {
--                      ch = hex(*buf++) << 4;
--                      ch |= hex(*buf++);
--              }
--              if (kgdb_write_byte(ch, mem++) != 0)
--                      return 0;
--      }
--
--      return mem;
--}
--
--/*
-- * This table contains the mapping between SPARC hardware trap types, and
-- * signals, which are primarily what GDB understands.  It also indicates
-- * which hardware traps we need to commandeer when initializing the stub.
-- */
--static struct hard_trap_info {
--      unsigned char tt;               /* Trap type code for MIPS R3xxx and R4xxx */
--      unsigned char signo;            /* Signal that we map this trap into */
--} hard_trap_info[] = {
--      { 6, SIGBUS },                  /* instruction bus error */
--      { 7, SIGBUS },                  /* data bus error */
--      { 9, SIGTRAP },                 /* break */
--      { 10, SIGILL },                 /* reserved instruction */
--/*    { 11, SIGILL },         */      /* CPU unusable */
--      { 12, SIGFPE },                 /* overflow */
--      { 13, SIGTRAP },                /* trap */
--      { 14, SIGSEGV },                /* virtual instruction cache coherency */
--      { 15, SIGFPE },                 /* floating point exception */
--      { 23, SIGSEGV },                /* watch */
--      { 31, SIGSEGV },                /* virtual data cache coherency */
--      { 0, 0}                         /* Must be last */
--};
--
--/* Save the normal trap handlers for user-mode traps. */
--void *saved_vectors[32];
--
--/*
-- * Set up exception handlers for tracing and breakpoints
-- */
--void set_debug_traps(void)
--{
--      struct hard_trap_info *ht;
--      unsigned long flags;
--      unsigned char c;
--
--      local_irq_save(flags);
--      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
--              saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low);
--
--      putDebugChar('+'); /* 'hello world' */
--      /*
--       * In case GDB is started before us, ack any packets
--       * (presumably "$?#xx") sitting there.
--       */
--      while((c = getDebugChar()) != '$');
--      while((c = getDebugChar()) != '#');
--      c = getDebugChar(); /* eat first csum byte */
--      c = getDebugChar(); /* eat second csum byte */
--      putDebugChar('+'); /* ack it */
--
--      initialized = 1;
--      local_irq_restore(flags);
--}
--
--void restore_debug_traps(void)
--{
--      struct hard_trap_info *ht;
--      unsigned long flags;
--
--      local_irq_save(flags);
--      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
--              set_except_vector(ht->tt, saved_vectors[ht->tt]);
--      local_irq_restore(flags);
--}
--
--/*
-- * Convert the MIPS hardware trap type code to a Unix signal number.
-- */
--static int computeSignal(int tt)
--{
--      struct hard_trap_info *ht;
--
--      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
--              if (ht->tt == tt)
--                      return ht->signo;
--
--      return SIGHUP;          /* default for things we don't know about */
--}
--
--/*
-- * While we find nice hex chars, build an int.
-- * Return number of chars processed.
-- */
--static int hexToInt(char **ptr, int *intValue)
--{
--      int numChars = 0;
--      int hexValue;
--
--      *intValue = 0;
--
--      while (**ptr) {
--              hexValue = hex(**ptr);
--              if (hexValue < 0)
--                      break;
--
--              *intValue = (*intValue << 4) | hexValue;
--              numChars ++;
--
--              (*ptr)++;
--      }
--
--      return (numChars);
--}
--
--static int hexToLong(char **ptr, long *longValue)
--{
--      int numChars = 0;
--      int hexValue;
--
--      *longValue = 0;
--
--      while (**ptr) {
--              hexValue = hex(**ptr);
--              if (hexValue < 0)
--                      break;
--
--              *longValue = (*longValue << 4) | hexValue;
--              numChars ++;
--
--              (*ptr)++;
--      }
--
--      return numChars;
--}
--
--
--#if 0
--/*
-- * Print registers (on target console)
-- * Used only to debug the stub...
-- */
--void show_gdbregs(struct gdb_regs * regs)
--{
--      /*
--       * Saved main processor registers
--       */
--      printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
--             regs->reg0, regs->reg1, regs->reg2, regs->reg3,
--             regs->reg4, regs->reg5, regs->reg6, regs->reg7);
--      printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
--             regs->reg8, regs->reg9, regs->reg10, regs->reg11,
--             regs->reg12, regs->reg13, regs->reg14, regs->reg15);
--      printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
--             regs->reg16, regs->reg17, regs->reg18, regs->reg19,
--             regs->reg20, regs->reg21, regs->reg22, regs->reg23);
--      printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
--             regs->reg24, regs->reg25, regs->reg26, regs->reg27,
--             regs->reg28, regs->reg29, regs->reg30, regs->reg31);
--
--      /*
--       * Saved cp0 registers
--       */
--      printk("epc  : %08lx\nStatus: %08lx\nCause : %08lx\n",
--             regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
--}
--#endif /* dead code */
--
--/*
-- * We single-step by setting breakpoints. When an exception
-- * is handled, we need to restore the instructions hoisted
-- * when the breakpoints were set.
-- *
-- * This is where we save the original instructions.
-- */
--static struct gdb_bp_save {
--      unsigned long addr;
--      unsigned int val;
--} step_bp[2];
--
--#define BP 0x0000000d  /* break opcode */
--
--/*
-- * Set breakpoint instructions for single stepping.
-- */
--static void single_step(struct gdb_regs *regs)
--{
--      union mips_instruction insn;
--      unsigned long targ;
--      int is_branch, is_cond, i;
--
--      targ = regs->cp0_epc;
--      insn.word = *(unsigned int *)targ;
--      is_branch = is_cond = 0;
--
--      switch (insn.i_format.opcode) {
--      /*
--       * jr and jalr are in r_format format.
--       */
--      case spec_op:
--              switch (insn.r_format.func) {
--              case jalr_op:
--              case jr_op:
--                      targ = *(&regs->reg0 + insn.r_format.rs);
--                      is_branch = 1;
--                      break;
--              }
--              break;
--
--      /*
--       * This group contains:
--       * bltz_op, bgez_op, bltzl_op, bgezl_op,
--       * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
--       */
--      case bcond_op:
--              is_branch = is_cond = 1;
--              targ += 4 + (insn.i_format.simmediate << 2);
--              break;
--
--      /*
--       * These are unconditional and in j_format.
--       */
--      case jal_op:
--      case j_op:
--              is_branch = 1;
--              targ += 4;
--              targ >>= 28;
--              targ <<= 28;
--              targ |= (insn.j_format.target << 2);
--              break;
--
--      /*
--       * These are conditional.
--       */
--      case beq_op:
--      case beql_op:
--      case bne_op:
--      case bnel_op:
--      case blez_op:
--      case blezl_op:
--      case bgtz_op:
--      case bgtzl_op:
--      case cop0_op:
--      case cop1_op:
--      case cop2_op:
--      case cop1x_op:
--              is_branch = is_cond = 1;
--              targ += 4 + (insn.i_format.simmediate << 2);
--              break;
--      }
--
--      if (is_branch) {
--              i = 0;
--              if (is_cond && targ != (regs->cp0_epc + 8)) {
--                      step_bp[i].addr = regs->cp0_epc + 8;
--                      step_bp[i++].val = *(unsigned *)(regs->cp0_epc + 8);
--                      *(unsigned *)(regs->cp0_epc + 8) = BP;
--              }
--              step_bp[i].addr = targ;
--              step_bp[i].val  = *(unsigned *)targ;
--              *(unsigned *)targ = BP;
--      } else {
--              step_bp[0].addr = regs->cp0_epc + 4;
--              step_bp[0].val  = *(unsigned *)(regs->cp0_epc + 4);
--              *(unsigned *)(regs->cp0_epc + 4) = BP;
--      }
--}
--
--/*
-- *  If asynchronously interrupted by gdb, then we need to set a breakpoint
-- *  at the interrupted instruction so that we wind up stopped with a
-- *  reasonable stack frame.
-- */
--static struct gdb_bp_save async_bp;
--
--/*
-- * Swap the interrupted EPC with our asynchronous breakpoint routine.
-- * This is safer than stuffing the breakpoint in-place, since no cache
-- * flushes (or resulting smp_call_functions) are required.  The
-- * assumption is that only one CPU will be handling asynchronous bp's,
-- * and only one can be active at a time.
-- */
--extern spinlock_t smp_call_lock;
--
--void set_async_breakpoint(unsigned long *epc)
--{
--      /* skip breaking into userland */
--      if ((*epc & 0x80000000) == 0)
--              return;
--
--#ifdef CONFIG_SMP
--      /* avoid deadlock if someone is make IPC */
--      if (spin_is_locked(&smp_call_lock))
--              return;
--#endif
--
--      async_bp.addr = *epc;
--      *epc = (unsigned long)async_breakpoint;
--}
--
--static void kgdb_wait(void *arg)
--{
--      unsigned flags;
--      int cpu = smp_processor_id();
--
--      local_irq_save(flags);
--
--      __raw_spin_lock(&kgdb_cpulock[cpu]);
--      __raw_spin_unlock(&kgdb_cpulock[cpu]);
--
--      local_irq_restore(flags);
--}
--
--/*
-- * GDB stub needs to call kgdb_wait on all processor with interrupts
-- * disabled, so it uses it's own special variant.
-- */
--static int kgdb_smp_call_kgdb_wait(void)
--{
--#ifdef CONFIG_SMP
--      struct call_data_struct data;
--      int i, cpus = num_online_cpus() - 1;
--      int cpu = smp_processor_id();
--
--      /*
--       * Can die spectacularly if this CPU isn't yet marked online
--       */
--      BUG_ON(!cpu_online(cpu));
--
--      if (!cpus)
--              return 0;
--
--      if (spin_is_locked(&smp_call_lock)) {
--              /*
--               * Some other processor is trying to make us do something
--               * but we're not going to respond... give up
--               */
--              return -1;
--              }
--
--      /*
--       * We will continue here, accepting the fact that
--       * the kernel may deadlock if another CPU attempts
--       * to call smp_call_function now...
--       */
--
--      data.func = kgdb_wait;
--      data.info = NULL;
--      atomic_set(&data.started, 0);
--      data.wait = 0;
--
--      spin_lock(&smp_call_lock);
--      call_data = &data;
--      mb();
--
--      /* Send a message to all other CPUs and wait for them to respond */
--      for (i = 0; i < NR_CPUS; i++)
--              if (cpu_online(i) && i != cpu)
--                      core_send_ipi(i, SMP_CALL_FUNCTION);
--
--      /* Wait for response */
--      /* FIXME: lock-up detection, backtrace on lock-up */
--      while (atomic_read(&data.started) != cpus)
--              barrier();
--
--      call_data = NULL;
--      spin_unlock(&smp_call_lock);
--#endif
--
--      return 0;
--}
--
--/*
-- * This function does all command processing for interfacing to gdb.  It
-- * returns 1 if you should skip the instruction at the trap address, 0
-- * otherwise.
-- */
--void handle_exception (struct gdb_regs *regs)
--{
--      int trap;                       /* Trap type */
--      int sigval;
--      long addr;
--      int length;
--      char *ptr;
--      unsigned long *stack;
--      int i;
--      int bflag = 0;
--
--      kgdb_started = 1;
--
--      /*
--       * acquire the big kgdb spinlock
--       */
--      if (!spin_trylock(&kgdb_lock)) {
--              /*
--               * some other CPU has the lock, we should go back to
--               * receive the gdb_wait IPC
--               */
--              return;
--      }
--
--      /*
--       * If we're in async_breakpoint(), restore the real EPC from
--       * the breakpoint.
--       */
--      if (regs->cp0_epc == (unsigned long)async_breakinst) {
--              regs->cp0_epc = async_bp.addr;
--              async_bp.addr = 0;
--      }
--
--      /*
--       * acquire the CPU spinlocks
--       */
--      for (i = num_online_cpus()-1; i >= 0; i--)
--              if (__raw_spin_trylock(&kgdb_cpulock[i]) == 0)
--                      panic("kgdb: couldn't get cpulock %d\n", i);
--
--      /*
--       * force other cpus to enter kgdb
--       */
--      kgdb_smp_call_kgdb_wait();
--
--      /*
--       * If we're in breakpoint() increment the PC
--       */
--      trap = (regs->cp0_cause & 0x7c) >> 2;
--      if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst)
--              regs->cp0_epc += 4;
--
--      /*
--       * If we were single_stepping, restore the opcodes hoisted
--       * for the breakpoint[s].
--       */
--      if (step_bp[0].addr) {
--              *(unsigned *)step_bp[0].addr = step_bp[0].val;
--              step_bp[0].addr = 0;
--
--              if (step_bp[1].addr) {
--                      *(unsigned *)step_bp[1].addr = step_bp[1].val;
--                      step_bp[1].addr = 0;
--              }
--      }
--
--      stack = (long *)regs->reg29;                    /* stack ptr */
--      sigval = computeSignal(trap);
--
--      /*
--       * reply to host that an exception has occurred
--       */
--      ptr = output_buffer;
--
--      /*
--       * Send trap type (converted to signal)
--       */
--      *ptr++ = 'T';
--      *ptr++ = hexchars[sigval >> 4];
--      *ptr++ = hexchars[sigval & 0xf];
--
--      /*
--       * Send Error PC
--       */
--      *ptr++ = hexchars[REG_EPC >> 4];
--      *ptr++ = hexchars[REG_EPC & 0xf];
--      *ptr++ = ':';
--      ptr = mem2hex((char *)&regs->cp0_epc, ptr, sizeof(long), 0);
--      *ptr++ = ';';
--
--      /*
--       * Send frame pointer
--       */
--      *ptr++ = hexchars[REG_FP >> 4];
--      *ptr++ = hexchars[REG_FP & 0xf];
--      *ptr++ = ':';
--      ptr = mem2hex((char *)&regs->reg30, ptr, sizeof(long), 0);
--      *ptr++ = ';';
--
--      /*
--       * Send stack pointer
--       */
--      *ptr++ = hexchars[REG_SP >> 4];
--      *ptr++ = hexchars[REG_SP & 0xf];
--      *ptr++ = ':';
--      ptr = mem2hex((char *)&regs->reg29, ptr, sizeof(long), 0);
--      *ptr++ = ';';
--
--      *ptr++ = 0;
--      putpacket(output_buffer);       /* send it off... */
--
--      /*
--       * Wait for input from remote GDB
--       */
--      while (1) {
--              output_buffer[0] = 0;
--              getpacket(input_buffer);
--
--              switch (input_buffer[0])
--              {
--              case '?':
--                      output_buffer[0] = 'S';
--                      output_buffer[1] = hexchars[sigval >> 4];
--                      output_buffer[2] = hexchars[sigval & 0xf];
--                      output_buffer[3] = 0;
--                      break;
--
--              /*
--               * Detach debugger; let CPU run
--               */
--              case 'D':
--                      putpacket(output_buffer);
--                      goto finish_kgdb;
--                      break;
--
--              case 'd':
--                      /* toggle debug flag */
--                      break;
--
--              /*
--               * Return the value of the CPU registers
--               */
--              case 'g':
--                      ptr = output_buffer;
--                      ptr = mem2hex((char *)&regs->reg0, ptr, 32*sizeof(long), 0); /* r0...r31 */
--                      ptr = mem2hex((char *)&regs->cp0_status, ptr, 6*sizeof(long), 0); /* cp0 */
--                      ptr = mem2hex((char *)&regs->fpr0, ptr, 32*sizeof(long), 0); /* f0...31 */
--                      ptr = mem2hex((char *)&regs->cp1_fsr, ptr, 2*sizeof(long), 0); /* cp1 */
--                      ptr = mem2hex((char *)&regs->frame_ptr, ptr, 2*sizeof(long), 0); /* frp */
--                      ptr = mem2hex((char *)&regs->cp0_index, ptr, 16*sizeof(long), 0); /* cp0 */
--                      break;
--
--              /*
--               * set the value of the CPU registers - return OK
--               */
--              case 'G':
--              {
--                      ptr = &input_buffer[1];
--                      hex2mem(ptr, (char *)&regs->reg0, 32*sizeof(long), 0, 0);
--                      ptr += 32*(2*sizeof(long));
--                      hex2mem(ptr, (char *)&regs->cp0_status, 6*sizeof(long), 0, 0);
--                      ptr += 6*(2*sizeof(long));
--                      hex2mem(ptr, (char *)&regs->fpr0, 32*sizeof(long), 0, 0);
--                      ptr += 32*(2*sizeof(long));
--                      hex2mem(ptr, (char *)&regs->cp1_fsr, 2*sizeof(long), 0, 0);
--                      ptr += 2*(2*sizeof(long));
--                      hex2mem(ptr, (char *)&regs->frame_ptr, 2*sizeof(long), 0, 0);
--                      ptr += 2*(2*sizeof(long));
--                      hex2mem(ptr, (char *)&regs->cp0_index, 16*sizeof(long), 0, 0);
--                      strcpy(output_buffer,"OK");
--               }
--              break;
--
--              /*
--               * mAA..AA,LLLL  Read LLLL bytes at address AA..AA
--               */
--              case 'm':
--                      ptr = &input_buffer[1];
--
--                      if (hexToLong(&ptr, &addr)
--                              && *ptr++ == ','
--                              && hexToInt(&ptr, &length)) {
--                              if (mem2hex((char *)addr, output_buffer, length, 1))
--                                      break;
--                              strcpy (output_buffer, "E03");
--                      } else
--                              strcpy(output_buffer,"E01");
--                      break;
--
--              /*
--               * XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA
--               */
--              case 'X':
--                      bflag = 1;
--                      /* fall through */
--
--              /*
--               * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
--               */
--              case 'M':
--                      ptr = &input_buffer[1];
--
--                      if (hexToLong(&ptr, &addr)
--                              && *ptr++ == ','
--                              && hexToInt(&ptr, &length)
--                              && *ptr++ == ':') {
--                              if (hex2mem(ptr, (char *)addr, length, bflag, 1))
--                                      strcpy(output_buffer, "OK");
--                              else
--                                      strcpy(output_buffer, "E03");
--                      }
--                      else
--                              strcpy(output_buffer, "E02");
--                      break;
--
--              /*
--               * cAA..AA    Continue at address AA..AA(optional)
--               */
--              case 'c':
--                      /* try to read optional parameter, pc unchanged if no parm */
--
--                      ptr = &input_buffer[1];
--                      if (hexToLong(&ptr, &addr))
--                              regs->cp0_epc = addr;
--
--                      goto exit_kgdb_exception;
--                      break;
--
--              /*
--               * kill the program; let us try to restart the machine
--               * Reset the whole machine.
--               */
--              case 'k':
--              case 'r':
--                      machine_restart("kgdb restarts machine");
--                      break;
--
--              /*
--               * Step to next instruction
--               */
--              case 's':
--                      /*
--                       * There is no single step insn in the MIPS ISA, so we
--                       * use breakpoints and continue, instead.
--                       */
--                      single_step(regs);
--                      goto exit_kgdb_exception;
--                      /* NOTREACHED */
--                      break;
--
--              /*
--               * Set baud rate (bBB)
--               * FIXME: Needs to be written
--               */
--              case 'b':
--              {
--#if 0
--                      int baudrate;
--                      extern void set_timer_3();
--
--                      ptr = &input_buffer[1];
--                      if (!hexToInt(&ptr, &baudrate))
--                      {
--                              strcpy(output_buffer,"B01");
--                              break;
--                      }
--
--                      /* Convert baud rate to uart clock divider */
--
--                      switch (baudrate)
--                      {
--                              case 38400:
--                                      baudrate = 16;
--                                      break;
--                              case 19200:
--                                      baudrate = 33;
--                                      break;
--                              case 9600:
--                                      baudrate = 65;
--                                      break;
--                              default:
--                                      baudrate = 0;
--                                      strcpy(output_buffer,"B02");
--                                      goto x1;
--                      }
--
--                      if (baudrate) {
--                              putpacket("OK");        /* Ack before changing speed */
--                              set_timer_3(baudrate); /* Set it */
--                      }
--#endif
--              }
--              break;
--
--              }                       /* switch */
--
--              /*
--               * reply to the request
--               */
--
--              putpacket(output_buffer);
--
--      } /* while */
--
--      return;
--
--finish_kgdb:
--      restore_debug_traps();
--
--exit_kgdb_exception:
--      /* release locks so other CPUs can go */
--      for (i = num_online_cpus()-1; i >= 0; i--)
--              __raw_spin_unlock(&kgdb_cpulock[i]);
--      spin_unlock(&kgdb_lock);
--
--      __flush_cache_all();
--      return;
--}
--
--/*
-- * This function will generate a breakpoint exception.  It is used at the
-- * beginning of a program to sync up with a debugger and can be used
-- * otherwise as a quick means to stop program execution and "break" into
-- * the debugger.
-- */
--void breakpoint(void)
--{
--      if (!initialized)
--              return;
--
--      __asm__ __volatile__(
--                      ".globl breakinst\n\t"
--                      ".set\tnoreorder\n\t"
--                      "nop\n"
--                      "breakinst:\tbreak\n\t"
--                      "nop\n\t"
--                      ".set\treorder"
--                      );
--}
--
--/* Nothing but the break; don't pollute any registers */
--void async_breakpoint(void)
--{
--      __asm__ __volatile__(
--                      ".globl async_breakinst\n\t"
--                      ".set\tnoreorder\n\t"
--                      "nop\n"
--                      "async_breakinst:\tbreak\n\t"
--                      "nop\n\t"
--                      ".set\treorder"
--                      );
--}
--
--void adel(void)
--{
--      __asm__ __volatile__(
--                      ".globl\tadel\n\t"
--                      "lui\t$8,0x8000\n\t"
--                      "lw\t$9,1($8)\n\t"
--                      );
--}
--
--/*
-- * malloc is needed by gdb client in "call func()", even a private one
-- * will make gdb happy
-- */
--static void * __attribute_used__ malloc(size_t size)
--{
--      return kmalloc(size, GFP_ATOMIC);
--}
--
--static void __attribute_used__ free (void *where)
--{
--      kfree(where);
--}
--
--#ifdef CONFIG_GDB_CONSOLE
--
--void gdb_putsn(const char *str, int l)
--{
--      char outbuf[18];
--
--      if (!kgdb_started)
--              return;
--
--      outbuf[0]='O';
--
--      while(l) {
--              int i = (l>8)?8:l;
--              mem2hex((char *)str, &outbuf[1], i, 0);
--              outbuf[(i*2)+1]=0;
--              putpacket(outbuf);
--              str += i;
--              l -= i;
--      }
--}
--
--static void gdb_console_write(struct console *con, const char *s, unsigned n)
--{
--      gdb_putsn(s, n);
--}
--
--static struct console gdb_console = {
--      .name   = "gdb",
--      .write  = gdb_console_write,
--      .flags  = CON_PRINTBUFFER,
--      .index  = -1
--};
--
--static int __init register_gdb_console(void)
--{
--      register_console(&gdb_console);
--
--      return 0;
--}
--
--console_initcall(register_gdb_console);
--
--#endif
-diff -Nurb linux-2.6.22-570/arch/mips/kernel/irq.c linux-2.6.22-590/arch/mips/kernel/irq.c
---- linux-2.6.22-570/arch/mips/kernel/irq.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/kernel/irq.c    2008-01-02 13:56:37.000000000 -0500
-@@ -25,6 +25,10 @@
- #include <asm/atomic.h>
- #include <asm/system.h>
- #include <asm/uaccess.h>
-+#include <asm/kgdb.h>
-+
-+/* Keep track of if we've done certain initialization already or not. */
-+int kgdb_early_setup;
- static unsigned long irq_map[NR_IRQS / BITS_PER_LONG];
-@@ -138,28 +142,23 @@
-       atomic_inc(&irq_err_count);
- }
--#ifdef CONFIG_KGDB
--extern void breakpoint(void);
--extern void set_debug_traps(void);
--
--static int kgdb_flag = 1;
--static int __init nokgdb(char *str)
-+void __init init_IRQ(void)
- {
--      kgdb_flag = 0;
--      return 1;
--}
--__setup("nokgdb", nokgdb);
-+
-+#ifdef CONFIG_KGDB
-+      if (kgdb_early_setup)
-+              return;
- #endif
--void __init init_IRQ(void)
--{
-       arch_init_irq();
-+
- #ifdef CONFIG_KGDB
--      if (kgdb_flag) {
--              printk("Wait for gdb client connection ...\n");
--              set_debug_traps();
--              breakpoint();
--      }
-+      /*
-+       * We have been called before kgdb_arch_init(). Hence,
-+       * we dont want the traps to be reinitialized
-+       */
-+      if (kgdb_early_setup == 0)
-+              kgdb_early_setup = 1;
- #endif
- }
-diff -Nurb linux-2.6.22-570/arch/mips/kernel/kgdb-jmp.c linux-2.6.22-590/arch/mips/kernel/kgdb-jmp.c
---- linux-2.6.22-570/arch/mips/kernel/kgdb-jmp.c       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/mips/kernel/kgdb-jmp.c       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,110 @@
-+/*
-+ * arch/mips/kernel/kgdb-jmp.c
-+ *
-+ * Save and restore system registers so that within a limited frame we
-+ * may have a fault and "jump back" to a known safe location.
-+ *
-+ * Author: Tom Rini <trini@kernel.crashing.org>
-+ * Author: Manish Lachwani <mlachwani@mvista.com>
-+ *
-+ * Cribbed from glibc, which carries the following:
-+ * Copyright (C) 1996, 1997, 2000, 2002, 2003 Free Software Foundation, Inc.
-+ * Copyright (C) 2005-2006 by MontaVista Software.
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program as licensed "as is" without any warranty of
-+ * any kind, whether express or implied.
-+ */
-+
-+#include <linux/kgdb.h>
-+
-+#ifdef CONFIG_64BIT
-+/*
-+ * MIPS 64-bit
-+ */
-+
-+int kgdb_fault_setjmp_aux(unsigned long *curr_context, unsigned long sp, unsigned long fp)
-+{
-+      __asm__ __volatile__ ("sd $gp, %0" : : "m" (curr_context[0]));
-+      __asm__ __volatile__ ("sd $16, %0" : : "m" (curr_context[1]));
-+      __asm__ __volatile__ ("sd $17, %0" : : "m" (curr_context[2]));
-+      __asm__ __volatile__ ("sd $18, %0" : : "m" (curr_context[3]));
-+      __asm__ __volatile__ ("sd $19, %0" : : "m" (curr_context[4]));
-+      __asm__ __volatile__ ("sd $20, %0" : : "m" (curr_context[5]));
-+      __asm__ __volatile__ ("sd $21, %0" : : "m" (curr_context[6]));
-+      __asm__ __volatile__ ("sd $22, %0" : : "m" (curr_context[7]));
-+      __asm__ __volatile__ ("sd $23, %0" : : "m" (curr_context[8]));
-+      __asm__ __volatile__ ("sd $31, %0" : : "m" (curr_context[9]));
-+      curr_context[10] = sp;
-+      curr_context[11] = fp;
-+
-+      return 0;
-+}
-+
-+void kgdb_fault_longjmp(unsigned long *curr_context)
-+{
-+      __asm__ __volatile__ ("ld $gp, %0" : : "m" (curr_context[0]));
-+      __asm__ __volatile__ ("ld $16, %0" : : "m" (curr_context[1]));
-+      __asm__ __volatile__ ("ld $17, %0" : : "m" (curr_context[2]));
-+      __asm__ __volatile__ ("ld $18, %0" : : "m" (curr_context[3]));
-+      __asm__ __volatile__ ("ld $19, %0" : : "m" (curr_context[4]));
-+      __asm__ __volatile__ ("ld $20, %0" : : "m" (curr_context[5]));
-+      __asm__ __volatile__ ("ld $21, %0" : : "m" (curr_context[6]));
-+      __asm__ __volatile__ ("ld $22, %0" : : "m" (curr_context[7]));
-+      __asm__ __volatile__ ("ld $23, %0" : : "m" (curr_context[8]));
-+      __asm__ __volatile__ ("ld $25, %0" : : "m" (curr_context[9]));
-+      __asm__ __volatile__ ("ld $29, %0\n\t"
-+                            "ld $30, %1\n\t" : :
-+                            "m" (curr_context[10]), "m" (curr_context[11]));
-+
-+      __asm__ __volatile__ ("dli $2, 1");
-+      __asm__ __volatile__ ("j $25");
-+
-+      for (;;);
-+}
-+#else
-+/*
-+ * MIPS 32-bit
-+ */
-+
-+int kgdb_fault_setjmp_aux(unsigned long *curr_context, unsigned long sp, unsigned long fp)
-+{
-+      __asm__ __volatile__("sw $gp, %0" : : "m" (curr_context[0]));
-+      __asm__ __volatile__("sw $16, %0" : : "m" (curr_context[1]));
-+      __asm__ __volatile__("sw $17, %0" : : "m" (curr_context[2]));
-+      __asm__ __volatile__("sw $18, %0" : : "m" (curr_context[3]));
-+      __asm__ __volatile__("sw $19, %0" : : "m" (curr_context[4]));
-+      __asm__ __volatile__("sw $20, %0" : : "m" (curr_context[5]));
-+      __asm__ __volatile__("sw $21, %0" : : "m" (curr_context[6]));
-+      __asm__ __volatile__("sw $22, %0" : : "m" (curr_context[7]));
-+      __asm__ __volatile__("sw $23, %0" : : "m" (curr_context[8]));
-+      __asm__ __volatile__("sw $31, %0" : : "m" (curr_context[9]));
-+      curr_context[10] = sp;
-+      curr_context[11] = fp;
-+
-+      return 0;
-+}
-+
-+void kgdb_fault_longjmp(unsigned long *curr_context)
-+{
-+      __asm__ __volatile__("lw $gp, %0" : : "m" (curr_context[0]));
-+      __asm__ __volatile__("lw $16, %0" : : "m" (curr_context[1]));
-+      __asm__ __volatile__("lw $17, %0" : : "m" (curr_context[2]));
-+      __asm__ __volatile__("lw $18, %0" : : "m" (curr_context[3]));
-+      __asm__ __volatile__("lw $19, %0" : : "m" (curr_context[4]));
-+      __asm__ __volatile__("lw $20, %0" : : "m" (curr_context[5]));
-+      __asm__ __volatile__("lw $21, %0" : : "m" (curr_context[6]));
-+      __asm__ __volatile__("lw $22, %0" : : "m" (curr_context[7]));
-+      __asm__ __volatile__("lw $23, %0" : : "m" (curr_context[8]));
-+      __asm__ __volatile__("lw $25, %0" : : "m" (curr_context[9]));
-+
-+      __asm__ __volatile__("lw $29, %0\n\t"
-+                           "lw $30, %1\n\t" : :
-+                           "m" (curr_context[10]), "m" (curr_context[11]));
-+
-+      __asm__ __volatile__("li $2, 1");
-+      __asm__ __volatile__("jr $25");
-+
-+      for (;;);
-+}
-+#endif
-diff -Nurb linux-2.6.22-570/arch/mips/kernel/kgdb-setjmp.S linux-2.6.22-590/arch/mips/kernel/kgdb-setjmp.S
---- linux-2.6.22-570/arch/mips/kernel/kgdb-setjmp.S    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/mips/kernel/kgdb-setjmp.S    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,28 @@
-+/*
-+ * arch/mips/kernel/kgdb-jmp.c
-+ *
-+ * Save and restore system registers so that within a limited frame we
-+ * may have a fault and "jump back" to a known safe location.
-+ *
-+ * Copyright (C) 2005 by MontaVista Software.
-+ * Author: Manish Lachwani (mlachwani@mvista.com)
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program as licensed "as is" without any warranty of
-+ * any kind, whether express or implied.
-+ */
-+
-+#include <asm/asm.h>
-+#include <asm/mipsregs.h>
-+#include <asm/regdef.h>
-+#include <asm/stackframe.h>
-+
-+      .ent    kgdb_fault_setjmp,0
-+ENTRY (kgdb_fault_setjmp)
-+      move    a1, sp
-+      move    a2, fp
-+#ifdef CONFIG_64BIT
-+      nop
-+#endif
-+      j       kgdb_fault_setjmp_aux
-+      .end    kgdb_fault_setjmp
-diff -Nurb linux-2.6.22-570/arch/mips/kernel/kgdb.c linux-2.6.22-590/arch/mips/kernel/kgdb.c
---- linux-2.6.22-570/arch/mips/kernel/kgdb.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/mips/kernel/kgdb.c   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,299 @@
-+/*
-+ * arch/mips/kernel/kgdb.c
-+ *
-+ *  Originally written by Glenn Engel, Lake Stevens Instrument Division
-+ *
-+ *  Contributed by HP Systems
-+ *
-+ *  Modified for SPARC by Stu Grossman, Cygnus Support.
-+ *
-+ *  Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
-+ *  Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
-+ *
-+ *  Copyright (C) 1995 Andreas Busse
-+ *
-+ *  Copyright (C) 2003 MontaVista Software Inc.
-+ *  Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
-+ *
-+ *  Copyright (C) 2004-2005 MontaVista Software Inc.
-+ *  Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com
-+ *
-+ *  This file is licensed under the terms of the GNU General Public License
-+ *  version 2. This program is licensed "as is" without any warranty of any
-+ *  kind, whether express or implied.
-+ */
-+
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/smp.h>
-+#include <linux/spinlock.h>
-+#include <linux/delay.h>
-+#include <asm/system.h>
-+#include <asm/ptrace.h>               /* for linux pt_regs struct */
-+#include <linux/kgdb.h>
-+#include <linux/init.h>
-+#include <linux/kdebug.h>
-+#include <asm/inst.h>
-+#include <asm/gdb-stub.h>
-+#include <asm/cacheflush.h>
-+#include <asm/kdebug.h>
-+
-+static struct hard_trap_info {
-+      unsigned char tt;       /* Trap type code for MIPS R3xxx and R4xxx */
-+      unsigned char signo;    /* Signal that we map this trap into */
-+} hard_trap_info[] = {
-+      { 6, SIGBUS },          /* instruction bus error */
-+      { 7, SIGBUS },          /* data bus error */
-+      { 9, SIGTRAP },         /* break */
-+/*    { 11, SIGILL }, */      /* CPU unusable */
-+      { 12, SIGFPE },         /* overflow */
-+      { 13, SIGTRAP },        /* trap */
-+      { 14, SIGSEGV },        /* virtual instruction cache coherency */
-+      { 15, SIGFPE },         /* floating point exception */
-+      { 23, SIGSEGV },        /* watch */
-+      { 31, SIGSEGV },        /* virtual data cache coherency */
-+      { 0, 0}                 /* Must be last */
-+};
-+
-+/* Save the normal trap handlers for user-mode traps. */
-+void *saved_vectors[32];
-+
-+extern void trap_low(void);
-+extern void breakinst(void);
-+extern void init_IRQ(void);
-+
-+void kgdb_call_nmi_hook(void *ignored)
-+{
-+      kgdb_nmihook(smp_processor_id(), (void *)0);
-+}
-+
-+void kgdb_roundup_cpus(unsigned long flags)
-+{
-+      local_irq_enable();
-+      smp_call_function(kgdb_call_nmi_hook, 0, 0, 0);
-+      local_irq_disable();
-+}
-+
-+static int compute_signal(int tt)
-+{
-+      struct hard_trap_info *ht;
-+
-+      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
-+              if (ht->tt == tt)
-+                      return ht->signo;
-+
-+      return SIGHUP;          /* default for things we don't know about */
-+}
-+
-+/*
-+ * Set up exception handlers for tracing and breakpoints
-+ */
-+void handle_exception(struct pt_regs *regs)
-+{
-+      int trap = (regs->cp0_cause & 0x7c) >> 2;
-+
-+      if (fixup_exception(regs)) {
-+              return;
-+      }
-+
-+      if (atomic_read(&debugger_active))
-+              kgdb_nmihook(smp_processor_id(), regs);
-+
-+      if (atomic_read(&kgdb_setting_breakpoint))
-+              if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst))
-+                      regs->cp0_epc += 4;
-+
-+      kgdb_handle_exception(0, compute_signal(trap), 0, regs);
-+
-+      /* In SMP mode, __flush_cache_all does IPI */
-+      local_irq_enable();
-+      __flush_cache_all();
-+}
-+
-+void set_debug_traps(void)
-+{
-+      struct hard_trap_info *ht;
-+      unsigned long flags;
-+
-+      local_irq_save(flags);
-+
-+      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
-+              saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low);
-+
-+      local_irq_restore(flags);
-+}
-+
-+#if 0
-+/* This should be called before we exit kgdb_handle_exception() I believe.
-+ * -- Tom
-+ */
-+void restore_debug_traps(void)
-+{
-+      struct hard_trap_info *ht;
-+      unsigned long flags;
-+
-+      local_irq_save(flags);
-+      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
-+              set_except_vector(ht->tt, saved_vectors[ht->tt]);
-+      local_irq_restore(flags);
-+}
-+#endif
-+
-+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-+{
-+      int reg;
-+      gdb_reg_t *ptr = (gdb_reg_t*)gdb_regs;
-+
-+      for (reg = 0; reg < 32; reg++)
-+              *(ptr++) = regs->regs[reg];
-+
-+      *(ptr++) = regs->cp0_status;
-+      *(ptr++) = regs->lo;
-+      *(ptr++) = regs->hi;
-+      *(ptr++) = regs->cp0_badvaddr;
-+      *(ptr++) = regs->cp0_cause;
-+      *(ptr++) = regs->cp0_epc;
-+
-+      return;
-+}
-+
-+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-+{
-+
-+      int reg;
-+      const gdb_reg_t *ptr = (gdb_reg_t*)gdb_regs;
-+
-+      for (reg = 0; reg < 32; reg++)
-+              regs->regs[reg] = *(ptr++);
-+
-+      regs->cp0_status = *(ptr++);
-+      regs->lo = *(ptr++);
-+      regs->hi = *(ptr++);
-+      regs->cp0_badvaddr = *(ptr++);
-+      regs->cp0_cause = *(ptr++);
-+      regs->cp0_epc = *(ptr++);
-+
-+      return;
-+}
-+
-+/*
-+ * Similar to regs_to_gdb_regs() except that process is sleeping and so
-+ * we may not be able to get all the info.
-+ */
-+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
-+{
-+      int reg;
-+      struct thread_info *ti = task_thread_info(p);
-+      unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32;
-+      struct pt_regs *regs = (struct pt_regs *)ksp - 1;
-+      gdb_reg_t *ptr = (gdb_reg_t*)gdb_regs;
-+
-+      for (reg = 0; reg < 16; reg++)
-+              *(ptr++) = regs->regs[reg];
-+
-+      /* S0 - S7 */
-+      for (reg = 16; reg < 24; reg++)
-+              *(ptr++) = regs->regs[reg];
-+
-+      for (reg = 24; reg < 28; reg++)
-+              *(ptr++) = 0;
-+
-+      /* GP, SP, FP, RA */
-+      for (reg = 28; reg < 32; reg++)
-+              *(ptr++) = regs->regs[reg];
-+
-+      *(ptr++) = regs->cp0_status;
-+      *(ptr++) = regs->lo;
-+      *(ptr++) = regs->hi;
-+      *(ptr++) = regs->cp0_badvaddr;
-+      *(ptr++) = regs->cp0_cause;
-+      *(ptr++) = regs->cp0_epc;
-+
-+      return;
-+}
-+
-+/*
-+ * Calls linux_debug_hook before the kernel dies. If KGDB is enabled,
-+ * then try to fall into the debugger
-+ */
-+static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
-+                          void *ptr)
-+{
-+      struct die_args *args = (struct die_args *)ptr;
-+      struct pt_regs *regs = args->regs;
-+      int trap = (regs->cp0_cause & 0x7c) >> 2;
-+
-+      /* See if KGDB is interested. */
-+      if (user_mode(regs))
-+              /* Userpace events, ignore. */
-+              return NOTIFY_DONE;
-+
-+      kgdb_handle_exception(trap, compute_signal(trap), 0, regs);
-+      return NOTIFY_OK;
-+}
-+
-+static struct notifier_block kgdb_notifier = {
-+      .notifier_call = kgdb_mips_notify,
-+};
-+
-+/*
-+ * Handle the 's' and 'c' commands
-+ */
-+int kgdb_arch_handle_exception(int vector, int signo, int err_code,
-+                             char *remcom_in_buffer, char *remcom_out_buffer,
-+                             struct pt_regs *regs)
-+{
-+      char *ptr;
-+      unsigned long address;
-+      int cpu = smp_processor_id();
-+
-+      switch (remcom_in_buffer[0]) {
-+      case 's':
-+      case 'c':
-+              /* handle the optional parameter */
-+              ptr = &remcom_in_buffer[1];
-+              if (kgdb_hex2long(&ptr, &address))
-+                      regs->cp0_epc = address;
-+
-+              atomic_set(&cpu_doing_single_step, -1);
-+              if (remcom_in_buffer[0] == 's')
-+                      if (kgdb_contthread)
-+                              atomic_set(&cpu_doing_single_step, cpu);
-+
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+struct kgdb_arch arch_kgdb_ops = {
-+#ifdef CONFIG_CPU_LITTLE_ENDIAN
-+      .gdb_bpt_instr = {0xd},
-+#else
-+      .gdb_bpt_instr = {0x00, 0x00, 0x00, 0x0d},
-+#endif
-+};
-+
-+/*
-+ * We use kgdb_early_setup so that functions we need to call now don't
-+ * cause trouble when called again later.
-+ */
-+__init int kgdb_arch_init(void)
-+{
-+      /* Board-specifics. */
-+      /* Force some calls to happen earlier. */
-+      if (kgdb_early_setup == 0) {
-+              trap_init();
-+              init_IRQ();
-+              kgdb_early_setup = 1;
-+      }
-+
-+      /* Set our traps. */
-+      /* This needs to be done more finely grained again, paired in
-+       * a before/after in kgdb_handle_exception(...) -- Tom */
-+      set_debug_traps();
-+      register_die_notifier(&kgdb_notifier);
-+
-+      return 0;
-+}
-diff -Nurb linux-2.6.22-570/arch/mips/kernel/kgdb_handler.S linux-2.6.22-590/arch/mips/kernel/kgdb_handler.S
---- linux-2.6.22-570/arch/mips/kernel/kgdb_handler.S   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/mips/kernel/kgdb_handler.S   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,339 @@
-+/*
-+ * arch/mips/kernel/kgdb_handler.S
-+ *
-+ * Copyright (C) 2007 Wind River Systems, Inc
-+ *
-+ * Copyright (C) 2004-2005 MontaVista Software Inc.
-+ * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com
-+ *
-+ * This file is licensed under the terms of the GNU General Public
-+ * version 2. This program is licensed "as is" without any warranty of any
-+ * kind, whether express or implied.
-+ */
-+
-+/*
-+ * Trap Handler for the new KGDB framework. The main KGDB handler is
-+ * handle_exception that will be called from here
-+ *
-+ */
-+
-+#include <linux/sys.h>
-+
-+#include <asm/asm.h>
-+#include <asm/errno.h>
-+#include <asm/mipsregs.h>
-+#include <asm/regdef.h>
-+#include <asm/stackframe.h>
-+#include <asm/gdb-stub.h>
-+
-+#ifdef CONFIG_32BIT
-+#define DMFC0 mfc0
-+#define DMTC0 mtc0
-+#define LDC1  lwc1
-+#define SDC1  swc1
-+#endif
-+#ifdef CONFIG_64BIT
-+#define DMFC0 dmfc0
-+#define DMTC0 dmtc0
-+#define LDC1  ldc1
-+#define SDC1  sdc1
-+#endif
-+
-+#include <asm/asmmacro.h>
-+
-+/*
-+ * [jsun] We reserves about 2x GDB_FR_SIZE in stack.  The lower (addressed)
-+ * part is used to store registers and passed to exception handler.
-+ * The upper part is reserved for "call func" feature where gdb client
-+ * saves some of the regs, setups call frame and passes args.
-+ *
-+ * A trace shows about 200 bytes are used to store about half of all regs.
-+ * The rest should be big enough for frame setup and passing args.
-+ */
-+
-+/*
-+ * The low level trap handler
-+ */
-+              .align  5
-+              NESTED(trap_low, GDB_FR_SIZE, sp)
-+              .set    noat
-+              .set    noreorder
-+
-+              mfc0    k0, CP0_STATUS
-+              sll     k0, 3                   /* extract cu0 bit */
-+              bltz    k0, 1f
-+              move    k1, sp
-+
-+              /*
-+               * Called from user mode, go somewhere else.
-+               */
-+#if defined(CONFIG_32BIT)
-+              lui     k1, %hi(saved_vectors)
-+              mfc0    k0, CP0_CAUSE
-+              andi    k0, k0, 0x7c
-+              add     k1, k1, k0
-+              lw      k0, %lo(saved_vectors)(k1)
-+#elif defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64)
-+              DMFC0   k0, CP0_CAUSE
-+              lui     k1, %highest(saved_vectors)
-+                andi    k0, k0, 0x7c           /* mask exception type */
-+                dsll    k0, 1                  /* turn into byte offset */
-+              daddiu  k1, %higher(saved_vectors)
-+              dsll    k1, k1, 16
-+              daddiu  k1, %hi(saved_vectors)
-+              dsll    k1, k1, 16
-+              daddu   k1, k1, k0
-+              LONG_L  k0, %lo(saved_vectors)(k1)
-+#else
-+#error "MIPS configuration is unsupported for kgdb!!"
-+#endif
-+              jr      k0
-+              nop
-+1:
-+              move    k0, sp
-+              PTR_SUBU sp, k1, GDB_FR_SIZE*2  # see comment above
-+              LONG_S  k0, GDB_FR_REG29(sp)
-+              LONG_S  $2, GDB_FR_REG2(sp)
-+
-+/*
-+ * First save the CP0 and special registers
-+ */
-+
-+              mfc0    v0, CP0_STATUS
-+              LONG_S  v0, GDB_FR_STATUS(sp)
-+              mfc0    v0, CP0_CAUSE
-+              LONG_S  v0, GDB_FR_CAUSE(sp)
-+              DMFC0   v0, CP0_EPC
-+              LONG_S  v0, GDB_FR_EPC(sp)
-+              DMFC0   v0, CP0_BADVADDR
-+              LONG_S  v0, GDB_FR_BADVADDR(sp)
-+              mfhi    v0
-+              LONG_S  v0, GDB_FR_HI(sp)
-+              mflo    v0
-+              LONG_S  v0, GDB_FR_LO(sp)
-+
-+/*
-+ * Now the integer registers
-+ */
-+
-+              LONG_S  zero, GDB_FR_REG0(sp)           /* I know... */
-+              LONG_S  $1, GDB_FR_REG1(sp)
-+              /* v0 already saved */
-+              LONG_S  $3, GDB_FR_REG3(sp)
-+              LONG_S  $4, GDB_FR_REG4(sp)
-+              LONG_S  $5, GDB_FR_REG5(sp)
-+              LONG_S  $6, GDB_FR_REG6(sp)
-+              LONG_S  $7, GDB_FR_REG7(sp)
-+              LONG_S  $8, GDB_FR_REG8(sp)
-+              LONG_S  $9, GDB_FR_REG9(sp)
-+              LONG_S  $10, GDB_FR_REG10(sp)
-+              LONG_S  $11, GDB_FR_REG11(sp)
-+              LONG_S  $12, GDB_FR_REG12(sp)
-+              LONG_S  $13, GDB_FR_REG13(sp)
-+              LONG_S  $14, GDB_FR_REG14(sp)
-+              LONG_S  $15, GDB_FR_REG15(sp)
-+              LONG_S  $16, GDB_FR_REG16(sp)
-+              LONG_S  $17, GDB_FR_REG17(sp)
-+              LONG_S  $18, GDB_FR_REG18(sp)
-+              LONG_S  $19, GDB_FR_REG19(sp)
-+              LONG_S  $20, GDB_FR_REG20(sp)
-+              LONG_S  $21, GDB_FR_REG21(sp)
-+              LONG_S  $22, GDB_FR_REG22(sp)
-+              LONG_S  $23, GDB_FR_REG23(sp)
-+              LONG_S  $24, GDB_FR_REG24(sp)
-+              LONG_S  $25, GDB_FR_REG25(sp)
-+              LONG_S  $26, GDB_FR_REG26(sp)
-+              LONG_S  $27, GDB_FR_REG27(sp)
-+              LONG_S  $28, GDB_FR_REG28(sp)
-+              /* sp already saved */
-+              LONG_S  $30, GDB_FR_REG30(sp)
-+              LONG_S  $31, GDB_FR_REG31(sp)
-+
-+              CLI                             /* disable interrupts */
-+
-+/*
-+ * Followed by the floating point registers
-+ */
-+              mfc0    v0, CP0_STATUS          /* FPU enabled? */
-+              srl     v0, v0, 16
-+              andi    v0, v0, (ST0_CU1 >> 16)
-+
-+              beqz    v0,3f                   /* disabled, skip */
-+               nop
-+
-+              li      t0, 0
-+#ifdef CONFIG_64BIT
-+              mfc0    t0, CP0_STATUS
-+#endif
-+              fpu_save_double_kgdb sp t0 t1   # clobbers t1
-+
-+
-+/*
-+ * Current stack frame ptr
-+ */
-+
-+3:
-+              LONG_S  sp, GDB_FR_FRP(sp)
-+
-+/*
-+ * CP0 registers (R4000/R4400 unused registers skipped)
-+ */
-+
-+              mfc0    v0, CP0_INDEX
-+              LONG_S  v0, GDB_FR_CP0_INDEX(sp)
-+              mfc0    v0, CP0_RANDOM
-+              LONG_S  v0, GDB_FR_CP0_RANDOM(sp)
-+              DMFC0   v0, CP0_ENTRYLO0
-+              LONG_S  v0, GDB_FR_CP0_ENTRYLO0(sp)
-+              DMFC0   v0, CP0_ENTRYLO1
-+              LONG_S  v0, GDB_FR_CP0_ENTRYLO1(sp)
-+              DMFC0   v0, CP0_CONTEXT
-+              LONG_S  v0, GDB_FR_CP0_CONTEXT(sp)
-+              mfc0    v0, CP0_PAGEMASK
-+              LONG_S  v0, GDB_FR_CP0_PAGEMASK(sp)
-+              mfc0    v0, CP0_WIRED
-+              LONG_S  v0, GDB_FR_CP0_WIRED(sp)
-+              DMFC0   v0, CP0_ENTRYHI
-+              LONG_S  v0, GDB_FR_CP0_ENTRYHI(sp)
-+              mfc0    v0, CP0_PRID
-+              LONG_S  v0, GDB_FR_CP0_PRID(sp)
-+
-+              .set    at
-+
-+/*
-+ * Continue with the higher level handler
-+ */
-+
-+              move    a0,sp
-+
-+              jal     handle_exception
-+               nop
-+
-+/*
-+ * Restore all writable registers, in reverse order
-+ */
-+
-+              .set    noat
-+
-+              LONG_L  v0, GDB_FR_CP0_ENTRYHI(sp)
-+              LONG_L  v1, GDB_FR_CP0_WIRED(sp)
-+              DMTC0   v0, CP0_ENTRYHI
-+              mtc0    v1, CP0_WIRED
-+              LONG_L  v0, GDB_FR_CP0_PAGEMASK(sp)
-+              LONG_L  v1, GDB_FR_CP0_ENTRYLO1(sp)
-+              mtc0    v0, CP0_PAGEMASK
-+              DMTC0   v1, CP0_ENTRYLO1
-+              LONG_L  v0, GDB_FR_CP0_ENTRYLO0(sp)
-+              LONG_L  v1, GDB_FR_CP0_INDEX(sp)
-+              DMTC0   v0, CP0_ENTRYLO0
-+              LONG_L  v0, GDB_FR_CP0_CONTEXT(sp)
-+              mtc0    v1, CP0_INDEX
-+              DMTC0   v0, CP0_CONTEXT
-+
-+
-+/*
-+ * Next, the floating point registers
-+ */
-+              mfc0    v0, CP0_STATUS          /* check if the FPU is enabled */
-+              srl     v0, v0, 16
-+              andi    v0, v0, (ST0_CU1 >> 16)
-+
-+              beqz    v0, 3f                  /* disabled, skip */
-+               nop
-+
-+              li      t0, 0
-+#ifdef CONFIG_64BIT
-+              mfc0    t0, CP0_STATUS
-+#endif
-+              fpu_restore_double_kgdb sp t0 t1 # clobbers t1
-+
-+
-+/*
-+ * Now the CP0 and integer registers
-+ */
-+
-+3:
-+              mfc0    t0, CP0_STATUS
-+              ori     t0, 0x1f
-+              xori    t0, 0x1f
-+              mtc0    t0, CP0_STATUS
-+
-+              LONG_L  v0, GDB_FR_STATUS(sp)
-+              LONG_L  v1, GDB_FR_EPC(sp)
-+              mtc0    v0, CP0_STATUS
-+              DMTC0   v1, CP0_EPC
-+              LONG_L  v0, GDB_FR_HI(sp)
-+              LONG_L  v1, GDB_FR_LO(sp)
-+              mthi    v0
-+              mtlo    v1
-+              LONG_L  $31, GDB_FR_REG31(sp)
-+              LONG_L  $30, GDB_FR_REG30(sp)
-+              LONG_L  $28, GDB_FR_REG28(sp)
-+              LONG_L  $27, GDB_FR_REG27(sp)
-+              LONG_L  $26, GDB_FR_REG26(sp)
-+              LONG_L  $25, GDB_FR_REG25(sp)
-+              LONG_L  $24, GDB_FR_REG24(sp)
-+              LONG_L  $23, GDB_FR_REG23(sp)
-+              LONG_L  $22, GDB_FR_REG22(sp)
-+              LONG_L  $21, GDB_FR_REG21(sp)
-+              LONG_L  $20, GDB_FR_REG20(sp)
-+              LONG_L  $19, GDB_FR_REG19(sp)
-+              LONG_L  $18, GDB_FR_REG18(sp)
-+              LONG_L  $17, GDB_FR_REG17(sp)
-+              LONG_L  $16, GDB_FR_REG16(sp)
-+              LONG_L  $15, GDB_FR_REG15(sp)
-+              LONG_L  $14, GDB_FR_REG14(sp)
-+              LONG_L  $13, GDB_FR_REG13(sp)
-+              LONG_L  $12, GDB_FR_REG12(sp)
-+              LONG_L  $11, GDB_FR_REG11(sp)
-+              LONG_L  $10, GDB_FR_REG10(sp)
-+              LONG_L  $9, GDB_FR_REG9(sp)
-+              LONG_L  $8, GDB_FR_REG8(sp)
-+              LONG_L  $7, GDB_FR_REG7(sp)
-+              LONG_L  $6, GDB_FR_REG6(sp)
-+              LONG_L  $5, GDB_FR_REG5(sp)
-+              LONG_L  $4, GDB_FR_REG4(sp)
-+              LONG_L  $3, GDB_FR_REG3(sp)
-+              LONG_L  $2, GDB_FR_REG2(sp)
-+              LONG_L  $1, GDB_FR_REG1(sp)
-+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
-+              LONG_L  k0, GDB_FR_EPC(sp)
-+              LONG_L  $29, GDB_FR_REG29(sp)           /* Deallocate stack */
-+              jr      k0
-+              rfe
-+#else
-+              LONG_L  sp, GDB_FR_REG29(sp)            /* Deallocate stack */
-+
-+              .set    mips3
-+              eret
-+              .set    mips0
-+#endif
-+              .set    at
-+              .set    reorder
-+              END(trap_low)
-+
-+LEAF(kgdb_read_byte)
-+4:            lb      t0, (a0)
-+              sb      t0, (a1)
-+              li      v0, 0
-+              jr      ra
-+              .section __ex_table,"a"
-+              PTR     4b, kgdbfault
-+              .previous
-+              END(kgdb_read_byte)
-+
-+LEAF(kgdb_write_byte)
-+5:            sb      a0, (a1)
-+              li      v0, 0
-+              jr      ra
-+              .section __ex_table,"a"
-+              PTR     5b, kgdbfault
-+              .previous
-+              END(kgdb_write_byte)
-+
-+              .type   kgdbfault@function
-+              .ent    kgdbfault
-+
-+kgdbfault:    li      v0, -EFAULT
-+              jr      ra
-+              .end    kgdbfault
-diff -Nurb linux-2.6.22-570/arch/mips/kernel/traps.c linux-2.6.22-590/arch/mips/kernel/traps.c
---- linux-2.6.22-570/arch/mips/kernel/traps.c  2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/mips/kernel/traps.c  2008-01-02 13:56:37.000000000 -0500
-@@ -10,6 +10,8 @@
-  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
-  * Copyright (C) 2000, 01 MIPS Technologies, Inc.
-  * Copyright (C) 2002, 2003, 2004, 2005  Maciej W. Rozycki
-+ *
-+ * KGDB specific changes - Manish Lachwani (mlachwani@mvista.com)
-  */
- #include <linux/bug.h>
- #include <linux/init.h>
-@@ -21,6 +23,7 @@
- #include <linux/kallsyms.h>
- #include <linux/bootmem.h>
- #include <linux/interrupt.h>
-+#include <linux/kgdb.h>
- #include <asm/bootinfo.h>
- #include <asm/branch.h>
-@@ -42,6 +45,7 @@
- #include <asm/watch.h>
- #include <asm/types.h>
- #include <asm/stacktrace.h>
-+#include <asm/kdebug.h>
- extern asmlinkage void handle_int(void);
- extern asmlinkage void handle_tlbm(void);
-@@ -1445,6 +1449,11 @@
-       extern char except_vec4;
-       unsigned long i;
-+#if defined(CONFIG_KGDB)
-+      if (kgdb_early_setup)
-+              return; /* Already done */
-+#endif
-+
-       if (cpu_has_veic || cpu_has_vint)
-               ebase = (unsigned long) alloc_bootmem_low_pages (0x200 + VECTORSPACING*64);
-       else
-diff -Nurb linux-2.6.22-570/arch/mips/mips-boards/atlas/Makefile linux-2.6.22-590/arch/mips/mips-boards/atlas/Makefile
---- linux-2.6.22-570/arch/mips/mips-boards/atlas/Makefile      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/mips-boards/atlas/Makefile      2008-01-02 13:56:37.000000000 -0500
-@@ -17,4 +17,3 @@
- #
- obj-y                 := atlas_int.o atlas_setup.o
--obj-$(CONFIG_KGDB)    += atlas_gdb.o
-diff -Nurb linux-2.6.22-570/arch/mips/mips-boards/atlas/atlas_gdb.c linux-2.6.22-590/arch/mips/mips-boards/atlas/atlas_gdb.c
---- linux-2.6.22-570/arch/mips/mips-boards/atlas/atlas_gdb.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/mips-boards/atlas/atlas_gdb.c   1969-12-31 19:00:00.000000000 -0500
-@@ -1,97 +0,0 @@
--/*
-- * Carsten Langgaard, carstenl@mips.com
-- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
-- *
-- *  This program is free software; you can distribute it and/or modify it
-- *  under the terms of the GNU General Public License (Version 2) as
-- *  published by the Free Software Foundation.
-- *
-- *  This program is distributed in the hope 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.
-- *
-- * This is the interface to the remote debugger stub.
-- */
--#include <asm/io.h>
--#include <asm/mips-boards/atlas.h>
--#include <asm/mips-boards/saa9730_uart.h>
--
--#define INB(a)     inb((unsigned long)a)
--#define OUTB(x,a)  outb(x,(unsigned long)a)
--
--/*
-- * This is the interface to the remote debugger stub
-- * if the Philips part is used for the debug port,
-- * called from the platform setup code.
-- */
--void *saa9730_base = (void *)ATLAS_SAA9730_REG;
--
--static int saa9730_kgdb_active = 0;
--
--#define SAA9730_BAUDCLOCK(baud) (((ATLAS_SAA9730_BAUDCLOCK/(baud))/16)-1)
--
--int saa9730_kgdb_hook(int speed)
--{
--      int baudclock;
--      t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
--
--        /*
--         * Clear all interrupts
--         */
--      (void) INB(&kgdb_uart->Lsr);
--      (void) INB(&kgdb_uart->Msr);
--      (void) INB(&kgdb_uart->Thr_Rbr);
--      (void) INB(&kgdb_uart->Iir_Fcr);
--
--        /*
--         * Now, initialize the UART
--         */
--      /* 8 data bits, one stop bit, no parity */
--      OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr);
--
--      baudclock = SAA9730_BAUDCLOCK(speed);
--
--      OUTB((baudclock >> 16) & 0xff, &kgdb_uart->BaudDivMsb);
--      OUTB( baudclock        & 0xff, &kgdb_uart->BaudDivLsb);
--
--      /* Set RTS/DTR active */
--      OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr);
--      saa9730_kgdb_active = 1;
--
--      return speed;
--}
--
--int saa9730_putDebugChar(char c)
--{
--      t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
--
--        if (!saa9730_kgdb_active) {     /* need to init device first */
--                return 0;
--        }
--
--        while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE))
--                ;
--      OUTB(c, &kgdb_uart->Thr_Rbr);
--
--        return 1;
--}
--
--char saa9730_getDebugChar(void)
--{
--      t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
--      char c;
--
--        if (!saa9730_kgdb_active) {     /* need to init device first */
--                return 0;
--        }
--        while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR))
--                ;
--
--      c = INB(&kgdb_uart->Thr_Rbr);
--      return(c);
--}
-diff -Nurb linux-2.6.22-570/arch/mips/mips-boards/atlas/atlas_setup.c linux-2.6.22-590/arch/mips/mips-boards/atlas/atlas_setup.c
---- linux-2.6.22-570/arch/mips/mips-boards/atlas/atlas_setup.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/mips-boards/atlas/atlas_setup.c 2008-01-02 13:56:37.000000000 -0500
-@@ -37,10 +37,6 @@
- extern void mips_time_init(void);
- extern unsigned long mips_rtc_get_time(void);
--#ifdef CONFIG_KGDB
--extern void kgdb_config(void);
--#endif
--
- static void __init serial_init(void);
- const char *get_system_type(void)
-@@ -58,9 +54,6 @@
-       serial_init ();
--#ifdef CONFIG_KGDB
--      kgdb_config();
--#endif
-       mips_reboot_setup();
-       board_time_init = mips_time_init;
-diff -Nurb linux-2.6.22-570/arch/mips/mips-boards/generic/gdb_hook.c linux-2.6.22-590/arch/mips/mips-boards/generic/gdb_hook.c
---- linux-2.6.22-570/arch/mips/mips-boards/generic/gdb_hook.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/mips-boards/generic/gdb_hook.c  1969-12-31 19:00:00.000000000 -0500
-@@ -1,133 +0,0 @@
--/*
-- * Carsten Langgaard, carstenl@mips.com
-- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
-- *
-- *  This program is free software; you can distribute it and/or modify it
-- *  under the terms of the GNU General Public License (Version 2) as
-- *  published by the Free Software Foundation.
-- *
-- *  This program is distributed in the hope 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.
-- *
-- * This is the interface to the remote debugger stub.
-- */
--#include <linux/types.h>
--#include <linux/serial.h>
--#include <linux/serialP.h>
--#include <linux/serial_reg.h>
--
--#include <asm/serial.h>
--#include <asm/io.h>
--
--static struct serial_state rs_table[] = {
--      SERIAL_PORT_DFNS        /* Defined in serial.h */
--};
--
--static struct async_struct kdb_port_info = {0};
--
--int (*generic_putDebugChar)(char);
--char (*generic_getDebugChar)(void);
--
--static __inline__ unsigned int serial_in(struct async_struct *info, int offset)
--{
--      return inb(info->port + offset);
--}
--
--static __inline__ void serial_out(struct async_struct *info, int offset,
--                              int value)
--{
--      outb(value, info->port+offset);
--}
--
--int rs_kgdb_hook(int tty_no, int speed) {
--      int t;
--      struct serial_state *ser = &rs_table[tty_no];
--
--      kdb_port_info.state = ser;
--      kdb_port_info.magic = SERIAL_MAGIC;
--      kdb_port_info.port = ser->port;
--      kdb_port_info.flags = ser->flags;
--
--      /*
--       * Clear all interrupts
--       */
--      serial_in(&kdb_port_info, UART_LSR);
--      serial_in(&kdb_port_info, UART_RX);
--      serial_in(&kdb_port_info, UART_IIR);
--      serial_in(&kdb_port_info, UART_MSR);
--
--      /*
--       * Now, initialize the UART
--       */
--      serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);   /* reset DLAB */
--      if (kdb_port_info.flags & ASYNC_FOURPORT) {
--              kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS;
--              t = UART_MCR_DTR | UART_MCR_OUT1;
--      } else {
--              kdb_port_info.MCR
--                      = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
--              t = UART_MCR_DTR | UART_MCR_RTS;
--      }
--
--      kdb_port_info.MCR = t;          /* no interrupts, please */
--      serial_out(&kdb_port_info, UART_MCR, kdb_port_info.MCR);
--
--      /*
--       * and set the speed of the serial port
--       */
--      if (speed == 0)
--              speed = 9600;
--
--      t = kdb_port_info.state->baud_base / speed;
--      /* set DLAB */
--      serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB);
--      serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */
--      serial_out(&kdb_port_info, UART_DLM, t >> 8);  /* MS of divisor */
--      /* reset DLAB */
--      serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);
--
--      return speed;
--}
--
--int putDebugChar(char c)
--{
--      return generic_putDebugChar(c);
--}
--
--char getDebugChar(void)
--{
--      return generic_getDebugChar();
--}
--
--int rs_putDebugChar(char c)
--{
--
--      if (!kdb_port_info.state) {     /* need to init device first */
--              return 0;
--      }
--
--      while ((serial_in(&kdb_port_info, UART_LSR) & UART_LSR_THRE) == 0)
--              ;
--
--      serial_out(&kdb_port_info, UART_TX, c);
--
--      return 1;
--}
--
--char rs_getDebugChar(void)
--{
--      if (!kdb_port_info.state) {     /* need to init device first */
--              return 0;
--      }
--
--      while (!(serial_in(&kdb_port_info, UART_LSR) & 1))
--              ;
--
--      return serial_in(&kdb_port_info, UART_RX);
--}
-diff -Nurb linux-2.6.22-570/arch/mips/mips-boards/generic/init.c linux-2.6.22-590/arch/mips/mips-boards/generic/init.c
---- linux-2.6.22-570/arch/mips/mips-boards/generic/init.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/mips-boards/generic/init.c      2008-01-02 13:56:37.000000000 -0500
-@@ -37,15 +37,6 @@
- #include <asm/mips-boards/malta.h>
--#ifdef CONFIG_KGDB
--extern int rs_kgdb_hook(int, int);
--extern int rs_putDebugChar(char);
--extern char rs_getDebugChar(void);
--extern int saa9730_kgdb_hook(int);
--extern int saa9730_putDebugChar(char);
--extern char saa9730_getDebugChar(void);
--#endif
--
- int prom_argc;
- int *_prom_argv, *_prom_envp;
-@@ -173,59 +164,6 @@
- }
- #endif
--#ifdef CONFIG_KGDB
--void __init kgdb_config (void)
--{
--      extern int (*generic_putDebugChar)(char);
--      extern char (*generic_getDebugChar)(void);
--      char *argptr;
--      int line, speed;
--
--      argptr = prom_getcmdline();
--      if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
--              argptr += strlen("kgdb=ttyS");
--              if (*argptr != '0' && *argptr != '1')
--                      printk("KGDB: Unknown serial line /dev/ttyS%c, "
--                             "falling back to /dev/ttyS1\n", *argptr);
--              line = *argptr == '0' ? 0 : 1;
--              printk("KGDB: Using serial line /dev/ttyS%d for session\n", line);
--
--              speed = 0;
--              if (*++argptr == ',')
--              {
--                      int c;
--                      while ((c = *++argptr) && ('0' <= c && c <= '9'))
--                              speed = speed * 10 + c - '0';
--              }
--#ifdef CONFIG_MIPS_ATLAS
--              if (line == 1) {
--                      speed = saa9730_kgdb_hook(speed);
--                      generic_putDebugChar = saa9730_putDebugChar;
--                      generic_getDebugChar = saa9730_getDebugChar;
--              }
--              else
--#endif
--              {
--                      speed = rs_kgdb_hook(line, speed);
--                      generic_putDebugChar = rs_putDebugChar;
--                      generic_getDebugChar = rs_getDebugChar;
--              }
--
--              pr_info("KGDB: Using serial line /dev/ttyS%d at %d for "
--                      "session, please connect your debugger\n",
--                      line ? 1 : 0, speed);
--
--              {
--                      char *s;
--                      for (s = "Please connect GDB to this port\r\n"; *s; )
--                              generic_putDebugChar (*s++);
--              }
--
--              /* Breakpoint is invoked after interrupts are initialised */
--      }
--}
--#endif
--
- void __init mips_nmi_setup (void)
- {
-       void *base;
-diff -Nurb linux-2.6.22-570/arch/mips/mips-boards/malta/malta_setup.c linux-2.6.22-590/arch/mips/mips-boards/malta/malta_setup.c
---- linux-2.6.22-570/arch/mips/mips-boards/malta/malta_setup.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/mips-boards/malta/malta_setup.c 2008-01-02 13:56:37.000000000 -0500
-@@ -39,10 +39,6 @@
- extern void mips_time_init(void);
- extern unsigned long mips_rtc_get_time(void);
--#ifdef CONFIG_KGDB
--extern void kgdb_config(void);
--#endif
--
- struct resource standard_io_resources[] = {
-       { .name = "dma1", .start = 0x00, .end = 0x1f, .flags = IORESOURCE_BUSY },
-       { .name = "timer", .start = 0x40, .end = 0x5f, .flags = IORESOURCE_BUSY },
-@@ -99,10 +95,6 @@
-        */
-       enable_dma(4);
--#ifdef CONFIG_KGDB
--      kgdb_config ();
--#endif
--
-       if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) {
-               char *argptr;
-diff -Nurb linux-2.6.22-570/arch/mips/mm/extable.c linux-2.6.22-590/arch/mips/mm/extable.c
---- linux-2.6.22-570/arch/mips/mm/extable.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/mm/extable.c    2008-01-02 13:56:37.000000000 -0500
-@@ -3,6 +3,7 @@
-  */
- #include <linux/module.h>
- #include <linux/spinlock.h>
-+#include <linux/kgdb.h>
- #include <asm/branch.h>
- #include <asm/uaccess.h>
-@@ -16,6 +17,12 @@
-               return 1;
-       }
-+#ifdef CONFIG_KGDB
-+      if (atomic_read(&debugger_active) && kgdb_may_fault)
-+              /* Restore our previous state. */
-+              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
-+              /* Not reached. */
-+#endif
-       return 0;
- }
-diff -Nurb linux-2.6.22-570/arch/mips/momentum/ocelot_c/Makefile linux-2.6.22-590/arch/mips/momentum/ocelot_c/Makefile
---- linux-2.6.22-570/arch/mips/momentum/ocelot_c/Makefile      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/momentum/ocelot_c/Makefile      2008-01-02 13:56:37.000000000 -0500
-@@ -4,5 +4,3 @@
- obj-y                 += cpci-irq.o irq.o platform.o prom.o reset.o \
-                          setup.o uart-irq.o
--
--obj-$(CONFIG_KGDB)    += dbg_io.o
-diff -Nurb linux-2.6.22-570/arch/mips/momentum/ocelot_c/dbg_io.c linux-2.6.22-590/arch/mips/momentum/ocelot_c/dbg_io.c
---- linux-2.6.22-570/arch/mips/momentum/ocelot_c/dbg_io.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/momentum/ocelot_c/dbg_io.c      1969-12-31 19:00:00.000000000 -0500
-@@ -1,121 +0,0 @@
--
--#include <asm/serial.h> /* For the serial port location and base baud */
--
--/* --- CONFIG --- */
--
--typedef unsigned char uint8;
--typedef unsigned int uint32;
--
--/* --- END OF CONFIG --- */
--
--#define         UART16550_BAUD_2400             2400
--#define         UART16550_BAUD_4800             4800
--#define         UART16550_BAUD_9600             9600
--#define         UART16550_BAUD_19200            19200
--#define         UART16550_BAUD_38400            38400
--#define         UART16550_BAUD_57600            57600
--#define         UART16550_BAUD_115200           115200
--
--#define         UART16550_PARITY_NONE           0
--#define         UART16550_PARITY_ODD            0x08
--#define         UART16550_PARITY_EVEN           0x18
--#define         UART16550_PARITY_MARK           0x28
--#define         UART16550_PARITY_SPACE          0x38
--
--#define         UART16550_DATA_5BIT             0x0
--#define         UART16550_DATA_6BIT             0x1
--#define         UART16550_DATA_7BIT             0x2
--#define         UART16550_DATA_8BIT             0x3
--
--#define         UART16550_STOP_1BIT             0x0
--#define         UART16550_STOP_2BIT             0x4
--
--/* ----------------------------------------------------- */
--
--/* === CONFIG === */
--
--/* [jsun] we use the second serial port for kdb */
--#define         BASE                    OCELOT_SERIAL1_BASE
--#define         MAX_BAUD                OCELOT_BASE_BAUD
--
--/* === END OF CONFIG === */
--
--#define         REG_OFFSET              4
--
--/* register offset */
--#define         OFS_RCV_BUFFER          0
--#define         OFS_TRANS_HOLD          0
--#define         OFS_SEND_BUFFER         0
--#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
--#define         OFS_INTR_ID             (2*REG_OFFSET)
--#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
--#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
--#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
--#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
--#define         OFS_LINE_STATUS         (5*REG_OFFSET)
--#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
--#define         OFS_RS232_INPUT         (6*REG_OFFSET)
--#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
--
--#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
--#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
--
--
--/* memory-mapped read/write of the port */
--#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
--#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
--
--void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
--{
--      /* disable interrupts */
--      UART16550_WRITE(OFS_INTR_ENABLE, 0);
--
--      /* set up baud rate */
--      {
--              uint32 divisor;
--
--              /* set DIAB bit */
--              UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
--
--              /* set divisor */
--              divisor = MAX_BAUD / baud;
--              UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
--              UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
--
--              /* clear DIAB bit */
--              UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
--      }
--
--      /* set data format */
--      UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
--}
--
--static int remoteDebugInitialized = 0;
--
--uint8 getDebugChar(void)
--{
--      if (!remoteDebugInitialized) {
--              remoteDebugInitialized = 1;
--              debugInit(UART16550_BAUD_38400,
--                        UART16550_DATA_8BIT,
--                        UART16550_PARITY_NONE, UART16550_STOP_1BIT);
--      }
--
--      while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
--      return UART16550_READ(OFS_RCV_BUFFER);
--}
--
--
--int putDebugChar(uint8 byte)
--{
--      if (!remoteDebugInitialized) {
--              remoteDebugInitialized = 1;
--              debugInit(UART16550_BAUD_38400,
--                        UART16550_DATA_8BIT,
--                        UART16550_PARITY_NONE, UART16550_STOP_1BIT);
--      }
--
--      while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
--      UART16550_WRITE(OFS_SEND_BUFFER, byte);
--      return 1;
--}
-diff -Nurb linux-2.6.22-570/arch/mips/pci/fixup-atlas.c linux-2.6.22-590/arch/mips/pci/fixup-atlas.c
---- linux-2.6.22-570/arch/mips/pci/fixup-atlas.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/pci/fixup-atlas.c       2008-01-02 13:56:37.000000000 -0500
-@@ -68,24 +68,3 @@
- {
-       return 0;
- }
--
--#ifdef CONFIG_KGDB
--/*
-- * The PCI scan may have moved the saa9730 I/O address, so reread
-- * the address here.
-- * This does mean that it's not possible to debug the PCI bus configuration
-- * code, but it is better than nothing...
-- */
--
--static void atlas_saa9730_base_fixup (struct pci_dev *pdev)
--{
--      extern void *saa9730_base;
--      if (pdev->bus == 0 && PCI_SLOT(pdev->devfn) == 19)
--              (void) pci_read_config_dword (pdev, 0x14, (u32 *)&saa9730_base);
--      printk ("saa9730_base = %x\n", saa9730_base);
--}
--
--DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730,
--       atlas_saa9730_base_fixup);
--
--#endif
-diff -Nurb linux-2.6.22-570/arch/mips/philips/pnx8550/common/Makefile linux-2.6.22-590/arch/mips/philips/pnx8550/common/Makefile
---- linux-2.6.22-570/arch/mips/philips/pnx8550/common/Makefile 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/philips/pnx8550/common/Makefile 2008-01-02 13:56:37.000000000 -0500
-@@ -24,4 +24,3 @@
- obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o
- obj-$(CONFIG_PCI) += pci.o
--obj-$(CONFIG_KGDB) += gdb_hook.o
-diff -Nurb linux-2.6.22-570/arch/mips/philips/pnx8550/common/gdb_hook.c linux-2.6.22-590/arch/mips/philips/pnx8550/common/gdb_hook.c
---- linux-2.6.22-570/arch/mips/philips/pnx8550/common/gdb_hook.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/philips/pnx8550/common/gdb_hook.c       1969-12-31 19:00:00.000000000 -0500
-@@ -1,109 +0,0 @@
--/*
-- * Carsten Langgaard, carstenl@mips.com
-- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
-- *
-- * ########################################################################
-- *
-- *  This program is free software; you can distribute it and/or modify it
-- *  under the terms of the GNU General Public License (Version 2) as
-- *  published by the Free Software Foundation.
-- *
-- *  This program is distributed in the hope 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.
-- *
-- * ########################################################################
-- *
-- * This is the interface to the remote debugger stub.
-- *
-- */
--#include <linux/types.h>
--#include <linux/serial.h>
--#include <linux/serialP.h>
--#include <linux/serial_reg.h>
--#include <linux/serial_ip3106.h>
--
--#include <asm/serial.h>
--#include <asm/io.h>
--
--#include <uart.h>
--
--static struct serial_state rs_table[IP3106_NR_PORTS] = {
--};
--static struct async_struct kdb_port_info = {0};
--
--void rs_kgdb_hook(int tty_no)
--{
--      struct serial_state *ser = &rs_table[tty_no];
--
--      kdb_port_info.state = ser;
--      kdb_port_info.magic = SERIAL_MAGIC;
--      kdb_port_info.port  = tty_no;
--      kdb_port_info.flags = ser->flags;
--
--      /*
--       * Clear all interrupts
--       */
--      /* Clear all the transmitter FIFO counters (pointer and status) */
--      ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_TX_RST;
--      /* Clear all the receiver FIFO counters (pointer and status) */
--      ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_RX_RST;
--      /* Clear all interrupts */
--      ip3106_iclr(UART_BASE, tty_no) = IP3106_UART_INT_ALLRX |
--              IP3106_UART_INT_ALLTX;
--
--      /*
--       * Now, initialize the UART
--       */
--      ip3106_lcr(UART_BASE, tty_no) = IP3106_UART_LCR_8BIT;
--      ip3106_baud(UART_BASE, tty_no) = 5; // 38400 Baud
--}
--
--int putDebugChar(char c)
--{
--      /* Wait until FIFO not full */
--      while (((ip3106_fifo(UART_BASE, kdb_port_info.port) & IP3106_UART_FIFO_TXFIFO) >> 16) >= 16)
--              ;
--      /* Send one char */
--      ip3106_fifo(UART_BASE, kdb_port_info.port) = c;
--
--      return 1;
--}
--
--char getDebugChar(void)
--{
--      char ch;
--
--      /* Wait until there is a char in the FIFO */
--      while (!((ip3106_fifo(UART_BASE, kdb_port_info.port) &
--                                      IP3106_UART_FIFO_RXFIFO) >> 8))
--              ;
--      /* Read one char */
--      ch = ip3106_fifo(UART_BASE, kdb_port_info.port) &
--              IP3106_UART_FIFO_RBRTHR;
--      /* Advance the RX FIFO read pointer */
--      ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_RX_NEXT;
--      return (ch);
--}
--
--void rs_disable_debug_interrupts(void)
--{
--      ip3106_ien(UART_BASE, kdb_port_info.port) = 0; /* Disable all interrupts */
--}
--
--void rs_enable_debug_interrupts(void)
--{
--      /* Clear all the transmitter FIFO counters (pointer and status) */
--      ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_TX_RST;
--      /* Clear all the receiver FIFO counters (pointer and status) */
--      ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_RX_RST;
--      /* Clear all interrupts */
--      ip3106_iclr(UART_BASE, kdb_port_info.port) = IP3106_UART_INT_ALLRX |
--              IP3106_UART_INT_ALLTX;
--      ip3106_ien(UART_BASE, kdb_port_info.port)  = IP3106_UART_INT_ALLRX; /* Enable RX interrupts */
--}
-diff -Nurb linux-2.6.22-570/arch/mips/philips/pnx8550/common/setup.c linux-2.6.22-590/arch/mips/philips/pnx8550/common/setup.c
---- linux-2.6.22-570/arch/mips/philips/pnx8550/common/setup.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/philips/pnx8550/common/setup.c  2008-01-02 13:56:37.000000000 -0500
-@@ -145,16 +145,5 @@
-               ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
-       }
--#ifdef CONFIG_KGDB
--      argptr = prom_getcmdline();
--      if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
--              int line;
--              argptr += strlen("kgdb=ttyS");
--              line = *argptr == '0' ? 0 : 1;
--              rs_kgdb_hook(line);
--              pr_info("KGDB: Using ttyS%i for session, "
--                      "please connect your debugger\n", line ? 1 : 0);
--      }
--#endif
-       return;
- }
-diff -Nurb linux-2.6.22-570/arch/mips/pmc-sierra/yosemite/Makefile linux-2.6.22-590/arch/mips/pmc-sierra/yosemite/Makefile
---- linux-2.6.22-570/arch/mips/pmc-sierra/yosemite/Makefile    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/pmc-sierra/yosemite/Makefile    2008-01-02 13:56:37.000000000 -0500
-@@ -4,5 +4,4 @@
- obj-y    += irq.o i2c-yosemite.o prom.o py-console.o setup.o
--obj-$(CONFIG_KGDB)            += dbg_io.o
- obj-$(CONFIG_SMP)             += smp.o
-diff -Nurb linux-2.6.22-570/arch/mips/pmc-sierra/yosemite/dbg_io.c linux-2.6.22-590/arch/mips/pmc-sierra/yosemite/dbg_io.c
---- linux-2.6.22-570/arch/mips/pmc-sierra/yosemite/dbg_io.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/pmc-sierra/yosemite/dbg_io.c    1969-12-31 19:00:00.000000000 -0500
-@@ -1,180 +0,0 @@
--/*
-- * Copyright 2003 PMC-Sierra
-- * Author: Manish Lachwani (lachwani@pmc-sierra.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  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.
-- */
--
--/*
-- * Support for KGDB for the Yosemite board. We make use of single serial
-- * port to be used for KGDB as well as console. The second serial port
-- * seems to be having a problem. Single IRQ is allocated for both the
-- * ports. Hence, the interrupt routing code needs to figure out whether
-- * the interrupt came from channel A or B.
-- */
--
--#include <asm/serial.h>
--
--/*
-- * Baud rate, Parity, Data and Stop bit settings for the
-- * serial port on the Yosemite. Note that the Early printk
-- * patch has been added. So, we should be all set to go
-- */
--#define       YOSEMITE_BAUD_2400      2400
--#define       YOSEMITE_BAUD_4800      4800
--#define       YOSEMITE_BAUD_9600      9600
--#define       YOSEMITE_BAUD_19200     19200
--#define       YOSEMITE_BAUD_38400     38400
--#define       YOSEMITE_BAUD_57600     57600
--#define       YOSEMITE_BAUD_115200    115200
--
--#define       YOSEMITE_PARITY_NONE    0
--#define       YOSEMITE_PARITY_ODD     0x08
--#define       YOSEMITE_PARITY_EVEN    0x18
--#define       YOSEMITE_PARITY_MARK    0x28
--#define       YOSEMITE_PARITY_SPACE   0x38
--
--#define       YOSEMITE_DATA_5BIT      0x0
--#define       YOSEMITE_DATA_6BIT      0x1
--#define       YOSEMITE_DATA_7BIT      0x2
--#define       YOSEMITE_DATA_8BIT      0x3
--
--#define       YOSEMITE_STOP_1BIT      0x0
--#define       YOSEMITE_STOP_2BIT      0x4
--
--/* This is crucial */
--#define       SERIAL_REG_OFS          0x1
--
--#define       SERIAL_RCV_BUFFER       0x0
--#define       SERIAL_TRANS_HOLD       0x0
--#define       SERIAL_SEND_BUFFER      0x0
--#define       SERIAL_INTR_ENABLE      (1 * SERIAL_REG_OFS)
--#define       SERIAL_INTR_ID          (2 * SERIAL_REG_OFS)
--#define       SERIAL_DATA_FORMAT      (3 * SERIAL_REG_OFS)
--#define       SERIAL_LINE_CONTROL     (3 * SERIAL_REG_OFS)
--#define       SERIAL_MODEM_CONTROL    (4 * SERIAL_REG_OFS)
--#define       SERIAL_RS232_OUTPUT     (4 * SERIAL_REG_OFS)
--#define       SERIAL_LINE_STATUS      (5 * SERIAL_REG_OFS)
--#define       SERIAL_MODEM_STATUS     (6 * SERIAL_REG_OFS)
--#define       SERIAL_RS232_INPUT      (6 * SERIAL_REG_OFS)
--#define       SERIAL_SCRATCH_PAD      (7 * SERIAL_REG_OFS)
--
--#define       SERIAL_DIVISOR_LSB      (0 * SERIAL_REG_OFS)
--#define       SERIAL_DIVISOR_MSB      (1 * SERIAL_REG_OFS)
--
--/*
-- * Functions to READ and WRITE to serial port 0
-- */
--#define       SERIAL_READ(ofs)                (*((volatile unsigned char*)    \
--                                      (TITAN_SERIAL_BASE + ofs)))
--
--#define       SERIAL_WRITE(ofs, val)          ((*((volatile unsigned char*)   \
--                                      (TITAN_SERIAL_BASE + ofs))) = val)
--
--/*
-- * Functions to READ and WRITE to serial port 1
-- */
--#define       SERIAL_READ_1(ofs)              (*((volatile unsigned char*)    \
--                                      (TITAN_SERIAL_BASE_1 + ofs)))
--
--#define       SERIAL_WRITE_1(ofs, val)        ((*((volatile unsigned char*)   \
--                                      (TITAN_SERIAL_BASE_1 + ofs))) = val)
--
--/*
-- * Second serial port initialization
-- */
--void init_second_port(void)
--{
--      /* Disable Interrupts */
--      SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
--      SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0x0);
--
--      {
--              unsigned int divisor;
--
--              SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x80);
--              divisor = TITAN_SERIAL_BASE_BAUD / YOSEMITE_BAUD_115200;
--              SERIAL_WRITE_1(SERIAL_DIVISOR_LSB, divisor & 0xff);
--
--              SERIAL_WRITE_1(SERIAL_DIVISOR_MSB,
--                             (divisor & 0xff00) >> 8);
--              SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
--      }
--
--      SERIAL_WRITE_1(SERIAL_DATA_FORMAT, YOSEMITE_DATA_8BIT |
--                     YOSEMITE_PARITY_NONE | YOSEMITE_STOP_1BIT);
--
--      /* Enable Interrupts */
--      SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0xf);
--}
--
--/* Initialize the serial port for KGDB debugging */
--void debugInit(unsigned int baud, unsigned char data, unsigned char parity,
--             unsigned char stop)
--{
--      /* Disable Interrupts */
--      SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
--      SERIAL_WRITE(SERIAL_INTR_ENABLE, 0x0);
--
--      {
--              unsigned int divisor;
--
--              SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x80);
--
--              divisor = TITAN_SERIAL_BASE_BAUD / baud;
--              SERIAL_WRITE(SERIAL_DIVISOR_LSB, divisor & 0xff);
--
--              SERIAL_WRITE(SERIAL_DIVISOR_MSB, (divisor & 0xff00) >> 8);
--              SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
--      }
--
--      SERIAL_WRITE(SERIAL_DATA_FORMAT, data | parity | stop);
--}
--
--static int remoteDebugInitialized = 0;
--
--unsigned char getDebugChar(void)
--{
--      if (!remoteDebugInitialized) {
--              remoteDebugInitialized = 1;
--              debugInit(YOSEMITE_BAUD_115200,
--                        YOSEMITE_DATA_8BIT,
--                        YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
--      }
--
--      while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x1) == 0);
--      return SERIAL_READ(SERIAL_RCV_BUFFER);
--}
--
--int putDebugChar(unsigned char byte)
--{
--      if (!remoteDebugInitialized) {
--              remoteDebugInitialized = 1;
--              debugInit(YOSEMITE_BAUD_115200,
--                        YOSEMITE_DATA_8BIT,
--                        YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
--      }
--
--      while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x20) == 0);
--      SERIAL_WRITE(SERIAL_SEND_BUFFER, byte);
--
--      return 1;
--}
-diff -Nurb linux-2.6.22-570/arch/mips/pmc-sierra/yosemite/irq.c linux-2.6.22-590/arch/mips/pmc-sierra/yosemite/irq.c
---- linux-2.6.22-570/arch/mips/pmc-sierra/yosemite/irq.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/pmc-sierra/yosemite/irq.c       2008-01-02 13:56:37.000000000 -0500
-@@ -137,10 +137,6 @@
-       }
- }
--#ifdef CONFIG_KGDB
--extern void init_second_port(void);
--#endif
--
- /*
-  * Initialize the next level interrupt handler
-  */
-@@ -152,11 +148,6 @@
-       rm7k_cpu_irq_init();
-       rm9k_cpu_irq_init();
--#ifdef CONFIG_KGDB
--      /* At this point, initialize the second serial port */
--      init_second_port();
--#endif
--
- #ifdef CONFIG_GDB_CONSOLE
-       register_gdb_console();
- #endif
-diff -Nurb linux-2.6.22-570/arch/mips/sgi-ip22/ip22-setup.c linux-2.6.22-590/arch/mips/sgi-ip22/ip22-setup.c
---- linux-2.6.22-570/arch/mips/sgi-ip22/ip22-setup.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/sgi-ip22/ip22-setup.c   2008-01-02 13:56:37.000000000 -0500
-@@ -101,30 +101,6 @@
-               add_preferred_console("arc", 0, NULL);
-       }
--#ifdef CONFIG_KGDB
--      {
--      char *kgdb_ttyd = prom_getcmdline();
--
--      if ((kgdb_ttyd = strstr(kgdb_ttyd, "kgdb=ttyd")) != NULL) {
--              int line;
--              kgdb_ttyd += strlen("kgdb=ttyd");
--              if (*kgdb_ttyd != '1' && *kgdb_ttyd != '2')
--                      printk(KERN_INFO "KGDB: Uknown serial line /dev/ttyd%c"
--                             ", falling back to /dev/ttyd1\n", *kgdb_ttyd);
--              line = *kgdb_ttyd == '2' ? 0 : 1;
--              printk(KERN_INFO "KGDB: Using serial line /dev/ttyd%d for "
--                     "session\n", line ? 1 : 2);
--              rs_kgdb_hook(line);
--
--              printk(KERN_INFO "KGDB: Using serial line /dev/ttyd%d for "
--                     "session, please connect your debugger\n", line ? 1:2);
--
--              kgdb_enabled = 1;
--              /* Breakpoints and stuff are in sgi_irq_setup() */
--      }
--      }
--#endif
--
- #if defined(CONFIG_VT) && defined(CONFIG_SGI_NEWPORT_CONSOLE)
-       {
-               ULONG *gfxinfo;
-diff -Nurb linux-2.6.22-570/arch/mips/sgi-ip27/Makefile linux-2.6.22-590/arch/mips/sgi-ip27/Makefile
---- linux-2.6.22-570/arch/mips/sgi-ip27/Makefile       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/sgi-ip27/Makefile       2008-01-02 13:56:37.000000000 -0500
-@@ -7,5 +7,4 @@
-          ip27-xtalk.o
- obj-$(CONFIG_EARLY_PRINTK)    += ip27-console.o
--obj-$(CONFIG_KGDB)            += ip27-dbgio.o
- obj-$(CONFIG_SMP)             += ip27-smp.o
-diff -Nurb linux-2.6.22-570/arch/mips/sgi-ip27/ip27-dbgio.c linux-2.6.22-590/arch/mips/sgi-ip27/ip27-dbgio.c
---- linux-2.6.22-570/arch/mips/sgi-ip27/ip27-dbgio.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/sgi-ip27/ip27-dbgio.c   1969-12-31 19:00:00.000000000 -0500
-@@ -1,60 +0,0 @@
--/*
-- *  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.
-- *
-- * Copyright 2004 Ralf Baechle <ralf@linux-mips.org>
-- */
--#include <asm/sn/addrs.h>
--#include <asm/sn/sn0/hub.h>
--#include <asm/sn/klconfig.h>
--#include <asm/sn/ioc3.h>
--#include <asm/sn/sn_private.h>
--
--#include <linux/serial.h>
--#include <linux/serial_core.h>
--#include <linux/serial_reg.h>
--
--#define IOC3_CLK        (22000000 / 3)
--#define IOC3_FLAGS      (0)
--
--static inline struct ioc3_uartregs *console_uart(void)
--{
--      struct ioc3 *ioc3;
--
--      ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(get_nasid())->memory_base;
--
--      return &ioc3->sregs.uarta;
--}
--
--unsigned char getDebugChar(void)
--{
--      struct ioc3_uartregs *uart = console_uart();
--
--      while ((uart->iu_lsr & UART_LSR_DR) == 0);
--      return uart->iu_rbr;
--}
--
--void putDebugChar(unsigned char c)
--{
--      struct ioc3_uartregs *uart = console_uart();
--
--      while ((uart->iu_lsr & UART_LSR_THRE) == 0);
--      uart->iu_thr = c;
--}
-diff -Nurb linux-2.6.22-570/arch/mips/sibyte/bcm1480/irq.c linux-2.6.22-590/arch/mips/sibyte/bcm1480/irq.c
---- linux-2.6.22-570/arch/mips/sibyte/bcm1480/irq.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/sibyte/bcm1480/irq.c    2008-01-02 13:56:37.000000000 -0500
-@@ -57,30 +57,6 @@
- extern unsigned long ht_eoi_space;
- #endif
--#ifdef CONFIG_KGDB
--#include <asm/gdb-stub.h>
--extern void breakpoint(void);
--static int kgdb_irq;
--#ifdef CONFIG_GDB_CONSOLE
--extern void register_gdb_console(void);
--#endif
--
--/* kgdb is on when configured.  Pass "nokgdb" kernel arg to turn it off */
--static int kgdb_flag = 1;
--static int __init nokgdb(char *str)
--{
--      kgdb_flag = 0;
--      return 1;
--}
--__setup("nokgdb", nokgdb);
--
--/* Default to UART1 */
--int kgdb_port = 1;
--#ifdef CONFIG_SIBYTE_SB1250_DUART
--extern char sb1250_duart_present[];
--#endif
--#endif
--
- static struct irq_chip bcm1480_irq_type = {
-       .name = "BCM1480-IMR",
-       .ack = ack_bcm1480_irq,
-@@ -394,62 +370,11 @@
-        * does its own management of IP7.
-        */
--#ifdef CONFIG_KGDB
--      imask |= STATUSF_IP6;
--#endif
-       /* Enable necessary IPs, disable the rest */
-       change_c0_status(ST0_IM, imask);
--#ifdef CONFIG_KGDB
--      if (kgdb_flag) {
--              kgdb_irq = K_BCM1480_INT_UART_0 + kgdb_port;
--
--#ifdef CONFIG_SIBYTE_SB1250_DUART
--              sb1250_duart_present[kgdb_port] = 0;
--#endif
--              /* Setup uart 1 settings, mapper */
--              /* QQQ FIXME */
--              __raw_writeq(M_DUART_IMR_BRK, IO_SPACE_BASE + A_DUART_IMRREG(kgdb_port));
--
--              bcm1480_steal_irq(kgdb_irq);
--              __raw_writeq(IMR_IP6_VAL,
--                           IO_SPACE_BASE + A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) +
--                           (kgdb_irq<<3));
--              bcm1480_unmask_irq(0, kgdb_irq);
--
--#ifdef CONFIG_GDB_CONSOLE
--              register_gdb_console();
--#endif
--              printk("Waiting for GDB on UART port %d\n", kgdb_port);
--              set_debug_traps();
--              breakpoint();
--      }
--#endif
- }
--#ifdef CONFIG_KGDB
--
--#include <linux/delay.h>
--
--#define duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
--#define duart_in(reg)           csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
--
--static void bcm1480_kgdb_interrupt(void)
--{
--      /*
--       * Clear break-change status (allow some time for the remote
--       * host to stop the break, since we would see another
--       * interrupt on the end-of-break too)
--       */
--      kstat.irqs[smp_processor_id()][kgdb_irq]++;
--      mdelay(500);
--      duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
--                              M_DUART_RX_EN | M_DUART_TX_EN);
--      set_async_breakpoint(&get_irq_regs()->cp0_epc);
--}
--
--#endif        /* CONFIG_KGDB */
--
- extern void bcm1480_timer_interrupt(void);
- extern void bcm1480_mailbox_interrupt(void);
-@@ -478,11 +403,6 @@
-               bcm1480_mailbox_interrupt();
- #endif
--#ifdef CONFIG_KGDB
--      else if (pending & CAUSEF_IP6)
--              bcm1480_kgdb_interrupt();               /* KGDB (uart 1) */
--#endif
--
-       else if (pending & CAUSEF_IP2) {
-               unsigned long long mask_h, mask_l;
-               unsigned long base;
-diff -Nurb linux-2.6.22-570/arch/mips/sibyte/cfe/setup.c linux-2.6.22-590/arch/mips/sibyte/cfe/setup.c
---- linux-2.6.22-570/arch/mips/sibyte/cfe/setup.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/sibyte/cfe/setup.c      2008-01-02 13:56:37.000000000 -0500
-@@ -58,10 +58,6 @@
- extern unsigned long initrd_start, initrd_end;
- #endif
--#ifdef CONFIG_KGDB
--extern int kgdb_port;
--#endif
--
- static void ATTRIB_NORET cfe_linux_exit(void *arg)
- {
-       int warm = *(int *)arg;
-@@ -242,9 +238,6 @@
-       int argc = fw_arg0;
-       char **envp = (char **) fw_arg2;
-       int *prom_vec = (int *) fw_arg3;
--#ifdef CONFIG_KGDB
--      char *arg;
--#endif
-       _machine_restart   = cfe_linux_restart;
-       _machine_halt      = cfe_linux_halt;
-@@ -308,13 +301,6 @@
-               }
-       }
--#ifdef CONFIG_KGDB
--      if ((arg = strstr(arcs_cmdline,"kgdb=duart")) != NULL)
--              kgdb_port = (arg[10] == '0') ? 0 : 1;
--      else
--              kgdb_port = 1;
--#endif
--
- #ifdef CONFIG_BLK_DEV_INITRD
-       {
-               char *ptr;
-diff -Nurb linux-2.6.22-570/arch/mips/sibyte/sb1250/Makefile linux-2.6.22-590/arch/mips/sibyte/sb1250/Makefile
---- linux-2.6.22-570/arch/mips/sibyte/sb1250/Makefile  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/sibyte/sb1250/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -3,3 +3,4 @@
- obj-$(CONFIG_SMP)                     += smp.o
- obj-$(CONFIG_SIBYTE_STANDALONE)               += prom.o
- obj-$(CONFIG_SIBYTE_BUS_WATCHER)      += bus_watcher.o
-+obj-$(CONFIG_KGDB_SIBYTE)             += kgdb_sibyte.o
-diff -Nurb linux-2.6.22-570/arch/mips/sibyte/sb1250/irq.c linux-2.6.22-590/arch/mips/sibyte/sb1250/irq.c
---- linux-2.6.22-570/arch/mips/sibyte/sb1250/irq.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/sibyte/sb1250/irq.c     2008-01-02 13:56:37.000000000 -0500
-@@ -29,6 +29,7 @@
- #include <asm/signal.h>
- #include <asm/system.h>
- #include <asm/io.h>
-+#include <asm/kgdb.h>
- #include <asm/sibyte/sb1250_regs.h>
- #include <asm/sibyte/sb1250_int.h>
-@@ -56,16 +57,6 @@
- extern unsigned long ldt_eoi_space;
- #endif
--#ifdef CONFIG_KGDB
--static int kgdb_irq;
--
--/* Default to UART1 */
--int kgdb_port = 1;
--#ifdef CONFIG_SIBYTE_SB1250_DUART
--extern char sb1250_duart_present[];
--#endif
--#endif
--
- static struct irq_chip sb1250_irq_type = {
-       .name = "SB1250-IMR",
-       .ack = ack_sb1250_irq,
-@@ -304,6 +295,11 @@
-       unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
-               STATUSF_IP1 | STATUSF_IP0;
-+#ifdef CONFIG_KGDB
-+      if (kgdb_early_setup)
-+              return;
-+#endif
-+
-       /* Default everything to IP2 */
-       for (i = 0; i < SB1250_NR_IRQS; i++) {  /* was I0 */
-               __raw_writeq(IMR_IP2_VAL,
-@@ -349,58 +345,16 @@
-        * does its own management of IP7.
-        */
--#ifdef CONFIG_KGDB
-+#ifdef CONFIG_KGDB_SIBYTE
-       imask |= STATUSF_IP6;
- #endif
-       /* Enable necessary IPs, disable the rest */
-       change_c0_status(ST0_IM, imask);
--
--#ifdef CONFIG_KGDB
--      if (kgdb_flag) {
--              kgdb_irq = K_INT_UART_0 + kgdb_port;
--
--#ifdef CONFIG_SIBYTE_SB1250_DUART
--              sb1250_duart_present[kgdb_port] = 0;
--#endif
--              /* Setup uart 1 settings, mapper */
--              __raw_writeq(M_DUART_IMR_BRK,
--                           IOADDR(A_DUART_IMRREG(kgdb_port)));
--
--              sb1250_steal_irq(kgdb_irq);
--              __raw_writeq(IMR_IP6_VAL,
--                           IOADDR(A_IMR_REGISTER(0,
--                                                 R_IMR_INTERRUPT_MAP_BASE) +
--                                  (kgdb_irq << 3)));
--              sb1250_unmask_irq(0, kgdb_irq);
--      }
--#endif
- }
--#ifdef CONFIG_KGDB
--
--#include <linux/delay.h>
--
--#define duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
--#define duart_in(reg)           csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
--
--static void sb1250_kgdb_interrupt(void)
--{
--      /*
--       * Clear break-change status (allow some time for the remote
--       * host to stop the break, since we would see another
--       * interrupt on the end-of-break too)
--       */
--      kstat_this_cpu.irqs[kgdb_irq]++;
--      mdelay(500);
--      duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
--                              M_DUART_RX_EN | M_DUART_TX_EN);
--      set_async_breakpoint(&get_irq_regs()->cp0_epc);
--}
--
--#endif        /* CONFIG_KGDB */
--
- extern void sb1250_timer_interrupt(void);
- extern void sb1250_mailbox_interrupt(void);
-+extern void sb1250_kgdb_interrupt(void);
- asmlinkage void plat_irq_dispatch(void)
- {
-@@ -437,7 +391,7 @@
-               sb1250_mailbox_interrupt();
- #endif
--#ifdef CONFIG_KGDB
-+#ifdef CONFIG_KGDB_SIBYTE
-       else if (pending & CAUSEF_IP6)                  /* KGDB (uart 1) */
-               sb1250_kgdb_interrupt();
- #endif
-diff -Nurb linux-2.6.22-570/arch/mips/sibyte/sb1250/kgdb_sibyte.c linux-2.6.22-590/arch/mips/sibyte/sb1250/kgdb_sibyte.c
---- linux-2.6.22-570/arch/mips/sibyte/sb1250/kgdb_sibyte.c     1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/mips/sibyte/sb1250/kgdb_sibyte.c     2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,144 @@
-+/*
-+ * arch/mips/sibyte/sb1250/kgdb_sibyte.c
-+ *
-+ * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com
-+ *
-+ * 2004 (c) MontaVista Software, Inc. This file is licensed under
-+ * the terms of the GNU General Public License version 2. This program
-+ * is licensed "as is" without any warranty of any kind, whether express
-+ * or implied.
-+ */
-+
-+/*
-+ * Support for KGDB on the Broadcom Sibyte. The SWARM board
-+ * for example does not have a 8250/16550 compatible serial
-+ * port. Hence, we need to have a driver for the serial
-+ * ports to handle KGDB.  This board needs nothing in addition
-+ * to what is normally provided by the gdb portion of the stub.
-+ */
-+
-+#include <linux/delay.h>
-+#include <linux/kernel_stat.h>
-+#include <linux/init.h>
-+#include <linux/kgdb.h>
-+
-+#include <asm/io.h>
-+#include <asm/sibyte/sb1250.h>
-+#include <asm/sibyte/sb1250_regs.h>
-+#include <asm/sibyte/sb1250_uart.h>
-+#include <asm/sibyte/sb1250_int.h>
-+#include <asm/addrspace.h>
-+
-+int kgdb_port = 1;
-+static int kgdb_irq;
-+
-+extern char sb1250_duart_present[];
-+extern int sb1250_steal_irq(int irq);
-+
-+/* Forward declarations. */
-+static void kgdbsibyte_init_duart(void);
-+static int kgdb_init_io(void);
-+
-+#define IMR_IP6_VAL   K_INT_MAP_I4
-+#define       duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
-+#define duart_in(reg)         csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
-+
-+static void kgdbsibyte_write_char(u8 c)
-+{
-+      while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0) ;
-+      duart_out(R_DUART_TX_HOLD, c);
-+}
-+
-+static int kgdbsibyte_read_char(void)
-+{
-+      int ret_char;
-+      unsigned int status;
-+
-+      do {
-+              status = duart_in(R_DUART_STATUS);
-+      } while ((status & M_DUART_RX_RDY) == 0);
-+
-+      /*
-+       * Check for framing error
-+       */
-+      if (status & M_DUART_FRM_ERR) {
-+              kgdbsibyte_init_duart();
-+              kgdbsibyte_write_char('-');
-+              return '-';
-+      }
-+
-+      ret_char = duart_in(R_DUART_RX_HOLD);
-+
-+      return ret_char;
-+}
-+
-+void sb1250_kgdb_interrupt(void)
-+{
-+      int kgdb_irq = K_INT_UART_0 + kgdb_port;
-+
-+      /*
-+       * Clear break-change status (allow some time for the remote
-+       * host to stop the break, since we would see another
-+       * interrupt on the end-of-break too)
-+       */
-+      kstat_this_cpu.irqs[kgdb_irq]++;
-+      mdelay(500);
-+      duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
-+                M_DUART_RX_EN | M_DUART_TX_EN);
-+      breakpoint();
-+
-+}
-+
-+/*
-+ * We use port #1 and we set it for 115200 BAUD, 8n1.
-+ */
-+static void kgdbsibyte_init_duart(void)
-+{
-+      /* Set 8n1. */
-+      duart_out(R_DUART_MODE_REG_1,
-+                V_DUART_BITS_PER_CHAR_8 | V_DUART_PARITY_MODE_NONE);
-+      duart_out(R_DUART_MODE_REG_2, M_DUART_STOP_BIT_LEN_1);
-+      /* Set baud rate of 115200. */
-+      duart_out(R_DUART_CLK_SEL, V_DUART_BAUD_RATE(115200));
-+      /* Enable rx and tx */
-+      duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN);
-+}
-+
-+static int kgdb_init_io(void)
-+{
-+#ifdef CONFIG_SIBYTE_SB1250_DUART
-+      sb1250_duart_present[kgdb_port] = 0;
-+#endif
-+
-+      kgdbsibyte_init_duart();
-+
-+      return 0;
-+}
-+
-+/*
-+ * Hookup our IRQ line.  We will already have been initialized a
-+ * this point.
-+ */
-+static void __init kgdbsibyte_hookup_irq(void)
-+{
-+      /* Steal the IRQ. */
-+      kgdb_irq = K_INT_UART_0 + kgdb_port;
-+
-+      /* Setup uart 1 settings, mapper */
-+      __raw_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port)));
-+
-+      sb1250_steal_irq(kgdb_irq);
-+
-+      __raw_writeq(IMR_IP6_VAL,
-+                   IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
-+                          (kgdb_irq << 3)));
-+
-+      sb1250_unmask_irq(0, kgdb_irq);
-+}
-+
-+struct kgdb_io kgdb_io_ops = {
-+      .read_char  = kgdbsibyte_read_char,
-+      .write_char = kgdbsibyte_write_char,
-+      .init = kgdb_init_io,
-+      .late_init  = kgdbsibyte_hookup_irq,
-+};
-diff -Nurb linux-2.6.22-570/arch/mips/sibyte/swarm/Makefile linux-2.6.22-590/arch/mips/sibyte/swarm/Makefile
---- linux-2.6.22-570/arch/mips/sibyte/swarm/Makefile   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/sibyte/swarm/Makefile   2008-01-02 13:56:37.000000000 -0500
-@@ -1,3 +1 @@
- lib-y                         = setup.o rtc_xicor1241.o rtc_m41t81.o
--
--lib-$(CONFIG_KGDB)            += dbg_io.o
-diff -Nurb linux-2.6.22-570/arch/mips/sibyte/swarm/dbg_io.c linux-2.6.22-590/arch/mips/sibyte/swarm/dbg_io.c
---- linux-2.6.22-570/arch/mips/sibyte/swarm/dbg_io.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/sibyte/swarm/dbg_io.c   1969-12-31 19:00:00.000000000 -0500
-@@ -1,76 +0,0 @@
--/*
-- * kgdb debug routines for SiByte boards.
-- *
-- * Copyright (C) 2001 MontaVista Software Inc.
-- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
-- *
-- * 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.
-- *
-- */
--
--/* -------------------- BEGINNING OF CONFIG --------------------- */
--
--#include <linux/delay.h>
--#include <asm/io.h>
--#include <asm/sibyte/sb1250.h>
--#include <asm/sibyte/sb1250_regs.h>
--#include <asm/sibyte/sb1250_uart.h>
--#include <asm/sibyte/sb1250_int.h>
--#include <asm/addrspace.h>
--
--/*
-- * We use the second serial port for kgdb traffic.
-- *    115200, 8, N, 1.
-- */
--
--#define       BAUD_RATE               115200
--#define       CLK_DIVISOR             V_DUART_BAUD_RATE(BAUD_RATE)
--#define       DATA_BITS               V_DUART_BITS_PER_CHAR_8         /* or 7    */
--#define       PARITY                  V_DUART_PARITY_MODE_NONE        /* or even */
--#define       STOP_BITS               M_DUART_STOP_BIT_LEN_1          /* or 2    */
--
--static int duart_initialized = 0;     /* 0: need to be init'ed by kgdb */
--
--/* -------------------- END OF CONFIG --------------------- */
--extern int kgdb_port;
--
--#define       duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
--#define duart_in(reg)         csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
--
--void putDebugChar(unsigned char c);
--unsigned char getDebugChar(void);
--static void
--duart_init(int clk_divisor, int data, int parity, int stop)
--{
--      duart_out(R_DUART_MODE_REG_1, data | parity);
--      duart_out(R_DUART_MODE_REG_2, stop);
--      duart_out(R_DUART_CLK_SEL, clk_divisor);
--
--      duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN);  /* enable rx and tx */
--}
--
--void
--putDebugChar(unsigned char c)
--{
--      if (!duart_initialized) {
--              duart_initialized = 1;
--              duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
--      }
--      while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0);
--      duart_out(R_DUART_TX_HOLD, c);
--}
--
--unsigned char
--getDebugChar(void)
--{
--      if (!duart_initialized) {
--              duart_initialized = 1;
--              duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
--      }
--      while ((duart_in(R_DUART_STATUS) & M_DUART_RX_RDY) == 0) ;
--      return duart_in(R_DUART_RX_HOLD);
--}
--
-diff -Nurb linux-2.6.22-570/arch/mips/tx4927/common/Makefile linux-2.6.22-590/arch/mips/tx4927/common/Makefile
---- linux-2.6.22-570/arch/mips/tx4927/common/Makefile  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/tx4927/common/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -9,4 +9,3 @@
- obj-y += tx4927_prom.o tx4927_setup.o tx4927_irq.o
- obj-$(CONFIG_TOSHIBA_FPCIB0)     += smsc_fdc37m81x.o
--obj-$(CONFIG_KGDB)                 += tx4927_dbgio.o
-diff -Nurb linux-2.6.22-570/arch/mips/tx4927/common/tx4927_dbgio.c linux-2.6.22-590/arch/mips/tx4927/common/tx4927_dbgio.c
---- linux-2.6.22-570/arch/mips/tx4927/common/tx4927_dbgio.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/tx4927/common/tx4927_dbgio.c    1969-12-31 19:00:00.000000000 -0500
-@@ -1,47 +0,0 @@
--/*
-- * linux/arch/mips/tx4927/common/tx4927_dbgio.c
-- *
-- * kgdb interface for gdb
-- *
-- * Author: MontaVista Software, Inc.
-- *         source@mvista.com
-- *
-- * Copyright 2001-2002 MontaVista Software 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.
-- */
--
--#include <asm/mipsregs.h>
--#include <asm/system.h>
--#include <asm/tx4927/tx4927_mips.h>
--
--u8 getDebugChar(void)
--{
--      extern u8 txx9_sio_kdbg_rd(void);
--      return (txx9_sio_kdbg_rd());
--}
--
--
--int putDebugChar(u8 byte)
--{
--      extern int txx9_sio_kdbg_wr( u8 ch );
--      return (txx9_sio_kdbg_wr(byte));
--}
-diff -Nurb linux-2.6.22-570/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c linux-2.6.22-590/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
---- linux-2.6.22-570/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c        2008-01-02 13:56:37.000000000 -0500
-@@ -76,7 +76,7 @@
- #include <linux/hdreg.h>
- #include <linux/ide.h>
- #endif
--#ifdef CONFIG_SERIAL_TXX9
-+#if defined(CONFIG_SERIAL_TXX9) || defined(CONFIG_KGDB_TXX9)
- #include <linux/tty.h>
- #include <linux/serial.h>
- #include <linux/serial_core.h>
-@@ -973,9 +973,10 @@
- #endif /* CONFIG_PCI */
--#ifdef CONFIG_SERIAL_TXX9
-+#if defined (CONFIG_SERIAL_TXX9) || defined(CONFIG_KGDB_TXX9)
-       {
-               extern int early_serial_txx9_setup(struct uart_port *port);
-+              extern int txx9_kgdb_add_port(int n, struct uart_port *port);
-               int i;
-               struct uart_port req;
-               for(i = 0; i < 2; i++) {
-@@ -987,7 +988,12 @@
-                       req.irq = 32 + i;
-                       req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
-                       req.uartclk = 50000000;
-+#ifdef CONFIG_SERIAL_TXX9
-                       early_serial_txx9_setup(&req);
-+#endif
-+#ifdef CONFIG_KGDB_TXX9
-+                      txx9_kgdb_add_port(i, &req);
-+#endif
-               }
-       }
- #ifdef CONFIG_SERIAL_TXX9_CONSOLE
-@@ -996,7 +1002,7 @@
-                 strcat(argptr, " console=ttyS0,38400");
-         }
- #endif
--#endif
-+#endif /* defined(CONFIG_SERIAL_TXX9) || defined(CONFIG_KGDB_TXX9) */
- #ifdef CONFIG_ROOT_NFS
-         argptr = prom_getcmdline();
-diff -Nurb linux-2.6.22-570/arch/mips/tx4938/common/Makefile linux-2.6.22-590/arch/mips/tx4938/common/Makefile
---- linux-2.6.22-570/arch/mips/tx4938/common/Makefile  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/tx4938/common/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -7,5 +7,4 @@
- #
- obj-y += prom.o setup.o irq.o rtc_rx5c348.o
--obj-$(CONFIG_KGDB) += dbgio.o
-diff -Nurb linux-2.6.22-570/arch/mips/tx4938/common/dbgio.c linux-2.6.22-590/arch/mips/tx4938/common/dbgio.c
---- linux-2.6.22-570/arch/mips/tx4938/common/dbgio.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/tx4938/common/dbgio.c   1969-12-31 19:00:00.000000000 -0500
-@@ -1,50 +0,0 @@
--/*
-- * linux/arch/mips/tx4938/common/dbgio.c
-- *
-- * kgdb interface for gdb
-- *
-- * Author: MontaVista Software, Inc.
-- *         source@mvista.com
-- *
-- * Copyright 2005 MontaVista Software 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.
-- *
-- * Support for TX4938 in 2.6 - Hiroshi DOYU <Hiroshi_DOYU@montavista.co.jp>
-- */
--
--#include <asm/mipsregs.h>
--#include <asm/system.h>
--#include <asm/tx4938/tx4938_mips.h>
--
--extern u8 txx9_sio_kdbg_rd(void);
--extern int txx9_sio_kdbg_wr( u8 ch );
--
--u8 getDebugChar(void)
--{
--      return (txx9_sio_kdbg_rd());
--}
--
--int putDebugChar(u8 byte)
--{
--      return (txx9_sio_kdbg_wr(byte));
--}
--
-diff -Nurb linux-2.6.22-570/arch/mips/tx4938/toshiba_rbtx4938/setup.c linux-2.6.22-590/arch/mips/tx4938/toshiba_rbtx4938/setup.c
---- linux-2.6.22-570/arch/mips/tx4938/toshiba_rbtx4938/setup.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/mips/tx4938/toshiba_rbtx4938/setup.c 2008-01-02 13:56:37.000000000 -0500
-@@ -30,7 +30,7 @@
- #include <asm/io.h>
- #include <asm/bootinfo.h>
- #include <asm/tx4938/rbtx4938.h>
--#ifdef CONFIG_SERIAL_TXX9
-+#if defined(CONFIG_SERIAL_TXX9) || defined(CONFIG_KGDB_TXX9)
- #include <linux/tty.h>
- #include <linux/serial.h>
- #include <linux/serial_core.h>
-@@ -924,9 +924,10 @@
-       set_io_port_base(RBTX4938_ETHER_BASE);
- #endif
--#ifdef CONFIG_SERIAL_TXX9
-+#if defined (CONFIG_SERIAL_TXX9) || defined (CONFIG_KGDB_TXX9)
-       {
-               extern int early_serial_txx9_setup(struct uart_port *port);
-+              extern int txx9_kgdb_add_port(int n, struct uart_port *port);
-               int i;
-               struct uart_port req;
-               for(i = 0; i < 2; i++) {
-@@ -938,7 +939,12 @@
-                       req.irq = 32 + i;
-                       req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
-                       req.uartclk = 50000000;
-+#ifdef CONFIG_SERIAL_TXX9
-                       early_serial_txx9_setup(&req);
-+#endif
-+#ifdef CONFIG_KGDB_TXX9
-+                      txx9_kgdb_add_port(i, &req);
-+#endif
-               }
-       }
- #ifdef CONFIG_SERIAL_TXX9_CONSOLE
-diff -Nurb linux-2.6.22-570/arch/powerpc/Kconfig linux-2.6.22-590/arch/powerpc/Kconfig
---- linux-2.6.22-570/arch/powerpc/Kconfig      2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/Kconfig      2008-01-02 13:56:37.000000000 -0500
-@@ -4,12 +4,7 @@
- mainmenu "Linux/PowerPC Kernel Configuration"
--config PPC64
--      bool "64-bit kernel"
--      default n
--      help
--        This option selects whether a 32-bit or a 64-bit kernel
--        will be built.
-+source "arch/powerpc/platforms/Kconfig.cputype"
- config PPC_PM_NEEDS_RTC_LIB
-       bool
-@@ -132,123 +127,6 @@
-       depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL))
-       default y
--menu "Processor support"
--choice
--      prompt "Processor Type"
--      depends on PPC32
--      default 6xx
--
--config CLASSIC32
--      bool "52xx/6xx/7xx/74xx"
--      select PPC_FPU
--      select 6xx
--      help
--        There are four families of PowerPC chips supported.  The more common
--        types (601, 603, 604, 740, 750, 7400), the Motorola embedded
--        versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC
--        embedded versions (403 and 405) and the high end 64 bit Power
--        processors (POWER 3, POWER4, and IBM PPC970 also known as G5).
--
--        This option is the catch-all for 6xx types, including some of the
--        embedded versions.  Unless there is see an option for the specific
--        chip family you are using, you want this option.
--        
--        You do not want this if you are building a kernel for a 64 bit
--        IBM RS/6000 or an Apple G5, choose 6xx.
--        
--        If unsure, select this option
--        
--        Note that the kernel runs in 32-bit mode even on 64-bit chips.
--
--config PPC_82xx
--      bool "Freescale 82xx"
--      select 6xx
--      select PPC_FPU
--
--config PPC_83xx
--      bool "Freescale 83xx"
--      select 6xx
--      select FSL_SOC
--      select 83xx
--      select PPC_FPU
--      select WANT_DEVICE_TREE
--
--config PPC_85xx
--      bool "Freescale 85xx"
--      select E500
--      select FSL_SOC
--      select 85xx
--      select WANT_DEVICE_TREE
--
--config PPC_86xx
--      bool "Freescale 86xx"
--      select 6xx
--      select FSL_SOC
--      select FSL_PCIE
--      select PPC_FPU
--      select ALTIVEC
--      help
--        The Freescale E600 SoCs have 74xx cores.
--
--config PPC_8xx
--      bool "Freescale 8xx"
--      select FSL_SOC
--      select 8xx
--
--config 40x
--      bool "AMCC 40x"
--      select PPC_DCR_NATIVE
--
--config 44x
--      bool "AMCC 44x"
--      select PPC_DCR_NATIVE
--      select WANT_DEVICE_TREE
--
--config E200
--      bool "Freescale e200"
--
--endchoice
--
--config POWER4_ONLY
--      bool "Optimize for POWER4"
--      depends on PPC64
--      default n
--      ---help---
--        Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
--        The resulting binary will not work on POWER3 or RS64 processors
--        when compiled with binutils 2.15 or later.
--
--config POWER3
--      bool
--      depends on PPC64
--      default y if !POWER4_ONLY
--
--config POWER4
--      depends on PPC64
--      def_bool y
--
--config 6xx
--      bool
--
--# this is temp to handle compat with arch=ppc
--config 8xx
--      bool
--
--# this is temp to handle compat with arch=ppc
--config 83xx
--      bool
--
--# this is temp to handle compat with arch=ppc
--config 85xx
--      bool
--
--config E500
--      bool
--
--config PPC_FPU
--      bool
--      default y if PPC64
--
- config PPC_DCR_NATIVE
-       bool
-       default n
-@@ -267,134 +145,6 @@
-       depends on PPC64 # not supported on 32 bits yet
-       default n
--config 4xx
--      bool
--      depends on 40x || 44x
--      default y
--
--config BOOKE
--      bool
--      depends on E200 || E500 || 44x
--      default y
--
--config FSL_BOOKE
--      bool
--      depends on E200 || E500
--      default y
--
--config PTE_64BIT
--      bool
--      depends on 44x || E500
--      default y if 44x
--      default y if E500 && PHYS_64BIT
--
--config PHYS_64BIT
--      bool 'Large physical address support' if E500
--      depends on 44x || E500
--      select RESOURCES_64BIT
--      default y if 44x
--      ---help---
--        This option enables kernel support for larger than 32-bit physical
--        addresses.  This features is not be available on all e500 cores.
--
--        If in doubt, say N here.
--
--config ALTIVEC
--      bool "AltiVec Support"
--      depends on CLASSIC32 || POWER4
--      ---help---
--        This option enables kernel support for the Altivec extensions to the
--        PowerPC processor. The kernel currently supports saving and restoring
--        altivec registers, and turning on the 'altivec enable' bit so user
--        processes can execute altivec instructions.
--
--        This option is only usefully if you have a processor that supports
--        altivec (G4, otherwise known as 74xx series), but does not have
--        any affect on a non-altivec cpu (it does, however add code to the
--        kernel).
--
--        If in doubt, say Y here.
--
--config SPE
--      bool "SPE Support"
--      depends on E200 || E500
--      default y
--      ---help---
--        This option enables kernel support for the Signal Processing
--        Extensions (SPE) to the PowerPC processor. The kernel currently
--        supports saving and restoring SPE registers, and turning on the
--        'spe enable' bit so user processes can execute SPE instructions.
--
--        This option is only useful if you have a processor that supports
--        SPE (e500, otherwise known as 85xx series), but does not have any
--        effect on a non-spe cpu (it does, however add code to the kernel).
--
--        If in doubt, say Y here.
--
--config PPC_STD_MMU
--      bool
--      depends on 6xx || POWER3 || POWER4 || PPC64
--      default y
--
--config PPC_STD_MMU_32
--      def_bool y
--      depends on PPC_STD_MMU && PPC32
--
--config PPC_MM_SLICES
--      bool
--      default y if HUGETLB_PAGE
--      default n
--
--config VIRT_CPU_ACCOUNTING
--      bool "Deterministic task and CPU time accounting"
--      depends on PPC64
--      default y
--      help
--        Select this option to enable more accurate task and CPU time
--        accounting.  This is done by reading a CPU counter on each
--        kernel entry and exit and on transitions within the kernel
--        between system, softirq and hardirq state, so there is a
--        small performance impact.  This also enables accounting of
--        stolen time on logically-partitioned systems running on
--        IBM POWER5-based machines.
--
--        If in doubt, say Y here.
--
--config SMP
--      depends on PPC_STD_MMU
--      bool "Symmetric multi-processing support"
--      ---help---
--        This enables support for systems with more than one CPU. If you have
--        a system with only one CPU, say N. If you have a system with more
--        than one CPU, say Y.  Note that the kernel does not currently
--        support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
--        since they have inadequate hardware support for multiprocessor
--        operation.
--
--        If you say N here, the kernel will run on single and multiprocessor
--        machines, but will use only one CPU of a multiprocessor machine. If
--        you say Y here, the kernel will run on single-processor machines.
--        On a single-processor machine, the kernel will run faster if you say
--        N here.
--
--        If you don't know what to do here, say N.
--
--config NR_CPUS
--      int "Maximum number of CPUs (2-128)"
--      range 2 128
--      depends on SMP
--      default "32" if PPC64
--      default "4"
--
--config NOT_COHERENT_CACHE
--      bool
--      depends on 4xx || 8xx || E200
--      default y
--
--config CONFIG_CHECK_CACHE_COHERENCY
--      bool
--endmenu
--
- source "init/Kconfig"
- source "arch/powerpc/platforms/Kconfig"
-@@ -686,9 +436,9 @@
-       bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
-               || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \
-               || MPC7448HPC2 || PPC_PS3 || PPC_HOLLY
--      default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
-+      default y if !40x && !CPM2 && !8xx && !PPC_83xx \
-               && !PPC_85xx && !PPC_86xx
--      default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
-+      default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
-       default PCI_QSPAN if !4xx && !CPM2 && 8xx
-       select ARCH_SUPPORTS_MSI
-       help
-diff -Nurb linux-2.6.22-570/arch/powerpc/Kconfig.debug linux-2.6.22-590/arch/powerpc/Kconfig.debug
---- linux-2.6.22-570/arch/powerpc/Kconfig.debug        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/Kconfig.debug        2008-01-02 13:56:37.000000000 -0500
-@@ -41,52 +41,9 @@
-         This option will add a small amount of overhead to all hypervisor
-         calls.
--config DEBUGGER
--      bool "Enable debugger hooks"
--      depends on DEBUG_KERNEL
--      help
--        Include in-kernel hooks for kernel debuggers. Unless you are
--        intending to debug the kernel, say N here.
--
--config KGDB
--      bool "Include kgdb kernel debugger"
--      depends on DEBUGGER && (BROKEN || PPC_GEN550 || 4xx)
--      select DEBUG_INFO
--      help
--        Include in-kernel hooks for kgdb, the Linux kernel source level
--        debugger.  See <http://kgdb.sourceforge.net/> for more information.
--        Unless you are intending to debug the kernel, say N here.
--
--choice
--      prompt "Serial Port"
--      depends on KGDB
--      default KGDB_TTYS1
--
--config KGDB_TTYS0
--      bool "ttyS0"
--
--config KGDB_TTYS1
--      bool "ttyS1"
--
--config KGDB_TTYS2
--      bool "ttyS2"
--
--config KGDB_TTYS3
--      bool "ttyS3"
--
--endchoice
--
--config KGDB_CONSOLE
--      bool "Enable serial console thru kgdb port"
--      depends on KGDB && 8xx || CPM2
--      help
--        If you enable this, all serial console messages will be sent
--        over the gdb stub.
--        If unsure, say N.
--
- config XMON
-       bool "Include xmon kernel debugger"
--      depends on DEBUGGER
-+      depends on DEBUG_KERNEL
-       help
-         Include in-kernel hooks for the xmon kernel monitor/debugger.
-         Unless you are intending to debug the kernel, say N here.
-@@ -116,6 +73,11 @@
-         to say Y here, unless you're building for a memory-constrained
-         system.
-+config DEBUGGER
-+      bool
-+      depends on KGDB || XMON
-+      default y
-+
- config IRQSTACKS
-       bool "Use separate kernel stacks when processing interrupts"
-       depends on PPC64
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/44x.c linux-2.6.22-590/arch/powerpc/boot/44x.c
---- linux-2.6.22-570/arch/powerpc/boot/44x.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/boot/44x.c   2008-01-02 13:56:37.000000000 -0500
-@@ -38,3 +38,48 @@
-       dt_fixup_memory(0, memsize);
- }
-+
-+#define SPRN_DBCR0            0x134
-+#define   DBCR0_RST_SYSTEM    0x30000000
-+
-+void ibm44x_dbcr_reset(void)
-+{
-+      unsigned long tmp;
-+
-+      asm volatile (
-+              "mfspr  %0,%1\n"
-+              "oris   %0,%0,%2@h\n"
-+              "mtspr  %1,%0"
-+              : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
-+              );
-+
-+}
-+
-+/* Read 4xx EBC bus bridge registers to get mappings of the peripheral
-+ * banks into the OPB address space */
-+void ibm4xx_fixup_ebc_ranges(const char *ebc)
-+{
-+      void *devp;
-+      u32 bxcr;
-+      u32 ranges[EBC_NUM_BANKS*4];
-+      u32 *p = ranges;
-+      int i;
-+
-+      for (i = 0; i < EBC_NUM_BANKS; i++) {
-+              mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
-+              bxcr = mfdcr(DCRN_EBC0_CFGDATA);
-+
-+              if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
-+                      *p++ = i;
-+                      *p++ = 0;
-+                      *p++ = bxcr & EBC_BXCR_BAS;
-+                      *p++ = EBC_BXCR_BANK_SIZE(bxcr);
-+              }
-+      }
-+
-+      devp = finddevice(ebc);
-+      if (! devp)
-+              fatal("Couldn't locate EBC node %s\n\r", ebc);
-+
-+      setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
-+}
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/44x.h linux-2.6.22-590/arch/powerpc/boot/44x.h
---- linux-2.6.22-570/arch/powerpc/boot/44x.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/boot/44x.h   2008-01-02 13:56:37.000000000 -0500
-@@ -11,6 +11,9 @@
- #define _PPC_BOOT_44X_H_
- void ibm44x_fixup_memsize(void);
-+void ibm4xx_fixup_ebc_ranges(const char *ebc);
-+
-+void ibm44x_dbcr_reset(void);
- void ebony_init(void *mac0, void *mac1);
- #endif /* _PPC_BOOT_44X_H_ */
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/Makefile linux-2.6.22-590/arch/powerpc/boot/Makefile
---- linux-2.6.22-570/arch/powerpc/boot/Makefile        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/boot/Makefile        2008-01-02 13:56:37.000000000 -0500
-@@ -43,8 +43,8 @@
- src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
-               ns16550.c serial.c simple_alloc.c div64.S util.S \
--              gunzip_util.c elf_util.c $(zlib) devtree.c \
--              44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c
-+              gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
-+              44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c
- src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
-               cuboot-ebony.c treeboot-ebony.c prpmc2800.c
- src-boot := $(src-wlib) $(src-plat) empty.c
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/cuboot-83xx.c linux-2.6.22-590/arch/powerpc/boot/cuboot-83xx.c
---- linux-2.6.22-570/arch/powerpc/boot/cuboot-83xx.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/boot/cuboot-83xx.c   2008-01-02 13:56:37.000000000 -0500
-@@ -12,12 +12,12 @@
- #include "ops.h"
- #include "stdio.h"
-+#include "cuboot.h"
- #define TARGET_83xx
- #include "ppcboot.h"
- static bd_t bd;
--extern char _end[];
- extern char _dtb_start[], _dtb_end[];
- static void platform_fixups(void)
-@@ -52,16 +52,7 @@
- void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-                    unsigned long r6, unsigned long r7)
- {
--      unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
--      unsigned long avail_ram = end_of_ram - (unsigned long)_end;
--
--      memcpy(&bd, (bd_t *)r3, sizeof(bd));
--      loader_info.initrd_addr = r4;
--      loader_info.initrd_size = r4 ? r5 - r4 : 0;
--      loader_info.cmdline = (char *)r6;
--      loader_info.cmdline_len = r7 - r6;
--
--      simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
-+      CUBOOT_INIT();
-       ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
-       serial_console_init();
-       platform_ops.fixups = platform_fixups;
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/cuboot-85xx.c linux-2.6.22-590/arch/powerpc/boot/cuboot-85xx.c
---- linux-2.6.22-570/arch/powerpc/boot/cuboot-85xx.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/boot/cuboot-85xx.c   2008-01-02 13:56:37.000000000 -0500
-@@ -12,12 +12,12 @@
- #include "ops.h"
- #include "stdio.h"
-+#include "cuboot.h"
- #define TARGET_85xx
- #include "ppcboot.h"
- static bd_t bd;
--extern char _end[];
- extern char _dtb_start[], _dtb_end[];
- static void platform_fixups(void)
-@@ -53,16 +53,7 @@
- void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-                    unsigned long r6, unsigned long r7)
- {
--      unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
--      unsigned long avail_ram = end_of_ram - (unsigned long)_end;
--
--      memcpy(&bd, (bd_t *)r3, sizeof(bd));
--      loader_info.initrd_addr = r4;
--      loader_info.initrd_size = r4 ? r5 - r4 : 0;
--      loader_info.cmdline = (char *)r6;
--      loader_info.cmdline_len = r7 - r6;
--
--      simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
-+      CUBOOT_INIT();
-       ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
-       serial_console_init();
-       platform_ops.fixups = platform_fixups;
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/cuboot-ebony.c linux-2.6.22-590/arch/powerpc/boot/cuboot-ebony.c
---- linux-2.6.22-570/arch/powerpc/boot/cuboot-ebony.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/boot/cuboot-ebony.c  2008-01-02 13:56:37.000000000 -0500
-@@ -15,28 +15,16 @@
- #include "ops.h"
- #include "stdio.h"
- #include "44x.h"
-+#include "cuboot.h"
- #define TARGET_44x
- #include "ppcboot.h"
- static bd_t bd;
--extern char _end[];
--
--BSS_STACK(4096);
- void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-                    unsigned long r6, unsigned long r7)
- {
--      unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
--      unsigned long avail_ram = end_of_ram - (unsigned long)_end;
--
--      memcpy(&bd, (bd_t *)r3, sizeof(bd));
--      loader_info.initrd_addr = r4;
--      loader_info.initrd_size = r4 ? r5 : 0;
--      loader_info.cmdline = (char *)r6;
--      loader_info.cmdline_len = r7 - r6;
--
--      simple_alloc_init(_end, avail_ram, 32, 64);
--
-+      CUBOOT_INIT();
-       ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr);
- }
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/cuboot.c linux-2.6.22-590/arch/powerpc/boot/cuboot.c
---- linux-2.6.22-570/arch/powerpc/boot/cuboot.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/boot/cuboot.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,35 @@
-+/*
-+ * Compatibility for old (not device tree aware) U-Boot versions
-+ *
-+ * Author: Scott Wood <scottwood@freescale.com>
-+ * Consolidated using macros by David Gibson <david@gibson.dropbear.id.au>
-+ *
-+ * Copyright 2007 David Gibson, IBM Corporation.
-+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ */
-+
-+#include "ops.h"
-+#include "stdio.h"
-+
-+#include "ppcboot.h"
-+
-+extern char _end[];
-+extern char _dtb_start[], _dtb_end[];
-+
-+void cuboot_init(unsigned long r4, unsigned long r5,
-+               unsigned long r6, unsigned long r7,
-+               unsigned long end_of_ram)
-+{
-+      unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-+
-+      loader_info.initrd_addr = r4;
-+      loader_info.initrd_size = r4 ? r5 - r4 : 0;
-+      loader_info.cmdline = (char *)r6;
-+      loader_info.cmdline_len = r7 - r6;
-+
-+      simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
-+}
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/cuboot.h linux-2.6.22-590/arch/powerpc/boot/cuboot.h
---- linux-2.6.22-570/arch/powerpc/boot/cuboot.h        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/boot/cuboot.h        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,14 @@
-+#ifndef _PPC_BOOT_CUBOOT_H_
-+#define _PPC_BOOT_CUBOOT_H_
-+
-+void cuboot_init(unsigned long r4, unsigned long r5,
-+               unsigned long r6, unsigned long r7,
-+               unsigned long end_of_ram);
-+
-+#define CUBOOT_INIT() \
-+      do { \
-+              memcpy(&bd, (bd_t *)r3, sizeof(bd)); \
-+              cuboot_init(r4, r5, r6, r7, bd.bi_memstart + bd.bi_memsize); \
-+      } while (0)
-+
-+#endif /* _PPC_BOOT_CUBOOT_H_ */
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/dcr.h linux-2.6.22-590/arch/powerpc/boot/dcr.h
---- linux-2.6.22-570/arch/powerpc/boot/dcr.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/boot/dcr.h   2008-01-02 13:56:37.000000000 -0500
-@@ -26,6 +26,43 @@
- #define                       SDRAM_CONFIG_BANK_SIZE(reg)     \
-       (0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17))
-+/* 440GP External Bus Controller (EBC) */
-+#define DCRN_EBC0_CFGADDR                             0x012
-+#define DCRN_EBC0_CFGDATA                             0x013
-+#define   EBC_NUM_BANKS                                         8
-+#define   EBC_B0CR                                      0x00
-+#define   EBC_B1CR                                      0x01
-+#define   EBC_B2CR                                      0x02
-+#define   EBC_B3CR                                      0x03
-+#define   EBC_B4CR                                      0x04
-+#define   EBC_B5CR                                      0x05
-+#define   EBC_B6CR                                      0x06
-+#define   EBC_B7CR                                      0x07
-+#define   EBC_BXCR(n)                                   (n)
-+#define           EBC_BXCR_BAS                                    0xfff00000
-+#define           EBC_BXCR_BS                                     0x000e0000
-+#define           EBC_BXCR_BANK_SIZE(reg) \
-+      (0x100000 << (((reg) & EBC_BXCR_BS) >> 17))
-+#define           EBC_BXCR_BU                                     0x00018000
-+#define             EBC_BXCR_BU_OFF                                 0x00000000
-+#define             EBC_BXCR_BU_RO                                  0x00008000
-+#define             EBC_BXCR_BU_WO                                  0x00010000
-+#define             EBC_BXCR_BU_RW                                  0x00018000
-+#define           EBC_BXCR_BW                                     0x00006000
-+#define   EBC_B0AP                                      0x10
-+#define   EBC_B1AP                                      0x11
-+#define   EBC_B2AP                                      0x12
-+#define   EBC_B3AP                                      0x13
-+#define   EBC_B4AP                                      0x14
-+#define   EBC_B5AP                                      0x15
-+#define   EBC_B6AP                                      0x16
-+#define   EBC_B7AP                                      0x17
-+#define   EBC_BXAP(n)                                   (0x10+(n))
-+#define   EBC_BEAR                                      0x20
-+#define   EBC_BESR                                      0x21
-+#define   EBC_CFG                                       0x23
-+#define   EBC_CID                                       0x24
-+
- /* 440GP Clock, PM, chip control */
- #define DCRN_CPC0_SR                                  0x0b0
- #define DCRN_CPC0_ER                                  0x0b1
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/dts/ebony.dts linux-2.6.22-590/arch/powerpc/boot/dts/ebony.dts
---- linux-2.6.22-570/arch/powerpc/boot/dts/ebony.dts   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/boot/dts/ebony.dts   2008-01-02 13:56:37.000000000 -0500
-@@ -135,11 +135,9 @@
-                               #address-cells = <2>;
-                               #size-cells = <1>;
-                               clock-frequency = <0>; // Filled in by zImage
--                              ranges = <0 00000000 fff00000 100000
--                                        1 00000000 48000000 100000
--                                        2 00000000 ff800000 400000
--                                        3 00000000 48200000 100000
--                                        7 00000000 48300000 100000>;
-+                              // ranges property is supplied by zImage
-+                              // based on firmware's configuration of the
-+                              // EBC bridge
-                               interrupts = <5 4>;
-                               interrupt-parent = <&UIC1>;
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/dts/holly.dts linux-2.6.22-590/arch/powerpc/boot/dts/holly.dts
---- linux-2.6.22-570/arch/powerpc/boot/dts/holly.dts   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/boot/dts/holly.dts   2008-01-02 13:56:37.000000000 -0500
-@@ -46,7 +46,7 @@
-       tsi109@c0000000 {
-               device_type = "tsi-bridge";
--              compatible = "tsi-bridge";
-+              compatible = "tsi109-bridge", "tsi108-bridge";
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges = <00000000 c0000000 00010000>;
-@@ -54,52 +54,55 @@
-               i2c@7000 {
-                       device_type = "i2c";
--                      compatible  = "tsi-i2c";
--                      interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
-+                      compatible  = "tsi109-i2c", "tsi108-i2c";
-+                      interrupt-parent = <&MPIC>;
-                       interrupts = <e 2>;
-                       reg = <7000 400>;
-               };
--              mdio@6000 {
-+              MDIO: mdio@6000 {
-                       device_type = "mdio";
--                      compatible = "tsi-ethernet";
--
--                      PHY1: ethernet-phy@6000 {
--                              device_type = "ethernet-phy";
--                              compatible = "bcm54xx";
-+                      compatible = "tsi109-mdio", "tsi108-mdio";
-                               reg = <6000 50>;
--                              phy-id = <1>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      PHY1: ethernet-phy@1 {
-+                              compatible = "bcm5461a";
-+                              reg = <1>;
-+                              txc-rxc-delay-disable;
-                       };
--                      PHY2: ethernet-phy@6400 {
--                              device_type = "ethernet-phy";
--                              compatible = "bcm54xx";
--                              reg = <6000 50>;
--                              phy-id = <2>;
-+                      PHY2: ethernet-phy@2 {
-+                              compatible = "bcm5461a";
-+                              reg = <2>;
-+                              txc-rxc-delay-disable;
-                       };
-               };
-               ethernet@6200 {
-                       device_type = "network";
--                      compatible = "tsi-ethernet";
-+                      compatible = "tsi109-ethernet", "tsi108-ethernet";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <6000 200>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
--                      interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
-+                      interrupt-parent = <&MPIC>;
-                       interrupts = <10 2>;
-+                      mdio-handle = <&MDIO>;
-                       phy-handle = <&PHY1>;
-               };
-               ethernet@6600 {
-                       device_type = "network";
--                      compatible = "tsi-ethernet";
-+                      compatible = "tsi109-ethernet", "tsi108-ethernet";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <6400 200>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
--                      interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
-+                      interrupt-parent = <&MPIC>;
-                       interrupts = <11 2>;
-+                      mdio-handle = <&MDIO>;
-                       phy-handle = <&PHY2>;
-               };
-@@ -110,7 +113,7 @@
-                       virtual-reg = <c0007808>;
-                       clock-frequency = <3F9C6000>;
-                       current-speed = <1c200>;
--                      interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
-+                      interrupt-parent = <&MPIC>;
-                       interrupts = <c 2>;
-               };
-@@ -121,7 +124,7 @@
-                       virtual-reg = <c0007c08>;
-                       clock-frequency = <3F9C6000>;
-                       current-speed = <1c200>;
--                      interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
-+                      interrupt-parent = <&MPIC>;
-                       interrupts = <d 2>;
-               };
-@@ -136,7 +139,7 @@
-               pci@1000 {
-                       device_type = "pci";
--                      compatible = "tsi109";
-+                      compatible = "tsi109-pci", "tsi108-pci";
-                       #interrupt-cells = <1>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-@@ -150,7 +153,7 @@
-                       ranges = <02000000 0 40000000 40000000 0 10000000
-                                 01000000 0 00000000 7e000000 0 00010000>;
-                       clock-frequency = <7f28154>;
--                      interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
-+                      interrupt-parent = <&MPIC>;
-                       interrupts = <17 2>;
-                       interrupt-map-mask = <f800 0 0 7>;
-                       /*----------------------------------------------------+
-@@ -186,13 +189,12 @@
-                               #address-cells = <0>;
-                               #interrupt-cells = <2>;
-                               interrupts = <17 2>;
--                              interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
-+                              interrupt-parent = <&MPIC>;
-                       };
-               };
-       };
-       chosen {
-               linux,stdout-path = "/tsi109@c0000000/serial@7808";
--              bootargs = "console=ttyS0,115200";
-       };
- };
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/dts/mpc7448hpc2.dts linux-2.6.22-590/arch/powerpc/boot/dts/mpc7448hpc2.dts
---- linux-2.6.22-570/arch/powerpc/boot/dts/mpc7448hpc2.dts     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/boot/dts/mpc7448hpc2.dts     2008-01-02 13:56:37.000000000 -0500
-@@ -45,7 +45,7 @@
-               #address-cells = <1>;
-               #size-cells = <1>;
-               #interrupt-cells = <2>;
--              device_type = "tsi-bridge";
-+              device_type = "tsi108-bridge";
-               ranges = <00000000 c0000000 00010000>;
-               reg = <c0000000 00010000>;
-               bus-frequency = <0>;
-@@ -55,27 +55,26 @@
-                       interrupts = <E 0>;
-                       reg = <7000 400>;
-                       device_type = "i2c";
--                      compatible  = "tsi-i2c";
-+                      compatible  = "tsi108-i2c";
-               };
--              mdio@6000 {
-+              MDIO: mdio@6000 {
-                       device_type = "mdio";
--                      compatible = "tsi-ethernet";
-+                      compatible = "tsi108-mdio";
-+                      reg = <6000 50>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
--                      phy8: ethernet-phy@6000 {
-+                      phy8: ethernet-phy@8 {
-                               interrupt-parent = <&mpic>;
-                               interrupts = <2 1>;
--                              reg = <6000 50>;
--                              phy-id = <8>;
--                              device_type = "ethernet-phy";
-+                              reg = <8>;
-                       };
--                      phy9: ethernet-phy@6400 {
-+                      phy9: ethernet-phy@9 {
-                               interrupt-parent = <&mpic>;
-                               interrupts = <2 1>;
--                              reg = <6000 50>;
--                              phy-id = <9>;
--                              device_type = "ethernet-phy";
-+                              reg = <9>;
-                       };
-               };
-@@ -83,12 +82,12 @@
-               ethernet@6200 {
-                       #size-cells = <0>;
-                       device_type = "network";
--                      model = "TSI-ETH";
--                      compatible = "tsi-ethernet";
-+                      compatible = "tsi108-ethernet";
-                       reg = <6000 200>;
-                       address = [ 00 06 D2 00 00 01 ];
-                       interrupts = <10 2>;
-                       interrupt-parent = <&mpic>;
-+                      mdio-handle = <&MDIO>;
-                       phy-handle = <&phy8>;
-               };
-@@ -96,12 +95,12 @@
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       device_type = "network";
--                      model = "TSI-ETH";
--                      compatible = "tsi-ethernet";
-+                      compatible = "tsi108-ethernet";
-                       reg = <6400 200>;
-                       address = [ 00 06 D2 00 00 02 ];
-                       interrupts = <11 2>;
-                       interrupt-parent = <&mpic>;
-+                      mdio-handle = <&MDIO>;
-                       phy-handle = <&phy9>;
-               };
-@@ -135,7 +134,7 @@
-                               big-endian;
-               };
-               pci@1000 {
--                      compatible = "tsi10x";
-+                      compatible = "tsi108-pci";
-                       device_type = "pci";
-                       #interrupt-cells = <1>;
-                       #size-cells = <2>;
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/ebony.c linux-2.6.22-590/arch/powerpc/boot/ebony.c
---- linux-2.6.22-570/arch/powerpc/boot/ebony.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/boot/ebony.c 2008-01-02 13:56:37.000000000 -0500
-@@ -100,28 +100,13 @@
-       ibm440gp_fixup_clocks(sysclk, 6 * 1843200);
-       ibm44x_fixup_memsize();
-       dt_fixup_mac_addresses(ebony_mac0, ebony_mac1);
--}
--
--#define SPRN_DBCR0            0x134
--#define   DBCR0_RST_SYSTEM    0x30000000
--
--static void ebony_exit(void)
--{
--      unsigned long tmp;
--
--      asm volatile (
--              "mfspr  %0,%1\n"
--              "oris   %0,%0,%2@h\n"
--              "mtspr  %1,%0"
--              : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
--              );
--
-+      ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
- }
- void ebony_init(void *mac0, void *mac1)
- {
-       platform_ops.fixups = ebony_fixups;
--      platform_ops.exit = ebony_exit;
-+      platform_ops.exit = ibm44x_dbcr_reset;
-       ebony_mac0 = mac0;
-       ebony_mac1 = mac1;
-       ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/of.c linux-2.6.22-590/arch/powerpc/boot/of.c
---- linux-2.6.22-570/arch/powerpc/boot/of.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/boot/of.c    2008-01-02 13:56:37.000000000 -0500
-@@ -15,8 +15,7 @@
- #include "page.h"
- #include "ops.h"
--typedef void *ihandle;
--typedef void *phandle;
-+#include "of.h"
- extern char _end[];
-@@ -25,154 +24,10 @@
- #define RAM_END               (512<<20)       /* Fixme: use OF */
- #define       ONE_MB          0x100000
--int (*prom) (void *);
- static unsigned long claim_base;
--static int call_prom(const char *service, int nargs, int nret, ...)
--{
--      int i;
--      struct prom_args {
--              const char *service;
--              int nargs;
--              int nret;
--              unsigned int args[12];
--      } args;
--      va_list list;
--
--      args.service = service;
--      args.nargs = nargs;
--      args.nret = nret;
--
--      va_start(list, nret);
--      for (i = 0; i < nargs; i++)
--              args.args[i] = va_arg(list, unsigned int);
--      va_end(list);
--
--      for (i = 0; i < nret; i++)
--              args.args[nargs+i] = 0;
--
--      if (prom(&args) < 0)
--              return -1;
--
--      return (nret > 0)? args.args[nargs]: 0;
--}
--
--static int call_prom_ret(const char *service, int nargs, int nret,
--                unsigned int *rets, ...)
--{
--      int i;
--      struct prom_args {
--              const char *service;
--              int nargs;
--              int nret;
--              unsigned int args[12];
--      } args;
--      va_list list;
--
--      args.service = service;
--      args.nargs = nargs;
--      args.nret = nret;
--
--      va_start(list, rets);
--      for (i = 0; i < nargs; i++)
--              args.args[i] = va_arg(list, unsigned int);
--      va_end(list);
--
--      for (i = 0; i < nret; i++)
--              args.args[nargs+i] = 0;
--
--      if (prom(&args) < 0)
--              return -1;
--
--      if (rets != (void *) 0)
--              for (i = 1; i < nret; ++i)
--                      rets[i-1] = args.args[nargs+i];
--
--      return (nret > 0)? args.args[nargs]: 0;
--}
--
--/*
-- * Older OF's require that when claiming a specific range of addresses,
-- * we claim the physical space in the /memory node and the virtual
-- * space in the chosen mmu node, and then do a map operation to
-- * map virtual to physical.
-- */
--static int need_map = -1;
--static ihandle chosen_mmu;
--static phandle memory;
--
--/* returns true if s2 is a prefix of s1 */
--static int string_match(const char *s1, const char *s2)
--{
--      for (; *s2; ++s2)
--              if (*s1++ != *s2)
--                      return 0;
--      return 1;
--}
--
--static int check_of_version(void)
--{
--      phandle oprom, chosen;
--      char version[64];
--
--      oprom = finddevice("/openprom");
--      if (oprom == (phandle) -1)
--              return 0;
--      if (getprop(oprom, "model", version, sizeof(version)) <= 0)
--              return 0;
--      version[sizeof(version)-1] = 0;
--      printf("OF version = '%s'\r\n", version);
--      if (!string_match(version, "Open Firmware, 1.")
--          && !string_match(version, "FirmWorks,3."))
--              return 0;
--      chosen = finddevice("/chosen");
--      if (chosen == (phandle) -1) {
--              chosen = finddevice("/chosen@0");
--              if (chosen == (phandle) -1) {
--                      printf("no chosen\n");
--                      return 0;
--              }
--      }
--      if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
--              printf("no mmu\n");
--              return 0;
--      }
--      memory = (ihandle) call_prom("open", 1, 1, "/memory");
--      if (memory == (ihandle) -1) {
--              memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
--              if (memory == (ihandle) -1) {
--                      printf("no memory node\n");
--                      return 0;
--              }
--      }
--      printf("old OF detected\r\n");
--      return 1;
--}
--
--static void *claim(unsigned long virt, unsigned long size, unsigned long align)
--{
--      int ret;
--      unsigned int result;
--
--      if (need_map < 0)
--              need_map = check_of_version();
--      if (align || !need_map)
--              return (void *) call_prom("claim", 3, 1, virt, size, align);
--
--      ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
--                          align, size, virt);
--      if (ret != 0 || result == -1)
--              return (void *) -1;
--      ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
--                          align, size, virt);
--      /* 0x12 == coherent + read/write */
--      ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
--                      0x12, size, virt, virt);
--      return (void *) virt;
--}
--
- static void *of_try_claim(unsigned long size)
- {
-       unsigned long addr = 0;
-@@ -184,7 +39,7 @@
- #ifdef DEBUG
-               printf("    trying: 0x%08lx\n\r", claim_base);
- #endif
--              addr = (unsigned long)claim(claim_base, size, 0);
-+              addr = (unsigned long)of_claim(claim_base, size, 0);
-               if ((void *)addr != (void *)-1)
-                       break;
-       }
-@@ -218,52 +73,24 @@
-       return p;
- }
--static void of_exit(void)
--{
--      call_prom("exit", 0, 0);
--}
--
- /*
-  * OF device tree routines
-  */
- static void *of_finddevice(const char *name)
- {
--      return (phandle) call_prom("finddevice", 1, 1, name);
-+      return (phandle) of_call_prom("finddevice", 1, 1, name);
- }
- static int of_getprop(const void *phandle, const char *name, void *buf,
-               const int buflen)
- {
--      return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
-+      return of_call_prom("getprop", 4, 1, phandle, name, buf, buflen);
- }
- static int of_setprop(const void *phandle, const char *name, const void *buf,
-               const int buflen)
- {
--      return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
--}
--
--/*
-- * OF console routines
-- */
--static void *of_stdout_handle;
--
--static int of_console_open(void)
--{
--      void *devp;
--
--      if (((devp = finddevice("/chosen")) != NULL)
--                      && (getprop(devp, "stdout", &of_stdout_handle,
--                              sizeof(of_stdout_handle))
--                              == sizeof(of_stdout_handle)))
--              return 0;
--
--      return -1;
--}
--
--static void of_console_write(char *buf, int len)
--{
--      call_prom("write", 3, 1, of_stdout_handle, buf, len);
-+      return of_call_prom("setprop", 4, 1, phandle, name, buf, buflen);
- }
- void platform_init(unsigned long a1, unsigned long a2, void *promptr)
-@@ -277,10 +104,9 @@
-       dt_ops.getprop = of_getprop;
-       dt_ops.setprop = of_setprop;
--      console_ops.open = of_console_open;
--      console_ops.write = of_console_write;
-+      of_console_init();
--      prom = (int (*)(void *))promptr;
-+      of_init(promptr);
-       loader_info.promptr = promptr;
-       if (a1 && a2 && a2 != 0xdeadbeef) {
-               loader_info.initrd_addr = a1;
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/of.h linux-2.6.22-590/arch/powerpc/boot/of.h
---- linux-2.6.22-570/arch/powerpc/boot/of.h    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/boot/of.h    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,15 @@
-+#ifndef _PPC_BOOT_OF_H_
-+#define _PPC_BOOT_OF_H_
-+
-+typedef void *phandle;
-+typedef void *ihandle;
-+
-+void of_init(void *promptr);
-+int of_call_prom(const char *service, int nargs, int nret, ...);
-+void *of_claim(unsigned long virt, unsigned long size, unsigned long align);
-+void of_exit(void);
-+
-+/* Console functions */
-+void of_console_init(void);
-+
-+#endif /* _PPC_BOOT_OF_H_ */
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/ofconsole.c linux-2.6.22-590/arch/powerpc/boot/ofconsole.c
---- linux-2.6.22-570/arch/powerpc/boot/ofconsole.c     1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/boot/ofconsole.c     2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,45 @@
-+/*
-+ * OF console routines
-+ *
-+ * Copyright (C) Paul Mackerras 1997.
-+ *
-+ * 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.
-+ */
-+#include <stddef.h>
-+#include "types.h"
-+#include "elf.h"
-+#include "string.h"
-+#include "stdio.h"
-+#include "page.h"
-+#include "ops.h"
-+
-+#include "of.h"
-+
-+static void *of_stdout_handle;
-+
-+static int of_console_open(void)
-+{
-+      void *devp;
-+
-+      if (((devp = finddevice("/chosen")) != NULL)
-+                      && (getprop(devp, "stdout", &of_stdout_handle,
-+                              sizeof(of_stdout_handle))
-+                              == sizeof(of_stdout_handle)))
-+              return 0;
-+
-+      return -1;
-+}
-+
-+static void of_console_write(char *buf, int len)
-+{
-+      of_call_prom("write", 3, 1, of_stdout_handle, buf, len);
-+}
-+
-+void of_console_init(void)
-+{
-+      console_ops.open = of_console_open;
-+      console_ops.write = of_console_write;
-+}
-diff -Nurb linux-2.6.22-570/arch/powerpc/boot/oflib.c linux-2.6.22-590/arch/powerpc/boot/oflib.c
---- linux-2.6.22-570/arch/powerpc/boot/oflib.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/boot/oflib.c 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,172 @@
-+/*
-+ * Copyright (C) Paul Mackerras 1997.
-+ *
-+ * 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.
-+ */
-+#include <stddef.h>
-+#include "types.h"
-+#include "elf.h"
-+#include "string.h"
-+#include "stdio.h"
-+#include "page.h"
-+#include "ops.h"
-+
-+#include "of.h"
-+
-+static int (*prom) (void *);
-+
-+void of_init(void *promptr)
-+{
-+      prom = (int (*)(void *))promptr;
-+}
-+
-+int of_call_prom(const char *service, int nargs, int nret, ...)
-+{
-+      int i;
-+      struct prom_args {
-+              const char *service;
-+              int nargs;
-+              int nret;
-+              unsigned int args[12];
-+      } args;
-+      va_list list;
-+
-+      args.service = service;
-+      args.nargs = nargs;
-+      args.nret = nret;
-+
-+      va_start(list, nret);
-+      for (i = 0; i < nargs; i++)
-+              args.args[i] = va_arg(list, unsigned int);
-+      va_end(list);
-+
-+      for (i = 0; i < nret; i++)
-+              args.args[nargs+i] = 0;
-+
-+      if (prom(&args) < 0)
-+              return -1;
-+
-+      return (nret > 0)? args.args[nargs]: 0;
-+}
-+
-+static int of_call_prom_ret(const char *service, int nargs, int nret,
-+                          unsigned int *rets, ...)
-+{
-+      int i;
-+      struct prom_args {
-+              const char *service;
-+              int nargs;
-+              int nret;
-+              unsigned int args[12];
-+      } args;
-+      va_list list;
-+
-+      args.service = service;
-+      args.nargs = nargs;
-+      args.nret = nret;
-+
-+      va_start(list, rets);
-+      for (i = 0; i < nargs; i++)
-+              args.args[i] = va_arg(list, unsigned int);
-+      va_end(list);
-+
-+      for (i = 0; i < nret; i++)
-+              args.args[nargs+i] = 0;
-+
-+      if (prom(&args) < 0)
-+              return -1;
-+
-+      if (rets != (void *) 0)
-+              for (i = 1; i < nret; ++i)
-+                      rets[i-1] = args.args[nargs+i];
-+
-+      return (nret > 0)? args.args[nargs]: 0;
-+}
-+
-+/* returns true if s2 is a prefix of s1 */
-+static int string_match(const char *s1, const char *s2)
-+{
-+      for (; *s2; ++s2)
-+              if (*s1++ != *s2)
-+                      return 0;
-+      return 1;
-+}
-+
-+/*
-+ * Older OF's require that when claiming a specific range of addresses,
-+ * we claim the physical space in the /memory node and the virtual
-+ * space in the chosen mmu node, and then do a map operation to
-+ * map virtual to physical.
-+ */
-+static int need_map = -1;
-+static ihandle chosen_mmu;
-+static phandle memory;
-+
-+static int check_of_version(void)
-+{
-+      phandle oprom, chosen;
-+      char version[64];
-+
-+      oprom = finddevice("/openprom");
-+      if (oprom == (phandle) -1)
-+              return 0;
-+      if (getprop(oprom, "model", version, sizeof(version)) <= 0)
-+              return 0;
-+      version[sizeof(version)-1] = 0;
-+      printf("OF version = '%s'\r\n", version);
-+      if (!string_match(version, "Open Firmware, 1.")
-+          && !string_match(version, "FirmWorks,3."))
-+              return 0;
-+      chosen = finddevice("/chosen");
-+      if (chosen == (phandle) -1) {
-+              chosen = finddevice("/chosen@0");
-+              if (chosen == (phandle) -1) {
-+                      printf("no chosen\n");
-+                      return 0;
-+              }
-+      }
-+      if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
-+              printf("no mmu\n");
-+              return 0;
-+      }
-+      memory = (ihandle) of_call_prom("open", 1, 1, "/memory");
-+      if (memory == (ihandle) -1) {
-+              memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0");
-+              if (memory == (ihandle) -1) {
-+                      printf("no memory node\n");
-+                      return 0;
-+              }
-+      }
-+      printf("old OF detected\r\n");
-+      return 1;
-+}
-+
-+void *of_claim(unsigned long virt, unsigned long size, unsigned long align)
-+{
-+      int ret;
-+      unsigned int result;
-+
-+      if (need_map < 0)
-+              need_map = check_of_version();
-+      if (align || !need_map)
-+              return (void *) of_call_prom("claim", 3, 1, virt, size, align);
-+
-+      ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", memory,
-+                             align, size, virt);
-+      if (ret != 0 || result == -1)
-+              return (void *) -1;
-+      ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
-+                             align, size, virt);
-+      /* 0x12 == coherent + read/write */
-+      ret = of_call_prom("call-method", 6, 1, "map", chosen_mmu,
-+                         0x12, size, virt, virt);
-+      return (void *) virt;
-+}
-+
-+void of_exit(void)
-+{
-+      of_call_prom("exit", 0, 0);
-+}
-diff -Nurb linux-2.6.22-570/arch/powerpc/configs/holly_defconfig linux-2.6.22-590/arch/powerpc/configs/holly_defconfig
---- linux-2.6.22-570/arch/powerpc/configs/holly_defconfig      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/configs/holly_defconfig      2008-01-02 13:56:37.000000000 -0500
-@@ -190,7 +190,8 @@
- # CONFIG_RESOURCES_64BIT is not set
- CONFIG_ZONE_DMA_FLAG=1
- CONFIG_PROC_DEVICETREE=y
--# CONFIG_CMDLINE_BOOL is not set
-+CONFIG_CMDLINE_BOOL=y
-+CONFIG_CMDLINE="console=ttyS0,115200"
- # CONFIG_PM is not set
- # CONFIG_SECCOMP is not set
- # CONFIG_WANT_DEVICE_TREE is not set
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/Makefile linux-2.6.22-590/arch/powerpc/kernel/Makefile
---- linux-2.6.22-570/arch/powerpc/kernel/Makefile      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/Makefile      2008-01-02 13:56:37.000000000 -0500
-@@ -12,7 +12,8 @@
- obj-y                         := semaphore.o cputable.o ptrace.o syscalls.o \
-                                  irq.o align.o signal_32.o pmc.o vdso.o \
--                                 init_task.o process.o systbl.o idle.o
-+                                 init_task.o process.o systbl.o idle.o \
-+                                 signal.o
- obj-y                         += vdso32/
- obj-$(CONFIG_PPC64)           += setup_64.o binfmt_elf32.o sys_ppc32.o \
-                                  signal_64.o ptrace32.o \
-@@ -62,10 +63,16 @@
- obj-$(CONFIG_KPROBES)         += kprobes.o
- obj-$(CONFIG_PPC_UDBG_16550)  += legacy_serial.o udbg_16550.o
-+ifeq ($(CONFIG_PPC32),y)
-+obj-$(CONFIG_KGDB)            += kgdb.o kgdb_setjmp32.o
-+else
-+obj-$(CONFIG_KGDB)            += kgdb.o kgdb_setjmp64.o
-+endif
-+
- module-$(CONFIG_PPC64)                += module_64.o
- obj-$(CONFIG_MODULES)         += $(module-y)
--pci64-$(CONFIG_PPC64)         += pci_64.o pci_dn.o
-+pci64-$(CONFIG_PPC64)         += pci_64.o pci_dn.o isa-bridge.o
- pci32-$(CONFIG_PPC32)         := pci_32.o
- obj-$(CONFIG_PCI)             += $(pci64-y) $(pci32-y)
- obj-$(CONFIG_PCI_MSI)         += msi.o
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/head_32.S linux-2.6.22-590/arch/powerpc/kernel/head_32.S
---- linux-2.6.22-570/arch/powerpc/kernel/head_32.S     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/head_32.S     2008-01-02 13:56:37.000000000 -0500
-@@ -9,7 +9,6 @@
-  *  rewritten by Paul Mackerras.
-  *    Copyright (C) 1996 Paul Mackerras.
-  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  *  This file contains the low-level support and setup for the
-  *  PowerPC platform, including trap and interrupt dispatch.
-@@ -32,10 +31,6 @@
- #include <asm/ppc_asm.h>
- #include <asm/asm-offsets.h>
--#ifdef CONFIG_APUS
--#include <asm/amigappc.h>
--#endif
--
- /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
- #define LOAD_BAT(n, reg, RA, RB)      \
-       /* see the comment for clear_bats() -- Cort */ \
-@@ -92,11 +87,6 @@
-  *  r4: virtual address of boot_infos_t
-  *  r5: 0
-  *
-- * APUS
-- *   r3: 'APUS'
-- *   r4: physical address of memory base
-- *   Linux/m68k style BootInfo structure at &_end.
-- *
-  * PREP
-  * This is jumped to on prep systems right after the kernel is relocated
-  * to its proper place in memory by the boot loader.  The expected layout
-@@ -150,14 +140,6 @@
-  */
-       bl      early_init
--#ifdef CONFIG_APUS
--/* On APUS the __va/__pa constants need to be set to the correct
-- * values before continuing.
-- */
--      mr      r4,r30
--      bl      fix_mem_constants
--#endif /* CONFIG_APUS */
--
- /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
-  * the physical address we are running at, returned by early_init()
-  */
-@@ -167,7 +149,7 @@
-       bl      flush_tlbs
-       bl      initial_bats
--#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
-+#if defined(CONFIG_BOOTX_TEXT)
-       bl      setup_disp_bat
- #endif
-@@ -183,7 +165,6 @@
- #endif /* CONFIG_6xx */
--#ifndef CONFIG_APUS
- /*
-  * We need to run with _start at physical address 0.
-  * On CHRP, we are loaded at 0x10000 since OF on CHRP uses
-@@ -196,7 +177,6 @@
-       addis   r4,r3,KERNELBASE@h      /* current address of _start */
-       cmpwi   0,r4,0                  /* are we already running at 0? */
-       bne     relocate_kernel
--#endif /* CONFIG_APUS */
- /*
-  * we now have the 1st 16M of ram mapped with the bats.
-  * prep needs the mmu to be turned on here, but pmac already has it on.
-@@ -881,85 +861,6 @@
-       addi    r6,r6,4
-       blr
--#ifdef CONFIG_APUS
--/*
-- * On APUS the physical base address of the kernel is not known at compile
-- * time, which means the __pa/__va constants used are incorrect. In the
-- * __init section is recorded the virtual addresses of instructions using
-- * these constants, so all that has to be done is fix these before
-- * continuing the kernel boot.
-- *
-- * r4 = The physical address of the kernel base.
-- */
--fix_mem_constants:
--      mr      r10,r4
--      addis   r10,r10,-KERNELBASE@h    /* virt_to_phys constant */
--      neg     r11,r10                  /* phys_to_virt constant */
--
--      lis     r12,__vtop_table_begin@h
--      ori     r12,r12,__vtop_table_begin@l
--      add     r12,r12,r10              /* table begin phys address */
--      lis     r13,__vtop_table_end@h
--      ori     r13,r13,__vtop_table_end@l
--      add     r13,r13,r10              /* table end phys address */
--      subi    r12,r12,4
--      subi    r13,r13,4
--1:    lwzu    r14,4(r12)               /* virt address of instruction */
--      add     r14,r14,r10              /* phys address of instruction */
--      lwz     r15,0(r14)               /* instruction, now insert top */
--      rlwimi  r15,r10,16,16,31         /* half of vp const in low half */
--      stw     r15,0(r14)               /* of instruction and restore. */
--      dcbst   r0,r14                   /* write it to memory */
--      sync
--      icbi    r0,r14                   /* flush the icache line */
--      cmpw    r12,r13
--      bne     1b
--      sync                            /* additional sync needed on g4 */
--      isync
--
--/*
-- * Map the memory where the exception handlers will
-- * be copied to when hash constants have been patched.
-- */
--#ifdef CONFIG_APUS_FAST_EXCEPT
--      lis     r8,0xfff0
--#else
--      lis     r8,0
--#endif
--      ori     r8,r8,0x2               /* 128KB, supervisor */
--      mtspr   SPRN_DBAT3U,r8
--      mtspr   SPRN_DBAT3L,r8
--
--      lis     r12,__ptov_table_begin@h
--      ori     r12,r12,__ptov_table_begin@l
--      add     r12,r12,r10              /* table begin phys address */
--      lis     r13,__ptov_table_end@h
--      ori     r13,r13,__ptov_table_end@l
--      add     r13,r13,r10              /* table end phys address */
--      subi    r12,r12,4
--      subi    r13,r13,4
--1:    lwzu    r14,4(r12)               /* virt address of instruction */
--      add     r14,r14,r10              /* phys address of instruction */
--      lwz     r15,0(r14)               /* instruction, now insert top */
--      rlwimi  r15,r11,16,16,31         /* half of pv const in low half*/
--      stw     r15,0(r14)               /* of instruction and restore. */
--      dcbst   r0,r14                   /* write it to memory */
--      sync
--      icbi    r0,r14                   /* flush the icache line */
--      cmpw    r12,r13
--      bne     1b
--
--      sync                            /* additional sync needed on g4 */
--      isync                           /* No speculative loading until now */
--      blr
--
--/***********************************************************************
-- *  Please note that on APUS the exception handlers are located at the
-- *  physical address 0xfff0000. For this reason, the exception handlers
-- *  cannot use relative branches to access the code below.
-- ***********************************************************************/
--#endif /* CONFIG_APUS */
--
- #ifdef CONFIG_SMP
- #ifdef CONFIG_GEMINI
-       .globl  __secondary_start_gemini
-@@ -1135,19 +1036,6 @@
-       bl      __save_cpu_setup
-       bl      MMU_init
--#ifdef CONFIG_APUS
--      /* Copy exception code to exception vector base on APUS. */
--      lis     r4,KERNELBASE@h
--#ifdef CONFIG_APUS_FAST_EXCEPT
--      lis     r3,0xfff0               /* Copy to 0xfff00000 */
--#else
--      lis     r3,0                    /* Copy to 0x00000000 */
--#endif
--      li      r5,0x4000               /* # bytes of memory to copy */
--      li      r6,0
--      bl      copy_and_flush          /* copy the first 0x4000 bytes */
--#endif  /* CONFIG_APUS */
--
- /*
-  * Go back to running unmapped so we can load up new values
-  * for SDR1 (hash table pointer) and the segment registers
-@@ -1324,11 +1212,7 @@
- #else
-       ori     r8,r8,2                 /* R/W access */
- #endif /* CONFIG_SMP */
--#ifdef CONFIG_APUS
--      ori     r11,r11,BL_8M<<2|0x2    /* set up 8MB BAT registers for 604 */
--#else
-       ori     r11,r11,BL_256M<<2|0x2  /* set up BAT registers for 604 */
--#endif /* CONFIG_APUS */
-       mtspr   SPRN_DBAT0L,r8          /* N.B. 6xx (not 601) have valid */
-       mtspr   SPRN_DBAT0U,r11         /* bit in upper BAT register */
-@@ -1338,7 +1222,7 @@
-       blr
--#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
-+#ifdef CONFIG_BOOTX_TEXT
- setup_disp_bat:
-       /*
-        * setup the display bat prepared for us in prom.c
-@@ -1362,7 +1246,7 @@
- 1:    mtspr   SPRN_IBAT3L,r8
-       mtspr   SPRN_IBAT3U,r11
-       blr
--#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
-+#endif /* CONFIG_BOOTX_TEXT */
- #ifdef CONFIG_8260
- /* Jump into the system reset for the rom.
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/irq.c linux-2.6.22-590/arch/powerpc/kernel/irq.c
---- linux-2.6.22-570/arch/powerpc/kernel/irq.c 2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/kernel/irq.c 2008-01-02 13:56:37.000000000 -0500
-@@ -7,7 +7,6 @@
-  *    Copyright (C) 1996-2001 Cort Dougan
-  *  Adapted for Power Macintosh by Paul Mackerras
-  *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  * This program is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU General Public License
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/isa-bridge.c linux-2.6.22-590/arch/powerpc/kernel/isa-bridge.c
---- linux-2.6.22-570/arch/powerpc/kernel/isa-bridge.c  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/kernel/isa-bridge.c  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,271 @@
-+/*
-+ * Routines for tracking a legacy ISA bridge
-+ *
-+ * Copyrigh 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
-+ *
-+ * Some bits and pieces moved over from pci_64.c
-+ *
-+ * Copyrigh 2003 Anton Blanchard <anton@au.ibm.com>, IBM Corp.
-+ *
-+ *      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.
-+ */
-+
-+#define DEBUG
-+
-+#include <linux/kernel.h>
-+#include <linux/pci.h>
-+#include <linux/string.h>
-+#include <linux/init.h>
-+#include <linux/mm.h>
-+#include <linux/notifier.h>
-+
-+#include <asm/processor.h>
-+#include <asm/io.h>
-+#include <asm/prom.h>
-+#include <asm/pci-bridge.h>
-+#include <asm/machdep.h>
-+#include <asm/ppc-pci.h>
-+#include <asm/firmware.h>
-+
-+unsigned long isa_io_base;    /* NULL if no ISA bus */
-+EXPORT_SYMBOL(isa_io_base);
-+
-+/* Cached ISA bridge dev. */
-+static struct device_node *isa_bridge_devnode;
-+struct pci_dev *isa_bridge_pcidev;
-+EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
-+
-+#define ISA_SPACE_MASK 0x1
-+#define ISA_SPACE_IO 0x1
-+
-+static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
-+                                              unsigned long phb_io_base_phys)
-+{
-+      /* We should get some saner parsing here and remove these structs */
-+      struct pci_address {
-+              u32 a_hi;
-+              u32 a_mid;
-+              u32 a_lo;
-+      };
-+
-+      struct isa_address {
-+              u32 a_hi;
-+              u32 a_lo;
-+      };
-+
-+      struct isa_range {
-+              struct isa_address isa_addr;
-+              struct pci_address pci_addr;
-+              unsigned int size;
-+      };
-+
-+      const struct isa_range *range;
-+      unsigned long pci_addr;
-+      unsigned int isa_addr;
-+      unsigned int size;
-+      int rlen = 0;
-+
-+      range = of_get_property(isa_node, "ranges", &rlen);
-+      if (range == NULL || (rlen < sizeof(struct isa_range)))
-+              goto inval_range;
-+
-+      /* From "ISA Binding to 1275"
-+       * The ranges property is laid out as an array of elements,
-+       * each of which comprises:
-+       *   cells 0 - 1:       an ISA address
-+       *   cells 2 - 4:       a PCI address
-+       *                      (size depending on dev->n_addr_cells)
-+       *   cell 5:            the size of the range
-+       */
-+      if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) {
-+              range++;
-+              rlen -= sizeof(struct isa_range);
-+              if (rlen < sizeof(struct isa_range))
-+                      goto inval_range;
-+      }
-+      if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO)
-+              goto inval_range;
-+
-+      isa_addr = range->isa_addr.a_lo;
-+      pci_addr = (unsigned long) range->pci_addr.a_mid << 32 |
-+              range->pci_addr.a_lo;
-+
-+      /* Assume these are both zero. Note: We could fix that and
-+       * do a proper parsing instead ... oh well, that will do for
-+       * now as nobody uses fancy mappings for ISA bridges
-+       */
-+      if ((pci_addr != 0) || (isa_addr != 0)) {
-+              printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
-+                     __FUNCTION__);
-+              return;
-+      }
-+
-+      /* Align size and make sure it's cropped to 64K */
-+      size = PAGE_ALIGN(range->size);
-+      if (size > 0x10000)
-+              size = 0x10000;
-+
-+      printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
-+             "mapping 64k\n");
-+
-+      __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
-+                   size, _PAGE_NO_CACHE|_PAGE_GUARDED);
-+      return;
-+
-+inval_range:
-+      printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
-+             "mapping 64k\n");
-+      __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
-+                   0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED);
-+}
-+
-+
-+/**
-+ * isa_bridge_find_early - Find and map the ISA IO space early before
-+ *                         main PCI discovery. This is optionally called by
-+ *                         the arch code when adding PCI PHBs to get early
-+ *                         access to ISA IO ports
-+ */
-+void __init isa_bridge_find_early(struct pci_controller *hose)
-+{
-+      struct device_node *np, *parent = NULL, *tmp;
-+
-+      /* If we already have an ISA bridge, bail off */
-+      if (isa_bridge_devnode != NULL)
-+              return;
-+
-+      /* For each "isa" node in the system. Note : we do a search by
-+       * type and not by name. It might be better to do by name but that's
-+       * what the code used to do and I don't want to break too much at
-+       * once. We can look into changing that separately
-+       */
-+      for_each_node_by_type(np, "isa") {
-+              /* Look for our hose being a parent */
-+              for (parent = of_get_parent(np); parent;) {
-+                      if (parent == hose->arch_data) {
-+                              of_node_put(parent);
-+                              break;
-+                      }
-+                      tmp = parent;
-+                      parent = of_get_parent(parent);
-+                      of_node_put(tmp);
-+              }
-+              if (parent != NULL)
-+                      break;
-+      }
-+      if (np == NULL)
-+              return;
-+      isa_bridge_devnode = np;
-+
-+      /* Now parse the "ranges" property and setup the ISA mapping */
-+      pci_process_ISA_OF_ranges(np, hose->io_base_phys);
-+
-+      /* Set the global ISA io base to indicate we have an ISA bridge */
-+      isa_io_base = ISA_IO_BASE;
-+
-+      pr_debug("ISA bridge (early) is %s\n", np->full_name);
-+}
-+
-+/**
-+ * isa_bridge_find_late - Find and map the ISA IO space upon discovery of
-+ *                        a new ISA bridge
-+ */
-+static void __devinit isa_bridge_find_late(struct pci_dev *pdev,
-+                                         struct device_node *devnode)
-+{
-+      struct pci_controller *hose = pci_bus_to_host(pdev->bus);
-+
-+      /* Store ISA device node and PCI device */
-+      isa_bridge_devnode = of_node_get(devnode);
-+      isa_bridge_pcidev = pdev;
-+
-+      /* Now parse the "ranges" property and setup the ISA mapping */
-+      pci_process_ISA_OF_ranges(devnode, hose->io_base_phys);
-+
-+      /* Set the global ISA io base to indicate we have an ISA bridge */
-+      isa_io_base = ISA_IO_BASE;
-+
-+      pr_debug("ISA bridge (late) is %s on %s\n",
-+               devnode->full_name, pci_name(pdev));
-+}
-+
-+/**
-+ * isa_bridge_remove - Remove/unmap an ISA bridge
-+ */
-+static void isa_bridge_remove(void)
-+{
-+      pr_debug("ISA bridge removed !\n");
-+
-+      /* Clear the global ISA io base to indicate that we have no more
-+       * ISA bridge. Note that drivers don't quite handle that, though
-+       * we should probably do something about it. But do we ever really
-+       * have ISA bridges being removed on machines using legacy devices ?
-+       */
-+      isa_io_base = ISA_IO_BASE;
-+
-+      /* Clear references to the bridge */
-+      of_node_put(isa_bridge_devnode);
-+      isa_bridge_devnode = NULL;
-+      isa_bridge_pcidev = NULL;
-+
-+      /* Unmap the ISA area */
-+      __iounmap_at((void *)ISA_IO_BASE, 0x10000);
-+}
-+
-+/**
-+ * isa_bridge_notify - Get notified of PCI devices addition/removal
-+ */
-+static int __devinit isa_bridge_notify(struct notifier_block *nb,
-+                                     unsigned long action, void *data)
-+{
-+      struct device *dev = data;
-+      struct pci_dev *pdev = to_pci_dev(dev);
-+      struct device_node *devnode = pci_device_to_OF_node(pdev);
-+
-+      switch(action) {
-+      case BUS_NOTIFY_ADD_DEVICE:
-+              /* Check if we have an early ISA device, without PCI dev */
-+              if (isa_bridge_devnode && isa_bridge_devnode == devnode &&
-+                  !isa_bridge_pcidev) {
-+                      pr_debug("ISA bridge PCI attached: %s\n",
-+                               pci_name(pdev));
-+                      isa_bridge_pcidev = pdev;
-+              }
-+
-+              /* Check if we have no ISA device, and this happens to be one,
-+               * register it as such if it has an OF device
-+               */
-+              if (!isa_bridge_devnode && devnode && devnode->type &&
-+                  !strcmp(devnode->type, "isa"))
-+                      isa_bridge_find_late(pdev, devnode);
-+
-+              return 0;
-+      case BUS_NOTIFY_DEL_DEVICE:
-+              /* Check if this our existing ISA device */
-+              if (pdev == isa_bridge_pcidev ||
-+                  (devnode && devnode == isa_bridge_devnode))
-+                      isa_bridge_remove();
-+              return 0;
-+      }
-+      return 0;
-+}
-+
-+static struct notifier_block isa_bridge_notifier = {
-+      .notifier_call = isa_bridge_notify
-+};
-+
-+/**
-+ * isa_bridge_init - register to be notified of ISA bridge addition/removal
-+ *
-+ */
-+static int __init isa_bridge_init(void)
-+{
-+      if (firmware_has_feature(FW_FEATURE_ISERIES))
-+              return 0;
-+      bus_register_notifier(&pci_bus_type, &isa_bridge_notifier);
-+      return 0;
-+}
-+arch_initcall(isa_bridge_init);
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/kgdb.c linux-2.6.22-590/arch/powerpc/kernel/kgdb.c
---- linux-2.6.22-570/arch/powerpc/kernel/kgdb.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/kernel/kgdb.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,499 @@
-+/*
-+ * arch/powerpc/kernel/kgdb.c
-+ *
-+ * PowerPC backend to the KGDB stub.
-+ *
-+ * Maintainer: Tom Rini <trini@kernel.crashing.org>
-+ *
-+ * Copied from arch/ppc/kernel/kgdb.c, updated for ppc64
-+ *
-+ * 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu)
-+ * Copyright (C) 2003 Timesys Corporation.
-+ * Copyright (C) 2004-2006 MontaVista Software, Inc.
-+ * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
-+ * PPC32 support restored by Vitaly Wool <vwool@ru.mvista.com> and
-+ * Sergei Shtylyov <sshtylyov@ru.mvista.com>
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program as licensed "as is" without any warranty of any
-+ * kind, whether express or implied.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/kgdb.h>
-+#include <linux/smp.h>
-+#include <linux/signal.h>
-+#include <linux/ptrace.h>
-+#include <asm/current.h>
-+#include <asm/ptrace.h>
-+#include <asm/processor.h>
-+#include <asm/machdep.h>
-+
-+/*
-+ * This table contains the mapping between PowerPC hardware trap types, and
-+ * signals, which are primarily what GDB understands.  GDB and the kernel
-+ * don't always agree on values, so we use constants taken from gdb-6.2.
-+ */
-+static struct hard_trap_info
-+{
-+      unsigned int tt;                /* Trap type code for powerpc */
-+      unsigned char signo;            /* Signal that we map this trap into */
-+} hard_trap_info[] = {
-+      { 0x0100, 0x02 /* SIGINT */  },         /* system reset */
-+      { 0x0200, 0x0b /* SIGSEGV */ },         /* machine check */
-+      { 0x0300, 0x0b /* SIGSEGV */ },         /* data access */
-+      { 0x0400, 0x0b /* SIGSEGV */ },         /* instruction access */
-+      { 0x0500, 0x02 /* SIGINT */  },         /* external interrupt */
-+      { 0x0600, 0x0a /* SIGBUS */  },         /* alignment */
-+      { 0x0700, 0x05 /* SIGTRAP */ },         /* program check */
-+      { 0x0800, 0x08 /* SIGFPE */  },         /* fp unavailable */
-+      { 0x0900, 0x0e /* SIGALRM */ },         /* decrementer */
-+      { 0x0c00, 0x14 /* SIGCHLD */ },         /* system call */
-+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
-+      { 0x2002, 0x05 /* SIGTRAP */ },         /* debug */
-+#if defined(CONFIG_FSL_BOOKE)
-+      { 0x2010, 0x08 /* SIGFPE */  },         /* spe unavailable */
-+      { 0x2020, 0x08 /* SIGFPE */  },         /* spe unavailable */
-+      { 0x2030, 0x08 /* SIGFPE */  },         /* spe fp data */
-+      { 0x2040, 0x08 /* SIGFPE */  },         /* spe fp data */
-+      { 0x2050, 0x08 /* SIGFPE */  },         /* spe fp round */
-+      { 0x2060, 0x0e /* SIGILL */  },         /* performace monitor */
-+      { 0x2900, 0x08 /* SIGFPE */  },         /* apu unavailable */
-+      { 0x3100, 0x0e /* SIGALRM */ },         /* fixed interval timer */
-+      { 0x3200, 0x02 /* SIGINT */  },         /* watchdog */
-+#else
-+      { 0x1000, 0x0e /* SIGALRM */ },         /* programmable interval timer */
-+      { 0x1010, 0x0e /* SIGALRM */ },         /* fixed interval timer */
-+      { 0x1020, 0x02 /* SIGINT */  },         /* watchdog */
-+      { 0x2010, 0x08 /* SIGFPE */  },         /* fp unavailable */
-+      { 0x2020, 0x08 /* SIGFPE */  },         /* ap unavailable */
-+#endif
-+#else
-+      { 0x0d00, 0x05 /* SIGTRAP */ },         /* single-step */
-+#if defined(CONFIG_8xx)
-+      { 0x1000, 0x04 /* SIGILL */  },         /* software emulation */
-+#else
-+      { 0x0f00, 0x04 /* SIGILL */  },         /* performance monitor */
-+      { 0x0f20, 0x08 /* SIGFPE */  },         /* altivec unavailable */
-+      { 0x1300, 0x05 /* SIGTRAP */ },         /* instruction address break */
-+#if defined(CONFIG_PPC64)
-+      { 0x1200, 0x05 /* SIGILL */  },         /* system error */
-+      { 0x1500, 0x04 /* SIGILL */  },         /* soft patch */
-+      { 0x1600, 0x04 /* SIGILL */  },         /* maintenance */
-+      { 0x1700, 0x08 /* SIGFPE */  },         /* altivec assist */
-+      { 0x1800, 0x04 /* SIGILL */  },         /* thermal */
-+#else
-+      { 0x1400, 0x02 /* SIGINT */  },         /* SMI */
-+      { 0x1600, 0x08 /* SIGFPE */  },         /* altivec assist */
-+      { 0x1700, 0x04 /* SIGILL */  },         /* TAU */
-+      { 0x2000, 0x05 /* SIGTRAP */ },         /* run mode */
-+#endif
-+#endif
-+#endif
-+      { 0x0000, 0x00 }                        /* Must be last */
-+};
-+
-+extern atomic_t cpu_doing_single_step;
-+
-+static int computeSignal(unsigned int tt)
-+{
-+      struct hard_trap_info *ht;
-+
-+      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
-+              if (ht->tt == tt)
-+                      return ht->signo;
-+
-+      return SIGHUP;          /* default for things we don't know about */
-+}
-+
-+static int kgdb_call_nmi_hook(struct pt_regs *regs)
-+{
-+      kgdb_nmihook(smp_processor_id(), regs);
-+      return 0;
-+}
-+
-+#ifdef CONFIG_SMP
-+void kgdb_roundup_cpus(unsigned long flags)
-+{
-+      smp_send_debugger_break(MSG_ALL_BUT_SELF);
-+}
-+#endif
-+
-+/* KGDB functions to use existing PowerPC64 hooks. */
-+static int kgdb_debugger(struct pt_regs *regs)
-+{
-+      return kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
-+}
-+
-+static int kgdb_breakpoint(struct pt_regs *regs)
-+{
-+      if (user_mode(regs))
-+              return 0;
-+
-+      kgdb_handle_exception(0, SIGTRAP, 0, regs);
-+
-+      if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
-+              regs->nip += 4;
-+
-+      return 1;
-+}
-+
-+static int kgdb_singlestep(struct pt_regs *regs)
-+{
-+      struct thread_info *thread_info, *exception_thread_info;
-+
-+      if (user_mode(regs))
-+              return 0;
-+
-+      /*
-+       * On Book E and perhaps other processsors, singlestep is handled on
-+       * the critical exception stack.  This causes current_thread_info()
-+       * to fail, since it it locates the thread_info by masking off
-+       * the low bits of the current stack pointer.  We work around
-+       * this issue by copying the thread_info from the kernel stack
-+       * before calling kgdb_handle_exception, and copying it back
-+       * afterwards.  On most processors the copy is avoided since
-+       * exception_thread_info == thread_info.
-+       */
-+      thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
-+      exception_thread_info = current_thread_info();
-+
-+      if (thread_info != exception_thread_info)
-+              memcpy(exception_thread_info, thread_info, sizeof *thread_info);
-+
-+      kgdb_handle_exception(0, SIGTRAP, 0, regs);
-+
-+      if (thread_info != exception_thread_info)
-+              memcpy(thread_info, exception_thread_info, sizeof *thread_info);
-+
-+      return 1;
-+}
-+
-+int kgdb_iabr_match(struct pt_regs *regs)
-+{
-+      if (user_mode(regs))
-+              return 0;
-+
-+      kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
-+      return 1;
-+}
-+
-+int kgdb_dabr_match(struct pt_regs *regs)
-+{
-+      if (user_mode(regs))
-+              return 0;
-+
-+      kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
-+      return 1;
-+}
-+
-+#define PACK64(ptr,src) do { *(ptr++) = (src); } while(0)
-+
-+#define PACK32(ptr,src) do {          \
-+      u32 *ptr32;                   \
-+      ptr32 = (u32 *)ptr;           \
-+      *(ptr32++) = (src);           \
-+      ptr = (unsigned long *)ptr32; \
-+      } while(0)
-+
-+
-+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-+{
-+      unsigned long *ptr = gdb_regs;
-+      int reg;
-+
-+      memset(gdb_regs, 0, NUMREGBYTES);
-+
-+      for (reg = 0; reg < 32; reg++)
-+              PACK64(ptr, regs->gpr[reg]);
-+
-+#ifdef CONFIG_FSL_BOOKE
-+#ifdef CONFIG_SPE
-+      for (reg = 0; reg < 32; reg++)
-+              PACK64(ptr, current->thread.evr[reg]);
-+#else
-+      ptr += 32;
-+#endif
-+#else
-+      /* fp registers not used by kernel, leave zero */
-+      ptr += 32 * 8 / sizeof(long);
-+#endif
-+
-+      PACK64(ptr, regs->nip);
-+      PACK64(ptr, regs->msr);
-+      PACK32(ptr, regs->ccr);
-+      PACK64(ptr, regs->link);
-+      PACK64(ptr, regs->ctr);
-+      PACK32(ptr, regs->xer);
-+
-+#if 0
-+      Following are in struct thread_struct, not struct pt_regs,
-+      ignoring for now since kernel does not use them.  Would it
-+      make sense to get them from the thread that kgdb is set to?
-+
-+      If this code is enabled, update the definition of NUMREGBYTES to
-+      include the vector registers and vector state registers.
-+
-+      PACK32(ptr, current->thread->fpscr);
-+
-+      /* vr registers not used by kernel, leave zero */
-+      ptr += 32 * 16 / sizeof(long);
-+
-+#ifdef CONFIG_ALTIVEC
-+      PACK32(ptr, current->thread->vscr);
-+      PACK32(ptr, current->thread->vrsave);
-+#else
-+      ptr += 2 * 4 / sizeof(long);
-+#endif
-+#else
-+#ifdef CONFIG_FSL_BOOKE
-+#ifdef CONFIG_SPE
-+      /* u64 acc */
-+      PACK32(ptr, current->thread.acc >> 32);
-+      PACK32(ptr, current->thread.acc & 0xffffffff);
-+      PACK64(ptr, current->thread.spefscr);
-+#else
-+      ptr += 2 + 1;
-+#endif
-+#else
-+      /* fpscr not used by kernel, leave zero */
-+      PACK32(ptr, 0);
-+#endif
-+#endif
-+
-+      BUG_ON((unsigned long)ptr >
-+             (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
-+}
-+
-+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
-+{
-+      struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
-+                                                STACK_FRAME_OVERHEAD);
-+      unsigned long *ptr = gdb_regs;
-+      int reg;
-+
-+      memset(gdb_regs, 0, NUMREGBYTES);
-+
-+      /* Regs GPR0-2 */
-+      for (reg = 0; reg < 3; reg++)
-+              PACK64(ptr, regs->gpr[reg]);
-+
-+      /* Regs GPR3-13 are caller saved, not in regs->gpr[] */
-+      ptr += 11;
-+
-+      /* Regs GPR14-31 */
-+      for (reg = 14; reg < 32; reg++)
-+              PACK64(ptr, regs->gpr[reg]);
-+
-+#ifdef CONFIG_FSL_BOOKE
-+#ifdef CONFIG_SPE
-+      for (reg = 0; reg < 32; reg++)
-+              PACK64(ptr, p->thread.evr[reg]);
-+#else
-+      ptr += 32;
-+#endif
-+#else
-+      /* fp registers not used by kernel, leave zero */
-+      ptr += 32 * 8 / sizeof(long);
-+#endif
-+
-+      PACK64(ptr, regs->nip);
-+      PACK64(ptr, regs->msr);
-+      PACK32(ptr, regs->ccr);
-+      PACK64(ptr, regs->link);
-+      PACK64(ptr, regs->ctr);
-+      PACK32(ptr, regs->xer);
-+
-+#if 0
-+      Following are in struct thread_struct, not struct pt_regs,
-+      ignoring for now since kernel does not use them.  Would it
-+      make sense to get them from the thread that kgdb is set to?
-+
-+      If this code is enabled, update the definition of NUMREGBYTES to
-+      include the vector registers and vector state registers.
-+
-+      PACK32(ptr, p->thread->fpscr);
-+
-+      /* vr registers not used by kernel, leave zero */
-+      ptr += 32 * 16 / sizeof(long);
-+
-+#ifdef CONFIG_ALTIVEC
-+      PACK32(ptr, p->thread->vscr);
-+      PACK32(ptr, p->thread->vrsave);
-+#else
-+      ptr += 2 * 4 / sizeof(long);
-+#endif
-+#else
-+#ifdef CONFIG_FSL_BOOKE
-+#ifdef CONFIG_SPE
-+      /* u64 acc */
-+      PACK32(ptr, p->thread.acc >> 32);
-+      PACK32(ptr, p->thread.acc & 0xffffffff);
-+      PACK64(ptr, p->thread.spefscr);
-+#else
-+      ptr += 2 + 1;
-+#endif
-+#else
-+      /* fpscr not used by kernel, leave zero */
-+      PACK32(ptr, 0);
-+#endif
-+#endif
-+
-+      BUG_ON((unsigned long)ptr >
-+             (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
-+}
-+
-+#define UNPACK64(dest,ptr) do { dest = *(ptr++); } while(0)
-+
-+#define UNPACK32(dest,ptr) do {       \
-+      u32 *ptr32;                   \
-+      ptr32 = (u32 *)ptr;           \
-+      dest = *(ptr32++);            \
-+      ptr = (unsigned long *)ptr32; \
-+      } while(0)
-+
-+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-+{
-+      unsigned long *ptr = gdb_regs;
-+      int reg;
-+#ifdef CONFIG_SPE
-+      union {
-+              u32 v32[2];
-+              u64 v64;
-+      } acc;
-+#endif
-+
-+      for (reg = 0; reg < 32; reg++)
-+              UNPACK64(regs->gpr[reg], ptr);
-+
-+#ifdef CONFIG_FSL_BOOKE
-+#ifdef CONFIG_SPE
-+      for (reg = 0; reg < 32; reg++)
-+              UNPACK64(current->thread.evr[reg], ptr);
-+#else
-+      ptr += 32;
-+#endif
-+#else
-+      /* fp registers not used by kernel, leave zero */
-+      ptr += 32 * 8 / sizeof(int);
-+#endif
-+
-+      UNPACK64(regs->nip, ptr);
-+      UNPACK64(regs->msr, ptr);
-+      UNPACK32(regs->ccr, ptr);
-+      UNPACK64(regs->link, ptr);
-+      UNPACK64(regs->ctr, ptr);
-+      UNPACK32(regs->xer, ptr);
-+
-+#if 0
-+      Following are in struct thread_struct, not struct pt_regs,
-+      ignoring for now since kernel does not use them.  Would it
-+      make sense to get them from the thread that kgdb is set to?
-+
-+      If this code is enabled, update the definition of NUMREGBYTES to
-+      include the vector registers and vector state registers.
-+
-+      /* fpscr, vscr, vrsave not used by kernel, leave unchanged */
-+
-+      UNPACK32(current->thread->fpscr, ptr);
-+
-+      /* vr registers not used by kernel, leave zero */
-+      ptr += 32 * 16 / sizeof(long);
-+
-+#ifdef CONFIG_ALTIVEC
-+      UNPACK32(current->thread->vscr, ptr);
-+      UNPACK32(current->thread->vrsave, ptr);
-+#else
-+      ptr += 2 * 4 / sizeof(long);
-+#endif
-+#else
-+#ifdef CONFIG_FSL_BOOKE
-+#ifdef CONFIG_SPE
-+      /* u64 acc */
-+      UNPACK32(acc.v32[0], ptr);
-+      UNPACK32(acc.v32[1], ptr);
-+      current->thread.acc = acc.v64;
-+      UNPACK64(current->thread.spefscr, ptr);
-+#else
-+      ptr += 2 + 1;
-+#endif
-+#endif
-+#endif
-+
-+      BUG_ON((unsigned long)ptr >
-+             (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
-+}
-+
-+/*
-+ * This function does PowerPC specific procesing for interfacing to gdb.
-+ */
-+int kgdb_arch_handle_exception(int vector, int signo, int err_code,
-+                             char *remcom_in_buffer, char *remcom_out_buffer,
-+                             struct pt_regs *linux_regs)
-+{
-+      char *ptr = &remcom_in_buffer[1];
-+      unsigned long addr;
-+
-+      switch (remcom_in_buffer[0]) {
-+              /*
-+               * sAA..AA   Step one instruction from AA..AA
-+               * This will return an error to gdb ..
-+               */
-+      case 's':
-+      case 'c':
-+              /* handle the optional parameter */
-+              if (kgdb_hex2long(&ptr, &addr))
-+                      linux_regs->nip = addr;
-+
-+              atomic_set(&cpu_doing_single_step, -1);
-+              /* set the trace bit if we're stepping */
-+              if (remcom_in_buffer[0] == 's') {
-+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
-+                      mtspr(SPRN_DBCR0,
-+                            mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
-+                      linux_regs->msr |= MSR_DE;
-+#else
-+                      linux_regs->msr |= MSR_SE;
-+#endif
-+                      debugger_step = 1;
-+                      if (kgdb_contthread)
-+                              atomic_set(&cpu_doing_single_step,
-+                                         smp_processor_id());
-+              }
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+/*
-+ * Global data
-+ */
-+struct kgdb_arch arch_kgdb_ops = {
-+      .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
-+};
-+
-+int kgdb_not_implemented(struct pt_regs *regs)
-+{
-+      return 0;
-+}
-+
-+int kgdb_arch_init(void)
-+{
-+#ifdef CONFIG_XMON
-+#error Both XMON and KGDB selected in .config.  Unselect one of them.
-+#endif
-+
-+      __debugger_ipi = kgdb_call_nmi_hook;
-+      __debugger = kgdb_debugger;
-+      __debugger_bpt = kgdb_breakpoint;
-+      __debugger_sstep = kgdb_singlestep;
-+      __debugger_iabr_match = kgdb_iabr_match;
-+      __debugger_dabr_match = kgdb_dabr_match;
-+      __debugger_fault_handler = kgdb_not_implemented;
-+
-+      return 0;
-+}
-+
-+arch_initcall(kgdb_arch_init);
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/kgdb_setjmp32.S linux-2.6.22-590/arch/powerpc/kernel/kgdb_setjmp32.S
---- linux-2.6.22-570/arch/powerpc/kernel/kgdb_setjmp32.S       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/kernel/kgdb_setjmp32.S       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,41 @@
-+/*
-+ * Copyright (C) 1996 Paul Mackerras
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program as licensed "as is" without any warranty of any
-+ * kind, whether express or implied.
-+ */
-+
-+#include <asm/processor.h>
-+#include <asm/ppc_asm.h>
-+
-+      .text
-+
-+/*
-+ * Save/restore state in case a memory access causes a fault.
-+ *
-+ * int kgdb_fault_setjmp(unsigned long *curr_context);
-+ * void kgdb_fault_longjmp(unsigned long *curr_context);
-+ */
-+
-+_GLOBAL(kgdb_fault_setjmp)
-+      mflr    r0
-+      stw     r0,0(r3)
-+      stw     r1,4(r3)
-+      stw     r2,8(r3)
-+      mfcr    r0
-+      stw     r0,12(r3)
-+      stmw    r13,16(r3)
-+      li      r3,0
-+      blr
-+
-+_GLOBAL(kgdb_fault_longjmp)
-+      lmw     r13,16(r3)
-+      lwz     r0,12(r3)
-+      mtcrf   0x38,r0
-+      lwz     r0,0(r3)
-+      lwz     r1,4(r3)
-+      lwz     r2,8(r3)
-+      mtlr    r0
-+      mr      r3,r1
-+      blr
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/kgdb_setjmp64.S linux-2.6.22-590/arch/powerpc/kernel/kgdb_setjmp64.S
---- linux-2.6.22-570/arch/powerpc/kernel/kgdb_setjmp64.S       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/kernel/kgdb_setjmp64.S       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,77 @@
-+/*
-+ * Copyright (C) 1996 Paul Mackerras
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program as licensed "as is" without any warranty of any
-+ * kind, whether express or implied.
-+ */
-+
-+#include <asm/processor.h>
-+#include <asm/ppc_asm.h>
-+
-+      .text
-+
-+/*
-+ * Save/restore state in case a memory access causes a fault.
-+ *
-+ * int kgdb_fault_setjmp(unsigned long *curr_context);
-+ * void kgdb_fault_longjmp(unsigned long *curr_context);
-+ */
-+
-+_GLOBAL(kgdb_fault_setjmp)
-+      mflr    r0
-+      std     r0,0(r3)
-+      std     r1,8(r3)
-+      std     r2,16(r3)
-+      mfcr    r0
-+      std     r0,24(r3)
-+      std     r13,32(r3)
-+      std     r14,40(r3)
-+      std     r15,48(r3)
-+      std     r16,56(r3)
-+      std     r17,64(r3)
-+      std     r18,72(r3)
-+      std     r19,80(r3)
-+      std     r20,88(r3)
-+      std     r21,96(r3)
-+      std     r22,104(r3)
-+      std     r23,112(r3)
-+      std     r24,120(r3)
-+      std     r25,128(r3)
-+      std     r26,136(r3)
-+      std     r27,144(r3)
-+      std     r28,152(r3)
-+      std     r29,160(r3)
-+      std     r30,168(r3)
-+      std     r31,176(r3)
-+      li      r3,0
-+      blr
-+
-+_GLOBAL(kgdb_fault_longjmp)
-+      ld      r13,32(r3)
-+      ld      r14,40(r3)
-+      ld      r15,48(r3)
-+      ld      r16,56(r3)
-+      ld      r17,64(r3)
-+      ld      r18,72(r3)
-+      ld      r19,80(r3)
-+      ld      r20,88(r3)
-+      ld      r21,96(r3)
-+      ld      r22,104(r3)
-+      ld      r23,112(r3)
-+      ld      r24,120(r3)
-+      ld      r25,128(r3)
-+      ld      r26,136(r3)
-+      ld      r27,144(r3)
-+      ld      r28,152(r3)
-+      ld      r29,160(r3)
-+      ld      r30,168(r3)
-+      ld      r31,176(r3)
-+      ld      r0,24(r3)
-+      mtcrf   0x38,r0
-+      ld      r0,0(r3)
-+      ld      r1,8(r3)
-+      ld      r2,16(r3)
-+      mtlr    r0
-+      mr      r3,r1
-+      blr
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/legacy_serial.c linux-2.6.22-590/arch/powerpc/kernel/legacy_serial.c
---- linux-2.6.22-570/arch/powerpc/kernel/legacy_serial.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/legacy_serial.c       2008-01-02 13:56:37.000000000 -0500
-@@ -11,6 +11,9 @@
- #include <asm/udbg.h>
- #include <asm/pci-bridge.h>
- #include <asm/ppc-pci.h>
-+#ifdef CONFIG_KGDB_8250
-+#include <linux/kgdb.h>
-+#endif
- #undef DEBUG
-@@ -487,6 +490,9 @@
-                       fixup_port_pio(i, np, port);
-               if ((port->iotype == UPIO_MEM) || (port->iotype == UPIO_TSI))
-                       fixup_port_mmio(i, np, port);
-+#ifdef CONFIG_KGDB_8250
-+              kgdb8250_add_platform_port(i, port);
-+#endif
-       }
-       DBG("Registering platform serial ports\n");
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/misc_32.S linux-2.6.22-590/arch/powerpc/kernel/misc_32.S
---- linux-2.6.22-570/arch/powerpc/kernel/misc_32.S     2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/kernel/misc_32.S     2008-01-02 13:56:37.000000000 -0500
-@@ -392,7 +392,7 @@
-       mtspr   SPRN_L1CSR0,r3
-       isync
-       blr
--END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
-+END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
-       mfspr   r3,SPRN_L1CSR1
-       ori     r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
-       mtspr   SPRN_L1CSR1,r3
-@@ -419,7 +419,7 @@
- _GLOBAL(__flush_icache_range)
- BEGIN_FTR_SECTION
-       blr                             /* for 601, do nothing */
--END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
-+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
-       li      r5,L1_CACHE_BYTES-1
-       andc    r3,r3,r5
-       subf    r4,r3,r4
-@@ -514,8 +514,8 @@
-  */
- _GLOBAL(__flush_dcache_icache)
- BEGIN_FTR_SECTION
--      blr                                     /* for 601, do nothing */
--END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
-+      blr
-+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
-       rlwinm  r3,r3,0,0,19                    /* Get page base address */
-       li      r4,4096/L1_CACHE_BYTES  /* Number of lines in a page */
-       mtctr   r4
-@@ -543,7 +543,7 @@
- _GLOBAL(__flush_dcache_icache_phys)
- BEGIN_FTR_SECTION
-       blr                                     /* for 601, do nothing */
--END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
-+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
-       mfmsr   r10
-       rlwinm  r0,r10,0,28,26                  /* clear DR */
-       mtmsr   r0
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/of_platform.c linux-2.6.22-590/arch/powerpc/kernel/of_platform.c
---- linux-2.6.22-570/arch/powerpc/kernel/of_platform.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/of_platform.c 2008-01-02 13:56:37.000000000 -0500
-@@ -427,14 +427,6 @@
-       /* Process "ranges" property */
-       pci_process_bridge_OF_ranges(phb, dev->node, 0);
--      /* Setup IO space. We use the non-dynamic version of that code here,
--       * which doesn't quite support unplugging. Next kernel release will
--       * have a better fix for this.
--       * Note also that we don't do ISA, this will also be fixed with a
--       * more massive rework.
--       */
--      pci_setup_phb_io(phb, pci_io_base == 0);
--
-       /* Init pci_dn data structures */
-       pci_devs_phb_init_dynamic(phb);
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/pci_64.c linux-2.6.22-590/arch/powerpc/kernel/pci_64.c
---- linux-2.6.22-570/arch/powerpc/kernel/pci_64.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/pci_64.c      2008-01-02 13:56:37.000000000 -0500
-@@ -11,7 +11,7 @@
-  *      2 of the License, or (at your option) any later version.
-  */
--#undef DEBUG
-+#define DEBUG
- #include <linux/kernel.h>
- #include <linux/pci.h>
-@@ -22,6 +22,7 @@
- #include <linux/list.h>
- #include <linux/syscalls.h>
- #include <linux/irq.h>
-+#include <linux/vmalloc.h>
- #include <asm/processor.h>
- #include <asm/io.h>
-@@ -41,35 +42,26 @@
- unsigned long pci_probe_only = 1;
- int pci_assign_all_buses = 0;
--static int pci_initial_scan_done;
- static void fixup_resource(struct resource *res, struct pci_dev *dev);
- static void do_bus_setup(struct pci_bus *bus);
--static void phbs_remap_io(void);
- /* pci_io_base -- the base address from which io bars are offsets.
-  * This is the lowest I/O base address (so bar values are always positive),
-  * and it *must* be the start of ISA space if an ISA bus exists because
-- * ISA drivers use hard coded offsets.  If no ISA bus exists a dummy
-- * page is mapped and isa_io_limit prevents access to it.
-+ * ISA drivers use hard coded offsets.  If no ISA bus exists nothing
-+ * is mapped on the first 64K of IO space
-  */
--unsigned long isa_io_base;    /* NULL if no ISA bus */
--EXPORT_SYMBOL(isa_io_base);
--unsigned long pci_io_base;
-+unsigned long pci_io_base = ISA_IO_BASE;
- EXPORT_SYMBOL(pci_io_base);
--void iSeries_pcibios_init(void);
--
- LIST_HEAD(hose_list);
- static struct dma_mapping_ops *pci_dma_ops;
-+/* XXX kill that some day ... */
- int global_phb_number;                /* Global phb counter */
--/* Cached ISA bridge dev. */
--struct pci_dev *ppc64_isabridge_dev = NULL;
--EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
--
- void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
- {
-       pci_dma_ops = dma_ops;
-@@ -100,7 +92,7 @@
-               return;
-       if (res->flags & IORESOURCE_IO)
--              offset = (unsigned long)hose->io_base_virt - pci_io_base;
-+              offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-       if (res->flags & IORESOURCE_MEM)
-               offset = hose->pci_mem_offset;
-@@ -119,7 +111,7 @@
-               return;
-       if (res->flags & IORESOURCE_IO)
--              offset = (unsigned long)hose->io_base_virt - pci_io_base;
-+              offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-       if (res->flags & IORESOURCE_MEM)
-               offset = hose->pci_mem_offset;
-@@ -156,7 +148,7 @@
-       if (res->flags & IORESOURCE_IO) {
-               unsigned long offset = (unsigned long)hose->io_base_virt -
--                                      pci_io_base;
-+                                      _IO_BASE;
-               /* Make sure we start at our min on all hoses */
-               if (start - offset < PCIBIOS_MIN_IO)
-                       start = PCIBIOS_MIN_IO + offset;
-@@ -535,10 +527,16 @@
-       bus->secondary = hose->first_busno;
-       hose->bus = bus;
-+      if (!firmware_has_feature(FW_FEATURE_ISERIES))
-+              pcibios_map_io_space(bus);
-+
-       bus->resource[0] = res = &hose->io_resource;
--      if (res->flags && request_resource(&ioport_resource, res))
-+      if (res->flags && request_resource(&ioport_resource, res)) {
-               printk(KERN_ERR "Failed to request PCI IO region "
-                      "on PCI domain %04x\n", hose->global_number);
-+              DBG("res->start = 0x%016lx, res->end = 0x%016lx\n",
-+                  res->start, res->end);
-+      }
-       for (i = 0; i < 3; ++i) {
-               res = &hose->mem_resources[i];
-@@ -596,17 +594,6 @@
-       if (ppc_md.pcibios_fixup)
-               ppc_md.pcibios_fixup();
--      /* Cache the location of the ISA bridge (if we have one) */
--      ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
--      if (ppc64_isabridge_dev != NULL)
--              printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
--
--      if (!firmware_has_feature(FW_FEATURE_ISERIES))
--              /* map in PCI I/O space */
--              phbs_remap_io();
--
--      pci_initial_scan_done = 1;
--
-       printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
-       return 0;
-@@ -711,7 +698,7 @@
- #endif
-               res_bit = IORESOURCE_MEM;
-       } else {
--              io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
-+              io_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-               *offset += io_offset;
-               res_bit = IORESOURCE_IO;
-       }
-@@ -881,76 +868,6 @@
-       device_create_file(&pdev->dev, &dev_attr_devspec);
- }
--#define ISA_SPACE_MASK 0x1
--#define ISA_SPACE_IO 0x1
--
--static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
--                                    unsigned long phb_io_base_phys,
--                                    void __iomem * phb_io_base_virt)
--{
--      /* Remove these asap */
--
--      struct pci_address {
--              u32 a_hi;
--              u32 a_mid;
--              u32 a_lo;
--      };
--
--      struct isa_address {
--              u32 a_hi;
--              u32 a_lo;
--      };
--
--      struct isa_range {
--              struct isa_address isa_addr;
--              struct pci_address pci_addr;
--              unsigned int size;
--      };
--
--      const struct isa_range *range;
--      unsigned long pci_addr;
--      unsigned int isa_addr;
--      unsigned int size;
--      int rlen = 0;
--
--      range = of_get_property(isa_node, "ranges", &rlen);
--      if (range == NULL || (rlen < sizeof(struct isa_range))) {
--              printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
--                     "mapping 64k\n");
--              __ioremap_explicit(phb_io_base_phys,
--                                 (unsigned long)phb_io_base_virt,
--                                 0x10000, _PAGE_NO_CACHE | _PAGE_GUARDED);
--              return; 
--      }
--      
--      /* From "ISA Binding to 1275"
--       * The ranges property is laid out as an array of elements,
--       * each of which comprises:
--       *   cells 0 - 1:       an ISA address
--       *   cells 2 - 4:       a PCI address 
--       *                      (size depending on dev->n_addr_cells)
--       *   cell 5:            the size of the range
--       */
--      if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) {
--              isa_addr = range->isa_addr.a_lo;
--              pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | 
--                      range->pci_addr.a_lo;
--
--              /* Assume these are both zero */
--              if ((pci_addr != 0) || (isa_addr != 0)) {
--                      printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
--                                      __FUNCTION__);
--                      return;
--              }
--              
--              size = PAGE_ALIGN(range->size);
--
--              __ioremap_explicit(phb_io_base_phys, 
--                                 (unsigned long) phb_io_base_virt, 
--                                 size, _PAGE_NO_CACHE | _PAGE_GUARDED);
--      }
--}
--
- void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
-                                           struct device_node *dev, int prim)
- {
-@@ -1045,155 +962,122 @@
-       }
- }
--void __devinit pci_setup_phb_io(struct pci_controller *hose, int primary)
--{
--      unsigned long size = hose->pci_io_size;
--      unsigned long io_virt_offset;
--      struct resource *res;
--      struct device_node *isa_dn;
--
--      if (size == 0)
--              return;
--
--      hose->io_base_virt = reserve_phb_iospace(size);
--      DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
--              hose->global_number, hose->io_base_phys,
--              (unsigned long) hose->io_base_virt);
--
--      if (primary) {
--              pci_io_base = (unsigned long)hose->io_base_virt;
--              isa_dn = of_find_node_by_type(NULL, "isa");
--              if (isa_dn) {
--                      isa_io_base = pci_io_base;
--                      pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys,
--                                              hose->io_base_virt);
--                      of_node_put(isa_dn);
--              }
--      }
--
--      io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
--      res = &hose->io_resource;
--      res->start += io_virt_offset;
--      res->end += io_virt_offset;
--
--      /* If this is called after the initial PCI scan, then we need to
--       * proceed to IO mappings now
--       */
--      if (pci_initial_scan_done)
--              __ioremap_explicit(hose->io_base_phys,
--                                 (unsigned long)hose->io_base_virt,
--                                 hose->pci_io_size,
--                                 _PAGE_NO_CACHE | _PAGE_GUARDED);
--}
-+#ifdef CONFIG_HOTPLUG
--void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose,
--                                      int primary)
-+int pcibios_unmap_io_space(struct pci_bus *bus)
- {
--      unsigned long size = hose->pci_io_size;
--      unsigned long io_virt_offset;
--      struct resource *res;
-+      struct pci_controller *hose;
--      if (size == 0)
--              return;
-+      WARN_ON(bus == NULL);
--      hose->io_base_virt = __ioremap(hose->io_base_phys, size,
--                                      _PAGE_NO_CACHE | _PAGE_GUARDED);
--      DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
--              hose->global_number, hose->io_base_phys,
--              (unsigned long) hose->io_base_virt);
--
--      if (primary)
--              pci_io_base = (unsigned long)hose->io_base_virt;
--
--      io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
--      res = &hose->io_resource;
--      res->start += io_virt_offset;
--      res->end += io_virt_offset;
--}
-+      /* If this is not a PHB, we only flush the hash table over
-+       * the area mapped by this bridge. We don't play with the PTE
-+       * mappings since we might have to deal with sub-page alignemnts
-+       * so flushing the hash table is the only sane way to make sure
-+       * that no hash entries are covering that removed bridge area
-+       * while still allowing other busses overlapping those pages
-+       */
-+      if (bus->self) {
-+              struct resource *res = bus->resource[0];
-+              DBG("IO unmapping for PCI-PCI bridge %s\n",
-+                  pci_name(bus->self));
--static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys,
--                              unsigned long *start_virt, unsigned long *size)
--{
--      struct pci_controller *hose = pci_bus_to_host(bus);
--      struct resource *res;
-+              __flush_hash_table_range(&init_mm, res->start + _IO_BASE,
-+                                       res->end - res->start + 1);
-+              return 0;
-+      }
--      if (bus->self)
--              res = bus->resource[0];
--      else
--              /* Root Bus */
--              res = &hose->io_resource;
-+      /* Get the host bridge */
-+      hose = pci_bus_to_host(bus);
--      if (res->end == 0 && res->start == 0)
--              return 1;
-+      /* Check if we have IOs allocated */
-+      if (hose->io_base_alloc == 0)
-+              return 0;
--      *start_virt = pci_io_base + res->start;
--      *start_phys = *start_virt + hose->io_base_phys
--              - (unsigned long) hose->io_base_virt;
-+      DBG("IO unmapping for PHB %s\n",
-+          ((struct device_node *)hose->arch_data)->full_name);
-+      DBG("  alloc=0x%p\n", hose->io_base_alloc);
--      if (res->end > res->start)
--              *size = res->end - res->start + 1;
--      else {
--              printk("%s(): unexpected region 0x%lx->0x%lx\n",
--                     __FUNCTION__, res->start, res->end);
--              return 1;
--      }
-+      /* This is a PHB, we fully unmap the IO area */
-+      vunmap(hose->io_base_alloc);
-       return 0;
- }
-+EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
--int unmap_bus_range(struct pci_bus *bus)
--{
--      unsigned long start_phys;
--      unsigned long start_virt;
--      unsigned long size;
-+#endif /* CONFIG_HOTPLUG */
--      if (!bus) {
--              printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
--              return 1;
--      }
-+int __devinit pcibios_map_io_space(struct pci_bus *bus)
-+{
-+      struct vm_struct *area;
-+      unsigned long phys_page;
-+      unsigned long size_page;
-+      unsigned long io_virt_offset;
-+      struct pci_controller *hose;
-       
--      if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
--              return 1;
--      if (__iounmap_explicit((void __iomem *) start_virt, size))
--              return 1;
-+      WARN_ON(bus == NULL);
-+      /* If this not a PHB, nothing to do, page tables still exist and
-+       * thus HPTEs will be faulted in when needed
-+       */
-+      if (bus->self) {
-+              DBG("IO mapping for PCI-PCI bridge %s\n",
-+                  pci_name(bus->self));
-+              DBG("  virt=0x%016lx...0x%016lx\n",
-+                  bus->resource[0]->start + _IO_BASE,
-+                  bus->resource[0]->end + _IO_BASE);
-       return 0;
--}
--EXPORT_SYMBOL(unmap_bus_range);
--
--int remap_bus_range(struct pci_bus *bus)
--{
--      unsigned long start_phys;
--      unsigned long start_virt;
--      unsigned long size;
--
--      if (!bus) {
--              printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
--              return 1;
-       }
-       
-+      /* Get the host bridge */
-+      hose = pci_bus_to_host(bus);
-+      phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE);
-+      size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE);
-       
--      if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
--              return 1;
--      if (start_phys == 0)
--              return 1;
--      printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
--      if (__ioremap_explicit(start_phys, start_virt, size,
--                             _PAGE_NO_CACHE | _PAGE_GUARDED))
--              return 1;
-+      /* Make sure IO area address is clear */
-+      hose->io_base_alloc = NULL;
-+      /* If there's no IO to map on that bus, get away too */
-+      if (hose->pci_io_size == 0 || hose->io_base_phys == 0)
-       return 0;
--}
--EXPORT_SYMBOL(remap_bus_range);
--static void phbs_remap_io(void)
--{
--      struct pci_controller *hose, *tmp;
-+      /* Let's allocate some IO space for that guy. We don't pass
-+       * VM_IOREMAP because we don't care about alignment tricks that
-+       * the core does in that case. Maybe we should due to stupid card
-+       * with incomplete address decoding but I'd rather not deal with
-+       * those outside of the reserved 64K legacy region.
-+       */
-+      area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END);
-+      if (area == NULL)
-+              return -ENOMEM;
-+      hose->io_base_alloc = area->addr;
-+      hose->io_base_virt = (void __iomem *)(area->addr +
-+                                            hose->io_base_phys - phys_page);
-+
-+      DBG("IO mapping for PHB %s\n",
-+          ((struct device_node *)hose->arch_data)->full_name);
-+      DBG("  phys=0x%016lx, virt=0x%p (alloc=0x%p)\n",
-+          hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
-+      DBG("  size=0x%016lx (alloc=0x%016lx)\n",
-+          hose->pci_io_size, size_page);
-+
-+      /* Establish the mapping */
-+      if (__ioremap_at(phys_page, area->addr, size_page,
-+                       _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL)
-+              return -ENOMEM;
-+
-+      /* Fixup hose IO resource */
-+      io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-+      hose->io_resource.start += io_virt_offset;
-+      hose->io_resource.end += io_virt_offset;
--      list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
--              remap_bus_range(hose->bus);
-+      DBG("  hose->io_resource=0x%016lx...0x%016lx\n",
-+          hose->io_resource.start, hose->io_resource.end);
-+
-+      return 0;
- }
-+EXPORT_SYMBOL_GPL(pcibios_map_io_space);
- static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
- {
-@@ -1201,8 +1085,7 @@
-       unsigned long offset;
-       if (res->flags & IORESOURCE_IO) {
--              offset = (unsigned long)hose->io_base_virt - pci_io_base;
--
-+              offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-               res->start += offset;
-               res->end += offset;
-       } else if (res->flags & IORESOURCE_MEM) {
-@@ -1217,9 +1100,20 @@
-       /* Update device resources.  */
-       int i;
--      for (i = 0; i < PCI_NUM_RESOURCES; i++)
--              if (dev->resource[i].flags)
--                      fixup_resource(&dev->resource[i], dev);
-+      DBG("%s: Fixup resources:\n", pci_name(dev));
-+      for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-+              struct resource *res = &dev->resource[i];
-+              if (!res->flags)
-+                      continue;
-+
-+              DBG("  0x%02x < %08lx:0x%016lx...0x%016lx\n",
-+                  i, res->flags, res->start, res->end);
-+
-+              fixup_resource(res, dev);
-+
-+              DBG("       > %08lx:0x%016lx...0x%016lx\n",
-+                  res->flags, res->start, res->end);
-+      }
- }
- EXPORT_SYMBOL(pcibios_fixup_device_resources);
-@@ -1360,7 +1254,7 @@
-               return;
-       if (rsrc->flags & IORESOURCE_IO)
--              offset = (unsigned long)hose->io_base_virt - pci_io_base;
-+              offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-       /* We pass a fully fixed up address to userland for MMIO instead of
-        * a BAR value because X is lame and expects to be able to use that
-@@ -1410,7 +1304,7 @@
-               if (address >= hose->io_base_phys &&
-                   address < (hose->io_base_phys + hose->pci_io_size)) {
-                       unsigned long base =
--                              (unsigned long)hose->io_base_virt - pci_io_base;
-+                              (unsigned long)hose->io_base_virt - _IO_BASE;
-                       return base + (address - hose->io_base_phys);
-               }
-       }
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/process.c linux-2.6.22-590/arch/powerpc/kernel/process.c
---- linux-2.6.22-570/arch/powerpc/kernel/process.c     2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/kernel/process.c     2008-01-02 13:56:37.000000000 -0500
-@@ -219,22 +219,26 @@
- }
- #endif /* CONFIG_SMP */
--#ifdef CONFIG_PPC_MERGE               /* XXX for now */
- int set_dabr(unsigned long dabr)
- {
-+#ifdef CONFIG_PPC_MERGE               /* XXX for now */
-       if (ppc_md.set_dabr)
-               return ppc_md.set_dabr(dabr);
-+#endif
-+      /* XXX should we have a CPU_FTR_HAS_DABR ? */
-+#if defined(CONFIG_PPC64) || defined(CONFIG_6xx)
-       mtspr(SPRN_DABR, dabr);
-+#endif
-       return 0;
- }
--#endif
- #ifdef CONFIG_PPC64
- DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
--static DEFINE_PER_CPU(unsigned long, current_dabr);
- #endif
-+static DEFINE_PER_CPU(unsigned long, current_dabr);
-+
- struct task_struct *__switch_to(struct task_struct *prev,
-       struct task_struct *new)
- {
-@@ -299,12 +303,10 @@
- #endif /* CONFIG_SMP */
--#ifdef CONFIG_PPC64   /* for now */
-       if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
-               set_dabr(new->thread.dabr);
-               __get_cpu_var(current_dabr) = new->thread.dabr;
-       }
--#endif /* CONFIG_PPC64 */
-       new_thread = &new->thread;
-       old_thread = &current->thread;
-@@ -474,12 +476,10 @@
-       discard_lazy_cpu_state();
--#ifdef CONFIG_PPC64   /* for now */
-       if (current->thread.dabr) {
-               current->thread.dabr = 0;
-               set_dabr(0);
-       }
--#endif
- }
- void
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/prom_init.c linux-2.6.22-590/arch/powerpc/kernel/prom_init.c
---- linux-2.6.22-570/arch/powerpc/kernel/prom_init.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/prom_init.c   2008-01-02 13:56:37.000000000 -0500
-@@ -635,6 +635,7 @@
- /* ibm,dynamic-reconfiguration-memory property supported */
- #define OV5_DRCONF_MEMORY     0x20
- #define OV5_LARGE_PAGES               0x10    /* large pages supported */
-+#define OV5_DONATE_DEDICATE_CPU 0x02  /* donate dedicated CPU support */
- /* PCIe/MSI support.  Without MSI full PCIe is not supported */
- #ifdef CONFIG_PCI_MSI
- #define OV5_MSI                       0x01    /* PCIe/MSI support */
-@@ -685,7 +686,8 @@
-       /* option vector 5: PAPR/OF options */
-       3 - 2,                          /* length */
-       0,                              /* don't ignore, don't halt */
--      OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI,
-+      OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
-+      OV5_DONATE_DEDICATE_CPU | OV5_MSI,
- };
- /* Old method - ELF header with PT_NOTE sections */
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/ptrace-common.h linux-2.6.22-590/arch/powerpc/kernel/ptrace-common.h
---- linux-2.6.22-570/arch/powerpc/kernel/ptrace-common.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/ptrace-common.h       1969-12-31 19:00:00.000000000 -0500
-@@ -1,161 +0,0 @@
--/*
-- *    Copyright (c) 2002 Stephen Rothwell, IBM Coproration
-- *    Extracted from ptrace.c and ptrace32.c
-- *
-- * This file is subject to the terms and conditions of the GNU General
-- * Public License.  See the file README.legal in the main directory of
-- * this archive for more details.
-- */
--
--#ifndef _PPC64_PTRACE_COMMON_H
--#define _PPC64_PTRACE_COMMON_H
--
--#include <asm/system.h>
--
--/*
-- * Set of msr bits that gdb can change on behalf of a process.
-- */
--#define MSR_DEBUGCHANGE       (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
--
--/*
-- * Get contents of register REGNO in task TASK.
-- */
--static inline unsigned long get_reg(struct task_struct *task, int regno)
--{
--      unsigned long tmp = 0;
--
--      /*
--       * Put the correct FP bits in, they might be wrong as a result
--       * of our lazy FP restore.
--       */
--      if (regno == PT_MSR) {
--              tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
--              tmp |= task->thread.fpexc_mode;
--      } else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
--              tmp = ((unsigned long *)task->thread.regs)[regno];
--      }
--
--      return tmp;
--}
--
--/*
-- * Write contents of register REGNO in task TASK.
-- */
--static inline int put_reg(struct task_struct *task, int regno,
--                        unsigned long data)
--{
--      if (regno < PT_SOFTE) {
--              if (regno == PT_MSR)
--                      data = (data & MSR_DEBUGCHANGE)
--                              | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
--              ((unsigned long *)task->thread.regs)[regno] = data;
--              return 0;
--      }
--      return -EIO;
--}
--
--static inline void set_single_step(struct task_struct *task)
--{
--      struct pt_regs *regs = task->thread.regs;
--      if (regs != NULL)
--              regs->msr |= MSR_SE;
--      set_tsk_thread_flag(task, TIF_SINGLESTEP);
--}
--
--static inline void clear_single_step(struct task_struct *task)
--{
--      struct pt_regs *regs = task->thread.regs;
--      if (regs != NULL)
--              regs->msr &= ~MSR_SE;
--      clear_tsk_thread_flag(task, TIF_SINGLESTEP);
--}
--
--#ifdef CONFIG_ALTIVEC
--/*
-- * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
-- * The transfer totals 34 quadword.  Quadwords 0-31 contain the
-- * corresponding vector registers.  Quadword 32 contains the vscr as the
-- * last word (offset 12) within that quadword.  Quadword 33 contains the
-- * vrsave as the first word (offset 0) within the quadword.
-- *
-- * This definition of the VMX state is compatible with the current PPC32
-- * ptrace interface.  This allows signal handling and ptrace to use the
-- * same structures.  This also simplifies the implementation of a bi-arch
-- * (combined (32- and 64-bit) gdb.
-- */
--
--/*
-- * Get contents of AltiVec register state in task TASK
-- */
--static inline int get_vrregs(unsigned long __user *data,
--                           struct task_struct *task)
--{
--      unsigned long regsize;
--
--      /* copy AltiVec registers VR[0] .. VR[31] */
--      regsize = 32 * sizeof(vector128);
--      if (copy_to_user(data, task->thread.vr, regsize))
--              return -EFAULT;
--      data += (regsize / sizeof(unsigned long));
--
--      /* copy VSCR */
--      regsize = 1 * sizeof(vector128);
--      if (copy_to_user(data, &task->thread.vscr, regsize))
--              return -EFAULT;
--      data += (regsize / sizeof(unsigned long));
--
--      /* copy VRSAVE */
--      if (put_user(task->thread.vrsave, (u32 __user *)data))
--              return -EFAULT;
--
--      return 0;
--}
--
--/*
-- * Write contents of AltiVec register state into task TASK.
-- */
--static inline int set_vrregs(struct task_struct *task,
--                           unsigned long __user *data)
--{
--      unsigned long regsize;
--
--      /* copy AltiVec registers VR[0] .. VR[31] */
--      regsize = 32 * sizeof(vector128);
--      if (copy_from_user(task->thread.vr, data, regsize))
--              return -EFAULT;
--      data += (regsize / sizeof(unsigned long));
--
--      /* copy VSCR */
--      regsize = 1 * sizeof(vector128);
--      if (copy_from_user(&task->thread.vscr, data, regsize))
--              return -EFAULT;
--      data += (regsize / sizeof(unsigned long));
--
--      /* copy VRSAVE */
--      if (get_user(task->thread.vrsave, (u32 __user *)data))
--              return -EFAULT;
--
--      return 0;
--}
--#endif
--
--static inline int ptrace_set_debugreg(struct task_struct *task,
--                                    unsigned long addr, unsigned long data)
--{
--      /* We only support one DABR and no IABRS at the moment */
--      if (addr > 0)
--              return -EINVAL;
--
--      /* The bottom 3 bits are flags */
--      if ((data & ~0x7UL) >= TASK_SIZE)
--              return -EIO;
--
--      /* Ensure translation is on */
--      if (data && !(data & DABR_TRANSLATION))
--              return -EIO;
--
--      task->thread.dabr = data;
--      return 0;
--}
--
--#endif /* _PPC64_PTRACE_COMMON_H */
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/ptrace.c linux-2.6.22-590/arch/powerpc/kernel/ptrace.c
---- linux-2.6.22-570/arch/powerpc/kernel/ptrace.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/ptrace.c      2008-01-02 13:56:37.000000000 -0500
-@@ -35,11 +35,11 @@
- #include <asm/pgtable.h>
- #include <asm/system.h>
--#ifdef CONFIG_PPC64
--#include "ptrace-common.h"
--#endif
-+/*
-+ * does not yet catch signals sent when the child dies.
-+ * in exit.c or in signal.c.
-+ */
--#ifdef CONFIG_PPC32
- /*
-  * Set of msr bits that gdb can change on behalf of a process.
-  */
-@@ -48,65 +48,117 @@
- #else
- #define MSR_DEBUGCHANGE       (MSR_SE | MSR_BE)
- #endif
--#endif /* CONFIG_PPC32 */
- /*
-- * does not yet catch signals sent when the child dies.
-- * in exit.c or in signal.c.
-+ * Max register writeable via put_reg
-  */
--
- #ifdef CONFIG_PPC32
-+#define PT_MAX_PUT_REG        PT_MQ
-+#else
-+#define PT_MAX_PUT_REG        PT_CCR
-+#endif
-+
- /*
-  * Get contents of register REGNO in task TASK.
-  */
--static inline unsigned long get_reg(struct task_struct *task, int regno)
-+unsigned long ptrace_get_reg(struct task_struct *task, int regno)
- {
--      if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)
--          && task->thread.regs != NULL)
-+      unsigned long tmp = 0;
-+
-+      if (task->thread.regs == NULL)
-+              return -EIO;
-+
-+      if (regno == PT_MSR) {
-+              tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
-+              return tmp | task->thread.fpexc_mode;
-+      }
-+
-+      if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
-               return ((unsigned long *)task->thread.regs)[regno];
--      return (0);
-+
-+      return -EIO;
- }
- /*
-  * Write contents of register REGNO in task TASK.
-  */
--static inline int put_reg(struct task_struct *task, int regno,
--                        unsigned long data)
-+int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
- {
--      if (regno <= PT_MQ && task->thread.regs != NULL) {
-+      if (task->thread.regs == NULL)
-+              return -EIO;
-+
-+      if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) {
-               if (regno == PT_MSR)
-                       data = (data & MSR_DEBUGCHANGE)
-                               | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
-+              /* We prevent mucking around with the reserved area of trap
-+               * which are used internally by the kernel
-+               */
-+              if (regno == PT_TRAP)
-+                      data &= 0xfff0;
-               ((unsigned long *)task->thread.regs)[regno] = data;
-               return 0;
-       }
-       return -EIO;
- }
-+
-+static int get_fpregs(void __user *data, struct task_struct *task,
-+                    int has_fpscr)
-+{
-+      unsigned int count = has_fpscr ? 33 : 32;
-+
-+      if (copy_to_user(data, task->thread.fpr, count * sizeof(double)))
-+              return -EFAULT;
-+      return 0;
-+}
-+
-+static int set_fpregs(void __user *data, struct task_struct *task,
-+                    int has_fpscr)
-+{
-+      unsigned int count = has_fpscr ? 33 : 32;
-+
-+      if (copy_from_user(task->thread.fpr, data, count * sizeof(double)))
-+              return -EFAULT;
-+      return 0;
-+}
-+
-+
- #ifdef CONFIG_ALTIVEC
- /*
-+ * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
-+ * The transfer totals 34 quadword.  Quadwords 0-31 contain the
-+ * corresponding vector registers.  Quadword 32 contains the vscr as the
-+ * last word (offset 12) within that quadword.  Quadword 33 contains the
-+ * vrsave as the first word (offset 0) within the quadword.
-+ *
-+ * This definition of the VMX state is compatible with the current PPC32
-+ * ptrace interface.  This allows signal handling and ptrace to use the
-+ * same structures.  This also simplifies the implementation of a bi-arch
-+ * (combined (32- and 64-bit) gdb.
-+ */
-+
-+/*
-  * Get contents of AltiVec register state in task TASK
-  */
--static inline int get_vrregs(unsigned long __user *data, struct task_struct *task)
-+static int get_vrregs(unsigned long __user *data, struct task_struct *task)
- {
--      int i, j;
--
--      if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long)))
--              return -EFAULT;
-+      unsigned long regsize;
-       /* copy AltiVec registers VR[0] .. VR[31] */
--      for (i = 0; i < 32; i++)
--              for (j = 0; j < 4; j++, data++)
--                      if (__put_user(task->thread.vr[i].u[j], data))
-+      regsize = 32 * sizeof(vector128);
-+      if (copy_to_user(data, task->thread.vr, regsize))
-                               return -EFAULT;
-+      data += (regsize / sizeof(unsigned long));
-       /* copy VSCR */
--      for (i = 0; i < 4; i++, data++)
--              if (__put_user(task->thread.vscr.u[i], data))
-+      regsize = 1 * sizeof(vector128);
-+      if (copy_to_user(data, &task->thread.vscr, regsize))
-                       return -EFAULT;
-+      data += (regsize / sizeof(unsigned long));
-         /* copy VRSAVE */
--      if (__put_user(task->thread.vrsave, data))
-+      if (put_user(task->thread.vrsave, (u32 __user *)data))
-               return -EFAULT;
-       return 0;
-@@ -115,31 +167,29 @@
- /*
-  * Write contents of AltiVec register state into task TASK.
-  */
--static inline int set_vrregs(struct task_struct *task, unsigned long __user *data)
-+static int set_vrregs(struct task_struct *task, unsigned long __user *data)
- {
--      int i, j;
--
--      if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long)))
--              return -EFAULT;
-+      unsigned long regsize;
-       /* copy AltiVec registers VR[0] .. VR[31] */
--      for (i = 0; i < 32; i++)
--              for (j = 0; j < 4; j++, data++)
--                      if (__get_user(task->thread.vr[i].u[j], data))
-+      regsize = 32 * sizeof(vector128);
-+      if (copy_from_user(task->thread.vr, data, regsize))
-                               return -EFAULT;
-+      data += (regsize / sizeof(unsigned long));
-       /* copy VSCR */
--      for (i = 0; i < 4; i++, data++)
--              if (__get_user(task->thread.vscr.u[i], data))
-+      regsize = 1 * sizeof(vector128);
-+      if (copy_from_user(&task->thread.vscr, data, regsize))
-                       return -EFAULT;
-+      data += (regsize / sizeof(unsigned long));
-       /* copy VRSAVE */
--      if (__get_user(task->thread.vrsave, data))
-+      if (get_user(task->thread.vrsave, (u32 __user *)data))
-               return -EFAULT;
-       return 0;
- }
--#endif
-+#endif /* CONFIG_ALTIVEC */
- #ifdef CONFIG_SPE
-@@ -156,7 +206,7 @@
- /*
-  * Get contents of SPE register state in task TASK.
-  */
--static inline int get_evrregs(unsigned long *data, struct task_struct *task)
-+static int get_evrregs(unsigned long *data, struct task_struct *task)
- {
-       int i;
-@@ -182,7 +232,7 @@
- /*
-  * Write contents of SPE register state into task TASK.
-  */
--static inline int set_evrregs(struct task_struct *task, unsigned long *data)
-+static int set_evrregs(struct task_struct *task, unsigned long *data)
- {
-       int i;
-@@ -205,8 +255,8 @@
- }
- #endif /* CONFIG_SPE */
--static inline void
--set_single_step(struct task_struct *task)
-+
-+static void set_single_step(struct task_struct *task)
- {
-       struct pt_regs *regs = task->thread.regs;
-@@ -221,8 +271,7 @@
-       set_tsk_thread_flag(task, TIF_SINGLESTEP);
- }
--static inline void
--clear_single_step(struct task_struct *task)
-+static void clear_single_step(struct task_struct *task)
- {
-       struct pt_regs *regs = task->thread.regs;
-@@ -236,7 +285,25 @@
-       }
-       clear_tsk_thread_flag(task, TIF_SINGLESTEP);
- }
--#endif /* CONFIG_PPC32 */
-+
-+static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
-+                             unsigned long data)
-+{
-+      /* We only support one DABR and no IABRS at the moment */
-+      if (addr > 0)
-+              return -EINVAL;
-+
-+      /* The bottom 3 bits are flags */
-+      if ((data & ~0x7UL) >= TASK_SIZE)
-+              return -EIO;
-+
-+      /* Ensure translation is on */
-+      if (data && !(data & DABR_TRANSLATION))
-+              return -EIO;
-+
-+      task->thread.dabr = data;
-+      return 0;
-+}
- /*
-  * Called by kernel/ptrace.c when detaching..
-@@ -249,6 +316,62 @@
-       clear_single_step(child);
- }
-+/*
-+ * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
-+ * we mark them as obsolete now, they will be removed in a future version
-+ */
-+static long arch_ptrace_old(struct task_struct *child, long request, long addr,
-+                          long data)
-+{
-+      int ret = -EPERM;
-+
-+      switch(request) {
-+      case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
-+              int i;
-+              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-+              unsigned long __user *tmp = (unsigned long __user *)addr;
-+
-+              for (i = 0; i < 32; i++) {
-+                      ret = put_user(*reg, tmp);
-+                      if (ret)
-+                              break;
-+                      reg++;
-+                      tmp++;
-+              }
-+              break;
-+      }
-+
-+      case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
-+              int i;
-+              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-+              unsigned long __user *tmp = (unsigned long __user *)addr;
-+
-+              for (i = 0; i < 32; i++) {
-+                      ret = get_user(*reg, tmp);
-+                      if (ret)
-+                              break;
-+                      reg++;
-+                      tmp++;
-+              }
-+              break;
-+      }
-+
-+      case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
-+              flush_fp_to_thread(child);
-+              ret = get_fpregs((void __user *)addr, child, 0);
-+              break;
-+      }
-+
-+      case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
-+              flush_fp_to_thread(child);
-+              ret = set_fpregs((void __user *)addr, child, 0);
-+              break;
-+      }
-+
-+      }
-+      return ret;
-+}
-+
- long arch_ptrace(struct task_struct *child, long request, long addr, long data)
- {
-       int ret = -EPERM;
-@@ -284,11 +407,9 @@
- #endif
-                       break;
--#ifdef CONFIG_PPC32
-               CHECK_FULL_REGS(child->thread.regs);
--#endif
-               if (index < PT_FPR0) {
--                      tmp = get_reg(child, (int) index);
-+                      tmp = ptrace_get_reg(child, (int) index);
-               } else {
-                       flush_fp_to_thread(child);
-                       tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
-@@ -323,13 +444,9 @@
- #endif
-                       break;
--#ifdef CONFIG_PPC32
-               CHECK_FULL_REGS(child->thread.regs);
--#endif
--              if (index == PT_ORIG_R3)
--                      break;
-               if (index < PT_FPR0) {
--                      ret = put_reg(child, index, data);
-+                      ret = ptrace_put_reg(child, index, data);
-               } else {
-                       flush_fp_to_thread(child);
-                       ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
-@@ -384,7 +501,6 @@
-               break;
-       }
--#ifdef CONFIG_PPC64
-       case PTRACE_GET_DEBUGREG: {
-               ret = -EINVAL;
-               /* We only support one DABR and no IABRS at the moment */
-@@ -398,73 +514,61 @@
-       case PTRACE_SET_DEBUGREG:
-               ret = ptrace_set_debugreg(child, addr, data);
-               break;
--#endif
-       case PTRACE_DETACH:
-               ret = ptrace_detach(child, data);
-               break;
--      case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
--              int i;
--              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
--              unsigned long __user *tmp = (unsigned long __user *)addr;
--
--              for (i = 0; i < 32; i++) {
--                      ret = put_user(*reg, tmp);
--                      if (ret)
-+#ifdef CONFIG_PPC64
-+      case PTRACE_GETREGS64:
-+#endif
-+      case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
-+              int ui;
-+              if (!access_ok(VERIFY_WRITE, (void __user *)data,
-+                             sizeof(struct pt_regs))) {
-+                      ret = -EIO;
-                               break;
--                      reg++;
--                      tmp++;
-               }
--              break;
-+              ret = 0;
-+              for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
-+                      ret |= __put_user(ptrace_get_reg(child, ui),
-+                                        (unsigned long __user *) data);
-+                      data += sizeof(long);
-       }
--
--      case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
--              int i;
--              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
--              unsigned long __user *tmp = (unsigned long __user *)addr;
--
--              for (i = 0; i < 32; i++) {
--                      ret = get_user(*reg, tmp);
--                      if (ret)
-                               break;
--                      reg++;
--                      tmp++;
-               }
-+
-+#ifdef CONFIG_PPC64
-+      case PTRACE_SETREGS64:
-+#endif
-+      case PTRACE_SETREGS: { /* Set all gp regs in the child. */
-+              unsigned long tmp;
-+              int ui;
-+              if (!access_ok(VERIFY_READ, (void __user *)data,
-+                             sizeof(struct pt_regs))) {
-+                      ret = -EIO;
-               break;
-       }
--
--      case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
--              int i;
--              unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
--              unsigned long __user *tmp = (unsigned long __user *)addr;
--
--              flush_fp_to_thread(child);
--
--              for (i = 0; i < 32; i++) {
--                      ret = put_user(*reg, tmp);
-+              ret = 0;
-+              for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
-+                      ret = __get_user(tmp, (unsigned long __user *) data);
-                       if (ret)
-                               break;
--                      reg++;
--                      tmp++;
-+                      ptrace_put_reg(child, ui, tmp);
-+                      data += sizeof(long);
-               }
-               break;
-       }
--      case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
--              int i;
--              unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
--              unsigned long __user *tmp = (unsigned long __user *)addr;
--
-+      case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */
-               flush_fp_to_thread(child);
--
--              for (i = 0; i < 32; i++) {
--                      ret = get_user(*reg, tmp);
--                      if (ret)
-+              ret = get_fpregs((void __user *)data, child, 1);
-                               break;
--                      reg++;
--                      tmp++;
-               }
-+
-+      case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */
-+              flush_fp_to_thread(child);
-+              ret = set_fpregs((void __user *)data, child, 1);
-               break;
-       }
-@@ -499,11 +603,18 @@
-               break;
- #endif
-+      /* Old reverse args ptrace callss */
-+      case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
-+      case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
-+      case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
-+      case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */
-+              ret = arch_ptrace_old(child, request, addr, data);
-+              break;
-+
-       default:
-               ret = ptrace_request(child, request, addr, data);
-               break;
-       }
--
-       return ret;
- }
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/ptrace32.c linux-2.6.22-590/arch/powerpc/kernel/ptrace32.c
---- linux-2.6.22-570/arch/powerpc/kernel/ptrace32.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/ptrace32.c    2008-01-02 13:56:37.000000000 -0500
-@@ -33,13 +33,55 @@
- #include <asm/pgtable.h>
- #include <asm/system.h>
--#include "ptrace-common.h"
--
- /*
-  * does not yet catch signals sent when the child dies.
-  * in exit.c or in signal.c.
-  */
-+/*
-+ * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
-+ * we mark them as obsolete now, they will be removed in a future version
-+ */
-+static long compat_ptrace_old(struct task_struct *child, long request,
-+                            long addr, long data)
-+{
-+      int ret = -EPERM;
-+
-+      switch(request) {
-+      case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
-+              int i;
-+              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-+              unsigned int __user *tmp = (unsigned int __user *)addr;
-+
-+              for (i = 0; i < 32; i++) {
-+                      ret = put_user(*reg, tmp);
-+                      if (ret)
-+                              break;
-+                      reg++;
-+                      tmp++;
-+              }
-+              break;
-+      }
-+
-+      case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
-+              int i;
-+              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-+              unsigned int __user *tmp = (unsigned int __user *)addr;
-+
-+              for (i = 0; i < 32; i++) {
-+                      ret = get_user(*reg, tmp);
-+                      if (ret)
-+                              break;
-+                      reg++;
-+                      tmp++;
-+              }
-+              break;
-+      }
-+
-+      }
-+      return ret;
-+}
-+
- long compat_sys_ptrace(int request, int pid, unsigned long addr,
-                      unsigned long data)
- {
-@@ -123,7 +165,7 @@
-                       break;
-               if (index < PT_FPR0) {
--                      tmp = get_reg(child, index);
-+                      tmp = ptrace_get_reg(child, index);
-               } else {
-                       flush_fp_to_thread(child);
-                       /*
-@@ -162,7 +204,9 @@
-               else
-                       part = 0;  /* want the 1st half of the register (left-most). */
--              /* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */
-+              /* Validate the input - check to see if address is on the wrong boundary
-+               * or beyond the end of the user area
-+               */
-               if ((addr & 3) || numReg > PT_FPSCR)
-                       break;
-@@ -170,7 +214,7 @@
-                       flush_fp_to_thread(child);
-                       tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
-               } else { /* register within PT_REGS struct */
--                      tmp = get_reg(child, numReg);
-+                      tmp = ptrace_get_reg(child, numReg);
-               } 
-               reg32bits = ((u32*)&tmp)[part];
-               ret = put_user(reg32bits, (u32 __user *)data);
-@@ -226,10 +270,8 @@
-               if ((addr & 3) || (index > PT_FPSCR32))
-                       break;
--              if (index == PT_ORIG_R3)
--                      break;
-               if (index < PT_FPR0) {
--                      ret = put_reg(child, index, data);
-+                      ret = ptrace_put_reg(child, index, data);
-               } else {
-                       flush_fp_to_thread(child);
-                       /*
-@@ -258,70 +300,25 @@
-               /* Determine which register the user wants */
-               index = (u64)addr >> 2;
-               numReg = index / 2;
-+
-               /*
-                * Validate the input - check to see if address is on the
-                * wrong boundary or beyond the end of the user area
-                */
-               if ((addr & 3) || (numReg > PT_FPSCR))
-                       break;
--              /* Insure it is a register we let them change */
--              if ((numReg == PT_ORIG_R3)
--                              || ((numReg > PT_CCR) && (numReg < PT_FPR0)))
--                      break;
--              if (numReg >= PT_FPR0) {
--                      flush_fp_to_thread(child);
--              }
--              if (numReg == PT_MSR)
--                      data = (data & MSR_DEBUGCHANGE)
--                              | (child->thread.regs->msr & ~MSR_DEBUGCHANGE);
--              ((u32*)child->thread.regs)[index] = data;
--              ret = 0;
--              break;
--      }
--
--      case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
--      case PTRACE_CONT: { /* restart after signal. */
--              ret = -EIO;
--              if (!valid_signal(data))
--                      break;
--              if (request == PTRACE_SYSCALL)
--                      set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-+              if (numReg < PT_FPR0) {
-+                      unsigned long freg = ptrace_get_reg(child, numReg);
-+                      if (index % 2)
-+                              freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
-               else
--                      clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
--              child->exit_code = data;
--              /* make sure the single step bit is not set. */
--              clear_single_step(child);
--              wake_up_process(child);
--              ret = 0;
--              break;
--      }
--
--      /*
--       * make the child exit.  Best I can do is send it a sigkill.
--       * perhaps it should be put in the status that it wants to
--       * exit.
--       */
--      case PTRACE_KILL: {
-+                              freg = (freg & 0xfffffffful) | (data << 32);
-+                      ret = ptrace_put_reg(child, numReg, freg);
-+              } else {
-+                      flush_fp_to_thread(child);
-+                      ((unsigned int *)child->thread.regs)[index] = data;
-               ret = 0;
--              if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
--                      break;
--              child->exit_code = SIGKILL;
--              /* make sure the single step bit is not set. */
--              clear_single_step(child);
--              wake_up_process(child);
--              break;
-       }
--
--      case PTRACE_SINGLESTEP: {  /* set the trap flag. */
--              ret = -EIO;
--              if (!valid_signal(data))
--                      break;
--              clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
--              set_single_step(child);
--              child->exit_code = data;
--              /* give it a chance to run. */
--              wake_up_process(child);
--              ret = 0;
-               break;
-       }
-@@ -334,95 +331,67 @@
-               break;
-       }
--      case PTRACE_SET_DEBUGREG:
--              ret = ptrace_set_debugreg(child, addr, data);
--              break;
--
--      case PTRACE_DETACH:
--              ret = ptrace_detach(child, data);
-+      case PTRACE_GETEVENTMSG:
-+              ret = put_user(child->ptrace_message, (unsigned int __user *) data);
-               break;
--      case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
--              int i;
--              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
--              unsigned int __user *tmp = (unsigned int __user *)addr;
--
--              for (i = 0; i < 32; i++) {
--                      ret = put_user(*reg, tmp);
--                      if (ret)
--                              break;
--                      reg++;
--                      tmp++;
--              }
-+      case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
-+              int ui;
-+              if (!access_ok(VERIFY_WRITE, (void __user *)data,
-+                             PT_REGS_COUNT * sizeof(int))) {
-+                      ret = -EIO;
-               break;
-       }
--
--      case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
--              int i;
--              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
--              unsigned int __user *tmp = (unsigned int __user *)addr;
--
--              for (i = 0; i < 32; i++) {
--                      ret = get_user(*reg, tmp);
--                      if (ret)
--                              break;
--                      reg++;
--                      tmp++;
-+              ret = 0;
-+              for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
-+                      ret |= __put_user(ptrace_get_reg(child, ui),
-+                                        (unsigned int __user *) data);
-+                      data += sizeof(int);
-               }
-               break;
-       }
--      case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
--              int i;
--              unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
--              unsigned int __user *tmp = (unsigned int __user *)addr;
--
--              flush_fp_to_thread(child);
--
--              for (i = 0; i < 32; i++) {
--                      ret = put_user(*reg, tmp);
--                      if (ret)
--                              break;
--                      reg++;
--                      tmp++;
--              }
-+      case PTRACE_SETREGS: { /* Set all gp regs in the child. */
-+              unsigned long tmp;
-+              int ui;
-+              if (!access_ok(VERIFY_READ, (void __user *)data,
-+                             PT_REGS_COUNT * sizeof(int))) {
-+                      ret = -EIO;
-               break;
-       }
--
--      case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
--              int i;
--              unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
--              unsigned int __user *tmp = (unsigned int __user *)addr;
--
--              flush_fp_to_thread(child);
--
--              for (i = 0; i < 32; i++) {
--                      ret = get_user(*reg, tmp);
-+              ret = 0;
-+              for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
-+                      ret = __get_user(tmp, (unsigned int __user *) data);
-                       if (ret)
-                               break;
--                      reg++;
--                      tmp++;
-+                      ptrace_put_reg(child, ui, tmp);
-+                      data += sizeof(int);
-               }
-               break;
-       }
--      case PTRACE_GETEVENTMSG:
--              ret = put_user(child->ptrace_message, (unsigned int __user *) data);
--              break;
--
--#ifdef CONFIG_ALTIVEC
-+      case PTRACE_GETFPREGS:
-+      case PTRACE_SETFPREGS:
-       case PTRACE_GETVRREGS:
--              /* Get the child altivec register state. */
--              flush_altivec_to_thread(child);
--              ret = get_vrregs((unsigned long __user *)data, child);
-+      case PTRACE_SETVRREGS:
-+      case PTRACE_GETREGS64:
-+      case PTRACE_SETREGS64:
-+      case PPC_PTRACE_GETFPREGS:
-+      case PPC_PTRACE_SETFPREGS:
-+      case PTRACE_KILL:
-+      case PTRACE_SINGLESTEP:
-+      case PTRACE_DETACH:
-+      case PTRACE_SET_DEBUGREG:
-+      case PTRACE_SYSCALL:
-+      case PTRACE_CONT:
-+              ret = arch_ptrace(child, request, addr, data);
-               break;
--      case PTRACE_SETVRREGS:
--              /* Set the child altivec register state. */
--              flush_altivec_to_thread(child);
--              ret = set_vrregs(child, (unsigned long __user *)data);
-+      /* Old reverse args ptrace callss */
-+      case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
-+      case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
-+              ret = compat_ptrace_old(child, request, addr, data);
-               break;
--#endif
-       default:
-               ret = ptrace_request(child, request, addr, data);
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/rtas_pci.c linux-2.6.22-590/arch/powerpc/kernel/rtas_pci.c
---- linux-2.6.22-570/arch/powerpc/kernel/rtas_pci.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/rtas_pci.c    2008-01-02 13:56:37.000000000 -0500
-@@ -278,10 +278,8 @@
- {
-       struct device_node *node;
-       struct pci_controller *phb;
--      unsigned int index;
-       struct device_node *root = of_find_node_by_path("/");
--      index = 0;
-       for (node = of_get_next_child(root, NULL);
-            node != NULL;
-            node = of_get_next_child(root, node)) {
-@@ -295,8 +293,7 @@
-                       continue;
-               rtas_setup_phb(phb);
-               pci_process_bridge_OF_ranges(phb, node, 0);
--              pci_setup_phb_io(phb, index == 0);
--              index++;
-+              isa_bridge_find_early(phb);
-       }
-       of_node_put(root);
-@@ -335,7 +332,7 @@
-               return 1;
-       }
--      rc = unmap_bus_range(b);
-+      rc = pcibios_unmap_io_space(b);
-       if (rc) {
-               printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
-                       __FUNCTION__, b->name);
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/setup_32.c linux-2.6.22-590/arch/powerpc/kernel/setup_32.c
---- linux-2.6.22-570/arch/powerpc/kernel/setup_32.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/setup_32.c    2008-01-02 13:56:37.000000000 -0500
-@@ -45,10 +45,6 @@
- #define DBG(fmt...)
--#if defined CONFIG_KGDB
--#include <asm/kgdb.h>
--#endif
--
- extern void bootx_init(unsigned long r4, unsigned long phys);
- struct ide_machdep_calls ppc_ide_md;
-@@ -245,30 +241,16 @@
-       xmon_setup();
--#if defined(CONFIG_KGDB)
--      if (ppc_md.kgdb_map_scc)
--              ppc_md.kgdb_map_scc();
--      set_debug_traps();
--      if (strstr(cmd_line, "gdb")) {
--              if (ppc_md.progress)
--                      ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
--              printk("kgdb breakpoint activated\n");
--              breakpoint();
--      }
--#endif
--
-       /*
-        * Set cache line size based on type of cpu as a default.
-        * Systems with OF can look in the properties on the cpu node(s)
-        * for a possibly more accurate value.
-        */
--      if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
-               dcache_bsize = cur_cpu_spec->dcache_bsize;
-               icache_bsize = cur_cpu_spec->icache_bsize;
-               ucache_bsize = 0;
--      } else
--              ucache_bsize = dcache_bsize = icache_bsize
--                      = cur_cpu_spec->dcache_bsize;
-+      if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE))
-+              ucache_bsize = icache_bsize = dcache_bsize;
-       /* reboot on panic */
-       panic_timeout = 180;
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/signal.c linux-2.6.22-590/arch/powerpc/kernel/signal.c
---- linux-2.6.22-570/arch/powerpc/kernel/signal.c      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/kernel/signal.c      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,180 @@
-+/*
-+ * Common signal handling code for both 32 and 64 bits
-+ *
-+ *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
-+ *    Extracted from signal_32.c and signal_64.c
-+ *
-+ * This file is subject to the terms and conditions of the GNU General
-+ * Public License.  See the file README.legal in the main directory of
-+ * this archive for more details.
-+ */
-+
-+#include <linux/ptrace.h>
-+#include <linux/signal.h>
-+#include <asm/uaccess.h>
-+#include <asm/unistd.h>
-+
-+#include "signal.h"
-+
-+/*
-+ * Allocate space for the signal frame
-+ */
-+void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
-+                         size_t frame_size)
-+{
-+        unsigned long oldsp, newsp;
-+
-+        /* Default to using normal stack */
-+        oldsp = regs->gpr[1];
-+
-+      /* Check for alt stack */
-+      if ((ka->sa.sa_flags & SA_ONSTACK) &&
-+          current->sas_ss_size && !on_sig_stack(oldsp))
-+              oldsp = (current->sas_ss_sp + current->sas_ss_size);
-+
-+      /* Get aligned frame */
-+      newsp = (oldsp - frame_size) & ~0xFUL;
-+
-+      /* Check access */
-+      if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp))
-+              return NULL;
-+
-+        return (void __user *)newsp;
-+}
-+
-+
-+/*
-+ * Restore the user process's signal mask
-+ */
-+void restore_sigmask(sigset_t *set)
-+{
-+      sigdelsetmask(set, ~_BLOCKABLE);
-+      spin_lock_irq(&current->sighand->siglock);
-+      current->blocked = *set;
-+      recalc_sigpending();
-+      spin_unlock_irq(&current->sighand->siglock);
-+}
-+
-+static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
-+                                int has_handler)
-+{
-+      unsigned long ret = regs->gpr[3];
-+      int restart = 1;
-+
-+      /* syscall ? */
-+      if (TRAP(regs) != 0x0C00)
-+              return;
-+
-+      /* error signalled ? */
-+      if (!(regs->ccr & 0x10000000))
-+              return;
-+
-+      switch (ret) {
-+      case ERESTART_RESTARTBLOCK:
-+      case ERESTARTNOHAND:
-+              /* ERESTARTNOHAND means that the syscall should only be
-+               * restarted if there was no handler for the signal, and since
-+               * we only get here if there is a handler, we dont restart.
-+               */
-+              restart = !has_handler;
-+              break;
-+      case ERESTARTSYS:
-+              /* ERESTARTSYS means to restart the syscall if there is no
-+               * handler or the handler was registered with SA_RESTART
-+               */
-+              restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0;
-+              break;
-+      case ERESTARTNOINTR:
-+              /* ERESTARTNOINTR means that the syscall should be
-+               * called again after the signal handler returns.
-+               */
-+              break;
-+      default:
-+              return;
-+      }
-+      if (restart) {
-+              if (ret == ERESTART_RESTARTBLOCK)
-+                      regs->gpr[0] = __NR_restart_syscall;
-+              else
-+                      regs->gpr[3] = regs->orig_gpr3;
-+              regs->nip -= 4;
-+              regs->result = 0;
-+      } else {
-+              regs->result = -EINTR;
-+              regs->gpr[3] = EINTR;
-+              regs->ccr |= 0x10000000;
-+      }
-+}
-+
-+int do_signal(sigset_t *oldset, struct pt_regs *regs)
-+{
-+      siginfo_t info;
-+      int signr;
-+      struct k_sigaction ka;
-+      int ret;
-+      int is32 = is_32bit_task();
-+
-+      if (test_thread_flag(TIF_RESTORE_SIGMASK))
-+              oldset = &current->saved_sigmask;
-+      else if (!oldset)
-+              oldset = &current->blocked;
-+
-+      signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-+
-+      /* Is there any syscall restart business here ? */
-+      check_syscall_restart(regs, &ka, signr > 0);
-+
-+      if (signr <= 0) {
-+              /* No signal to deliver -- put the saved sigmask back */
-+              if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-+                      clear_thread_flag(TIF_RESTORE_SIGMASK);
-+                      sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-+              }
-+              return 0;               /* no signals delivered */
-+      }
-+
-+        /*
-+       * Reenable the DABR before delivering the signal to
-+       * user space. The DABR will have been cleared if it
-+       * triggered inside the kernel.
-+       */
-+      if (current->thread.dabr)
-+              set_dabr(current->thread.dabr);
-+
-+      if (is32) {
-+              if (ka.sa.sa_flags & SA_SIGINFO)
-+                      ret = handle_rt_signal32(signr, &ka, &info, oldset,
-+                                      regs);
-+              else
-+                      ret = handle_signal32(signr, &ka, &info, oldset,
-+                                      regs);
-+      } else {
-+              ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
-+      }
-+
-+      if (ret) {
-+              spin_lock_irq(&current->sighand->siglock);
-+              sigorsets(&current->blocked, &current->blocked,
-+                        &ka.sa.sa_mask);
-+              if (!(ka.sa.sa_flags & SA_NODEFER))
-+                      sigaddset(&current->blocked, signr);
-+              recalc_sigpending();
-+              spin_unlock_irq(&current->sighand->siglock);
-+
-+              /*
-+               * A signal was successfully delivered; the saved sigmask is in
-+               * its frame, and we can clear the TIF_RESTORE_SIGMASK flag.
-+               */
-+              if (test_thread_flag(TIF_RESTORE_SIGMASK))
-+                      clear_thread_flag(TIF_RESTORE_SIGMASK);
-+      }
-+
-+      return ret;
-+}
-+
-+long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
-+              unsigned long r5, unsigned long r6, unsigned long r7,
-+              unsigned long r8, struct pt_regs *regs)
-+{
-+      return do_sigaltstack(uss, uoss, regs->gpr[1]);
-+}
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/signal.h linux-2.6.22-590/arch/powerpc/kernel/signal.h
---- linux-2.6.22-570/arch/powerpc/kernel/signal.h      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/kernel/signal.h      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,55 @@
-+/*
-+ *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
-+ *    Extracted from signal_32.c and signal_64.c
-+ *
-+ * This file is subject to the terms and conditions of the GNU General
-+ * Public License.  See the file README.legal in the main directory of
-+ * this archive for more details.
-+ */
-+
-+#ifndef _POWERPC_ARCH_SIGNAL_H
-+#define _POWERPC_ARCH_SIGNAL_H
-+
-+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-+
-+extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
-+                                size_t frame_size);
-+extern void restore_sigmask(sigset_t *set);
-+
-+extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
-+                         siginfo_t *info, sigset_t *oldset,
-+                         struct pt_regs *regs);
-+
-+extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
-+                            siginfo_t *info, sigset_t *oldset,
-+                            struct pt_regs *regs);
-+
-+
-+#ifdef CONFIG_PPC64
-+
-+static inline int is_32bit_task(void)
-+{
-+      return test_thread_flag(TIF_32BIT);
-+}
-+
-+extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
-+                            siginfo_t *info, sigset_t *set,
-+                            struct pt_regs *regs);
-+
-+#else /* CONFIG_PPC64 */
-+
-+static inline int is_32bit_task(void)
-+{
-+      return 1;
-+}
-+
-+static inline int handle_rt_signal64(int signr, struct k_sigaction *ka,
-+                                   siginfo_t *info, sigset_t *set,
-+                                   struct pt_regs *regs)
-+{
-+      return -EFAULT;
-+}
-+
-+#endif /* !defined(CONFIG_PPC64) */
-+
-+#endif  /* _POWERPC_ARCH_SIGNAL_H */
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/signal_32.c linux-2.6.22-590/arch/powerpc/kernel/signal_32.c
---- linux-2.6.22-570/arch/powerpc/kernel/signal_32.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/signal_32.c   2008-01-02 13:56:37.000000000 -0500
-@@ -51,12 +51,11 @@
- #include <asm/pgtable.h>
- #endif
--#undef DEBUG_SIG
-+#include "signal.h"
--#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-+#undef DEBUG_SIG
- #ifdef CONFIG_PPC64
--#define do_signal     do_signal32
- #define sys_sigsuspend        compat_sys_sigsuspend
- #define sys_rt_sigsuspend     compat_sys_rt_sigsuspend
- #define sys_rt_sigreturn      compat_sys_rt_sigreturn
-@@ -231,8 +230,6 @@
- #endif /* CONFIG_PPC64 */
--int do_signal(sigset_t *oldset, struct pt_regs *regs);
--
- /*
-  * Atomically swap in the new signal mask, and wait for a signal.
-  */
-@@ -251,14 +248,6 @@
-       return -ERESTARTNOHAND;
- }
--#ifdef CONFIG_PPC32
--long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5,
--              int r6, int r7, int r8, struct pt_regs *regs)
--{
--      return do_sigaltstack(uss, uoss, regs->gpr[1]);
--}
--#endif
--
- long sys_sigaction(int sig, struct old_sigaction __user *act,
-               struct old_sigaction __user *oact)
- {
-@@ -293,14 +282,17 @@
- /*
-  * When we have signals to deliver, we set up on the
-  * user stack, going down from the original stack pointer:
-- *    a sigregs struct
-+ *    an ABI gap of 56 words
-+ *    an mcontext struct
-  *    a sigcontext struct
-  *    a gap of __SIGNAL_FRAMESIZE bytes
-  *
-- * Each of these things must be a multiple of 16 bytes in size.
-+ * Each of these things must be a multiple of 16 bytes in size. The following
-+ * structure represent all of this except the __SIGNAL_FRAMESIZE gap
-  *
-  */
--struct sigregs {
-+struct sigframe {
-+      struct sigcontext sctx;         /* the sigcontext */
-       struct mcontext mctx;           /* all the register values */
-       /*
-        * Programs using the rs6000/xcoff abi can save up to 19 gp
-@@ -703,44 +695,22 @@
- }
- #endif /* CONFIG_PPC64 */
--
--/*
-- * Restore the user process's signal mask
-- */
--#ifdef CONFIG_PPC64
--extern void restore_sigmask(sigset_t *set);
--#else /* CONFIG_PPC64 */
--static void restore_sigmask(sigset_t *set)
--{
--      sigdelsetmask(set, ~_BLOCKABLE);
--      spin_lock_irq(&current->sighand->siglock);
--      current->blocked = *set;
--      recalc_sigpending();
--      spin_unlock_irq(&current->sighand->siglock);
--}
--#endif
--
- /*
-  * Set up a signal frame for a "real-time" signal handler
-  * (one which gets siginfo).
-  */
--static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
-+int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
-               siginfo_t *info, sigset_t *oldset,
--              struct pt_regs *regs, unsigned long newsp)
-+              struct pt_regs *regs)
- {
-       struct rt_sigframe __user *rt_sf;
-       struct mcontext __user *frame;
--      unsigned long origsp = newsp;
-+      unsigned long newsp = 0;
-       /* Set up Signal Frame */
-       /* Put a Real Time Context onto stack */
--      newsp -= sizeof(*rt_sf);
--      rt_sf = (struct rt_sigframe __user *)newsp;
--
--      /* create a stack frame for the caller of the handler */
--      newsp -= __SIGNAL_FRAMESIZE + 16;
--
--      if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
-+      rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf));
-+      if (unlikely(rt_sf == NULL))
-               goto badframe;
-       /* Put the siginfo & fill in most of the ucontext */
-@@ -770,8 +740,12 @@
-       current->thread.fpscr.val = 0;  /* turn off all fp exceptions */
-+      /* create a stack frame for the caller of the handler */
-+      newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
-       if (put_user(regs->gpr[1], (u32 __user *)newsp))
-               goto badframe;
-+
-+      /* Fill registers for signal handler */
-       regs->gpr[1] = newsp;
-       regs->gpr[3] = sig;
-       regs->gpr[4] = (unsigned long) &rt_sf->info;
-@@ -1015,27 +989,18 @@
- /*
-  * OK, we're invoking a handler
-  */
--static int handle_signal(unsigned long sig, struct k_sigaction *ka,
--              siginfo_t *info, sigset_t *oldset, struct pt_regs *regs,
--              unsigned long newsp)
-+int handle_signal32(unsigned long sig, struct k_sigaction *ka,
-+                  siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
- {
-       struct sigcontext __user *sc;
--      struct sigregs __user *frame;
--      unsigned long origsp = newsp;
-+      struct sigframe __user *frame;
-+      unsigned long newsp = 0;
-       /* Set up Signal Frame */
--      newsp -= sizeof(struct sigregs);
--      frame = (struct sigregs __user *) newsp;
--
--      /* Put a sigcontext on the stack */
--      newsp -= sizeof(*sc);
--      sc = (struct sigcontext __user *) newsp;
--
--      /* create a stack frame for the caller of the handler */
--      newsp -= __SIGNAL_FRAMESIZE;
--
--      if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
-+      frame = get_sigframe(ka, regs, sizeof(*frame));
-+      if (unlikely(frame == NULL))
-               goto badframe;
-+      sc = (struct sigcontext __user *) &frame->sctx;
- #if _NSIG != 64
- #error "Please adjust handle_signal()"
-@@ -1047,7 +1012,7 @@
- #else
-           || __put_user(oldset->sig[1], &sc->_unused[3])
- #endif
--          || __put_user(to_user_ptr(frame), &sc->regs)
-+          || __put_user(to_user_ptr(&frame->mctx), &sc->regs)
-           || __put_user(sig, &sc->signal))
-               goto badframe;
-@@ -1063,8 +1028,11 @@
-       current->thread.fpscr.val = 0;  /* turn off all fp exceptions */
-+      /* create a stack frame for the caller of the handler */
-+      newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
-       if (put_user(regs->gpr[1], (u32 __user *)newsp))
-               goto badframe;
-+
-       regs->gpr[1] = newsp;
-       regs->gpr[3] = sig;
-       regs->gpr[4] = (unsigned long) sc;
-@@ -1126,106 +1094,3 @@
-       force_sig(SIGSEGV, current);
-       return 0;
- }
--
--/*
-- * Note that 'init' is a special process: it doesn't get signals it doesn't
-- * want to handle. Thus you cannot kill init even with a SIGKILL even by
-- * mistake.
-- */
--int do_signal(sigset_t *oldset, struct pt_regs *regs)
--{
--      siginfo_t info;
--      struct k_sigaction ka;
--      unsigned int newsp;
--      int signr, ret;
--
--#ifdef CONFIG_PPC32
--      if (try_to_freeze()) {
--              signr = 0;
--              if (!signal_pending(current))
--                      goto no_signal;
--      }
--#endif
--
--      if (test_thread_flag(TIF_RESTORE_SIGMASK))
--              oldset = &current->saved_sigmask;
--      else if (!oldset)
--              oldset = &current->blocked;
--
--      signr = get_signal_to_deliver(&info, &ka, regs, NULL);
--#ifdef CONFIG_PPC32
--no_signal:
--#endif
--      if (TRAP(regs) == 0x0C00                /* System Call! */
--          && regs->ccr & 0x10000000           /* error signalled */
--          && ((ret = regs->gpr[3]) == ERESTARTSYS
--              || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
--              || ret == ERESTART_RESTARTBLOCK)) {
--
--              if (signr > 0
--                  && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
--                      || (ret == ERESTARTSYS
--                          && !(ka.sa.sa_flags & SA_RESTART)))) {
--                      /* make the system call return an EINTR error */
--                      regs->result = -EINTR;
--                      regs->gpr[3] = EINTR;
--                      /* note that the cr0.SO bit is already set */
--              } else {
--                      regs->nip -= 4; /* Back up & retry system call */
--                      regs->result = 0;
--                      regs->trap = 0;
--                      if (ret == ERESTART_RESTARTBLOCK)
--                              regs->gpr[0] = __NR_restart_syscall;
--                      else
--                              regs->gpr[3] = regs->orig_gpr3;
--              }
--      }
--
--      if (signr == 0) {
--              /* No signal to deliver -- put the saved sigmask back */
--              if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
--                      clear_thread_flag(TIF_RESTORE_SIGMASK);
--                      sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
--              }
--              return 0;               /* no signals delivered */
--      }
--
--      if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
--          && !on_sig_stack(regs->gpr[1]))
--              newsp = current->sas_ss_sp + current->sas_ss_size;
--      else
--              newsp = regs->gpr[1];
--      newsp &= ~0xfUL;
--
--#ifdef CONFIG_PPC64
--      /*
--       * Reenable the DABR before delivering the signal to
--       * user space. The DABR will have been cleared if it
--       * triggered inside the kernel.
--       */
--      if (current->thread.dabr)
--              set_dabr(current->thread.dabr);
--#endif
--
--      /* Whee!  Actually deliver the signal.  */
--      if (ka.sa.sa_flags & SA_SIGINFO)
--              ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
--      else
--              ret = handle_signal(signr, &ka, &info, oldset, regs, newsp);
--
--      if (ret) {
--              spin_lock_irq(&current->sighand->siglock);
--              sigorsets(&current->blocked, &current->blocked,
--                        &ka.sa.sa_mask);
--              if (!(ka.sa.sa_flags & SA_NODEFER))
--                      sigaddset(&current->blocked, signr);
--              recalc_sigpending();
--              spin_unlock_irq(&current->sighand->siglock);
--              /* A signal was successfully delivered; the saved sigmask is in
--                 its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
--              if (test_thread_flag(TIF_RESTORE_SIGMASK))
--                      clear_thread_flag(TIF_RESTORE_SIGMASK);
--      }
--
--      return ret;
--}
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/signal_64.c linux-2.6.22-590/arch/powerpc/kernel/signal_64.c
---- linux-2.6.22-570/arch/powerpc/kernel/signal_64.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/kernel/signal_64.c   2008-01-02 13:56:37.000000000 -0500
-@@ -34,9 +34,9 @@
- #include <asm/syscalls.h>
- #include <asm/vdso.h>
--#define DEBUG_SIG 0
-+#include "signal.h"
--#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-+#define DEBUG_SIG 0
- #define GP_REGS_SIZE  min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
- #define FP_REGS_SIZE  sizeof(elf_fpregset_t)
-@@ -64,14 +64,6 @@
-       char abigap[288];
- } __attribute__ ((aligned (16)));
--long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
--                   unsigned long r6, unsigned long r7, unsigned long r8,
--                   struct pt_regs *regs)
--{
--      return do_sigaltstack(uss, uoss, regs->gpr[1]);
--}
--
--
- /*
-  * Set up the sigcontext for the signal frame.
-  */
-@@ -208,25 +200,6 @@
- }
- /*
-- * Allocate space for the signal frame
-- */
--static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
--                                size_t frame_size)
--{
--        unsigned long newsp;
--
--        /* Default to using normal stack */
--        newsp = regs->gpr[1];
--
--      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);
--      }
--
--        return (void __user *)((newsp - frame_size) & -16ul);
--}
--
--/*
-  * Setup the trampoline code on the stack
-  */
- static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp)
-@@ -253,19 +226,6 @@
- }
- /*
-- * Restore the user process's signal mask (also used by signal32.c)
-- */
--void restore_sigmask(sigset_t *set)
--{
--      sigdelsetmask(set, ~_BLOCKABLE);
--      spin_lock_irq(&current->sighand->siglock);
--      current->blocked = *set;
--      recalc_sigpending();
--      spin_unlock_irq(&current->sighand->siglock);
--}
--
--
--/*
-  * Handle {get,set,swap}_context operations
-  */
- int sys_swapcontext(struct ucontext __user *old_ctx,
-@@ -359,7 +319,7 @@
-       return 0;
- }
--static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
-+int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
-               sigset_t *set, struct pt_regs *regs)
- {
-       /* Handler is *really* a pointer to the function descriptor for
-@@ -373,8 +333,7 @@
-       long err = 0;
-       frame = get_sigframe(ka, regs, sizeof(*frame));
--
--      if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-+      if (unlikely(frame == NULL))
-               goto badframe;
-       err |= __put_user(&frame->info, &frame->pinfo);
-@@ -411,7 +370,7 @@
-       funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;
-       /* Allocate a dummy caller frame for the signal handler. */
--      newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE;
-+      newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
-       err |= put_user(regs->gpr[1], (unsigned long __user *)newsp);
-       /* Set up "regs" so we "return" to the signal handler. */
-@@ -442,134 +401,3 @@
-       force_sigsegv(signr, current);
-       return 0;
- }
--
--
--/*
-- * OK, we're invoking a handler
-- */
--static int handle_signal(unsigned long sig, struct k_sigaction *ka,
--                       siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
--{
--      int ret;
--
--      /* Set up Signal Frame */
--      ret = setup_rt_frame(sig, ka, info, oldset, regs);
--
--      if (ret) {
--              spin_lock_irq(&current->sighand->siglock);
--              sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
--              if (!(ka->sa.sa_flags & SA_NODEFER))
--                      sigaddset(&current->blocked,sig);
--              recalc_sigpending();
--              spin_unlock_irq(&current->sighand->siglock);
--      }
--
--      return ret;
--}
--
--static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
--{
--      switch ((int)regs->result) {
--      case -ERESTART_RESTARTBLOCK:
--      case -ERESTARTNOHAND:
--              /* ERESTARTNOHAND means that the syscall should only be
--               * restarted if there was no handler for the signal, and since
--               * we only get here if there is a handler, we dont restart.
--               */
--              regs->result = -EINTR;
--              regs->gpr[3] = EINTR;
--              regs->ccr |= 0x10000000;
--              break;
--      case -ERESTARTSYS:
--              /* ERESTARTSYS means to restart the syscall if there is no
--               * handler or the handler was registered with SA_RESTART
--               */
--              if (!(ka->sa.sa_flags & SA_RESTART)) {
--                      regs->result = -EINTR;
--                      regs->gpr[3] = EINTR;
--                      regs->ccr |= 0x10000000;
--                      break;
--              }
--              /* fallthrough */
--      case -ERESTARTNOINTR:
--              /* ERESTARTNOINTR means that the syscall should be
--               * called again after the signal handler returns.
--               */
--              regs->gpr[3] = regs->orig_gpr3;
--              regs->nip -= 4;
--              regs->result = 0;
--              break;
--      }
--}
--
--/*
-- * Note that 'init' is a special process: it doesn't get signals it doesn't
-- * want to handle. Thus you cannot kill init even with a SIGKILL even by
-- * mistake.
-- */
--int do_signal(sigset_t *oldset, struct pt_regs *regs)
--{
--      siginfo_t info;
--      int signr;
--      struct k_sigaction ka;
--
--      /*
--       * If the current thread is 32 bit - invoke the
--       * 32 bit signal handling code
--       */
--      if (test_thread_flag(TIF_32BIT))
--              return do_signal32(oldset, regs);
--
--      if (test_thread_flag(TIF_RESTORE_SIGMASK))
--              oldset = &current->saved_sigmask;
--      else if (!oldset)
--              oldset = &current->blocked;
--
--      signr = get_signal_to_deliver(&info, &ka, regs, NULL);
--      if (signr > 0) {
--              int ret;
--
--              /* Whee!  Actually deliver the signal.  */
--              if (TRAP(regs) == 0x0C00)
--                      syscall_restart(regs, &ka);
--
--              /*
--               * Reenable the DABR before delivering the signal to
--               * user space. The DABR will have been cleared if it
--               * triggered inside the kernel.
--               */
--              if (current->thread.dabr)
--                      set_dabr(current->thread.dabr);
--
--              ret = handle_signal(signr, &ka, &info, oldset, regs);
--
--              /* If a signal was successfully delivered, the saved sigmask is in
--                 its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
--              if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
--                      clear_thread_flag(TIF_RESTORE_SIGMASK);
--
--              return ret;
--      }
--
--      if (TRAP(regs) == 0x0C00) {     /* System Call! */
--              if ((int)regs->result == -ERESTARTNOHAND ||
--                  (int)regs->result == -ERESTARTSYS ||
--                  (int)regs->result == -ERESTARTNOINTR) {
--                      regs->gpr[3] = regs->orig_gpr3;
--                      regs->nip -= 4; /* Back up & retry system call */
--                      regs->result = 0;
--              } else if ((int)regs->result == -ERESTART_RESTARTBLOCK) {
--                      regs->gpr[0] = __NR_restart_syscall;
--                      regs->nip -= 4;
--                      regs->result = 0;
--              }
--      }
--      /* No signal to deliver -- put the saved sigmask back */
--      if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
--              clear_thread_flag(TIF_RESTORE_SIGMASK);
--              sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
--      }
--
--      return 0;
--}
--EXPORT_SYMBOL(do_signal);
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/sys_ppc32.c linux-2.6.22-590/arch/powerpc/kernel/sys_ppc32.c
---- linux-2.6.22-570/arch/powerpc/kernel/sys_ppc32.c   2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/kernel/sys_ppc32.c   2008-01-02 13:56:37.000000000 -0500
-@@ -773,6 +773,13 @@
-       return sys_truncate(path, (high << 32) | low);
- }
-+asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo,
-+                                   u32 lenhi, u32 lenlo)
-+{
-+      return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
-+                           ((loff_t)lenhi << 32) | lenlo);
-+}
-+
- asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long high,
-                                unsigned long low)
- {
-diff -Nurb linux-2.6.22-570/arch/powerpc/kernel/vdso.c linux-2.6.22-590/arch/powerpc/kernel/vdso.c
---- linux-2.6.22-570/arch/powerpc/kernel/vdso.c        2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/kernel/vdso.c        2008-01-02 13:56:37.000000000 -0500
-@@ -671,7 +671,7 @@
-       /*
-        * Fill up the "systemcfg" stuff for backward compatiblity
-        */
--      strcpy(vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
-+      strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
-       vdso_data->version.major = SYSTEMCFG_MAJOR;
-       vdso_data->version.minor = SYSTEMCFG_MINOR;
-       vdso_data->processor = mfspr(SPRN_PVR);
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/44x_mmu.c linux-2.6.22-590/arch/powerpc/mm/44x_mmu.c
---- linux-2.6.22-570/arch/powerpc/mm/44x_mmu.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/44x_mmu.c 2008-01-02 13:56:37.000000000 -0500
-@@ -12,7 +12,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  *  Derived from "arch/i386/mm/init.c"
-  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/4xx_mmu.c linux-2.6.22-590/arch/powerpc/mm/4xx_mmu.c
---- linux-2.6.22-570/arch/powerpc/mm/4xx_mmu.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/4xx_mmu.c 2008-01-02 13:56:37.000000000 -0500
-@@ -9,7 +9,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  *  Derived from "arch/i386/mm/init.c"
-  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/Makefile linux-2.6.22-590/arch/powerpc/mm/Makefile
---- linux-2.6.22-570/arch/powerpc/mm/Makefile  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -11,8 +11,7 @@
- hash-$(CONFIG_PPC_NATIVE)     := hash_native_64.o
- obj-$(CONFIG_PPC64)           += init_64.o pgtable_64.o mmu_context_64.o \
-                                  hash_utils_64.o hash_low_64.o tlb_64.o \
--                                 slb_low.o slb.o stab.o mmap.o imalloc.o \
--                                 $(hash-y)
-+                                 slb_low.o slb.o stab.o mmap.o $(hash-y)
- obj-$(CONFIG_PPC_STD_MMU_32)  += ppc_mmu_32.o hash_low_32.o tlb_32.o
- obj-$(CONFIG_40x)             += 4xx_mmu.o
- obj-$(CONFIG_44x)             += 44x_mmu.o
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/fault.c linux-2.6.22-590/arch/powerpc/mm/fault.c
---- linux-2.6.22-570/arch/powerpc/mm/fault.c   2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/mm/fault.c   2008-01-02 13:56:37.000000000 -0500
-@@ -29,6 +29,7 @@
- #include <linux/module.h>
- #include <linux/kprobes.h>
- #include <linux/kdebug.h>
-+#include <linux/kgdb.h>
- #include <asm/page.h>
- #include <asm/pgtable.h>
-@@ -381,7 +382,7 @@
-       printk("VM: killing process %s(%d:#%u)\n",
-               current->comm, current->pid, current->xid);
-       if (user_mode(regs))
--              do_exit(SIGKILL);
-+              do_group_exit(SIGKILL);
-       return SIGKILL;
- do_sigbus:
-@@ -412,6 +413,13 @@
-               return;
-       }
-+#ifdef CONFIG_KGDB
-+      if (atomic_read(&debugger_active) && kgdb_may_fault)
-+              /* Restore our previous state. */
-+              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
-+              /* Not reached. */
-+#endif
-+
-       /* kernel has accessed a bad area */
-       switch (regs->trap) {
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/fsl_booke_mmu.c linux-2.6.22-590/arch/powerpc/mm/fsl_booke_mmu.c
---- linux-2.6.22-570/arch/powerpc/mm/fsl_booke_mmu.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/fsl_booke_mmu.c   2008-01-02 13:56:37.000000000 -0500
-@@ -14,7 +14,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  *  Derived from "arch/i386/mm/init.c"
-  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/hash_native_64.c linux-2.6.22-590/arch/powerpc/mm/hash_native_64.c
---- linux-2.6.22-570/arch/powerpc/mm/hash_native_64.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/hash_native_64.c  2008-01-02 13:56:37.000000000 -0500
-@@ -104,7 +104,7 @@
-               spin_unlock(&native_tlbie_lock);
- }
--static inline void native_lock_hpte(hpte_t *hptep)
-+static inline void native_lock_hpte(struct hash_pte *hptep)
- {
-       unsigned long *word = &hptep->v;
-@@ -116,7 +116,7 @@
-       }
- }
--static inline void native_unlock_hpte(hpte_t *hptep)
-+static inline void native_unlock_hpte(struct hash_pte *hptep)
- {
-       unsigned long *word = &hptep->v;
-@@ -128,7 +128,7 @@
-                       unsigned long pa, unsigned long rflags,
-                       unsigned long vflags, int psize)
- {
--      hpte_t *hptep = htab_address + hpte_group;
-+      struct hash_pte *hptep = htab_address + hpte_group;
-       unsigned long hpte_v, hpte_r;
-       int i;
-@@ -177,7 +177,7 @@
- static long native_hpte_remove(unsigned long hpte_group)
- {
--      hpte_t *hptep;
-+      struct hash_pte *hptep;
-       int i;
-       int slot_offset;
-       unsigned long hpte_v;
-@@ -217,7 +217,7 @@
- static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
-                                unsigned long va, int psize, int local)
- {
--      hpte_t *hptep = htab_address + slot;
-+      struct hash_pte *hptep = htab_address + slot;
-       unsigned long hpte_v, want_v;
-       int ret = 0;
-@@ -233,15 +233,14 @@
-       /* Even if we miss, we need to invalidate the TLB */
-       if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) {
-               DBG_LOW(" -> miss\n");
--              native_unlock_hpte(hptep);
-               ret = -1;
-       } else {
-               DBG_LOW(" -> hit\n");
-               /* Update the HPTE */
-               hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
-                       (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C));
--              native_unlock_hpte(hptep);
-       }
-+      native_unlock_hpte(hptep);
-       /* Ensure it is out of the tlb too. */
-       tlbie(va, psize, local);
-@@ -251,7 +250,7 @@
- static long native_hpte_find(unsigned long va, int psize)
- {
--      hpte_t *hptep;
-+      struct hash_pte *hptep;
-       unsigned long hash;
-       unsigned long i, j;
-       long slot;
-@@ -294,7 +293,7 @@
- {
-       unsigned long vsid, va;
-       long slot;
--      hpte_t *hptep;
-+      struct hash_pte *hptep;
-       vsid = get_kernel_vsid(ea);
-       va = (vsid << 28) | (ea & 0x0fffffff);
-@@ -315,7 +314,7 @@
- static void native_hpte_invalidate(unsigned long slot, unsigned long va,
-                                  int psize, int local)
- {
--      hpte_t *hptep = htab_address + slot;
-+      struct hash_pte *hptep = htab_address + slot;
-       unsigned long hpte_v;
-       unsigned long want_v;
-       unsigned long flags;
-@@ -345,7 +344,7 @@
- #define LP_BITS               8
- #define LP_MASK(i)    ((0xFF >> (i)) << LP_SHIFT)
--static void hpte_decode(hpte_t *hpte, unsigned long slot,
-+static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
-                       int *psize, unsigned long *va)
- {
-       unsigned long hpte_r = hpte->r;
-@@ -415,7 +414,7 @@
- static void native_hpte_clear(void)
- {
-       unsigned long slot, slots, flags;
--      hpte_t *hptep = htab_address;
-+      struct hash_pte *hptep = htab_address;
-       unsigned long hpte_v, va;
-       unsigned long pteg_count;
-       int psize;
-@@ -462,7 +461,7 @@
- static void native_flush_hash_range(unsigned long number, int local)
- {
-       unsigned long va, hash, index, hidx, shift, slot;
--      hpte_t *hptep;
-+      struct hash_pte *hptep;
-       unsigned long hpte_v;
-       unsigned long want_v;
-       unsigned long flags;
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/hash_utils_64.c linux-2.6.22-590/arch/powerpc/mm/hash_utils_64.c
---- linux-2.6.22-570/arch/powerpc/mm/hash_utils_64.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/hash_utils_64.c   2008-01-02 13:56:37.000000000 -0500
-@@ -87,7 +87,7 @@
- static unsigned long _SDR1;
- struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
--hpte_t *htab_address;
-+struct hash_pte *htab_address;
- unsigned long htab_size_bytes;
- unsigned long htab_hash_mask;
- int mmu_linear_psize = MMU_PAGE_4K;
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/imalloc.c linux-2.6.22-590/arch/powerpc/mm/imalloc.c
---- linux-2.6.22-570/arch/powerpc/mm/imalloc.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/imalloc.c 1969-12-31 19:00:00.000000000 -0500
-@@ -1,313 +0,0 @@
--/*
-- * c 2001 PPC 64 Team, IBM Corp
-- * 
-- *      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.
-- */
--
--#include <linux/slab.h>
--#include <linux/vmalloc.h>
--
--#include <asm/uaccess.h>
--#include <asm/pgalloc.h>
--#include <asm/pgtable.h>
--#include <linux/mutex.h>
--#include <asm/cacheflush.h>
--
--#include "mmu_decl.h"
--
--static DEFINE_MUTEX(imlist_mutex);
--struct vm_struct * imlist = NULL;
--
--static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
--{
--      unsigned long addr;
--      struct vm_struct **p, *tmp;
--
--      addr = ioremap_bot;
--      for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
--              if (size + addr < (unsigned long) tmp->addr)
--                      break;
--              if ((unsigned long)tmp->addr >= ioremap_bot)
--                      addr = tmp->size + (unsigned long) tmp->addr;
--              if (addr >= IMALLOC_END-size)
--                      return 1;
--      }
--      *im_addr = addr;
--
--      return 0;
--}
--
--/* Return whether the region described by v_addr and size is a subset
-- * of the region described by parent
-- */
--static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
--                      struct vm_struct *parent)
--{
--      return (int) (v_addr >= (unsigned long) parent->addr &&
--                    v_addr < (unsigned long) parent->addr + parent->size &&
--                    size < parent->size);
--}
--
--/* Return whether the region described by v_addr and size is a superset
-- * of the region described by child
-- */
--static int im_region_is_superset(unsigned long v_addr, unsigned long size,
--              struct vm_struct *child)
--{
--      struct vm_struct parent;
--
--      parent.addr = (void *) v_addr;
--      parent.size = size;
--
--      return im_region_is_subset((unsigned long) child->addr, child->size,
--                      &parent);
--}
--
--/* Return whether the region described by v_addr and size overlaps
-- * the region described by vm.  Overlapping regions meet the
-- * following conditions:
-- * 1) The regions share some part of the address space
-- * 2) The regions aren't identical
-- * 3) Neither region is a subset of the other
-- */
--static int im_region_overlaps(unsigned long v_addr, unsigned long size,
--                   struct vm_struct *vm)
--{
--      if (im_region_is_superset(v_addr, size, vm))
--              return 0;
--
--      return (v_addr + size > (unsigned long) vm->addr + vm->size &&
--              v_addr < (unsigned long) vm->addr + vm->size) ||
--             (v_addr < (unsigned long) vm->addr &&
--              v_addr + size > (unsigned long) vm->addr);
--}
--
--/* Determine imalloc status of region described by v_addr and size.
-- * Can return one of the following:
-- * IM_REGION_UNUSED   -  Entire region is unallocated in imalloc space.
-- * IM_REGION_SUBSET -    Region is a subset of a region that is already
-- *                     allocated in imalloc space.
-- *                     vm will be assigned to a ptr to the parent region.
-- * IM_REGION_EXISTS -    Exact region already allocated in imalloc space.
-- *                       vm will be assigned to a ptr to the existing imlist
-- *                       member.
-- * IM_REGION_OVERLAPS -  Region overlaps an allocated region in imalloc space.
-- * IM_REGION_SUPERSET -  Region is a superset of a region that is already
-- *                       allocated in imalloc space.
-- */
--static int im_region_status(unsigned long v_addr, unsigned long size,
--                  struct vm_struct **vm)
--{
--      struct vm_struct *tmp;
--
--      for (tmp = imlist; tmp; tmp = tmp->next)
--              if (v_addr < (unsigned long) tmp->addr + tmp->size)
--                      break;
--
--      *vm = NULL;
--      if (tmp) {
--              if (im_region_overlaps(v_addr, size, tmp))
--                      return IM_REGION_OVERLAP;
--
--              *vm = tmp;
--              if (im_region_is_subset(v_addr, size, tmp)) {
--                      /* Return with tmp pointing to superset */
--                      return IM_REGION_SUBSET;
--              }
--              if (im_region_is_superset(v_addr, size, tmp)) {
--                      /* Return with tmp pointing to first subset */
--                      return IM_REGION_SUPERSET;
--              }
--              else if (v_addr == (unsigned long) tmp->addr &&
--                       size == tmp->size) {
--                      /* Return with tmp pointing to exact region */
--                      return IM_REGION_EXISTS;
--              }
--      }
--
--      return IM_REGION_UNUSED;
--}
--
--static struct vm_struct * split_im_region(unsigned long v_addr, 
--              unsigned long size, struct vm_struct *parent)
--{
--      struct vm_struct *vm1 = NULL;
--      struct vm_struct *vm2 = NULL;
--      struct vm_struct *new_vm = NULL;
--      
--      vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL);
--      if (vm1 == NULL) {
--              printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
--              return NULL;
--      }
--
--      if (v_addr == (unsigned long) parent->addr) {
--              /* Use existing parent vm_struct to represent child, allocate
--               * new one for the remainder of parent range
--               */
--              vm1->size = parent->size - size;
--              vm1->addr = (void *) (v_addr + size);
--              vm1->next = parent->next;
--
--              parent->size = size;
--              parent->next = vm1;
--              new_vm = parent;
--      } else if (v_addr + size == (unsigned long) parent->addr + 
--                      parent->size) {
--              /* Allocate new vm_struct to represent child, use existing
--               * parent one for remainder of parent range
--               */
--              vm1->size = size;
--              vm1->addr = (void *) v_addr;
--              vm1->next = parent->next;
--              new_vm = vm1;
--
--              parent->size -= size;
--              parent->next = vm1;
--      } else {
--              /* Allocate two new vm_structs for the new child and 
--               * uppermost remainder, and use existing parent one for the
--               * lower remainder of parent range
--               */
--              vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL);
--              if (vm2 == NULL) {
--                      printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
--                      kfree(vm1);
--                      return NULL;
--              }
--
--              vm1->size = size;
--              vm1->addr = (void *) v_addr;
--              vm1->next = vm2;
--              new_vm = vm1;
--
--              vm2->size = ((unsigned long) parent->addr + parent->size) - 
--                              (v_addr + size);
--              vm2->addr = (void *) v_addr + size;
--              vm2->next = parent->next;
--
--              parent->size = v_addr - (unsigned long) parent->addr;
--              parent->next = vm1;
--      }
--
--      return new_vm;
--}
--
--static struct vm_struct * __add_new_im_area(unsigned long req_addr, 
--                                          unsigned long size)
--{
--      struct vm_struct **p, *tmp, *area;
--              
--      for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
--              if (req_addr + size <= (unsigned long)tmp->addr)
--                      break;
--      }
--      
--      area = kmalloc(sizeof(*area), GFP_KERNEL);
--      if (!area)
--              return NULL;
--      area->flags = 0;
--      area->addr = (void *)req_addr;
--      area->size = size;
--      area->next = *p;
--      *p = area;
--
--      return area;
--}
--
--static struct vm_struct * __im_get_area(unsigned long req_addr, 
--                                      unsigned long size,
--                                      int criteria)
--{
--      struct vm_struct *tmp;
--      int status;
--
--      status = im_region_status(req_addr, size, &tmp);
--      if ((criteria & status) == 0) {
--              return NULL;
--      }
--      
--      switch (status) {
--      case IM_REGION_UNUSED:
--              tmp = __add_new_im_area(req_addr, size);
--              break;
--      case IM_REGION_SUBSET:
--              tmp = split_im_region(req_addr, size, tmp);
--              break;
--      case IM_REGION_EXISTS:
--              /* Return requested region */
--              break;
--      case IM_REGION_SUPERSET:
--              /* Return first existing subset of requested region */
--              break;
--      default:
--              printk(KERN_ERR "%s() unexpected imalloc region status\n",
--                              __FUNCTION__);
--              tmp = NULL;
--      }
--
--      return tmp;
--}
--
--struct vm_struct * im_get_free_area(unsigned long size)
--{
--      struct vm_struct *area;
--      unsigned long addr;
--      
--      mutex_lock(&imlist_mutex);
--      if (get_free_im_addr(size, &addr)) {
--              printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n",
--                              __FUNCTION__, size);
--              area = NULL;
--              goto next_im_done;
--      }
--
--      area = __im_get_area(addr, size, IM_REGION_UNUSED);
--      if (area == NULL) {
--              printk(KERN_ERR 
--                     "%s() cannot obtain area for addr 0x%lx size 0x%lx\n",
--                      __FUNCTION__, addr, size);
--      }
--next_im_done:
--      mutex_unlock(&imlist_mutex);
--      return area;
--}
--
--struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
--              int criteria)
--{
--      struct vm_struct *area;
--
--      mutex_lock(&imlist_mutex);
--      area = __im_get_area(v_addr, size, criteria);
--      mutex_unlock(&imlist_mutex);
--      return area;
--}
--
--void im_free(void * addr)
--{
--      struct vm_struct **p, *tmp;
--  
--      if (!addr)
--              return;
--      if ((unsigned long) addr & ~PAGE_MASK) {
--              printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__,                        addr);
--              return;
--      }
--      mutex_lock(&imlist_mutex);
--      for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
--              if (tmp->addr == addr) {
--                      *p = tmp->next;
--                      unmap_vm_area(tmp);
--                      kfree(tmp);
--                      mutex_unlock(&imlist_mutex);
--                      return;
--              }
--      }
--      mutex_unlock(&imlist_mutex);
--      printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
--                      addr);
--}
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/init_32.c linux-2.6.22-590/arch/powerpc/mm/init_32.c
---- linux-2.6.22-570/arch/powerpc/mm/init_32.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/init_32.c 2008-01-02 13:56:37.000000000 -0500
-@@ -5,7 +5,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
-  *
-  *  Derived from "arch/i386/mm/init.c"
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/init_64.c linux-2.6.22-590/arch/powerpc/mm/init_64.c
---- linux-2.6.22-570/arch/powerpc/mm/init_64.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/init_64.c 2008-01-02 13:56:37.000000000 -0500
-@@ -5,7 +5,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  *  Derived from "arch/i386/mm/init.c"
-  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/mem.c linux-2.6.22-590/arch/powerpc/mm/mem.c
---- linux-2.6.22-570/arch/powerpc/mm/mem.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/mem.c     2008-01-02 13:56:37.000000000 -0500
-@@ -5,7 +5,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
-  *
-  *  Derived from "arch/i386/mm/init.c"
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/mmu_context_32.c linux-2.6.22-590/arch/powerpc/mm/mmu_context_32.c
---- linux-2.6.22-570/arch/powerpc/mm/mmu_context_32.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/mmu_context_32.c  2008-01-02 13:56:37.000000000 -0500
-@@ -11,7 +11,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  *  Derived from "arch/i386/mm/init.c"
-  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/mmu_decl.h linux-2.6.22-590/arch/powerpc/mm/mmu_decl.h
---- linux-2.6.22-570/arch/powerpc/mm/mmu_decl.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/mmu_decl.h        2008-01-02 13:56:37.000000000 -0500
-@@ -8,7 +8,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  *  Derived from "arch/i386/mm/init.c"
-  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
-@@ -40,8 +39,8 @@
- extern unsigned long ioremap_base;
- extern unsigned int rtas_data, rtas_size;
--struct _PTE;
--extern struct _PTE *Hash, *Hash_end;
-+struct hash_pte;
-+extern struct hash_pte *Hash, *Hash_end;
- extern unsigned long Hash_size, Hash_mask;
- extern unsigned int num_tlbcam_entries;
-@@ -90,16 +89,4 @@
-       else
-               _tlbie(va);
- }
--#else /* CONFIG_PPC64 */
--/* imalloc region types */
--#define IM_REGION_UNUSED      0x1
--#define IM_REGION_SUBSET      0x2
--#define IM_REGION_EXISTS      0x4
--#define IM_REGION_OVERLAP     0x8
--#define IM_REGION_SUPERSET    0x10
--
--extern struct vm_struct * im_get_free_area(unsigned long size);
--extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
--                                    int region_type);
--extern void im_free(void *addr);
- #endif
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/pgtable_32.c linux-2.6.22-590/arch/powerpc/mm/pgtable_32.c
---- linux-2.6.22-570/arch/powerpc/mm/pgtable_32.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/pgtable_32.c      2008-01-02 13:56:37.000000000 -0500
-@@ -8,7 +8,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  *  Derived from "arch/i386/mm/init.c"
-  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
-@@ -37,7 +36,6 @@
- unsigned long ioremap_base;
- unsigned long ioremap_bot;
- EXPORT_SYMBOL(ioremap_bot);   /* aka VMALLOC_END */
--int io_bat_index;
- #if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
- #define HAVE_BATS     1
-@@ -300,51 +298,6 @@
-       }
- }
--/* is x a power of 4? */
--#define is_power_of_4(x)      is_power_of_2(x) && (ffs(x) & 1)
--
--/*
-- * Set up a mapping for a block of I/O.
-- * virt, phys, size must all be page-aligned.
-- * This should only be called before ioremap is called.
-- */
--void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
--                           unsigned int size, int flags)
--{
--      int i;
--
--      if (virt > KERNELBASE && virt < ioremap_bot)
--              ioremap_bot = ioremap_base = virt;
--
--#ifdef HAVE_BATS
--      /*
--       * Use a BAT for this if possible...
--       */
--      if (io_bat_index < 2 && is_power_of_2(size)
--          && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
--              setbat(io_bat_index, virt, phys, size, flags);
--              ++io_bat_index;
--              return;
--      }
--#endif /* HAVE_BATS */
--
--#ifdef HAVE_TLBCAM
--      /*
--       * Use a CAM for this if possible...
--       */
--      if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size)
--          && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
--              settlbcam(tlbcam_index, virt, phys, size, flags, 0);
--              ++tlbcam_index;
--              return;
--      }
--#endif /* HAVE_TLBCAM */
--
--      /* No BATs available, put it in the page tables. */
--      for (i = 0; i < size; i += PAGE_SIZE)
--              map_page(virt + i, phys + i, flags);
--}
--
- /* Scan the real Linux page tables and return a PTE pointer for
-  * a virtual address in a context.
-  * Returns true (1) if PTE was found, zero otherwise.  The pointer to
-@@ -379,82 +332,6 @@
-         return(retval);
- }
--/* Find physical address for this virtual address.  Normally used by
-- * I/O functions, but anyone can call it.
-- */
--unsigned long iopa(unsigned long addr)
--{
--      unsigned long pa;
--
--      /* I don't know why this won't work on PMacs or CHRP.  It
--       * appears there is some bug, or there is some implicit
--       * mapping done not properly represented by BATs or in page
--       * tables.......I am actively working on resolving this, but
--       * can't hold up other stuff.  -- Dan
--       */
--      pte_t *pte;
--      struct mm_struct *mm;
--
--      /* Check the BATs */
--      pa = v_mapped_by_bats(addr);
--      if (pa)
--              return pa;
--
--      /* Allow mapping of user addresses (within the thread)
--       * for DMA if necessary.
--       */
--      if (addr < TASK_SIZE)
--              mm = current->mm;
--      else
--              mm = &init_mm;
--
--      pa = 0;
--      if (get_pteptr(mm, addr, &pte, NULL)) {
--              pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
--              pte_unmap(pte);
--      }
--
--      return(pa);
--}
--
--/* This is will find the virtual address for a physical one....
-- * Swiped from APUS, could be dangerous :-).
-- * This is only a placeholder until I really find a way to make this
-- * work.  -- Dan
-- */
--unsigned long
--mm_ptov (unsigned long paddr)
--{
--      unsigned long ret;
--#if 0
--      if (paddr < 16*1024*1024)
--              ret = ZTWO_VADDR(paddr);
--      else {
--              int i;
--
--              for (i = 0; i < kmap_chunk_count;){
--                      unsigned long phys = kmap_chunks[i++];
--                      unsigned long size = kmap_chunks[i++];
--                      unsigned long virt = kmap_chunks[i++];
--                      if (paddr >= phys
--                          && paddr < (phys + size)){
--                              ret = virt + paddr - phys;
--                              goto exit;
--                      }
--              }
--      
--              ret = (unsigned long) __va(paddr);
--      }
--exit:
--#ifdef DEBUGPV
--      printk ("PTOV(%lx)=%lx\n", paddr, ret);
--#endif
--#else
--      ret = (unsigned long)paddr + KERNELBASE;
--#endif
--      return ret;
--}
--
- #ifdef CONFIG_DEBUG_PAGEALLOC
- static int __change_page_attr(struct page *page, pgprot_t prot)
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/pgtable_64.c linux-2.6.22-590/arch/powerpc/mm/pgtable_64.c
---- linux-2.6.22-570/arch/powerpc/mm/pgtable_64.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/pgtable_64.c      2008-01-02 13:56:37.000000000 -0500
-@@ -7,7 +7,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@samba.org)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  *  Derived from "arch/i386/mm/init.c"
-  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
-@@ -34,41 +33,27 @@
- #include <linux/stddef.h>
- #include <linux/vmalloc.h>
- #include <linux/init.h>
--#include <linux/delay.h>
--#include <linux/bootmem.h>
--#include <linux/highmem.h>
--#include <linux/idr.h>
--#include <linux/nodemask.h>
--#include <linux/module.h>
- #include <asm/pgalloc.h>
- #include <asm/page.h>
- #include <asm/prom.h>
--#include <asm/lmb.h>
--#include <asm/rtas.h>
- #include <asm/io.h>
- #include <asm/mmu_context.h>
- #include <asm/pgtable.h>
- #include <asm/mmu.h>
--#include <asm/uaccess.h>
- #include <asm/smp.h>
- #include <asm/machdep.h>
- #include <asm/tlb.h>
--#include <asm/eeh.h>
- #include <asm/processor.h>
--#include <asm/mmzone.h>
- #include <asm/cputable.h>
- #include <asm/sections.h>
- #include <asm/system.h>
--#include <asm/iommu.h>
- #include <asm/abs_addr.h>
--#include <asm/vdso.h>
- #include <asm/firmware.h>
- #include "mmu_decl.h"
--unsigned long ioremap_bot = IMALLOC_BASE;
--static unsigned long phbs_io_bot = PHBS_IO_BASE;
-+unsigned long ioremap_bot = IOREMAP_BASE;
- /*
-  * map_io_page currently only called by __ioremap
-@@ -102,8 +87,8 @@
-                * entry in the hardware page table.
-                *
-                */
--              if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
--                                    mmu_io_psize)) {
-+              if (htab_bolt_mapping(ea, (unsigned long)ea + PAGE_SIZE,
-+                                    pa, flags, mmu_io_psize)) {
-                       printk(KERN_ERR "Failed to do bolted mapping IO "
-                              "memory at %016lx !\n", pa);
-                       return -ENOMEM;
-@@ -113,8 +98,11 @@
- }
--static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa,
--                          unsigned long ea, unsigned long size,
-+/**
-+ * __ioremap_at - Low level function to establish the page tables
-+ *                for an IO mapping
-+ */
-+void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size,
-                           unsigned long flags)
- {
-       unsigned long i;
-@@ -122,17 +110,35 @@
-       if ((flags & _PAGE_PRESENT) == 0)
-               flags |= pgprot_val(PAGE_KERNEL);
-+      WARN_ON(pa & ~PAGE_MASK);
-+      WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
-+      WARN_ON(size & ~PAGE_MASK);
-+
-       for (i = 0; i < size; i += PAGE_SIZE)
--              if (map_io_page(ea+i, pa+i, flags))
-+              if (map_io_page((unsigned long)ea+i, pa+i, flags))
-                       return NULL;
--      return (void __iomem *) (ea + (addr & ~PAGE_MASK));
-+      return (void __iomem *)ea;
-+}
-+
-+/**
-+ * __iounmap_from - Low level function to tear down the page tables
-+ *                  for an IO mapping. This is used for mappings that
-+ *                  are manipulated manually, like partial unmapping of
-+ *                  PCI IOs or ISA space.
-+ */
-+void __iounmap_at(void *ea, unsigned long size)
-+{
-+      WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
-+      WARN_ON(size & ~PAGE_MASK);
-+
-+      unmap_kernel_range((unsigned long)ea, size);
- }
- void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
-                        unsigned long flags)
- {
--      unsigned long pa, ea;
-+      phys_addr_t paligned;
-       void __iomem *ret;
-       /*
-@@ -144,27 +150,30 @@
-        * IMALLOC_END
-        * 
-        */
--      pa = addr & PAGE_MASK;
--      size = PAGE_ALIGN(addr + size) - pa;
-+      paligned = addr & PAGE_MASK;
-+      size = PAGE_ALIGN(addr + size) - paligned;
--      if ((size == 0) || (pa == 0))
-+      if ((size == 0) || (paligned == 0))
-               return NULL;
-       if (mem_init_done) {
-               struct vm_struct *area;
--              area = im_get_free_area(size);
-+
-+              area = __get_vm_area(size, VM_IOREMAP,
-+                                   ioremap_bot, IOREMAP_END);
-               if (area == NULL)
-                       return NULL;
--              ea = (unsigned long)(area->addr);
--              ret = __ioremap_com(addr, pa, ea, size, flags);
-+              ret = __ioremap_at(paligned, area->addr, size, flags);
-               if (!ret)
--                      im_free(area->addr);
-+                      vunmap(area->addr);
-       } else {
--              ea = ioremap_bot;
--              ret = __ioremap_com(addr, pa, ea, size, flags);
-+              ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags);
-               if (ret)
-                       ioremap_bot += size;
-       }
-+
-+      if (ret)
-+              ret += addr & ~PAGE_MASK;
-       return ret;
- }
-@@ -187,62 +196,9 @@
- }
--#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
--
--int __ioremap_explicit(phys_addr_t pa, unsigned long ea,
--                     unsigned long size, unsigned long flags)
--{
--      struct vm_struct *area;
--      void __iomem *ret;
--      
--      /* For now, require page-aligned values for pa, ea, and size */
--      if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) ||
--          !IS_PAGE_ALIGNED(size)) {
--              printk(KERN_ERR "unaligned value in %s\n", __FUNCTION__);
--              return 1;
--      }
--      
--      if (!mem_init_done) {
--              /* Two things to consider in this case:
--               * 1) No records will be kept (imalloc, etc) that the region
--               *    has been remapped
--               * 2) It won't be easy to iounmap() the region later (because
--               *    of 1)
--               */
--              ;
--      } else {
--              area = im_get_area(ea, size,
--                      IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS);
--              if (area == NULL) {
--                      /* Expected when PHB-dlpar is in play */
--                      return 1;
--              }
--              if (ea != (unsigned long) area->addr) {
--                      printk(KERN_ERR "unexpected addr return from "
--                             "im_get_area\n");
--                      return 1;
--              }
--      }
--      
--      ret = __ioremap_com(pa, pa, ea, size, flags);
--      if (ret == NULL) {
--              printk(KERN_ERR "ioremap_explicit() allocation failure !\n");
--              return 1;
--      }
--      if (ret != (void *) ea) {
--              printk(KERN_ERR "__ioremap_com() returned unexpected addr\n");
--              return 1;
--      }
--
--      return 0;
--}
--
- /*  
-  * Unmap an IO region and remove it from imalloc'd list.
-  * Access to IO memory should be serialized by driver.
-- * This code is modeled after vmalloc code - unmap_vm_area()
-- *
-- * XXX        what about calls before mem_init_done (ie python_countermeasures())
-  */
- void __iounmap(volatile void __iomem *token)
- {
-@@ -251,9 +207,14 @@
-       if (!mem_init_done)
-               return;
-       
--      addr = (void *) ((unsigned long __force) token & PAGE_MASK);
--
--      im_free(addr);
-+      addr = (void *) ((unsigned long __force)
-+                       PCI_FIX_ADDR(token) & PAGE_MASK);
-+      if ((unsigned long)addr < ioremap_bot) {
-+              printk(KERN_WARNING "Attempt to iounmap early bolted mapping"
-+                     " at 0x%p\n", addr);
-+              return;
-+      }
-+      vunmap(addr);
- }
- void iounmap(volatile void __iomem *token)
-@@ -264,77 +225,8 @@
-               __iounmap(token);
- }
--static int iounmap_subset_regions(unsigned long addr, unsigned long size)
--{
--      struct vm_struct *area;
--
--      /* Check whether subsets of this region exist */
--      area = im_get_area(addr, size, IM_REGION_SUPERSET);
--      if (area == NULL)
--              return 1;
--
--      while (area) {
--              iounmap((void __iomem *) area->addr);
--              area = im_get_area(addr, size,
--                              IM_REGION_SUPERSET);
--      }
--
--      return 0;
--}
--
--int __iounmap_explicit(volatile void __iomem *start, unsigned long size)
--{
--      struct vm_struct *area;
--      unsigned long addr;
--      int rc;
--      
--      addr = (unsigned long __force) start & PAGE_MASK;
--
--      /* Verify that the region either exists or is a subset of an existing
--       * region.  In the latter case, split the parent region to create 
--       * the exact region 
--       */
--      area = im_get_area(addr, size, 
--                          IM_REGION_EXISTS | IM_REGION_SUBSET);
--      if (area == NULL) {
--              /* Determine whether subset regions exist.  If so, unmap */
--              rc = iounmap_subset_regions(addr, size);
--              if (rc) {
--                      printk(KERN_ERR
--                             "%s() cannot unmap nonexistent range 0x%lx\n",
--                              __FUNCTION__, addr);
--                      return 1;
--              }
--      } else {
--              iounmap((void __iomem *) area->addr);
--      }
--      /*
--       * FIXME! This can't be right:
--      iounmap(area->addr);
--       * Maybe it should be "iounmap(area);"
--       */
--      return 0;
--}
--
- EXPORT_SYMBOL(ioremap);
- EXPORT_SYMBOL(ioremap_flags);
- EXPORT_SYMBOL(__ioremap);
- EXPORT_SYMBOL(iounmap);
- EXPORT_SYMBOL(__iounmap);
--
--static DEFINE_SPINLOCK(phb_io_lock);
--
--void __iomem * reserve_phb_iospace(unsigned long size)
--{
--      void __iomem *virt_addr;
--              
--      if (phbs_io_bot >= IMALLOC_BASE) 
--              panic("reserve_phb_iospace(): phb io space overflow\n");
--                      
--      spin_lock(&phb_io_lock);
--      virt_addr = (void __iomem *) phbs_io_bot;
--      phbs_io_bot += size;
--      spin_unlock(&phb_io_lock);
--
--      return virt_addr;
--}
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/ppc_mmu_32.c linux-2.6.22-590/arch/powerpc/mm/ppc_mmu_32.c
---- linux-2.6.22-570/arch/powerpc/mm/ppc_mmu_32.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/ppc_mmu_32.c      2008-01-02 13:56:37.000000000 -0500
-@@ -11,7 +11,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  *  Derived from "arch/i386/mm/init.c"
-  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
-@@ -35,12 +34,12 @@
- #include "mmu_decl.h"
--PTE *Hash, *Hash_end;
-+struct hash_pte *Hash, *Hash_end;
- unsigned long Hash_size, Hash_mask;
- unsigned long _SDR1;
- union ubat {                  /* BAT register values to be loaded */
--      BAT     bat;
-+      struct ppc_bat bat;
-       u32     word[2];
- } BATS[8][2];                 /* 8 pairs of IBAT, DBAT */
-@@ -245,7 +244,7 @@
-       cacheable_memzero(Hash, Hash_size);
-       _SDR1 = __pa(Hash) | SDR1_LOW_BITS;
--      Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
-+      Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size);
-       printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
-              total_memory >> 20, Hash_size >> 10, Hash);
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/tlb_32.c linux-2.6.22-590/arch/powerpc/mm/tlb_32.c
---- linux-2.6.22-570/arch/powerpc/mm/tlb_32.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/tlb_32.c  2008-01-02 13:56:37.000000000 -0500
-@@ -11,7 +11,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  *  Derived from "arch/i386/mm/init.c"
-  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
-diff -Nurb linux-2.6.22-570/arch/powerpc/mm/tlb_64.c linux-2.6.22-590/arch/powerpc/mm/tlb_64.c
---- linux-2.6.22-570/arch/powerpc/mm/tlb_64.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/mm/tlb_64.c  2008-01-02 13:56:37.000000000 -0500
-@@ -8,7 +8,6 @@
-  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
-  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
-  *    Copyright (C) 1996 Paul Mackerras
-- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
-  *
-  *  Derived from "arch/i386/mm/init.c"
-  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
-@@ -239,3 +238,59 @@
-       pte_free_submit(*batchp);
-       *batchp = NULL;
- }
-+
-+/**
-+ * __flush_hash_table_range - Flush all HPTEs for a given address range
-+ *                            from the hash table (and the TLB). But keeps
-+ *                            the linux PTEs intact.
-+ *
-+ * @mm                : mm_struct of the target address space (generally init_mm)
-+ * @start     : starting address
-+ * @end         : ending address (not included in the flush)
-+ *
-+ * This function is mostly to be used by some IO hotplug code in order
-+ * to remove all hash entries from a given address range used to map IO
-+ * space on a removed PCI-PCI bidge without tearing down the full mapping
-+ * since 64K pages may overlap with other bridges when using 64K pages
-+ * with 4K HW pages on IO space.
-+ *
-+ * Because of that usage pattern, it's only available with CONFIG_HOTPLUG
-+ * and is implemented for small size rather than speed.
-+ */
-+#ifdef CONFIG_HOTPLUG
-+
-+void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
-+                            unsigned long end)
-+{
-+      unsigned long flags;
-+
-+      start = _ALIGN_DOWN(start, PAGE_SIZE);
-+      end = _ALIGN_UP(end, PAGE_SIZE);
-+
-+      BUG_ON(!mm->pgd);
-+
-+      /* Note: Normally, we should only ever use a batch within a
-+       * PTE locked section. This violates the rule, but will work
-+       * since we don't actually modify the PTEs, we just flush the
-+       * hash while leaving the PTEs intact (including their reference
-+       * to being hashed). This is not the most performance oriented
-+       * way to do things but is fine for our needs here.
-+       */
-+      local_irq_save(flags);
-+      arch_enter_lazy_mmu_mode();
-+      for (; start < end; start += PAGE_SIZE) {
-+              pte_t *ptep = find_linux_pte(mm->pgd, start);
-+              unsigned long pte;
-+
-+              if (ptep == NULL)
-+                      continue;
-+              pte = pte_val(*ptep);
-+              if (!(pte & _PAGE_HASHPTE))
-+                      continue;
-+              hpte_need_flush(mm, start, ptep, pte, 0);
-+      }
-+      arch_leave_lazy_mmu_mode();
-+      local_irq_restore(flags);
-+}
-+
-+#endif /* CONFIG_HOTPLUG */
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/Kconfig linux-2.6.22-590/arch/powerpc/platforms/Kconfig
---- linux-2.6.22-570/arch/powerpc/platforms/Kconfig    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/Kconfig    2008-01-02 13:56:37.000000000 -0500
-@@ -16,13 +16,6 @@
-       bool "Embedded 6xx/7xx/7xxx-based board"
-       depends on PPC32 && (BROKEN||BROKEN_ON_SMP)
--config APUS
--      bool "Amiga-APUS"
--      depends on PPC32 && BROKEN
--      help
--        Select APUS if configuring for a PowerUP Amiga.
--        More information is available at:
--        <http://linux-apus.sourceforge.net/>.
- endchoice
- source "arch/powerpc/platforms/pseries/Kconfig"
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/Kconfig.cputype linux-2.6.22-590/arch/powerpc/platforms/Kconfig.cputype
---- linux-2.6.22-570/arch/powerpc/platforms/Kconfig.cputype    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/platforms/Kconfig.cputype    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,252 @@
-+config PPC64
-+      bool "64-bit kernel"
-+      default n
-+      help
-+        This option selects whether a 32-bit or a 64-bit kernel
-+        will be built.
-+
-+menu "Processor support"
-+choice
-+      prompt "Processor Type"
-+      depends on PPC32
-+      default 6xx
-+
-+config CLASSIC32
-+      bool "52xx/6xx/7xx/74xx"
-+      select PPC_FPU
-+      select 6xx
-+      help
-+        There are four families of PowerPC chips supported.  The more common
-+        types (601, 603, 604, 740, 750, 7400), the Motorola embedded
-+        versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC
-+        embedded versions (403 and 405) and the high end 64 bit Power
-+        processors (POWER 3, POWER4, and IBM PPC970 also known as G5).
-+
-+        This option is the catch-all for 6xx types, including some of the
-+        embedded versions.  Unless there is see an option for the specific
-+        chip family you are using, you want this option.
-+
-+        You do not want this if you are building a kernel for a 64 bit
-+        IBM RS/6000 or an Apple G5, choose 6xx.
-+
-+        If unsure, select this option
-+
-+        Note that the kernel runs in 32-bit mode even on 64-bit chips.
-+
-+config PPC_82xx
-+      bool "Freescale 82xx"
-+      select 6xx
-+      select PPC_FPU
-+
-+config PPC_83xx
-+      bool "Freescale 83xx"
-+      select 6xx
-+      select FSL_SOC
-+      select 83xx
-+      select PPC_FPU
-+      select WANT_DEVICE_TREE
-+
-+config PPC_85xx
-+      bool "Freescale 85xx"
-+      select E500
-+      select FSL_SOC
-+      select 85xx
-+      select WANT_DEVICE_TREE
-+
-+config PPC_86xx
-+      bool "Freescale 86xx"
-+      select 6xx
-+      select FSL_SOC
-+      select FSL_PCIE
-+      select PPC_FPU
-+      select ALTIVEC
-+      help
-+        The Freescale E600 SoCs have 74xx cores.
-+
-+config PPC_8xx
-+      bool "Freescale 8xx"
-+      select FSL_SOC
-+      select 8xx
-+
-+config 40x
-+      bool "AMCC 40x"
-+      select PPC_DCR_NATIVE
-+
-+config 44x
-+      bool "AMCC 44x"
-+      select PPC_DCR_NATIVE
-+      select WANT_DEVICE_TREE
-+
-+config E200
-+      bool "Freescale e200"
-+
-+endchoice
-+
-+config POWER4_ONLY
-+      bool "Optimize for POWER4"
-+      depends on PPC64
-+      default n
-+      ---help---
-+        Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
-+        The resulting binary will not work on POWER3 or RS64 processors
-+        when compiled with binutils 2.15 or later.
-+
-+config POWER3
-+      bool
-+      depends on PPC64
-+      default y if !POWER4_ONLY
-+
-+config POWER4
-+      depends on PPC64
-+      def_bool y
-+
-+config 6xx
-+      bool
-+
-+# this is temp to handle compat with arch=ppc
-+config 8xx
-+      bool
-+
-+# this is temp to handle compat with arch=ppc
-+config 83xx
-+      bool
-+
-+# this is temp to handle compat with arch=ppc
-+config 85xx
-+      bool
-+
-+config E500
-+      bool
-+
-+config PPC_FPU
-+      bool
-+      default y if PPC64
-+
-+config 4xx
-+      bool
-+      depends on 40x || 44x
-+      default y
-+
-+config BOOKE
-+      bool
-+      depends on E200 || E500 || 44x
-+      default y
-+
-+config FSL_BOOKE
-+      bool
-+      depends on E200 || E500
-+      default y
-+
-+config PTE_64BIT
-+      bool
-+      depends on 44x || E500
-+      default y if 44x
-+      default y if E500 && PHYS_64BIT
-+
-+config PHYS_64BIT
-+      bool 'Large physical address support' if E500
-+      depends on 44x || E500
-+      select RESOURCES_64BIT
-+      default y if 44x
-+      ---help---
-+        This option enables kernel support for larger than 32-bit physical
-+        addresses.  This features is not be available on all e500 cores.
-+
-+        If in doubt, say N here.
-+
-+config ALTIVEC
-+      bool "AltiVec Support"
-+      depends on CLASSIC32 || POWER4
-+      ---help---
-+        This option enables kernel support for the Altivec extensions to the
-+        PowerPC processor. The kernel currently supports saving and restoring
-+        altivec registers, and turning on the 'altivec enable' bit so user
-+        processes can execute altivec instructions.
-+
-+        This option is only usefully if you have a processor that supports
-+        altivec (G4, otherwise known as 74xx series), but does not have
-+        any affect on a non-altivec cpu (it does, however add code to the
-+        kernel).
-+
-+        If in doubt, say Y here.
-+
-+config SPE
-+      bool "SPE Support"
-+      depends on E200 || E500
-+      default y
-+      ---help---
-+        This option enables kernel support for the Signal Processing
-+        Extensions (SPE) to the PowerPC processor. The kernel currently
-+        supports saving and restoring SPE registers, and turning on the
-+        'spe enable' bit so user processes can execute SPE instructions.
-+
-+        This option is only useful if you have a processor that supports
-+        SPE (e500, otherwise known as 85xx series), but does not have any
-+        effect on a non-spe cpu (it does, however add code to the kernel).
-+
-+        If in doubt, say Y here.
-+
-+config PPC_STD_MMU
-+      bool
-+      depends on 6xx || POWER3 || POWER4 || PPC64
-+      default y
-+
-+config PPC_STD_MMU_32
-+      def_bool y
-+      depends on PPC_STD_MMU && PPC32
-+
-+config PPC_MM_SLICES
-+      bool
-+      default y if HUGETLB_PAGE
-+      default n
-+
-+config VIRT_CPU_ACCOUNTING
-+      bool "Deterministic task and CPU time accounting"
-+      depends on PPC64
-+      default y
-+      help
-+        Select this option to enable more accurate task and CPU time
-+        accounting.  This is done by reading a CPU counter on each
-+        kernel entry and exit and on transitions within the kernel
-+        between system, softirq and hardirq state, so there is a
-+        small performance impact.  This also enables accounting of
-+        stolen time on logically-partitioned systems running on
-+        IBM POWER5-based machines.
-+
-+        If in doubt, say Y here.
-+
-+config SMP
-+      depends on PPC_STD_MMU
-+      bool "Symmetric multi-processing support"
-+      ---help---
-+        This enables support for systems with more than one CPU. If you have
-+        a system with only one CPU, say N. If you have a system with more
-+        than one CPU, say Y.  Note that the kernel does not currently
-+        support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
-+        since they have inadequate hardware support for multiprocessor
-+        operation.
-+
-+        If you say N here, the kernel will run on single and multiprocessor
-+        machines, but will use only one CPU of a multiprocessor machine. If
-+        you say Y here, the kernel will run on single-processor machines.
-+        On a single-processor machine, the kernel will run faster if you say
-+        N here.
-+
-+        If you don't know what to do here, say N.
-+
-+config NR_CPUS
-+      int "Maximum number of CPUs (2-128)"
-+      range 2 128
-+      depends on SMP
-+      default "32" if PPC64
-+      default "4"
-+
-+config NOT_COHERENT_CACHE
-+      bool
-+      depends on 4xx || 8xx || E200
-+      default y
-+
-+config CONFIG_CHECK_CACHE_COHERENCY
-+      bool
-+
-+endmenu
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/apus/Kconfig linux-2.6.22-590/arch/powerpc/platforms/apus/Kconfig
---- linux-2.6.22-570/arch/powerpc/platforms/apus/Kconfig       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/apus/Kconfig       1969-12-31 19:00:00.000000000 -0500
-@@ -1,130 +0,0 @@
--
--config AMIGA
--      bool
--      depends on APUS
--      default y
--      help
--        This option enables support for the Amiga series of computers.
--
--config ZORRO
--      bool
--      depends on APUS
--      default y
--      help
--        This enables support for the Zorro bus in the Amiga. If you have
--        expansion cards in your Amiga that conform to the Amiga
--        AutoConfig(tm) specification, say Y, otherwise N. Note that even
--        expansion cards that do not fit in the Zorro slots but fit in e.g.
--        the CPU slot may fall in this category, so you have to say Y to let
--        Linux use these.
--
--config ABSTRACT_CONSOLE
--      bool
--      depends on APUS
--      default y
--
--config APUS_FAST_EXCEPT
--      bool
--      depends on APUS
--      default y
--
--config AMIGA_PCMCIA
--      bool "Amiga 1200/600 PCMCIA support"
--      depends on APUS && EXPERIMENTAL
--      help
--        Include support in the kernel for pcmcia on Amiga 1200 and Amiga
--        600. If you intend to use pcmcia cards say Y; otherwise say N.
--
--config AMIGA_BUILTIN_SERIAL
--      tristate "Amiga builtin serial support"
--      depends on APUS
--      help
--        If you want to use your Amiga's built-in serial port in Linux,
--        answer Y.
--
--        To compile this driver as a module, choose M here.
--
--config GVPIOEXT
--      tristate "GVP IO-Extender support"
--      depends on APUS
--      help
--        If you want to use a GVP IO-Extender serial card in Linux, say Y.
--        Otherwise, say N.
--
--config GVPIOEXT_LP
--      tristate "GVP IO-Extender parallel printer support"
--      depends on GVPIOEXT
--      help
--        Say Y to enable driving a printer from the parallel port on your
--        GVP IO-Extender card, N otherwise.
--
--config GVPIOEXT_PLIP
--      tristate "GVP IO-Extender PLIP support"
--      depends on GVPIOEXT
--      help
--        Say Y to enable doing IP over the parallel port on your GVP
--        IO-Extender card, N otherwise.
--
--config MULTIFACE_III_TTY
--      tristate "Multiface Card III serial support"
--      depends on APUS
--      help
--        If you want to use a Multiface III card's serial port in Linux,
--        answer Y.
--
--        To compile this driver as a module, choose M here.
--
--config A2232
--      tristate "Commodore A2232 serial support (EXPERIMENTAL)"
--      depends on EXPERIMENTAL && APUS
--      ---help---
--        This option supports the 2232 7-port serial card shipped with the
--        Amiga 2000 and other Zorro-bus machines, dating from 1989.  At
--        a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
--        each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
--        ports were connected with 8 pin DIN connectors on the card bracket,
--        for which 8 pin to DB25 adapters were supplied. The card also had
--        jumpers internally to toggle various pinning configurations.
--
--        This driver can be built as a module; but then "generic_serial"
--        will also be built as a module. This has to be loaded before
--        "ser_a2232". If you want to do this, answer M here.
--
--config WHIPPET_SERIAL
--      tristate "Hisoft Whippet PCMCIA serial support"
--      depends on AMIGA_PCMCIA
--      help
--        HiSoft has a web page at <http://www.hisoft.co.uk/>, but there
--        is no listing for the Whippet in their Amiga section.
--
--config APNE
--      tristate "PCMCIA NE2000 support"
--      depends on AMIGA_PCMCIA
--      help
--        If you have a PCMCIA NE2000 compatible adapter, say Y.  Otherwise,
--        say N.
--
--        To compile this driver as a module, choose M here: the
--        module will be called apne.
--
--config SERIAL_CONSOLE
--      bool "Support for serial port console"
--      depends on APUS && (AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y)
--
--config HEARTBEAT
--      bool "Use power LED as a heartbeat"
--      depends on APUS
--      help
--        Use the power-on LED on your machine as a load meter.  The exact
--        behavior is platform-dependent, but normally the flash frequency is
--        a hyperbolic function of the 5-minute load average.
--
--config PROC_HARDWARE
--      bool "/proc/hardware support"
--      depends on APUS
--
--source "drivers/zorro/Kconfig"
--
--config PCI_PERMEDIA
--      bool "PCI for Permedia2"
--      depends on !4xx && !8xx && APUS
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/cell/io-workarounds.c linux-2.6.22-590/arch/powerpc/platforms/cell/io-workarounds.c
---- linux-2.6.22-570/arch/powerpc/platforms/cell/io-workarounds.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/cell/io-workarounds.c      2008-01-02 13:56:37.000000000 -0500
-@@ -102,7 +102,7 @@
-               vaddr = (unsigned long)PCI_FIX_ADDR(addr);
-               /* Check if it's in allowed range for  PIO */
--              if (vaddr < PHBS_IO_BASE || vaddr >= IMALLOC_BASE)
-+              if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END)
-                       return;
-               /* Try to find a PTE. If not, clear the paddr, we'll do
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/cell/spufs/file.c linux-2.6.22-590/arch/powerpc/platforms/cell/spufs/file.c
---- linux-2.6.22-570/arch/powerpc/platforms/cell/spufs/file.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/cell/spufs/file.c  2008-01-02 13:56:37.000000000 -0500
-@@ -28,6 +28,7 @@
- #include <linux/pagemap.h>
- #include <linux/poll.h>
- #include <linux/ptrace.h>
-+#include <linux/seq_file.h>
- #include <asm/io.h>
- #include <asm/semaphore.h>
-@@ -39,6 +40,7 @@
- #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
-+
- static int
- spufs_mem_open(struct inode *inode, struct file *file)
- {
-@@ -1797,6 +1799,29 @@
-       return 0;
- }
-+static int spufs_caps_show(struct seq_file *s, void *private)
-+{
-+      struct spu_context *ctx = s->private;
-+
-+      if (!(ctx->flags & SPU_CREATE_NOSCHED))
-+              seq_puts(s, "sched\n");
-+      if (!(ctx->flags & SPU_CREATE_ISOLATE))
-+              seq_puts(s, "step\n");
-+      return 0;
-+}
-+
-+static int spufs_caps_open(struct inode *inode, struct file *file)
-+{
-+      return single_open(file, spufs_caps_show, SPUFS_I(inode)->i_ctx);
-+}
-+
-+static const struct file_operations spufs_caps_fops = {
-+      .open           = spufs_caps_open,
-+      .read           = seq_read,
-+      .llseek         = seq_lseek,
-+      .release        = single_release,
-+};
-+
- static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
-                       char __user *buf, size_t len, loff_t *pos)
- {
-@@ -2015,6 +2040,7 @@
- };
- struct tree_descr spufs_dir_contents[] = {
-+      { "capabilities", &spufs_caps_fops, 0444, },
-       { "mem",  &spufs_mem_fops,  0666, },
-       { "regs", &spufs_regs_fops,  0666, },
-       { "mbox", &spufs_mbox_fops, 0444, },
-@@ -2050,6 +2076,7 @@
- };
- struct tree_descr spufs_dir_nosched_contents[] = {
-+      { "capabilities", &spufs_caps_fops, 0444, },
-       { "mem",  &spufs_mem_fops,  0666, },
-       { "mbox", &spufs_mbox_fops, 0444, },
-       { "ibox", &spufs_ibox_fops, 0444, },
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/cell/spufs/run.c linux-2.6.22-590/arch/powerpc/platforms/cell/spufs/run.c
---- linux-2.6.22-570/arch/powerpc/platforms/cell/spufs/run.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/cell/spufs/run.c   2008-01-02 13:56:37.000000000 -0500
-@@ -142,8 +142,12 @@
-                       runcntl = SPU_RUNCNTL_RUNNABLE;
-               ctx->ops->runcntl_write(ctx, runcntl);
-       } else {
-+              unsigned long mode = SPU_PRIVCNTL_MODE_NORMAL;
-               spu_start_tick(ctx);
-               ctx->ops->npc_write(ctx, *npc);
-+              if (test_thread_flag(TIF_SINGLESTEP))
-+                      mode = SPU_PRIVCNTL_MODE_SINGLE_STEP;
-+              out_be64(&ctx->spu->priv2->spu_privcntl_RW, mode);
-               ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
-       }
-@@ -334,7 +338,8 @@
-               ret = spu_process_events(ctx);
-       } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
--                                    SPU_STATUS_STOPPED_BY_HALT)));
-+                                    SPU_STATUS_STOPPED_BY_HALT |
-+                                     SPU_STATUS_SINGLE_STEP)));
-       ctx->ops->master_stop(ctx);
-       ret = spu_run_fini(ctx, npc, &status);
-@@ -344,10 +349,15 @@
-       if ((ret == 0) ||
-           ((ret == -ERESTARTSYS) &&
-            ((status & SPU_STATUS_STOPPED_BY_HALT) ||
-+            (status & SPU_STATUS_SINGLE_STEP) ||
-             ((status & SPU_STATUS_STOPPED_BY_STOP) &&
-              (status >> SPU_STOP_STATUS_SHIFT != 0x2104)))))
-               ret = status;
-+      /* Note: we don't need to force_sig SIGTRAP on single-step
-+       * since we have TIF_SINGLESTEP set, thus the kernel will do
-+       * it upon return from the syscall anyawy
-+       */
-       if ((status & SPU_STATUS_STOPPED_BY_STOP)
-           && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
-               force_sig(SIGTRAP, current);
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/iseries/call_hpt.h linux-2.6.22-590/arch/powerpc/platforms/iseries/call_hpt.h
---- linux-2.6.22-570/arch/powerpc/platforms/iseries/call_hpt.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/iseries/call_hpt.h 2008-01-02 13:56:37.000000000 -0500
-@@ -76,24 +76,25 @@
-       return compressedStatus;
- }
--static inline u64 HvCallHpt_findValid(hpte_t *hpte, u64 vpn)
-+static inline u64 HvCallHpt_findValid(struct hash_pte *hpte, u64 vpn)
- {
-       return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
- }
--static inline u64 HvCallHpt_findNextValid(hpte_t *hpte, u32 hpteIndex,
-+static inline u64 HvCallHpt_findNextValid(struct hash_pte *hpte, u32 hpteIndex,
-               u8 bitson, u8 bitsoff)
- {
-       return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
-                       bitson, bitsoff);
- }
--static inline void HvCallHpt_get(hpte_t *hpte, u32 hpteIndex)
-+static inline void HvCallHpt_get(struct hash_pte *hpte, u32 hpteIndex)
- {
-       HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
- }
--static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, hpte_t *hpte)
-+static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit,
-+                                       struct hash_pte *hpte)
- {
-       HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r);
- }
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/iseries/htab.c linux-2.6.22-590/arch/powerpc/platforms/iseries/htab.c
---- linux-2.6.22-570/arch/powerpc/platforms/iseries/htab.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/iseries/htab.c     2008-01-02 13:56:37.000000000 -0500
-@@ -44,7 +44,7 @@
-                        unsigned long vflags, int psize)
- {
-       long slot;
--      hpte_t lhpte;
-+      struct hash_pte lhpte;
-       int secondary = 0;
-       BUG_ON(psize != MMU_PAGE_4K);
-@@ -99,7 +99,7 @@
- static unsigned long iSeries_hpte_getword0(unsigned long slot)
- {
--      hpte_t hpte;
-+      struct hash_pte hpte;
-       HvCallHpt_get(&hpte, slot);
-       return hpte.v;
-@@ -144,7 +144,7 @@
- static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
-                                 unsigned long va, int psize, int local)
- {
--      hpte_t hpte;
-+      struct hash_pte hpte;
-       unsigned long want_v;
-       iSeries_hlock(slot);
-@@ -176,7 +176,7 @@
-  */
- static long iSeries_hpte_find(unsigned long vpn)
- {
--      hpte_t hpte;
-+      struct hash_pte hpte;
-       long slot;
-       /*
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/iseries/pci.c linux-2.6.22-590/arch/powerpc/platforms/iseries/pci.c
---- linux-2.6.22-570/arch/powerpc/platforms/iseries/pci.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/iseries/pci.c      2008-01-02 13:56:37.000000000 -0500
-@@ -742,6 +742,11 @@
-       /* Install IO hooks */
-       ppc_pci_io = iseries_pci_io;
-+      /* iSeries has no IO space in the common sense, it needs to set
-+       * the IO base to 0
-+       */
-+      pci_io_base = 0;
-+
-       if (root == NULL) {
-               printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
-                               "of device tree\n");
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/maple/pci.c linux-2.6.22-590/arch/powerpc/platforms/maple/pci.c
---- linux-2.6.22-570/arch/powerpc/platforms/maple/pci.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/maple/pci.c        2008-01-02 13:56:37.000000000 -0500
-@@ -519,23 +519,6 @@
-       DBG(" <- maple_pci_irq_fixup\n");
- }
--static void __init maple_fixup_phb_resources(void)
--{
--      struct pci_controller *hose, *tmp;
--      
--      list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
--              unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
--
--              hose->io_resource.start += offset;
--              hose->io_resource.end += offset;
--
--              printk(KERN_INFO "PCI Host %d, io start: %llx; io end: %llx\n",
--                     hose->global_number,
--                     (unsigned long long)hose->io_resource.start,
--                     (unsigned long long)hose->io_resource.end);
--      }
--}
--
- void __init maple_pci_init(void)
- {
-       struct device_node *np, *root;
-@@ -573,24 +556,6 @@
-       if (ht && add_bridge(ht) != 0)
-               of_node_put(ht);
--        /*
--         * We need to call pci_setup_phb_io for the HT bridge first
--         * so it gets the I/O port numbers starting at 0, and we
--         * need to call it for the AGP bridge after that so it gets
--         * small positive I/O port numbers.
--         */
--        if (u3_ht)
--                pci_setup_phb_io(u3_ht, 1);
--        if (u3_agp)
--                pci_setup_phb_io(u3_agp, 0);
--        if (u4_pcie)
--                pci_setup_phb_io(u4_pcie, 0);
--
--      /* Fixup the IO resources on our host bridges as the common code
--       * does it only for childs of the host bridges
--       */
--      maple_fixup_phb_resources();
--
-       /* Setup the linkage between OF nodes and PHBs */ 
-       pci_devs_phb_init();
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/pasemi/pci.c linux-2.6.22-590/arch/powerpc/platforms/pasemi/pci.c
---- linux-2.6.22-570/arch/powerpc/platforms/pasemi/pci.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/pasemi/pci.c       2008-01-02 13:56:37.000000000 -0500
-@@ -150,29 +150,11 @@
-       printk(KERN_INFO "Found PA-PXP PCI host bridge.\n");
-       /* Interpret the "ranges" property */
--      /* This also maps the I/O region and sets isa_io/mem_base */
-       pci_process_bridge_OF_ranges(hose, dev, 1);
--      pci_setup_phb_io(hose, 1);
-       return 0;
- }
--
--static void __init pas_fixup_phb_resources(void)
--{
--      struct pci_controller *hose, *tmp;
--
--      list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
--              unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
--              hose->io_resource.start += offset;
--              hose->io_resource.end += offset;
--              printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
--                     hose->global_number,
--                     hose->io_resource.start, hose->io_resource.end);
--      }
--}
--
--
- void __init pas_pci_init(void)
- {
-       struct device_node *np, *root;
-@@ -190,8 +172,6 @@
-       of_node_put(root);
--      pas_fixup_phb_resources();
--
-       /* Setup the linkage between OF nodes and PHBs */
-       pci_devs_phb_init();
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/powermac/pci.c linux-2.6.22-590/arch/powerpc/platforms/powermac/pci.c
---- linux-2.6.22-570/arch/powerpc/platforms/powermac/pci.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/powermac/pci.c     2008-01-02 13:56:37.000000000 -0500
-@@ -1006,19 +1006,6 @@
- #endif /* CONFIG_PPC32 */
- }
--#ifdef CONFIG_PPC64
--static void __init pmac_fixup_phb_resources(void)
--{
--      struct pci_controller *hose, *tmp;
--
--      list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
--              printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
--                     hose->global_number,
--                     hose->io_resource.start, hose->io_resource.end);
--      }
--}
--#endif
--
- void __init pmac_pci_init(void)
- {
-       struct device_node *np, *root;
-@@ -1053,25 +1040,6 @@
-       if (ht && add_bridge(ht) != 0)
-               of_node_put(ht);
--      /*
--       * We need to call pci_setup_phb_io for the HT bridge first
--       * so it gets the I/O port numbers starting at 0, and we
--       * need to call it for the AGP bridge after that so it gets
--       * small positive I/O port numbers.
--       */
--      if (u3_ht)
--              pci_setup_phb_io(u3_ht, 1);
--      if (u3_agp)
--              pci_setup_phb_io(u3_agp, 0);
--      if (u4_pcie)
--              pci_setup_phb_io(u4_pcie, 0);
--
--      /*
--       * On ppc64, fixup the IO resources on our host bridges as
--       * the common code does it only for children of the host bridges
--       */
--      pmac_fixup_phb_resources();
--
-       /* Setup the linkage between OF nodes and PHBs */
-       pci_devs_phb_init();
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/powermac/setup.c linux-2.6.22-590/arch/powerpc/platforms/powermac/setup.c
---- linux-2.6.22-570/arch/powerpc/platforms/powermac/setup.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/powermac/setup.c   2008-01-02 13:56:37.000000000 -0500
-@@ -98,8 +98,6 @@
- int sccdbg;
- #endif
--extern void zs_kgdb_hook(int tty_num);
--
- sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
- EXPORT_SYMBOL(sys_ctrler);
-@@ -330,10 +328,6 @@
-       l2cr_init();
- #endif /* CONFIG_PPC32 */
--#ifdef CONFIG_KGDB
--      zs_kgdb_hook(0);
--#endif
--
-       find_via_cuda();
-       find_via_pmu();
-       smu_init();
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/ps3/htab.c linux-2.6.22-590/arch/powerpc/platforms/ps3/htab.c
---- linux-2.6.22-570/arch/powerpc/platforms/ps3/htab.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/ps3/htab.c 2008-01-02 13:56:37.000000000 -0500
-@@ -34,7 +34,7 @@
- #define DBG(fmt...) do{if(0)printk(fmt);}while(0)
- #endif
--static hpte_t *htab;
-+static struct hash_pte *htab;
- static unsigned long htab_addr;
- static unsigned char *bolttab;
- static unsigned char *inusetab;
-@@ -44,8 +44,8 @@
- #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \
-       _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
- static void _debug_dump_hpte(unsigned long pa, unsigned long va,
--      unsigned long group, unsigned long bitmap, hpte_t lhpte, int psize,
--      unsigned long slot, const char* func, int line)
-+      unsigned long group, unsigned long bitmap, struct hash_pte lhpte,
-+      int psize, unsigned long slot, const char* func, int line)
- {
-       DBG("%s:%d: pa     = %lxh\n", func, line, pa);
-       DBG("%s:%d: lpar   = %lxh\n", func, line,
-@@ -63,7 +63,7 @@
-       unsigned long pa, unsigned long rflags, unsigned long vflags, int psize)
- {
-       unsigned long slot;
--      hpte_t lhpte;
-+      struct hash_pte lhpte;
-       int secondary = 0;
-       unsigned long result;
-       unsigned long bitmap;
-@@ -255,7 +255,7 @@
-       ppc64_pft_size = __ilog2(htab_size);
--      bitmap_size = htab_size / sizeof(hpte_t) / 8;
-+      bitmap_size = htab_size / sizeof(struct hash_pte) / 8;
-       bolttab = __va(lmb_alloc(bitmap_size, 1));
-       inusetab = __va(lmb_alloc(bitmap_size, 1));
-@@ -273,7 +273,7 @@
-       result = lv1_map_htab(0, &htab_addr);
--      htab = (hpte_t *)__ioremap(htab_addr, htab_size,
-+      htab = (struct hash_pte *)__ioremap(htab_addr, htab_size,
-                                  pgprot_val(PAGE_READONLY_X));
-       DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__,
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/pseries/Makefile linux-2.6.22-590/arch/powerpc/platforms/pseries/Makefile
---- linux-2.6.22-570/arch/powerpc/platforms/pseries/Makefile   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/pseries/Makefile   2008-01-02 13:56:37.000000000 -0500
-@@ -8,7 +8,7 @@
- obj-$(CONFIG_SMP)     += smp.o
- obj-$(CONFIG_XICS)    += xics.o
- obj-$(CONFIG_SCANLOG) += scanlog.o
--obj-$(CONFIG_EEH)     += eeh.o eeh_cache.o eeh_driver.o eeh_event.o
-+obj-$(CONFIG_EEH)     += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o
- obj-$(CONFIG_KEXEC)   += kexec.o
- obj-$(CONFIG_PCI)     += pci.o pci_dlpar.o
- obj-$(CONFIG_PCI_MSI) += msi.o
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh.c linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh.c
---- linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh.c      2008-01-02 13:56:37.000000000 -0500
-@@ -1,6 +1,8 @@
- /*
-  * eeh.c
-- * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation
-+ * Copyright IBM Corporation 2001, 2005, 2006
-+ * Copyright Dave Engebretsen & Todd Inglett 2001
-+ * Copyright Linas Vepstas 2005, 2006
-  *
-  * 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
-@@ -15,6 +17,8 @@
-  * 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
-+ *
-+ * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com>
-  */
- #include <linux/delay.h>
-@@ -117,7 +121,6 @@
- static unsigned long ignored_check;
- static unsigned long total_mmio_ffs;
- static unsigned long false_positives;
--static unsigned long ignored_failures;
- static unsigned long slot_resets;
- #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)
-@@ -505,6 +508,7 @@
-               printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n",
-                      ret, dn->full_name);
-               false_positives++;
-+              pdn->eeh_false_positives ++;
-               rc = 0;
-               goto dn_unlock;
-       }
-@@ -513,6 +517,7 @@
-        * they are empty when they don't have children. */
-       if ((rets[0] == 5) && (dn->child == NULL)) {
-               false_positives++;
-+              pdn->eeh_false_positives ++;
-               rc = 0;
-               goto dn_unlock;
-       }
-@@ -522,6 +527,7 @@
-               printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n",
-                      ret, dn->full_name);
-               false_positives++;
-+              pdn->eeh_false_positives ++;
-               rc = 0;
-               goto dn_unlock;
-       }
-@@ -529,6 +535,7 @@
-       /* If not the kind of error we know about, punt. */
-       if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) {
-               false_positives++;
-+              pdn->eeh_false_positives ++;
-               rc = 0;
-               goto dn_unlock;
-       }
-@@ -921,6 +928,7 @@
-       pdn->eeh_mode = 0;
-       pdn->eeh_check_count = 0;
-       pdn->eeh_freeze_count = 0;
-+      pdn->eeh_false_positives = 0;
-       if (status && strcmp(status, "ok") != 0)
-               return NULL;    /* ignore devices with bad status */
-@@ -1139,7 +1147,8 @@
-       pdn = PCI_DN(dn);
-       pdn->pcidev = dev;
--      pci_addr_cache_insert_device (dev);
-+      pci_addr_cache_insert_device(dev);
-+      eeh_sysfs_add_device(dev);
- }
- void eeh_add_device_tree_late(struct pci_bus *bus)
-@@ -1178,6 +1187,7 @@
-       printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev));
- #endif
-       pci_addr_cache_remove_device(dev);
-+      eeh_sysfs_remove_device(dev);
-       dn = pci_device_to_OF_node(dev);
-       if (PCI_DN(dn)->pcidev) {
-@@ -1214,11 +1224,10 @@
-                               "check not wanted=%ld\n"
-                               "eeh_total_mmio_ffs=%ld\n"
-                               "eeh_false_positives=%ld\n"
--                              "eeh_ignored_failures=%ld\n"
-                               "eeh_slot_resets=%ld\n",
-                               no_device, no_dn, no_cfg_addr, 
-                               ignored_check, total_mmio_ffs, 
--                              false_positives, ignored_failures, 
-+                              false_positives,
-                               slot_resets);
-       }
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh_cache.c linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh_cache.c
---- linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh_cache.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh_cache.c        2008-01-02 13:56:37.000000000 -0500
-@@ -2,7 +2,8 @@
-  * eeh_cache.c
-  * PCI address cache; allows the lookup of PCI devices based on I/O address
-  *
-- * Copyright (C) 2004 Linas Vepstas <linas@austin.ibm.com> IBM Corporation
-+ * Copyright IBM Corporation 2004
-+ * Copyright Linas Vepstas <linas@austin.ibm.com> 2004
-  *
-  * 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
-@@ -295,6 +296,8 @@
-                       continue;
-               pci_dev_get (dev);  /* matching put is in eeh_remove_device() */
-               PCI_DN(dn)->pcidev = dev;
-+
-+              eeh_sysfs_add_device(dev);
-       }
- #ifdef DEBUG
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh_driver.c linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh_driver.c
---- linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh_driver.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh_driver.c       2008-01-02 13:56:37.000000000 -0500
-@@ -1,6 +1,7 @@
- /*
-  * PCI Error Recovery Driver for RPA-compliant PPC64 platform.
-- * Copyright (C) 2004, 2005 Linas Vepstas <linas@linas.org>
-+ * Copyright IBM Corp. 2004 2005
-+ * Copyright Linas Vepstas <linas@linas.org> 2004, 2005
-  *
-  * All rights reserved.
-  *
-@@ -19,8 +20,7 @@
-  * along with this program; if not, write to the Free Software
-  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-  *
-- * Send feedback to <linas@us.ibm.com>
-- *
-+ * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
-  */
- #include <linux/delay.h>
- #include <linux/interrupt.h>
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh_sysfs.c linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh_sysfs.c
---- linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh_sysfs.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh_sysfs.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,87 @@
-+/*
-+ * Sysfs entries for PCI Error Recovery for PAPR-compliant platform.
-+ * Copyright IBM Corporation 2007
-+ * Copyright Linas Vepstas <linas@austin.ibm.com> 2007
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or (at
-+ * your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
-+ * NON INFRINGEMENT.  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.
-+ *
-+ * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
-+ */
-+#include <linux/pci.h>
-+#include <asm/ppc-pci.h>
-+#include <asm/pci-bridge.h>
-+#include <linux/kobject.h>
-+
-+/**
-+ * EEH_SHOW_ATTR -- create sysfs entry for eeh statistic
-+ * @_name: name of file in sysfs directory
-+ * @_memb: name of member in struct pci_dn to access
-+ * @_format: printf format for display
-+ *
-+ * All of the attributes look very similar, so just
-+ * auto-gen a cut-n-paste routine to display them.
-+ */
-+#define EEH_SHOW_ATTR(_name,_memb,_format)               \
-+static ssize_t eeh_show_##_name(struct device *dev,      \
-+              struct device_attribute *attr, char *buf)          \
-+{                                                        \
-+      struct pci_dev *pdev = to_pci_dev(dev);               \
-+      struct device_node *dn = pci_device_to_OF_node(pdev); \
-+      struct pci_dn *pdn;                                   \
-+                                                            \
-+      if (!dn || PCI_DN(dn) == NULL)                        \
-+              return 0;                                          \
-+                                                            \
-+      pdn = PCI_DN(dn);                                     \
-+      return sprintf(buf, _format "\n", pdn->_memb);        \
-+}                                                        \
-+static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL);
-+
-+
-+EEH_SHOW_ATTR(eeh_mode, eeh_mode, "0x%x");
-+EEH_SHOW_ATTR(eeh_config_addr, eeh_config_addr, "0x%x");
-+EEH_SHOW_ATTR(eeh_pe_config_addr, eeh_pe_config_addr, "0x%x");
-+EEH_SHOW_ATTR(eeh_check_count, eeh_check_count, "%d");
-+EEH_SHOW_ATTR(eeh_freeze_count, eeh_freeze_count, "%d");
-+EEH_SHOW_ATTR(eeh_false_positives, eeh_false_positives, "%d");
-+
-+void eeh_sysfs_add_device(struct pci_dev *pdev)
-+{
-+      int rc=0;
-+
-+      rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode);
-+      rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr);
-+      rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
-+      rc += device_create_file(&pdev->dev, &dev_attr_eeh_check_count);
-+      rc += device_create_file(&pdev->dev, &dev_attr_eeh_false_positives);
-+      rc += device_create_file(&pdev->dev, &dev_attr_eeh_freeze_count);
-+
-+      if (rc)
-+              printk(KERN_WARNING "EEH: Unable to create sysfs entries\n");
-+}
-+
-+void eeh_sysfs_remove_device(struct pci_dev *pdev)
-+{
-+      device_remove_file(&pdev->dev, &dev_attr_eeh_mode);
-+      device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr);
-+      device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
-+      device_remove_file(&pdev->dev, &dev_attr_eeh_check_count);
-+      device_remove_file(&pdev->dev, &dev_attr_eeh_false_positives);
-+      device_remove_file(&pdev->dev, &dev_attr_eeh_freeze_count);
-+}
-+
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/pseries/pci_dlpar.c linux-2.6.22-590/arch/powerpc/platforms/pseries/pci_dlpar.c
---- linux-2.6.22-570/arch/powerpc/platforms/pseries/pci_dlpar.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/pseries/pci_dlpar.c        2008-01-02 13:56:37.000000000 -0500
-@@ -110,8 +110,6 @@
-                       }
-               }
-       }
--
--      eeh_add_device_tree_late(bus);
- }
- EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
-@@ -139,6 +137,8 @@
-       /* Make the discovered devices available */
-       pci_bus_add_devices(child_bus);
-+
-+      eeh_add_device_tree_late(child_bus);
-       return 0;
- }
-@@ -171,6 +171,7 @@
-               if (!list_empty(&bus->devices)) {
-                       pcibios_fixup_new_pci_devices(bus, 0);
-                       pci_bus_add_devices(bus);
-+                      eeh_add_device_tree_late(bus);
-               }
-       } else if (mode == PCI_PROBE_NORMAL) {
-               /* use legacy probe */
-@@ -179,6 +180,7 @@
-               if (num) {
-                       pcibios_fixup_new_pci_devices(bus, 1);
-                       pci_bus_add_devices(bus);
-+                      eeh_add_device_tree_late(bus);
-               }
-               list_for_each_entry(dev, &bus->devices, bus_list)
-@@ -200,8 +202,6 @@
-       rtas_setup_phb(phb);
-       pci_process_bridge_OF_ranges(phb, dn, 0);
--      pci_setup_phb_io_dynamic(phb, primary);
--
-       pci_devs_phb_init_dynamic(phb);
-       if (dn->child)
-@@ -210,6 +210,7 @@
-       scan_phb(phb);
-       pcibios_fixup_new_pci_devices(phb->bus, 0);
-       pci_bus_add_devices(phb->bus);
-+      eeh_add_device_tree_late(phb->bus);
-       return phb;
- }
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/pseries/pseries.h linux-2.6.22-590/arch/powerpc/platforms/pseries/pseries.h
---- linux-2.6.22-570/arch/powerpc/platforms/pseries/pseries.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/pseries/pseries.h  2008-01-02 13:56:37.000000000 -0500
-@@ -33,6 +33,8 @@
- static inline void setup_kexec_cpu_down_mpic(void) { }
- #endif
-+extern void pSeries_final_fixup(void);
-+
- /* Poweron flag used for enabling auto ups restart */
- extern unsigned long rtas_poweron_auto;
-diff -Nurb linux-2.6.22-570/arch/powerpc/platforms/pseries/setup.c linux-2.6.22-590/arch/powerpc/platforms/pseries/setup.c
---- linux-2.6.22-570/arch/powerpc/platforms/pseries/setup.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/platforms/pseries/setup.c    2008-01-02 13:56:37.000000000 -0500
-@@ -399,6 +399,7 @@
-        * a good time to find other work to dispatch.
-        */
-       get_lppaca()->idle = 1;
-+      get_lppaca()->donate_dedicated_cpu = 1;
-       /*
-        * We come in with interrupts disabled, and need_resched()
-@@ -431,6 +432,7 @@
- out:
-       HMT_medium();
-+      get_lppaca()->donate_dedicated_cpu = 0;
-       get_lppaca()->idle = 0;
- }
-diff -Nurb linux-2.6.22-570/arch/powerpc/sysdev/tsi108_dev.c linux-2.6.22-590/arch/powerpc/sysdev/tsi108_dev.c
---- linux-2.6.22-570/arch/powerpc/sysdev/tsi108_dev.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/powerpc/sysdev/tsi108_dev.c  2008-01-02 13:56:37.000000000 -0500
-@@ -72,12 +72,11 @@
-       int ret;
-       for (np = NULL, i = 0;
--           (np = of_find_compatible_node(np, "network", "tsi-ethernet")) != NULL;
-+           (np = of_find_compatible_node(np, "network", "tsi108-ethernet")) != NULL;
-            i++) {
-               struct resource r[2];
--              struct device_node *phy;
-+              struct device_node *phy, *mdio;
-               hw_info tsi_eth_data;
--              const unsigned int *id;
-               const unsigned int *phy_id;
-               const void *mac_addr;
-               const phandle *ph;
-@@ -111,6 +110,13 @@
-               if (mac_addr)
-                       memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
-+              ph = of_get_property(np, "mdio-handle", NULL);
-+              mdio = of_find_node_by_phandle(*ph);
-+              ret = of_address_to_resource(mdio, 0, &res);
-+              of_node_put(mdio);
-+              if (ret)
-+                      goto unreg;
-+
-               ph = of_get_property(np, "phy-handle", NULL);
-               phy = of_find_node_by_phandle(*ph);
-@@ -119,20 +125,25 @@
-                       goto unreg;
-               }
--              id = of_get_property(phy, "reg", NULL);
--              phy_id = of_get_property(phy, "phy-id", NULL);
--              ret = of_address_to_resource(phy, 0, &res);
--              if (ret) {
--                      of_node_put(phy);
--                      goto unreg;
--              }
-+              phy_id = of_get_property(phy, "reg", NULL);
-+
-               tsi_eth_data.regs = r[0].start;
-               tsi_eth_data.phyregs = res.start;
-               tsi_eth_data.phy = *phy_id;
-               tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
--              if (of_device_is_compatible(phy, "bcm54xx"))
-+
-+              /* Some boards with the TSI108 bridge (e.g. Holly)
-+               * have a miswiring of the ethernet PHYs which
-+               * requires a workaround.  The special
-+               * "txc-rxc-delay-disable" property enables this
-+               * workaround.  FIXME: Need to port the tsi108_eth
-+               * driver itself to phylib and use a non-misleading
-+               * name for the workaround flag - it's not actually to
-+               * do with the model of PHY in use */
-+              if (of_get_property(phy, "txc-rxc-delay-disable", NULL))
-                       tsi_eth_data.phy_type = TSI108_PHY_BCM54XX;
-               of_node_put(phy);
-+
-               ret =
-                   platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
-                                            sizeof(hw_info));
-diff -Nurb linux-2.6.22-570/arch/ppc/8260_io/enet.c linux-2.6.22-590/arch/ppc/8260_io/enet.c
---- linux-2.6.22-570/arch/ppc/8260_io/enet.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/8260_io/enet.c   2008-01-02 13:56:37.000000000 -0500
-@@ -477,9 +477,9 @@
-               }
-               else {
-                       skb_put(skb,pkt_len-4); /* Make room */
--                      eth_copy_and_sum(skb,
-+                      skb_copy_to_linear_data(skb,
-                               (unsigned char *)__va(bdp->cbd_bufaddr),
--                              pkt_len-4, 0);
-+                              pkt_len-4);
-                       skb->protocol=eth_type_trans(skb,dev);
-                       netif_rx(skb);
-               }
-diff -Nurb linux-2.6.22-570/arch/ppc/8260_io/fcc_enet.c linux-2.6.22-590/arch/ppc/8260_io/fcc_enet.c
---- linux-2.6.22-570/arch/ppc/8260_io/fcc_enet.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/8260_io/fcc_enet.c       2008-01-02 13:56:37.000000000 -0500
-@@ -734,9 +734,9 @@
-               }
-               else {
-                       skb_put(skb,pkt_len);   /* Make room */
--                      eth_copy_and_sum(skb,
-+                      skb_copy_to_linear_data(skb,
-                               (unsigned char *)__va(bdp->cbd_bufaddr),
--                              pkt_len, 0);
-+                              pkt_len);
-                       skb->protocol=eth_type_trans(skb,dev);
-                       netif_rx(skb);
-               }
-diff -Nurb linux-2.6.22-570/arch/ppc/8xx_io/enet.c linux-2.6.22-590/arch/ppc/8xx_io/enet.c
---- linux-2.6.22-570/arch/ppc/8xx_io/enet.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/8xx_io/enet.c    2008-01-02 13:56:37.000000000 -0500
-@@ -506,9 +506,9 @@
-               }
-               else {
-                       skb_put(skb,pkt_len-4); /* Make room */
--                      eth_copy_and_sum(skb,
-+                      skb_copy_to_linear_data(skb,
-                               cep->rx_vaddr[bdp - cep->rx_bd_base],
--                              pkt_len-4, 0);
-+                              pkt_len-4);
-                       skb->protocol=eth_type_trans(skb,dev);
-                       netif_rx(skb);
-               }
-diff -Nurb linux-2.6.22-570/arch/ppc/8xx_io/fec.c linux-2.6.22-590/arch/ppc/8xx_io/fec.c
---- linux-2.6.22-570/arch/ppc/8xx_io/fec.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/8xx_io/fec.c     2008-01-02 13:56:37.000000000 -0500
-@@ -725,7 +725,7 @@
-               fep->stats.rx_dropped++;
-       } else {
-               skb_put(skb,pkt_len-4); /* Make room */
--              eth_copy_and_sum(skb, data, pkt_len-4, 0);
-+              skb_copy_to_linear_data(skb, data, pkt_len-4);
-               skb->protocol=eth_type_trans(skb,dev);
-               netif_rx(skb);
-       }
-diff -Nurb linux-2.6.22-570/arch/ppc/Kconfig.debug linux-2.6.22-590/arch/ppc/Kconfig.debug
---- linux-2.6.22-570/arch/ppc/Kconfig.debug    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/Kconfig.debug    2008-01-02 13:56:37.000000000 -0500
-@@ -2,42 +2,6 @@
- source "lib/Kconfig.debug"
--config KGDB
--      bool "Include kgdb kernel debugger"
--      depends on DEBUG_KERNEL && (BROKEN || PPC_GEN550 || 4xx)
--      select DEBUG_INFO
--      help
--        Include in-kernel hooks for kgdb, the Linux kernel source level
--        debugger.  See <http://kgdb.sourceforge.net/> for more information.
--        Unless you are intending to debug the kernel, say N here.
--
--choice
--      prompt "Serial Port"
--      depends on KGDB
--      default KGDB_TTYS1
--
--config KGDB_TTYS0
--      bool "ttyS0"
--
--config KGDB_TTYS1
--      bool "ttyS1"
--
--config KGDB_TTYS2
--      bool "ttyS2"
--
--config KGDB_TTYS3
--      bool "ttyS3"
--
--endchoice
--
--config KGDB_CONSOLE
--      bool "Enable serial console thru kgdb port"
--      depends on KGDB && 8xx || CPM2
--      help
--        If you enable this, all serial console messages will be sent
--        over the gdb stub.
--        If unsure, say N.
--
- config XMON
-       bool "Include xmon kernel debugger"
-       depends on DEBUG_KERNEL
-diff -Nurb linux-2.6.22-570/arch/ppc/amiga/config.c linux-2.6.22-590/arch/ppc/amiga/config.c
---- linux-2.6.22-570/arch/ppc/amiga/config.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/amiga/config.c   2008-01-02 13:56:37.000000000 -0500
-@@ -753,17 +753,11 @@
- void amiga_serial_console_write(struct console *co, const char *s,
-                                      unsigned int count)
- {
--#if 0 /* def CONFIG_KGDB */
--      /* FIXME:APUS GDB doesn't seem to like O-packages before it is
--           properly connected with the target. */
--      __gdb_output_string (s, count);
--#else
-       while (count--) {
-               if (*s == '\n')
-                       amiga_serial_putc('\r');
-               amiga_serial_putc(*s++);
-       }
--#endif
- }
- #ifdef CONFIG_SERIAL_CONSOLE
-diff -Nurb linux-2.6.22-570/arch/ppc/kernel/Makefile linux-2.6.22-590/arch/ppc/kernel/Makefile
---- linux-2.6.22-570/arch/ppc/kernel/Makefile  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/kernel/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -14,7 +14,7 @@
- obj-$(CONFIG_MODULES)         += ppc_ksyms.o
- obj-$(CONFIG_PCI)             += pci.o
- obj-$(CONFIG_RAPIDIO)         += rio.o
--obj-$(CONFIG_KGDB)            += ppc-stub.o
-+obj-$(CONFIG_KGDB)            += kgdb.o kgdb_setjmp32.o
- obj-$(CONFIG_SMP)             += smp.o smp-tbsync.o
- obj-$(CONFIG_KEXEC)           += machine_kexec.o relocate_kernel.o
-diff -Nurb linux-2.6.22-570/arch/ppc/kernel/kgdb.c linux-2.6.22-590/arch/ppc/kernel/kgdb.c
---- linux-2.6.22-570/arch/ppc/kernel/kgdb.c    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/ppc/kernel/kgdb.c    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,348 @@
-+/*
-+ * arch/ppc/kernel/kgdb.c
-+ *
-+ * PowerPC backend to the KGDB stub.
-+ *
-+ * Maintainer: Tom Rini <trini@kernel.crashing.org>
-+ *
-+ * 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu)
-+ * Copyright (C) 2003 Timesys Corporation.
-+ * Copyright (C) 2004, 2006 MontaVista Software, Inc.
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program as licensed "as is" without any warranty of any
-+ * kind, whether express or implied.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/kgdb.h>
-+#include <linux/smp.h>
-+#include <linux/signal.h>
-+#include <linux/ptrace.h>
-+#include <asm/current.h>
-+#include <asm/ptrace.h>
-+#include <asm/processor.h>
-+#include <asm/machdep.h>
-+
-+/*
-+ * This table contains the mapping between PowerPC hardware trap types, and
-+ * signals, which are primarily what GDB understands.  GDB and the kernel
-+ * don't always agree on values, so we use constants taken from gdb-6.2.
-+ */
-+static struct hard_trap_info
-+{
-+      unsigned int tt;                /* Trap type code for powerpc */
-+      unsigned char signo;            /* Signal that we map this trap into */
-+} hard_trap_info[] = {
-+      { 0x0100, 0x02 /* SIGINT */  },         /* system reset */
-+      { 0x0200, 0x0b /* SIGSEGV */ },         /* machine check */
-+      { 0x0300, 0x0b /* SIGSEGV */ },         /* data access */
-+      { 0x0400, 0x0b /* SIGSEGV */ },         /* instruction access */
-+      { 0x0500, 0x02 /* SIGINT */  },         /* external interrupt */
-+      { 0x0600, 0x0a /* SIGBUS */  },         /* alignment */
-+      { 0x0700, 0x05 /* SIGTRAP */ },         /* program check */
-+      { 0x0800, 0x08 /* SIGFPE */  },         /* fp unavailable */
-+      { 0x0900, 0x0e /* SIGALRM */ },         /* decrementer */
-+      { 0x0c00, 0x14 /* SIGCHLD */ },         /* system call */
-+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
-+      { 0x2002, 0x05 /* SIGTRAP */ },         /* debug */
-+#if defined(CONFIG_FSL_BOOKE)
-+      { 0x2010, 0x08 /* SIGFPE */  },         /* spe unavailable */
-+      { 0x2020, 0x08 /* SIGFPE */  },         /* spe unavailable */
-+      { 0x2030, 0x08 /* SIGFPE */  },         /* spe fp data */
-+      { 0x2040, 0x08 /* SIGFPE */  },         /* spe fp data */
-+      { 0x2050, 0x08 /* SIGFPE */  },         /* spe fp round */
-+      { 0x2060, 0x0e /* SIGILL */  },         /* performace monitor */
-+      { 0x2900, 0x08 /* SIGFPE */  },         /* apu unavailable */
-+      { 0x3100, 0x0e /* SIGALRM */ },         /* fixed interval timer */
-+      { 0x3200, 0x02 /* SIGINT */  },         /* watchdog */
-+#else
-+      { 0x1000, 0x0e /* SIGALRM */ },         /* programmable interval timer */
-+      { 0x1010, 0x0e /* SIGALRM */ },         /* fixed interval timer */
-+      { 0x1020, 0x02 /* SIGINT */  },         /* watchdog */
-+      { 0x2010, 0x08 /* SIGFPE */  },         /* fp unavailable */
-+      { 0x2020, 0x08 /* SIGFPE */  },         /* ap unavailable */
-+#endif
-+#else
-+      { 0x0d00, 0x05 /* SIGTRAP */ },         /* single-step */
-+#if defined(CONFIG_8xx)
-+      { 0x1000, 0x04 /* SIGILL */  },         /* software emulation */
-+#else
-+      { 0x0f00, 0x04 /* SIGILL */  },         /* performance monitor */
-+      { 0x0f20, 0x08 /* SIGFPE */  },         /* altivec unavailable */
-+      { 0x1300, 0x05 /* SIGTRAP */ },         /* instruction address break */
-+      { 0x1400, 0x02 /* SIGINT */  },         /* SMI */
-+      { 0x1600, 0x08 /* SIGFPE */  },         /* altivec assist */
-+      { 0x1700, 0x04 /* SIGILL */  },         /* TAU */
-+      { 0x2000, 0x05 /* SIGTRAP */ },         /* run mode */
-+#endif
-+#endif
-+      { 0x0000, 0x00 }                        /* Must be last */
-+};
-+
-+extern atomic_t cpu_doing_single_step;
-+
-+static int computeSignal(unsigned int tt)
-+{
-+      struct hard_trap_info *ht;
-+
-+      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
-+              if (ht->tt == tt)
-+                      return ht->signo;
-+
-+      return SIGHUP;          /* default for things we don't know about */
-+}
-+
-+/* KGDB functions to use existing PowerPC hooks. */
-+static void kgdb_debugger(struct pt_regs *regs)
-+{
-+      kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
-+}
-+
-+static int kgdb_breakpoint(struct pt_regs *regs)
-+{
-+      if (user_mode(regs))
-+              return 0;
-+
-+      kgdb_handle_exception(0, SIGTRAP, 0, regs);
-+
-+      if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
-+              regs->nip += 4;
-+
-+      return 1;
-+}
-+
-+static int kgdb_singlestep(struct pt_regs *regs)
-+{
-+      struct thread_info *thread_info, *exception_thread_info;
-+
-+      if (user_mode(regs))
-+              return 0;
-+      /*
-+      * On Book E and perhaps other processsors, singlestep is handled on
-+      * the critical exception stack.  This causes current_thread_info()
-+      * to fail, since it it locates the thread_info by masking off
-+      * the low bits of the current stack pointer.  We work around
-+      * this issue by copying the thread_info from the kernel stack
-+      * before calling kgdb_handle_exception, and copying it back
-+      * afterwards.  On most processors the copy is avoided since
-+      * exception_thread_info == thread_info.
-+      */
-+      thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
-+      exception_thread_info = current_thread_info();
-+
-+      if (thread_info != exception_thread_info)
-+              memcpy(exception_thread_info, thread_info, sizeof *thread_info);
-+
-+      kgdb_handle_exception(0, SIGTRAP, 0, regs);
-+
-+      if (thread_info != exception_thread_info)
-+              memcpy(thread_info, exception_thread_info, sizeof *thread_info);
-+
-+      return 1;
-+}
-+
-+int kgdb_iabr_match(struct pt_regs *regs)
-+{
-+      if (user_mode(regs))
-+              return 0;
-+
-+      kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
-+      return 1;
-+}
-+
-+int kgdb_dabr_match(struct pt_regs *regs)
-+{
-+      if (user_mode(regs))
-+              return 0;
-+
-+      kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
-+      return 1;
-+}
-+
-+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-+{
-+      unsigned long *ptr = gdb_regs;
-+      int reg;
-+
-+      memset(gdb_regs, 0, MAXREG * 4);
-+
-+      for (reg = 0; reg < 32; reg++)
-+              *(ptr++) = regs->gpr[reg];
-+
-+#ifdef CONFIG_FSL_BOOKE
-+#ifdef CONFIG_SPE
-+      for (reg = 0; reg < 32; reg++)
-+              *(ptr++) = current->thread.evr[reg];
-+#else
-+      ptr += 32;
-+#endif
-+#else
-+      ptr += 64;
-+#endif
-+
-+      *(ptr++) = regs->nip;
-+      *(ptr++) = regs->msr;
-+      *(ptr++) = regs->ccr;
-+      *(ptr++) = regs->link;
-+      *(ptr++) = regs->ctr;
-+      *(ptr++) = regs->xer;
-+
-+#ifdef CONFIG_SPE
-+      /* u64 acc */
-+      *(ptr++) = current->thread.acc >> 32;
-+      *(ptr++) = current->thread.acc & 0xffffffff;
-+      *(ptr++) = current->thread.spefscr;
-+#endif
-+}
-+
-+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
-+{
-+      struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
-+                                                STACK_FRAME_OVERHEAD);
-+      unsigned long *ptr = gdb_regs;
-+      int reg;
-+
-+      memset(gdb_regs, 0, MAXREG * 4);
-+
-+      /* Regs GPR0-2 */
-+      for (reg = 0; reg < 3; reg++)
-+              *(ptr++) = regs->gpr[reg];
-+
-+      /* Regs GPR3-13 are not saved */
-+      ptr += 11;
-+
-+      /* Regs GPR14-31 */
-+      for (reg = 14; reg < 32; reg++)
-+              *(ptr++) = regs->gpr[reg];
-+
-+#ifdef CONFIG_FSL_BOOKE
-+#ifdef CONFIG_SPE
-+      for (reg = 0; reg < 32; reg++)
-+              *(ptr++) = p->thread.evr[reg];
-+#else
-+      ptr += 32;
-+#endif
-+#else
-+      ptr += 64;
-+#endif
-+
-+      *(ptr++) = regs->nip;
-+      *(ptr++) = regs->msr;
-+      *(ptr++) = regs->ccr;
-+      *(ptr++) = regs->link;
-+      *(ptr++) = regs->ctr;
-+      *(ptr++) = regs->xer;
-+
-+#ifdef CONFIG_SPE
-+      /* u64 acc */
-+      *(ptr++) = p->thread.acc >> 32;
-+      *(ptr++) = p->thread.acc & 0xffffffff;
-+      *(ptr++) = p->thread.spefscr;
-+#endif
-+}
-+
-+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-+{
-+      unsigned long *ptr = gdb_regs;
-+      int reg;
-+#ifdef CONFIG_SPE
-+      union {
-+              u32 v32[2];
-+              u64 v64;
-+      } acc;
-+#endif
-+
-+      for (reg = 0; reg < 32; reg++)
-+              regs->gpr[reg] = *(ptr++);
-+
-+#ifdef CONFIG_FSL_BOOKE
-+#ifdef CONFIG_SPE
-+      for (reg = 0; reg < 32; reg++)
-+              current->thread.evr[reg] = *(ptr++);
-+#else
-+      ptr += 32;
-+#endif
-+#else
-+      ptr += 64;
-+#endif
-+
-+      regs->nip = *(ptr++);
-+      regs->msr = *(ptr++);
-+      regs->ccr = *(ptr++);
-+      regs->link = *(ptr++);
-+      regs->ctr = *(ptr++);
-+      regs->xer = *(ptr++);
-+
-+#ifdef CONFIG_SPE
-+      /* u64 acc */
-+      acc.v32[0] = *(ptr++);
-+      acc.v32[1] = *(ptr++);
-+      current->thread.acc = acc.v64;
-+      current->thread.spefscr = *(ptr++);
-+#endif
-+}
-+
-+/*
-+ * This function does PowerPC specific processing for interfacing to gdb.
-+ */
-+int kgdb_arch_handle_exception(int vector, int signo, int err_code,
-+                             char *remcom_in_buffer, char *remcom_out_buffer,
-+                             struct pt_regs *linux_regs)
-+{
-+      char *ptr = &remcom_in_buffer[1];
-+      unsigned long addr;
-+
-+      switch (remcom_in_buffer[0])
-+              {
-+              /*
-+               * sAA..AA   Step one instruction from AA..AA
-+               * This will return an error to gdb ..
-+               */
-+              case 's':
-+              case 'c':
-+                      /* handle the optional parameter */
-+                      if (kgdb_hex2long (&ptr, &addr))
-+                              linux_regs->nip = addr;
-+
-+                      atomic_set(&cpu_doing_single_step, -1);
-+                      /* set the trace bit if we're stepping */
-+                      if (remcom_in_buffer[0] == 's') {
-+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
-+                              mtspr(SPRN_DBCR0,
-+                                    mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
-+                              linux_regs->msr |= MSR_DE;
-+#else
-+                              linux_regs->msr |= MSR_SE;
-+#endif
-+                              debugger_step = 1;
-+                              if (kgdb_contthread)
-+                                      atomic_set(&cpu_doing_single_step,
-+                                                      smp_processor_id());
-+                      }
-+                      return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+/*
-+ * Global data
-+ */
-+struct kgdb_arch arch_kgdb_ops = {
-+      .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
-+};
-+
-+int kgdb_arch_init(void)
-+{
-+      debugger = kgdb_debugger;
-+      debugger_bpt = kgdb_breakpoint;
-+      debugger_sstep = kgdb_singlestep;
-+      debugger_iabr_match = kgdb_iabr_match;
-+      debugger_dabr_match = kgdb_dabr_match;
-+
-+      return 0;
-+}
-+
-+arch_initcall(kgdb_arch_init);
-diff -Nurb linux-2.6.22-570/arch/ppc/kernel/kgdb_setjmp32.S linux-2.6.22-590/arch/ppc/kernel/kgdb_setjmp32.S
---- linux-2.6.22-570/arch/ppc/kernel/kgdb_setjmp32.S   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/ppc/kernel/kgdb_setjmp32.S   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,41 @@
-+/*
-+ * Copyright (C) 1996 Paul Mackerras
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program as licensed "as is" without any warranty of any
-+ * kind, whether express or implied.
-+ */
-+
-+#include <asm/processor.h>
-+#include <asm/ppc_asm.h>
-+
-+      .text
-+
-+/*
-+ * Save/restore state in case a memory access causes a fault.
-+ *
-+ * int kgdb_fault_setjmp(unsigned long *curr_context);
-+ * void kgdb_fault_longjmp(unsigned long *curr_context);
-+ */
-+
-+_GLOBAL(kgdb_fault_setjmp)
-+      mflr    r0
-+      stw     r0,0(r3)
-+      stw     r1,4(r3)
-+      stw     r2,8(r3)
-+      mfcr    r0
-+      stw     r0,12(r3)
-+      stmw    r13,16(r3)
-+      li      r3,0
-+      blr
-+
-+_GLOBAL(kgdb_fault_longjmp)
-+      lmw     r13,16(r3)
-+      lwz     r0,12(r3)
-+      mtcrf   0x38,r0
-+      lwz     r0,0(r3)
-+      lwz     r1,4(r3)
-+      lwz     r2,8(r3)
-+      mtlr    r0
-+      mr      r3,r1
-+      blr
-diff -Nurb linux-2.6.22-570/arch/ppc/kernel/misc.S linux-2.6.22-590/arch/ppc/kernel/misc.S
---- linux-2.6.22-570/arch/ppc/kernel/misc.S    2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/ppc/kernel/misc.S    2008-01-02 13:56:37.000000000 -0500
-@@ -328,7 +328,7 @@
-       mtspr   SPRN_L1CSR0,r3
-       isync
-       blr
--END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
-+END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
-       mfspr   r3,SPRN_L1CSR1
-       ori     r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
-       mtspr   SPRN_L1CSR1,r3
-@@ -355,7 +355,7 @@
- _GLOBAL(__flush_icache_range)
- BEGIN_FTR_SECTION
-       blr                             /* for 601, do nothing */
--END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
-+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
-       li      r5,L1_CACHE_BYTES-1
-       andc    r3,r3,r5
-       subf    r4,r3,r4
-@@ -472,7 +472,7 @@
- _GLOBAL(__flush_dcache_icache)
- BEGIN_FTR_SECTION
-       blr                                     /* for 601, do nothing */
--END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
-+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
-       rlwinm  r3,r3,0,0,19                    /* Get page base address */
-       li      r4,4096/L1_CACHE_BYTES  /* Number of lines in a page */
-       mtctr   r4
-@@ -500,7 +500,7 @@
- _GLOBAL(__flush_dcache_icache_phys)
- BEGIN_FTR_SECTION
-       blr                                     /* for 601, do nothing */
--END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
-+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
-       mfmsr   r10
-       rlwinm  r0,r10,0,28,26                  /* clear DR */
-       mtmsr   r0
-diff -Nurb linux-2.6.22-570/arch/ppc/kernel/ppc-stub.c linux-2.6.22-590/arch/ppc/kernel/ppc-stub.c
---- linux-2.6.22-570/arch/ppc/kernel/ppc-stub.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/kernel/ppc-stub.c        1969-12-31 19:00:00.000000000 -0500
-@@ -1,866 +0,0 @@
--/*
-- * ppc-stub.c:  KGDB support for the Linux kernel.
-- *
-- * adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC
-- * some stuff borrowed from Paul Mackerras' xmon
-- * Copyright (C) 1998 Michael AK Tesch (tesch@cs.wisc.edu)
-- *
-- * Modifications to run under Linux
-- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
-- *
-- * This file originally came from the gdb sources, and the
-- * copyright notices have been retained below.
-- */
--
--/****************************************************************************
--
--              THIS SOFTWARE IS NOT COPYRIGHTED
--
--   HP offers the following for use in the public domain.  HP makes no
--   warranty with regard to the software or its performance and the
--   user accepts the software "AS IS" with all faults.
--
--   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
--   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
--   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
--
--****************************************************************************/
--
--/****************************************************************************
-- *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
-- *
-- *  Module name: remcom.c $
-- *  Revision: 1.34 $
-- *  Date: 91/03/09 12:29:49 $
-- *  Contributor:     Lake Stevens Instrument Division$
-- *
-- *  Description:     low level support for gdb debugger. $
-- *
-- *  Considerations:  only works on target hardware $
-- *
-- *  Written by:      Glenn Engel $
-- *  ModuleState:     Experimental $
-- *
-- *  NOTES:           See Below $
-- *
-- *  Modified for SPARC by Stu Grossman, Cygnus Support.
-- *
-- *  This code has been extensively tested on the Fujitsu SPARClite demo board.
-- *
-- *  To enable debugger support, two things need to happen.  One, a
-- *  call to set_debug_traps() is necessary in order to allow any breakpoints
-- *  or error conditions to be properly intercepted and reported to gdb.
-- *  Two, a breakpoint needs to be generated to begin communication.  This
-- *  is most easily accomplished by a call to breakpoint().  Breakpoint()
-- *  simulates a breakpoint by executing a trap #1.
-- *
-- *************
-- *
-- *    The following gdb commands are supported:
-- *
-- * command          function                    Return value
-- *
-- *    g             return the value of the CPU registers  hex data or ENN
-- *    G             set the value of the CPU registers     OK or ENN
-- *    qOffsets      Get section offsets.  Reply is Text=xxx;Data=yyy;Bss=zzz
-- *
-- *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
-- *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
-- *
-- *    c             Resume at current address              SNN   ( signal NN)
-- *    cAA..AA       Continue at address AA..AA             SNN
-- *
-- *    s             Step one instruction                   SNN
-- *    sAA..AA       Step one instruction from AA..AA       SNN
-- *
-- *    k             kill
-- *
-- *    ?             What was the last sigval ?             SNN   (signal NN)
-- *
-- *    bBB..BB     Set baud rate to BB..BB                OK or BNN, then sets
-- *                                                       baud rate
-- *
-- * All commands and responses are sent with a packet which includes a
-- * checksum.  A packet consists of
-- *
-- * $<packet info>#<checksum>.
-- *
-- * where
-- * <packet info> :: <characters representing the command or response>
-- * <checksum>    :: <two hex digits computed as modulo 256 sum of <packetinfo>>
-- *
-- * When a packet is received, it is first acknowledged with either '+' or '-'.
-- * '+' indicates a successful transfer.  '-' indicates a failed transfer.
-- *
-- * Example:
-- *
-- * Host:                  Reply:
-- * $m0,10#2a               +$00010203040506070809101112131415#42
-- *
-- ****************************************************************************/
--
--#include <linux/kernel.h>
--#include <linux/string.h>
--#include <linux/mm.h>
--#include <linux/smp.h>
--#include <linux/smp_lock.h>
--#include <linux/init.h>
--#include <linux/sysrq.h>
--
--#include <asm/cacheflush.h>
--#include <asm/system.h>
--#include <asm/signal.h>
--#include <asm/kgdb.h>
--#include <asm/pgtable.h>
--#include <asm/ptrace.h>
--
--void breakinst(void);
--
--/*
-- * BUFMAX defines the maximum number of characters in inbound/outbound buffers
-- * at least NUMREGBYTES*2 are needed for register packets
-- */
--#define BUFMAX 2048
--static char remcomInBuffer[BUFMAX];
--static char remcomOutBuffer[BUFMAX];
--
--static int initialized;
--static int kgdb_active;
--static int kgdb_started;
--static u_int fault_jmp_buf[100];
--static int kdebug;
--
--
--static const char hexchars[]="0123456789abcdef";
--
--/* Place where we save old trap entries for restoration - sparc*/
--/* struct tt_entry kgdb_savettable[256]; */
--/* typedef void (*trapfunc_t)(void); */
--
--static void kgdb_fault_handler(struct pt_regs *regs);
--static int handle_exception (struct pt_regs *regs);
--
--#if 0
--/* Install an exception handler for kgdb */
--static void exceptionHandler(int tnum, unsigned int *tfunc)
--{
--      /* We are dorking with a live trap table, all irqs off */
--}
--#endif
--
--int
--kgdb_setjmp(long *buf)
--{
--      asm ("mflr 0; stw 0,0(%0);"
--           "stw 1,4(%0); stw 2,8(%0);"
--           "mfcr 0; stw 0,12(%0);"
--           "stmw 13,16(%0)"
--           : : "r" (buf));
--      /* XXX should save fp regs as well */
--      return 0;
--}
--void
--kgdb_longjmp(long *buf, int val)
--{
--      if (val == 0)
--              val = 1;
--      asm ("lmw 13,16(%0);"
--           "lwz 0,12(%0); mtcrf 0x38,0;"
--           "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
--           "mtlr 0; mr 3,%1"
--           : : "r" (buf), "r" (val));
--}
--/* Convert ch from a hex digit to an int */
--static int
--hex(unsigned char ch)
--{
--      if (ch >= 'a' && ch <= 'f')
--              return ch-'a'+10;
--      if (ch >= '0' && ch <= '9')
--              return ch-'0';
--      if (ch >= 'A' && ch <= 'F')
--              return ch-'A'+10;
--      return -1;
--}
--
--/* Convert the memory pointed to by mem into hex, placing result in buf.
-- * Return a pointer to the last char put in buf (null), in case of mem fault,
-- * return 0.
-- */
--static unsigned char *
--mem2hex(const char *mem, char *buf, int count)
--{
--      unsigned char ch;
--      unsigned short tmp_s;
--      unsigned long tmp_l;
--
--      if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
--              debugger_fault_handler = kgdb_fault_handler;
--
--              /* Accessing 16 bit and 32 bit objects in a single
--              ** load instruction is required to avoid bad side
--              ** effects for some IO registers.
--              */
--
--              if ((count == 2) && (((long)mem & 1) == 0)) {
--                      tmp_s = *(unsigned short *)mem;
--                      mem += 2;
--                      *buf++ = hexchars[(tmp_s >> 12) & 0xf];
--                      *buf++ = hexchars[(tmp_s >> 8) & 0xf];
--                      *buf++ = hexchars[(tmp_s >> 4) & 0xf];
--                      *buf++ = hexchars[tmp_s & 0xf];
--
--              } else if ((count == 4) && (((long)mem & 3) == 0)) {
--                      tmp_l = *(unsigned int *)mem;
--                      mem += 4;
--                      *buf++ = hexchars[(tmp_l >> 28) & 0xf];
--                      *buf++ = hexchars[(tmp_l >> 24) & 0xf];
--                      *buf++ = hexchars[(tmp_l >> 20) & 0xf];
--                      *buf++ = hexchars[(tmp_l >> 16) & 0xf];
--                      *buf++ = hexchars[(tmp_l >> 12) & 0xf];
--                      *buf++ = hexchars[(tmp_l >> 8) & 0xf];
--                      *buf++ = hexchars[(tmp_l >> 4) & 0xf];
--                      *buf++ = hexchars[tmp_l & 0xf];
--
--              } else {
--                      while (count-- > 0) {
--                              ch = *mem++;
--                              *buf++ = hexchars[ch >> 4];
--                              *buf++ = hexchars[ch & 0xf];
--                      }
--              }
--
--      } else {
--              /* error condition */
--      }
--      debugger_fault_handler = NULL;
--      *buf = 0;
--      return buf;
--}
--
--/* convert the hex array pointed to by buf into binary to be placed in mem
-- * return a pointer to the character AFTER the last byte written.
--*/
--static char *
--hex2mem(char *buf, char *mem, int count)
--{
--      unsigned char ch;
--      int i;
--      char *orig_mem;
--      unsigned short tmp_s;
--      unsigned long tmp_l;
--
--      orig_mem = mem;
--
--      if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
--              debugger_fault_handler = kgdb_fault_handler;
--
--              /* Accessing 16 bit and 32 bit objects in a single
--              ** store instruction is required to avoid bad side
--              ** effects for some IO registers.
--              */
--
--              if ((count == 2) && (((long)mem & 1) == 0)) {
--                      tmp_s = hex(*buf++) << 12;
--                      tmp_s |= hex(*buf++) << 8;
--                      tmp_s |= hex(*buf++) << 4;
--                      tmp_s |= hex(*buf++);
--
--                      *(unsigned short *)mem = tmp_s;
--                      mem += 2;
--
--              } else if ((count == 4) && (((long)mem & 3) == 0)) {
--                      tmp_l = hex(*buf++) << 28;
--                      tmp_l |= hex(*buf++) << 24;
--                      tmp_l |= hex(*buf++) << 20;
--                      tmp_l |= hex(*buf++) << 16;
--                      tmp_l |= hex(*buf++) << 12;
--                      tmp_l |= hex(*buf++) << 8;
--                      tmp_l |= hex(*buf++) << 4;
--                      tmp_l |= hex(*buf++);
--
--                      *(unsigned long *)mem = tmp_l;
--                      mem += 4;
--
--              } else {
--                      for (i=0; i<count; i++) {
--                              ch = hex(*buf++) << 4;
--                              ch |= hex(*buf++);
--                              *mem++ = ch;
--                      }
--              }
--
--
--              /*
--              ** Flush the data cache, invalidate the instruction cache.
--              */
--              flush_icache_range((int)orig_mem, (int)orig_mem + count - 1);
--
--      } else {
--              /* error condition */
--      }
--      debugger_fault_handler = NULL;
--      return mem;
--}
--
--/*
-- * While we find nice hex chars, build an int.
-- * Return number of chars processed.
-- */
--static int
--hexToInt(char **ptr, int *intValue)
--{
--      int numChars = 0;
--      int hexValue;
--
--      *intValue = 0;
--
--      if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
--              debugger_fault_handler = kgdb_fault_handler;
--              while (**ptr) {
--                      hexValue = hex(**ptr);
--                      if (hexValue < 0)
--                              break;
--
--                      *intValue = (*intValue << 4) | hexValue;
--                      numChars ++;
--
--                      (*ptr)++;
--              }
--      } else {
--              /* error condition */
--      }
--      debugger_fault_handler = NULL;
--
--      return (numChars);
--}
--
--/* scan for the sequence $<data>#<checksum> */
--static void
--getpacket(char *buffer)
--{
--      unsigned char checksum;
--      unsigned char xmitcsum;
--      int i;
--      int count;
--      unsigned char ch;
--
--      do {
--              /* wait around for the start character, ignore all other
--               * characters */
--              while ((ch = (getDebugChar() & 0x7f)) != '$') ;
--
--              checksum = 0;
--              xmitcsum = -1;
--
--              count = 0;
--
--              /* now, read until a # or end of buffer is found */
--              while (count < BUFMAX) {
--                      ch = getDebugChar() & 0x7f;
--                      if (ch == '#')
--                              break;
--                      checksum = checksum + ch;
--                      buffer[count] = ch;
--                      count = count + 1;
--              }
--
--              if (count >= BUFMAX)
--                      continue;
--
--              buffer[count] = 0;
--
--              if (ch == '#') {
--                      xmitcsum = hex(getDebugChar() & 0x7f) << 4;
--                      xmitcsum |= hex(getDebugChar() & 0x7f);
--                      if (checksum != xmitcsum)
--                              putDebugChar('-');      /* failed checksum */
--                      else {
--                              putDebugChar('+'); /* successful transfer */
--                              /* if a sequence char is present, reply the ID */
--                              if (buffer[2] == ':') {
--                                      putDebugChar(buffer[0]);
--                                      putDebugChar(buffer[1]);
--                                      /* remove sequence chars from buffer */
--                                      count = strlen(buffer);
--                                      for (i=3; i <= count; i++)
--                                              buffer[i-3] = buffer[i];
--                              }
--                      }
--              }
--      } while (checksum != xmitcsum);
--}
--
--/* send the packet in buffer. */
--static void putpacket(unsigned char *buffer)
--{
--      unsigned char checksum;
--      int count;
--      unsigned char ch, recv;
--
--      /* $<packet info>#<checksum>. */
--      do {
--              putDebugChar('$');
--              checksum = 0;
--              count = 0;
--
--              while ((ch = buffer[count])) {
--                      putDebugChar(ch);
--                      checksum += ch;
--                      count += 1;
--              }
--
--              putDebugChar('#');
--              putDebugChar(hexchars[checksum >> 4]);
--              putDebugChar(hexchars[checksum & 0xf]);
--              recv = getDebugChar();
--      } while ((recv & 0x7f) != '+');
--}
--
--static void kgdb_flush_cache_all(void)
--{
--      flush_instruction_cache();
--}
--
--/* Set up exception handlers for tracing and breakpoints
-- * [could be called kgdb_init()]
-- */
--void set_debug_traps(void)
--{
--#if 0
--      unsigned char c;
--
--      save_and_cli(flags);
--
--      /* In case GDB is started before us, ack any packets (presumably
--       * "$?#xx") sitting there.
--       *
--       * I've found this code causes more problems than it solves,
--       * so that's why it's commented out.  GDB seems to work fine
--       * now starting either before or after the kernel   -bwb
--       */
--
--      while((c = getDebugChar()) != '$');
--      while((c = getDebugChar()) != '#');
--      c = getDebugChar(); /* eat first csum byte */
--      c = getDebugChar(); /* eat second csum byte */
--      putDebugChar('+'); /* ack it */
--#endif
--      debugger = kgdb;
--      debugger_bpt = kgdb_bpt;
--      debugger_sstep = kgdb_sstep;
--      debugger_iabr_match = kgdb_iabr_match;
--      debugger_dabr_match = kgdb_dabr_match;
--
--      initialized = 1;
--}
--
--static void kgdb_fault_handler(struct pt_regs *regs)
--{
--      kgdb_longjmp((long*)fault_jmp_buf, 1);
--}
--
--int kgdb_bpt(struct pt_regs *regs)
--{
--      return handle_exception(regs);
--}
--
--int kgdb_sstep(struct pt_regs *regs)
--{
--      return handle_exception(regs);
--}
--
--void kgdb(struct pt_regs *regs)
--{
--      handle_exception(regs);
--}
--
--int kgdb_iabr_match(struct pt_regs *regs)
--{
--      printk(KERN_ERR "kgdb doesn't support iabr, what?!?\n");
--      return handle_exception(regs);
--}
--
--int kgdb_dabr_match(struct pt_regs *regs)
--{
--      printk(KERN_ERR "kgdb doesn't support dabr, what?!?\n");
--      return handle_exception(regs);
--}
--
--/* Convert the hardware trap type code to a unix signal number. */
--/*
-- * This table contains the mapping between PowerPC hardware trap types, and
-- * signals, which are primarily what GDB understands.
-- */
--static struct hard_trap_info
--{
--      unsigned int tt;                /* Trap type code for powerpc */
--      unsigned char signo;            /* Signal that we map this trap into */
--} hard_trap_info[] = {
--#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
--      { 0x100, SIGINT  },             /* critical input interrupt */
--      { 0x200, SIGSEGV },             /* machine check */
--      { 0x300, SIGSEGV },             /* data storage */
--      { 0x400, SIGBUS  },             /* instruction storage */
--      { 0x500, SIGINT  },             /* interrupt */
--      { 0x600, SIGBUS  },             /* alignment */
--      { 0x700, SIGILL  },             /* program */
--      { 0x800, SIGILL  },             /* reserved */
--      { 0x900, SIGILL  },             /* reserved */
--      { 0xa00, SIGILL  },             /* reserved */
--      { 0xb00, SIGILL  },             /* reserved */
--      { 0xc00, SIGCHLD },             /* syscall */
--      { 0xd00, SIGILL  },             /* reserved */
--      { 0xe00, SIGILL  },             /* reserved */
--      { 0xf00, SIGILL  },             /* reserved */
--      /*
--      ** 0x1000  PIT
--      ** 0x1010  FIT
--      ** 0x1020  watchdog
--      ** 0x1100  data TLB miss
--      ** 0x1200  instruction TLB miss
--      */
--      { 0x2002, SIGTRAP},             /* debug */
--#else
--      { 0x200, SIGSEGV },             /* machine check */
--      { 0x300, SIGSEGV },             /* address error (store) */
--      { 0x400, SIGBUS },              /* instruction bus error */
--      { 0x500, SIGINT },              /* interrupt */
--      { 0x600, SIGBUS },              /* alingment */
--      { 0x700, SIGTRAP },             /* breakpoint trap */
--      { 0x800, SIGFPE },              /* fpu unavail */
--      { 0x900, SIGALRM },             /* decrementer */
--      { 0xa00, SIGILL },              /* reserved */
--      { 0xb00, SIGILL },              /* reserved */
--      { 0xc00, SIGCHLD },             /* syscall */
--      { 0xd00, SIGTRAP },             /* single-step/watch */
--      { 0xe00, SIGFPE },              /* fp assist */
--#endif
--      { 0, 0}                         /* Must be last */
--
--};
--
--static int computeSignal(unsigned int tt)
--{
--      struct hard_trap_info *ht;
--
--      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
--              if (ht->tt == tt)
--                      return ht->signo;
--
--      return SIGHUP; /* default for things we don't know about */
--}
--
--#define PC_REGNUM 64
--#define SP_REGNUM 1
--
--/*
-- * This function does all command processing for interfacing to gdb.
-- */
--static int
--handle_exception (struct pt_regs *regs)
--{
--      int sigval;
--      int addr;
--      int length;
--      char *ptr;
--      unsigned int msr;
--
--      /* We don't handle user-mode breakpoints. */
--      if (user_mode(regs))
--              return 0;
--
--      if (debugger_fault_handler) {
--              debugger_fault_handler(regs);
--              panic("kgdb longjump failed!\n");
--      }
--      if (kgdb_active) {
--              printk(KERN_ERR "interrupt while in kgdb, returning\n");
--              return 0;
--      }
--
--      kgdb_active = 1;
--      kgdb_started = 1;
--
--#ifdef KGDB_DEBUG
--      printk("kgdb: entering handle_exception; trap [0x%x]\n",
--                      (unsigned int)regs->trap);
--#endif
--
--      kgdb_interruptible(0);
--      lock_kernel();
--      msr = mfmsr();
--      mtmsr(msr & ~MSR_EE);   /* disable interrupts */
--
--      if (regs->nip == (unsigned long)breakinst) {
--              /* Skip over breakpoint trap insn */
--              regs->nip += 4;
--      }
--
--      /* reply to host that an exception has occurred */
--      sigval = computeSignal(regs->trap);
--      ptr = remcomOutBuffer;
--
--      *ptr++ = 'T';
--      *ptr++ = hexchars[sigval >> 4];
--      *ptr++ = hexchars[sigval & 0xf];
--      *ptr++ = hexchars[PC_REGNUM >> 4];
--      *ptr++ = hexchars[PC_REGNUM & 0xf];
--      *ptr++ = ':';
--      ptr = mem2hex((char *)&regs->nip, ptr, 4);
--      *ptr++ = ';';
--      *ptr++ = hexchars[SP_REGNUM >> 4];
--      *ptr++ = hexchars[SP_REGNUM & 0xf];
--      *ptr++ = ':';
--      ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4);
--      *ptr++ = ';';
--      *ptr++ = 0;
--
--      putpacket(remcomOutBuffer);
--      if (kdebug)
--              printk("remcomOutBuffer: %s\n", remcomOutBuffer);
--
--      /* XXX We may want to add some features dealing with poking the
--       * XXX page tables, ... (look at sparc-stub.c for more info)
--       * XXX also required hacking to the gdb sources directly...
--       */
--
--      while (1) {
--              remcomOutBuffer[0] = 0;
--
--              getpacket(remcomInBuffer);
--              switch (remcomInBuffer[0]) {
--              case '?': /* report most recent signal */
--                      remcomOutBuffer[0] = 'S';
--                      remcomOutBuffer[1] = hexchars[sigval >> 4];
--                      remcomOutBuffer[2] = hexchars[sigval & 0xf];
--                      remcomOutBuffer[3] = 0;
--                      break;
--#if 0
--              case 'q': /* this screws up gdb for some reason...*/
--              {
--                      extern long _start, sdata, __bss_start;
--
--                      ptr = &remcomInBuffer[1];
--                      if (strncmp(ptr, "Offsets", 7) != 0)
--                              break;
--
--                      ptr = remcomOutBuffer;
--                      sprintf(ptr, "Text=%8.8x;Data=%8.8x;Bss=%8.8x",
--                              &_start, &sdata, &__bss_start);
--                      break;
--              }
--#endif
--              case 'd':
--                      /* toggle debug flag */
--                      kdebug ^= 1;
--                      break;
--
--              case 'g':       /* return the value of the CPU registers.
--                               * some of them are non-PowerPC names :(
--                               * they are stored in gdb like:
--                               * struct {
--                               *     u32 gpr[32];
--                               *     f64 fpr[32];
--                               *     u32 pc, ps, cnd, lr; (ps=msr)
--                               *     u32 cnt, xer, mq;
--                               * }
--                               */
--              {
--                      int i;
--                      ptr = remcomOutBuffer;
--                      /* General Purpose Regs */
--                      ptr = mem2hex((char *)regs, ptr, 32 * 4);
--                      /* Floating Point Regs - FIXME */
--                      /*ptr = mem2hex((char *), ptr, 32 * 8);*/
--                      for(i=0; i<(32*8*2); i++) { /* 2chars/byte */
--                              ptr[i] = '0';
--                      }
--                      ptr += 32*8*2;
--                      /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
--                      ptr = mem2hex((char *)&regs->nip, ptr, 4);
--                      ptr = mem2hex((char *)&regs->msr, ptr, 4);
--                      ptr = mem2hex((char *)&regs->ccr, ptr, 4);
--                      ptr = mem2hex((char *)&regs->link, ptr, 4);
--                      ptr = mem2hex((char *)&regs->ctr, ptr, 4);
--                      ptr = mem2hex((char *)&regs->xer, ptr, 4);
--              }
--                      break;
--
--              case 'G': /* set the value of the CPU registers */
--              {
--                      ptr = &remcomInBuffer[1];
--
--                      /*
--                       * If the stack pointer has moved, you should pray.
--                       * (cause only god can help you).
--                       */
--
--                      /* General Purpose Regs */
--                      hex2mem(ptr, (char *)regs, 32 * 4);
--
--                      /* Floating Point Regs - FIXME?? */
--                      /*ptr = hex2mem(ptr, ??, 32 * 8);*/
--                      ptr += 32*8*2;
--
--                      /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
--                      ptr = hex2mem(ptr, (char *)&regs->nip, 4);
--                      ptr = hex2mem(ptr, (char *)&regs->msr, 4);
--                      ptr = hex2mem(ptr, (char *)&regs->ccr, 4);
--                      ptr = hex2mem(ptr, (char *)&regs->link, 4);
--                      ptr = hex2mem(ptr, (char *)&regs->ctr, 4);
--                      ptr = hex2mem(ptr, (char *)&regs->xer, 4);
--
--                      strcpy(remcomOutBuffer,"OK");
--              }
--                      break;
--              case 'H':
--                      /* don't do anything, yet, just acknowledge */
--                      hexToInt(&ptr, &addr);
--                      strcpy(remcomOutBuffer,"OK");
--                      break;
--
--              case 'm':       /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
--                              /* Try to read %x,%x.  */
--
--                      ptr = &remcomInBuffer[1];
--
--                      if (hexToInt(&ptr, &addr) && *ptr++ == ','
--                                      && hexToInt(&ptr, &length)) {
--                              if (mem2hex((char *)addr, remcomOutBuffer,
--                                                      length))
--                                      break;
--                              strcpy(remcomOutBuffer, "E03");
--                      } else
--                              strcpy(remcomOutBuffer, "E01");
--                      break;
--
--              case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
--                      /* Try to read '%x,%x:'.  */
--
--                      ptr = &remcomInBuffer[1];
--
--                      if (hexToInt(&ptr, &addr) && *ptr++ == ','
--                                      && hexToInt(&ptr, &length)
--                                      && *ptr++ == ':') {
--                              if (hex2mem(ptr, (char *)addr, length))
--                                      strcpy(remcomOutBuffer, "OK");
--                              else
--                                      strcpy(remcomOutBuffer, "E03");
--                              flush_icache_range(addr, addr+length);
--                      } else
--                              strcpy(remcomOutBuffer, "E02");
--                      break;
--
--
--              case 'k': /* kill the program, actually just continue */
--              case 'c': /* cAA..AA  Continue; address AA..AA optional */
--                      /* try to read optional parameter, pc unchanged if no parm */
--
--                      ptr = &remcomInBuffer[1];
--                      if (hexToInt(&ptr, &addr))
--                              regs->nip = addr;
--
--/* Need to flush the instruction cache here, as we may have deposited a
-- * breakpoint, and the icache probably has no way of knowing that a data ref to
-- * some location may have changed something that is in the instruction cache.
-- */
--                      kgdb_flush_cache_all();
--                      mtmsr(msr);
--
--                      kgdb_interruptible(1);
--                      unlock_kernel();
--                      kgdb_active = 0;
--                      if (kdebug) {
--                              printk("remcomInBuffer: %s\n", remcomInBuffer);
--                              printk("remcomOutBuffer: %s\n", remcomOutBuffer);
--                      }
--                      return 1;
--
--              case 's':
--                      kgdb_flush_cache_all();
--#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
--                      mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC);
--                      regs->msr |= MSR_DE;
--#else
--                      regs->msr |= MSR_SE;
--#endif
--                      unlock_kernel();
--                      kgdb_active = 0;
--                      if (kdebug) {
--                              printk("remcomInBuffer: %s\n", remcomInBuffer);
--                              printk("remcomOutBuffer: %s\n", remcomOutBuffer);
--                      }
--                      return 1;
--
--              case 'r':               /* Reset (if user process..exit ???)*/
--                      panic("kgdb reset.");
--                      break;
--              }                       /* switch */
--              if (remcomOutBuffer[0] && kdebug) {
--                      printk("remcomInBuffer: %s\n", remcomInBuffer);
--                      printk("remcomOutBuffer: %s\n", remcomOutBuffer);
--              }
--              /* reply to the request */
--              putpacket(remcomOutBuffer);
--      } /* while(1) */
--}
--
--/* This function will generate a breakpoint exception.  It is used at the
--   beginning of a program to sync up with a debugger and can be used
--   otherwise as a quick means to stop program execution and "break" into
--   the debugger. */
--
--void
--breakpoint(void)
--{
--      if (!initialized) {
--              printk("breakpoint() called b4 kgdb init\n");
--              return;
--      }
--
--      asm("   .globl breakinst        \n\
--           breakinst: .long 0x7d821008");
--}
--
--#ifdef CONFIG_KGDB_CONSOLE
--/* Output string in GDB O-packet format if GDB has connected. If nothing
--   output, returns 0 (caller must then handle output). */
--int
--kgdb_output_string (const char* s, unsigned int count)
--{
--      char buffer[512];
--
--      if (!kgdb_started)
--              return 0;
--
--      count = (count <= (sizeof(buffer) / 2 - 2))
--              ? count : (sizeof(buffer) / 2 - 2);
--
--      buffer[0] = 'O';
--      mem2hex (s, &buffer[1], count);
--      putpacket(buffer);
--
--      return 1;
--}
--#endif
--
--static void sysrq_handle_gdb(int key, struct pt_regs *pt_regs,
--                           struct tty_struct *tty)
--{
--      printk("Entering GDB stub\n");
--      breakpoint();
--}
--static struct sysrq_key_op sysrq_gdb_op = {
--        .handler        = sysrq_handle_gdb,
--        .help_msg       = "Gdb",
--        .action_msg     = "GDB",
--};
--
--static int gdb_register_sysrq(void)
--{
--      printk("Registering GDB sysrq handler\n");
--      register_sysrq_key('g', &sysrq_gdb_op);
--      return 0;
--}
--module_init(gdb_register_sysrq);
-diff -Nurb linux-2.6.22-570/arch/ppc/kernel/setup.c linux-2.6.22-590/arch/ppc/kernel/setup.c
---- linux-2.6.22-570/arch/ppc/kernel/setup.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/kernel/setup.c   2008-01-02 13:56:37.000000000 -0500
-@@ -48,10 +48,6 @@
- #include <asm/ppc_sys.h>
- #endif
--#if defined CONFIG_KGDB
--#include <asm/kgdb.h>
--#endif
--
- extern void platform_init(unsigned long r3, unsigned long r4,
-               unsigned long r5, unsigned long r6, unsigned long r7);
- extern void reloc_got2(unsigned long offset);
-@@ -509,24 +505,12 @@
- #endif /* CONFIG_XMON */
-       if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
--#if defined(CONFIG_KGDB)
--      if (ppc_md.kgdb_map_scc)
--              ppc_md.kgdb_map_scc();
--      set_debug_traps();
--      if (strstr(cmd_line, "gdb")) {
--              if (ppc_md.progress)
--                      ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
--              printk("kgdb breakpoint activated\n");
--              breakpoint();
--      }
--#endif
--
-       /*
-        * Set cache line size based on type of cpu as a default.
-        * Systems with OF can look in the properties on the cpu node(s)
-        * for a possibly more accurate value.
-        */
--      if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
-+      if (! cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) {
-               dcache_bsize = cur_cpu_spec->dcache_bsize;
-               icache_bsize = cur_cpu_spec->icache_bsize;
-               ucache_bsize = 0;
-diff -Nurb linux-2.6.22-570/arch/ppc/mm/fault.c linux-2.6.22-590/arch/ppc/mm/fault.c
---- linux-2.6.22-570/arch/ppc/mm/fault.c       2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/ppc/mm/fault.c       2008-01-02 13:56:37.000000000 -0500
-@@ -25,6 +25,7 @@
- #include <linux/interrupt.h>
- #include <linux/highmem.h>
- #include <linux/module.h>
-+#include <linux/kgdb.h>
- #include <asm/page.h>
- #include <asm/pgtable.h>
-@@ -330,6 +331,14 @@
-               return;
-       }
-+#ifdef CONFIG_KGDB
-+      if (atomic_read(&debugger_active) && kgdb_may_fault) {
-+              /* Restore our previous state. */
-+              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
-+              /* Not reached. */
-+      }
-+#endif
-+
-       /* kernel has accessed a bad area */
- #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
-       if (debugger_kernel_faults)
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/4xx/bamboo.c linux-2.6.22-590/arch/ppc/platforms/4xx/bamboo.c
---- linux-2.6.22-570/arch/ppc/platforms/4xx/bamboo.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/4xx/bamboo.c   2008-01-02 13:56:37.000000000 -0500
-@@ -30,6 +30,7 @@
- #include <linux/serial.h>
- #include <linux/serial_core.h>
- #include <linux/ethtool.h>
-+#include <linux/kgdb.h>
- #include <asm/system.h>
- #include <asm/pgtable.h>
-@@ -337,10 +338,13 @@
-               printk("Early serial init of port 0 failed\n");
-       }
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       /* Configure debug serial access */
-       gen550_init(0, &port);
- #endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(0, &port);
-+#endif
-       port.membase = ioremap64(PPC440EP_UART1_ADDR, 8);
-       port.irq = 1;
-@@ -351,10 +355,13 @@
-               printk("Early serial init of port 1 failed\n");
-       }
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       /* Configure debug serial access */
-       gen550_init(1, &port);
- #endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(1, &port);
-+#endif
-       port.membase = ioremap64(PPC440EP_UART2_ADDR, 8);
-       port.irq = 3;
-@@ -365,10 +372,13 @@
-               printk("Early serial init of port 2 failed\n");
-       }
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       /* Configure debug serial access */
-       gen550_init(2, &port);
- #endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(2, &port);
-+#endif
-       port.membase = ioremap64(PPC440EP_UART3_ADDR, 8);
-       port.irq = 4;
-@@ -378,6 +388,10 @@
-       if (early_serial_setup(&port) != 0) {
-               printk("Early serial init of port 3 failed\n");
-       }
-+
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(3, &port);
-+#endif
- }
- static void __init
-@@ -435,8 +449,5 @@
-       ppc_md.nvram_read_val = todc_direct_read_val;
-       ppc_md.nvram_write_val = todc_direct_write_val;
--#ifdef CONFIG_KGDB
--      ppc_md.early_serial_map = bamboo_early_serial_map;
--#endif
- }
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/4xx/bubinga.c linux-2.6.22-590/arch/ppc/platforms/4xx/bubinga.c
---- linux-2.6.22-570/arch/ppc/platforms/4xx/bubinga.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/4xx/bubinga.c  2008-01-02 13:56:37.000000000 -0500
-@@ -4,7 +4,7 @@
-  * Author: SAW (IBM), derived from walnut.c.
-  *         Maintained by MontaVista Software <source@mvista.com>
-  *
-- * 2003 (c) MontaVista Softare Inc.  This file is licensed under the
-+ * 2003-2004 (c) MontaVista Softare Inc.  This file is licensed under the
-  * terms of the GNU General Public License version 2. This program is
-  * licensed "as is" without any warranty of any kind, whether express
-  * or implied.
-@@ -21,6 +21,7 @@
- #include <linux/tty.h>
- #include <linux/serial.h>
- #include <linux/serial_core.h>
-+#include <linux/kgdb.h>
- #include <asm/system.h>
- #include <asm/pci-bridge.h>
-@@ -30,7 +31,6 @@
- #include <asm/time.h>
- #include <asm/io.h>
- #include <asm/todc.h>
--#include <asm/kgdb.h>
- #include <asm/ocp.h>
- #include <asm/ibm_ocp_pci.h>
-@@ -100,17 +100,26 @@
-       port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-       port.line = 0;
--      if (early_serial_setup(&port) != 0) {
-+#ifdef CONFIG_SERIAL_8250
-+      if (early_serial_setup(&port) != 0)
-               printk("Early serial init of port 0 failed\n");
--      }
-+#endif
-+
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(0, &port);
-+#endif
-       port.membase = (void*)ACTING_UART1_IO_BASE;
-       port.irq = ACTING_UART1_INT;
-       port.line = 1;
--      if (early_serial_setup(&port) != 0) {
-+#ifdef CONFIG_SERIAL_8250
-+      if (early_serial_setup(&port) != 0)
-               printk("Early serial init of port 1 failed\n");
--      }
-+#endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(1, &port);
-+#endif
- }
- void __init
-@@ -257,8 +266,4 @@
-       ppc_md.nvram_read_val = todc_direct_read_val;
-       ppc_md.nvram_write_val = todc_direct_write_val;
- #endif
--#ifdef CONFIG_KGDB
--      ppc_md.early_serial_map = bubinga_early_serial_map;
--#endif
- }
--
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/4xx/ebony.c linux-2.6.22-590/arch/ppc/platforms/4xx/ebony.c
---- linux-2.6.22-570/arch/ppc/platforms/4xx/ebony.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/4xx/ebony.c    2008-01-02 13:56:37.000000000 -0500
-@@ -32,6 +32,7 @@
- #include <linux/tty.h>
- #include <linux/serial.h>
- #include <linux/serial_core.h>
-+#include <linux/kgdb.h>
- #include <asm/system.h>
- #include <asm/pgtable.h>
-@@ -226,14 +227,20 @@
-       port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-       port.line = 0;
--      if (early_serial_setup(&port) != 0) {
-+#ifdef CONFIG_SERIAL_8250
-+      if (early_serial_setup(&port) != 0)
-               printk("Early serial init of port 0 failed\n");
--      }
-+#endif
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       /* Configure debug serial access */
-       gen550_init(0, &port);
-+#endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(0, &port);
-+#endif
-+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
-       /* Purge TLB entry added in head_44x.S for early serial access */
-       _tlbie(UART0_IO_BASE);
- #endif
-@@ -243,14 +250,18 @@
-       port.uartclk = clocks.uart1;
-       port.line = 1;
--      if (early_serial_setup(&port) != 0) {
-+#ifdef CONFIG_SERIAL_8250
-+      if (early_serial_setup(&port) != 1)
-               printk("Early serial init of port 1 failed\n");
--      }
-+#endif
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       /* Configure debug serial access */
-       gen550_init(1, &port);
- #endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(1, &port);
-+#endif
- }
- static void __init
-@@ -327,8 +338,4 @@
-       ppc_md.nvram_read_val = todc_direct_read_val;
-       ppc_md.nvram_write_val = todc_direct_write_val;
--#ifdef CONFIG_KGDB
--      ppc_md.early_serial_map = ebony_early_serial_map;
--#endif
- }
--
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/4xx/luan.c linux-2.6.22-590/arch/ppc/platforms/4xx/luan.c
---- linux-2.6.22-570/arch/ppc/platforms/4xx/luan.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/4xx/luan.c     2008-01-02 13:56:37.000000000 -0500
-@@ -30,6 +30,7 @@
- #include <linux/tty.h>
- #include <linux/serial.h>
- #include <linux/serial_core.h>
-+#include <linux/kgdb.h>
- #include <asm/system.h>
- #include <asm/pgtable.h>
-@@ -283,6 +284,9 @@
-       if (early_serial_setup(&port) != 0) {
-               printk("Early serial init of port 0 failed\n");
-       }
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(0, &port);
-+#endif
-       port.membase = ioremap64(PPC440SP_UART1_ADDR, 8);
-       port.irq = UART1_INT;
-@@ -292,6 +296,9 @@
-       if (early_serial_setup(&port) != 0) {
-               printk("Early serial init of port 1 failed\n");
-       }
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(1, &port);
-+#endif
-       port.membase = ioremap64(PPC440SP_UART2_ADDR, 8);
-       port.irq = UART2_INT;
-@@ -301,6 +308,9 @@
-       if (early_serial_setup(&port) != 0) {
-               printk("Early serial init of port 2 failed\n");
-       }
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(2, &port);
-+#endif
- }
- static void __init
-@@ -360,7 +370,4 @@
-       ppc_md.get_irq = NULL;          /* Set in ppc4xx_pic_init() */
-       ppc_md.calibrate_decr = luan_calibrate_decr;
--#ifdef CONFIG_KGDB
--      ppc_md.early_serial_map = luan_early_serial_map;
--#endif
- }
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/4xx/ocotea.c linux-2.6.22-590/arch/ppc/platforms/4xx/ocotea.c
---- linux-2.6.22-570/arch/ppc/platforms/4xx/ocotea.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/4xx/ocotea.c   2008-01-02 13:56:37.000000000 -0500
-@@ -30,6 +30,7 @@
- #include <linux/tty.h>
- #include <linux/serial.h>
- #include <linux/serial_core.h>
-+#include <linux/kgdb.h>
- #include <asm/system.h>
- #include <asm/pgtable.h>
-@@ -249,14 +250,20 @@
-       port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-       port.line = 0;
--      if (early_serial_setup(&port) != 0) {
-+#ifdef CONFIG_SERIAL_8250
-+      if (early_serial_setup(&port) != 0)
-               printk("Early serial init of port 0 failed\n");
--      }
-+#endif
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       /* Configure debug serial access */
-       gen550_init(0, &port);
-+#endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(0, &port);
-+#endif
-+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
-       /* Purge TLB entry added in head_44x.S for early serial access */
-       _tlbie(UART0_IO_BASE);
- #endif
-@@ -266,14 +273,18 @@
-       port.uartclk = clocks.uart1;
-       port.line = 1;
--      if (early_serial_setup(&port) != 0) {
-+#ifdef CONFIG_SERIAL_8250
-+      if (early_serial_setup(&port) != 1)
-               printk("Early serial init of port 1 failed\n");
--      }
-+#endif
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       /* Configure debug serial access */
-       gen550_init(1, &port);
- #endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(1, &port);
-+#endif
- }
- static void __init
-@@ -343,8 +354,5 @@
-       ppc_md.nvram_read_val = todc_direct_read_val;
-       ppc_md.nvram_write_val = todc_direct_write_val;
--#ifdef CONFIG_KGDB
--      ppc_md.early_serial_map = ocotea_early_serial_map;
--#endif
-       ppc_md.init = ocotea_init;
- }
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/4xx/taishan.c linux-2.6.22-590/arch/ppc/platforms/4xx/taishan.c
---- linux-2.6.22-570/arch/ppc/platforms/4xx/taishan.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/4xx/taishan.c  2008-01-02 13:56:37.000000000 -0500
-@@ -310,7 +310,7 @@
-       if (early_serial_setup(&port) != 0)
-               printk("Early serial init of port 0 failed\n");
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       /* Configure debug serial access */
-       gen550_init(0, &port);
-@@ -326,7 +326,7 @@
-       if (early_serial_setup(&port) != 0)
-               printk("Early serial init of port 1 failed\n");
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       /* Configure debug serial access */
-       gen550_init(1, &port);
- #endif
-@@ -387,9 +387,6 @@
-       ppc_md.calibrate_decr = taishan_calibrate_decr;
--#ifdef CONFIG_KGDB
--      ppc_md.early_serial_map = taishan_early_serial_map;
--#endif
-       ppc_md.init = taishan_init;
- }
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/4xx/xilinx_ml300.c linux-2.6.22-590/arch/ppc/platforms/4xx/xilinx_ml300.c
---- linux-2.6.22-570/arch/ppc/platforms/4xx/xilinx_ml300.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/4xx/xilinx_ml300.c     2008-01-02 13:56:37.000000000 -0500
-@@ -16,6 +16,8 @@
- #include <linux/serial_core.h>
- #include <linux/serial_8250.h>
- #include <linux/serialP.h>
-+#include <linux/kgdb.h>
-+
- #include <asm/io.h>
- #include <asm/machdep.h>
-@@ -41,9 +43,6 @@
-  *      ppc4xx_map_io                         arch/ppc/syslib/ppc4xx_setup.c
-  *  start_kernel                              init/main.c
-  *    setup_arch                              arch/ppc/kernel/setup.c
-- * #if defined(CONFIG_KGDB)
-- *      *ppc_md.kgdb_map_scc() == gen550_kgdb_map_scc
-- * #endif
-  *      *ppc_md.setup_arch == ml300_setup_arch        this file
-  *        ppc4xx_setup_arch                   arch/ppc/syslib/ppc4xx_setup.c
-  *          ppc4xx_find_bridges                       arch/ppc/syslib/ppc405_pci.c
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/4xx/xilinx_ml403.c linux-2.6.22-590/arch/ppc/platforms/4xx/xilinx_ml403.c
---- linux-2.6.22-570/arch/ppc/platforms/4xx/xilinx_ml403.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/4xx/xilinx_ml403.c     2008-01-02 13:56:37.000000000 -0500
-@@ -43,9 +43,6 @@
-  *      ppc4xx_map_io                         arch/ppc/syslib/ppc4xx_setup.c
-  *  start_kernel                              init/main.c
-  *    setup_arch                              arch/ppc/kernel/setup.c
-- * #if defined(CONFIG_KGDB)
-- *      *ppc_md.kgdb_map_scc() == gen550_kgdb_map_scc
-- * #endif
-  *      *ppc_md.setup_arch == ml403_setup_arch        this file
-  *        ppc4xx_setup_arch                   arch/ppc/syslib/ppc4xx_setup.c
-  *          ppc4xx_find_bridges                       arch/ppc/syslib/ppc405_pci.c
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/4xx/yucca.c linux-2.6.22-590/arch/ppc/platforms/4xx/yucca.c
---- linux-2.6.22-570/arch/ppc/platforms/4xx/yucca.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/4xx/yucca.c    2008-01-02 13:56:37.000000000 -0500
-@@ -386,7 +386,4 @@
-       ppc_md.get_irq = NULL;          /* Set in ppc4xx_pic_init() */
-       ppc_md.calibrate_decr = yucca_calibrate_decr;
--#ifdef CONFIG_KGDB
--      ppc_md.early_serial_map = yucca_early_serial_map;
--#endif
- }
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/83xx/mpc834x_sys.c linux-2.6.22-590/arch/ppc/platforms/83xx/mpc834x_sys.c
---- linux-2.6.22-570/arch/ppc/platforms/83xx/mpc834x_sys.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/83xx/mpc834x_sys.c     2008-01-02 13:56:37.000000000 -0500
-@@ -42,11 +42,11 @@
- #include <asm/pci-bridge.h>
- #include <asm/mpc83xx.h>
- #include <asm/irq.h>
--#include <asm/kgdb.h>
- #include <asm/ppc_sys.h>
- #include <mm/mmu_decl.h>
- #include <syslib/ppc83xx_setup.h>
-+#include <syslib/gen550.h>
- #ifndef CONFIG_PCI
- unsigned long isa_io_base = 0;
-@@ -114,7 +114,9 @@
-       /* setup PCI host bridges */
-       mpc83xx_setup_hose();
- #endif
-+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_KGDB_8250)
-       mpc83xx_early_serial_map();
-+#endif
-       /* setup the board related info for the MDIO bus */
-       mdata = (struct gianfar_mdio_data *) ppc_sys_get_pdata(MPC83xx_MDIO);
-@@ -334,7 +336,6 @@
-       ppc_md.get_rtc_time = NULL;
-       ppc_md.calibrate_decr = mpc83xx_calibrate_decr;
--      ppc_md.early_serial_map = mpc83xx_early_serial_map;
- #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
-       ppc_md.progress = gen550_progress;
- #endif        /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/85xx/mpc8540_ads.c linux-2.6.22-590/arch/ppc/platforms/85xx/mpc8540_ads.c
---- linux-2.6.22-570/arch/ppc/platforms/85xx/mpc8540_ads.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/85xx/mpc8540_ads.c     2008-01-02 13:56:37.000000000 -0500
-@@ -43,11 +43,11 @@
- #include <asm/mpc85xx.h>
- #include <asm/irq.h>
- #include <asm/immap_85xx.h>
--#include <asm/kgdb.h>
- #include <asm/ppc_sys.h>
- #include <mm/mmu_decl.h>
- #include <syslib/ppc85xx_setup.h>
-+#include <syslib/gen550.h>
- /* ************************************************************************
-  *
-@@ -77,7 +77,7 @@
-       mpc85xx_setup_hose();
- #endif
--#ifdef CONFIG_SERIAL_8250
-+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_KGDB_8250)
-       mpc85xx_early_serial_map();
- #endif
-@@ -215,9 +215,6 @@
- #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
-       ppc_md.progress = gen550_progress;
- #endif        /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
--#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
--      ppc_md.early_serial_map = mpc85xx_early_serial_map;
--#endif        /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
-       if (ppc_md.progress)
-               ppc_md.progress("mpc8540ads_init(): exit", 0);
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/85xx/mpc8560_ads.c linux-2.6.22-590/arch/ppc/platforms/85xx/mpc8560_ads.c
---- linux-2.6.22-570/arch/ppc/platforms/85xx/mpc8560_ads.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/85xx/mpc8560_ads.c     2008-01-02 13:56:37.000000000 -0500
-@@ -44,7 +44,6 @@
- #include <asm/mpc85xx.h>
- #include <asm/irq.h>
- #include <asm/immap_85xx.h>
--#include <asm/kgdb.h>
- #include <asm/ppc_sys.h>
- #include <asm/cpm2.h>
- #include <mm/mmu_decl.h>
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/85xx/mpc85xx_cds_common.c linux-2.6.22-590/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
---- linux-2.6.22-570/arch/ppc/platforms/85xx/mpc85xx_cds_common.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/85xx/mpc85xx_cds_common.c      2008-01-02 13:56:37.000000000 -0500
-@@ -47,12 +47,12 @@
- #include <asm/immap_85xx.h>
- #include <asm/cpm2.h>
- #include <asm/ppc_sys.h>
--#include <asm/kgdb.h>
- #include <mm/mmu_decl.h>
- #include <syslib/cpm2_pic.h>
- #include <syslib/ppc85xx_common.h>
- #include <syslib/ppc85xx_setup.h>
-+#include <syslib/gen550.h>
- #ifndef CONFIG_PCI
-@@ -436,7 +436,7 @@
-       mpc85xx_setup_hose();
- #endif
--#ifdef CONFIG_SERIAL_8250
-+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_KGDB_8250)
-       mpc85xx_early_serial_map();
- #endif
-@@ -590,9 +590,6 @@
- #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
-       ppc_md.progress = gen550_progress;
- #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
--#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
--      ppc_md.early_serial_map = mpc85xx_early_serial_map;
--#endif        /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
-       if (ppc_md.progress)
-               ppc_md.progress("mpc85xx_cds_init(): exit", 0);
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/85xx/sbc8560.c linux-2.6.22-590/arch/ppc/platforms/85xx/sbc8560.c
---- linux-2.6.22-570/arch/ppc/platforms/85xx/sbc8560.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/85xx/sbc8560.c 2008-01-02 13:56:37.000000000 -0500
-@@ -29,6 +29,7 @@
- #include <linux/initrd.h>
- #include <linux/module.h>
- #include <linux/fsl_devices.h>
-+#include <linux/kgdb.h>
- #include <asm/system.h>
- #include <asm/pgtable.h>
-@@ -43,14 +44,13 @@
- #include <asm/mpc85xx.h>
- #include <asm/irq.h>
- #include <asm/immap_85xx.h>
--#include <asm/kgdb.h>
- #include <asm/ppc_sys.h>
- #include <mm/mmu_decl.h>
- #include <syslib/ppc85xx_common.h>
- #include <syslib/ppc85xx_setup.h>
-+#include <syslib/gen550.h>
--#ifdef CONFIG_SERIAL_8250
- static void __init
- sbc8560_early_serial_map(void)
- {
-@@ -66,12 +66,16 @@
-         uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART0_SIZE);
-       uart_req.type = PORT_16650;
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
--        gen550_init(0, &uart_req);
--#endif
-- 
-+#ifdef CONFIG_SERIAL_8250
-         if (early_serial_setup(&uart_req) != 0)
-                 printk("Early serial init of port 0 failed\n");
-+#endif
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-+      gen550_init(0, &uart_req);
-+#endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(0, &uart_req);
-+#endif
-  
-         /* Assume early_serial_setup() doesn't modify uart_req */
-       uart_req.line = 1;
-@@ -79,14 +83,17 @@
-         uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART1_SIZE);
-       uart_req.irq = MPC85xx_IRQ_EXT10;
-  
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
--        gen550_init(1, &uart_req);
--#endif
-- 
-+#ifdef CONFIG_SERIAL_8250
-         if (early_serial_setup(&uart_req) != 0)
--                printk("Early serial init of port 1 failed\n");
--}
-+              printk("Early serial init of port 0 failed\n");
- #endif
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-+      gen550_init(0, &uart_req);
-+#endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(0, &uart_req);
-+#endif
-+}
- /* ************************************************************************
-  *
-@@ -115,9 +122,7 @@
-       /* setup PCI host bridges */
-       mpc85xx_setup_hose();
- #endif
--#ifdef CONFIG_SERIAL_8250
-       sbc8560_early_serial_map();
--#endif
- #ifdef CONFIG_SERIAL_TEXT_DEBUG
-       /* Invalidate the entry we stole earlier the serial ports
-        * should be properly mapped */ 
-@@ -224,9 +229,6 @@
- #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
-       ppc_md.progress = gen550_progress;
- #endif        /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
--#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
--      ppc_md.early_serial_map = sbc8560_early_serial_map;
--#endif        /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
-       if (ppc_md.progress)
-               ppc_md.progress("sbc8560_init(): exit", 0);
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/85xx/tqm85xx.c linux-2.6.22-590/arch/ppc/platforms/85xx/tqm85xx.c
---- linux-2.6.22-570/arch/ppc/platforms/85xx/tqm85xx.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/85xx/tqm85xx.c 2008-01-02 13:56:37.000000000 -0500
-@@ -46,7 +46,6 @@
- #include <asm/mpc85xx.h>
- #include <asm/irq.h>
- #include <asm/immap_85xx.h>
--#include <asm/kgdb.h>
- #include <asm/ppc_sys.h>
- #include <asm/cpm2.h>
- #include <mm/mmu_decl.h>
-@@ -55,6 +54,7 @@
- #include <syslib/cpm2_pic.h>
- #include <syslib/ppc85xx_common.h>
- #include <syslib/ppc85xx_rio.h>
-+#include <syslib/gen550.h>
- #ifndef CONFIG_PCI
- unsigned long isa_io_base = 0;
-@@ -121,7 +121,7 @@
- #endif
- #ifndef CONFIG_MPC8560
--#if defined(CONFIG_SERIAL_8250)
-+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_KGDB_8250)
-       mpc85xx_early_serial_map();
- #endif
-@@ -400,9 +400,6 @@
- #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
-       ppc_md.progress = gen550_progress;
- #endif        /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
--#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
--      ppc_md.early_serial_map = mpc85xx_early_serial_map;
--#endif        /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
- #endif /* CONFIG_MPC8560 */
-       if (ppc_md.progress)
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/apus_setup.c linux-2.6.22-590/arch/ppc/platforms/apus_setup.c
---- linux-2.6.22-570/arch/ppc/platforms/apus_setup.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/apus_setup.c   2008-01-02 13:56:37.000000000 -0500
-@@ -598,12 +598,6 @@
-       ciab.ddra |= (SER_DTR | SER_RTS);   /* outputs */
-       ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
--#ifdef CONFIG_KGDB
--      /* turn Rx interrupts on for GDB */
--      amiga_custom.intena = IF_SETCLR | IF_RBF;
--      ser_RTSon();
--#endif
--
-       return 0;
- }
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/chestnut.c linux-2.6.22-590/arch/ppc/platforms/chestnut.c
---- linux-2.6.22-570/arch/ppc/platforms/chestnut.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/chestnut.c     2008-01-02 13:56:37.000000000 -0500
-@@ -34,9 +34,9 @@
- #include <asm/io.h>
- #include <asm/hw_irq.h>
- #include <asm/machdep.h>
--#include <asm/kgdb.h>
- #include <asm/bootinfo.h>
- #include <asm/mv64x60.h>
-+#include <syslib/gen550.h>
- #include <platforms/chestnut.h>
- static void __iomem *sram_base; /* Virtual addr of Internal SRAM */
-@@ -492,7 +492,7 @@
- static void __init
- chestnut_map_io(void)
- {
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
-       io_block_mapping(CHESTNUT_UART_BASE, CHESTNUT_UART_BASE, 0x100000,
-               _PAGE_IO);
- #endif
-@@ -566,9 +566,6 @@
- #if defined(CONFIG_SERIAL_TEXT_DEBUG)
-       ppc_md.progress = gen550_progress;
- #endif
--#if defined(CONFIG_KGDB)
--      ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
--#endif
-       if (ppc_md.progress)
-                 ppc_md.progress("chestnut_init(): exit", 0);
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/ev64260.c linux-2.6.22-590/arch/ppc/platforms/ev64260.c
---- linux-2.6.22-570/arch/ppc/platforms/ev64260.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/ev64260.c      2008-01-02 13:56:37.000000000 -0500
-@@ -330,7 +330,7 @@
-               port.iotype = UPIO_MEM;
-               port.flags = STD_COM_FLAGS;
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-               gen550_init(0, &port);
- #endif
-@@ -568,7 +568,7 @@
-       return;
- }
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
- static void __init
- ev64260_map_io(void)
- {
-@@ -624,20 +624,12 @@
-       ppc_md.setup_io_mappings = ev64260_map_io;
-       ppc_md.progress = gen550_progress;
- #endif
--#if defined(CONFIG_KGDB)
--      ppc_md.setup_io_mappings = ev64260_map_io;
--      ppc_md.early_serial_map = ev64260_early_serial_map;
--#endif
- #elif defined(CONFIG_SERIAL_MPSC_CONSOLE)
- #ifdef        CONFIG_SERIAL_TEXT_DEBUG
-       ppc_md.setup_io_mappings = ev64260_map_io;
-       ppc_md.progress = mv64x60_mpsc_progress;
-       mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
- #endif        /* CONFIG_SERIAL_TEXT_DEBUG */
--#ifdef        CONFIG_KGDB
--      ppc_md.setup_io_mappings = ev64260_map_io;
--      ppc_md.early_serial_map = ev64260_early_serial_map;
--#endif        /* CONFIG_KGDB */
- #endif
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/hdpu.c linux-2.6.22-590/arch/ppc/platforms/hdpu.c
---- linux-2.6.22-570/arch/ppc/platforms/hdpu.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/hdpu.c 2008-01-02 13:56:37.000000000 -0500
-@@ -281,25 +281,6 @@
- #if defined(CONFIG_SERIAL_MPSC_CONSOLE)
- static void __init hdpu_early_serial_map(void)
- {
--#ifdef        CONFIG_KGDB
--      static char first_time = 1;
--
--#if defined(CONFIG_KGDB_TTYS0)
--#define KGDB_PORT 0
--#elif defined(CONFIG_KGDB_TTYS1)
--#define KGDB_PORT 1
--#else
--#error "Invalid kgdb_tty port"
--#endif
--
--      if (first_time) {
--              gt_early_mpsc_init(KGDB_PORT,
--                                 B9600 | CS8 | CREAD | HUPCL | CLOCAL);
--              first_time = 0;
--      }
--
--      return;
--#endif
- }
- #endif
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/lopec.c linux-2.6.22-590/arch/ppc/platforms/lopec.c
---- linux-2.6.22-570/arch/ppc/platforms/lopec.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/lopec.c        2008-01-02 13:56:37.000000000 -0500
-@@ -32,7 +32,8 @@
- #include <asm/mpc10x.h>
- #include <asm/hw_irq.h>
- #include <asm/prep_nvram.h>
--#include <asm/kgdb.h>
-+
-+#include <syslib/gen550.h>
- /*
-  * Define all of the IRQ senses and polarities.  Taken from the
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/pplus.c linux-2.6.22-590/arch/ppc/platforms/pplus.c
---- linux-2.6.22-570/arch/ppc/platforms/pplus.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/pplus.c        2008-01-02 13:56:37.000000000 -0500
-@@ -35,9 +35,9 @@
- #include <asm/hawk.h>
- #include <asm/todc.h>
- #include <asm/bootinfo.h>
--#include <asm/kgdb.h>
- #include <asm/reg.h>
-+#include <syslib/gen550.h>
- #include "pplus.h"
- #undef DUMP_DBATS
-@@ -893,9 +893,6 @@
- #ifdef CONFIG_SERIAL_TEXT_DEBUG
-       ppc_md.progress = gen550_progress;
- #endif                                /* CONFIG_SERIAL_TEXT_DEBUG */
--#ifdef CONFIG_KGDB
--      ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
--#endif
- #ifdef CONFIG_SMP
-       smp_ops = &pplus_smp_ops;
- #endif                                /* CONFIG_SMP */
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/radstone_ppc7d.c linux-2.6.22-590/arch/ppc/platforms/radstone_ppc7d.c
---- linux-2.6.22-570/arch/ppc/platforms/radstone_ppc7d.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/radstone_ppc7d.c       2008-01-02 13:56:37.000000000 -0500
-@@ -84,7 +84,7 @@
-  * Serial port code
-  *****************************************************************************/
--#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
- static void __init ppc7d_early_serial_map(void)
- {
- #if defined(CONFIG_SERIAL_MPSC_CONSOLE)
-@@ -113,10 +113,10 @@
-       if (early_serial_setup(&serial_req) != 0)
-               printk(KERN_ERR "Early serial init of port 1 failed\n");
- #else
--#error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
-+#error CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
- #endif
- }
--#endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */
-+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
- /*****************************************************************************
-  * Low-level board support code
-@@ -1459,18 +1459,16 @@
-            PPC7D_CPLD_COMS_COM4_TXEN, PPC7D_CPLD_COMS);
- #endif /* CONFIG_SERIAL_MPSC */
--#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
--      ppc7d_early_serial_map();
- #ifdef  CONFIG_SERIAL_TEXT_DEBUG
-+      ppc7d_early_serial_map();
- #if defined(CONFIG_SERIAL_MPSC_CONSOLE)
-       ppc_md.progress = mv64x60_mpsc_progress;
- #elif defined(CONFIG_SERIAL_8250)
-       ppc_md.progress = gen550_progress;
- #else
--#error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
-+#error CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
- #endif /* CONFIG_SERIAL_8250 */
- #endif /* CONFIG_SERIAL_TEXT_DEBUG */
--#endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */
-       /* Enable write access to user flash.  This is necessary for
-        * flash probe.
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/sandpoint.c linux-2.6.22-590/arch/ppc/platforms/sandpoint.c
---- linux-2.6.22-570/arch/ppc/platforms/sandpoint.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/sandpoint.c    2008-01-02 13:56:37.000000000 -0500
-@@ -95,9 +95,9 @@
- #include <asm/bootinfo.h>
- #include <asm/mpc10x.h>
- #include <asm/pci-bridge.h>
--#include <asm/kgdb.h>
- #include <asm/ppc_sys.h>
-+#include <syslib/gen550.h>
- #include "sandpoint.h"
- /* Set non-zero if an X2 Sandpoint detected. */
-@@ -730,9 +730,6 @@
-       ppc_md.nvram_read_val = todc_mc146818_read_val;
-       ppc_md.nvram_write_val = todc_mc146818_write_val;
--#ifdef CONFIG_KGDB
--      ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
--#endif
- #ifdef CONFIG_SERIAL_TEXT_DEBUG
-       ppc_md.progress = gen550_progress;
- #endif
-diff -Nurb linux-2.6.22-570/arch/ppc/platforms/spruce.c linux-2.6.22-590/arch/ppc/platforms/spruce.c
---- linux-2.6.22-570/arch/ppc/platforms/spruce.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/platforms/spruce.c       2008-01-02 13:56:37.000000000 -0500
-@@ -27,6 +27,7 @@
- #include <linux/serial.h>
- #include <linux/tty.h>
- #include <linux/serial_core.h>
-+#include <linux/kgdb.h>
- #include <asm/system.h>
- #include <asm/pgtable.h>
-@@ -37,9 +38,9 @@
- #include <asm/time.h>
- #include <asm/todc.h>
- #include <asm/bootinfo.h>
--#include <asm/kgdb.h>
- #include <syslib/cpc700.h>
-+#include <syslib/gen550.h>
- #include "spruce.h"
-@@ -178,26 +179,32 @@
-       serial_req.membase = (u_char *)UART0_IO_BASE;
-       serial_req.regshift = 0;
--#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
--      gen550_init(0, &serial_req);
--#endif
- #ifdef CONFIG_SERIAL_8250
-       if (early_serial_setup(&serial_req) != 0)
-               printk("Early serial init of port 0 failed\n");
- #endif
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-+      gen550_init(0, &serial_req);
-+#endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(0, &port);
-+#endif
-       /* Assume early_serial_setup() doesn't modify serial_req */
-       serial_req.line = 1;
-       serial_req.irq = UART1_INT;
-       serial_req.membase = (u_char *)UART1_IO_BASE;
--#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
--      gen550_init(1, &serial_req);
--#endif
- #ifdef CONFIG_SERIAL_8250
-       if (early_serial_setup(&serial_req) != 0)
-               printk("Early serial init of port 1 failed\n");
- #endif
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-+      gen550_init(1, &serial_req);
-+#endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(1, &serial_req);
-+#endif
- }
- TODC_ALLOC();
-@@ -316,7 +323,4 @@
- #ifdef CONFIG_SERIAL_TEXT_DEBUG
-       ppc_md.progress = gen550_progress;
- #endif /* CONFIG_SERIAL_TEXT_DEBUG */
--#ifdef CONFIG_KGDB
--      ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
--#endif
- }
-diff -Nurb linux-2.6.22-570/arch/ppc/syslib/Makefile linux-2.6.22-590/arch/ppc/syslib/Makefile
---- linux-2.6.22-570/arch/ppc/syslib/Makefile  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/syslib/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -77,7 +77,6 @@
- obj-$(CONFIG_8260_PCI9)               += m8260_pci_erratum9.o
- obj-$(CONFIG_CPM2)            += cpm2_common.o cpm2_pic.o
- ifeq ($(CONFIG_PPC_GEN550),y)
--obj-$(CONFIG_KGDB)            += gen550_kgdb.o gen550_dbg.o
- obj-$(CONFIG_SERIAL_TEXT_DEBUG)       += gen550_dbg.o
- endif
- ifeq ($(CONFIG_SERIAL_MPSC_CONSOLE),y)
-diff -Nurb linux-2.6.22-570/arch/ppc/syslib/gen550.h linux-2.6.22-590/arch/ppc/syslib/gen550.h
---- linux-2.6.22-570/arch/ppc/syslib/gen550.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/syslib/gen550.h  2008-01-02 13:56:37.000000000 -0500
-@@ -11,4 +11,3 @@
- extern void gen550_progress(char *, unsigned short);
- extern void gen550_init(int, struct uart_port *);
--extern void gen550_kgdb_map_scc(void);
-diff -Nurb linux-2.6.22-570/arch/ppc/syslib/gen550_kgdb.c linux-2.6.22-590/arch/ppc/syslib/gen550_kgdb.c
---- linux-2.6.22-570/arch/ppc/syslib/gen550_kgdb.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/syslib/gen550_kgdb.c     1969-12-31 19:00:00.000000000 -0500
-@@ -1,83 +0,0 @@
--/*
-- * Generic 16550 kgdb support intended to be useful on a variety
-- * of platforms.  To enable this support, it is necessary to set
-- * the CONFIG_GEN550 option.  Any virtual mapping of the serial
-- * port(s) to be used can be accomplished by setting
-- * ppc_md.early_serial_map to a platform-specific mapping function.
-- *
-- * Adapted from ppc4xx_kgdb.c.
-- *
-- * Author: Matt Porter <mporter@kernel.crashing.org>
-- *
-- * 2002-2004 (c) MontaVista Software, Inc.  This file is licensed under
-- * the terms of the GNU General Public License version 2.  This program
-- * is licensed "as is" without any warranty of any kind, whether express
-- * or implied.
-- */
--
--#include <linux/types.h>
--#include <linux/kernel.h>
--
--#include <asm/machdep.h>
--
--extern unsigned long serial_init(int, void *);
--extern unsigned long serial_getc(unsigned long);
--extern unsigned long serial_putc(unsigned long, unsigned char);
--
--#if defined(CONFIG_KGDB_TTYS0)
--#define KGDB_PORT 0
--#elif defined(CONFIG_KGDB_TTYS1)
--#define KGDB_PORT 1
--#elif defined(CONFIG_KGDB_TTYS2)
--#define KGDB_PORT 2
--#elif defined(CONFIG_KGDB_TTYS3)
--#define KGDB_PORT 3
--#else
--#error "invalid kgdb_tty port"
--#endif
--
--static volatile unsigned int kgdb_debugport;
--
--void putDebugChar(unsigned char c)
--{
--      if (kgdb_debugport == 0)
--              kgdb_debugport = serial_init(KGDB_PORT, NULL);
--
--      serial_putc(kgdb_debugport, c);
--}
--
--int getDebugChar(void)
--{
--      if (kgdb_debugport == 0)
--              kgdb_debugport = serial_init(KGDB_PORT, NULL);
--
--      return(serial_getc(kgdb_debugport));
--}
--
--void kgdb_interruptible(int enable)
--{
--      return;
--}
--
--void putDebugString(char* str)
--{
--      while (*str != '\0') {
--              putDebugChar(*str);
--              str++;
--      }
--      putDebugChar('\r');
--      return;
--}
--
--/*
-- * Note: gen550_init() must be called already on the port we are going
-- * to use.
-- */
--void
--gen550_kgdb_map_scc(void)
--{
--      printk(KERN_DEBUG "kgdb init\n");
--      if (ppc_md.early_serial_map)
--              ppc_md.early_serial_map();
--      kgdb_debugport = serial_init(KGDB_PORT, NULL);
--}
-diff -Nurb linux-2.6.22-570/arch/ppc/syslib/ibm44x_common.c linux-2.6.22-590/arch/ppc/syslib/ibm44x_common.c
---- linux-2.6.22-570/arch/ppc/syslib/ibm44x_common.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/syslib/ibm44x_common.c   2008-01-02 13:56:37.000000000 -0500
-@@ -192,9 +192,6 @@
- #ifdef CONFIG_SERIAL_TEXT_DEBUG
-       ppc_md.progress = gen550_progress;
- #endif /* CONFIG_SERIAL_TEXT_DEBUG */
--#ifdef CONFIG_KGDB
--      ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
--#endif
-       /*
-        * The Abatron BDI JTAG debugger does not tolerate others
-diff -Nurb linux-2.6.22-570/arch/ppc/syslib/mv64x60.c linux-2.6.22-590/arch/ppc/syslib/mv64x60.c
---- linux-2.6.22-570/arch/ppc/syslib/mv64x60.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/syslib/mv64x60.c 2008-01-02 13:56:37.000000000 -0500
-@@ -241,6 +241,12 @@
-               .end    = MV64x60_IRQ_SDMA_0,
-               .flags  = IORESOURCE_IRQ,
-       },
-+      [4] = {
-+              .name   = "mpsc 0 irq",
-+              .start  = MV64x60_IRQ_MPSC_0,
-+              .end    = MV64x60_IRQ_MPSC_0,
-+              .flags  = IORESOURCE_IRQ,
-+      },
- };
- static struct platform_device mpsc0_device = {
-@@ -298,6 +304,12 @@
-               .end    = MV64360_IRQ_SDMA_1,
-               .flags  = IORESOURCE_IRQ,
-       },
-+      [4] = {
-+              .name   = "mpsc 1 irq",
-+              .start  = MV64360_IRQ_MPSC_1,
-+              .end    = MV64360_IRQ_MPSC_1,
-+              .flags  = IORESOURCE_IRQ,
-+      },
- };
- static struct platform_device mpsc1_device = {
-@@ -1432,12 +1444,46 @@
- static int __init
- mv64x60_add_pds(void)
- {
--      return platform_add_devices(mv64x60_pd_devs,
--              ARRAY_SIZE(mv64x60_pd_devs));
-+      int i, ret = 0;
-+
-+      for (i = 0; i < ARRAY_SIZE(mv64x60_pd_devs); i++) {
-+              if (mv64x60_pd_devs[i]) {
-+                      ret = platform_device_register(mv64x60_pd_devs[i]);
-+              }
-+              if (ret) {
-+                      while (--i >= 0)
-+                              platform_device_unregister(mv64x60_pd_devs[i]);
-+                      break;
-+              }
-+      }
-+      return ret;
- }
- arch_initcall(mv64x60_add_pds);
- /*
-+ * mv64x60_early_get_pdev_data()
-+ *
-+ * Get the data associated with a platform device by name and number.
-+ */
-+struct platform_device * __init
-+mv64x60_early_get_pdev_data(const char *name, int id, int remove)
-+{
-+      int i;
-+      struct platform_device *pdev;
-+
-+      for (i = 0; i <ARRAY_SIZE(mv64x60_pd_devs); i++) {
-+              if ((pdev = mv64x60_pd_devs[i]) &&
-+                      pdev->id == id &&
-+                      !strcmp(pdev->name, name)) {
-+                      if (remove)
-+                              mv64x60_pd_devs[i] = NULL;
-+                      return pdev;
-+              }
-+      }
-+      return NULL;
-+}
-+
-+/*
-  *****************************************************************************
-  *
-  *    GT64260-Specific Routines
-@@ -1770,6 +1816,11 @@
-               r->start = MV64x60_IRQ_SDMA_0;
-               r->end = MV64x60_IRQ_SDMA_0;
-       }
-+      if ((r = platform_get_resource(&mpsc1_device, IORESOURCE_IRQ, 1))
-+                      != NULL) {
-+              r->start = GT64260_IRQ_MPSC_1;
-+              r->end = GT64260_IRQ_MPSC_1;
-+      }
- #endif
- }
-@@ -2415,7 +2466,6 @@
-       .attr = {
-               .name = "hs_reg",
-               .mode = S_IRUGO | S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size  = VAL_LEN_MAX,
-       .read  = mv64xxx_hs_reg_read,
-diff -Nurb linux-2.6.22-570/arch/ppc/syslib/mv64x60_dbg.c linux-2.6.22-590/arch/ppc/syslib/mv64x60_dbg.c
---- linux-2.6.22-570/arch/ppc/syslib/mv64x60_dbg.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/syslib/mv64x60_dbg.c     2008-01-02 13:56:37.000000000 -0500
-@@ -34,7 +34,7 @@
- void
- mv64x60_progress_init(u32 base)
- {
--      mv64x60_dbg_bh.v_base = base;
-+      mv64x60_dbg_bh.v_base = (void*)base;
-       return;
- }
-@@ -69,53 +69,3 @@
-       return;
- }
- #endif        /* CONFIG_SERIAL_TEXT_DEBUG */
--
--
--#if defined(CONFIG_KGDB)
--
--#if defined(CONFIG_KGDB_TTYS0)
--#define KGDB_PORT 0
--#elif defined(CONFIG_KGDB_TTYS1)
--#define KGDB_PORT 1
--#else
--#error "Invalid kgdb_tty port"
--#endif
--
--void
--putDebugChar(unsigned char c)
--{
--      mv64x60_polled_putc(KGDB_PORT, (char)c);
--}
--
--int
--getDebugChar(void)
--{
--      unsigned char   c;
--
--      while (!mv64x60_polled_getc(KGDB_PORT, &c));
--      return (int)c;
--}
--
--void
--putDebugString(char* str)
--{
--      while (*str != '\0') {
--              putDebugChar(*str);
--              str++;
--      }
--      putDebugChar('\r');
--      return;
--}
--
--void
--kgdb_interruptible(int enable)
--{
--}
--
--void
--kgdb_map_scc(void)
--{
--      if (ppc_md.early_serial_map)
--              ppc_md.early_serial_map();
--}
--#endif        /* CONFIG_KGDB */
-diff -Nurb linux-2.6.22-570/arch/ppc/syslib/ppc4xx_setup.c linux-2.6.22-590/arch/ppc/syslib/ppc4xx_setup.c
---- linux-2.6.22-570/arch/ppc/syslib/ppc4xx_setup.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/syslib/ppc4xx_setup.c    2008-01-02 13:56:37.000000000 -0500
-@@ -32,7 +32,6 @@
- #include <asm/processor.h>
- #include <asm/machdep.h>
- #include <asm/page.h>
--#include <asm/kgdb.h>
- #include <asm/ibm4xx.h>
- #include <asm/time.h>
- #include <asm/todc.h>
-diff -Nurb linux-2.6.22-570/arch/ppc/syslib/ppc83xx_setup.c linux-2.6.22-590/arch/ppc/syslib/ppc83xx_setup.c
---- linux-2.6.22-570/arch/ppc/syslib/ppc83xx_setup.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/syslib/ppc83xx_setup.c   2008-01-02 13:56:37.000000000 -0500
-@@ -30,12 +30,12 @@
- #include <linux/tty.h>        /* for linux/serial_core.h */
- #include <linux/serial_core.h>
- #include <linux/serial_8250.h>
-+#include <linux/kgdb.h>
- #include <asm/time.h>
- #include <asm/mpc83xx.h>
- #include <asm/mmu.h>
- #include <asm/ppc_sys.h>
--#include <asm/kgdb.h>
- #include <asm/delay.h>
- #include <asm/machdep.h>
-@@ -44,6 +44,7 @@
- #include <asm/delay.h>
- #include <syslib/ppc83xx_pci.h>
- #endif
-+#include <syslib/gen550.h>
- phys_addr_t immrbar;
-@@ -87,11 +88,11 @@
-       tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
- }
--#ifdef CONFIG_SERIAL_8250
-+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_KGDB_8250)
- void __init
- mpc83xx_early_serial_map(void)
- {
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
-       struct uart_port serial_req;
- #endif
-       struct plat_serial8250_port *pdata;
-@@ -103,27 +104,40 @@
-       pdata[0].mapbase += binfo->bi_immr_base;
-       pdata[0].membase = ioremap(pdata[0].mapbase, 0x100);
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
-       memset(&serial_req, 0, sizeof (serial_req));
-       serial_req.iotype = UPIO_MEM;
-       serial_req.mapbase = pdata[0].mapbase;
-       serial_req.membase = pdata[0].membase;
-       serial_req.regshift = 0;
-+      serial_req.irq = pdata[0].irq;
-+      serial_req.flags = pdata[0].flags;
-+      serial_req.uartclk = pdata[0].uartclk;
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       gen550_init(0, &serial_req);
- #endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(0, &serial_req);
-+#endif
-+#endif
-       pdata[1].uartclk = binfo->bi_busfreq;
-       pdata[1].mapbase += binfo->bi_immr_base;
-       pdata[1].membase = ioremap(pdata[1].mapbase, 0x100);
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
-       /* Assume gen550_init() doesn't modify serial_req */
-       serial_req.mapbase = pdata[1].mapbase;
-       serial_req.membase = pdata[1].membase;
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       gen550_init(1, &serial_req);
- #endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(1, &serial_req);
-+#endif
-+#endif
- }
- #endif
-diff -Nurb linux-2.6.22-570/arch/ppc/syslib/ppc85xx_setup.c linux-2.6.22-590/arch/ppc/syslib/ppc85xx_setup.c
---- linux-2.6.22-570/arch/ppc/syslib/ppc85xx_setup.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/ppc/syslib/ppc85xx_setup.c   2008-01-02 13:56:37.000000000 -0500
-@@ -19,16 +19,17 @@
- #include <linux/tty.h>        /* for linux/serial_core.h */
- #include <linux/serial_core.h>
- #include <linux/serial_8250.h>
-+#include <linux/kgdb.h>
- #include <asm/time.h>
- #include <asm/mpc85xx.h>
- #include <asm/immap_85xx.h>
- #include <asm/mmu.h>
- #include <asm/ppc_sys.h>
--#include <asm/kgdb.h>
- #include <asm/machdep.h>
- #include <syslib/ppc85xx_setup.h>
-+#include <syslib/gen550.h>
- extern void abort(void);
-@@ -69,11 +70,11 @@
-       mtspr(SPRN_TCR, TCR_DIE);
- }
--#ifdef CONFIG_SERIAL_8250
-+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_KGDB_8250)
- void __init
- mpc85xx_early_serial_map(void)
- {
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
-       struct uart_port serial_req;
- #endif
-       struct plat_serial8250_port *pdata;
-@@ -85,27 +86,40 @@
-       pdata[0].mapbase += binfo->bi_immr_base;
-       pdata[0].membase = ioremap(pdata[0].mapbase, MPC85xx_UART0_SIZE);
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
-       memset(&serial_req, 0, sizeof (serial_req));
-       serial_req.iotype = UPIO_MEM;
-       serial_req.mapbase = pdata[0].mapbase;
-       serial_req.membase = pdata[0].membase;
-       serial_req.regshift = 0;
-+      serial_req.irq = pdata[0].irq;
-+      serial_req.flags = pdata[0].flags;
-+      serial_req.uartclk = pdata[0].uartclk;
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       gen550_init(0, &serial_req);
- #endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(0, &serial_req);
-+#endif
-+#endif
-       pdata[1].uartclk = binfo->bi_busfreq;
-       pdata[1].mapbase += binfo->bi_immr_base;
-       pdata[1].membase = ioremap(pdata[1].mapbase, MPC85xx_UART0_SIZE);
--#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
-+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
-       /* Assume gen550_init() doesn't modify serial_req */
-       serial_req.mapbase = pdata[1].mapbase;
-       serial_req.membase = pdata[1].membase;
-+#ifdef CONFIG_SERIAL_TEXT_DEBUG
-       gen550_init(1, &serial_req);
- #endif
-+#ifdef CONFIG_KGDB_8250
-+      kgdb8250_add_port(1, &serial_req);
-+#endif
-+#endif
- }
- #endif
-@@ -363,5 +377,3 @@
-       return;
- }
- #endif /* CONFIG_PCI */
--
--
-diff -Nurb linux-2.6.22-570/arch/s390/appldata/appldata_net_sum.c linux-2.6.22-590/arch/s390/appldata/appldata_net_sum.c
---- linux-2.6.22-570/arch/s390/appldata/appldata_net_sum.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/s390/appldata/appldata_net_sum.c     2008-01-02 13:56:37.000000000 -0500
-@@ -16,6 +16,7 @@
- #include <linux/errno.h>
- #include <linux/kernel_stat.h>
- #include <linux/netdevice.h>
-+#include <net/net_namespace.h>
- #include "appldata.h"
-@@ -107,7 +108,7 @@
-       tx_dropped = 0;
-       collisions = 0;
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               stats = dev->get_stats(dev);
-               rx_packets += stats->rx_packets;
-               tx_packets += stats->tx_packets;
-diff -Nurb linux-2.6.22-570/arch/s390/kernel/ipl.c linux-2.6.22-590/arch/s390/kernel/ipl.c
---- linux-2.6.22-570/arch/s390/kernel/ipl.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/s390/kernel/ipl.c    2008-01-02 13:56:37.000000000 -0500
-@@ -314,7 +314,6 @@
-       .attr = {
-               .name = "binary_parameter",
-               .mode = S_IRUGO,
--              .owner = THIS_MODULE,
-       },
-       .size = PAGE_SIZE,
-       .read = &ipl_parameter_read,
-@@ -338,7 +337,6 @@
-       .attr = {
-               .name = "scp_data",
-               .mode = S_IRUGO,
--              .owner = THIS_MODULE,
-       },
-       .size = PAGE_SIZE,
-       .read = &ipl_scp_data_read,
-diff -Nurb linux-2.6.22-570/arch/sh/Kconfig.debug linux-2.6.22-590/arch/sh/Kconfig.debug
---- linux-2.6.22-570/arch/sh/Kconfig.debug     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/sh/Kconfig.debug     2008-01-02 13:56:37.000000000 -0500
-@@ -78,82 +78,4 @@
-         on the VM subsystem for higher order allocations. This option
-         will also use IRQ stacks to compensate for the reduced stackspace.
--config SH_KGDB
--      bool "Include KGDB kernel debugger"
--      select FRAME_POINTER
--      select DEBUG_INFO
--      help
--        Include in-kernel hooks for kgdb, the Linux kernel source level
--        debugger.  See <http://kgdb.sourceforge.net/> for more information.
--        Unless you are intending to debug the kernel, say N here.
--
--menu "KGDB configuration options"
--      depends on SH_KGDB
--
--config MORE_COMPILE_OPTIONS
--      bool "Add any additional compile options"
--      help
--        If you want to add additional CFLAGS to the kernel build, enable this
--        option and then enter what you would like to add in the next question.
--        Note however that -g is already appended with the selection of KGDB.
--
--config COMPILE_OPTIONS
--      string "Additional compile arguments"
--      depends on MORE_COMPILE_OPTIONS
--
--config KGDB_NMI
--      bool "Enter KGDB on NMI"
--      default n
--
--config SH_KGDB_CONSOLE
--      bool "Console messages through GDB"
--      depends on !SERIAL_SH_SCI_CONSOLE
--      select SERIAL_CORE_CONSOLE
--      default n
--
--config KGDB_SYSRQ
--      bool "Allow SysRq 'G' to enter KGDB"
--      default y
--
--comment "Serial port setup"
--
--config KGDB_DEFPORT
--      int "Port number (ttySCn)"
--      default "1"
--
--config KGDB_DEFBAUD
--      int "Baud rate"
--      default "115200"
--
--choice
--      prompt "Parity"
--      depends on SH_KGDB
--      default KGDB_DEFPARITY_N
--
--config KGDB_DEFPARITY_N
--      bool "None"
--
--config KGDB_DEFPARITY_E
--      bool "Even"
--
--config KGDB_DEFPARITY_O
--      bool "Odd"
--
--endchoice
--
--choice
--      prompt "Data bits"
--      depends on SH_KGDB
--      default KGDB_DEFBITS_8
--
--config KGDB_DEFBITS_8
--      bool "8"
--
--config KGDB_DEFBITS_7
--      bool "7"
--
--endchoice
--
--endmenu
--
- endmenu
-diff -Nurb linux-2.6.22-570/arch/sh/kernel/Makefile linux-2.6.22-590/arch/sh/kernel/Makefile
---- linux-2.6.22-570/arch/sh/kernel/Makefile   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/sh/kernel/Makefile   2008-01-02 13:56:37.000000000 -0500
-@@ -15,7 +15,7 @@
- obj-$(CONFIG_SMP)             += smp.o
- obj-$(CONFIG_CF_ENABLER)      += cf-enabler.o
- obj-$(CONFIG_SH_STANDARD_BIOS)        += sh_bios.o
--obj-$(CONFIG_SH_KGDB)         += kgdb_stub.o kgdb_jmp.o
-+obj-$(CONFIG_KGDB)            += kgdb.o kgdb-jmp.o
- obj-$(CONFIG_SH_CPU_FREQ)     += cpufreq.o
- obj-$(CONFIG_MODULES)         += module.o
- obj-$(CONFIG_EARLY_PRINTK)    += early_printk.o
-diff -Nurb linux-2.6.22-570/arch/sh/kernel/cpu/sh3/ex.S linux-2.6.22-590/arch/sh/kernel/cpu/sh3/ex.S
---- linux-2.6.22-570/arch/sh/kernel/cpu/sh3/ex.S       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/sh/kernel/cpu/sh3/ex.S       2008-01-02 13:56:37.000000000 -0500
-@@ -45,7 +45,7 @@
-       .long   exception_error ! reserved_instruction (filled by trap_init) /* 180 */
-       .long   exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
- ENTRY(nmi_slot)
--#if defined (CONFIG_KGDB_NMI)
-+#if defined (CONFIG_KGDB)
-       .long   debug_enter     /* 1C0 */       ! Allow trap to debugger
- #else
-       .long   exception_none  /* 1C0 */       ! Not implemented yet
-diff -Nurb linux-2.6.22-570/arch/sh/kernel/kgdb-jmp.S linux-2.6.22-590/arch/sh/kernel/kgdb-jmp.S
---- linux-2.6.22-570/arch/sh/kernel/kgdb-jmp.S 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/sh/kernel/kgdb-jmp.S 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,32 @@
-+#include <linux/linkage.h>
-+
-+ENTRY(kgdb_fault_setjmp)
-+      add     #(9*4), r4
-+      sts.l   pr, @-r4
-+      mov.l   r15, @-r4
-+      mov.l   r14, @-r4
-+      mov.l   r13, @-r4
-+      mov.l   r12, @-r4
-+      mov.l   r11, @-r4
-+      mov.l   r10, @-r4
-+      mov.l   r9, @-r4
-+      mov.l   r8, @-r4
-+      rts
-+       mov    #0, r0
-+
-+ENTRY(kgdb_fault_longjmp)
-+      mov.l   @r4+, r8
-+      mov.l   @r4+, r9
-+      mov.l   @r4+, r10
-+      mov.l   @r4+, r11
-+      mov.l   @r4+, r12
-+      mov.l   @r4+, r13
-+      mov.l   @r4+, r14
-+      mov.l   @r4+, r15
-+      lds.l   @r4+, pr
-+      mov     r5, r0
-+      tst     r0, r0
-+      bf      1f
-+      mov     #1, r0
-+1:    rts
-+       nop
-diff -Nurb linux-2.6.22-570/arch/sh/kernel/kgdb.c linux-2.6.22-590/arch/sh/kernel/kgdb.c
---- linux-2.6.22-570/arch/sh/kernel/kgdb.c     1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/sh/kernel/kgdb.c     2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,363 @@
-+/*
-+ * arch/sh/kernel/kgdb.c
-+ *
-+ * Contains SH-specific low-level support for KGDB.
-+ *
-+ * Containes extracts from code by Glenn Engel, Jim Kingdon,
-+ * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
-+ * Amit S. Kale <akale@veritas.com>,  William Gatliff <bgat@open-widgets.com>,
-+ * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>,
-+ * Henry Bell <henry.bell@st.com> and Jeremy Siegel <jsiegel@mvista.com>
-+ *
-+ * Maintainer: Tom Rini <trini@kernel.crashing.org>
-+ *
-+ * 2004 (c) MontaVista Software, Inc. This file is licensed under
-+ * the terms of the GNU General Public License version 2. This program
-+ * is licensed "as is" without any warranty of any kind, whether express
-+ * or implied.
-+ */
-+
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/smp.h>
-+#include <linux/spinlock.h>
-+#include <linux/delay.h>
-+#include <linux/linkage.h>
-+#include <linux/init.h>
-+#include <linux/kgdb.h>
-+
-+#include <asm/system.h>
-+#include <asm/current.h>
-+#include <asm/signal.h>
-+#include <asm/pgtable.h>
-+#include <asm/ptrace.h>
-+
-+extern void per_cpu_trap_init(void);
-+extern atomic_t cpu_doing_single_step;
-+
-+/* Function pointers for linkage */
-+static struct kgdb_regs trap_registers;
-+
-+/* Globals. */
-+char in_nmi;                  /* Set during NMI to prevent reentry */
-+
-+/* TRA differs sh3/4 */
-+#if defined(CONFIG_CPU_SH3)
-+#define TRA 0xffffffd0
-+#elif defined(CONFIG_CPU_SH4)
-+#define TRA 0xff000020
-+#endif
-+
-+/* Macros for single step instruction identification */
-+#define OPCODE_BT(op)         (((op) & 0xff00) == 0x8900)
-+#define OPCODE_BF(op)         (((op) & 0xff00) == 0x8b00)
-+#define OPCODE_BTF_DISP(op)   (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \
-+                            (((op) & 0x7f ) << 1))
-+#define OPCODE_BFS(op)        (((op) & 0xff00) == 0x8f00)
-+#define OPCODE_BTS(op)        (((op) & 0xff00) == 0x8d00)
-+#define OPCODE_BRA(op)        (((op) & 0xf000) == 0xa000)
-+#define OPCODE_BRA_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
-+                            (((op) & 0x7ff) << 1))
-+#define OPCODE_BRAF(op)       (((op) & 0xf0ff) == 0x0023)
-+#define OPCODE_BRAF_REG(op)   (((op) & 0x0f00) >> 8)
-+#define OPCODE_BSR(op)        (((op) & 0xf000) == 0xb000)
-+#define OPCODE_BSR_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
-+                            (((op) & 0x7ff) << 1))
-+#define OPCODE_BSRF(op)       (((op) & 0xf0ff) == 0x0003)
-+#define OPCODE_BSRF_REG(op)   (((op) >> 8) & 0xf)
-+#define OPCODE_JMP(op)        (((op) & 0xf0ff) == 0x402b)
-+#define OPCODE_JMP_REG(op)    (((op) >> 8) & 0xf)
-+#define OPCODE_JSR(op)        (((op) & 0xf0ff) == 0x400b)
-+#define OPCODE_JSR_REG(op)    (((op) >> 8) & 0xf)
-+#define OPCODE_RTS(op)        ((op) == 0xb)
-+#define OPCODE_RTE(op)        ((op) == 0x2b)
-+
-+#define SR_T_BIT_MASK           0x1
-+#define STEP_OPCODE             0xc320
-+#define BIOS_CALL_TRAP          0x3f
-+
-+/* Exception codes as per SH-4 core manual */
-+#define ADDRESS_ERROR_LOAD_VEC   7
-+#define ADDRESS_ERROR_STORE_VEC  8
-+#define TRAP_VEC                 11
-+#define INVALID_INSN_VEC         12
-+#define INVALID_SLOT_VEC         13
-+#define NMI_VEC                  14
-+#define SERIAL_BREAK_VEC         58
-+
-+/* Misc static */
-+static int stepped_address;
-+static short stepped_opcode;
-+
-+/* Translate SH-3/4 exception numbers to unix-like signal values */
-+static int compute_signal(const int excep_code)
-+{
-+      switch (excep_code) {
-+      case INVALID_INSN_VEC:
-+      case INVALID_SLOT_VEC:
-+              return SIGILL;
-+      case ADDRESS_ERROR_LOAD_VEC:
-+      case ADDRESS_ERROR_STORE_VEC:
-+              return SIGSEGV;
-+      case SERIAL_BREAK_VEC:
-+      case NMI_VEC:
-+              return SIGINT;
-+      default:
-+              /* Act like it was a break/trap. */
-+              return SIGTRAP;
-+      }
-+}
-+
-+/*
-+ * Translate the registers of the system into the format that GDB wants.  Since
-+ * we use a local structure to store things, instead of getting them out
-+ * of pt_regs, we can just do a memcpy.
-+ */
-+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *ign)
-+{
-+      memcpy(gdb_regs, &trap_registers, sizeof(trap_registers));
-+}
-+
-+/*
-+ * On SH we save: r1 (prev->thread.sp) r2 (prev->thread.pc) r4 (prev) r5 (next)
-+ * r6 (next->thread.sp) r7 (next->thread.pc)
-+ */
-+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
-+{
-+      int count;
-+
-+      for (count = 0; count < 16; count++)
-+              *(gdb_regs++) = 0;
-+      *(gdb_regs++) = p->thread.pc;
-+      *(gdb_regs++) = 0;
-+      *(gdb_regs++) = 0;
-+      *(gdb_regs++) = 0;
-+      *(gdb_regs++) = 0;
-+      *(gdb_regs++) = 0;
-+      *(gdb_regs++) = 0;
-+}
-+
-+/*
-+ * Translate the registers values that GDB has given us back into the
-+ * format of the system.  See the comment above about memcpy.
-+ */
-+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *ign)
-+{
-+      memcpy(&trap_registers, gdb_regs, sizeof(trap_registers));
-+}
-+
-+/* Calculate the new address for after a step */
-+static short *get_step_address(void)
-+{
-+      short op = *(short *)trap_registers.pc;
-+      long addr;
-+
-+      /* BT */
-+      if (OPCODE_BT(op)) {
-+              if (trap_registers.sr & SR_T_BIT_MASK)
-+                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
-+              else
-+                      addr = trap_registers.pc + 2;
-+      }
-+
-+      /* BTS */
-+      else if (OPCODE_BTS(op)) {
-+              if (trap_registers.sr & SR_T_BIT_MASK)
-+                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
-+              else
-+                      addr = trap_registers.pc + 4;   /* Not in delay slot */
-+      }
-+
-+      /* BF */
-+      else if (OPCODE_BF(op)) {
-+              if (!(trap_registers.sr & SR_T_BIT_MASK))
-+                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
-+              else
-+                      addr = trap_registers.pc + 2;
-+      }
-+
-+      /* BFS */
-+      else if (OPCODE_BFS(op)) {
-+              if (!(trap_registers.sr & SR_T_BIT_MASK))
-+                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
-+              else
-+                      addr = trap_registers.pc + 4;   /* Not in delay slot */
-+      }
-+
-+      /* BRA */
-+      else if (OPCODE_BRA(op))
-+              addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op);
-+
-+      /* BRAF */
-+      else if (OPCODE_BRAF(op))
-+              addr = trap_registers.pc + 4
-+                  + trap_registers.regs[OPCODE_BRAF_REG(op)];
-+
-+      /* BSR */
-+      else if (OPCODE_BSR(op))
-+              addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op);
-+
-+      /* BSRF */
-+      else if (OPCODE_BSRF(op))
-+              addr = trap_registers.pc + 4
-+                  + trap_registers.regs[OPCODE_BSRF_REG(op)];
-+
-+      /* JMP */
-+      else if (OPCODE_JMP(op))
-+              addr = trap_registers.regs[OPCODE_JMP_REG(op)];
-+
-+      /* JSR */
-+      else if (OPCODE_JSR(op))
-+              addr = trap_registers.regs[OPCODE_JSR_REG(op)];
-+
-+      /* RTS */
-+      else if (OPCODE_RTS(op))
-+              addr = trap_registers.pr;
-+
-+      /* RTE */
-+      else if (OPCODE_RTE(op))
-+              addr = trap_registers.regs[15];
-+
-+      /* Other */
-+      else
-+              addr = trap_registers.pc + 2;
-+
-+      kgdb_flush_icache_range(addr, addr + 2);
-+      return (short *)addr;
-+}
-+
-+/* The command loop, read and act on requests */
-+int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
-+                             char *remcom_in_buffer, char *remcom_out_buffer,
-+                             struct pt_regs *ign)
-+{
-+      unsigned long addr;
-+      char *ptr = &remcom_in_buffer[1];
-+
-+      /* Examine first char of buffer to see what we need to do */
-+      switch (remcom_in_buffer[0]) {
-+      case 'c':               /* Continue at address AA..AA (optional) */
-+      case 's':               /* Step one instruction from AA..AA */
-+              /* Try to read optional parameter, PC unchanged if none */
-+              if (kgdb_hex2long(&ptr, &addr))
-+                      trap_registers.pc = addr;
-+
-+              atomic_set(&cpu_doing_single_step, -1);
-+              if (remcom_in_buffer[0] == 's') {
-+                      /* Replace the instruction immediately after the
-+                       * current instruction (i.e. next in the expected
-+                       * flow of control) with a trap instruction, so that
-+                       * returning will cause only a single instruction to
-+                       * be executed. Note that this model is slightly
-+                       * broken for instructions with delay slots
-+                       * (e.g. B[TF]S, BSR, BRA etc), where both the branch
-+                       * and the instruction in the delay slot will be
-+                       * executed.
-+                       */
-+                      /* Determine where the target instruction will send
-+                       * us to */
-+                      unsigned short *next_addr = get_step_address();
-+                      stepped_address = (int)next_addr;
-+
-+                      /* Replace it */
-+                      stepped_opcode = *(short *)next_addr;
-+                      *next_addr = STEP_OPCODE;
-+
-+                      /* Flush and return */
-+                      kgdb_flush_icache_range((long)next_addr,
-+                                              (long)next_addr + 2);
-+                      if (kgdb_contthread)
-+                              atomic_set(&cpu_doing_single_step,
-+                                         smp_processor_id());
-+              }
-+              return 0;
-+      }
-+      return -1;
-+}
-+
-+/*
-+ * When an exception has occured, we are called.  We need to set things
-+ * up so that we can call kgdb_handle_exception to handle requests from
-+ * the remote GDB.
-+ */
-+void kgdb_exception_handler(struct pt_regs *regs)
-+{
-+      int excep_code, vbr_val;
-+      int count;
-+
-+      /* Copy kernel regs (from stack) */
-+      for (count = 0; count < 16; count++)
-+              trap_registers.regs[count] = regs->regs[count];
-+      trap_registers.pc = regs->pc;
-+      trap_registers.pr = regs->pr;
-+      trap_registers.sr = regs->sr;
-+      trap_registers.gbr = regs->gbr;
-+      trap_registers.mach = regs->mach;
-+      trap_registers.macl = regs->macl;
-+
-+      __asm__ __volatile__("stc vbr, %0":"=r"(vbr_val));
-+      trap_registers.vbr = vbr_val;
-+
-+      /* Get the execption code. */
-+      __asm__ __volatile__("stc r2_bank, %0":"=r"(excep_code));
-+
-+      excep_code >>= 5;
-+
-+      /* If we got an NMI, and KGDB is not yet initialized, call
-+       * breakpoint() to try and initialize everything for us. */
-+      if (excep_code == NMI_VEC && !kgdb_initialized) {
-+              breakpoint();
-+              return;
-+      }
-+
-+      /* TRAP_VEC exception indicates a software trap inserted in place of
-+       * code by GDB so back up PC by one instruction, as this instruction
-+       * will later be replaced by its original one.  Do NOT do this for
-+       * trap 0xff, since that indicates a compiled-in breakpoint which
-+       * will not be replaced (and we would retake the trap forever) */
-+      if (excep_code == TRAP_VEC &&
-+          (*(volatile unsigned long *)TRA != (0xff << 2)))
-+              trap_registers.pc -= 2;
-+
-+      /* If we have been single-stepping, put back the old instruction.
-+       * We use stepped_address in case we have stopped more than one
-+       * instruction away. */
-+      if (stepped_opcode != 0) {
-+              *(short *)stepped_address = stepped_opcode;
-+              kgdb_flush_icache_range(stepped_address, stepped_address + 2);
-+      }
-+      stepped_opcode = 0;
-+
-+      /* Call the stub to do the processing.  Note that not everything we
-+       * need to send back and forth lives in pt_regs. */
-+      kgdb_handle_exception(excep_code, compute_signal(excep_code), 0, regs);
-+
-+      /* Copy back the (maybe modified) registers */
-+      for (count = 0; count < 16; count++)
-+              regs->regs[count] = trap_registers.regs[count];
-+      regs->pc = trap_registers.pc;
-+      regs->pr = trap_registers.pr;
-+      regs->sr = trap_registers.sr;
-+      regs->gbr = trap_registers.gbr;
-+      regs->mach = trap_registers.mach;
-+      regs->macl = trap_registers.macl;
-+
-+      vbr_val = trap_registers.vbr;
-+      __asm__ __volatile__("ldc %0, vbr": :"r"(vbr_val));
-+}
-+
-+int __init kgdb_arch_init(void)
-+{
-+      per_cpu_trap_init();
-+
-+      return 0;
-+}
-+
-+struct kgdb_arch arch_kgdb_ops = {
-+#ifdef CONFIG_CPU_LITTLE_ENDIAN
-+      .gdb_bpt_instr = {0xff, 0xc3},
-+#else
-+      .gdb_bpt_instr = {0xc3, 0xff},
-+#endif
-+};
-diff -Nurb linux-2.6.22-570/arch/sh/kernel/kgdb_jmp.S linux-2.6.22-590/arch/sh/kernel/kgdb_jmp.S
---- linux-2.6.22-570/arch/sh/kernel/kgdb_jmp.S 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/sh/kernel/kgdb_jmp.S 1969-12-31 19:00:00.000000000 -0500
-@@ -1,33 +0,0 @@
--#include <linux/linkage.h>
--
--ENTRY(setjmp)
--      add     #(9*4), r4
--      sts.l   pr, @-r4
--      mov.l   r15, @-r4
--      mov.l   r14, @-r4
--      mov.l   r13, @-r4
--      mov.l   r12, @-r4
--      mov.l   r11, @-r4
--      mov.l   r10, @-r4
--      mov.l   r9, @-r4
--      mov.l   r8, @-r4
--      rts
--       mov    #0, r0
--
--ENTRY(longjmp)
--      mov.l   @r4+, r8
--      mov.l   @r4+, r9
--      mov.l   @r4+, r10
--      mov.l   @r4+, r11
--      mov.l   @r4+, r12
--      mov.l   @r4+, r13
--      mov.l   @r4+, r14
--      mov.l   @r4+, r15
--      lds.l   @r4+, pr
--      mov     r5, r0
--      tst     r0, r0
--      bf      1f
--      mov     #1, r0  ! in case val==0
--1:    rts
--       nop
--
-diff -Nurb linux-2.6.22-570/arch/sh/kernel/kgdb_stub.c linux-2.6.22-590/arch/sh/kernel/kgdb_stub.c
---- linux-2.6.22-570/arch/sh/kernel/kgdb_stub.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/sh/kernel/kgdb_stub.c        1969-12-31 19:00:00.000000000 -0500
-@@ -1,1093 +0,0 @@
--/*
-- * May be copied or modified under the terms of the GNU General Public
-- * License.  See linux/COPYING for more information.
-- *
-- * Contains extracts from code by Glenn Engel, Jim Kingdon,
-- * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
-- * Amit S. Kale <akale@veritas.com>,  William Gatliff <bgat@open-widgets.com>,
-- * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>.
-- *
-- * This version by Henry Bell <henry.bell@st.com>
-- * Minor modifications by Jeremy Siegel <jsiegel@mvista.com>
-- *
-- * Contains low-level support for remote debug using GDB.
-- *
-- * To enable debugger support, two things need to happen. A call to
-- * set_debug_traps() is necessary in order to allow any breakpoints
-- * or error conditions to be properly intercepted and reported to gdb.
-- * A breakpoint also needs to be generated to begin communication.  This
-- * is most easily accomplished by a call to breakpoint() which does
-- * a trapa if the initialisation phase has been successfully completed.
-- *
-- * In this case, set_debug_traps() is not used to "take over" exceptions;
-- * other kernel code is modified instead to enter the kgdb functions here
-- * when appropriate (see entry.S for breakpoint traps and NMI interrupts,
-- * see traps.c for kernel error exceptions).
-- *
-- * The following gdb commands are supported:
-- *
-- *    Command       Function                               Return value
-- *
-- *    g             return the value of the CPU registers  hex data or ENN
-- *    G             set the value of the CPU registers     OK or ENN
-- *
-- *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
-- *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
-- *    XAA..AA,LLLL: Same, but data is binary (not hex)     OK or ENN
-- *
-- *    c             Resume at current address              SNN   ( signal NN)
-- *    cAA..AA       Continue at address AA..AA             SNN
-- *    CNN;          Resume at current address with signal  SNN
-- *    CNN;AA..AA    Resume at address AA..AA with signal   SNN
-- *
-- *    s             Step one instruction                   SNN
-- *    sAA..AA       Step one instruction from AA..AA       SNN
-- *    SNN;          Step one instruction with signal       SNN
-- *    SNNAA..AA     Step one instruction from AA..AA w/NN  SNN
-- *
-- *    k             kill (Detach GDB)
-- *
-- *    d             Toggle debug flag
-- *    D             Detach GDB
-- *
-- *    Hct           Set thread t for operations,           OK or ENN
-- *                  c = 'c' (step, cont), c = 'g' (other
-- *                  operations)
-- *
-- *    qC            Query current thread ID                QCpid
-- *    qfThreadInfo  Get list of current threads (first)    m<id>
-- *    qsThreadInfo   "    "  "     "      "   (subsequent)
-- *    qOffsets      Get section offsets                  Text=x;Data=y;Bss=z
-- *
-- *    TXX           Find if thread XX is alive             OK or ENN
-- *    ?             What was the last sigval ?             SNN   (signal NN)
-- *    O             Output to GDB console
-- *
-- * Remote communication protocol.
-- *
-- *    A debug packet whose contents are <data> is encapsulated for
-- *    transmission in the form:
-- *
-- *       $ <data> # CSUM1 CSUM2
-- *
-- *       <data> must be ASCII alphanumeric and cannot include characters
-- *       '$' or '#'.  If <data> starts with two characters followed by
-- *       ':', then the existing stubs interpret this as a sequence number.
-- *
-- *       CSUM1 and CSUM2 are ascii hex representation of an 8-bit
-- *       checksum of <data>, the most significant nibble is sent first.
-- *       the hex digits 0-9,a-f are used.
-- *
-- *    Receiver responds with:
-- *
-- *       +       - if CSUM is correct and ready for next packet
-- *       -       - if CSUM is incorrect
-- *
-- * Responses can be run-length encoded to save space.  A '*' means that
-- * the next character is an ASCII encoding giving a repeat count which
-- * stands for that many repetitions of the character preceding the '*'.
-- * The encoding is n+29, yielding a printable character where n >=3
-- * (which is where RLE starts to win).  Don't use an n > 126.
-- *
-- * So "0* " means the same as "0000".
-- */
--
--#include <linux/string.h>
--#include <linux/kernel.h>
--#include <linux/sched.h>
--#include <linux/smp.h>
--#include <linux/spinlock.h>
--#include <linux/delay.h>
--#include <linux/linkage.h>
--#include <linux/init.h>
--#include <linux/console.h>
--#include <linux/sysrq.h>
--#include <asm/system.h>
--#include <asm/cacheflush.h>
--#include <asm/current.h>
--#include <asm/signal.h>
--#include <asm/pgtable.h>
--#include <asm/ptrace.h>
--#include <asm/kgdb.h>
--#include <asm/io.h>
--
--/* Function pointers for linkage */
--kgdb_debug_hook_t *kgdb_debug_hook;
--kgdb_bus_error_hook_t *kgdb_bus_err_hook;
--
--int (*kgdb_getchar)(void);
--void (*kgdb_putchar)(int);
--
--static void put_debug_char(int c)
--{
--      if (!kgdb_putchar)
--              return;
--      (*kgdb_putchar)(c);
--}
--static int get_debug_char(void)
--{
--      if (!kgdb_getchar)
--              return -1;
--      return (*kgdb_getchar)();
--}
--
--/* Num chars in in/out bound buffers, register packets need NUMREGBYTES * 2 */
--#define BUFMAX 1024
--#define NUMREGBYTES (MAXREG*4)
--#define OUTBUFMAX (NUMREGBYTES*2+512)
--
--enum regs {
--      R0 = 0, R1,  R2,  R3,   R4,   R5,  R6, R7,
--      R8, R9, R10, R11, R12,  R13,  R14, R15,
--      PC, PR, GBR, VBR, MACH, MACL, SR,
--      /*  */
--      MAXREG
--};
--
--static unsigned int registers[MAXREG];
--struct kgdb_regs trap_registers;
--
--char kgdb_in_gdb_mode;
--char in_nmi;                  /* Set during NMI to prevent reentry */
--int kgdb_nofault;             /* Boolean to ignore bus errs (i.e. in GDB) */
--int kgdb_enabled = 1;         /* Default to enabled, cmdline can disable */
--
--/* Exposed for user access */
--struct task_struct *kgdb_current;
--unsigned int kgdb_g_imask;
--int kgdb_trapa_val;
--int kgdb_excode;
--
--/* Default values for SCI (can override via kernel args in setup.c) */
--#ifndef CONFIG_KGDB_DEFPORT
--#define CONFIG_KGDB_DEFPORT 1
--#endif
--
--#ifndef CONFIG_KGDB_DEFBAUD
--#define CONFIG_KGDB_DEFBAUD 115200
--#endif
--
--#if defined(CONFIG_KGDB_DEFPARITY_E)
--#define CONFIG_KGDB_DEFPARITY 'E'
--#elif defined(CONFIG_KGDB_DEFPARITY_O)
--#define CONFIG_KGDB_DEFPARITY 'O'
--#else /* CONFIG_KGDB_DEFPARITY_N */
--#define CONFIG_KGDB_DEFPARITY 'N'
--#endif
--
--#ifdef CONFIG_KGDB_DEFBITS_7
--#define CONFIG_KGDB_DEFBITS '7'
--#else /* CONFIG_KGDB_DEFBITS_8 */
--#define CONFIG_KGDB_DEFBITS '8'
--#endif
--
--/* SCI/UART settings, used in kgdb_console_setup() */
--int  kgdb_portnum = CONFIG_KGDB_DEFPORT;
--int  kgdb_baud = CONFIG_KGDB_DEFBAUD;
--char kgdb_parity = CONFIG_KGDB_DEFPARITY;
--char kgdb_bits = CONFIG_KGDB_DEFBITS;
--
--/* Jump buffer for setjmp/longjmp */
--static jmp_buf rem_com_env;
--
--/* TRA differs sh3/4 */
--#if defined(CONFIG_CPU_SH3)
--#define TRA 0xffffffd0
--#elif defined(CONFIG_CPU_SH4)
--#define TRA 0xff000020
--#endif
--
--/* Macros for single step instruction identification */
--#define OPCODE_BT(op)         (((op) & 0xff00) == 0x8900)
--#define OPCODE_BF(op)         (((op) & 0xff00) == 0x8b00)
--#define OPCODE_BTF_DISP(op)   (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \
--                            (((op) & 0x7f ) << 1))
--#define OPCODE_BFS(op)        (((op) & 0xff00) == 0x8f00)
--#define OPCODE_BTS(op)        (((op) & 0xff00) == 0x8d00)
--#define OPCODE_BRA(op)        (((op) & 0xf000) == 0xa000)
--#define OPCODE_BRA_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
--                            (((op) & 0x7ff) << 1))
--#define OPCODE_BRAF(op)       (((op) & 0xf0ff) == 0x0023)
--#define OPCODE_BRAF_REG(op)   (((op) & 0x0f00) >> 8)
--#define OPCODE_BSR(op)        (((op) & 0xf000) == 0xb000)
--#define OPCODE_BSR_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
--                            (((op) & 0x7ff) << 1))
--#define OPCODE_BSRF(op)       (((op) & 0xf0ff) == 0x0003)
--#define OPCODE_BSRF_REG(op)   (((op) >> 8) & 0xf)
--#define OPCODE_JMP(op)        (((op) & 0xf0ff) == 0x402b)
--#define OPCODE_JMP_REG(op)    (((op) >> 8) & 0xf)
--#define OPCODE_JSR(op)        (((op) & 0xf0ff) == 0x400b)
--#define OPCODE_JSR_REG(op)    (((op) >> 8) & 0xf)
--#define OPCODE_RTS(op)        ((op) == 0xb)
--#define OPCODE_RTE(op)        ((op) == 0x2b)
--
--#define SR_T_BIT_MASK           0x1
--#define STEP_OPCODE             0xc320
--#define BIOS_CALL_TRAP          0x3f
--
--/* Exception codes as per SH-4 core manual */
--#define ADDRESS_ERROR_LOAD_VEC   7
--#define ADDRESS_ERROR_STORE_VEC  8
--#define TRAP_VEC                 11
--#define INVALID_INSN_VEC         12
--#define INVALID_SLOT_VEC         13
--#define NMI_VEC                  14
--#define USER_BREAK_VEC           15
--#define SERIAL_BREAK_VEC         58
--
--/* Misc static */
--static int stepped_address;
--static short stepped_opcode;
--static char in_buffer[BUFMAX];
--static char out_buffer[OUTBUFMAX];
--
--static void kgdb_to_gdb(const char *s);
--
--/* Convert ch to hex */
--static int hex(const char ch)
--{
--      if ((ch >= 'a') && (ch <= 'f'))
--              return (ch - 'a' + 10);
--      if ((ch >= '0') && (ch <= '9'))
--              return (ch - '0');
--      if ((ch >= 'A') && (ch <= 'F'))
--              return (ch - 'A' + 10);
--      return (-1);
--}
--
--/* Convert the memory pointed to by mem into hex, placing result in buf.
--   Returns a pointer to the last char put in buf (null) */
--static char *mem_to_hex(const char *mem, char *buf, const int count)
--{
--      int i;
--      int ch;
--      unsigned short s_val;
--      unsigned long l_val;
--
--      /* Check for 16 or 32 */
--      if (count == 2 && ((long) mem & 1) == 0) {
--              s_val = *(unsigned short *) mem;
--              mem = (char *) &s_val;
--      } else if (count == 4 && ((long) mem & 3) == 0) {
--              l_val = *(unsigned long *) mem;
--              mem = (char *) &l_val;
--      }
--      for (i = 0; i < count; i++) {
--              ch = *mem++;
--              *buf++ = highhex(ch);
--              *buf++ = lowhex(ch);
--      }
--      *buf = 0;
--      return (buf);
--}
--
--/* Convert the hex array pointed to by buf into binary, to be placed in mem.
--   Return a pointer to the character after the last byte written */
--static char *hex_to_mem(const char *buf, char *mem, const int count)
--{
--      int i;
--      unsigned char ch;
--
--      for (i = 0; i < count; i++) {
--              ch = hex(*buf++) << 4;
--              ch = ch + hex(*buf++);
--              *mem++ = ch;
--      }
--      return (mem);
--}
--
--/* While finding valid hex chars, convert to an integer, then return it */
--static int hex_to_int(char **ptr, int *int_value)
--{
--      int num_chars = 0;
--      int hex_value;
--
--      *int_value = 0;
--
--      while (**ptr) {
--              hex_value = hex(**ptr);
--              if (hex_value >= 0) {
--                      *int_value = (*int_value << 4) | hex_value;
--                      num_chars++;
--              } else
--                      break;
--              (*ptr)++;
--      }
--      return num_chars;
--}
--
--/*  Copy the binary array pointed to by buf into mem.  Fix $, #,
--    and 0x7d escaped with 0x7d.  Return a pointer to the character
--    after the last byte written. */
--static char *ebin_to_mem(const char *buf, char *mem, int count)
--{
--      for (; count > 0; count--, buf++) {
--              if (*buf == 0x7d)
--                      *mem++ = *(++buf) ^ 0x20;
--              else
--                      *mem++ = *buf;
--      }
--      return mem;
--}
--
--/* Pack a hex byte */
--static char *pack_hex_byte(char *pkt, int byte)
--{
--      *pkt++ = hexchars[(byte >> 4) & 0xf];
--      *pkt++ = hexchars[(byte & 0xf)];
--      return pkt;
--}
--
--/* Scan for the start char '$', read the packet and check the checksum */
--static void get_packet(char *buffer, int buflen)
--{
--      unsigned char checksum;
--      unsigned char xmitcsum;
--      int i;
--      int count;
--      char ch;
--
--      do {
--              /* Ignore everything until the start character */
--              while ((ch = get_debug_char()) != '$');
--
--              checksum = 0;
--              xmitcsum = -1;
--              count = 0;
--
--              /* Now, read until a # or end of buffer is found */
--              while (count < (buflen - 1)) {
--                      ch = get_debug_char();
--
--                      if (ch == '#')
--                              break;
--
--                      checksum = checksum + ch;
--                      buffer[count] = ch;
--                      count = count + 1;
--              }
--
--              buffer[count] = 0;
--
--              /* Continue to read checksum following # */
--              if (ch == '#') {
--                      xmitcsum = hex(get_debug_char()) << 4;
--                      xmitcsum += hex(get_debug_char());
--
--                      /* Checksum */
--                      if (checksum != xmitcsum)
--                              put_debug_char('-');    /* Failed checksum */
--                      else {
--                              /* Ack successful transfer */
--                              put_debug_char('+');
--
--                              /* If a sequence char is present, reply
--                                 the sequence ID */
--                              if (buffer[2] == ':') {
--                                      put_debug_char(buffer[0]);
--                                      put_debug_char(buffer[1]);
--
--                                      /* Remove sequence chars from buffer */
--                                      count = strlen(buffer);
--                                      for (i = 3; i <= count; i++)
--                                              buffer[i - 3] = buffer[i];
--                              }
--                      }
--              }
--      }
--      while (checksum != xmitcsum);   /* Keep trying while we fail */
--}
--
--/* Send the packet in the buffer with run-length encoding */
--static void put_packet(char *buffer)
--{
--      int checksum;
--      char *src;
--      int runlen;
--      int encode;
--
--      do {
--              src = buffer;
--              put_debug_char('$');
--              checksum = 0;
--
--              /* Continue while we still have chars left */
--              while (*src) {
--                      /* Check for runs up to 99 chars long */
--                      for (runlen = 1; runlen < 99; runlen++) {
--                              if (src[0] != src[runlen])
--                                      break;
--                      }
--
--                      if (runlen > 3) {
--                              /* Got a useful amount, send encoding */
--                              encode = runlen + ' ' - 4;
--                              put_debug_char(*src);   checksum += *src;
--                              put_debug_char('*');    checksum += '*';
--                              put_debug_char(encode); checksum += encode;
--                              src += runlen;
--                      } else {
--                              /* Otherwise just send the current char */
--                              put_debug_char(*src);   checksum += *src;
--                              src += 1;
--                      }
--              }
--
--              /* '#' Separator, put high and low components of checksum */
--              put_debug_char('#');
--              put_debug_char(highhex(checksum));
--              put_debug_char(lowhex(checksum));
--      }
--      while ((get_debug_char()) != '+');      /* While no ack */
--}
--
--/* A bus error has occurred - perform a longjmp to return execution and
--   allow handling of the error */
--static void kgdb_handle_bus_error(void)
--{
--      longjmp(rem_com_env, 1);
--}
--
--/* Translate SH-3/4 exception numbers to unix-like signal values */
--static int compute_signal(const int excep_code)
--{
--      int sigval;
--
--      switch (excep_code) {
--
--      case INVALID_INSN_VEC:
--      case INVALID_SLOT_VEC:
--              sigval = SIGILL;
--              break;
--      case ADDRESS_ERROR_LOAD_VEC:
--      case ADDRESS_ERROR_STORE_VEC:
--              sigval = SIGSEGV;
--              break;
--
--      case SERIAL_BREAK_VEC:
--      case NMI_VEC:
--              sigval = SIGINT;
--              break;
--
--      case USER_BREAK_VEC:
--      case TRAP_VEC:
--              sigval = SIGTRAP;
--              break;
--
--      default:
--              sigval = SIGBUS;        /* "software generated" */
--              break;
--      }
--
--      return (sigval);
--}
--
--/* Make a local copy of the registers passed into the handler (bletch) */
--static void kgdb_regs_to_gdb_regs(const struct kgdb_regs *regs,
--                                int *gdb_regs)
--{
--      gdb_regs[R0] = regs->regs[R0];
--      gdb_regs[R1] = regs->regs[R1];
--      gdb_regs[R2] = regs->regs[R2];
--      gdb_regs[R3] = regs->regs[R3];
--      gdb_regs[R4] = regs->regs[R4];
--      gdb_regs[R5] = regs->regs[R5];
--      gdb_regs[R6] = regs->regs[R6];
--      gdb_regs[R7] = regs->regs[R7];
--      gdb_regs[R8] = regs->regs[R8];
--      gdb_regs[R9] = regs->regs[R9];
--      gdb_regs[R10] = regs->regs[R10];
--      gdb_regs[R11] = regs->regs[R11];
--      gdb_regs[R12] = regs->regs[R12];
--      gdb_regs[R13] = regs->regs[R13];
--      gdb_regs[R14] = regs->regs[R14];
--      gdb_regs[R15] = regs->regs[R15];
--      gdb_regs[PC] = regs->pc;
--      gdb_regs[PR] = regs->pr;
--      gdb_regs[GBR] = regs->gbr;
--      gdb_regs[MACH] = regs->mach;
--      gdb_regs[MACL] = regs->macl;
--      gdb_regs[SR] = regs->sr;
--      gdb_regs[VBR] = regs->vbr;
--}
--
--/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
--static void gdb_regs_to_kgdb_regs(const int *gdb_regs,
--                                struct kgdb_regs *regs)
--{
--      regs->regs[R0] = gdb_regs[R0];
--      regs->regs[R1] = gdb_regs[R1];
--      regs->regs[R2] = gdb_regs[R2];
--      regs->regs[R3] = gdb_regs[R3];
--      regs->regs[R4] = gdb_regs[R4];
--      regs->regs[R5] = gdb_regs[R5];
--      regs->regs[R6] = gdb_regs[R6];
--      regs->regs[R7] = gdb_regs[R7];
--      regs->regs[R8] = gdb_regs[R8];
--      regs->regs[R9] = gdb_regs[R9];
--      regs->regs[R10] = gdb_regs[R10];
--      regs->regs[R11] = gdb_regs[R11];
--      regs->regs[R12] = gdb_regs[R12];
--      regs->regs[R13] = gdb_regs[R13];
--      regs->regs[R14] = gdb_regs[R14];
--      regs->regs[R15] = gdb_regs[R15];
--      regs->pc = gdb_regs[PC];
--      regs->pr = gdb_regs[PR];
--      regs->gbr = gdb_regs[GBR];
--      regs->mach = gdb_regs[MACH];
--      regs->macl = gdb_regs[MACL];
--      regs->sr = gdb_regs[SR];
--      regs->vbr = gdb_regs[VBR];
--}
--
--/* Calculate the new address for after a step */
--static short *get_step_address(void)
--{
--      short op = *(short *) trap_registers.pc;
--      long addr;
--
--      /* BT */
--      if (OPCODE_BT(op)) {
--              if (trap_registers.sr & SR_T_BIT_MASK)
--                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
--              else
--                      addr = trap_registers.pc + 2;
--      }
--
--      /* BTS */
--      else if (OPCODE_BTS(op)) {
--              if (trap_registers.sr & SR_T_BIT_MASK)
--                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
--              else
--                      addr = trap_registers.pc + 4;   /* Not in delay slot */
--      }
--
--      /* BF */
--      else if (OPCODE_BF(op)) {
--              if (!(trap_registers.sr & SR_T_BIT_MASK))
--                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
--              else
--                      addr = trap_registers.pc + 2;
--      }
--
--      /* BFS */
--      else if (OPCODE_BFS(op)) {
--              if (!(trap_registers.sr & SR_T_BIT_MASK))
--                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
--              else
--                      addr = trap_registers.pc + 4;   /* Not in delay slot */
--      }
--
--      /* BRA */
--      else if (OPCODE_BRA(op))
--              addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op);
--
--      /* BRAF */
--      else if (OPCODE_BRAF(op))
--              addr = trap_registers.pc + 4
--                  + trap_registers.regs[OPCODE_BRAF_REG(op)];
--
--      /* BSR */
--      else if (OPCODE_BSR(op))
--              addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op);
--
--      /* BSRF */
--      else if (OPCODE_BSRF(op))
--              addr = trap_registers.pc + 4
--                  + trap_registers.regs[OPCODE_BSRF_REG(op)];
--
--      /* JMP */
--      else if (OPCODE_JMP(op))
--              addr = trap_registers.regs[OPCODE_JMP_REG(op)];
--
--      /* JSR */
--      else if (OPCODE_JSR(op))
--              addr = trap_registers.regs[OPCODE_JSR_REG(op)];
--
--      /* RTS */
--      else if (OPCODE_RTS(op))
--              addr = trap_registers.pr;
--
--      /* RTE */
--      else if (OPCODE_RTE(op))
--              addr = trap_registers.regs[15];
--
--      /* Other */
--      else
--              addr = trap_registers.pc + 2;
--
--      kgdb_flush_icache_range(addr, addr + 2);
--      return (short *) addr;
--}
--
--/* Set up a single-step.  Replace the instruction immediately after the
--   current instruction (i.e. next in the expected flow of control) with a
--   trap instruction, so that returning will cause only a single instruction
--   to be executed. Note that this model is slightly broken for instructions
--   with delay slots (e.g. B[TF]S, BSR, BRA etc), where both the branch
--   and the instruction in the delay slot will be executed. */
--static void do_single_step(void)
--{
--      unsigned short *addr = 0;
--
--      /* Determine where the target instruction will send us to */
--      addr = get_step_address();
--      stepped_address = (int)addr;
--
--      /* Replace it */
--      stepped_opcode = *(short *)addr;
--      *addr = STEP_OPCODE;
--
--      /* Flush and return */
--      kgdb_flush_icache_range((long) addr, (long) addr + 2);
--      return;
--}
--
--/* Undo a single step */
--static void undo_single_step(void)
--{
--      /* If we have stepped, put back the old instruction */
--      /* Use stepped_address in case we stopped elsewhere */
--      if (stepped_opcode != 0) {
--              *(short*)stepped_address = stepped_opcode;
--              kgdb_flush_icache_range(stepped_address, stepped_address + 2);
--      }
--      stepped_opcode = 0;
--}
--
--/* Send a signal message */
--static void send_signal_msg(const int signum)
--{
--      out_buffer[0] = 'S';
--      out_buffer[1] = highhex(signum);
--      out_buffer[2] = lowhex(signum);
--      out_buffer[3] = 0;
--      put_packet(out_buffer);
--}
--
--/* Reply that all was well */
--static void send_ok_msg(void)
--{
--      strcpy(out_buffer, "OK");
--      put_packet(out_buffer);
--}
--
--/* Reply that an error occurred */
--static void send_err_msg(void)
--{
--      strcpy(out_buffer, "E01");
--      put_packet(out_buffer);
--}
--
--/* Empty message indicates unrecognised command */
--static void send_empty_msg(void)
--{
--      put_packet("");
--}
--
--/* Read memory due to 'm' message */
--static void read_mem_msg(void)
--{
--      char *ptr;
--      int addr;
--      int length;
--
--      /* Jmp, disable bus error handler */
--      if (setjmp(rem_com_env) == 0) {
--
--              kgdb_nofault = 1;
--
--              /* Walk through, have m<addr>,<length> */
--              ptr = &in_buffer[1];
--              if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
--                      if (hex_to_int(&ptr, &length)) {
--                              ptr = 0;
--                              if (length * 2 > OUTBUFMAX)
--                                      length = OUTBUFMAX / 2;
--                              mem_to_hex((char *) addr, out_buffer, length);
--                      }
--              if (ptr)
--                      send_err_msg();
--              else
--                      put_packet(out_buffer);
--      } else
--              send_err_msg();
--
--      /* Restore bus error handler */
--      kgdb_nofault = 0;
--}
--
--/* Write memory due to 'M' or 'X' message */
--static void write_mem_msg(int binary)
--{
--      char *ptr;
--      int addr;
--      int length;
--
--      if (setjmp(rem_com_env) == 0) {
--
--              kgdb_nofault = 1;
--
--              /* Walk through, have M<addr>,<length>:<data> */
--              ptr = &in_buffer[1];
--              if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
--                      if (hex_to_int(&ptr, &length) && (*ptr++ == ':')) {
--                              if (binary)
--                                      ebin_to_mem(ptr, (char*)addr, length);
--                              else
--                                      hex_to_mem(ptr, (char*)addr, length);
--                              kgdb_flush_icache_range(addr, addr + length);
--                              ptr = 0;
--                              send_ok_msg();
--                      }
--              if (ptr)
--                      send_err_msg();
--      } else
--              send_err_msg();
--
--      /* Restore bus error handler */
--      kgdb_nofault = 0;
--}
--
--/* Continue message  */
--static void continue_msg(void)
--{
--      /* Try to read optional parameter, PC unchanged if none */
--      char *ptr = &in_buffer[1];
--      int addr;
--
--      if (hex_to_int(&ptr, &addr))
--              trap_registers.pc = addr;
--}
--
--/* Continue message with signal */
--static void continue_with_sig_msg(void)
--{
--      int signal;
--      char *ptr = &in_buffer[1];
--      int addr;
--
--      /* Report limitation */
--      kgdb_to_gdb("Cannot force signal in kgdb, continuing anyway.\n");
--
--      /* Signal */
--      hex_to_int(&ptr, &signal);
--      if (*ptr == ';')
--              ptr++;
--
--      /* Optional address */
--      if (hex_to_int(&ptr, &addr))
--              trap_registers.pc = addr;
--}
--
--/* Step message */
--static void step_msg(void)
--{
--      continue_msg();
--      do_single_step();
--}
--
--/* Step message with signal */
--static void step_with_sig_msg(void)
--{
--      continue_with_sig_msg();
--      do_single_step();
--}
--
--/* Send register contents */
--static void send_regs_msg(void)
--{
--      kgdb_regs_to_gdb_regs(&trap_registers, registers);
--      mem_to_hex((char *) registers, out_buffer, NUMREGBYTES);
--      put_packet(out_buffer);
--}
--
--/* Set register contents - currently can't set other thread's registers */
--static void set_regs_msg(void)
--{
--      kgdb_regs_to_gdb_regs(&trap_registers, registers);
--      hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES);
--      gdb_regs_to_kgdb_regs(registers, &trap_registers);
--      send_ok_msg();
--}
--
--#ifdef CONFIG_SH_KGDB_CONSOLE
--/*
-- * Bring up the ports..
-- */
--static int kgdb_serial_setup(void)
--{
--      extern int kgdb_console_setup(struct console *co, char *options);
--      struct console dummy;
--
--      kgdb_console_setup(&dummy, 0);
--
--      return 0;
--}
--#else
--#define kgdb_serial_setup()   0
--#endif
--
--/* The command loop, read and act on requests */
--static void kgdb_command_loop(const int excep_code, const int trapa_value)
--{
--      int sigval;
--
--      if (excep_code == NMI_VEC) {
--#ifndef CONFIG_KGDB_NMI
--              printk(KERN_NOTICE "KGDB: Ignoring unexpected NMI?\n");
--              return;
--#else /* CONFIG_KGDB_NMI */
--              if (!kgdb_enabled) {
--                      kgdb_enabled = 1;
--                      kgdb_init();
--              }
--#endif /* CONFIG_KGDB_NMI */
--      }
--
--      /* Ignore if we're disabled */
--      if (!kgdb_enabled)
--              return;
--
--      /* Enter GDB mode (e.g. after detach) */
--      if (!kgdb_in_gdb_mode) {
--              /* Do serial setup, notify user, issue preemptive ack */
--              printk(KERN_NOTICE "KGDB: Waiting for GDB\n");
--              kgdb_in_gdb_mode = 1;
--              put_debug_char('+');
--      }
--
--      /* Reply to host that an exception has occurred */
--      sigval = compute_signal(excep_code);
--      send_signal_msg(sigval);
--
--      /* TRAP_VEC exception indicates a software trap inserted in place of
--         code by GDB so back up PC by one instruction, as this instruction
--         will later be replaced by its original one.  Do NOT do this for
--         trap 0xff, since that indicates a compiled-in breakpoint which
--         will not be replaced (and we would retake the trap forever) */
--      if ((excep_code == TRAP_VEC) && (trapa_value != (0x3c << 2)))
--              trap_registers.pc -= 2;
--
--      /* Undo any stepping we may have done */
--      undo_single_step();
--
--      while (1) {
--              out_buffer[0] = 0;
--              get_packet(in_buffer, BUFMAX);
--
--              /* Examine first char of buffer to see what we need to do */
--              switch (in_buffer[0]) {
--              case '?':       /* Send which signal we've received */
--                      send_signal_msg(sigval);
--                      break;
--
--              case 'g':       /* Return the values of the CPU registers */
--                      send_regs_msg();
--                      break;
--
--              case 'G':       /* Set the value of the CPU registers */
--                      set_regs_msg();
--                      break;
--
--              case 'm':       /* Read LLLL bytes address AA..AA */
--                      read_mem_msg();
--                      break;
--
--              case 'M':       /* Write LLLL bytes address AA..AA, ret OK */
--                      write_mem_msg(0);       /* 0 = data in hex */
--                      break;
--
--              case 'X':       /* Write LLLL bytes esc bin address AA..AA */
--                      if (kgdb_bits == '8')
--                              write_mem_msg(1); /* 1 = data in binary */
--                      else
--                              send_empty_msg();
--                      break;
--
--              case 'C':       /* Continue, signum included, we ignore it */
--                      continue_with_sig_msg();
--                      return;
--
--              case 'c':       /* Continue at address AA..AA (optional) */
--                      continue_msg();
--                      return;
--
--              case 'S':       /* Step, signum included, we ignore it */
--                      step_with_sig_msg();
--                      return;
--
--              case 's':       /* Step one instruction from AA..AA */
--                      step_msg();
--                      return;
--
--              case 'k':       /* 'Kill the program' with a kernel ? */
--                      break;
--
--              case 'D':       /* Detach from program, send reply OK */
--                      kgdb_in_gdb_mode = 0;
--                      send_ok_msg();
--                      get_debug_char();
--                      return;
--
--              default:
--                      send_empty_msg();
--                      break;
--              }
--      }
--}
--
--/* There has been an exception, most likely a breakpoint. */
--static void handle_exception(struct pt_regs *regs)
--{
--      int excep_code, vbr_val;
--      int count;
--      int trapa_value = ctrl_inl(TRA);
--
--      /* Copy kernel regs (from stack) */
--      for (count = 0; count < 16; count++)
--              trap_registers.regs[count] = regs->regs[count];
--      trap_registers.pc = regs->pc;
--      trap_registers.pr = regs->pr;
--      trap_registers.sr = regs->sr;
--      trap_registers.gbr = regs->gbr;
--      trap_registers.mach = regs->mach;
--      trap_registers.macl = regs->macl;
--
--      asm("stc vbr, %0":"=r"(vbr_val));
--      trap_registers.vbr = vbr_val;
--
--      /* Get excode for command loop call, user access */
--      asm("stc r2_bank, %0":"=r"(excep_code));
--      kgdb_excode = excep_code;
--
--      /* Other interesting environment items for reference */
--      asm("stc r6_bank, %0":"=r"(kgdb_g_imask));
--      kgdb_current = current;
--      kgdb_trapa_val = trapa_value;
--
--      /* Act on the exception */
--      kgdb_command_loop(excep_code, trapa_value);
--
--      kgdb_current = NULL;
--
--      /* Copy back the (maybe modified) registers */
--      for (count = 0; count < 16; count++)
--              regs->regs[count] = trap_registers.regs[count];
--      regs->pc = trap_registers.pc;
--      regs->pr = trap_registers.pr;
--      regs->sr = trap_registers.sr;
--      regs->gbr = trap_registers.gbr;
--      regs->mach = trap_registers.mach;
--      regs->macl = trap_registers.macl;
--
--      vbr_val = trap_registers.vbr;
--      asm("ldc %0, vbr": :"r"(vbr_val));
--}
--
--asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5,
--                                    unsigned long r6, unsigned long r7,
--                                    struct pt_regs __regs)
--{
--      struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
--      handle_exception(regs);
--}
--
--/* Initialise the KGDB data structures and serial configuration */
--int kgdb_init(void)
--{
--      if (!kgdb_enabled)
--              return 1;
--
--      in_nmi = 0;
--      kgdb_nofault = 0;
--      stepped_opcode = 0;
--      kgdb_in_gdb_mode = 0;
--
--      if (kgdb_serial_setup() != 0) {
--              printk(KERN_NOTICE "KGDB: serial setup error\n");
--              return -1;
--      }
--
--      /* Init ptr to exception handler */
--      kgdb_debug_hook = handle_exception;
--      kgdb_bus_err_hook = kgdb_handle_bus_error;
--
--      /* Enter kgdb now if requested, or just report init done */
--      printk(KERN_NOTICE "KGDB: stub is initialized.\n");
--
--      return 0;
--}
--
--/* Make function available for "user messages"; console will use it too. */
--
--char gdbmsgbuf[BUFMAX];
--#define MAXOUT ((BUFMAX-2)/2)
--
--static void kgdb_msg_write(const char *s, unsigned count)
--{
--      int i;
--      int wcount;
--      char *bufptr;
--
--      /* 'O'utput */
--      gdbmsgbuf[0] = 'O';
--
--      /* Fill and send buffers... */
--      while (count > 0) {
--              bufptr = gdbmsgbuf + 1;
--
--              /* Calculate how many this time */
--              wcount = (count > MAXOUT) ? MAXOUT : count;
--
--              /* Pack in hex chars */
--              for (i = 0; i < wcount; i++)
--                      bufptr = pack_hex_byte(bufptr, s[i]);
--              *bufptr = '\0';
--
--              /* Move up */
--              s += wcount;
--              count -= wcount;
--
--              /* Write packet */
--              put_packet(gdbmsgbuf);
--      }
--}
--
--static void kgdb_to_gdb(const char *s)
--{
--      kgdb_msg_write(s, strlen(s));
--}
--
--#ifdef CONFIG_SH_KGDB_CONSOLE
--void kgdb_console_write(struct console *co, const char *s, unsigned count)
--{
--      /* Bail if we're not talking to GDB */
--      if (!kgdb_in_gdb_mode)
--              return;
--
--      kgdb_msg_write(s, count);
--}
--#endif
--
--#ifdef CONFIG_KGDB_SYSRQ
--static void sysrq_handle_gdb(int key, struct tty_struct *tty)
--{
--      printk("Entering GDB stub\n");
--      breakpoint();
--}
--
--static struct sysrq_key_op sysrq_gdb_op = {
--        .handler        = sysrq_handle_gdb,
--        .help_msg       = "Gdb",
--        .action_msg     = "GDB",
--};
--
--static int gdb_register_sysrq(void)
--{
--      printk("Registering GDB sysrq handler\n");
--      register_sysrq_key('g', &sysrq_gdb_op);
--      return 0;
--}
--module_init(gdb_register_sysrq);
--#endif
-diff -Nurb linux-2.6.22-570/arch/sh/kernel/time.c linux-2.6.22-590/arch/sh/kernel/time.c
---- linux-2.6.22-570/arch/sh/kernel/time.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/sh/kernel/time.c     2008-01-02 13:56:37.000000000 -0500
-@@ -259,11 +259,4 @@
-                      ((sh_hpt_frequency + 500) / 1000) / 1000,
-                      ((sh_hpt_frequency + 500) / 1000) % 1000);
--#if defined(CONFIG_SH_KGDB)
--      /*
--       * Set up kgdb as requested. We do it here because the serial
--       * init uses the timer vars we just set up for figuring baud.
--       */
--      kgdb_init();
--#endif
- }
-diff -Nurb linux-2.6.22-570/arch/sh/kernel/traps.c linux-2.6.22-590/arch/sh/kernel/traps.c
---- linux-2.6.22-570/arch/sh/kernel/traps.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/sh/kernel/traps.c    2008-01-02 13:56:37.000000000 -0500
-@@ -25,16 +25,10 @@
- #include <linux/limits.h>
- #include <asm/system.h>
- #include <asm/uaccess.h>
-+#include <linux/kgdb.h>
--#ifdef CONFIG_SH_KGDB
--#include <asm/kgdb.h>
--#define CHK_REMOTE_DEBUG(regs)                        \
--{                                             \
--      if (kgdb_debug_hook && !user_mode(regs))\
--              (*kgdb_debug_hook)(regs);       \
--}
--#else
--#define CHK_REMOTE_DEBUG(regs)
-+#ifndef CONFIG_KGDB
-+#define kgdb_handle_exception(t, s, e, r)
- #endif
- #ifdef CONFIG_CPU_SH2
-@@ -91,7 +85,9 @@
-       printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
--      CHK_REMOTE_DEBUG(regs);
-+#ifdef CONFIG_KGDB
-+      kgdb_handle_exception(1, SIGTRAP, err, regs);
-+#endif
-       print_modules();
-       show_regs(regs);
-@@ -700,7 +696,9 @@
-       lookup_exception_vector(error_code);
-       local_irq_enable();
--      CHK_REMOTE_DEBUG(regs);
-+#ifdef CONFIG_KGDB
-+      kgdb_handle_exception(1, SIGILL, err, regs);
-+#endif
-       force_sig(SIGILL, tsk);
-       die_if_no_fixup("reserved instruction", regs, error_code);
- }
-@@ -771,7 +769,9 @@
-       lookup_exception_vector(error_code);
-       local_irq_enable();
--      CHK_REMOTE_DEBUG(regs);
-+#ifdef CONFIG_KGDB
-+      kgdb_handle_exception(1, SIGILL, err, regs);
-+#endif
-       force_sig(SIGILL, tsk);
-       die_if_no_fixup("illegal slot instruction", regs, error_code);
- }
-diff -Nurb linux-2.6.22-570/arch/sh/mm/extable.c linux-2.6.22-590/arch/sh/mm/extable.c
---- linux-2.6.22-570/arch/sh/mm/extable.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/sh/mm/extable.c      2008-01-02 13:56:37.000000000 -0500
-@@ -5,6 +5,7 @@
-  */
- #include <linux/module.h>
-+#include <linux/kgdb.h>
- #include <asm/uaccess.h>
- int fixup_exception(struct pt_regs *regs)
-@@ -16,6 +17,12 @@
-               regs->pc = fixup->fixup;
-               return 1;
-       }
-+#ifdef CONFIG_KGDB
-+      if (atomic_read(&debugger_active) && kgdb_may_fault)
-+              /* Restore our previous state. */
-+              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
-+              /* Never reached. */
-+#endif
-       return 0;
- }
-diff -Nurb linux-2.6.22-570/arch/sh/mm/fault-nommu.c linux-2.6.22-590/arch/sh/mm/fault-nommu.c
---- linux-2.6.22-570/arch/sh/mm/fault-nommu.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/sh/mm/fault-nommu.c  2008-01-02 13:56:37.000000000 -0500
-@@ -28,10 +28,6 @@
- #include <asm/mmu_context.h>
- #include <asm/cacheflush.h>
--#if defined(CONFIG_SH_KGDB)
--#include <asm/kgdb.h>
--#endif
--
- extern void die(const char *,struct pt_regs *,long);
- /*
-@@ -42,11 +38,6 @@
- asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
-                             unsigned long address)
- {
--#if defined(CONFIG_SH_KGDB)
--      if (kgdb_nofault && kgdb_bus_err_hook)
--              kgdb_bus_err_hook();
--#endif
--
-       /*
-        * Oops. The kernel tried to access some bad page. We'll have to
-        * terminate things with extreme prejudice.
-@@ -68,11 +59,6 @@
- asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
-                              unsigned long address)
- {
--#if defined(CONFIG_SH_KGDB)
--      if (kgdb_nofault && kgdb_bus_err_hook)
--              kgdb_bus_err_hook();
--#endif
--
-       if (address >= TASK_SIZE)
-               return 1;
-diff -Nurb linux-2.6.22-570/arch/sh/mm/fault.c linux-2.6.22-590/arch/sh/mm/fault.c
---- linux-2.6.22-570/arch/sh/mm/fault.c        2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/sh/mm/fault.c        2008-01-02 13:56:37.000000000 -0500
-@@ -18,7 +18,6 @@
- #include <asm/system.h>
- #include <asm/mmu_context.h>
- #include <asm/tlbflush.h>
--#include <asm/kgdb.h>
- /*
-  * This routine handles page faults.  It determines the address,
-@@ -39,11 +38,6 @@
-       trace_hardirqs_on();
-       local_irq_enable();
--#ifdef CONFIG_SH_KGDB
--      if (kgdb_nofault && kgdb_bus_err_hook)
--              kgdb_bus_err_hook();
--#endif
--
-       tsk = current;
-       mm = tsk->mm;
-       si_code = SEGV_MAPERR;
-@@ -189,6 +183,7 @@
-       }
-       die("Oops", regs, writeaccess);
-       do_exit(SIGKILL);
-+      dump_stack();
- /*
-  * We ran out of memory, or some other thing happened to us that made
-@@ -252,11 +247,6 @@
-       spinlock_t *ptl = NULL;
-       int ret = 1;
--#ifdef CONFIG_SH_KGDB
--      if (kgdb_nofault && kgdb_bus_err_hook)
--              kgdb_bus_err_hook();
--#endif
--
-       /*
-        * We don't take page faults for P1, P2, and parts of P4, these
-        * are always mapped, whether it be due to legacy behaviour in
-diff -Nurb linux-2.6.22-570/arch/sparc64/kernel/power.c linux-2.6.22-590/arch/sparc64/kernel/power.c
---- linux-2.6.22-570/arch/sparc64/kernel/power.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/sparc64/kernel/power.c       2008-01-02 13:56:37.000000000 -0500
-@@ -13,6 +13,7 @@
- #include <linux/interrupt.h>
- #include <linux/pm.h>
- #include <linux/syscalls.h>
-+#include <linux/reboot.h>
- #include <asm/system.h>
- #include <asm/auxio.h>
-@@ -33,14 +34,13 @@
- #include <linux/pci.h>
- static void __iomem *power_reg;
--static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
- static int button_pressed;
- static irqreturn_t power_handler(int irq, void *dev_id)
- {
-       if (button_pressed == 0) {
-               button_pressed = 1;
--              wake_up(&powerd_wait);
-+              orderly_poweroff(true);
-       }
-       /* FIXME: Check registers for status... */
-@@ -77,36 +77,6 @@
- EXPORT_SYMBOL(pm_power_off);
- #ifdef CONFIG_PCI
--static int powerd(void *__unused)
--{
--      static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
--      char *argv[] = { "/sbin/shutdown", "-h", "now", NULL };
--      DECLARE_WAITQUEUE(wait, current);
--
--      daemonize("powerd");
--
--      add_wait_queue(&powerd_wait, &wait);
--again:
--      for (;;) {
--              set_task_state(current, TASK_INTERRUPTIBLE);
--              if (button_pressed)
--                      break;
--              flush_signals(current);
--              schedule();
--      }
--      __set_current_state(TASK_RUNNING);
--      remove_wait_queue(&powerd_wait, &wait);
--
--      /* Ok, down we go... */
--      button_pressed = 0;
--      if (kernel_execve("/sbin/shutdown", argv, envp) < 0) {
--              printk("powerd: shutdown execution failed\n");
--              add_wait_queue(&powerd_wait, &wait);
--              goto again;
--      }
--      return 0;
--}
--
- static int __init has_button_interrupt(unsigned int irq, struct device_node *dp)
- {
-       if (irq == PCI_IRQ_NONE)
-@@ -130,12 +100,6 @@
-       poweroff_method = machine_halt;  /* able to use the standard halt */
-       if (has_button_interrupt(irq, op->node)) {
--              if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
--                      printk("Failed to start power daemon.\n");
--                      return 0;
--              }
--              printk("powerd running.\n");
--
-               if (request_irq(irq,
-                               power_handler, 0, "power", NULL) < 0)
-                       printk("power: Error, cannot register IRQ handler.\n");
-diff -Nurb linux-2.6.22-570/arch/sparc64/solaris/ioctl.c linux-2.6.22-590/arch/sparc64/solaris/ioctl.c
---- linux-2.6.22-570/arch/sparc64/solaris/ioctl.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/sparc64/solaris/ioctl.c      2008-01-02 13:56:37.000000000 -0500
-@@ -28,6 +28,7 @@
- #include <linux/compat.h>
- #include <net/sock.h>
-+#include <net/net_namespace.h>
- #include <asm/uaccess.h>
- #include <asm/termios.h>
-@@ -686,7 +687,7 @@
-                       int i = 0;
-                       
-                       read_lock_bh(&dev_base_lock);
--                      for_each_netdev(d)
-+                      for_each_netdev(&init_net, d)
-                               i++;
-                       read_unlock_bh(&dev_base_lock);
-diff -Nurb linux-2.6.22-570/arch/um/Kconfig.debug linux-2.6.22-590/arch/um/Kconfig.debug
---- linux-2.6.22-570/arch/um/Kconfig.debug     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/um/Kconfig.debug     2008-01-02 13:56:37.000000000 -0500
-@@ -47,4 +47,13 @@
-         If you're involved in UML kernel development and want to use gcov,
-         say Y.  If you're unsure, say N.
-+config DEBUG_STACK_USAGE
-+      bool "Stack utilization instrumentation"
-+      default N
-+      help
-+        Track the maximum kernel stack usage - this will look at each
-+        kernel stack at process exit and log it if it's the deepest
-+        stack seen so far.
-+
-+        This option will slow down process creation and destruction somewhat.
- endmenu
-diff -Nurb linux-2.6.22-570/arch/um/defconfig linux-2.6.22-590/arch/um/defconfig
---- linux-2.6.22-570/arch/um/defconfig 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/um/defconfig 2008-01-02 13:56:37.000000000 -0500
-@@ -527,3 +527,4 @@
- # CONFIG_RCU_TORTURE_TEST is not set
- # CONFIG_GPROF is not set
- # CONFIG_GCOV is not set
-+# CONFIG_DEBUG_STACK_USAGE is not set
-diff -Nurb linux-2.6.22-570/arch/x86_64/Kconfig linux-2.6.22-590/arch/x86_64/Kconfig
---- linux-2.6.22-570/arch/x86_64/Kconfig       2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/x86_64/Kconfig       2008-01-02 13:56:37.000000000 -0500
-@@ -698,6 +698,8 @@
- source "arch/x86_64/kernel/cpufreq/Kconfig"
-+source "drivers/cpuidle/Kconfig"
-+
- endmenu
- menu "Bus options (PCI etc.)"
-diff -Nurb linux-2.6.22-570/arch/x86_64/Kconfig.debug linux-2.6.22-590/arch/x86_64/Kconfig.debug
---- linux-2.6.22-570/arch/x86_64/Kconfig.debug 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/x86_64/Kconfig.debug 2008-01-02 13:56:37.000000000 -0500
-@@ -55,7 +55,4 @@
-         This option will slow down process creation somewhat.
--#config X86_REMOTE_DEBUG
--#       bool "kgdb debugging stub"
--
- endmenu
-diff -Nurb linux-2.6.22-570/arch/x86_64/Makefile linux-2.6.22-590/arch/x86_64/Makefile
---- linux-2.6.22-570/arch/x86_64/Makefile      2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/arch/x86_64/Makefile      2008-01-02 13:56:37.000000000 -0500
-@@ -41,7 +41,9 @@
- cflags-y += -mcmodel=kernel
- cflags-y += -pipe
- cflags-y += -Wno-sign-compare
-+ifneq ($(CONFIG_UNWIND_INFO),y)
- cflags-y += -fno-asynchronous-unwind-tables
-+endif
- ifneq ($(CONFIG_DEBUG_INFO),y)
- # -fweb shrinks the kernel a bit, but the difference is very small
- # it also messes up debugging, so don't use it for now.
-diff -Nurb linux-2.6.22-570/arch/x86_64/ia32/ia32entry.S linux-2.6.22-590/arch/x86_64/ia32/ia32entry.S
---- linux-2.6.22-570/arch/x86_64/ia32/ia32entry.S      2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/x86_64/ia32/ia32entry.S      2008-01-02 13:56:37.000000000 -0500
-@@ -731,4 +731,7 @@
-       .quad compat_sys_signalfd
-       .quad compat_sys_timerfd
-       .quad sys_eventfd
-+      .quad sys_revokeat
-+      .quad sys_frevoke               /* 325 */
-+      .quad sys_fallocate
- ia32_syscall_end:
-diff -Nurb linux-2.6.22-570/arch/x86_64/kernel/Makefile linux-2.6.22-590/arch/x86_64/kernel/Makefile
---- linux-2.6.22-570/arch/x86_64/kernel/Makefile       2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/arch/x86_64/kernel/Makefile       2008-01-02 13:56:37.000000000 -0500
-@@ -33,10 +33,12 @@
- obj-$(CONFIG_CALGARY_IOMMU)   += pci-calgary.o tce.o
- obj-$(CONFIG_SWIOTLB)         += pci-swiotlb.o
- obj-$(CONFIG_KPROBES)         += kprobes.o
-+obj-$(CONFIG_KGDB)            += kgdb.o kgdb-jmp.o
- obj-$(CONFIG_X86_PM_TIMER)    += pmtimer.o
- obj-$(CONFIG_X86_VSMP)                += vsmp.o
- obj-$(CONFIG_K8_NB)           += k8.o
- obj-$(CONFIG_AUDIT)           += audit.o
-+obj-$(CONFIG_STACK_UNWIND)    += unwind.o
- obj-$(CONFIG_MODULES)         += module.o
- obj-$(CONFIG_PCI)             += early-quirks.o
-diff -Nurb linux-2.6.22-570/arch/x86_64/kernel/kgdb-jmp.S linux-2.6.22-590/arch/x86_64/kernel/kgdb-jmp.S
---- linux-2.6.22-570/arch/x86_64/kernel/kgdb-jmp.S     1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/x86_64/kernel/kgdb-jmp.S     2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,65 @@
-+/*
-+ * arch/x86_64/kernel/kgdb-jmp.S
-+ *
-+ * Save and restore system registers so that within a limited frame we
-+ * may have a fault and "jump back" to a known safe location.
-+ *
-+ * Author: Tom Rini <trini@kernel.crashing.org>
-+ *
-+ * Cribbed from glibc, which carries the following:
-+ * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
-+ * Copyright (C) 2005 by MontaVista Software.
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program as licensed "as is" without any warranty of
-+ * any kind, whether express or implied.
-+ */
-+
-+#include <linux/linkage.h>
-+
-+#define JB_RBX                0
-+#define JB_RBP                1
-+#define JB_R12                2
-+#define JB_R13                3
-+#define JB_R14                4
-+#define JB_R15                5
-+#define JB_RSP                6
-+#define JB_PC         7
-+
-+      .code64
-+
-+/* This must be called prior to kgdb_fault_longjmp and
-+ * kgdb_fault_longjmp must not be called outside of the context of the
-+ * last call to kgdb_fault_setjmp.
-+ */
-+ENTRY(kgdb_fault_setjmp)
-+      /* Save registers. */
-+      movq %rbx, (JB_RBX*8)(%rdi)
-+      movq %rbp, (JB_RBP*8)(%rdi)
-+      movq %r12, (JB_R12*8)(%rdi)
-+      movq %r13, (JB_R13*8)(%rdi)
-+      movq %r14, (JB_R14*8)(%rdi)
-+      movq %r15, (JB_R15*8)(%rdi)
-+      leaq 8(%rsp), %rdx      /* Save SP as it will be after we return. */
-+      movq %rdx, (JB_RSP*8)(%rdi)
-+      movq (%rsp), %rax       /* Save PC we are returning to now. */
-+      movq %rax, (JB_PC*8)(%rdi)
-+      /* Set return value for setjmp. */
-+      mov $0,%eax
-+      movq (JB_PC*8)(%rdi),%rdx
-+      movq (JB_RSP*8)(%rdi),%rsp
-+      jmpq *%rdx
-+
-+ENTRY(kgdb_fault_longjmp)
-+      /* Restore registers. */
-+      movq (JB_RBX*8)(%rdi),%rbx
-+      movq (JB_RBP*8)(%rdi),%rbp
-+      movq (JB_R12*8)(%rdi),%r12
-+      movq (JB_R13*8)(%rdi),%r13
-+      movq (JB_R14*8)(%rdi),%r14
-+      movq (JB_R15*8)(%rdi),%r15
-+      /* Set return value for setjmp. */
-+      movq (JB_PC*8)(%rdi),%rdx
-+      movq (JB_RSP*8)(%rdi),%rsp
-+      mov $1,%eax
-+      jmpq *%rdx
-diff -Nurb linux-2.6.22-570/arch/x86_64/kernel/kgdb.c linux-2.6.22-590/arch/x86_64/kernel/kgdb.c
---- linux-2.6.22-570/arch/x86_64/kernel/kgdb.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/x86_64/kernel/kgdb.c 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,461 @@
-+/*
-+ *
-+ * 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, 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.
-+ *
-+ */
-+
-+/*
-+ * Copyright (C) 2004 Amit S. Kale <amitkale@linsyssoft.com>
-+ * Copyright (C) 2000-2001 VERITAS Software Corporation.
-+ * Copyright (C) 2002 Andi Kleen, SuSE Labs
-+ * Copyright (C) 2004 LinSysSoft Technologies Pvt. Ltd.
-+ * Copyright (C) 2007 Jason Wessel, Wind River Systems, Inc.
-+ */
-+/****************************************************************************
-+ *  Contributor:     Lake Stevens Instrument Division$
-+ *  Written by:      Glenn Engel $
-+ *  Updated by:            Amit Kale<akale@veritas.com>
-+ *  Modified for 386 by Jim Kingdon, Cygnus Support.
-+ *  Origianl kgdb, compatibility with 2.1.xx kernel by
-+ *  David Grothe <dave@gcom.com>
-+ *  Integrated into 2.2.5 kernel by Tigran Aivazian <tigran@sco.com>
-+ *  X86_64 changes from Andi Kleen's patch merged by Jim Houston
-+ */
-+
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/smp.h>
-+#include <linux/spinlock.h>
-+#include <linux/delay.h>
-+#include <asm/system.h>
-+#include <asm/ptrace.h>               /* for linux pt_regs struct */
-+#include <linux/kgdb.h>
-+#include <linux/init.h>
-+#include <linux/kdebug.h>
-+#include <asm/apicdef.h>
-+#include <asm/mach_apic.h>
-+#include <asm/kdebug.h>
-+#include <asm/debugreg.h>
-+
-+/* Put the error code here just in case the user cares.  */
-+int gdb_x86_64errcode;
-+/* Likewise, the vector number here (since GDB only gets the signal
-+   number through the usual means, and that's not very specific).  */
-+int gdb_x86_64vector = -1;
-+
-+extern atomic_t cpu_doing_single_step;
-+
-+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-+{
-+      gdb_regs[_RAX] = regs->rax;
-+      gdb_regs[_RBX] = regs->rbx;
-+      gdb_regs[_RCX] = regs->rcx;
-+      gdb_regs[_RDX] = regs->rdx;
-+      gdb_regs[_RSI] = regs->rsi;
-+      gdb_regs[_RDI] = regs->rdi;
-+      gdb_regs[_RBP] = regs->rbp;
-+      gdb_regs[_PS] = regs->eflags;
-+      gdb_regs[_PC] = regs->rip;
-+      gdb_regs[_R8] = regs->r8;
-+      gdb_regs[_R9] = regs->r9;
-+      gdb_regs[_R10] = regs->r10;
-+      gdb_regs[_R11] = regs->r11;
-+      gdb_regs[_R12] = regs->r12;
-+      gdb_regs[_R13] = regs->r13;
-+      gdb_regs[_R14] = regs->r14;
-+      gdb_regs[_R15] = regs->r15;
-+      gdb_regs[_RSP] = regs->rsp;
-+}
-+
-+extern void thread_return(void);
-+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
-+{
-+      gdb_regs[_RAX] = 0;
-+      gdb_regs[_RBX] = 0;
-+      gdb_regs[_RCX] = 0;
-+      gdb_regs[_RDX] = 0;
-+      gdb_regs[_RSI] = 0;
-+      gdb_regs[_RDI] = 0;
-+      gdb_regs[_RBP] = *(unsigned long *)p->thread.rsp;
-+      gdb_regs[_PS] = *(unsigned long *)(p->thread.rsp + 8);
-+      gdb_regs[_PC] = (unsigned long)&thread_return;
-+      gdb_regs[_R8] = 0;
-+      gdb_regs[_R9] = 0;
-+      gdb_regs[_R10] = 0;
-+      gdb_regs[_R11] = 0;
-+      gdb_regs[_R12] = 0;
-+      gdb_regs[_R13] = 0;
-+      gdb_regs[_R14] = 0;
-+      gdb_regs[_R15] = 0;
-+      gdb_regs[_RSP] = p->thread.rsp;
-+}
-+
-+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-+{
-+      regs->rax = gdb_regs[_RAX];
-+      regs->rbx = gdb_regs[_RBX];
-+      regs->rcx = gdb_regs[_RCX];
-+      regs->rdx = gdb_regs[_RDX];
-+      regs->rsi = gdb_regs[_RSI];
-+      regs->rdi = gdb_regs[_RDI];
-+      regs->rbp = gdb_regs[_RBP];
-+      regs->eflags = gdb_regs[_PS];
-+      regs->rip = gdb_regs[_PC];
-+      regs->r8 = gdb_regs[_R8];
-+      regs->r9 = gdb_regs[_R9];
-+      regs->r10 = gdb_regs[_R10];
-+      regs->r11 = gdb_regs[_R11];
-+      regs->r12 = gdb_regs[_R12];
-+      regs->r13 = gdb_regs[_R13];
-+      regs->r14 = gdb_regs[_R14];
-+      regs->r15 = gdb_regs[_R15];
-+#if 0                         /* can't change these */
-+      regs->rsp = gdb_regs[_RSP];
-+      regs->ss = gdb_regs[_SS];
-+      regs->fs = gdb_regs[_FS];
-+      regs->gs = gdb_regs[_GS];
-+#endif
-+
-+}                             /* gdb_regs_to_regs */
-+
-+struct hw_breakpoint {
-+      unsigned enabled;
-+      unsigned type;
-+      unsigned len;
-+      unsigned long addr;
-+} breakinfo[4] = { {
-+enabled:0}, {
-+enabled:0}, {
-+enabled:0}, {
-+enabled:0}};
-+
-+static void kgdb_correct_hw_break(void)
-+{
-+      int breakno;
-+      int correctit;
-+      int breakbit;
-+      unsigned long dr7;
-+
-+      get_debugreg(dr7, 7);
-+      correctit = 0;
-+      for (breakno = 0; breakno < 3; breakno++) {
-+              breakbit = 2 << (breakno << 1);
-+              if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
-+                      correctit = 1;
-+                      dr7 |= breakbit;
-+                      dr7 &= ~(0xf0000 << (breakno << 2));
-+                      dr7 |= (((breakinfo[breakno].len << 2) |
-+                               breakinfo[breakno].type) << 16) <<
-+                          (breakno << 2);
-+                      switch (breakno) {
-+                      case 0:
-+                              set_debugreg(breakinfo[breakno].addr, 0);
-+                              break;
-+
-+                      case 1:
-+                              set_debugreg(breakinfo[breakno].addr, 1);
-+                              break;
-+
-+                      case 2:
-+                              set_debugreg(breakinfo[breakno].addr, 2);
-+                              break;
-+
-+                      case 3:
-+                              set_debugreg(breakinfo[breakno].addr, 3);
-+                              break;
-+                      }
-+              } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
-+                      correctit = 1;
-+                      dr7 &= ~breakbit;
-+                      dr7 &= ~(0xf0000 << (breakno << 2));
-+              }
-+      }
-+      if (correctit)
-+              set_debugreg(dr7, 7);
-+}
-+
-+static int kgdb_remove_hw_break(unsigned long addr, int len,
-+                                               enum kgdb_bptype bptype)
-+{
-+      int i, idx = -1;
-+      for (i = 0; i < 4; i++) {
-+              if (breakinfo[i].addr == addr && breakinfo[i].enabled) {
-+                      idx = i;
-+                      break;
-+              }
-+      }
-+      if (idx == -1)
-+              return -1;
-+
-+      breakinfo[idx].enabled = 0;
-+      return 0;
-+}
-+
-+static void kgdb_remove_all_hw_break(void)
-+{
-+      int i;
-+
-+      for (i = 0; i < 4; i++) {
-+              memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint));
-+      }
-+}
-+
-+static int kgdb_set_hw_break(unsigned long addr, int len,
-+                                        enum kgdb_bptype bptype)
-+{
-+      int i, idx = -1;
-+      for (i = 0; i < 4; i++) {
-+              if (!breakinfo[i].enabled) {
-+                      idx = i;
-+                      break;
-+              }
-+      }
-+      if (idx == -1)
-+              return -1;
-+      if (bptype == bp_hardware_breakpoint) {
-+              breakinfo[idx].type = 0;
-+              breakinfo[idx].len = 0;
-+      } else if (bptype == bp_write_watchpoint) {
-+              breakinfo[idx].type = 1;
-+              if (len == 1 || len == 2 || len == 4)
-+                      breakinfo[idx].len = len - 1;
-+              else
-+                      return -1;
-+      } else if (bptype == bp_access_watchpoint) {
-+              breakinfo[idx].type = 3;
-+              if (len == 1 || len == 2 || len == 4)
-+                      breakinfo[idx].len = len - 1;
-+              else
-+                      return -1;
-+      } else
-+              return -1;
-+      breakinfo[idx].enabled = 1;
-+      breakinfo[idx].addr = addr;
-+      return 0;
-+}
-+
-+void kgdb_disable_hw_debug(struct pt_regs *regs)
-+{
-+      /* Disable hardware debugging while we are in kgdb */
-+      set_debugreg(0UL, 7);
-+}
-+
-+void kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code)
-+{
-+      /* Master processor is completely in the debugger */
-+      gdb_x86_64vector = e_vector;
-+      gdb_x86_64errcode = err_code;
-+}
-+
-+void kgdb_roundup_cpus(unsigned long flags)
-+{
-+      send_IPI_allbutself(APIC_DM_NMI);
-+}
-+
-+int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
-+                             char *remcomInBuffer, char *remcomOutBuffer,
-+                             struct pt_regs *linux_regs)
-+{
-+      unsigned long addr;
-+      unsigned long breakno;
-+      char *ptr;
-+      int newPC;
-+      unsigned long dr6;
-+
-+      switch (remcomInBuffer[0]) {
-+      case 'c':
-+      case 's':
-+              /* try to read optional parameter, pc unchanged if no parm */
-+              ptr = &remcomInBuffer[1];
-+              if (kgdb_hex2long(&ptr, &addr))
-+                      linux_regs->rip = addr;
-+              newPC = linux_regs->rip;
-+
-+              /* clear the trace bit */
-+              linux_regs->eflags &= ~TF_MASK;
-+
-+              atomic_set(&cpu_doing_single_step, -1);
-+              /* set the trace bit if we're stepping */
-+              if (remcomInBuffer[0] == 's') {
-+                      linux_regs->eflags |= TF_MASK;
-+                      debugger_step = 1;
-+                      if (kgdb_contthread)
-+                              atomic_set(&cpu_doing_single_step,
-+                                         raw_smp_processor_id());
-+
-+              }
-+
-+              get_debugreg(dr6, 6);
-+              if (!(dr6 & 0x4000)) {
-+                      for (breakno = 0; breakno < 4; ++breakno) {
-+                              if (dr6 & (1 << breakno)) {
-+                                      if (breakinfo[breakno].type == 0) {
-+                                              /* Set restore flag */
-+                                              linux_regs->eflags |=
-+                                                  X86_EFLAGS_RF;
-+                                              break;
-+                                      }
-+                              }
-+                      }
-+              }
-+              set_debugreg(0UL, 6);
-+              kgdb_correct_hw_break();
-+
-+              return (0);
-+      }                       /* switch */
-+      return -1;
-+}
-+
-+static struct pt_regs *in_interrupt_stack(unsigned long rsp, int cpu)
-+{
-+      struct pt_regs *regs;
-+      unsigned long end = (unsigned long)cpu_pda(cpu)->irqstackptr;
-+      if (rsp <= end && rsp >= end - IRQSTACKSIZE + 8) {
-+              regs = *(((struct pt_regs **)end) - 1);
-+              return regs;
-+      }
-+      return NULL;
-+}
-+
-+static struct pt_regs *in_exception_stack(unsigned long rsp, int cpu)
-+{
-+      int i;
-+      struct tss_struct *init_tss = &__get_cpu_var(init_tss);
-+      for (i = 0; i < N_EXCEPTION_STACKS; i++)
-+              if (rsp >= init_tss[cpu].ist[i] &&
-+                  rsp <= init_tss[cpu].ist[i] + EXCEPTION_STKSZ) {
-+                      struct pt_regs *r =
-+                          (void *)init_tss[cpu].ist[i] + EXCEPTION_STKSZ;
-+                      return r - 1;
-+              }
-+      return NULL;
-+}
-+
-+void kgdb_shadowinfo(struct pt_regs *regs, char *buffer, unsigned threadid)
-+{
-+      static char intr_desc[] = "Stack at interrupt entrypoint";
-+      static char exc_desc[] = "Stack at exception entrypoint";
-+      struct pt_regs *stregs;
-+      int cpu = raw_smp_processor_id();
-+
-+      if ((stregs = in_interrupt_stack(regs->rsp, cpu)))
-+              kgdb_mem2hex(intr_desc, buffer, strlen(intr_desc));
-+      else if ((stregs = in_exception_stack(regs->rsp, cpu)))
-+              kgdb_mem2hex(exc_desc, buffer, strlen(exc_desc));
-+}
-+
-+struct task_struct *kgdb_get_shadow_thread(struct pt_regs *regs, int threadid)
-+{
-+      struct pt_regs *stregs;
-+      int cpu = raw_smp_processor_id();
-+
-+      if ((stregs = in_interrupt_stack(regs->rsp, cpu)))
-+              return current;
-+      else if ((stregs = in_exception_stack(regs->rsp, cpu)))
-+              return current;
-+
-+      return NULL;
-+}
-+
-+struct pt_regs *kgdb_shadow_regs(struct pt_regs *regs, int threadid)
-+{
-+      struct pt_regs *stregs;
-+      int cpu = raw_smp_processor_id();
-+
-+      if ((stregs = in_interrupt_stack(regs->rsp, cpu)))
-+              return stregs;
-+      else if ((stregs = in_exception_stack(regs->rsp, cpu)))
-+              return stregs;
-+
-+      return NULL;
-+}
-+
-+/* Register KGDB with the die_chain so that we hook into all of the right
-+ * spots. */
-+static int kgdb_notify(struct notifier_block *self, unsigned long cmd,
-+                     void *ptr)
-+{
-+      struct die_args *args = ptr;
-+      struct pt_regs *regs = args->regs;
-+
-+      if (cmd == DIE_PAGE_FAULT_NO_CONTEXT && atomic_read(&debugger_active)
-+                      && kgdb_may_fault) {
-+              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
-+              return NOTIFY_STOP;
-+      /* CPU roundup? */
-+      } else if (atomic_read(&debugger_active) && cmd == DIE_NMI_IPI) {
-+              kgdb_nmihook(raw_smp_processor_id(), regs);
-+              return NOTIFY_STOP;
-+              /* See if KGDB is interested. */
-+      } else if (cmd == DIE_DEBUG
-+                         && atomic_read(&cpu_doing_single_step) == raw_smp_processor_id()
-+                         && user_mode(regs)) {
-+              /* single step exception from kernel space to user space so
-+               * eat the exception and continue the process
-+               */
-+              printk(KERN_ERR "KGDB: trap/step from kernel to user space, resuming...\n");
-+              kgdb_arch_handle_exception(args->trapnr, args->signr, args->err, "c","",regs);
-+              return NOTIFY_STOP;
-+      } else if (cmd == DIE_PAGE_FAULT || user_mode(regs) ||
-+                 cmd == DIE_NMI_IPI || (cmd == DIE_DEBUG &&
-+                                        atomic_read(&debugger_active)))
-+              /* Userpace events, normal watchdog event, or spurious
-+               * debug exception.  Ignore. */
-+              return NOTIFY_DONE;
-+
-+      kgdb_handle_exception(args->trapnr, args->signr, args->err, regs);
-+
-+      return NOTIFY_STOP;
-+}
-+
-+static struct notifier_block kgdb_notifier = {
-+      .notifier_call = kgdb_notify,
-+      .priority = 0x7fffffff, /* we need to notified first */
-+};
-+
-+int kgdb_arch_init(void)
-+{
-+      register_die_notifier(&kgdb_notifier);
-+      return 0;
-+}
-+/*
-+ * Skip an int3 exception when it occurs after a breakpoint has been
-+ * removed. Backtrack eip by 1 since the int3 would have caused it to
-+ * increment by 1.
-+ */
-+
-+int kgdb_skipexception(int exception, struct pt_regs *regs)
-+{
-+      if (exception == 3 && kgdb_isremovedbreak(regs->rip - 1)) {
-+              regs->rip -= 1;
-+              return 1;
-+      }
-+      return 0;
-+}
-+
-+unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
-+{
-+      if (exception == 3) {
-+              return instruction_pointer(regs) - 1;
-+      }
-+      return instruction_pointer(regs);
-+}
-+
-+struct kgdb_arch arch_kgdb_ops = {
-+      .gdb_bpt_instr = {0xcc},
-+      .flags = KGDB_HW_BREAKPOINT,
-+      .shadowth = 1,
-+      .set_hw_breakpoint = kgdb_set_hw_break,
-+      .remove_hw_breakpoint = kgdb_remove_hw_break,
-+      .remove_all_hw_break = kgdb_remove_all_hw_break,
-+      .correct_hw_break = kgdb_correct_hw_break,
-+};
-diff -Nurb linux-2.6.22-570/arch/x86_64/kernel/mce.c linux-2.6.22-590/arch/x86_64/kernel/mce.c
---- linux-2.6.22-570/arch/x86_64/kernel/mce.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/x86_64/kernel/mce.c  2008-01-02 13:56:37.000000000 -0500
-@@ -174,7 +174,7 @@
-       if (events != atomic_read(&mce_logged) && trigger[0]) {
-               /* Small race window, but should be harmless.  */
-               atomic_set(&mce_logged, events);
--              call_usermodehelper(trigger, trigger_argv, NULL, -1);
-+              call_usermodehelper(trigger, trigger_argv, NULL, UMH_NO_WAIT);
-       }
- }
-diff -Nurb linux-2.6.22-570/arch/x86_64/kernel/signal.c linux-2.6.22-590/arch/x86_64/kernel/signal.c
---- linux-2.6.22-570/arch/x86_64/kernel/signal.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/x86_64/kernel/signal.c       2008-01-02 13:56:37.000000000 -0500
-@@ -480,7 +480,7 @@
- void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
- { 
-       struct task_struct *me = current; 
--      if (exception_trace)
-+      if (show_unhandled_signals && printk_ratelimit())
-               printk("%s[%d] bad frame in %s frame:%p rip:%lx rsp:%lx orax:%lx\n",
-              me->comm,me->pid,where,frame,regs->rip,regs->rsp,regs->orig_rax); 
-diff -Nurb linux-2.6.22-570/arch/x86_64/kernel/traps.c linux-2.6.22-590/arch/x86_64/kernel/traps.c
---- linux-2.6.22-570/arch/x86_64/kernel/traps.c        2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/x86_64/kernel/traps.c        2008-01-02 13:56:37.000000000 -0500
-@@ -96,6 +96,11 @@
- }
- int kstack_depth_to_print = 12;
-+#ifdef CONFIG_STACK_UNWIND
-+static int call_trace = 1;
-+#else
-+#define call_trace (-1)
-+#endif
- #ifdef CONFIG_KALLSYMS
- void printk_address(unsigned long address)
-@@ -198,6 +203,33 @@
-       return NULL;
- }
-+struct ops_and_data {
-+      struct stacktrace_ops *ops;
-+      void *data;
-+};
-+
-+static int dump_trace_unwind(struct unwind_frame_info *info, void *context)
-+{
-+      struct ops_and_data *oad = (struct ops_and_data *)context;
-+      int n = 0;
-+      unsigned long sp = UNW_SP(info);
-+
-+      if (arch_unw_user_mode(info))
-+              return -1;
-+      while (unwind(info) == 0 && UNW_PC(info)) {
-+              n++;
-+              oad->ops->address(oad->data, UNW_PC(info));
-+              if (arch_unw_user_mode(info))
-+                      break;
-+              if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
-+                  && sp > UNW_SP(info))
-+                      break;
-+              sp = UNW_SP(info);
-+              touch_nmi_watchdog();
-+      }
-+      return n;
-+}
-+
- #define MSG(txt) ops->warning(data, txt)
- /*
-@@ -225,6 +257,40 @@
-       if (!tsk)
-               tsk = current;
-+      if (call_trace >= 0) {
-+              int unw_ret = 0;
-+              struct unwind_frame_info info;
-+              struct ops_and_data oad = { .ops = ops, .data = data };
-+
-+              if (regs) {
-+                      if (unwind_init_frame_info(&info, tsk, regs) == 0)
-+                              unw_ret = dump_trace_unwind(&info, &oad);
-+              } else if (tsk == current)
-+                      unw_ret = unwind_init_running(&info, dump_trace_unwind,
-+                                                    &oad);
-+              else {
-+                      if (unwind_init_blocked(&info, tsk) == 0)
-+                              unw_ret = dump_trace_unwind(&info, &oad);
-+              }
-+              if (unw_ret > 0) {
-+                      if (call_trace == 1 && !arch_unw_user_mode(&info)) {
-+                              ops->warning_symbol(data,
-+                                           "DWARF2 unwinder stuck at %s",
-+                                           UNW_PC(&info));
-+                              if ((long)UNW_SP(&info) < 0) {
-+                                      MSG("Leftover inexact backtrace:");
-+                                      stack = (unsigned long *)UNW_SP(&info);
-+                                      if (!stack)
-+                                              goto out;
-+                              } else
-+                                      MSG("Full inexact backtrace again:");
-+                      } else if (call_trace >= 1)
-+                              goto out;
-+                      else
-+                              MSG("Full inexact backtrace again:");
-+              } else
-+                      MSG("Inexact backtrace:");
-+      }
-       if (!stack) {
-               unsigned long dummy;
-               stack = &dummy;
-@@ -308,6 +374,7 @@
-       tinfo = task_thread_info(tsk);
-       HANDLE_STACK (valid_stack_ptr(tinfo, stack));
- #undef HANDLE_STACK
-+out:
-       put_cpu();
- }
- EXPORT_SYMBOL(dump_trace);
-@@ -585,7 +652,8 @@
-               tsk->thread.error_code = error_code;
-               tsk->thread.trap_no = trapnr;
--              if (exception_trace && unhandled_signal(tsk, signr))
-+              if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
-+                  printk_ratelimit())
-                       printk(KERN_INFO
-                              "%s[%d:#%u] trap %s rip:%lx rsp:%lx error:%lx\n",
-                              tsk->comm, tsk->pid, tsk->xid, str,
-@@ -689,7 +757,8 @@
-               tsk->thread.error_code = error_code;
-               tsk->thread.trap_no = 13;
--              if (exception_trace && unhandled_signal(tsk, SIGSEGV))
-+              if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
-+                  printk_ratelimit())
-                       printk(KERN_INFO
-                      "%s[%d:#%u] general protection rip:%lx rsp:%lx error:%lx\n",
-                              tsk->comm, tsk->pid, tsk->xid,
-@@ -1128,3 +1197,21 @@
-       return 0;
- }
- early_param("kstack", kstack_setup);
-+
-+#ifdef CONFIG_STACK_UNWIND
-+static int __init call_trace_setup(char *s)
-+{
-+      if (!s)
-+              return -EINVAL;
-+      if (strcmp(s, "old") == 0)
-+              call_trace = -1;
-+      else if (strcmp(s, "both") == 0)
-+              call_trace = 0;
-+      else if (strcmp(s, "newfallback") == 0)
-+              call_trace = 1;
-+      else if (strcmp(s, "new") == 0)
-+              call_trace = 2;
-+      return 0;
-+}
-+early_param("call_trace", call_trace_setup);
-+#endif
-diff -Nurb linux-2.6.22-570/arch/x86_64/kernel/unwind.S linux-2.6.22-590/arch/x86_64/kernel/unwind.S
---- linux-2.6.22-570/arch/x86_64/kernel/unwind.S       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/arch/x86_64/kernel/unwind.S       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,38 @@
-+/* Assembler support for dwarf2 unwinder */
-+#include <linux/linkage.h>
-+#include <asm/dwarf2.h>
-+#include <asm/segment.h>
-+#include <asm/ptrace.h>
-+#include <asm/asm-offsets.h>
-+
-+ENTRY(arch_unwind_init_running)
-+      CFI_STARTPROC
-+      movq    %r15, R15(%rdi)
-+      movq    %r14, R14(%rdi)
-+      xchgq   %rsi, %rdx
-+      movq    %r13, R13(%rdi)
-+      movq    %r12, R12(%rdi)
-+      xorl    %eax, %eax
-+      movq    %rbp, RBP(%rdi)
-+      movq    %rbx, RBX(%rdi)
-+      movq    (%rsp), %rcx
-+      movq    %rax, R11(%rdi)
-+      movq    %rax, R10(%rdi)
-+      movq    %rax, R9(%rdi)
-+      movq    %rax, R8(%rdi)
-+      movq    %rax, RAX(%rdi)
-+      movq    %rax, RCX(%rdi)
-+      movq    %rax, RDX(%rdi)
-+      movq    %rax, RSI(%rdi)
-+      movq    %rax, RDI(%rdi)
-+      movq    %rax, ORIG_RAX(%rdi)
-+      movq    %rcx, RIP(%rdi)
-+      leaq    8(%rsp), %rcx
-+      movq    $__KERNEL_CS, CS(%rdi)
-+      movq    %rax, EFLAGS(%rdi)
-+      movq    %rcx, RSP(%rdi)
-+      movq    $__KERNEL_DS, SS(%rdi)
-+      jmpq    *%rdx
-+      CFI_ENDPROC
-+ENDPROC(arch_unwind_init_running)
-+
-diff -Nurb linux-2.6.22-570/arch/x86_64/kernel/vmlinux.lds.S linux-2.6.22-590/arch/x86_64/kernel/vmlinux.lds.S
---- linux-2.6.22-570/arch/x86_64/kernel/vmlinux.lds.S  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/arch/x86_64/kernel/vmlinux.lds.S  2008-01-02 13:56:37.000000000 -0500
-@@ -219,7 +219,9 @@
-   /* Sections to be discarded */
-   /DISCARD/ : {
-       *(.exitcall.exit)
-+#ifndef CONFIG_UNWIND_INFO
-       *(.eh_frame)
-+#endif
-       }
-   STABS_DEBUG
-diff -Nurb linux-2.6.22-570/arch/x86_64/mm/fault.c linux-2.6.22-590/arch/x86_64/mm/fault.c
---- linux-2.6.22-570/arch/x86_64/mm/fault.c    2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/arch/x86_64/mm/fault.c    2008-01-02 13:56:37.000000000 -0500
-@@ -221,16 +221,6 @@
-       return 0;
- } 
--int unhandled_signal(struct task_struct *tsk, int sig)
--{
--      if (is_init(tsk))
--              return 1;
--      if (tsk->ptrace & PT_PTRACED)
--              return 0;
--      return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) ||
--              (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL);
--}
--
- static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
-                                unsigned long error_code)
- {
-@@ -302,7 +292,7 @@
- }
- int page_fault_trace = 0;
--int exception_trace = 1;
-+int show_unhandled_signals = 1;
- /*
-  * This routine handles page faults.  It determines the address,
-@@ -534,6 +524,10 @@
-       if (is_errata93(regs, address))
-               return; 
-+      if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs,
-+                              error_code, 14, SIGSEGV) == NOTIFY_STOP)
-+              return;
-+
- /*
-  * Oops. The kernel tried to access some bad page. We'll have to
-  * terminate things with extreme prejudice.
-diff -Nurb linux-2.6.22-570/arch/x86_64/mm/init.c linux-2.6.22-590/arch/x86_64/mm/init.c
---- linux-2.6.22-570/arch/x86_64/mm/init.c     2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/arch/x86_64/mm/init.c     2008-01-02 13:56:37.000000000 -0500
-@@ -697,41 +697,6 @@
-       return pfn_valid(pte_pfn(*pte));
- }
--#ifdef CONFIG_SYSCTL
--#include <linux/sysctl.h>
--
--extern int exception_trace, page_fault_trace;
--
--static ctl_table debug_table2[] = {
--      {
--              .ctl_name       = 99,
--              .procname       = "exception-trace",
--              .data           = &exception_trace,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = proc_dointvec
--      },
--      {}
--}; 
--
--static ctl_table debug_root_table2[] = { 
--      {
--              .ctl_name = CTL_DEBUG,
--              .procname = "debug",
--              .mode = 0555,
--              .child = debug_table2
--      },
--      {}
--}; 
--
--static __init int x8664_sysctl_init(void)
--{ 
--      register_sysctl_table(debug_root_table2);
--      return 0;
--}
--__initcall(x8664_sysctl_init);
--#endif
--
- /* A pseudo VMA to allow ptrace access for the vsyscall page.  This only
-    covers the 64bit vsyscall page now. 32bit has a real VMA now and does
-    not need special handling anymore. */
-diff -Nurb linux-2.6.22-570/creatinst.sh linux-2.6.22-590/creatinst.sh
---- linux-2.6.22-570/creatinst.sh      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/creatinst.sh      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,12 @@
-+rm -fR inst
-+mkdir inst
-+make install INSTALL_PATH=inst
-+make modules_install INSTALL_MOD_PATH=inst
-+tar cfz inst.tar.gz inst
-+scp -i ~/newvici inst.tar.gz root@vici-03:/tmp
-+ssh -i ~/newvici root@vici-03 "cd /tmp;tar xvfz inst.tar.gz"
-+ssh -i ~/newvici root@vici-03 "wget www/~sapanb/vgup;sh vgup"
-+ssh -i ~/newvici root@vici-03 "cp -R /tmp/inst/lib/* /mnt/lib/"
-+ssh -i ~/newvici root@vici-03 "rm -fR /tmp/inst/lib; mv /tmp/inst/* /mnt/boot"
-+sleep 5
-+ssh -i ~/newvici root@vici-03 reboot
-diff -Nurb linux-2.6.22-570/crypto/Kconfig linux-2.6.22-590/crypto/Kconfig
---- linux-2.6.22-570/crypto/Kconfig    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/crypto/Kconfig    2008-01-02 13:56:37.000000000 -0500
-@@ -1,7 +1,17 @@
- #
--# Cryptographic API Configuration
-+# Generic algorithms support
-+#
-+config XOR_BLOCKS
-+      tristate
-+
- #
-+# async_tx api: hardware offloaded memory transfer/transform support
-+#
-+source "crypto/async_tx/Kconfig"
-+#
-+# Cryptographic API Configuration
-+#
- menu "Cryptographic options"
- config CRYPTO
-diff -Nurb linux-2.6.22-570/crypto/Makefile linux-2.6.22-590/crypto/Makefile
---- linux-2.6.22-570/crypto/Makefile   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/crypto/Makefile   2008-01-02 13:56:37.000000000 -0500
-@@ -50,3 +50,9 @@
- obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
- obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
-+
-+#
-+# generic algorithms and the async_tx api
-+#
-+obj-$(CONFIG_XOR_BLOCKS) += xor.o
-+obj-$(CONFIG_ASYNC_CORE) += async_tx/
-diff -Nurb linux-2.6.22-570/crypto/async_tx/Kconfig linux-2.6.22-590/crypto/async_tx/Kconfig
---- linux-2.6.22-570/crypto/async_tx/Kconfig   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/crypto/async_tx/Kconfig   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,16 @@
-+config ASYNC_CORE
-+      tristate
-+
-+config ASYNC_MEMCPY
-+      tristate
-+      select ASYNC_CORE
-+
-+config ASYNC_XOR
-+      tristate
-+      select ASYNC_CORE
-+      select XOR_BLOCKS
-+
-+config ASYNC_MEMSET
-+      tristate
-+      select ASYNC_CORE
-+
-diff -Nurb linux-2.6.22-570/crypto/async_tx/Makefile linux-2.6.22-590/crypto/async_tx/Makefile
---- linux-2.6.22-570/crypto/async_tx/Makefile  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/crypto/async_tx/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,4 @@
-+obj-$(CONFIG_ASYNC_CORE) += async_tx.o
-+obj-$(CONFIG_ASYNC_MEMCPY) += async_memcpy.o
-+obj-$(CONFIG_ASYNC_MEMSET) += async_memset.o
-+obj-$(CONFIG_ASYNC_XOR) += async_xor.o
-diff -Nurb linux-2.6.22-570/crypto/async_tx/async_memcpy.c linux-2.6.22-590/crypto/async_tx/async_memcpy.c
---- linux-2.6.22-570/crypto/async_tx/async_memcpy.c    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/crypto/async_tx/async_memcpy.c    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,131 @@
-+/*
-+ * copy offload engine support
-+ *
-+ * Copyright Â© 2006, Intel Corporation.
-+ *
-+ *      Dan Williams <dan.j.williams@intel.com>
-+ *
-+ *      with architecture considerations by:
-+ *      Neil Brown <neilb@suse.de>
-+ *      Jeff Garzik <jeff@garzik.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/highmem.h>
-+#include <linux/mm.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/async_tx.h>
-+
-+/**
-+ * async_memcpy - attempt to copy memory with a dma engine.
-+ * @dest: destination page
-+ * @src: src page
-+ * @offset: offset in pages to start transaction
-+ * @len: length in bytes
-+ * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK,
-+ *    ASYNC_TX_KMAP_SRC, ASYNC_TX_KMAP_DST
-+ * @depend_tx: memcpy depends on the result of this transaction
-+ * @cb_fn: function to call when the memcpy completes
-+ * @cb_param: parameter to pass to the callback routine
-+ */
-+struct dma_async_tx_descriptor *
-+async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
-+      unsigned int src_offset, size_t len, enum async_tx_flags flags,
-+      struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_param)
-+{
-+      struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMCPY);
-+      struct dma_device *device = chan ? chan->device : NULL;
-+      int int_en = cb_fn ? 1 : 0;
-+      struct dma_async_tx_descriptor *tx = device ?
-+              device->device_prep_dma_memcpy(chan, len,
-+              int_en) : NULL;
-+
-+      if (tx) { /* run the memcpy asynchronously */
-+              dma_addr_t addr;
-+              enum dma_data_direction dir;
-+
-+              pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
-+
-+              dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
-+                      DMA_NONE : DMA_FROM_DEVICE;
-+
-+              addr = dma_map_page(device->dev, dest, dest_offset, len, dir);
-+              tx->tx_set_dest(addr, tx, 0);
-+
-+              dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
-+                      DMA_NONE : DMA_TO_DEVICE;
-+
-+              addr = dma_map_page(device->dev, src, src_offset, len, dir);
-+              tx->tx_set_src(addr, tx, 0);
-+
-+              async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
-+      } else { /* run the memcpy synchronously */
-+              void *dest_buf, *src_buf;
-+              pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
-+
-+              /* wait for any prerequisite operations */
-+              if (depend_tx) {
-+                      /* if ack is already set then we cannot be sure
-+                       * we are referring to the correct operation
-+                       */
-+                      BUG_ON(depend_tx->ack);
-+                      if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
-+                              panic("%s: DMA_ERROR waiting for depend_tx\n",
-+                                      __FUNCTION__);
-+              }
-+
-+              if (flags & ASYNC_TX_KMAP_DST)
-+                      dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
-+              else
-+                      dest_buf = page_address(dest) + dest_offset;
-+
-+              if (flags & ASYNC_TX_KMAP_SRC)
-+                      src_buf = kmap_atomic(src, KM_USER0) + src_offset;
-+              else
-+                      src_buf = page_address(src) + src_offset;
-+
-+              memcpy(dest_buf, src_buf, len);
-+
-+              if (flags & ASYNC_TX_KMAP_DST)
-+                      kunmap_atomic(dest_buf, KM_USER0);
-+
-+              if (flags & ASYNC_TX_KMAP_SRC)
-+                      kunmap_atomic(src_buf, KM_USER0);
-+
-+              async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
-+      }
-+
-+      return tx;
-+}
-+EXPORT_SYMBOL_GPL(async_memcpy);
-+
-+static int __init async_memcpy_init(void)
-+{
-+      return 0;
-+}
-+
-+static void __exit async_memcpy_exit(void)
-+{
-+      do { } while (0);
-+}
-+
-+module_init(async_memcpy_init);
-+module_exit(async_memcpy_exit);
-+
-+MODULE_AUTHOR("Intel Corporation");
-+MODULE_DESCRIPTION("asynchronous memcpy api");
-+MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/crypto/async_tx/async_memset.c linux-2.6.22-590/crypto/async_tx/async_memset.c
---- linux-2.6.22-570/crypto/async_tx/async_memset.c    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/crypto/async_tx/async_memset.c    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,109 @@
-+/*
-+ * memory fill offload engine support
-+ *
-+ * Copyright Â© 2006, Intel Corporation.
-+ *
-+ *      Dan Williams <dan.j.williams@intel.com>
-+ *
-+ *      with architecture considerations by:
-+ *      Neil Brown <neilb@suse.de>
-+ *      Jeff Garzik <jeff@garzik.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/interrupt.h>
-+#include <linux/mm.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/async_tx.h>
-+
-+/**
-+ * async_memset - attempt to fill memory with a dma engine.
-+ * @dest: destination page
-+ * @val: fill value
-+ * @offset: offset in pages to start transaction
-+ * @len: length in bytes
-+ * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
-+ * @depend_tx: memset depends on the result of this transaction
-+ * @cb_fn: function to call when the memcpy completes
-+ * @cb_param: parameter to pass to the callback routine
-+ */
-+struct dma_async_tx_descriptor *
-+async_memset(struct page *dest, int val, unsigned int offset,
-+      size_t len, enum async_tx_flags flags,
-+      struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_param)
-+{
-+      struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMSET);
-+      struct dma_device *device = chan ? chan->device : NULL;
-+      int int_en = cb_fn ? 1 : 0;
-+      struct dma_async_tx_descriptor *tx = device ?
-+              device->device_prep_dma_memset(chan, val, len,
-+                      int_en) : NULL;
-+
-+      if (tx) { /* run the memset asynchronously */
-+              dma_addr_t dma_addr;
-+              enum dma_data_direction dir;
-+
-+              pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
-+              dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
-+                      DMA_NONE : DMA_FROM_DEVICE;
-+
-+              dma_addr = dma_map_page(device->dev, dest, offset, len, dir);
-+              tx->tx_set_dest(dma_addr, tx, 0);
-+
-+              async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
-+      } else { /* run the memset synchronously */
-+              void *dest_buf;
-+              pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
-+
-+              dest_buf = (void *) (((char *) page_address(dest)) + offset);
-+
-+              /* wait for any prerequisite operations */
-+              if (depend_tx) {
-+                      /* if ack is already set then we cannot be sure
-+                       * we are referring to the correct operation
-+                       */
-+                      BUG_ON(depend_tx->ack);
-+                      if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
-+                              panic("%s: DMA_ERROR waiting for depend_tx\n",
-+                                      __FUNCTION__);
-+              }
-+
-+              memset(dest_buf, val, len);
-+
-+              async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
-+      }
-+
-+      return tx;
-+}
-+EXPORT_SYMBOL_GPL(async_memset);
-+
-+static int __init async_memset_init(void)
-+{
-+      return 0;
-+}
-+
-+static void __exit async_memset_exit(void)
-+{
-+      do { } while (0);
-+}
-+
-+module_init(async_memset_init);
-+module_exit(async_memset_exit);
-+
-+MODULE_AUTHOR("Intel Corporation");
-+MODULE_DESCRIPTION("asynchronous memset api");
-+MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/crypto/async_tx/async_tx.c linux-2.6.22-590/crypto/async_tx/async_tx.c
---- linux-2.6.22-570/crypto/async_tx/async_tx.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/crypto/async_tx/async_tx.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,497 @@
-+/*
-+ * core routines for the asynchronous memory transfer/transform api
-+ *
-+ * Copyright Â© 2006, Intel Corporation.
-+ *
-+ *    Dan Williams <dan.j.williams@intel.com>
-+ *
-+ *    with architecture considerations by:
-+ *    Neil Brown <neilb@suse.de>
-+ *    Jeff Garzik <jeff@garzik.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/async_tx.h>
-+
-+#ifdef CONFIG_DMA_ENGINE
-+static enum dma_state_client
-+dma_channel_add_remove(struct dma_client *client,
-+      struct dma_chan *chan, enum dma_state state);
-+
-+static struct dma_client async_tx_dma = {
-+      .event_callback = dma_channel_add_remove,
-+      /* .cap_mask == 0 defaults to all channels */
-+};
-+
-+/**
-+ * dma_cap_mask_all - enable iteration over all operation types
-+ */
-+static dma_cap_mask_t dma_cap_mask_all;
-+
-+/**
-+ * chan_ref_percpu - tracks channel allocations per core/opertion
-+ */
-+struct chan_ref_percpu {
-+      struct dma_chan_ref *ref;
-+};
-+
-+static int channel_table_initialized;
-+static struct chan_ref_percpu *channel_table[DMA_TX_TYPE_END];
-+
-+/**
-+ * async_tx_lock - protect modification of async_tx_master_list and serialize
-+ *    rebalance operations
-+ */
-+static spinlock_t async_tx_lock;
-+
-+static struct list_head
-+async_tx_master_list = LIST_HEAD_INIT(async_tx_master_list);
-+
-+/* async_tx_issue_pending_all - start all transactions on all channels */
-+void async_tx_issue_pending_all(void)
-+{
-+      struct dma_chan_ref *ref;
-+
-+      rcu_read_lock();
-+      list_for_each_entry_rcu(ref, &async_tx_master_list, node)
-+              ref->chan->device->device_issue_pending(ref->chan);
-+      rcu_read_unlock();
-+}
-+EXPORT_SYMBOL_GPL(async_tx_issue_pending_all);
-+
-+/* dma_wait_for_async_tx - spin wait for a transcation to complete
-+ * @tx: transaction to wait on
-+ */
-+enum dma_status
-+dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
-+{
-+      enum dma_status status;
-+      struct dma_async_tx_descriptor *iter;
-+
-+      if (!tx)
-+              return DMA_SUCCESS;
-+
-+      /* poll through the dependency chain, return when tx is complete */
-+      do {
-+              iter = tx;
-+              while (iter->cookie == -EBUSY)
-+                      iter = iter->parent;
-+
-+              status = dma_sync_wait(iter->chan, iter->cookie);
-+      } while (status == DMA_IN_PROGRESS || (iter != tx));
-+
-+      return status;
-+}
-+EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);
-+
-+/* async_tx_run_dependencies - helper routine for dma drivers to process
-+ *    (start) dependent operations on their target channel
-+ * @tx: transaction with dependencies
-+ */
-+void
-+async_tx_run_dependencies(struct dma_async_tx_descriptor *tx)
-+{
-+      struct dma_async_tx_descriptor *dep_tx, *_dep_tx;
-+      struct dma_device *dev;
-+      struct dma_chan *chan;
-+
-+      list_for_each_entry_safe(dep_tx, _dep_tx, &tx->depend_list,
-+              depend_node) {
-+              chan = dep_tx->chan;
-+              dev = chan->device;
-+              /* we can't depend on ourselves */
-+              BUG_ON(chan == tx->chan);
-+              list_del(&dep_tx->depend_node);
-+              tx->tx_submit(dep_tx);
-+
-+              /* we need to poke the engine as client code does not
-+               * know about dependency submission events
-+               */
-+              dev->device_issue_pending(chan);
-+      }
-+}
-+EXPORT_SYMBOL_GPL(async_tx_run_dependencies);
-+
-+static void
-+free_dma_chan_ref(struct rcu_head *rcu)
-+{
-+      struct dma_chan_ref *ref;
-+      ref = container_of(rcu, struct dma_chan_ref, rcu);
-+      kfree(ref);
-+}
-+
-+static void
-+init_dma_chan_ref(struct dma_chan_ref *ref, struct dma_chan *chan)
-+{
-+      INIT_LIST_HEAD(&ref->node);
-+      INIT_RCU_HEAD(&ref->rcu);
-+      ref->chan = chan;
-+      atomic_set(&ref->count, 0);
-+}
-+
-+/**
-+ * get_chan_ref_by_cap - returns the nth channel of the given capability
-+ *    defaults to returning the channel with the desired capability and the
-+ *    lowest reference count if the index can not be satisfied
-+ * @cap: capability to match
-+ * @index: nth channel desired, passing -1 has the effect of forcing the
-+ *  default return value
-+ */
-+static struct dma_chan_ref *
-+get_chan_ref_by_cap(enum dma_transaction_type cap, int index)
-+{
-+      struct dma_chan_ref *ret_ref = NULL, *min_ref = NULL, *ref;
-+
-+      rcu_read_lock();
-+      list_for_each_entry_rcu(ref, &async_tx_master_list, node)
-+              if (dma_has_cap(cap, ref->chan->device->cap_mask)) {
-+                      if (!min_ref)
-+                              min_ref = ref;
-+                      else if (atomic_read(&ref->count) <
-+                              atomic_read(&min_ref->count))
-+                              min_ref = ref;
-+
-+                      if (index-- == 0) {
-+                              ret_ref = ref;
-+                              break;
-+                      }
-+              }
-+      rcu_read_unlock();
-+
-+      if (!ret_ref)
-+              ret_ref = min_ref;
-+
-+      if (ret_ref)
-+              atomic_inc(&ret_ref->count);
-+
-+      return ret_ref;
-+}
-+
-+/**
-+ * async_tx_rebalance - redistribute the available channels, optimize
-+ * for cpu isolation in the SMP case, and opertaion isolation in the
-+ * uniprocessor case
-+ */
-+static void async_tx_rebalance(void)
-+{
-+      int cpu, cap, cpu_idx = 0;
-+      unsigned long flags;
-+
-+      if (!channel_table_initialized)
-+              return;
-+
-+      spin_lock_irqsave(&async_tx_lock, flags);
-+
-+      /* undo the last distribution */
-+      for_each_dma_cap_mask(cap, dma_cap_mask_all)
-+              for_each_possible_cpu(cpu) {
-+                      struct dma_chan_ref *ref =
-+                              per_cpu_ptr(channel_table[cap], cpu)->ref;
-+                      if (ref) {
-+                              atomic_set(&ref->count, 0);
-+                              per_cpu_ptr(channel_table[cap], cpu)->ref =
-+                                                                      NULL;
-+                      }
-+              }
-+
-+      for_each_dma_cap_mask(cap, dma_cap_mask_all)
-+              for_each_online_cpu(cpu) {
-+                      struct dma_chan_ref *new;
-+                      if (NR_CPUS > 1)
-+                              new = get_chan_ref_by_cap(cap, cpu_idx++);
-+                      else
-+                              new = get_chan_ref_by_cap(cap, -1);
-+
-+                      per_cpu_ptr(channel_table[cap], cpu)->ref = new;
-+              }
-+
-+      spin_unlock_irqrestore(&async_tx_lock, flags);
-+}
-+
-+static enum dma_state_client
-+dma_channel_add_remove(struct dma_client *client,
-+      struct dma_chan *chan, enum dma_state state)
-+{
-+      unsigned long found, flags;
-+      struct dma_chan_ref *master_ref, *ref;
-+      enum dma_state_client ack = DMA_DUP; /* default: take no action */
-+
-+      switch (state) {
-+      case DMA_RESOURCE_AVAILABLE:
-+              found = 0;
-+              rcu_read_lock();
-+              list_for_each_entry_rcu(ref, &async_tx_master_list, node)
-+                      if (ref->chan == chan) {
-+                              found = 1;
-+                              break;
-+                      }
-+              rcu_read_unlock();
-+
-+              pr_debug("async_tx: dma resource available [%s]\n",
-+                      found ? "old" : "new");
-+
-+              if (!found)
-+                      ack = DMA_ACK;
-+              else
-+                      break;
-+
-+              /* add the channel to the generic management list */
-+              master_ref = kmalloc(sizeof(*master_ref), GFP_KERNEL);
-+              if (master_ref) {
-+                      /* keep a reference until async_tx is unloaded */
-+                      dma_chan_get(chan);
-+                      init_dma_chan_ref(master_ref, chan);
-+                      spin_lock_irqsave(&async_tx_lock, flags);
-+                      list_add_tail_rcu(&master_ref->node,
-+                              &async_tx_master_list);
-+                      spin_unlock_irqrestore(&async_tx_lock,
-+                              flags);
-+              } else {
-+                      printk(KERN_WARNING "async_tx: unable to create"
-+                              " new master entry in response to"
-+                              " a DMA_RESOURCE_ADDED event"
-+                              " (-ENOMEM)\n");
-+                      return 0;
-+              }
-+
-+              async_tx_rebalance();
-+              break;
-+      case DMA_RESOURCE_REMOVED:
-+              found = 0;
-+              spin_lock_irqsave(&async_tx_lock, flags);
-+              list_for_each_entry_rcu(ref, &async_tx_master_list, node)
-+                      if (ref->chan == chan) {
-+                              /* permit backing devices to go away */
-+                              dma_chan_put(ref->chan);
-+                              list_del_rcu(&ref->node);
-+                              call_rcu(&ref->rcu, free_dma_chan_ref);
-+                              found = 1;
-+                              break;
-+                      }
-+              spin_unlock_irqrestore(&async_tx_lock, flags);
-+
-+              pr_debug("async_tx: dma resource removed [%s]\n",
-+                      found ? "ours" : "not ours");
-+
-+              if (found)
-+                      ack = DMA_ACK;
-+              else
-+                      break;
-+
-+              async_tx_rebalance();
-+              break;
-+      case DMA_RESOURCE_SUSPEND:
-+      case DMA_RESOURCE_RESUME:
-+              printk(KERN_WARNING "async_tx: does not support dma channel"
-+                      " suspend/resume\n");
-+              break;
-+      default:
-+              BUG();
-+      }
-+
-+      return ack;
-+}
-+
-+static int __init
-+async_tx_init(void)
-+{
-+      enum dma_transaction_type cap;
-+
-+      spin_lock_init(&async_tx_lock);
-+      bitmap_fill(dma_cap_mask_all.bits, DMA_TX_TYPE_END);
-+
-+      /* an interrupt will never be an explicit operation type.
-+       * clearing this bit prevents allocation to a slot in 'channel_table'
-+       */
-+      clear_bit(DMA_INTERRUPT, dma_cap_mask_all.bits);
-+
-+      for_each_dma_cap_mask(cap, dma_cap_mask_all) {
-+              channel_table[cap] = alloc_percpu(struct chan_ref_percpu);
-+              if (!channel_table[cap])
-+                      goto err;
-+      }
-+
-+      channel_table_initialized = 1;
-+      dma_async_client_register(&async_tx_dma);
-+      dma_async_client_chan_request(&async_tx_dma);
-+
-+      printk(KERN_INFO "async_tx: api initialized (async)\n");
-+
-+      return 0;
-+err:
-+      printk(KERN_ERR "async_tx: initialization failure\n");
-+
-+      while (--cap >= 0)
-+              free_percpu(channel_table[cap]);
-+
-+      return 1;
-+}
-+
-+static void __exit async_tx_exit(void)
-+{
-+      enum dma_transaction_type cap;
-+
-+      channel_table_initialized = 0;
-+
-+      for_each_dma_cap_mask(cap, dma_cap_mask_all)
-+              if (channel_table[cap])
-+                      free_percpu(channel_table[cap]);
-+
-+      dma_async_client_unregister(&async_tx_dma);
-+}
-+
-+/**
-+ * async_tx_find_channel - find a channel to carry out the operation or let
-+ *    the transaction execute synchronously
-+ * @depend_tx: transaction dependency
-+ * @tx_type: transaction type
-+ */
-+struct dma_chan *
-+async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
-+      enum dma_transaction_type tx_type)
-+{
-+      /* see if we can keep the chain on one channel */
-+      if (depend_tx &&
-+              dma_has_cap(tx_type, depend_tx->chan->device->cap_mask))
-+              return depend_tx->chan;
-+      else if (likely(channel_table_initialized)) {
-+              struct dma_chan_ref *ref;
-+              int cpu = get_cpu();
-+              ref = per_cpu_ptr(channel_table[tx_type], cpu)->ref;
-+              put_cpu();
-+              return ref ? ref->chan : NULL;
-+      } else
-+              return NULL;
-+}
-+EXPORT_SYMBOL_GPL(async_tx_find_channel);
-+#else
-+static int __init async_tx_init(void)
-+{
-+      printk(KERN_INFO "async_tx: api initialized (sync-only)\n");
-+      return 0;
-+}
-+
-+static void __exit async_tx_exit(void)
-+{
-+      do { } while (0);
-+}
-+#endif
-+
-+void
-+async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
-+      enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_param)
-+{
-+      tx->callback = cb_fn;
-+      tx->callback_param = cb_param;
-+
-+      /* set this new tx to run after depend_tx if:
-+       * 1/ a dependency exists (depend_tx is !NULL)
-+       * 2/ the tx can not be submitted to the current channel
-+       */
-+      if (depend_tx && depend_tx->chan != chan) {
-+              /* if ack is already set then we cannot be sure
-+               * we are referring to the correct operation
-+               */
-+              BUG_ON(depend_tx->ack);
-+
-+              tx->parent = depend_tx;
-+              spin_lock_bh(&depend_tx->lock);
-+              list_add_tail(&tx->depend_node, &depend_tx->depend_list);
-+              if (depend_tx->cookie == 0) {
-+                      struct dma_chan *dep_chan = depend_tx->chan;
-+                      struct dma_device *dep_dev = dep_chan->device;
-+                      dep_dev->device_dependency_added(dep_chan);
-+              }
-+              spin_unlock_bh(&depend_tx->lock);
-+
-+              /* schedule an interrupt to trigger the channel switch */
-+              async_trigger_callback(ASYNC_TX_ACK, depend_tx, NULL, NULL);
-+      } else {
-+              tx->parent = NULL;
-+              tx->tx_submit(tx);
-+      }
-+
-+      if (flags & ASYNC_TX_ACK)
-+              async_tx_ack(tx);
-+
-+      if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
-+              async_tx_ack(depend_tx);
-+}
-+EXPORT_SYMBOL_GPL(async_tx_submit);
-+
-+/**
-+ * async_trigger_callback - schedules the callback function to be run after
-+ * any dependent operations have been completed.
-+ * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
-+ * @depend_tx: 'callback' requires the completion of this transaction
-+ * @cb_fn: function to call after depend_tx completes
-+ * @cb_param: parameter to pass to the callback routine
-+ */
-+struct dma_async_tx_descriptor *
-+async_trigger_callback(enum async_tx_flags flags,
-+      struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_param)
-+{
-+      struct dma_chan *chan;
-+      struct dma_device *device;
-+      struct dma_async_tx_descriptor *tx;
-+
-+      if (depend_tx) {
-+              chan = depend_tx->chan;
-+              device = chan->device;
-+
-+              /* see if we can schedule an interrupt
-+               * otherwise poll for completion
-+               */
-+              if (device && !dma_has_cap(DMA_INTERRUPT, device->cap_mask))
-+                      device = NULL;
-+
-+              tx = device ? device->device_prep_dma_interrupt(chan) : NULL;
-+      } else
-+              tx = NULL;
-+
-+      if (tx) {
-+              pr_debug("%s: (async)\n", __FUNCTION__);
-+
-+              async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
-+      } else {
-+              pr_debug("%s: (sync)\n", __FUNCTION__);
-+
-+              /* wait for any prerequisite operations */
-+              if (depend_tx) {
-+                      /* if ack is already set then we cannot be sure
-+                       * we are referring to the correct operation
-+                       */
-+                      BUG_ON(depend_tx->ack);
-+                      if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
-+                              panic("%s: DMA_ERROR waiting for depend_tx\n",
-+                                      __FUNCTION__);
-+              }
-+
-+              async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
-+      }
-+
-+      return tx;
-+}
-+EXPORT_SYMBOL_GPL(async_trigger_callback);
-+
-+module_init(async_tx_init);
-+module_exit(async_tx_exit);
-+
-+MODULE_AUTHOR("Intel Corporation");
-+MODULE_DESCRIPTION("Asynchronous Bulk Memory Transactions API");
-+MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/crypto/async_tx/async_xor.c linux-2.6.22-590/crypto/async_tx/async_xor.c
---- linux-2.6.22-570/crypto/async_tx/async_xor.c       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/crypto/async_tx/async_xor.c       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,327 @@
-+/*
-+ * xor offload engine api
-+ *
-+ * Copyright Â© 2006, Intel Corporation.
-+ *
-+ *      Dan Williams <dan.j.williams@intel.com>
-+ *
-+ *      with architecture considerations by:
-+ *      Neil Brown <neilb@suse.de>
-+ *      Jeff Garzik <jeff@garzik.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/interrupt.h>
-+#include <linux/mm.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/raid/xor.h>
-+#include <linux/async_tx.h>
-+
-+static void
-+do_async_xor(struct dma_async_tx_descriptor *tx, struct dma_device *device,
-+      struct dma_chan *chan, struct page *dest, struct page **src_list,
-+      unsigned int offset, unsigned int src_cnt, size_t len,
-+      enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_param)
-+{
-+      dma_addr_t dma_addr;
-+      enum dma_data_direction dir;
-+      int i;
-+
-+      pr_debug("%s: len: %zu\n", __FUNCTION__, len);
-+
-+      dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
-+              DMA_NONE : DMA_FROM_DEVICE;
-+
-+      dma_addr = dma_map_page(device->dev, dest, offset, len, dir);
-+      tx->tx_set_dest(dma_addr, tx, 0);
-+
-+      dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
-+              DMA_NONE : DMA_TO_DEVICE;
-+
-+      for (i = 0; i < src_cnt; i++) {
-+              dma_addr = dma_map_page(device->dev, src_list[i],
-+                      offset, len, dir);
-+              tx->tx_set_src(dma_addr, tx, i);
-+      }
-+
-+      async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
-+}
-+
-+static void
-+do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,
-+      unsigned int src_cnt, size_t len, enum async_tx_flags flags,
-+      struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_param)
-+{
-+      void *_dest;
-+      int i;
-+
-+      pr_debug("%s: len: %zu\n", __FUNCTION__, len);
-+
-+      /* reuse the 'src_list' array to convert to buffer pointers */
-+      for (i = 0; i < src_cnt; i++)
-+              src_list[i] = (struct page *)
-+                      (page_address(src_list[i]) + offset);
-+
-+      /* set destination address */
-+      _dest = page_address(dest) + offset;
-+
-+      if (flags & ASYNC_TX_XOR_ZERO_DST)
-+              memset(_dest, 0, len);
-+
-+      xor_blocks(src_cnt, len, _dest,
-+              (void **) src_list);
-+
-+      async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
-+}
-+
-+/**
-+ * async_xor - attempt to xor a set of blocks with a dma engine.
-+ *    xor_blocks always uses the dest as a source so the ASYNC_TX_XOR_ZERO_DST
-+ *    flag must be set to not include dest data in the calculation.  The
-+ *    assumption with dma eninges is that they only use the destination
-+ *    buffer as a source when it is explicity specified in the source list.
-+ * @dest: destination page
-+ * @src_list: array of source pages (if the dest is also a source it must be
-+ *    at index zero).  The contents of this array may be overwritten.
-+ * @offset: offset in pages to start transaction
-+ * @src_cnt: number of source pages
-+ * @len: length in bytes
-+ * @flags: ASYNC_TX_XOR_ZERO_DST, ASYNC_TX_XOR_DROP_DEST,
-+ *    ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
-+ * @depend_tx: xor depends on the result of this transaction.
-+ * @cb_fn: function to call when the xor completes
-+ * @cb_param: parameter to pass to the callback routine
-+ */
-+struct dma_async_tx_descriptor *
-+async_xor(struct page *dest, struct page **src_list, unsigned int offset,
-+      int src_cnt, size_t len, enum async_tx_flags flags,
-+      struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_param)
-+{
-+      struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR);
-+      struct dma_device *device = chan ? chan->device : NULL;
-+      struct dma_async_tx_descriptor *tx = NULL;
-+      dma_async_tx_callback _cb_fn;
-+      void *_cb_param;
-+      unsigned long local_flags;
-+      int xor_src_cnt;
-+      int i = 0, src_off = 0, int_en;
-+
-+      BUG_ON(src_cnt <= 1);
-+
-+      while (src_cnt) {
-+              local_flags = flags;
-+              if (device) { /* run the xor asynchronously */
-+                      xor_src_cnt = min(src_cnt, device->max_xor);
-+                      /* if we are submitting additional xors
-+                       * only set the callback on the last transaction
-+                       */
-+                      if (src_cnt > xor_src_cnt) {
-+                              local_flags &= ~ASYNC_TX_ACK;
-+                              _cb_fn = NULL;
-+                              _cb_param = NULL;
-+                      } else {
-+                              _cb_fn = cb_fn;
-+                              _cb_param = cb_param;
-+                      }
-+
-+                      int_en = _cb_fn ? 1 : 0;
-+
-+                      tx = device->device_prep_dma_xor(
-+                              chan, xor_src_cnt, len, int_en);
-+
-+                      if (tx) {
-+                              do_async_xor(tx, device, chan, dest,
-+                              &src_list[src_off], offset, xor_src_cnt, len,
-+                              local_flags, depend_tx, _cb_fn,
-+                              _cb_param);
-+                      } else /* fall through */
-+                              goto xor_sync;
-+              } else { /* run the xor synchronously */
-+xor_sync:
-+                      /* in the sync case the dest is an implied source
-+                       * (assumes the dest is at the src_off index)
-+                       */
-+                      if (flags & ASYNC_TX_XOR_DROP_DST) {
-+                              src_cnt--;
-+                              src_off++;
-+                      }
-+
-+                      /* process up to 'MAX_XOR_BLOCKS' sources */
-+                      xor_src_cnt = min(src_cnt, MAX_XOR_BLOCKS);
-+
-+                      /* if we are submitting additional xors
-+                       * only set the callback on the last transaction
-+                       */
-+                      if (src_cnt > xor_src_cnt) {
-+                              local_flags &= ~ASYNC_TX_ACK;
-+                              _cb_fn = NULL;
-+                              _cb_param = NULL;
-+                      } else {
-+                              _cb_fn = cb_fn;
-+                              _cb_param = cb_param;
-+                      }
-+
-+                      /* wait for any prerequisite operations */
-+                      if (depend_tx) {
-+                              /* if ack is already set then we cannot be sure
-+                               * we are referring to the correct operation
-+                               */
-+                              BUG_ON(depend_tx->ack);
-+                              if (dma_wait_for_async_tx(depend_tx) ==
-+                                      DMA_ERROR)
-+                                      panic("%s: DMA_ERROR waiting for "
-+                                              "depend_tx\n",
-+                                              __FUNCTION__);
-+                      }
-+
-+                      do_sync_xor(dest, &src_list[src_off], offset,
-+                              xor_src_cnt, len, local_flags, depend_tx,
-+                              _cb_fn, _cb_param);
-+              }
-+
-+              /* the previous tx is hidden from the client,
-+               * so ack it
-+               */
-+              if (i && depend_tx)
-+                      async_tx_ack(depend_tx);
-+
-+              depend_tx = tx;
-+
-+              if (src_cnt > xor_src_cnt) {
-+                      /* drop completed sources */
-+                      src_cnt -= xor_src_cnt;
-+                      src_off += xor_src_cnt;
-+
-+                      /* unconditionally preserve the destination */
-+                      flags &= ~ASYNC_TX_XOR_ZERO_DST;
-+
-+                      /* use the intermediate result a source, but remember
-+                       * it's dropped, because it's implied, in the sync case
-+                       */
-+                      src_list[--src_off] = dest;
-+                      src_cnt++;
-+                      flags |= ASYNC_TX_XOR_DROP_DST;
-+              } else
-+                      src_cnt = 0;
-+              i++;
-+      }
-+
-+      return tx;
-+}
-+EXPORT_SYMBOL_GPL(async_xor);
-+
-+static int page_is_zero(struct page *p, unsigned int offset, size_t len)
-+{
-+      char *a = page_address(p) + offset;
-+      return ((*(u32 *) a) == 0 &&
-+              memcmp(a, a + 4, len - 4) == 0);
-+}
-+
-+/**
-+ * async_xor_zero_sum - attempt a xor parity check with a dma engine.
-+ * @dest: destination page used if the xor is performed synchronously
-+ * @src_list: array of source pages.  The dest page must be listed as a source
-+ *    at index zero.  The contents of this array may be overwritten.
-+ * @offset: offset in pages to start transaction
-+ * @src_cnt: number of source pages
-+ * @len: length in bytes
-+ * @result: 0 if sum == 0 else non-zero
-+ * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
-+ * @depend_tx: xor depends on the result of this transaction.
-+ * @cb_fn: function to call when the xor completes
-+ * @cb_param: parameter to pass to the callback routine
-+ */
-+struct dma_async_tx_descriptor *
-+async_xor_zero_sum(struct page *dest, struct page **src_list,
-+      unsigned int offset, int src_cnt, size_t len,
-+      u32 *result, enum async_tx_flags flags,
-+      struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_param)
-+{
-+      struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_ZERO_SUM);
-+      struct dma_device *device = chan ? chan->device : NULL;
-+      int int_en = cb_fn ? 1 : 0;
-+      struct dma_async_tx_descriptor *tx = device ?
-+              device->device_prep_dma_zero_sum(chan, src_cnt, len, result,
-+                      int_en) : NULL;
-+      int i;
-+
-+      BUG_ON(src_cnt <= 1);
-+
-+      if (tx) {
-+              dma_addr_t dma_addr;
-+              enum dma_data_direction dir;
-+
-+              pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
-+
-+              dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
-+                      DMA_NONE : DMA_TO_DEVICE;
-+
-+              for (i = 0; i < src_cnt; i++) {
-+                      dma_addr = dma_map_page(device->dev, src_list[i],
-+                              offset, len, dir);
-+                      tx->tx_set_src(dma_addr, tx, i);
-+              }
-+
-+              async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
-+      } else {
-+              unsigned long xor_flags = flags;
-+
-+              pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
-+
-+              xor_flags |= ASYNC_TX_XOR_DROP_DST;
-+              xor_flags &= ~ASYNC_TX_ACK;
-+
-+              tx = async_xor(dest, src_list, offset, src_cnt, len, xor_flags,
-+                      depend_tx, NULL, NULL);
-+
-+              if (tx) {
-+                      if (dma_wait_for_async_tx(tx) == DMA_ERROR)
-+                              panic("%s: DMA_ERROR waiting for tx\n",
-+                                      __FUNCTION__);
-+                      async_tx_ack(tx);
-+              }
-+
-+              *result = page_is_zero(dest, offset, len) ? 0 : 1;
-+
-+              tx = NULL;
-+
-+              async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
-+      }
-+
-+      return tx;
-+}
-+EXPORT_SYMBOL_GPL(async_xor_zero_sum);
-+
-+static int __init async_xor_init(void)
-+{
-+      return 0;
-+}
-+
-+static void __exit async_xor_exit(void)
-+{
-+      do { } while (0);
-+}
-+
-+module_init(async_xor_init);
-+module_exit(async_xor_exit);
-+
-+MODULE_AUTHOR("Intel Corporation");
-+MODULE_DESCRIPTION("asynchronous xor/xor-zero-sum api");
-+MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/crypto/xor.c linux-2.6.22-590/crypto/xor.c
---- linux-2.6.22-570/crypto/xor.c      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/crypto/xor.c      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,155 @@
-+/*
-+ * xor.c : Multiple Devices driver for Linux
-+ *
-+ * Copyright (C) 1996, 1997, 1998, 1999, 2000,
-+ * Ingo Molnar, Matti Aarnio, Jakub Jelinek, Richard Henderson.
-+ *
-+ * Dispatch optimized RAID-5 checksumming functions.
-+ *
-+ * 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, or (at your option)
-+ * any later version.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * (for example /usr/src/linux/COPYING); if not, write to the Free
-+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#define BH_TRACE 0
-+#include <linux/module.h>
-+#include <linux/raid/md.h>
-+#include <linux/raid/xor.h>
-+#include <asm/xor.h>
-+
-+/* The xor routines to use.  */
-+static struct xor_block_template *active_template;
-+
-+void
-+xor_blocks(unsigned int src_count, unsigned int bytes, void *dest, void **srcs)
-+{
-+      unsigned long *p1, *p2, *p3, *p4;
-+
-+      p1 = (unsigned long *) srcs[0];
-+      if (src_count == 1) {
-+              active_template->do_2(bytes, dest, p1);
-+              return;
-+      }
-+
-+      p2 = (unsigned long *) srcs[1];
-+      if (src_count == 2) {
-+              active_template->do_3(bytes, dest, p1, p2);
-+              return;
-+      }
-+
-+      p3 = (unsigned long *) srcs[2];
-+      if (src_count == 3) {
-+              active_template->do_4(bytes, dest, p1, p2, p3);
-+              return;
-+      }
-+
-+      p4 = (unsigned long *) srcs[3];
-+      active_template->do_5(bytes, dest, p1, p2, p3, p4);
-+}
-+EXPORT_SYMBOL(xor_blocks);
-+
-+/* Set of all registered templates.  */
-+static struct xor_block_template *template_list;
-+
-+#define BENCH_SIZE (PAGE_SIZE)
-+
-+static void
-+do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
-+{
-+      int speed;
-+      unsigned long now;
-+      int i, count, max;
-+
-+      tmpl->next = template_list;
-+      template_list = tmpl;
-+
-+      /*
-+       * Count the number of XORs done during a whole jiffy, and use
-+       * this to calculate the speed of checksumming.  We use a 2-page
-+       * allocation to have guaranteed color L1-cache layout.
-+       */
-+      max = 0;
-+      for (i = 0; i < 5; i++) {
-+              now = jiffies;
-+              count = 0;
-+              while (jiffies == now) {
-+                      mb(); /* prevent loop optimzation */
-+                      tmpl->do_2(BENCH_SIZE, b1, b2);
-+                      mb();
-+                      count++;
-+                      mb();
-+              }
-+              if (count > max)
-+                      max = count;
-+      }
-+
-+      speed = max * (HZ * BENCH_SIZE / 1024);
-+      tmpl->speed = speed;
-+
-+      printk(KERN_INFO "   %-10s: %5d.%03d MB/sec\n", tmpl->name,
-+             speed / 1000, speed % 1000);
-+}
-+
-+static int __init
-+calibrate_xor_blocks(void)
-+{
-+      void *b1, *b2;
-+      struct xor_block_template *f, *fastest;
-+
-+      b1 = (void *) __get_free_pages(GFP_KERNEL, 2);
-+      if (!b1) {
-+              printk(KERN_WARNING "xor: Yikes!  No memory available.\n");
-+              return -ENOMEM;
-+      }
-+      b2 = b1 + 2*PAGE_SIZE + BENCH_SIZE;
-+
-+      /*
-+       * If this arch/cpu has a short-circuited selection, don't loop through
-+       * all the possible functions, just test the best one
-+       */
-+
-+      fastest = NULL;
-+
-+#ifdef XOR_SELECT_TEMPLATE
-+              fastest = XOR_SELECT_TEMPLATE(fastest);
-+#endif
-+
-+#define xor_speed(templ)      do_xor_speed((templ), b1, b2)
-+
-+      if (fastest) {
-+              printk(KERN_INFO "xor: automatically using best "
-+                      "checksumming function: %s\n",
-+                      fastest->name);
-+              xor_speed(fastest);
-+      } else {
-+              printk(KERN_INFO "xor: measuring software checksum speed\n");
-+              XOR_TRY_TEMPLATES;
-+              fastest = template_list;
-+              for (f = fastest; f; f = f->next)
-+                      if (f->speed > fastest->speed)
-+                              fastest = f;
-+      }
-+
-+      printk(KERN_INFO "xor: using function: %s (%d.%03d MB/sec)\n",
-+             fastest->name, fastest->speed / 1000, fastest->speed % 1000);
-+
-+#undef xor_speed
-+
-+      free_pages((unsigned long)b1, 2);
-+
-+      active_template = fastest;
-+      return 0;
-+}
-+
-+static __exit void xor_exit(void) { }
-+
-+MODULE_LICENSE("GPL");
-+
-+/* when built-in xor.o must initialize before drivers/md/md.o */
-+core_initcall(calibrate_xor_blocks);
-+module_exit(xor_exit);
-diff -Nurb linux-2.6.22-570/drivers/Makefile linux-2.6.22-590/drivers/Makefile
---- linux-2.6.22-570/drivers/Makefile  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -70,6 +70,7 @@
- obj-$(CONFIG_MCA)             += mca/
- obj-$(CONFIG_EISA)            += eisa/
- obj-$(CONFIG_CPU_FREQ)                += cpufreq/
-+obj-$(CONFIG_CPU_IDLE)                += cpuidle/
- obj-$(CONFIG_MMC)             += mmc/
- obj-$(CONFIG_NEW_LEDS)                += leds/
- obj-$(CONFIG_INFINIBAND)      += infiniband/
-diff -Nurb linux-2.6.22-570/drivers/acpi/Kconfig linux-2.6.22-590/drivers/acpi/Kconfig
---- linux-2.6.22-570/drivers/acpi/Kconfig      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/acpi/Kconfig      2008-01-02 13:56:37.000000000 -0500
-@@ -124,7 +124,7 @@
- config ACPI_VIDEO
-       tristate "Video"
--      depends on X86 && BACKLIGHT_CLASS_DEVICE
-+      depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL
-       help
-         This driver implement the ACPI Extensions For Display Adapters
-         for integrated graphics devices on motherboard, as specified in
-@@ -280,6 +280,14 @@
-         of verbosity. Saying Y enables these statements. This will increase
-         your kernel size by around 50K.
-+config ACPI_DEBUG_FUNC_TRACE
-+      bool "Additionally enable ACPI function tracing"
-+      default n
-+      depends on ACPI_DEBUG
-+      help
-+        ACPI Debug Statements slow down ACPI processing. Function trace
-+        is about half of the penalty and is rarely useful.
-+
- config ACPI_EC
-       bool
-       default y
-diff -Nurb linux-2.6.22-570/drivers/acpi/battery.c linux-2.6.22-590/drivers/acpi/battery.c
---- linux-2.6.22-570/drivers/acpi/battery.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/acpi/battery.c    2008-01-02 13:56:37.000000000 -0500
-@@ -43,21 +43,30 @@
- #define ACPI_BATTERY_CLASS            "battery"
- #define ACPI_BATTERY_HID              "PNP0C0A"
- #define ACPI_BATTERY_DEVICE_NAME      "Battery"
--#define ACPI_BATTERY_FILE_INFO                "info"
--#define ACPI_BATTERY_FILE_STATUS      "state"
--#define ACPI_BATTERY_FILE_ALARM               "alarm"
- #define ACPI_BATTERY_NOTIFY_STATUS    0x80
- #define ACPI_BATTERY_NOTIFY_INFO      0x81
- #define ACPI_BATTERY_UNITS_WATTS      "mW"
- #define ACPI_BATTERY_UNITS_AMPS               "mA"
- #define _COMPONENT            ACPI_BATTERY_COMPONENT
-+
-+#define ACPI_BATTERY_UPDATE_TIME      0
-+
-+#define ACPI_BATTERY_NONE_UPDATE      0
-+#define ACPI_BATTERY_EASY_UPDATE      1
-+#define ACPI_BATTERY_INIT_UPDATE      2
-+
- ACPI_MODULE_NAME("battery");
- MODULE_AUTHOR("Paul Diefenbaugh");
- MODULE_DESCRIPTION("ACPI Battery Driver");
- MODULE_LICENSE("GPL");
-+static unsigned int update_time = ACPI_BATTERY_UPDATE_TIME;
-+
-+/* 0 - every time, > 0 - by update_time */
-+module_param(update_time, uint, 0644);
-+
- extern struct proc_dir_entry *acpi_lock_battery_dir(void);
- extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
-@@ -76,7 +85,7 @@
-               },
- };
--struct acpi_battery_status {
-+struct acpi_battery_state {
-       acpi_integer state;
-       acpi_integer present_rate;
-       acpi_integer remaining_capacity;
-@@ -99,33 +108,111 @@
-       acpi_string oem_info;
- };
--struct acpi_battery_flags {
--      u8 present:1;           /* Bay occupied? */
--      u8 power_unit:1;        /* 0=watts, 1=apms */
--      u8 alarm:1;             /* _BTP present? */
--      u8 reserved:5;
-+enum acpi_battery_files{
-+      ACPI_BATTERY_INFO = 0,
-+      ACPI_BATTERY_STATE,
-+      ACPI_BATTERY_ALARM,
-+      ACPI_BATTERY_NUMFILES,
- };
--struct acpi_battery_trips {
--      unsigned long warning;
--      unsigned long low;
-+struct acpi_battery_flags {
-+      u8 battery_present_prev;
-+      u8 alarm_present;
-+      u8 init_update;
-+      u8 update[ACPI_BATTERY_NUMFILES];
-+      u8 power_unit;
- };
- struct acpi_battery {
--      struct acpi_device * device;
-+      struct mutex mutex;
-+      struct acpi_device *device;
-       struct acpi_battery_flags flags;
--      struct acpi_battery_trips trips;
-+      struct acpi_buffer bif_data;
-+      struct acpi_buffer bst_data;
-       unsigned long alarm;
--      struct acpi_battery_info *info;
-+      unsigned long update_time[ACPI_BATTERY_NUMFILES];
- };
-+inline int acpi_battery_present(struct acpi_battery *battery)
-+{
-+      return battery->device->status.battery_present;
-+}
-+inline char *acpi_battery_power_units(struct acpi_battery *battery)
-+{
-+      if (battery->flags.power_unit)
-+              return ACPI_BATTERY_UNITS_AMPS;
-+      else
-+              return ACPI_BATTERY_UNITS_WATTS;
-+}
-+
-+inline acpi_handle acpi_battery_handle(struct acpi_battery *battery)
-+{
-+      return battery->device->handle;
-+}
-+
- /* --------------------------------------------------------------------------
-                                Battery Management
-    -------------------------------------------------------------------------- */
--static int
--acpi_battery_get_info(struct acpi_battery *battery,
--                    struct acpi_battery_info **bif)
-+static void acpi_battery_check_result(struct acpi_battery *battery, int result)
-+{
-+      if (!battery)
-+              return;
-+
-+      if (result) {
-+              battery->flags.init_update = 1;
-+      }
-+}
-+
-+static int acpi_battery_extract_package(struct acpi_battery *battery,
-+                                      union acpi_object *package,
-+                                      struct acpi_buffer *format,
-+                                      struct acpi_buffer *data,
-+                                      char *package_name)
-+{
-+      acpi_status status = AE_OK;
-+      struct acpi_buffer data_null = { 0, NULL };
-+
-+      status = acpi_extract_package(package, format, &data_null);
-+      if (status != AE_BUFFER_OVERFLOW) {
-+              ACPI_EXCEPTION((AE_INFO, status, "Extracting size %s",
-+                              package_name));
-+              return -ENODEV;
-+      }
-+
-+      if (data_null.length != data->length) {
-+              kfree(data->pointer);
-+              data->pointer = kzalloc(data_null.length, GFP_KERNEL);
-+              if (!data->pointer) {
-+                      ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()"));
-+                      return -ENOMEM;
-+              }
-+              data->length = data_null.length;
-+      }
-+
-+      status = acpi_extract_package(package, format, data);
-+      if (ACPI_FAILURE(status)) {
-+              ACPI_EXCEPTION((AE_INFO, status, "Extracting %s",
-+                              package_name));
-+              return -ENODEV;
-+      }
-+
-+      return 0;
-+}
-+
-+static int acpi_battery_get_status(struct acpi_battery *battery)
-+{
-+      int result = 0;
-+
-+      result = acpi_bus_get_status(battery->device);
-+      if (result) {
-+              ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
-+              return -ENODEV;
-+      }
-+      return result;
-+}
-+
-+static int acpi_battery_get_info(struct acpi_battery *battery)
- {
-       int result = 0;
-       acpi_status status = 0;
-@@ -133,16 +220,20 @@
-       struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF),
-               ACPI_BATTERY_FORMAT_BIF
-       };
--      struct acpi_buffer data = { 0, NULL };
-       union acpi_object *package = NULL;
-+      struct acpi_buffer *data = NULL;
-+      struct acpi_battery_info *bif = NULL;
-+      battery->update_time[ACPI_BATTERY_INFO] = get_seconds();
--      if (!battery || !bif)
--              return -EINVAL;
-+      if (!acpi_battery_present(battery))
-+              return 0;
--      /* Evalute _BIF */
-+      /* Evaluate _BIF */
--      status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer);
-+      status =
-+          acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL,
-+                               &buffer);
-       if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
-               return -ENODEV;
-@@ -150,41 +241,29 @@
-       package = buffer.pointer;
--      /* Extract Package Data */
--
--      status = acpi_extract_package(package, &format, &data);
--      if (status != AE_BUFFER_OVERFLOW) {
--              ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF"));
--              result = -ENODEV;
--              goto end;
--      }
-+      data = &battery->bif_data;
--      data.pointer = kzalloc(data.length, GFP_KERNEL);
--      if (!data.pointer) {
--              result = -ENOMEM;
--              goto end;
--      }
-+      /* Extract Package Data */
--      status = acpi_extract_package(package, &format, &data);
--      if (ACPI_FAILURE(status)) {
--              ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF"));
--              kfree(data.pointer);
--              result = -ENODEV;
-+      result =
-+          acpi_battery_extract_package(battery, package, &format, data,
-+                                       "_BIF");
-+      if (result)
-               goto end;
--      }
-       end:
-+
-       kfree(buffer.pointer);
--      if (!result)
--              (*bif) = data.pointer;
-+      if (!result) {
-+              bif = data->pointer;
-+              battery->flags.power_unit = bif->power_unit;
-+      }
-       return result;
- }
--static int
--acpi_battery_get_status(struct acpi_battery *battery,
--                      struct acpi_battery_status **bst)
-+static int acpi_battery_get_state(struct acpi_battery *battery)
- {
-       int result = 0;
-       acpi_status status = 0;
-@@ -192,16 +271,19 @@
-       struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST),
-               ACPI_BATTERY_FORMAT_BST
-       };
--      struct acpi_buffer data = { 0, NULL };
-       union acpi_object *package = NULL;
-+      struct acpi_buffer *data = NULL;
-+      battery->update_time[ACPI_BATTERY_STATE] = get_seconds();
--      if (!battery || !bst)
--              return -EINVAL;
-+      if (!acpi_battery_present(battery))
-+              return 0;
--      /* Evalute _BST */
-+      /* Evaluate _BST */
--      status = acpi_evaluate_object(battery->device->handle, "_BST", NULL, &buffer);
-+      status =
-+          acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL,
-+                               &buffer);
-       if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
-               return -ENODEV;
-@@ -209,55 +291,49 @@
-       package = buffer.pointer;
--      /* Extract Package Data */
-+      data = &battery->bst_data;
--      status = acpi_extract_package(package, &format, &data);
--      if (status != AE_BUFFER_OVERFLOW) {
--              ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST"));
--              result = -ENODEV;
--              goto end;
--      }
--
--      data.pointer = kzalloc(data.length, GFP_KERNEL);
--      if (!data.pointer) {
--              result = -ENOMEM;
--              goto end;
--      }
-+      /* Extract Package Data */
--      status = acpi_extract_package(package, &format, &data);
--      if (ACPI_FAILURE(status)) {
--              ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST"));
--              kfree(data.pointer);
--              result = -ENODEV;
-+      result =
-+          acpi_battery_extract_package(battery, package, &format, data,
-+                                       "_BST");
-+      if (result)
-               goto end;
--      }
-       end:
-       kfree(buffer.pointer);
--      if (!result)
--              (*bst) = data.pointer;
--
-       return result;
- }
--static int
--acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
-+static int acpi_battery_get_alarm(struct acpi_battery *battery)
-+{
-+      battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();
-+
-+      return 0;
-+}
-+
-+static int acpi_battery_set_alarm(struct acpi_battery *battery,
-+                                unsigned long alarm)
- {
-       acpi_status status = 0;
-       union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-       struct acpi_object_list arg_list = { 1, &arg0 };
-+      battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();
--      if (!battery)
--              return -EINVAL;
-+      if (!acpi_battery_present(battery))
-+              return -ENODEV;
--      if (!battery->flags.alarm)
-+      if (!battery->flags.alarm_present)
-               return -ENODEV;
-       arg0.integer.value = alarm;
--      status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL);
-+      status =
-+          acpi_evaluate_object(acpi_battery_handle(battery), "_BTP",
-+                               &arg_list, NULL);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
-@@ -268,65 +344,114 @@
-       return 0;
- }
--static int acpi_battery_check(struct acpi_battery *battery)
-+static int acpi_battery_init_alarm(struct acpi_battery *battery)
- {
-       int result = 0;
-       acpi_status status = AE_OK;
-       acpi_handle handle = NULL;
--      struct acpi_device *device = NULL;
--      struct acpi_battery_info *bif = NULL;
-+      struct acpi_battery_info *bif = battery->bif_data.pointer;
-+      unsigned long alarm = battery->alarm;
-+      /* See if alarms are supported, and if so, set default */
--      if (!battery)
--              return -EINVAL;
-+      status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle);
-+      if (ACPI_SUCCESS(status)) {
-+              battery->flags.alarm_present = 1;
-+              if (!alarm && bif) {
-+                      alarm = bif->design_capacity_warning;
-+              }
-+              result = acpi_battery_set_alarm(battery, alarm);
-+              if (result)
-+                      goto end;
-+      } else {
-+              battery->flags.alarm_present = 0;
-+      }
--      device = battery->device;
-+      end:
--      result = acpi_bus_get_status(device);
--      if (result)
-               return result;
-+}
--      /* Insertion? */
--
--      if (!battery->flags.present && device->status.battery_present) {
-+static int acpi_battery_init_update(struct acpi_battery *battery)
-+{
-+      int result = 0;
--              ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n"));
-+      result = acpi_battery_get_status(battery);
-+      if (result)
-+              return result;
--              /* Evalute _BIF to get certain static information */
-+      battery->flags.battery_present_prev = acpi_battery_present(battery);
--              result = acpi_battery_get_info(battery, &bif);
-+      if (acpi_battery_present(battery)) {
-+              result = acpi_battery_get_info(battery);
-+              if (result)
-+                      return result;
-+              result = acpi_battery_get_state(battery);
-               if (result)
-                       return result;
--              battery->flags.power_unit = bif->power_unit;
--              battery->trips.warning = bif->design_capacity_warning;
--              battery->trips.low = bif->design_capacity_low;
--              kfree(bif);
-+              acpi_battery_init_alarm(battery);
-+      }
--              /* See if alarms are supported, and if so, set default */
-+      return result;
-+}
--              status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
--              if (ACPI_SUCCESS(status)) {
--                      battery->flags.alarm = 1;
--                      acpi_battery_set_alarm(battery, battery->trips.warning);
-+static int acpi_battery_update(struct acpi_battery *battery,
-+                             int update, int *update_result_ptr)
-+{
-+      int result = 0;
-+      int update_result = ACPI_BATTERY_NONE_UPDATE;
-+
-+      if (!acpi_battery_present(battery)) {
-+              update = 1;
-+      }
-+
-+      if (battery->flags.init_update) {
-+              result = acpi_battery_init_update(battery);
-+              if (result)
-+                      goto end;
-+              update_result = ACPI_BATTERY_INIT_UPDATE;
-+      } else if (update) {
-+              result = acpi_battery_get_status(battery);
-+              if (result)
-+                      goto end;
-+              if ((!battery->flags.battery_present_prev & acpi_battery_present(battery))
-+                  || (battery->flags.battery_present_prev & !acpi_battery_present(battery))) {
-+                      result = acpi_battery_init_update(battery);
-+                      if (result)
-+                              goto end;
-+                      update_result = ACPI_BATTERY_INIT_UPDATE;
-+              } else {
-+                      update_result = ACPI_BATTERY_EASY_UPDATE;
-               }
-       }
--      /* Removal? */
-+      end:
--      else if (battery->flags.present && !device->status.battery_present) {
--              ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n"));
--      }
-+      battery->flags.init_update = (result != 0);
--      battery->flags.present = device->status.battery_present;
-+      *update_result_ptr = update_result;
-       return result;
- }
--static void acpi_battery_check_present(struct acpi_battery *battery)
-+static void acpi_battery_notify_update(struct acpi_battery *battery)
- {
--      if (!battery->flags.present) {
--              acpi_battery_check(battery);
-+      acpi_battery_get_status(battery);
-+
-+      if (battery->flags.init_update) {
-+              return;
-+      }
-+
-+      if ((!battery->flags.battery_present_prev &
-+           acpi_battery_present(battery)) ||
-+          (battery->flags.battery_present_prev &
-+           !acpi_battery_present(battery))) {
-+              battery->flags.init_update = 1;
-+      } else {
-+              battery->flags.update[ACPI_BATTERY_INFO] = 1;
-+              battery->flags.update[ACPI_BATTERY_STATE] = 1;
-+              battery->flags.update[ACPI_BATTERY_ALARM] = 1;
-       }
- }
-@@ -335,37 +460,33 @@
-    -------------------------------------------------------------------------- */
- static struct proc_dir_entry *acpi_battery_dir;
--static int acpi_battery_read_info(struct seq_file *seq, void *offset)
-+
-+static int acpi_battery_print_info(struct seq_file *seq, int result)
- {
--      int result = 0;
-       struct acpi_battery *battery = seq->private;
-       struct acpi_battery_info *bif = NULL;
-       char *units = "?";
--
--      if (!battery)
-+      if (result)
-               goto end;
--      acpi_battery_check_present(battery);
--
--      if (battery->flags.present)
-+      if (acpi_battery_present(battery))
-               seq_printf(seq, "present:                 yes\n");
-       else {
-               seq_printf(seq, "present:                 no\n");
-               goto end;
-       }
--      /* Battery Info (_BIF) */
--
--      result = acpi_battery_get_info(battery, &bif);
--      if (result || !bif) {
--              seq_printf(seq, "ERROR: Unable to read battery information\n");
-+      bif = battery->bif_data.pointer;
-+      if (!bif) {
-+              ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BIF buffer is NULL"));
-+              result = -ENODEV;
-               goto end;
-       }
--      units =
--          bif->
--          power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
-+      /* Battery Units */
-+
-+      units = acpi_battery_power_units(battery);
-       if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "design capacity:         unknown\n");
-@@ -396,7 +517,6 @@
-       else
-               seq_printf(seq, "design voltage:          %d mV\n",
-                          (u32) bif->design_voltage);
--
-       seq_printf(seq, "design capacity warning: %d %sh\n",
-                  (u32) bif->design_capacity_warning, units);
-       seq_printf(seq, "design capacity low:     %d %sh\n",
-@@ -411,50 +531,40 @@
-       seq_printf(seq, "OEM info:                %s\n", bif->oem_info);
-       end:
--      kfree(bif);
--      return 0;
--}
-+      if (result)
-+              seq_printf(seq, "ERROR: Unable to read battery info\n");
--static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
--{
--      return single_open(file, acpi_battery_read_info, PDE(inode)->data);
-+      return result;
- }
--static int acpi_battery_read_state(struct seq_file *seq, void *offset)
-+static int acpi_battery_print_state(struct seq_file *seq, int result)
- {
--      int result = 0;
-       struct acpi_battery *battery = seq->private;
--      struct acpi_battery_status *bst = NULL;
-+      struct acpi_battery_state *bst = NULL;
-       char *units = "?";
--
--      if (!battery)
-+      if (result)
-               goto end;
--      acpi_battery_check_present(battery);
--
--      if (battery->flags.present)
-+      if (acpi_battery_present(battery))
-               seq_printf(seq, "present:                 yes\n");
-       else {
-               seq_printf(seq, "present:                 no\n");
-               goto end;
-       }
--      /* Battery Units */
--
--      units =
--          battery->flags.
--          power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
--
--      /* Battery Status (_BST) */
--
--      result = acpi_battery_get_status(battery, &bst);
--      if (result || !bst) {
--              seq_printf(seq, "ERROR: Unable to read battery status\n");
-+      bst = battery->bst_data.pointer;
-+      if (!bst) {
-+              ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BST buffer is NULL"));
-+              result = -ENODEV;
-               goto end;
-       }
-+      /* Battery Units */
-+
-+      units = acpi_battery_power_units(battery);
-+
-       if (!(bst->state & 0x04))
-               seq_printf(seq, "capacity state:          ok\n");
-       else
-@@ -490,48 +600,43 @@
-                          (u32) bst->present_voltage);
-       end:
--      kfree(bst);
--      return 0;
--}
-+      if (result) {
-+              seq_printf(seq, "ERROR: Unable to read battery state\n");
-+      }
--static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
--{
--      return single_open(file, acpi_battery_read_state, PDE(inode)->data);
-+      return result;
- }
--static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
-+static int acpi_battery_print_alarm(struct seq_file *seq, int result)
- {
-       struct acpi_battery *battery = seq->private;
-       char *units = "?";
--
--      if (!battery)
-+      if (result)
-               goto end;
--      acpi_battery_check_present(battery);
--
--      if (!battery->flags.present) {
-+      if (!acpi_battery_present(battery)) {
-               seq_printf(seq, "present:                 no\n");
-               goto end;
-       }
-       /* Battery Units */
--      units =
--          battery->flags.
--          power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
--
--      /* Battery Alarm */
-+      units = acpi_battery_power_units(battery);
-       seq_printf(seq, "alarm:                   ");
-       if (!battery->alarm)
-               seq_printf(seq, "unsupported\n");
-       else
--              seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units);
-+              seq_printf(seq, "%lu %sh\n", battery->alarm, units);
-       end:
--      return 0;
-+
-+      if (result)
-+              seq_printf(seq, "ERROR: Unable to read battery alarm\n");
-+
-+      return result;
- }
- static ssize_t
-@@ -543,27 +648,113 @@
-       char alarm_string[12] = { '\0' };
-       struct seq_file *m = file->private_data;
-       struct acpi_battery *battery = m->private;
--
-+      int update_result = ACPI_BATTERY_NONE_UPDATE;
-       if (!battery || (count > sizeof(alarm_string) - 1))
-               return -EINVAL;
--      acpi_battery_check_present(battery);
-+      mutex_lock(&battery->mutex);
--      if (!battery->flags.present)
--              return -ENODEV;
-+      result = acpi_battery_update(battery, 1, &update_result);
-+      if (result) {
-+              result = -ENODEV;
-+              goto end;
-+      }
--      if (copy_from_user(alarm_string, buffer, count))
--              return -EFAULT;
-+      if (!acpi_battery_present(battery)) {
-+              result = -ENODEV;
-+              goto end;
-+      }
-+
-+      if (copy_from_user(alarm_string, buffer, count)) {
-+              result = -EFAULT;
-+              goto end;
-+      }
-       alarm_string[count] = '\0';
-       result = acpi_battery_set_alarm(battery,
-                                       simple_strtoul(alarm_string, NULL, 0));
-       if (result)
-+              goto end;
-+
-+      end:
-+
-+      acpi_battery_check_result(battery, result);
-+
-+      if (!result)
-+              result = count;
-+
-+      mutex_unlock(&battery->mutex);
-+
-               return result;
-+}
-+
-+typedef int(*print_func)(struct seq_file *seq, int result);
-+typedef int(*get_func)(struct acpi_battery *battery);
-+
-+static struct acpi_read_mux {
-+      print_func print;
-+      get_func get;
-+} acpi_read_funcs[ACPI_BATTERY_NUMFILES] = {
-+      {.get = acpi_battery_get_info, .print = acpi_battery_print_info},
-+      {.get = acpi_battery_get_state, .print = acpi_battery_print_state},
-+      {.get = acpi_battery_get_alarm, .print = acpi_battery_print_alarm},
-+};
-+
-+static int acpi_battery_read(int fid, struct seq_file *seq)
-+{
-+      struct acpi_battery *battery = seq->private;
-+      int result = 0;
-+      int update_result = ACPI_BATTERY_NONE_UPDATE;
-+      int update = 0;
-+
-+      mutex_lock(&battery->mutex);
-+
-+      update = (get_seconds() - battery->update_time[fid] >= update_time);
-+      update = (update | battery->flags.update[fid]);
-+
-+      result = acpi_battery_update(battery, update, &update_result);
-+      if (result)
-+              goto end;
-+
-+      if (update_result == ACPI_BATTERY_EASY_UPDATE) {
-+              result = acpi_read_funcs[fid].get(battery);
-+              if (result)
-+                      goto end;
-+      }
--      return count;
-+      end:
-+      result = acpi_read_funcs[fid].print(seq, result);
-+      acpi_battery_check_result(battery, result);
-+      battery->flags.update[fid] = result;
-+      mutex_unlock(&battery->mutex);
-+      return result;
-+}
-+
-+static int acpi_battery_read_info(struct seq_file *seq, void *offset)
-+{
-+      return acpi_battery_read(ACPI_BATTERY_INFO, seq);
-+}
-+
-+static int acpi_battery_read_state(struct seq_file *seq, void *offset)
-+{
-+      return acpi_battery_read(ACPI_BATTERY_STATE, seq);
-+}
-+
-+static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
-+{
-+      return acpi_battery_read(ACPI_BATTERY_ALARM, seq);
-+}
-+
-+static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
-+{
-+      return single_open(file, acpi_battery_read_info, PDE(inode)->data);
-+}
-+
-+static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
-+{
-+      return single_open(file, acpi_battery_read_state, PDE(inode)->data);
- }
- static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
-@@ -571,35 +762,51 @@
-       return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
- }
--static const struct file_operations acpi_battery_info_ops = {
-+static struct battery_file {
-+      struct file_operations ops;
-+      mode_t mode;
-+      char *name;
-+} acpi_battery_file[] = {
-+      {
-+      .name = "info",
-+      .mode = S_IRUGO,
-+      .ops = {
-       .open = acpi_battery_info_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
--};
--
--static const struct file_operations acpi_battery_state_ops = {
-+      },
-+      },
-+      {
-+      .name = "state",
-+      .mode = S_IRUGO,
-+      .ops = {
-       .open = acpi_battery_state_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
--};
--
--static const struct file_operations acpi_battery_alarm_ops = {
-+      },
-+      },
-+      {
-+      .name = "alarm",
-+      .mode = S_IFREG | S_IRUGO | S_IWUSR,
-+      .ops = {
-       .open = acpi_battery_alarm_open_fs,
-       .read = seq_read,
-       .write = acpi_battery_write_alarm,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-+      },
-+      },
- };
- static int acpi_battery_add_fs(struct acpi_device *device)
- {
-       struct proc_dir_entry *entry = NULL;
--
-+      int i;
-       if (!acpi_device_dir(device)) {
-               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-@@ -609,38 +816,16 @@
-               acpi_device_dir(device)->owner = THIS_MODULE;
-       }
--      /* 'info' [R] */
--      entry = create_proc_entry(ACPI_BATTERY_FILE_INFO,
--                                S_IRUGO, acpi_device_dir(device));
-+      for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
-+              entry = create_proc_entry(acpi_battery_file[i].name,
-+                                acpi_battery_file[i].mode, acpi_device_dir(device));
-       if (!entry)
-               return -ENODEV;
-       else {
--              entry->proc_fops = &acpi_battery_info_ops;
-+                      entry->proc_fops = &acpi_battery_file[i].ops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
--
--      /* 'status' [R] */
--      entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS,
--                                S_IRUGO, acpi_device_dir(device));
--      if (!entry)
--              return -ENODEV;
--      else {
--              entry->proc_fops = &acpi_battery_state_ops;
--              entry->data = acpi_driver_data(device);
--              entry->owner = THIS_MODULE;
--      }
--
--      /* 'alarm' [R/W] */
--      entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM,
--                                S_IFREG | S_IRUGO | S_IWUSR,
--                                acpi_device_dir(device));
--      if (!entry)
--              return -ENODEV;
--      else {
--              entry->proc_fops = &acpi_battery_alarm_ops;
--              entry->data = acpi_driver_data(device);
--              entry->owner = THIS_MODULE;
-       }
-       return 0;
-@@ -648,15 +833,12 @@
- static int acpi_battery_remove_fs(struct acpi_device *device)
- {
--
-+      int i;
-       if (acpi_device_dir(device)) {
--              remove_proc_entry(ACPI_BATTERY_FILE_ALARM,
-+              for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
-+                      remove_proc_entry(acpi_battery_file[i].name,
-                                 acpi_device_dir(device));
--              remove_proc_entry(ACPI_BATTERY_FILE_STATUS,
--                                acpi_device_dir(device));
--              remove_proc_entry(ACPI_BATTERY_FILE_INFO,
--                                acpi_device_dir(device));
--
-+              }
-               remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
-               acpi_device_dir(device) = NULL;
-       }
-@@ -673,7 +855,6 @@
-       struct acpi_battery *battery = data;
-       struct acpi_device *device = NULL;
--
-       if (!battery)
-               return;
-@@ -684,8 +865,10 @@
-       case ACPI_BATTERY_NOTIFY_INFO:
-       case ACPI_NOTIFY_BUS_CHECK:
-       case ACPI_NOTIFY_DEVICE_CHECK:
--              acpi_battery_check(battery);
--              acpi_bus_generate_event(device, event, battery->flags.present);
-+              device = battery->device;
-+              acpi_battery_notify_update(battery);
-+              acpi_bus_generate_event(device, event,
-+                                      acpi_battery_present(battery));
-               break;
-       default:
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-@@ -702,7 +885,6 @@
-       acpi_status status = 0;
-       struct acpi_battery *battery = NULL;
--
-       if (!device)
-               return -EINVAL;
-@@ -710,15 +892,21 @@
-       if (!battery)
-               return -ENOMEM;
-+      mutex_init(&battery->mutex);
-+
-+      mutex_lock(&battery->mutex);
-+
-       battery->device = device;
-       strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
-       strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
-       acpi_driver_data(device) = battery;
--      result = acpi_battery_check(battery);
-+      result = acpi_battery_get_status(battery);
-       if (result)
-               goto end;
-+      battery->flags.init_update = 1;
-+
-       result = acpi_battery_add_fs(device);
-       if (result)
-               goto end;
-@@ -727,6 +915,7 @@
-                                            ACPI_ALL_NOTIFY,
-                                            acpi_battery_notify, battery);
-       if (ACPI_FAILURE(status)) {
-+              ACPI_EXCEPTION((AE_INFO, status, "Installing notify handler"));
-               result = -ENODEV;
-               goto end;
-       }
-@@ -736,11 +925,14 @@
-              device->status.battery_present ? "present" : "absent");
-       end:
-+
-       if (result) {
-               acpi_battery_remove_fs(device);
-               kfree(battery);
-       }
-+      mutex_unlock(&battery->mutex);
-+
-       return result;
- }
-@@ -749,18 +941,27 @@
-       acpi_status status = 0;
-       struct acpi_battery *battery = NULL;
--
-       if (!device || !acpi_driver_data(device))
-               return -EINVAL;
-       battery = acpi_driver_data(device);
-+      mutex_lock(&battery->mutex);
-+
-       status = acpi_remove_notify_handler(device->handle,
-                                           ACPI_ALL_NOTIFY,
-                                           acpi_battery_notify);
-       acpi_battery_remove_fs(device);
-+      kfree(battery->bif_data.pointer);
-+
-+      kfree(battery->bst_data.pointer);
-+
-+      mutex_unlock(&battery->mutex);
-+
-+      mutex_destroy(&battery->mutex);
-+
-       kfree(battery);
-       return 0;
-@@ -775,7 +976,10 @@
-               return -EINVAL;
-       battery = device->driver_data;
--      return acpi_battery_check(battery);
-+
-+      battery->flags.init_update = 1;
-+
-+      return 0;
- }
- static int __init acpi_battery_init(void)
-@@ -800,7 +1004,6 @@
- static void __exit acpi_battery_exit(void)
- {
--
-       acpi_bus_unregister_driver(&acpi_battery_driver);
-       acpi_unlock_battery_dir(acpi_battery_dir);
-diff -Nurb linux-2.6.22-570/drivers/acpi/bay.c linux-2.6.22-590/drivers/acpi/bay.c
---- linux-2.6.22-570/drivers/acpi/bay.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/acpi/bay.c        2008-01-02 13:56:37.000000000 -0500
-@@ -288,6 +288,11 @@
-       new_bay->pdev = pdev;
-       platform_set_drvdata(pdev, new_bay);
-+      /*
-+       * we want the bay driver to be able to send uevents
-+       */
-+      pdev->dev.uevent_suppress = 0;
-+
-       if (acpi_bay_add_fs(new_bay)) {
-               platform_device_unregister(new_bay->pdev);
-               goto bay_add_err;
-@@ -328,18 +333,12 @@
- {
-       struct bay *bay_dev = (struct bay *)data;
-       struct device *dev = &bay_dev->pdev->dev;
-+      char event_string[12];
-+      char *envp[] = { event_string, NULL };
-       bay_dprintk(handle, "Bay event");
--
--      switch(event) {
--      case ACPI_NOTIFY_BUS_CHECK:
--      case ACPI_NOTIFY_DEVICE_CHECK:
--      case ACPI_NOTIFY_EJECT_REQUEST:
--              kobject_uevent(&dev->kobj, KOBJ_CHANGE);
--              break;
--      default:
--              printk(KERN_ERR PREFIX "Bay: unknown event %d\n", event);
--      }
-+      sprintf(event_string, "BAY_EVENT=%d\n", event);
-+      kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
- }
- static acpi_status
-diff -Nurb linux-2.6.22-570/drivers/acpi/dock.c linux-2.6.22-590/drivers/acpi/dock.c
---- linux-2.6.22-570/drivers/acpi/dock.c       2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/acpi/dock.c       2008-01-02 13:56:37.000000000 -0500
-@@ -40,8 +40,15 @@
- MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION);
- MODULE_LICENSE("GPL");
-+static int immediate_undock = 1;
-+module_param(immediate_undock, bool, 0644);
-+MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
-+      "undock immediately when the undock button is pressed, 0 will cause"
-+      " the driver to wait for userspace to write the undock sysfs file "
-+      " before undocking");
-+
- static struct atomic_notifier_head dock_notifier_list;
--static struct platform_device dock_device;
-+static struct platform_device *dock_device;
- static char dock_device_name[] = "dock";
- struct dock_station {
-@@ -63,6 +70,7 @@
- };
- #define DOCK_DOCKING  0x00000001
-+#define DOCK_UNDOCKING  0x00000002
- #define DOCK_EVENT    3
- #define UNDOCK_EVENT  2
-@@ -327,12 +335,20 @@
- static void dock_event(struct dock_station *ds, u32 event, int num)
- {
--      struct device *dev = &dock_device.dev;
-+      struct device *dev = &dock_device->dev;
-+      char event_string[7];
-+      char *envp[] = { event_string, NULL };
-+
-+      if (num == UNDOCK_EVENT)
-+              sprintf(event_string, "UNDOCK");
-+      else
-+              sprintf(event_string, "DOCK");
-+
-       /*
-        * Indicate that the status of the dock station has
-        * changed.
-        */
--      kobject_uevent(&dev->kobj, KOBJ_CHANGE);
-+      kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
- }
- /**
-@@ -420,6 +436,16 @@
-       ds->last_dock_time = jiffies;
- }
-+static inline void begin_undock(struct dock_station *ds)
-+{
-+      ds->flags |= DOCK_UNDOCKING;
-+}
-+
-+static inline void complete_undock(struct dock_station *ds)
-+{
-+      ds->flags &= ~(DOCK_UNDOCKING);
-+}
-+
- /**
-  * dock_in_progress - see if we are in the middle of handling a dock event
-  * @ds: the dock station
-@@ -550,7 +576,7 @@
-               printk(KERN_ERR PREFIX "Unable to undock!\n");
-               return -EBUSY;
-       }
--
-+      complete_undock(ds);
-       return 0;
- }
-@@ -594,7 +620,11 @@
-        * to the driver who wish to hotplug.
-          */
-       case ACPI_NOTIFY_EJECT_REQUEST:
-+              begin_undock(ds);
-+              if (immediate_undock)
-               handle_eject_request(ds, event);
-+              else
-+                      dock_event(ds, event, UNDOCK_EVENT);
-               break;
-       default:
-               printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
-@@ -653,6 +683,17 @@
- DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
- /*
-+ * show_flags - read method for flags file in sysfs
-+ */
-+static ssize_t show_flags(struct device *dev,
-+                        struct device_attribute *attr, char *buf)
-+{
-+      return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
-+
-+}
-+DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
-+
-+/*
-  * write_undock - write method for "undock" file in sysfs
-  */
- static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
-@@ -675,16 +716,15 @@
-                            struct device_attribute *attr, char *buf)
- {
-       unsigned long lbuf;
--      acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf);
--      if(ACPI_FAILURE(status)) {
-+      acpi_status status = acpi_evaluate_integer(dock_station->handle,
-+                                      "_UID", NULL, &lbuf);
-+      if (ACPI_FAILURE(status))
-           return 0;
--      }
-+
-       return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
- }
- DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
--
--
- /**
-  * dock_add - add a new dock station
-  * @handle: the dock station handle
-diff -Nurb linux-2.6.22-570/drivers/acpi/ec.c linux-2.6.22-590/drivers/acpi/ec.c
---- linux-2.6.22-570/drivers/acpi/ec.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/acpi/ec.c 2008-01-02 13:56:37.000000000 -0500
-@@ -34,25 +34,26 @@
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/interrupt.h>
-+#include <linux/list.h>
- #include <asm/io.h>
- #include <acpi/acpi_bus.h>
- #include <acpi/acpi_drivers.h>
- #include <acpi/actypes.h>
--#define _COMPONENT            ACPI_EC_COMPONENT
--ACPI_MODULE_NAME("ec");
--#define ACPI_EC_COMPONENT             0x00100000
- #define ACPI_EC_CLASS                 "embedded_controller"
- #define ACPI_EC_HID                   "PNP0C09"
- #define ACPI_EC_DEVICE_NAME           "Embedded Controller"
- #define ACPI_EC_FILE_INFO             "info"
-+
- #undef PREFIX
- #define PREFIX                                "ACPI: EC: "
-+
- /* EC status register */
- #define ACPI_EC_FLAG_OBF      0x01    /* Output buffer full */
- #define ACPI_EC_FLAG_IBF      0x02    /* Input buffer full */
- #define ACPI_EC_FLAG_BURST    0x10    /* burst mode */
- #define ACPI_EC_FLAG_SCI      0x20    /* EC-SCI occurred */
-+
- /* EC commands */
- enum ec_command {
-       ACPI_EC_COMMAND_READ = 0x80,
-@@ -61,6 +62,7 @@
-       ACPI_EC_BURST_DISABLE = 0x83,
-       ACPI_EC_COMMAND_QUERY = 0x84,
- };
-+
- /* EC events */
- enum ec_event {
-       ACPI_EC_EVENT_OBF_1 = 1,        /* Output buffer full */
-@@ -94,6 +96,16 @@
- /* If we find an EC via the ECDT, we need to keep a ptr to its context */
- /* External interfaces use first EC only, so remember */
-+typedef int (*acpi_ec_query_func) (void *data);
-+
-+struct acpi_ec_query_handler {
-+      struct list_head node;
-+      acpi_ec_query_func func;
-+      acpi_handle handle;
-+      void *data;
-+      u8 query_bit;
-+};
-+
- static struct acpi_ec {
-       acpi_handle handle;
-       unsigned long gpe;
-@@ -104,6 +116,7 @@
-       atomic_t query_pending;
-       atomic_t event_count;
-       wait_queue_head_t wait;
-+      struct list_head list;
- } *boot_ec, *first_ec;
- /* --------------------------------------------------------------------------
-@@ -245,7 +258,7 @@
-       status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0);
-       if (status) {
--              printk(KERN_DEBUG PREFIX
-+              printk(KERN_ERR PREFIX
-                      "input buffer is not empty, aborting transaction\n");
-               goto end;
-       }
-@@ -394,21 +407,67 @@
- /* --------------------------------------------------------------------------
-                                 Event Management
-    -------------------------------------------------------------------------- */
-+int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
-+                            acpi_handle handle, acpi_ec_query_func func,
-+                            void *data)
-+{
-+      struct acpi_ec_query_handler *handler =
-+          kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL);
-+      if (!handler)
-+              return -ENOMEM;
-+
-+      handler->query_bit = query_bit;
-+      handler->handle = handle;
-+      handler->func = func;
-+      handler->data = data;
-+      mutex_lock(&ec->lock);
-+      list_add_tail(&handler->node, &ec->list);
-+      mutex_unlock(&ec->lock);
-+      return 0;
-+}
-+
-+EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
-+
-+void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
-+{
-+      struct acpi_ec_query_handler *handler;
-+      mutex_lock(&ec->lock);
-+      list_for_each_entry(handler, &ec->list, node) {
-+              if (query_bit == handler->query_bit) {
-+                      list_del(&handler->node);
-+                      kfree(handler);
-+                      break;
-+              }
-+      }
-+      mutex_unlock(&ec->lock);
-+}
-+
-+EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
- static void acpi_ec_gpe_query(void *ec_cxt)
- {
-       struct acpi_ec *ec = ec_cxt;
-       u8 value = 0;
--      char object_name[8];
-+      struct acpi_ec_query_handler *handler, copy;
-       if (!ec || acpi_ec_query(ec, &value))
-               return;
--
--      snprintf(object_name, 8, "_Q%2.2X", value);
--
--      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name));
--
--      acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
-+      mutex_lock(&ec->lock);
-+      list_for_each_entry(handler, &ec->list, node) {
-+              if (value == handler->query_bit) {
-+                      /* have custom handler for this bit */
-+                      memcpy(&copy, handler, sizeof(copy));
-+                      mutex_unlock(&ec->lock);
-+                      if (copy.func) {
-+                              copy.func(copy.data);
-+                      } else if (copy.handle) {
-+                              acpi_evaluate_object(copy.handle, NULL, NULL, NULL);
-+                      }
-+                      return;
-+              }
-+      }
-+      mutex_unlock(&ec->lock);
-+      printk(KERN_ERR PREFIX "Handler for query 0x%x is not found!\n", value);
- }
- static u32 acpi_ec_gpe_handler(void *data)
-@@ -427,8 +486,7 @@
-       if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) {
-               atomic_set(&ec->query_pending, 1);
-               status =
--                  acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query,
--                                  ec);
-+                  acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec);
-       }
-       return status == AE_OK ?
-@@ -454,57 +512,35 @@
- }
- static acpi_status
--acpi_ec_space_handler(u32 function,
--                    acpi_physical_address address,
--                    u32 bit_width,
--                    acpi_integer * value,
-+acpi_ec_space_handler(u32 function, acpi_physical_address address,
-+                    u32 bits, acpi_integer *value,
-                     void *handler_context, void *region_context)
- {
--      int result = 0;
-       struct acpi_ec *ec = handler_context;
--      u64 temp = *value;
--      acpi_integer f_v = 0;
--      int i = 0;
-+      int result = 0, i = 0;
-+      u8 temp = 0;
-       if ((address > 0xFF) || !value || !handler_context)
-               return AE_BAD_PARAMETER;
--      if (bit_width != 8 && acpi_strict) {
-+      if (function != ACPI_READ && function != ACPI_WRITE)
-               return AE_BAD_PARAMETER;
--      }
--      next_byte:
--      switch (function) {
--      case ACPI_READ:
--              temp = 0;
--              result = acpi_ec_read(ec, (u8) address, (u8 *) & temp);
--              break;
--      case ACPI_WRITE:
--              result = acpi_ec_write(ec, (u8) address, (u8) temp);
--              break;
--      default:
--              result = -EINVAL;
--              goto out;
--              break;
--      }
--
--      bit_width -= 8;
--      if (bit_width) {
--              if (function == ACPI_READ)
--                      f_v |= temp << 8 * i;
--              if (function == ACPI_WRITE)
--                      temp >>= 8;
--              i++;
--              address++;
--              goto next_byte;
--      }
-+      if (bits != 8 && acpi_strict)
-+              return AE_BAD_PARAMETER;
-+      while (bits - i > 0) {
-       if (function == ACPI_READ) {
--              f_v |= temp << 8 * i;
--              *value = f_v;
-+                      result = acpi_ec_read(ec, address, &temp);
-+                      (*value) |= ((acpi_integer)temp) << i;
-+              } else {
-+                      temp = 0xff & ((*value) >> i);
-+                      result = acpi_ec_write(ec, address, temp);
-+              }
-+              i += 8;
-+              ++address;
-       }
--      out:
-       switch (result) {
-       case -EINVAL:
-               return AE_BAD_PARAMETER;
-@@ -597,9 +633,6 @@
- static acpi_status
- ec_parse_io_ports(struct acpi_resource *resource, void *context);
--static acpi_status
--ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval);
--
- static struct acpi_ec *make_acpi_ec(void)
- {
-       struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
-@@ -610,13 +643,52 @@
-       atomic_set(&ec->event_count, 1);
-       mutex_init(&ec->lock);
-       init_waitqueue_head(&ec->wait);
-+      INIT_LIST_HEAD(&ec->list);
-       return ec;
- }
-+static acpi_status
-+acpi_ec_register_query_methods(acpi_handle handle, u32 level,
-+                             void *context, void **return_value)
-+{
-+      struct acpi_namespace_node *node = handle;
-+      struct acpi_ec *ec = context;
-+      int value = 0;
-+      if (sscanf(node->name.ascii, "_Q%x", &value) == 1) {
-+              acpi_ec_add_query_handler(ec, value, handle, NULL, NULL);
-+      }
-+      return AE_OK;
-+}
-+
-+static int ec_parse_device(struct acpi_ec *ec, acpi_handle handle)
-+{
-+      if (ACPI_FAILURE(acpi_walk_resources(handle, METHOD_NAME__CRS,
-+                                   ec_parse_io_ports, ec)))
-+              return -EINVAL;
-+
-+      /* Get GPE bit assignment (EC events). */
-+      /* TODO: Add support for _GPE returning a package */
-+      if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe)))
-+              return -EINVAL;
-+
-+      /* Use the global lock for all EC transactions? */
-+      acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
-+
-+      /* Find and register all query methods */
-+      acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1,
-+                          acpi_ec_register_query_methods, ec, NULL);
-+
-+      ec->handle = handle;
-+
-+      printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx",
-+                        ec->gpe, ec->command_addr, ec->data_addr);
-+
-+      return 0;
-+}
-+
- static int acpi_ec_add(struct acpi_device *device)
- {
--      acpi_status status = AE_OK;
-       struct acpi_ec *ec = NULL;
-       if (!device)
-@@ -629,8 +701,7 @@
-       if (!ec)
-               return -ENOMEM;
--      status = ec_parse_device(device->handle, 0, ec, NULL);
--      if (status != AE_CTRL_TERMINATE) {
-+      if (ec_parse_device(ec, device->handle)) {
-               kfree(ec);
-               return -EINVAL;
-       }
-@@ -641,6 +712,8 @@
-                       /* We might have incorrect info for GL at boot time */
-                       mutex_lock(&boot_ec->lock);
-                       boot_ec->global_lock = ec->global_lock;
-+                      /* Copy handlers from new ec into boot ec */
-+                      list_splice(&ec->list, &boot_ec->list);
-                       mutex_unlock(&boot_ec->lock);
-                       kfree(ec);
-                       ec = boot_ec;
-@@ -651,22 +724,24 @@
-       acpi_driver_data(device) = ec;
-       acpi_ec_add_fs(device);
--
--      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.",
--                        acpi_device_name(device), acpi_device_bid(device),
--                        (u32) ec->gpe));
--
-       return 0;
- }
- static int acpi_ec_remove(struct acpi_device *device, int type)
- {
-       struct acpi_ec *ec;
-+      struct acpi_ec_query_handler *handler;
-       if (!device)
-               return -EINVAL;
-       ec = acpi_driver_data(device);
-+      mutex_lock(&ec->lock);
-+      list_for_each_entry(handler, &ec->list, node) {
-+              list_del(&handler->node);
-+              kfree(handler);
-+      }
-+      mutex_unlock(&ec->lock);
-       acpi_ec_remove_fs(device);
-       acpi_driver_data(device) = NULL;
-       if (ec == first_ec)
-@@ -722,15 +797,13 @@
-               return -ENODEV;
-       }
--      /* EC is fully operational, allow queries */
--      atomic_set(&ec->query_pending, 0);
--
-       return 0;
- }
- static int acpi_ec_start(struct acpi_device *device)
- {
-       struct acpi_ec *ec;
-+      int ret = 0;
-       if (!device)
-               return -EINVAL;
-@@ -740,14 +813,14 @@
-       if (!ec)
-               return -EINVAL;
--      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
--                        ec->gpe, ec->command_addr, ec->data_addr));
--
-       /* Boot EC is already working */
--      if (ec == boot_ec)
--              return 0;
-+      if (ec != boot_ec)
-+              ret = ec_install_handlers(ec);
--      return ec_install_handlers(ec);
-+      /* EC is fully operational, allow queries */
-+      atomic_set(&ec->query_pending, 0);
-+
-+      return ret;
- }
- static int acpi_ec_stop(struct acpi_device *device, int type)
-@@ -779,34 +852,6 @@
-       return 0;
- }
--static acpi_status
--ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
--{
--      acpi_status status;
--
--      struct acpi_ec *ec = context;
--      status = acpi_walk_resources(handle, METHOD_NAME__CRS,
--                                   ec_parse_io_ports, ec);
--      if (ACPI_FAILURE(status))
--              return status;
--
--      /* Get GPE bit assignment (EC events). */
--      /* TODO: Add support for _GPE returning a package */
--      status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
--      if (ACPI_FAILURE(status))
--              return status;
--
--      /* Use the global lock for all EC transactions? */
--      acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
--
--      ec->handle = handle;
--
--      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
--                        ec->gpe, ec->command_addr, ec->data_addr));
--
--      return AE_CTRL_TERMINATE;
--}
--
- int __init acpi_ec_ecdt_probe(void)
- {
-       int ret;
-@@ -825,7 +870,7 @@
-       if (ACPI_FAILURE(status))
-               goto error;
--      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT"));
-+      printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n");
-       boot_ec->command_addr = ecdt_ptr->control.address;
-       boot_ec->data_addr = ecdt_ptr->data.address;
-diff -Nurb linux-2.6.22-570/drivers/acpi/osl.c linux-2.6.22-590/drivers/acpi/osl.c
---- linux-2.6.22-570/drivers/acpi/osl.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/acpi/osl.c        2008-01-02 13:56:37.000000000 -0500
-@@ -77,13 +77,7 @@
- #define       OSI_STRING_LENGTH_MAX 64        /* arbitrary */
- static char osi_additional_string[OSI_STRING_LENGTH_MAX];
--#define OSI_LINUX_ENABLED
--#ifdef        OSI_LINUX_ENABLED
--int osi_linux = 1;    /* enable _OSI(Linux) by default */
--#else
- int osi_linux;                /* disable _OSI(Linux) by default */
--#endif
--
- #ifdef CONFIG_DMI
- static struct __initdata dmi_system_id acpi_osl_dmi_table[];
-@@ -1056,6 +1050,17 @@
- EXPORT_SYMBOL(max_cstate);
-+void (*acpi_do_set_cstate_limit)(void);
-+EXPORT_SYMBOL(acpi_do_set_cstate_limit);
-+
-+void acpi_set_cstate_limit(unsigned int new_limit)
-+{
-+      max_cstate = new_limit;
-+      if (acpi_do_set_cstate_limit)
-+              acpi_do_set_cstate_limit();
-+}
-+EXPORT_SYMBOL(acpi_set_cstate_limit);
-+
- /*
-  * Acquire a spinlock.
-  *
-@@ -1183,17 +1188,10 @@
-       if (!strcmp("Linux", interface)) {
-               printk(KERN_WARNING PREFIX
-                       "System BIOS is requesting _OSI(Linux)\n");
--#ifdef        OSI_LINUX_ENABLED
--              printk(KERN_WARNING PREFIX
--                      "Please test with \"acpi_osi=!Linux\"\n"
--                      "Please send dmidecode "
--                      "to linux-acpi@vger.kernel.org\n");
--#else
-               printk(KERN_WARNING PREFIX
-                       "If \"acpi_osi=Linux\" works better,\n"
-                       "Please send dmidecode "
-                       "to linux-acpi@vger.kernel.org\n");
--#endif
-               if(osi_linux)
-                       return AE_OK;
-       }
-@@ -1227,36 +1225,14 @@
- }
- #ifdef CONFIG_DMI
--#ifdef        OSI_LINUX_ENABLED
--static int dmi_osi_not_linux(struct dmi_system_id *d)
--{
--      printk(KERN_NOTICE "%s detected: requires not _OSI(Linux)\n", d->ident);
--      enable_osi_linux(0);
--      return 0;
--}
--#else
- static int dmi_osi_linux(struct dmi_system_id *d)
- {
--      printk(KERN_NOTICE "%s detected: requires _OSI(Linux)\n", d->ident);
-+      printk(KERN_NOTICE "%s detected: enabling _OSI(Linux)\n", d->ident);
-       enable_osi_linux(1);
-       return 0;
- }
--#endif
- static struct dmi_system_id acpi_osl_dmi_table[] __initdata = {
--#ifdef        OSI_LINUX_ENABLED
--      /*
--       * Boxes that need NOT _OSI(Linux)
--       */
--      {
--       .callback = dmi_osi_not_linux,
--       .ident = "Toshiba Satellite P100",
--       .matches = {
--                   DMI_MATCH(DMI_BOARD_VENDOR, "TOSHIBA"),
--                   DMI_MATCH(DMI_BOARD_NAME, "Satellite P100"),
--                   },
--       },
--#else
-       /*
-        * Boxes that need _OSI(Linux)
-        */
-@@ -1268,7 +1244,6 @@
-                    DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"),
-                    },
-        },
--#endif
-       {}
- };
- #endif /* CONFIG_DMI */
-diff -Nurb linux-2.6.22-570/drivers/acpi/processor_core.c linux-2.6.22-590/drivers/acpi/processor_core.c
---- linux-2.6.22-570/drivers/acpi/processor_core.c     2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/acpi/processor_core.c     2008-01-02 13:56:37.000000000 -0500
-@@ -44,6 +44,7 @@
- #include <linux/seq_file.h>
- #include <linux/dmi.h>
- #include <linux/moduleparam.h>
-+#include <linux/cpuidle.h>
- #include <asm/io.h>
- #include <asm/system.h>
-@@ -66,6 +67,7 @@
- #define ACPI_PROCESSOR_FILE_LIMIT     "limit"
- #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
- #define ACPI_PROCESSOR_NOTIFY_POWER   0x81
-+#define ACPI_PROCESSOR_NOTIFY_THROTTLING      0x82
- #define ACPI_PROCESSOR_LIMIT_USER     0
- #define ACPI_PROCESSOR_LIMIT_THERMAL  1
-@@ -84,6 +86,8 @@
- static void acpi_processor_notify(acpi_handle handle, u32 event, void *data);
- static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
- static int acpi_processor_handle_eject(struct acpi_processor *pr);
-+extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
-+
- static struct acpi_driver acpi_processor_driver = {
-       .name = "processor",
-@@ -701,6 +705,9 @@
-               acpi_processor_cst_has_changed(pr);
-               acpi_bus_generate_event(device, event, 0);
-               break;
-+      case ACPI_PROCESSOR_NOTIFY_THROTTLING:
-+              acpi_processor_tstate_has_changed(pr);
-+              acpi_bus_generate_event(device, event, 0);
-       default:
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "Unsupported event [0x%x]\n", event));
-@@ -1024,11 +1031,15 @@
-       acpi_processor_ppc_init();
-+      cpuidle_register_driver(&acpi_idle_driver);
-+      acpi_do_set_cstate_limit = acpi_max_cstate_changed;
-       return 0;
- }
- static void __exit acpi_processor_exit(void)
- {
-+      acpi_do_set_cstate_limit = NULL;
-+      cpuidle_unregister_driver(&acpi_idle_driver);
-       acpi_processor_ppc_exit();
-diff -Nurb linux-2.6.22-570/drivers/acpi/processor_idle.c linux-2.6.22-590/drivers/acpi/processor_idle.c
---- linux-2.6.22-570/drivers/acpi/processor_idle.c     2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/acpi/processor_idle.c     2008-01-02 13:56:37.000000000 -0500
-@@ -40,6 +40,7 @@
- #include <linux/sched.h>      /* need_resched() */
- #include <linux/latency.h>
- #include <linux/clockchips.h>
-+#include <linux/cpuidle.h>
- /*
-  * Include the apic definitions for x86 to have the APIC timer related defines
-@@ -62,25 +63,34 @@
- #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
- ACPI_MODULE_NAME("processor_idle");
- #define ACPI_PROCESSOR_FILE_POWER     "power"
--#define US_TO_PM_TIMER_TICKS(t)               ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
--#define C2_OVERHEAD                   4       /* 1us (3.579 ticks per us) */
--#define C3_OVERHEAD                   4       /* 1us (3.579 ticks per us) */
--static void (*pm_idle_save) (void) __read_mostly;
--module_param(max_cstate, uint, 0644);
-+#define PM_TIMER_TICKS_TO_US(p)               (((p) * 1000)/(PM_TIMER_FREQUENCY/1000))
-+#define C2_OVERHEAD                   1       /* 1us */
-+#define C3_OVERHEAD                   1       /* 1us */
-+
-+void acpi_max_cstate_changed(void)
-+{
-+      /* Driver will reset devices' max cstate limit */
-+      cpuidle_force_redetect_devices(&acpi_idle_driver);
-+}
-+
-+static int change_max_cstate(const char *val, struct kernel_param *kp)
-+{
-+      int max;
-+
-+      max = simple_strtol(val, NULL, 0);
-+      if (!max)
-+              return -EINVAL;
-+      max_cstate = max;
-+      if (acpi_do_set_cstate_limit)
-+              acpi_do_set_cstate_limit();
-+      return 0;
-+}
-+
-+module_param_call(max_cstate, change_max_cstate, param_get_uint, &max_cstate, 0644);
- static unsigned int nocst __read_mostly;
- module_param(nocst, uint, 0000);
--/*
-- * bm_history -- bit-mask with a bit per jiffy of bus-master activity
-- * 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms
-- * 800 HZ: 0xFFFFFFFF: 32 jiffies = 40ms
-- * 100 HZ: 0x0000000F: 4 jiffies = 40ms
-- * reduce history for more aggressive entry into C3
-- */
--static unsigned int bm_history __read_mostly =
--    (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
--module_param(bm_history, uint, 0644);
- /* --------------------------------------------------------------------------
-                                 Power Management
-    -------------------------------------------------------------------------- */
-@@ -166,88 +176,6 @@
-       {},
- };
--static inline u32 ticks_elapsed(u32 t1, u32 t2)
--{
--      if (t2 >= t1)
--              return (t2 - t1);
--      else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER))
--              return (((0x00FFFFFF - t1) + t2) & 0x00FFFFFF);
--      else
--              return ((0xFFFFFFFF - t1) + t2);
--}
--
--static void
--acpi_processor_power_activate(struct acpi_processor *pr,
--                            struct acpi_processor_cx *new)
--{
--      struct acpi_processor_cx *old;
--
--      if (!pr || !new)
--              return;
--
--      old = pr->power.state;
--
--      if (old)
--              old->promotion.count = 0;
--      new->demotion.count = 0;
--
--      /* Cleanup from old state. */
--      if (old) {
--              switch (old->type) {
--              case ACPI_STATE_C3:
--                      /* Disable bus master reload */
--                      if (new->type != ACPI_STATE_C3 && pr->flags.bm_check)
--                              acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
--                      break;
--              }
--      }
--
--      /* Prepare to use new state. */
--      switch (new->type) {
--      case ACPI_STATE_C3:
--              /* Enable bus master reload */
--              if (old->type != ACPI_STATE_C3 && pr->flags.bm_check)
--                      acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
--              break;
--      }
--
--      pr->power.state = new;
--
--      return;
--}
--
--static void acpi_safe_halt(void)
--{
--      current_thread_info()->status &= ~TS_POLLING;
--      /*
--       * TS_POLLING-cleared state must be visible before we
--       * test NEED_RESCHED:
--       */
--      smp_mb();
--      if (!need_resched())
--              safe_halt();
--      current_thread_info()->status |= TS_POLLING;
--}
--
--static atomic_t c3_cpu_count;
--
--/* Common C-state entry for C2, C3, .. */
--static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
--{
--      if (cstate->space_id == ACPI_CSTATE_FFH) {
--              /* Call into architectural FFH based C-state */
--              acpi_processor_ffh_cstate_enter(cstate);
--      } else {
--              int unused;
--              /* IO port based C-state */
--              inb(cstate->address);
--              /* Dummy wait op - must do something useless after P_LVL2 read
--                 because chipsets cannot guarantee that STPCLK# signal
--                 gets asserted in time to freeze execution properly. */
--              unused = inl(acpi_gbl_FADT.xpm_timer_block.address);
--      }
--}
--
- #ifdef ARCH_APICTIMER_STOPS_ON_C3
- /*
-@@ -341,6 +269,7 @@
-       return 0;
- }
-+<<<<<<< HEAD/drivers/acpi/processor_idle.c
- static void acpi_processor_idle(void)
- {
-       struct acpi_processor *pr = NULL;
-@@ -712,6 +641,8 @@
-       return 0;
- }
-+=======
-+>>>>>>> /drivers/acpi/processor_idle.c
- static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
- {
-@@ -929,7 +860,7 @@
-        * Normalize the C2 latency to expidite policy
-        */
-       cx->valid = 1;
--      cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
-+      cx->latency_ticks = cx->latency;
-       return;
- }
-@@ -1003,7 +934,7 @@
-        * use this in our C3 policy
-        */
-       cx->valid = 1;
--      cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
-+      cx->latency_ticks = cx->latency;
-       return;
- }
-@@ -1069,18 +1000,6 @@
-       pr->power.count = acpi_processor_power_verify(pr);
-       /*
--       * Set Default Policy
--       * ------------------
--       * Now that we know which states are supported, set the default
--       * policy.  Note that this policy can be changed dynamically
--       * (e.g. encourage deeper sleeps to conserve battery life when
--       * not on AC).
--       */
--      result = acpi_processor_set_power_policy(pr);
--      if (result)
--              return result;
--
--      /*
-        * if one state of type C2 or C3 is available, mark this
-        * CPU as being "idle manageable"
-        */
-@@ -1097,9 +1016,6 @@
- int acpi_processor_cst_has_changed(struct acpi_processor *pr)
- {
--      int result = 0;
--
--
-       if (!pr)
-               return -EINVAL;
-@@ -1110,16 +1026,9 @@
-       if (!pr->flags.power_setup_done)
-               return -ENODEV;
--      /* Fall back to the default idle loop */
--      pm_idle = pm_idle_save;
--      synchronize_sched();    /* Relies on interrupts forcing exit from idle. */
--
--      pr->flags.power = 0;
--      result = acpi_processor_get_power_info(pr);
--      if ((pr->flags.power == 1) && (pr->flags.power_setup_done))
--              pm_idle = acpi_processor_idle;
--
--      return result;
-+      acpi_processor_get_power_info(pr);
-+      return cpuidle_force_redetect(per_cpu(cpuidle_devices, pr->id),
-+              &acpi_idle_driver);
- }
- /* proc interface */
-@@ -1205,30 +1114,6 @@
-       .release = single_release,
- };
--#ifdef CONFIG_SMP
--static void smp_callback(void *v)
--{
--      /* we already woke the CPU up, nothing more to do */
--}
--
--/*
-- * This function gets called when a part of the kernel has a new latency
-- * requirement.  This means we need to get all processors out of their C-state,
-- * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that
-- * wakes them all right up.
-- */
--static int acpi_processor_latency_notify(struct notifier_block *b,
--              unsigned long l, void *v)
--{
--      smp_call_function(smp_callback, NULL, 0, 1);
--      return NOTIFY_OK;
--}
--
--static struct notifier_block acpi_processor_latency_notifier = {
--      .notifier_call = acpi_processor_latency_notify,
--};
--#endif
--
- int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
-                             struct acpi_device *device)
- {
-@@ -1245,9 +1130,6 @@
-                              "ACPI: processor limited to max C-state %d\n",
-                              max_cstate);
-               first_run++;
--#ifdef CONFIG_SMP
--              register_latency_notifier(&acpi_processor_latency_notifier);
--#endif
-       }
-       if (!pr)
-@@ -1264,6 +1146,7 @@
-       acpi_processor_get_power_info(pr);
-+
-       /*
-        * Install the idle handler if processor power management is supported.
-        * Note that we use previously set idle handler will be used on
-@@ -1276,11 +1159,6 @@
-                               printk(" C%d[C%d]", i,
-                                      pr->power.states[i].type);
-               printk(")\n");
--
--              if (pr->id == 0) {
--                      pm_idle_save = pm_idle;
--                      pm_idle = acpi_processor_idle;
--              }
-       }
-       /* 'power' [R] */
-@@ -1308,21 +1186,332 @@
-       if (acpi_device_dir(device))
-               remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,
-                                 acpi_device_dir(device));
-+      return 0;
-+}
-+
-+/**
-+ * ticks_elapsed - a helper function that determines how many ticks (in US)
-+ *               have elapsed between two PM Timer timestamps
-+ * @t1: the start time
-+ * @t2: the end time
-+ */
-+static inline u32 ticks_elapsed(u32 t1, u32 t2)
-+{
-+      if (t2 >= t1)
-+              return PM_TIMER_TICKS_TO_US(t2 - t1);
-+      else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER))
-+              return PM_TIMER_TICKS_TO_US(((0x00FFFFFF - t1) + t2) & 0x00FFFFFF);
-+      else
-+              return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2);
-+}
--      /* Unregister the idle handler when processor #0 is removed. */
--      if (pr->id == 0) {
--              pm_idle = pm_idle_save;
-+/**
-+ * acpi_idle_update_bm_rld - updates the BM_RLD bit depending on target state
-+ * @pr: the processor
-+ * @target: the new target state
-+ */
-+static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr,
-+                                         struct acpi_processor_cx *target)
-+{
-+      if (pr->flags.bm_rld_set && target->type != ACPI_STATE_C3) {
-+              acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
-+              pr->flags.bm_rld_set = 0;
-+      }
-+      if (!pr->flags.bm_rld_set && target->type == ACPI_STATE_C3) {
-+              acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
-+              pr->flags.bm_rld_set = 1;
-+      }
-+}
-+
-+/**
-+ * acpi_idle_do_entry - a helper function that does C2 and C3 type entry
-+ * @cx: cstate data
-+ */
-+static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
-+{
-+      if (cx->space_id == ACPI_CSTATE_FFH) {
-+              /* Call into architectural FFH based C-state */
-+              acpi_processor_ffh_cstate_enter(cx);
-+      } else {
-+              int unused;
-+              /* IO port based C-state */
-+              inb(cx->address);
-+              /* Dummy wait op - must do something useless after P_LVL2 read
-+                 because chipsets cannot guarantee that STPCLK# signal
-+                 gets asserted in time to freeze execution properly. */
-+              unused = inl(acpi_gbl_FADT.xpm_timer_block.address);
-+      }
-+}
-+
-+/**
-+ * acpi_idle_enter_c1 - enters an ACPI C1 state-type
-+ * @dev: the target CPU
-+ * @state: the state data
-+ *
-+ * This is equivalent to the HALT instruction.
-+ */
-+static int acpi_idle_enter_c1(struct cpuidle_device *dev,
-+                            struct cpuidle_state *state)
-+{
-+      struct acpi_processor *pr;
-+      struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
-+      pr = processors[smp_processor_id()];
-+
-+      if (unlikely(!pr))
-+              return 0;
-+
-+      if (pr->flags.bm_check)
-+              acpi_idle_update_bm_rld(pr, cx);
-+
-+      current_thread_info()->status &= ~TS_POLLING;
-               /*
--               * We are about to unload the current idle thread pm callback
--               * (pm_idle), Wait for all processors to update cached/local
--               * copies of pm_idle before proceeding.
--               */
--              cpu_idle_wait();
--#ifdef CONFIG_SMP
--              unregister_latency_notifier(&acpi_processor_latency_notifier);
-+       * TS_POLLING-cleared state must be visible before we test
-+       * NEED_RESCHED:
-+       */
-+      smp_mb();
-+      if (!need_resched())
-+              safe_halt();
-+      current_thread_info()->status |= TS_POLLING;
-+
-+      cx->usage++;
-+
-+      return 0;
-+}
-+
-+/**
-+ * acpi_idle_enter_c2 - enters an ACPI C2 state-type
-+ * @dev: the target CPU
-+ * @state: the state data
-+ */
-+static int acpi_idle_enter_c2(struct cpuidle_device *dev,
-+                            struct cpuidle_state *state)
-+{
-+      struct acpi_processor *pr;
-+      struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
-+      u32 t1, t2;
-+      pr = processors[smp_processor_id()];
-+
-+      if (unlikely(!pr))
-+              return 0;
-+
-+      if (pr->flags.bm_check)
-+              acpi_idle_update_bm_rld(pr, cx);
-+
-+      local_irq_disable();
-+      current_thread_info()->status &= ~TS_POLLING;
-+      /*
-+       * TS_POLLING-cleared state must be visible before we test
-+       * NEED_RESCHED:
-+       */
-+      smp_mb();
-+
-+      if (unlikely(need_resched())) {
-+              current_thread_info()->status |= TS_POLLING;
-+              local_irq_enable();
-+              return 0;
-+      }
-+
-+      t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
-+      acpi_state_timer_broadcast(pr, cx, 1);
-+      acpi_idle_do_entry(cx);
-+      t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
-+
-+#ifdef CONFIG_GENERIC_TIME
-+      /* TSC halts in C2, so notify users */
-+      mark_tsc_unstable("possible TSC halt in C2");
- #endif
-+
-+      local_irq_enable();
-+      current_thread_info()->status |= TS_POLLING;
-+
-+      cx->usage++;
-+
-+      acpi_state_timer_broadcast(pr, cx, 0);
-+      return ticks_elapsed(t1, t2);
-+}
-+
-+static int c3_cpu_count;
-+static DEFINE_SPINLOCK(c3_lock);
-+
-+/**
-+ * acpi_idle_enter_c3 - enters an ACPI C3 state-type
-+ * @dev: the target CPU
-+ * @state: the state data
-+ *
-+ * Similar to C2 entry, except special bus master handling is needed.
-+ */
-+static int acpi_idle_enter_c3(struct cpuidle_device *dev,
-+                            struct cpuidle_state *state)
-+{
-+      struct acpi_processor *pr;
-+      struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
-+      u32 t1, t2;
-+      pr = processors[smp_processor_id()];
-+
-+      if (unlikely(!pr))
-+              return 0;
-+
-+      if (pr->flags.bm_check)
-+              acpi_idle_update_bm_rld(pr, cx);
-+
-+      local_irq_disable();
-+      current_thread_info()->status &= ~TS_POLLING;
-+      /*
-+       * TS_POLLING-cleared state must be visible before we test
-+       * NEED_RESCHED:
-+       */
-+      smp_mb();
-+
-+      if (unlikely(need_resched())) {
-+              current_thread_info()->status |= TS_POLLING;
-+              local_irq_enable();
-+              return 0;
-+      }
-+
-+      /* disable bus master */
-+      if (pr->flags.bm_check) {
-+              spin_lock(&c3_lock);
-+                      c3_cpu_count++;
-+              if (c3_cpu_count == num_online_cpus()) {
-+                      /*
-+                       * All CPUs are trying to go to C3
-+                       * Disable bus master arbitration
-+                       */
-+                      acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
-+              }
-+              spin_unlock(&c3_lock);
-+      } else {
-+              /* SMP with no shared cache... Invalidate cache  */
-+              ACPI_FLUSH_CPU_CACHE();
-+      }
-+
-+      /* Get start time (ticks) */
-+      t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
-+      acpi_state_timer_broadcast(pr, cx, 1);
-+      acpi_idle_do_entry(cx);
-+      t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
-+
-+      if (pr->flags.bm_check) {
-+              spin_lock(&c3_lock);
-+              /* Enable bus master arbitration */
-+              if (c3_cpu_count == num_online_cpus())
-+                      acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
-+              c3_cpu_count--;
-+              spin_unlock(&c3_lock);
-       }
-+#ifdef CONFIG_GENERIC_TIME
-+      /* TSC halts in C3, so notify users */
-+      mark_tsc_unstable("TSC halts in C3");
-+#endif
-+
-+      local_irq_enable();
-+      current_thread_info()->status |= TS_POLLING;
-+
-+      cx->usage++;
-+
-+      acpi_state_timer_broadcast(pr, cx, 0);
-+      return ticks_elapsed(t1, t2);
-+}
-+
-+/**
-+ * acpi_idle_bm_check - checks if bus master activity was detected
-+ */
-+static int acpi_idle_bm_check(void)
-+{
-+      u32 bm_status = 0;
-+
-+      acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
-+      if (bm_status)
-+              acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
-+      /*
-+       * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
-+       * the true state of bus mastering activity; forcing us to
-+       * manually check the BMIDEA bit of each IDE channel.
-+       */
-+      else if (errata.piix4.bmisx) {
-+              if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01)
-+                  || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
-+                      bm_status = 1;
-+      }
-+      return bm_status;
-+}
-+
-+/**
-+ * acpi_idle_init - attaches the driver to a CPU
-+ * @dev: the CPU
-+ */
-+static int acpi_idle_init(struct cpuidle_device *dev)
-+{
-+      int cpu = dev->cpu;
-+      int i, count = 0;
-+      struct acpi_processor_cx *cx;
-+      struct cpuidle_state *state;
-+
-+      struct acpi_processor *pr = processors[cpu];
-+
-+      if (!pr->flags.power_setup_done)
-+              return -EINVAL;
-+
-+      if (pr->flags.power == 0) {
-+              return -EINVAL;
-+      }
-+
-+      for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
-+              cx = &pr->power.states[i];
-+              state = &dev->states[count];
-+
-+              if (!cx->valid)
-+                      continue;
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+              if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
-+                  !pr->flags.has_cst &&
-+                  !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
-+                      continue;
-+#endif
-+              cpuidle_set_statedata(state, cx);
-+
-+              state->exit_latency = cx->latency;
-+              state->target_residency = cx->latency * 6;
-+              state->power_usage = cx->power;
-+
-+              state->flags = 0;
-+              switch (cx->type) {
-+                      case ACPI_STATE_C1:
-+                      state->flags |= CPUIDLE_FLAG_SHALLOW;
-+                      state->enter = acpi_idle_enter_c1;
-+                      break;
-+
-+                      case ACPI_STATE_C2:
-+                      state->flags |= CPUIDLE_FLAG_BALANCED;
-+                      state->flags |= CPUIDLE_FLAG_TIME_VALID;
-+                      state->enter = acpi_idle_enter_c2;
-+                      break;
-+
-+                      case ACPI_STATE_C3:
-+                      state->flags |= CPUIDLE_FLAG_DEEP;
-+                      state->flags |= CPUIDLE_FLAG_TIME_VALID;
-+                      state->flags |= CPUIDLE_FLAG_CHECK_BM;
-+                      state->enter = acpi_idle_enter_c3;
-+                      break;
-+              }
-+
-+              count++;
-+      }
-+
-+      if (!count)
-+              return -EINVAL;
-+
-+      dev->state_count = count;
-       return 0;
- }
-+
-+struct cpuidle_driver acpi_idle_driver = {
-+      .name =         "acpi_idle",
-+      .init =         acpi_idle_init,
-+      .redetect =     acpi_idle_init,
-+      .bm_check =     acpi_idle_bm_check,
-+      .owner =        THIS_MODULE,
-+};
-diff -Nurb linux-2.6.22-570/drivers/acpi/processor_throttling.c linux-2.6.22-590/drivers/acpi/processor_throttling.c
---- linux-2.6.22-570/drivers/acpi/processor_throttling.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/acpi/processor_throttling.c       2008-01-02 13:56:37.000000000 -0500
-@@ -44,17 +44,231 @@
- #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
- ACPI_MODULE_NAME("processor_throttling");
-+static int acpi_processor_get_throttling(struct acpi_processor *pr);
-+int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
-+
-+static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
-+{
-+      acpi_status status = 0;
-+      unsigned long tpc = 0;
-+
-+      if (!pr)
-+              return -EINVAL;
-+      status = acpi_evaluate_integer(pr->handle, "_TPC", NULL, &tpc);
-+      if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-+              ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TPC"));
-+              return -ENODEV;
-+      }
-+      pr->throttling_platform_limit = (int)tpc;
-+      return 0;
-+}
-+
-+int acpi_processor_tstate_has_changed(struct acpi_processor *pr)
-+{
-+      return acpi_processor_get_platform_limit(pr);
-+}
-+
-+/* --------------------------------------------------------------------------
-+                             _PTC, _TSS, _TSD support 
-+   -------------------------------------------------------------------------- */
-+static int acpi_processor_get_throttling_control(struct acpi_processor *pr)
-+{
-+      int result = 0;
-+      acpi_status status = 0;
-+      struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-+      union acpi_object *ptc = NULL;
-+      union acpi_object obj = { 0 };
-+
-+      status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer);
-+      if (ACPI_FAILURE(status)) {
-+              ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTC"));
-+              return -ENODEV;
-+      }
-+
-+      ptc = (union acpi_object *)buffer.pointer;
-+      if (!ptc || (ptc->type != ACPI_TYPE_PACKAGE)
-+          || (ptc->package.count != 2)) {
-+              printk(KERN_ERR PREFIX "Invalid _PTC data\n");
-+              result = -EFAULT;
-+              goto end;
-+      }
-+
-+      /*
-+       * control_register
-+       */
-+
-+      obj = ptc->package.elements[0];
-+
-+      if ((obj.type != ACPI_TYPE_BUFFER)
-+          || (obj.buffer.length < sizeof(struct acpi_ptc_register))
-+          || (obj.buffer.pointer == NULL)) {
-+              printk(KERN_ERR PREFIX
-+                     "Invalid _PTC data (control_register)\n");
-+              result = -EFAULT;
-+              goto end;
-+      }
-+      memcpy(&pr->throttling.control_register, obj.buffer.pointer,
-+             sizeof(struct acpi_ptc_register));
-+
-+      /*
-+       * status_register
-+       */
-+
-+      obj = ptc->package.elements[1];
-+
-+      if ((obj.type != ACPI_TYPE_BUFFER)
-+          || (obj.buffer.length < sizeof(struct acpi_ptc_register))
-+          || (obj.buffer.pointer == NULL)) {
-+              printk(KERN_ERR PREFIX "Invalid _PTC data (status_register)\n");
-+              result = -EFAULT;
-+              goto end;
-+      }
-+
-+      memcpy(&pr->throttling.status_register, obj.buffer.pointer,
-+             sizeof(struct acpi_ptc_register));
-+
-+      end:
-+      kfree(buffer.pointer);
-+
-+      return result;
-+}
-+static int acpi_processor_get_throttling_states(struct acpi_processor *pr)
-+{
-+      int result = 0;
-+      acpi_status status = AE_OK;
-+      struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-+      struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
-+      struct acpi_buffer state = { 0, NULL };
-+      union acpi_object *tss = NULL;
-+      int i;
-+
-+      status = acpi_evaluate_object(pr->handle, "_TSS", NULL, &buffer);
-+      if (ACPI_FAILURE(status)) {
-+              ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSS"));
-+              return -ENODEV;
-+      }
-+
-+      tss = buffer.pointer;
-+      if (!tss || (tss->type != ACPI_TYPE_PACKAGE)) {
-+              printk(KERN_ERR PREFIX "Invalid _TSS data\n");
-+              result = -EFAULT;
-+              goto end;
-+      }
-+
-+      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n",
-+                        tss->package.count));
-+
-+      pr->throttling.state_count = tss->package.count;
-+      pr->throttling.states_tss =
-+          kmalloc(sizeof(struct acpi_processor_tx_tss) * tss->package.count,
-+                  GFP_KERNEL);
-+      if (!pr->throttling.states_tss) {
-+              result = -ENOMEM;
-+              goto end;
-+      }
-+
-+      for (i = 0; i < pr->throttling.state_count; i++) {
-+
-+              struct acpi_processor_tx_tss *tx =
-+                  (struct acpi_processor_tx_tss *)&(pr->throttling.
-+                                                    states_tss[i]);
-+
-+              state.length = sizeof(struct acpi_processor_tx_tss);
-+              state.pointer = tx;
-+
-+              ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
-+
-+              status = acpi_extract_package(&(tss->package.elements[i]),
-+                                            &format, &state);
-+              if (ACPI_FAILURE(status)) {
-+                      ACPI_EXCEPTION((AE_INFO, status, "Invalid _TSS data"));
-+                      result = -EFAULT;
-+                      kfree(pr->throttling.states_tss);
-+                      goto end;
-+              }
-+
-+              if (!tx->freqpercentage) {
-+                      printk(KERN_ERR PREFIX
-+                             "Invalid _TSS data: freq is zero\n");
-+                      result = -EFAULT;
-+                      kfree(pr->throttling.states_tss);
-+                      goto end;
-+              }
-+      }
-+
-+      end:
-+      kfree(buffer.pointer);
-+
-+      return result;
-+}
-+static int acpi_processor_get_tsd(struct acpi_processor *pr)
-+{
-+      int result = 0;
-+      acpi_status status = AE_OK;
-+      struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-+      struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
-+      struct acpi_buffer state = { 0, NULL };
-+      union acpi_object *tsd = NULL;
-+      struct acpi_tsd_package *pdomain;
-+
-+      status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer);
-+      if (ACPI_FAILURE(status)) {
-+              return -ENODEV;
-+      }
-+
-+      tsd = buffer.pointer;
-+      if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) {
-+              ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
-+              result = -EFAULT;
-+              goto end;
-+      }
-+
-+      if (tsd->package.count != 1) {
-+              ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
-+              result = -EFAULT;
-+              goto end;
-+      }
-+
-+      pdomain = &(pr->throttling.domain_info);
-+
-+      state.length = sizeof(struct acpi_tsd_package);
-+      state.pointer = pdomain;
-+
-+      status = acpi_extract_package(&(tsd->package.elements[0]),
-+                                    &format, &state);
-+      if (ACPI_FAILURE(status)) {
-+              ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
-+              result = -EFAULT;
-+              goto end;
-+      }
-+
-+      if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) {
-+              ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:num_entries\n"));
-+              result = -EFAULT;
-+              goto end;
-+      }
-+
-+      if (pdomain->revision != ACPI_TSD_REV0_REVISION) {
-+              ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:revision\n"));
-+              result = -EFAULT;
-+              goto end;
-+      }
-+
-+      end:
-+      kfree(buffer.pointer);
-+      return result;
-+}
-+
- /* --------------------------------------------------------------------------
-                               Throttling Control
-    -------------------------------------------------------------------------- */
--static int acpi_processor_get_throttling(struct acpi_processor *pr)
-+static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr)
- {
-       int state = 0;
-       u32 value = 0;
-       u32 duty_mask = 0;
-       u32 duty_value = 0;
--
-       if (!pr)
-               return -EINVAL;
-@@ -94,13 +308,114 @@
-       return 0;
- }
--int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
-+static int acpi_read_throttling_status(struct acpi_processor_throttling
-+                                     *throttling)
-+{
-+      int value = -1;
-+      switch (throttling->status_register.space_id) {
-+      case ACPI_ADR_SPACE_SYSTEM_IO:
-+              acpi_os_read_port((acpi_io_address) throttling->status_register.
-+                                address, &value,
-+                                (u32) throttling->status_register.bit_width *
-+                                8);
-+              break;
-+      case ACPI_ADR_SPACE_FIXED_HARDWARE:
-+              printk(KERN_ERR PREFIX
-+                     "HARDWARE addr space,NOT supported yet\n");
-+              break;
-+      default:
-+              printk(KERN_ERR PREFIX "Unknown addr space %d\n",
-+                     (u32) (throttling->status_register.space_id));
-+      }
-+      return value;
-+}
-+
-+static int acpi_write_throttling_state(struct acpi_processor_throttling
-+                                     *throttling, int value)
-+{
-+      int ret = -1;
-+
-+      switch (throttling->control_register.space_id) {
-+      case ACPI_ADR_SPACE_SYSTEM_IO:
-+              acpi_os_write_port((acpi_io_address) throttling->
-+                                 control_register.address, value,
-+                                 (u32) throttling->control_register.
-+                                 bit_width * 8);
-+              ret = 0;
-+              break;
-+      case ACPI_ADR_SPACE_FIXED_HARDWARE:
-+              printk(KERN_ERR PREFIX
-+                     "HARDWARE addr space,NOT supported yet\n");
-+              break;
-+      default:
-+              printk(KERN_ERR PREFIX "Unknown addr space %d\n",
-+                     (u32) (throttling->control_register.space_id));
-+      }
-+      return ret;
-+}
-+
-+static int acpi_get_throttling_state(struct acpi_processor *pr, int value)
-+{
-+      int i;
-+
-+      for (i = 0; i < pr->throttling.state_count; i++) {
-+              struct acpi_processor_tx_tss *tx =
-+                  (struct acpi_processor_tx_tss *)&(pr->throttling.
-+                                                    states_tss[i]);
-+              if (tx->control == value)
-+                      break;
-+      }
-+      if (i > pr->throttling.state_count)
-+              i = -1;
-+      return i;
-+}
-+
-+static int acpi_get_throttling_value(struct acpi_processor *pr, int state)
-+{
-+      int value = -1;
-+      if (state >= 0 && state <= pr->throttling.state_count) {
-+              struct acpi_processor_tx_tss *tx =
-+                  (struct acpi_processor_tx_tss *)&(pr->throttling.
-+                                                    states_tss[state]);
-+              value = tx->control;
-+      }
-+      return value;
-+}
-+
-+static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
-+{
-+      int state = 0;
-+      u32 value = 0;
-+
-+      if (!pr)
-+              return -EINVAL;
-+
-+      if (!pr->flags.throttling)
-+              return -ENODEV;
-+
-+      pr->throttling.state = 0;
-+      local_irq_disable();
-+      value = acpi_read_throttling_status(&pr->throttling);
-+      if (value >= 0) {
-+              state = acpi_get_throttling_state(pr, value);
-+              pr->throttling.state = state;
-+      }
-+      local_irq_enable();
-+
-+      return 0;
-+}
-+
-+static int acpi_processor_get_throttling(struct acpi_processor *pr)
-+{
-+      return pr->throttling.acpi_processor_get_throttling(pr);
-+}
-+
-+int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, int state)
- {
-       u32 value = 0;
-       u32 duty_mask = 0;
-       u32 duty_value = 0;
--
-       if (!pr)
-               return -EINVAL;
-@@ -113,6 +428,8 @@
-       if (state == pr->throttling.state)
-               return 0;
-+      if (state < pr->throttling_platform_limit)
-+              return -EPERM;
-       /*
-        * Calculate the duty_value and duty_mask.
-        */
-@@ -165,12 +482,50 @@
-       return 0;
- }
-+int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, int state)
-+{
-+      u32 value = 0;
-+
-+      if (!pr)
-+              return -EINVAL;
-+
-+      if ((state < 0) || (state > (pr->throttling.state_count - 1)))
-+              return -EINVAL;
-+
-+      if (!pr->flags.throttling)
-+              return -ENODEV;
-+
-+      if (state == pr->throttling.state)
-+              return 0;
-+
-+      if (state < pr->throttling_platform_limit)
-+              return -EPERM;
-+
-+      local_irq_disable();
-+
-+      value = acpi_get_throttling_value(pr, state);
-+      if (value >= 0) {
-+              acpi_write_throttling_state(&pr->throttling, value);
-+              pr->throttling.state = state;
-+      }
-+      local_irq_enable();
-+
-+      return 0;
-+}
-+
-+int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
-+{
-+      return pr->throttling.acpi_processor_set_throttling(pr, state);
-+}
-+
- int acpi_processor_get_throttling_info(struct acpi_processor *pr)
- {
-       int result = 0;
-       int step = 0;
-       int i = 0;
--
-+      int no_ptc = 0;
-+      int no_tss = 0;
-+      int no_tsd = 0;
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                         "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n",
-@@ -182,6 +537,21 @@
-               return -EINVAL;
-       /* TBD: Support ACPI 2.0 objects */
-+      no_ptc = acpi_processor_get_throttling_control(pr);
-+      no_tss = acpi_processor_get_throttling_states(pr);
-+      no_tsd = acpi_processor_get_tsd(pr);
-+
-+      if (no_ptc || no_tss) {
-+              pr->throttling.acpi_processor_get_throttling =
-+                  &acpi_processor_get_throttling_fadt;
-+              pr->throttling.acpi_processor_set_throttling =
-+                  &acpi_processor_set_throttling_fadt;
-+      } else {
-+              pr->throttling.acpi_processor_get_throttling =
-+                  &acpi_processor_get_throttling_ptc;
-+              pr->throttling.acpi_processor_set_throttling =
-+                  &acpi_processor_set_throttling_ptc;
-+      }
-       if (!pr->throttling.address) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n"));
-@@ -262,7 +632,6 @@
-       int i = 0;
-       int result = 0;
--
-       if (!pr)
-               goto end;
-@@ -280,15 +649,27 @@
-       }
-       seq_printf(seq, "state count:             %d\n"
--                 "active state:            T%d\n",
--                 pr->throttling.state_count, pr->throttling.state);
-+                 "active state:            T%d\n"
-+                 "state available: T%d to T%d\n",
-+                 pr->throttling.state_count, pr->throttling.state,
-+                 pr->throttling_platform_limit,
-+                 pr->throttling.state_count - 1);
-       seq_puts(seq, "states:\n");
-+      if (pr->throttling.acpi_processor_get_throttling ==
-+                      acpi_processor_get_throttling_fadt) {
-       for (i = 0; i < pr->throttling.state_count; i++)
-               seq_printf(seq, "   %cT%d:                  %02d%%\n",
-                          (i == pr->throttling.state ? '*' : ' '), i,
-                          (pr->throttling.states[i].performance ? pr->
-                           throttling.states[i].performance / 10 : 0));
-+      } else {
-+              for (i = 0; i < pr->throttling.state_count; i++)
-+                      seq_printf(seq, "   %cT%d:                  %02d%%\n",
-+                                 (i == pr->throttling.state ? '*' : ' '), i,
-+                                 (int)pr->throttling.states_tss[i].
-+                                 freqpercentage);
-+      }
-       end:
-       return 0;
-@@ -301,7 +682,7 @@
-                          PDE(inode)->data);
- }
--static ssize_t acpi_processor_write_throttling(struct file * file,
-+static ssize_t acpi_processor_write_throttling(struct file *file,
-                                              const char __user * buffer,
-                                              size_t count, loff_t * data)
- {
-@@ -310,7 +691,6 @@
-       struct acpi_processor *pr = m->private;
-       char state_string[12] = { '\0' };
--
-       if (!pr || (count > sizeof(state_string) - 1))
-               return -EINVAL;
-diff -Nurb linux-2.6.22-570/drivers/acpi/sbs.c linux-2.6.22-590/drivers/acpi/sbs.c
---- linux-2.6.22-570/drivers/acpi/sbs.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/acpi/sbs.c        2008-01-02 13:56:37.000000000 -0500
-@@ -127,7 +127,7 @@
- static struct acpi_driver acpi_sbs_driver = {
-       .name = "sbs",
-       .class = ACPI_SBS_CLASS,
--      .ids = ACPI_SBS_HID,
-+      .ids = "ACPI0001,ACPI0005",
-       .ops = {
-               .add = acpi_sbs_add,
-               .remove = acpi_sbs_remove,
-@@ -176,10 +176,8 @@
- };
- struct acpi_sbs {
--      acpi_handle handle;
-       int base;
-       struct acpi_device *device;
--      struct acpi_ec_smbus *smbus;
-       struct mutex mutex;
-       int sbsm_present;
-       int sbsm_batteries_supported;
-@@ -511,7 +509,7 @@
-                               "acpi_sbs_read_word() failed"));
-               goto end;
-       }
--
-+      sbs->sbsm_present = 1;
-       sbs->sbsm_batteries_supported = battery_system_info & 0x000f;
-       end:
-@@ -1630,13 +1628,12 @@
- {
-       struct acpi_sbs *sbs = NULL;
-       int result = 0, remove_result = 0;
--      unsigned long sbs_obj;
-       int id;
-       acpi_status status = AE_OK;
-       unsigned long val;
-       status =
--          acpi_evaluate_integer(device->parent->handle, "_EC", NULL, &val);
-+          acpi_evaluate_integer(device->handle, "_EC", NULL, &val);
-       if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Error obtaining _EC"));
-               return -EIO;
-@@ -1653,7 +1650,7 @@
-       sbs_mutex_lock(sbs);
--      sbs->base = (val & 0xff00ull) >> 8;
-+      sbs->base = 0xff & (val >> 8);
-       sbs->device = device;
-       strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
-@@ -1665,24 +1662,10 @@
-               ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed"));
-               goto end;
-       }
--      status = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj);
--      if (status) {
--              ACPI_EXCEPTION((AE_INFO, status,
--                              "acpi_evaluate_integer() failed"));
--              result = -EIO;
--              goto end;
--      }
--      if (sbs_obj > 0) {
--              result = acpi_sbsm_get_info(sbs);
--              if (result) {
--                      ACPI_EXCEPTION((AE_INFO, AE_ERROR,
--                                      "acpi_sbsm_get_info() failed"));
--                      goto end;
--              }
--              sbs->sbsm_present = 1;
--      }
--      if (sbs->sbsm_present == 0) {
-+      acpi_sbsm_get_info(sbs);
-+
-+      if (!sbs->sbsm_present) {
-               result = acpi_battery_add(sbs, 0);
-               if (result) {
-                       ACPI_EXCEPTION((AE_INFO, AE_ERROR,
-@@ -1702,8 +1685,6 @@
-               }
-       }
--      sbs->handle = device->handle;
--
-       init_timer(&sbs->update_timer);
-       result = acpi_check_update_proc(sbs);
-       if (result)
-diff -Nurb linux-2.6.22-570/drivers/acpi/system.c linux-2.6.22-590/drivers/acpi/system.c
---- linux-2.6.22-570/drivers/acpi/system.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/acpi/system.c     2008-01-02 13:56:37.000000000 -0500
-@@ -39,15 +39,12 @@
- #define ACPI_SYSTEM_CLASS             "system"
- #define ACPI_SYSTEM_DEVICE_NAME               "System"
--#define ACPI_SYSTEM_FILE_INFO         "info"
--#define ACPI_SYSTEM_FILE_EVENT                "event"
--#define ACPI_SYSTEM_FILE_DSDT         "dsdt"
--#define ACPI_SYSTEM_FILE_FADT         "fadt"
- /*
-  * Make ACPICA version work as module param
-  */
--static int param_get_acpica_version(char *buffer, struct kernel_param *kp) {
-+static int param_get_acpica_version(char *buffer, struct kernel_param *kp)
-+{
-       int result;
-       result = sprintf(buffer, "%x", ACPI_CA_VERSION);
-@@ -58,9 +55,126 @@
- module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
- /* --------------------------------------------------------------------------
-+                              FS Interface (/sys)
-+   -------------------------------------------------------------------------- */
-+static LIST_HEAD(acpi_table_attr_list);
-+static struct kobject tables_kobj;
-+
-+struct acpi_table_attr {
-+      struct bin_attribute attr;
-+      char name[8];
-+      int instance;
-+      struct list_head node;
-+};
-+
-+static ssize_t acpi_table_show(struct kobject *kobj,
-+                             struct bin_attribute *bin_attr, char *buf,
-+                             loff_t offset, size_t count)
-+{
-+      struct acpi_table_attr *table_attr =
-+          container_of(bin_attr, struct acpi_table_attr, attr);
-+      struct acpi_table_header *table_header = NULL;
-+      acpi_status status;
-+      ssize_t ret_count = count;
-+
-+      status =
-+          acpi_get_table(table_attr->name, table_attr->instance,
-+                         &table_header);
-+      if (ACPI_FAILURE(status))
-+              return -ENODEV;
-+
-+      if (offset >= table_header->length) {
-+              ret_count = 0;
-+              goto end;
-+      }
-+
-+      if (offset + ret_count > table_header->length)
-+              ret_count = table_header->length - offset;
-+
-+      memcpy(buf, ((char *)table_header) + offset, ret_count);
-+
-+      end:
-+      return ret_count;
-+}
-+
-+static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
-+                               struct acpi_table_header *table_header)
-+{
-+      struct acpi_table_header *header = NULL;
-+      struct acpi_table_attr *attr = NULL;
-+
-+      memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE);
-+
-+      list_for_each_entry(attr, &acpi_table_attr_list, node) {
-+              if (!memcmp(table_header->signature, attr->name,
-+                          ACPI_NAME_SIZE))
-+                      if (table_attr->instance < attr->instance)
-+                              table_attr->instance = attr->instance;
-+      }
-+      table_attr->instance++;
-+
-+      if (table_attr->instance > 1 || (table_attr->instance == 1 &&
-+                                       !acpi_get_table(table_header->
-+                                                       signature, 2,
-+                                                       &header)))
-+              sprintf(table_attr->name + 4, "%d", table_attr->instance);
-+
-+      table_attr->attr.size = 0;
-+      table_attr->attr.read = acpi_table_show;
-+      table_attr->attr.attr.name = table_attr->name;
-+      table_attr->attr.attr.mode = 0444;
-+      table_attr->attr.attr.owner = THIS_MODULE;
-+
-+      return;
-+}
-+
-+static int acpi_system_sysfs_init(void)
-+{
-+      struct acpi_table_attr *table_attr;
-+      struct acpi_table_header *table_header = NULL;
-+      int table_index = 0;
-+      int result;
-+
-+      tables_kobj.parent = &acpi_subsys.kobj;
-+      kobject_set_name(&tables_kobj, "tables");
-+      result = kobject_register(&tables_kobj);
-+      if (result)
-+              return result;
-+
-+      do {
-+              result = acpi_get_table_by_index(table_index, &table_header);
-+              if (!result) {
-+                      table_index++;
-+                      table_attr = NULL;
-+                      table_attr =
-+                          kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL);
-+                      if (!table_attr)
-+                              return -ENOMEM;
-+
-+                      acpi_table_attr_init(table_attr, table_header);
-+                      result =
-+                          sysfs_create_bin_file(&tables_kobj,
-+                                                &table_attr->attr);
-+                      if (result) {
-+                              kfree(table_attr);
-+                              return result;
-+                      } else
-+                              list_add_tail(&table_attr->node,
-+                                            &acpi_table_attr_list);
-+              }
-+      } while (!result);
-+
-+      return 0;
-+}
-+
-+/* --------------------------------------------------------------------------
-                               FS Interface (/proc)
-    -------------------------------------------------------------------------- */
- #ifdef CONFIG_ACPI_PROCFS
-+#define ACPI_SYSTEM_FILE_INFO         "info"
-+#define ACPI_SYSTEM_FILE_EVENT                "event"
-+#define ACPI_SYSTEM_FILE_DSDT         "dsdt"
-+#define ACPI_SYSTEM_FILE_FADT         "fadt"
- static int acpi_system_read_info(struct seq_file *seq, void *offset)
- {
-@@ -80,7 +194,6 @@
-       .llseek = seq_lseek,
-       .release = single_release,
- };
--#endif
- static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t,
-                                    loff_t *);
-@@ -97,13 +210,11 @@
-       struct acpi_table_header *dsdt = NULL;
-       ssize_t res;
--
-       status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
--      res = simple_read_from_buffer(buffer, count, ppos,
--                                    dsdt, dsdt->length);
-+      res = simple_read_from_buffer(buffer, count, ppos, dsdt, dsdt->length);
-       return res;
- }
-@@ -123,28 +234,21 @@
-       struct acpi_table_header *fadt = NULL;
-       ssize_t res;
--
-       status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
--      res = simple_read_from_buffer(buffer, count, ppos,
--                                    fadt, fadt->length);
-+      res = simple_read_from_buffer(buffer, count, ppos, fadt, fadt->length);
-       return res;
- }
--static int __init acpi_system_init(void)
-+static int acpi_system_procfs_init(void)
- {
-       struct proc_dir_entry *entry;
-       int error = 0;
-       char *name;
--
--      if (acpi_disabled)
--              return 0;
--
--#ifdef CONFIG_ACPI_PROCFS
-       /* 'info' [R] */
-       name = ACPI_SYSTEM_FILE_INFO;
-       entry = create_proc_entry(name, S_IRUGO, acpi_root_dir);
-@@ -153,7 +257,6 @@
-       else {
-               entry->proc_fops = &acpi_system_info_ops;
-       }
--#endif
-       /* 'dsdt' [R] */
-       name = ACPI_SYSTEM_FILE_DSDT;
-@@ -177,12 +280,32 @@
-       Error:
-       remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir);
-       remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir);
--#ifdef CONFIG_ACPI_PROCFS
-       remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir);
--#endif
-       error = -EFAULT;
-       goto Done;
- }
-+#else
-+static int acpi_system_procfs_init(void)
-+{
-+      return 0;
-+}
-+#endif
-+
-+static int __init acpi_system_init(void)
-+{
-+      int result = 0;
-+
-+      if (acpi_disabled)
-+              return 0;
-+
-+      result = acpi_system_procfs_init();
-+      if (result)
-+              return result;
-+
-+      result = acpi_system_sysfs_init();
-+
-+      return result;
-+}
- subsys_initcall(acpi_system_init);
-diff -Nurb linux-2.6.22-570/drivers/acpi/thermal.c linux-2.6.22-590/drivers/acpi/thermal.c
---- linux-2.6.22-570/drivers/acpi/thermal.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/acpi/thermal.c    2008-01-02 13:56:37.000000000 -0500
-@@ -40,6 +40,7 @@
- #include <linux/jiffies.h>
- #include <linux/kmod.h>
- #include <linux/seq_file.h>
-+#include <linux/reboot.h>
- #include <asm/uaccess.h>
- #include <acpi/acpi_bus.h>
-@@ -59,7 +60,6 @@
- #define ACPI_THERMAL_NOTIFY_CRITICAL  0xF0
- #define ACPI_THERMAL_NOTIFY_HOT               0xF1
- #define ACPI_THERMAL_MODE_ACTIVE      0x00
--#define ACPI_THERMAL_PATH_POWEROFF    "/sbin/poweroff"
- #define ACPI_THERMAL_MAX_ACTIVE       10
- #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
-@@ -419,26 +419,6 @@
-       return 0;
- }
--static int acpi_thermal_call_usermode(char *path)
--{
--      char *argv[2] = { NULL, NULL };
--      char *envp[3] = { NULL, NULL, NULL };
--
--
--      if (!path)
--              return -EINVAL;
--
--      argv[0] = path;
--
--      /* minimal command environment */
--      envp[0] = "HOME=/";
--      envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
--
--      call_usermodehelper(argv[0], argv, envp, 0);
--
--      return 0;
--}
--
- static int acpi_thermal_critical(struct acpi_thermal *tz)
- {
-       if (!tz || !tz->trips.critical.flags.valid)
-@@ -456,7 +436,7 @@
-       acpi_bus_generate_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,
-                               tz->trips.critical.flags.enabled);
--      acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF);
-+      orderly_poweroff(true);
-       return 0;
- }
-@@ -1114,7 +1094,6 @@
-               break;
-       case ACPI_THERMAL_NOTIFY_THRESHOLDS:
-               acpi_thermal_get_trip_points(tz);
--              acpi_thermal_check(tz);
-               acpi_bus_generate_event(device, event, 0);
-               break;
-       case ACPI_THERMAL_NOTIFY_DEVICES:
-diff -Nurb linux-2.6.22-570/drivers/acpi/utilities/uteval.c linux-2.6.22-590/drivers/acpi/utilities/uteval.c
---- linux-2.6.22-570/drivers/acpi/utilities/uteval.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/acpi/utilities/uteval.c   2008-01-02 13:56:37.000000000 -0500
-@@ -62,16 +62,13 @@
- static char *acpi_interfaces_supported[] = {
-       /* Operating System Vendor Strings */
--      "Windows 2000",
--      "Windows 2001",
--      "Windows 2001 SP0",
--      "Windows 2001 SP1",
--      "Windows 2001 SP2",
--      "Windows 2001 SP3",
--      "Windows 2001 SP4",
--      "Windows 2001.1",
--      "Windows 2001.1 SP1",   /* Added 03/2006 */
--      "Windows 2006",         /* Added 03/2006 */
-+      "Windows 2000",         /* Windows 2000 */
-+      "Windows 2001",         /* Windows XP */
-+      "Windows 2001 SP1",     /* Windows XP SP1 */
-+      "Windows 2001 SP2",     /* Windows XP SP2 */
-+      "Windows 2001.1",       /* Windows Server 2003 */
-+      "Windows 2001.1 SP1",   /* Windows Server 2003 SP1 - Added 03/2006 */
-+      "Windows 2006",         /* Windows Vista - Added 03/2006 */
-       /* Feature Group Strings */
-diff -Nurb linux-2.6.22-570/drivers/acpi/video.c linux-2.6.22-590/drivers/acpi/video.c
---- linux-2.6.22-570/drivers/acpi/video.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/acpi/video.c      2008-01-02 13:56:37.000000000 -0500
-@@ -33,6 +33,7 @@
- #include <linux/seq_file.h>
- #include <linux/backlight.h>
-+#include <linux/video_output.h>
- #include <asm/uaccess.h>
- #include <acpi/acpi_bus.h>
-@@ -169,6 +170,7 @@
-       struct acpi_device *dev;
-       struct acpi_video_device_brightness *brightness;
-       struct backlight_device *backlight;
-+      struct output_device *output_dev;
- };
- /* bus */
-@@ -272,6 +274,10 @@
-                                    u32 level_current, u32 event);
- static void acpi_video_switch_brightness(struct acpi_video_device *device,
-                                        int event);
-+static int acpi_video_device_get_state(struct acpi_video_device *device,
-+                          unsigned long *state);
-+static int acpi_video_output_get(struct output_device *od);
-+static int acpi_video_device_set_state(struct acpi_video_device *device, int state);
- /*backlight device sysfs support*/
- static int acpi_video_get_brightness(struct backlight_device *bd)
-@@ -297,6 +303,28 @@
-       .update_status  = acpi_video_set_brightness,
- };
-+/*video output device sysfs support*/
-+static int acpi_video_output_get(struct output_device *od)
-+{
-+      unsigned long state;
-+      struct acpi_video_device *vd =
-+              (struct acpi_video_device *)class_get_devdata(&od->class_dev);
-+      acpi_video_device_get_state(vd, &state);
-+      return (int)state;
-+}
-+
-+static int acpi_video_output_set(struct output_device *od)
-+{
-+      unsigned long state = od->request_state;
-+      struct acpi_video_device *vd=
-+              (struct acpi_video_device *)class_get_devdata(&od->class_dev);
-+      return acpi_video_device_set_state(vd, state);
-+}
-+
-+static struct output_properties acpi_output_properties = {
-+      .set_state = acpi_video_output_set,
-+      .get_status = acpi_video_output_get,
-+};
- /* --------------------------------------------------------------------------
-                                Video Management
-    -------------------------------------------------------------------------- */
-@@ -531,7 +559,6 @@
- static void acpi_video_device_find_cap(struct acpi_video_device *device)
- {
--      acpi_integer status;
-       acpi_handle h_dummy1;
-       int i;
-       u32 max_level = 0;
-@@ -565,9 +592,9 @@
-               device->cap._DSS = 1;
-       }
--      status = acpi_video_device_lcd_query_levels(device, &obj);
-+      if (ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
--      if (obj && obj->type == ACPI_TYPE_PACKAGE && obj->package.count >= 2) {
-+              if (obj->package.count >= 2) {
-               int count = 0;
-               union acpi_object *o;
-@@ -588,6 +615,7 @@
-                                       continue;
-                               }
-                               br->levels[count] = (u32) o->integer.value;
-+
-                               if (br->levels[count] > max_level)
-                                       max_level = br->levels[count];
-                               count++;
-@@ -606,9 +634,13 @@
-               }
-       }
-+      } else {
-+              ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available LCD brightness level\n"));
-+      }
-+
-       kfree(obj);
--      if (device->cap._BCL && device->cap._BCM && device->cap._BQC){
-+      if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
-               unsigned long tmp;
-               static int count = 0;
-               char *name;
-@@ -626,6 +658,17 @@
-               kfree(name);
-       }
-+      if (device->cap._DCS && device->cap._DSS){
-+              static int count = 0;
-+              char *name;
-+              name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
-+              if (!name)
-+                      return;
-+              sprintf(name, "acpi_video%d", count++);
-+              device->output_dev = video_output_register(name,
-+                              NULL, device, &acpi_output_properties);
-+              kfree(name);
-+      }
-       return;
- }
-@@ -1669,6 +1712,7 @@
-                                           ACPI_DEVICE_NOTIFY,
-                                           acpi_video_device_notify);
-       backlight_device_unregister(device->backlight);
-+      video_output_unregister(device->output_dev);
-       return 0;
- }
-diff -Nurb linux-2.6.22-570/drivers/atm/idt77252.c linux-2.6.22-590/drivers/atm/idt77252.c
---- linux-2.6.22-570/drivers/atm/idt77252.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/atm/idt77252.c    2008-01-02 13:56:37.000000000 -0500
-@@ -3576,7 +3576,7 @@
-        * XXX: <hack>
-        */
-       sprintf(tname, "eth%d", card->index);
--      tmp = dev_get_by_name(tname);   /* jhs: was "tmp = dev_get(tname);" */
-+      tmp = dev_get_by_name(&init_net, tname);        /* jhs: was "tmp = dev_get(tname);" */
-       if (tmp) {
-               memcpy(card->atmdev->esi, tmp->dev_addr, 6);
-diff -Nurb linux-2.6.22-570/drivers/base/bus.c linux-2.6.22-590/drivers/base/bus.c
---- linux-2.6.22-570/drivers/base/bus.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/base/bus.c        2008-01-02 13:56:37.000000000 -0500
-@@ -562,7 +562,6 @@
-       bus->drivers_probe_attr.attr.name = "drivers_probe";
-       bus->drivers_probe_attr.attr.mode = S_IWUSR;
--      bus->drivers_probe_attr.attr.owner = bus->owner;
-       bus->drivers_probe_attr.store = store_drivers_probe;
-       retval = bus_create_file(bus, &bus->drivers_probe_attr);
-       if (retval)
-@@ -570,7 +569,6 @@
-       bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe";
-       bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO;
--      bus->drivers_autoprobe_attr.attr.owner = bus->owner;
-       bus->drivers_autoprobe_attr.show = show_drivers_autoprobe;
-       bus->drivers_autoprobe_attr.store = store_drivers_autoprobe;
-       retval = bus_create_file(bus, &bus->drivers_autoprobe_attr);
-diff -Nurb linux-2.6.22-570/drivers/base/class.c linux-2.6.22-590/drivers/base/class.c
---- linux-2.6.22-570/drivers/base/class.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/base/class.c      2008-01-02 13:56:37.000000000 -0500
-@@ -134,6 +134,17 @@
-       }
- }
-+static int class_setup_shadowing(struct class *cls)
-+{
-+      const struct shadow_dir_operations *shadow_ops;
-+
-+      shadow_ops = cls->shadow_ops;
-+      if (!shadow_ops)
-+              return 0;
-+
-+      return sysfs_enable_shadowing(&cls->subsys.kobj, shadow_ops);
-+}
-+
- int class_register(struct class * cls)
- {
-       int error;
-@@ -152,11 +163,22 @@
-       subsys_set_kset(cls, class_subsys);
-       error = subsystem_register(&cls->subsys);
--      if (!error) {
--              error = add_class_attrs(class_get(cls));
--              class_put(cls);
--      }
-+      if (error)
-+              goto out;
-+
-+      error = class_setup_shadowing(cls);
-+      if (error)
-+              goto out_unregister;
-+
-+      error = add_class_attrs(cls);
-+      if (error)
-+              goto out_unregister;
-+
-+out:
-       return error;
-+out_unregister:
-+      subsystem_unregister(&cls->subsys);
-+      goto out;
- }
- void class_unregister(struct class * cls)
-@@ -312,9 +334,6 @@
-       pr_debug("device class '%s': release.\n", cd->class_id);
--      kfree(cd->devt_attr);
--      cd->devt_attr = NULL;
--
-       if (cd->release)
-               cd->release(cd);
-       else if (cls->release)
-@@ -547,6 +566,9 @@
-       return print_dev_t(buf, class_dev->devt);
- }
-+static struct class_device_attribute class_devt_attr =
-+      __ATTR(dev, S_IRUGO, show_dev, NULL);
-+
- static ssize_t store_uevent(struct class_device *class_dev,
-                           const char *buf, size_t count)
- {
-@@ -554,6 +576,9 @@
-       return count;
- }
-+static struct class_device_attribute class_uevent_attr =
-+      __ATTR(uevent, S_IWUSR, NULL, store_uevent);
-+
- void class_device_initialize(struct class_device *class_dev)
- {
-       kobj_set_kset_s(class_dev, class_obj_subsys);
-@@ -603,34 +628,17 @@
-                                 &parent_class->subsys.kobj, "subsystem");
-       if (error)
-               goto out3;
--      class_dev->uevent_attr.attr.name = "uevent";
--      class_dev->uevent_attr.attr.mode = S_IWUSR;
--      class_dev->uevent_attr.attr.owner = parent_class->owner;
--      class_dev->uevent_attr.store = store_uevent;
--      error = class_device_create_file(class_dev, &class_dev->uevent_attr);
-+
-+      error = class_device_create_file(class_dev, &class_uevent_attr);
-       if (error)
-               goto out3;
-       if (MAJOR(class_dev->devt)) {
--              struct class_device_attribute *attr;
--              attr = kzalloc(sizeof(*attr), GFP_KERNEL);
--              if (!attr) {
--                      error = -ENOMEM;
--                      goto out4;
--              }
--              attr->attr.name = "dev";
--              attr->attr.mode = S_IRUGO;
--              attr->attr.owner = parent_class->owner;
--              attr->show = show_dev;
--              error = class_device_create_file(class_dev, attr);
--              if (error) {
--                      kfree(attr);
-+              error = class_device_create_file(class_dev, &class_devt_attr);
-+              if (error)
-                       goto out4;
-               }
--              class_dev->devt_attr = attr;
--      }
--
-       error = class_device_add_attrs(class_dev);
-       if (error)
-               goto out5;
-@@ -671,10 +679,10 @@
-  out6:
-       class_device_remove_attrs(class_dev);
-  out5:
--      if (class_dev->devt_attr)
--              class_device_remove_file(class_dev, class_dev->devt_attr);
-+      if (MAJOR(class_dev->devt))
-+              class_device_remove_file(class_dev, &class_devt_attr);
-  out4:
--      class_device_remove_file(class_dev, &class_dev->uevent_attr);
-+      class_device_remove_file(class_dev, &class_uevent_attr);
-  out3:
-       kobject_del(&class_dev->kobj);
-  out2:
-@@ -774,9 +782,9 @@
-               sysfs_remove_link(&class_dev->kobj, "device");
-       }
-       sysfs_remove_link(&class_dev->kobj, "subsystem");
--      class_device_remove_file(class_dev, &class_dev->uevent_attr);
--      if (class_dev->devt_attr)
--              class_device_remove_file(class_dev, class_dev->devt_attr);
-+      class_device_remove_file(class_dev, &class_uevent_attr);
-+      if (MAJOR(class_dev->devt))
-+              class_device_remove_file(class_dev, &class_devt_attr);
-       class_device_remove_attrs(class_dev);
-       class_device_remove_groups(class_dev);
-diff -Nurb linux-2.6.22-570/drivers/base/core.c linux-2.6.22-590/drivers/base/core.c
---- linux-2.6.22-570/drivers/base/core.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/base/core.c       2008-01-02 13:56:37.000000000 -0500
-@@ -310,6 +310,9 @@
-       return count;
- }
-+static struct device_attribute uevent_attr =
-+      __ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);
-+
- static int device_add_attributes(struct device *dev,
-                                struct device_attribute *attrs)
- {
-@@ -423,6 +426,9 @@
-       return print_dev_t(buf, dev->devt);
- }
-+static struct device_attribute devt_attr =
-+      __ATTR(dev, S_IRUGO, show_dev, NULL);
-+
- /*
-  *    devices_subsys - structure to be registered with kobject core.
-  */
-@@ -616,8 +622,14 @@
-                       return kobj;
-               /* or create a new class-directory at the parent device */
--              return kobject_kset_add_dir(&dev->class->class_dirs,
-+              kobj = kobject_kset_add_dir(&dev->class->class_dirs,
-                                           parent_kobj, dev->class->name);
-+
-+              /* If we created a new class-directory setup shadowing */
-+              if (kobj && dev->class->shadow_ops)
-+                      sysfs_enable_shadowing(kobj, dev->class->shadow_ops);
-+
-+              return kobj;
-       }
-       if (parent)
-@@ -637,6 +649,82 @@
-       return 0;
- }
-+static int device_add_class_symlinks(struct device *dev)
-+{
-+      int error;
-+
-+      if (!dev->class)
-+              return 0;
-+      error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
-+                                "subsystem");
-+      if (error)
-+              goto out;
-+      /*
-+       * If this is not a "fake" compatible device, then create the
-+       * symlink from the class to the device.
-+       */
-+      if (dev->kobj.parent != &dev->class->subsys.kobj) {
-+      error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
-+                                dev->bus_id);
-+      if (error)
-+              goto out_subsys;
-+      }
-+      /* only bus-device parents get a "device"-link */
-+      if (dev->parent && dev->parent->bus) {
-+              error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
-+                                        "device");
-+              if (error)
-+                      goto out_busid;
-+#ifdef CONFIG_SYSFS_DEPRECATED
-+              {
-+                      char * class_name = make_class_name(dev->class->name,
-+                                                              &dev->kobj);
-+                      if (class_name)
-+                              error = sysfs_create_link(&dev->parent->kobj,
-+                                                      &dev->kobj, class_name);
-+                      kfree(class_name);
-+                      if (error)
-+                              goto out_device;
-+              }
-+#endif
-+      }
-+      return 0;
-+
-+#ifdef CONFIG_SYSFS_DEPRECATED
-+out_device:
-+      if (dev->parent)
-+              sysfs_remove_link(&dev->kobj, "device");
-+#endif
-+out_busid:
-+      if (dev->kobj.parent != &dev->class->subsys.kobj)
-+      sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
-+out_subsys:
-+      sysfs_remove_link(&dev->kobj, "subsystem");
-+out:
-+      return error;
-+}
-+
-+static void device_remove_class_symlinks(struct device *dev)
-+{
-+      if (!dev->class)
-+              return;
-+      if (dev->parent) {
-+#ifdef CONFIG_SYSFS_DEPRECATED
-+              char *class_name;
-+
-+              class_name = make_class_name(dev->class->name, &dev->kobj);
-+              if (class_name) {
-+                      sysfs_remove_link(&dev->parent->kobj, class_name);
-+                      kfree(class_name);
-+              }
-+#endif
-+              sysfs_remove_link(&dev->kobj, "device");
-+      }
-+      if (dev->kobj.parent != &dev->class->subsys.kobj)
-+      sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
-+      sysfs_remove_link(&dev->kobj, "subsystem");
-+}
-+
- /**
-  *    device_add - add device to device hierarchy.
-  *    @dev:   device.
-@@ -651,7 +739,6 @@
- int device_add(struct device *dev)
- {
-       struct device *parent = NULL;
--      char *class_name = NULL;
-       struct class_interface *class_intf;
-       int error = -EINVAL;
-@@ -681,58 +768,17 @@
-               blocking_notifier_call_chain(&dev->bus->bus_notifier,
-                                            BUS_NOTIFY_ADD_DEVICE, dev);
--      dev->uevent_attr.attr.name = "uevent";
--      dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR;
--      if (dev->driver)
--              dev->uevent_attr.attr.owner = dev->driver->owner;
--      dev->uevent_attr.store = store_uevent;
--      dev->uevent_attr.show = show_uevent;
--      error = device_create_file(dev, &dev->uevent_attr);
-+      error = device_create_file(dev, &uevent_attr);
-       if (error)
-               goto attrError;
-       if (MAJOR(dev->devt)) {
--              struct device_attribute *attr;
--              attr = kzalloc(sizeof(*attr), GFP_KERNEL);
--              if (!attr) {
--                      error = -ENOMEM;
--                      goto ueventattrError;
--              }
--              attr->attr.name = "dev";
--              attr->attr.mode = S_IRUGO;
--              if (dev->driver)
--                      attr->attr.owner = dev->driver->owner;
--              attr->show = show_dev;
--              error = device_create_file(dev, attr);
--              if (error) {
--                      kfree(attr);
-+              error = device_create_file(dev, &devt_attr);
-+              if (error)
-                       goto ueventattrError;
-               }
--
--              dev->devt_attr = attr;
--      }
--
--      if (dev->class) {
--              sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
--                                "subsystem");
--              /* If this is not a "fake" compatible device, then create the
--               * symlink from the class to the device. */
--              if (dev->kobj.parent != &dev->class->subsys.kobj)
--                      sysfs_create_link(&dev->class->subsys.kobj,
--                                        &dev->kobj, dev->bus_id);
--              if (parent) {
--                      sysfs_create_link(&dev->kobj, &dev->parent->kobj,
--                                                      "device");
--#ifdef CONFIG_SYSFS_DEPRECATED
--                      class_name = make_class_name(dev->class->name,
--                                                      &dev->kobj);
--                      if (class_name)
--                              sysfs_create_link(&dev->parent->kobj,
--                                                &dev->kobj, class_name);
--#endif
--              }
--      }
--
-+      if ((error = device_add_class_symlinks(dev)))
-+              goto SymlinkError;
-       if ((error = device_add_attrs(dev)))
-               goto AttrsError;
-       if ((error = device_pm_add(dev)))
-@@ -756,7 +802,6 @@
-               up(&dev->class->sem);
-       }
-  Done:
--      kfree(class_name);
-       put_device(dev);
-       return error;
-  BusError:
-@@ -767,10 +812,10 @@
-                                            BUS_NOTIFY_DEL_DEVICE, dev);
-       device_remove_attrs(dev);
-  AttrsError:
--      if (dev->devt_attr) {
--              device_remove_file(dev, dev->devt_attr);
--              kfree(dev->devt_attr);
--      }
-+      device_remove_class_symlinks(dev);
-+ SymlinkError:
-+      if (MAJOR(dev->devt))
-+              device_remove_file(dev, &devt_attr);
-       if (dev->class) {
-               sysfs_remove_link(&dev->kobj, "subsystem");
-@@ -792,7 +837,7 @@
-               }
-       }
-  ueventattrError:
--      device_remove_file(dev, &dev->uevent_attr);
-+      device_remove_file(dev, &uevent_attr);
-  attrError:
-       kobject_uevent(&dev->kobj, KOBJ_REMOVE);
-       kobject_del(&dev->kobj);
-@@ -869,17 +914,15 @@
-       if (parent)
-               klist_del(&dev->knode_parent);
--      if (dev->devt_attr) {
--              device_remove_file(dev, dev->devt_attr);
--              kfree(dev->devt_attr);
--      }
-+      if (MAJOR(dev->devt))
-+              device_remove_file(dev, &devt_attr);
-       if (dev->class) {
-               sysfs_remove_link(&dev->kobj, "subsystem");
-               /* If this is not a "fake" compatible device, remove the
-                * symlink from the class to the device. */
-               if (dev->kobj.parent != &dev->class->subsys.kobj)
--                      sysfs_remove_link(&dev->class->subsys.kobj,
--                                        dev->bus_id);
-+                      sysfs_delete_link(&dev->class->subsys.kobj,
-+                                        &dev->kobj, dev->bus_id);
-               if (parent) {
- #ifdef CONFIG_SYSFS_DEPRECATED
-                       char *class_name = make_class_name(dev->class->name,
-@@ -926,7 +969,7 @@
-                       up(&dev->class->sem);
-               }
-       }
--      device_remove_file(dev, &dev->uevent_attr);
-+      device_remove_file(dev, &uevent_attr);
-       device_remove_attrs(dev);
-       bus_remove_device(dev);
-@@ -1155,7 +1198,7 @@
- {
-       char *old_class_name = NULL;
-       char *new_class_name = NULL;
--      char *old_symlink_name = NULL;
-+      char *old_device_name = NULL;
-       int error;
-       dev = get_device(dev);
-@@ -1169,42 +1212,46 @@
-               old_class_name = make_class_name(dev->class->name, &dev->kobj);
- #endif
--      if (dev->class) {
--              old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
--              if (!old_symlink_name) {
-+      old_device_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
-+      if (!old_device_name) {
-                       error = -ENOMEM;
--                      goto out_free_old_class;
--              }
--              strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE);
-+              goto out;
-       }
--
-+      strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE);
-       strlcpy(dev->bus_id, new_name, BUS_ID_SIZE);
-+      if (dev->class && (dev->kobj.parent != &dev->class->subsys.kobj)) {
-+              error = sysfs_rename_link(&dev->class->subsys.kobj,
-+                      &dev->kobj, old_device_name, new_name);
-+              if (error)
-+                      goto out;
-+      }
-+
-       error = kobject_rename(&dev->kobj, new_name);
-+      if (error) {
-+              strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE);
-+              goto out;
-+      }
- #ifdef CONFIG_SYSFS_DEPRECATED
-       if (old_class_name) {
-+              error = -ENOMEM;
-               new_class_name = make_class_name(dev->class->name, &dev->kobj);
--              if (new_class_name) {
--                      sysfs_create_link(&dev->parent->kobj, &dev->kobj,
--                                        new_class_name);
--                      sysfs_remove_link(&dev->parent->kobj, old_class_name);
--              }
--      }
--#endif
-+              if (!new_class_name)
-+                      goto out;
--      if (dev->class) {
--              sysfs_remove_link(&dev->class->subsys.kobj,
--                                old_symlink_name);
--              sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
--                                dev->bus_id);
-+              error = sysfs_rename_link(&dev->parent->kobj, &dev->kobj,
-+                                        old_class_name, new_class_name);
-+                      if (error)
-+                              goto out;
-       }
-+#endif
-+out:
-       put_device(dev);
-       kfree(new_class_name);
--      kfree(old_symlink_name);
-- out_free_old_class:
-       kfree(old_class_name);
-+      kfree(old_device_name);
-       return error;
- }
-diff -Nurb linux-2.6.22-570/drivers/base/dd.c linux-2.6.22-590/drivers/base/dd.c
---- linux-2.6.22-570/drivers/base/dd.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/base/dd.c 2008-01-02 13:56:37.000000000 -0500
-@@ -296,9 +296,8 @@
- {
-       struct device_driver * drv;
--      drv = dev->driver;
-+      drv = get_driver(dev->driver);
-       if (drv) {
--              get_driver(drv);
-               driver_sysfs_remove(dev);
-               sysfs_remove_link(&dev->kobj, "driver");
-               klist_remove(&dev->knode_driver);
-diff -Nurb linux-2.6.22-570/drivers/base/firmware_class.c linux-2.6.22-590/drivers/base/firmware_class.c
---- linux-2.6.22-570/drivers/base/firmware_class.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/base/firmware_class.c     2008-01-02 13:56:37.000000000 -0500
-@@ -175,7 +175,7 @@
- static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
- static ssize_t
--firmware_data_read(struct kobject *kobj,
-+firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
-                  char *buffer, loff_t offset, size_t count)
- {
-       struct device *dev = to_dev(kobj);
-@@ -240,7 +240,7 @@
-  *    the driver as a firmware image.
-  **/
- static ssize_t
--firmware_data_write(struct kobject *kobj,
-+firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr,
-                   char *buffer, loff_t offset, size_t count)
- {
-       struct device *dev = to_dev(kobj);
-@@ -271,7 +271,7 @@
- }
- static struct bin_attribute firmware_attr_data_tmpl = {
--      .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
-+      .attr = {.name = "data", .mode = 0644},
-       .size = 0,
-       .read = firmware_data_read,
-       .write = firmware_data_write,
-diff -Nurb linux-2.6.22-570/drivers/block/acsi_slm.c linux-2.6.22-590/drivers/block/acsi_slm.c
---- linux-2.6.22-570/drivers/block/acsi_slm.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/block/acsi_slm.c  2008-01-02 13:56:37.000000000 -0500
-@@ -367,7 +367,7 @@
-       int length;
-       int end;
--      if (!(page = __get_free_page( GFP_KERNEL )))
-+      if (!(page = __get_free_page(GFP_TEMPORARY)))
-               return( -ENOMEM );
-       
-       length = slm_getstats( (char *)page, iminor(node) );
-diff -Nurb linux-2.6.22-570/drivers/block/aoe/aoecmd.c linux-2.6.22-590/drivers/block/aoe/aoecmd.c
---- linux-2.6.22-570/drivers/block/aoe/aoecmd.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/block/aoe/aoecmd.c        2008-01-02 13:56:37.000000000 -0500
-@@ -9,6 +9,7 @@
- #include <linux/skbuff.h>
- #include <linux/netdevice.h>
- #include <linux/genhd.h>
-+#include <net/net_namespace.h>
- #include <asm/unaligned.h>
- #include "aoe.h"
-@@ -194,7 +195,7 @@
-       sl = sl_tail = NULL;
-       read_lock(&dev_base_lock);
--      for_each_netdev(ifp) {
-+      for_each_netdev(&init_net, ifp) {
-               dev_hold(ifp);
-               if (!is_aoe_netif(ifp))
-                       goto cont;
-diff -Nurb linux-2.6.22-570/drivers/block/aoe/aoenet.c linux-2.6.22-590/drivers/block/aoe/aoenet.c
---- linux-2.6.22-570/drivers/block/aoe/aoenet.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/block/aoe/aoenet.c        2008-01-02 13:56:37.000000000 -0500
-@@ -8,6 +8,7 @@
- #include <linux/blkdev.h>
- #include <linux/netdevice.h>
- #include <linux/moduleparam.h>
-+#include <net/net_namespace.h>
- #include <asm/unaligned.h>
- #include "aoe.h"
-@@ -114,6 +115,9 @@
-       struct aoe_hdr *h;
-       u32 n;
-+      if (ifp->nd_net != &init_net)
-+              goto exit;
-+
-       skb = skb_share_check(skb, GFP_ATOMIC);
-       if (skb == NULL)
-               return 0;
-diff -Nurb linux-2.6.22-570/drivers/block/cciss_scsi.c linux-2.6.22-590/drivers/block/cciss_scsi.c
---- linux-2.6.22-570/drivers/block/cciss_scsi.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/block/cciss_scsi.c        2008-01-02 13:56:37.000000000 -0500
-@@ -555,7 +555,6 @@
- {
-       struct scsi_cmnd *cmd;
-       ctlr_info_t *ctlr;
--      u64bit addr64;
-       ErrorInfo_struct *ei;
-       ei = cp->err_info;
-@@ -569,20 +568,7 @@
-       cmd = (struct scsi_cmnd *) cp->scsi_cmd;        
-       ctlr = hba[cp->ctlr];
--      /* undo the DMA mappings */
--
--      if (cmd->use_sg) {
--              pci_unmap_sg(ctlr->pdev,
--                      cmd->request_buffer, cmd->use_sg,
--                              cmd->sc_data_direction); 
--      }
--      else if (cmd->request_bufflen) {
--              addr64.val32.lower = cp->SG[0].Addr.lower;
--                addr64.val32.upper = cp->SG[0].Addr.upper;
--                pci_unmap_single(ctlr->pdev, (dma_addr_t) addr64.val,
--                      cmd->request_bufflen, 
--                              cmd->sc_data_direction);
--      }
-+      scsi_dma_unmap(cmd);
-       cmd->result = (DID_OK << 16);           /* host byte */
-       cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */
-@@ -597,7 +583,7 @@
-               ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
-                       SCSI_SENSE_BUFFERSIZE : 
-                       ei->SenseLen);
--      cmd->resid = ei->ResidualCnt;
-+      scsi_set_resid(cmd, ei->ResidualCnt);
-       if(ei->CommandStatus != 0) 
-       { /* an error has occurred */ 
-@@ -1204,46 +1190,29 @@
-               CommandList_struct *cp, 
-               struct scsi_cmnd *cmd)
- {
--      unsigned int use_sg, nsegs=0, len;
--      struct scatterlist *scatter = (struct scatterlist *) cmd->request_buffer;
-+      unsigned int len;
-+      struct scatterlist *sg;
-       __u64 addr64;
-+      int use_sg, i;
--      /* is it just one virtual address? */   
--      if (!cmd->use_sg) {
--              if (cmd->request_bufflen) {     /* anything to xfer? */
--
--                      addr64 = (__u64) pci_map_single(pdev, 
--                              cmd->request_buffer, 
--                              cmd->request_bufflen, 
--                              cmd->sc_data_direction); 
-+      BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES);
-       
--                      cp->SG[0].Addr.lower = 
-+      use_sg = scsi_dma_map(cmd);
-+      if (use_sg) {   /* not too many addrs? */
-+              scsi_for_each_sg(cmd, sg, use_sg, i) {
-+                      addr64 = (__u64) sg_dma_address(sg);
-+                      len  = sg_dma_len(sg);
-+                      cp->SG[i].Addr.lower =
-                         (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
--                      cp->SG[0].Addr.upper =
-+                      cp->SG[i].Addr.upper =
-                         (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
--                      cp->SG[0].Len = cmd->request_bufflen;
--                      nsegs=1;
-+                      cp->SG[i].Len = len;
-+                      cp->SG[i].Ext = 0;  // we are not chaining
-               }
--      } /* else, must be a list of virtual addresses.... */
--      else if (cmd->use_sg <= MAXSGENTRIES) { /* not too many addrs? */
--
--              use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg,
--                      cmd->sc_data_direction);
--
--              for (nsegs=0; nsegs < use_sg; nsegs++) {
--                      addr64 = (__u64) sg_dma_address(&scatter[nsegs]);
--                      len  = sg_dma_len(&scatter[nsegs]);
--                      cp->SG[nsegs].Addr.lower =
--                        (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
--                      cp->SG[nsegs].Addr.upper =
--                        (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
--                      cp->SG[nsegs].Len = len;
--                      cp->SG[nsegs].Ext = 0;  // we are not chaining
-               }
--      } else BUG();
--      cp->Header.SGList = (__u8) nsegs;   /* no. SGs contig in this cmd */
--      cp->Header.SGTotal = (__u16) nsegs; /* total sgs in this cmd list */
-+      cp->Header.SGList = (__u8) use_sg;   /* no. SGs contig in this cmd */
-+      cp->Header.SGTotal = (__u16) use_sg; /* total sgs in this cmd list */
-       return;
- }
-diff -Nurb linux-2.6.22-570/drivers/block/loop.c linux-2.6.22-590/drivers/block/loop.c
---- linux-2.6.22-570/drivers/block/loop.c      2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/drivers/block/loop.c      2008-01-02 13:56:37.000000000 -0500
-@@ -68,6 +68,7 @@
- #include <linux/loop.h>
- #include <linux/compat.h>
- #include <linux/suspend.h>
-+#include <linux/freezer.h>
- #include <linux/writeback.h>
- #include <linux/buffer_head.h>                /* for invalidate_bdev() */
- #include <linux/completion.h>
-@@ -577,13 +578,6 @@
-       struct loop_device *lo = data;
-       struct bio *bio;
--      /*
--       * loop can be used in an encrypted device,
--       * hence, it mustn't be stopped at all
--       * because it could be indirectly used during suspension
--       */
--      current->flags |= PF_NOFREEZE;
--
-       set_user_nice(current, -20);
-       while (!kthread_should_stop() || lo->lo_bio) {
-diff -Nurb linux-2.6.22-570/drivers/block/pktcdvd.c linux-2.6.22-590/drivers/block/pktcdvd.c
---- linux-2.6.22-570/drivers/block/pktcdvd.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/block/pktcdvd.c   2008-01-02 13:56:37.000000000 -0500
-@@ -146,8 +146,7 @@
-  **********************************************************/
- #define DEF_ATTR(_obj,_name,_mode) \
--      static struct attribute _obj = { \
--              .name = _name, .owner = THIS_MODULE, .mode = _mode }
-+      static struct attribute _obj = { .name = _name, .mode = _mode }
- /**********************************************************
-   /sys/class/pktcdvd/pktcdvd[0-7]/
-@@ -1594,6 +1593,7 @@
-       long min_sleep_time, residue;
-       set_user_nice(current, -20);
-+      set_freezable();
-       for (;;) {
-               DECLARE_WAITQUEUE(wait, current);
-diff -Nurb linux-2.6.22-570/drivers/char/apm-emulation.c linux-2.6.22-590/drivers/char/apm-emulation.c
---- linux-2.6.22-570/drivers/char/apm-emulation.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/char/apm-emulation.c      2008-01-02 13:56:37.000000000 -0500
-@@ -20,6 +20,7 @@
- #include <linux/sched.h>
- #include <linux/pm.h>
- #include <linux/apm-emulation.h>
-+#include <linux/freezer.h>
- #include <linux/device.h>
- #include <linux/kernel.h>
- #include <linux/list.h>
-@@ -329,13 +330,8 @@
-                       /*
-                        * Wait for the suspend/resume to complete.  If there
-                        * are pending acknowledges, we wait here for them.
--                       *
--                       * Note: we need to ensure that the PM subsystem does
--                       * not kick us out of the wait when it suspends the
--                       * threads.
-                        */
-                       flags = current->flags;
--                      current->flags |= PF_NOFREEZE;
-                       wait_event(apm_suspend_waitqueue,
-                                  as->suspend_state == SUSPEND_DONE);
-@@ -365,13 +361,8 @@
-                       /*
-                        * Wait for the suspend/resume to complete.  If there
-                        * are pending acknowledges, we wait here for them.
--                       *
--                       * Note: we need to ensure that the PM subsystem does
--                       * not kick us out of the wait when it suspends the
--                       * threads.
-                        */
-                       flags = current->flags;
--                      current->flags |= PF_NOFREEZE;
-                       wait_event_interruptible(apm_suspend_waitqueue,
-                                        as->suspend_state == SUSPEND_DONE);
-@@ -598,7 +589,6 @@
-               kapmd_tsk = NULL;
-               return ret;
-       }
--      kapmd_tsk->flags |= PF_NOFREEZE;
-       wake_up_process(kapmd_tsk);
- #ifdef CONFIG_PROC_FS
-diff -Nurb linux-2.6.22-570/drivers/char/hvc_console.c linux-2.6.22-590/drivers/char/hvc_console.c
---- linux-2.6.22-570/drivers/char/hvc_console.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/char/hvc_console.c        2008-01-02 13:56:37.000000000 -0500
-@@ -674,11 +674,12 @@
-  * calling hvc_poll() who determines whether a console adapter support
-  * interrupts.
-  */
--int khvcd(void *unused)
-+static int khvcd(void *unused)
- {
-       int poll_mask;
-       struct hvc_struct *hp;
-+      set_freezable();
-       __set_current_state(TASK_RUNNING);
-       do {
-               poll_mask = 0;
-diff -Nurb linux-2.6.22-570/drivers/char/ipmi/ipmi_msghandler.c linux-2.6.22-590/drivers/char/ipmi/ipmi_msghandler.c
---- linux-2.6.22-570/drivers/char/ipmi/ipmi_msghandler.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/char/ipmi/ipmi_msghandler.c       2008-01-02 13:56:37.000000000 -0500
-@@ -2171,52 +2171,42 @@
-       int err;
-       bmc->device_id_attr.attr.name = "device_id";
--      bmc->device_id_attr.attr.owner = THIS_MODULE;
-       bmc->device_id_attr.attr.mode = S_IRUGO;
-       bmc->device_id_attr.show = device_id_show;
-       bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs";
--      bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE;
-       bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO;
-       bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show;
-       bmc->revision_attr.attr.name = "revision";
--      bmc->revision_attr.attr.owner = THIS_MODULE;
-       bmc->revision_attr.attr.mode = S_IRUGO;
-       bmc->revision_attr.show = revision_show;
-       bmc->firmware_rev_attr.attr.name = "firmware_revision";
--      bmc->firmware_rev_attr.attr.owner = THIS_MODULE;
-       bmc->firmware_rev_attr.attr.mode = S_IRUGO;
-       bmc->firmware_rev_attr.show = firmware_rev_show;
-       bmc->version_attr.attr.name = "ipmi_version";
--      bmc->version_attr.attr.owner = THIS_MODULE;
-       bmc->version_attr.attr.mode = S_IRUGO;
-       bmc->version_attr.show = ipmi_version_show;
-       bmc->add_dev_support_attr.attr.name = "additional_device_support";
--      bmc->add_dev_support_attr.attr.owner = THIS_MODULE;
-       bmc->add_dev_support_attr.attr.mode = S_IRUGO;
-       bmc->add_dev_support_attr.show = add_dev_support_show;
-       bmc->manufacturer_id_attr.attr.name = "manufacturer_id";
--      bmc->manufacturer_id_attr.attr.owner = THIS_MODULE;
-       bmc->manufacturer_id_attr.attr.mode = S_IRUGO;
-       bmc->manufacturer_id_attr.show = manufacturer_id_show;
-       bmc->product_id_attr.attr.name = "product_id";
--      bmc->product_id_attr.attr.owner = THIS_MODULE;
-       bmc->product_id_attr.attr.mode = S_IRUGO;
-       bmc->product_id_attr.show = product_id_show;
-       bmc->guid_attr.attr.name = "guid";
--      bmc->guid_attr.attr.owner = THIS_MODULE;
-       bmc->guid_attr.attr.mode = S_IRUGO;
-       bmc->guid_attr.show = guid_show;
-       bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision";
--      bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE;
-       bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO;
-       bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show;
-diff -Nurb linux-2.6.22-570/drivers/char/keyboard.c linux-2.6.22-590/drivers/char/keyboard.c
---- linux-2.6.22-570/drivers/char/keyboard.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/char/keyboard.c   2008-01-02 13:56:37.000000000 -0500
-@@ -1150,6 +1150,7 @@
-               sysrq_down = 0;
-       if (sysrq_down && down && !rep) {
-               handle_sysrq(kbd_sysrq_xlate[keycode], tty);
-+              sysrq_down = 0;         /* In case we miss the 'up' event. */
-               return;
-       }
- #endif
-diff -Nurb linux-2.6.22-570/drivers/connector/connector.c linux-2.6.22-590/drivers/connector/connector.c
---- linux-2.6.22-570/drivers/connector/connector.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/connector/connector.c     2008-01-02 13:56:37.000000000 -0500
-@@ -446,7 +446,7 @@
-       dev->id.idx = cn_idx;
-       dev->id.val = cn_val;
--      dev->nls = netlink_kernel_create(NETLINK_CONNECTOR,
-+      dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR,
-                                        CN_NETLINK_USERS + 0xf,
-                                        dev->input, NULL, THIS_MODULE);
-       if (!dev->nls)
-diff -Nurb linux-2.6.22-570/drivers/cpufreq/cpufreq_stats.c linux-2.6.22-590/drivers/cpufreq/cpufreq_stats.c
---- linux-2.6.22-570/drivers/cpufreq/cpufreq_stats.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/cpufreq/cpufreq_stats.c   2008-01-02 13:56:37.000000000 -0500
-@@ -25,8 +25,7 @@
- #define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \
- static struct freq_attr _attr_##_name = {\
--      .attr = {.name = __stringify(_name), .owner = THIS_MODULE, \
--              .mode = _mode, }, \
-+      .attr = {.name = __stringify(_name), .mode = _mode, }, \
-       .show = _show,\
- };
-diff -Nurb linux-2.6.22-570/drivers/cpufreq/cpufreq_userspace.c linux-2.6.22-590/drivers/cpufreq/cpufreq_userspace.c
---- linux-2.6.22-570/drivers/cpufreq/cpufreq_userspace.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/cpufreq/cpufreq_userspace.c       2008-01-02 13:56:37.000000000 -0500
-@@ -120,7 +120,7 @@
- static struct freq_attr freq_attr_scaling_setspeed =
- {
--      .attr = { .name = "scaling_setspeed", .mode = 0644, .owner = THIS_MODULE },
-+      .attr = { .name = "scaling_setspeed", .mode = 0644 },
-       .show = show_speed,
-       .store = store_speed,
- };
-diff -Nurb linux-2.6.22-570/drivers/cpufreq/freq_table.c linux-2.6.22-590/drivers/cpufreq/freq_table.c
---- linux-2.6.22-570/drivers/cpufreq/freq_table.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/cpufreq/freq_table.c      2008-01-02 13:56:37.000000000 -0500
-@@ -199,7 +199,6 @@
- struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
-       .attr = { .name = "scaling_available_frequencies",
-                 .mode = 0444,
--                .owner=THIS_MODULE
-               },
-       .show = show_available_freqs,
- };
-diff -Nurb linux-2.6.22-570/drivers/cpuidle/Kconfig linux-2.6.22-590/drivers/cpuidle/Kconfig
---- linux-2.6.22-570/drivers/cpuidle/Kconfig   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/cpuidle/Kconfig   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,39 @@
-+menu "CPU idle PM support"
-+
-+config CPU_IDLE
-+      bool "CPU idle PM support"
-+      help
-+        CPU idle is a generic framework for supporting software-controlled
-+        idle processor power management.  It includes modular cross-platform
-+        governors that can be swapped during runtime.
-+
-+        If you're using a mobile platform that supports CPU idle PM (e.g.
-+        an ACPI-capable notebook), you should say Y here.
-+
-+if CPU_IDLE
-+
-+comment "Governors"
-+
-+config CPU_IDLE_GOV_LADDER
-+      tristate "'ladder' governor"
-+      depends on CPU_IDLE
-+      default y
-+      help
-+        This cpuidle governor promotes and demotes through the supported idle
-+        states using residency time and bus master activity as metrics.  This
-+        algorithm was originally introduced in the old ACPI processor driver.
-+
-+config CPU_IDLE_GOV_MENU
-+      tristate "'menu' governor"
-+      depends on CPU_IDLE && NO_HZ
-+      default y
-+      help
-+        This cpuidle governor evaluates all available states and chooses the
-+        deepest state that meets all of the following constraints: BM activity,
-+        expected time until next timer interrupt, and last break event time
-+        delta.  It is designed to minimize power consumption.  Currently
-+        dynticks is required.
-+
-+endif # CPU_IDLE
-+
-+endmenu
-diff -Nurb linux-2.6.22-570/drivers/cpuidle/Makefile linux-2.6.22-590/drivers/cpuidle/Makefile
---- linux-2.6.22-570/drivers/cpuidle/Makefile  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/cpuidle/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,5 @@
-+#
-+# Makefile for cpuidle.
-+#
-+
-+obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
-diff -Nurb linux-2.6.22-570/drivers/cpuidle/cpuidle.c linux-2.6.22-590/drivers/cpuidle/cpuidle.c
---- linux-2.6.22-570/drivers/cpuidle/cpuidle.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/cpuidle/cpuidle.c 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,306 @@
-+/*
-+ * cpuidle.c - core cpuidle infrastructure
-+ *
-+ * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
-+ *               Shaohua Li <shaohua.li@intel.com>
-+ *               Adam Belay <abelay@novell.com>
-+ *
-+ * This code is licenced under the GPL.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/mutex.h>
-+#include <linux/sched.h>
-+#include <linux/notifier.h>
-+#include <linux/cpu.h>
-+#include <linux/latency.h>
-+#include <linux/cpuidle.h>
-+
-+#include "cpuidle.h"
-+
-+DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
-+EXPORT_PER_CPU_SYMBOL_GPL(cpuidle_devices);
-+
-+DEFINE_MUTEX(cpuidle_lock);
-+LIST_HEAD(cpuidle_detected_devices);
-+static void (*pm_idle_old)(void);
-+
-+/**
-+ * cpuidle_idle_call - the main idle loop
-+ *
-+ * NOTE: no locks or semaphores should be used here
-+ */
-+static void cpuidle_idle_call(void)
-+{
-+      struct cpuidle_device *dev = __get_cpu_var(cpuidle_devices);
-+      struct cpuidle_state *target_state;
-+      int next_state;
-+
-+      /* check if the device is ready */
-+      if (!dev || dev->status != CPUIDLE_STATUS_DOIDLE) {
-+              if (pm_idle_old)
-+                      pm_idle_old();
-+              else
-+                      local_irq_enable();
-+              return;
-+      }
-+
-+      /* ask the governor for the next state */
-+      next_state = cpuidle_curr_governor->select(dev);
-+      if (need_resched())
-+              return;
-+      target_state = &dev->states[next_state];
-+
-+      /* enter the state and update stats */
-+      dev->last_residency = target_state->enter(dev, target_state);
-+      dev->last_state = target_state;
-+      target_state->time += dev->last_residency;
-+      target_state->usage++;
-+
-+      /* give the governor an opportunity to reflect on the outcome */
-+      if (cpuidle_curr_governor->reflect)
-+              cpuidle_curr_governor->reflect(dev);
-+}
-+
-+/**
-+ * cpuidle_install_idle_handler - installs the cpuidle idle loop handler
-+ */
-+void cpuidle_install_idle_handler(void)
-+{
-+      if (pm_idle != cpuidle_idle_call) {
-+              /* Make sure all changes finished before we switch to new idle */
-+              smp_wmb();
-+              pm_idle = cpuidle_idle_call;
-+      }
-+}
-+
-+/**
-+ * cpuidle_uninstall_idle_handler - uninstalls the cpuidle idle loop handler
-+ */
-+void cpuidle_uninstall_idle_handler(void)
-+{
-+      if (pm_idle != pm_idle_old) {
-+              pm_idle = pm_idle_old;
-+              cpu_idle_wait();
-+      }
-+}
-+
-+/**
-+ * cpuidle_rescan_device - prepares for a new state configuration
-+ * @dev: the target device
-+ *
-+ * Must be called with cpuidle_lock aquired.
-+ */
-+void cpuidle_rescan_device(struct cpuidle_device *dev)
-+{
-+      int i;
-+
-+      if (cpuidle_curr_governor->scan)
-+              cpuidle_curr_governor->scan(dev);
-+
-+      for (i = 0; i < dev->state_count; i++) {
-+              dev->states[i].usage = 0;
-+              dev->states[i].time = 0;
-+      }
-+}
-+
-+/**
-+ * cpuidle_add_device - attaches the driver to a CPU instance
-+ * @sys_dev: the system device (driver model CPU representation)
-+ */
-+static int cpuidle_add_device(struct sys_device *sys_dev)
-+{
-+      int cpu = sys_dev->id;
-+      struct cpuidle_device *dev;
-+
-+      dev = per_cpu(cpuidle_devices, cpu);
-+
-+      mutex_lock(&cpuidle_lock);
-+      if (cpu_is_offline(cpu)) {
-+              mutex_unlock(&cpuidle_lock);
-+              return 0;
-+      }
-+
-+      if (!dev) {
-+              dev = kzalloc(sizeof(struct cpuidle_device), GFP_KERNEL);
-+              if (!dev) {
-+                      mutex_unlock(&cpuidle_lock);
-+                      return -ENOMEM;
-+              }
-+              init_completion(&dev->kobj_unregister);
-+              per_cpu(cpuidle_devices, cpu) = dev;
-+      }
-+      dev->cpu = cpu;
-+
-+      if (dev->status & CPUIDLE_STATUS_DETECTED) {
-+              mutex_unlock(&cpuidle_lock);
-+              return 0;
-+      }
-+
-+      cpuidle_add_sysfs(sys_dev);
-+
-+      if (cpuidle_curr_driver) {
-+              if (cpuidle_attach_driver(dev))
-+                      goto err_ret;
-+      }
-+
-+      if (cpuidle_curr_governor) {
-+              if (cpuidle_attach_governor(dev)) {
-+                      cpuidle_detach_driver(dev);
-+                      goto err_ret;
-+              }
-+      }
-+
-+      if (cpuidle_device_can_idle(dev))
-+              cpuidle_install_idle_handler();
-+
-+      list_add(&dev->device_list, &cpuidle_detected_devices);
-+      dev->status |= CPUIDLE_STATUS_DETECTED;
-+
-+err_ret:
-+      mutex_unlock(&cpuidle_lock);
-+
-+      return 0;
-+}
-+
-+/**
-+ * __cpuidle_remove_device - detaches the driver from a CPU instance
-+ * @sys_dev: the system device (driver model CPU representation)
-+ *
-+ * Must be called with cpuidle_lock aquired.
-+ */
-+static int __cpuidle_remove_device(struct sys_device *sys_dev)
-+{
-+      struct cpuidle_device *dev;
-+
-+      dev = per_cpu(cpuidle_devices, sys_dev->id);
-+
-+      if (!(dev->status & CPUIDLE_STATUS_DETECTED)) {
-+              return 0;
-+      }
-+      dev->status &= ~CPUIDLE_STATUS_DETECTED;
-+      /* NOTE: we don't wait because the cpu is already offline */
-+      if (cpuidle_curr_governor)
-+              cpuidle_detach_governor(dev);
-+      if (cpuidle_curr_driver)
-+              cpuidle_detach_driver(dev);
-+      cpuidle_remove_sysfs(sys_dev);
-+      list_del(&dev->device_list);
-+      wait_for_completion(&dev->kobj_unregister);
-+      per_cpu(cpuidle_devices, sys_dev->id) = NULL;
-+      kfree(dev);
-+
-+      return 0;
-+}
-+
-+/**
-+ * cpuidle_remove_device - detaches the driver from a CPU instance
-+ * @sys_dev: the system device (driver model CPU representation)
-+ */
-+static int cpuidle_remove_device(struct sys_device *sys_dev)
-+{
-+      int ret;
-+      mutex_lock(&cpuidle_lock);
-+      ret = __cpuidle_remove_device(sys_dev);
-+      mutex_unlock(&cpuidle_lock);
-+
-+      return ret;
-+}
-+
-+static struct sysdev_driver cpuidle_sysdev_driver = {
-+      .add            = cpuidle_add_device,
-+      .remove         = cpuidle_remove_device,
-+};
-+
-+static int cpuidle_cpu_callback(struct notifier_block *nfb,
-+                                      unsigned long action, void *hcpu)
-+{
-+      struct sys_device *sys_dev;
-+
-+      sys_dev = get_cpu_sysdev((unsigned long)hcpu);
-+
-+      switch (action) {
-+      case CPU_ONLINE:
-+              cpuidle_add_device(sys_dev);
-+              break;
-+      case CPU_DOWN_PREPARE:
-+              mutex_lock(&cpuidle_lock);
-+              break;
-+      case CPU_DEAD:
-+              __cpuidle_remove_device(sys_dev);
-+              mutex_unlock(&cpuidle_lock);
-+              break;
-+      case CPU_DOWN_FAILED:
-+              mutex_unlock(&cpuidle_lock);
-+              break;
-+      }
-+
-+      return NOTIFY_OK;
-+}
-+
-+static struct notifier_block __cpuinitdata cpuidle_cpu_notifier =
-+{
-+    .notifier_call = cpuidle_cpu_callback,
-+};
-+
-+#ifdef CONFIG_SMP
-+
-+static void smp_callback(void *v)
-+{
-+      /* we already woke the CPU up, nothing more to do */
-+}
-+
-+/*
-+ * This function gets called when a part of the kernel has a new latency
-+ * requirement.  This means we need to get all processors out of their C-state,
-+ * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that
-+ * wakes them all right up.
-+ */
-+static int cpuidle_latency_notify(struct notifier_block *b,
-+              unsigned long l, void *v)
-+{
-+      smp_call_function(smp_callback, NULL, 0, 1);
-+      return NOTIFY_OK;
-+}
-+
-+static struct notifier_block cpuidle_latency_notifier = {
-+      .notifier_call = cpuidle_latency_notify,
-+};
-+
-+#define latency_notifier_init(x) do { register_latency_notifier(x); } while (0)
-+
-+#else /* CONFIG_SMP */
-+
-+#define latency_notifier_init(x) do { } while (0)
-+
-+#endif /* CONFIG_SMP */
-+
-+/**
-+ * cpuidle_init - core initializer
-+ */
-+static int __init cpuidle_init(void)
-+{
-+      int ret;
-+
-+      pm_idle_old = pm_idle;
-+
-+      ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);
-+      if (ret)
-+              return ret;
-+
-+      register_hotcpu_notifier(&cpuidle_cpu_notifier);
-+
-+      ret = sysdev_driver_register(&cpu_sysdev_class, &cpuidle_sysdev_driver);
-+
-+      if (ret) {
-+              cpuidle_remove_class_sysfs(&cpu_sysdev_class);
-+              printk(KERN_ERR "cpuidle: failed to initialize\n");
-+              return ret;
-+      }
-+
-+      latency_notifier_init(&cpuidle_latency_notifier);
-+
-+      return 0;
-+}
-+
-+core_initcall(cpuidle_init);
-diff -Nurb linux-2.6.22-570/drivers/cpuidle/cpuidle.h linux-2.6.22-590/drivers/cpuidle/cpuidle.h
---- linux-2.6.22-570/drivers/cpuidle/cpuidle.h 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/cpuidle/cpuidle.h 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,50 @@
-+/*
-+ * cpuidle.h - The internal header file
-+ */
-+
-+#ifndef __DRIVER_CPUIDLE_H
-+#define __DRIVER_CPUIDLE_H
-+
-+#include <linux/sysdev.h>
-+
-+/* For internal use only */
-+extern struct cpuidle_governor *cpuidle_curr_governor;
-+extern struct cpuidle_driver *cpuidle_curr_driver;
-+extern struct list_head cpuidle_drivers;
-+extern struct list_head cpuidle_governors;
-+extern struct list_head cpuidle_detected_devices;
-+extern struct mutex cpuidle_lock;
-+
-+/* idle loop */
-+extern void cpuidle_install_idle_handler(void);
-+extern void cpuidle_uninstall_idle_handler(void);
-+extern void cpuidle_rescan_device(struct cpuidle_device *dev);
-+
-+/* drivers */
-+extern int cpuidle_attach_driver(struct cpuidle_device *dev);
-+extern void cpuidle_detach_driver(struct cpuidle_device *dev);
-+extern int cpuidle_switch_driver(struct cpuidle_driver *drv);
-+
-+/* governors */
-+extern int cpuidle_attach_governor(struct cpuidle_device *dev);
-+extern void cpuidle_detach_governor(struct cpuidle_device *dev);
-+extern int cpuidle_switch_governor(struct cpuidle_governor *gov);
-+
-+/* sysfs */
-+extern int cpuidle_add_class_sysfs(struct sysdev_class *cls);
-+extern void cpuidle_remove_class_sysfs(struct sysdev_class *cls);
-+extern int cpuidle_add_driver_sysfs(struct cpuidle_device *device);
-+extern void cpuidle_remove_driver_sysfs(struct cpuidle_device *device);
-+extern int cpuidle_add_sysfs(struct sys_device *sysdev);
-+extern void cpuidle_remove_sysfs(struct sys_device *sysdev);
-+
-+/**
-+ * cpuidle_device_can_idle - determines if a CPU can utilize the idle loop
-+ * @dev: the target CPU
-+ */
-+static inline int cpuidle_device_can_idle(struct cpuidle_device *dev)
-+{
-+      return (dev->status == CPUIDLE_STATUS_DOIDLE);
-+}
-+
-+#endif /* __DRIVER_CPUIDLE_H */
-diff -Nurb linux-2.6.22-570/drivers/cpuidle/driver.c linux-2.6.22-590/drivers/cpuidle/driver.c
---- linux-2.6.22-570/drivers/cpuidle/driver.c  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/cpuidle/driver.c  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,276 @@
-+/*
-+ * driver.c - driver support
-+ *
-+ * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
-+ *               Shaohua Li <shaohua.li@intel.com>
-+ *               Adam Belay <abelay@novell.com>
-+ *
-+ * This code is licenced under the GPL.
-+ */
-+
-+#include <linux/mutex.h>
-+#include <linux/module.h>
-+#include <linux/cpuidle.h>
-+
-+#include "cpuidle.h"
-+
-+LIST_HEAD(cpuidle_drivers);
-+struct cpuidle_driver *cpuidle_curr_driver;
-+
-+
-+/**
-+ * cpuidle_attach_driver - attaches a driver to a CPU
-+ * @dev: the target CPU
-+ *
-+ * Must be called with cpuidle_lock aquired.
-+ */
-+int cpuidle_attach_driver(struct cpuidle_device *dev)
-+{
-+      int ret;
-+
-+      if (dev->status & CPUIDLE_STATUS_DRIVER_ATTACHED)
-+              return -EIO;
-+
-+      if (!try_module_get(cpuidle_curr_driver->owner))
-+              return -EINVAL;
-+
-+      ret = cpuidle_curr_driver->init(dev);
-+      if (ret) {
-+              module_put(cpuidle_curr_driver->owner);
-+              printk(KERN_INFO "cpuidle: driver %s failed to attach to "
-+                      "cpu %d\n", cpuidle_curr_driver->name, dev->cpu);
-+      } else {
-+              if (dev->status & CPUIDLE_STATUS_GOVERNOR_ATTACHED)
-+                      cpuidle_rescan_device(dev);
-+              smp_wmb();
-+              dev->status |= CPUIDLE_STATUS_DRIVER_ATTACHED;
-+              cpuidle_add_driver_sysfs(dev);
-+      }
-+
-+      return ret;
-+}
-+
-+/**
-+ * cpuidle_detach_govenor - detaches a driver from a CPU
-+ * @dev: the target CPU
-+ *
-+ * Must be called with cpuidle_lock aquired.
-+ */
-+void cpuidle_detach_driver(struct cpuidle_device *dev)
-+{
-+      if (dev->status & CPUIDLE_STATUS_DRIVER_ATTACHED) {
-+              cpuidle_remove_driver_sysfs(dev);
-+              dev->status &= ~CPUIDLE_STATUS_DRIVER_ATTACHED;
-+              if (cpuidle_curr_driver->exit)
-+                      cpuidle_curr_driver->exit(dev);
-+              module_put(cpuidle_curr_driver->owner);
-+      }
-+}
-+
-+/**
-+ * __cpuidle_find_driver - finds a driver of the specified name
-+ * @str: the name
-+ *
-+ * Must be called with cpuidle_lock aquired.
-+ */
-+static struct cpuidle_driver * __cpuidle_find_driver(const char *str)
-+{
-+      struct cpuidle_driver *drv;
-+
-+      list_for_each_entry(drv, &cpuidle_drivers, driver_list)
-+              if (!strnicmp(str, drv->name, CPUIDLE_NAME_LEN))
-+                      return drv;
-+
-+      return NULL;
-+}
-+
-+/**
-+ * cpuidle_switch_driver - changes the driver
-+ * @drv: the new target driver
-+ *
-+ * NOTE: "drv" can be NULL to specify disabled
-+ * Must be called with cpuidle_lock aquired.
-+ */
-+int cpuidle_switch_driver(struct cpuidle_driver *drv)
-+{
-+      struct cpuidle_device *dev;
-+
-+      if (drv == cpuidle_curr_driver)
-+              return -EINVAL;
-+
-+      cpuidle_uninstall_idle_handler();
-+
-+      if (cpuidle_curr_driver)
-+              list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
-+                      cpuidle_detach_driver(dev);
-+
-+      cpuidle_curr_driver = drv;
-+
-+      if (drv) {
-+              int ret = 1;
-+              list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
-+                      if (cpuidle_attach_driver(dev) == 0)
-+                              ret = 0;
-+
-+              /* If attach on all devices fail, switch to NULL driver */
-+              if (ret)
-+                      cpuidle_curr_driver = NULL;
-+
-+              if (cpuidle_curr_driver && cpuidle_curr_governor) {
-+                      printk(KERN_INFO "cpuidle: using driver %s\n",
-+                                      drv->name);
-+                      cpuidle_install_idle_handler();
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+/**
-+ * cpuidle_register_driver - registers a driver
-+ * @drv: the driver
-+ */
-+int cpuidle_register_driver(struct cpuidle_driver *drv)
-+{
-+      int ret = -EEXIST;
-+
-+      if (!drv || !drv->init)
-+              return -EINVAL;
-+
-+      mutex_lock(&cpuidle_lock);
-+      if (__cpuidle_find_driver(drv->name) == NULL) {
-+              ret = 0;
-+              list_add_tail(&drv->driver_list, &cpuidle_drivers);
-+              if (!cpuidle_curr_driver)
-+                      cpuidle_switch_driver(drv);
-+      }
-+      mutex_unlock(&cpuidle_lock);
-+
-+      return ret;
-+}
-+
-+EXPORT_SYMBOL_GPL(cpuidle_register_driver);
-+
-+/**
-+ * cpuidle_unregister_driver - unregisters a driver
-+ * @drv: the driver
-+ */
-+void cpuidle_unregister_driver(struct cpuidle_driver *drv)
-+{
-+      if (!drv)
-+              return;
-+
-+      mutex_lock(&cpuidle_lock);
-+      if (drv == cpuidle_curr_driver)
-+              cpuidle_switch_driver(NULL);
-+      list_del(&drv->driver_list);
-+      mutex_unlock(&cpuidle_lock);
-+}
-+
-+EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
-+
-+static void __cpuidle_force_redetect(struct cpuidle_device *dev)
-+{
-+      cpuidle_remove_driver_sysfs(dev);
-+      cpuidle_curr_driver->redetect(dev);
-+      cpuidle_add_driver_sysfs(dev);
-+}
-+
-+/**
-+ * cpuidle_force_redetect - redetects the idle states of a CPU
-+ *
-+ * @dev: the CPU to redetect
-+ * @drv: the target driver
-+ *
-+ * Generally, the driver will call this when the supported states set has
-+ * changed. (e.g. as the result of an ACPI transition to battery power)
-+ */
-+int cpuidle_force_redetect(struct cpuidle_device *dev,
-+              struct cpuidle_driver *drv)
-+{
-+      int uninstalled = 0;
-+
-+      mutex_lock(&cpuidle_lock);
-+
-+      if (drv != cpuidle_curr_driver) {
-+              mutex_unlock(&cpuidle_lock);
-+              return 0;
-+      }
-+
-+      if (!(dev->status & CPUIDLE_STATUS_DRIVER_ATTACHED) ||
-+          !cpuidle_curr_driver->redetect) {
-+              mutex_unlock(&cpuidle_lock);
-+              return -EIO;
-+      }
-+
-+      if (cpuidle_device_can_idle(dev)) {
-+              uninstalled = 1;
-+              cpuidle_uninstall_idle_handler();
-+      }
-+
-+      __cpuidle_force_redetect(dev);
-+
-+      if (cpuidle_device_can_idle(dev)) {
-+              cpuidle_rescan_device(dev);
-+              cpuidle_install_idle_handler();
-+      }
-+
-+      /* other devices are still ok */
-+      if (uninstalled)
-+              cpuidle_install_idle_handler();
-+
-+      mutex_unlock(&cpuidle_lock);
-+
-+      return 0;
-+}
-+
-+EXPORT_SYMBOL_GPL(cpuidle_force_redetect);
-+
-+/**
-+ * cpuidle_force_redetect_devices - redetects the idle states of all CPUs
-+ *
-+ * @drv: the target driver
-+ *
-+ * Generally, the driver will call this when the supported states set has
-+ * changed. (e.g. as the result of an ACPI transition to battery power)
-+ */
-+int cpuidle_force_redetect_devices(struct cpuidle_driver *drv)
-+{
-+      struct cpuidle_device *dev;
-+      int ret = 0;
-+
-+      mutex_lock(&cpuidle_lock);
-+
-+      if (drv != cpuidle_curr_driver)
-+              goto out;
-+
-+      if (!cpuidle_curr_driver->redetect) {
-+              ret = -EIO;
-+              goto out;
-+      }
-+
-+      cpuidle_uninstall_idle_handler();
-+
-+      list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
-+              __cpuidle_force_redetect(dev);
-+
-+      cpuidle_install_idle_handler();
-+out:
-+      mutex_unlock(&cpuidle_lock);
-+      return ret;
-+}
-+
-+EXPORT_SYMBOL_GPL(cpuidle_force_redetect_devices);
-+
-+/**
-+ * cpuidle_get_bm_activity - determines if BM activity has occured
-+ */
-+int cpuidle_get_bm_activity(void)
-+{
-+      if (cpuidle_curr_driver->bm_check)
-+              return cpuidle_curr_driver->bm_check();
-+      else
-+              return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpuidle_get_bm_activity);
-+
-diff -Nurb linux-2.6.22-570/drivers/cpuidle/governor.c linux-2.6.22-590/drivers/cpuidle/governor.c
---- linux-2.6.22-570/drivers/cpuidle/governor.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/cpuidle/governor.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,160 @@
-+/*
-+ * governor.c - governor support
-+ *
-+ * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
-+ *               Shaohua Li <shaohua.li@intel.com>
-+ *               Adam Belay <abelay@novell.com>
-+ *
-+ * This code is licenced under the GPL.
-+ */
-+
-+#include <linux/mutex.h>
-+#include <linux/module.h>
-+#include <linux/cpuidle.h>
-+
-+#include "cpuidle.h"
-+
-+LIST_HEAD(cpuidle_governors);
-+struct cpuidle_governor *cpuidle_curr_governor;
-+
-+
-+/**
-+ * cpuidle_attach_governor - attaches a governor to a CPU
-+ * @dev: the target CPU
-+ *
-+ * Must be called with cpuidle_lock aquired.
-+ */
-+int cpuidle_attach_governor(struct cpuidle_device *dev)
-+{
-+      int ret = 0;
-+
-+      if(dev->status & CPUIDLE_STATUS_GOVERNOR_ATTACHED)
-+              return -EIO;
-+
-+      if (!try_module_get(cpuidle_curr_governor->owner))
-+              return -EINVAL;
-+
-+      if (cpuidle_curr_governor->init)
-+              ret = cpuidle_curr_governor->init(dev);
-+      if (ret) {
-+              module_put(cpuidle_curr_governor->owner);
-+              printk(KERN_ERR "cpuidle: governor %s failed to attach to cpu %d\n",
-+                      cpuidle_curr_governor->name, dev->cpu);
-+      } else {
-+              if (dev->status & CPUIDLE_STATUS_DRIVER_ATTACHED)
-+                      cpuidle_rescan_device(dev);
-+              smp_wmb();
-+              dev->status |= CPUIDLE_STATUS_GOVERNOR_ATTACHED;
-+      }
-+
-+      return ret;
-+}
-+
-+/**
-+ * cpuidle_detach_govenor - detaches a governor from a CPU
-+ * @dev: the target CPU
-+ *
-+ * Must be called with cpuidle_lock aquired.
-+ */
-+void cpuidle_detach_governor(struct cpuidle_device *dev)
-+{
-+      if (dev->status & CPUIDLE_STATUS_GOVERNOR_ATTACHED) {
-+              dev->status &= ~CPUIDLE_STATUS_GOVERNOR_ATTACHED;
-+              if (cpuidle_curr_governor->exit)
-+                      cpuidle_curr_governor->exit(dev);
-+              module_put(cpuidle_curr_governor->owner);
-+      }
-+}
-+
-+/**
-+ * __cpuidle_find_governor - finds a governor of the specified name
-+ * @str: the name
-+ *
-+ * Must be called with cpuidle_lock aquired.
-+ */
-+static struct cpuidle_governor * __cpuidle_find_governor(const char *str)
-+{
-+      struct cpuidle_governor *gov;
-+
-+      list_for_each_entry(gov, &cpuidle_governors, governor_list)
-+              if (!strnicmp(str, gov->name, CPUIDLE_NAME_LEN))
-+                      return gov;
-+
-+      return NULL;
-+}
-+
-+/**
-+ * cpuidle_switch_governor - changes the governor
-+ * @gov: the new target governor
-+ *
-+ * NOTE: "gov" can be NULL to specify disabled
-+ * Must be called with cpuidle_lock aquired.
-+ */
-+int cpuidle_switch_governor(struct cpuidle_governor *gov)
-+{
-+      struct cpuidle_device *dev;
-+
-+      if (gov == cpuidle_curr_governor)
-+              return -EINVAL;
-+
-+      cpuidle_uninstall_idle_handler();
-+
-+      if (cpuidle_curr_governor)
-+              list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
-+                      cpuidle_detach_governor(dev);
-+
-+      cpuidle_curr_governor = gov;
-+
-+      if (gov) {
-+              list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
-+                      cpuidle_attach_governor(dev);
-+              if (cpuidle_curr_driver)
-+                      cpuidle_install_idle_handler();
-+              printk(KERN_INFO "cpuidle: using governor %s\n", gov->name);
-+      }
-+
-+      return 0;
-+}
-+
-+/**
-+ * cpuidle_register_governor - registers a governor
-+ * @gov: the governor
-+ */
-+int cpuidle_register_governor(struct cpuidle_governor *gov)
-+{
-+      int ret = -EEXIST;
-+
-+      if (!gov || !gov->select)
-+              return -EINVAL;
-+
-+      mutex_lock(&cpuidle_lock);
-+      if (__cpuidle_find_governor(gov->name) == NULL) {
-+              ret = 0;
-+              list_add_tail(&gov->governor_list, &cpuidle_governors);
-+              if (!cpuidle_curr_governor)
-+                      cpuidle_switch_governor(gov);
-+      }
-+      mutex_unlock(&cpuidle_lock);
-+
-+      return ret;
-+}
-+
-+EXPORT_SYMBOL_GPL(cpuidle_register_governor);
-+
-+/**
-+ * cpuidle_unregister_governor - unregisters a governor
-+ * @gov: the governor
-+ */
-+void cpuidle_unregister_governor(struct cpuidle_governor *gov)
-+{
-+      if (!gov)
-+              return;
-+
-+      mutex_lock(&cpuidle_lock);
-+      if (gov == cpuidle_curr_governor)
-+              cpuidle_switch_governor(NULL);
-+      list_del(&gov->governor_list);
-+      mutex_unlock(&cpuidle_lock);
-+}
-+
-+EXPORT_SYMBOL_GPL(cpuidle_unregister_governor);
-diff -Nurb linux-2.6.22-570/drivers/cpuidle/governors/Makefile linux-2.6.22-590/drivers/cpuidle/governors/Makefile
---- linux-2.6.22-570/drivers/cpuidle/governors/Makefile        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/cpuidle/governors/Makefile        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,6 @@
-+#
-+# Makefile for cpuidle governors.
-+#
-+
-+obj-$(CONFIG_CPU_IDLE_GOV_LADDER) += ladder.o
-+obj-$(CONFIG_CPU_IDLE_GOV_MENU) += menu.o
-diff -Nurb linux-2.6.22-570/drivers/cpuidle/governors/ladder.c linux-2.6.22-590/drivers/cpuidle/governors/ladder.c
---- linux-2.6.22-570/drivers/cpuidle/governors/ladder.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/cpuidle/governors/ladder.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,227 @@
-+/*
-+ * ladder.c - the residency ladder algorithm
-+ *
-+ *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
-+ *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
-+ *  Copyright (C) 2004, 2005 Dominik Brodowski <linux@brodo.de>
-+ *
-+ * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
-+ *               Shaohua Li <shaohua.li@intel.com>
-+ *               Adam Belay <abelay@novell.com>
-+ *
-+ * This code is licenced under the GPL.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/cpuidle.h>
-+#include <linux/latency.h>
-+#include <linux/moduleparam.h>
-+#include <linux/jiffies.h>
-+
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+
-+#define PROMOTION_COUNT 4
-+#define DEMOTION_COUNT 1
-+
-+/*
-+ * bm_history -- bit-mask with a bit per jiffy of bus-master activity
-+ * 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms
-+ * 800 HZ: 0xFFFFFFFF: 32 jiffies = 40ms
-+ * 100 HZ: 0x0000000F: 4 jiffies = 40ms
-+ * reduce history for more aggressive entry into C3
-+ */
-+static unsigned int bm_history __read_mostly =
-+    (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
-+module_param(bm_history, uint, 0644);
-+
-+struct ladder_device_state {
-+      struct {
-+              u32 promotion_count;
-+              u32 demotion_count;
-+              u32 promotion_time;
-+              u32 demotion_time;
-+              u32 bm;
-+      } threshold;
-+      struct {
-+              int promotion_count;
-+              int demotion_count;
-+      } stats;
-+};
-+
-+struct ladder_device {
-+      struct ladder_device_state states[CPUIDLE_STATE_MAX];
-+      unsigned int bm_check:1;
-+      unsigned long bm_check_timestamp;
-+      unsigned long bm_activity; /* FIXME: bm activity should be global */
-+      int last_state_idx;
-+};
-+
-+/**
-+ * ladder_do_selection - prepares private data for a state change
-+ * @ldev: the ladder device
-+ * @old_idx: the current state index
-+ * @new_idx: the new target state index
-+ */
-+static inline void ladder_do_selection(struct ladder_device *ldev,
-+                                     int old_idx, int new_idx)
-+{
-+      ldev->states[old_idx].stats.promotion_count = 0;
-+      ldev->states[old_idx].stats.demotion_count = 0;
-+      ldev->last_state_idx = new_idx;
-+}
-+
-+/**
-+ * ladder_select_state - selects the next state to enter
-+ * @dev: the CPU
-+ */
-+static int ladder_select_state(struct cpuidle_device *dev)
-+{
-+      struct ladder_device *ldev = dev->governor_data;
-+      struct ladder_device_state *last_state;
-+      int last_residency, last_idx = ldev->last_state_idx;
-+
-+      if (unlikely(!ldev))
-+              return 0;
-+
-+      last_state = &ldev->states[last_idx];
-+
-+      /* demote if within BM threshold */
-+      if (ldev->bm_check) {
-+              unsigned long diff;
-+
-+              diff = jiffies - ldev->bm_check_timestamp;
-+              if (diff > 31)
-+                      diff = 31;
-+
-+              ldev->bm_activity <<= diff;
-+              if (cpuidle_get_bm_activity())
-+                      ldev->bm_activity |= ((1 << diff) - 1);
-+
-+              ldev->bm_check_timestamp = jiffies;
-+              if ((last_idx > 0) &&
-+                  (last_state->threshold.bm & ldev->bm_activity)) {
-+                      ladder_do_selection(ldev, last_idx, last_idx - 1);
-+                      return last_idx - 1;
-+              }
-+      }
-+
-+      if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID)
-+              last_residency = cpuidle_get_last_residency(dev) - dev->states[last_idx].exit_latency;
-+      else
-+              last_residency = last_state->threshold.promotion_time + 1;
-+
-+      /* consider promotion */
-+      if (last_idx < dev->state_count - 1 &&
-+          last_residency > last_state->threshold.promotion_time &&
-+          dev->states[last_idx + 1].exit_latency <= system_latency_constraint()) {
-+              last_state->stats.promotion_count++;
-+              last_state->stats.demotion_count = 0;
-+              if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
-+                      ladder_do_selection(ldev, last_idx, last_idx + 1);
-+                      return last_idx + 1;
-+              }
-+      }
-+
-+      /* consider demotion */
-+      if (last_idx > 0 &&
-+          last_residency < last_state->threshold.demotion_time) {
-+              last_state->stats.demotion_count++;
-+              last_state->stats.promotion_count = 0;
-+              if (last_state->stats.demotion_count >= last_state->threshold.demotion_count) {
-+                      ladder_do_selection(ldev, last_idx, last_idx - 1);
-+                      return last_idx - 1;
-+              }
-+      }
-+
-+      /* otherwise remain at the current state */
-+      return last_idx;
-+}
-+
-+/**
-+ * ladder_scan_device - scans a CPU's states and does setup
-+ * @dev: the CPU
-+ */
-+static void ladder_scan_device(struct cpuidle_device *dev)
-+{
-+      int i, bm_check = 0;
-+      struct ladder_device *ldev = dev->governor_data;
-+      struct ladder_device_state *lstate;
-+      struct cpuidle_state *state;
-+
-+      ldev->last_state_idx = 0;
-+      ldev->bm_check_timestamp = 0;
-+      ldev->bm_activity = 0;
-+
-+      for (i = 0; i < dev->state_count; i++) {
-+              state = &dev->states[i];
-+              lstate = &ldev->states[i];
-+
-+              lstate->stats.promotion_count = 0;
-+              lstate->stats.demotion_count = 0;
-+
-+              lstate->threshold.promotion_count = PROMOTION_COUNT;
-+              lstate->threshold.demotion_count = DEMOTION_COUNT;
-+
-+              if (i < dev->state_count - 1)
-+                      lstate->threshold.promotion_time = state->exit_latency;
-+              if (i > 0)
-+                      lstate->threshold.demotion_time = state->exit_latency;
-+              if (state->flags & CPUIDLE_FLAG_CHECK_BM) {
-+                      lstate->threshold.bm = bm_history;
-+                      bm_check = 1;
-+              } else
-+                      lstate->threshold.bm = 0;
-+      }
-+
-+      ldev->bm_check = bm_check;
-+}
-+
-+/**
-+ * ladder_init_device - initializes a CPU-instance
-+ * @dev: the CPU
-+ */
-+static int ladder_init_device(struct cpuidle_device *dev)
-+{
-+      dev->governor_data = kmalloc(sizeof(struct ladder_device), GFP_KERNEL);
-+
-+      return !dev->governor_data;
-+}
-+
-+/**
-+ * ladder_exit_device - exits a CPU-instance
-+ * @dev: the CPU
-+ */
-+static void ladder_exit_device(struct cpuidle_device *dev)
-+{
-+      kfree(dev->governor_data);
-+}
-+
-+static struct cpuidle_governor ladder_governor = {
-+      .name =         "ladder",
-+      .init =         ladder_init_device,
-+      .exit =         ladder_exit_device,
-+      .scan =         ladder_scan_device,
-+      .select =       ladder_select_state,
-+      .owner =        THIS_MODULE,
-+};
-+
-+/**
-+ * init_ladder - initializes the governor
-+ */
-+static int __init init_ladder(void)
-+{
-+      return cpuidle_register_governor(&ladder_governor);
-+}
-+
-+/**
-+ * exit_ladder - exits the governor
-+ */
-+static void __exit exit_ladder(void)
-+{
-+      cpuidle_unregister_governor(&ladder_governor);
-+}
-+
-+MODULE_LICENSE("GPL");
-+module_init(init_ladder);
-+module_exit(exit_ladder);
-diff -Nurb linux-2.6.22-570/drivers/cpuidle/governors/menu.c linux-2.6.22-590/drivers/cpuidle/governors/menu.c
---- linux-2.6.22-570/drivers/cpuidle/governors/menu.c  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/cpuidle/governors/menu.c  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,152 @@
-+/*
-+ * menu.c - the menu idle governor
-+ *
-+ * Copyright (C) 2006-2007 Adam Belay <abelay@novell.com>
-+ *
-+ * This code is licenced under the GPL.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/cpuidle.h>
-+#include <linux/latency.h>
-+#include <linux/time.h>
-+#include <linux/ktime.h>
-+#include <linux/tick.h>
-+#include <linux/hrtimer.h>
-+
-+#define BM_HOLDOFF    20000   /* 20 ms */
-+
-+struct menu_device {
-+      int             last_state_idx;
-+      int             deepest_bm_state;
-+
-+      int             break_last_us;
-+      int             break_elapsed_us;
-+
-+      int             bm_elapsed_us;
-+      int             bm_holdoff_us;
-+
-+      unsigned long   idle_jiffies;
-+};
-+
-+static DEFINE_PER_CPU(struct menu_device, menu_devices);
-+
-+/**
-+ * menu_select - selects the next idle state to enter
-+ * @dev: the CPU
-+ */
-+static int menu_select(struct cpuidle_device *dev)
-+{
-+      struct menu_device *data = &__get_cpu_var(menu_devices);
-+      int i, expected_us, max_state = dev->state_count;
-+
-+      /* discard BM history because it is sticky */
-+      cpuidle_get_bm_activity();
-+
-+      /* determine the expected residency time */
-+      expected_us = (s32) ktime_to_ns(tick_nohz_get_sleep_length()) / 1000;
-+      expected_us = min(expected_us, data->break_last_us);
-+
-+      /* determine the maximum state compatible with current BM status */
-+      if (cpuidle_get_bm_activity())
-+              data->bm_elapsed_us = 0;
-+      if (data->bm_elapsed_us <= data->bm_holdoff_us)
-+              max_state = data->deepest_bm_state + 1;
-+
-+      /* find the deepest idle state that satisfies our constraints */
-+      for (i = 1; i < max_state; i++) {
-+              struct cpuidle_state *s = &dev->states[i];
-+              if (s->target_residency > expected_us)
-+                      break;
-+              if (s->exit_latency > system_latency_constraint())
-+                      break;
-+      }
-+
-+      data->last_state_idx = i - 1;
-+      data->idle_jiffies = tick_nohz_get_idle_jiffies();
-+      return i - 1;
-+}
-+
-+/**
-+ * menu_reflect - attempts to guess what happened after entry
-+ * @dev: the CPU
-+ *
-+ * NOTE: it's important to be fast here because this operation will add to
-+ *       the overall exit latency.
-+ */
-+static void menu_reflect(struct cpuidle_device *dev)
-+{
-+      struct menu_device *data = &__get_cpu_var(menu_devices);
-+      int last_idx = data->last_state_idx;
-+      int measured_us = cpuidle_get_last_residency(dev);
-+      struct cpuidle_state *target = &dev->states[last_idx];
-+
-+      /*
-+       * Ugh, this idle state doesn't support residency measurements, so we
-+       * are basically lost in the dark.  As a compromise, assume we slept
-+       * for one full standard timer tick.  However, be aware that this
-+       * could potentially result in a suboptimal state transition.
-+       */
-+      if (!(target->flags & CPUIDLE_FLAG_TIME_VALID))
-+              measured_us = USEC_PER_SEC / HZ;
-+
-+      data->bm_elapsed_us += measured_us;
-+      data->break_elapsed_us += measured_us;
-+
-+      /*
-+       * Did something other than the timer interrupt cause the break event?
-+       */
-+      if (tick_nohz_get_idle_jiffies() == data->idle_jiffies) {
-+              data->break_last_us = data->break_elapsed_us;
-+              data->break_elapsed_us = 0;
-+      }
-+}
-+
-+/**
-+ * menu_scan_device - scans a CPU's states and does setup
-+ * @dev: the CPU
-+ */
-+static void menu_scan_device(struct cpuidle_device *dev)
-+{
-+      struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
-+      int i;
-+
-+      data->last_state_idx = 0;
-+      data->break_last_us = 0;
-+      data->break_elapsed_us = 0;
-+      data->bm_elapsed_us = 0;
-+      data->bm_holdoff_us = BM_HOLDOFF;
-+
-+      for (i = 1; i < dev->state_count; i++)
-+              if (dev->states[i].flags & CPUIDLE_FLAG_CHECK_BM)
-+                      break;
-+      data->deepest_bm_state = i - 1;
-+}
-+
-+struct cpuidle_governor menu_governor = {
-+      .name =         "menu",
-+      .scan =         menu_scan_device,
-+      .select =       menu_select,
-+      .reflect =      menu_reflect,
-+      .owner =        THIS_MODULE,
-+};
-+
-+/**
-+ * init_menu - initializes the governor
-+ */
-+static int __init init_menu(void)
-+{
-+      return cpuidle_register_governor(&menu_governor);
-+}
-+
-+/**
-+ * exit_menu - exits the governor
-+ */
-+static void __exit exit_menu(void)
-+{
-+      cpuidle_unregister_governor(&menu_governor);
-+}
-+
-+MODULE_LICENSE("GPL");
-+module_init(init_menu);
-+module_exit(exit_menu);
-diff -Nurb linux-2.6.22-570/drivers/cpuidle/sysfs.c linux-2.6.22-590/drivers/cpuidle/sysfs.c
---- linux-2.6.22-570/drivers/cpuidle/sysfs.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/cpuidle/sysfs.c   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,393 @@
-+/*
-+ * sysfs.c - sysfs support
-+ *
-+ * (C) 2006-2007 Shaohua Li <shaohua.li@intel.com>
-+ *
-+ * This code is licenced under the GPL.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/cpuidle.h>
-+#include <linux/sysfs.h>
-+#include <linux/cpu.h>
-+
-+#include "cpuidle.h"
-+
-+static unsigned int sysfs_switch;
-+static int __init cpuidle_sysfs_setup(char *unused)
-+{
-+      sysfs_switch = 1;
-+      return 1;
-+}
-+__setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup);
-+
-+static ssize_t show_available_drivers(struct sys_device *dev, char *buf)
-+{
-+      ssize_t i = 0;
-+      struct cpuidle_driver *tmp;
-+
-+      mutex_lock(&cpuidle_lock);
-+      list_for_each_entry(tmp, &cpuidle_drivers, driver_list) {
-+              if (i >= (ssize_t)((PAGE_SIZE/sizeof(char)) - CPUIDLE_NAME_LEN - 2))
-+                      goto out;
-+              i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name);
-+      }
-+out:
-+      i+= sprintf(&buf[i], "\n");
-+      mutex_unlock(&cpuidle_lock);
-+      return i;
-+}
-+
-+static ssize_t show_available_governors(struct sys_device *dev, char *buf)
-+{
-+      ssize_t i = 0;
-+      struct cpuidle_governor *tmp;
-+
-+      mutex_lock(&cpuidle_lock);
-+      list_for_each_entry(tmp, &cpuidle_governors, governor_list) {
-+              if (i >= (ssize_t)((PAGE_SIZE/sizeof(char)) - CPUIDLE_NAME_LEN - 2))
-+                      goto out;
-+              i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name);
-+      }
-+      if (list_empty(&cpuidle_governors))
-+              i+= sprintf(&buf[i], "no governors");
-+out:
-+      i+= sprintf(&buf[i], "\n");
-+      mutex_unlock(&cpuidle_lock);
-+      return i;
-+}
-+
-+static ssize_t show_current_driver(struct sys_device *dev, char *buf)
-+{
-+      ssize_t ret;
-+
-+      mutex_lock(&cpuidle_lock);
-+      ret = sprintf(buf, "%s\n", cpuidle_curr_driver->name);
-+      mutex_unlock(&cpuidle_lock);
-+      return ret;
-+}
-+
-+static ssize_t store_current_driver(struct sys_device *dev,
-+      const char *buf, size_t count)
-+{
-+      char str[CPUIDLE_NAME_LEN];
-+      int len = count;
-+      struct cpuidle_driver *tmp, *found = NULL;
-+
-+      if (len > CPUIDLE_NAME_LEN)
-+              len = CPUIDLE_NAME_LEN;
-+
-+      if (sscanf(buf, "%s", str) != 1)
-+              return -EINVAL;
-+
-+      mutex_lock(&cpuidle_lock);
-+      list_for_each_entry(tmp, &cpuidle_drivers, driver_list) {
-+              if (strncmp(tmp->name, str, CPUIDLE_NAME_LEN) == 0) {
-+                      found = tmp;
-+                      break;
-+              }
-+      }
-+      if (found)
-+              cpuidle_switch_driver(found);
-+      mutex_unlock(&cpuidle_lock);
-+
-+      return count;
-+}
-+
-+static ssize_t show_current_governor(struct sys_device *dev, char *buf)
-+{
-+      ssize_t i;
-+
-+      mutex_lock(&cpuidle_lock);
-+      if (cpuidle_curr_governor)
-+              i = sprintf(buf, "%s\n", cpuidle_curr_governor->name);
-+      else
-+              i = sprintf(buf, "no governor\n");
-+      mutex_unlock(&cpuidle_lock);
-+
-+      return i;
-+}
-+
-+static ssize_t store_current_governor(struct sys_device *dev,
-+      const char *buf, size_t count)
-+{
-+      char str[CPUIDLE_NAME_LEN];
-+      int len = count;
-+      struct cpuidle_governor *tmp, *found = NULL;
-+
-+      if (len > CPUIDLE_NAME_LEN)
-+              len = CPUIDLE_NAME_LEN;
-+
-+      if (sscanf(buf, "%s", str) != 1)
-+              return -EINVAL;
-+
-+      mutex_lock(&cpuidle_lock);
-+      list_for_each_entry(tmp, &cpuidle_governors, governor_list) {
-+              if (strncmp(tmp->name, str, CPUIDLE_NAME_LEN) == 0) {
-+                      found = tmp;
-+                      break;
-+              }
-+      }
-+      if (found)
-+              cpuidle_switch_governor(found);
-+      mutex_unlock(&cpuidle_lock);
-+
-+      return count;
-+}
-+
-+static SYSDEV_ATTR(current_driver_ro, 0444, show_current_driver, NULL);
-+static SYSDEV_ATTR(current_governor_ro, 0444, show_current_governor, NULL);
-+
-+static struct attribute *cpuclass_default_attrs[] = {
-+      &attr_current_driver_ro.attr,
-+      &attr_current_governor_ro.attr,
-+      NULL
-+};
-+
-+static SYSDEV_ATTR(available_drivers, 0444, show_available_drivers, NULL);
-+static SYSDEV_ATTR(available_governors, 0444, show_available_governors, NULL);
-+static SYSDEV_ATTR(current_driver, 0644, show_current_driver,
-+      store_current_driver);
-+static SYSDEV_ATTR(current_governor, 0644, show_current_governor,
-+      store_current_governor);
-+
-+static struct attribute *cpuclass_switch_attrs[] = {
-+      &attr_available_drivers.attr,
-+      &attr_available_governors.attr,
-+      &attr_current_driver.attr,
-+      &attr_current_governor.attr,
-+      NULL
-+};
-+
-+static struct attribute_group cpuclass_attr_group = {
-+      .attrs = cpuclass_default_attrs,
-+      .name = "cpuidle",
-+};
-+
-+/**
-+ * cpuidle_add_class_sysfs - add CPU global sysfs attributes
-+ */
-+int cpuidle_add_class_sysfs(struct sysdev_class *cls)
-+{
-+      if (sysfs_switch)
-+              cpuclass_attr_group.attrs = cpuclass_switch_attrs;
-+
-+      return sysfs_create_group(&cls->kset.kobj, &cpuclass_attr_group);
-+}
-+
-+/**
-+ * cpuidle_remove_class_sysfs - remove CPU global sysfs attributes
-+ */
-+void cpuidle_remove_class_sysfs(struct sysdev_class *cls)
-+{
-+      sysfs_remove_group(&cls->kset.kobj, &cpuclass_attr_group);
-+}
-+
-+struct cpuidle_attr {
-+      struct attribute attr;
-+      ssize_t (*show)(struct cpuidle_device *, char *);
-+      ssize_t (*store)(struct cpuidle_device *, const char *, size_t count);
-+};
-+
-+#define define_one_ro(_name, show) \
-+      static struct cpuidle_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
-+#define define_one_rw(_name, show, store) \
-+      static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store)
-+
-+#define kobj_to_cpuidledev(k) container_of(k, struct cpuidle_device, kobj)
-+#define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr)
-+static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char * buf)
-+{
-+      int ret = -EIO;
-+      struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
-+      struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
-+
-+      if (cattr->show) {
-+              mutex_lock(&cpuidle_lock);
-+              ret = cattr->show(dev, buf);
-+              mutex_unlock(&cpuidle_lock);
-+      }
-+      return ret;
-+}
-+
-+static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr,
-+                   const char * buf, size_t count)
-+{
-+      int ret = -EIO;
-+      struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
-+      struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
-+
-+      if (cattr->store) {
-+              mutex_lock(&cpuidle_lock);
-+              ret = cattr->store(dev, buf, count);
-+              mutex_unlock(&cpuidle_lock);
-+      }
-+      return ret;
-+}
-+
-+static struct sysfs_ops cpuidle_sysfs_ops = {
-+      .show = cpuidle_show,
-+      .store = cpuidle_store,
-+};
-+
-+static void cpuidle_sysfs_release(struct kobject *kobj)
-+{
-+      struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
-+
-+      complete(&dev->kobj_unregister);
-+}
-+
-+static struct kobj_type ktype_cpuidle = {
-+      .sysfs_ops = &cpuidle_sysfs_ops,
-+      .release = cpuidle_sysfs_release,
-+};
-+
-+struct cpuidle_state_attr {
-+      struct attribute attr;
-+      ssize_t (*show)(struct cpuidle_state *, char *);
-+      ssize_t (*store)(struct cpuidle_state *, const char *, size_t);
-+};
-+
-+#define define_one_state_ro(_name, show) \
-+static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
-+
-+#define define_show_state_function(_name) \
-+static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
-+{ \
-+      return sprintf(buf, "%d\n", state->_name);\
-+}
-+
-+define_show_state_function(exit_latency)
-+define_show_state_function(power_usage)
-+define_show_state_function(usage)
-+define_show_state_function(time)
-+define_one_state_ro(latency, show_state_exit_latency);
-+define_one_state_ro(power, show_state_power_usage);
-+define_one_state_ro(usage, show_state_usage);
-+define_one_state_ro(time, show_state_time);
-+
-+static struct attribute *cpuidle_state_default_attrs[] = {
-+      &attr_latency.attr,
-+      &attr_power.attr,
-+      &attr_usage.attr,
-+      &attr_time.attr,
-+      NULL
-+};
-+
-+#define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
-+#define kobj_to_state(k) (kobj_to_state_obj(k)->state)
-+#define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
-+static ssize_t cpuidle_state_show(struct kobject * kobj,
-+      struct attribute * attr ,char * buf)
-+{
-+      int ret = -EIO;
-+      struct cpuidle_state *state = kobj_to_state(kobj);
-+      struct cpuidle_state_attr * cattr = attr_to_stateattr(attr);
-+
-+      if (cattr->show)
-+              ret = cattr->show(state, buf);
-+
-+      return ret;
-+}
-+
-+static struct sysfs_ops cpuidle_state_sysfs_ops = {
-+      .show = cpuidle_state_show,
-+};
-+
-+static void cpuidle_state_sysfs_release(struct kobject *kobj)
-+{
-+      struct cpuidle_state_kobj *state_obj = kobj_to_state_obj(kobj);
-+
-+      complete(&state_obj->kobj_unregister);
-+}
-+
-+static struct kobj_type ktype_state_cpuidle = {
-+      .sysfs_ops = &cpuidle_state_sysfs_ops,
-+      .default_attrs = cpuidle_state_default_attrs,
-+      .release = cpuidle_state_sysfs_release,
-+};
-+
-+static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
-+{
-+      kobject_unregister(&device->kobjs[i]->kobj);
-+      wait_for_completion(&device->kobjs[i]->kobj_unregister);
-+      kfree(device->kobjs[i]);
-+      device->kobjs[i] = NULL;
-+}
-+
-+/**
-+ * cpuidle_add_driver_sysfs - adds driver-specific sysfs attributes
-+ * @device: the target device
-+ */
-+int cpuidle_add_driver_sysfs(struct cpuidle_device *device)
-+{
-+      int i, ret = -ENOMEM;
-+      struct cpuidle_state_kobj *kobj;
-+
-+      /* state statistics */
-+      for (i = 0; i < device->state_count; i++) {
-+              kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
-+              if (!kobj)
-+                      goto error_state;
-+              kobj->state = &device->states[i];
-+              init_completion(&kobj->kobj_unregister);
-+
-+              kobj->kobj.parent = &device->kobj;
-+              kobj->kobj.ktype = &ktype_state_cpuidle;
-+              kobject_set_name(&kobj->kobj, "state%d", i);
-+              ret = kobject_register(&kobj->kobj);
-+              if (ret) {
-+                      kfree(kobj);
-+                      goto error_state;
-+              }
-+              device->kobjs[i] = kobj;
-+      }
-+
-+      return 0;
-+
-+error_state:
-+      for (i = i - 1; i >= 0; i--)
-+              cpuidle_free_state_kobj(device, i);
-+      return ret;
-+}
-+
-+/**
-+ * cpuidle_remove_driver_sysfs - removes driver-specific sysfs attributes
-+ * @device: the target device
-+ */
-+void cpuidle_remove_driver_sysfs(struct cpuidle_device *device)
-+{
-+      int i;
-+
-+      for (i = 0; i < device->state_count; i++)
-+              cpuidle_free_state_kobj(device, i);
-+}
-+
-+/**
-+ * cpuidle_add_sysfs - creates a sysfs instance for the target device
-+ * @sysdev: the target device
-+ */
-+int cpuidle_add_sysfs(struct sys_device *sysdev)
-+{
-+      int cpu = sysdev->id;
-+      struct cpuidle_device *dev;
-+
-+      dev = per_cpu(cpuidle_devices, cpu);
-+      dev->kobj.parent = &sysdev->kobj;
-+      dev->kobj.ktype = &ktype_cpuidle;
-+      kobject_set_name(&dev->kobj, "%s", "cpuidle");
-+      return kobject_register(&dev->kobj);
-+}
-+
-+/**
-+ * cpuidle_remove_sysfs - deletes a sysfs instance on the target device
-+ * @sysdev: the target device
-+ */
-+void cpuidle_remove_sysfs(struct sys_device *sysdev)
-+{
-+      int cpu = sysdev->id;
-+      struct cpuidle_device *dev;
-+
-+      dev = per_cpu(cpuidle_devices, cpu);
-+      kobject_unregister(&dev->kobj);
-+}
-diff -Nurb linux-2.6.22-570/drivers/dma/Kconfig linux-2.6.22-590/drivers/dma/Kconfig
---- linux-2.6.22-570/drivers/dma/Kconfig       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/dma/Kconfig       2008-01-02 13:56:37.000000000 -0500
-@@ -8,8 +8,8 @@
- config DMA_ENGINE
-       bool "Support for DMA engines"
-       ---help---
--        DMA engines offload copy operations from the CPU to dedicated
--        hardware, allowing the copies to happen asynchronously.
-+          DMA engines offload bulk memory operations from the CPU to dedicated
-+          hardware, allowing the operations to happen asynchronously.
- comment "DMA Clients"
-@@ -32,4 +32,11 @@
-       ---help---
-         Enable support for the Intel(R) I/OAT DMA engine.
-+config INTEL_IOP_ADMA
-+        tristate "Intel IOP ADMA support"
-+        depends on DMA_ENGINE && (ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX)
-+        default m
-+        ---help---
-+          Enable support for the Intel(R) IOP Series RAID engines.
-+
- endmenu
-diff -Nurb linux-2.6.22-570/drivers/dma/Makefile linux-2.6.22-590/drivers/dma/Makefile
---- linux-2.6.22-570/drivers/dma/Makefile      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/dma/Makefile      2008-01-02 13:56:37.000000000 -0500
-@@ -1,3 +1,4 @@
- obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
- obj-$(CONFIG_NET_DMA) += iovlock.o
- obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
-+obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
-diff -Nurb linux-2.6.22-570/drivers/dma/dmaengine.c linux-2.6.22-590/drivers/dma/dmaengine.c
---- linux-2.6.22-570/drivers/dma/dmaengine.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/dma/dmaengine.c   2008-01-02 13:56:37.000000000 -0500
-@@ -37,11 +37,11 @@
-  * Each device has a channels list, which runs unlocked but is never modified
-  * once the device is registered, it's just setup by the driver.
-  *
-- * Each client has a channels list, it's only modified under the client->lock
-- * and in an RCU callback, so it's safe to read under rcu_read_lock().
-+ * Each client is responsible for keeping track of the channels it uses.  See
-+ * the definition of dma_event_callback in dmaengine.h.
-  *
-  * Each device has a kref, which is initialized to 1 when the device is
-- * registered. A kref_put is done for each class_device registered.  When the
-+ * registered. A kref_get is done for each class_device registered.  When the
-  * class_device is released, the coresponding kref_put is done in the release
-  * method. Every time one of the device's channels is allocated to a client,
-  * a kref_get occurs.  When the channel is freed, the coresponding kref_put
-@@ -51,14 +51,17 @@
-  * references to finish.
-  *
-  * Each channel has an open-coded implementation of Rusty Russell's "bigref,"
-- * with a kref and a per_cpu local_t.  A single reference is set when on an
-- * ADDED event, and removed with a REMOVE event.  Net DMA client takes an
-- * extra reference per outstanding transaction.  The relase function does a
-- * kref_put on the device. -ChrisL
-+ * with a kref and a per_cpu local_t.  A dma_chan_get is called when a client
-+ * signals that it wants to use a channel, and dma_chan_put is called when
-+ * a channel is removed or a client using it is unregesitered.  A client can
-+ * take extra references per outstanding transaction, as is the case with
-+ * the NET DMA client.  The release function does a kref_put on the device.
-+ *    -ChrisL, DanW
-  */
- #include <linux/init.h>
- #include <linux/module.h>
-+#include <linux/mm.h>
- #include <linux/device.h>
- #include <linux/dmaengine.h>
- #include <linux/hardirq.h>
-@@ -66,6 +69,7 @@
- #include <linux/percpu.h>
- #include <linux/rcupdate.h>
- #include <linux/mutex.h>
-+#include <linux/jiffies.h>
- static DEFINE_MUTEX(dma_list_mutex);
- static LIST_HEAD(dma_device_list);
-@@ -100,8 +104,19 @@
- static ssize_t show_in_use(struct class_device *cd, char *buf)
- {
-       struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
-+      int in_use = 0;
--      return sprintf(buf, "%d\n", (chan->client ? 1 : 0));
-+      if (unlikely(chan->slow_ref) &&
-+              atomic_read(&chan->refcount.refcount) > 1)
-+              in_use = 1;
-+      else {
-+              if (local_read(&(per_cpu_ptr(chan->local,
-+                      get_cpu())->refcount)) > 0)
-+                      in_use = 1;
-+              put_cpu();
-+      }
-+
-+      return sprintf(buf, "%d\n", in_use);
- }
- static struct class_device_attribute dma_class_attrs[] = {
-@@ -127,43 +142,72 @@
- /* --- client and device registration --- */
-+#define dma_chan_satisfies_mask(chan, mask) \
-+      __dma_chan_satisfies_mask((chan), &(mask))
-+static int
-+__dma_chan_satisfies_mask(struct dma_chan *chan, dma_cap_mask_t *want)
-+{
-+      dma_cap_mask_t has;
-+
-+      bitmap_and(has.bits, want->bits, chan->device->cap_mask.bits,
-+              DMA_TX_TYPE_END);
-+      return bitmap_equal(want->bits, has.bits, DMA_TX_TYPE_END);
-+}
-+
- /**
-- * dma_client_chan_alloc - try to allocate a channel to a client
-+ * dma_client_chan_alloc - try to allocate channels to a client
-  * @client: &dma_client
-  *
-  * Called with dma_list_mutex held.
-  */
--static struct dma_chan *dma_client_chan_alloc(struct dma_client *client)
-+static void dma_client_chan_alloc(struct dma_client *client)
- {
-       struct dma_device *device;
-       struct dma_chan *chan;
--      unsigned long flags;
-       int desc;       /* allocated descriptor count */
-+      enum dma_state_client ack;
--      /* Find a channel, any DMA engine will do */
--      list_for_each_entry(device, &dma_device_list, global_node) {
-+      /* Find a channel */
-+      list_for_each_entry(device, &dma_device_list, global_node)
-               list_for_each_entry(chan, &device->channels, device_node) {
--                      if (chan->client)
-+                      if (!dma_chan_satisfies_mask(chan, client->cap_mask))
-                               continue;
-                       desc = chan->device->device_alloc_chan_resources(chan);
-                       if (desc >= 0) {
-+                              ack = client->event_callback(client,
-+                                              chan,
-+                                              DMA_RESOURCE_AVAILABLE);
-+
-+                              /* we are done once this client rejects
-+                               * an available resource
-+                               */
-+                              if (ack == DMA_ACK) {
-+                                      dma_chan_get(chan);
-                               kref_get(&device->refcount);
--                              kref_init(&chan->refcount);
--                              chan->slow_ref = 0;
--                              INIT_RCU_HEAD(&chan->rcu);
--                              chan->client = client;
--                              spin_lock_irqsave(&client->lock, flags);
--                              list_add_tail_rcu(&chan->client_node,
--                                                &client->channels);
--                              spin_unlock_irqrestore(&client->lock, flags);
--                              return chan;
-+                              } else if (ack == DMA_NAK)
-+                                      return;
-                       }
-               }
-+}
-+
-+enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie)
-+{
-+      enum dma_status status;
-+      unsigned long dma_sync_wait_timeout = jiffies + msecs_to_jiffies(5000);
-+
-+      dma_async_issue_pending(chan);
-+      do {
-+              status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
-+              if (time_after_eq(jiffies, dma_sync_wait_timeout)) {
-+                      printk(KERN_ERR "dma_sync_wait_timeout!\n");
-+                      return DMA_ERROR;
-       }
-+      } while (status == DMA_IN_PROGRESS);
--      return NULL;
-+      return status;
- }
-+EXPORT_SYMBOL(dma_sync_wait);
- /**
-  * dma_chan_cleanup - release a DMA channel's resources
-@@ -173,7 +217,6 @@
- {
-       struct dma_chan *chan = container_of(kref, struct dma_chan, refcount);
-       chan->device->device_free_chan_resources(chan);
--      chan->client = NULL;
-       kref_put(&chan->device->refcount, dma_async_device_cleanup);
- }
- EXPORT_SYMBOL(dma_chan_cleanup);
-@@ -189,7 +232,7 @@
-       kref_put(&chan->refcount, dma_chan_cleanup);
- }
--static void dma_client_chan_free(struct dma_chan *chan)
-+static void dma_chan_release(struct dma_chan *chan)
- {
-       atomic_add(0x7FFFFFFF, &chan->refcount.refcount);
-       chan->slow_ref = 1;
-@@ -197,70 +240,57 @@
- }
- /**
-- * dma_chans_rebalance - reallocate channels to clients
-- *
-- * When the number of DMA channel in the system changes,
-- * channels need to be rebalanced among clients.
-+ * dma_chans_notify_available - broadcast available channels to the clients
-  */
--static void dma_chans_rebalance(void)
-+static void dma_clients_notify_available(void)
- {
-       struct dma_client *client;
--      struct dma_chan *chan;
--      unsigned long flags;
-       mutex_lock(&dma_list_mutex);
--      list_for_each_entry(client, &dma_client_list, global_node) {
--              while (client->chans_desired > client->chan_count) {
--                      chan = dma_client_chan_alloc(client);
--                      if (!chan)
--                              break;
--                      client->chan_count++;
--                      client->event_callback(client,
--                                             chan,
--                                             DMA_RESOURCE_ADDED);
--              }
--              while (client->chans_desired < client->chan_count) {
--                      spin_lock_irqsave(&client->lock, flags);
--                      chan = list_entry(client->channels.next,
--                                        struct dma_chan,
--                                        client_node);
--                      list_del_rcu(&chan->client_node);
--                      spin_unlock_irqrestore(&client->lock, flags);
--                      client->chan_count--;
--                      client->event_callback(client,
--                                             chan,
--                                             DMA_RESOURCE_REMOVED);
--                      dma_client_chan_free(chan);
--              }
--      }
-+      list_for_each_entry(client, &dma_client_list, global_node)
-+              dma_client_chan_alloc(client);
-       mutex_unlock(&dma_list_mutex);
- }
- /**
-- * dma_async_client_register - allocate and register a &dma_client
-- * @event_callback: callback for notification of channel addition/removal
-+ * dma_chans_notify_available - tell the clients that a channel is going away
-+ * @chan: channel on its way out
-  */
--struct dma_client *dma_async_client_register(dma_event_callback event_callback)
-+static void dma_clients_notify_removed(struct dma_chan *chan)
- {
-       struct dma_client *client;
-+      enum dma_state_client ack;
--      client = kzalloc(sizeof(*client), GFP_KERNEL);
--      if (!client)
--              return NULL;
-+      mutex_lock(&dma_list_mutex);
--      INIT_LIST_HEAD(&client->channels);
--      spin_lock_init(&client->lock);
--      client->chans_desired = 0;
--      client->chan_count = 0;
--      client->event_callback = event_callback;
-+      list_for_each_entry(client, &dma_client_list, global_node) {
-+              ack = client->event_callback(client, chan,
-+                              DMA_RESOURCE_REMOVED);
-+              /* client was holding resources for this channel so
-+               * free it
-+               */
-+              if (ack == DMA_ACK) {
-+                      dma_chan_put(chan);
-+                      kref_put(&chan->device->refcount,
-+                              dma_async_device_cleanup);
-+              }
-+      }
-+
-+      mutex_unlock(&dma_list_mutex);
-+}
-+
-+/**
-+ * dma_async_client_register - register a &dma_client
-+ * @client: ptr to a client structure with valid 'event_callback' and 'cap_mask'
-+ */
-+void dma_async_client_register(struct dma_client *client)
-+{
-       mutex_lock(&dma_list_mutex);
-       list_add_tail(&client->global_node, &dma_client_list);
-       mutex_unlock(&dma_list_mutex);
--
--      return client;
- }
- EXPORT_SYMBOL(dma_async_client_register);
-@@ -272,40 +302,42 @@
-  */
- void dma_async_client_unregister(struct dma_client *client)
- {
-+      struct dma_device *device;
-       struct dma_chan *chan;
-+      enum dma_state_client ack;
-       if (!client)
-               return;
--      rcu_read_lock();
--      list_for_each_entry_rcu(chan, &client->channels, client_node)
--              dma_client_chan_free(chan);
--      rcu_read_unlock();
--
-       mutex_lock(&dma_list_mutex);
-+      /* free all channels the client is holding */
-+      list_for_each_entry(device, &dma_device_list, global_node)
-+              list_for_each_entry(chan, &device->channels, device_node) {
-+                      ack = client->event_callback(client, chan,
-+                              DMA_RESOURCE_REMOVED);
-+
-+                      if (ack == DMA_ACK) {
-+                              dma_chan_put(chan);
-+                              kref_put(&chan->device->refcount,
-+                                      dma_async_device_cleanup);
-+                      }
-+              }
-+
-       list_del(&client->global_node);
-       mutex_unlock(&dma_list_mutex);
--
--      kfree(client);
--      dma_chans_rebalance();
- }
- EXPORT_SYMBOL(dma_async_client_unregister);
- /**
-- * dma_async_client_chan_request - request DMA channels
-- * @client: &dma_client
-- * @number: count of DMA channels requested
-- *
-- * Clients call dma_async_client_chan_request() to specify how many
-- * DMA channels they need, 0 to free all currently allocated.
-- * The resulting allocations/frees are indicated to the client via the
-- * event callback.
-+ * dma_async_client_chan_request - send all available channels to the
-+ * client that satisfy the capability mask
-+ * @client - requester
-  */
--void dma_async_client_chan_request(struct dma_client *client,
--                      unsigned int number)
-+void dma_async_client_chan_request(struct dma_client *client)
- {
--      client->chans_desired = number;
--      dma_chans_rebalance();
-+      mutex_lock(&dma_list_mutex);
-+      dma_client_chan_alloc(client);
-+      mutex_unlock(&dma_list_mutex);
- }
- EXPORT_SYMBOL(dma_async_client_chan_request);
-@@ -322,6 +354,25 @@
-       if (!device)
-               return -ENODEV;
-+      /* validate device routines */
-+      BUG_ON(dma_has_cap(DMA_MEMCPY, device->cap_mask) &&
-+              !device->device_prep_dma_memcpy);
-+      BUG_ON(dma_has_cap(DMA_XOR, device->cap_mask) &&
-+              !device->device_prep_dma_xor);
-+      BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) &&
-+              !device->device_prep_dma_zero_sum);
-+      BUG_ON(dma_has_cap(DMA_MEMSET, device->cap_mask) &&
-+              !device->device_prep_dma_memset);
-+      BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) &&
-+              !device->device_prep_dma_interrupt);
-+
-+      BUG_ON(!device->device_alloc_chan_resources);
-+      BUG_ON(!device->device_free_chan_resources);
-+      BUG_ON(!device->device_dependency_added);
-+      BUG_ON(!device->device_is_tx_complete);
-+      BUG_ON(!device->device_issue_pending);
-+      BUG_ON(!device->dev);
-+
-       init_completion(&device->done);
-       kref_init(&device->refcount);
-       device->dev_id = id++;
-@@ -339,6 +390,9 @@
-                        device->dev_id, chan->chan_id);
-               kref_get(&device->refcount);
-+              kref_init(&chan->refcount);
-+              chan->slow_ref = 0;
-+              INIT_RCU_HEAD(&chan->rcu);
-               class_device_register(&chan->class_dev);
-       }
-@@ -346,7 +400,7 @@
-       list_add_tail(&device->global_node, &dma_device_list);
-       mutex_unlock(&dma_list_mutex);
--      dma_chans_rebalance();
-+      dma_clients_notify_available();
-       return 0;
- }
-@@ -371,32 +425,165 @@
- void dma_async_device_unregister(struct dma_device *device)
- {
-       struct dma_chan *chan;
--      unsigned long flags;
-       mutex_lock(&dma_list_mutex);
-       list_del(&device->global_node);
-       mutex_unlock(&dma_list_mutex);
-       list_for_each_entry(chan, &device->channels, device_node) {
--              if (chan->client) {
--                      spin_lock_irqsave(&chan->client->lock, flags);
--                      list_del(&chan->client_node);
--                      chan->client->chan_count--;
--                      spin_unlock_irqrestore(&chan->client->lock, flags);
--                      chan->client->event_callback(chan->client,
--                                                   chan,
--                                                   DMA_RESOURCE_REMOVED);
--                      dma_client_chan_free(chan);
--              }
-+              dma_clients_notify_removed(chan);
-               class_device_unregister(&chan->class_dev);
-+              dma_chan_release(chan);
-       }
--      dma_chans_rebalance();
-       kref_put(&device->refcount, dma_async_device_cleanup);
-       wait_for_completion(&device->done);
- }
- EXPORT_SYMBOL(dma_async_device_unregister);
-+/**
-+ * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
-+ * @chan: DMA channel to offload copy to
-+ * @dest: destination address (virtual)
-+ * @src: source address (virtual)
-+ * @len: length
-+ *
-+ * Both @dest and @src must be mappable to a bus address according to the
-+ * DMA mapping API rules for streaming mappings.
-+ * Both @dest and @src must stay memory resident (kernel memory or locked
-+ * user space pages).
-+ */
-+dma_cookie_t
-+dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
-+                      void *src, size_t len)
-+{
-+      struct dma_device *dev = chan->device;
-+      struct dma_async_tx_descriptor *tx;
-+      dma_addr_t addr;
-+      dma_cookie_t cookie;
-+      int cpu;
-+
-+      tx = dev->device_prep_dma_memcpy(chan, len, 0);
-+      if (!tx)
-+              return -ENOMEM;
-+
-+      tx->ack = 1;
-+      tx->callback = NULL;
-+      addr = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
-+      tx->tx_set_src(addr, tx, 0);
-+      addr = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
-+      tx->tx_set_dest(addr, tx, 0);
-+      cookie = tx->tx_submit(tx);
-+
-+      cpu = get_cpu();
-+      per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
-+      per_cpu_ptr(chan->local, cpu)->memcpy_count++;
-+      put_cpu();
-+
-+      return cookie;
-+}
-+EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf);
-+
-+/**
-+ * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
-+ * @chan: DMA channel to offload copy to
-+ * @page: destination page
-+ * @offset: offset in page to copy to
-+ * @kdata: source address (virtual)
-+ * @len: length
-+ *
-+ * Both @page/@offset and @kdata must be mappable to a bus address according
-+ * to the DMA mapping API rules for streaming mappings.
-+ * Both @page/@offset and @kdata must stay memory resident (kernel memory or
-+ * locked user space pages)
-+ */
-+dma_cookie_t
-+dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
-+                      unsigned int offset, void *kdata, size_t len)
-+{
-+      struct dma_device *dev = chan->device;
-+      struct dma_async_tx_descriptor *tx;
-+      dma_addr_t addr;
-+      dma_cookie_t cookie;
-+      int cpu;
-+
-+      tx = dev->device_prep_dma_memcpy(chan, len, 0);
-+      if (!tx)
-+              return -ENOMEM;
-+
-+      tx->ack = 1;
-+      tx->callback = NULL;
-+      addr = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
-+      tx->tx_set_src(addr, tx, 0);
-+      addr = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
-+      tx->tx_set_dest(addr, tx, 0);
-+      cookie = tx->tx_submit(tx);
-+
-+      cpu = get_cpu();
-+      per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
-+      per_cpu_ptr(chan->local, cpu)->memcpy_count++;
-+      put_cpu();
-+
-+      return cookie;
-+}
-+EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg);
-+
-+/**
-+ * dma_async_memcpy_pg_to_pg - offloaded copy from page to page
-+ * @chan: DMA channel to offload copy to
-+ * @dest_pg: destination page
-+ * @dest_off: offset in page to copy to
-+ * @src_pg: source page
-+ * @src_off: offset in page to copy from
-+ * @len: length
-+ *
-+ * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
-+ * address according to the DMA mapping API rules for streaming mappings.
-+ * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
-+ * (kernel memory or locked user space pages).
-+ */
-+dma_cookie_t
-+dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
-+      unsigned int dest_off, struct page *src_pg, unsigned int src_off,
-+      size_t len)
-+{
-+      struct dma_device *dev = chan->device;
-+      struct dma_async_tx_descriptor *tx;
-+      dma_addr_t addr;
-+      dma_cookie_t cookie;
-+      int cpu;
-+
-+      tx = dev->device_prep_dma_memcpy(chan, len, 0);
-+      if (!tx)
-+              return -ENOMEM;
-+
-+      tx->ack = 1;
-+      tx->callback = NULL;
-+      addr = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
-+      tx->tx_set_src(addr, tx, 0);
-+      addr = dma_map_page(dev->dev, dest_pg, dest_off, len, DMA_FROM_DEVICE);
-+      tx->tx_set_dest(addr, tx, 0);
-+      cookie = tx->tx_submit(tx);
-+
-+      cpu = get_cpu();
-+      per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
-+      per_cpu_ptr(chan->local, cpu)->memcpy_count++;
-+      put_cpu();
-+
-+      return cookie;
-+}
-+EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg);
-+
-+void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
-+      struct dma_chan *chan)
-+{
-+      tx->chan = chan;
-+      spin_lock_init(&tx->lock);
-+      INIT_LIST_HEAD(&tx->depend_node);
-+      INIT_LIST_HEAD(&tx->depend_list);
-+}
-+EXPORT_SYMBOL(dma_async_tx_descriptor_init);
-+
- static int __init dma_bus_init(void)
- {
-       mutex_init(&dma_list_mutex);
-diff -Nurb linux-2.6.22-570/drivers/dma/ioatdma.c linux-2.6.22-590/drivers/dma/ioatdma.c
---- linux-2.6.22-570/drivers/dma/ioatdma.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/dma/ioatdma.c     2008-01-02 13:56:37.000000000 -0500
-@@ -39,6 +39,7 @@
- #define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)
- #define to_ioat_device(dev) container_of(dev, struct ioat_device, common)
- #define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
-+#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)
- /* internal functions */
- static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-@@ -71,13 +72,76 @@
-               INIT_LIST_HEAD(&ioat_chan->used_desc);
-               /* This should be made common somewhere in dmaengine.c */
-               ioat_chan->common.device = &device->common;
--              ioat_chan->common.client = NULL;
-               list_add_tail(&ioat_chan->common.device_node,
-                             &device->common.channels);
-       }
-       return device->common.chancnt;
- }
-+static void
-+ioat_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index)
-+{
-+      struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx);
-+      struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
-+
-+      pci_unmap_addr_set(desc, src, addr);
-+
-+      list_for_each_entry(iter, &desc->group_list, node) {
-+              iter->hw->src_addr = addr;
-+              addr += ioat_chan->xfercap;
-+      }
-+
-+}
-+
-+static void
-+ioat_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index)
-+{
-+      struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx);
-+      struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
-+
-+      pci_unmap_addr_set(desc, dst, addr);
-+
-+      list_for_each_entry(iter, &desc->group_list, node) {
-+              iter->hw->dst_addr = addr;
-+              addr += ioat_chan->xfercap;
-+      }
-+}
-+
-+static dma_cookie_t
-+ioat_tx_submit(struct dma_async_tx_descriptor *tx)
-+{
-+      struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
-+      struct ioat_desc_sw *desc = tx_to_ioat_desc(tx);
-+      struct ioat_desc_sw *group_start = list_entry(desc->group_list.next,
-+              struct ioat_desc_sw, node);
-+      int append = 0;
-+      dma_cookie_t cookie;
-+
-+      spin_lock_bh(&ioat_chan->desc_lock);
-+      /* cookie incr and addition to used_list must be atomic */
-+      cookie = ioat_chan->common.cookie;
-+      cookie++;
-+      if (cookie < 0)
-+              cookie = 1;
-+      ioat_chan->common.cookie = desc->async_tx.cookie = cookie;
-+
-+      /* write address into NextDescriptor field of last desc in chain */
-+      to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = group_start->phys;
-+      list_splice_init(&desc->group_list, ioat_chan->used_desc.prev);
-+
-+      ioat_chan->pending += desc->group_count;
-+      if (ioat_chan->pending >= 4) {
-+              append = 1;
-+              ioat_chan->pending = 0;
-+      }
-+      spin_unlock_bh(&ioat_chan->desc_lock);
-+
-+      if (append)
-+              ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET,
-+                                      IOAT_CHANCMD_APPEND);
-+      return cookie;
-+}
-+
- static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
-       struct ioat_dma_chan *ioat_chan,
-       gfp_t flags)
-@@ -99,6 +163,11 @@
-       }
-       memset(desc, 0, sizeof(*desc));
-+      dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common);
-+      desc_sw->async_tx.tx_set_src = ioat_set_src;
-+      desc_sw->async_tx.tx_set_dest = ioat_set_dest;
-+      desc_sw->async_tx.tx_submit = ioat_tx_submit;
-+      INIT_LIST_HEAD(&desc_sw->group_list);
-       desc_sw->hw = desc;
-       desc_sw->phys = phys;
-@@ -215,45 +284,25 @@
-       ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
- }
--/**
-- * do_ioat_dma_memcpy - actual function that initiates a IOAT DMA transaction
-- * @ioat_chan: IOAT DMA channel handle
-- * @dest: DMA destination address
-- * @src: DMA source address
-- * @len: transaction length in bytes
-- */
--
--static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan,
--                                       dma_addr_t dest,
--                                       dma_addr_t src,
--                                       size_t len)
--{
--      struct ioat_desc_sw *first;
--      struct ioat_desc_sw *prev;
--      struct ioat_desc_sw *new;
--      dma_cookie_t cookie;
-+static struct dma_async_tx_descriptor *
-+ioat_dma_prep_memcpy(struct dma_chan *chan, size_t len, int int_en)
-+{
-+      struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-+      struct ioat_desc_sw *first, *prev, *new;
-       LIST_HEAD(new_chain);
-       u32 copy;
-       size_t orig_len;
--      dma_addr_t orig_src, orig_dst;
--      unsigned int desc_count = 0;
--      unsigned int append = 0;
--
--      if (!ioat_chan || !dest || !src)
--              return -EFAULT;
-+      int desc_count = 0;
-       if (!len)
--              return ioat_chan->common.cookie;
-+              return NULL;
-       orig_len = len;
--      orig_src = src;
--      orig_dst = dest;
-       first = NULL;
-       prev = NULL;
-       spin_lock_bh(&ioat_chan->desc_lock);
--
-       while (len) {
-               if (!list_empty(&ioat_chan->free_desc)) {
-                       new = to_ioat_desc(ioat_chan->free_desc.next);
-@@ -270,9 +319,8 @@
-               new->hw->size = copy;
-               new->hw->ctl = 0;
--              new->hw->src_addr = src;
--              new->hw->dst_addr = dest;
--              new->cookie = 0;
-+              new->async_tx.cookie = 0;
-+              new->async_tx.ack = 1;
-               /* chain together the physical address list for the HW */
-               if (!first)
-@@ -281,130 +329,26 @@
-                       prev->hw->next = (u64) new->phys;
-               prev = new;
--
-               len  -= copy;
--              dest += copy;
--              src  += copy;
--
-               list_add_tail(&new->node, &new_chain);
-               desc_count++;
-       }
--      new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
--      new->hw->next = 0;
--      /* cookie incr and addition to used_list must be atomic */
-+      list_splice(&new_chain, &new->group_list);
--      cookie = ioat_chan->common.cookie;
--      cookie++;
--      if (cookie < 0)
--              cookie = 1;
--      ioat_chan->common.cookie = new->cookie = cookie;
-+      new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
-+      new->hw->next = 0;
-+      new->group_count = desc_count;
-+      new->async_tx.ack = 0; /* client is in control of this ack */
-+      new->async_tx.cookie = -EBUSY;
--      pci_unmap_addr_set(new, src, orig_src);
--      pci_unmap_addr_set(new, dst, orig_dst);
-       pci_unmap_len_set(new, src_len, orig_len);
-       pci_unmap_len_set(new, dst_len, orig_len);
--
--      /* write address into NextDescriptor field of last desc in chain */
--      to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = first->phys;
--      list_splice_init(&new_chain, ioat_chan->used_desc.prev);
--
--      ioat_chan->pending += desc_count;
--      if (ioat_chan->pending >= 20) {
--              append = 1;
--              ioat_chan->pending = 0;
--      }
--
-       spin_unlock_bh(&ioat_chan->desc_lock);
--      if (append)
--              ioatdma_chan_write8(ioat_chan,
--                                  IOAT_CHANCMD_OFFSET,
--                                  IOAT_CHANCMD_APPEND);
--      return cookie;
--}
--
--/**
-- * ioat_dma_memcpy_buf_to_buf - wrapper that takes src & dest bufs
-- * @chan: IOAT DMA channel handle
-- * @dest: DMA destination address
-- * @src: DMA source address
-- * @len: transaction length in bytes
-- */
--
--static dma_cookie_t ioat_dma_memcpy_buf_to_buf(struct dma_chan *chan,
--                                               void *dest,
--                                               void *src,
--                                               size_t len)
--{
--      dma_addr_t dest_addr;
--      dma_addr_t src_addr;
--      struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
--
--      dest_addr = pci_map_single(ioat_chan->device->pdev,
--              dest, len, PCI_DMA_FROMDEVICE);
--      src_addr = pci_map_single(ioat_chan->device->pdev,
--              src, len, PCI_DMA_TODEVICE);
--
--      return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
--}
--
--/**
-- * ioat_dma_memcpy_buf_to_pg - wrapper, copying from a buf to a page
-- * @chan: IOAT DMA channel handle
-- * @page: pointer to the page to copy to
-- * @offset: offset into that page
-- * @src: DMA source address
-- * @len: transaction length in bytes
-- */
--
--static dma_cookie_t ioat_dma_memcpy_buf_to_pg(struct dma_chan *chan,
--                                              struct page *page,
--                                              unsigned int offset,
--                                              void *src,
--                                              size_t len)
--{
--      dma_addr_t dest_addr;
--      dma_addr_t src_addr;
--      struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
--
--      dest_addr = pci_map_page(ioat_chan->device->pdev,
--              page, offset, len, PCI_DMA_FROMDEVICE);
--      src_addr = pci_map_single(ioat_chan->device->pdev,
--              src, len, PCI_DMA_TODEVICE);
--
--      return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
-+      return new ? &new->async_tx : NULL;
- }
--/**
-- * ioat_dma_memcpy_pg_to_pg - wrapper, copying between two pages
-- * @chan: IOAT DMA channel handle
-- * @dest_pg: pointer to the page to copy to
-- * @dest_off: offset into that page
-- * @src_pg: pointer to the page to copy from
-- * @src_off: offset into that page
-- * @len: transaction length in bytes. This is guaranteed not to make a copy
-- *     across a page boundary.
-- */
--
--static dma_cookie_t ioat_dma_memcpy_pg_to_pg(struct dma_chan *chan,
--                                             struct page *dest_pg,
--                                             unsigned int dest_off,
--                                             struct page *src_pg,
--                                             unsigned int src_off,
--                                             size_t len)
--{
--      dma_addr_t dest_addr;
--      dma_addr_t src_addr;
--      struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
--
--      dest_addr = pci_map_page(ioat_chan->device->pdev,
--              dest_pg, dest_off, len, PCI_DMA_FROMDEVICE);
--      src_addr = pci_map_page(ioat_chan->device->pdev,
--              src_pg, src_off, len, PCI_DMA_TODEVICE);
--
--      return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
--}
- /**
-  * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended descriptors to hw
-@@ -467,8 +411,8 @@
-                * exceeding xfercap, perhaps. If so, only the last one will
-                * have a cookie, and require unmapping.
-                */
--              if (desc->cookie) {
--                      cookie = desc->cookie;
-+              if (desc->async_tx.cookie) {
-+                      cookie = desc->async_tx.cookie;
-                       /* yes we are unmapping both _page and _single alloc'd
-                          regions with unmap_page. Is this *really* that bad?
-@@ -484,13 +428,18 @@
-               }
-               if (desc->phys != phys_complete) {
--                      /* a completed entry, but not the last, so cleanup */
-+                      /* a completed entry, but not the last, so cleanup
-+                       * if the client is done with the descriptor
-+                       */
-+                      if (desc->async_tx.ack) {
-                       list_del(&desc->node);
-                       list_add_tail(&desc->node, &chan->free_desc);
-+                      } else
-+                              desc->async_tx.cookie = 0;
-               } else {
-                       /* last used desc. Do not remove, so we can append from
-                          it, but don't look at it next time, either */
--                      desc->cookie = 0;
-+                      desc->async_tx.cookie = 0;
-                       /* TODO check status bits? */
-                       break;
-@@ -506,6 +455,17 @@
-       spin_unlock(&chan->cleanup_lock);
- }
-+static void ioat_dma_dependency_added(struct dma_chan *chan)
-+{
-+      struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-+      spin_lock_bh(&ioat_chan->desc_lock);
-+      if (ioat_chan->pending == 0) {
-+              spin_unlock_bh(&ioat_chan->desc_lock);
-+              ioat_dma_memcpy_cleanup(ioat_chan);
-+      } else
-+              spin_unlock_bh(&ioat_chan->desc_lock);
-+}
-+
- /**
-  * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
-  * @chan: IOAT DMA channel handle
-@@ -607,6 +567,7 @@
-       desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
-       desc->hw->next = 0;
-+      desc->async_tx.ack = 1;
-       list_add_tail(&desc->node, &ioat_chan->used_desc);
-       spin_unlock_bh(&ioat_chan->desc_lock);
-@@ -633,6 +594,8 @@
-       u8 *src;
-       u8 *dest;
-       struct dma_chan *dma_chan;
-+      struct dma_async_tx_descriptor *tx;
-+      dma_addr_t addr;
-       dma_cookie_t cookie;
-       int err = 0;
-@@ -658,7 +621,15 @@
-               goto out;
-       }
--      cookie = ioat_dma_memcpy_buf_to_buf(dma_chan, dest, src, IOAT_TEST_SIZE);
-+      tx = ioat_dma_prep_memcpy(dma_chan, IOAT_TEST_SIZE, 0);
-+      async_tx_ack(tx);
-+      addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE,
-+                      DMA_TO_DEVICE);
-+      ioat_set_src(addr, tx, 0);
-+      addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,
-+                      DMA_FROM_DEVICE);
-+      ioat_set_dest(addr, tx, 0);
-+      cookie = ioat_tx_submit(tx);
-       ioat_dma_memcpy_issue_pending(dma_chan);
-       msleep(1);
-@@ -754,13 +725,14 @@
-       INIT_LIST_HEAD(&device->common.channels);
-       enumerate_dma_channels(device);
-+      dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
-       device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources;
-       device->common.device_free_chan_resources = ioat_dma_free_chan_resources;
--      device->common.device_memcpy_buf_to_buf = ioat_dma_memcpy_buf_to_buf;
--      device->common.device_memcpy_buf_to_pg = ioat_dma_memcpy_buf_to_pg;
--      device->common.device_memcpy_pg_to_pg = ioat_dma_memcpy_pg_to_pg;
--      device->common.device_memcpy_complete = ioat_dma_is_complete;
--      device->common.device_memcpy_issue_pending = ioat_dma_memcpy_issue_pending;
-+      device->common.device_prep_dma_memcpy = ioat_dma_prep_memcpy;
-+      device->common.device_is_tx_complete = ioat_dma_is_complete;
-+      device->common.device_issue_pending = ioat_dma_memcpy_issue_pending;
-+      device->common.device_dependency_added = ioat_dma_dependency_added;
-+      device->common.dev = &pdev->dev;
-       printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n",
-               device->common.chancnt);
-diff -Nurb linux-2.6.22-570/drivers/dma/ioatdma.h linux-2.6.22-590/drivers/dma/ioatdma.h
---- linux-2.6.22-570/drivers/dma/ioatdma.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/dma/ioatdma.h     2008-01-02 13:56:37.000000000 -0500
-@@ -30,9 +30,6 @@
- #define IOAT_LOW_COMPLETION_MASK      0xffffffc0
--extern struct list_head dma_device_list;
--extern struct list_head dma_client_list;
--
- /**
-  * struct ioat_device - internal representation of a IOAT device
-  * @pdev: PCI-Express device
-@@ -105,15 +102,20 @@
- /**
-  * struct ioat_desc_sw - wrapper around hardware descriptor
-  * @hw: hardware DMA descriptor
-+ * @async_tx:
-  * @node:
-+ * @group_list:
-+ * @group_cnt:
-  * @cookie:
-  * @phys:
-  */
- struct ioat_desc_sw {
-       struct ioat_dma_descriptor *hw;
-+      struct dma_async_tx_descriptor async_tx;
-       struct list_head node;
--      dma_cookie_t cookie;
-+      struct list_head group_list;
-+      int group_count;
-       dma_addr_t phys;
-       DECLARE_PCI_UNMAP_ADDR(src)
-       DECLARE_PCI_UNMAP_LEN(src_len)
-@@ -122,4 +124,3 @@
- };
- #endif /* IOATDMA_H */
--
-diff -Nurb linux-2.6.22-570/drivers/dma/iop-adma.c linux-2.6.22-590/drivers/dma/iop-adma.c
---- linux-2.6.22-570/drivers/dma/iop-adma.c    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/dma/iop-adma.c    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,1465 @@
-+/*
-+ * offload engine driver for the Intel Xscale series of i/o processors
-+ * Copyright Â© 2006, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ */
-+
-+/*
-+ * This driver supports the asynchrounous DMA copy and RAID engines available
-+ * on the Intel Xscale(R) family of I/O Processors (IOP 32x, 33x, 134x)
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/async_tx.h>
-+#include <linux/delay.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/spinlock.h>
-+#include <linux/interrupt.h>
-+#include <linux/platform_device.h>
-+#include <linux/memory.h>
-+#include <linux/ioport.h>
-+
-+#include <asm/arch/adma.h>
-+
-+#define to_iop_adma_chan(chan) container_of(chan, struct iop_adma_chan, common)
-+#define to_iop_adma_device(dev) \
-+      container_of(dev, struct iop_adma_device, common)
-+#define tx_to_iop_adma_slot(tx) \
-+      container_of(tx, struct iop_adma_desc_slot, async_tx)
-+
-+/**
-+ * iop_adma_free_slots - flags descriptor slots for reuse
-+ * @slot: Slot to free
-+ * Caller must hold &iop_chan->lock while calling this function
-+ */
-+static void iop_adma_free_slots(struct iop_adma_desc_slot *slot)
-+{
-+      int stride = slot->slots_per_op;
-+
-+      while (stride--) {
-+              slot->slots_per_op = 0;
-+              slot = list_entry(slot->slot_node.next,
-+                              struct iop_adma_desc_slot,
-+                              slot_node);
-+      }
-+}
-+
-+static dma_cookie_t
-+iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
-+      struct iop_adma_chan *iop_chan, dma_cookie_t cookie)
-+{
-+      BUG_ON(desc->async_tx.cookie < 0);
-+      spin_lock_bh(&desc->async_tx.lock);
-+      if (desc->async_tx.cookie > 0) {
-+              cookie = desc->async_tx.cookie;
-+              desc->async_tx.cookie = 0;
-+
-+              /* call the callback (must not sleep or submit new
-+               * operations to this channel)
-+               */
-+              if (desc->async_tx.callback)
-+                      desc->async_tx.callback(
-+                              desc->async_tx.callback_param);
-+
-+              /* unmap dma addresses
-+               * (unmap_single vs unmap_page?)
-+               */
-+              if (desc->group_head && desc->unmap_len) {
-+                      struct iop_adma_desc_slot *unmap = desc->group_head;
-+                      struct device *dev =
-+                              &iop_chan->device->pdev->dev;
-+                      u32 len = unmap->unmap_len;
-+                      u32 src_cnt = unmap->unmap_src_cnt;
-+                      dma_addr_t addr = iop_desc_get_dest_addr(unmap,
-+                              iop_chan);
-+
-+                      dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
-+                      while (src_cnt--) {
-+                              addr = iop_desc_get_src_addr(unmap,
-+                                                      iop_chan,
-+                                                      src_cnt);
-+                              dma_unmap_page(dev, addr, len,
-+                                      DMA_TO_DEVICE);
-+                      }
-+                      desc->group_head = NULL;
-+              }
-+      }
-+
-+      /* run dependent operations */
-+      async_tx_run_dependencies(&desc->async_tx);
-+      spin_unlock_bh(&desc->async_tx.lock);
-+
-+      return cookie;
-+}
-+
-+static int
-+iop_adma_clean_slot(struct iop_adma_desc_slot *desc,
-+      struct iop_adma_chan *iop_chan)
-+{
-+      /* the client is allowed to attach dependent operations
-+       * until 'ack' is set
-+       */
-+      if (!desc->async_tx.ack)
-+              return 0;
-+
-+      /* leave the last descriptor in the chain
-+       * so we can append to it
-+       */
-+      if (desc->chain_node.next == &iop_chan->chain)
-+              return 1;
-+
-+      dev_dbg(iop_chan->device->common.dev,
-+              "\tfree slot: %d slots_per_op: %d\n",
-+              desc->idx, desc->slots_per_op);
-+
-+      list_del(&desc->chain_node);
-+      iop_adma_free_slots(desc);
-+
-+      return 0;
-+}
-+
-+static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
-+{
-+      struct iop_adma_desc_slot *iter, *_iter, *grp_start = NULL;
-+      dma_cookie_t cookie = 0;
-+      u32 current_desc = iop_chan_get_current_descriptor(iop_chan);
-+      int busy = iop_chan_is_busy(iop_chan);
-+      int seen_current = 0, slot_cnt = 0, slots_per_op = 0;
-+
-+      dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
-+      /* free completed slots from the chain starting with
-+       * the oldest descriptor
-+       */
-+      list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
-+                                      chain_node) {
-+              pr_debug("\tcookie: %d slot: %d busy: %d "
-+                      "this_desc: %#x next_desc: %#x ack: %d\n",
-+                      iter->async_tx.cookie, iter->idx, busy, iter->phys,
-+                      iop_desc_get_next_desc(iter),
-+                      iter->async_tx.ack);
-+              prefetch(_iter);
-+              prefetch(&_iter->async_tx);
-+
-+              /* do not advance past the current descriptor loaded into the
-+               * hardware channel, subsequent descriptors are either in
-+               * process or have not been submitted
-+               */
-+              if (seen_current)
-+                      break;
-+
-+              /* stop the search if we reach the current descriptor and the
-+               * channel is busy, or if it appears that the current descriptor
-+               * needs to be re-read (i.e. has been appended to)
-+               */
-+              if (iter->phys == current_desc) {
-+                      BUG_ON(seen_current++);
-+                      if (busy || iop_desc_get_next_desc(iter))
-+                              break;
-+              }
-+
-+              /* detect the start of a group transaction */
-+              if (!slot_cnt && !slots_per_op) {
-+                      slot_cnt = iter->slot_cnt;
-+                      slots_per_op = iter->slots_per_op;
-+                      if (slot_cnt <= slots_per_op) {
-+                              slot_cnt = 0;
-+                              slots_per_op = 0;
-+                      }
-+              }
-+
-+              if (slot_cnt) {
-+                      pr_debug("\tgroup++\n");
-+                      if (!grp_start)
-+                              grp_start = iter;
-+                      slot_cnt -= slots_per_op;
-+              }
-+
-+              /* all the members of a group are complete */
-+              if (slots_per_op != 0 && slot_cnt == 0) {
-+                      struct iop_adma_desc_slot *grp_iter, *_grp_iter;
-+                      int end_of_chain = 0;
-+                      pr_debug("\tgroup end\n");
-+
-+                      /* collect the total results */
-+                      if (grp_start->xor_check_result) {
-+                              u32 zero_sum_result = 0;
-+                              slot_cnt = grp_start->slot_cnt;
-+                              grp_iter = grp_start;
-+
-+                              list_for_each_entry_from(grp_iter,
-+                                      &iop_chan->chain, chain_node) {
-+                                      zero_sum_result |=
-+                                          iop_desc_get_zero_result(grp_iter);
-+                                          pr_debug("\titer%d result: %d\n",
-+                                          grp_iter->idx, zero_sum_result);
-+                                      slot_cnt -= slots_per_op;
-+                                      if (slot_cnt == 0)
-+                                              break;
-+                              }
-+                              pr_debug("\tgrp_start->xor_check_result: %p\n",
-+                                      grp_start->xor_check_result);
-+                              *grp_start->xor_check_result = zero_sum_result;
-+                      }
-+
-+                      /* clean up the group */
-+                      slot_cnt = grp_start->slot_cnt;
-+                      grp_iter = grp_start;
-+                      list_for_each_entry_safe_from(grp_iter, _grp_iter,
-+                              &iop_chan->chain, chain_node) {
-+                              cookie = iop_adma_run_tx_complete_actions(
-+                                      grp_iter, iop_chan, cookie);
-+
-+                              slot_cnt -= slots_per_op;
-+                              end_of_chain = iop_adma_clean_slot(grp_iter,
-+                                      iop_chan);
-+
-+                              if (slot_cnt == 0 || end_of_chain)
-+                                      break;
-+                      }
-+
-+                      /* the group should be complete at this point */
-+                      BUG_ON(slot_cnt);
-+
-+                      slots_per_op = 0;
-+                      grp_start = NULL;
-+                      if (end_of_chain)
-+                              break;
-+                      else
-+                              continue;
-+              } else if (slots_per_op) /* wait for group completion */
-+                      continue;
-+
-+              /* write back zero sum results (single descriptor case) */
-+              if (iter->xor_check_result && iter->async_tx.cookie)
-+                      *iter->xor_check_result =
-+                              iop_desc_get_zero_result(iter);
-+
-+              cookie = iop_adma_run_tx_complete_actions(
-+                                      iter, iop_chan, cookie);
-+
-+              if (iop_adma_clean_slot(iter, iop_chan))
-+                      break;
-+      }
-+
-+      BUG_ON(!seen_current);
-+
-+      iop_chan_idle(busy, iop_chan);
-+
-+      if (cookie > 0) {
-+              iop_chan->completed_cookie = cookie;
-+              pr_debug("\tcompleted cookie %d\n", cookie);
-+      }
-+}
-+
-+static void
-+iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
-+{
-+      spin_lock_bh(&iop_chan->lock);
-+      __iop_adma_slot_cleanup(iop_chan);
-+      spin_unlock_bh(&iop_chan->lock);
-+}
-+
-+static void iop_adma_tasklet(unsigned long data)
-+{
-+      struct iop_adma_chan *chan = (struct iop_adma_chan *) data;
-+      __iop_adma_slot_cleanup(chan);
-+}
-+
-+static struct iop_adma_desc_slot *
-+iop_adma_alloc_slots(struct iop_adma_chan *iop_chan, int num_slots,
-+                      int slots_per_op)
-+{
-+      struct iop_adma_desc_slot *iter, *_iter, *alloc_start = NULL;
-+      struct list_head chain = LIST_HEAD_INIT(chain);
-+      int slots_found, retry = 0;
-+
-+      /* start search from the last allocated descrtiptor
-+       * if a contiguous allocation can not be found start searching
-+       * from the beginning of the list
-+       */
-+retry:
-+      slots_found = 0;
-+      if (retry == 0)
-+              iter = iop_chan->last_used;
-+      else
-+              iter = list_entry(&iop_chan->all_slots,
-+                      struct iop_adma_desc_slot,
-+                      slot_node);
-+
-+      list_for_each_entry_safe_continue(
-+              iter, _iter, &iop_chan->all_slots, slot_node) {
-+              prefetch(_iter);
-+              prefetch(&_iter->async_tx);
-+              if (iter->slots_per_op) {
-+                      /* give up after finding the first busy slot
-+                       * on the second pass through the list
-+                       */
-+                      if (retry)
-+                              break;
-+
-+                      slots_found = 0;
-+                      continue;
-+              }
-+
-+              /* start the allocation if the slot is correctly aligned */
-+              if (!slots_found++) {
-+                      if (iop_desc_is_aligned(iter, slots_per_op))
-+                              alloc_start = iter;
-+                      else {
-+                              slots_found = 0;
-+                              continue;
-+                      }
-+              }
-+
-+              if (slots_found == num_slots) {
-+                      struct iop_adma_desc_slot *alloc_tail = NULL;
-+                      struct iop_adma_desc_slot *last_used = NULL;
-+                      iter = alloc_start;
-+                      while (num_slots) {
-+                              int i;
-+                              dev_dbg(iop_chan->device->common.dev,
-+                                      "allocated slot: %d "
-+                                      "(desc %p phys: %#x) slots_per_op %d\n",
-+                                      iter->idx, iter->hw_desc, iter->phys,
-+                                      slots_per_op);
-+
-+                              /* pre-ack all but the last descriptor */
-+                              if (num_slots != slots_per_op)
-+                                      iter->async_tx.ack = 1;
-+                              else
-+                                      iter->async_tx.ack = 0;
-+
-+                              list_add_tail(&iter->chain_node, &chain);
-+                              alloc_tail = iter;
-+                              iter->async_tx.cookie = 0;
-+                              iter->slot_cnt = num_slots;
-+                              iter->xor_check_result = NULL;
-+                              for (i = 0; i < slots_per_op; i++) {
-+                                      iter->slots_per_op = slots_per_op - i;
-+                                      last_used = iter;
-+                                      iter = list_entry(iter->slot_node.next,
-+                                              struct iop_adma_desc_slot,
-+                                              slot_node);
-+                              }
-+                              num_slots -= slots_per_op;
-+                      }
-+                      alloc_tail->group_head = alloc_start;
-+                      alloc_tail->async_tx.cookie = -EBUSY;
-+                      list_splice(&chain, &alloc_tail->group_list);
-+                      iop_chan->last_used = last_used;
-+                      iop_desc_clear_next_desc(alloc_start);
-+                      iop_desc_clear_next_desc(alloc_tail);
-+                      return alloc_tail;
-+              }
-+      }
-+      if (!retry++)
-+              goto retry;
-+
-+      /* try to free some slots if the allocation fails */
-+      tasklet_schedule(&iop_chan->irq_tasklet);
-+
-+      return NULL;
-+}
-+
-+static dma_cookie_t
-+iop_desc_assign_cookie(struct iop_adma_chan *iop_chan,
-+      struct iop_adma_desc_slot *desc)
-+{
-+      dma_cookie_t cookie = iop_chan->common.cookie;
-+      cookie++;
-+      if (cookie < 0)
-+              cookie = 1;
-+      iop_chan->common.cookie = desc->async_tx.cookie = cookie;
-+      return cookie;
-+}
-+
-+static void iop_adma_check_threshold(struct iop_adma_chan *iop_chan)
-+{
-+      dev_dbg(iop_chan->device->common.dev, "pending: %d\n",
-+              iop_chan->pending);
-+
-+      if (iop_chan->pending >= IOP_ADMA_THRESHOLD) {
-+              iop_chan->pending = 0;
-+              iop_chan_append(iop_chan);
-+      }
-+}
-+
-+static dma_cookie_t
-+iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
-+{
-+      struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
-+      struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan);
-+      struct iop_adma_desc_slot *grp_start, *old_chain_tail;
-+      int slot_cnt;
-+      int slots_per_op;
-+      dma_cookie_t cookie;
-+
-+      grp_start = sw_desc->group_head;
-+      slot_cnt = grp_start->slot_cnt;
-+      slots_per_op = grp_start->slots_per_op;
-+
-+      spin_lock_bh(&iop_chan->lock);
-+      cookie = iop_desc_assign_cookie(iop_chan, sw_desc);
-+
-+      old_chain_tail = list_entry(iop_chan->chain.prev,
-+              struct iop_adma_desc_slot, chain_node);
-+      list_splice_init(&sw_desc->group_list, &old_chain_tail->chain_node);
-+
-+      /* fix up the hardware chain */
-+      iop_desc_set_next_desc(old_chain_tail, grp_start->phys);
-+
-+      /* 1/ don't add pre-chained descriptors
-+       * 2/ dummy read to flush next_desc write
-+       */
-+      BUG_ON(iop_desc_get_next_desc(sw_desc));
-+
-+      /* increment the pending count by the number of slots
-+       * memcpy operations have a 1:1 (slot:operation) relation
-+       * other operations are heavier and will pop the threshold
-+       * more often.
-+       */
-+      iop_chan->pending += slot_cnt;
-+      iop_adma_check_threshold(iop_chan);
-+      spin_unlock_bh(&iop_chan->lock);
-+
-+      dev_dbg(iop_chan->device->common.dev, "%s cookie: %d slot: %d\n",
-+              __FUNCTION__, sw_desc->async_tx.cookie, sw_desc->idx);
-+
-+      return cookie;
-+}
-+
-+static void
-+iop_adma_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
-+      int index)
-+{
-+      struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
-+      struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan);
-+
-+      /* to do: support transfers lengths > IOP_ADMA_MAX_BYTE_COUNT */
-+      iop_desc_set_dest_addr(sw_desc->group_head, iop_chan, addr);
-+}
-+
-+static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan);
-+static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan);
-+
-+/* returns the number of allocated descriptors */
-+static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
-+{
-+      char *hw_desc;
-+      int idx;
-+      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-+      struct iop_adma_desc_slot *slot = NULL;
-+      int init = iop_chan->slots_allocated ? 0 : 1;
-+      struct iop_adma_platform_data *plat_data =
-+              iop_chan->device->pdev->dev.platform_data;
-+      int num_descs_in_pool = plat_data->pool_size/IOP_ADMA_SLOT_SIZE;
-+
-+      /* Allocate descriptor slots */
-+      do {
-+              idx = iop_chan->slots_allocated;
-+              if (idx == num_descs_in_pool)
-+                      break;
-+
-+              slot = kzalloc(sizeof(*slot), GFP_KERNEL);
-+              if (!slot) {
-+                      printk(KERN_INFO "IOP ADMA Channel only initialized"
-+                              " %d descriptor slots", idx);
-+                      break;
-+              }
-+              hw_desc = (char *) iop_chan->device->dma_desc_pool_virt;
-+              slot->hw_desc = (void *) &hw_desc[idx * IOP_ADMA_SLOT_SIZE];
-+
-+              dma_async_tx_descriptor_init(&slot->async_tx, chan);
-+              slot->async_tx.tx_submit = iop_adma_tx_submit;
-+              slot->async_tx.tx_set_dest = iop_adma_set_dest;
-+              INIT_LIST_HEAD(&slot->chain_node);
-+              INIT_LIST_HEAD(&slot->slot_node);
-+              INIT_LIST_HEAD(&slot->group_list);
-+              hw_desc = (char *) iop_chan->device->dma_desc_pool;
-+              slot->phys = (dma_addr_t) &hw_desc[idx * IOP_ADMA_SLOT_SIZE];
-+              slot->idx = idx;
-+
-+              spin_lock_bh(&iop_chan->lock);
-+              iop_chan->slots_allocated++;
-+              list_add_tail(&slot->slot_node, &iop_chan->all_slots);
-+              spin_unlock_bh(&iop_chan->lock);
-+      } while (iop_chan->slots_allocated < num_descs_in_pool);
-+
-+      if (idx && !iop_chan->last_used)
-+              iop_chan->last_used = list_entry(iop_chan->all_slots.next,
-+                                      struct iop_adma_desc_slot,
-+                                      slot_node);
-+
-+      dev_dbg(iop_chan->device->common.dev,
-+              "allocated %d descriptor slots last_used: %p\n",
-+              iop_chan->slots_allocated, iop_chan->last_used);
-+
-+      /* initialize the channel and the chain with a null operation */
-+      if (init) {
-+              if (dma_has_cap(DMA_MEMCPY,
-+                      iop_chan->device->common.cap_mask))
-+                      iop_chan_start_null_memcpy(iop_chan);
-+              else if (dma_has_cap(DMA_XOR,
-+                      iop_chan->device->common.cap_mask))
-+                      iop_chan_start_null_xor(iop_chan);
-+              else
-+                      BUG();
-+      }
-+
-+      return (idx > 0) ? idx : -ENOMEM;
-+}
-+
-+static struct dma_async_tx_descriptor *
-+iop_adma_prep_dma_interrupt(struct dma_chan *chan)
-+{
-+      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-+      struct iop_adma_desc_slot *sw_desc, *grp_start;
-+      int slot_cnt, slots_per_op;
-+
-+      dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
-+
-+      spin_lock_bh(&iop_chan->lock);
-+      slot_cnt = iop_chan_interrupt_slot_count(&slots_per_op, iop_chan);
-+      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-+      if (sw_desc) {
-+              grp_start = sw_desc->group_head;
-+              iop_desc_init_interrupt(grp_start, iop_chan);
-+              grp_start->unmap_len = 0;
-+      }
-+      spin_unlock_bh(&iop_chan->lock);
-+
-+      return sw_desc ? &sw_desc->async_tx : NULL;
-+}
-+
-+static void
-+iop_adma_memcpy_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
-+      int index)
-+{
-+      struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
-+      struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
-+
-+      iop_desc_set_memcpy_src_addr(grp_start, addr);
-+}
-+
-+static struct dma_async_tx_descriptor *
-+iop_adma_prep_dma_memcpy(struct dma_chan *chan, size_t len, int int_en)
-+{
-+      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-+      struct iop_adma_desc_slot *sw_desc, *grp_start;
-+      int slot_cnt, slots_per_op;
-+
-+      if (unlikely(!len))
-+              return NULL;
-+      BUG_ON(unlikely(len > IOP_ADMA_MAX_BYTE_COUNT));
-+
-+      dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
-+              __FUNCTION__, len);
-+
-+      spin_lock_bh(&iop_chan->lock);
-+      slot_cnt = iop_chan_memcpy_slot_count(len, &slots_per_op);
-+      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-+      if (sw_desc) {
-+              grp_start = sw_desc->group_head;
-+              iop_desc_init_memcpy(grp_start, int_en);
-+              iop_desc_set_byte_count(grp_start, iop_chan, len);
-+              sw_desc->unmap_src_cnt = 1;
-+              sw_desc->unmap_len = len;
-+              sw_desc->async_tx.tx_set_src = iop_adma_memcpy_set_src;
-+      }
-+      spin_unlock_bh(&iop_chan->lock);
-+
-+      return sw_desc ? &sw_desc->async_tx : NULL;
-+}
-+
-+static struct dma_async_tx_descriptor *
-+iop_adma_prep_dma_memset(struct dma_chan *chan, int value, size_t len,
-+      int int_en)
-+{
-+      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-+      struct iop_adma_desc_slot *sw_desc, *grp_start;
-+      int slot_cnt, slots_per_op;
-+
-+      if (unlikely(!len))
-+              return NULL;
-+      BUG_ON(unlikely(len > IOP_ADMA_MAX_BYTE_COUNT));
-+
-+      dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
-+              __FUNCTION__, len);
-+
-+      spin_lock_bh(&iop_chan->lock);
-+      slot_cnt = iop_chan_memset_slot_count(len, &slots_per_op);
-+      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-+      if (sw_desc) {
-+              grp_start = sw_desc->group_head;
-+              iop_desc_init_memset(grp_start, int_en);
-+              iop_desc_set_byte_count(grp_start, iop_chan, len);
-+              iop_desc_set_block_fill_val(grp_start, value);
-+              sw_desc->unmap_src_cnt = 1;
-+              sw_desc->unmap_len = len;
-+      }
-+      spin_unlock_bh(&iop_chan->lock);
-+
-+      return sw_desc ? &sw_desc->async_tx : NULL;
-+}
-+
-+static void
-+iop_adma_xor_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
-+      int index)
-+{
-+      struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
-+      struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
-+
-+      iop_desc_set_xor_src_addr(grp_start, index, addr);
-+}
-+
-+static struct dma_async_tx_descriptor *
-+iop_adma_prep_dma_xor(struct dma_chan *chan, unsigned int src_cnt, size_t len,
-+      int int_en)
-+{
-+      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-+      struct iop_adma_desc_slot *sw_desc, *grp_start;
-+      int slot_cnt, slots_per_op;
-+
-+      if (unlikely(!len))
-+              return NULL;
-+      BUG_ON(unlikely(len > IOP_ADMA_XOR_MAX_BYTE_COUNT));
-+
-+      dev_dbg(iop_chan->device->common.dev,
-+              "%s src_cnt: %d len: %u int_en: %d\n",
-+              __FUNCTION__, src_cnt, len, int_en);
-+
-+      spin_lock_bh(&iop_chan->lock);
-+      slot_cnt = iop_chan_xor_slot_count(len, src_cnt, &slots_per_op);
-+      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-+      if (sw_desc) {
-+              grp_start = sw_desc->group_head;
-+              iop_desc_init_xor(grp_start, src_cnt, int_en);
-+              iop_desc_set_byte_count(grp_start, iop_chan, len);
-+              sw_desc->unmap_src_cnt = src_cnt;
-+              sw_desc->unmap_len = len;
-+              sw_desc->async_tx.tx_set_src = iop_adma_xor_set_src;
-+      }
-+      spin_unlock_bh(&iop_chan->lock);
-+
-+      return sw_desc ? &sw_desc->async_tx : NULL;
-+}
-+
-+static void
-+iop_adma_xor_zero_sum_set_src(dma_addr_t addr,
-+                              struct dma_async_tx_descriptor *tx,
-+                              int index)
-+{
-+      struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
-+      struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
-+
-+      iop_desc_set_zero_sum_src_addr(grp_start, index, addr);
-+}
-+
-+static struct dma_async_tx_descriptor *
-+iop_adma_prep_dma_zero_sum(struct dma_chan *chan, unsigned int src_cnt,
-+      size_t len, u32 *result, int int_en)
-+{
-+      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-+      struct iop_adma_desc_slot *sw_desc, *grp_start;
-+      int slot_cnt, slots_per_op;
-+
-+      if (unlikely(!len))
-+              return NULL;
-+
-+      dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %u\n",
-+              __FUNCTION__, src_cnt, len);
-+
-+      spin_lock_bh(&iop_chan->lock);
-+      slot_cnt = iop_chan_zero_sum_slot_count(len, src_cnt, &slots_per_op);
-+      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-+      if (sw_desc) {
-+              grp_start = sw_desc->group_head;
-+              iop_desc_init_zero_sum(grp_start, src_cnt, int_en);
-+              iop_desc_set_zero_sum_byte_count(grp_start, len);
-+              grp_start->xor_check_result = result;
-+              pr_debug("\t%s: grp_start->xor_check_result: %p\n",
-+                      __FUNCTION__, grp_start->xor_check_result);
-+              sw_desc->unmap_src_cnt = src_cnt;
-+              sw_desc->unmap_len = len;
-+              sw_desc->async_tx.tx_set_src = iop_adma_xor_zero_sum_set_src;
-+      }
-+      spin_unlock_bh(&iop_chan->lock);
-+
-+      return sw_desc ? &sw_desc->async_tx : NULL;
-+}
-+
-+static void iop_adma_dependency_added(struct dma_chan *chan)
-+{
-+      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-+      tasklet_schedule(&iop_chan->irq_tasklet);
-+}
-+
-+static void iop_adma_free_chan_resources(struct dma_chan *chan)
-+{
-+      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-+      struct iop_adma_desc_slot *iter, *_iter;
-+      int in_use_descs = 0;
-+
-+      iop_adma_slot_cleanup(iop_chan);
-+
-+      spin_lock_bh(&iop_chan->lock);
-+      list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
-+                                      chain_node) {
-+              in_use_descs++;
-+              list_del(&iter->chain_node);
-+      }
-+      list_for_each_entry_safe_reverse(
-+              iter, _iter, &iop_chan->all_slots, slot_node) {
-+              list_del(&iter->slot_node);
-+              kfree(iter);
-+              iop_chan->slots_allocated--;
-+      }
-+      iop_chan->last_used = NULL;
-+
-+      dev_dbg(iop_chan->device->common.dev, "%s slots_allocated %d\n",
-+              __FUNCTION__, iop_chan->slots_allocated);
-+      spin_unlock_bh(&iop_chan->lock);
-+
-+      /* one is ok since we left it on there on purpose */
-+      if (in_use_descs > 1)
-+              printk(KERN_ERR "IOP: Freeing %d in use descriptors!\n",
-+                      in_use_descs - 1);
-+}
-+
-+/**
-+ * iop_adma_is_complete - poll the status of an ADMA transaction
-+ * @chan: ADMA channel handle
-+ * @cookie: ADMA transaction identifier
-+ */
-+static enum dma_status iop_adma_is_complete(struct dma_chan *chan,
-+                                      dma_cookie_t cookie,
-+                                      dma_cookie_t *done,
-+                                      dma_cookie_t *used)
-+{
-+      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-+      dma_cookie_t last_used;
-+      dma_cookie_t last_complete;
-+      enum dma_status ret;
-+
-+      last_used = chan->cookie;
-+      last_complete = iop_chan->completed_cookie;
-+
-+      if (done)
-+              *done = last_complete;
-+      if (used)
-+              *used = last_used;
-+
-+      ret = dma_async_is_complete(cookie, last_complete, last_used);
-+      if (ret == DMA_SUCCESS)
-+              return ret;
-+
-+      iop_adma_slot_cleanup(iop_chan);
-+
-+      last_used = chan->cookie;
-+      last_complete = iop_chan->completed_cookie;
-+
-+      if (done)
-+              *done = last_complete;
-+      if (used)
-+              *used = last_used;
-+
-+      return dma_async_is_complete(cookie, last_complete, last_used);
-+}
-+
-+static irqreturn_t iop_adma_eot_handler(int irq, void *data)
-+{
-+      struct iop_adma_chan *chan = data;
-+
-+      dev_dbg(chan->device->common.dev, "%s\n", __FUNCTION__);
-+
-+      tasklet_schedule(&chan->irq_tasklet);
-+
-+      iop_adma_device_clear_eot_status(chan);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static irqreturn_t iop_adma_eoc_handler(int irq, void *data)
-+{
-+      struct iop_adma_chan *chan = data;
-+
-+      dev_dbg(chan->device->common.dev, "%s\n", __FUNCTION__);
-+
-+      tasklet_schedule(&chan->irq_tasklet);
-+
-+      iop_adma_device_clear_eoc_status(chan);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static irqreturn_t iop_adma_err_handler(int irq, void *data)
-+{
-+      struct iop_adma_chan *chan = data;
-+      unsigned long status = iop_chan_get_status(chan);
-+
-+      dev_printk(KERN_ERR, chan->device->common.dev,
-+              "error ( %s%s%s%s%s%s%s)\n",
-+              iop_is_err_int_parity(status, chan) ? "int_parity " : "",
-+              iop_is_err_mcu_abort(status, chan) ? "mcu_abort " : "",
-+              iop_is_err_int_tabort(status, chan) ? "int_tabort " : "",
-+              iop_is_err_int_mabort(status, chan) ? "int_mabort " : "",
-+              iop_is_err_pci_tabort(status, chan) ? "pci_tabort " : "",
-+              iop_is_err_pci_mabort(status, chan) ? "pci_mabort " : "",
-+              iop_is_err_split_tx(status, chan) ? "split_tx " : "");
-+
-+      iop_adma_device_clear_err_status(chan);
-+
-+      BUG();
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static void iop_adma_issue_pending(struct dma_chan *chan)
-+{
-+      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-+
-+      if (iop_chan->pending) {
-+              iop_chan->pending = 0;
-+              iop_chan_append(iop_chan);
-+      }
-+}
-+
-+/*
-+ * Perform a transaction to verify the HW works.
-+ */
-+#define IOP_ADMA_TEST_SIZE 2000
-+
-+static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
-+{
-+      int i;
-+      void *src, *dest;
-+      dma_addr_t src_dma, dest_dma;
-+      struct dma_chan *dma_chan;
-+      dma_cookie_t cookie;
-+      struct dma_async_tx_descriptor *tx;
-+      int err = 0;
-+      struct iop_adma_chan *iop_chan;
-+
-+      dev_dbg(device->common.dev, "%s\n", __FUNCTION__);
-+
-+      src = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
-+      if (!src)
-+              return -ENOMEM;
-+      dest = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
-+      if (!dest) {
-+              kfree(src);
-+              return -ENOMEM;
-+      }
-+
-+      /* Fill in src buffer */
-+      for (i = 0; i < IOP_ADMA_TEST_SIZE; i++)
-+              ((u8 *) src)[i] = (u8)i;
-+
-+      memset(dest, 0, IOP_ADMA_TEST_SIZE);
-+
-+      /* Start copy, using first DMA channel */
-+      dma_chan = container_of(device->common.channels.next,
-+                              struct dma_chan,
-+                              device_node);
-+      if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
-+              err = -ENODEV;
-+              goto out;
-+      }
-+
-+      tx = iop_adma_prep_dma_memcpy(dma_chan, IOP_ADMA_TEST_SIZE, 1);
-+      dest_dma = dma_map_single(dma_chan->device->dev, dest,
-+                              IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
-+      iop_adma_set_dest(dest_dma, tx, 0);
-+      src_dma = dma_map_single(dma_chan->device->dev, src,
-+                              IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE);
-+      iop_adma_memcpy_set_src(src_dma, tx, 0);
-+
-+      cookie = iop_adma_tx_submit(tx);
-+      iop_adma_issue_pending(dma_chan);
-+      async_tx_ack(tx);
-+      msleep(1);
-+
-+      if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
-+                      DMA_SUCCESS) {
-+              dev_printk(KERN_ERR, dma_chan->device->dev,
-+                      "Self-test copy timed out, disabling\n");
-+              err = -ENODEV;
-+              goto free_resources;
-+      }
-+
-+      iop_chan = to_iop_adma_chan(dma_chan);
-+      dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
-+              IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
-+      if (memcmp(src, dest, IOP_ADMA_TEST_SIZE)) {
-+              dev_printk(KERN_ERR, dma_chan->device->dev,
-+                      "Self-test copy failed compare, disabling\n");
-+              err = -ENODEV;
-+              goto free_resources;
-+      }
-+
-+free_resources:
-+      iop_adma_free_chan_resources(dma_chan);
-+out:
-+      kfree(src);
-+      kfree(dest);
-+      return err;
-+}
-+
-+#define IOP_ADMA_NUM_SRC_TEST 4 /* must be <= 15 */
-+static int __devinit
-+iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
-+{
-+      int i, src_idx;
-+      struct page *dest;
-+      struct page *xor_srcs[IOP_ADMA_NUM_SRC_TEST];
-+      struct page *zero_sum_srcs[IOP_ADMA_NUM_SRC_TEST + 1];
-+      dma_addr_t dma_addr, dest_dma;
-+      struct dma_async_tx_descriptor *tx;
-+      struct dma_chan *dma_chan;
-+      dma_cookie_t cookie;
-+      u8 cmp_byte = 0;
-+      u32 cmp_word;
-+      u32 zero_sum_result;
-+      int err = 0;
-+      struct iop_adma_chan *iop_chan;
-+
-+      dev_dbg(device->common.dev, "%s\n", __FUNCTION__);
-+
-+      for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
-+              xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
-+              if (!xor_srcs[src_idx])
-+                      while (src_idx--) {
-+                              __free_page(xor_srcs[src_idx]);
-+                              return -ENOMEM;
-+                      }
-+      }
-+
-+      dest = alloc_page(GFP_KERNEL);
-+      if (!dest)
-+              while (src_idx--) {
-+                      __free_page(xor_srcs[src_idx]);
-+                      return -ENOMEM;
-+              }
-+
-+      /* Fill in src buffers */
-+      for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
-+              u8 *ptr = page_address(xor_srcs[src_idx]);
-+              for (i = 0; i < PAGE_SIZE; i++)
-+                      ptr[i] = (1 << src_idx);
-+      }
-+
-+      for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++)
-+              cmp_byte ^= (u8) (1 << src_idx);
-+
-+      cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
-+                      (cmp_byte << 8) | cmp_byte;
-+
-+      memset(page_address(dest), 0, PAGE_SIZE);
-+
-+      dma_chan = container_of(device->common.channels.next,
-+                              struct dma_chan,
-+                              device_node);
-+      if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
-+              err = -ENODEV;
-+              goto out;
-+      }
-+
-+      /* test xor */
-+      tx = iop_adma_prep_dma_xor(dma_chan, IOP_ADMA_NUM_SRC_TEST,
-+                              PAGE_SIZE, 1);
-+      dest_dma = dma_map_page(dma_chan->device->dev, dest, 0,
-+                              PAGE_SIZE, DMA_FROM_DEVICE);
-+      iop_adma_set_dest(dest_dma, tx, 0);
-+
-+      for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++) {
-+              dma_addr = dma_map_page(dma_chan->device->dev, xor_srcs[i], 0,
-+                      PAGE_SIZE, DMA_TO_DEVICE);
-+              iop_adma_xor_set_src(dma_addr, tx, i);
-+      }
-+
-+      cookie = iop_adma_tx_submit(tx);
-+      iop_adma_issue_pending(dma_chan);
-+      async_tx_ack(tx);
-+      msleep(8);
-+
-+      if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
-+              DMA_SUCCESS) {
-+              dev_printk(KERN_ERR, dma_chan->device->dev,
-+                      "Self-test xor timed out, disabling\n");
-+              err = -ENODEV;
-+              goto free_resources;
-+      }
-+
-+      iop_chan = to_iop_adma_chan(dma_chan);
-+      dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
-+              PAGE_SIZE, DMA_FROM_DEVICE);
-+      for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
-+              u32 *ptr = page_address(dest);
-+              if (ptr[i] != cmp_word) {
-+                      dev_printk(KERN_ERR, dma_chan->device->dev,
-+                              "Self-test xor failed compare, disabling\n");
-+                      err = -ENODEV;
-+                      goto free_resources;
-+              }
-+      }
-+      dma_sync_single_for_device(&iop_chan->device->pdev->dev, dest_dma,
-+              PAGE_SIZE, DMA_TO_DEVICE);
-+
-+      /* skip zero sum if the capability is not present */
-+      if (!dma_has_cap(DMA_ZERO_SUM, dma_chan->device->cap_mask))
-+              goto free_resources;
-+
-+      /* zero sum the sources with the destintation page */
-+      for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++)
-+              zero_sum_srcs[i] = xor_srcs[i];
-+      zero_sum_srcs[i] = dest;
-+
-+      zero_sum_result = 1;
-+
-+      tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1,
-+              PAGE_SIZE, &zero_sum_result, 1);
-+      for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) {
-+              dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i],
-+                      0, PAGE_SIZE, DMA_TO_DEVICE);
-+              iop_adma_xor_zero_sum_set_src(dma_addr, tx, i);
-+      }
-+
-+      cookie = iop_adma_tx_submit(tx);
-+      iop_adma_issue_pending(dma_chan);
-+      async_tx_ack(tx);
-+      msleep(8);
-+
-+      if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
-+              dev_printk(KERN_ERR, dma_chan->device->dev,
-+                      "Self-test zero sum timed out, disabling\n");
-+              err = -ENODEV;
-+              goto free_resources;
-+      }
-+
-+      if (zero_sum_result != 0) {
-+              dev_printk(KERN_ERR, dma_chan->device->dev,
-+                      "Self-test zero sum failed compare, disabling\n");
-+              err = -ENODEV;
-+              goto free_resources;
-+      }
-+
-+      /* test memset */
-+      tx = iop_adma_prep_dma_memset(dma_chan, 0, PAGE_SIZE, 1);
-+      dma_addr = dma_map_page(dma_chan->device->dev, dest, 0,
-+                      PAGE_SIZE, DMA_FROM_DEVICE);
-+      iop_adma_set_dest(dma_addr, tx, 0);
-+
-+      cookie = iop_adma_tx_submit(tx);
-+      iop_adma_issue_pending(dma_chan);
-+      async_tx_ack(tx);
-+      msleep(8);
-+
-+      if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
-+              dev_printk(KERN_ERR, dma_chan->device->dev,
-+                      "Self-test memset timed out, disabling\n");
-+              err = -ENODEV;
-+              goto free_resources;
-+      }
-+
-+      for (i = 0; i < PAGE_SIZE/sizeof(u32); i++) {
-+              u32 *ptr = page_address(dest);
-+              if (ptr[i]) {
-+                      dev_printk(KERN_ERR, dma_chan->device->dev,
-+                              "Self-test memset failed compare, disabling\n");
-+                      err = -ENODEV;
-+                      goto free_resources;
-+              }
-+      }
-+
-+      /* test for non-zero parity sum */
-+      zero_sum_result = 0;
-+      tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1,
-+              PAGE_SIZE, &zero_sum_result, 1);
-+      for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) {
-+              dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i],
-+                      0, PAGE_SIZE, DMA_TO_DEVICE);
-+              iop_adma_xor_zero_sum_set_src(dma_addr, tx, i);
-+      }
-+
-+      cookie = iop_adma_tx_submit(tx);
-+      iop_adma_issue_pending(dma_chan);
-+      async_tx_ack(tx);
-+      msleep(8);
-+
-+      if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
-+              dev_printk(KERN_ERR, dma_chan->device->dev,
-+                      "Self-test non-zero sum timed out, disabling\n");
-+              err = -ENODEV;
-+              goto free_resources;
-+      }
-+
-+      if (zero_sum_result != 1) {
-+              dev_printk(KERN_ERR, dma_chan->device->dev,
-+                      "Self-test non-zero sum failed compare, disabling\n");
-+              err = -ENODEV;
-+              goto free_resources;
-+      }
-+
-+free_resources:
-+      iop_adma_free_chan_resources(dma_chan);
-+out:
-+      src_idx = IOP_ADMA_NUM_SRC_TEST;
-+      while (src_idx--)
-+              __free_page(xor_srcs[src_idx]);
-+      __free_page(dest);
-+      return err;
-+}
-+
-+static int __devexit iop_adma_remove(struct platform_device *dev)
-+{
-+      struct iop_adma_device *device = platform_get_drvdata(dev);
-+      struct dma_chan *chan, *_chan;
-+      struct iop_adma_chan *iop_chan;
-+      int i;
-+      struct iop_adma_platform_data *plat_data = dev->dev.platform_data;
-+
-+      dma_async_device_unregister(&device->common);
-+
-+      for (i = 0; i < 3; i++) {
-+              unsigned int irq;
-+              irq = platform_get_irq(dev, i);
-+              free_irq(irq, device);
-+      }
-+
-+      dma_free_coherent(&dev->dev, plat_data->pool_size,
-+                      device->dma_desc_pool_virt, device->dma_desc_pool);
-+
-+      do {
-+              struct resource *res;
-+              res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-+              release_mem_region(res->start, res->end - res->start);
-+      } while (0);
-+
-+      list_for_each_entry_safe(chan, _chan, &device->common.channels,
-+                              device_node) {
-+              iop_chan = to_iop_adma_chan(chan);
-+              list_del(&chan->device_node);
-+              kfree(iop_chan);
-+      }
-+      kfree(device);
-+
-+      return 0;
-+}
-+
-+static int __devinit iop_adma_probe(struct platform_device *pdev)
-+{
-+      struct resource *res;
-+      int ret = 0, i;
-+      struct iop_adma_device *adev;
-+      struct iop_adma_chan *iop_chan;
-+      struct dma_device *dma_dev;
-+      struct iop_adma_platform_data *plat_data = pdev->dev.platform_data;
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      if (!res)
-+              return -ENODEV;
-+
-+      if (!devm_request_mem_region(&pdev->dev, res->start,
-+                              res->end - res->start, pdev->name))
-+              return -EBUSY;
-+
-+      adev = kzalloc(sizeof(*adev), GFP_KERNEL);
-+      if (!adev)
-+              return -ENOMEM;
-+      dma_dev = &adev->common;
-+
-+      /* allocate coherent memory for hardware descriptors
-+       * note: writecombine gives slightly better performance, but
-+       * requires that we explicitly flush the writes
-+       */
-+      if ((adev->dma_desc_pool_virt = dma_alloc_writecombine(&pdev->dev,
-+                                      plat_data->pool_size,
-+                                      &adev->dma_desc_pool,
-+                                      GFP_KERNEL)) == NULL) {
-+              ret = -ENOMEM;
-+              goto err_free_adev;
-+      }
-+
-+      dev_dbg(&pdev->dev, "%s: allocted descriptor pool virt %p phys %p\n",
-+              __FUNCTION__, adev->dma_desc_pool_virt,
-+              (void *) adev->dma_desc_pool);
-+
-+      adev->id = plat_data->hw_id;
-+
-+      /* discover transaction capabilites from the platform data */
-+      dma_dev->cap_mask = plat_data->cap_mask;
-+
-+      adev->pdev = pdev;
-+      platform_set_drvdata(pdev, adev);
-+
-+      INIT_LIST_HEAD(&dma_dev->channels);
-+
-+      /* set base routines */
-+      dma_dev->device_alloc_chan_resources = iop_adma_alloc_chan_resources;
-+      dma_dev->device_free_chan_resources = iop_adma_free_chan_resources;
-+      dma_dev->device_is_tx_complete = iop_adma_is_complete;
-+      dma_dev->device_issue_pending = iop_adma_issue_pending;
-+      dma_dev->device_dependency_added = iop_adma_dependency_added;
-+      dma_dev->dev = &pdev->dev;
-+
-+      /* set prep routines based on capability */
-+      if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask))
-+              dma_dev->device_prep_dma_memcpy = iop_adma_prep_dma_memcpy;
-+      if (dma_has_cap(DMA_MEMSET, dma_dev->cap_mask))
-+              dma_dev->device_prep_dma_memset = iop_adma_prep_dma_memset;
-+      if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
-+              dma_dev->max_xor = iop_adma_get_max_xor();
-+              dma_dev->device_prep_dma_xor = iop_adma_prep_dma_xor;
-+      }
-+      if (dma_has_cap(DMA_ZERO_SUM, dma_dev->cap_mask))
-+              dma_dev->device_prep_dma_zero_sum =
-+                      iop_adma_prep_dma_zero_sum;
-+      if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask))
-+              dma_dev->device_prep_dma_interrupt =
-+                      iop_adma_prep_dma_interrupt;
-+
-+      iop_chan = kzalloc(sizeof(*iop_chan), GFP_KERNEL);
-+      if (!iop_chan) {
-+              ret = -ENOMEM;
-+              goto err_free_dma;
-+      }
-+      iop_chan->device = adev;
-+
-+      iop_chan->mmr_base = devm_ioremap(&pdev->dev, res->start,
-+                                      res->end - res->start);
-+      if (!iop_chan->mmr_base) {
-+              ret = -ENOMEM;
-+              goto err_free_iop_chan;
-+      }
-+      tasklet_init(&iop_chan->irq_tasklet, iop_adma_tasklet, (unsigned long)
-+              iop_chan);
-+
-+      /* clear errors before enabling interrupts */
-+      iop_adma_device_clear_err_status(iop_chan);
-+
-+      for (i = 0; i < 3; i++) {
-+              irq_handler_t handler[] = { iop_adma_eot_handler,
-+                                      iop_adma_eoc_handler,
-+                                      iop_adma_err_handler };
-+              int irq = platform_get_irq(pdev, i);
-+              if (irq < 0) {
-+                      ret = -ENXIO;
-+                      goto err_free_iop_chan;
-+              } else {
-+                      ret = devm_request_irq(&pdev->dev, irq,
-+                                      handler[i], 0, pdev->name, iop_chan);
-+                      if (ret)
-+                              goto err_free_iop_chan;
-+              }
-+      }
-+
-+      spin_lock_init(&iop_chan->lock);
-+      init_timer(&iop_chan->cleanup_watchdog);
-+      iop_chan->cleanup_watchdog.data = (unsigned long) iop_chan;
-+      iop_chan->cleanup_watchdog.function = iop_adma_tasklet;
-+      INIT_LIST_HEAD(&iop_chan->chain);
-+      INIT_LIST_HEAD(&iop_chan->all_slots);
-+      INIT_RCU_HEAD(&iop_chan->common.rcu);
-+      iop_chan->common.device = dma_dev;
-+      list_add_tail(&iop_chan->common.device_node, &dma_dev->channels);
-+
-+      if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
-+              ret = iop_adma_memcpy_self_test(adev);
-+              dev_dbg(&pdev->dev, "memcpy self test returned %d\n", ret);
-+              if (ret)
-+                      goto err_free_iop_chan;
-+      }
-+
-+      if (dma_has_cap(DMA_XOR, dma_dev->cap_mask) ||
-+              dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)) {
-+              ret = iop_adma_xor_zero_sum_self_test(adev);
-+              dev_dbg(&pdev->dev, "xor self test returned %d\n", ret);
-+              if (ret)
-+                      goto err_free_iop_chan;
-+      }
-+
-+      dev_printk(KERN_INFO, &pdev->dev, "Intel(R) IOP: "
-+        "( %s%s%s%s%s%s%s%s%s%s)\n",
-+        dma_has_cap(DMA_PQ_XOR, dma_dev->cap_mask) ? "pq_xor " : "",
-+        dma_has_cap(DMA_PQ_UPDATE, dma_dev->cap_mask) ? "pq_update " : "",
-+        dma_has_cap(DMA_PQ_ZERO_SUM, dma_dev->cap_mask) ? "pq_zero_sum " : "",
-+        dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
-+        dma_has_cap(DMA_DUAL_XOR, dma_dev->cap_mask) ? "dual_xor " : "",
-+        dma_has_cap(DMA_ZERO_SUM, dma_dev->cap_mask) ? "xor_zero_sum " : "",
-+        dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)  ? "fill " : "",
-+        dma_has_cap(DMA_MEMCPY_CRC32C, dma_dev->cap_mask) ? "cpy+crc " : "",
-+        dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
-+        dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
-+
-+      dma_async_device_register(dma_dev);
-+      goto out;
-+
-+ err_free_iop_chan:
-+      kfree(iop_chan);
-+ err_free_dma:
-+      dma_free_coherent(&adev->pdev->dev, plat_data->pool_size,
-+                      adev->dma_desc_pool_virt, adev->dma_desc_pool);
-+ err_free_adev:
-+      kfree(adev);
-+ out:
-+      return ret;
-+}
-+
-+static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
-+{
-+      struct iop_adma_desc_slot *sw_desc, *grp_start;
-+      dma_cookie_t cookie;
-+      int slot_cnt, slots_per_op;
-+
-+      dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
-+
-+      spin_lock_bh(&iop_chan->lock);
-+      slot_cnt = iop_chan_memcpy_slot_count(0, &slots_per_op);
-+      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-+      if (sw_desc) {
-+              grp_start = sw_desc->group_head;
-+
-+              list_splice_init(&sw_desc->group_list, &iop_chan->chain);
-+              sw_desc->async_tx.ack = 1;
-+              iop_desc_init_memcpy(grp_start, 0);
-+              iop_desc_set_byte_count(grp_start, iop_chan, 0);
-+              iop_desc_set_dest_addr(grp_start, iop_chan, 0);
-+              iop_desc_set_memcpy_src_addr(grp_start, 0);
-+
-+              cookie = iop_chan->common.cookie;
-+              cookie++;
-+              if (cookie <= 1)
-+                      cookie = 2;
-+
-+              /* initialize the completed cookie to be less than
-+               * the most recently used cookie
-+               */
-+              iop_chan->completed_cookie = cookie - 1;
-+              iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
-+
-+              /* channel should not be busy */
-+              BUG_ON(iop_chan_is_busy(iop_chan));
-+
-+              /* clear any prior error-status bits */
-+              iop_adma_device_clear_err_status(iop_chan);
-+
-+              /* disable operation */
-+              iop_chan_disable(iop_chan);
-+
-+              /* set the descriptor address */
-+              iop_chan_set_next_descriptor(iop_chan, sw_desc->phys);
-+
-+              /* 1/ don't add pre-chained descriptors
-+               * 2/ dummy read to flush next_desc write
-+               */
-+              BUG_ON(iop_desc_get_next_desc(sw_desc));
-+
-+              /* run the descriptor */
-+              iop_chan_enable(iop_chan);
-+      } else
-+              dev_printk(KERN_ERR, iop_chan->device->common.dev,
-+                       "failed to allocate null descriptor\n");
-+      spin_unlock_bh(&iop_chan->lock);
-+}
-+
-+static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
-+{
-+      struct iop_adma_desc_slot *sw_desc, *grp_start;
-+      dma_cookie_t cookie;
-+      int slot_cnt, slots_per_op;
-+
-+      dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
-+
-+      spin_lock_bh(&iop_chan->lock);
-+      slot_cnt = iop_chan_xor_slot_count(0, 2, &slots_per_op);
-+      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-+      if (sw_desc) {
-+              grp_start = sw_desc->group_head;
-+              list_splice_init(&sw_desc->group_list, &iop_chan->chain);
-+              sw_desc->async_tx.ack = 1;
-+              iop_desc_init_null_xor(grp_start, 2, 0);
-+              iop_desc_set_byte_count(grp_start, iop_chan, 0);
-+              iop_desc_set_dest_addr(grp_start, iop_chan, 0);
-+              iop_desc_set_xor_src_addr(grp_start, 0, 0);
-+              iop_desc_set_xor_src_addr(grp_start, 1, 0);
-+
-+              cookie = iop_chan->common.cookie;
-+              cookie++;
-+              if (cookie <= 1)
-+                      cookie = 2;
-+
-+              /* initialize the completed cookie to be less than
-+               * the most recently used cookie
-+               */
-+              iop_chan->completed_cookie = cookie - 1;
-+              iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
-+
-+              /* channel should not be busy */
-+              BUG_ON(iop_chan_is_busy(iop_chan));
-+
-+              /* clear any prior error-status bits */
-+              iop_adma_device_clear_err_status(iop_chan);
-+
-+              /* disable operation */
-+              iop_chan_disable(iop_chan);
-+
-+              /* set the descriptor address */
-+              iop_chan_set_next_descriptor(iop_chan, sw_desc->phys);
-+
-+              /* 1/ don't add pre-chained descriptors
-+               * 2/ dummy read to flush next_desc write
-+               */
-+              BUG_ON(iop_desc_get_next_desc(sw_desc));
-+
-+              /* run the descriptor */
-+              iop_chan_enable(iop_chan);
-+      } else
-+              dev_printk(KERN_ERR, iop_chan->device->common.dev,
-+                      "failed to allocate null descriptor\n");
-+      spin_unlock_bh(&iop_chan->lock);
-+}
-+
-+static struct platform_driver iop_adma_driver = {
-+      .probe          = iop_adma_probe,
-+      .remove         = iop_adma_remove,
-+      .driver         = {
-+              .owner  = THIS_MODULE,
-+              .name   = "iop-adma",
-+      },
-+};
-+
-+static int __init iop_adma_init (void)
-+{
-+      /* it's currently unsafe to unload this module */
-+      /* if forced, worst case is that rmmod hangs */
-+      __unsafe(THIS_MODULE);
-+
-+      return platform_driver_register(&iop_adma_driver);
-+}
-+
-+static void __exit iop_adma_exit (void)
-+{
-+      platform_driver_unregister(&iop_adma_driver);
-+      return;
-+}
-+
-+module_init(iop_adma_init);
-+module_exit(iop_adma_exit);
-+
-+MODULE_AUTHOR("Intel Corporation");
-+MODULE_DESCRIPTION("IOP ADMA Engine Driver");
-+MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/drivers/edac/edac_mc.c linux-2.6.22-590/drivers/edac/edac_mc.c
---- linux-2.6.22-570/drivers/edac/edac_mc.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/edac/edac_mc.c    2008-01-02 13:56:37.000000000 -0500
-@@ -1906,6 +1906,7 @@
- static int edac_kernel_thread(void *arg)
- {
-+      set_freezable();
-       while (!kthread_should_stop()) {
-               do_edac_check();
-diff -Nurb linux-2.6.22-570/drivers/firmware/dcdbas.c linux-2.6.22-590/drivers/firmware/dcdbas.c
---- linux-2.6.22-570/drivers/firmware/dcdbas.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/firmware/dcdbas.c 2008-01-02 13:56:37.000000000 -0500
-@@ -149,8 +149,9 @@
-       return count;
- }
--static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos,
--                           size_t count)
-+static ssize_t smi_data_read(struct kobject *kobj,
-+                           struct bin_attribute *bin_attr,
-+                           char *buf, loff_t pos, size_t count)
- {
-       size_t max_read;
-       ssize_t ret;
-@@ -170,8 +171,9 @@
-       return ret;
- }
--static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos,
--                            size_t count)
-+static ssize_t smi_data_write(struct kobject *kobj,
-+                            struct bin_attribute *bin_attr,
-+                            char *buf, loff_t pos, size_t count)
- {
-       ssize_t ret;
-diff -Nurb linux-2.6.22-570/drivers/firmware/dcdbas.h linux-2.6.22-590/drivers/firmware/dcdbas.h
---- linux-2.6.22-570/drivers/firmware/dcdbas.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/firmware/dcdbas.h 2008-01-02 13:56:37.000000000 -0500
-@@ -67,8 +67,7 @@
- #define DCDBAS_BIN_ATTR_RW(_name) \
- struct bin_attribute bin_attr_##_name = { \
-       .attr =  { .name = __stringify(_name), \
--                 .mode = 0600, \
--                 .owner = THIS_MODULE }, \
-+                 .mode = 0600 }, \
-       .read =  _name##_read, \
-       .write = _name##_write, \
- }
-diff -Nurb linux-2.6.22-570/drivers/firmware/dell_rbu.c linux-2.6.22-590/drivers/firmware/dell_rbu.c
---- linux-2.6.22-570/drivers/firmware/dell_rbu.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/firmware/dell_rbu.c       2008-01-02 13:56:37.000000000 -0500
-@@ -543,8 +543,9 @@
-       return ret_count;
- }
--static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
--      loff_t pos, size_t count)
-+static ssize_t read_rbu_data(struct kobject *kobj,
-+                           struct bin_attribute *bin_attr,
-+                           char *buffer, loff_t pos, size_t count)
- {
-       ssize_t ret_count = 0;
-@@ -591,8 +592,9 @@
-       spin_unlock(&rbu_data.lock);
- }
--static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
--      loff_t pos, size_t count)
-+static ssize_t read_rbu_image_type(struct kobject *kobj,
-+                                 struct bin_attribute *bin_attr,
-+                                 char *buffer, loff_t pos, size_t count)
- {
-       int size = 0;
-       if (!pos)
-@@ -600,8 +602,9 @@
-       return size;
- }
--static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
--      loff_t pos, size_t count)
-+static ssize_t write_rbu_image_type(struct kobject *kobj,
-+                                  struct bin_attribute *bin_attr,
-+                                  char *buffer, loff_t pos, size_t count)
- {
-       int rc = count;
-       int req_firm_rc = 0;
-@@ -660,8 +663,9 @@
-       return rc;
- }
--static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,
--      loff_t pos, size_t count)
-+static ssize_t read_rbu_packet_size(struct kobject *kobj,
-+                                  struct bin_attribute *bin_attr,
-+                                  char *buffer, loff_t pos, size_t count)
- {
-       int size = 0;
-       if (!pos) {
-@@ -672,8 +676,9 @@
-       return size;
- }
--static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,
--      loff_t pos, size_t count)
-+static ssize_t write_rbu_packet_size(struct kobject *kobj,
-+                                   struct bin_attribute *bin_attr,
-+                                   char *buffer, loff_t pos, size_t count)
- {
-       unsigned long temp;
-       spin_lock(&rbu_data.lock);
-@@ -687,18 +692,18 @@
- }
- static struct bin_attribute rbu_data_attr = {
--      .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
-+      .attr = {.name = "data", .mode = 0444},
-       .read = read_rbu_data,
- };
- static struct bin_attribute rbu_image_type_attr = {
--      .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
-+      .attr = {.name = "image_type", .mode = 0644},
-       .read = read_rbu_image_type,
-       .write = write_rbu_image_type,
- };
- static struct bin_attribute rbu_packet_size_attr = {
--      .attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644},
-+      .attr = {.name = "packet_size", .mode = 0644},
-       .read = read_rbu_packet_size,
-       .write = write_rbu_packet_size,
- };
-diff -Nurb linux-2.6.22-570/drivers/firmware/edd.c linux-2.6.22-590/drivers/firmware/edd.c
---- linux-2.6.22-570/drivers/firmware/edd.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/firmware/edd.c    2008-01-02 13:56:37.000000000 -0500
-@@ -74,7 +74,7 @@
- #define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \
- struct edd_attribute edd_attr_##_name = {     \
--      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },     \
-+      .attr = {.name = __stringify(_name), .mode = _mode },   \
-       .show   = _show,                                \
-       .test   = _test,                                \
- };
-diff -Nurb linux-2.6.22-570/drivers/firmware/efivars.c linux-2.6.22-590/drivers/firmware/efivars.c
---- linux-2.6.22-570/drivers/firmware/efivars.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/firmware/efivars.c        2008-01-02 13:56:37.000000000 -0500
-@@ -131,21 +131,21 @@
- #define EFI_ATTR(_name, _mode, _show, _store) \
- struct subsys_attribute efi_attr_##_name = { \
--      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
-+      .attr = {.name = __stringify(_name), .mode = _mode}, \
-       .show = _show, \
-       .store = _store, \
- };
- #define EFIVAR_ATTR(_name, _mode, _show, _store) \
- struct efivar_attribute efivar_attr_##_name = { \
--      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
-+      .attr = {.name = __stringify(_name), .mode = _mode}, \
-       .show = _show, \
-       .store = _store, \
- };
- #define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \
- struct subsys_attribute var_subsys_attr_##_name = { \
--      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
-+      .attr = {.name = __stringify(_name), .mode = _mode}, \
-       .show = _show, \
-       .store = _store, \
- };
-diff -Nurb linux-2.6.22-570/drivers/i2c/chips/eeprom.c linux-2.6.22-590/drivers/i2c/chips/eeprom.c
---- linux-2.6.22-570/drivers/i2c/chips/eeprom.c        2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/i2c/chips/eeprom.c        2008-01-02 13:56:37.000000000 -0500
-@@ -110,7 +110,8 @@
-       mutex_unlock(&data->update_lock);
- }
--static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr,
-+                         char *buf, loff_t off, size_t count)
- {
-       struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
-       struct eeprom_data *data = i2c_get_clientdata(client);
-@@ -150,7 +151,6 @@
-       .attr = {
-               .name = "eeprom",
-               .mode = S_IRUGO,
--              .owner = THIS_MODULE,
-       },
-       .size = EEPROM_SIZE,
-       .read = eeprom_read,
-diff -Nurb linux-2.6.22-570/drivers/i2c/chips/max6875.c linux-2.6.22-590/drivers/i2c/chips/max6875.c
---- linux-2.6.22-570/drivers/i2c/chips/max6875.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/i2c/chips/max6875.c       2008-01-02 13:56:37.000000000 -0500
-@@ -125,8 +125,9 @@
-       mutex_unlock(&data->update_lock);
- }
--static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off,
--                          size_t count)
-+static ssize_t max6875_read(struct kobject *kobj,
-+                          struct bin_attribute *bin_attr,
-+                          char *buf, loff_t off, size_t count)
- {
-       struct i2c_client *client = kobj_to_i2c_client(kobj);
-       struct max6875_data *data = i2c_get_clientdata(client);
-@@ -152,7 +153,6 @@
-       .attr = {
-               .name = "eeprom",
-               .mode = S_IRUGO,
--              .owner = THIS_MODULE,
-       },
-       .size = USER_EEPROM_SIZE,
-       .read = max6875_read,
-diff -Nurb linux-2.6.22-570/drivers/ieee1394/ieee1394_core.c linux-2.6.22-590/drivers/ieee1394/ieee1394_core.c
---- linux-2.6.22-570/drivers/ieee1394/ieee1394_core.c  2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/ieee1394/ieee1394_core.c  2008-01-02 13:56:37.000000000 -0500
-@@ -30,6 +30,7 @@
- #include <linux/moduleparam.h>
- #include <linux/bitops.h>
- #include <linux/kdev_t.h>
-+#include <linux/freezer.h>
- #include <linux/suspend.h>
- #include <linux/kthread.h>
- #include <linux/preempt.h>
-@@ -1133,8 +1134,6 @@
-       struct list_head tmp;
-       int may_schedule;
--      current->flags |= PF_NOFREEZE;
--
-       while (!kthread_should_stop()) {
-               INIT_LIST_HEAD(&tmp);
-diff -Nurb linux-2.6.22-570/drivers/ieee1394/nodemgr.c linux-2.6.22-590/drivers/ieee1394/nodemgr.c
---- linux-2.6.22-570/drivers/ieee1394/nodemgr.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/ieee1394/nodemgr.c        2008-01-02 13:56:37.000000000 -0500
-@@ -1669,6 +1669,7 @@
-       unsigned int g, generation = 0;
-       int i, reset_cycles = 0;
-+      set_freezable();
-       /* Setup our device-model entries */
-       nodemgr_create_host_dev_files(host);
-diff -Nurb linux-2.6.22-570/drivers/ieee1394/sbp2.c linux-2.6.22-590/drivers/ieee1394/sbp2.c
---- linux-2.6.22-570/drivers/ieee1394/sbp2.c   2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/ieee1394/sbp2.c   2008-01-02 13:56:37.000000000 -0500
-@@ -1505,69 +1505,6 @@
-       }
- }
--static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
--                                      struct sbp2_fwhost_info *hi,
--                                      struct sbp2_command_info *cmd,
--                                      struct scatterlist *sgpnt,
--                                      u32 orb_direction,
--                                      unsigned int scsi_request_bufflen,
--                                      void *scsi_request_buffer,
--                                      enum dma_data_direction dma_dir)
--{
--      cmd->dma_dir = dma_dir;
--      cmd->dma_size = scsi_request_bufflen;
--      cmd->dma_type = CMD_DMA_SINGLE;
--      cmd->cmd_dma = dma_map_single(hi->host->device.parent,
--                                    scsi_request_buffer,
--                                    cmd->dma_size, cmd->dma_dir);
--      orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
--      orb->misc |= ORB_SET_DIRECTION(orb_direction);
--
--      /* handle case where we get a command w/o s/g enabled
--       * (but check for transfers larger than 64K) */
--      if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
--
--              orb->data_descriptor_lo = cmd->cmd_dma;
--              orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
--
--      } else {
--              /* The buffer is too large. Turn this into page tables. */
--
--              struct sbp2_unrestricted_page_table *sg_element =
--                                              &cmd->scatter_gather_element[0];
--              u32 sg_count, sg_len;
--              dma_addr_t sg_addr;
--
--              orb->data_descriptor_lo = cmd->sge_dma;
--              orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
--
--              /* fill out our SBP-2 page tables; split up the large buffer */
--              sg_count = 0;
--              sg_len = scsi_request_bufflen;
--              sg_addr = cmd->cmd_dma;
--              while (sg_len) {
--                      sg_element[sg_count].segment_base_lo = sg_addr;
--                      if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
--                              sg_element[sg_count].length_segment_base_hi =
--                                      PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
--                              sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
--                              sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
--                      } else {
--                              sg_element[sg_count].length_segment_base_hi =
--                                      PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
--                              sg_len = 0;
--                      }
--                      sg_count++;
--              }
--
--              orb->misc |= ORB_SET_DATA_SIZE(sg_count);
--
--              sbp2util_cpu_to_be32_buffer(sg_element,
--                              (sizeof(struct sbp2_unrestricted_page_table)) *
--                              sg_count);
--      }
--}
--
- static void sbp2_create_command_orb(struct sbp2_lu *lu,
-                                   struct sbp2_command_info *cmd,
-                                   unchar *scsi_cmd,
-@@ -1611,13 +1548,9 @@
-               orb->data_descriptor_hi = 0x0;
-               orb->data_descriptor_lo = 0x0;
-               orb->misc |= ORB_SET_DIRECTION(1);
--      } else if (scsi_use_sg)
-+      } else
-               sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sgpnt,
-                                        orb_direction, dma_dir);
--      else
--              sbp2_prep_command_orb_no_sg(orb, hi, cmd, sgpnt, orb_direction,
--                                          scsi_request_bufflen,
--                                          scsi_request_buffer, dma_dir);
-       sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
-@@ -1706,15 +1639,15 @@
-                            void (*done)(struct scsi_cmnd *))
- {
-       unchar *scsi_cmd = (unchar *)SCpnt->cmnd;
--      unsigned int request_bufflen = SCpnt->request_bufflen;
-+      unsigned int request_bufflen = scsi_bufflen(SCpnt);
-       struct sbp2_command_info *cmd;
-       cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
-       if (!cmd)
-               return -EIO;
--      sbp2_create_command_orb(lu, cmd, scsi_cmd, SCpnt->use_sg,
--                              request_bufflen, SCpnt->request_buffer,
-+      sbp2_create_command_orb(lu, cmd, scsi_cmd, scsi_sg_count(SCpnt),
-+                              request_bufflen, scsi_sglist(SCpnt),
-                               SCpnt->sc_data_direction);
-       sbp2_link_orb_command(lu, cmd);
-diff -Nurb linux-2.6.22-570/drivers/infiniband/core/addr.c linux-2.6.22-590/drivers/infiniband/core/addr.c
---- linux-2.6.22-570/drivers/infiniband/core/addr.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/infiniband/core/addr.c    2008-01-02 13:56:37.000000000 -0500
-@@ -110,7 +110,7 @@
-       __be32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
-       int ret;
--      dev = ip_dev_find(ip);
-+      dev = ip_dev_find(&init_net, ip);
-       if (!dev)
-               return -EADDRNOTAVAIL;
-@@ -157,6 +157,7 @@
-       u32 dst_ip = dst_in->sin_addr.s_addr;
-       memset(&fl, 0, sizeof fl);
-+      fl.fl_net = &init_net;
-       fl.nl_u.ip4_u.daddr = dst_ip;
-       if (ip_route_output_key(&rt, &fl))
-               return;
-@@ -178,6 +179,7 @@
-       int ret;
-       memset(&fl, 0, sizeof fl);
-+      fl.fl_net = &init_net;
-       fl.nl_u.ip4_u.daddr = dst_ip;
-       fl.nl_u.ip4_u.saddr = src_ip;
-       ret = ip_route_output_key(&rt, &fl);
-@@ -262,7 +264,7 @@
-       __be32 dst_ip = dst_in->sin_addr.s_addr;
-       int ret;
--      dev = ip_dev_find(dst_ip);
-+      dev = ip_dev_find(&init_net, dst_ip);
-       if (!dev)
-               return -EADDRNOTAVAIL;
-diff -Nurb linux-2.6.22-570/drivers/infiniband/core/cma.c linux-2.6.22-590/drivers/infiniband/core/cma.c
---- linux-2.6.22-570/drivers/infiniband/core/cma.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/infiniband/core/cma.c     2008-01-02 13:56:37.000000000 -0500
-@@ -1267,7 +1267,7 @@
-       atomic_inc(&conn_id->dev_remove);
-       conn_id->state = CMA_CONNECT;
--      dev = ip_dev_find(iw_event->local_addr.sin_addr.s_addr);
-+      dev = ip_dev_find(&init_net, iw_event->local_addr.sin_addr.s_addr);
-       if (!dev) {
-               ret = -EADDRNOTAVAIL;
-               cma_enable_remove(conn_id);
-@@ -1880,18 +1880,18 @@
-       if (ret)
-               goto err1;
--      if (port > sysctl_local_port_range[1]) {
--              if (next_port != sysctl_local_port_range[0]) {
-+      if (port > init_net.sysctl_local_port_range[1]) {
-+              if (next_port != init_net.sysctl_local_port_range[0]) {
-                       idr_remove(ps, port);
--                      next_port = sysctl_local_port_range[0];
-+                      next_port = init_net.sysctl_local_port_range[0];
-                       goto retry;
-               }
-               ret = -EADDRNOTAVAIL;
-               goto err2;
-       }
--      if (port == sysctl_local_port_range[1])
--              next_port = sysctl_local_port_range[0];
-+      if (port == init_net.sysctl_local_port_range[1])
-+              next_port = init_net.sysctl_local_port_range[0];
-       else
-               next_port = port + 1;
-@@ -2774,8 +2774,9 @@
-       get_random_bytes(&next_port, sizeof next_port);
-       next_port = ((unsigned int) next_port %
--                  (sysctl_local_port_range[1] - sysctl_local_port_range[0])) +
--                  sysctl_local_port_range[0];
-+                   (init_net.sysctl_local_port_range[1] - 
-+                    init_net.sysctl_local_port_range[0])) +
-+                  init_net.sysctl_local_port_range[0];
-       cma_wq = create_singlethread_workqueue("rdma_cm");
-       if (!cma_wq)
-               return -ENOMEM;
-diff -Nurb linux-2.6.22-570/drivers/infiniband/core/sysfs.c linux-2.6.22-590/drivers/infiniband/core/sysfs.c
---- linux-2.6.22-570/drivers/infiniband/core/sysfs.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/infiniband/core/sysfs.c   2008-01-02 13:56:37.000000000 -0500
-@@ -479,7 +479,6 @@
-               element->attr.attr.name  = element->name;
-               element->attr.attr.mode  = S_IRUGO;
--              element->attr.attr.owner = THIS_MODULE;
-               element->attr.show       = show;
-               element->index           = i;
-diff -Nurb linux-2.6.22-570/drivers/infiniband/ulp/iser/iscsi_iser.c linux-2.6.22-590/drivers/infiniband/ulp/iser/iscsi_iser.c
---- linux-2.6.22-570/drivers/infiniband/ulp/iser/iscsi_iser.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/infiniband/ulp/iser/iscsi_iser.c  2008-01-02 13:56:37.000000000 -0500
-@@ -134,19 +134,9 @@
- {
-       struct iscsi_iser_conn     *iser_conn  = ctask->conn->dd_data;
-       struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
--      struct scsi_cmnd  *sc = ctask->sc;
-       iser_ctask->command_sent = 0;
-       iser_ctask->iser_conn    = iser_conn;
--
--      if (sc->sc_data_direction == DMA_TO_DEVICE) {
--              BUG_ON(ctask->total_length == 0);
--
--              debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
--                         ctask->itt, ctask->total_length, ctask->imm_count,
--                         ctask->unsol_count);
--      }
--
-       iser_ctask_rdma_init(iser_ctask);
- }
-@@ -219,6 +209,14 @@
-       struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
-       int error = 0;
-+      if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {
-+              BUG_ON(scsi_bufflen(ctask->sc) == 0);
-+
-+              debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
-+                         ctask->itt, scsi_bufflen(ctask->sc),
-+                         ctask->imm_count, ctask->unsol_count);
-+      }
-+
-       debug_scsi("ctask deq [cid %d itt 0x%x]\n",
-                  conn->id, ctask->itt);
-@@ -375,6 +373,7 @@
- static struct iscsi_cls_session *
- iscsi_iser_session_create(struct iscsi_transport *iscsit,
-                        struct scsi_transport_template *scsit,
-+                       uint16_t cmds_max, uint16_t qdepth,
-                         uint32_t initial_cmdsn, uint32_t *hostno)
- {
-       struct iscsi_cls_session *cls_session;
-@@ -386,7 +385,13 @@
-       struct iscsi_iser_cmd_task *iser_ctask;
-       struct iser_desc *desc;
-+      /*
-+       * we do not support setting can_queue cmd_per_lun from userspace yet
-+       * because we preallocate so many resources
-+       */
-       cls_session = iscsi_session_setup(iscsit, scsit,
-+                                        ISCSI_DEF_XMIT_CMDS_MAX,
-+                                        ISCSI_MAX_CMD_PER_LUN,
-                                         sizeof(struct iscsi_iser_cmd_task),
-                                         sizeof(struct iser_desc),
-                                         initial_cmdsn, &hn);
-@@ -545,7 +550,7 @@
- static struct scsi_host_template iscsi_iser_sht = {
-       .name                   = "iSCSI Initiator over iSER, v." DRV_VER,
-       .queuecommand           = iscsi_queuecommand,
--      .can_queue              = ISCSI_XMIT_CMDS_MAX - 1,
-+      .can_queue              = ISCSI_DEF_XMIT_CMDS_MAX - 1,
-       .sg_tablesize           = ISCSI_ISER_SG_TABLESIZE,
-       .max_sectors            = 1024,
-       .cmd_per_lun            = ISCSI_MAX_CMD_PER_LUN,
-@@ -574,8 +579,12 @@
-                                 ISCSI_EXP_STATSN |
-                                 ISCSI_PERSISTENT_PORT |
-                                 ISCSI_PERSISTENT_ADDRESS |
--                                ISCSI_TARGET_NAME |
--                                ISCSI_TPGT,
-+                                ISCSI_TARGET_NAME | ISCSI_TPGT |
-+                                ISCSI_USERNAME | ISCSI_PASSWORD |
-+                                ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
-+      .host_param_mask        = ISCSI_HOST_HWADDRESS |
-+                                ISCSI_HOST_NETDEV_NAME |
-+                                ISCSI_HOST_INITIATOR_NAME,
-       .host_template          = &iscsi_iser_sht,
-       .conndata_size          = sizeof(struct iscsi_conn),
-       .max_lun                = ISCSI_ISER_MAX_LUN,
-@@ -592,6 +601,9 @@
-       .get_session_param      = iscsi_session_get_param,
-       .start_conn             = iscsi_iser_conn_start,
-       .stop_conn              = iscsi_conn_stop,
-+      /* iscsi host params */
-+      .get_host_param         = iscsi_host_get_param,
-+      .set_host_param         = iscsi_host_set_param,
-       /* IO */
-       .send_pdu               = iscsi_conn_send_pdu,
-       .get_stats              = iscsi_iser_conn_get_stats,
-diff -Nurb linux-2.6.22-570/drivers/infiniband/ulp/iser/iscsi_iser.h linux-2.6.22-590/drivers/infiniband/ulp/iser/iscsi_iser.h
---- linux-2.6.22-570/drivers/infiniband/ulp/iser/iscsi_iser.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/infiniband/ulp/iser/iscsi_iser.h  2008-01-02 13:56:37.000000000 -0500
-@@ -98,7 +98,7 @@
- #define ISER_MAX_TX_MISC_PDUS         6 /* NOOP_OUT(2), TEXT(1),         *
-                                          * SCSI_TMFUNC(2), LOGOUT(1) */
--#define ISER_QP_MAX_RECV_DTOS         (ISCSI_XMIT_CMDS_MAX + \
-+#define ISER_QP_MAX_RECV_DTOS         (ISCSI_DEF_XMIT_CMDS_MAX + \
-                                       ISER_MAX_RX_MISC_PDUS    +  \
-                                       ISER_MAX_TX_MISC_PDUS)
-@@ -110,7 +110,7 @@
- #define ISER_INFLIGHT_DATAOUTS                8
--#define ISER_QP_MAX_REQ_DTOS          (ISCSI_XMIT_CMDS_MAX *    \
-+#define ISER_QP_MAX_REQ_DTOS          (ISCSI_DEF_XMIT_CMDS_MAX *    \
-                                       (1 + ISER_INFLIGHT_DATAOUTS) + \
-                                       ISER_MAX_TX_MISC_PDUS        + \
-                                       ISER_MAX_RX_MISC_PDUS)
-diff -Nurb linux-2.6.22-570/drivers/infiniband/ulp/iser/iser_initiator.c linux-2.6.22-590/drivers/infiniband/ulp/iser/iser_initiator.c
---- linux-2.6.22-570/drivers/infiniband/ulp/iser/iser_initiator.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/infiniband/ulp/iser/iser_initiator.c      2008-01-02 13:56:37.000000000 -0500
-@@ -351,18 +351,12 @@
-       else
-               data_buf = &iser_ctask->data[ISER_DIR_OUT];
--      if (sc->use_sg) { /* using a scatter list */
--              data_buf->buf  = sc->request_buffer;
--              data_buf->size = sc->use_sg;
--      } else if (sc->request_bufflen) {
--              /* using a single buffer - convert it into one entry SG */
--              sg_init_one(&data_buf->sg_single,
--                          sc->request_buffer, sc->request_bufflen);
--              data_buf->buf   = &data_buf->sg_single;
--              data_buf->size  = 1;
-+      if (scsi_sg_count(sc)) { /* using a scatter list */
-+              data_buf->buf  = scsi_sglist(sc);
-+              data_buf->size = scsi_sg_count(sc);
-       }
--      data_buf->data_len = sc->request_bufflen;
-+      data_buf->data_len = scsi_bufflen(sc);
-       if (hdr->flags & ISCSI_FLAG_CMD_READ) {
-               err = iser_prepare_read_cmd(ctask, edtl);
-diff -Nurb linux-2.6.22-570/drivers/infiniband/ulp/iser/iser_verbs.c linux-2.6.22-590/drivers/infiniband/ulp/iser/iser_verbs.c
---- linux-2.6.22-570/drivers/infiniband/ulp/iser/iser_verbs.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/infiniband/ulp/iser/iser_verbs.c  2008-01-02 13:56:37.000000000 -0500
-@@ -155,8 +155,8 @@
-       params.max_pages_per_fmr = ISCSI_ISER_SG_TABLESIZE + 1;
-       /* make the pool size twice the max number of SCSI commands *
-        * the ML is expected to queue, watermark for unmap at 50%  */
--      params.pool_size         = ISCSI_XMIT_CMDS_MAX * 2;
--      params.dirty_watermark   = ISCSI_XMIT_CMDS_MAX;
-+      params.pool_size         = ISCSI_DEF_XMIT_CMDS_MAX * 2;
-+      params.dirty_watermark   = ISCSI_DEF_XMIT_CMDS_MAX;
-       params.cache             = 0;
-       params.flush_function    = NULL;
-       params.access            = (IB_ACCESS_LOCAL_WRITE  |
-diff -Nurb linux-2.6.22-570/drivers/infiniband/ulp/srp/ib_srp.c linux-2.6.22-590/drivers/infiniband/ulp/srp/ib_srp.c
---- linux-2.6.22-570/drivers/infiniband/ulp/srp/ib_srp.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/infiniband/ulp/srp/ib_srp.c       2008-01-02 13:56:37.000000000 -0500
-@@ -455,10 +455,7 @@
-                          struct srp_target_port *target,
-                          struct srp_request *req)
- {
--      struct scatterlist *scat;
--      int nents;
--
--      if (!scmnd->request_buffer ||
-+      if (!scsi_sglist(scmnd) ||
-           (scmnd->sc_data_direction != DMA_TO_DEVICE &&
-            scmnd->sc_data_direction != DMA_FROM_DEVICE))
-               return;
-@@ -468,20 +465,8 @@
-               req->fmr = NULL;
-       }
--      /*
--       * This handling of non-SG commands can be killed when the
--       * SCSI midlayer no longer generates non-SG commands.
--       */
--      if (likely(scmnd->use_sg)) {
--              nents = scmnd->use_sg;
--              scat  = scmnd->request_buffer;
--      } else {
--              nents = 1;
--              scat  = &req->fake_sg;
--      }
--
--      ib_dma_unmap_sg(target->srp_host->dev->dev, scat, nents,
--                      scmnd->sc_data_direction);
-+      ib_dma_unmap_sg(target->srp_host->dev->dev, scsi_sglist(scmnd),
-+                      scsi_sg_count(scmnd), scmnd->sc_data_direction);
- }
- static void srp_remove_req(struct srp_target_port *target, struct srp_request *req)
-@@ -595,6 +580,7 @@
-       int ret;
-       struct srp_device *dev = target->srp_host->dev;
-       struct ib_device *ibdev = dev->dev;
-+      struct scatterlist *sg;
-       if (!dev->fmr_pool)
-               return -ENODEV;
-@@ -604,16 +590,16 @@
-               return -EINVAL;
-       len = page_cnt = 0;
--      for (i = 0; i < sg_cnt; ++i) {
--              unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]);
-+      scsi_for_each_sg(req->scmnd, sg, sg_cnt, i) {
-+              unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
--              if (ib_sg_dma_address(ibdev, &scat[i]) & ~dev->fmr_page_mask) {
-+              if (ib_sg_dma_address(ibdev, sg) & ~dev->fmr_page_mask) {
-                       if (i > 0)
-                               return -EINVAL;
-                       else
-                               ++page_cnt;
-               }
--              if ((ib_sg_dma_address(ibdev, &scat[i]) + dma_len) &
-+              if ((ib_sg_dma_address(ibdev, sg) + dma_len) &
-                   ~dev->fmr_page_mask) {
-                       if (i < sg_cnt - 1)
-                               return -EINVAL;
-@@ -633,12 +619,12 @@
-               return -ENOMEM;
-       page_cnt = 0;
--      for (i = 0; i < sg_cnt; ++i) {
--              unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]);
-+      scsi_for_each_sg(req->scmnd, sg, sg_cnt, i) {
-+              unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
-               for (j = 0; j < dma_len; j += dev->fmr_page_size)
-                       dma_pages[page_cnt++] =
--                              (ib_sg_dma_address(ibdev, &scat[i]) &
-+                              (ib_sg_dma_address(ibdev, sg) &
-                                dev->fmr_page_mask) + j;
-       }
-@@ -673,7 +659,7 @@
-       struct srp_device *dev;
-       struct ib_device *ibdev;
--      if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE)
-+      if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
-               return sizeof (struct srp_cmd);
-       if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
-@@ -683,18 +669,8 @@
-               return -EINVAL;
-       }
--      /*
--       * This handling of non-SG commands can be killed when the
--       * SCSI midlayer no longer generates non-SG commands.
--       */
--      if (likely(scmnd->use_sg)) {
--              nents = scmnd->use_sg;
--              scat  = scmnd->request_buffer;
--      } else {
--              nents = 1;
--              scat  = &req->fake_sg;
--              sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen);
--      }
-+      nents = scsi_sg_count(scmnd);
-+      scat  = scsi_sglist(scmnd);
-       dev = target->srp_host->dev;
-       ibdev = dev->dev;
-@@ -724,6 +700,7 @@
-                * descriptor.
-                */
-               struct srp_indirect_buf *buf = (void *) cmd->add_data;
-+              struct scatterlist *sg;
-               u32 datalen = 0;
-               int i;
-@@ -732,11 +709,11 @@
-                       sizeof (struct srp_indirect_buf) +
-                       count * sizeof (struct srp_direct_buf);
--              for (i = 0; i < count; ++i) {
--                      unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]);
-+              scsi_for_each_sg(scmnd, sg, count, i) {
-+                      unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
-                       buf->desc_list[i].va  =
--                              cpu_to_be64(ib_sg_dma_address(ibdev, &scat[i]));
-+                              cpu_to_be64(ib_sg_dma_address(ibdev, sg));
-                       buf->desc_list[i].key =
-                               cpu_to_be32(dev->mr->rkey);
-                       buf->desc_list[i].len = cpu_to_be32(dma_len);
-@@ -802,9 +779,9 @@
-               }
-               if (rsp->flags & (SRP_RSP_FLAG_DOOVER | SRP_RSP_FLAG_DOUNDER))
--                      scmnd->resid = be32_to_cpu(rsp->data_out_res_cnt);
-+                      scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt));
-               else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))
--                      scmnd->resid = be32_to_cpu(rsp->data_in_res_cnt);
-+                      scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
-               if (!req->tsk_mgmt) {
-                       scmnd->host_scribble = (void *) -1L;
-diff -Nurb linux-2.6.22-570/drivers/infiniband/ulp/srp/ib_srp.h linux-2.6.22-590/drivers/infiniband/ulp/srp/ib_srp.h
---- linux-2.6.22-570/drivers/infiniband/ulp/srp/ib_srp.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/infiniband/ulp/srp/ib_srp.h       2008-01-02 13:56:37.000000000 -0500
-@@ -106,11 +106,6 @@
-       struct srp_iu          *cmd;
-       struct srp_iu          *tsk_mgmt;
-       struct ib_pool_fmr     *fmr;
--      /*
--       * Fake scatterlist used when scmnd->use_sg==0.  Can be killed
--       * when the SCSI midlayer no longer generates non-SG commands.
--       */
--      struct scatterlist      fake_sg;
-       struct completion       done;
-       short                   index;
-       u8                      cmd_done;
-diff -Nurb linux-2.6.22-570/drivers/input/gameport/gameport.c linux-2.6.22-590/drivers/input/gameport/gameport.c
---- linux-2.6.22-570/drivers/input/gameport/gameport.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/input/gameport/gameport.c 2008-01-02 13:56:37.000000000 -0500
-@@ -445,6 +445,7 @@
- static int gameport_thread(void *nothing)
- {
-+      set_freezable();
-       do {
-               gameport_handle_event();
-               wait_event_interruptible(gameport_wait,
-diff -Nurb linux-2.6.22-570/drivers/input/mouse/psmouse.h linux-2.6.22-590/drivers/input/mouse/psmouse.h
---- linux-2.6.22-570/drivers/input/mouse/psmouse.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/input/mouse/psmouse.h     2008-01-02 13:56:37.000000000 -0500
-@@ -118,7 +118,6 @@
-               .attr   = {                                                     \
-                       .name   = __stringify(_name),                           \
-                       .mode   = _mode,                                        \
--                      .owner  = THIS_MODULE,                                  \
-               },                                                              \
-               .show   = psmouse_attr_show_helper,                             \
-               .store  = psmouse_attr_set_helper,                              \
-diff -Nurb linux-2.6.22-570/drivers/input/serio/serio.c linux-2.6.22-590/drivers/input/serio/serio.c
---- linux-2.6.22-570/drivers/input/serio/serio.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/input/serio/serio.c       2008-01-02 13:56:37.000000000 -0500
-@@ -384,6 +384,7 @@
- static int serio_thread(void *nothing)
- {
-+      set_freezable();
-       do {
-               serio_handle_event();
-               wait_event_interruptible(serio_wait,
-diff -Nurb linux-2.6.22-570/drivers/input/touchscreen/ucb1400_ts.c linux-2.6.22-590/drivers/input/touchscreen/ucb1400_ts.c
---- linux-2.6.22-570/drivers/input/touchscreen/ucb1400_ts.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/input/touchscreen/ucb1400_ts.c    2008-01-02 13:56:37.000000000 -0500
-@@ -292,6 +292,7 @@
-       sched_setscheduler(tsk, SCHED_FIFO, &param);
-+      set_freezable();
-       while (!kthread_should_stop()) {
-               unsigned int x, y, p;
-               long timeout;
-diff -Nurb linux-2.6.22-570/drivers/isdn/divert/divert_procfs.c linux-2.6.22-590/drivers/isdn/divert/divert_procfs.c
---- linux-2.6.22-570/drivers/isdn/divert/divert_procfs.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/isdn/divert/divert_procfs.c       2008-01-02 13:56:37.000000000 -0500
-@@ -17,6 +17,7 @@
- #include <linux/fs.h>
- #endif
- #include <linux/isdnif.h>
-+#include <net/net_namespace.h>
- #include "isdn_divert.h"
-@@ -284,12 +285,12 @@
-       init_waitqueue_head(&rd_queue);
- #ifdef CONFIG_PROC_FS
--      isdn_proc_entry = proc_mkdir("net/isdn", NULL);
-+      isdn_proc_entry = proc_mkdir("isdn", init_net.proc_net);
-       if (!isdn_proc_entry)
-               return (-1);
-       isdn_divert_entry = create_proc_entry("divert", S_IFREG | S_IRUGO, isdn_proc_entry);
-       if (!isdn_divert_entry) {
--              remove_proc_entry("net/isdn", NULL);
-+              remove_proc_entry("isdn", init_net.proc_net);
-               return (-1);
-       }
-       isdn_divert_entry->proc_fops = &isdn_fops; 
-@@ -309,7 +310,7 @@
- #ifdef CONFIG_PROC_FS
-       remove_proc_entry("divert", isdn_proc_entry);
--      remove_proc_entry("net/isdn", NULL);
-+      remove_proc_entry("isdn", init_net.proc_net);
- #endif        /* CONFIG_PROC_FS */
-       return (0);
-diff -Nurb linux-2.6.22-570/drivers/isdn/hardware/eicon/diva_didd.c linux-2.6.22-590/drivers/isdn/hardware/eicon/diva_didd.c
---- linux-2.6.22-570/drivers/isdn/hardware/eicon/diva_didd.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/isdn/hardware/eicon/diva_didd.c   2008-01-02 13:56:37.000000000 -0500
-@@ -15,6 +15,7 @@
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/proc_fs.h>
-+#include <net/net_namespace.h>
- #include "platform.h"
- #include "di_defs.h"
-@@ -86,7 +87,7 @@
- static int DIVA_INIT_FUNCTION create_proc(void)
- {
--      proc_net_eicon = proc_mkdir("net/eicon", NULL);
-+      proc_net_eicon = proc_mkdir("eicon", init_net.proc_net);
-       if (proc_net_eicon) {
-               if ((proc_didd =
-@@ -102,7 +103,7 @@
- static void remove_proc(void)
- {
-       remove_proc_entry(DRIVERLNAME, proc_net_eicon);
--      remove_proc_entry("net/eicon", NULL);
-+      remove_proc_entry("eicon", init_net.proc_net);
- }
- static int DIVA_INIT_FUNCTION divadidd_init(void)
-diff -Nurb linux-2.6.22-570/drivers/isdn/hysdn/hysdn_procconf.c linux-2.6.22-590/drivers/isdn/hysdn/hysdn_procconf.c
---- linux-2.6.22-570/drivers/isdn/hysdn/hysdn_procconf.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/isdn/hysdn/hysdn_procconf.c       2008-01-02 13:56:37.000000000 -0500
-@@ -392,7 +392,7 @@
-       hysdn_card *card;
-       unsigned char conf_name[20];
--      hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, proc_net);
-+      hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, init_net.proc_net);
-       if (!hysdn_proc_entry) {
-               printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n");
-               return (-1);
-@@ -437,5 +437,5 @@
-               card = card->next;      /* point to next card */
-       }
--      remove_proc_entry(PROC_SUBDIR_NAME, proc_net);
-+      remove_proc_entry(PROC_SUBDIR_NAME, init_net.proc_net);
- }
-diff -Nurb linux-2.6.22-570/drivers/macintosh/therm_adt746x.c linux-2.6.22-590/drivers/macintosh/therm_adt746x.c
---- linux-2.6.22-570/drivers/macintosh/therm_adt746x.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/macintosh/therm_adt746x.c 2008-01-02 13:56:37.000000000 -0500
-@@ -335,6 +335,7 @@
- {
-       struct thermostat* th = arg;
-+      set_freezable();
-       while(!kthread_should_stop()) {
-               try_to_freeze();
-               msleep_interruptible(2000);
-diff -Nurb linux-2.6.22-570/drivers/macintosh/therm_pm72.c linux-2.6.22-590/drivers/macintosh/therm_pm72.c
---- linux-2.6.22-570/drivers/macintosh/therm_pm72.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/macintosh/therm_pm72.c    2008-01-02 13:56:37.000000000 -0500
-@@ -1770,7 +1770,8 @@
-                               "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
-                               NULL };
--      return call_usermodehelper(critical_overtemp_path, argv, envp, 0);
-+      return call_usermodehelper(critical_overtemp_path,
-+                                 argv, envp, UMH_WAIT_EXEC);
- }
-diff -Nurb linux-2.6.22-570/drivers/macintosh/windfarm_core.c linux-2.6.22-590/drivers/macintosh/windfarm_core.c
---- linux-2.6.22-570/drivers/macintosh/windfarm_core.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/macintosh/windfarm_core.c 2008-01-02 13:56:37.000000000 -0500
-@@ -80,7 +80,8 @@
-                               "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
-                               NULL };
--      return call_usermodehelper(critical_overtemp_path, argv, envp, 0);
-+      return call_usermodehelper(critical_overtemp_path,
-+                                 argv, envp, UMH_WAIT_EXEC);
- }
- EXPORT_SYMBOL_GPL(wf_critical_overtemp);
-@@ -92,6 +93,7 @@
-       DBG("wf: thread started\n");
-+      set_freezable();
-       while(!kthread_should_stop()) {
-               if (time_after_eq(jiffies, next)) {
-                       wf_notify(WF_EVENT_TICK, NULL);
-@@ -212,7 +214,6 @@
-       list_add(&new_ct->link, &wf_controls);
-       new_ct->attr.attr.name = new_ct->name;
--      new_ct->attr.attr.owner = THIS_MODULE;
-       new_ct->attr.attr.mode = 0644;
-       new_ct->attr.show = wf_show_control;
-       new_ct->attr.store = wf_store_control;
-@@ -325,7 +326,6 @@
-       list_add(&new_sr->link, &wf_sensors);
-       new_sr->attr.attr.name = new_sr->name;
--      new_sr->attr.attr.owner = THIS_MODULE;
-       new_sr->attr.attr.mode = 0444;
-       new_sr->attr.show = wf_show_sensor;
-       new_sr->attr.store = NULL;
-diff -Nurb linux-2.6.22-570/drivers/md/Kconfig linux-2.6.22-590/drivers/md/Kconfig
---- linux-2.6.22-570/drivers/md/Kconfig        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/md/Kconfig        2008-01-02 13:56:37.000000000 -0500
-@@ -109,6 +109,8 @@
- config MD_RAID456
-       tristate "RAID-4/RAID-5/RAID-6 mode"
-       depends on BLK_DEV_MD
-+      select ASYNC_MEMCPY
-+      select ASYNC_XOR
-       ---help---
-         A RAID-5 set of N drives with a capacity of C MB per drive provides
-         the capacity of C * (N - 1) MB, and protects against a failure
-@@ -271,6 +273,11 @@
-       If unsure, say N.
-+config DM_NETLINK
-+      bool "DM netlink events (EXPERIMENTAL)"
-+      depends on BLK_DEV_DM && EXPERIMENTAL
-+      ---help---
-+      Generate netlink events for DM events.
- endmenu
- endif
-diff -Nurb linux-2.6.22-570/drivers/md/Makefile linux-2.6.22-590/drivers/md/Makefile
---- linux-2.6.22-570/drivers/md/Makefile       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/md/Makefile       2008-01-02 13:56:37.000000000 -0500
-@@ -17,7 +17,7 @@
- hostprogs-y   := mktables
- # Note: link order is important.  All raid personalities
--# and xor.o must come before md.o, as they each initialise 
-+# and must come before md.o, as they each initialise 
- # themselves, and md.o may use the personalities when it 
- # auto-initialised.
-@@ -25,7 +25,7 @@
- obj-$(CONFIG_MD_RAID0)                += raid0.o
- obj-$(CONFIG_MD_RAID1)                += raid1.o
- obj-$(CONFIG_MD_RAID10)               += raid10.o
--obj-$(CONFIG_MD_RAID456)      += raid456.o xor.o
-+obj-$(CONFIG_MD_RAID456)      += raid456.o
- obj-$(CONFIG_MD_MULTIPATH)    += multipath.o
- obj-$(CONFIG_MD_FAULTY)               += faulty.o
- obj-$(CONFIG_BLK_DEV_MD)      += md-mod.o
-@@ -46,6 +46,10 @@
- altivec_flags := -maltivec -mabi=altivec
- endif
-+ifeq ($(CONFIG_DM_NETLINK),y)
-+dm-mod-objs                   += dm-netlink.o
-+endif
-+
- targets += raid6int1.c
- $(obj)/raid6int1.c:   UNROLL := 1
- $(obj)/raid6int1.c:   $(src)/raid6int.uc $(src)/unroll.pl FORCE
-diff -Nurb linux-2.6.22-570/drivers/md/dm-netlink.c linux-2.6.22-590/drivers/md/dm-netlink.c
---- linux-2.6.22-570/drivers/md/dm-netlink.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/md/dm-netlink.c   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,103 @@
-+/*
-+ * Device Mapper Netlink Support (dm-netlink)
-+ *
-+ * 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.
-+ *
-+ * Copyright IBM Corporation, 2005, 2006
-+ *    Author: Mike Anderson <andmike@us.ibm.com>
-+ */
-+#include <linux/module.h>
-+#include <linux/mempool.h>
-+#include <linux/time.h>
-+#include <linux/jiffies.h>
-+#include <linux/security.h>
-+#include <net/sock.h>
-+#include <net/netlink.h>
-+
-+#include "dm.h"
-+#include "dm-netlink.h"
-+
-+#define DM_MSG_PREFIX "netlink"
-+
-+#define DM_EVENT_SKB_SIZE NLMSG_GOODSIZE
-+
-+struct dm_event_cache {
-+      struct kmem_cache *cache;
-+      unsigned skb_size;
-+};
-+
-+static struct dm_event_cache _dme_cache;
-+
-+static int dme_cache_init(struct dm_event_cache *dc, unsigned skb_size)
-+{
-+      dc->skb_size = skb_size;
-+
-+      dc->cache = KMEM_CACHE(dm_event, 0);
-+      if (!dc->cache)
-+              return -ENOMEM;
-+
-+      return 0;
-+}
-+
-+static void dme_cache_destroy(struct dm_event_cache *dc)
-+{
-+      kmem_cache_destroy(dc->cache);
-+}
-+
-+static void dme_cache_event_put(struct dm_event *evt)
-+{
-+      struct dm_event_cache *dc = evt->cdata;
-+
-+      kmem_cache_free(dc->cache, evt);
-+}
-+
-+static struct dm_event *dme_cache_event_get(struct dm_event_cache *dc,
-+                                          struct mapped_device *md)
-+{
-+      struct dm_event *evt;
-+
-+      evt = kmem_cache_alloc(dc->cache, GFP_ATOMIC);
-+      if (!evt)
-+              return NULL;
-+
-+      INIT_LIST_HEAD(&evt->elist);
-+      evt->cdata = dc;
-+      evt->md = md;
-+      evt->skb = alloc_skb(dc->skb_size, GFP_ATOMIC);
-+      if (!evt->skb)
-+              goto cache_err;
-+
-+      return evt;
-+
-+cache_err:
-+      dme_cache_event_put(evt);
-+      return NULL;
-+}
-+
-+int __init dm_netlink_init(void)
-+{
-+      int r;
-+
-+      r = dme_cache_init(&_dme_cache, DM_EVENT_SKB_SIZE);
-+      if (!r)
-+              DMINFO("version 1.0.0 loaded");
-+
-+      return r;
-+}
-+
-+void dm_netlink_exit(void)
-+{
-+      dme_cache_destroy(&_dme_cache);
-+}
-diff -Nurb linux-2.6.22-570/drivers/md/dm-netlink.h linux-2.6.22-590/drivers/md/dm-netlink.h
---- linux-2.6.22-570/drivers/md/dm-netlink.h   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/md/dm-netlink.h   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,50 @@
-+/*
-+ * Device Mapper Netlink Support
-+ *
-+ * 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.
-+ *
-+ * Copyright IBM Corporation, 2005, 2006
-+ *    Author: Mike Anderson <andmike@us.ibm.com>
-+ */
-+#ifndef DM_NETLINK_H
-+#define DM_NETLINK_H
-+
-+struct dm_event_cache;
-+struct mapped_device;
-+struct dm_event {
-+      struct dm_event_cache *cdata;
-+      struct mapped_device *md;
-+      struct sk_buff *skb;
-+      struct list_head elist;
-+};
-+
-+#ifdef CONFIG_DM_NETLINK
-+
-+int dm_netlink_init(void);
-+void dm_netlink_exit(void);
-+
-+#else /* CONFIG_DM_NETLINK */
-+
-+static inline int __init dm_netlink_init(void)
-+{
-+      return 0;
-+}
-+static inline void dm_netlink_exit(void)
-+{
-+}
-+
-+#endif        /* CONFIG_DM_NETLINK */
-+
-+#endif        /* DM_NETLINK_H */
-diff -Nurb linux-2.6.22-570/drivers/md/dm.c linux-2.6.22-590/drivers/md/dm.c
---- linux-2.6.22-570/drivers/md/dm.c   2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/drivers/md/dm.c   2008-01-02 13:56:37.000000000 -0500
-@@ -7,6 +7,7 @@
- #include "dm.h"
- #include "dm-bio-list.h"
-+#include "dm-netlink.h"
- #include <linux/init.h>
- #include <linux/module.h>
-@@ -180,6 +181,7 @@
-       dm_linear_init,
-       dm_stripe_init,
-       dm_interface_init,
-+      dm_netlink_init,
- };
- void (*_exits[])(void) = {
-@@ -188,6 +190,7 @@
-       dm_linear_exit,
-       dm_stripe_exit,
-       dm_interface_exit,
-+      dm_netlink_exit,
- };
- static int __init dm_init(void)
-diff -Nurb linux-2.6.22-570/drivers/md/md.c linux-2.6.22-590/drivers/md/md.c
---- linux-2.6.22-570/drivers/md/md.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/md/md.c   2008-01-02 13:56:37.000000000 -0500
-@@ -4642,7 +4642,6 @@
-        * many dirty RAID5 blocks.
-        */
--      current->flags |= PF_NOFREEZE;
-       allow_signal(SIGKILL);
-       while (!kthread_should_stop()) {
-@@ -5814,7 +5813,7 @@
-       }
- }
--module_init(md_init)
-+subsys_initcall(md_init);
- module_exit(md_exit)
- static int get_ro(char *buffer, struct kernel_param *kp)
-diff -Nurb linux-2.6.22-570/drivers/md/raid5.c linux-2.6.22-590/drivers/md/raid5.c
---- linux-2.6.22-570/drivers/md/raid5.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/md/raid5.c        2008-01-02 13:56:37.000000000 -0500
-@@ -52,6 +52,7 @@
- #include "raid6.h"
- #include <linux/raid/bitmap.h>
-+#include <linux/async_tx.h>
- /*
-  * Stripe cache
-@@ -80,7 +81,6 @@
- /*
-  * The following can be used to debug the driver
-  */
--#define RAID5_DEBUG   0
- #define RAID5_PARANOIA        1
- #if RAID5_PARANOIA && defined(CONFIG_SMP)
- # define CHECK_DEVLOCK() assert_spin_locked(&conf->device_lock)
-@@ -88,8 +88,7 @@
- # define CHECK_DEVLOCK()
- #endif
--#define PRINTK(x...) ((void)(RAID5_DEBUG && printk(x)))
--#if RAID5_DEBUG
-+#ifdef DEBUG
- #define inline
- #define __inline__
- #endif
-@@ -125,6 +124,7 @@
-                       }
-                       md_wakeup_thread(conf->mddev->thread);
-               } else {
-+                      BUG_ON(sh->ops.pending);
-                       if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-                               atomic_dec(&conf->preread_active_stripes);
-                               if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
-@@ -152,7 +152,8 @@
- static inline void remove_hash(struct stripe_head *sh)
- {
--      PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector);
-+      pr_debug("remove_hash(), stripe %llu\n",
-+              (unsigned long long)sh->sector);
-       hlist_del_init(&sh->hash);
- }
-@@ -161,7 +162,8 @@
- {
-       struct hlist_head *hp = stripe_hash(conf, sh->sector);
--      PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector);
-+      pr_debug("insert_hash(), stripe %llu\n",
-+              (unsigned long long)sh->sector);
-       CHECK_DEVLOCK();
-       hlist_add_head(&sh->hash, hp);
-@@ -224,9 +226,10 @@
-       BUG_ON(atomic_read(&sh->count) != 0);
-       BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
-+      BUG_ON(sh->ops.pending || sh->ops.ack || sh->ops.complete);
-       
-       CHECK_DEVLOCK();
--      PRINTK("init_stripe called, stripe %llu\n", 
-+      pr_debug("init_stripe called, stripe %llu\n",
-               (unsigned long long)sh->sector);
-       remove_hash(sh);
-@@ -240,11 +243,11 @@
-       for (i = sh->disks; i--; ) {
-               struct r5dev *dev = &sh->dev[i];
--              if (dev->toread || dev->towrite || dev->written ||
-+              if (dev->toread || dev->read || dev->towrite || dev->written ||
-                   test_bit(R5_LOCKED, &dev->flags)) {
--                      printk("sector=%llx i=%d %p %p %p %d\n",
-+                      printk(KERN_ERR "sector=%llx i=%d %p %p %p %p %d\n",
-                              (unsigned long long)sh->sector, i, dev->toread,
--                             dev->towrite, dev->written,
-+                             dev->read, dev->towrite, dev->written,
-                              test_bit(R5_LOCKED, &dev->flags));
-                       BUG();
-               }
-@@ -260,11 +263,11 @@
-       struct hlist_node *hn;
-       CHECK_DEVLOCK();
--      PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
-+      pr_debug("__find_stripe, sector %llu\n", (unsigned long long)sector);
-       hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
-               if (sh->sector == sector && sh->disks == disks)
-                       return sh;
--      PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
-+      pr_debug("__stripe %llu not in cache\n", (unsigned long long)sector);
-       return NULL;
- }
-@@ -276,7 +279,7 @@
- {
-       struct stripe_head *sh;
--      PRINTK("get_stripe, sector %llu\n", (unsigned long long)sector);
-+      pr_debug("get_stripe, sector %llu\n", (unsigned long long)sector);
-       spin_lock_irq(&conf->device_lock);
-@@ -324,179 +327,762 @@
-       return sh;
- }
--static int grow_one_stripe(raid5_conf_t *conf)
-+/* test_and_ack_op() ensures that we only dequeue an operation once */
-+#define test_and_ack_op(op, pend) \
-+do {                                                  \
-+      if (test_bit(op, &sh->ops.pending) &&           \
-+              !test_bit(op, &sh->ops.complete)) {     \
-+              if (test_and_set_bit(op, &sh->ops.ack)) \
-+                      clear_bit(op, &pend);           \
-+              else                                    \
-+                      ack++;                          \
-+      } else                                          \
-+              clear_bit(op, &pend);                   \
-+} while (0)
-+
-+/* find new work to run, do not resubmit work that is already
-+ * in flight
-+ */
-+static unsigned long get_stripe_work(struct stripe_head *sh)
-+{
-+      unsigned long pending;
-+      int ack = 0;
-+
-+      pending = sh->ops.pending;
-+
-+      test_and_ack_op(STRIPE_OP_BIOFILL, pending);
-+      test_and_ack_op(STRIPE_OP_COMPUTE_BLK, pending);
-+      test_and_ack_op(STRIPE_OP_PREXOR, pending);
-+      test_and_ack_op(STRIPE_OP_BIODRAIN, pending);
-+      test_and_ack_op(STRIPE_OP_POSTXOR, pending);
-+      test_and_ack_op(STRIPE_OP_CHECK, pending);
-+      if (test_and_clear_bit(STRIPE_OP_IO, &sh->ops.pending))
-+              ack++;
-+
-+      sh->ops.count -= ack;
-+      BUG_ON(sh->ops.count < 0);
-+
-+      return pending;
-+}
-+
-+static int
-+raid5_end_read_request(struct bio *bi, unsigned int bytes_done, int error);
-+static int
-+raid5_end_write_request (struct bio *bi, unsigned int bytes_done, int error);
-+
-+static void ops_run_io(struct stripe_head *sh)
- {
--      struct stripe_head *sh;
--      sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
--      if (!sh)
--              return 0;
--      memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
--      sh->raid_conf = conf;
--      spin_lock_init(&sh->lock);
-+      raid5_conf_t *conf = sh->raid_conf;
-+      int i, disks = sh->disks;
--      if (grow_buffers(sh, conf->raid_disks)) {
--              shrink_buffers(sh, conf->raid_disks);
--              kmem_cache_free(conf->slab_cache, sh);
--              return 0;
--      }
--      sh->disks = conf->raid_disks;
--      /* we just created an active stripe so... */
--      atomic_set(&sh->count, 1);
--      atomic_inc(&conf->active_stripes);
--      INIT_LIST_HEAD(&sh->lru);
--      release_stripe(sh);
--      return 1;
--}
-+      might_sleep();
--static int grow_stripes(raid5_conf_t *conf, int num)
--{
--      struct kmem_cache *sc;
--      int devs = conf->raid_disks;
-+      for (i = disks; i--; ) {
-+              int rw;
-+              struct bio *bi;
-+              mdk_rdev_t *rdev;
-+              if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
-+                      rw = WRITE;
-+              else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
-+                      rw = READ;
-+              else
-+                      continue;
--      sprintf(conf->cache_name[0], "raid5-%s", mdname(conf->mddev));
--      sprintf(conf->cache_name[1], "raid5-%s-alt", mdname(conf->mddev));
--      conf->active_name = 0;
--      sc = kmem_cache_create(conf->cache_name[conf->active_name],
--                             sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
--                             0, 0, NULL, NULL);
--      if (!sc)
--              return 1;
--      conf->slab_cache = sc;
--      conf->pool_size = devs;
--      while (num--)
--              if (!grow_one_stripe(conf))
--                      return 1;
--      return 0;
-+              bi = &sh->dev[i].req;
-+
-+              bi->bi_rw = rw;
-+              if (rw == WRITE)
-+                      bi->bi_end_io = raid5_end_write_request;
-+              else
-+                      bi->bi_end_io = raid5_end_read_request;
-+
-+              rcu_read_lock();
-+              rdev = rcu_dereference(conf->disks[i].rdev);
-+              if (rdev && test_bit(Faulty, &rdev->flags))
-+                      rdev = NULL;
-+              if (rdev)
-+                      atomic_inc(&rdev->nr_pending);
-+              rcu_read_unlock();
-+
-+              if (rdev) {
-+                      if (test_bit(STRIPE_SYNCING, &sh->state) ||
-+                              test_bit(STRIPE_EXPAND_SOURCE, &sh->state) ||
-+                              test_bit(STRIPE_EXPAND_READY, &sh->state))
-+                              md_sync_acct(rdev->bdev, STRIPE_SECTORS);
-+
-+                      bi->bi_bdev = rdev->bdev;
-+                      pr_debug("%s: for %llu schedule op %ld on disc %d\n",
-+                              __FUNCTION__, (unsigned long long)sh->sector,
-+                              bi->bi_rw, i);
-+                      atomic_inc(&sh->count);
-+                      bi->bi_sector = sh->sector + rdev->data_offset;
-+                      bi->bi_flags = 1 << BIO_UPTODATE;
-+                      bi->bi_vcnt = 1;
-+                      bi->bi_max_vecs = 1;
-+                      bi->bi_idx = 0;
-+                      bi->bi_io_vec = &sh->dev[i].vec;
-+                      bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
-+                      bi->bi_io_vec[0].bv_offset = 0;
-+                      bi->bi_size = STRIPE_SIZE;
-+                      bi->bi_next = NULL;
-+                      if (rw == WRITE &&
-+                          test_bit(R5_ReWrite, &sh->dev[i].flags))
-+                              atomic_add(STRIPE_SECTORS,
-+                                      &rdev->corrected_errors);
-+                      generic_make_request(bi);
-+              } else {
-+                      if (rw == WRITE)
-+                              set_bit(STRIPE_DEGRADED, &sh->state);
-+                      pr_debug("skip op %ld on disc %d for sector %llu\n",
-+                              bi->bi_rw, i, (unsigned long long)sh->sector);
-+                      clear_bit(R5_LOCKED, &sh->dev[i].flags);
-+                      set_bit(STRIPE_HANDLE, &sh->state);
-+              }
-+      }
- }
--#ifdef CONFIG_MD_RAID5_RESHAPE
--static int resize_stripes(raid5_conf_t *conf, int newsize)
-+static struct dma_async_tx_descriptor *
-+async_copy_data(int frombio, struct bio *bio, struct page *page,
-+      sector_t sector, struct dma_async_tx_descriptor *tx)
- {
--      /* Make all the stripes able to hold 'newsize' devices.
--       * New slots in each stripe get 'page' set to a new page.
--       *
--       * This happens in stages:
--       * 1/ create a new kmem_cache and allocate the required number of
--       *    stripe_heads.
--       * 2/ gather all the old stripe_heads and tranfer the pages across
--       *    to the new stripe_heads.  This will have the side effect of
--       *    freezing the array as once all stripe_heads have been collected,
--       *    no IO will be possible.  Old stripe heads are freed once their
--       *    pages have been transferred over, and the old kmem_cache is
--       *    freed when all stripes are done.
--       * 3/ reallocate conf->disks to be suitable bigger.  If this fails,
--       *    we simple return a failre status - no need to clean anything up.
--       * 4/ allocate new pages for the new slots in the new stripe_heads.
--       *    If this fails, we don't bother trying the shrink the
--       *    stripe_heads down again, we just leave them as they are.
--       *    As each stripe_head is processed the new one is released into
--       *    active service.
--       *
--       * Once step2 is started, we cannot afford to wait for a write,
--       * so we use GFP_NOIO allocations.
--       */
--      struct stripe_head *osh, *nsh;
--      LIST_HEAD(newstripes);
--      struct disk_info *ndisks;
--      int err = 0;
--      struct kmem_cache *sc;
-+      struct bio_vec *bvl;
-+      struct page *bio_page;
-       int i;
-+      int page_offset;
--      if (newsize <= conf->pool_size)
--              return 0; /* never bother to shrink */
-+      if (bio->bi_sector >= sector)
-+              page_offset = (signed)(bio->bi_sector - sector) * 512;
-+      else
-+              page_offset = (signed)(sector - bio->bi_sector) * -512;
-+      bio_for_each_segment(bvl, bio, i) {
-+              int len = bio_iovec_idx(bio, i)->bv_len;
-+              int clen;
-+              int b_offset = 0;
--      md_allow_write(conf->mddev);
-+              if (page_offset < 0) {
-+                      b_offset = -page_offset;
-+                      page_offset += b_offset;
-+                      len -= b_offset;
-+              }
--      /* Step 1 */
--      sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
--                             sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev),
--                             0, 0, NULL, NULL);
--      if (!sc)
--              return -ENOMEM;
-+              if (len > 0 && page_offset + len > STRIPE_SIZE)
-+                      clen = STRIPE_SIZE - page_offset;
-+              else
-+                      clen = len;
--      for (i = conf->max_nr_stripes; i; i--) {
--              nsh = kmem_cache_alloc(sc, GFP_KERNEL);
--              if (!nsh)
-+              if (clen > 0) {
-+                      b_offset += bio_iovec_idx(bio, i)->bv_offset;
-+                      bio_page = bio_iovec_idx(bio, i)->bv_page;
-+                      if (frombio)
-+                              tx = async_memcpy(page, bio_page, page_offset,
-+                                      b_offset, clen,
-+                                      ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_SRC,
-+                                      tx, NULL, NULL);
-+                      else
-+                              tx = async_memcpy(bio_page, page, b_offset,
-+                                      page_offset, clen,
-+                                      ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_DST,
-+                                      tx, NULL, NULL);
-+              }
-+              if (clen < len) /* hit end of page */
-                       break;
-+              page_offset +=  len;
-+      }
--              memset(nsh, 0, sizeof(*nsh) + (newsize-1)*sizeof(struct r5dev));
-+      return tx;
-+}
--              nsh->raid_conf = conf;
--              spin_lock_init(&nsh->lock);
-+static void ops_complete_biofill(void *stripe_head_ref)
-+{
-+      struct stripe_head *sh = stripe_head_ref;
-+      struct bio *return_bi = NULL, *bi;
-+      raid5_conf_t *conf = sh->raid_conf;
-+      int i, more_to_read = 0;
--              list_add(&nsh->lru, &newstripes);
--      }
--      if (i) {
--              /* didn't get enough, give up */
--              while (!list_empty(&newstripes)) {
--                      nsh = list_entry(newstripes.next, struct stripe_head, lru);
--                      list_del(&nsh->lru);
--                      kmem_cache_free(sc, nsh);
--              }
--              kmem_cache_destroy(sc);
--              return -ENOMEM;
--      }
--      /* Step 2 - Must use GFP_NOIO now.
--       * OK, we have enough stripes, start collecting inactive
--       * stripes and copying them over
-+      pr_debug("%s: stripe %llu\n", __FUNCTION__,
-+              (unsigned long long)sh->sector);
-+
-+      /* clear completed biofills */
-+      for (i = sh->disks; i--; ) {
-+              struct r5dev *dev = &sh->dev[i];
-+              /* check if this stripe has new incoming reads */
-+              if (dev->toread)
-+                      more_to_read++;
-+
-+              /* acknowledge completion of a biofill operation */
-+              /* and check if we need to reply to a read request
-        */
--      list_for_each_entry(nsh, &newstripes, lru) {
-+              if (test_bit(R5_Wantfill, &dev->flags) && !dev->toread) {
-+                      struct bio *rbi, *rbi2;
-+                      clear_bit(R5_Wantfill, &dev->flags);
-+
-+                      /* The access to dev->read is outside of the
-+                       * spin_lock_irq(&conf->device_lock), but is protected
-+                       * by the STRIPE_OP_BIOFILL pending bit
-+                       */
-+                      BUG_ON(!dev->read);
-+                      rbi = dev->read;
-+                      dev->read = NULL;
-+                      while (rbi && rbi->bi_sector <
-+                              dev->sector + STRIPE_SECTORS) {
-+                              rbi2 = r5_next_bio(rbi, dev->sector);
-               spin_lock_irq(&conf->device_lock);
--              wait_event_lock_irq(conf->wait_for_stripe,
--                                  !list_empty(&conf->inactive_list),
--                                  conf->device_lock,
--                                  unplug_slaves(conf->mddev)
--                      );
--              osh = get_free_stripe(conf);
-+                              if (--rbi->bi_phys_segments == 0) {
-+                                      rbi->bi_next = return_bi;
-+                                      return_bi = rbi;
-+                              }
-               spin_unlock_irq(&conf->device_lock);
--              atomic_set(&nsh->count, 1);
--              for(i=0; i<conf->pool_size; i++)
--                      nsh->dev[i].page = osh->dev[i].page;
--              for( ; i<newsize; i++)
--                      nsh->dev[i].page = NULL;
--              kmem_cache_free(conf->slab_cache, osh);
-+                              rbi = rbi2;
-       }
--      kmem_cache_destroy(conf->slab_cache);
-+              }
-+      }
-+      clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack);
-+      clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending);
--      /* Step 3.
--       * At this point, we are holding all the stripes so the array
--       * is completely stalled, so now is a good time to resize
--       * conf->disks.
--       */
--      ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO);
--      if (ndisks) {
--              for (i=0; i<conf->raid_disks; i++)
--                      ndisks[i] = conf->disks[i];
--              kfree(conf->disks);
--              conf->disks = ndisks;
--      } else
--              err = -ENOMEM;
-+      bi = return_bi;
-+      while (bi) {
-+              int bytes = bi->bi_size;
--      /* Step 4, return new stripes to service */
--      while(!list_empty(&newstripes)) {
--              nsh = list_entry(newstripes.next, struct stripe_head, lru);
--              list_del_init(&nsh->lru);
--              for (i=conf->raid_disks; i < newsize; i++)
--                      if (nsh->dev[i].page == NULL) {
--                              struct page *p = alloc_page(GFP_NOIO);
--                              nsh->dev[i].page = p;
--                              if (!p)
--                                      err = -ENOMEM;
--                      }
--              release_stripe(nsh);
-+              return_bi = bi->bi_next;
-+              bi->bi_next = NULL;
-+              bi->bi_size = 0;
-+              bi->bi_end_io(bi, bytes,
-+                      test_bit(BIO_UPTODATE, &bi->bi_flags) ? 0 : -EIO);
-+              bi = return_bi;
-       }
--      /* critical section pass, GFP_NOIO no longer needed */
--      conf->slab_cache = sc;
--      conf->active_name = 1-conf->active_name;
--      conf->pool_size = newsize;
--      return err;
-+      if (more_to_read)
-+              set_bit(STRIPE_HANDLE, &sh->state);
-+      release_stripe(sh);
- }
--#endif
--static int drop_one_stripe(raid5_conf_t *conf)
-+static void ops_run_biofill(struct stripe_head *sh)
- {
--      struct stripe_head *sh;
-+      struct dma_async_tx_descriptor *tx = NULL;
-+      raid5_conf_t *conf = sh->raid_conf;
-+      int i;
-+
-+      pr_debug("%s: stripe %llu\n", __FUNCTION__,
-+              (unsigned long long)sh->sector);
-+
-+      for (i = sh->disks; i--; ) {
-+              struct r5dev *dev = &sh->dev[i];
-+              if (test_bit(R5_Wantfill, &dev->flags)) {
-+                      struct bio *rbi;
-+                      spin_lock_irq(&conf->device_lock);
-+                      dev->read = rbi = dev->toread;
-+                      dev->toread = NULL;
-+                      spin_unlock_irq(&conf->device_lock);
-+                      while (rbi && rbi->bi_sector <
-+                              dev->sector + STRIPE_SECTORS) {
-+                              tx = async_copy_data(0, rbi, dev->page,
-+                                      dev->sector, tx);
-+                              rbi = r5_next_bio(rbi, dev->sector);
-+                      }
-+              }
-+      }
-+
-+      atomic_inc(&sh->count);
-+      async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,
-+              ops_complete_biofill, sh);
-+}
-+
-+static void ops_complete_compute5(void *stripe_head_ref)
-+{
-+      struct stripe_head *sh = stripe_head_ref;
-+      int target = sh->ops.target;
-+      struct r5dev *tgt = &sh->dev[target];
-+
-+      pr_debug("%s: stripe %llu\n", __FUNCTION__,
-+              (unsigned long long)sh->sector);
-+
-+      set_bit(R5_UPTODATE, &tgt->flags);
-+      BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
-+      clear_bit(R5_Wantcompute, &tgt->flags);
-+      set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
-+      set_bit(STRIPE_HANDLE, &sh->state);
-+      release_stripe(sh);
-+}
-+
-+static struct dma_async_tx_descriptor *
-+ops_run_compute5(struct stripe_head *sh, unsigned long pending)
-+{
-+      /* kernel stack size limits the total number of disks */
-+      int disks = sh->disks;
-+      struct page *xor_srcs[disks];
-+      int target = sh->ops.target;
-+      struct r5dev *tgt = &sh->dev[target];
-+      struct page *xor_dest = tgt->page;
-+      int count = 0;
-+      struct dma_async_tx_descriptor *tx;
-+      int i;
-+
-+      pr_debug("%s: stripe %llu block: %d\n",
-+              __FUNCTION__, (unsigned long long)sh->sector, target);
-+      BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
-+
-+      for (i = disks; i--; )
-+              if (i != target)
-+                      xor_srcs[count++] = sh->dev[i].page;
-+
-+      atomic_inc(&sh->count);
-+
-+      if (unlikely(count == 1))
-+              tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,
-+                      0, NULL, ops_complete_compute5, sh);
-+      else
-+              tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
-+                      ASYNC_TX_XOR_ZERO_DST, NULL,
-+                      ops_complete_compute5, sh);
-+
-+      /* ack now if postxor is not set to be run */
-+      if (tx && !test_bit(STRIPE_OP_POSTXOR, &pending))
-+              async_tx_ack(tx);
-+
-+      return tx;
-+}
-+
-+static void ops_complete_prexor(void *stripe_head_ref)
-+{
-+      struct stripe_head *sh = stripe_head_ref;
-+
-+      pr_debug("%s: stripe %llu\n", __FUNCTION__,
-+              (unsigned long long)sh->sector);
-+
-+      set_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
-+}
-+
-+static struct dma_async_tx_descriptor *
-+ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
-+{
-+      /* kernel stack size limits the total number of disks */
-+      int disks = sh->disks;
-+      struct page *xor_srcs[disks];
-+      int count = 0, pd_idx = sh->pd_idx, i;
-+
-+      /* existing parity data subtracted */
-+      struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
-+
-+      pr_debug("%s: stripe %llu\n", __FUNCTION__,
-+              (unsigned long long)sh->sector);
-+
-+      for (i = disks; i--; ) {
-+              struct r5dev *dev = &sh->dev[i];
-+              /* Only process blocks that are known to be uptodate */
-+              if (dev->towrite && test_bit(R5_Wantprexor, &dev->flags))
-+                      xor_srcs[count++] = dev->page;
-+      }
-+
-+      tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
-+              ASYNC_TX_DEP_ACK | ASYNC_TX_XOR_DROP_DST, tx,
-+              ops_complete_prexor, sh);
-+
-+      return tx;
-+}
-+
-+static struct dma_async_tx_descriptor *
-+ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
-+{
-+      int disks = sh->disks;
-+      int pd_idx = sh->pd_idx, i;
-+
-+      /* check if prexor is active which means only process blocks
-+       * that are part of a read-modify-write (Wantprexor)
-+       */
-+      int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
-+
-+      pr_debug("%s: stripe %llu\n", __FUNCTION__,
-+              (unsigned long long)sh->sector);
-+
-+      for (i = disks; i--; ) {
-+              struct r5dev *dev = &sh->dev[i];
-+              struct bio *chosen;
-+              int towrite;
-+
-+              towrite = 0;
-+              if (prexor) { /* rmw */
-+                      if (dev->towrite &&
-+                          test_bit(R5_Wantprexor, &dev->flags))
-+                              towrite = 1;
-+              } else { /* rcw */
-+                      if (i != pd_idx && dev->towrite &&
-+                              test_bit(R5_LOCKED, &dev->flags))
-+                              towrite = 1;
-+              }
-+
-+              if (towrite) {
-+                      struct bio *wbi;
-+
-+                      spin_lock(&sh->lock);
-+                      chosen = dev->towrite;
-+                      dev->towrite = NULL;
-+                      BUG_ON(dev->written);
-+                      wbi = dev->written = chosen;
-+                      spin_unlock(&sh->lock);
-+
-+                      while (wbi && wbi->bi_sector <
-+                              dev->sector + STRIPE_SECTORS) {
-+                              tx = async_copy_data(1, wbi, dev->page,
-+                                      dev->sector, tx);
-+                              wbi = r5_next_bio(wbi, dev->sector);
-+                      }
-+              }
-+      }
-+
-+      return tx;
-+}
-+
-+static void ops_complete_postxor(void *stripe_head_ref)
-+{
-+      struct stripe_head *sh = stripe_head_ref;
-+
-+      pr_debug("%s: stripe %llu\n", __FUNCTION__,
-+              (unsigned long long)sh->sector);
-+
-+      set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
-+      set_bit(STRIPE_HANDLE, &sh->state);
-+      release_stripe(sh);
-+}
-+
-+static void ops_complete_write(void *stripe_head_ref)
-+{
-+      struct stripe_head *sh = stripe_head_ref;
-+      int disks = sh->disks, i, pd_idx = sh->pd_idx;
-+
-+      pr_debug("%s: stripe %llu\n", __FUNCTION__,
-+              (unsigned long long)sh->sector);
-+
-+      for (i = disks; i--; ) {
-+              struct r5dev *dev = &sh->dev[i];
-+              if (dev->written || i == pd_idx)
-+                      set_bit(R5_UPTODATE, &dev->flags);
-+      }
-+
-+      set_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
-+      set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
-+
-+      set_bit(STRIPE_HANDLE, &sh->state);
-+      release_stripe(sh);
-+}
-+
-+static void
-+ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
-+{
-+      /* kernel stack size limits the total number of disks */
-+      int disks = sh->disks;
-+      struct page *xor_srcs[disks];
-+
-+      int count = 0, pd_idx = sh->pd_idx, i;
-+      struct page *xor_dest;
-+      int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
-+      unsigned long flags;
-+      dma_async_tx_callback callback;
-+
-+      pr_debug("%s: stripe %llu\n", __FUNCTION__,
-+              (unsigned long long)sh->sector);
-+
-+      /* check if prexor is active which means only process blocks
-+       * that are part of a read-modify-write (written)
-+       */
-+      if (prexor) {
-+              xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
-+              for (i = disks; i--; ) {
-+                      struct r5dev *dev = &sh->dev[i];
-+                      if (dev->written)
-+                              xor_srcs[count++] = dev->page;
-+              }
-+      } else {
-+              xor_dest = sh->dev[pd_idx].page;
-+              for (i = disks; i--; ) {
-+                      struct r5dev *dev = &sh->dev[i];
-+                      if (i != pd_idx)
-+                              xor_srcs[count++] = dev->page;
-+              }
-+      }
-+
-+      /* check whether this postxor is part of a write */
-+      callback = test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending) ?
-+              ops_complete_write : ops_complete_postxor;
-+
-+      /* 1/ if we prexor'd then the dest is reused as a source
-+       * 2/ if we did not prexor then we are redoing the parity
-+       * set ASYNC_TX_XOR_DROP_DST and ASYNC_TX_XOR_ZERO_DST
-+       * for the synchronous xor case
-+       */
-+      flags = ASYNC_TX_DEP_ACK | ASYNC_TX_ACK |
-+              (prexor ? ASYNC_TX_XOR_DROP_DST : ASYNC_TX_XOR_ZERO_DST);
-+
-+      atomic_inc(&sh->count);
-+
-+      if (unlikely(count == 1)) {
-+              flags &= ~(ASYNC_TX_XOR_DROP_DST | ASYNC_TX_XOR_ZERO_DST);
-+              tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,
-+                      flags, tx, callback, sh);
-+      } else
-+              tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
-+                      flags, tx, callback, sh);
-+}
-+
-+static void ops_complete_check(void *stripe_head_ref)
-+{
-+      struct stripe_head *sh = stripe_head_ref;
-+      int pd_idx = sh->pd_idx;
-+
-+      pr_debug("%s: stripe %llu\n", __FUNCTION__,
-+              (unsigned long long)sh->sector);
-+
-+      if (test_and_clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending) &&
-+              sh->ops.zero_sum_result == 0)
-+              set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-+
-+      set_bit(STRIPE_OP_CHECK, &sh->ops.complete);
-+      set_bit(STRIPE_HANDLE, &sh->state);
-+      release_stripe(sh);
-+}
-+
-+static void ops_run_check(struct stripe_head *sh)
-+{
-+      /* kernel stack size limits the total number of disks */
-+      int disks = sh->disks;
-+      struct page *xor_srcs[disks];
-+      struct dma_async_tx_descriptor *tx;
-+
-+      int count = 0, pd_idx = sh->pd_idx, i;
-+      struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
-+
-+      pr_debug("%s: stripe %llu\n", __FUNCTION__,
-+              (unsigned long long)sh->sector);
-+
-+      for (i = disks; i--; ) {
-+              struct r5dev *dev = &sh->dev[i];
-+              if (i != pd_idx)
-+                      xor_srcs[count++] = dev->page;
-+      }
-+
-+      tx = async_xor_zero_sum(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
-+              &sh->ops.zero_sum_result, 0, NULL, NULL, NULL);
-+
-+      if (tx)
-+              set_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
-+      else
-+              clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
-+
-+      atomic_inc(&sh->count);
-+      tx = async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,
-+              ops_complete_check, sh);
-+}
-+
-+static void raid5_run_ops(struct stripe_head *sh, unsigned long pending)
-+{
-+      int overlap_clear = 0, i, disks = sh->disks;
-+      struct dma_async_tx_descriptor *tx = NULL;
-+
-+      if (test_bit(STRIPE_OP_BIOFILL, &pending)) {
-+              ops_run_biofill(sh);
-+              overlap_clear++;
-+      }
-+
-+      if (test_bit(STRIPE_OP_COMPUTE_BLK, &pending))
-+              tx = ops_run_compute5(sh, pending);
-+
-+      if (test_bit(STRIPE_OP_PREXOR, &pending))
-+              tx = ops_run_prexor(sh, tx);
-+
-+      if (test_bit(STRIPE_OP_BIODRAIN, &pending)) {
-+              tx = ops_run_biodrain(sh, tx);
-+              overlap_clear++;
-+      }
-+
-+      if (test_bit(STRIPE_OP_POSTXOR, &pending))
-+              ops_run_postxor(sh, tx);
-+
-+      if (test_bit(STRIPE_OP_CHECK, &pending))
-+              ops_run_check(sh);
-+
-+      if (test_bit(STRIPE_OP_IO, &pending))
-+              ops_run_io(sh);
-+
-+      if (overlap_clear)
-+              for (i = disks; i--; ) {
-+                      struct r5dev *dev = &sh->dev[i];
-+                      if (test_and_clear_bit(R5_Overlap, &dev->flags))
-+                              wake_up(&sh->raid_conf->wait_for_overlap);
-+              }
-+}
-+
-+static int grow_one_stripe(raid5_conf_t *conf)
-+{
-+      struct stripe_head *sh;
-+      sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
-+      if (!sh)
-+              return 0;
-+      memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
-+      sh->raid_conf = conf;
-+      spin_lock_init(&sh->lock);
-+
-+      if (grow_buffers(sh, conf->raid_disks)) {
-+              shrink_buffers(sh, conf->raid_disks);
-+              kmem_cache_free(conf->slab_cache, sh);
-+              return 0;
-+      }
-+      sh->disks = conf->raid_disks;
-+      /* we just created an active stripe so... */
-+      atomic_set(&sh->count, 1);
-+      atomic_inc(&conf->active_stripes);
-+      INIT_LIST_HEAD(&sh->lru);
-+      release_stripe(sh);
-+      return 1;
-+}
-+
-+static int grow_stripes(raid5_conf_t *conf, int num)
-+{
-+      struct kmem_cache *sc;
-+      int devs = conf->raid_disks;
-+
-+      sprintf(conf->cache_name[0], "raid5-%s", mdname(conf->mddev));
-+      sprintf(conf->cache_name[1], "raid5-%s-alt", mdname(conf->mddev));
-+      conf->active_name = 0;
-+      sc = kmem_cache_create(conf->cache_name[conf->active_name],
-+                             sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
-+                             0, 0, NULL, NULL);
-+      if (!sc)
-+              return 1;
-+      conf->slab_cache = sc;
-+      conf->pool_size = devs;
-+      while (num--)
-+              if (!grow_one_stripe(conf))
-+                      return 1;
-+      return 0;
-+}
-+
-+#ifdef CONFIG_MD_RAID5_RESHAPE
-+static int resize_stripes(raid5_conf_t *conf, int newsize)
-+{
-+      /* Make all the stripes able to hold 'newsize' devices.
-+       * New slots in each stripe get 'page' set to a new page.
-+       *
-+       * This happens in stages:
-+       * 1/ create a new kmem_cache and allocate the required number of
-+       *    stripe_heads.
-+       * 2/ gather all the old stripe_heads and tranfer the pages across
-+       *    to the new stripe_heads.  This will have the side effect of
-+       *    freezing the array as once all stripe_heads have been collected,
-+       *    no IO will be possible.  Old stripe heads are freed once their
-+       *    pages have been transferred over, and the old kmem_cache is
-+       *    freed when all stripes are done.
-+       * 3/ reallocate conf->disks to be suitable bigger.  If this fails,
-+       *    we simple return a failre status - no need to clean anything up.
-+       * 4/ allocate new pages for the new slots in the new stripe_heads.
-+       *    If this fails, we don't bother trying the shrink the
-+       *    stripe_heads down again, we just leave them as they are.
-+       *    As each stripe_head is processed the new one is released into
-+       *    active service.
-+       *
-+       * Once step2 is started, we cannot afford to wait for a write,
-+       * so we use GFP_NOIO allocations.
-+       */
-+      struct stripe_head *osh, *nsh;
-+      LIST_HEAD(newstripes);
-+      struct disk_info *ndisks;
-+      int err = 0;
-+      struct kmem_cache *sc;
-+      int i;
-+
-+      if (newsize <= conf->pool_size)
-+              return 0; /* never bother to shrink */
-+
-+      md_allow_write(conf->mddev);
-+
-+      /* Step 1 */
-+      sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
-+                             sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev),
-+                             0, 0, NULL, NULL);
-+      if (!sc)
-+              return -ENOMEM;
-+
-+      for (i = conf->max_nr_stripes; i; i--) {
-+              nsh = kmem_cache_alloc(sc, GFP_KERNEL);
-+              if (!nsh)
-+                      break;
-+
-+              memset(nsh, 0, sizeof(*nsh) + (newsize-1)*sizeof(struct r5dev));
-+
-+              nsh->raid_conf = conf;
-+              spin_lock_init(&nsh->lock);
-+
-+              list_add(&nsh->lru, &newstripes);
-+      }
-+      if (i) {
-+              /* didn't get enough, give up */
-+              while (!list_empty(&newstripes)) {
-+                      nsh = list_entry(newstripes.next, struct stripe_head, lru);
-+                      list_del(&nsh->lru);
-+                      kmem_cache_free(sc, nsh);
-+              }
-+              kmem_cache_destroy(sc);
-+              return -ENOMEM;
-+      }
-+      /* Step 2 - Must use GFP_NOIO now.
-+       * OK, we have enough stripes, start collecting inactive
-+       * stripes and copying them over
-+       */
-+      list_for_each_entry(nsh, &newstripes, lru) {
-+              spin_lock_irq(&conf->device_lock);
-+              wait_event_lock_irq(conf->wait_for_stripe,
-+                                  !list_empty(&conf->inactive_list),
-+                                  conf->device_lock,
-+                                  unplug_slaves(conf->mddev)
-+                      );
-+              osh = get_free_stripe(conf);
-+              spin_unlock_irq(&conf->device_lock);
-+              atomic_set(&nsh->count, 1);
-+              for(i=0; i<conf->pool_size; i++)
-+                      nsh->dev[i].page = osh->dev[i].page;
-+              for( ; i<newsize; i++)
-+                      nsh->dev[i].page = NULL;
-+              kmem_cache_free(conf->slab_cache, osh);
-+      }
-+      kmem_cache_destroy(conf->slab_cache);
-+
-+      /* Step 3.
-+       * At this point, we are holding all the stripes so the array
-+       * is completely stalled, so now is a good time to resize
-+       * conf->disks.
-+       */
-+      ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO);
-+      if (ndisks) {
-+              for (i=0; i<conf->raid_disks; i++)
-+                      ndisks[i] = conf->disks[i];
-+              kfree(conf->disks);
-+              conf->disks = ndisks;
-+      } else
-+              err = -ENOMEM;
-+
-+      /* Step 4, return new stripes to service */
-+      while(!list_empty(&newstripes)) {
-+              nsh = list_entry(newstripes.next, struct stripe_head, lru);
-+              list_del_init(&nsh->lru);
-+              for (i=conf->raid_disks; i < newsize; i++)
-+                      if (nsh->dev[i].page == NULL) {
-+                              struct page *p = alloc_page(GFP_NOIO);
-+                              nsh->dev[i].page = p;
-+                              if (!p)
-+                                      err = -ENOMEM;
-+                      }
-+              release_stripe(nsh);
-+      }
-+      /* critical section pass, GFP_NOIO no longer needed */
-+
-+      conf->slab_cache = sc;
-+      conf->active_name = 1-conf->active_name;
-+      conf->pool_size = newsize;
-+      return err;
-+}
-+#endif
-+
-+static int drop_one_stripe(raid5_conf_t *conf)
-+{
-+      struct stripe_head *sh;
-       spin_lock_irq(&conf->device_lock);
-       sh = get_free_stripe(conf);
-@@ -537,7 +1123,7 @@
-               if (bi == &sh->dev[i].req)
-                       break;
--      PRINTK("end_read_request %llu/%d, count: %d, uptodate %d.\n", 
-+      pr_debug("end_read_request %llu/%d, count: %d, uptodate %d.\n",
-               (unsigned long long)sh->sector, i, atomic_read(&sh->count), 
-               uptodate);
-       if (i == disks) {
-@@ -613,7 +1199,7 @@
-               if (bi == &sh->dev[i].req)
-                       break;
--      PRINTK("end_write_request %llu/%d, count %d, uptodate: %d.\n", 
-+      pr_debug("end_write_request %llu/%d, count %d, uptodate: %d.\n",
-               (unsigned long long)sh->sector, i, atomic_read(&sh->count),
-               uptodate);
-       if (i == disks) {
-@@ -658,7 +1244,7 @@
- {
-       char b[BDEVNAME_SIZE];
-       raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
--      PRINTK("raid5: error called\n");
-+      pr_debug("raid5: error called\n");
-       if (!test_bit(Faulty, &rdev->flags)) {
-               set_bit(MD_CHANGE_DEVS, &mddev->flags);
-@@ -918,135 +1504,11 @@
- #define check_xor()   do {                                            \
-                          if (count == MAX_XOR_BLOCKS) {               \
--                              xor_block(count, STRIPE_SIZE, ptr);     \
--                              count = 1;                              \
-+                              xor_blocks(count, STRIPE_SIZE, dest, ptr);\
-+                              count = 0;                                \
-                          }                                            \
-                       } while(0)
--
--static void compute_block(struct stripe_head *sh, int dd_idx)
--{
--      int i, count, disks = sh->disks;
--      void *ptr[MAX_XOR_BLOCKS], *p;
--
--      PRINTK("compute_block, stripe %llu, idx %d\n", 
--              (unsigned long long)sh->sector, dd_idx);
--
--      ptr[0] = page_address(sh->dev[dd_idx].page);
--      memset(ptr[0], 0, STRIPE_SIZE);
--      count = 1;
--      for (i = disks ; i--; ) {
--              if (i == dd_idx)
--                      continue;
--              p = page_address(sh->dev[i].page);
--              if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
--                      ptr[count++] = p;
--              else
--                      printk(KERN_ERR "compute_block() %d, stripe %llu, %d"
--                              " not present\n", dd_idx,
--                              (unsigned long long)sh->sector, i);
--
--              check_xor();
--      }
--      if (count != 1)
--              xor_block(count, STRIPE_SIZE, ptr);
--      set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
--}
--
--static void compute_parity5(struct stripe_head *sh, int method)
--{
--      raid5_conf_t *conf = sh->raid_conf;
--      int i, pd_idx = sh->pd_idx, disks = sh->disks, count;
--      void *ptr[MAX_XOR_BLOCKS];
--      struct bio *chosen;
--
--      PRINTK("compute_parity5, stripe %llu, method %d\n",
--              (unsigned long long)sh->sector, method);
--
--      count = 1;
--      ptr[0] = page_address(sh->dev[pd_idx].page);
--      switch(method) {
--      case READ_MODIFY_WRITE:
--              BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags));
--              for (i=disks ; i-- ;) {
--                      if (i==pd_idx)
--                              continue;
--                      if (sh->dev[i].towrite &&
--                          test_bit(R5_UPTODATE, &sh->dev[i].flags)) {
--                              ptr[count++] = page_address(sh->dev[i].page);
--                              chosen = sh->dev[i].towrite;
--                              sh->dev[i].towrite = NULL;
--
--                              if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
--                                      wake_up(&conf->wait_for_overlap);
--
--                              BUG_ON(sh->dev[i].written);
--                              sh->dev[i].written = chosen;
--                              check_xor();
--                      }
--              }
--              break;
--      case RECONSTRUCT_WRITE:
--              memset(ptr[0], 0, STRIPE_SIZE);
--              for (i= disks; i-- ;)
--                      if (i!=pd_idx && sh->dev[i].towrite) {
--                              chosen = sh->dev[i].towrite;
--                              sh->dev[i].towrite = NULL;
--
--                              if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
--                                      wake_up(&conf->wait_for_overlap);
--
--                              BUG_ON(sh->dev[i].written);
--                              sh->dev[i].written = chosen;
--                      }
--              break;
--      case CHECK_PARITY:
--              break;
--      }
--      if (count>1) {
--              xor_block(count, STRIPE_SIZE, ptr);
--              count = 1;
--      }
--      
--      for (i = disks; i--;)
--              if (sh->dev[i].written) {
--                      sector_t sector = sh->dev[i].sector;
--                      struct bio *wbi = sh->dev[i].written;
--                      while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) {
--                              copy_data(1, wbi, sh->dev[i].page, sector);
--                              wbi = r5_next_bio(wbi, sector);
--                      }
--
--                      set_bit(R5_LOCKED, &sh->dev[i].flags);
--                      set_bit(R5_UPTODATE, &sh->dev[i].flags);
--              }
--
--      switch(method) {
--      case RECONSTRUCT_WRITE:
--      case CHECK_PARITY:
--              for (i=disks; i--;)
--                      if (i != pd_idx) {
--                              ptr[count++] = page_address(sh->dev[i].page);
--                              check_xor();
--                      }
--              break;
--      case READ_MODIFY_WRITE:
--              for (i = disks; i--;)
--                      if (sh->dev[i].written) {
--                              ptr[count++] = page_address(sh->dev[i].page);
--                              check_xor();
--                      }
--      }
--      if (count != 1)
--              xor_block(count, STRIPE_SIZE, ptr);
--      
--      if (method != CHECK_PARITY) {
--              set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
--              set_bit(R5_LOCKED,   &sh->dev[pd_idx].flags);
--      } else
--              clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
--}
--
- static void compute_parity6(struct stripe_head *sh, int method)
- {
-       raid6_conf_t *conf = sh->raid_conf;
-@@ -1058,7 +1520,7 @@
-       qd_idx = raid6_next_disk(pd_idx, disks);
-       d0_idx = raid6_next_disk(qd_idx, disks);
--      PRINTK("compute_parity, stripe %llu, method %d\n",
-+      pr_debug("compute_parity, stripe %llu, method %d\n",
-               (unsigned long long)sh->sector, method);
-       switch(method) {
-@@ -1132,20 +1594,20 @@
- static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
- {
-       int i, count, disks = sh->disks;
--      void *ptr[MAX_XOR_BLOCKS], *p;
-+      void *ptr[MAX_XOR_BLOCKS], *dest, *p;
-       int pd_idx = sh->pd_idx;
-       int qd_idx = raid6_next_disk(pd_idx, disks);
--      PRINTK("compute_block_1, stripe %llu, idx %d\n",
-+      pr_debug("compute_block_1, stripe %llu, idx %d\n",
-               (unsigned long long)sh->sector, dd_idx);
-       if ( dd_idx == qd_idx ) {
-               /* We're actually computing the Q drive */
-               compute_parity6(sh, UPDATE_PARITY);
-       } else {
--              ptr[0] = page_address(sh->dev[dd_idx].page);
--              if (!nozero) memset(ptr[0], 0, STRIPE_SIZE);
--              count = 1;
-+              dest = page_address(sh->dev[dd_idx].page);
-+              if (!nozero) memset(dest, 0, STRIPE_SIZE);
-+              count = 0;
-               for (i = disks ; i--; ) {
-                       if (i == dd_idx || i == qd_idx)
-                               continue;
-@@ -1159,8 +1621,8 @@
-                       check_xor();
-               }
--              if (count != 1)
--                      xor_block(count, STRIPE_SIZE, ptr);
-+              if (count)
-+                      xor_blocks(count, STRIPE_SIZE, dest, ptr);
-               if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
-               else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
-       }
-@@ -1183,7 +1645,7 @@
-       BUG_ON(faila == failb);
-       if ( failb < faila ) { int tmp = faila; faila = failb; failb = tmp; }
--      PRINTK("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",
-+      pr_debug("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",
-              (unsigned long long)sh->sector, dd_idx1, dd_idx2, faila, failb);
-       if ( failb == disks-1 ) {
-@@ -1229,7 +1691,79 @@
-       }
- }
-+static int
-+handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
-+{
-+      int i, pd_idx = sh->pd_idx, disks = sh->disks;
-+      int locked = 0;
-+
-+      if (rcw) {
-+              /* if we are not expanding this is a proper write request, and
-+               * there will be bios with new data to be drained into the
-+               * stripe cache
-+               */
-+              if (!expand) {
-+                      set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
-+                      sh->ops.count++;
-+              }
-+
-+              set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
-+              sh->ops.count++;
-+
-+              for (i = disks; i--; ) {
-+                      struct r5dev *dev = &sh->dev[i];
-+
-+                      if (dev->towrite) {
-+                              set_bit(R5_LOCKED, &dev->flags);
-+                              if (!expand)
-+                                      clear_bit(R5_UPTODATE, &dev->flags);
-+                              locked++;
-+                      }
-+              }
-+      } else {
-+              BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||
-+                      test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));
-+
-+              set_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
-+              set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
-+              set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
-+
-+              sh->ops.count += 3;
-+
-+              for (i = disks; i--; ) {
-+                      struct r5dev *dev = &sh->dev[i];
-+                      if (i == pd_idx)
-+                              continue;
-+
-+                      /* For a read-modify write there may be blocks that are
-+                       * locked for reading while others are ready to be
-+                       * written so we distinguish these blocks by the
-+                       * R5_Wantprexor bit
-+                       */
-+                      if (dev->towrite &&
-+                          (test_bit(R5_UPTODATE, &dev->flags) ||
-+                          test_bit(R5_Wantcompute, &dev->flags))) {
-+                              set_bit(R5_Wantprexor, &dev->flags);
-+                              set_bit(R5_LOCKED, &dev->flags);
-+                              clear_bit(R5_UPTODATE, &dev->flags);
-+                              locked++;
-+                      }
-+              }
-+      }
-+
-+      /* keep the parity disk locked while asynchronous operations
-+       * are in flight
-+       */
-+      set_bit(R5_LOCKED, &sh->dev[pd_idx].flags);
-+      clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-+      locked++;
-+
-+      pr_debug("%s: stripe %llu locked: %d pending: %lx\n",
-+              __FUNCTION__, (unsigned long long)sh->sector,
-+              locked, sh->ops.pending);
-+      return locked;
-+}
- /*
-  * Each stripe/dev can have one or more bion attached.
-@@ -1242,7 +1776,7 @@
-       raid5_conf_t *conf = sh->raid_conf;
-       int firstwrite=0;
--      PRINTK("adding bh b#%llu to stripe s#%llu\n",
-+      pr_debug("adding bh b#%llu to stripe s#%llu\n",
-               (unsigned long long)bi->bi_sector,
-               (unsigned long long)sh->sector);
-@@ -1271,7 +1805,7 @@
-       spin_unlock_irq(&conf->device_lock);
-       spin_unlock(&sh->lock);
--      PRINTK("added bi b#%llu to stripe s#%llu, disk %d.\n",
-+      pr_debug("added bi b#%llu to stripe s#%llu, disk %d.\n",
-               (unsigned long long)bi->bi_sector,
-               (unsigned long long)sh->sector, dd_idx);
-@@ -1326,116 +1860,14 @@
-       return pd_idx;
- }
--
--/*
-- * handle_stripe - do things to a stripe.
-- *
-- * We lock the stripe and then examine the state of various bits
-- * to see what needs to be done.
-- * Possible results:
-- *    return some read request which now have data
-- *    return some write requests which are safely on disc
-- *    schedule a read on some buffers
-- *    schedule a write of some buffers
-- *    return confirmation of parity correctness
-- *
-- * Parity calculations are done inside the stripe lock
-- * buffers are taken off read_list or write_list, and bh_cache buffers
-- * get BH_Lock set before the stripe lock is released.
-- *
-- */
-- 
--static void handle_stripe5(struct stripe_head *sh)
-+static void
-+handle_requests_to_failed_array(raid5_conf_t *conf, struct stripe_head *sh,
-+                              struct stripe_head_state *s, int disks,
-+                              struct bio **return_bi)
- {
--      raid5_conf_t *conf = sh->raid_conf;
--      int disks = sh->disks;
--      struct bio *return_bi= NULL;
--      struct bio *bi;
-       int i;
--      int syncing, expanding, expanded;
--      int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
--      int non_overwrite = 0;
--      int failed_num=0;
--      struct r5dev *dev;
--
--      PRINTK("handling stripe %llu, cnt=%d, pd_idx=%d\n",
--              (unsigned long long)sh->sector, atomic_read(&sh->count),
--              sh->pd_idx);
--
--      spin_lock(&sh->lock);
--      clear_bit(STRIPE_HANDLE, &sh->state);
--      clear_bit(STRIPE_DELAYED, &sh->state);
--
--      syncing = test_bit(STRIPE_SYNCING, &sh->state);
--      expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
--      expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
--      /* Now to look around and see what can be done */
--
--      rcu_read_lock();
--      for (i=disks; i--; ) {
--              mdk_rdev_t *rdev;
--              dev = &sh->dev[i];
--              clear_bit(R5_Insync, &dev->flags);
--
--              PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
--                      i, dev->flags, dev->toread, dev->towrite, dev->written);
--              /* maybe we can reply to a read */
--              if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
--                      struct bio *rbi, *rbi2;
--                      PRINTK("Return read for disc %d\n", i);
--                      spin_lock_irq(&conf->device_lock);
--                      rbi = dev->toread;
--                      dev->toread = NULL;
--                      if (test_and_clear_bit(R5_Overlap, &dev->flags))
--                              wake_up(&conf->wait_for_overlap);
--                      spin_unlock_irq(&conf->device_lock);
--                      while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
--                              copy_data(0, rbi, dev->page, dev->sector);
--                              rbi2 = r5_next_bio(rbi, dev->sector);
--                              spin_lock_irq(&conf->device_lock);
--                              if (--rbi->bi_phys_segments == 0) {
--                                      rbi->bi_next = return_bi;
--                                      return_bi = rbi;
--                              }
--                              spin_unlock_irq(&conf->device_lock);
--                              rbi = rbi2;
--                      }
--              }
--
--              /* now count some things */
--              if (test_bit(R5_LOCKED, &dev->flags)) locked++;
--              if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;
--
--              
--              if (dev->toread) to_read++;
--              if (dev->towrite) {
--                      to_write++;
--                      if (!test_bit(R5_OVERWRITE, &dev->flags))
--                              non_overwrite++;
--              }
--              if (dev->written) written++;
--              rdev = rcu_dereference(conf->disks[i].rdev);
--              if (!rdev || !test_bit(In_sync, &rdev->flags)) {
--                      /* The ReadError flag will just be confusing now */
--                      clear_bit(R5_ReadError, &dev->flags);
--                      clear_bit(R5_ReWrite, &dev->flags);
--              }
--              if (!rdev || !test_bit(In_sync, &rdev->flags)
--                  || test_bit(R5_ReadError, &dev->flags)) {
--                      failed++;
--                      failed_num = i;
--              } else
--                      set_bit(R5_Insync, &dev->flags);
--      }
--      rcu_read_unlock();
--      PRINTK("locked=%d uptodate=%d to_read=%d"
--              " to_write=%d failed=%d failed_num=%d\n",
--              locked, uptodate, to_read, to_write, failed, failed_num);
--      /* check if the array has lost two devices and, if so, some requests might
--       * need to be failed
--       */
--      if (failed > 1 && to_read+to_write+written) {
--              for (i=disks; i--; ) {
-+      for (i = disks; i--; ) {
-+              struct bio *bi;
-                       int bitmap_end = 0;
-                       if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-@@ -1447,23 +1879,26 @@
-                                       md_error(conf->mddev, rdev);
-                               rcu_read_unlock();
-                       }
--
-                       spin_lock_irq(&conf->device_lock);
-                       /* fail all writes first */
-                       bi = sh->dev[i].towrite;
-                       sh->dev[i].towrite = NULL;
--                      if (bi) { to_write--; bitmap_end = 1; }
-+              if (bi) {
-+                      s->to_write--;
-+                      bitmap_end = 1;
-+              }
-                       if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-                               wake_up(&conf->wait_for_overlap);
--                      while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
-+              while (bi && bi->bi_sector <
-+                      sh->dev[i].sector + STRIPE_SECTORS) {
-                               struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
-                               clear_bit(BIO_UPTODATE, &bi->bi_flags);
-                               if (--bi->bi_phys_segments == 0) {
-                                       md_write_end(conf->mddev);
--                                      bi->bi_next = return_bi;
--                                      return_bi = bi;
-+                              bi->bi_next = *return_bi;
-+                              *return_bi = bi;
-                               }
-                               bi = nextbi;
-                       }
-@@ -1471,78 +1906,235 @@
-                       bi = sh->dev[i].written;
-                       sh->dev[i].written = NULL;
-                       if (bi) bitmap_end = 1;
--                      while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
-+              while (bi && bi->bi_sector <
-+                     sh->dev[i].sector + STRIPE_SECTORS) {
-                               struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
-                               clear_bit(BIO_UPTODATE, &bi->bi_flags);
-                               if (--bi->bi_phys_segments == 0) {
-                                       md_write_end(conf->mddev);
--                                      bi->bi_next = return_bi;
--                                      return_bi = bi;
-+                              bi->bi_next = *return_bi;
-+                              *return_bi = bi;
-+                      }
-+                      bi = bi2;
-+              }
-+
-+              /* fail any reads if this device is non-operational and
-+               * the data has not reached the cache yet.
-+               */
-+              if (!test_bit(R5_Wantfill, &sh->dev[i].flags) &&
-+                  (!test_bit(R5_Insync, &sh->dev[i].flags) ||
-+                    test_bit(R5_ReadError, &sh->dev[i].flags))) {
-+                      bi = sh->dev[i].toread;
-+                      sh->dev[i].toread = NULL;
-+                      if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-+                              wake_up(&conf->wait_for_overlap);
-+                      if (bi) s->to_read--;
-+                      while (bi && bi->bi_sector <
-+                             sh->dev[i].sector + STRIPE_SECTORS) {
-+                              struct bio *nextbi =
-+                                      r5_next_bio(bi, sh->dev[i].sector);
-+                              clear_bit(BIO_UPTODATE, &bi->bi_flags);
-+                              if (--bi->bi_phys_segments == 0) {
-+                                      bi->bi_next = *return_bi;
-+                                      *return_bi = bi;
-+                              }
-+                              bi = nextbi;
-+                      }
-+              }
-+              spin_unlock_irq(&conf->device_lock);
-+              if (bitmap_end)
-+                      bitmap_endwrite(conf->mddev->bitmap, sh->sector,
-+                                      STRIPE_SECTORS, 0, 0);
-+      }
-+
-+}
-+
-+/* __handle_issuing_new_read_requests5 - returns 0 if there are no more disks
-+ * to process
-+ */
-+static int __handle_issuing_new_read_requests5(struct stripe_head *sh,
-+                      struct stripe_head_state *s, int disk_idx, int disks)
-+{
-+      struct r5dev *dev = &sh->dev[disk_idx];
-+      struct r5dev *failed_dev = &sh->dev[s->failed_num];
-+
-+      /* don't schedule compute operations or reads on the parity block while
-+       * a check is in flight
-+       */
-+      if ((disk_idx == sh->pd_idx) &&
-+           test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
-+              return ~0;
-+
-+      /* is the data in this block needed, and can we get it? */
-+      if (!test_bit(R5_LOCKED, &dev->flags) &&
-+          !test_bit(R5_UPTODATE, &dev->flags) && (dev->toread ||
-+          (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
-+           s->syncing || s->expanding || (s->failed &&
-+           (failed_dev->toread || (failed_dev->towrite &&
-+           !test_bit(R5_OVERWRITE, &failed_dev->flags)
-+           ))))) {
-+              /* 1/ We would like to get this block, possibly by computing it,
-+               * but we might not be able to.
-+               *
-+               * 2/ Since parity check operations potentially make the parity
-+               * block !uptodate it will need to be refreshed before any
-+               * compute operations on data disks are scheduled.
-+               *
-+               * 3/ We hold off parity block re-reads until check operations
-+               * have quiesced.
-+               */
-+              if ((s->uptodate == disks - 1) &&
-+                  !test_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
-+                      set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
-+                      set_bit(R5_Wantcompute, &dev->flags);
-+                      sh->ops.target = disk_idx;
-+                      s->req_compute = 1;
-+                      sh->ops.count++;
-+                      /* Careful: from this point on 'uptodate' is in the eye
-+                       * of raid5_run_ops which services 'compute' operations
-+                       * before writes. R5_Wantcompute flags a block that will
-+                       * be R5_UPTODATE by the time it is needed for a
-+                       * subsequent operation.
-+                       */
-+                      s->uptodate++;
-+                      return 0; /* uptodate + compute == disks */
-+              } else if ((s->uptodate < disks - 1) &&
-+                      test_bit(R5_Insync, &dev->flags)) {
-+                      /* Note: we hold off compute operations while checks are
-+                       * in flight, but we still prefer 'compute' over 'read'
-+                       * hence we only read if (uptodate < * disks-1)
-+                       */
-+                      set_bit(R5_LOCKED, &dev->flags);
-+                      set_bit(R5_Wantread, &dev->flags);
-+                      if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
-+                              sh->ops.count++;
-+                      s->locked++;
-+                      pr_debug("Reading block %d (sync=%d)\n", disk_idx,
-+                              s->syncing);
-                               }
--                              bi = bi2;
-                       }
--                      /* fail any reads if this device is non-operational */
--                      if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
--                          test_bit(R5_ReadError, &sh->dev[i].flags)) {
--                              bi = sh->dev[i].toread;
--                              sh->dev[i].toread = NULL;
--                              if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
--                                      wake_up(&conf->wait_for_overlap);
--                              if (bi) to_read--;
--                              while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
--                                      struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
--                                      clear_bit(BIO_UPTODATE, &bi->bi_flags);
--                                      if (--bi->bi_phys_segments == 0) {
--                                              bi->bi_next = return_bi;
--                                              return_bi = bi;
--                                      }
--                                      bi = nextbi;
-+      return ~0;
-+}
-+
-+static void handle_issuing_new_read_requests5(struct stripe_head *sh,
-+                      struct stripe_head_state *s, int disks)
-+{
-+      int i;
-+
-+      /* Clear completed compute operations.  Parity recovery
-+       * (STRIPE_OP_MOD_REPAIR_PD) implies a write-back which is handled
-+       * later on in this routine
-+       */
-+      if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
-+              !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
-+              clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
-+              clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
-+              clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
-+      }
-+
-+      /* look for blocks to read/compute, skip this if a compute
-+       * is already in flight, or if the stripe contents are in the
-+       * midst of changing due to a write
-+       */
-+      if (!test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
-+              !test_bit(STRIPE_OP_PREXOR, &sh->ops.pending) &&
-+              !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
-+              for (i = disks; i--; )
-+                      if (__handle_issuing_new_read_requests5(
-+                              sh, s, i, disks) == 0)
-+                              break;
-                               }
-+      set_bit(STRIPE_HANDLE, &sh->state);
-+}
-+
-+static void handle_issuing_new_read_requests6(struct stripe_head *sh,
-+                      struct stripe_head_state *s, struct r6_state *r6s,
-+                      int disks)
-+{
-+      int i;
-+      for (i = disks; i--; ) {
-+              struct r5dev *dev = &sh->dev[i];
-+              if (!test_bit(R5_LOCKED, &dev->flags) &&
-+                  !test_bit(R5_UPTODATE, &dev->flags) &&
-+                  (dev->toread || (dev->towrite &&
-+                   !test_bit(R5_OVERWRITE, &dev->flags)) ||
-+                   s->syncing || s->expanding ||
-+                   (s->failed >= 1 &&
-+                    (sh->dev[r6s->failed_num[0]].toread ||
-+                     s->to_write)) ||
-+                   (s->failed >= 2 &&
-+                    (sh->dev[r6s->failed_num[1]].toread ||
-+                     s->to_write)))) {
-+                      /* we would like to get this block, possibly
-+                       * by computing it, but we might not be able to
-+                       */
-+                      if (s->uptodate == disks-1) {
-+                              pr_debug("Computing stripe %llu block %d\n",
-+                                     (unsigned long long)sh->sector, i);
-+                              compute_block_1(sh, i, 0);
-+                              s->uptodate++;
-+                      } else if ( s->uptodate == disks-2 && s->failed >= 2 ) {
-+                              /* Computing 2-failure is *very* expensive; only
-+                               * do it if failed >= 2
-+                               */
-+                              int other;
-+                              for (other = disks; other--; ) {
-+                                      if (other == i)
-+                                              continue;
-+                                      if (!test_bit(R5_UPTODATE,
-+                                            &sh->dev[other].flags))
-+                                              break;
-                       }
--                      spin_unlock_irq(&conf->device_lock);
--                      if (bitmap_end)
--                              bitmap_endwrite(conf->mddev->bitmap, sh->sector,
--                                              STRIPE_SECTORS, 0, 0);
-+                              BUG_ON(other < 0);
-+                              pr_debug("Computing stripe %llu blocks %d,%d\n",
-+                                     (unsigned long long)sh->sector,
-+                                     i, other);
-+                              compute_block_2(sh, i, other);
-+                              s->uptodate += 2;
-+                      } else if (test_bit(R5_Insync, &dev->flags)) {
-+                              set_bit(R5_LOCKED, &dev->flags);
-+                              set_bit(R5_Wantread, &dev->flags);
-+                              s->locked++;
-+                              pr_debug("Reading block %d (sync=%d)\n",
-+                                      i, s->syncing);
-               }
-       }
--      if (failed > 1 && syncing) {
--              md_done_sync(conf->mddev, STRIPE_SECTORS,0);
--              clear_bit(STRIPE_SYNCING, &sh->state);
--              syncing = 0;
-       }
-+      set_bit(STRIPE_HANDLE, &sh->state);
-+}
--      /* might be able to return some write requests if the parity block
--       * is safe, or on a failed drive
--       */
--      dev = &sh->dev[sh->pd_idx];
--      if ( written &&
--           ( (test_bit(R5_Insync, &dev->flags) && !test_bit(R5_LOCKED, &dev->flags) &&
--              test_bit(R5_UPTODATE, &dev->flags))
--             || (failed == 1 && failed_num == sh->pd_idx))
--          ) {
--          /* any written block on an uptodate or failed drive can be returned.
-+
-+/* handle_completed_write_requests
-+ * any written block on an uptodate or failed drive can be returned.
-            * Note that if we 'wrote' to a failed drive, it will be UPTODATE, but 
-            * never LOCKED, so we don't need to test 'failed' directly.
-            */
--          for (i=disks; i--; )
-+static void handle_completed_write_requests(raid5_conf_t *conf,
-+      struct stripe_head *sh, int disks, struct bio **return_bi)
-+{
-+      int i;
-+      struct r5dev *dev;
-+
-+      for (i = disks; i--; )
-               if (sh->dev[i].written) {
-                   dev = &sh->dev[i];
-                   if (!test_bit(R5_LOCKED, &dev->flags) &&
--                       test_bit(R5_UPTODATE, &dev->flags) ) {
-+                              test_bit(R5_UPTODATE, &dev->flags)) {
-                       /* We can return any write requests */
-                           struct bio *wbi, *wbi2;
-                           int bitmap_end = 0;
--                          PRINTK("Return write for disc %d\n", i);
-+                              pr_debug("Return write for disc %d\n", i);
-                           spin_lock_irq(&conf->device_lock);
-                           wbi = dev->written;
-                           dev->written = NULL;
--                          while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
-+                              while (wbi && wbi->bi_sector <
-+                                      dev->sector + STRIPE_SECTORS) {
-                                   wbi2 = r5_next_bio(wbi, dev->sector);
-                                   if (--wbi->bi_phys_segments == 0) {
-                                           md_write_end(conf->mddev);
--                                          wbi->bi_next = return_bi;
--                                          return_bi = wbi;
-+                                              wbi->bi_next = *return_bi;
-+                                              *return_bi = wbi;
-                                   }
-                                   wbi = wbi2;
-                           }
-@@ -1550,89 +2142,63 @@
-                                   bitmap_end = 1;
-                           spin_unlock_irq(&conf->device_lock);
-                           if (bitmap_end)
--                                  bitmap_endwrite(conf->mddev->bitmap, sh->sector,
-+                                      bitmap_endwrite(conf->mddev->bitmap,
-+                                                      sh->sector,
-                                                   STRIPE_SECTORS,
--                                                  !test_bit(STRIPE_DEGRADED, &sh->state), 0);
--                  }
--              }
--      }
--
--      /* Now we might consider reading some blocks, either to check/generate
--       * parity, or to satisfy requests
--       * or to load a block that is being partially written.
--       */
--      if (to_read || non_overwrite || (syncing && (uptodate < disks)) || expanding) {
--              for (i=disks; i--;) {
--                      dev = &sh->dev[i];
--                      if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
--                          (dev->toread ||
--                           (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
--                           syncing ||
--                           expanding ||
--                           (failed && (sh->dev[failed_num].toread ||
--                                       (sh->dev[failed_num].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num].flags))))
--                                  )
--                              ) {
--                              /* we would like to get this block, possibly
--                               * by computing it, but we might not be able to
--                               */
--                              if (uptodate == disks-1) {
--                                      PRINTK("Computing block %d\n", i);
--                                      compute_block(sh, i);
--                                      uptodate++;
--                              } else if (test_bit(R5_Insync, &dev->flags)) {
--                                      set_bit(R5_LOCKED, &dev->flags);
--                                      set_bit(R5_Wantread, &dev->flags);
--                                      locked++;
--                                      PRINTK("Reading block %d (sync=%d)\n", 
--                                              i, syncing);
--                              }
-+                                       !test_bit(STRIPE_DEGRADED, &sh->state),
-+                                                      0);
-                       }
-               }
--              set_bit(STRIPE_HANDLE, &sh->state);
--      }
-+}
--      /* now to consider writing and what else, if anything should be read */
--      if (to_write) {
--              int rmw=0, rcw=0;
--              for (i=disks ; i--;) {
-+static void handle_issuing_new_write_requests5(raid5_conf_t *conf,
-+              struct stripe_head *sh, struct stripe_head_state *s, int disks)
-+{
-+      int rmw = 0, rcw = 0, i;
-+      for (i = disks; i--; ) {
-                       /* would I have to read this buffer for read_modify_write */
--                      dev = &sh->dev[i];
-+              struct r5dev *dev = &sh->dev[i];
-                       if ((dev->towrite || i == sh->pd_idx) &&
--                          (!test_bit(R5_LOCKED, &dev->flags) 
--                                  ) &&
--                          !test_bit(R5_UPTODATE, &dev->flags)) {
--                              if (test_bit(R5_Insync, &dev->flags)
--/*                                && !(!mddev->insync && i == sh->pd_idx) */
--                                      )
-+                  !test_bit(R5_LOCKED, &dev->flags) &&
-+                  !(test_bit(R5_UPTODATE, &dev->flags) ||
-+                    test_bit(R5_Wantcompute, &dev->flags))) {
-+                      if (test_bit(R5_Insync, &dev->flags))
-                                       rmw++;
--                              else rmw += 2*disks;  /* cannot read it */
-+                      else
-+                              rmw += 2*disks;  /* cannot read it */
-                       }
-                       /* Would I have to read this buffer for reconstruct_write */
-                       if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
--                          (!test_bit(R5_LOCKED, &dev->flags) 
--                                  ) &&
--                          !test_bit(R5_UPTODATE, &dev->flags)) {
-+                  !test_bit(R5_LOCKED, &dev->flags) &&
-+                  !(test_bit(R5_UPTODATE, &dev->flags) ||
-+                  test_bit(R5_Wantcompute, &dev->flags))) {
-                               if (test_bit(R5_Insync, &dev->flags)) rcw++;
--                              else rcw += 2*disks;
-+                      else
-+                              rcw += 2*disks;
-                       }
-               }
--              PRINTK("for sector %llu, rmw=%d rcw=%d\n", 
-+      pr_debug("for sector %llu, rmw=%d rcw=%d\n",
-                       (unsigned long long)sh->sector, rmw, rcw);
-               set_bit(STRIPE_HANDLE, &sh->state);
-               if (rmw < rcw && rmw > 0)
-                       /* prefer read-modify-write, but need to get some data */
--                      for (i=disks; i--;) {
--                              dev = &sh->dev[i];
-+              for (i = disks; i--; ) {
-+                      struct r5dev *dev = &sh->dev[i];
-                               if ((dev->towrite || i == sh->pd_idx) &&
--                                  !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-+                          !test_bit(R5_LOCKED, &dev->flags) &&
-+                          !(test_bit(R5_UPTODATE, &dev->flags) ||
-+                          test_bit(R5_Wantcompute, &dev->flags)) &&
-                                   test_bit(R5_Insync, &dev->flags)) {
--                                      if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
--                                      {
--                                              PRINTK("Read_old block %d for r-m-w\n", i);
-+                              if (
-+                                test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-+                                      pr_debug("Read_old block "
-+                                              "%d for r-m-w\n", i);
-                                               set_bit(R5_LOCKED, &dev->flags);
-                                               set_bit(R5_Wantread, &dev->flags);
--                                              locked++;
-+                                      if (!test_and_set_bit(
-+                                              STRIPE_OP_IO, &sh->ops.pending))
-+                                              sh->ops.count++;
-+                                      s->locked++;
-                                       } else {
-                                               set_bit(STRIPE_DELAYED, &sh->state);
-                                               set_bit(STRIPE_HANDLE, &sh->state);
-@@ -1641,165 +2207,367 @@
-                       }
-               if (rcw <= rmw && rcw > 0)
-                       /* want reconstruct write, but need to get some data */
--                      for (i=disks; i--;) {
--                              dev = &sh->dev[i];
--                              if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
--                                  !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-+              for (i = disks; i--; ) {
-+                      struct r5dev *dev = &sh->dev[i];
-+                      if (!test_bit(R5_OVERWRITE, &dev->flags) &&
-+                          i != sh->pd_idx &&
-+                          !test_bit(R5_LOCKED, &dev->flags) &&
-+                          !(test_bit(R5_UPTODATE, &dev->flags) ||
-+                          test_bit(R5_Wantcompute, &dev->flags)) &&
-                                   test_bit(R5_Insync, &dev->flags)) {
--                                      if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
--                                      {
--                                              PRINTK("Read_old block %d for Reconstruct\n", i);
-+                              if (
-+                                test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-+                                      pr_debug("Read_old block "
-+                                              "%d for Reconstruct\n", i);
-                                               set_bit(R5_LOCKED, &dev->flags);
-                                               set_bit(R5_Wantread, &dev->flags);
--                                              locked++;
-+                                      if (!test_and_set_bit(
-+                                              STRIPE_OP_IO, &sh->ops.pending))
-+                                              sh->ops.count++;
-+                                      s->locked++;
-+                              } else {
-+                                      set_bit(STRIPE_DELAYED, &sh->state);
-+                                      set_bit(STRIPE_HANDLE, &sh->state);
-+                              }
-+                      }
-+              }
-+      /* now if nothing is locked, and if we have enough data,
-+       * we can start a write request
-+       */
-+      /* since handle_stripe can be called at any time we need to handle the
-+       * case where a compute block operation has been submitted and then a
-+       * subsequent call wants to start a write request.  raid5_run_ops only
-+       * handles the case where compute block and postxor are requested
-+       * simultaneously.  If this is not the case then new writes need to be
-+       * held off until the compute completes.
-+       */
-+      if ((s->req_compute ||
-+          !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) &&
-+              (s->locked == 0 && (rcw == 0 || rmw == 0) &&
-+              !test_bit(STRIPE_BIT_DELAY, &sh->state)))
-+              s->locked += handle_write_operations5(sh, rcw == 0, 0);
-+}
-+
-+static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
-+              struct stripe_head *sh, struct stripe_head_state *s,
-+              struct r6_state *r6s, int disks)
-+{
-+      int rcw = 0, must_compute = 0, pd_idx = sh->pd_idx, i;
-+      int qd_idx = r6s->qd_idx;
-+      for (i = disks; i--; ) {
-+              struct r5dev *dev = &sh->dev[i];
-+              /* Would I have to read this buffer for reconstruct_write */
-+              if (!test_bit(R5_OVERWRITE, &dev->flags)
-+                  && i != pd_idx && i != qd_idx
-+                  && (!test_bit(R5_LOCKED, &dev->flags)
-+                          ) &&
-+                  !test_bit(R5_UPTODATE, &dev->flags)) {
-+                      if (test_bit(R5_Insync, &dev->flags)) rcw++;
-+                      else {
-+                              pr_debug("raid6: must_compute: "
-+                                      "disk %d flags=%#lx\n", i, dev->flags);
-+                              must_compute++;
-+                      }
-+              }
-+      }
-+      pr_debug("for sector %llu, rcw=%d, must_compute=%d\n",
-+             (unsigned long long)sh->sector, rcw, must_compute);
-+      set_bit(STRIPE_HANDLE, &sh->state);
-+
-+      if (rcw > 0)
-+              /* want reconstruct write, but need to get some data */
-+              for (i = disks; i--; ) {
-+                      struct r5dev *dev = &sh->dev[i];
-+                      if (!test_bit(R5_OVERWRITE, &dev->flags)
-+                          && !(s->failed == 0 && (i == pd_idx || i == qd_idx))
-+                          && !test_bit(R5_LOCKED, &dev->flags) &&
-+                          !test_bit(R5_UPTODATE, &dev->flags) &&
-+                          test_bit(R5_Insync, &dev->flags)) {
-+                              if (
-+                                test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-+                                      pr_debug("Read_old stripe %llu "
-+                                              "block %d for Reconstruct\n",
-+                                           (unsigned long long)sh->sector, i);
-+                                      set_bit(R5_LOCKED, &dev->flags);
-+                                      set_bit(R5_Wantread, &dev->flags);
-+                                      s->locked++;
-                                       } else {
-+                                      pr_debug("Request delayed stripe %llu "
-+                                              "block %d for Reconstruct\n",
-+                                           (unsigned long long)sh->sector, i);
-                                               set_bit(STRIPE_DELAYED, &sh->state);
-                                               set_bit(STRIPE_HANDLE, &sh->state);
-                                       }
-                               }
-                       }
--              /* now if nothing is locked, and if we have enough data, we can start a write request */
--              if (locked == 0 && (rcw == 0 ||rmw == 0) &&
-+      /* now if nothing is locked, and if we have enough data, we can start a
-+       * write request
-+       */
-+      if (s->locked == 0 && rcw == 0 &&
-                   !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
--                      PRINTK("Computing parity...\n");
--                      compute_parity5(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
-+              if (must_compute > 0) {
-+                      /* We have failed blocks and need to compute them */
-+                      switch (s->failed) {
-+                      case 0:
-+                              BUG();
-+                      case 1:
-+                              compute_block_1(sh, r6s->failed_num[0], 0);
-+                              break;
-+                      case 2:
-+                              compute_block_2(sh, r6s->failed_num[0],
-+                                              r6s->failed_num[1]);
-+                              break;
-+                      default: /* This request should have been failed? */
-+                              BUG();
-+                      }
-+              }
-+
-+              pr_debug("Computing parity for stripe %llu\n",
-+                      (unsigned long long)sh->sector);
-+              compute_parity6(sh, RECONSTRUCT_WRITE);
-                       /* now every locked buffer is ready to be written */
--                      for (i=disks; i--;)
-+              for (i = disks; i--; )
-                               if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
--                                      PRINTK("Writing block %d\n", i);
--                                      locked++;
-+                              pr_debug("Writing stripe %llu block %d\n",
-+                                     (unsigned long long)sh->sector, i);
-+                              s->locked++;
-                                       set_bit(R5_Wantwrite, &sh->dev[i].flags);
--                                      if (!test_bit(R5_Insync, &sh->dev[i].flags)
--                                          || (i==sh->pd_idx && failed == 0))
--                                              set_bit(STRIPE_INSYNC, &sh->state);
-                               }
-+              /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
-+              set_bit(STRIPE_INSYNC, &sh->state);
-+
-                       if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-                               atomic_dec(&conf->preread_active_stripes);
--                              if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
-+                      if (atomic_read(&conf->preread_active_stripes) <
-+                          IO_THRESHOLD)
-                                       md_wakeup_thread(conf->mddev->thread);
-                       }
-               }
--      }
-+}
--      /* maybe we need to check and possibly fix the parity for this stripe
--       * Any reads will already have been scheduled, so we just see if enough data
--       * is available
--       */
--      if (syncing && locked == 0 &&
--          !test_bit(STRIPE_INSYNC, &sh->state)) {
-+static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
-+                              struct stripe_head_state *s, int disks)
-+{
-               set_bit(STRIPE_HANDLE, &sh->state);
--              if (failed == 0) {
--                      BUG_ON(uptodate != disks);
--                      compute_parity5(sh, CHECK_PARITY);
--                      uptodate--;
--                      if (page_is_zero(sh->dev[sh->pd_idx].page)) {
--                              /* parity is correct (on disc, not in buffer any more) */
-+      /* Take one of the following actions:
-+       * 1/ start a check parity operation if (uptodate == disks)
-+       * 2/ finish a check parity operation and act on the result
-+       * 3/ skip to the writeback section if we previously
-+       *    initiated a recovery operation
-+       */
-+      if (s->failed == 0 &&
-+          !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
-+              if (!test_and_set_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
-+                      BUG_ON(s->uptodate != disks);
-+                      clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
-+                      sh->ops.count++;
-+                      s->uptodate--;
-+              } else if (
-+                     test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) {
-+                      clear_bit(STRIPE_OP_CHECK, &sh->ops.ack);
-+                      clear_bit(STRIPE_OP_CHECK, &sh->ops.pending);
-+
-+                      if (sh->ops.zero_sum_result == 0)
-+                              /* parity is correct (on disc,
-+                               * not in buffer any more)
-+                               */
-                               set_bit(STRIPE_INSYNC, &sh->state);
--                      } else {
--                              conf->mddev->resync_mismatches += STRIPE_SECTORS;
--                              if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
-+                      else {
-+                              conf->mddev->resync_mismatches +=
-+                                      STRIPE_SECTORS;
-+                              if (test_bit(
-+                                   MD_RECOVERY_CHECK, &conf->mddev->recovery))
-                                       /* don't try to repair!! */
-                                       set_bit(STRIPE_INSYNC, &sh->state);
-                               else {
--                                      compute_block(sh, sh->pd_idx);
--                                      uptodate++;
-+                                      set_bit(STRIPE_OP_COMPUTE_BLK,
-+                                              &sh->ops.pending);
-+                                      set_bit(STRIPE_OP_MOD_REPAIR_PD,
-+                                              &sh->ops.pending);
-+                                      set_bit(R5_Wantcompute,
-+                                              &sh->dev[sh->pd_idx].flags);
-+                                      sh->ops.target = sh->pd_idx;
-+                                      sh->ops.count++;
-+                                      s->uptodate++;
-+                              }
-+                      }
-                               }
-                       }
-+
-+      /* check if we can clear a parity disk reconstruct */
-+      if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
-+              test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
-+
-+              clear_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending);
-+              clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
-+              clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
-+              clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
-               }
--              if (!test_bit(STRIPE_INSYNC, &sh->state)) {
-+
-+      /* Wait for check parity and compute block operations to complete
-+       * before write-back
-+       */
-+      if (!test_bit(STRIPE_INSYNC, &sh->state) &&
-+              !test_bit(STRIPE_OP_CHECK, &sh->ops.pending) &&
-+              !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) {
-+              struct r5dev *dev;
-                       /* either failed parity check, or recovery is happening */
--                      if (failed==0)
--                              failed_num = sh->pd_idx;
--                      dev = &sh->dev[failed_num];
-+              if (s->failed == 0)
-+                      s->failed_num = sh->pd_idx;
-+              dev = &sh->dev[s->failed_num];
-                       BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
--                      BUG_ON(uptodate != disks);
-+              BUG_ON(s->uptodate != disks);
-                       set_bit(R5_LOCKED, &dev->flags);
-                       set_bit(R5_Wantwrite, &dev->flags);
-+              if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
-+                      sh->ops.count++;
-+
-                       clear_bit(STRIPE_DEGRADED, &sh->state);
--                      locked++;
-+              s->locked++;
-                       set_bit(STRIPE_INSYNC, &sh->state);
-               }
-+}
-+
-+
-+static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
-+                              struct stripe_head_state *s,
-+                              struct r6_state *r6s, struct page *tmp_page,
-+                              int disks)
-+{
-+      int update_p = 0, update_q = 0;
-+      struct r5dev *dev;
-+      int pd_idx = sh->pd_idx;
-+      int qd_idx = r6s->qd_idx;
-+
-+      set_bit(STRIPE_HANDLE, &sh->state);
-+
-+      BUG_ON(s->failed > 2);
-+      BUG_ON(s->uptodate < disks);
-+      /* Want to check and possibly repair P and Q.
-+       * However there could be one 'failed' device, in which
-+       * case we can only check one of them, possibly using the
-+       * other to generate missing data
-+       */
-+
-+      /* If !tmp_page, we cannot do the calculations,
-+       * but as we have set STRIPE_HANDLE, we will soon be called
-+       * by stripe_handle with a tmp_page - just wait until then.
-+       */
-+      if (tmp_page) {
-+              if (s->failed == r6s->q_failed) {
-+                      /* The only possible failed device holds 'Q', so it
-+                       * makes sense to check P (If anything else were failed,
-+                       * we would have used P to recreate it).
-+                       */
-+                      compute_block_1(sh, pd_idx, 1);
-+                      if (!page_is_zero(sh->dev[pd_idx].page)) {
-+                              compute_block_1(sh, pd_idx, 0);
-+                              update_p = 1;
-+                      }
-       }
--      if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
--              md_done_sync(conf->mddev, STRIPE_SECTORS,1);
--              clear_bit(STRIPE_SYNCING, &sh->state);
-+              if (!r6s->q_failed && s->failed < 2) {
-+                      /* q is not failed, and we didn't use it to generate
-+                       * anything, so it makes sense to check it
-+                       */
-+                      memcpy(page_address(tmp_page),
-+                             page_address(sh->dev[qd_idx].page),
-+                             STRIPE_SIZE);
-+                      compute_parity6(sh, UPDATE_PARITY);
-+                      if (memcmp(page_address(tmp_page),
-+                                 page_address(sh->dev[qd_idx].page),
-+                                 STRIPE_SIZE) != 0) {
-+                              clear_bit(STRIPE_INSYNC, &sh->state);
-+                              update_q = 1;
-+                      }
-+              }
-+              if (update_p || update_q) {
-+                      conf->mddev->resync_mismatches += STRIPE_SECTORS;
-+                      if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
-+                              /* don't try to repair!! */
-+                              update_p = update_q = 0;
-       }
--      /* If the failed drive is just a ReadError, then we might need to progress
--       * the repair/check process
-+              /* now write out any block on a failed drive,
-+               * or P or Q if they need it
-        */
--      if (failed == 1 && ! conf->mddev->ro &&
--          test_bit(R5_ReadError, &sh->dev[failed_num].flags)
--          && !test_bit(R5_LOCKED, &sh->dev[failed_num].flags)
--          && test_bit(R5_UPTODATE, &sh->dev[failed_num].flags)
--              ) {
--              dev = &sh->dev[failed_num];
--              if (!test_bit(R5_ReWrite, &dev->flags)) {
-+
-+              if (s->failed == 2) {
-+                      dev = &sh->dev[r6s->failed_num[1]];
-+                      s->locked++;
-+                      set_bit(R5_LOCKED, &dev->flags);
-                       set_bit(R5_Wantwrite, &dev->flags);
--                      set_bit(R5_ReWrite, &dev->flags);
-+              }
-+              if (s->failed >= 1) {
-+                      dev = &sh->dev[r6s->failed_num[0]];
-+                      s->locked++;
-                       set_bit(R5_LOCKED, &dev->flags);
--                      locked++;
--              } else {
--                      /* let's read it back */
--                      set_bit(R5_Wantread, &dev->flags);
-+                      set_bit(R5_Wantwrite, &dev->flags);
-+              }
-+
-+              if (update_p) {
-+                      dev = &sh->dev[pd_idx];
-+                      s->locked++;
-                       set_bit(R5_LOCKED, &dev->flags);
--                      locked++;
-+                      set_bit(R5_Wantwrite, &dev->flags);
-               }
-+              if (update_q) {
-+                      dev = &sh->dev[qd_idx];
-+                      s->locked++;
-+                      set_bit(R5_LOCKED, &dev->flags);
-+                      set_bit(R5_Wantwrite, &dev->flags);
-       }
-+              clear_bit(STRIPE_DEGRADED, &sh->state);
--      if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
--              /* Need to write out all blocks after computing parity */
--              sh->disks = conf->raid_disks;
--              sh->pd_idx = stripe_to_pdidx(sh->sector, conf, conf->raid_disks);
--              compute_parity5(sh, RECONSTRUCT_WRITE);
--              for (i= conf->raid_disks; i--;) {
--                      set_bit(R5_LOCKED, &sh->dev[i].flags);
--                      locked++;
--                      set_bit(R5_Wantwrite, &sh->dev[i].flags);
--              }
--              clear_bit(STRIPE_EXPANDING, &sh->state);
--      } else if (expanded) {
--              clear_bit(STRIPE_EXPAND_READY, &sh->state);
--              atomic_dec(&conf->reshape_stripes);
--              wake_up(&conf->wait_for_overlap);
--              md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
-+              set_bit(STRIPE_INSYNC, &sh->state);
-       }
-+}
-+
-+static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
-+                              struct r6_state *r6s)
-+{
-+      int i;
--      if (expanding && locked == 0) {
-               /* We have read all the blocks in this stripe and now we need to
-                * copy some of them into a target stripe for expand.
-                */
-+      struct dma_async_tx_descriptor *tx = NULL;
-               clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
--              for (i=0; i< sh->disks; i++)
--                      if (i != sh->pd_idx) {
-+      for (i = 0; i < sh->disks; i++)
-+              if (i != sh->pd_idx && (r6s && i != r6s->qd_idx)) {
-                               int dd_idx, pd_idx, j;
-                               struct stripe_head *sh2;
-                               sector_t bn = compute_blocknr(sh, i);
-                               sector_t s = raid5_compute_sector(bn, conf->raid_disks,
--                                                                conf->raid_disks-1,
--                                                                &dd_idx, &pd_idx, conf);
--                              sh2 = get_active_stripe(conf, s, conf->raid_disks, pd_idx, 1);
-+                                              conf->raid_disks -
-+                                              conf->max_degraded, &dd_idx,
-+                                              &pd_idx, conf);
-+                      sh2 = get_active_stripe(conf, s, conf->raid_disks,
-+                                              pd_idx, 1);
-                               if (sh2 == NULL)
-                                       /* so far only the early blocks of this stripe
-                                        * have been requested.  When later blocks
-                                        * get requested, we will try again
-                                        */
-                                       continue;
--                              if(!test_bit(STRIPE_EXPANDING, &sh2->state) ||
-+                      if (!test_bit(STRIPE_EXPANDING, &sh2->state) ||
-                                  test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) {
-                                       /* must have already done this block */
-                                       release_stripe(sh2);
-                                       continue;
-                               }
--                              memcpy(page_address(sh2->dev[dd_idx].page),
--                                     page_address(sh->dev[i].page),
--                                     STRIPE_SIZE);
-+
-+                      /* place all the copies on one channel */
-+                      tx = async_memcpy(sh2->dev[dd_idx].page,
-+                              sh->dev[i].page, 0, 0, STRIPE_SIZE,
-+                              ASYNC_TX_DEP_ACK, tx, NULL, NULL);
-+
-                               set_bit(R5_Expanded, &sh2->dev[dd_idx].flags);
-                               set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags);
--                              for (j=0; j<conf->raid_disks; j++)
-+                      for (j = 0; j < conf->raid_disks; j++)
-                                       if (j != sh2->pd_idx &&
-+                                  (r6s && j != r6s->qd_idx) &&
-                                           !test_bit(R5_Expanded, &sh2->dev[j].flags))
-                                               break;
-                               if (j == conf->raid_disks) {
-@@ -1807,153 +2575,91 @@
-                                       set_bit(STRIPE_HANDLE, &sh2->state);
-                               }
-                               release_stripe(sh2);
--                      }
--      }
--
--      spin_unlock(&sh->lock);
--
--      while ((bi=return_bi)) {
--              int bytes = bi->bi_size;
--
--              return_bi = bi->bi_next;
--              bi->bi_next = NULL;
--              bi->bi_size = 0;
--              bi->bi_end_io(bi, bytes,
--                            test_bit(BIO_UPTODATE, &bi->bi_flags)
--                              ? 0 : -EIO);
--      }
--      for (i=disks; i-- ;) {
--              int rw;
--              struct bio *bi;
--              mdk_rdev_t *rdev;
--              if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
--                      rw = WRITE;
--              else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
--                      rw = READ;
--              else
--                      continue;
-- 
--              bi = &sh->dev[i].req;
-- 
--              bi->bi_rw = rw;
--              if (rw == WRITE)
--                      bi->bi_end_io = raid5_end_write_request;
--              else
--                      bi->bi_end_io = raid5_end_read_request;
-- 
--              rcu_read_lock();
--              rdev = rcu_dereference(conf->disks[i].rdev);
--              if (rdev && test_bit(Faulty, &rdev->flags))
--                      rdev = NULL;
--              if (rdev)
--                      atomic_inc(&rdev->nr_pending);
--              rcu_read_unlock();
-- 
--              if (rdev) {
--                      if (syncing || expanding || expanded)
--                              md_sync_acct(rdev->bdev, STRIPE_SECTORS);
--                      bi->bi_bdev = rdev->bdev;
--                      PRINTK("for %llu schedule op %ld on disc %d\n",
--                              (unsigned long long)sh->sector, bi->bi_rw, i);
--                      atomic_inc(&sh->count);
--                      bi->bi_sector = sh->sector + rdev->data_offset;
--                      bi->bi_flags = 1 << BIO_UPTODATE;
--                      bi->bi_vcnt = 1;        
--                      bi->bi_max_vecs = 1;
--                      bi->bi_idx = 0;
--                      bi->bi_io_vec = &sh->dev[i].vec;
--                      bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
--                      bi->bi_io_vec[0].bv_offset = 0;
--                      bi->bi_size = STRIPE_SIZE;
--                      bi->bi_next = NULL;
--                      if (rw == WRITE &&
--                          test_bit(R5_ReWrite, &sh->dev[i].flags))
--                              atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
--                      generic_make_request(bi);
--              } else {
--                      if (rw == WRITE)
--                              set_bit(STRIPE_DEGRADED, &sh->state);
--                      PRINTK("skip op %ld on disc %d for sector %llu\n",
--                              bi->bi_rw, i, (unsigned long long)sh->sector);
--                      clear_bit(R5_LOCKED, &sh->dev[i].flags);
--                      set_bit(STRIPE_HANDLE, &sh->state);
-+                      /* done submitting copies, wait for them to complete */
-+                      if (i + 1 >= sh->disks) {
-+                              async_tx_ack(tx);
-+                              dma_wait_for_async_tx(tx);
-               }
-       }
- }
--static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
-+/*
-+ * handle_stripe - do things to a stripe.
-+ *
-+ * We lock the stripe and then examine the state of various bits
-+ * to see what needs to be done.
-+ * Possible results:
-+ *    return some read request which now have data
-+ *    return some write requests which are safely on disc
-+ *    schedule a read on some buffers
-+ *    schedule a write of some buffers
-+ *    return confirmation of parity correctness
-+ *
-+ * buffers are taken off read_list or write_list, and bh_cache buffers
-+ * get BH_Lock set before the stripe lock is released.
-+ *
-+ */
-+
-+static void handle_stripe5(struct stripe_head *sh)
- {
--      raid6_conf_t *conf = sh->raid_conf;
--      int disks = sh->disks;
--      struct bio *return_bi= NULL;
--      struct bio *bi;
--      int i;
--      int syncing, expanding, expanded;
--      int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
--      int non_overwrite = 0;
--      int failed_num[2] = {0, 0};
--      struct r5dev *dev, *pdev, *qdev;
--      int pd_idx = sh->pd_idx;
--      int qd_idx = raid6_next_disk(pd_idx, disks);
--      int p_failed, q_failed;
-+      raid5_conf_t *conf = sh->raid_conf;
-+      int disks = sh->disks, i;
-+      struct bio *return_bi = NULL, *bi;
-+      struct stripe_head_state s;
-+      struct r5dev *dev;
-+      unsigned long pending = 0;
--      PRINTK("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d, qd_idx=%d\n",
--             (unsigned long long)sh->sector, sh->state, atomic_read(&sh->count),
--             pd_idx, qd_idx);
-+      memset(&s, 0, sizeof(s));
-+      pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d "
-+              "ops=%lx:%lx:%lx\n", (unsigned long long)sh->sector, sh->state,
-+              atomic_read(&sh->count), sh->pd_idx,
-+              sh->ops.pending, sh->ops.ack, sh->ops.complete);
-       spin_lock(&sh->lock);
-       clear_bit(STRIPE_HANDLE, &sh->state);
-       clear_bit(STRIPE_DELAYED, &sh->state);
--      syncing = test_bit(STRIPE_SYNCING, &sh->state);
--      expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
--      expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
-+      s.syncing = test_bit(STRIPE_SYNCING, &sh->state);
-+      s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
-+      s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
-       /* Now to look around and see what can be done */
-       rcu_read_lock();
-       for (i=disks; i--; ) {
-               mdk_rdev_t *rdev;
--              dev = &sh->dev[i];
-+              struct r5dev *dev = &sh->dev[i];
-               clear_bit(R5_Insync, &dev->flags);
--              PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
--                      i, dev->flags, dev->toread, dev->towrite, dev->written);
--              /* maybe we can reply to a read */
--              if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
--                      struct bio *rbi, *rbi2;
--                      PRINTK("Return read for disc %d\n", i);
--                      spin_lock_irq(&conf->device_lock);
--                      rbi = dev->toread;
--                      dev->toread = NULL;
--                      if (test_and_clear_bit(R5_Overlap, &dev->flags))
--                              wake_up(&conf->wait_for_overlap);
--                      spin_unlock_irq(&conf->device_lock);
--                      while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
--                              copy_data(0, rbi, dev->page, dev->sector);
--                              rbi2 = r5_next_bio(rbi, dev->sector);
--                              spin_lock_irq(&conf->device_lock);
--                              if (--rbi->bi_phys_segments == 0) {
--                                      rbi->bi_next = return_bi;
--                                      return_bi = rbi;
--                              }
--                              spin_unlock_irq(&conf->device_lock);
--                              rbi = rbi2;
--                      }
--              }
--
--              /* now count some things */
--              if (test_bit(R5_LOCKED, &dev->flags)) locked++;
--              if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;
-+              pr_debug("check %d: state 0x%lx toread %p read %p write %p "
-+                      "written %p\n", i, dev->flags, dev->toread, dev->read,
-+                      dev->towrite, dev->written);
-+              /* maybe we can request a biofill operation
-+               *
-+               * new wantfill requests are only permitted while
-+               * STRIPE_OP_BIOFILL is clear
-+               */
-+              if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread &&
-+                      !test_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
-+                      set_bit(R5_Wantfill, &dev->flags);
--              if (dev->toread) to_read++;
-+              /* now count some things */
-+              if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;
-+              if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;
-+              if (test_bit(R5_Wantcompute, &dev->flags)) s.compute++;
-+
-+              if (test_bit(R5_Wantfill, &dev->flags))
-+                      s.to_fill++;
-+              else if (dev->toread)
-+                      s.to_read++;
-               if (dev->towrite) {
--                      to_write++;
-+                      s.to_write++;
-                       if (!test_bit(R5_OVERWRITE, &dev->flags))
--                              non_overwrite++;
-+                              s.non_overwrite++;
-               }
--              if (dev->written) written++;
-+              if (dev->written)
-+                      s.written++;
-               rdev = rcu_dereference(conf->disks[i].rdev);
-               if (!rdev || !test_bit(In_sync, &rdev->flags)) {
-                       /* The ReadError flag will just be confusing now */
-@@ -1962,376 +2668,361 @@
-               }
-               if (!rdev || !test_bit(In_sync, &rdev->flags)
-                   || test_bit(R5_ReadError, &dev->flags)) {
--                      if ( failed < 2 )
--                              failed_num[failed] = i;
--                      failed++;
-+                      s.failed++;
-+                      s.failed_num = i;
-               } else
-                       set_bit(R5_Insync, &dev->flags);
-       }
-       rcu_read_unlock();
--      PRINTK("locked=%d uptodate=%d to_read=%d"
--             " to_write=%d failed=%d failed_num=%d,%d\n",
--             locked, uptodate, to_read, to_write, failed,
--             failed_num[0], failed_num[1]);
--      /* check if the array has lost >2 devices and, if so, some requests might
--       * need to be failed
--       */
--      if (failed > 2 && to_read+to_write+written) {
--              for (i=disks; i--; ) {
--                      int bitmap_end = 0;
--
--                      if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
--                              mdk_rdev_t *rdev;
--                              rcu_read_lock();
--                              rdev = rcu_dereference(conf->disks[i].rdev);
--                              if (rdev && test_bit(In_sync, &rdev->flags))
--                                      /* multiple read failures in one stripe */
--                                      md_error(conf->mddev, rdev);
--                              rcu_read_unlock();
--                      }
--
--                      spin_lock_irq(&conf->device_lock);
--                      /* fail all writes first */
--                      bi = sh->dev[i].towrite;
--                      sh->dev[i].towrite = NULL;
--                      if (bi) { to_write--; bitmap_end = 1; }
--
--                      if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
--                              wake_up(&conf->wait_for_overlap);
--                      while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
--                              struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
--                              clear_bit(BIO_UPTODATE, &bi->bi_flags);
--                              if (--bi->bi_phys_segments == 0) {
--                                      md_write_end(conf->mddev);
--                                      bi->bi_next = return_bi;
--                                      return_bi = bi;
--                              }
--                              bi = nextbi;
--                      }
--                      /* and fail all 'written' */
--                      bi = sh->dev[i].written;
--                      sh->dev[i].written = NULL;
--                      if (bi) bitmap_end = 1;
--                      while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
--                              struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
--                              clear_bit(BIO_UPTODATE, &bi->bi_flags);
--                              if (--bi->bi_phys_segments == 0) {
--                                      md_write_end(conf->mddev);
--                                      bi->bi_next = return_bi;
--                                      return_bi = bi;
--                              }
--                              bi = bi2;
--                      }
-+      if (s.to_fill && !test_and_set_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
-+              sh->ops.count++;
--                      /* fail any reads if this device is non-operational */
--                      if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
--                          test_bit(R5_ReadError, &sh->dev[i].flags)) {
--                              bi = sh->dev[i].toread;
--                              sh->dev[i].toread = NULL;
--                              if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
--                                      wake_up(&conf->wait_for_overlap);
--                              if (bi) to_read--;
--                              while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
--                                      struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
--                                      clear_bit(BIO_UPTODATE, &bi->bi_flags);
--                                      if (--bi->bi_phys_segments == 0) {
--                                              bi->bi_next = return_bi;
--                                              return_bi = bi;
--                                      }
--                                      bi = nextbi;
--                              }
--                      }
--                      spin_unlock_irq(&conf->device_lock);
--                      if (bitmap_end)
--                              bitmap_endwrite(conf->mddev->bitmap, sh->sector,
--                                              STRIPE_SECTORS, 0, 0);
--              }
--      }
--      if (failed > 2 && syncing) {
-+      pr_debug("locked=%d uptodate=%d to_read=%d"
-+              " to_write=%d failed=%d failed_num=%d\n",
-+              s.locked, s.uptodate, s.to_read, s.to_write,
-+              s.failed, s.failed_num);
-+      /* check if the array has lost two devices and, if so, some requests might
-+       * need to be failed
-+       */
-+      if (s.failed > 1 && s.to_read+s.to_write+s.written)
-+              handle_requests_to_failed_array(conf, sh, &s, disks,
-+                                              &return_bi);
-+      if (s.failed > 1 && s.syncing) {
-               md_done_sync(conf->mddev, STRIPE_SECTORS,0);
-               clear_bit(STRIPE_SYNCING, &sh->state);
--              syncing = 0;
-+              s.syncing = 0;
-       }
--      /*
--       * might be able to return some write requests if the parity blocks
--       * are safe, or on a failed drive
--       */
--      pdev = &sh->dev[pd_idx];
--      p_failed = (failed >= 1 && failed_num[0] == pd_idx)
--              || (failed >= 2 && failed_num[1] == pd_idx);
--      qdev = &sh->dev[qd_idx];
--      q_failed = (failed >= 1 && failed_num[0] == qd_idx)
--              || (failed >= 2 && failed_num[1] == qd_idx);
--
--      if ( written &&
--           ( p_failed || ((test_bit(R5_Insync, &pdev->flags)
--                           && !test_bit(R5_LOCKED, &pdev->flags)
--                           && test_bit(R5_UPTODATE, &pdev->flags))) ) &&
--           ( q_failed || ((test_bit(R5_Insync, &qdev->flags)
--                           && !test_bit(R5_LOCKED, &qdev->flags)
--                           && test_bit(R5_UPTODATE, &qdev->flags))) ) ) {
--              /* any written block on an uptodate or failed drive can be
--               * returned.  Note that if we 'wrote' to a failed drive,
--               * it will be UPTODATE, but never LOCKED, so we don't need
--               * to test 'failed' directly.
-+      /* might be able to return some write requests if the parity block
-+       * is safe, or on a failed drive
-                */
--              for (i=disks; i--; )
--                      if (sh->dev[i].written) {
--                              dev = &sh->dev[i];
--                              if (!test_bit(R5_LOCKED, &dev->flags) &&
--                                  test_bit(R5_UPTODATE, &dev->flags) ) {
--                                      /* We can return any write requests */
--                                      int bitmap_end = 0;
--                                      struct bio *wbi, *wbi2;
--                                      PRINTK("Return write for stripe %llu disc %d\n",
--                                             (unsigned long long)sh->sector, i);
--                                      spin_lock_irq(&conf->device_lock);
--                                      wbi = dev->written;
--                                      dev->written = NULL;
--                                      while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
--                                              wbi2 = r5_next_bio(wbi, dev->sector);
--                                              if (--wbi->bi_phys_segments == 0) {
--                                                      md_write_end(conf->mddev);
--                                                      wbi->bi_next = return_bi;
--                                                      return_bi = wbi;
--                                              }
--                                              wbi = wbi2;
--                                      }
--                                      if (dev->towrite == NULL)
--                                              bitmap_end = 1;
--                                      spin_unlock_irq(&conf->device_lock);
--                                      if (bitmap_end)
--                                              bitmap_endwrite(conf->mddev->bitmap, sh->sector,
--                                                              STRIPE_SECTORS,
--                                                              !test_bit(STRIPE_DEGRADED, &sh->state), 0);
--                              }
--                      }
--      }
-+      dev = &sh->dev[sh->pd_idx];
-+      if ( s.written &&
-+           ((test_bit(R5_Insync, &dev->flags) &&
-+             !test_bit(R5_LOCKED, &dev->flags) &&
-+             test_bit(R5_UPTODATE, &dev->flags)) ||
-+             (s.failed == 1 && s.failed_num == sh->pd_idx)))
-+              handle_completed_write_requests(conf, sh, disks, &return_bi);
-       /* Now we might consider reading some blocks, either to check/generate
-        * parity, or to satisfy requests
-        * or to load a block that is being partially written.
-        */
--      if (to_read || non_overwrite || (to_write && failed) ||
--          (syncing && (uptodate < disks)) || expanding) {
--              for (i=disks; i--;) {
--                      dev = &sh->dev[i];
--                      if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
--                          (dev->toread ||
--                           (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
--                           syncing ||
--                           expanding ||
--                           (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) ||
--                           (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write))
--                                  )
--                              ) {
--                              /* we would like to get this block, possibly
--                               * by computing it, but we might not be able to
-+      if (s.to_read || s.non_overwrite ||
-+          (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding ||
-+          test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
-+              handle_issuing_new_read_requests5(sh, &s, disks);
-+
-+      /* Now we check to see if any write operations have recently
-+       * completed
-                                */
--                              if (uptodate == disks-1) {
--                                      PRINTK("Computing stripe %llu block %d\n",
--                                             (unsigned long long)sh->sector, i);
--                                      compute_block_1(sh, i, 0);
--                                      uptodate++;
--                              } else if ( uptodate == disks-2 && failed >= 2 ) {
--                                      /* Computing 2-failure is *very* expensive; only do it if failed >= 2 */
--                                      int other;
--                                      for (other=disks; other--;) {
--                                              if ( other == i )
--                                                      continue;
--                                              if ( !test_bit(R5_UPTODATE, &sh->dev[other].flags) )
--                                                      break;
--                                      }
--                                      BUG_ON(other < 0);
--                                      PRINTK("Computing stripe %llu blocks %d,%d\n",
--                                             (unsigned long long)sh->sector, i, other);
--                                      compute_block_2(sh, i, other);
--                                      uptodate += 2;
--                              } else if (test_bit(R5_Insync, &dev->flags)) {
--                                      set_bit(R5_LOCKED, &dev->flags);
--                                      set_bit(R5_Wantread, &dev->flags);
--                                      locked++;
--                                      PRINTK("Reading block %d (sync=%d)\n",
--                                              i, syncing);
--                              }
--                      }
--              }
--              set_bit(STRIPE_HANDLE, &sh->state);
-+
-+      /* leave prexor set until postxor is done, allows us to distinguish
-+       * a rmw from a rcw during biodrain
-+       */
-+      if (test_bit(STRIPE_OP_PREXOR, &sh->ops.complete) &&
-+              test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
-+
-+              clear_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
-+              clear_bit(STRIPE_OP_PREXOR, &sh->ops.ack);
-+              clear_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
-+
-+              for (i = disks; i--; )
-+                      clear_bit(R5_Wantprexor, &sh->dev[i].flags);
-       }
--      /* now to consider writing and what else, if anything should be read */
--      if (to_write) {
--              int rcw=0, must_compute=0;
--              for (i=disks ; i--;) {
-+      /* if only POSTXOR is set then this is an 'expand' postxor */
-+      if (test_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete) &&
-+              test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
-+
-+              clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
-+              clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.ack);
-+              clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
-+
-+              clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
-+              clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
-+              clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
-+
-+              /* All the 'written' buffers and the parity block are ready to
-+               * be written back to disk
-+               */
-+              BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
-+              for (i = disks; i--; ) {
-                       dev = &sh->dev[i];
--                      /* Would I have to read this buffer for reconstruct_write */
--                      if (!test_bit(R5_OVERWRITE, &dev->flags)
--                          && i != pd_idx && i != qd_idx
--                          && (!test_bit(R5_LOCKED, &dev->flags)
--                                  ) &&
--                          !test_bit(R5_UPTODATE, &dev->flags)) {
--                              if (test_bit(R5_Insync, &dev->flags)) rcw++;
--                              else {
--                                      PRINTK("raid6: must_compute: disk %d flags=%#lx\n", i, dev->flags);
--                                      must_compute++;
-+                      if (test_bit(R5_LOCKED, &dev->flags) &&
-+                              (i == sh->pd_idx || dev->written)) {
-+                              pr_debug("Writing block %d\n", i);
-+                              set_bit(R5_Wantwrite, &dev->flags);
-+                              if (!test_and_set_bit(
-+                                  STRIPE_OP_IO, &sh->ops.pending))
-+                                      sh->ops.count++;
-+                              if (!test_bit(R5_Insync, &dev->flags) ||
-+                                  (i == sh->pd_idx && s.failed == 0))
-+                                      set_bit(STRIPE_INSYNC, &sh->state);
-+                      }
-                               }
-+              if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-+                      atomic_dec(&conf->preread_active_stripes);
-+                      if (atomic_read(&conf->preread_active_stripes) <
-+                              IO_THRESHOLD)
-+                              md_wakeup_thread(conf->mddev->thread);
-                       }
-               }
--              PRINTK("for sector %llu, rcw=%d, must_compute=%d\n",
--                     (unsigned long long)sh->sector, rcw, must_compute);
--              set_bit(STRIPE_HANDLE, &sh->state);
--              if (rcw > 0)
--                      /* want reconstruct write, but need to get some data */
--                      for (i=disks; i--;) {
--                              dev = &sh->dev[i];
--                              if (!test_bit(R5_OVERWRITE, &dev->flags)
--                                  && !(failed == 0 && (i == pd_idx || i == qd_idx))
--                                  && !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
--                                  test_bit(R5_Insync, &dev->flags)) {
--                                      if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
--                                      {
--                                              PRINTK("Read_old stripe %llu block %d for Reconstruct\n",
--                                                     (unsigned long long)sh->sector, i);
-+      /* Now to consider new write requests and what else, if anything
-+       * should be read.  We do not handle new writes when:
-+       * 1/ A 'write' operation (copy+xor) is already in flight.
-+       * 2/ A 'check' operation is in flight, as it may clobber the parity
-+       *    block.
-+       */
-+      if (s.to_write && !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending) &&
-+                        !test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
-+              handle_issuing_new_write_requests5(conf, sh, &s, disks);
-+
-+      /* maybe we need to check and possibly fix the parity for this stripe
-+       * Any reads will already have been scheduled, so we just see if enough
-+       * data is available.  The parity check is held off while parity
-+       * dependent operations are in flight.
-+       */
-+      if ((s.syncing && s.locked == 0 &&
-+           !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
-+           !test_bit(STRIPE_INSYNC, &sh->state)) ||
-+            test_bit(STRIPE_OP_CHECK, &sh->ops.pending) ||
-+            test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending))
-+              handle_parity_checks5(conf, sh, &s, disks);
-+
-+      if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
-+              md_done_sync(conf->mddev, STRIPE_SECTORS,1);
-+              clear_bit(STRIPE_SYNCING, &sh->state);
-+      }
-+
-+      /* If the failed drive is just a ReadError, then we might need to progress
-+       * the repair/check process
-+       */
-+      if (s.failed == 1 && !conf->mddev->ro &&
-+          test_bit(R5_ReadError, &sh->dev[s.failed_num].flags)
-+          && !test_bit(R5_LOCKED, &sh->dev[s.failed_num].flags)
-+          && test_bit(R5_UPTODATE, &sh->dev[s.failed_num].flags)
-+              ) {
-+              dev = &sh->dev[s.failed_num];
-+              if (!test_bit(R5_ReWrite, &dev->flags)) {
-+                      set_bit(R5_Wantwrite, &dev->flags);
-+                      if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
-+                              sh->ops.count++;
-+                      set_bit(R5_ReWrite, &dev->flags);
-                                               set_bit(R5_LOCKED, &dev->flags);
--                                              set_bit(R5_Wantread, &dev->flags);
--                                              locked++;
-+                      s.locked++;
-                                       } else {
--                                              PRINTK("Request delayed stripe %llu block %d for Reconstruct\n",
--                                                     (unsigned long long)sh->sector, i);
--                                              set_bit(STRIPE_DELAYED, &sh->state);
--                                              set_bit(STRIPE_HANDLE, &sh->state);
-+                      /* let's read it back */
-+                      set_bit(R5_Wantread, &dev->flags);
-+                      if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
-+                              sh->ops.count++;
-+                      set_bit(R5_LOCKED, &dev->flags);
-+                      s.locked++;
-                                       }
-                               }
-+
-+      /* Finish postxor operations initiated by the expansion
-+       * process
-+       */
-+      if (test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete) &&
-+              !test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending)) {
-+
-+              clear_bit(STRIPE_EXPANDING, &sh->state);
-+
-+              clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
-+              clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
-+              clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
-+
-+              for (i = conf->raid_disks; i--; ) {
-+                      set_bit(R5_Wantwrite, &sh->dev[i].flags);
-+                      if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
-+                              sh->ops.count++;
-                       }
--              /* now if nothing is locked, and if we have enough data, we can start a write request */
--              if (locked == 0 && rcw == 0 &&
--                  !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
--                      if ( must_compute > 0 ) {
--                              /* We have failed blocks and need to compute them */
--                              switch ( failed ) {
--                              case 0: BUG();
--                              case 1: compute_block_1(sh, failed_num[0], 0); break;
--                              case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break;
--                              default: BUG(); /* This request should have been failed? */
-                               }
-+
-+      if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state) &&
-+              !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
-+              /* Need to write out all blocks after computing parity */
-+              sh->disks = conf->raid_disks;
-+              sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
-+                      conf->raid_disks);
-+              s.locked += handle_write_operations5(sh, 0, 1);
-+      } else if (s.expanded &&
-+              !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
-+              clear_bit(STRIPE_EXPAND_READY, &sh->state);
-+              atomic_dec(&conf->reshape_stripes);
-+              wake_up(&conf->wait_for_overlap);
-+              md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
-                       }
--                      PRINTK("Computing parity for stripe %llu\n", (unsigned long long)sh->sector);
--                      compute_parity6(sh, RECONSTRUCT_WRITE);
--                      /* now every locked buffer is ready to be written */
--                      for (i=disks; i--;)
--                              if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
--                                      PRINTK("Writing stripe %llu block %d\n",
--                                             (unsigned long long)sh->sector, i);
--                                      locked++;
--                                      set_bit(R5_Wantwrite, &sh->dev[i].flags);
-+      if (s.expanding && s.locked == 0)
-+              handle_stripe_expansion(conf, sh, NULL);
-+
-+      if (sh->ops.count)
-+              pending = get_stripe_work(sh);
-+
-+      spin_unlock(&sh->lock);
-+
-+      if (pending)
-+              raid5_run_ops(sh, pending);
-+
-+      while ((bi=return_bi)) {
-+              int bytes = bi->bi_size;
-+
-+              return_bi = bi->bi_next;
-+              bi->bi_next = NULL;
-+              bi->bi_size = 0;
-+              bi->bi_end_io(bi, bytes,
-+                            test_bit(BIO_UPTODATE, &bi->bi_flags)
-+                              ? 0 : -EIO);
-                               }
--                      /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
--                      set_bit(STRIPE_INSYNC, &sh->state);
-+}
--                      if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
--                              atomic_dec(&conf->preread_active_stripes);
--                              if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
--                                      md_wakeup_thread(conf->mddev->thread);
-+static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
-+{
-+      raid6_conf_t *conf = sh->raid_conf;
-+      int disks = sh->disks;
-+      struct bio *return_bi = NULL;
-+      struct bio *bi;
-+      int i, pd_idx = sh->pd_idx;
-+      struct stripe_head_state s;
-+      struct r6_state r6s;
-+      struct r5dev *dev, *pdev, *qdev;
-+
-+      r6s.qd_idx = raid6_next_disk(pd_idx, disks);
-+      pr_debug("handling stripe %llu, state=%#lx cnt=%d, "
-+              "pd_idx=%d, qd_idx=%d\n",
-+             (unsigned long long)sh->sector, sh->state,
-+             atomic_read(&sh->count), pd_idx, r6s.qd_idx);
-+      memset(&s, 0, sizeof(s));
-+
-+      spin_lock(&sh->lock);
-+      clear_bit(STRIPE_HANDLE, &sh->state);
-+      clear_bit(STRIPE_DELAYED, &sh->state);
-+
-+      s.syncing = test_bit(STRIPE_SYNCING, &sh->state);
-+      s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
-+      s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
-+      /* Now to look around and see what can be done */
-+
-+      rcu_read_lock();
-+      for (i=disks; i--; ) {
-+              mdk_rdev_t *rdev;
-+              dev = &sh->dev[i];
-+              clear_bit(R5_Insync, &dev->flags);
-+
-+              pr_debug("check %d: state 0x%lx read %p write %p written %p\n",
-+                      i, dev->flags, dev->toread, dev->towrite, dev->written);
-+              /* maybe we can reply to a read */
-+              if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
-+                      struct bio *rbi, *rbi2;
-+                      pr_debug("Return read for disc %d\n", i);
-+                      spin_lock_irq(&conf->device_lock);
-+                      rbi = dev->toread;
-+                      dev->toread = NULL;
-+                      if (test_and_clear_bit(R5_Overlap, &dev->flags))
-+                              wake_up(&conf->wait_for_overlap);
-+                      spin_unlock_irq(&conf->device_lock);
-+                      while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
-+                              copy_data(0, rbi, dev->page, dev->sector);
-+                              rbi2 = r5_next_bio(rbi, dev->sector);
-+                              spin_lock_irq(&conf->device_lock);
-+                              if (--rbi->bi_phys_segments == 0) {
-+                                      rbi->bi_next = return_bi;
-+                                      return_bi = rbi;
-                       }
-+                              spin_unlock_irq(&conf->device_lock);
-+                              rbi = rbi2;
-               }
-       }
--      /* maybe we need to check and possibly fix the parity for this stripe
--       * Any reads will already have been scheduled, so we just see if enough data
--       * is available
--       */
--      if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) {
--              int update_p = 0, update_q = 0;
--              struct r5dev *dev;
--
--              set_bit(STRIPE_HANDLE, &sh->state);
-+              /* now count some things */
-+              if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;
-+              if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;
--              BUG_ON(failed>2);
--              BUG_ON(uptodate < disks);
--              /* Want to check and possibly repair P and Q.
--               * However there could be one 'failed' device, in which
--               * case we can only check one of them, possibly using the
--               * other to generate missing data
--               */
--              /* If !tmp_page, we cannot do the calculations,
--               * but as we have set STRIPE_HANDLE, we will soon be called
--               * by stripe_handle with a tmp_page - just wait until then.
--               */
--              if (tmp_page) {
--                      if (failed == q_failed) {
--                              /* The only possible failed device holds 'Q', so it makes
--                               * sense to check P (If anything else were failed, we would
--                               * have used P to recreate it).
--                               */
--                              compute_block_1(sh, pd_idx, 1);
--                              if (!page_is_zero(sh->dev[pd_idx].page)) {
--                                      compute_block_1(sh,pd_idx,0);
--                                      update_p = 1;
--                              }
-+              if (dev->toread)
-+                      s.to_read++;
-+              if (dev->towrite) {
-+                      s.to_write++;
-+                      if (!test_bit(R5_OVERWRITE, &dev->flags))
-+                              s.non_overwrite++;
-                       }
--                      if (!q_failed && failed < 2) {
--                              /* q is not failed, and we didn't use it to generate
--                               * anything, so it makes sense to check it
--                               */
--                              memcpy(page_address(tmp_page),
--                                     page_address(sh->dev[qd_idx].page),
--                                     STRIPE_SIZE);
--                              compute_parity6(sh, UPDATE_PARITY);
--                              if (memcmp(page_address(tmp_page),
--                                         page_address(sh->dev[qd_idx].page),
--                                         STRIPE_SIZE)!= 0) {
--                                      clear_bit(STRIPE_INSYNC, &sh->state);
--                                      update_q = 1;
-+              if (dev->written)
-+                      s.written++;
-+              rdev = rcu_dereference(conf->disks[i].rdev);
-+              if (!rdev || !test_bit(In_sync, &rdev->flags)) {
-+                      /* The ReadError flag will just be confusing now */
-+                      clear_bit(R5_ReadError, &dev->flags);
-+                      clear_bit(R5_ReWrite, &dev->flags);
-                               }
-+              if (!rdev || !test_bit(In_sync, &rdev->flags)
-+                  || test_bit(R5_ReadError, &dev->flags)) {
-+                      if (s.failed < 2)
-+                              r6s.failed_num[s.failed] = i;
-+                      s.failed++;
-+              } else
-+                      set_bit(R5_Insync, &dev->flags);
-                       }
--                      if (update_p || update_q) {
--                              conf->mddev->resync_mismatches += STRIPE_SECTORS;
--                              if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
--                                      /* don't try to repair!! */
--                                      update_p = update_q = 0;
-+      rcu_read_unlock();
-+      pr_debug("locked=%d uptodate=%d to_read=%d"
-+             " to_write=%d failed=%d failed_num=%d,%d\n",
-+             s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
-+             r6s.failed_num[0], r6s.failed_num[1]);
-+      /* check if the array has lost >2 devices and, if so, some requests
-+       * might need to be failed
-+       */
-+      if (s.failed > 2 && s.to_read+s.to_write+s.written)
-+              handle_requests_to_failed_array(conf, sh, &s, disks,
-+                                              &return_bi);
-+      if (s.failed > 2 && s.syncing) {
-+              md_done_sync(conf->mddev, STRIPE_SECTORS,0);
-+              clear_bit(STRIPE_SYNCING, &sh->state);
-+              s.syncing = 0;
-                       }
--                      /* now write out any block on a failed drive,
--                       * or P or Q if they need it
-+      /*
-+       * might be able to return some write requests if the parity blocks
-+       * are safe, or on a failed drive
-                        */
-+      pdev = &sh->dev[pd_idx];
-+      r6s.p_failed = (s.failed >= 1 && r6s.failed_num[0] == pd_idx)
-+              || (s.failed >= 2 && r6s.failed_num[1] == pd_idx);
-+      qdev = &sh->dev[r6s.qd_idx];
-+      r6s.q_failed = (s.failed >= 1 && r6s.failed_num[0] == r6s.qd_idx)
-+              || (s.failed >= 2 && r6s.failed_num[1] == r6s.qd_idx);
--                      if (failed == 2) {
--                              dev = &sh->dev[failed_num[1]];
--                              locked++;
--                              set_bit(R5_LOCKED, &dev->flags);
--                              set_bit(R5_Wantwrite, &dev->flags);
--                      }
--                      if (failed >= 1) {
--                              dev = &sh->dev[failed_num[0]];
--                              locked++;
--                              set_bit(R5_LOCKED, &dev->flags);
--                              set_bit(R5_Wantwrite, &dev->flags);
--                      }
-+      if ( s.written &&
-+           ( r6s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
-+                           && !test_bit(R5_LOCKED, &pdev->flags)
-+                           && test_bit(R5_UPTODATE, &pdev->flags)))) &&
-+           ( r6s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
-+                           && !test_bit(R5_LOCKED, &qdev->flags)
-+                           && test_bit(R5_UPTODATE, &qdev->flags)))))
-+              handle_completed_write_requests(conf, sh, disks, &return_bi);
--                      if (update_p) {
--                              dev = &sh->dev[pd_idx];
--                              locked ++;
--                              set_bit(R5_LOCKED, &dev->flags);
--                              set_bit(R5_Wantwrite, &dev->flags);
--                      }
--                      if (update_q) {
--                              dev = &sh->dev[qd_idx];
--                              locked++;
--                              set_bit(R5_LOCKED, &dev->flags);
--                              set_bit(R5_Wantwrite, &dev->flags);
--                      }
--                      clear_bit(STRIPE_DEGRADED, &sh->state);
-+      /* Now we might consider reading some blocks, either to check/generate
-+       * parity, or to satisfy requests
-+       * or to load a block that is being partially written.
-+       */
-+      if (s.to_read || s.non_overwrite || (s.to_write && s.failed) ||
-+          (s.syncing && (s.uptodate < disks)) || s.expanding)
-+              handle_issuing_new_read_requests6(sh, &s, &r6s, disks);
--                      set_bit(STRIPE_INSYNC, &sh->state);
--              }
--      }
-+      /* now to consider writing and what else, if anything should be read */
-+      if (s.to_write)
-+              handle_issuing_new_write_requests6(conf, sh, &s, &r6s, disks);
-+
-+      /* maybe we need to check and possibly fix the parity for this stripe
-+       * Any reads will already have been scheduled, so we just see if enough
-+       * data is available
-+       */
-+      if (s.syncing && s.locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state))
-+              handle_parity_checks6(conf, sh, &s, &r6s, tmp_page, disks);
--      if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
-+      if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
-               md_done_sync(conf->mddev, STRIPE_SECTORS,1);
-               clear_bit(STRIPE_SYNCING, &sh->state);
-       }
-@@ -2339,9 +3030,9 @@
-       /* If the failed drives are just a ReadError, then we might need
-        * to progress the repair/check process
-        */
--      if (failed <= 2 && ! conf->mddev->ro)
--              for (i=0; i<failed;i++) {
--                      dev = &sh->dev[failed_num[i]];
-+      if (s.failed <= 2 && !conf->mddev->ro)
-+              for (i = 0; i < s.failed; i++) {
-+                      dev = &sh->dev[r6s.failed_num[i]];
-                       if (test_bit(R5_ReadError, &dev->flags)
-                           && !test_bit(R5_LOCKED, &dev->flags)
-                           && test_bit(R5_UPTODATE, &dev->flags)
-@@ -2358,7 +3049,7 @@
-                       }
-               }
--      if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
-+      if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
-               /* Need to write out all blocks after computing P&Q */
-               sh->disks = conf->raid_disks;
-               sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
-@@ -2366,69 +3057,19 @@
-               compute_parity6(sh, RECONSTRUCT_WRITE);
-               for (i = conf->raid_disks ; i-- ;  ) {
-                       set_bit(R5_LOCKED, &sh->dev[i].flags);
--                      locked++;
-+                      s.locked++;
-                       set_bit(R5_Wantwrite, &sh->dev[i].flags);
-               }
-               clear_bit(STRIPE_EXPANDING, &sh->state);
--      } else if (expanded) {
-+      } else if (s.expanded) {
-               clear_bit(STRIPE_EXPAND_READY, &sh->state);
-               atomic_dec(&conf->reshape_stripes);
-               wake_up(&conf->wait_for_overlap);
-               md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
-       }
--      if (expanding && locked == 0) {
--              /* We have read all the blocks in this stripe and now we need to
--               * copy some of them into a target stripe for expand.
--               */
--              clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
--              for (i = 0; i < sh->disks ; i++)
--                      if (i != pd_idx && i != qd_idx) {
--                              int dd_idx2, pd_idx2, j;
--                              struct stripe_head *sh2;
--
--                              sector_t bn = compute_blocknr(sh, i);
--                              sector_t s = raid5_compute_sector(
--                                      bn, conf->raid_disks,
--                                      conf->raid_disks - conf->max_degraded,
--                                      &dd_idx2, &pd_idx2, conf);
--                              sh2 = get_active_stripe(conf, s,
--                                                      conf->raid_disks,
--                                                     pd_idx2, 1);
--                              if (sh2 == NULL)
--                                      /* so for only the early blocks of
--                                       * this stripe have been requests.
--                                       * When later blocks get requests, we
--                                       * will try again
--                                       */
--                                      continue;
--                              if (!test_bit(STRIPE_EXPANDING, &sh2->state) ||
--                                  test_bit(R5_Expanded,
--                                           &sh2->dev[dd_idx2].flags)) {
--                                      /* must have already done this block */
--                                      release_stripe(sh2);
--                                      continue;
--                              }
--                              memcpy(page_address(sh2->dev[dd_idx2].page),
--                                     page_address(sh->dev[i].page),
--                                     STRIPE_SIZE);
--                              set_bit(R5_Expanded, &sh2->dev[dd_idx2].flags);
--                              set_bit(R5_UPTODATE, &sh2->dev[dd_idx2].flags);
--                              for (j = 0 ; j < conf->raid_disks ; j++)
--                                      if (j != sh2->pd_idx &&
--                                          j != raid6_next_disk(sh2->pd_idx,
--                                                         sh2->disks) &&
--                                          !test_bit(R5_Expanded,
--                                                    &sh2->dev[j].flags))
--                                              break;
--                              if (j == conf->raid_disks) {
--                                      set_bit(STRIPE_EXPAND_READY,
--                                              &sh2->state);
--                                      set_bit(STRIPE_HANDLE, &sh2->state);
--                              }
--                              release_stripe(sh2);
--                      }
--      }
-+      if (s.expanding && s.locked == 0)
-+              handle_stripe_expansion(conf, sh, &r6s);
-       spin_unlock(&sh->lock);
-@@ -2470,11 +3111,11 @@
-               rcu_read_unlock();
-               if (rdev) {
--                      if (syncing || expanding || expanded)
-+                      if (s.syncing || s.expanding || s.expanded)
-                               md_sync_acct(rdev->bdev, STRIPE_SECTORS);
-                       bi->bi_bdev = rdev->bdev;
--                      PRINTK("for %llu schedule op %ld on disc %d\n",
-+                      pr_debug("for %llu schedule op %ld on disc %d\n",
-                               (unsigned long long)sh->sector, bi->bi_rw, i);
-                       atomic_inc(&sh->count);
-                       bi->bi_sector = sh->sector + rdev->data_offset;
-@@ -2494,7 +3135,7 @@
-               } else {
-                       if (rw == WRITE)
-                               set_bit(STRIPE_DEGRADED, &sh->state);
--                      PRINTK("skip op %ld on disc %d for sector %llu\n",
-+                      pr_debug("skip op %ld on disc %d for sector %llu\n",
-                               bi->bi_rw, i, (unsigned long long)sh->sector);
-                       clear_bit(R5_LOCKED, &sh->dev[i].flags);
-                       set_bit(STRIPE_HANDLE, &sh->state);
-@@ -2738,7 +3379,7 @@
-       }
--      PRINTK("raid5_align_endio : io error...handing IO for a retry\n");
-+      pr_debug("raid5_align_endio : io error...handing IO for a retry\n");
-       add_bio_to_retry(raid_bi, conf);
-       return 0;
-@@ -2776,7 +3417,7 @@
-       mdk_rdev_t *rdev;
-       if (!in_chunk_boundary(mddev, raid_bio)) {
--              PRINTK("chunk_aligned_read : non aligned\n");
-+              pr_debug("chunk_aligned_read : non aligned\n");
-               return 0;
-       }
-       /*
-@@ -2900,7 +3541,7 @@
-               new_sector = raid5_compute_sector(logical_sector, disks, data_disks,
-                                                 &dd_idx, &pd_idx, conf);
--              PRINTK("raid5: make_request, sector %llu logical %llu\n",
-+              pr_debug("raid5: make_request, sector %llu logical %llu\n",
-                       (unsigned long long)new_sector, 
-                       (unsigned long long)logical_sector);
-@@ -3273,7 +3914,7 @@
-       raid5_conf_t *conf = mddev_to_conf(mddev);
-       int handled;
--      PRINTK("+++ raid5d active\n");
-+      pr_debug("+++ raid5d active\n");
-       md_check_recovery(mddev);
-@@ -3308,8 +3949,10 @@
-                       handled++;
-               }
--              if (list_empty(&conf->handle_list))
-+              if (list_empty(&conf->handle_list)) {
-+                      async_tx_issue_pending_all();
-                       break;
-+              }
-               first = conf->handle_list.next;
-               sh = list_entry(first, struct stripe_head, lru);
-@@ -3325,13 +3968,13 @@
-               spin_lock_irq(&conf->device_lock);
-       }
--      PRINTK("%d stripes handled\n", handled);
-+      pr_debug("%d stripes handled\n", handled);
-       spin_unlock_irq(&conf->device_lock);
-       unplug_slaves(mddev);
--      PRINTK("--- raid5d inactive\n");
-+      pr_debug("--- raid5d inactive\n");
- }
- static ssize_t
-@@ -3507,7 +4150,7 @@
-       atomic_set(&conf->preread_active_stripes, 0);
-       atomic_set(&conf->active_aligned_reads, 0);
--      PRINTK("raid5: run(%s) called.\n", mdname(mddev));
-+      pr_debug("raid5: run(%s) called.\n", mdname(mddev));
-       ITERATE_RDEV(mddev,rdev,tmp) {
-               raid_disk = rdev->raid_disk;
-@@ -3690,7 +4333,7 @@
-       return 0;
- }
--#if RAID5_DEBUG
-+#ifdef DEBUG
- static void print_sh (struct seq_file *seq, struct stripe_head *sh)
- {
-       int i;
-@@ -3737,7 +4380,7 @@
-                              conf->disks[i].rdev &&
-                              test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_");
-       seq_printf (seq, "]");
--#if RAID5_DEBUG
-+#ifdef DEBUG
-       seq_printf (seq, "\n");
-       printall(seq, conf);
- #endif
-diff -Nurb linux-2.6.22-570/drivers/md/xor.c linux-2.6.22-590/drivers/md/xor.c
---- linux-2.6.22-570/drivers/md/xor.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/md/xor.c  1969-12-31 19:00:00.000000000 -0500
-@@ -1,154 +0,0 @@
--/*
-- * xor.c : Multiple Devices driver for Linux
-- *
-- * Copyright (C) 1996, 1997, 1998, 1999, 2000,
-- * Ingo Molnar, Matti Aarnio, Jakub Jelinek, Richard Henderson.
-- *
-- * Dispatch optimized RAID-5 checksumming functions.
-- *
-- * 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, or (at your option)
-- * any later version.
-- *
-- * You should have received a copy of the GNU General Public License
-- * (for example /usr/src/linux/COPYING); if not, write to the Free
-- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-- */
--
--#define BH_TRACE 0
--#include <linux/module.h>
--#include <linux/raid/md.h>
--#include <linux/raid/xor.h>
--#include <asm/xor.h>
--
--/* The xor routines to use.  */
--static struct xor_block_template *active_template;
--
--void
--xor_block(unsigned int count, unsigned int bytes, void **ptr)
--{
--      unsigned long *p0, *p1, *p2, *p3, *p4;
--
--      p0 = (unsigned long *) ptr[0];
--      p1 = (unsigned long *) ptr[1];
--      if (count == 2) {
--              active_template->do_2(bytes, p0, p1);
--              return;
--      }
--
--      p2 = (unsigned long *) ptr[2];
--      if (count == 3) {
--              active_template->do_3(bytes, p0, p1, p2);
--              return;
--      }
--
--      p3 = (unsigned long *) ptr[3];
--      if (count == 4) {
--              active_template->do_4(bytes, p0, p1, p2, p3);
--              return;
--      }
--
--      p4 = (unsigned long *) ptr[4];
--      active_template->do_5(bytes, p0, p1, p2, p3, p4);
--}
--
--/* Set of all registered templates.  */
--static struct xor_block_template *template_list;
--
--#define BENCH_SIZE (PAGE_SIZE)
--
--static void
--do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
--{
--      int speed;
--      unsigned long now;
--      int i, count, max;
--
--      tmpl->next = template_list;
--      template_list = tmpl;
--
--      /*
--       * Count the number of XORs done during a whole jiffy, and use
--       * this to calculate the speed of checksumming.  We use a 2-page
--       * allocation to have guaranteed color L1-cache layout.
--       */
--      max = 0;
--      for (i = 0; i < 5; i++) {
--              now = jiffies;
--              count = 0;
--              while (jiffies == now) {
--                      mb();
--                      tmpl->do_2(BENCH_SIZE, b1, b2);
--                      mb();
--                      count++;
--                      mb();
--              }
--              if (count > max)
--                      max = count;
--      }
--
--      speed = max * (HZ * BENCH_SIZE / 1024);
--      tmpl->speed = speed;
--
--      printk("   %-10s: %5d.%03d MB/sec\n", tmpl->name,
--             speed / 1000, speed % 1000);
--}
--
--static int
--calibrate_xor_block(void)
--{
--      void *b1, *b2;
--      struct xor_block_template *f, *fastest;
--
--      b1 = (void *) __get_free_pages(GFP_KERNEL, 2);
--      if (! b1) {
--              printk("raid5: Yikes!  No memory available.\n");
--              return -ENOMEM;
--      }
--      b2 = b1 + 2*PAGE_SIZE + BENCH_SIZE;
--
--      /*
--       * If this arch/cpu has a short-circuited selection, don't loop through all
--       * the possible functions, just test the best one
--       */
--
--      fastest = NULL;
--
--#ifdef XOR_SELECT_TEMPLATE
--              fastest = XOR_SELECT_TEMPLATE(fastest);
--#endif
--
--#define xor_speed(templ)      do_xor_speed((templ), b1, b2)
--
--      if (fastest) {
--              printk(KERN_INFO "raid5: automatically using best checksumming function: %s\n",
--                      fastest->name);
--              xor_speed(fastest);
--      } else {
--              printk(KERN_INFO "raid5: measuring checksumming speed\n");
--              XOR_TRY_TEMPLATES;
--              fastest = template_list;
--              for (f = fastest; f; f = f->next)
--                      if (f->speed > fastest->speed)
--                              fastest = f;
--      }
--
--      printk("raid5: using function: %s (%d.%03d MB/sec)\n",
--             fastest->name, fastest->speed / 1000, fastest->speed % 1000);
--
--#undef xor_speed
--
--      free_pages((unsigned long)b1, 2);
--
--      active_template = fastest;
--      return 0;
--}
--
--static __exit void xor_exit(void) { }
--
--EXPORT_SYMBOL(xor_block);
--MODULE_LICENSE("GPL");
--
--module_init(calibrate_xor_block);
--module_exit(xor_exit);
-diff -Nurb linux-2.6.22-570/drivers/media/dvb/dvb-core/dvb_frontend.c linux-2.6.22-590/drivers/media/dvb/dvb-core/dvb_frontend.c
---- linux-2.6.22-570/drivers/media/dvb/dvb-core/dvb_frontend.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/media/dvb/dvb-core/dvb_frontend.c 2008-01-02 13:56:37.000000000 -0500
-@@ -523,6 +523,7 @@
-       dvb_frontend_init(fe);
-+      set_freezable();
-       while (1) {
-               up(&fepriv->sem);           /* is locked when we enter the thread... */
- restart:
-diff -Nurb linux-2.6.22-570/drivers/media/video/cx88/cx88-tvaudio.c linux-2.6.22-590/drivers/media/video/cx88/cx88-tvaudio.c
---- linux-2.6.22-570/drivers/media/video/cx88/cx88-tvaudio.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/media/video/cx88/cx88-tvaudio.c   2008-01-02 13:56:37.000000000 -0500
-@@ -906,6 +906,7 @@
-       u32 mode = 0;
-       dprintk("cx88: tvaudio thread started\n");
-+      set_freezable();
-       for (;;) {
-               msleep_interruptible(1000);
-               if (kthread_should_stop())
-diff -Nurb linux-2.6.22-570/drivers/media/video/msp3400-kthreads.c linux-2.6.22-590/drivers/media/video/msp3400-kthreads.c
---- linux-2.6.22-570/drivers/media/video/msp3400-kthreads.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/media/video/msp3400-kthreads.c    2008-01-02 13:56:37.000000000 -0500
-@@ -23,6 +23,7 @@
- #include <linux/module.h>
- #include <linux/slab.h>
- #include <linux/i2c.h>
-+#include <linux/freezer.h>
- #include <linux/videodev.h>
- #include <linux/videodev2.h>
- #include <media/v4l2-common.h>
-@@ -468,6 +469,7 @@
-       v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
-+      set_freezable();
-       for (;;) {
-               v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
-               msp_sleep(state, -1);
-@@ -646,7 +648,7 @@
-       int val, i, std, count;
-       v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
--
-+      set_freezable();
-       for (;;) {
-               v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
-               msp_sleep(state,-1);
-@@ -940,7 +942,7 @@
-       int val, i;
-       v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
--
-+      set_freezable();
-       for (;;) {
-               v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
-               msp_sleep(state, -1);
-diff -Nurb linux-2.6.22-570/drivers/media/video/tvaudio.c linux-2.6.22-590/drivers/media/video/tvaudio.c
---- linux-2.6.22-570/drivers/media/video/tvaudio.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/media/video/tvaudio.c     2008-01-02 13:56:37.000000000 -0500
-@@ -271,7 +271,7 @@
-       struct CHIPDESC  *desc = chiplist + chip->type;
-       v4l_dbg(1, debug, &chip->c, "%s: thread started\n", chip->c.name);
--
-+      set_freezable();
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (!kthread_should_stop())
-diff -Nurb linux-2.6.22-570/drivers/media/video/video-buf-dvb.c linux-2.6.22-590/drivers/media/video/video-buf-dvb.c
---- linux-2.6.22-570/drivers/media/video/video-buf-dvb.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/media/video/video-buf-dvb.c       2008-01-02 13:56:37.000000000 -0500
-@@ -47,6 +47,7 @@
-       int err;
-       dprintk("dvb thread started\n");
-+      set_freezable();
-       videobuf_read_start(&dvb->dvbq);
-       for (;;) {
-diff -Nurb linux-2.6.22-570/drivers/media/video/vivi.c linux-2.6.22-590/drivers/media/video/vivi.c
---- linux-2.6.22-570/drivers/media/video/vivi.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/media/video/vivi.c        2008-01-02 13:56:37.000000000 -0500
-@@ -573,6 +573,7 @@
-       dprintk(1,"thread started\n");
-       mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
-+      set_freezable();
-       for (;;) {
-               vivi_sleep(dma_q);
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/linux_compat.h linux-2.6.22-590/drivers/message/fusion/linux_compat.h
---- linux-2.6.22-570/drivers/message/fusion/linux_compat.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/linux_compat.h     1969-12-31 19:00:00.000000000 -0500
-@@ -1,9 +0,0 @@
--/* drivers/message/fusion/linux_compat.h */
--
--#ifndef FUSION_LINUX_COMPAT_H
--#define FUSION_LINUX_COMPAT_H
--
--#include <linux/version.h>
--#include <scsi/scsi_device.h>
--
--#endif /* _LINUX_COMPAT_H */
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/lsi/mpi.h linux-2.6.22-590/drivers/message/fusion/lsi/mpi.h
---- linux-2.6.22-570/drivers/message/fusion/lsi/mpi.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/lsi/mpi.h  2008-01-02 13:56:37.000000000 -0500
-@@ -1,12 +1,12 @@
- /*
-- *  Copyright (c) 2000-2006 LSI Logic Corporation.
-+ *  Copyright (c) 2000-2007 LSI Logic Corporation.
-  *
-  *
-  *           Name:  mpi.h
-  *          Title:  MPI Message independent structures and definitions
-  *  Creation Date:  July 27, 2000
-  *
-- *    mpi.h Version:  01.05.12
-+ *    mpi.h Version:  01.05.13
-  *
-  *  Version History
-  *  ---------------
-@@ -78,6 +78,7 @@
-  *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
-  *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
-  *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
-+ *  05-24-07  01.05.13  Bumped MPI_HEADER_VERSION_UNIT.
-  *  --------------------------------------------------------------------------
-  */
-@@ -108,7 +109,7 @@
- /* Note: The major versions of 0xe0 through 0xff are reserved */
- /* versioning for this MPI header set */
--#define MPI_HEADER_VERSION_UNIT             (0x0E)
-+#define MPI_HEADER_VERSION_UNIT             (0x10)
- #define MPI_HEADER_VERSION_DEV              (0x00)
- #define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
- #define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/lsi/mpi_cnfg.h linux-2.6.22-590/drivers/message/fusion/lsi/mpi_cnfg.h
---- linux-2.6.22-570/drivers/message/fusion/lsi/mpi_cnfg.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/lsi/mpi_cnfg.h     2008-01-02 13:56:37.000000000 -0500
-@@ -1,12 +1,12 @@
- /*
-- *  Copyright (c) 2000-2006 LSI Logic Corporation.
-+ *  Copyright (c) 2000-2007 LSI Logic Corporation.
-  *
-  *
-  *           Name:  mpi_cnfg.h
-  *          Title:  MPI Config message, structures, and Pages
-  *  Creation Date:  July 27, 2000
-  *
-- *    mpi_cnfg.h Version:  01.05.13
-+ *    mpi_cnfg.h Version:  01.05.15
-  *
-  *  Version History
-  *  ---------------
-@@ -293,6 +293,21 @@
-  *                      Added more AccessStatus values for SAS Device Page 0.
-  *                      Added bit for SATA Asynchronous Notification Support in
-  *                      Flags field of SAS Device Page 0.
-+ *  02-28-07  01.05.14  Added ExtFlags field to Manufacturing Page 4.
-+ *                      Added Disable SMART Polling for CapabilitiesFlags of
-+ *                      IOC Page 6.
-+ *                      Added Disable SMART Polling to DeviceSettings of BIOS
-+ *                      Page 1.
-+ *                      Added Multi-Port Domain bit for DiscoveryStatus field
-+ *                      of SAS IO Unit Page.
-+ *                      Added Multi-Port Domain Illegal flag for SAS IO Unit
-+ *                      Page 1 AdditionalControlFlags field.
-+ *  05-24-07  01.05.15  Added Hide Physical Disks with Non-Integrated RAID
-+ *                      Metadata bit to Manufacturing Page 4 ExtFlags field.
-+ *                      Added Internal Connector to End Device Present bit to
-+ *                      Expander Page 0 Flags field.
-+ *                      Fixed define for
-+ *                      MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED.
-  *  --------------------------------------------------------------------------
-  */
-@@ -639,7 +654,7 @@
-     U8                              InfoSize1;          /* 0Bh */
-     U8                              InquirySize;        /* 0Ch */
-     U8                              Flags;              /* 0Dh */
--    U16                             Reserved2;          /* 0Eh */
-+    U16                             ExtFlags;           /* 0Eh */
-     U8                              InquiryData[56];    /* 10h */
-     U32                             ISVolumeSettings;   /* 48h */
-     U32                             IMEVolumeSettings;  /* 4Ch */
-@@ -658,7 +673,7 @@
- } CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
-   ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
--#define MPI_MANUFACTURING4_PAGEVERSION                  (0x04)
-+#define MPI_MANUFACTURING4_PAGEVERSION                  (0x05)
- /* defines for the Flags field */
- #define MPI_MANPAGE4_FORCE_BAD_BLOCK_TABLE              (0x80)
-@@ -670,6 +685,12 @@
- #define MPI_MANPAGE4_IM_RESYNC_CACHE_ENABLE             (0x02)
- #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA                 (0x01)
-+/* defines for the ExtFlags field */
-+#define MPI_MANPAGE4_EXTFLAGS_HIDE_NON_IR_METADATA      (0x0008)
-+#define MPI_MANPAGE4_EXTFLAGS_SAS_CACHE_DISABLE         (0x0004)
-+#define MPI_MANPAGE4_EXTFLAGS_SATA_CACHE_DISABLE        (0x0002)
-+#define MPI_MANPAGE4_EXTFLAGS_LEGACY_MODE               (0x0001)
-+
- #ifndef MPI_MANPAGE5_NUM_FORCEWWID
- #define MPI_MANPAGE5_NUM_FORCEWWID      (1)
-@@ -781,7 +802,7 @@
- } CONFIG_PAGE_MANUFACTURING_9, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_9,
-   ManufacturingPage9_t, MPI_POINTER pManufacturingPage9_t;
--#define MPI_MANUFACTURING6_PAGEVERSION                  (0x00)
-+#define MPI_MANUFACTURING9_PAGEVERSION                  (0x00)
- typedef struct _CONFIG_PAGE_MANUFACTURING_10
-@@ -1138,6 +1159,8 @@
- /* IOC Page 6 Capabilities Flags */
-+#define MPI_IOCPAGE6_CAP_FLAGS_DISABLE_SMART_POLLING    (0x00000008)
-+
- #define MPI_IOCPAGE6_CAP_FLAGS_MASK_METADATA_SIZE       (0x00000006)
- #define MPI_IOCPAGE6_CAP_FLAGS_64MB_METADATA_SIZE       (0x00000000)
- #define MPI_IOCPAGE6_CAP_FLAGS_512MB_METADATA_SIZE      (0x00000002)
-@@ -1208,6 +1231,7 @@
- #define MPI_BIOSPAGE1_IOCSET_ALTERNATE_CHS              (0x00000008)
- /* values for the DeviceSettings field */
-+#define MPI_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING      (0x00000010)
- #define MPI_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN            (0x00000008)
- #define MPI_BIOSPAGE1_DEVSET_DISABLE_RM_LUN             (0x00000004)
- #define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN         (0x00000002)
-@@ -2281,11 +2305,11 @@
- typedef struct _CONFIG_PAGE_RAID_VOL_1
- {
-     CONFIG_PAGE_HEADER      Header;         /* 00h */
--    U8                      VolumeID;       /* 01h */
--    U8                      VolumeBus;      /* 02h */
--    U8                      VolumeIOC;      /* 03h */
--    U8                      Reserved0;      /* 04h */
--    U8                      GUID[24];       /* 05h */
-+    U8                      VolumeID;       /* 04h */
-+    U8                      VolumeBus;      /* 05h */
-+    U8                      VolumeIOC;      /* 06h */
-+    U8                      Reserved0;      /* 07h */
-+    U8                      GUID[24];       /* 08h */
-     U8                      Name[32];       /* 20h */
-     U64                     WWID;           /* 40h */
-     U32                     Reserved1;      /* 48h */
-@@ -2340,7 +2364,7 @@
- } RAID_PHYS_DISK0_STATUS, MPI_POINTER PTR_RAID_PHYS_DISK0_STATUS,
-   RaidPhysDiskStatus_t, MPI_POINTER pRaidPhysDiskStatus_t;
--/* RAID Volume 2 IM Physical Disk DiskStatus flags */
-+/* RAID Physical Disk PhysDiskStatus flags */
- #define MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC           (0x01)
- #define MPI_PHYSDISK0_STATUS_FLAG_QUIESCED              (0x02)
-@@ -2544,6 +2568,7 @@
- #define MPI_SAS_IOUNIT0_DS_TABLE_LINK                       (0x00000400)
- #define MPI_SAS_IOUNIT0_DS_UNSUPPORTED_DEVICE               (0x00000800)
- #define MPI_SAS_IOUNIT0_DS_MAX_SATA_TARGETS                 (0x00001000)
-+#define MPI_SAS_IOUNIT0_DS_MULTI_PORT_DOMAIN                (0x00002000)
- typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA
-@@ -2607,6 +2632,7 @@
- #define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION           (0x0001)
- /* values for SAS IO Unit Page 1 AdditionalControlFlags */
-+#define MPI_SAS_IOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL          (0x0080)
- #define MPI_SAS_IOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION    (0x0040)
- #define MPI_SAS_IOUNIT1_ACONTROL_HIDE_NONZERO_ATTACHED_PHY_IDENT    (0x0020)
- #define MPI_SAS_IOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET   (0x0010)
-@@ -2734,6 +2760,7 @@
- #define MPI_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE         (0x00000800)
- /* values for SAS Expander Page 0 Flags field */
-+#define MPI_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE    (0x04)
- #define MPI_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG      (0x02)
- #define MPI_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS      (0x01)
-@@ -2774,7 +2801,7 @@
- /* see mpi_sas.h for values for SAS Expander Page 1 AttachedDeviceInfo values */
- /* values for SAS Expander Page 1 DiscoveryInfo field */
--#define MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY DISABLED     (0x04)
-+#define MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED     (0x04)
- #define MPI_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE   (0x02)
- #define MPI_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES   (0x01)
-@@ -2895,11 +2922,11 @@
-     U8                                  AttachedPhyIdentifier;  /* 16h */
-     U8                                  Reserved2;              /* 17h */
-     U32                                 AttachedDeviceInfo;     /* 18h */
--    U8                                  ProgrammedLinkRate;     /* 20h */
--    U8                                  HwLinkRate;             /* 21h */
--    U8                                  ChangeCount;            /* 22h */
--    U8                                  Flags;                  /* 23h */
--    U32                                 PhyInfo;                /* 24h */
-+    U8                                  ProgrammedLinkRate;     /* 1Ch */
-+    U8                                  HwLinkRate;             /* 1Dh */
-+    U8                                  ChangeCount;            /* 1Eh */
-+    U8                                  Flags;                  /* 1Fh */
-+    U32                                 PhyInfo;                /* 20h */
- } CONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0,
-   SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t;
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/lsi/mpi_history.txt linux-2.6.22-590/drivers/message/fusion/lsi/mpi_history.txt
---- linux-2.6.22-570/drivers/message/fusion/lsi/mpi_history.txt        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/lsi/mpi_history.txt        2008-01-02 13:56:37.000000000 -0500
-@@ -3,28 +3,28 @@
-  MPI Header File Change History
-  ==============================
-- Copyright (c) 2000-2006 LSI Logic Corporation.
-+ Copyright (c) 2000-2007 LSI Logic Corporation.
-  ---------------------------------------
-- Header Set Release Version:    01.05.14
-- Header Set Release Date:       10-11-06
-+ Header Set Release Version:    01.05.16
-+ Header Set Release Date:       05-24-07
-  ---------------------------------------
-  Filename               Current version     Prior version
-  ----------             ---------------     -------------
-- mpi.h                  01.05.12            01.05.11
-- mpi_ioc.h              01.05.12            01.05.11
-- mpi_cnfg.h             01.05.13            01.05.12
-- mpi_init.h             01.05.08            01.05.07
-+ mpi.h                  01.05.13            01.05.12
-+ mpi_ioc.h              01.05.14            01.05.13
-+ mpi_cnfg.h             01.05.15            01.05.14
-+ mpi_init.h             01.05.09            01.05.09
-  mpi_targ.h             01.05.06            01.05.06
-  mpi_fc.h               01.05.01            01.05.01
-  mpi_lan.h              01.05.01            01.05.01
-- mpi_raid.h             01.05.02            01.05.02
-+ mpi_raid.h             01.05.03            01.05.03
-  mpi_tool.h             01.05.03            01.05.03
-  mpi_inb.h              01.05.01            01.05.01
-- mpi_sas.h              01.05.04            01.05.03
-+ mpi_sas.h              01.05.04            01.05.04
-  mpi_type.h             01.05.02            01.05.02
-- mpi_history.txt        01.05.14            01.05.13
-+ mpi_history.txt        01.05.14            01.05.14
-  *  Date      Version   Description
-@@ -95,6 +95,7 @@
-  *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
-  *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
-  *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
-+ *  05-24-07  01.05.13  Bumped MPI_HEADER_VERSION_UNIT.
-  *  --------------------------------------------------------------------------
- mpi_ioc.h
-@@ -191,6 +192,13 @@
-  *                      data structure.
-  *                      Added new ImageType values for FWDownload and FWUpload
-  *                      requests.
-+ *  02-28-07  01.05.13  Added MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT for SAS
-+ *                      Broadcast Event Data (replacing _RESERVED2).
-+ *                      For Discovery Error Event Data DiscoveryStatus field,
-+ *                      replaced _MULTPL_PATHS with _UNSUPPORTED_DEVICE and
-+ *                      added _MULTI_PORT_DOMAIN.
-+ *  05-24-07  01.05.14  Added Common Boot Block type to FWDownload Request.
-+ *                      Added Common Boot Block type to FWUpload Request.
-  *  --------------------------------------------------------------------------
- mpi_cnfg.h
-@@ -473,6 +481,21 @@
-  *                      Added more AccessStatus values for SAS Device Page 0.
-  *                      Added bit for SATA Asynchronous Notification Support in
-  *                      Flags field of SAS Device Page 0.
-+ *  02-28-07  01.05.14  Added ExtFlags field to Manufacturing Page 4.
-+ *                      Added Disable SMART Polling for CapabilitiesFlags of
-+ *                      IOC Page 6.
-+ *                      Added Disable SMART Polling to DeviceSettings of BIOS
-+ *                      Page 1.
-+ *                      Added Multi-Port Domain bit for DiscoveryStatus field
-+ *                      of SAS IO Unit Page.
-+ *                      Added Multi-Port Domain Illegal flag for SAS IO Unit
-+ *                      Page 1 AdditionalControlFlags field.
-+ *  05-24-07  01.05.15  Added Hide Physical Disks with Non-Integrated RAID
-+ *                      Metadata bit to Manufacturing Page 4 ExtFlags field.
-+ *                      Added Internal Connector to End Device Present bit to
-+ *                      Expander Page 0 Flags field.
-+ *                      Fixed define for
-+ *                      MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED.
-  *  --------------------------------------------------------------------------
- mpi_init.h
-@@ -517,6 +540,8 @@
-  *                      unique in the first 32 characters.
-  *  03-27-06  01.05.07  Added Task Management type of Clear ACA.
-  *  10-11-06  01.05.08  Shortened define for Task Management type of Clear ACA.
-+ *  02-28-07  01.05.09  Defined two new MsgFlags bits for SCSI Task Management
-+ *                      Request: Do Not Send Task IU and Soft Reset Option.
-  *  --------------------------------------------------------------------------
- mpi_targ.h
-@@ -571,7 +596,7 @@
-  *  11-02-00  01.01.01  Original release for post 1.0 work
-  *  12-04-00  01.01.02  Added messages for Common Transport Send and
-  *                      Primitive Send.
-- *  01-09-01  01.01.03  Modified some of the new flags to have an MPI prefix
-+ *  01-09-01  01.01.03  Modifed some of the new flags to have an MPI prefix
-  *                      and modified the FcPrimitiveSend flags.
-  *  01-25-01  01.01.04  Move InitiatorIndex in LinkServiceRsp reply to a larger
-  *                      field.
-@@ -634,6 +659,8 @@
-  *  08-19-04  01.05.01  Original release for MPI v1.5.
-  *  01-15-05  01.05.02  Added defines for the two new RAID Actions for
-  *                      _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
-+ *  02-28-07  01.05.03  Added new RAID Action, Device FW Update Mode, and
-+ *                      associated defines.
-  *  --------------------------------------------------------------------------
- mpi_tool.h
-@@ -682,7 +709,22 @@
- mpi_history.txt         Parts list history
--Filename    01.05.13   01.05.13   01.05.12   01.05.11   01.05.10   01.05.09
-+Filename    01.05.15   01.05.15
-+----------  --------   --------
-+mpi.h       01.05.12   01.05.13
-+mpi_ioc.h   01.05.13   01.05.14
-+mpi_cnfg.h  01.05.14   01.05.15
-+mpi_init.h  01.05.09   01.05.09
-+mpi_targ.h  01.05.06   01.05.06
-+mpi_fc.h    01.05.01   01.05.01
-+mpi_lan.h   01.05.01   01.05.01
-+mpi_raid.h  01.05.03   01.05.03
-+mpi_tool.h  01.05.03   01.05.03
-+mpi_inb.h   01.05.01   01.05.01
-+mpi_sas.h   01.05.04   01.05.04
-+mpi_type.h  01.05.02   01.05.02
-+
-+Filename    01.05.14   01.05.13   01.05.12   01.05.11   01.05.10   01.05.09
- ----------  --------   --------   --------   --------   --------   --------
- mpi.h       01.05.12   01.05.11   01.05.10   01.05.09   01.05.08   01.05.07
- mpi_ioc.h   01.05.12   01.05.11   01.05.10   01.05.09   01.05.09   01.05.08
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/lsi/mpi_inb.h linux-2.6.22-590/drivers/message/fusion/lsi/mpi_inb.h
---- linux-2.6.22-570/drivers/message/fusion/lsi/mpi_inb.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/lsi/mpi_inb.h      1969-12-31 19:00:00.000000000 -0500
-@@ -1,221 +0,0 @@
--/*
-- *  Copyright (c) 2003-2004 LSI Logic Corporation.
-- *
-- *
-- *           Name:  mpi_inb.h
-- *          Title:  MPI Inband structures and definitions
-- *  Creation Date:  September 30, 2003
-- *
-- *    mpi_inb.h Version:  01.05.01
-- *
-- *  Version History
-- *  ---------------
-- *
-- *  Date      Version   Description
-- *  --------  --------  ------------------------------------------------------
-- *  05-11-04  01.03.01  Original release.
-- *  08-19-04  01.05.01  Original release for MPI v1.5.
-- *  --------------------------------------------------------------------------
-- */
--
--#ifndef MPI_INB_H
--#define MPI_INB_H
--
--/******************************************************************************
--*
--*        I n b a n d    M e s s a g e s
--*
--*******************************************************************************/
--
--
--/****************************************************************************/
--/* Inband Buffer Post Request                                               */
--/****************************************************************************/
--
--typedef struct _MSG_INBAND_BUFFER_POST_REQUEST
--{
--    U8                      Reserved1;          /* 00h */
--    U8                      BufferCount;        /* 01h */
--    U8                      ChainOffset;        /* 02h */
--    U8                      Function;           /* 03h */
--    U16                     Reserved2;          /* 04h */
--    U8                      Reserved3;          /* 06h */
--    U8                      MsgFlags;           /* 07h */
--    U32                     MsgContext;         /* 08h */
--    U32                     Reserved4;          /* 0Ch */
--    SGE_TRANS_SIMPLE_UNION  SGL;                /* 10h */
--} MSG_INBAND_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_INBAND_BUFFER_POST_REQUEST,
--  MpiInbandBufferPostRequest_t , MPI_POINTER pMpiInbandBufferPostRequest_t;
--
--
--typedef struct _WWN_FC_FORMAT
--{
--    U64                     NodeName;           /* 00h */
--    U64                     PortName;           /* 08h */
--} WWN_FC_FORMAT, MPI_POINTER PTR_WWN_FC_FORMAT,
--  WwnFcFormat_t, MPI_POINTER pWwnFcFormat_t;
--
--typedef struct _WWN_SAS_FORMAT
--{
--    U64                     WorldWideID;        /* 00h */
--    U32                     Reserved1;          /* 08h */
--    U32                     Reserved2;          /* 0Ch */
--} WWN_SAS_FORMAT, MPI_POINTER PTR_WWN_SAS_FORMAT,
--  WwnSasFormat_t, MPI_POINTER pWwnSasFormat_t;
--
--typedef union _WWN_INBAND_FORMAT
--{
--    WWN_FC_FORMAT           Fc;
--    WWN_SAS_FORMAT          Sas;
--} WWN_INBAND_FORMAT, MPI_POINTER PTR_WWN_INBAND_FORMAT,
--  WwnInbandFormat, MPI_POINTER pWwnInbandFormat;
--
--
--/* Inband Buffer Post reply message */
--
--typedef struct _MSG_INBAND_BUFFER_POST_REPLY
--{
--    U16                     Reserved1;          /* 00h */
--    U8                      MsgLength;          /* 02h */
--    U8                      Function;           /* 03h */
--    U16                     Reserved2;          /* 04h */
--    U8                      Reserved3;          /* 06h */
--    U8                      MsgFlags;           /* 07h */
--    U32                     MsgContext;         /* 08h */
--    U16                     Reserved4;          /* 0Ch */
--    U16                     IOCStatus;          /* 0Eh */
--    U32                     IOCLogInfo;         /* 10h */
--    U32                     TransferLength;     /* 14h */
--    U32                     TransactionContext; /* 18h */
--    WWN_INBAND_FORMAT       Wwn;                /* 1Ch */
--    U32                     IOCIdentifier[4];   /* 2Ch */
--} MSG_INBAND_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_INBAND_BUFFER_POST_REPLY,
--  MpiInbandBufferPostReply_t, MPI_POINTER pMpiInbandBufferPostReply_t;
--
--
--/****************************************************************************/
--/* Inband Send Request                                                      */
--/****************************************************************************/
--
--typedef struct _MSG_INBAND_SEND_REQUEST
--{
--    U16                     Reserved1;          /* 00h */
--    U8                      ChainOffset;        /* 02h */
--    U8                      Function;           /* 03h */
--    U16                     Reserved2;          /* 04h */
--    U8                      Reserved3;          /* 06h */
--    U8                      MsgFlags;           /* 07h */
--    U32                     MsgContext;         /* 08h */
--    U32                     Reserved4;          /* 0Ch */
--    WWN_INBAND_FORMAT       Wwn;                /* 10h */
--    U32                     Reserved5;          /* 20h */
--    SGE_IO_UNION            SGL;                /* 24h */
--} MSG_INBAND_SEND_REQUEST, MPI_POINTER PTR_MSG_INBAND_SEND_REQUEST,
--  MpiInbandSendRequest_t , MPI_POINTER pMpiInbandSendRequest_t;
--
--
--/* Inband Send reply message */
--
--typedef struct _MSG_INBAND_SEND_REPLY
--{
--    U16                     Reserved1;          /* 00h */
--    U8                      MsgLength;          /* 02h */
--    U8                      Function;           /* 03h */
--    U16                     Reserved2;          /* 04h */
--    U8                      Reserved3;          /* 06h */
--    U8                      MsgFlags;           /* 07h */
--    U32                     MsgContext;         /* 08h */
--    U16                     Reserved4;          /* 0Ch */
--    U16                     IOCStatus;          /* 0Eh */
--    U32                     IOCLogInfo;         /* 10h */
--    U32                     ResponseLength;     /* 14h */
--} MSG_INBAND_SEND_REPLY, MPI_POINTER PTR_MSG_INBAND_SEND_REPLY,
--  MpiInbandSendReply_t, MPI_POINTER pMpiInbandSendReply_t;
--
--
--/****************************************************************************/
--/* Inband Response Request                                                  */
--/****************************************************************************/
--
--typedef struct _MSG_INBAND_RSP_REQUEST
--{
--    U16                     Reserved1;          /* 00h */
--    U8                      ChainOffset;        /* 02h */
--    U8                      Function;           /* 03h */
--    U16                     Reserved2;          /* 04h */
--    U8                      Reserved3;          /* 06h */
--    U8                      MsgFlags;           /* 07h */
--    U32                     MsgContext;         /* 08h */
--    U32                     Reserved4;          /* 0Ch */
--    WWN_INBAND_FORMAT       Wwn;                /* 10h */
--    U32                     IOCIdentifier[4];   /* 20h */
--    U32                     ResponseLength;     /* 30h */
--    SGE_IO_UNION            SGL;                /* 34h */
--} MSG_INBAND_RSP_REQUEST, MPI_POINTER PTR_MSG_INBAND_RSP_REQUEST,
--  MpiInbandRspRequest_t , MPI_POINTER pMpiInbandRspRequest_t;
--
--
--/* Inband Response reply message */
--
--typedef struct _MSG_INBAND_RSP_REPLY
--{
--    U16                     Reserved1;          /* 00h */
--    U8                      MsgLength;          /* 02h */
--    U8                      Function;           /* 03h */
--    U16                     Reserved2;          /* 04h */
--    U8                      Reserved3;          /* 06h */
--    U8                      MsgFlags;           /* 07h */
--    U32                     MsgContext;         /* 08h */
--    U16                     Reserved4;          /* 0Ch */
--    U16                     IOCStatus;          /* 0Eh */
--    U32                     IOCLogInfo;         /* 10h */
--} MSG_INBAND_RSP_REPLY, MPI_POINTER PTR_MSG_INBAND_RSP_REPLY,
--  MpiInbandRspReply_t, MPI_POINTER pMpiInbandRspReply_t;
--
--
--/****************************************************************************/
--/* Inband Abort Request                                                     */
--/****************************************************************************/
--
--typedef struct _MSG_INBAND_ABORT_REQUEST
--{
--    U8                      Reserved1;          /* 00h */
--    U8                      AbortType;          /* 01h */
--    U8                      ChainOffset;        /* 02h */
--    U8                      Function;           /* 03h */
--    U16                     Reserved2;          /* 04h */
--    U8                      Reserved3;          /* 06h */
--    U8                      MsgFlags;           /* 07h */
--    U32                     MsgContext;         /* 08h */
--    U32                     Reserved4;          /* 0Ch */
--    U32                     ContextToAbort;     /* 10h */
--} MSG_INBAND_ABORT_REQUEST, MPI_POINTER PTR_MSG_INBAND_ABORT_REQUEST,
--  MpiInbandAbortRequest_t , MPI_POINTER pMpiInbandAbortRequest_t;
--
--#define MPI_INBAND_ABORT_TYPE_ALL_BUFFERS       (0x00)
--#define MPI_INBAND_ABORT_TYPE_EXACT_BUFFER      (0x01)
--#define MPI_INBAND_ABORT_TYPE_SEND_REQUEST      (0x02)
--#define MPI_INBAND_ABORT_TYPE_RESPONSE_REQUEST  (0x03)
--
--
--/* Inband Abort reply message */
--
--typedef struct _MSG_INBAND_ABORT_REPLY
--{
--    U8                      Reserved1;          /* 00h */
--    U8                      AbortType;          /* 01h */
--    U8                      MsgLength;          /* 02h */
--    U8                      Function;           /* 03h */
--    U16                     Reserved2;          /* 04h */
--    U8                      Reserved3;          /* 06h */
--    U8                      MsgFlags;           /* 07h */
--    U32                     MsgContext;         /* 08h */
--    U16                     Reserved4;          /* 0Ch */
--    U16                     IOCStatus;          /* 0Eh */
--    U32                     IOCLogInfo;         /* 10h */
--} MSG_INBAND_ABORT_REPLY, MPI_POINTER PTR_MSG_INBAND_ABORT_REPLY,
--  MpiInbandAbortReply_t, MPI_POINTER pMpiInbandAbortReply_t;
--
--
--#endif
--
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/lsi/mpi_init.h linux-2.6.22-590/drivers/message/fusion/lsi/mpi_init.h
---- linux-2.6.22-570/drivers/message/fusion/lsi/mpi_init.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/lsi/mpi_init.h     2008-01-02 13:56:37.000000000 -0500
-@@ -1,12 +1,12 @@
- /*
-- *  Copyright (c) 2000-2006 LSI Logic Corporation.
-+ *  Copyright (c) 2000-2007 LSI Logic Corporation.
-  *
-  *
-  *           Name:  mpi_init.h
-  *          Title:  MPI initiator mode messages and structures
-  *  Creation Date:  June 8, 2000
-  *
-- *    mpi_init.h Version:  01.05.08
-+ *    mpi_init.h Version:  01.05.09
-  *
-  *  Version History
-  *  ---------------
-@@ -54,6 +54,8 @@
-  *                      unique in the first 32 characters.
-  *  03-27-06  01.05.07  Added Task Management type of Clear ACA.
-  *  10-11-06  01.05.08  Shortened define for Task Management type of Clear ACA.
-+ *  02-28-07  01.05.09  Defined two new MsgFlags bits for SCSI Task Management
-+ *                      Request: Do Not Send Task IU and Soft Reset Option.
-  *  --------------------------------------------------------------------------
-  */
-@@ -432,10 +434,14 @@
- #define MPI_SCSITASKMGMT_TASKTYPE_CLR_ACA               (0x08)
- /* MsgFlags bits */
-+#define MPI_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU   (0x01)
-+
- #define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION   (0x00)
- #define MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION      (0x02)
- #define MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION (0x04)
-+#define MPI_SCSITASKMGMT_MSGFLAGS_SOFT_RESET_OPTION     (0x08)
-+
- /* SCSI Task Management Reply */
- typedef struct _MSG_SCSI_TASK_MGMT_REPLY
- {
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/lsi/mpi_ioc.h linux-2.6.22-590/drivers/message/fusion/lsi/mpi_ioc.h
---- linux-2.6.22-570/drivers/message/fusion/lsi/mpi_ioc.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/lsi/mpi_ioc.h      2008-01-02 13:56:37.000000000 -0500
-@@ -1,12 +1,12 @@
- /*
-- *  Copyright (c) 2000-2006 LSI Logic Corporation.
-+ *  Copyright (c) 2000-2007 LSI Logic Corporation.
-  *
-  *
-  *           Name:  mpi_ioc.h
-  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
-  *  Creation Date:  August 11, 2000
-  *
-- *    mpi_ioc.h Version:  01.05.12
-+ *    mpi_ioc.h Version:  01.05.14
-  *
-  *  Version History
-  *  ---------------
-@@ -106,6 +106,13 @@
-  *                      data structure.
-  *                      Added new ImageType values for FWDownload and FWUpload
-  *                      requests.
-+ *  02-28-07  01.05.13  Added MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT for SAS
-+ *                      Broadcast Event Data (replacing _RESERVED2).
-+ *                      For Discovery Error Event Data DiscoveryStatus field,
-+ *                      replaced _MULTPL_PATHS with _UNSUPPORTED_DEVICE and
-+ *                      added _MULTI_PORT_DOMAIN.
-+ *  05-24-07  01.05.14  Added Common Boot Block type to FWDownload Request.
-+ *                      Added Common Boot Block type to FWUpload Request.
-  *  --------------------------------------------------------------------------
-  */
-@@ -792,7 +799,7 @@
- #define MPI_EVENT_PRIMITIVE_CHANGE              (0x01)
- #define MPI_EVENT_PRIMITIVE_EXPANDER            (0x03)
--#define MPI_EVENT_PRIMITIVE_RESERVED2           (0x04)
-+#define MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT  (0x04)
- #define MPI_EVENT_PRIMITIVE_RESERVED3           (0x05)
- #define MPI_EVENT_PRIMITIVE_RESERVED4           (0x06)
- #define MPI_EVENT_PRIMITIVE_CHANGE0_RESERVED    (0x07)
-@@ -857,8 +864,9 @@
- #define MPI_EVENT_DSCVRY_ERR_DS_SMP_CRC_ERROR               (0x00000100)
- #define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_SUBTRACTIVE          (0x00000200)
- #define MPI_EVENT_DSCVRY_ERR_DS_TABLE_TO_TABLE              (0x00000400)
--#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS                (0x00000800)
-+#define MPI_EVENT_DSCVRY_ERR_DS_UNSUPPORTED_DEVICE          (0x00000800)
- #define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS            (0x00001000)
-+#define MPI_EVENT_DSCVRY_ERR_DS_MULTI_PORT_DOMAIN           (0x00002000)
- /* SAS SMP Error Event data */
-@@ -990,6 +998,7 @@
- #define MPI_FW_DOWNLOAD_ITYPE_CONFIG_1          (0x07)
- #define MPI_FW_DOWNLOAD_ITYPE_CONFIG_2          (0x08)
- #define MPI_FW_DOWNLOAD_ITYPE_MEGARAID          (0x09)
-+#define MPI_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
- typedef struct _FWDownloadTCSGE
-@@ -1049,6 +1058,7 @@
- #define MPI_FW_UPLOAD_ITYPE_CONFIG_2        (0x08)
- #define MPI_FW_UPLOAD_ITYPE_MEGARAID        (0x09)
- #define MPI_FW_UPLOAD_ITYPE_COMPLETE        (0x0A)
-+#define MPI_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK   (0x0B)
- typedef struct _FWUploadTCSGE
- {
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/lsi/mpi_raid.h linux-2.6.22-590/drivers/message/fusion/lsi/mpi_raid.h
---- linux-2.6.22-570/drivers/message/fusion/lsi/mpi_raid.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/lsi/mpi_raid.h     2008-01-02 13:56:37.000000000 -0500
-@@ -1,12 +1,12 @@
- /*
-- *  Copyright (c) 2001-2005 LSI Logic Corporation.
-+ *  Copyright (c) 2001-2007 LSI Logic Corporation.
-  *
-  *
-  *           Name:  mpi_raid.h
-  *          Title:  MPI RAID message and structures
-  *  Creation Date:  February 27, 2001
-  *
-- *    mpi_raid.h Version:  01.05.02
-+ *    mpi_raid.h Version:  01.05.03
-  *
-  *  Version History
-  *  ---------------
-@@ -32,6 +32,8 @@
-  *  08-19-04  01.05.01  Original release for MPI v1.5.
-  *  01-15-05  01.05.02  Added defines for the two new RAID Actions for
-  *                      _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
-+ *  02-28-07  01.05.03  Added new RAID Action, Device FW Update Mode, and
-+ *                      associated defines.
-  *  --------------------------------------------------------------------------
-  */
-@@ -90,6 +92,7 @@
- #define MPI_RAID_ACTION_INACTIVATE_VOLUME           (0x12)
- #define MPI_RAID_ACTION_SET_RESYNC_RATE             (0x13)
- #define MPI_RAID_ACTION_SET_DATA_SCRUB_RATE         (0x14)
-+#define MPI_RAID_ACTION_DEVICE_FW_UPDATE_MODE       (0x15)
- /* ActionDataWord defines for use with MPI_RAID_ACTION_CREATE_VOLUME action */
- #define MPI_RAID_ACTION_ADATA_DO_NOT_SYNC           (0x00000001)
-@@ -111,6 +114,10 @@
- /* ActionDataWord defines for use with MPI_RAID_ACTION_SET_DATA_SCRUB_RATE action */
- #define MPI_RAID_ACTION_ADATA_DATA_SCRUB_RATE_MASK  (0x000000FF)
-+/* ActionDataWord defines for use with MPI_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */
-+#define MPI_RAID_ACTION_ADATA_ENABLE_FW_UPDATE          (0x00000001)
-+#define MPI_RAID_ACTION_ADATA_MASK_FW_UPDATE_TIMEOUT    (0x0000FF00)
-+#define MPI_RAID_ACTION_ADATA_SHIFT_FW_UPDATE_TIMEOUT   (8)
- /* RAID Action reply message */
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/mptbase.c linux-2.6.22-590/drivers/message/fusion/mptbase.c
---- linux-2.6.22-570/drivers/message/fusion/mptbase.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/mptbase.c  2008-01-02 13:56:37.000000000 -0500
-@@ -6,7 +6,7 @@
-  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
-  *
-  *  Copyright (c) 1999-2007 LSI Logic Corporation
-- *  (mailto:mpt_linux_developer@lsi.com)
-+ *  (mailto:DL-MPTFusionLinux@lsi.com)
-  *
-  */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-@@ -64,6 +64,7 @@
- #endif
- #include "mptbase.h"
-+#include "lsi/mpi_log_fc.h"
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
- #define my_NAME               "Fusion MPT base driver"
-@@ -6349,14 +6350,37 @@
- static void
- mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
- {
--      static char *subcl_str[8] = {
--              "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
--              "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
--      };
--      u8 subcl = (log_info >> 24) & 0x7;
-+      char *desc = "unknown";
-+
-+      switch (log_info & 0xFF000000) {
-+      case MPI_IOCLOGINFO_FC_INIT_BASE:
-+              desc = "FCP Initiator";
-+              break;
-+      case MPI_IOCLOGINFO_FC_TARGET_BASE:
-+              desc = "FCP Target";
-+              break;
-+      case MPI_IOCLOGINFO_FC_LAN_BASE:
-+              desc = "LAN";
-+              break;
-+      case MPI_IOCLOGINFO_FC_MSG_BASE:
-+              desc = "MPI Message Layer";
-+              break;
-+      case MPI_IOCLOGINFO_FC_LINK_BASE:
-+              desc = "FC Link";
-+              break;
-+      case MPI_IOCLOGINFO_FC_CTX_BASE:
-+              desc = "Context Manager";
-+              break;
-+      case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET:
-+              desc = "Invalid Field Offset";
-+              break;
-+      case MPI_IOCLOGINFO_FC_STATE_CHANGE:
-+              desc = "State Change Info";
-+              break;
-+      }
--      printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
--                      ioc->name, log_info, subcl_str[subcl]);
-+      printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
-+                      ioc->name, log_info, desc, (log_info & 0xFFFFFF));
- }
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/mptbase.h linux-2.6.22-590/drivers/message/fusion/mptbase.h
---- linux-2.6.22-570/drivers/message/fusion/mptbase.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/mptbase.h  2008-01-02 13:56:37.000000000 -0500
-@@ -6,7 +6,7 @@
-  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
-  *
-  *  Copyright (c) 1999-2007 LSI Logic Corporation
-- *  (mailto:mpt_linux_developer@lsi.com)
-+ *  (mailto:DL-MPTFusionLinux@lsi.com)
-  *
-  */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-@@ -75,8 +75,8 @@
- #define COPYRIGHT     "Copyright (c) 1999-2007 " MODULEAUTHOR
- #endif
--#define MPT_LINUX_VERSION_COMMON      "3.04.04"
--#define MPT_LINUX_PACKAGE_NAME                "@(#)mptlinux-3.04.04"
-+#define MPT_LINUX_VERSION_COMMON      "3.04.05"
-+#define MPT_LINUX_PACKAGE_NAME                "@(#)mptlinux-3.04.05"
- #define WHAT_MAGIC_STRING             "@" "(" "#" ")"
- #define show_mptmod_ver(s,ver)  \
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/mptctl.c linux-2.6.22-590/drivers/message/fusion/mptctl.c
---- linux-2.6.22-570/drivers/message/fusion/mptctl.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/mptctl.c   2008-01-02 13:56:37.000000000 -0500
-@@ -5,7 +5,7 @@
-  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
-  *
-  *  Copyright (c) 1999-2007 LSI Logic Corporation
-- *  (mailto:mpt_linux_developer@lsi.com)
-+ *  (mailto:DL-MPTFusionLinux@lsi.com)
-  *
-  */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/mptctl.h linux-2.6.22-590/drivers/message/fusion/mptctl.h
---- linux-2.6.22-570/drivers/message/fusion/mptctl.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/mptctl.h   2008-01-02 13:56:37.000000000 -0500
-@@ -6,7 +6,7 @@
-  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
-  *
-  *  Copyright (c) 1999-2007 LSI Logic Corporation
-- *  (mailto:mpt_linux_developer@lsi.com)
-+ *  (mailto:DL-MPTFusionLinux@lsi.com)
-  *
-  */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/mptfc.c linux-2.6.22-590/drivers/message/fusion/mptfc.c
---- linux-2.6.22-570/drivers/message/fusion/mptfc.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/mptfc.c    2008-01-02 13:56:37.000000000 -0500
-@@ -4,7 +4,7 @@
-  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
-  *
-  *  Copyright (c) 1999-2007 LSI Logic Corporation
-- *  (mailto:mpt_linux_developer@lsi.com)
-+ *  (mailto:DL-MPTFusionLinux@lsi.com)
-  *
-  */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-@@ -43,7 +43,6 @@
-     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
--#include "linux_compat.h"     /* linux-2.6 tweaks */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/mptlan.c linux-2.6.22-590/drivers/message/fusion/mptlan.c
---- linux-2.6.22-570/drivers/message/fusion/mptlan.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/mptlan.c   2008-01-02 13:56:37.000000000 -0500
-@@ -5,7 +5,7 @@
-  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
-  *
-  *  Copyright (c) 2000-2007 LSI Logic Corporation
-- *  (mailto:mpt_linux_developer@lsi.com)
-+ *  (mailto:DL-MPTFusionLinux@lsi.com)
-  *
-  */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/mptlan.h linux-2.6.22-590/drivers/message/fusion/mptlan.h
---- linux-2.6.22-570/drivers/message/fusion/mptlan.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/mptlan.h   2008-01-02 13:56:37.000000000 -0500
-@@ -5,7 +5,7 @@
-  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
-  *
-  *  Copyright (c) 2000-2007 LSI Logic Corporation
-- *  (mailto:mpt_linux_developer@lsi.com)
-+ *  (mailto:DL-MPTFusionLinux@lsi.com)
-  *
-  */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/mptsas.c linux-2.6.22-590/drivers/message/fusion/mptsas.c
---- linux-2.6.22-570/drivers/message/fusion/mptsas.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/mptsas.c   2008-01-02 13:56:37.000000000 -0500
-@@ -4,7 +4,7 @@
-  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
-  *
-  *  Copyright (c) 1999-2007 LSI Logic Corporation
-- *  (mailto:mpt_linux_developer@lsi.com)
-+ *  (mailto:DL-MPTFusionLinux@lsi.com)
-  *  Copyright (c) 2005-2007 Dell
-  */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/mptscsih.c linux-2.6.22-590/drivers/message/fusion/mptscsih.c
---- linux-2.6.22-570/drivers/message/fusion/mptscsih.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/mptscsih.c 2008-01-02 13:56:37.000000000 -0500
-@@ -4,7 +4,7 @@
-  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
-  *
-  *  Copyright (c) 1999-2007 LSI Logic Corporation
-- *  (mailto:mpt_linux_developer@lsi.com)
-+ *  (mailto:DL-MPTFusionLinux@lsi.com)
-  *
-  */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-@@ -44,7 +44,6 @@
- */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
--#include "linux_compat.h"     /* linux-2.6 tweaks */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
-@@ -260,30 +259,13 @@
-       /* Map the data portion, if any.
-        * sges_left  = 0 if no data transfer.
-        */
--      if ( (sges_left = SCpnt->use_sg) ) {
--              sges_left = pci_map_sg(ioc->pcidev,
--                             (struct scatterlist *) SCpnt->request_buffer,
--                             SCpnt->use_sg,
--                             SCpnt->sc_data_direction);
--              if (sges_left == 0)
-+      sges_left = scsi_dma_map(SCpnt);
-+      if (sges_left < 0)
-                       return FAILED;
--      } else if (SCpnt->request_bufflen) {
--              SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
--                                    SCpnt->request_buffer,
--                                    SCpnt->request_bufflen,
--                                    SCpnt->sc_data_direction);
--              dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
--                              ioc->name, SCpnt, SCpnt->request_bufflen));
--              mptscsih_add_sge((char *) &pReq->SGL,
--                      0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
--                      SCpnt->SCp.dma_handle);
--
--              return SUCCESS;
--      }
-       /* Handle the SG case.
-        */
--      sg = (struct scatterlist *) SCpnt->request_buffer;
-+      sg = scsi_sglist(SCpnt);
-       sg_done  = 0;
-       sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
-       chainSge = NULL;
-@@ -465,7 +447,12 @@
-       MPT_FRAME_HDR *mf;
-       SEPRequest_t     *SEPMsg;
--      if (ioc->bus_type == FC)
-+      if (ioc->bus_type != SAS)
-+              return;
-+
-+      /* Not supported for hidden raid components
-+       */
-+      if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
-               return;
-       if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
-@@ -662,7 +649,7 @@
-               scsi_state = pScsiReply->SCSIState;
-               scsi_status = pScsiReply->SCSIStatus;
-               xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
--              sc->resid = sc->request_bufflen - xfer_cnt;
-+              scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
-               log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
-               /*
-@@ -767,7 +754,7 @@
-                       break;
-               case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:      /* 0x0049 */
--                      sc->resid = sc->request_bufflen - xfer_cnt;
-+                      scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
-                       if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
-                               sc->result=DID_SOFT_ERROR << 16;
-                       else /* Sufficient data transfer occurred */
-@@ -816,7 +803,7 @@
-                       break;
-               case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:           /* 0x0044 */
--                      sc->resid=0;
-+                      scsi_set_resid(sc, 0);
-               case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
-               case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
-                       sc->result = (DID_OK << 16) | scsi_status;
-@@ -900,22 +887,17 @@
-                       dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d "
-                           "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
--                          sc->device->host->host_no, sc->device->channel, sc->device->id,
--                          sc->device->lun, sc->resid, sc->request_bufflen,
--                          xfer_cnt));
-+                                    sc->device->host->host_no,
-+                                    sc->device->channel, sc->device->id,
-+                                    sc->device->lun, scsi_get_resid(sc),
-+                                    scsi_bufflen(sc), xfer_cnt));
-               }
- #endif
-       } /* end of address reply case */
-       /* Unmap the DMA buffers, if any. */
--      if (sc->use_sg) {
--              pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
--                          sc->use_sg, sc->sc_data_direction);
--      } else if (sc->request_bufflen) {
--              pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
--                              sc->request_bufflen, sc->sc_data_direction);
--      }
-+      scsi_dma_unmap(sc);
-       sc->scsi_done(sc);              /* Issue the command callback */
-@@ -970,17 +952,8 @@
-                       /* Set status, free OS resources (SG DMA buffers)
-                        * Do OS callback
-                        */
--                      if (SCpnt->use_sg) {
--                              pci_unmap_sg(ioc->pcidev,
--                                      (struct scatterlist *) SCpnt->request_buffer,
--                                      SCpnt->use_sg,
--                                      SCpnt->sc_data_direction);
--                      } else if (SCpnt->request_bufflen) {
--                              pci_unmap_single(ioc->pcidev,
--                                      SCpnt->SCp.dma_handle,
--                                      SCpnt->request_bufflen,
--                                      SCpnt->sc_data_direction);
--                      }
-+                      scsi_dma_unmap(SCpnt);
-+
-                       SCpnt->result = DID_RESET << 16;
-                       SCpnt->host_scribble = NULL;
-@@ -1023,14 +996,19 @@
-                       mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
-                       if (mf == NULL)
-                               continue;
-+                      /* If the device is a hidden raid component, then its
-+                       * expected that the mf->function will be RAID_SCSI_IO
-+                       */
-+                      if (vdevice->vtarget->tflags &
-+                          MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function !=
-+                          MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)
-+                              continue;
-+
-                       int_to_scsilun(vdevice->lun, &lun);
-                       if ((mf->Bus != vdevice->vtarget->channel) ||
-                           (mf->TargetID != vdevice->vtarget->id) ||
-                           memcmp(lun.scsi_lun, mf->LUN, 8))
-                               continue;
--                      dsprintk(( "search_running: found (sc=%p, mf = %p) "
--                          "channel %d id %d, lun %d \n", hd->ScsiLookup[ii],
--                          mf, mf->Bus, mf->TargetID, vdevice->lun));
-                       /* Cleanup
-                        */
-@@ -1039,19 +1017,12 @@
-                       mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
-                       if ((unsigned char *)mf != sc->host_scribble)
-                               continue;
--                      if (sc->use_sg) {
--                              pci_unmap_sg(hd->ioc->pcidev,
--                              (struct scatterlist *) sc->request_buffer,
--                                      sc->use_sg,
--                                      sc->sc_data_direction);
--                      } else if (sc->request_bufflen) {
--                              pci_unmap_single(hd->ioc->pcidev,
--                                      sc->SCp.dma_handle,
--                                      sc->request_bufflen,
--                                      sc->sc_data_direction);
--                      }
-+                      scsi_dma_unmap(sc);
-                       sc->host_scribble = NULL;
-                       sc->result = DID_NO_CONNECT << 16;
-+                      dsprintk(( "search_running: found (sc=%p, mf = %p) "
-+                          "channel %d id %d, lun %d \n", sc, mf,
-+                          vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun));
-                       sc->scsi_done(sc);
-               }
-       }
-@@ -1380,10 +1351,10 @@
-        *    will be no data transfer!  GRRRRR...
-        */
-       if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
--              datalen = SCpnt->request_bufflen;
-+              datalen = scsi_bufflen(SCpnt);
-               scsidir = MPI_SCSIIO_CONTROL_READ;      /* DATA IN  (host<--ioc<--dev) */
-       } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
--              datalen = SCpnt->request_bufflen;
-+              datalen = scsi_bufflen(SCpnt);
-               scsidir = MPI_SCSIIO_CONTROL_WRITE;     /* DATA OUT (host-->ioc-->dev) */
-       } else {
-               datalen = 0;
-@@ -1768,20 +1739,45 @@
-       u32              ctx2abort;
-       int              scpnt_idx;
-       int              retval;
--      VirtDevice       *vdev;
-+      VirtDevice       *vdevice;
-       ulong            sn = SCpnt->serial_number;
-+      MPT_ADAPTER     *ioc;
-       /* If we can't locate our host adapter structure, return FAILED status.
-        */
-       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
-               SCpnt->result = DID_RESET << 16;
-               SCpnt->scsi_done(SCpnt);
--              dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
--                         "Can't locate host! (sc=%p)\n",
--                         SCpnt));
-+              dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: Can't locate "
-+                  "host! (sc=%p)\n", SCpnt));
-               return FAILED;
-       }
-+      ioc = hd->ioc;
-+      printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n",
-+             ioc->name, SCpnt);
-+      scsi_print_command(SCpnt);
-+
-+      vdevice = SCpnt->device->hostdata;
-+      if (!vdevice || !vdevice->vtarget) {
-+              dtmprintk((MYIOC_s_DEBUG_FMT "task abort: device has been "
-+                  "deleted (sc=%p)\n", ioc->name, SCpnt));
-+              SCpnt->result = DID_NO_CONNECT << 16;
-+              SCpnt->scsi_done(SCpnt);
-+              retval = 0;
-+              goto out;
-+      }
-+
-+      /* Task aborts are not supported for hidden raid components.
-+       */
-+      if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
-+              dtmprintk((MYIOC_s_DEBUG_FMT "task abort: hidden raid "
-+                  "component (sc=%p)\n", ioc->name, SCpnt));
-+              SCpnt->result = DID_RESET << 16;
-+              retval = FAILED;
-+              goto out;
-+      }
-+
-       /* Find this command
-        */
-       if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
-@@ -1790,21 +1786,20 @@
-                */
-               SCpnt->result = DID_RESET << 16;
-               dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
--                         "Command not in the active list! (sc=%p)\n",
--                         hd->ioc->name, SCpnt));
--              return SUCCESS;
-+                 "Command not in the active list! (sc=%p)\n", ioc->name,
-+                 SCpnt));
-+              retval = 0;
-+              goto out;
-       }
--      if (hd->resetPending)
--              return FAILED;
-+      if (hd->resetPending) {
-+              retval = FAILED;
-+              goto out;
-+      }
-       if (hd->timeouts < -1)
-               hd->timeouts++;
--      printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
--             hd->ioc->name, SCpnt);
--      scsi_print_command(SCpnt);
--
-       /* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
-        * (the IO to be ABORT'd)
-        *
-@@ -1817,18 +1812,17 @@
-       hd->abortSCpnt = SCpnt;
--      vdev = SCpnt->device->hostdata;
-       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
--              vdev->vtarget->channel, vdev->vtarget->id, vdev->lun,
--              ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
-+          vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
-+          ctx2abort, mptscsih_get_tm_timeout(ioc));
-       if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
-           SCpnt->serial_number == sn)
-               retval = FAILED;
--      printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
--              hd->ioc->name,
--              ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
-+ out:
-+      printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
-+          ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
-       if (retval == 0)
-               return SUCCESS;
-@@ -1850,32 +1844,47 @@
- {
-       MPT_SCSI_HOST   *hd;
-       int              retval;
--      VirtDevice       *vdev;
-+      VirtDevice       *vdevice;
-+      MPT_ADAPTER     *ioc;
-       /* If we can't locate our host adapter structure, return FAILED status.
-        */
-       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
--              dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
--                         "Can't locate host! (sc=%p)\n",
--                         SCpnt));
-+              dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: Can't "
-+                  "locate host! (sc=%p)\n", SCpnt));
-               return FAILED;
-       }
--      if (hd->resetPending)
--              return FAILED;
--
--      printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
--             hd->ioc->name, SCpnt);
-+      ioc = hd->ioc;
-+      printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n",
-+             ioc->name, SCpnt);
-       scsi_print_command(SCpnt);
--      vdev = SCpnt->device->hostdata;
-+      if (hd->resetPending) {
-+              retval = FAILED;
-+              goto out;
-+      }
-+
-+      vdevice = SCpnt->device->hostdata;
-+      if (!vdevice || !vdevice->vtarget) {
-+              retval = 0;
-+              goto out;
-+      }
-+
-+      /* Target reset to hidden raid component is not supported
-+       */
-+      if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
-+              retval = FAILED;
-+              goto out;
-+      }
-+
-       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
--              vdev->vtarget->channel, vdev->vtarget->id,
--              0, 0, mptscsih_get_tm_timeout(hd->ioc));
-+          vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0,
-+          mptscsih_get_tm_timeout(ioc));
--      printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
--              hd->ioc->name,
--              ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
-+ out:
-+      printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
-+          ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
-       if (retval == 0)
-               return SUCCESS;
-@@ -1899,18 +1908,19 @@
-       MPT_SCSI_HOST   *hd;
-       int              retval;
-       VirtDevice       *vdev;
-+      MPT_ADAPTER     *ioc;
-       /* If we can't locate our host adapter structure, return FAILED status.
-        */
-       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
--              dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
--                         "Can't locate host! (sc=%p)\n",
--                         SCpnt ) );
-+              dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: Can't "
-+                  "locate host! (sc=%p)\n", SCpnt ));
-               return FAILED;
-       }
--      printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
--             hd->ioc->name, SCpnt);
-+      ioc = hd->ioc;
-+      printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n",
-+             ioc->name, SCpnt);
-       scsi_print_command(SCpnt);
-       if (hd->timeouts < -1)
-@@ -1918,11 +1928,10 @@
-       vdev = SCpnt->device->hostdata;
-       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
--              vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
-+          vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc));
--      printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
--              hd->ioc->name,
--              ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
-+      printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
-+          ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
-       if (retval == 0)
-               return SUCCESS;
-@@ -1943,37 +1952,38 @@
- mptscsih_host_reset(struct scsi_cmnd *SCpnt)
- {
-       MPT_SCSI_HOST *  hd;
--      int              status = SUCCESS;
-+      int              retval;
-+      MPT_ADAPTER     *ioc;
-       /*  If we can't locate the host to reset, then we failed. */
-       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
--              dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
--                           "Can't locate host! (sc=%p)\n",
--                           SCpnt ) );
-+              dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: Can't "
-+                  "locate host! (sc=%p)\n", SCpnt));
-               return FAILED;
-       }
--      printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
--             hd->ioc->name, SCpnt);
-+      ioc = hd->ioc;
-+      printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
-+          ioc->name, SCpnt);
-       /*  If our attempts to reset the host failed, then return a failed
-        *  status.  The host will be taken off line by the SCSI mid-layer.
-        */
--      if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
--              status = FAILED;
-+      if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
-+              retval = FAILED;
-       } else {
-               /*  Make sure TM pending is cleared and TM state is set to
-                *  NONE.
-                */
-+              retval = 0;
-               hd->tmPending = 0;
-               hd->tmState = TM_STATE_NONE;
-       }
--      dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
--                   "Status = %s\n",
--                   (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
-+      printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
-+          ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
--      return status;
-+      return retval;
- }
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-@@ -3150,6 +3160,16 @@
- {
-       INTERNAL_CMD             iocmd;
-+      /* Ignore hidden raid components, this is handled when the command
-+       * is sent to the volume
-+       */
-+      if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
-+              return;
-+
-+      if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted ||
-+          !vdevice->configured_lun)
-+              return;
-+
-       /* Following parameters will not change
-        * in this routine.
-        */
-@@ -3164,8 +3184,6 @@
-       iocmd.id = vdevice->vtarget->id;
-       iocmd.lun = vdevice->lun;
--      if ((vdevice->vtarget->type == TYPE_DISK) &&
--          (vdevice->configured_lun))
-               mptscsih_do_cmd(hd, &iocmd);
- }
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/mptscsih.h linux-2.6.22-590/drivers/message/fusion/mptscsih.h
---- linux-2.6.22-570/drivers/message/fusion/mptscsih.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/mptscsih.h 2008-01-02 13:56:37.000000000 -0500
-@@ -6,7 +6,7 @@
-  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
-  *
-  *  Copyright (c) 1999-2007 LSI Logic Corporation
-- *  (mailto:mpt_linux_developer@lsi.com)
-+ *  (mailto:DL-MPTFusionLinux@lsi.com)
-  *
-  */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-diff -Nurb linux-2.6.22-570/drivers/message/fusion/mptspi.c linux-2.6.22-590/drivers/message/fusion/mptspi.c
---- linux-2.6.22-570/drivers/message/fusion/mptspi.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/fusion/mptspi.c   2008-01-02 13:56:37.000000000 -0500
-@@ -4,7 +4,7 @@
-  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
-  *
-  *  Copyright (c) 1999-2007 LSI Logic Corporation
-- *  (mailto:mpt_linux_developer@lsi.com)
-+ *  (mailto:DL-MPTFusionLinux@lsi.com)
-  *
-  */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-@@ -44,7 +44,6 @@
- */
- /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
--#include "linux_compat.h"     /* linux-2.6 tweaks */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
-diff -Nurb linux-2.6.22-570/drivers/message/i2o/i2o_scsi.c linux-2.6.22-590/drivers/message/i2o/i2o_scsi.c
---- linux-2.6.22-570/drivers/message/i2o/i2o_scsi.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/message/i2o/i2o_scsi.c    2008-01-02 13:56:37.000000000 -0500
-@@ -377,12 +377,8 @@
-               osm_err("SCSI error %08x\n", error);
-       dev = &c->pdev->dev;
--      if (cmd->use_sg)
--              dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg,
--                           cmd->sc_data_direction);
--      else if (cmd->SCp.dma_handle)
--              dma_unmap_single(dev, cmd->SCp.dma_handle, cmd->request_bufflen,
--                               cmd->sc_data_direction);
-+
-+      scsi_dma_unmap(cmd);
-       cmd->scsi_done(cmd);
-@@ -664,21 +660,15 @@
-       if (sgl_offset != SGL_OFFSET_0) {
-               /* write size of data addressed by SGL */
--              *mptr++ = cpu_to_le32(SCpnt->request_bufflen);
-+              *mptr++ = cpu_to_le32(scsi_bufflen(SCpnt));
-               /* Now fill in the SGList and command */
--              if (SCpnt->use_sg) {
--                      if (!i2o_dma_map_sg(c, SCpnt->request_buffer,
--                                          SCpnt->use_sg,
-+
-+              if (scsi_sg_count(SCpnt)) {
-+                      if (!i2o_dma_map_sg(c, scsi_sglist(SCpnt),
-+                                          scsi_sg_count(SCpnt),
-                                           SCpnt->sc_data_direction, &mptr))
-                               goto nomem;
--              } else {
--                      SCpnt->SCp.dma_handle =
--                          i2o_dma_map_single(c, SCpnt->request_buffer,
--                                             SCpnt->request_bufflen,
--                                             SCpnt->sc_data_direction, &mptr);
--                      if (dma_mapping_error(SCpnt->SCp.dma_handle))
--                              goto nomem;
-               }
-       }
-diff -Nurb linux-2.6.22-570/drivers/mfd/ucb1x00-ts.c linux-2.6.22-590/drivers/mfd/ucb1x00-ts.c
---- linux-2.6.22-570/drivers/mfd/ucb1x00-ts.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mfd/ucb1x00-ts.c  2008-01-02 13:56:37.000000000 -0500
-@@ -209,6 +209,7 @@
-       DECLARE_WAITQUEUE(wait, tsk);
-       int valid = 0;
-+      set_freezable();
-       add_wait_queue(&ts->irq_wait, &wait);
-       while (!kthread_should_stop()) {
-               unsigned int x, y, p;
-diff -Nurb linux-2.6.22-570/drivers/misc/asus-laptop.c linux-2.6.22-590/drivers/misc/asus-laptop.c
---- linux-2.6.22-570/drivers/misc/asus-laptop.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/misc/asus-laptop.c        2008-01-02 13:56:37.000000000 -0500
-@@ -737,8 +737,7 @@
-       struct device_attribute dev_attr_##_name = {                    \
-               .attr = {                                               \
-                       .name = __stringify(_name),                     \
--                      .mode = 0,                                      \
--                      .owner = THIS_MODULE },                         \
-+                      .mode = 0 },                                    \
-               .show   = NULL,                                         \
-               .store  = NULL,                                         \
-       }
-diff -Nurb linux-2.6.22-570/drivers/mmc/card/Kconfig linux-2.6.22-590/drivers/mmc/card/Kconfig
---- linux-2.6.22-570/drivers/mmc/card/Kconfig  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/card/Kconfig  2008-01-02 13:56:37.000000000 -0500
-@@ -14,3 +14,21 @@
-         mount the filesystem. Almost everyone wishing MMC support
-         should say Y or M here.
-+config MMC_BLOCK_BOUNCE
-+      bool "Use bounce buffer for simple hosts"
-+      depends on MMC_BLOCK
-+      default y
-+      help
-+        SD/MMC is a high latency protocol where it is crucial to
-+        send large requests in order to get high performance. Many
-+        controllers, however, are restricted to continuous memory
-+        (i.e. they can't do scatter-gather), something the kernel
-+        rarely can provide.
-+
-+        Say Y here to help these restricted hosts by bouncing
-+        requests back and forth from a large buffer. You will get
-+        a big performance gain at the cost of up to 64 KiB of
-+        physical memory.
-+
-+        If unsure, say Y here.
-+
-diff -Nurb linux-2.6.22-570/drivers/mmc/card/block.c linux-2.6.22-590/drivers/mmc/card/block.c
---- linux-2.6.22-570/drivers/mmc/card/block.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/card/block.c  2008-01-02 13:56:37.000000000 -0500
-@@ -262,7 +262,9 @@
-               }
-               brq.data.sg = mq->sg;
--              brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
-+              brq.data.sg_len = mmc_queue_map_sg(mq);
-+
-+              mmc_queue_bounce_pre(mq);
-               if (brq.data.blocks !=
-                   (req->nr_sectors >> (md->block_bits - 9))) {
-@@ -279,6 +281,9 @@
-               }
-               mmc_wait_for_req(card->host, &brq.mrq);
-+
-+              mmc_queue_bounce_post(mq);
-+
-               if (brq.cmd.error) {
-                       printk(KERN_ERR "%s: error %d sending read/write command\n",
-                              req->rq_disk->disk_name, brq.cmd.error);
-diff -Nurb linux-2.6.22-570/drivers/mmc/card/queue.c linux-2.6.22-590/drivers/mmc/card/queue.c
---- linux-2.6.22-570/drivers/mmc/card/queue.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/card/queue.c  2008-01-02 13:56:37.000000000 -0500
-@@ -11,12 +11,15 @@
-  */
- #include <linux/module.h>
- #include <linux/blkdev.h>
-+#include <linux/freezer.h>
- #include <linux/kthread.h>
- #include <linux/mmc/card.h>
- #include <linux/mmc/host.h>
- #include "queue.h"
-+#define MMC_QUEUE_BOUNCESZ    65536
-+
- #define MMC_QUEUE_SUSPENDED   (1 << 0)
- /*
-@@ -42,11 +45,7 @@
-       struct mmc_queue *mq = d;
-       struct request_queue *q = mq->queue;
--      /*
--       * Set iothread to ensure that we aren't put to sleep by
--       * the process freezing.  We handle suspension ourselves.
--       */
--      current->flags |= PF_MEMALLOC|PF_NOFREEZE;
-+      current->flags |= PF_MEMALLOC;
-       down(&mq->thread_sem);
-       do {
-@@ -118,6 +117,7 @@
-       struct mmc_host *host = card->host;
-       u64 limit = BLK_BOUNCE_HIGH;
-       int ret;
-+      unsigned int bouncesz;
-       if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
-               limit = *mmc_dev(host)->dma_mask;
-@@ -127,36 +127,83 @@
-       if (!mq->queue)
-               return -ENOMEM;
-+      mq->queue->queuedata = mq;
-+      mq->req = NULL;
-+
-       blk_queue_prep_rq(mq->queue, mmc_prep_request);
-+
-+#ifdef CONFIG_MMC_BLOCK_BOUNCE
-+      if (host->max_hw_segs == 1) {
-+              bouncesz = MMC_QUEUE_BOUNCESZ;
-+
-+              if (bouncesz > host->max_req_size)
-+                      bouncesz = host->max_req_size;
-+              if (bouncesz > host->max_seg_size)
-+                      bouncesz = host->max_seg_size;
-+
-+              mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
-+              if (!mq->bounce_buf) {
-+                      printk(KERN_WARNING "%s: unable to allocate "
-+                              "bounce buffer\n", mmc_card_name(card));
-+              } else {
-+                      blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH);
-+                      blk_queue_max_sectors(mq->queue, bouncesz / 512);
-+                      blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
-+                      blk_queue_max_hw_segments(mq->queue, bouncesz / 512);
-+                      blk_queue_max_segment_size(mq->queue, bouncesz);
-+
-+                      mq->sg = kmalloc(sizeof(struct scatterlist),
-+                              GFP_KERNEL);
-+                      if (!mq->sg) {
-+                              ret = -ENOMEM;
-+                              goto free_bounce_buf;
-+                      }
-+
-+                      mq->bounce_sg = kmalloc(sizeof(struct scatterlist) *
-+                              bouncesz / 512, GFP_KERNEL);
-+                      if (!mq->bounce_sg) {
-+                              ret = -ENOMEM;
-+                              goto free_sg;
-+                      }
-+              }
-+      }
-+#endif
-+
-+      if (!mq->bounce_buf) {
-       blk_queue_bounce_limit(mq->queue, limit);
-       blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
-       blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
-       blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
-       blk_queue_max_segment_size(mq->queue, host->max_seg_size);
--      mq->queue->queuedata = mq;
--      mq->req = NULL;
--
--      mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs,
--                       GFP_KERNEL);
-+              mq->sg = kmalloc(sizeof(struct scatterlist) *
-+                      host->max_phys_segs, GFP_KERNEL);
-       if (!mq->sg) {
-               ret = -ENOMEM;
-               goto cleanup_queue;
-       }
-+      }
-       init_MUTEX(&mq->thread_sem);
-       mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");
-       if (IS_ERR(mq->thread)) {
-               ret = PTR_ERR(mq->thread);
--              goto free_sg;
-+              goto free_bounce_sg;
-       }
-       return 0;
--
-+ free_bounce_sg:
-+      if (mq->bounce_sg)
-+              kfree(mq->bounce_sg);
-+      mq->bounce_sg = NULL;
-  free_sg:
-       kfree(mq->sg);
-       mq->sg = NULL;
-+ free_bounce_buf:
-+      if (mq->bounce_buf)
-+              kfree(mq->bounce_buf);
-+      mq->bounce_buf = NULL;
-  cleanup_queue:
-       blk_cleanup_queue(mq->queue);
-       return ret;
-@@ -178,9 +225,17 @@
-       /* Then terminate our worker thread */
-       kthread_stop(mq->thread);
-+      if (mq->bounce_sg)
-+              kfree(mq->bounce_sg);
-+      mq->bounce_sg = NULL;
-+
-       kfree(mq->sg);
-       mq->sg = NULL;
-+      if (mq->bounce_buf)
-+              kfree(mq->bounce_buf);
-+      mq->bounce_buf = NULL;
-+
-       blk_cleanup_queue(mq->queue);
-       mq->card = NULL;
-@@ -231,3 +286,108 @@
-       }
- }
-+static void copy_sg(struct scatterlist *dst, unsigned int dst_len,
-+      struct scatterlist *src, unsigned int src_len)
-+{
-+      unsigned int chunk;
-+      char *dst_buf, *src_buf;
-+      unsigned int dst_size, src_size;
-+
-+      dst_buf = NULL;
-+      src_buf = NULL;
-+      dst_size = 0;
-+      src_size = 0;
-+
-+      while (src_len) {
-+              BUG_ON(dst_len == 0);
-+
-+              if (dst_size == 0) {
-+                      dst_buf = page_address(dst->page) + dst->offset;
-+                      dst_size = dst->length;
-+              }
-+
-+              if (src_size == 0) {
-+                      src_buf = page_address(src->page) + src->offset;
-+                      src_size = src->length;
-+              }
-+
-+              chunk = min(dst_size, src_size);
-+
-+              memcpy(dst_buf, src_buf, chunk);
-+
-+              dst_buf += chunk;
-+              src_buf += chunk;
-+              dst_size -= chunk;
-+              src_size -= chunk;
-+
-+              if (dst_size == 0) {
-+                      dst++;
-+                      dst_len--;
-+              }
-+
-+              if (src_size == 0) {
-+                      src++;
-+                      src_len--;
-+              }
-+      }
-+}
-+
-+unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
-+{
-+      unsigned int sg_len;
-+
-+      if (!mq->bounce_buf)
-+              return blk_rq_map_sg(mq->queue, mq->req, mq->sg);
-+
-+      BUG_ON(!mq->bounce_sg);
-+
-+      sg_len = blk_rq_map_sg(mq->queue, mq->req, mq->bounce_sg);
-+
-+      mq->bounce_sg_len = sg_len;
-+
-+      /*
-+       * Shortcut in the event we only get a single entry.
-+       */
-+      if (sg_len == 1) {
-+              memcpy(mq->sg, mq->bounce_sg, sizeof(struct scatterlist));
-+              return 1;
-+      }
-+
-+      mq->sg[0].page = virt_to_page(mq->bounce_buf);
-+      mq->sg[0].offset = offset_in_page(mq->bounce_buf);
-+      mq->sg[0].length = 0;
-+
-+      while (sg_len) {
-+              mq->sg[0].length += mq->bounce_sg[sg_len - 1].length;
-+              sg_len--;
-+      }
-+
-+      return 1;
-+}
-+
-+void mmc_queue_bounce_pre(struct mmc_queue *mq)
-+{
-+      if (!mq->bounce_buf)
-+              return;
-+
-+      if (mq->bounce_sg_len == 1)
-+              return;
-+      if (rq_data_dir(mq->req) != WRITE)
-+              return;
-+
-+      copy_sg(mq->sg, 1, mq->bounce_sg, mq->bounce_sg_len);
-+}
-+
-+void mmc_queue_bounce_post(struct mmc_queue *mq)
-+{
-+      if (!mq->bounce_buf)
-+              return;
-+
-+      if (mq->bounce_sg_len == 1)
-+              return;
-+      if (rq_data_dir(mq->req) != READ)
-+              return;
-+
-+      copy_sg(mq->bounce_sg, mq->bounce_sg_len, mq->sg, 1);
-+}
-+
-diff -Nurb linux-2.6.22-570/drivers/mmc/card/queue.h linux-2.6.22-590/drivers/mmc/card/queue.h
---- linux-2.6.22-570/drivers/mmc/card/queue.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/card/queue.h  2008-01-02 13:56:37.000000000 -0500
-@@ -14,6 +14,9 @@
-       void                    *data;
-       struct request_queue    *queue;
-       struct scatterlist      *sg;
-+      char                    *bounce_buf;
-+      struct scatterlist      *bounce_sg;
-+      unsigned int            bounce_sg_len;
- };
- extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);
-@@ -21,4 +24,8 @@
- extern void mmc_queue_suspend(struct mmc_queue *);
- extern void mmc_queue_resume(struct mmc_queue *);
-+extern unsigned int mmc_queue_map_sg(struct mmc_queue *);
-+extern void mmc_queue_bounce_pre(struct mmc_queue *);
-+extern void mmc_queue_bounce_post(struct mmc_queue *);
-+
- #endif
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/Kconfig linux-2.6.22-590/drivers/mmc/core/Kconfig
---- linux-2.6.22-570/drivers/mmc/core/Kconfig  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/core/Kconfig  2008-01-02 13:56:37.000000000 -0500
-@@ -14,3 +14,16 @@
-         This option is usually just for embedded systems which use
-         a MMC/SD card for rootfs. Most people should say N here.
-+config MMC_PASSWORDS
-+      boolean "MMC card lock/unlock passwords (EXPERIMENTAL)"
-+      depends on EXPERIMENTAL
-+      select KEYS
-+      help
-+        Say Y here to enable the use of passwords to lock and unlock
-+        MMC cards.  This uses the access key retention support, using
-+        request_key to look up the key associated with each card.
-+
-+        For example, if you have an MMC card that was locked using
-+        Symbian OS on your cell phone, you won't be able to read it
-+        on Linux without this support.
-+
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/Makefile linux-2.6.22-590/drivers/mmc/core/Makefile
---- linux-2.6.22-570/drivers/mmc/core/Makefile 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/core/Makefile 2008-01-02 13:56:37.000000000 -0500
-@@ -7,5 +7,6 @@
- endif
- obj-$(CONFIG_MMC)             += mmc_core.o
--mmc_core-y                    := core.o sysfs.o mmc.o mmc_ops.o sd.o sd_ops.o
-+mmc_core-y                    := core.o sysfs.o bus.o host.o mmc.o mmc_ops.o sd.o sd_ops.o
-+mmc_core-$(CONFIG_MMC_PASSWORDS) += lock.o
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/bus.c linux-2.6.22-590/drivers/mmc/core/bus.c
---- linux-2.6.22-570/drivers/mmc/core/bus.c    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/mmc/core/bus.c    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,245 @@
-+/*
-+ *  linux/drivers/mmc/core/bus.c
-+ *
-+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
-+ *  Copyright (C) 2007 Pierre Ossman
-+ *
-+ * 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.
-+ *
-+ *  MMC card bus driver model
-+ */
-+
-+#include <linux/device.h>
-+#include <linux/err.h>
-+
-+#include <linux/mmc/card.h>
-+#include <linux/mmc/host.h>
-+
-+#include "sysfs.h"
-+#include "bus.h"
-+
-+#define dev_to_mmc_card(d)    container_of(d, struct mmc_card, dev)
-+#define to_mmc_driver(d)      container_of(d, struct mmc_driver, drv)
-+
-+static ssize_t mmc_type_show(struct device *dev,
-+      struct device_attribute *attr, char *buf)
-+{
-+      struct mmc_card *card = dev_to_mmc_card(dev);
-+
-+      switch (card->type) {
-+      case MMC_TYPE_MMC:
-+              return sprintf(buf, "MMC\n");
-+      case MMC_TYPE_SD:
-+              return sprintf(buf, "SD\n");
-+      default:
-+              return -EFAULT;
-+      }
-+}
-+
-+static struct device_attribute mmc_dev_attrs[] = {
-+      MMC_ATTR_RO(type),
-+      __ATTR_NULL,
-+};
-+
-+/*
-+ * This currently matches any MMC driver to any MMC card - drivers
-+ * themselves make the decision whether to drive this card in their
-+ * probe method.
-+ *
-+ * We also fail for all locked cards; drivers expect to be able to do block
-+ * I/O still on probe(), which is not possible while the card is locked.
-+ * Device probing must be triggered sometime later to make the card available
-+ * to the block driver.
-+ */
-+static int mmc_bus_match(struct device *dev, struct device_driver *drv)
-+{
-+      struct mmc_card *card = dev_to_mmc_card(dev);
-+
-+      if (mmc_card_locked(card)) {
-+              dev_dbg(&card->dev, "card is locked; binding is deferred\n");
-+              return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+static int
-+mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
-+              int buf_size)
-+{
-+      struct mmc_card *card = dev_to_mmc_card(dev);
-+      int retval = 0, i = 0, length = 0;
-+
-+#define add_env(fmt,val) do {                                 \
-+      retval = add_uevent_var(envp, num_envp, &i,             \
-+                              buf, buf_size, &length,         \
-+                              fmt, val);                      \
-+      if (retval)                                             \
-+              return retval;                                  \
-+} while (0);
-+
-+      switch (card->type) {
-+      case MMC_TYPE_MMC:
-+              add_env("MMC_TYPE=%s", "MMC");
-+              break;
-+      case MMC_TYPE_SD:
-+              add_env("MMC_TYPE=%s", "SD");
-+              break;
-+      }
-+
-+      add_env("MMC_NAME=%s", mmc_card_name(card));
-+
-+#undef add_env
-+
-+      envp[i] = NULL;
-+
-+      return 0;
-+}
-+
-+static int mmc_bus_probe(struct device *dev)
-+{
-+      struct mmc_driver *drv = to_mmc_driver(dev->driver);
-+      struct mmc_card *card = dev_to_mmc_card(dev);
-+
-+      return drv->probe(card);
-+}
-+
-+static int mmc_bus_remove(struct device *dev)
-+{
-+      struct mmc_driver *drv = to_mmc_driver(dev->driver);
-+      struct mmc_card *card = dev_to_mmc_card(dev);
-+
-+      drv->remove(card);
-+
-+      return 0;
-+}
-+
-+static int mmc_bus_suspend(struct device *dev, pm_message_t state)
-+{
-+      struct mmc_driver *drv = to_mmc_driver(dev->driver);
-+      struct mmc_card *card = dev_to_mmc_card(dev);
-+      int ret = 0;
-+
-+      if (dev->driver && drv->suspend)
-+              ret = drv->suspend(card, state);
-+      return ret;
-+}
-+
-+static int mmc_bus_resume(struct device *dev)
-+{
-+      struct mmc_driver *drv = to_mmc_driver(dev->driver);
-+      struct mmc_card *card = dev_to_mmc_card(dev);
-+      int ret = 0;
-+
-+      if (dev->driver && drv->resume)
-+              ret = drv->resume(card);
-+      return ret;
-+}
-+
-+static struct bus_type mmc_bus_type = {
-+      .name           = "mmc",
-+      .dev_attrs      = mmc_dev_attrs,
-+      .match          = mmc_bus_match,
-+      .uevent         = mmc_bus_uevent,
-+      .probe          = mmc_bus_probe,
-+      .remove         = mmc_bus_remove,
-+      .suspend        = mmc_bus_suspend,
-+      .resume         = mmc_bus_resume,
-+};
-+
-+int mmc_register_bus(void)
-+{
-+      return bus_register(&mmc_bus_type);
-+}
-+
-+void mmc_unregister_bus(void)
-+{
-+      bus_unregister(&mmc_bus_type);
-+}
-+
-+/**
-+ *    mmc_register_driver - register a media driver
-+ *    @drv: MMC media driver
-+ */
-+int mmc_register_driver(struct mmc_driver *drv)
-+{
-+      drv->drv.bus = &mmc_bus_type;
-+      return driver_register(&drv->drv);
-+}
-+
-+EXPORT_SYMBOL(mmc_register_driver);
-+
-+/**
-+ *    mmc_unregister_driver - unregister a media driver
-+ *    @drv: MMC media driver
-+ */
-+void mmc_unregister_driver(struct mmc_driver *drv)
-+{
-+      drv->drv.bus = &mmc_bus_type;
-+      driver_unregister(&drv->drv);
-+}
-+
-+EXPORT_SYMBOL(mmc_unregister_driver);
-+
-+static void mmc_release_card(struct device *dev)
-+{
-+      struct mmc_card *card = dev_to_mmc_card(dev);
-+
-+      kfree(card);
-+}
-+
-+/*
-+ * Allocate and initialise a new MMC card structure.
-+ */
-+struct mmc_card *mmc_alloc_card(struct mmc_host *host)
-+{
-+      struct mmc_card *card;
-+
-+      card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
-+      if (!card)
-+              return ERR_PTR(-ENOMEM);
-+
-+      memset(card, 0, sizeof(struct mmc_card));
-+
-+      card->host = host;
-+
-+      device_initialize(&card->dev);
-+
-+      card->dev.parent = mmc_classdev(host);
-+      card->dev.bus = &mmc_bus_type;
-+      card->dev.release = mmc_release_card;
-+
-+      return card;
-+}
-+
-+/*
-+ * Register a new MMC card with the driver model.
-+ */
-+int mmc_add_card(struct mmc_card *card)
-+{
-+      int ret;
-+
-+      snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
-+               "%s:%04x", mmc_hostname(card->host), card->rca);
-+
-+      ret = device_add(&card->dev);
-+      if (ret == 0)
-+              mmc_card_set_present(card);
-+
-+      return ret;
-+}
-+
-+/*
-+ * Unregister a new MMC card with the driver model, and
-+ * (eventually) free it.
-+ */
-+void mmc_remove_card(struct mmc_card *card)
-+{
-+      if (mmc_card_present(card))
-+              device_del(&card->dev);
-+
-+      put_device(&card->dev);
-+}
-+
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/bus.h linux-2.6.22-590/drivers/mmc/core/bus.h
---- linux-2.6.22-570/drivers/mmc/core/bus.h    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/mmc/core/bus.h    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,22 @@
-+/*
-+ *  linux/drivers/mmc/core/bus.h
-+ *
-+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
-+ *  Copyright 2007 Pierre Ossman
-+ *
-+ * 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.
-+ */
-+#ifndef _MMC_CORE_BUS_H
-+#define _MMC_CORE_BUS_H
-+
-+struct mmc_card *mmc_alloc_card(struct mmc_host *host);
-+int mmc_add_card(struct mmc_card *card);
-+void mmc_remove_card(struct mmc_card *card);
-+
-+int mmc_register_bus(void);
-+void mmc_unregister_bus(void);
-+
-+#endif
-+
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/core.c linux-2.6.22-590/drivers/mmc/core/core.c
---- linux-2.6.22-570/drivers/mmc/core/core.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/core/core.c   2008-01-02 13:56:37.000000000 -0500
-@@ -27,7 +27,9 @@
- #include <linux/mmc/sd.h>
- #include "core.h"
--#include "sysfs.h"
-+#include "bus.h"
-+#include "host.h"
-+#include "lock.h"
- #include "mmc_ops.h"
- #include "sd_ops.h"
-@@ -35,6 +37,25 @@
- extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
- extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
-+static struct workqueue_struct *workqueue;
-+
-+/*
-+ * Internal function. Schedule delayed work in the MMC work queue.
-+ */
-+static int mmc_schedule_delayed_work(struct delayed_work *work,
-+                                   unsigned long delay)
-+{
-+      return queue_delayed_work(workqueue, work, delay);
-+}
-+
-+/*
-+ * Internal function. Flush all scheduled work from the MMC work queue.
-+ */
-+static void mmc_flush_scheduled_work(void)
-+{
-+      flush_workqueue(workqueue);
-+}
-+
- /**
-  *    mmc_request_done - finish processing an MMC request
-  *    @host: MMC host which completed request
-@@ -369,22 +390,6 @@
- }
- /*
-- * Allocate a new MMC card
-- */
--struct mmc_card *mmc_alloc_card(struct mmc_host *host)
--{
--      struct mmc_card *card;
--
--      card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
--      if (!card)
--              return ERR_PTR(-ENOMEM);
--
--      mmc_init_card(card, host);
--
--      return card;
--}
--
--/*
-  * Apply power to the MMC stack.  This is a two-stage process.
-  * First, we enable power to the card without the clock running.
-  * We then wait a bit for the power to stabilise.  Finally,
-@@ -512,7 +517,7 @@
- EXPORT_SYMBOL(mmc_detect_change);
--static void mmc_rescan(struct work_struct *work)
-+void mmc_rescan(struct work_struct *work)
- {
-       struct mmc_host *host =
-               container_of(work, struct mmc_host, detect.work);
-@@ -561,69 +566,13 @@
-       }
- }
--
--/**
-- *    mmc_alloc_host - initialise the per-host structure.
-- *    @extra: sizeof private data structure
-- *    @dev: pointer to host device model structure
-- *
-- *    Initialise the per-host structure.
-- */
--struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
--{
--      struct mmc_host *host;
--
--      host = mmc_alloc_host_sysfs(extra, dev);
--      if (host) {
--              spin_lock_init(&host->lock);
--              init_waitqueue_head(&host->wq);
--              INIT_DELAYED_WORK(&host->detect, mmc_rescan);
--
--              /*
--               * By default, hosts do not support SGIO or large requests.
--               * They have to set these according to their abilities.
--               */
--              host->max_hw_segs = 1;
--              host->max_phys_segs = 1;
--              host->max_seg_size = PAGE_CACHE_SIZE;
--
--              host->max_req_size = PAGE_CACHE_SIZE;
--              host->max_blk_size = 512;
--              host->max_blk_count = PAGE_CACHE_SIZE / 512;
--      }
--
--      return host;
--}
--
--EXPORT_SYMBOL(mmc_alloc_host);
--
--/**
-- *    mmc_add_host - initialise host hardware
-- *    @host: mmc host
-- */
--int mmc_add_host(struct mmc_host *host)
-+void mmc_start_host(struct mmc_host *host)
- {
--      int ret;
--
--      ret = mmc_add_host_sysfs(host);
--      if (ret == 0) {
-               mmc_power_off(host);
-               mmc_detect_change(host, 0);
--      }
--
--      return ret;
- }
--EXPORT_SYMBOL(mmc_add_host);
--
--/**
-- *    mmc_remove_host - remove host hardware
-- *    @host: mmc host
-- *
-- *    Unregister and remove all cards associated with this host,
-- *    and power down the MMC bus.
-- */
--void mmc_remove_host(struct mmc_host *host)
-+void mmc_stop_host(struct mmc_host *host)
- {
- #ifdef CONFIG_MMC_DEBUG
-       unsigned long flags;
-@@ -648,24 +597,8 @@
-       BUG_ON(host->card);
-       mmc_power_off(host);
--      mmc_remove_host_sysfs(host);
- }
--EXPORT_SYMBOL(mmc_remove_host);
--
--/**
-- *    mmc_free_host - free the host structure
-- *    @host: mmc host
-- *
-- *    Free the host once all references to it have been dropped.
-- */
--void mmc_free_host(struct mmc_host *host)
--{
--      mmc_free_host_sysfs(host);
--}
--
--EXPORT_SYMBOL(mmc_free_host);
--
- #ifdef CONFIG_PM
- /**
-@@ -726,4 +659,47 @@
- #endif
-+static int __init mmc_init(void)
-+{
-+      int ret;
-+
-+      workqueue = create_singlethread_workqueue("kmmcd");
-+      if (!workqueue)
-+              return -ENOMEM;
-+
-+      ret = mmc_register_bus();
-+      if (ret)
-+              goto destroy_workqueue;
-+
-+      ret = mmc_register_host_class();
-+      if (ret)
-+              goto unregister_bus;
-+
-+      ret = mmc_register_key_type();
-+      if (ret)
-+              goto unregister_host_class;
-+
-+      return 0;
-+
-+unregister_host_class:
-+      mmc_unregister_host_class();
-+unregister_bus:
-+      mmc_unregister_bus();
-+destroy_workqueue:
-+      destroy_workqueue(workqueue);
-+
-+      return ret;
-+}
-+
-+static void __exit mmc_exit(void)
-+{
-+      mmc_unregister_key_type();
-+      mmc_unregister_host_class();
-+      mmc_unregister_bus();
-+      destroy_workqueue(workqueue);
-+}
-+
-+module_init(mmc_init);
-+module_exit(mmc_exit);
-+
- MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/core.h linux-2.6.22-590/drivers/mmc/core/core.h
---- linux-2.6.22-570/drivers/mmc/core/core.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/core/core.h   2008-01-02 13:56:37.000000000 -0500
-@@ -54,8 +54,6 @@
- u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
- void mmc_set_timing(struct mmc_host *host, unsigned int timing);
--struct mmc_card *mmc_alloc_card(struct mmc_host *host);
--
- static inline void mmc_delay(unsigned int ms)
- {
-       if (ms < 1000 / HZ) {
-@@ -66,5 +64,9 @@
-       }
- }
-+void mmc_rescan(struct work_struct *work);
-+void mmc_start_host(struct mmc_host *host);
-+void mmc_stop_host(struct mmc_host *host);
-+
- #endif
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/host.c linux-2.6.22-590/drivers/mmc/core/host.c
---- linux-2.6.22-570/drivers/mmc/core/host.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/mmc/core/host.c   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,156 @@
-+/*
-+ *  linux/drivers/mmc/core/host.c
-+ *
-+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
-+ *  Copyright (C) 2007 Pierre Ossman
-+ *
-+ * 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.
-+ *
-+ *  MMC host class device management
-+ */
-+
-+#include <linux/device.h>
-+#include <linux/err.h>
-+#include <linux/idr.h>
-+#include <linux/pagemap.h>
-+
-+#include <linux/mmc/host.h>
-+
-+#include "core.h"
-+#include "host.h"
-+
-+#define cls_dev_to_mmc_host(d)        container_of(d, struct mmc_host, class_dev)
-+
-+static void mmc_host_classdev_release(struct device *dev)
-+{
-+      struct mmc_host *host = cls_dev_to_mmc_host(dev);
-+      kfree(host);
-+}
-+
-+static struct class mmc_host_class = {
-+      .name           = "mmc_host",
-+      .dev_release    = mmc_host_classdev_release,
-+};
-+
-+int mmc_register_host_class(void)
-+{
-+      return class_register(&mmc_host_class);
-+}
-+
-+void mmc_unregister_host_class(void)
-+{
-+      class_unregister(&mmc_host_class);
-+}
-+
-+static DEFINE_IDR(mmc_host_idr);
-+static DEFINE_SPINLOCK(mmc_host_lock);
-+
-+/**
-+ *    mmc_alloc_host - initialise the per-host structure.
-+ *    @extra: sizeof private data structure
-+ *    @dev: pointer to host device model structure
-+ *
-+ *    Initialise the per-host structure.
-+ */
-+struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
-+{
-+      struct mmc_host *host;
-+
-+      host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
-+      if (!host)
-+              return NULL;
-+
-+      memset(host, 0, sizeof(struct mmc_host) + extra);
-+
-+      host->parent = dev;
-+      host->class_dev.parent = dev;
-+      host->class_dev.class = &mmc_host_class;
-+      device_initialize(&host->class_dev);
-+
-+      spin_lock_init(&host->lock);
-+      init_waitqueue_head(&host->wq);
-+      INIT_DELAYED_WORK(&host->detect, mmc_rescan);
-+
-+      /*
-+       * By default, hosts do not support SGIO or large requests.
-+       * They have to set these according to their abilities.
-+       */
-+      host->max_hw_segs = 1;
-+      host->max_phys_segs = 1;
-+      host->max_seg_size = PAGE_CACHE_SIZE;
-+
-+      host->max_req_size = PAGE_CACHE_SIZE;
-+      host->max_blk_size = 512;
-+      host->max_blk_count = PAGE_CACHE_SIZE / 512;
-+
-+      return host;
-+}
-+
-+EXPORT_SYMBOL(mmc_alloc_host);
-+
-+/**
-+ *    mmc_add_host - initialise host hardware
-+ *    @host: mmc host
-+ */
-+int mmc_add_host(struct mmc_host *host)
-+{
-+      int err;
-+
-+      if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
-+              return -ENOMEM;
-+
-+      spin_lock(&mmc_host_lock);
-+      err = idr_get_new(&mmc_host_idr, host, &host->index);
-+      spin_unlock(&mmc_host_lock);
-+      if (err)
-+              return err;
-+
-+      snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
-+               "mmc%d", host->index);
-+
-+      err = device_add(&host->class_dev);
-+      if (err)
-+              return err;
-+
-+      mmc_start_host(host);
-+
-+      return 0;
-+}
-+
-+EXPORT_SYMBOL(mmc_add_host);
-+
-+/**
-+ *    mmc_remove_host - remove host hardware
-+ *    @host: mmc host
-+ *
-+ *    Unregister and remove all cards associated with this host,
-+ *    and power down the MMC bus.
-+ */
-+void mmc_remove_host(struct mmc_host *host)
-+{
-+      mmc_stop_host(host);
-+
-+      device_del(&host->class_dev);
-+
-+      spin_lock(&mmc_host_lock);
-+      idr_remove(&mmc_host_idr, host->index);
-+      spin_unlock(&mmc_host_lock);
-+}
-+
-+EXPORT_SYMBOL(mmc_remove_host);
-+
-+/**
-+ *    mmc_free_host - free the host structure
-+ *    @host: mmc host
-+ *
-+ *    Free the host once all references to it have been dropped.
-+ */
-+void mmc_free_host(struct mmc_host *host)
-+{
-+      put_device(&host->class_dev);
-+}
-+
-+EXPORT_SYMBOL(mmc_free_host);
-+
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/host.h linux-2.6.22-590/drivers/mmc/core/host.h
---- linux-2.6.22-570/drivers/mmc/core/host.h   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/mmc/core/host.h   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,18 @@
-+/*
-+ *  linux/drivers/mmc/core/host.h
-+ *
-+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
-+ *  Copyright 2007 Pierre Ossman
-+ *
-+ * 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.
-+ */
-+#ifndef _MMC_CORE_HOST_H
-+#define _MMC_CORE_HOST_H
-+
-+int mmc_register_host_class(void);
-+void mmc_unregister_host_class(void);
-+
-+#endif
-+
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/lock.c linux-2.6.22-590/drivers/mmc/core/lock.c
---- linux-2.6.22-570/drivers/mmc/core/lock.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/mmc/core/lock.c   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,199 @@
-+/*
-+ *  linux/drivers/mmc/core/lock.h
-+ *
-+ *  Copyright 2006 Instituto Nokia de Tecnologia (INdT), All Rights Reserved.
-+ *  Copyright 2007 Pierre Ossman
-+ *
-+ * 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.
-+ *
-+ * MMC password key handling.
-+ */
-+
-+#include <linux/device.h>
-+#include <linux/key.h>
-+#include <linux/err.h>
-+
-+#include <linux/mmc/card.h>
-+#include <linux/mmc/host.h>
-+#include <linux/mmc/mmc.h>
-+
-+#include "sysfs.h"
-+#include "mmc_ops.h"
-+#include "lock.h"
-+
-+#define MMC_KEYLEN_MAXBYTES 32
-+
-+#define dev_to_mmc_card(d)    container_of(d, struct mmc_card, dev)
-+
-+static int mmc_key_instantiate(struct key *key, const void *data, size_t datalen)
-+{
-+      struct mmc_key_payload *mpayload;
-+      int ret;
-+
-+      ret = -EINVAL;
-+      if (datalen <= 0 || datalen > MMC_KEYLEN_MAXBYTES || !data) {
-+              pr_debug("Invalid data\n");
-+              goto error;
-+      }
-+
-+      ret = key_payload_reserve(key, datalen);
-+      if (ret < 0) {
-+              pr_debug("ret = %d\n", ret);
-+              goto error;
-+      }
-+
-+      ret = -ENOMEM;
-+      mpayload = kmalloc(sizeof(*mpayload) + datalen, GFP_KERNEL);
-+      if (!mpayload) {
-+              pr_debug("Unable to allocate mpayload structure\n");
-+              goto error;
-+      }
-+      mpayload->datalen = datalen;
-+      memcpy(mpayload->data, data, datalen);
-+
-+      rcu_assign_pointer(key->payload.data, mpayload);
-+
-+      /* ret = 0 if there is no error */
-+      ret = 0;
-+
-+error:
-+      return ret;
-+}
-+
-+static int mmc_key_match(const struct key *key, const void *description)
-+{
-+      return strcmp(key->description, description) == 0;
-+}
-+
-+/*
-+ * dispose of the data dangling from the corpse of a mmc key
-+ */
-+static void mmc_key_destroy(struct key *key)
-+{
-+      struct mmc_key_payload *mpayload = key->payload.data;
-+
-+      kfree(mpayload);
-+}
-+
-+static struct key_type mmc_key_type = {
-+      .name           = "mmc",
-+      .def_datalen    = MMC_KEYLEN_MAXBYTES,
-+      .instantiate    = mmc_key_instantiate,
-+      .match          = mmc_key_match,
-+      .destroy        = mmc_key_destroy,
-+};
-+
-+int mmc_register_key_type(void)
-+{
-+      return register_key_type(&mmc_key_type);
-+}
-+
-+void mmc_unregister_key_type(void)
-+{
-+      unregister_key_type(&mmc_key_type);
-+}
-+
-+static ssize_t
-+mmc_lockable_show(struct device *dev, struct device_attribute *att, char *buf)
-+{
-+      struct mmc_card *card = dev_to_mmc_card(dev);
-+
-+      return sprintf(buf, "%slocked\n", mmc_card_locked(card) ? "" : "un");
-+}
-+
-+/*
-+ * implement MMC password functions: force erase, remove password, change
-+ * password, unlock card and assign password.
-+ */
-+static ssize_t
-+mmc_lockable_store(struct device *dev, struct device_attribute *att,
-+      const char *data, size_t len)
-+{
-+      struct mmc_card *card = dev_to_mmc_card(dev);
-+      int ret;
-+      struct key *mmc_key;
-+
-+      if(!mmc_card_lockable(card))
-+              return -EINVAL;
-+
-+      mmc_claim_host(card->host);
-+
-+      ret = -EINVAL;
-+      if (mmc_card_locked(card) && !strncmp(data, "erase", 5)) {
-+              /* forced erase only works while card is locked */
-+              mmc_lock_unlock(card, NULL, MMC_LOCK_MODE_ERASE);
-+              ret = len;
-+      } else if (!mmc_card_locked(card) && !strncmp(data, "remove", 6)) {
-+              /* remove password only works while card is unlocked */
-+              mmc_key = request_key(&mmc_key_type, "mmc:key", "remove");
-+
-+              if (!IS_ERR(mmc_key)) {
-+                      ret =  mmc_lock_unlock(card, mmc_key, MMC_LOCK_MODE_CLR_PWD);
-+                      if (!ret)
-+                              ret = len;
-+              } else
-+                      dev_dbg(&card->dev, "request_key returned error %ld\n", PTR_ERR(mmc_key));
-+      } else if (!mmc_card_locked(card) && ((!strncmp(data, "assign", 6)) ||
-+                                            (!strncmp(data, "change", 6)))) {
-+              /* assign or change */
-+              if(!(strncmp(data, "assign", 6)))
-+                      mmc_key = request_key(&mmc_key_type, "mmc:key", "assign");
-+              else
-+                      mmc_key = request_key(&mmc_key_type, "mmc:key", "change");
-+
-+              if (!IS_ERR(mmc_key)) {
-+                      ret = mmc_lock_unlock(card, mmc_key, MMC_LOCK_MODE_SET_PWD);
-+                      if (!ret)
-+                              ret = len;
-+              } else
-+                      dev_dbg(&card->dev, "request_key returned error %ld\n", PTR_ERR(mmc_key));
-+      } else if (mmc_card_locked(card) && !strncmp(data, "unlock", 6)) {
-+              /* unlock */
-+              mmc_key = request_key(&mmc_key_type, "mmc:key", "unlock");
-+              if (!IS_ERR(mmc_key)) {
-+                      ret = mmc_lock_unlock(card, mmc_key, MMC_LOCK_MODE_UNLOCK);
-+                      if (ret) {
-+                              dev_dbg(&card->dev, "Wrong password\n");
-+                              ret = -EINVAL;
-+                      }
-+                      else {
-+                              mmc_release_host(card->host);
-+                              device_release_driver(dev);
-+                              ret = device_attach(dev);
-+                              if(!ret)
-+                                      return -EINVAL;
-+                              else
-+                                      return len;
-+                      }
-+              } else
-+                      dev_dbg(&card->dev, "request_key returned error %ld\n", PTR_ERR(mmc_key));
-+      }
-+
-+      mmc_release_host(card->host);
-+      return ret;
-+}
-+
-+static struct device_attribute mmc_dev_attr_lockable[] = {
-+      __ATTR(lockable, S_IWUSR | S_IRUGO,
-+              mmc_lockable_show, mmc_lockable_store),
-+      __ATTR_NULL,
-+};
-+
-+int mmc_lock_add_sysfs(struct mmc_card *card)
-+{
-+      if (!mmc_card_lockable(card))
-+              return 0;
-+
-+      return mmc_add_attrs(card, mmc_dev_attr_lockable);
-+}
-+
-+void mmc_lock_remove_sysfs(struct mmc_card *card)
-+{
-+      if (!mmc_card_lockable(card))
-+              return;
-+
-+      mmc_remove_attrs(card, mmc_dev_attr_lockable);
-+}
-+
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/lock.h linux-2.6.22-590/drivers/mmc/core/lock.h
---- linux-2.6.22-570/drivers/mmc/core/lock.h   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/mmc/core/lock.h   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,51 @@
-+/*
-+ *  linux/drivers/mmc/core/lock.h
-+ *
-+ *  Copyright 2006 Instituto Nokia de Tecnologia (INdT), All Rights Reserved.
-+ *  Copyright 2007 Pierre Ossman
-+ *
-+ * 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.
-+ */
-+#ifndef _MMC_CORE_LOCK_H
-+#define _MMC_CORE_LOCK_H
-+
-+#ifdef CONFIG_MMC_PASSWORDS
-+
-+/* core-internal data */
-+struct mmc_key_payload {
-+      struct rcu_head rcu;            /* RCU destructor */
-+      unsigned short  datalen;        /* length of this data */
-+      char            data[0];        /* actual data */
-+};
-+
-+int mmc_register_key_type(void);
-+void mmc_unregister_key_type(void);
-+
-+int mmc_lock_add_sysfs(struct mmc_card *card);
-+void mmc_lock_remove_sysfs(struct mmc_card *card);
-+
-+#else
-+
-+static inline int mmc_register_key_type(void)
-+{
-+      return 0;
-+}
-+
-+static inline void mmc_unregister_key_type(void)
-+{
-+}
-+
-+static inline int mmc_lock_add_sysfs(struct mmc_card *card)
-+{
-+      return 0;
-+}
-+
-+static inline void mmc_lock_remove_sysfs(struct mmc_card *card)
-+{
-+}
-+
-+#endif
-+
-+#endif
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/mmc.c linux-2.6.22-590/drivers/mmc/core/mmc.c
---- linux-2.6.22-570/drivers/mmc/core/mmc.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/core/mmc.c    2008-01-02 13:56:37.000000000 -0500
-@@ -18,6 +18,8 @@
- #include "core.h"
- #include "sysfs.h"
-+#include "bus.h"
-+#include "lock.h"
- #include "mmc_ops.h"
- static const unsigned int tran_exp[] = {
-@@ -230,19 +232,74 @@
-       return err;
- }
-+MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
-+      card->raw_cid[2], card->raw_cid[3]);
-+MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
-+      card->raw_csd[2], card->raw_csd[3]);
-+MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year);
-+MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev);
-+MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev);
-+MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid);
-+MMC_ATTR_FN(name, "%s\n", card->cid.prod_name);
-+MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid);
-+MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial);
-+
-+static struct device_attribute mmc_dev_attrs[] = {
-+      MMC_ATTR_RO(cid),
-+      MMC_ATTR_RO(csd),
-+      MMC_ATTR_RO(date),
-+      MMC_ATTR_RO(fwrev),
-+      MMC_ATTR_RO(hwrev),
-+      MMC_ATTR_RO(manfid),
-+      MMC_ATTR_RO(name),
-+      MMC_ATTR_RO(oemid),
-+      MMC_ATTR_RO(serial),
-+      __ATTR_NULL,
-+};
-+
-+/*
-+ * Adds sysfs entries as relevant.
-+ */
-+static int mmc_sysfs_add(struct mmc_card *card)
-+{
-+      int ret;
-+
-+      ret = mmc_add_attrs(card, mmc_dev_attrs);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = mmc_lock_add_sysfs(card);
-+      if (ret < 0) {
-+              mmc_remove_attrs(card, mmc_dev_attrs);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+/*
-+ * Removes the sysfs entries added by mmc_sysfs_add().
-+ */
-+static void mmc_sysfs_remove(struct mmc_card *card)
-+{
-+      mmc_lock_remove_sysfs(card);
-+      mmc_remove_attrs(card, mmc_dev_attrs);
-+}
-+
- /*
-  * Handle the detection and initialisation of a card.
-  *
-  * In the case of a resume, "curcard" will contain the card
-  * we're trying to reinitialise.
-  */
--static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
-+static int mmc_init_card(struct mmc_host *host, u32 ocr,
-       struct mmc_card *oldcard)
- {
-       struct mmc_card *card;
-       int err;
-       u32 cid[4];
-       unsigned int max_dtr;
-+      u32 status;
-       BUG_ON(!host);
-       BUG_ON(!host->claimed);
-@@ -294,6 +351,15 @@
-       mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
-+      /*
-+       * Check if card is locked.
-+       */
-+      err = mmc_send_status(card, &status);
-+      if (err != MMC_ERR_NONE)
-+              goto free_card;
-+      if (status & R1_CARD_IS_LOCKED)
-+              mmc_card_set_locked(card);
-+
-       if (!oldcard) {
-               /*
-                * Fetch CSD from card.
-@@ -389,6 +455,8 @@
-       BUG_ON(!host);
-       BUG_ON(!host->card);
-+      mmc_sysfs_remove(host->card);
-+
-       mmc_remove_card(host->card);
-       host->card = NULL;
- }
-@@ -413,8 +481,7 @@
-       mmc_release_host(host);
-       if (err != MMC_ERR_NONE) {
--              mmc_remove_card(host->card);
--              host->card = NULL;
-+              mmc_remove(host);
-               mmc_claim_host(host);
-               mmc_detach_bus(host);
-@@ -434,7 +501,7 @@
-       mmc_claim_host(host);
-       mmc_deselect_cards(host);
--      host->card->state &= ~MMC_STATE_HIGHSPEED;
-+      host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_LOCKED);
-       mmc_release_host(host);
- }
-@@ -453,11 +520,9 @@
-       mmc_claim_host(host);
--      err = mmc_sd_init_card(host, host->ocr, host->card);
-+      err = mmc_init_card(host, host->ocr, host->card);
-       if (err != MMC_ERR_NONE) {
--              mmc_remove_card(host->card);
--              host->card = NULL;
--
-+              mmc_remove(host);
-               mmc_detach_bus(host);
-       }
-@@ -512,13 +577,17 @@
-       /*
-        * Detect and init the card.
-        */
--      err = mmc_sd_init_card(host, host->ocr, NULL);
-+      err = mmc_init_card(host, host->ocr, NULL);
-       if (err != MMC_ERR_NONE)
-               goto err;
-       mmc_release_host(host);
--      err = mmc_register_card(host->card);
-+      err = mmc_add_card(host->card);
-+      if (err)
-+              goto reclaim_host;
-+
-+      err = mmc_sysfs_add(host->card);
-       if (err)
-               goto reclaim_host;
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/mmc_ops.c linux-2.6.22-590/drivers/mmc/core/mmc_ops.c
---- linux-2.6.22-570/drivers/mmc/core/mmc_ops.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/core/mmc_ops.c        2008-01-02 13:56:37.000000000 -0500
-@@ -2,6 +2,8 @@
-  *  linux/drivers/mmc/mmc_ops.h
-  *
-  *  Copyright 2006-2007 Pierre Ossman
-+ *  MMC password protection (C) 2006 Instituto Nokia de Tecnologia (INdT),
-+ *     All Rights Reserved.
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-@@ -12,12 +14,14 @@
- #include <linux/types.h>
- #include <asm/scatterlist.h>
- #include <linux/scatterlist.h>
-+#include <linux/key.h>
- #include <linux/mmc/host.h>
- #include <linux/mmc/card.h>
- #include <linux/mmc/mmc.h>
- #include "core.h"
-+#include "lock.h"
- #include "mmc_ops.h"
- static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
-@@ -274,3 +278,114 @@
-       return MMC_ERR_NONE;
- }
-+#ifdef CONFIG_MMC_PASSWORDS
-+
-+int mmc_lock_unlock(struct mmc_card *card, struct key *key, int mode)
-+{
-+      struct mmc_request mrq;
-+      struct mmc_command cmd;
-+      struct mmc_data data;
-+      struct scatterlist sg;
-+      struct mmc_key_payload *mpayload;
-+      unsigned long erase_timeout;
-+      int err, data_size;
-+      u8 *data_buf;
-+
-+      mpayload = NULL;
-+      data_size = 1;
-+      if (!(mode & MMC_LOCK_MODE_ERASE)) {
-+              mpayload = rcu_dereference(key->payload.data);
-+              data_size = 2 + mpayload->datalen;
-+      }
-+
-+      data_buf = kmalloc(data_size, GFP_KERNEL);
-+      if (!data_buf)
-+              return -ENOMEM;
-+      memset(data_buf, 0, data_size);
-+
-+      data_buf[0] |= mode;
-+      if (mode & MMC_LOCK_MODE_UNLOCK)
-+              data_buf[0] &= ~MMC_LOCK_MODE_UNLOCK;
-+
-+      if (!(mode & MMC_LOCK_MODE_ERASE)) {
-+              data_buf[1] = mpayload->datalen;
-+              memcpy(data_buf + 2, mpayload->data, mpayload->datalen);
-+      }
-+
-+      memset(&cmd, 0, sizeof(struct mmc_command));
-+
-+      cmd.opcode = MMC_SET_BLOCKLEN;
-+      cmd.arg = data_size;
-+      cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-+      err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
-+      if (err != MMC_ERR_NONE)
-+              goto out;
-+
-+      memset(&cmd, 0, sizeof(struct mmc_command));
-+
-+      cmd.opcode = MMC_LOCK_UNLOCK;
-+      cmd.arg = 0;
-+      cmd.flags = MMC_RSP_R1B | MMC_CMD_ADTC;
-+
-+      memset(&data, 0, sizeof(struct mmc_data));
-+
-+      mmc_set_data_timeout(&data, card, 1);
-+
-+      data.blksz = data_size;
-+      data.blocks = 1;
-+      data.flags = MMC_DATA_WRITE;
-+      data.sg = &sg;
-+      data.sg_len = 1;
-+
-+      memset(&mrq, 0, sizeof(struct mmc_request));
-+
-+      mrq.cmd = &cmd;
-+      mrq.data = &data;
-+
-+      sg_init_one(&sg, data_buf, data_size);
-+      err = mmc_wait_for_req(card->host, &mrq);
-+      if (err != MMC_ERR_NONE)
-+              goto out;
-+
-+      memset(&cmd, 0, sizeof(struct mmc_command));
-+
-+      cmd.opcode = MMC_SEND_STATUS;
-+      cmd.arg = card->rca << 16;
-+      cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-+
-+      /* set timeout for forced erase operation to 3 min. (see MMC spec) */
-+      erase_timeout = jiffies + 180 * HZ;
-+      do {
-+              /* we cannot use "retries" here because the
-+               * R1_LOCK_UNLOCK_FAILED bit is cleared by subsequent reads to
-+               * the status register, hiding the error condition */
-+              err = mmc_wait_for_cmd(card->host, &cmd, 0);
-+              if (err != MMC_ERR_NONE)
-+                      break;
-+              /* the other modes don't need timeout checking */
-+              if (!(mode & MMC_LOCK_MODE_ERASE))
-+                      continue;
-+              if (time_after(jiffies, erase_timeout)) {
-+                      dev_dbg(&card->dev, "forced erase timed out\n");
-+                      err = MMC_ERR_TIMEOUT;
-+                      break;
-+              }
-+      } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
-+      if (cmd.resp[0] & R1_LOCK_UNLOCK_FAILED) {
-+              dev_dbg(&card->dev, "LOCK_UNLOCK operation failed\n");
-+              err = MMC_ERR_FAILED;
-+      }
-+
-+      if (cmd.resp[0] & R1_CARD_IS_LOCKED)
-+              mmc_card_set_locked(card);
-+      else
-+              card->state &= ~MMC_STATE_LOCKED;
-+
-+out:
-+      kfree(data_buf);
-+
-+      return err;
-+}
-+
-+#endif /* CONFIG_MMC_PASSWORDS */
-+
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/mmc_ops.h linux-2.6.22-590/drivers/mmc/core/mmc_ops.h
---- linux-2.6.22-570/drivers/mmc/core/mmc_ops.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/core/mmc_ops.h        2008-01-02 13:56:37.000000000 -0500
-@@ -12,6 +12,8 @@
- #ifndef _MMC_MMC_OPS_H
- #define _MMC_MMC_OPS_H
-+struct key;
-+
- int mmc_select_card(struct mmc_card *card);
- int mmc_deselect_cards(struct mmc_host *host);
- int mmc_go_idle(struct mmc_host *host);
-@@ -22,6 +24,7 @@
- int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
- int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value);
- int mmc_send_status(struct mmc_card *card, u32 *status);
-+int mmc_lock_unlock(struct mmc_card *card, struct key *key, int mode);
- #endif
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/sd.c linux-2.6.22-590/drivers/mmc/core/sd.c
---- linux-2.6.22-570/drivers/mmc/core/sd.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/core/sd.c     2008-01-02 13:56:37.000000000 -0500
-@@ -19,11 +19,11 @@
- #include "core.h"
- #include "sysfs.h"
-+#include "bus.h"
-+#include "lock.h"
- #include "mmc_ops.h"
- #include "sd_ops.h"
--#include "core.h"
--
- static const unsigned int tran_exp[] = {
-       10000,          100000,         1000000,        10000000,
-       0,              0,              0,              0
-@@ -280,6 +280,62 @@
-       return err;
- }
-+MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
-+      card->raw_cid[2], card->raw_cid[3]);
-+MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
-+      card->raw_csd[2], card->raw_csd[3]);
-+MMC_ATTR_FN(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
-+MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year);
-+MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev);
-+MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev);
-+MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid);
-+MMC_ATTR_FN(name, "%s\n", card->cid.prod_name);
-+MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid);
-+MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial);
-+
-+static struct device_attribute mmc_sd_dev_attrs[] = {
-+      MMC_ATTR_RO(cid),
-+      MMC_ATTR_RO(csd),
-+      MMC_ATTR_RO(scr),
-+      MMC_ATTR_RO(date),
-+      MMC_ATTR_RO(fwrev),
-+      MMC_ATTR_RO(hwrev),
-+      MMC_ATTR_RO(manfid),
-+      MMC_ATTR_RO(name),
-+      MMC_ATTR_RO(oemid),
-+      MMC_ATTR_RO(serial),
-+      __ATTR_NULL,
-+};
-+
-+/*
-+ * Adds sysfs entries as relevant.
-+ */
-+static int mmc_sd_sysfs_add(struct mmc_card *card)
-+{
-+      int ret;
-+
-+      ret = mmc_add_attrs(card, mmc_sd_dev_attrs);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = mmc_lock_add_sysfs(card);
-+      if (ret < 0) {
-+              mmc_remove_attrs(card, mmc_sd_dev_attrs);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+/*
-+ * Removes the sysfs entries added by mmc_sysfs_add().
-+ */
-+static void mmc_sd_sysfs_remove(struct mmc_card *card)
-+{
-+      mmc_lock_remove_sysfs(card);
-+      mmc_remove_attrs(card, mmc_sd_dev_attrs);
-+}
-+
- /*
-  * Handle the detection and initialisation of a card.
-  *
-@@ -293,6 +349,7 @@
-       int err;
-       u32 cid[4];
-       unsigned int max_dtr;
-+      u32 status;
-       BUG_ON(!host);
-       BUG_ON(!host->claimed);
-@@ -352,6 +409,15 @@
-       mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
-+      /*
-+       * Check if card is locked.
-+       */
-+      err = mmc_send_status(card, &status);
-+      if (err != MMC_ERR_NONE)
-+              goto free_card;
-+      if (status & R1_CARD_IS_LOCKED)
-+              mmc_card_set_locked(card);
-+
-       if (!oldcard) {
-               /*
-                * Fetch CSD from card.
-@@ -463,6 +529,8 @@
-       BUG_ON(!host);
-       BUG_ON(!host->card);
-+      mmc_sd_sysfs_remove(host->card);
-+
-       mmc_remove_card(host->card);
-       host->card = NULL;
- }
-@@ -487,8 +555,7 @@
-       mmc_release_host(host);
-       if (err != MMC_ERR_NONE) {
--              mmc_remove_card(host->card);
--              host->card = NULL;
-+              mmc_sd_remove(host);
-               mmc_claim_host(host);
-               mmc_detach_bus(host);
-@@ -508,7 +575,7 @@
-       mmc_claim_host(host);
-       mmc_deselect_cards(host);
--      host->card->state &= ~MMC_STATE_HIGHSPEED;
-+      host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_LOCKED);
-       mmc_release_host(host);
- }
-@@ -529,9 +596,7 @@
-       err = mmc_sd_init_card(host, host->ocr, host->card);
-       if (err != MMC_ERR_NONE) {
--              mmc_remove_card(host->card);
--              host->card = NULL;
--
-+              mmc_sd_remove(host);
-               mmc_detach_bus(host);
-       }
-@@ -599,7 +664,11 @@
-       mmc_release_host(host);
--      err = mmc_register_card(host->card);
-+      err = mmc_add_card(host->card);
-+      if (err)
-+              goto reclaim_host;
-+
-+      err = mmc_sd_sysfs_add(host->card);
-       if (err)
-               goto reclaim_host;
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/sysfs.c linux-2.6.22-590/drivers/mmc/core/sysfs.c
---- linux-2.6.22-570/drivers/mmc/core/sysfs.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/core/sysfs.c  2008-01-02 13:56:37.000000000 -0500
-@@ -2,6 +2,7 @@
-  *  linux/drivers/mmc/core/sysfs.c
-  *
-  *  Copyright (C) 2003 Russell King, All Rights Reserved.
-+ *  Copyright 2007 Pierre Ossman
-  *
-  * 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
-@@ -9,352 +10,34 @@
-  *
-  *  MMC sysfs/driver model support.
-  */
--#include <linux/module.h>
--#include <linux/init.h>
- #include <linux/device.h>
--#include <linux/idr.h>
--#include <linux/workqueue.h>
- #include <linux/mmc/card.h>
--#include <linux/mmc/host.h>
- #include "sysfs.h"
--#define dev_to_mmc_card(d)    container_of(d, struct mmc_card, dev)
--#define to_mmc_driver(d)      container_of(d, struct mmc_driver, drv)
--#define cls_dev_to_mmc_host(d)        container_of(d, struct mmc_host, class_dev)
--
--#define MMC_ATTR(name, fmt, args...)                                  \
--static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)       \
--{                                                                     \
--      struct mmc_card *card = dev_to_mmc_card(dev);                   \
--      return sprintf(buf, fmt, args);                                 \
--}
--
--MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
--      card->raw_cid[2], card->raw_cid[3]);
--MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
--      card->raw_csd[2], card->raw_csd[3]);
--MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
--MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
--MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
--MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
--MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
--MMC_ATTR(name, "%s\n", card->cid.prod_name);
--MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
--MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
--
--#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
--
--static struct device_attribute mmc_dev_attrs[] = {
--      MMC_ATTR_RO(cid),
--      MMC_ATTR_RO(csd),
--      MMC_ATTR_RO(date),
--      MMC_ATTR_RO(fwrev),
--      MMC_ATTR_RO(hwrev),
--      MMC_ATTR_RO(manfid),
--      MMC_ATTR_RO(name),
--      MMC_ATTR_RO(oemid),
--      MMC_ATTR_RO(serial),
--      __ATTR_NULL
--};
--
--static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
--
--
--static void mmc_release_card(struct device *dev)
--{
--      struct mmc_card *card = dev_to_mmc_card(dev);
--
--      kfree(card);
--}
--
--/*
-- * This currently matches any MMC driver to any MMC card - drivers
-- * themselves make the decision whether to drive this card in their
-- * probe method.
-- */
--static int mmc_bus_match(struct device *dev, struct device_driver *drv)
--{
--      return 1;
--}
--
--static int
--mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
--              int buf_size)
--{
--      struct mmc_card *card = dev_to_mmc_card(dev);
--      char ccc[13];
--      int retval = 0, i = 0, length = 0;
--
--#define add_env(fmt,val) do {                                 \
--      retval = add_uevent_var(envp, num_envp, &i,             \
--                              buf, buf_size, &length,         \
--                              fmt, val);                      \
--      if (retval)                                             \
--              return retval;                                  \
--} while (0);
--
--      for (i = 0; i < 12; i++)
--              ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';
--      ccc[12] = '\0';
--
--      add_env("MMC_CCC=%s", ccc);
--      add_env("MMC_MANFID=%06x", card->cid.manfid);
--      add_env("MMC_NAME=%s", mmc_card_name(card));
--      add_env("MMC_OEMID=%04x", card->cid.oemid);
--#undef add_env
--      envp[i] = NULL;
--
--      return 0;
--}
--
--static int mmc_bus_suspend(struct device *dev, pm_message_t state)
-+int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs)
- {
--      struct mmc_driver *drv = to_mmc_driver(dev->driver);
--      struct mmc_card *card = dev_to_mmc_card(dev);
--      int ret = 0;
--
--      if (dev->driver && drv->suspend)
--              ret = drv->suspend(card, state);
--      return ret;
--}
-+      int error = 0;
-+      int i;
--static int mmc_bus_resume(struct device *dev)
--{
--      struct mmc_driver *drv = to_mmc_driver(dev->driver);
--      struct mmc_card *card = dev_to_mmc_card(dev);
--      int ret = 0;
--
--      if (dev->driver && drv->resume)
--              ret = drv->resume(card);
--      return ret;
--}
--
--static int mmc_bus_probe(struct device *dev)
--{
--      struct mmc_driver *drv = to_mmc_driver(dev->driver);
--      struct mmc_card *card = dev_to_mmc_card(dev);
--
--      return drv->probe(card);
--}
--
--static int mmc_bus_remove(struct device *dev)
--{
--      struct mmc_driver *drv = to_mmc_driver(dev->driver);
--      struct mmc_card *card = dev_to_mmc_card(dev);
--
--      drv->remove(card);
--
--      return 0;
--}
--
--static struct bus_type mmc_bus_type = {
--      .name           = "mmc",
--      .dev_attrs      = mmc_dev_attrs,
--      .match          = mmc_bus_match,
--      .uevent         = mmc_bus_uevent,
--      .probe          = mmc_bus_probe,
--      .remove         = mmc_bus_remove,
--      .suspend        = mmc_bus_suspend,
--      .resume         = mmc_bus_resume,
--};
--
--/**
-- *    mmc_register_driver - register a media driver
-- *    @drv: MMC media driver
-- */
--int mmc_register_driver(struct mmc_driver *drv)
--{
--      drv->drv.bus = &mmc_bus_type;
--      return driver_register(&drv->drv);
--}
--
--EXPORT_SYMBOL(mmc_register_driver);
--
--/**
-- *    mmc_unregister_driver - unregister a media driver
-- *    @drv: MMC media driver
-- */
--void mmc_unregister_driver(struct mmc_driver *drv)
--{
--      drv->drv.bus = &mmc_bus_type;
--      driver_unregister(&drv->drv);
--}
--
--EXPORT_SYMBOL(mmc_unregister_driver);
--
--
--/*
-- * Internal function.  Initialise a MMC card structure.
-- */
--void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
--{
--      memset(card, 0, sizeof(struct mmc_card));
--      card->host = host;
--      device_initialize(&card->dev);
--      card->dev.parent = mmc_classdev(host);
--      card->dev.bus = &mmc_bus_type;
--      card->dev.release = mmc_release_card;
--}
--
--/*
-- * Internal function.  Register a new MMC card with the driver model.
-- */
--int mmc_register_card(struct mmc_card *card)
--{
--      int ret;
--
--      snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
--               "%s:%04x", mmc_hostname(card->host), card->rca);
--
--      ret = device_add(&card->dev);
--      if (ret == 0) {
--              if (mmc_card_sd(card)) {
--                      ret = device_create_file(&card->dev, &mmc_dev_attr_scr);
--                      if (ret)
--                              device_del(&card->dev);
--              }
-+      for (i = 0; attr_name(attrs[i]); i++) {
-+              error = device_create_file(&card->dev, &attrs[i]);
-+              if (error) {
-+                      while (--i >= 0)
-+                              device_remove_file(&card->dev, &attrs[i]);
-+                      break;
-       }
--      if (ret == 0)
--              mmc_card_set_present(card);
--      return ret;
--}
--
--/*
-- * Internal function.  Unregister a new MMC card with the
-- * driver model, and (eventually) free it.
-- */
--void mmc_remove_card(struct mmc_card *card)
--{
--      if (mmc_card_present(card)) {
--              if (mmc_card_sd(card))
--                      device_remove_file(&card->dev, &mmc_dev_attr_scr);
--
--              device_del(&card->dev);
-       }
--      put_device(&card->dev);
--}
--
--
--static void mmc_host_classdev_release(struct device *dev)
--{
--      struct mmc_host *host = cls_dev_to_mmc_host(dev);
--      kfree(host);
--}
--
--static struct class mmc_host_class = {
--      .name           = "mmc_host",
--      .dev_release    = mmc_host_classdev_release,
--};
--
--static DEFINE_IDR(mmc_host_idr);
--static DEFINE_SPINLOCK(mmc_host_lock);
--
--/*
-- * Internal function. Allocate a new MMC host.
-- */
--struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
--{
--      struct mmc_host *host;
--
--      host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
--      if (host) {
--              memset(host, 0, sizeof(struct mmc_host) + extra);
--
--              host->parent = dev;
--              host->class_dev.parent = dev;
--              host->class_dev.class = &mmc_host_class;
--              device_initialize(&host->class_dev);
--      }
--
--      return host;
--}
--
--/*
-- * Internal function. Register a new MMC host with the MMC class.
-- */
--int mmc_add_host_sysfs(struct mmc_host *host)
--{
--      int err;
--
--      if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
--              return -ENOMEM;
--
--      spin_lock(&mmc_host_lock);
--      err = idr_get_new(&mmc_host_idr, host, &host->index);
--      spin_unlock(&mmc_host_lock);
--      if (err)
--              return err;
--
--      snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
--               "mmc%d", host->index);
--
--      return device_add(&host->class_dev);
--}
--
--/*
-- * Internal function. Unregister a MMC host with the MMC class.
-- */
--void mmc_remove_host_sysfs(struct mmc_host *host)
--{
--      device_del(&host->class_dev);
--
--      spin_lock(&mmc_host_lock);
--      idr_remove(&mmc_host_idr, host->index);
--      spin_unlock(&mmc_host_lock);
-+      return error;
- }
--/*
-- * Internal function. Free a MMC host.
-- */
--void mmc_free_host_sysfs(struct mmc_host *host)
-+void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs)
- {
--      put_device(&host->class_dev);
--}
-+      int i;
--static struct workqueue_struct *workqueue;
--
--/*
-- * Internal function. Schedule delayed work in the MMC work queue.
-- */
--int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)
--{
--      return queue_delayed_work(workqueue, work, delay);
--}
--
--/*
-- * Internal function. Flush all scheduled work from the MMC work queue.
-- */
--void mmc_flush_scheduled_work(void)
--{
--      flush_workqueue(workqueue);
--}
--
--static int __init mmc_init(void)
--{
--      int ret;
--
--      workqueue = create_singlethread_workqueue("kmmcd");
--      if (!workqueue)
--              return -ENOMEM;
--
--      ret = bus_register(&mmc_bus_type);
--      if (ret == 0) {
--              ret = class_register(&mmc_host_class);
--              if (ret)
--                      bus_unregister(&mmc_bus_type);
--      }
--      return ret;
--}
--
--static void __exit mmc_exit(void)
--{
--      class_unregister(&mmc_host_class);
--      bus_unregister(&mmc_bus_type);
--      destroy_workqueue(workqueue);
-+      for (i = 0; attr_name(attrs[i]); i++)
-+              device_remove_file(&card->dev, &attrs[i]);
- }
--module_init(mmc_init);
--module_exit(mmc_exit);
-diff -Nurb linux-2.6.22-570/drivers/mmc/core/sysfs.h linux-2.6.22-590/drivers/mmc/core/sysfs.h
---- linux-2.6.22-570/drivers/mmc/core/sysfs.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/core/sysfs.h  2008-01-02 13:56:37.000000000 -0500
-@@ -11,17 +11,16 @@
- #ifndef _MMC_CORE_SYSFS_H
- #define _MMC_CORE_SYSFS_H
--void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
--int mmc_register_card(struct mmc_card *card);
--void mmc_remove_card(struct mmc_card *card);
-+#define MMC_ATTR_FN(name, fmt, args...)                                       \
-+static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)       \
-+{                                                                     \
-+      struct mmc_card *card = container_of(dev, struct mmc_card, dev);\
-+      return sprintf(buf, fmt, args);                                 \
-+}
--struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
--int mmc_add_host_sysfs(struct mmc_host *host);
--void mmc_remove_host_sysfs(struct mmc_host *host);
--void mmc_free_host_sysfs(struct mmc_host *host);
-+#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
--int mmc_schedule_work(struct work_struct *work);
--int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
--void mmc_flush_scheduled_work(void);
-+int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs);
-+void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs);
- #endif
-diff -Nurb linux-2.6.22-570/drivers/mmc/host/sdhci.c linux-2.6.22-590/drivers/mmc/host/sdhci.c
---- linux-2.6.22-570/drivers/mmc/host/sdhci.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mmc/host/sdhci.c  2008-01-02 13:56:37.000000000 -0500
-@@ -70,6 +70,14 @@
-               .driver_data    = SDHCI_QUIRK_SINGLE_POWER_WRITE,
-       },
-+      {
-+              .vendor         = PCI_VENDOR_ID_ENE,
-+              .device         = PCI_DEVICE_ID_ENE_CB712_SD_2,
-+              .subvendor      = PCI_ANY_ID,
-+              .subdevice      = PCI_ANY_ID,
-+              .driver_data    = SDHCI_QUIRK_SINGLE_POWER_WRITE,
-+      },
-+
-       {       /* Generic SD host controller */
-               PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
-       },
-diff -Nurb linux-2.6.22-570/drivers/mtd/mtd_blkdevs.c linux-2.6.22-590/drivers/mtd/mtd_blkdevs.c
---- linux-2.6.22-570/drivers/mtd/mtd_blkdevs.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mtd/mtd_blkdevs.c 2008-01-02 13:56:37.000000000 -0500
-@@ -16,6 +16,7 @@
- #include <linux/mtd/mtd.h>
- #include <linux/blkdev.h>
- #include <linux/blkpg.h>
-+#include <linux/freezer.h>
- #include <linux/spinlock.h>
- #include <linux/hdreg.h>
- #include <linux/init.h>
-@@ -80,7 +81,7 @@
-       struct request_queue *rq = tr->blkcore_priv->rq;
-       /* we might get involved when memory gets low, so use PF_MEMALLOC */
--      current->flags |= PF_MEMALLOC | PF_NOFREEZE;
-+      current->flags |= PF_MEMALLOC;
-       spin_lock_irq(rq->queue_lock);
-       while (!kthread_should_stop()) {
-diff -Nurb linux-2.6.22-570/drivers/mtd/ubi/wl.c linux-2.6.22-590/drivers/mtd/ubi/wl.c
---- linux-2.6.22-570/drivers/mtd/ubi/wl.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/mtd/ubi/wl.c      2008-01-02 13:56:37.000000000 -0500
-@@ -1346,6 +1346,7 @@
-       ubi_msg("background thread \"%s\" started, PID %d",
-               ubi->bgt_name, current->pid);
-+      set_freezable();
-       for (;;) {
-               int err;
-diff -Nurb linux-2.6.22-570/drivers/net/3c523.c linux-2.6.22-590/drivers/net/3c523.c
---- linux-2.6.22-570/drivers/net/3c523.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/3c523.c       2008-01-02 13:56:37.000000000 -0500
-@@ -990,7 +990,7 @@
-                               if (skb != NULL) {
-                                       skb_reserve(skb, 2);    /* 16 byte alignment */
-                                       skb_put(skb,totlen);
--                                      eth_copy_and_sum(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen,0);
-+                                      skb_copy_to_linear_data(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen);
-                                       skb->protocol = eth_type_trans(skb, dev);
-                                       netif_rx(skb);
-                                       dev->last_rx = jiffies;
-diff -Nurb linux-2.6.22-570/drivers/net/7990.c linux-2.6.22-590/drivers/net/7990.c
---- linux-2.6.22-570/drivers/net/7990.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/7990.c        2008-01-02 13:56:37.000000000 -0500
-@@ -333,9 +333,9 @@
-                         skb_reserve (skb, 2);           /* 16 byte align */
-                         skb_put (skb, len);             /* make room */
--                        eth_copy_and_sum(skb,
-+                        skb_copy_to_linear_data(skb,
-                                          (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
--                                         len, 0);
-+                                         len);
-                         skb->protocol = eth_type_trans (skb, dev);
-                       netif_rx (skb);
-                       dev->last_rx = jiffies;
-diff -Nurb linux-2.6.22-570/drivers/net/8139too.c linux-2.6.22-590/drivers/net/8139too.c
---- linux-2.6.22-570/drivers/net/8139too.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/8139too.c     2008-01-02 13:56:37.000000000 -0500
-@@ -2017,7 +2017,7 @@
- #if RX_BUF_IDX == 3
-                       wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
- #else
--                      eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
-+                      skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size);
- #endif
-                       skb_put (skb, pkt_size);
-diff -Nurb linux-2.6.22-570/drivers/net/Kconfig linux-2.6.22-590/drivers/net/Kconfig
---- linux-2.6.22-570/drivers/net/Kconfig       2008-01-02 13:56:23.000000000 -0500
-+++ linux-2.6.22-590/drivers/net/Kconfig       2008-01-02 13:56:37.000000000 -0500
-@@ -119,6 +119,20 @@
-         If you don't know what to use this for, you don't need it.
-+config ETUN
-+      tristate "Ethernet tunnel device driver support"
-+      depends on SYSFS
-+      ---help---
-+        ETUN provices a pair of network devices that can be used for
-+        configuring interesting topolgies.  What one devices transmits
-+        the other receives and vice versa.  The link level framing
-+        is ethernet for wide compatibility with network stacks.
-+
-+        To compile this driver as a module, choose M here: the module
-+        will be called etun.
-+
-+        If you don't know what to use this for, you don't need it.
-+
- config NET_SB1000
-       tristate "General Instruments Surfboard 1000"
-       depends on PNP
-@@ -2555,6 +2569,18 @@
- source "drivers/s390/net/Kconfig"
-+config XEN_NETDEV_FRONTEND
-+      tristate "Xen network device frontend driver"
-+      depends on XEN
-+      default y
-+      help
-+        The network device frontend driver allows the kernel to
-+        access network devices exported exported by a virtual
-+        machine containing a physical network device driver. The
-+        frontend driver is intended for unprivileged guest domains;
-+        if you are compiling a kernel for a Xen guest, you almost
-+        certainly want to enable this.
-+
- config ISERIES_VETH
-       tristate "iSeries Virtual Ethernet driver support"
-       depends on PPC_ISERIES
-diff -Nurb linux-2.6.22-570/drivers/net/Makefile linux-2.6.22-590/drivers/net/Makefile
---- linux-2.6.22-570/drivers/net/Makefile      2008-01-02 13:56:23.000000000 -0500
-+++ linux-2.6.22-590/drivers/net/Makefile      2008-01-02 13:56:37.000000000 -0500
-@@ -186,6 +186,7 @@
- obj-$(CONFIG_MACMACE) += macmace.o
- obj-$(CONFIG_MAC89x0) += mac89x0.o
- obj-$(CONFIG_TUN) += tun.o
-+obj-$(CONFIG_ETUN) += etun.o
- obj-$(CONFIG_NET_NETX) += netx-eth.o
- obj-$(CONFIG_DL2K) += dl2k.o
- obj-$(CONFIG_R8169) += r8169.o
-@@ -224,7 +225,10 @@
- obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/
- obj-$(CONFIG_NETCONSOLE) += netconsole.o
-+obj-$(CONFIG_KGDBOE) += kgdboe.o
- obj-$(CONFIG_FS_ENET) += fs_enet/
- obj-$(CONFIG_NETXEN_NIC) += netxen/
-+obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
-+
-diff -Nurb linux-2.6.22-570/drivers/net/a2065.c linux-2.6.22-590/drivers/net/a2065.c
---- linux-2.6.22-570/drivers/net/a2065.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/a2065.c       2008-01-02 13:56:37.000000000 -0500
-@@ -322,9 +322,9 @@
-                       skb_reserve (skb, 2);           /* 16 byte align */
-                       skb_put (skb, len);             /* make room */
--                      eth_copy_and_sum(skb,
-+                      skb_copy_to_linear_data(skb,
-                                        (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
--                                       len, 0);
-+                                       len);
-                       skb->protocol = eth_type_trans (skb, dev);
-                       netif_rx (skb);
-                       dev->last_rx = jiffies;
-diff -Nurb linux-2.6.22-570/drivers/net/ariadne.c linux-2.6.22-590/drivers/net/ariadne.c
---- linux-2.6.22-570/drivers/net/ariadne.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/ariadne.c     2008-01-02 13:56:37.000000000 -0500
-@@ -746,7 +746,7 @@
-           skb_reserve(skb,2);         /* 16 byte align */
-           skb_put(skb,pkt_len);       /* Make room */
--          eth_copy_and_sum(skb, (char *)priv->rx_buff[entry], pkt_len,0);
-+          skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry], pkt_len);
-           skb->protocol=eth_type_trans(skb,dev);
- #if 0
-           printk(KERN_DEBUG "RX pkt type 0x%04x from ",
-diff -Nurb linux-2.6.22-570/drivers/net/arm/ep93xx_eth.c linux-2.6.22-590/drivers/net/arm/ep93xx_eth.c
---- linux-2.6.22-570/drivers/net/arm/ep93xx_eth.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/arm/ep93xx_eth.c      2008-01-02 13:56:37.000000000 -0500
-@@ -258,7 +258,7 @@
-                       skb_reserve(skb, 2);
-                       dma_sync_single(NULL, ep->descs->rdesc[entry].buf_addr,
-                                               length, DMA_FROM_DEVICE);
--                      eth_copy_and_sum(skb, ep->rx_buf[entry], length, 0);
-+                      skb_copy_to_linear_data(skb, ep->rx_buf[entry], length);
-                       skb_put(skb, length);
-                       skb->protocol = eth_type_trans(skb, dev);
-diff -Nurb linux-2.6.22-570/drivers/net/au1000_eth.c linux-2.6.22-590/drivers/net/au1000_eth.c
---- linux-2.6.22-570/drivers/net/au1000_eth.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/au1000_eth.c  2008-01-02 13:56:37.000000000 -0500
-@@ -1205,8 +1205,8 @@
-                               continue;
-                       }
-                       skb_reserve(skb, 2);    /* 16 byte IP header align */
--                      eth_copy_and_sum(skb,
--                              (unsigned char *)pDB->vaddr, frmlen, 0);
-+                      skb_copy_to_linear_data(skb,
-+                              (unsigned char *)pDB->vaddr, frmlen);
-                       skb_put(skb, frmlen);
-                       skb->protocol = eth_type_trans(skb, dev);
-                       netif_rx(skb);  /* pass the packet to upper layers */
-diff -Nurb linux-2.6.22-570/drivers/net/bnx2.c linux-2.6.22-590/drivers/net/bnx2.c
---- linux-2.6.22-570/drivers/net/bnx2.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/bnx2.c        2008-01-02 13:56:37.000000000 -0500
-@@ -6490,10 +6490,10 @@
-       memcpy(dev->perm_addr, bp->mac_addr, 6);
-       bp->name = board_info[ent->driver_data].name;
--      if (CHIP_NUM(bp) == CHIP_NUM_5709)
--              dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
--      else
-               dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
-+      if (CHIP_NUM(bp) == CHIP_NUM_5709)
-+              dev->features |= NETIF_F_IPV6_CSUM;
-+
- #ifdef BCM_VLAN
-       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- #endif
-diff -Nurb linux-2.6.22-570/drivers/net/bonding/bond_3ad.c linux-2.6.22-590/drivers/net/bonding/bond_3ad.c
---- linux-2.6.22-570/drivers/net/bonding/bond_3ad.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/bonding/bond_3ad.c    2008-01-02 13:56:37.000000000 -0500
-@@ -29,6 +29,7 @@
- #include <linux/ethtool.h>
- #include <linux/if_bonding.h>
- #include <linux/pkt_sched.h>
-+#include <net/net_namespace.h>
- #include "bonding.h"
- #include "bond_3ad.h"
-@@ -2448,6 +2449,9 @@
-       struct slave *slave = NULL;
-       int ret = NET_RX_DROP;
-+      if (dev->nd_net != &init_net)
-+              goto out;
-+
-       if (!(dev->flags & IFF_MASTER))
-               goto out;
-diff -Nurb linux-2.6.22-570/drivers/net/bonding/bond_alb.c linux-2.6.22-590/drivers/net/bonding/bond_alb.c
---- linux-2.6.22-570/drivers/net/bonding/bond_alb.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/bonding/bond_alb.c    2008-01-02 13:56:37.000000000 -0500
-@@ -345,6 +345,9 @@
-       struct arp_pkt *arp = (struct arp_pkt *)skb->data;
-       int res = NET_RX_DROP;
-+      if (bond_dev->nd_net != &init_net)
-+              goto out;
-+
-       if (!(bond_dev->flags & IFF_MASTER))
-               goto out;
-diff -Nurb linux-2.6.22-570/drivers/net/bonding/bond_main.c linux-2.6.22-590/drivers/net/bonding/bond_main.c
---- linux-2.6.22-570/drivers/net/bonding/bond_main.c   2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/net/bonding/bond_main.c   2008-01-02 13:56:37.000000000 -0500
-@@ -75,6 +75,7 @@
- #include <linux/if_vlan.h>
- #include <linux/if_bonding.h>
- #include <net/route.h>
-+#include <net/net_namespace.h>
- #include "bonding.h"
- #include "bond_3ad.h"
- #include "bond_alb.h"
-@@ -2376,6 +2377,7 @@
-                * can tag the ARP with the proper VLAN tag.
-                */
-               memset(&fl, 0, sizeof(fl));
-+              fl.fl_net = &init_net;
-               fl.fl4_dst = targets[i];
-               fl.fl4_tos = RTO_ONLINK;
-@@ -2485,6 +2487,9 @@
-       unsigned char *arp_ptr;
-       u32 sip, tip;
-+      if (dev->nd_net != &init_net)
-+              goto out;
-+
-       if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
-               goto out;
-@@ -3172,7 +3177,7 @@
- {
-       int len = strlen(DRV_NAME);
--      for (bond_proc_dir = proc_net->subdir; bond_proc_dir;
-+      for (bond_proc_dir = init_net.proc_net->subdir; bond_proc_dir;
-            bond_proc_dir = bond_proc_dir->next) {
-               if ((bond_proc_dir->namelen == len) &&
-                   !memcmp(bond_proc_dir->name, DRV_NAME, len)) {
-@@ -3181,7 +3186,7 @@
-       }
-       if (!bond_proc_dir) {
--              bond_proc_dir = proc_mkdir(DRV_NAME, proc_net);
-+              bond_proc_dir = proc_mkdir(DRV_NAME, init_net.proc_net);
-               if (bond_proc_dir) {
-                       bond_proc_dir->owner = THIS_MODULE;
-               } else {
-@@ -3216,7 +3221,7 @@
-                       bond_proc_dir->owner = NULL;
-               }
-       } else {
--              remove_proc_entry(DRV_NAME, proc_net);
-+              remove_proc_entry(DRV_NAME, init_net.proc_net);
-               bond_proc_dir = NULL;
-       }
- }
-@@ -3323,6 +3328,9 @@
- {
-       struct net_device *event_dev = (struct net_device *)ptr;
-+      if (event_dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       dprintk("event_dev: %s, event: %lx\n",
-               (event_dev ? event_dev->name : "None"),
-               event);
-@@ -3740,7 +3748,7 @@
-       }
-       down_write(&(bonding_rwsem));
--      slave_dev = dev_get_by_name(ifr->ifr_slave);
-+      slave_dev = dev_get_by_name(&init_net, ifr->ifr_slave);
-       dprintk("slave_dev=%p: \n", slave_dev);
-diff -Nurb linux-2.6.22-570/drivers/net/bonding/bond_sysfs.c linux-2.6.22-590/drivers/net/bonding/bond_sysfs.c
---- linux-2.6.22-570/drivers/net/bonding/bond_sysfs.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/bonding/bond_sysfs.c  2008-01-02 13:56:37.000000000 -0500
-@@ -35,6 +35,7 @@
- #include <linux/ctype.h>
- #include <linux/inet.h>
- #include <linux/rtnetlink.h>
-+#include <net/net_namespace.h>
- /* #define BONDING_DEBUG 1 */
- #include "bonding.h"
-@@ -299,7 +300,7 @@
-               read_unlock_bh(&bond->lock);
-               printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n",
-                      bond->dev->name, ifname);
--              dev = dev_get_by_name(ifname);
-+              dev = dev_get_by_name(&init_net, ifname);
-               if (!dev) {
-                       printk(KERN_INFO DRV_NAME
-                              ": %s: Interface %s does not exist!\n",
-diff -Nurb linux-2.6.22-570/drivers/net/dl2k.c linux-2.6.22-590/drivers/net/dl2k.c
---- linux-2.6.22-570/drivers/net/dl2k.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/dl2k.c        2008-01-02 13:56:37.000000000 -0500
-@@ -866,9 +866,9 @@
-                                                           PCI_DMA_FROMDEVICE);
-                               /* 16 byte align the IP header */
-                               skb_reserve (skb, 2);
--                              eth_copy_and_sum (skb,
-+                              skb_copy_to_linear_data (skb,
-                                                 np->rx_skbuff[entry]->data,
--                                                pkt_len, 0);
-+                                                pkt_len);
-                               skb_put (skb, pkt_len);
-                               pci_dma_sync_single_for_device(np->pdev,
-                                                              desc->fraginfo &
-diff -Nurb linux-2.6.22-570/drivers/net/dummy.c linux-2.6.22-590/drivers/net/dummy.c
---- linux-2.6.22-570/drivers/net/dummy.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/dummy.c       2008-01-02 13:56:37.000000000 -0500
-@@ -34,11 +34,17 @@
- #include <linux/etherdevice.h>
- #include <linux/init.h>
- #include <linux/moduleparam.h>
-+#include <linux/rtnetlink.h>
-+#include <net/rtnetlink.h>
-+
-+struct dummy_priv {
-+      struct net_device *dev;
-+      struct list_head list;
-+};
- static int numdummies = 1;
- static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);
--static struct net_device_stats *dummy_get_stats(struct net_device *dev);
- static int dummy_set_address(struct net_device *dev, void *p)
- {
-@@ -56,13 +62,13 @@
- {
- }
--static void __init dummy_setup(struct net_device *dev)
-+static void dummy_setup(struct net_device *dev)
- {
-       /* Initialize the device structure. */
--      dev->get_stats = dummy_get_stats;
-       dev->hard_start_xmit = dummy_xmit;
-       dev->set_multicast_list = set_multicast_list;
-       dev->set_mac_address = dummy_set_address;
-+      dev->destructor = free_netdev;
-       /* Fill in device structure with ethernet-generic values. */
-       ether_setup(dev);
-@@ -76,77 +82,114 @@
- static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
- {
--      struct net_device_stats *stats = netdev_priv(dev);
--
--      stats->tx_packets++;
--      stats->tx_bytes+=skb->len;
-+      dev->stats.tx_packets++;
-+      dev->stats.tx_bytes += skb->len;
-       dev_kfree_skb(skb);
-       return 0;
- }
--static struct net_device_stats *dummy_get_stats(struct net_device *dev)
-+static LIST_HEAD(dummies);
-+
-+static int dummy_newlink(struct net_device *dev,
-+                       struct nlattr *tb[], struct nlattr *data[])
- {
--      return netdev_priv(dev);
-+      struct dummy_priv *priv = netdev_priv(dev);
-+      int err;
-+
-+      err = register_netdevice(dev);
-+      if (err < 0)
-+              return err;
-+
-+      priv->dev = dev;
-+      list_add_tail(&priv->list, &dummies);
-+      return 0;
-+}
-+
-+static void dummy_dellink(struct net_device *dev)
-+{
-+      struct dummy_priv *priv = netdev_priv(dev);
-+
-+      list_del(&priv->list);
-+      unregister_netdevice(dev);
- }
--static struct net_device **dummies;
-+static struct rtnl_link_ops dummy_link_ops __read_mostly = {
-+      .kind           = "dummy",
-+      .priv_size      = sizeof(struct dummy_priv),
-+      .setup          = dummy_setup,
-+      .newlink        = dummy_newlink,
-+      .dellink        = dummy_dellink,
-+};
- /* Number of dummy devices to be set up by this module. */
- module_param(numdummies, int, 0);
- MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
--static int __init dummy_init_one(int index)
-+static int __init dummy_init_one(void)
- {
-       struct net_device *dev_dummy;
-+      struct dummy_priv *priv;
-       int err;
--      dev_dummy = alloc_netdev(sizeof(struct net_device_stats),
--                               "dummy%d", dummy_setup);
-+      dev_dummy = alloc_netdev(sizeof(struct dummy_priv), "dummy%d",
-+                               dummy_setup);
-       if (!dev_dummy)
-               return -ENOMEM;
--      if ((err = register_netdev(dev_dummy))) {
--              free_netdev(dev_dummy);
--              dev_dummy = NULL;
--      } else {
--              dummies[index] = dev_dummy;
--      }
-+      err = dev_alloc_name(dev_dummy, dev_dummy->name);
-+      if (err < 0)
-+              goto err;
-+
-+      dev_dummy->rtnl_link_ops = &dummy_link_ops;
-+      err = register_netdevice(dev_dummy);
-+      if (err < 0)
-+              goto err;
-+
-+      priv = netdev_priv(dev_dummy);
-+      priv->dev = dev_dummy;
-+      list_add_tail(&priv->list, &dummies);
-+      return 0;
-+err:
-+      free_netdev(dev_dummy);
-       return err;
- }
--static void dummy_free_one(int index)
--{
--      unregister_netdev(dummies[index]);
--      free_netdev(dummies[index]);
--}
--
- static int __init dummy_init_module(void)
- {
-+      struct dummy_priv *priv, *next;
-       int i, err = 0;
--      dummies = kmalloc(numdummies * sizeof(void *), GFP_KERNEL);
--      if (!dummies)
--              return -ENOMEM;
-+
-+      rtnl_lock();
-+      err = __rtnl_link_register(&dummy_link_ops);
-+
-       for (i = 0; i < numdummies && !err; i++)
--              err = dummy_init_one(i);
--      if (err) {
--              i--;
--              while (--i >= 0)
--                      dummy_free_one(i);
-+              err = dummy_init_one();
-+      if (err < 0) {
-+              list_for_each_entry_safe(priv, next, &dummies, list)
-+                      dummy_dellink(priv->dev);
-+              __rtnl_link_unregister(&dummy_link_ops);
-       }
-+      rtnl_unlock();
-+
-       return err;
- }
- static void __exit dummy_cleanup_module(void)
- {
--      int i;
--      for (i = 0; i < numdummies; i++)
--              dummy_free_one(i);
--      kfree(dummies);
-+      struct dummy_priv *priv, *next;
-+
-+      rtnl_lock();
-+      list_for_each_entry_safe(priv, next, &dummies, list)
-+              dummy_dellink(priv->dev);
-+
-+      __rtnl_link_unregister(&dummy_link_ops);
-+      rtnl_unlock();
- }
- module_init(dummy_init_module);
- module_exit(dummy_cleanup_module);
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS_RTNL_LINK("dummy");
-diff -Nurb linux-2.6.22-570/drivers/net/eepro100.c linux-2.6.22-590/drivers/net/eepro100.c
---- linux-2.6.22-570/drivers/net/eepro100.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/eepro100.c    2008-01-02 13:56:37.000000000 -0500
-@@ -1801,7 +1801,7 @@
- #if 1 || USE_IP_CSUM
-                               /* Packet is in one chunk -- we can copy + cksum. */
--                              eth_copy_and_sum(skb, sp->rx_skbuff[entry]->data, pkt_len, 0);
-+                              skb_copy_to_linear_data(skb, sp->rx_skbuff[entry]->data, pkt_len);
-                               skb_put(skb, pkt_len);
- #else
-                               skb_copy_from_linear_data(sp->rx_skbuff[entry],
-diff -Nurb linux-2.6.22-570/drivers/net/epic100.c linux-2.6.22-590/drivers/net/epic100.c
---- linux-2.6.22-570/drivers/net/epic100.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/epic100.c     2008-01-02 13:56:37.000000000 -0500
-@@ -1201,7 +1201,7 @@
-                                                           ep->rx_ring[entry].bufaddr,
-                                                           ep->rx_buf_sz,
-                                                           PCI_DMA_FROMDEVICE);
--                              eth_copy_and_sum(skb, ep->rx_skbuff[entry]->data, pkt_len, 0);
-+                              skb_copy_to_linear_data(skb, ep->rx_skbuff[entry]->data, pkt_len);
-                               skb_put(skb, pkt_len);
-                               pci_dma_sync_single_for_device(ep->pci_dev,
-                                                              ep->rx_ring[entry].bufaddr,
-diff -Nurb linux-2.6.22-570/drivers/net/eql.c linux-2.6.22-590/drivers/net/eql.c
---- linux-2.6.22-570/drivers/net/eql.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/eql.c 2008-01-02 13:56:37.000000000 -0500
-@@ -116,6 +116,7 @@
- #include <linux/init.h>
- #include <linux/timer.h>
- #include <linux/netdevice.h>
-+#include <net/net_namespace.h>
- #include <linux/if.h>
- #include <linux/if_arp.h>
-@@ -412,7 +413,7 @@
-       if (copy_from_user(&srq, srqp, sizeof (slaving_request_t)))
-               return -EFAULT;
--      slave_dev  = dev_get_by_name(srq.slave_name);
-+      slave_dev  = dev_get_by_name(&init_net, srq.slave_name);
-       if (slave_dev) {
-               if ((master_dev->flags & IFF_UP) == IFF_UP) {
-                       /* slave is not a master & not already a slave: */
-@@ -460,7 +461,7 @@
-       if (copy_from_user(&srq, srqp, sizeof (slaving_request_t)))
-               return -EFAULT;
--      slave_dev = dev_get_by_name(srq.slave_name);
-+      slave_dev = dev_get_by_name(&init_net, srq.slave_name);
-       ret = -EINVAL;
-       if (slave_dev) {
-               spin_lock_bh(&eql->queue.lock);
-@@ -493,7 +494,7 @@
-       if (copy_from_user(&sc, scp, sizeof (slave_config_t)))
-               return -EFAULT;
--      slave_dev = dev_get_by_name(sc.slave_name);
-+      slave_dev = dev_get_by_name(&init_net, sc.slave_name);
-       if (!slave_dev)
-               return -ENODEV;
-@@ -528,7 +529,7 @@
-       if (copy_from_user(&sc, scp, sizeof (slave_config_t)))
-               return -EFAULT;
--      slave_dev = dev_get_by_name(sc.slave_name);
-+      slave_dev = dev_get_by_name(&init_net, sc.slave_name);
-       if (!slave_dev)
-               return -ENODEV;
-diff -Nurb linux-2.6.22-570/drivers/net/etun.c linux-2.6.22-590/drivers/net/etun.c
---- linux-2.6.22-570/drivers/net/etun.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/net/etun.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,489 @@
-+/*
-+ *  ETUN - Universal ETUN device driver.
-+ *  Copyright (C) 2006 Linux Networx
-+ *
-+ */
-+
-+#define DRV_NAME      "etun"
-+#define DRV_VERSION   "1.0"
-+#define DRV_DESCRIPTION       "Ethernet pseudo tunnel device driver"
-+#define DRV_COPYRIGHT "(C) 2007 Linux Networx"
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/list.h>
-+#include <linux/spinlock.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if.h>
-+#include <linux/if_ether.h>
-+#include <linux/ctype.h>
-+#include <linux/nsproxy.h>
-+#include <net/net_namespace.h>
-+#include <net/dst.h>
-+
-+
-+/* Device cheksum strategy.
-+ *
-+ * etun is designed to a be a pair of virutal devices
-+ * connecting two network stack instances.
-+ *
-+ * Typically it will either be used with ethernet bridging or
-+ * it will be used to route packets between the two stacks.
-+ *
-+ * The only checksum offloading I can do is to completely
-+ * skip the checksumming step all together.
-+ *
-+ * When used for ethernet bridging I don't believe any
-+ * checksum off loading is safe.
-+ * - If my source is an external interface the checksum may be
-+ *   invalid so I don't want to report I have already checked it.
-+ * - If my destination is an external interface I don't want to put
-+ *   a packet on the wire with someone computing the checksum.
-+ *
-+ * When used for routing between two stacks checksums should
-+ * be as unnecessary as they are on the loopback device.
-+ *
-+ * So by default I am safe and disable checksumming and
-+ * other advanced features like SG and TSO.
-+ *
-+ * However because I think these features could be useful
-+ * I provide the ethtool functions to and enable/disable
-+ * them at runtime.
-+ *
-+ * If you think you can correctly enable these go ahead.
-+ * For checksums both the transmitter and the receiver must
-+ * agree before the are actually disabled.
-+ */
-+
-+#define ETUN_NUM_STATS 1
-+static struct {
-+      const char string[ETH_GSTRING_LEN];
-+} ethtool_stats_keys[ETUN_NUM_STATS] = {
-+      { "partner_ifindex" },
-+};
-+
-+struct etun_info {
-+      struct net_device       *rx_dev;
-+      unsigned                ip_summed;
-+      struct net_device_stats stats;
-+      struct list_head        list;
-+      struct net_device       *dev;
-+};
-+
-+/*
-+ * I have to hold the rtnl_lock during device delete.
-+ * So I use the rtnl_lock to protect my list manipulations
-+ * as well.  Crude but simple.
-+ */
-+static LIST_HEAD(etun_list);
-+
-+/*
-+ * The higher levels take care of making this non-reentrant (it's
-+ * called with bh's disabled).
-+ */
-+static int etun_xmit(struct sk_buff *skb, struct net_device *tx_dev)
-+{
-+      struct etun_info *tx_info = tx_dev->priv;
-+      struct net_device *rx_dev = tx_info->rx_dev;
-+      struct etun_info *rx_info = rx_dev->priv;
-+
-+      tx_info->stats.tx_packets++;
-+      tx_info->stats.tx_bytes += skb->len;
-+
-+      /* Drop the skb state that was needed to get here */
-+      skb_orphan(skb);
-+      if (skb->dst)
-+              skb->dst = dst_pop(skb->dst);   /* Allow for smart routing */
-+
-+      /* Switch to the receiving device */
-+      skb->pkt_type = PACKET_HOST;
-+      skb->protocol = eth_type_trans(skb, rx_dev);
-+      skb->dev = rx_dev;
-+      skb->ip_summed = CHECKSUM_NONE;
-+
-+      /* If both halves agree no checksum is needed */
-+      if (tx_dev->features & NETIF_F_NO_CSUM)
-+              skb->ip_summed = rx_info->ip_summed;
-+
-+      rx_dev->last_rx = jiffies;
-+      rx_info->stats.rx_packets++;
-+      rx_info->stats.rx_bytes += skb->len;
-+      netif_rx(skb);
-+
-+      return 0;
-+}
-+
-+static struct net_device_stats *etun_get_stats(struct net_device *dev)
-+{
-+      struct etun_info *info = dev->priv;
-+      return &info->stats;
-+}
-+
-+/* ethtool interface */
-+static int etun_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-+{
-+      cmd->supported          = 0;
-+      cmd->advertising        = 0;
-+      cmd->speed              = SPEED_10000; /* Memory is fast! */
-+      cmd->duplex             = DUPLEX_FULL;
-+      cmd->port               = PORT_TP;
-+      cmd->phy_address        = 0;
-+      cmd->transceiver        = XCVR_INTERNAL;
-+      cmd->autoneg            = AUTONEG_DISABLE;
-+      cmd->maxtxpkt           = 0;
-+      cmd->maxrxpkt           = 0;
-+      return 0;
-+}
-+
-+static void etun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-+{
-+      strcpy(info->driver, DRV_NAME);
-+      strcpy(info->version, DRV_VERSION);
-+      strcpy(info->fw_version, "N/A");
-+}
-+
-+static void etun_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
-+{
-+      switch(stringset) {
-+      case ETH_SS_STATS:
-+              memcpy(buf, &ethtool_stats_keys, sizeof(ethtool_stats_keys));
-+              break;
-+      case ETH_SS_TEST:
-+      default:
-+              break;
-+      }
-+}
-+
-+static int etun_get_stats_count(struct net_device *dev)
-+{
-+      return ETUN_NUM_STATS;
-+}
-+
-+static void etun_get_ethtool_stats(struct net_device *dev,
-+      struct ethtool_stats *stats, u64 *data)
-+{
-+      struct etun_info *info = dev->priv;
-+
-+      data[0] = info->rx_dev->ifindex;
-+}
-+
-+static u32 etun_get_rx_csum(struct net_device *dev)
-+{
-+      struct etun_info *info = dev->priv;
-+      return info->ip_summed == CHECKSUM_UNNECESSARY;
-+}
-+
-+static int etun_set_rx_csum(struct net_device *dev, u32 data)
-+{
-+      struct etun_info *info = dev->priv;
-+
-+      info->ip_summed = data ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
-+
-+      return 0;
-+}
-+
-+static u32 etun_get_tx_csum(struct net_device *dev)
-+{
-+      return (dev->features & NETIF_F_NO_CSUM) != 0;
-+}
-+
-+static int etun_set_tx_csum(struct net_device *dev, u32 data)
-+{
-+      dev->features &= ~NETIF_F_NO_CSUM;
-+      if (data)
-+              dev->features |= NETIF_F_NO_CSUM;
-+
-+      return 0;
-+}
-+
-+static struct ethtool_ops etun_ethtool_ops = {
-+      .get_settings           = etun_get_settings,
-+      .get_drvinfo            = etun_get_drvinfo,
-+      .get_link               = ethtool_op_get_link,
-+      .get_rx_csum            = etun_get_rx_csum,
-+      .set_rx_csum            = etun_set_rx_csum,
-+      .get_tx_csum            = etun_get_tx_csum,
-+      .set_tx_csum            = etun_set_tx_csum,
-+      .get_sg                 = ethtool_op_get_sg,
-+      .set_sg                 = ethtool_op_set_sg,
-+#if 0 /* Does just setting the bit successfuly emulate tso? */
-+      .get_tso                = ethtool_op_get_tso,
-+      .set_tso                = ethtool_op_set_tso,
-+#endif
-+      .get_strings            = etun_get_strings,
-+      .get_stats_count        = etun_get_stats_count,
-+      .get_ethtool_stats      = etun_get_ethtool_stats,
-+      .get_perm_addr          = ethtool_op_get_perm_addr,
-+};
-+
-+static int etun_open(struct net_device *tx_dev)
-+{
-+      struct etun_info *tx_info = tx_dev->priv;
-+      struct net_device *rx_dev = tx_info->rx_dev;
-+      /* If we attempt to bring up etun in the small window before
-+       * it is connected to it's partner error.
-+       */
-+      if (!rx_dev)
-+              return -ENOTCONN;
-+      if (rx_dev->flags & IFF_UP) {
-+              netif_carrier_on(tx_dev);
-+              netif_carrier_on(rx_dev);
-+      }
-+      netif_start_queue(tx_dev);
-+      return 0;
-+}
-+
-+static int etun_stop(struct net_device *tx_dev)
-+{
-+      struct etun_info *tx_info = tx_dev->priv;
-+      struct net_device *rx_dev = tx_info->rx_dev;
-+      netif_stop_queue(tx_dev);
-+      if (netif_carrier_ok(tx_dev)) {
-+              netif_carrier_off(tx_dev);
-+              netif_carrier_off(rx_dev);
-+      }
-+      return 0;
-+}
-+
-+static int etun_change_mtu(struct net_device *dev, int new_mtu)
-+{
-+      /* Don't allow ridiculously small mtus */
-+      if (new_mtu < (ETH_ZLEN - ETH_HLEN))
-+              return -EINVAL;
-+      dev->mtu = new_mtu;
-+      return 0;
-+}
-+
-+static void etun_set_multicast_list(struct net_device *dev)
-+{
-+      /* Nothing sane I can do here */
-+      return;
-+}
-+
-+static int etun_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-+{
-+      return -EOPNOTSUPP;
-+}
-+
-+/* Only allow letters and numbers in an etun device name */
-+static int is_valid_name(const char *name)
-+{
-+      const char *ptr;
-+      for (ptr = name; *ptr; ptr++) {
-+              if (!isalnum(*ptr))
-+                      return 0;
-+      }
-+      return 1;
-+}
-+
-+static struct net_device *etun_alloc(struct net *net, const char *name)
-+{
-+      struct net_device *dev;
-+      struct etun_info *info;
-+      int err;
-+
-+      if (!name || !is_valid_name(name))
-+              return ERR_PTR(-EINVAL);
-+
-+      dev = alloc_netdev(sizeof(struct etun_info), name, ether_setup);
-+      if (!dev)
-+              return ERR_PTR(-ENOMEM);
-+
-+      info = dev->priv;
-+      info->dev = dev;
-+      dev->nd_net = net;
-+
-+      random_ether_addr(dev->dev_addr);
-+      dev->tx_queue_len       = 0; /* A queue is silly for a loopback device */
-+      dev->hard_start_xmit    = etun_xmit;
-+      dev->get_stats          = etun_get_stats;
-+      dev->open               = etun_open;
-+      dev->stop               = etun_stop;
-+      dev->set_multicast_list = etun_set_multicast_list;
-+      dev->do_ioctl           = etun_ioctl;
-+      dev->features           = NETIF_F_FRAGLIST
-+                                | NETIF_F_HIGHDMA
-+                                | NETIF_F_LLTX;
-+      dev->flags              = IFF_BROADCAST | IFF_MULTICAST |IFF_PROMISC;
-+      dev->ethtool_ops        = &etun_ethtool_ops;
-+      dev->destructor         = free_netdev;
-+      dev->change_mtu         = etun_change_mtu;
-+      err = register_netdev(dev);
-+      if (err) {
-+              free_netdev(dev);
-+              dev = ERR_PTR(err);
-+              goto out;
-+      }
-+      netif_carrier_off(dev);
-+out:
-+      return dev;
-+}
-+
-+static int etun_alloc_pair(struct net *net, const char *name0, const char *name1)
-+{
-+      struct net_device *dev0, *dev1;
-+      struct etun_info *info0, *info1;
-+
-+      dev0 = etun_alloc(net, name0);
-+      if (IS_ERR(dev0)) {
-+              return PTR_ERR(dev0);
-+      }
-+      info0 = dev0->priv;
-+
-+      dev1 = etun_alloc(net, name1);
-+      if (IS_ERR(dev1)) {
-+              unregister_netdev(dev0);
-+              return PTR_ERR(dev1);
-+      }
-+      info1 = dev1->priv;
-+
-+      dev_hold(dev0);
-+      dev_hold(dev1);
-+      info0->rx_dev = dev1;
-+      info1->rx_dev = dev0;
-+
-+      /* Only place one member of the pair on the list
-+       * so I don't confuse list_for_each_entry_safe,
-+       * by deleting two list entries at once.
-+       */
-+      rtnl_lock();
-+      list_add(&info0->list, &etun_list);
-+      INIT_LIST_HEAD(&info1->list);
-+      rtnl_unlock();
-+
-+      return 0;
-+}
-+
-+static int etun_unregister_pair(struct net_device *dev0)
-+{
-+      struct etun_info *info0, *info1;
-+      struct net_device *dev1;
-+
-+      ASSERT_RTNL();
-+
-+      if (!dev0)
-+              return -ENODEV;
-+
-+      /* Ensure my network devices are not passing packets */
-+      dev_close(dev0);
-+      info0 = dev0->priv;
-+      dev1  = info0->rx_dev;
-+      info1 = dev1->priv;
-+      dev_close(dev1);
-+
-+      /* Drop the cross device references */
-+      dev_put(dev0);
-+      dev_put(dev1);
-+
-+      /* Remove from the etun list */
-+      if (!list_empty(&info0->list))
-+              list_del_init(&info0->list);
-+      if (!list_empty(&info1->list))
-+              list_del_init(&info1->list);
-+
-+      unregister_netdevice(dev0);
-+      unregister_netdevice(dev1);
-+      return 0;
-+}
-+
-+static int etun_noget(char *buffer, struct kernel_param *kp)
-+{
-+      return 0;
-+}
-+
-+static int etun_newif(const char *val, struct kernel_param *kp)
-+{
-+      char name0[IFNAMSIZ], name1[IFNAMSIZ];
-+      const char *mid;
-+      int len, len0, len1;
-+      if (!capable(CAP_NET_ADMIN))
-+              return -EPERM;
-+
-+      /* Avoid frustration by removing trailing whitespace */
-+      len = strlen(val);
-+      while (isspace(val[len - 1]))
-+              len--;
-+
-+      /* Split the string into 2 names */
-+      mid = memchr(val, ',', len);
-+      if (!mid)
-+              return -EINVAL;
-+
-+      /* Get the first device name */
-+      len0 = mid - val;
-+      if (len0 > sizeof(name0) - 1)
-+              len = sizeof(name0) - 1;
-+      strncpy(name0, val, len0);
-+      name0[len0] = '\0';
-+
-+      /* And the second device name */
-+      len1 = len - (len0 + 1);
-+      if (len1 > sizeof(name1) - 1)
-+              len1 = sizeof(name1) - 1;
-+      strncpy(name1, mid + 1, len1);
-+      name1[len1] = '\0';
-+
-+      return etun_alloc_pair(current->nsproxy->net_ns, name0, name1);
-+}
-+
-+static int etun_delif(const char *val, struct kernel_param *kp)
-+{
-+      char name[IFNAMSIZ];
-+      int len;
-+      struct net_device *dev;
-+      int err;
-+      if (!capable(CAP_NET_ADMIN))
-+              return -EPERM;
-+
-+      /* Avoid frustration by removing trailing whitespace */
-+      len = strlen(val);
-+      while (isspace(val[len - 1]))
-+              len--;
-+
-+      /* Get the device name */
-+      if (len > sizeof(name) - 1)
-+              return -EINVAL;
-+      strncpy(name, val, len);
-+      name[len] = '\0';
-+
-+      /* Double check I don't have strange characters in my device name */
-+      if (!is_valid_name(name))
-+              return -EINVAL;
-+
-+      rtnl_lock();
-+      err = -ENODEV;
-+      dev = __dev_get_by_name(current->nsproxy->net_ns, name);
-+      err = etun_unregister_pair(dev);
-+      rtnl_unlock();
-+      return err;
-+}
-+
-+static int __init etun_init(void)
-+{
-+      printk(KERN_INFO "etun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
-+      printk(KERN_INFO "etun: %s\n", DRV_COPYRIGHT);
-+
-+      return 0;
-+}
-+
-+static void etun_cleanup(void)
-+{
-+      struct etun_info *info, *tmp;
-+      rtnl_lock();
-+      list_for_each_entry_safe(info, tmp, &etun_list, list) {
-+              etun_unregister_pair(info->dev);
-+      }
-+      rtnl_unlock();
-+}
-+
-+module_param_call(newif, etun_newif, etun_noget, NULL, S_IWUSR);
-+module_param_call(delif, etun_delif, etun_noget, NULL, S_IWUSR);
-+module_init(etun_init);
-+module_exit(etun_cleanup);
-+MODULE_DESCRIPTION(DRV_DESCRIPTION);
-+MODULE_AUTHOR("Eric Biederman <ebiederm@xmission.com>");
-+MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/drivers/net/fealnx.c linux-2.6.22-590/drivers/net/fealnx.c
---- linux-2.6.22-570/drivers/net/fealnx.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/fealnx.c      2008-01-02 13:56:37.000000000 -0500
-@@ -1727,8 +1727,8 @@
-                               /* Call copy + cksum if available. */
- #if ! defined(__alpha__)
--                              eth_copy_and_sum(skb,
--                                      np->cur_rx->skbuff->data, pkt_len, 0);
-+                              skb_copy_to_linear_data(skb,
-+                                      np->cur_rx->skbuff->data, pkt_len);
-                               skb_put(skb, pkt_len);
- #else
-                               memcpy(skb_put(skb, pkt_len),
-diff -Nurb linux-2.6.22-570/drivers/net/fec.c linux-2.6.22-590/drivers/net/fec.c
---- linux-2.6.22-570/drivers/net/fec.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/fec.c 2008-01-02 13:56:37.000000000 -0500
-@@ -648,7 +648,7 @@
-               fep->stats.rx_dropped++;
-       } else {
-               skb_put(skb,pkt_len-4); /* Make room */
--              eth_copy_and_sum(skb, data, pkt_len-4, 0);
-+              skb_copy_to_linear_data(skb, data, pkt_len-4);
-               skb->protocol=eth_type_trans(skb,dev);
-               netif_rx(skb);
-       }
-diff -Nurb linux-2.6.22-570/drivers/net/hamachi.c linux-2.6.22-590/drivers/net/hamachi.c
---- linux-2.6.22-570/drivers/net/hamachi.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/hamachi.c     2008-01-02 13:56:37.000000000 -0500
-@@ -1575,8 +1575,8 @@
-                                                           PCI_DMA_FROMDEVICE);
-                               /* Call copy + cksum if available. */
- #if 1 || USE_IP_COPYSUM
--                              eth_copy_and_sum(skb,
--                                      hmp->rx_skbuff[entry]->data, pkt_len, 0);
-+                              skb_copy_to_linear_data(skb,
-+                                      hmp->rx_skbuff[entry]->data, pkt_len);
-                               skb_put(skb, pkt_len);
- #else
-                               memcpy(skb_put(skb, pkt_len), hmp->rx_ring_dma
-diff -Nurb linux-2.6.22-570/drivers/net/hamradio/baycom_epp.c linux-2.6.22-590/drivers/net/hamradio/baycom_epp.c
---- linux-2.6.22-570/drivers/net/hamradio/baycom_epp.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/hamradio/baycom_epp.c 2008-01-02 13:56:37.000000000 -0500
-@@ -320,7 +320,7 @@
-       sprintf(portarg, "%ld", bc->pdev->port->base);
-       printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n", bc_drvname, eppconfig_path, portarg, modearg);
--      return call_usermodehelper(eppconfig_path, argv, envp, 1);
-+      return call_usermodehelper(eppconfig_path, argv, envp, UMH_WAIT_PROC);
- }
- /* ---------------------------------------------------------------------- */
-diff -Nurb linux-2.6.22-570/drivers/net/hamradio/bpqether.c linux-2.6.22-590/drivers/net/hamradio/bpqether.c
---- linux-2.6.22-570/drivers/net/hamradio/bpqether.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/hamradio/bpqether.c   2008-01-02 13:56:37.000000000 -0500
-@@ -83,6 +83,7 @@
- #include <net/ip.h>
- #include <net/arp.h>
-+#include <net/net_namespace.h>
- #include <linux/bpqether.h>
-@@ -172,6 +173,9 @@
-       struct ethhdr *eth;
-       struct bpqdev *bpq;
-+      if (dev->nd_net != &init_net)
-+              goto drop;
-+
-       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
-               return NET_RX_DROP;
-@@ -559,6 +563,9 @@
- {
-       struct net_device *dev = (struct net_device *)ptr;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (!dev_is_ethdev(dev))
-               return NOTIFY_DONE;
-@@ -594,7 +601,7 @@
- static int __init bpq_init_driver(void)
- {
- #ifdef CONFIG_PROC_FS
--      if (!proc_net_fops_create("bpqether", S_IRUGO, &bpq_info_fops)) {
-+      if (!proc_net_fops_create(&init_net, "bpqether", S_IRUGO, &bpq_info_fops)) {
-               printk(KERN_ERR
-                       "bpq: cannot create /proc/net/bpqether entry.\n");
-               return -ENOENT;
-@@ -618,7 +625,7 @@
-       unregister_netdevice_notifier(&bpq_dev_notifier);
--      proc_net_remove("bpqether");
-+      proc_net_remove(&init_net, "bpqether");
-       rtnl_lock();
-       while (!list_empty(&bpq_devices)) {
-diff -Nurb linux-2.6.22-570/drivers/net/hamradio/scc.c linux-2.6.22-590/drivers/net/hamradio/scc.c
---- linux-2.6.22-570/drivers/net/hamradio/scc.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/hamradio/scc.c        2008-01-02 13:56:37.000000000 -0500
-@@ -174,6 +174,7 @@
- #include <linux/seq_file.h>
- #include <linux/bitops.h>
-+#include <net/net_namespace.h>
- #include <net/ax25.h>
- #include <asm/irq.h>
-@@ -2114,7 +2115,7 @@
-       }
-       rtnl_unlock();
--      proc_net_fops_create("z8530drv", 0, &scc_net_seq_fops);
-+      proc_net_fops_create(&init_net, "z8530drv", 0, &scc_net_seq_fops);
-       return 0;
- }
-@@ -2169,7 +2170,7 @@
-       if (Vector_Latch)
-               release_region(Vector_Latch, 1);
--      proc_net_remove("z8530drv");
-+      proc_net_remove(&init_net, "z8530drv");
- }
- MODULE_AUTHOR("Joerg Reuter <jreuter@yaina.de>");
-diff -Nurb linux-2.6.22-570/drivers/net/hamradio/yam.c linux-2.6.22-590/drivers/net/hamradio/yam.c
---- linux-2.6.22-570/drivers/net/hamradio/yam.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/hamradio/yam.c        2008-01-02 13:56:37.000000000 -0500
-@@ -61,6 +61,7 @@
- #include <linux/etherdevice.h>
- #include <linux/skbuff.h>
- #include <net/ax25.h>
-+#include <net/net_namespace.h>
- #include <linux/kernel.h>
- #include <linux/proc_fs.h>
-@@ -1142,7 +1143,7 @@
-       yam_timer.expires = jiffies + HZ / 100;
-       add_timer(&yam_timer);
--      proc_net_fops_create("yam", S_IRUGO, &yam_info_fops);
-+      proc_net_fops_create(&init_net, "yam", S_IRUGO, &yam_info_fops);
-       return 0;
-  error:
-       while (--i >= 0) {
-@@ -1174,7 +1175,7 @@
-               kfree(p);
-       }
--      proc_net_remove("yam");
-+      proc_net_remove(&init_net, "yam");
- }
- /* --------------------------------------------------------------------- */
-diff -Nurb linux-2.6.22-570/drivers/net/ibmveth.c linux-2.6.22-590/drivers/net/ibmveth.c
---- linux-2.6.22-570/drivers/net/ibmveth.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/ibmveth.c     2008-01-02 13:56:37.000000000 -0500
-@@ -47,6 +47,7 @@
- #include <linux/mm.h>
- #include <linux/ethtool.h>
- #include <linux/proc_fs.h>
-+#include <net/net_namespace.h>
- #include <asm/semaphore.h>
- #include <asm/hvcall.h>
- #include <asm/atomic.h>
-@@ -97,7 +98,7 @@
- static struct kobj_type ktype_veth_pool;
- #ifdef CONFIG_PROC_FS
--#define IBMVETH_PROC_DIR "net/ibmveth"
-+#define IBMVETH_PROC_DIR "ibmveth"
- static struct proc_dir_entry *ibmveth_proc_dir;
- #endif
-@@ -1093,7 +1094,7 @@
- #ifdef CONFIG_PROC_FS
- static void ibmveth_proc_register_driver(void)
- {
--      ibmveth_proc_dir = proc_mkdir(IBMVETH_PROC_DIR, NULL);
-+      ibmveth_proc_dir = proc_mkdir(IBMVETH_PROC_DIR, init_net.proc_net);
-       if (ibmveth_proc_dir) {
-               SET_MODULE_OWNER(ibmveth_proc_dir);
-       }
-@@ -1101,7 +1102,7 @@
- static void ibmveth_proc_unregister_driver(void)
- {
--      remove_proc_entry(IBMVETH_PROC_DIR, NULL);
-+      remove_proc_entry(IBMVETH_PROC_DIR, init_net.proc_net);
- }
- static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos)
-@@ -1337,7 +1338,7 @@
- #define ATTR(_name, _mode)      \
-         struct attribute veth_##_name##_attr = {               \
--        .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \
-+        .name = __stringify(_name), .mode = _mode, \
-         };
- static ATTR(active, 0644);
-diff -Nurb linux-2.6.22-570/drivers/net/ifb.c linux-2.6.22-590/drivers/net/ifb.c
---- linux-2.6.22-570/drivers/net/ifb.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/ifb.c 2008-01-02 13:56:37.000000000 -0500
-@@ -33,12 +33,15 @@
- #include <linux/etherdevice.h>
- #include <linux/init.h>
- #include <linux/moduleparam.h>
-+#include <linux/list.h>
- #include <net/pkt_sched.h>
- #define TX_TIMEOUT  (2*HZ)
- #define TX_Q_LIMIT    32
- struct ifb_private {
-+      struct list_head        list;
-+      struct net_device       *dev;
-       struct net_device_stats stats;
-       struct tasklet_struct   ifb_tasklet;
-       int     tasklet_pending;
-@@ -136,13 +139,14 @@
- }
--static void __init ifb_setup(struct net_device *dev)
-+static void ifb_setup(struct net_device *dev)
- {
-       /* Initialize the device structure. */
-       dev->get_stats = ifb_get_stats;
-       dev->hard_start_xmit = ifb_xmit;
-       dev->open = &ifb_open;
-       dev->stop = &ifb_close;
-+      dev->destructor = free_netdev;
-       /* Fill in device structure with ethernet-generic values. */
-       ether_setup(dev);
-@@ -197,7 +201,7 @@
-       return stats;
- }
--static struct net_device **ifbs;
-+static LIST_HEAD(ifbs);
- /* Number of ifb devices to be set up by this module. */
- module_param(numifbs, int, 0);
-@@ -226,9 +230,41 @@
-       return 0;
- }
-+static int ifb_newlink(struct net_device *dev,
-+                     struct nlattr *tb[], struct nlattr *data[])
-+{
-+      struct ifb_private *priv = netdev_priv(dev);
-+      int err;
-+
-+      err = register_netdevice(dev);
-+      if (err < 0)
-+              return err;
-+
-+      priv->dev = dev;
-+      list_add_tail(&priv->list, &ifbs);
-+      return 0;
-+}
-+
-+static void ifb_dellink(struct net_device *dev)
-+{
-+      struct ifb_private *priv = netdev_priv(dev);
-+
-+      list_del(&priv->list);
-+      unregister_netdevice(dev);
-+}
-+
-+static struct rtnl_link_ops ifb_link_ops __read_mostly = {
-+      .kind           = "ifb",
-+      .priv_size      = sizeof(struct ifb_private),
-+      .setup          = ifb_setup,
-+      .newlink        = ifb_newlink,
-+      .dellink        = ifb_dellink,
-+};
-+
- static int __init ifb_init_one(int index)
- {
-       struct net_device *dev_ifb;
-+      struct ifb_private *priv;
-       int err;
-       dev_ifb = alloc_netdev(sizeof(struct ifb_private),
-@@ -237,49 +273,59 @@
-       if (!dev_ifb)
-               return -ENOMEM;
--      if ((err = register_netdev(dev_ifb))) {
--              free_netdev(dev_ifb);
--              dev_ifb = NULL;
--      } else {
--              ifbs[index] = dev_ifb;
--      }
-+      err = dev_alloc_name(dev_ifb, dev_ifb->name);
-+      if (err < 0)
-+              goto err;
-+
-+      dev_ifb->rtnl_link_ops = &ifb_link_ops;
-+      err = register_netdevice(dev_ifb);
-+      if (err < 0)
-+              goto err;
-+
-+      priv = netdev_priv(dev_ifb);
-+      priv->dev = dev_ifb;
-+      list_add_tail(&priv->list, &ifbs);
-+      return 0;
-+err:
-+      free_netdev(dev_ifb);
-       return err;
- }
--static void ifb_free_one(int index)
--{
--      unregister_netdev(ifbs[index]);
--      free_netdev(ifbs[index]);
--}
--
- static int __init ifb_init_module(void)
- {
--      int i, err = 0;
--      ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL);
--      if (!ifbs)
--              return -ENOMEM;
-+      struct ifb_private *priv, *next;
-+      int i, err;
-+
-+      rtnl_lock();
-+      err = __rtnl_link_register(&ifb_link_ops);
-+
-       for (i = 0; i < numifbs && !err; i++)
-               err = ifb_init_one(i);
-       if (err) {
--              i--;
--              while (--i >= 0)
--                      ifb_free_one(i);
-+              list_for_each_entry_safe(priv, next, &ifbs, list)
-+                      ifb_dellink(priv->dev);
-+              __rtnl_link_unregister(&ifb_link_ops);
-       }
-+      rtnl_unlock();
-       return err;
- }
- static void __exit ifb_cleanup_module(void)
- {
--      int i;
-+      struct ifb_private *priv, *next;
-+
-+      rtnl_lock();
-+      list_for_each_entry_safe(priv, next, &ifbs, list)
-+              ifb_dellink(priv->dev);
--      for (i = 0; i < numifbs; i++)
--              ifb_free_one(i);
--      kfree(ifbs);
-+      __rtnl_link_unregister(&ifb_link_ops);
-+      rtnl_unlock();
- }
- module_init(ifb_init_module);
- module_exit(ifb_cleanup_module);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Jamal Hadi Salim");
-+MODULE_ALIAS_RTNL_LINK("ifb");
-diff -Nurb linux-2.6.22-570/drivers/net/ixp2000/ixpdev.c linux-2.6.22-590/drivers/net/ixp2000/ixpdev.c
---- linux-2.6.22-570/drivers/net/ixp2000/ixpdev.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/ixp2000/ixpdev.c      2008-01-02 13:56:37.000000000 -0500
-@@ -111,7 +111,7 @@
-               skb = dev_alloc_skb(desc->pkt_length + 2);
-               if (likely(skb != NULL)) {
-                       skb_reserve(skb, 2);
--                      eth_copy_and_sum(skb, buf, desc->pkt_length, 0);
-+                      skb_copy_to_linear_data(skb, buf, desc->pkt_length);
-                       skb_put(skb, desc->pkt_length);
-                       skb->protocol = eth_type_trans(skb, nds[desc->channel]);
-diff -Nurb linux-2.6.22-570/drivers/net/kgdboe.c linux-2.6.22-590/drivers/net/kgdboe.c
---- linux-2.6.22-570/drivers/net/kgdboe.c      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/net/kgdboe.c      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,294 @@
-+/*
-+ * drivers/net/kgdboe.c
-+ *
-+ * A network interface for GDB.
-+ * Based upon 'gdbserial' by David Grothe <dave@gcom.com>
-+ * and Scott Foehner <sfoehner@engr.sgi.com>
-+ *
-+ * Maintainers: Amit S. Kale <amitkale@linsyssoft.com> and
-+ *            Tom Rini <trini@kernel.crashing.org>
-+ *
-+ * 2004 (c) Amit S. Kale <amitkale@linsyssoft.com>
-+ * 2004-2005 (c) MontaVista Software, Inc.
-+ * 2005 (c) Wind River Systems, Inc.
-+ *
-+ * Contributors at various stages not listed above:
-+ * San Mehat <nettwerk@biodome.org>, Robert Walsh <rjwalsh@durables.org>,
-+ * wangdi <wangdi@clusterfs.com>, Matt Mackall <mpm@selenic.com>,
-+ * Pavel Machek <pavel@suse.cz>, Jason Wessel <jason.wessel@windriver.com>
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program is licensed "as is" without any warranty of any
-+ * kind, whether express or implied.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/interrupt.h>
-+#include <linux/string.h>
-+#include <linux/kgdb.h>
-+#include <linux/netpoll.h>
-+#include <linux/init.h>
-+
-+#include <asm/atomic.h>
-+
-+#define IN_BUF_SIZE 512               /* power of 2, please */
-+#define NOT_CONFIGURED_STRING "not_configured"
-+#define OUT_BUF_SIZE 30               /* We don't want to send too big of a packet. */
-+#define MAX_KGDBOE_CONFIG_STR 256
-+
-+static char in_buf[IN_BUF_SIZE], out_buf[OUT_BUF_SIZE];
-+static int in_head, in_tail, out_count;
-+static atomic_t in_count;
-+/* 0 = unconfigured, 1 = netpoll options parsed, 2 = fully configured. */
-+static int configured;
-+static struct kgdb_io local_kgdb_io_ops;
-+static int use_dynamic_mac;
-+
-+MODULE_DESCRIPTION("KGDB driver for network interfaces");
-+MODULE_LICENSE("GPL");
-+static char config[MAX_KGDBOE_CONFIG_STR] = NOT_CONFIGURED_STRING;
-+static struct kparam_string kps = {
-+      .string = config,
-+      .maxlen = MAX_KGDBOE_CONFIG_STR,
-+};
-+
-+static void rx_hook(struct netpoll *np, int port, char *msg, int len,
-+                  struct sk_buff *skb)
-+{
-+      int i;
-+
-+      np->remote_port = port;
-+
-+      /* Copy the MAC address if we need to. */
-+      if (use_dynamic_mac) {
-+              memcpy(np->remote_mac, eth_hdr(skb)->h_source,
-+                              sizeof(np->remote_mac));
-+              use_dynamic_mac = 0;
-+      }
-+
-+      /*
-+       * This could be GDB trying to attach.  But it could also be GDB
-+       * finishing up a session, with kgdb_connected=0 but GDB sending
-+       * an ACK for the final packet.  To make sure we don't try and
-+       * make a breakpoint when GDB is leaving, make sure that if
-+       * !kgdb_connected the only len == 1 packet we allow is ^C.
-+       */
-+      if (!kgdb_connected && (len != 1 || msg[0] == 3) &&
-+          !atomic_read(&kgdb_setting_breakpoint)) {
-+              tasklet_schedule(&kgdb_tasklet_breakpoint);
-+      }
-+
-+      for (i = 0; i < len; i++) {
-+              if (msg[i] == 3)
-+                      tasklet_schedule(&kgdb_tasklet_breakpoint);
-+
-+              if (atomic_read(&in_count) >= IN_BUF_SIZE) {
-+                      /* buffer overflow, clear it */
-+                      in_head = in_tail = 0;
-+                      atomic_set(&in_count, 0);
-+                      break;
-+              }
-+              in_buf[in_head++] = msg[i];
-+              in_head &= (IN_BUF_SIZE - 1);
-+              atomic_inc(&in_count);
-+      }
-+}
-+
-+static struct netpoll np = {
-+      .dev_name = "eth0",
-+      .name = "kgdboe",
-+      .rx_hook = rx_hook,
-+      .local_port = 6443,
-+      .remote_port = 6442,
-+      .remote_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
-+};
-+
-+static void eth_pre_exception_handler(void)
-+{
-+      /* Increment the module count when the debugger is active */
-+      if (!kgdb_connected)
-+              try_module_get(THIS_MODULE);
-+      netpoll_set_trap(1);
-+}
-+
-+static void eth_post_exception_handler(void)
-+{
-+      /* decrement the module count when the debugger detaches */
-+      if (!kgdb_connected)
-+              module_put(THIS_MODULE);
-+      netpoll_set_trap(0);
-+}
-+
-+static int eth_get_char(void)
-+{
-+      int chr;
-+
-+      while (atomic_read(&in_count) == 0)
-+              netpoll_poll(&np);
-+
-+      chr = in_buf[in_tail++];
-+      in_tail &= (IN_BUF_SIZE - 1);
-+      atomic_dec(&in_count);
-+      return chr;
-+}
-+
-+static void eth_flush_buf(void)
-+{
-+      if (out_count && np.dev) {
-+              netpoll_send_udp(&np, out_buf, out_count);
-+              memset(out_buf, 0, sizeof(out_buf));
-+              out_count = 0;
-+      }
-+}
-+
-+static void eth_put_char(u8 chr)
-+{
-+      out_buf[out_count++] = chr;
-+      if (out_count == OUT_BUF_SIZE)
-+              eth_flush_buf();
-+}
-+
-+static int option_setup(char *opt)
-+{
-+      char opt_scratch[MAX_KGDBOE_CONFIG_STR];
-+
-+      /* If we're being given a new configuration, copy it in. */
-+      if (opt != config)
-+              strcpy(config, opt);
-+      /* But work on a copy as netpoll_parse_options will eat it. */
-+      strcpy(opt_scratch, opt);
-+      configured = !netpoll_parse_options(&np, opt_scratch);
-+
-+      use_dynamic_mac = 1;
-+
-+      return 0;
-+}
-+__setup("kgdboe=", option_setup);
-+
-+/* With our config string set by some means, configure kgdboe. */
-+static int configure_kgdboe(void)
-+{
-+      /* Try out the string. */
-+      option_setup(config);
-+
-+      if (!configured) {
-+              printk(KERN_ERR "kgdboe: configuration incorrect - kgdboe not "
-+                     "loaded.\n");
-+              printk(KERN_ERR "  Usage: kgdboe=[src-port]@[src-ip]/[dev],"
-+                              "[tgt-port]@<tgt-ip>/<tgt-macaddr>\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Bring it up. */
-+      if (netpoll_setup(&np)) {
-+              printk(KERN_ERR "kgdboe: netpoll_setup failed kgdboe failed\n");
-+              return -EINVAL;
-+      }
-+
-+      if (kgdb_register_io_module(&local_kgdb_io_ops)) {
-+              netpoll_cleanup(&np);
-+              return -EINVAL;
-+      }
-+
-+      configured = 2;
-+
-+      return 0;
-+}
-+
-+static int init_kgdboe(void)
-+{
-+      int ret;
-+
-+      /* Already done? */
-+      if (configured == 2)
-+              return 0;
-+
-+      /* OK, go ahead and do it. */
-+      ret = configure_kgdboe();
-+
-+      if (configured == 2)
-+              printk(KERN_INFO "kgdboe: debugging over ethernet enabled\n");
-+
-+      return ret;
-+}
-+
-+static void cleanup_kgdboe(void)
-+{
-+      netpoll_cleanup(&np);
-+      configured = 0;
-+      kgdb_unregister_io_module(&local_kgdb_io_ops);
-+}
-+
-+static int param_set_kgdboe_var(const char *kmessage, struct kernel_param *kp)
-+{
-+      char kmessage_save[MAX_KGDBOE_CONFIG_STR];
-+      int msg_len = strlen(kmessage);
-+
-+      if (msg_len + 1 > MAX_KGDBOE_CONFIG_STR) {
-+              printk(KERN_ERR "%s: string doesn't fit in %u chars.\n",
-+                     kp->name, MAX_KGDBOE_CONFIG_STR - 1);
-+              return -ENOSPC;
-+      }
-+
-+      if (kgdb_connected) {
-+              printk(KERN_ERR "kgdboe: Cannot reconfigure while KGDB is "
-+                              "connected.\n");
-+              return 0;
-+      }
-+
-+      /* Start the reconfiguration process by saving the old string */
-+      strncpy(kmessage_save, config, sizeof(kmessage_save));
-+
-+
-+      /* Copy in the new param and strip out invalid characters so we
-+       * can optionally specify the MAC.
-+       */
-+      strncpy(config, kmessage, sizeof(config));
-+      msg_len--;
-+      while (msg_len > 0 &&
-+                      (config[msg_len] < ',' || config[msg_len] > 'f')) {
-+              config[msg_len] = '\0';
-+              msg_len--;
-+      }
-+
-+      /* Check to see if we are unconfiguring the io module and that it
-+       * was in a fully configured state, as this is the only time that
-+       * netpoll_cleanup should get called
-+       */
-+      if (configured == 2 && strcmp(config, NOT_CONFIGURED_STRING) == 0) {
-+              printk(KERN_INFO "kgdboe: reverting to unconfigured state\n");
-+              cleanup_kgdboe();
-+              return 0;
-+      } else
-+              /* Go and configure with the new params. */
-+              configure_kgdboe();
-+
-+      if (configured == 2)
-+              return 0;
-+
-+      /* If the new string was invalid, revert to the previous state, which
-+       * is at a minimum not_configured. */
-+      strncpy(config, kmessage_save, sizeof(config));
-+      if (strcmp(kmessage_save, NOT_CONFIGURED_STRING) != 0) {
-+              printk(KERN_INFO "kgdboe: reverting to prior configuration\n");
-+              /* revert back to the original config */
-+              strncpy(config, kmessage_save, sizeof(config));
-+              configure_kgdboe();
-+      }
-+      return 0;
-+}
-+
-+static struct kgdb_io local_kgdb_io_ops = {
-+      .read_char = eth_get_char,
-+      .write_char = eth_put_char,
-+      .init = init_kgdboe,
-+      .flush = eth_flush_buf,
-+      .pre_exception = eth_pre_exception_handler,
-+      .post_exception = eth_post_exception_handler
-+};
-+
-+module_init(init_kgdboe);
-+module_exit(cleanup_kgdboe);
-+module_param_call(kgdboe, param_set_kgdboe_var, param_get_string, &kps, 0644);
-+MODULE_PARM_DESC(kgdboe, " kgdboe=[src-port]@[src-ip]/[dev],"
-+               "[tgt-port]@<tgt-ip>/<tgt-macaddr>\n");
-diff -Nurb linux-2.6.22-570/drivers/net/lance.c linux-2.6.22-590/drivers/net/lance.c
---- linux-2.6.22-570/drivers/net/lance.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/lance.c       2008-01-02 13:56:37.000000000 -0500
-@@ -1186,9 +1186,9 @@
-                               }
-                               skb_reserve(skb,2);     /* 16 byte align */
-                               skb_put(skb,pkt_len);   /* Make room */
--                              eth_copy_and_sum(skb,
-+                              skb_copy_to_linear_data(skb,
-                                       (unsigned char *)isa_bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)),
--                                      pkt_len,0);
-+                                      pkt_len);
-                               skb->protocol=eth_type_trans(skb,dev);
-                               netif_rx(skb);
-                               dev->last_rx = jiffies;
-diff -Nurb linux-2.6.22-570/drivers/net/loopback.c linux-2.6.22-590/drivers/net/loopback.c
---- linux-2.6.22-570/drivers/net/loopback.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/loopback.c    2008-01-02 13:56:37.000000000 -0500
-@@ -57,6 +57,7 @@
- #include <linux/ip.h>
- #include <linux/tcp.h>
- #include <linux/percpu.h>
-+#include <net/net_namespace.h>
- struct pcpu_lstats {
-       unsigned long packets;
-@@ -199,39 +200,52 @@
-       .get_rx_csum            = always_on,
- };
-+static int loopback_net_init(struct net *net)
-+{
-+      struct net_device *lo = &net->loopback_dev;
- /*
-  * The loopback device is special. There is only one instance and
-  * it is statically allocated. Don't do this for other devices.
-  */
--struct net_device loopback_dev = {
--      .name                   = "lo",
--      .get_stats              = &get_stats,
--      .mtu                    = (16 * 1024) + 20 + 20 + 12,
--      .hard_start_xmit        = loopback_xmit,
--      .hard_header            = eth_header,
--      .hard_header_cache      = eth_header_cache,
--      .header_cache_update    = eth_header_cache_update,
--      .hard_header_len        = ETH_HLEN,     /* 14   */
--      .addr_len               = ETH_ALEN,     /* 6    */
--      .tx_queue_len           = 0,
--      .type                   = ARPHRD_LOOPBACK,      /* 0x0001*/
--      .rebuild_header         = eth_rebuild_header,
--      .flags                  = IFF_LOOPBACK,
--      .features               = NETIF_F_SG | NETIF_F_FRAGLIST
-+      strcpy(lo->name, "lo");
-+      lo->get_stats           = &get_stats,
-+      lo->mtu                 = (16 * 1024) + 20 + 20 + 12,
-+      lo->hard_start_xmit     = loopback_xmit,
-+      lo->hard_header         = eth_header,
-+      lo->hard_header_cache   = eth_header_cache,
-+      lo->header_cache_update = eth_header_cache_update,
-+      lo->hard_header_len     = ETH_HLEN,     /* 14   */
-+      lo->addr_len            = ETH_ALEN,     /* 6    */
-+      lo->tx_queue_len        = 0,
-+      lo->type                = ARPHRD_LOOPBACK,      /* 0x0001*/
-+      lo->rebuild_header      = eth_rebuild_header,
-+      lo->flags               = IFF_LOOPBACK,
-+      lo->features            = NETIF_F_SG | NETIF_F_FRAGLIST
- #ifdef LOOPBACK_TSO
-                                 | NETIF_F_TSO
- #endif
-                                 | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA
--                                | NETIF_F_LLTX,
--      .ethtool_ops            = &loopback_ethtool_ops,
-+                                | NETIF_F_LLTX
-+                                | NETIF_F_NETNS_LOCAL,
-+      lo->ethtool_ops         = &loopback_ethtool_ops,
-+      lo->nd_net = net;
-+      return register_netdev(lo);
-+}
-+
-+static void loopback_net_exit(struct net *net)
-+{
-+      unregister_netdev(&net->loopback_dev);
-+}
-+
-+static struct pernet_operations loopback_net_ops = {
-+      .init = loopback_net_init,
-+      .exit = loopback_net_exit,
- };
- /* Setup and register the loopback device. */
- static int __init loopback_init(void)
- {
--      return register_netdev(&loopback_dev);
-+      return register_pernet_device(&loopback_net_ops);
- };
- module_init(loopback_init);
--
--EXPORT_SYMBOL(loopback_dev);
-diff -Nurb linux-2.6.22-570/drivers/net/natsemi.c linux-2.6.22-590/drivers/net/natsemi.c
---- linux-2.6.22-570/drivers/net/natsemi.c     2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/net/natsemi.c     2008-01-02 13:56:37.000000000 -0500
-@@ -2357,8 +2357,8 @@
-                                       np->rx_dma[entry],
-                                       buflen,
-                                       PCI_DMA_FROMDEVICE);
--                              eth_copy_and_sum(skb,
--                                      np->rx_skbuff[entry]->data, pkt_len, 0);
-+                              skb_copy_to_linear_data(skb,
-+                                      np->rx_skbuff[entry]->data, pkt_len);
-                               skb_put(skb, pkt_len);
-                               pci_dma_sync_single_for_device(np->pci_dev,
-                                       np->rx_dma[entry],
-diff -Nurb linux-2.6.22-570/drivers/net/ni52.c linux-2.6.22-590/drivers/net/ni52.c
---- linux-2.6.22-570/drivers/net/ni52.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/ni52.c        2008-01-02 13:56:37.000000000 -0500
-@@ -936,7 +936,7 @@
-                                       {
-                                               skb_reserve(skb,2);
-                                               skb_put(skb,totlen);
--                                              eth_copy_and_sum(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen,0);
-+                                              skb_copy_to_linear_data(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen);
-                                               skb->protocol=eth_type_trans(skb,dev);
-                                               netif_rx(skb);
-                                               dev->last_rx = jiffies;
-diff -Nurb linux-2.6.22-570/drivers/net/ni65.c linux-2.6.22-590/drivers/net/ni65.c
---- linux-2.6.22-570/drivers/net/ni65.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/ni65.c        2008-01-02 13:56:37.000000000 -0500
-@@ -1096,7 +1096,7 @@
- #ifdef RCV_VIA_SKB
-                               if( (unsigned long) (skb->data + R_BUF_SIZE) > 0x1000000) {
-                                       skb_put(skb,len);
--                                      eth_copy_and_sum(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len,0);
-+                                      skb_copy_to_linear_data(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len);
-                               }
-                               else {
-                                       struct sk_buff *skb1 = p->recv_skb[p->rmdnum];
-@@ -1108,7 +1108,7 @@
-                               }
- #else
-                               skb_put(skb,len);
--                              eth_copy_and_sum(skb, (unsigned char *) p->recvbounce[p->rmdnum],len,0);
-+                              skb_copy_to_linear_data(skb, (unsigned char *) p->recvbounce[p->rmdnum],len);
- #endif
-                               p->stats.rx_packets++;
-                               p->stats.rx_bytes += len;
-diff -Nurb linux-2.6.22-570/drivers/net/pci-skeleton.c linux-2.6.22-590/drivers/net/pci-skeleton.c
---- linux-2.6.22-570/drivers/net/pci-skeleton.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/pci-skeleton.c        2008-01-02 13:56:37.000000000 -0500
-@@ -1567,7 +1567,7 @@
-               if (skb) {
-                       skb_reserve (skb, 2);   /* 16 byte align the IP fields. */
--                      eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
-+                      skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size);
-                       skb_put (skb, pkt_size);
-                       skb->protocol = eth_type_trans (skb, dev);
-diff -Nurb linux-2.6.22-570/drivers/net/pcnet32.c linux-2.6.22-590/drivers/net/pcnet32.c
---- linux-2.6.22-570/drivers/net/pcnet32.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/pcnet32.c     2008-01-02 13:56:37.000000000 -0500
-@@ -1235,9 +1235,9 @@
-                                           lp->rx_dma_addr[entry],
-                                           pkt_len,
-                                           PCI_DMA_FROMDEVICE);
--              eth_copy_and_sum(skb,
-+              skb_copy_to_linear_data(skb,
-                                (unsigned char *)(lp->rx_skbuff[entry]->data),
--                               pkt_len, 0);
-+                               pkt_len);
-               pci_dma_sync_single_for_device(lp->pci_dev,
-                                              lp->rx_dma_addr[entry],
-                                              pkt_len,
-diff -Nurb linux-2.6.22-570/drivers/net/pppoe.c linux-2.6.22-590/drivers/net/pppoe.c
---- linux-2.6.22-570/drivers/net/pppoe.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/pppoe.c       2008-01-02 13:56:37.000000000 -0500
-@@ -78,6 +78,7 @@
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
-+#include <net/net_namespace.h>
- #include <net/sock.h>
- #include <asm/uaccess.h>
-@@ -210,7 +211,7 @@
-       struct net_device *dev;
-       int ifindex;
--      dev = dev_get_by_name(sp->sa_addr.pppoe.dev);
-+      dev = dev_get_by_name(&init_net, sp->sa_addr.pppoe.dev);
-       if(!dev)
-               return NULL;
-       ifindex = dev->ifindex;
-@@ -295,6 +296,9 @@
- {
-       struct net_device *dev = (struct net_device *) ptr;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       /* Only look at sockets that are using this specific device. */
-       switch (event) {
-       case NETDEV_CHANGEMTU:
-@@ -380,6 +384,9 @@
-       struct pppoe_hdr *ph;
-       struct pppox_sock *po;
-+      if (dev->nd_net != &init_net)
-+              goto drop;
-+
-       if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
-               goto drop;
-@@ -412,6 +419,9 @@
-       struct pppoe_hdr *ph;
-       struct pppox_sock *po;
-+      if (dev->nd_net != &init_net)
-+              goto abort;
-+
-       if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
-               goto abort;
-@@ -471,12 +481,12 @@
-  * Initialize a new struct sock.
-  *
-  **********************************************************************/
--static int pppoe_create(struct socket *sock)
-+static int pppoe_create(struct net *net, struct socket *sock)
- {
-       int error = -ENOMEM;
-       struct sock *sk;
--      sk = sk_alloc(PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto, 1);
-+      sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto, 1);
-       if (!sk)
-               goto out;
-@@ -588,7 +598,7 @@
-       /* Don't re-bind if sid==0 */
-       if (sp->sa_addr.pppoe.sid != 0) {
--              dev = dev_get_by_name(sp->sa_addr.pppoe.dev);
-+              dev = dev_get_by_name(&init_net, sp->sa_addr.pppoe.dev);
-               error = -ENODEV;
-               if (!dev)
-@@ -1064,7 +1074,7 @@
- {
-       struct proc_dir_entry *p;
--      p = create_proc_entry("net/pppoe", S_IRUGO, NULL);
-+      p = create_proc_entry("pppoe", S_IRUGO, init_net.proc_net);
-       if (!p)
-               return -ENOMEM;
-@@ -1135,7 +1145,7 @@
-       dev_remove_pack(&pppoes_ptype);
-       dev_remove_pack(&pppoed_ptype);
-       unregister_netdevice_notifier(&pppoe_notifier);
--      remove_proc_entry("net/pppoe", NULL);
-+      remove_proc_entry("pppoe", init_net.proc_net);
-       proto_unregister(&pppoe_sk_proto);
- }
-diff -Nurb linux-2.6.22-570/drivers/net/pppox.c linux-2.6.22-590/drivers/net/pppox.c
---- linux-2.6.22-570/drivers/net/pppox.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/pppox.c       2008-01-02 13:56:37.000000000 -0500
-@@ -107,10 +107,13 @@
- EXPORT_SYMBOL(pppox_ioctl);
--static int pppox_create(struct socket *sock, int protocol)
-+static int pppox_create(struct net *net, struct socket *sock, int protocol)
- {
-       int rc = -EPROTOTYPE;
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
-+
-       if (protocol < 0 || protocol > PX_MAX_PROTO)
-               goto out;
-@@ -126,7 +129,7 @@
-           !try_module_get(pppox_protos[protocol]->owner))
-               goto out;
--      rc = pppox_protos[protocol]->create(sock);
-+      rc = pppox_protos[protocol]->create(net, sock);
-       module_put(pppox_protos[protocol]->owner);
- out:
-diff -Nurb linux-2.6.22-570/drivers/net/r8169.c linux-2.6.22-590/drivers/net/r8169.c
---- linux-2.6.22-570/drivers/net/r8169.c       2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/net/r8169.c       2008-01-02 13:56:37.000000000 -0500
-@@ -2492,7 +2492,7 @@
-               skb = dev_alloc_skb(pkt_size + align);
-               if (skb) {
-                       skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
--                      eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
-+                      skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
-                       *sk_buff = skb;
-                       rtl8169_mark_to_asic(desc, rx_buf_sz);
-                       ret = 0;
-diff -Nurb linux-2.6.22-570/drivers/net/saa9730.c linux-2.6.22-590/drivers/net/saa9730.c
---- linux-2.6.22-570/drivers/net/saa9730.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/saa9730.c     2008-01-02 13:56:37.000000000 -0500
-@@ -690,9 +690,9 @@
-                               lp->stats.rx_packets++;
-                               skb_reserve(skb, 2);    /* 16 byte align */
-                               skb_put(skb, len);      /* make room */
--                              eth_copy_and_sum(skb,
-+                              skb_copy_to_linear_data(skb,
-                                                (unsigned char *) pData,
--                                               len, 0);
-+                                               len);
-                               skb->protocol = eth_type_trans(skb, dev);
-                               netif_rx(skb);
-                               dev->last_rx = jiffies;
-diff -Nurb linux-2.6.22-570/drivers/net/sgiseeq.c linux-2.6.22-590/drivers/net/sgiseeq.c
---- linux-2.6.22-570/drivers/net/sgiseeq.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/sgiseeq.c     2008-01-02 13:56:37.000000000 -0500
-@@ -320,7 +320,7 @@
-                               skb_put(skb, len);
-                               /* Copy out of kseg1 to avoid silly cache flush. */
--                              eth_copy_and_sum(skb, pkt_pointer + 2, len, 0);
-+                              skb_copy_to_linear_data(skb, pkt_pointer + 2, len);
-                               skb->protocol = eth_type_trans(skb, dev);
-                               /* We don't want to receive our own packets */
-diff -Nurb linux-2.6.22-570/drivers/net/shaper.c linux-2.6.22-590/drivers/net/shaper.c
---- linux-2.6.22-570/drivers/net/shaper.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/shaper.c      2008-01-02 13:56:37.000000000 -0500
-@@ -86,6 +86,7 @@
- #include <net/dst.h>
- #include <net/arp.h>
-+#include <net/net_namespace.h>
- struct shaper_cb {
-       unsigned long   shapeclock;             /* Time it should go out */
-@@ -488,7 +489,7 @@
-       {
-               case SHAPER_SET_DEV:
-               {
--                      struct net_device *them=__dev_get_by_name(ss->ss_name);
-+                      struct net_device *them=__dev_get_by_name(&init_net, ss->ss_name);
-                       if(them==NULL)
-                               return -ENODEV;
-                       if(sh->dev)
-diff -Nurb linux-2.6.22-570/drivers/net/sis190.c linux-2.6.22-590/drivers/net/sis190.c
---- linux-2.6.22-570/drivers/net/sis190.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/sis190.c      2008-01-02 13:56:37.000000000 -0500
-@@ -548,7 +548,7 @@
-               skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
-               if (skb) {
-                       skb_reserve(skb, NET_IP_ALIGN);
--                      eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
-+                      skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
-                       *sk_buff = skb;
-                       sis190_give_to_asic(desc, rx_buf_sz);
-                       ret = 0;
-diff -Nurb linux-2.6.22-570/drivers/net/starfire.c linux-2.6.22-590/drivers/net/starfire.c
---- linux-2.6.22-570/drivers/net/starfire.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/starfire.c    2008-01-02 13:56:37.000000000 -0500
-@@ -1456,7 +1456,7 @@
-                       pci_dma_sync_single_for_cpu(np->pci_dev,
-                                                   np->rx_info[entry].mapping,
-                                                   pkt_len, PCI_DMA_FROMDEVICE);
--                      eth_copy_and_sum(skb, np->rx_info[entry].skb->data, pkt_len, 0);
-+                      skb_copy_to_linear_data(skb, np->rx_info[entry].skb->data, pkt_len);
-                       pci_dma_sync_single_for_device(np->pci_dev,
-                                                      np->rx_info[entry].mapping,
-                                                      pkt_len, PCI_DMA_FROMDEVICE);
-diff -Nurb linux-2.6.22-570/drivers/net/sun3_82586.c linux-2.6.22-590/drivers/net/sun3_82586.c
---- linux-2.6.22-570/drivers/net/sun3_82586.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/sun3_82586.c  2008-01-02 13:56:37.000000000 -0500
-@@ -777,7 +777,7 @@
-                                       {
-                                               skb_reserve(skb,2);
-                                               skb_put(skb,totlen);
--                                              eth_copy_and_sum(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen,0);
-+                                              skb_copy_to_linear_data(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen);
-                                               skb->protocol=eth_type_trans(skb,dev);
-                                               netif_rx(skb);
-                                               p->stats.rx_packets++;
-diff -Nurb linux-2.6.22-570/drivers/net/sun3lance.c linux-2.6.22-590/drivers/net/sun3lance.c
---- linux-2.6.22-570/drivers/net/sun3lance.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/sun3lance.c   2008-01-02 13:56:37.000000000 -0500
-@@ -853,10 +853,9 @@
-                               skb_reserve( skb, 2 );  /* 16 byte align */
-                               skb_put( skb, pkt_len );        /* Make room */
--//                            skb_copy_to_linear_data(skb, PKTBUF_ADDR(head), pkt_len);
--                              eth_copy_and_sum(skb,
-+                              skb_copy_to_linear_data(skb,
-                                                PKTBUF_ADDR(head),
--                                               pkt_len, 0);
-+                                               pkt_len);
-                               skb->protocol = eth_type_trans( skb, dev );
-                               netif_rx( skb );
-diff -Nurb linux-2.6.22-570/drivers/net/sunbmac.c linux-2.6.22-590/drivers/net/sunbmac.c
---- linux-2.6.22-570/drivers/net/sunbmac.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/sunbmac.c     2008-01-02 13:56:37.000000000 -0500
-@@ -860,7 +860,7 @@
-                       sbus_dma_sync_single_for_cpu(bp->bigmac_sdev,
-                                                    this->rx_addr, len,
-                                                    SBUS_DMA_FROMDEVICE);
--                      eth_copy_and_sum(copy_skb, (unsigned char *)skb->data, len, 0);
-+                      skb_copy_to_linear_data(copy_skb, (unsigned char *)skb->data, len);
-                       sbus_dma_sync_single_for_device(bp->bigmac_sdev,
-                                                       this->rx_addr, len,
-                                                       SBUS_DMA_FROMDEVICE);
-diff -Nurb linux-2.6.22-570/drivers/net/sundance.c linux-2.6.22-590/drivers/net/sundance.c
---- linux-2.6.22-570/drivers/net/sundance.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/sundance.c    2008-01-02 13:56:37.000000000 -0500
-@@ -1313,7 +1313,7 @@
-                                                           np->rx_buf_sz,
-                                                           PCI_DMA_FROMDEVICE);
--                              eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0);
-+                              skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
-                               pci_dma_sync_single_for_device(np->pci_dev,
-                                                              desc->frag[0].addr,
-                                                              np->rx_buf_sz,
-diff -Nurb linux-2.6.22-570/drivers/net/sunlance.c linux-2.6.22-590/drivers/net/sunlance.c
---- linux-2.6.22-570/drivers/net/sunlance.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/sunlance.c    2008-01-02 13:56:37.000000000 -0500
-@@ -549,9 +549,9 @@
-                       skb_reserve(skb, 2);            /* 16 byte align */
-                       skb_put(skb, len);              /* make room */
--                      eth_copy_and_sum(skb,
-+                      skb_copy_to_linear_data(skb,
-                                        (unsigned char *)&(ib->rx_buf [entry][0]),
--                                       len, 0);
-+                                       len);
-                       skb->protocol = eth_type_trans(skb, dev);
-                       netif_rx(skb);
-                       dev->last_rx = jiffies;
-diff -Nurb linux-2.6.22-570/drivers/net/sunqe.c linux-2.6.22-590/drivers/net/sunqe.c
---- linux-2.6.22-570/drivers/net/sunqe.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/sunqe.c       2008-01-02 13:56:37.000000000 -0500
-@@ -439,8 +439,8 @@
-                       } else {
-                               skb_reserve(skb, 2);
-                               skb_put(skb, len);
--                              eth_copy_and_sum(skb, (unsigned char *) this_qbuf,
--                                               len, 0);
-+                              skb_copy_to_linear_data(skb, (unsigned char *) this_qbuf,
-+                                               len);
-                               skb->protocol = eth_type_trans(skb, qep->dev);
-                               netif_rx(skb);
-                               qep->dev->last_rx = jiffies;
-diff -Nurb linux-2.6.22-570/drivers/net/tg3.c linux-2.6.22-590/drivers/net/tg3.c
---- linux-2.6.22-570/drivers/net/tg3.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/tg3.c 2008-01-02 13:56:37.000000000 -0500
-@@ -11944,12 +11944,11 @@
-        * checksumming.
-        */
-       if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
-+              dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
--                      dev->features |= NETIF_F_HW_CSUM;
--              else
--                      dev->features |= NETIF_F_IP_CSUM;
--              dev->features |= NETIF_F_SG;
-+                      dev->features |= NETIF_F_IPV6_CSUM;
-+
-               tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
-       } else
-               tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
-diff -Nurb linux-2.6.22-570/drivers/net/tokenring/lanstreamer.c linux-2.6.22-590/drivers/net/tokenring/lanstreamer.c
---- linux-2.6.22-570/drivers/net/tokenring/lanstreamer.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/tokenring/lanstreamer.c       2008-01-02 13:56:37.000000000 -0500
-@@ -250,7 +250,7 @@
- #if STREAMER_NETWORK_MONITOR
- #ifdef CONFIG_PROC_FS
-       if (!dev_streamer)
--              create_proc_read_entry("net/streamer_tr", 0, 0,
-+              create_proc_read_entry("streamer_tr", 0, init_net.proc_net,
-                                       streamer_proc_info, NULL); 
-       streamer_priv->next = dev_streamer;
-       dev_streamer = streamer_priv;
-@@ -423,7 +423,7 @@
-                       }
-               }
-               if (!dev_streamer)
--                      remove_proc_entry("net/streamer_tr", NULL);
-+                      remove_proc_entry("streamer_tr", init_net.proc_net);
-       }
- #endif
- #endif
-diff -Nurb linux-2.6.22-570/drivers/net/tokenring/olympic.c linux-2.6.22-590/drivers/net/tokenring/olympic.c
---- linux-2.6.22-570/drivers/net/tokenring/olympic.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/tokenring/olympic.c   2008-01-02 13:56:37.000000000 -0500
-@@ -101,6 +101,7 @@
- #include <linux/bitops.h>
- #include <linux/jiffies.h>
-+#include <net/net_namespace.h>
- #include <net/checksum.h>
- #include <asm/io.h>
-@@ -268,9 +269,9 @@
-       printk("Olympic: %s registered as: %s\n",olympic_priv->olympic_card_name,dev->name);
-       if (olympic_priv->olympic_network_monitor) { /* Must go after register_netdev as we need the device name */ 
-               char proc_name[20] ; 
--              strcpy(proc_name,"net/olympic_") ; 
-+              strcpy(proc_name,"olympic_") ; 
-               strcat(proc_name,dev->name) ; 
--              create_proc_read_entry(proc_name,0,NULL,olympic_proc_info,(void *)dev) ; 
-+              create_proc_read_entry(proc_name,0,init_net.proc_net,olympic_proc_info,(void *)dev) ; 
-               printk("Olympic: Network Monitor information: /proc/%s\n",proc_name); 
-       }
-       return  0 ;
-@@ -1752,9 +1753,9 @@
-       if (olympic_priv->olympic_network_monitor) { 
-               char proc_name[20] ; 
--              strcpy(proc_name,"net/olympic_") ; 
-+              strcpy(proc_name,"olympic_") ; 
-               strcat(proc_name,dev->name) ;
--              remove_proc_entry(proc_name,NULL); 
-+              remove_proc_entry(proc_name,init_net.proc_net);
-       }
-       unregister_netdev(dev) ; 
-       iounmap(olympic_priv->olympic_mmio) ; 
-diff -Nurb linux-2.6.22-570/drivers/net/tulip/interrupt.c linux-2.6.22-590/drivers/net/tulip/interrupt.c
---- linux-2.6.22-570/drivers/net/tulip/interrupt.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/tulip/interrupt.c     2008-01-02 13:56:37.000000000 -0500
-@@ -197,8 +197,8 @@
-                                                                  tp->rx_buffers[entry].mapping,
-                                                                  pkt_len, PCI_DMA_FROMDEVICE);
- #if ! defined(__alpha__)
--                                       eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
--                                                        pkt_len, 0);
-+                                       skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
-+                                                        pkt_len);
-                                        skb_put(skb, pkt_len);
- #else
-                                        memcpy(skb_put(skb, pkt_len),
-@@ -420,8 +420,8 @@
-                                                           tp->rx_buffers[entry].mapping,
-                                                           pkt_len, PCI_DMA_FROMDEVICE);
- #if ! defined(__alpha__)
--                              eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
--                                               pkt_len, 0);
-+                              skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
-+                                               pkt_len);
-                               skb_put(skb, pkt_len);
- #else
-                               memcpy(skb_put(skb, pkt_len),
-diff -Nurb linux-2.6.22-570/drivers/net/tulip/winbond-840.c linux-2.6.22-590/drivers/net/tulip/winbond-840.c
---- linux-2.6.22-570/drivers/net/tulip/winbond-840.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/tulip/winbond-840.c   2008-01-02 13:56:37.000000000 -0500
-@@ -1232,7 +1232,7 @@
-                               pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry],
-                                                           np->rx_skbuff[entry]->len,
-                                                           PCI_DMA_FROMDEVICE);
--                              eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0);
-+                              skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
-                               skb_put(skb, pkt_len);
-                               pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry],
-                                                              np->rx_skbuff[entry]->len,
-diff -Nurb linux-2.6.22-570/drivers/net/tulip/xircom_cb.c linux-2.6.22-590/drivers/net/tulip/xircom_cb.c
---- linux-2.6.22-570/drivers/net/tulip/xircom_cb.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/tulip/xircom_cb.c     2008-01-02 13:56:37.000000000 -0500
-@@ -1208,7 +1208,7 @@
-                               goto out;
-                       }
-                       skb_reserve(skb, 2);
--                      eth_copy_and_sum(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len, 0);
-+                      skb_copy_to_linear_data(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len);
-                       skb_put(skb, pkt_len);
-                       skb->protocol = eth_type_trans(skb, dev);
-                       netif_rx(skb);
-diff -Nurb linux-2.6.22-570/drivers/net/tulip/xircom_tulip_cb.c linux-2.6.22-590/drivers/net/tulip/xircom_tulip_cb.c
---- linux-2.6.22-570/drivers/net/tulip/xircom_tulip_cb.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/tulip/xircom_tulip_cb.c       2008-01-02 13:56:37.000000000 -0500
-@@ -1242,8 +1242,8 @@
-                               && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
-                               skb_reserve(skb, 2);    /* 16 byte align the IP header */
- #if ! defined(__alpha__)
--                              eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
--                                                               pkt_len, 0);
-+                              skb_copy_to_linear_data(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
-+                                                               pkt_len);
-                               skb_put(skb, pkt_len);
- #else
-                               memcpy(skb_put(skb, pkt_len),
-diff -Nurb linux-2.6.22-570/drivers/net/tun.c linux-2.6.22-590/drivers/net/tun.c
---- linux-2.6.22-570/drivers/net/tun.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/tun.c 2008-01-02 13:56:37.000000000 -0500
-@@ -62,6 +62,7 @@
- #include <linux/if_ether.h>
- #include <linux/if_tun.h>
- #include <linux/crc32.h>
-+#include <net/net_namespace.h>
- #include <asm/system.h>
- #include <asm/uaccess.h>
-@@ -432,6 +433,7 @@
-       init_waitqueue_head(&tun->read_wait);
-       tun->owner = -1;
-+      tun->group = -1;
-       SET_MODULE_OWNER(dev);
-       dev->open = tun_net_open;
-@@ -467,11 +469,14 @@
-                       return -EBUSY;
-               /* Check permissions */
--              if (tun->owner != -1 &&
--                  current->euid != tun->owner && !capable(CAP_NET_ADMIN))
-+              if (((tun->owner != -1 &&
-+                    current->euid != tun->owner) ||
-+                   (tun->group != -1 &&
-+                    current->egid != tun->group)) &&
-+                   !capable(CAP_NET_ADMIN))
-                       return -EPERM;
-       }
--      else if (__dev_get_by_name(ifr->ifr_name))
-+      else if (__dev_get_by_name(&init_net, ifr->ifr_name))
-               return -EINVAL;
-       else {
-               char *name;
-@@ -610,6 +615,13 @@
-               DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner);
-               break;
-+      case TUNSETGROUP:
-+              /* Set group of the device */
-+              tun->group= (gid_t) arg;
-+
-+              DBG(KERN_INFO "%s: group set to %d\n", tun->dev->name, tun->group);
-+              break;
-+
-       case TUNSETLINK:
-               /* Only allow setting the type when the interface is down */
-               if (tun->dev->flags & IFF_UP) {
-diff -Nurb linux-2.6.22-570/drivers/net/typhoon.c linux-2.6.22-590/drivers/net/typhoon.c
---- linux-2.6.22-570/drivers/net/typhoon.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/typhoon.c     2008-01-02 13:56:37.000000000 -0500
-@@ -1703,7 +1703,7 @@
-                       pci_dma_sync_single_for_cpu(tp->pdev, dma_addr,
-                                                   PKT_BUF_SZ,
-                                                   PCI_DMA_FROMDEVICE);
--                      eth_copy_and_sum(new_skb, skb->data, pkt_len, 0);
-+                      skb_copy_to_linear_data(new_skb, skb->data, pkt_len);
-                       pci_dma_sync_single_for_device(tp->pdev, dma_addr,
-                                                      PKT_BUF_SZ,
-                                                      PCI_DMA_FROMDEVICE);
-diff -Nurb linux-2.6.22-570/drivers/net/usb/catc.c linux-2.6.22-590/drivers/net/usb/catc.c
---- linux-2.6.22-570/drivers/net/usb/catc.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/usb/catc.c    2008-01-02 13:56:37.000000000 -0500
-@@ -255,7 +255,7 @@
-               if (!(skb = dev_alloc_skb(pkt_len)))
-                       return;
--              eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
-+              skb_copy_to_linear_data(skb, pkt_start + pkt_offset, pkt_len);
-               skb_put(skb, pkt_len);
-               skb->protocol = eth_type_trans(skb, catc->netdev);
-diff -Nurb linux-2.6.22-570/drivers/net/usb/kaweth.c linux-2.6.22-590/drivers/net/usb/kaweth.c
---- linux-2.6.22-570/drivers/net/usb/kaweth.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/usb/kaweth.c  2008-01-02 13:56:37.000000000 -0500
-@@ -635,7 +635,7 @@
-               skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
--              eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0);
-+              skb_copy_to_linear_data(skb, kaweth->rx_buf + 2, pkt_len);
-               skb_put(skb, pkt_len);
-diff -Nurb linux-2.6.22-570/drivers/net/via-rhine.c linux-2.6.22-590/drivers/net/via-rhine.c
---- linux-2.6.22-570/drivers/net/via-rhine.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/via-rhine.c   2008-01-02 13:56:37.000000000 -0500
-@@ -1492,9 +1492,9 @@
-                                                           rp->rx_buf_sz,
-                                                           PCI_DMA_FROMDEVICE);
--                              eth_copy_and_sum(skb,
-+                              skb_copy_to_linear_data(skb,
-                                                rp->rx_skbuff[entry]->data,
--                                               pkt_len, 0);
-+                                               pkt_len);
-                               skb_put(skb, pkt_len);
-                               pci_dma_sync_single_for_device(rp->pdev,
-                                                              rp->rx_skbuff_dma[entry],
-diff -Nurb linux-2.6.22-570/drivers/net/wan/dlci.c linux-2.6.22-590/drivers/net/wan/dlci.c
---- linux-2.6.22-570/drivers/net/wan/dlci.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/wan/dlci.c    2008-01-02 13:56:37.000000000 -0500
-@@ -361,7 +361,7 @@
-       /* validate slave device */
--      slave = dev_get_by_name(dlci->devname);
-+      slave = dev_get_by_name(&init_net, dlci->devname);
-       if (!slave)
-               return -ENODEV;
-@@ -427,7 +427,7 @@
-       int                     err;
-       /* validate slave device */
--      master = __dev_get_by_name(dlci->devname);
-+      master = __dev_get_by_name(&init_net, dlci->devname);
-       if (!master)
-               return(-ENODEV);
-@@ -513,6 +513,9 @@
- {
-       struct net_device *dev = (struct net_device *) ptr;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (event == NETDEV_UNREGISTER) {
-               struct dlci_local *dlp;
-diff -Nurb linux-2.6.22-570/drivers/net/wan/hdlc.c linux-2.6.22-590/drivers/net/wan/hdlc.c
---- linux-2.6.22-570/drivers/net/wan/hdlc.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/wan/hdlc.c    2008-01-02 13:56:37.000000000 -0500
-@@ -36,6 +36,7 @@
- #include <linux/rtnetlink.h>
- #include <linux/notifier.h>
- #include <linux/hdlc.h>
-+#include <net/net_namespace.h>
- static const char* version = "HDLC support module revision 1.21";
-@@ -66,6 +67,12 @@
-                   struct packet_type *p, struct net_device *orig_dev)
- {
-       struct hdlc_device_desc *desc = dev_to_desc(dev);
-+
-+      if (dev->nd_net != &init_net) {
-+              kfree_skb(skb);
-+              return 0;
-+      }
-+
-       if (desc->netif_rx)
-               return desc->netif_rx(skb);
-@@ -102,6 +109,9 @@
-       unsigned long flags;
-       int on;
-  
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (dev->get_stats != hdlc_get_stats)
-               return NOTIFY_DONE; /* not an HDLC device */
-  
-diff -Nurb linux-2.6.22-570/drivers/net/wan/lapbether.c linux-2.6.22-590/drivers/net/wan/lapbether.c
---- linux-2.6.22-570/drivers/net/wan/lapbether.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/wan/lapbether.c       2008-01-02 13:56:37.000000000 -0500
-@@ -91,6 +91,9 @@
-       int len, err;
-       struct lapbethdev *lapbeth;
-+      if (dev->nd_net != &init_net)
-+              goto drop;
-+
-       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
-               return NET_RX_DROP;
-@@ -391,6 +394,9 @@
-       struct lapbethdev *lapbeth;
-       struct net_device *dev = ptr;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (!dev_is_ethdev(dev))
-               return NOTIFY_DONE;
-diff -Nurb linux-2.6.22-570/drivers/net/wan/sbni.c linux-2.6.22-590/drivers/net/wan/sbni.c
---- linux-2.6.22-570/drivers/net/wan/sbni.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/wan/sbni.c    2008-01-02 13:56:37.000000000 -0500
-@@ -54,6 +54,7 @@
- #include <linux/init.h>
- #include <linux/delay.h>
-+#include <net/net_namespace.h>
- #include <net/arp.h>
- #include <asm/io.h>
-@@ -1362,7 +1363,7 @@
-               if (copy_from_user( slave_name, ifr->ifr_data, sizeof slave_name ))
-                       return -EFAULT;
--              slave_dev = dev_get_by_name( slave_name );
-+              slave_dev = dev_get_by_name(&init_net, slave_name );
-               if( !slave_dev  ||  !(slave_dev->flags & IFF_UP) ) {
-                       printk( KERN_ERR "%s: trying to enslave non-active "
-                               "device %s\n", dev->name, slave_name );
-diff -Nurb linux-2.6.22-570/drivers/net/wan/syncppp.c linux-2.6.22-590/drivers/net/wan/syncppp.c
---- linux-2.6.22-570/drivers/net/wan/syncppp.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/wan/syncppp.c 2008-01-02 13:56:37.000000000 -0500
-@@ -51,6 +51,7 @@
- #include <linux/spinlock.h>
- #include <linux/rcupdate.h>
-+#include <net/net_namespace.h>
- #include <net/syncppp.h>
- #include <asm/byteorder.h>
-@@ -1445,6 +1446,11 @@
- static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev)
- {
-+      if (dev->nd_net != &init_net) {
-+              kfree_skb(skb);
-+              return 0;
-+      }
-+
-       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
-               return NET_RX_DROP;
-       sppp_input(dev,skb);
-diff -Nurb linux-2.6.22-570/drivers/net/wireless/airo.c linux-2.6.22-590/drivers/net/wireless/airo.c
---- linux-2.6.22-570/drivers/net/wireless/airo.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/wireless/airo.c       2008-01-02 13:56:37.000000000 -0500
-@@ -3079,6 +3079,7 @@
-       struct airo_info *ai = dev->priv;
-       int locked;
-       
-+      set_freezable();
-       while(1) {
-               /* make swsusp happy with our thread */
-               try_to_freeze();
-diff -Nurb linux-2.6.22-570/drivers/net/wireless/hostap/hostap_main.c linux-2.6.22-590/drivers/net/wireless/hostap/hostap_main.c
---- linux-2.6.22-570/drivers/net/wireless/hostap/hostap_main.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/wireless/hostap/hostap_main.c 2008-01-02 13:56:37.000000000 -0500
-@@ -24,6 +24,7 @@
- #include <linux/rtnetlink.h>
- #include <linux/wireless.h>
- #include <linux/etherdevice.h>
-+#include <net/net_namespace.h>
- #include <net/iw_handler.h>
- #include <net/ieee80211.h>
- #include <net/ieee80211_crypt.h>
-@@ -1094,8 +1095,8 @@
- static int __init hostap_init(void)
- {
--      if (proc_net != NULL) {
--              hostap_proc = proc_mkdir("hostap", proc_net);
-+      if (init_net.proc_net != NULL) {
-+              hostap_proc = proc_mkdir("hostap", init_net.proc_net);
-               if (!hostap_proc)
-                       printk(KERN_WARNING "Failed to mkdir "
-                              "/proc/net/hostap\n");
-@@ -1110,7 +1111,7 @@
- {
-       if (hostap_proc != NULL) {
-               hostap_proc = NULL;
--              remove_proc_entry("hostap", proc_net);
-+              remove_proc_entry("hostap", init_net.proc_net);
-       }
- }
-diff -Nurb linux-2.6.22-570/drivers/net/wireless/libertas/main.c linux-2.6.22-590/drivers/net/wireless/libertas/main.c
---- linux-2.6.22-570/drivers/net/wireless/libertas/main.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/wireless/libertas/main.c      2008-01-02 13:56:37.000000000 -0500
-@@ -613,6 +613,7 @@
-       init_waitqueue_entry(&wait, current);
-+      set_freezable();
-       for (;;) {
-               lbs_deb_thread( "main-thread 111: intcounter=%d "
-                      "currenttxskb=%p dnld_sent=%d\n",
-diff -Nurb linux-2.6.22-570/drivers/net/wireless/strip.c linux-2.6.22-590/drivers/net/wireless/strip.c
---- linux-2.6.22-570/drivers/net/wireless/strip.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/wireless/strip.c      2008-01-02 13:56:37.000000000 -0500
-@@ -107,6 +107,7 @@
- #include <linux/serialP.h>
- #include <linux/rcupdate.h>
- #include <net/arp.h>
-+#include <net/net_namespace.h>
- #include <linux/ip.h>
- #include <linux/tcp.h>
-@@ -1971,7 +1972,7 @@
-                     sizeof(zero_address))) {
-               struct net_device *dev;
-               read_lock_bh(&dev_base_lock);
--              for_each_netdev(dev) {
-+              for_each_netdev(&init_net, dev) {
-                       if (dev->type == strip_info->dev->type &&
-                           !memcmp(dev->dev_addr,
-                                   &strip_info->true_dev_addr,
-@@ -2787,7 +2788,7 @@
-       /*
-        * Register the status file with /proc
-        */
--      proc_net_fops_create("strip", S_IFREG | S_IRUGO, &strip_seq_fops);
-+      proc_net_fops_create(&init_net, "strip", S_IFREG | S_IRUGO, &strip_seq_fops);
-       return status;
- }
-@@ -2809,7 +2810,7 @@
-       }
-       /* Unregister with the /proc/net file here. */
--      proc_net_remove("strip");
-+      proc_net_remove(&init_net, "strip");
-       if ((i = tty_unregister_ldisc(N_STRIP)))
-               printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i);
-diff -Nurb linux-2.6.22-570/drivers/net/wireless/wl3501_cs.c linux-2.6.22-590/drivers/net/wireless/wl3501_cs.c
---- linux-2.6.22-570/drivers/net/wireless/wl3501_cs.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/wireless/wl3501_cs.c  2008-01-02 13:56:37.000000000 -0500
-@@ -1011,7 +1011,7 @@
-       } else {
-               skb->dev = dev;
-               skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */
--              eth_copy_and_sum(skb, (unsigned char *)&sig.daddr, 12, 0);
-+              skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12);
-               wl3501_receive(this, skb->data, pkt_len);
-               skb_put(skb, pkt_len);
-               skb->protocol   = eth_type_trans(skb, dev);
-diff -Nurb linux-2.6.22-570/drivers/net/xen-netfront.c linux-2.6.22-590/drivers/net/xen-netfront.c
---- linux-2.6.22-570/drivers/net/xen-netfront.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/net/xen-netfront.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,1995 @@
-+/*
-+ * Virtual network driver for conversing with remote driver backends.
-+ *
-+ * Copyright (c) 2002-2005, K A Fraser
-+ * Copyright (c) 2005, XenSource Ltd
-+ *
-+ * 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; or, when distributed
-+ * separately from the Linux kernel or incorporated into other
-+ * software packages, subject to the following license:
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this source file (the "Software"), to deal in the Software without
-+ * restriction, including without limitation the rights to use, copy, modify,
-+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
-+ * and to permit persons to whom the Software is furnished to do so, subject to
-+ * the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#include <linux/ethtool.h>
-+#include <linux/if_ether.h>
-+#include <linux/tcp.h>
-+#include <linux/udp.h>
-+#include <linux/moduleparam.h>
-+#include <linux/mm.h>
-+#include <net/ip.h>
-+
-+#include <xen/xenbus.h>
-+#include <xen/events.h>
-+#include <xen/page.h>
-+#include <xen/grant_table.h>
-+
-+#include <xen/interface/io/netif.h>
-+#include <xen/interface/memory.h>
-+#include <xen/interface/grant_table.h>
-+
-+static struct ethtool_ops xennet_ethtool_ops;
-+
-+struct netfront_cb {
-+      struct page *page;
-+      unsigned offset;
-+};
-+
-+#define NETFRONT_SKB_CB(skb)  ((struct netfront_cb *)((skb)->cb))
-+
-+/*
-+ * Mutually-exclusive module options to select receive data path:
-+ *  copy : Packets are copied by network backend into local memory
-+ *  flip : Page containing packet data is transferred to our ownership
-+ * For fully-virtualised guests there is no option - copying must be used.
-+ * For paravirtualised guests, flipping is the default.
-+ */
-+typedef enum rx_mode {
-+      RX_COPY = 0,
-+      RX_FLIP = 1,
-+} rx_mode_t;
-+
-+static enum rx_mode rx_mode = RX_FLIP;
-+
-+#define param_check_rx_mode_t(name, p) __param_check(name, p, rx_mode_t)
-+
-+static int param_set_rx_mode_t(const char *val, struct kernel_param *kp)
-+{
-+      enum rx_mode *rxmp = kp->arg;
-+      int ret = 0;
-+
-+      if (strcmp(val, "copy") == 0)
-+              *rxmp = RX_COPY;
-+      else if (strcmp(val, "flip") == 0)
-+              *rxmp = RX_FLIP;
-+      else
-+              ret = -EINVAL;
-+
-+      return ret;
-+}
-+
-+static int param_get_rx_mode_t(char *buffer, struct kernel_param *kp)
-+{
-+      enum rx_mode *rxmp = kp->arg;
-+
-+      return sprintf(buffer, "%s", *rxmp == RX_COPY ? "copy" : "flip");
-+}
-+
-+MODULE_PARM_DESC(rx_mode, "How to get packets from card: \"copy\" or \"flip\"");
-+module_param(rx_mode, rx_mode_t, 0400);
-+
-+#define RX_COPY_THRESHOLD 256
-+
-+#define GRANT_INVALID_REF     0
-+
-+#define NET_TX_RING_SIZE __RING_SIZE((struct xen_netif_tx_sring *)0, PAGE_SIZE)
-+#define NET_RX_RING_SIZE __RING_SIZE((struct xen_netif_rx_sring *)0, PAGE_SIZE)
-+#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
-+
-+struct netfront_info {
-+      struct list_head list;
-+      struct net_device *netdev;
-+
-+      struct net_device_stats stats;
-+
-+      struct xen_netif_tx_front_ring tx;
-+      struct xen_netif_rx_front_ring rx;
-+
-+      spinlock_t   tx_lock;
-+      spinlock_t   rx_lock;
-+
-+      unsigned int evtchn;
-+      unsigned int copying_receiver;
-+
-+      /* Receive-ring batched refills. */
-+#define RX_MIN_TARGET 8
-+#define RX_DFL_MIN_TARGET 64
-+#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
-+      unsigned rx_min_target, rx_max_target, rx_target;
-+      struct sk_buff_head rx_batch;
-+
-+      struct timer_list rx_refill_timer;
-+
-+      /*
-+       * {tx,rx}_skbs store outstanding skbuffs. Free tx_skb entries
-+       * are linked from tx_skb_freelist through skb_entry.link.
-+       *
-+       *  NB. Freelist index entries are always going to be less than
-+       *  PAGE_OFFSET, whereas pointers to skbs will always be equal or
-+       *  greater than PAGE_OFFSET: we use this property to distinguish
-+       *  them.
-+       */
-+      union skb_entry {
-+              struct sk_buff *skb;
-+              unsigned link;
-+      } tx_skbs[NET_TX_RING_SIZE];;
-+      grant_ref_t gref_tx_head;
-+      grant_ref_t grant_tx_ref[NET_TX_RING_SIZE];
-+      unsigned tx_skb_freelist;
-+
-+      struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
-+      grant_ref_t gref_rx_head;
-+      grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
-+
-+      struct xenbus_device *xbdev;
-+      int tx_ring_ref;
-+      int rx_ring_ref;
-+
-+      unsigned long rx_pfn_array[NET_RX_RING_SIZE];
-+      struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1];
-+      struct mmu_update rx_mmu[NET_RX_RING_SIZE];
-+};
-+
-+struct netfront_rx_info {
-+      struct xen_netif_rx_response rx;
-+      struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
-+};
-+
-+/*
-+ * Access macros for acquiring freeing slots in tx_skbs[].
-+ */
-+
-+static void add_id_to_freelist(unsigned *head, union skb_entry *list, unsigned short id)
-+{
-+      list[id].link = *head;
-+      *head = id;
-+}
-+
-+static unsigned short get_id_from_freelist(unsigned *head, union skb_entry *list)
-+{
-+      unsigned int id = *head;
-+      *head = list[id].link;
-+      return id;
-+}
-+
-+static int xennet_rxidx(RING_IDX idx)
-+{
-+      return idx & (NET_RX_RING_SIZE - 1);
-+}
-+
-+static struct sk_buff *xennet_get_rx_skb(struct netfront_info *np,
-+                                       RING_IDX ri)
-+{
-+      int i = xennet_rxidx(ri);
-+      struct sk_buff *skb = np->rx_skbs[i];
-+      np->rx_skbs[i] = NULL;
-+      return skb;
-+}
-+
-+static grant_ref_t xennet_get_rx_ref(struct netfront_info *np,
-+                                          RING_IDX ri)
-+{
-+      int i = xennet_rxidx(ri);
-+      grant_ref_t ref = np->grant_rx_ref[i];
-+      np->grant_rx_ref[i] = GRANT_INVALID_REF;
-+      return ref;
-+}
-+
-+#ifdef CONFIG_SYSFS
-+static int xennet_sysfs_addif(struct net_device *netdev);
-+static void xennet_sysfs_delif(struct net_device *netdev);
-+#else /* !CONFIG_SYSFS */
-+#define xennet_sysfs_addif(dev) (0)
-+#define xennet_sysfs_delif(dev) do { } while(0)
-+#endif
-+
-+static int xennet_can_sg(struct net_device *dev)
-+{
-+      return dev->features & NETIF_F_SG;
-+}
-+
-+
-+static void rx_refill_timeout(unsigned long data)
-+{
-+      struct net_device *dev = (struct net_device *)data;
-+      netif_rx_schedule(dev);
-+}
-+
-+static int netfront_tx_slot_available(struct netfront_info *np)
-+{
-+      return ((np->tx.req_prod_pvt - np->tx.rsp_cons) <
-+              (TX_MAX_TARGET - MAX_SKB_FRAGS - 2));
-+}
-+
-+static void xennet_maybe_wake_tx(struct net_device *dev)
-+{
-+      struct netfront_info *np = netdev_priv(dev);
-+
-+      if (unlikely(netif_queue_stopped(dev)) &&
-+          netfront_tx_slot_available(np) &&
-+          likely(netif_running(dev)))
-+              netif_wake_queue(dev);
-+}
-+
-+static void xennet_alloc_rx_buffers(struct net_device *dev)
-+{
-+      unsigned short id;
-+      struct netfront_info *np = netdev_priv(dev);
-+      struct sk_buff *skb;
-+      struct page *page;
-+      int i, batch_target, notify;
-+      RING_IDX req_prod = np->rx.req_prod_pvt;
-+      struct xen_memory_reservation reservation;
-+      grant_ref_t ref;
-+      unsigned long pfn;
-+      void *vaddr;
-+      int nr_flips;
-+      struct xen_netif_rx_request *req;
-+
-+      if (unlikely(!netif_carrier_ok(dev)))
-+              return;
-+
-+      /*
-+       * Allocate skbuffs greedily, even though we batch updates to the
-+       * receive ring. This creates a less bursty demand on the memory
-+       * allocator, so should reduce the chance of failed allocation requests
-+       * both for ourself and for other kernel subsystems.
-+       */
-+      batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
-+      for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
-+              skb = __netdev_alloc_skb(dev, RX_COPY_THRESHOLD,
-+                                       GFP_ATOMIC | __GFP_NOWARN);
-+              if (unlikely(!skb))
-+                      goto no_skb;
-+
-+              page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
-+              if (!page) {
-+                      kfree_skb(skb);
-+no_skb:
-+                      /* Any skbuffs queued for refill? Force them out. */
-+                      if (i != 0)
-+                              goto refill;
-+                      /* Could not allocate any skbuffs. Try again later. */
-+                      mod_timer(&np->rx_refill_timer,
-+                                jiffies + (HZ/10));
-+                      break;
-+              }
-+
-+              skb_shinfo(skb)->frags[0].page = page;
-+              skb_shinfo(skb)->nr_frags = 1;
-+              __skb_queue_tail(&np->rx_batch, skb);
-+      }
-+
-+      /* Is the batch large enough to be worthwhile? */
-+      if (i < (np->rx_target/2)) {
-+              if (req_prod > np->rx.sring->req_prod)
-+                      goto push;
-+              return;
-+      }
-+
-+      /* Adjust our fill target if we risked running out of buffers. */
-+      if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) &&
-+          ((np->rx_target *= 2) > np->rx_max_target))
-+              np->rx_target = np->rx_max_target;
-+
-+ refill:
-+      for (nr_flips = i = 0; ; i++) {
-+              if ((skb = __skb_dequeue(&np->rx_batch)) == NULL)
-+                      break;
-+
-+              skb->dev = dev;
-+
-+              id = xennet_rxidx(req_prod + i);
-+
-+              BUG_ON(np->rx_skbs[id]);
-+              np->rx_skbs[id] = skb;
-+
-+              ref = gnttab_claim_grant_reference(&np->gref_rx_head);
-+              BUG_ON((signed short)ref < 0);
-+              np->grant_rx_ref[id] = ref;
-+
-+              pfn = page_to_pfn(skb_shinfo(skb)->frags[0].page);
-+              vaddr = page_address(skb_shinfo(skb)->frags[0].page);
-+
-+              req = RING_GET_REQUEST(&np->rx, req_prod + i);
-+              if (!np->copying_receiver) {
-+                      gnttab_grant_foreign_transfer_ref(ref,
-+                                                        np->xbdev->otherend_id,
-+                                                        pfn);
-+                      np->rx_pfn_array[nr_flips] = pfn_to_mfn(pfn);
-+                      if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-+                              /* Remove this page before passing
-+                               * back to Xen. */
-+                              set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
-+                              MULTI_update_va_mapping(np->rx_mcl+i,
-+                                                      (unsigned long)vaddr,
-+                                                      __pte(0), 0);
-+                      }
-+                      nr_flips++;
-+              } else {
-+                      gnttab_grant_foreign_access_ref(ref,
-+                                                      np->xbdev->otherend_id,
-+                                                      pfn_to_mfn(pfn),
-+                                                      0);
-+              }
-+
-+              req->id = id;
-+              req->gref = ref;
-+      }
-+
-+      if (nr_flips != 0) {
-+              reservation.extent_start = np->rx_pfn_array;
-+              reservation.nr_extents   = nr_flips;
-+              reservation.extent_order = 0;
-+              reservation.address_bits = 0;
-+              reservation.domid        = DOMID_SELF;
-+
-+              if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-+                      /* After all PTEs have been zapped, flush the TLB. */
-+                      np->rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] =
-+                              UVMF_TLB_FLUSH|UVMF_ALL;
-+
-+                      /* Give away a batch of pages. */
-+                      np->rx_mcl[i].op = __HYPERVISOR_memory_op;
-+                      np->rx_mcl[i].args[0] = XENMEM_decrease_reservation;
-+                      np->rx_mcl[i].args[1] = (unsigned long)&reservation;
-+
-+                      /* Zap PTEs and give away pages in one big
-+                       * multicall. */
-+                      (void)HYPERVISOR_multicall(np->rx_mcl, i+1);
-+
-+                      /* Check return status of HYPERVISOR_memory_op(). */
-+                      if (unlikely(np->rx_mcl[i].result != i))
-+                              panic("Unable to reduce memory reservation\n");
-+              } else {
-+                      if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
-+                                               &reservation) != i)
-+                              panic("Unable to reduce memory reservation\n");
-+              }
-+      } else {
-+              wmb();
-+      }
-+
-+      /* Above is a suitable barrier to ensure backend will see requests. */
-+      np->rx.req_prod_pvt = req_prod + i;
-+ push:
-+      RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
-+      if (notify)
-+              notify_remote_via_irq(np->netdev->irq);
-+}
-+
-+static int xennet_open(struct net_device *dev)
-+{
-+      struct netfront_info *np = netdev_priv(dev);
-+
-+      memset(&np->stats, 0, sizeof(np->stats));
-+
-+      spin_lock_bh(&np->rx_lock);
-+      if (netif_carrier_ok(dev)) {
-+              xennet_alloc_rx_buffers(dev);
-+              np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
-+              if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
-+                      netif_rx_schedule(dev);
-+      }
-+      spin_unlock_bh(&np->rx_lock);
-+
-+      xennet_maybe_wake_tx(dev);
-+
-+      return 0;
-+}
-+
-+static void xennet_tx_buf_gc(struct net_device *dev)
-+{
-+      RING_IDX cons, prod;
-+      unsigned short id;
-+      struct netfront_info *np = netdev_priv(dev);
-+      struct sk_buff *skb;
-+
-+      BUG_ON(!netif_carrier_ok(dev));
-+
-+      do {
-+              prod = np->tx.sring->rsp_prod;
-+              rmb(); /* Ensure we see responses up to 'rp'. */
-+
-+              for (cons = np->tx.rsp_cons; cons != prod; cons++) {
-+                      struct xen_netif_tx_response *txrsp;
-+
-+                      txrsp = RING_GET_RESPONSE(&np->tx, cons);
-+                      if (txrsp->status == NETIF_RSP_NULL)
-+                              continue;
-+
-+                      id  = txrsp->id;
-+                      skb = np->tx_skbs[id].skb;
-+                      if (unlikely(gnttab_query_foreign_access(
-+                              np->grant_tx_ref[id]) != 0)) {
-+                              printk(KERN_ALERT "xennet_tx_buf_gc: warning "
-+                                     "-- grant still in use by backend "
-+                                     "domain.\n");
-+                              BUG();
-+                      }
-+                      gnttab_end_foreign_access_ref(
-+                              np->grant_tx_ref[id], GNTMAP_readonly);
-+                      gnttab_release_grant_reference(
-+                              &np->gref_tx_head, np->grant_tx_ref[id]);
-+                      np->grant_tx_ref[id] = GRANT_INVALID_REF;
-+                      add_id_to_freelist(&np->tx_skb_freelist, np->tx_skbs, id);
-+                      dev_kfree_skb_irq(skb);
-+              }
-+
-+              np->tx.rsp_cons = prod;
-+
-+              /*
-+               * Set a new event, then check for race with update of tx_cons.
-+               * Note that it is essential to schedule a callback, no matter
-+               * how few buffers are pending. Even if there is space in the
-+               * transmit ring, higher layers may be blocked because too much
-+               * data is outstanding: in such cases notification from Xen is
-+               * likely to be the only kick that we'll get.
-+               */
-+              np->tx.sring->rsp_event =
-+                      prod + ((np->tx.sring->req_prod - prod) >> 1) + 1;
-+              mb();
-+      } while ((cons == prod) && (prod != np->tx.sring->rsp_prod));
-+
-+      xennet_maybe_wake_tx(dev);
-+}
-+
-+static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
-+                            struct xen_netif_tx_request *tx)
-+{
-+      struct netfront_info *np = netdev_priv(dev);
-+      char *data = skb->data;
-+      unsigned long mfn;
-+      RING_IDX prod = np->tx.req_prod_pvt;
-+      int frags = skb_shinfo(skb)->nr_frags;
-+      unsigned int offset = offset_in_page(data);
-+      unsigned int len = skb_headlen(skb);
-+      unsigned int id;
-+      grant_ref_t ref;
-+      int i;
-+
-+      /* While the header overlaps a page boundary (including being
-+         larger than a page), split it it into page-sized chunks. */
-+      while (len > PAGE_SIZE - offset) {
-+              tx->size = PAGE_SIZE - offset;
-+              tx->flags |= NETTXF_more_data;
-+              len -= tx->size;
-+              data += tx->size;
-+              offset = 0;
-+
-+              id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
-+              np->tx_skbs[id].skb = skb_get(skb);
-+              tx = RING_GET_REQUEST(&np->tx, prod++);
-+              tx->id = id;
-+              ref = gnttab_claim_grant_reference(&np->gref_tx_head);
-+              BUG_ON((signed short)ref < 0);
-+
-+              mfn = virt_to_mfn(data);
-+              gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
-+                                              mfn, GNTMAP_readonly);
-+
-+              tx->gref = np->grant_tx_ref[id] = ref;
-+              tx->offset = offset;
-+              tx->size = len;
-+              tx->flags = 0;
-+      }
-+
-+      /* Grant backend access to each skb fragment page. */
-+      for (i = 0; i < frags; i++) {
-+              skb_frag_t *frag = skb_shinfo(skb)->frags + i;
-+
-+              tx->flags |= NETTXF_more_data;
-+
-+              id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
-+              np->tx_skbs[id].skb = skb_get(skb);
-+              tx = RING_GET_REQUEST(&np->tx, prod++);
-+              tx->id = id;
-+              ref = gnttab_claim_grant_reference(&np->gref_tx_head);
-+              BUG_ON((signed short)ref < 0);
-+
-+              mfn = pfn_to_mfn(page_to_pfn(frag->page));
-+              gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
-+                                              mfn, GNTMAP_readonly);
-+
-+              tx->gref = np->grant_tx_ref[id] = ref;
-+              tx->offset = frag->page_offset;
-+              tx->size = frag->size;
-+              tx->flags = 0;
-+      }
-+
-+      np->tx.req_prod_pvt = prod;
-+}
-+
-+static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      unsigned short id;
-+      struct netfront_info *np = netdev_priv(dev);
-+      struct xen_netif_tx_request *tx;
-+      struct xen_netif_extra_info *extra;
-+      char *data = skb->data;
-+      RING_IDX i;
-+      grant_ref_t ref;
-+      unsigned long mfn;
-+      int notify;
-+      int frags = skb_shinfo(skb)->nr_frags;
-+      unsigned int offset = offset_in_page(data);
-+      unsigned int len = skb_headlen(skb);
-+
-+      frags += (offset + len + PAGE_SIZE - 1) / PAGE_SIZE;
-+      if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
-+              printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
-+                     frags);
-+              dump_stack();
-+              goto drop;
-+      }
-+
-+      spin_lock_irq(&np->tx_lock);
-+
-+      if (unlikely(!netif_carrier_ok(dev) ||
-+                   (frags > 1 && !xennet_can_sg(dev)) ||
-+                   netif_needs_gso(dev, skb))) {
-+              spin_unlock_irq(&np->tx_lock);
-+              goto drop;
-+      }
-+
-+      i = np->tx.req_prod_pvt;
-+
-+      id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
-+      np->tx_skbs[id].skb = skb;
-+
-+      tx = RING_GET_REQUEST(&np->tx, i);
-+
-+      tx->id   = id;
-+      ref = gnttab_claim_grant_reference(&np->gref_tx_head);
-+      BUG_ON((signed short)ref < 0);
-+      mfn = virt_to_mfn(data);
-+      gnttab_grant_foreign_access_ref(
-+              ref, np->xbdev->otherend_id, mfn, GNTMAP_readonly);
-+      tx->gref = np->grant_tx_ref[id] = ref;
-+      tx->offset = offset;
-+      tx->size = len;
-+      extra = NULL;
-+
-+      tx->flags = 0;
-+      if (skb->ip_summed == CHECKSUM_PARTIAL)
-+              /* local packet? */
-+              tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
-+      else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
-+              /* remote but checksummed. */
-+              tx->flags |= NETTXF_data_validated;
-+
-+      if (skb_shinfo(skb)->gso_size) {
-+              struct xen_netif_extra_info *gso;
-+
-+              gso = (struct xen_netif_extra_info *)
-+                      RING_GET_REQUEST(&np->tx, ++i);
-+
-+              if (extra)
-+                      extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
-+              else
-+                      tx->flags |= NETTXF_extra_info;
-+
-+              gso->u.gso.size = skb_shinfo(skb)->gso_size;
-+              gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
-+              gso->u.gso.pad = 0;
-+              gso->u.gso.features = 0;
-+
-+              gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
-+              gso->flags = 0;
-+              extra = gso;
-+      }
-+
-+      np->tx.req_prod_pvt = i + 1;
-+
-+      xennet_make_frags(skb, dev, tx);
-+      tx->size = skb->len;
-+
-+      RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->tx, notify);
-+      if (notify)
-+              notify_remote_via_irq(np->netdev->irq);
-+
-+      xennet_tx_buf_gc(dev);
-+
-+      if (!netfront_tx_slot_available(np))
-+              netif_stop_queue(dev);
-+
-+      spin_unlock_irq(&np->tx_lock);
-+
-+      np->stats.tx_bytes += skb->len;
-+      np->stats.tx_packets++;
-+
-+      return 0;
-+
-+ drop:
-+      np->stats.tx_dropped++;
-+      dev_kfree_skb(skb);
-+      return 0;
-+}
-+
-+static int xennet_close(struct net_device *dev)
-+{
-+      struct netfront_info *np = netdev_priv(dev);
-+      netif_stop_queue(np->netdev);
-+      return 0;
-+}
-+
-+static struct net_device_stats *xennet_get_stats(struct net_device *dev)
-+{
-+      struct netfront_info *np = netdev_priv(dev);
-+      return &np->stats;
-+}
-+
-+static void xennet_move_rx_slot(struct netfront_info *np, struct sk_buff *skb,
-+                              grant_ref_t ref)
-+{
-+      int new = xennet_rxidx(np->rx.req_prod_pvt);
-+
-+      BUG_ON(np->rx_skbs[new]);
-+      np->rx_skbs[new] = skb;
-+      np->grant_rx_ref[new] = ref;
-+      RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->id = new;
-+      RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->gref = ref;
-+      np->rx.req_prod_pvt++;
-+}
-+
-+static int xennet_get_extras(struct netfront_info *np,
-+                           struct xen_netif_extra_info *extras,
-+                           RING_IDX rp)
-+
-+{
-+      struct xen_netif_extra_info *extra;
-+      struct device *dev = &np->netdev->dev;
-+      RING_IDX cons = np->rx.rsp_cons;
-+      int err = 0;
-+
-+      do {
-+              struct sk_buff *skb;
-+              grant_ref_t ref;
-+
-+              if (unlikely(cons + 1 == rp)) {
-+                      if (net_ratelimit())
-+                              dev_warn(dev, "Missing extra info\n");
-+                      err = -EBADR;
-+                      break;
-+              }
-+
-+              extra = (struct xen_netif_extra_info *)
-+                      RING_GET_RESPONSE(&np->rx, ++cons);
-+
-+              if (unlikely(!extra->type ||
-+                           extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
-+                      if (net_ratelimit())
-+                              dev_warn(dev, "Invalid extra type: %d\n",
-+                                      extra->type);
-+                      err = -EINVAL;
-+              } else {
-+                      memcpy(&extras[extra->type - 1], extra,
-+                             sizeof(*extra));
-+              }
-+
-+              skb = xennet_get_rx_skb(np, cons);
-+              ref = xennet_get_rx_ref(np, cons);
-+              xennet_move_rx_slot(np, skb, ref);
-+      } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE);
-+
-+      np->rx.rsp_cons = cons;
-+      return err;
-+}
-+
-+static int xennet_get_responses(struct netfront_info *np,
-+                              struct netfront_rx_info *rinfo, RING_IDX rp,
-+                              struct sk_buff_head *list,
-+                              int *pages_flipped_p)
-+{
-+      int pages_flipped = *pages_flipped_p;
-+      struct mmu_update *mmu;
-+      struct multicall_entry *mcl;
-+      struct xen_netif_rx_response *rx = &rinfo->rx;
-+      struct xen_netif_extra_info *extras = rinfo->extras;
-+      struct device *dev = &np->netdev->dev;
-+      RING_IDX cons = np->rx.rsp_cons;
-+      struct sk_buff *skb = xennet_get_rx_skb(np, cons);
-+      grant_ref_t ref = xennet_get_rx_ref(np, cons);
-+      int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD);
-+      int frags = 1;
-+      int err = 0;
-+      unsigned long ret;
-+
-+      if (rx->flags & NETRXF_extra_info) {
-+              err = xennet_get_extras(np, extras, rp);
-+              cons = np->rx.rsp_cons;
-+      }
-+
-+      for (;;) {
-+              unsigned long mfn;
-+
-+              if (unlikely(rx->status < 0 ||
-+                           rx->offset + rx->status > PAGE_SIZE)) {
-+                      if (net_ratelimit())
-+                              dev_warn(dev, "rx->offset: %x, size: %u\n",
-+                                       rx->offset, rx->status);
-+                      xennet_move_rx_slot(np, skb, ref);
-+                      err = -EINVAL;
-+                      goto next;
-+              }
-+
-+              /*
-+               * This definitely indicates a bug, either in this driver or in
-+               * the backend driver. In future this should flag the bad
-+               * situation to the system controller to reboot the backed.
-+               */
-+              if (ref == GRANT_INVALID_REF) {
-+                      if (net_ratelimit())
-+                              dev_warn(dev, "Bad rx response id %d.\n",
-+                                       rx->id);
-+                      err = -EINVAL;
-+                      goto next;
-+              }
-+
-+              if (!np->copying_receiver) {
-+                      /* Memory pressure, insufficient buffer
-+                       * headroom, ... */
-+                      mfn = gnttab_end_foreign_transfer_ref(ref);
-+                      if (!mfn) {
-+                              if (net_ratelimit())
-+                                      dev_warn(dev, "Unfulfilled rx req "
-+                                               "(id=%d, st=%d).\n",
-+                                               rx->id, rx->status);
-+                              xennet_move_rx_slot(np, skb, ref);
-+                              err = -ENOMEM;
-+                              goto next;
-+                      }
-+
-+                      if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-+                              /* Remap the page. */
-+                              struct page *page =
-+                                      skb_shinfo(skb)->frags[0].page;
-+                              unsigned long pfn = page_to_pfn(page);
-+                              void *vaddr = page_address(page);
-+
-+                              mcl = np->rx_mcl + pages_flipped;
-+                              mmu = np->rx_mmu + pages_flipped;
-+
-+                              MULTI_update_va_mapping(mcl,
-+                                                      (unsigned long)vaddr,
-+                                                      mfn_pte(mfn, PAGE_KERNEL),
-+                                                      0);
-+                              mmu->ptr = ((u64)mfn << PAGE_SHIFT)
-+                                      | MMU_MACHPHYS_UPDATE;
-+                              mmu->val = pfn;
-+
-+                              set_phys_to_machine(pfn, mfn);
-+                      }
-+                      pages_flipped++;
-+              } else {
-+                      ret = gnttab_end_foreign_access_ref(ref, 0);
-+                      BUG_ON(!ret);
-+              }
-+
-+              gnttab_release_grant_reference(&np->gref_rx_head, ref);
-+
-+              __skb_queue_tail(list, skb);
-+
-+next:
-+              if (!(rx->flags & NETRXF_more_data))
-+                      break;
-+
-+              if (cons + frags == rp) {
-+                      if (net_ratelimit())
-+                              dev_warn(dev, "Need more frags\n");
-+                      err = -ENOENT;
-+                      break;
-+              }
-+
-+              rx = RING_GET_RESPONSE(&np->rx, cons + frags);
-+              skb = xennet_get_rx_skb(np, cons + frags);
-+              ref = xennet_get_rx_ref(np, cons + frags);
-+              frags++;
-+      }
-+
-+      if (unlikely(frags > max)) {
-+              if (net_ratelimit())
-+                      dev_warn(dev, "Too many frags\n");
-+              err = -E2BIG;
-+      }
-+
-+      if (unlikely(err))
-+              np->rx.rsp_cons = cons + frags;
-+
-+      *pages_flipped_p = pages_flipped;
-+
-+      return err;
-+}
-+
-+static int xennet_set_skb_gso(struct sk_buff *skb,
-+                            struct xen_netif_extra_info *gso)
-+{
-+      if (!gso->u.gso.size) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING "GSO size must not be zero.\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Currently only TCPv4 S.O. is supported. */
-+      if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING "Bad GSO type %d.\n", gso->u.gso.type);
-+              return -EINVAL;
-+      }
-+
-+      skb_shinfo(skb)->gso_size = gso->u.gso.size;
-+      skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
-+
-+      /* Header must be checked, and gso_segs computed. */
-+      skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
-+      skb_shinfo(skb)->gso_segs = 0;
-+
-+      return 0;
-+}
-+
-+static RING_IDX xennet_fill_frags(struct netfront_info *np,
-+                                struct sk_buff *skb,
-+                                struct sk_buff_head *list)
-+{
-+      struct skb_shared_info *shinfo = skb_shinfo(skb);
-+      int nr_frags = shinfo->nr_frags;
-+      RING_IDX cons = np->rx.rsp_cons;
-+      skb_frag_t *frag = shinfo->frags + nr_frags;
-+      struct sk_buff *nskb;
-+
-+      while ((nskb = __skb_dequeue(list))) {
-+              struct xen_netif_rx_response *rx =
-+                      RING_GET_RESPONSE(&np->rx, ++cons);
-+
-+              frag->page = skb_shinfo(nskb)->frags[0].page;
-+              frag->page_offset = rx->offset;
-+              frag->size = rx->status;
-+
-+              skb->data_len += rx->status;
-+
-+              skb_shinfo(nskb)->nr_frags = 0;
-+              kfree_skb(nskb);
-+
-+              frag++;
-+              nr_frags++;
-+      }
-+
-+      shinfo->nr_frags = nr_frags;
-+      return cons;
-+}
-+
-+static int skb_checksum_setup(struct sk_buff *skb)
-+{
-+      struct iphdr *iph;
-+      unsigned char *th;
-+      int err = -EPROTO;
-+
-+      if (skb->protocol != htons(ETH_P_IP))
-+              goto out;
-+
-+      iph = (void *)skb->data;
-+      th = skb->data + 4 * iph->ihl;
-+      if (th >= skb_tail_pointer(skb))
-+              goto out;
-+
-+      skb->csum_start = th - skb->head;
-+      switch (iph->protocol) {
-+      case IPPROTO_TCP:
-+              skb->csum_offset = offsetof(struct tcphdr, check);
-+              break;
-+      case IPPROTO_UDP:
-+              skb->csum_offset = offsetof(struct udphdr, check);
-+              break;
-+      default:
-+              if (net_ratelimit())
-+                      printk(KERN_ERR "Attempting to checksum a non-"
-+                             "TCP/UDP packet, dropping a protocol"
-+                             " %d packet", iph->protocol);
-+              goto out;
-+      }
-+
-+      if ((th + skb->csum_offset + 2) > skb_tail_pointer(skb))
-+              goto out;
-+
-+      err = 0;
-+
-+out:
-+      return err;
-+}
-+
-+static int handle_incoming_queue(struct net_device *dev,
-+                                struct sk_buff_head *rxq)
-+{
-+      struct netfront_info *np = netdev_priv(dev);
-+      int packets_dropped = 0;
-+      struct sk_buff *skb;
-+
-+      while ((skb = __skb_dequeue(rxq)) != NULL) {
-+              struct page *page = NETFRONT_SKB_CB(skb)->page;
-+              void *vaddr = page_address(page);
-+              unsigned offset = NETFRONT_SKB_CB(skb)->offset;
-+
-+              memcpy(skb->data, vaddr + offset,
-+                     skb_headlen(skb));
-+
-+              if (page != skb_shinfo(skb)->frags[0].page)
-+                      __free_page(page);
-+
-+              /* Ethernet work: Delayed to here as it peeks the header. */
-+              skb->protocol = eth_type_trans(skb, dev);
-+
-+              if (skb->ip_summed == CHECKSUM_PARTIAL) {
-+                      if (skb_checksum_setup(skb)) {
-+                              kfree_skb(skb);
-+                              packets_dropped++;
-+                              np->stats.rx_errors++;
-+                              continue;
-+                      }
-+              }
-+
-+              np->stats.rx_packets++;
-+              np->stats.rx_bytes += skb->len;
-+
-+              /* Pass it up. */
-+              netif_receive_skb(skb);
-+              dev->last_rx = jiffies;
-+      }
-+
-+      return packets_dropped;
-+}
-+
-+static int xennet_poll(struct net_device *dev, int *pbudget)
-+{
-+      struct netfront_info *np = netdev_priv(dev);
-+      struct sk_buff *skb;
-+      struct netfront_rx_info rinfo;
-+      struct xen_netif_rx_response *rx = &rinfo.rx;
-+      struct xen_netif_extra_info *extras = rinfo.extras;
-+      RING_IDX i, rp;
-+      struct multicall_entry *mcl;
-+      int work_done, budget, more_to_do = 1;
-+      struct sk_buff_head rxq;
-+      struct sk_buff_head errq;
-+      struct sk_buff_head tmpq;
-+      unsigned long flags;
-+      unsigned int len;
-+      int pages_flipped = 0;
-+      int err;
-+
-+      spin_lock(&np->rx_lock);
-+
-+      if (unlikely(!netif_carrier_ok(dev))) {
-+              spin_unlock(&np->rx_lock);
-+              return 0;
-+      }
-+
-+      skb_queue_head_init(&rxq);
-+      skb_queue_head_init(&errq);
-+      skb_queue_head_init(&tmpq);
-+
-+      if ((budget = *pbudget) > dev->quota)
-+              budget = dev->quota;
-+      rp = np->rx.sring->rsp_prod;
-+      rmb(); /* Ensure we see queued responses up to 'rp'. */
-+
-+      i = np->rx.rsp_cons;
-+      work_done = 0;
-+      while ((i != rp) && (work_done < budget)) {
-+              memcpy(rx, RING_GET_RESPONSE(&np->rx, i), sizeof(*rx));
-+              memset(extras, 0, sizeof(rinfo.extras));
-+
-+              err = xennet_get_responses(np, &rinfo, rp, &tmpq,
-+                                         &pages_flipped);
-+
-+              if (unlikely(err)) {
-+err:
-+                      while ((skb = __skb_dequeue(&tmpq)))
-+                              __skb_queue_tail(&errq, skb);
-+                      np->stats.rx_errors++;
-+                      i = np->rx.rsp_cons;
-+                      continue;
-+              }
-+
-+              skb = __skb_dequeue(&tmpq);
-+
-+              if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
-+                      struct xen_netif_extra_info *gso;
-+                      gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
-+
-+                      if (unlikely(xennet_set_skb_gso(skb, gso))) {
-+                              __skb_queue_head(&tmpq, skb);
-+                              np->rx.rsp_cons += skb_queue_len(&tmpq);
-+                              goto err;
-+                      }
-+              }
-+
-+              NETFRONT_SKB_CB(skb)->page = skb_shinfo(skb)->frags[0].page;
-+              NETFRONT_SKB_CB(skb)->offset = rx->offset;
-+
-+              len = rx->status;
-+              if (len > RX_COPY_THRESHOLD)
-+                      len = RX_COPY_THRESHOLD;
-+              skb_put(skb, len);
-+
-+              if (rx->status > len) {
-+                      skb_shinfo(skb)->frags[0].page_offset =
-+                              rx->offset + len;
-+                      skb_shinfo(skb)->frags[0].size = rx->status - len;
-+                      skb->data_len = rx->status - len;
-+              } else {
-+                      skb_shinfo(skb)->frags[0].page = NULL;
-+                      skb_shinfo(skb)->nr_frags = 0;
-+              }
-+
-+              i = xennet_fill_frags(np, skb, &tmpq);
-+
-+              /*
-+               * Truesize approximates the size of true data plus
-+               * any supervisor overheads. Adding hypervisor
-+               * overheads has been shown to significantly reduce
-+               * achievable bandwidth with the default receive
-+               * buffer size. It is therefore not wise to account
-+               * for it here.
-+               *
-+               * After alloc_skb(RX_COPY_THRESHOLD), truesize is set
-+               * to RX_COPY_THRESHOLD + the supervisor
-+               * overheads. Here, we add the size of the data pulled
-+               * in xennet_fill_frags().
-+               *
-+               * We also adjust for any unused space in the main
-+               * data area by subtracting (RX_COPY_THRESHOLD -
-+               * len). This is especially important with drivers
-+               * which split incoming packets into header and data,
-+               * using only 66 bytes of the main data area (see the
-+               * e1000 driver for example.)  On such systems,
-+               * without this last adjustement, our achievable
-+               * receive throughout using the standard receive
-+               * buffer size was cut by 25%(!!!).
-+               */
-+              skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len);
-+              skb->len += skb->data_len;
-+
-+              if (rx->flags & NETRXF_csum_blank)
-+                      skb->ip_summed = CHECKSUM_PARTIAL;
-+              else if (rx->flags & NETRXF_data_validated)
-+                      skb->ip_summed = CHECKSUM_UNNECESSARY;
-+
-+              __skb_queue_tail(&rxq, skb);
-+
-+              np->rx.rsp_cons = ++i;
-+              work_done++;
-+      }
-+
-+      if (pages_flipped) {
-+              /* Do all the remapping work, and M2P updates. */
-+              if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-+                      mcl = np->rx_mcl + pages_flipped;
-+                      MULTI_mmu_update(mcl, np->rx_mmu,
-+                                       pages_flipped, 0, DOMID_SELF);
-+                      (void)HYPERVISOR_multicall(np->rx_mcl,
-+                                                 pages_flipped + 1);
-+              }
-+      }
-+
-+      while ((skb = __skb_dequeue(&errq)))
-+              kfree_skb(skb);
-+
-+      work_done -= handle_incoming_queue(dev, &rxq);
-+
-+      /* If we get a callback with very few responses, reduce fill target. */
-+      /* NB. Note exponential increase, linear decrease. */
-+      if (((np->rx.req_prod_pvt - np->rx.sring->rsp_prod) >
-+           ((3*np->rx_target) / 4)) &&
-+          (--np->rx_target < np->rx_min_target))
-+              np->rx_target = np->rx_min_target;
-+
-+      xennet_alloc_rx_buffers(dev);
-+
-+      *pbudget   -= work_done;
-+      dev->quota -= work_done;
-+
-+      if (work_done < budget) {
-+              local_irq_save(flags);
-+
-+              RING_FINAL_CHECK_FOR_RESPONSES(&np->rx, more_to_do);
-+              if (!more_to_do)
-+                      __netif_rx_complete(dev);
-+
-+              local_irq_restore(flags);
-+      }
-+
-+      spin_unlock(&np->rx_lock);
-+
-+      return more_to_do;
-+}
-+
-+static int xennet_change_mtu(struct net_device *dev, int mtu)
-+{
-+      int max = xennet_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN;
-+
-+      if (mtu > max)
-+              return -EINVAL;
-+      dev->mtu = mtu;
-+      return 0;
-+}
-+
-+static void xennet_release_tx_bufs(struct netfront_info *np)
-+{
-+      struct sk_buff *skb;
-+      int i;
-+
-+      for (i = 0; i < NET_TX_RING_SIZE; i++) {
-+              /* Skip over entries which are actually freelist references */
-+              if ((unsigned long)np->tx_skbs[i].skb < PAGE_OFFSET)
-+                      continue;
-+
-+              skb = np->tx_skbs[i].skb;
-+              gnttab_end_foreign_access_ref(np->grant_tx_ref[i],
-+                                            GNTMAP_readonly);
-+              gnttab_release_grant_reference(&np->gref_tx_head,
-+                                             np->grant_tx_ref[i]);
-+              np->grant_tx_ref[i] = GRANT_INVALID_REF;
-+              add_id_to_freelist(&np->tx_skb_freelist, np->tx_skbs, i);
-+              dev_kfree_skb_irq(skb);
-+      }
-+}
-+
-+static void xennet_release_rx_bufs(struct netfront_info *np)
-+{
-+      struct mmu_update      *mmu = np->rx_mmu;
-+      struct multicall_entry *mcl = np->rx_mcl;
-+      struct sk_buff_head free_list;
-+      struct sk_buff *skb;
-+      unsigned long mfn;
-+      int xfer = 0, noxfer = 0, unused = 0;
-+      int id, ref;
-+
-+      if (np->copying_receiver) {
-+              dev_warn(&np->netdev->dev, "%s: fix me for copying receiver.\n",
-+                       __func__);
-+              return;
-+      }
-+
-+      skb_queue_head_init(&free_list);
-+
-+      spin_lock_bh(&np->rx_lock);
-+
-+      for (id = 0; id < NET_RX_RING_SIZE; id++) {
-+              if ((ref = np->grant_rx_ref[id]) == GRANT_INVALID_REF) {
-+                      unused++;
-+                      continue;
-+              }
-+
-+              skb = np->rx_skbs[id];
-+              mfn = gnttab_end_foreign_transfer_ref(ref);
-+              gnttab_release_grant_reference(&np->gref_rx_head, ref);
-+              np->grant_rx_ref[id] = GRANT_INVALID_REF;
-+
-+              if (0 == mfn) {
-+                      skb_shinfo(skb)->nr_frags = 0;
-+                      dev_kfree_skb(skb);
-+                      noxfer++;
-+                      continue;
-+              }
-+
-+              if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-+                      /* Remap the page. */
-+                      struct page *page = skb_shinfo(skb)->frags[0].page;
-+                      unsigned long pfn = page_to_pfn(page);
-+                      void *vaddr = page_address(page);
-+
-+                      MULTI_update_va_mapping(mcl, (unsigned long)vaddr,
-+                                              mfn_pte(mfn, PAGE_KERNEL),
-+                                              0);
-+                      mcl++;
-+                      mmu->ptr = ((u64)mfn << PAGE_SHIFT)
-+                              | MMU_MACHPHYS_UPDATE;
-+                      mmu->val = pfn;
-+                      mmu++;
-+
-+                      set_phys_to_machine(pfn, mfn);
-+              }
-+              __skb_queue_tail(&free_list, skb);
-+              xfer++;
-+      }
-+
-+      dev_info(&np->netdev->dev, "%s: %d xfer, %d noxfer, %d unused\n",
-+               __func__, xfer, noxfer, unused);
-+
-+      if (xfer) {
-+              if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-+                      /* Do all the remapping work and M2P updates. */
-+                      MULTI_mmu_update(mcl, np->rx_mmu, mmu - np->rx_mmu,
-+                                       0, DOMID_SELF);
-+                      mcl++;
-+                      HYPERVISOR_multicall(np->rx_mcl, mcl - np->rx_mcl);
-+              }
-+      }
-+
-+      while ((skb = __skb_dequeue(&free_list)) != NULL)
-+              dev_kfree_skb(skb);
-+
-+      spin_unlock_bh(&np->rx_lock);
-+}
-+
-+static void xennet_uninit(struct net_device *dev)
-+{
-+      struct netfront_info *np = netdev_priv(dev);
-+      xennet_release_tx_bufs(np);
-+      xennet_release_rx_bufs(np);
-+      gnttab_free_grant_references(np->gref_tx_head);
-+      gnttab_free_grant_references(np->gref_rx_head);
-+}
-+
-+static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev)
-+{
-+      int i, err;
-+      struct net_device *netdev;
-+      struct netfront_info *np;
-+
-+      netdev = alloc_etherdev(sizeof(struct netfront_info));
-+      if (!netdev) {
-+              printk(KERN_WARNING "%s> alloc_etherdev failed.\n",
-+                     __func__);
-+              return ERR_PTR(-ENOMEM);
-+      }
-+
-+      np                   = netdev_priv(netdev);
-+      np->xbdev            = dev;
-+
-+      spin_lock_init(&np->tx_lock);
-+      spin_lock_init(&np->rx_lock);
-+
-+      skb_queue_head_init(&np->rx_batch);
-+      np->rx_target     = RX_DFL_MIN_TARGET;
-+      np->rx_min_target = RX_DFL_MIN_TARGET;
-+      np->rx_max_target = RX_MAX_TARGET;
-+
-+      init_timer(&np->rx_refill_timer);
-+      np->rx_refill_timer.data = (unsigned long)netdev;
-+      np->rx_refill_timer.function = rx_refill_timeout;
-+
-+      /* Initialise tx_skbs as a free chain containing every entry. */
-+      np->tx_skb_freelist = 0;
-+      for (i = 0; i < NET_TX_RING_SIZE; i++) {
-+              np->tx_skbs[i].link = i+1;
-+              np->grant_tx_ref[i] = GRANT_INVALID_REF;
-+      }
-+
-+      /* Clear out rx_skbs */
-+      for (i = 0; i < NET_RX_RING_SIZE; i++) {
-+              np->rx_skbs[i] = NULL;
-+              np->grant_rx_ref[i] = GRANT_INVALID_REF;
-+      }
-+
-+      /* A grant for every tx ring slot */
-+      if (gnttab_alloc_grant_references(TX_MAX_TARGET,
-+                                        &np->gref_tx_head) < 0) {
-+              printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
-+              err = -ENOMEM;
-+              goto exit;
-+      }
-+      /* A grant for every rx ring slot */
-+      if (gnttab_alloc_grant_references(RX_MAX_TARGET,
-+                                        &np->gref_rx_head) < 0) {
-+              printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
-+              err = -ENOMEM;
-+              goto exit_free_tx;
-+      }
-+
-+      netdev->open            = xennet_open;
-+      netdev->hard_start_xmit = xennet_start_xmit;
-+      netdev->stop            = xennet_close;
-+      netdev->get_stats       = xennet_get_stats;
-+      netdev->poll            = xennet_poll;
-+      netdev->uninit          = xennet_uninit;
-+      netdev->change_mtu      = xennet_change_mtu;
-+      netdev->weight          = 64;
-+      netdev->features        = NETIF_F_IP_CSUM;
-+
-+      SET_ETHTOOL_OPS(netdev, &xennet_ethtool_ops);
-+      SET_MODULE_OWNER(netdev);
-+      SET_NETDEV_DEV(netdev, &dev->dev);
-+
-+      np->netdev = netdev;
-+
-+      netif_carrier_off(netdev);
-+
-+      return netdev;
-+
-+ exit_free_tx:
-+      gnttab_free_grant_references(np->gref_tx_head);
-+ exit:
-+      free_netdev(netdev);
-+      return ERR_PTR(err);
-+}
-+
-+/**
-+ * Entry point to this code when a new device is created.  Allocate the basic
-+ * structures and the ring buffers for communication with the backend, and
-+ * inform the backend of the appropriate details for those.
-+ */
-+static int __devinit netfront_probe(struct xenbus_device *dev,
-+                                  const struct xenbus_device_id *id)
-+{
-+      int err;
-+      struct net_device *netdev;
-+      struct netfront_info *info;
-+
-+      netdev = xennet_create_dev(dev);
-+      if (IS_ERR(netdev)) {
-+              err = PTR_ERR(netdev);
-+              xenbus_dev_fatal(dev, err, "creating netdev");
-+              return err;
-+      }
-+
-+      info = netdev_priv(netdev);
-+      dev->dev.driver_data = info;
-+
-+      err = register_netdev(info->netdev);
-+      if (err) {
-+              printk(KERN_WARNING "%s: register_netdev err=%d\n",
-+                     __func__, err);
-+              goto fail;
-+      }
-+
-+      err = xennet_sysfs_addif(info->netdev);
-+      if (err) {
-+              unregister_netdev(info->netdev);
-+              printk(KERN_WARNING "%s: add sysfs failed err=%d\n",
-+                     __func__, err);
-+              goto fail;
-+      }
-+
-+      return 0;
-+
-+ fail:
-+      free_netdev(netdev);
-+      dev->dev.driver_data = NULL;
-+      return err;
-+}
-+
-+static void xennet_end_access(int ref, void *page)
-+{
-+      /* This frees the page as a side-effect */
-+      if (ref != GRANT_INVALID_REF)
-+              gnttab_end_foreign_access(ref, 0, (unsigned long)page);
-+}
-+
-+static void xennet_disconnect_backend(struct netfront_info *info)
-+{
-+      /* Stop old i/f to prevent errors whilst we rebuild the state. */
-+      spin_lock_bh(&info->rx_lock);
-+      spin_lock_irq(&info->tx_lock);
-+      netif_carrier_off(info->netdev);
-+      spin_unlock_irq(&info->tx_lock);
-+      spin_unlock_bh(&info->rx_lock);
-+
-+      if (info->netdev->irq)
-+              unbind_from_irqhandler(info->netdev->irq, info->netdev);
-+      info->evtchn = info->netdev->irq = 0;
-+
-+      /* End access and free the pages */
-+      xennet_end_access(info->tx_ring_ref, info->tx.sring);
-+      xennet_end_access(info->rx_ring_ref, info->rx.sring);
-+
-+      info->tx_ring_ref = GRANT_INVALID_REF;
-+      info->rx_ring_ref = GRANT_INVALID_REF;
-+      info->tx.sring = NULL;
-+      info->rx.sring = NULL;
-+}
-+
-+/**
-+ * We are reconnecting to the backend, due to a suspend/resume, or a backend
-+ * driver restart.  We tear down our netif structure and recreate it, but
-+ * leave the device-layer structures intact so that this is transparent to the
-+ * rest of the kernel.
-+ */
-+static int netfront_resume(struct xenbus_device *dev)
-+{
-+      struct netfront_info *info = dev->dev.driver_data;
-+
-+      dev_dbg(&dev->dev, "%s\n", dev->nodename);
-+
-+      xennet_disconnect_backend(info);
-+      return 0;
-+}
-+
-+static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[])
-+{
-+      char *s, *e, *macstr;
-+      int i;
-+
-+      macstr = s = xenbus_read(XBT_NIL, dev->nodename, "mac", NULL);
-+      if (IS_ERR(macstr))
-+              return PTR_ERR(macstr);
-+
-+      for (i = 0; i < ETH_ALEN; i++) {
-+              mac[i] = simple_strtoul(s, &e, 16);
-+              if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
-+                      kfree(macstr);
-+                      return -ENOENT;
-+              }
-+              s = e+1;
-+      }
-+
-+      kfree(macstr);
-+      return 0;
-+}
-+
-+static irqreturn_t xennet_interrupt(int irq, void *dev_id)
-+{
-+      struct net_device *dev = dev_id;
-+      struct netfront_info *np = netdev_priv(dev);
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&np->tx_lock, flags);
-+
-+      if (likely(netif_carrier_ok(dev))) {
-+              xennet_tx_buf_gc(dev);
-+              /* Under tx_lock: protects access to rx shared-ring indexes. */
-+              if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
-+                      netif_rx_schedule(dev);
-+      }
-+
-+      spin_unlock_irqrestore(&np->tx_lock, flags);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info)
-+{
-+      struct xen_netif_tx_sring *txs;
-+      struct xen_netif_rx_sring *rxs;
-+      int err;
-+      struct net_device *netdev = info->netdev;
-+
-+      info->tx_ring_ref = GRANT_INVALID_REF;
-+      info->rx_ring_ref = GRANT_INVALID_REF;
-+      info->rx.sring = NULL;
-+      info->tx.sring = NULL;
-+      netdev->irq = 0;
-+
-+      err = xen_net_read_mac(dev, netdev->dev_addr);
-+      if (err) {
-+              xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
-+              goto fail;
-+      }
-+
-+      txs = (struct xen_netif_tx_sring *)get_zeroed_page(GFP_KERNEL);
-+      if (!txs) {
-+              err = -ENOMEM;
-+              xenbus_dev_fatal(dev, err, "allocating tx ring page");
-+              goto fail;
-+      }
-+      SHARED_RING_INIT(txs);
-+      FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE);
-+
-+      err = xenbus_grant_ring(dev, virt_to_mfn(txs));
-+      if (err < 0) {
-+              free_page((unsigned long)txs);
-+              goto fail;
-+      }
-+
-+      info->tx_ring_ref = err;
-+      rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_KERNEL);
-+      if (!rxs) {
-+              err = -ENOMEM;
-+              xenbus_dev_fatal(dev, err, "allocating rx ring page");
-+              goto fail;
-+      }
-+      SHARED_RING_INIT(rxs);
-+      FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);
-+
-+      err = xenbus_grant_ring(dev, virt_to_mfn(rxs));
-+      if (err < 0) {
-+              free_page((unsigned long)rxs);
-+              goto fail;
-+      }
-+      info->rx_ring_ref = err;
-+
-+      err = xenbus_alloc_evtchn(dev, &info->evtchn);
-+      if (err)
-+              goto fail;
-+
-+      err = bind_evtchn_to_irqhandler(info->evtchn, xennet_interrupt,
-+                                      IRQF_SAMPLE_RANDOM, netdev->name,
-+                                      netdev);
-+      if (err < 0)
-+              goto fail;
-+      netdev->irq = err;
-+      return 0;
-+
-+ fail:
-+      return err;
-+}
-+
-+/* Common code used when first setting up, and when resuming. */
-+static int talk_to_backend(struct xenbus_device *dev,
-+                         struct netfront_info *info)
-+{
-+      const char *message;
-+      struct xenbus_transaction xbt;
-+      int err;
-+
-+      /* Create shared ring, alloc event channel. */
-+      err = setup_netfront(dev, info);
-+      if (err)
-+              goto out;
-+
-+again:
-+      err = xenbus_transaction_start(&xbt);
-+      if (err) {
-+              xenbus_dev_fatal(dev, err, "starting transaction");
-+              goto destroy_ring;
-+      }
-+
-+      err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u",
-+                          info->tx_ring_ref);
-+      if (err) {
-+              message = "writing tx ring-ref";
-+              goto abort_transaction;
-+      }
-+      err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u",
-+                          info->rx_ring_ref);
-+      if (err) {
-+              message = "writing rx ring-ref";
-+              goto abort_transaction;
-+      }
-+      err = xenbus_printf(xbt, dev->nodename,
-+                          "event-channel", "%u", info->evtchn);
-+      if (err) {
-+              message = "writing event-channel";
-+              goto abort_transaction;
-+      }
-+
-+      err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u",
-+                          info->copying_receiver);
-+      if (err) {
-+              message = "writing request-rx-copy";
-+              goto abort_transaction;
-+      }
-+
-+      err = xenbus_printf(xbt, dev->nodename, "feature-rx-notify", "%d", 1);
-+      if (err) {
-+              message = "writing feature-rx-notify";
-+              goto abort_transaction;
-+      }
-+
-+      err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1);
-+      if (err) {
-+              message = "writing feature-sg";
-+              goto abort_transaction;
-+      }
-+
-+      err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%d", 1);
-+      if (err) {
-+              message = "writing feature-gso-tcpv4";
-+              goto abort_transaction;
-+      }
-+
-+      err = xenbus_transaction_end(xbt, 0);
-+      if (err) {
-+              if (err == -EAGAIN)
-+                      goto again;
-+              xenbus_dev_fatal(dev, err, "completing transaction");
-+              goto destroy_ring;
-+      }
-+
-+      return 0;
-+
-+ abort_transaction:
-+      xenbus_transaction_end(xbt, 1);
-+      xenbus_dev_fatal(dev, err, "%s", message);
-+ destroy_ring:
-+      xennet_disconnect_backend(info);
-+ out:
-+      return err;
-+}
-+
-+static int xennet_set_sg(struct net_device *dev, u32 data)
-+{
-+      if (data) {
-+              struct netfront_info *np = netdev_priv(dev);
-+              int val;
-+
-+              if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-sg",
-+                               "%d", &val) < 0)
-+                      val = 0;
-+              if (!val)
-+                      return -ENOSYS;
-+      } else if (dev->mtu > ETH_DATA_LEN)
-+              dev->mtu = ETH_DATA_LEN;
-+
-+      return ethtool_op_set_sg(dev, data);
-+}
-+
-+static int xennet_set_tso(struct net_device *dev, u32 data)
-+{
-+      if (data) {
-+              struct netfront_info *np = netdev_priv(dev);
-+              int val;
-+
-+              if (xenbus_scanf(XBT_NIL, np->xbdev->otherend,
-+                               "feature-gso-tcpv4", "%d", &val) < 0)
-+                      val = 0;
-+              if (!val)
-+                      return -ENOSYS;
-+      }
-+
-+      return ethtool_op_set_tso(dev, data);
-+}
-+
-+static void xennet_set_features(struct net_device *dev)
-+{
-+      /* Turn off all GSO bits except ROBUST. */
-+      dev->features &= (1 << NETIF_F_GSO_SHIFT) - 1;
-+      dev->features |= NETIF_F_GSO_ROBUST;
-+      xennet_set_sg(dev, 0);
-+
-+      /* We need checksum offload to enable scatter/gather and TSO. */
-+      if (!(dev->features & NETIF_F_IP_CSUM))
-+              return;
-+
-+      if (!xennet_set_sg(dev, 1))
-+              xennet_set_tso(dev, 1);
-+}
-+
-+static int xennet_connect(struct net_device *dev)
-+{
-+      struct netfront_info *np = netdev_priv(dev);
-+      int i, requeue_idx, err;
-+      struct sk_buff *skb;
-+      grant_ref_t ref;
-+      struct xen_netif_rx_request *req;
-+      unsigned int feature_rx_copy, feature_rx_flip;
-+
-+      err = xenbus_scanf(XBT_NIL, np->xbdev->otherend,
-+                         "feature-rx-copy", "%u", &feature_rx_copy);
-+      if (err != 1)
-+              feature_rx_copy = 0;
-+
-+      err = xenbus_scanf(XBT_NIL, np->xbdev->otherend,
-+                         "feature-rx-flip", "%u", &feature_rx_flip);
-+      /* Flip is the default, since it was once the only mode of
-+         operation. */
-+      if (err != 1)
-+              feature_rx_flip = 1;
-+
-+      /*
-+       * Copy packets on receive path if:
-+       *  (a) This was requested by user, and the backend supports it; or
-+       *  (b) Flipping was requested, but this is unsupported by the backend.
-+       */
-+      np->copying_receiver = (((rx_mode == RX_COPY) && feature_rx_copy) ||
-+                              ((rx_mode == RX_FLIP) && !feature_rx_flip));
-+
-+      err = talk_to_backend(np->xbdev, np);
-+      if (err)
-+              return err;
-+
-+      xennet_set_features(dev);
-+
-+      dev_info(&dev->dev, "has %s receive path.\n",
-+               np->copying_receiver ? "copying" : "flipping");
-+
-+      spin_lock_bh(&np->rx_lock);
-+      spin_lock_irq(&np->tx_lock);
-+
-+      /* Step 1: Discard all pending TX packet fragments. */
-+      xennet_release_tx_bufs(np);
-+
-+      /* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
-+      for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
-+              if (!np->rx_skbs[i])
-+                      continue;
-+
-+              skb = np->rx_skbs[requeue_idx] = xennet_get_rx_skb(np, i);
-+              ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i);
-+              req = RING_GET_REQUEST(&np->rx, requeue_idx);
-+
-+              if (!np->copying_receiver) {
-+                      gnttab_grant_foreign_transfer_ref(
-+                              ref, np->xbdev->otherend_id,
-+                              page_to_pfn(skb_shinfo(skb)->frags->page));
-+              } else {
-+                      gnttab_grant_foreign_access_ref(
-+                              ref, np->xbdev->otherend_id,
-+                              pfn_to_mfn(page_to_pfn(skb_shinfo(skb)->
-+                                                     frags->page)),
-+                              0);
-+              }
-+              req->gref = ref;
-+              req->id   = requeue_idx;
-+
-+              requeue_idx++;
-+      }
-+
-+      np->rx.req_prod_pvt = requeue_idx;
-+
-+      /*
-+       * Step 3: All public and private state should now be sane.  Get
-+       * ready to start sending and receiving packets and give the driver
-+       * domain a kick because we've probably just requeued some
-+       * packets.
-+       */
-+      netif_carrier_on(np->netdev);
-+      notify_remote_via_irq(np->netdev->irq);
-+      xennet_tx_buf_gc(dev);
-+      xennet_alloc_rx_buffers(dev);
-+
-+      spin_unlock_irq(&np->tx_lock);
-+      spin_unlock_bh(&np->rx_lock);
-+
-+      return 0;
-+}
-+
-+/**
-+ * Callback received when the backend's state changes.
-+ */
-+static void backend_changed(struct xenbus_device *dev,
-+                          enum xenbus_state backend_state)
-+{
-+      struct netfront_info *np = dev->dev.driver_data;
-+      struct net_device *netdev = np->netdev;
-+
-+      dev_dbg(&dev->dev, "%s\n", xenbus_strstate(backend_state));
-+
-+      switch (backend_state) {
-+      case XenbusStateInitialising:
-+      case XenbusStateInitialised:
-+      case XenbusStateConnected:
-+      case XenbusStateUnknown:
-+      case XenbusStateClosed:
-+              break;
-+
-+      case XenbusStateInitWait:
-+              if (dev->state != XenbusStateInitialising)
-+                      break;
-+              if (xennet_connect(netdev) != 0)
-+                      break;
-+              xenbus_switch_state(dev, XenbusStateConnected);
-+              break;
-+
-+      case XenbusStateClosing:
-+              xenbus_frontend_closed(dev);
-+              break;
-+      }
-+}
-+
-+static struct ethtool_ops xennet_ethtool_ops =
-+{
-+      .get_tx_csum = ethtool_op_get_tx_csum,
-+      .set_tx_csum = ethtool_op_set_tx_csum,
-+      .get_sg = ethtool_op_get_sg,
-+      .set_sg = xennet_set_sg,
-+      .get_tso = ethtool_op_get_tso,
-+      .set_tso = xennet_set_tso,
-+      .get_link = ethtool_op_get_link,
-+};
-+
-+#ifdef CONFIG_SYSFS
-+static ssize_t show_rxbuf_min(struct device *dev,
-+                            struct device_attribute *attr, char *buf)
-+{
-+      struct net_device *netdev = to_net_dev(dev);
-+      struct netfront_info *info = netdev_priv(netdev);
-+
-+      return sprintf(buf, "%u\n", info->rx_min_target);
-+}
-+
-+static ssize_t store_rxbuf_min(struct device *dev,
-+                             struct device_attribute *attr,
-+                             const char *buf, size_t len)
-+{
-+      struct net_device *netdev = to_net_dev(dev);
-+      struct netfront_info *np = netdev_priv(netdev);
-+      char *endp;
-+      unsigned long target;
-+
-+      if (!capable(CAP_NET_ADMIN))
-+              return -EPERM;
-+
-+      target = simple_strtoul(buf, &endp, 0);
-+      if (endp == buf)
-+              return -EBADMSG;
-+
-+      if (target < RX_MIN_TARGET)
-+              target = RX_MIN_TARGET;
-+      if (target > RX_MAX_TARGET)
-+              target = RX_MAX_TARGET;
-+
-+      spin_lock_bh(&np->rx_lock);
-+      if (target > np->rx_max_target)
-+              np->rx_max_target = target;
-+      np->rx_min_target = target;
-+      if (target > np->rx_target)
-+              np->rx_target = target;
-+
-+      xennet_alloc_rx_buffers(netdev);
-+
-+      spin_unlock_bh(&np->rx_lock);
-+      return len;
-+}
-+
-+static ssize_t show_rxbuf_max(struct device *dev,
-+                            struct device_attribute *attr, char *buf)
-+{
-+      struct net_device *netdev = to_net_dev(dev);
-+      struct netfront_info *info = netdev_priv(netdev);
-+
-+      return sprintf(buf, "%u\n", info->rx_max_target);
-+}
-+
-+static ssize_t store_rxbuf_max(struct device *dev,
-+                             struct device_attribute *attr,
-+                             const char *buf, size_t len)
-+{
-+      struct net_device *netdev = to_net_dev(dev);
-+      struct netfront_info *np = netdev_priv(netdev);
-+      char *endp;
-+      unsigned long target;
-+
-+      if (!capable(CAP_NET_ADMIN))
-+              return -EPERM;
-+
-+      target = simple_strtoul(buf, &endp, 0);
-+      if (endp == buf)
-+              return -EBADMSG;
-+
-+      if (target < RX_MIN_TARGET)
-+              target = RX_MIN_TARGET;
-+      if (target > RX_MAX_TARGET)
-+              target = RX_MAX_TARGET;
-+
-+      spin_lock_bh(&np->rx_lock);
-+      if (target < np->rx_min_target)
-+              np->rx_min_target = target;
-+      np->rx_max_target = target;
-+      if (target < np->rx_target)
-+              np->rx_target = target;
-+
-+      xennet_alloc_rx_buffers(netdev);
-+
-+      spin_unlock_bh(&np->rx_lock);
-+      return len;
-+}
-+
-+static ssize_t show_rxbuf_cur(struct device *dev,
-+                            struct device_attribute *attr, char *buf)
-+{
-+      struct net_device *netdev = to_net_dev(dev);
-+      struct netfront_info *info = netdev_priv(netdev);
-+
-+      return sprintf(buf, "%u\n", info->rx_target);
-+}
-+
-+static struct device_attribute xennet_attrs[] = {
-+      __ATTR(rxbuf_min, S_IRUGO|S_IWUSR, show_rxbuf_min, store_rxbuf_min),
-+      __ATTR(rxbuf_max, S_IRUGO|S_IWUSR, show_rxbuf_max, store_rxbuf_max),
-+      __ATTR(rxbuf_cur, S_IRUGO, show_rxbuf_cur, NULL),
-+};
-+
-+static int xennet_sysfs_addif(struct net_device *netdev)
-+{
-+      int i;
-+      int err;
-+
-+      for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++) {
-+              err = device_create_file(&netdev->dev,
-+                                         &xennet_attrs[i]);
-+              if (err)
-+                      goto fail;
-+      }
-+      return 0;
-+
-+ fail:
-+      while (--i >= 0)
-+              device_remove_file(&netdev->dev, &xennet_attrs[i]);
-+      return err;
-+}
-+
-+static void xennet_sysfs_delif(struct net_device *netdev)
-+{
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++)
-+              device_remove_file(&netdev->dev, &xennet_attrs[i]);
-+}
-+
-+#endif /* CONFIG_SYSFS */
-+
-+static struct xenbus_device_id netfront_ids[] = {
-+      { "vif" },
-+      { "" }
-+};
-+
-+
-+static int __devexit xennet_remove(struct xenbus_device *dev)
-+{
-+      struct netfront_info *info = dev->dev.driver_data;
-+
-+      dev_dbg(&dev->dev, "%s\n", dev->nodename);
-+
-+      unregister_netdev(info->netdev);
-+
-+      xennet_disconnect_backend(info);
-+
-+      del_timer_sync(&info->rx_refill_timer);
-+
-+      xennet_sysfs_delif(info->netdev);
-+
-+      free_netdev(info->netdev);
-+
-+      return 0;
-+}
-+
-+static struct xenbus_driver netfront = {
-+      .name = "vif",
-+      .owner = THIS_MODULE,
-+      .ids = netfront_ids,
-+      .probe = netfront_probe,
-+      .remove = __devexit_p(xennet_remove),
-+      .resume = netfront_resume,
-+      .otherend_changed = backend_changed,
-+};
-+
-+static int __init netif_init(void)
-+{
-+      if (!is_running_on_xen())
-+              return -ENODEV;
-+
-+      if (is_initial_xendomain())
-+              return 0;
-+
-+      printk(KERN_INFO "Initialising Xen virtual ethernet driver.\n");
-+
-+      return xenbus_register_frontend(&netfront);
-+}
-+module_init(netif_init);
-+
-+
-+static void __exit netif_exit(void)
-+{
-+      if (is_initial_xendomain())
-+              return;
-+
-+      return xenbus_unregister_driver(&netfront);
-+}
-+module_exit(netif_exit);
-+
-+MODULE_DESCRIPTION("Xen virtual network device frontend");
-+MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/drivers/net/yellowfin.c linux-2.6.22-590/drivers/net/yellowfin.c
---- linux-2.6.22-570/drivers/net/yellowfin.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/net/yellowfin.c   2008-01-02 13:56:37.000000000 -0500
-@@ -1137,7 +1137,7 @@
-                               if (skb == NULL)
-                                       break;
-                               skb_reserve(skb, 2);    /* 16 byte align the IP header */
--                              eth_copy_and_sum(skb, rx_skb->data, pkt_len, 0);
-+                              skb_copy_to_linear_data(skb, rx_skb->data, pkt_len);
-                               skb_put(skb, pkt_len);
-                               pci_dma_sync_single_for_device(yp->pci_dev, desc->addr,
-                                                                                          yp->rx_buf_sz,
-diff -Nurb linux-2.6.22-570/drivers/parisc/led.c linux-2.6.22-590/drivers/parisc/led.c
---- linux-2.6.22-570/drivers/parisc/led.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/parisc/led.c      2008-01-02 13:56:37.000000000 -0500
-@@ -359,7 +359,7 @@
-        * for reading should be OK */
-       read_lock(&dev_base_lock);
-       rcu_read_lock();
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-           struct net_device_stats *stats;
-           struct in_device *in_dev = __in_dev_get_rcu(dev);
-           if (!in_dev || !in_dev->ifa_list)
-diff -Nurb linux-2.6.22-570/drivers/parisc/pdc_stable.c linux-2.6.22-590/drivers/parisc/pdc_stable.c
---- linux-2.6.22-570/drivers/parisc/pdc_stable.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/parisc/pdc_stable.c       2008-01-02 13:56:37.000000000 -0500
-@@ -121,14 +121,14 @@
- #define PDCS_ATTR(_name, _mode, _show, _store) \
- struct subsys_attribute pdcs_attr_##_name = { \
--      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
-+      .attr = {.name = __stringify(_name), .mode = _mode}, \
-       .show = _show, \
-       .store = _store, \
- };
- #define PATHS_ATTR(_name, _mode, _show, _store) \
- struct pdcspath_attribute paths_attr_##_name = { \
--      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
-+      .attr = {.name = __stringify(_name), .mode = _mode}, \
-       .show = _show, \
-       .store = _store, \
- };
-diff -Nurb linux-2.6.22-570/drivers/pci/hotplug/acpiphp_ibm.c linux-2.6.22-590/drivers/pci/hotplug/acpiphp_ibm.c
---- linux-2.6.22-570/drivers/pci/hotplug/acpiphp_ibm.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/pci/hotplug/acpiphp_ibm.c 2008-01-02 13:56:37.000000000 -0500
-@@ -106,6 +106,7 @@
- static void ibm_handle_events(acpi_handle handle, u32 event, void *context);
- static int ibm_get_table_from_acpi(char **bufp);
- static ssize_t ibm_read_apci_table(struct kobject *kobj,
-+                                 struct bin_attribute *bin_attr,
-               char *buffer, loff_t pos, size_t size);
- static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
-               u32 lvl, void *context, void **rv);
-@@ -117,7 +118,6 @@
- static struct bin_attribute ibm_apci_table_attr = {
-           .attr = {
-                   .name = "apci_table",
--                  .owner = THIS_MODULE,
-                   .mode = S_IRUGO,
-           },
-           .read = ibm_read_apci_table,
-@@ -358,6 +358,7 @@
-  * our solution is to only allow reading the table in all at once
-  **/
- static ssize_t ibm_read_apci_table(struct kobject *kobj,
-+                                 struct bin_attribute *bin_attr,
-               char *buffer, loff_t pos, size_t size)
- {
-       int bytes_read = -EINVAL;
-diff -Nurb linux-2.6.22-570/drivers/pci/hotplug/rpadlpar_core.c linux-2.6.22-590/drivers/pci/hotplug/rpadlpar_core.c
---- linux-2.6.22-570/drivers/pci/hotplug/rpadlpar_core.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/pci/hotplug/rpadlpar_core.c       2008-01-02 13:56:37.000000000 -0500
-@@ -159,8 +159,8 @@
-       /* Claim new bus resources */
-       pcibios_claim_one_bus(dev->bus);
--      /* ioremap() for child bus, which may or may not succeed */
--      remap_bus_range(dev->subordinate);
-+      /* Map IO space for child bus, which may or may not succeed */
-+      pcibios_map_io_space(dev->subordinate);
-       /* Add new devices to global lists.  Register in proc, sysfs. */
-       pci_bus_add_devices(phb->bus);
-@@ -390,7 +390,7 @@
-       } else
-               pcibios_remove_pci_devices(bus);
--      if (unmap_bus_range(bus)) {
-+      if (pcibios_unmap_io_space(bus)) {
-               printk(KERN_ERR "%s: failed to unmap bus range\n",
-                       __FUNCTION__);
-               return -ERANGE;
-diff -Nurb linux-2.6.22-570/drivers/pci/pci-sysfs.c linux-2.6.22-590/drivers/pci/pci-sysfs.c
---- linux-2.6.22-570/drivers/pci/pci-sysfs.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/pci/pci-sysfs.c   2008-01-02 13:56:37.000000000 -0500
-@@ -213,7 +213,8 @@
- };
- static ssize_t
--pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
-+              char *buf, loff_t off, size_t count)
- {
-       struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
-       unsigned int size = 64;
-@@ -285,7 +286,8 @@
- }
- static ssize_t
--pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
-+               char *buf, loff_t off, size_t count)
- {
-       struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
-       unsigned int size = count;
-@@ -352,7 +354,8 @@
-  * callback routine (pci_legacy_read).
-  */
- ssize_t
--pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
-+                 char *buf, loff_t off, size_t count)
- {
-         struct pci_bus *bus = to_pci_bus(container_of(kobj,
-                                                       struct class_device,
-@@ -376,7 +379,8 @@
-  * callback routine (pci_legacy_write).
-  */
- ssize_t
--pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
-+                  char *buf, loff_t off, size_t count)
- {
-         struct pci_bus *bus = to_pci_bus(container_of(kobj,
-                                                     struct class_device,
-@@ -499,7 +503,6 @@
-                       sprintf(res_attr_name, "resource%d", i);
-                       res_attr->attr.name = res_attr_name;
-                       res_attr->attr.mode = S_IRUSR | S_IWUSR;
--                      res_attr->attr.owner = THIS_MODULE;
-                       res_attr->size = pci_resource_len(pdev, i);
-                       res_attr->mmap = pci_mmap_resource;
-                       res_attr->private = &pdev->resource[i];
-@@ -529,7 +532,8 @@
-  * writing anything except 0 enables it
-  */
- static ssize_t
--pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
-+            char *buf, loff_t off, size_t count)
- {
-       struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
-@@ -552,7 +556,8 @@
-  * device corresponding to @kobj.
-  */
- static ssize_t
--pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
-+           char *buf, loff_t off, size_t count)
- {
-       struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
-       void __iomem *rom;
-@@ -582,7 +587,6 @@
-       .attr = {
-               .name = "config",
-               .mode = S_IRUGO | S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = 256,
-       .read = pci_read_config,
-@@ -593,7 +597,6 @@
-       .attr = {
-               .name = "config",
-               .mode = S_IRUGO | S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = 4096,
-       .read = pci_read_config,
-@@ -628,7 +631,6 @@
-                       rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
-                       rom_attr->attr.name = "rom";
-                       rom_attr->attr.mode = S_IRUSR;
--                      rom_attr->attr.owner = THIS_MODULE;
-                       rom_attr->read = pci_read_rom;
-                       rom_attr->write = pci_write_rom;
-                       retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
-diff -Nurb linux-2.6.22-570/drivers/pci/probe.c linux-2.6.22-590/drivers/pci/probe.c
---- linux-2.6.22-570/drivers/pci/probe.c       2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/pci/probe.c       2008-01-02 13:56:37.000000000 -0500
-@@ -39,7 +39,6 @@
-               b->legacy_io->attr.name = "legacy_io";
-               b->legacy_io->size = 0xffff;
-               b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
--              b->legacy_io->attr.owner = THIS_MODULE;
-               b->legacy_io->read = pci_read_legacy_io;
-               b->legacy_io->write = pci_write_legacy_io;
-               class_device_create_bin_file(&b->class_dev, b->legacy_io);
-@@ -49,7 +48,6 @@
-               b->legacy_mem->attr.name = "legacy_mem";
-               b->legacy_mem->size = 1024*1024;
-               b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
--              b->legacy_mem->attr.owner = THIS_MODULE;
-               b->legacy_mem->mmap = pci_mmap_legacy_mem;
-               class_device_create_bin_file(&b->class_dev, b->legacy_mem);
-       }
-diff -Nurb linux-2.6.22-570/drivers/pcmcia/cs.c linux-2.6.22-590/drivers/pcmcia/cs.c
---- linux-2.6.22-570/drivers/pcmcia/cs.c       2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/pcmcia/cs.c       2008-01-02 13:56:37.000000000 -0500
-@@ -654,6 +654,7 @@
-       add_wait_queue(&skt->thread_wait, &wait);
-       complete(&skt->thread_done);
-+      set_freezable();
-       for (;;) {
-               unsigned long flags;
-               unsigned int events;
-diff -Nurb linux-2.6.22-570/drivers/pcmcia/socket_sysfs.c linux-2.6.22-590/drivers/pcmcia/socket_sysfs.c
---- linux-2.6.22-570/drivers/pcmcia/socket_sysfs.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/pcmcia/socket_sysfs.c     2008-01-02 13:56:37.000000000 -0500
-@@ -283,7 +283,9 @@
-       return (ret);
- }
--static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+static ssize_t pccard_show_cis(struct kobject *kobj,
-+                             struct bin_attribute *bin_attr,
-+                             char *buf, loff_t off, size_t count)
- {
-       unsigned int size = 0x200;
-@@ -311,7 +313,9 @@
-       return (count);
- }
--static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+static ssize_t pccard_store_cis(struct kobject *kobj,
-+                              struct bin_attribute *bin_attr,
-+                              char *buf, loff_t off, size_t count)
- {
-       struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj));
-       cisdump_t *cis;
-@@ -366,7 +370,7 @@
- };
- static struct bin_attribute pccard_cis_attr = {
--      .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE},
-+      .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR },
-       .size = 0x200,
-       .read = pccard_show_cis,
-       .write = pccard_store_cis,
-diff -Nurb linux-2.6.22-570/drivers/pnp/driver.c linux-2.6.22-590/drivers/pnp/driver.c
---- linux-2.6.22-570/drivers/pnp/driver.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/pnp/driver.c      2008-01-02 13:56:37.000000000 -0500
-@@ -167,6 +167,8 @@
-                       return error;
-       }
-+      if (pnp_dev->protocol && pnp_dev->protocol->suspend)
-+              pnp_dev->protocol->suspend(pnp_dev, state);
-       return 0;
- }
-@@ -179,6 +181,9 @@
-       if (!pnp_drv)
-               return 0;
-+      if (pnp_dev->protocol && pnp_dev->protocol->resume)
-+              pnp_dev->protocol->resume(pnp_dev);
-+
-       if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
-               error = pnp_start_dev(pnp_dev);
-               if (error)
-diff -Nurb linux-2.6.22-570/drivers/pnp/pnpacpi/core.c linux-2.6.22-590/drivers/pnp/pnpacpi/core.c
---- linux-2.6.22-570/drivers/pnp/pnpacpi/core.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/pnp/pnpacpi/core.c        2008-01-02 13:56:37.000000000 -0500
-@@ -119,11 +119,23 @@
-       return ACPI_FAILURE(status) ? -ENODEV : 0;
- }
-+static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
-+{
-+      return acpi_bus_set_power((acpi_handle)dev->data, 3);
-+}
-+
-+static int pnpacpi_resume(struct pnp_dev *dev)
-+{
-+      return acpi_bus_set_power((acpi_handle)dev->data, 0);
-+}
-+
- static struct pnp_protocol pnpacpi_protocol = {
-       .name   = "Plug and Play ACPI",
-       .get    = pnpacpi_get_resources,
-       .set    = pnpacpi_set_resources,
-       .disable = pnpacpi_disable_resources,
-+      .suspend = pnpacpi_suspend,
-+      .resume = pnpacpi_resume,
- };
- static int __init pnpacpi_add_device(struct acpi_device *device)
-diff -Nurb linux-2.6.22-570/drivers/pnp/pnpbios/core.c linux-2.6.22-590/drivers/pnp/pnpbios/core.c
---- linux-2.6.22-570/drivers/pnp/pnpbios/core.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/pnp/pnpbios/core.c        2008-01-02 13:56:37.000000000 -0500
-@@ -147,7 +147,7 @@
-               info->location_id, info->serial, info->capabilities);
-       envp[i] = NULL;
-       
--      value = call_usermodehelper (argv [0], argv, envp, 0);
-+      value = call_usermodehelper (argv [0], argv, envp, UMH_WAIT_EXEC);
-       kfree (buf);
-       kfree (envp);
-       return 0;
-@@ -160,6 +160,7 @@
- {
-       static struct pnp_docking_station_info now;
-       int docked = -1, d = 0;
-+      set_freezable();
-       while (!unloading)
-       {
-               int status;
-diff -Nurb linux-2.6.22-570/drivers/rapidio/rio-sysfs.c linux-2.6.22-590/drivers/rapidio/rio-sysfs.c
---- linux-2.6.22-570/drivers/rapidio/rio-sysfs.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/rapidio/rio-sysfs.c       2008-01-02 13:56:37.000000000 -0500
-@@ -67,7 +67,8 @@
- };
- static ssize_t
--rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+rio_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
-+              char *buf, loff_t off, size_t count)
- {
-       struct rio_dev *dev =
-           to_rio_dev(container_of(kobj, struct device, kobj));
-@@ -137,7 +138,8 @@
- }
- static ssize_t
--rio_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+rio_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
-+               char *buf, loff_t off, size_t count)
- {
-       struct rio_dev *dev =
-           to_rio_dev(container_of(kobj, struct device, kobj));
-@@ -197,7 +199,6 @@
-       .attr = {
-                .name = "config",
-                .mode = S_IRUGO | S_IWUSR,
--               .owner = THIS_MODULE,
-                },
-       .size = 0x200000,
-       .read = rio_read_config,
-diff -Nurb linux-2.6.22-570/drivers/rtc/rtc-ds1553.c linux-2.6.22-590/drivers/rtc/rtc-ds1553.c
---- linux-2.6.22-570/drivers/rtc/rtc-ds1553.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/rtc/rtc-ds1553.c  2008-01-02 13:56:37.000000000 -0500
-@@ -258,8 +258,9 @@
-       .ioctl          = ds1553_rtc_ioctl,
- };
--static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf,
--                               loff_t pos, size_t size)
-+static ssize_t ds1553_nvram_read(struct kobject *kobj,
-+                               struct bin_attribute *bin_attr,
-+                               char *buf, loff_t pos, size_t size)
- {
-       struct platform_device *pdev =
-               to_platform_device(container_of(kobj, struct device, kobj));
-@@ -272,8 +273,9 @@
-       return count;
- }
--static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf,
--                                loff_t pos, size_t size)
-+static ssize_t ds1553_nvram_write(struct kobject *kobj,
-+                                struct bin_attribute *bin_attr,
-+                                char *buf, loff_t pos, size_t size)
- {
-       struct platform_device *pdev =
-               to_platform_device(container_of(kobj, struct device, kobj));
-@@ -290,7 +292,6 @@
-       .attr = {
-               .name = "nvram",
-               .mode = S_IRUGO | S_IWUGO,
--              .owner = THIS_MODULE,
-       },
-       .size = RTC_OFFSET,
-       .read = ds1553_nvram_read,
-diff -Nurb linux-2.6.22-570/drivers/rtc/rtc-ds1742.c linux-2.6.22-590/drivers/rtc/rtc-ds1742.c
---- linux-2.6.22-570/drivers/rtc/rtc-ds1742.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/rtc/rtc-ds1742.c  2008-01-02 13:56:37.000000000 -0500
-@@ -127,8 +127,9 @@
-       .set_time       = ds1742_rtc_set_time,
- };
--static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
--                               loff_t pos, size_t size)
-+static ssize_t ds1742_nvram_read(struct kobject *kobj,
-+                               struct bin_attribute *bin_attr,
-+                               char *buf, loff_t pos, size_t size)
- {
-       struct platform_device *pdev =
-               to_platform_device(container_of(kobj, struct device, kobj));
-@@ -141,8 +142,9 @@
-       return count;
- }
--static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf,
--                                loff_t pos, size_t size)
-+static ssize_t ds1742_nvram_write(struct kobject *kobj,
-+                                struct bin_attribute *bin_attr,
-+                                char *buf, loff_t pos, size_t size)
- {
-       struct platform_device *pdev =
-               to_platform_device(container_of(kobj, struct device, kobj));
-@@ -159,7 +161,6 @@
-       .attr = {
-               .name = "nvram",
-               .mode = S_IRUGO | S_IWUGO,
--              .owner = THIS_MODULE,
-       },
-       .read = ds1742_nvram_read,
-       .write = ds1742_nvram_write,
-diff -Nurb linux-2.6.22-570/drivers/s390/cio/chp.c linux-2.6.22-590/drivers/s390/cio/chp.c
---- linux-2.6.22-570/drivers/s390/cio/chp.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/s390/cio/chp.c    2008-01-02 13:56:37.000000000 -0500
-@@ -141,8 +141,9 @@
- /*
-  * Channel measurement related functions
-  */
--static ssize_t chp_measurement_chars_read(struct kobject *kobj, char *buf,
--                                        loff_t off, size_t count)
-+static ssize_t chp_measurement_chars_read(struct kobject *kobj,
-+                                        struct bin_attribute *bin_attr,
-+                                        char *buf, loff_t off, size_t count)
- {
-       struct channel_path *chp;
-       unsigned int size;
-@@ -165,7 +166,6 @@
-       .attr = {
-               .name = "measurement_chars",
-               .mode = S_IRUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = sizeof(struct cmg_chars),
-       .read = chp_measurement_chars_read,
-@@ -193,8 +193,9 @@
-       } while (reference_buf.values[0] != buf->values[0]);
- }
--static ssize_t chp_measurement_read(struct kobject *kobj, char *buf,
--                                  loff_t off, size_t count)
-+static ssize_t chp_measurement_read(struct kobject *kobj,
-+                                  struct bin_attribute *bin_attr,
-+                                  char *buf, loff_t off, size_t count)
- {
-       struct channel_path *chp;
-       struct channel_subsystem *css;
-@@ -217,7 +218,6 @@
-       .attr = {
-               .name = "measurement",
-               .mode = S_IRUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = sizeof(struct cmg_entry),
-       .read = chp_measurement_read,
-diff -Nurb linux-2.6.22-570/drivers/s390/net/qeth_main.c linux-2.6.22-590/drivers/s390/net/qeth_main.c
---- linux-2.6.22-570/drivers/s390/net/qeth_main.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/s390/net/qeth_main.c      2008-01-02 13:56:37.000000000 -0500
-@@ -8127,7 +8127,7 @@
-       neigh->parms = neigh_parms_clone(parms);
-       rcu_read_unlock();
--      neigh->type = inet_addr_type(*(__be32 *) neigh->primary_key);
-+      neigh->type = inet_addr_type(&init_net, *(__be32 *) neigh->primary_key);
-       neigh->nud_state = NUD_NOARP;
-       neigh->ops = arp_direct_ops;
-       neigh->output = neigh->ops->queue_xmit;
-diff -Nurb linux-2.6.22-570/drivers/s390/net/qeth_sys.c linux-2.6.22-590/drivers/s390/net/qeth_sys.c
---- linux-2.6.22-570/drivers/s390/net/qeth_sys.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/s390/net/qeth_sys.c       2008-01-02 13:56:37.000000000 -0500
-@@ -991,7 +991,7 @@
- #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store)                             \
- struct device_attribute dev_attr_##_id = {                                 \
--      .attr = {.name=__stringify(_name), .mode=_mode, .owner=THIS_MODULE },\
-+      .attr = {.name=__stringify(_name), .mode=_mode, },\
-       .show   = _show,                                                     \
-       .store  = _store,                                                    \
- };
-diff -Nurb linux-2.6.22-570/drivers/s390/scsi/zfcp_aux.c linux-2.6.22-590/drivers/s390/scsi/zfcp_aux.c
---- linux-2.6.22-570/drivers/s390/scsi/zfcp_aux.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/s390/scsi/zfcp_aux.c      2008-01-02 13:56:37.000000000 -0500
-@@ -815,9 +815,7 @@
- struct zfcp_unit *
- zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
- {
--      struct zfcp_unit *unit, *tmp_unit;
--      unsigned int scsi_lun;
--      int found;
-+      struct zfcp_unit *unit;
-       /*
-        * check that there is no unit with this FCP_LUN already in list
-@@ -863,21 +861,9 @@
-       }
-       zfcp_unit_get(unit);
-+      unit->scsi_lun = scsilun_to_int((struct scsi_lun *)&unit->fcp_lun);
--      scsi_lun = 0;
--      found = 0;
-       write_lock_irq(&zfcp_data.config_lock);
--      list_for_each_entry(tmp_unit, &port->unit_list_head, list) {
--              if (tmp_unit->scsi_lun != scsi_lun) {
--                      found = 1;
--                      break;
--              }
--              scsi_lun++;
--      }
--      unit->scsi_lun = scsi_lun;
--      if (found)
--              list_add_tail(&unit->list, &tmp_unit->list);
--      else
-               list_add_tail(&unit->list, &port->unit_list_head);
-       atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
-       atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
-diff -Nurb linux-2.6.22-570/drivers/s390/scsi/zfcp_erp.c linux-2.6.22-590/drivers/s390/scsi/zfcp_erp.c
---- linux-2.6.22-570/drivers/s390/scsi/zfcp_erp.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/s390/scsi/zfcp_erp.c      2008-01-02 13:56:37.000000000 -0500
-@@ -1986,6 +1986,10 @@
-  failed_openfcp:
-       zfcp_close_fsf(erp_action->adapter);
-  failed_qdio:
-+      atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
-+                        ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
-+                        ZFCP_STATUS_ADAPTER_XPORT_OK,
-+                        &erp_action->adapter->status);
-  out:
-       return retval;
- }
-@@ -2167,6 +2171,9 @@
-               sleep *= 2;
-       }
-+      atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
-+                        &adapter->status);
-+
-       if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
-                             &adapter->status)) {
-               ZFCP_LOG_INFO("error: exchange of configuration data for "
-diff -Nurb linux-2.6.22-570/drivers/sbus/char/bbc_envctrl.c linux-2.6.22-590/drivers/sbus/char/bbc_envctrl.c
---- linux-2.6.22-570/drivers/sbus/char/bbc_envctrl.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/sbus/char/bbc_envctrl.c   2008-01-02 13:56:37.000000000 -0500
-@@ -7,6 +7,7 @@
- #include <linux/kthread.h>
- #include <linux/delay.h>
- #include <linux/kmod.h>
-+#include <linux/reboot.h>
- #include <asm/oplib.h>
- #include <asm/ebus.h>
-@@ -170,8 +171,6 @@
- static void do_envctrl_shutdown(struct bbc_cpu_temperature *tp)
- {
-       static int shutting_down = 0;
--      static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
--      char *argv[] = { "/sbin/shutdown", "-h", "now", NULL };
-       char *type = "???";
-       s8 val = -1;
-@@ -195,7 +194,7 @@
-       printk(KERN_CRIT "kenvctrld: Shutting down the system now.\n");
-       shutting_down = 1;
--      if (call_usermodehelper("/sbin/shutdown", argv, envp, 0) < 0)
-+      if (orderly_poweroff(true) < 0)
-               printk(KERN_CRIT "envctrl: shutdown execution failed\n");
- }
-diff -Nurb linux-2.6.22-570/drivers/sbus/char/envctrl.c linux-2.6.22-590/drivers/sbus/char/envctrl.c
---- linux-2.6.22-570/drivers/sbus/char/envctrl.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/sbus/char/envctrl.c       2008-01-02 13:56:37.000000000 -0500
-@@ -26,6 +26,7 @@
- #include <linux/ioport.h>
- #include <linux/miscdevice.h>
- #include <linux/kmod.h>
-+#include <linux/reboot.h>
- #include <asm/ebus.h>
- #include <asm/uaccess.h>
-@@ -966,10 +967,6 @@
- static void envctrl_do_shutdown(void)
- {
-       static int inprog = 0;
--      static char *envp[] = { 
--              "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
--      char *argv[] = { 
--              "/sbin/shutdown", "-h", "now", NULL };  
-       int ret;
-       if (inprog != 0)
-@@ -977,7 +974,7 @@
-       inprog = 1;
-       printk(KERN_CRIT "kenvctrld: WARNING: Shutting down the system now.\n");
--      ret = call_usermodehelper("/sbin/shutdown", argv, envp, 0);
-+      ret = orderly_poweroff(true);
-       if (ret < 0) {
-               printk(KERN_CRIT "kenvctrld: WARNING: system shutdown failed!\n"); 
-               inprog = 0;  /* unlikely to succeed, but we could try again */
-diff -Nurb linux-2.6.22-570/drivers/scsi/3w-9xxx.c linux-2.6.22-590/drivers/scsi/3w-9xxx.c
---- linux-2.6.22-570/drivers/scsi/3w-9xxx.c    2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/scsi/3w-9xxx.c    2008-01-02 13:56:37.000000000 -0500
-@@ -1307,22 +1307,26 @@
-                                       wake_up(&tw_dev->ioctl_wqueue);
-                               }
-                       } else {
-+                              struct scsi_cmnd *cmd;
-+
-+                              cmd = tw_dev->srb[request_id];
-+
-                               twa_scsiop_execute_scsi_complete(tw_dev, request_id);
-                               /* If no error command was a success */
-                               if (error == 0) {
--                                      tw_dev->srb[request_id]->result = (DID_OK << 16);
-+                                      cmd->result = (DID_OK << 16);
-                               }
-                               /* If error, command failed */
-                               if (error == 1) {
-                                       /* Ask for a host reset */
--                                      tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
-+                                      cmd->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
-                               }
-                               /* Report residual bytes for single sgl */
--                              if ((tw_dev->srb[request_id]->use_sg <= 1) && (full_command_packet->command.newcommand.status == 0)) {
--                                      if (full_command_packet->command.newcommand.sg_list[0].length < tw_dev->srb[request_id]->request_bufflen)
--                                              tw_dev->srb[request_id]->resid = tw_dev->srb[request_id]->request_bufflen - full_command_packet->command.newcommand.sg_list[0].length;
-+                              if ((scsi_sg_count(cmd) <= 1) && (full_command_packet->command.newcommand.status == 0)) {
-+                                      if (full_command_packet->command.newcommand.sg_list[0].length < scsi_bufflen(tw_dev->srb[request_id]))
-+                                              scsi_set_resid(cmd, scsi_bufflen(cmd) - full_command_packet->command.newcommand.sg_list[0].length);
-                               }
-                               /* Now complete the io */
-@@ -1385,52 +1389,20 @@
- {
-       int use_sg;
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
--      struct pci_dev *pdev = tw_dev->tw_pci_dev;
--      int retval = 0;
--
--      if (cmd->use_sg == 0)
--              goto out;
--
--      use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
--      if (use_sg == 0) {
-+      use_sg = scsi_dma_map(cmd);
-+      if (!use_sg)
-+              return 0;
-+      else if (use_sg < 0) {
-               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
--              goto out;
-+              return 0;
-       }
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
--      retval = use_sg;
--out:
--      return retval;
--} /* End twa_map_scsi_sg_data() */
--
--/* This function will perform a pci-dma map for a single buffer */
--static dma_addr_t twa_map_scsi_single_data(TW_Device_Extension *tw_dev, int request_id)
--{
--      dma_addr_t mapping;
--      struct scsi_cmnd *cmd = tw_dev->srb[request_id];
--      struct pci_dev *pdev = tw_dev->tw_pci_dev;
--      dma_addr_t retval = 0;
--
--      if (cmd->request_bufflen == 0) {
--              retval = 0;
--              goto out;
--      }
--
--      mapping = pci_map_single(pdev, cmd->request_buffer, cmd->request_bufflen, DMA_BIDIRECTIONAL);
--
--      if (mapping == 0) {
--              TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Failed to map page");
--              goto out;
--      }
--      cmd->SCp.phase = TW_PHASE_SINGLE;
--      cmd->SCp.have_data_in = mapping;
--      retval = mapping;
--out:
--      return retval;
--} /* End twa_map_scsi_single_data() */
-+      return use_sg;
-+} /* End twa_map_scsi_sg_data() */
- /* This function will poll for a response interrupt of a request */
- static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
-@@ -1816,15 +1788,13 @@
-       u32 num_sectors = 0x0;
-       int i, sg_count;
-       struct scsi_cmnd *srb = NULL;
--      struct scatterlist *sglist = NULL;
--      dma_addr_t buffaddr = 0x0;
-+      struct scatterlist *sglist = NULL, *sg;
-       int retval = 1;
-       if (tw_dev->srb[request_id]) {
--              if (tw_dev->srb[request_id]->request_buffer) {
--                      sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
--              }
-               srb = tw_dev->srb[request_id];
-+              if (scsi_sglist(srb))
-+                      sglist = scsi_sglist(srb);
-       }
-       /* Initialize command packet */
-@@ -1857,32 +1827,12 @@
-       if (!sglistarg) {
-               /* Map sglist from scsi layer to cmd packet */
--              if (tw_dev->srb[request_id]->use_sg == 0) {
--                      if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {
--                              command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
--                              command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
--                              if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)
--                                      memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
--                      } else {
--                              buffaddr = twa_map_scsi_single_data(tw_dev, request_id);
--                              if (buffaddr == 0)
--                                      goto out;
--
--                              command_packet->sg_list[0].address = TW_CPU_TO_SGL(buffaddr);
--                              command_packet->sg_list[0].length = cpu_to_le32(tw_dev->srb[request_id]->request_bufflen);
--                      }
--                      command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 1));
--                      if (command_packet->sg_list[0].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
--                              TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi");
--                              goto out;
--                      }
--              }
--
--              if (tw_dev->srb[request_id]->use_sg > 0) {
--                      if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
--                              if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) {
--                                      struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
-+              if (scsi_sg_count(srb)) {
-+                      if ((scsi_sg_count(srb) == 1) &&
-+                          (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
-+                              if (srb->sc_data_direction == DMA_TO_DEVICE || srb->sc_data_direction == DMA_BIDIRECTIONAL) {
-+                                      struct scatterlist *sg = scsi_sglist(srb);
-                                       char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
-                                       memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
-                                       kunmap_atomic(buf - sg->offset, KM_IRQ0);
-@@ -1894,16 +1844,16 @@
-                               if (sg_count == 0)
-                                       goto out;
--                              for (i = 0; i < sg_count; i++) {
--                                      command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(&sglist[i]));
--                                      command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(&sglist[i]));
-+                              scsi_for_each_sg(srb, sg, sg_count, i) {
-+                                      command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(sg));
-+                                      command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(sg));
-                                       if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
-                                               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
-                                               goto out;
-                                       }
-                               }
-                       }
--                      command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg));
-+                      command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), scsi_sg_count(tw_dev->srb[request_id])));
-               }
-       } else {
-               /* Internal cdb post */
-@@ -1933,7 +1883,7 @@
-       /* Update SG statistics */
-       if (srb) {
--              tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
-+              tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]);
-               if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
-                       tw_dev->max_sgl_entries = tw_dev->sgl_entries;
-       }
-@@ -1952,16 +1902,13 @@
- /* This function completes an execute scsi operation */
- static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id)
- {
--      if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH &&
--          (tw_dev->srb[request_id]->sc_data_direction == DMA_FROM_DEVICE ||
--           tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)) {
--              if (tw_dev->srb[request_id]->use_sg == 0) {
--                      memcpy(tw_dev->srb[request_id]->request_buffer,
--                             tw_dev->generic_buffer_virt[request_id],
--                             tw_dev->srb[request_id]->request_bufflen);
--              }
--              if (tw_dev->srb[request_id]->use_sg == 1) {
--                      struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
-+      struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-+
-+      if (scsi_bufflen(cmd) < TW_MIN_SGL_LENGTH &&
-+          (cmd->sc_data_direction == DMA_FROM_DEVICE ||
-+           cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
-+              if (scsi_sg_count(cmd) == 1) {
-+                      struct scatterlist *sg = scsi_sglist(tw_dev->srb[request_id]);
-                       char *buf;
-                       unsigned long flags = 0;
-                       local_irq_save(flags);
-@@ -2018,16 +1965,8 @@
- static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
- {
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
--      struct pci_dev *pdev = tw_dev->tw_pci_dev;
--      switch(cmd->SCp.phase) {
--      case TW_PHASE_SINGLE:
--              pci_unmap_single(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL);
--              break;
--      case TW_PHASE_SGLIST:
--              pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
--              break;
--      }
-+      scsi_dma_unmap(cmd);
- } /* End twa_unmap_scsi_data() */
- /* scsi_host_template initializer */
-diff -Nurb linux-2.6.22-570/drivers/scsi/3w-xxxx.c linux-2.6.22-590/drivers/scsi/3w-xxxx.c
---- linux-2.6.22-570/drivers/scsi/3w-xxxx.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/3w-xxxx.c    2008-01-02 13:56:37.000000000 -0500
-@@ -1274,12 +1274,8 @@
-       dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
-       
--      if (cmd->use_sg == 0)
--              return 0;
--
--      use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
--      
--      if (use_sg == 0) {
-+      use_sg = scsi_dma_map(cmd);
-+      if (use_sg < 0) {
-               printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
-               return 0;
-       }
-@@ -1290,40 +1286,11 @@
-       return use_sg;
- } /* End tw_map_scsi_sg_data() */
--static u32 tw_map_scsi_single_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
--{
--      dma_addr_t mapping;
--
--      dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data()\n");
--
--      if (cmd->request_bufflen == 0)
--              return 0;
--
--      mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), offset_in_page(cmd->request_buffer), cmd->request_bufflen, DMA_BIDIRECTIONAL);
--
--      if (mapping == 0) {
--              printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n");
--              return 0;
--      }
--
--      cmd->SCp.phase = TW_PHASE_SINGLE;
--      cmd->SCp.have_data_in = mapping;
--
--      return mapping;
--} /* End tw_map_scsi_single_data() */
--
- static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
- {
-       dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
--      switch(cmd->SCp.phase) {
--              case TW_PHASE_SINGLE:
--                      pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL);
--                      break;
--              case TW_PHASE_SGLIST:
--                      pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
--                      break;
--      }
-+      scsi_dma_unmap(cmd);
- } /* End tw_unmap_scsi_data() */
- /* This function will reset a device extension */
-@@ -1499,27 +1466,16 @@
-       void *buf;
-       unsigned int transfer_len;
-       unsigned long flags = 0;
-+      struct scatterlist *sg = scsi_sglist(cmd);
--      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 {
--              buf = cmd->request_buffer;
--              transfer_len = min(cmd->request_bufflen, len);
--      }
-       memcpy(buf, data, transfer_len);
-       
--      if (cmd->use_sg) {
--              struct scatterlist *sg;
--
--              sg = (struct scatterlist *)cmd->request_buffer;
-               kunmap_atomic(buf - sg->offset, KM_IRQ0);
-               local_irq_restore(flags);
--      }
- }
- /* This function is called by the isr to complete an inquiry command */
-@@ -1764,19 +1720,20 @@
- {
-       TW_Command *command_packet;
-       unsigned long command_que_value;
--      u32 lba = 0x0, num_sectors = 0x0, buffaddr = 0x0;
-+      u32 lba = 0x0, num_sectors = 0x0;
-       int i, use_sg;
-       struct scsi_cmnd *srb;
--      struct scatterlist *sglist;
-+      struct scatterlist *sglist, *sg;
-       dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n");
--      if (tw_dev->srb[request_id]->request_buffer == NULL) {
-+      srb = tw_dev->srb[request_id];
-+
-+      sglist = scsi_sglist(srb);
-+      if (!sglist) {
-               printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n");
-               return 1;
-       }
--      sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
--      srb = tw_dev->srb[request_id];
-       /* Initialize command packet */
-       command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
-@@ -1819,33 +1776,18 @@
-       command_packet->byte8.io.lba = lba;
-       command_packet->byte6.block_count = num_sectors;
--      /* Do this if there are no sg list entries */
--      if (tw_dev->srb[request_id]->use_sg == 0) {    
--              dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n");
--              buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
--              if (buffaddr == 0)
--                      return 1;
--
--              command_packet->byte8.io.sgl[0].address = buffaddr;
--              command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
--              command_packet->size+=2;
--      }
--
--      /* Do this if we have multiple sg list entries */
--      if (tw_dev->srb[request_id]->use_sg > 0) {
-               use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
--              if (use_sg == 0)
-+      if (!use_sg)
-                       return 1;
--              for (i=0;i<use_sg; i++) {
--                      command_packet->byte8.io.sgl[i].address = sg_dma_address(&sglist[i]);
--                      command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]);
-+      scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) {
-+              command_packet->byte8.io.sgl[i].address = sg_dma_address(sg);
-+              command_packet->byte8.io.sgl[i].length = sg_dma_len(sg);
-                       command_packet->size+=2;
-               }
--      }
-       /* Update SG statistics */
--      tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
-+      tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]);
-       if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
-               tw_dev->max_sgl_entries = tw_dev->sgl_entries;
-diff -Nurb linux-2.6.22-570/drivers/scsi/53c700.c linux-2.6.22-590/drivers/scsi/53c700.c
---- linux-2.6.22-570/drivers/scsi/53c700.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/53c700.c     2008-01-02 13:56:37.000000000 -0500
-@@ -585,16 +585,8 @@
-             struct NCR_700_command_slot *slot)
- {
-       if(SCp->sc_data_direction != DMA_NONE &&
--         SCp->sc_data_direction != DMA_BIDIRECTIONAL) {
--              if(SCp->use_sg) {
--                      dma_unmap_sg(hostdata->dev, SCp->request_buffer,
--                                   SCp->use_sg, SCp->sc_data_direction);
--              } else {
--                      dma_unmap_single(hostdata->dev, slot->dma_handle,
--                                       SCp->request_bufflen,
--                                       SCp->sc_data_direction);
--              }
--      }
-+         SCp->sc_data_direction != DMA_BIDIRECTIONAL)
-+              scsi_dma_unmap(SCp);
- }
- STATIC inline void
-@@ -661,7 +653,6 @@
- {
-       struct NCR_700_Host_Parameters *hostdata = 
-               (struct NCR_700_Host_Parameters *)host->hostdata[0];
--      __u32 dcntl_extra = 0;
-       __u8 min_period;
-       __u8 min_xferp = (hostdata->chip710 ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP);
-@@ -686,13 +677,14 @@
-                               burst_disable = BURST_DISABLE;
-                               break;
-               }
--              dcntl_extra = COMPAT_700_MODE;
-+              hostdata->dcntl_extra |= COMPAT_700_MODE;
--              NCR_700_writeb(dcntl_extra, host, DCNTL_REG);
-+              NCR_700_writeb(hostdata->dcntl_extra, host, DCNTL_REG);
-               NCR_700_writeb(burst_length | hostdata->dmode_extra,
-                              host, DMODE_710_REG);
--              NCR_700_writeb(burst_disable | (hostdata->differential ? 
--                                              DIFF : 0), host, CTEST7_REG);
-+              NCR_700_writeb(burst_disable | hostdata->ctest7_extra |
-+                             (hostdata->differential ? DIFF : 0),
-+                             host, CTEST7_REG);
-               NCR_700_writeb(BTB_TIMER_DISABLE, host, CTEST0_REG);
-               NCR_700_writeb(FULL_ARBITRATION | ENABLE_PARITY | PARITY
-                              | AUTO_ATN, host, SCNTL0_REG);
-@@ -727,13 +719,13 @@
-                * of spec: sync divider 2, async divider 3 */
-               DEBUG(("53c700: sync 2 async 3\n"));
-               NCR_700_writeb(SYNC_DIV_2_0, host, SBCL_REG);
--              NCR_700_writeb(ASYNC_DIV_3_0 | dcntl_extra, host, DCNTL_REG);
-+              NCR_700_writeb(ASYNC_DIV_3_0 | hostdata->dcntl_extra, host, DCNTL_REG);
-               hostdata->sync_clock = hostdata->clock/2;
-       } else  if(hostdata->clock > 50  && hostdata->clock <= 75) {
-               /* sync divider 1.5, async divider 3 */
-               DEBUG(("53c700: sync 1.5 async 3\n"));
-               NCR_700_writeb(SYNC_DIV_1_5, host, SBCL_REG);
--              NCR_700_writeb(ASYNC_DIV_3_0 | dcntl_extra, host, DCNTL_REG);
-+              NCR_700_writeb(ASYNC_DIV_3_0 | hostdata->dcntl_extra, host, DCNTL_REG);
-               hostdata->sync_clock = hostdata->clock*2;
-               hostdata->sync_clock /= 3;
-               
-@@ -741,18 +733,18 @@
-               /* sync divider 1, async divider 2 */
-               DEBUG(("53c700: sync 1 async 2\n"));
-               NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
--              NCR_700_writeb(ASYNC_DIV_2_0 | dcntl_extra, host, DCNTL_REG);
-+              NCR_700_writeb(ASYNC_DIV_2_0 | hostdata->dcntl_extra, host, DCNTL_REG);
-               hostdata->sync_clock = hostdata->clock;
-       } else if(hostdata->clock > 25 && hostdata->clock <=37) {
-               /* sync divider 1, async divider 1.5 */
-               DEBUG(("53c700: sync 1 async 1.5\n"));
-               NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
--              NCR_700_writeb(ASYNC_DIV_1_5 | dcntl_extra, host, DCNTL_REG);
-+              NCR_700_writeb(ASYNC_DIV_1_5 | hostdata->dcntl_extra, host, DCNTL_REG);
-               hostdata->sync_clock = hostdata->clock;
-       } else {
-               DEBUG(("53c700: sync 1 async 1\n"));
-               NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
--              NCR_700_writeb(ASYNC_DIV_1_0 | dcntl_extra, host, DCNTL_REG);
-+              NCR_700_writeb(ASYNC_DIV_1_0 | hostdata->dcntl_extra, host, DCNTL_REG);
-               /* sync divider 1, async divider 1 */
-               hostdata->sync_clock = hostdata->clock;
-       }
-@@ -1263,12 +1255,11 @@
-                      host->host_no, pun, lun, NCR_700_condition[i],
-                      NCR_700_phase[j], dsp - hostdata->pScript);
-               if(SCp != NULL) {
--                      scsi_print_command(SCp);
-+                      struct scatterlist *sg;
--                      if(SCp->use_sg) {
--                              for(i = 0; i < SCp->use_sg + 1; i++) {
--                                      printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->request_buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);
--                              }
-+                      scsi_print_command(SCp);
-+                      scsi_for_each_sg(SCp, sg, scsi_sg_count(SCp) + 1, i) {
-+                              printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, sg->length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);
-                       }
-               }              
-               NCR_700_internal_bus_reset(host);
-@@ -1844,8 +1835,8 @@
-       }
-       /* sanity check: some of the commands generated by the mid-layer
-        * have an eccentric idea of their sc_data_direction */
--      if(!SCp->use_sg && !SCp->request_bufflen 
--         && SCp->sc_data_direction != DMA_NONE) {
-+      if(!scsi_sg_count(SCp) && !scsi_bufflen(SCp) &&
-+         SCp->sc_data_direction != DMA_NONE) {
- #ifdef NCR_700_DEBUG
-               printk("53c700: Command");
-               scsi_print_command(SCp);
-@@ -1887,31 +1878,15 @@
-               int i;
-               int sg_count;
-               dma_addr_t vPtr = 0;
-+              struct scatterlist *sg;
-               __u32 count = 0;
--              if(SCp->use_sg) {
--                      sg_count = dma_map_sg(hostdata->dev,
--                                            SCp->request_buffer, SCp->use_sg,
--                                            direction);
--              } else {
--                      vPtr = dma_map_single(hostdata->dev,
--                                            SCp->request_buffer, 
--                                            SCp->request_bufflen,
--                                            direction);
--                      count = SCp->request_bufflen;
--                      slot->dma_handle = vPtr;
--                      sg_count = 1;
--              }
--                      
--
--              for(i = 0; i < sg_count; i++) {
-+              sg_count = scsi_dma_map(SCp);
-+              BUG_ON(sg_count < 0);
--                      if(SCp->use_sg) {
--                              struct scatterlist *sg = SCp->request_buffer;
--
--                              vPtr = sg_dma_address(&sg[i]);
--                              count = sg_dma_len(&sg[i]);
--                      }
-+              scsi_for_each_sg(SCp, sg, sg_count, i) {
-+                      vPtr = sg_dma_address(sg);
-+                      count = sg_dma_len(sg);
-                       slot->SG[i].ins = bS_to_host(move_ins | count);
-                       DEBUG((" scatter block %d: move %d[%08x] from 0x%lx\n",
-diff -Nurb linux-2.6.22-570/drivers/scsi/53c700.h linux-2.6.22-590/drivers/scsi/53c700.h
---- linux-2.6.22-570/drivers/scsi/53c700.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/53c700.h     2008-01-02 13:56:37.000000000 -0500
-@@ -177,6 +177,7 @@
-       __u8    state;
-       #define NCR_700_FLAG_AUTOSENSE  0x01
-       __u8    flags;
-+      __u8    pad1[2];        /* Needed for m68k where min alignment is 2 bytes */
-       int     tag;
-       __u32   resume_offset;
-       struct scsi_cmnd *cmnd;
-@@ -196,6 +197,8 @@
-       void __iomem    *base;          /* the base for the port (copied to host) */
-       struct device   *dev;
-       __u32   dmode_extra;    /* adjustable bus settings */
-+      __u32   dcntl_extra;    /* adjustable bus settings */
-+      __u32   ctest7_extra;   /* adjustable bus settings */
-       __u32   differential:1; /* if we are differential */
- #ifdef CONFIG_53C700_LE_ON_BE
-       /* This option is for HP only.  Set it if your chip is wired for
-@@ -352,6 +355,7 @@
- #define               SEL_TIMEOUT_DISABLE     0x10 /* 710 only */
- #define         DFP                     0x08
- #define         EVP                     0x04
-+#define         CTEST7_TT1              0x02
- #define               DIFF                    0x01
- #define CTEST6_REG                      0x1A
- #define       TEMP_REG                        0x1C
-@@ -385,6 +389,7 @@
- #define               SOFTWARE_RESET          0x01
- #define               COMPAT_700_MODE         0x01
- #define       SCRPTS_16BITS           0x20
-+#define               EA_710                  0x20
- #define               ASYNC_DIV_2_0           0x00
- #define               ASYNC_DIV_1_5           0x40
- #define               ASYNC_DIV_1_0           0x80
-diff -Nurb linux-2.6.22-570/drivers/scsi/53c7xx.c linux-2.6.22-590/drivers/scsi/53c7xx.c
---- linux-2.6.22-570/drivers/scsi/53c7xx.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/53c7xx.c     1969-12-31 19:00:00.000000000 -0500
-@@ -1,6102 +0,0 @@
--/*
-- * 53c710 driver.  Modified from Drew Eckhardts driver
-- * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
-- * Check out PERM_OPTIONS and EXPECTED_CLOCK, which may be defined in the
-- * relevant machine specific file (eg. mvme16x.[ch], amiga7xx.[ch]).
-- * There are also currently some defines at the top of 53c7xx.scr.
-- * The chip type is #defined in script_asm.pl, as well as the Makefile.
-- * Host scsi ID expected to be 7 - see NCR53c7x0_init().
-- *
-- * I have removed the PCI code and some of the 53c8xx specific code - 
-- * simply to make this file smaller and easier to manage.
-- *
-- * MVME16x issues:
-- *   Problems trying to read any chip registers in NCR53c7x0_init(), as they
-- *   may never have been set by 16xBug (eg. If kernel has come in over tftp).
-- */
--
--/*
-- * Adapted for Linux/m68k Amiga platforms for the A4000T/A4091 and
-- * WarpEngine SCSI controllers.
-- * By Alan Hourihane <alanh@fairlite.demon.co.uk>
-- * Thanks to Richard Hirst for making it possible with the MVME additions
-- */
--
--/*
-- * 53c710 rev 0 doesn't support add with carry.  Rev 1 and 2 does.  To
-- * overcome this problem you can define FORCE_DSA_ALIGNMENT, which ensures
-- * that the DSA address is always xxxxxx00.  If disconnection is not allowed,
-- * then the script only ever tries to add small (< 256) positive offsets to
-- * DSA, so lack of carry isn't a problem.  FORCE_DSA_ALIGNMENT can, of course,
-- * be defined for all chip revisions at a small cost in memory usage.
-- */
--
--#define FORCE_DSA_ALIGNMENT
--
--/*
-- * Selection timer does not always work on the 53c710, depending on the
-- * timing at the last disconnect, if this is a problem for you, try
-- * using validids as detailed below.
-- *
-- * Options for the NCR7xx driver
-- *
-- * noasync:0          -       disables sync and asynchronous negotiation
-- * nosync:0           -       disables synchronous negotiation (does async)
-- * nodisconnect:0     -       disables disconnection
-- * validids:0x??      -       Bitmask field that disallows certain ID's.
-- *                    -       e.g.    0x03    allows ID 0,1
-- *                    -               0x1F    allows ID 0,1,2,3,4
-- * opthi:n            -       replace top word of options with 'n'
-- * optlo:n            -       replace bottom word of options with 'n'
-- *                    -       ALWAYS SPECIFY opthi THEN optlo <<<<<<<<<<
-- */
--
--/*
-- * PERM_OPTIONS are driver options which will be enabled for all NCR boards
-- * in the system at driver initialization time.
-- *
-- * Don't THINK about touching these in PERM_OPTIONS : 
-- *   OPTION_MEMORY_MAPPED 
-- *    680x0 doesn't have an IO map!
-- *
-- *   OPTION_DEBUG_TEST1
-- *    Test 1 does bus mastering and interrupt tests, which will help weed 
-- *    out brain damaged main boards.
-- *
-- * Other PERM_OPTIONS settings are listed below.  Note the actual options
-- * required are set in the relevant file (mvme16x.c, amiga7xx.c, etc):
-- *
-- *   OPTION_NO_ASYNC
-- *    Don't negotiate for asynchronous transfers on the first command 
-- *    when OPTION_ALWAYS_SYNCHRONOUS is set.  Useful for dain bramaged
-- *    devices which do something bad rather than sending a MESSAGE 
-- *    REJECT back to us like they should if they can't cope.
-- *
-- *   OPTION_SYNCHRONOUS
-- *    Enable support for synchronous transfers.  Target negotiated 
-- *    synchronous transfers will be responded to.  To initiate 
-- *    a synchronous transfer request,  call 
-- *
-- *        request_synchronous (hostno, target) 
-- *
-- *    from within KGDB.
-- *
-- *   OPTION_ALWAYS_SYNCHRONOUS
-- *    Negotiate for synchronous transfers with every target after
-- *    driver initialization or a SCSI bus reset.  This is a bit dangerous, 
-- *    since there are some dain bramaged SCSI devices which will accept
-- *    SDTR messages but keep talking asynchronously.
-- *
-- *   OPTION_DISCONNECT
-- *    Enable support for disconnect/reconnect.  To change the 
-- *    default setting on a given host adapter, call
-- *
-- *        request_disconnect (hostno, allow)
-- *
-- *    where allow is non-zero to allow, 0 to disallow.
-- * 
-- *  If you really want to run 10MHz FAST SCSI-II transfers, you should 
-- *  know that the NCR driver currently ignores parity information.  Most
-- *  systems do 5MHz SCSI fine.  I've seen a lot that have problems faster
-- *  than 8MHz.  To play it safe, we only request 5MHz transfers.
-- *
-- *  If you'd rather get 10MHz transfers, edit sdtr_message and change 
-- *  the fourth byte from 50 to 25.
-- */
--
--/*
-- * Sponsored by 
-- *    iX Multiuser Multitasking Magazine
-- *    Hannover, Germany
-- *    hm@ix.de
-- *
-- * Copyright 1993, 1994, 1995 Drew Eckhardt
-- *      Visionary Computing 
-- *      (Unix and Linux consulting and custom programming)
-- *      drew@PoohSticks.ORG
-- *    +1 (303) 786-7975
-- *
-- * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
-- * 
-- * For more information, please consult 
-- *
-- * NCR53C810 
-- * SCSI I/O Processor
-- * Programmer's Guide
-- *
-- * NCR 53C810
-- * PCI-SCSI I/O Processor
-- * Data Manual
-- *
-- * NCR 53C810/53C820
-- * PCI-SCSI I/O Processor Design In Guide
-- *
-- * For literature on Symbios Logic Inc. formerly NCR, SCSI, 
-- * and Communication products please call (800) 334-5454 or
-- * (719) 536-3300. 
-- * 
-- * PCI BIOS Specification Revision
-- * PCI Local Bus Specification
-- * PCI System Design Guide
-- *
-- * PCI Special Interest Group
-- * M/S HF3-15A
-- * 5200 N.E. Elam Young Parkway
-- * Hillsboro, Oregon 97124-6497
-- * +1 (503) 696-2000 
-- * +1 (800) 433-5177
-- */
--
--/*
-- * Design issues : 
-- * The cumulative latency needed to propagate a read/write request 
-- * through the file system, buffer cache, driver stacks, SCSI host, and 
-- * SCSI device is ultimately the limiting factor in throughput once we 
-- * have a sufficiently fast host adapter.
-- *  
-- * So, to maximize performance we want to keep the ratio of latency to data 
-- * transfer time to a minimum by
-- * 1.  Minimizing the total number of commands sent (typical command latency
-- *    including drive and bus mastering host overhead is as high as 4.5ms)
-- *    to transfer a given amount of data.  
-- *
-- *      This is accomplished by placing no arbitrary limit on the number
-- *    of scatter/gather buffers supported, since we can transfer 1K
-- *    per scatter/gather buffer without Eric's cluster patches, 
-- *    4K with.  
-- *
-- * 2.  Minimizing the number of fatal interrupts serviced, since
-- *    fatal interrupts halt the SCSI I/O processor.  Basically,
-- *    this means offloading the practical maximum amount of processing 
-- *    to the SCSI chip.
-- * 
-- *    On the NCR53c810/820/720,  this is accomplished by using 
-- *            interrupt-on-the-fly signals when commands complete, 
-- *            and only handling fatal errors and SDTR / WDTR  messages 
-- *            in the host code.
-- *
-- *    On the NCR53c710, interrupts are generated as on the NCR53c8x0,
-- *            only the lack of a interrupt-on-the-fly facility complicates
-- *            things.   Also, SCSI ID registers and commands are 
-- *            bit fielded rather than binary encoded.
-- *            
-- *    On the NCR53c700 and NCR53c700-66, operations that are done via 
-- *            indirect, table mode on the more advanced chips must be
-- *            replaced by calls through a jump table which 
-- *            acts as a surrogate for the DSA.  Unfortunately, this 
-- *            will mean that we must service an interrupt for each 
-- *            disconnect/reconnect.
-- * 
-- * 3.  Eliminating latency by pipelining operations at the different levels.
-- *    
-- *    This driver allows a configurable number of commands to be enqueued
-- *    for each target/lun combination (experimentally, I have discovered
-- *    that two seems to work best) and will ultimately allow for 
-- *    SCSI-II tagged queuing.
-- *    
-- *
-- * Architecture : 
-- * This driver is built around a Linux queue of commands waiting to 
-- * be executed, and a shared Linux/NCR array of commands to start.  Commands
-- * are transferred to the array  by the run_process_issue_queue() function 
-- * which is called whenever a command completes.
-- *
-- * As commands are completed, the interrupt routine is triggered,
-- * looks for commands in the linked list of completed commands with
-- * valid status, removes these commands from a list of running commands, 
-- * calls the done routine, and flags their target/luns as not busy.
-- *
-- * Due to limitations in the intelligence of the NCR chips, certain
-- * concessions are made.  In many cases, it is easier to dynamically 
-- * generate/fix-up code rather than calculate on the NCR at run time.  
-- * So, code is generated or fixed up for
-- *
-- * - Handling data transfers, using a variable number of MOVE instructions
-- *    interspersed with CALL MSG_IN, WHEN MSGIN instructions.
-- *
-- *    The DATAIN and DATAOUT routines are separate, so that an incorrect
-- *    direction can be trapped, and space isn't wasted. 
-- *
-- *    It may turn out that we're better off using some sort 
-- *    of table indirect instruction in a loop with a variable
-- *    sized table on the NCR53c710 and newer chips.
-- *
-- * - Checking for reselection (NCR53c710 and better)
-- *
-- * - Handling the details of SCSI context switches (NCR53c710 and better),
-- *    such as reprogramming appropriate synchronous parameters, 
-- *    removing the dsa structure from the NCR's queue of outstanding
-- *    commands, etc.
-- *
-- */
--
--#include <linux/module.h>
--
--
--#include <linux/types.h>
--#include <asm/setup.h>
--#include <asm/dma.h>
--#include <asm/io.h>
--#include <asm/system.h>
--#include <linux/delay.h>
--#include <linux/signal.h>
--#include <linux/sched.h>
--#include <linux/errno.h>
--#include <linux/string.h>
--#include <linux/slab.h>
--#include <linux/vmalloc.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
--#include <linux/time.h>
--#include <linux/blkdev.h>
--#include <linux/spinlock.h>
--#include <linux/interrupt.h>
--#include <asm/pgtable.h>
--
--#ifdef CONFIG_AMIGA
--#include <asm/amigahw.h>
--#include <asm/amigaints.h>
--#include <asm/irq.h>
--
--#define BIG_ENDIAN
--#define NO_IO_SPACE
--#endif
--
--#ifdef CONFIG_MVME16x
--#include <asm/mvme16xhw.h>
--
--#define BIG_ENDIAN
--#define NO_IO_SPACE
--#define VALID_IDS
--#endif
--
--#ifdef CONFIG_BVME6000
--#include <asm/bvme6000hw.h>
--
--#define BIG_ENDIAN
--#define NO_IO_SPACE
--#define VALID_IDS
--#endif
--
--#include "scsi.h"
--#include <scsi/scsi_dbg.h>
--#include <scsi/scsi_host.h>
--#include <scsi/scsi_transport_spi.h>
--#include "53c7xx.h"
--#include <linux/stat.h>
--#include <linux/stddef.h>
--
--#ifdef NO_IO_SPACE
--/*
-- * The following make the definitions in 53c7xx.h (write8, etc) smaller,
-- * we don't have separate i/o space anyway.
-- */
--#undef inb
--#undef outb
--#undef inw
--#undef outw
--#undef inl
--#undef outl
--#define inb(x)          1
--#define inw(x)          1
--#define inl(x)          1
--#define outb(x,y)       1
--#define outw(x,y)       1
--#define outl(x,y)       1
--#endif
--
--static int check_address (unsigned long addr, int size);
--static void dump_events (struct Scsi_Host *host, int count);
--static Scsi_Cmnd * return_outstanding_commands (struct Scsi_Host *host, 
--    int free, int issue);
--static void hard_reset (struct Scsi_Host *host);
--static void ncr_scsi_reset (struct Scsi_Host *host);
--static void print_lots (struct Scsi_Host *host);
--static void set_synchronous (struct Scsi_Host *host, int target, int sxfer, 
--    int scntl3, int now_connected);
--static int datapath_residual (struct Scsi_Host *host);
--static const char * sbcl_to_phase (int sbcl);
--static void print_progress (Scsi_Cmnd *cmd);
--static void print_queues (struct Scsi_Host *host);
--static void process_issue_queue (unsigned long flags);
--static int shutdown (struct Scsi_Host *host);
--static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result);
--static int disable (struct Scsi_Host *host);
--static int NCR53c7xx_run_tests (struct Scsi_Host *host);
--static irqreturn_t NCR53c7x0_intr(int irq, void *dev_id);
--static void NCR53c7x0_intfly (struct Scsi_Host *host);
--static int ncr_halt (struct Scsi_Host *host);
--static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd 
--    *cmd);
--static void intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);
--static void print_dsa (struct Scsi_Host *host, u32 *dsa,
--    const char *prefix);
--static int print_insn (struct Scsi_Host *host, const u32 *insn,
--    const char *prefix, int kernel);
--
--static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd);
--static void NCR53c7x0_init_fixup (struct Scsi_Host *host);
--static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct 
--    NCR53c7x0_cmd *cmd);
--static void NCR53c7x0_soft_reset (struct Scsi_Host *host);
--
--/* Size of event list (per host adapter) */
--static int track_events = 0;
--static struct Scsi_Host *first_host = NULL;   /* Head of list of NCR boards */
--static struct scsi_host_template *the_template = NULL;
--
--/* NCR53c710 script handling code */
--
--#include "53c7xx_d.h"
--#ifdef A_int_debug_sync
--#define DEBUG_SYNC_INTR A_int_debug_sync
--#endif
--int NCR53c7xx_script_len = sizeof (SCRIPT);
--int NCR53c7xx_dsa_len = A_dsa_end + Ent_dsa_zero - Ent_dsa_code_template;
--#ifdef FORCE_DSA_ALIGNMENT
--int CmdPageStart = (0 - Ent_dsa_zero - sizeof(struct NCR53c7x0_cmd)) & 0xff;
--#endif
--
--static char *setup_strings[] =
--      {"","","","","","","",""};
--
--#define MAX_SETUP_STRINGS ARRAY_SIZE(setup_strings)
--#define SETUP_BUFFER_SIZE 200
--static char setup_buffer[SETUP_BUFFER_SIZE];
--static char setup_used[MAX_SETUP_STRINGS];
--
--void ncr53c7xx_setup (char *str, int *ints)
--{
--   int i;
--   char *p1, *p2;
--
--   p1 = setup_buffer;
--   *p1 = '\0';
--   if (str)
--      strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));
--   setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
--   p1 = setup_buffer;
--   i = 0;
--   while (*p1 && (i < MAX_SETUP_STRINGS)) {
--      p2 = strchr(p1, ',');
--      if (p2) {
--         *p2 = '\0';
--         if (p1 != p2)
--            setup_strings[i] = p1;
--         p1 = p2 + 1;
--         i++;
--         }
--      else {
--         setup_strings[i] = p1;
--         break;
--         }
--      }
--   for (i=0; i<MAX_SETUP_STRINGS; i++)
--      setup_used[i] = 0;
--}
--
--
--/* check_setup_strings() returns index if key found, 0 if not
-- */
--
--static int check_setup_strings(char *key, int *flags, int *val, char *buf)
--{
--int x;
--char *cp;
--
--   for  (x=0; x<MAX_SETUP_STRINGS; x++) {
--      if (setup_used[x])
--         continue;
--      if (!strncmp(setup_strings[x], key, strlen(key)))
--         break;
--      if (!strncmp(setup_strings[x], "next", strlen("next")))
--         return 0;
--      }
--   if (x == MAX_SETUP_STRINGS)
--      return 0;
--   setup_used[x] = 1;
--   cp = setup_strings[x] + strlen(key);
--   *val = -1;
--   if (*cp != ':')
--      return ++x;
--   cp++;
--   if ((*cp >= '0') && (*cp <= '9')) {
--      *val = simple_strtoul(cp,NULL,0);
--      }
--   return ++x;
--}
--
--
--
--/*
-- * KNOWN BUGS :
-- * - There is some sort of conflict when the PPP driver is compiled with 
-- *    support for 16 channels?
-- * 
-- * - On systems which predate the 1.3.x initialization order change,
-- *      the NCR driver will cause Cannot get free page messages to appear.  
-- *      These are harmless, but I don't know of an easy way to avoid them.
-- *
-- * - With OPTION_DISCONNECT, on two systems under unknown circumstances,
-- *    we get a PHASE MISMATCH with DSA set to zero (suggests that we 
-- *    are occurring somewhere in the reselection code) where 
-- *    DSP=some value DCMD|DBC=same value.  
-- *    
-- *    Closer inspection suggests that we may be trying to execute
-- *    some portion of the DSA?
-- * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO)
-- * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO)
-- * scsi0 : no current command : unexpected phase MSGIN.
-- *         DSP=0x1c46cc, DCMD|DBC=0x1c46ac, DSA=0x0
-- *         DSPS=0x0, TEMP=0x1c3e70, DMODE=0x80
-- * scsi0 : DSP->
-- * 001c46cc : 0x001c46cc 0x00000000
-- * 001c46d4 : 0x001c5ea0 0x000011f8
-- *
-- *    Changed the print code in the phase_mismatch handler so
-- *    that we call print_lots to try to diagnose this.
-- *
-- */
--
--/* 
-- * Possible future direction of architecture for max performance :
-- *
-- * We're using a single start array for the NCR chip.  This is 
-- * sub-optimal, because we cannot add a command which would conflict with 
-- * an executing command to this start queue, and therefore must insert the 
-- * next command for a given I/T/L combination after the first has completed;
-- * incurring our interrupt latency between SCSI commands.
-- *
-- * To allow further pipelining of the NCR and host CPU operation, we want 
-- * to set things up so that immediately on termination of a command destined 
-- * for a given LUN, we get that LUN busy again.  
-- * 
-- * To do this, we need to add a 32 bit pointer to which is jumped to 
-- * on completion of a command.  If no new command is available, this 
-- * would point to the usual DSA issue queue select routine.
-- *
-- * If one were, it would point to a per-NCR53c7x0_cmd select routine 
-- * which starts execution immediately, inserting the command at the head 
-- * of the start queue if the NCR chip is selected or reselected.
-- *
-- * We would change so that we keep a list of outstanding commands 
-- * for each unit, rather than a single running_list.  We'd insert 
-- * a new command into the right running list; if the NCR didn't 
-- * have something running for that yet, we'd put it in the 
-- * start queue as well.  Some magic needs to happen to handle the 
-- * race condition between the first command terminating before the 
-- * new one is written.
-- *
-- * Potential for profiling : 
-- * Call do_gettimeofday(struct timeval *tv) to get 800ns resolution.
-- */
--
--
--/*
-- * TODO : 
-- * 1.  To support WIDE transfers, not much needs to happen.  We
-- *    should do CHMOVE instructions instead of MOVEs when
-- *    we have scatter/gather segments of uneven length.  When
-- *    we do this, we need to handle the case where we disconnect
-- *    between segments.
-- * 
-- * 2.  Currently, when Icky things happen we do a FATAL().  Instead,
-- *     we want to do an integrity check on the parts of the NCR hostdata
-- *     structure which were initialized at boot time; FATAL() if that 
-- *     fails, and otherwise try to recover.  Keep track of how many
-- *     times this has happened within a single SCSI command; if it 
-- *     gets excessive, then FATAL().
-- *
-- * 3.  Parity checking is currently disabled, and a few things should 
-- *     happen here now that we support synchronous SCSI transfers :
-- *     1.  On soft-reset, we shoould set the EPC (Enable Parity Checking)
-- *       and AAP (Assert SATN/ on parity error) bits in SCNTL0.
-- *    
-- *     2.  We should enable the parity interrupt in the SIEN0 register.
-- * 
-- *     3.  intr_phase_mismatch() needs to believe that message out is 
-- *       always an "acceptable" phase to have a mismatch in.  If 
-- *       the old phase was MSG_IN, we should send a MESSAGE PARITY 
-- *       error.  If the old phase was something else, we should send
-- *       a INITIATOR_DETECTED_ERROR message.  Note that this could
-- *       cause a RESTORE POINTERS message; so we should handle that 
-- *       correctly first.  Instead, we should probably do an 
-- *       initiator_abort.
-- *
-- * 4.  MPEE bit of CTEST4 should be set so we get interrupted if 
-- *     we detect an error.
-- *
-- *  
-- * 5.  The initial code has been tested on the NCR53c810.  I don't 
-- *     have access to NCR53c700, 700-66 (Forex boards), NCR53c710
-- *     (NCR Pentium systems), NCR53c720, NCR53c820, or NCR53c825 boards to 
-- *     finish development on those platforms.
-- *
-- *     NCR53c820/825/720 - need to add wide transfer support, including WDTR 
-- *                    negotiation, programming of wide transfer capabilities
-- *            on reselection and table indirect selection.
-- *
-- *     NCR53c710 - need to add fatal interrupt or GEN code for 
-- *            command completion signaling.   Need to modify all 
-- *            SDID, SCID, etc. registers, and table indirect select code 
-- *            since these use bit fielded (ie 1<<target) instead of 
-- *            binary encoded target ids.  Need to accommodate
-- *            different register mappings, probably scan through
-- *            the SCRIPT code and change the non SFBR register operand
-- *            of all MOVE instructions.
-- *
-- *            It is rather worse than this actually, the 710 corrupts
-- *            both TEMP and DSA when you do a MOVE MEMORY.  This
-- *            screws you up all over the place.  MOVE MEMORY 4 with a
-- *            destination of DSA seems to work OK, which helps some.
-- *            Richard Hirst  richard@sleepie.demon.co.uk
-- * 
-- *     NCR53c700/700-66 - need to add code to refix addresses on 
-- *            every nexus change, eliminate all table indirect code,
-- *            very messy.
-- *
-- * 6.  The NCR53c7x0 series is very popular on other platforms that 
-- *     could be running Linux - ie, some high performance AMIGA SCSI 
-- *     boards use it.  
-- *    
-- *     So, I should include #ifdef'd code so that it is 
-- *     compatible with these systems.
-- *    
-- *     Specifically, the little Endian assumptions I made in my 
-- *     bit fields need to change, and if the NCR doesn't see memory
-- *     the right way, we need to provide options to reverse words
-- *     when the scripts are relocated.
-- *
-- * 7.  Use vremap() to access memory mapped boards.  
-- */
--
--/* 
-- * Allow for simultaneous existence of multiple SCSI scripts so we 
-- * can have a single driver binary for all of the family.
-- *
-- * - one for NCR53c700 and NCR53c700-66 chips (not yet supported)
-- * - one for rest (only the NCR53c810, 815, 820, and 825 are currently 
-- *    supported)
-- * 
-- * So that we only need two SCSI scripts, we need to modify things so
-- * that we fixup register accesses in READ/WRITE instructions, and 
-- * we'll also have to accommodate the bit vs. binary encoding of IDs
-- * with the 7xx chips.
-- */
--
--#define ROUNDUP(adr,type)     \
--  ((void *) (((long) (adr) + sizeof(type) - 1) & ~(sizeof(type) - 1)))
--
--
--/*
-- * Function: issue_to_cmd
-- *
-- * Purpose: convert jump instruction in issue array to NCR53c7x0_cmd
-- *    structure pointer.  
-- *
-- * Inputs; issue - pointer to start of NOP or JUMP instruction
-- *    in issue array.
-- *
-- * Returns: pointer to command on success; 0 if opcode is NOP.
-- */
--
--static inline struct NCR53c7x0_cmd *
--issue_to_cmd (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
--    u32 *issue)
--{
--    return (issue[0] != hostdata->NOP_insn) ? 
--    /* 
--     * If the IF TRUE bit is set, it's a JUMP instruction.  The
--     * operand is a bus pointer to the dsa_begin routine for this DSA.  The
--     * dsa field of the NCR53c7x0_cmd structure starts with the 
--     * DSA code template.  By converting to a virtual address,
--     * subtracting the code template size, and offset of the 
--     * dsa field, we end up with a pointer to the start of the 
--     * structure (alternatively, we could use the 
--     * dsa_cmnd field, an anachronism from when we weren't
--     * sure what the relationship between the NCR structures
--     * and host structures were going to be.
--     */
--      (struct NCR53c7x0_cmd *) ((char *) bus_to_virt (issue[1]) - 
--          (hostdata->E_dsa_code_begin - hostdata->E_dsa_code_template) -
--          offsetof(struct NCR53c7x0_cmd, dsa)) 
--    /* If the IF TRUE bit is not set, it's a NOP */
--      : NULL;
--}
--
--
--/* 
-- * FIXME: we should junk these, in favor of synchronous_want and 
-- * wide_want in the NCR53c7x0_hostdata structure.
-- */
--
--/* Template for "preferred" synchronous transfer parameters. */
--
--static const unsigned char sdtr_message[] = {
--#ifdef CONFIG_SCSI_NCR53C7xx_FAST
--    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 25 /* *4ns */, 8 /* off */
--#else
--    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 50 /* *4ns */, 8 /* off */ 
--#endif
--};
--
--/* Template to request asynchronous transfers */
--
--static const unsigned char async_message[] = {
--    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 0, 0 /* asynchronous */
--};
--
--/* Template for "preferred" WIDE transfer parameters */
--
--static const unsigned char wdtr_message[] = {
--    EXTENDED_MESSAGE, 2 /* length */, EXTENDED_WDTR, 1 /* 2^1 bytes */
--};
--
--#if 0
--/*
-- * Function : struct Scsi_Host *find_host (int host)
-- * 
-- * Purpose : KGDB support function which translates a host number 
-- *    to a host structure. 
-- *
-- * Inputs : host - number of SCSI host
-- *
-- * Returns : NULL on failure, pointer to host structure on success.
-- */
--
--static struct Scsi_Host *
--find_host (int host) {
--    struct Scsi_Host *h;
--    for (h = first_host; h && h->host_no != host; h = h->next);
--    if (!h) {
--      printk (KERN_ALERT "scsi%d not found\n", host);
--      return NULL;
--    } else if (h->hostt != the_template) {
--      printk (KERN_ALERT "scsi%d is not a NCR board\n", host);
--      return NULL;
--    }
--    return h;
--}
--
--#if 0
--/*
-- * Function : request_synchronous (int host, int target)
-- * 
-- * Purpose : KGDB interface which will allow us to negotiate for 
-- *    synchronous transfers.  This ill be replaced with a more 
-- *    integrated function; perhaps a new entry in the scsi_host 
-- *    structure, accessible via an ioctl() or perhaps /proc/scsi.
-- *
-- * Inputs : host - number of SCSI host; target - number of target.
-- *
-- * Returns : 0 when negotiation has been setup for next SCSI command,
-- *    -1 on failure.
-- */
--
--static int
--request_synchronous (int host, int target) {
--    struct Scsi_Host *h;
--    struct NCR53c7x0_hostdata *hostdata;
--    unsigned long flags;
--    if (target < 0) {
--      printk (KERN_ALERT "target %d is bogus\n", target);
--      return -1;
--    }
--    if (!(h = find_host (host)))
--      return -1;
--    else if (h->this_id == target) {
--      printk (KERN_ALERT "target %d is host ID\n", target);
--      return -1;
--    } 
--    else if (target >= h->max_id) {
--      printk (KERN_ALERT "target %d exceeds maximum of %d\n", target,
--          h->max_id);
--      return -1;
--    }
--    hostdata = (struct NCR53c7x0_hostdata *)h->hostdata[0];
--
--    local_irq_save(flags);
--    if (hostdata->initiate_sdtr & (1 << target)) {
--      local_irq_restore(flags);
--      printk (KERN_ALERT "target %d already doing SDTR\n", target);
--      return -1;
--    } 
--    hostdata->initiate_sdtr |= (1 << target);
--    local_irq_restore(flags);
--    return 0;
--}
--#endif
--
--/*
-- * Function : request_disconnect (int host, int on_or_off)
-- * 
-- * Purpose : KGDB support function, tells us to allow or disallow 
-- *    disconnections.
-- *
-- * Inputs : host - number of SCSI host; on_or_off - non-zero to allow,
-- *    zero to disallow.
-- *
-- * Returns : 0 on success, *  -1 on failure.
-- */
--
--static int 
--request_disconnect (int host, int on_or_off) {
--    struct Scsi_Host *h;
--    struct NCR53c7x0_hostdata *hostdata;
--    if (!(h = find_host (host)))
--      return -1;
--    hostdata = (struct NCR53c7x0_hostdata *) h->hostdata[0];
--    if (on_or_off) 
--      hostdata->options |= OPTION_DISCONNECT;
--    else
--      hostdata->options &= ~OPTION_DISCONNECT;
--    return 0;
--}
--#endif
--
--/*
-- * Function : static void NCR53c7x0_driver_init (struct Scsi_Host *host)
-- *
-- * Purpose : Initialize internal structures, as required on startup, or 
-- *    after a SCSI bus reset.
-- * 
-- * Inputs : host - pointer to this host adapter's structure
-- */
--
--static void 
--NCR53c7x0_driver_init (struct Scsi_Host *host) {
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    int i, j;
--    u32 *ncrcurrent;
--
--    for (i = 0; i < 16; ++i) {
--      hostdata->request_sense[i] = 0;
--      for (j = 0; j < 8; ++j) 
--          hostdata->busy[i][j] = 0;
--      set_synchronous (host, i, /* sxfer */ 0, hostdata->saved_scntl3, 0);
--    }
--    hostdata->issue_queue = NULL;
--    hostdata->running_list = hostdata->finished_queue = 
--      hostdata->ncrcurrent = NULL;
--    for (i = 0, ncrcurrent = (u32 *) hostdata->schedule; 
--      i < host->can_queue; ++i, ncrcurrent += 2) {
--      ncrcurrent[0] = hostdata->NOP_insn;
--      ncrcurrent[1] = 0xdeadbeef;
--    }
--    ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) | DBC_TCI_TRUE;
--    ncrcurrent[1] = (u32) virt_to_bus (hostdata->script) +
--      hostdata->E_wait_reselect;
--    hostdata->reconnect_dsa_head = 0;
--    hostdata->addr_reconnect_dsa_head = (u32) 
--      virt_to_bus((void *) &(hostdata->reconnect_dsa_head));
--    hostdata->expecting_iid = 0;
--    hostdata->expecting_sto = 0;
--    if (hostdata->options & OPTION_ALWAYS_SYNCHRONOUS) 
--      hostdata->initiate_sdtr = 0xffff; 
--    else
--      hostdata->initiate_sdtr = 0;
--    hostdata->talked_to = 0;
--    hostdata->idle = 1;
--}
--
--/* 
-- * Function : static int clock_to_ccf_710 (int clock)
-- *
-- * Purpose :  Return the clock conversion factor for a given SCSI clock.
-- *
-- * Inputs : clock - SCSI clock expressed in Hz.
-- *
-- * Returns : ccf on success, -1 on failure.
-- */
--
--static int 
--clock_to_ccf_710 (int clock) {
--    if (clock <= 16666666)
--      return -1;
--    if (clock <= 25000000)
--      return 2;       /* Divide by 1.0 */
--    else if (clock <= 37500000)
--      return 1;       /* Divide by 1.5 */
--    else if (clock <= 50000000)
--      return 0;       /* Divide by 2.0 */
--    else if (clock <= 66000000)
--      return 3;       /* Divide by 3.0 */
--    else 
--      return -1;
--}
--    
--/* 
-- * Function : static int NCR53c7x0_init (struct Scsi_Host *host)
-- *
-- * Purpose :  initialize the internal structures for a given SCSI host
-- *
-- * Inputs : host - pointer to this host adapter's structure
-- *
-- * Preconditions : when this function is called, the chip_type 
-- *    field of the hostdata structure MUST have been set.
-- *
-- * Returns : 0 on success, -1 on failure.
-- */
--
--int 
--NCR53c7x0_init (struct Scsi_Host *host) {
--    NCR53c7x0_local_declare();
--    int i, ccf;
--    unsigned char revision;
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    /* 
--     * There are some things which we need to know about in order to provide
--     * a semblance of support.  Print 'em if they aren't what we expect, 
--     * otherwise don't add to the noise.
--     * 
--     * -1 means we don't know what to expect.
--     */
--    int val, flags;
--    char buf[32];
--    int expected_id = -1;
--    int expected_clock = -1;
--    int uninitialized = 0;
--#ifdef NO_IO_SPACE
--    int expected_mapping = OPTION_MEMORY_MAPPED;
--#else
--    int expected_mapping = OPTION_IO_MAPPED;
--#endif
--    for (i=0;i<7;i++)
--      hostdata->valid_ids[i] = 1;     /* Default all ID's to scan */
--
--    /* Parse commandline flags */
--    if (check_setup_strings("noasync",&flags,&val,buf))
--    {
--      hostdata->options |= OPTION_NO_ASYNC;
--      hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS);
--    }
--
--    if (check_setup_strings("nosync",&flags,&val,buf))
--    {
--      hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS);
--    }
--
--    if (check_setup_strings("nodisconnect",&flags,&val,buf))
--      hostdata->options &= ~OPTION_DISCONNECT;
--
--    if (check_setup_strings("validids",&flags,&val,buf))
--    {
--      for (i=0;i<7;i++) 
--              hostdata->valid_ids[i] = val & (1<<i);
--    }
-- 
--    if  ((i = check_setup_strings("next",&flags,&val,buf)))
--    {
--      while (i)
--              setup_used[--i] = 1;
--    }
--
--    if (check_setup_strings("opthi",&flags,&val,buf))
--      hostdata->options = (long long)val << 32;
--    if (check_setup_strings("optlo",&flags,&val,buf))
--      hostdata->options |= val;
--
--    NCR53c7x0_local_setup(host);
--    switch (hostdata->chip) {
--    case 710:
--    case 770:
--      hostdata->dstat_sir_intr = NCR53c7x0_dstat_sir_intr;
--      hostdata->init_save_regs = NULL;
--      hostdata->dsa_fixup = NCR53c7xx_dsa_fixup;
--      hostdata->init_fixup = NCR53c7x0_init_fixup;
--      hostdata->soft_reset = NCR53c7x0_soft_reset;
--      hostdata->run_tests = NCR53c7xx_run_tests;
--      expected_clock = hostdata->scsi_clock;
--      expected_id = 7;
--      break;
--    default:
--      printk ("scsi%d : chip type of %d is not supported yet, detaching.\n",
--          host->host_no, hostdata->chip);
--      scsi_unregister (host);
--      return -1;
--    }
--
--    /* Assign constants accessed by NCR */
--    hostdata->NCR53c7xx_zero = 0;                     
--    hostdata->NCR53c7xx_msg_reject = MESSAGE_REJECT;
--    hostdata->NCR53c7xx_msg_abort = ABORT;
--    hostdata->NCR53c7xx_msg_nop = NOP;
--    hostdata->NOP_insn = (DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24;
--    if (expected_mapping == -1 || 
--      (hostdata->options & (OPTION_MEMORY_MAPPED)) != 
--      (expected_mapping & OPTION_MEMORY_MAPPED))
--      printk ("scsi%d : using %s mapped access\n", host->host_no, 
--          (hostdata->options & OPTION_MEMORY_MAPPED) ? "memory" : 
--          "io");
--
--    hostdata->dmode = (hostdata->chip == 700 || hostdata->chip == 70066) ? 
--      DMODE_REG_00 : DMODE_REG_10;
--    hostdata->istat = ((hostdata->chip / 100) == 8) ? 
--      ISTAT_REG_800 : ISTAT_REG_700;
--
--/* We have to assume that this may be the first access to the chip, so
-- * we must set EA in DCNTL. */
--
--    NCR53c7x0_write8 (DCNTL_REG, DCNTL_10_EA|DCNTL_10_COM);
--
--
--/* Only the ISTAT register is readable when the NCR is running, so make 
--   sure it's halted. */
--    ncr_halt(host);
--
--/* 
-- * XXX - the NCR53c700 uses bitfielded registers for SCID, SDID, etc,
-- *    as does the 710 with one bit per SCSI ID.  Conversely, the NCR
-- *    uses a normal, 3 bit binary representation of these values.
-- *
-- * Get the rest of the NCR documentation, and FIND OUT where the change
-- * was.
-- */
--
--#if 0
--      /* May not be able to do this - chip my not have been set up yet */
--      tmp = hostdata->this_id_mask = NCR53c7x0_read8(SCID_REG);
--      for (host->this_id = 0; tmp != 1; tmp >>=1, ++host->this_id);
--#else
--      host->this_id = 7;
--#endif
--
--/*
-- * Note : we should never encounter a board setup for ID0.  So,
-- *    if we see ID0, assume that it was uninitialized and set it
-- *    to the industry standard 7.
-- */
--    if (!host->this_id) {
--      printk("scsi%d : initiator ID was %d, changing to 7\n",
--          host->host_no, host->this_id);
--      host->this_id = 7;
--      hostdata->this_id_mask = 1 << 7;
--      uninitialized = 1;
--    };
--
--    if (expected_id == -1 || host->this_id != expected_id)
--      printk("scsi%d : using initiator ID %d\n", host->host_no,
--          host->this_id);
--
--    /*
--     * Save important registers to allow a soft reset.
--     */
--
--    /*
--     * CTEST7 controls cache snooping, burst mode, and support for 
--     * external differential drivers.  This isn't currently used - the
--     * default value may not be optimal anyway.
--     * Even worse, it may never have been set up since reset.
--     */
--    hostdata->saved_ctest7 = NCR53c7x0_read8(CTEST7_REG) & CTEST7_SAVE;
--    revision = (NCR53c7x0_read8(CTEST8_REG) & 0xF0) >> 4;
--    switch (revision) {
--      case 1: revision = 0;    break;
--      case 2: revision = 1;    break;
--      case 4: revision = 2;    break;
--      case 8: revision = 3;    break;
--      default: revision = 255; break;
--    }
--    printk("scsi%d: Revision 0x%x\n",host->host_no,revision);
--
--    if ((revision == 0 || revision == 255) && (hostdata->options & (OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS)))
--    {
--      printk ("scsi%d: Disabling sync working and disconnect/reselect\n",
--                                                      host->host_no);
--      hostdata->options &= ~(OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS);
--    }
--
--    /*
--     * On NCR53c700 series chips, DCNTL controls the SCSI clock divisor,
--     * on 800 series chips, it allows for a totem-pole IRQ driver.
--     * NOTE saved_dcntl currently overwritten in init function.
--     * The value read here may be garbage anyway, MVME16x board at least
--     * does not initialise chip if kernel arrived via tftp.
--     */
--
--    hostdata->saved_dcntl = NCR53c7x0_read8(DCNTL_REG);
--
--    /*
--     * DMODE controls DMA burst length, and on 700 series chips,
--     * 286 mode and bus width  
--     * NOTE:  On MVME16x, chip may have been reset, so this could be a
--     * power-on/reset default value.
--     */
--    hostdata->saved_dmode = NCR53c7x0_read8(hostdata->dmode);
--
--    /* 
--     * Now that burst length and enabled/disabled status is known, 
--     * clue the user in on it.  
--     */
--   
--    ccf = clock_to_ccf_710 (expected_clock);
--
--    for (i = 0; i < 16; ++i) 
--      hostdata->cmd_allocated[i] = 0;
--
--    if (hostdata->init_save_regs)
--      hostdata->init_save_regs (host);
--    if (hostdata->init_fixup)
--      hostdata->init_fixup (host);
--
--    if (!the_template) {
--      the_template = host->hostt;
--      first_host = host;
--    }
--
--    /* 
--     * Linux SCSI drivers have always been plagued with initialization 
--     * problems - some didn't work with the BIOS disabled since they expected
--     * initialization from it, some didn't work when the networking code
--     * was enabled and registers got scrambled, etc.
--     *
--     * To avoid problems like this, in the future, we will do a soft 
--     * reset on the SCSI chip, taking it back to a sane state.
--     */
--
--    hostdata->soft_reset (host);
--
--#if 1
--    hostdata->debug_count_limit = -1;
--#else
--    hostdata->debug_count_limit = 1;
--#endif
--    hostdata->intrs = -1;
--    hostdata->resets = -1;
--    memcpy ((void *) hostdata->synchronous_want, (void *) sdtr_message, 
--      sizeof (hostdata->synchronous_want));
--
--    NCR53c7x0_driver_init (host);
--
--    if (request_irq(host->irq, NCR53c7x0_intr, IRQF_SHARED, "53c7xx", host))
--    {
--      printk("scsi%d : IRQ%d not free, detaching\n",
--              host->host_no, host->irq);
--      goto err_unregister;
--    } 
--
--    if ((hostdata->run_tests && hostdata->run_tests(host) == -1) ||
--        (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) {
--      /* XXX Should disable interrupts, etc. here */
--      goto err_free_irq;
--    } else {
--      if (host->io_port)  {
--          host->n_io_port = 128;
--          if (!request_region (host->io_port, host->n_io_port, "ncr53c7xx"))
--              goto err_free_irq;
--      }
--    }
--    
--    if (NCR53c7x0_read8 (SBCL_REG) & SBCL_BSY) {
--      printk ("scsi%d : bus wedge, doing SCSI reset\n", host->host_no);
--      hard_reset (host);
--    }
--    return 0;
--
-- err_free_irq:
--    free_irq(host->irq,  NCR53c7x0_intr);
-- err_unregister:
--    scsi_unregister(host);
--    return -1;
--}
+diff -Nurb linux-2.6.22-590/.config.orig linux-2.6.22-570/.config.orig
+--- linux-2.6.22-590/.config.orig      2008-01-23 19:16:18.000000000 -0500
++++ linux-2.6.22-570/.config.orig      1969-12-31 19:00:00.000000000 -0500
+@@ -1,1693 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.22-prep
+-# Fri Dec 21 15:54:46 2007
+-#
+-CONFIG_X86_32=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_CLOCKSOURCE_WATCHDOG=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+-CONFIG_LOCKDEP_SUPPORT=y
+-CONFIG_STACKTRACE_SUPPORT=y
+-CONFIG_SEMAPHORE_SLEEPERS=y
+-CONFIG_X86=y
+-CONFIG_MMU=y
+-CONFIG_ZONE_DMA=y
+-CONFIG_QUICKLIST=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_GENERIC_IOMAP=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_DMI=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 -
--/* 
-- * Function : int ncr53c7xx_init(struct scsi_host_template *tpnt, int board, int chip,
-- *    unsigned long base, int io_port, int irq, int dma, long long options,
-- *    int clock);
-- *
-- * Purpose : initializes a NCR53c7,8x0 based on base addresses,
-- *    IRQ, and DMA channel.   
-- *    
-- * Inputs : tpnt - Template for this SCSI adapter, board - board level
-- *    product, chip - 710
-- * 
-- * Returns : 0 on success, -1 on failure.
-- *
-- */
--
--int 
--ncr53c7xx_init (struct scsi_host_template *tpnt, int board, int chip,
--    unsigned long base, int io_port, int irq, int dma, 
--    long long options, int clock)
--{
--    struct Scsi_Host *instance;
--    struct NCR53c7x0_hostdata *hostdata;
--    char chip_str[80];
--    int script_len = 0, dsa_len = 0, size = 0, max_cmd_size = 0,
--      schedule_size = 0, ok = 0;
--    void *tmp;
--    unsigned long page;
--
--    switch (chip) {
--    case 710:
--    case 770:
--      schedule_size = (tpnt->can_queue + 1) * 8 /* JUMP instruction size */;
--      script_len = NCR53c7xx_script_len;
--      dsa_len = NCR53c7xx_dsa_len;
--      options |= OPTION_INTFLY;
--      sprintf (chip_str, "NCR53c%d", chip);
--      break;
--    default:
--      printk("scsi-ncr53c7xx : unsupported SCSI chip %d\n", chip);
--      return -1;
--    }
--
--    printk("scsi-ncr53c7xx : %s at memory 0x%lx, io 0x%x, irq %d",
--      chip_str, base, io_port, irq);
--    if (dma == DMA_NONE)
--      printk("\n");
--    else 
--      printk(", dma %d\n", dma);
--
--    if (options & OPTION_DEBUG_PROBE_ONLY) {
--      printk ("scsi-ncr53c7xx : probe only enabled, aborting initialization\n");
--      return -1;
--    }
--
--    max_cmd_size = sizeof(struct NCR53c7x0_cmd) + dsa_len +
--      /* Size of dynamic part of command structure : */
--      2 * /* Worst case : we don't know if we need DATA IN or DATA out */
--              ( 2 * /* Current instructions per scatter/gather segment */ 
--                tpnt->sg_tablesize + 
--                  3 /* Current startup / termination required per phase */
--              ) *
--      8 /* Each instruction is eight bytes */;
--
--    /* Allocate fixed part of hostdata, dynamic part to hold appropriate
--       SCSI SCRIPT(tm) plus a single, maximum-sized NCR53c7x0_cmd structure.
--
--       We need a NCR53c7x0_cmd structure for scan_scsis() when we are 
--       not loaded as a module, and when we're loaded as a module, we 
--       can't use a non-dynamically allocated structure because modules
--       are vmalloc()'d, which can allow structures to cross page 
--       boundaries and breaks our physical/virtual address assumptions
--       for DMA.
--
--       So, we stick it past the end of our hostdata structure.
--
--       ASSUMPTION : 
--               Regardless of how many simultaneous SCSI commands we allow,
--       the probe code only executes a _single_ instruction at a time,
--       so we only need one here, and don't need to allocate NCR53c7x0_cmd
--       structures for each target until we are no longer in scan_scsis
--       and kmalloc() has become functional (memory_init() happens 
--       after all device driver initialization).
--    */
--
--    size = sizeof(struct NCR53c7x0_hostdata) + script_len + 
--    /* Note that alignment will be guaranteed, since we put the command
--       allocated at probe time after the fixed-up SCSI script, which 
--       consists of 32 bit words, aligned on a 32 bit boundary.  But
--       on a 64bit machine we need 8 byte alignment for hostdata->free, so
--       we add in another 4 bytes to take care of potential misalignment
--       */
--      (sizeof(void *) - sizeof(u32)) + max_cmd_size + schedule_size;
--
--    page = __get_free_pages(GFP_ATOMIC,1);
--    if(page==0)
--    {
--      printk(KERN_ERR "53c7xx: out of memory.\n");
--      return -ENOMEM;
--    }
--#ifdef FORCE_DSA_ALIGNMENT
--    /*
--     * 53c710 rev.0 doesn't have an add-with-carry instruction.
--     * Ensure we allocate enough memory to force DSA alignment.
--    */
--    size += 256;
--#endif
--    /* Size should be < 8K, so we can fit it in two pages. */
--    if (size > 8192) {
--      printk(KERN_ERR "53c7xx: hostdata > 8K\n");
--      return -1;
--    }
--
--    instance = scsi_register (tpnt, 4);
--    if (!instance)
--    {
--        free_page(page);
--      return -1;
--    }
--    instance->hostdata[0] = page;
--    memset((void *)instance->hostdata[0], 0, 8192);
--    cache_push(virt_to_phys((void *)(instance->hostdata[0])), 8192);
--    cache_clear(virt_to_phys((void *)(instance->hostdata[0])), 8192);
--    kernel_set_cachemode((void *)instance->hostdata[0], 8192, IOMAP_NOCACHE_SER);
--
--    /* FIXME : if we ever support an ISA NCR53c7xx based board, we
--       need to check if the chip is running in a 16 bit mode, and if so 
--       unregister it if it is past the 16M (0x1000000) mark */
--
--    hostdata = (struct NCR53c7x0_hostdata *)instance->hostdata[0];
--    hostdata->size = size;
--    hostdata->script_count = script_len / sizeof(u32);
--    hostdata->board = board;
--    hostdata->chip = chip;
--
--    /*
--     * Being memory mapped is more desirable, since 
--     *
--     * - Memory accesses may be faster.
--     *
--     * - The destination and source address spaces are the same for 
--     *         all instructions, meaning we don't have to twiddle dmode or 
--     *         any other registers.
--     *
--     * So, we try for memory mapped, and if we don't get it,
--     * we go for port mapped, and that failing we tell the user
--     * it can't work.
--     */
--
--    if (base) {
--      instance->base = base;
--      /* Check for forced I/O mapping */
--      if (!(options & OPTION_IO_MAPPED)) {
--          options |= OPTION_MEMORY_MAPPED;
--          ok = 1;
--      }
--    } else {
--      options &= ~OPTION_MEMORY_MAPPED;
--    }
--
--    if (io_port) {
--      instance->io_port = io_port;
--      options |= OPTION_IO_MAPPED;
--      ok = 1;
--    } else {
--      options &= ~OPTION_IO_MAPPED;
--    }
--
--    if (!ok) {
--      printk ("scsi%d : not initializing, no I/O or memory mapping known \n",
--          instance->host_no);
--      scsi_unregister (instance);
--      return -1;
--    }
--    instance->irq = irq;
--    instance->dma_channel = dma;
--
--    hostdata->options = options;
--    hostdata->dsa_len = dsa_len;
--    hostdata->max_cmd_size = max_cmd_size;
--    hostdata->num_cmds = 1;
--    hostdata->scsi_clock = clock;
--    /* Initialize single command */
--    tmp = (hostdata->script + hostdata->script_count);
--#ifdef FORCE_DSA_ALIGNMENT
--    {
--      void *t = ROUNDUP(tmp, void *);
--      if (((u32)t & 0xff) > CmdPageStart)
--          t = (void *)((u32)t + 255);
--      t = (void *)(((u32)t & ~0xff) + CmdPageStart);
--        hostdata->free = t;
--#if 0
--      printk ("scsi: Registered size increased by 256 to %d\n", size);
--      printk ("scsi: CmdPageStart = 0x%02x\n", CmdPageStart);
--      printk ("scsi: tmp = 0x%08x, hostdata->free set to 0x%08x\n",
--                      (u32)tmp, (u32)t);
--#endif
--    }
--#else
--    hostdata->free = ROUNDUP(tmp, void *);
--#endif
--    hostdata->free->real = tmp;
--    hostdata->free->size = max_cmd_size;
--    hostdata->free->free = NULL;
--    hostdata->free->next = NULL;
--    hostdata->extra_allocate = 0;
+-#
+-# Code maturity level options
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_LOCK_KERNEL=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
 -
--    /* Allocate command start code space */
--    hostdata->schedule = (chip == 700 || chip == 70066) ?
--      NULL : (u32 *) ((char *)hostdata->free + max_cmd_size);
+-#
+-# General setup
+-#
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_USER_NS is not set
+-# CONFIG_AUDIT is not set
+-CONFIG_IKCONFIG=y
+-CONFIG_IKCONFIG_PROC=y
+-CONFIG_LOG_BUF_SHIFT=18
+-CONFIG_OOM_PANIC=y
+-# CONFIG_CONTAINER_DEBUG is not set
+-# CONFIG_CPUSETS is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_CONTAINER_CPUACCT is not set
+-# CONFIG_CONTAINER_NS is not set
+-# CONFIG_RELAY is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+-CONFIG_SYSCTL=y
+-# CONFIG_EMBEDDED is not set
+-CONFIG_UID16=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-# 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_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-CONFIG_PROC_SMAPS=y
+-CONFIG_PROC_CLEAR_REFS=y
+-CONFIG_PROC_PAGEMAP=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_PAGE_GROUP_BY_MOBILITY=y
 -
--/* 
-- * For diagnostic purposes, we don't really care how fast things blaze.
-- * For profiling, we want to access the 800ns resolution system clock,
-- * using a 'C' call on the host processor.
-- *
-- * Therefore, there's no need for the NCR chip to directly manipulate
-- * this data, and we should put it wherever is most convenient for 
-- * Linux.
-- */
--    if (track_events) 
--      hostdata->events = (struct NCR53c7x0_event *) (track_events ? 
--          vmalloc (sizeof (struct NCR53c7x0_event) * track_events) : NULL);
--    else
--      hostdata->events = NULL;
+-#
+-# Loadable module support
+-#
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-CONFIG_MODULE_FORCE_UNLOAD=y
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_STOP_MACHINE=y
 -
--    if (hostdata->events) {
--      memset ((void *) hostdata->events, 0, sizeof(struct NCR53c7x0_event) *
--          track_events);      
--      hostdata->event_size = track_events;
--      hostdata->event_index = 0;
--    } else 
--      hostdata->event_size = 0;
+-#
+-# Block layer
+-#
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
 -
--    return NCR53c7x0_init(instance);
--}
+-#
+-# 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"
 -
+-#
+-# Processor type and features
+-#
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_SMP=y
+-# CONFIG_X86_PC is not set
+-# CONFIG_X86_ELAN is not set
+-# CONFIG_X86_VOYAGER is not set
+-# CONFIG_X86_NUMAQ is not set
+-# CONFIG_X86_SUMMIT is not set
+-# CONFIG_X86_BIGSMP is not set
+-# CONFIG_X86_VISWS is not set
+-CONFIG_X86_GENERICARCH=y
+-# CONFIG_X86_ES7000 is not set
+-# CONFIG_PARAVIRT is not set
+-CONFIG_X86_CYCLONE_TIMER=y
+-# CONFIG_M386 is not set
+-# CONFIG_M486 is not set
+-# CONFIG_M586 is not set
+-# CONFIG_M586TSC is not set
+-# CONFIG_M586MMX is not set
+-# CONFIG_M686 is not set
+-# CONFIG_MPENTIUMII is not set
+-CONFIG_MPENTIUMIII=y
+-# CONFIG_MPENTIUMM is not set
+-# CONFIG_MCORE2 is not set
+-# CONFIG_MPENTIUM4 is not set
+-# CONFIG_MK6 is not set
+-# CONFIG_MK7 is not set
+-# CONFIG_MK8 is not set
+-# CONFIG_MCRUSOE is not set
+-# CONFIG_MEFFICEON is not set
+-# CONFIG_MWINCHIPC6 is not set
+-# CONFIG_MWINCHIP2 is not set
+-# CONFIG_MWINCHIP3D is not set
+-# CONFIG_MGEODEGX1 is not set
+-# CONFIG_MGEODE_LX is not set
+-# CONFIG_MCYRIXIII is not set
+-# CONFIG_MVIAC3_2 is not set
+-# CONFIG_MVIAC7 is not set
+-CONFIG_X86_GENERIC=y
+-CONFIG_X86_CMPXCHG=y
+-CONFIG_X86_L1_CACHE_SHIFT=7
+-CONFIG_X86_XADD=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_X86_WP_WORKS_OK=y
+-CONFIG_X86_INVLPG=y
+-CONFIG_X86_BSWAP=y
+-CONFIG_X86_POPAD_OK=y
+-CONFIG_X86_GOOD_APIC=y
+-CONFIG_X86_INTEL_USERCOPY=y
+-CONFIG_X86_USE_PPRO_CHECKSUM=y
+-CONFIG_X86_TSC=y
+-CONFIG_X86_CMOV=y
+-CONFIG_X86_MINIMUM_CPU_MODEL=4
+-CONFIG_HPET_TIMER=y
+-CONFIG_HPET_EMULATE_RTC=y
+-CONFIG_NR_CPUS=32
+-CONFIG_SCHED_SMT=y
+-CONFIG_SCHED_MC=y
+-# CONFIG_PREEMPT_NONE is not set
+-CONFIG_PREEMPT_VOLUNTARY=y
+-# CONFIG_PREEMPT is not set
+-CONFIG_PREEMPT_BKL=y
+-CONFIG_X86_LOCAL_APIC=y
+-CONFIG_X86_IO_APIC=y
+-CONFIG_X86_MCE=y
+-CONFIG_X86_MCE_NONFATAL=y
+-CONFIG_X86_MCE_P4THERMAL=y
+-CONFIG_VM86=y
+-# CONFIG_TOSHIBA is not set
+-# CONFIG_I8K is not set
+-# CONFIG_X86_REBOOTFIXUPS is not set
+-CONFIG_MICROCODE=y
+-CONFIG_MICROCODE_OLD_INTERFACE=y
+-CONFIG_X86_MSR=y
+-CONFIG_X86_CPUID=y
 -
--/* 
-- * Function : static void NCR53c7x0_init_fixup (struct Scsi_Host *host)
-- *
-- * Purpose :  copy and fixup the SCSI SCRIPTS(tm) code for this device.
-- *
-- * Inputs : host - pointer to this host adapter's structure
-- *
-- */
--
--static void 
--NCR53c7x0_init_fixup (struct Scsi_Host *host) {
--    NCR53c7x0_local_declare();
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    unsigned char tmp;
--    int i, ncr_to_memory, memory_to_ncr;
--    u32 base;
--    NCR53c7x0_local_setup(host);
--
--
--    /* XXX - NOTE : this code MUST be made endian aware */
--    /*  Copy code into buffer that was allocated at detection time.  */
--    memcpy ((void *) hostdata->script, (void *) SCRIPT, 
--      sizeof(SCRIPT));
--    /* Fixup labels */
--    for (i = 0; i < PATCHES; ++i) 
--      hostdata->script[LABELPATCHES[i]] += 
--          virt_to_bus(hostdata->script);
--    /* Fixup addresses of constants that used to be EXTERNAL */
--
--    patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_abort, 
--      virt_to_bus(&(hostdata->NCR53c7xx_msg_abort)));
--    patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_reject, 
--      virt_to_bus(&(hostdata->NCR53c7xx_msg_reject)));
--    patch_abs_32 (hostdata->script, 0, NCR53c7xx_zero, 
--      virt_to_bus(&(hostdata->NCR53c7xx_zero)));
--    patch_abs_32 (hostdata->script, 0, NCR53c7xx_sink, 
--      virt_to_bus(&(hostdata->NCR53c7xx_sink)));
--    patch_abs_32 (hostdata->script, 0, NOP_insn,
--      virt_to_bus(&(hostdata->NOP_insn)));
--    patch_abs_32 (hostdata->script, 0, schedule,
--      virt_to_bus((void *) hostdata->schedule));
--
--    /* Fixup references to external variables: */
--    for (i = 0; i < EXTERNAL_PATCHES_LEN; ++i)
--       hostdata->script[EXTERNAL_PATCHES[i].offset] +=
--         virt_to_bus(EXTERNAL_PATCHES[i].address);
--
--    /* 
--     * Fixup absolutes set at boot-time.
--     * 
--     * All non-code absolute variables suffixed with "dsa_" and "int_"
--     * are constants, and need no fixup provided the assembler has done 
--     * it for us (I don't know what the "real" NCR assembler does in 
--     * this case, my assembler does the right magic).
--     */
--
--    patch_abs_rwri_data (hostdata->script, 0, dsa_save_data_pointer, 
--      Ent_dsa_code_save_data_pointer - Ent_dsa_zero);
--    patch_abs_rwri_data (hostdata->script, 0, dsa_restore_pointers,
--      Ent_dsa_code_restore_pointers - Ent_dsa_zero);
--    patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect,
--      Ent_dsa_code_check_reselect - Ent_dsa_zero);
--
--    /*
--     * Just for the hell of it, preserve the settings of 
--     * Burst Length and Enable Read Line bits from the DMODE 
--     * register.  Make sure SCRIPTS start automagically.
--     */
--
--#if defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)
--    /* We know better what we want than 16xBug does! */
--    tmp = DMODE_10_BL_8 | DMODE_10_FC2;
--#else
--    tmp = NCR53c7x0_read8(DMODE_REG_10);
--    tmp &= (DMODE_BL_MASK | DMODE_10_FC2 | DMODE_10_FC1 | DMODE_710_PD |
--                                                              DMODE_710_UO);
--#endif
+-#
+-# Firmware Drivers
+-#
+-# CONFIG_EDD is not set
+-# CONFIG_DELL_RBU is not set
+-# CONFIG_DCDBAS is not set
+-# CONFIG_NOHIGHMEM is not set
+-CONFIG_HIGHMEM4G=y
+-# CONFIG_HIGHMEM64G is not set
+-CONFIG_PAGE_OFFSET=0xC0000000
+-CONFIG_HIGHMEM=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-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=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_NR_QUICK=1
+-# CONFIG_HIGHPTE is not set
+-# CONFIG_MATH_EMULATION is not set
+-CONFIG_MTRR=y
+-# CONFIG_EFI is not set
+-# CONFIG_IRQBALANCE is not set
+-CONFIG_SECCOMP=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-CONFIG_KEXEC=y
+-# CONFIG_CRASH_DUMP is not set
+-CONFIG_PHYSICAL_START=0x100000
+-# CONFIG_RELOCATABLE is not set
+-CONFIG_PHYSICAL_ALIGN=0x100000
+-# CONFIG_HOTPLUG_CPU is not set
+-CONFIG_COMPAT_VDSO=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 -
--    if (!(hostdata->options & OPTION_MEMORY_MAPPED)) {
--      base = (u32) host->io_port;
--      memory_to_ncr = tmp|DMODE_800_DIOM;
--      ncr_to_memory = tmp|DMODE_800_SIOM;
--    } else {
--      base = virt_to_bus((void *)host->base);
--      memory_to_ncr = ncr_to_memory = tmp;
--    }
--
--    /* SCRATCHB_REG_10 == SCRATCHA_REG_800, as it happens */
--    patch_abs_32 (hostdata->script, 0, addr_scratch, base + SCRATCHA_REG_800);
--    patch_abs_32 (hostdata->script, 0, addr_temp, base + TEMP_REG);
--    patch_abs_32 (hostdata->script, 0, addr_dsa, base + DSA_REG);
--
--    /*
--     * I needed some variables in the script to be accessible to 
--     * both the NCR chip and the host processor. For these variables,
--     * I made the arbitrary decision to store them directly in the 
--     * hostdata structure rather than in the RELATIVE area of the 
--     * SCRIPTS.
--     */
--    
+-#
+-# Power management options (ACPI, APM)
+-#
+-CONFIG_PM=y
+-CONFIG_PM_LEGACY=y
+-# CONFIG_PM_DEBUG is not set
+-CONFIG_PM_SYSFS_DEPRECATED=y
 -
--    patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_memory, tmp);
--    patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_ncr, memory_to_ncr);
--    patch_abs_rwri_data (hostdata->script, 0, dmode_ncr_to_memory, ncr_to_memory);
--
--    patch_abs_32 (hostdata->script, 0, msg_buf, 
--      virt_to_bus((void *)&(hostdata->msg_buf)));
--    patch_abs_32 (hostdata->script, 0, reconnect_dsa_head, 
--      virt_to_bus((void *)&(hostdata->reconnect_dsa_head)));
--    patch_abs_32 (hostdata->script, 0, addr_reconnect_dsa_head, 
--      virt_to_bus((void *)&(hostdata->addr_reconnect_dsa_head)));
--    patch_abs_32 (hostdata->script, 0, reselected_identify, 
--      virt_to_bus((void *)&(hostdata->reselected_identify)));
--/* reselected_tag is currently unused */
--#if 0
--    patch_abs_32 (hostdata->script, 0, reselected_tag, 
--      virt_to_bus((void *)&(hostdata->reselected_tag)));
--#endif
+-#
+-# ACPI (Advanced Configuration and Power Interface) Support
+-#
+-CONFIG_ACPI=y
+-CONFIG_ACPI_PROCFS=y
+-CONFIG_ACPI_AC=y
+-CONFIG_ACPI_BATTERY=y
+-CONFIG_ACPI_BUTTON=y
+-CONFIG_ACPI_FAN=y
+-# CONFIG_ACPI_DOCK is not set
+-CONFIG_ACPI_PROCESSOR=y
+-CONFIG_ACPI_THERMAL=y
+-# CONFIG_ACPI_ASUS is not set
+-# CONFIG_ACPI_TOSHIBA is not set
+-CONFIG_ACPI_BLACKLIST_YEAR=2001
+-CONFIG_ACPI_DEBUG=y
+-# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
+-CONFIG_ACPI_EC=y
+-CONFIG_ACPI_POWER=y
+-CONFIG_ACPI_SYSTEM=y
+-CONFIG_X86_PM_TIMER=y
+-# CONFIG_ACPI_CONTAINER is not set
+-# CONFIG_ACPI_SBS is not set
+-# CONFIG_APM is not set
 -
--    patch_abs_32 (hostdata->script, 0, test_dest, 
--      virt_to_bus((void*)&hostdata->test_dest));
--    patch_abs_32 (hostdata->script, 0, test_src, 
--      virt_to_bus(&hostdata->test_source));
--    patch_abs_32 (hostdata->script, 0, saved_dsa,
--      virt_to_bus((void *)&hostdata->saved2_dsa));
--    patch_abs_32 (hostdata->script, 0, emulfly,
--      virt_to_bus((void *)&hostdata->emulated_intfly));
--
--    patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect, 
--      (unsigned char)(Ent_dsa_code_check_reselect - Ent_dsa_zero));
--
--/* These are for event logging; the ncr_event enum contains the 
--   actual interrupt numbers. */
--#ifdef A_int_EVENT_SELECT
--   patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT, (u32) EVENT_SELECT);
--#endif
--#ifdef A_int_EVENT_DISCONNECT
--   patch_abs_32 (hostdata->script, 0, int_EVENT_DISCONNECT, (u32) EVENT_DISCONNECT);
--#endif
--#ifdef A_int_EVENT_RESELECT
--   patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT, (u32) EVENT_RESELECT);
--#endif
--#ifdef A_int_EVENT_COMPLETE
--   patch_abs_32 (hostdata->script, 0, int_EVENT_COMPLETE, (u32) EVENT_COMPLETE);
--#endif
--#ifdef A_int_EVENT_IDLE
--   patch_abs_32 (hostdata->script, 0, int_EVENT_IDLE, (u32) EVENT_IDLE);
--#endif
--#ifdef A_int_EVENT_SELECT_FAILED
--   patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT_FAILED, 
--      (u32) EVENT_SELECT_FAILED);
--#endif
--#ifdef A_int_EVENT_BEFORE_SELECT
--   patch_abs_32 (hostdata->script, 0, int_EVENT_BEFORE_SELECT,
--      (u32) EVENT_BEFORE_SELECT);
--#endif
--#ifdef A_int_EVENT_RESELECT_FAILED
--   patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT_FAILED, 
--      (u32) EVENT_RESELECT_FAILED);
--#endif
+-#
+-# 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 is not set
+-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+-# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+-CONFIG_CPU_FREQ_GOV_USERSPACE=y
+-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+-# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
 -
--    /*
--     * Make sure the NCR and Linux code agree on the location of 
--     * certain fields.
--     */
--
--    hostdata->E_accept_message = Ent_accept_message;
--    hostdata->E_command_complete = Ent_command_complete;              
--    hostdata->E_cmdout_cmdout = Ent_cmdout_cmdout;
--    hostdata->E_data_transfer = Ent_data_transfer;
--    hostdata->E_debug_break = Ent_debug_break;        
--    hostdata->E_dsa_code_template = Ent_dsa_code_template;
--    hostdata->E_dsa_code_template_end = Ent_dsa_code_template_end;
--    hostdata->E_end_data_transfer = Ent_end_data_transfer;
--    hostdata->E_initiator_abort = Ent_initiator_abort;
--    hostdata->E_msg_in = Ent_msg_in;
--    hostdata->E_other_transfer = Ent_other_transfer;
--    hostdata->E_other_in = Ent_other_in;
--    hostdata->E_other_out = Ent_other_out;
--    hostdata->E_reject_message = Ent_reject_message;
--    hostdata->E_respond_message = Ent_respond_message;
--    hostdata->E_select = Ent_select;
--    hostdata->E_select_msgout = Ent_select_msgout;
--    hostdata->E_target_abort = Ent_target_abort;
--#ifdef Ent_test_0
--    hostdata->E_test_0 = Ent_test_0;
--#endif
--    hostdata->E_test_1 = Ent_test_1;
--    hostdata->E_test_2 = Ent_test_2;
--#ifdef Ent_test_3
--    hostdata->E_test_3 = Ent_test_3;
--#endif
--    hostdata->E_wait_reselect = Ent_wait_reselect;
--    hostdata->E_dsa_code_begin = Ent_dsa_code_begin;
--
--    hostdata->dsa_cmdout = A_dsa_cmdout;
--    hostdata->dsa_cmnd = A_dsa_cmnd;
--    hostdata->dsa_datain = A_dsa_datain;
--    hostdata->dsa_dataout = A_dsa_dataout;
--    hostdata->dsa_end = A_dsa_end;                    
--    hostdata->dsa_msgin = A_dsa_msgin;
--    hostdata->dsa_msgout = A_dsa_msgout;
--    hostdata->dsa_msgout_other = A_dsa_msgout_other;
--    hostdata->dsa_next = A_dsa_next;
--    hostdata->dsa_select = A_dsa_select;
--    hostdata->dsa_start = Ent_dsa_code_template - Ent_dsa_zero;
--    hostdata->dsa_status = A_dsa_status;
--    hostdata->dsa_jump_dest = Ent_dsa_code_fix_jump - Ent_dsa_zero + 
--      8 /* destination operand */;
--
--    /* sanity check */
--    if (A_dsa_fields_start != Ent_dsa_code_template_end - 
--      Ent_dsa_zero) 
--      printk("scsi%d : NCR dsa_fields start is %d not %d\n",
--          host->host_no, A_dsa_fields_start, Ent_dsa_code_template_end - 
--          Ent_dsa_zero);
--
--    printk("scsi%d : NCR code relocated to 0x%lx (virt 0x%p)\n", host->host_no,
--      virt_to_bus(hostdata->script), hostdata->script);
--}
+-#
+-# CPUFreq processor drivers
+-#
+-CONFIG_X86_ACPI_CPUFREQ=y
+-# CONFIG_X86_POWERNOW_K6 is not set
+-# CONFIG_X86_POWERNOW_K7 is not set
+-CONFIG_X86_POWERNOW_K8=y
+-CONFIG_X86_POWERNOW_K8_ACPI=y
+-# CONFIG_X86_GX_SUSPMOD is not set
+-# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+-# CONFIG_X86_SPEEDSTEP_ICH is not set
+-# CONFIG_X86_SPEEDSTEP_SMI is not set
+-# CONFIG_X86_P4_CLOCKMOD is not set
+-# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+-# CONFIG_X86_LONGRUN is not set
+-# CONFIG_X86_LONGHAUL is not set
+-# CONFIG_X86_E_POWERSAVER is not set
 -
--/*
-- * Function : static int NCR53c7xx_run_tests (struct Scsi_Host *host)
-- *
-- * Purpose : run various verification tests on the NCR chip, 
-- *    including interrupt generation, and proper bus mastering
-- *    operation.
-- * 
-- * Inputs : host - a properly initialized Scsi_Host structure
-- *
-- * Preconditions : the NCR chip must be in a halted state.
-- *
-- * Returns : 0 if all tests were successful, -1 on error.
-- * 
-- */
+-#
+-# shared options
+-#
+-CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y
+-# CONFIG_X86_SPEEDSTEP_LIB is not set
 -
--static int 
--NCR53c7xx_run_tests (struct Scsi_Host *host) {
--    NCR53c7x0_local_declare();
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    unsigned long timeout;
--    u32 start;
--    int failed, i;
--    unsigned long flags;
--    NCR53c7x0_local_setup(host);
+-#
+-# CPU idle PM support
+-#
+-# CONFIG_CPU_IDLE is not set
 -
--    /* The NCR chip _must_ be idle to run the test scripts */
+-#
+-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+-#
+-CONFIG_PCI=y
+-# CONFIG_PCI_GOBIOS is not set
+-# CONFIG_PCI_GOMMCONFIG is not set
+-# CONFIG_PCI_GODIRECT is not set
+-CONFIG_PCI_GOANY=y
+-CONFIG_PCI_BIOS=y
+-CONFIG_PCI_DIRECT=y
+-CONFIG_PCI_MMCONFIG=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-CONFIG_PCI_MSI=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_HT_IRQ is not set
+-CONFIG_ISA_DMA_API=y
+-# CONFIG_ISA is not set
+-# CONFIG_MCA is not set
+-# CONFIG_SCx200 is not set
 -
--    local_irq_save(flags);
--    if (!hostdata->idle) {
--      printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);
--      local_irq_restore(flags);
--      return -1;
--    }
--
--    /* 
--     * Check for functional interrupts, this could work as an
--     * autoprobe routine.
--     */
--
--    if ((hostdata->options & OPTION_DEBUG_TEST1) && 
--          hostdata->state != STATE_DISABLED) {
--      hostdata->idle = 0;
--      hostdata->test_running = 1;
--      hostdata->test_completed = -1;
--      hostdata->test_dest = 0;
--      hostdata->test_source = 0xdeadbeef;
--      start = virt_to_bus (hostdata->script) + hostdata->E_test_1;
--      hostdata->state = STATE_RUNNING;
--      printk ("scsi%d : test 1", host->host_no);
--      NCR53c7x0_write32 (DSP_REG, start);
--      if (hostdata->options & OPTION_DEBUG_TRACE)
--          NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM |
--                                              DCNTL_STD);
--      printk (" started\n");
--      local_irq_restore(flags);
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
 -
--      /* 
--       * This is currently a .5 second timeout, since (in theory) no slow 
--       * board will take that long.  In practice, we've seen one 
--       * pentium which occassionally fails with this, but works with 
--       * 10 times as much?
--       */
+-#
+-# Executable file formats
+-#
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_AOUT is not set
+-# CONFIG_BINFMT_MISC is not set
 -
--      timeout = jiffies + 5 * HZ / 10;
--      while ((hostdata->test_completed == -1) && time_before(jiffies, timeout))
--              barrier();
--
--      failed = 1;
--      if (hostdata->test_completed == -1)
--          printk ("scsi%d : driver test 1 timed out%s\n",host->host_no ,
--              (hostdata->test_dest == 0xdeadbeef) ? 
--                  " due to lost interrupt.\n"
--                  "         Please verify that the correct IRQ is being used for your board,\n"
--                  : "");
--      else if (hostdata->test_completed != 1) 
--          printk ("scsi%d : test 1 bad interrupt value (%d)\n", 
--              host->host_no, hostdata->test_completed);
--      else 
--          failed = (hostdata->test_dest != 0xdeadbeef);
--
--      if (hostdata->test_dest != 0xdeadbeef) {
--          printk ("scsi%d : driver test 1 read 0x%x instead of 0xdeadbeef indicating a\n"
--                    "         probable cache invalidation problem.  Please configure caching\n"
--                  "         as write-through or disabled\n",
--              host->host_no, hostdata->test_dest);
--      }
--
--      if (failed) {
--          printk ("scsi%d : DSP = 0x%p (script at 0x%p, start at 0x%x)\n",
--              host->host_no, bus_to_virt(NCR53c7x0_read32(DSP_REG)),
--              hostdata->script, start);
--          printk ("scsi%d : DSPS = 0x%x\n", host->host_no,
--              NCR53c7x0_read32(DSPS_REG));
--          local_irq_restore(flags);
--          return -1;
--      }
--      hostdata->test_running = 0;
--    }
--
--    if ((hostdata->options & OPTION_DEBUG_TEST2) && 
--      hostdata->state != STATE_DISABLED) {
--      u32 dsa[48];
--      unsigned char identify = IDENTIFY(0, 0);
--      unsigned char cmd[6];
--      unsigned char data[36];
--      unsigned char status = 0xff;
--      unsigned char msg = 0xff;
--
--      cmd[0] = INQUIRY;
--      cmd[1] = cmd[2] = cmd[3] = cmd[5] = 0;
--      cmd[4] = sizeof(data); 
--
--      dsa[2] = 1;
--      dsa[3] = virt_to_bus(&identify);
--      dsa[4] = 6;
--      dsa[5] = virt_to_bus(&cmd);
--      dsa[6] = sizeof(data);
--      dsa[7] = virt_to_bus(&data);
--      dsa[8] = 1;
--      dsa[9] = virt_to_bus(&status);
--      dsa[10] = 1;
--      dsa[11] = virt_to_bus(&msg);
--
--      for (i = 0; i < 6; ++i) {
--#ifdef VALID_IDS
--          if (!hostdata->valid_ids[i])
--              continue;
--#endif
--          local_irq_disable();
--          if (!hostdata->idle) {
--              printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);
--              local_irq_restore(flags);
--              return -1;
--          }
--
--          /* 710: bit mapped scsi ID, async   */
--            dsa[0] = (1 << i) << 16;
--          hostdata->idle = 0;
--          hostdata->test_running = 2;
--          hostdata->test_completed = -1;
--          start = virt_to_bus(hostdata->script) + hostdata->E_test_2;
--          hostdata->state = STATE_RUNNING;
--          NCR53c7x0_write32 (DSA_REG, virt_to_bus(dsa));
--          NCR53c7x0_write32 (DSP_REG, start);
--          if (hostdata->options & OPTION_DEBUG_TRACE)
--              NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
--                              DCNTL_SSM | DCNTL_STD);
--          local_irq_restore(flags);
--
--          timeout = jiffies + 5 * HZ; /* arbitrary */
--          while ((hostdata->test_completed == -1) && time_before(jiffies, timeout))
--              barrier();
--
--          NCR53c7x0_write32 (DSA_REG, 0);
--
--          if (hostdata->test_completed == 2) {
--              data[35] = 0;
--              printk ("scsi%d : test 2 INQUIRY to target %d, lun 0 : %s\n",
--                  host->host_no, i, data + 8);
--              printk ("scsi%d : status ", host->host_no);
--              scsi_print_status (status);
--              printk ("\nscsi%d : message ", host->host_no);
--              spi_print_msg(&msg);
--              printk ("\n");
--          } else if (hostdata->test_completed == 3) {
--              printk("scsi%d : test 2 no connection with target %d\n",
--                  host->host_no, i);
--              if (!hostdata->idle) {
--                  printk("scsi%d : not idle\n", host->host_no);
--                  local_irq_restore(flags);
--                  return -1;
--              }
--          } else if (hostdata->test_completed == -1) {
--              printk ("scsi%d : test 2 timed out\n", host->host_no);
--              local_irq_restore(flags);
--              return -1;
--          } 
--          hostdata->test_running = 0;
--      }
--    }
+-#
+-# Networking
+-#
+-CONFIG_NET=y
 -
--    local_irq_restore(flags);
--    return 0;
--}
+-#
+-# Networking options
+-#
+-# CONFIG_NET_NS is not set
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# 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 is not set
+-# CONFIG_IP_PNP_RARP is not set
+-# 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 is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-CONFIG_INET_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IP_VS is not set
+-# CONFIG_ICMP_IPOD is not set
+-CONFIG_IPV6=y
+-# CONFIG_IPV6_PRIVACY is not set
+-# CONFIG_IPV6_ROUTER_PREF is not set
+-# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+-# CONFIG_INET6_AH is not set
+-# CONFIG_INET6_ESP is not set
+-# CONFIG_INET6_IPCOMP is not set
+-# CONFIG_IPV6_MIP6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET6_XFRM_MODE_TUNNEL=y
+-# CONFIG_INET6_XFRM_MODE_BEET is not set
+-# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+-CONFIG_IPV6_SIT=y
+-# CONFIG_IPV6_TUNNEL is not set
+-# CONFIG_IPV6_MULTIPLE_TABLES is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-CONFIG_NETFILTER=y
+-# CONFIG_NETFILTER_DEBUG is not set
 -
--/*
-- * Function : static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd)
-- *
-- * Purpose : copy the NCR53c8xx dsa structure into cmd's dsa buffer,
-- *    performing all necessary relocation.
-- *
-- * Inputs : cmd, a NCR53c7x0_cmd structure with a dsa area large
-- *    enough to hold the NCR53c8xx dsa.
-- */
+-#
+-# Core Netfilter Configuration
+-#
+-# CONFIG_NETFILTER_NETLINK is not set
+-CONFIG_NF_CONNTRACK_ENABLED=m
+-CONFIG_NF_CONNTRACK=m
+-# CONFIG_NF_CT_ACCT is not set
+-# CONFIG_NF_CONNTRACK_MARK is not set
+-# CONFIG_NF_CONNTRACK_EVENTS is not set
+-# CONFIG_NF_CT_PROTO_SCTP is not set
+-# CONFIG_NF_CONNTRACK_AMANDA is not set
+-# CONFIG_NF_CONNTRACK_FTP is not set
+-# CONFIG_NF_CONNTRACK_H323 is not set
+-# CONFIG_NF_CONNTRACK_IRC is not set
+-# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+-# CONFIG_NF_CONNTRACK_PPTP is not set
+-# CONFIG_NF_CONNTRACK_SANE is not set
+-# CONFIG_NF_CONNTRACK_SIP is not set
+-# CONFIG_NF_CONNTRACK_TFTP is not set
+-CONFIG_NETFILTER_XTABLES=m
+-# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+-# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+-# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+-# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+-# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+-# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+-# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+-# CONFIG_NETFILTER_XT_TARGET_SETXID is not set
+-# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+-# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+-# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+-# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+-# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+-# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+-# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+-# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+-# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+-# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+-# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+-# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+-# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+-# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+-# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+-# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+-# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+-# CONFIG_NETFILTER_XT_MATCH_STATE is not set
+-# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+-# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+-# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+-# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
 -
--static void 
--NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) {
--    Scsi_Cmnd *c = cmd->cmd;
--    struct Scsi_Host *host = c->device->host;
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    int i;
+-#
+-# IP: Netfilter Configuration
+-#
+-CONFIG_NF_CONNTRACK_IPV4=m
+-CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+-# CONFIG_IP_NF_QUEUE is not set
+-CONFIG_IP_NF_IPTABLES=m
+-# CONFIG_IP_NF_MATCH_IPRANGE is not set
+-# CONFIG_IP_NF_MATCH_TOS is not set
+-# CONFIG_IP_NF_MATCH_RECENT is not set
+-# CONFIG_IP_NF_MATCH_ECN is not set
+-# CONFIG_IP_NF_MATCH_AH is not set
+-# CONFIG_IP_NF_MATCH_TTL is not set
+-# CONFIG_IP_NF_MATCH_OWNER is not set
+-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+-CONFIG_IP_NF_FILTER=m
+-# CONFIG_IP_NF_TARGET_REJECT is not set
+-# CONFIG_IP_NF_TARGET_LOG is not set
+-# CONFIG_IP_NF_TARGET_ULOG is not set
+-CONFIG_NF_NAT=m
+-CONFIG_NF_NAT_NEEDED=y
+-# CONFIG_IP_NF_TARGET_MASQUERADE is not set
+-# CONFIG_IP_NF_TARGET_REDIRECT is not set
+-# CONFIG_IP_NF_TARGET_NETMAP is not set
+-# CONFIG_IP_NF_TARGET_SAME is not set
+-# CONFIG_NF_NAT_SNMP_BASIC is not set
+-# CONFIG_NF_NAT_FTP is not set
+-# CONFIG_NF_NAT_IRC is not set
+-# CONFIG_NF_NAT_TFTP is not set
+-# CONFIG_NF_NAT_AMANDA is not set
+-# CONFIG_NF_NAT_PPTP is not set
+-# CONFIG_NF_NAT_H323 is not set
+-# CONFIG_NF_NAT_SIP is not set
+-CONFIG_IP_NF_MANGLE=m
+-# CONFIG_IP_NF_TARGET_TOS is not set
+-# CONFIG_IP_NF_TARGET_ECN is not set
+-# CONFIG_IP_NF_TARGET_TTL is not set
+-# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+-# CONFIG_IP_NF_RAW is not set
+-# CONFIG_IP_NF_ARPTABLES is not set
+-# CONFIG_IP_NF_SET is not set
 -
--    memcpy (cmd->dsa, hostdata->script + (hostdata->E_dsa_code_template / 4),
--      hostdata->E_dsa_code_template_end - hostdata->E_dsa_code_template);
--
--    /* 
--     * Note : within the NCR 'C' code, dsa points to the _start_
--     * of the DSA structure, and _not_ the offset of dsa_zero within
--     * that structure used to facilitate shorter signed offsets
--     * for the 8 bit ALU.
--     * 
--     * The implications of this are that 
--     * 
--     * - 32 bit A_dsa_* absolute values require an additional 
--     *         dsa_zero added to their value to be correct, since they are 
--     *   relative to dsa_zero which is in essentially a separate
--     *   space from the code symbols.
--     *
--     * - All other symbols require no special treatment.
--     */
--
--    patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
--      dsa_temp_lun, c->device->lun);
--    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
--      dsa_temp_addr_next, virt_to_bus(&cmd->dsa_next_addr));
--    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
--      dsa_temp_next, virt_to_bus(cmd->dsa) + Ent_dsa_zero -
--      Ent_dsa_code_template + A_dsa_next);
--    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), 
--      dsa_temp_sync, virt_to_bus((void *)hostdata->sync[c->device->id].script));
--    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), 
--      dsa_sscf_710, virt_to_bus((void *)&hostdata->sync[c->device->id].sscf_710));
--    patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
--          dsa_temp_target, 1 << c->device->id);
--    /* XXX - new pointer stuff */
--    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
--      dsa_temp_addr_saved_pointer, virt_to_bus(&cmd->saved_data_pointer));
--    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
--      dsa_temp_addr_saved_residual, virt_to_bus(&cmd->saved_residual));
--    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
--      dsa_temp_addr_residual, virt_to_bus(&cmd->residual));
--
--    /*  XXX - new start stuff */
--
--    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
--      dsa_temp_addr_dsa_value, virt_to_bus(&cmd->dsa_addr));
--}
+-#
+-# IPv6: Netfilter Configuration (EXPERIMENTAL)
+-#
+-# CONFIG_NF_CONNTRACK_IPV6 is not set
+-# CONFIG_IP6_NF_QUEUE is not set
+-# CONFIG_IP6_NF_IPTABLES is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
 -
--/* 
-- * Function : run_process_issue_queue (void)
-- * 
-- * Purpose : insure that the coroutine is running and will process our 
-- *    request.  process_issue_queue_running is checked/set here (in an 
-- *    inline function) rather than in process_issue_queue itself to reduce 
-- *    the chances of stack overflow.
-- *
-- */
--
--static volatile int process_issue_queue_running = 0;
--
--static __inline__ void 
--run_process_issue_queue(void) {
--    unsigned long flags;
--    local_irq_save(flags);
--    if (!process_issue_queue_running) {
--      process_issue_queue_running = 1;
--        process_issue_queue(flags);
--      /* 
--         * process_issue_queue_running is cleared in process_issue_queue 
--       * once it can't do more work, and process_issue_queue exits with 
--       * interrupts disabled.
--       */
--    }
--    local_irq_restore(flags);
--}
+-#
+-# QoS and/or fair queueing
+-#
+-# CONFIG_NET_SCHED is not set
 -
--/*
-- * Function : static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int
-- *    result)
-- *
-- * Purpose : mark SCSI command as finished, OR'ing the host portion 
-- *    of the result word into the result field of the corresponding
-- *    Scsi_Cmnd structure, and removing it from the internal queues.
-- *
-- * Inputs : cmd - command, result - entire result field
-- *
-- * Preconditions : the        NCR chip should be in a halted state when 
-- *    abnormal_finished is run, since it modifies structures which
-- *    the NCR expects to have exclusive access to.
-- */
+-#
+-# Network testing
+-#
+-CONFIG_NET_PKTGEN=m
+-# CONFIG_NET_TCPPROBE is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
 -
--static void 
--abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) {
--    Scsi_Cmnd *c = cmd->cmd;
--    struct Scsi_Host *host = c->device->host;
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    unsigned long flags;
--    int left, found;
--    volatile struct NCR53c7x0_cmd * linux_search;
--    volatile struct NCR53c7x0_cmd * volatile *linux_prev;
--    volatile u32 *ncr_prev, *ncrcurrent, ncr_search;
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
 -
--#if 0
--    printk ("scsi%d: abnormal finished\n", host->host_no);
--#endif
+-#
+-# Device Drivers
+-#
 -
--    local_irq_save(flags);
--    found = 0;
--    /* 
--     * Traverse the NCR issue array until we find a match or run out 
--     * of instructions.  Instructions in the NCR issue array are 
--     * either JUMP or NOP instructions, which are 2 words in length.
--     */
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
 -
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+-CONFIG_CONNECTOR=m
+-# CONFIG_MTD is not set
 -
--    for (found = 0, left = host->can_queue, ncrcurrent = hostdata->schedule; 
--      left > 0; --left, ncrcurrent += 2)
--    {
--      if (issue_to_cmd (host, hostdata, (u32 *) ncrcurrent) == cmd) 
--      {
--          ncrcurrent[0] = hostdata->NOP_insn;
--          ncrcurrent[1] = 0xdeadbeef;
--          ++found;
--          break;
--      }
--    }
--      
--    /* 
--     * Traverse the NCR reconnect list of DSA structures until we find 
--     * a pointer to this dsa or have found too many command structures.  
--     * We let prev point at the next field of the previous element or 
--     * head of the list, so we don't do anything different for removing 
--     * the head element.  
--     */
--
--    for (left = host->can_queue,
--          ncr_search = hostdata->reconnect_dsa_head, 
--          ncr_prev = &hostdata->reconnect_dsa_head;
--      left >= 0 && ncr_search && 
--          ((char*)bus_to_virt(ncr_search) + hostdata->dsa_start) 
--              != (char *) cmd->dsa;
--      ncr_prev = (u32*) ((char*)bus_to_virt(ncr_search) + 
--          hostdata->dsa_next), ncr_search = *ncr_prev, --left);
--
--    if (left < 0) 
--      printk("scsi%d: loop detected in ncr reconncect list\n",
--          host->host_no);
--    else if (ncr_search) {
--      if (found)
--          printk("scsi%d: scsi %ld in ncr issue array and reconnect lists\n",
--              host->host_no, c->pid);
--      else {
--          volatile u32 * next = (u32 *) 
--              ((char *)bus_to_virt(ncr_search) + hostdata->dsa_next);
--          *ncr_prev = *next;
--/* If we're at the tail end of the issue queue, update that pointer too. */
--          found = 1;
--      }
--    }
--
--    /*
--     * Traverse the host running list until we find this command or discover
--     * we have too many elements, pointing linux_prev at the next field of the 
--     * linux_previous element or head of the list, search at this element.
--     */
--
--    for (left = host->can_queue, linux_search = hostdata->running_list, 
--          linux_prev = &hostdata->running_list;
--      left >= 0 && linux_search && linux_search != cmd;
--      linux_prev = &(linux_search->next), 
--          linux_search = linux_search->next, --left);
--    
--    if (left < 0) 
--      printk ("scsi%d: loop detected in host running list for scsi pid %ld\n",
--          host->host_no, c->pid);
--    else if (linux_search) {
--      *linux_prev = linux_search->next;
--      --hostdata->busy[c->device->id][c->device->lun];
--    }
+-#
+-# Parallel port support
+-#
+-# CONFIG_PARPORT is not set
 -
--    /* Return the NCR command structure to the free list */
--    cmd->next = hostdata->free;
--    hostdata->free = cmd;
--    c->host_scribble = NULL;
+-#
+-# Plug and Play support
+-#
+-CONFIG_PNP=y
+-# CONFIG_PNP_DEBUG is not set
 -
--    /* And return */
--    c->result = result;
--    c->scsi_done(c);
+-#
+-# Protocols
+-#
+-CONFIG_PNPACPI=y
 -
--    local_irq_restore(flags);
--    run_process_issue_queue();
--}
+-#
+-# Block devices
+-#
+-CONFIG_BLK_DEV_FD=y
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 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=4096
+-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
 -
--/* 
-- * Function : static void intr_break (struct Scsi_Host *host,
-- *    struct NCR53c7x0_cmd *cmd)
-- *
-- * Purpose :  Handler for breakpoint interrupts from a SCSI script
-- *
-- * Inputs : host - pointer to this host adapter's structure,
-- *    cmd - pointer to the command (if any) dsa was pointing 
-- *    to.
-- *
-- */
+-#
+-# Misc devices
+-#
+-# CONFIG_IBM_ASM is not set
+-# CONFIG_PHANTOM is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_SONY_LAPTOP is not set
+-# CONFIG_THINKPAD_ACPI is not set
+-CONFIG_IDE=y
+-CONFIG_BLK_DEV_IDE=y
 -
--static void 
--intr_break (struct Scsi_Host *host, struct 
--    NCR53c7x0_cmd *cmd) {
--    NCR53c7x0_local_declare();
--    struct NCR53c7x0_break *bp;
--#if 0
--    Scsi_Cmnd *c = cmd ? cmd->cmd : NULL;
--#endif
--    u32 *dsp;
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];              
--    unsigned long flags;
--    NCR53c7x0_local_setup(host);
--
--    /*
--     * Find the break point corresponding to this address, and 
--     * dump the appropriate debugging information to standard 
--     * output.  
--     */
--    local_irq_save(flags);
--    dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG));
--    for (bp = hostdata->breakpoints; bp && bp->address != dsp; 
--      bp = bp->next);
--    if (!bp) 
--      panic("scsi%d : break point interrupt from %p with no breakpoint!",
--          host->host_no, dsp);
--
--    /*
--     * Configure the NCR chip for manual start mode, so that we can 
--     * point the DSP register at the instruction that follows the 
--     * INT int_debug_break instruction.
--     */
--
--    NCR53c7x0_write8 (hostdata->dmode, 
--      NCR53c7x0_read8(hostdata->dmode)|DMODE_MAN);
--
--    /*
--     * And update the DSP register, using the size of the old 
--     * instruction in bytes.
--     */
--
--    local_irq_restore(flags);
--}
--/*
-- * Function : static void print_synchronous (const char *prefix, 
-- *    const unsigned char *msg)
-- * 
-- * Purpose : print a pretty, user and machine parsable representation
-- *    of a SDTR message, including the "real" parameters, data
-- *    clock so we can tell transfer rate at a glance.
-- *
-- * Inputs ; prefix - text to prepend, msg - SDTR message (5 bytes)
-- */
+-#
+-# Please see Documentation/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-# CONFIG_BLK_DEV_HD_IDE is not set
+-CONFIG_BLK_DEV_IDEDISK=y
+-CONFIG_IDEDISK_MULTI_MODE=y
+-CONFIG_BLK_DEV_IDECD=y
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_BLK_DEV_IDESCSI is not set
+-# CONFIG_BLK_DEV_IDEACPI is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
 -
--static void
--print_synchronous (const char *prefix, const unsigned char *msg) {
--    if (msg[4]) {
--      int Hz = 1000000000 / (msg[3] * 4);
--      int integer = Hz / 1000000;
--      int fraction = (Hz - (integer * 1000000)) / 10000;
--      printk ("%speriod %dns offset %d %d.%02dMHz %s SCSI%s\n",
--          prefix, (int) msg[3] * 4, (int) msg[4], integer, fraction,
--          (((msg[3] * 4) < 200) ? "FAST" : "synchronous"),
--          (((msg[3] * 4) < 200) ? "-II" : ""));
--    } else 
--      printk ("%sasynchronous SCSI\n", prefix);
--}
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_CMD640 is not set
+-# CONFIG_BLK_DEV_IDEPNP is not set
+-CONFIG_BLK_DEV_IDEPCI=y
+-# CONFIG_IDEPCI_SHARE_IRQ is not set
+-CONFIG_IDEPCI_PCIBUS_ORDER=y
+-# CONFIG_BLK_DEV_OFFBOARD is not set
+-# CONFIG_BLK_DEV_GENERIC is not set
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-# CONFIG_BLK_DEV_RZ1000 is not set
+-CONFIG_BLK_DEV_IDEDMA_PCI=y
+-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+-# CONFIG_IDEDMA_ONLYDISK is not set
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-CONFIG_BLK_DEV_AMD74XX=y
+-# CONFIG_BLK_DEV_ATIIXP is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_CS5535 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-CONFIG_BLK_DEV_PIIX=y
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SIS5513 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-# CONFIG_BLK_DEV_VIA82CXXX is not set
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-# CONFIG_IDE_ARM is not set
+-CONFIG_BLK_DEV_IDEDMA=y
+-# CONFIG_IDEDMA_IVB is not set
+-# CONFIG_BLK_DEV_HD is not set
 -
--/*
-- * Function : static void set_synchronous (struct Scsi_Host *host, 
-- *            int target, int sxfer, int scntl3, int now_connected)
-- *
-- * Purpose : reprogram transfers between the selected SCSI initiator and 
-- *    target with the given register values; in the indirect
-- *    select operand, reselection script, and chip registers.
-- *
-- * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id,
-- *    sxfer and scntl3 - NCR registers. now_connected - if non-zero, 
-- *    we should reprogram the registers now too.
-- *
-- *      NOTE:  For 53c710, scntl3 is actually used for SCF bits from
-- *    SBCL, as we don't have a SCNTL3.
-- */
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-# CONFIG_SCSI_TGT is not set
+-CONFIG_SCSI_NETLINK=y
+-# CONFIG_SCSI_PROC_FS is not set
 -
--static void
--set_synchronous (struct Scsi_Host *host, int target, int sxfer, int scntl3,
--    int now_connected) {
--    NCR53c7x0_local_declare();
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) 
--      host->hostdata[0];
--    u32 *script;
--    NCR53c7x0_local_setup(host);
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-CONFIG_BLK_DEV_SR=y
+-# CONFIG_BLK_DEV_SR_VENDOR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
 -
--    /* These are eight bit registers */
--    sxfer &= 0xff;
--    scntl3 &= 0xff;
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
 -
--    hostdata->sync[target].sxfer_sanity = sxfer;
--    hostdata->sync[target].scntl3_sanity = scntl3;
+-#
+-# SCSI Transports
+-#
+-CONFIG_SCSI_SPI_ATTRS=y
+-CONFIG_SCSI_FC_ATTRS=y
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
 -
--/* 
-- * HARD CODED : synchronous script is EIGHT words long.  This 
-- * must agree with 53c7.8xx.h
-- */
+-#
+-# SCSI low-level drivers
+-#
+-# CONFIG_ISCSI_TCP is not set
+-CONFIG_BLK_DEV_3W_XXXX_RAID=y
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-CONFIG_SCSI_AIC7XXX=y
+-CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+-CONFIG_AIC7XXX_RESET_DELAY_MS=5000
+-CONFIG_AIC7XXX_DEBUG_ENABLE=y
+-CONFIG_AIC7XXX_DEBUG_MASK=0
+-CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-CONFIG_SCSI_AIC79XX=y
+-CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+-CONFIG_AIC79XX_RESET_DELAY_MS=4000
+-# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+-CONFIG_AIC79XX_DEBUG_MASK=0
+-# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_IPR is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-CONFIG_ATA_ACPI=y
+-CONFIG_SATA_AHCI=y
+-CONFIG_SATA_SVW=y
+-CONFIG_ATA_PIIX=y
+-# CONFIG_SATA_MV is not set
+-CONFIG_SATA_NV=y
+-# CONFIG_PDC_ADMA is not set
+-# CONFIG_SATA_QSTOR is not set
+-# CONFIG_SATA_PROMISE is not set
+-# CONFIG_SATA_SX4 is not set
+-CONFIG_SATA_SIL=y
+-# CONFIG_SATA_SIL24 is not set
+-# CONFIG_SATA_SIS is not set
+-# CONFIG_SATA_ULI is not set
+-CONFIG_SATA_VIA=y
+-# CONFIG_SATA_VITESSE is not set
+-# CONFIG_SATA_INIC162X is not set
+-# CONFIG_PATA_ALI is not set
+-# CONFIG_PATA_AMD is not set
+-# CONFIG_PATA_ARTOP is not set
+-# CONFIG_PATA_ATIIXP is not set
+-# CONFIG_PATA_CMD640_PCI is not set
+-# CONFIG_PATA_CMD64X is not set
+-# CONFIG_PATA_CS5520 is not set
+-# CONFIG_PATA_CS5530 is not set
+-# CONFIG_PATA_CS5535 is not set
+-# CONFIG_PATA_CYPRESS is not set
+-# CONFIG_PATA_EFAR is not set
+-# CONFIG_ATA_GENERIC is not set
+-# CONFIG_PATA_HPT366 is not set
+-# CONFIG_PATA_HPT37X is not set
+-# CONFIG_PATA_HPT3X2N is not set
+-# CONFIG_PATA_HPT3X3 is not set
+-# CONFIG_PATA_IT821X is not set
+-# CONFIG_PATA_IT8213 is not set
+-# CONFIG_PATA_JMICRON is not set
+-# CONFIG_PATA_TRIFLEX is not set
+-# CONFIG_PATA_MARVELL is not set
+-# CONFIG_PATA_MPIIX is not set
+-# CONFIG_PATA_OLDPIIX is not set
+-# CONFIG_PATA_NETCELL is not set
+-# CONFIG_PATA_NS87410 is not set
+-# CONFIG_PATA_OPTI is not set
+-# CONFIG_PATA_OPTIDMA is not set
+-# CONFIG_PATA_PDC_OLD is not set
+-# CONFIG_PATA_RADISYS is not set
+-# CONFIG_PATA_RZ1000 is not set
+-# CONFIG_PATA_SC1200 is not set
+-# CONFIG_PATA_SERVERWORKS is not set
+-# CONFIG_PATA_PDC2027X is not set
+-# CONFIG_PATA_SIL680 is not set
+-# CONFIG_PATA_SIS is not set
+-# CONFIG_PATA_VIA is not set
+-# CONFIG_PATA_WINBOND is not set
 -
--    if ((hostdata->chip != 700) && (hostdata->chip != 70066)) {
--      hostdata->sync[target].select_indirect = (1 << target) << 16 |
--              (sxfer << 8);
--      hostdata->sync[target].sscf_710 = scntl3;
+-#
+-# Multi-device support (RAID and LVM)
+-#
+-CONFIG_MD=y
+-# CONFIG_BLK_DEV_MD is not set
+-CONFIG_BLK_DEV_DM=y
+-# CONFIG_DM_DEBUG is not set
+-# CONFIG_DM_CRYPT is not set
+-# CONFIG_DM_SNAPSHOT is not set
+-# CONFIG_DM_MIRROR is not set
+-# CONFIG_DM_ZERO is not set
+-# CONFIG_DM_MULTIPATH is not set
+-# CONFIG_DM_DELAY is not set
+-# CONFIG_DM_NETLINK is not set
 -
--      script = (u32 *) hostdata->sync[target].script;
+-#
+-# Fusion MPT device support
+-#
+-CONFIG_FUSION=y
+-CONFIG_FUSION_SPI=y
+-# CONFIG_FUSION_FC is not set
+-# CONFIG_FUSION_SAS is not set
+-CONFIG_FUSION_MAX_SGE=128
+-# CONFIG_FUSION_CTL is not set
 -
--      /* XXX - add NCR53c7x0 code to reprogram SCF bits if we want to */
--      script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY |
--              DCMD_RWRI_OP_MOVE) << 24) |
--              (SBCL_REG << 16) | (scntl3 << 8);
--      script[1] = 0;
--      script += 2;
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-CONFIG_IEEE1394=y
 -
--      script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY |
--          DCMD_RWRI_OP_MOVE) << 24) |
--              (SXFER_REG << 16) | (sxfer << 8);
--      script[1] = 0;
--      script += 2;
+-#
+-# Subsystem Options
+-#
+-# CONFIG_IEEE1394_VERBOSEDEBUG is not set
 -
--#ifdef DEBUG_SYNC_INTR
--      if (hostdata->options & OPTION_DEBUG_DISCONNECT) {
--          script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_INT) << 24) | DBC_TCI_TRUE;
--          script[1] = DEBUG_SYNC_INTR;
--          script += 2;
--      }
--#endif
+-#
+-# Controllers
+-#
 -
--      script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_RETURN) << 24) | DBC_TCI_TRUE;
--      script[1] = 0;
--      script += 2;
--    }
+-#
+-# Texas Instruments PCILynx requires I2C
+-#
+-CONFIG_IEEE1394_OHCI1394=y
 -
--    if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) 
--      printk ("scsi%d : target %d sync parameters are sxfer=0x%x, scntl3=0x%x\n",
--      host->host_no, target, sxfer, scntl3);
+-#
+-# Protocols
+-#
+-# CONFIG_IEEE1394_VIDEO1394 is not set
+-# CONFIG_IEEE1394_SBP2 is not set
+-# CONFIG_IEEE1394_ETH1394_ROM_ENTRY is not set
+-# CONFIG_IEEE1394_ETH1394 is not set
+-# CONFIG_IEEE1394_DV1394 is not set
+-CONFIG_IEEE1394_RAWIO=y
 -
--    if (now_connected) {
--      NCR53c7x0_write8(SBCL_REG, scntl3);
--      NCR53c7x0_write8(SXFER_REG, sxfer);
--    }
--}
+-#
+-# I2O device support
+-#
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
 -
+-#
+-# Network device support
+-#
+-CONFIG_NETDEVICES=y
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_EQUALIZER is not set
+-CONFIG_TUN=m
+-# CONFIG_ETUN is not set
+-# CONFIG_NET_SB1000 is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
 -
--/*
-- * Function : static int asynchronous (struct Scsi_Host *host, int target)
-- *
-- * Purpose : reprogram between the selected SCSI Host adapter and target 
-- *      (assumed to be currently connected) for asynchronous transfers.
-- *
-- * Inputs : host - SCSI host structure, target - numeric target ID.
-- *
-- * Preconditions : the NCR chip should be in one of the halted states
-- */
--    
--static void
--asynchronous (struct Scsi_Host *host, int target) {
--    NCR53c7x0_local_declare();
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    NCR53c7x0_local_setup(host);
--    set_synchronous (host, target, /* no offset */ 0, hostdata->saved_scntl3,
--      1);
--    printk ("scsi%d : setting target %d to asynchronous SCSI\n",
--      host->host_no, target);
--}
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
 -
--/* 
-- * XXX - do we want to go out of our way (ie, add extra code to selection
-- *    in the NCR53c710/NCR53c720 script) to reprogram the synchronous
-- *    conversion bits, or can we be content in just setting the 
-- *    sxfer bits?  I chose to do so [richard@sleepie.demon.co.uk]
-- */
+-#
+-# Tulip family network device support
+-#
+-CONFIG_NET_TULIP=y
+-# CONFIG_DE2104X is not set
+-CONFIG_TULIP=y
+-# CONFIG_TULIP_MWI is not set
+-# CONFIG_TULIP_MMIO is not set
+-# CONFIG_TULIP_NAPI is not set
+-# CONFIG_DE4X5 is not set
+-# CONFIG_WINBOND_840 is not set
+-# CONFIG_DM9102 is not set
+-# CONFIG_ULI526X is not set
+-# CONFIG_HP100 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-CONFIG_B44=y
+-CONFIG_FORCEDETH=y
+-# CONFIG_FORCEDETH_NAPI is not set
+-# CONFIG_DGRS is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-CONFIG_8139CP=y
+-CONFIG_8139TOO=y
+-# CONFIG_8139TOO_PIO is not set
+-# CONFIG_8139TOO_TUNE_TWISTER is not set
+-# CONFIG_8139TOO_8129 is not set
+-# CONFIG_8139_OLD_RX_RESET is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-CONFIG_E1000=y
+-# CONFIG_E1000_NAPI is not set
+-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-CONFIG_R8169=y
+-# CONFIG_R8169_NAPI is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-CONFIG_SKY2=y
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-CONFIG_TIGON3=y
+-CONFIG_BNX2=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TR is not set
 -
--/* Table for NCR53c8xx synchronous values */
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
 -
--/* This table is also correct for 710, allowing that scf=4 is equivalent
-- * of SSCF=0 (ie use DCNTL, divide by 3) for a 50.01-66.00MHz clock.
-- * For any other clock values, we cannot use entries with SCF values of
-- * 4.  I guess that for a 66MHz clock, the slowest it will set is 2MHz,
-- * and for a 50MHz clock, the slowest will be 2.27Mhz.  Should check
-- * that a device doesn't try and negotiate sync below these limits!
-- */
-- 
--static const struct {
--    int div;          /* Total clock divisor * 10 */
--    unsigned char scf;        /* */
--    unsigned char tp; /* 4 + tp = xferp divisor */
--} syncs[] = {
--/*    div     scf     tp      div     scf     tp      div     scf     tp */
--    { 40,     1,      0}, {   50,     1,      1}, {   60,     1,      2}, 
--    { 70,     1,      3}, {   75,     2,      1}, {   80,     1,      4},
--    { 90,     1,      5}, {   100,    1,      6}, {   105,    2,      3},
--    { 110,    1,      7}, {   120,    2,      4}, {   135,    2,      5},
--    { 140,    3,      3}, {   150,    2,      6}, {   160,    3,      4},
--    { 165,    2,      7}, {   180,    3,      5}, {   200,    3,      6},
--    { 210,    4,      3}, {   220,    3,      7}, {   240,    4,      4},
--    { 270,    4,      5}, {   300,    4,      6}, {   330,    4,      7}
--};
+-#
+-# 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_MII is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-CONFIG_PPP=m
+-# CONFIG_PPP_MULTILINK is not set
+-# CONFIG_PPP_FILTER is not set
+-# CONFIG_PPP_ASYNC is not set
+-# CONFIG_PPP_SYNC_TTY is not set
+-# CONFIG_PPP_DEFLATE is not set
+-# CONFIG_PPP_BSDCOMP is not set
+-# CONFIG_PPP_MPPE is not set
+-# CONFIG_PPPOE is not set
+-# CONFIG_SLIP is not set
+-CONFIG_SLHC=m
+-# CONFIG_NET_FC is not set
+-# CONFIG_SHAPER is not set
+-CONFIG_NETCONSOLE=y
+-CONFIG_NETPOLL=y
+-# CONFIG_NETPOLL_TRAP is not set
+-CONFIG_NET_POLL_CONTROLLER=y
 -
--/*
-- * Function : static void synchronous (struct Scsi_Host *host, int target, 
-- *    char *msg)
-- *
-- * Purpose : reprogram transfers between the selected SCSI initiator and 
-- *    target for synchronous SCSI transfers such that the synchronous 
-- *    offset is less than that requested and period at least as long 
-- *    as that requested.  Also modify *msg such that it contains 
-- *    an appropriate response. 
-- *
-- * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id,
-- *    msg - synchronous transfer request.
-- */
+-#
+-# ISDN subsystem
+-#
+-# CONFIG_ISDN is not set
 -
+-#
+-# Telephony Support
+-#
+-# CONFIG_PHONE is not set
 -
--static void
--synchronous (struct Scsi_Host *host, int target, char *msg) {
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    int desire, divisor, i, limit;
--    unsigned char scntl3, sxfer;
--/* The diagnostic message fits on one line, even with max. width integers */
--    char buf[80];
--
--/* Desired transfer clock in Hz */
--    desire = 1000000000L / (msg[3] * 4);
--/* Scale the available SCSI clock by 10 so we get tenths */
--    divisor = (hostdata->scsi_clock * 10) / desire;
--
--/* NCR chips can handle at most an offset of 8 */
--    if (msg[4] > 8)
--      msg[4] = 8;
--
--    if (hostdata->options & OPTION_DEBUG_SDTR)
--      printk("scsi%d : optimal synchronous divisor of %d.%01d\n",
--          host->host_no, divisor / 10, divisor % 10);
--
--    limit = ARRAY_SIZE(syncs) - 1;
--    for (i = 0; (i < limit) && (divisor > syncs[i].div); ++i);
--
--    if (hostdata->options & OPTION_DEBUG_SDTR)
--      printk("scsi%d : selected synchronous divisor of %d.%01d\n",
--          host->host_no, syncs[i].div / 10, syncs[i].div % 10);
--
--    msg[3] = ((1000000000L / hostdata->scsi_clock) * syncs[i].div / 10 / 4);
--
--    if (hostdata->options & OPTION_DEBUG_SDTR)
--      printk("scsi%d : selected synchronous period of %dns\n", host->host_no,
--          msg[3] * 4);
--
--    scntl3 = syncs[i].scf;
--    sxfer = (msg[4] << SXFER_MO_SHIFT) | (syncs[i].tp << 4);
--    if (hostdata->options & OPTION_DEBUG_SDTR)
--      printk ("scsi%d : sxfer=0x%x scntl3=0x%x\n", 
--          host->host_no, (int) sxfer, (int) scntl3);
--    set_synchronous (host, target, sxfer, scntl3, 1);
--    sprintf (buf, "scsi%d : setting target %d to ", host->host_no, target);
--    print_synchronous (buf, msg);
--}
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
 -
--/* 
-- * Function : static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host,
-- *    struct NCR53c7x0_cmd *cmd)
-- *
-- * Purpose :  Handler for INT generated instructions for the 
-- *    NCR53c810/820 SCSI SCRIPT
-- *
-- * Inputs : host - pointer to this host adapter's structure,
-- *    cmd - pointer to the command (if any) dsa was pointing 
-- *    to.
-- *
-- */
+-#
+-# Userland interfaces
+-#
+-CONFIG_INPUT_MOUSEDEV=y
+-CONFIG_INPUT_MOUSEDEV_PSAUX=y
+-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+-CONFIG_INPUT_EVDEV=y
+-# CONFIG_INPUT_EVBUG is not set
 -
--static int 
--NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct 
--    NCR53c7x0_cmd *cmd) {
--    NCR53c7x0_local_declare();
--    int print;
--    Scsi_Cmnd *c = cmd ? cmd->cmd : NULL;
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];              
--    u32 dsps,*dsp;    /* Argument of the INT instruction */
+-#
+-# Input Device Drivers
+-#
+-CONFIG_INPUT_KEYBOARD=y
+-CONFIG_KEYBOARD_ATKBD=y
+-# 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_STOWAWAY is not set
+-CONFIG_INPUT_MOUSE=y
+-CONFIG_MOUSE_PS2=y
+-CONFIG_MOUSE_PS2_ALPS=y
+-CONFIG_MOUSE_PS2_LOGIPS2PP=y
+-CONFIG_MOUSE_PS2_SYNAPTICS=y
+-CONFIG_MOUSE_PS2_LIFEBOOK=y
+-CONFIG_MOUSE_PS2_TRACKPOINT=y
+-# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+-# CONFIG_MOUSE_SERIAL is not set
+-# CONFIG_MOUSE_APPLETOUCH is not set
+-# CONFIG_MOUSE_VSXXXAA is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
 -
--    NCR53c7x0_local_setup(host);
--    dsps = NCR53c7x0_read32(DSPS_REG);
--    dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG));
+-#
+-# Hardware I/O ports
+-#
+-CONFIG_SERIO=y
+-CONFIG_SERIO_I8042=y
+-# CONFIG_SERIO_SERPORT is not set
+-# CONFIG_SERIO_CT82C710 is not set
+-# CONFIG_SERIO_PCIPS2 is not set
+-CONFIG_SERIO_LIBPS2=y
+-# CONFIG_SERIO_RAW is not set
+-# CONFIG_GAMEPORT is not set
 -
--    /* RGH 150597:  Frig.  Commands which fail with Check Condition are
--     * Flagged as successful - hack dsps to indicate check condition */
--#if 0
--    /* RGH 200597:  Need to disable for BVME6000, as it gets Check Conditions
--     * and then dies.  Seems to handle Check Condition at startup, but
--     * not mid kernel build. */
--    if (dsps == A_int_norm_emulateintfly && cmd && cmd->result == 2)
--        dsps = A_int_err_check_condition;
--#endif
+-#
+-# Character devices
+-#
+-CONFIG_VT=y
+-CONFIG_VT_CONSOLE=y
+-CONFIG_HW_CONSOLE=y
+-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
 -
--    if (hostdata->options & OPTION_DEBUG_INTR) 
--      printk ("scsi%d : DSPS = 0x%x\n", host->host_no, dsps);
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_PNP=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
 -
--    switch (dsps) {
--    case A_int_msg_1:
--      print = 1;
--      switch (hostdata->msg_buf[0]) {
--      /* 
--       * Unless we've initiated synchronous negotiation, I don't
--       * think that this should happen.
--       */
--      case MESSAGE_REJECT:
--          hostdata->dsp = hostdata->script + hostdata->E_accept_message /
--              sizeof(u32);
--          hostdata->dsp_changed = 1;
--          if (cmd && (cmd->flags & CMD_FLAG_SDTR)) {
--              printk ("scsi%d : target %d rejected SDTR\n", host->host_no, 
--                  c->device->id);
--              cmd->flags &= ~CMD_FLAG_SDTR;
--              asynchronous (host, c->device->id);
--              print = 0;
--          } 
--          break;
--      case INITIATE_RECOVERY:
--          printk ("scsi%d : extended contingent allegiance not supported yet, rejecting\n",
--              host->host_no);
--          /* Fall through to default */
--          hostdata->dsp = hostdata->script + hostdata->E_reject_message /
--              sizeof(u32);
--          hostdata->dsp_changed = 1;
--          break;
--      default:
--          printk ("scsi%d : unsupported message, rejecting\n",
--              host->host_no);
--          hostdata->dsp = hostdata->script + hostdata->E_reject_message /
--              sizeof(u32);
--          hostdata->dsp_changed = 1;
--      }
--      if (print) {
--          printk ("scsi%d : received message", host->host_no);
--          if (c) 
--              printk (" from target %d lun %d ", c->device->id, c->device->lun);
--          spi_print_msg((unsigned char *) hostdata->msg_buf);
--          printk("\n");
--      }
--      
--      return SPECIFIC_INT_NOTHING;
+-#
+-# Non-8250 serial port support
+-#
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
 -
+-#
+-# IPMI
+-#
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_WATCHDOG is not set
+-CONFIG_HW_RANDOM=y
+-CONFIG_HW_RANDOM_INTEL=y
+-CONFIG_HW_RANDOM_AMD=y
+-CONFIG_HW_RANDOM_GEODE=y
+-CONFIG_HW_RANDOM_VIA=y
+-# CONFIG_NVRAM is not set
+-CONFIG_RTC=y
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_SONYPI is not set
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_MWAVE is not set
+-# CONFIG_PC8736x_GPIO is not set
+-# CONFIG_NSC_GPIO is not set
+-# CONFIG_CS5535_GPIO is not set
+-CONFIG_RAW_DRIVER=y
+-CONFIG_MAX_RAW_DEVS=256
+-CONFIG_HPET=y
+-# CONFIG_HPET_RTC_IRQ is not set
+-CONFIG_HPET_MMAP=y
+-CONFIG_HANGCHECK_TIMER=y
 -
--    case A_int_msg_sdtr:
--/*
-- * At this point, hostdata->msg_buf contains
-- * 0 EXTENDED MESSAGE
-- * 1 length 
-- * 2 SDTR
-- * 3 period * 4ns
-- * 4 offset
-- */
--
--      if (cmd) {
--          char buf[80];
--          sprintf (buf, "scsi%d : target %d %s ", host->host_no, c->device->id,
--              (cmd->flags & CMD_FLAG_SDTR) ? "accepting" : "requesting");
--          print_synchronous (buf, (unsigned char *) hostdata->msg_buf);
--
--      /* 
--       * Initiator initiated, won't happen unless synchronous 
--       *      transfers are enabled.  If we get a SDTR message in
--       *      response to our SDTR, we should program our parameters
--       *      such that 
--       *              offset <= requested offset
--       *              period >= requested period                      
--       */
--          if (cmd->flags & CMD_FLAG_SDTR) {
--              cmd->flags &= ~CMD_FLAG_SDTR; 
--              if (hostdata->msg_buf[4]) 
--                  synchronous (host, c->device->id, (unsigned char *) 
--                      hostdata->msg_buf);
--              else 
--                  asynchronous (host, c->device->id);
--              hostdata->dsp = hostdata->script + hostdata->E_accept_message /
--                  sizeof(u32);
--              hostdata->dsp_changed = 1;
--              return SPECIFIC_INT_NOTHING;
--          } else {
--              if (hostdata->options & OPTION_SYNCHRONOUS)  {
--                  cmd->flags |= CMD_FLAG_DID_SDTR;
--                  synchronous (host, c->device->id, (unsigned char *) 
--                      hostdata->msg_buf);
--              } else {
--                  hostdata->msg_buf[4] = 0;           /* 0 offset = async */
--                  asynchronous (host, c->device->id);
--              }
--              patch_dsa_32 (cmd->dsa, dsa_msgout_other, 0, 5);
--              patch_dsa_32 (cmd->dsa, dsa_msgout_other, 1, (u32) 
--                  virt_to_bus ((void *)&hostdata->msg_buf));
--              hostdata->dsp = hostdata->script + 
--                  hostdata->E_respond_message / sizeof(u32);
--              hostdata->dsp_changed = 1;
--          }
--          return SPECIFIC_INT_NOTHING;
--      }
--      /* Fall through to abort if we couldn't find a cmd, and 
--         therefore a dsa structure to twiddle */
--    case A_int_msg_wdtr:
--      hostdata->dsp = hostdata->script + hostdata->E_reject_message /
--          sizeof(u32);
--      hostdata->dsp_changed = 1;
--      return SPECIFIC_INT_NOTHING;
--    case A_int_err_unexpected_phase:
--      if (hostdata->options & OPTION_DEBUG_INTR) 
--          printk ("scsi%d : unexpected phase\n", host->host_no);
--      return SPECIFIC_INT_ABORT;
--    case A_int_err_selected:
--      if ((hostdata->chip / 100) == 8)
--          printk ("scsi%d : selected by target %d\n", host->host_no,
--              (int) NCR53c7x0_read8(SDID_REG_800) &7);
--      else
--            printk ("scsi%d : selected by target LCRC=0x%02x\n", host->host_no,
--                (int) NCR53c7x0_read8(LCRC_REG_10));
--      hostdata->dsp = hostdata->script + hostdata->E_target_abort / 
--          sizeof(u32);
--      hostdata->dsp_changed = 1;
--      return SPECIFIC_INT_NOTHING;
--    case A_int_err_unexpected_reselect:
--      if ((hostdata->chip / 100) == 8)
--          printk ("scsi%d : unexpected reselect by target %d lun %d\n", 
--              host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & 7,
--              hostdata->reselected_identify & 7);
--      else
--            printk ("scsi%d : unexpected reselect LCRC=0x%02x\n", host->host_no,
--                (int) NCR53c7x0_read8(LCRC_REG_10));
--      hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
--          sizeof(u32);
--      hostdata->dsp_changed = 1;
--      return SPECIFIC_INT_NOTHING;
--/*
-- * Since contingent allegiance conditions are cleared by the next 
-- * command issued to a target, we must issue a REQUEST SENSE 
-- * command after receiving a CHECK CONDITION status, before
-- * another command is issued.
-- * 
-- * Since this NCR53c7x0_cmd will be freed after use, we don't 
-- * care if we step on the various fields, so modify a few things.
-- */
--    case A_int_err_check_condition: 
--#if 0
--      if (hostdata->options & OPTION_DEBUG_INTR) 
--#endif
--          printk ("scsi%d : CHECK CONDITION\n", host->host_no);
--      if (!c) {
--          printk("scsi%d : CHECK CONDITION with no SCSI command\n",
--              host->host_no);
--          return SPECIFIC_INT_PANIC;
--      }
+-#
+-# TPM devices
+-#
+-# CONFIG_TCG_TPM is not set
+-# CONFIG_TELCLOCK is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
 -
--      /* 
--       * FIXME : this uses the normal one-byte selection message.
--       *      We may want to renegotiate for synchronous & WIDE transfers
--       *      since these could be the crux of our problem.
--       *
--       hostdata->NOP_insn* FIXME : once SCSI-II tagged queuing is implemented, we'll
--       *      have to set this up so that the rest of the DSA
--       *      agrees with this being an untagged queue'd command.
--       */
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
 -
--      patch_dsa_32 (cmd->dsa, dsa_msgout, 0, 1);
+-#
+-# Dallas's 1-wire bus
+-#
+-# CONFIG_W1 is not set
+-# CONFIG_HWMON is not set
 -
--      /* 
--       * Modify the table indirect for COMMAND OUT phase, since 
--       * Request Sense is a six byte command.
--       */
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
 -
--      patch_dsa_32 (cmd->dsa, dsa_cmdout, 0, 6);
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
 -
--        /*
--         * The CDB is now mirrored in our local non-cached
--         * structure, but keep the old structure up to date as well,
--         * just in case anyone looks at it.
--         */
+-#
+-# Graphics support
+-#
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 -
--      /*
--       * XXX Need to worry about data buffer alignment/cache state
--       * XXX here, but currently never get A_int_err_check_condition,
--       * XXX so ignore problem for now.
--         */
--      cmd->cmnd[0] = c->cmnd[0] = REQUEST_SENSE;
--      cmd->cmnd[0] = c->cmnd[1] &= 0xe0;      /* Zero all but LUN */
--      cmd->cmnd[0] = c->cmnd[2] = 0;
--      cmd->cmnd[0] = c->cmnd[3] = 0;
--      cmd->cmnd[0] = c->cmnd[4] = sizeof(c->sense_buffer);
--      cmd->cmnd[0] = c->cmnd[5] = 0; 
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
 -
--      /*
--       * Disable dataout phase, and program datain to transfer to the 
--       * sense buffer, and add a jump to other_transfer after the 
--       * command so overflow/underrun conditions are detected.
--       */
+-#
+-# Console display driver support
+-#
+-CONFIG_VGA_CONSOLE=y
+-CONFIG_VGACON_SOFT_SCROLLBACK=y
+-CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=128
+-CONFIG_VIDEO_SELECT=y
+-CONFIG_DUMMY_CONSOLE=y
 -
--      patch_dsa_32 (cmd->dsa, dsa_dataout, 0, 
--          virt_to_bus(hostdata->script) + hostdata->E_other_transfer);
--      patch_dsa_32 (cmd->dsa, dsa_datain, 0, 
--          virt_to_bus(cmd->data_transfer_start));
--      cmd->data_transfer_start[0] = (((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | 
--          DCMD_BMI_IO)) << 24) | sizeof(c->sense_buffer);
--      cmd->data_transfer_start[1] = (u32) virt_to_bus(c->sense_buffer);
--
--      cmd->data_transfer_start[2] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) 
--          << 24) | DBC_TCI_TRUE;
--      cmd->data_transfer_start[3] = (u32) virt_to_bus(hostdata->script) + 
--          hostdata->E_other_transfer;
--
--      /*
--       * Currently, this command is flagged as completed, ie 
--       * it has valid status and message data.  Reflag it as
--       * incomplete.  Q - need to do something so that original
--       * status, etc are used.
--       */
--
--      cmd->result = cmd->cmd->result = 0xffff;                
--
--      /* 
--       * Restart command as a REQUEST SENSE.
--       */
--      hostdata->dsp = (u32 *) hostdata->script + hostdata->E_select /
--          sizeof(u32);
--      hostdata->dsp_changed = 1;
--      return SPECIFIC_INT_NOTHING;
--    case A_int_debug_break:
--      return SPECIFIC_INT_BREAK;
--    case A_int_norm_aborted:
--      hostdata->dsp = (u32 *) hostdata->schedule;
--      hostdata->dsp_changed = 1;
--      if (cmd)
--          abnormal_finished (cmd, DID_ERROR << 16);
--      return SPECIFIC_INT_NOTHING;
--    case A_int_norm_emulateintfly:
--      NCR53c7x0_intfly(host);
--      return SPECIFIC_INT_NOTHING;
--    case A_int_test_1:
--    case A_int_test_2:
--      hostdata->idle = 1;
--      hostdata->test_completed = (dsps - A_int_test_1) / 0x00010000 + 1;
--      if (hostdata->options & OPTION_DEBUG_INTR)
--          printk("scsi%d : test%d complete\n", host->host_no,
--              hostdata->test_completed);
--      return SPECIFIC_INT_NOTHING;
--#ifdef A_int_debug_reselected_ok
--    case A_int_debug_reselected_ok:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
--              OPTION_DEBUG_DISCONNECT)) {
--          /* 
--           * Note - this dsa is not based on location relative to 
--           * the command structure, but to location relative to the 
--           * DSA register 
--           */ 
--          u32 *dsa;
--          dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG));
--
--          printk("scsi%d : reselected_ok (DSA = 0x%x (virt 0x%p)\n", 
--              host->host_no, NCR53c7x0_read32(DSA_REG), dsa);
--          printk("scsi%d : resume address is 0x%x (virt 0x%p)\n",
--                  host->host_no, cmd->saved_data_pointer,
--                  bus_to_virt(cmd->saved_data_pointer));
--          print_insn (host, hostdata->script + Ent_reselected_ok / 
--                  sizeof(u32), "", 1);
--          if ((hostdata->chip / 100) == 8)
--              printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n",
--                  host->host_no, NCR53c7x0_read8(SXFER_REG),
--                  NCR53c7x0_read8(SCNTL3_REG_800));
--          else
--              printk ("scsi%d : sxfer=0x%x, cannot read SBCL\n",
--                  host->host_no, NCR53c7x0_read8(SXFER_REG));
--          if (c) {
--              print_insn (host, (u32 *) 
--                  hostdata->sync[c->device->id].script, "", 1);
--              print_insn (host, (u32 *) 
--                  hostdata->sync[c->device->id].script + 2, "", 1);
--          }
--      }
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_reselect_check
--    case A_int_debug_reselect_check:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
--          u32 *dsa;
--#if 0
--          u32 *code;
--#endif
--          /* 
--           * Note - this dsa is not based on location relative to 
--           * the command structure, but to location relative to the 
--           * DSA register 
--           */ 
--          dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG));
--          printk("scsi%d : reselected_check_next (DSA = 0x%lx (virt 0x%p))\n",
--              host->host_no, virt_to_bus(dsa), dsa);
--          if (dsa) {
--              printk("scsi%d : resume address is 0x%x (virt 0x%p)\n",
--                  host->host_no, cmd->saved_data_pointer,
--                  bus_to_virt (cmd->saved_data_pointer));
--#if 0
--              printk("scsi%d : template code :\n", host->host_no);
--              for (code = dsa + (Ent_dsa_code_check_reselect - Ent_dsa_zero) 
--                  / sizeof(u32); code < (dsa + Ent_dsa_zero / sizeof(u32)); 
--                  code += print_insn (host, code, "", 1));
--#endif
--          }
--          print_insn (host, hostdata->script + Ent_reselected_ok / 
--                  sizeof(u32), "", 1);
--      }
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_dsa_schedule
--    case A_int_debug_dsa_schedule:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
--          u32 *dsa;
--          /* 
--           * Note - this dsa is not based on location relative to 
--           * the command structure, but to location relative to the 
--           * DSA register 
--           */ 
--          dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG));
--          printk("scsi%d : dsa_schedule (old DSA = 0x%lx (virt 0x%p))\n", 
--              host->host_no, virt_to_bus(dsa), dsa);
--          if (dsa) 
--              printk("scsi%d : resume address is 0x%x (virt 0x%p)\n"
--                     "         (temp was 0x%x (virt 0x%p))\n",
--                  host->host_no, cmd->saved_data_pointer,
--                  bus_to_virt (cmd->saved_data_pointer),
--                  NCR53c7x0_read32 (TEMP_REG),
--                  bus_to_virt (NCR53c7x0_read32(TEMP_REG)));
--      }
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_scheduled
--    case A_int_debug_scheduled:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
--          printk("scsi%d : new I/O 0x%x (virt 0x%p) scheduled\n", 
--              host->host_no, NCR53c7x0_read32(DSA_REG),
--              bus_to_virt(NCR53c7x0_read32(DSA_REG)));
--      }
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_idle
--    case A_int_debug_idle:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
--          printk("scsi%d : idle\n", host->host_no);
--      }
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_cmd
--    case A_int_debug_cmd:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
--          printk("scsi%d : command sent\n");
--      }
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_dsa_loaded
--    case A_int_debug_dsa_loaded:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
--          printk("scsi%d : DSA loaded with 0x%x (virt 0x%p)\n", host->host_no,
--              NCR53c7x0_read32(DSA_REG), 
--              bus_to_virt(NCR53c7x0_read32(DSA_REG)));
--      }
--      return SPECIFIC_INT_RESTART; 
--#endif
--#ifdef A_int_debug_reselected
--    case A_int_debug_reselected:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
--          OPTION_DEBUG_DISCONNECT)) {
--          if ((hostdata->chip / 100) == 8)
--              printk("scsi%d : reselected by target %d lun %d\n",
--                  host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & ~0x80, 
--                  (int) hostdata->reselected_identify & 7);
--          else
--              printk("scsi%d : reselected by LCRC=0x%02x lun %d\n",
--                    host->host_no, (int) NCR53c7x0_read8(LCRC_REG_10),
--                    (int) hostdata->reselected_identify & 7);
--          print_queues(host);
--      }
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_disconnect_msg
--    case A_int_debug_disconnect_msg:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
--          if (c)
--              printk("scsi%d : target %d lun %d disconnecting\n", 
--                  host->host_no, c->device->id, c->device->lun);
--          else
--              printk("scsi%d : unknown target disconnecting\n",
--                  host->host_no);
--      }
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_disconnected
--    case A_int_debug_disconnected:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
--              OPTION_DEBUG_DISCONNECT)) {
--          printk ("scsi%d : disconnected, new queues are\n", 
--              host->host_no);
--          print_queues(host);
--#if 0
--          /* Not valid on ncr53c710! */
--          printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n",
--              host->host_no, NCR53c7x0_read8(SXFER_REG),
--              NCR53c7x0_read8(SCNTL3_REG_800));
--#endif
--          if (c) {
--              print_insn (host, (u32 *) 
--                  hostdata->sync[c->device->id].script, "", 1);
--              print_insn (host, (u32 *) 
--                  hostdata->sync[c->device->id].script + 2, "", 1);
--          }
--      }
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_panic
--    case A_int_debug_panic:
--      printk("scsi%d : int_debug_panic received\n", host->host_no);
--      print_lots (host);
--      return SPECIFIC_INT_PANIC;
--#endif
--#ifdef A_int_debug_saved
--    case A_int_debug_saved:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
--          OPTION_DEBUG_DISCONNECT)) {
--          printk ("scsi%d : saved data pointer 0x%x (virt 0x%p)\n",
--              host->host_no, cmd->saved_data_pointer,
--              bus_to_virt (cmd->saved_data_pointer));
--          print_progress (c);
--      }
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_restored
--    case A_int_debug_restored:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
--          OPTION_DEBUG_DISCONNECT)) {
--          if (cmd) {
--              int size;
--              printk ("scsi%d : restored data pointer 0x%x (virt 0x%p)\n",
--                  host->host_no, cmd->saved_data_pointer, bus_to_virt (
--                  cmd->saved_data_pointer));
--              size = print_insn (host, (u32 *) 
--                  bus_to_virt(cmd->saved_data_pointer), "", 1);
--              size = print_insn (host, (u32 *) 
--                  bus_to_virt(cmd->saved_data_pointer) + size, "", 1);
--              print_progress (c);
--          }
--#if 0
--          printk ("scsi%d : datapath residual %d\n",
--              host->host_no, datapath_residual (host)) ;
--#endif
--      }
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_sync
--    case A_int_debug_sync:
--      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
--          OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) {
--          unsigned char sxfer = NCR53c7x0_read8 (SXFER_REG), scntl3;
--          if ((hostdata->chip / 100) == 8) {
--              scntl3 = NCR53c7x0_read8 (SCNTL3_REG_800);
--              if (c) {
--                if (sxfer != hostdata->sync[c->device->id].sxfer_sanity ||
--                  scntl3 != hostdata->sync[c->device->id].scntl3_sanity) {
--                      printk ("scsi%d :  sync sanity check failed sxfer=0x%x, scntl3=0x%x",
--                          host->host_no, sxfer, scntl3);
--                      NCR53c7x0_write8 (SXFER_REG, sxfer);
--                      NCR53c7x0_write8 (SCNTL3_REG_800, scntl3);
--                  }
--              } else 
--                printk ("scsi%d : unknown command sxfer=0x%x, scntl3=0x%x\n",
--                  host->host_no, (int) sxfer, (int) scntl3);
--          } else {
--              if (c) {
--                if (sxfer != hostdata->sync[c->device->id].sxfer_sanity) {
--                      printk ("scsi%d :  sync sanity check failed sxfer=0x%x",
--                          host->host_no, sxfer);
--                      NCR53c7x0_write8 (SXFER_REG, sxfer);
--                      NCR53c7x0_write8 (SBCL_REG,
--                              hostdata->sync[c->device->id].sscf_710);
--                  }
--              } else 
--                printk ("scsi%d : unknown command sxfer=0x%x\n",
--                  host->host_no, (int) sxfer);
--          }
--      }
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_datain
--      case A_int_debug_datain:
--          if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
--              OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) {
--              int size;
--              if ((hostdata->chip / 100) == 8)
--                printk ("scsi%d : In do_datain (%s) sxfer=0x%x, scntl3=0x%x\n"
--                      "         datapath residual=%d\n",
--                  host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)),
--                  (int) NCR53c7x0_read8(SXFER_REG), 
--                  (int) NCR53c7x0_read8(SCNTL3_REG_800),
--                  datapath_residual (host)) ;
--              else
--                printk ("scsi%d : In do_datain (%s) sxfer=0x%x\n"
--                      "         datapath residual=%d\n",
--                  host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)),
--                  (int) NCR53c7x0_read8(SXFER_REG), 
--                  datapath_residual (host)) ;
--              print_insn (host, dsp, "", 1);
--              size = print_insn (host, (u32 *) bus_to_virt(dsp[1]), "", 1);
--              print_insn (host, (u32 *) bus_to_virt(dsp[1]) + size, "", 1);
--         } 
--      return SPECIFIC_INT_RESTART;
--#endif
--#ifdef A_int_debug_check_dsa
--      case A_int_debug_check_dsa:
--          if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) {
--              int sdid;
--              int tmp;
--              char *where;
--              if (hostdata->chip / 100 == 8)
--                  sdid = NCR53c7x0_read8 (SDID_REG_800) & 15;
--              else {
--                  tmp = NCR53c7x0_read8 (SDID_REG_700);
--                  if (!tmp)
--                      panic ("SDID_REG_700 = 0");
--                  tmp >>= 1;
--                  sdid = 0;
--                  while (tmp) {
--                      tmp >>= 1;
--                      sdid++;
--                  }
--              }
--              where = dsp - NCR53c7x0_insn_size(NCR53c7x0_read8 
--                      (DCMD_REG)) == hostdata->script + 
--                      Ent_select_check_dsa / sizeof(u32) ?
--                  "selection" : "reselection";
--              if (c && sdid != c->device->id) {
--                  printk ("scsi%d : SDID target %d != DSA target %d at %s\n",
--                      host->host_no, sdid, c->device->id, where);
--                  print_lots(host);
--                  dump_events (host, 20);
--                  return SPECIFIC_INT_PANIC;
--              }
--          }
--          return SPECIFIC_INT_RESTART;
--#endif
--    default:
--      if ((dsps & 0xff000000) == 0x03000000) {
--           printk ("scsi%d : misc debug interrupt 0x%x\n",
--              host->host_no, dsps);
--          return SPECIFIC_INT_RESTART;
--      } else if ((dsps & 0xff000000) == 0x05000000) {
--          if (hostdata->events) {
--              struct NCR53c7x0_event *event;
--              ++hostdata->event_index;
--              if (hostdata->event_index >= hostdata->event_size)
--                  hostdata->event_index = 0;
--              event = (struct NCR53c7x0_event *) hostdata->events + 
--                  hostdata->event_index;
--              event->event = (enum ncr_event) dsps;
--              event->dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
--              if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) {
--                  if (hostdata->chip / 100 == 8)
--                      event->target = NCR53c7x0_read8(SSID_REG_800);
--                  else {
--                      unsigned char tmp, sdid;
--                      tmp = NCR53c7x0_read8 (SDID_REG_700);
--                      if (!tmp)
--                          panic ("SDID_REG_700 = 0");
--                      tmp >>= 1;
--                      sdid = 0;
--                      while (tmp) {
--                          tmp >>= 1;
--                          sdid++;
--                      }
--                      event->target = sdid;
--                  }
--              }
--              else 
--                      event->target = 255;
+-#
+-# Sound
+-#
+-CONFIG_SOUND=y
 -
--              if (event->event == EVENT_RESELECT)
--                  event->lun = hostdata->reselected_identify & 0xf;
--              else if (c)
--                  event->lun = c->device->lun;
--              else
--                  event->lun = 255;
--              do_gettimeofday(&(event->time));
--              if (c) {
--                  event->pid = c->pid;
--                  memcpy ((void *) event->cmnd, (void *) c->cmnd, 
--                      sizeof (event->cmnd));
--              } else {
--                  event->pid = -1;
--              }
--          }
--          return SPECIFIC_INT_RESTART;
--      }
+-#
+-# Advanced Linux Sound Architecture
+-#
+-# CONFIG_SND is not set
 -
--      printk ("scsi%d : unknown user interrupt 0x%x\n", 
--          host->host_no, (unsigned) dsps);
--      return SPECIFIC_INT_PANIC;
--    }
--}
+-#
+-# Open Sound System
+-#
+-CONFIG_SOUND_PRIME=y
+-# CONFIG_OSS_OBSOLETE is not set
+-# CONFIG_SOUND_TRIDENT is not set
+-# CONFIG_SOUND_MSNDCLAS is not set
+-# CONFIG_SOUND_MSNDPIN is not set
+-# CONFIG_SOUND_OSS is not set
 -
--/* 
-- * XXX - the stock NCR assembler won't output the scriptu.h file,
-- * which undefine's all #define'd CPP symbols from the script.h
-- * file, which will create problems if you use multiple scripts
-- * with the same  symbol names.
-- *
-- * If you insist on using NCR's assembler, you could generate
-- * scriptu.h from script.h using something like 
-- *
-- * grep #define script.h | \
-- * sed 's/#define[    ][      ]*\([_a-zA-Z][_a-zA-Z0-9]*\).*$/#undefine \1/' \
-- * > scriptu.h
-- */
+-#
+-# HID Devices
+-#
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
 -
--#include "53c7xx_u.h"
+-#
+-# USB Input Devices
+-#
+-CONFIG_USB_HID=y
+-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+-# CONFIG_HID_FF is not set
+-# CONFIG_USB_HIDDEV is not set
 -
--/* XXX - add alternate script handling code here */
+-#
+-# USB support
+-#
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
 -
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_SUSPEND is not set
+-# CONFIG_USB_OTG is not set
 -
--/* 
-- * Function : static void NCR537xx_soft_reset (struct Scsi_Host *host)
-- *
-- * Purpose :  perform a soft reset of the NCR53c7xx chip
-- *
-- * Inputs : host - pointer to this host adapter's structure
-- *
-- * Preconditions : NCR53c7x0_init must have been called for this 
-- *      host.
-- * 
-- */
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-# CONFIG_USB_EHCI_SPLIT_ISO is not set
+-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+-# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-CONFIG_USB_UHCI_HCD=y
+-# CONFIG_USB_SL811_HCD is not set
 -
--static void 
--NCR53c7x0_soft_reset (struct Scsi_Host *host) {
--    NCR53c7x0_local_declare();
--    unsigned long flags;
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    NCR53c7x0_local_setup(host);
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-CONFIG_USB_PRINTER=y
 -
--    local_irq_save(flags);
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
 -
--    /* Disable scsi chip and s/w level 7 ints */
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
 -
--#ifdef CONFIG_MVME16x
--    if (MACH_IS_MVME16x)
--    {
--        volatile unsigned long v;
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
 -
--        v = *(volatile unsigned long *)0xfff4006c;
--        v &= ~0x8000;
--        *(volatile unsigned long *)0xfff4006c = v;
--        v = *(volatile unsigned long *)0xfff4202c;
--        v &= ~0x10;
--        *(volatile unsigned long *)0xfff4202c = v;
--    }
--#endif
--    /* Anything specific for your hardware? */
--
--    /*
--     * Do a soft reset of the chip so that everything is 
--     * reinitialized to the power-on state.
--     *
--     * Basically follow the procedure outlined in the NCR53c700
--     * data manual under Chapter Six, How to Use, Steps Necessary to
--     * Start SCRIPTS, with the exception of actually starting the 
--     * script and setting up the synchronous transfer gunk.
--     */
--
--    /* Should we reset the scsi bus here??????????????????? */
--
--    NCR53c7x0_write8(ISTAT_REG_700, ISTAT_10_SRST);
--    NCR53c7x0_write8(ISTAT_REG_700, 0);
--
--    /*
--     * saved_dcntl is set up in NCR53c7x0_init() before it is overwritten
--     * here.  We should have some better way of working out the CF bit
--     * setting..
--     */
--
--    hostdata->saved_dcntl = DCNTL_10_EA|DCNTL_10_COM;
--    if (hostdata->scsi_clock > 50000000)
--      hostdata->saved_dcntl |= DCNTL_700_CF_3;
--    else
--    if (hostdata->scsi_clock > 37500000)
--        hostdata->saved_dcntl |= DCNTL_700_CF_2;
--#if 0
--    else
--      /* Any clocks less than 37.5MHz? */
--#endif
+-#
+-# USB port drivers
+-#
 -
--    if (hostdata->options & OPTION_DEBUG_TRACE)
--      NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM);
--    else
--      NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl);
--    /* Following disables snooping - snooping is not required, as non-
--     * cached pages are used for shared data, and appropriate use is
--     * made of cache_push/cache_clear.  Indeed, for 68060
--     * enabling snooping causes disk corruption of ext2fs free block
--     * bitmaps and the like.  If you have a 68060 with snooping hardwared
--     * on, then you need to enable CONFIG_060_WRITETHROUGH.
--     */
--    NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD);
--    /* Actually burst of eight, according to my 53c710 databook */
--    NCR53c7x0_write8(hostdata->dmode, DMODE_10_BL_8 | DMODE_10_FC2);
--    NCR53c7x0_write8(SCID_REG, 1 << host->this_id);
--    NCR53c7x0_write8(SBCL_REG, 0);
--    NCR53c7x0_write8(SCNTL1_REG, SCNTL1_ESR_700);
--    NCR53c7x0_write8(SCNTL0_REG, ((hostdata->options & OPTION_PARITY) ? 
--            SCNTL0_EPC : 0) | SCNTL0_EPG_700 | SCNTL0_ARB1 | SCNTL0_ARB2);
--
--    /*
--     * Enable all interrupts, except parity which we only want when
--     * the user requests it.
--     */
--
--    NCR53c7x0_write8(DIEN_REG, DIEN_700_BF |
--              DIEN_ABRT | DIEN_SSI | DIEN_SIR | DIEN_700_OPC);
--
--    NCR53c7x0_write8(SIEN_REG_700, ((hostdata->options & OPTION_PARITY) ?
--          SIEN_PAR : 0) | SIEN_700_STO | SIEN_RST | SIEN_UDC |
--              SIEN_SGE | SIEN_MA);
--
--#ifdef CONFIG_MVME16x
--    if (MACH_IS_MVME16x)
--    {
--        volatile unsigned long v;
--
--        /* Enable scsi chip and s/w level 7 ints */
--        v = *(volatile unsigned long *)0xfff40080;
--        v = (v & ~(0xf << 28)) | (4 << 28);
--        *(volatile unsigned long *)0xfff40080 = v;
--        v = *(volatile unsigned long *)0xfff4006c;
--        v |= 0x8000;
--        *(volatile unsigned long *)0xfff4006c = v;
--        v = *(volatile unsigned long *)0xfff4202c;
--        v = (v & ~0xff) | 0x10 | 4;
--        *(volatile unsigned long *)0xfff4202c = v;
--    }
--#endif
--    /* Anything needed for your hardware? */
--    local_irq_restore(flags);
--}
+-#
+-# USB Serial Converter support
+-#
+-# CONFIG_USB_SERIAL is not set
 -
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
 -
--/*
-- * Function static struct NCR53c7x0_cmd *allocate_cmd (Scsi_Cmnd *cmd)
-- * 
-- * Purpose : Return the first free NCR53c7x0_cmd structure (which are 
-- *    reused in a LIFO manner to minimize cache thrashing).
-- *
-- * Side effects : If we haven't yet scheduled allocation of NCR53c7x0_cmd
-- *    structures for this device, do so.  Attempt to complete all scheduled
-- *    allocations using get_zeroed_page(), putting NCR53c7x0_cmd structures on
-- *    the free list.  Teach programmers not to drink and hack.
-- *
-- * Inputs : cmd - SCSI command
-- *
-- * Returns : NCR53c7x0_cmd structure allocated on behalf of cmd;
-- *    NULL on failure.
-- */
+-#
+-# USB DSL modem support
+-#
 -
--static void
--my_free_page (void *addr, int dummy)
--{
--    /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
--     * XXX may be invalid (CONFIG_060_WRITETHROUGH)
--     */
--    kernel_set_cachemode((void *)addr, 4096, IOMAP_FULL_CACHING);
--    free_page ((u32)addr);
--}
--
--static struct NCR53c7x0_cmd *
--allocate_cmd (Scsi_Cmnd *cmd) {
--    struct Scsi_Host *host = cmd->device->host;
--    struct NCR53c7x0_hostdata *hostdata = 
--      (struct NCR53c7x0_hostdata *) host->hostdata[0];
--    u32 real;                 /* Real address */
--    int size;                 /* Size of *tmp */
--    struct NCR53c7x0_cmd *tmp;
--    unsigned long flags;
--
--    if (hostdata->options & OPTION_DEBUG_ALLOCATION)
--      printk ("scsi%d : num_cmds = %d, can_queue = %d\n"
--              "         target = %d, lun = %d, %s\n",
--          host->host_no, hostdata->num_cmds, host->can_queue,
--          cmd->device->id, cmd->device->lun, (hostdata->cmd_allocated[cmd->device->id] &
--              (1 << cmd->device->lun)) ? "already allocated" : "not allocated");
+-#
+-# USB Gadget Support
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
 -
--/*
-- * If we have not yet reserved commands for this I_T_L nexus, and
-- * the device exists (as indicated by permanent Scsi_Cmnd structures
-- * being allocated under 1.3.x, or being outside of scan_scsis in
-- * 1.2.x), do so now.
-- */
--    if (!(hostdata->cmd_allocated[cmd->device->id] & (1 << cmd->device->lun)) &&
--                              cmd->device && cmd->device->has_cmdblocks) {
--      if ((hostdata->extra_allocate + hostdata->num_cmds) < host->can_queue)
--          hostdata->extra_allocate += host->cmd_per_lun;
--      hostdata->cmd_allocated[cmd->device->id] |= (1 << cmd->device->lun);
--    }
--
--    for (; hostdata->extra_allocate > 0 ; --hostdata->extra_allocate, 
--      ++hostdata->num_cmds) {
--    /* historically, kmalloc has returned unaligned addresses; pad so we
--       have enough room to ROUNDUP */
--      size = hostdata->max_cmd_size + sizeof (void *);
--#ifdef FORCE_DSA_ALIGNMENT
--      /*
--       * 53c710 rev.0 doesn't have an add-with-carry instruction.
--       * Ensure we allocate enough memory to force alignment.
--       */
--      size += 256;
--#endif
--/* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */
--
--        if (size > 4096) {
--            printk (KERN_ERR "53c7xx: allocate_cmd size > 4K\n");
--          return NULL;
--      }
--        real = get_zeroed_page(GFP_ATOMIC);
--        if (real == 0)
--              return NULL;
--        cache_push(virt_to_phys((void *)real), 4096);
--        cache_clear(virt_to_phys((void *)real), 4096);
--        kernel_set_cachemode((void *)real, 4096, IOMAP_NOCACHE_SER);
--      tmp = ROUNDUP(real, void *);
--#ifdef FORCE_DSA_ALIGNMENT
--      {
--          if (((u32)tmp & 0xff) > CmdPageStart)
--              tmp = (struct NCR53c7x0_cmd *)((u32)tmp + 255);
--          tmp = (struct NCR53c7x0_cmd *)(((u32)tmp & ~0xff) + CmdPageStart);
--#if 0
--          printk ("scsi: size = %d, real = 0x%08x, tmp set to 0x%08x\n",
--                      size, real, (u32)tmp);
--#endif
--      }
--#endif
--      tmp->real = (void *)real;
--      tmp->size = size;                       
--      tmp->free = ((void (*)(void *, int)) my_free_page);
--      local_irq_save(flags);
--      tmp->next = hostdata->free;
--      hostdata->free = tmp;
--      local_irq_restore(flags);
--    }
--    local_irq_save(flags);
--    tmp = (struct NCR53c7x0_cmd *) hostdata->free;
--    if (tmp) {
--      hostdata->free = tmp->next;
--    }
--    local_irq_restore(flags);
--    if (!tmp)
--      printk ("scsi%d : can't allocate command for target %d lun %d\n",
--          host->host_no, cmd->device->id, cmd->device->lun);
--    return tmp;
--}
+-#
+-# LED devices
+-#
+-# CONFIG_NEW_LEDS is not set
 -
--/*
-- * Function static struct NCR53c7x0_cmd *create_cmd (Scsi_Cmnd *cmd) 
-- *
-- *
-- * Purpose : allocate a NCR53c7x0_cmd structure, initialize it based on the 
-- *    Scsi_Cmnd structure passed in cmd, including dsa and Linux field 
-- *    initialization, and dsa code relocation.
-- *
-- * Inputs : cmd - SCSI command
-- *
-- * Returns : NCR53c7x0_cmd structure corresponding to cmd,
-- *    NULL on failure.
-- */
--static struct NCR53c7x0_cmd *
--create_cmd (Scsi_Cmnd *cmd) {
--    NCR53c7x0_local_declare();
--    struct Scsi_Host *host = cmd->device->host;
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--        host->hostdata[0];    
--    struct NCR53c7x0_cmd *tmp;        /* NCR53c7x0_cmd structure for this command */
--    int datain,               /* Number of instructions per phase */
--      dataout;
--    int data_transfer_instructions, /* Count of dynamic instructions */
--      i;                      /* Counter */
--    u32 *cmd_datain,          /* Address of datain/dataout code */
--      *cmd_dataout;           /* Incremented as we assemble */
--#ifdef notyet
--    unsigned char *msgptr;    /* Current byte in select message */
--    int msglen;                       /* Length of whole select message */
--#endif
--    unsigned long flags;
--    u32 exp_select_indirect;  /* Used in sanity check */
--    NCR53c7x0_local_setup(cmd->device->host);
+-#
+-# LED drivers
+-#
 -
--    if (!(tmp = allocate_cmd (cmd)))
--      return NULL;
+-#
+-# LED Triggers
+-#
 -
--    /*
--     * Copy CDB and initialised result fields from Scsi_Cmnd to NCR53c7x0_cmd.
--     * We do this because NCR53c7x0_cmd may have a special cache mode
--     * selected to cope with lack of bus snooping, etc.
--     */
--
--    memcpy(tmp->cmnd, cmd->cmnd, 12);
--    tmp->result = cmd->result;
--
--    /*
--     * Decide whether we need to generate commands for DATA IN,
--     * DATA OUT, neither, or both based on the SCSI command 
--     */
--
--    switch (cmd->cmnd[0]) {
--    /* These commands do DATA IN */
--    case INQUIRY:
--    case MODE_SENSE:
--    case READ_6:
--    case READ_10:
--    case READ_CAPACITY:
--    case REQUEST_SENSE:
--    case READ_BLOCK_LIMITS:
--    case READ_TOC:
--      datain = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
--      dataout = 0;
--      break;
--    /* These commands do DATA OUT */
--    case MODE_SELECT: 
--    case WRITE_6:
--    case WRITE_10:
--#if 0
--      printk("scsi%d : command is ", host->host_no);
--      __scsi_print_command(cmd->cmnd);
--#endif
--#if 0
--      printk ("scsi%d : %d scatter/gather segments\n", host->host_no,
--          cmd->use_sg);
--#endif
--      datain = 0;
--      dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
--#if 0
--      hostdata->options |= OPTION_DEBUG_INTR;
--#endif
--      break;
--    /* 
--     * These commands do no data transfer, we should force an
--     * interrupt if a data phase is attempted on them.
--     */
--    case TEST_UNIT_READY:
--    case ALLOW_MEDIUM_REMOVAL:
--    case START_STOP:
--      datain = dataout = 0;
--      break;
--    /*
--     * We don't know about these commands, so generate code to handle
--     * both DATA IN and DATA OUT phases.  More efficient to identify them
--     * and add them to the above cases.
--     */
--    default:
--      printk("scsi%d : datain+dataout for command ", host->host_no);
--      __scsi_print_command(cmd->cmnd);
--      datain = dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
--    }
--
--    /*
--     * New code : so that active pointers work correctly regardless
--     *        of where the saved data pointer is at, we want to immediately
--     *        enter the dynamic code after selection, and on a non-data
--     *        phase perform a CALL to the non-data phase handler, with
--     *        returns back to this address.
--     *
--     *        If a phase mismatch is encountered in the middle of a 
--     *        Block MOVE instruction, we want to _leave_ that instruction
--     *        unchanged as the current case is, modify a temporary buffer,
--     *        and point the active pointer (TEMP) at that.
--     *
--     *        Furthermore, we want to implement a saved data pointer, 
--     *        set by the SAVE_DATA_POINTERs message.
--     *
--     *        So, the data transfer segments will change to 
--     *                CALL data_transfer, WHEN NOT data phase
--     *                MOVE x, x, WHEN data phase
--     *                ( repeat )
--     *                JUMP other_transfer
--     */
--
--    data_transfer_instructions = datain + dataout;
--
--    /*
--     * When we perform a request sense, we overwrite various things,
--     * including the data transfer code.  Make sure we have enough
--     * space to do that.
--     */
--
--    if (data_transfer_instructions < 2)
--      data_transfer_instructions = 2;
--
--
--    /*
--     * The saved data pointer is set up so that a RESTORE POINTERS message 
--     * will start the data transfer over at the beginning.
--     */
--
--    tmp->saved_data_pointer = virt_to_bus (hostdata->script) + 
--      hostdata->E_data_transfer;
--
--    /*
--     * Initialize Linux specific fields.
--     */
--
--    tmp->cmd = cmd;
--    tmp->next = NULL;
--    tmp->flags = 0;
--    tmp->dsa_next_addr = virt_to_bus(tmp->dsa) + hostdata->dsa_next - 
--      hostdata->dsa_start;
--    tmp->dsa_addr = virt_to_bus(tmp->dsa) - hostdata->dsa_start;
--
--    /* 
--     * Calculate addresses of dynamic code to fill in DSA
--     */
--
--    tmp->data_transfer_start = tmp->dsa + (hostdata->dsa_end - 
--      hostdata->dsa_start) / sizeof(u32);
--    tmp->data_transfer_end = tmp->data_transfer_start + 
--      2 * data_transfer_instructions;
--
--    cmd_datain = datain ? tmp->data_transfer_start : NULL;
--    cmd_dataout = dataout ? (datain ? cmd_datain + 2 * datain : tmp->
--      data_transfer_start) : NULL;
--
--    /*
--     * Fill in the NCR53c7x0_cmd structure as follows
--     * dsa, with fixed up DSA code
--     * datain code
--     * dataout code
--     */
--
--    /* Copy template code into dsa and perform all necessary fixups */
--    if (hostdata->dsa_fixup)
--      hostdata->dsa_fixup(tmp);
--
--    patch_dsa_32(tmp->dsa, dsa_next, 0, 0);
--    /*
--     * XXX is this giving 53c710 access to the Scsi_Cmnd in some way?
--     * Do we need to change it for caching reasons?
--     */
--    patch_dsa_32(tmp->dsa, dsa_cmnd, 0, virt_to_bus(cmd));
--
--    if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) {
--
--      exp_select_indirect = ((1 << cmd->device->id) << 16) |
--                      (hostdata->sync[cmd->device->id].sxfer_sanity << 8);
--
--      if (hostdata->sync[cmd->device->id].select_indirect !=
--                              exp_select_indirect) {
--          printk ("scsi%d :  sanity check failed select_indirect=0x%x\n",
--              host->host_no, hostdata->sync[cmd->device->id].select_indirect);
--          FATAL(host);
--
--      }
--    }
--
--    patch_dsa_32(tmp->dsa, dsa_select, 0,
--              hostdata->sync[cmd->device->id].select_indirect);
--
--    /*
--     * Right now, we'll do the WIDE and SYNCHRONOUS negotiations on
--     * different commands; although it should be trivial to do them
--     * both at the same time.
--     */
--    if (hostdata->initiate_wdtr & (1 << cmd->device->id)) {
--      memcpy ((void *) (tmp->select + 1), (void *) wdtr_message,
--          sizeof(wdtr_message));
--      patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(wdtr_message));
--      local_irq_save(flags);
--      hostdata->initiate_wdtr &= ~(1 << cmd->device->id);
--      local_irq_restore(flags);
--    } else if (hostdata->initiate_sdtr & (1 << cmd->device->id)) {
--      memcpy ((void *) (tmp->select + 1), (void *) sdtr_message, 
--          sizeof(sdtr_message));
--      patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(sdtr_message));
--      tmp->flags |= CMD_FLAG_SDTR;
--      local_irq_save(flags);
--      hostdata->initiate_sdtr &= ~(1 << cmd->device->id);
--      local_irq_restore(flags);
--    
--    }
--#if 1
--    else if (!(hostdata->talked_to & (1 << cmd->device->id)) &&
--              !(hostdata->options & OPTION_NO_ASYNC)) {
--
--      memcpy ((void *) (tmp->select + 1), (void *) async_message, 
--          sizeof(async_message));
--      patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(async_message));
--      tmp->flags |= CMD_FLAG_SDTR;
--    } 
--#endif
--    else 
--      patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1);
--
--    hostdata->talked_to |= (1 << cmd->device->id);
--    tmp->select[0] = (hostdata->options & OPTION_DISCONNECT) ? 
--      IDENTIFY (1, cmd->device->lun) : IDENTIFY (0, cmd->device->lun);
--    patch_dsa_32(tmp->dsa, dsa_msgout, 1, virt_to_bus(tmp->select));
--    patch_dsa_32(tmp->dsa, dsa_cmdout, 0, cmd->cmd_len);
--    patch_dsa_32(tmp->dsa, dsa_cmdout, 1, virt_to_bus(tmp->cmnd));
--    patch_dsa_32(tmp->dsa, dsa_dataout, 0, cmd_dataout ? 
--          virt_to_bus (cmd_dataout)
--      : virt_to_bus (hostdata->script) + hostdata->E_other_transfer);
--    patch_dsa_32(tmp->dsa, dsa_datain, 0, cmd_datain ? 
--          virt_to_bus (cmd_datain) 
--      : virt_to_bus (hostdata->script) + hostdata->E_other_transfer);
--    /* 
--     * XXX - need to make endian aware, should use separate variables
--     * for both status and message bytes.
--     */
--    patch_dsa_32(tmp->dsa, dsa_msgin, 0, 1);
--/* 
-- * FIXME : these only works for little endian.  We probably want to 
-- *    provide message and status fields in the NCR53c7x0_cmd 
-- *    structure, and assign them to cmd->result when we're done.
-- */
--#ifdef BIG_ENDIAN
--    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 2);
--    patch_dsa_32(tmp->dsa, dsa_status, 0, 1);
--    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result) + 3);
--#else
--    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 1);
--    patch_dsa_32(tmp->dsa, dsa_status, 0, 1);
--    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result));
--#endif
--    patch_dsa_32(tmp->dsa, dsa_msgout_other, 0, 1);
--    patch_dsa_32(tmp->dsa, dsa_msgout_other, 1, 
--      virt_to_bus(&(hostdata->NCR53c7xx_msg_nop)));
--    
--    /*
--     * Generate code for zero or more of the DATA IN, DATA OUT phases 
--     * in the format 
--     *
--     * CALL data_transfer, WHEN NOT phase
--     * MOVE first buffer length, first buffer address, WHEN phase
--     * ...
--     * MOVE last buffer length, last buffer address, WHEN phase
--     * JUMP other_transfer
--     */
+-#
+-# InfiniBand support
+-#
+-# CONFIG_INFINIBAND is not set
 -
--/* 
-- * See if we're getting to data transfer by generating an unconditional 
-- * interrupt.
-- */
--#if 0
--    if (datain) {
--      cmd_datain[0] = 0x98080000;
--      cmd_datain[1] = 0x03ffd00d;
--      cmd_datain += 2;
--    }
--#endif
+-#
+-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+-#
+-# CONFIG_EDAC is not set
 -
--/* 
-- * XXX - I'm undecided whether all of this nonsense is faster
-- * in the long run, or whether I should just go and implement a loop
-- * on the NCR chip using table indirect mode?
-- *
-- * In any case, this is how it _must_ be done for 53c700/700-66 chips,
-- * so this stays even when we come up with something better.
-- *
-- * When we're limited to 1 simultaneous command, no overlapping processing,
-- * we're seeing 630K/sec, with 7% CPU usage on a slow Syquest 45M
-- * drive.
-- *
-- * Not bad, not good. We'll see.
-- */
+-#
+-# Real Time Clock
+-#
+-# CONFIG_RTC_CLASS is not set
 -
--    tmp->bounce.len = 0;      /* Assume aligned buffer */
+-#
+-# DMA Engine support
+-#
+-# CONFIG_DMA_ENGINE is not set
 -
--    for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4, 
--      cmd_dataout += 4, ++i) {
--      u32 vbuf = cmd->use_sg
--          ? (u32)page_address(((struct scatterlist *)cmd->request_buffer)[i].page)+
--            ((struct scatterlist *)cmd->request_buffer)[i].offset
--          : (u32)(cmd->request_buffer);
--      u32 bbuf = virt_to_bus((void *)vbuf);
--      u32 count = cmd->use_sg ?
--          ((struct scatterlist *)cmd->request_buffer)[i].length :
--          cmd->request_bufflen;
+-#
+-# DMA Clients
+-#
 -
--      /*
--       * If we have buffers which are not aligned with 16 byte cache
--       * lines, then we just hope nothing accesses the other parts of
--       * those cache lines while the transfer is in progress.  That would
--       * fill the cache, and subsequent reads of the dma data would pick
--       * up the wrong thing.
--       * XXX We need a bounce buffer to handle that correctly.
--       */
+-#
+-# DMA Devices
+-#
 -
--      if (((bbuf & 15) || (count & 15)) && (datain || dataout))
--      {
--          /* Bounce buffer needed */
--          if (cmd->use_sg)
--              printk ("53c7xx: Non-aligned buffer with use_sg\n");
--          else if (datain && dataout)
--                printk ("53c7xx: Non-aligned buffer with datain && dataout\n");
--            else if (count > 256)
--              printk ("53c7xx: Non-aligned transfer > 256 bytes\n");
--          else
--          {
--                  if (datain)
--                  {
--                      tmp->bounce.len = count;
--                      tmp->bounce.addr = vbuf;
--                      bbuf = virt_to_bus(tmp->bounce.buf);
--                      tmp->bounce.buf[0] = 0xff;
--                      tmp->bounce.buf[1] = 0xfe;
--                      tmp->bounce.buf[2] = 0xfd;
--                      tmp->bounce.buf[3] = 0xfc;
--                  }
--                  if (dataout)
--                  {
--                      memcpy ((void *)tmp->bounce.buf, (void *)vbuf, count);
--                      bbuf = virt_to_bus(tmp->bounce.buf);
--                  }
--          }
--      }
--
--      if (datain) {
--            cache_clear(virt_to_phys((void *)vbuf), count);
--          /* CALL other_in, WHEN NOT DATA_IN */  
--          cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL | 
--              DCMD_TCI_IO) << 24) | 
--              DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
--          cmd_datain[1] = virt_to_bus (hostdata->script) + 
--              hostdata->E_other_in;
--          /* MOVE count, buf, WHEN DATA_IN */
--          cmd_datain[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | DCMD_BMI_IO) 
--              << 24) | count;
--          cmd_datain[3] = bbuf;
--#if 0
--          print_insn (host, cmd_datain, "dynamic ", 1);
--          print_insn (host, cmd_datain + 2, "dynamic ", 1);
--#endif
--      }
--      if (dataout) {
--            cache_push(virt_to_phys((void *)vbuf), count);
--          /* CALL other_out, WHEN NOT DATA_OUT */
--          cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL) << 24) | 
--              DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
--          cmd_dataout[1] = virt_to_bus(hostdata->script) + 
--              hostdata->E_other_out;
--          /* MOVE count, buf, WHEN DATA+OUT */
--          cmd_dataout[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I) << 24) 
--              | count;
--          cmd_dataout[3] = bbuf;
--#if 0
--          print_insn (host, cmd_dataout, "dynamic ", 1);
--          print_insn (host, cmd_dataout + 2, "dynamic ", 1);
--#endif
--      }
--    }
+-#
+-# Virtualization
+-#
+-# CONFIG_KVM is not set
 -
--    /*
--     * Install JUMP instructions after the data transfer routines to return
--     * control to the do_other_transfer routines.
--     */
--  
--    
--    if (datain) {
--      cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) |
--          DBC_TCI_TRUE;
--      cmd_datain[1] = virt_to_bus(hostdata->script) + 
--          hostdata->E_other_transfer;
--#if 0
--      print_insn (host, cmd_datain, "dynamic jump ", 1);
--#endif
--      cmd_datain += 2; 
--    }
--#if 0
--    if (datain) {
--      cmd_datain[0] = 0x98080000;
--      cmd_datain[1] = 0x03ffdeed;
--      cmd_datain += 2;
--    }
--#endif
--    if (dataout) {
--      cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) |
--          DBC_TCI_TRUE;
--      cmd_dataout[1] = virt_to_bus(hostdata->script) + 
--          hostdata->E_other_transfer;
--#if 0
--      print_insn (host, cmd_dataout, "dynamic jump ", 1);
--#endif
--      cmd_dataout += 2;
--    }
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-CONFIG_EXT2_FS_XATTR=y
+-CONFIG_EXT2_FS_POSIX_ACL=y
+-# CONFIG_EXT2_FS_SECURITY is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-CONFIG_EXT3_FS_POSIX_ACL=y
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-# CONFIG_JBD_DEBUG is not set
+-CONFIG_FS_MBCACHE=y
+-CONFIG_REISERFS_FS=y
+-# CONFIG_REISERFS_CHECK is not set
+-# CONFIG_REISERFS_PROC_INFO is not set
+-CONFIG_REISERFS_FS_XATTR=y
+-CONFIG_REISERFS_FS_POSIX_ACL=y
+-# CONFIG_REISERFS_FS_SECURITY is not set
+-# CONFIG_JFS_FS is not set
+-CONFIG_FS_POSIX_ACL=y
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-CONFIG_DNOTIFY=y
+-# CONFIG_AUTOFS_FS is not set
+-CONFIG_AUTOFS4_FS=y
+-CONFIG_FUSE_FS=m
+-CONFIG_GENERIC_ACL=y
 -
--    return tmp;
--}
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-CONFIG_ISO9660_FS=y
+-# CONFIG_JOLIET is not set
+-# CONFIG_ZISOFS is not set
+-CONFIG_UDF_FS=m
+-CONFIG_UDF_NLS=y
 -
--/*
-- * Function : int NCR53c7xx_queue_command (Scsi_Cmnd *cmd,
-- *      void (*done)(Scsi_Cmnd *))
-- *
-- * Purpose :  enqueues a SCSI command
-- *
-- * Inputs : cmd - SCSI command, done - function called on completion, with
-- *      a pointer to the command descriptor.
-- *
-- * Returns : 0
-- *
-- * Side effects :
-- *      cmd is added to the per instance driver issue_queue, with major
-- *      twiddling done to the host specific fields of cmd.  If the
-- *      process_issue_queue coroutine isn't running, it is restarted.
-- * 
-- * NOTE : we use the host_scribble field of the Scsi_Cmnd structure to 
-- *    hold our own data, and pervert the ptr field of the SCp field
-- *    to create a linked list.
-- */
+-#
+-# 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=m
+-# CONFIG_NTFS_DEBUG is not set
+-CONFIG_NTFS_RW=y
 -
--int
--NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) {
--    struct Scsi_Host *host = cmd->device->host;
--    struct NCR53c7x0_hostdata *hostdata = 
--      (struct NCR53c7x0_hostdata *) host->hostdata[0];
--    unsigned long flags;
--    Scsi_Cmnd *tmp;
--
--    cmd->scsi_done = done;
--    cmd->host_scribble = NULL;
--    cmd->SCp.ptr = NULL;
--    cmd->SCp.buffer = NULL;
--
--#ifdef VALID_IDS
--    /* Ignore commands on invalid IDs */
--    if (!hostdata->valid_ids[cmd->device->id]) {
--        printk("scsi%d : ignoring target %d lun %d\n", host->host_no,
--            cmd->device->id, cmd->device->lun);
--        cmd->result = (DID_BAD_TARGET << 16);
--        done(cmd);
--        return 0;
--    }
--#endif
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-CONFIG_TMPFS_POSIX_ACL=y
+-CONFIG_HUGETLBFS=y
+-CONFIG_HUGETLB_PAGE=y
+-CONFIG_RAMFS=y
+-# CONFIG_CONFIGFS_FS is not set
 -
--    local_irq_save(flags);
--    if ((hostdata->options & (OPTION_DEBUG_INIT_ONLY|OPTION_DEBUG_PROBE_ONLY)) 
--      || ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) &&
--          !(hostdata->debug_lun_limit[cmd->device->id] & (1 << cmd->device->lun)))
--#ifdef LINUX_1_2
--      || cmd->device->id > 7
--#else
--      || cmd->device->id >= host->max_id
--#endif
--      || cmd->device->id == host->this_id
--      || hostdata->state == STATE_DISABLED) {
--      printk("scsi%d : disabled or bad target %d lun %d\n", host->host_no,
--          cmd->device->id, cmd->device->lun);
--      cmd->result = (DID_BAD_TARGET << 16);
--      done(cmd);
--      local_irq_restore(flags);
--      return 0;
--    }
+-#
+-# Layered filesystems
+-#
+-# CONFIG_UNION_FS is not set
 -
--    if ((hostdata->options & OPTION_DEBUG_NCOMMANDS_LIMIT) &&
--      (hostdata->debug_count_limit == 0)) {
--      printk("scsi%d : maximum commands exceeded\n", host->host_no);
--      cmd->result = (DID_BAD_TARGET << 16);
--      done(cmd);
--      local_irq_restore(flags);
--      return 0;
--    }
--
--    if (hostdata->options & OPTION_DEBUG_READ_ONLY) {
--      switch (cmd->cmnd[0]) {
--      case WRITE_6:
--      case WRITE_10:
--          printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n",
--              host->host_no);
--          cmd->result = (DID_BAD_TARGET << 16);
--          done(cmd);
--          local_irq_restore(flags);
--          return 0;
--      }
--    }
--
--    if ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) &&
--          hostdata->debug_count_limit != -1) 
--      --hostdata->debug_count_limit;
--
--    cmd->result = 0xffff;     /* The NCR will overwrite message
--                                     and status with valid data */
--    cmd->host_scribble = (unsigned char *) tmp = create_cmd (cmd);
--
--    /*
--     * REQUEST SENSE commands are inserted at the head of the queue 
--     * so that we do not clear the contingent allegiance condition
--     * they may be looking at.
--     */
--
--    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
--      cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
--      hostdata->issue_queue = cmd;
--    } else {
--      for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->SCp.ptr; 
--              tmp = (Scsi_Cmnd *) tmp->SCp.ptr);
--      tmp->SCp.ptr = (unsigned char *) cmd;
--    }
--    local_irq_restore(flags);
--    run_process_issue_queue();
--    return 0;
--}
+-#
+-# 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_CRAMFS is not set
+-# 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
 -
--/*
-- * Function : void to_schedule_list (struct Scsi_Host *host,
-- *    struct NCR53c7x0_hostdata * hostdata, Scsi_Cmnd *cmd)
-- *
-- * Purpose : takes a SCSI command which was just removed from the 
-- *    issue queue, and deals with it by inserting it in the first
-- *    free slot in the schedule list or by terminating it immediately.
-- *
-- * Inputs : 
-- *    host - SCSI host adapter; hostdata - hostdata structure for 
-- *    this adapter; cmd - a pointer to the command; should have 
-- *    the host_scribble field initialized to point to a valid 
-- *    
-- * Side effects : 
-- *      cmd is added to the per instance schedule list, with minor 
-- *      twiddling done to the host specific fields of cmd.
-- *
-- */
+-#
+-# Network File Systems
+-#
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-CONFIG_NFSD=y
+-CONFIG_NFSD_V3=y
+-# CONFIG_NFSD_V3_ACL is not set
+-# CONFIG_NFSD_V4 is not set
+-CONFIG_NFSD_TCP=y
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_EXPORTFS=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-CONFIG_SMB_FS=m
+-# CONFIG_SMB_NLS_DEFAULT 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
 -
--static __inline__ void
--to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
--    struct NCR53c7x0_cmd *cmd) {
--    NCR53c7x0_local_declare();
--    Scsi_Cmnd *tmp = cmd->cmd;
--    unsigned long flags;
--    /* dsa start is negative, so subtraction is used */
--    volatile u32 *ncrcurrent;
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
 -
--    int i;
--    NCR53c7x0_local_setup(host);
--#if 0
--    printk("scsi%d : new dsa is 0x%lx (virt 0x%p)\n", host->host_no, 
--      virt_to_bus(hostdata->dsa), hostdata->dsa);
--#endif
+-#
+-# Native Language Support
+-#
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-CONFIG_NLS_CODEPAGE_437=y
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-CONFIG_NLS_CODEPAGE_850=y
+-CONFIG_NLS_CODEPAGE_852=y
+-# 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=y
+-CONFIG_NLS_ISO8859_1=y
+-CONFIG_NLS_ISO8859_2=y
+-# 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=y
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-CONFIG_NLS_UTF8=y
 -
--    local_irq_save(flags);
--    
--    /* 
--     * Work around race condition : if an interrupt fired and we 
--     * got disabled forget about this command.
--     */
--
--    if (hostdata->state == STATE_DISABLED) {
--      printk("scsi%d : driver disabled\n", host->host_no);
--      tmp->result = (DID_BAD_TARGET << 16);
--      cmd->next = (struct NCR53c7x0_cmd *) hostdata->free;
--      hostdata->free = cmd;
--      tmp->scsi_done(tmp);
--      local_irq_restore(flags);
--      return;
--    }
--
--    for (i = host->can_queue, ncrcurrent = hostdata->schedule; 
--      i > 0  && ncrcurrent[0] != hostdata->NOP_insn;
--      --i, ncrcurrent += 2 /* JUMP instructions are two words */);
--
--    if (i > 0) {
--      ++hostdata->busy[tmp->device->id][tmp->device->lun];
--      cmd->next = hostdata->running_list;
--      hostdata->running_list = cmd;
--
--      /* Restore this instruction to a NOP once the command starts */
--      cmd->dsa [(hostdata->dsa_jump_dest - hostdata->dsa_start) / 
--          sizeof(u32)] = (u32) virt_to_bus ((void *)ncrcurrent);
--      /* Replace the current jump operand.  */
--      ncrcurrent[1] =
--          virt_to_bus ((void *) cmd->dsa) + hostdata->E_dsa_code_begin -
--          hostdata->E_dsa_code_template;
--      /* Replace the NOP instruction with a JUMP */
--      ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) |
--          DBC_TCI_TRUE;
--    }  else {
--      printk ("scsi%d: no free slot\n", host->host_no);
--      disable(host);
--      tmp->result = (DID_ERROR << 16);
--      cmd->next = (struct NCR53c7x0_cmd *) hostdata->free;
--      hostdata->free = cmd;
--      tmp->scsi_done(tmp);
--      local_irq_restore(flags);
--      return;
--    }
+-#
+-# Distributed Lock Manager
+-#
+-# CONFIG_DLM is not set
 -
--    /* 
--     * If the NCR chip is in an idle state, start it running the scheduler
--     * immediately.  Otherwise, signal the chip to jump to schedule as 
--     * soon as it is idle.
--     */
+-#
+-# Instrumentation Support
+-#
+-CONFIG_PROFILING=y
+-CONFIG_OPROFILE=y
+-CONFIG_KPROBES=y
 -
--    if (hostdata->idle) {
--      hostdata->idle = 0;
--      hostdata->state = STATE_RUNNING;
--      NCR53c7x0_write32 (DSP_REG,  virt_to_bus ((void *)hostdata->schedule));
--      if (hostdata->options & OPTION_DEBUG_TRACE)
--          NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
--                              DCNTL_SSM | DCNTL_STD);
--    } else {
--      NCR53c7x0_write8(hostdata->istat, ISTAT_10_SIGP);
--    }
+-#
+-# Kernel hacking
+-#
+-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+-CONFIG_PRINTK_TIME=y
+-# CONFIG_ENABLE_MUST_CHECK is not set
+-CONFIG_MAGIC_SYSRQ=y
+-CONFIG_UNUSED_SYMBOLS=y
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_DEBUG_SLAB is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_LOCK_ALLOC is not set
+-# CONFIG_PROVE_LOCKING is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_HIGHMEM is not set
+-CONFIG_DEBUG_BUGVERBOSE=y
+-CONFIG_DEBUG_INFO=y
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_FRAME_POINTER is not set
+-# CONFIG_UNWIND_INFO is not set
+-# CONFIG_FORCED_INLINING is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_LKDTM is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_WANT_EXTRA_DEBUG_INFORMATION is not set
+-# CONFIG_KGDB is not set
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_DEBUG_STACKOVERFLOW=y
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_RODATA is not set
+-# CONFIG_4KSTACKS is not set
+-CONFIG_X86_FIND_SMP_CONFIG=y
+-CONFIG_X86_MPPARSE=y
+-CONFIG_DOUBLEFAULT=y
 -
--    local_irq_restore(flags);
--}
+-#
+-# Linux VServer
+-#
+-CONFIG_VSERVER_FILESHARING=y
+-CONFIG_VSERVER_AUTO_LBACK=y
+-CONFIG_VSERVER_AUTO_SINGLE=y
+-CONFIG_VSERVER_COWBL=y
+-# CONFIG_VSERVER_VTIME is not set
+-# CONFIG_VSERVER_DEVICE is not set
+-CONFIG_VSERVER_PROC_SECURE=y
+-CONFIG_VSERVER_HARDCPU=y
+-CONFIG_VSERVER_IDLETIME=y
+-# CONFIG_VSERVER_IDLELIMIT is not set
+-# CONFIG_TAGGING_NONE is not set
+-# CONFIG_TAGGING_UID16 is not set
+-# CONFIG_TAGGING_GID16 is not set
+-CONFIG_TAGGING_ID24=y
+-# CONFIG_TAGGING_INTERN is not set
+-# CONFIG_TAG_NFSD is not set
+-# CONFIG_VSERVER_PRIVACY is not set
+-CONFIG_VSERVER_CONTEXTS=256
+-CONFIG_VSERVER_WARN=y
+-# CONFIG_VSERVER_DEBUG is not set
+-CONFIG_VSERVER=y
 -
--/*
-- * Function : busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata 
-- *    *hostdata, Scsi_Cmnd *cmd)
-- *
-- * Purpose : decide if we can pass the given SCSI command on to the 
-- *    device in question or not.
-- *  
-- * Returns : non-zero when we're busy, 0 when we aren't.
-- */
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
+-# CONFIG_CRYPTO is not set
 -
--static __inline__ int
--busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, 
--    Scsi_Cmnd *cmd) {
--    /* FIXME : in the future, this needs to accommodate SCSI-II tagged
--       queuing, and we may be able to play with fairness here a bit.
--     */
--    return hostdata->busy[cmd->device->id][cmd->device->lun];
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-CONFIG_CRC_CCITT=y
+-CONFIG_CRC16=y
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-CONFIG_LIBCRC32C=y
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_GENERIC_IRQ_PROBE=y
+-CONFIG_GENERIC_PENDING_IRQ=y
+-CONFIG_X86_SMP=y
+-CONFIG_X86_HT=y
+-CONFIG_X86_BIOS_REBOOT=y
+-CONFIG_X86_TRAMPOLINE=y
+-CONFIG_KTIME_SCALAR=y
+diff -Nurb linux-2.6.22-590/Documentation/DocBook/Makefile linux-2.6.22-570/Documentation/DocBook/Makefile
+--- linux-2.6.22-590/Documentation/DocBook/Makefile    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/DocBook/Makefile    2007-07-08 19:32:17.000000000 -0400
+@@ -11,7 +11,7 @@
+           procfs-guide.xml writing_usb_driver.xml \
+           kernel-api.xml filesystems.xml lsm.xml usb.xml \
+           gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
+-          genericirq.xml kgdb.xml
++          genericirq.xml
+ ###
+ # The build process is as follows (targets):
+diff -Nurb linux-2.6.22-590/Documentation/DocBook/kgdb.tmpl linux-2.6.22-570/Documentation/DocBook/kgdb.tmpl
+--- linux-2.6.22-590/Documentation/DocBook/kgdb.tmpl   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/DocBook/kgdb.tmpl   1969-12-31 19:00:00.000000000 -0500
+@@ -1,250 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8"?>
+-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+-      "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+-
+-<book id="kgdbInternals">
+- <bookinfo>
+-  <title>KGDB Internals</title>
+-
+-  <authorgroup>
+-   <author>
+-    <firstname>Tom</firstname>
+-    <surname>Rini</surname>
+-    <affiliation>
+-     <address>
+-      <email>trini@kernel.crashing.org</email>
+-     </address>
+-    </affiliation>
+-   </author>
+-  </authorgroup>
+-
+-  <authorgroup>
+-   <author>
+-    <firstname>Amit S.</firstname>
+-    <surname>Kale</surname>
+-    <affiliation>
+-     <address>
+-      <email>amitkale@linsyssoft.com</email>
+-     </address>
+-    </affiliation>
+-   </author>
+-  </authorgroup>
+-
+-  <copyright>
+-   <year>2004-2005</year>
+-   <holder>MontaVista Software, Inc.</holder>
+-  </copyright>
+-  <copyright>
+-   <year>2004</year>
+-   <holder>Amit S. Kale</holder>
+-  </copyright>
+-
+-  <legalnotice>
+-   <para>
+-   This file is licensed under the terms of the GNU General Public License
+-   version 2. This program is licensed "as is" without any warranty of any
+-   kind, whether express or implied.
+-   </para>
+-
+-  </legalnotice>
+- </bookinfo>
+-
+-<toc></toc>
+-  <chapter id="Introduction">
+-    <title>Introduction</title>
+-    <para>
+-    kgdb is a source level debugger for linux kernel. It is used along
+-    with gdb to debug a linux kernel. Kernel developers can debug a kernel
+-    similar to application programs with the use of kgdb. It makes it
+-    possible to place breakpoints in kernel code, step through the code
+-    and observe variables.
+-    </para>
+-    <para>
+-    Two machines are required for using kgdb. One of these machines is a
+-    development machine and the other is a test machine. The machines are
+-    typically connected through a serial line, a null-modem cable which
+-    connects their serial ports.  It is also possible however, to use an
+-    ethernet connection between the machines.  The kernel to be debugged
+-    runs on the test machine. gdb runs on the development machine. The
+-    serial line or ethernet connection is used by gdb to communicate to
+-    the kernel being debugged.
+-    </para>
+-  </chapter>
+-  <chapter id="CompilingAKernel">
+-    <title>Compiling a kernel</title>
+-    <para>
+-    To enable <symbol>CONFIG_KGDB</symbol>, look under the "Kernel debugging"
+-    and then select "KGDB: kernel debugging with remote gdb".
+-    </para>
+-    <para>
+-    The first choice for I/O is <symbol>CONFIG_KGDB_ONLY_MODULES</symbol>.
+-    This means that you will only be able to use KGDB after loading a
+-    kernel module that defines how you want to be able to talk with
+-    KGDB.  There are two other choices (more on some architectures) that
+-    can be enabled as modules later, if not picked here.
+-    </para>
+-    <para>The first of these is <symbol>CONFIG_KGDB_8250_NOMODULE</symbol>.
+-    This has sub-options such as <symbol>CONFIG_KGDB_SIMPLE_SERIAL</symbol>
+-    which toggles choosing the serial port by ttyS number or by specifying
+-    a port and IRQ number.
+-    </para>
+-    <para>
+-    The second of these choices on most systems for I/O is
+-    <symbol>CONFIG_KGDBOE</symbol>. This requires that the machine to be
+-    debugged has an ethernet card which supports the netpoll API, such as
+-    the cards supported by <symbol>CONFIG_E100</symbol>.  There are no
+-    sub-options for this, but a kernel command line option is required.
+-    </para>
+-  </chapter>
+-  <chapter id="BootingTheKernel">
+-    <title>Booting the kernel</title>
+-    <para>
+-    The Kernel command line option <constant>kgdbwait</constant> makes kgdb
+-    wait for gdb connection during booting of a kernel.  If the
+-    <symbol>CONFIG_KGDB_8250</symbol> driver is used (or if applicable,
+-    another serial driver) this breakpoint will happen very early on, before
+-    console output.  If you wish to change serial port information and you
+-    have enabled both <symbol>CONFIG_KGDB_8250</symbol> and
+-    <symbol>CONFIG_KGDB_SIMPLE_SERIAL</symbol> then you must pass the option
+-    <constant>kgdb8250=&lt;io or mmio&gt;,&lt;address&gt;,&lt;baud
+-    rate&gt;,&lt;irq&gt;</constant> before <constant>kgdbwait</constant>.
+-    The values <constant>io</constant> or <constant>mmio</constant> refer to
+-    if the address being passed next needs to be memory mapped
+-    (<constant>mmio</constant>) or not. The <constant>address</constant> must
+-    be passed in hex and is the hardware address and will be remapped if
+-    passed as <constant>mmio</constant>. The value
+-    <constant>baud rate</constant> and <constant>irq</constant> are base-10.
+-    The supported values for <constant>baud rate</constant> are
+-    <constant>9600</constant>, <constant>19200</constant>,
+-    <constant>38400</constant>, <constant>57600</constant>, and
+-    <constant>115200</constant>.
+-    </para>
+-    <para>
+-    To have KGDB stop the kernel and wait, with the compiled values for the
+-    serial driver, pass in: <constant>kgdbwait</constant>.
+-    </para>
+-    <para>
+-    To specify the values of the SH SCI(F) serial port at boot:
+-    <constant>kgdbsci=0,115200</constant>.
+-    </para>
+-    <para>
+-    To specify the values of the serial port at boot:
+-    <constant>kgdb8250=io,3f8,115200,3</constant>.
+-    On IA64 this could also be:
+-    <constant>kgdb8250=mmio,0xff5e0000,115200,74</constant>
+-    And to have KGDB also stop the kernel and wait for GDB to connect, pass in
+-    <constant>kgdbwait</constant> after this arguement.
+-    </para>
+-    <para>
+-    To configure the <symbol>CONFIG_KGDBOE</symbol> driver, pass in
+-    <constant>kgdboe=[src-port]@&lt;src-ip&gt;/[dev],[tgt-port]@&lt;tgt-ip&gt;/[tgt-macaddr]</constant>
+-    where:
+-    <itemizedlist>
+-      <listitem><para>src-port (optional): source for UDP packets (defaults to <constant>6443</constant>)</para></listitem>
+-      <listitem><para>src-ip: source IP to use (interface address)</para></listitem>
+-      <listitem><para>dev (optional): network interface (<constant>eth0</constant>)</para></listitem>
+-      <listitem><para>tgt-port (optional): port GDB will use (defaults to <constant>6442</constant>)</para></listitem>
+-      <listitem><para>tgt-ip: IP address GDB will be connecting from</para></listitem>
+-      <listitem><para>tgt-macaddr (optional): ethernet MAC address for logging agent (default is broadcast)</para></listitem>
+-    </itemizedlist>
+-    </para>
+-    <para>
+-    The <symbol>CONFIG_KGDBOE</symbol> driver can be reconfigured at run
+-    time, if <symbol>CONFIG_SYSFS</symbol> and
+-    <symbol>CONFIG_MODULES</symbol> by echo'ing a new config string to
+-    <constant>/sys/module/kgdboe/parameter/kgdboe</constant>.  The
+-    driver can be unconfigured with the special string
+-    <constant>not_configured</constant>.
+-    </para>
+-  </chapter>
+-  <chapter id="ConnectingGDB">
+-  <title>Connecting gdb</title>
+-    <para>
+-    If you have used any of the methods to have KGDB stop and create
+-    an initial breakpoint described in the previous chapter, kgdb prints
+-    the message "Waiting for connection from remote gdb..." on the console
+-    and waits for connection from gdb. At this point you connect gdb to kgdb.
+-    </para>
+-    <para>
+-    Example (serial):
+-    </para>
+-    <programlisting>
+-    % gdb ./vmlinux
+-    (gdb) set remotebaud 115200
+-    (gdb) target remote /dev/ttyS0
+-    </programlisting>
+-    <para>
+-    Example (ethernet):
+-    </para>
+-    <programlisting>
+-    % gdb ./vmlinux
+-    (gdb) target remote udp:192.168.2.2:6443
+-    </programlisting>
+-    <para>
+-    Once connected, you can debug a kernel the way you would debug an
+-    application program.
+-    </para>
+-  </chapter>
+-  <chapter id="ArchitectureNotes">
+-    <title>Architecture specific notes</title>
+-      <para>
+-      SuperH: The NMI switch found on some boards can be used to trigger an
+-      initial breakpoint.  Subsequent triggers do nothing.  If console
+-      is enabled on the SCI(F) serial port, and that is the port being used
+-      for KGDB, then you must trigger a breakpoint via sysrq, NMI, or
+-      some other method prior to connecting, or echo a control-c to the
+-      serial port.  Also, to use the SCI(F) port for KGDB, the
+-      <symbol>CONFIG_SERIAL_SH_SCI</symbol> driver must be enabled.
+-      </para>
+-  </chapter>
+-  <chapter id="CommonBackEndReq">
+-    <title>The common backend (required)</title>
+-      <para>
+-      There are a few flags which must be set on every architecture in
+-      their &lt;asm/kgdb.h&gt; file.  These are:
+-      <itemizedlist>
+-        <listitem>
+-        <para>
+-        NUMREGBYTES: The size in bytes of all of the registers, so
+-        that we can ensure they will all fit into a packet.
+-        </para>
+-        <para>
+-        BUFMAX: The size in bytes of the buffer GDB will read into.
+-        This must be larger than NUMREGBYTES.
+-        </para>
+-        <para>
+-        CACHE_FLUSH_IS_SAFE: Set to one if it always safe to call
+-        flush_cache_range or flush_icache_range.  On some architectures,
+-        these functions may not be safe to call on SMP since we keep other
+-        CPUs in a holding pattern.
+-        </para>
+-      </listitem>
+-      </itemizedlist>
+-      </para>
+-      <para>
+-      There are also the following functions for the common backend,
+-      found in kernel/kgdb.c that must be supplied by the
+-      architecture-specific backend.  No weak version of these is provided.
+-      </para>
+-!Iinclude/linux/kgdb.h
+-  </chapter>
+-  <chapter id="CommonBackEndOpt">
+-    <title>The common backend (optional)</title>
+-      <para>
+-      These functions are part of the common backend, found in kernel/kgdb.c
+-      and are optionally implemented.  Some functions (with _hw_ in the name)
+-      end up being required on arches which use hardware breakpoints.
+-      </para>
+-!Ikernel/kgdb.c
+-  </chapter>
+-  <chapter id="DriverSpecificFunctions">
+-    <title>Driver-Specific Functions</title>
+-      <para>
+-      Some of the I/O drivers have additional functions that can be
+-      called, that are specific to the driver.  Calls from other places
+-      to these functions must be wrapped in #ifdefs for the driver in
+-      question.
+-      </para>
+-!Idrivers/serial/8250_kgdb.c
+-   </chapter>
+-</book>
+diff -Nurb linux-2.6.22-590/Documentation/accounting/getdelays.c linux-2.6.22-570/Documentation/accounting/getdelays.c
+--- linux-2.6.22-590/Documentation/accounting/getdelays.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/accounting/getdelays.c      2007-07-08 19:32:17.000000000 -0400
+@@ -49,7 +49,6 @@
+ int dbg;
+ int print_delays;
+ int print_io_accounting;
+-int print_task_context_switch_counts;
+ __u64 stime, utime;
+ #define PRINTF(fmt, arg...) {                 \
+@@ -196,7 +195,7 @@
+              "IO    %15s%15s\n"
+              "      %15llu%15llu\n"
+              "MEM   %15s%15s\n"
+-             "      %15llu%15llu\n"
++             "      %15llu%15llu\n\n",
+              "count", "real total", "virtual total", "delay total",
+              t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total,
+              t->cpu_delay_total,
+@@ -205,14 +204,6 @@
+              "count", "delay total", t->swapin_count, t->swapin_delay_total);
+ }
+-void task_context_switch_counts(struct taskstats *t)
+-{
+-      printf("\n\nTask   %15s%15s\n"
+-             "       %15lu%15lu\n",
+-             "voluntary", "nonvoluntary",
+-             t->nvcsw, t->nivcsw);
 -}
 -
--/*
-- * Function : process_issue_queue (void)
-- *
-- * Purpose : transfer commands from the issue queue to NCR start queue 
-- *    of each NCR53c7/8xx in the system, avoiding kernel stack 
-- *    overflows when the scsi_done() function is invoked recursively.
-- * 
-- * NOTE : process_issue_queue exits with interrupts *disabled*, so the 
-- *    caller must reenable them if it desires.
-- * 
-- * NOTE : process_issue_queue should be called from both 
-- *    NCR53c7x0_queue_command() and from the interrupt handler 
-- *    after command completion in case NCR53c7x0_queue_command()
-- *    isn't invoked again but we've freed up resources that are
-- *    needed.
-- */
--
--static void 
--process_issue_queue (unsigned long flags) {
--    Scsi_Cmnd *tmp, *prev;
--    struct Scsi_Host *host;
--    struct NCR53c7x0_hostdata *hostdata;
--    int done;
--
--    /*
--     * We run (with interrupts disabled) until we're sure that none of 
--     * the host adapters have anything that can be done, at which point 
--     * we set process_issue_queue_running to 0 and exit.
--     *
--     * Interrupts are enabled before doing various other internal 
--     * instructions, after we've decided that we need to run through
--     * the loop again.
--     *
--     */
--
--    do {
--      local_irq_disable(); /* Freeze request queues */
--      done = 1;
--      for (host = first_host; host && host->hostt == the_template;
--          host = host->next) {
--          hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
--          local_irq_disable();
--          if (hostdata->issue_queue) {
--              if (hostdata->state == STATE_DISABLED) {
--                  tmp = (Scsi_Cmnd *) hostdata->issue_queue;
--                  hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;
--                  tmp->result = (DID_BAD_TARGET << 16);
--                  if (tmp->host_scribble) {
--                      ((struct NCR53c7x0_cmd *)tmp->host_scribble)->next = 
--                          hostdata->free;
--                      hostdata->free = 
--                          (struct NCR53c7x0_cmd *)tmp->host_scribble;
--                      tmp->host_scribble = NULL;
--                  }
--                  tmp->scsi_done (tmp);
--                  done = 0;
--              } else 
--                  for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, 
--                      prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) 
--                      tmp->SCp.ptr) 
--                      if (!tmp->host_scribble || 
--                          !busyp (host, hostdata, tmp)) {
--                              if (prev)
--                                  prev->SCp.ptr = tmp->SCp.ptr;
--                              else
--                                  hostdata->issue_queue = (Scsi_Cmnd *) 
--                                      tmp->SCp.ptr;
--                          tmp->SCp.ptr = NULL;
--                          if (tmp->host_scribble) {
--                              if (hostdata->options & OPTION_DEBUG_QUEUES) 
--                                  printk ("scsi%d : moving command for target %d lun %d to start list\n",
--                                      host->host_no, tmp->device->id, tmp->device->lun);
--              
+ void print_ioacct(struct taskstats *t)
+ {
+       printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
+@@ -244,7 +235,7 @@
+       struct msgtemplate msg;
+       while (1) {
+-              c = getopt(argc, argv, "qdiw:r:m:t:p:vl");
++              c = getopt(argc, argv, "diw:r:m:t:p:vl");
+               if (c < 0)
+                       break;
+@@ -257,10 +248,6 @@
+                       printf("printing IO accounting\n");
+                       print_io_accounting = 1;
+                       break;
+-              case 'q':
+-                      printf("printing task/process context switch rates\n");
+-                      print_task_context_switch_counts = 1;
+-                      break;
+               case 'w':
+                       logfile = strdup(optarg);
+                       printf("write to file %s\n", logfile);
+@@ -402,8 +389,6 @@
+                                                       print_delayacct((struct taskstats *) NLA_DATA(na));
+                                               if (print_io_accounting)
+                                                       print_ioacct((struct taskstats *) NLA_DATA(na));
+-                                              if (print_task_context_switch_counts)
+-                                                      task_context_switch_counts((struct taskstats *) NLA_DATA(na));
+                                               if (fd) {
+                                                       if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
+                                                               err(1,"write error\n");
+diff -Nurb linux-2.6.22-590/Documentation/accounting/taskstats-struct.txt linux-2.6.22-570/Documentation/accounting/taskstats-struct.txt
+--- linux-2.6.22-590/Documentation/accounting/taskstats-struct.txt     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/accounting/taskstats-struct.txt     2007-07-08 19:32:17.000000000 -0400
+@@ -22,8 +22,6 @@
+     /* Extended accounting fields end */
+     Their values are collected if CONFIG_TASK_XACCT is set.
+-4) Per-task and per-thread context switch count statistics
 -
--                              to_schedule_list (host, hostdata, 
--                                  (struct NCR53c7x0_cmd *)
--                                  tmp->host_scribble);
--                          } else {
--                              if (((tmp->result & 0xff) == 0xff) ||
--                                  ((tmp->result & 0xff00) == 0xff00)) {
--                                  printk ("scsi%d : danger Will Robinson!\n",
--                                      host->host_no);
--                                  tmp->result = DID_ERROR << 16;
--                                  disable (host);
--                              }
--                              tmp->scsi_done(tmp);
--                          }
--                          done = 0;
--                      } /* if target/lun is not busy */
--          } /* if hostdata->issue_queue */
--          if (!done)
--              local_irq_restore(flags);
--      } /* for host */
--    } while (!done);
--    process_issue_queue_running = 0;
--}
+ Future extension should add fields to the end of the taskstats struct, and
+ should not change the relative position of each field within the struct.
+@@ -160,8 +158,4 @@
+       /* Extended accounting fields end */
+-4) Per-task and per-thread statistics
+-      __u64   nvcsw;                  /* Context voluntary switch counter */
+-      __u64   nivcsw;                 /* Context involuntary switch counter */
 -
--/*
-- * Function : static void intr_scsi (struct Scsi_Host *host, 
-- *    struct NCR53c7x0_cmd *cmd)
-- *
-- * Purpose : handle all SCSI interrupts, indicated by the setting 
-- *    of the SIP bit in the ISTAT register.
-- *
-- * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
-- *    may be NULL.
-- */
--
--static void 
--intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
--    NCR53c7x0_local_declare();
--    struct NCR53c7x0_hostdata *hostdata = 
--      (struct NCR53c7x0_hostdata *) host->hostdata[0];
--    unsigned char sstat0_sist0, sist1,                /* Registers */
--          fatal;                              /* Did a fatal interrupt 
--                                                 occur ? */
--   
--    NCR53c7x0_local_setup(host);
--
--    fatal = 0;
--
--    sstat0_sist0 = NCR53c7x0_read8(SSTAT0_REG);
--    sist1 = 0;
--
--    if (hostdata->options & OPTION_DEBUG_INTR) 
--      printk ("scsi%d : SIST0 0x%0x, SIST1 0x%0x\n", host->host_no,
--          sstat0_sist0, sist1);
--
--    /* 250ms selection timeout */
--    if (sstat0_sist0 & SSTAT0_700_STO) {
--      fatal = 1;
--      if (hostdata->options & OPTION_DEBUG_INTR) {
--          printk ("scsi%d : Selection Timeout\n", host->host_no);
--          if (cmd) {
--              printk("scsi%d : target %d, lun %d, command ",
--                  host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun);
--              __scsi_print_command (cmd->cmd->cmnd);
--              printk("scsi%d : dsp = 0x%x (virt 0x%p)\n", host->host_no,
--                  NCR53c7x0_read32(DSP_REG),
--                  bus_to_virt(NCR53c7x0_read32(DSP_REG)));
--          } else {
--              printk("scsi%d : no command\n", host->host_no);
--          }
--      }
--/*
-- * XXX - question : how do we want to handle the Illegal Instruction
-- *    interrupt, which may occur before or after the Selection Timeout
-- *    interrupt?
-- */
+ }
+diff -Nurb linux-2.6.22-590/Documentation/cachetlb.txt linux-2.6.22-570/Documentation/cachetlb.txt
+--- linux-2.6.22-590/Documentation/cachetlb.txt        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/cachetlb.txt        2007-07-08 19:32:17.000000000 -0400
+@@ -253,7 +253,7 @@
+       The first of these two routines is invoked after map_vm_area()
+       has installed the page table entries.  The second is invoked
+-      before unmap_kernel_range() deletes the page table entries.
++      before unmap_vm_area() deletes the page table entries.
+ There exists another whole class of cpu cache issues which currently
+ require a whole different set of interfaces to handle properly.
+diff -Nurb linux-2.6.22-590/Documentation/containers.txt linux-2.6.22-570/Documentation/containers.txt
+--- linux-2.6.22-590/Documentation/containers.txt      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/containers.txt      1969-12-31 19:00:00.000000000 -0500
+@@ -1,543 +0,0 @@
+-                              CONTAINERS
+-                              -------
+-
+-Written by Paul Menage <menage@google.com> based on Documentation/cpusets.txt
+-
+-Original copyright statements from cpusets.txt:
+-Portions Copyright (C) 2004 BULL SA.
+-Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
+-Modified by Paul Jackson <pj@sgi.com>
+-Modified by Christoph Lameter <clameter@sgi.com>
+-
+-CONTENTS:
+-=========
+-
+-1. Containers
+-  1.1 What are containers ?
+-  1.2 Why are containers needed ?
+-  1.3 How are containers implemented ?
+-  1.4 What does notify_on_release do ?
+-  1.5 How do I use containers ?
+-2. Usage Examples and Syntax
+-  2.1 Basic Usage
+-  2.2 Attaching processes
+-3. Kernel API
+-  3.1 Overview
+-  3.2 Synchronization
+-  3.3 Subsystem API
+-4. Questions
+-
+-1. Containers
+-==========
+-
+-1.1 What are containers ?
+-----------------------
+-
+-Containers provide a mechanism for aggregating/partitioning sets of
+-tasks, and all their future children, into hierarchical groups with
+-specialized behaviour.
+-
+-Definitions:
+-
+-A *container* associates a set of tasks with a set of parameters for one
+-or more subsystems.
+-
+-A *subsystem* is a module that makes use of the task grouping
+-facilities provided by containers to treat groups of tasks in
+-particular ways. A subsystem is typically a "resource controller" that
+-schedules a resource or applies per-container limits, but it may be
+-anything that wants to act on a group of processes, e.g. a
+-virtualization subsystem.
+-
+-A *hierarchy* is a set of containers arranged in a tree, such that
+-every task in the system is in exactly one of the containers in the
+-hierarchy, and a set of subsystems; each subsystem has system-specific
+-state attached to each container in the hierarchy.  Each hierarchy has
+-an instance of the container virtual filesystem associated with it.
+-
+-At any one time there may be multiple active hierachies of task
+-containers. Each hierarchy is a partition of all tasks in the system.
+-
+-User level code may create and destroy containers by name in an
+-instance of the container virtual file system, specify and query to
+-which container a task is assigned, and list the task pids assigned to
+-a container. Those creations and assignments only affect the hierarchy
+-associated with that instance of the container file system.
+-
+-On their own, the only use for containers is for simple job
+-tracking. The intention is that other subsystems hook into the generic
+-container support to provide new attributes for containers, such as
+-accounting/limiting the resources which processes in a container can
+-access. For example, cpusets (see Documentation/cpusets.txt) allows
+-you to associate a set of CPUs and a set of memory nodes with the
+-tasks in each container.
+-
+-1.2 Why are containers needed ?
+-----------------------------
+-
+-There are multiple efforts to provide process aggregations in the
+-Linux kernel, mainly for resource tracking purposes. Such efforts
+-include cpusets, CKRM/ResGroups, UserBeanCounters, and virtual server
+-namespaces. These all require the basic notion of a
+-grouping/partitioning of processes, with newly forked processes ending
+-in the same group (container) as their parent process.
+-
+-The kernel container patch provides the minimum essential kernel
+-mechanisms required to efficiently implement such groups. It has
+-minimal impact on the system fast paths, and provides hooks for
+-specific subsystems such as cpusets to provide additional behaviour as
+-desired.
+-
+-Multiple hierarchy support is provided to allow for situations where
+-the division of tasks into containers is distinctly different for
+-different subsystems - having parallel hierarchies allows each
+-hierarchy to be a natural division of tasks, without having to handle
+-complex combinations of tasks that would be present if several
+-unrelated subsystems needed to be forced into the same tree of
+-containers.
+-
+-At one extreme, each resource controller or subsystem could be in a
+-separate hierarchy; at the other extreme, all subsystems
+-would be attached to the same hierarchy.
+-
+-As an example of a scenario (originally proposed by vatsa@in.ibm.com)
+-that can benefit from multiple hierarchies, consider a large
+-university server with various users - students, professors, system
+-tasks etc. The resource planning for this server could be along the
+-following lines:
+-
+-       CPU :           Top cpuset
+-                       /       \
+-               CPUSet1         CPUSet2
+-                  |              |
+-               (Profs)         (Students)
+-
+-               In addition (system tasks) are attached to topcpuset (so
+-               that they can run anywhere) with a limit of 20%
+-
+-       Memory : Professors (50%), students (30%), system (20%)
+-
+-       Disk : Prof (50%), students (30%), system (20%)
+-
+-       Network : WWW browsing (20%), Network File System (60%), others (20%)
+-                               / \
+-                       Prof (15%) students (5%)
+-
+-Browsers like firefox/lynx go into the WWW network class, while (k)nfsd go
+-into NFS network class.
+-
+-At the same time firefox/lynx will share an appropriate CPU/Memory class
+-depending on who launched it (prof/student).
+-
+-With the ability to classify tasks differently for different resources
+-(by putting those resource subsystems in different hierarchies) then
+-the admin can easily set up a script which receives exec notifications
+-and depending on who is launching the browser he can
+-
+-       # echo browser_pid > /mnt/<restype>/<userclass>/tasks
+-
+-With only a single hierarchy, he now would potentially have to create
+-a separate container for every browser launched and associate it with
+-approp network and other resource class.  This may lead to
+-proliferation of such containers.
+-
+-Also lets say that the administrator would like to give enhanced network
+-access temporarily to a student's browser (since it is night and the user
+-wants to do online gaming :)  OR give one of the students simulation
+-apps enhanced CPU power,
+-
+-With ability to write pids directly to resource classes, its just a
+-matter of :
+-
+-       # echo pid > /mnt/network/<new_class>/tasks
+-       (after some time)
+-       # echo pid > /mnt/network/<orig_class>/tasks
+-
+-Without this ability, he would have to split the container into
+-multiple separate ones and then associate the new containers with the
+-new resource classes.
+-
+-
+-
+-1.3 How are containers implemented ?
+----------------------------------
+-
+-Containers extends the kernel as follows:
+-
+- - Each task in the system has a reference-counted pointer to a
+-   css_group.
+-
+- - A css_group contains a set of reference-counted pointers to
+-   container_subsys_state objects, one for each container subsystem
+-   registered in the system. There is no direct link from a task to
+-   the container of which it's a member in each hierarchy, but this
+-   can be determined by following pointers through the
+-   container_subsys_state objects. This is because accessing the
+-   subsystem state is something that's expected to happen frequently
+-   and in performance-critical code, whereas operations that require a
+-   task's actual container assignments (in particular, moving between
+-   containers) are less common. A linked list runs through the cg_list
+-   field of each task_struct using the css_group, anchored at
+-   css_group->tasks.
+-
+- - A container hierarchy filesystem can be mounted  for browsing and
+-   manipulation from user space.
+-
+- - You can list all the tasks (by pid) attached to any container.
+-
+-The implementation of containers requires a few, simple hooks
+-into the rest of the kernel, none in performance critical paths:
 -
--      if (1) {
--          hostdata->idle = 1;
--          hostdata->expecting_sto = 0;
--
--          if (hostdata->test_running) {
--              hostdata->test_running = 0;
--              hostdata->test_completed = 3;
--          } else if (cmd) {
--              abnormal_finished(cmd, DID_BAD_TARGET << 16);
--          }
--#if 0     
--          hostdata->intrs = 0;
--#endif
--      }
--    } 
+- - in init/main.c, to initialize the root containers and initial
+-   css_group at system boot.
 -
--/*
-- * FIXME : in theory, we can also get a UDC when a STO occurs.
-- */
--    if (sstat0_sist0 & SSTAT0_UDC) {
--      fatal = 1;
--      if (cmd) {
--          printk("scsi%d : target %d lun %d unexpected disconnect\n",
--              host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun);
--          print_lots (host);
--          abnormal_finished(cmd, DID_ERROR << 16);
--      } else 
--           printk("scsi%d : unexpected disconnect (no command)\n",
--              host->host_no);
--
--      hostdata->dsp = (u32 *) hostdata->schedule;
--      hostdata->dsp_changed = 1;
--    }
--
--    /* SCSI PARITY error */
--    if (sstat0_sist0 & SSTAT0_PAR) {
--      fatal = 1;
--      if (cmd && cmd->cmd) {
--          printk("scsi%d : target %d lun %d parity error.\n",
--              host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun);
--          abnormal_finished (cmd, DID_PARITY << 16); 
--      } else
--          printk("scsi%d : parity error\n", host->host_no);
--      /* Should send message out, parity error */
--
--      /* XXX - Reduce synchronous transfer rate! */
--      hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
--          sizeof(u32);
--      hostdata->dsp_changed = 1; 
--    /* SCSI GROSS error */
--    } 
--
--    if (sstat0_sist0 & SSTAT0_SGE) {
--      fatal = 1;
--      printk("scsi%d : gross error, saved2_dsa = 0x%x\n", host->host_no,
--                                      (unsigned int)hostdata->saved2_dsa);
--      print_lots (host);
--      
--      /* 
--         * A SCSI gross error may occur when we have 
--       *
--       * - A synchronous offset which causes the SCSI FIFO to be overwritten.
--       *
--       * - A REQ which causes the maximum synchronous offset programmed in 
--       *      the SXFER register to be exceeded.
--       *
--       * - A phase change with an outstanding synchronous offset.
--       *
--       * - Residual data in the synchronous data FIFO, with a transfer
--       *      other than a synchronous receive is started.$#
--       */
--              
+- - in fork and exit, to attach and detach a task from its css_group.
 -
--      /* XXX Should deduce synchronous transfer rate! */
--      hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
--          sizeof(u32);
--      hostdata->dsp_changed = 1;
--    /* Phase mismatch */
--    } 
+-In addition a new file system, of type "container" may be mounted, to
+-enable browsing and modifying the containers presently known to the
+-kernel.  When mounting a container hierarchy, you may specify a
+-comma-separated list of subsystems to mount as the filesystem mount
+-options.  By default, mounting the container filesystem attempts to
+-mount a hierarchy containing all registered subsystems.
 -
--    if (sstat0_sist0 & SSTAT0_MA) {
--      fatal = 1;
--      if (hostdata->options & OPTION_DEBUG_INTR)
--          printk ("scsi%d : SSTAT0_MA\n", host->host_no);
--      intr_phase_mismatch (host, cmd);
--    }
+-If an active hierarchy with exactly the same set of subsystems already
+-exists, it will be reused for the new mount. If no existing hierarchy
+-matches, and any of the requested subsystems are in use in an existing
+-hierarchy, the mount will fail with -EBUSY. Otherwise, a new hierarchy
+-is activated, associated with the requested subsystems.
 -
--#if 0
--    if (sstat0_sist0 & SIST0_800_RSL) 
--      printk ("scsi%d : Oh no Mr. Bill!\n", host->host_no);
--#endif
--    
--/*
-- * If a fatal SCSI interrupt occurs, we must insure that the DMA and
-- * SCSI FIFOs were flushed.
-- */
+-It's not currently possible to bind a new subsystem to an active
+-container hierarchy, or to unbind a subsystem from an active container
+-hierarchy. This may be possible in future, but is fraught with nasty
+-error-recovery issues.
 -
--    if (fatal) {
--      if (!hostdata->dstat_valid) {
--          hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
--          hostdata->dstat_valid = 1;
--      }
+-When a container filesystem is unmounted, if there are any
+-subcontainers created below the top-level container, that hierarchy
+-will remain active even though unmounted; if there are no
+-subcontainers then the hierarchy will be deactivated.
 -
--      if (!(hostdata->dstat & DSTAT_DFE)) {
--        printk ("scsi%d : DMA FIFO not empty\n", host->host_no);
--        /*
--         * Really need to check this code for 710  RGH.
--         * Havn't seen any problems, but maybe we should FLUSH before
--         * clearing sometimes.
--         */
--          NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
--          while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF)
--              ;
--        hostdata->dstat |= DSTAT_DFE;
--      }
--    }
--}
+-No new system calls are added for containers - all support for
+-querying and modifying containers is via this container file system.
 -
--#ifdef CYCLIC_TRACE
+-Each task under /proc has an added file named 'container' displaying,
+-for each active hierarchy, the subsystem names and the container name
+-as the path relative to the root of the container file system.
 -
--/*
-- * The following implements a cyclic log of instructions executed, if you turn
-- * TRACE on.  It will also print the log for you.  Very useful when debugging
-- * 53c710 support, possibly not really needed any more.
-- */
+-Each container is represented by a directory in the container file system
+-containing the following files describing that container:
 -
--u32 insn_log[4096];
--u32 insn_log_index = 0;
+- - tasks: list of tasks (by pid) attached to that container
+- - notify_on_release flag: run /sbin/container_release_agent on exit?
 -
--void log1 (u32 i)
--{
--      insn_log[insn_log_index++] = i;
--      if (insn_log_index == 4096)
--              insn_log_index = 0;
--}
+-Other subsystems such as cpusets may add additional files in each
+-container dir
 -
--void log_insn (u32 *ip)
--{
--      log1 ((u32)ip);
--      log1 (*ip);
--      log1 (*(ip+1));
--      if (((*ip >> 24) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI)
--              log1 (*(ip+2));
--}
+-New containers are created using the mkdir system call or shell
+-command.  The properties of a container, such as its flags, are
+-modified by writing to the appropriate file in that containers
+-directory, as listed above.
+-
+-The named hierarchical structure of nested containers allows partitioning
+-a large system into nested, dynamically changeable, "soft-partitions".
 -
--void dump_log(void)
--{
--      int cnt = 0;
--      int i = insn_log_index;
--      int size;
--      struct Scsi_Host *host = first_host;
+-The attachment of each task, automatically inherited at fork by any
+-children of that task, to a container allows organizing the work load
+-on a system into related sets of tasks.  A task may be re-attached to
+-any other container, if allowed by the permissions on the necessary
+-container file system directories.
 -
--      while (cnt < 4096) {
--              printk ("%08x (+%6x): ", insn_log[i], (insn_log[i] - (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4);
--              if (++i == 4096)
--                      i = 0;
--              cnt++;
--              if (((insn_log[i]  >> 24) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI) 
--                      size = 3;
--              else
--                      size = 2;
--              while (size--) {
--                      printk ("%08x ", insn_log[i]);
--                      if (++i == 4096)
--                              i = 0;
--                      cnt++;
--              }
--              printk ("\n");
--      }
--}
--#endif
+-When a task is moved from one container to another, it gets a new
+-css_group pointer - if there's an already existing css_group with the
+-desired collection of containers then that group is reused, else a new
+-css_group is allocated. Note that the current implementation uses a
+-linear search to locate an appropriate existing css_group, so isn't
+-very efficient. A future version will use a hash table for better
+-performance.
+-
+-To allow access from a container to the css_groups (and hence tasks)
+-that comprise it, a set of cg_container_link objects form a lattice;
+-each cg_container_link is linked into a list of cg_container_links for
+-a single container on its cont_link_list field, and a list of
+-cg_container_links for a single css_group on its cg_link_list.
+-
+-Thus the set of tasks in a container can be listed by iterating over
+-each css_group that references the container, and sub-iterating over
+-each css_group's task set.
+-
+-The use of a Linux virtual file system (vfs) to represent the
+-container hierarchy provides for a familiar permission and name space
+-for containers, with a minimum of additional kernel code.
+-
+-1.4 What does notify_on_release do ?
+-------------------------------------
 -
+-*** notify_on_release is disabled in the current patch set. It will be
+-*** reactivated in a future patch in a less-intrusive manner
+-
+-If the notify_on_release flag is enabled (1) in a container, then
+-whenever the last task in the container leaves (exits or attaches to
+-some other container) and the last child container of that container
+-is removed, then the kernel runs the command specified by the contents
+-of the "release_agent" file in that hierarchy's root directory,
+-supplying the pathname (relative to the mount point of the container
+-file system) of the abandoned container.  This enables automatic
+-removal of abandoned containers.  The default value of
+-notify_on_release in the root container at system boot is disabled
+-(0).  The default value of other containers at creation is the current
+-value of their parents notify_on_release setting. The default value of
+-a container hierarchy's release_agent path is empty.
+-
+-1.5 How do I use containers ?
+---------------------------
+-
+-To start a new job that is to be contained within a container, using
+-the "cpuset" container subsystem, the steps are something like:
 -
--/*
-- * Function : static void NCR53c7x0_intfly (struct Scsi_Host *host)
-- *
-- * Purpose : Scan command queue for specified host, looking for completed
-- *           commands.
-- * 
-- * Inputs : Scsi_Host pointer.
-- *
-- *    This is called from the interrupt handler, when a simulated INTFLY
-- *    interrupt occurs.
-- */
+- 1) mkdir /dev/container
+- 2) mount -t container -ocpuset cpuset /dev/container
+- 3) Create the new container by doing mkdir's and write's (or echo's) in
+-    the /dev/container virtual file system.
+- 4) Start a task that will be the "founding father" of the new job.
+- 5) Attach that task to the new container by writing its pid to the
+-    /dev/container tasks file for that container.
+- 6) fork, exec or clone the job tasks from this founding father task.
 -
--static void
--NCR53c7x0_intfly (struct Scsi_Host *host)
--{
--    NCR53c7x0_local_declare();
--    struct NCR53c7x0_hostdata *hostdata;      /* host->hostdata[0] */
--    struct NCR53c7x0_cmd *cmd,                        /* command which halted */
--      **cmd_prev_ptr;
--    unsigned long flags;                              
--    char search_found = 0;                    /* Got at least one ? */
+-For example, the following sequence of commands will setup a container
+-named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
+-and then start a subshell 'sh' in that container:
 -
--    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
--    NCR53c7x0_local_setup(host);
+-  mount -t container cpuset -ocpuset /dev/container
+-  cd /dev/container
+-  mkdir Charlie
+-  cd Charlie
+-  /bin/echo $$ > tasks
+-  sh
+-  # The subshell 'sh' is now running in container Charlie
+-  # The next line should display '/Charlie'
+-  cat /proc/self/container
 -
--    if (hostdata->options & OPTION_DEBUG_INTR)
--    printk ("scsi%d : INTFLY\n", host->host_no); 
+-2. Usage Examples and Syntax
+-============================
+-
+-2.1 Basic Usage
+----------------
+-
+-Creating, modifying, using the containers can be done through the container
+-virtual filesystem.
 -
--    /*
--    * Traverse our list of running commands, and look
--    * for those with valid (non-0xff ff) status and message
--    * bytes encoded in the result which signify command
--    * completion.
--    */
+-To mount a container hierarchy will all available subsystems, type:
+-# mount -t container xxx /dev/container
+-
+-The "xxx" is not interpreted by the container code, but will appear in
+-/proc/mounts so may be any useful identifying string that you like.
 -
--    local_irq_save(flags);
--restart:
--    for (cmd_prev_ptr = (struct NCR53c7x0_cmd **)&(hostdata->running_list),
--      cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ;
--      cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next), 
--      cmd = (struct NCR53c7x0_cmd *) cmd->next)
--    {
--      Scsi_Cmnd *tmp;
--
--      if (!cmd) {
--          printk("scsi%d : very weird.\n", host->host_no);
--          break;
--      }
--
--      if (!(tmp = cmd->cmd)) {
--          printk("scsi%d : weird.  NCR53c7x0_cmd has no Scsi_Cmnd\n",
--                  host->host_no);
--          continue;
--      }
--      /* Copy the result over now; may not be complete,
--       * but subsequent tests may as well be done on
--       * cached memory.
--       */
--      tmp->result = cmd->result;
+-To mount a container hierarchy with just the cpuset and numtasks
+-subsystems, type:
+-# mount -t container -o cpuset,numtasks hier1 /dev/container
+-
+-To change the set of subsystems bound to a mounted hierarchy, just
+-remount with different options:
+-
+-# mount -o remount,cpuset,ns  /dev/container
+-
+-Note that changing the set of subsystems is currently only supported
+-when the hierarchy consists of a single (root) container. Supporting
+-the ability to arbitrarily bind/unbind subsystems from an existing
+-container hierarchy is intended to be implemented in the future.
 -
--      if (((tmp->result & 0xff) == 0xff) ||
--                          ((tmp->result & 0xff00) == 0xff00))
--          continue;
+-Then under /dev/container you can find a tree that corresponds to the
+-tree of the containers in the system. For instance, /dev/container
+-is the container that holds the whole system.
 -
--      search_found = 1;
+-If you want to create a new container under /dev/container:
+-# cd /dev/container
+-# mkdir my_container
 -
--      if (cmd->bounce.len)
--          memcpy ((void *)cmd->bounce.addr,
--                              (void *)cmd->bounce.buf, cmd->bounce.len);
+-Now you want to do something with this container.
+-# cd my_container
 -
--      /* Important - remove from list _before_ done is called */
--      if (cmd_prev_ptr)
--          *cmd_prev_ptr = (struct NCR53c7x0_cmd *) cmd->next;
+-In this directory you can find several files:
+-# ls
+-notify_on_release release_agent tasks
+-(plus whatever files are added by the attached subsystems)
 -
--      --hostdata->busy[tmp->device->id][tmp->device->lun];
--      cmd->next = hostdata->free;
--      hostdata->free = cmd;
+-Now attach your shell to this container:
+-# /bin/echo $$ > tasks
+-
+-You can also create containers inside your container by using mkdir in this
+-directory.
+-# mkdir my_sub_cs
+-
+-To remove a container, just use rmdir:
+-# rmdir my_sub_cs
+-
+-This will fail if the container is in use (has containers inside, or
+-has processes attached, or is held alive by other subsystem-specific
+-reference).
+-
+-2.2 Attaching processes
+------------------------
+-
+-# /bin/echo PID > tasks
+-
+-Note that it is PID, not PIDs. You can only attach ONE task at a time.
+-If you have several tasks to attach, you have to do it one after another:
+-
+-# /bin/echo PID1 > tasks
+-# /bin/echo PID2 > tasks
+-      ...
+-# /bin/echo PIDn > tasks
+-
+-3. Kernel API
+-=============
 -
--      tmp->host_scribble = NULL;
+-3.1 Overview
+-------------
 -
--      if (hostdata->options & OPTION_DEBUG_INTR) {
--          printk ("scsi%d : command complete : pid %lu, id %d,lun %d result 0x%x ", 
--                host->host_no, tmp->pid, tmp->device->id, tmp->device->lun, tmp->result);
--          __scsi_print_command (tmp->cmnd);
--      }
+-Each kernel subsystem that wants to hook into the generic container
+-system needs to create a container_subsys object. This contains
+-various methods, which are callbacks from the container system, along
+-with a subsystem id which will be assigned by the container system.
 -
--      tmp->scsi_done(tmp);
--      goto restart;
--    }
--    local_irq_restore(flags);
+-Other fields in the container_subsys object include:
 -
--    if (!search_found)  {
--      printk ("scsi%d : WARNING : INTFLY with no completed commands.\n",
--                          host->host_no);
--    } else {
--      run_process_issue_queue();
--    }
--    return;
--}
+-- subsys_id: a unique array index for the subsystem, indicating which
+-  entry in container->subsys[] this subsystem should be
+-  managing. Initialized by container_register_subsys(); prior to this
+-  it should be initialized to -1
 -
--/*
-- * Function : static irqreturn_t NCR53c7x0_intr (int irq, void *dev_id)
-- *
-- * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing
-- *    the same IRQ line.  
-- * 
-- * Inputs : Since we're using the IRQF_DISABLED interrupt handler
-- *    semantics, irq indicates the interrupt which invoked 
-- *    this handler.  
-- *
-- * On the 710 we simualte an INTFLY with a script interrupt, and the
-- * script interrupt handler will call back to this function.
-- */
+-- hierarchy: an index indicating which hierarchy, if any, this
+-  subsystem is currently attached to. If this is -1, then the
+-  subsystem is not attached to any hierarchy, and all tasks should be
+-  considered to be members of the subsystem's top_container. It should
+-  be initialized to -1.
 -
--static irqreturn_t
--NCR53c7x0_intr (int irq, void *dev_id)
--{
--    NCR53c7x0_local_declare();
--    struct Scsi_Host *host;                   /* Host we are looking at */
--    unsigned char istat;                      /* Values of interrupt regs */
--    struct NCR53c7x0_hostdata *hostdata;      /* host->hostdata[0] */
--    struct NCR53c7x0_cmd *cmd;                        /* command which halted */
--    u32 *dsa;                                 /* DSA */
--    int handled = 0;
--
--#ifdef NCR_DEBUG
--    char buf[80];                             /* Debugging sprintf buffer */
--    size_t buflen;                            /* Length of same */
--#endif
+-- name: should be initialized to a unique subsystem name prior to
+-  calling container_register_subsystem. Should be no longer than
+-  MAX_CONTAINER_TYPE_NAMELEN
 -
--    host     = (struct Scsi_Host *)dev_id;
--    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
--    NCR53c7x0_local_setup(host);
+-Each container object created by the system has an array of pointers,
+-indexed by subsystem id; this pointer is entirely managed by the
+-subsystem; the generic container code will never touch this pointer.
 -
--    /*
--     * Only read istat once per loop, since reading it again will unstack
--     * interrupts
--     */
+-3.2 Synchronization
+--------------------
 -
--    while ((istat = NCR53c7x0_read8(hostdata->istat)) & (ISTAT_SIP|ISTAT_DIP)) {
--      handled = 1;
--      hostdata->dsp_changed = 0;
--      hostdata->dstat_valid = 0;
--      hostdata->state = STATE_HALTED;
+-There is a global mutex, container_mutex, used by the container
+-system. This should be taken by anything that wants to modify a
+-container. It may also be taken to prevent containers from being
+-modified, but more specific locks may be more appropriate in that
+-situation.
 -
--      if (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) 
--          printk ("scsi%d : SCSI FIFO not empty\n", host->host_no);
+-See kernel/container.c for more details.
 -
--      /*
--       * NCR53c700 and NCR53c700-66 change the current SCSI
--       * process, hostdata->ncrcurrent, in the Linux driver so
--       * cmd = hostdata->ncrcurrent.
--       *
--       * With other chips, we must look through the commands
--       * executing and find the command structure which 
--       * corresponds to the DSA register.
--       */
+-Subsystems can take/release the container_mutex via the functions
+-container_lock()/container_unlock(), and can
+-take/release the callback_mutex via the functions
+-container_lock()/container_unlock().
 -
--      if (hostdata->options & OPTION_700) {
--          cmd = (struct NCR53c7x0_cmd *) hostdata->ncrcurrent;
--      } else {
--          dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
--          for (cmd = (struct NCR53c7x0_cmd *) hostdata->running_list;
--              cmd && (dsa + (hostdata->dsa_start / sizeof(u32))) != cmd->dsa;
--                  cmd = (struct NCR53c7x0_cmd *)(cmd->next))
--              ;
--      }
--      if (hostdata->options & OPTION_DEBUG_INTR) {
--          if (cmd) {
--              printk("scsi%d : interrupt for pid %lu, id %d, lun %d ", 
--                  host->host_no, cmd->cmd->pid, (int) cmd->cmd->device->id,
--                  (int) cmd->cmd->device->lun);
--              __scsi_print_command (cmd->cmd->cmnd);
--          } else {
--              printk("scsi%d : no active command\n", host->host_no);
--          }
--      }
--      
--      if (istat & ISTAT_SIP) {
--          if (hostdata->options & OPTION_DEBUG_INTR) 
--              printk ("scsi%d : ISTAT_SIP\n", host->host_no);
--          intr_scsi (host, cmd);
--      }
--      
--      if (istat & ISTAT_DIP) {
--          if (hostdata->options & OPTION_DEBUG_INTR) 
--              printk ("scsi%d : ISTAT_DIP\n", host->host_no);
--          intr_dma (host, cmd);
--      }
--      
--      if (!hostdata->dstat_valid) {
--          hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
--          hostdata->dstat_valid = 1;
--      }
--      
--      if (!(hostdata->dstat & DSTAT_DFE)) {
--          printk ("scsi%d : DMA FIFO not empty\n", host->host_no);
--          /* Really need to check this out for 710 RGH */
--          NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
--          while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF)
--              ;
--          hostdata->dstat |= DSTAT_DFE;
--      }
+-Accessing a task's container pointer may be done in the following ways:
+-- while holding container_mutex
+-- while holding the task's alloc_lock (via task_lock())
+-- inside an rcu_read_lock() section via rcu_dereference()
 -
--      if (!hostdata->idle && hostdata->state == STATE_HALTED) {
--          if (!hostdata->dsp_changed)
--              hostdata->dsp = (u32 *)bus_to_virt(NCR53c7x0_read32(DSP_REG));
--#if 0
--          printk("scsi%d : new dsp is 0x%lx (virt 0x%p)\n",
--              host->host_no,  virt_to_bus(hostdata->dsp), hostdata->dsp);
--#endif
--              
--          hostdata->state = STATE_RUNNING;
--          NCR53c7x0_write32 (DSP_REG, virt_to_bus(hostdata->dsp));
--          if (hostdata->options & OPTION_DEBUG_TRACE) {
--#ifdef CYCLIC_TRACE
--              log_insn (hostdata->dsp);
--#else
--              print_insn (host, hostdata->dsp, "t ", 1);
--#endif
--              NCR53c7x0_write8 (DCNTL_REG,
--                      hostdata->saved_dcntl | DCNTL_SSM | DCNTL_STD);
--          }
--      }
--    }
--    return IRQ_HANDLED;
--}
+-3.3 Subsystem API
+---------------------------
 -
+-Each subsystem should:
 -
--/* 
-- * Function : static int abort_connected (struct Scsi_Host *host)
-- *
-- * Purpose : Assuming that the NCR SCSI processor is currently 
-- *    halted, break the currently established nexus.  Clean
-- *    up of the NCR53c7x0_cmd and Scsi_Cmnd structures should
-- *    be done on receipt of the abort interrupt.
-- *
-- * Inputs : host - SCSI host
-- *
-- */
+-- add an entry in linux/container_subsys.h
+-- define a container_subsys object called <name>_subsys
 -
--static int 
--abort_connected (struct Scsi_Host *host) {
--#ifdef NEW_ABORT
--    NCR53c7x0_local_declare();
--#endif
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--/* FIXME : this probably should change for production kernels; at the 
--   least, counter should move to a per-host structure. */
--    static int counter = 5;
--#ifdef NEW_ABORT
--    int sstat, phase, offset;
--    u32 *script;
--    NCR53c7x0_local_setup(host);
--#endif
+-Each subsystem may export the following methods. The only mandatory
+-methods are create/destroy. Any others that are null are presumed to
+-be successful no-ops.
 -
--    if (--counter <= 0) {
--      disable(host);
--      return 0;
--    }
+-int create(struct container *cont)
+-LL=container_mutex
 -
--    printk ("scsi%d : DANGER : abort_connected() called \n",
--      host->host_no);
+-Called to create a subsystem state object for a container. The
+-subsystem should set its subsystem pointer for the passed container,
+-returning 0 on success or a negative error code. On success, the
+-subsystem pointer should point to a structure of type
+-container_subsys_state (typically embedded in a larger
+-subsystem-specific object), which will be initialized by the container
+-system. Note that this will be called at initialization to create the
+-root subsystem state for this subsystem; this case can be identified
+-by the passed container object having a NULL parent (since it's the
+-root of the hierarchy) and may be an appropriate place for
+-initialization code.
 -
--#ifdef NEW_ABORT
+-void destroy(struct container *cont)
+-LL=container_mutex
 -
--/*
-- * New strategy : Rather than using a generic abort routine,
-- * we'll specifically try to source or sink the appropriate
-- * amount of data for the phase we're currently in (taking into 
-- * account the current synchronous offset) 
-- */
+-The container system is about to destroy the passed container; the
+-subsystem should do any necessary cleanup
 -
--    sstat = NCR53c8x0_read8 (SSTAT2_REG);
--    offset = OFFSET (sstat & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
--    phase = sstat & SSTAT2_PHASE_MASK;
+-int can_attach(struct container_subsys *ss, struct container *cont,
+-             struct task_struct *task)
+-LL=container_mutex
 -
--/*
-- * SET ATN
-- * MOVE source_or_sink, WHEN CURRENT PHASE 
-- * < repeat for each outstanding byte >
-- * JUMP send_abort_message
-- */
+-Called prior to moving a task into a container; if the subsystem
+-returns an error, this will abort the attach operation.  If a NULL
+-task is passed, then a successful result indicates that *any*
+-unspecified task can be moved into the container. Note that this isn't
+-called on a fork. If this method returns 0 (success) then this should
+-remain valid while the caller holds container_mutex.
 -
--    script = hostdata->abort_script = kmalloc (
--      8  /* instruction size */ * (
--          1 /* set ATN */ +
--          (!offset ? 1 : offset) /* One transfer per outstanding byte */ +
--          1 /* send abort message */),
--      GFP_ATOMIC);
+-void attach(struct container_subsys *ss, struct container *cont,
+-          struct container *old_cont, struct task_struct *task)
+-LL=container_mutex
 -
 -
--#else /* def NEW_ABORT */
--    hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
--          sizeof(u32);
--#endif /* def NEW_ABORT */
--    hostdata->dsp_changed = 1;
+-Called after the task has been attached to the container, to allow any
+-post-attachment activity that requires memory allocations or blocking.
 -
--/* XXX - need to flag the command as aborted after the abort_connected
--       code runs 
-- */
--    return 0;
--}
+-void fork(struct container_subsy *ss, struct task_struct *task)
+-LL=callback_mutex, maybe read_lock(tasklist_lock)
 -
--/*
-- * Function : static int datapath_residual (Scsi_Host *host)
-- *
-- * Purpose : return residual data count of what's in the chip.
-- *
-- * Inputs : host - SCSI host
-- */
+-Called when a task is forked into a container. Also called during
+-registration for all existing tasks.
 -
--static int
--datapath_residual (struct Scsi_Host *host) {
--    NCR53c7x0_local_declare();
--    int count, synchronous, sstat;
--    unsigned int ddir;
--
--    NCR53c7x0_local_setup(host);
--    /* COMPAT : the 700 and 700-66 need to use DFIFO_00_BO_MASK */
--    count = ((NCR53c7x0_read8 (DFIFO_REG) & DFIFO_10_BO_MASK) -
--      (NCR53c7x0_read32 (DBC_REG) & DFIFO_10_BO_MASK)) & DFIFO_10_BO_MASK;
--    synchronous = NCR53c7x0_read8 (SXFER_REG) & SXFER_MO_MASK;
--    /* COMPAT : DDIR is elsewhere on non-'8xx chips. */
--    ddir = NCR53c7x0_read8 (CTEST0_REG_700) & CTEST0_700_DDIR;
--
--    if (ddir) {
--    /* Receive */
--      if (synchronous) 
--          count += (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
--      else
--          if (NCR53c7x0_read8 (SSTAT1_REG) & SSTAT1_ILF)
--              ++count;
--    } else {
--    /* Send */
--      sstat = NCR53c7x0_read8 (SSTAT1_REG);
--      if (sstat & SSTAT1_OLF)
--          ++count;
--      if (synchronous && (sstat & SSTAT1_ORF))
--          ++count;
--    }
--    return count;
--}
+-void exit(struct container_subsys *ss, struct task_struct *task)
+-LL=callback_mutex
 -
--/* 
-- * Function : static const char * sbcl_to_phase (int sbcl)_
-- *
-- * Purpose : Convert SBCL register to user-parsable phase representation
-- *
-- * Inputs : sbcl - value of sbcl register
-- */
+-Called during task exit
 -
+-int populate(struct container_subsys *ss, struct container *cont)
+-LL=none
 -
--static const char *
--sbcl_to_phase (int sbcl) {
--    switch (sbcl & SBCL_PHASE_MASK) {
--    case SBCL_PHASE_DATAIN:
--      return "DATAIN";
--    case SBCL_PHASE_DATAOUT:
--      return "DATAOUT";
--    case SBCL_PHASE_MSGIN:
--      return "MSGIN";
--    case SBCL_PHASE_MSGOUT:
--      return "MSGOUT";
--    case SBCL_PHASE_CMDOUT:
--      return "CMDOUT";
--    case SBCL_PHASE_STATIN:
--      return "STATUSIN";
--    default:
--      return "unknown";
--    }
--}
+-Called after creation of a container to allow a subsystem to populate
+-the container directory with file entries.  The subsystem should make
+-calls to container_add_file() with objects of type cftype (see
+-include/linux/container.h for details).  Note that although this
+-method can return an error code, the error code is currently not
+-always handled well.
 -
--/* 
-- * Function : static const char * sstat2_to_phase (int sstat)_
-- *
-- * Purpose : Convert SSTAT2 register to user-parsable phase representation
-- *
-- * Inputs : sstat - value of sstat register
-- */
+-void post_clone(struct container_subsys *ss, struct container *cont)
 -
+-Called at the end of container_clone() to do any paramater
+-initialization which might be required before a task could attach.  For
+-example in cpusets, no task may attach before 'cpus' and 'mems' are set
+-up.
 -
--static const char *
--sstat2_to_phase (int sstat) {
--    switch (sstat & SSTAT2_PHASE_MASK) {
--    case SSTAT2_PHASE_DATAIN:
--      return "DATAIN";
--    case SSTAT2_PHASE_DATAOUT:
--      return "DATAOUT";
--    case SSTAT2_PHASE_MSGIN:
--      return "MSGIN";
--    case SSTAT2_PHASE_MSGOUT:
--      return "MSGOUT";
--    case SSTAT2_PHASE_CMDOUT:
--      return "CMDOUT";
--    case SSTAT2_PHASE_STATIN:
--      return "STATUSIN";
--    default:
--      return "unknown";
--    }
--}
+-void bind(struct container_subsys *ss, struct container *root)
+-LL=callback_mutex
 -
--/* 
-- * Function : static void intr_phase_mismatch (struct Scsi_Host *host, 
-- *    struct NCR53c7x0_cmd *cmd)
-- *
-- * Purpose : Handle phase mismatch interrupts
-- *
-- * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
-- *    may be NULL.
-- *
-- * Side effects : The abort_connected() routine is called or the NCR chip 
-- *    is restarted, jumping to the command_complete entry point, or 
-- *    patching the address and transfer count of the current instruction 
-- *    and calling the msg_in entry point as appropriate.
-- */
--
--static void 
--intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
--    NCR53c7x0_local_declare();
--    u32 dbc_dcmd, *dsp, *dsp_next;
--    unsigned char dcmd, sbcl;
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    int residual;
--    enum {ACTION_ABORT, ACTION_ABORT_PRINT, ACTION_CONTINUE} action = 
--      ACTION_ABORT_PRINT;
--    const char *where = NULL;
--
--    NCR53c7x0_local_setup(host);
--
--    /*
--     * Corrective action is based on where in the SCSI SCRIPT(tm) the error 
--     * occurred, as well as which SCSI phase we are currently in.
--     */
--    dsp_next = bus_to_virt(NCR53c7x0_read32(DSP_REG));
--
--    /* 
--     * Fetch the current instruction, and remove the operands for easier 
--     * interpretation.
--     */
--    dbc_dcmd = NCR53c7x0_read32(DBC_REG);
--    dcmd = (dbc_dcmd & 0xff000000) >> 24;
--    /*
--     * Like other processors, the NCR adjusts the instruction pointer before
--     * instruction decode.  Set the DSP address back to what it should
--     * be for this instruction based on its size (2 or 3 32 bit words).
--     */
--    dsp = dsp_next - NCR53c7x0_insn_size(dcmd);
--
--
--    /*
--     * Read new SCSI phase from the SBCL lines.  Since all of our code uses 
--     * a WHEN conditional instead of an IF conditional, we don't need to 
--     * wait for a new REQ.
--     */
--    sbcl = NCR53c7x0_read8(SBCL_REG) & SBCL_PHASE_MASK;
--
--    if (!cmd) {
--      action = ACTION_ABORT_PRINT;
--      where = "no current command";
--    /*
--     * The way my SCSI SCRIPTS(tm) are architected, recoverable phase
--     * mismatches should only occur where we're doing a multi-byte  
--     * BMI instruction.  Specifically, this means 
--     *
--     *  - select messages (a SCSI-I target may ignore additional messages
--     *                after the IDENTIFY; any target may reject a SDTR or WDTR)
--     *
--     *  - command out (targets may send a message to signal an error 
--     *                condition, or go into STATUSIN after they've decided 
--     *                they don't like the command.
--     *
--     *        - reply_message (targets may reject a multi-byte message in the 
--     *                middle)
--     *
--     *        - data transfer routines (command completion with buffer space
--     *                left, disconnect message, or error message)
--     */
--    } else if (((dsp >= cmd->data_transfer_start && 
--      dsp < cmd->data_transfer_end)) || dsp == (cmd->residual + 2)) {
--      if ((dcmd & (DCMD_TYPE_MASK|DCMD_BMI_OP_MASK|DCMD_BMI_INDIRECT|
--              DCMD_BMI_MSG|DCMD_BMI_CD)) == (DCMD_TYPE_BMI|
--              DCMD_BMI_OP_MOVE_I)) {
--          residual = datapath_residual (host);
--          if (hostdata->options & OPTION_DEBUG_DISCONNECT)
--              printk ("scsi%d : handling residual transfer (+ %d bytes from DMA FIFO)\n", 
--                  host->host_no, residual);
--
--          /*
--           * The first instruction is a CALL to the alternate handler for 
--           * this data transfer phase, so we can do calls to 
--           * munge_msg_restart as we would if control were passed 
--           * from normal dynamic code.
--           */
--          if (dsp != cmd->residual + 2) {
--              cmd->residual[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL |
--                      ((dcmd & DCMD_BMI_IO) ? DCMD_TCI_IO : 0)) << 24) | 
--                  DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
--              cmd->residual[1] = virt_to_bus(hostdata->script)
--                  + ((dcmd & DCMD_BMI_IO)
--                     ? hostdata->E_other_in : hostdata->E_other_out);
--          }
--
--          /*
--           * The second instruction is the a data transfer block
--           * move instruction, reflecting the pointer and count at the 
--           * time of the phase mismatch.
--           */
--          cmd->residual[2] = dbc_dcmd + residual;
--          cmd->residual[3] = NCR53c7x0_read32(DNAD_REG) - residual;
--
--          /*
--           * The third and final instruction is a jump to the instruction
--           * which follows the instruction which had to be 'split'
--           */
--          if (dsp != cmd->residual + 2) {
--              cmd->residual[4] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) 
--                  << 24) | DBC_TCI_TRUE;
--              cmd->residual[5] = virt_to_bus(dsp_next);
--          }
--
--          /*
--           * For the sake of simplicity, transfer control to the 
--           * conditional CALL at the start of the residual buffer.
--           */
--          hostdata->dsp = cmd->residual;
--          hostdata->dsp_changed = 1;
--          action = ACTION_CONTINUE;
--      } else {
--          where = "non-BMI dynamic DSA code";
--          action = ACTION_ABORT_PRINT;
--      }
--    } else if (dsp == (hostdata->script + hostdata->E_select_msgout / 4 + 2)) {
--      /* RGH 290697:  Added +2 above, to compensate for the script
--       * instruction which disables the selection timer. */
--      /* Release ATN */
--      NCR53c7x0_write8 (SOCL_REG, 0);
--      switch (sbcl) {
--    /* 
--     * Some devices (SQ555 come to mind) grab the IDENTIFY message
--     * sent on selection, and decide to go into COMMAND OUT phase
--     * rather than accepting the rest of the messages or rejecting
--     * them.  Handle these devices gracefully.
--     */
--      case SBCL_PHASE_CMDOUT:
--          hostdata->dsp = dsp + 2 /* two _words_ */;
--          hostdata->dsp_changed = 1;
--          printk ("scsi%d : target %d ignored SDTR and went into COMMAND OUT\n", 
--              host->host_no, cmd->cmd->device->id);
--          cmd->flags &= ~CMD_FLAG_SDTR;
--          action = ACTION_CONTINUE;
--          break;
--      case SBCL_PHASE_MSGIN:
--          hostdata->dsp = hostdata->script + hostdata->E_msg_in / 
--              sizeof(u32);
--          hostdata->dsp_changed = 1;
--          action = ACTION_CONTINUE;
--          break;
--      default:
--          where="select message out";
--          action = ACTION_ABORT_PRINT;
--      }
--    /*
--     * Some SCSI devices will interpret a command as they read the bytes
--     * off the SCSI bus, and may decide that the command is Bogus before 
--     * they've read the entire command off the bus.
--     */
--    } else if (dsp == hostdata->script + hostdata->E_cmdout_cmdout / sizeof 
--      (u32)) {
--      hostdata->dsp = hostdata->script + hostdata->E_data_transfer /
--          sizeof (u32);
--      hostdata->dsp_changed = 1;
--      action = ACTION_CONTINUE;
--    /* FIXME : we need to handle message reject, etc. within msg_respond. */
--#ifdef notyet
--    } else if (dsp == hostdata->script + hostdata->E_reply_message) {
--      switch (sbcl) {
--    /* Any other phase mismatches abort the currently executing command.  */
--#endif
--    } else {
--      where = "unknown location";
--      action = ACTION_ABORT_PRINT;
--    }
--
--    /* Flush DMA FIFO */
--    if (!hostdata->dstat_valid) {
--      hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
--      hostdata->dstat_valid = 1;
--    }
--    if (!(hostdata->dstat & DSTAT_DFE)) {
--      /* Really need to check this out for 710 RGH */
--      NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
--      while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF);
--      hostdata->dstat |= DSTAT_DFE;
--    }
--
--    switch (action) {
--    case ACTION_ABORT_PRINT:
--      printk("scsi%d : %s : unexpected phase %s.\n",
--           host->host_no, where ? where : "unknown location", 
--           sbcl_to_phase(sbcl));
--      print_lots (host);
--    /* Fall through to ACTION_ABORT */
--    case ACTION_ABORT:
--      abort_connected (host);
--      break;
--    case ACTION_CONTINUE:
--      break;
--    }
+-Called when a container subsystem is rebound to a different hierarchy
+-and root container. Currently this will only involve movement between
+-the default hierarchy (which never has sub-containers) and a hierarchy
+-that is being created/destroyed (and hence has no sub-containers).
 -
--#if 0
--    if (hostdata->dsp_changed) {
--      printk("scsi%d: new dsp 0x%p\n", host->host_no, hostdata->dsp);
--      print_insn (host, hostdata->dsp, "", 1);
--    }
--#endif
--}
+-4. Questions
+-============
 -
--/*
-- * Function : static void intr_bf (struct Scsi_Host *host, 
-- *    struct NCR53c7x0_cmd *cmd)
-- *
-- * Purpose : handle BUS FAULT interrupts 
-- *
-- * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
-- *    may be NULL.
-- */
+-Q: what's up with this '/bin/echo' ?
+-A: bash's builtin 'echo' command does not check calls to write() against
+-   errors. If you use it in the container file system, you won't be
+-   able to tell whether a command succeeded or failed.
 -
--static void
--intr_bf (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
--    NCR53c7x0_local_declare();
--    u32 *dsp,
--      *next_dsp,              /* Current dsp */
--      *dsa,
--      dbc_dcmd;               /* DCMD (high eight bits) + DBC */
--    char *reason = NULL;
--    /* Default behavior is for a silent error, with a retry until we've
--       exhausted retries. */
--    enum {MAYBE, ALWAYS, NEVER} retry = MAYBE;
--    int report = 0;
--    NCR53c7x0_local_setup(host);
--
--    dbc_dcmd = NCR53c7x0_read32 (DBC_REG);
--    next_dsp = bus_to_virt (NCR53c7x0_read32(DSP_REG));
--    dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff);
--/* FIXME - check chip type  */
--    dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG));
--
--    /*
--     * Bus faults can be caused by either a Bad Address or 
--     * Target Abort. We should check the Received Target Abort
--     * bit of the PCI status register and Master Abort Bit.
--     *
--     *        - Master Abort bit indicates that no device claimed
--     *                the address with DEVSEL within five clocks
--     *
--     *        - Target Abort bit indicates that a target claimed it,
--     *                but changed its mind once it saw the byte enables.
--     *
--     */
--
--    /* 53c710, not PCI system */
--    report = 1;
--    reason = "Unknown";
--
--#ifndef notyet
--    report = 1;
--#endif
--    if (report && reason)
--    {
--      printk(KERN_ALERT "scsi%d : BUS FAULT reason = %s\n",
--           host->host_no, reason ? reason : "unknown");
--      print_lots (host);
--    }
--
--#ifndef notyet
--    retry = NEVER;
--#endif
+-Q: When I attach processes, only the first of the line gets really attached !
+-A: We can only return one error code per call to write(). So you should also
+-   put only ONE pid.
 -
--    /* 
--     * TODO : we should attempt to recover from any spurious bus 
--     * faults.  After X retries, we should figure that things are 
--     * sufficiently wedged, and call NCR53c7xx_reset.
--     *
--     * This code should only get executed once we've decided that we 
--     * cannot retry.
--     */
+diff -Nurb linux-2.6.22-590/Documentation/cpuidle/core.txt linux-2.6.22-570/Documentation/cpuidle/core.txt
+--- linux-2.6.22-590/Documentation/cpuidle/core.txt    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/cpuidle/core.txt    1969-12-31 19:00:00.000000000 -0500
+@@ -1,17 +0,0 @@
 -
--    if (retry == NEVER) {
--      printk(KERN_ALERT "          mail richard@sleepie.demon.co.uk\n");
--      FATAL (host);
--    }
--}
+-              Supporting multiple CPU idle levels in kernel
 -
--/*
-- * Function : static void intr_dma (struct Scsi_Host *host, 
-- *    struct NCR53c7x0_cmd *cmd)
-- *
-- * Purpose : handle all DMA interrupts, indicated by the setting 
-- *    of the DIP bit in the ISTAT register.
-- *
-- * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
-- *    may be NULL.
-- */
--
--static void 
--intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
--    NCR53c7x0_local_declare();
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    unsigned char dstat;      /* DSTAT */     
--    u32 *dsp,
--      *next_dsp,              /* Current dsp */
--      *dsa,
--      dbc_dcmd;               /* DCMD (high eight bits) + DBC */
--    int tmp;
--    unsigned long flags;
--    NCR53c7x0_local_setup(host);
--
--    if (!hostdata->dstat_valid) {
--      hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
--      hostdata->dstat_valid = 1;
--    }
--    
--    dstat = hostdata->dstat;
--    
--    if (hostdata->options & OPTION_DEBUG_INTR)
--      printk("scsi%d : DSTAT=0x%x\n", host->host_no, (int) dstat);
--
--    dbc_dcmd = NCR53c7x0_read32 (DBC_REG);
--    next_dsp = bus_to_virt(NCR53c7x0_read32(DSP_REG));
--    dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff);
--/* XXX - check chip type */
--    dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
--
--    /*
--     * DSTAT_ABRT is the aborted interrupt.  This is set whenever the 
--     * SCSI chip is aborted.  
--     * 
--     * With NCR53c700 and NCR53c700-66 style chips, we should only 
--     * get this when the chip is currently running the accept 
--     * reselect/select code and we have set the abort bit in the 
--     * ISTAT register.
--     *
--     */
--    
--    if (dstat & DSTAT_ABRT) {
--#if 0
--      /* XXX - add code here to deal with normal abort */
--      if ((hostdata->options & OPTION_700) && (hostdata->state ==
--          STATE_ABORTING)) {
--      } else 
--#endif
--      {
--          printk(KERN_ALERT "scsi%d : unexpected abort interrupt at\n" 
--                 "         ", host->host_no);
--          print_insn (host, dsp, KERN_ALERT "s ", 1);
--          FATAL (host);
--      }
--    }
--
--    /*
--     * DSTAT_SSI is the single step interrupt.  Should be generated 
--     * whenever we have single stepped or are tracing.
--     */
--
--    if (dstat & DSTAT_SSI) {
--      if (hostdata->options & OPTION_DEBUG_TRACE) {
--          /* Don't print instr. until we write DSP at end of intr function */
--      } else if (hostdata->options & OPTION_DEBUG_SINGLE) {
--          print_insn (host, dsp, "s ", 0);
--          local_irq_save(flags);
--/* XXX - should we do this, or can we get away with writing dsp? */
--
--          NCR53c7x0_write8 (DCNTL_REG, (NCR53c7x0_read8(DCNTL_REG) & 
--              ~DCNTL_SSM) | DCNTL_STD);
--          local_irq_restore(flags);
--      } else {
--          printk(KERN_ALERT "scsi%d : unexpected single step interrupt at\n"
--                 "         ", host->host_no);
--          print_insn (host, dsp, KERN_ALERT "", 1);
--          printk(KERN_ALERT "         mail drew@PoohSticks.ORG\n");
--          FATAL (host);
--      }
--    }
--
--    /*
--     * DSTAT_IID / DSTAT_OPC (same bit, same meaning, only the name 
--     * is different) is generated whenever an illegal instruction is 
--     * encountered.  
--     * 
--     * XXX - we may want to emulate INTFLY here, so we can use 
--     *    the same SCSI SCRIPT (tm) for NCR53c710 through NCR53c810  
--     *          chips.
--     */
--
--    if (dstat & DSTAT_OPC) {
--    /* 
--     * Ascertain if this IID interrupts occurred before or after a STO 
--     * interrupt.  Since the interrupt handling code now leaves 
--     * DSP unmodified until _after_ all stacked interrupts have been
--     * processed, reading the DSP returns the original DSP register.
--     * This means that if dsp lies between the select code, and 
--     * message out following the selection code (where the IID interrupt
--     * would have to have occurred by due to the implicit wait for REQ),
--     * we have an IID interrupt resulting from a STO condition and 
--     * can ignore it.
--     */
--
--      if (((dsp >= (hostdata->script + hostdata->E_select / sizeof(u32))) &&
--          (dsp <= (hostdata->script + hostdata->E_select_msgout / 
--          sizeof(u32) + 8))) || (hostdata->test_running == 2)) {
--          if (hostdata->options & OPTION_DEBUG_INTR) 
--              printk ("scsi%d : ignoring DSTAT_IID for SSTAT_STO\n",
--                  host->host_no);
--          if (hostdata->expecting_iid) {
--              hostdata->expecting_iid = 0;
--              hostdata->idle = 1;
--              if (hostdata->test_running == 2) {
--                  hostdata->test_running = 0;
--                  hostdata->test_completed = 3;
--              } else if (cmd) 
--                      abnormal_finished (cmd, DID_BAD_TARGET << 16);
--          } else {
--              hostdata->expecting_sto = 1;
--          }
--    /*
--     * We can't guarantee we'll be able to execute the WAIT DISCONNECT
--     * instruction within the 3.4us of bus free and arbitration delay
--     * that a target can RESELECT in and assert REQ after we've dropped
--     * ACK.  If this happens, we'll get an illegal instruction interrupt.
--     * Doing away with the WAIT DISCONNECT instructions broke everything,
--     * so instead I'll settle for moving one WAIT DISCONNECT a few 
--     * instructions closer to the CLEAR ACK before it to minimize the
--     * chances of this happening, and handle it if it occurs anyway.
--     *
--     * Simply continue with what we were doing, and control should
--     * be transferred to the schedule routine which will ultimately
--     * pass control onto the reselection or selection (not yet)
--     * code.
--     */
--      } else if (dbc_dcmd == 0x48000000 && (NCR53c7x0_read8 (SBCL_REG) &
--          SBCL_REQ)) {
--          if (!(hostdata->options & OPTION_NO_PRINT_RACE))
--          {
--              printk("scsi%d: REQ before WAIT DISCONNECT IID\n", 
--                  host->host_no);
--              hostdata->options |= OPTION_NO_PRINT_RACE;
--          }
--      } else {
--          printk(KERN_ALERT "scsi%d : invalid instruction\n", host->host_no);
--          print_lots (host);
--          printk(KERN_ALERT "         mail Richard@sleepie.demon.co.uk with ALL\n"
--                            "         boot messages and diagnostic output\n");
--          FATAL (host);
--      }
--    }
+-                              cpuidle
 -
--    /* 
--     * DSTAT_BF are bus fault errors.  DSTAT_800_BF is valid for 710 also.
--     */
--    
--    if (dstat & DSTAT_800_BF) {
--      intr_bf (host, cmd);
--    }
--      
+-General Information:
 -
--    /* 
--     * DSTAT_SIR interrupts are generated by the execution of 
--     * the INT instruction.  Since the exact values available 
--     * are determined entirely by the SCSI script running, 
--     * and are local to a particular script, a unique handler
--     * is called for each script.
--     */
--
--    if (dstat & DSTAT_SIR) {
--      if (hostdata->options & OPTION_DEBUG_INTR)
--          printk ("scsi%d : DSTAT_SIR\n", host->host_no);
--      switch ((tmp = hostdata->dstat_sir_intr (host, cmd))) {
--      case SPECIFIC_INT_NOTHING:
--      case SPECIFIC_INT_RESTART:
--          break;
--      case SPECIFIC_INT_ABORT:
--          abort_connected(host);
--          break;
--      case SPECIFIC_INT_PANIC:
--          printk(KERN_ALERT "scsi%d : failure at ", host->host_no);
--          print_insn (host, dsp, KERN_ALERT "", 1);
--          printk(KERN_ALERT "          dstat_sir_intr() returned SPECIFIC_INT_PANIC\n");
--          FATAL (host);
--          break;
--      case SPECIFIC_INT_BREAK:
--          intr_break (host, cmd);
--          break;
--      default:
--          printk(KERN_ALERT "scsi%d : failure at ", host->host_no);
--          print_insn (host, dsp, KERN_ALERT "", 1);
--          printk(KERN_ALERT"          dstat_sir_intr() returned unknown value %d\n", 
--              tmp);
--          FATAL (host);
--      }
--    } 
--}
+-Various CPUs today support multiple idle levels that are differentiated
+-by varying exit latencies and power consumption during idle.
+-cpuidle is a generic in-kernel infrastructure that separates
+-idle policy (governor) from idle mechanism (driver) and provides a
+-standardized infrastructure to support independent development of
+-governors and drivers.
 -
--/*
-- * Function : static int print_insn (struct Scsi_Host *host, 
-- *    u32 *insn, int kernel)
-- *
-- * Purpose : print numeric representation of the instruction pointed
-- *    to by insn to the debugging or kernel message buffer
-- *    as appropriate.  
-- *
-- *    If desired, a user level program can interpret this 
-- *    information.
-- *
-- * Inputs : host, insn - host, pointer to instruction, prefix - 
-- *    string to prepend, kernel - use printk instead of debugging buffer.
-- *
-- * Returns : size, in u32s, of instruction printed.
-- */
+-cpuidle resides under /drivers/cpuidle.
 -
--/*
-- * FIXME: should change kernel parameter so that it takes an ENUM
-- *    specifying severity - either KERN_ALERT or KERN_PANIC so
-- *    all panic messages are output with the same severity.
-- */
 -
--static int 
--print_insn (struct Scsi_Host *host, const u32 *insn, 
--    const char *prefix, int kernel) {
--    char buf[160],            /* Temporary buffer and pointer.  ICKY 
--                                 arbitrary length.  */
+diff -Nurb linux-2.6.22-590/Documentation/cpuidle/driver.txt linux-2.6.22-570/Documentation/cpuidle/driver.txt
+--- linux-2.6.22-590/Documentation/cpuidle/driver.txt  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/cpuidle/driver.txt  1969-12-31 19:00:00.000000000 -0500
+@@ -1,24 +0,0 @@
 -
--              
--      *tmp;                   
--    unsigned char dcmd;               /* dcmd register for *insn */
--    int size;
--
--    /* 
--     * Check to see if the instruction pointer is not bogus before 
--     * indirecting through it; avoiding red-zone at start of 
--     * memory.
--     *
--     * FIXME: icky magic needs to happen here on non-intel boxes which
--     * don't have kernel memory mapped in like this.  Might be reasonable
--     * to use vverify()?
--     */
--
--    if (virt_to_phys((void *)insn) < PAGE_SIZE || 
--      virt_to_phys((void *)(insn + 8)) > virt_to_phys(high_memory) ||
--      ((((dcmd = (insn[0] >> 24) & 0xff) & DCMD_TYPE_MMI) == DCMD_TYPE_MMI) &&
--      virt_to_phys((void *)(insn + 12)) > virt_to_phys(high_memory))) {
--      size = 0;
--      sprintf (buf, "%s%p: address out of range\n",
--          prefix, insn);
--    } else {
--/* 
-- * FIXME : (void *) cast in virt_to_bus should be unnecessary, because
-- *    it should take const void * as argument.
-- */
--#if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000)
--      sprintf(buf, "%s0x%lx (virt 0x%p) : 0x%08x 0x%08x (virt 0x%p)", 
--          (prefix ? prefix : ""), virt_to_bus((void *) insn), insn,  
--          insn[0], insn[1], bus_to_virt (insn[1]));
--#else
--      /* Remove virtual addresses to reduce output, as they are the same */
--      sprintf(buf, "%s0x%x (+%x) : 0x%08x 0x%08x", 
--          (prefix ? prefix : ""), (u32)insn, ((u32)insn -
--              (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4, 
--          insn[0], insn[1]);
--#endif
--      tmp = buf + strlen(buf);
--      if ((dcmd & DCMD_TYPE_MASK) == DCMD_TYPE_MMI)  {
--#if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000)
--          sprintf (tmp, " 0x%08x (virt 0x%p)\n", insn[2], 
--              bus_to_virt(insn[2]));
--#else
--          /* Remove virtual addr to reduce output, as it is the same */
--          sprintf (tmp, " 0x%08x\n", insn[2]);
--#endif
--          size = 3;
--      } else {
--          sprintf (tmp, "\n");
--          size = 2;
--      }
--    }
--
--    if (kernel) 
--      printk ("%s", buf);
--#ifdef NCR_DEBUG
--    else {
--      size_t len = strlen(buf);
--      debugger_kernel_write(host, buf, len);
--    }
--#endif
--    return size;
--}
 -
--/*
-- * Function : int NCR53c7xx_abort (Scsi_Cmnd *cmd)
-- * 
-- * Purpose : Abort an errant SCSI command, doing all necessary
-- *    cleanup of the issue_queue, running_list, shared Linux/NCR
-- *    dsa issue and reconnect queues.
-- *
-- * Inputs : cmd - command to abort, code - entire result field
-- *
-- * Returns : 0 on success, -1 on failure.
-- */
--
--int 
--NCR53c7xx_abort (Scsi_Cmnd *cmd) {
--    NCR53c7x0_local_declare();
--    struct Scsi_Host *host = cmd->device->host;
--    struct NCR53c7x0_hostdata *hostdata = host ? (struct NCR53c7x0_hostdata *) 
--      host->hostdata[0] : NULL;
--    unsigned long flags;
--    struct NCR53c7x0_cmd *curr, **prev;
--    Scsi_Cmnd *me, **last;
--#if 0
--    static long cache_pid = -1;
--#endif
+-              Supporting multiple CPU idle levels in kernel
 -
+-                              cpuidle drivers
 -
--    if (!host) {
--      printk ("Bogus SCSI command pid %ld; no host structure\n",
--          cmd->pid);
--      return SCSI_ABORT_ERROR;
--    } else if (!hostdata) {
--      printk ("Bogus SCSI host %d; no hostdata\n", host->host_no);
--      return SCSI_ABORT_ERROR;
--    }
--    NCR53c7x0_local_setup(host);
 -
--/*
-- * CHECK : I don't think that reading ISTAT will unstack any interrupts,
-- *    since we need to write the INTF bit to clear it, and SCSI/DMA
-- *    interrupts don't clear until we read SSTAT/SIST and DSTAT registers.
-- *    
-- *    See that this is the case.  Appears to be correct on the 710, at least.
-- *
-- * I suspect that several of our failures may be coming from a new fatal
-- * interrupt (possibly due to a phase mismatch) happening after we've left
-- * the interrupt handler, but before the PIC has had the interrupt condition
-- * cleared.
-- */
--
--    if (NCR53c7x0_read8(hostdata->istat) & (ISTAT_DIP|ISTAT_SIP)) {
--      printk ("scsi%d : dropped interrupt for command %ld\n", host->host_no,
--          cmd->pid);
--      NCR53c7x0_intr (host->irq, NULL, NULL);
--      return SCSI_ABORT_BUSY;
--    }
--      
--    local_irq_save(flags);
--#if 0
--    if (cache_pid == cmd->pid) 
--      panic ("scsi%d : bloody fetus %d\n", host->host_no, cmd->pid);
--    else
--      cache_pid = cmd->pid;
--#endif
--      
 -
--/*
-- * The command could be hiding in the issue_queue.  This would be very
-- * nice, as commands can't be moved from the high level driver's issue queue 
-- * into the shared queue until an interrupt routine is serviced, and this
-- * moving is atomic.  
-- *
-- * If this is the case, we don't have to worry about anything - we simply
-- * pull the command out of the old queue, and call it aborted.
-- */
--
--    for (me = (Scsi_Cmnd *) hostdata->issue_queue, 
--         last = (Scsi_Cmnd **) &(hostdata->issue_queue);
--       me && me != cmd;  last = (Scsi_Cmnd **)&(me->SCp.ptr), 
--       me = (Scsi_Cmnd *)me->SCp.ptr);
--
--    if (me) {
--      *last = (Scsi_Cmnd *) me->SCp.ptr;
--      if (me->host_scribble) {
--          ((struct NCR53c7x0_cmd *)me->host_scribble)->next = hostdata->free;
--          hostdata->free = (struct NCR53c7x0_cmd *) me->host_scribble;
--          me->host_scribble = NULL;
--      }
--      cmd->result = DID_ABORT << 16;
--      cmd->scsi_done(cmd);
--      printk ("scsi%d : found command %ld in Linux issue queue\n", 
--          host->host_no, me->pid);
--      local_irq_restore(flags);
--      run_process_issue_queue();
--      return SCSI_ABORT_SUCCESS;
--    }
 -
--/* 
-- * That failing, the command could be in our list of already executing 
-- * commands.  If this is the case, drastic measures are called for.  
-- */ 
--
--    for (curr = (struct NCR53c7x0_cmd *) hostdata->running_list, 
--       prev = (struct NCR53c7x0_cmd **) &(hostdata->running_list);
--       curr && curr->cmd != cmd; prev = (struct NCR53c7x0_cmd **) 
--         &(curr->next), curr = (struct NCR53c7x0_cmd *) curr->next);
--
--    if (curr) {
--      if ((curr->result & 0xff) != 0xff && (curr->result & 0xff00) != 0xff00) {
--            cmd->result = curr->result;
--          if (prev)
--              *prev = (struct NCR53c7x0_cmd *) curr->next;
--          curr->next = (struct NCR53c7x0_cmd *) hostdata->free;
--          cmd->host_scribble = NULL;
--          hostdata->free = curr;
--          cmd->scsi_done(cmd);
--      printk ("scsi%d : found finished command %ld in running list\n", 
--          host->host_no, cmd->pid);
--          local_irq_restore(flags);
--          return SCSI_ABORT_NOT_RUNNING;
--      } else {
--          printk ("scsi%d : DANGER : command running, can not abort.\n",
--              cmd->device->host->host_no);
--          local_irq_restore(flags);
--          return SCSI_ABORT_BUSY;
--      }
--    }
+-cpuidle driver supports capability detection for a particular system. The
+-init and exit routines will be called for each online CPU, with a percpu
+-cpuidle_driver object and driver should fill in cpuidle_states inside
+-cpuidle_driver depending on the CPU capability.
 -
--/* 
-- * And if we couldn't find it in any of our queues, it must have been 
-- * a dropped interrupt.
-- */
--
--    curr = (struct NCR53c7x0_cmd *) cmd->host_scribble;
--    if (curr) {
--      curr->next = hostdata->free;
--      hostdata->free = curr;
--      cmd->host_scribble = NULL;
--    }
--
--    if (curr == NULL || ((curr->result & 0xff00) == 0xff00) ||
--              ((curr->result & 0xff) == 0xff)) {
--      printk ("scsi%d : did this command ever run?\n", host->host_no);
--          cmd->result = DID_ABORT << 16;
--    } else {
--      printk ("scsi%d : probably lost INTFLY, normal completion\n", 
--          host->host_no);
--        cmd->result = curr->result;
--/* 
-- * FIXME : We need to add an additional flag which indicates if a 
-- * command was ever counted as BUSY, so if we end up here we can
-- * decrement the busy count if and only if it is necessary.
-- */
--        --hostdata->busy[cmd->device->id][cmd->device->lun];
--    }
--    local_irq_restore(flags);
--    cmd->scsi_done(cmd);
+-Driver can handle dynamic state changes (like battery<->AC), by calling
+-force_redetect interface.
 -
--/* 
-- * We need to run process_issue_queue since termination of this command 
-- * may allow another queued command to execute first? 
-- */
--    return SCSI_ABORT_NOT_RUNNING;
--}
+-It is possible to have more than one driver registered at the same time and
+-user can switch between drivers using /sysfs interface.
 -
--/*
-- * Function : int NCR53c7xx_reset (Scsi_Cmnd *cmd) 
-- * 
-- * Purpose : perform a hard reset of the SCSI bus and NCR
-- *    chip.
-- *
-- * Inputs : cmd - command which caused the SCSI RESET
-- *
-- * Returns : 0 on success.
-- */
-- 
--int 
--NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) {
--    NCR53c7x0_local_declare();
--    unsigned long flags;
--    int found = 0;
--    struct NCR53c7x0_cmd * c;
--    Scsi_Cmnd *tmp;
--    /*
--     * When we call scsi_done(), it's going to wake up anything sleeping on the
--     * resources which were in use by the aborted commands, and we'll start to 
--     * get new commands.
--     *
--     * We can't let this happen until after we've re-initialized the driver
--     * structures, and can't reinitialize those structures until after we've 
--     * dealt with their contents.
--     *
--     * So, we need to find all of the commands which were running, stick
--     * them on a linked list of completed commands (we'll use the host_scribble
--     * pointer), do our reinitialization, and then call the done function for
--     * each command.  
--     */
--    Scsi_Cmnd *nuke_list = NULL;
--    struct Scsi_Host *host = cmd->device->host;
--    struct NCR53c7x0_hostdata *hostdata = 
--      (struct NCR53c7x0_hostdata *) host->hostdata[0];
--
--    NCR53c7x0_local_setup(host);
--    local_irq_save(flags);
--    ncr_halt (host);
--    print_lots (host);
--    dump_events (host, 30);
--    ncr_scsi_reset (host);
--    for (tmp = nuke_list = return_outstanding_commands (host, 1 /* free */,
--      0 /* issue */ ); tmp; tmp = (Scsi_Cmnd *) tmp->SCp.buffer)
--      if (tmp == cmd) {
--          found = 1;
--          break;
--      }
--          
--    /* 
--     * If we didn't find the command which caused this reset in our running
--     * list, then we've lost it.  See that it terminates normally anyway.
--     */
--    if (!found) {
--      c = (struct NCR53c7x0_cmd *) cmd->host_scribble;
--      if (c) {
--          cmd->host_scribble = NULL;
--          c->next = hostdata->free;
--          hostdata->free = c;
--      } else
--          printk ("scsi%d: lost command %ld\n", host->host_no, cmd->pid);
--      cmd->SCp.buffer = (struct scatterlist *) nuke_list;
--      nuke_list = cmd;
--    }
--
--    NCR53c7x0_driver_init (host);
--    hostdata->soft_reset (host);
--    if (hostdata->resets == 0) 
--      disable(host);
--    else if (hostdata->resets != -1)
--      --hostdata->resets;
--    local_irq_restore(flags);
--    for (; nuke_list; nuke_list = tmp) {
--      tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
--      nuke_list->result = DID_RESET << 16;
--      nuke_list->scsi_done (nuke_list);
--    }
--    local_irq_restore(flags);
--    return SCSI_RESET_SUCCESS;
--}
+-Interfaces:
+-int cpuidle_register_driver(struct cpuidle_driver *drv);
+-void cpuidle_unregister_driver(struct cpuidle_driver *drv);
+-int cpuidle_force_redetect(struct cpuidle_device *dev);
+diff -Nurb linux-2.6.22-590/Documentation/cpuidle/governor.txt linux-2.6.22-570/Documentation/cpuidle/governor.txt
+--- linux-2.6.22-590/Documentation/cpuidle/governor.txt        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/cpuidle/governor.txt        1969-12-31 19:00:00.000000000 -0500
+@@ -1,24 +0,0 @@
 -
--/*
-- * The NCR SDMS bios follows Annex A of the SCSI-CAM draft, and 
-- * therefore shares the scsicam_bios_param function.
-- */
 -
--/*
-- * Function : int insn_to_offset (Scsi_Cmnd *cmd, u32 *insn)
-- *
-- * Purpose : convert instructions stored at NCR pointer into data 
-- *    pointer offset.
-- * 
-- * Inputs : cmd - SCSI command; insn - pointer to instruction.  Either current
-- *    DSP, or saved data pointer.
-- *
-- * Returns : offset on success, -1 on failure.
-- */
 -
+-              Supporting multiple CPU idle levels in kernel
 -
--static int 
--insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) {
--    struct NCR53c7x0_hostdata *hostdata = 
--      (struct NCR53c7x0_hostdata *) cmd->device->host->hostdata[0];
--    struct NCR53c7x0_cmd *ncmd = 
--      (struct NCR53c7x0_cmd *) cmd->host_scribble;
--    int offset = 0, buffers;
--    struct scatterlist *segment;
--    char *ptr;
--    int found = 0;
+-                              cpuidle governors
 -
--/*
-- * With the current code implementation, if the insn is inside dynamically 
-- * generated code, the data pointer will be the instruction preceding 
-- * the next transfer segment.
-- */
--
--    if (!check_address ((unsigned long) ncmd, sizeof (struct NCR53c7x0_cmd)) &&
--      ((insn >= ncmd->data_transfer_start &&  
--          insn < ncmd->data_transfer_end) ||
--      (insn >= ncmd->residual &&
--          insn < (ncmd->residual + 
--              sizeof(ncmd->residual))))) {
--          ptr = bus_to_virt(insn[3]);
--
--          if ((buffers = cmd->use_sg)) {
--              for (offset = 0, 
--                      segment = (struct scatterlist *) cmd->request_buffer;
--                   buffers && !((found = ((ptr >= (char *)page_address(segment->page)+segment->offset) && 
--                          (ptr < ((char *)page_address(segment->page)+segment->offset+segment->length)))));
--                   --buffers, offset += segment->length, ++segment)
--#if 0
--                  printk("scsi%d: comparing 0x%p to 0x%p\n", 
--                      cmd->device->host->host_no, saved, page_address(segment->page+segment->offset));
--#else
--                  ;
--#endif
--                  offset += ptr - ((char *)page_address(segment->page)+segment->offset);
--          } else {
--              found = 1;
--              offset = ptr - (char *) (cmd->request_buffer);
--          }
--    } else if ((insn >= hostdata->script + 
--              hostdata->E_data_transfer / sizeof(u32)) &&
--             (insn <= hostdata->script +
--              hostdata->E_end_data_transfer / sizeof(u32))) {
--      found = 1;
--      offset = 0;
--    }
--    return found ? offset : -1;
--}
 -
 -
 -
--/*
-- * Function : void print_progress (Scsi_Cmnd *cmd) 
-- * 
-- * Purpose : print the current location of the saved data pointer
-- *
-- * Inputs : cmd - command we are interested in
-- *
-- */
--
--static void 
--print_progress (Scsi_Cmnd *cmd) {
--    NCR53c7x0_local_declare();
--    struct NCR53c7x0_cmd *ncmd = 
--      (struct NCR53c7x0_cmd *) cmd->host_scribble;
--    int offset, i;
--    char *where;
--    u32 *ptr;
--    NCR53c7x0_local_setup (cmd->device->host);
--
--    if (check_address ((unsigned long) ncmd,sizeof (struct NCR53c7x0_cmd)) == 0)
--    {
--      printk("\nNCR53c7x0_cmd fields:\n");
--      printk("  bounce.len=0x%x, addr=0x%0x, buf[]=0x%02x %02x %02x %02x\n",
--          ncmd->bounce.len, ncmd->bounce.addr, ncmd->bounce.buf[0],
--          ncmd->bounce.buf[1], ncmd->bounce.buf[2], ncmd->bounce.buf[3]);
--      printk("  result=%04x, cdb[0]=0x%02x\n", ncmd->result, ncmd->cmnd[0]);
--    }
--
--    for (i = 0; i < 2; ++i) {
--      if (check_address ((unsigned long) ncmd, 
--          sizeof (struct NCR53c7x0_cmd)) == -1) 
--          continue;
--      if (!i) {
--          where = "saved";
--          ptr = bus_to_virt(ncmd->saved_data_pointer);
--      } else {
--          where = "active";
--          ptr = bus_to_virt (NCR53c7x0_read32 (DSP_REG) -
--              NCR53c7x0_insn_size (NCR53c7x0_read8 (DCMD_REG)) *
--              sizeof(u32));
--      } 
--      offset = insn_to_offset (cmd, ptr);
--
--      if (offset != -1) 
--          printk ("scsi%d : %s data pointer at offset %d\n",
--              cmd->device->host->host_no, where, offset);
--      else {
--          int size;
--          printk ("scsi%d : can't determine %s data pointer offset\n",
--              cmd->device->host->host_no, where);
--          if (ncmd) {
--              size = print_insn (cmd->device->host,
--                  bus_to_virt(ncmd->saved_data_pointer), "", 1);
--              print_insn (cmd->device->host,
--                  bus_to_virt(ncmd->saved_data_pointer) + size * sizeof(u32),
--                  "", 1);
--          }
--      }
--    }
--}
--
--
--static void 
--print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) {
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    int i, len;
--    char *ptr;
--    Scsi_Cmnd *cmd;
--
--    if (check_address ((unsigned long) dsa, hostdata->dsa_end - 
--      hostdata->dsa_start) == -1) {
--      printk("scsi%d : bad dsa virt 0x%p\n", host->host_no, dsa);
--      return;
--    }
--    printk("%sscsi%d : dsa at phys 0x%lx (virt 0x%p)\n"
--          "        + %d : dsa_msgout length = %u, data = 0x%x (virt 0x%p)\n" ,
--          prefix ? prefix : "",
--          host->host_no,  virt_to_bus (dsa), dsa, hostdata->dsa_msgout,
--          dsa[hostdata->dsa_msgout / sizeof(u32)],
--          dsa[hostdata->dsa_msgout / sizeof(u32) + 1],
--          bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1]));
--
--    /* 
--     * Only print messages if they're sane in length so we don't
--     * blow the kernel printk buffer on something which won't buy us
--     * anything.
--     */
--
--    if (dsa[hostdata->dsa_msgout / sizeof(u32)] < 
--          sizeof (hostdata->free->select)) 
--      for (i = dsa[hostdata->dsa_msgout / sizeof(u32)],
--          ptr = bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1]); 
--          i > 0 && !check_address ((unsigned long) ptr, 1);
--          ptr += len, i -= len) {
--          printk("               ");
--          len = spi_print_msg(ptr);
--          printk("\n");
--          if (!len)
--              break;
--      }
+-cpuidle governor is policy routine that decides what idle state to enter at
+-any given time. cpuidle core uses different callbacks to governor while
+-handling idle entry.
+-* select_state callback where governor can determine next idle state to enter
+-* prepare_idle callback is called before entering an idle state
+-* scan callback is called after a driver forces redetection of the states
 -
--    printk("        + %d : select_indirect = 0x%x\n",
--      hostdata->dsa_select, dsa[hostdata->dsa_select / sizeof(u32)]);
--    cmd = (Scsi_Cmnd *) bus_to_virt(dsa[hostdata->dsa_cmnd / sizeof(u32)]);
--    printk("        + %d : dsa_cmnd = 0x%x ", hostdata->dsa_cmnd,
--         (u32) virt_to_bus(cmd));
--    /* XXX Maybe we should access cmd->host_scribble->result here. RGH */
--    if (cmd) {
--      printk("               result = 0x%x, target = %d, lun = %d, cmd = ",
--          cmd->result, cmd->device->id, cmd->device->lun);
--      __scsi_print_command(cmd->cmnd);
--    } else
--      printk("\n");
--    printk("        + %d : dsa_next = 0x%x\n", hostdata->dsa_next,
--      dsa[hostdata->dsa_next / sizeof(u32)]);
--    if (cmd) { 
--      printk("scsi%d target %d : sxfer_sanity = 0x%x, scntl3_sanity = 0x%x\n"
--             "                   script : ",
--          host->host_no, cmd->device->id,
--          hostdata->sync[cmd->device->id].sxfer_sanity,
--          hostdata->sync[cmd->device->id].scntl3_sanity);
--      for (i = 0; i < (sizeof(hostdata->sync[cmd->device->id].script) / 4); ++i)
--          printk ("0x%x ", hostdata->sync[cmd->device->id].script[i]);
--      printk ("\n");
--      print_progress (cmd);
--    }
--}
--/*
-- * Function : void print_queues (Scsi_Host *host) 
-- * 
-- * Purpose : print the contents of the NCR issue and reconnect queues
-- *
-- * Inputs : host - SCSI host we are interested in
-- *
-- */
+-More than one governor can be registered at the same time and
+-user can switch between drivers using /sysfs interface.
 -
--static void 
--print_queues (struct Scsi_Host *host) {
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    u32 *dsa, *next_dsa;
--    volatile u32 *ncrcurrent;
--    int left;
--    Scsi_Cmnd *cmd, *next_cmd;
--    unsigned long flags;
+-Interfaces:
+-int cpuidle_register_governor(struct cpuidle_governor *gov);
+-void cpuidle_unregister_governor(struct cpuidle_governor *gov);
 -
--    printk ("scsi%d : issue queue\n", host->host_no);
+diff -Nurb linux-2.6.22-590/Documentation/cpuidle/sysfs.txt linux-2.6.22-570/Documentation/cpuidle/sysfs.txt
+--- linux-2.6.22-590/Documentation/cpuidle/sysfs.txt   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/cpuidle/sysfs.txt   1969-12-31 19:00:00.000000000 -0500
+@@ -1,27 +0,0 @@
 -
--    for (left = host->can_queue, cmd = (Scsi_Cmnd *) hostdata->issue_queue; 
--          left >= 0 && cmd; 
--          cmd = next_cmd) {
--      next_cmd = (Scsi_Cmnd *) cmd->SCp.ptr;
--      local_irq_save(flags);
--      if (cmd->host_scribble) {
--          if (check_address ((unsigned long) (cmd->host_scribble), 
--              sizeof (cmd->host_scribble)) == -1)
--              printk ("scsi%d: scsi pid %ld bad pointer to NCR53c7x0_cmd\n",
--                  host->host_no, cmd->pid);
--          /* print_dsa does sanity check on address, no need to check */
--          else
--              print_dsa (host, ((struct NCR53c7x0_cmd *) cmd->host_scribble)
--                  -> dsa, "");
--      } else 
--          printk ("scsi%d : scsi pid %ld for target %d lun %d has no NCR53c7x0_cmd\n",
--              host->host_no, cmd->pid, cmd->device->id, cmd->device->lun);
--      local_irq_restore(flags);
--    }
--
--    if (left <= 0) {
--      printk ("scsi%d : loop detected in issue queue\n",
--          host->host_no);
--    }
--
--    /*
--     * Traverse the NCR reconnect and start DSA structures, printing out 
--     * each element until we hit the end or detect a loop.  Currently,
--     * the reconnect structure is a linked list; and the start structure
--     * is an array.  Eventually, the reconnect structure will become a 
--     * list as well, since this simplifies the code.
--     */
--
--    printk ("scsi%d : schedule dsa array :\n", host->host_no);
--    for (left = host->can_queue, ncrcurrent = hostdata->schedule;
--          left > 0; ncrcurrent += 2, --left)
--      if (ncrcurrent[0] != hostdata->NOP_insn) 
--/* FIXME : convert pointer to dsa_begin to pointer to dsa. */
--          print_dsa (host, bus_to_virt (ncrcurrent[1] - 
--              (hostdata->E_dsa_code_begin - 
--              hostdata->E_dsa_code_template)), "");
--    printk ("scsi%d : end schedule dsa array\n", host->host_no);
--    
--    printk ("scsi%d : reconnect_dsa_head :\n", host->host_no);
--          
--    for (left = host->can_queue, 
--      dsa = bus_to_virt (hostdata->reconnect_dsa_head);
--      left >= 0 && dsa; 
--      dsa = next_dsa) {
--      local_irq_save(flags);
--      if (check_address ((unsigned long) dsa, sizeof(dsa)) == -1) {
--          printk ("scsi%d: bad DSA pointer 0x%p", host->host_no,
--              dsa);
--          next_dsa = NULL;
--      }
--      else 
--      {
--          next_dsa = bus_to_virt(dsa[hostdata->dsa_next / sizeof(u32)]);
--          print_dsa (host, dsa, "");
--      }
--      local_irq_restore(flags);
--    }
--    printk ("scsi%d : end reconnect_dsa_head\n", host->host_no);
--    if (left < 0)
--      printk("scsi%d: possible loop in ncr reconnect list\n",
--          host->host_no);
--}
 -
--static void
--print_lots (struct Scsi_Host *host) {
--    NCR53c7x0_local_declare();
--    struct NCR53c7x0_hostdata *hostdata = 
--      (struct NCR53c7x0_hostdata *) host->hostdata[0];
--    u32 *dsp_next, *dsp, *dsa, dbc_dcmd;
--    unsigned char dcmd, sbcl;
--    int i, size;
--    NCR53c7x0_local_setup(host);
--
--    if ((dsp_next = bus_to_virt(NCR53c7x0_read32 (DSP_REG)))) {
--      dbc_dcmd = NCR53c7x0_read32(DBC_REG);
--      dcmd = (dbc_dcmd & 0xff000000) >> 24;
--      dsp = dsp_next - NCR53c7x0_insn_size(dcmd);
--      dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
--      sbcl = NCR53c7x0_read8 (SBCL_REG);
--          
--      /*
--       * For the 53c710, the following will report value 0 for SCNTL3
--       * and STEST0 - we don't have these registers.
--       */
--      printk ("scsi%d : DCMD|DBC=0x%x, DNAD=0x%x (virt 0x%p)\n"
--              "         DSA=0x%lx (virt 0x%p)\n"
--              "         DSPS=0x%x, TEMP=0x%x (virt 0x%p), DMODE=0x%x\n"
--              "         SXFER=0x%x, SCNTL3=0x%x\n"
--              "         %s%s%sphase=%s, %d bytes in SCSI FIFO\n"
--              "         SCRATCH=0x%x, saved2_dsa=0x%0lx\n",
--          host->host_no, dbc_dcmd, NCR53c7x0_read32(DNAD_REG),
--              bus_to_virt(NCR53c7x0_read32(DNAD_REG)),
--          virt_to_bus(dsa), dsa,
--          NCR53c7x0_read32(DSPS_REG), NCR53c7x0_read32(TEMP_REG), 
--          bus_to_virt (NCR53c7x0_read32(TEMP_REG)),
--          (int) NCR53c7x0_read8(hostdata->dmode),
--          (int) NCR53c7x0_read8(SXFER_REG), 
--          ((hostdata->chip / 100) == 8) ?
--              (int) NCR53c7x0_read8(SCNTL3_REG_800) : 0,
--          (sbcl & SBCL_BSY) ? "BSY " : "",
--          (sbcl & SBCL_SEL) ? "SEL " : "",
--          (sbcl & SBCL_REQ) ? "REQ " : "",
--          sstat2_to_phase(NCR53c7x0_read8 (((hostdata->chip / 100) == 8) ?
--              SSTAT1_REG : SSTAT2_REG)),
--          (NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ? 
--              SSTAT1_REG : SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT,
--          ((hostdata->chip / 100) == 8) ? NCR53c7x0_read8 (STEST0_REG_800) :
--              NCR53c7x0_read32(SCRATCHA_REG_800),
--          hostdata->saved2_dsa);
--      printk ("scsi%d : DSP 0x%lx (virt 0x%p) ->\n", host->host_no, 
--          virt_to_bus(dsp), dsp);
--      for (i = 6; i > 0; --i, dsp += size)
--          size = print_insn (host, dsp, "", 1);
--      if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON)  {
--          if ((hostdata->chip / 100) == 8)
--              printk ("scsi%d : connected (SDID=0x%x, SSID=0x%x)\n",
--                  host->host_no, NCR53c7x0_read8 (SDID_REG_800),
--                  NCR53c7x0_read8 (SSID_REG_800));
--          else
--              printk ("scsi%d : connected (SDID=0x%x)\n",
--                  host->host_no, NCR53c7x0_read8 (SDID_REG_700));
--          print_dsa (host, dsa, "");
--      }
--
--#if 1
--      print_queues (host);
--#endif
--    }
--}
+-              Supporting multiple CPU idle levels in kernel
 -
--/*
-- * Function : static int shutdown (struct Scsi_Host *host)
-- * 
-- * Purpose : does a clean (we hope) shutdown of the NCR SCSI 
-- *    chip.  Use prior to dumping core, unloading the NCR driver,
-- * 
-- * Returns : 0 on success
-- */
--static int 
--shutdown (struct Scsi_Host *host) {
--    NCR53c7x0_local_declare();
--    unsigned long flags;
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    NCR53c7x0_local_setup(host);
--    local_irq_save(flags);
--/* Get in a state where we can reset the SCSI bus */
--    ncr_halt (host);
--    ncr_scsi_reset (host);
--    hostdata->soft_reset(host);
--
--    disable (host);
--    local_irq_restore(flags);
--    return 0;
--}
+-                              cpuidle sysfs
 -
--/*
-- * Function : void ncr_scsi_reset (struct Scsi_Host *host)
-- *
-- * Purpose : reset the SCSI bus.
-- */
+-System global cpuidle information are under
+-/sys/devices/system/cpu/cpuidle
 -
--static void 
--ncr_scsi_reset (struct Scsi_Host *host) {
--    NCR53c7x0_local_declare();
--    unsigned long flags;
--    NCR53c7x0_local_setup(host);
--    local_irq_save(flags);
--    NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
--    udelay(25);       /* Minimum amount of time to assert RST */
--    NCR53c7x0_write8(SCNTL1_REG, 0);
--    local_irq_restore(flags);
--}
+-The current interfaces in this directory has self-explanatory names:
+-* available_drivers
+-* available_governors
+-* current_driver
+-* current_governor
 -
--/* 
-- * Function : void hard_reset (struct Scsi_Host *host)
-- *
-- */
+-Per logical CPU specific cpuidle information are under
+-/sys/devices/system/cpu/cpuX/cpuidle
+-for each online cpu X
 -
--static void 
--hard_reset (struct Scsi_Host *host) {
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    unsigned long flags;
--    local_irq_save(flags);
--    ncr_scsi_reset(host);
--    NCR53c7x0_driver_init (host);
--    if (hostdata->soft_reset)
--      hostdata->soft_reset (host);
--    local_irq_restore(flags);
--}
+-Under this percpu directory, there is a directory for each idle state supported
+-by the driver, which in turn has
+-* latency
+-* power
+-* time
+-* usage
 -
 -
--/*
-- * Function : Scsi_Cmnd *return_outstanding_commands (struct Scsi_Host *host,
-- *    int free, int issue)
-- *
-- * Purpose : return a linked list (using the SCp.buffer field as next,
-- *    so we don't perturb hostdata.  We don't use a field of the 
-- *    NCR53c7x0_cmd structure since we may not have allocated one 
-- *    for the command causing the reset.) of Scsi_Cmnd structures that 
-- *    had propagated below the Linux issue queue level.  If free is set, 
-- *    free the NCR53c7x0_cmd structures which are associated with 
-- *    the Scsi_Cmnd structures, and clean up any internal 
-- *    NCR lists that the commands were on.  If issue is set,
-- *    also return commands in the issue queue.
-- *
-- * Returns : linked list of commands
-- *
-- * NOTE : the caller should insure that the NCR chip is halted
-- *    if the free flag is set. 
-- */
--
--static Scsi_Cmnd *
--return_outstanding_commands (struct Scsi_Host *host, int free, int issue) {
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    struct NCR53c7x0_cmd *c;
--    int i;
--    u32 *ncrcurrent;
--    Scsi_Cmnd *list = NULL, *tmp;
--    for (c = (struct NCR53c7x0_cmd *) hostdata->running_list; c; 
--      c = (struct NCR53c7x0_cmd *) c->next)  {
--      if (c->cmd->SCp.buffer) {
--          printk ("scsi%d : loop detected in running list!\n", host->host_no);
--          break;
--      } else {
--          printk ("Duh? Bad things happening in the NCR driver\n");
--          break;
--      }
+diff -Nurb linux-2.6.22-590/Documentation/cpusets.txt linux-2.6.22-570/Documentation/cpusets.txt
+--- linux-2.6.22-590/Documentation/cpusets.txt 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/cpusets.txt 2007-07-08 19:32:17.000000000 -0400
+@@ -7,7 +7,6 @@
+ Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
+ Modified by Paul Jackson <pj@sgi.com>
+ Modified by Christoph Lameter <clameter@sgi.com>
+-Modified by Paul Menage <menage@google.com>
+ CONTENTS:
+ =========
+@@ -17,9 +16,10 @@
+   1.2 Why are cpusets needed ?
+   1.3 How are cpusets implemented ?
+   1.4 What are exclusive cpusets ?
+-  1.5 What is memory_pressure ?
+-  1.6 What is memory spread ?
+-  1.7 How do I use cpusets ?
++  1.5 What does notify_on_release do ?
++  1.6 What is memory_pressure ?
++  1.7 What is memory spread ?
++  1.8 How do I use cpusets ?
+ 2. Usage Examples and Syntax
+   2.1 Basic Usage
+   2.2 Adding/removing cpus
+@@ -43,19 +43,18 @@
+ hooks, beyond what is already present, required to manage dynamic
+ job placement on large systems.
+-Cpusets use the generic container subsystem described in
+-Documentation/container.txt.
++Each task has a pointer to a cpuset.  Multiple tasks may reference
++the same cpuset.  Requests by a task, using the sched_setaffinity(2)
++system call to include CPUs in its CPU affinity mask, and using the
++mbind(2) and set_mempolicy(2) system calls to include Memory Nodes
++in its memory policy, are both filtered through that tasks cpuset,
++filtering out any CPUs or Memory Nodes not in that cpuset.  The
++scheduler will not schedule a task on a CPU that is not allowed in
++its cpus_allowed vector, and the kernel page allocator will not
++allocate a page on a node that is not allowed in the requesting tasks
++mems_allowed vector.
+-Requests by a task, using the sched_setaffinity(2) system call to
+-include CPUs in its CPU affinity mask, and using the mbind(2) and
+-set_mempolicy(2) system calls to include Memory Nodes in its memory
+-policy, are both filtered through that tasks cpuset, filtering out any
+-CPUs or Memory Nodes not in that cpuset.  The scheduler will not
+-schedule a task on a CPU that is not allowed in its cpus_allowed
+-vector, and the kernel page allocator will not allocate a page on a
+-node that is not allowed in the requesting tasks mems_allowed vector.
+-
+-User level code may create and destroy cpusets by name in the container
++User level code may create and destroy cpusets by name in the cpuset
+ virtual file system, manage the attributes and permissions of these
+ cpusets and which CPUs and Memory Nodes are assigned to each cpuset,
+ specify and query to which cpuset a task is assigned, and list the
+@@ -87,6 +86,9 @@
+       and a database), or
+     * NUMA systems running large HPC applications with demanding
+       performance characteristics.
++    * Also cpu_exclusive cpusets are useful for servers running orthogonal
++      workloads such as RT applications requiring low latency and HPC
++      applications that are throughput sensitive
+ These subsets, or "soft partitions" must be able to be dynamically
+ adjusted, as the job mix changes, without impacting other concurrently
+@@ -115,7 +117,7 @@
+  - Cpusets are sets of allowed CPUs and Memory Nodes, known to the
+    kernel.
+  - Each task in the system is attached to a cpuset, via a pointer
+-   in the task structure to a reference counted container structure.
++   in the task structure to a reference counted cpuset structure.
+  - Calls to sched_setaffinity are filtered to just those CPUs
+    allowed in that tasks cpuset.
+  - Calls to mbind and set_mempolicy are filtered to just
+@@ -129,6 +131,8 @@
+  - A cpuset may be marked exclusive, which ensures that no other
+    cpuset (except direct ancestors and descendents) may contain
+    any overlapping CPUs or Memory Nodes.
++   Also a cpu_exclusive cpuset would be associated with a sched
++   domain.
+  - You can list all the tasks (by pid) attached to any cpuset.
+ The implementation of cpusets requires a few, simple hooks
+@@ -140,15 +144,23 @@
+    allowed in that tasks cpuset.
+  - in sched.c migrate_all_tasks(), to keep migrating tasks within
+    the CPUs allowed by their cpuset, if possible.
++ - in sched.c, a new API partition_sched_domains for handling
++   sched domain changes associated with cpu_exclusive cpusets
++   and related changes in both sched.c and arch/ia64/kernel/domain.c
+  - in the mbind and set_mempolicy system calls, to mask the requested
+    Memory Nodes by what's allowed in that tasks cpuset.
+  - in page_alloc.c, to restrict memory to allowed nodes.
+  - in vmscan.c, to restrict page recovery to the current cpuset.
+-You should mount the "container" filesystem type in order to enable
+-browsing and modifying the cpusets presently known to the kernel.  No
+-new system calls are added for cpusets - all support for querying and
+-modifying cpusets is via this cpuset file system.
++In addition a new file system, of type "cpuset" may be mounted,
++typically at /dev/cpuset, to enable browsing and modifying the cpusets
++presently known to the kernel.  No new system calls are added for
++cpusets - all support for querying and modifying cpusets is via
++this cpuset file system.
++
++Each task under /proc has an added file named 'cpuset', displaying
++the cpuset name, as the path relative to the root of the cpuset file
++system.
+ The /proc/<pid>/status file for each task has two added lines,
+ displaying the tasks cpus_allowed (on which CPUs it may be scheduled)
+@@ -158,15 +170,16 @@
+   Cpus_allowed:   ffffffff,ffffffff,ffffffff,ffffffff
+   Mems_allowed:   ffffffff,ffffffff
+-Each cpuset is represented by a directory in the container file system
+-containing (on top of the standard container files) the following
+-files describing that cpuset:
++Each cpuset is represented by a directory in the cpuset file system
++containing the following files describing that cpuset:
+  - cpus: list of CPUs in that cpuset
+  - mems: list of Memory Nodes in that cpuset
+  - memory_migrate flag: if set, move pages to cpusets nodes
+  - cpu_exclusive flag: is cpu placement exclusive?
+  - mem_exclusive flag: is memory placement exclusive?
++ - tasks: list of tasks (by pid) attached to that cpuset
++ - notify_on_release flag: run /sbin/cpuset_release_agent on exit?
+  - memory_pressure: measure of how much paging pressure in cpuset
+ In addition, the root cpuset only has the following file:
+@@ -218,6 +231,15 @@
+ a direct ancestor or descendent, may share any of the same CPUs or
+ Memory Nodes.
++A cpuset that is cpu_exclusive has a scheduler (sched) domain
++associated with it.  The sched domain consists of all CPUs in the
++current cpuset that are not part of any exclusive child cpusets.
++This ensures that the scheduler load balancing code only balances
++against the CPUs that are in the sched domain as defined above and
++not all of the CPUs in the system. This removes any overhead due to
++load balancing code trying to pull tasks outside of the cpu_exclusive
++cpuset only to be prevented by the tasks' cpus_allowed mask.
++
+ A cpuset that is mem_exclusive restricts kernel allocations for
+ page, buffer and other data commonly shared by the kernel across
+ multiple users.  All cpusets, whether mem_exclusive or not, restrict
+@@ -231,7 +253,21 @@
+ outside even a mem_exclusive cpuset.
+-1.5 What is memory_pressure ?
++1.5 What does notify_on_release do ?
++------------------------------------
++
++If the notify_on_release flag is enabled (1) in a cpuset, then whenever
++the last task in the cpuset leaves (exits or attaches to some other
++cpuset) and the last child cpuset of that cpuset is removed, then
++the kernel runs the command /sbin/cpuset_release_agent, supplying the
++pathname (relative to the mount point of the cpuset file system) of the
++abandoned cpuset.  This enables automatic removal of abandoned cpusets.
++The default value of notify_on_release in the root cpuset at system
++boot is disabled (0).  The default value of other cpusets at creation
++is the current value of their parents notify_on_release setting.
++
++
++1.6 What is memory_pressure ?
+ -----------------------------
+ The memory_pressure of a cpuset provides a simple per-cpuset metric
+ of the rate that the tasks in a cpuset are attempting to free up in
+@@ -288,7 +324,7 @@
+ times 1000.
+-1.6 What is memory spread ?
++1.7 What is memory spread ?
+ ---------------------------
+ There are two boolean flag files per cpuset that control where the
+ kernel allocates pages for the file system buffers and related in
+@@ -359,7 +395,7 @@
+ can become very uneven.
+-1.7 How do I use cpusets ?
++1.8 How do I use cpusets ?
+ --------------------------
+ In order to minimize the impact of cpusets on critical kernel
+@@ -449,7 +485,7 @@
+ To start a new job that is to be contained within a cpuset, the steps are:
+  1) mkdir /dev/cpuset
+- 2) mount -t container -ocpuset cpuset /dev/cpuset
++ 2) mount -t cpuset none /dev/cpuset
+  3) Create the new cpuset by doing mkdir's and write's (or echo's) in
+     the /dev/cpuset virtual file system.
+  4) Start a task that will be the "founding father" of the new job.
+@@ -461,7 +497,7 @@
+ named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
+ and then start a subshell 'sh' in that cpuset:
+-  mount -t container -ocpuset cpuset /dev/cpuset
++  mount -t cpuset none /dev/cpuset
+   cd /dev/cpuset
+   mkdir Charlie
+   cd Charlie
+@@ -493,7 +529,7 @@
+ virtual filesystem.
+ To mount it, type:
+-# mount -t container -o cpuset cpuset /dev/cpuset
++# mount -t cpuset none /dev/cpuset
+ Then under /dev/cpuset you can find a tree that corresponds to the
+ tree of the cpusets in the system. For instance, /dev/cpuset
+@@ -536,18 +572,6 @@
+ This will fail if the cpuset is in use (has cpusets inside, or has
+ processes attached).
+-Note that for legacy reasons, the "cpuset" filesystem exists as a
+-wrapper around the container filesystem.
 -
--      c->cmd->SCp.buffer = (struct scatterlist *) list;
--      list = c->cmd;
--      if (free) {
--          c->next = hostdata->free;
--          hostdata->free = c;
--      }
--    }
+-The command
 -
--    if (free) { 
--      for (i = 0, ncrcurrent = (u32 *) hostdata->schedule; 
--          i < host->can_queue; ++i, ncrcurrent += 2) {
--          ncrcurrent[0] = hostdata->NOP_insn;
--          ncrcurrent[1] = 0xdeadbeef;
--      }
--      hostdata->ncrcurrent = NULL;
--    }
+-mount -t cpuset X /dev/cpuset
 -
--    if (issue) {
--      for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; tmp = tmp->next) {
--          if (tmp->SCp.buffer) {
--              printk ("scsi%d : loop detected in issue queue!\n", 
--                      host->host_no);
--              break;
--          }
--          tmp->SCp.buffer = (struct scatterlist *) list;
--          list = tmp;
--      }
--      if (free)
--          hostdata->issue_queue = NULL;
--              
--    }
--    return list;
--}
+-is equivalent to
 -
--/* 
-- * Function : static int disable (struct Scsi_Host *host)
-- *
-- * Purpose : disables the given NCR host, causing all commands
-- *    to return a driver error.  Call this so we can unload the
-- *    module during development and try again.  Eventually, 
-- *    we should be able to find clean workarounds for these
-- *    problems.
-- *
-- * Inputs : host - hostadapter to twiddle
-- *
-- * Returns : 0 on success.
-- */
--
--static int 
--disable (struct Scsi_Host *host) {
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    unsigned long flags;
--    Scsi_Cmnd *nuke_list, *tmp;
--    local_irq_save(flags);
--    if (hostdata->state != STATE_HALTED)
--      ncr_halt (host);
--    nuke_list = return_outstanding_commands (host, 1 /* free */, 1 /* issue */);
--    hard_reset (host);
--    hostdata->state = STATE_DISABLED;
--    local_irq_restore(flags);
--    printk ("scsi%d : nuking commands\n", host->host_no);
--    for (; nuke_list; nuke_list = tmp) {
--          tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
--          nuke_list->result = DID_ERROR << 16;
--          nuke_list->scsi_done(nuke_list);
--    }
--    printk ("scsi%d : done. \n", host->host_no);
--    printk (KERN_ALERT "scsi%d : disabled.  Unload and reload\n",
--      host->host_no);
--    return 0;
--}
+-mount -t container -ocpuset X /dev/cpuset
+-echo "/sbin/cpuset_release_agent" > /dev/cpuset/release_agent
 -
--/*
-- * Function : static int ncr_halt (struct Scsi_Host *host)
-- * 
-- * Purpose : halts the SCSI SCRIPTS(tm) processor on the NCR chip
-- *
-- * Inputs : host - SCSI chip to halt
-- *
-- * Returns : 0 on success
-- */
--
--static int 
--ncr_halt (struct Scsi_Host *host) {
--    NCR53c7x0_local_declare();
--    unsigned long flags;
--    unsigned char istat, tmp;
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    int stage;
--    NCR53c7x0_local_setup(host);
--
--    local_irq_save(flags);
--    /* Stage 0 : eat all interrupts
--       Stage 1 : set ABORT
--       Stage 2 : eat all but abort interrupts
--       Stage 3 : eat all interrupts
--     */
--    for (stage = 0;;) {
--      if (stage == 1) {
--          NCR53c7x0_write8(hostdata->istat, ISTAT_ABRT);
--          ++stage;
--      }
--      istat = NCR53c7x0_read8 (hostdata->istat);
--      if (istat & ISTAT_SIP) {
--          tmp = NCR53c7x0_read8(SSTAT0_REG);
--      } else if (istat & ISTAT_DIP) {
--          tmp = NCR53c7x0_read8(DSTAT_REG);
--          if (stage == 2) {
--              if (tmp & DSTAT_ABRT) {
--                  NCR53c7x0_write8(hostdata->istat, 0);
--                  ++stage;
--              } else {
--                  printk(KERN_ALERT "scsi%d : could not halt NCR chip\n", 
--                      host->host_no);
--                  disable (host);
--              }
--          }
--      }
--      if (!(istat & (ISTAT_SIP|ISTAT_DIP))) {
--          if (stage == 0)
--              ++stage;
--          else if (stage == 3)
--              break;
--      }
--    }
--    hostdata->state = STATE_HALTED;
--    local_irq_restore(flags);
--#if 0
--    print_lots (host);
--#endif
--    return 0;
--}
+ 2.2 Adding/removing cpus
+ ------------------------
+diff -Nurb linux-2.6.22-590/Documentation/feature-removal-schedule.txt linux-2.6.22-570/Documentation/feature-removal-schedule.txt
+--- linux-2.6.22-590/Documentation/feature-removal-schedule.txt        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/feature-removal-schedule.txt        2007-07-08 19:32:17.000000000 -0400
+@@ -162,33 +162,6 @@
+ ---------------------------
+-What: filemap_nopage, filemap_populate
+-When: April 2007
+-Why:  These legacy interfaces no longer have any callers in the kernel and
+-      any functionality provided can be provided with filemap_fault. The
+-      removal schedule is short because they are a big maintainence burden
+-      and have some bugs.
+-Who:  Nick Piggin <npiggin@suse.de>
 -
--/* 
-- * Function: event_name (int event)
-- * 
-- * Purpose: map event enum into user-readable strings.
-- */
+----------------------------
 -
--static const char *
--event_name (int event) {
--    switch (event) {
--    case EVENT_NONE:          return "none";
--    case EVENT_ISSUE_QUEUE:   return "to issue queue";
--    case EVENT_START_QUEUE:   return "to start queue";
--    case EVENT_SELECT:                return "selected";
--    case EVENT_DISCONNECT:    return "disconnected";
--    case EVENT_RESELECT:      return "reselected";
--    case EVENT_COMPLETE:      return "completed";
--    case EVENT_IDLE:          return "idle";
--    case EVENT_SELECT_FAILED: return "select failed";
--    case EVENT_BEFORE_SELECT: return "before select";
--    case EVENT_RESELECT_FAILED:       return "reselect failed";
--    default:                  return "unknown";
--    }
--}
+-What: vm_ops.populate, install_page
+-When: April 2007
+-Why:  These legacy interfaces no longer have any callers in the kernel and
+-      any functionality provided can be provided with vm_ops.fault.
+-Who:  Nick Piggin <npiggin@suse.de>
 -
--/*
-- * Function : void dump_events (struct Scsi_Host *host, count)
-- *
-- * Purpose : print last count events which have occurred.
-- */ 
--static void
--dump_events (struct Scsi_Host *host, int count) {
--    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
--      host->hostdata[0];
--    struct NCR53c7x0_event event;
--    int i;
--    unsigned long flags;
--    if (hostdata->events) {
--      if (count > hostdata->event_size)
--          count = hostdata->event_size;
--      for (i = hostdata->event_index; count > 0; 
--          i = (i ? i - 1 : hostdata->event_size -1), --count) {
--/*
-- * By copying the event we're currently examining with interrupts
-- * disabled, we can do multiple printk(), etc. operations and 
-- * still be guaranteed that they're happening on the same 
-- * event structure.
-- */
--          local_irq_save(flags);
--#if 0
--          event = hostdata->events[i];
--#else
--          memcpy ((void *) &event, (void *) &(hostdata->events[i]),
--              sizeof(event));
--#endif
+----------------------------
 -
--          local_irq_restore(flags);
--          printk ("scsi%d : %s event %d at %ld secs %ld usecs target %d lun %d\n",
--              host->host_no, event_name (event.event), count,
--              (long) event.time.tv_sec, (long) event.time.tv_usec,
--              event.target, event.lun);
--          if (event.dsa) 
--              printk ("         event for dsa 0x%lx (virt 0x%p)\n", 
--                  virt_to_bus(event.dsa), event.dsa);
--          if (event.pid != -1) {
--              printk ("         event for pid %ld ", event.pid);
--              __scsi_print_command (event.cmnd);
--          }
--      }
--    }
--}
+-What: vm_ops.nopage
+-When: February 2008, provided in-kernel callers have been converted
+-Why:  This interface is replaced by vm_ops.fault, but it has been around
+-      forever, is used by a lot of drivers, and doesn't cost much to
+-      maintain.
+-Who:  Nick Piggin <npiggin@suse.de>
 -
--/*
-- * Function: check_address
-- *
-- * Purpose: Check to see if a possibly corrupt pointer will fault the 
-- *    kernel.
-- *
-- * Inputs: addr - address; size - size of area
-- *
-- * Returns: 0 if area is OK, -1 on error.
-- *
-- * NOTES: should be implemented in terms of vverify on kernels 
-- *    that have it.
-- */
+----------------------------
+-
+ What: Interrupt only SA_* flags
+ When: September 2007
+ Why:  The interrupt related SA_* flags are replaced by IRQF_* to move them
+@@ -307,6 +280,25 @@
+ ---------------------------
++What: Multipath cached routing support in ipv4
++When: in 2.6.23
++Why:  Code was merged, then submitter immediately disappeared leaving
++      us with no maintainer and lots of bugs.  The code should not have
++      been merged in the first place, and many aspects of it's
++      implementation are blocking more critical core networking
++      development.  It's marked EXPERIMENTAL and no distribution
++      enables it because it cause obscure crashes due to unfixable bugs
++      (interfaces don't return errors so memory allocation can't be
++      handled, calling contexts of these interfaces make handling
++      errors impossible too because they get called after we've
++      totally commited to creating a route object, for example).
++      This problem has existed for years and no forward progress
++      has ever been made, and nobody steps up to try and salvage
++      this code, so we're going to finally just get rid of it.
++Who:  David S. Miller <davem@davemloft.net>
++
++---------------------------
++
+ What: read_dev_chars(), read_conf_data{,_lpm}() (s390 common I/O layer)
+ When: December 2007
+ Why:  These functions are a leftover from 2.4 times. They have several
+diff -Nurb linux-2.6.22-590/Documentation/filesystems/00-INDEX linux-2.6.22-570/Documentation/filesystems/00-INDEX
+--- linux-2.6.22-590/Documentation/filesystems/00-INDEX        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/filesystems/00-INDEX        2007-07-08 19:32:17.000000000 -0400
+@@ -84,8 +84,6 @@
+       - info and mount options for the UDF filesystem.
+ ufs.txt
+       - info on the ufs filesystem.
+-unionfs/
+-      - info on the unionfs filesystem
+ vfat.txt
+       - info on using the VFAT filesystem used in Windows NT and Windows 95
+ vfs.txt
+diff -Nurb linux-2.6.22-590/Documentation/filesystems/Locking linux-2.6.22-570/Documentation/filesystems/Locking
+--- linux-2.6.22-590/Documentation/filesystems/Locking 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/filesystems/Locking 2007-07-08 19:32:17.000000000 -0400
+@@ -510,14 +510,12 @@
+ prototypes:
+       void (*open)(struct vm_area_struct*);
+       void (*close)(struct vm_area_struct*);
+-      struct page *(*fault)(struct vm_area_struct*, struct fault_data *);
+       struct page *(*nopage)(struct vm_area_struct*, unsigned long, int *);
+ locking rules:
+               BKL     mmap_sem
+ open:         no      yes
+ close:                no      yes
+-fault:                no      yes
+ nopage:               no      yes
+ ================================================================================
+diff -Nurb linux-2.6.22-590/Documentation/filesystems/configfs/configfs.txt linux-2.6.22-570/Documentation/filesystems/configfs/configfs.txt
+--- linux-2.6.22-590/Documentation/filesystems/configfs/configfs.txt   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/filesystems/configfs/configfs.txt   2007-07-08 19:32:17.000000000 -0400
+@@ -238,8 +238,6 @@
+               struct config_group *(*make_group)(struct config_group *group,
+                                                  const char *name);
+               int (*commit_item)(struct config_item *item);
+-              void (*disconnect_notify)(struct config_group *group,
+-                                        struct config_item *item);
+               void (*drop_item)(struct config_group *group,
+                                 struct config_item *item);
+       };
+@@ -270,16 +268,6 @@
+ for the item to actually disappear from the subsystem's usage.  But it
+ is gone from configfs.
+-When drop_item() is called, the item's linkage has already been torn
+-down.  It no longer has a reference on its parent and has no place in
+-the item hierarchy.  If a client needs to do some cleanup before this
+-teardown happens, the subsystem can implement the
+-ct_group_ops->disconnect_notify() method.  The method is called after
+-configfs has removed the item from the filesystem view but before the
+-item is removed from its parent group.  Like drop_item(),
+-disconnect_notify() is void and cannot fail.  Client subsystems should
+-not drop any references here, as they still must do it in drop_item().
 -
--static int 
--check_address (unsigned long addr, int size) {
--    return (virt_to_phys((void *)addr) < PAGE_SIZE || virt_to_phys((void *)(addr + size)) > virt_to_phys(high_memory) ?  -1 : 0);
--}
+ A config_group cannot be removed while it still has child items.  This
+ is implemented in the configfs rmdir(2) code.  ->drop_item() will not be
+ called, as the item has not been dropped.  rmdir(2) will fail, as the
+@@ -398,33 +386,6 @@
+ rmdir(2).  They also are not considered when rmdir(2) on the parent
+ group is checking for children.
+-[Dependant Subsystems]
 -
--#ifdef MODULE
--int 
--NCR53c7x0_release(struct Scsi_Host *host) {
--    struct NCR53c7x0_hostdata *hostdata = 
--      (struct NCR53c7x0_hostdata *) host->hostdata[0];
--    struct NCR53c7x0_cmd *cmd, *tmp;
--    shutdown (host);
--    if (host->irq != SCSI_IRQ_NONE)
--      {
--          int irq_count;
--          struct Scsi_Host *tmp;
--          for (irq_count = 0, tmp = first_host; tmp; tmp = tmp->next)
--              if (tmp->hostt == the_template && tmp->irq == host->irq)
--                  ++irq_count;
--          if (irq_count == 1)
--              free_irq(host->irq, NULL);
--      }
--    if (host->dma_channel != DMA_NONE)
--      free_dma(host->dma_channel);
--    if (host->io_port)
--      release_region(host->io_port, host->n_io_port);
+-Sometimes other drivers depend on particular configfs items.  For
+-example, ocfs2 mounts depend on a heartbeat region item.  If that
+-region item is removed with rmdir(2), the ocfs2 mount must BUG or go
+-readonly.  Not happy.
 -    
--    for (cmd = (struct NCR53c7x0_cmd *) hostdata->free; cmd; cmd = tmp, 
--      --hostdata->num_cmds) {
--      tmp = (struct NCR53c7x0_cmd *) cmd->next;
--    /* 
--     * If we're going to loop, try to stop it to get a more accurate
--     * count of the leaked commands.
--     */
--      cmd->next = NULL;
--      if (cmd->free)
--          cmd->free ((void *) cmd->real, cmd->size);
--    }
--    if (hostdata->num_cmds)
--      printk ("scsi%d : leaked %d NCR53c7x0_cmd structures\n",
--          host->host_no, hostdata->num_cmds);
--
--    vfree(hostdata->events);
--
--    /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
--     * XXX may be invalid (CONFIG_060_WRITETHROUGH)
--     */
--    kernel_set_cachemode((void *)hostdata, 8192, IOMAP_FULL_CACHING);
--    free_pages ((u32)hostdata, 1);
--    return 1;
--}
--#endif /* def MODULE */
-diff -Nurb linux-2.6.22-570/drivers/scsi/53c7xx.h linux-2.6.22-590/drivers/scsi/53c7xx.h
---- linux-2.6.22-570/drivers/scsi/53c7xx.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/53c7xx.h     1969-12-31 19:00:00.000000000 -0500
-@@ -1,1608 +0,0 @@
--/*
-- * 53c710 driver.  Modified from Drew Eckhardts driver
-- * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
-- *
-- * I have left the code for the 53c8xx family in here, because it didn't
-- * seem worth removing it.  The possibility of IO_MAPPED chips rather
-- * than MEMORY_MAPPED remains, in case someone wants to add support for
-- * 53c710 chips on Intel PCs (some older machines have them on the
-- * motherboard).
-- *
-- * NOTE THERE MAY BE PROBLEMS WITH CASTS IN read8 AND Co.
-- */
--
--/*
-- * NCR 53c{7,8}0x0 driver, header file
-- *
-- * Sponsored by
-- *      iX Multiuser Multitasking Magazine
-- *    Hannover, Germany
-- *    hm@ix.de        
-- *
-- * Copyright 1993, 1994, 1995 Drew Eckhardt
-- *      Visionary Computing 
-- *      (Unix and Linux consulting and custom programming)
-- *      drew@PoohSticks.ORG
-- *    +1 (303) 786-7975
-- *
-- * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
-- * 
-- * PRE-ALPHA
-- *
-- * For more information, please consult 
-- *
-- * NCR 53C700/53C700-66
-- * SCSI I/O Processor
-- * Data Manual
-- *
-- * NCR 53C810
-- * PCI-SCSI I/O Processor 
-- * Data Manual
-- *
-- * NCR Microelectronics
-- * 1635 Aeroplaza Drive
-- * Colorado Springs, CO 80916
-- * +1 (719) 578-3400
-- *
-- * Toll free literature number
-- * +1 (800) 334-5454
-- *
-- */
--
--#ifndef NCR53c710_H
--#define NCR53c710_H
--
--#ifndef HOSTS_C
--
--/* SCSI control 0 rw, default = 0xc0 */ 
--#define SCNTL0_REG            0x00    
--#define SCNTL0_ARB1           0x80    /* 0 0 = simple arbitration */
--#define SCNTL0_ARB2           0x40    /* 1 1 = full arbitration */
--#define SCNTL0_STRT           0x20    /* Start Sequence */
--#define SCNTL0_WATN           0x10    /* Select with ATN */
--#define SCNTL0_EPC            0x08    /* Enable parity checking */
--/* Bit 2 is reserved on 800 series chips */
--#define SCNTL0_EPG_700                0x04    /* Enable parity generation */
--#define SCNTL0_AAP            0x02    /*  ATN/ on parity error */
--#define SCNTL0_TRG            0x01    /* Target mode */
--
--/* SCSI control 1 rw, default = 0x00 */
--
--#define SCNTL1_REG            0x01    
--#define SCNTL1_EXC            0x80    /* Extra Clock Cycle of Data setup */
--#define SCNTL1_ADB            0x40    /*  contents of SODL on bus */
--#define SCNTL1_ESR_700                0x20    /* Enable SIOP response to selection 
--                                         and reselection */
--#define SCNTL1_DHP_800                0x20    /* Disable halt on parity error or ATN
--                                         target mode only */
--#define SCNTL1_CON            0x10    /* Connected */
--#define SCNTL1_RST            0x08    /* SCSI RST/ */
--#define SCNTL1_AESP           0x04    /* Force bad parity */
--#define SCNTL1_SND_700                0x02    /* Start SCSI send */
--#define SCNTL1_IARB_800               0x02    /* Immediate Arbitration, start
--                                         arbitration immediately after
--                                         busfree is detected */
--#define SCNTL1_RCV_700                0x01    /* Start SCSI receive */
--#define SCNTL1_SST_800                0x01    /* Start SCSI transfer */
--
--/* SCSI control 2 rw, */
--
--#define SCNTL2_REG_800                0x02    
--#define SCNTL2_800_SDU                0x80    /* SCSI disconnect unexpected */
--
--/* SCSI control 3 rw */
--
--#define SCNTL3_REG_800                0x03    
--#define SCNTL3_800_SCF_SHIFT  4
--#define SCNTL3_800_SCF_MASK   0x70
--#define SCNTL3_800_SCF2               0x40    /* Synchronous divisor */
--#define SCNTL3_800_SCF1               0x20    /* 0x00 = SCLK/3 */
--#define SCNTL3_800_SCF0               0x10    /* 0x10 = SCLK/1 */
--                                      /* 0x20 = SCLK/1.5 
--                                         0x30 = SCLK/2 
--                                         0x40 = SCLK/3 */
--          
--#define SCNTL3_800_CCF_SHIFT  0
--#define SCNTL3_800_CCF_MASK   0x07
--#define SCNTL3_800_CCF2               0x04    /* 0x00 50.01 to 66 */
--#define SCNTL3_800_CCF1               0x02    /* 0x01 16.67 to 25 */
--#define SCNTL3_800_CCF0               0x01    /* 0x02 25.01 - 37.5 
--                                         0x03 37.51 - 50 
--                                         0x04 50.01 - 66 */
--
--/*  
-- * SCSI destination ID rw - the appropriate bit is set for the selected
-- * target ID.  This is written by the SCSI SCRIPTS processor.
-- * default = 0x00
-- */
--#define SDID_REG_700                  0x02    
--#define SDID_REG_800          0x06
--
--#define GP_REG_800            0x07    /* General purpose IO */
--#define GP_800_IO1            0x02
--#define GP_800_IO2            0x01
--
--/* SCSI interrupt enable rw, default = 0x00 */
--#define SIEN_REG_700          0x03    
--#define SIEN0_REG_800         0x40
--#define SIEN_MA                       0x80    /* Phase mismatch (ini) or ATN (tgt) */
--#define SIEN_FC                       0x40    /* Function complete */
--#define SIEN_700_STO          0x20    /* Selection or reselection timeout */
--#define SIEN_800_SEL          0x20    /* Selected */
--#define SIEN_700_SEL          0x10    /* Selected or reselected */
--#define SIEN_800_RESEL                0x10    /* Reselected */
--#define SIEN_SGE              0x08    /* SCSI gross error */
--#define SIEN_UDC              0x04    /* Unexpected disconnect */
--#define SIEN_RST              0x02    /* SCSI RST/ received */
--#define SIEN_PAR              0x01    /* Parity error */
--
--/* 
-- * SCSI chip ID rw
-- * NCR53c700 : 
-- *    When arbitrating, the highest bit is used, when reselection or selection
-- *    occurs, the chip responds to all IDs for which a bit is set.
-- *    default = 0x00 
-- * NCR53c810 : 
-- *    Uses bit mapping
-- */
--#define SCID_REG              0x04    
--/* Bit 7 is reserved on 800 series chips */
--#define SCID_800_RRE          0x40    /* Enable response to reselection */
--#define SCID_800_SRE          0x20    /* Enable response to selection */
--/* Bits four and three are reserved on 800 series chips */
--#define SCID_800_ENC_MASK     0x07    /* Encoded SCSI ID */
--
--/* SCSI transfer rw, default = 0x00 */
--#define SXFER_REG             0x05
--#define SXFER_DHP             0x80    /* Disable halt on parity */
--
--#define SXFER_TP2             0x40    /* Transfer period msb */
--#define SXFER_TP1             0x20
--#define SXFER_TP0             0x10    /* lsb */
--#define SXFER_TP_MASK         0x70
--/* FIXME : SXFER_TP_SHIFT == 5 is right for '8xx chips */
--#define SXFER_TP_SHIFT                5
--#define SXFER_TP_4            0x00    /* Divisors */
--#define SXFER_TP_5            0x10<<1
--#define SXFER_TP_6            0x20<<1
--#define SXFER_TP_7            0x30<<1
--#define SXFER_TP_8            0x40<<1
--#define SXFER_TP_9            0x50<<1
--#define SXFER_TP_10           0x60<<1
--#define SXFER_TP_11           0x70<<1
--
--#define SXFER_MO3             0x08    /* Max offset msb */
--#define SXFER_MO2             0x04
--#define SXFER_MO1             0x02
--#define SXFER_MO0             0x01    /* lsb */
--#define SXFER_MO_MASK         0x0f
--#define SXFER_MO_SHIFT                0
--
--/* 
-- * SCSI output data latch rw
-- * The contents of this register are driven onto the SCSI bus when 
-- * the Assert Data Bus bit of the SCNTL1 register is set and 
-- * the CD, IO, and MSG bits of the SOCL register match the SCSI phase
-- */
--#define SODL_REG_700          0x06    
--#define SODL_REG_800          0x54
--
--
--/* 
-- * SCSI output control latch rw, default = 0 
-- * Note that when the chip is being manually programmed as an initiator,
-- * the MSG, CD, and IO bits must be set correctly for the phase the target
-- * is driving the bus in.  Otherwise no data transfer will occur due to 
-- * phase mismatch.
-- */
--
--#define SOCL_REG              0x07
--#define SOCL_REQ              0x80    /*  REQ */
--#define SOCL_ACK              0x40    /*  ACK */
--#define SOCL_BSY              0x20    /*  BSY */
--#define SOCL_SEL              0x10    /*  SEL */
--#define SOCL_ATN              0x08    /*  ATN */
--#define SOCL_MSG              0x04    /*  MSG */
--#define SOCL_CD                       0x02    /*  C/D */
--#define SOCL_IO                       0x01    /*  I/O */
--
--/* 
-- * SCSI first byte received latch ro 
-- * This register contains the first byte received during a block MOVE 
-- * SCSI SCRIPTS instruction, including
-- * 
-- * Initiator mode     Target mode
-- * Message in         Command
-- * Status             Message out
-- * Data in            Data out
-- *
-- * It also contains the selecting or reselecting device's ID and our 
-- * ID.
-- *
-- * Note that this is the register the various IF conditionals can 
-- * operate on.
-- */
--#define SFBR_REG              0x08    
--
--/* 
-- * SCSI input data latch ro
-- * In initiator mode, data is latched into this register on the rising
-- * edge of REQ/. In target mode, data is latched on the rising edge of 
-- * ACK/
-- */
--#define SIDL_REG_700          0x09
--#define SIDL_REG_800          0x50
--
--/* 
-- * SCSI bus data lines ro 
-- * This register reflects the instantaneous status of the SCSI data 
-- * lines.  Note that SCNTL0 must be set to disable parity checking, 
-- * otherwise reading this register will latch new parity.
-- */
--#define SBDL_REG_700          0x0a
--#define SBDL_REG_800          0x58
--
--#define SSID_REG_800          0x0a
--#define SSID_800_VAL          0x80    /* Exactly two bits asserted at sel */
--#define SSID_800_ENCID_MASK   0x07    /* Device which performed operation */
+-configfs provides two additional API calls: configfs_depend_item() and
+-configfs_undepend_item().  A client driver can call
+-configfs_depend_item() on an existing item to tell configfs that it is
+-depended on.  configfs will then return -EBUSY from rmdir(2) for that
+-item.  When the item is no longer depended on, the client driver calls
+-configfs_undepend_item() on it.
+-
+-These API cannot be called underneath any configfs callbacks, as
+-they will conflict.  They can block and allocate.  A client driver
+-probably shouldn't calling them of its own gumption.  Rather it should
+-be providing an API that external subsystems call.
+-
+-How does this work?  Imagine the ocfs2 mount process.  When it mounts,
+-it asks for a heartbeat region item.  This is done via a call into the
+-heartbeat code.  Inside the heartbeat code, the region item is looked
+-up.  Here, the heartbeat code calls configfs_depend_item().  If it
+-succeeds, then heartbeat knows the region is safe to give to ocfs2.
+-If it fails, it was being torn down anyway, and heartbeat can gracefully
+-pass up an error.
 -
+ [Committable Items]
+ NOTE: Committable items are currently unimplemented.
+diff -Nurb linux-2.6.22-590/Documentation/filesystems/unionfs/00-INDEX linux-2.6.22-570/Documentation/filesystems/unionfs/00-INDEX
+--- linux-2.6.22-590/Documentation/filesystems/unionfs/00-INDEX        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/filesystems/unionfs/00-INDEX        1969-12-31 19:00:00.000000000 -0500
+@@ -1,10 +0,0 @@
+-00-INDEX
+-      - this file.
+-concepts.txt
+-      - A brief introduction of concepts.
+-issues.txt
+-      - A summary of known issues with unionfs.
+-rename.txt
+-      - Information regarding rename operations.
+-usage.txt
+-      - Usage information and examples.
+diff -Nurb linux-2.6.22-590/Documentation/filesystems/unionfs/concepts.txt linux-2.6.22-570/Documentation/filesystems/unionfs/concepts.txt
+--- linux-2.6.22-590/Documentation/filesystems/unionfs/concepts.txt    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/filesystems/unionfs/concepts.txt    1969-12-31 19:00:00.000000000 -0500
+@@ -1,75 +0,0 @@
+-Unionfs 2.0 CONCEPTS:
+-=====================
+-
+-This file describes the concepts needed by a namespace unification file
+-system.
 -
--/* 
-- * SCSI bus control lines rw, 
-- * instantaneous readout of control lines 
-- */
--#define SBCL_REG              0x0b    
--#define SBCL_REQ              0x80    /*  REQ ro */
--#define SBCL_ACK              0x40    /*  ACK ro */
--#define SBCL_BSY              0x20    /*  BSY ro */
--#define SBCL_SEL              0x10    /*  SEL ro */
--#define SBCL_ATN              0x08    /*  ATN ro */
--#define SBCL_MSG              0x04    /*  MSG ro */
--#define SBCL_CD                       0x02    /*  C/D ro */
--#define SBCL_IO                       0x01    /*  I/O ro */
--#define SBCL_PHASE_CMDOUT     SBCL_CD
--#define SBCL_PHASE_DATAIN     SBCL_IO
--#define SBCL_PHASE_DATAOUT    0
--#define SBCL_PHASE_MSGIN      (SBCL_CD|SBCL_IO|SBCL_MSG)
--#define SBCL_PHASE_MSGOUT     (SBCL_CD|SBCL_MSG)
--#define SBCL_PHASE_STATIN     (SBCL_CD|SBCL_IO)
--#define SBCL_PHASE_MASK               (SBCL_CD|SBCL_IO|SBCL_MSG)
--/* 
-- * Synchronous SCSI Clock Control bits 
-- * 0 - set by DCNTL 
-- * 1 - SCLK / 1.0
-- * 2 - SCLK / 1.5
-- * 3 - SCLK / 2.0 
-- */
--#define SBCL_SSCF1            0x02    /* wo, -66 only */
--#define SBCL_SSCF0            0x01    /* wo, -66 only */
--#define SBCL_SSCF_MASK                0x03
+-Branch Priority:
+-================
 -
--/* 
-- * XXX note : when reading the DSTAT and STAT registers to clear interrupts,
-- * insure that 10 clocks elapse between the two  
-- */
--/* DMA status ro */
--#define DSTAT_REG             0x0c    
--#define DSTAT_DFE             0x80    /* DMA FIFO empty */
--#define DSTAT_800_MDPE                0x40    /* Master Data Parity Error */
--#define DSTAT_800_BF          0x20    /* Bus Fault */
--#define DSTAT_ABRT            0x10    /* Aborted - set on error */
--#define DSTAT_SSI             0x08    /* SCRIPTS single step interrupt */
--#define DSTAT_SIR             0x04    /* SCRIPTS interrupt received - 
--                                         set when INT instruction is 
--                                         executed */
--#define DSTAT_WTD             0x02    /* Watchdog timeout detected */
--#define DSTAT_OPC             0x01    /* Illegal instruction */
--#define DSTAT_800_IID         0x01    /* Same thing, different name */
--
--
--/* NCR53c800 moves this stuff into SIST0 */
--#define SSTAT0_REG            0x0d    /* SCSI status 0 ro */
--#define SIST0_REG_800         0x42    
--#define SSTAT0_MA             0x80    /* ini : phase mismatch,
--                                       * tgt : ATN/ asserted 
--                                       */
--#define SSTAT0_CMP            0x40    /* function complete */
--#define SSTAT0_700_STO                0x20    /* Selection or reselection timeout */
--#define SIST0_800_SEL         0x20    /* Selected */
--#define SSTAT0_700_SEL                0x10    /* Selected or reselected */
--#define SIST0_800_RSL         0x10    /* Reselected */
--#define SSTAT0_SGE            0x08    /* SCSI gross error */
--#define SSTAT0_UDC            0x04    /* Unexpected disconnect */
--#define SSTAT0_RST            0x02    /* SCSI RST/ received */
--#define SSTAT0_PAR            0x01    /* Parity error */
--
--/* And uses SSTAT0 for what was SSTAT1 */
--
--#define SSTAT1_REG            0x0e    /* SCSI status 1 ro */
--#define SSTAT1_ILF            0x80    /* SIDL full */
--#define SSTAT1_ORF            0x40    /* SODR full */
--#define SSTAT1_OLF            0x20    /* SODL full */
--#define SSTAT1_AIP            0x10    /* Arbitration in progress */
--#define SSTAT1_LOA            0x08    /* Lost arbitration */
--#define SSTAT1_WOA            0x04    /* Won arbitration */
--#define SSTAT1_RST            0x02    /* Instant readout of RST/ */
--#define SSTAT1_SDP            0x01    /* Instant readout of SDP/ */
--
--#define SSTAT2_REG            0x0f    /* SCSI status 2 ro */
--#define SSTAT2_FF3            0x80    /* number of bytes in synchronous */
--#define SSTAT2_FF2            0x40    /* data FIFO */
--#define SSTAT2_FF1            0x20    
--#define SSTAT2_FF0            0x10
--#define SSTAT2_FF_MASK                0xf0
--#define SSTAT2_FF_SHIFT               4
+-Each branch is assigned a unique priority - starting from 0 (highest
+-priority).  No two branches can have the same priority.
 -
--/* 
-- * Latched signals, latched on the leading edge of REQ/ for initiators,
-- * ACK/ for targets.
-- */
--#define SSTAT2_SDP            0x08    /* SDP */
--#define SSTAT2_MSG            0x04    /* MSG */
--#define SSTAT2_CD             0x02    /* C/D */
--#define SSTAT2_IO             0x01    /* I/O */
--#define SSTAT2_PHASE_CMDOUT   SSTAT2_CD
--#define SSTAT2_PHASE_DATAIN   SSTAT2_IO
--#define SSTAT2_PHASE_DATAOUT  0
--#define SSTAT2_PHASE_MSGIN    (SSTAT2_CD|SSTAT2_IO|SSTAT2_MSG)
--#define SSTAT2_PHASE_MSGOUT   (SSTAT2_CD|SSTAT2_MSG)
--#define SSTAT2_PHASE_STATIN   (SSTAT2_CD|SSTAT2_IO)
--#define SSTAT2_PHASE_MASK     (SSTAT2_CD|SSTAT2_IO|SSTAT2_MSG)
--
--
--/* NCR53c700-66 only */
--#define SCRATCHA_REG_00               0x10    /* through  0x13 Scratch A rw */
--/* NCR53c710 and higher */
--#define DSA_REG                       0x10    /* DATA structure address */
--
--#define CTEST0_REG_700                0x14    /* Chip test 0 ro */
--#define CTEST0_REG_800                0x18    /* Chip test 0 rw, general purpose */
--/* 0x80 - 0x04 are reserved */
--#define CTEST0_700_RTRG               0x02    /* Real target mode */
--#define CTEST0_700_DDIR               0x01    /* Data direction, 1 = 
--                                       * SCSI bus to host, 0  =
--                                       * host to SCSI.
--                                       */
 -
--#define CTEST1_REG_700                0x15    /* Chip test 1 ro */
--#define CTEST1_REG_800                0x19    /* Chip test 1 ro */
--#define CTEST1_FMT3           0x80    /* Identify which byte lanes are empty */
--#define CTEST1_FMT2           0x40    /* in the DMA FIFO */
--#define CTEST1_FMT1           0x20
--#define CTEST1_FMT0           0x10
--
--#define CTEST1_FFL3           0x08    /* Identify which bytes lanes are full */
--#define CTEST1_FFL2           0x04    /* in the DMA FIFO */
--#define CTEST1_FFL1           0x02
--#define CTEST1_FFL0           0x01
--
--#define CTEST2_REG_700                0x16    /* Chip test 2 ro */
--#define CTEST2_REG_800                0x1a    /* Chip test 2 ro */
--
--#define CTEST2_800_DDIR               0x80    /* 1 = SCSI->host */
--#define CTEST2_800_SIGP               0x40    /* A copy of SIGP in ISTAT.
--                                         Reading this register clears */
--#define CTEST2_800_CIO                0x20    /* Configured as IO */.
--#define CTEST2_800_CM         0x10    /* Configured as memory */
--
--/* 0x80 - 0x40 are reserved on 700 series chips */
--#define CTEST2_700_SOFF               0x20    /* SCSI Offset Compare,
--                                       * As an initiator, this bit is 
--                                       * one when the synchronous offset
--                                       * is zero, as a target this bit 
--                                       * is one when the synchronous 
--                                       * offset is at the maximum
--                                       * defined in SXFER
--                                       */
--#define CTEST2_700_SFP                0x10    /* SCSI FIFO parity bit,
--                                       * reading CTEST3 unloads a byte
--                                       * from the FIFO and sets this
--                                       */
--#define CTEST2_700_DFP                0x08    /* DMA FIFO parity bit,
--                                       * reading CTEST6 unloads a byte
--                                       * from the FIFO and sets this
--                                       */
--#define CTEST2_TEOP           0x04    /* SCSI true end of process,
--                                       * indicates a totally finished
--                                       * transfer
--                                       */
--#define CTEST2_DREQ           0x02    /* Data request signal */
--/* 0x01 is reserved on 700 series chips */
--#define CTEST2_800_DACK               0x01    
+-Branch Mode:
+-============
 -
--/* 
-- * Chip test 3 ro 
-- * Unloads the bottom byte of the eight deep SCSI synchronous FIFO,
-- * check SSTAT2 FIFO full bits to determine size.  Note that a GROSS
-- * error results if a read is attempted on this register.  Also note 
-- * that 16 and 32 bit reads of this register will cause corruption.
-- */
--#define CTEST3_REG_700                0x17    
--/*  Chip test 3 rw */
--#define CTEST3_REG_800                0x1b
--#define CTEST3_800_V3         0x80    /* Chip revision */
--#define CTEST3_800_V2         0x40
--#define CTEST3_800_V1         0x20
--#define CTEST3_800_V0         0x10
--#define CTEST3_800_FLF                0x08    /* Flush DMA FIFO */
--#define CTEST3_800_CLF                0x04    /* Clear DMA FIFO */
--#define CTEST3_800_FM         0x02    /* Fetch mode pin */
--/* bit 0 is reserved on 800 series chips */
--
--#define CTEST4_REG_700                0x18    /* Chip test 4 rw */
--#define CTEST4_REG_800                0x21    /* Chip test 4 rw */
--/* 0x80 is reserved on 700 series chips */
--#define CTEST4_800_BDIS               0x80    /* Burst mode disable */
--#define CTEST4_ZMOD           0x40    /* High impedance mode */
--#define CTEST4_SZM            0x20    /* SCSI bus high impedance */
--#define CTEST4_700_SLBE               0x10    /* SCSI loopback enabled */
--#define CTEST4_800_SRTM               0x10    /* Shadow Register Test Mode */
--#define CTEST4_700_SFWR               0x08    /* SCSI FIFO write enable, 
--                                       * redirects writes from SODL
--                                       * to the SCSI FIFO.
--                                       */
--#define CTEST4_800_MPEE               0x08    /* Enable parity checking
--                                         during master cycles on PCI
--                                         bus */
+-Each branch is assigned a mode - read-write or read-only. This allows
+-directories on media mounted read-write to be used in a read-only manner.
 -
--/* 
-- * These bits send the contents of the CTEST6 register to the appropriate
-- * byte lane of the 32 bit DMA FIFO.  Normal operation is zero, otherwise 
-- * the high bit means the low two bits select the byte lane.
-- */
--#define CTEST4_FBL2           0x04    
--#define CTEST4_FBL1           0x02
--#define CTEST4_FBL0           0x01    
--#define CTEST4_FBL_MASK               0x07
--#define CTEST4_FBL_0          0x04    /* Select DMA FIFO byte lane 0 */
--#define CTEST4_FBL_1          0x05    /* Select DMA FIFO byte lane 1 */
--#define CTEST4_FBL_2          0x06    /* Select DMA FIFO byte lane 2 */
--#define CTEST4_FBL_3          0x07    /* Select DMA FIFO byte lane 3 */
--#define CTEST4_800_SAVE               (CTEST4_800_BDIS)
--
--
--#define CTEST5_REG_700                0x19    /* Chip test 5 rw */
--#define CTEST5_REG_800                0x22    /* Chip test 5 rw */
--/* 
-- * Clock Address Incrementor.  When set, it increments the 
-- * DNAD register to the next bus size boundary.  It automatically 
-- * resets itself when the operation is complete.
-- */
--#define CTEST5_ADCK           0x80
--/*
-- * Clock Byte Counter.  When set, it decrements the DBC register to
-- * the next bus size boundary.
-- */
--#define CTEST5_BBCK           0x40
--/*
-- * Reset SCSI Offset.  Setting this bit to 1 clears the current offset
-- * pointer in the SCSI synchronous offset counter (SSTAT).  This bit
-- * is set to 1 if a SCSI Gross Error Condition occurs.  The offset should
-- * be cleared when a synchronous transfer fails.  When written, it is 
-- * automatically cleared after the SCSI synchronous offset counter is 
-- * reset.
-- */
--/* Bit 5 is reserved on 800 series chips */
--#define CTEST5_700_ROFF               0x20
--/* 
-- * Master Control for Set or Reset pulses. When 1, causes the low 
-- * four bits of register to set when set, 0 causes the low bits to
-- * clear when set.
-- */
--#define CTEST5_MASR           0x10    
--#define CTEST5_DDIR           0x08    /* DMA direction */
--/*
-- * Bits 2-0 are reserved on 800 series chips
-- */
--#define CTEST5_700_EOP                0x04    /* End of process */
--#define CTEST5_700_DREQ               0x02    /* Data request */
--#define CTEST5_700_DACK               0x01    /* Data acknowledge */
 -
--/* 
-- * Chip test 6 rw - writing to this register writes to the byte 
-- * lane in the DMA FIFO as determined by the FBL bits in the CTEST4
-- * register.
-- */
--#define CTEST6_REG_700                0x1a
--#define CTEST6_REG_800                0x23
--
--#define CTEST7_REG            0x1b    /* Chip test 7 rw */
--/* 0x80 - 0x40 are reserved on NCR53c700 and NCR53c700-66 chips */
--#define CTEST7_10_CDIS                0x80    /* Cache burst disable */
--#define CTEST7_10_SC1         0x40    /* Snoop control bits */
--#define CTEST7_10_SC0         0x20    
--#define CTEST7_10_SC_MASK     0x60
--/* 0x20 is reserved on the NCR53c700 */
--#define CTEST7_0060_FM                0x20    /* Fetch mode */
--#define CTEST7_STD            0x10    /* Selection timeout disable */
--#define CTEST7_DFP            0x08    /* DMA FIFO parity bit for CTEST6 */
--#define CTEST7_EVP            0x04    /* 1 = host bus even parity, 0 = odd */
--#define CTEST7_10_TT1         0x02    /* Transfer type */
--#define CTEST7_00_DC          0x02    /* Set to drive DC low during instruction 
--                                         fetch */
--#define CTEST7_DIFF           0x01    /* Differential mode */
--
--#define CTEST7_SAVE ( CTEST7_EVP | CTEST7_DIFF )
--
--
--#define TEMP_REG              0x1c    /* through 0x1f Temporary stack rw */
--
--#define DFIFO_REG             0x20    /* DMA FIFO rw */
--/* 
-- * 0x80 is reserved on the NCR53c710, the CLF and FLF bits have been
-- * moved into the CTEST8 register.
-- */
--#define DFIFO_00_FLF          0x80    /* Flush DMA FIFO to memory */
--#define DFIFO_00_CLF          0x40    /* Clear DMA and SCSI FIFOs */
--#define DFIFO_BO6             0x40
--#define DFIFO_BO5             0x20
--#define DFIFO_BO4             0x10
--#define DFIFO_BO3             0x08
--#define DFIFO_BO2             0x04 
--#define DFIFO_BO1             0x02
--#define DFIFO_BO0             0x01
--#define DFIFO_10_BO_MASK      0x7f    /* 7 bit counter */
--#define DFIFO_00_BO_MASK      0x3f    /* 6 bit counter */
+-Whiteouts:
+-==========
 -
--/* 
-- * Interrupt status rw 
-- * Note that this is the only register which can be read while SCSI
-- * SCRIPTS are being executed.
-- */
--#define ISTAT_REG_700         0x21
--#define ISTAT_REG_800         0x14
--#define ISTAT_ABRT            0x80    /* Software abort, write 
--                                       *1 to abort, wait for interrupt. */
--/* 0x40 and 0x20 are reserved on NCR53c700 and NCR53c700-66 chips */
--#define ISTAT_10_SRST         0x40    /* software reset */
--#define ISTAT_10_SIGP         0x20    /* signal script */
--/* 0x10 is reserved on NCR53c700 series chips */
--#define ISTAT_800_SEM         0x10    /* semaphore */
--#define ISTAT_CON             0x08    /* 1 when connected */
--#define ISTAT_800_INTF                0x04    /* Interrupt on the fly */
--#define ISTAT_700_PRE         0x04    /* Pointer register empty.
--                                       * Set to 1 when DSPS and DSP
--                                       * registers are empty in pipeline
--                                       * mode, always set otherwise.
--                                       */
--#define ISTAT_SIP             0x02    /* SCSI interrupt pending from
--                                       * SCSI portion of SIOP see
--                                       * SSTAT0
--                                       */
--#define ISTAT_DIP             0x01    /* DMA interrupt pending 
--                                       * see DSTAT
--                                       */
+-A whiteout removes a file name from the namespace. Whiteouts are needed when
+-one attempts to remove a file on a read-only branch.
 -
--/* NCR53c700-66 and NCR53c710 only */
--#define CTEST8_REG            0x22    /* Chip test 8 rw */
--#define CTEST8_0066_EAS               0x80    /* Enable alternate SCSI clock,
--                                       * ie read from SCLK/ rather than CLK/
--                                       */
--#define CTEST8_0066_EFM               0x40    /* Enable fetch and master outputs */
--#define CTEST8_0066_GRP               0x20    /* Generate Receive Parity for 
--                                       * pass through.  This insures that 
--                                       * bad parity won't reach the host 
--                                       * bus.
--                                       */
--#define CTEST8_0066_TE                0x10    /* TolerANT enable.  Enable 
--                                       * active negation, should only
--                                       * be used for slow SCSI 
--                                       * non-differential.
--                                       */
--#define CTEST8_0066_HSC               0x08    /* Halt SCSI clock */
--#define CTEST8_0066_SRA               0x04    /* Shorten REQ/ACK filtering,
--                                       * must be set for fast SCSI-II
--                                       * speeds.
--                                       */
--#define CTEST8_0066_DAS               0x02    /* Disable automatic target/initiator
--                                       * switching.
--                                       */
--#define CTEST8_0066_LDE               0x01    /* Last disconnect enable.
--                                       * The status of pending 
--                                       * disconnect is maintained by
--                                       * the core, eliminating
--                                       * the possibility of missing a 
--                                       * selection or reselection
--                                       * while waiting to fetch a 
--                                       * WAIT DISCONNECT opcode.
--                                       */
+-Suppose we have a two-branch union, where branch 0 is read-write and branch
+-1 is read-only. And a file 'foo' on branch 1:
 -
--#define CTEST8_10_V3          0x80    /* Chip revision */
--#define CTEST8_10_V2          0x40
--#define CTEST8_10_V1          0x20    
--#define CTEST8_10_V0          0x10
--#define CTEST8_10_V_MASK      0xf0    
--#define CTEST8_10_FLF         0x08    /* Flush FIFOs */
--#define CTEST8_10_CLF         0x04    /* Clear FIFOs */
--#define CTEST8_10_FM          0x02    /* Fetch pin mode */
--#define CTEST8_10_SM          0x01    /* Snoop pin mode */
+-./b0/
+-./b1/
+-./b1/foo
 -
+-The unified view would simply be:
 -
--/* 
-- * The CTEST9 register may be used to differentiate between a
-- * NCR53c700 and a NCR53c710.  
-- *
-- * Write 0xff to this register.
-- * Read it.
-- * If the contents are 0xff, it is a NCR53c700
-- * If the contents are 0x00, it is a NCR53c700-66 first revision
-- * If the contents are some other value, it is some other NCR53c700-66
-- */
--#define CTEST9_REG_00         0x23    /* Chip test 9 ro */
--#define LCRC_REG_10           0x23    
+-./union/
+-./union/foo
 -
--/*
-- * 0x24 through 0x27 are the DMA byte counter register.  Instructions
-- * write their high 8 bits into the DCMD register, the low 24 bits into
-- * the DBC register.
-- *
-- * Function is dependent on the command type being executed.
-- */
+-Since 'foo' is stored on a read-only branch, it cannot be removed. A
+-whiteout is used to remove the name 'foo' from the unified namespace. Again,
+-since branch 1 is read-only, the whiteout cannot be created there. So, we
+-try on a higher priority (lower numerically) branch and create the whiteout
+-there.
 -
-- 
--#define DBC_REG                       0x24
--/* 
-- * For Block Move Instructions, DBC is a 24 bit quantity representing 
-- *     the number of bytes to transfer.
-- * For Transfer Control Instructions, DBC is bit fielded as follows : 
-- */
--/* Bits 20 - 23 should be clear */
--#define DBC_TCI_TRUE          (1 << 19)       /* Jump when true */
--#define DBC_TCI_COMPARE_DATA  (1 << 18)       /* Compare data */
--#define DBC_TCI_COMPARE_PHASE (1 << 17)       /* Compare phase with DCMD field */
--#define DBC_TCI_WAIT_FOR_VALID        (1 << 16)       /* Wait for REQ */
--/* Bits 8 - 15 are reserved on some implementations ? */
--#define DBC_TCI_MASK_MASK     0xff00          /* Mask for data compare */
--#define DBC_TCI_MASK_SHIFT    8
--#define DBC_TCI_DATA_MASK     0xff            /* Data to be compared */ 
--#define DBC_TCI_DATA_SHIFT    0
--
--#define DBC_RWRI_IMMEDIATE_MASK       0xff00          /* Immediate data */
--#define DBC_RWRI_IMMEDIATE_SHIFT 8            /* Amount to shift */
--#define DBC_RWRI_ADDRESS_MASK 0x3f0000        /* Register address */
--#define DBC_RWRI_ADDRESS_SHIFT        16
+-./b0/
+-./b0/.wh.foo
+-./b1/
+-./b1/foo
 -
+-Later, when Unionfs traverses branches (due to lookup or readdir), it
+-eliminate 'foo' from the namespace (as well as the whiteout itself.)
 -
--/*
-- * DMA command r/w
-- */
--#define DCMD_REG              0x27    
--#define DCMD_TYPE_MASK                0xc0    /* Masks off type */
--#define DCMD_TYPE_BMI         0x00    /* Indicates a Block Move instruction */
--#define DCMD_BMI_IO           0x01    /* I/O, CD, and MSG bits selecting   */
--#define DCMD_BMI_CD           0x02    /* the phase for the block MOVE      */
--#define DCMD_BMI_MSG          0x04    /* instruction                       */
--
--#define DCMD_BMI_OP_MASK      0x18    /* mask for opcode */
--#define DCMD_BMI_OP_MOVE_T    0x00    /* MOVE */
--#define DCMD_BMI_OP_MOVE_I    0x08    /* MOVE Initiator */
--
--#define DCMD_BMI_INDIRECT     0x20    /*  Indirect addressing */
--
--#define DCMD_TYPE_TCI         0x80    /* Indicates a Transfer Control 
--                                         instruction */
--#define DCMD_TCI_IO           0x01    /* I/O, CD, and MSG bits selecting   */
--#define DCMD_TCI_CD           0x02    /* the phase for the block MOVE      */
--#define DCMD_TCI_MSG          0x04    /* instruction                       */
--#define DCMD_TCI_OP_MASK      0x38    /* mask for opcode */
--#define DCMD_TCI_OP_JUMP      0x00    /* JUMP */
--#define DCMD_TCI_OP_CALL      0x08    /* CALL */
--#define DCMD_TCI_OP_RETURN    0x10    /* RETURN */
--#define DCMD_TCI_OP_INT               0x18    /* INT */
--
--#define DCMD_TYPE_RWRI                0x40    /* Indicates I/O or register Read/Write
--                                         instruction */
--#define DCMD_RWRI_OPC_MASK    0x38    /* Opcode mask */
--#define DCMD_RWRI_OPC_WRITE   0x28    /* Write SFBR to register */
--#define DCMD_RWRI_OPC_READ    0x30    /* Read register to SFBR */
--#define DCMD_RWRI_OPC_MODIFY  0x38    /* Modify in place */
--
--#define DCMD_RWRI_OP_MASK     0x07
--#define DCMD_RWRI_OP_MOVE     0x00
--#define DCMD_RWRI_OP_SHL      0x01
--#define DCMD_RWRI_OP_OR               0x02
--#define DCMD_RWRI_OP_XOR      0x03
--#define DCMD_RWRI_OP_AND      0x04
--#define DCMD_RWRI_OP_SHR      0x05
--#define DCMD_RWRI_OP_ADD      0x06
--#define DCMD_RWRI_OP_ADDC     0x07
--
--#define DCMD_TYPE_MMI         0xc0    /* Indicates a Memory Move instruction 
--                                         (three words) */
--
--
--#define DNAD_REG              0x28    /* through 0x2b DMA next address for 
--                                         data */
--#define DSP_REG                       0x2c    /* through 0x2f DMA SCRIPTS pointer rw */
--#define DSPS_REG              0x30    /* through 0x33 DMA SCRIPTS pointer 
--                                         save rw */
--#define DMODE_REG_00          0x34    /* DMA mode rw */
--#define DMODE_00_BL1  0x80    /* Burst length bits */
--#define DMODE_00_BL0  0x40
--#define DMODE_BL_MASK 0xc0
--/* Burst lengths (800) */
--#define DMODE_BL_2    0x00    /* 2 transfer */
--#define DMODE_BL_4    0x40    /* 4 transfers */
--#define DMODE_BL_8    0x80    /* 8 transfers */
--#define DMODE_BL_16   0xc0    /* 16 transfers */
--
--#define DMODE_10_BL_1 0x00    /* 1 transfer */
--#define DMODE_10_BL_2 0x40    /* 2 transfers */
--#define DMODE_10_BL_4 0x80    /* 4 transfers */
--#define DMODE_10_BL_8 0xc0    /* 8 transfers */
--#define DMODE_10_FC2  0x20    /* Driven to FC2 pin */
--#define DMODE_10_FC1  0x10    /* Driven to FC1 pin */
--#define DMODE_710_PD  0x08    /* Program/data on FC0 pin */
--#define DMODE_710_UO  0x02    /* User prog. output */
--
--#define DMODE_700_BW16        0x20    /* Host buswidth = 16 */
--#define DMODE_700_286 0x10    /* 286 mode */
--#define DMODE_700_IOM 0x08    /* Transfer to IO port */
--#define DMODE_700_FAM 0x04    /* Fixed address mode */
--#define DMODE_700_PIPE        0x02    /* Pipeline mode disables 
--                                       * automatic fetch / exec 
--                                       */
--#define DMODE_MAN     0x01            /* Manual start mode, 
--                                       * requires a 1 to be written
--                                       * to the start DMA bit in the DCNTL
--                                       * register to run scripts 
--                                       */
 -
--#define DMODE_700_SAVE ( DMODE_00_BL_MASK | DMODE_00_BW16 | DMODE_00_286 )
--
--/* NCR53c800 series only */
--#define SCRATCHA_REG_800      0x34    /* through 0x37 Scratch A rw */
--/* NCR53c710 only */
--#define SCRATCHB_REG_10               0x34    /* through 0x37 scratch B rw */
--
--#define DMODE_REG_10          0x38    /* DMA mode rw, NCR53c710 and newer */
--#define DMODE_800_SIOM                0x20    /* Source IO = 1 */
--#define DMODE_800_DIOM                0x10    /* Destination IO = 1 */
--#define DMODE_800_ERL         0x08    /* Enable Read Line */
--
--/* 35-38 are reserved on 700 and 700-66 series chips */
--#define DIEN_REG              0x39    /* DMA interrupt enable rw */
--/* 0x80, 0x40, and 0x20 are reserved on 700-series chips */
--#define DIEN_800_MDPE         0x40    /* Master data parity error */
--#define DIEN_800_BF           0x20    /* BUS fault */
--#define DIEN_700_BF           0x20    /* BUS fault */
--#define DIEN_ABRT             0x10    /* Enable aborted interrupt */
--#define DIEN_SSI              0x08    /* Enable single step interrupt */
--#define DIEN_SIR              0x04    /* Enable SCRIPTS INT command 
--                                       * interrupt
--                                       */
--/* 0x02 is reserved on 800 series chips */
--#define DIEN_700_WTD          0x02    /* Enable watchdog timeout interrupt */
--#define DIEN_700_OPC          0x01    /* Enable illegal instruction 
--                                       * interrupt 
--                                       */
--#define DIEN_800_IID          0x01    /*  Same meaning, different name */ 
+-Duplicate Elimination:
+-======================
 -
--/*
-- * DMA watchdog timer rw
-- * set in 16 CLK input periods.
-- */
--#define DWT_REG                       0x3a
--
--/* DMA control rw */
--#define DCNTL_REG             0x3b
--#define DCNTL_700_CF1         0x80    /* Clock divisor bits */
--#define DCNTL_700_CF0         0x40
--#define DCNTL_700_CF_MASK     0xc0
--/* Clock divisors                        Divisor SCLK range (MHZ) */
--#define DCNTL_700_CF_2                0x00    /* 2.0     37.51-50.00 */
--#define DCNTL_700_CF_1_5      0x40    /* 1.5     25.01-37.50 */
--#define DCNTL_700_CF_1                0x80    /* 1.0     16.67-25.00 */
--#define DCNTL_700_CF_3                0xc0    /* 3.0     50.01-66.67 (53c700-66) */
--
--#define DCNTL_700_S16         0x20    /* Load scripts 16 bits at a time */
--#define DCNTL_SSM             0x10    /* Single step mode */
--#define DCNTL_700_LLM         0x08    /* Low level mode, can only be set 
--                                       * after selection */
--#define DCNTL_800_IRQM                0x08    /* Totem pole IRQ pin */
--#define DCNTL_STD             0x04    /* Start DMA / SCRIPTS */
--/* 0x02 is reserved */
--#define DCNTL_00_RST          0x01    /* Software reset, resets everything
--                                       * but 286 mode bit  in DMODE. On the
--                                       * NCR53c710, this bit moved to CTEST8
--                                       */
--#define DCNTL_10_COM          0x01    /* 700 software compatibility mode */
--#define DCNTL_10_EA           0x20    /* Enable Ack - needed for MVME16x */
--
--#define DCNTL_700_SAVE ( DCNTL_CF_MASK | DCNTL_S16)
--
--
--/* NCR53c700-66 only */
--#define SCRATCHB_REG_00               0x3c    /* through 0x3f scratch b rw */
--#define SCRATCHB_REG_800      0x5c    /* through 0x5f scratch b rw */
--/* NCR53c710 only */
--#define ADDER_REG_10          0x3c    /* Adder, NCR53c710 only */
--
--#define SIEN1_REG_800         0x41
--#define SIEN1_800_STO         0x04    /* selection/reselection timeout */
--#define SIEN1_800_GEN         0x02    /* general purpose timer */
--#define SIEN1_800_HTH         0x01    /* handshake to handshake */
--
--#define SIST1_REG_800         0x43
--#define SIST1_800_STO         0x04    /* selection/reselection timeout */
--#define SIST1_800_GEN         0x02    /* general purpose timer */
--#define SIST1_800_HTH         0x01    /* handshake to handshake */
--
--#define SLPAR_REG_800         0x44    /* Parity */
--
--#define MACNTL_REG_800                0x46    /* Memory access control */
--#define MACNTL_800_TYP3               0x80
--#define MACNTL_800_TYP2               0x40
--#define MACNTL_800_TYP1               0x20
--#define MACNTL_800_TYP0               0x10
--#define MACNTL_800_DWR                0x08
--#define MACNTL_800_DRD                0x04
--#define MACNTL_800_PSCPT      0x02
--#define MACNTL_800_SCPTS      0x01
--
--#define GPCNTL_REG_800                0x47    /* General Purpose Pin Control */
--
--/* Timeouts are expressed such that 0=off, 1=100us, doubling after that */
--#define STIME0_REG_800                0x48    /* SCSI Timer Register 0 */
--#define STIME0_800_HTH_MASK   0xf0    /* Handshake to Handshake timeout */
--#define STIME0_800_HTH_SHIFT  4
--#define STIME0_800_SEL_MASK   0x0f    /* Selection timeout */
--#define STIME0_800_SEL_SHIFT  0
--
--#define STIME1_REG_800                0x49
--#define STIME1_800_GEN_MASK   0x0f    /* General purpose timer */
--
--#define RESPID_REG_800                0x4a    /* Response ID, bit fielded.  8
--                                         bits on narrow chips, 16 on WIDE */
--
--#define STEST0_REG_800                0x4c    
--#define STEST0_800_SLT                0x08    /* Selection response logic test */
--#define STEST0_800_ART                0x04    /* Arbitration priority encoder test */
--#define STEST0_800_SOZ                0x02    /* Synchronous offset zero */
--#define STEST0_800_SOM                0x01    /* Synchronous offset maximum */
--
--#define STEST1_REG_800                0x4d
--#define STEST1_800_SCLK               0x80    /* Disable SCSI clock */
--
--#define STEST2_REG_800                0x4e    
--#define STEST2_800_SCE                0x80    /* Enable SOCL/SODL */
--#define STEST2_800_ROF                0x40    /* Reset SCSI sync offset */
--#define STEST2_800_SLB                0x10    /* Enable SCSI loopback mode */
--#define STEST2_800_SZM                0x08    /* SCSI high impedance mode */
--#define STEST2_800_EXT                0x02    /* Extend REQ/ACK filter 30 to 60ns */
--#define STEST2_800_LOW                0x01    /* SCSI low level mode */
--
--#define STEST3_REG_800                0x4f     
--#define STEST3_800_TE         0x80    /* Enable active negation */
--#define STEST3_800_STR                0x40    /* SCSI FIFO test read */
--#define STEST3_800_HSC                0x20    /* Halt SCSI clock */
--#define STEST3_800_DSI                0x10    /* Disable single initiator response */
--#define STEST3_800_TTM                0x04    /* Time test mode */
--#define STEST3_800_CSF                0x02    /* Clear SCSI FIFO */
--#define STEST3_800_STW                0x01    /* SCSI FIFO test write */
--
--#define OPTION_PARITY                 0x1     /* Enable parity checking */
--#define OPTION_TAGGED_QUEUE   0x2     /* Enable SCSI-II tagged queuing */
--#define OPTION_700            0x8     /* Always run NCR53c700 scripts */
--#define OPTION_INTFLY         0x10    /* Use INTFLY interrupts */
--#define OPTION_DEBUG_INTR     0x20    /* Debug interrupts */
--#define OPTION_DEBUG_INIT_ONLY        0x40    /* Run initialization code and 
--                                         simple test code, return
--                                         DID_NO_CONNECT if any SCSI
--                                         commands are attempted. */
--#define OPTION_DEBUG_READ_ONLY        0x80    /* Return DID_ERROR if any 
--                                         SCSI write is attempted */
--#define OPTION_DEBUG_TRACE    0x100   /* Animated trace mode, print 
--                                         each address and instruction 
--                                         executed to debug buffer. */
--#define OPTION_DEBUG_SINGLE   0x200   /* stop after executing one 
--                                         instruction */
--#define OPTION_SYNCHRONOUS    0x400   /* Enable sync SCSI.  */
--#define OPTION_MEMORY_MAPPED  0x800   /* NCR registers have valid 
--                                         memory mapping */
--#define OPTION_IO_MAPPED      0x1000  /* NCR registers have valid
--                                           I/O mapping */
--#define OPTION_DEBUG_PROBE_ONLY       0x2000  /* Probe only, don't even init */
--#define OPTION_DEBUG_TESTS_ONLY       0x4000  /* Probe, init, run selected tests */
--#define OPTION_DEBUG_TEST0    0x08000 /* Run test 0 */
--#define OPTION_DEBUG_TEST1    0x10000 /* Run test 1 */
--#define OPTION_DEBUG_TEST2    0x20000 /* Run test 2 */
--#define OPTION_DEBUG_DUMP     0x40000 /* Dump commands */
--#define OPTION_DEBUG_TARGET_LIMIT 0x80000 /* Only talk to target+luns specified */
--#define OPTION_DEBUG_NCOMMANDS_LIMIT 0x100000 /* Limit the number of commands */
--#define OPTION_DEBUG_SCRIPT 0x200000 /* Print when checkpoints are passed */
--#define OPTION_DEBUG_FIXUP 0x400000 /* print fixup values */
--#define OPTION_DEBUG_DSA 0x800000
--#define OPTION_DEBUG_CORRUPTION       0x1000000       /* Detect script corruption */
--#define OPTION_DEBUG_SDTR       0x2000000     /* Debug SDTR problem */
--#define OPTION_DEBUG_MISMATCH         0x4000000       /* Debug phase mismatches */
--#define OPTION_DISCONNECT     0x8000000       /* Allow disconnect */
--#define OPTION_DEBUG_DISCONNECT 0x10000000    
--#define OPTION_ALWAYS_SYNCHRONOUS 0x20000000  /* Negotiate sync. transfers
--                                                 on power up */
--#define OPTION_DEBUG_QUEUES   0x80000000      
--#define OPTION_DEBUG_ALLOCATION 0x100000000LL
--#define OPTION_DEBUG_SYNCHRONOUS 0x200000000LL        /* Sanity check SXFER and 
--                                                 SCNTL3 registers */
--#define OPTION_NO_ASYNC       0x400000000LL           /* Don't automagically send
--                                                 SDTR for async transfers when
--                                                 we haven't been told to do
--                                                 a synchronous transfer. */
--#define OPTION_NO_PRINT_RACE 0x800000000LL    /* Don't print message when
--                                                 the reselect/WAIT DISCONNECT
--                                                 race condition hits */
--#if !defined(PERM_OPTIONS)
--#define PERM_OPTIONS 0
--#endif
--                              
--/*
-- * Some data which is accessed by the NCR chip must be 4-byte aligned.
-- * For some hosts the default is less than that (eg. 68K uses 2-byte).
-- * Alignment has only been forced where it is important; also if one
-- * 32 bit structure field is aligned then it is assumed that following
-- * 32 bit fields are also aligned.  Take care when adding fields
-- * which are other than 32 bit.
-- */
--
--struct NCR53c7x0_synchronous {
--    u32 select_indirect                       /* Value used for indirect selection */
--      __attribute__ ((aligned (4)));
--    u32 sscf_710;                     /* Used to set SSCF bits for 710 */
--    u32 script[8];                    /* Size ?? Script used when target is 
--                                              reselected */
--    unsigned char synchronous_want[5];        /* Per target desired SDTR */
--/* 
-- * Set_synchronous programs these, select_indirect and current settings after
-- * int_debug_should show a match.
-- */
--    unsigned char sxfer_sanity, scntl3_sanity;
--};
+-It is possible for files on different branches to have the same name.
+-Unionfs then has to select which instance of the file to show to the user.
+-Given the fact that each branch has a priority associated with it, the
+-simplest solution is to take the instance from the highest priority
+-(numerically lowest value) and "hide" the others.
 -
--#define CMD_FLAG_SDTR                 1       /* Initiating synchronous 
--                                         transfer negotiation */
--#define CMD_FLAG_WDTR         2       /* Initiating wide transfer
--                                         negotiation */
--#define CMD_FLAG_DID_SDTR     4       /* did SDTR */
--#define CMD_FLAG_DID_WDTR     8       /* did WDTR */
 -
--struct NCR53c7x0_table_indirect {
--    u32 count;
--    void *address;
--};
+-Copyup:
+-=======
 -
--enum ncr_event { 
--    EVENT_NONE = 0,
--/* 
-- * Order is IMPORTANT, since these must correspond to the event interrupts
-- * in 53c7,8xx.scr 
-- */
--
--    EVENT_ISSUE_QUEUE = 0x5000000,    /* 0 Command was added to issue queue */
--    EVENT_START_QUEUE,                        /* 1 Command moved to start queue */
--    EVENT_SELECT,                     /* 2 Command completed selection */
--    EVENT_DISCONNECT,                 /* 3 Command disconnected */
--    EVENT_RESELECT,                   /* 4 Command reselected */
--    EVENT_COMPLETE,                   /* 5 Command completed */
--    EVENT_IDLE,                               /* 6 */
--    EVENT_SELECT_FAILED,              /* 7 */
--    EVENT_BEFORE_SELECT,              /* 8 */
--    EVENT_RESELECT_FAILED             /* 9 */
--};
+-When a change is made to the contents of a file's data or meta-data, they
+-have to be stored somewhere. The best way is to create a copy of the
+-original file on a branch that is writable, and then redirect the write
+-though to this copy. The copy must be made on a higher priority branch so
+-that lookup and readdir return this newer "version" of the file rather than
+-the original (see duplicate elimination).
 -
--struct NCR53c7x0_event {
--    enum ncr_event event;     /* What type of event */
--    unsigned char target;
--    unsigned char lun;
--    struct timeval time;      
--    u32 *dsa;                 /* What's in the DSA register now (virt) */
--/* 
-- * A few things from that SCSI pid so we know what happened after 
-- * the Scsi_Cmnd structure in question may have disappeared.
-- */
--    unsigned long pid;                /* The SCSI PID which caused this 
--                                 event */
--    unsigned char cmnd[12];
--};
 -
--/*
-- * Things in the NCR53c7x0_cmd structure are split into two parts :
-- *
-- * 1.  A fixed portion, for things which are not accessed directly by static NCR
-- *    code (ie, are referenced only by the Linux side of the driver,
-- *    or only by dynamically generated code).  
-- *
-- * 2.  The DSA portion, for things which are accessed directly by static NCR
-- *    code.
-- *
-- * This is a little ugly, but it 
-- * 1.  Avoids conflicts between the NCR code's picture of the structure, and 
-- *    Linux code's idea of what it looks like.
-- *
-- * 2.  Minimizes the pain in the Linux side of the code needed 
-- *    to calculate real dsa locations for things, etc.
-- * 
-- */
+-For more information, see <http://unionfs.filesystems.org/>.
+diff -Nurb linux-2.6.22-590/Documentation/filesystems/unionfs/issues.txt linux-2.6.22-570/Documentation/filesystems/unionfs/issues.txt
+--- linux-2.6.22-590/Documentation/filesystems/unionfs/issues.txt      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/filesystems/unionfs/issues.txt      1969-12-31 19:00:00.000000000 -0500
+@@ -1,39 +0,0 @@
+-KNOWN Unionfs 2.0 ISSUES:
+-=========================
 -
--struct NCR53c7x0_cmd {
--    void *real;                               /* Real, unaligned address for
--                                         free function */
--    void (* free)(void *, int);               /* Command to deallocate; NULL
--                                         for structures allocated with
--                                         scsi_register, etc. */
--    Scsi_Cmnd *cmd;                   /* Associated Scsi_Cmnd 
--                                         structure, Scsi_Cmnd points
--                                         at NCR53c7x0_cmd using 
--                                         host_scribble structure */
+-1. The NFS server returns -EACCES for read-only exports, instead of -EROFS.
+-   This means we can't reliably detect a read-only NFS export.
 -
--    int size;                         /* scsi_malloc'd size of this 
--                                         structure */
+-2. Modifying a Unionfs branch directly, while the union is mounted, is
+-   currently unsupported, because it could cause a cache incoherency between
+-   the union layer and the lower file systems (for that reason, Unionfs
+-   currently prohibits using branches which overlap with each other, even
+-   partially).  We have tested Unionfs under such conditions, and fixed any
+-   bugs we found (Unionfs comes with an extensive regression test suite).
+-   However, it may still be possible that changes made to lower branches
+-   directly could cause cache incoherency which, in the worst case, may case
+-   an oops.
 -
--    int flags;                                /* CMD_* flags */
+-   Unionfs 2.0 has a temporary workaround for this.  You can force Unionfs
+-   to increase the superblock generation number, and hence purge all cached
+-   Unionfs objects, which would then  be re-gotten from the lower branches.
+-   This should ensure cache consistency.  To increase the generation number,
+-   executed the command:
 -
--    unsigned char      cmnd[12];      /* CDB, copied from Scsi_Cmnd */
--    int                result;                /* Copy to Scsi_Cmnd when done */
+-      mount -t unionfs -o remount,incgen none MOUNTPOINT
 -
--    struct {                          /* Private non-cached bounce buffer */
--        unsigned char buf[256];
--      u32           addr;
--        u32           len;
--    } bounce;
+-   Note that the older way of incrementing the generation number using an
+-   ioctl, is no longer supported in Unionfs 2.0.  Ioctls in general are not
+-   encouraged.  Plus, an ioctl is per-file concept, whereas the generation
+-   number is a per-file-system concept.  Worse, such an ioctl requires an
+-   open file, which then has to be invalidated by the very nature of the
+-   generation number increase (read: the old generation increase ioctl was
+-   pretty racy).
 -
--/*
-- * SDTR and WIDE messages are an either/or affair
-- * in this message, since we will go into message out and send
-- * _the whole mess_ without dropping out of message out to 
-- * let the target go into message in after sending the first 
-- * message.
-- */
+-3. Unionfs should not use lookup_one_len() on the underlying f/s as it
+-   confuses NFS.  Currently, unionfs_lookup() passes lookup intents to the
+-   lower file-system, this eliminates part of the problem.  The remaining
+-   calls to lookup_one_len may need to be changed to pass an intent.
 -
--    unsigned char select[11];         /* Select message, includes
--                                         IDENTIFY
--                                         (optional) QUEUE TAG
--                                         (optional) SDTR or WDTR
--                                       */
 -
+-For more information, see <http://unionfs.filesystems.org/>.
+diff -Nurb linux-2.6.22-590/Documentation/filesystems/unionfs/rename.txt linux-2.6.22-570/Documentation/filesystems/unionfs/rename.txt
+--- linux-2.6.22-590/Documentation/filesystems/unionfs/rename.txt      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/filesystems/unionfs/rename.txt      1969-12-31 19:00:00.000000000 -0500
+@@ -1,31 +0,0 @@
+-Rename is a complex beast. The following table shows which rename(2) operations
+-should succeed and which should fail.
 -
--    volatile struct NCR53c7x0_cmd *next; /* Linux maintained lists (free,
--                                          running, eventually finished */
--                                       
+-o: success
+-E: error (either unionfs or vfs)
+-X: EXDEV
 -
--    u32 *data_transfer_start;         /* Start of data transfer routines */
--    u32 *data_transfer_end;           /* Address after end of data transfer o
--                                         routines */
--/* 
-- * The following three fields were moved from the DSA proper to here
-- * since only dynamically generated NCR code refers to them, meaning
-- * we don't need dsa_* absolutes, and it is simpler to let the 
-- * host code refer to them directly.
-- */
+-none = file does not exist
+-file = file is a file
+-dir  = file is a empty directory
+-child= file is a non-empty directory
+-wh   = file is a directory containing only whiteouts; this makes it logically
+-              empty
 -
--/* 
-- * HARD CODED : residual and saved_residual need to agree with the sizes
-- * used in NCR53c7,8xx.scr.  
-- * 
-- * FIXME: we want to consider the case where we have odd-length 
-- *    scatter/gather buffers and a WIDE transfer, in which case 
-- *    we'll need to use the CHAIN MOVE instruction.  Ick.
-- */
--    u32 residual[6] __attribute__ ((aligned (4)));
--                                      /* Residual data transfer which
--                                         allows pointer code to work
--                                         right.
--
--                                          [0-1] : Conditional call to 
--                                              appropriate other transfer 
--                                              routine.
--                                          [2-3] : Residual block transfer
--                                              instruction.
--                                          [4-5] : Jump to instruction
--                                              after splice.
--                                       */
--    u32 saved_residual[6];            /* Copy of old residual, so we 
--                                         can get another partial 
--                                         transfer and still recover 
--                                       */
--              
--    u32 saved_data_pointer;           /* Saved data pointer */
--
--    u32 dsa_next_addr;                        /* _Address_ of dsa_next field  
--                                         in this dsa for RISCy 
--                                         style constant. */
--
--    u32 dsa_addr;                     /* Address of dsa; RISCy style
--                                         constant */
--
--    u32 dsa[0];                               /* Variable length (depending
--                                         on host type, number of scatter /
--                                         gather buffers, etc).  */
--};
+-                      none    file    dir     child   wh
+-file                  o       o       E       E       E
+-dir                   o       E       o       E       o
+-child                 X       E       X       E       X
+-wh                    o       E       o       E       o
 -
--struct NCR53c7x0_break {
--    u32 *address, old_instruction[2];
--    struct NCR53c7x0_break *next;
--    unsigned char old_size;           /* Size of old instruction */
--};
 -
--/* Indicates that the NCR is not executing code */
--#define STATE_HALTED  0               
--/* 
-- * Indicates that the NCR is executing the wait for select / reselect 
-- * script.  Only used when running NCR53c700 compatible scripts, only 
-- * state during which an ABORT is _not_ considered an error condition.
-- */
--#define STATE_WAITING 1               
--/* Indicates that the NCR is executing other code. */
--#define STATE_RUNNING 2               
--/* 
-- * Indicates that the NCR was being aborted.
-- */
--#define STATE_ABORTING        3
--/* Indicates that the NCR was successfully aborted. */
--#define STATE_ABORTED 4
--/* Indicates that the NCR has been disabled due to a fatal error */
--#define STATE_DISABLED 5
+-Renaming directories:
+-=====================
 -
--/* 
-- * Where knowledge of SCSI SCRIPT(tm) specified values are needed 
-- * in an interrupt handler, an interrupt handler exists for each 
-- * different SCSI script so we don't have name space problems.
-- * 
-- * Return values of these handlers are as follows : 
-- */
--#define SPECIFIC_INT_NOTHING  0       /* don't even restart */
--#define SPECIFIC_INT_RESTART  1       /* restart at the next instruction */
--#define SPECIFIC_INT_ABORT    2       /* recoverable error, abort cmd */
--#define SPECIFIC_INT_PANIC    3       /* unrecoverable error, panic */
--#define SPECIFIC_INT_DONE     4       /* normal command completion */
--#define SPECIFIC_INT_BREAK    5       /* break point encountered */
--
--struct NCR53c7x0_hostdata {
--    int size;                         /* Size of entire Scsi_Host
--                                         structure */
--    int board;                                /* set to board type, useful if 
--                                         we have host specific things,
--                                         ie, a general purpose I/O 
--                                         bit is being used to enable
--                                         termination, etc. */
--
--    int chip;                         /* set to chip type; 700-66 is
--                                         700-66, rest are last three
--                                         digits of part number */
--
--    char valid_ids[8];                        /* Valid SCSI ID's for adapter */
--
--    u32 *dsp;                         /* dsp to restart with after
--                                         all stacked interrupts are
--                                         handled. */
--
--    unsigned dsp_changed:1;           /* Has dsp changed within this
--                                         set of stacked interrupts ? */
--
--    unsigned char dstat;              /* Most recent value of dstat */
--    unsigned dstat_valid:1;
--
--    unsigned expecting_iid:1;         /* Expect IID interrupt */
--    unsigned expecting_sto:1;         /* Expect STO interrupt */
--    
--    /* 
--     * The code stays cleaner if we use variables with function
--     * pointers and offsets that are unique for the different
--     * scripts rather than having a slew of switch(hostdata->chip) 
--     * statements.
--     * 
--     * It also means that the #defines from the SCSI SCRIPTS(tm)
--     * don't have to be visible outside of the script-specific
--     * instructions, preventing name space pollution.
--     */
--
--    void (* init_fixup)(struct Scsi_Host *host);
--    void (* init_save_regs)(struct Scsi_Host *host);
--    void (* dsa_fixup)(struct NCR53c7x0_cmd *cmd);
--    void (* soft_reset)(struct Scsi_Host *host);
--    int (* run_tests)(struct Scsi_Host *host);
--
--    /*
--     * Called when DSTAT_SIR is set, indicating an interrupt generated
--     * by the INT instruction, where values are unique for each SCSI
--     * script.  Should return one of the SPEC_* values.
--     */
--
--    int (* dstat_sir_intr)(struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);
--
--    int dsa_len; /* Size of DSA structure */
--
--    /*
--     * Location of DSA fields for the SCSI SCRIPT corresponding to this 
--     * chip.  
--     */
--
--    s32 dsa_start;                    
--    s32 dsa_end;                      
--    s32 dsa_next;
--    s32 dsa_prev;
--    s32 dsa_cmnd;
--    s32 dsa_select;
--    s32 dsa_msgout;
--    s32 dsa_cmdout;
--    s32 dsa_dataout;
--    s32 dsa_datain;
--    s32 dsa_msgin;
--    s32 dsa_msgout_other;
--    s32 dsa_write_sync;
--    s32 dsa_write_resume;
--    s32 dsa_check_reselect;
--    s32 dsa_status;
--    s32 dsa_saved_pointer;
--    s32 dsa_jump_dest;
--
--    /* 
--     * Important entry points that generic fixup code needs
--     * to know about, fixed up.
--     */
--
--    s32 E_accept_message;
--    s32 E_command_complete;           
--    s32 E_data_transfer;
--    s32 E_dsa_code_template;
--    s32 E_dsa_code_template_end;
--    s32 E_end_data_transfer;
--    s32 E_msg_in;
--    s32 E_initiator_abort;
--    s32 E_other_transfer;
--    s32 E_other_in;
--    s32 E_other_out;
--    s32 E_target_abort;
--    s32 E_debug_break;        
--    s32 E_reject_message;
--    s32 E_respond_message;
--    s32 E_select;
--    s32 E_select_msgout;
--    s32 E_test_0;
--    s32 E_test_1;
--    s32 E_test_2;
--    s32 E_test_3;
--    s32 E_dsa_zero;
--    s32 E_cmdout_cmdout;
--    s32 E_wait_reselect;
--    s32 E_dsa_code_begin;
--
--    long long options;                        /* Bitfielded set of options enabled */
--    volatile u32 test_completed;      /* Test completed */
--    int test_running;                 /* Test currently running */
--    s32 test_source
--      __attribute__ ((aligned (4)));
--    volatile s32 test_dest;
--
--    volatile int state;                       /* state of driver, only used for 
--                                         OPTION_700 */
--
--    unsigned char  dmode;             /* 
--                                       * set to the address of the DMODE 
--                                       * register for this chip.
--                                       */
--    unsigned char istat;              /* 
--                                       * set to the address of the ISTAT 
--                                       * register for this chip.
--                                       */
--  
--    int scsi_clock;                   /* 
--                                       * SCSI clock in HZ. 0 may be used 
--                                       * for unknown, although this will
--                                       * disable synchronous negotiation.
--                                       */
+-Whenever a empty (either physically or logically) directory is being renamed,
+-the following sequence of events should take place:
 -
--    volatile int intrs;                       /* Number of interrupts */
--    volatile int resets;              /* Number of SCSI resets */
--    unsigned char saved_dmode;        
--    unsigned char saved_ctest4;
--    unsigned char saved_ctest7;
--    unsigned char saved_dcntl;
--    unsigned char saved_scntl3;
--
--    unsigned char this_id_mask;
--
--    /* Debugger information */
--    struct NCR53c7x0_break *breakpoints, /* Linked list of all break points */
--      *breakpoint_current;            /* Current breakpoint being stepped 
--                                         through, NULL if we are running 
--                                         normally. */
--#ifdef NCR_DEBUG
--    int debug_size;                   /* Size of debug buffer */
--    volatile int debug_count;         /* Current data count */
--    volatile char *debug_buf;         /* Output ring buffer */
--    volatile char *debug_write;               /* Current write pointer */
--    volatile char *debug_read;                /* Current read pointer */
--#endif /* def NCR_DEBUG */
--
--    /* XXX - primitive debugging junk, remove when working ? */
--    int debug_print_limit;            /* Number of commands to print
--                                         out exhaustive debugging
--                                         information for if 
--                                         OPTION_DEBUG_DUMP is set */ 
--
--    unsigned char debug_lun_limit[16];        /* If OPTION_DEBUG_TARGET_LIMIT
--                                         set, puke if commands are sent
--                                         to other target/lun combinations */
--
--    int debug_count_limit;            /* Number of commands to execute
--                                         before puking to limit debugging 
--                                         output */
--                                  
--
--    volatile unsigned idle:1;                 /* set to 1 if idle */
--
--    /* 
--     * Table of synchronous+wide transfer parameters set on a per-target
--     * basis.
--     */
--    
--    volatile struct NCR53c7x0_synchronous sync[16]
--      __attribute__ ((aligned (4)));
--
--    volatile Scsi_Cmnd *issue_queue
--      __attribute__ ((aligned (4)));
--                                              /* waiting to be issued by
--                                                 Linux driver */
--    volatile struct NCR53c7x0_cmd *running_list;      
--                                              /* commands running, maintained
--                                                 by Linux driver */
--
--    volatile struct NCR53c7x0_cmd *ncrcurrent;        /* currently connected 
--                                                 nexus, ONLY valid for
--                                                 NCR53c700/NCR53c700-66
--                                               */
+-1) Remove whiteouts from both source and destination directory
+-2) Rename source to destination
+-3) Make destination opaque to prevent anything under it from showing up
 -
--    volatile struct NCR53c7x0_cmd *spare;     /* pointer to spare,
--                                                 allocated at probe time,
--                                                 which we can use for 
--                                                 initialization */
--    volatile struct NCR53c7x0_cmd *free;
--    int max_cmd_size;                         /* Maximum size of NCR53c7x0_cmd
--                                                 based on number of 
--                                                 scatter/gather segments, etc.
--                                                 */
--    volatile int num_cmds;                    /* Number of commands 
--                                                 allocated */
--    volatile int extra_allocate;
--    volatile unsigned char cmd_allocated[16]; /* Have we allocated commands
--                                                 for this target yet?  If not,
--                                                 do so ASAP */
--    volatile unsigned char busy[16][8];       /* number of commands 
--                                                 executing on each target
--                                               */
--    /* 
--     * Eventually, I'll switch to a coroutine for calling 
--     * cmd->done(cmd), etc. so that we can overlap interrupt
--     * processing with this code for maximum performance.
--     */
--    
--    volatile struct NCR53c7x0_cmd *finished_queue;    
--                                              
--    /* Shared variables between SCRIPT and host driver */
--    volatile u32 *schedule
--      __attribute__ ((aligned (4)));          /* Array of JUMPs to dsa_begin
--                                                 routines of various DSAs.  
--                                                 When not in use, replace
--                                                 with jump to next slot */
--
--
--    volatile unsigned char msg_buf[16];               /* buffer for messages
--                                                 other than the command
--                                                 complete message */
--
--    /* Per-target default synchronous and WIDE messages */
--    volatile unsigned char synchronous_want[16][5];
--    volatile unsigned char wide_want[16][4];
--
--    /* Bit fielded set of targets we want to speak synchronously with */ 
--    volatile u16 initiate_sdtr;       
--    /* Bit fielded set of targets we want to speak wide with */
--    volatile u16 initiate_wdtr;
--    /* Bit fielded list of targets we've talked to. */
--    volatile u16 talked_to;
--
--    /* Array of bit-fielded lun lists that we need to request_sense */
--    volatile unsigned char request_sense[16];
--
--    u32 addr_reconnect_dsa_head
--      __attribute__ ((aligned (4)));          /* RISCy style constant,
--                                                 address of following */
--    volatile u32 reconnect_dsa_head;  
--    /* Data identifying nexus we are trying to match during reselection */
--    volatile unsigned char reselected_identify; /* IDENTIFY message */
--    volatile unsigned char reselected_tag;    /* second byte of queue tag 
--                                                 message or 0 */
--
--    /* These were static variables before we moved them */
--
--    s32 NCR53c7xx_zero
--      __attribute__ ((aligned (4)));
--    s32 NCR53c7xx_sink;
--    u32 NOP_insn;
--    char NCR53c7xx_msg_reject;
--    char NCR53c7xx_msg_abort;
--    char NCR53c7xx_msg_nop;
--
--    /*
--     * Following item introduced by RGH to support NCRc710, which is
--     * VERY brain-dead when it come to memory moves
--     */
--
--                        /* DSA save area used only by the NCR chip */
--    volatile unsigned long saved2_dsa
--      __attribute__ ((aligned (4)));
--
--    volatile unsigned long emulated_intfly
--      __attribute__ ((aligned (4)));
--
--    volatile int event_size, event_index;
--    volatile struct NCR53c7x0_event *events;
--
--    /* If we need to generate code to kill off the currently connected 
--       command, this is where we do it. Should have a BMI instruction
--       to source or sink the current data, followed by a JUMP
--       to abort_connected */
--
--    u32 *abort_script;
--
--    int script_count;                         /* Size of script in words */
--    u32 script[0];                            /* Relocated SCSI script */
+diff -Nurb linux-2.6.22-590/Documentation/filesystems/unionfs/usage.txt linux-2.6.22-570/Documentation/filesystems/unionfs/usage.txt
+--- linux-2.6.22-590/Documentation/filesystems/unionfs/usage.txt       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/filesystems/unionfs/usage.txt       1969-12-31 19:00:00.000000000 -0500
+@@ -1,90 +0,0 @@
+-Unionfs is a stackable unification file system, which can appear to merge
+-the contents of several directories (branches), while keeping their physical
+-content separate.  Unionfs is useful for unified source tree management,
+-merged contents of split CD-ROM, merged separate software package
+-directories, data grids, and more.  Unionfs allows any mix of read-only and
+-read-write branches, as well as insertion and deletion of branches anywhere
+-in the fan-out.  To maintain Unix semantics, Unionfs handles elimination of
+-duplicates, partial-error conditions, and more.
 -
--};
+-# mount -t unionfs -o branch-option[,union-options[,...]] none MOUNTPOINT
 -
--#define SCSI_IRQ_NONE 255
--#define DMA_NONE      255
--#define IRQ_AUTO      254
--#define DMA_AUTO      254
+-The available branch-option for the mount command is:
 -
--#define BOARD_GENERIC 0
+-      dirs=branch[=ro|=rw][:...]
 -
--#define NCR53c7x0_insn_size(insn)                                     \
--    (((insn) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI ? 3 : 2)
--    
+-specifies a separated list of which directories compose the union.
+-Directories that come earlier in the list have a higher precedence than
+-those which come later. Additionally, read-only or read-write permissions of
+-the branch can be specified by appending =ro or =rw (default) to each
+-directory.
 -
--#define NCR53c7x0_local_declare()                                     \
--    volatile unsigned char *NCR53c7x0_address_memory;                 \
--    unsigned int NCR53c7x0_address_io;                                        \
--    int NCR53c7x0_memory_mapped
--
--#define NCR53c7x0_local_setup(host)                                   \
--    NCR53c7x0_address_memory = (void *) (host)->base;                 \
--    NCR53c7x0_address_io = (unsigned int) (host)->io_port;            \
--    NCR53c7x0_memory_mapped = ((struct NCR53c7x0_hostdata *)          \
--      host->hostdata[0])-> options & OPTION_MEMORY_MAPPED 
--
--#ifdef BIG_ENDIAN
--/* These could be more efficient, given that we are always memory mapped,
-- * but they don't give the same problems as the write macros, so leave
-- * them. */
--#ifdef __mc68000__
--#define NCR53c7x0_read8(address)                                      \
--    ((unsigned int)raw_inb((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) )
--
--#define NCR53c7x0_read16(address)                                     \
--    ((unsigned int)raw_inw((u32)NCR53c7x0_address_memory + ((u32)(address)^2)))
--#else
--#define NCR53c7x0_read8(address)                                      \
--    (NCR53c7x0_memory_mapped ?                                                \
--      (unsigned int)readb((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) :       \
--      inb(NCR53c7x0_address_io + (address)))
--
--#define NCR53c7x0_read16(address)                                     \
--    (NCR53c7x0_memory_mapped ?                                                \
--      (unsigned int)readw((u32)NCR53c7x0_address_memory + ((u32)(address)^2)) :       \
--      inw(NCR53c7x0_address_io + (address)))
--#endif /* mc68000 */
--#else
--#define NCR53c7x0_read8(address)                                      \
--    (NCR53c7x0_memory_mapped ?                                                \
--      (unsigned int)readb((u32)NCR53c7x0_address_memory + (u32)(address)) :   \
--      inb(NCR53c7x0_address_io + (address)))
--
--#define NCR53c7x0_read16(address)                                     \
--    (NCR53c7x0_memory_mapped ?                                                \
--      (unsigned int)readw((u32)NCR53c7x0_address_memory + (u32)(address)) :   \
--      inw(NCR53c7x0_address_io + (address)))
--#endif
+-Syntax:
 -
--#ifdef __mc68000__
--#define NCR53c7x0_read32(address)                                     \
--    ((unsigned int) raw_inl((u32)NCR53c7x0_address_memory + (u32)(address)))
--#else
--#define NCR53c7x0_read32(address)                                     \
--    (NCR53c7x0_memory_mapped ?                                                \
--      (unsigned int) readl((u32)NCR53c7x0_address_memory + (u32)(address)) :  \
--      inl(NCR53c7x0_address_io + (address)))
--#endif /* mc68000*/
+-      dirs=/branch1[=ro|=rw]:/branch2[=ro|=rw]:...:/branchN[=ro|=rw]
 -
--#ifdef BIG_ENDIAN
--/* If we are big-endian, then we are not Intel, so probably don't have
-- * an i/o map as well as a memory map.  So, let's assume memory mapped.
-- * Also, I am having terrible problems trying to persuade the compiler
-- * not to lay down code which does a read after write for these macros.
-- * If you remove 'volatile' from writeb() and friends it is ok....
-- */
+-Example:
 -
--#define NCR53c7x0_write8(address,value)                               \
--      *(volatile unsigned char *)                                     \
--              ((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) = (value)
+-      dirs=/writable_branch=rw:/read-only_branch=ro
 -
--#define NCR53c7x0_write16(address,value)                              \
--      *(volatile unsigned short *)                                    \
--              ((u32)NCR53c7x0_address_memory + ((u32)(address)^2)) = (value)
 -
--#define NCR53c7x0_write32(address,value)                              \
--      *(volatile unsigned long *)                                     \
--              ((u32)NCR53c7x0_address_memory + ((u32)(address))) = (value)
+-DYNAMIC BRANCH MANAGEMENT AND REMOUNTS
+-======================================
 -
--#else
+-You can remount a union and change its overall mode, or reconfigure the
+-branches, as follows.
 -
--#define NCR53c7x0_write8(address,value)                               \
--    (NCR53c7x0_memory_mapped ?                                                \
--     ({writeb((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) :     \
--      outb((value), NCR53c7x0_address_io + (address)))
+-To downgrade a union from read-write to read-only:
 -
--#define NCR53c7x0_write16(address,value)                              \
--    (NCR53c7x0_memory_mapped ?                                                \
--     ({writew((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) :     \
--      outw((value), NCR53c7x0_address_io + (address)))
+-# mount -t unionfs -o remount,ro none MOUNTPOINT
 -
--#define NCR53c7x0_write32(address,value)                              \
--    (NCR53c7x0_memory_mapped ?                                                \
--     ({writel((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) :     \
--      outl((value), NCR53c7x0_address_io + (address)))
+-To upgrade a union from read-only to read-write:
 -
--#endif
+-# mount -t unionfs -o remount,rw none MOUNTPOINT
 -
--/* Patch arbitrary 32 bit words in the script */
--#define patch_abs_32(script, offset, symbol, value)                   \
--      for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof            \
--          (u32)); ++i) {                                      \
--          (script)[A_##symbol##_used[i] - (offset)] += (value);       \
--          if (hostdata->options & OPTION_DEBUG_FIXUP)                 \
--            printk("scsi%d : %s reference %d at 0x%x in %s is now 0x%x\n",\
--              host->host_no, #symbol, i, A_##symbol##_used[i] -       \
--              (int)(offset), #script, (script)[A_##symbol##_used[i] - \
--              (offset)]);                                             \
--      }
--
--/* Patch read/write instruction immediate field */
--#define patch_abs_rwri_data(script, offset, symbol, value)            \
--      for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof            \
--          (u32)); ++i)                                        \
--          (script)[A_##symbol##_used[i] - (offset)] =                 \
--              ((script)[A_##symbol##_used[i] - (offset)] &            \
--              ~DBC_RWRI_IMMEDIATE_MASK) |                             \
--              (((value) << DBC_RWRI_IMMEDIATE_SHIFT) &                \
--               DBC_RWRI_IMMEDIATE_MASK)
--
--/* Patch transfer control instruction data field */
--#define patch_abs_tci_data(script, offset, symbol, value)             \
--      for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof            \
--          (u32)); ++i)                                        \
--          (script)[A_##symbol##_used[i] - (offset)] =                 \
--              ((script)[A_##symbol##_used[i] - (offset)] &            \
--              ~DBC_TCI_DATA_MASK) |                                   \
--              (((value) << DBC_TCI_DATA_SHIFT) &                      \
--               DBC_TCI_DATA_MASK)
--
--/* Patch field in dsa structure (assignment should be +=?) */
--#define patch_dsa_32(dsa, symbol, word, value)                                \
--      {                                                               \
--      (dsa)[(hostdata->##symbol - hostdata->dsa_start) / sizeof(u32)  \
--          + (word)] = (value);                                        \
--      if (hostdata->options & OPTION_DEBUG_DSA)                       \
--          printk("scsi : dsa %s symbol %s(%d) word %d now 0x%x\n",    \
--              #dsa, #symbol, hostdata->##symbol,                      \
--              (word), (u32) (value));                                 \
--      }
--
--/* Paranoid people could use panic() here. */
--#define FATAL(host) shutdown((host));
--
--extern int ncr53c7xx_init(struct scsi_host_template *tpnt, int board, int chip,
--                        unsigned long base, int io_port, int irq, int dma,
--                        long long options, int clock);
--
--#endif /* NCR53c710_C */
--#endif /* NCR53c710_H */
-diff -Nurb linux-2.6.22-570/drivers/scsi/53c7xx.scr linux-2.6.22-590/drivers/scsi/53c7xx.scr
---- linux-2.6.22-570/drivers/scsi/53c7xx.scr   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/53c7xx.scr   1969-12-31 19:00:00.000000000 -0500
-@@ -1,1591 +0,0 @@
--#undef DEBUG
--#undef EVENTS
--#undef NO_SELECTION_TIMEOUT
--#define BIG_ENDIAN
--
--; 53c710 driver.  Modified from Drew Eckhardts driver
--; for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
--;
--; I have left the script for the 53c8xx family in here, as it is likely
--; to be useful to see what I changed when bug hunting.
--
--; NCR 53c810 driver, main script
--; Sponsored by 
--;     iX Multiuser Multitasking Magazine
--;     hm@ix.de
--;
--; Copyright 1993, 1994, 1995 Drew Eckhardt
--;      Visionary Computing 
--;      (Unix and Linux consulting and custom programming)
--;      drew@PoohSticks.ORG
--;      +1 (303) 786-7975
--;
--; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
--;
--; PRE-ALPHA
--;
--; For more information, please consult 
--;
--; NCR 53C810
--; PCI-SCSI I/O Processor
--; Data Manual
--;
--; NCR 53C710 
--; SCSI I/O Processor
--; Programmers Guide
--;
--; NCR Microelectronics
--; 1635 Aeroplaza Drive
--; Colorado Springs, CO 80916
--; 1+ (719) 578-3400
--;
--; Toll free literature number
--; +1 (800) 334-5454
--;
--; IMPORTANT : This code is self modifying due to the limitations of 
--;     the NCR53c7,8xx series chips.  Persons debugging this code with
--;     the remote debugger should take this into account, and NOT set
--;     breakpoints in modified instructions.
--;
--; Design:
--; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard 
--; microcontroller using a simple instruction set.   
--;
--; So, to minimize the effects of interrupt latency, and to maximize 
--; throughput, this driver offloads the practical maximum amount 
--; of processing to the SCSI chip while still maintaining a common
--; structure.
--;
--; Where tradeoffs were needed between efficiency on the older
--; chips and the newer NCR53c800 series, the NCR53c800 series 
--; was chosen.
--;
--; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully
--; automate SCSI transfers without host processor intervention, this 
--; isn't the case with the NCR53c710 and newer chips which allow 
--;
--; - reads and writes to the internal registers from within the SCSI
--;     scripts, allowing the SCSI SCRIPTS(tm) code to save processor
--;     state so that multiple threads of execution are possible, and also
--;     provide an ALU for loop control, etc.
--; 
--; - table indirect addressing for some instructions. This allows 
--;     pointers to be located relative to the DSA ((Data Structure
--;     Address) register.
--;
--; These features make it possible to implement a mailbox style interface,
--; where the same piece of code is run to handle I/O for multiple threads
--; at once minimizing our need to relocate code.  Since the NCR53c700/
--; NCR53c800 series have a unique combination of features, making a 
--; a standard ingoing/outgoing mailbox system, costly, I've modified it.
--;
--; - Mailboxes are a mixture of code and data.  This lets us greatly
--;     simplify the NCR53c810 code and do things that would otherwise
--;     not be possible.
--;
--; The saved data pointer is now implemented as follows :
--;
--;     Control flow has been architected such that if control reaches
--;     munge_save_data_pointer, on a restore pointers message or 
--;     reconnection, a jump to the address formerly in the TEMP register
--;     will allow the SCSI command to resume execution.
--;
--
--;
--; Note : the DSA structures must be aligned on 32 bit boundaries,
--; since the source and destination of MOVE MEMORY instructions 
--; must share the same alignment and this is the alignment of the
--; NCR registers.
--;
--
--; For some systems (MVME166, for example) dmode is always the same, so don't
--; waste time writing it
--
--#if 1
--#define DMODE_MEMORY_TO_NCR
--#define DMODE_MEMORY_TO_MEMORY
--#define DMODE_NCR_TO_MEMORY
--#else
--#define DMODE_MEMORY_TO_NCR    MOVE dmode_memory_to_ncr TO DMODE
--#define DMODE_MEMORY_TO_MEMORY MOVE dmode_memory_to_memory TO DMODE
--#define DMODE_NCR_TO_MEMORY    MOVE dmode_ncr_to_memory TO DMODE
--#endif
+-To delete a branch /foo, regardless where it is in the current union:
 -
--ABSOLUTE dsa_temp_lun = 0             ; Patch to lun for current dsa
--ABSOLUTE dsa_temp_next = 0            ; Patch to dsa next for current dsa
--ABSOLUTE dsa_temp_addr_next = 0               ; Patch to address of dsa next address 
--                                      ;       for current dsa
--ABSOLUTE dsa_temp_sync = 0            ; Patch to address of per-target
--                                      ;       sync routine
--ABSOLUTE dsa_sscf_710 = 0             ; Patch to address of per-target
--                                      ;       sscf value (53c710)
--ABSOLUTE dsa_temp_target = 0          ; Patch to id for current dsa
--ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command
--                                      ;       saved data pointer
--ABSOLUTE dsa_temp_addr_residual = 0   ; Patch to address of per-command
--                                      ;       current residual code
--ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command
--                                      ; saved residual code
--ABSOLUTE dsa_temp_addr_new_value = 0  ; Address of value for JUMP operand
--ABSOLUTE dsa_temp_addr_array_value = 0        ; Address to copy to
--ABSOLUTE dsa_temp_addr_dsa_value = 0  ; Address of this DSA value
--
--;
--; Once a device has initiated reselection, we need to compare it 
--; against the singly linked list of commands which have disconnected
--; and are pending reselection.  These commands are maintained in 
--; an unordered singly linked list of DSA structures, through the
--; DSA pointers at their 'centers' headed by the reconnect_dsa_head
--; pointer.
--; 
--; To avoid complications in removing commands from the list,
--; I minimize the amount of expensive (at eight operations per
--; addition @ 500-600ns each) pointer operations which must
--; be done in the NCR driver by precomputing them on the 
--; host processor during dsa structure generation.
--;
--; The fixed-up per DSA code knows how to recognize the nexus
--; associated with the corresponding SCSI command, and modifies
--; the source and destination pointers for the MOVE MEMORY 
--; instruction which is executed when reselected_ok is called
--; to remove the command from the list.  Similarly, DSA is 
--; loaded with the address of the next DSA structure and
--; reselected_check_next is called if a failure occurs.
--;
--; Perhaps more concisely, the net effect of the mess is 
--;
--; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, 
--;     src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) {
--;     src = &dsa->next;
--;     if (target_id == dsa->id && target_lun == dsa->lun) {
--;             *dest = *src;
--;             break;
--;         }   
--; }
--;
--; if (!dsa)
--;           error (int_err_unexpected_reselect);
--; else  
--;     longjmp (dsa->jump_resume, 0);
--;
--;     
--
--#if (CHIP != 700) && (CHIP != 70066)
--; Define DSA structure used for mailboxes
--ENTRY dsa_code_template
--dsa_code_template:
--ENTRY dsa_code_begin
--dsa_code_begin:
--; RGH: Don't care about TEMP and DSA here
--      DMODE_MEMORY_TO_NCR
--      MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch
--      DMODE_MEMORY_TO_MEMORY
--#if (CHIP == 710)
--      MOVE MEMORY 4, addr_scratch, saved_dsa
--      ; We are about to go and select the device, so must set SSCF bits
--      MOVE MEMORY 4, dsa_sscf_710, addr_scratch
--#ifdef BIG_ENDIAN
--      MOVE SCRATCH3 TO SFBR
--#else
--      MOVE SCRATCH0 TO SFBR
--#endif
--      MOVE SFBR TO SBCL
--      MOVE MEMORY 4, saved_dsa, addr_dsa
--#else
--      CALL scratch_to_dsa
--#endif
--      CALL select
--; Handle the phase mismatch which may have resulted from the 
--; MOVE FROM dsa_msgout if we returned here.  The CLEAR ATN 
--; may or may not be necessary, and we should update script_asm.pl
--; to handle multiple pieces.
--    CLEAR ATN
--    CLEAR ACK
--
--; Replace second operand with address of JUMP instruction dest operand
--; in schedule table for this DSA.  Becomes dsa_jump_dest in 53c7,8xx.c.
--ENTRY dsa_code_fix_jump
--dsa_code_fix_jump:
--      MOVE MEMORY 4, NOP_insn, 0
--      JUMP select_done
--
--; wrong_dsa loads the DSA register with the value of the dsa_next
--; field.
--;
--wrong_dsa:
--#if (CHIP == 710)
--;                NOTE DSA is corrupt when we arrive here!
--#endif
--;             Patch the MOVE MEMORY INSTRUCTION such that 
--;             the destination address is the address of the OLD 
--;             next pointer.
--;
--      MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 8
--      DMODE_MEMORY_TO_NCR
--;
--;     Move the _contents_ of the next pointer into the DSA register as 
--;     the next I_T_L or I_T_L_Q tupple to check against the established
--;     nexus.
--;
--      MOVE MEMORY 4, dsa_temp_next, addr_scratch
--      DMODE_MEMORY_TO_MEMORY
--#if (CHIP == 710)
--      MOVE MEMORY 4, addr_scratch, saved_dsa
--      MOVE MEMORY 4, saved_dsa, addr_dsa
--#else
--      CALL scratch_to_dsa
--#endif
--      JUMP reselected_check_next
--
--ABSOLUTE dsa_save_data_pointer = 0
--ENTRY dsa_code_save_data_pointer
--dsa_code_save_data_pointer:
--#if (CHIP == 710)
--      ; When we get here, TEMP has been saved in jump_temp+4, DSA is corrupt
--      ; We MUST return with DSA correct
--      MOVE MEMORY 4, jump_temp+4, dsa_temp_addr_saved_pointer
--; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
--      MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
--        CLEAR ACK
--#ifdef DEBUG
--        INT int_debug_saved
--#endif
--      MOVE MEMORY 4, saved_dsa, addr_dsa
--      JUMP jump_temp
--#else
--      DMODE_NCR_TO_MEMORY
--      MOVE MEMORY 4, addr_temp, dsa_temp_addr_saved_pointer
--      DMODE_MEMORY_TO_MEMORY
--; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
--      MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
--        CLEAR ACK
--#ifdef DEBUG
--        INT int_debug_saved
--#endif
--      RETURN
--#endif
--ABSOLUTE dsa_restore_pointers = 0
--ENTRY dsa_code_restore_pointers
--dsa_code_restore_pointers:
--#if (CHIP == 710)
--      ; TEMP and DSA are corrupt when we get here, but who cares!
--      MOVE MEMORY 4, dsa_temp_addr_saved_pointer, jump_temp + 4
--; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
--      MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
--        CLEAR ACK
--      ; Restore DSA, note we don't care about TEMP
--      MOVE MEMORY 4, saved_dsa, addr_dsa
--#ifdef DEBUG
--        INT int_debug_restored
--#endif
--      JUMP jump_temp
--#else
--      DMODE_MEMORY_TO_NCR
--      MOVE MEMORY 4, dsa_temp_addr_saved_pointer, addr_temp
--      DMODE_MEMORY_TO_MEMORY
--; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
--      MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
--        CLEAR ACK
--#ifdef DEBUG
--        INT int_debug_restored
--#endif
--      RETURN
--#endif
+-# mount -t unionfs -o del=/foo none MOUNTPOINT
 -
--ABSOLUTE dsa_check_reselect = 0
--; dsa_check_reselect determines whether or not the current target and
--; lun match the current DSA
--ENTRY dsa_code_check_reselect
--dsa_code_check_reselect:
--#if (CHIP == 710)
--      /* Arrives here with DSA correct */
--      /* Assumes we are always ID 7 */
--      MOVE LCRC TO SFBR               ; LCRC has our ID and his ID bits set
--      JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0x80
--#else
--      MOVE SSID TO SFBR               ; SSID contains 3 bit target ID
--; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
--      JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0xf8
--#endif
--;
--; Hack - move to scratch first, since SFBR is not writeable
--;     via the CPU and hence a MOVE MEMORY instruction.
--;
--      DMODE_MEMORY_TO_NCR
--      MOVE MEMORY 1, reselected_identify, addr_scratch
--      DMODE_MEMORY_TO_MEMORY
--#ifdef BIG_ENDIAN
--      ; BIG ENDIAN ON MVME16x
--      MOVE SCRATCH3 TO SFBR
--#else
--      MOVE SCRATCH0 TO SFBR
--#endif
--; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
--; Are you sure about that?  richard@sleepie.demon.co.uk
--      JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8
--;             Patch the MOVE MEMORY INSTRUCTION such that
--;             the source address is the address of this dsa's
--;             next pointer.
--      MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 4
--      CALL reselected_ok
--#if (CHIP == 710)
--;     Restore DSA following memory moves in reselected_ok
--;     dsa_temp_sync doesn't really care about DSA, but it has an
--;     optional debug INT so a valid DSA is a good idea.
--      MOVE MEMORY 4, saved_dsa, addr_dsa
--#endif
--      CALL dsa_temp_sync      
--; Release ACK on the IDENTIFY message _after_ we've set the synchronous 
--; transfer parameters! 
--      CLEAR ACK
--; Implicitly restore pointers on reselection, so a RETURN
--; will transfer control back to the right spot.
--      CALL REL (dsa_code_restore_pointers)
--      RETURN
--ENTRY dsa_zero
--dsa_zero:
--ENTRY dsa_code_template_end
--dsa_code_template_end:
--
--; Perform sanity check for dsa_fields_start == dsa_code_template_end - 
--; dsa_zero, puke.
--
--ABSOLUTE dsa_fields_start =  0        ; Sanity marker
--                              ;       pad 48 bytes (fix this RSN)
--ABSOLUTE dsa_next = 48                ; len 4 Next DSA
--                              ; del 4 Previous DSA address
--ABSOLUTE dsa_cmnd = 56                ; len 4 Scsi_Cmnd * for this thread.
--ABSOLUTE dsa_select = 60      ; len 4 Device ID, Period, Offset for 
--                              ;       table indirect select
--ABSOLUTE dsa_msgout = 64      ; len 8 table indirect move parameter for 
--                              ;       select message
--ABSOLUTE dsa_cmdout = 72      ; len 8 table indirect move parameter for 
--                              ;       command
--ABSOLUTE dsa_dataout = 80     ; len 4 code pointer for dataout
--ABSOLUTE dsa_datain = 84      ; len 4 code pointer for datain
--ABSOLUTE dsa_msgin = 88               ; len 8 table indirect move for msgin
--ABSOLUTE dsa_status = 96      ; len 8 table indirect move for status byte
--ABSOLUTE dsa_msgout_other = 104       ; len 8 table indirect for normal message out
--                              ; (Synchronous transfer negotiation, etc).
--ABSOLUTE dsa_end = 112
--
--ABSOLUTE schedule = 0                 ; Array of JUMP dsa_begin or JUMP (next),
--                              ; terminated by a call to JUMP wait_reselect
--
--; Linked lists of DSA structures
--ABSOLUTE reconnect_dsa_head = 0       ; Link list of DSAs which can reconnect
--ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing
--                              ; address of reconnect_dsa_head
--
--; These select the source and destination of a MOVE MEMORY instruction
--ABSOLUTE dmode_memory_to_memory = 0x0
--ABSOLUTE dmode_memory_to_ncr = 0x0
--ABSOLUTE dmode_ncr_to_memory = 0x0
--
--ABSOLUTE addr_scratch = 0x0
--ABSOLUTE addr_temp = 0x0
--#if (CHIP == 710)
--ABSOLUTE saved_dsa = 0x0
--ABSOLUTE emulfly = 0x0
--ABSOLUTE addr_dsa = 0x0
--#endif
--#endif /* CHIP != 700 && CHIP != 70066 */
--
--; Interrupts - 
--; MSB indicates type
--; 0   handle error condition
--; 1   handle message 
--; 2   handle normal condition
--; 3   debugging interrupt
--; 4   testing interrupt 
--; Next byte indicates specific error
--
--; XXX not yet implemented, I'm not sure if I want to - 
--; Next byte indicates the routine the error occurred in
--; The LSB indicates the specific place the error occurred
-- 
--ABSOLUTE int_err_unexpected_phase = 0x00000000        ; Unexpected phase encountered
--ABSOLUTE int_err_selected = 0x00010000                ; SELECTED (nee RESELECTED)
--ABSOLUTE int_err_unexpected_reselect = 0x00020000 
--ABSOLUTE int_err_check_condition = 0x00030000 
--ABSOLUTE int_err_no_phase = 0x00040000
--ABSOLUTE int_msg_wdtr = 0x01000000            ; WDTR message received
--ABSOLUTE int_msg_sdtr = 0x01010000            ; SDTR received
--ABSOLUTE int_msg_1 = 0x01020000                       ; single byte special message
--                                              ; received
--
--ABSOLUTE int_norm_select_complete = 0x02000000        ; Select complete, reprogram
--                                              ; registers.
--ABSOLUTE int_norm_reselect_complete = 0x02010000      ; Nexus established
--ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete
--ABSOLUTE int_norm_disconnected = 0x02030000   ; Disconnected 
--ABSOLUTE int_norm_aborted =0x02040000         ; Aborted *dsa
--ABSOLUTE int_norm_reset = 0x02050000          ; Generated BUS reset.
--ABSOLUTE int_norm_emulateintfly = 0x02060000  ; 53C710 Emulated intfly
--ABSOLUTE int_debug_break = 0x03000000         ; Break point
--#ifdef DEBUG
--ABSOLUTE int_debug_scheduled = 0x03010000     ; new I/O scheduled 
--ABSOLUTE int_debug_idle = 0x03020000          ; scheduler is idle
--ABSOLUTE int_debug_dsa_loaded = 0x03030000    ; dsa reloaded
--ABSOLUTE int_debug_reselected = 0x03040000    ; NCR reselected
--ABSOLUTE int_debug_head = 0x03050000          ; issue head overwritten
--ABSOLUTE int_debug_disconnected = 0x03060000  ; disconnected
--ABSOLUTE int_debug_disconnect_msg = 0x03070000        ; got message to disconnect
--ABSOLUTE int_debug_dsa_schedule = 0x03080000  ; in dsa_schedule
--ABSOLUTE int_debug_reselect_check = 0x03090000  ; Check for reselection of DSA
--ABSOLUTE int_debug_reselected_ok = 0x030a0000         ; Reselection accepted
--#endif
--ABSOLUTE int_debug_panic = 0x030b0000         ; Panic driver
--#ifdef DEBUG
--ABSOLUTE int_debug_saved = 0x030c0000                 ; save/restore pointers
--ABSOLUTE int_debug_restored = 0x030d0000
--ABSOLUTE int_debug_sync = 0x030e0000          ; Sanity check synchronous 
--                                              ; parameters. 
--ABSOLUTE int_debug_datain = 0x030f0000                ; going into data in phase 
--                                              ; now.
--ABSOLUTE int_debug_check_dsa = 0x03100000     ; Sanity check DSA against
--                                              ; SDID.
--#endif
+-To insert (add) a branch /foo before /bar:
 -
--ABSOLUTE int_test_1 = 0x04000000              ; Test 1 complete
--ABSOLUTE int_test_2 = 0x04010000              ; Test 2 complete
--ABSOLUTE int_test_3 = 0x04020000              ; Test 3 complete
+-# mount -t unionfs -o remount,add=/bar:/foo none MOUNTPOINT
 -
+-To insert (add) a branch /foo (with the "rw" mode flag) before /bar:
 -
--; These should start with 0x05000000, with low bits incrementing for 
--; each one.
+-# mount -t unionfs -o remount,add=/bar:/foo=rw none MOUNTPOINT
 -
--#ifdef EVENTS
--ABSOLUTE int_EVENT_SELECT = 0
--ABSOLUTE int_EVENT_DISCONNECT = 0
--ABSOLUTE int_EVENT_RESELECT = 0
--ABSOLUTE int_EVENT_COMPLETE = 0
--ABSOLUTE int_EVENT_IDLE = 0
--ABSOLUTE int_EVENT_SELECT_FAILED = 0
--ABSOLUTE int_EVENT_BEFORE_SELECT = 0
--ABSOLUTE int_EVENT_RESELECT_FAILED = 0
--#endif
--                                              
--ABSOLUTE NCR53c7xx_msg_abort = 0      ; Pointer to abort message
--ABSOLUTE NCR53c7xx_msg_reject = 0       ; Pointer to reject message
--ABSOLUTE NCR53c7xx_zero       = 0             ; long with zero in it, use for source
--ABSOLUTE NCR53c7xx_sink = 0           ; long to dump worthless data in
--ABSOLUTE NOP_insn = 0                 ; NOP instruction
--
--; Pointer to message, potentially multi-byte
--ABSOLUTE msg_buf = 0
--
--; Pointer to holding area for reselection information
--ABSOLUTE reselected_identify = 0
--ABSOLUTE reselected_tag = 0
--
--; Request sense command pointer, it's a 6 byte command, should
--; be constant for all commands since we always want 16 bytes of 
--; sense and we don't need to change any fields as we did under 
--; SCSI-I when we actually cared about the LUN field.
--;EXTERNAL NCR53c7xx_sense             ; Request sense command
--
--#if (CHIP != 700) && (CHIP != 70066)
--; dsa_schedule  
--; PURPOSE : after a DISCONNECT message has been received, and pointers
--;     saved, insert the current DSA structure at the head of the 
--;     disconnected queue and fall through to the scheduler.
--;
--; CALLS : OK
--;
--; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list
--;     of disconnected commands
--;
--; MODIFIES : SCRATCH, reconnect_dsa_head
--; 
--; EXITS : always passes control to schedule
--
--ENTRY dsa_schedule
--dsa_schedule:
--#ifdef DEBUG
--    INT int_debug_dsa_schedule
--#endif
+-To insert (add) a branch /foo (in "rw" mode) at the very beginning (i.e., a
+-new highest-priority branch), you can use the above syntax, or use a short
+-hand version as follows:
 -
--;
--; Calculate the address of the next pointer within the DSA 
--; structure of the command that is currently disconnecting
--;
--#if (CHIP == 710)
--    ; Read what should be the current DSA from memory - actual DSA
--    ; register is probably corrupt
--    MOVE MEMORY 4, saved_dsa, addr_scratch
--#else
--    CALL dsa_to_scratch
--#endif
--    MOVE SCRATCH0 + dsa_next TO SCRATCH0
--    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
--    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
--    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
--
--; Point the next field of this DSA structure at the current disconnected 
--; list
--    DMODE_NCR_TO_MEMORY
--    MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8
--    DMODE_MEMORY_TO_MEMORY
--dsa_schedule_insert:
--    MOVE MEMORY 4, reconnect_dsa_head, 0 
--
--; And update the head pointer.
--#if (CHIP == 710)
--    ; Read what should be the current DSA from memory - actual DSA
--    ; register is probably corrupt
--    MOVE MEMORY 4, saved_dsa, addr_scratch
--#else
--    CALL dsa_to_scratch
--#endif
--    DMODE_NCR_TO_MEMORY
--    MOVE MEMORY 4, addr_scratch, reconnect_dsa_head
--    DMODE_MEMORY_TO_MEMORY
--/* Temporarily, see what happens. */
--#ifndef ORIGINAL
--#if (CHIP != 710)
--    MOVE SCNTL2 & 0x7f TO SCNTL2
--#endif
--    CLEAR ACK
--#endif
--#if (CHIP == 710)
--    ; Time to correct DSA following memory move
--    MOVE MEMORY 4, saved_dsa, addr_dsa
--#endif
--    WAIT DISCONNECT
--#ifdef EVENTS
--    INT int_EVENT_DISCONNECT;
--#endif
--#ifdef DEBUG
--    INT int_debug_disconnected
--#endif
--    JUMP schedule
--#endif 
--
--;
--; select
--;
--; PURPOSE : establish a nexus for the SCSI command referenced by DSA.
--;     On success, the current DSA structure is removed from the issue 
--;     queue.  Usually, this is entered as a fall-through from schedule,
--;     although the contingent allegiance handling code will write
--;     the select entry address to the DSP to restart a command as a 
--;     REQUEST SENSE.  A message is sent (usually IDENTIFY, although
--;     additional SDTR or WDTR messages may be sent).  COMMAND OUT
--;     is handled.
--;
--; INPUTS : DSA - SCSI command, issue_dsa_head
--;
--; CALLS : NOT OK
--;
--; MODIFIES : SCRATCH, issue_dsa_head
--;
--; EXITS : on reselection or selection, go to select_failed
--;     otherwise, RETURN so control is passed back to 
--;     dsa_begin.
--;
--
--ENTRY select
--select:
--
--#ifdef EVENTS
--    INT int_EVENT_BEFORE_SELECT
--#endif
+-# mount -t unionfs -o remount,add=/foo none MOUNTPOINT
 -
--#ifdef DEBUG
--    INT int_debug_scheduled
--#endif
--    CLEAR TARGET
--
--; XXX
--;
--; In effect, SELECTION operations are backgrounded, with execution
--; continuing until code which waits for REQ or a fatal interrupt is 
--; encountered.
--;
--; So, for more performance, we could overlap the code which removes 
--; the command from the NCRs issue queue with the selection, but 
--; at this point I don't want to deal with the error recovery.
--;
--
--#if (CHIP != 700) && (CHIP != 70066)
--#if (CHIP == 710)
--    ; Enable selection timer
--#ifdef NO_SELECTION_TIMEOUT
--    MOVE CTEST7 & 0xff TO CTEST7
--#else
--    MOVE CTEST7 & 0xef TO CTEST7
--#endif
--#endif
--    SELECT ATN FROM dsa_select, select_failed
--    JUMP select_msgout, WHEN MSG_OUT
--ENTRY select_msgout
--select_msgout:
--#if (CHIP == 710)
--    ; Disable selection timer
--    MOVE CTEST7 | 0x10 TO CTEST7
--#endif
--    MOVE FROM dsa_msgout, WHEN MSG_OUT
--#else
--ENTRY select_msgout
--    SELECT ATN 0, select_failed
--select_msgout:
--    MOVE 0, 0, WHEN MSGOUT
--#endif
+-To append a branch to the very end (new lowest-priority branch):
 -
--#ifdef EVENTS
--   INT int_EVENT_SELECT
--#endif
--   RETURN
--
--; 
--; select_done
--; 
--; PURPOSE: continue on to normal data transfer; called as the exit 
--;     point from dsa_begin.
--;
--; INPUTS: dsa
--;
--; CALLS: OK
--;
--;
--
--select_done:
--#if (CHIP == 710)
--; NOTE DSA is corrupt when we arrive here!
--    MOVE MEMORY 4, saved_dsa, addr_dsa
--#endif
+-# mount -t unionfs -o remount,add=:/foo none MOUNTPOINT
 -
--#ifdef DEBUG
--ENTRY select_check_dsa
--select_check_dsa:
--    INT int_debug_check_dsa
--#endif
+-To append a branch to the very end (new lowest-priority branch), in
+-read-only mode:
 -
--; After a successful selection, we should get either a CMD phase or 
--; some transfer request negotiation message.
+-# mount -t unionfs -o remount,add=:/foo:ro none MOUNTPOINT
 -
--    JUMP cmdout, WHEN CMD
--    INT int_err_unexpected_phase, WHEN NOT MSG_IN 
+-Finally, to change the mode of one existing branch, say /foo, from read-only
+-to read-write, and change /bar from read-write to read-only:
 -
--select_msg_in:
--    CALL msg_in, WHEN MSG_IN
--    JUMP select_msg_in, WHEN MSG_IN
+-# mount -t unionfs -o remount,mode=/foo=rw,mode=/bar=ro none MOUNTPOINT
 -
--cmdout:
--    INT int_err_unexpected_phase, WHEN NOT CMD
--#if (CHIP == 700)
--    INT int_norm_selected
--#endif
--ENTRY cmdout_cmdout
--cmdout_cmdout:
--#if (CHIP != 700) && (CHIP != 70066)
--    MOVE FROM dsa_cmdout, WHEN CMD
--#else
--    MOVE 0, 0, WHEN CMD
--#endif /* (CHIP != 700) && (CHIP != 70066) */
--
--;
--; data_transfer  
--; other_out
--; other_in
--; other_transfer
--;
--; PURPOSE : handle the main data transfer for a SCSI command in 
--;     several parts.  In the first part, data_transfer, DATA_IN
--;     and DATA_OUT phases are allowed, with the user provided
--;     code (usually dynamically generated based on the scatter/gather
--;     list associated with a SCSI command) called to handle these 
--;     phases.
--;
--;     After control has passed to one of the user provided 
--;     DATA_IN or DATA_OUT routines, back calls are made to 
--;     other_transfer_in or other_transfer_out to handle non-DATA IN
--;     and DATA OUT phases respectively, with the state of the active
--;     data pointer being preserved in TEMP.
--;
--;     On completion, the user code passes control to other_transfer
--;     which causes DATA_IN and DATA_OUT to result in unexpected_phase
--;     interrupts so that data overruns may be trapped.
--;
--; INPUTS : DSA - SCSI command
--;
--; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in
--;     other_transfer
--;
--; MODIFIES : SCRATCH
--;
--; EXITS : if STATUS IN is detected, signifying command completion,
--;     the NCR jumps to command_complete.  If MSG IN occurs, a 
--;     CALL is made to msg_in.  Otherwise, other_transfer runs in 
--;     an infinite loop.
--;     
--
--ENTRY data_transfer
--data_transfer:
--    JUMP cmdout_cmdout, WHEN CMD
--    CALL msg_in, WHEN MSG_IN
--    INT int_err_unexpected_phase, WHEN MSG_OUT
--    JUMP do_dataout, WHEN DATA_OUT
--    JUMP do_datain, WHEN DATA_IN
--    JUMP command_complete, WHEN STATUS
--    JUMP data_transfer
--ENTRY end_data_transfer
--end_data_transfer:
--
--;
--; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain 
--; should be fixed up whenever the nexus changes so it can point to the 
--; correct routine for that command.
--;
--
--#if (CHIP != 700) && (CHIP != 70066)
--; Nasty jump to dsa->dataout
--do_dataout:
--#if (CHIP == 710)
--    MOVE MEMORY 4, saved_dsa, addr_scratch
--#else
--    CALL dsa_to_scratch
--#endif
--    MOVE SCRATCH0 + dsa_dataout TO SCRATCH0   
--    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
--    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
--    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
--    DMODE_NCR_TO_MEMORY
--    MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4
--    DMODE_MEMORY_TO_MEMORY
--dataout_to_jump:
--    MOVE MEMORY 4, 0, dataout_jump + 4 
--#if (CHIP == 710)
--    ; Time to correct DSA following memory move
--    MOVE MEMORY 4, saved_dsa, addr_dsa
--#endif
--dataout_jump:
--    JUMP 0
 -
--; Nasty jump to dsa->dsain
--do_datain:
--#if (CHIP == 710)
--    MOVE MEMORY 4, saved_dsa, addr_scratch
--#else
--    CALL dsa_to_scratch
--#endif
--    MOVE SCRATCH0 + dsa_datain TO SCRATCH0    
--    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
--    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
--    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
--    DMODE_NCR_TO_MEMORY
--    MOVE MEMORY 4, addr_scratch, datain_to_jump + 4
--    DMODE_MEMORY_TO_MEMORY
--ENTRY datain_to_jump
--datain_to_jump:
--    MOVE MEMORY 4, 0, datain_jump + 4
--#if (CHIP == 710)
--    ; Time to correct DSA following memory move
--    MOVE MEMORY 4, saved_dsa, addr_dsa
--#endif
--#ifdef DEBUG
--    INT int_debug_datain
--#endif
--datain_jump:
--    JUMP 0
--#endif /* (CHIP != 700) && (CHIP != 70066) */
+-CACHE CONSISTENCY
+-=================
 -
+-If you modify any file on any of the lower branches directly, while there is
+-a Unionfs 2.0 mounted above any of those branches, you should tell Unionfs
+-to purge its caches and re-get the objects.  To do that, you have to
+-increment the generation number of the superblock using the following
+-command:
 -
--; Note that other_out and other_in loop until a non-data phase
--; is discovered, so we only execute return statements when we
--; can go on to the next data phase block move statement.
+-# mount -t unionfs -o remount,incgen none MOUNTPOINT
 -
--ENTRY other_out
--other_out:
--#if 0
--    INT 0x03ffdead
--#endif
--    INT int_err_unexpected_phase, WHEN CMD
--    JUMP msg_in_restart, WHEN MSG_IN 
--    INT int_err_unexpected_phase, WHEN MSG_OUT
--    INT int_err_unexpected_phase, WHEN DATA_IN
--    JUMP command_complete, WHEN STATUS
--    JUMP other_out, WHEN NOT DATA_OUT
--#if (CHIP == 710)
--; TEMP should be OK, as we got here from a call in the user dataout code.
--#endif
--    RETURN
 -
--ENTRY other_in
--other_in:
--#if 0
--    INT 0x03ffdead
--#endif
--    INT int_err_unexpected_phase, WHEN CMD
--    JUMP msg_in_restart, WHEN MSG_IN 
--    INT int_err_unexpected_phase, WHEN MSG_OUT
--    INT int_err_unexpected_phase, WHEN DATA_OUT
--    JUMP command_complete, WHEN STATUS
--    JUMP other_in, WHEN NOT DATA_IN
--#if (CHIP == 710)
--; TEMP should be OK, as we got here from a call in the user datain code.
--#endif
--    RETURN
--
--
--ENTRY other_transfer
--other_transfer:
--    INT int_err_unexpected_phase, WHEN CMD
--    CALL msg_in, WHEN MSG_IN
--    INT int_err_unexpected_phase, WHEN MSG_OUT
--    INT int_err_unexpected_phase, WHEN DATA_OUT
--    INT int_err_unexpected_phase, WHEN DATA_IN
--    JUMP command_complete, WHEN STATUS
--    JUMP other_transfer
--
--;
--; msg_in_restart
--; msg_in
--; munge_msg
--;
--; PURPOSE : process messages from a target.  msg_in is called when the 
--;     caller hasn't read the first byte of the message.  munge_message
--;     is called when the caller has read the first byte of the message,
--;     and left it in SFBR.  msg_in_restart is called when the caller 
--;     hasn't read the first byte of the message, and wishes RETURN
--;     to transfer control back to the address of the conditional
--;     CALL instruction rather than to the instruction after it.
--;
--;     Various int_* interrupts are generated when the host system
--;     needs to intervene, as is the case with SDTR, WDTR, and
--;     INITIATE RECOVERY messages.
--;
--;     When the host system handles one of these interrupts,
--;     it can respond by reentering at reject_message, 
--;     which rejects the message and returns control to
--;     the caller of msg_in or munge_msg, accept_message
--;     which clears ACK and returns control, or reply_message
--;     which sends the message pointed to by the DSA 
--;     msgout_other table indirect field.
--;
--;     DISCONNECT messages are handled by moving the command
--;     to the reconnect_dsa_queue.
--#if (CHIP == 710)
--; NOTE: DSA should be valid when we get here - we cannot save both it
--;     and TEMP in this routine.
--#endif
--;
--; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg
--;     only)
--;
--; CALLS : NO.  The TEMP register isn't backed up to allow nested calls.
--;
--; MODIFIES : SCRATCH, DSA on DISCONNECT
--;
--; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS,
--;     and normal return from message handlers running under
--;     Linux, control is returned to the caller.  Receipt
--;     of DISCONNECT messages pass control to dsa_schedule.
--;
--ENTRY msg_in_restart
--msg_in_restart:
--; XXX - hackish
--;
--; Since it's easier to debug changes to the statically 
--; compiled code, rather than the dynamically generated 
--; stuff, such as
--;
--;     MOVE x, y, WHEN data_phase
--;     CALL other_z, WHEN NOT data_phase
--;     MOVE x, y, WHEN data_phase
--;
--; I'd like to have certain routines (notably the message handler)
--; restart on the conditional call rather than the next instruction.
--;
--; So, subtract 8 from the return address
--
--    MOVE TEMP0 + 0xf8 TO TEMP0
--    MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY
--    MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY
--    MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY
--
--ENTRY msg_in
--msg_in:
--    MOVE 1, msg_buf, WHEN MSG_IN
--
--munge_msg:
--    JUMP munge_extended, IF 0x01              ; EXTENDED MESSAGE
--    JUMP munge_2, IF 0x20, AND MASK 0xdf      ; two byte message
--;
--; XXX - I've seen a handful of broken SCSI devices which fail to issue
--;     a SAVE POINTERS message before disconnecting in the middle of 
--;     a transfer, assuming that the DATA POINTER will be implicitly 
--;     restored.  
--;
--; Historically, I've often done an implicit save when the DISCONNECT
--; message is processed.  We may want to consider having the option of 
--; doing that here. 
--;
--    JUMP munge_save_data_pointer, IF 0x02     ; SAVE DATA POINTER
--    JUMP munge_restore_pointers, IF 0x03      ; RESTORE POINTERS 
--    JUMP munge_disconnect, IF 0x04            ; DISCONNECT
--    INT int_msg_1, IF 0x07                    ; MESSAGE REJECT
--    INT int_msg_1, IF 0x0f                    ; INITIATE RECOVERY
--#ifdef EVENTS 
--    INT int_EVENT_SELECT_FAILED 
--#endif
--    JUMP reject_message
--
--munge_2:
--    JUMP reject_message
--;
--; The SCSI standard allows targets to recover from transient 
--; error conditions by backing up the data pointer with a 
--; RESTORE POINTERS message.  
--;     
--; So, we must save and restore the _residual_ code as well as 
--; the current instruction pointer.  Because of this messiness,
--; it is simpler to put dynamic code in the dsa for this and to
--; just do a simple jump down there. 
--;
--
--munge_save_data_pointer:
--#if (CHIP == 710)
--    ; We have something in TEMP here, so first we must save that
--    MOVE TEMP0 TO SFBR
--    MOVE SFBR TO SCRATCH0
--    MOVE TEMP1 TO SFBR
--    MOVE SFBR TO SCRATCH1
--    MOVE TEMP2 TO SFBR
--    MOVE SFBR TO SCRATCH2
--    MOVE TEMP3 TO SFBR
--    MOVE SFBR TO SCRATCH3
--    MOVE MEMORY 4, addr_scratch, jump_temp + 4
--    ; Now restore DSA
--    MOVE MEMORY 4, saved_dsa, addr_dsa
--#endif
--    MOVE DSA0 + dsa_save_data_pointer TO SFBR
--    MOVE SFBR TO SCRATCH0
--    MOVE DSA1 + 0xff TO SFBR WITH CARRY
--    MOVE SFBR TO SCRATCH1
--    MOVE DSA2 + 0xff TO SFBR WITH CARRY 
--    MOVE SFBR TO SCRATCH2
--    MOVE DSA3 + 0xff TO SFBR WITH CARRY
--    MOVE SFBR TO SCRATCH3
--
--    DMODE_NCR_TO_MEMORY
--    MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4
--    DMODE_MEMORY_TO_MEMORY
--jump_dsa_save:
--    JUMP 0
--
--munge_restore_pointers:
--#if (CHIP == 710)
--    ; The code at dsa_restore_pointers will RETURN, but we don't care
--    ; about TEMP here, as it will overwrite it anyway.
--#endif
--    MOVE DSA0 + dsa_restore_pointers TO SFBR
--    MOVE SFBR TO SCRATCH0
--    MOVE DSA1 + 0xff TO SFBR WITH CARRY
--    MOVE SFBR TO SCRATCH1
--    MOVE DSA2 + 0xff TO SFBR WITH CARRY
--    MOVE SFBR TO SCRATCH2
--    MOVE DSA3 + 0xff TO SFBR WITH CARRY
--    MOVE SFBR TO SCRATCH3
--
--    DMODE_NCR_TO_MEMORY
--    MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4
--    DMODE_MEMORY_TO_MEMORY
--jump_dsa_restore:
--    JUMP 0
--
--
--munge_disconnect:
--#ifdef DEBUG
--    INT int_debug_disconnect_msg
--#endif
+-For more information, see <http://unionfs.filesystems.org/>.
+diff -Nurb linux-2.6.22-590/Documentation/firmware_class/firmware_sample_firmware_class.c linux-2.6.22-570/Documentation/firmware_class/firmware_sample_firmware_class.c
+--- linux-2.6.22-590/Documentation/firmware_class/firmware_sample_firmware_class.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/firmware_class/firmware_sample_firmware_class.c     2007-07-08 19:32:17.000000000 -0400
+@@ -78,7 +78,6 @@
+                        firmware_loading_show, firmware_loading_store);
+ static ssize_t firmware_data_read(struct kobject *kobj,
+-                                struct bin_attribute *bin_attr,
+                                 char *buffer, loff_t offset, size_t count)
+ {
+       struct class_device *class_dev = to_class_dev(kobj);
+@@ -89,7 +88,6 @@
+       return count;
+ }
+ static ssize_t firmware_data_write(struct kobject *kobj,
+-                                 struct bin_attribute *bin_attr,
+                                  char *buffer, loff_t offset, size_t count)
+ {
+       struct class_device *class_dev = to_class_dev(kobj);
+diff -Nurb linux-2.6.22-590/Documentation/power/freezing-of-tasks.txt linux-2.6.22-570/Documentation/power/freezing-of-tasks.txt
+--- linux-2.6.22-590/Documentation/power/freezing-of-tasks.txt 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/power/freezing-of-tasks.txt 1969-12-31 19:00:00.000000000 -0500
+@@ -1,160 +0,0 @@
+-Freezing of tasks
+-      (C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL
+-
+-I. What is the freezing of tasks?
+-
+-The freezing of tasks is a mechanism by which user space processes and some
+-kernel threads are controlled during hibernation or system-wide suspend (on some
+-architectures).
+-
+-II. How does it work?
+-
+-There are four per-task flags used for that, PF_NOFREEZE, PF_FROZEN, TIF_FREEZE
+-and PF_FREEZER_SKIP (the last one is auxiliary).  The tasks that have
+-PF_NOFREEZE unset (all user space processes and some kernel threads) are
+-regarded as 'freezable' and treated in a special way before the system enters a
+-suspend state as well as before a hibernation image is created (in what follows
+-we only consider hibernation, but the description also applies to suspend).
+-
+-Namely, as the first step of the hibernation procedure the function
+-freeze_processes() (defined in kernel/power/process.c) is called.  It executes
+-try_to_freeze_tasks() that sets TIF_FREEZE for all of the freezable tasks and
+-sends a fake signal to each of them.  A task that receives such a signal and has
+-TIF_FREEZE set, should react to it by calling the refrigerator() function
+-(defined in kernel/power/process.c), which sets the task's PF_FROZEN flag,
+-changes its state to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is
+-cleared for it.  Then, we say that the task is 'frozen' and therefore the set of
+-functions handling this mechanism is called 'the freezer' (these functions are
+-defined in kernel/power/process.c and include/linux/freezer.h).  User space
+-processes are generally frozen before kernel threads.
+-
+-It is not recommended to call refrigerator() directly.  Instead, it is
+-recommended to use the try_to_freeze() function (defined in
+-include/linux/freezer.h), that checks the task's TIF_FREEZE flag and makes the
+-task enter refrigerator() if the flag is set.
+-
+-For user space processes try_to_freeze() is called automatically from the
+-signal-handling code, but the freezable kernel threads need to call it
+-explicitly in suitable places.  The code to do this may look like the following:
 -
--/* 
-- * Before, we overlapped processing with waiting for disconnect, but
-- * debugging was beginning to appear messy.  Temporarily move things
-- * to just before the WAIT DISCONNECT.
-- */
-- 
--#ifdef ORIGINAL
--#if (CHIP == 710)
--; Following clears Unexpected Disconnect bit.  What do we do?
--#else
--    MOVE SCNTL2 & 0x7f TO SCNTL2
--#endif
--    CLEAR ACK
--#endif
+-      do {
+-              hub_events();
+-              wait_event_interruptible(khubd_wait,
+-                                      !list_empty(&hub_event_list));
+-              try_to_freeze();
+-      } while (!signal_pending(current));
+-
+-(from drivers/usb/core/hub.c::hub_thread()).
+-
+-If a freezable kernel thread fails to call try_to_freeze() after the freezer has
+-set TIF_FREEZE for it, the freezing of tasks will fail and the entire
+-hibernation operation will be cancelled.  For this reason, freezable kernel
+-threads must call try_to_freeze() somewhere.
+-
+-After the system memory state has been restored from a hibernation image and
+-devices have been reinitialized, the function thaw_processes() is called in
+-order to clear the PF_FROZEN flag for each frozen task.  Then, the tasks that
+-have been frozen leave refrigerator() and continue running.
+-
+-III. Which kernel threads are freezable?
+-
+-Kernel threads are not freezable by default.  However, a kernel thread may clear
+-PF_NOFREEZE for itself by calling set_freezable() (the resetting of PF_NOFREEZE
+-directly is strongly discouraged).  From this point it is regarded as freezable
+-and must call try_to_freeze() in a suitable place.
+-
+-IV. Why do we do that?
+-
+-Generally speaking, there is a couple of reasons to use the freezing of tasks:
+-
+-1. The principal reason is to prevent filesystems from being damaged after
+-hibernation.  At the moment we have no simple means of checkpointing
+-filesystems, so if there are any modifications made to filesystem data and/or
+-metadata on disks, we cannot bring them back to the state from before the
+-modifications.  At the same time each hibernation image contains some
+-filesystem-related information that must be consistent with the state of the
+-on-disk data and metadata after the system memory state has been restored from
+-the image (otherwise the filesystems will be damaged in a nasty way, usually
+-making them almost impossible to repair).  We therefore freeze tasks that might
+-cause the on-disk filesystems' data and metadata to be modified after the
+-hibernation image has been created and before the system is finally powered off.
+-The majority of these are user space processes, but if any of the kernel threads
+-may cause something like this to happen, they have to be freezable.
+-
+-2. The second reason is to prevent user space processes and some kernel threads
+-from interfering with the suspending and resuming of devices.  A user space
+-process running on a second CPU while we are suspending devices may, for
+-example, be troublesome and without the freezing of tasks we would need some
+-safeguards against race conditions that might occur in such a case.
+-
+-Although Linus Torvalds doesn't like the freezing of tasks, he said this in one
+-of the discussions on LKML (http://lkml.org/lkml/2007/4/27/608):
+-
+-"RJW:> Why we freeze tasks at all or why we freeze kernel threads?
+-
+-Linus: In many ways, 'at all'.
+-
+-I _do_ realize the IO request queue issues, and that we cannot actually do
+-s2ram with some devices in the middle of a DMA.  So we want to be able to
+-avoid *that*, there's no question about that.  And I suspect that stopping
+-user threads and then waiting for a sync is practically one of the easier
+-ways to do so.
+-
+-So in practice, the 'at all' may become a 'why freeze kernel threads?' and
+-freezing user threads I don't find really objectionable."
+-
+-Still, there are kernel threads that may want to be freezable.  For example, if
+-a kernel that belongs to a device driver accesses the device directly, it in
+-principle needs to know when the device is suspended, so that it doesn't try to
+-access it at that time.  However, if the kernel thread is freezable, it will be
+-frozen before the driver's .suspend() callback is executed and it will be
+-thawed after the driver's .resume() callback has run, so it won't be accessing
+-the device while it's suspended.
+-
+-3. Another reason for freezing tasks is to prevent user space processes from
+-realizing that hibernation (or suspend) operation takes place.  Ideally, user
+-space processes should not notice that such a system-wide operation has occurred
+-and should continue running without any problems after the restore (or resume
+-from suspend).  Unfortunately, in the most general case this is quite difficult
+-to achieve without the freezing of tasks.  Consider, for example, a process
+-that depends on all CPUs being online while it's running.  Since we need to
+-disable nonboot CPUs during the hibernation, if this process is not frozen, it
+-may notice that the number of CPUs has changed and may start to work incorrectly
+-because of that.
+-
+-V. Are there any problems related to the freezing of tasks?
+-
+-Yes, there are.
+-
+-First of all, the freezing of kernel threads may be tricky if they depend one
+-on another.  For example, if kernel thread A waits for a completion (in the
+-TASK_UNINTERRUPTIBLE state) that needs to be done by freezable kernel thread B
+-and B is frozen in the meantime, then A will be blocked until B is thawed, which
+-may be undesirable.  That's why kernel threads are not freezable by default.
+-
+-Second, there are the following two problems related to the freezing of user
+-space processes:
+-1. Putting processes into an uninterruptible sleep distorts the load average.
+-2. Now that we have FUSE, plus the framework for doing device drivers in
+-userspace, it gets even more complicated because some userspace processes are
+-now doing the sorts of things that kernel threads do
+-(https://lists.linux-foundation.org/pipermail/linux-pm/2007-May/012309.html).
+-
+-The problem 1. seems to be fixable, although it hasn't been fixed so far.  The
+-other one is more serious, but it seems that we can work around it by using
+-hibernation (and suspend) notifiers (in that case, though, we won't be able to
+-avoid the realization by the user space processes that the hibernation is taking
+-place).
+-
+-There are also problems that the freezing of tasks tends to expose, although
+-they are not directly related to it.  For example, if request_firmware() is
+-called from a device driver's .resume() routine, it will timeout and eventually
+-fail, because the user land process that should respond to the request is frozen
+-at this point.  So, seemingly, the failure is due to the freezing of tasks.
+-Suppose, however, that the firmware file is located on a filesystem accessible
+-only through another device that hasn't been resumed yet.  In that case,
+-request_firmware() will fail regardless of whether or not the freezing of tasks
+-is used.  Consequently, the problem is not really related to the freezing of
+-tasks, since it generally exists anyway.  [The solution to this particular
+-problem is to keep the firmware in memory after it's loaded for the first time
+-and upload if from memory to the device whenever necessary.]
+diff -Nurb linux-2.6.22-590/Documentation/power/kernel_threads.txt linux-2.6.22-570/Documentation/power/kernel_threads.txt
+--- linux-2.6.22-590/Documentation/power/kernel_threads.txt    1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/Documentation/power/kernel_threads.txt    2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,40 @@
++KERNEL THREADS
++
++
++Freezer
++
++Upon entering a suspended state the system will freeze all
++tasks. This is done by delivering pseudosignals. This affects
++kernel threads, too. To successfully freeze a kernel thread
++the thread has to check for the pseudosignal and enter the
++refrigerator. Code to do this looks like this:
++
++      do {
++              hub_events();
++              wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
++              try_to_freeze();
++      } while (!signal_pending(current));
++
++from drivers/usb/core/hub.c::hub_thread()
++
++
++The Unfreezable
++
++Some kernel threads however, must not be frozen. The kernel must
++be able to finish pending IO operations and later on be able to
++write the memory image to disk. Kernel threads needed to do IO
++must stay awake. Such threads must mark themselves unfreezable
++like this:
++
++      /*
++       * This thread doesn't need any user-level access,
++       * so get rid of all our resources.
++       */
++      daemonize("usb-storage");
++
++      current->flags |= PF_NOFREEZE;
++
++from drivers/usb/storage/usb.c::usb_stor_control_thread()
++
++Such drivers are themselves responsible for staying quiet during
++the actual snapshotting.
+diff -Nurb linux-2.6.22-590/Documentation/power/swsusp.txt linux-2.6.22-570/Documentation/power/swsusp.txt
+--- linux-2.6.22-590/Documentation/power/swsusp.txt    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/power/swsusp.txt    2007-07-08 19:32:17.000000000 -0400
+@@ -140,11 +140,21 @@
+ website, and not to the Linux Kernel Mailing List. We are working
+ toward merging suspend2 into the mainline kernel.
+-Q: What is the freezing of tasks and why are we using it?
++Q: A kernel thread must voluntarily freeze itself (call 'refrigerator').
++I found some kernel threads that don't do it, and they don't freeze
++so the system can't sleep. Is this a known behavior?
++
++A: All such kernel threads need to be fixed, one by one. Select the
++place where the thread is safe to be frozen (no kernel semaphores
++should be held at that point and it must be safe to sleep there), and
++add:
++
++       try_to_freeze();
++
++If the thread is needed for writing the image to storage, you should
++instead set the PF_NOFREEZE process flag when creating the thread (and
++be very careful).
+-A: The freezing of tasks is a mechanism by which user space processes and some
+-kernel threads are controlled during hibernation or system-wide suspend (on some
+-architectures).  See freezing-of-tasks.txt for details.
+ Q: What is the difference between "platform" and "shutdown"?
+diff -Nurb linux-2.6.22-590/Documentation/scsi/scsi_fc_transport.txt linux-2.6.22-570/Documentation/scsi/scsi_fc_transport.txt
+--- linux-2.6.22-590/Documentation/scsi/scsi_fc_transport.txt  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/scsi/scsi_fc_transport.txt  1969-12-31 19:00:00.000000000 -0500
+@@ -1,450 +0,0 @@
+-                             SCSI FC Tansport
+-                 =============================================
+-
+-Date:  4/12/2007
+-Kernel Revisions for features:
+-  rports : <<TBS>>
+-  vports : 2.6.22 (? TBD)
+-
+-
+-Introduction
+-============
+-This file documents the features and components of the SCSI FC Transport.
+-It also provides documents the API between the transport and FC LLDDs.
+-The FC transport can be found at:
+-  drivers/scsi/scsi_transport_fc.c
+-  include/scsi/scsi_transport_fc.h
+-  include/scsi/scsi_netlink_fc.h
+-
+-This file is found at Documentation/scsi/scsi_fc_transport.txt
+-
+-
+-FC Remote Ports (rports)
+-========================================================================
+-<< To Be Supplied >>
+-
+-
+-FC Virtual Ports (vports)
+-========================================================================
+-
+-Overview:
+--------------------------------
+-
+-  New FC standards have defined mechanisms which allows for a single physical
+-  port to appear on as multiple communication ports. Using the N_Port Id
+-  Virtualization (NPIV) mechanism, a point-to-point connection to a Fabric
+-  can be assigned more than 1 N_Port_ID.  Each N_Port_ID appears as a
+-  separate port to other endpoints on the fabric, even though it shares one
+-  physical link to the switch for communication. Each N_Port_ID can have a
+-  unique view of the fabric based on fabric zoning and array lun-masking
+-  (just like a normal non-NPIV adapter).  Using the Virtual Fabric (VF)
+-  mechanism, adding a fabric header to each frame allows the port to
+-  interact with the Fabric Port to join multiple fabrics. The port will
+-  obtain an N_Port_ID on each fabric it joins. Each fabric will have its
+-  own unique view of endpoints and configuration parameters.  NPIV may be
+-  used together with VF so that the port can obtain multiple N_Port_IDs
+-  on each virtual fabric.
+-
+-  The FC transport is now recognizing a new object - a vport.  A vport is
+-  an entity that has a world-wide unique World Wide Port Name (wwpn) and
+-  World Wide Node Name (wwnn). The transport also allows for the FC4's to
+-  be specified for the vport, with FCP_Initiator being the primary role
+-  expected. Once instantiated by one of the above methods, it will have a
+-  distinct N_Port_ID and view of fabric endpoints and storage entities.
+-  The fc_host associated with the physical adapter will export the ability
+-  to create vports. The transport will create the vport object within the
+-  Linux device tree, and instruct the fc_host's driver to instantiate the
+-  virtual port. Typically, the driver will create a new scsi_host instance
+-  on the vport, resulting in a unique <H,C,T,L> namespace for the vport.
+-  Thus, whether a FC port is based on a physical port or on a virtual port,
+-  each will appear as a unique scsi_host with its own target and lun space.
+-
+-  Note: At this time, the transport is written to create only NPIV-based
+-    vports. However, consideration was given to VF-based vports and it
+-    should be a minor change to add support if needed.  The remaining
+-    discussion will concentrate on NPIV.
+-
+-  Note: World Wide Name assignment (and uniqueness guarantees) are left
+-    up to an administrative entity controling the vport. For example,
+-    if vports are to be associated with virtual machines, a XEN mgmt
+-    utility would be responsible for creating wwpn/wwnn's for the vport,
+-    using it's own naming authority and OUI. (Note: it already does this
+-    for virtual MAC addresses).
+-
+-
+-Device Trees and Vport Objects:
+--------------------------------
+-
+-  Today, the device tree typically contains the scsi_host object,
+-  with rports and scsi target objects underneath it. Currently the FC
+-  transport creates the vport object and places it under the scsi_host
+-  object corresponding to the physical adapter.  The LLDD will allocate
+-  a new scsi_host for the vport and link it's object under the vport.
+-  The remainder of the tree under the vports scsi_host is the same
+-  as the non-NPIV case. The transport is written currently to easily
+-  allow the parent of the vport to be something other than the scsi_host.
+-  This could be used in the future to link the object onto a vm-specific
+-  device tree. If the vport's parent is not the physical port's scsi_host,
+-  a symbolic link to the vport object will be placed in the physical
+-  port's scsi_host.
+-
+-  Here's what to expect in the device tree :
+-   The typical Physical Port's Scsi_Host:
+-     /sys/devices/.../host17/
+-   and it has the typical decendent tree:
+-     /sys/devices/.../host17/rport-17:0-0/target17:0:0/17:0:0:0:
+-   and then the vport is created on the Physical Port:
+-     /sys/devices/.../host17/vport-17:0-0
+-   and the vport's Scsi_Host is then created:
+-     /sys/devices/.../host17/vport-17:0-0/host18
+-   and then the rest of the tree progresses, such as:
+-     /sys/devices/.../host17/vport-17:0-0/host18/rport-18:0-0/target18:0:0/18:0:0:0:
+-
+-  Here's what to expect in the sysfs tree :
+-   scsi_hosts:
+-     /sys/class/scsi_host/host17                physical port's scsi_host
+-     /sys/class/scsi_host/host18                vport's scsi_host
+-   fc_hosts:
+-     /sys/class/fc_host/host17                  physical port's fc_host
+-     /sys/class/fc_host/host18                  vport's fc_host
+-   fc_vports:
+-     /sys/class/fc_vports/vport-17:0-0          the vport's fc_vport
+-   fc_rports:
+-     /sys/class/fc_remote_ports/rport-17:0-0    rport on the physical port
+-     /sys/class/fc_remote_ports/rport-18:0-0    rport on the vport
+-
+-
+-Vport Attributes:
+--------------------------------
+-
+-  The new fc_vport class object has the following attributes
+-
+-     node_name:                                                 Read_Only
+-       The WWNN of the vport
+-
+-     port_name:                                                 Read_Only
+-       The WWPN of the vport
+-
+-     roles:                                                     Read_Only
+-       Indicates the FC4 roles enabled on the vport.
+-
+-     symbolic_name:                                             Read_Write
+-       A string, appended to the driver's symbolic port name string, which
+-       is registered with the switch to identify the vport. For example,
+-       a hypervisor could set this string to "Xen Domain 2 VM 5 Vport 2",
+-       and this set of identifiers can be seen on switch management screens
+-       to identify the port.
+-
+-     vport_delete:                                              Write_Only
+-       When written with a "1", will tear down the vport.
+-
+-     vport_disable:                                             Write_Only
+-       When written with a "1", will transition the vport to a disabled.
+-       state.  The vport will still be instantiated with the Linux kernel,
+-       but it will not be active on the FC link.
+-       When written with a "0", will enable the vport.
+-
+-     vport_last_state:                                          Read_Only
+-       Indicates the previous state of the vport.  See the section below on
+-       "Vport States".
+-
+-     vport_state:                                               Read_Only
+-       Indicates the state of the vport.  See the section below on
+-       "Vport States".
+-
+-     vport_type:                                                Read_Only
+-       Reflects the FC mechanism used to create the virtual port.
+-       Only NPIV is supported currently.
+-
+-
+-  For the fc_host class object, the following attributes are added for vports:
+-
+-     max_npiv_vports:                                           Read_Only
+-       Indicates the maximum number of NPIV-based vports that the
+-       driver/adapter can support on the fc_host.
+-
+-     npiv_vports_inuse:                                         Read_Only
+-       Indicates how many NPIV-based vports have been instantiated on the
+-       fc_host.
+-
+-     vport_create:                                              Write_Only
+-       A "simple" create interface to instantiate a vport on an fc_host.
+-       A "<WWPN>:<WWNN>" string is written to the attribute. The transport
+-       then instantiates the vport object and calls the LLDD to create the
+-       vport with the role of FCP_Initiator.  Each WWN is specified as 16
+-       hex characters and may *not* contain any prefixes (e.g. 0x, x, etc).
+-
+-     vport_delete:                                              Write_Only
+-        A "simple" delete interface to teardown a vport. A "<WWPN>:<WWNN>"
+-        string is written to the attribute. The transport will locate the
+-        vport on the fc_host with the same WWNs and tear it down.  Each WWN
+-        is specified as 16 hex characters and may *not* contain any prefixes
+-        (e.g. 0x, x, etc).
+-
+-
+-Vport States:
+--------------------------------
+-
+-  Vport instantiation consists of two parts:
+-    - Creation with the kernel and LLDD. This means all transport and
+-      driver data structures are built up, and device objects created.
+-      This is equivalent to a driver "attach" on an adapter, which is
+-      independent of the adapter's link state.
+-    - Instantiation of the vport on the FC link via ELS traffic, etc.
+-      This is equivalent to a "link up" and successfull link initialization.
+-  Futher information can be found in the interfaces section below for
+-  Vport Creation.
+-
+-  Once a vport has been instantiated with the kernel/LLDD, a vport state
+-  can be reported via the sysfs attribute. The following states exist:
+-
+-    FC_VPORT_UNKNOWN            - Unknown
+-      An temporary state, typically set only while the vport is being
+-      instantiated with the kernel and LLDD.
+-
+-    FC_VPORT_ACTIVE             - Active
+-      The vport has been successfully been created on the FC link.
+-      It is fully functional.
+-
+-    FC_VPORT_DISABLED           - Disabled
+-      The vport instantiated, but "disabled". The vport is not instantiated
+-      on the FC link. This is equivalent to a physical port with the
+-      link "down".
+-
+-    FC_VPORT_LINKDOWN           - Linkdown
+-      The vport is not operational as the physical link is not operational.
+-
+-    FC_VPORT_INITIALIZING       - Initializing
+-      The vport is in the process of instantiating on the FC link.
+-      The LLDD will set this state just prior to starting the ELS traffic
+-      to create the vport. This state will persist until the vport is
+-      successfully created (state becomes FC_VPORT_ACTIVE) or it fails
+-      (state is one of the values below).  As this state is transitory,
+-      it will not be preserved in the "vport_last_state".
+-
+-    FC_VPORT_NO_FABRIC_SUPP     - No Fabric Support
+-      The vport is not operational. One of the following conditions were
+-      encountered:
+-       - The FC topology is not Point-to-Point
+-       - The FC port is not connected to an F_Port
+-       - The F_Port has indicated that NPIV is not supported.
+-
+-    FC_VPORT_NO_FABRIC_RSCS     - No Fabric Resources
+-      The vport is not operational. The Fabric failed FDISC with a status
+-      indicating that it does not have sufficient resources to complete
+-      the operation.
+-
+-    FC_VPORT_FABRIC_LOGOUT      - Fabric Logout
+-      The vport is not operational. The Fabric has LOGO'd the N_Port_ID
+-      associated with the vport.
+-
+-    FC_VPORT_FABRIC_REJ_WWN     - Fabric Rejected WWN
+-      The vport is not operational. The Fabric failed FDISC with a status
+-      indicating that the WWN's are not valid.
+-
+-    FC_VPORT_FAILED             - VPort Failed
+-      The vport is not operational. This is a catchall for all other
+-      error conditions.
+-
+-
+-  The following state table indicates the different state transitions:
+-
+-    State              Event                            New State
+-    --------------------------------------------------------------------
+-     n/a                Initialization                  Unknown
+-    Unknown:            Link Down                       Linkdown
+-                        Link Up & Loop                  No Fabric Support
+-                        Link Up & no Fabric             No Fabric Support
+-                        Link Up & FLOGI response        No Fabric Support
+-                          indicates no NPIV support
+-                        Link Up & FDISC being sent      Initializing
+-                        Disable request                 Disable
+-    Linkdown:           Link Up                         Unknown
+-    Initializing:       FDISC ACC                       Active
+-                        FDISC LS_RJT w/ no resources    No Fabric Resources
+-                        FDISC LS_RJT w/ invalid         Fabric Rejected WWN
+-                          pname or invalid nport_id
+-                        FDISC LS_RJT failed for         Vport Failed
+-                          other reasons
+-                        Link Down                       Linkdown
+-                        Disable request                 Disable
+-    Disable:            Enable request                  Unknown
+-    Active:             LOGO received from fabric       Fabric Logout
+-                        Link Down                       Linkdown
+-                        Disable request                 Disable
+-    Fabric Logout:      Link still up                   Unknown
+-
+-         The following 4 error states all have the same transitions:
+-    No Fabric Support:
+-    No Fabric Resources:
+-    Fabric Rejected WWN:
+-    Vport Failed:
+-                        Disable request                 Disable
+-                        Link goes down                  Linkdown
+-
+-
+-Transport <-> LLDD Interfaces :
+--------------------------------
+-
+-Vport support by LLDD:
+-
+-  The LLDD indicates support for vports by supplying a vport_create()
+-  function in the transport template.  The presense of this function will
+-  cause the creation of the new attributes on the fc_host.  As part of
+-  the physical port completing its initialization relative to the
+-  transport, it should set the max_npiv_vports attribute to indicate the
+-  maximum number of vports the driver and/or adapter supports.
+-
+-
+-Vport Creation:
+-
+-  The LLDD vport_create() syntax is:
+-
+-      int vport_create(struct fc_vport *vport, bool disable)
+-
+-    where:
+-      vport:    Is the newly allocated vport object
+-      disable:  If "true", the vport is to be created in a disabled stated.
+-                If "false", the vport is to be enabled upon creation.
+-
+-  When a request is made to create a new vport (via sgio/netlink, or the
+-  vport_create fc_host attribute), the transport will validate that the LLDD
+-  can support another vport (e.g. max_npiv_vports > npiv_vports_inuse).
+-  If not, the create request will be failed.  If space remains, the transport
+-  will increment the vport count, create the vport object, and then call the
+-  LLDD's vport_create() function with the newly allocated vport object.
+-
+-  As mentioned above, vport creation is divided into two parts:
+-    - Creation with the kernel and LLDD. This means all transport and
+-      driver data structures are built up, and device objects created.
+-      This is equivalent to a driver "attach" on an adapter, which is
+-      independent of the adapter's link state.
+-    - Instantiation of the vport on the FC link via ELS traffic, etc.
+-      This is equivalent to a "link up" and successfull link initialization.
+-
+-  The LLDD's vport_create() function will not synchronously wait for both
+-  parts to be fully completed before returning. It must validate that the
+-  infrastructure exists to support NPIV, and complete the first part of
+-  vport creation (data structure build up) before returning.  We do not
+-  hinge vport_create() on the link-side operation mainly because:
+-    - The link may be down. It is not a failure if it is. It simply
+-      means the vport is in an inoperable state until the link comes up.
+-      This is consistent with the link bouncing post vport creation.
+-    - The vport may be created in a disabled state.
+-    - This is consistent with a model where:  the vport equates to a
+-      FC adapter. The vport_create is synonymous with driver attachment
+-      to the adapter, which is independent of link state.
+-
+-    Note: special error codes have been defined to delineate infrastructure
+-      failure cases for quicker resolution.
+-
+-  The expected behavior for the LLDD's vport_create() function is:
+-    - Validate Infrastructure:
+-        - If the driver or adapter cannot support another vport, whether
+-            due to improper firmware, (a lie about) max_npiv, or a lack of
+-            some other resource - return VPCERR_UNSUPPORTED.
+-        - If the driver validates the WWN's against those already active on
+-            the adapter and detects an overlap - return VPCERR_BAD_WWN.
+-        - If the driver detects the topology is loop, non-fabric, or the
+-            FLOGI did not support NPIV - return VPCERR_NO_FABRIC_SUPP.
+-    - Allocate data structures. If errors are encountered, such as out
+-        of memory conditions, return the respective negative Exxx error code.
+-    - If the role is FCP Initiator, the LLDD is to :
+-        - Call scsi_host_alloc() to allocate a scsi_host for the vport.
+-        - Call scsi_add_host(new_shost, &vport->dev) to start the scsi_host
+-          and bind it as a child of the vport device.
+-        - Initializes the fc_host attribute values.
+-    - Kick of further vport state transitions based on the disable flag and
+-        link state - and return success (zero).
+-
+-  LLDD Implementers Notes:
+-  - It is suggested that there be a different fc_function_templates for
+-    the physical port and the virtual port.  The physical port's template
+-    would have the vport_create, vport_delete, and vport_disable functions,
+-    while the vports would not.
+-  - It is suggested that there be different scsi_host_templates
+-    for the physical port and virtual port. Likely, there are driver
+-    attributes, embedded into the scsi_host_template, that are applicable
+-    for the physical port only (link speed, topology setting, etc). This
+-    ensures that the attributes are applicable to the respective scsi_host.
+-
+-
+-Vport Disable/Enable:
+-
+-  The LLDD vport_disable() syntax is:
+-
+-      int vport_disable(struct fc_vport *vport, bool disable)
+-
+-    where:
+-      vport:    Is vport to to be enabled or disabled
+-      disable:  If "true", the vport is to be disabled.
+-                If "false", the vport is to be enabled.
+-
+-  When a request is made to change the disabled state on a vport, the
+-  transport will validate the request against the existing vport state.
+-  If the request is to disable and the vport is already disabled, the
+-  request will fail. Similarly, if the request is to enable, and the
+-  vport is not in a disabled state, the request will fail.  If the request
+-  is valid for the vport state, the transport will call the LLDD to
+-  change the vport's state.
+-
+-  Within the LLDD, if a vport is disabled, it remains instantiated with
+-  the kernel and LLDD, but it is not active or visible on the FC link in
+-  any way. (see Vport Creation and the 2 part instantiation discussion).
+-  The vport will remain in this state until it is deleted or re-enabled.
+-  When enabling a vport, the LLDD reinstantiates the vport on the FC
+-  link - essentially restarting the LLDD statemachine (see Vport States
+-  above).
+-
+-
+-Vport Deletion:
+-
+-  The LLDD vport_delete() syntax is:
+-
+-      int vport_delete(struct fc_vport *vport)
+-
+-    where:
+-      vport:    Is vport to delete
+-
+-  When a request is made to delete a vport (via sgio/netlink, or via the
+-  fc_host or fc_vport vport_delete attributes), the transport will call
+-  the LLDD to terminate the vport on the FC link, and teardown all other
+-  datastructures and references.  If the LLDD completes successfully,
+-  the transport will teardown the vport objects and complete the vport
+-  removal.  If the LLDD delete request fails, the vport object will remain,
+-  but will be in an indeterminate state.
+-
+-  Within the LLDD, the normal code paths for a scsi_host teardown should
+-  be followed. E.g. If the vport has a FCP Initiator role, the LLDD
+-  will call fc_remove_host() for the vports scsi_host, followed by
+-  scsi_remove_host() and scsi_host_put() for the vports scsi_host.
+-
+-
+-Other:
+-  fc_host port_type attribute:
+-    There is a new fc_host port_type value - FC_PORTTYPE_NPIV. This value
+-    must be set on all vport-based fc_hosts.  Normally, on a physical port,
+-    the port_type attribute would be set to NPORT, NLPORT, etc based on the
+-    topology type and existence of the fabric. As this is not applicable to
+-    a vport, it makes more sense to report the FC mechanism used to create
+-    the vport.
+-
+-  Driver unload:
+-    FC drivers are required to call fc_remove_host() prior to calling
+-    scsi_remove_host().  This allows the fc_host to tear down all remote
+-    ports prior the scsi_host being torn down.  The fc_remove_host() call
+-    was updated to remove all vports for the fc_host as well.
+-
+-
+-Credits
+-=======
+-The following people have contributed to this document:
 -
--#if (CHIP != 700) && (CHIP != 70066)
--    JUMP dsa_schedule
--#else
--    WAIT DISCONNECT
--    INT int_norm_disconnected
--#endif
 -
--munge_extended:
--    CLEAR ACK
--    INT int_err_unexpected_phase, WHEN NOT MSG_IN
--    MOVE 1, msg_buf + 1, WHEN MSG_IN
--    JUMP munge_extended_2, IF 0x02
--    JUMP munge_extended_3, IF 0x03 
--    JUMP reject_message
--
--munge_extended_2:
--    CLEAR ACK
--    MOVE 1, msg_buf + 2, WHEN MSG_IN
--    JUMP reject_message, IF NOT 0x02  ; Must be WDTR
--    CLEAR ACK
--    MOVE 1, msg_buf + 3, WHEN MSG_IN
--    INT int_msg_wdtr
--
--munge_extended_3:
--    CLEAR ACK
--    MOVE 1, msg_buf + 2, WHEN MSG_IN
--    JUMP reject_message, IF NOT 0x01  ; Must be SDTR
--    CLEAR ACK
--    MOVE 2, msg_buf + 3, WHEN MSG_IN
--    INT int_msg_sdtr
--
--ENTRY reject_message
--reject_message:
--    SET ATN
--    CLEAR ACK
--    MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT
--    RETURN
--
--ENTRY accept_message
--accept_message:
--    CLEAR ATN
--    CLEAR ACK
--    RETURN
--
--ENTRY respond_message
--respond_message:
--    SET ATN
--    CLEAR ACK
--    MOVE FROM dsa_msgout_other, WHEN MSG_OUT
--    RETURN
--
--;
--; command_complete
--;
--; PURPOSE : handle command termination when STATUS IN is detected by reading
--;     a status byte followed by a command termination message. 
--;
--;     Normal termination results in an INTFLY instruction, and 
--;     the host system can pick out which command terminated by 
--;     examining the MESSAGE and STATUS buffers of all currently 
--;     executing commands;
--;
--;     Abnormal (CHECK_CONDITION) termination results in an
--;     int_err_check_condition interrupt so that a REQUEST SENSE
--;     command can be issued out-of-order so that no other command
--;     clears the contingent allegiance condition.
--;     
--;
--; INPUTS : DSA - command      
--;
--; CALLS : OK
--;
--; EXITS : On successful termination, control is passed to schedule.
--;     On abnormal termination, the user will usually modify the 
--;     DSA fields and corresponding buffers and return control
--;     to select.
--;
--
--ENTRY command_complete
--command_complete:
--    MOVE FROM dsa_status, WHEN STATUS
--#if (CHIP != 700) && (CHIP != 70066)
--    MOVE SFBR TO SCRATCH0             ; Save status
--#endif /* (CHIP != 700) && (CHIP != 70066) */
--ENTRY command_complete_msgin
--command_complete_msgin:
--    MOVE FROM dsa_msgin, WHEN MSG_IN
--; Indicate that we should be expecting a disconnect
--#if (CHIP != 710)
--    MOVE SCNTL2 & 0x7f TO SCNTL2
--#else
--    ; Above code cleared the Unexpected Disconnect bit, what do we do?
--#endif
--    CLEAR ACK
--#if (CHIP != 700) && (CHIP != 70066)
--    WAIT DISCONNECT
--
--;
--; The SCSI specification states that when a UNIT ATTENTION condition
--; is pending, as indicated by a CHECK CONDITION status message,
--; the target shall revert to asynchronous transfers.  Since
--; synchronous transfers parameters are maintained on a per INITIATOR/TARGET 
--; basis, and returning control to our scheduler could work on a command
--; running on another lun on that target using the old parameters, we must
--; interrupt the host processor to get them changed, or change them ourselves.
--;
--; Once SCSI-II tagged queueing is implemented, things will be even more
--; hairy, since contingent allegiance conditions exist on a per-target/lun
--; basis, and issuing a new command with a different tag would clear it.
--; In these cases, we must interrupt the host processor to get a request 
--; added to the HEAD of the queue with the request sense command, or we
--; must automatically issue the request sense command.
 -
--#if 0
--    MOVE SCRATCH0 TO SFBR                     
--    JUMP command_failed, IF 0x02
--#endif
--#if (CHIP == 710)
--#if defined(MVME16x_INTFLY)
--; For MVME16x (ie CHIP=710) we will force an INTFLY by triggering a software
--; interrupt (SW7).  We can use SCRATCH, as we are about to jump to
--; schedule, which corrupts it anyway.  Will probably remove this later,
--; but want to check performance effects first.
--
--#define INTFLY_ADDR     0xfff40070
--
--    MOVE 0 TO SCRATCH0
--    MOVE 0x80 TO SCRATCH1
--    MOVE 0 TO SCRATCH2
--    MOVE 0 TO SCRATCH3
--    MOVE MEMORY 4, addr_scratch, INTFLY_ADDR
--#else
--    INT int_norm_emulateintfly
--#endif
--#else
--    INTFLY
--#endif
--#endif /* (CHIP != 700) && (CHIP != 70066) */
--#if (CHIP == 710)
--    ; Time to correct DSA following memory move
--    MOVE MEMORY 4, saved_dsa, addr_dsa
--#endif
--#ifdef EVENTS
--    INT int_EVENT_COMPLETE
--#endif
--#if (CHIP != 700) && (CHIP != 70066)
--    JUMP schedule
--command_failed:
--    INT int_err_check_condition
--#else
--    INT int_norm_command_complete
--#endif
 -
--;
--; wait_reselect
--;
--; PURPOSE : This is essentially the idle routine, where control lands
--;     when there are no new processes to schedule.  wait_reselect
--;     waits for reselection, selection, and new commands.
--;
--;     When a successful reselection occurs, with the aid 
--;     of fixed up code in each DSA, wait_reselect walks the 
--;     reconnect_dsa_queue, asking each dsa if the target ID
--;     and LUN match its.
--;
--;     If a match is found, a call is made back to reselected_ok,
--;     which through the miracles of self modifying code, extracts
--;     the found DSA from the reconnect_dsa_queue and then 
--;     returns control to the DSAs thread of execution.
--;
--; INPUTS : NONE
--;
--; CALLS : OK
--;
--; MODIFIES : DSA,
--;
--; EXITS : On successful reselection, control is returned to the 
--;     DSA which called reselected_ok.  If the WAIT RESELECT
--;     was interrupted by a new commands arrival signaled by 
--;     SIG_P, control is passed to schedule.  If the NCR is 
--;     selected, the host system is interrupted with an 
--;     int_err_selected which is usually responded to by
--;     setting DSP to the target_abort address.
--
--ENTRY wait_reselect
--wait_reselect:
--#ifdef EVENTS
--    int int_EVENT_IDLE
--#endif
--#ifdef DEBUG
--    int int_debug_idle
--#endif
--    WAIT RESELECT wait_reselect_failed
 -
--reselected:
--#ifdef EVENTS
--    int int_EVENT_RESELECT
--#endif
--    CLEAR TARGET
--    DMODE_MEMORY_TO_MEMORY
--    ; Read all data needed to reestablish the nexus - 
--    MOVE 1, reselected_identify, WHEN MSG_IN
--    ; We used to CLEAR ACK here.
--#if (CHIP != 700) && (CHIP != 70066)
--#ifdef DEBUG
--    int int_debug_reselected
--#endif
 -
--    ; Point DSA at the current head of the disconnected queue.
--    DMODE_MEMORY_TO_NCR
--    MOVE MEMORY 4, reconnect_dsa_head, addr_scratch
--    DMODE_MEMORY_TO_MEMORY
--#if (CHIP == 710)
--    MOVE MEMORY 4, addr_scratch, saved_dsa
--#else
--    CALL scratch_to_dsa
--#endif
+-James Smart
+-james.smart@emulex.com
 -
--    ; Fix the update-next pointer so that the reconnect_dsa_head
--    ; pointer is the one that will be updated if this DSA is a hit 
--    ; and we remove it from the queue.
+diff -Nurb linux-2.6.22-590/Documentation/sysctl/kernel.txt linux-2.6.22-570/Documentation/sysctl/kernel.txt
+--- linux-2.6.22-590/Documentation/sysctl/kernel.txt   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/sysctl/kernel.txt   2007-07-08 19:32:17.000000000 -0400
+@@ -29,7 +29,6 @@
+ - java-interpreter            [ binfmt_java, obsolete ]
+ - kstack_depth_to_print       [ X86 only ]
+ - l2cr                        [ PPC only ]
+-- mmap_min_addr
+ - modprobe                    ==> Documentation/kmod.txt
+ - msgmax
+ - msgmnb
+@@ -179,19 +178,6 @@
+ ==============================================================
+-mmap_min_addr
 -
--    MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok_patch + 8
--#if (CHIP == 710)
--    ; Time to correct DSA following memory move
--    MOVE MEMORY 4, saved_dsa, addr_dsa
--#endif
+-This file indicates the amount of address space  which a user process will be
+-restricted from mmaping.  Since kernel null dereference bugs could
+-accidentally operate based on the information in the first couple of pages of
+-memory userspace processes should not be allowed to write to them.  By default
+-this value is set to 0 and no protections will be enforced by the security
+-module.  Setting this value to something like 64k will allow the vast majority
+-of applications to work correctly and provide defense in depth against future
+-potential kernel bugs.
 -
--ENTRY reselected_check_next
--reselected_check_next:
--#ifdef DEBUG
--    INT int_debug_reselect_check
--#endif
--    ; Check for a NULL pointer.
--    MOVE DSA0 TO SFBR
--    JUMP reselected_not_end, IF NOT 0
--    MOVE DSA1 TO SFBR
--    JUMP reselected_not_end, IF NOT 0
--    MOVE DSA2 TO SFBR
--    JUMP reselected_not_end, IF NOT 0
--    MOVE DSA3 TO SFBR
--    JUMP reselected_not_end, IF NOT 0
--    INT int_err_unexpected_reselect
--
--reselected_not_end:
--    ;
--    ; XXX the ALU is only eight bits wide, and the assembler
--    ; wont do the dirt work for us.  As long as dsa_check_reselect
--    ; is negative, we need to sign extend with 1 bits to the full
--    ; 32 bit width of the address.
--    ;
--    ; A potential work around would be to have a known alignment 
--    ; of the DSA structure such that the base address plus 
--    ; dsa_check_reselect doesn't require carrying from bytes 
--    ; higher than the LSB.
--    ;
--
--    MOVE DSA0 TO SFBR
--    MOVE SFBR + dsa_check_reselect TO SCRATCH0
--    MOVE DSA1 TO SFBR
--    MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY
--    MOVE DSA2 TO SFBR
--    MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY
--    MOVE DSA3 TO SFBR
--    MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY
--
--    DMODE_NCR_TO_MEMORY
--    MOVE MEMORY 4, addr_scratch, reselected_check + 4
--    DMODE_MEMORY_TO_MEMORY
--#if (CHIP == 710)
--    ; Time to correct DSA following memory move
--    MOVE MEMORY 4, saved_dsa, addr_dsa
--#endif
--reselected_check:
--    JUMP 0
--
--
--;
--;
--#if (CHIP == 710)
--; We have problems here - the memory move corrupts TEMP and DSA.  This
--; routine is called from DSA code, and patched from many places.  Scratch
--; is probably free when it is called.
--; We have to:
--;   copy temp to scratch, one byte at a time
--;   write scratch to patch a jump in place of the return
--;   do the move memory
--;   jump to the patched in return address
--; DSA is corrupt when we get here, and can be left corrupt
--
--ENTRY reselected_ok
--reselected_ok:
--    MOVE TEMP0 TO SFBR
--    MOVE SFBR TO SCRATCH0
--    MOVE TEMP1 TO SFBR
--    MOVE SFBR TO SCRATCH1
--    MOVE TEMP2 TO SFBR
--    MOVE SFBR TO SCRATCH2
--    MOVE TEMP3 TO SFBR
--    MOVE SFBR TO SCRATCH3
--    MOVE MEMORY 4, addr_scratch, reselected_ok_jump + 4
--reselected_ok_patch:
--    MOVE MEMORY 4, 0, 0
--reselected_ok_jump:
--    JUMP 0
--#else
--ENTRY reselected_ok
--reselected_ok:
--reselected_ok_patch:
--    MOVE MEMORY 4, 0, 0                               ; Patched : first word
--                                              ;       is address of 
--                                              ;       successful dsa_next
--                                              ; Second word is last 
--                                              ;       unsuccessful dsa_next,
--                                              ;       starting with 
--                                              ;       dsa_reconnect_head
--    ; We used to CLEAR ACK here.
--#ifdef DEBUG
--    INT int_debug_reselected_ok
--#endif
--#ifdef DEBUG
--    INT int_debug_check_dsa
--#endif
--    RETURN                                    ; Return control to where
--#endif
--#else
--    INT int_norm_reselected
--#endif /* (CHIP != 700) && (CHIP != 70066) */
--
--selected:
--    INT int_err_selected;
--
--;
--; A select or reselect failure can be caused by one of two conditions : 
--; 1.  SIG_P was set.  This will be the case if the user has written
--;     a new value to a previously NULL head of the issue queue.
--;
--; 2.  The NCR53c810 was selected or reselected by another device.
--;
--; 3.  The bus was already busy since we were selected or reselected
--;     before starting the command.
--
--wait_reselect_failed:
--#ifdef EVENTS 
--      INT int_EVENT_RESELECT_FAILED
--#endif
--; Check selected bit.  
--#if (CHIP == 710)
--    ; Must work out how to tell if we are selected....
--#else
--    MOVE SIST0 & 0x20 TO SFBR
--    JUMP selected, IF 0x20
--#endif
--; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
--    MOVE CTEST2 & 0x40 TO SFBR        
--    JUMP schedule, IF 0x40
--; Check connected bit.  
--; FIXME: this needs to change if we support target mode
--    MOVE ISTAT & 0x08 TO SFBR
--    JUMP reselected, IF 0x08
--; FIXME : Something bogus happened, and we shouldn't fail silently.
--#if 0
--    JUMP schedule
--#else
--    INT int_debug_panic
--#endif
+-==============================================================
 -
+ osrelease, ostype & version:
+ # cat osrelease
+diff -Nurb linux-2.6.22-590/Documentation/sysfs-rules.txt linux-2.6.22-570/Documentation/sysfs-rules.txt
+--- linux-2.6.22-590/Documentation/sysfs-rules.txt     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Documentation/sysfs-rules.txt     1969-12-31 19:00:00.000000000 -0500
+@@ -1,166 +0,0 @@
+-Rules on how to access information in the Linux kernel sysfs
+-
+-The kernel exported sysfs exports internal kernel implementation-details
+-and depends on internal kernel structures and layout. It is agreed upon
+-by the kernel developers that the Linux kernel does not provide a stable
+-internal API. As sysfs is a direct export of kernel internal
+-structures, the sysfs interface can not provide a stable interface eighter,
+-it may always change along with internal kernel changes.
+-
+-To minimize the risk of breaking users of sysfs, which are in most cases
+-low-level userspace applications, with a new kernel release, the users
+-of sysfs must follow some rules to use an as abstract-as-possible way to
+-access this filesystem. The current udev and HAL programs already
+-implement this and users are encouraged to plug, if possible, into the
+-abstractions these programs provide instead of accessing sysfs
+-directly.
+-
+-But if you really do want or need to access sysfs directly, please follow
+-the following rules and then your programs should work with future
+-versions of the sysfs interface.
+-
+-- Do not use libsysfs
+-  It makes assumptions about sysfs which are not true. Its API does not
+-  offer any abstraction, it exposes all the kernel driver-core
+-  implementation details in its own API. Therefore it is not better than
+-  reading directories and opening the files yourself.
+-  Also, it is not actively maintained, in the sense of reflecting the
+-  current kernel-development. The goal of providing a stable interface
+-  to sysfs has failed, it causes more problems, than it solves. It
+-  violates many of the rules in this document.
+-
+-- sysfs is always at /sys
+-  Parsing /proc/mounts is a waste of time. Other mount points are a
+-  system configuration bug you should not try to solve. For test cases,
+-  possibly support a SYSFS_PATH environment variable to overwrite the
+-  applications behavior, but never try to search for sysfs. Never try
+-  to mount it, if you are not an early boot script.
+-
+-- devices are only "devices"
+-  There is no such thing like class-, bus-, physical devices,
+-  interfaces, and such that you can rely on in userspace. Everything is
+-  just simply a "device". Class-, bus-, physical, ... types are just
+-  kernel implementation details, which should not be expected by
+-  applications that look for devices in sysfs.
+-
+-  The properties of a device are:
+-    o devpath (/devices/pci0000:00/0000:00:1d.1/usb2/2-2/2-2:1.0)
+-      - identical to the DEVPATH value in the event sent from the kernel
+-        at device creation and removal
+-      - the unique key to the device at that point in time
+-      - the kernels path to the device-directory without the leading
+-        /sys, and always starting with with a slash
+-      - all elements of a devpath must be real directories. Symlinks
+-        pointing to /sys/devices must always be resolved to their real
+-        target, and the target path must be used to access the device.
+-        That way the devpath to the device matches the devpath of the
+-        kernel used at event time.
+-      - using or exposing symlink values as elements in a devpath string
+-        is a bug in the application
+-
+-    o kernel name (sda, tty, 0000:00:1f.2, ...)
+-      - a directory name, identical to the last element of the devpath
+-      - applications need to handle spaces and characters like '!' in
+-        the name
+-
+-    o subsystem (block, tty, pci, ...)
+-      - simple string, never a path or a link
+-      - retrieved by reading the "subsystem"-link and using only the
+-        last element of the target path
+-
+-    o driver (tg3, ata_piix, uhci_hcd)
+-      - a simple string, which may contain spaces, never a path or a
+-        link
+-      - it is retrieved by reading the "driver"-link and using only the
+-        last element of the target path
+-      - devices which do not have "driver"-link, just do not have a
+-        driver; copying the driver value in a child device context, is a
+-        bug in the application
+-
+-    o attributes
+-      - the files in the device directory or files below a subdirectories
+-        of the same device directory
+-      - accessing attributes reached by a symlink pointing to another device,
+-        like the "device"-link, is a bug in the application
+-
+-  Everything else is just a kernel driver-core implementation detail,
+-  that should not be assumed to be stable across kernel releases.
+-
+-- Properties of parent devices never belong into a child device.
+-  Always look at the parent devices themselves for determining device
+-  context properties. If the device 'eth0' or 'sda' does not have a
+-  "driver"-link, then this device does not have a driver. Its value is empty.
+-  Never copy any property of the parent-device into a child-device. Parent
+-  device-properties may change dynamically without any notice to the
+-  child device.
+-
+-- Hierarchy in a single device-tree
+-  There is only one valid place in sysfs where hierarchy can be examined
+-  and this is below: /sys/devices.
+-  It is planned, that all device directories will end up in the tree
+-  below this directory.
+-
+-- Classification by subsystem
+-  There are currently three places for classification of devices:
+-  /sys/block, /sys/class and /sys/bus. It is planned that these will
+-  not contain any device-directories themselves, but only flat lists of
+-  symlinks pointing to the unified /sys/devices tree.
+-  All three places have completely different rules on how to access
+-  device information. It is planned to merge all three
+-  classification-directories into one place at /sys/subsystem,
+-  following the layout of the bus-directories. All buses and
+-  classes, including the converted block-subsystem, will show up
+-  there.
+-  The devices belonging to a subsystem will create a symlink in the
+-  "devices" directory at /sys/subsystem/<name>/devices.
+-
+-  If /sys/subsystem exists, /sys/bus, /sys/class and /sys/block can be
+-  ignored. If it does not exist, you have always to scan all three
+-  places, as the kernel is free to move a subsystem from one place to
+-  the other, as long as the devices are still reachable by the same
+-  subsystem name.
+-
+-  Assuming /sys/class/<subsystem> and /sys/bus/<subsystem>, or
+-  /sys/block and /sys/class/block are not interchangeable, is a bug in
+-  the application.
+-
+-- Block
+-  The converted block-subsystem at /sys/class/block, or
+-  /sys/subsystem/block will contain the links for disks and partitions
+-  at the same level, never in a hierarchy. Assuming the block-subsytem to
+-  contain only disks and not partition-devices in the same flat list is
+-  a bug in the application.
+-
+-- "device"-link and <subsystem>:<kernel name>-links
+-  Never depend on the "device"-link. The "device"-link is a workaround
+-  for the old layout, where class-devices are not created in
+-  /sys/devices/ like the bus-devices. If the link-resolving of a
+-  device-directory does not end in /sys/devices/, you can use the
+-  "device"-link to find the parent devices in /sys/devices/. That is the
+-  single valid use of the "device"-link, it must never appear in any
+-  path as an element. Assuming the existence of the "device"-link for
+-  a device in /sys/devices/ is a bug in the application.
+-  Accessing /sys/class/net/eth0/device is a bug in the application.
+-
+-  Never depend on the class-specific links back to the /sys/class
+-  directory.  These links are also a workaround for the design mistake
+-  that class-devices are not created in /sys/devices. If a device
+-  directory does not contain directories for child devices, these links
+-  may be used to find the child devices in /sys/class. That is the single
+-  valid use of these links, they must never appear in any path as an
+-  element. Assuming the existence of these links for devices which are
+-  real child device directories in the /sys/devices tree, is a bug in
+-  the application.
+-
+-  It is planned to remove all these links when when all class-device
+-  directories live in /sys/devices.
+-
+-- Position of devices along device chain can change.
+-  Never depend on a specific parent device position in the devpath,
+-  or the chain of parent devices. The kernel is free to insert devices into
+-  the chain. You must always request the parent device you are looking for
+-  by its subsystem value. You need to walk up the chain until you find
+-  the device that matches the expected subsystem. Depending on a specific
+-  position of a parent device, or exposing relative paths, using "../" to
+-  access the chain of parents, is a bug in the application.
+-
+diff -Nurb linux-2.6.22-590/MAINTAINERS linux-2.6.22-570/MAINTAINERS
+--- linux-2.6.22-590/MAINTAINERS       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/MAINTAINERS       2007-07-08 19:32:17.000000000 -0400
+@@ -232,15 +232,15 @@
+ S:    Supported
+ ACPI BATTERY DRIVERS
+-P:    Alexey Starikovskiy
+-M:    astarikovskiy@suse.de
++P:    Vladimir P. Lebedev
++M:    vladimir.p.lebedev@intel.com
+ L:    linux-acpi@vger.kernel.org
+ W:    http://acpi.sourceforge.net/
+ S:    Supported
+ ACPI EC DRIVER
+ P:    Alexey Starikovskiy
+-M:    astarikovskiy@suse.de
++M:    alexey.y.starikovskiy@linux.intel.com
+ L:    linux-acpi@vger.kernel.org
+ W:    http://acpi.sourceforge.net/
+ S:    Supported
+@@ -2127,15 +2127,6 @@
+ L:    kexec@lists.infradead.org
+ S:    Maintained
+-KGDB
+-P:    Jason Wessel
+-M:    jason.wessel@windriver.com
+-P:    Amit S. Kale
+-M:    amitkale@linsyssoft.com
+-W:    http://sourceforge.net/projects/kgdb
+-L:    kgdb-bugreport@lists.sourceforge.net
+-S:    Maintained
 -
--select_failed:
--#if (CHIP == 710)
--    ; Disable selection timer
--    MOVE CTEST7 | 0x10 TO CTEST7
--#endif
--#ifdef EVENTS
--  int int_EVENT_SELECT_FAILED
--#endif
--; Otherwise, mask the selected and reselected bits off SIST0
--#if (CHIP ==710)
--    ; Let's assume we don't get selected for now
--    MOVE SSTAT0 & 0x10 TO SFBR
--#else
--    MOVE SIST0 & 0x30 TO SFBR
--    JUMP selected, IF 0x20
--#endif
--    JUMP reselected, IF 0x10 
--; If SIGP is set, the user just gave us another command, and
--; we should restart or return to the scheduler.
--; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
--    MOVE CTEST2 & 0x40 TO SFBR        
--    JUMP select, IF 0x40
--; Check connected bit.  
--; FIXME: this needs to change if we support target mode
--; FIXME: is this really necessary? 
--    MOVE ISTAT & 0x08 TO SFBR
--    JUMP reselected, IF 0x08
--; FIXME : Something bogus happened, and we shouldn't fail silently.
--#if 0
--    JUMP schedule
--#else
--    INT int_debug_panic
--#endif
+ KPROBES
+ P:    Prasanna S Panchamukhi
+ M:    prasanna@in.ibm.com
+@@ -3602,15 +3593,6 @@
+ W:    http://www.kernel.dk
+ S:    Maintained
+-UNIONFS
+-P:    Erez Zadok
+-M:    ezk@cs.sunysb.edu
+-P:    Josef "Jeff" Sipek
+-M:    jsipek@cs.sunysb.edu
+-L:    unionfs@filesystems.org
+-W:    http://unionfs.filesystems.org
+-S:    Maintained
 -
--;
--; test_1
--; test_2
--;
--; PURPOSE : run some verification tests on the NCR.  test_1
--;     copies test_src to test_dest and interrupts the host
--;     processor, testing for cache coherency and interrupt
--;     problems in the processes.
--;
--;     test_2 runs a command with offsets relative to the 
--;     DSA on entry, and is useful for miscellaneous experimentation.
--;
--
--; Verify that interrupts are working correctly and that we don't 
--; have a cache invalidation problem.
--
--ABSOLUTE test_src = 0, test_dest = 0
--ENTRY test_1
--test_1:
--    MOVE MEMORY 4, test_src, test_dest
--    INT int_test_1
--
--;
--; Run arbitrary commands, with test code establishing a DSA
--;
-- 
--ENTRY test_2
--test_2:
--    CLEAR TARGET
--#if (CHIP == 710)
--    ; Enable selection timer
--#ifdef NO_SELECTION_TIMEOUT
--    MOVE CTEST7 & 0xff TO CTEST7
--#else
--    MOVE CTEST7 & 0xef TO CTEST7
--#endif
--#endif
--    SELECT ATN FROM 0, test_2_fail
--    JUMP test_2_msgout, WHEN MSG_OUT
--ENTRY test_2_msgout
--test_2_msgout:
--#if (CHIP == 710)
--    ; Disable selection timer
--    MOVE CTEST7 | 0x10 TO CTEST7
--#endif
--    MOVE FROM 8, WHEN MSG_OUT
--    MOVE FROM 16, WHEN CMD 
--    MOVE FROM 24, WHEN DATA_IN
--    MOVE FROM 32, WHEN STATUS
--    MOVE FROM 40, WHEN MSG_IN
--#if (CHIP != 710)
--    MOVE SCNTL2 & 0x7f TO SCNTL2
--#endif
--    CLEAR ACK
--    WAIT DISCONNECT
--test_2_fail:
--#if (CHIP == 710)
--    ; Disable selection timer
--    MOVE CTEST7 | 0x10 TO CTEST7
--#endif
--    INT int_test_2
--
--ENTRY debug_break
--debug_break:
--    INT int_debug_break
--
--;
--; initiator_abort
--; target_abort
--;
--; PURPOSE : Abort the currently established nexus from with initiator
--;     or target mode.
--;
--;  
--
--ENTRY target_abort
--target_abort:
--    SET TARGET
--    DISCONNECT
--    CLEAR TARGET
--    JUMP schedule
--    
--ENTRY initiator_abort
--initiator_abort:
--    SET ATN
--;
--; The SCSI-I specification says that targets may go into MSG out at 
--; their leisure upon receipt of the ATN single.  On all versions of the 
--; specification, we can't change phases until REQ transitions true->false, 
--; so we need to sink/source one byte of data to allow the transition.
--;
--; For the sake of safety, we'll only source one byte of data in all 
--; cases, but to accommodate the SCSI-I dain bramage, we'll sink an  
--; arbitrary number of bytes.
--    JUMP spew_cmd, WHEN CMD
--    JUMP eat_msgin, WHEN MSG_IN
--    JUMP eat_datain, WHEN DATA_IN
--    JUMP eat_status, WHEN STATUS
--    JUMP spew_dataout, WHEN DATA_OUT
--    JUMP sated
--spew_cmd:
--    MOVE 1, NCR53c7xx_zero, WHEN CMD
--    JUMP sated
--eat_msgin:
--    MOVE 1, NCR53c7xx_sink, WHEN MSG_IN
--    JUMP eat_msgin, WHEN MSG_IN
--    JUMP sated
--eat_status:
--    MOVE 1, NCR53c7xx_sink, WHEN STATUS
--    JUMP eat_status, WHEN STATUS
--    JUMP sated
--eat_datain:
--    MOVE 1, NCR53c7xx_sink, WHEN DATA_IN
--    JUMP eat_datain, WHEN DATA_IN
--    JUMP sated
--spew_dataout:
--    MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT
--sated:
--#if (CHIP != 710)
--    MOVE SCNTL2 & 0x7f TO SCNTL2
--#endif
--    MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT
--    WAIT DISCONNECT
--    INT int_norm_aborted
--
--#if (CHIP != 710)
--;
--; dsa_to_scratch
--; scratch_to_dsa
--;
--; PURPOSE :
--;     The NCR chips cannot do a move memory instruction with the DSA register 
--;     as the source or destination.  So, we provide a couple of subroutines
--;     that let us switch between the DSA register and scratch register.
--;
--;     Memory moves to/from the DSPS  register also don't work, but we 
--;     don't use them.
--;
--;
+ USB ACM DRIVER
+ P:    Oliver Neukum
+ M:    oliver@neukum.name
+diff -Nurb linux-2.6.22-590/Makefile linux-2.6.22-570/Makefile
+--- linux-2.6.22-590/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/Makefile  2008-01-23 19:16:03.000000000 -0500
+@@ -1,7 +1,7 @@
+ VERSION = 2
+ PATCHLEVEL = 6
+ SUBLEVEL = 22
+-EXTRAVERSION = -prep
++EXTRAVERSION = .14-vs2.3.0.29
+ NAME = Holy Dancing Manatees, Batman!
+ # *DOCUMENTATION*
+@@ -496,11 +496,6 @@
+ CFLAGS                += -fomit-frame-pointer
+ endif
+-ifdef CONFIG_UNWIND_INFO
+-CFLAGS                += -fasynchronous-unwind-tables
+-LDFLAGS_vmlinux       += --eh-frame-hdr
+-endif
 -
-- 
--dsa_to_scratch:
--    MOVE DSA0 TO SFBR
--    MOVE SFBR TO SCRATCH0
--    MOVE DSA1 TO SFBR
--    MOVE SFBR TO SCRATCH1
--    MOVE DSA2 TO SFBR
--    MOVE SFBR TO SCRATCH2
--    MOVE DSA3 TO SFBR
--    MOVE SFBR TO SCRATCH3
--    RETURN
--
--scratch_to_dsa:
--    MOVE SCRATCH0 TO SFBR
--    MOVE SFBR TO DSA0
--    MOVE SCRATCH1 TO SFBR
--    MOVE SFBR TO DSA1
--    MOVE SCRATCH2 TO SFBR
--    MOVE SFBR TO DSA2
--    MOVE SCRATCH3 TO SFBR
--    MOVE SFBR TO DSA3
--    RETURN
--#endif
-- 
--#if (CHIP == 710)
--; Little patched jump, used to overcome problems with TEMP getting
--; corrupted on memory moves.
+ ifdef CONFIG_DEBUG_INFO
+ CFLAGS                += -g
+ endif
+diff -Nurb linux-2.6.22-590/Makefile.orig linux-2.6.22-570/Makefile.orig
+--- linux-2.6.22-590/Makefile.orig     1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/Makefile.orig     2008-01-23 19:15:54.000000000 -0500
+@@ -0,0 +1,1493 @@
++VERSION = 2
++PATCHLEVEL = 6
++SUBLEVEL = 22
++EXTRAVERSION = .14
++NAME = Holy Dancing Manatees, Batman!
++
++# *DOCUMENTATION*
++# To see a list of typical targets execute "make help"
++# More info can be located in ./README
++# Comments in this file are targeted only to the developer, do not
++# expect to learn how to build the kernel reading this file.
++
++# Do not:
++# o  use make's built-in rules and variables
++#    (this increases performance and avoid hard-to-debug behavour);
++# o  print "Entering directory ...";
++MAKEFLAGS += -rR --no-print-directory
++
++# We are using a recursive build, so we need to do a little thinking
++# to get the ordering right.
++#
++# Most importantly: sub-Makefiles should only ever modify files in
++# their own directory. If in some directory we have a dependency on
++# a file in another dir (which doesn't happen often, but it's often
++# unavoidable when linking the built-in.o targets which finally
++# turn into vmlinux), we will call a sub make in that other dir, and
++# after that we are sure that everything which is in that other dir
++# is now up to date.
++#
++# The only cases where we need to modify files which have global
++# effects are thus separated out and done before the recursive
++# descending is started. They are now explicitly listed as the
++# prepare rule.
++
++# To put more focus on warnings, be less verbose as default
++# Use 'make V=1' to see the full commands
++
++ifdef V
++  ifeq ("$(origin V)", "command line")
++    KBUILD_VERBOSE = $(V)
++  endif
++endif
++ifndef KBUILD_VERBOSE
++  KBUILD_VERBOSE = 0
++endif
++
++# Call a source code checker (by default, "sparse") as part of the
++# C compilation.
++#
++# Use 'make C=1' to enable checking of only re-compiled files.
++# Use 'make C=2' to enable checking of *all* source files, regardless
++# of whether they are re-compiled or not.
++#
++# See the file "Documentation/sparse.txt" for more details, including
++# where to get the "sparse" utility.
++
++ifdef C
++  ifeq ("$(origin C)", "command line")
++    KBUILD_CHECKSRC = $(C)
++  endif
++endif
++ifndef KBUILD_CHECKSRC
++  KBUILD_CHECKSRC = 0
++endif
++
++# Use make M=dir to specify directory of external module to build
++# Old syntax make ... SUBDIRS=$PWD is still supported
++# Setting the environment variable KBUILD_EXTMOD take precedence
++ifdef SUBDIRS
++  KBUILD_EXTMOD ?= $(SUBDIRS)
++endif
++ifdef M
++  ifeq ("$(origin M)", "command line")
++    KBUILD_EXTMOD := $(M)
++  endif
++endif
++
++
++# kbuild supports saving output files in a separate directory.
++# To locate output files in a separate directory two syntaxes are supported.
++# In both cases the working directory must be the root of the kernel src.
++# 1) O=
++# Use "make O=dir/to/store/output/files/"
++#
++# 2) Set KBUILD_OUTPUT
++# Set the environment variable KBUILD_OUTPUT to point to the directory
++# where the output files shall be placed.
++# export KBUILD_OUTPUT=dir/to/store/output/files/
++# make
++#
++# The O= assignment takes precedence over the KBUILD_OUTPUT environment
++# variable.
++
++
++# KBUILD_SRC is set on invocation of make in OBJ directory
++# KBUILD_SRC is not intended to be used by the regular user (for now)
++ifeq ($(KBUILD_SRC),)
++
++# OK, Make called in directory where kernel src resides
++# Do we want to locate output files in a separate directory?
++ifdef O
++  ifeq ("$(origin O)", "command line")
++    KBUILD_OUTPUT := $(O)
++  endif
++endif
++
++# That's our default target when none is given on the command line
++PHONY := _all
++_all:
++
++ifneq ($(KBUILD_OUTPUT),)
++# Invoke a second make in the output directory, passing relevant variables
++# check that the output directory actually exists
++saved-output := $(KBUILD_OUTPUT)
++KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
++$(if $(KBUILD_OUTPUT),, \
++     $(error output directory "$(saved-output)" does not exist))
++
++PHONY += $(MAKECMDGOALS)
++
++$(filter-out _all,$(MAKECMDGOALS)) _all:
++      $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
++      KBUILD_SRC=$(CURDIR) \
++      KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@
++
++# Leave processing to above invocation of make
++skip-makefile := 1
++endif # ifneq ($(KBUILD_OUTPUT),)
++endif # ifeq ($(KBUILD_SRC),)
++
++# We process the rest of the Makefile if this is the final invocation of make
++ifeq ($(skip-makefile),)
++
++# If building an external module we do not care about the all: rule
++# but instead _all depend on modules
++PHONY += all
++ifeq ($(KBUILD_EXTMOD),)
++_all: all
++else
++_all: modules
++endif
++
++srctree               := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))
++TOPDIR                := $(srctree)
++# FIXME - TOPDIR is obsolete, use srctree/objtree
++objtree               := $(CURDIR)
++src           := $(srctree)
++obj           := $(objtree)
++
++VPATH         := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
++
++export srctree objtree VPATH TOPDIR
++
++
++# SUBARCH tells the usermode build what the underlying arch is.  That is set
++# first, and if a usermode build is happening, the "ARCH=um" on the command
++# line overrides the setting of ARCH below.  If a native build is happening,
++# then ARCH is assigned, getting whatever value it gets normally, and 
++# SUBARCH is subsequently ignored.
++
++SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
++                                -e s/arm.*/arm/ -e s/sa110/arm/ \
++                                -e s/s390x/s390/ -e s/parisc64/parisc/ \
++                                -e s/ppc.*/powerpc/ -e s/mips.*/mips/ )
++
++# Cross compiling and selecting different set of gcc/bin-utils
++# ---------------------------------------------------------------------------
++#
++# When performing cross compilation for other architectures ARCH shall be set
++# to the target architecture. (See arch/* for the possibilities).
++# ARCH can be set during invocation of make:
++# make ARCH=ia64
++# Another way is to have ARCH set in the environment.
++# The default ARCH is the host where make is executed.
++
++# CROSS_COMPILE specify the prefix used for all executables used
++# during compilation. Only gcc and related bin-utils executables
++# are prefixed with $(CROSS_COMPILE).
++# CROSS_COMPILE can be set on the command line
++# make CROSS_COMPILE=ia64-linux-
++# Alternatively CROSS_COMPILE can be set in the environment.
++# Default value for CROSS_COMPILE is not to prefix executables
++# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
++
++ARCH          ?= $(SUBARCH)
++CROSS_COMPILE ?=
++
++# Architecture as present in compile.h
++UTS_MACHINE := $(ARCH)
++
++KCONFIG_CONFIG        ?= .config
++
++# SHELL used by kbuild
++CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
++        else if [ -x /bin/bash ]; then echo /bin/bash; \
++        else echo sh; fi ; fi)
++
++HOSTCC       = gcc
++HOSTCXX      = g++
++HOSTCFLAGS   = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
++HOSTCXXFLAGS = -O2
++
++# Decide whether to build built-in, modular, or both.
++# Normally, just do built-in.
++
++KBUILD_MODULES :=
++KBUILD_BUILTIN := 1
++
++#     If we have only "make modules", don't compile built-in objects.
++#     When we're building modules with modversions, we need to consider
++#     the built-in objects during the descend as well, in order to
++#     make sure the checksums are up to date before we record them.
++
++ifeq ($(MAKECMDGOALS),modules)
++  KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
++endif
++
++#     If we have "make <whatever> modules", compile modules
++#     in addition to whatever we do anyway.
++#     Just "make" or "make all" shall build modules as well
++
++ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
++  KBUILD_MODULES := 1
++endif
++
++ifeq ($(MAKECMDGOALS),)
++  KBUILD_MODULES := 1
++endif
++
++export KBUILD_MODULES KBUILD_BUILTIN
++export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
++
++# Beautify output
++# ---------------------------------------------------------------------------
++#
++# Normally, we echo the whole command before executing it. By making
++# that echo $($(quiet)$(cmd)), we now have the possibility to set
++# $(quiet) to choose other forms of output instead, e.g.
++#
++#         quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
++#         cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<
++#
++# If $(quiet) is empty, the whole command will be printed.
++# If it is set to "quiet_", only the short version will be printed. 
++# If it is set to "silent_", nothing will be printed at all, since
++# the variable $(silent_cmd_cc_o_c) doesn't exist.
++#
++# A simple variant is to prefix commands with $(Q) - that's useful
++# for commands that shall be hidden in non-verbose mode.
++#
++#     $(Q)ln $@ :<
++#
++# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
++# If KBUILD_VERBOSE equals 1 then the above command is displayed.
++
++ifeq ($(KBUILD_VERBOSE),1)
++  quiet =
++  Q =
++else
++  quiet=quiet_
++  Q = @
++endif
++
++# If the user is running make -s (silent mode), suppress echoing of
++# commands
++
++ifneq ($(findstring s,$(MAKEFLAGS)),)
++  quiet=silent_
++endif
++
++export quiet Q KBUILD_VERBOSE
++
++
++# Look for make include files relative to root of kernel src
++MAKEFLAGS += --include-dir=$(srctree)
++
++# We need some generic definitions.
++include $(srctree)/scripts/Kbuild.include
++
++# Make variables (CC, etc...)
++
++AS            = $(CROSS_COMPILE)as
++LD            = $(CROSS_COMPILE)ld
++CC            = $(CROSS_COMPILE)gcc
++CPP           = $(CC) -E
++AR            = $(CROSS_COMPILE)ar
++NM            = $(CROSS_COMPILE)nm
++STRIP         = $(CROSS_COMPILE)strip
++OBJCOPY               = $(CROSS_COMPILE)objcopy
++OBJDUMP               = $(CROSS_COMPILE)objdump
++AWK           = awk
++GENKSYMS      = scripts/genksyms/genksyms
++DEPMOD                = /sbin/depmod
++KALLSYMS      = scripts/kallsyms
++PERL          = perl
++CHECK         = sparse
++
++CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise $(CF)
++MODFLAGS      = -DMODULE
++CFLAGS_MODULE   = $(MODFLAGS)
++AFLAGS_MODULE   = $(MODFLAGS)
++LDFLAGS_MODULE  = -r
++CFLAGS_KERNEL =
++AFLAGS_KERNEL =
++
++
++# Use LINUXINCLUDE when you must reference the include/ directory.
++# Needed to be compatible with the O= option
++LINUXINCLUDE    := -Iinclude \
++                   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
++                 -include include/linux/autoconf.h
++
++CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
++
++CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
++                   -fno-strict-aliasing -fno-common
++AFLAGS          := -D__ASSEMBLY__
++
++# Read KERNELRELEASE from include/config/kernel.release (if it exists)
++KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
++KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
++
++export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
++export ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
++export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
++export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
++
++export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
++export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
++export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
++
++# When compiling out-of-tree modules, put MODVERDIR in the module
++# tree rather than in the kernel tree. The kernel tree might
++# even be read-only.
++export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
++
++# Files to ignore in find ... statements
++
++RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git \) -prune -o
++export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg --exclude .git
++
++# ===========================================================================
++# Rules shared between *config targets and build targets
++
++# Basic helpers built in scripts/
++PHONY += scripts_basic
++scripts_basic:
++      $(Q)$(MAKE) $(build)=scripts/basic
++
++# To avoid any implicit rule to kick in, define an empty command.
++scripts/basic/%: scripts_basic ;
++
++PHONY += outputmakefile
++# outputmakefile generates a Makefile in the output directory, if using a
++# separate output directory. This allows convenient use of make in the
++# output directory.
++outputmakefile:
++ifneq ($(KBUILD_SRC),)
++      $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
++          $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
++endif
++
++# To make sure we do not include .config for any of the *config targets
++# catch them early, and hand them over to scripts/kconfig/Makefile
++# It is allowed to specify more targets when calling make, including
++# mixing *config targets and build targets.
++# For example 'make oldconfig all'.
++# Detect when mixed targets is specified, and make a second invocation
++# of make so .config is not included in this case either (for *config).
++
++no-dot-config-targets := clean mrproper distclean \
++                       cscope TAGS tags help %docs check% \
++                       include/linux/version.h headers_% \
++                       kernelrelease kernelversion
++
++config-targets := 0
++mixed-targets  := 0
++dot-config     := 1
++
++ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
++      ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
++              dot-config := 0
++      endif
++endif
++
++ifeq ($(KBUILD_EXTMOD),)
++        ifneq ($(filter config %config,$(MAKECMDGOALS)),)
++                config-targets := 1
++                ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)
++                        mixed-targets := 1
++                endif
++        endif
++endif
++
++ifeq ($(mixed-targets),1)
++# ===========================================================================
++# We're called with mixed targets (*config and build targets).
++# Handle them one by one.
++
++%:: FORCE
++      $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@
++
++else
++ifeq ($(config-targets),1)
++# ===========================================================================
++# *config targets only - make sure prerequisites are updated, and descend
++# in scripts/kconfig to make the *config target
++
++# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
++# KBUILD_DEFCONFIG may point out an alternative default configuration
++# used for 'make defconfig'
++include $(srctree)/arch/$(ARCH)/Makefile
++export KBUILD_DEFCONFIG
++
++config %config: scripts_basic outputmakefile FORCE
++      $(Q)mkdir -p include/linux include/config
++      $(Q)$(MAKE) $(build)=scripts/kconfig $@
++
++else
++# ===========================================================================
++# Build targets only - this includes vmlinux, arch specific targets, clean
++# targets and others. In general all targets except *config targets.
++
++ifeq ($(KBUILD_EXTMOD),)
++# Additional helpers built in scripts/
++# Carefully list dependencies so we do not try to build scripts twice
++# in parallel
++PHONY += scripts
++scripts: scripts_basic include/config/auto.conf
++      $(Q)$(MAKE) $(build)=$(@)
++
++# Objects we will link into vmlinux / subdirs we need to visit
++init-y                := init/
++drivers-y     := drivers/ sound/
++net-y         := net/
++libs-y                := lib/
++core-y                := usr/
++endif # KBUILD_EXTMOD
++
++ifeq ($(dot-config),1)
++# Read in config
++-include include/config/auto.conf
++
++ifeq ($(KBUILD_EXTMOD),)
++# Read in dependencies to all Kconfig* files, make sure to run
++# oldconfig if changes are detected.
++-include include/config/auto.conf.cmd
++
++# To avoid any implicit rule to kick in, define an empty command
++$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
++
++# If .config is newer than include/config/auto.conf, someone tinkered
++# with it and forgot to run make oldconfig.
++# if auto.conf.cmd is missing then we are probably in a cleaned tree so
++# we execute the config step to be sure to catch updated Kconfig files
++include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
++      $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
++else
++# external modules needs include/linux/autoconf.h and include/config/auto.conf
++# but do not care if they are up-to-date. Use auto.conf to trigger the test
++PHONY += include/config/auto.conf
++
++include/config/auto.conf:
++      $(Q)test -e include/linux/autoconf.h -a -e $@ || (              \
++      echo;                                                           \
++      echo "  ERROR: Kernel configuration is invalid.";               \
++      echo "         include/linux/autoconf.h or $@ are missing.";    \
++      echo "         Run 'make oldconfig && make prepare' on kernel src to fix it.";  \
++      echo;                                                           \
++      /bin/false)
++
++endif # KBUILD_EXTMOD
++
++else
++# Dummy target needed, because used as prerequisite
++include/config/auto.conf: ;
++endif # $(dot-config)
++
++# The all: target is the default when no target is given on the
++# command line.
++# This allow a user to issue only 'make' to build a kernel including modules
++# Defaults vmlinux but it is usually overridden in the arch makefile
++all: vmlinux
++
++ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
++CFLAGS                += -Os
++else
++CFLAGS                += -O2
++endif
++
++include $(srctree)/arch/$(ARCH)/Makefile
++
++ifdef CONFIG_FRAME_POINTER
++CFLAGS                += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
++else
++CFLAGS                += -fomit-frame-pointer
++endif
++
++ifdef CONFIG_DEBUG_INFO
++CFLAGS                += -g
++endif
++
++# Force gcc to behave correct even for buggy distributions
++CFLAGS          += $(call cc-option, -fno-stack-protector)
++
++# arch Makefile may override CC so keep this after arch Makefile is included
++NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
++CHECKFLAGS     += $(NOSTDINC_FLAGS)
++
++# warn about C99 declaration after statement
++CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
++
++# disable pointer signed / unsigned warnings in gcc 4.0
++CFLAGS += $(call cc-option,-Wno-pointer-sign,)
++
++# Default kernel image to build when no specific target is given.
++# KBUILD_IMAGE may be overruled on the command line or
++# set in the environment
++# Also any assignments in arch/$(ARCH)/Makefile take precedence over
++# this default value
++export KBUILD_IMAGE ?= vmlinux
++
++#
++# INSTALL_PATH specifies where to place the updated kernel and system map
++# images. Default is /boot, but you can set it to other values
++export        INSTALL_PATH ?= /boot
++
++#
++# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
++# relocations required by build roots.  This is not defined in the
++# makefile but the argument can be passed to make if needed.
++#
++
++MODLIB        = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
++export MODLIB
++
++#
++#  INSTALL_MOD_STRIP, if defined, will cause modules to be
++#  stripped after they are installed.  If INSTALL_MOD_STRIP is '1', then
++#  the default option --strip-debug will be used.  Otherwise,
++#  INSTALL_MOD_STRIP will used as the options to the strip command.
++
++ifdef INSTALL_MOD_STRIP
++ifeq ($(INSTALL_MOD_STRIP),1)
++mod_strip_cmd = $(STRIP) --strip-debug
++else
++mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
++endif # INSTALL_MOD_STRIP=1
++else
++mod_strip_cmd = true
++endif # INSTALL_MOD_STRIP
++export mod_strip_cmd
++
++
++ifeq ($(KBUILD_EXTMOD),)
++core-y                += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
++
++vmlinux-dirs  := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
++                   $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
++                   $(net-y) $(net-m) $(libs-y) $(libs-m)))
++
++vmlinux-alldirs       := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
++                   $(init-n) $(init-) \
++                   $(core-n) $(core-) $(drivers-n) $(drivers-) \
++                   $(net-n)  $(net-)  $(libs-n)    $(libs-))))
++
++init-y                := $(patsubst %/, %/built-in.o, $(init-y))
++core-y                := $(patsubst %/, %/built-in.o, $(core-y))
++drivers-y     := $(patsubst %/, %/built-in.o, $(drivers-y))
++net-y         := $(patsubst %/, %/built-in.o, $(net-y))
++libs-y1               := $(patsubst %/, %/lib.a, $(libs-y))
++libs-y2               := $(patsubst %/, %/built-in.o, $(libs-y))
++libs-y                := $(libs-y1) $(libs-y2)
++
++# Build vmlinux
++# ---------------------------------------------------------------------------
++# vmlinux is built from the objects selected by $(vmlinux-init) and
++# $(vmlinux-main). Most are built-in.o files from top-level directories
++# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
++# Ordering when linking is important, and $(vmlinux-init) must be first.
++#
++# vmlinux
++#   ^
++#   |
++#   +-< $(vmlinux-init)
++#   |   +--< init/version.o + more
++#   |
++#   +--< $(vmlinux-main)
++#   |    +--< driver/built-in.o mm/built-in.o + more
++#   |
++#   +-< kallsyms.o (see description in CONFIG_KALLSYMS section)
++#
++# vmlinux version (uname -v) cannot be updated during normal
++# descending-into-subdirs phase since we do not yet know if we need to
++# update vmlinux.
++# Therefore this step is delayed until just before final link of vmlinux -
++# except in the kallsyms case where it is done just before adding the
++# symbols to the kernel.
++#
++# System.map is generated to document addresses of all kernel symbols
++
++vmlinux-init := $(head-y) $(init-y)
++vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
++vmlinux-all  := $(vmlinux-init) $(vmlinux-main)
++vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds
++export KBUILD_VMLINUX_OBJS := $(vmlinux-all)
++
++# Rule to link vmlinux - also used during CONFIG_KALLSYMS
++# May be overridden by arch/$(ARCH)/Makefile
++quiet_cmd_vmlinux__ ?= LD      $@
++      cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
++      -T $(vmlinux-lds) $(vmlinux-init)                          \
++      --start-group $(vmlinux-main) --end-group                  \
++      $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
++
++# Generate new vmlinux version
++quiet_cmd_vmlinux_version = GEN     .version
++      cmd_vmlinux_version = set -e;                     \
++      if [ ! -r .version ]; then                      \
++        rm -f .version;                               \
++        echo 1 >.version;                             \
++      else                                            \
++        mv .version .old_version;                     \
++        expr 0$$(cat .old_version) + 1 >.version;     \
++      fi;                                             \
++      $(MAKE) $(build)=init
++
++# Generate System.map
++quiet_cmd_sysmap = SYSMAP
++      cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
++
++# Link of vmlinux
++# If CONFIG_KALLSYMS is set .version is already updated
++# Generate System.map and verify that the content is consistent
++# Use + in front of the vmlinux_version rule to silent warning with make -j2
++# First command is ':' to allow us to use + in front of the rule
++define rule_vmlinux__
++      :
++      $(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
++
++      $(call cmd,vmlinux__)
++      $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
++
++      $(Q)$(if $($(quiet)cmd_sysmap),                                      \
++        echo '  $($(quiet)cmd_sysmap)  System.map' &&)                     \
++      $(cmd_sysmap) $@ System.map;                                         \
++      if [ $$? -ne 0 ]; then                                               \
++              rm -f $@;                                                    \
++              /bin/false;                                                  \
++      fi;
++      $(verify_kallsyms)
++endef
++
++
++ifdef CONFIG_KALLSYMS
++# Generate section listing all symbols and add it into vmlinux $(kallsyms.o)
++# It's a three stage process:
++# o .tmp_vmlinux1 has all symbols and sections, but __kallsyms is
++#   empty
++#   Running kallsyms on that gives us .tmp_kallsyms1.o with
++#   the right size - vmlinux version (uname -v) is updated during this step
++# o .tmp_vmlinux2 now has a __kallsyms section of the right size,
++#   but due to the added section, some addresses have shifted.
++#   From here, we generate a correct .tmp_kallsyms2.o
++# o The correct .tmp_kallsyms2.o is linked into the final vmlinux.
++# o Verify that the System.map from vmlinux matches the map from
++#   .tmp_vmlinux2, just in case we did not generate kallsyms correctly.
++# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using
++#   .tmp_vmlinux3 and .tmp_kallsyms3.o.  This is only meant as a
++#   temporary bypass to allow the kernel to be built while the
++#   maintainers work out what went wrong with kallsyms.
++
++ifdef CONFIG_KALLSYMS_EXTRA_PASS
++last_kallsyms := 3
++else
++last_kallsyms := 2
++endif
++
++kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
++
++define verify_kallsyms
++      $(Q)$(if $($(quiet)cmd_sysmap),                                      \
++        echo '  $($(quiet)cmd_sysmap)  .tmp_System.map' &&)                \
++        $(cmd_sysmap) .tmp_vmlinux$(last_kallsyms) .tmp_System.map
++      $(Q)cmp -s System.map .tmp_System.map ||                             \
++              (echo Inconsistent kallsyms data;                            \
++               echo Try setting CONFIG_KALLSYMS_EXTRA_PASS;                \
++               rm .tmp_kallsyms* ; /bin/false )
++endef
++
++# Update vmlinux version before link
++# Use + in front of this rule to silent warning about make -j1
++# First command is ':' to allow us to use + in front of this rule
++cmd_ksym_ld = $(cmd_vmlinux__)
++define rule_ksym_ld
++      : 
++      +$(call cmd,vmlinux_version)
++      $(call cmd,vmlinux__)
++      $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
++endef
++
++# Generate .S file with all kernel symbols
++quiet_cmd_kallsyms = KSYM    $@
++      cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \
++                     $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
++
++.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
++      $(call if_changed_dep,as_o_S)
++
++.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS)
++      $(call cmd,kallsyms)
++
++# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version
++.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
++      $(call if_changed_rule,ksym_ld)
++
++.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
++      $(call if_changed,vmlinux__)
++
++.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE
++      $(call if_changed,vmlinux__)
++
++# Needs to visit scripts/ before $(KALLSYMS) can be used.
++$(KALLSYMS): scripts ;
++
++# Generate some data for debugging strange kallsyms problems
++debug_kallsyms: .tmp_map$(last_kallsyms)
++
++.tmp_map%: .tmp_vmlinux% FORCE
++      ($(OBJDUMP) -h $< | $(AWK) '/^ +[0-9]/{print $$4 " 0 " $$2}'; $(NM) $<) | sort > $@
++
++.tmp_map3: .tmp_map2
++
++.tmp_map2: .tmp_map1
++
++endif # ifdef CONFIG_KALLSYMS
++
++# vmlinux image - including updated kernel symbols
++vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
++ifdef CONFIG_HEADERS_CHECK
++      $(Q)$(MAKE) -f $(srctree)/Makefile headers_check
++endif
++      $(call if_changed_rule,vmlinux__)
++      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
++      $(Q)rm -f .old_version
++
++# The actual objects are generated when descending, 
++# make sure no implicit rule kicks in
++$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
++
++# Handle descending into subdirectories listed in $(vmlinux-dirs)
++# Preset locale variables to speed up the build process. Limit locale
++# tweaks to this spot to avoid wrong language settings when running
++# make menuconfig etc.
++# Error messages still appears in the original language
++
++PHONY += $(vmlinux-dirs)
++$(vmlinux-dirs): prepare scripts
++      $(Q)$(MAKE) $(build)=$@
++
++# Build the kernel release string
++#
++# The KERNELRELEASE value built here is stored in the file
++# include/config/kernel.release, and is used when executing several
++# make targets, such as "make install" or "make modules_install."
++#
++# The eventual kernel release string consists of the following fields,
++# shown in a hierarchical format to show how smaller parts are concatenated
++# to form the larger and final value, with values coming from places like
++# the Makefile, kernel config options, make command line options and/or
++# SCM tag information.
++#
++#     $(KERNELVERSION)
++#       $(VERSION)                    eg, 2
++#       $(PATCHLEVEL)                 eg, 6
++#       $(SUBLEVEL)                   eg, 18
++#       $(EXTRAVERSION)               eg, -rc6
++#     $(localver-full)
++#       $(localver)
++#         localversion*               (files without backups, containing '~')
++#         $(CONFIG_LOCALVERSION)      (from kernel config setting)
++#       $(localver-auto)              (only if CONFIG_LOCALVERSION_AUTO is set)
++#         ./scripts/setlocalversion   (SCM tag, if one exists)
++#         $(LOCALVERSION)             (from make command line if provided)
++#
++#  Note how the final $(localver-auto) string is included *only* if the
++# kernel config option CONFIG_LOCALVERSION_AUTO is selected.  Also, at the
++# moment, only git is supported but other SCMs can edit the script
++# scripts/setlocalversion and add the appropriate checks as needed.
++
++pattern = ".*/localversion[^~]*"
++string  = $(shell cat /dev/null \
++         `find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort -u`)
++
++localver = $(subst $(space),, $(string) \
++                            $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
++
++# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
++# and if the SCM is know a tag from the SCM is appended.
++# The appended tag is determined by the SCM used.
++#
++# Currently, only git is supported.
++# Other SCMs can edit scripts/setlocalversion and add the appropriate
++# checks as needed.
++ifdef CONFIG_LOCALVERSION_AUTO
++      _localver-auto = $(shell $(CONFIG_SHELL) \
++                        $(srctree)/scripts/setlocalversion $(srctree))
++      localver-auto  = $(LOCALVERSION)$(_localver-auto)
++endif
++
++localver-full = $(localver)$(localver-auto)
++
++# Store (new) KERNELRELASE string in include/config/kernel.release
++kernelrelease = $(KERNELVERSION)$(localver-full)
++include/config/kernel.release: include/config/auto.conf FORCE
++      $(Q)rm -f $@
++      $(Q)echo $(kernelrelease) > $@
++
++
++# Things we need to do before we recursively start building the kernel
++# or the modules are listed in "prepare".
++# A multi level approach is used. prepareN is processed before prepareN-1.
++# archprepare is used in arch Makefiles and when processed asm symlink,
++# version.h and scripts_basic is processed / created.
++
++# Listed in dependency order
++PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
++
++# prepare3 is used to check if we are building in a separate output directory,
++# and if so do:
++# 1) Check that make has not been executed in the kernel src $(srctree)
++# 2) Create the include2 directory, used for the second asm symlink
++prepare3: include/config/kernel.release
++ifneq ($(KBUILD_SRC),)
++      @echo '  Using $(srctree) as source for kernel'
++      $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
++              echo "  $(srctree) is not clean, please run 'make mrproper'";\
++              echo "  in the '$(srctree)' directory.";\
++              /bin/false; \
++      fi;
++      $(Q)if [ ! -d include2 ]; then mkdir -p include2; fi;
++      $(Q)ln -fsn $(srctree)/include/asm-$(ARCH) include2/asm
++endif
++
++# prepare2 creates a makefile if using a separate output directory
++prepare2: prepare3 outputmakefile
++
++prepare1: prepare2 include/linux/version.h include/linux/utsrelease.h \
++                   include/asm include/config/auto.conf
++ifneq ($(KBUILD_MODULES),)
++      $(Q)mkdir -p $(MODVERDIR)
++      $(Q)rm -f $(MODVERDIR)/*
++endif
++
++archprepare: prepare1 scripts_basic
++
++prepare0: archprepare FORCE
++      $(Q)$(MAKE) $(build)=.
++      $(Q)$(MAKE) $(build)=. missing-syscalls
++
++# All the preparing..
++prepare: prepare0
++
++# Leave this as default for preprocessing vmlinux.lds.S, which is now
++# done in arch/$(ARCH)/kernel/Makefile
++
++export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
++
++# FIXME: The asm symlink changes when $(ARCH) changes. That's
++# hard to detect, but I suppose "make mrproper" is a good idea
++# before switching between archs anyway.
++
++include/asm:
++      @echo '  SYMLINK $@ -> include/asm-$(ARCH)'
++      $(Q)if [ ! -d include ]; then mkdir -p include; fi;
++      @ln -fsn asm-$(ARCH) $@
++
++# Generate some files
++# ---------------------------------------------------------------------------
++
++# KERNELRELEASE can change from a few different places, meaning version.h
++# needs to be updated, so this check is forced on all builds
++
++uts_len := 64
++define filechk_utsrelease.h
++      if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \
++        echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2;    \
++        exit 1;                                                         \
++      fi;                                                               \
++      (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";)
++endef
++
++define filechk_version.h
++      (echo \#define LINUX_VERSION_CODE $(shell                             \
++      expr $(VERSION) \* 65536 + $(PATCHLEVEL) \* 256 + $(SUBLEVEL));     \
++      echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
++endef
++
++include/linux/version.h: $(srctree)/Makefile FORCE
++      $(call filechk,version.h)
++
++include/linux/utsrelease.h: include/config/kernel.release FORCE
++      $(call filechk,utsrelease.h)
++
++# ---------------------------------------------------------------------------
++
++PHONY += depend dep
++depend dep:
++      @echo '*** Warning: make $@ is unnecessary now.'
++
++# ---------------------------------------------------------------------------
++# Kernel headers
++INSTALL_HDR_PATH=$(objtree)/usr
++export INSTALL_HDR_PATH
++
++HDRARCHES=$(filter-out generic,$(patsubst $(srctree)/include/asm-%/Kbuild,%,$(wildcard $(srctree)/include/asm-*/Kbuild)))
++
++PHONY += headers_install_all
++headers_install_all: include/linux/version.h scripts_basic FORCE
++      $(Q)$(MAKE) $(build)=scripts scripts/unifdef
++      $(Q)for arch in $(HDRARCHES); do \
++       $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch ;\
++       done
++
++PHONY += headers_install
++headers_install: include/linux/version.h scripts_basic FORCE
++      @if [ ! -r $(srctree)/include/asm-$(ARCH)/Kbuild ]; then \
++        echo '*** Error: Headers not exportable for this architecture ($(ARCH))'; \
++        exit 1 ; fi
++      $(Q)$(MAKE) $(build)=scripts scripts/unifdef
++      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst obj=include
++
++PHONY += headers_check_all
++headers_check_all: headers_install_all
++      $(Q)for arch in $(HDRARCHES); do \
++       $(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch HDRCHECK=1 ;\
++       done
++
++PHONY += headers_check
++headers_check: headers_install
++      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst obj=include HDRCHECK=1
++
++# ---------------------------------------------------------------------------
++# Modules
++
++ifdef CONFIG_MODULES
++
++# By default, build modules as well
++
++all: modules
++
++#     Build modules
++
++PHONY += modules
++modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
++      @echo '  Building modules, stage 2.';
++      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
++
++
++# Target to prepare building external modules
++PHONY += modules_prepare
++modules_prepare: prepare scripts
++
++# Target to install modules
++PHONY += modules_install
++modules_install: _modinst_ _modinst_post
++
++PHONY += _modinst_
++_modinst_:
++      @if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
++              echo "Warning: you may need to install module-init-tools"; \
++              echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
++              sleep 1; \
++      fi
++      @rm -rf $(MODLIB)/kernel
++      @rm -f $(MODLIB)/source
++      @mkdir -p $(MODLIB)/kernel
++      @ln -s $(srctree) $(MODLIB)/source
++      @if [ ! $(objtree) -ef  $(MODLIB)/build ]; then \
++              rm -f $(MODLIB)/build ; \
++              ln -s $(objtree) $(MODLIB)/build ; \
++      fi
++      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
++
++# If System.map exists, run depmod.  This deliberately does not have a
++# dependency on System.map since that would run the dependency tree on
++# vmlinux.  This depmod is only for convenience to give the initial
++# boot a modules.dep even before / is mounted read-write.  However the
++# boot script depmod is the master version.
++ifeq "$(strip $(INSTALL_MOD_PATH))" ""
++depmod_opts   :=
++else
++depmod_opts   := -b $(INSTALL_MOD_PATH) -r
++endif
++PHONY += _modinst_post
++_modinst_post: _modinst_
++      if [ -r System.map -a -x $(DEPMOD) ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
++
++else # CONFIG_MODULES
++
++# Modules not configured
++# ---------------------------------------------------------------------------
++
++modules modules_install: FORCE
++      @echo
++      @echo "The present kernel configuration has modules disabled."
++      @echo "Type 'make config' and enable loadable module support."
++      @echo "Then build a kernel with module support enabled."
++      @echo
++      @exit 1
++
++endif # CONFIG_MODULES
++
++###
++# Cleaning is done on three levels.
++# make clean     Delete most generated files
++#                Leave enough to build external modules
++# make mrproper  Delete the current configuration, and all generated files
++# make distclean Remove editor backup files, patch leftover files and the like
++
++# Directories & files removed with 'make clean'
++CLEAN_DIRS  += $(MODVERDIR)
++CLEAN_FILES +=        vmlinux System.map \
++                .tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map
++
++# Directories & files removed with 'make mrproper'
++MRPROPER_DIRS  += include/config include2 usr/include
++MRPROPER_FILES += .config .config.old include/asm .version .old_version \
++                  include/linux/autoconf.h include/linux/version.h      \
++                  include/linux/utsrelease.h                            \
++                Module.symvers tags TAGS cscope*
++
++# clean - Delete most, but leave enough to build external modules
++#
++clean: rm-dirs  := $(CLEAN_DIRS)
++clean: rm-files := $(CLEAN_FILES)
++clean-dirs      := $(addprefix _clean_,$(srctree) $(vmlinux-alldirs))
++
++PHONY += $(clean-dirs) clean archclean
++$(clean-dirs):
++      $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
++
++clean: archclean $(clean-dirs)
++      $(call cmd,rmdirs)
++      $(call cmd,rmfiles)
++      @find . $(RCS_FIND_IGNORE) \
++              \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
++              -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
++              -o -name '*.symtypes' \) \
++              -type f -print | xargs rm -f
++
++# mrproper - Delete all generated files, including .config
++#
++mrproper: rm-dirs  := $(wildcard $(MRPROPER_DIRS))
++mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
++mrproper-dirs      := $(addprefix _mrproper_,Documentation/DocBook scripts)
++
++PHONY += $(mrproper-dirs) mrproper archmrproper
++$(mrproper-dirs):
++      $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
++
++mrproper: clean archmrproper $(mrproper-dirs)
++      $(call cmd,rmdirs)
++      $(call cmd,rmfiles)
++
++# distclean
++#
++PHONY += distclean
++
++distclean: mrproper
++      @find $(srctree) $(RCS_FIND_IGNORE) \
++              \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
++              -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
++              -o -name '.*.rej' -o -size 0 \
++              -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
++              -type f -print | xargs rm -f
++
++
++# Packaging of the kernel to various formats
++# ---------------------------------------------------------------------------
++# rpm target kept for backward compatibility
++package-dir   := $(srctree)/scripts/package
++
++%pkg: include/config/kernel.release FORCE
++      $(Q)$(MAKE) $(build)=$(package-dir) $@
++rpm: include/config/kernel.release FORCE
++      $(Q)$(MAKE) $(build)=$(package-dir) $@
++
++
++# Brief documentation of the typical targets used
++# ---------------------------------------------------------------------------
++
++boards := $(wildcard $(srctree)/arch/$(ARCH)/configs/*_defconfig)
++boards := $(notdir $(boards))
++
++help:
++      @echo  'Cleaning targets:'
++      @echo  '  clean           - Remove most generated files but keep the config and'
++      @echo  '                    enough build support to build external modules'
++      @echo  '  mrproper        - Remove all generated files + config + various backup files'
++      @echo  '  distclean       - mrproper + remove editor backup and patch files'
++      @echo  ''
++      @echo  'Configuration targets:'
++      @$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help
++      @echo  ''
++      @echo  'Other generic targets:'
++      @echo  '  all             - Build all targets marked with [*]'
++      @echo  '* vmlinux         - Build the bare kernel'
++      @echo  '* modules         - Build all modules'
++      @echo  '  modules_install - Install all modules to INSTALL_MOD_PATH (default: /)'
++      @echo  '  dir/            - Build all files in dir and below'
++      @echo  '  dir/file.[ois]  - Build specified target only'
++      @echo  '  dir/file.ko     - Build module including final link'
++      @echo  '  rpm             - Build a kernel as an RPM package'
++      @echo  '  tags/TAGS       - Generate tags file for editors'
++      @echo  '  cscope          - Generate cscope index'
++      @echo  '  kernelrelease   - Output the release version string'
++      @echo  '  kernelversion   - Output the version stored in Makefile'
++      @if [ -r $(srctree)/include/asm-$(ARCH)/Kbuild ]; then \
++       echo  '  headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
++       echo  '                    (default: $(INSTALL_HDR_PATH))'; \
++       fi
++      @echo  ''
++      @echo  'Static analysers'
++      @echo  '  checkstack      - Generate a list of stack hogs'
++      @echo  '  namespacecheck  - Name space analysis on compiled kernel'
++      @if [ -r $(srctree)/include/asm-$(ARCH)/Kbuild ]; then \
++       echo  '  headers_check   - Sanity check on exported headers'; \
++       fi
++      @echo  ''
++      @echo  'Kernel packaging:'
++      @$(MAKE) $(build)=$(package-dir) help
++      @echo  ''
++      @echo  'Documentation targets:'
++      @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp
++      @echo  ''
++      @echo  'Architecture specific targets ($(ARCH)):'
++      @$(if $(archhelp),$(archhelp),\
++              echo '  No architecture specific help defined for $(ARCH)')
++      @echo  ''
++      @$(if $(boards), \
++              $(foreach b, $(boards), \
++              printf "  %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \
++              echo '')
++
++      @echo  '  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
++      @echo  '  make V=2   [targets] 2 => give reason for rebuild of target'
++      @echo  '  make O=dir [targets] Locate all output files in "dir", including .config'
++      @echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse by default)'
++      @echo  '  make C=2   [targets] Force check of all c source with $$CHECK'
++      @echo  ''
++      @echo  'Execute "make" or "make all" to build all targets marked with [*] '
++      @echo  'For further info see the ./README file'
++
++
++# Documentation targets
++# ---------------------------------------------------------------------------
++%docs: scripts_basic FORCE
++      $(Q)$(MAKE) $(build)=Documentation/DocBook $@
++
++else # KBUILD_EXTMOD
++
++###
++# External module support.
++# When building external modules the kernel used as basis is considered
++# read-only, and no consistency checks are made and the make
++# system is not used on the basis kernel. If updates are required
++# in the basis kernel ordinary make commands (without M=...) must
++# be used.
++#
++# The following are the only valid targets when building external
++# modules.
++# make M=dir clean     Delete all automatically generated files
++# make M=dir modules   Make all modules in specified dir
++# make M=dir         Same as 'make M=dir modules'
++# make M=dir modules_install
++#                      Install the modules built in the module directory
++#                      Assumes install directory is already created
++
++# We are always building modules
++KBUILD_MODULES := 1
++PHONY += crmodverdir
++crmodverdir:
++      $(Q)mkdir -p $(MODVERDIR)
++      $(Q)rm -f $(MODVERDIR)/*
++
++PHONY += $(objtree)/Module.symvers
++$(objtree)/Module.symvers:
++      @test -e $(objtree)/Module.symvers || ( \
++      echo; \
++      echo "  WARNING: Symbol version dump $(objtree)/Module.symvers"; \
++      echo "           is missing; modules will have no dependencies and modversions."; \
++      echo )
++
++module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
++PHONY += $(module-dirs) modules
++$(module-dirs): crmodverdir $(objtree)/Module.symvers
++      $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@)
++
++modules: $(module-dirs)
++      @echo '  Building modules, stage 2.';
++      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
++
++PHONY += modules_install
++modules_install: _emodinst_ _emodinst_post
++
++install-dir := $(if $(INSTALL_MOD_DIR),$(INSTALL_MOD_DIR),extra)
++PHONY += _emodinst_
++_emodinst_:
++      $(Q)mkdir -p $(MODLIB)/$(install-dir)
++      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
++
++# Run depmod only is we have System.map and depmod is executable
++quiet_cmd_depmod = DEPMOD  $(KERNELRELEASE)
++      cmd_depmod = if [ -r System.map -a -x $(DEPMOD) ]; then \
++                      $(DEPMOD) -ae -F System.map             \
++                      $(if $(strip $(INSTALL_MOD_PATH)),      \
++                    -b $(INSTALL_MOD_PATH) -r)              \
++                    $(KERNELRELEASE);                       \
++                   fi
++
++PHONY += _emodinst_post
++_emodinst_post: _emodinst_
++      $(call cmd,depmod)
++
++clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD))
++
++PHONY += $(clean-dirs) clean
++$(clean-dirs):
++      $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
++
++clean:        rm-dirs := $(MODVERDIR)
++clean: $(clean-dirs)
++      $(call cmd,rmdirs)
++      @find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \
++              \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
++              -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
++              -type f -print | xargs rm -f
++
++help:
++      @echo  '  Building external modules.'
++      @echo  '  Syntax: make -C path/to/kernel/src M=$$PWD target'
++      @echo  ''
++      @echo  '  modules         - default target, build the module(s)'
++      @echo  '  modules_install - install the module'
++      @echo  '  clean           - remove generated files in module directory only'
++      @echo  ''
++
++# Dummies...
++PHONY += prepare scripts
++prepare: ;
++scripts: ;
++endif # KBUILD_EXTMOD
++
++# Generate tags for editors
++# ---------------------------------------------------------------------------
++
++#We want __srctree to totally vanish out when KBUILD_OUTPUT is not set
++#(which is the most common case IMHO) to avoid unneeded clutter in the big tags file.
++#Adding $(srctree) adds about 20M on i386 to the size of the output file!
++
++ifeq ($(src),$(obj))
++__srctree =
++else
++__srctree = $(srctree)/
++endif
++
++ifeq ($(ALLSOURCE_ARCHS),)
++ifeq ($(ARCH),um)
++ALLINCLUDE_ARCHS := $(ARCH) $(SUBARCH)
++else
++ALLINCLUDE_ARCHS := $(ARCH)
++endif
++else
++#Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behavour.
++ALLINCLUDE_ARCHS := $(ALLSOURCE_ARCHS)
++endif
++
++ALLSOURCE_ARCHS := $(ARCH)
++
++define find-sources
++        ( for ARCH in $(ALLSOURCE_ARCHS) ; do \
++             find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
++                  -name $1 -print; \
++        done ; \
++        find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
++             -name $1 -print; \
++        find $(__srctree)include $(RCS_FIND_IGNORE) \
++             \( -name config -o -name 'asm-*' \) -prune \
++             -o -name $1 -print; \
++        for ARCH in $(ALLINCLUDE_ARCHS) ; do \
++             find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
++                  -name $1 -print; \
++        done ; \
++        find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
++             -name $1 -print; \
++        find $(__srctree) $(RCS_FIND_IGNORE) \
++             \( -name include -o -name arch \) -prune -o \
++             -name $1 -print; \
++        )
++endef
++
++define all-sources
++      $(call find-sources,'*.[chS]')
++endef
++define all-kconfigs
++      $(call find-sources,'Kconfig*')
++endef
++define all-defconfigs
++      $(call find-sources,'defconfig')
++endef
++
++define xtags
++      if $1 --version 2>&1 | grep -iq exuberant; then \
++          $(all-sources) | xargs $1 -a \
++              -I __initdata,__exitdata,__acquires,__releases \
++              -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
++              --extra=+f --c-kinds=+px \
++              --regex-asm='/ENTRY\(([^)]*)\).*/\1/'; \
++          $(all-kconfigs) | xargs $1 -a \
++              --langdef=kconfig \
++              --language-force=kconfig \
++              --regex-kconfig='/^[[:blank:]]*config[[:blank:]]+([[:alnum:]_]+)/\1/'; \
++          $(all-defconfigs) | xargs -r $1 -a \
++              --langdef=dotconfig \
++              --language-force=dotconfig \
++              --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/'; \
++      elif $1 --version 2>&1 | grep -iq emacs; then \
++          $(all-sources) | xargs $1 -a; \
++          $(all-kconfigs) | xargs $1 -a \
++              --regex='/^[ \t]*config[ \t]+\([a-zA-Z0-9_]+\)/\1/'; \
++          $(all-defconfigs) | xargs -r $1 -a \
++              --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'; \
++      else \
++          $(all-sources) | xargs $1 -a; \
++      fi
++endef
++
++quiet_cmd_cscope-file = FILELST cscope.files
++      cmd_cscope-file = (echo \-k; echo \-q; $(all-sources)) > cscope.files
++
++quiet_cmd_cscope = MAKE    cscope.out
++      cmd_cscope = cscope -b
++
++cscope: FORCE
++      $(call cmd,cscope-file)
++      $(call cmd,cscope)
++
++quiet_cmd_TAGS = MAKE   $@
++define cmd_TAGS
++      rm -f $@; \
++      $(call xtags,etags)
++endef
++
++TAGS: FORCE
++      $(call cmd,TAGS)
++
++quiet_cmd_tags = MAKE   $@
++define cmd_tags
++      rm -f $@; \
++      $(call xtags,ctags)
++endef
++
++tags: FORCE
++      $(call cmd,tags)
++
++
++# Scripts to check various things for consistency
++# ---------------------------------------------------------------------------
++
++includecheck:
++      find * $(RCS_FIND_IGNORE) \
++              -name '*.[hcS]' -type f -print | sort \
++              | xargs $(PERL) -w scripts/checkincludes.pl
++
++versioncheck:
++      find * $(RCS_FIND_IGNORE) \
++              -name '*.[hcS]' -type f -print | sort \
++              | xargs $(PERL) -w scripts/checkversion.pl
++
++namespacecheck:
++      $(PERL) $(srctree)/scripts/namespace.pl
++
++endif #ifeq ($(config-targets),1)
++endif #ifeq ($(mixed-targets),1)
++
++PHONY += checkstack kernelrelease kernelversion
++
++# UML needs a little special treatment here.  It wants to use the host
++# toolchain, so needs $(SUBARCH) passed to checkstack.pl.  Everyone
++# else wants $(ARCH), including people doing cross-builds, which means
++# that $(SUBARCH) doesn't work here.
++ifeq ($(ARCH), um)
++CHECKSTACK_ARCH := $(SUBARCH)
++else
++CHECKSTACK_ARCH := $(ARCH)
++endif
++checkstack:
++      $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
++      $(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH)
++
++kernelrelease:
++      $(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \
++      $(error kernelrelease not valid - run 'make prepare' to update it))
++kernelversion:
++      @echo $(KERNELVERSION)
++
++# Single targets
++# ---------------------------------------------------------------------------
++# Single targets are compatible with:
++# - build whith mixed source and output
++# - build with separate output dir 'make O=...'
++# - external modules
++#
++#  target-dir => where to store outputfile
++#  build-dir  => directory in kernel source tree to use
++
++ifeq ($(KBUILD_EXTMOD),)
++        build-dir  = $(patsubst %/,%,$(dir $@))
++        target-dir = $(dir $@)
++else
++        zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
++        build-dir  = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
++        target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@))
++endif
++
++%.s: %.c prepare scripts FORCE
++      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++%.i: %.c prepare scripts FORCE
++      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++%.o: %.c prepare scripts FORCE
++      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++%.lst: %.c prepare scripts FORCE
++      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++%.s: %.S prepare scripts FORCE
++      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++%.o: %.S prepare scripts FORCE
++      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++%.symtypes: %.c prepare scripts FORCE
++      $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++
++# Modules
++/ %/: prepare scripts FORCE
++      $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
++      $(build)=$(build-dir)
++%.ko: prepare scripts FORCE
++      $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1)   \
++      $(build)=$(build-dir) $(@:.ko=.o)
++      $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
++
++# FIXME Should go into a make.lib or something 
++# ===========================================================================
++
++quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN   $(wildcard $(rm-dirs)))
++      cmd_rmdirs = rm -rf $(rm-dirs)
++
++quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files)))
++      cmd_rmfiles = rm -f $(rm-files)
++
++
++a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(AFLAGS_KERNEL) \
++        $(NOSTDINC_FLAGS) $(CPPFLAGS) \
++        $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o)
++
++quiet_cmd_as_o_S = AS      $@
++cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
++
++# read all saved command lines
++
++targets := $(wildcard $(sort $(targets)))
++cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
++
++ifneq ($(cmd_files),)
++  $(cmd_files): ;     # Do not try to update included dependency files
++  include $(cmd_files)
++endif
++
++# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir
++# Usage:
++# $(Q)$(MAKE) $(clean)=dir
++clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
++
++endif # skip-makefile
++
++PHONY += FORCE
++FORCE:
++
++# Cancel implicit rules on top Makefile, `-rR' will apply to sub-makes.
++Makefile: ;
++
++# Declare the contents of the .PHONY variable as phony.  We keep that
++# information in a variable se we can use it in if_changed and friends.
++.PHONY: $(PHONY)
+diff -Nurb linux-2.6.22-590/arch/arm/Kconfig linux-2.6.22-570/arch/arm/Kconfig
+--- linux-2.6.22-590/arch/arm/Kconfig  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/Kconfig  2008-01-23 19:16:03.000000000 -0500
+@@ -1034,8 +1034,6 @@
+ source "drivers/rtc/Kconfig"
+-source "drivers/dma/Kconfig"
 -
--jump_temp:
--    JUMP 0
--#endif
-diff -Nurb linux-2.6.22-570/drivers/scsi/53c7xx_d.h_shipped linux-2.6.22-590/drivers/scsi/53c7xx_d.h_shipped
---- linux-2.6.22-570/drivers/scsi/53c7xx_d.h_shipped   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/53c7xx_d.h_shipped   1969-12-31 19:00:00.000000000 -0500
-@@ -1,2874 +0,0 @@
--/* DO NOT EDIT - Generated automatically by script_asm.pl */
--static u32 SCRIPT[] = {
+ endmenu
+ source "fs/Kconfig"
+diff -Nurb linux-2.6.22-590/arch/arm/boot/.gitignore.rej linux-2.6.22-570/arch/arm/boot/.gitignore.rej
+--- linux-2.6.22-590/arch/arm/boot/.gitignore.rej      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/boot/.gitignore.rej      1969-12-31 19:00:00.000000000 -0500
+@@ -1,10 +0,0 @@
+-***************
+-*** 1,2 ****
+-  Image
+-  zImage
+---- 1,5 ----
+-  Image
+-  zImage
+-+ xipImage
+-+ bootpImage
+-+ uImage
+diff -Nurb linux-2.6.22-590/arch/arm/kernel/Makefile linux-2.6.22-570/arch/arm/kernel/Makefile
+--- linux-2.6.22-590/arch/arm/kernel/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/kernel/Makefile  2007-07-08 19:32:17.000000000 -0400
+@@ -20,7 +20,6 @@
+ obj-$(CONFIG_SMP)             += smp.o
+ obj-$(CONFIG_KEXEC)           += machine_kexec.o relocate_kernel.o
+ obj-$(CONFIG_OABI_COMPAT)     += sys_oabi-compat.o
+-obj-$(CONFIG_KGDB)            += kgdb.o kgdb-jmp.o
+ obj-$(CONFIG_CRUNCH)          += crunch.o crunch-bits.o
+ AFLAGS_crunch-bits.o          := -Wa,-mcpu=ep9312
+diff -Nurb linux-2.6.22-590/arch/arm/kernel/kgdb-jmp.S linux-2.6.22-570/arch/arm/kernel/kgdb-jmp.S
+--- linux-2.6.22-590/arch/arm/kernel/kgdb-jmp.S        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/kernel/kgdb-jmp.S        1969-12-31 19:00:00.000000000 -0500
+@@ -1,32 +0,0 @@
 -/*
+- * arch/arm/kernel/kgdb-jmp.S
+- *
+- * Trivial setjmp and longjmp procedures to support bus error recovery
+- * which may occur during kgdb memory read/write operations.
+- *
+- * Author: MontaVista Software, Inc. <source@mvista.com>
+- *         source@mvista.com
+- *
+- * 2002-2005 (c) MontaVista Software, Inc.  This file is licensed under the
+- * terms of the GNU General Public License version 2. This program as licensed
+- * "as is" without any warranty of any kind, whether express or implied.
+- */
+-#include <linux/linkage.h>
 -
+-ENTRY (kgdb_fault_setjmp)
+-      /* Save registers */
+-      stmia   r0, {r0-r14}
+-      str     lr,[r0, #60]
+-      mrs     r1,cpsr
+-      str     r1,[r0,#64]
+-      ldr     r1,[r0,#4]
+-      mov     r0, #0
+-      mov     pc,lr
+-
+-ENTRY (kgdb_fault_longjmp)
+-      /* Restore registers */
+-      mov     r1,#1
+-      str     r1,[r0]
+-      ldr     r1,[r0, #64]
+-      msr     spsr,r1
+-      ldmia   r0,{r0-pc}^
+diff -Nurb linux-2.6.22-590/arch/arm/kernel/kgdb.c linux-2.6.22-570/arch/arm/kernel/kgdb.c
+--- linux-2.6.22-590/arch/arm/kernel/kgdb.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/kernel/kgdb.c    1969-12-31 19:00:00.000000000 -0500
+@@ -1,202 +0,0 @@
+-/*
+- * arch/arm/kernel/kgdb.c
+- *
+- * ARM KGDB support
+- *
+- * Copyright (c) 2002-2004 MontaVista Software, Inc
+- *
+- * Authors:  George Davis <davis_g@mvista.com>
+- *           Deepak Saxena <dsaxena@plexity.net>
+- */
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/mm.h>
+-#include <linux/spinlock.h>
+-#include <linux/personality.h>
+-#include <linux/ptrace.h>
+-#include <linux/elf.h>
+-#include <linux/interrupt.h>
+-#include <linux/init.h>
+-#include <linux/kgdb.h>
 -
+-#include <asm/atomic.h>
+-#include <asm/io.h>
+-#include <asm/pgtable.h>
+-#include <asm/system.h>
+-#include <asm/uaccess.h>
+-#include <asm/unistd.h>
+-#include <asm/ptrace.h>
+-#include <asm/traps.h>
 -
+-/* Make a local copy of the registers passed into the handler (bletch) */
+-void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
+-{
+-      int regno;
+-
+-      /* Initialize all to zero (??) */
+-      for (regno = 0; regno < GDB_MAX_REGS; regno++)
+-              gdb_regs[regno] = 0;
+-
+-      gdb_regs[_R0] = kernel_regs->ARM_r0;
+-      gdb_regs[_R1] = kernel_regs->ARM_r1;
+-      gdb_regs[_R2] = kernel_regs->ARM_r2;
+-      gdb_regs[_R3] = kernel_regs->ARM_r3;
+-      gdb_regs[_R4] = kernel_regs->ARM_r4;
+-      gdb_regs[_R5] = kernel_regs->ARM_r5;
+-      gdb_regs[_R6] = kernel_regs->ARM_r6;
+-      gdb_regs[_R7] = kernel_regs->ARM_r7;
+-      gdb_regs[_R8] = kernel_regs->ARM_r8;
+-      gdb_regs[_R9] = kernel_regs->ARM_r9;
+-      gdb_regs[_R10] = kernel_regs->ARM_r10;
+-      gdb_regs[_FP] = kernel_regs->ARM_fp;
+-      gdb_regs[_IP] = kernel_regs->ARM_ip;
+-      gdb_regs[_SP] = kernel_regs->ARM_sp;
+-      gdb_regs[_LR] = kernel_regs->ARM_lr;
+-      gdb_regs[_PC] = kernel_regs->ARM_pc;
+-      gdb_regs[_CPSR] = kernel_regs->ARM_cpsr;
+-}
 -
+-/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
+-void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
+-{
+-      kernel_regs->ARM_r0 = gdb_regs[_R0];
+-      kernel_regs->ARM_r1 = gdb_regs[_R1];
+-      kernel_regs->ARM_r2 = gdb_regs[_R2];
+-      kernel_regs->ARM_r3 = gdb_regs[_R3];
+-      kernel_regs->ARM_r4 = gdb_regs[_R4];
+-      kernel_regs->ARM_r5 = gdb_regs[_R5];
+-      kernel_regs->ARM_r6 = gdb_regs[_R6];
+-      kernel_regs->ARM_r7 = gdb_regs[_R7];
+-      kernel_regs->ARM_r8 = gdb_regs[_R8];
+-      kernel_regs->ARM_r9 = gdb_regs[_R9];
+-      kernel_regs->ARM_r10 = gdb_regs[_R10];
+-      kernel_regs->ARM_fp = gdb_regs[_FP];
+-      kernel_regs->ARM_ip = gdb_regs[_IP];
+-      kernel_regs->ARM_sp = gdb_regs[_SP];
+-      kernel_regs->ARM_lr = gdb_regs[_LR];
+-      kernel_regs->ARM_pc = gdb_regs[_PC];
+-      kernel_regs->ARM_cpsr = gdb_regs[_CPSR];
+-}
+-
+-void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
+-                               struct task_struct *task)
+-{
+-      int regno;
+-      struct pt_regs *thread_regs;
+-
+-      /* Just making sure... */
+-      if (task == NULL)
+-              return;
 -
--; 53c710 driver.  Modified from Drew Eckhardts driver
--; for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
--;
--; I have left the script for the 53c8xx family in here, as it is likely
--; to be useful to see what I changed when bug hunting.
--
--; NCR 53c810 driver, main script
--; Sponsored by 
--;     iX Multiuser Multitasking Magazine
--;     hm@ix.de
--;
--; Copyright 1993, 1994, 1995 Drew Eckhardt
--;      Visionary Computing 
--;      (Unix and Linux consulting and custom programming)
--;      drew@PoohSticks.ORG
--;      +1 (303) 786-7975
--;
--; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
--;
--; PRE-ALPHA
--;
--; For more information, please consult 
--;
--; NCR 53C810
--; PCI-SCSI I/O Processor
--; Data Manual
--;
--; NCR 53C710 
--; SCSI I/O Processor
--; Programmers Guide
--;
--; NCR Microelectronics
--; 1635 Aeroplaza Drive
--; Colorado Springs, CO 80916
--; 1+ (719) 578-3400
--;
--; Toll free literature number
--; +1 (800) 334-5454
--;
--; IMPORTANT : This code is self modifying due to the limitations of 
--;     the NCR53c7,8xx series chips.  Persons debugging this code with
--;     the remote debugger should take this into account, and NOT set
--;     breakpoints in modified instructions.
--;
--; Design:
--; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard 
--; microcontroller using a simple instruction set.   
--;
--; So, to minimize the effects of interrupt latency, and to maximize 
--; throughput, this driver offloads the practical maximum amount 
--; of processing to the SCSI chip while still maintaining a common
--; structure.
--;
--; Where tradeoffs were needed between efficiency on the older
--; chips and the newer NCR53c800 series, the NCR53c800 series 
--; was chosen.
--;
--; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully
--; automate SCSI transfers without host processor intervention, this 
--; isn't the case with the NCR53c710 and newer chips which allow 
--;
--; - reads and writes to the internal registers from within the SCSI
--;     scripts, allowing the SCSI SCRIPTS(tm) code to save processor
--;     state so that multiple threads of execution are possible, and also
--;     provide an ALU for loop control, etc.
--; 
--; - table indirect addressing for some instructions. This allows 
--;     pointers to be located relative to the DSA ((Data Structure
--;     Address) register.
--;
--; These features make it possible to implement a mailbox style interface,
--; where the same piece of code is run to handle I/O for multiple threads
--; at once minimizing our need to relocate code.  Since the NCR53c700/
--; NCR53c800 series have a unique combination of features, making a 
--; a standard ingoing/outgoing mailbox system, costly, I've modified it.
--;
--; - Mailboxes are a mixture of code and data.  This lets us greatly
--;     simplify the NCR53c810 code and do things that would otherwise
--;     not be possible.
--;
--; The saved data pointer is now implemented as follows :
--;
--;     Control flow has been architected such that if control reaches
--;     munge_save_data_pointer, on a restore pointers message or 
--;     reconnection, a jump to the address formerly in the TEMP register
--;     will allow the SCSI command to resume execution.
--;
--
--;
--; Note : the DSA structures must be aligned on 32 bit boundaries,
--; since the source and destination of MOVE MEMORY instructions 
--; must share the same alignment and this is the alignment of the
--; NCR registers.
--;
--
--; For some systems (MVME166, for example) dmode is always the same, so don't
--; waste time writing it
--
--
--
--
--
--
--
--
--
--
--
--ABSOLUTE dsa_temp_lun = 0             ; Patch to lun for current dsa
--ABSOLUTE dsa_temp_next = 0            ; Patch to dsa next for current dsa
--ABSOLUTE dsa_temp_addr_next = 0               ; Patch to address of dsa next address 
--                                      ;       for current dsa
--ABSOLUTE dsa_temp_sync = 0            ; Patch to address of per-target
--                                      ;       sync routine
--ABSOLUTE dsa_sscf_710 = 0             ; Patch to address of per-target
--                                      ;       sscf value (53c710)
--ABSOLUTE dsa_temp_target = 0          ; Patch to id for current dsa
--ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command
--                                      ;       saved data pointer
--ABSOLUTE dsa_temp_addr_residual = 0   ; Patch to address of per-command
--                                      ;       current residual code
--ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command
--                                      ; saved residual code
--ABSOLUTE dsa_temp_addr_new_value = 0  ; Address of value for JUMP operand
--ABSOLUTE dsa_temp_addr_array_value = 0        ; Address to copy to
--ABSOLUTE dsa_temp_addr_dsa_value = 0  ; Address of this DSA value
--
--;
--; Once a device has initiated reselection, we need to compare it 
--; against the singly linked list of commands which have disconnected
--; and are pending reselection.  These commands are maintained in 
--; an unordered singly linked list of DSA structures, through the
--; DSA pointers at their 'centers' headed by the reconnect_dsa_head
--; pointer.
--; 
--; To avoid complications in removing commands from the list,
--; I minimize the amount of expensive (at eight operations per
--; addition @ 500-600ns each) pointer operations which must
--; be done in the NCR driver by precomputing them on the 
--; host processor during dsa structure generation.
--;
--; The fixed-up per DSA code knows how to recognize the nexus
--; associated with the corresponding SCSI command, and modifies
--; the source and destination pointers for the MOVE MEMORY 
--; instruction which is executed when reselected_ok is called
--; to remove the command from the list.  Similarly, DSA is 
--; loaded with the address of the next DSA structure and
--; reselected_check_next is called if a failure occurs.
--;
--; Perhaps more concisely, the net effect of the mess is 
--;
--; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, 
--;     src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) {
--;     src = &dsa->next;
--;     if (target_id == dsa->id && target_lun == dsa->lun) {
--;             *dest = *src;
--;             break;
--;         }   
--; }
--;
--; if (!dsa)
--;           error (int_err_unexpected_reselect);
--; else  
--;     longjmp (dsa->jump_resume, 0);
--;
--;     
--
--
--; Define DSA structure used for mailboxes
--ENTRY dsa_code_template
--dsa_code_template:
--ENTRY dsa_code_begin
--dsa_code_begin:
--; RGH: Don't care about TEMP and DSA here
--      
--      MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch
--
--at 0x00000000 : */    0xc0000004,0x00000000,0x00000000,
--/*
--      
--
--      MOVE MEMORY 4, addr_scratch, saved_dsa
--
--at 0x00000003 : */    0xc0000004,0x00000000,0x00000000,
--/*
--      ; We are about to go and select the device, so must set SSCF bits
--      MOVE MEMORY 4, dsa_sscf_710, addr_scratch
+-      /* Initialize to zero */
+-      for (regno = 0; regno < GDB_MAX_REGS; regno++)
+-              gdb_regs[regno] = 0;
+-
+-      /* Otherwise, we have only some registers from switch_to() */
+-      thread_regs = task_pt_regs(task);
+-      gdb_regs[_R0] = thread_regs->ARM_r0;    /* Not really valid? */
+-      gdb_regs[_R1] = thread_regs->ARM_r1;    /* "               " */
+-      gdb_regs[_R2] = thread_regs->ARM_r2;    /* "               " */
+-      gdb_regs[_R3] = thread_regs->ARM_r3;    /* "               " */
+-      gdb_regs[_R4] = thread_regs->ARM_r4;
+-      gdb_regs[_R5] = thread_regs->ARM_r5;
+-      gdb_regs[_R6] = thread_regs->ARM_r6;
+-      gdb_regs[_R7] = thread_regs->ARM_r7;
+-      gdb_regs[_R8] = thread_regs->ARM_r8;
+-      gdb_regs[_R9] = thread_regs->ARM_r9;
+-      gdb_regs[_R10] = thread_regs->ARM_r10;
+-      gdb_regs[_FP] = thread_regs->ARM_fp;
+-      gdb_regs[_IP] = thread_regs->ARM_ip;
+-      gdb_regs[_SP] = thread_regs->ARM_sp;
+-      gdb_regs[_LR] = thread_regs->ARM_lr;
+-      gdb_regs[_PC] = thread_regs->ARM_pc;
+-      gdb_regs[_CPSR] = thread_regs->ARM_cpsr;
+-}
+-
+-static int compiled_break;
+-
+-int kgdb_arch_handle_exception(int exception_vector, int signo,
+-                             int err_code, char *remcom_in_buffer,
+-                             char *remcom_out_buffer,
+-                             struct pt_regs *linux_regs)
+-{
+-      long addr;
+-      char *ptr;
 -
--at 0x00000006 : */    0xc0000004,0x00000000,0x00000000,
--/*
+-      switch (remcom_in_buffer[0]) {
+-      case 'D':
+-      case 'k':
+-      case 'c':
+-              kgdb_contthread = NULL;
 -
--      MOVE SCRATCH3 TO SFBR
+-              /*
+-               * Try to read optional parameter, pc unchanged if no parm.
+-               * If this was a compiled breakpoint, we need to move
+-               * to the next instruction or we will just breakpoint
+-               * over and over again.
+-               */
+-              ptr = &remcom_in_buffer[1];
+-              if (kgdb_hex2long(&ptr, &addr)) {
+-                      linux_regs->ARM_pc = addr;
+-              } else if (compiled_break == 1) {
+-                      linux_regs->ARM_pc += 4;
+-              }
 -
--at 0x00000009 : */    0x72370000,0x00000000,
--/*
+-              compiled_break = 0;
 -
+-              return 0;
+-      }
 -
+-      return -1;
+-}
 -
--      MOVE SFBR TO SBCL
+-static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
+-{
+-      kgdb_handle_exception(1, SIGTRAP, 0, regs);
 -
--at 0x0000000b : */    0x6a0b0000,0x00000000,
--/*
--      MOVE MEMORY 4, saved_dsa, addr_dsa
+-      return 0;
+-}
 -
--at 0x0000000d : */    0xc0000004,0x00000000,0x00000000,
--/*
+-static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
+-{
+-      compiled_break = 1;
+-      kgdb_handle_exception(1, SIGTRAP, 0, regs);
 -
+-      return 0;
+-}
 -
+-static struct undef_hook kgdb_brkpt_hook = {
+-      .instr_mask = 0xffffffff,
+-      .instr_val = KGDB_BREAKINST,
+-      .fn = kgdb_brk_fn
+-};
 -
--      CALL select
+-static struct undef_hook kgdb_compiled_brkpt_hook = {
+-      .instr_mask = 0xffffffff,
+-      .instr_val = KGDB_COMPILED_BREAK,
+-      .fn = kgdb_compiled_brk_fn
+-};
 -
--at 0x00000010 : */    0x88080000,0x000001f8,
 -/*
--; Handle the phase mismatch which may have resulted from the 
--; MOVE FROM dsa_msgout if we returned here.  The CLEAR ATN 
--; may or may not be necessary, and we should update script_asm.pl
--; to handle multiple pieces.
--    CLEAR ATN
+- * Register our undef instruction hooks with ARM undef core.
+- * We regsiter a hook specifically looking for the KGB break inst
+- * and we handle the normal undef case within the do_undefinstr
+- * handler.
+- */
+-int kgdb_arch_init(void)
+-{
+-      register_undef_hook(&kgdb_brkpt_hook);
+-      register_undef_hook(&kgdb_compiled_brkpt_hook);
 -
--at 0x00000012 : */    0x60000008,0x00000000,
--/*
--    CLEAR ACK
+-      return 0;
+-}
 -
--at 0x00000014 : */    0x60000040,0x00000000,
--/*
+-struct kgdb_arch arch_kgdb_ops = {
+-#ifndef __ARMEB__
+-      .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7}
+-#else
+-      .gdb_bpt_instr = {0xe7, 0xff, 0xde, 0xfe}
+-#endif
+-};
+diff -Nurb linux-2.6.22-590/arch/arm/kernel/setup.c linux-2.6.22-570/arch/arm/kernel/setup.c
+--- linux-2.6.22-590/arch/arm/kernel/setup.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/kernel/setup.c   2007-07-08 19:32:17.000000000 -0400
+@@ -832,11 +832,6 @@
+       conswitchp = &dummy_con;
+ #endif
+ #endif
 -
--; Replace second operand with address of JUMP instruction dest operand
--; in schedule table for this DSA.  Becomes dsa_jump_dest in 53c7,8xx.c.
--ENTRY dsa_code_fix_jump
--dsa_code_fix_jump:
--      MOVE MEMORY 4, NOP_insn, 0
+-#if   defined(CONFIG_KGDB)
+-      extern void __init early_trap_init(void);
+-      early_trap_init();
+-#endif
+ }
+diff -Nurb linux-2.6.22-590/arch/arm/kernel/traps.c linux-2.6.22-570/arch/arm/kernel/traps.c
+--- linux-2.6.22-590/arch/arm/kernel/traps.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/kernel/traps.c   2008-01-23 19:16:03.000000000 -0500
+@@ -301,7 +301,6 @@
+       unsigned int instr;
+       struct undef_hook *hook;
+       siginfo_t info;
+-      mm_segment_t fs;
+       void __user *pc;
+       unsigned long flags;
+@@ -312,8 +311,6 @@
+        */
+       regs->ARM_pc -= correction;
+-      fs = get_fs();
+-      set_fs(KERNEL_DS);
+       pc = (void __user *)instruction_pointer(regs);
+       if (processor_mode(regs) == SVC_MODE) {
+@@ -323,7 +320,6 @@
+       } else {
+               get_user(instr, (u32 __user *)pc);
+       }
+-      set_fs(fs);
+       spin_lock_irqsave(&undef_lock, flags);
+       list_for_each_entry(hook, &undef_hook, node) {
+@@ -711,13 +707,6 @@
+ void __init trap_init(void)
+ {
+-#if   defined(CONFIG_KGDB)
+-      return;
+-}
 -
--at 0x00000016 : */    0xc0000004,0x00000000,0x00000000,
--/*
--      JUMP select_done
+-void __init early_trap_init(void)
+-{
+-#endif
+       unsigned long vectors = CONFIG_VECTORS_BASE;
+       extern char __stubs_start[], __stubs_end[];
+       extern char __vectors_start[], __vectors_end[];
+diff -Nurb linux-2.6.22-590/arch/arm/mach-iop13xx/setup.c linux-2.6.22-570/arch/arm/mach-iop13xx/setup.c
+--- linux-2.6.22-590/arch/arm/mach-iop13xx/setup.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-iop13xx/setup.c     2007-07-08 19:32:17.000000000 -0400
+@@ -25,7 +25,6 @@
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+-#include <asm/hardware/iop_adma.h>
+ #define IOP13XX_UART_XTAL 33334000
+ #define IOP13XX_SETUP_DEBUG 0
+@@ -237,143 +236,19 @@
+ }
+ #endif
+-/* ADMA Channels */
+-static struct resource iop13xx_adma_0_resources[] = {
+-      [0] = {
+-              .start = IOP13XX_ADMA_PHYS_BASE(0),
+-              .end = IOP13XX_ADMA_UPPER_PA(0),
+-              .flags = IORESOURCE_MEM,
+-      },
+-      [1] = {
+-              .start = IRQ_IOP13XX_ADMA0_EOT,
+-              .end = IRQ_IOP13XX_ADMA0_EOT,
+-              .flags = IORESOURCE_IRQ
+-      },
+-      [2] = {
+-              .start = IRQ_IOP13XX_ADMA0_EOC,
+-              .end = IRQ_IOP13XX_ADMA0_EOC,
+-              .flags = IORESOURCE_IRQ
+-      },
+-      [3] = {
+-              .start = IRQ_IOP13XX_ADMA0_ERR,
+-              .end = IRQ_IOP13XX_ADMA0_ERR,
+-              .flags = IORESOURCE_IRQ
+-      }
+-};
 -
--at 0x00000019 : */    0x80080000,0x00000230,
--/*
+-static struct resource iop13xx_adma_1_resources[] = {
+-      [0] = {
+-              .start = IOP13XX_ADMA_PHYS_BASE(1),
+-              .end = IOP13XX_ADMA_UPPER_PA(1),
+-              .flags = IORESOURCE_MEM,
+-      },
+-      [1] = {
+-              .start = IRQ_IOP13XX_ADMA1_EOT,
+-              .end = IRQ_IOP13XX_ADMA1_EOT,
+-              .flags = IORESOURCE_IRQ
+-      },
+-      [2] = {
+-              .start = IRQ_IOP13XX_ADMA1_EOC,
+-              .end = IRQ_IOP13XX_ADMA1_EOC,
+-              .flags = IORESOURCE_IRQ
+-      },
+-      [3] = {
+-              .start = IRQ_IOP13XX_ADMA1_ERR,
+-              .end = IRQ_IOP13XX_ADMA1_ERR,
+-              .flags = IORESOURCE_IRQ
+-      }
+-};
 -
--; wrong_dsa loads the DSA register with the value of the dsa_next
--; field.
--;
--wrong_dsa:
+-static struct resource iop13xx_adma_2_resources[] = {
+-      [0] = {
+-              .start = IOP13XX_ADMA_PHYS_BASE(2),
+-              .end = IOP13XX_ADMA_UPPER_PA(2),
+-              .flags = IORESOURCE_MEM,
+-      },
+-      [1] = {
+-              .start = IRQ_IOP13XX_ADMA2_EOT,
+-              .end = IRQ_IOP13XX_ADMA2_EOT,
+-              .flags = IORESOURCE_IRQ
+-      },
+-      [2] = {
+-              .start = IRQ_IOP13XX_ADMA2_EOC,
+-              .end = IRQ_IOP13XX_ADMA2_EOC,
+-              .flags = IORESOURCE_IRQ
+-      },
+-      [3] = {
+-              .start = IRQ_IOP13XX_ADMA2_ERR,
+-              .end = IRQ_IOP13XX_ADMA2_ERR,
+-              .flags = IORESOURCE_IRQ
+-      }
+-};
 -
--;                NOTE DSA is corrupt when we arrive here!
+-static u64 iop13xx_adma_dmamask = DMA_64BIT_MASK;
+-static struct iop_adma_platform_data iop13xx_adma_0_data = {
+-      .hw_id = 0,
+-      .pool_size = PAGE_SIZE,
+-};
 -
--;             Patch the MOVE MEMORY INSTRUCTION such that 
--;             the destination address is the address of the OLD 
--;             next pointer.
--;
--      MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 8
+-static struct iop_adma_platform_data iop13xx_adma_1_data = {
+-      .hw_id = 1,
+-      .pool_size = PAGE_SIZE,
+-};
 -
--at 0x0000001b : */    0xc0000004,0x00000000,0x000007ec,
--/*
--      
--;
--;     Move the _contents_ of the next pointer into the DSA register as 
--;     the next I_T_L or I_T_L_Q tupple to check against the established
--;     nexus.
--;
--      MOVE MEMORY 4, dsa_temp_next, addr_scratch
--
--at 0x0000001e : */    0xc0000004,0x00000000,0x00000000,
--/*
--      
+-static struct iop_adma_platform_data iop13xx_adma_2_data = {
+-      .hw_id = 2,
+-      .pool_size = PAGE_SIZE,
+-};
 -
--      MOVE MEMORY 4, addr_scratch, saved_dsa
+-/* The ids are fixed up later in iop13xx_platform_init */
+-static struct platform_device iop13xx_adma_0_channel = {
+-      .name = "iop-adma",
+-      .id = 0,
+-      .num_resources = 4,
+-      .resource = iop13xx_adma_0_resources,
+-      .dev = {
+-              .dma_mask = &iop13xx_adma_dmamask,
+-              .coherent_dma_mask = DMA_64BIT_MASK,
+-              .platform_data = (void *) &iop13xx_adma_0_data,
+-      },
+-};
 -
--at 0x00000021 : */    0xc0000004,0x00000000,0x00000000,
--/*
--      MOVE MEMORY 4, saved_dsa, addr_dsa
+-static struct platform_device iop13xx_adma_1_channel = {
+-      .name = "iop-adma",
+-      .id = 0,
+-      .num_resources = 4,
+-      .resource = iop13xx_adma_1_resources,
+-      .dev = {
+-              .dma_mask = &iop13xx_adma_dmamask,
+-              .coherent_dma_mask = DMA_64BIT_MASK,
+-              .platform_data = (void *) &iop13xx_adma_1_data,
+-      },
+-};
 -
--at 0x00000024 : */    0xc0000004,0x00000000,0x00000000,
--/*
+-static struct platform_device iop13xx_adma_2_channel = {
+-      .name = "iop-adma",
+-      .id = 0,
+-      .num_resources = 4,
+-      .resource = iop13xx_adma_2_resources,
+-      .dev = {
+-              .dma_mask = &iop13xx_adma_dmamask,
+-              .coherent_dma_mask = DMA_64BIT_MASK,
+-              .platform_data = (void *) &iop13xx_adma_2_data,
+-      },
+-};
 -
+ void __init iop13xx_map_io(void)
+ {
+       /* Initialize the Static Page Table maps */
+       iotable_init(iop13xx_std_desc, ARRAY_SIZE(iop13xx_std_desc));
+ }
+-static int init_uart;
+-static int init_i2c;
+-static int init_adma;
++static int init_uart = 0;
++static int init_i2c = 0;
+ void __init iop13xx_platform_init(void)
+ {
+       int i;
+-      u32 uart_idx, i2c_idx, adma_idx, plat_idx;
++      u32 uart_idx, i2c_idx, plat_idx;
+       struct platform_device *iop13xx_devices[IQ81340_MAX_PLAT_DEVICES];
+       /* set the bases so we can read the device id */
+@@ -419,12 +294,6 @@
+               }
+       }
+-      if (init_adma == IOP13XX_INIT_ADMA_DEFAULT) {
+-              init_adma |= IOP13XX_INIT_ADMA_0;
+-              init_adma |= IOP13XX_INIT_ADMA_1;
+-              init_adma |= IOP13XX_INIT_ADMA_2;
+-      }
 -
+       plat_idx = 0;
+       uart_idx = 0;
+       i2c_idx = 0;
+@@ -463,56 +332,6 @@
+               }
+       }
+-      /* initialize adma channel ids and capabilities */
+-      adma_idx = 0;
+-      for (i = 0; i < IQ81340_NUM_ADMA; i++) {
+-              struct iop_adma_platform_data *plat_data;
+-              if ((init_adma & (1 << i)) && IOP13XX_SETUP_DEBUG)
+-                      printk(KERN_INFO
+-                              "Adding adma%d to platform device list\n", i);
+-              switch (init_adma & (1 << i)) {
+-              case IOP13XX_INIT_ADMA_0:
+-                      iop13xx_adma_0_channel.id = adma_idx++;
+-                      iop13xx_devices[plat_idx++] = &iop13xx_adma_0_channel;
+-                      plat_data = &iop13xx_adma_0_data;
+-                      dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
+-                      dma_cap_set(DMA_XOR, plat_data->cap_mask);
+-                      dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
+-                      dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
+-                      dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
+-                      dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
+-                      dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
+-                      break;
+-              case IOP13XX_INIT_ADMA_1:
+-                      iop13xx_adma_1_channel.id = adma_idx++;
+-                      iop13xx_devices[plat_idx++] = &iop13xx_adma_1_channel;
+-                      plat_data = &iop13xx_adma_1_data;
+-                      dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
+-                      dma_cap_set(DMA_XOR, plat_data->cap_mask);
+-                      dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
+-                      dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
+-                      dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
+-                      dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
+-                      dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
+-                      break;
+-              case IOP13XX_INIT_ADMA_2:
+-                      iop13xx_adma_2_channel.id = adma_idx++;
+-                      iop13xx_devices[plat_idx++] = &iop13xx_adma_2_channel;
+-                      plat_data = &iop13xx_adma_2_data;
+-                      dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
+-                      dma_cap_set(DMA_XOR, plat_data->cap_mask);
+-                      dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
+-                      dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
+-                      dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
+-                      dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
+-                      dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
+-                      dma_cap_set(DMA_PQ_XOR, plat_data->cap_mask);
+-                      dma_cap_set(DMA_PQ_UPDATE, plat_data->cap_mask);
+-                      dma_cap_set(DMA_PQ_ZERO_SUM, plat_data->cap_mask);
+-                      break;
+-              }
+-      }
 -
--      JUMP reselected_check_next
+ #ifdef CONFIG_MTD_PHYSMAP
+       iq8134x_flash_resource.end = iq8134x_flash_resource.start +
+                               iq8134x_probe_flash_size() - 1;
+@@ -580,35 +399,5 @@
+       return 1;
+ }
+-static int __init iop13xx_init_adma_setup(char *str)
+-{
+-      if (str)        {
+-              while (*str != '\0') {
+-                      switch (*str) {
+-                      case '0':
+-                              init_adma |= IOP13XX_INIT_ADMA_0;
+-                              break;
+-                      case '1':
+-                              init_adma |= IOP13XX_INIT_ADMA_1;
+-                              break;
+-                      case '2':
+-                              init_adma |= IOP13XX_INIT_ADMA_2;
+-                              break;
+-                      case ',':
+-                      case '=':
+-                              break;
+-                      default:
+-                              PRINTK("\"iop13xx_init_adma\" malformed"
+-                                          " at character: \'%c\'", *str);
+-                              *(str + 1) = '\0';
+-                              init_adma = IOP13XX_INIT_ADMA_DEFAULT;
+-                      }
+-                      str++;
+-              }
+-      }
+-      return 1;
+-}
 -
--at 0x00000027 : */    0x80080000,0x000006f0,
--/*
+-__setup("iop13xx_init_adma", iop13xx_init_adma_setup);
+ __setup("iop13xx_init_uart", iop13xx_init_uart_setup);
+ __setup("iop13xx_init_i2c", iop13xx_init_i2c_setup);
+diff -Nurb linux-2.6.22-590/arch/arm/mach-iop32x/glantank.c linux-2.6.22-570/arch/arm/mach-iop32x/glantank.c
+--- linux-2.6.22-590/arch/arm/mach-iop32x/glantank.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-iop32x/glantank.c   2007-07-08 19:32:17.000000000 -0400
+@@ -180,8 +180,6 @@
+       platform_device_register(&iop3xx_i2c1_device);
+       platform_device_register(&glantank_flash_device);
+       platform_device_register(&glantank_serial_device);
+-      platform_device_register(&iop3xx_dma_0_channel);
+-      platform_device_register(&iop3xx_dma_1_channel);
+       pm_power_off = glantank_power_off;
+ }
+diff -Nurb linux-2.6.22-590/arch/arm/mach-iop32x/iq31244.c linux-2.6.22-570/arch/arm/mach-iop32x/iq31244.c
+--- linux-2.6.22-590/arch/arm/mach-iop32x/iq31244.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-iop32x/iq31244.c    2007-07-08 19:32:17.000000000 -0400
+@@ -298,14 +298,9 @@
+       platform_device_register(&iop3xx_i2c1_device);
+       platform_device_register(&iq31244_flash_device);
+       platform_device_register(&iq31244_serial_device);
+-      platform_device_register(&iop3xx_dma_0_channel);
+-      platform_device_register(&iop3xx_dma_1_channel);
+       if (is_ep80219())
+               pm_power_off = ep80219_power_off;
 -
--ABSOLUTE dsa_save_data_pointer = 0
--ENTRY dsa_code_save_data_pointer
--dsa_code_save_data_pointer:
+-      if (!is_80219())
+-              platform_device_register(&iop3xx_aau_channel);
+ }
+ static int __init force_ep80219_setup(char *str)
+diff -Nurb linux-2.6.22-590/arch/arm/mach-iop32x/iq80321.c linux-2.6.22-570/arch/arm/mach-iop32x/iq80321.c
+--- linux-2.6.22-590/arch/arm/mach-iop32x/iq80321.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-iop32x/iq80321.c    2007-07-08 19:32:17.000000000 -0400
+@@ -181,9 +181,6 @@
+       platform_device_register(&iop3xx_i2c1_device);
+       platform_device_register(&iq80321_flash_device);
+       platform_device_register(&iq80321_serial_device);
+-      platform_device_register(&iop3xx_dma_0_channel);
+-      platform_device_register(&iop3xx_dma_1_channel);
+-      platform_device_register(&iop3xx_aau_channel);
+ }
+ MACHINE_START(IQ80321, "Intel IQ80321")
+diff -Nurb linux-2.6.22-590/arch/arm/mach-iop32x/n2100.c linux-2.6.22-570/arch/arm/mach-iop32x/n2100.c
+--- linux-2.6.22-590/arch/arm/mach-iop32x/n2100.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-iop32x/n2100.c      2007-07-08 19:32:17.000000000 -0400
+@@ -245,8 +245,6 @@
+       platform_device_register(&iop3xx_i2c0_device);
+       platform_device_register(&n2100_flash_device);
+       platform_device_register(&n2100_serial_device);
+-      platform_device_register(&iop3xx_dma_0_channel);
+-      platform_device_register(&iop3xx_dma_1_channel);
+       pm_power_off = n2100_power_off;
+diff -Nurb linux-2.6.22-590/arch/arm/mach-iop33x/iq80331.c linux-2.6.22-570/arch/arm/mach-iop33x/iq80331.c
+--- linux-2.6.22-590/arch/arm/mach-iop33x/iq80331.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-iop33x/iq80331.c    2007-07-08 19:32:17.000000000 -0400
+@@ -136,9 +136,6 @@
+       platform_device_register(&iop33x_uart0_device);
+       platform_device_register(&iop33x_uart1_device);
+       platform_device_register(&iq80331_flash_device);
+-      platform_device_register(&iop3xx_dma_0_channel);
+-      platform_device_register(&iop3xx_dma_1_channel);
+-      platform_device_register(&iop3xx_aau_channel);
+ }
+ MACHINE_START(IQ80331, "Intel IQ80331")
+diff -Nurb linux-2.6.22-590/arch/arm/mach-iop33x/iq80332.c linux-2.6.22-570/arch/arm/mach-iop33x/iq80332.c
+--- linux-2.6.22-590/arch/arm/mach-iop33x/iq80332.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-iop33x/iq80332.c    2007-07-08 19:32:17.000000000 -0400
+@@ -136,9 +136,6 @@
+       platform_device_register(&iop33x_uart0_device);
+       platform_device_register(&iop33x_uart1_device);
+       platform_device_register(&iq80332_flash_device);
+-      platform_device_register(&iop3xx_dma_0_channel);
+-      platform_device_register(&iop3xx_dma_1_channel);
+-      platform_device_register(&iop3xx_aau_channel);
+ }
+ MACHINE_START(IQ80332, "Intel IQ80332")
+diff -Nurb linux-2.6.22-590/arch/arm/mach-ixp2000/core.c linux-2.6.22-570/arch/arm/mach-ixp2000/core.c
+--- linux-2.6.22-590/arch/arm/mach-ixp2000/core.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-ixp2000/core.c      2007-07-08 19:32:17.000000000 -0400
+@@ -34,7 +34,6 @@
+ #include <asm/system.h>
+ #include <asm/tlbflush.h>
+ #include <asm/pgtable.h>
+-#include <asm/kgdb.h>
+ #include <asm/mach/map.h>
+ #include <asm/mach/time.h>
+@@ -185,9 +184,6 @@
+ void __init ixp2000_uart_init(void)
+ {
+       platform_device_register(&ixp2000_serial_device);
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_platform_port(0, &ixp2000_serial_port);
+-#endif
+ }
+diff -Nurb linux-2.6.22-590/arch/arm/mach-ixp2000/ixdp2x01.c linux-2.6.22-570/arch/arm/mach-ixp2000/ixdp2x01.c
+--- linux-2.6.22-590/arch/arm/mach-ixp2000/ixdp2x01.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-ixp2000/ixdp2x01.c  2007-07-08 19:32:17.000000000 -0400
+@@ -38,7 +38,6 @@
+ #include <asm/system.h>
+ #include <asm/hardware.h>
+ #include <asm/mach-types.h>
+-#include <asm/kgdb.h>
+ #include <asm/mach/pci.h>
+ #include <asm/mach/map.h>
+@@ -414,11 +413,6 @@
+       platform_add_devices(ixdp2x01_devices, ARRAY_SIZE(ixdp2x01_devices));
+       ixp2000_uart_init();
+       ixdp2x01_uart_init();
 -
--      ; When we get here, TEMP has been saved in jump_temp+4, DSA is corrupt
--      ; We MUST return with DSA correct
--      MOVE MEMORY 4, jump_temp+4, dsa_temp_addr_saved_pointer
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_platform_port(0, ixdp2x01_serial_port1);
+-      kgdb8250_add_platform_port(1, ixdp2x01_serial_port1);
+-#endif
+ }
+diff -Nurb linux-2.6.22-590/arch/arm/mach-ixp4xx/coyote-setup.c linux-2.6.22-570/arch/arm/mach-ixp4xx/coyote-setup.c
+--- linux-2.6.22-590/arch/arm/mach-ixp4xx/coyote-setup.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-ixp4xx/coyote-setup.c       2007-07-08 19:32:17.000000000 -0400
+@@ -96,10 +96,6 @@
+       }
+       platform_add_devices(coyote_devices, ARRAY_SIZE(coyote_devices));
 -
--at 0x00000029 : */    0xc0000004,0x000009c8,0x00000000,
--/*
--; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
--      MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_platform_port(0, &coyote_uart_data);
+-#endif
+ }
+ #ifdef CONFIG_ARCH_ADI_COYOTE
+diff -Nurb linux-2.6.22-590/arch/arm/mach-ixp4xx/ixdp425-setup.c linux-2.6.22-570/arch/arm/mach-ixp4xx/ixdp425-setup.c
+--- linux-2.6.22-590/arch/arm/mach-ixp4xx/ixdp425-setup.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-ixp4xx/ixdp425-setup.c      2007-07-08 19:32:17.000000000 -0400
+@@ -76,8 +76,7 @@
+               .mapbase        = IXP4XX_UART1_BASE_PHYS,
+               .membase        = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+               .irq            = IRQ_IXP4XX_UART1,
+-              .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+-                                      UPF_SHARE_IRQ,
++              .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IXP4XX_UART_XTAL,
+@@ -86,8 +85,7 @@
+               .mapbase        = IXP4XX_UART2_BASE_PHYS,
+               .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+               .irq            = IRQ_IXP4XX_UART2,
+-              .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+-                                      UPF_SHARE_IRQ,
++              .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IXP4XX_UART_XTAL,
+@@ -125,22 +123,12 @@
+       platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
+ }
+-static void __init ixdp425_map_io(void)
+-{
+-      ixp4xx_map_io();
 -
--at 0x0000002c : */    0xc0000018,0x00000000,0x00000000,
--/*
--        CLEAR ACK
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_platform_port(0, &ixdp425_uart_data[0]);
+-      kgdb8250_add_platform_port(1, &ixdp425_uart_data[1]);
+-#endif
+-}
 -
--at 0x0000002f : */    0x60000040,0x00000000,
+ #ifdef CONFIG_ARCH_IXDP425
+ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
+       /* Maintainer: MontaVista Software, Inc. */
+       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
+       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+-      .map_io         = ixdp425_map_io,
++      .map_io         = ixp4xx_map_io,
+       .init_irq       = ixp4xx_init_irq,
+       .timer          = &ixp4xx_timer,
+       .boot_params    = 0x0100,
+@@ -153,7 +141,7 @@
+       /* Maintainer: MontaVista Software, Inc. */
+       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
+       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+-      .map_io         = ixdp425_map_io,
++      .map_io         = ixp4xx_map_io,
+       .init_irq       = ixp4xx_init_irq,
+       .timer          = &ixp4xx_timer,
+       .boot_params    = 0x0100,
+diff -Nurb linux-2.6.22-590/arch/arm/mach-omap1/serial.c linux-2.6.22-570/arch/arm/mach-omap1/serial.c
+--- linux-2.6.22-590/arch/arm/mach-omap1/serial.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-omap1/serial.c      2007-07-08 19:32:17.000000000 -0400
+@@ -15,7 +15,6 @@
+ #include <linux/delay.h>
+ #include <linux/serial.h>
+ #include <linux/tty.h>
+-#include <linux/kgdb.h>
+ #include <linux/serial_8250.h>
+ #include <linux/serial_reg.h>
+ #include <linux/clk.h>
+@@ -200,9 +199,6 @@
+                       break;
+               }
+               omap_serial_reset(&serial_platform_data[i]);
+-#ifdef CONFIG_KGDB_8250
+-              kgdb8250_add_platform_port(i, &serial_platform_data[i]);
+-#endif
+       }
+ }
+diff -Nurb linux-2.6.22-590/arch/arm/mach-pnx4008/core.c linux-2.6.22-570/arch/arm/mach-pnx4008/core.c
+--- linux-2.6.22-590/arch/arm/mach-pnx4008/core.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-pnx4008/core.c      2007-07-08 19:32:17.000000000 -0400
+@@ -224,10 +224,6 @@
+       spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+       /* Switch on the UART clocks */
+       pnx4008_uart_init();
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_platform_port(0, &platform_serial_ports[0]);
+-      kgdb8250_add_platform_port(1, &platform_serial_ports[1]);
+-#endif
+ }
+ static struct map_desc pnx4008_io_desc[] __initdata = {
+diff -Nurb linux-2.6.22-590/arch/arm/mach-pxa/Makefile linux-2.6.22-570/arch/arm/mach-pxa/Makefile
+--- linux-2.6.22-590/arch/arm/mach-pxa/Makefile        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-pxa/Makefile        2007-07-08 19:32:17.000000000 -0400
+@@ -31,7 +31,6 @@
+ # Misc features
+ obj-$(CONFIG_PM) += pm.o sleep.o
+ obj-$(CONFIG_PXA_SSP) += ssp.o
+-obj-$(CONFIG_KGDB_PXA_SERIAL) += kgdb-serial.o
+ ifeq ($(CONFIG_PXA27x),y)
+ obj-$(CONFIG_PM) += standby.o
+diff -Nurb linux-2.6.22-590/arch/arm/mach-pxa/kgdb-serial.c linux-2.6.22-570/arch/arm/mach-pxa/kgdb-serial.c
+--- linux-2.6.22-590/arch/arm/mach-pxa/kgdb-serial.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-pxa/kgdb-serial.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,97 +0,0 @@
 -/*
+- * linux/arch/arm/mach-pxa/kgdb-serial.c
+- *
+- * Provides low level kgdb serial support hooks for PXA2xx boards
+- *
+- * Author:    Nicolas Pitre
+- * Copyright: (C) 2002-2005 MontaVista Software Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
 -
+-#include <linux/serial_reg.h>
+-#include <linux/kgdb.h>
+-#include <asm/processor.h>
+-#include <asm/hardware.h>
+-#include <asm/arch/pxa-regs.h>
 -
+-#if   defined(CONFIG_KGDB_PXA_FFUART)
 -
--      MOVE MEMORY 4, saved_dsa, addr_dsa
--
--at 0x00000031 : */    0xc0000004,0x00000000,0x00000000,
--/*
--      JUMP jump_temp
--
--at 0x00000034 : */    0x80080000,0x000009c4,
--/*
--
--ABSOLUTE dsa_restore_pointers = 0
--ENTRY dsa_code_restore_pointers
--dsa_code_restore_pointers:
+-#define UART          FFUART
+-#define CKEN_UART     CKEN6_FFUART
+-#define GPIO_RX_MD    GPIO34_FFRXD_MD
+-#define GPIO_TX_MD    GPIO39_FFTXD_MD
 -
--      ; TEMP and DSA are corrupt when we get here, but who cares!
--      MOVE MEMORY 4, dsa_temp_addr_saved_pointer, jump_temp + 4
+-#elif defined(CONFIG_KGDB_PXA_BTUART)
 -
--at 0x00000036 : */    0xc0000004,0x00000000,0x000009c8,
--/*
--; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
--      MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
+-#define UART          BTUART
+-#define CKEN_UART     CKEN7_BTUART
+-#define GPIO_RX_MD    GPIO42_BTRXD_MD
+-#define GPIO_TX_MD    GPIO43_BTTXD_MD
 -
--at 0x00000039 : */    0xc0000018,0x00000000,0x00000000,
--/*
--        CLEAR ACK
+-#elif defined(CONFIG_KGDB_PXA_STUART)
 -
--at 0x0000003c : */    0x60000040,0x00000000,
--/*
--      ; Restore DSA, note we don't care about TEMP
--      MOVE MEMORY 4, saved_dsa, addr_dsa
+-#define UART          STUART
+-#define CKEN_UART     CKEN5_STUART
+-#define GPIO_RX_MD    GPIO46_STRXD_MD
+-#define GPIO_TX_MD    GPIO47_STTXD_MD
 -
--at 0x0000003e : */    0xc0000004,0x00000000,0x00000000,
--/*
+-#endif
 -
+-#define UART_BAUDRATE (CONFIG_KGDB_BAUDRATE)
 -
+-static volatile unsigned long *port = (unsigned long *)&UART;
 -
--      JUMP jump_temp
+-static int kgdb_serial_init(void)
+-{
+-      pxa_set_cken(CKEN_UART, 1);
+-      pxa_gpio_mode(GPIO_RX_MD);
+-      pxa_gpio_mode(GPIO_TX_MD);
 -
--at 0x00000041 : */    0x80080000,0x000009c4,
--/*
+-      port[UART_IER] = 0;
+-      port[UART_LCR] = LCR_DLAB;
+-      port[UART_DLL] = ((921600 / UART_BAUDRATE) & 0xff);
+-      port[UART_DLM] = ((921600 / UART_BAUDRATE) >> 8);
+-      port[UART_LCR] = LCR_WLS1 | LCR_WLS0;
+-      port[UART_MCR] = 0;
+-      port[UART_IER] = IER_UUE;
+-      port[UART_FCR] = FCR_ITL_16;
 -
+-      return 0;
+-}
 -
--ABSOLUTE dsa_check_reselect = 0
--; dsa_check_reselect determines whether or not the current target and
--; lun match the current DSA
--ENTRY dsa_code_check_reselect
--dsa_code_check_reselect:
+-static void kgdb_serial_putchar(u8 c)
+-{
+-      if (!(CKEN & CKEN_UART) || port[UART_IER] != IER_UUE)
+-              kgdb_serial_init();
+-      while (!(port[UART_LSR] & LSR_TDRQ))
+-              cpu_relax();
+-      port[UART_TX] = c;
+-}
 -
--      
--      
--      MOVE LCRC TO SFBR               ; LCRC has our ID and his ID bits set
+-static void kgdb_serial_flush(void)
+-{
+-      if ((CKEN & CKEN_UART) && (port[UART_IER] & IER_UUE))
+-              while (!(port[UART_LSR] & LSR_TEMT))
+-                      cpu_relax();
+-}
 -
--at 0x00000043 : */    0x72230000,0x00000000,
--/*
--      JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0x80
+-static int kgdb_serial_getchar(void)
+-{
+-      unsigned char c;
+-      if (!(CKEN & CKEN_UART) || port[UART_IER] != IER_UUE)
+-              kgdb_serial_init();
+-      while (!(port[UART_LSR] & UART_LSR_DR))
+-              cpu_relax();
+-      c = port[UART_RX];
+-      return c;
+-}
 -
--at 0x00000045 : */    0x80848000,0x00ffff50,
+-struct kgdb_io kgdb_io_ops = {
+-      .init = kgdb_serial_init,
+-      .write_char = kgdb_serial_putchar,
+-      .flush = kgdb_serial_flush,
+-      .read_char = kgdb_serial_getchar,
+-};
+diff -Nurb linux-2.6.22-590/arch/arm/mach-versatile/core.c linux-2.6.22-570/arch/arm/mach-versatile/core.c
+--- linux-2.6.22-590/arch/arm/mach-versatile/core.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mach-versatile/core.c    2007-07-08 19:32:17.000000000 -0400
+@@ -184,14 +184,6 @@
+               .type           = MT_DEVICE
+       },
+ #endif
+-#ifdef CONFIG_KGDB_AMBA_PL011
+-      {
+-              .virtual        =  IO_ADDRESS(CONFIG_KGDB_AMBA_BASE),
+-              .pfn            = __phys_to_pfn(CONFIG_KGDB_AMBA_BASE),
+-              .length         = SZ_4K,
+-              .type           = MT_DEVICE
+-      },
+-#endif
+ #ifdef CONFIG_PCI
+       {
+               .virtual        =  IO_ADDRESS(VERSATILE_PCI_CORE_BASE),
+diff -Nurb linux-2.6.22-590/arch/arm/mm/extable.c linux-2.6.22-570/arch/arm/mm/extable.c
+--- linux-2.6.22-590/arch/arm/mm/extable.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/mm/extable.c     2007-07-08 19:32:17.000000000 -0400
+@@ -2,7 +2,6 @@
+  *  linux/arch/arm/mm/extable.c
+  */
+ #include <linux/module.h>
+-#include <linux/kgdb.h>
+ #include <asm/uaccess.h>
+ int fixup_exception(struct pt_regs *regs)
+@@ -12,12 +11,6 @@
+       fixup = search_exception_tables(instruction_pointer(regs));
+       if (fixup)
+               regs->ARM_pc = fixup->fixup;
+-#ifdef CONFIG_KGDB
+-      if (atomic_read(&debugger_active) && kgdb_may_fault)
+-              /* Restore our previous state. */
+-              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+-              /* Not reached. */
+-#endif
+       return fixup != NULL;
+ }
+diff -Nurb linux-2.6.22-590/arch/arm/plat-iop/Makefile linux-2.6.22-570/arch/arm/plat-iop/Makefile
+--- linux-2.6.22-590/arch/arm/plat-iop/Makefile        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/plat-iop/Makefile        2007-07-08 19:32:17.000000000 -0400
+@@ -12,7 +12,6 @@
+ obj-$(CONFIG_ARCH_IOP32X) += time.o
+ obj-$(CONFIG_ARCH_IOP32X) += io.o
+ obj-$(CONFIG_ARCH_IOP32X) += cp6.o
+-obj-$(CONFIG_ARCH_IOP32X) += adma.o
+ # IOP33X
+ obj-$(CONFIG_ARCH_IOP33X) += gpio.o
+@@ -22,7 +21,6 @@
+ obj-$(CONFIG_ARCH_IOP33X) += time.o
+ obj-$(CONFIG_ARCH_IOP33X) += io.o
+ obj-$(CONFIG_ARCH_IOP33X) += cp6.o
+-obj-$(CONFIG_ARCH_IOP33X) += adma.o
+ # IOP13XX
+ obj-$(CONFIG_ARCH_IOP13XX) += cp6.o
+diff -Nurb linux-2.6.22-590/arch/arm/plat-iop/adma.c linux-2.6.22-570/arch/arm/plat-iop/adma.c
+--- linux-2.6.22-590/arch/arm/plat-iop/adma.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/arm/plat-iop/adma.c  1969-12-31 19:00:00.000000000 -0500
+@@ -1,209 +0,0 @@
 -/*
+- * platform device definitions for the iop3xx dma/xor engines
+- * Copyright Â© 2006, Intel Corporation.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- *
+- */
+-#include <linux/platform_device.h>
+-#include <asm/hardware/iop3xx.h>
+-#include <linux/dma-mapping.h>
+-#include <asm/arch/adma.h>
+-#include <asm/hardware/iop_adma.h>
+-
+-#ifdef CONFIG_ARCH_IOP32X
+-#define IRQ_DMA0_EOT IRQ_IOP32X_DMA0_EOT
+-#define IRQ_DMA0_EOC IRQ_IOP32X_DMA0_EOC
+-#define IRQ_DMA0_ERR IRQ_IOP32X_DMA0_ERR
+-
+-#define IRQ_DMA1_EOT IRQ_IOP32X_DMA1_EOT
+-#define IRQ_DMA1_EOC IRQ_IOP32X_DMA1_EOC
+-#define IRQ_DMA1_ERR IRQ_IOP32X_DMA1_ERR
+-
+-#define IRQ_AA_EOT IRQ_IOP32X_AA_EOT
+-#define IRQ_AA_EOC IRQ_IOP32X_AA_EOC
+-#define IRQ_AA_ERR IRQ_IOP32X_AA_ERR
+-#endif
+-#ifdef CONFIG_ARCH_IOP33X
+-#define IRQ_DMA0_EOT IRQ_IOP33X_DMA0_EOT
+-#define IRQ_DMA0_EOC IRQ_IOP33X_DMA0_EOC
+-#define IRQ_DMA0_ERR IRQ_IOP33X_DMA0_ERR
+-
+-#define IRQ_DMA1_EOT IRQ_IOP33X_DMA1_EOT
+-#define IRQ_DMA1_EOC IRQ_IOP33X_DMA1_EOC
+-#define IRQ_DMA1_ERR IRQ_IOP33X_DMA1_ERR
+-
+-#define IRQ_AA_EOT IRQ_IOP33X_AA_EOT
+-#define IRQ_AA_EOC IRQ_IOP33X_AA_EOC
+-#define IRQ_AA_ERR IRQ_IOP33X_AA_ERR
+-#endif
+-/* AAU and DMA Channels */
+-static struct resource iop3xx_dma_0_resources[] = {
+-      [0] = {
+-              .start = IOP3XX_DMA_PHYS_BASE(0),
+-              .end = IOP3XX_DMA_UPPER_PA(0),
+-              .flags = IORESOURCE_MEM,
+-      },
+-      [1] = {
+-              .start = IRQ_DMA0_EOT,
+-              .end = IRQ_DMA0_EOT,
+-              .flags = IORESOURCE_IRQ
+-      },
+-      [2] = {
+-              .start = IRQ_DMA0_EOC,
+-              .end = IRQ_DMA0_EOC,
+-              .flags = IORESOURCE_IRQ
+-      },
+-      [3] = {
+-              .start = IRQ_DMA0_ERR,
+-              .end = IRQ_DMA0_ERR,
+-              .flags = IORESOURCE_IRQ
+-      }
+-};
 -
+-static struct resource iop3xx_dma_1_resources[] = {
+-      [0] = {
+-              .start = IOP3XX_DMA_PHYS_BASE(1),
+-              .end = IOP3XX_DMA_UPPER_PA(1),
+-              .flags = IORESOURCE_MEM,
+-      },
+-      [1] = {
+-              .start = IRQ_DMA1_EOT,
+-              .end = IRQ_DMA1_EOT,
+-              .flags = IORESOURCE_IRQ
+-      },
+-      [2] = {
+-              .start = IRQ_DMA1_EOC,
+-              .end = IRQ_DMA1_EOC,
+-              .flags = IORESOURCE_IRQ
+-      },
+-      [3] = {
+-              .start = IRQ_DMA1_ERR,
+-              .end = IRQ_DMA1_ERR,
+-              .flags = IORESOURCE_IRQ
+-      }
+-};
 -
 -
+-static struct resource iop3xx_aau_resources[] = {
+-      [0] = {
+-              .start = IOP3XX_AAU_PHYS_BASE,
+-              .end = IOP3XX_AAU_UPPER_PA,
+-              .flags = IORESOURCE_MEM,
+-      },
+-      [1] = {
+-              .start = IRQ_AA_EOT,
+-              .end = IRQ_AA_EOT,
+-              .flags = IORESOURCE_IRQ
+-      },
+-      [2] = {
+-              .start = IRQ_AA_EOC,
+-              .end = IRQ_AA_EOC,
+-              .flags = IORESOURCE_IRQ
+-      },
+-      [3] = {
+-              .start = IRQ_AA_ERR,
+-              .end = IRQ_AA_ERR,
+-              .flags = IORESOURCE_IRQ
+-      }
+-};
 -
+-static u64 iop3xx_adma_dmamask = DMA_32BIT_MASK;
 -
--;
--; Hack - move to scratch first, since SFBR is not writeable
--;     via the CPU and hence a MOVE MEMORY instruction.
--;
--      
--      MOVE MEMORY 1, reselected_identify, addr_scratch
--
--at 0x00000047 : */    0xc0000001,0x00000000,0x00000000,
--/*
--      
--
--      ; BIG ENDIAN ON MVME16x
--      MOVE SCRATCH3 TO SFBR
+-static struct iop_adma_platform_data iop3xx_dma_0_data = {
+-      .hw_id = DMA0_ID,
+-      .pool_size = PAGE_SIZE,
+-};
 -
--at 0x0000004a : */    0x72370000,0x00000000,
--/*
+-static struct iop_adma_platform_data iop3xx_dma_1_data = {
+-      .hw_id = DMA1_ID,
+-      .pool_size = PAGE_SIZE,
+-};
 -
+-static struct iop_adma_platform_data iop3xx_aau_data = {
+-      .hw_id = AAU_ID,
+-      .pool_size = 3 * PAGE_SIZE,
+-};
 -
+-struct platform_device iop3xx_dma_0_channel = {
+-      .name = "iop-adma",
+-      .id = 0,
+-      .num_resources = 4,
+-      .resource = iop3xx_dma_0_resources,
+-      .dev = {
+-              .dma_mask = &iop3xx_adma_dmamask,
+-              .coherent_dma_mask = DMA_64BIT_MASK,
+-              .platform_data = (void *) &iop3xx_dma_0_data,
+-      },
+-};
 -
--; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
--; Are you sure about that?  richard@sleepie.demon.co.uk
--      JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8
+-struct platform_device iop3xx_dma_1_channel = {
+-      .name = "iop-adma",
+-      .id = 1,
+-      .num_resources = 4,
+-      .resource = iop3xx_dma_1_resources,
+-      .dev = {
+-              .dma_mask = &iop3xx_adma_dmamask,
+-              .coherent_dma_mask = DMA_64BIT_MASK,
+-              .platform_data = (void *) &iop3xx_dma_1_data,
+-      },
+-};
 -
--at 0x0000004c : */    0x8084f800,0x00ffff34,
--/*
--;             Patch the MOVE MEMORY INSTRUCTION such that
--;             the source address is the address of this dsa's
--;             next pointer.
--      MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 4
+-struct platform_device iop3xx_aau_channel = {
+-      .name = "iop-adma",
+-      .id = 2,
+-      .num_resources = 4,
+-      .resource = iop3xx_aau_resources,
+-      .dev = {
+-              .dma_mask = &iop3xx_adma_dmamask,
+-              .coherent_dma_mask = DMA_64BIT_MASK,
+-              .platform_data = (void *) &iop3xx_aau_data,
+-      },
+-};
 -
--at 0x0000004e : */    0xc0000004,0x00000000,0x000007e8,
--/*
--      CALL reselected_ok
+-static int __init iop3xx_adma_cap_init(void)
+-{
+-      #ifdef CONFIG_ARCH_IOP32X /* the 32x DMA does not perform CRC32C */
+-      dma_cap_set(DMA_MEMCPY, iop3xx_dma_0_data.cap_mask);
+-      dma_cap_set(DMA_INTERRUPT, iop3xx_dma_0_data.cap_mask);
+-      #else
+-      dma_cap_set(DMA_MEMCPY, iop3xx_dma_0_data.cap_mask);
+-      dma_cap_set(DMA_MEMCPY_CRC32C, iop3xx_dma_0_data.cap_mask);
+-      dma_cap_set(DMA_INTERRUPT, iop3xx_dma_0_data.cap_mask);
+-      #endif
+-
+-      #ifdef CONFIG_ARCH_IOP32X /* the 32x DMA does not perform CRC32C */
+-      dma_cap_set(DMA_MEMCPY, iop3xx_dma_1_data.cap_mask);
+-      dma_cap_set(DMA_INTERRUPT, iop3xx_dma_1_data.cap_mask);
+-      #else
+-      dma_cap_set(DMA_MEMCPY, iop3xx_dma_1_data.cap_mask);
+-      dma_cap_set(DMA_MEMCPY_CRC32C, iop3xx_dma_1_data.cap_mask);
+-      dma_cap_set(DMA_INTERRUPT, iop3xx_dma_1_data.cap_mask);
+-      #endif
+-
+-      #ifdef CONFIG_ARCH_IOP32X /* the 32x AAU does not perform zero sum */
+-      dma_cap_set(DMA_XOR, iop3xx_aau_data.cap_mask);
+-      dma_cap_set(DMA_MEMSET, iop3xx_aau_data.cap_mask);
+-      dma_cap_set(DMA_INTERRUPT, iop3xx_aau_data.cap_mask);
+-      #else
+-      dma_cap_set(DMA_XOR, iop3xx_aau_data.cap_mask);
+-      dma_cap_set(DMA_ZERO_SUM, iop3xx_aau_data.cap_mask);
+-      dma_cap_set(DMA_MEMSET, iop3xx_aau_data.cap_mask);
+-      dma_cap_set(DMA_INTERRUPT, iop3xx_aau_data.cap_mask);
+-      #endif
 -
--at 0x00000051 : */    0x88080000,0x00000798,
--/*
+-      return 0;
+-}
 -
--;     Restore DSA following memory moves in reselected_ok
--;     dsa_temp_sync doesn't really care about DSA, but it has an
--;     optional debug INT so a valid DSA is a good idea.
--      MOVE MEMORY 4, saved_dsa, addr_dsa
+-arch_initcall(iop3xx_adma_cap_init);
+diff -Nurb linux-2.6.22-590/arch/i386/Kconfig linux-2.6.22-570/arch/i386/Kconfig
+--- linux-2.6.22-590/arch/i386/Kconfig 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/Kconfig 2008-01-23 19:16:03.000000000 -0500
+@@ -1053,8 +1053,6 @@
+ source "arch/i386/kernel/cpu/cpufreq/Kconfig"
+-source "drivers/cpuidle/Kconfig"
 -
--at 0x00000053 : */    0xc0000004,0x00000000,0x00000000,
+ endmenu
+ menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
+diff -Nurb linux-2.6.22-590/arch/i386/kernel/Makefile linux-2.6.22-570/arch/i386/kernel/Makefile
+--- linux-2.6.22-590/arch/i386/kernel/Makefile 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/kernel/Makefile 2008-01-23 19:15:54.000000000 -0500
+@@ -39,7 +39,6 @@
+ obj-$(CONFIG_EARLY_PRINTK)    += early_printk.o
+ obj-$(CONFIG_HPET_TIMER)      += hpet.o
+ obj-$(CONFIG_K8_NB)           += k8.o
+-obj-$(CONFIG_STACK_UNWIND)    += unwind.o
+ obj-$(CONFIG_VMI)             += vmi.o vmiclock.o
+ obj-$(CONFIG_PARAVIRT)                += paravirt.o
+diff -Nurb linux-2.6.22-590/arch/i386/kernel/acpi/boot.c linux-2.6.22-570/arch/i386/kernel/acpi/boot.c
+--- linux-2.6.22-590/arch/i386/kernel/acpi/boot.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/kernel/acpi/boot.c      2007-07-08 19:32:17.000000000 -0400
+@@ -950,6 +950,14 @@
+        },
+       {
+        .callback = force_acpi_ht,
++       .ident = "DELL GX240",
++       .matches = {
++                   DMI_MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
++                   DMI_MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
++                   },
++       },
++      {
++       .callback = force_acpi_ht,
+        .ident = "HP VISUALIZE NT Workstation",
+        .matches = {
+                    DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+diff -Nurb linux-2.6.22-590/arch/i386/kernel/apm.c linux-2.6.22-570/arch/i386/kernel/apm.c
+--- linux-2.6.22-590/arch/i386/kernel/apm.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/kernel/apm.c    2007-07-08 19:32:17.000000000 -0400
+@@ -222,7 +222,6 @@
+ #include <linux/capability.h>
+ #include <linux/device.h>
+ #include <linux/kernel.h>
+-#include <linux/freezer.h>
+ #include <linux/smp.h>
+ #include <linux/dmi.h>
+ #include <linux/suspend.h>
+@@ -2312,6 +2311,7 @@
+               remove_proc_entry("apm", NULL);
+               return err;
+       }
++      kapmd_task->flags |= PF_NOFREEZE;
+       wake_up_process(kapmd_task);
+       if (num_online_cpus() > 1 && !smp ) {
+diff -Nurb linux-2.6.22-590/arch/i386/kernel/io_apic.c linux-2.6.22-570/arch/i386/kernel/io_apic.c
+--- linux-2.6.22-590/arch/i386/kernel/io_apic.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/kernel/io_apic.c        2008-01-23 19:15:54.000000000 -0500
+@@ -667,7 +667,6 @@
+               set_pending_irq(i, cpumask_of_cpu(0));
+       }
+-      set_freezable();
+       for ( ; ; ) {
+               time_remaining = schedule_timeout_interruptible(time_remaining);
+               try_to_freeze();
+diff -Nurb linux-2.6.22-590/arch/i386/kernel/kgdb-jmp.S linux-2.6.22-570/arch/i386/kernel/kgdb-jmp.S
+--- linux-2.6.22-590/arch/i386/kernel/kgdb-jmp.S       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/kernel/kgdb-jmp.S       1969-12-31 19:00:00.000000000 -0500
+@@ -1,74 +0,0 @@
 -/*
+- * arch/i386/kernel/kgdb-jmp.S
+- *
+- * Save and restore system registers so that within a limited frame we
+- * may have a fault and "jump back" to a known safe location.
+- *
+- * Author: George Anzinger <george@mvista.com>
+- *
+- * Cribbed from glibc, which carries the following:
+- * Copyright (C) 1996, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
+- * Copyright (C) 2005 by MontaVista Software.
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program as licensed "as is" without any warranty of
+- * any kind, whether express or implied.
+- */
 -
--      CALL dsa_temp_sync      
--
--at 0x00000056 : */    0x88080000,0x00000000,
--/*
--; Release ACK on the IDENTIFY message _after_ we've set the synchronous 
--; transfer parameters! 
--      CLEAR ACK
+-#include <linux/linkage.h>
 -
--at 0x00000058 : */    0x60000040,0x00000000,
--/*
--; Implicitly restore pointers on reselection, so a RETURN
--; will transfer control back to the right spot.
--      CALL REL (dsa_code_restore_pointers)
+-#define PCOFF         0
+-#define LINKAGE               4               /* just the return address */
+-#define PTR_SIZE      4
+-#define PARMS         LINKAGE         /* no space for saved regs */
+-#define JMPBUF                PARMS
+-#define VAL           JMPBUF+PTR_SIZE
+-
+-#define JB_BX         0
+-#define JB_SI         1
+-#define JB_DI         2
+-#define JB_BP         3
+-#define JB_SP         4
+-#define JB_PC         5
+-
+-/* This must be called prior to kgdb_fault_longjmp and
+- * kgdb_fault_longjmp must not be called outside of the context of the
+- * last call to kgdb_fault_setjmp.
+- * kgdb_fault_setjmp(int *jmp_buf[6])
+- */
+-ENTRY(kgdb_fault_setjmp)
+-      movl JMPBUF(%esp), %eax
+-
+-      /* Save registers.  */
+-      movl    %ebx, (JB_BX*4)(%eax)
+-      movl    %esi, (JB_SI*4)(%eax)
+-      movl    %edi, (JB_DI*4)(%eax)
+-      /* Save SP as it will be after we return.  */
+-      leal    JMPBUF(%esp), %ecx
+-      movl    %ecx, (JB_SP*4)(%eax)
+-      movl    PCOFF(%esp), %ecx       /* Save PC we are returning to now.  */
+-      movl    %ecx, (JB_PC*4)(%eax)
+-      movl    %ebp, (JB_BP*4)(%eax)   /* Save caller's frame pointer.  */
+-
+-      /* Restore state so we can now try the access. */
+-      movl    JMPBUF(%esp), %ecx      /* User's jmp_buf in %ecx.  */
+-      /* Save the return address now.  */
+-      movl    (JB_PC*4)(%ecx), %edx
+-      /* Restore registers.  */
+-      movl    $0, %eax
+-      movl    (JB_SP*4)(%ecx), %esp
+-      jmp     *%edx           /* Jump to saved PC. */
+-
+-/* kgdb_fault_longjmp(int *jmp_buf[6]) */
+-ENTRY(kgdb_fault_longjmp)
+-      movl    JMPBUF(%esp), %ecx      /* User's jmp_buf in %ecx.  */
+-      /* Save the return address now.  */
+-      movl    (JB_PC*4)(%ecx), %edx
+-      /* Restore registers.  */
+-      movl    (JB_BX*4)(%ecx), %ebx
+-      movl    (JB_SI*4)(%ecx), %esi
+-      movl    (JB_DI*4)(%ecx), %edi
+-      movl    (JB_BP*4)(%ecx), %ebp
+-      movl    $1, %eax
+-      movl    (JB_SP*4)(%ecx), %esp
+-      jmp     *%edx           /* Jump to saved PC. */
+diff -Nurb linux-2.6.22-590/arch/i386/kernel/kgdb.c linux-2.6.22-570/arch/i386/kernel/kgdb.c
+--- linux-2.6.22-590/arch/i386/kernel/kgdb.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/kernel/kgdb.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,388 +0,0 @@
+-/*
+- *
+- * 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, 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.
+- *
+- */
 -
--at 0x0000005a : */    0x88880000,0x00ffff68,
 -/*
--      RETURN
--
--at 0x0000005c : */    0x90080000,0x00000000,
+- * Copyright (C) 2000-2001 VERITAS Software Corporation.
+- * Copyright (C) 2007 Wind River Systems, Inc.
+- */
 -/*
--ENTRY dsa_zero
--dsa_zero:
--ENTRY dsa_code_template_end
--dsa_code_template_end:
--
--; Perform sanity check for dsa_fields_start == dsa_code_template_end - 
--; dsa_zero, puke.
--
--ABSOLUTE dsa_fields_start =  0        ; Sanity marker
--                              ;       pad 48 bytes (fix this RSN)
--ABSOLUTE dsa_next = 48                ; len 4 Next DSA
--                              ; del 4 Previous DSA address
--ABSOLUTE dsa_cmnd = 56                ; len 4 Scsi_Cmnd * for this thread.
--ABSOLUTE dsa_select = 60      ; len 4 Device ID, Period, Offset for 
--                              ;       table indirect select
--ABSOLUTE dsa_msgout = 64      ; len 8 table indirect move parameter for 
--                              ;       select message
--ABSOLUTE dsa_cmdout = 72      ; len 8 table indirect move parameter for 
--                              ;       command
--ABSOLUTE dsa_dataout = 80     ; len 4 code pointer for dataout
--ABSOLUTE dsa_datain = 84      ; len 4 code pointer for datain
--ABSOLUTE dsa_msgin = 88               ; len 8 table indirect move for msgin
--ABSOLUTE dsa_status = 96      ; len 8 table indirect move for status byte
--ABSOLUTE dsa_msgout_other = 104       ; len 8 table indirect for normal message out
--                              ; (Synchronous transfer negotiation, etc).
--ABSOLUTE dsa_end = 112
--
--ABSOLUTE schedule = 0                 ; Array of JUMP dsa_begin or JUMP (next),
--                              ; terminated by a call to JUMP wait_reselect
--
--; Linked lists of DSA structures
--ABSOLUTE reconnect_dsa_head = 0       ; Link list of DSAs which can reconnect
--ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing
--                              ; address of reconnect_dsa_head
--
--; These select the source and destination of a MOVE MEMORY instruction
--ABSOLUTE dmode_memory_to_memory = 0x0
--ABSOLUTE dmode_memory_to_ncr = 0x0
--ABSOLUTE dmode_ncr_to_memory = 0x0
--
--ABSOLUTE addr_scratch = 0x0
--ABSOLUTE addr_temp = 0x0
--
--ABSOLUTE saved_dsa = 0x0
--ABSOLUTE emulfly = 0x0
--ABSOLUTE addr_dsa = 0x0
--
--
--
--; Interrupts - 
--; MSB indicates type
--; 0   handle error condition
--; 1   handle message 
--; 2   handle normal condition
--; 3   debugging interrupt
--; 4   testing interrupt 
--; Next byte indicates specific error
--
--; XXX not yet implemented, I'm not sure if I want to - 
--; Next byte indicates the routine the error occurred in
--; The LSB indicates the specific place the error occurred
-- 
--ABSOLUTE int_err_unexpected_phase = 0x00000000        ; Unexpected phase encountered
--ABSOLUTE int_err_selected = 0x00010000                ; SELECTED (nee RESELECTED)
--ABSOLUTE int_err_unexpected_reselect = 0x00020000 
--ABSOLUTE int_err_check_condition = 0x00030000 
--ABSOLUTE int_err_no_phase = 0x00040000
--ABSOLUTE int_msg_wdtr = 0x01000000            ; WDTR message received
--ABSOLUTE int_msg_sdtr = 0x01010000            ; SDTR received
--ABSOLUTE int_msg_1 = 0x01020000                       ; single byte special message
--                                              ; received
--
--ABSOLUTE int_norm_select_complete = 0x02000000        ; Select complete, reprogram
--                                              ; registers.
--ABSOLUTE int_norm_reselect_complete = 0x02010000      ; Nexus established
--ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete
--ABSOLUTE int_norm_disconnected = 0x02030000   ; Disconnected 
--ABSOLUTE int_norm_aborted =0x02040000         ; Aborted *dsa
--ABSOLUTE int_norm_reset = 0x02050000          ; Generated BUS reset.
--ABSOLUTE int_norm_emulateintfly = 0x02060000  ; 53C710 Emulated intfly
--ABSOLUTE int_debug_break = 0x03000000         ; Break point
--
--ABSOLUTE int_debug_panic = 0x030b0000         ; Panic driver
--
--
--ABSOLUTE int_test_1 = 0x04000000              ; Test 1 complete
--ABSOLUTE int_test_2 = 0x04010000              ; Test 2 complete
--ABSOLUTE int_test_3 = 0x04020000              ; Test 3 complete
--
+- *  Contributor:     Lake Stevens Instrument Division$
+- *  Written by:      Glenn Engel $
+- *  Updated by:            Amit Kale<akale@veritas.com>
+- *  Updated by:            Tom Rini <trini@kernel.crashing.org>
+- *  Updated by:            Jason Wessel <jason.wessel@windriver.com>
+- *  Modified for 386 by Jim Kingdon, Cygnus Support.
+- *  Origianl kgdb, compatibility with 2.1.xx kernel by
+- *  David Grothe <dave@gcom.com>
+- *  Additional support from Tigran Aivazian <tigran@sco.com>
+- */
 -
--; These should start with 0x05000000, with low bits incrementing for 
--; each one.
+-#include <linux/string.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/spinlock.h>
+-#include <linux/delay.h>
+-#include <asm/vm86.h>
+-#include <asm/system.h>
+-#include <asm/ptrace.h>               /* for linux pt_regs struct */
+-#include <linux/kgdb.h>
+-#include <linux/init.h>
+-#include <linux/kdebug.h>
+-#include <asm/apicdef.h>
+-#include <asm/desc.h>
+-#include <asm/kdebug.h>
+-
+-#include "mach_ipi.h"
+-
+-/* Put the error code here just in case the user cares.  */
+-int gdb_i386errcode;
+-/* Likewise, the vector number here (since GDB only gets the signal
+-   number through the usual means, and that's not very specific).  */
+-int gdb_i386vector = -1;
+-
+-extern atomic_t cpu_doing_single_step;
+-
+-void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+-{
+-      gdb_regs[_EAX] = regs->eax;
+-      gdb_regs[_EBX] = regs->ebx;
+-      gdb_regs[_ECX] = regs->ecx;
+-      gdb_regs[_EDX] = regs->edx;
+-      gdb_regs[_ESI] = regs->esi;
+-      gdb_regs[_EDI] = regs->edi;
+-      gdb_regs[_EBP] = regs->ebp;
+-      gdb_regs[_DS] = regs->xds;
+-      gdb_regs[_ES] = regs->xes;
+-      gdb_regs[_PS] = regs->eflags;
+-      gdb_regs[_CS] = regs->xcs;
+-      gdb_regs[_PC] = regs->eip;
+-      gdb_regs[_ESP] = (int)(&regs->esp);
+-      gdb_regs[_SS] = __KERNEL_DS;
+-      gdb_regs[_FS] = 0xFFFF;
+-      gdb_regs[_GS] = 0xFFFF;
+-}
+-
+-/*
+- * Extracts ebp, esp and eip values understandable by gdb from the values
+- * saved by switch_to.
+- * thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp
+- * prior to entering switch_to is 8 greater then the value that is saved.
+- * If switch_to changes, change following code appropriately.
+- */
+-void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+-{
+-      gdb_regs[_EAX] = 0;
+-      gdb_regs[_EBX] = 0;
+-      gdb_regs[_ECX] = 0;
+-      gdb_regs[_EDX] = 0;
+-      gdb_regs[_ESI] = 0;
+-      gdb_regs[_EDI] = 0;
+-      gdb_regs[_EBP] = *(unsigned long *)p->thread.esp;
+-      gdb_regs[_DS] = __KERNEL_DS;
+-      gdb_regs[_ES] = __KERNEL_DS;
+-      gdb_regs[_PS] = 0;
+-      gdb_regs[_CS] = __KERNEL_CS;
+-      gdb_regs[_PC] = p->thread.eip;
+-      gdb_regs[_ESP] = p->thread.esp;
+-      gdb_regs[_SS] = __KERNEL_DS;
+-      gdb_regs[_FS] = 0xFFFF;
+-      gdb_regs[_GS] = 0xFFFF;
+-}
+-
+-void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+-{
+-      regs->eax = gdb_regs[_EAX];
+-      regs->ebx = gdb_regs[_EBX];
+-      regs->ecx = gdb_regs[_ECX];
+-      regs->edx = gdb_regs[_EDX];
+-      regs->esi = gdb_regs[_ESI];
+-      regs->edi = gdb_regs[_EDI];
+-      regs->ebp = gdb_regs[_EBP];
+-      regs->xds = gdb_regs[_DS];
+-      regs->xes = gdb_regs[_ES];
+-      regs->eflags = gdb_regs[_PS];
+-      regs->xcs = gdb_regs[_CS];
+-      regs->eip = gdb_regs[_PC];
+-}
+-
+-static struct hw_breakpoint {
+-      unsigned enabled;
+-      unsigned type;
+-      unsigned len;
+-      unsigned addr;
+-} breakinfo[4] = {
+-      { .enabled = 0 },
+-      { .enabled = 0 },
+-      { .enabled = 0 },
+-      { .enabled = 0 },
+-};
 -
+-static void kgdb_correct_hw_break(void)
+-{
+-      int breakno;
+-      int correctit;
+-      int breakbit;
+-      unsigned long dr7;
+-
+-      get_debugreg(dr7, 7);
+-      correctit = 0;
+-      for (breakno = 0; breakno < 3; breakno++) {
+-              breakbit = 2 << (breakno << 1);
+-              if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
+-                      correctit = 1;
+-                      dr7 |= breakbit;
+-                      dr7 &= ~(0xf0000 << (breakno << 2));
+-                      dr7 |= (((breakinfo[breakno].len << 2) |
+-                               breakinfo[breakno].type) << 16) <<
+-                          (breakno << 2);
+-                      switch (breakno) {
+-                      case 0:
+-                              set_debugreg(breakinfo[breakno].addr, 0);
+-                              break;
 -
--                                              
--ABSOLUTE NCR53c7xx_msg_abort = 0      ; Pointer to abort message
--ABSOLUTE NCR53c7xx_msg_reject = 0       ; Pointer to reject message
--ABSOLUTE NCR53c7xx_zero       = 0             ; long with zero in it, use for source
--ABSOLUTE NCR53c7xx_sink = 0           ; long to dump worthless data in
--ABSOLUTE NOP_insn = 0                 ; NOP instruction
+-                      case 1:
+-                              set_debugreg(breakinfo[breakno].addr, 1);
+-                              break;
 -
--; Pointer to message, potentially multi-byte
--ABSOLUTE msg_buf = 0
+-                      case 2:
+-                              set_debugreg(breakinfo[breakno].addr, 2);
+-                              break;
 -
--; Pointer to holding area for reselection information
--ABSOLUTE reselected_identify = 0
--ABSOLUTE reselected_tag = 0
+-                      case 3:
+-                              set_debugreg(breakinfo[breakno].addr, 3);
+-                              break;
+-                      }
+-              } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
+-                      correctit = 1;
+-                      dr7 &= ~breakbit;
+-                      dr7 &= ~(0xf0000 << (breakno << 2));
+-              }
+-      }
+-      if (correctit)
+-              set_debugreg(dr7, 7);
+-}
 -
--; Request sense command pointer, it's a 6 byte command, should
--; be constant for all commands since we always want 16 bytes of 
--; sense and we don't need to change any fields as we did under 
--; SCSI-I when we actually cared about the LUN field.
--;EXTERNAL NCR53c7xx_sense             ; Request sense command
+-static int kgdb_remove_hw_break(unsigned long addr, int len,
+-                                               enum kgdb_bptype bptype)
+-{
+-      int i, idx = -1;
+-      for (i = 0; i < 4; i++) {
+-              if (breakinfo[i].addr == addr && breakinfo[i].enabled) {
+-                      idx = i;
+-                      break;
+-              }
+-      }
+-      if (idx == -1)
+-              return -1;
 -
+-      breakinfo[idx].enabled = 0;
+-      return 0;
+-}
 -
--; dsa_schedule  
--; PURPOSE : after a DISCONNECT message has been received, and pointers
--;     saved, insert the current DSA structure at the head of the 
--;     disconnected queue and fall through to the scheduler.
--;
--; CALLS : OK
--;
--; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list
--;     of disconnected commands
--;
--; MODIFIES : SCRATCH, reconnect_dsa_head
--; 
--; EXITS : always passes control to schedule
+-static void kgdb_remove_all_hw_break(void)
+-{
+-      int i;
 -
--ENTRY dsa_schedule
--dsa_schedule:
+-      for (i = 0; i < 4; i++) {
+-              memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint));
+-      }
+-}
 -
+-static int kgdb_set_hw_break(unsigned long addr, int len,
+-                                        enum kgdb_bptype bptype)
+-{
+-      int i, idx = -1;
+-      for (i = 0; i < 4; i++) {
+-              if (!breakinfo[i].enabled) {
+-                      idx = i;
+-                      break;
+-              }
+-      }
+-      if (idx == -1)
+-              return -1;
+-      if (bptype == bp_hardware_breakpoint) {
+-              breakinfo[idx].type = 0;
+-              breakinfo[idx].len = 0;
+-      } else if (bptype == bp_write_watchpoint) {
+-              breakinfo[idx].type = 1;
+-              if (len == 1 || len == 2 || len == 4)
+-                      breakinfo[idx].len = len - 1;
+-              else
+-                      return -1;
+-      } else if (bptype == bp_access_watchpoint) {
+-              breakinfo[idx].type = 3;
+-              if (len == 1 || len == 2 || len == 4)
+-                      breakinfo[idx].len = len - 1;
+-              else
+-                      return -1;
+-      } else
+-              return -1;
+-      breakinfo[idx].enabled = 1;
+-      breakinfo[idx].addr = addr;
+-      return 0;
+-}
 -
+-void kgdb_disable_hw_debug(struct pt_regs *regs)
+-{
+-      /* Disable hardware debugging while we are in kgdb */
+-      set_debugreg(0, 7);
+-}
 -
+-void kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code)
+-{
+-      /* Master processor is completely in the debugger */
+-      gdb_i386vector = e_vector;
+-      gdb_i386errcode = err_code;
+-}
 -
--;
--; Calculate the address of the next pointer within the DSA 
--; structure of the command that is currently disconnecting
--;
+-#ifdef CONFIG_SMP
+-void kgdb_roundup_cpus(unsigned long flags)
+-{
+-      send_IPI_allbutself(APIC_DM_NMI);
+-}
+-#endif
 -
--    ; Read what should be the current DSA from memory - actual DSA
--    ; register is probably corrupt
--    MOVE MEMORY 4, saved_dsa, addr_scratch
+-int kgdb_arch_handle_exception(int e_vector, int signo,
+-                             int err_code, char *remcom_in_buffer,
+-                             char *remcom_out_buffer,
+-                             struct pt_regs *linux_regs)
+-{
+-      long addr;
+-      char *ptr;
+-      int newPC, dr6;
+-
+-      switch (remcom_in_buffer[0]) {
+-      case 'c':
+-      case 's':
+-              /* try to read optional parameter, pc unchanged if no parm */
+-              ptr = &remcom_in_buffer[1];
+-              if (kgdb_hex2long(&ptr, &addr))
+-                      linux_regs->eip = addr;
+-              newPC = linux_regs->eip;
+-
+-              /* clear the trace bit */
+-              linux_regs->eflags &= ~TF_MASK;
+-              atomic_set(&cpu_doing_single_step, -1);
+-
+-              /* set the trace bit if we're stepping */
+-              if (remcom_in_buffer[0] == 's') {
+-                      linux_regs->eflags |= TF_MASK;
+-                      debugger_step = 1;
+-                      atomic_set(&cpu_doing_single_step,raw_smp_processor_id());
+-              }
 -
--at 0x0000005e : */    0xc0000004,0x00000000,0x00000000,
--/*
+-              get_debugreg(dr6, 6);
+-              if (!(dr6 & 0x4000)) {
+-                      long breakno;
+-                      for (breakno = 0; breakno < 4; ++breakno) {
+-                              if (dr6 & (1 << breakno) &&
+-                                  breakinfo[breakno].type == 0) {
+-                                      /* Set restore flag */
+-                                      linux_regs->eflags |= X86_EFLAGS_RF;
+-                                      break;
+-                              }
+-                      }
+-              }
+-              set_debugreg(0, 6);
+-              kgdb_correct_hw_break();
 -
+-              return (0);
+-      }                       /* switch */
+-      /* this means that we do not want to exit from the handler */
+-      return -1;
+-}
 -
+-/* Register KGDB with the i386die_chain so that we hook into all of the right
+- * spots. */
+-static int kgdb_notify(struct notifier_block *self, unsigned long cmd,
+-                     void *ptr)
+-{
+-      struct die_args *args = ptr;
+-      struct pt_regs *regs = args->regs;
+-
+-      /* Bad memory access? */
+-      if (cmd == DIE_PAGE_FAULT_NO_CONTEXT && atomic_read(&debugger_active)
+-              && kgdb_may_fault) {
+-              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+-              return NOTIFY_STOP;
+-      } else if (cmd == DIE_PAGE_FAULT)
+-              /* A normal page fault, ignore. */
+-              return NOTIFY_DONE;
+-      else if ((cmd == DIE_NMI || cmd == DIE_NMI_IPI ||
+-                        cmd == DIE_NMIWATCHDOG) && atomic_read(&debugger_active)) {
+-              /* CPU roundup */
+-              kgdb_nmihook(raw_smp_processor_id(), regs);
+-              return NOTIFY_STOP;
+-      } else if (cmd == DIE_DEBUG
+-                         && atomic_read(&cpu_doing_single_step) == raw_smp_processor_id()
+-                         && user_mode(regs)) {
+-              /* single step exception from kernel space to user space so
+-               * eat the exception and continue the process
+-               */
+-              printk(KERN_ERR "KGDB: trap/step from kernel to user space, resuming...\n");
+-              kgdb_arch_handle_exception(args->trapnr, args->signr, args->err, "c","",regs);
+-              return NOTIFY_STOP;
+-      } else if (cmd == DIE_NMI_IPI || cmd == DIE_NMI || user_mode(regs) ||
+-                         (cmd == DIE_DEBUG && atomic_read(&debugger_active)))
+-              /* Normal watchdog event or userspace debugging, or spurious
+-               * debug exception, ignore. */
+-              return NOTIFY_DONE;
 -
--    MOVE SCRATCH0 + dsa_next TO SCRATCH0
+-      kgdb_handle_exception(args->trapnr, args->signr, args->err, regs);
 -
--at 0x00000061 : */    0x7e343000,0x00000000,
--/*
--    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
+-      return NOTIFY_STOP;
+-}
 -
--at 0x00000063 : */    0x7f350000,0x00000000,
--/*
--    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
+-static struct notifier_block kgdb_notifier = {
+-      .notifier_call = kgdb_notify,
+-};
 -
--at 0x00000065 : */    0x7f360000,0x00000000,
--/*
--    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
+-int kgdb_arch_init(void)
+-{
+-      register_die_notifier(&kgdb_notifier);
+-      return 0;
+-}
 -
--at 0x00000067 : */    0x7f370000,0x00000000,
 -/*
+- * Skip an int3 exception when it occurs after a breakpoint has been
+- * removed. Backtrack eip by 1 since the int3 would have caused it to
+- * increment by 1.
+- */
 -
--; Point the next field of this DSA structure at the current disconnected 
--; list
--    
--    MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8
--
--at 0x00000069 : */    0xc0000004,0x00000000,0x000001b8,
--/*
--    
--dsa_schedule_insert:
--    MOVE MEMORY 4, reconnect_dsa_head, 0 
+-int kgdb_skipexception(int exception, struct pt_regs *regs)
+-{
+-      if (exception == 3 && kgdb_isremovedbreak(regs->eip - 1)) {
+-              regs->eip -= 1;
+-              return 1;
+-      }
+-      return 0;
+-}
 -
--at 0x0000006c : */    0xc0000004,0x00000000,0x00000000,
--/*
+-unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
+-{
+-      if (exception == 3) {
+-              return instruction_pointer(regs) - 1;
+-      }
+-      return instruction_pointer(regs);
+-}
 -
--; And update the head pointer.
+-struct kgdb_arch arch_kgdb_ops = {
+-      .gdb_bpt_instr = {0xcc},
+-      .flags = KGDB_HW_BREAKPOINT,
+-      .set_hw_breakpoint = kgdb_set_hw_break,
+-      .remove_hw_breakpoint = kgdb_remove_hw_break,
+-      .remove_all_hw_break = kgdb_remove_all_hw_break,
+-      .correct_hw_break = kgdb_correct_hw_break,
+-};
+diff -Nurb linux-2.6.22-590/arch/i386/kernel/process.c linux-2.6.22-570/arch/i386/kernel/process.c
+--- linux-2.6.22-590/arch/i386/kernel/process.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/kernel/process.c        2008-01-23 19:16:03.000000000 -0500
+@@ -179,13 +179,13 @@
+       /* endless idle loop with no priority at all */
+       while (1) {
++              tick_nohz_stop_sched_tick();
+               while (!need_resched()) {
+                       void (*idle)(void);
+                       if (__get_cpu_var(cpu_idle_state))
+                               __get_cpu_var(cpu_idle_state) = 0;
+-                      tick_nohz_stop_sched_tick();
+                       check_pgt_cache();
+                       rmb();
+                       idle = pm_idle;
+diff -Nurb linux-2.6.22-590/arch/i386/kernel/setup.c linux-2.6.22-570/arch/i386/kernel/setup.c
+--- linux-2.6.22-590/arch/i386/kernel/setup.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/kernel/setup.c  2007-07-08 19:32:17.000000000 -0400
+@@ -124,7 +124,6 @@
+ #endif
+ extern void early_cpu_init(void);
+-extern void early_trap_init(void);
+ extern int root_mountflags;
+ unsigned long saved_videomode;
+@@ -515,7 +514,6 @@
+       memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
+       pre_setup_arch_hook();
+       early_cpu_init();
+-      early_trap_init();
+       /*
+        * FIXME: This isn't an official loader_type right
+diff -Nurb linux-2.6.22-590/arch/i386/kernel/signal.c linux-2.6.22-570/arch/i386/kernel/signal.c
+--- linux-2.6.22-590/arch/i386/kernel/signal.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/kernel/signal.c 2007-07-08 19:32:17.000000000 -0400
+@@ -199,13 +199,6 @@
+       return eax;
+ badframe:
+-      if (show_unhandled_signals && printk_ratelimit())
+-              printk("%s%s[%d] bad frame in sigreturn frame:%p eip:%lx"
+-                     " esp:%lx oeax:%lx\n",
+-                  current->pid > 1 ? KERN_INFO : KERN_EMERG,
+-                  current->comm, current->pid, frame, regs->eip,
+-                  regs->esp, regs->orig_eax);
 -
--    ; Read what should be the current DSA from memory - actual DSA
--    ; register is probably corrupt
--    MOVE MEMORY 4, saved_dsa, addr_scratch
+       force_sig(SIGSEGV, current);
+       return 0;
+ }     
+diff -Nurb linux-2.6.22-590/arch/i386/kernel/syscall_table.S linux-2.6.22-570/arch/i386/kernel/syscall_table.S
+--- linux-2.6.22-590/arch/i386/kernel/syscall_table.S  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/kernel/syscall_table.S  2008-01-23 19:16:03.000000000 -0500
+@@ -323,6 +323,3 @@
+       .long sys_signalfd
+       .long sys_timerfd
+       .long sys_eventfd
+-      .long sys_revokeat
+-      .long sys_frevoke               /* 325 */
+-      .long sys_fallocate
+diff -Nurb linux-2.6.22-590/arch/i386/kernel/traps.c linux-2.6.22-570/arch/i386/kernel/traps.c
+--- linux-2.6.22-590/arch/i386/kernel/traps.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/kernel/traps.c  2008-01-23 19:16:03.000000000 -0500
+@@ -97,11 +97,6 @@
+ int kstack_depth_to_print = 24;
+ static unsigned int code_bytes = 64;
+-#ifdef CONFIG_STACK_UNWIND
+-static int call_trace = 1;
+-#else
+-#define call_trace (-1)
+-#endif
+ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+ {
+@@ -141,34 +136,6 @@
+       return ebp;
+ }
+-struct ops_and_data {
+-      struct stacktrace_ops *ops;
+-      void *data;
+-};
 -
--at 0x0000006f : */    0xc0000004,0x00000000,0x00000000,
--/*
+-static asmlinkage int
+-dump_trace_unwind(struct unwind_frame_info *info, void *data)
+-{
+-      struct ops_and_data *oad = (struct ops_and_data *)data;
+-      int n = 0;
+-      unsigned long sp = UNW_SP(info);
 -
+-      if (arch_unw_user_mode(info))
+-              return -1;
+-      while (unwind(info) == 0 && UNW_PC(info)) {
+-              n++;
+-              oad->ops->address(oad->data, UNW_PC(info));
+-              if (arch_unw_user_mode(info))
+-                      break;
+-              if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
+-                  && sp > UNW_SP(info))
+-                      break;
+-              sp = UNW_SP(info);
+-              touch_nmi_watchdog();
+-      }
+-      return n;
+-}
 -
+ #define MSG(msg) ops->warning(data, msg)
+ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+@@ -180,41 +147,6 @@
+       if (!task)
+               task = current;
+-      if (call_trace >= 0) {
+-              int unw_ret = 0;
+-              struct unwind_frame_info info;
+-              struct ops_and_data oad = { .ops = ops, .data = data };
+-
+-              if (regs) {
+-                      if (unwind_init_frame_info(&info, task, regs) == 0)
+-                              unw_ret = dump_trace_unwind(&info, &oad);
+-              } else if (task == current)
+-                      unw_ret = unwind_init_running(&info, dump_trace_unwind,
+-                                                    &oad);
+-              else {
+-                      if (unwind_init_blocked(&info, task) == 0)
+-                              unw_ret = dump_trace_unwind(&info, &oad);
+-              }
+-              if (unw_ret > 0) {
+-                      if (call_trace == 1 && !arch_unw_user_mode(&info)) {
+-                              ops->warning_symbol(data,
+-                                           "DWARF2 unwinder stuck at %s",
+-                                           UNW_PC(&info));
+-                              if (UNW_SP(&info) >= PAGE_OFFSET) {
+-                                      MSG("Leftover inexact backtrace:");
+-                                      stack = (void *)UNW_SP(&info);
+-                                      if (!stack)
+-                                              return;
+-                                      ebp = UNW_FP(&info);
+-                              } else
+-                                      MSG("Full inexact backtrace again:");
+-                      } else if (call_trace >= 1)
+-                              return;
+-                      else
+-                              MSG("Full inexact backtrace again:");
+-              } else
+-                      MSG("Inexact backtrace:");
+-      }
+       if (!stack) {
+               unsigned long dummy;
+               stack = &dummy;
+@@ -682,13 +614,6 @@
+       current->thread.error_code = error_code;
+       current->thread.trap_no = 13;
+-      if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) &&
+-          printk_ratelimit())
+-              printk(KERN_INFO
+-                  "%s[%d] general protection eip:%lx esp:%lx error:%lx\n",
+-                  current->comm, current->pid,
+-                  regs->eip, regs->esp, error_code);
 -
--    
--    MOVE MEMORY 4, addr_scratch, reconnect_dsa_head
+       force_sig(SIGSEGV, current);
+       return;
+@@ -929,7 +854,6 @@
+        */
+ clear_dr7:
+       set_debugreg(0, 7);
+-      notify_die(DIE_DEBUG, "debug2", regs, condition, error_code, SIGTRAP);
+       return;
+ debug_vm86:
+@@ -1194,12 +1118,6 @@
+       _set_gate(n, DESCTYPE_TASK, (void *)0, (gdt_entry<<3));
+ }
+-/* Some traps need to be set early. */
+-void __init early_trap_init(void) {
+-      set_intr_gate(1,&debug);
+-      set_system_intr_gate(3, &int3); /* int3 can be called from all */
+-      set_intr_gate(14,&page_fault);
+-}
+ void __init trap_init(void)
+ {
+@@ -1216,8 +1134,10 @@
+ #endif
+       set_trap_gate(0,&divide_error);
++      set_intr_gate(1,&debug);
+       set_intr_gate(2,&nmi);
+-      set_system_gate(4,&overflow); /* int4/5 can be called from all */
++      set_system_intr_gate(3, &int3); /* int3/4 can be called from all */
++      set_system_gate(4,&overflow);
+       set_trap_gate(5,&bounds);
+       set_trap_gate(6,&invalid_op);
+       set_trap_gate(7,&device_not_available);
+@@ -1227,6 +1147,7 @@
+       set_trap_gate(11,&segment_not_present);
+       set_trap_gate(12,&stack_segment);
+       set_trap_gate(13,&general_protection);
++      set_intr_gate(14,&page_fault);
+       set_trap_gate(15,&spurious_interrupt_bug);
+       set_trap_gate(16,&coprocessor_error);
+       set_trap_gate(17,&alignment_check);
+@@ -1283,19 +1204,3 @@
+       return 1;
+ }
+ __setup("code_bytes=", code_bytes_setup);
 -
--at 0x00000072 : */    0xc0000004,0x00000000,0x00000000,
--/*
--    
+-#ifdef CONFIG_STACK_UNWIND
+-static int __init call_trace_setup(char *s)
+-{
+-      if (strcmp(s, "old") == 0)
+-              call_trace = -1;
+-      else if (strcmp(s, "both") == 0)
+-              call_trace = 0;
+-      else if (strcmp(s, "newfallback") == 0)
+-              call_trace = 1;
+-      else if (strcmp(s, "new") == 2)
+-              call_trace = 2;
+-      return 1;
+-}
+-__setup("call_trace=", call_trace_setup);
+-#endif
+diff -Nurb linux-2.6.22-590/arch/i386/kernel/unwind.S linux-2.6.22-570/arch/i386/kernel/unwind.S
+--- linux-2.6.22-590/arch/i386/kernel/unwind.S 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/kernel/unwind.S 1969-12-31 19:00:00.000000000 -0500
+@@ -1,36 +0,0 @@
+-/* Assembler support code for dwarf2 unwinder */
+-#include <linux/linkage.h>
+-#include <asm/dwarf2.h>
+-#include <asm/ptrace-abi.h>
+-#include <asm/segment.h>
+-#include <asm/asm-offsets.h>
+-
+-ENTRY(arch_unwind_init_running)
+-      CFI_STARTPROC
+-      movl    4(%esp), %edx
+-      movl    (%esp), %ecx
+-      leal    4(%esp), %eax
+-      movl    %ebx, PT_EBX(%edx)
+-      xorl    %ebx, %ebx
+-      movl    %ebx, PT_ECX(%edx)
+-      movl    %ebx, PT_EDX(%edx)
+-      movl    %esi, PT_ESI(%edx)
+-      movl    %edi, PT_EDI(%edx)
+-      movl    %ebp, PT_EBP(%edx)
+-      movl    %ebx, PT_EAX(%edx)
+-      movl    $__USER_DS, PT_DS(%edx)
+-      movl    $__USER_DS, PT_ES(%edx)
+-      movl    $0, PT_FS(%edx)
+-      movl    %ebx, PT_ORIG_EAX(%edx)
+-      movl    %ecx, PT_EIP(%edx)
+-      movl    12(%esp), %ecx
+-      movl    $__KERNEL_CS, PT_CS(%edx)
+-      movl    %ebx, PT_EFLAGS(%edx)
+-      movl    %eax, PT_OLDESP(%edx)
+-      movl    8(%esp), %eax
+-      movl    %ecx, 8(%esp)
+-      movl    PT_EBX(%edx), %ebx
+-      movl    $__KERNEL_DS, PT_OLDSS(%edx)
+-      jmpl    *%eax
+-      CFI_ENDPROC
+-ENDPROC(arch_unwind_init_running)
+diff -Nurb linux-2.6.22-590/arch/i386/mach-voyager/voyager_thread.c linux-2.6.22-570/arch/i386/mach-voyager/voyager_thread.c
+--- linux-2.6.22-590/arch/i386/mach-voyager/voyager_thread.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/mach-voyager/voyager_thread.c   2007-07-08 19:32:17.000000000 -0400
+@@ -52,7 +52,7 @@
+               NULL,
+       };
+-      if ((ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC)) != 0) {
++      if ((ret = call_usermodehelper(argv[0], argv, envp, 1)) != 0) {
+               printk(KERN_ERR "Voyager failed to run \"%s\": %i\n",
+                      string, ret);
+       }
+diff -Nurb linux-2.6.22-590/arch/i386/mm/fault.c linux-2.6.22-570/arch/i386/mm/fault.c
+--- linux-2.6.22-590/arch/i386/mm/fault.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/i386/mm/fault.c      2008-01-23 19:16:03.000000000 -0500
+@@ -284,8 +284,6 @@
+       return 0;
+ }
+-int show_unhandled_signals = 1;
 -
+ /*
+  * This routine handles page faults.  It determines the address,
+  * and the problem, and then passes it off to one of the appropriate
+@@ -473,14 +471,6 @@
+               if (is_prefetch(regs, address, error_code))
+                       return;
+-              if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+-                  printk_ratelimit()) {
+-                      printk("%s%s[%d]: segfault at %08lx eip %08lx "
+-                          "esp %08lx error %lx\n",
+-                          tsk->pid > 1 ? KERN_INFO : KERN_EMERG,
+-                          tsk->comm, tsk->pid, address, regs->eip,
+-                          regs->esp, error_code);
+-              }
+               tsk->thread.cr2 = address;
+               /* Kernel addresses are always protection faults */
+               tsk->thread.error_code = error_code | (address >= TASK_SIZE);
+@@ -518,10 +508,6 @@
+       if (is_prefetch(regs, address, error_code))
+               return;
+-      if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs,
+-                              error_code, 14, SIGSEGV) == NOTIFY_STOP)
+-              return;
 -
+ /*
+  * Oops. The kernel tried to access some bad page. We'll have to
+  * terminate things with extreme prejudice.
+diff -Nurb linux-2.6.22-590/arch/ia64/hp/sim/simeth.c linux-2.6.22-570/arch/ia64/hp/sim/simeth.c
+--- linux-2.6.22-590/arch/ia64/hp/sim/simeth.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ia64/hp/sim/simeth.c 2007-07-08 19:32:17.000000000 -0400
+@@ -300,9 +300,6 @@
+               return NOTIFY_DONE;
+       }
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
+       if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE;
+       /*
+diff -Nurb linux-2.6.22-590/arch/ia64/kernel/Makefile linux-2.6.22-570/arch/ia64/kernel/Makefile
+--- linux-2.6.22-590/arch/ia64/kernel/Makefile 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ia64/kernel/Makefile 2007-07-08 19:32:17.000000000 -0400
+@@ -35,7 +35,6 @@
+ obj-$(CONFIG_PCI_MSI)         += msi_ia64.o
+ mca_recovery-y                        += mca_drv.o mca_drv_asm.o
+ obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o
+-obj-$(CONFIG_KGDB)            += kgdb.o kgdb-jmp.o
+ obj-$(CONFIG_IA64_ESI)                += esi.o
+ ifneq ($(CONFIG_IA64_ESI),)
+diff -Nurb linux-2.6.22-590/arch/ia64/kernel/kgdb-jmp.S linux-2.6.22-570/arch/ia64/kernel/kgdb-jmp.S
+--- linux-2.6.22-590/arch/ia64/kernel/kgdb-jmp.S       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ia64/kernel/kgdb-jmp.S       1969-12-31 19:00:00.000000000 -0500
+@@ -1,238 +0,0 @@
+-/* setjmp() and longjmp() assembler support for kdb on ia64.
+-
+-   This code was copied from glibc CVS as of 2001-06-27 and modified where
+-   necessary to fit the kernel.
+-   Keith Owens <kaos@melbourne.sgi.com> 2001-06-27
+- */
 -
+-/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+-   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
 -
--    CLEAR ACK
+-   The GNU C Library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Library General Public License as
+-   published by the Free Software Foundation; either version 2 of the
+-   License, or (at your option) any later version.
 -
--at 0x00000075 : */    0x60000040,0x00000000,
--/*
+-   The GNU C Library 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
+-   Library General Public License for more details.
 -
+-   You should have received a copy of the GNU Library General Public
+-   License along with the GNU C Library; see the file COPYING.LIB.  If
+-   not, write to the Free Software Foundation, Inc.,
+-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-*/
 -
--    ; Time to correct DSA following memory move
--    MOVE MEMORY 4, saved_dsa, addr_dsa
+-#include <asm/asmmacro.h>
+-GLOBAL_ENTRY(kgdb_fault_setjmp)
+-      .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
+-      alloc loc1=ar.pfs,2,2,2,0
+-      mov r16=ar.unat
+-      ;;
+-      mov r17=ar.fpsr
+-      mov r2=in0
+-      add r3=8,in0
+-      ;;
+-.mem.offset 0,0;
+-      st8.spill.nta [r2]=sp,16        // r12 (sp)
+-.mem.offset 8,0;
+-      st8.spill.nta [r3]=gp,16        // r1 (gp)
+-      ;;
+-      st8.nta [r2]=r16,16             // save caller's unat
+-      st8.nta [r3]=r17,16             // save fpsr
+-      add r8=0xa0,in0
+-      ;;
+-.mem.offset 160,0;
+-      st8.spill.nta [r2]=r4,16        // r4
+-.mem.offset 168,0;
+-      st8.spill.nta [r3]=r5,16        // r5
+-      add r9=0xb0,in0
+-      ;;
+-      stf.spill.nta [r8]=f2,32
+-      stf.spill.nta [r9]=f3,32
+-      mov loc0=rp
+-      .body
+-      ;;
+-      stf.spill.nta [r8]=f4,32
+-      stf.spill.nta [r9]=f5,32
+-      mov r17=b1
+-      ;;
+-      stf.spill.nta [r8]=f16,32
+-      stf.spill.nta [r9]=f17,32
+-      mov r18=b2
+-      ;;
+-      stf.spill.nta [r8]=f18,32
+-      stf.spill.nta [r9]=f19,32
+-      mov r19=b3
+-      ;;
+-      stf.spill.nta [r8]=f20,32
+-      stf.spill.nta [r9]=f21,32
+-      mov r20=b4
+-      ;;
+-      stf.spill.nta [r8]=f22,32
+-      stf.spill.nta [r9]=f23,32
+-      mov r21=b5
+-      ;;
+-      stf.spill.nta [r8]=f24,32
+-      stf.spill.nta [r9]=f25,32
+-      mov r22=ar.lc
+-      ;;
+-      stf.spill.nta [r8]=f26,32
+-      stf.spill.nta [r9]=f27,32
+-      mov r24=pr
+-      ;;
+-      stf.spill.nta [r8]=f28,32
+-      stf.spill.nta [r9]=f29,32
+-      ;;
+-      stf.spill.nta [r8]=f30
+-      stf.spill.nta [r9]=f31
+-
+-.mem.offset 0,0;
+-      st8.spill.nta [r2]=r6,16        // r6
+-.mem.offset 8,0;
+-      st8.spill.nta [r3]=r7,16        // r7
+-      ;;
+-      mov r23=ar.bsp
+-      mov r25=ar.unat
+-      st8.nta [r2]=loc0,16            // b0
+-      st8.nta [r3]=r17,16             // b1
+-      ;;
+-      st8.nta [r2]=r18,16             // b2
+-      st8.nta [r3]=r19,16             // b3
+-      ;;
+-      st8.nta [r2]=r20,16             // b4
+-      st8.nta [r3]=r21,16             // b5
+-      ;;
+-      st8.nta [r2]=loc1,16            // ar.pfs
+-      st8.nta [r3]=r22,16             // ar.lc
+-      ;;
+-      st8.nta [r2]=r24,16             // pr
+-      st8.nta [r3]=r23,16             // ar.bsp
+-      ;;
+-      st8.nta [r2]=r25                // ar.unat
+-      st8.nta [r3]=in0                // &__jmp_buf
+-      mov r8=0
+-      mov rp=loc0
+-      mov ar.pfs=loc1
+-      br.ret.sptk.few rp
+-END(kdba_setjmp)
+-#define       pPos    p6      /* is rotate count positive? */
+-#define       pNeg    p7      /* is rotate count negative? */
+-GLOBAL_ENTRY(kgdb_fault_longjmp)
+-      alloc r8=ar.pfs,2,1,0,0
+-      mov r27=ar.rsc
+-      add r2=0x98,in0         // r2 <- &jmpbuf.orig_jmp_buf_addr
+-      ;;
+-      ld8 r8=[r2],-16         // r8 <- orig_jmp_buf_addr
+-      mov r10=ar.bsp
+-      and r11=~0x3,r27        // clear ar.rsc.mode
+-      ;;
+-      flushrs                 // flush dirty regs to backing store (must be first in insn grp)
+-      ld8 r23=[r2],8          // r23 <- jmpbuf.ar_bsp
+-      sub r8=r8,in0           // r8 <- &orig_jmpbuf - &jmpbuf
+-      ;;
+-      ld8 r25=[r2]            // r25 <- jmpbuf.ar_unat
+-      extr.u r8=r8,3,6        // r8 <- (&orig_jmpbuf - &jmpbuf)/8 & 0x3f
+-      ;;
+-      cmp.lt pNeg,pPos=r8,r0
+-      mov r2=in0
+-      ;;
+-(pPos)        mov r16=r8
+-(pNeg)        add r16=64,r8
+-(pPos)        sub r17=64,r8
+-(pNeg)        sub r17=r0,r8
+-      ;;
+-      mov ar.rsc=r11          // put RSE in enforced lazy mode
+-      shr.u r8=r25,r16
+-      add r3=8,in0            // r3 <- &jmpbuf.r1
+-      shl r9=r25,r17
+-      ;;
+-      or r25=r8,r9
+-      ;;
+-      mov r26=ar.rnat
+-      mov ar.unat=r25         // setup ar.unat (NaT bits for r1, r4-r7, and r12)
+-      ;;
+-      ld8.fill.nta sp=[r2],16 // r12 (sp)
+-      ld8.fill.nta gp=[r3],16         // r1 (gp)
+-      dep r11=-1,r23,3,6      // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+-      ;;
+-      ld8.nta r16=[r2],16             // caller's unat
+-      ld8.nta r17=[r3],16             // fpsr
+-      ;;
+-      ld8.fill.nta r4=[r2],16 // r4
+-      ld8.fill.nta r5=[r3],16         // r5 (gp)
+-      cmp.geu p8,p0=r10,r11   // p8 <- (ar.bsp >= jmpbuf.ar_bsp)
+-      ;;
+-      ld8.fill.nta r6=[r2],16 // r6
+-      ld8.fill.nta r7=[r3],16         // r7
+-      ;;
+-      mov ar.unat=r16                 // restore caller's unat
+-      mov ar.fpsr=r17                 // restore fpsr
+-      ;;
+-      ld8.nta r16=[r2],16             // b0
+-      ld8.nta r17=[r3],16             // b1
+-      ;;
+-(p8)  ld8 r26=[r11]           // r26 <- *ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+-      mov ar.bspstore=r23     // restore ar.bspstore
+-      ;;
+-      ld8.nta r18=[r2],16             // b2
+-      ld8.nta r19=[r3],16             // b3
+-      ;;
+-      ld8.nta r20=[r2],16             // b4
+-      ld8.nta r21=[r3],16             // b5
+-      ;;
+-      ld8.nta r11=[r2],16             // ar.pfs
+-      ld8.nta r22=[r3],56             // ar.lc
+-      ;;
+-      ld8.nta r24=[r2],32             // pr
+-      mov b0=r16
+-      ;;
+-      ldf.fill.nta f2=[r2],32
+-      ldf.fill.nta f3=[r3],32
+-      mov b1=r17
+-      ;;
+-      ldf.fill.nta f4=[r2],32
+-      ldf.fill.nta f5=[r3],32
+-      mov b2=r18
+-      ;;
+-      ldf.fill.nta f16=[r2],32
+-      ldf.fill.nta f17=[r3],32
+-      mov b3=r19
+-      ;;
+-      ldf.fill.nta f18=[r2],32
+-      ldf.fill.nta f19=[r3],32
+-      mov b4=r20
+-      ;;
+-      ldf.fill.nta f20=[r2],32
+-      ldf.fill.nta f21=[r3],32
+-      mov b5=r21
+-      ;;
+-      ldf.fill.nta f22=[r2],32
+-      ldf.fill.nta f23=[r3],32
+-      mov ar.lc=r22
+-      ;;
+-      ldf.fill.nta f24=[r2],32
+-      ldf.fill.nta f25=[r3],32
+-      cmp.eq p8,p9=0,in1
+-      ;;
+-      ldf.fill.nta f26=[r2],32
+-      ldf.fill.nta f27=[r3],32
+-      mov ar.pfs=r11
+-      ;;
+-      ldf.fill.nta f28=[r2],32
+-      ldf.fill.nta f29=[r3],32
+-      ;;
+-      ldf.fill.nta f30=[r2]
+-      ldf.fill.nta f31=[r3]
+-(p8)  mov r8=1
+-
+-      mov ar.rnat=r26         // restore ar.rnat
+-      ;;
+-      mov ar.rsc=r27          // restore ar.rsc
+-(p9)  mov r8=in1
+-
+-      invala                  // virt. -> phys. regnum mapping may change
+-      mov pr=r24,-1
+-      br.ret.sptk.few rp
+-END(kgdb_fault_longjmp)
+diff -Nurb linux-2.6.22-590/arch/ia64/kernel/kgdb.c linux-2.6.22-570/arch/ia64/kernel/kgdb.c
+--- linux-2.6.22-590/arch/ia64/kernel/kgdb.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ia64/kernel/kgdb.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,944 +0,0 @@
+-/*
+- *
+- * 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, 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.
+- *
+- */
 -
--at 0x00000077 : */    0xc0000004,0x00000000,0x00000000,
 -/*
--
--    WAIT DISCONNECT
--
--at 0x0000007a : */    0x48000000,0x00000000,
+- * Copyright (C) 2000-2001 VERITAS Software Corporation.
+- * (c) Copyright 2005 Hewlett-Packard Development Company, L.P.
+- *     Bob Picco <bob.picco@hp.com>
+- */
 -/*
+- *  Contributor:     Lake Stevens Instrument Division$
+- *  Written by:      Glenn Engel $
+- *  Updated by:            Amit Kale<akale@veritas.com>
+- *  Modified for 386 by Jim Kingdon, Cygnus Support.
+- *  Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe <dave@gcom.com>
+- */
 -
+-#include <linux/string.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/spinlock.h>
+-#include <linux/delay.h>
+-#include <asm/system.h>
+-#include <asm/ptrace.h>               /* for linux pt_regs struct */
+-#include <asm/unwind.h>
+-#include <asm/rse.h>
+-#include <linux/kgdb.h>
+-#include <linux/init.h>
+-#include <asm/cacheflush.h>
+-#include <asm/kdebug.h>
+-
+-#define NUM_REGS 590
+-#define REGISTER_BYTES (NUM_REGS*8+128*8)
+-#define REGISTER_BYTE(N) (((N) * 8)                                    \
+-      + ((N) <= IA64_FR0_REGNUM ?                                     \
+-      0 : 8 * (((N) > IA64_FR127_REGNUM) ? 128 : (N) - IA64_FR0_REGNUM)))
+-#define REGISTER_SIZE(N)                                               \
+-      (((N) >= IA64_FR0_REGNUM && (N) <= IA64_FR127_REGNUM) ? 16 : 8)
+-#define IA64_GR0_REGNUM         0
+-#define IA64_FR0_REGNUM         128
+-#define IA64_FR127_REGNUM       (IA64_FR0_REGNUM+127)
+-#define IA64_PR0_REGNUM         256
+-#define IA64_BR0_REGNUM         320
+-#define IA64_VFP_REGNUM         328
+-#define IA64_PR_REGNUM          330
+-#define IA64_IP_REGNUM          331
+-#define IA64_PSR_REGNUM         332
+-#define IA64_CFM_REGNUM         333
+-#define IA64_AR0_REGNUM         334
+-#define IA64_NAT0_REGNUM        462
+-#define IA64_NAT31_REGNUM       (IA64_NAT0_REGNUM+31)
+-#define IA64_NAT32_REGNUM       (IA64_NAT0_REGNUM+32)
+-#define IA64_RSC_REGNUM               (IA64_AR0_REGNUM+16)
+-#define IA64_BSP_REGNUM               (IA64_AR0_REGNUM+17)
+-#define IA64_BSPSTORE_REGNUM  (IA64_AR0_REGNUM+18)
+-#define IA64_RNAT_REGNUM      (IA64_AR0_REGNUM+19)
+-#define IA64_FCR_REGNUM               (IA64_AR0_REGNUM+21)
+-#define IA64_EFLAG_REGNUM     (IA64_AR0_REGNUM+24)
+-#define IA64_CSD_REGNUM               (IA64_AR0_REGNUM+25)
+-#define IA64_SSD_REGNUM               (IA64_AR0_REGNUM+26)
+-#define IA64_CFLG_REGNUM      (IA64_AR0_REGNUM+27)
+-#define IA64_FSR_REGNUM               (IA64_AR0_REGNUM+28)
+-#define IA64_FIR_REGNUM               (IA64_AR0_REGNUM+29)
+-#define IA64_FDR_REGNUM               (IA64_AR0_REGNUM+30)
+-#define IA64_CCV_REGNUM               (IA64_AR0_REGNUM+32)
+-#define IA64_UNAT_REGNUM      (IA64_AR0_REGNUM+36)
+-#define IA64_FPSR_REGNUM      (IA64_AR0_REGNUM+40)
+-#define IA64_ITC_REGNUM               (IA64_AR0_REGNUM+44)
+-#define IA64_PFS_REGNUM               (IA64_AR0_REGNUM+64)
+-#define IA64_LC_REGNUM                (IA64_AR0_REGNUM+65)
+-#define IA64_EC_REGNUM                (IA64_AR0_REGNUM+66)
+-
+-#define       REGISTER_INDEX(N)       (REGISTER_BYTE(N) / sizeof (unsigned long))
+-#define BREAK_INSTR_ALIGN     (~0xfULL)
+-
+-#define       ptoff(V)        ((unsigned int) &((struct pt_regs *)0x0)->V)
+-struct reg_to_ptreg_index {
+-      unsigned int reg;
+-      unsigned int ptregoff;
+-};
 -
+-static struct reg_to_ptreg_index gr_reg_to_ptreg_index[] = {
+-      {IA64_GR0_REGNUM + 1, ptoff(r1)},
+-      {IA64_GR0_REGNUM + 2, ptoff(r2)},
+-      {IA64_GR0_REGNUM + 3, ptoff(r3)},
+-      {IA64_GR0_REGNUM + 8, ptoff(r8)},
+-      {IA64_GR0_REGNUM + 9, ptoff(r9)},
+-      {IA64_GR0_REGNUM + 10, ptoff(r10)},
+-      {IA64_GR0_REGNUM + 11, ptoff(r11)},
+-      {IA64_GR0_REGNUM + 12, ptoff(r12)},
+-      {IA64_GR0_REGNUM + 13, ptoff(r13)},
+-      {IA64_GR0_REGNUM + 14, ptoff(r14)},
+-      {IA64_GR0_REGNUM + 15, ptoff(r15)},
+-      {IA64_GR0_REGNUM + 16, ptoff(r16)},
+-      {IA64_GR0_REGNUM + 17, ptoff(r17)},
+-      {IA64_GR0_REGNUM + 18, ptoff(r18)},
+-      {IA64_GR0_REGNUM + 19, ptoff(r19)},
+-      {IA64_GR0_REGNUM + 20, ptoff(r20)},
+-      {IA64_GR0_REGNUM + 21, ptoff(r21)},
+-      {IA64_GR0_REGNUM + 22, ptoff(r22)},
+-      {IA64_GR0_REGNUM + 23, ptoff(r23)},
+-      {IA64_GR0_REGNUM + 24, ptoff(r24)},
+-      {IA64_GR0_REGNUM + 25, ptoff(r25)},
+-      {IA64_GR0_REGNUM + 26, ptoff(r26)},
+-      {IA64_GR0_REGNUM + 27, ptoff(r27)},
+-      {IA64_GR0_REGNUM + 28, ptoff(r28)},
+-      {IA64_GR0_REGNUM + 29, ptoff(r29)},
+-      {IA64_GR0_REGNUM + 30, ptoff(r30)},
+-      {IA64_GR0_REGNUM + 31, ptoff(r31)},
+-};
 -
+-static struct reg_to_ptreg_index br_reg_to_ptreg_index[] = {
+-      {IA64_BR0_REGNUM, ptoff(b0)},
+-      {IA64_BR0_REGNUM + 6, ptoff(b6)},
+-      {IA64_BR0_REGNUM + 7, ptoff(b7)},
+-};
 -
+-static struct reg_to_ptreg_index ar_reg_to_ptreg_index[] = {
+-      {IA64_PFS_REGNUM, ptoff(ar_pfs)},
+-      {IA64_UNAT_REGNUM, ptoff(ar_unat)},
+-      {IA64_RNAT_REGNUM, ptoff(ar_rnat)},
+-      {IA64_BSPSTORE_REGNUM, ptoff(ar_bspstore)},
+-      {IA64_RSC_REGNUM, ptoff(ar_rsc)},
+-      {IA64_CSD_REGNUM, ptoff(ar_csd)},
+-      {IA64_SSD_REGNUM, ptoff(ar_ssd)},
+-      {IA64_FPSR_REGNUM, ptoff(ar_fpsr)},
+-      {IA64_CCV_REGNUM, ptoff(ar_ccv)},
+-};
 -
+-extern atomic_t cpu_doing_single_step;
 -
--    JUMP schedule
--
--at 0x0000007c : */    0x80080000,0x00000000,
--/*
+-static int kgdb_gr_reg(int regnum, struct unw_frame_info *info,
+-      unsigned long *reg, int rw)
+-{
+-      char nat;
 -
+-      if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) ||
+-              (regnum >= (IA64_GR0_REGNUM + 4) &&
+-              regnum <= (IA64_GR0_REGNUM + 7)))
+-              return !unw_access_gr(info, regnum - IA64_GR0_REGNUM,
+-              reg, &nat, rw);
+-      else
+-              return 0;
+-}
+-static int kgdb_gr_ptreg(int regnum, struct pt_regs * ptregs,
+-      struct unw_frame_info *info, unsigned long *reg, int rw)
+-{
+-      int i, result = 1;
+-      char nat;
 -
--;
--; select
--;
--; PURPOSE : establish a nexus for the SCSI command referenced by DSA.
--;     On success, the current DSA structure is removed from the issue 
--;     queue.  Usually, this is entered as a fall-through from schedule,
--;     although the contingent allegiance handling code will write
--;     the select entry address to the DSP to restart a command as a 
--;     REQUEST SENSE.  A message is sent (usually IDENTIFY, although
--;     additional SDTR or WDTR messages may be sent).  COMMAND OUT
--;     is handled.
--;
--; INPUTS : DSA - SCSI command, issue_dsa_head
--;
--; CALLS : NOT OK
--;
--; MODIFIES : SCRATCH, issue_dsa_head
--;
--; EXITS : on reselection or selection, go to select_failed
--;     otherwise, RETURN so control is passed back to 
--;     dsa_begin.
--;
+-      if (!((regnum >= (IA64_GR0_REGNUM + 2) &&
+-              regnum <= (IA64_GR0_REGNUM + 3)) ||
+-              (regnum >= (IA64_GR0_REGNUM + 8) &&
+-              regnum <= (IA64_GR0_REGNUM + 15)) ||
+-              (regnum >= (IA64_GR0_REGNUM + 16) &&
+-              regnum <= (IA64_GR0_REGNUM + 31))))
+-              return 0;
+-      else if (rw && ptregs) {
+-              for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++)
+-                      if (gr_reg_to_ptreg_index[i].reg == regnum) {
+-                              *((unsigned long *)(((void *)ptregs) +
+-                              gr_reg_to_ptreg_index[i].ptregoff)) = *reg;
+-                              break;
+-                      }
+-      } else if (!rw && ptregs) {
+-              for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++)
+-                      if (gr_reg_to_ptreg_index[i].reg == regnum) {
+-                              *reg = *((unsigned long *)
+-                              (((void *)ptregs) +
+-                               gr_reg_to_ptreg_index[i].ptregoff));
+-                              break;
+-                      }
+-      } else
+-              result = !unw_access_gr(info, regnum - IA64_GR0_REGNUM,
+-                                      reg, &nat, rw);
+-      return result;
+-}
 -
--ENTRY select
--select:
+-static int kgdb_br_reg(int regnum, struct pt_regs * ptregs,
+-      struct unw_frame_info *info, unsigned long *reg, int rw)
+-{
+-      int i, result = 1;
 -
+-      if (!(regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7)))
+-              return 0;
 -
+-      switch (regnum) {
+-      case IA64_BR0_REGNUM:
+-      case IA64_BR0_REGNUM + 6:
+-      case IA64_BR0_REGNUM + 7:
+-              if (rw) {
+-                      for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++)
+-                              if (br_reg_to_ptreg_index[i].reg == regnum) {
+-                                      *((unsigned long *)
+-                                      (((void *)ptregs) +
+-                                      br_reg_to_ptreg_index[i].ptregoff)) =
+-                                      *reg;
+-                                      break;
+-                              }
+-              } else
+-                      for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++)
+-                              if (br_reg_to_ptreg_index[i].reg == regnum) {
+-                                              *reg = *((unsigned long *)
+-                                              (((void *)ptregs) +
+-                                              br_reg_to_ptreg_index[i].
+-                                              ptregoff));
+-                                              break;
+-                              }
+-              break;
+-      case IA64_BR0_REGNUM + 1:
+-      case IA64_BR0_REGNUM + 2:
+-      case IA64_BR0_REGNUM + 3:
+-      case IA64_BR0_REGNUM + 4:
+-      case IA64_BR0_REGNUM + 5:
+-              result = !unw_access_br(info, regnum - IA64_BR0_REGNUM,
+-                              reg, rw);
+-              break;
+-      }
 -
+-      return result;
+-}
 -
+-static int kgdb_fr_reg(int regnum, char *inbuffer, struct pt_regs * ptregs,
+-      struct unw_frame_info *info, unsigned long *reg,
+-      struct ia64_fpreg *freg, int rw)
+-{
+-      int result = 1;
 -
+-      if (!(regnum >= IA64_FR0_REGNUM && regnum <= (IA64_FR0_REGNUM + 127)))
+-              return 0;
 -
+-      switch (regnum) {
+-      case IA64_FR0_REGNUM + 6:
+-      case IA64_FR0_REGNUM + 7:
+-      case IA64_FR0_REGNUM + 8:
+-      case IA64_FR0_REGNUM + 9:
+-      case IA64_FR0_REGNUM + 10:
+-      case IA64_FR0_REGNUM + 11:
+-      case IA64_FR0_REGNUM + 12:
+-              if (rw) {
+-                      char *ptr = inbuffer;
+-
+-                      freg->u.bits[0] = *reg;
+-                      kgdb_hex2long(&ptr, &freg->u.bits[1]);
+-                      *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) =
+-                              *freg;
+-                      break;
+-              } else if (!ptregs)
+-                      result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM,
+-                              freg, rw);
+-              else
+-                      *freg =
+-                      *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6)));
+-              break;
+-      default:
+-              if (!rw)
+-                      result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM,
+-                              freg, rw);
+-              else
+-                      result = 0;
+-              break;
+-      }
 -
+-      return result;
+-}
 -
--    CLEAR TARGET
+-static int kgdb_ar_reg(int regnum, struct pt_regs * ptregs,
+-      struct unw_frame_info *info, unsigned long *reg, int rw)
+-{
+-      int result = 0, i;
 -
--at 0x0000007e : */    0x60000200,0x00000000,
--/*
+-      if (!(regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM))
+-              return 0;
 -
--; XXX
--;
--; In effect, SELECTION operations are backgrounded, with execution
--; continuing until code which waits for REQ or a fatal interrupt is 
--; encountered.
--;
--; So, for more performance, we could overlap the code which removes 
--; the command from the NCRs issue queue with the selection, but 
--; at this point I don't want to deal with the error recovery.
--;
+-      if (rw && ptregs) {
+-              for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++)
+-                      if (ar_reg_to_ptreg_index[i].reg == regnum) {
+-                              *((unsigned long *) (((void *)ptregs) +
+-                              ar_reg_to_ptreg_index[i].ptregoff)) =
+-                                      *reg;
+-                              result = 1;
+-                              break;
+-                      }
+-      } else if (ptregs) {
+-              for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++)
+-                      if (ar_reg_to_ptreg_index[i].reg == regnum) {
+-                              *reg = *((unsigned long *) (((void *)ptregs) +
+-                                      ar_reg_to_ptreg_index[i].ptregoff));
+-                                      result = 1;
+-                              break;
+-                      }
+-      }
 -
+-      if (result)
+-              return result;
 -
+-       result = 1;
 -
--    ; Enable selection timer
+-      switch (regnum) {
+-      case IA64_CSD_REGNUM:
+-              result = !unw_access_ar(info, UNW_AR_CSD, reg, rw);
+-              break;
+-      case IA64_SSD_REGNUM:
+-              result = !unw_access_ar(info, UNW_AR_SSD, reg, rw);
+-              break;
+-      case IA64_UNAT_REGNUM:
+-              result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
+-              break;
+-              case IA64_RNAT_REGNUM:
+-              result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
+-              break;
+-      case IA64_BSPSTORE_REGNUM:
+-              result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
+-              break;
+-      case IA64_PFS_REGNUM:
+-              result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
+-              break;
+-      case IA64_LC_REGNUM:
+-              result = !unw_access_ar(info, UNW_AR_LC, reg, rw);
+-              break;
+-      case IA64_EC_REGNUM:
+-              result = !unw_access_ar(info, UNW_AR_EC, reg, rw);
+-              break;
+-      case IA64_FPSR_REGNUM:
+-              result = !unw_access_ar(info, UNW_AR_FPSR, reg, rw);
+-              break;
+-      case IA64_RSC_REGNUM:
+-              result = !unw_access_ar(info, UNW_AR_RSC, reg, rw);
+-              break;
+-      case IA64_CCV_REGNUM:
+-              result = !unw_access_ar(info, UNW_AR_CCV, reg, rw);
+-              break;
+-      default:
+-              result = 0;
+-      }
 -
+-      return result;
+-}
 -
+-void kgdb_get_reg(char *outbuffer, int regnum, struct unw_frame_info *info,
+-      struct pt_regs *ptregs)
+-{
+-      unsigned long reg, size = 0, *mem = &reg;
+-      struct ia64_fpreg freg;
+-
+-      if (kgdb_gr_reg(regnum, info, &reg, 0) ||
+-              kgdb_gr_ptreg(regnum, ptregs, info, &reg, 0) ||
+-              kgdb_br_reg(regnum, ptregs, info, &reg, 0) ||
+-              kgdb_ar_reg(regnum, ptregs, info, &reg, 0))
+-                      size = sizeof(reg);
+-      else if (kgdb_fr_reg(regnum, NULL, ptregs, info, &reg, &freg, 0)) {
+-              size = sizeof(freg);
+-              mem = (unsigned long *)&freg;
+-      } else if (regnum == IA64_IP_REGNUM) {
+-              if (!ptregs) {
+-                      unw_get_ip(info, &reg);
+-                      size = sizeof(reg);
+-              } else {
+-                      reg = ptregs->cr_iip;
+-                      size = sizeof(reg);
+-              }
+-      } else if (regnum == IA64_CFM_REGNUM) {
+-              if (!ptregs)
+-                      unw_get_cfm(info, &reg);
+-              else
+-                      reg = ptregs->cr_ifs;
+-              size = sizeof(reg);
+-      } else if (regnum == IA64_PSR_REGNUM) {
+-              if (!ptregs && kgdb_usethread)
+-                      ptregs = (struct pt_regs *)
+-                      ((unsigned long)kgdb_usethread +
+-                      IA64_STK_OFFSET) - 1;
+-              if (ptregs)
+-                      reg = ptregs->cr_ipsr;
+-              size = sizeof(reg);
+-      } else if (regnum == IA64_PR_REGNUM) {
+-              if (ptregs)
+-                      reg = ptregs->pr;
+-              else
+-                      unw_access_pr(info, &reg, 0);
+-              size = sizeof(reg);
+-      } else if (regnum == IA64_BSP_REGNUM) {
+-              unw_get_bsp(info, &reg);
+-              size = sizeof(reg);
+-      }
 -
--    MOVE CTEST7 & 0xef TO CTEST7
+-      if (size) {
+-              kgdb_mem2hex((char *) mem, outbuffer, size);
+-              outbuffer[size*2] = 0;
+-      }
+-      else
+-              strcpy(outbuffer, "E0");
 -
--at 0x00000080 : */    0x7c1bef00,0x00000000,
--/*
+-      return;
+-}
 -
+-void kgdb_put_reg(char *inbuffer, char *outbuffer, int regnum,
+-                struct unw_frame_info *info, struct pt_regs *ptregs)
+-{
+-      unsigned long reg;
+-      struct ia64_fpreg freg;
+-      char *ptr = inbuffer;
+-
+-      kgdb_hex2long(&ptr, &reg);
+-      strcpy(outbuffer, "OK");
+-
+-      if (kgdb_gr_reg(regnum, info, &reg, 1) ||
+-              kgdb_gr_ptreg(regnum, ptregs, info, &reg, 1) ||
+-              kgdb_br_reg(regnum, ptregs, info, &reg, 1) ||
+-              kgdb_fr_reg(regnum, inbuffer, ptregs, info, &reg, &freg, 1) ||
+-              kgdb_ar_reg(regnum, ptregs, info, &reg, 1)) ;
+-      else if (regnum == IA64_IP_REGNUM)
+-              ptregs->cr_iip = reg;
+-      else if (regnum == IA64_CFM_REGNUM)
+-              ptregs->cr_ifs = reg;
+-      else if (regnum == IA64_PSR_REGNUM)
+-              ptregs->cr_ipsr = reg;
+-      else if (regnum == IA64_PR_REGNUM)
+-              ptregs->pr = reg;
+-      else
+-              strcpy(outbuffer, "E01");
+-      return;
+-}
 -
--    SELECT ATN FROM dsa_select, select_failed
+-void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+-{
+-}
 -
--at 0x00000082 : */    0x4300003c,0x00000828,
--/*
--    JUMP select_msgout, WHEN MSG_OUT
+-void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+-{
+-}
 -
--at 0x00000084 : */    0x860b0000,0x00000218,
--/*
--ENTRY select_msgout
--select_msgout:
+-void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+-{
 -
--    ; Disable selection timer
--    MOVE CTEST7 | 0x10 TO CTEST7
+-}
 -
--at 0x00000086 : */    0x7a1b1000,0x00000000,
--/*
+-#define       MAX_HW_BREAKPOINT       (20)
+-long hw_break_total_dbr, hw_break_total_ibr;
+-#define       HW_BREAKPOINT   (hw_break_total_dbr + hw_break_total_ibr)
+-#define       WATCH_INSTRUCTION       0x0
+-#define WATCH_WRITE           0x1
+-#define       WATCH_READ              0x2
+-#define       WATCH_ACCESS            0x3
 -
--    MOVE FROM dsa_msgout, WHEN MSG_OUT
+-#define       HWCAP_DBR       ((1 << WATCH_WRITE) | (1 << WATCH_READ))
+-#define       HWCAP_IBR       (1 << WATCH_INSTRUCTION)
+-struct hw_breakpoint {
+-      unsigned enabled;
+-      unsigned long capable;
+-      unsigned long type;
+-      unsigned long mask;
+-      unsigned long addr;
+-} *breakinfo;
+-
+-static struct hw_breakpoint hwbreaks[MAX_HW_BREAKPOINT];
+-
+-enum instruction_type { A, I, M, F, B, L, X, u };
+-
+-static enum instruction_type bundle_encoding[32][3] = {
+-      {M, I, I},              /* 00 */
+-      {M, I, I},              /* 01 */
+-      {M, I, I},              /* 02 */
+-      {M, I, I},              /* 03 */
+-      {M, L, X},              /* 04 */
+-      {M, L, X},              /* 05 */
+-      {u, u, u},              /* 06 */
+-      {u, u, u},              /* 07 */
+-      {M, M, I},              /* 08 */
+-      {M, M, I},              /* 09 */
+-      {M, M, I},              /* 0A */
+-      {M, M, I},              /* 0B */
+-      {M, F, I},              /* 0C */
+-      {M, F, I},              /* 0D */
+-      {M, M, F},              /* 0E */
+-      {M, M, F},              /* 0F */
+-      {M, I, B},              /* 10 */
+-      {M, I, B},              /* 11 */
+-      {M, B, B},              /* 12 */
+-      {M, B, B},              /* 13 */
+-      {u, u, u},              /* 14 */
+-      {u, u, u},              /* 15 */
+-      {B, B, B},              /* 16 */
+-      {B, B, B},              /* 17 */
+-      {M, M, B},              /* 18 */
+-      {M, M, B},              /* 19 */
+-      {u, u, u},              /* 1A */
+-      {u, u, u},              /* 1B */
+-      {M, F, B},              /* 1C */
+-      {M, F, B},              /* 1D */
+-      {u, u, u},              /* 1E */
+-      {u, u, u},              /* 1F */
+-};
 -
--at 0x00000088 : */    0x1e000000,0x00000040,
--/*
+-int kgdb_validate_break_address(unsigned long addr)
+-{
+-      int error;
+-      char tmp_variable[BREAK_INSTR_SIZE];
+-      error = kgdb_get_mem((char *)(addr & BREAK_INSTR_ALIGN), tmp_variable,
+-              BREAK_INSTR_SIZE);
+-      return error;
+-}
 -
+-int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
+-{
+-      extern unsigned long _start[];
+-      unsigned long slot = addr & BREAK_INSTR_ALIGN, bundle_addr;
+-      unsigned long template;
+-      struct bundle {
+-              struct {
+-                      unsigned long long template:5;
+-                      unsigned long long slot0:41;
+-                      unsigned long long slot1_p0:64 - 46;
+-              } quad0;
+-              struct {
+-                      unsigned long long slot1_p1:41 - (64 - 46);
+-                      unsigned long long slot2:41;
+-              } quad1;
+-      } bundle;
+-      int ret;
 -
+-      bundle_addr = addr & ~0xFULL;
 -
+-      if (bundle_addr == (unsigned long)_start)
+-              return 0;
 -
+-      ret = kgdb_get_mem((char *)bundle_addr, (char *)&bundle,
+-                         BREAK_INSTR_SIZE);
+-      if (ret < 0)
+-              return ret;
 -
+-      if (slot > 2)
+-              slot = 0;
 -
+-      memcpy(saved_instr, &bundle, BREAK_INSTR_SIZE);
+-      template = bundle.quad0.template;
 -
+-      if (slot == 1 && bundle_encoding[template][1] == L)
+-              slot = 2;
 -
+-      switch (slot) {
+-      case 0:
+-              bundle.quad0.slot0 = BREAKNUM;
+-              break;
+-      case 1:
+-              bundle.quad0.slot1_p0 = BREAKNUM;
+-              bundle.quad1.slot1_p1 = (BREAKNUM >> (64 - 46));
+-              break;
+-      case 2:
+-              bundle.quad1.slot2 = BREAKNUM;
+-              break;
+-      }
 -
+-      return kgdb_set_mem((char *)bundle_addr, (char *)&bundle,
+-                          BREAK_INSTR_SIZE);
+-}
 -
--   RETURN
+-int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
+-{
+-      extern unsigned long _start[];
+-      
+-      addr = addr & BREAK_INSTR_ALIGN;
+-      if (addr == (unsigned long)_start)
+-              return 0;
+-      return kgdb_set_mem((char *)addr, (char *)bundle, BREAK_INSTR_SIZE);
+-}
 -
--at 0x0000008a : */    0x90080000,0x00000000,
--/*
+-volatile static struct smp_unw {
+-      struct unw_frame_info *unw;
+-      struct task_struct *task;
+-} smp_unw[NR_CPUS];
 -
--; 
--; select_done
--; 
--; PURPOSE: continue on to normal data transfer; called as the exit 
--;     point from dsa_begin.
--;
--; INPUTS: dsa
--;
--; CALLS: OK
--;
--;
+-static int inline kgdb_get_blocked_state(struct task_struct *p,
+-                                       struct unw_frame_info *unw)
+-{
+-      unsigned long ip;
+-      int count = 0;
 -
--select_done:
+-      unw_init_from_blocked_task(unw, p);
+-      ip = 0UL;
+-      do {
+-              if (unw_unwind(unw) < 0)
+-                      return -1;
+-              unw_get_ip(unw, &ip);
+-              if (!in_sched_functions(ip))
+-                      break;
+-      } while (count++ < 16);
 -
--; NOTE DSA is corrupt when we arrive here!
--    MOVE MEMORY 4, saved_dsa, addr_dsa
+-      if (!ip)
+-              return -1;
+-      else
+-              return 0;
+-}
 -
--at 0x0000008c : */    0xc0000004,0x00000000,0x00000000,
--/*
+-static void inline kgdb_wait(struct pt_regs *regs)
+-{
+-      unsigned long hw_breakpoint_status = ia64_getreg(_IA64_REG_PSR);
+-      if (hw_breakpoint_status & IA64_PSR_DB)
+-              ia64_setreg(_IA64_REG_PSR_L,
+-                          hw_breakpoint_status ^ IA64_PSR_DB);
+-      kgdb_nmihook(smp_processor_id(), regs);
+-      if (hw_breakpoint_status & IA64_PSR_DB)
+-              ia64_setreg(_IA64_REG_PSR_L, hw_breakpoint_status);
 -
+-      return;
+-}
 -
+-static void inline normalize(struct unw_frame_info *running,
+-                           struct pt_regs *regs)
+-{
+-      unsigned long sp;
 -
+-      do {
+-              unw_get_sp(running, &sp);
+-              if ((sp + 0x10) >= (unsigned long)regs)
+-                      break;
+-      } while (unw_unwind(running) >= 0);
 -
+-      return;
+-}
 -
+-static void kgdb_init_running(struct unw_frame_info *unw, void *data)
+-{
+-      struct pt_regs *regs;
 -
+-      regs = data;
+-      normalize(unw, regs);
+-      smp_unw[smp_processor_id()].unw = unw;
+-      kgdb_wait(regs);
+-}
 -
+-void kgdb_wait_ipi(struct pt_regs *regs)
+-{
+-      struct unw_frame_info unw;
 -
--; After a successful selection, we should get either a CMD phase or 
--; some transfer request negotiation message.
+-      smp_unw[smp_processor_id()].task = current;
 -
--    JUMP cmdout, WHEN CMD
+-      if (user_mode(regs)) {
+-              smp_unw[smp_processor_id()].unw = (struct unw_frame_info *)1;
+-              kgdb_wait(regs);
+-      } else {
+-              if (current->state == TASK_RUNNING)
+-                      unw_init_running(kgdb_init_running, regs);
+-              else {
+-                      if (kgdb_get_blocked_state(current, &unw))
+-                              smp_unw[smp_processor_id()].unw =
+-                                  (struct unw_frame_info *)1;
+-                      else
+-                              smp_unw[smp_processor_id()].unw = &unw;
+-                      kgdb_wait(regs);
+-              }
+-      }
 -
--at 0x0000008f : */    0x820b0000,0x0000025c,
--/*
--    INT int_err_unexpected_phase, WHEN NOT MSG_IN 
+-      smp_unw[smp_processor_id()].unw = NULL;
+-      return;
+-}
 -
--at 0x00000091 : */    0x9f030000,0x00000000,
--/*
+-void kgdb_roundup_cpus(unsigned long flags)
+-{
+-      if (num_online_cpus() > 1)
+-              smp_send_nmi_allbutself();
+-}
 -
--select_msg_in:
--    CALL msg_in, WHEN MSG_IN
+-static volatile int kgdb_hwbreak_sstep[NR_CPUS];
 -
--at 0x00000093 : */    0x8f0b0000,0x0000041c,
--/*
--    JUMP select_msg_in, WHEN MSG_IN
+-static int kgdb_notify(struct notifier_block *self, unsigned long cmd,
+-      void *ptr)
+-{
+-      struct die_args *args = ptr;
+-      struct pt_regs *regs = args->regs;
+-      unsigned long err = args->err;
 -
--at 0x00000095 : */    0x870b0000,0x0000024c,
--/*
+-      switch (cmd) {
+-      default:
+-              return NOTIFY_DONE;
+-      case DIE_PAGE_FAULT_NO_CONTEXT:
+-              if (atomic_read(&debugger_active) && kgdb_may_fault) {
+-                      kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+-                      return NOTIFY_STOP;
+-              }
+-              break;
+-      case DIE_BREAK:
+-              if (user_mode(regs) || err == 0x80001)
+-                      return NOTIFY_DONE;
+-              break;
+-      case DIE_FAULT:
+-              if (user_mode(regs))
+-                      return NOTIFY_DONE;
+-              else if (err == 36 && kgdb_hwbreak_sstep[smp_processor_id()]) {
+-                      kgdb_hwbreak_sstep[smp_processor_id()] = 0;
+-                      regs->cr_ipsr &= ~IA64_PSR_SS;
+-                      return NOTIFY_STOP;
+-              }
+-      case DIE_MCA_MONARCH_PROCESS:
+-      case DIE_INIT_MONARCH_PROCESS:
+-              break;
+-      }
 -
--cmdout:
--    INT int_err_unexpected_phase, WHEN NOT CMD
+-      kgdb_handle_exception(args->trapnr, args->signr, args->err, regs);
+-      return NOTIFY_STOP;
+-}
 -
--at 0x00000097 : */    0x9a030000,0x00000000,
--/*
+-static struct notifier_block kgdb_notifier = {
+-      .notifier_call = kgdb_notify,
+-};
 -
+-int kgdb_arch_init(void)
+-{
+-      atomic_notifier_chain_register(&ia64die_chain, &kgdb_notifier);
+-      return 0;
+-}
 -
+-static void do_kgdb_handle_exception(struct unw_frame_info *, void *data);
 -
--ENTRY cmdout_cmdout
--cmdout_cmdout:
+-struct kgdb_state {
+-      int e_vector;
+-      int signo;
+-      unsigned long err_code;
+-      struct pt_regs *regs;
+-      struct unw_frame_info *unw;
+-      char *inbuf;
+-      char *outbuf;
+-      int unwind;
+-      int ret;
+-};
 -
--    MOVE FROM dsa_cmdout, WHEN CMD
+-static void inline kgdb_pc(struct pt_regs *regs, unsigned long pc)
+-{
+-      regs->cr_iip = pc & ~0xf;
+-      ia64_psr(regs)->ri = pc & 0x3;
+-      return;
+-}
 -
--at 0x00000099 : */    0x1a000000,0x00000048,
--/*
+-int kgdb_arch_handle_exception(int e_vector, int signo,
+-                             int err_code, char *remcom_in_buffer,
+-                             char *remcom_out_buffer,
+-                             struct pt_regs *linux_regs)
+-{
+-      struct kgdb_state info;
+-
+-      info.e_vector = e_vector;
+-      info.signo = signo;
+-      info.err_code = err_code;
+-      info.unw = (void *)0;
+-      info.inbuf = remcom_in_buffer;
+-      info.outbuf = remcom_out_buffer;
+-      info.unwind = 0;
+-      info.ret = -1;
+-
+-      if (remcom_in_buffer[0] == 'c' || remcom_in_buffer[0] == 's') {
+-              info.regs = linux_regs;
+-              do_kgdb_handle_exception(NULL, &info);
+-      } else if (kgdb_usethread == current) {
+-              info.regs = linux_regs;
+-              info.unwind = 1;
+-              unw_init_running(do_kgdb_handle_exception, &info);
+-      } else if (kgdb_usethread->state != TASK_RUNNING) {
+-              struct unw_frame_info unw_info;
+-
+-              if (kgdb_get_blocked_state(kgdb_usethread, &unw_info)) {
+-                      info.ret = 1;
+-                      goto bad;
+-              }
+-              info.regs = NULL;
+-              do_kgdb_handle_exception(&unw_info, &info);
+-      } else {
+-              int i;
 -
+-              for (i = 0; i < NR_CPUS; i++)
+-                      if (smp_unw[i].task == kgdb_usethread && smp_unw[i].unw
+-                          && smp_unw[i].unw != (struct unw_frame_info *)1) {
+-                              info.regs = NULL;
+-                              do_kgdb_handle_exception(smp_unw[i].unw, &info);
+-                              break;
+-                      } else {
+-                              info.ret = 1;
+-                              goto bad;
+-                      }
+-      }
 -
+-      bad:
+-      if (info.ret != -1 && remcom_in_buffer[0] == 'p') {
+-              unsigned long bad = 0xbad4badbadbadbadUL;
 -
+-              printk("kgdb_arch_handle_exception: p packet bad (%s)\n",
+-                     remcom_in_buffer);
+-              kgdb_mem2hex((char *)&bad, remcom_out_buffer, sizeof(bad));
+-              remcom_out_buffer[sizeof(bad) * 2] = 0;
+-              info.ret = -1;
+-      }
+-      return info.ret;
+-}
 -
--;
--; data_transfer  
--; other_out
--; other_in
--; other_transfer
--;
--; PURPOSE : handle the main data transfer for a SCSI command in 
--;     several parts.  In the first part, data_transfer, DATA_IN
--;     and DATA_OUT phases are allowed, with the user provided
--;     code (usually dynamically generated based on the scatter/gather
--;     list associated with a SCSI command) called to handle these 
--;     phases.
--;
--;     After control has passed to one of the user provided 
--;     DATA_IN or DATA_OUT routines, back calls are made to 
--;     other_transfer_in or other_transfer_out to handle non-DATA IN
--;     and DATA OUT phases respectively, with the state of the active
--;     data pointer being preserved in TEMP.
--;
--;     On completion, the user code passes control to other_transfer
--;     which causes DATA_IN and DATA_OUT to result in unexpected_phase
--;     interrupts so that data overruns may be trapped.
--;
--; INPUTS : DSA - SCSI command
--;
--; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in
--;     other_transfer
--;
--; MODIFIES : SCRATCH
--;
--; EXITS : if STATUS IN is detected, signifying command completion,
--;     the NCR jumps to command_complete.  If MSG IN occurs, a 
--;     CALL is made to msg_in.  Otherwise, other_transfer runs in 
--;     an infinite loop.
--;     
--
--ENTRY data_transfer
--data_transfer:
--    JUMP cmdout_cmdout, WHEN CMD
--
--at 0x0000009b : */    0x820b0000,0x00000264,
 -/*
--    CALL msg_in, WHEN MSG_IN
+- * This is done because I evidently made an incorrect 'p' encoding
+- * when my patch for gdb was committed. It was later corrected. This
+- * check supports both my wrong encoding of the register number and
+- * the correct encoding. Eventually this should be eliminated and
+- * kgdb_hex2long should be demarshalling the regnum.
+- */
+-static inline int check_packet(unsigned int regnum, char *packet)
+-{
+-      static int check_done, swap;
+-      unsigned long reglong;
 -
--at 0x0000009d : */    0x8f0b0000,0x0000041c,
--/*
--    INT int_err_unexpected_phase, WHEN MSG_OUT
+-      if (likely(check_done)) {
+-              if (swap) {
+-                      kgdb_hex2long(&packet, &reglong);
+-                      regnum = (int) reglong;
+-              }
 -
--at 0x0000009f : */    0x9e0b0000,0x00000000,
--/*
--    JUMP do_dataout, WHEN DATA_OUT
+-      } else {
+-              if (regnum > NUM_REGS) {
+-                      kgdb_hex2long(&packet, &reglong);
+-                      regnum = (int) reglong;
+-                      swap = 1;
+-              }
+-              check_done = 1;
+-      }
+-      return regnum;
+-}
 -
--at 0x000000a1 : */    0x800b0000,0x000002a4,
--/*
--    JUMP do_datain, WHEN DATA_IN
+-static void do_kgdb_handle_exception(struct unw_frame_info *unw_info,
+-      void *data)
+-{
+-      long addr;
+-      char *ptr;
+-      unsigned long newPC;
+-      int e_vector, signo;
+-      unsigned long err_code;
+-      struct pt_regs *linux_regs;
+-      struct kgdb_state *info;
+-      char *remcom_in_buffer, *remcom_out_buffer;
+-
+-      info = data;
+-      info->unw = unw_info;
+-      e_vector = info->e_vector;
+-      signo = info->signo;
+-      err_code = info->err_code;
+-      remcom_in_buffer = info->inbuf;
+-      remcom_out_buffer = info->outbuf;
+-      linux_regs = info->regs;
+-
+-      if (info->unwind)
+-              normalize(unw_info, linux_regs);
+-
+-      switch (remcom_in_buffer[0]) {
+-      case 'p':
+-              {
+-                      unsigned int regnum;
+-
+-                      kgdb_hex2mem(&remcom_in_buffer[1], (char *)&regnum,
+-                                   sizeof(regnum));
+-                      regnum = check_packet(regnum, &remcom_in_buffer[1]);
+-                      if (regnum >= NUM_REGS) {
+-                              remcom_out_buffer[0] = 'E';
+-                              remcom_out_buffer[1] = 0;
+-                      } else
+-                              kgdb_get_reg(remcom_out_buffer, regnum,
+-                                           unw_info, linux_regs);
+-                      break;
+-              }
+-      case 'P':
+-              {
+-                      unsigned int regno;
+-                      long v;
+-                      char *ptr;
+-
+-                      ptr = &remcom_in_buffer[1];
+-                      if ((!kgdb_usethread || kgdb_usethread == current) &&
+-                          kgdb_hex2long(&ptr, &v) &&
+-                          *ptr++ == '=' && (v >= 0)) {
+-                              regno = (unsigned int)v;
+-                              regno = (regno >= NUM_REGS ? 0 : regno);
+-                              kgdb_put_reg(ptr, remcom_out_buffer, regno,
+-                                           unw_info, linux_regs);
+-                      } else
+-                              strcpy(remcom_out_buffer, "E01");
+-                      break;
+-              }
+-      case 'c':
+-      case 's':
+-              if (e_vector == TRAP_BRKPT && err_code == KGDBBREAKNUM) {
+-                      if (ia64_psr(linux_regs)->ri < 2)
+-                              kgdb_pc(linux_regs, linux_regs->cr_iip +
+-                                      ia64_psr(linux_regs)->ri + 1);
+-                      else
+-                              kgdb_pc(linux_regs, linux_regs->cr_iip + 16);
+-              }
 -
--at 0x000000a3 : */    0x810b0000,0x000002fc,
--/*
--    JUMP command_complete, WHEN STATUS
+-              /* try to read optional parameter, pc unchanged if no parm */
+-              ptr = &remcom_in_buffer[1];
+-              if (kgdb_hex2long(&ptr, &addr)) {
+-                      linux_regs->cr_iip = addr;
+-              }
+-              newPC = linux_regs->cr_iip;
 -
--at 0x000000a5 : */    0x830b0000,0x0000065c,
--/*
--    JUMP data_transfer
+-              /* clear the trace bit */
+-              linux_regs->cr_ipsr &= ~IA64_PSR_SS;
 -
--at 0x000000a7 : */    0x80080000,0x0000026c,
--/*
--ENTRY end_data_transfer
--end_data_transfer:
+-              atomic_set(&cpu_doing_single_step, -1);
+-
+-              /* set the trace bit if we're stepping or took a hardware break */
+-              if (remcom_in_buffer[0] == 's' || e_vector == TRAP_HWBKPT) {
+-                      linux_regs->cr_ipsr |= IA64_PSR_SS;
+-                      debugger_step = 1;
+-                      if (kgdb_contthread)
+-                              atomic_set(&cpu_doing_single_step,
+-                                         smp_processor_id());
+-              }
 -
--;
--; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain 
--; should be fixed up whenever the nexus changes so it can point to the 
--; correct routine for that command.
--;
+-              kgdb_correct_hw_break();
 -
+-              /* if not hardware breakpoint, then reenable them */
+-              if (e_vector != TRAP_HWBKPT)
+-                      linux_regs->cr_ipsr |= IA64_PSR_DB;
+-              else {
+-                      kgdb_hwbreak_sstep[smp_processor_id()] = 1;
+-                      linux_regs->cr_ipsr &= ~IA64_PSR_DB;
+-              }
 -
--; Nasty jump to dsa->dataout
--do_dataout:
+-              info->ret = 0;
+-              break;
+-      default:
+-              break;
+-      }
 -
--    MOVE MEMORY 4, saved_dsa, addr_scratch
+-      return;
+-}
 -
--at 0x000000a9 : */    0xc0000004,0x00000000,0x00000000,
--/*
+-struct kgdb_arch arch_kgdb_ops = {
+-      .gdb_bpt_instr = {0xcc},
+-};
+diff -Nurb linux-2.6.22-590/arch/ia64/kernel/smp.c linux-2.6.22-570/arch/ia64/kernel/smp.c
+--- linux-2.6.22-590/arch/ia64/kernel/smp.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ia64/kernel/smp.c    2007-07-08 19:32:17.000000000 -0400
+@@ -48,7 +48,6 @@
+ #include <asm/tlbflush.h>
+ #include <asm/unistd.h>
+ #include <asm/mca.h>
+-#include <linux/kgdb.h>
+ /*
+  * Note: alignment of 4 entries/cacheline was empirically determined
+@@ -80,9 +79,6 @@
+ #define IPI_CALL_FUNC         0
+ #define IPI_CPU_STOP          1
+-#ifdef        CONFIG_KGDB
+-#define       IPI_KGDB_INTERRUPT      2
+-#endif
+ #define IPI_KDUMP_CPU_STOP    3
+ /* This needs to be cacheline aligned because it is written to by *other* CPUs.  */
+@@ -173,11 +169,6 @@
+                             case IPI_CPU_STOP:
+                               stop_this_cpu();
+                               break;
+-#ifdef        CONFIG_KGDB
+-                            case IPI_KGDB_INTERRUPT:
+-                              kgdb_wait_ipi(get_irq_regs());
+-                              break;
+-#endif
+ #ifdef CONFIG_KEXEC
+                             case IPI_KDUMP_CPU_STOP:
+                               unw_init_running(kdump_cpu_freeze, NULL);
+@@ -408,14 +399,6 @@
+ }
+ EXPORT_SYMBOL(smp_call_function_single);
+-#ifdef        CONFIG_KGDB
+-void
+-smp_send_nmi_allbutself(void)
+-{
+-      send_IPI_allbutself(IPI_KGDB_INTERRUPT);
+-}
+-#endif
 -
+ /*
+  * this function sends a 'generic call function' IPI to all other CPUs
+  * in the system.
+diff -Nurb linux-2.6.22-590/arch/ia64/kernel/traps.c linux-2.6.22-570/arch/ia64/kernel/traps.c
+--- linux-2.6.22-590/arch/ia64/kernel/traps.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ia64/kernel/traps.c  2008-01-23 19:16:03.000000000 -0500
+@@ -155,12 +155,8 @@
+               break;
+             default:
+-              if (break_num < 0x40000 || break_num > 0x100000) {
+-                      if (notify_die(DIE_BREAK, "bad break", regs,
+-                              break_num, TRAP_BRKPT, SIGTRAP) == NOTIFY_STOP)
+-                              return;
++              if (break_num < 0x40000 || break_num > 0x100000)
+                       die_if_kernel("Bad break", regs, break_num);
+-              }
+               if (break_num < 0x80000) {
+                       sig = SIGILL; code = __ILL_BREAK;
+diff -Nurb linux-2.6.22-590/arch/ia64/mm/extable.c linux-2.6.22-570/arch/ia64/mm/extable.c
+--- linux-2.6.22-590/arch/ia64/mm/extable.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ia64/mm/extable.c    2007-07-08 19:32:17.000000000 -0400
+@@ -6,7 +6,6 @@
+  */
+ #include <linux/sort.h>
+-#include <linux/kgdb.h>
+ #include <asm/uaccess.h>
+ #include <asm/module.h>
+@@ -74,11 +73,6 @@
+                 else
+                         last = mid - 1;
+         }
+-#ifdef CONFIG_KGDB
+-      if (atomic_read(&debugger_active) && kgdb_may_fault)
+-              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+-              /* Not reached. */
+-#endif
+         return NULL;
+ }
+diff -Nurb linux-2.6.22-590/arch/ia64/mm/fault.c linux-2.6.22-570/arch/ia64/mm/fault.c
+--- linux-2.6.22-590/arch/ia64/mm/fault.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ia64/mm/fault.c      2008-01-23 19:16:03.000000000 -0500
+@@ -255,10 +255,6 @@
+        */
+       bust_spinlocks(1);
+-      if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs,
+-                      isr, 14, SIGSEGV) == NOTIFY_STOP)
+-              return;
 -
+       if (address < PAGE_SIZE)
+               printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference (address %016lx)\n", address);
+       else
+diff -Nurb linux-2.6.22-590/arch/mips/Kconfig linux-2.6.22-570/arch/mips/Kconfig
+--- linux-2.6.22-590/arch/mips/Kconfig 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/Kconfig 2008-01-23 19:16:03.000000000 -0500
+@@ -30,6 +30,7 @@
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
++      select SYS_SUPPORTS_KGDB
+       help
+         The eXcite is a smart camera platform manufactured by
+         Basler Vision Technologies AG.
+@@ -97,6 +98,7 @@
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
++      select SYS_SUPPORTS_KGDB
+       help
+         This is an evaluation board based on the Galileo GT-64120
+         single-chip system controller that contains a MIPS R5000 compatible
+@@ -267,6 +269,7 @@
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
++      select SYS_SUPPORTS_KGDB
+       help
+         The Ocelot is a MIPS-based Single Board Computer (SBC) made by
+         Momentum Computer <http://www.momenco.com/>.
+@@ -328,6 +331,8 @@
+       select SYS_HAS_CPU_R5432
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
++      select SYS_SUPPORTS_KGDB
++      select SYS_SUPPORTS_KGDB
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       help
+         This enables support for the R5432-based NEC DDB Vrc-5477,
+@@ -355,6 +360,7 @@
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_HIGHMEM
++      select SYS_SUPPORTS_KGDB
+       select SYS_SUPPORTS_SMP
+       help
+         Yosemite is an evaluation board for the RM9000x2 processor
+@@ -434,6 +440,7 @@
+       select SYS_HAS_CPU_R10000
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
++      select SYS_SUPPORTS_KGDB
+       select SYS_SUPPORTS_NUMA
+       select SYS_SUPPORTS_SMP
+       select GENERIC_HARDIRQS_NO__DO_IRQ
+@@ -483,6 +490,7 @@
+       select SYS_HAS_CPU_SB1
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_HIGHMEM
++      select SYS_SUPPORTS_KGDB
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+ config SIBYTE_SENTOSA
+@@ -623,6 +631,7 @@
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       select SYS_SUPPORTS_BIG_ENDIAN
++      select SYS_SUPPORTS_KGDB
+       select GENERIC_HARDIRQS_NO__DO_IRQ
+       help
+         This Toshiba board is based on the TX4927 processor. Say Y here to
+@@ -641,6 +650,7 @@
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       select SYS_SUPPORTS_BIG_ENDIAN
++      select SYS_SUPPORTS_KGDB
+       select GENERIC_HARDIRQS_NO__DO_IRQ
+       help
+         This Toshiba board is based on the TX4938 processor. Say Y here to
+@@ -816,6 +826,7 @@
+ config DDB5XXX_COMMON
+       bool
++      select SYS_SUPPORTS_KGDB
+ config MIPS_BOARDS_GEN
+       bool
+@@ -851,6 +862,7 @@
+       select SYS_HAS_EARLY_PRINTK
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select GENERIC_HARDIRQS_NO__DO_IRQ
++      select SYS_SUPPORTS_KGDB
+ config SWAP_IO_SPACE
+       bool
+diff -Nurb linux-2.6.22-590/arch/mips/Kconfig.debug linux-2.6.22-570/arch/mips/Kconfig.debug
+--- linux-2.6.22-590/arch/mips/Kconfig.debug   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/Kconfig.debug   2007-07-08 19:32:17.000000000 -0400
+@@ -46,6 +46,28 @@
+         arch/mips/kernel/smtc.c.  This debugging option result in significant
+         overhead so should be disabled in production kernels.
++config KGDB
++      bool "Remote GDB kernel debugging"
++      depends on DEBUG_KERNEL && SYS_SUPPORTS_KGDB
++      select DEBUG_INFO
++      help
++        If you say Y here, it will be possible to remotely debug the MIPS
++        kernel using gdb. This enlarges your kernel image disk size by
++        several megabytes and requires a machine with more than 16 MB,
++        better 32 MB RAM to avoid excessive linking time. This is only
++        useful for kernel hackers. If unsure, say N.
++
++config SYS_SUPPORTS_KGDB
++      bool
++
++config GDB_CONSOLE
++      bool "Console output to GDB"
++      depends on KGDB
++      help
++        If you are using GDB for remote debugging over a serial port and
++        would like kernel messages to be formatted into GDB $O packets so
++        that GDB prints them as program output, say 'Y'.
++
+ config SB1XXX_CORELIS
+       bool "Corelis Debugger"
+       depends on SIBYTE_SB1xxx_SOC
+diff -Nurb linux-2.6.22-590/arch/mips/au1000/common/Makefile linux-2.6.22-570/arch/mips/au1000/common/Makefile
+--- linux-2.6.22-590/arch/mips/au1000/common/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/au1000/common/Makefile  2007-07-08 19:32:17.000000000 -0400
+@@ -10,4 +10,5 @@
+       au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
+       sleeper.o cputable.o dma.o dbdma.o gpio.o
++obj-$(CONFIG_KGDB)            += dbg_io.o
+ obj-$(CONFIG_PCI)             += pci.o
+diff -Nurb linux-2.6.22-590/arch/mips/au1000/common/dbg_io.c linux-2.6.22-570/arch/mips/au1000/common/dbg_io.c
+--- linux-2.6.22-590/arch/mips/au1000/common/dbg_io.c  1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/au1000/common/dbg_io.c  2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,121 @@
++
++#include <asm/io.h>
++#include <asm/mach-au1x00/au1000.h>
++
++#ifdef CONFIG_KGDB
++
++/*
++ * FIXME the user should be able to select the
++ * uart to be used for debugging.
++ */
++#define DEBUG_BASE  UART_DEBUG_BASE
++/**/
++
++/* we need uint32 uint8 */
++/* #include "types.h" */
++typedef         unsigned char uint8;
++typedef         unsigned int  uint32;
++
++#define         UART16550_BAUD_2400             2400
++#define         UART16550_BAUD_4800             4800
++#define         UART16550_BAUD_9600             9600
++#define         UART16550_BAUD_19200            19200
++#define         UART16550_BAUD_38400            38400
++#define         UART16550_BAUD_57600            57600
++#define         UART16550_BAUD_115200           115200
++
++#define         UART16550_PARITY_NONE           0
++#define         UART16550_PARITY_ODD            0x08
++#define         UART16550_PARITY_EVEN           0x18
++#define         UART16550_PARITY_MARK           0x28
++#define         UART16550_PARITY_SPACE          0x38
++
++#define         UART16550_DATA_5BIT             0x0
++#define         UART16550_DATA_6BIT             0x1
++#define         UART16550_DATA_7BIT             0x2
++#define         UART16550_DATA_8BIT             0x3
++
++#define         UART16550_STOP_1BIT             0x0
++#define         UART16550_STOP_2BIT             0x4
++
++
++#define UART_RX               0       /* Receive buffer */
++#define UART_TX               4       /* Transmit buffer */
++#define UART_IER      8       /* Interrupt Enable Register */
++#define UART_IIR      0xC     /* Interrupt ID Register */
++#define UART_FCR      0x10    /* FIFO Control Register */
++#define UART_LCR      0x14    /* Line Control Register */
++#define UART_MCR      0x18    /* Modem Control Register */
++#define UART_LSR      0x1C    /* Line Status Register */
++#define UART_MSR      0x20    /* Modem Status Register */
++#define UART_CLK      0x28    /* Baud Rat4e Clock Divider */
++#define UART_MOD_CNTRL        0x100   /* Module Control */
++
++/* memory-mapped read/write of the port */
++#define UART16550_READ(y)    (au_readl(DEBUG_BASE + y) & 0xff)
++#define UART16550_WRITE(y,z) (au_writel(z&0xff, DEBUG_BASE + y))
++
++extern unsigned long get_au1x00_uart_baud_base(void);
++extern unsigned long cal_r4koff(void);
++
++void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
++{
++
++      if (UART16550_READ(UART_MOD_CNTRL) != 0x3) {
++              UART16550_WRITE(UART_MOD_CNTRL, 3);
++      }
++      cal_r4koff();
++
++      /* disable interrupts */
++      UART16550_WRITE(UART_IER, 0);
++
++      /* set up baud rate */
++      {
++              uint32 divisor;
++
++              /* set divisor */
++              divisor = get_au1x00_uart_baud_base() / baud;
++              UART16550_WRITE(UART_CLK, divisor & 0xffff);
++      }
++
++      /* set data format */
++      UART16550_WRITE(UART_LCR, (data | parity | stop));
++}
++
++static int remoteDebugInitialized = 0;
++
++uint8 getDebugChar(void)
++{
++      if (!remoteDebugInitialized) {
++              remoteDebugInitialized = 1;
++              debugInit(UART16550_BAUD_115200,
++                        UART16550_DATA_8BIT,
++                        UART16550_PARITY_NONE,
++                        UART16550_STOP_1BIT);
++      }
++
++      while((UART16550_READ(UART_LSR) & 0x1) == 0);
++      return UART16550_READ(UART_RX);
++}
++
++
++int putDebugChar(uint8 byte)
++{
++//    int i;
++
++      if (!remoteDebugInitialized) {
++              remoteDebugInitialized = 1;
++              debugInit(UART16550_BAUD_115200,
++                        UART16550_DATA_8BIT,
++                        UART16550_PARITY_NONE,
++                        UART16550_STOP_1BIT);
++      }
++
++      while ((UART16550_READ(UART_LSR)&0x40) == 0);
++      UART16550_WRITE(UART_TX, byte);
++      //for (i=0;i<0xfff;i++);
++
++      return 1;
++}
++
++#endif
+diff -Nurb linux-2.6.22-590/arch/mips/basler/excite/Makefile linux-2.6.22-570/arch/mips/basler/excite/Makefile
+--- linux-2.6.22-590/arch/mips/basler/excite/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/basler/excite/Makefile  2007-07-08 19:32:17.000000000 -0400
+@@ -5,4 +5,5 @@
+ obj-$(CONFIG_BASLER_EXCITE)   += excite_irq.o excite_prom.o excite_setup.o \
+                                  excite_device.o excite_procfs.o
++obj-$(CONFIG_KGDB)            += excite_dbg_io.o
+ obj-m                         += excite_iodev.o
+diff -Nurb linux-2.6.22-590/arch/mips/basler/excite/excite_dbg_io.c linux-2.6.22-570/arch/mips/basler/excite/excite_dbg_io.c
+--- linux-2.6.22-590/arch/mips/basler/excite/excite_dbg_io.c   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/basler/excite/excite_dbg_io.c   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,121 @@
++/*
++ *  Copyright (C) 2004 by Basler Vision Technologies AG
++ *  Author: Thomas Koeller <thomas.koeller@baslerweb.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/linkage.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <asm/gdb-stub.h>
++#include <asm/rm9k-ocd.h>
++#include <excite.h>
++
++#if defined(CONFIG_SERIAL_8250) && CONFIG_SERIAL_8250_NR_UARTS > 1
++#error Debug port used by serial driver
++#endif
++
++#define UART_CLK              25000000
++#define BASE_BAUD             (UART_CLK / 16)
++#define REGISTER_BASE_0               0x0208UL
++#define REGISTER_BASE_1               0x0238UL
++
++#define REGISTER_BASE_DBG     REGISTER_BASE_1
++
++#define CPRR  0x0004
++#define UACFG 0x0200
++#define UAINTS        0x0204
++#define UARBR (REGISTER_BASE_DBG + 0x0000)
++#define UATHR (REGISTER_BASE_DBG + 0x0004)
++#define UADLL (REGISTER_BASE_DBG + 0x0008)
++#define UAIER (REGISTER_BASE_DBG + 0x000c)
++#define UADLH (REGISTER_BASE_DBG + 0x0010)
++#define UAIIR (REGISTER_BASE_DBG + 0x0014)
++#define UAFCR (REGISTER_BASE_DBG + 0x0018)
++#define UALCR (REGISTER_BASE_DBG + 0x001c)
++#define UAMCR (REGISTER_BASE_DBG + 0x0020)
++#define UALSR (REGISTER_BASE_DBG + 0x0024)
++#define UAMSR (REGISTER_BASE_DBG + 0x0028)
++#define UASCR (REGISTER_BASE_DBG + 0x002c)
++
++#define       PARITY_NONE     0
++#define       PARITY_ODD      0x08
++#define       PARITY_EVEN     0x18
++#define       PARITY_MARK     0x28
++#define       PARITY_SPACE    0x38
++
++#define       DATA_5BIT       0x0
++#define       DATA_6BIT       0x1
++#define       DATA_7BIT       0x2
++#define       DATA_8BIT       0x3
++
++#define       STOP_1BIT       0x0
++#define       STOP_2BIT       0x4
++
++#define BAUD_DBG      57600
++#define       PARITY_DBG      PARITY_NONE
++#define       DATA_DBG        DATA_8BIT
++#define       STOP_DBG        STOP_1BIT
++
++/* Initialize the serial port for KGDB debugging */
++void __init excite_kgdb_init(void)
++{
++      const u32 divisor = BASE_BAUD / BAUD_DBG;
++
++      /* Take the UART out of reset */
++      titan_writel(0x00ff1cff, CPRR);
++      titan_writel(0x00000000, UACFG);
++      titan_writel(0x00000002, UACFG);
++
++      titan_writel(0x0, UALCR);
++      titan_writel(0x0, UAIER);
++
++      /* Disable FIFOs */
++      titan_writel(0x00, UAFCR);
++
++      titan_writel(0x80, UALCR);
++      titan_writel(divisor & 0xff, UADLL);
++      titan_writel((divisor & 0xff00) >> 8, UADLH);
++      titan_writel(0x0, UALCR);
++
++      titan_writel(DATA_DBG | PARITY_DBG | STOP_DBG, UALCR);
++
++      /* Enable receiver interrupt */
++      titan_readl(UARBR);
++      titan_writel(0x1, UAIER);
++}
++
++int getDebugChar(void)
++{
++      while (!(titan_readl(UALSR) & 0x1));
++      return titan_readl(UARBR);
++}
++
++int putDebugChar(int data)
++{
++      while (!(titan_readl(UALSR) & 0x20));
++      titan_writel(data, UATHR);
++      return 1;
++}
++
++/* KGDB interrupt handler */
++asmlinkage void excite_kgdb_inthdl(void)
++{
++      if (unlikely(
++              ((titan_readl(UAIIR) & 0x7) == 4)
++              && ((titan_readl(UARBR) & 0xff) == 0x3)))
++                      set_async_breakpoint(&regs->cp0_epc);
++}
+diff -Nurb linux-2.6.22-590/arch/mips/basler/excite/excite_irq.c linux-2.6.22-570/arch/mips/basler/excite/excite_irq.c
+--- linux-2.6.22-590/arch/mips/basler/excite/excite_irq.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/basler/excite/excite_irq.c      2007-07-08 19:32:17.000000000 -0400
+@@ -50,6 +50,10 @@
+       mips_cpu_irq_init();
+       rm7k_cpu_irq_init();
+       rm9k_cpu_irq_init();
++
++#ifdef CONFIG_KGDB
++      excite_kgdb_init();
++#endif
+ }
+ asmlinkage void plat_irq_dispatch(void)
+@@ -86,6 +90,9 @@
+       msgint      = msgintflags & msgintmask & (0x1 << (TITAN_MSGINT % 0x20));
+       if ((pending & (1 << TITAN_IRQ)) && msgint) {
+               ocd_writel(msgint, INTP0Clear0 + (TITAN_MSGINT / 0x20 * 0x10));
++#if defined(CONFIG_KGDB)
++              excite_kgdb_inthdl();
++#endif
+               do_IRQ(TITAN_IRQ);
+               return;
+       }
+diff -Nurb linux-2.6.22-590/arch/mips/basler/excite/excite_setup.c linux-2.6.22-570/arch/mips/basler/excite/excite_setup.c
+--- linux-2.6.22-590/arch/mips/basler/excite/excite_setup.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/basler/excite/excite_setup.c    2007-07-08 19:32:17.000000000 -0400
+@@ -95,13 +95,13 @@
+       /* Take the DUART out of reset */
+       titan_writel(0x00ff1cff, CPRR);
+-#if (CONFIG_SERIAL_8250_NR_UARTS > 1)
++#if defined(CONFIG_KGDB) || (CONFIG_SERIAL_8250_NR_UARTS > 1)
+       /* Enable both ports */
+       titan_writel(MASK_SER0 | MASK_SER1, UACFG);
+ #else
+       /* Enable port #0 only */
+       titan_writel(MASK_SER0, UACFG);
+-#endif
++#endif        /* defined(CONFIG_KGDB) */
+       /*
+        * Set up serial port #0. Do not use autodetection; the result is
+diff -Nurb linux-2.6.22-590/arch/mips/ddb5xxx/ddb5477/Makefile linux-2.6.22-570/arch/mips/ddb5xxx/ddb5477/Makefile
+--- linux-2.6.22-590/arch/mips/ddb5xxx/ddb5477/Makefile        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/ddb5xxx/ddb5477/Makefile        2007-07-08 19:32:17.000000000 -0400
+@@ -5,3 +5,4 @@
+ obj-y                 += irq.o irq_5477.o setup.o lcd44780.o
+ obj-$(CONFIG_RUNTIME_DEBUG)   += debug.o
++obj-$(CONFIG_KGDB)            += kgdb_io.o
+diff -Nurb linux-2.6.22-590/arch/mips/ddb5xxx/ddb5477/kgdb_io.c linux-2.6.22-570/arch/mips/ddb5xxx/ddb5477/kgdb_io.c
+--- linux-2.6.22-590/arch/mips/ddb5xxx/ddb5477/kgdb_io.c       1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/ddb5xxx/ddb5477/kgdb_io.c       2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,136 @@
++/*
++ * kgdb io functions for DDB5477.  We use the second serial port (upper one).
++ *
++ * Copyright (C) 2001 MontaVista Software Inc.
++ * Author: jsun@mvista.com or jsun@junsun.net
++ *
++ * 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.
++ *
++ */
++
++/* ======================= CONFIG ======================== */
++
++/* [jsun] we use the second serial port for kdb */
++#define         BASE                    0xbfa04240
++#define         MAX_BAUD                115200
++
++/* distance in bytes between two serial registers */
++#define         REG_OFFSET              8
++
++/*
++ * 0 - kgdb does serial init
++ * 1 - kgdb skip serial init
++ */
++static int remoteDebugInitialized = 0;
++
++/*
++ * the default baud rate *if* kgdb does serial init
++ */
++#define               BAUD_DEFAULT            UART16550_BAUD_38400
++
++/* ======================= END OF CONFIG ======================== */
++
++typedef unsigned char uint8;
++typedef unsigned int uint32;
++
++#define         UART16550_BAUD_2400             2400
++#define         UART16550_BAUD_4800             4800
++#define         UART16550_BAUD_9600             9600
++#define         UART16550_BAUD_19200            19200
++#define         UART16550_BAUD_38400            38400
++#define         UART16550_BAUD_57600            57600
++#define         UART16550_BAUD_115200           115200
++
++#define         UART16550_PARITY_NONE           0
++#define         UART16550_PARITY_ODD            0x08
++#define         UART16550_PARITY_EVEN           0x18
++#define         UART16550_PARITY_MARK           0x28
++#define         UART16550_PARITY_SPACE          0x38
++
++#define         UART16550_DATA_5BIT             0x0
++#define         UART16550_DATA_6BIT             0x1
++#define         UART16550_DATA_7BIT             0x2
++#define         UART16550_DATA_8BIT             0x3
++
++#define         UART16550_STOP_1BIT             0x0
++#define         UART16550_STOP_2BIT             0x4
++
++/* register offset */
++#define         OFS_RCV_BUFFER          0
++#define         OFS_TRANS_HOLD          0
++#define         OFS_SEND_BUFFER         0
++#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
++#define         OFS_INTR_ID             (2*REG_OFFSET)
++#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
++#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
++#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
++#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
++#define         OFS_LINE_STATUS         (5*REG_OFFSET)
++#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
++#define         OFS_RS232_INPUT         (6*REG_OFFSET)
++#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
++
++#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
++#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
++
++
++/* memory-mapped read/write of the port */
++#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
++#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
++
++void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
++{
++        /* disable interrupts */
++        UART16550_WRITE(OFS_INTR_ENABLE, 0);
++
++        /* set up baud rate */
++        {
++                uint32 divisor;
++
++                /* set DIAB bit */
++                UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
++
++                /* set divisor */
++                divisor = MAX_BAUD / baud;
++                UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
++                UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
++
++                /* clear DIAB bit */
++                UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
++        }
++
++        /* set data format */
++        UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
++}
++
++
++uint8 getDebugChar(void)
++{
++        if (!remoteDebugInitialized) {
++                remoteDebugInitialized = 1;
++                debugInit(BAUD_DEFAULT,
++                          UART16550_DATA_8BIT,
++                          UART16550_PARITY_NONE, UART16550_STOP_1BIT);
++        }
++
++        while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
++        return UART16550_READ(OFS_RCV_BUFFER);
++}
++
++
++int putDebugChar(uint8 byte)
++{
++        if (!remoteDebugInitialized) {
++                remoteDebugInitialized = 1;
++                debugInit(BAUD_DEFAULT,
++                          UART16550_DATA_8BIT,
++                          UART16550_PARITY_NONE, UART16550_STOP_1BIT);
++        }
++
++        while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
++        UART16550_WRITE(OFS_SEND_BUFFER, byte);
++        return 1;
++}
+diff -Nurb linux-2.6.22-590/arch/mips/gt64120/momenco_ocelot/Makefile linux-2.6.22-570/arch/mips/gt64120/momenco_ocelot/Makefile
+--- linux-2.6.22-590/arch/mips/gt64120/momenco_ocelot/Makefile 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/gt64120/momenco_ocelot/Makefile 2007-07-08 19:32:17.000000000 -0400
+@@ -3,3 +3,5 @@
+ #
+ obj-y                 += irq.o prom.o reset.o setup.o
++
++obj-$(CONFIG_KGDB)    += dbg_io.o
+diff -Nurb linux-2.6.22-590/arch/mips/gt64120/momenco_ocelot/dbg_io.c linux-2.6.22-570/arch/mips/gt64120/momenco_ocelot/dbg_io.c
+--- linux-2.6.22-590/arch/mips/gt64120/momenco_ocelot/dbg_io.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/gt64120/momenco_ocelot/dbg_io.c 2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,121 @@
++
++#include <asm/serial.h> /* For the serial port location and base baud */
++
++/* --- CONFIG --- */
++
++typedef unsigned char uint8;
++typedef unsigned int uint32;
++
++/* --- END OF CONFIG --- */
++
++#define         UART16550_BAUD_2400             2400
++#define         UART16550_BAUD_4800             4800
++#define         UART16550_BAUD_9600             9600
++#define         UART16550_BAUD_19200            19200
++#define         UART16550_BAUD_38400            38400
++#define         UART16550_BAUD_57600            57600
++#define         UART16550_BAUD_115200           115200
++
++#define         UART16550_PARITY_NONE           0
++#define         UART16550_PARITY_ODD            0x08
++#define         UART16550_PARITY_EVEN           0x18
++#define         UART16550_PARITY_MARK           0x28
++#define         UART16550_PARITY_SPACE          0x38
++
++#define         UART16550_DATA_5BIT             0x0
++#define         UART16550_DATA_6BIT             0x1
++#define         UART16550_DATA_7BIT             0x2
++#define         UART16550_DATA_8BIT             0x3
++
++#define         UART16550_STOP_1BIT             0x0
++#define         UART16550_STOP_2BIT             0x4
++
++/* ----------------------------------------------------- */
++
++/* === CONFIG === */
++
++/* [jsun] we use the second serial port for kdb */
++#define         BASE                    OCELOT_SERIAL1_BASE
++#define         MAX_BAUD                OCELOT_BASE_BAUD
++
++/* === END OF CONFIG === */
++
++#define         REG_OFFSET              4
++
++/* register offset */
++#define         OFS_RCV_BUFFER          0
++#define         OFS_TRANS_HOLD          0
++#define         OFS_SEND_BUFFER         0
++#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
++#define         OFS_INTR_ID             (2*REG_OFFSET)
++#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
++#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
++#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
++#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
++#define         OFS_LINE_STATUS         (5*REG_OFFSET)
++#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
++#define         OFS_RS232_INPUT         (6*REG_OFFSET)
++#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
++
++#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
++#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
++
++
++/* memory-mapped read/write of the port */
++#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
++#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
++
++void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
++{
++      /* disable interrupts */
++      UART16550_WRITE(OFS_INTR_ENABLE, 0);
++
++      /* set up baud rate */
++      {
++              uint32 divisor;
++
++              /* set DIAB bit */
++              UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
++
++              /* set divisor */
++              divisor = MAX_BAUD / baud;
++              UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
++              UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
++
++              /* clear DIAB bit */
++              UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
++      }
++
++      /* set data format */
++      UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
++}
++
++static int remoteDebugInitialized = 0;
++
++uint8 getDebugChar(void)
++{
++      if (!remoteDebugInitialized) {
++              remoteDebugInitialized = 1;
++              debugInit(UART16550_BAUD_38400,
++                        UART16550_DATA_8BIT,
++                        UART16550_PARITY_NONE, UART16550_STOP_1BIT);
++      }
++
++      while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
++      return UART16550_READ(OFS_RCV_BUFFER);
++}
++
++
++int putDebugChar(uint8 byte)
++{
++      if (!remoteDebugInitialized) {
++              remoteDebugInitialized = 1;
++              debugInit(UART16550_BAUD_38400,
++                        UART16550_DATA_8BIT,
++                        UART16550_PARITY_NONE, UART16550_STOP_1BIT);
++      }
++
++      while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
++      UART16550_WRITE(OFS_SEND_BUFFER, byte);
++      return 1;
++}
+diff -Nurb linux-2.6.22-590/arch/mips/jmr3927/rbhma3100/Makefile linux-2.6.22-570/arch/mips/jmr3927/rbhma3100/Makefile
+--- linux-2.6.22-590/arch/mips/jmr3927/rbhma3100/Makefile      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/jmr3927/rbhma3100/Makefile      2007-07-08 19:32:17.000000000 -0400
+@@ -3,3 +3,4 @@
+ #
+ obj-y                         += init.o irq.o setup.o
++obj-$(CONFIG_KGDB)            += kgdb_io.o
+diff -Nurb linux-2.6.22-590/arch/mips/jmr3927/rbhma3100/kgdb_io.c linux-2.6.22-570/arch/mips/jmr3927/rbhma3100/kgdb_io.c
+--- linux-2.6.22-590/arch/mips/jmr3927/rbhma3100/kgdb_io.c     1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/jmr3927/rbhma3100/kgdb_io.c     2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,105 @@
++/*
++ * BRIEF MODULE DESCRIPTION
++ *    Low level uart routines to directly access a TX[34]927 SIO.
++ *
++ * Copyright 2001 MontaVista Software Inc.
++ * Author: MontaVista Software, Inc.
++ *            ahennessy@mvista.com or source@mvista.com
++ *
++ * Based on arch/mips/ddb5xxx/ddb5477/kgdb_io.c
++ *
++ * Copyright (C) 2000-2001 Toshiba Corporation
++ *
++ *  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.
++ */
++
++#include <asm/jmr3927/jmr3927.h>
++
++#define TIMEOUT       0xffffff
++
++static int remoteDebugInitialized = 0;
++static void debugInit(int baud);
++
++int putDebugChar(unsigned char c)
++{
++        int i = 0;
++
++      if (!remoteDebugInitialized) {
++              remoteDebugInitialized = 1;
++              debugInit(38400);
++      }
++
++        do {
++            slow_down();
++            i++;
++            if (i>TIMEOUT) {
++                break;
++            }
++        } while (!(tx3927_sioptr(0)->cisr & TXx927_SICISR_TXALS));
++      tx3927_sioptr(0)->tfifo = c;
++
++      return 1;
++}
++
++unsigned char getDebugChar(void)
++{
++        int i = 0;
++      int dicr;
++      char c;
++
++      if (!remoteDebugInitialized) {
++              remoteDebugInitialized = 1;
++              debugInit(38400);
++      }
++
++      /* diable RX int. */
++      dicr = tx3927_sioptr(0)->dicr;
++      tx3927_sioptr(0)->dicr = 0;
++
++        do {
++            slow_down();
++            i++;
++            if (i>TIMEOUT) {
++                break;
++            }
++        } while (tx3927_sioptr(0)->disr & TXx927_SIDISR_UVALID)
++              ;
++      c = tx3927_sioptr(0)->rfifo;
++
++      /* clear RX int. status */
++      tx3927_sioptr(0)->disr &= ~TXx927_SIDISR_RDIS;
++      /* enable RX int. */
++      tx3927_sioptr(0)->dicr = dicr;
++
++      return c;
++}
++
++static void debugInit(int baud)
++{
++      tx3927_sioptr(0)->lcr = 0x020;
++      tx3927_sioptr(0)->dicr = 0;
++      tx3927_sioptr(0)->disr = 0x4100;
++      tx3927_sioptr(0)->cisr = 0x014;
++      tx3927_sioptr(0)->fcr = 0;
++      tx3927_sioptr(0)->flcr = 0x02;
++      tx3927_sioptr(0)->bgr = ((JMR3927_BASE_BAUD + baud / 2) / baud) |
++              TXx927_SIBGR_BCLK_T0;
++}
+diff -Nurb linux-2.6.22-590/arch/mips/kernel/Makefile linux-2.6.22-570/arch/mips/kernel/Makefile
+--- linux-2.6.22-590/arch/mips/kernel/Makefile 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/kernel/Makefile 2007-07-08 19:32:17.000000000 -0400
+@@ -57,8 +57,7 @@
+ obj-$(CONFIG_MIPS32_N32)      += binfmt_elfn32.o scall64-n32.o signal_n32.o
+ obj-$(CONFIG_MIPS32_O32)      += binfmt_elfo32.o scall64-o32.o
+-obj-$(CONFIG_KGDB)            += kgdb_handler.o kgdb.o kgdb-jmp.o     \
+-                                      kgdb-setjmp.o
++obj-$(CONFIG_KGDB)            += gdb-low.o gdb-stub.o
+ obj-$(CONFIG_PROC_FS)         += proc.o
+ obj-$(CONFIG_64BIT)           += cpu-bugs64.o
+diff -Nurb linux-2.6.22-590/arch/mips/kernel/cpu-probe.c linux-2.6.22-570/arch/mips/kernel/cpu-probe.c
+--- linux-2.6.22-590/arch/mips/kernel/cpu-probe.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/kernel/cpu-probe.c      2007-07-08 19:32:17.000000000 -0400
+@@ -177,17 +177,6 @@
+               cpu_wait = r4k_wait;
+               break;
+-      case CPU_20KC:
+-              /*
+-               * WAIT on Rev1.0 has E1, E2, E3 and E16.
+-               * WAIT on Rev2.0 and Rev3.0 has E16.
+-               * Rev3.1 WAIT is nop, why bother
+-               */
+-              if ((c->processor_id & 0xff) <= 0x64)
+-                      break;
 -
--    MOVE SCRATCH0 + dsa_dataout TO SCRATCH0   
+-              cpu_wait = r4k_wait;
+-              break;
+       case CPU_RM9000:
+               if ((c->processor_id & 0x00ff) >= 0x40)
+                       cpu_wait = r4k_wait;
+diff -Nurb linux-2.6.22-590/arch/mips/kernel/gdb-low.S linux-2.6.22-570/arch/mips/kernel/gdb-low.S
+--- linux-2.6.22-590/arch/mips/kernel/gdb-low.S        1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/kernel/gdb-low.S        2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,394 @@
++/*
++ * gdb-low.S contains the low-level trap handler for the GDB stub.
++ *
++ * Copyright (C) 1995 Andreas Busse
++ */
++#include <linux/sys.h>
++
++#include <asm/asm.h>
++#include <asm/errno.h>
++#include <asm/irqflags.h>
++#include <asm/mipsregs.h>
++#include <asm/regdef.h>
++#include <asm/stackframe.h>
++#include <asm/gdb-stub.h>
++
++#ifdef CONFIG_32BIT
++#define DMFC0 mfc0
++#define DMTC0 mtc0
++#define LDC1  lwc1
++#define SDC1  lwc1
++#endif
++#ifdef CONFIG_64BIT
++#define DMFC0 dmfc0
++#define DMTC0 dmtc0
++#define LDC1  ldc1
++#define SDC1  ldc1
++#endif
++
++/*
++ * [jsun] We reserves about 2x GDB_FR_SIZE in stack.  The lower (addressed)
++ * part is used to store registers and passed to exception handler.
++ * The upper part is reserved for "call func" feature where gdb client
++ * saves some of the regs, setups call frame and passes args.
++ *
++ * A trace shows about 200 bytes are used to store about half of all regs.
++ * The rest should be big enough for frame setup and passing args.
++ */
++
++/*
++ * The low level trap handler
++ */
++              .align  5
++              NESTED(trap_low, GDB_FR_SIZE, sp)
++              .set    noat
++              .set    noreorder
++
++              mfc0    k0, CP0_STATUS
++              sll     k0, 3                   /* extract cu0 bit */
++              bltz    k0, 1f
++              move    k1, sp
++
++              /*
++               * Called from user mode, go somewhere else.
++               */
++              mfc0    k0, CP0_CAUSE
++              andi    k0, k0, 0x7c
++#ifdef CONFIG_64BIT
++              dsll    k0, k0, 1
++#endif
++              PTR_L   k1, saved_vectors(k0)
++              jr      k1
++              nop
++1:
++              move    k0, sp
++              PTR_SUBU sp, k1, GDB_FR_SIZE*2  # see comment above
++              LONG_S  k0, GDB_FR_REG29(sp)
++              LONG_S  $2, GDB_FR_REG2(sp)
++
++/*
++ * First save the CP0 and special registers
++ */
++
++              mfc0    v0, CP0_STATUS
++              LONG_S  v0, GDB_FR_STATUS(sp)
++              mfc0    v0, CP0_CAUSE
++              LONG_S  v0, GDB_FR_CAUSE(sp)
++              DMFC0   v0, CP0_EPC
++              LONG_S  v0, GDB_FR_EPC(sp)
++              DMFC0   v0, CP0_BADVADDR
++              LONG_S  v0, GDB_FR_BADVADDR(sp)
++              mfhi    v0
++              LONG_S  v0, GDB_FR_HI(sp)
++              mflo    v0
++              LONG_S  v0, GDB_FR_LO(sp)
++
++/*
++ * Now the integer registers
++ */
++
++              LONG_S  zero, GDB_FR_REG0(sp)           /* I know... */
++              LONG_S  $1, GDB_FR_REG1(sp)
++              /* v0 already saved */
++              LONG_S  $3, GDB_FR_REG3(sp)
++              LONG_S  $4, GDB_FR_REG4(sp)
++              LONG_S  $5, GDB_FR_REG5(sp)
++              LONG_S  $6, GDB_FR_REG6(sp)
++              LONG_S  $7, GDB_FR_REG7(sp)
++              LONG_S  $8, GDB_FR_REG8(sp)
++              LONG_S  $9, GDB_FR_REG9(sp)
++              LONG_S  $10, GDB_FR_REG10(sp)
++              LONG_S  $11, GDB_FR_REG11(sp)
++              LONG_S  $12, GDB_FR_REG12(sp)
++              LONG_S  $13, GDB_FR_REG13(sp)
++              LONG_S  $14, GDB_FR_REG14(sp)
++              LONG_S  $15, GDB_FR_REG15(sp)
++              LONG_S  $16, GDB_FR_REG16(sp)
++              LONG_S  $17, GDB_FR_REG17(sp)
++              LONG_S  $18, GDB_FR_REG18(sp)
++              LONG_S  $19, GDB_FR_REG19(sp)
++              LONG_S  $20, GDB_FR_REG20(sp)
++              LONG_S  $21, GDB_FR_REG21(sp)
++              LONG_S  $22, GDB_FR_REG22(sp)
++              LONG_S  $23, GDB_FR_REG23(sp)
++              LONG_S  $24, GDB_FR_REG24(sp)
++              LONG_S  $25, GDB_FR_REG25(sp)
++              LONG_S  $26, GDB_FR_REG26(sp)
++              LONG_S  $27, GDB_FR_REG27(sp)
++              LONG_S  $28, GDB_FR_REG28(sp)
++              /* sp already saved */
++              LONG_S  $30, GDB_FR_REG30(sp)
++              LONG_S  $31, GDB_FR_REG31(sp)
++
++              CLI                             /* disable interrupts */
++              TRACE_IRQS_OFF
++
++/*
++ * Followed by the floating point registers
++ */
++              mfc0    v0, CP0_STATUS          /* FPU enabled? */
++              srl     v0, v0, 16
++              andi    v0, v0, (ST0_CU1 >> 16)
++
++              beqz    v0,2f                   /* disabled, skip */
++               nop
++
++              SDC1    $0, GDB_FR_FPR0(sp)
++              SDC1    $1, GDB_FR_FPR1(sp)
++              SDC1    $2, GDB_FR_FPR2(sp)
++              SDC1    $3, GDB_FR_FPR3(sp)
++              SDC1    $4, GDB_FR_FPR4(sp)
++              SDC1    $5, GDB_FR_FPR5(sp)
++              SDC1    $6, GDB_FR_FPR6(sp)
++              SDC1    $7, GDB_FR_FPR7(sp)
++              SDC1    $8, GDB_FR_FPR8(sp)
++              SDC1    $9, GDB_FR_FPR9(sp)
++              SDC1    $10, GDB_FR_FPR10(sp)
++              SDC1    $11, GDB_FR_FPR11(sp)
++              SDC1    $12, GDB_FR_FPR12(sp)
++              SDC1    $13, GDB_FR_FPR13(sp)
++              SDC1    $14, GDB_FR_FPR14(sp)
++              SDC1    $15, GDB_FR_FPR15(sp)
++              SDC1    $16, GDB_FR_FPR16(sp)
++              SDC1    $17, GDB_FR_FPR17(sp)
++              SDC1    $18, GDB_FR_FPR18(sp)
++              SDC1    $19, GDB_FR_FPR19(sp)
++              SDC1    $20, GDB_FR_FPR20(sp)
++              SDC1    $21, GDB_FR_FPR21(sp)
++              SDC1    $22, GDB_FR_FPR22(sp)
++              SDC1    $23, GDB_FR_FPR23(sp)
++              SDC1    $24, GDB_FR_FPR24(sp)
++              SDC1    $25, GDB_FR_FPR25(sp)
++              SDC1    $26, GDB_FR_FPR26(sp)
++              SDC1    $27, GDB_FR_FPR27(sp)
++              SDC1    $28, GDB_FR_FPR28(sp)
++              SDC1    $29, GDB_FR_FPR29(sp)
++              SDC1    $30, GDB_FR_FPR30(sp)
++              SDC1    $31, GDB_FR_FPR31(sp)
++
++/*
++ * FPU control registers
++ */
++
++              cfc1    v0, CP1_STATUS
++              LONG_S  v0, GDB_FR_FSR(sp)
++              cfc1    v0, CP1_REVISION
++              LONG_S  v0, GDB_FR_FIR(sp)
++
++/*
++ * Current stack frame ptr
++ */
++
++2:
++              LONG_S  sp, GDB_FR_FRP(sp)
++
++/*
++ * CP0 registers (R4000/R4400 unused registers skipped)
++ */
++
++              mfc0    v0, CP0_INDEX
++              LONG_S  v0, GDB_FR_CP0_INDEX(sp)
++              mfc0    v0, CP0_RANDOM
++              LONG_S  v0, GDB_FR_CP0_RANDOM(sp)
++              DMFC0   v0, CP0_ENTRYLO0
++              LONG_S  v0, GDB_FR_CP0_ENTRYLO0(sp)
++              DMFC0   v0, CP0_ENTRYLO1
++              LONG_S  v0, GDB_FR_CP0_ENTRYLO1(sp)
++              DMFC0   v0, CP0_CONTEXT
++              LONG_S  v0, GDB_FR_CP0_CONTEXT(sp)
++              mfc0    v0, CP0_PAGEMASK
++              LONG_S  v0, GDB_FR_CP0_PAGEMASK(sp)
++              mfc0    v0, CP0_WIRED
++              LONG_S  v0, GDB_FR_CP0_WIRED(sp)
++              DMFC0   v0, CP0_ENTRYHI
++              LONG_S  v0, GDB_FR_CP0_ENTRYHI(sp)
++              mfc0    v0, CP0_PRID
++              LONG_S  v0, GDB_FR_CP0_PRID(sp)
++
++              .set    at
++
++/*
++ * Continue with the higher level handler
++ */
++
++              move    a0,sp
++
++              jal     handle_exception
++               nop
++
++/*
++ * Restore all writable registers, in reverse order
++ */
++
++              .set    noat
++
++              LONG_L  v0, GDB_FR_CP0_ENTRYHI(sp)
++              LONG_L  v1, GDB_FR_CP0_WIRED(sp)
++              DMTC0   v0, CP0_ENTRYHI
++              mtc0    v1, CP0_WIRED
++              LONG_L  v0, GDB_FR_CP0_PAGEMASK(sp)
++              LONG_L  v1, GDB_FR_CP0_ENTRYLO1(sp)
++              mtc0    v0, CP0_PAGEMASK
++              DMTC0   v1, CP0_ENTRYLO1
++              LONG_L  v0, GDB_FR_CP0_ENTRYLO0(sp)
++              LONG_L  v1, GDB_FR_CP0_INDEX(sp)
++              DMTC0   v0, CP0_ENTRYLO0
++              LONG_L  v0, GDB_FR_CP0_CONTEXT(sp)
++              mtc0    v1, CP0_INDEX
++              DMTC0   v0, CP0_CONTEXT
++
++
++/*
++ * Next, the floating point registers
++ */
++              mfc0    v0, CP0_STATUS          /* check if the FPU is enabled */
++              srl     v0, v0, 16
++              andi    v0, v0, (ST0_CU1 >> 16)
++
++              beqz    v0, 3f                  /* disabled, skip */
++               nop
++
++              LDC1    $31, GDB_FR_FPR31(sp)
++              LDC1    $30, GDB_FR_FPR30(sp)
++              LDC1    $29, GDB_FR_FPR29(sp)
++              LDC1    $28, GDB_FR_FPR28(sp)
++              LDC1    $27, GDB_FR_FPR27(sp)
++              LDC1    $26, GDB_FR_FPR26(sp)
++              LDC1    $25, GDB_FR_FPR25(sp)
++              LDC1    $24, GDB_FR_FPR24(sp)
++              LDC1    $23, GDB_FR_FPR23(sp)
++              LDC1    $22, GDB_FR_FPR22(sp)
++              LDC1    $21, GDB_FR_FPR21(sp)
++              LDC1    $20, GDB_FR_FPR20(sp)
++              LDC1    $19, GDB_FR_FPR19(sp)
++              LDC1    $18, GDB_FR_FPR18(sp)
++              LDC1    $17, GDB_FR_FPR17(sp)
++              LDC1    $16, GDB_FR_FPR16(sp)
++              LDC1    $15, GDB_FR_FPR15(sp)
++              LDC1    $14, GDB_FR_FPR14(sp)
++              LDC1    $13, GDB_FR_FPR13(sp)
++              LDC1    $12, GDB_FR_FPR12(sp)
++              LDC1    $11, GDB_FR_FPR11(sp)
++              LDC1    $10, GDB_FR_FPR10(sp)
++              LDC1    $9, GDB_FR_FPR9(sp)
++              LDC1    $8, GDB_FR_FPR8(sp)
++              LDC1    $7, GDB_FR_FPR7(sp)
++              LDC1    $6, GDB_FR_FPR6(sp)
++              LDC1    $5, GDB_FR_FPR5(sp)
++              LDC1    $4, GDB_FR_FPR4(sp)
++              LDC1    $3, GDB_FR_FPR3(sp)
++              LDC1    $2, GDB_FR_FPR2(sp)
++              LDC1    $1, GDB_FR_FPR1(sp)
++              LDC1    $0, GDB_FR_FPR0(sp)
++
++/*
++ * Now the CP0 and integer registers
++ */
++
++3:
++#ifdef CONFIG_MIPS_MT_SMTC
++              /* Read-modify write of Status must be atomic */
++              mfc0    t2, CP0_TCSTATUS
++              ori     t1, t2, TCSTATUS_IXMT
++              mtc0    t1, CP0_TCSTATUS
++              andi    t2, t2, TCSTATUS_IXMT
++              _ehb
++              DMT     9                               # dmt   t1
++              jal     mips_ihb
++              nop
++#endif /* CONFIG_MIPS_MT_SMTC */
++              mfc0    t0, CP0_STATUS
++              ori     t0, 0x1f
++              xori    t0, 0x1f
++              mtc0    t0, CP0_STATUS
++#ifdef CONFIG_MIPS_MT_SMTC
++              andi    t1, t1, VPECONTROL_TE
++              beqz    t1, 9f
++              nop
++              EMT                                     # emt
++9:
++              mfc0    t1, CP0_TCSTATUS
++              xori    t1, t1, TCSTATUS_IXMT
++              or      t1, t1, t2
++              mtc0    t1, CP0_TCSTATUS
++              _ehb
++#endif /* CONFIG_MIPS_MT_SMTC */
++              LONG_L  v0, GDB_FR_STATUS(sp)
++              LONG_L  v1, GDB_FR_EPC(sp)
++              mtc0    v0, CP0_STATUS
++              DMTC0   v1, CP0_EPC
++              LONG_L  v0, GDB_FR_HI(sp)
++              LONG_L  v1, GDB_FR_LO(sp)
++              mthi    v0
++              mtlo    v1
++              LONG_L  $31, GDB_FR_REG31(sp)
++              LONG_L  $30, GDB_FR_REG30(sp)
++              LONG_L  $28, GDB_FR_REG28(sp)
++              LONG_L  $27, GDB_FR_REG27(sp)
++              LONG_L  $26, GDB_FR_REG26(sp)
++              LONG_L  $25, GDB_FR_REG25(sp)
++              LONG_L  $24, GDB_FR_REG24(sp)
++              LONG_L  $23, GDB_FR_REG23(sp)
++              LONG_L  $22, GDB_FR_REG22(sp)
++              LONG_L  $21, GDB_FR_REG21(sp)
++              LONG_L  $20, GDB_FR_REG20(sp)
++              LONG_L  $19, GDB_FR_REG19(sp)
++              LONG_L  $18, GDB_FR_REG18(sp)
++              LONG_L  $17, GDB_FR_REG17(sp)
++              LONG_L  $16, GDB_FR_REG16(sp)
++              LONG_L  $15, GDB_FR_REG15(sp)
++              LONG_L  $14, GDB_FR_REG14(sp)
++              LONG_L  $13, GDB_FR_REG13(sp)
++              LONG_L  $12, GDB_FR_REG12(sp)
++              LONG_L  $11, GDB_FR_REG11(sp)
++              LONG_L  $10, GDB_FR_REG10(sp)
++              LONG_L  $9, GDB_FR_REG9(sp)
++              LONG_L  $8, GDB_FR_REG8(sp)
++              LONG_L  $7, GDB_FR_REG7(sp)
++              LONG_L  $6, GDB_FR_REG6(sp)
++              LONG_L  $5, GDB_FR_REG5(sp)
++              LONG_L  $4, GDB_FR_REG4(sp)
++              LONG_L  $3, GDB_FR_REG3(sp)
++              LONG_L  $2, GDB_FR_REG2(sp)
++              LONG_L  $1, GDB_FR_REG1(sp)
++#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
++              LONG_L  k0, GDB_FR_EPC(sp)
++              LONG_L  $29, GDB_FR_REG29(sp)           /* Deallocate stack */
++              jr      k0
++              rfe
++#else
++              LONG_L  sp, GDB_FR_REG29(sp)            /* Deallocate stack */
++
++              .set    mips3
++              eret
++              .set    mips0
++#endif
++              .set    at
++              .set    reorder
++              END(trap_low)
++
++LEAF(kgdb_read_byte)
++4:            lb      t0, (a0)
++              sb      t0, (a1)
++              li      v0, 0
++              jr      ra
++              .section __ex_table,"a"
++              PTR     4b, kgdbfault
++              .previous
++              END(kgdb_read_byte)
++
++LEAF(kgdb_write_byte)
++5:            sb      a0, (a1)
++              li      v0, 0
++              jr      ra
++              .section __ex_table,"a"
++              PTR     5b, kgdbfault
++              .previous
++              END(kgdb_write_byte)
++
++              .type   kgdbfault@function
++              .ent    kgdbfault
++
++kgdbfault:    li      v0, -EFAULT
++              jr      ra
++              .end    kgdbfault
+diff -Nurb linux-2.6.22-590/arch/mips/kernel/gdb-stub.c linux-2.6.22-570/arch/mips/kernel/gdb-stub.c
+--- linux-2.6.22-590/arch/mips/kernel/gdb-stub.c       1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/kernel/gdb-stub.c       2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,1154 @@
++/*
++ *  arch/mips/kernel/gdb-stub.c
++ *
++ *  Originally written by Glenn Engel, Lake Stevens Instrument Division
++ *
++ *  Contributed by HP Systems
++ *
++ *  Modified for SPARC by Stu Grossman, Cygnus Support.
++ *
++ *  Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
++ *  Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
++ *
++ *  Copyright (C) 1995 Andreas Busse
++ *
++ *  Copyright (C) 2003 MontaVista Software Inc.
++ *  Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
++ */
++
++/*
++ *  To enable debugger support, two things need to happen.  One, a
++ *  call to set_debug_traps() is necessary in order to allow any breakpoints
++ *  or error conditions to be properly intercepted and reported to gdb.
++ *  Two, a breakpoint needs to be generated to begin communication.  This
++ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
++ *  simulates a breakpoint by executing a BREAK instruction.
++ *
++ *
++ *    The following gdb commands are supported:
++ *
++ * command          function                               Return value
++ *
++ *    g             return the value of the CPU registers  hex data or ENN
++ *    G             set the value of the CPU registers     OK or ENN
++ *
++ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
++ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
++ *
++ *    c             Resume at current address              SNN   ( signal NN)
++ *    cAA..AA       Continue at address AA..AA             SNN
++ *
++ *    s             Step one instruction                   SNN
++ *    sAA..AA       Step one instruction from AA..AA       SNN
++ *
++ *    k             kill
++ *
++ *    ?             What was the last sigval ?             SNN   (signal NN)
++ *
++ *    bBB..BB     Set baud rate to BB..BB                OK or BNN, then sets
++ *                                                       baud rate
++ *
++ * All commands and responses are sent with a packet which includes a
++ * checksum.  A packet consists of
++ *
++ * $<packet info>#<checksum>.
++ *
++ * where
++ * <packet info> :: <characters representing the command or response>
++ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
++ *
++ * When a packet is received, it is first acknowledged with either '+' or '-'.
++ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
++ *
++ * Example:
++ *
++ * Host:                  Reply:
++ * $m0,10#2a               +$00010203040506070809101112131415#42
++ *
++ *
++ *  ==============
++ *  MORE EXAMPLES:
++ *  ==============
++ *
++ *  For reference -- the following are the steps that one
++ *  company took (RidgeRun Inc) to get remote gdb debugging
++ *  going. In this scenario the host machine was a PC and the
++ *  target platform was a Galileo EVB64120A MIPS evaluation
++ *  board.
++ *
++ *  Step 1:
++ *  First download gdb-5.0.tar.gz from the internet.
++ *  and then build/install the package.
++ *
++ *  Example:
++ *    $ tar zxf gdb-5.0.tar.gz
++ *    $ cd gdb-5.0
++ *    $ ./configure --target=mips-linux-elf
++ *    $ make
++ *    $ install
++ *    $ which mips-linux-elf-gdb
++ *    /usr/local/bin/mips-linux-elf-gdb
++ *
++ *  Step 2:
++ *  Configure linux for remote debugging and build it.
++ *
++ *  Example:
++ *    $ cd ~/linux
++ *    $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
++ *    $ make
++ *
++ *  Step 3:
++ *  Download the kernel to the remote target and start
++ *  the kernel running. It will promptly halt and wait
++ *  for the host gdb session to connect. It does this
++ *  since the "Kernel Hacking" option has defined
++ *  CONFIG_KGDB which in turn enables your calls
++ *  to:
++ *     set_debug_traps();
++ *     breakpoint();
++ *
++ *  Step 4:
++ *  Start the gdb session on the host.
++ *
++ *  Example:
++ *    $ mips-linux-elf-gdb vmlinux
++ *    (gdb) set remotebaud 115200
++ *    (gdb) target remote /dev/ttyS1
++ *    ...at this point you are connected to
++ *       the remote target and can use gdb
++ *       in the normal fasion. Setting
++ *       breakpoints, single stepping,
++ *       printing variables, etc.
++ */
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/console.h>
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/reboot.h>
++
++#include <asm/asm.h>
++#include <asm/cacheflush.h>
++#include <asm/mipsregs.h>
++#include <asm/pgtable.h>
++#include <asm/system.h>
++#include <asm/gdb-stub.h>
++#include <asm/inst.h>
++#include <asm/smp.h>
++
++/*
++ * external low-level support routines
++ */
++
++extern int putDebugChar(char c);    /* write a single character      */
++extern char getDebugChar(void);     /* read and return a single char */
++extern void trap_low(void);
++
++/*
++ * breakpoint and test functions
++ */
++extern void breakpoint(void);
++extern void breakinst(void);
++extern void async_breakpoint(void);
++extern void async_breakinst(void);
++extern void adel(void);
++
++/*
++ * local prototypes
++ */
++
++static void getpacket(char *buffer);
++static void putpacket(char *buffer);
++static int computeSignal(int tt);
++static int hex(unsigned char ch);
++static int hexToInt(char **ptr, int *intValue);
++static int hexToLong(char **ptr, long *longValue);
++static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
++void handle_exception(struct gdb_regs *regs);
++
++int kgdb_enabled;
++
++/*
++ * spin locks for smp case
++ */
++static DEFINE_SPINLOCK(kgdb_lock);
++static raw_spinlock_t kgdb_cpulock[NR_CPUS] = {
++      [0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED,
++};
++
++/*
++ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
++ * at least NUMREGBYTES*2 are needed for register packets
++ */
++#define BUFMAX 2048
++
++static char input_buffer[BUFMAX];
++static char output_buffer[BUFMAX];
++static int initialized;       /* !0 means we've been initialized */
++static int kgdb_started;
++static const char hexchars[]="0123456789abcdef";
++
++/* Used to prevent crashes in memory access.  Note that they'll crash anyway if
++   we haven't set up fault handlers yet... */
++int kgdb_read_byte(unsigned char *address, unsigned char *dest);
++int kgdb_write_byte(unsigned char val, unsigned char *dest);
++
++/*
++ * Convert ch from a hex digit to an int
++ */
++static int hex(unsigned char ch)
++{
++      if (ch >= 'a' && ch <= 'f')
++              return ch-'a'+10;
++      if (ch >= '0' && ch <= '9')
++              return ch-'0';
++      if (ch >= 'A' && ch <= 'F')
++              return ch-'A'+10;
++      return -1;
++}
++
++/*
++ * scan for the sequence $<data>#<checksum>
++ */
++static void getpacket(char *buffer)
++{
++      unsigned char checksum;
++      unsigned char xmitcsum;
++      int i;
++      int count;
++      unsigned char ch;
++
++      do {
++              /*
++               * wait around for the start character,
++               * ignore all other characters
++               */
++              while ((ch = (getDebugChar() & 0x7f)) != '$') ;
++
++              checksum = 0;
++              xmitcsum = -1;
++              count = 0;
++
++              /*
++               * now, read until a # or end of buffer is found
++               */
++              while (count < BUFMAX) {
++                      ch = getDebugChar();
++                      if (ch == '#')
++                              break;
++                      checksum = checksum + ch;
++                      buffer[count] = ch;
++                      count = count + 1;
++              }
++
++              if (count >= BUFMAX)
++                      continue;
++
++              buffer[count] = 0;
++
++              if (ch == '#') {
++                      xmitcsum = hex(getDebugChar() & 0x7f) << 4;
++                      xmitcsum |= hex(getDebugChar() & 0x7f);
++
++                      if (checksum != xmitcsum)
++                              putDebugChar('-');      /* failed checksum */
++                      else {
++                              putDebugChar('+'); /* successful transfer */
++
++                              /*
++                               * if a sequence char is present,
++                               * reply the sequence ID
++                               */
++                              if (buffer[2] == ':') {
++                                      putDebugChar(buffer[0]);
++                                      putDebugChar(buffer[1]);
++
++                                      /*
++                                       * remove sequence chars from buffer
++                                       */
++                                      count = strlen(buffer);
++                                      for (i=3; i <= count; i++)
++                                              buffer[i-3] = buffer[i];
++                              }
++                      }
++              }
++      }
++      while (checksum != xmitcsum);
++}
++
++/*
++ * send the packet in buffer.
++ */
++static void putpacket(char *buffer)
++{
++      unsigned char checksum;
++      int count;
++      unsigned char ch;
++
++      /*
++       * $<packet info>#<checksum>.
++       */
++
++      do {
++              putDebugChar('$');
++              checksum = 0;
++              count = 0;
++
++              while ((ch = buffer[count]) != 0) {
++                      if (!(putDebugChar(ch)))
++                              return;
++                      checksum += ch;
++                      count += 1;
++              }
++
++              putDebugChar('#');
++              putDebugChar(hexchars[checksum >> 4]);
++              putDebugChar(hexchars[checksum & 0xf]);
++
++      }
++      while ((getDebugChar() & 0x7f) != '+');
++}
++
++
++/*
++ * Convert the memory pointed to by mem into hex, placing result in buf.
++ * Return a pointer to the last char put in buf (null), in case of mem fault,
++ * return 0.
++ * may_fault is non-zero if we are reading from arbitrary memory, but is currently
++ * not used.
++ */
++static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
++{
++      unsigned char ch;
++
++      while (count-- > 0) {
++              if (kgdb_read_byte(mem++, &ch) != 0)
++                      return 0;
++              *buf++ = hexchars[ch >> 4];
++              *buf++ = hexchars[ch & 0xf];
++      }
++
++      *buf = 0;
++
++      return buf;
++}
++
++/*
++ * convert the hex array pointed to by buf into binary to be placed in mem
++ * return a pointer to the character AFTER the last byte written
++ * may_fault is non-zero if we are reading from arbitrary memory, but is currently
++ * not used.
++ */
++static char *hex2mem(char *buf, char *mem, int count, int binary, int may_fault)
++{
++      int i;
++      unsigned char ch;
++
++      for (i=0; i<count; i++)
++      {
++              if (binary) {
++                      ch = *buf++;
++                      if (ch == 0x7d)
++                              ch = 0x20 ^ *buf++;
++              }
++              else {
++                      ch = hex(*buf++) << 4;
++                      ch |= hex(*buf++);
++              }
++              if (kgdb_write_byte(ch, mem++) != 0)
++                      return 0;
++      }
++
++      return mem;
++}
++
++/*
++ * This table contains the mapping between SPARC hardware trap types, and
++ * signals, which are primarily what GDB understands.  It also indicates
++ * which hardware traps we need to commandeer when initializing the stub.
++ */
++static struct hard_trap_info {
++      unsigned char tt;               /* Trap type code for MIPS R3xxx and R4xxx */
++      unsigned char signo;            /* Signal that we map this trap into */
++} hard_trap_info[] = {
++      { 6, SIGBUS },                  /* instruction bus error */
++      { 7, SIGBUS },                  /* data bus error */
++      { 9, SIGTRAP },                 /* break */
++      { 10, SIGILL },                 /* reserved instruction */
++/*    { 11, SIGILL },         */      /* CPU unusable */
++      { 12, SIGFPE },                 /* overflow */
++      { 13, SIGTRAP },                /* trap */
++      { 14, SIGSEGV },                /* virtual instruction cache coherency */
++      { 15, SIGFPE },                 /* floating point exception */
++      { 23, SIGSEGV },                /* watch */
++      { 31, SIGSEGV },                /* virtual data cache coherency */
++      { 0, 0}                         /* Must be last */
++};
++
++/* Save the normal trap handlers for user-mode traps. */
++void *saved_vectors[32];
++
++/*
++ * Set up exception handlers for tracing and breakpoints
++ */
++void set_debug_traps(void)
++{
++      struct hard_trap_info *ht;
++      unsigned long flags;
++      unsigned char c;
++
++      local_irq_save(flags);
++      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
++              saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low);
++
++      putDebugChar('+'); /* 'hello world' */
++      /*
++       * In case GDB is started before us, ack any packets
++       * (presumably "$?#xx") sitting there.
++       */
++      while((c = getDebugChar()) != '$');
++      while((c = getDebugChar()) != '#');
++      c = getDebugChar(); /* eat first csum byte */
++      c = getDebugChar(); /* eat second csum byte */
++      putDebugChar('+'); /* ack it */
++
++      initialized = 1;
++      local_irq_restore(flags);
++}
++
++void restore_debug_traps(void)
++{
++      struct hard_trap_info *ht;
++      unsigned long flags;
++
++      local_irq_save(flags);
++      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
++              set_except_vector(ht->tt, saved_vectors[ht->tt]);
++      local_irq_restore(flags);
++}
++
++/*
++ * Convert the MIPS hardware trap type code to a Unix signal number.
++ */
++static int computeSignal(int tt)
++{
++      struct hard_trap_info *ht;
++
++      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
++              if (ht->tt == tt)
++                      return ht->signo;
++
++      return SIGHUP;          /* default for things we don't know about */
++}
++
++/*
++ * While we find nice hex chars, build an int.
++ * Return number of chars processed.
++ */
++static int hexToInt(char **ptr, int *intValue)
++{
++      int numChars = 0;
++      int hexValue;
++
++      *intValue = 0;
++
++      while (**ptr) {
++              hexValue = hex(**ptr);
++              if (hexValue < 0)
++                      break;
++
++              *intValue = (*intValue << 4) | hexValue;
++              numChars ++;
++
++              (*ptr)++;
++      }
++
++      return (numChars);
++}
++
++static int hexToLong(char **ptr, long *longValue)
++{
++      int numChars = 0;
++      int hexValue;
++
++      *longValue = 0;
++
++      while (**ptr) {
++              hexValue = hex(**ptr);
++              if (hexValue < 0)
++                      break;
++
++              *longValue = (*longValue << 4) | hexValue;
++              numChars ++;
++
++              (*ptr)++;
++      }
++
++      return numChars;
++}
++
++
++#if 0
++/*
++ * Print registers (on target console)
++ * Used only to debug the stub...
++ */
++void show_gdbregs(struct gdb_regs * regs)
++{
++      /*
++       * Saved main processor registers
++       */
++      printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
++             regs->reg0, regs->reg1, regs->reg2, regs->reg3,
++             regs->reg4, regs->reg5, regs->reg6, regs->reg7);
++      printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
++             regs->reg8, regs->reg9, regs->reg10, regs->reg11,
++             regs->reg12, regs->reg13, regs->reg14, regs->reg15);
++      printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
++             regs->reg16, regs->reg17, regs->reg18, regs->reg19,
++             regs->reg20, regs->reg21, regs->reg22, regs->reg23);
++      printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
++             regs->reg24, regs->reg25, regs->reg26, regs->reg27,
++             regs->reg28, regs->reg29, regs->reg30, regs->reg31);
++
++      /*
++       * Saved cp0 registers
++       */
++      printk("epc  : %08lx\nStatus: %08lx\nCause : %08lx\n",
++             regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
++}
++#endif /* dead code */
++
++/*
++ * We single-step by setting breakpoints. When an exception
++ * is handled, we need to restore the instructions hoisted
++ * when the breakpoints were set.
++ *
++ * This is where we save the original instructions.
++ */
++static struct gdb_bp_save {
++      unsigned long addr;
++      unsigned int val;
++} step_bp[2];
++
++#define BP 0x0000000d  /* break opcode */
++
++/*
++ * Set breakpoint instructions for single stepping.
++ */
++static void single_step(struct gdb_regs *regs)
++{
++      union mips_instruction insn;
++      unsigned long targ;
++      int is_branch, is_cond, i;
++
++      targ = regs->cp0_epc;
++      insn.word = *(unsigned int *)targ;
++      is_branch = is_cond = 0;
++
++      switch (insn.i_format.opcode) {
++      /*
++       * jr and jalr are in r_format format.
++       */
++      case spec_op:
++              switch (insn.r_format.func) {
++              case jalr_op:
++              case jr_op:
++                      targ = *(&regs->reg0 + insn.r_format.rs);
++                      is_branch = 1;
++                      break;
++              }
++              break;
++
++      /*
++       * This group contains:
++       * bltz_op, bgez_op, bltzl_op, bgezl_op,
++       * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
++       */
++      case bcond_op:
++              is_branch = is_cond = 1;
++              targ += 4 + (insn.i_format.simmediate << 2);
++              break;
++
++      /*
++       * These are unconditional and in j_format.
++       */
++      case jal_op:
++      case j_op:
++              is_branch = 1;
++              targ += 4;
++              targ >>= 28;
++              targ <<= 28;
++              targ |= (insn.j_format.target << 2);
++              break;
++
++      /*
++       * These are conditional.
++       */
++      case beq_op:
++      case beql_op:
++      case bne_op:
++      case bnel_op:
++      case blez_op:
++      case blezl_op:
++      case bgtz_op:
++      case bgtzl_op:
++      case cop0_op:
++      case cop1_op:
++      case cop2_op:
++      case cop1x_op:
++              is_branch = is_cond = 1;
++              targ += 4 + (insn.i_format.simmediate << 2);
++              break;
++      }
++
++      if (is_branch) {
++              i = 0;
++              if (is_cond && targ != (regs->cp0_epc + 8)) {
++                      step_bp[i].addr = regs->cp0_epc + 8;
++                      step_bp[i++].val = *(unsigned *)(regs->cp0_epc + 8);
++                      *(unsigned *)(regs->cp0_epc + 8) = BP;
++              }
++              step_bp[i].addr = targ;
++              step_bp[i].val  = *(unsigned *)targ;
++              *(unsigned *)targ = BP;
++      } else {
++              step_bp[0].addr = regs->cp0_epc + 4;
++              step_bp[0].val  = *(unsigned *)(regs->cp0_epc + 4);
++              *(unsigned *)(regs->cp0_epc + 4) = BP;
++      }
++}
++
++/*
++ *  If asynchronously interrupted by gdb, then we need to set a breakpoint
++ *  at the interrupted instruction so that we wind up stopped with a
++ *  reasonable stack frame.
++ */
++static struct gdb_bp_save async_bp;
++
++/*
++ * Swap the interrupted EPC with our asynchronous breakpoint routine.
++ * This is safer than stuffing the breakpoint in-place, since no cache
++ * flushes (or resulting smp_call_functions) are required.  The
++ * assumption is that only one CPU will be handling asynchronous bp's,
++ * and only one can be active at a time.
++ */
++extern spinlock_t smp_call_lock;
++
++void set_async_breakpoint(unsigned long *epc)
++{
++      /* skip breaking into userland */
++      if ((*epc & 0x80000000) == 0)
++              return;
++
++#ifdef CONFIG_SMP
++      /* avoid deadlock if someone is make IPC */
++      if (spin_is_locked(&smp_call_lock))
++              return;
++#endif
++
++      async_bp.addr = *epc;
++      *epc = (unsigned long)async_breakpoint;
++}
++
++static void kgdb_wait(void *arg)
++{
++      unsigned flags;
++      int cpu = smp_processor_id();
++
++      local_irq_save(flags);
++
++      __raw_spin_lock(&kgdb_cpulock[cpu]);
++      __raw_spin_unlock(&kgdb_cpulock[cpu]);
++
++      local_irq_restore(flags);
++}
++
++/*
++ * GDB stub needs to call kgdb_wait on all processor with interrupts
++ * disabled, so it uses it's own special variant.
++ */
++static int kgdb_smp_call_kgdb_wait(void)
++{
++#ifdef CONFIG_SMP
++      struct call_data_struct data;
++      int i, cpus = num_online_cpus() - 1;
++      int cpu = smp_processor_id();
++
++      /*
++       * Can die spectacularly if this CPU isn't yet marked online
++       */
++      BUG_ON(!cpu_online(cpu));
++
++      if (!cpus)
++              return 0;
++
++      if (spin_is_locked(&smp_call_lock)) {
++              /*
++               * Some other processor is trying to make us do something
++               * but we're not going to respond... give up
++               */
++              return -1;
++              }
++
++      /*
++       * We will continue here, accepting the fact that
++       * the kernel may deadlock if another CPU attempts
++       * to call smp_call_function now...
++       */
++
++      data.func = kgdb_wait;
++      data.info = NULL;
++      atomic_set(&data.started, 0);
++      data.wait = 0;
++
++      spin_lock(&smp_call_lock);
++      call_data = &data;
++      mb();
++
++      /* Send a message to all other CPUs and wait for them to respond */
++      for (i = 0; i < NR_CPUS; i++)
++              if (cpu_online(i) && i != cpu)
++                      core_send_ipi(i, SMP_CALL_FUNCTION);
++
++      /* Wait for response */
++      /* FIXME: lock-up detection, backtrace on lock-up */
++      while (atomic_read(&data.started) != cpus)
++              barrier();
++
++      call_data = NULL;
++      spin_unlock(&smp_call_lock);
++#endif
++
++      return 0;
++}
++
++/*
++ * This function does all command processing for interfacing to gdb.  It
++ * returns 1 if you should skip the instruction at the trap address, 0
++ * otherwise.
++ */
++void handle_exception (struct gdb_regs *regs)
++{
++      int trap;                       /* Trap type */
++      int sigval;
++      long addr;
++      int length;
++      char *ptr;
++      unsigned long *stack;
++      int i;
++      int bflag = 0;
++
++      kgdb_started = 1;
++
++      /*
++       * acquire the big kgdb spinlock
++       */
++      if (!spin_trylock(&kgdb_lock)) {
++              /*
++               * some other CPU has the lock, we should go back to
++               * receive the gdb_wait IPC
++               */
++              return;
++      }
++
++      /*
++       * If we're in async_breakpoint(), restore the real EPC from
++       * the breakpoint.
++       */
++      if (regs->cp0_epc == (unsigned long)async_breakinst) {
++              regs->cp0_epc = async_bp.addr;
++              async_bp.addr = 0;
++      }
++
++      /*
++       * acquire the CPU spinlocks
++       */
++      for (i = num_online_cpus()-1; i >= 0; i--)
++              if (__raw_spin_trylock(&kgdb_cpulock[i]) == 0)
++                      panic("kgdb: couldn't get cpulock %d\n", i);
++
++      /*
++       * force other cpus to enter kgdb
++       */
++      kgdb_smp_call_kgdb_wait();
++
++      /*
++       * If we're in breakpoint() increment the PC
++       */
++      trap = (regs->cp0_cause & 0x7c) >> 2;
++      if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst)
++              regs->cp0_epc += 4;
++
++      /*
++       * If we were single_stepping, restore the opcodes hoisted
++       * for the breakpoint[s].
++       */
++      if (step_bp[0].addr) {
++              *(unsigned *)step_bp[0].addr = step_bp[0].val;
++              step_bp[0].addr = 0;
++
++              if (step_bp[1].addr) {
++                      *(unsigned *)step_bp[1].addr = step_bp[1].val;
++                      step_bp[1].addr = 0;
++              }
++      }
++
++      stack = (long *)regs->reg29;                    /* stack ptr */
++      sigval = computeSignal(trap);
++
++      /*
++       * reply to host that an exception has occurred
++       */
++      ptr = output_buffer;
++
++      /*
++       * Send trap type (converted to signal)
++       */
++      *ptr++ = 'T';
++      *ptr++ = hexchars[sigval >> 4];
++      *ptr++ = hexchars[sigval & 0xf];
++
++      /*
++       * Send Error PC
++       */
++      *ptr++ = hexchars[REG_EPC >> 4];
++      *ptr++ = hexchars[REG_EPC & 0xf];
++      *ptr++ = ':';
++      ptr = mem2hex((char *)&regs->cp0_epc, ptr, sizeof(long), 0);
++      *ptr++ = ';';
++
++      /*
++       * Send frame pointer
++       */
++      *ptr++ = hexchars[REG_FP >> 4];
++      *ptr++ = hexchars[REG_FP & 0xf];
++      *ptr++ = ':';
++      ptr = mem2hex((char *)&regs->reg30, ptr, sizeof(long), 0);
++      *ptr++ = ';';
++
++      /*
++       * Send stack pointer
++       */
++      *ptr++ = hexchars[REG_SP >> 4];
++      *ptr++ = hexchars[REG_SP & 0xf];
++      *ptr++ = ':';
++      ptr = mem2hex((char *)&regs->reg29, ptr, sizeof(long), 0);
++      *ptr++ = ';';
++
++      *ptr++ = 0;
++      putpacket(output_buffer);       /* send it off... */
++
++      /*
++       * Wait for input from remote GDB
++       */
++      while (1) {
++              output_buffer[0] = 0;
++              getpacket(input_buffer);
++
++              switch (input_buffer[0])
++              {
++              case '?':
++                      output_buffer[0] = 'S';
++                      output_buffer[1] = hexchars[sigval >> 4];
++                      output_buffer[2] = hexchars[sigval & 0xf];
++                      output_buffer[3] = 0;
++                      break;
++
++              /*
++               * Detach debugger; let CPU run
++               */
++              case 'D':
++                      putpacket(output_buffer);
++                      goto finish_kgdb;
++                      break;
++
++              case 'd':
++                      /* toggle debug flag */
++                      break;
++
++              /*
++               * Return the value of the CPU registers
++               */
++              case 'g':
++                      ptr = output_buffer;
++                      ptr = mem2hex((char *)&regs->reg0, ptr, 32*sizeof(long), 0); /* r0...r31 */
++                      ptr = mem2hex((char *)&regs->cp0_status, ptr, 6*sizeof(long), 0); /* cp0 */
++                      ptr = mem2hex((char *)&regs->fpr0, ptr, 32*sizeof(long), 0); /* f0...31 */
++                      ptr = mem2hex((char *)&regs->cp1_fsr, ptr, 2*sizeof(long), 0); /* cp1 */
++                      ptr = mem2hex((char *)&regs->frame_ptr, ptr, 2*sizeof(long), 0); /* frp */
++                      ptr = mem2hex((char *)&regs->cp0_index, ptr, 16*sizeof(long), 0); /* cp0 */
++                      break;
++
++              /*
++               * set the value of the CPU registers - return OK
++               */
++              case 'G':
++              {
++                      ptr = &input_buffer[1];
++                      hex2mem(ptr, (char *)&regs->reg0, 32*sizeof(long), 0, 0);
++                      ptr += 32*(2*sizeof(long));
++                      hex2mem(ptr, (char *)&regs->cp0_status, 6*sizeof(long), 0, 0);
++                      ptr += 6*(2*sizeof(long));
++                      hex2mem(ptr, (char *)&regs->fpr0, 32*sizeof(long), 0, 0);
++                      ptr += 32*(2*sizeof(long));
++                      hex2mem(ptr, (char *)&regs->cp1_fsr, 2*sizeof(long), 0, 0);
++                      ptr += 2*(2*sizeof(long));
++                      hex2mem(ptr, (char *)&regs->frame_ptr, 2*sizeof(long), 0, 0);
++                      ptr += 2*(2*sizeof(long));
++                      hex2mem(ptr, (char *)&regs->cp0_index, 16*sizeof(long), 0, 0);
++                      strcpy(output_buffer,"OK");
++               }
++              break;
++
++              /*
++               * mAA..AA,LLLL  Read LLLL bytes at address AA..AA
++               */
++              case 'm':
++                      ptr = &input_buffer[1];
++
++                      if (hexToLong(&ptr, &addr)
++                              && *ptr++ == ','
++                              && hexToInt(&ptr, &length)) {
++                              if (mem2hex((char *)addr, output_buffer, length, 1))
++                                      break;
++                              strcpy (output_buffer, "E03");
++                      } else
++                              strcpy(output_buffer,"E01");
++                      break;
++
++              /*
++               * XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA
++               */
++              case 'X':
++                      bflag = 1;
++                      /* fall through */
++
++              /*
++               * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
++               */
++              case 'M':
++                      ptr = &input_buffer[1];
++
++                      if (hexToLong(&ptr, &addr)
++                              && *ptr++ == ','
++                              && hexToInt(&ptr, &length)
++                              && *ptr++ == ':') {
++                              if (hex2mem(ptr, (char *)addr, length, bflag, 1))
++                                      strcpy(output_buffer, "OK");
++                              else
++                                      strcpy(output_buffer, "E03");
++                      }
++                      else
++                              strcpy(output_buffer, "E02");
++                      break;
++
++              /*
++               * cAA..AA    Continue at address AA..AA(optional)
++               */
++              case 'c':
++                      /* try to read optional parameter, pc unchanged if no parm */
++
++                      ptr = &input_buffer[1];
++                      if (hexToLong(&ptr, &addr))
++                              regs->cp0_epc = addr;
++
++                      goto exit_kgdb_exception;
++                      break;
++
++              /*
++               * kill the program; let us try to restart the machine
++               * Reset the whole machine.
++               */
++              case 'k':
++              case 'r':
++                      machine_restart("kgdb restarts machine");
++                      break;
++
++              /*
++               * Step to next instruction
++               */
++              case 's':
++                      /*
++                       * There is no single step insn in the MIPS ISA, so we
++                       * use breakpoints and continue, instead.
++                       */
++                      single_step(regs);
++                      goto exit_kgdb_exception;
++                      /* NOTREACHED */
++                      break;
++
++              /*
++               * Set baud rate (bBB)
++               * FIXME: Needs to be written
++               */
++              case 'b':
++              {
++#if 0
++                      int baudrate;
++                      extern void set_timer_3();
++
++                      ptr = &input_buffer[1];
++                      if (!hexToInt(&ptr, &baudrate))
++                      {
++                              strcpy(output_buffer,"B01");
++                              break;
++                      }
++
++                      /* Convert baud rate to uart clock divider */
++
++                      switch (baudrate)
++                      {
++                              case 38400:
++                                      baudrate = 16;
++                                      break;
++                              case 19200:
++                                      baudrate = 33;
++                                      break;
++                              case 9600:
++                                      baudrate = 65;
++                                      break;
++                              default:
++                                      baudrate = 0;
++                                      strcpy(output_buffer,"B02");
++                                      goto x1;
++                      }
++
++                      if (baudrate) {
++                              putpacket("OK");        /* Ack before changing speed */
++                              set_timer_3(baudrate); /* Set it */
++                      }
++#endif
++              }
++              break;
++
++              }                       /* switch */
++
++              /*
++               * reply to the request
++               */
++
++              putpacket(output_buffer);
++
++      } /* while */
++
++      return;
++
++finish_kgdb:
++      restore_debug_traps();
++
++exit_kgdb_exception:
++      /* release locks so other CPUs can go */
++      for (i = num_online_cpus()-1; i >= 0; i--)
++              __raw_spin_unlock(&kgdb_cpulock[i]);
++      spin_unlock(&kgdb_lock);
++
++      __flush_cache_all();
++      return;
++}
++
++/*
++ * This function will generate a breakpoint exception.  It is used at the
++ * beginning of a program to sync up with a debugger and can be used
++ * otherwise as a quick means to stop program execution and "break" into
++ * the debugger.
++ */
++void breakpoint(void)
++{
++      if (!initialized)
++              return;
++
++      __asm__ __volatile__(
++                      ".globl breakinst\n\t"
++                      ".set\tnoreorder\n\t"
++                      "nop\n"
++                      "breakinst:\tbreak\n\t"
++                      "nop\n\t"
++                      ".set\treorder"
++                      );
++}
++
++/* Nothing but the break; don't pollute any registers */
++void async_breakpoint(void)
++{
++      __asm__ __volatile__(
++                      ".globl async_breakinst\n\t"
++                      ".set\tnoreorder\n\t"
++                      "nop\n"
++                      "async_breakinst:\tbreak\n\t"
++                      "nop\n\t"
++                      ".set\treorder"
++                      );
++}
++
++void adel(void)
++{
++      __asm__ __volatile__(
++                      ".globl\tadel\n\t"
++                      "lui\t$8,0x8000\n\t"
++                      "lw\t$9,1($8)\n\t"
++                      );
++}
++
++/*
++ * malloc is needed by gdb client in "call func()", even a private one
++ * will make gdb happy
++ */
++static void * __attribute_used__ malloc(size_t size)
++{
++      return kmalloc(size, GFP_ATOMIC);
++}
++
++static void __attribute_used__ free (void *where)
++{
++      kfree(where);
++}
++
++#ifdef CONFIG_GDB_CONSOLE
++
++void gdb_putsn(const char *str, int l)
++{
++      char outbuf[18];
++
++      if (!kgdb_started)
++              return;
++
++      outbuf[0]='O';
++
++      while(l) {
++              int i = (l>8)?8:l;
++              mem2hex((char *)str, &outbuf[1], i, 0);
++              outbuf[(i*2)+1]=0;
++              putpacket(outbuf);
++              str += i;
++              l -= i;
++      }
++}
++
++static void gdb_console_write(struct console *con, const char *s, unsigned n)
++{
++      gdb_putsn(s, n);
++}
++
++static struct console gdb_console = {
++      .name   = "gdb",
++      .write  = gdb_console_write,
++      .flags  = CON_PRINTBUFFER,
++      .index  = -1
++};
++
++static int __init register_gdb_console(void)
++{
++      register_console(&gdb_console);
++
++      return 0;
++}
++
++console_initcall(register_gdb_console);
++
++#endif
+diff -Nurb linux-2.6.22-590/arch/mips/kernel/irq.c linux-2.6.22-570/arch/mips/kernel/irq.c
+--- linux-2.6.22-590/arch/mips/kernel/irq.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/kernel/irq.c    2007-07-08 19:32:17.000000000 -0400
+@@ -25,10 +25,6 @@
+ #include <asm/atomic.h>
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+-#include <asm/kgdb.h>
 -
--at 0x000000ac : */    0x7e345000,0x00000000,
--/*
--    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
+-/* Keep track of if we've done certain initialization already or not. */
+-int kgdb_early_setup;
+ static unsigned long irq_map[NR_IRQS / BITS_PER_LONG];
+@@ -142,23 +138,28 @@
+       atomic_inc(&irq_err_count);
+ }
+-void __init init_IRQ(void)
+-{
 -
--at 0x000000ae : */    0x7f350000,0x00000000,
--/*
--    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
+ #ifdef CONFIG_KGDB
+-      if (kgdb_early_setup)
+-              return;
++extern void breakpoint(void);
++extern void set_debug_traps(void);
++
++static int kgdb_flag = 1;
++static int __init nokgdb(char *str)
++{
++      kgdb_flag = 0;
++      return 1;
++}
++__setup("nokgdb", nokgdb);
+ #endif
++void __init init_IRQ(void)
++{
+       arch_init_irq();
 -
--at 0x000000b0 : */    0x7f360000,0x00000000,
+ #ifdef CONFIG_KGDB
+-      /*
+-       * We have been called before kgdb_arch_init(). Hence,
+-       * we dont want the traps to be reinitialized
+-       */
+-      if (kgdb_early_setup == 0)
+-              kgdb_early_setup = 1;
++      if (kgdb_flag) {
++              printk("Wait for gdb client connection ...\n");
++              set_debug_traps();
++              breakpoint();
++      }
+ #endif
+ }
+diff -Nurb linux-2.6.22-590/arch/mips/kernel/kgdb-jmp.c linux-2.6.22-570/arch/mips/kernel/kgdb-jmp.c
+--- linux-2.6.22-590/arch/mips/kernel/kgdb-jmp.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/kernel/kgdb-jmp.c       1969-12-31 19:00:00.000000000 -0500
+@@ -1,110 +0,0 @@
 -/*
--    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
+- * arch/mips/kernel/kgdb-jmp.c
+- *
+- * Save and restore system registers so that within a limited frame we
+- * may have a fault and "jump back" to a known safe location.
+- *
+- * Author: Tom Rini <trini@kernel.crashing.org>
+- * Author: Manish Lachwani <mlachwani@mvista.com>
+- *
+- * Cribbed from glibc, which carries the following:
+- * Copyright (C) 1996, 1997, 2000, 2002, 2003 Free Software Foundation, Inc.
+- * Copyright (C) 2005-2006 by MontaVista Software.
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program as licensed "as is" without any warranty of
+- * any kind, whether express or implied.
+- */
 -
--at 0x000000b2 : */    0x7f370000,0x00000000,
--/*
--    
--    MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4
+-#include <linux/kgdb.h>
 -
--at 0x000000b4 : */    0xc0000004,0x00000000,0x000002e0,
+-#ifdef CONFIG_64BIT
 -/*
--    
--dataout_to_jump:
--    MOVE MEMORY 4, 0, dataout_jump + 4 
+- * MIPS 64-bit
+- */
 -
--at 0x000000b7 : */    0xc0000004,0x00000000,0x000002f8,
--/*
+-int kgdb_fault_setjmp_aux(unsigned long *curr_context, unsigned long sp, unsigned long fp)
+-{
+-      __asm__ __volatile__ ("sd $gp, %0" : : "m" (curr_context[0]));
+-      __asm__ __volatile__ ("sd $16, %0" : : "m" (curr_context[1]));
+-      __asm__ __volatile__ ("sd $17, %0" : : "m" (curr_context[2]));
+-      __asm__ __volatile__ ("sd $18, %0" : : "m" (curr_context[3]));
+-      __asm__ __volatile__ ("sd $19, %0" : : "m" (curr_context[4]));
+-      __asm__ __volatile__ ("sd $20, %0" : : "m" (curr_context[5]));
+-      __asm__ __volatile__ ("sd $21, %0" : : "m" (curr_context[6]));
+-      __asm__ __volatile__ ("sd $22, %0" : : "m" (curr_context[7]));
+-      __asm__ __volatile__ ("sd $23, %0" : : "m" (curr_context[8]));
+-      __asm__ __volatile__ ("sd $31, %0" : : "m" (curr_context[9]));
+-      curr_context[10] = sp;
+-      curr_context[11] = fp;
 -
--    ; Time to correct DSA following memory move
--    MOVE MEMORY 4, saved_dsa, addr_dsa
+-      return 0;
+-}
 -
--at 0x000000ba : */    0xc0000004,0x00000000,0x00000000,
--/*
+-void kgdb_fault_longjmp(unsigned long *curr_context)
+-{
+-      __asm__ __volatile__ ("ld $gp, %0" : : "m" (curr_context[0]));
+-      __asm__ __volatile__ ("ld $16, %0" : : "m" (curr_context[1]));
+-      __asm__ __volatile__ ("ld $17, %0" : : "m" (curr_context[2]));
+-      __asm__ __volatile__ ("ld $18, %0" : : "m" (curr_context[3]));
+-      __asm__ __volatile__ ("ld $19, %0" : : "m" (curr_context[4]));
+-      __asm__ __volatile__ ("ld $20, %0" : : "m" (curr_context[5]));
+-      __asm__ __volatile__ ("ld $21, %0" : : "m" (curr_context[6]));
+-      __asm__ __volatile__ ("ld $22, %0" : : "m" (curr_context[7]));
+-      __asm__ __volatile__ ("ld $23, %0" : : "m" (curr_context[8]));
+-      __asm__ __volatile__ ("ld $25, %0" : : "m" (curr_context[9]));
+-      __asm__ __volatile__ ("ld $29, %0\n\t"
+-                            "ld $30, %1\n\t" : :
+-                            "m" (curr_context[10]), "m" (curr_context[11]));
 -
--dataout_jump:
--    JUMP 0
+-      __asm__ __volatile__ ("dli $2, 1");
+-      __asm__ __volatile__ ("j $25");
 -
--at 0x000000bd : */    0x80080000,0x00000000,
+-      for (;;);
+-}
+-#else
 -/*
+- * MIPS 32-bit
+- */
 -
--; Nasty jump to dsa->dsain
--do_datain:
--
--    MOVE MEMORY 4, saved_dsa, addr_scratch
+-int kgdb_fault_setjmp_aux(unsigned long *curr_context, unsigned long sp, unsigned long fp)
+-{
+-      __asm__ __volatile__("sw $gp, %0" : : "m" (curr_context[0]));
+-      __asm__ __volatile__("sw $16, %0" : : "m" (curr_context[1]));
+-      __asm__ __volatile__("sw $17, %0" : : "m" (curr_context[2]));
+-      __asm__ __volatile__("sw $18, %0" : : "m" (curr_context[3]));
+-      __asm__ __volatile__("sw $19, %0" : : "m" (curr_context[4]));
+-      __asm__ __volatile__("sw $20, %0" : : "m" (curr_context[5]));
+-      __asm__ __volatile__("sw $21, %0" : : "m" (curr_context[6]));
+-      __asm__ __volatile__("sw $22, %0" : : "m" (curr_context[7]));
+-      __asm__ __volatile__("sw $23, %0" : : "m" (curr_context[8]));
+-      __asm__ __volatile__("sw $31, %0" : : "m" (curr_context[9]));
+-      curr_context[10] = sp;
+-      curr_context[11] = fp;
 -
--at 0x000000bf : */    0xc0000004,0x00000000,0x00000000,
--/*
+-      return 0;
+-}
 -
+-void kgdb_fault_longjmp(unsigned long *curr_context)
+-{
+-      __asm__ __volatile__("lw $gp, %0" : : "m" (curr_context[0]));
+-      __asm__ __volatile__("lw $16, %0" : : "m" (curr_context[1]));
+-      __asm__ __volatile__("lw $17, %0" : : "m" (curr_context[2]));
+-      __asm__ __volatile__("lw $18, %0" : : "m" (curr_context[3]));
+-      __asm__ __volatile__("lw $19, %0" : : "m" (curr_context[4]));
+-      __asm__ __volatile__("lw $20, %0" : : "m" (curr_context[5]));
+-      __asm__ __volatile__("lw $21, %0" : : "m" (curr_context[6]));
+-      __asm__ __volatile__("lw $22, %0" : : "m" (curr_context[7]));
+-      __asm__ __volatile__("lw $23, %0" : : "m" (curr_context[8]));
+-      __asm__ __volatile__("lw $25, %0" : : "m" (curr_context[9]));
 -
+-      __asm__ __volatile__("lw $29, %0\n\t"
+-                           "lw $30, %1\n\t" : :
+-                           "m" (curr_context[10]), "m" (curr_context[11]));
 -
--    MOVE SCRATCH0 + dsa_datain TO SCRATCH0    
+-      __asm__ __volatile__("li $2, 1");
+-      __asm__ __volatile__("jr $25");
 -
--at 0x000000c2 : */    0x7e345400,0x00000000,
+-      for (;;);
+-}
+-#endif
+diff -Nurb linux-2.6.22-590/arch/mips/kernel/kgdb-setjmp.S linux-2.6.22-570/arch/mips/kernel/kgdb-setjmp.S
+--- linux-2.6.22-590/arch/mips/kernel/kgdb-setjmp.S    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/kernel/kgdb-setjmp.S    1969-12-31 19:00:00.000000000 -0500
+@@ -1,28 +0,0 @@
 -/*
--    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
+- * arch/mips/kernel/kgdb-jmp.c
+- *
+- * Save and restore system registers so that within a limited frame we
+- * may have a fault and "jump back" to a known safe location.
+- *
+- * Copyright (C) 2005 by MontaVista Software.
+- * Author: Manish Lachwani (mlachwani@mvista.com)
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program as licensed "as is" without any warranty of
+- * any kind, whether express or implied.
+- */
 -
--at 0x000000c4 : */    0x7f350000,0x00000000,
--/*
--    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
+-#include <asm/asm.h>
+-#include <asm/mipsregs.h>
+-#include <asm/regdef.h>
+-#include <asm/stackframe.h>
 -
--at 0x000000c6 : */    0x7f360000,0x00000000,
+-      .ent    kgdb_fault_setjmp,0
+-ENTRY (kgdb_fault_setjmp)
+-      move    a1, sp
+-      move    a2, fp
+-#ifdef CONFIG_64BIT
+-      nop
+-#endif
+-      j       kgdb_fault_setjmp_aux
+-      .end    kgdb_fault_setjmp
+diff -Nurb linux-2.6.22-590/arch/mips/kernel/kgdb.c linux-2.6.22-570/arch/mips/kernel/kgdb.c
+--- linux-2.6.22-590/arch/mips/kernel/kgdb.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/kernel/kgdb.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,299 +0,0 @@
 -/*
--    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
+- * arch/mips/kernel/kgdb.c
+- *
+- *  Originally written by Glenn Engel, Lake Stevens Instrument Division
+- *
+- *  Contributed by HP Systems
+- *
+- *  Modified for SPARC by Stu Grossman, Cygnus Support.
+- *
+- *  Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
+- *  Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
+- *
+- *  Copyright (C) 1995 Andreas Busse
+- *
+- *  Copyright (C) 2003 MontaVista Software Inc.
+- *  Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+- *
+- *  Copyright (C) 2004-2005 MontaVista Software Inc.
+- *  Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com
+- *
+- *  This file is licensed under the terms of the GNU General Public License
+- *  version 2. This program is licensed "as is" without any warranty of any
+- *  kind, whether express or implied.
+- */
 -
--at 0x000000c8 : */    0x7f370000,0x00000000,
--/*
--    
--    MOVE MEMORY 4, addr_scratch, datain_to_jump + 4
+-#include <linux/string.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/spinlock.h>
+-#include <linux/delay.h>
+-#include <asm/system.h>
+-#include <asm/ptrace.h>               /* for linux pt_regs struct */
+-#include <linux/kgdb.h>
+-#include <linux/init.h>
+-#include <linux/kdebug.h>
+-#include <asm/inst.h>
+-#include <asm/gdb-stub.h>
+-#include <asm/cacheflush.h>
+-#include <asm/kdebug.h>
 -
--at 0x000000ca : */    0xc0000004,0x00000000,0x00000338,
--/*
--    
--ENTRY datain_to_jump
--datain_to_jump:
--    MOVE MEMORY 4, 0, datain_jump + 4
+-static struct hard_trap_info {
+-      unsigned char tt;       /* Trap type code for MIPS R3xxx and R4xxx */
+-      unsigned char signo;    /* Signal that we map this trap into */
+-} hard_trap_info[] = {
+-      { 6, SIGBUS },          /* instruction bus error */
+-      { 7, SIGBUS },          /* data bus error */
+-      { 9, SIGTRAP },         /* break */
+-/*    { 11, SIGILL }, */      /* CPU unusable */
+-      { 12, SIGFPE },         /* overflow */
+-      { 13, SIGTRAP },        /* trap */
+-      { 14, SIGSEGV },        /* virtual instruction cache coherency */
+-      { 15, SIGFPE },         /* floating point exception */
+-      { 23, SIGSEGV },        /* watch */
+-      { 31, SIGSEGV },        /* virtual data cache coherency */
+-      { 0, 0}                 /* Must be last */
+-};
 -
--at 0x000000cd : */    0xc0000004,0x00000000,0x00000350,
--/*
+-/* Save the normal trap handlers for user-mode traps. */
+-void *saved_vectors[32];
 -
--    ; Time to correct DSA following memory move
--    MOVE MEMORY 4, saved_dsa, addr_dsa
+-extern void trap_low(void);
+-extern void breakinst(void);
+-extern void init_IRQ(void);
 -
--at 0x000000d0 : */    0xc0000004,0x00000000,0x00000000,
--/*
+-void kgdb_call_nmi_hook(void *ignored)
+-{
+-      kgdb_nmihook(smp_processor_id(), (void *)0);
+-}
 -
+-void kgdb_roundup_cpus(unsigned long flags)
+-{
+-      local_irq_enable();
+-      smp_call_function(kgdb_call_nmi_hook, 0, 0, 0);
+-      local_irq_disable();
+-}
 -
+-static int compute_signal(int tt)
+-{
+-      struct hard_trap_info *ht;
 -
+-      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+-              if (ht->tt == tt)
+-                      return ht->signo;
 -
--datain_jump:
--    JUMP 0
+-      return SIGHUP;          /* default for things we don't know about */
+-}
 -
--at 0x000000d3 : */    0x80080000,0x00000000,
 -/*
+- * Set up exception handlers for tracing and breakpoints
+- */
+-void handle_exception(struct pt_regs *regs)
+-{
+-      int trap = (regs->cp0_cause & 0x7c) >> 2;
 -
+-      if (fixup_exception(regs)) {
+-              return;
+-      }
 -
+-      if (atomic_read(&debugger_active))
+-              kgdb_nmihook(smp_processor_id(), regs);
 -
--; Note that other_out and other_in loop until a non-data phase
--; is discovered, so we only execute return statements when we
--; can go on to the next data phase block move statement.
--
--ENTRY other_out
--other_out:
+-      if (atomic_read(&kgdb_setting_breakpoint))
+-              if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst))
+-                      regs->cp0_epc += 4;
 -
+-      kgdb_handle_exception(0, compute_signal(trap), 0, regs);
 -
+-      /* In SMP mode, __flush_cache_all does IPI */
+-      local_irq_enable();
+-      __flush_cache_all();
+-}
 -
--    INT int_err_unexpected_phase, WHEN CMD
+-void set_debug_traps(void)
+-{
+-      struct hard_trap_info *ht;
+-      unsigned long flags;
 -
--at 0x000000d5 : */    0x9a0b0000,0x00000000,
--/*
--    JUMP msg_in_restart, WHEN MSG_IN 
+-      local_irq_save(flags);
 -
--at 0x000000d7 : */    0x870b0000,0x000003fc,
--/*
--    INT int_err_unexpected_phase, WHEN MSG_OUT
+-      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+-              saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low);
 -
--at 0x000000d9 : */    0x9e0b0000,0x00000000,
--/*
--    INT int_err_unexpected_phase, WHEN DATA_IN
+-      local_irq_restore(flags);
+-}
 -
--at 0x000000db : */    0x990b0000,0x00000000,
--/*
--    JUMP command_complete, WHEN STATUS
+-#if 0
+-/* This should be called before we exit kgdb_handle_exception() I believe.
+- * -- Tom
+- */
+-void restore_debug_traps(void)
+-{
+-      struct hard_trap_info *ht;
+-      unsigned long flags;
 -
--at 0x000000dd : */    0x830b0000,0x0000065c,
--/*
--    JUMP other_out, WHEN NOT DATA_OUT
+-      local_irq_save(flags);
+-      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+-              set_except_vector(ht->tt, saved_vectors[ht->tt]);
+-      local_irq_restore(flags);
+-}
+-#endif
 -
--at 0x000000df : */    0x80030000,0x00000354,
--/*
+-void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+-{
+-      int reg;
+-      gdb_reg_t *ptr = (gdb_reg_t*)gdb_regs;
 -
--; TEMP should be OK, as we got here from a call in the user dataout code.
+-      for (reg = 0; reg < 32; reg++)
+-              *(ptr++) = regs->regs[reg];
 -
--    RETURN
+-      *(ptr++) = regs->cp0_status;
+-      *(ptr++) = regs->lo;
+-      *(ptr++) = regs->hi;
+-      *(ptr++) = regs->cp0_badvaddr;
+-      *(ptr++) = regs->cp0_cause;
+-      *(ptr++) = regs->cp0_epc;
 -
--at 0x000000e1 : */    0x90080000,0x00000000,
--/*
+-      return;
+-}
 -
--ENTRY other_in
--other_in:
+-void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+-{
 -
+-      int reg;
+-      const gdb_reg_t *ptr = (gdb_reg_t*)gdb_regs;
 -
+-      for (reg = 0; reg < 32; reg++)
+-              regs->regs[reg] = *(ptr++);
 -
--    INT int_err_unexpected_phase, WHEN CMD
+-      regs->cp0_status = *(ptr++);
+-      regs->lo = *(ptr++);
+-      regs->hi = *(ptr++);
+-      regs->cp0_badvaddr = *(ptr++);
+-      regs->cp0_cause = *(ptr++);
+-      regs->cp0_epc = *(ptr++);
 -
--at 0x000000e3 : */    0x9a0b0000,0x00000000,
--/*
--    JUMP msg_in_restart, WHEN MSG_IN 
+-      return;
+-}
 -
--at 0x000000e5 : */    0x870b0000,0x000003fc,
 -/*
--    INT int_err_unexpected_phase, WHEN MSG_OUT
+- * Similar to regs_to_gdb_regs() except that process is sleeping and so
+- * we may not be able to get all the info.
+- */
+-void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+-{
+-      int reg;
+-      struct thread_info *ti = task_thread_info(p);
+-      unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32;
+-      struct pt_regs *regs = (struct pt_regs *)ksp - 1;
+-      gdb_reg_t *ptr = (gdb_reg_t*)gdb_regs;
 -
--at 0x000000e7 : */    0x9e0b0000,0x00000000,
--/*
--    INT int_err_unexpected_phase, WHEN DATA_OUT
+-      for (reg = 0; reg < 16; reg++)
+-              *(ptr++) = regs->regs[reg];
 -
--at 0x000000e9 : */    0x980b0000,0x00000000,
--/*
--    JUMP command_complete, WHEN STATUS
+-      /* S0 - S7 */
+-      for (reg = 16; reg < 24; reg++)
+-              *(ptr++) = regs->regs[reg];
 -
--at 0x000000eb : */    0x830b0000,0x0000065c,
--/*
--    JUMP other_in, WHEN NOT DATA_IN
+-      for (reg = 24; reg < 28; reg++)
+-              *(ptr++) = 0;
 -
--at 0x000000ed : */    0x81030000,0x0000038c,
--/*
+-      /* GP, SP, FP, RA */
+-      for (reg = 28; reg < 32; reg++)
+-              *(ptr++) = regs->regs[reg];
 -
--; TEMP should be OK, as we got here from a call in the user datain code.
+-      *(ptr++) = regs->cp0_status;
+-      *(ptr++) = regs->lo;
+-      *(ptr++) = regs->hi;
+-      *(ptr++) = regs->cp0_badvaddr;
+-      *(ptr++) = regs->cp0_cause;
+-      *(ptr++) = regs->cp0_epc;
 -
--    RETURN
+-      return;
+-}
 -
--at 0x000000ef : */    0x90080000,0x00000000,
 -/*
+- * Calls linux_debug_hook before the kernel dies. If KGDB is enabled,
+- * then try to fall into the debugger
+- */
+-static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
+-                          void *ptr)
+-{
+-      struct die_args *args = (struct die_args *)ptr;
+-      struct pt_regs *regs = args->regs;
+-      int trap = (regs->cp0_cause & 0x7c) >> 2;
 -
+-      /* See if KGDB is interested. */
+-      if (user_mode(regs))
+-              /* Userpace events, ignore. */
+-              return NOTIFY_DONE;
 -
--ENTRY other_transfer
--other_transfer:
--    INT int_err_unexpected_phase, WHEN CMD
--
--at 0x000000f1 : */    0x9a0b0000,0x00000000,
--/*
--    CALL msg_in, WHEN MSG_IN
+-      kgdb_handle_exception(trap, compute_signal(trap), 0, regs);
+-      return NOTIFY_OK;
+-}
 -
--at 0x000000f3 : */    0x8f0b0000,0x0000041c,
--/*
--    INT int_err_unexpected_phase, WHEN MSG_OUT
+-static struct notifier_block kgdb_notifier = {
+-      .notifier_call = kgdb_mips_notify,
+-};
 -
--at 0x000000f5 : */    0x9e0b0000,0x00000000,
 -/*
--    INT int_err_unexpected_phase, WHEN DATA_OUT
+- * Handle the 's' and 'c' commands
+- */
+-int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+-                             char *remcom_in_buffer, char *remcom_out_buffer,
+-                             struct pt_regs *regs)
+-{
+-      char *ptr;
+-      unsigned long address;
+-      int cpu = smp_processor_id();
 -
--at 0x000000f7 : */    0x980b0000,0x00000000,
--/*
--    INT int_err_unexpected_phase, WHEN DATA_IN
+-      switch (remcom_in_buffer[0]) {
+-      case 's':
+-      case 'c':
+-              /* handle the optional parameter */
+-              ptr = &remcom_in_buffer[1];
+-              if (kgdb_hex2long(&ptr, &address))
+-                      regs->cp0_epc = address;
 -
--at 0x000000f9 : */    0x990b0000,0x00000000,
--/*
--    JUMP command_complete, WHEN STATUS
+-              atomic_set(&cpu_doing_single_step, -1);
+-              if (remcom_in_buffer[0] == 's')
+-                      if (kgdb_contthread)
+-                              atomic_set(&cpu_doing_single_step, cpu);
 -
--at 0x000000fb : */    0x830b0000,0x0000065c,
--/*
--    JUMP other_transfer
+-              return 0;
+-      }
 -
--at 0x000000fd : */    0x80080000,0x000003c4,
--/*
+-      return -1;
+-}
 -
--;
--; msg_in_restart
--; msg_in
--; munge_msg
--;
--; PURPOSE : process messages from a target.  msg_in is called when the 
--;     caller hasn't read the first byte of the message.  munge_message
--;     is called when the caller has read the first byte of the message,
--;     and left it in SFBR.  msg_in_restart is called when the caller 
--;     hasn't read the first byte of the message, and wishes RETURN
--;     to transfer control back to the address of the conditional
--;     CALL instruction rather than to the instruction after it.
--;
--;     Various int_* interrupts are generated when the host system
--;     needs to intervene, as is the case with SDTR, WDTR, and
--;     INITIATE RECOVERY messages.
--;
--;     When the host system handles one of these interrupts,
--;     it can respond by reentering at reject_message, 
--;     which rejects the message and returns control to
--;     the caller of msg_in or munge_msg, accept_message
--;     which clears ACK and returns control, or reply_message
--;     which sends the message pointed to by the DSA 
--;     msgout_other table indirect field.
--;
--;     DISCONNECT messages are handled by moving the command
--;     to the reconnect_dsa_queue.
--
--; NOTE: DSA should be valid when we get here - we cannot save both it
--;     and TEMP in this routine.
--
--;
--; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg
--;     only)
--;
--; CALLS : NO.  The TEMP register isn't backed up to allow nested calls.
--;
--; MODIFIES : SCRATCH, DSA on DISCONNECT
--;
--; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS,
--;     and normal return from message handlers running under
--;     Linux, control is returned to the caller.  Receipt
--;     of DISCONNECT messages pass control to dsa_schedule.
--;
--ENTRY msg_in_restart
--msg_in_restart:
--; XXX - hackish
--;
--; Since it's easier to debug changes to the statically 
--; compiled code, rather than the dynamically generated 
--; stuff, such as
--;
--;     MOVE x, y, WHEN data_phase
--;     CALL other_z, WHEN NOT data_phase
--;     MOVE x, y, WHEN data_phase
--;
--; I'd like to have certain routines (notably the message handler)
--; restart on the conditional call rather than the next instruction.
--;
--; So, subtract 8 from the return address
--
--    MOVE TEMP0 + 0xf8 TO TEMP0
--
--at 0x000000ff : */    0x7e1cf800,0x00000000,
--/*
--    MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY
+-struct kgdb_arch arch_kgdb_ops = {
+-#ifdef CONFIG_CPU_LITTLE_ENDIAN
+-      .gdb_bpt_instr = {0xd},
+-#else
+-      .gdb_bpt_instr = {0x00, 0x00, 0x00, 0x0d},
+-#endif
+-};
 -
--at 0x00000101 : */    0x7f1dff00,0x00000000,
 -/*
--    MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY
+- * We use kgdb_early_setup so that functions we need to call now don't
+- * cause trouble when called again later.
+- */
+-__init int kgdb_arch_init(void)
+-{
+-      /* Board-specifics. */
+-      /* Force some calls to happen earlier. */
+-      if (kgdb_early_setup == 0) {
+-              trap_init();
+-              init_IRQ();
+-              kgdb_early_setup = 1;
+-      }
 -
--at 0x00000103 : */    0x7f1eff00,0x00000000,
--/*
--    MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY
+-      /* Set our traps. */
+-      /* This needs to be done more finely grained again, paired in
+-       * a before/after in kgdb_handle_exception(...) -- Tom */
+-      set_debug_traps();
+-      register_die_notifier(&kgdb_notifier);
 -
--at 0x00000105 : */    0x7f1fff00,0x00000000,
+-      return 0;
+-}
+diff -Nurb linux-2.6.22-590/arch/mips/kernel/kgdb_handler.S linux-2.6.22-570/arch/mips/kernel/kgdb_handler.S
+--- linux-2.6.22-590/arch/mips/kernel/kgdb_handler.S   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/kernel/kgdb_handler.S   1969-12-31 19:00:00.000000000 -0500
+@@ -1,339 +0,0 @@
 -/*
+- * arch/mips/kernel/kgdb_handler.S
+- *
+- * Copyright (C) 2007 Wind River Systems, Inc
+- *
+- * Copyright (C) 2004-2005 MontaVista Software Inc.
+- * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * version 2. This program is licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
 -
--ENTRY msg_in
--msg_in:
--    MOVE 1, msg_buf, WHEN MSG_IN
--
--at 0x00000107 : */    0x0f000001,0x00000000,
 -/*
+- * Trap Handler for the new KGDB framework. The main KGDB handler is
+- * handle_exception that will be called from here
+- *
+- */
 -
--munge_msg:
--    JUMP munge_extended, IF 0x01              ; EXTENDED MESSAGE
--
--at 0x00000109 : */    0x800c0001,0x00000574,
--/*
--    JUMP munge_2, IF 0x20, AND MASK 0xdf      ; two byte message
+-#include <linux/sys.h>
 -
--at 0x0000010b : */    0x800cdf20,0x00000464,
--/*
--;
--; XXX - I've seen a handful of broken SCSI devices which fail to issue
--;     a SAVE POINTERS message before disconnecting in the middle of 
--;     a transfer, assuming that the DATA POINTER will be implicitly 
--;     restored.  
--;
--; Historically, I've often done an implicit save when the DISCONNECT
--; message is processed.  We may want to consider having the option of 
--; doing that here. 
--;
--    JUMP munge_save_data_pointer, IF 0x02     ; SAVE DATA POINTER
--
--at 0x0000010d : */    0x800c0002,0x0000046c,
--/*
--    JUMP munge_restore_pointers, IF 0x03      ; RESTORE POINTERS 
+-#include <asm/asm.h>
+-#include <asm/errno.h>
+-#include <asm/mipsregs.h>
+-#include <asm/regdef.h>
+-#include <asm/stackframe.h>
+-#include <asm/gdb-stub.h>
 -
--at 0x0000010f : */    0x800c0003,0x00000518,
--/*
--    JUMP munge_disconnect, IF 0x04            ; DISCONNECT
+-#ifdef CONFIG_32BIT
+-#define DMFC0 mfc0
+-#define DMTC0 mtc0
+-#define LDC1  lwc1
+-#define SDC1  swc1
+-#endif
+-#ifdef CONFIG_64BIT
+-#define DMFC0 dmfc0
+-#define DMTC0 dmtc0
+-#define LDC1  ldc1
+-#define SDC1  sdc1
+-#endif
 -
--at 0x00000111 : */    0x800c0004,0x0000056c,
--/*
--    INT int_msg_1, IF 0x07                    ; MESSAGE REJECT
+-#include <asm/asmmacro.h>
 -
--at 0x00000113 : */    0x980c0007,0x01020000,
 -/*
--    INT int_msg_1, IF 0x0f                    ; INITIATE RECOVERY
+- * [jsun] We reserves about 2x GDB_FR_SIZE in stack.  The lower (addressed)
+- * part is used to store registers and passed to exception handler.
+- * The upper part is reserved for "call func" feature where gdb client
+- * saves some of the regs, setups call frame and passes args.
+- *
+- * A trace shows about 200 bytes are used to store about half of all regs.
+- * The rest should be big enough for frame setup and passing args.
+- */
 -
--at 0x00000115 : */    0x980c000f,0x01020000,
 -/*
+- * The low level trap handler
+- */
+-              .align  5
+-              NESTED(trap_low, GDB_FR_SIZE, sp)
+-              .set    noat
+-              .set    noreorder
 -
+-              mfc0    k0, CP0_STATUS
+-              sll     k0, 3                   /* extract cu0 bit */
+-              bltz    k0, 1f
+-              move    k1, sp
 -
+-              /*
+-               * Called from user mode, go somewhere else.
+-               */
+-#if defined(CONFIG_32BIT)
+-              lui     k1, %hi(saved_vectors)
+-              mfc0    k0, CP0_CAUSE
+-              andi    k0, k0, 0x7c
+-              add     k1, k1, k0
+-              lw      k0, %lo(saved_vectors)(k1)
+-#elif defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64)
+-              DMFC0   k0, CP0_CAUSE
+-              lui     k1, %highest(saved_vectors)
+-                andi    k0, k0, 0x7c           /* mask exception type */
+-                dsll    k0, 1                  /* turn into byte offset */
+-              daddiu  k1, %higher(saved_vectors)
+-              dsll    k1, k1, 16
+-              daddiu  k1, %hi(saved_vectors)
+-              dsll    k1, k1, 16
+-              daddu   k1, k1, k0
+-              LONG_L  k0, %lo(saved_vectors)(k1)
+-#else
+-#error "MIPS configuration is unsupported for kgdb!!"
+-#endif
+-              jr      k0
+-              nop
+-1:
+-              move    k0, sp
+-              PTR_SUBU sp, k1, GDB_FR_SIZE*2  # see comment above
+-              LONG_S  k0, GDB_FR_REG29(sp)
+-              LONG_S  $2, GDB_FR_REG2(sp)
 -
--    JUMP reject_message
--
--at 0x00000117 : */    0x80080000,0x00000604,
--/*
--
--munge_2:
--    JUMP reject_message
--
--at 0x00000119 : */    0x80080000,0x00000604,
 -/*
--;
--; The SCSI standard allows targets to recover from transient 
--; error conditions by backing up the data pointer with a 
--; RESTORE POINTERS message.  
--;     
--; So, we must save and restore the _residual_ code as well as 
--; the current instruction pointer.  Because of this messiness,
--; it is simpler to put dynamic code in the dsa for this and to
--; just do a simple jump down there. 
--;
--
--munge_save_data_pointer:
--
--    ; We have something in TEMP here, so first we must save that
--    MOVE TEMP0 TO SFBR
--
--at 0x0000011b : */    0x721c0000,0x00000000,
--/*
--    MOVE SFBR TO SCRATCH0
+- * First save the CP0 and special registers
+- */
 -
--at 0x0000011d : */    0x6a340000,0x00000000,
--/*
--    MOVE TEMP1 TO SFBR
+-              mfc0    v0, CP0_STATUS
+-              LONG_S  v0, GDB_FR_STATUS(sp)
+-              mfc0    v0, CP0_CAUSE
+-              LONG_S  v0, GDB_FR_CAUSE(sp)
+-              DMFC0   v0, CP0_EPC
+-              LONG_S  v0, GDB_FR_EPC(sp)
+-              DMFC0   v0, CP0_BADVADDR
+-              LONG_S  v0, GDB_FR_BADVADDR(sp)
+-              mfhi    v0
+-              LONG_S  v0, GDB_FR_HI(sp)
+-              mflo    v0
+-              LONG_S  v0, GDB_FR_LO(sp)
 -
--at 0x0000011f : */    0x721d0000,0x00000000,
 -/*
--    MOVE SFBR TO SCRATCH1
+- * Now the integer registers
+- */
 -
--at 0x00000121 : */    0x6a350000,0x00000000,
--/*
--    MOVE TEMP2 TO SFBR
+-              LONG_S  zero, GDB_FR_REG0(sp)           /* I know... */
+-              LONG_S  $1, GDB_FR_REG1(sp)
+-              /* v0 already saved */
+-              LONG_S  $3, GDB_FR_REG3(sp)
+-              LONG_S  $4, GDB_FR_REG4(sp)
+-              LONG_S  $5, GDB_FR_REG5(sp)
+-              LONG_S  $6, GDB_FR_REG6(sp)
+-              LONG_S  $7, GDB_FR_REG7(sp)
+-              LONG_S  $8, GDB_FR_REG8(sp)
+-              LONG_S  $9, GDB_FR_REG9(sp)
+-              LONG_S  $10, GDB_FR_REG10(sp)
+-              LONG_S  $11, GDB_FR_REG11(sp)
+-              LONG_S  $12, GDB_FR_REG12(sp)
+-              LONG_S  $13, GDB_FR_REG13(sp)
+-              LONG_S  $14, GDB_FR_REG14(sp)
+-              LONG_S  $15, GDB_FR_REG15(sp)
+-              LONG_S  $16, GDB_FR_REG16(sp)
+-              LONG_S  $17, GDB_FR_REG17(sp)
+-              LONG_S  $18, GDB_FR_REG18(sp)
+-              LONG_S  $19, GDB_FR_REG19(sp)
+-              LONG_S  $20, GDB_FR_REG20(sp)
+-              LONG_S  $21, GDB_FR_REG21(sp)
+-              LONG_S  $22, GDB_FR_REG22(sp)
+-              LONG_S  $23, GDB_FR_REG23(sp)
+-              LONG_S  $24, GDB_FR_REG24(sp)
+-              LONG_S  $25, GDB_FR_REG25(sp)
+-              LONG_S  $26, GDB_FR_REG26(sp)
+-              LONG_S  $27, GDB_FR_REG27(sp)
+-              LONG_S  $28, GDB_FR_REG28(sp)
+-              /* sp already saved */
+-              LONG_S  $30, GDB_FR_REG30(sp)
+-              LONG_S  $31, GDB_FR_REG31(sp)
 -
--at 0x00000123 : */    0x721e0000,0x00000000,
--/*
--    MOVE SFBR TO SCRATCH2
+-              CLI                             /* disable interrupts */
 -
--at 0x00000125 : */    0x6a360000,0x00000000,
 -/*
--    MOVE TEMP3 TO SFBR
+- * Followed by the floating point registers
+- */
+-              mfc0    v0, CP0_STATUS          /* FPU enabled? */
+-              srl     v0, v0, 16
+-              andi    v0, v0, (ST0_CU1 >> 16)
 -
--at 0x00000127 : */    0x721f0000,0x00000000,
--/*
--    MOVE SFBR TO SCRATCH3
+-              beqz    v0,3f                   /* disabled, skip */
+-               nop
 -
--at 0x00000129 : */    0x6a370000,0x00000000,
--/*
--    MOVE MEMORY 4, addr_scratch, jump_temp + 4
+-              li      t0, 0
+-#ifdef CONFIG_64BIT
+-              mfc0    t0, CP0_STATUS
+-#endif
+-              fpu_save_double_kgdb sp t0 t1   # clobbers t1
 -
--at 0x0000012b : */    0xc0000004,0x00000000,0x000009c8,
--/*
--    ; Now restore DSA
--    MOVE MEMORY 4, saved_dsa, addr_dsa
 -
--at 0x0000012e : */    0xc0000004,0x00000000,0x00000000,
 -/*
+- * Current stack frame ptr
+- */
 -
--    MOVE DSA0 + dsa_save_data_pointer TO SFBR
+-3:
+-              LONG_S  sp, GDB_FR_FRP(sp)
 -
--at 0x00000131 : */    0x76100000,0x00000000,
 -/*
--    MOVE SFBR TO SCRATCH0
+- * CP0 registers (R4000/R4400 unused registers skipped)
+- */
 -
--at 0x00000133 : */    0x6a340000,0x00000000,
--/*
--    MOVE DSA1 + 0xff TO SFBR WITH CARRY
+-              mfc0    v0, CP0_INDEX
+-              LONG_S  v0, GDB_FR_CP0_INDEX(sp)
+-              mfc0    v0, CP0_RANDOM
+-              LONG_S  v0, GDB_FR_CP0_RANDOM(sp)
+-              DMFC0   v0, CP0_ENTRYLO0
+-              LONG_S  v0, GDB_FR_CP0_ENTRYLO0(sp)
+-              DMFC0   v0, CP0_ENTRYLO1
+-              LONG_S  v0, GDB_FR_CP0_ENTRYLO1(sp)
+-              DMFC0   v0, CP0_CONTEXT
+-              LONG_S  v0, GDB_FR_CP0_CONTEXT(sp)
+-              mfc0    v0, CP0_PAGEMASK
+-              LONG_S  v0, GDB_FR_CP0_PAGEMASK(sp)
+-              mfc0    v0, CP0_WIRED
+-              LONG_S  v0, GDB_FR_CP0_WIRED(sp)
+-              DMFC0   v0, CP0_ENTRYHI
+-              LONG_S  v0, GDB_FR_CP0_ENTRYHI(sp)
+-              mfc0    v0, CP0_PRID
+-              LONG_S  v0, GDB_FR_CP0_PRID(sp)
 -
--at 0x00000135 : */    0x7711ff00,0x00000000,
--/*
--    MOVE SFBR TO SCRATCH1
+-              .set    at
 -
--at 0x00000137 : */    0x6a350000,0x00000000,
 -/*
--    MOVE DSA2 + 0xff TO SFBR WITH CARRY 
+- * Continue with the higher level handler
+- */
 -
--at 0x00000139 : */    0x7712ff00,0x00000000,
--/*
--    MOVE SFBR TO SCRATCH2
+-              move    a0,sp
 -
--at 0x0000013b : */    0x6a360000,0x00000000,
--/*
--    MOVE DSA3 + 0xff TO SFBR WITH CARRY
+-              jal     handle_exception
+-               nop
 -
--at 0x0000013d : */    0x7713ff00,0x00000000,
 -/*
--    MOVE SFBR TO SCRATCH3
+- * Restore all writable registers, in reverse order
+- */
 -
--at 0x0000013f : */    0x6a370000,0x00000000,
--/*
+-              .set    noat
 -
--    
--    MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4
+-              LONG_L  v0, GDB_FR_CP0_ENTRYHI(sp)
+-              LONG_L  v1, GDB_FR_CP0_WIRED(sp)
+-              DMTC0   v0, CP0_ENTRYHI
+-              mtc0    v1, CP0_WIRED
+-              LONG_L  v0, GDB_FR_CP0_PAGEMASK(sp)
+-              LONG_L  v1, GDB_FR_CP0_ENTRYLO1(sp)
+-              mtc0    v0, CP0_PAGEMASK
+-              DMTC0   v1, CP0_ENTRYLO1
+-              LONG_L  v0, GDB_FR_CP0_ENTRYLO0(sp)
+-              LONG_L  v1, GDB_FR_CP0_INDEX(sp)
+-              DMTC0   v0, CP0_ENTRYLO0
+-              LONG_L  v0, GDB_FR_CP0_CONTEXT(sp)
+-              mtc0    v1, CP0_INDEX
+-              DMTC0   v0, CP0_CONTEXT
 -
--at 0x00000141 : */    0xc0000004,0x00000000,0x00000514,
--/*
--    
--jump_dsa_save:
--    JUMP 0
 -
--at 0x00000144 : */    0x80080000,0x00000000,
 -/*
+- * Next, the floating point registers
+- */
+-              mfc0    v0, CP0_STATUS          /* check if the FPU is enabled */
+-              srl     v0, v0, 16
+-              andi    v0, v0, (ST0_CU1 >> 16)
 -
--munge_restore_pointers:
+-              beqz    v0, 3f                  /* disabled, skip */
+-               nop
 -
--    ; The code at dsa_restore_pointers will RETURN, but we don't care
--    ; about TEMP here, as it will overwrite it anyway.
+-              li      t0, 0
+-#ifdef CONFIG_64BIT
+-              mfc0    t0, CP0_STATUS
+-#endif
+-              fpu_restore_double_kgdb sp t0 t1 # clobbers t1
 -
--    MOVE DSA0 + dsa_restore_pointers TO SFBR
 -
--at 0x00000146 : */    0x76100000,0x00000000,
 -/*
--    MOVE SFBR TO SCRATCH0
+- * Now the CP0 and integer registers
+- */
 -
--at 0x00000148 : */    0x6a340000,0x00000000,
--/*
--    MOVE DSA1 + 0xff TO SFBR WITH CARRY
+-3:
+-              mfc0    t0, CP0_STATUS
+-              ori     t0, 0x1f
+-              xori    t0, 0x1f
+-              mtc0    t0, CP0_STATUS
 -
--at 0x0000014a : */    0x7711ff00,0x00000000,
--/*
--    MOVE SFBR TO SCRATCH1
+-              LONG_L  v0, GDB_FR_STATUS(sp)
+-              LONG_L  v1, GDB_FR_EPC(sp)
+-              mtc0    v0, CP0_STATUS
+-              DMTC0   v1, CP0_EPC
+-              LONG_L  v0, GDB_FR_HI(sp)
+-              LONG_L  v1, GDB_FR_LO(sp)
+-              mthi    v0
+-              mtlo    v1
+-              LONG_L  $31, GDB_FR_REG31(sp)
+-              LONG_L  $30, GDB_FR_REG30(sp)
+-              LONG_L  $28, GDB_FR_REG28(sp)
+-              LONG_L  $27, GDB_FR_REG27(sp)
+-              LONG_L  $26, GDB_FR_REG26(sp)
+-              LONG_L  $25, GDB_FR_REG25(sp)
+-              LONG_L  $24, GDB_FR_REG24(sp)
+-              LONG_L  $23, GDB_FR_REG23(sp)
+-              LONG_L  $22, GDB_FR_REG22(sp)
+-              LONG_L  $21, GDB_FR_REG21(sp)
+-              LONG_L  $20, GDB_FR_REG20(sp)
+-              LONG_L  $19, GDB_FR_REG19(sp)
+-              LONG_L  $18, GDB_FR_REG18(sp)
+-              LONG_L  $17, GDB_FR_REG17(sp)
+-              LONG_L  $16, GDB_FR_REG16(sp)
+-              LONG_L  $15, GDB_FR_REG15(sp)
+-              LONG_L  $14, GDB_FR_REG14(sp)
+-              LONG_L  $13, GDB_FR_REG13(sp)
+-              LONG_L  $12, GDB_FR_REG12(sp)
+-              LONG_L  $11, GDB_FR_REG11(sp)
+-              LONG_L  $10, GDB_FR_REG10(sp)
+-              LONG_L  $9, GDB_FR_REG9(sp)
+-              LONG_L  $8, GDB_FR_REG8(sp)
+-              LONG_L  $7, GDB_FR_REG7(sp)
+-              LONG_L  $6, GDB_FR_REG6(sp)
+-              LONG_L  $5, GDB_FR_REG5(sp)
+-              LONG_L  $4, GDB_FR_REG4(sp)
+-              LONG_L  $3, GDB_FR_REG3(sp)
+-              LONG_L  $2, GDB_FR_REG2(sp)
+-              LONG_L  $1, GDB_FR_REG1(sp)
+-#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+-              LONG_L  k0, GDB_FR_EPC(sp)
+-              LONG_L  $29, GDB_FR_REG29(sp)           /* Deallocate stack */
+-              jr      k0
+-              rfe
+-#else
+-              LONG_L  sp, GDB_FR_REG29(sp)            /* Deallocate stack */
 -
--at 0x0000014c : */    0x6a350000,0x00000000,
--/*
--    MOVE DSA2 + 0xff TO SFBR WITH CARRY
+-              .set    mips3
+-              eret
+-              .set    mips0
+-#endif
+-              .set    at
+-              .set    reorder
+-              END(trap_low)
 -
--at 0x0000014e : */    0x7712ff00,0x00000000,
--/*
--    MOVE SFBR TO SCRATCH2
+-LEAF(kgdb_read_byte)
+-4:            lb      t0, (a0)
+-              sb      t0, (a1)
+-              li      v0, 0
+-              jr      ra
+-              .section __ex_table,"a"
+-              PTR     4b, kgdbfault
+-              .previous
+-              END(kgdb_read_byte)
 -
--at 0x00000150 : */    0x6a360000,0x00000000,
--/*
--    MOVE DSA3 + 0xff TO SFBR WITH CARRY
+-LEAF(kgdb_write_byte)
+-5:            sb      a0, (a1)
+-              li      v0, 0
+-              jr      ra
+-              .section __ex_table,"a"
+-              PTR     5b, kgdbfault
+-              .previous
+-              END(kgdb_write_byte)
 -
--at 0x00000152 : */    0x7713ff00,0x00000000,
--/*
--    MOVE SFBR TO SCRATCH3
+-              .type   kgdbfault@function
+-              .ent    kgdbfault
 -
--at 0x00000154 : */    0x6a370000,0x00000000,
--/*
+-kgdbfault:    li      v0, -EFAULT
+-              jr      ra
+-              .end    kgdbfault
+diff -Nurb linux-2.6.22-590/arch/mips/kernel/traps.c linux-2.6.22-570/arch/mips/kernel/traps.c
+--- linux-2.6.22-590/arch/mips/kernel/traps.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/kernel/traps.c  2008-01-23 19:16:03.000000000 -0500
+@@ -10,8 +10,6 @@
+  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+  * Copyright (C) 2000, 01 MIPS Technologies, Inc.
+  * Copyright (C) 2002, 2003, 2004, 2005  Maciej W. Rozycki
+- *
+- * KGDB specific changes - Manish Lachwani (mlachwani@mvista.com)
+  */
+ #include <linux/bug.h>
+ #include <linux/init.h>
+@@ -23,7 +21,6 @@
+ #include <linux/kallsyms.h>
+ #include <linux/bootmem.h>
+ #include <linux/interrupt.h>
+-#include <linux/kgdb.h>
+ #include <asm/bootinfo.h>
+ #include <asm/branch.h>
+@@ -45,7 +42,6 @@
+ #include <asm/watch.h>
+ #include <asm/types.h>
+ #include <asm/stacktrace.h>
+-#include <asm/kdebug.h>
+ extern asmlinkage void handle_int(void);
+ extern asmlinkage void handle_tlbm(void);
+@@ -1449,11 +1445,6 @@
+       extern char except_vec4;
+       unsigned long i;
+-#if defined(CONFIG_KGDB)
+-      if (kgdb_early_setup)
+-              return; /* Already done */
+-#endif
 -
--    
--    MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4
+       if (cpu_has_veic || cpu_has_vint)
+               ebase = (unsigned long) alloc_bootmem_low_pages (0x200 + VECTORSPACING*64);
+       else
+diff -Nurb linux-2.6.22-590/arch/mips/mips-boards/atlas/Makefile linux-2.6.22-570/arch/mips/mips-boards/atlas/Makefile
+--- linux-2.6.22-590/arch/mips/mips-boards/atlas/Makefile      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/mips-boards/atlas/Makefile      2007-07-08 19:32:17.000000000 -0400
+@@ -17,3 +17,4 @@
+ #
+ obj-y                 := atlas_int.o atlas_setup.o
++obj-$(CONFIG_KGDB)    += atlas_gdb.o
+diff -Nurb linux-2.6.22-590/arch/mips/mips-boards/atlas/atlas_gdb.c linux-2.6.22-570/arch/mips/mips-boards/atlas/atlas_gdb.c
+--- linux-2.6.22-590/arch/mips/mips-boards/atlas/atlas_gdb.c   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/mips-boards/atlas/atlas_gdb.c   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,97 @@
++/*
++ * Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
++ *
++ *  This program is free software; you can distribute it and/or modify it
++ *  under the terms of the GNU General Public License (Version 2) as
++ *  published by the Free Software Foundation.
++ *
++ *  This program is distributed in the hope 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.
++ *
++ * This is the interface to the remote debugger stub.
++ */
++#include <asm/io.h>
++#include <asm/mips-boards/atlas.h>
++#include <asm/mips-boards/saa9730_uart.h>
++
++#define INB(a)     inb((unsigned long)a)
++#define OUTB(x,a)  outb(x,(unsigned long)a)
++
++/*
++ * This is the interface to the remote debugger stub
++ * if the Philips part is used for the debug port,
++ * called from the platform setup code.
++ */
++void *saa9730_base = (void *)ATLAS_SAA9730_REG;
++
++static int saa9730_kgdb_active = 0;
++
++#define SAA9730_BAUDCLOCK(baud) (((ATLAS_SAA9730_BAUDCLOCK/(baud))/16)-1)
++
++int saa9730_kgdb_hook(int speed)
++{
++      int baudclock;
++      t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
++
++        /*
++         * Clear all interrupts
++         */
++      (void) INB(&kgdb_uart->Lsr);
++      (void) INB(&kgdb_uart->Msr);
++      (void) INB(&kgdb_uart->Thr_Rbr);
++      (void) INB(&kgdb_uart->Iir_Fcr);
++
++        /*
++         * Now, initialize the UART
++         */
++      /* 8 data bits, one stop bit, no parity */
++      OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr);
++
++      baudclock = SAA9730_BAUDCLOCK(speed);
++
++      OUTB((baudclock >> 16) & 0xff, &kgdb_uart->BaudDivMsb);
++      OUTB( baudclock        & 0xff, &kgdb_uart->BaudDivLsb);
++
++      /* Set RTS/DTR active */
++      OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr);
++      saa9730_kgdb_active = 1;
++
++      return speed;
++}
++
++int saa9730_putDebugChar(char c)
++{
++      t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
++
++        if (!saa9730_kgdb_active) {     /* need to init device first */
++                return 0;
++        }
++
++        while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE))
++                ;
++      OUTB(c, &kgdb_uart->Thr_Rbr);
++
++        return 1;
++}
++
++char saa9730_getDebugChar(void)
++{
++      t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
++      char c;
++
++        if (!saa9730_kgdb_active) {     /* need to init device first */
++                return 0;
++        }
++        while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR))
++                ;
++
++      c = INB(&kgdb_uart->Thr_Rbr);
++      return(c);
++}
+diff -Nurb linux-2.6.22-590/arch/mips/mips-boards/atlas/atlas_setup.c linux-2.6.22-570/arch/mips/mips-boards/atlas/atlas_setup.c
+--- linux-2.6.22-590/arch/mips/mips-boards/atlas/atlas_setup.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/mips-boards/atlas/atlas_setup.c 2007-07-08 19:32:17.000000000 -0400
+@@ -37,6 +37,10 @@
+ extern void mips_time_init(void);
+ extern unsigned long mips_rtc_get_time(void);
++#ifdef CONFIG_KGDB
++extern void kgdb_config(void);
++#endif
++
+ static void __init serial_init(void);
+ const char *get_system_type(void)
+@@ -54,6 +58,9 @@
+       serial_init ();
++#ifdef CONFIG_KGDB
++      kgdb_config();
++#endif
+       mips_reboot_setup();
+       board_time_init = mips_time_init;
+diff -Nurb linux-2.6.22-590/arch/mips/mips-boards/generic/gdb_hook.c linux-2.6.22-570/arch/mips/mips-boards/generic/gdb_hook.c
+--- linux-2.6.22-590/arch/mips/mips-boards/generic/gdb_hook.c  1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/mips-boards/generic/gdb_hook.c  2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,133 @@
++/*
++ * Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
++ *
++ *  This program is free software; you can distribute it and/or modify it
++ *  under the terms of the GNU General Public License (Version 2) as
++ *  published by the Free Software Foundation.
++ *
++ *  This program is distributed in the hope 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.
++ *
++ * This is the interface to the remote debugger stub.
++ */
++#include <linux/types.h>
++#include <linux/serial.h>
++#include <linux/serialP.h>
++#include <linux/serial_reg.h>
++
++#include <asm/serial.h>
++#include <asm/io.h>
++
++static struct serial_state rs_table[] = {
++      SERIAL_PORT_DFNS        /* Defined in serial.h */
++};
++
++static struct async_struct kdb_port_info = {0};
++
++int (*generic_putDebugChar)(char);
++char (*generic_getDebugChar)(void);
++
++static __inline__ unsigned int serial_in(struct async_struct *info, int offset)
++{
++      return inb(info->port + offset);
++}
++
++static __inline__ void serial_out(struct async_struct *info, int offset,
++                              int value)
++{
++      outb(value, info->port+offset);
++}
++
++int rs_kgdb_hook(int tty_no, int speed) {
++      int t;
++      struct serial_state *ser = &rs_table[tty_no];
++
++      kdb_port_info.state = ser;
++      kdb_port_info.magic = SERIAL_MAGIC;
++      kdb_port_info.port = ser->port;
++      kdb_port_info.flags = ser->flags;
++
++      /*
++       * Clear all interrupts
++       */
++      serial_in(&kdb_port_info, UART_LSR);
++      serial_in(&kdb_port_info, UART_RX);
++      serial_in(&kdb_port_info, UART_IIR);
++      serial_in(&kdb_port_info, UART_MSR);
++
++      /*
++       * Now, initialize the UART
++       */
++      serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);   /* reset DLAB */
++      if (kdb_port_info.flags & ASYNC_FOURPORT) {
++              kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS;
++              t = UART_MCR_DTR | UART_MCR_OUT1;
++      } else {
++              kdb_port_info.MCR
++                      = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
++              t = UART_MCR_DTR | UART_MCR_RTS;
++      }
++
++      kdb_port_info.MCR = t;          /* no interrupts, please */
++      serial_out(&kdb_port_info, UART_MCR, kdb_port_info.MCR);
++
++      /*
++       * and set the speed of the serial port
++       */
++      if (speed == 0)
++              speed = 9600;
++
++      t = kdb_port_info.state->baud_base / speed;
++      /* set DLAB */
++      serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB);
++      serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */
++      serial_out(&kdb_port_info, UART_DLM, t >> 8);  /* MS of divisor */
++      /* reset DLAB */
++      serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);
++
++      return speed;
++}
++
++int putDebugChar(char c)
++{
++      return generic_putDebugChar(c);
++}
++
++char getDebugChar(void)
++{
++      return generic_getDebugChar();
++}
++
++int rs_putDebugChar(char c)
++{
++
++      if (!kdb_port_info.state) {     /* need to init device first */
++              return 0;
++      }
++
++      while ((serial_in(&kdb_port_info, UART_LSR) & UART_LSR_THRE) == 0)
++              ;
++
++      serial_out(&kdb_port_info, UART_TX, c);
++
++      return 1;
++}
++
++char rs_getDebugChar(void)
++{
++      if (!kdb_port_info.state) {     /* need to init device first */
++              return 0;
++      }
++
++      while (!(serial_in(&kdb_port_info, UART_LSR) & 1))
++              ;
++
++      return serial_in(&kdb_port_info, UART_RX);
++}
+diff -Nurb linux-2.6.22-590/arch/mips/mips-boards/generic/init.c linux-2.6.22-570/arch/mips/mips-boards/generic/init.c
+--- linux-2.6.22-590/arch/mips/mips-boards/generic/init.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/mips-boards/generic/init.c      2007-07-08 19:32:17.000000000 -0400
+@@ -37,6 +37,15 @@
+ #include <asm/mips-boards/malta.h>
++#ifdef CONFIG_KGDB
++extern int rs_kgdb_hook(int, int);
++extern int rs_putDebugChar(char);
++extern char rs_getDebugChar(void);
++extern int saa9730_kgdb_hook(int);
++extern int saa9730_putDebugChar(char);
++extern char saa9730_getDebugChar(void);
++#endif
++
+ int prom_argc;
+ int *_prom_argv, *_prom_envp;
+@@ -164,6 +173,59 @@
+ }
+ #endif
++#ifdef CONFIG_KGDB
++void __init kgdb_config (void)
++{
++      extern int (*generic_putDebugChar)(char);
++      extern char (*generic_getDebugChar)(void);
++      char *argptr;
++      int line, speed;
++
++      argptr = prom_getcmdline();
++      if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
++              argptr += strlen("kgdb=ttyS");
++              if (*argptr != '0' && *argptr != '1')
++                      printk("KGDB: Unknown serial line /dev/ttyS%c, "
++                             "falling back to /dev/ttyS1\n", *argptr);
++              line = *argptr == '0' ? 0 : 1;
++              printk("KGDB: Using serial line /dev/ttyS%d for session\n", line);
++
++              speed = 0;
++              if (*++argptr == ',')
++              {
++                      int c;
++                      while ((c = *++argptr) && ('0' <= c && c <= '9'))
++                              speed = speed * 10 + c - '0';
++              }
++#ifdef CONFIG_MIPS_ATLAS
++              if (line == 1) {
++                      speed = saa9730_kgdb_hook(speed);
++                      generic_putDebugChar = saa9730_putDebugChar;
++                      generic_getDebugChar = saa9730_getDebugChar;
++              }
++              else
++#endif
++              {
++                      speed = rs_kgdb_hook(line, speed);
++                      generic_putDebugChar = rs_putDebugChar;
++                      generic_getDebugChar = rs_getDebugChar;
++              }
++
++              pr_info("KGDB: Using serial line /dev/ttyS%d at %d for "
++                      "session, please connect your debugger\n",
++                      line ? 1 : 0, speed);
++
++              {
++                      char *s;
++                      for (s = "Please connect GDB to this port\r\n"; *s; )
++                              generic_putDebugChar (*s++);
++              }
++
++              /* Breakpoint is invoked after interrupts are initialised */
++      }
++}
++#endif
++
+ void __init mips_nmi_setup (void)
+ {
+       void *base;
+diff -Nurb linux-2.6.22-590/arch/mips/mips-boards/malta/malta_setup.c linux-2.6.22-570/arch/mips/mips-boards/malta/malta_setup.c
+--- linux-2.6.22-590/arch/mips/mips-boards/malta/malta_setup.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/mips-boards/malta/malta_setup.c 2007-07-08 19:32:17.000000000 -0400
+@@ -39,6 +39,10 @@
+ extern void mips_time_init(void);
+ extern unsigned long mips_rtc_get_time(void);
++#ifdef CONFIG_KGDB
++extern void kgdb_config(void);
++#endif
++
+ struct resource standard_io_resources[] = {
+       { .name = "dma1", .start = 0x00, .end = 0x1f, .flags = IORESOURCE_BUSY },
+       { .name = "timer", .start = 0x40, .end = 0x5f, .flags = IORESOURCE_BUSY },
+@@ -95,6 +99,10 @@
+        */
+       enable_dma(4);
++#ifdef CONFIG_KGDB
++      kgdb_config ();
++#endif
++
+       if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) {
+               char *argptr;
+diff -Nurb linux-2.6.22-590/arch/mips/mm/extable.c linux-2.6.22-570/arch/mips/mm/extable.c
+--- linux-2.6.22-590/arch/mips/mm/extable.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/mm/extable.c    2007-07-08 19:32:17.000000000 -0400
+@@ -3,7 +3,6 @@
+  */
+ #include <linux/module.h>
+ #include <linux/spinlock.h>
+-#include <linux/kgdb.h>
+ #include <asm/branch.h>
+ #include <asm/uaccess.h>
+@@ -17,12 +16,6 @@
+               return 1;
+       }
+-#ifdef CONFIG_KGDB
+-      if (atomic_read(&debugger_active) && kgdb_may_fault)
+-              /* Restore our previous state. */
+-              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+-              /* Not reached. */
+-#endif
+       return 0;
+ }
+diff -Nurb linux-2.6.22-590/arch/mips/momentum/ocelot_c/Makefile linux-2.6.22-570/arch/mips/momentum/ocelot_c/Makefile
+--- linux-2.6.22-590/arch/mips/momentum/ocelot_c/Makefile      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/momentum/ocelot_c/Makefile      2007-07-08 19:32:17.000000000 -0400
+@@ -4,3 +4,5 @@
+ obj-y                 += cpci-irq.o irq.o platform.o prom.o reset.o \
+                          setup.o uart-irq.o
++
++obj-$(CONFIG_KGDB)    += dbg_io.o
+diff -Nurb linux-2.6.22-590/arch/mips/momentum/ocelot_c/dbg_io.c linux-2.6.22-570/arch/mips/momentum/ocelot_c/dbg_io.c
+--- linux-2.6.22-590/arch/mips/momentum/ocelot_c/dbg_io.c      1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/momentum/ocelot_c/dbg_io.c      2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,121 @@
++
++#include <asm/serial.h> /* For the serial port location and base baud */
++
++/* --- CONFIG --- */
++
++typedef unsigned char uint8;
++typedef unsigned int uint32;
++
++/* --- END OF CONFIG --- */
++
++#define         UART16550_BAUD_2400             2400
++#define         UART16550_BAUD_4800             4800
++#define         UART16550_BAUD_9600             9600
++#define         UART16550_BAUD_19200            19200
++#define         UART16550_BAUD_38400            38400
++#define         UART16550_BAUD_57600            57600
++#define         UART16550_BAUD_115200           115200
++
++#define         UART16550_PARITY_NONE           0
++#define         UART16550_PARITY_ODD            0x08
++#define         UART16550_PARITY_EVEN           0x18
++#define         UART16550_PARITY_MARK           0x28
++#define         UART16550_PARITY_SPACE          0x38
++
++#define         UART16550_DATA_5BIT             0x0
++#define         UART16550_DATA_6BIT             0x1
++#define         UART16550_DATA_7BIT             0x2
++#define         UART16550_DATA_8BIT             0x3
++
++#define         UART16550_STOP_1BIT             0x0
++#define         UART16550_STOP_2BIT             0x4
++
++/* ----------------------------------------------------- */
++
++/* === CONFIG === */
++
++/* [jsun] we use the second serial port for kdb */
++#define         BASE                    OCELOT_SERIAL1_BASE
++#define         MAX_BAUD                OCELOT_BASE_BAUD
++
++/* === END OF CONFIG === */
++
++#define         REG_OFFSET              4
++
++/* register offset */
++#define         OFS_RCV_BUFFER          0
++#define         OFS_TRANS_HOLD          0
++#define         OFS_SEND_BUFFER         0
++#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
++#define         OFS_INTR_ID             (2*REG_OFFSET)
++#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
++#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
++#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
++#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
++#define         OFS_LINE_STATUS         (5*REG_OFFSET)
++#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
++#define         OFS_RS232_INPUT         (6*REG_OFFSET)
++#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
++
++#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
++#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
++
++
++/* memory-mapped read/write of the port */
++#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
++#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
++
++void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
++{
++      /* disable interrupts */
++      UART16550_WRITE(OFS_INTR_ENABLE, 0);
++
++      /* set up baud rate */
++      {
++              uint32 divisor;
++
++              /* set DIAB bit */
++              UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
++
++              /* set divisor */
++              divisor = MAX_BAUD / baud;
++              UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
++              UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
++
++              /* clear DIAB bit */
++              UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
++      }
++
++      /* set data format */
++      UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
++}
++
++static int remoteDebugInitialized = 0;
++
++uint8 getDebugChar(void)
++{
++      if (!remoteDebugInitialized) {
++              remoteDebugInitialized = 1;
++              debugInit(UART16550_BAUD_38400,
++                        UART16550_DATA_8BIT,
++                        UART16550_PARITY_NONE, UART16550_STOP_1BIT);
++      }
++
++      while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
++      return UART16550_READ(OFS_RCV_BUFFER);
++}
++
++
++int putDebugChar(uint8 byte)
++{
++      if (!remoteDebugInitialized) {
++              remoteDebugInitialized = 1;
++              debugInit(UART16550_BAUD_38400,
++                        UART16550_DATA_8BIT,
++                        UART16550_PARITY_NONE, UART16550_STOP_1BIT);
++      }
++
++      while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
++      UART16550_WRITE(OFS_SEND_BUFFER, byte);
++      return 1;
++}
+diff -Nurb linux-2.6.22-590/arch/mips/pci/fixup-atlas.c linux-2.6.22-570/arch/mips/pci/fixup-atlas.c
+--- linux-2.6.22-590/arch/mips/pci/fixup-atlas.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/pci/fixup-atlas.c       2007-07-08 19:32:17.000000000 -0400
+@@ -68,3 +68,24 @@
+ {
+       return 0;
+ }
++
++#ifdef CONFIG_KGDB
++/*
++ * The PCI scan may have moved the saa9730 I/O address, so reread
++ * the address here.
++ * This does mean that it's not possible to debug the PCI bus configuration
++ * code, but it is better than nothing...
++ */
++
++static void atlas_saa9730_base_fixup (struct pci_dev *pdev)
++{
++      extern void *saa9730_base;
++      if (pdev->bus == 0 && PCI_SLOT(pdev->devfn) == 19)
++              (void) pci_read_config_dword (pdev, 0x14, (u32 *)&saa9730_base);
++      printk ("saa9730_base = %x\n", saa9730_base);
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730,
++       atlas_saa9730_base_fixup);
++
++#endif
+diff -Nurb linux-2.6.22-590/arch/mips/philips/pnx8550/common/Makefile linux-2.6.22-570/arch/mips/philips/pnx8550/common/Makefile
+--- linux-2.6.22-590/arch/mips/philips/pnx8550/common/Makefile 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/philips/pnx8550/common/Makefile 2007-07-08 19:32:17.000000000 -0400
+@@ -24,3 +24,4 @@
+ obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o
+ obj-$(CONFIG_PCI) += pci.o
++obj-$(CONFIG_KGDB) += gdb_hook.o
+diff -Nurb linux-2.6.22-590/arch/mips/philips/pnx8550/common/gdb_hook.c linux-2.6.22-570/arch/mips/philips/pnx8550/common/gdb_hook.c
+--- linux-2.6.22-590/arch/mips/philips/pnx8550/common/gdb_hook.c       1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/philips/pnx8550/common/gdb_hook.c       2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,109 @@
++/*
++ * Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
++ *
++ * ########################################################################
++ *
++ *  This program is free software; you can distribute it and/or modify it
++ *  under the terms of the GNU General Public License (Version 2) as
++ *  published by the Free Software Foundation.
++ *
++ *  This program is distributed in the hope 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.
++ *
++ * ########################################################################
++ *
++ * This is the interface to the remote debugger stub.
++ *
++ */
++#include <linux/types.h>
++#include <linux/serial.h>
++#include <linux/serialP.h>
++#include <linux/serial_reg.h>
++#include <linux/serial_ip3106.h>
++
++#include <asm/serial.h>
++#include <asm/io.h>
++
++#include <uart.h>
++
++static struct serial_state rs_table[IP3106_NR_PORTS] = {
++};
++static struct async_struct kdb_port_info = {0};
++
++void rs_kgdb_hook(int tty_no)
++{
++      struct serial_state *ser = &rs_table[tty_no];
++
++      kdb_port_info.state = ser;
++      kdb_port_info.magic = SERIAL_MAGIC;
++      kdb_port_info.port  = tty_no;
++      kdb_port_info.flags = ser->flags;
++
++      /*
++       * Clear all interrupts
++       */
++      /* Clear all the transmitter FIFO counters (pointer and status) */
++      ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_TX_RST;
++      /* Clear all the receiver FIFO counters (pointer and status) */
++      ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_RX_RST;
++      /* Clear all interrupts */
++      ip3106_iclr(UART_BASE, tty_no) = IP3106_UART_INT_ALLRX |
++              IP3106_UART_INT_ALLTX;
++
++      /*
++       * Now, initialize the UART
++       */
++      ip3106_lcr(UART_BASE, tty_no) = IP3106_UART_LCR_8BIT;
++      ip3106_baud(UART_BASE, tty_no) = 5; // 38400 Baud
++}
++
++int putDebugChar(char c)
++{
++      /* Wait until FIFO not full */
++      while (((ip3106_fifo(UART_BASE, kdb_port_info.port) & IP3106_UART_FIFO_TXFIFO) >> 16) >= 16)
++              ;
++      /* Send one char */
++      ip3106_fifo(UART_BASE, kdb_port_info.port) = c;
++
++      return 1;
++}
++
++char getDebugChar(void)
++{
++      char ch;
++
++      /* Wait until there is a char in the FIFO */
++      while (!((ip3106_fifo(UART_BASE, kdb_port_info.port) &
++                                      IP3106_UART_FIFO_RXFIFO) >> 8))
++              ;
++      /* Read one char */
++      ch = ip3106_fifo(UART_BASE, kdb_port_info.port) &
++              IP3106_UART_FIFO_RBRTHR;
++      /* Advance the RX FIFO read pointer */
++      ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_RX_NEXT;
++      return (ch);
++}
++
++void rs_disable_debug_interrupts(void)
++{
++      ip3106_ien(UART_BASE, kdb_port_info.port) = 0; /* Disable all interrupts */
++}
++
++void rs_enable_debug_interrupts(void)
++{
++      /* Clear all the transmitter FIFO counters (pointer and status) */
++      ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_TX_RST;
++      /* Clear all the receiver FIFO counters (pointer and status) */
++      ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_RX_RST;
++      /* Clear all interrupts */
++      ip3106_iclr(UART_BASE, kdb_port_info.port) = IP3106_UART_INT_ALLRX |
++              IP3106_UART_INT_ALLTX;
++      ip3106_ien(UART_BASE, kdb_port_info.port)  = IP3106_UART_INT_ALLRX; /* Enable RX interrupts */
++}
+diff -Nurb linux-2.6.22-590/arch/mips/philips/pnx8550/common/setup.c linux-2.6.22-570/arch/mips/philips/pnx8550/common/setup.c
+--- linux-2.6.22-590/arch/mips/philips/pnx8550/common/setup.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/philips/pnx8550/common/setup.c  2007-07-08 19:32:17.000000000 -0400
+@@ -145,5 +145,16 @@
+               ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
+       }
++#ifdef CONFIG_KGDB
++      argptr = prom_getcmdline();
++      if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
++              int line;
++              argptr += strlen("kgdb=ttyS");
++              line = *argptr == '0' ? 0 : 1;
++              rs_kgdb_hook(line);
++              pr_info("KGDB: Using ttyS%i for session, "
++                      "please connect your debugger\n", line ? 1 : 0);
++      }
++#endif
+       return;
+ }
+diff -Nurb linux-2.6.22-590/arch/mips/pmc-sierra/yosemite/Makefile linux-2.6.22-570/arch/mips/pmc-sierra/yosemite/Makefile
+--- linux-2.6.22-590/arch/mips/pmc-sierra/yosemite/Makefile    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/pmc-sierra/yosemite/Makefile    2007-07-08 19:32:17.000000000 -0400
+@@ -4,4 +4,5 @@
+ obj-y    += irq.o i2c-yosemite.o prom.o py-console.o setup.o
++obj-$(CONFIG_KGDB)            += dbg_io.o
+ obj-$(CONFIG_SMP)             += smp.o
+diff -Nurb linux-2.6.22-590/arch/mips/pmc-sierra/yosemite/dbg_io.c linux-2.6.22-570/arch/mips/pmc-sierra/yosemite/dbg_io.c
+--- linux-2.6.22-590/arch/mips/pmc-sierra/yosemite/dbg_io.c    1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/pmc-sierra/yosemite/dbg_io.c    2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,180 @@
++/*
++ * Copyright 2003 PMC-Sierra
++ * Author: Manish Lachwani (lachwani@pmc-sierra.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  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.
++ */
++
++/*
++ * Support for KGDB for the Yosemite board. We make use of single serial
++ * port to be used for KGDB as well as console. The second serial port
++ * seems to be having a problem. Single IRQ is allocated for both the
++ * ports. Hence, the interrupt routing code needs to figure out whether
++ * the interrupt came from channel A or B.
++ */
++
++#include <asm/serial.h>
++
++/*
++ * Baud rate, Parity, Data and Stop bit settings for the
++ * serial port on the Yosemite. Note that the Early printk
++ * patch has been added. So, we should be all set to go
++ */
++#define       YOSEMITE_BAUD_2400      2400
++#define       YOSEMITE_BAUD_4800      4800
++#define       YOSEMITE_BAUD_9600      9600
++#define       YOSEMITE_BAUD_19200     19200
++#define       YOSEMITE_BAUD_38400     38400
++#define       YOSEMITE_BAUD_57600     57600
++#define       YOSEMITE_BAUD_115200    115200
++
++#define       YOSEMITE_PARITY_NONE    0
++#define       YOSEMITE_PARITY_ODD     0x08
++#define       YOSEMITE_PARITY_EVEN    0x18
++#define       YOSEMITE_PARITY_MARK    0x28
++#define       YOSEMITE_PARITY_SPACE   0x38
++
++#define       YOSEMITE_DATA_5BIT      0x0
++#define       YOSEMITE_DATA_6BIT      0x1
++#define       YOSEMITE_DATA_7BIT      0x2
++#define       YOSEMITE_DATA_8BIT      0x3
++
++#define       YOSEMITE_STOP_1BIT      0x0
++#define       YOSEMITE_STOP_2BIT      0x4
++
++/* This is crucial */
++#define       SERIAL_REG_OFS          0x1
++
++#define       SERIAL_RCV_BUFFER       0x0
++#define       SERIAL_TRANS_HOLD       0x0
++#define       SERIAL_SEND_BUFFER      0x0
++#define       SERIAL_INTR_ENABLE      (1 * SERIAL_REG_OFS)
++#define       SERIAL_INTR_ID          (2 * SERIAL_REG_OFS)
++#define       SERIAL_DATA_FORMAT      (3 * SERIAL_REG_OFS)
++#define       SERIAL_LINE_CONTROL     (3 * SERIAL_REG_OFS)
++#define       SERIAL_MODEM_CONTROL    (4 * SERIAL_REG_OFS)
++#define       SERIAL_RS232_OUTPUT     (4 * SERIAL_REG_OFS)
++#define       SERIAL_LINE_STATUS      (5 * SERIAL_REG_OFS)
++#define       SERIAL_MODEM_STATUS     (6 * SERIAL_REG_OFS)
++#define       SERIAL_RS232_INPUT      (6 * SERIAL_REG_OFS)
++#define       SERIAL_SCRATCH_PAD      (7 * SERIAL_REG_OFS)
++
++#define       SERIAL_DIVISOR_LSB      (0 * SERIAL_REG_OFS)
++#define       SERIAL_DIVISOR_MSB      (1 * SERIAL_REG_OFS)
++
++/*
++ * Functions to READ and WRITE to serial port 0
++ */
++#define       SERIAL_READ(ofs)                (*((volatile unsigned char*)    \
++                                      (TITAN_SERIAL_BASE + ofs)))
++
++#define       SERIAL_WRITE(ofs, val)          ((*((volatile unsigned char*)   \
++                                      (TITAN_SERIAL_BASE + ofs))) = val)
++
++/*
++ * Functions to READ and WRITE to serial port 1
++ */
++#define       SERIAL_READ_1(ofs)              (*((volatile unsigned char*)    \
++                                      (TITAN_SERIAL_BASE_1 + ofs)))
++
++#define       SERIAL_WRITE_1(ofs, val)        ((*((volatile unsigned char*)   \
++                                      (TITAN_SERIAL_BASE_1 + ofs))) = val)
++
++/*
++ * Second serial port initialization
++ */
++void init_second_port(void)
++{
++      /* Disable Interrupts */
++      SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
++      SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0x0);
++
++      {
++              unsigned int divisor;
++
++              SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x80);
++              divisor = TITAN_SERIAL_BASE_BAUD / YOSEMITE_BAUD_115200;
++              SERIAL_WRITE_1(SERIAL_DIVISOR_LSB, divisor & 0xff);
++
++              SERIAL_WRITE_1(SERIAL_DIVISOR_MSB,
++                             (divisor & 0xff00) >> 8);
++              SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
++      }
++
++      SERIAL_WRITE_1(SERIAL_DATA_FORMAT, YOSEMITE_DATA_8BIT |
++                     YOSEMITE_PARITY_NONE | YOSEMITE_STOP_1BIT);
++
++      /* Enable Interrupts */
++      SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0xf);
++}
++
++/* Initialize the serial port for KGDB debugging */
++void debugInit(unsigned int baud, unsigned char data, unsigned char parity,
++             unsigned char stop)
++{
++      /* Disable Interrupts */
++      SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
++      SERIAL_WRITE(SERIAL_INTR_ENABLE, 0x0);
++
++      {
++              unsigned int divisor;
++
++              SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x80);
++
++              divisor = TITAN_SERIAL_BASE_BAUD / baud;
++              SERIAL_WRITE(SERIAL_DIVISOR_LSB, divisor & 0xff);
++
++              SERIAL_WRITE(SERIAL_DIVISOR_MSB, (divisor & 0xff00) >> 8);
++              SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
++      }
++
++      SERIAL_WRITE(SERIAL_DATA_FORMAT, data | parity | stop);
++}
++
++static int remoteDebugInitialized = 0;
++
++unsigned char getDebugChar(void)
++{
++      if (!remoteDebugInitialized) {
++              remoteDebugInitialized = 1;
++              debugInit(YOSEMITE_BAUD_115200,
++                        YOSEMITE_DATA_8BIT,
++                        YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
++      }
++
++      while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x1) == 0);
++      return SERIAL_READ(SERIAL_RCV_BUFFER);
++}
++
++int putDebugChar(unsigned char byte)
++{
++      if (!remoteDebugInitialized) {
++              remoteDebugInitialized = 1;
++              debugInit(YOSEMITE_BAUD_115200,
++                        YOSEMITE_DATA_8BIT,
++                        YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
++      }
++
++      while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x20) == 0);
++      SERIAL_WRITE(SERIAL_SEND_BUFFER, byte);
++
++      return 1;
++}
+diff -Nurb linux-2.6.22-590/arch/mips/pmc-sierra/yosemite/irq.c linux-2.6.22-570/arch/mips/pmc-sierra/yosemite/irq.c
+--- linux-2.6.22-590/arch/mips/pmc-sierra/yosemite/irq.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/pmc-sierra/yosemite/irq.c       2007-07-08 19:32:17.000000000 -0400
+@@ -137,6 +137,10 @@
+       }
+ }
++#ifdef CONFIG_KGDB
++extern void init_second_port(void);
++#endif
++
+ /*
+  * Initialize the next level interrupt handler
+  */
+@@ -148,6 +152,11 @@
+       rm7k_cpu_irq_init();
+       rm9k_cpu_irq_init();
++#ifdef CONFIG_KGDB
++      /* At this point, initialize the second serial port */
++      init_second_port();
++#endif
++
+ #ifdef CONFIG_GDB_CONSOLE
+       register_gdb_console();
+ #endif
+diff -Nurb linux-2.6.22-590/arch/mips/sgi-ip22/ip22-setup.c linux-2.6.22-570/arch/mips/sgi-ip22/ip22-setup.c
+--- linux-2.6.22-590/arch/mips/sgi-ip22/ip22-setup.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/sgi-ip22/ip22-setup.c   2007-07-08 19:32:17.000000000 -0400
+@@ -101,6 +101,30 @@
+               add_preferred_console("arc", 0, NULL);
+       }
++#ifdef CONFIG_KGDB
++      {
++      char *kgdb_ttyd = prom_getcmdline();
++
++      if ((kgdb_ttyd = strstr(kgdb_ttyd, "kgdb=ttyd")) != NULL) {
++              int line;
++              kgdb_ttyd += strlen("kgdb=ttyd");
++              if (*kgdb_ttyd != '1' && *kgdb_ttyd != '2')
++                      printk(KERN_INFO "KGDB: Uknown serial line /dev/ttyd%c"
++                             ", falling back to /dev/ttyd1\n", *kgdb_ttyd);
++              line = *kgdb_ttyd == '2' ? 0 : 1;
++              printk(KERN_INFO "KGDB: Using serial line /dev/ttyd%d for "
++                     "session\n", line ? 1 : 2);
++              rs_kgdb_hook(line);
++
++              printk(KERN_INFO "KGDB: Using serial line /dev/ttyd%d for "
++                     "session, please connect your debugger\n", line ? 1:2);
++
++              kgdb_enabled = 1;
++              /* Breakpoints and stuff are in sgi_irq_setup() */
++      }
++      }
++#endif
++
+ #if defined(CONFIG_VT) && defined(CONFIG_SGI_NEWPORT_CONSOLE)
+       {
+               ULONG *gfxinfo;
+diff -Nurb linux-2.6.22-590/arch/mips/sgi-ip27/Makefile linux-2.6.22-570/arch/mips/sgi-ip27/Makefile
+--- linux-2.6.22-590/arch/mips/sgi-ip27/Makefile       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/sgi-ip27/Makefile       2007-07-08 19:32:17.000000000 -0400
+@@ -7,4 +7,5 @@
+          ip27-xtalk.o
+ obj-$(CONFIG_EARLY_PRINTK)    += ip27-console.o
++obj-$(CONFIG_KGDB)            += ip27-dbgio.o
+ obj-$(CONFIG_SMP)             += ip27-smp.o
+diff -Nurb linux-2.6.22-590/arch/mips/sgi-ip27/ip27-dbgio.c linux-2.6.22-570/arch/mips/sgi-ip27/ip27-dbgio.c
+--- linux-2.6.22-590/arch/mips/sgi-ip27/ip27-dbgio.c   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/sgi-ip27/ip27-dbgio.c   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,60 @@
++/*
++ *  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.
++ *
++ * Copyright 2004 Ralf Baechle <ralf@linux-mips.org>
++ */
++#include <asm/sn/addrs.h>
++#include <asm/sn/sn0/hub.h>
++#include <asm/sn/klconfig.h>
++#include <asm/sn/ioc3.h>
++#include <asm/sn/sn_private.h>
++
++#include <linux/serial.h>
++#include <linux/serial_core.h>
++#include <linux/serial_reg.h>
++
++#define IOC3_CLK        (22000000 / 3)
++#define IOC3_FLAGS      (0)
++
++static inline struct ioc3_uartregs *console_uart(void)
++{
++      struct ioc3 *ioc3;
++
++      ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(get_nasid())->memory_base;
++
++      return &ioc3->sregs.uarta;
++}
++
++unsigned char getDebugChar(void)
++{
++      struct ioc3_uartregs *uart = console_uart();
++
++      while ((uart->iu_lsr & UART_LSR_DR) == 0);
++      return uart->iu_rbr;
++}
++
++void putDebugChar(unsigned char c)
++{
++      struct ioc3_uartregs *uart = console_uart();
++
++      while ((uart->iu_lsr & UART_LSR_THRE) == 0);
++      uart->iu_thr = c;
++}
+diff -Nurb linux-2.6.22-590/arch/mips/sibyte/bcm1480/irq.c linux-2.6.22-570/arch/mips/sibyte/bcm1480/irq.c
+--- linux-2.6.22-590/arch/mips/sibyte/bcm1480/irq.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/sibyte/bcm1480/irq.c    2007-07-08 19:32:17.000000000 -0400
+@@ -57,6 +57,30 @@
+ extern unsigned long ht_eoi_space;
+ #endif
++#ifdef CONFIG_KGDB
++#include <asm/gdb-stub.h>
++extern void breakpoint(void);
++static int kgdb_irq;
++#ifdef CONFIG_GDB_CONSOLE
++extern void register_gdb_console(void);
++#endif
++
++/* kgdb is on when configured.  Pass "nokgdb" kernel arg to turn it off */
++static int kgdb_flag = 1;
++static int __init nokgdb(char *str)
++{
++      kgdb_flag = 0;
++      return 1;
++}
++__setup("nokgdb", nokgdb);
++
++/* Default to UART1 */
++int kgdb_port = 1;
++#ifdef CONFIG_SIBYTE_SB1250_DUART
++extern char sb1250_duart_present[];
++#endif
++#endif
++
+ static struct irq_chip bcm1480_irq_type = {
+       .name = "BCM1480-IMR",
+       .ack = ack_bcm1480_irq,
+@@ -370,11 +394,62 @@
+        * does its own management of IP7.
+        */
++#ifdef CONFIG_KGDB
++      imask |= STATUSF_IP6;
++#endif
+       /* Enable necessary IPs, disable the rest */
+       change_c0_status(ST0_IM, imask);
++#ifdef CONFIG_KGDB
++      if (kgdb_flag) {
++              kgdb_irq = K_BCM1480_INT_UART_0 + kgdb_port;
++
++#ifdef CONFIG_SIBYTE_SB1250_DUART
++              sb1250_duart_present[kgdb_port] = 0;
++#endif
++              /* Setup uart 1 settings, mapper */
++              /* QQQ FIXME */
++              __raw_writeq(M_DUART_IMR_BRK, IO_SPACE_BASE + A_DUART_IMRREG(kgdb_port));
++
++              bcm1480_steal_irq(kgdb_irq);
++              __raw_writeq(IMR_IP6_VAL,
++                           IO_SPACE_BASE + A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) +
++                           (kgdb_irq<<3));
++              bcm1480_unmask_irq(0, kgdb_irq);
++
++#ifdef CONFIG_GDB_CONSOLE
++              register_gdb_console();
++#endif
++              printk("Waiting for GDB on UART port %d\n", kgdb_port);
++              set_debug_traps();
++              breakpoint();
++      }
++#endif
+ }
++#ifdef CONFIG_KGDB
++
++#include <linux/delay.h>
++
++#define duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
++#define duart_in(reg)           csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
++
++static void bcm1480_kgdb_interrupt(void)
++{
++      /*
++       * Clear break-change status (allow some time for the remote
++       * host to stop the break, since we would see another
++       * interrupt on the end-of-break too)
++       */
++      kstat.irqs[smp_processor_id()][kgdb_irq]++;
++      mdelay(500);
++      duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
++                              M_DUART_RX_EN | M_DUART_TX_EN);
++      set_async_breakpoint(&get_irq_regs()->cp0_epc);
++}
++
++#endif        /* CONFIG_KGDB */
++
+ extern void bcm1480_timer_interrupt(void);
+ extern void bcm1480_mailbox_interrupt(void);
+@@ -403,6 +478,11 @@
+               bcm1480_mailbox_interrupt();
+ #endif
++#ifdef CONFIG_KGDB
++      else if (pending & CAUSEF_IP6)
++              bcm1480_kgdb_interrupt();               /* KGDB (uart 1) */
++#endif
++
+       else if (pending & CAUSEF_IP2) {
+               unsigned long long mask_h, mask_l;
+               unsigned long base;
+diff -Nurb linux-2.6.22-590/arch/mips/sibyte/cfe/setup.c linux-2.6.22-570/arch/mips/sibyte/cfe/setup.c
+--- linux-2.6.22-590/arch/mips/sibyte/cfe/setup.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/sibyte/cfe/setup.c      2007-07-08 19:32:17.000000000 -0400
+@@ -58,6 +58,10 @@
+ extern unsigned long initrd_start, initrd_end;
+ #endif
++#ifdef CONFIG_KGDB
++extern int kgdb_port;
++#endif
++
+ static void ATTRIB_NORET cfe_linux_exit(void *arg)
+ {
+       int warm = *(int *)arg;
+@@ -238,6 +242,9 @@
+       int argc = fw_arg0;
+       char **envp = (char **) fw_arg2;
+       int *prom_vec = (int *) fw_arg3;
++#ifdef CONFIG_KGDB
++      char *arg;
++#endif
+       _machine_restart   = cfe_linux_restart;
+       _machine_halt      = cfe_linux_halt;
+@@ -301,6 +308,13 @@
+               }
+       }
++#ifdef CONFIG_KGDB
++      if ((arg = strstr(arcs_cmdline,"kgdb=duart")) != NULL)
++              kgdb_port = (arg[10] == '0') ? 0 : 1;
++      else
++              kgdb_port = 1;
++#endif
++
+ #ifdef CONFIG_BLK_DEV_INITRD
+       {
+               char *ptr;
+diff -Nurb linux-2.6.22-590/arch/mips/sibyte/sb1250/Makefile linux-2.6.22-570/arch/mips/sibyte/sb1250/Makefile
+--- linux-2.6.22-590/arch/mips/sibyte/sb1250/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/sibyte/sb1250/Makefile  2007-07-08 19:32:17.000000000 -0400
+@@ -3,4 +3,3 @@
+ obj-$(CONFIG_SMP)                     += smp.o
+ obj-$(CONFIG_SIBYTE_STANDALONE)               += prom.o
+ obj-$(CONFIG_SIBYTE_BUS_WATCHER)      += bus_watcher.o
+-obj-$(CONFIG_KGDB_SIBYTE)             += kgdb_sibyte.o
+diff -Nurb linux-2.6.22-590/arch/mips/sibyte/sb1250/irq.c linux-2.6.22-570/arch/mips/sibyte/sb1250/irq.c
+--- linux-2.6.22-590/arch/mips/sibyte/sb1250/irq.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/sibyte/sb1250/irq.c     2007-07-08 19:32:17.000000000 -0400
+@@ -29,7 +29,6 @@
+ #include <asm/signal.h>
+ #include <asm/system.h>
+ #include <asm/io.h>
+-#include <asm/kgdb.h>
+ #include <asm/sibyte/sb1250_regs.h>
+ #include <asm/sibyte/sb1250_int.h>
+@@ -57,6 +56,16 @@
+ extern unsigned long ldt_eoi_space;
+ #endif
++#ifdef CONFIG_KGDB
++static int kgdb_irq;
++
++/* Default to UART1 */
++int kgdb_port = 1;
++#ifdef CONFIG_SIBYTE_SB1250_DUART
++extern char sb1250_duart_present[];
++#endif
++#endif
++
+ static struct irq_chip sb1250_irq_type = {
+       .name = "SB1250-IMR",
+       .ack = ack_sb1250_irq,
+@@ -295,11 +304,6 @@
+       unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
+               STATUSF_IP1 | STATUSF_IP0;
+-#ifdef CONFIG_KGDB
+-      if (kgdb_early_setup)
+-              return;
+-#endif
 -
--at 0x00000156 : */    0xc0000004,0x00000000,0x00000568,
+       /* Default everything to IP2 */
+       for (i = 0; i < SB1250_NR_IRQS; i++) {  /* was I0 */
+               __raw_writeq(IMR_IP2_VAL,
+@@ -345,16 +349,58 @@
+        * does its own management of IP7.
+        */
+-#ifdef CONFIG_KGDB_SIBYTE
++#ifdef CONFIG_KGDB
+       imask |= STATUSF_IP6;
+ #endif
+       /* Enable necessary IPs, disable the rest */
+       change_c0_status(ST0_IM, imask);
++
++#ifdef CONFIG_KGDB
++      if (kgdb_flag) {
++              kgdb_irq = K_INT_UART_0 + kgdb_port;
++
++#ifdef CONFIG_SIBYTE_SB1250_DUART
++              sb1250_duart_present[kgdb_port] = 0;
++#endif
++              /* Setup uart 1 settings, mapper */
++              __raw_writeq(M_DUART_IMR_BRK,
++                           IOADDR(A_DUART_IMRREG(kgdb_port)));
++
++              sb1250_steal_irq(kgdb_irq);
++              __raw_writeq(IMR_IP6_VAL,
++                           IOADDR(A_IMR_REGISTER(0,
++                                                 R_IMR_INTERRUPT_MAP_BASE) +
++                                  (kgdb_irq << 3)));
++              sb1250_unmask_irq(0, kgdb_irq);
++      }
++#endif
+ }
++#ifdef CONFIG_KGDB
++
++#include <linux/delay.h>
++
++#define duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
++#define duart_in(reg)           csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
++
++static void sb1250_kgdb_interrupt(void)
++{
++      /*
++       * Clear break-change status (allow some time for the remote
++       * host to stop the break, since we would see another
++       * interrupt on the end-of-break too)
++       */
++      kstat_this_cpu.irqs[kgdb_irq]++;
++      mdelay(500);
++      duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
++                              M_DUART_RX_EN | M_DUART_TX_EN);
++      set_async_breakpoint(&get_irq_regs()->cp0_epc);
++}
++
++#endif        /* CONFIG_KGDB */
++
+ extern void sb1250_timer_interrupt(void);
+ extern void sb1250_mailbox_interrupt(void);
+-extern void sb1250_kgdb_interrupt(void);
+ asmlinkage void plat_irq_dispatch(void)
+ {
+@@ -391,7 +437,7 @@
+               sb1250_mailbox_interrupt();
+ #endif
+-#ifdef CONFIG_KGDB_SIBYTE
++#ifdef CONFIG_KGDB
+       else if (pending & CAUSEF_IP6)                  /* KGDB (uart 1) */
+               sb1250_kgdb_interrupt();
+ #endif
+diff -Nurb linux-2.6.22-590/arch/mips/sibyte/sb1250/kgdb_sibyte.c linux-2.6.22-570/arch/mips/sibyte/sb1250/kgdb_sibyte.c
+--- linux-2.6.22-590/arch/mips/sibyte/sb1250/kgdb_sibyte.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/sibyte/sb1250/kgdb_sibyte.c     1969-12-31 19:00:00.000000000 -0500
+@@ -1,144 +0,0 @@
 -/*
--    
--jump_dsa_restore:
--    JUMP 0
+- * arch/mips/sibyte/sb1250/kgdb_sibyte.c
+- *
+- * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com
+- *
+- * 2004 (c) MontaVista Software, Inc. This file is licensed under
+- * the terms of the GNU General Public License version 2. This program
+- * is licensed "as is" without any warranty of any kind, whether express
+- * or implied.
+- */
 -
--at 0x00000159 : */    0x80080000,0x00000000,
 -/*
+- * Support for KGDB on the Broadcom Sibyte. The SWARM board
+- * for example does not have a 8250/16550 compatible serial
+- * port. Hence, we need to have a driver for the serial
+- * ports to handle KGDB.  This board needs nothing in addition
+- * to what is normally provided by the gdb portion of the stub.
+- */
 -
+-#include <linux/delay.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/init.h>
+-#include <linux/kgdb.h>
 -
--munge_disconnect:
--
--
--
--
--
--
--
--
--
-- 
--
--
--
--
--
--
--
--
--
--
--    JUMP dsa_schedule
+-#include <asm/io.h>
+-#include <asm/sibyte/sb1250.h>
+-#include <asm/sibyte/sb1250_regs.h>
+-#include <asm/sibyte/sb1250_uart.h>
+-#include <asm/sibyte/sb1250_int.h>
+-#include <asm/addrspace.h>
 -
--at 0x0000015b : */    0x80080000,0x00000178,
--/*
+-int kgdb_port = 1;
+-static int kgdb_irq;
 -
+-extern char sb1250_duart_present[];
+-extern int sb1250_steal_irq(int irq);
 -
+-/* Forward declarations. */
+-static void kgdbsibyte_init_duart(void);
+-static int kgdb_init_io(void);
 -
+-#define IMR_IP6_VAL   K_INT_MAP_I4
+-#define       duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+-#define duart_in(reg)         csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 -
+-static void kgdbsibyte_write_char(u8 c)
+-{
+-      while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0) ;
+-      duart_out(R_DUART_TX_HOLD, c);
+-}
 -
--munge_extended:
--    CLEAR ACK
+-static int kgdbsibyte_read_char(void)
+-{
+-      int ret_char;
+-      unsigned int status;
 -
--at 0x0000015d : */    0x60000040,0x00000000,
--/*
--    INT int_err_unexpected_phase, WHEN NOT MSG_IN
+-      do {
+-              status = duart_in(R_DUART_STATUS);
+-      } while ((status & M_DUART_RX_RDY) == 0);
 -
--at 0x0000015f : */    0x9f030000,0x00000000,
--/*
--    MOVE 1, msg_buf + 1, WHEN MSG_IN
+-      /*
+-       * Check for framing error
+-       */
+-      if (status & M_DUART_FRM_ERR) {
+-              kgdbsibyte_init_duart();
+-              kgdbsibyte_write_char('-');
+-              return '-';
+-      }
 -
--at 0x00000161 : */    0x0f000001,0x00000001,
--/*
--    JUMP munge_extended_2, IF 0x02
+-      ret_char = duart_in(R_DUART_RX_HOLD);
 -
--at 0x00000163 : */    0x800c0002,0x000005a4,
--/*
--    JUMP munge_extended_3, IF 0x03 
+-      return ret_char;
+-}
 -
--at 0x00000165 : */    0x800c0003,0x000005d4,
--/*
--    JUMP reject_message
+-void sb1250_kgdb_interrupt(void)
+-{
+-      int kgdb_irq = K_INT_UART_0 + kgdb_port;
 -
--at 0x00000167 : */    0x80080000,0x00000604,
--/*
+-      /*
+-       * Clear break-change status (allow some time for the remote
+-       * host to stop the break, since we would see another
+-       * interrupt on the end-of-break too)
+-       */
+-      kstat_this_cpu.irqs[kgdb_irq]++;
+-      mdelay(500);
+-      duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
+-                M_DUART_RX_EN | M_DUART_TX_EN);
+-      breakpoint();
 -
--munge_extended_2:
--    CLEAR ACK
+-}
 -
--at 0x00000169 : */    0x60000040,0x00000000,
 -/*
--    MOVE 1, msg_buf + 2, WHEN MSG_IN
+- * We use port #1 and we set it for 115200 BAUD, 8n1.
+- */
+-static void kgdbsibyte_init_duart(void)
+-{
+-      /* Set 8n1. */
+-      duart_out(R_DUART_MODE_REG_1,
+-                V_DUART_BITS_PER_CHAR_8 | V_DUART_PARITY_MODE_NONE);
+-      duart_out(R_DUART_MODE_REG_2, M_DUART_STOP_BIT_LEN_1);
+-      /* Set baud rate of 115200. */
+-      duart_out(R_DUART_CLK_SEL, V_DUART_BAUD_RATE(115200));
+-      /* Enable rx and tx */
+-      duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN);
+-}
 -
--at 0x0000016b : */    0x0f000001,0x00000002,
--/*
--    JUMP reject_message, IF NOT 0x02  ; Must be WDTR
+-static int kgdb_init_io(void)
+-{
+-#ifdef CONFIG_SIBYTE_SB1250_DUART
+-      sb1250_duart_present[kgdb_port] = 0;
+-#endif
 -
--at 0x0000016d : */    0x80040002,0x00000604,
--/*
--    CLEAR ACK
+-      kgdbsibyte_init_duart();
 -
--at 0x0000016f : */    0x60000040,0x00000000,
--/*
--    MOVE 1, msg_buf + 3, WHEN MSG_IN
+-      return 0;
+-}
 -
--at 0x00000171 : */    0x0f000001,0x00000003,
 -/*
--    INT int_msg_wdtr
+- * Hookup our IRQ line.  We will already have been initialized a
+- * this point.
+- */
+-static void __init kgdbsibyte_hookup_irq(void)
+-{
+-      /* Steal the IRQ. */
+-      kgdb_irq = K_INT_UART_0 + kgdb_port;
 -
--at 0x00000173 : */    0x98080000,0x01000000,
--/*
+-      /* Setup uart 1 settings, mapper */
+-      __raw_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port)));
 -
--munge_extended_3:
--    CLEAR ACK
+-      sb1250_steal_irq(kgdb_irq);
 -
--at 0x00000175 : */    0x60000040,0x00000000,
--/*
--    MOVE 1, msg_buf + 2, WHEN MSG_IN
+-      __raw_writeq(IMR_IP6_VAL,
+-                   IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+-                          (kgdb_irq << 3)));
 -
--at 0x00000177 : */    0x0f000001,0x00000002,
--/*
--    JUMP reject_message, IF NOT 0x01  ; Must be SDTR
+-      sb1250_unmask_irq(0, kgdb_irq);
+-}
 -
--at 0x00000179 : */    0x80040001,0x00000604,
--/*
--    CLEAR ACK
+-struct kgdb_io kgdb_io_ops = {
+-      .read_char  = kgdbsibyte_read_char,
+-      .write_char = kgdbsibyte_write_char,
+-      .init = kgdb_init_io,
+-      .late_init  = kgdbsibyte_hookup_irq,
+-};
+diff -Nurb linux-2.6.22-590/arch/mips/sibyte/swarm/Makefile linux-2.6.22-570/arch/mips/sibyte/swarm/Makefile
+--- linux-2.6.22-590/arch/mips/sibyte/swarm/Makefile   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/sibyte/swarm/Makefile   2007-07-08 19:32:17.000000000 -0400
+@@ -1 +1,3 @@
+ lib-y                         = setup.o rtc_xicor1241.o rtc_m41t81.o
++
++lib-$(CONFIG_KGDB)            += dbg_io.o
+diff -Nurb linux-2.6.22-590/arch/mips/sibyte/swarm/dbg_io.c linux-2.6.22-570/arch/mips/sibyte/swarm/dbg_io.c
+--- linux-2.6.22-590/arch/mips/sibyte/swarm/dbg_io.c   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/sibyte/swarm/dbg_io.c   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,76 @@
++/*
++ * kgdb debug routines for SiByte boards.
++ *
++ * Copyright (C) 2001 MontaVista Software Inc.
++ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
++ *
++ * 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.
++ *
++ */
++
++/* -------------------- BEGINNING OF CONFIG --------------------- */
++
++#include <linux/delay.h>
++#include <asm/io.h>
++#include <asm/sibyte/sb1250.h>
++#include <asm/sibyte/sb1250_regs.h>
++#include <asm/sibyte/sb1250_uart.h>
++#include <asm/sibyte/sb1250_int.h>
++#include <asm/addrspace.h>
++
++/*
++ * We use the second serial port for kgdb traffic.
++ *    115200, 8, N, 1.
++ */
++
++#define       BAUD_RATE               115200
++#define       CLK_DIVISOR             V_DUART_BAUD_RATE(BAUD_RATE)
++#define       DATA_BITS               V_DUART_BITS_PER_CHAR_8         /* or 7    */
++#define       PARITY                  V_DUART_PARITY_MODE_NONE        /* or even */
++#define       STOP_BITS               M_DUART_STOP_BIT_LEN_1          /* or 2    */
++
++static int duart_initialized = 0;     /* 0: need to be init'ed by kgdb */
++
++/* -------------------- END OF CONFIG --------------------- */
++extern int kgdb_port;
++
++#define       duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
++#define duart_in(reg)         csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
++
++void putDebugChar(unsigned char c);
++unsigned char getDebugChar(void);
++static void
++duart_init(int clk_divisor, int data, int parity, int stop)
++{
++      duart_out(R_DUART_MODE_REG_1, data | parity);
++      duart_out(R_DUART_MODE_REG_2, stop);
++      duart_out(R_DUART_CLK_SEL, clk_divisor);
++
++      duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN);  /* enable rx and tx */
++}
++
++void
++putDebugChar(unsigned char c)
++{
++      if (!duart_initialized) {
++              duart_initialized = 1;
++              duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
++      }
++      while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0);
++      duart_out(R_DUART_TX_HOLD, c);
++}
++
++unsigned char
++getDebugChar(void)
++{
++      if (!duart_initialized) {
++              duart_initialized = 1;
++              duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
++      }
++      while ((duart_in(R_DUART_STATUS) & M_DUART_RX_RDY) == 0) ;
++      return duart_in(R_DUART_RX_HOLD);
++}
++
+diff -Nurb linux-2.6.22-590/arch/mips/tx4927/common/Makefile linux-2.6.22-570/arch/mips/tx4927/common/Makefile
+--- linux-2.6.22-590/arch/mips/tx4927/common/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/tx4927/common/Makefile  2007-07-08 19:32:17.000000000 -0400
+@@ -9,3 +9,4 @@
+ obj-y += tx4927_prom.o tx4927_setup.o tx4927_irq.o
+ obj-$(CONFIG_TOSHIBA_FPCIB0)     += smsc_fdc37m81x.o
++obj-$(CONFIG_KGDB)                 += tx4927_dbgio.o
+diff -Nurb linux-2.6.22-590/arch/mips/tx4927/common/tx4927_dbgio.c linux-2.6.22-570/arch/mips/tx4927/common/tx4927_dbgio.c
+--- linux-2.6.22-590/arch/mips/tx4927/common/tx4927_dbgio.c    1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/tx4927/common/tx4927_dbgio.c    2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,47 @@
++/*
++ * linux/arch/mips/tx4927/common/tx4927_dbgio.c
++ *
++ * kgdb interface for gdb
++ *
++ * Author: MontaVista Software, Inc.
++ *         source@mvista.com
++ *
++ * Copyright 2001-2002 MontaVista Software 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.
++ */
++
++#include <asm/mipsregs.h>
++#include <asm/system.h>
++#include <asm/tx4927/tx4927_mips.h>
++
++u8 getDebugChar(void)
++{
++      extern u8 txx9_sio_kdbg_rd(void);
++      return (txx9_sio_kdbg_rd());
++}
++
++
++int putDebugChar(u8 byte)
++{
++      extern int txx9_sio_kdbg_wr( u8 ch );
++      return (txx9_sio_kdbg_wr(byte));
++}
+diff -Nurb linux-2.6.22-590/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c linux-2.6.22-570/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+--- linux-2.6.22-590/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c        2007-07-08 19:32:17.000000000 -0400
+@@ -76,7 +76,7 @@
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+ #endif
+-#if defined(CONFIG_SERIAL_TXX9) || defined(CONFIG_KGDB_TXX9)
++#ifdef CONFIG_SERIAL_TXX9
+ #include <linux/tty.h>
+ #include <linux/serial.h>
+ #include <linux/serial_core.h>
+@@ -973,10 +973,9 @@
+ #endif /* CONFIG_PCI */
+-#if defined (CONFIG_SERIAL_TXX9) || defined(CONFIG_KGDB_TXX9)
++#ifdef CONFIG_SERIAL_TXX9
+       {
+               extern int early_serial_txx9_setup(struct uart_port *port);
+-              extern int txx9_kgdb_add_port(int n, struct uart_port *port);
+               int i;
+               struct uart_port req;
+               for(i = 0; i < 2; i++) {
+@@ -988,12 +987,7 @@
+                       req.irq = 32 + i;
+                       req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
+                       req.uartclk = 50000000;
+-#ifdef CONFIG_SERIAL_TXX9
+                       early_serial_txx9_setup(&req);
+-#endif
+-#ifdef CONFIG_KGDB_TXX9
+-                      txx9_kgdb_add_port(i, &req);
+-#endif
+               }
+       }
+ #ifdef CONFIG_SERIAL_TXX9_CONSOLE
+@@ -1002,7 +996,7 @@
+                 strcat(argptr, " console=ttyS0,38400");
+         }
+ #endif
+-#endif /* defined(CONFIG_SERIAL_TXX9) || defined(CONFIG_KGDB_TXX9) */
++#endif
+ #ifdef CONFIG_ROOT_NFS
+         argptr = prom_getcmdline();
+diff -Nurb linux-2.6.22-590/arch/mips/tx4938/common/Makefile linux-2.6.22-570/arch/mips/tx4938/common/Makefile
+--- linux-2.6.22-590/arch/mips/tx4938/common/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/tx4938/common/Makefile  2007-07-08 19:32:17.000000000 -0400
+@@ -7,4 +7,5 @@
+ #
+ obj-y += prom.o setup.o irq.o rtc_rx5c348.o
++obj-$(CONFIG_KGDB) += dbgio.o
+diff -Nurb linux-2.6.22-590/arch/mips/tx4938/common/dbgio.c linux-2.6.22-570/arch/mips/tx4938/common/dbgio.c
+--- linux-2.6.22-590/arch/mips/tx4938/common/dbgio.c   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/mips/tx4938/common/dbgio.c   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,50 @@
++/*
++ * linux/arch/mips/tx4938/common/dbgio.c
++ *
++ * kgdb interface for gdb
++ *
++ * Author: MontaVista Software, Inc.
++ *         source@mvista.com
++ *
++ * Copyright 2005 MontaVista Software 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.
++ *
++ * Support for TX4938 in 2.6 - Hiroshi DOYU <Hiroshi_DOYU@montavista.co.jp>
++ */
++
++#include <asm/mipsregs.h>
++#include <asm/system.h>
++#include <asm/tx4938/tx4938_mips.h>
++
++extern u8 txx9_sio_kdbg_rd(void);
++extern int txx9_sio_kdbg_wr( u8 ch );
++
++u8 getDebugChar(void)
++{
++      return (txx9_sio_kdbg_rd());
++}
++
++int putDebugChar(u8 byte)
++{
++      return (txx9_sio_kdbg_wr(byte));
++}
++
+diff -Nurb linux-2.6.22-590/arch/mips/tx4938/toshiba_rbtx4938/setup.c linux-2.6.22-570/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+--- linux-2.6.22-590/arch/mips/tx4938/toshiba_rbtx4938/setup.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/mips/tx4938/toshiba_rbtx4938/setup.c 2007-07-08 19:32:17.000000000 -0400
+@@ -30,7 +30,7 @@
+ #include <asm/io.h>
+ #include <asm/bootinfo.h>
+ #include <asm/tx4938/rbtx4938.h>
+-#if defined(CONFIG_SERIAL_TXX9) || defined(CONFIG_KGDB_TXX9)
++#ifdef CONFIG_SERIAL_TXX9
+ #include <linux/tty.h>
+ #include <linux/serial.h>
+ #include <linux/serial_core.h>
+@@ -924,10 +924,9 @@
+       set_io_port_base(RBTX4938_ETHER_BASE);
+ #endif
+-#if defined (CONFIG_SERIAL_TXX9) || defined (CONFIG_KGDB_TXX9)
++#ifdef CONFIG_SERIAL_TXX9
+       {
+               extern int early_serial_txx9_setup(struct uart_port *port);
+-              extern int txx9_kgdb_add_port(int n, struct uart_port *port);
+               int i;
+               struct uart_port req;
+               for(i = 0; i < 2; i++) {
+@@ -939,12 +938,7 @@
+                       req.irq = 32 + i;
+                       req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
+                       req.uartclk = 50000000;
+-#ifdef CONFIG_SERIAL_TXX9
+                       early_serial_txx9_setup(&req);
+-#endif
+-#ifdef CONFIG_KGDB_TXX9
+-                      txx9_kgdb_add_port(i, &req);
+-#endif
+               }
+       }
+ #ifdef CONFIG_SERIAL_TXX9_CONSOLE
+diff -Nurb linux-2.6.22-590/arch/powerpc/Kconfig linux-2.6.22-570/arch/powerpc/Kconfig
+--- linux-2.6.22-590/arch/powerpc/Kconfig      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/Kconfig      2008-01-23 19:16:03.000000000 -0500
+@@ -4,7 +4,12 @@
+ mainmenu "Linux/PowerPC Kernel Configuration"
+-source "arch/powerpc/platforms/Kconfig.cputype"
++config PPC64
++      bool "64-bit kernel"
++      default n
++      help
++        This option selects whether a 32-bit or a 64-bit kernel
++        will be built.
+ config PPC_PM_NEEDS_RTC_LIB
+       bool
+@@ -127,6 +132,123 @@
+       depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL))
+       default y
++menu "Processor support"
++choice
++      prompt "Processor Type"
++      depends on PPC32
++      default 6xx
++
++config CLASSIC32
++      bool "52xx/6xx/7xx/74xx"
++      select PPC_FPU
++      select 6xx
++      help
++        There are four families of PowerPC chips supported.  The more common
++        types (601, 603, 604, 740, 750, 7400), the Motorola embedded
++        versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC
++        embedded versions (403 and 405) and the high end 64 bit Power
++        processors (POWER 3, POWER4, and IBM PPC970 also known as G5).
++
++        This option is the catch-all for 6xx types, including some of the
++        embedded versions.  Unless there is see an option for the specific
++        chip family you are using, you want this option.
++        
++        You do not want this if you are building a kernel for a 64 bit
++        IBM RS/6000 or an Apple G5, choose 6xx.
++        
++        If unsure, select this option
++        
++        Note that the kernel runs in 32-bit mode even on 64-bit chips.
++
++config PPC_82xx
++      bool "Freescale 82xx"
++      select 6xx
++      select PPC_FPU
++
++config PPC_83xx
++      bool "Freescale 83xx"
++      select 6xx
++      select FSL_SOC
++      select 83xx
++      select PPC_FPU
++      select WANT_DEVICE_TREE
++
++config PPC_85xx
++      bool "Freescale 85xx"
++      select E500
++      select FSL_SOC
++      select 85xx
++      select WANT_DEVICE_TREE
++
++config PPC_86xx
++      bool "Freescale 86xx"
++      select 6xx
++      select FSL_SOC
++      select FSL_PCIE
++      select PPC_FPU
++      select ALTIVEC
++      help
++        The Freescale E600 SoCs have 74xx cores.
++
++config PPC_8xx
++      bool "Freescale 8xx"
++      select FSL_SOC
++      select 8xx
++
++config 40x
++      bool "AMCC 40x"
++      select PPC_DCR_NATIVE
++
++config 44x
++      bool "AMCC 44x"
++      select PPC_DCR_NATIVE
++      select WANT_DEVICE_TREE
++
++config E200
++      bool "Freescale e200"
++
++endchoice
++
++config POWER4_ONLY
++      bool "Optimize for POWER4"
++      depends on PPC64
++      default n
++      ---help---
++        Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
++        The resulting binary will not work on POWER3 or RS64 processors
++        when compiled with binutils 2.15 or later.
++
++config POWER3
++      bool
++      depends on PPC64
++      default y if !POWER4_ONLY
++
++config POWER4
++      depends on PPC64
++      def_bool y
++
++config 6xx
++      bool
++
++# this is temp to handle compat with arch=ppc
++config 8xx
++      bool
++
++# this is temp to handle compat with arch=ppc
++config 83xx
++      bool
++
++# this is temp to handle compat with arch=ppc
++config 85xx
++      bool
++
++config E500
++      bool
++
++config PPC_FPU
++      bool
++      default y if PPC64
++
+ config PPC_DCR_NATIVE
+       bool
+       default n
+@@ -145,6 +267,134 @@
+       depends on PPC64 # not supported on 32 bits yet
+       default n
++config 4xx
++      bool
++      depends on 40x || 44x
++      default y
++
++config BOOKE
++      bool
++      depends on E200 || E500 || 44x
++      default y
++
++config FSL_BOOKE
++      bool
++      depends on E200 || E500
++      default y
++
++config PTE_64BIT
++      bool
++      depends on 44x || E500
++      default y if 44x
++      default y if E500 && PHYS_64BIT
++
++config PHYS_64BIT
++      bool 'Large physical address support' if E500
++      depends on 44x || E500
++      select RESOURCES_64BIT
++      default y if 44x
++      ---help---
++        This option enables kernel support for larger than 32-bit physical
++        addresses.  This features is not be available on all e500 cores.
++
++        If in doubt, say N here.
++
++config ALTIVEC
++      bool "AltiVec Support"
++      depends on CLASSIC32 || POWER4
++      ---help---
++        This option enables kernel support for the Altivec extensions to the
++        PowerPC processor. The kernel currently supports saving and restoring
++        altivec registers, and turning on the 'altivec enable' bit so user
++        processes can execute altivec instructions.
++
++        This option is only usefully if you have a processor that supports
++        altivec (G4, otherwise known as 74xx series), but does not have
++        any affect on a non-altivec cpu (it does, however add code to the
++        kernel).
++
++        If in doubt, say Y here.
++
++config SPE
++      bool "SPE Support"
++      depends on E200 || E500
++      default y
++      ---help---
++        This option enables kernel support for the Signal Processing
++        Extensions (SPE) to the PowerPC processor. The kernel currently
++        supports saving and restoring SPE registers, and turning on the
++        'spe enable' bit so user processes can execute SPE instructions.
++
++        This option is only useful if you have a processor that supports
++        SPE (e500, otherwise known as 85xx series), but does not have any
++        effect on a non-spe cpu (it does, however add code to the kernel).
++
++        If in doubt, say Y here.
++
++config PPC_STD_MMU
++      bool
++      depends on 6xx || POWER3 || POWER4 || PPC64
++      default y
++
++config PPC_STD_MMU_32
++      def_bool y
++      depends on PPC_STD_MMU && PPC32
++
++config PPC_MM_SLICES
++      bool
++      default y if HUGETLB_PAGE
++      default n
++
++config VIRT_CPU_ACCOUNTING
++      bool "Deterministic task and CPU time accounting"
++      depends on PPC64
++      default y
++      help
++        Select this option to enable more accurate task and CPU time
++        accounting.  This is done by reading a CPU counter on each
++        kernel entry and exit and on transitions within the kernel
++        between system, softirq and hardirq state, so there is a
++        small performance impact.  This also enables accounting of
++        stolen time on logically-partitioned systems running on
++        IBM POWER5-based machines.
++
++        If in doubt, say Y here.
++
++config SMP
++      depends on PPC_STD_MMU
++      bool "Symmetric multi-processing support"
++      ---help---
++        This enables support for systems with more than one CPU. If you have
++        a system with only one CPU, say N. If you have a system with more
++        than one CPU, say Y.  Note that the kernel does not currently
++        support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
++        since they have inadequate hardware support for multiprocessor
++        operation.
++
++        If you say N here, the kernel will run on single and multiprocessor
++        machines, but will use only one CPU of a multiprocessor machine. If
++        you say Y here, the kernel will run on single-processor machines.
++        On a single-processor machine, the kernel will run faster if you say
++        N here.
++
++        If you don't know what to do here, say N.
++
++config NR_CPUS
++      int "Maximum number of CPUs (2-128)"
++      range 2 128
++      depends on SMP
++      default "32" if PPC64
++      default "4"
++
++config NOT_COHERENT_CACHE
++      bool
++      depends on 4xx || 8xx || E200
++      default y
++
++config CONFIG_CHECK_CACHE_COHERENCY
++      bool
++endmenu
++
+ source "init/Kconfig"
+ source "arch/powerpc/platforms/Kconfig"
+@@ -436,9 +686,9 @@
+       bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
+               || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \
+               || MPC7448HPC2 || PPC_PS3 || PPC_HOLLY
+-      default y if !40x && !CPM2 && !8xx && !PPC_83xx \
++      default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
+               && !PPC_85xx && !PPC_86xx
+-      default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
++      default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
+       default PCI_QSPAN if !4xx && !CPM2 && 8xx
+       select ARCH_SUPPORTS_MSI
+       help
+diff -Nurb linux-2.6.22-590/arch/powerpc/Kconfig.debug linux-2.6.22-570/arch/powerpc/Kconfig.debug
+--- linux-2.6.22-590/arch/powerpc/Kconfig.debug        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/Kconfig.debug        2007-07-08 19:32:17.000000000 -0400
+@@ -41,9 +41,52 @@
+         This option will add a small amount of overhead to all hypervisor
+         calls.
++config DEBUGGER
++      bool "Enable debugger hooks"
++      depends on DEBUG_KERNEL
++      help
++        Include in-kernel hooks for kernel debuggers. Unless you are
++        intending to debug the kernel, say N here.
++
++config KGDB
++      bool "Include kgdb kernel debugger"
++      depends on DEBUGGER && (BROKEN || PPC_GEN550 || 4xx)
++      select DEBUG_INFO
++      help
++        Include in-kernel hooks for kgdb, the Linux kernel source level
++        debugger.  See <http://kgdb.sourceforge.net/> for more information.
++        Unless you are intending to debug the kernel, say N here.
++
++choice
++      prompt "Serial Port"
++      depends on KGDB
++      default KGDB_TTYS1
++
++config KGDB_TTYS0
++      bool "ttyS0"
++
++config KGDB_TTYS1
++      bool "ttyS1"
++
++config KGDB_TTYS2
++      bool "ttyS2"
++
++config KGDB_TTYS3
++      bool "ttyS3"
++
++endchoice
++
++config KGDB_CONSOLE
++      bool "Enable serial console thru kgdb port"
++      depends on KGDB && 8xx || CPM2
++      help
++        If you enable this, all serial console messages will be sent
++        over the gdb stub.
++        If unsure, say N.
++
+ config XMON
+       bool "Include xmon kernel debugger"
+-      depends on DEBUG_KERNEL
++      depends on DEBUGGER
+       help
+         Include in-kernel hooks for the xmon kernel monitor/debugger.
+         Unless you are intending to debug the kernel, say N here.
+@@ -73,11 +116,6 @@
+         to say Y here, unless you're building for a memory-constrained
+         system.
+-config DEBUGGER
+-      bool
+-      depends on KGDB || XMON
+-      default y
 -
--at 0x0000017b : */    0x60000040,0x00000000,
--/*
--    MOVE 2, msg_buf + 3, WHEN MSG_IN
+ config IRQSTACKS
+       bool "Use separate kernel stacks when processing interrupts"
+       depends on PPC64
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/44x.c linux-2.6.22-570/arch/powerpc/boot/44x.c
+--- linux-2.6.22-590/arch/powerpc/boot/44x.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/44x.c   2007-07-08 19:32:17.000000000 -0400
+@@ -38,48 +38,3 @@
+       dt_fixup_memory(0, memsize);
+ }
 -
--at 0x0000017d : */    0x0f000002,0x00000003,
--/*
--    INT int_msg_sdtr
+-#define SPRN_DBCR0            0x134
+-#define   DBCR0_RST_SYSTEM    0x30000000
 -
--at 0x0000017f : */    0x98080000,0x01010000,
--/*
+-void ibm44x_dbcr_reset(void)
+-{
+-      unsigned long tmp;
 -
--ENTRY reject_message
--reject_message:
--    SET ATN
+-      asm volatile (
+-              "mfspr  %0,%1\n"
+-              "oris   %0,%0,%2@h\n"
+-              "mtspr  %1,%0"
+-              : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
+-              );
 -
--at 0x00000181 : */    0x58000008,0x00000000,
--/*
--    CLEAR ACK
+-}
 -
--at 0x00000183 : */    0x60000040,0x00000000,
--/*
--    MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT
+-/* Read 4xx EBC bus bridge registers to get mappings of the peripheral
+- * banks into the OPB address space */
+-void ibm4xx_fixup_ebc_ranges(const char *ebc)
+-{
+-      void *devp;
+-      u32 bxcr;
+-      u32 ranges[EBC_NUM_BANKS*4];
+-      u32 *p = ranges;
+-      int i;
 -
--at 0x00000185 : */    0x0e000001,0x00000000,
--/*
--    RETURN
+-      for (i = 0; i < EBC_NUM_BANKS; i++) {
+-              mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
+-              bxcr = mfdcr(DCRN_EBC0_CFGDATA);
 -
--at 0x00000187 : */    0x90080000,0x00000000,
--/*
+-              if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
+-                      *p++ = i;
+-                      *p++ = 0;
+-                      *p++ = bxcr & EBC_BXCR_BAS;
+-                      *p++ = EBC_BXCR_BANK_SIZE(bxcr);
+-              }
+-      }
 -
--ENTRY accept_message
--accept_message:
--    CLEAR ATN
+-      devp = finddevice(ebc);
+-      if (! devp)
+-              fatal("Couldn't locate EBC node %s\n\r", ebc);
 -
--at 0x00000189 : */    0x60000008,0x00000000,
--/*
--    CLEAR ACK
+-      setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
+-}
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/44x.h linux-2.6.22-570/arch/powerpc/boot/44x.h
+--- linux-2.6.22-590/arch/powerpc/boot/44x.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/44x.h   2007-07-08 19:32:17.000000000 -0400
+@@ -11,9 +11,6 @@
+ #define _PPC_BOOT_44X_H_
+ void ibm44x_fixup_memsize(void);
+-void ibm4xx_fixup_ebc_ranges(const char *ebc);
 -
--at 0x0000018b : */    0x60000040,0x00000000,
+-void ibm44x_dbcr_reset(void);
+ void ebony_init(void *mac0, void *mac1);
+ #endif /* _PPC_BOOT_44X_H_ */
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/Makefile linux-2.6.22-570/arch/powerpc/boot/Makefile
+--- linux-2.6.22-590/arch/powerpc/boot/Makefile        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/Makefile        2007-07-08 19:32:17.000000000 -0400
+@@ -43,8 +43,8 @@
+ src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
+               ns16550.c serial.c simple_alloc.c div64.S util.S \
+-              gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
+-              44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c
++              gunzip_util.c elf_util.c $(zlib) devtree.c \
++              44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c
+ src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
+               cuboot-ebony.c treeboot-ebony.c prpmc2800.c
+ src-boot := $(src-wlib) $(src-plat) empty.c
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/cuboot-83xx.c linux-2.6.22-570/arch/powerpc/boot/cuboot-83xx.c
+--- linux-2.6.22-590/arch/powerpc/boot/cuboot-83xx.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/cuboot-83xx.c   2007-07-08 19:32:17.000000000 -0400
+@@ -12,12 +12,12 @@
+ #include "ops.h"
+ #include "stdio.h"
+-#include "cuboot.h"
+ #define TARGET_83xx
+ #include "ppcboot.h"
+ static bd_t bd;
++extern char _end[];
+ extern char _dtb_start[], _dtb_end[];
+ static void platform_fixups(void)
+@@ -52,7 +52,16 @@
+ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+                    unsigned long r6, unsigned long r7)
+ {
+-      CUBOOT_INIT();
++      unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
++      unsigned long avail_ram = end_of_ram - (unsigned long)_end;
++
++      memcpy(&bd, (bd_t *)r3, sizeof(bd));
++      loader_info.initrd_addr = r4;
++      loader_info.initrd_size = r4 ? r5 - r4 : 0;
++      loader_info.cmdline = (char *)r6;
++      loader_info.cmdline_len = r7 - r6;
++
++      simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+       ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+       serial_console_init();
+       platform_ops.fixups = platform_fixups;
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/cuboot-85xx.c linux-2.6.22-570/arch/powerpc/boot/cuboot-85xx.c
+--- linux-2.6.22-590/arch/powerpc/boot/cuboot-85xx.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/cuboot-85xx.c   2007-07-08 19:32:17.000000000 -0400
+@@ -12,12 +12,12 @@
+ #include "ops.h"
+ #include "stdio.h"
+-#include "cuboot.h"
+ #define TARGET_85xx
+ #include "ppcboot.h"
+ static bd_t bd;
++extern char _end[];
+ extern char _dtb_start[], _dtb_end[];
+ static void platform_fixups(void)
+@@ -53,7 +53,16 @@
+ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+                    unsigned long r6, unsigned long r7)
+ {
+-      CUBOOT_INIT();
++      unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
++      unsigned long avail_ram = end_of_ram - (unsigned long)_end;
++
++      memcpy(&bd, (bd_t *)r3, sizeof(bd));
++      loader_info.initrd_addr = r4;
++      loader_info.initrd_size = r4 ? r5 - r4 : 0;
++      loader_info.cmdline = (char *)r6;
++      loader_info.cmdline_len = r7 - r6;
++
++      simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+       ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+       serial_console_init();
+       platform_ops.fixups = platform_fixups;
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/cuboot-ebony.c linux-2.6.22-570/arch/powerpc/boot/cuboot-ebony.c
+--- linux-2.6.22-590/arch/powerpc/boot/cuboot-ebony.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/cuboot-ebony.c  2007-07-08 19:32:17.000000000 -0400
+@@ -15,16 +15,28 @@
+ #include "ops.h"
+ #include "stdio.h"
+ #include "44x.h"
+-#include "cuboot.h"
+ #define TARGET_44x
+ #include "ppcboot.h"
+ static bd_t bd;
++extern char _end[];
++
++BSS_STACK(4096);
+ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+                    unsigned long r6, unsigned long r7)
+ {
+-      CUBOOT_INIT();
++      unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
++      unsigned long avail_ram = end_of_ram - (unsigned long)_end;
++
++      memcpy(&bd, (bd_t *)r3, sizeof(bd));
++      loader_info.initrd_addr = r4;
++      loader_info.initrd_size = r4 ? r5 : 0;
++      loader_info.cmdline = (char *)r6;
++      loader_info.cmdline_len = r7 - r6;
++
++      simple_alloc_init(_end, avail_ram, 32, 64);
++
+       ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr);
+ }
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/cuboot.c linux-2.6.22-570/arch/powerpc/boot/cuboot.c
+--- linux-2.6.22-590/arch/powerpc/boot/cuboot.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/cuboot.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,35 +0,0 @@
 -/*
--    RETURN
+- * Compatibility for old (not device tree aware) U-Boot versions
+- *
+- * Author: Scott Wood <scottwood@freescale.com>
+- * Consolidated using macros by David Gibson <david@gibson.dropbear.id.au>
+- *
+- * Copyright 2007 David Gibson, IBM Corporation.
+- * Copyright (c) 2007 Freescale Semiconductor, Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License version 2 as published
+- * by the Free Software Foundation.
+- */
 -
--at 0x0000018d : */    0x90080000,0x00000000,
--/*
+-#include "ops.h"
+-#include "stdio.h"
 -
--ENTRY respond_message
--respond_message:
--    SET ATN
+-#include "ppcboot.h"
 -
--at 0x0000018f : */    0x58000008,0x00000000,
--/*
--    CLEAR ACK
+-extern char _end[];
+-extern char _dtb_start[], _dtb_end[];
 -
--at 0x00000191 : */    0x60000040,0x00000000,
--/*
--    MOVE FROM dsa_msgout_other, WHEN MSG_OUT
+-void cuboot_init(unsigned long r4, unsigned long r5,
+-               unsigned long r6, unsigned long r7,
+-               unsigned long end_of_ram)
+-{
+-      unsigned long avail_ram = end_of_ram - (unsigned long)_end;
 -
--at 0x00000193 : */    0x1e000000,0x00000068,
--/*
--    RETURN
+-      loader_info.initrd_addr = r4;
+-      loader_info.initrd_size = r4 ? r5 - r4 : 0;
+-      loader_info.cmdline = (char *)r6;
+-      loader_info.cmdline_len = r7 - r6;
 -
--at 0x00000195 : */    0x90080000,0x00000000,
--/*
+-      simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+-}
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/cuboot.h linux-2.6.22-570/arch/powerpc/boot/cuboot.h
+--- linux-2.6.22-590/arch/powerpc/boot/cuboot.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/cuboot.h        1969-12-31 19:00:00.000000000 -0500
+@@ -1,14 +0,0 @@
+-#ifndef _PPC_BOOT_CUBOOT_H_
+-#define _PPC_BOOT_CUBOOT_H_
+-
+-void cuboot_init(unsigned long r4, unsigned long r5,
+-               unsigned long r6, unsigned long r7,
+-               unsigned long end_of_ram);
+-
+-#define CUBOOT_INIT() \
+-      do { \
+-              memcpy(&bd, (bd_t *)r3, sizeof(bd)); \
+-              cuboot_init(r4, r5, r6, r7, bd.bi_memstart + bd.bi_memsize); \
+-      } while (0)
+-
+-#endif /* _PPC_BOOT_CUBOOT_H_ */
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/dcr.h linux-2.6.22-570/arch/powerpc/boot/dcr.h
+--- linux-2.6.22-590/arch/powerpc/boot/dcr.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/dcr.h   2007-07-08 19:32:17.000000000 -0400
+@@ -26,43 +26,6 @@
+ #define                       SDRAM_CONFIG_BANK_SIZE(reg)     \
+       (0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17))
+-/* 440GP External Bus Controller (EBC) */
+-#define DCRN_EBC0_CFGADDR                             0x012
+-#define DCRN_EBC0_CFGDATA                             0x013
+-#define   EBC_NUM_BANKS                                         8
+-#define   EBC_B0CR                                      0x00
+-#define   EBC_B1CR                                      0x01
+-#define   EBC_B2CR                                      0x02
+-#define   EBC_B3CR                                      0x03
+-#define   EBC_B4CR                                      0x04
+-#define   EBC_B5CR                                      0x05
+-#define   EBC_B6CR                                      0x06
+-#define   EBC_B7CR                                      0x07
+-#define   EBC_BXCR(n)                                   (n)
+-#define           EBC_BXCR_BAS                                    0xfff00000
+-#define           EBC_BXCR_BS                                     0x000e0000
+-#define           EBC_BXCR_BANK_SIZE(reg) \
+-      (0x100000 << (((reg) & EBC_BXCR_BS) >> 17))
+-#define           EBC_BXCR_BU                                     0x00018000
+-#define             EBC_BXCR_BU_OFF                                 0x00000000
+-#define             EBC_BXCR_BU_RO                                  0x00008000
+-#define             EBC_BXCR_BU_WO                                  0x00010000
+-#define             EBC_BXCR_BU_RW                                  0x00018000
+-#define           EBC_BXCR_BW                                     0x00006000
+-#define   EBC_B0AP                                      0x10
+-#define   EBC_B1AP                                      0x11
+-#define   EBC_B2AP                                      0x12
+-#define   EBC_B3AP                                      0x13
+-#define   EBC_B4AP                                      0x14
+-#define   EBC_B5AP                                      0x15
+-#define   EBC_B6AP                                      0x16
+-#define   EBC_B7AP                                      0x17
+-#define   EBC_BXAP(n)                                   (0x10+(n))
+-#define   EBC_BEAR                                      0x20
+-#define   EBC_BESR                                      0x21
+-#define   EBC_CFG                                       0x23
+-#define   EBC_CID                                       0x24
 -
--;
--; command_complete
--;
--; PURPOSE : handle command termination when STATUS IN is detected by reading
--;     a status byte followed by a command termination message. 
--;
--;     Normal termination results in an INTFLY instruction, and 
--;     the host system can pick out which command terminated by 
--;     examining the MESSAGE and STATUS buffers of all currently 
--;     executing commands;
--;
--;     Abnormal (CHECK_CONDITION) termination results in an
--;     int_err_check_condition interrupt so that a REQUEST SENSE
--;     command can be issued out-of-order so that no other command
--;     clears the contingent allegiance condition.
--;     
--;
--; INPUTS : DSA - command      
--;
--; CALLS : OK
--;
--; EXITS : On successful termination, control is passed to schedule.
--;     On abnormal termination, the user will usually modify the 
--;     DSA fields and corresponding buffers and return control
--;     to select.
--;
--
--ENTRY command_complete
--command_complete:
--    MOVE FROM dsa_status, WHEN STATUS
--
--at 0x00000197 : */    0x1b000000,0x00000060,
--/*
+ /* 440GP Clock, PM, chip control */
+ #define DCRN_CPC0_SR                                  0x0b0
+ #define DCRN_CPC0_ER                                  0x0b1
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/dts/ebony.dts linux-2.6.22-570/arch/powerpc/boot/dts/ebony.dts
+--- linux-2.6.22-590/arch/powerpc/boot/dts/ebony.dts   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/dts/ebony.dts   2007-07-08 19:32:17.000000000 -0400
+@@ -135,9 +135,11 @@
+                               #address-cells = <2>;
+                               #size-cells = <1>;
+                               clock-frequency = <0>; // Filled in by zImage
+-                              // ranges property is supplied by zImage
+-                              // based on firmware's configuration of the
+-                              // EBC bridge
++                              ranges = <0 00000000 fff00000 100000
++                                        1 00000000 48000000 100000
++                                        2 00000000 ff800000 400000
++                                        3 00000000 48200000 100000
++                                        7 00000000 48300000 100000>;
+                               interrupts = <5 4>;
+                               interrupt-parent = <&UIC1>;
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/dts/holly.dts linux-2.6.22-570/arch/powerpc/boot/dts/holly.dts
+--- linux-2.6.22-590/arch/powerpc/boot/dts/holly.dts   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/dts/holly.dts   2007-07-08 19:32:17.000000000 -0400
+@@ -46,7 +46,7 @@
+       tsi109@c0000000 {
+               device_type = "tsi-bridge";
+-              compatible = "tsi109-bridge", "tsi108-bridge";
++              compatible = "tsi-bridge";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <00000000 c0000000 00010000>;
+@@ -54,55 +54,52 @@
+               i2c@7000 {
+                       device_type = "i2c";
+-                      compatible  = "tsi109-i2c", "tsi108-i2c";
+-                      interrupt-parent = <&MPIC>;
++                      compatible  = "tsi-i2c";
++                      interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupts = <e 2>;
+                       reg = <7000 400>;
+               };
+-              MDIO: mdio@6000 {
++              mdio@6000 {
+                       device_type = "mdio";
+-                      compatible = "tsi109-mdio", "tsi108-mdio";
+-                              reg = <6000 50>;
+-                      #address-cells = <1>;
+-                      #size-cells = <0>;
++                      compatible = "tsi-ethernet";
+-                      PHY1: ethernet-phy@1 {
+-                              compatible = "bcm5461a";
+-                              reg = <1>;
+-                              txc-rxc-delay-disable;
++                      PHY1: ethernet-phy@6000 {
++                              device_type = "ethernet-phy";
++                              compatible = "bcm54xx";
++                              reg = <6000 50>;
++                              phy-id = <1>;
+                       };
+-                      PHY2: ethernet-phy@2 {
+-                              compatible = "bcm5461a";
+-                              reg = <2>;
+-                              txc-rxc-delay-disable;
++                      PHY2: ethernet-phy@6400 {
++                              device_type = "ethernet-phy";
++                              compatible = "bcm54xx";
++                              reg = <6000 50>;
++                              phy-id = <2>;
+                       };
+               };
+               ethernet@6200 {
+                       device_type = "network";
+-                      compatible = "tsi109-ethernet", "tsi108-ethernet";
++                      compatible = "tsi-ethernet";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <6000 200>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+-                      interrupt-parent = <&MPIC>;
++                      interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupts = <10 2>;
+-                      mdio-handle = <&MDIO>;
+                       phy-handle = <&PHY1>;
+               };
+               ethernet@6600 {
+                       device_type = "network";
+-                      compatible = "tsi109-ethernet", "tsi108-ethernet";
++                      compatible = "tsi-ethernet";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <6400 200>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+-                      interrupt-parent = <&MPIC>;
++                      interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupts = <11 2>;
+-                      mdio-handle = <&MDIO>;
+                       phy-handle = <&PHY2>;
+               };
+@@ -113,7 +110,7 @@
+                       virtual-reg = <c0007808>;
+                       clock-frequency = <3F9C6000>;
+                       current-speed = <1c200>;
+-                      interrupt-parent = <&MPIC>;
++                      interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupts = <c 2>;
+               };
+@@ -124,7 +121,7 @@
+                       virtual-reg = <c0007c08>;
+                       clock-frequency = <3F9C6000>;
+                       current-speed = <1c200>;
+-                      interrupt-parent = <&MPIC>;
++                      interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupts = <d 2>;
+               };
+@@ -139,7 +136,7 @@
+               pci@1000 {
+                       device_type = "pci";
+-                      compatible = "tsi109-pci", "tsi108-pci";
++                      compatible = "tsi109";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+@@ -153,7 +150,7 @@
+                       ranges = <02000000 0 40000000 40000000 0 10000000
+                                 01000000 0 00000000 7e000000 0 00010000>;
+                       clock-frequency = <7f28154>;
+-                      interrupt-parent = <&MPIC>;
++                      interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupts = <17 2>;
+                       interrupt-map-mask = <f800 0 0 7>;
+                       /*----------------------------------------------------+
+@@ -189,12 +186,13 @@
+                               #address-cells = <0>;
+                               #interrupt-cells = <2>;
+                               interrupts = <17 2>;
+-                              interrupt-parent = <&MPIC>;
++                              interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       };
+               };
+       };
+       chosen {
+               linux,stdout-path = "/tsi109@c0000000/serial@7808";
++              bootargs = "console=ttyS0,115200";
+       };
+ };
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/dts/mpc7448hpc2.dts linux-2.6.22-570/arch/powerpc/boot/dts/mpc7448hpc2.dts
+--- linux-2.6.22-590/arch/powerpc/boot/dts/mpc7448hpc2.dts     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/dts/mpc7448hpc2.dts     2007-07-08 19:32:17.000000000 -0400
+@@ -45,7 +45,7 @@
+               #address-cells = <1>;
+               #size-cells = <1>;
+               #interrupt-cells = <2>;
+-              device_type = "tsi108-bridge";
++              device_type = "tsi-bridge";
+               ranges = <00000000 c0000000 00010000>;
+               reg = <c0000000 00010000>;
+               bus-frequency = <0>;
+@@ -55,26 +55,27 @@
+                       interrupts = <E 0>;
+                       reg = <7000 400>;
+                       device_type = "i2c";
+-                      compatible  = "tsi108-i2c";
++                      compatible  = "tsi-i2c";
+               };
+-              MDIO: mdio@6000 {
++              mdio@6000 {
+                       device_type = "mdio";
+-                      compatible = "tsi108-mdio";
+-                      reg = <6000 50>;
+-                      #address-cells = <1>;
+-                      #size-cells = <0>;
++                      compatible = "tsi-ethernet";
+-                      phy8: ethernet-phy@8 {
++                      phy8: ethernet-phy@6000 {
+                               interrupt-parent = <&mpic>;
+                               interrupts = <2 1>;
+-                              reg = <8>;
++                              reg = <6000 50>;
++                              phy-id = <8>;
++                              device_type = "ethernet-phy";
+                       };
+-                      phy9: ethernet-phy@9 {
++                      phy9: ethernet-phy@6400 {
+                               interrupt-parent = <&mpic>;
+                               interrupts = <2 1>;
+-                              reg = <9>;
++                              reg = <6000 50>;
++                              phy-id = <9>;
++                              device_type = "ethernet-phy";
+                       };
+               };
+@@ -82,12 +83,12 @@
+               ethernet@6200 {
+                       #size-cells = <0>;
+                       device_type = "network";
+-                      compatible = "tsi108-ethernet";
++                      model = "TSI-ETH";
++                      compatible = "tsi-ethernet";
+                       reg = <6000 200>;
+                       address = [ 00 06 D2 00 00 01 ];
+                       interrupts = <10 2>;
+                       interrupt-parent = <&mpic>;
+-                      mdio-handle = <&MDIO>;
+                       phy-handle = <&phy8>;
+               };
+@@ -95,12 +96,12 @@
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+-                      compatible = "tsi108-ethernet";
++                      model = "TSI-ETH";
++                      compatible = "tsi-ethernet";
+                       reg = <6400 200>;
+                       address = [ 00 06 D2 00 00 02 ];
+                       interrupts = <11 2>;
+                       interrupt-parent = <&mpic>;
+-                      mdio-handle = <&MDIO>;
+                       phy-handle = <&phy9>;
+               };
+@@ -134,7 +135,7 @@
+                               big-endian;
+               };
+               pci@1000 {
+-                      compatible = "tsi108-pci";
++                      compatible = "tsi10x";
+                       device_type = "pci";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/ebony.c linux-2.6.22-570/arch/powerpc/boot/ebony.c
+--- linux-2.6.22-590/arch/powerpc/boot/ebony.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/ebony.c 2007-07-08 19:32:17.000000000 -0400
+@@ -100,13 +100,28 @@
+       ibm440gp_fixup_clocks(sysclk, 6 * 1843200);
+       ibm44x_fixup_memsize();
+       dt_fixup_mac_addresses(ebony_mac0, ebony_mac1);
+-      ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
++}
++
++#define SPRN_DBCR0            0x134
++#define   DBCR0_RST_SYSTEM    0x30000000
++
++static void ebony_exit(void)
++{
++      unsigned long tmp;
++
++      asm volatile (
++              "mfspr  %0,%1\n"
++              "oris   %0,%0,%2@h\n"
++              "mtspr  %1,%0"
++              : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
++              );
++
+ }
+ void ebony_init(void *mac0, void *mac1)
+ {
+       platform_ops.fixups = ebony_fixups;
+-      platform_ops.exit = ibm44x_dbcr_reset;
++      platform_ops.exit = ebony_exit;
+       ebony_mac0 = mac0;
+       ebony_mac1 = mac1;
+       ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/of.c linux-2.6.22-570/arch/powerpc/boot/of.c
+--- linux-2.6.22-590/arch/powerpc/boot/of.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/of.c    2007-07-08 19:32:17.000000000 -0400
+@@ -15,7 +15,8 @@
+ #include "page.h"
+ #include "ops.h"
+-#include "of.h"
++typedef void *ihandle;
++typedef void *phandle;
+ extern char _end[];
+@@ -24,10 +25,154 @@
+ #define RAM_END               (512<<20)       /* Fixme: use OF */
+ #define       ONE_MB          0x100000
++int (*prom) (void *);
+ static unsigned long claim_base;
++static int call_prom(const char *service, int nargs, int nret, ...)
++{
++      int i;
++      struct prom_args {
++              const char *service;
++              int nargs;
++              int nret;
++              unsigned int args[12];
++      } args;
++      va_list list;
++
++      args.service = service;
++      args.nargs = nargs;
++      args.nret = nret;
++
++      va_start(list, nret);
++      for (i = 0; i < nargs; i++)
++              args.args[i] = va_arg(list, unsigned int);
++      va_end(list);
++
++      for (i = 0; i < nret; i++)
++              args.args[nargs+i] = 0;
++
++      if (prom(&args) < 0)
++              return -1;
++
++      return (nret > 0)? args.args[nargs]: 0;
++}
++
++static int call_prom_ret(const char *service, int nargs, int nret,
++                unsigned int *rets, ...)
++{
++      int i;
++      struct prom_args {
++              const char *service;
++              int nargs;
++              int nret;
++              unsigned int args[12];
++      } args;
++      va_list list;
++
++      args.service = service;
++      args.nargs = nargs;
++      args.nret = nret;
++
++      va_start(list, rets);
++      for (i = 0; i < nargs; i++)
++              args.args[i] = va_arg(list, unsigned int);
++      va_end(list);
++
++      for (i = 0; i < nret; i++)
++              args.args[nargs+i] = 0;
++
++      if (prom(&args) < 0)
++              return -1;
++
++      if (rets != (void *) 0)
++              for (i = 1; i < nret; ++i)
++                      rets[i-1] = args.args[nargs+i];
++
++      return (nret > 0)? args.args[nargs]: 0;
++}
++
++/*
++ * Older OF's require that when claiming a specific range of addresses,
++ * we claim the physical space in the /memory node and the virtual
++ * space in the chosen mmu node, and then do a map operation to
++ * map virtual to physical.
++ */
++static int need_map = -1;
++static ihandle chosen_mmu;
++static phandle memory;
++
++/* returns true if s2 is a prefix of s1 */
++static int string_match(const char *s1, const char *s2)
++{
++      for (; *s2; ++s2)
++              if (*s1++ != *s2)
++                      return 0;
++      return 1;
++}
++
++static int check_of_version(void)
++{
++      phandle oprom, chosen;
++      char version[64];
++
++      oprom = finddevice("/openprom");
++      if (oprom == (phandle) -1)
++              return 0;
++      if (getprop(oprom, "model", version, sizeof(version)) <= 0)
++              return 0;
++      version[sizeof(version)-1] = 0;
++      printf("OF version = '%s'\r\n", version);
++      if (!string_match(version, "Open Firmware, 1.")
++          && !string_match(version, "FirmWorks,3."))
++              return 0;
++      chosen = finddevice("/chosen");
++      if (chosen == (phandle) -1) {
++              chosen = finddevice("/chosen@0");
++              if (chosen == (phandle) -1) {
++                      printf("no chosen\n");
++                      return 0;
++              }
++      }
++      if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
++              printf("no mmu\n");
++              return 0;
++      }
++      memory = (ihandle) call_prom("open", 1, 1, "/memory");
++      if (memory == (ihandle) -1) {
++              memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
++              if (memory == (ihandle) -1) {
++                      printf("no memory node\n");
++                      return 0;
++              }
++      }
++      printf("old OF detected\r\n");
++      return 1;
++}
++
++static void *claim(unsigned long virt, unsigned long size, unsigned long align)
++{
++      int ret;
++      unsigned int result;
++
++      if (need_map < 0)
++              need_map = check_of_version();
++      if (align || !need_map)
++              return (void *) call_prom("claim", 3, 1, virt, size, align);
++
++      ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
++                          align, size, virt);
++      if (ret != 0 || result == -1)
++              return (void *) -1;
++      ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
++                          align, size, virt);
++      /* 0x12 == coherent + read/write */
++      ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
++                      0x12, size, virt, virt);
++      return (void *) virt;
++}
++
+ static void *of_try_claim(unsigned long size)
+ {
+       unsigned long addr = 0;
+@@ -39,7 +184,7 @@
+ #ifdef DEBUG
+               printf("    trying: 0x%08lx\n\r", claim_base);
+ #endif
+-              addr = (unsigned long)of_claim(claim_base, size, 0);
++              addr = (unsigned long)claim(claim_base, size, 0);
+               if ((void *)addr != (void *)-1)
+                       break;
+       }
+@@ -73,24 +218,52 @@
+       return p;
+ }
++static void of_exit(void)
++{
++      call_prom("exit", 0, 0);
++}
++
+ /*
+  * OF device tree routines
+  */
+ static void *of_finddevice(const char *name)
+ {
+-      return (phandle) of_call_prom("finddevice", 1, 1, name);
++      return (phandle) call_prom("finddevice", 1, 1, name);
+ }
+ static int of_getprop(const void *phandle, const char *name, void *buf,
+               const int buflen)
+ {
+-      return of_call_prom("getprop", 4, 1, phandle, name, buf, buflen);
++      return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
+ }
+ static int of_setprop(const void *phandle, const char *name, const void *buf,
+               const int buflen)
+ {
+-      return of_call_prom("setprop", 4, 1, phandle, name, buf, buflen);
++      return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
++}
++
++/*
++ * OF console routines
++ */
++static void *of_stdout_handle;
++
++static int of_console_open(void)
++{
++      void *devp;
++
++      if (((devp = finddevice("/chosen")) != NULL)
++                      && (getprop(devp, "stdout", &of_stdout_handle,
++                              sizeof(of_stdout_handle))
++                              == sizeof(of_stdout_handle)))
++              return 0;
++
++      return -1;
++}
++
++static void of_console_write(char *buf, int len)
++{
++      call_prom("write", 3, 1, of_stdout_handle, buf, len);
+ }
+ void platform_init(unsigned long a1, unsigned long a2, void *promptr)
+@@ -104,9 +277,10 @@
+       dt_ops.getprop = of_getprop;
+       dt_ops.setprop = of_setprop;
+-      of_console_init();
++      console_ops.open = of_console_open;
++      console_ops.write = of_console_write;
+-      of_init(promptr);
++      prom = (int (*)(void *))promptr;
+       loader_info.promptr = promptr;
+       if (a1 && a2 && a2 != 0xdeadbeef) {
+               loader_info.initrd_addr = a1;
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/of.h linux-2.6.22-570/arch/powerpc/boot/of.h
+--- linux-2.6.22-590/arch/powerpc/boot/of.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/of.h    1969-12-31 19:00:00.000000000 -0500
+@@ -1,15 +0,0 @@
+-#ifndef _PPC_BOOT_OF_H_
+-#define _PPC_BOOT_OF_H_
 -
--    MOVE SFBR TO SCRATCH0             ; Save status
+-typedef void *phandle;
+-typedef void *ihandle;
 -
--at 0x00000199 : */    0x6a340000,0x00000000,
--/*
+-void of_init(void *promptr);
+-int of_call_prom(const char *service, int nargs, int nret, ...);
+-void *of_claim(unsigned long virt, unsigned long size, unsigned long align);
+-void of_exit(void);
 -
--ENTRY command_complete_msgin
--command_complete_msgin:
--    MOVE FROM dsa_msgin, WHEN MSG_IN
+-/* Console functions */
+-void of_console_init(void);
 -
--at 0x0000019b : */    0x1f000000,0x00000058,
+-#endif /* _PPC_BOOT_OF_H_ */
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/ofconsole.c linux-2.6.22-570/arch/powerpc/boot/ofconsole.c
+--- linux-2.6.22-590/arch/powerpc/boot/ofconsole.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/ofconsole.c     1969-12-31 19:00:00.000000000 -0500
+@@ -1,45 +0,0 @@
 -/*
--; Indicate that we should be expecting a disconnect
+- * OF console routines
+- *
+- * Copyright (C) Paul Mackerras 1997.
+- *
+- * 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.
+- */
+-#include <stddef.h>
+-#include "types.h"
+-#include "elf.h"
+-#include "string.h"
+-#include "stdio.h"
+-#include "page.h"
+-#include "ops.h"
 -
+-#include "of.h"
 -
+-static void *of_stdout_handle;
 -
--    ; Above code cleared the Unexpected Disconnect bit, what do we do?
+-static int of_console_open(void)
+-{
+-      void *devp;
 -
--    CLEAR ACK
+-      if (((devp = finddevice("/chosen")) != NULL)
+-                      && (getprop(devp, "stdout", &of_stdout_handle,
+-                              sizeof(of_stdout_handle))
+-                              == sizeof(of_stdout_handle)))
+-              return 0;
 -
--at 0x0000019d : */    0x60000040,0x00000000,
--/*
+-      return -1;
+-}
 -
--    WAIT DISCONNECT
+-static void of_console_write(char *buf, int len)
+-{
+-      of_call_prom("write", 3, 1, of_stdout_handle, buf, len);
+-}
 -
--at 0x0000019f : */    0x48000000,0x00000000,
+-void of_console_init(void)
+-{
+-      console_ops.open = of_console_open;
+-      console_ops.write = of_console_write;
+-}
+diff -Nurb linux-2.6.22-590/arch/powerpc/boot/oflib.c linux-2.6.22-570/arch/powerpc/boot/oflib.c
+--- linux-2.6.22-590/arch/powerpc/boot/oflib.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/boot/oflib.c 1969-12-31 19:00:00.000000000 -0500
+@@ -1,172 +0,0 @@
 -/*
+- * Copyright (C) Paul Mackerras 1997.
+- *
+- * 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.
+- */
+-#include <stddef.h>
+-#include "types.h"
+-#include "elf.h"
+-#include "string.h"
+-#include "stdio.h"
+-#include "page.h"
+-#include "ops.h"
 -
--;
--; The SCSI specification states that when a UNIT ATTENTION condition
--; is pending, as indicated by a CHECK CONDITION status message,
--; the target shall revert to asynchronous transfers.  Since
--; synchronous transfers parameters are maintained on a per INITIATOR/TARGET 
--; basis, and returning control to our scheduler could work on a command
--; running on another lun on that target using the old parameters, we must
--; interrupt the host processor to get them changed, or change them ourselves.
--;
--; Once SCSI-II tagged queueing is implemented, things will be even more
--; hairy, since contingent allegiance conditions exist on a per-target/lun
--; basis, and issuing a new command with a different tag would clear it.
--; In these cases, we must interrupt the host processor to get a request 
--; added to the HEAD of the queue with the request sense command, or we
--; must automatically issue the request sense command.
--
--
--
--
--
+-#include "of.h"
 -
+-static int (*prom) (void *);
 -
--    INT int_norm_emulateintfly
+-void of_init(void *promptr)
+-{
+-      prom = (int (*)(void *))promptr;
+-}
 -
--at 0x000001a1 : */    0x98080000,0x02060000,
--/*
+-int of_call_prom(const char *service, int nargs, int nret, ...)
+-{
+-      int i;
+-      struct prom_args {
+-              const char *service;
+-              int nargs;
+-              int nret;
+-              unsigned int args[12];
+-      } args;
+-      va_list list;
 -
+-      args.service = service;
+-      args.nargs = nargs;
+-      args.nret = nret;
 -
+-      va_start(list, nret);
+-      for (i = 0; i < nargs; i++)
+-              args.args[i] = va_arg(list, unsigned int);
+-      va_end(list);
 -
+-      for (i = 0; i < nret; i++)
+-              args.args[nargs+i] = 0;
 -
+-      if (prom(&args) < 0)
+-              return -1;
 -
+-      return (nret > 0)? args.args[nargs]: 0;
+-}
 -
--    ; Time to correct DSA following memory move
--    MOVE MEMORY 4, saved_dsa, addr_dsa
+-static int of_call_prom_ret(const char *service, int nargs, int nret,
+-                          unsigned int *rets, ...)
+-{
+-      int i;
+-      struct prom_args {
+-              const char *service;
+-              int nargs;
+-              int nret;
+-              unsigned int args[12];
+-      } args;
+-      va_list list;
 -
--at 0x000001a3 : */    0xc0000004,0x00000000,0x00000000,
--/*
+-      args.service = service;
+-      args.nargs = nargs;
+-      args.nret = nret;
 -
+-      va_start(list, rets);
+-      for (i = 0; i < nargs; i++)
+-              args.args[i] = va_arg(list, unsigned int);
+-      va_end(list);
 -
+-      for (i = 0; i < nret; i++)
+-              args.args[nargs+i] = 0;
 -
+-      if (prom(&args) < 0)
+-              return -1;
 -
+-      if (rets != (void *) 0)
+-              for (i = 1; i < nret; ++i)
+-                      rets[i-1] = args.args[nargs+i];
 -
--    JUMP schedule
+-      return (nret > 0)? args.args[nargs]: 0;
+-}
 -
--at 0x000001a6 : */    0x80080000,0x00000000,
--/*
--command_failed:
--    INT int_err_check_condition
+-/* returns true if s2 is a prefix of s1 */
+-static int string_match(const char *s1, const char *s2)
+-{
+-      for (; *s2; ++s2)
+-              if (*s1++ != *s2)
+-                      return 0;
+-      return 1;
+-}
 -
--at 0x000001a8 : */    0x98080000,0x00030000,
 -/*
+- * Older OF's require that when claiming a specific range of addresses,
+- * we claim the physical space in the /memory node and the virtual
+- * space in the chosen mmu node, and then do a map operation to
+- * map virtual to physical.
+- */
+-static int need_map = -1;
+-static ihandle chosen_mmu;
+-static phandle memory;
 -
+-static int check_of_version(void)
+-{
+-      phandle oprom, chosen;
+-      char version[64];
 -
+-      oprom = finddevice("/openprom");
+-      if (oprom == (phandle) -1)
+-              return 0;
+-      if (getprop(oprom, "model", version, sizeof(version)) <= 0)
+-              return 0;
+-      version[sizeof(version)-1] = 0;
+-      printf("OF version = '%s'\r\n", version);
+-      if (!string_match(version, "Open Firmware, 1.")
+-          && !string_match(version, "FirmWorks,3."))
+-              return 0;
+-      chosen = finddevice("/chosen");
+-      if (chosen == (phandle) -1) {
+-              chosen = finddevice("/chosen@0");
+-              if (chosen == (phandle) -1) {
+-                      printf("no chosen\n");
+-                      return 0;
+-              }
+-      }
+-      if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+-              printf("no mmu\n");
+-              return 0;
+-      }
+-      memory = (ihandle) of_call_prom("open", 1, 1, "/memory");
+-      if (memory == (ihandle) -1) {
+-              memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0");
+-              if (memory == (ihandle) -1) {
+-                      printf("no memory node\n");
+-                      return 0;
+-              }
+-      }
+-      printf("old OF detected\r\n");
+-      return 1;
+-}
 -
+-void *of_claim(unsigned long virt, unsigned long size, unsigned long align)
+-{
+-      int ret;
+-      unsigned int result;
 -
--;
--; wait_reselect
--;
--; PURPOSE : This is essentially the idle routine, where control lands
--;     when there are no new processes to schedule.  wait_reselect
--;     waits for reselection, selection, and new commands.
--;
--;     When a successful reselection occurs, with the aid 
--;     of fixed up code in each DSA, wait_reselect walks the 
--;     reconnect_dsa_queue, asking each dsa if the target ID
--;     and LUN match its.
--;
--;     If a match is found, a call is made back to reselected_ok,
--;     which through the miracles of self modifying code, extracts
--;     the found DSA from the reconnect_dsa_queue and then 
--;     returns control to the DSAs thread of execution.
--;
--; INPUTS : NONE
--;
--; CALLS : OK
--;
--; MODIFIES : DSA,
--;
--; EXITS : On successful reselection, control is returned to the 
--;     DSA which called reselected_ok.  If the WAIT RESELECT
--;     was interrupted by a new commands arrival signaled by 
--;     SIG_P, control is passed to schedule.  If the NCR is 
--;     selected, the host system is interrupted with an 
--;     int_err_selected which is usually responded to by
--;     setting DSP to the target_abort address.
--
--ENTRY wait_reselect
--wait_reselect:
--
--
--
--
+-      if (need_map < 0)
+-              need_map = check_of_version();
+-      if (align || !need_map)
+-              return (void *) of_call_prom("claim", 3, 1, virt, size, align);
 -
+-      ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", memory,
+-                             align, size, virt);
+-      if (ret != 0 || result == -1)
+-              return (void *) -1;
+-      ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+-                             align, size, virt);
+-      /* 0x12 == coherent + read/write */
+-      ret = of_call_prom("call-method", 6, 1, "map", chosen_mmu,
+-                         0x12, size, virt, virt);
+-      return (void *) virt;
+-}
 -
--    WAIT RESELECT wait_reselect_failed
+-void of_exit(void)
+-{
+-      of_call_prom("exit", 0, 0);
+-}
+diff -Nurb linux-2.6.22-590/arch/powerpc/configs/holly_defconfig linux-2.6.22-570/arch/powerpc/configs/holly_defconfig
+--- linux-2.6.22-590/arch/powerpc/configs/holly_defconfig      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/configs/holly_defconfig      2007-07-08 19:32:17.000000000 -0400
+@@ -190,8 +190,7 @@
+ # CONFIG_RESOURCES_64BIT is not set
+ CONFIG_ZONE_DMA_FLAG=1
+ CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE="console=ttyS0,115200"
++# CONFIG_CMDLINE_BOOL is not set
+ # CONFIG_PM is not set
+ # CONFIG_SECCOMP is not set
+ # CONFIG_WANT_DEVICE_TREE is not set
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/Makefile linux-2.6.22-570/arch/powerpc/kernel/Makefile
+--- linux-2.6.22-590/arch/powerpc/kernel/Makefile      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/Makefile      2007-07-08 19:32:17.000000000 -0400
+@@ -12,8 +12,7 @@
+ obj-y                         := semaphore.o cputable.o ptrace.o syscalls.o \
+                                  irq.o align.o signal_32.o pmc.o vdso.o \
+-                                 init_task.o process.o systbl.o idle.o \
+-                                 signal.o
++                                 init_task.o process.o systbl.o idle.o
+ obj-y                         += vdso32/
+ obj-$(CONFIG_PPC64)           += setup_64.o binfmt_elf32.o sys_ppc32.o \
+                                  signal_64.o ptrace32.o \
+@@ -63,16 +62,10 @@
+ obj-$(CONFIG_KPROBES)         += kprobes.o
+ obj-$(CONFIG_PPC_UDBG_16550)  += legacy_serial.o udbg_16550.o
+-ifeq ($(CONFIG_PPC32),y)
+-obj-$(CONFIG_KGDB)            += kgdb.o kgdb_setjmp32.o
+-else
+-obj-$(CONFIG_KGDB)            += kgdb.o kgdb_setjmp64.o
+-endif
 -
--at 0x000001aa : */    0x50000000,0x00000800,
+ module-$(CONFIG_PPC64)                += module_64.o
+ obj-$(CONFIG_MODULES)         += $(module-y)
+-pci64-$(CONFIG_PPC64)         += pci_64.o pci_dn.o isa-bridge.o
++pci64-$(CONFIG_PPC64)         += pci_64.o pci_dn.o
+ pci32-$(CONFIG_PPC32)         := pci_32.o
+ obj-$(CONFIG_PCI)             += $(pci64-y) $(pci32-y)
+ obj-$(CONFIG_PCI_MSI)         += msi.o
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/head_32.S linux-2.6.22-570/arch/powerpc/kernel/head_32.S
+--- linux-2.6.22-590/arch/powerpc/kernel/head_32.S     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/head_32.S     2007-07-08 19:32:17.000000000 -0400
+@@ -9,6 +9,7 @@
+  *  rewritten by Paul Mackerras.
+  *    Copyright (C) 1996 Paul Mackerras.
+  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  *  This file contains the low-level support and setup for the
+  *  PowerPC platform, including trap and interrupt dispatch.
+@@ -31,6 +32,10 @@
+ #include <asm/ppc_asm.h>
+ #include <asm/asm-offsets.h>
++#ifdef CONFIG_APUS
++#include <asm/amigappc.h>
++#endif
++
+ /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
+ #define LOAD_BAT(n, reg, RA, RB)      \
+       /* see the comment for clear_bats() -- Cort */ \
+@@ -87,6 +92,11 @@
+  *  r4: virtual address of boot_infos_t
+  *  r5: 0
+  *
++ * APUS
++ *   r3: 'APUS'
++ *   r4: physical address of memory base
++ *   Linux/m68k style BootInfo structure at &_end.
++ *
+  * PREP
+  * This is jumped to on prep systems right after the kernel is relocated
+  * to its proper place in memory by the boot loader.  The expected layout
+@@ -140,6 +150,14 @@
+  */
+       bl      early_init
++#ifdef CONFIG_APUS
++/* On APUS the __va/__pa constants need to be set to the correct
++ * values before continuing.
++ */
++      mr      r4,r30
++      bl      fix_mem_constants
++#endif /* CONFIG_APUS */
++
+ /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
+  * the physical address we are running at, returned by early_init()
+  */
+@@ -149,7 +167,7 @@
+       bl      flush_tlbs
+       bl      initial_bats
+-#if defined(CONFIG_BOOTX_TEXT)
++#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+       bl      setup_disp_bat
+ #endif
+@@ -165,6 +183,7 @@
+ #endif /* CONFIG_6xx */
++#ifndef CONFIG_APUS
+ /*
+  * We need to run with _start at physical address 0.
+  * On CHRP, we are loaded at 0x10000 since OF on CHRP uses
+@@ -177,6 +196,7 @@
+       addis   r4,r3,KERNELBASE@h      /* current address of _start */
+       cmpwi   0,r4,0                  /* are we already running at 0? */
+       bne     relocate_kernel
++#endif /* CONFIG_APUS */
+ /*
+  * we now have the 1st 16M of ram mapped with the bats.
+  * prep needs the mmu to be turned on here, but pmac already has it on.
+@@ -861,6 +881,85 @@
+       addi    r6,r6,4
+       blr
++#ifdef CONFIG_APUS
++/*
++ * On APUS the physical base address of the kernel is not known at compile
++ * time, which means the __pa/__va constants used are incorrect. In the
++ * __init section is recorded the virtual addresses of instructions using
++ * these constants, so all that has to be done is fix these before
++ * continuing the kernel boot.
++ *
++ * r4 = The physical address of the kernel base.
++ */
++fix_mem_constants:
++      mr      r10,r4
++      addis   r10,r10,-KERNELBASE@h    /* virt_to_phys constant */
++      neg     r11,r10                  /* phys_to_virt constant */
++
++      lis     r12,__vtop_table_begin@h
++      ori     r12,r12,__vtop_table_begin@l
++      add     r12,r12,r10              /* table begin phys address */
++      lis     r13,__vtop_table_end@h
++      ori     r13,r13,__vtop_table_end@l
++      add     r13,r13,r10              /* table end phys address */
++      subi    r12,r12,4
++      subi    r13,r13,4
++1:    lwzu    r14,4(r12)               /* virt address of instruction */
++      add     r14,r14,r10              /* phys address of instruction */
++      lwz     r15,0(r14)               /* instruction, now insert top */
++      rlwimi  r15,r10,16,16,31         /* half of vp const in low half */
++      stw     r15,0(r14)               /* of instruction and restore. */
++      dcbst   r0,r14                   /* write it to memory */
++      sync
++      icbi    r0,r14                   /* flush the icache line */
++      cmpw    r12,r13
++      bne     1b
++      sync                            /* additional sync needed on g4 */
++      isync
++
++/*
++ * Map the memory where the exception handlers will
++ * be copied to when hash constants have been patched.
++ */
++#ifdef CONFIG_APUS_FAST_EXCEPT
++      lis     r8,0xfff0
++#else
++      lis     r8,0
++#endif
++      ori     r8,r8,0x2               /* 128KB, supervisor */
++      mtspr   SPRN_DBAT3U,r8
++      mtspr   SPRN_DBAT3L,r8
++
++      lis     r12,__ptov_table_begin@h
++      ori     r12,r12,__ptov_table_begin@l
++      add     r12,r12,r10              /* table begin phys address */
++      lis     r13,__ptov_table_end@h
++      ori     r13,r13,__ptov_table_end@l
++      add     r13,r13,r10              /* table end phys address */
++      subi    r12,r12,4
++      subi    r13,r13,4
++1:    lwzu    r14,4(r12)               /* virt address of instruction */
++      add     r14,r14,r10              /* phys address of instruction */
++      lwz     r15,0(r14)               /* instruction, now insert top */
++      rlwimi  r15,r11,16,16,31         /* half of pv const in low half*/
++      stw     r15,0(r14)               /* of instruction and restore. */
++      dcbst   r0,r14                   /* write it to memory */
++      sync
++      icbi    r0,r14                   /* flush the icache line */
++      cmpw    r12,r13
++      bne     1b
++
++      sync                            /* additional sync needed on g4 */
++      isync                           /* No speculative loading until now */
++      blr
++
++/***********************************************************************
++ *  Please note that on APUS the exception handlers are located at the
++ *  physical address 0xfff0000. For this reason, the exception handlers
++ *  cannot use relative branches to access the code below.
++ ***********************************************************************/
++#endif /* CONFIG_APUS */
++
+ #ifdef CONFIG_SMP
+ #ifdef CONFIG_GEMINI
+       .globl  __secondary_start_gemini
+@@ -1036,6 +1135,19 @@
+       bl      __save_cpu_setup
+       bl      MMU_init
++#ifdef CONFIG_APUS
++      /* Copy exception code to exception vector base on APUS. */
++      lis     r4,KERNELBASE@h
++#ifdef CONFIG_APUS_FAST_EXCEPT
++      lis     r3,0xfff0               /* Copy to 0xfff00000 */
++#else
++      lis     r3,0                    /* Copy to 0x00000000 */
++#endif
++      li      r5,0x4000               /* # bytes of memory to copy */
++      li      r6,0
++      bl      copy_and_flush          /* copy the first 0x4000 bytes */
++#endif  /* CONFIG_APUS */
++
+ /*
+  * Go back to running unmapped so we can load up new values
+  * for SDR1 (hash table pointer) and the segment registers
+@@ -1212,7 +1324,11 @@
+ #else
+       ori     r8,r8,2                 /* R/W access */
+ #endif /* CONFIG_SMP */
++#ifdef CONFIG_APUS
++      ori     r11,r11,BL_8M<<2|0x2    /* set up 8MB BAT registers for 604 */
++#else
+       ori     r11,r11,BL_256M<<2|0x2  /* set up BAT registers for 604 */
++#endif /* CONFIG_APUS */
+       mtspr   SPRN_DBAT0L,r8          /* N.B. 6xx (not 601) have valid */
+       mtspr   SPRN_DBAT0U,r11         /* bit in upper BAT register */
+@@ -1222,7 +1338,7 @@
+       blr
+-#ifdef CONFIG_BOOTX_TEXT
++#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+ setup_disp_bat:
+       /*
+        * setup the display bat prepared for us in prom.c
+@@ -1246,7 +1362,7 @@
+ 1:    mtspr   SPRN_IBAT3L,r8
+       mtspr   SPRN_IBAT3U,r11
+       blr
+-#endif /* CONFIG_BOOTX_TEXT */
++#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
+ #ifdef CONFIG_8260
+ /* Jump into the system reset for the rom.
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/irq.c linux-2.6.22-570/arch/powerpc/kernel/irq.c
+--- linux-2.6.22-590/arch/powerpc/kernel/irq.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/irq.c 2008-01-23 19:16:03.000000000 -0500
+@@ -7,6 +7,7 @@
+  *    Copyright (C) 1996-2001 Cort Dougan
+  *  Adapted for Power Macintosh by Paul Mackerras
+  *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/isa-bridge.c linux-2.6.22-570/arch/powerpc/kernel/isa-bridge.c
+--- linux-2.6.22-590/arch/powerpc/kernel/isa-bridge.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/isa-bridge.c  1969-12-31 19:00:00.000000000 -0500
+@@ -1,271 +0,0 @@
 -/*
+- * Routines for tracking a legacy ISA bridge
+- *
+- * Copyrigh 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+- *
+- * Some bits and pieces moved over from pci_64.c
+- *
+- * Copyrigh 2003 Anton Blanchard <anton@au.ibm.com>, IBM Corp.
+- *
+- *      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.
+- */
 -
--reselected:
--
--
--
--    CLEAR TARGET
+-#define DEBUG
 -
--at 0x000001ac : */    0x60000200,0x00000000,
--/*
--    
--    ; Read all data needed to reestablish the nexus - 
--    MOVE 1, reselected_identify, WHEN MSG_IN
+-#include <linux/kernel.h>
+-#include <linux/pci.h>
+-#include <linux/string.h>
+-#include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/notifier.h>
 -
--at 0x000001ae : */    0x0f000001,0x00000000,
--/*
--    ; We used to CLEAR ACK here.
+-#include <asm/processor.h>
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/machdep.h>
+-#include <asm/ppc-pci.h>
+-#include <asm/firmware.h>
 -
+-unsigned long isa_io_base;    /* NULL if no ISA bus */
+-EXPORT_SYMBOL(isa_io_base);
 -
+-/* Cached ISA bridge dev. */
+-static struct device_node *isa_bridge_devnode;
+-struct pci_dev *isa_bridge_pcidev;
+-EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
 -
+-#define ISA_SPACE_MASK 0x1
+-#define ISA_SPACE_IO 0x1
 -
+-static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
+-                                              unsigned long phb_io_base_phys)
+-{
+-      /* We should get some saner parsing here and remove these structs */
+-      struct pci_address {
+-              u32 a_hi;
+-              u32 a_mid;
+-              u32 a_lo;
+-      };
 -
--    ; Point DSA at the current head of the disconnected queue.
--    
--    MOVE MEMORY 4, reconnect_dsa_head, addr_scratch
+-      struct isa_address {
+-              u32 a_hi;
+-              u32 a_lo;
+-      };
 -
--at 0x000001b0 : */    0xc0000004,0x00000000,0x00000000,
--/*
--    
+-      struct isa_range {
+-              struct isa_address isa_addr;
+-              struct pci_address pci_addr;
+-              unsigned int size;
+-      };
 -
--    MOVE MEMORY 4, addr_scratch, saved_dsa
+-      const struct isa_range *range;
+-      unsigned long pci_addr;
+-      unsigned int isa_addr;
+-      unsigned int size;
+-      int rlen = 0;
 -
--at 0x000001b3 : */    0xc0000004,0x00000000,0x00000000,
--/*
+-      range = of_get_property(isa_node, "ranges", &rlen);
+-      if (range == NULL || (rlen < sizeof(struct isa_range)))
+-              goto inval_range;
 -
+-      /* From "ISA Binding to 1275"
+-       * The ranges property is laid out as an array of elements,
+-       * each of which comprises:
+-       *   cells 0 - 1:       an ISA address
+-       *   cells 2 - 4:       a PCI address
+-       *                      (size depending on dev->n_addr_cells)
+-       *   cell 5:            the size of the range
+-       */
+-      if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) {
+-              range++;
+-              rlen -= sizeof(struct isa_range);
+-              if (rlen < sizeof(struct isa_range))
+-                      goto inval_range;
+-      }
+-      if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO)
+-              goto inval_range;
+-
+-      isa_addr = range->isa_addr.a_lo;
+-      pci_addr = (unsigned long) range->pci_addr.a_mid << 32 |
+-              range->pci_addr.a_lo;
+-
+-      /* Assume these are both zero. Note: We could fix that and
+-       * do a proper parsing instead ... oh well, that will do for
+-       * now as nobody uses fancy mappings for ISA bridges
+-       */
+-      if ((pci_addr != 0) || (isa_addr != 0)) {
+-              printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
+-                     __FUNCTION__);
+-              return;
+-      }
 -
+-      /* Align size and make sure it's cropped to 64K */
+-      size = PAGE_ALIGN(range->size);
+-      if (size > 0x10000)
+-              size = 0x10000;
 -
+-      printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
+-             "mapping 64k\n");
 -
--    ; Fix the update-next pointer so that the reconnect_dsa_head
--    ; pointer is the one that will be updated if this DSA is a hit 
--    ; and we remove it from the queue.
+-      __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
+-                   size, _PAGE_NO_CACHE|_PAGE_GUARDED);
+-      return;
 -
--    MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok_patch + 8
+-inval_range:
+-      printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
+-             "mapping 64k\n");
+-      __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
+-                   0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED);
+-}
 -
--at 0x000001b6 : */    0xc0000004,0x00000000,0x000007ec,
--/*
 -
--    ; Time to correct DSA following memory move
--    MOVE MEMORY 4, saved_dsa, addr_dsa
+-/**
+- * isa_bridge_find_early - Find and map the ISA IO space early before
+- *                         main PCI discovery. This is optionally called by
+- *                         the arch code when adding PCI PHBs to get early
+- *                         access to ISA IO ports
+- */
+-void __init isa_bridge_find_early(struct pci_controller *hose)
+-{
+-      struct device_node *np, *parent = NULL, *tmp;
 -
--at 0x000001b9 : */    0xc0000004,0x00000000,0x00000000,
--/*
+-      /* If we already have an ISA bridge, bail off */
+-      if (isa_bridge_devnode != NULL)
+-              return;
 -
+-      /* For each "isa" node in the system. Note : we do a search by
+-       * type and not by name. It might be better to do by name but that's
+-       * what the code used to do and I don't want to break too much at
+-       * once. We can look into changing that separately
+-       */
+-      for_each_node_by_type(np, "isa") {
+-              /* Look for our hose being a parent */
+-              for (parent = of_get_parent(np); parent;) {
+-                      if (parent == hose->arch_data) {
+-                              of_node_put(parent);
+-                              break;
+-                      }
+-                      tmp = parent;
+-                      parent = of_get_parent(parent);
+-                      of_node_put(tmp);
+-              }
+-              if (parent != NULL)
+-                      break;
+-      }
+-      if (np == NULL)
+-              return;
+-      isa_bridge_devnode = np;
 -
--ENTRY reselected_check_next
--reselected_check_next:
+-      /* Now parse the "ranges" property and setup the ISA mapping */
+-      pci_process_ISA_OF_ranges(np, hose->io_base_phys);
 -
+-      /* Set the global ISA io base to indicate we have an ISA bridge */
+-      isa_io_base = ISA_IO_BASE;
 -
+-      pr_debug("ISA bridge (early) is %s\n", np->full_name);
+-}
 -
--    ; Check for a NULL pointer.
--    MOVE DSA0 TO SFBR
+-/**
+- * isa_bridge_find_late - Find and map the ISA IO space upon discovery of
+- *                        a new ISA bridge
+- */
+-static void __devinit isa_bridge_find_late(struct pci_dev *pdev,
+-                                         struct device_node *devnode)
+-{
+-      struct pci_controller *hose = pci_bus_to_host(pdev->bus);
 -
--at 0x000001bc : */    0x72100000,0x00000000,
--/*
--    JUMP reselected_not_end, IF NOT 0
+-      /* Store ISA device node and PCI device */
+-      isa_bridge_devnode = of_node_get(devnode);
+-      isa_bridge_pcidev = pdev;
 -
--at 0x000001be : */    0x80040000,0x00000738,
--/*
--    MOVE DSA1 TO SFBR
+-      /* Now parse the "ranges" property and setup the ISA mapping */
+-      pci_process_ISA_OF_ranges(devnode, hose->io_base_phys);
 -
--at 0x000001c0 : */    0x72110000,0x00000000,
--/*
--    JUMP reselected_not_end, IF NOT 0
+-      /* Set the global ISA io base to indicate we have an ISA bridge */
+-      isa_io_base = ISA_IO_BASE;
 -
--at 0x000001c2 : */    0x80040000,0x00000738,
--/*
--    MOVE DSA2 TO SFBR
+-      pr_debug("ISA bridge (late) is %s on %s\n",
+-               devnode->full_name, pci_name(pdev));
+-}
 -
--at 0x000001c4 : */    0x72120000,0x00000000,
--/*
--    JUMP reselected_not_end, IF NOT 0
+-/**
+- * isa_bridge_remove - Remove/unmap an ISA bridge
+- */
+-static void isa_bridge_remove(void)
+-{
+-      pr_debug("ISA bridge removed !\n");
 -
--at 0x000001c6 : */    0x80040000,0x00000738,
--/*
--    MOVE DSA3 TO SFBR
+-      /* Clear the global ISA io base to indicate that we have no more
+-       * ISA bridge. Note that drivers don't quite handle that, though
+-       * we should probably do something about it. But do we ever really
+-       * have ISA bridges being removed on machines using legacy devices ?
+-       */
+-      isa_io_base = ISA_IO_BASE;
 -
--at 0x000001c8 : */    0x72130000,0x00000000,
--/*
--    JUMP reselected_not_end, IF NOT 0
+-      /* Clear references to the bridge */
+-      of_node_put(isa_bridge_devnode);
+-      isa_bridge_devnode = NULL;
+-      isa_bridge_pcidev = NULL;
 -
--at 0x000001ca : */    0x80040000,0x00000738,
--/*
--    INT int_err_unexpected_reselect
+-      /* Unmap the ISA area */
+-      __iounmap_at((void *)ISA_IO_BASE, 0x10000);
+-}
 -
--at 0x000001cc : */    0x98080000,0x00020000,
--/*
+-/**
+- * isa_bridge_notify - Get notified of PCI devices addition/removal
+- */
+-static int __devinit isa_bridge_notify(struct notifier_block *nb,
+-                                     unsigned long action, void *data)
+-{
+-      struct device *dev = data;
+-      struct pci_dev *pdev = to_pci_dev(dev);
+-      struct device_node *devnode = pci_device_to_OF_node(pdev);
+-
+-      switch(action) {
+-      case BUS_NOTIFY_ADD_DEVICE:
+-              /* Check if we have an early ISA device, without PCI dev */
+-              if (isa_bridge_devnode && isa_bridge_devnode == devnode &&
+-                  !isa_bridge_pcidev) {
+-                      pr_debug("ISA bridge PCI attached: %s\n",
+-                               pci_name(pdev));
+-                      isa_bridge_pcidev = pdev;
+-              }
 -
--reselected_not_end:
--    ;
--    ; XXX the ALU is only eight bits wide, and the assembler
--    ; wont do the dirt work for us.  As long as dsa_check_reselect
--    ; is negative, we need to sign extend with 1 bits to the full
--    ; 32 bit width of the address.
--    ;
--    ; A potential work around would be to have a known alignment 
--    ; of the DSA structure such that the base address plus 
--    ; dsa_check_reselect doesn't require carrying from bytes 
--    ; higher than the LSB.
--    ;
--
--    MOVE DSA0 TO SFBR
--
--at 0x000001ce : */    0x72100000,0x00000000,
--/*
--    MOVE SFBR + dsa_check_reselect TO SCRATCH0
+-              /* Check if we have no ISA device, and this happens to be one,
+-               * register it as such if it has an OF device
+-               */
+-              if (!isa_bridge_devnode && devnode && devnode->type &&
+-                  !strcmp(devnode->type, "isa"))
+-                      isa_bridge_find_late(pdev, devnode);
 -
--at 0x000001d0 : */    0x6e340000,0x00000000,
--/*
--    MOVE DSA1 TO SFBR
+-              return 0;
+-      case BUS_NOTIFY_DEL_DEVICE:
+-              /* Check if this our existing ISA device */
+-              if (pdev == isa_bridge_pcidev ||
+-                  (devnode && devnode == isa_bridge_devnode))
+-                      isa_bridge_remove();
+-              return 0;
+-      }
+-      return 0;
+-}
 -
--at 0x000001d2 : */    0x72110000,0x00000000,
--/*
--    MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY
+-static struct notifier_block isa_bridge_notifier = {
+-      .notifier_call = isa_bridge_notify
+-};
 -
--at 0x000001d4 : */    0x6f35ff00,0x00000000,
+-/**
+- * isa_bridge_init - register to be notified of ISA bridge addition/removal
+- *
+- */
+-static int __init isa_bridge_init(void)
+-{
+-      if (firmware_has_feature(FW_FEATURE_ISERIES))
+-              return 0;
+-      bus_register_notifier(&pci_bus_type, &isa_bridge_notifier);
+-      return 0;
+-}
+-arch_initcall(isa_bridge_init);
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/kgdb.c linux-2.6.22-570/arch/powerpc/kernel/kgdb.c
+--- linux-2.6.22-590/arch/powerpc/kernel/kgdb.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/kgdb.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,499 +0,0 @@
 -/*
--    MOVE DSA2 TO SFBR
+- * arch/powerpc/kernel/kgdb.c
+- *
+- * PowerPC backend to the KGDB stub.
+- *
+- * Maintainer: Tom Rini <trini@kernel.crashing.org>
+- *
+- * Copied from arch/ppc/kernel/kgdb.c, updated for ppc64
+- *
+- * 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu)
+- * Copyright (C) 2003 Timesys Corporation.
+- * Copyright (C) 2004-2006 MontaVista Software, Inc.
+- * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
+- * PPC32 support restored by Vitaly Wool <vwool@ru.mvista.com> and
+- * Sergei Shtylyov <sshtylyov@ru.mvista.com>
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program as licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
 -
--at 0x000001d6 : */    0x72120000,0x00000000,
--/*
--    MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/kgdb.h>
+-#include <linux/smp.h>
+-#include <linux/signal.h>
+-#include <linux/ptrace.h>
+-#include <asm/current.h>
+-#include <asm/ptrace.h>
+-#include <asm/processor.h>
+-#include <asm/machdep.h>
 -
--at 0x000001d8 : */    0x6f36ff00,0x00000000,
 -/*
--    MOVE DSA3 TO SFBR
+- * This table contains the mapping between PowerPC hardware trap types, and
+- * signals, which are primarily what GDB understands.  GDB and the kernel
+- * don't always agree on values, so we use constants taken from gdb-6.2.
+- */
+-static struct hard_trap_info
+-{
+-      unsigned int tt;                /* Trap type code for powerpc */
+-      unsigned char signo;            /* Signal that we map this trap into */
+-} hard_trap_info[] = {
+-      { 0x0100, 0x02 /* SIGINT */  },         /* system reset */
+-      { 0x0200, 0x0b /* SIGSEGV */ },         /* machine check */
+-      { 0x0300, 0x0b /* SIGSEGV */ },         /* data access */
+-      { 0x0400, 0x0b /* SIGSEGV */ },         /* instruction access */
+-      { 0x0500, 0x02 /* SIGINT */  },         /* external interrupt */
+-      { 0x0600, 0x0a /* SIGBUS */  },         /* alignment */
+-      { 0x0700, 0x05 /* SIGTRAP */ },         /* program check */
+-      { 0x0800, 0x08 /* SIGFPE */  },         /* fp unavailable */
+-      { 0x0900, 0x0e /* SIGALRM */ },         /* decrementer */
+-      { 0x0c00, 0x14 /* SIGCHLD */ },         /* system call */
+-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+-      { 0x2002, 0x05 /* SIGTRAP */ },         /* debug */
+-#if defined(CONFIG_FSL_BOOKE)
+-      { 0x2010, 0x08 /* SIGFPE */  },         /* spe unavailable */
+-      { 0x2020, 0x08 /* SIGFPE */  },         /* spe unavailable */
+-      { 0x2030, 0x08 /* SIGFPE */  },         /* spe fp data */
+-      { 0x2040, 0x08 /* SIGFPE */  },         /* spe fp data */
+-      { 0x2050, 0x08 /* SIGFPE */  },         /* spe fp round */
+-      { 0x2060, 0x0e /* SIGILL */  },         /* performace monitor */
+-      { 0x2900, 0x08 /* SIGFPE */  },         /* apu unavailable */
+-      { 0x3100, 0x0e /* SIGALRM */ },         /* fixed interval timer */
+-      { 0x3200, 0x02 /* SIGINT */  },         /* watchdog */
+-#else
+-      { 0x1000, 0x0e /* SIGALRM */ },         /* programmable interval timer */
+-      { 0x1010, 0x0e /* SIGALRM */ },         /* fixed interval timer */
+-      { 0x1020, 0x02 /* SIGINT */  },         /* watchdog */
+-      { 0x2010, 0x08 /* SIGFPE */  },         /* fp unavailable */
+-      { 0x2020, 0x08 /* SIGFPE */  },         /* ap unavailable */
+-#endif
+-#else
+-      { 0x0d00, 0x05 /* SIGTRAP */ },         /* single-step */
+-#if defined(CONFIG_8xx)
+-      { 0x1000, 0x04 /* SIGILL */  },         /* software emulation */
+-#else
+-      { 0x0f00, 0x04 /* SIGILL */  },         /* performance monitor */
+-      { 0x0f20, 0x08 /* SIGFPE */  },         /* altivec unavailable */
+-      { 0x1300, 0x05 /* SIGTRAP */ },         /* instruction address break */
+-#if defined(CONFIG_PPC64)
+-      { 0x1200, 0x05 /* SIGILL */  },         /* system error */
+-      { 0x1500, 0x04 /* SIGILL */  },         /* soft patch */
+-      { 0x1600, 0x04 /* SIGILL */  },         /* maintenance */
+-      { 0x1700, 0x08 /* SIGFPE */  },         /* altivec assist */
+-      { 0x1800, 0x04 /* SIGILL */  },         /* thermal */
+-#else
+-      { 0x1400, 0x02 /* SIGINT */  },         /* SMI */
+-      { 0x1600, 0x08 /* SIGFPE */  },         /* altivec assist */
+-      { 0x1700, 0x04 /* SIGILL */  },         /* TAU */
+-      { 0x2000, 0x05 /* SIGTRAP */ },         /* run mode */
+-#endif
+-#endif
+-#endif
+-      { 0x0000, 0x00 }                        /* Must be last */
+-};
 -
--at 0x000001da : */    0x72130000,0x00000000,
--/*
--    MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY
+-extern atomic_t cpu_doing_single_step;
 -
--at 0x000001dc : */    0x6f37ff00,0x00000000,
--/*
+-static int computeSignal(unsigned int tt)
+-{
+-      struct hard_trap_info *ht;
 -
--    
--    MOVE MEMORY 4, addr_scratch, reselected_check + 4
+-      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+-              if (ht->tt == tt)
+-                      return ht->signo;
 -
--at 0x000001de : */    0xc0000004,0x00000000,0x00000794,
--/*
--    
+-      return SIGHUP;          /* default for things we don't know about */
+-}
 -
--    ; Time to correct DSA following memory move
--    MOVE MEMORY 4, saved_dsa, addr_dsa
+-static int kgdb_call_nmi_hook(struct pt_regs *regs)
+-{
+-      kgdb_nmihook(smp_processor_id(), regs);
+-      return 0;
+-}
 -
--at 0x000001e1 : */    0xc0000004,0x00000000,0x00000000,
--/*
+-#ifdef CONFIG_SMP
+-void kgdb_roundup_cpus(unsigned long flags)
+-{
+-      smp_send_debugger_break(MSG_ALL_BUT_SELF);
+-}
+-#endif
 -
--reselected_check:
--    JUMP 0
+-/* KGDB functions to use existing PowerPC64 hooks. */
+-static int kgdb_debugger(struct pt_regs *regs)
+-{
+-      return kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
+-}
 -
--at 0x000001e4 : */    0x80080000,0x00000000,
--/*
+-static int kgdb_breakpoint(struct pt_regs *regs)
+-{
+-      if (user_mode(regs))
+-              return 0;
 -
+-      kgdb_handle_exception(0, SIGTRAP, 0, regs);
 -
--;
--;
+-      if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
+-              regs->nip += 4;
 -
--; We have problems here - the memory move corrupts TEMP and DSA.  This
--; routine is called from DSA code, and patched from many places.  Scratch
--; is probably free when it is called.
--; We have to:
--;   copy temp to scratch, one byte at a time
--;   write scratch to patch a jump in place of the return
--;   do the move memory
--;   jump to the patched in return address
--; DSA is corrupt when we get here, and can be left corrupt
+-      return 1;
+-}
 -
--ENTRY reselected_ok
--reselected_ok:
--    MOVE TEMP0 TO SFBR
+-static int kgdb_singlestep(struct pt_regs *regs)
+-{
+-      struct thread_info *thread_info, *exception_thread_info;
 -
--at 0x000001e6 : */    0x721c0000,0x00000000,
--/*
--    MOVE SFBR TO SCRATCH0
+-      if (user_mode(regs))
+-              return 0;
 -
--at 0x000001e8 : */    0x6a340000,0x00000000,
--/*
--    MOVE TEMP1 TO SFBR
+-      /*
+-       * On Book E and perhaps other processsors, singlestep is handled on
+-       * the critical exception stack.  This causes current_thread_info()
+-       * to fail, since it it locates the thread_info by masking off
+-       * the low bits of the current stack pointer.  We work around
+-       * this issue by copying the thread_info from the kernel stack
+-       * before calling kgdb_handle_exception, and copying it back
+-       * afterwards.  On most processors the copy is avoided since
+-       * exception_thread_info == thread_info.
+-       */
+-      thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
+-      exception_thread_info = current_thread_info();
 -
--at 0x000001ea : */    0x721d0000,0x00000000,
--/*
--    MOVE SFBR TO SCRATCH1
+-      if (thread_info != exception_thread_info)
+-              memcpy(exception_thread_info, thread_info, sizeof *thread_info);
 -
--at 0x000001ec : */    0x6a350000,0x00000000,
--/*
--    MOVE TEMP2 TO SFBR
+-      kgdb_handle_exception(0, SIGTRAP, 0, regs);
 -
--at 0x000001ee : */    0x721e0000,0x00000000,
--/*
--    MOVE SFBR TO SCRATCH2
+-      if (thread_info != exception_thread_info)
+-              memcpy(thread_info, exception_thread_info, sizeof *thread_info);
 -
--at 0x000001f0 : */    0x6a360000,0x00000000,
--/*
--    MOVE TEMP3 TO SFBR
+-      return 1;
+-}
 -
--at 0x000001f2 : */    0x721f0000,0x00000000,
--/*
--    MOVE SFBR TO SCRATCH3
+-int kgdb_iabr_match(struct pt_regs *regs)
+-{
+-      if (user_mode(regs))
+-              return 0;
 -
--at 0x000001f4 : */    0x6a370000,0x00000000,
--/*
--    MOVE MEMORY 4, addr_scratch, reselected_ok_jump + 4
+-      kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
+-      return 1;
+-}
 -
--at 0x000001f6 : */    0xc0000004,0x00000000,0x000007f4,
--/*
--reselected_ok_patch:
--    MOVE MEMORY 4, 0, 0
+-int kgdb_dabr_match(struct pt_regs *regs)
+-{
+-      if (user_mode(regs))
+-              return 0;
 -
--at 0x000001f9 : */    0xc0000004,0x00000000,0x00000000,
--/*
--reselected_ok_jump:
--    JUMP 0
+-      kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
+-      return 1;
+-}
 -
--at 0x000001fc : */    0x80080000,0x00000000,
--/*
+-#define PACK64(ptr,src) do { *(ptr++) = (src); } while(0)
 -
+-#define PACK32(ptr,src) do {          \
+-      u32 *ptr32;                   \
+-      ptr32 = (u32 *)ptr;           \
+-      *(ptr32++) = (src);           \
+-      ptr = (unsigned long *)ptr32; \
+-      } while(0)
 -
 -
+-void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+-{
+-      unsigned long *ptr = gdb_regs;
+-      int reg;
 -
+-      memset(gdb_regs, 0, NUMREGBYTES);
 -
--selected:
--    INT int_err_selected;
+-      for (reg = 0; reg < 32; reg++)
+-              PACK64(ptr, regs->gpr[reg]);
 -
--at 0x000001fe : */    0x98080000,0x00010000,
--/*
+-#ifdef CONFIG_FSL_BOOKE
+-#ifdef CONFIG_SPE
+-      for (reg = 0; reg < 32; reg++)
+-              PACK64(ptr, current->thread.evr[reg]);
+-#else
+-      ptr += 32;
+-#endif
+-#else
+-      /* fp registers not used by kernel, leave zero */
+-      ptr += 32 * 8 / sizeof(long);
+-#endif
 -
--;
--; A select or reselect failure can be caused by one of two conditions : 
--; 1.  SIG_P was set.  This will be the case if the user has written
--;     a new value to a previously NULL head of the issue queue.
--;
--; 2.  The NCR53c810 was selected or reselected by another device.
--;
--; 3.  The bus was already busy since we were selected or reselected
--;     before starting the command.
+-      PACK64(ptr, regs->nip);
+-      PACK64(ptr, regs->msr);
+-      PACK32(ptr, regs->ccr);
+-      PACK64(ptr, regs->link);
+-      PACK64(ptr, regs->ctr);
+-      PACK32(ptr, regs->xer);
 -
--wait_reselect_failed:
+-#if 0
+-      Following are in struct thread_struct, not struct pt_regs,
+-      ignoring for now since kernel does not use them.  Would it
+-      make sense to get them from the thread that kgdb is set to?
 -
+-      If this code is enabled, update the definition of NUMREGBYTES to
+-      include the vector registers and vector state registers.
 -
+-      PACK32(ptr, current->thread->fpscr);
 -
--; Check selected bit.  
+-      /* vr registers not used by kernel, leave zero */
+-      ptr += 32 * 16 / sizeof(long);
 -
--    ; Must work out how to tell if we are selected....
+-#ifdef CONFIG_ALTIVEC
+-      PACK32(ptr, current->thread->vscr);
+-      PACK32(ptr, current->thread->vrsave);
+-#else
+-      ptr += 2 * 4 / sizeof(long);
+-#endif
+-#else
+-#ifdef CONFIG_FSL_BOOKE
+-#ifdef CONFIG_SPE
+-      /* u64 acc */
+-      PACK32(ptr, current->thread.acc >> 32);
+-      PACK32(ptr, current->thread.acc & 0xffffffff);
+-      PACK64(ptr, current->thread.spefscr);
+-#else
+-      ptr += 2 + 1;
+-#endif
+-#else
+-      /* fpscr not used by kernel, leave zero */
+-      PACK32(ptr, 0);
+-#endif
+-#endif
 -
+-      BUG_ON((unsigned long)ptr >
+-             (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
+-}
 -
+-void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+-{
+-      struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
+-                                                STACK_FRAME_OVERHEAD);
+-      unsigned long *ptr = gdb_regs;
+-      int reg;
 -
+-      memset(gdb_regs, 0, NUMREGBYTES);
 -
--; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
--    MOVE CTEST2 & 0x40 TO SFBR        
+-      /* Regs GPR0-2 */
+-      for (reg = 0; reg < 3; reg++)
+-              PACK64(ptr, regs->gpr[reg]);
 -
--at 0x00000200 : */    0x74164000,0x00000000,
--/*
--    JUMP schedule, IF 0x40
+-      /* Regs GPR3-13 are caller saved, not in regs->gpr[] */
+-      ptr += 11;
 -
--at 0x00000202 : */    0x800c0040,0x00000000,
--/*
--; Check connected bit.  
--; FIXME: this needs to change if we support target mode
--    MOVE ISTAT & 0x08 TO SFBR
+-      /* Regs GPR14-31 */
+-      for (reg = 14; reg < 32; reg++)
+-              PACK64(ptr, regs->gpr[reg]);
 -
--at 0x00000204 : */    0x74210800,0x00000000,
--/*
--    JUMP reselected, IF 0x08
+-#ifdef CONFIG_FSL_BOOKE
+-#ifdef CONFIG_SPE
+-      for (reg = 0; reg < 32; reg++)
+-              PACK64(ptr, p->thread.evr[reg]);
+-#else
+-      ptr += 32;
+-#endif
+-#else
+-      /* fp registers not used by kernel, leave zero */
+-      ptr += 32 * 8 / sizeof(long);
+-#endif
 -
--at 0x00000206 : */    0x800c0008,0x000006b0,
--/*
--; FIXME : Something bogus happened, and we shouldn't fail silently.
+-      PACK64(ptr, regs->nip);
+-      PACK64(ptr, regs->msr);
+-      PACK32(ptr, regs->ccr);
+-      PACK64(ptr, regs->link);
+-      PACK64(ptr, regs->ctr);
+-      PACK32(ptr, regs->xer);
 -
+-#if 0
+-      Following are in struct thread_struct, not struct pt_regs,
+-      ignoring for now since kernel does not use them.  Would it
+-      make sense to get them from the thread that kgdb is set to?
 -
+-      If this code is enabled, update the definition of NUMREGBYTES to
+-      include the vector registers and vector state registers.
 -
--    INT int_debug_panic
+-      PACK32(ptr, p->thread->fpscr);
 -
--at 0x00000208 : */    0x98080000,0x030b0000,
--/*
+-      /* vr registers not used by kernel, leave zero */
+-      ptr += 32 * 16 / sizeof(long);
 -
+-#ifdef CONFIG_ALTIVEC
+-      PACK32(ptr, p->thread->vscr);
+-      PACK32(ptr, p->thread->vrsave);
+-#else
+-      ptr += 2 * 4 / sizeof(long);
+-#endif
+-#else
+-#ifdef CONFIG_FSL_BOOKE
+-#ifdef CONFIG_SPE
+-      /* u64 acc */
+-      PACK32(ptr, p->thread.acc >> 32);
+-      PACK32(ptr, p->thread.acc & 0xffffffff);
+-      PACK64(ptr, p->thread.spefscr);
+-#else
+-      ptr += 2 + 1;
+-#endif
+-#else
+-      /* fpscr not used by kernel, leave zero */
+-      PACK32(ptr, 0);
+-#endif
+-#endif
 -
+-      BUG_ON((unsigned long)ptr >
+-             (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
+-}
 -
--select_failed:
+-#define UNPACK64(dest,ptr) do { dest = *(ptr++); } while(0)
 -
--    ; Disable selection timer
--    MOVE CTEST7 | 0x10 TO CTEST7
+-#define UNPACK32(dest,ptr) do {       \
+-      u32 *ptr32;                   \
+-      ptr32 = (u32 *)ptr;           \
+-      dest = *(ptr32++);            \
+-      ptr = (unsigned long *)ptr32; \
+-      } while(0)
 -
--at 0x0000020a : */    0x7a1b1000,0x00000000,
--/*
+-void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+-{
+-      unsigned long *ptr = gdb_regs;
+-      int reg;
+-#ifdef CONFIG_SPE
+-      union {
+-              u32 v32[2];
+-              u64 v64;
+-      } acc;
+-#endif
 -
+-      for (reg = 0; reg < 32; reg++)
+-              UNPACK64(regs->gpr[reg], ptr);
 -
+-#ifdef CONFIG_FSL_BOOKE
+-#ifdef CONFIG_SPE
+-      for (reg = 0; reg < 32; reg++)
+-              UNPACK64(current->thread.evr[reg], ptr);
+-#else
+-      ptr += 32;
+-#endif
+-#else
+-      /* fp registers not used by kernel, leave zero */
+-      ptr += 32 * 8 / sizeof(int);
+-#endif
 -
+-      UNPACK64(regs->nip, ptr);
+-      UNPACK64(regs->msr, ptr);
+-      UNPACK32(regs->ccr, ptr);
+-      UNPACK64(regs->link, ptr);
+-      UNPACK64(regs->ctr, ptr);
+-      UNPACK32(regs->xer, ptr);
 -
--; Otherwise, mask the selected and reselected bits off SIST0
+-#if 0
+-      Following are in struct thread_struct, not struct pt_regs,
+-      ignoring for now since kernel does not use them.  Would it
+-      make sense to get them from the thread that kgdb is set to?
 -
--    ; Let's assume we don't get selected for now
--    MOVE SSTAT0 & 0x10 TO SFBR
+-      If this code is enabled, update the definition of NUMREGBYTES to
+-      include the vector registers and vector state registers.
 -
--at 0x0000020c : */    0x740d1000,0x00000000,
--/*
+-      /* fpscr, vscr, vrsave not used by kernel, leave unchanged */
 -
+-      UNPACK32(current->thread->fpscr, ptr);
 -
+-      /* vr registers not used by kernel, leave zero */
+-      ptr += 32 * 16 / sizeof(long);
 -
+-#ifdef CONFIG_ALTIVEC
+-      UNPACK32(current->thread->vscr, ptr);
+-      UNPACK32(current->thread->vrsave, ptr);
+-#else
+-      ptr += 2 * 4 / sizeof(long);
+-#endif
+-#else
+-#ifdef CONFIG_FSL_BOOKE
+-#ifdef CONFIG_SPE
+-      /* u64 acc */
+-      UNPACK32(acc.v32[0], ptr);
+-      UNPACK32(acc.v32[1], ptr);
+-      current->thread.acc = acc.v64;
+-      UNPACK64(current->thread.spefscr, ptr);
+-#else
+-      ptr += 2 + 1;
+-#endif
+-#endif
+-#endif
 -
--    JUMP reselected, IF 0x10 
+-      BUG_ON((unsigned long)ptr >
+-             (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
+-}
 -
--at 0x0000020e : */    0x800c0010,0x000006b0,
 -/*
--; If SIGP is set, the user just gave us another command, and
--; we should restart or return to the scheduler.
--; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
--    MOVE CTEST2 & 0x40 TO SFBR        
+- * This function does PowerPC specific procesing for interfacing to gdb.
+- */
+-int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+-                             char *remcom_in_buffer, char *remcom_out_buffer,
+-                             struct pt_regs *linux_regs)
+-{
+-      char *ptr = &remcom_in_buffer[1];
+-      unsigned long addr;
 -
--at 0x00000210 : */    0x74164000,0x00000000,
--/*
--    JUMP select, IF 0x40
+-      switch (remcom_in_buffer[0]) {
+-              /*
+-               * sAA..AA   Step one instruction from AA..AA
+-               * This will return an error to gdb ..
+-               */
+-      case 's':
+-      case 'c':
+-              /* handle the optional parameter */
+-              if (kgdb_hex2long(&ptr, &addr))
+-                      linux_regs->nip = addr;
+-
+-              atomic_set(&cpu_doing_single_step, -1);
+-              /* set the trace bit if we're stepping */
+-              if (remcom_in_buffer[0] == 's') {
+-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+-                      mtspr(SPRN_DBCR0,
+-                            mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
+-                      linux_regs->msr |= MSR_DE;
+-#else
+-                      linux_regs->msr |= MSR_SE;
+-#endif
+-                      debugger_step = 1;
+-                      if (kgdb_contthread)
+-                              atomic_set(&cpu_doing_single_step,
+-                                         smp_processor_id());
+-              }
+-              return 0;
+-      }
 -
--at 0x00000212 : */    0x800c0040,0x000001f8,
--/*
--; Check connected bit.  
--; FIXME: this needs to change if we support target mode
--; FIXME: is this really necessary? 
--    MOVE ISTAT & 0x08 TO SFBR
+-      return -1;
+-}
 -
--at 0x00000214 : */    0x74210800,0x00000000,
 -/*
--    JUMP reselected, IF 0x08
+- * Global data
+- */
+-struct kgdb_arch arch_kgdb_ops = {
+-      .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
+-};
 -
--at 0x00000216 : */    0x800c0008,0x000006b0,
--/*
--; FIXME : Something bogus happened, and we shouldn't fail silently.
+-int kgdb_not_implemented(struct pt_regs *regs)
+-{
+-      return 0;
+-}
 -
+-int kgdb_arch_init(void)
+-{
+-#ifdef CONFIG_XMON
+-#error Both XMON and KGDB selected in .config.  Unselect one of them.
+-#endif
 -
+-      __debugger_ipi = kgdb_call_nmi_hook;
+-      __debugger = kgdb_debugger;
+-      __debugger_bpt = kgdb_breakpoint;
+-      __debugger_sstep = kgdb_singlestep;
+-      __debugger_iabr_match = kgdb_iabr_match;
+-      __debugger_dabr_match = kgdb_dabr_match;
+-      __debugger_fault_handler = kgdb_not_implemented;
 -
--    INT int_debug_panic
+-      return 0;
+-}
 -
--at 0x00000218 : */    0x98080000,0x030b0000,
+-arch_initcall(kgdb_arch_init);
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/kgdb_setjmp32.S linux-2.6.22-570/arch/powerpc/kernel/kgdb_setjmp32.S
+--- linux-2.6.22-590/arch/powerpc/kernel/kgdb_setjmp32.S       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/kgdb_setjmp32.S       1969-12-31 19:00:00.000000000 -0500
+@@ -1,41 +0,0 @@
 -/*
+- * Copyright (C) 1996 Paul Mackerras
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program as licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
 -
+-#include <asm/processor.h>
+-#include <asm/ppc_asm.h>
 -
--;
--; test_1
--; test_2
--;
--; PURPOSE : run some verification tests on the NCR.  test_1
--;     copies test_src to test_dest and interrupts the host
--;     processor, testing for cache coherency and interrupt
--;     problems in the processes.
--;
--;     test_2 runs a command with offsets relative to the 
--;     DSA on entry, and is useful for miscellaneous experimentation.
--;
--
--; Verify that interrupts are working correctly and that we don't 
--; have a cache invalidation problem.
--
--ABSOLUTE test_src = 0, test_dest = 0
--ENTRY test_1
--test_1:
--    MOVE MEMORY 4, test_src, test_dest
--
--at 0x0000021a : */    0xc0000004,0x00000000,0x00000000,
--/*
--    INT int_test_1
+-      .text
 -
--at 0x0000021d : */    0x98080000,0x04000000,
 -/*
+- * Save/restore state in case a memory access causes a fault.
+- *
+- * int kgdb_fault_setjmp(unsigned long *curr_context);
+- * void kgdb_fault_longjmp(unsigned long *curr_context);
+- */
 -
--;
--; Run arbitrary commands, with test code establishing a DSA
--;
-- 
--ENTRY test_2
--test_2:
--    CLEAR TARGET
+-_GLOBAL(kgdb_fault_setjmp)
+-      mflr    r0
+-      stw     r0,0(r3)
+-      stw     r1,4(r3)
+-      stw     r2,8(r3)
+-      mfcr    r0
+-      stw     r0,12(r3)
+-      stmw    r13,16(r3)
+-      li      r3,0
+-      blr
 -
--at 0x0000021f : */    0x60000200,0x00000000,
+-_GLOBAL(kgdb_fault_longjmp)
+-      lmw     r13,16(r3)
+-      lwz     r0,12(r3)
+-      mtcrf   0x38,r0
+-      lwz     r0,0(r3)
+-      lwz     r1,4(r3)
+-      lwz     r2,8(r3)
+-      mtlr    r0
+-      mr      r3,r1
+-      blr
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/kgdb_setjmp64.S linux-2.6.22-570/arch/powerpc/kernel/kgdb_setjmp64.S
+--- linux-2.6.22-590/arch/powerpc/kernel/kgdb_setjmp64.S       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/kgdb_setjmp64.S       1969-12-31 19:00:00.000000000 -0500
+@@ -1,77 +0,0 @@
 -/*
+- * Copyright (C) 1996 Paul Mackerras
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program as licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
 -
--    ; Enable selection timer
--
--
+-#include <asm/processor.h>
+-#include <asm/ppc_asm.h>
 -
--    MOVE CTEST7 & 0xef TO CTEST7
+-      .text
 -
--at 0x00000221 : */    0x7c1bef00,0x00000000,
 -/*
+- * Save/restore state in case a memory access causes a fault.
+- *
+- * int kgdb_fault_setjmp(unsigned long *curr_context);
+- * void kgdb_fault_longjmp(unsigned long *curr_context);
+- */
 -
+-_GLOBAL(kgdb_fault_setjmp)
+-      mflr    r0
+-      std     r0,0(r3)
+-      std     r1,8(r3)
+-      std     r2,16(r3)
+-      mfcr    r0
+-      std     r0,24(r3)
+-      std     r13,32(r3)
+-      std     r14,40(r3)
+-      std     r15,48(r3)
+-      std     r16,56(r3)
+-      std     r17,64(r3)
+-      std     r18,72(r3)
+-      std     r19,80(r3)
+-      std     r20,88(r3)
+-      std     r21,96(r3)
+-      std     r22,104(r3)
+-      std     r23,112(r3)
+-      std     r24,120(r3)
+-      std     r25,128(r3)
+-      std     r26,136(r3)
+-      std     r27,144(r3)
+-      std     r28,152(r3)
+-      std     r29,160(r3)
+-      std     r30,168(r3)
+-      std     r31,176(r3)
+-      li      r3,0
+-      blr
 -
--    SELECT ATN FROM 0, test_2_fail
+-_GLOBAL(kgdb_fault_longjmp)
+-      ld      r13,32(r3)
+-      ld      r14,40(r3)
+-      ld      r15,48(r3)
+-      ld      r16,56(r3)
+-      ld      r17,64(r3)
+-      ld      r18,72(r3)
+-      ld      r19,80(r3)
+-      ld      r20,88(r3)
+-      ld      r21,96(r3)
+-      ld      r22,104(r3)
+-      ld      r23,112(r3)
+-      ld      r24,120(r3)
+-      ld      r25,128(r3)
+-      ld      r26,136(r3)
+-      ld      r27,144(r3)
+-      ld      r28,152(r3)
+-      ld      r29,160(r3)
+-      ld      r30,168(r3)
+-      ld      r31,176(r3)
+-      ld      r0,24(r3)
+-      mtcrf   0x38,r0
+-      ld      r0,0(r3)
+-      ld      r1,8(r3)
+-      ld      r2,16(r3)
+-      mtlr    r0
+-      mr      r3,r1
+-      blr
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/legacy_serial.c linux-2.6.22-570/arch/powerpc/kernel/legacy_serial.c
+--- linux-2.6.22-590/arch/powerpc/kernel/legacy_serial.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/legacy_serial.c       2007-07-08 19:32:17.000000000 -0400
+@@ -11,9 +11,6 @@
+ #include <asm/udbg.h>
+ #include <asm/pci-bridge.h>
+ #include <asm/ppc-pci.h>
+-#ifdef CONFIG_KGDB_8250
+-#include <linux/kgdb.h>
+-#endif
+ #undef DEBUG
+@@ -490,9 +487,6 @@
+                       fixup_port_pio(i, np, port);
+               if ((port->iotype == UPIO_MEM) || (port->iotype == UPIO_TSI))
+                       fixup_port_mmio(i, np, port);
+-#ifdef CONFIG_KGDB_8250
+-              kgdb8250_add_platform_port(i, port);
+-#endif
+       }
+       DBG("Registering platform serial ports\n");
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/misc_32.S linux-2.6.22-570/arch/powerpc/kernel/misc_32.S
+--- linux-2.6.22-590/arch/powerpc/kernel/misc_32.S     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/misc_32.S     2008-01-23 19:16:03.000000000 -0500
+@@ -392,7 +392,7 @@
+       mtspr   SPRN_L1CSR0,r3
+       isync
+       blr
+-END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
++END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+       mfspr   r3,SPRN_L1CSR1
+       ori     r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
+       mtspr   SPRN_L1CSR1,r3
+@@ -419,7 +419,7 @@
+ _GLOBAL(__flush_icache_range)
+ BEGIN_FTR_SECTION
+       blr                             /* for 601, do nothing */
+-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
++END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+       li      r5,L1_CACHE_BYTES-1
+       andc    r3,r3,r5
+       subf    r4,r3,r4
+@@ -514,8 +514,8 @@
+  */
+ _GLOBAL(__flush_dcache_icache)
+ BEGIN_FTR_SECTION
+-      blr
+-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
++      blr                                     /* for 601, do nothing */
++END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+       rlwinm  r3,r3,0,0,19                    /* Get page base address */
+       li      r4,4096/L1_CACHE_BYTES  /* Number of lines in a page */
+       mtctr   r4
+@@ -543,7 +543,7 @@
+ _GLOBAL(__flush_dcache_icache_phys)
+ BEGIN_FTR_SECTION
+       blr                                     /* for 601, do nothing */
+-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
++END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+       mfmsr   r10
+       rlwinm  r0,r10,0,28,26                  /* clear DR */
+       mtmsr   r0
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/of_platform.c linux-2.6.22-570/arch/powerpc/kernel/of_platform.c
+--- linux-2.6.22-590/arch/powerpc/kernel/of_platform.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/of_platform.c 2007-07-08 19:32:17.000000000 -0400
+@@ -427,6 +427,14 @@
+       /* Process "ranges" property */
+       pci_process_bridge_OF_ranges(phb, dev->node, 0);
++      /* Setup IO space. We use the non-dynamic version of that code here,
++       * which doesn't quite support unplugging. Next kernel release will
++       * have a better fix for this.
++       * Note also that we don't do ISA, this will also be fixed with a
++       * more massive rework.
++       */
++      pci_setup_phb_io(phb, pci_io_base == 0);
++
+       /* Init pci_dn data structures */
+       pci_devs_phb_init_dynamic(phb);
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/pci_64.c linux-2.6.22-570/arch/powerpc/kernel/pci_64.c
+--- linux-2.6.22-590/arch/powerpc/kernel/pci_64.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/pci_64.c      2007-07-08 19:32:17.000000000 -0400
+@@ -11,7 +11,7 @@
+  *      2 of the License, or (at your option) any later version.
+  */
+-#define DEBUG
++#undef DEBUG
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+@@ -22,7 +22,6 @@
+ #include <linux/list.h>
+ #include <linux/syscalls.h>
+ #include <linux/irq.h>
+-#include <linux/vmalloc.h>
+ #include <asm/processor.h>
+ #include <asm/io.h>
+@@ -42,26 +41,35 @@
+ unsigned long pci_probe_only = 1;
+ int pci_assign_all_buses = 0;
++static int pci_initial_scan_done;
+ static void fixup_resource(struct resource *res, struct pci_dev *dev);
+ static void do_bus_setup(struct pci_bus *bus);
++static void phbs_remap_io(void);
+ /* pci_io_base -- the base address from which io bars are offsets.
+  * This is the lowest I/O base address (so bar values are always positive),
+  * and it *must* be the start of ISA space if an ISA bus exists because
+- * ISA drivers use hard coded offsets.  If no ISA bus exists nothing
+- * is mapped on the first 64K of IO space
++ * ISA drivers use hard coded offsets.  If no ISA bus exists a dummy
++ * page is mapped and isa_io_limit prevents access to it.
+  */
+-unsigned long pci_io_base = ISA_IO_BASE;
++unsigned long isa_io_base;    /* NULL if no ISA bus */
++EXPORT_SYMBOL(isa_io_base);
++unsigned long pci_io_base;
+ EXPORT_SYMBOL(pci_io_base);
++void iSeries_pcibios_init(void);
++
+ LIST_HEAD(hose_list);
+ static struct dma_mapping_ops *pci_dma_ops;
+-/* XXX kill that some day ... */
+ int global_phb_number;                /* Global phb counter */
++/* Cached ISA bridge dev. */
++struct pci_dev *ppc64_isabridge_dev = NULL;
++EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
++
+ void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
+ {
+       pci_dma_ops = dma_ops;
+@@ -92,7 +100,7 @@
+               return;
+       if (res->flags & IORESOURCE_IO)
+-              offset = (unsigned long)hose->io_base_virt - _IO_BASE;
++              offset = (unsigned long)hose->io_base_virt - pci_io_base;
+       if (res->flags & IORESOURCE_MEM)
+               offset = hose->pci_mem_offset;
+@@ -111,7 +119,7 @@
+               return;
+       if (res->flags & IORESOURCE_IO)
+-              offset = (unsigned long)hose->io_base_virt - _IO_BASE;
++              offset = (unsigned long)hose->io_base_virt - pci_io_base;
+       if (res->flags & IORESOURCE_MEM)
+               offset = hose->pci_mem_offset;
+@@ -148,7 +156,7 @@
+       if (res->flags & IORESOURCE_IO) {
+               unsigned long offset = (unsigned long)hose->io_base_virt -
+-                                      _IO_BASE;
++                                      pci_io_base;
+               /* Make sure we start at our min on all hoses */
+               if (start - offset < PCIBIOS_MIN_IO)
+                       start = PCIBIOS_MIN_IO + offset;
+@@ -527,16 +535,10 @@
+       bus->secondary = hose->first_busno;
+       hose->bus = bus;
+-      if (!firmware_has_feature(FW_FEATURE_ISERIES))
+-              pcibios_map_io_space(bus);
 -
--at 0x00000223 : */    0x43000000,0x000008dc,
--/*
--    JUMP test_2_msgout, WHEN MSG_OUT
+       bus->resource[0] = res = &hose->io_resource;
+-      if (res->flags && request_resource(&ioport_resource, res)) {
++      if (res->flags && request_resource(&ioport_resource, res))
+               printk(KERN_ERR "Failed to request PCI IO region "
+                      "on PCI domain %04x\n", hose->global_number);
+-              DBG("res->start = 0x%016lx, res->end = 0x%016lx\n",
+-                  res->start, res->end);
+-      }
+       for (i = 0; i < 3; ++i) {
+               res = &hose->mem_resources[i];
+@@ -594,6 +596,17 @@
+       if (ppc_md.pcibios_fixup)
+               ppc_md.pcibios_fixup();
++      /* Cache the location of the ISA bridge (if we have one) */
++      ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
++      if (ppc64_isabridge_dev != NULL)
++              printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
++
++      if (!firmware_has_feature(FW_FEATURE_ISERIES))
++              /* map in PCI I/O space */
++              phbs_remap_io();
++
++      pci_initial_scan_done = 1;
++
+       printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
+       return 0;
+@@ -698,7 +711,7 @@
+ #endif
+               res_bit = IORESOURCE_MEM;
+       } else {
+-              io_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
++              io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
+               *offset += io_offset;
+               res_bit = IORESOURCE_IO;
+       }
+@@ -868,6 +881,76 @@
+       device_create_file(&pdev->dev, &dev_attr_devspec);
+ }
++#define ISA_SPACE_MASK 0x1
++#define ISA_SPACE_IO 0x1
++
++static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
++                                    unsigned long phb_io_base_phys,
++                                    void __iomem * phb_io_base_virt)
++{
++      /* Remove these asap */
++
++      struct pci_address {
++              u32 a_hi;
++              u32 a_mid;
++              u32 a_lo;
++      };
++
++      struct isa_address {
++              u32 a_hi;
++              u32 a_lo;
++      };
++
++      struct isa_range {
++              struct isa_address isa_addr;
++              struct pci_address pci_addr;
++              unsigned int size;
++      };
++
++      const struct isa_range *range;
++      unsigned long pci_addr;
++      unsigned int isa_addr;
++      unsigned int size;
++      int rlen = 0;
++
++      range = of_get_property(isa_node, "ranges", &rlen);
++      if (range == NULL || (rlen < sizeof(struct isa_range))) {
++              printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
++                     "mapping 64k\n");
++              __ioremap_explicit(phb_io_base_phys,
++                                 (unsigned long)phb_io_base_virt,
++                                 0x10000, _PAGE_NO_CACHE | _PAGE_GUARDED);
++              return; 
++      }
++      
++      /* From "ISA Binding to 1275"
++       * The ranges property is laid out as an array of elements,
++       * each of which comprises:
++       *   cells 0 - 1:       an ISA address
++       *   cells 2 - 4:       a PCI address 
++       *                      (size depending on dev->n_addr_cells)
++       *   cell 5:            the size of the range
++       */
++      if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) {
++              isa_addr = range->isa_addr.a_lo;
++              pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | 
++                      range->pci_addr.a_lo;
++
++              /* Assume these are both zero */
++              if ((pci_addr != 0) || (isa_addr != 0)) {
++                      printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
++                                      __FUNCTION__);
++                      return;
++              }
++              
++              size = PAGE_ALIGN(range->size);
++
++              __ioremap_explicit(phb_io_base_phys, 
++                                 (unsigned long) phb_io_base_virt, 
++                                 size, _PAGE_NO_CACHE | _PAGE_GUARDED);
++      }
++}
++
+ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
+                                           struct device_node *dev, int prim)
+ {
+@@ -962,122 +1045,155 @@
+       }
+ }
+-#ifdef CONFIG_HOTPLUG
 -
--at 0x00000225 : */    0x860b0000,0x0000089c,
--/*
--ENTRY test_2_msgout
--test_2_msgout:
+-int pcibios_unmap_io_space(struct pci_bus *bus)
++void __devinit pci_setup_phb_io(struct pci_controller *hose, int primary)
+ {
+-      struct pci_controller *hose;
++      unsigned long size = hose->pci_io_size;
++      unsigned long io_virt_offset;
++      struct resource *res;
++      struct device_node *isa_dn;
+-      WARN_ON(bus == NULL);
++      if (size == 0)
++              return;
+-      /* If this is not a PHB, we only flush the hash table over
+-       * the area mapped by this bridge. We don't play with the PTE
+-       * mappings since we might have to deal with sub-page alignemnts
+-       * so flushing the hash table is the only sane way to make sure
+-       * that no hash entries are covering that removed bridge area
+-       * while still allowing other busses overlapping those pages
+-       */
+-      if (bus->self) {
+-              struct resource *res = bus->resource[0];
++      hose->io_base_virt = reserve_phb_iospace(size);
++      DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
++              hose->global_number, hose->io_base_phys,
++              (unsigned long) hose->io_base_virt);
++
++      if (primary) {
++              pci_io_base = (unsigned long)hose->io_base_virt;
++              isa_dn = of_find_node_by_type(NULL, "isa");
++              if (isa_dn) {
++                      isa_io_base = pci_io_base;
++                      pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys,
++                                              hose->io_base_virt);
++                      of_node_put(isa_dn);
++              }
++      }
+-              DBG("IO unmapping for PCI-PCI bridge %s\n",
+-                  pci_name(bus->self));
++      io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
++      res = &hose->io_resource;
++      res->start += io_virt_offset;
++      res->end += io_virt_offset;
+-              __flush_hash_table_range(&init_mm, res->start + _IO_BASE,
+-                                       res->end - res->start + 1);
+-              return 0;
+-      }
++      /* If this is called after the initial PCI scan, then we need to
++       * proceed to IO mappings now
++       */
++      if (pci_initial_scan_done)
++              __ioremap_explicit(hose->io_base_phys,
++                                 (unsigned long)hose->io_base_virt,
++                                 hose->pci_io_size,
++                                 _PAGE_NO_CACHE | _PAGE_GUARDED);
++}
+-      /* Get the host bridge */
+-      hose = pci_bus_to_host(bus);
++void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose,
++                                      int primary)
++{
++      unsigned long size = hose->pci_io_size;
++      unsigned long io_virt_offset;
++      struct resource *res;
+-      /* Check if we have IOs allocated */
+-      if (hose->io_base_alloc == 0)
+-              return 0;
++      if (size == 0)
++              return;
+-      DBG("IO unmapping for PHB %s\n",
+-          ((struct device_node *)hose->arch_data)->full_name);
+-      DBG("  alloc=0x%p\n", hose->io_base_alloc);
++      hose->io_base_virt = __ioremap(hose->io_base_phys, size,
++                                      _PAGE_NO_CACHE | _PAGE_GUARDED);
++      DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
++              hose->global_number, hose->io_base_phys,
++              (unsigned long) hose->io_base_virt);
+-      /* This is a PHB, we fully unmap the IO area */
+-      vunmap(hose->io_base_alloc);
++      if (primary)
++              pci_io_base = (unsigned long)hose->io_base_virt;
+-      return 0;
++      io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
++      res = &hose->io_resource;
++      res->start += io_virt_offset;
++      res->end += io_virt_offset;
+ }
+-EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
+-#endif /* CONFIG_HOTPLUG */
+-int __devinit pcibios_map_io_space(struct pci_bus *bus)
++static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys,
++                              unsigned long *start_virt, unsigned long *size)
+ {
+-      struct vm_struct *area;
+-      unsigned long phys_page;
+-      unsigned long size_page;
+-      unsigned long io_virt_offset;
+-      struct pci_controller *hose;
++      struct pci_controller *hose = pci_bus_to_host(bus);
++      struct resource *res;
+       
+-      WARN_ON(bus == NULL);
++      if (bus->self)
++              res = bus->resource[0];
++      else
++              /* Root Bus */
++              res = &hose->io_resource;
+-      /* If this not a PHB, nothing to do, page tables still exist and
+-       * thus HPTEs will be faulted in when needed
+-       */
+-      if (bus->self) {
+-              DBG("IO mapping for PCI-PCI bridge %s\n",
+-                  pci_name(bus->self));
+-              DBG("  virt=0x%016lx...0x%016lx\n",
+-                  bus->resource[0]->start + _IO_BASE,
+-                  bus->resource[0]->end + _IO_BASE);
+-      return 0;
++      if (res->end == 0 && res->start == 0)
++              return 1;
++
++      *start_virt = pci_io_base + res->start;
++      *start_phys = *start_virt + hose->io_base_phys
++              - (unsigned long) hose->io_base_virt;
++
++      if (res->end > res->start)
++              *size = res->end - res->start + 1;
++      else {
++              printk("%s(): unexpected region 0x%lx->0x%lx\n",
++                     __FUNCTION__, res->start, res->end);
++              return 1;
+       }
+       
+-      /* Get the host bridge */
+-      hose = pci_bus_to_host(bus);
+-      phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE);
+-      size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE);
++      return 0;
++}
++
++int unmap_bus_range(struct pci_bus *bus)
++{
++      unsigned long start_phys;
++      unsigned long start_virt;
++      unsigned long size;
++
++      if (!bus) {
++              printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
++              return 1;
++      }
+       
+-      /* Make sure IO area address is clear */
+-      hose->io_base_alloc = NULL;
++      if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
++              return 1;
++      if (__iounmap_explicit((void __iomem *) start_virt, size))
++              return 1;
+-      /* If there's no IO to map on that bus, get away too */
+-      if (hose->pci_io_size == 0 || hose->io_base_phys == 0)
+       return 0;
++}
++EXPORT_SYMBOL(unmap_bus_range);
++
++int remap_bus_range(struct pci_bus *bus)
++{
++      unsigned long start_phys;
++      unsigned long start_virt;
++      unsigned long size;
+-      /* Let's allocate some IO space for that guy. We don't pass
+-       * VM_IOREMAP because we don't care about alignment tricks that
+-       * the core does in that case. Maybe we should due to stupid card
+-       * with incomplete address decoding but I'd rather not deal with
+-       * those outside of the reserved 64K legacy region.
+-       */
+-      area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END);
+-      if (area == NULL)
+-              return -ENOMEM;
+-      hose->io_base_alloc = area->addr;
+-      hose->io_base_virt = (void __iomem *)(area->addr +
+-                                            hose->io_base_phys - phys_page);
+-
+-      DBG("IO mapping for PHB %s\n",
+-          ((struct device_node *)hose->arch_data)->full_name);
+-      DBG("  phys=0x%016lx, virt=0x%p (alloc=0x%p)\n",
+-          hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
+-      DBG("  size=0x%016lx (alloc=0x%016lx)\n",
+-          hose->pci_io_size, size_page);
+-
+-      /* Establish the mapping */
+-      if (__ioremap_at(phys_page, area->addr, size_page,
+-                       _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL)
+-              return -ENOMEM;
 -
--    ; Disable selection timer
--    MOVE CTEST7 | 0x10 TO CTEST7
+-      /* Fixup hose IO resource */
+-      io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+-      hose->io_resource.start += io_virt_offset;
+-      hose->io_resource.end += io_virt_offset;
++      if (!bus) {
++              printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
++              return 1;
++      }
+-      DBG("  hose->io_resource=0x%016lx...0x%016lx\n",
+-          hose->io_resource.start, hose->io_resource.end);
++      
++      if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
++              return 1;
++      if (start_phys == 0)
++              return 1;
++      printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
++      if (__ioremap_explicit(start_phys, start_virt, size,
++                             _PAGE_NO_CACHE | _PAGE_GUARDED))
++              return 1;
+       return 0;
+ }
+-EXPORT_SYMBOL_GPL(pcibios_map_io_space);
++EXPORT_SYMBOL(remap_bus_range);
++
++static void phbs_remap_io(void)
++{
++      struct pci_controller *hose, *tmp;
++
++      list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
++              remap_bus_range(hose->bus);
++}
+ static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
+ {
+@@ -1085,7 +1201,8 @@
+       unsigned long offset;
+       if (res->flags & IORESOURCE_IO) {
+-              offset = (unsigned long)hose->io_base_virt - _IO_BASE;
++              offset = (unsigned long)hose->io_base_virt - pci_io_base;
++
+               res->start += offset;
+               res->end += offset;
+       } else if (res->flags & IORESOURCE_MEM) {
+@@ -1100,20 +1217,9 @@
+       /* Update device resources.  */
+       int i;
+-      DBG("%s: Fixup resources:\n", pci_name(dev));
+-      for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+-              struct resource *res = &dev->resource[i];
+-              if (!res->flags)
+-                      continue;
 -
--at 0x00000227 : */    0x7a1b1000,0x00000000,
--/*
+-              DBG("  0x%02x < %08lx:0x%016lx...0x%016lx\n",
+-                  i, res->flags, res->start, res->end);
 -
--    MOVE FROM 8, WHEN MSG_OUT
+-              fixup_resource(res, dev);
 -
--at 0x00000229 : */    0x1e000000,0x00000008,
--/*
--    MOVE FROM 16, WHEN CMD 
+-              DBG("       > %08lx:0x%016lx...0x%016lx\n",
+-                  res->flags, res->start, res->end);
+-      }
++      for (i = 0; i < PCI_NUM_RESOURCES; i++)
++              if (dev->resource[i].flags)
++                      fixup_resource(&dev->resource[i], dev);
+ }
+ EXPORT_SYMBOL(pcibios_fixup_device_resources);
+@@ -1254,7 +1360,7 @@
+               return;
+       if (rsrc->flags & IORESOURCE_IO)
+-              offset = (unsigned long)hose->io_base_virt - _IO_BASE;
++              offset = (unsigned long)hose->io_base_virt - pci_io_base;
+       /* We pass a fully fixed up address to userland for MMIO instead of
+        * a BAR value because X is lame and expects to be able to use that
+@@ -1304,7 +1410,7 @@
+               if (address >= hose->io_base_phys &&
+                   address < (hose->io_base_phys + hose->pci_io_size)) {
+                       unsigned long base =
+-                              (unsigned long)hose->io_base_virt - _IO_BASE;
++                              (unsigned long)hose->io_base_virt - pci_io_base;
+                       return base + (address - hose->io_base_phys);
+               }
+       }
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/process.c linux-2.6.22-570/arch/powerpc/kernel/process.c
+--- linux-2.6.22-590/arch/powerpc/kernel/process.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/process.c     2008-01-23 19:16:03.000000000 -0500
+@@ -219,25 +219,21 @@
+ }
+ #endif /* CONFIG_SMP */
++#ifdef CONFIG_PPC_MERGE               /* XXX for now */
+ int set_dabr(unsigned long dabr)
+ {
+-#ifdef CONFIG_PPC_MERGE               /* XXX for now */
+       if (ppc_md.set_dabr)
+               return ppc_md.set_dabr(dabr);
+-#endif
+-      /* XXX should we have a CPU_FTR_HAS_DABR ? */
+-#if defined(CONFIG_PPC64) || defined(CONFIG_6xx)
+       mtspr(SPRN_DABR, dabr);
+-#endif
+       return 0;
+ }
++#endif
+ #ifdef CONFIG_PPC64
+ DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
+-#endif
 -
--at 0x0000022b : */    0x1a000000,0x00000010,
+ static DEFINE_PER_CPU(unsigned long, current_dabr);
++#endif
+ struct task_struct *__switch_to(struct task_struct *prev,
+       struct task_struct *new)
+@@ -303,10 +299,12 @@
+ #endif /* CONFIG_SMP */
++#ifdef CONFIG_PPC64   /* for now */
+       if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
+               set_dabr(new->thread.dabr);
+               __get_cpu_var(current_dabr) = new->thread.dabr;
+       }
++#endif /* CONFIG_PPC64 */
+       new_thread = &new->thread;
+       old_thread = &current->thread;
+@@ -476,10 +474,12 @@
+       discard_lazy_cpu_state();
++#ifdef CONFIG_PPC64   /* for now */
+       if (current->thread.dabr) {
+               current->thread.dabr = 0;
+               set_dabr(0);
+       }
++#endif
+ }
+ void
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/prom_init.c linux-2.6.22-570/arch/powerpc/kernel/prom_init.c
+--- linux-2.6.22-590/arch/powerpc/kernel/prom_init.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/prom_init.c   2007-07-08 19:32:17.000000000 -0400
+@@ -635,7 +635,6 @@
+ /* ibm,dynamic-reconfiguration-memory property supported */
+ #define OV5_DRCONF_MEMORY     0x20
+ #define OV5_LARGE_PAGES               0x10    /* large pages supported */
+-#define OV5_DONATE_DEDICATE_CPU 0x02  /* donate dedicated CPU support */
+ /* PCIe/MSI support.  Without MSI full PCIe is not supported */
+ #ifdef CONFIG_PCI_MSI
+ #define OV5_MSI                       0x01    /* PCIe/MSI support */
+@@ -686,8 +685,7 @@
+       /* option vector 5: PAPR/OF options */
+       3 - 2,                          /* length */
+       0,                              /* don't ignore, don't halt */
+-      OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
+-      OV5_DONATE_DEDICATE_CPU | OV5_MSI,
++      OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI,
+ };
+ /* Old method - ELF header with PT_NOTE sections */
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/ptrace-common.h linux-2.6.22-570/arch/powerpc/kernel/ptrace-common.h
+--- linux-2.6.22-590/arch/powerpc/kernel/ptrace-common.h       1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/ptrace-common.h       2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,161 @@
++/*
++ *    Copyright (c) 2002 Stephen Rothwell, IBM Coproration
++ *    Extracted from ptrace.c and ptrace32.c
++ *
++ * This file is subject to the terms and conditions of the GNU General
++ * Public License.  See the file README.legal in the main directory of
++ * this archive for more details.
++ */
++
++#ifndef _PPC64_PTRACE_COMMON_H
++#define _PPC64_PTRACE_COMMON_H
++
++#include <asm/system.h>
++
++/*
++ * Set of msr bits that gdb can change on behalf of a process.
++ */
++#define MSR_DEBUGCHANGE       (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
++
++/*
++ * Get contents of register REGNO in task TASK.
++ */
++static inline unsigned long get_reg(struct task_struct *task, int regno)
++{
++      unsigned long tmp = 0;
++
++      /*
++       * Put the correct FP bits in, they might be wrong as a result
++       * of our lazy FP restore.
++       */
++      if (regno == PT_MSR) {
++              tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
++              tmp |= task->thread.fpexc_mode;
++      } else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
++              tmp = ((unsigned long *)task->thread.regs)[regno];
++      }
++
++      return tmp;
++}
++
++/*
++ * Write contents of register REGNO in task TASK.
++ */
++static inline int put_reg(struct task_struct *task, int regno,
++                        unsigned long data)
++{
++      if (regno < PT_SOFTE) {
++              if (regno == PT_MSR)
++                      data = (data & MSR_DEBUGCHANGE)
++                              | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
++              ((unsigned long *)task->thread.regs)[regno] = data;
++              return 0;
++      }
++      return -EIO;
++}
++
++static inline void set_single_step(struct task_struct *task)
++{
++      struct pt_regs *regs = task->thread.regs;
++      if (regs != NULL)
++              regs->msr |= MSR_SE;
++      set_tsk_thread_flag(task, TIF_SINGLESTEP);
++}
++
++static inline void clear_single_step(struct task_struct *task)
++{
++      struct pt_regs *regs = task->thread.regs;
++      if (regs != NULL)
++              regs->msr &= ~MSR_SE;
++      clear_tsk_thread_flag(task, TIF_SINGLESTEP);
++}
++
++#ifdef CONFIG_ALTIVEC
++/*
++ * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
++ * The transfer totals 34 quadword.  Quadwords 0-31 contain the
++ * corresponding vector registers.  Quadword 32 contains the vscr as the
++ * last word (offset 12) within that quadword.  Quadword 33 contains the
++ * vrsave as the first word (offset 0) within the quadword.
++ *
++ * This definition of the VMX state is compatible with the current PPC32
++ * ptrace interface.  This allows signal handling and ptrace to use the
++ * same structures.  This also simplifies the implementation of a bi-arch
++ * (combined (32- and 64-bit) gdb.
++ */
++
++/*
++ * Get contents of AltiVec register state in task TASK
++ */
++static inline int get_vrregs(unsigned long __user *data,
++                           struct task_struct *task)
++{
++      unsigned long regsize;
++
++      /* copy AltiVec registers VR[0] .. VR[31] */
++      regsize = 32 * sizeof(vector128);
++      if (copy_to_user(data, task->thread.vr, regsize))
++              return -EFAULT;
++      data += (regsize / sizeof(unsigned long));
++
++      /* copy VSCR */
++      regsize = 1 * sizeof(vector128);
++      if (copy_to_user(data, &task->thread.vscr, regsize))
++              return -EFAULT;
++      data += (regsize / sizeof(unsigned long));
++
++      /* copy VRSAVE */
++      if (put_user(task->thread.vrsave, (u32 __user *)data))
++              return -EFAULT;
++
++      return 0;
++}
++
++/*
++ * Write contents of AltiVec register state into task TASK.
++ */
++static inline int set_vrregs(struct task_struct *task,
++                           unsigned long __user *data)
++{
++      unsigned long regsize;
++
++      /* copy AltiVec registers VR[0] .. VR[31] */
++      regsize = 32 * sizeof(vector128);
++      if (copy_from_user(task->thread.vr, data, regsize))
++              return -EFAULT;
++      data += (regsize / sizeof(unsigned long));
++
++      /* copy VSCR */
++      regsize = 1 * sizeof(vector128);
++      if (copy_from_user(&task->thread.vscr, data, regsize))
++              return -EFAULT;
++      data += (regsize / sizeof(unsigned long));
++
++      /* copy VRSAVE */
++      if (get_user(task->thread.vrsave, (u32 __user *)data))
++              return -EFAULT;
++
++      return 0;
++}
++#endif
++
++static inline int ptrace_set_debugreg(struct task_struct *task,
++                                    unsigned long addr, unsigned long data)
++{
++      /* We only support one DABR and no IABRS at the moment */
++      if (addr > 0)
++              return -EINVAL;
++
++      /* The bottom 3 bits are flags */
++      if ((data & ~0x7UL) >= TASK_SIZE)
++              return -EIO;
++
++      /* Ensure translation is on */
++      if (data && !(data & DABR_TRANSLATION))
++              return -EIO;
++
++      task->thread.dabr = data;
++      return 0;
++}
++
++#endif /* _PPC64_PTRACE_COMMON_H */
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/ptrace.c linux-2.6.22-570/arch/powerpc/kernel/ptrace.c
+--- linux-2.6.22-590/arch/powerpc/kernel/ptrace.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/ptrace.c      2007-07-08 19:32:17.000000000 -0400
+@@ -35,11 +35,11 @@
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
 -/*
--    MOVE FROM 24, WHEN DATA_IN
+- * does not yet catch signals sent when the child dies.
+- * in exit.c or in signal.c.
+- */
++#ifdef CONFIG_PPC64
++#include "ptrace-common.h"
++#endif
++#ifdef CONFIG_PPC32
+ /*
+  * Set of msr bits that gdb can change on behalf of a process.
+  */
+@@ -48,117 +48,65 @@
+ #else
+ #define MSR_DEBUGCHANGE       (MSR_SE | MSR_BE)
+ #endif
++#endif /* CONFIG_PPC32 */
+ /*
+- * Max register writeable via put_reg
++ * does not yet catch signals sent when the child dies.
++ * in exit.c or in signal.c.
+  */
+-#ifdef CONFIG_PPC32
+-#define PT_MAX_PUT_REG        PT_MQ
+-#else
+-#define PT_MAX_PUT_REG        PT_CCR
+-#endif
++#ifdef CONFIG_PPC32
+ /*
+  * Get contents of register REGNO in task TASK.
+  */
+-unsigned long ptrace_get_reg(struct task_struct *task, int regno)
++static inline unsigned long get_reg(struct task_struct *task, int regno)
+ {
+-      unsigned long tmp = 0;
 -
--at 0x0000022d : */    0x19000000,0x00000018,
--/*
--    MOVE FROM 32, WHEN STATUS
+-      if (task->thread.regs == NULL)
+-              return -EIO;
 -
--at 0x0000022f : */    0x1b000000,0x00000020,
--/*
--    MOVE FROM 40, WHEN MSG_IN
+-      if (regno == PT_MSR) {
+-              tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
+-              return tmp | task->thread.fpexc_mode;
+-      }
 -
--at 0x00000231 : */    0x1f000000,0x00000028,
--/*
+-      if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
++      if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)
++          && task->thread.regs != NULL)
+               return ((unsigned long *)task->thread.regs)[regno];
 -
+-      return -EIO;
++      return (0);
+ }
+ /*
+  * Write contents of register REGNO in task TASK.
+  */
+-int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
++static inline int put_reg(struct task_struct *task, int regno,
++                        unsigned long data)
+ {
+-      if (task->thread.regs == NULL)
+-              return -EIO;
 -
+-      if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) {
++      if (regno <= PT_MQ && task->thread.regs != NULL) {
+               if (regno == PT_MSR)
+                       data = (data & MSR_DEBUGCHANGE)
+                               | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
+-              /* We prevent mucking around with the reserved area of trap
+-               * which are used internally by the kernel
+-               */
+-              if (regno == PT_TRAP)
+-                      data &= 0xfff0;
+               ((unsigned long *)task->thread.regs)[regno] = data;
+               return 0;
+       }
+       return -EIO;
+ }
 -
--    CLEAR ACK
+-static int get_fpregs(void __user *data, struct task_struct *task,
+-                    int has_fpscr)
+-{
+-      unsigned int count = has_fpscr ? 33 : 32;
 -
--at 0x00000233 : */    0x60000040,0x00000000,
--/*
--    WAIT DISCONNECT
+-      if (copy_to_user(data, task->thread.fpr, count * sizeof(double)))
+-              return -EFAULT;
+-      return 0;
+-}
 -
--at 0x00000235 : */    0x48000000,0x00000000,
--/*
--test_2_fail:
+-static int set_fpregs(void __user *data, struct task_struct *task,
+-                    int has_fpscr)
+-{
+-      unsigned int count = has_fpscr ? 33 : 32;
 -
--    ; Disable selection timer
--    MOVE CTEST7 | 0x10 TO CTEST7
+-      if (copy_from_user(task->thread.fpr, data, count * sizeof(double)))
+-              return -EFAULT;
+-      return 0;
+-}
 -
--at 0x00000237 : */    0x7a1b1000,0x00000000,
--/*
 -
--    INT int_test_2
+ #ifdef CONFIG_ALTIVEC
+ /*
+- * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
+- * The transfer totals 34 quadword.  Quadwords 0-31 contain the
+- * corresponding vector registers.  Quadword 32 contains the vscr as the
+- * last word (offset 12) within that quadword.  Quadword 33 contains the
+- * vrsave as the first word (offset 0) within the quadword.
+- *
+- * This definition of the VMX state is compatible with the current PPC32
+- * ptrace interface.  This allows signal handling and ptrace to use the
+- * same structures.  This also simplifies the implementation of a bi-arch
+- * (combined (32- and 64-bit) gdb.
+- */
 -
--at 0x00000239 : */    0x98080000,0x04010000,
 -/*
+  * Get contents of AltiVec register state in task TASK
+  */
+-static int get_vrregs(unsigned long __user *data, struct task_struct *task)
++static inline int get_vrregs(unsigned long __user *data, struct task_struct *task)
+ {
+-      unsigned long regsize;
++      int i, j;
++
++      if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long)))
++              return -EFAULT;
+       /* copy AltiVec registers VR[0] .. VR[31] */
+-      regsize = 32 * sizeof(vector128);
+-      if (copy_to_user(data, task->thread.vr, regsize))
++      for (i = 0; i < 32; i++)
++              for (j = 0; j < 4; j++, data++)
++                      if (__put_user(task->thread.vr[i].u[j], data))
+                               return -EFAULT;
+-      data += (regsize / sizeof(unsigned long));
+       /* copy VSCR */
+-      regsize = 1 * sizeof(vector128);
+-      if (copy_to_user(data, &task->thread.vscr, regsize))
++      for (i = 0; i < 4; i++, data++)
++              if (__put_user(task->thread.vscr.u[i], data))
+                       return -EFAULT;
+-      data += (regsize / sizeof(unsigned long));
+         /* copy VRSAVE */
+-      if (put_user(task->thread.vrsave, (u32 __user *)data))
++      if (__put_user(task->thread.vrsave, data))
+               return -EFAULT;
+       return 0;
+@@ -167,29 +115,31 @@
+ /*
+  * Write contents of AltiVec register state into task TASK.
+  */
+-static int set_vrregs(struct task_struct *task, unsigned long __user *data)
++static inline int set_vrregs(struct task_struct *task, unsigned long __user *data)
+ {
+-      unsigned long regsize;
++      int i, j;
++
++      if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long)))
++              return -EFAULT;
+       /* copy AltiVec registers VR[0] .. VR[31] */
+-      regsize = 32 * sizeof(vector128);
+-      if (copy_from_user(task->thread.vr, data, regsize))
++      for (i = 0; i < 32; i++)
++              for (j = 0; j < 4; j++, data++)
++                      if (__get_user(task->thread.vr[i].u[j], data))
+                               return -EFAULT;
+-      data += (regsize / sizeof(unsigned long));
+       /* copy VSCR */
+-      regsize = 1 * sizeof(vector128);
+-      if (copy_from_user(&task->thread.vscr, data, regsize))
++      for (i = 0; i < 4; i++, data++)
++              if (__get_user(task->thread.vscr.u[i], data))
+                       return -EFAULT;
+-      data += (regsize / sizeof(unsigned long));
+       /* copy VRSAVE */
+-      if (get_user(task->thread.vrsave, (u32 __user *)data))
++      if (__get_user(task->thread.vrsave, data))
+               return -EFAULT;
+       return 0;
+ }
+-#endif /* CONFIG_ALTIVEC */
++#endif
+ #ifdef CONFIG_SPE
+@@ -206,7 +156,7 @@
+ /*
+  * Get contents of SPE register state in task TASK.
+  */
+-static int get_evrregs(unsigned long *data, struct task_struct *task)
++static inline int get_evrregs(unsigned long *data, struct task_struct *task)
+ {
+       int i;
+@@ -232,7 +182,7 @@
+ /*
+  * Write contents of SPE register state into task TASK.
+  */
+-static int set_evrregs(struct task_struct *task, unsigned long *data)
++static inline int set_evrregs(struct task_struct *task, unsigned long *data)
+ {
+       int i;
+@@ -255,8 +205,8 @@
+ }
+ #endif /* CONFIG_SPE */
 -
--ENTRY debug_break
--debug_break:
--    INT int_debug_break
--
--at 0x0000023b : */    0x98080000,0x03000000,
--/*
+-static void set_single_step(struct task_struct *task)
++static inline void
++set_single_step(struct task_struct *task)
+ {
+       struct pt_regs *regs = task->thread.regs;
+@@ -271,7 +221,8 @@
+       set_tsk_thread_flag(task, TIF_SINGLESTEP);
+ }
+-static void clear_single_step(struct task_struct *task)
++static inline void
++clear_single_step(struct task_struct *task)
+ {
+       struct pt_regs *regs = task->thread.regs;
+@@ -285,25 +236,7 @@
+       }
+       clear_tsk_thread_flag(task, TIF_SINGLESTEP);
+ }
 -
--;
--; initiator_abort
--; target_abort
--;
--; PURPOSE : Abort the currently established nexus from with initiator
--;     or target mode.
--;
--;  
+-static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
+-                             unsigned long data)
+-{
+-      /* We only support one DABR and no IABRS at the moment */
+-      if (addr > 0)
+-              return -EINVAL;
 -
--ENTRY target_abort
--target_abort:
--    SET TARGET
+-      /* The bottom 3 bits are flags */
+-      if ((data & ~0x7UL) >= TASK_SIZE)
+-              return -EIO;
 -
--at 0x0000023d : */    0x58000200,0x00000000,
--/*
--    DISCONNECT
+-      /* Ensure translation is on */
+-      if (data && !(data & DABR_TRANSLATION))
+-              return -EIO;
 -
--at 0x0000023f : */    0x48000000,0x00000000,
+-      task->thread.dabr = data;
+-      return 0;
+-}
++#endif /* CONFIG_PPC32 */
+ /*
+  * Called by kernel/ptrace.c when detaching..
+@@ -316,62 +249,6 @@
+       clear_single_step(child);
+ }
 -/*
--    CLEAR TARGET
+- * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
+- * we mark them as obsolete now, they will be removed in a future version
+- */
+-static long arch_ptrace_old(struct task_struct *child, long request, long addr,
+-                          long data)
+-{
+-      int ret = -EPERM;
 -
--at 0x00000241 : */    0x60000200,0x00000000,
--/*
--    JUMP schedule
+-      switch(request) {
+-      case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
+-              int i;
+-              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+-              unsigned long __user *tmp = (unsigned long __user *)addr;
 -
--at 0x00000243 : */    0x80080000,0x00000000,
--/*
--    
--ENTRY initiator_abort
--initiator_abort:
--    SET ATN
+-              for (i = 0; i < 32; i++) {
+-                      ret = put_user(*reg, tmp);
+-                      if (ret)
+-                              break;
+-                      reg++;
+-                      tmp++;
+-              }
+-              break;
+-      }
 -
--at 0x00000245 : */    0x58000008,0x00000000,
--/*
--;
--; The SCSI-I specification says that targets may go into MSG out at 
--; their leisure upon receipt of the ATN single.  On all versions of the 
--; specification, we can't change phases until REQ transitions true->false, 
--; so we need to sink/source one byte of data to allow the transition.
--;
--; For the sake of safety, we'll only source one byte of data in all 
--; cases, but to accommodate the SCSI-I dain bramage, we'll sink an  
--; arbitrary number of bytes.
--    JUMP spew_cmd, WHEN CMD
--
--at 0x00000247 : */    0x820b0000,0x0000094c,
--/*
--    JUMP eat_msgin, WHEN MSG_IN
+-      case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
+-              int i;
+-              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+-              unsigned long __user *tmp = (unsigned long __user *)addr;
 -
--at 0x00000249 : */    0x870b0000,0x0000095c,
--/*
--    JUMP eat_datain, WHEN DATA_IN
+-              for (i = 0; i < 32; i++) {
+-                      ret = get_user(*reg, tmp);
+-                      if (ret)
+-                              break;
+-                      reg++;
+-                      tmp++;
+-              }
+-              break;
+-      }
 -
--at 0x0000024b : */    0x810b0000,0x0000098c,
--/*
--    JUMP eat_status, WHEN STATUS
+-      case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
+-              flush_fp_to_thread(child);
+-              ret = get_fpregs((void __user *)addr, child, 0);
+-              break;
+-      }
 -
--at 0x0000024d : */    0x830b0000,0x00000974,
--/*
--    JUMP spew_dataout, WHEN DATA_OUT
+-      case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
+-              flush_fp_to_thread(child);
+-              ret = set_fpregs((void __user *)addr, child, 0);
+-              break;
+-      }
 -
--at 0x0000024f : */    0x800b0000,0x000009a4,
--/*
--    JUMP sated
+-      }
+-      return ret;
+-}
 -
--at 0x00000251 : */    0x80080000,0x000009ac,
--/*
--spew_cmd:
--    MOVE 1, NCR53c7xx_zero, WHEN CMD
+ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ {
+       int ret = -EPERM;
+@@ -407,9 +284,11 @@
+ #endif
+                       break;
++#ifdef CONFIG_PPC32
+               CHECK_FULL_REGS(child->thread.regs);
++#endif
+               if (index < PT_FPR0) {
+-                      tmp = ptrace_get_reg(child, (int) index);
++                      tmp = get_reg(child, (int) index);
+               } else {
+                       flush_fp_to_thread(child);
+                       tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
+@@ -444,9 +323,13 @@
+ #endif
+                       break;
++#ifdef CONFIG_PPC32
+               CHECK_FULL_REGS(child->thread.regs);
++#endif
++              if (index == PT_ORIG_R3)
++                      break;
+               if (index < PT_FPR0) {
+-                      ret = ptrace_put_reg(child, index, data);
++                      ret = put_reg(child, index, data);
+               } else {
+                       flush_fp_to_thread(child);
+                       ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
+@@ -501,6 +384,7 @@
+               break;
+       }
++#ifdef CONFIG_PPC64
+       case PTRACE_GET_DEBUGREG: {
+               ret = -EINVAL;
+               /* We only support one DABR and no IABRS at the moment */
+@@ -514,61 +398,73 @@
+       case PTRACE_SET_DEBUGREG:
+               ret = ptrace_set_debugreg(child, addr, data);
+               break;
++#endif
+       case PTRACE_DETACH:
+               ret = ptrace_detach(child, data);
+               break;
+-#ifdef CONFIG_PPC64
+-      case PTRACE_GETREGS64:
+-#endif
+-      case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
+-              int ui;
+-              if (!access_ok(VERIFY_WRITE, (void __user *)data,
+-                             sizeof(struct pt_regs))) {
+-                      ret = -EIO;
++      case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
++              int i;
++              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
++              unsigned long __user *tmp = (unsigned long __user *)addr;
++
++              for (i = 0; i < 32; i++) {
++                      ret = put_user(*reg, tmp);
++                      if (ret)
+                               break;
+-              }
+-              ret = 0;
+-              for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+-                      ret |= __put_user(ptrace_get_reg(child, ui),
+-                                        (unsigned long __user *) data);
+-                      data += sizeof(long);
++                      reg++;
++                      tmp++;
+       }
+                               break;
+               }
+-#ifdef CONFIG_PPC64
+-      case PTRACE_SETREGS64:
+-#endif
+-      case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+-              unsigned long tmp;
+-              int ui;
+-              if (!access_ok(VERIFY_READ, (void __user *)data,
+-                             sizeof(struct pt_regs))) {
+-                      ret = -EIO;
+-              break;
+-      }
+-              ret = 0;
+-              for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+-                      ret = __get_user(tmp, (unsigned long __user *) data);
++      case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
++              int i;
++              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
++              unsigned long __user *tmp = (unsigned long __user *)addr;
++
++              for (i = 0; i < 32; i++) {
++                      ret = get_user(*reg, tmp);
+                       if (ret)
+                               break;
+-                      ptrace_put_reg(child, ui, tmp);
+-                      data += sizeof(long);
++                      reg++;
++                      tmp++;
+               }
+               break;
+       }
+-      case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */
++      case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
++              int i;
++              unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
++              unsigned long __user *tmp = (unsigned long __user *)addr;
++
+               flush_fp_to_thread(child);
+-              ret = get_fpregs((void __user *)data, child, 1);
++
++              for (i = 0; i < 32; i++) {
++                      ret = put_user(*reg, tmp);
++                      if (ret)
++                              break;
++                      reg++;
++                      tmp++;
++              }
+                               break;
+               }
+-      case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */
++      case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
++              int i;
++              unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
++              unsigned long __user *tmp = (unsigned long __user *)addr;
++
+               flush_fp_to_thread(child);
+-              ret = set_fpregs((void __user *)data, child, 1);
++
++              for (i = 0; i < 32; i++) {
++                      ret = get_user(*reg, tmp);
++                      if (ret)
++                              break;
++                      reg++;
++                      tmp++;
++              }
+               break;
+       }
+@@ -603,18 +499,11 @@
+               break;
+ #endif
+-      /* Old reverse args ptrace callss */
+-      case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
+-      case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
+-      case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
+-      case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */
+-              ret = arch_ptrace_old(child, request, addr, data);
+-              break;
 -
--at 0x00000253 : */    0x0a000001,0x00000000,
+       default:
+               ret = ptrace_request(child, request, addr, data);
+               break;
+       }
++
+       return ret;
+ }
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/ptrace32.c linux-2.6.22-570/arch/powerpc/kernel/ptrace32.c
+--- linux-2.6.22-590/arch/powerpc/kernel/ptrace32.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/ptrace32.c    2007-07-08 19:32:17.000000000 -0400
+@@ -33,55 +33,13 @@
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
++#include "ptrace-common.h"
++
+ /*
+  * does not yet catch signals sent when the child dies.
+  * in exit.c or in signal.c.
+  */
 -/*
--    JUMP sated
+- * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
+- * we mark them as obsolete now, they will be removed in a future version
+- */
+-static long compat_ptrace_old(struct task_struct *child, long request,
+-                            long addr, long data)
+-{
+-      int ret = -EPERM;
 -
--at 0x00000255 : */    0x80080000,0x000009ac,
--/*
--eat_msgin:
--    MOVE 1, NCR53c7xx_sink, WHEN MSG_IN
+-      switch(request) {
+-      case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
+-              int i;
+-              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+-              unsigned int __user *tmp = (unsigned int __user *)addr;
 -
--at 0x00000257 : */    0x0f000001,0x00000000,
--/*
--    JUMP eat_msgin, WHEN MSG_IN
+-              for (i = 0; i < 32; i++) {
+-                      ret = put_user(*reg, tmp);
+-                      if (ret)
+-                              break;
+-                      reg++;
+-                      tmp++;
+-              }
+-              break;
+-      }
 -
--at 0x00000259 : */    0x870b0000,0x0000095c,
--/*
--    JUMP sated
+-      case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
+-              int i;
+-              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+-              unsigned int __user *tmp = (unsigned int __user *)addr;
 -
--at 0x0000025b : */    0x80080000,0x000009ac,
--/*
--eat_status:
--    MOVE 1, NCR53c7xx_sink, WHEN STATUS
+-              for (i = 0; i < 32; i++) {
+-                      ret = get_user(*reg, tmp);
+-                      if (ret)
+-                              break;
+-                      reg++;
+-                      tmp++;
+-              }
+-              break;
+-      }
 -
--at 0x0000025d : */    0x0b000001,0x00000000,
--/*
--    JUMP eat_status, WHEN STATUS
+-      }
+-      return ret;
+-}
 -
--at 0x0000025f : */    0x830b0000,0x00000974,
--/*
--    JUMP sated
+ long compat_sys_ptrace(int request, int pid, unsigned long addr,
+                      unsigned long data)
+ {
+@@ -165,7 +123,7 @@
+                       break;
+               if (index < PT_FPR0) {
+-                      tmp = ptrace_get_reg(child, index);
++                      tmp = get_reg(child, index);
+               } else {
+                       flush_fp_to_thread(child);
+                       /*
+@@ -204,9 +162,7 @@
+               else
+                       part = 0;  /* want the 1st half of the register (left-most). */
+-              /* Validate the input - check to see if address is on the wrong boundary
+-               * or beyond the end of the user area
+-               */
++              /* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */
+               if ((addr & 3) || numReg > PT_FPSCR)
+                       break;
+@@ -214,7 +170,7 @@
+                       flush_fp_to_thread(child);
+                       tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
+               } else { /* register within PT_REGS struct */
+-                      tmp = ptrace_get_reg(child, numReg);
++                      tmp = get_reg(child, numReg);
+               } 
+               reg32bits = ((u32*)&tmp)[part];
+               ret = put_user(reg32bits, (u32 __user *)data);
+@@ -270,8 +226,10 @@
+               if ((addr & 3) || (index > PT_FPSCR32))
+                       break;
++              if (index == PT_ORIG_R3)
++                      break;
+               if (index < PT_FPR0) {
+-                      ret = ptrace_put_reg(child, index, data);
++                      ret = put_reg(child, index, data);
+               } else {
+                       flush_fp_to_thread(child);
+                       /*
+@@ -300,25 +258,70 @@
+               /* Determine which register the user wants */
+               index = (u64)addr >> 2;
+               numReg = index / 2;
 -
--at 0x00000261 : */    0x80080000,0x000009ac,
+               /*
+                * Validate the input - check to see if address is on the
+                * wrong boundary or beyond the end of the user area
+                */
+               if ((addr & 3) || (numReg > PT_FPSCR))
+                       break;
+-              if (numReg < PT_FPR0) {
+-                      unsigned long freg = ptrace_get_reg(child, numReg);
+-                      if (index % 2)
+-                              freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
+-              else
+-                              freg = (freg & 0xfffffffful) | (data << 32);
+-                      ret = ptrace_put_reg(child, numReg, freg);
+-              } else {
++              /* Insure it is a register we let them change */
++              if ((numReg == PT_ORIG_R3)
++                              || ((numReg > PT_CCR) && (numReg < PT_FPR0)))
++                      break;
++              if (numReg >= PT_FPR0) {
+                       flush_fp_to_thread(child);
+-                      ((unsigned int *)child->thread.regs)[index] = data;
++              }
++              if (numReg == PT_MSR)
++                      data = (data & MSR_DEBUGCHANGE)
++                              | (child->thread.regs->msr & ~MSR_DEBUGCHANGE);
++              ((u32*)child->thread.regs)[index] = data;
+               ret = 0;
++              break;
+       }
++
++      case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
++      case PTRACE_CONT: { /* restart after signal. */
++              ret = -EIO;
++              if (!valid_signal(data))
++                      break;
++              if (request == PTRACE_SYSCALL)
++                      set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
++              else
++                      clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
++              child->exit_code = data;
++              /* make sure the single step bit is not set. */
++              clear_single_step(child);
++              wake_up_process(child);
++              ret = 0;
++              break;
++      }
++
++      /*
++       * make the child exit.  Best I can do is send it a sigkill.
++       * perhaps it should be put in the status that it wants to
++       * exit.
++       */
++      case PTRACE_KILL: {
++              ret = 0;
++              if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
++                      break;
++              child->exit_code = SIGKILL;
++              /* make sure the single step bit is not set. */
++              clear_single_step(child);
++              wake_up_process(child);
++              break;
++      }
++
++      case PTRACE_SINGLESTEP: {  /* set the trap flag. */
++              ret = -EIO;
++              if (!valid_signal(data))
++                      break;
++              clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
++              set_single_step(child);
++              child->exit_code = data;
++              /* give it a chance to run. */
++              wake_up_process(child);
++              ret = 0;
+               break;
+       }
+@@ -331,67 +334,95 @@
+               break;
+       }
+-      case PTRACE_GETEVENTMSG:
+-              ret = put_user(child->ptrace_message, (unsigned int __user *) data);
++      case PTRACE_SET_DEBUGREG:
++              ret = ptrace_set_debugreg(child, addr, data);
+               break;
+-      case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
+-              int ui;
+-              if (!access_ok(VERIFY_WRITE, (void __user *)data,
+-                             PT_REGS_COUNT * sizeof(int))) {
+-                      ret = -EIO;
++      case PTRACE_DETACH:
++              ret = ptrace_detach(child, data);
+               break;
++
++      case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
++              int i;
++              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
++              unsigned int __user *tmp = (unsigned int __user *)addr;
++
++              for (i = 0; i < 32; i++) {
++                      ret = put_user(*reg, tmp);
++                      if (ret)
++                              break;
++                      reg++;
++                      tmp++;
+       }
+-              ret = 0;
+-              for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+-                      ret |= __put_user(ptrace_get_reg(child, ui),
+-                                        (unsigned int __user *) data);
+-                      data += sizeof(int);
++              break;
++      }
++
++      case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
++              int i;
++              unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
++              unsigned int __user *tmp = (unsigned int __user *)addr;
++
++              for (i = 0; i < 32; i++) {
++                      ret = get_user(*reg, tmp);
++                      if (ret)
++                              break;
++                      reg++;
++                      tmp++;
+               }
+               break;
+       }
+-      case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+-              unsigned long tmp;
+-              int ui;
+-              if (!access_ok(VERIFY_READ, (void __user *)data,
+-                             PT_REGS_COUNT * sizeof(int))) {
+-                      ret = -EIO;
++      case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
++              int i;
++              unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
++              unsigned int __user *tmp = (unsigned int __user *)addr;
++
++              flush_fp_to_thread(child);
++
++              for (i = 0; i < 32; i++) {
++                      ret = put_user(*reg, tmp);
++                      if (ret)
+               break;
++                      reg++;
++                      tmp++;
+       }
+-              ret = 0;
+-              for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+-                      ret = __get_user(tmp, (unsigned int __user *) data);
++              break;
++      }
++
++      case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
++              int i;
++              unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
++              unsigned int __user *tmp = (unsigned int __user *)addr;
++
++              flush_fp_to_thread(child);
++
++              for (i = 0; i < 32; i++) {
++                      ret = get_user(*reg, tmp);
+                       if (ret)
+                               break;
+-                      ptrace_put_reg(child, ui, tmp);
+-                      data += sizeof(int);
++                      reg++;
++                      tmp++;
+               }
+               break;
+       }
+-      case PTRACE_GETFPREGS:
+-      case PTRACE_SETFPREGS:
++      case PTRACE_GETEVENTMSG:
++              ret = put_user(child->ptrace_message, (unsigned int __user *) data);
++              break;
++
++#ifdef CONFIG_ALTIVEC
+       case PTRACE_GETVRREGS:
+-      case PTRACE_SETVRREGS:
+-      case PTRACE_GETREGS64:
+-      case PTRACE_SETREGS64:
+-      case PPC_PTRACE_GETFPREGS:
+-      case PPC_PTRACE_SETFPREGS:
+-      case PTRACE_KILL:
+-      case PTRACE_SINGLESTEP:
+-      case PTRACE_DETACH:
+-      case PTRACE_SET_DEBUGREG:
+-      case PTRACE_SYSCALL:
+-      case PTRACE_CONT:
+-              ret = arch_ptrace(child, request, addr, data);
++              /* Get the child altivec register state. */
++              flush_altivec_to_thread(child);
++              ret = get_vrregs((unsigned long __user *)data, child);
+               break;
+-      /* Old reverse args ptrace callss */
+-      case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
+-      case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
+-              ret = compat_ptrace_old(child, request, addr, data);
++      case PTRACE_SETVRREGS:
++              /* Set the child altivec register state. */
++              flush_altivec_to_thread(child);
++              ret = set_vrregs(child, (unsigned long __user *)data);
+               break;
++#endif
+       default:
+               ret = ptrace_request(child, request, addr, data);
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/rtas_pci.c linux-2.6.22-570/arch/powerpc/kernel/rtas_pci.c
+--- linux-2.6.22-590/arch/powerpc/kernel/rtas_pci.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/rtas_pci.c    2007-07-08 19:32:17.000000000 -0400
+@@ -278,8 +278,10 @@
+ {
+       struct device_node *node;
+       struct pci_controller *phb;
++      unsigned int index;
+       struct device_node *root = of_find_node_by_path("/");
++      index = 0;
+       for (node = of_get_next_child(root, NULL);
+            node != NULL;
+            node = of_get_next_child(root, node)) {
+@@ -293,7 +295,8 @@
+                       continue;
+               rtas_setup_phb(phb);
+               pci_process_bridge_OF_ranges(phb, node, 0);
+-              isa_bridge_find_early(phb);
++              pci_setup_phb_io(phb, index == 0);
++              index++;
+       }
+       of_node_put(root);
+@@ -332,7 +335,7 @@
+               return 1;
+       }
+-      rc = pcibios_unmap_io_space(b);
++      rc = unmap_bus_range(b);
+       if (rc) {
+               printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
+                       __FUNCTION__, b->name);
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/setup_32.c linux-2.6.22-570/arch/powerpc/kernel/setup_32.c
+--- linux-2.6.22-590/arch/powerpc/kernel/setup_32.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/setup_32.c    2007-07-08 19:32:17.000000000 -0400
+@@ -45,6 +45,10 @@
+ #define DBG(fmt...)
++#if defined CONFIG_KGDB
++#include <asm/kgdb.h>
++#endif
++
+ extern void bootx_init(unsigned long r4, unsigned long phys);
+ struct ide_machdep_calls ppc_ide_md;
+@@ -241,16 +245,30 @@
+       xmon_setup();
++#if defined(CONFIG_KGDB)
++      if (ppc_md.kgdb_map_scc)
++              ppc_md.kgdb_map_scc();
++      set_debug_traps();
++      if (strstr(cmd_line, "gdb")) {
++              if (ppc_md.progress)
++                      ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
++              printk("kgdb breakpoint activated\n");
++              breakpoint();
++      }
++#endif
++
+       /*
+        * Set cache line size based on type of cpu as a default.
+        * Systems with OF can look in the properties on the cpu node(s)
+        * for a possibly more accurate value.
+        */
++      if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
+               dcache_bsize = cur_cpu_spec->dcache_bsize;
+               icache_bsize = cur_cpu_spec->icache_bsize;
+               ucache_bsize = 0;
+-      if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE))
+-              ucache_bsize = icache_bsize = dcache_bsize;
++      } else
++              ucache_bsize = dcache_bsize = icache_bsize
++                      = cur_cpu_spec->dcache_bsize;
+       /* reboot on panic */
+       panic_timeout = 180;
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/signal.c linux-2.6.22-570/arch/powerpc/kernel/signal.c
+--- linux-2.6.22-590/arch/powerpc/kernel/signal.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/signal.c      1969-12-31 19:00:00.000000000 -0500
+@@ -1,180 +0,0 @@
 -/*
--eat_datain:
--    MOVE 1, NCR53c7xx_sink, WHEN DATA_IN
+- * Common signal handling code for both 32 and 64 bits
+- *
+- *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+- *    Extracted from signal_32.c and signal_64.c
+- *
+- * This file is subject to the terms and conditions of the GNU General
+- * Public License.  See the file README.legal in the main directory of
+- * this archive for more details.
+- */
 -
--at 0x00000263 : */    0x09000001,0x00000000,
--/*
--    JUMP eat_datain, WHEN DATA_IN
+-#include <linux/ptrace.h>
+-#include <linux/signal.h>
+-#include <asm/uaccess.h>
+-#include <asm/unistd.h>
 -
--at 0x00000265 : */    0x810b0000,0x0000098c,
--/*
--    JUMP sated
+-#include "signal.h"
 -
--at 0x00000267 : */    0x80080000,0x000009ac,
 -/*
--spew_dataout:
--    MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT
+- * Allocate space for the signal frame
+- */
+-void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+-                         size_t frame_size)
+-{
+-        unsigned long oldsp, newsp;
 -
--at 0x00000269 : */    0x08000001,0x00000000,
--/*
--sated:
+-        /* Default to using normal stack */
+-        oldsp = regs->gpr[1];
 -
+-      /* Check for alt stack */
+-      if ((ka->sa.sa_flags & SA_ONSTACK) &&
+-          current->sas_ss_size && !on_sig_stack(oldsp))
+-              oldsp = (current->sas_ss_sp + current->sas_ss_size);
 -
+-      /* Get aligned frame */
+-      newsp = (oldsp - frame_size) & ~0xFUL;
 -
--    MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT
+-      /* Check access */
+-      if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp))
+-              return NULL;
 -
--at 0x0000026b : */    0x0e000001,0x00000000,
--/*
--    WAIT DISCONNECT
+-        return (void __user *)newsp;
+-}
 -
--at 0x0000026d : */    0x48000000,0x00000000,
--/*
--    INT int_norm_aborted
 -
--at 0x0000026f : */    0x98080000,0x02040000,
 -/*
+- * Restore the user process's signal mask
+- */
+-void restore_sigmask(sigset_t *set)
+-{
+-      sigdelsetmask(set, ~_BLOCKABLE);
+-      spin_lock_irq(&current->sighand->siglock);
+-      current->blocked = *set;
+-      recalc_sigpending();
+-      spin_unlock_irq(&current->sighand->siglock);
+-}
 -
+-static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
+-                                int has_handler)
+-{
+-      unsigned long ret = regs->gpr[3];
+-      int restart = 1;
 -
-- 
--
--; Little patched jump, used to overcome problems with TEMP getting
--; corrupted on memory moves.
--
--jump_temp:
--    JUMP 0
--
--at 0x00000271 : */    0x80080000,0x00000000,
--};
--
--#define A_NCR53c7xx_msg_abort 0x00000000
--static u32 A_NCR53c7xx_msg_abort_used[] __attribute((unused)) = {
--      0x0000026c,
--};
--
--#define A_NCR53c7xx_msg_reject        0x00000000
--static u32 A_NCR53c7xx_msg_reject_used[] __attribute((unused)) = {
--      0x00000186,
--};
--
--#define A_NCR53c7xx_sink      0x00000000
--static u32 A_NCR53c7xx_sink_used[] __attribute((unused)) = {
--      0x00000258,
--      0x0000025e,
--      0x00000264,
--};
--
--#define A_NCR53c7xx_zero      0x00000000
--static u32 A_NCR53c7xx_zero_used[] __attribute((unused)) = {
--      0x00000254,
--      0x0000026a,
--};
--
--#define A_NOP_insn    0x00000000
--static u32 A_NOP_insn_used[] __attribute((unused)) = {
--      0x00000017,
--};
--
--#define A_addr_dsa    0x00000000
--static u32 A_addr_dsa_used[] __attribute((unused)) = {
--      0x0000000f,
--      0x00000026,
--      0x00000033,
--      0x00000040,
--      0x00000055,
--      0x00000079,
--      0x0000008e,
--      0x000000bc,
--      0x000000d2,
--      0x00000130,
--      0x000001a5,
--      0x000001bb,
--      0x000001e3,
--};
--
--#define A_addr_reconnect_dsa_head     0x00000000
--static u32 A_addr_reconnect_dsa_head_used[] __attribute((unused)) = {
--      0x000001b7,
--};
--
--#define A_addr_scratch        0x00000000
--static u32 A_addr_scratch_used[] __attribute((unused)) = {
--      0x00000002,
--      0x00000004,
--      0x00000008,
--      0x00000020,
--      0x00000022,
--      0x00000049,
--      0x00000060,
--      0x0000006a,
--      0x00000071,
--      0x00000073,
--      0x000000ab,
--      0x000000b5,
--      0x000000c1,
--      0x000000cb,
--      0x0000012c,
--      0x00000142,
--      0x00000157,
--      0x000001b2,
--      0x000001b4,
--      0x000001df,
--      0x000001f7,
--};
--
--#define A_addr_temp   0x00000000
--static u32 A_addr_temp_used[] __attribute((unused)) = {
--};
--
--#define A_dmode_memory_to_memory      0x00000000
--static u32 A_dmode_memory_to_memory_used[] __attribute((unused)) = {
--};
--
--#define A_dmode_memory_to_ncr 0x00000000
--static u32 A_dmode_memory_to_ncr_used[] __attribute((unused)) = {
--};
--
--#define A_dmode_ncr_to_memory 0x00000000
--static u32 A_dmode_ncr_to_memory_used[] __attribute((unused)) = {
--};
--
--#define A_dsa_check_reselect  0x00000000
--static u32 A_dsa_check_reselect_used[] __attribute((unused)) = {
--      0x000001d0,
--};
--
--#define A_dsa_cmdout  0x00000048
--static u32 A_dsa_cmdout_used[] __attribute((unused)) = {
--      0x0000009a,
--};
--
--#define A_dsa_cmnd    0x00000038
--static u32 A_dsa_cmnd_used[] __attribute((unused)) = {
--};
--
--#define A_dsa_datain  0x00000054
--static u32 A_dsa_datain_used[] __attribute((unused)) = {
--      0x000000c2,
--};
--
--#define A_dsa_dataout 0x00000050
--static u32 A_dsa_dataout_used[] __attribute((unused)) = {
--      0x000000ac,
--};
--
--#define A_dsa_end     0x00000070
--static u32 A_dsa_end_used[] __attribute((unused)) = {
--};
--
--#define A_dsa_fields_start    0x00000000
--static u32 A_dsa_fields_start_used[] __attribute((unused)) = {
--};
--
--#define A_dsa_msgin   0x00000058
--static u32 A_dsa_msgin_used[] __attribute((unused)) = {
--      0x0000019c,
--};
--
--#define A_dsa_msgout  0x00000040
--static u32 A_dsa_msgout_used[] __attribute((unused)) = {
--      0x00000089,
--};
--
--#define A_dsa_msgout_other    0x00000068
--static u32 A_dsa_msgout_other_used[] __attribute((unused)) = {
--      0x00000194,
--};
--
--#define A_dsa_next    0x00000030
--static u32 A_dsa_next_used[] __attribute((unused)) = {
--      0x00000061,
--};
--
--#define A_dsa_restore_pointers        0x00000000
--static u32 A_dsa_restore_pointers_used[] __attribute((unused)) = {
--      0x00000146,
--};
--
--#define A_dsa_save_data_pointer       0x00000000
--static u32 A_dsa_save_data_pointer_used[] __attribute((unused)) = {
--      0x00000131,
--};
--
--#define A_dsa_select  0x0000003c
--static u32 A_dsa_select_used[] __attribute((unused)) = {
--      0x00000082,
--};
--
--#define A_dsa_sscf_710        0x00000000
--static u32 A_dsa_sscf_710_used[] __attribute((unused)) = {
--      0x00000007,
--};
--
--#define A_dsa_status  0x00000060
--static u32 A_dsa_status_used[] __attribute((unused)) = {
--      0x00000198,
--};
--
--#define A_dsa_temp_addr_array_value   0x00000000
--static u32 A_dsa_temp_addr_array_value_used[] __attribute((unused)) = {
--};
--
--#define A_dsa_temp_addr_dsa_value     0x00000000
--static u32 A_dsa_temp_addr_dsa_value_used[] __attribute((unused)) = {
--      0x00000001,
--};
--
--#define A_dsa_temp_addr_new_value     0x00000000
--static u32 A_dsa_temp_addr_new_value_used[] __attribute((unused)) = {
--};
--
--#define A_dsa_temp_addr_next  0x00000000
--static u32 A_dsa_temp_addr_next_used[] __attribute((unused)) = {
--      0x0000001c,
--      0x0000004f,
--};
--
--#define A_dsa_temp_addr_residual      0x00000000
--static u32 A_dsa_temp_addr_residual_used[] __attribute((unused)) = {
--      0x0000002d,
--      0x0000003b,
--};
--
--#define A_dsa_temp_addr_saved_pointer 0x00000000
--static u32 A_dsa_temp_addr_saved_pointer_used[] __attribute((unused)) = {
--      0x0000002b,
--      0x00000037,
--};
--
--#define A_dsa_temp_addr_saved_residual        0x00000000
--static u32 A_dsa_temp_addr_saved_residual_used[] __attribute((unused)) = {
--      0x0000002e,
--      0x0000003a,
--};
--
--#define A_dsa_temp_lun        0x00000000
--static u32 A_dsa_temp_lun_used[] __attribute((unused)) = {
--      0x0000004c,
--};
--
--#define A_dsa_temp_next       0x00000000
--static u32 A_dsa_temp_next_used[] __attribute((unused)) = {
--      0x0000001f,
--};
--
--#define A_dsa_temp_sync       0x00000000
--static u32 A_dsa_temp_sync_used[] __attribute((unused)) = {
--      0x00000057,
--};
--
--#define A_dsa_temp_target     0x00000000
--static u32 A_dsa_temp_target_used[] __attribute((unused)) = {
--      0x00000045,
--};
--
--#define A_emulfly     0x00000000
--static u32 A_emulfly_used[] __attribute((unused)) = {
--};
--
--#define A_int_debug_break     0x03000000
--static u32 A_int_debug_break_used[] __attribute((unused)) = {
--      0x0000023c,
--};
--
--#define A_int_debug_panic     0x030b0000
--static u32 A_int_debug_panic_used[] __attribute((unused)) = {
--      0x00000209,
--      0x00000219,
--};
--
--#define A_int_err_check_condition     0x00030000
--static u32 A_int_err_check_condition_used[] __attribute((unused)) = {
--      0x000001a9,
--};
--
--#define A_int_err_no_phase    0x00040000
--static u32 A_int_err_no_phase_used[] __attribute((unused)) = {
--};
+-      /* syscall ? */
+-      if (TRAP(regs) != 0x0C00)
+-              return;
 -
--#define A_int_err_selected    0x00010000
--static u32 A_int_err_selected_used[] __attribute((unused)) = {
--      0x000001ff,
--};
+-      /* error signalled ? */
+-      if (!(regs->ccr & 0x10000000))
+-              return;
 -
--#define A_int_err_unexpected_phase    0x00000000
--static u32 A_int_err_unexpected_phase_used[] __attribute((unused)) = {
--      0x00000092,
--      0x00000098,
--      0x000000a0,
--      0x000000d6,
--      0x000000da,
--      0x000000dc,
--      0x000000e4,
--      0x000000e8,
--      0x000000ea,
--      0x000000f2,
--      0x000000f6,
--      0x000000f8,
--      0x000000fa,
--      0x00000160,
--};
+-      switch (ret) {
+-      case ERESTART_RESTARTBLOCK:
+-      case ERESTARTNOHAND:
+-              /* ERESTARTNOHAND means that the syscall should only be
+-               * restarted if there was no handler for the signal, and since
+-               * we only get here if there is a handler, we dont restart.
+-               */
+-              restart = !has_handler;
+-              break;
+-      case ERESTARTSYS:
+-              /* ERESTARTSYS means to restart the syscall if there is no
+-               * handler or the handler was registered with SA_RESTART
+-               */
+-              restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0;
+-              break;
+-      case ERESTARTNOINTR:
+-              /* ERESTARTNOINTR means that the syscall should be
+-               * called again after the signal handler returns.
+-               */
+-              break;
+-      default:
+-              return;
+-      }
+-      if (restart) {
+-              if (ret == ERESTART_RESTARTBLOCK)
+-                      regs->gpr[0] = __NR_restart_syscall;
+-              else
+-                      regs->gpr[3] = regs->orig_gpr3;
+-              regs->nip -= 4;
+-              regs->result = 0;
+-      } else {
+-              regs->result = -EINTR;
+-              regs->gpr[3] = EINTR;
+-              regs->ccr |= 0x10000000;
+-      }
+-}
 -
--#define A_int_err_unexpected_reselect 0x00020000
--static u32 A_int_err_unexpected_reselect_used[] __attribute((unused)) = {
--      0x000001cd,
--};
+-int do_signal(sigset_t *oldset, struct pt_regs *regs)
+-{
+-      siginfo_t info;
+-      int signr;
+-      struct k_sigaction ka;
+-      int ret;
+-      int is32 = is_32bit_task();
 -
--#define A_int_msg_1   0x01020000
--static u32 A_int_msg_1_used[] __attribute((unused)) = {
--      0x00000114,
--      0x00000116,
--};
+-      if (test_thread_flag(TIF_RESTORE_SIGMASK))
+-              oldset = &current->saved_sigmask;
+-      else if (!oldset)
+-              oldset = &current->blocked;
 -
--#define A_int_msg_sdtr        0x01010000
--static u32 A_int_msg_sdtr_used[] __attribute((unused)) = {
--      0x00000180,
--};
+-      signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 -
--#define A_int_msg_wdtr        0x01000000
--static u32 A_int_msg_wdtr_used[] __attribute((unused)) = {
--      0x00000174,
--};
+-      /* Is there any syscall restart business here ? */
+-      check_syscall_restart(regs, &ka, signr > 0);
 -
--#define A_int_norm_aborted    0x02040000
--static u32 A_int_norm_aborted_used[] __attribute((unused)) = {
--      0x00000270,
--};
+-      if (signr <= 0) {
+-              /* No signal to deliver -- put the saved sigmask back */
+-              if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+-                      clear_thread_flag(TIF_RESTORE_SIGMASK);
+-                      sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+-              }
+-              return 0;               /* no signals delivered */
+-      }
 -
--#define A_int_norm_command_complete   0x02020000
--static u32 A_int_norm_command_complete_used[] __attribute((unused)) = {
--};
+-        /*
+-       * Reenable the DABR before delivering the signal to
+-       * user space. The DABR will have been cleared if it
+-       * triggered inside the kernel.
+-       */
+-      if (current->thread.dabr)
+-              set_dabr(current->thread.dabr);
 -
--#define A_int_norm_disconnected       0x02030000
--static u32 A_int_norm_disconnected_used[] __attribute((unused)) = {
--};
+-      if (is32) {
+-              if (ka.sa.sa_flags & SA_SIGINFO)
+-                      ret = handle_rt_signal32(signr, &ka, &info, oldset,
+-                                      regs);
+-              else
+-                      ret = handle_signal32(signr, &ka, &info, oldset,
+-                                      regs);
+-      } else {
+-              ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
+-      }
 -
--#define A_int_norm_emulateintfly      0x02060000
--static u32 A_int_norm_emulateintfly_used[] __attribute((unused)) = {
--      0x000001a2,
--};
+-      if (ret) {
+-              spin_lock_irq(&current->sighand->siglock);
+-              sigorsets(&current->blocked, &current->blocked,
+-                        &ka.sa.sa_mask);
+-              if (!(ka.sa.sa_flags & SA_NODEFER))
+-                      sigaddset(&current->blocked, signr);
+-              recalc_sigpending();
+-              spin_unlock_irq(&current->sighand->siglock);
 -
--#define A_int_norm_reselect_complete  0x02010000
--static u32 A_int_norm_reselect_complete_used[] __attribute((unused)) = {
--};
+-              /*
+-               * A signal was successfully delivered; the saved sigmask is in
+-               * its frame, and we can clear the TIF_RESTORE_SIGMASK flag.
+-               */
+-              if (test_thread_flag(TIF_RESTORE_SIGMASK))
+-                      clear_thread_flag(TIF_RESTORE_SIGMASK);
+-      }
 -
--#define A_int_norm_reset      0x02050000
--static u32 A_int_norm_reset_used[] __attribute((unused)) = {
--};
+-      return ret;
+-}
 -
--#define A_int_norm_select_complete    0x02000000
--static u32 A_int_norm_select_complete_used[] __attribute((unused)) = {
--};
+-long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+-              unsigned long r5, unsigned long r6, unsigned long r7,
+-              unsigned long r8, struct pt_regs *regs)
+-{
+-      return do_sigaltstack(uss, uoss, regs->gpr[1]);
+-}
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/signal.h linux-2.6.22-570/arch/powerpc/kernel/signal.h
+--- linux-2.6.22-590/arch/powerpc/kernel/signal.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/signal.h      1969-12-31 19:00:00.000000000 -0500
+@@ -1,55 +0,0 @@
+-/*
+- *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+- *    Extracted from signal_32.c and signal_64.c
+- *
+- * This file is subject to the terms and conditions of the GNU General
+- * Public License.  See the file README.legal in the main directory of
+- * this archive for more details.
+- */
 -
--#define A_int_test_1  0x04000000
--static u32 A_int_test_1_used[] __attribute((unused)) = {
--      0x0000021e,
--};
+-#ifndef _POWERPC_ARCH_SIGNAL_H
+-#define _POWERPC_ARCH_SIGNAL_H
 -
--#define A_int_test_2  0x04010000
--static u32 A_int_test_2_used[] __attribute((unused)) = {
--      0x0000023a,
--};
+-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 -
--#define A_int_test_3  0x04020000
--static u32 A_int_test_3_used[] __attribute((unused)) = {
--};
+-extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+-                                size_t frame_size);
+-extern void restore_sigmask(sigset_t *set);
 -
--#define A_msg_buf     0x00000000
--static u32 A_msg_buf_used[] __attribute((unused)) = {
--      0x00000108,
--      0x00000162,
--      0x0000016c,
--      0x00000172,
--      0x00000178,
--      0x0000017e,
--};
+-extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+-                         siginfo_t *info, sigset_t *oldset,
+-                         struct pt_regs *regs);
 -
--#define A_reconnect_dsa_head  0x00000000
--static u32 A_reconnect_dsa_head_used[] __attribute((unused)) = {
--      0x0000006d,
--      0x00000074,
--      0x000001b1,
--};
+-extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
+-                            siginfo_t *info, sigset_t *oldset,
+-                            struct pt_regs *regs);
 -
--#define A_reselected_identify 0x00000000
--static u32 A_reselected_identify_used[] __attribute((unused)) = {
--      0x00000048,
--      0x000001af,
--};
 -
--#define A_reselected_tag      0x00000000
--static u32 A_reselected_tag_used[] __attribute((unused)) = {
--};
+-#ifdef CONFIG_PPC64
 -
--#define A_saved_dsa   0x00000000
--static u32 A_saved_dsa_used[] __attribute((unused)) = {
--      0x00000005,
--      0x0000000e,
--      0x00000023,
--      0x00000025,
--      0x00000032,
--      0x0000003f,
--      0x00000054,
--      0x0000005f,
--      0x00000070,
--      0x00000078,
--      0x0000008d,
--      0x000000aa,
--      0x000000bb,
--      0x000000c0,
--      0x000000d1,
--      0x0000012f,
--      0x000001a4,
--      0x000001b5,
--      0x000001ba,
--      0x000001e2,
--};
+-static inline int is_32bit_task(void)
+-{
+-      return test_thread_flag(TIF_32BIT);
+-}
 -
--#define A_schedule    0x00000000
--static u32 A_schedule_used[] __attribute((unused)) = {
--      0x0000007d,
--      0x000001a7,
--      0x00000203,
--      0x00000244,
--};
+-extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
+-                            siginfo_t *info, sigset_t *set,
+-                            struct pt_regs *regs);
 -
--#define A_test_dest   0x00000000
--static u32 A_test_dest_used[] __attribute((unused)) = {
--      0x0000021c,
--};
+-#else /* CONFIG_PPC64 */
 -
--#define A_test_src    0x00000000
--static u32 A_test_src_used[] __attribute((unused)) = {
--      0x0000021b,
--};
+-static inline int is_32bit_task(void)
+-{
+-      return 1;
+-}
 -
--#define Ent_accept_message    0x00000624
--#define Ent_cmdout_cmdout     0x00000264
--#define Ent_command_complete  0x0000065c
--#define Ent_command_complete_msgin    0x0000066c
--#define Ent_data_transfer     0x0000026c
--#define Ent_datain_to_jump    0x00000334
--#define Ent_debug_break       0x000008ec
--#define Ent_dsa_code_begin    0x00000000
--#define Ent_dsa_code_check_reselect   0x0000010c
--#define Ent_dsa_code_fix_jump 0x00000058
--#define Ent_dsa_code_restore_pointers 0x000000d8
--#define Ent_dsa_code_save_data_pointer        0x000000a4
--#define Ent_dsa_code_template 0x00000000
--#define Ent_dsa_code_template_end     0x00000178
--#define Ent_dsa_schedule      0x00000178
--#define Ent_dsa_zero  0x00000178
--#define Ent_end_data_transfer 0x000002a4
--#define Ent_initiator_abort   0x00000914
--#define Ent_msg_in    0x0000041c
--#define Ent_msg_in_restart    0x000003fc
--#define Ent_other_in  0x0000038c
--#define Ent_other_out 0x00000354
--#define Ent_other_transfer    0x000003c4
--#define Ent_reject_message    0x00000604
--#define Ent_reselected_check_next     0x000006f0
--#define Ent_reselected_ok     0x00000798
--#define Ent_respond_message   0x0000063c
--#define Ent_select    0x000001f8
--#define Ent_select_msgout     0x00000218
--#define Ent_target_abort      0x000008f4
--#define Ent_test_1    0x00000868
--#define Ent_test_2    0x0000087c
--#define Ent_test_2_msgout     0x0000089c
--#define Ent_wait_reselect     0x000006a8
--static u32 LABELPATCHES[] __attribute((unused)) = {
--      0x00000011,
--      0x0000001a,
--      0x0000001d,
--      0x00000028,
--      0x0000002a,
--      0x00000035,
--      0x00000038,
--      0x00000042,
--      0x00000050,
--      0x00000052,
--      0x0000006b,
--      0x00000083,
--      0x00000085,
--      0x00000090,
--      0x00000094,
--      0x00000096,
--      0x0000009c,
--      0x0000009e,
--      0x000000a2,
--      0x000000a4,
--      0x000000a6,
--      0x000000a8,
--      0x000000b6,
--      0x000000b9,
--      0x000000cc,
--      0x000000cf,
--      0x000000d8,
--      0x000000de,
--      0x000000e0,
--      0x000000e6,
--      0x000000ec,
--      0x000000ee,
--      0x000000f4,
--      0x000000fc,
--      0x000000fe,
--      0x0000010a,
--      0x0000010c,
--      0x0000010e,
--      0x00000110,
--      0x00000112,
--      0x00000118,
--      0x0000011a,
--      0x0000012d,
--      0x00000143,
--      0x00000158,
--      0x0000015c,
--      0x00000164,
--      0x00000166,
--      0x00000168,
--      0x0000016e,
--      0x0000017a,
--      0x000001ab,
--      0x000001b8,
--      0x000001bf,
--      0x000001c3,
--      0x000001c7,
--      0x000001cb,
--      0x000001e0,
--      0x000001f8,
--      0x00000207,
--      0x0000020f,
--      0x00000213,
--      0x00000217,
--      0x00000224,
--      0x00000226,
--      0x00000248,
--      0x0000024a,
--      0x0000024c,
--      0x0000024e,
--      0x00000250,
--      0x00000252,
--      0x00000256,
--      0x0000025a,
--      0x0000025c,
--      0x00000260,
--      0x00000262,
--      0x00000266,
--      0x00000268,
--};
+-static inline int handle_rt_signal64(int signr, struct k_sigaction *ka,
+-                                   siginfo_t *info, sigset_t *set,
+-                                   struct pt_regs *regs)
+-{
+-      return -EFAULT;
+-}
 -
--static struct {
--      u32     offset;
--      void            *address;
--} EXTERNAL_PATCHES[] __attribute((unused)) = {
--};
+-#endif /* !defined(CONFIG_PPC64) */
 -
--static u32 INSTRUCTIONS __attribute((unused)) = 290;
--static u32 PATCHES __attribute((unused))      = 78;
--static u32 EXTERNAL_PATCHES_LEN __attribute((unused)) = 0;
-diff -Nurb linux-2.6.22-570/drivers/scsi/53c7xx_u.h_shipped linux-2.6.22-590/drivers/scsi/53c7xx_u.h_shipped
---- linux-2.6.22-570/drivers/scsi/53c7xx_u.h_shipped   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/53c7xx_u.h_shipped   1969-12-31 19:00:00.000000000 -0500
-@@ -1,102 +0,0 @@
--#undef A_NCR53c7xx_msg_abort
--#undef A_NCR53c7xx_msg_reject
--#undef A_NCR53c7xx_sink
--#undef A_NCR53c7xx_zero
--#undef A_NOP_insn
--#undef A_addr_dsa
--#undef A_addr_reconnect_dsa_head
--#undef A_addr_scratch
--#undef A_addr_temp
--#undef A_dmode_memory_to_memory
--#undef A_dmode_memory_to_ncr
--#undef A_dmode_ncr_to_memory
--#undef A_dsa_check_reselect
--#undef A_dsa_cmdout
--#undef A_dsa_cmnd
--#undef A_dsa_datain
--#undef A_dsa_dataout
--#undef A_dsa_end
--#undef A_dsa_fields_start
--#undef A_dsa_msgin
--#undef A_dsa_msgout
--#undef A_dsa_msgout_other
--#undef A_dsa_next
--#undef A_dsa_restore_pointers
--#undef A_dsa_save_data_pointer
--#undef A_dsa_select
--#undef A_dsa_sscf_710
--#undef A_dsa_status
--#undef A_dsa_temp_addr_array_value
--#undef A_dsa_temp_addr_dsa_value
--#undef A_dsa_temp_addr_new_value
--#undef A_dsa_temp_addr_next
--#undef A_dsa_temp_addr_residual
--#undef A_dsa_temp_addr_saved_pointer
--#undef A_dsa_temp_addr_saved_residual
--#undef A_dsa_temp_lun
--#undef A_dsa_temp_next
--#undef A_dsa_temp_sync
--#undef A_dsa_temp_target
--#undef A_emulfly
--#undef A_int_debug_break
--#undef A_int_debug_panic
--#undef A_int_err_check_condition
--#undef A_int_err_no_phase
--#undef A_int_err_selected
--#undef A_int_err_unexpected_phase
--#undef A_int_err_unexpected_reselect
--#undef A_int_msg_1
--#undef A_int_msg_sdtr
--#undef A_int_msg_wdtr
--#undef A_int_norm_aborted
--#undef A_int_norm_command_complete
--#undef A_int_norm_disconnected
--#undef A_int_norm_emulateintfly
--#undef A_int_norm_reselect_complete
--#undef A_int_norm_reset
--#undef A_int_norm_select_complete
--#undef A_int_test_1
--#undef A_int_test_2
--#undef A_int_test_3
--#undef A_msg_buf
--#undef A_reconnect_dsa_head
--#undef A_reselected_identify
--#undef A_reselected_tag
--#undef A_saved_dsa
--#undef A_schedule
--#undef A_test_dest
--#undef A_test_src
--#undef Ent_accept_message
--#undef Ent_cmdout_cmdout
--#undef Ent_command_complete
--#undef Ent_command_complete_msgin
--#undef Ent_data_transfer
--#undef Ent_datain_to_jump
--#undef Ent_debug_break
--#undef Ent_dsa_code_begin
--#undef Ent_dsa_code_check_reselect
--#undef Ent_dsa_code_fix_jump
--#undef Ent_dsa_code_restore_pointers
--#undef Ent_dsa_code_save_data_pointer
--#undef Ent_dsa_code_template
--#undef Ent_dsa_code_template_end
--#undef Ent_dsa_schedule
--#undef Ent_dsa_zero
--#undef Ent_end_data_transfer
--#undef Ent_initiator_abort
--#undef Ent_msg_in
--#undef Ent_msg_in_restart
--#undef Ent_other_in
--#undef Ent_other_out
--#undef Ent_other_transfer
--#undef Ent_reject_message
--#undef Ent_reselected_check_next
--#undef Ent_reselected_ok
--#undef Ent_respond_message
--#undef Ent_select
--#undef Ent_select_msgout
--#undef Ent_target_abort
--#undef Ent_test_1
--#undef Ent_test_2
--#undef Ent_test_2_msgout
--#undef Ent_wait_reselect
-diff -Nurb linux-2.6.22-570/drivers/scsi/BusLogic.c linux-2.6.22-590/drivers/scsi/BusLogic.c
---- linux-2.6.22-570/drivers/scsi/BusLogic.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/BusLogic.c   2008-01-02 13:56:37.000000000 -0500
-@@ -304,16 +304,8 @@
- static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB)
- {
-       struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
--      struct scsi_cmnd *cmd = CCB->Command;
--      if (cmd->use_sg != 0) {
--              pci_unmap_sg(HostAdapter->PCI_Device,
--                              (struct scatterlist *)cmd->request_buffer,
--                              cmd->use_sg, cmd->sc_data_direction);
--      } else if (cmd->request_bufflen != 0) {
--              pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer,
--                              CCB->DataLength, cmd->sc_data_direction);
--      }
-+      scsi_dma_unmap(CCB->Command);
-       pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer,
-                       CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
+-#endif  /* _POWERPC_ARCH_SIGNAL_H */
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/signal_32.c linux-2.6.22-570/arch/powerpc/kernel/signal_32.c
+--- linux-2.6.22-590/arch/powerpc/kernel/signal_32.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/signal_32.c   2007-07-08 19:32:17.000000000 -0400
+@@ -51,11 +51,12 @@
+ #include <asm/pgtable.h>
+ #endif
  
-@@ -2648,7 +2640,8 @@
-                        */
-                       if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 && CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) {
-                               struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[CCB->TargetID];
--                              struct SCSI_Inquiry *InquiryResult = (struct SCSI_Inquiry *) Command->request_buffer;
-+                              struct SCSI_Inquiry *InquiryResult =
-+                                      (struct SCSI_Inquiry *) scsi_sglist(Command);
-                               TargetFlags->TargetExists = true;
-                               TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
-                               TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
-@@ -2819,9 +2812,8 @@
-       int CDB_Length = Command->cmd_len;
-       int TargetID = Command->device->id;
-       int LogicalUnit = Command->device->lun;
--      void *BufferPointer = Command->request_buffer;
--      int BufferLength = Command->request_bufflen;
--      int SegmentCount = Command->use_sg;
-+      int BufferLength = scsi_bufflen(Command);
-+      int Count;
-       struct BusLogic_CCB *CCB;
-       /*
-          SCSI REQUEST_SENSE commands will be executed automatically by the Host
-@@ -2851,36 +2843,35 @@
-                       return 0;
-               }
-       }
-+
-       /*
-          Initialize the fields in the BusLogic Command Control Block (CCB).
-        */
--      if (SegmentCount == 0 && BufferLength != 0) {
--              CCB->Opcode = BusLogic_InitiatorCCB;
--              CCB->DataLength = BufferLength;
--              CCB->DataPointer = pci_map_single(HostAdapter->PCI_Device,
--                              BufferPointer, BufferLength,
--                              Command->sc_data_direction);
--      } else if (SegmentCount != 0) {
--              struct scatterlist *ScatterList = (struct scatterlist *) BufferPointer;
--              int Segment, Count;
-+      Count = scsi_dma_map(Command);
-+      BUG_ON(Count < 0);
-+      if (Count) {
-+              struct scatterlist *sg;
-+              int i;
+-#include "signal.h"
+-
+ #undef DEBUG_SIG
  
--              Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount,
--                              Command->sc_data_direction);
-               CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
-               CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment);
-               if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
-                       CCB->DataPointer = (unsigned int) CCB->DMA_Handle + ((unsigned long) &CCB->ScatterGatherList - (unsigned long) CCB);
-               else
-                       CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList);
--              for (Segment = 0; Segment < Count; Segment++) {
--                      CCB->ScatterGatherList[Segment].SegmentByteCount = sg_dma_len(ScatterList + Segment);
--                      CCB->ScatterGatherList[Segment].SegmentDataPointer = sg_dma_address(ScatterList + Segment);
-+
-+              scsi_for_each_sg(Command, sg, Count, i) {
-+                      CCB->ScatterGatherList[i].SegmentByteCount =
-+                              sg_dma_len(sg);
-+                      CCB->ScatterGatherList[i].SegmentDataPointer =
-+                              sg_dma_address(sg);
-               }
--      } else {
-+      } else if (!Count) {
-               CCB->Opcode = BusLogic_InitiatorCCB;
-               CCB->DataLength = BufferLength;
-               CCB->DataPointer = 0;
-       }
++#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 +
-       switch (CDB[0]) {
-       case READ_6:
-       case READ_10:
-diff -Nurb linux-2.6.22-570/drivers/scsi/Kconfig linux-2.6.22-590/drivers/scsi/Kconfig
---- linux-2.6.22-570/drivers/scsi/Kconfig      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/Kconfig      2008-01-02 13:56:37.000000000 -0500
-@@ -739,7 +739,7 @@
- config SCSI_IBMMCA
-       tristate "IBMMCA SCSI support"
--      depends on MCA_LEGACY && SCSI
-+      depends on MCA && SCSI
-       ---help---
-         This is support for the IBM SCSI adapter found in many of the PS/2
-         series computers.  These machines have an MCA bus, so you need to
-@@ -1007,6 +1007,11 @@
-         To compile this driver as a module, choose M here: the
-         module will be called stex.
+ #ifdef CONFIG_PPC64
++#define do_signal     do_signal32
+ #define sys_sigsuspend        compat_sys_sigsuspend
+ #define sys_rt_sigsuspend     compat_sys_rt_sigsuspend
+ #define sys_rt_sigreturn      compat_sys_rt_sigreturn
+@@ -230,6 +231,8 @@
  
-+config 53C700_BE_BUS
-+      bool
-+      depends on SCSI_A4000T || SCSI_ZORRO7XX || MVME16x_SCSI || BVME6000_SCSI
-+      default y
-+
- config SCSI_SYM53C8XX_2
-       tristate "SYM53C8XX Version 2 SCSI support"
-       depends on PCI && SCSI
-@@ -1611,13 +1616,25 @@
-         If you have the Phase5 Fastlane Z3 SCSI controller, or plan to use
-         one in the near future, say Y to this question. Otherwise, say N.
+ #endif /* CONFIG_PPC64 */
  
--config SCSI_AMIGA7XX
--      bool "Amiga NCR53c710 SCSI support (EXPERIMENTAL)"
--      depends on AMIGA && SCSI && EXPERIMENTAL && BROKEN
-+config SCSI_A4000T
-+      tristate "A4000T NCR53c710 SCSI support (EXPERIMENTAL)"
-+      depends on AMIGA && SCSI && EXPERIMENTAL
-+      select SCSI_SPI_ATTRS
-       help
--        Support for various NCR53c710-based SCSI controllers on the Amiga.
-+        If you have an Amiga 4000T and have SCSI devices connected to the
-+        built-in SCSI controller, say Y. Otherwise, say N.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called a4000t.
++int do_signal(sigset_t *oldset, struct pt_regs *regs);
 +
-+config SCSI_ZORRO7XX
-+      tristate "Zorro NCR53c710 SCSI support (EXPERIMENTAL)"
-+      depends on ZORRO && SCSI && EXPERIMENTAL
-+      select SCSI_SPI_ATTRS
-+      help
-+        Support for various NCR53c710-based SCSI controllers on Zorro
-+        expansion boards for the Amiga.
-         This includes:
--          - the builtin SCSI controller on the Amiga 4000T,
-           - the Amiga 4091 Zorro III SCSI-2 controller,
-           - the MacroSystem Development's WarpEngine Amiga SCSI-2 controller
-             (info at
-@@ -1625,10 +1642,6 @@
-           - the SCSI controller on the Phase5 Blizzard PowerUP 603e+
-             accelerator card for the Amiga 1200,
-           - the SCSI controller on the GVP Turbo 040/060 accelerator.
--        Note that all of the above SCSI controllers, except for the builtin
--        SCSI controller on the Amiga 4000T, reside on the Zorro expansion
--        bus, so you also have to enable Zorro bus support if you want to use
--        them.
- config OKTAGON_SCSI
-       tristate "BSC Oktagon SCSI support (EXPERIMENTAL)"
-@@ -1712,8 +1725,8 @@
-         single-board computer.
- config MVME16x_SCSI
--      bool "NCR53C710 SCSI driver for MVME16x"
--      depends on MVME16x && SCSI && BROKEN
-+      tristate "NCR53C710 SCSI driver for MVME16x"
-+      depends on MVME16x && SCSI
-       select SCSI_SPI_ATTRS
-       help
-         The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710
-@@ -1721,22 +1734,14 @@
-         will want to say Y to this question.
- config BVME6000_SCSI
--      bool "NCR53C710 SCSI driver for BVME6000"
--      depends on BVME6000 && SCSI && BROKEN
-+      tristate "NCR53C710 SCSI driver for BVME6000"
-+      depends on BVME6000 && SCSI
-       select SCSI_SPI_ATTRS
-       help
-         The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710
-         SCSI controller chip.  Almost everyone using one of these boards
-         will want to say Y to this question.
--config SCSI_NCR53C7xx_FAST
--      bool "allow FAST-SCSI [10MHz]"
--      depends on SCSI_AMIGA7XX || MVME16x_SCSI || BVME6000_SCSI
--      help
--        This will enable 10MHz FAST-SCSI transfers with your host
--        adapter. Some systems have problems with that speed, so it's safest
--        to say N here.
--
- config SUN3_SCSI
-       tristate "Sun3 NCR5380 SCSI"
-       depends on SUN3 && SCSI
-diff -Nurb linux-2.6.22-570/drivers/scsi/Makefile linux-2.6.22-590/drivers/scsi/Makefile
---- linux-2.6.22-570/drivers/scsi/Makefile     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/Makefile     2008-01-02 13:56:37.000000000 -0500
-@@ -37,7 +37,8 @@
- obj-$(CONFIG_ISCSI_TCP)       += libiscsi.o   iscsi_tcp.o
- obj-$(CONFIG_INFINIBAND_ISER)         += libiscsi.o
--obj-$(CONFIG_SCSI_AMIGA7XX)   += amiga7xx.o   53c7xx.o
-+obj-$(CONFIG_SCSI_A4000T)     += 53c700.o     a4000t.o
-+obj-$(CONFIG_SCSI_ZORRO7XX)   += 53c700.o     zorro7xx.o
- obj-$(CONFIG_A3000_SCSI)      += a3000.o      wd33c93.o
- obj-$(CONFIG_A2091_SCSI)      += a2091.o      wd33c93.o
- obj-$(CONFIG_GVP11_SCSI)      += gvp11.o      wd33c93.o
-@@ -53,8 +54,8 @@
- obj-$(CONFIG_MAC_SCSI)                += mac_scsi.o
- obj-$(CONFIG_SCSI_MAC_ESP)    += mac_esp.o    NCR53C9x.o
- obj-$(CONFIG_SUN3_SCSI)               += sun3_scsi.o  sun3_scsi_vme.o
--obj-$(CONFIG_MVME16x_SCSI)    += mvme16x.o    53c7xx.o
--obj-$(CONFIG_BVME6000_SCSI)   += bvme6000.o   53c7xx.o
-+obj-$(CONFIG_MVME16x_SCSI)    += 53c700.o     mvme16x_scsi.o
-+obj-$(CONFIG_BVME6000_SCSI)   += 53c700.o     bvme6000_scsi.o
- obj-$(CONFIG_SCSI_SIM710)     += 53c700.o     sim710.o
- obj-$(CONFIG_SCSI_ADVANSYS)   += advansys.o
- obj-$(CONFIG_SCSI_PSI240I)    += psi240i.o
-@@ -168,10 +169,8 @@
- oktagon_esp_mod-objs  := oktagon_esp.o oktagon_io.o
- # Files generated that shall be removed upon make clean
--clean-files :=        53c7xx_d.h 53c700_d.h   \
--              53c7xx_u.h 53c700_u.h
-+clean-files :=        53c700_d.h 53c700_u.h
--$(obj)/53c7xx.o:   $(obj)/53c7xx_d.h $(obj)/53c7xx_u.h
- $(obj)/53c700.o $(MODVERDIR)/$(obj)/53c700.ver: $(obj)/53c700_d.h
- # If you want to play with the firmware, uncomment
-@@ -179,11 +178,6 @@
- ifdef GENERATE_FIRMWARE
--$(obj)/53c7xx_d.h: $(src)/53c7xx.scr $(src)/script_asm.pl
--      $(CPP) -traditional -DCHIP=710 - < $< | grep -v '^#' | $(PERL) -s $(src)/script_asm.pl -ncr7x0_family $@ $(@:_d.h=_u.h)
--
--$(obj)/53c7xx_u.h: $(obj)/53c7xx_d.h
--
- $(obj)/53c700_d.h: $(src)/53c700.scr $(src)/script_asm.pl
-       $(PERL) -s $(src)/script_asm.pl -ncr7x0_family $@ $(@:_d.h=_u.h) < $<
-diff -Nurb linux-2.6.22-570/drivers/scsi/NCR5380.c linux-2.6.22-590/drivers/scsi/NCR5380.c
---- linux-2.6.22-570/drivers/scsi/NCR5380.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/NCR5380.c    2008-01-02 13:56:37.000000000 -0500
-@@ -347,7 +347,7 @@
-               if((r & bit) == val)
-                       return 0;
-               if(!in_interrupt())
--                      yield();
-+                      cond_resched();
-               else
-                       cpu_relax();
-       }
-@@ -357,7 +357,7 @@
- static struct {
-       unsigned char value;
-       const char *name;
--} phases[] = {
-+} phases[] __maybe_unused = {
-       {PHASE_DATAOUT, "DATAOUT"}, 
-       {PHASE_DATAIN, "DATAIN"}, 
-       {PHASE_CMDOUT, "CMDOUT"}, 
-@@ -575,7 +575,8 @@
-  *    Locks: none, irqs must be enabled on entry
-  */
--static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
-+static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
-+                                              int possible)
- {
-       NCR5380_local_declare();
-       struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
-@@ -629,7 +630,8 @@
-  *    Locks: none
+ /*
+  * Atomically swap in the new signal mask, and wait for a signal.
   */
+@@ -248,6 +251,14 @@
+       return -ERESTARTNOHAND;
+ }
  
--static void __init NCR5380_print_options(struct Scsi_Host *instance)
-+static void __init __maybe_unused
-+NCR5380_print_options(struct Scsi_Host *instance)
- {
-       printk(" generic options"
- #ifdef AUTOPROBE_IRQ
-@@ -703,8 +705,8 @@
- static
- char *lprint_opcode(int opcode, char *pos, char *buffer, int length);
--static
--int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, off_t offset, int length, int inout)
-+static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
-+      char *buffer, char **start, off_t offset, int length, int inout)
- {
-       char *pos = buffer;
-       struct NCR5380_hostdata *hostdata;
-diff -Nurb linux-2.6.22-570/drivers/scsi/NCR5380.h linux-2.6.22-590/drivers/scsi/NCR5380.h
---- linux-2.6.22-570/drivers/scsi/NCR5380.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/NCR5380.h    2008-01-02 13:56:37.000000000 -0500
-@@ -299,7 +299,7 @@
- static irqreturn_t NCR5380_intr(int irq, void *dev_id);
- #endif
- static void NCR5380_main(struct work_struct *work);
--static void NCR5380_print_options(struct Scsi_Host *instance);
-+static void __maybe_unused NCR5380_print_options(struct Scsi_Host *instance);
- #ifdef NDEBUG
- static void NCR5380_print_phase(struct Scsi_Host *instance);
- static void NCR5380_print(struct Scsi_Host *instance);
-@@ -307,8 +307,8 @@
- static int NCR5380_abort(Scsi_Cmnd * cmd);
- static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
- static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
--static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
--off_t offset, int length, int inout);
-+static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
-+      char *buffer, char **start, off_t offset, int length, int inout);
- static void NCR5380_reselect(struct Scsi_Host *instance);
- static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
-diff -Nurb linux-2.6.22-570/drivers/scsi/NCR53c406a.c linux-2.6.22-590/drivers/scsi/NCR53c406a.c
---- linux-2.6.22-570/drivers/scsi/NCR53c406a.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/NCR53c406a.c 2008-01-02 13:56:37.000000000 -0500
-@@ -698,7 +698,7 @@
-       int i;
-       VDEB(printk("NCR53c406a_queue called\n"));
--      DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, SCpnt->request_bufflen));
-+      DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, scsi_bufflen(SCpnt)));
- #if 0
-       VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
-@@ -785,8 +785,8 @@
-       unsigned char status, int_reg;
- #if USE_PIO
-       unsigned char pio_status;
--      struct scatterlist *sglist;
--      unsigned int sgcount;
-+      struct scatterlist *sg;
-+        int i;
- #endif
-       VDEB(printk("NCR53c406a_intr called\n"));
-@@ -866,21 +866,17 @@
-                       current_SC->SCp.phase = data_out;
-                       VDEB(printk("NCR53c406a: Data-Out phase\n"));
-                       outb(FLUSH_FIFO, CMD_REG);
--                      LOAD_DMA_COUNT(current_SC->request_bufflen);    /* Max transfer size */
-+                      LOAD_DMA_COUNT(scsi_bufflen(current_SC));       /* Max transfer size */
- #if USE_DMA                   /* No s/g support for DMA */
--                      NCR53c406a_dma_write(current_SC->request_buffer, current_SC->request_bufflen);
-+                      NCR53c406a_dma_write(scsi_sglist(current_SC),
-+                                             scsdi_bufflen(current_SC));
++#ifdef CONFIG_PPC32
++long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5,
++              int r6, int r7, int r8, struct pt_regs *regs)
++{
++      return do_sigaltstack(uss, uoss, regs->gpr[1]);
++}
++#endif
 +
- #endif                                /* USE_DMA */
-                       outb(TRANSFER_INFO | DMA_OP, CMD_REG);
- #if USE_PIO
--                      if (!current_SC->use_sg)        /* Don't use scatter-gather */
--                              NCR53c406a_pio_write(current_SC->request_buffer, current_SC->request_bufflen);
--                      else {  /* use scatter-gather */
--                              sgcount = current_SC->use_sg;
--                              sglist = current_SC->request_buffer;
--                              while (sgcount--) {
--                                      NCR53c406a_pio_write(page_address(sglist->page) + sglist->offset, sglist->length);
--                                      sglist++;
--                              }
-+                        scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) {
-+                                NCR53c406a_pio_write(page_address(sg->page) + sg->offset,
-+                                                     sg->length);
-                       }
-                       REG0;
- #endif                                /* USE_PIO */
-@@ -893,21 +889,16 @@
-                       current_SC->SCp.phase = data_in;
-                       VDEB(printk("NCR53c406a: Data-In phase\n"));
-                       outb(FLUSH_FIFO, CMD_REG);
--                      LOAD_DMA_COUNT(current_SC->request_bufflen);    /* Max transfer size */
-+                      LOAD_DMA_COUNT(scsi_bufflen(current_SC));       /* Max transfer size */
- #if USE_DMA                   /* No s/g support for DMA */
--                      NCR53c406a_dma_read(current_SC->request_buffer, current_SC->request_bufflen);
-+                      NCR53c406a_dma_read(scsi_sglist(current_SC),
-+                                            scsdi_bufflen(current_SC));
- #endif                                /* USE_DMA */
-                       outb(TRANSFER_INFO | DMA_OP, CMD_REG);
- #if USE_PIO
--                      if (!current_SC->use_sg)        /* Don't use scatter-gather */
--                              NCR53c406a_pio_read(current_SC->request_buffer, current_SC->request_bufflen);
--                      else {  /* Use scatter-gather */
--                              sgcount = current_SC->use_sg;
--                              sglist = current_SC->request_buffer;
--                              while (sgcount--) {
--                                      NCR53c406a_pio_read(page_address(sglist->page) + sglist->offset, sglist->length);
--                                      sglist++;
--                              }
-+                        scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) {
-+                                NCR53c406a_pio_read(page_address(sg->page) + sg->offset,
-+                                                    sg->length);
-                       }
-                       REG0;
- #endif                                /* USE_PIO */
-diff -Nurb linux-2.6.22-570/drivers/scsi/a100u2w.c linux-2.6.22-590/drivers/scsi/a100u2w.c
---- linux-2.6.22-570/drivers/scsi/a100u2w.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/a100u2w.c    2008-01-02 13:56:37.000000000 -0500
-@@ -19,27 +19,6 @@
-  * along with this program; see the file COPYING.  If not, write to
-  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ long sys_sigaction(int sig, struct old_sigaction __user *act,
+               struct old_sigaction __user *oact)
+ {
+@@ -282,17 +293,14 @@
+ /*
+  * When we have signals to deliver, we set up on the
+  * user stack, going down from the original stack pointer:
+- *    an ABI gap of 56 words
+- *    an mcontext struct
++ *    a sigregs struct
+  *    a sigcontext struct
+  *    a gap of __SIGNAL_FRAMESIZE bytes
+  *
+- * Each of these things must be a multiple of 16 bytes in size. The following
+- * structure represent all of this except the __SIGNAL_FRAMESIZE gap
++ * Each of these things must be a multiple of 16 bytes in size.
   *
-- * --------------------------------------------------------------------------
-- *
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met:
-- * 1. Redistributions of source code must retain the above copyright
-- *    notice, this list of conditions, and the following disclaimer,
-- *    without modification, immediately at the beginning of the file.
-- * 2. Redistributions in binary form must reproduce the above copyright
-- *    notice, this list of conditions and the following disclaimer in the
-- *    documentation and/or other materials provided with the distribution.
-- * 3. The name of the author may not be used to endorse or promote products
-- *    derived from this software without specific prior written permission.
-- *
-- * Where this Software is combined with software released under the terms of 
-- * the GNU General Public License ("GPL") and the terms of the GPL would require the 
-- * combined work to also be released under the terms of the GPL, the terms
-- * and conditions of this License will apply in addition to those of the
-- * GPL with the exception of any terms or conditions of this License that
-- * conflict with, or are expressly prohibited by, the GPL.
-- *
-  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-@@ -75,6 +54,8 @@
-  * 9/28/04 Christoph Hellwig <hch@lst.de>
-  *        - merge the two source files
-  *        - remove internal queueing code
-+ * 14/06/07 Alan Cox <alan@redhat.com>
-+ *     - Grand cleanup and Linuxisation
   */
+-struct sigframe {
+-      struct sigcontext sctx;         /* the sigcontext */
++struct sigregs {
+       struct mcontext mctx;           /* all the register values */
+       /*
+        * Programs using the rs6000/xcoff abi can save up to 19 gp
+@@ -695,22 +703,44 @@
+ }
+ #endif /* CONFIG_PPC64 */
  
- #include <linux/module.h>
-@@ -102,14 +83,12 @@
- #include "a100u2w.h"
++
++/*
++ * Restore the user process's signal mask
++ */
++#ifdef CONFIG_PPC64
++extern void restore_sigmask(sigset_t *set);
++#else /* CONFIG_PPC64 */
++static void restore_sigmask(sigset_t *set)
++{
++      sigdelsetmask(set, ~_BLOCKABLE);
++      spin_lock_irq(&current->sighand->siglock);
++      current->blocked = *set;
++      recalc_sigpending();
++      spin_unlock_irq(&current->sighand->siglock);
++}
++#endif
++
+ /*
+  * Set up a signal frame for a "real-time" signal handler
+  * (one which gets siginfo).
+  */
+-int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
++static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
+               siginfo_t *info, sigset_t *oldset,
+-              struct pt_regs *regs)
++              struct pt_regs *regs, unsigned long newsp)
+ {
+       struct rt_sigframe __user *rt_sf;
+       struct mcontext __user *frame;
+-      unsigned long newsp = 0;
++      unsigned long origsp = newsp;
  
+       /* Set up Signal Frame */
+       /* Put a Real Time Context onto stack */
+-      rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf));
+-      if (unlikely(rt_sf == NULL))
++      newsp -= sizeof(*rt_sf);
++      rt_sf = (struct rt_sigframe __user *)newsp;
++
++      /* create a stack frame for the caller of the handler */
++      newsp -= __SIGNAL_FRAMESIZE + 16;
++
++      if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
+               goto badframe;
  
--#define JIFFIES_TO_MS(t) ((t) * 1000 / HZ)
--#define MS_TO_JIFFIES(j) ((j * HZ) / 1000)
-+static struct orc_scb *__orc_alloc_scb(struct orc_host * host);
-+static void inia100_scb_handler(struct orc_host *host, struct orc_scb *scb);
+       /* Put the siginfo & fill in most of the ucontext */
+@@ -740,12 +770,8 @@
  
--static ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
--static void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
-+static struct orc_nvram nvram, *nvramp = &nvram;
+       current->thread.fpscr.val = 0;  /* turn off all fp exceptions */
  
--static NVRAM nvram, *nvramp = &nvram;
--static UCHAR dftNvRam[64] =
-+static u8 default_nvram[64] =
+-      /* create a stack frame for the caller of the handler */
+-      newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
+       if (put_user(regs->gpr[1], (u32 __user *)newsp))
+               goto badframe;
+-
+-      /* Fill registers for signal handler */
+       regs->gpr[1] = newsp;
+       regs->gpr[3] = sig;
+       regs->gpr[4] = (unsigned long) &rt_sf->info;
+@@ -989,18 +1015,27 @@
+ /*
+  * OK, we're invoking a handler
+  */
+-int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+-                  siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
++static int handle_signal(unsigned long sig, struct k_sigaction *ka,
++              siginfo_t *info, sigset_t *oldset, struct pt_regs *regs,
++              unsigned long newsp)
  {
- /*----------header -------------*/
-       0x01,                   /* 0x00: Sub System Vendor ID 0 */
-@@ -158,823 +137,882 @@
- };
+       struct sigcontext __user *sc;
+-      struct sigframe __user *frame;
+-      unsigned long newsp = 0;
++      struct sigregs __user *frame;
++      unsigned long origsp = newsp;
  
+       /* Set up Signal Frame */
+-      frame = get_sigframe(ka, regs, sizeof(*frame));
+-      if (unlikely(frame == NULL))
++      newsp -= sizeof(struct sigregs);
++      frame = (struct sigregs __user *) newsp;
++
++      /* Put a sigcontext on the stack */
++      newsp -= sizeof(*sc);
++      sc = (struct sigcontext __user *) newsp;
++
++      /* create a stack frame for the caller of the handler */
++      newsp -= __SIGNAL_FRAMESIZE;
++
++      if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+               goto badframe;
+-      sc = (struct sigcontext __user *) &frame->sctx;
  
--/***************************************************************************/
--static void waitForPause(unsigned amount)
--{
--      ULONG the_time = jiffies + MS_TO_JIFFIES(amount);
--      while (time_before_eq(jiffies, the_time))
--              cpu_relax();
--}
--
--/***************************************************************************/
--static UCHAR waitChipReady(ORC_HCS * hcsp)
-+static u8 wait_chip_ready(struct orc_host * host)
- {
-       int i;
+ #if _NSIG != 64
+ #error "Please adjust handle_signal()"
+@@ -1012,7 +1047,7 @@
+ #else
+           || __put_user(oldset->sig[1], &sc->_unused[3])
+ #endif
+-          || __put_user(to_user_ptr(&frame->mctx), &sc->regs)
++          || __put_user(to_user_ptr(frame), &sc->regs)
+           || __put_user(sig, &sc->signal))
+               goto badframe;
  
-       for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
--              if (ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HOSTSTOP)       /* Wait HOSTSTOP set */
-+              if (inb(host->base + ORC_HCTRL) & HOSTSTOP)     /* Wait HOSTSTOP set */
-                       return 1;
--              waitForPause(100);      /* wait 100ms before try again  */
-+              mdelay(100);
-       }
-       return 0;
- }
+@@ -1028,11 +1063,8 @@
  
--/***************************************************************************/
--static UCHAR waitFWReady(ORC_HCS * hcsp)
-+static u8 wait_firmware_ready(struct orc_host * host)
- {
-       int i;
+       current->thread.fpscr.val = 0;  /* turn off all fp exceptions */
  
-       for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
--              if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY)         /* Wait READY set */
-+              if (inb(host->base + ORC_HSTUS) & RREADY)               /* Wait READY set */
-                       return 1;
--              waitForPause(100);      /* wait 100ms before try again  */
-+              mdelay(100);    /* wait 100ms before try again  */
-       }
+-      /* create a stack frame for the caller of the handler */
+-      newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
+       if (put_user(regs->gpr[1], (u32 __user *)newsp))
+               goto badframe;
+-
+       regs->gpr[1] = newsp;
+       regs->gpr[3] = sig;
+       regs->gpr[4] = (unsigned long) sc;
+@@ -1094,3 +1126,106 @@
+       force_sig(SIGSEGV, current);
        return 0;
  }
++
++/*
++ * Note that 'init' is a special process: it doesn't get signals it doesn't
++ * want to handle. Thus you cannot kill init even with a SIGKILL even by
++ * mistake.
++ */
++int do_signal(sigset_t *oldset, struct pt_regs *regs)
++{
++      siginfo_t info;
++      struct k_sigaction ka;
++      unsigned int newsp;
++      int signr, ret;
++
++#ifdef CONFIG_PPC32
++      if (try_to_freeze()) {
++              signr = 0;
++              if (!signal_pending(current))
++                      goto no_signal;
++      }
++#endif
++
++      if (test_thread_flag(TIF_RESTORE_SIGMASK))
++              oldset = &current->saved_sigmask;
++      else if (!oldset)
++              oldset = &current->blocked;
++
++      signr = get_signal_to_deliver(&info, &ka, regs, NULL);
++#ifdef CONFIG_PPC32
++no_signal:
++#endif
++      if (TRAP(regs) == 0x0C00                /* System Call! */
++          && regs->ccr & 0x10000000           /* error signalled */
++          && ((ret = regs->gpr[3]) == ERESTARTSYS
++              || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
++              || ret == ERESTART_RESTARTBLOCK)) {
++
++              if (signr > 0
++                  && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
++                      || (ret == ERESTARTSYS
++                          && !(ka.sa.sa_flags & SA_RESTART)))) {
++                      /* make the system call return an EINTR error */
++                      regs->result = -EINTR;
++                      regs->gpr[3] = EINTR;
++                      /* note that the cr0.SO bit is already set */
++              } else {
++                      regs->nip -= 4; /* Back up & retry system call */
++                      regs->result = 0;
++                      regs->trap = 0;
++                      if (ret == ERESTART_RESTARTBLOCK)
++                              regs->gpr[0] = __NR_restart_syscall;
++                      else
++                              regs->gpr[3] = regs->orig_gpr3;
++              }
++      }
++
++      if (signr == 0) {
++              /* No signal to deliver -- put the saved sigmask back */
++              if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
++                      clear_thread_flag(TIF_RESTORE_SIGMASK);
++                      sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
++              }
++              return 0;               /* no signals delivered */
++      }
++
++      if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
++          && !on_sig_stack(regs->gpr[1]))
++              newsp = current->sas_ss_sp + current->sas_ss_size;
++      else
++              newsp = regs->gpr[1];
++      newsp &= ~0xfUL;
++
++#ifdef CONFIG_PPC64
++      /*
++       * Reenable the DABR before delivering the signal to
++       * user space. The DABR will have been cleared if it
++       * triggered inside the kernel.
++       */
++      if (current->thread.dabr)
++              set_dabr(current->thread.dabr);
++#endif
++
++      /* Whee!  Actually deliver the signal.  */
++      if (ka.sa.sa_flags & SA_SIGINFO)
++              ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
++      else
++              ret = handle_signal(signr, &ka, &info, oldset, regs, newsp);
++
++      if (ret) {
++              spin_lock_irq(&current->sighand->siglock);
++              sigorsets(&current->blocked, &current->blocked,
++                        &ka.sa.sa_mask);
++              if (!(ka.sa.sa_flags & SA_NODEFER))
++                      sigaddset(&current->blocked, signr);
++              recalc_sigpending();
++              spin_unlock_irq(&current->sighand->siglock);
++              /* A signal was successfully delivered; the saved sigmask is in
++                 its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
++              if (test_thread_flag(TIF_RESTORE_SIGMASK))
++                      clear_thread_flag(TIF_RESTORE_SIGMASK);
++      }
++
++      return ret;
++}
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/signal_64.c linux-2.6.22-570/arch/powerpc/kernel/signal_64.c
+--- linux-2.6.22-590/arch/powerpc/kernel/signal_64.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/signal_64.c   2007-07-08 19:32:17.000000000 -0400
+@@ -34,10 +34,10 @@
+ #include <asm/syscalls.h>
+ #include <asm/vdso.h>
  
- /***************************************************************************/
--static UCHAR waitSCSIRSTdone(ORC_HCS * hcsp)
-+static u8 wait_scsi_reset_done(struct orc_host * host)
- {
-       int i;
+-#include "signal.h"
+-
+ #define DEBUG_SIG 0
  
-       for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
--              if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & SCSIRST))     /* Wait SCSIRST done */
-+              if (!(inb(host->base + ORC_HCTRL) & SCSIRST))   /* Wait SCSIRST done */
-                       return 1;
--              waitForPause(100);      /* wait 100ms before try again  */
-+              mdelay(100);    /* wait 100ms before try again  */
-       }
-       return 0;
- }
++#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
++
+ #define GP_REGS_SIZE  min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
+ #define FP_REGS_SIZE  sizeof(elf_fpregset_t)
  
- /***************************************************************************/
--static UCHAR waitHDOoff(ORC_HCS * hcsp)
-+static u8 wait_HDO_off(struct orc_host * host)
- {
-       int i;
+@@ -64,6 +64,14 @@
+       char abigap[288];
+ } __attribute__ ((aligned (16)));
  
-       for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
--              if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HDO))         /* Wait HDO off */
-+              if (!(inb(host->base + ORC_HCTRL) & HDO))               /* Wait HDO off */
-                       return 1;
--              waitForPause(100);      /* wait 100ms before try again  */
-+              mdelay(100);    /* wait 100ms before try again  */
-       }
-       return 0;
++long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
++                   unsigned long r6, unsigned long r7, unsigned long r8,
++                   struct pt_regs *regs)
++{
++      return do_sigaltstack(uss, uoss, regs->gpr[1]);
++}
++
++
+ /*
+  * Set up the sigcontext for the signal frame.
+  */
+@@ -200,6 +208,25 @@
  }
  
- /***************************************************************************/
--static UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData)
-+static u8 wait_hdi_set(struct orc_host * host, u8 * data)
- {
-       int i;
+ /*
++ * Allocate space for the signal frame
++ */
++static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
++                                size_t frame_size)
++{
++        unsigned long newsp;
++
++        /* Default to using normal stack */
++        newsp = regs->gpr[1];
++
++      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);
++      }
++
++        return (void __user *)((newsp - frame_size) & -16ul);
++}
++
++/*
+  * Setup the trampoline code on the stack
+  */
+ static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp)
+@@ -226,6 +253,19 @@
+ }
  
-       for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
--              if ((*pData = ORC_RD(hcsp->HCS_Base, ORC_HSTUS)) & HDI)
-+              if ((*data = inb(host->base + ORC_HSTUS)) & HDI)
-                       return 1;       /* Wait HDI set */
--              waitForPause(100);      /* wait 100ms before try again  */
-+              mdelay(100);    /* wait 100ms before try again  */
-       }
+ /*
++ * Restore the user process's signal mask (also used by signal32.c)
++ */
++void restore_sigmask(sigset_t *set)
++{
++      sigdelsetmask(set, ~_BLOCKABLE);
++      spin_lock_irq(&current->sighand->siglock);
++      current->blocked = *set;
++      recalc_sigpending();
++      spin_unlock_irq(&current->sighand->siglock);
++}
++
++
++/*
+  * Handle {get,set,swap}_context operations
+  */
+ int sys_swapcontext(struct ucontext __user *old_ctx,
+@@ -319,7 +359,7 @@
        return 0;
  }
  
- /***************************************************************************/
--static unsigned short get_FW_version(ORC_HCS * hcsp)
-+static unsigned short orc_read_fwrev(struct orc_host * host)
+-int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
++static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+               sigset_t *set, struct pt_regs *regs)
  {
--      UCHAR bData;
--      union {
--              unsigned short sVersion;
--              unsigned char cVersion[2];
--      } Version;
-+      u16 version;
-+      u8 data;
--      ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_VERSION);
--      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
--      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
-+      outb(ORC_CMD_VERSION, host->base + ORC_HDATA);
-+      outb(HDO, host->base + ORC_HCTRL);
-+      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
-               return 0;
--      if (waitHDIset(hcsp, &bData) == 0)      /* Wait HDI set   */
-+      if (wait_hdi_set(host, &data) == 0)     /* Wait HDI set   */
-               return 0;
--      Version.cVersion[0] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
--      ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);      /* Clear HDI            */
-+      version = inb(host->base + ORC_HDATA);
-+      outb(data, host->base + ORC_HSTUS);     /* Clear HDI            */
--      if (waitHDIset(hcsp, &bData) == 0)      /* Wait HDI set   */
-+      if (wait_hdi_set(host, &data) == 0)     /* Wait HDI set   */
-               return 0;
--      Version.cVersion[1] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
--      ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);      /* Clear HDI            */
-+      version |= inb(host->base + ORC_HDATA) << 8;
-+      outb(data, host->base + ORC_HSTUS);     /* Clear HDI            */
--      return (Version.sVersion);
-+      return version;
- }
+       /* Handler is *really* a pointer to the function descriptor for
+@@ -333,7 +373,8 @@
+       long err = 0;
  
- /***************************************************************************/
--static UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value)
-+static u8 orc_nv_write(struct orc_host * host, unsigned char address, unsigned char value)
- {
--      ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_SET_NVM);    /* Write command */
--      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
--      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
-+      outb(ORC_CMD_SET_NVM, host->base + ORC_HDATA);  /* Write command */
-+      outb(HDO, host->base + ORC_HCTRL);
-+      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
-               return 0;
+       frame = get_sigframe(ka, regs, sizeof(*frame));
+-      if (unlikely(frame == NULL))
++
++      if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+               goto badframe;
  
--      ORC_WR(hcsp->HCS_Base + ORC_HDATA, address);    /* Write address */
--      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
--      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
-+      outb(address, host->base + ORC_HDATA);  /* Write address */
-+      outb(HDO, host->base + ORC_HCTRL);
-+      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
-               return 0;
+       err |= __put_user(&frame->info, &frame->pinfo);
+@@ -370,7 +411,7 @@
+       funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;
  
--      ORC_WR(hcsp->HCS_Base + ORC_HDATA, value);      /* Write value  */
--      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
--      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
-+      outb(value, host->base + ORC_HDATA);    /* Write value  */
-+      outb(HDO, host->base + ORC_HCTRL);
-+      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
-               return 0;
+       /* Allocate a dummy caller frame for the signal handler. */
+-      newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
++      newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE;
+       err |= put_user(regs->gpr[1], (unsigned long __user *)newsp);
  
-       return 1;
+       /* Set up "regs" so we "return" to the signal handler. */
+@@ -401,3 +442,134 @@
+       force_sigsegv(signr, current);
+       return 0;
+ }
++
++
++/*
++ * OK, we're invoking a handler
++ */
++static int handle_signal(unsigned long sig, struct k_sigaction *ka,
++                       siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
++{
++      int ret;
++
++      /* Set up Signal Frame */
++      ret = setup_rt_frame(sig, ka, info, oldset, regs);
++
++      if (ret) {
++              spin_lock_irq(&current->sighand->siglock);
++              sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
++              if (!(ka->sa.sa_flags & SA_NODEFER))
++                      sigaddset(&current->blocked,sig);
++              recalc_sigpending();
++              spin_unlock_irq(&current->sighand->siglock);
++      }
++
++      return ret;
++}
++
++static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
++{
++      switch ((int)regs->result) {
++      case -ERESTART_RESTARTBLOCK:
++      case -ERESTARTNOHAND:
++              /* ERESTARTNOHAND means that the syscall should only be
++               * restarted if there was no handler for the signal, and since
++               * we only get here if there is a handler, we dont restart.
++               */
++              regs->result = -EINTR;
++              regs->gpr[3] = EINTR;
++              regs->ccr |= 0x10000000;
++              break;
++      case -ERESTARTSYS:
++              /* ERESTARTSYS means to restart the syscall if there is no
++               * handler or the handler was registered with SA_RESTART
++               */
++              if (!(ka->sa.sa_flags & SA_RESTART)) {
++                      regs->result = -EINTR;
++                      regs->gpr[3] = EINTR;
++                      regs->ccr |= 0x10000000;
++                      break;
++              }
++              /* fallthrough */
++      case -ERESTARTNOINTR:
++              /* ERESTARTNOINTR means that the syscall should be
++               * called again after the signal handler returns.
++               */
++              regs->gpr[3] = regs->orig_gpr3;
++              regs->nip -= 4;
++              regs->result = 0;
++              break;
++      }
++}
++
++/*
++ * Note that 'init' is a special process: it doesn't get signals it doesn't
++ * want to handle. Thus you cannot kill init even with a SIGKILL even by
++ * mistake.
++ */
++int do_signal(sigset_t *oldset, struct pt_regs *regs)
++{
++      siginfo_t info;
++      int signr;
++      struct k_sigaction ka;
++
++      /*
++       * If the current thread is 32 bit - invoke the
++       * 32 bit signal handling code
++       */
++      if (test_thread_flag(TIF_32BIT))
++              return do_signal32(oldset, regs);
++
++      if (test_thread_flag(TIF_RESTORE_SIGMASK))
++              oldset = &current->saved_sigmask;
++      else if (!oldset)
++              oldset = &current->blocked;
++
++      signr = get_signal_to_deliver(&info, &ka, regs, NULL);
++      if (signr > 0) {
++              int ret;
++
++              /* Whee!  Actually deliver the signal.  */
++              if (TRAP(regs) == 0x0C00)
++                      syscall_restart(regs, &ka);
++
++              /*
++               * Reenable the DABR before delivering the signal to
++               * user space. The DABR will have been cleared if it
++               * triggered inside the kernel.
++               */
++              if (current->thread.dabr)
++                      set_dabr(current->thread.dabr);
++
++              ret = handle_signal(signr, &ka, &info, oldset, regs);
++
++              /* If a signal was successfully delivered, the saved sigmask is in
++                 its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
++              if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
++                      clear_thread_flag(TIF_RESTORE_SIGMASK);
++
++              return ret;
++      }
++
++      if (TRAP(regs) == 0x0C00) {     /* System Call! */
++              if ((int)regs->result == -ERESTARTNOHAND ||
++                  (int)regs->result == -ERESTARTSYS ||
++                  (int)regs->result == -ERESTARTNOINTR) {
++                      regs->gpr[3] = regs->orig_gpr3;
++                      regs->nip -= 4; /* Back up & retry system call */
++                      regs->result = 0;
++              } else if ((int)regs->result == -ERESTART_RESTARTBLOCK) {
++                      regs->gpr[0] = __NR_restart_syscall;
++                      regs->nip -= 4;
++                      regs->result = 0;
++              }
++      }
++      /* No signal to deliver -- put the saved sigmask back */
++      if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
++              clear_thread_flag(TIF_RESTORE_SIGMASK);
++              sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
++      }
++
++      return 0;
++}
++EXPORT_SYMBOL(do_signal);
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/sys_ppc32.c linux-2.6.22-570/arch/powerpc/kernel/sys_ppc32.c
+--- linux-2.6.22-590/arch/powerpc/kernel/sys_ppc32.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/sys_ppc32.c   2008-01-23 19:16:03.000000000 -0500
+@@ -773,13 +773,6 @@
+       return sys_truncate(path, (high << 32) | low);
  }
  
- /***************************************************************************/
--static UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn)
-+static u8 orc_nv_read(struct orc_host * host, u8 address, u8 *ptr)
- {
--      unsigned char bData;
-+      unsigned char data;
--      ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_GET_NVM);    /* Write command */
--      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
--      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
-+      outb(ORC_CMD_GET_NVM, host->base + ORC_HDATA);  /* Write command */
-+      outb(HDO, host->base + ORC_HCTRL);
-+      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
-               return 0;
+-asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo,
+-                                   u32 lenhi, u32 lenlo)
+-{
+-      return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
+-                           ((loff_t)lenhi << 32) | lenlo);
+-}
+-
+ asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long high,
+                                unsigned long low)
+ {
+diff -Nurb linux-2.6.22-590/arch/powerpc/kernel/vdso.c linux-2.6.22-570/arch/powerpc/kernel/vdso.c
+--- linux-2.6.22-590/arch/powerpc/kernel/vdso.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/kernel/vdso.c        2008-01-23 19:16:03.000000000 -0500
+@@ -671,7 +671,7 @@
+       /*
+        * Fill up the "systemcfg" stuff for backward compatiblity
+        */
+-      strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
++      strcpy(vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
+       vdso_data->version.major = SYSTEMCFG_MAJOR;
+       vdso_data->version.minor = SYSTEMCFG_MINOR;
+       vdso_data->processor = mfspr(SPRN_PVR);
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/44x_mmu.c linux-2.6.22-570/arch/powerpc/mm/44x_mmu.c
+--- linux-2.6.22-590/arch/powerpc/mm/44x_mmu.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/44x_mmu.c 2007-07-08 19:32:17.000000000 -0400
+@@ -12,6 +12,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  *  Derived from "arch/i386/mm/init.c"
+  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/4xx_mmu.c linux-2.6.22-570/arch/powerpc/mm/4xx_mmu.c
+--- linux-2.6.22-590/arch/powerpc/mm/4xx_mmu.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/4xx_mmu.c 2007-07-08 19:32:17.000000000 -0400
+@@ -9,6 +9,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  *  Derived from "arch/i386/mm/init.c"
+  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/Makefile linux-2.6.22-570/arch/powerpc/mm/Makefile
+--- linux-2.6.22-590/arch/powerpc/mm/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/Makefile  2007-07-08 19:32:17.000000000 -0400
+@@ -11,7 +11,8 @@
+ hash-$(CONFIG_PPC_NATIVE)     := hash_native_64.o
+ obj-$(CONFIG_PPC64)           += init_64.o pgtable_64.o mmu_context_64.o \
+                                  hash_utils_64.o hash_low_64.o tlb_64.o \
+-                                 slb_low.o slb.o stab.o mmap.o $(hash-y)
++                                 slb_low.o slb.o stab.o mmap.o imalloc.o \
++                                 $(hash-y)
+ obj-$(CONFIG_PPC_STD_MMU_32)  += ppc_mmu_32.o hash_low_32.o tlb_32.o
+ obj-$(CONFIG_40x)             += 4xx_mmu.o
+ obj-$(CONFIG_44x)             += 44x_mmu.o
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/fault.c linux-2.6.22-570/arch/powerpc/mm/fault.c
+--- linux-2.6.22-590/arch/powerpc/mm/fault.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/fault.c   2008-01-23 19:16:03.000000000 -0500
+@@ -29,7 +29,6 @@
+ #include <linux/module.h>
+ #include <linux/kprobes.h>
+ #include <linux/kdebug.h>
+-#include <linux/kgdb.h>
  
--      ORC_WR(hcsp->HCS_Base + ORC_HDATA, address);    /* Write address */
--      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
--      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
-+      outb(address, host->base + ORC_HDATA);  /* Write address */
-+      outb(HDO, host->base + ORC_HCTRL);
-+      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
-               return 0;
+ #include <asm/page.h>
+ #include <asm/pgtable.h>
+@@ -382,7 +381,7 @@
+       printk("VM: killing process %s(%d:#%u)\n",
+               current->comm, current->pid, current->xid);
+       if (user_mode(regs))
+-              do_group_exit(SIGKILL);
++              do_exit(SIGKILL);
+       return SIGKILL;
  
--      if (waitHDIset(hcsp, &bData) == 0)      /* Wait HDI set   */
-+      if (wait_hdi_set(host, &data) == 0)     /* Wait HDI set   */
-               return 0;
--      *pDataIn = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
--      ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);      /* Clear HDI    */
-+      *ptr = inb(host->base + ORC_HDATA);
-+      outb(data, host->base + ORC_HSTUS);     /* Clear HDI    */
+ do_sigbus:
+@@ -413,13 +412,6 @@
+               return;
+       }
  
-       return 1;
-+
+-#ifdef CONFIG_KGDB
+-      if (atomic_read(&debugger_active) && kgdb_may_fault)
+-              /* Restore our previous state. */
+-              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+-              /* Not reached. */
+-#endif
+-
+       /* kernel has accessed a bad area */
+       switch (regs->trap) {
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/fsl_booke_mmu.c linux-2.6.22-570/arch/powerpc/mm/fsl_booke_mmu.c
+--- linux-2.6.22-590/arch/powerpc/mm/fsl_booke_mmu.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/fsl_booke_mmu.c   2007-07-08 19:32:17.000000000 -0400
+@@ -14,6 +14,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  *  Derived from "arch/i386/mm/init.c"
+  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/hash_native_64.c linux-2.6.22-570/arch/powerpc/mm/hash_native_64.c
+--- linux-2.6.22-590/arch/powerpc/mm/hash_native_64.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/hash_native_64.c  2007-07-08 19:32:17.000000000 -0400
+@@ -104,7 +104,7 @@
+               spin_unlock(&native_tlbie_lock);
  }
  
--/***************************************************************************/
--static void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
-+/**
-+ *    orc_exec_sb             -       Queue an SCB with the HA
-+ *    @host: host adapter the SCB belongs to
-+ *    @scb: SCB to queue for execution
-+ */
-+
-+static void orc_exec_scb(struct orc_host * host, struct orc_scb * scb)
+-static inline void native_lock_hpte(struct hash_pte *hptep)
++static inline void native_lock_hpte(hpte_t *hptep)
  {
--      scbp->SCB_Status = ORCSCB_POST;
--      ORC_WR(hcsp->HCS_Base + ORC_PQUEUE, scbp->SCB_ScbIdx);
--      return;
-+      scb->status = ORCSCB_POST;
-+      outb(scb->scbidx, host->base + ORC_PQUEUE);
+       unsigned long *word = &hptep->v;
+@@ -116,7 +116,7 @@
+       }
  }
  
+-static inline void native_unlock_hpte(struct hash_pte *hptep)
++static inline void native_unlock_hpte(hpte_t *hptep)
+ {
+       unsigned long *word = &hptep->v;
  
--/***********************************************************************
-- Read SCSI H/A configuration parameters from serial EEPROM
--************************************************************************/
--static int se2_rd_all(ORC_HCS * hcsp)
-+/**
-+ *    se2_rd_all      -       read SCSI parameters from EEPROM
-+ *    @host: Host whose EEPROM is being loaded
-+ *
-+ *    Read SCSI H/A configuration parameters from serial EEPROM
-+ */
-+
-+static int se2_rd_all(struct orc_host * host)
+@@ -128,7 +128,7 @@
+                       unsigned long pa, unsigned long rflags,
+                       unsigned long vflags, int psize)
  {
+-      struct hash_pte *hptep = htab_address + hpte_group;
++      hpte_t *hptep = htab_address + hpte_group;
+       unsigned long hpte_v, hpte_r;
        int i;
--      UCHAR *np, chksum = 0;
-+      u8 *np, chksum = 0;
  
--      np = (UCHAR *) nvramp;
-+      np = (u8 *) nvramp;
-       for (i = 0; i < 64; i++, np++) {        /* <01> */
--              if (get_NVRAM(hcsp, (unsigned char) i, np) == 0)
-+              if (orc_nv_read(host, (u8) i, np) == 0)
-                       return -1;
--//      *np++ = get_NVRAM(hcsp, (unsigned char ) i);
-       }
+@@ -177,7 +177,7 @@
  
--/*------ Is ckecksum ok ? ------*/
--      np = (UCHAR *) nvramp;
-+      /*------ Is ckecksum ok ? ------*/
-+      np = (u8 *) nvramp;
-       for (i = 0; i < 63; i++)
-               chksum += *np++;
+ static long native_hpte_remove(unsigned long hpte_group)
+ {
+-      struct hash_pte *hptep;
++      hpte_t *hptep;
+       int i;
+       int slot_offset;
+       unsigned long hpte_v;
+@@ -217,7 +217,7 @@
+ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
+                                unsigned long va, int psize, int local)
+ {
+-      struct hash_pte *hptep = htab_address + slot;
++      hpte_t *hptep = htab_address + slot;
+       unsigned long hpte_v, want_v;
+       int ret = 0;
  
--      if (nvramp->CheckSum != (UCHAR) chksum)
-+      if (nvramp->CheckSum != (u8) chksum)
-               return -1;
-       return 1;
- }
+@@ -233,14 +233,15 @@
+       /* Even if we miss, we need to invalidate the TLB */
+       if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) {
+               DBG_LOW(" -> miss\n");
++              native_unlock_hpte(hptep);
+               ret = -1;
+       } else {
+               DBG_LOW(" -> hit\n");
+               /* Update the HPTE */
+               hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
+                       (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C));
+-      }
+       native_unlock_hpte(hptep);
++      }
  
--/************************************************************************
-- Update SCSI H/A configuration parameters from serial EEPROM
--*************************************************************************/
--static void se2_update_all(ORC_HCS * hcsp)
-+/**
-+ *    se2_update_all          -       update the EEPROM
-+ *    @host: Host whose EEPROM is being updated
-+ *
-+ *    Update changed bytes in the EEPROM image.
-+ */
-+
-+static void se2_update_all(struct orc_host * host)
- {                             /* setup default pattern  */
-       int i;
--      UCHAR *np, *np1, chksum = 0;
-+      u8 *np, *np1, chksum = 0;
+       /* Ensure it is out of the tlb too. */
+       tlbie(va, psize, local);
+@@ -250,7 +251,7 @@
  
-       /* Calculate checksum first   */
--      np = (UCHAR *) dftNvRam;
-+      np = (u8 *) default_nvram;
-       for (i = 0; i < 63; i++)
-               chksum += *np++;
-       *np = chksum;
+ static long native_hpte_find(unsigned long va, int psize)
+ {
+-      struct hash_pte *hptep;
++      hpte_t *hptep;
+       unsigned long hash;
+       unsigned long i, j;
+       long slot;
+@@ -293,7 +294,7 @@
+ {
+       unsigned long vsid, va;
+       long slot;
+-      struct hash_pte *hptep;
++      hpte_t *hptep;
  
--      np = (UCHAR *) dftNvRam;
--      np1 = (UCHAR *) nvramp;
-+      np = (u8 *) default_nvram;
-+      np1 = (u8 *) nvramp;
-       for (i = 0; i < 64; i++, np++, np1++) {
--              if (*np != *np1) {
--                      set_NVRAM(hcsp, (unsigned char) i, *np);
--              }
-+              if (*np != *np1)
-+                      orc_nv_write(host, (u8) i, *np);
-       }
--      return;
- }
+       vsid = get_kernel_vsid(ea);
+       va = (vsid << 28) | (ea & 0x0fffffff);
+@@ -314,7 +315,7 @@
+ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
+                                  int psize, int local)
+ {
+-      struct hash_pte *hptep = htab_address + slot;
++      hpte_t *hptep = htab_address + slot;
+       unsigned long hpte_v;
+       unsigned long want_v;
+       unsigned long flags;
+@@ -344,7 +345,7 @@
+ #define LP_BITS               8
+ #define LP_MASK(i)    ((0xFF >> (i)) << LP_SHIFT)
  
--/*************************************************************************
-- Function name  : read_eeprom
--**************************************************************************/
--static void read_eeprom(ORC_HCS * hcsp)
--{
--      if (se2_rd_all(hcsp) != 1) {
--              se2_update_all(hcsp);   /* setup default pattern        */
--              se2_rd_all(hcsp);       /* load again                   */
-+/**
-+ *    read_eeprom             -       load EEPROM
-+ *    @host: Host EEPROM to read
-+ *
-+ *    Read the EEPROM for a given host. If it is invalid or fails
-+ *    the restore the defaults and use them.
+-static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
++static void hpte_decode(hpte_t *hpte, unsigned long slot,
+                       int *psize, unsigned long *va)
+ {
+       unsigned long hpte_r = hpte->r;
+@@ -414,7 +415,7 @@
+ static void native_hpte_clear(void)
+ {
+       unsigned long slot, slots, flags;
+-      struct hash_pte *hptep = htab_address;
++      hpte_t *hptep = htab_address;
+       unsigned long hpte_v, va;
+       unsigned long pteg_count;
+       int psize;
+@@ -461,7 +462,7 @@
+ static void native_flush_hash_range(unsigned long number, int local)
+ {
+       unsigned long va, hash, index, hidx, shift, slot;
+-      struct hash_pte *hptep;
++      hpte_t *hptep;
+       unsigned long hpte_v;
+       unsigned long want_v;
+       unsigned long flags;
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/hash_utils_64.c linux-2.6.22-570/arch/powerpc/mm/hash_utils_64.c
+--- linux-2.6.22-590/arch/powerpc/mm/hash_utils_64.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/hash_utils_64.c   2007-07-08 19:32:17.000000000 -0400
+@@ -87,7 +87,7 @@
+ static unsigned long _SDR1;
+ struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
+-struct hash_pte *htab_address;
++hpte_t *htab_address;
+ unsigned long htab_size_bytes;
+ unsigned long htab_hash_mask;
+ int mmu_linear_psize = MMU_PAGE_4K;
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/imalloc.c linux-2.6.22-570/arch/powerpc/mm/imalloc.c
+--- linux-2.6.22-590/arch/powerpc/mm/imalloc.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/imalloc.c 2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,313 @@
++/*
++ * c 2001 PPC 64 Team, IBM Corp
++ * 
++ *      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.
 + */
 +
-+static void read_eeprom(struct orc_host * host)
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++
++#include <asm/uaccess.h>
++#include <asm/pgalloc.h>
++#include <asm/pgtable.h>
++#include <linux/mutex.h>
++#include <asm/cacheflush.h>
++
++#include "mmu_decl.h"
++
++static DEFINE_MUTEX(imlist_mutex);
++struct vm_struct * imlist = NULL;
++
++static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
++{
++      unsigned long addr;
++      struct vm_struct **p, *tmp;
++
++      addr = ioremap_bot;
++      for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
++              if (size + addr < (unsigned long) tmp->addr)
++                      break;
++              if ((unsigned long)tmp->addr >= ioremap_bot)
++                      addr = tmp->size + (unsigned long) tmp->addr;
++              if (addr >= IMALLOC_END-size)
++                      return 1;
++      }
++      *im_addr = addr;
++
++      return 0;
++}
++
++/* Return whether the region described by v_addr and size is a subset
++ * of the region described by parent
++ */
++static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
++                      struct vm_struct *parent)
 +{
-+      if (se2_rd_all(host) != 1) {
-+              se2_update_all(host);   /* setup default pattern        */
-+              se2_rd_all(host);       /* load again                   */
-       }
- }
--/***************************************************************************/
--static UCHAR load_FW(ORC_HCS * hcsp)
-+/**
-+ *    orc_load_firmware       -       initialise firmware
-+ *    @host: Host to set up
-+ *
-+ *    Load the firmware from the EEPROM into controller SRAM. This
-+ *    is basically a 4K block copy and then a 4K block read to check
-+ *    correctness. The rest is convulted by the indirect interfaces
-+ *    in the hardware
++      return (int) (v_addr >= (unsigned long) parent->addr &&
++                    v_addr < (unsigned long) parent->addr + parent->size &&
++                    size < parent->size);
++}
++
++/* Return whether the region described by v_addr and size is a superset
++ * of the region described by child
 + */
++static int im_region_is_superset(unsigned long v_addr, unsigned long size,
++              struct vm_struct *child)
++{
++      struct vm_struct parent;
 +
-+static u8 orc_load_firmware(struct orc_host * host)
- {
--      U32 dData;
--      USHORT wBIOSAddress;
--      USHORT i;
--      UCHAR *pData, bData;
--
--
--      bData = ORC_RD(hcsp->HCS_Base, ORC_GCFG);
--      ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData | EEPRG);       /* Enable EEPROM programming */
--      ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, 0x00);
--      ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x00);
--      if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0x55) {
--              ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);       /* Disable EEPROM programming */
--              return 0;
--      }
--      ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x01);
--      if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0xAA) {
--              ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);       /* Disable EEPROM programming */
--              return 0;
--      }
--      ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD);       /* Enable SRAM programming */
--      pData = (UCHAR *) & dData;
--      dData = 0;              /* Initial FW address to 0 */
--      ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x10);
--      *pData = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);         /* Read from BIOS */
--      ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x11);
--      *(pData + 1) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);   /* Read from BIOS */
--      ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x12);
--      *(pData + 2) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);   /* Read from BIOS */
--      ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, *(pData + 2));
--      ORC_WRLONG(hcsp->HCS_Base + ORC_FWBASEADR, dData);      /* Write FW address */
-+      u32 data32;
-+      u16 bios_addr;
-+      u16 i;
-+      u8 *data32_ptr, data;
-+
-+
-+      /* Set up the EEPROM for access */
--      wBIOSAddress = (USHORT) dData;  /* FW code locate at BIOS address + ? */
--      for (i = 0, pData = (UCHAR *) & dData;  /* Download the code    */
-+      data = inb(host->base + ORC_GCFG);
-+      outb(data | EEPRG, host->base + ORC_GCFG);      /* Enable EEPROM programming */
-+      outb(0x00, host->base + ORC_EBIOSADR2);
-+      outw(0x0000, host->base + ORC_EBIOSADR0);
-+      if (inb(host->base + ORC_EBIOSDATA) != 0x55) {
-+              outb(data, host->base + ORC_GCFG);      /* Disable EEPROM programming */
++      parent.addr = (void *) v_addr;
++      parent.size = size;
++
++      return im_region_is_subset((unsigned long) child->addr, child->size,
++                      &parent);
++}
++
++/* Return whether the region described by v_addr and size overlaps
++ * the region described by vm.  Overlapping regions meet the
++ * following conditions:
++ * 1) The regions share some part of the address space
++ * 2) The regions aren't identical
++ * 3) Neither region is a subset of the other
++ */
++static int im_region_overlaps(unsigned long v_addr, unsigned long size,
++                   struct vm_struct *vm)
++{
++      if (im_region_is_superset(v_addr, size, vm))
 +              return 0;
++
++      return (v_addr + size > (unsigned long) vm->addr + vm->size &&
++              v_addr < (unsigned long) vm->addr + vm->size) ||
++             (v_addr < (unsigned long) vm->addr &&
++              v_addr + size > (unsigned long) vm->addr);
++}
++
++/* Determine imalloc status of region described by v_addr and size.
++ * Can return one of the following:
++ * IM_REGION_UNUSED   -  Entire region is unallocated in imalloc space.
++ * IM_REGION_SUBSET -    Region is a subset of a region that is already
++ *                     allocated in imalloc space.
++ *                     vm will be assigned to a ptr to the parent region.
++ * IM_REGION_EXISTS -    Exact region already allocated in imalloc space.
++ *                       vm will be assigned to a ptr to the existing imlist
++ *                       member.
++ * IM_REGION_OVERLAPS -  Region overlaps an allocated region in imalloc space.
++ * IM_REGION_SUPERSET -  Region is a superset of a region that is already
++ *                       allocated in imalloc space.
++ */
++static int im_region_status(unsigned long v_addr, unsigned long size,
++                  struct vm_struct **vm)
++{
++      struct vm_struct *tmp;
++
++      for (tmp = imlist; tmp; tmp = tmp->next)
++              if (v_addr < (unsigned long) tmp->addr + tmp->size)
++                      break;
++
++      *vm = NULL;
++      if (tmp) {
++              if (im_region_overlaps(v_addr, size, tmp))
++                      return IM_REGION_OVERLAP;
++
++              *vm = tmp;
++              if (im_region_is_subset(v_addr, size, tmp)) {
++                      /* Return with tmp pointing to superset */
++                      return IM_REGION_SUBSET;
++              }
++              if (im_region_is_superset(v_addr, size, tmp)) {
++                      /* Return with tmp pointing to first subset */
++                      return IM_REGION_SUPERSET;
++              }
++              else if (v_addr == (unsigned long) tmp->addr &&
++                       size == tmp->size) {
++                      /* Return with tmp pointing to exact region */
++                      return IM_REGION_EXISTS;
++              }
 +      }
-+      outw(0x0001, host->base + ORC_EBIOSADR0);
-+      if (inb(host->base + ORC_EBIOSDATA) != 0xAA) {
-+              outb(data, host->base + ORC_GCFG);      /* Disable EEPROM programming */
-+              return 0;
++
++      return IM_REGION_UNUSED;
++}
++
++static struct vm_struct * split_im_region(unsigned long v_addr, 
++              unsigned long size, struct vm_struct *parent)
++{
++      struct vm_struct *vm1 = NULL;
++      struct vm_struct *vm2 = NULL;
++      struct vm_struct *new_vm = NULL;
++      
++      vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL);
++      if (vm1 == NULL) {
++              printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
++              return NULL;
 +      }
 +
-+      outb(PRGMRST | DOWNLOAD, host->base + ORC_RISCCTL);     /* Enable SRAM programming */
-+      data32_ptr = (u8 *) & data32;
-+      data32 = 0;             /* Initial FW address to 0 */
-+      outw(0x0010, host->base + ORC_EBIOSADR0);
-+      *data32_ptr = inb(host->base + ORC_EBIOSDATA);          /* Read from BIOS */
-+      outw(0x0011, host->base + ORC_EBIOSADR0);
-+      *(data32_ptr + 1) = inb(host->base + ORC_EBIOSDATA);    /* Read from BIOS */
-+      outw(0x0012, host->base + ORC_EBIOSADR0);
-+      *(data32_ptr + 2) = inb(host->base + ORC_EBIOSDATA);    /* Read from BIOS */
-+      outw(*(data32_ptr + 2), host->base + ORC_EBIOSADR2);
-+      outl(data32, host->base + ORC_FWBASEADR);               /* Write FW address */
++      if (v_addr == (unsigned long) parent->addr) {
++              /* Use existing parent vm_struct to represent child, allocate
++               * new one for the remainder of parent range
++               */
++              vm1->size = parent->size - size;
++              vm1->addr = (void *) (v_addr + size);
++              vm1->next = parent->next;
++
++              parent->size = size;
++              parent->next = vm1;
++              new_vm = parent;
++      } else if (v_addr + size == (unsigned long) parent->addr + 
++                      parent->size) {
++              /* Allocate new vm_struct to represent child, use existing
++               * parent one for remainder of parent range
++               */
++              vm1->size = size;
++              vm1->addr = (void *) v_addr;
++              vm1->next = parent->next;
++              new_vm = vm1;
 +
-+      /* Copy the code from the BIOS to the SRAM */
++              parent->size -= size;
++              parent->next = vm1;
++      } else {
++              /* Allocate two new vm_structs for the new child and 
++               * uppermost remainder, and use existing parent one for the
++               * lower remainder of parent range
++               */
++              vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL);
++              if (vm2 == NULL) {
++                      printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
++                      kfree(vm1);
++                      return NULL;
++              }
 +
-+      bios_addr = (u16) data32;       /* FW code locate at BIOS address + ? */
-+      for (i = 0, data32_ptr = (u8 *) & data32;       /* Download the code    */
-            i < 0x1000;        /* Firmware code size = 4K      */
--           i++, wBIOSAddress++) {
--              ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
--              *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);       /* Read from BIOS */
-+           i++, bios_addr++) {
-+              outw(bios_addr, host->base + ORC_EBIOSADR0);
-+              *data32_ptr++ = inb(host->base + ORC_EBIOSDATA);        /* Read from BIOS */
-               if ((i % 4) == 3) {
--                      ORC_WRLONG(hcsp->HCS_Base + ORC_RISCRAM, dData);        /* Write every 4 bytes */
--                      pData = (UCHAR *) & dData;
-+                      outl(data32, host->base + ORC_RISCRAM); /* Write every 4 bytes */
-+                      data32_ptr = (u8 *) & data32;
-               }
-       }
--      ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD);       /* Reset program count 0 */
--      wBIOSAddress -= 0x1000; /* Reset the BIOS adddress      */
--      for (i = 0, pData = (UCHAR *) & dData;  /* Check the code       */
-+      /* Go back and check they match */
++              vm1->size = size;
++              vm1->addr = (void *) v_addr;
++              vm1->next = vm2;
++              new_vm = vm1;
 +
-+      outb(PRGMRST | DOWNLOAD, host->base + ORC_RISCCTL);     /* Reset program count 0 */
-+      bios_addr -= 0x1000;    /* Reset the BIOS adddress      */
-+      for (i = 0, data32_ptr = (u8 *) & data32;       /* Check the code       */
-            i < 0x1000;        /* Firmware code size = 4K      */
--           i++, wBIOSAddress++) {
--              ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
--              *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);       /* Read from BIOS */
-+           i++, bios_addr++) {
-+              outw(bios_addr, host->base + ORC_EBIOSADR0);
-+              *data32_ptr++ = inb(host->base + ORC_EBIOSDATA);        /* Read from BIOS */
-               if ((i % 4) == 3) {
--                      if (ORC_RDLONG(hcsp->HCS_Base, ORC_RISCRAM) != dData) {
--                              ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST);  /* Reset program to 0 */
--                              ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);       /*Disable EEPROM programming */
-+                      if (inl(host->base + ORC_RISCRAM) != data32) {
-+                              outb(PRGMRST, host->base + ORC_RISCCTL);        /* Reset program to 0 */
-+                              outb(data, host->base + ORC_GCFG);      /*Disable EEPROM programming */
-                               return 0;
-                       }
--                      pData = (UCHAR *) & dData;
-+                      data32_ptr = (u8 *) & data32;
-               }
-       }
--      ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST);  /* Reset program to 0   */
--      ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);       /* Disable EEPROM programming */
++              vm2->size = ((unsigned long) parent->addr + parent->size) - 
++                              (v_addr + size);
++              vm2->addr = (void *) v_addr + size;
++              vm2->next = parent->next;
 +
-+      /* Success */
-+      outb(PRGMRST, host->base + ORC_RISCCTL);        /* Reset program to 0   */
-+      outb(data, host->base + ORC_GCFG);      /* Disable EEPROM programming */
-       return 1;
- }
- /***************************************************************************/
--static void setup_SCBs(ORC_HCS * hcsp)
-+static void setup_SCBs(struct orc_host * host)
- {
--      ORC_SCB *pVirScb;
-+      struct orc_scb *scb;
-       int i;
--      ESCB *pVirEscb;
--      dma_addr_t pPhysEscb;
-+      struct orc_extended_scb *escb;
-+      dma_addr_t escb_phys;
--      /* Setup SCB HCS_Base and SCB Size registers */
--      ORC_WR(hcsp->HCS_Base + ORC_SCBSIZE, ORC_MAXQUEUE);     /* Total number of SCBs */
--      /* SCB HCS_Base address 0      */
--      ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE0, hcsp->HCS_physScbArray);
--      /* SCB HCS_Base address 1      */
--      ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE1, hcsp->HCS_physScbArray);
-+      /* Setup SCB base and SCB Size registers */
-+      outb(ORC_MAXQUEUE, host->base + ORC_SCBSIZE);   /* Total number of SCBs */
-+      /* SCB base address 0      */
-+      outl(host->scb_phys, host->base + ORC_SCBBASE0);
-+      /* SCB base address 1      */
-+      outl(host->scb_phys, host->base + ORC_SCBBASE1);
-       /* setup scatter list address with one buffer */
--      pVirScb = hcsp->HCS_virScbArray;
--      pVirEscb = hcsp->HCS_virEscbArray;
-+      scb = host->scb_virt;
-+      escb = host->escb_virt;
-       for (i = 0; i < ORC_MAXQUEUE; i++) {
--              pPhysEscb = (hcsp->HCS_physEscbArray + (sizeof(ESCB) * i));
--              pVirScb->SCB_SGPAddr = (U32) pPhysEscb;
--              pVirScb->SCB_SensePAddr = (U32) pPhysEscb;
--              pVirScb->SCB_EScb = pVirEscb;
--              pVirScb->SCB_ScbIdx = i;
--              pVirScb++;
--              pVirEscb++;
-+              escb_phys = (host->escb_phys + (sizeof(struct orc_extended_scb) * i));
-+              scb->sg_addr = (u32) escb_phys;
-+              scb->sense_addr = (u32) escb_phys;
-+              scb->escb = escb;
-+              scb->scbidx = i;
-+              scb++;
-+              escb++;
-       }
--
--      return;
- }
--/***************************************************************************/
--static void initAFlag(ORC_HCS * hcsp)
-+/**
-+ *    init_alloc_map          -       initialise allocation map
-+ *    @host: host map to configure
-+ *
-+ *    Initialise the allocation maps for this device. If the device
-+ *    is not quiescent the caller must hold the allocation lock
-+ */
++              parent->size = v_addr - (unsigned long) parent->addr;
++              parent->next = vm1;
++      }
 +
-+static void init_alloc_map(struct orc_host * host)
- {
--      UCHAR i, j;
-+      u8 i, j;
-       for (i = 0; i < MAX_CHANNELS; i++) {
-               for (j = 0; j < 8; j++) {
--                      hcsp->BitAllocFlag[i][j] = 0xffffffff;
-+                      host->allocation_map[i][j] = 0xffffffff;
-               }
-       }
- }
--/***************************************************************************/
--static int init_orchid(ORC_HCS * hcsp)
-+/**
-+ *    init_orchid             -       initialise the host adapter
-+ *    @host:host adapter to initialise
-+ *
-+ *    Initialise the controller and if neccessary load the firmware.
-+ *
-+ *    Returns -1 if the initialisation fails.
-+ */
++      return new_vm;
++}
 +
-+static int init_orchid(struct orc_host * host)
- {
--      UBYTE *readBytep;
--      USHORT revision;
--      UCHAR i;
--
--      initAFlag(hcsp);
--      ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFF);       /* Disable all interrupt        */
--      if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) {       /* Orchid is ready              */
--              revision = get_FW_version(hcsp);
-+      u8 *ptr;
-+      u16 revision;
-+      u8 i;
++static struct vm_struct * __add_new_im_area(unsigned long req_addr, 
++                                          unsigned long size)
++{
++      struct vm_struct **p, *tmp, *area;
++              
++      for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
++              if (req_addr + size <= (unsigned long)tmp->addr)
++                      break;
++      }
++      
++      area = kmalloc(sizeof(*area), GFP_KERNEL);
++      if (!area)
++              return NULL;
++      area->flags = 0;
++      area->addr = (void *)req_addr;
++      area->size = size;
++      area->next = *p;
++      *p = area;
 +
-+      init_alloc_map(host);
-+      outb(0xFF, host->base + ORC_GIMSK);     /* Disable all interrupts */
++      return area;
++}
 +
-+      if (inb(host->base + ORC_HSTUS) & RREADY) {     /* Orchid is ready */
-+              revision = orc_read_fwrev(host);
-               if (revision == 0xFFFF) {
--                      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST);     /* Reset Host Adapter   */
--                      if (waitChipReady(hcsp) == 0)
--                              return (-1);
--                      load_FW(hcsp);  /* Download FW                  */
--                      setup_SCBs(hcsp);       /* Setup SCB HCS_Base and SCB Size registers */
--                      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, 0);  /* clear HOSTSTOP       */
--                      if (waitFWReady(hcsp) == 0)
--                              return (-1);
-+                      outb(DEVRST, host->base + ORC_HCTRL);   /* Reset Host Adapter   */
-+                      if (wait_chip_ready(host) == 0)
-+                              return -1;
-+                      orc_load_firmware(host);        /* Download FW                  */
-+                      setup_SCBs(host);       /* Setup SCB base and SCB Size registers */
-+                      outb(0x00, host->base + ORC_HCTRL);     /* clear HOSTSTOP       */
-+                      if (wait_firmware_ready(host) == 0)
-+                              return -1;
-                       /* Wait for firmware ready     */
-               } else {
--                      setup_SCBs(hcsp);       /* Setup SCB HCS_Base and SCB Size registers */
-+                      setup_SCBs(host);       /* Setup SCB base and SCB Size registers */
-               }
-       } else {                /* Orchid is not Ready          */
--              ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST);     /* Reset Host Adapter   */
--              if (waitChipReady(hcsp) == 0)
--                      return (-1);
--              load_FW(hcsp);  /* Download FW                  */
--              setup_SCBs(hcsp);       /* Setup SCB HCS_Base and SCB Size registers */
--              ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);        /* Do Hardware Reset &  */
-+              outb(DEVRST, host->base + ORC_HCTRL);   /* Reset Host Adapter   */
-+              if (wait_chip_ready(host) == 0)
-+                      return -1;
-+              orc_load_firmware(host);        /* Download FW                  */
-+              setup_SCBs(host);       /* Setup SCB base and SCB Size registers */
-+              outb(HDO, host->base + ORC_HCTRL);      /* Do Hardware Reset &  */
-               /*     clear HOSTSTOP  */
--              if (waitFWReady(hcsp) == 0)             /* Wait for firmware ready      */
--                      return (-1);
-+              if (wait_firmware_ready(host) == 0)             /* Wait for firmware ready      */
-+                      return -1;
-       }
--/*------------- get serial EEProm settting -------*/
-+      /* Load an EEProm copy into RAM */
-+      /* Assumes single threaded at this point */
-+      read_eeprom(host);
--      read_eeprom(hcsp);
--
--      if (nvramp->Revision != 1)
--              return (-1);
--
--      hcsp->HCS_SCSI_ID = nvramp->SCSI0Id;
--      hcsp->HCS_BIOS = nvramp->BIOSConfig1;
--      hcsp->HCS_MaxTar = MAX_TARGETS;
--      readBytep = (UCHAR *) & (nvramp->Target00Config);
--      for (i = 0; i < 16; readBytep++, i++) {
--              hcsp->TargetFlag[i] = *readBytep;
--              hcsp->MaximumTags[i] = ORC_MAXTAGS;
--      }                       /* for                          */
-+      if (nvramp->revision != 1)
-+              return -1;
--      if (nvramp->SCSI0Config & NCC_BUSRESET) {       /* Reset SCSI bus               */
--              hcsp->HCS_Flags |= HCF_SCSI_RESET;
-+      host->scsi_id = nvramp->scsi_id;
-+      host->BIOScfg = nvramp->BIOSConfig1;
-+      host->max_targets = MAX_TARGETS;
-+      ptr = (u8 *) & (nvramp->Target00Config);
-+      for (i = 0; i < 16; ptr++, i++) {
-+              host->target_flag[i] = *ptr;
-+              host->max_tags[i] = ORC_MAXTAGS;
-       }
--      ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFB);       /* enable RP FIFO interrupt     */
--      return (0);
-+
-+      if (nvramp->SCSI0Config & NCC_BUSRESET)
-+              host->flags |= HCF_SCSI_RESET;
-+      outb(0xFB, host->base + ORC_GIMSK);     /* enable RP FIFO interrupt     */
-+      return 0;
- }
--/*****************************************************************************
-- Function name  : orc_reset_scsi_bus
-- Description    : Reset registers, reset a hanging bus and
--                  kill active and disconnected commands for target w/o soft reset
-- Input          : pHCB  -       Pointer to host adapter structure
-- Output         : None.
-- Return         : pSRB  -       Pointer to SCSI request block.
--*****************************************************************************/
--static int orc_reset_scsi_bus(ORC_HCS * pHCB)
-+/**
-+ *    orc_reset_scsi_bus              -       perform bus reset
-+ *    @host: host being reset
-+ *
-+ *    Perform a full bus reset on the adapter.
-+ */
++static struct vm_struct * __im_get_area(unsigned long req_addr, 
++                                      unsigned long size,
++                                      int criteria)
++{
++      struct vm_struct *tmp;
++      int status;
 +
-+static int orc_reset_scsi_bus(struct orc_host * host)
- {                             /* I need Host Control Block Information */
--      ULONG flags;
-+      unsigned long flags;
--      spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
-+      spin_lock_irqsave(&host->allocation_lock, flags);
--      initAFlag(pHCB);
-+      init_alloc_map(host);
-       /* reset scsi bus */
--      ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST);
--      if (waitSCSIRSTdone(pHCB) == 0) {
--              spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-+      outb(SCSIRST, host->base + ORC_HCTRL);
-+      /* FIXME: We can spend up to a second with the lock held and
-+         interrupts off here */
-+      if (wait_scsi_reset_done(host) == 0) {
-+              spin_unlock_irqrestore(&host->allocation_lock, flags);
-               return FAILED;
-       } else {
--              spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-+              spin_unlock_irqrestore(&host->allocation_lock, flags);
-               return SUCCESS;
-       }
- }
--/*****************************************************************************
-- Function name  : orc_device_reset
-- Description    : Reset registers, reset a hanging bus and
--                  kill active and disconnected commands for target w/o soft reset
-- Input          : pHCB  -       Pointer to host adapter structure
-- Output         : None.
-- Return         : pSRB  -       Pointer to SCSI request block.
--*****************************************************************************/
--static int orc_device_reset(ORC_HCS * pHCB, struct scsi_cmnd *SCpnt, unsigned int target)
-+/**
-+ *    orc_device_reset        -       device reset handler
-+ *    @host: host to reset
-+ *    @cmd: command causing the reset
-+ *    @target; target device
-+ *
-+ *    Reset registers, reset a hanging bus and kill active and disconnected
-+ *    commands for target w/o soft reset
-+ */
++      status = im_region_status(req_addr, size, &tmp);
++      if ((criteria & status) == 0) {
++              return NULL;
++      }
++      
++      switch (status) {
++      case IM_REGION_UNUSED:
++              tmp = __add_new_im_area(req_addr, size);
++              break;
++      case IM_REGION_SUBSET:
++              tmp = split_im_region(req_addr, size, tmp);
++              break;
++      case IM_REGION_EXISTS:
++              /* Return requested region */
++              break;
++      case IM_REGION_SUPERSET:
++              /* Return first existing subset of requested region */
++              break;
++      default:
++              printk(KERN_ERR "%s() unexpected imalloc region status\n",
++                              __FUNCTION__);
++              tmp = NULL;
++      }
 +
-+static int orc_device_reset(struct orc_host * host, struct scsi_cmnd *cmd, unsigned int target)
- {                             /* I need Host Control Block Information */
--      ORC_SCB *pScb;
--      ESCB *pVirEscb;
--      ORC_SCB *pVirScb;
--      UCHAR i;
--      ULONG flags;
--
--      spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
--      pScb = (ORC_SCB *) NULL;
--      pVirEscb = (ESCB *) NULL;
-+      struct orc_scb *scb;
-+      struct orc_extended_scb *escb;
-+      struct orc_scb *host_scb;
-+      u8 i;
-+      unsigned long flags;
++      return tmp;
++}
 +
-+      spin_lock_irqsave(&(host->allocation_lock), flags);
-+      scb = (struct orc_scb *) NULL;
-+      escb = (struct orc_extended_scb *) NULL;
-       /* setup scatter list address with one buffer */
--      pVirScb = pHCB->HCS_virScbArray;
-+      host_scb = host->scb_virt;
--      initAFlag(pHCB);
--      /* device reset */
-+      /* FIXME: is this safe if we then fail to issue the reset or race
-+         a completion ? */
-+      init_alloc_map(host);
++struct vm_struct * im_get_free_area(unsigned long size)
++{
++      struct vm_struct *area;
++      unsigned long addr;
++      
++      mutex_lock(&imlist_mutex);
++      if (get_free_im_addr(size, &addr)) {
++              printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n",
++                              __FUNCTION__, size);
++              area = NULL;
++              goto next_im_done;
++      }
 +
-+      /* Find the scb corresponding to the command */
-       for (i = 0; i < ORC_MAXQUEUE; i++) {
--              pVirEscb = pVirScb->SCB_EScb;
--              if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt))
-+              escb = host_scb->escb;
-+              if (host_scb->status && escb->srb == cmd)
-                       break;
--              pVirScb++;
-+              host_scb++;
-       }
-       if (i == ORC_MAXQUEUE) {
--              printk("Unable to Reset - No SCB Found\n");
--              spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-+              printk(KERN_ERR "Unable to Reset - No SCB Found\n");
-+              spin_unlock_irqrestore(&(host->allocation_lock), flags);
-               return FAILED;
-       }
--      if ((pScb = orc_alloc_scb(pHCB)) == NULL) {
--              spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
++      area = __im_get_area(addr, size, IM_REGION_UNUSED);
++      if (area == NULL) {
++              printk(KERN_ERR 
++                     "%s() cannot obtain area for addr 0x%lx size 0x%lx\n",
++                      __FUNCTION__, addr, size);
++      }
++next_im_done:
++      mutex_unlock(&imlist_mutex);
++      return area;
++}
 +
-+      /* Allocate a new SCB for the reset command to the firmware */
-+      if ((scb = __orc_alloc_scb(host)) == NULL) {
-+              /* Can't happen.. */
-+              spin_unlock_irqrestore(&(host->allocation_lock), flags);
-               return FAILED;
-       }
--      pScb->SCB_Opcode = ORC_BUSDEVRST;
--      pScb->SCB_Target = target;
--      pScb->SCB_HaStat = 0;
--      pScb->SCB_TaStat = 0;
--      pScb->SCB_Status = 0x0;
--      pScb->SCB_Link = 0xFF;
--      pScb->SCB_Reserved0 = 0;
--      pScb->SCB_Reserved1 = 0;
--      pScb->SCB_XferLen = 0;
--      pScb->SCB_SGLen = 0;
--
--      pVirEscb->SCB_Srb = NULL;
--      pVirEscb->SCB_Srb = SCpnt;
--      orc_exec_scb(pHCB, pScb);       /* Start execute SCB            */
--      spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-+
-+      /* Reset device is handled by the firmare, we fill in an SCB and
-+         fire it at the controller, it does the rest */
-+      scb->opcode = ORC_BUSDEVRST;
-+      scb->target = target;
-+      scb->hastat = 0;
-+      scb->tastat = 0;
-+      scb->status = 0x0;
-+      scb->link = 0xFF;
-+      scb->reserved0 = 0;
-+      scb->reserved1 = 0;
-+      scb->xferlen = 0;
-+      scb->sg_len = 0;
-+
-+      escb->srb = NULL;
-+      escb->srb = cmd;
-+      orc_exec_scb(host, scb);        /* Start execute SCB            */
-+      spin_unlock_irqrestore(&host->allocation_lock, flags);
-       return SUCCESS;
- }
++struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
++              int criteria)
++{
++      struct vm_struct *area;
++
++      mutex_lock(&imlist_mutex);
++      area = __im_get_area(v_addr, size, criteria);
++      mutex_unlock(&imlist_mutex);
++      return area;
++}
++
++void im_free(void * addr)
++{
++      struct vm_struct **p, *tmp;
++  
++      if (!addr)
++              return;
++      if ((unsigned long) addr & ~PAGE_MASK) {
++              printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__,                        addr);
++              return;
++      }
++      mutex_lock(&imlist_mutex);
++      for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
++              if (tmp->addr == addr) {
++                      *p = tmp->next;
++                      unmap_vm_area(tmp);
++                      kfree(tmp);
++                      mutex_unlock(&imlist_mutex);
++                      return;
++              }
++      }
++      mutex_unlock(&imlist_mutex);
++      printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
++                      addr);
++}
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/init_32.c linux-2.6.22-570/arch/powerpc/mm/init_32.c
+--- linux-2.6.22-590/arch/powerpc/mm/init_32.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/init_32.c 2007-07-08 19:32:17.000000000 -0400
+@@ -5,6 +5,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
+  *
+  *  Derived from "arch/i386/mm/init.c"
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/init_64.c linux-2.6.22-570/arch/powerpc/mm/init_64.c
+--- linux-2.6.22-590/arch/powerpc/mm/init_64.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/init_64.c 2007-07-08 19:32:17.000000000 -0400
+@@ -5,6 +5,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  *  Derived from "arch/i386/mm/init.c"
+  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/mem.c linux-2.6.22-570/arch/powerpc/mm/mem.c
+--- linux-2.6.22-590/arch/powerpc/mm/mem.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/mem.c     2007-07-08 19:32:17.000000000 -0400
+@@ -5,6 +5,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
+  *
+  *  Derived from "arch/i386/mm/init.c"
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/mmu_context_32.c linux-2.6.22-570/arch/powerpc/mm/mmu_context_32.c
+--- linux-2.6.22-590/arch/powerpc/mm/mmu_context_32.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/mmu_context_32.c  2007-07-08 19:32:17.000000000 -0400
+@@ -11,6 +11,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  *  Derived from "arch/i386/mm/init.c"
+  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/mmu_decl.h linux-2.6.22-570/arch/powerpc/mm/mmu_decl.h
+--- linux-2.6.22-590/arch/powerpc/mm/mmu_decl.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/mmu_decl.h        2007-07-08 19:32:17.000000000 -0400
+@@ -8,6 +8,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  *  Derived from "arch/i386/mm/init.c"
+  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+@@ -39,8 +40,8 @@
+ extern unsigned long ioremap_base;
+ extern unsigned int rtas_data, rtas_size;
  
-+/**
-+ *    __orc_alloc_scb         -               allocate an SCB
-+ *    @host: host to allocate from
-+ *
-+ *    Allocate an SCB and return a pointer to the SCB object. NULL
-+ *    is returned if no SCB is free. The caller must already hold
-+ *    the allocator lock at this point.
-+ */
+-struct hash_pte;
+-extern struct hash_pte *Hash, *Hash_end;
++struct _PTE;
++extern struct _PTE *Hash, *Hash_end;
+ extern unsigned long Hash_size, Hash_mask;
  
--/***************************************************************************/
--static ORC_SCB *__orc_alloc_scb(ORC_HCS * hcsp)
-+
-+static struct orc_scb *__orc_alloc_scb(struct orc_host * host)
- {
--      ORC_SCB *pTmpScb;
--      UCHAR Ch;
--      ULONG idx;
--      UCHAR index;
--      UCHAR i;
-+      u8 channel;
-+      unsigned long idx;
-+      u8 index;
-+      u8 i;
+ extern unsigned int num_tlbcam_entries;
+@@ -89,4 +90,16 @@
+       else
+               _tlbie(va);
+ }
++#else /* CONFIG_PPC64 */
++/* imalloc region types */
++#define IM_REGION_UNUSED      0x1
++#define IM_REGION_SUBSET      0x2
++#define IM_REGION_EXISTS      0x4
++#define IM_REGION_OVERLAP     0x8
++#define IM_REGION_SUPERSET    0x10
++
++extern struct vm_struct * im_get_free_area(unsigned long size);
++extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
++                                    int region_type);
++extern void im_free(void *addr);
+ #endif
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/pgtable_32.c linux-2.6.22-570/arch/powerpc/mm/pgtable_32.c
+--- linux-2.6.22-590/arch/powerpc/mm/pgtable_32.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/pgtable_32.c      2007-07-08 19:32:17.000000000 -0400
+@@ -8,6 +8,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  *  Derived from "arch/i386/mm/init.c"
+  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+@@ -36,6 +37,7 @@
+ unsigned long ioremap_base;
+ unsigned long ioremap_bot;
+ EXPORT_SYMBOL(ioremap_bot);   /* aka VMALLOC_END */
++int io_bat_index;
  
--      Ch = hcsp->HCS_Index;
-+      channel = host->index;
-       for (i = 0; i < 8; i++) {
-               for (index = 0; index < 32; index++) {
--                      if ((hcsp->BitAllocFlag[Ch][i] >> index) & 0x01) {
--                              hcsp->BitAllocFlag[Ch][i] &= ~(1 << index);
-+                      if ((host->allocation_map[channel][i] >> index) & 0x01) {
-+                              host->allocation_map[channel][i] &= ~(1 << index);
-                               break;
-                       }
-               }
-               idx = index + 32 * i;
--              pTmpScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (idx * sizeof(ORC_SCB)));
--              return (pTmpScb);
-+              /* Translate the index to a structure instance */
-+              return (struct orc_scb *) ((unsigned long) host->scb_virt + (idx * sizeof(struct orc_scb)));
+ #if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
+ #define HAVE_BATS     1
+@@ -298,6 +300,51 @@
        }
--      return (NULL);
-+      return NULL;
  }
  
--static ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp)
-+/**
-+ *    orc_alloc_scb           -               allocate an SCB
-+ *    @host: host to allocate from
-+ *
-+ *    Allocate an SCB and return a pointer to the SCB object. NULL
-+ *    is returned if no SCB is free.
-+ */
++/* is x a power of 4? */
++#define is_power_of_4(x)      is_power_of_2(x) && (ffs(x) & 1)
 +
-+static struct orc_scb *orc_alloc_scb(struct orc_host * host)
- {
--      ORC_SCB *pTmpScb;
--      ULONG flags;
-+      struct orc_scb *scb;
-+      unsigned long flags;
--      spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
--      pTmpScb = __orc_alloc_scb(hcsp);
--      spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
--      return (pTmpScb);
-+      spin_lock_irqsave(&host->allocation_lock, flags);
-+      scb = __orc_alloc_scb(host);
-+      spin_unlock_irqrestore(&host->allocation_lock, flags);
-+      return scb;
- }
-+/**
-+ *    orc_release_scb                 -       release an SCB
-+ *    @host: host owning the SCB
-+ *    @scb: SCB that is now free
-+ *
-+ *    Called to return a completed SCB to the allocation pool. Before
-+ *    calling the SCB must be out of use on both the host and the HA.
-+ */
--/***************************************************************************/
--static void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
-+static void orc_release_scb(struct orc_host *host, struct orc_scb *scb)
- {
--      ULONG flags;
--      UCHAR Index;
--      UCHAR i;
--      UCHAR Ch;
--
--      spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
--      Ch = hcsp->HCS_Index;
--      Index = scbp->SCB_ScbIdx;
--      i = Index / 32;
--      Index %= 32;
--      hcsp->BitAllocFlag[Ch][i] |= (1 << Index);
--      spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-+      unsigned long flags;
-+      u8 index, i, channel;
-+
-+      spin_lock_irqsave(&(host->allocation_lock), flags);
-+      channel = host->index;  /* Channel */
-+      index = scb->scbidx;
-+      i = index / 32;
-+      index %= 32;
-+      host->allocation_map[channel][i] |= (1 << index);
-+      spin_unlock_irqrestore(&(host->allocation_lock), flags);
- }
--/*****************************************************************************
-- Function name  : abort_SCB
-- Description    : Abort a queued command.
--                       (commands that are on the bus can't be aborted easily)
-- Input          : pHCB  -       Pointer to host adapter structure
-- Output         : None.
-- Return         : pSRB  -       Pointer to SCSI request block.
--*****************************************************************************/
--static int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb)
-+/**
-+ *    orchid_abort_scb        -       abort a command
-+ *
-+ *    Abort a queued command that has been passed to the firmware layer
-+ *    if possible. This is all handled by the firmware. We aks the firmware
-+ *    and it either aborts the command or fails
++/*
++ * Set up a mapping for a block of I/O.
++ * virt, phys, size must all be page-aligned.
++ * This should only be called before ioremap is called.
 + */
++void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
++                           unsigned int size, int flags)
++{
++      int i;
 +
-+static int orchid_abort_scb(struct orc_host * host, struct orc_scb * scb)
- {
--      unsigned char bData, bStatus;
-+      unsigned char data, status;
--      ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_ABORT_SCB);  /* Write command */
--      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
--      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
-+      outb(ORC_CMD_ABORT_SCB, host->base + ORC_HDATA);        /* Write command */
-+      outb(HDO, host->base + ORC_HCTRL);
-+      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
-               return 0;
--      ORC_WR(hcsp->HCS_Base + ORC_HDATA, pScb->SCB_ScbIdx);   /* Write address */
--      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
--      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
-+      outb(scb->scbidx, host->base + ORC_HDATA);      /* Write address */
-+      outb(HDO, host->base + ORC_HCTRL);
-+      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
-               return 0;
--      if (waitHDIset(hcsp, &bData) == 0)      /* Wait HDI set   */
-+      if (wait_hdi_set(host, &data) == 0)     /* Wait HDI set   */
-               return 0;
--      bStatus = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
--      ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);      /* Clear HDI    */
-+      status = inb(host->base + ORC_HDATA);
-+      outb(data, host->base + ORC_HSTUS);     /* Clear HDI    */
--      if (bStatus == 1)       /* 0 - Successfully               */
-+      if (status == 1)        /* 0 - Successfully               */
-               return 0;       /* 1 - Fail                     */
-       return 1;
- }
--/*****************************************************************************
-- Function name  : inia100_abort
-- Description    : Abort a queued command.
--                       (commands that are on the bus can't be aborted easily)
-- Input          : pHCB  -       Pointer to host adapter structure
-- Output         : None.
-- Return         : pSRB  -       Pointer to SCSI request block.
--*****************************************************************************/
--static int orc_abort_srb(ORC_HCS * hcsp, struct scsi_cmnd *SCpnt)
-+static int inia100_abort_cmd(struct orc_host * host, struct scsi_cmnd *cmd)
- {
--      ESCB *pVirEscb;
--      ORC_SCB *pVirScb;
--      UCHAR i;
--      ULONG flags;
--
--      spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
--
--      pVirScb = hcsp->HCS_virScbArray;
--
--      for (i = 0; i < ORC_MAXQUEUE; i++, pVirScb++) {
--              pVirEscb = pVirScb->SCB_EScb;
--              if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt)) {
--                      if (pVirScb->SCB_TagMsg == 0) {
--                              spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
--                              return FAILED;
-+      struct orc_extended_scb *escb;
-+      struct orc_scb *scb;
-+      u8 i;
-+      unsigned long flags;
++      if (virt > KERNELBASE && virt < ioremap_bot)
++              ioremap_bot = ioremap_base = virt;
 +
-+      spin_lock_irqsave(&(host->allocation_lock), flags);
++#ifdef HAVE_BATS
++      /*
++       * Use a BAT for this if possible...
++       */
++      if (io_bat_index < 2 && is_power_of_2(size)
++          && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
++              setbat(io_bat_index, virt, phys, size, flags);
++              ++io_bat_index;
++              return;
++      }
++#endif /* HAVE_BATS */
 +
-+      scb = host->scb_virt;
++#ifdef HAVE_TLBCAM
++      /*
++       * Use a CAM for this if possible...
++       */
++      if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size)
++          && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
++              settlbcam(tlbcam_index, virt, phys, size, flags, 0);
++              ++tlbcam_index;
++              return;
++      }
++#endif /* HAVE_TLBCAM */
 +
-+      /* Walk the queue until we find the SCB that belongs to the command
-+         block. This isn't a performance critical path so a walk in the park
-+         here does no harm */
++      /* No BATs available, put it in the page tables. */
++      for (i = 0; i < size; i += PAGE_SIZE)
++              map_page(virt + i, phys + i, flags);
++}
 +
-+      for (i = 0; i < ORC_MAXQUEUE; i++, scb++) {
-+              escb = scb->escb;
-+              if (scb->status && escb->srb == cmd) {
-+                      if (scb->tag_msg == 0) {
-+                              goto out;
-                       } else {
--                              if (abort_SCB(hcsp, pVirScb)) {
--                                      pVirEscb->SCB_Srb = NULL;
--                                      spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-+                              /* Issue an ABORT to the firmware */
-+                              if (orchid_abort_scb(host, scb)) {
-+                                      escb->srb = NULL;
-+                                      spin_unlock_irqrestore(&host->allocation_lock, flags);
-                                       return SUCCESS;
--                              } else {
--                                      spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
--                                      return FAILED;
--                              }
-+                              } else
-+                                      goto out;
-                       }
-               }
-       }
--      spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-+out:
-+      spin_unlock_irqrestore(&host->allocation_lock, flags);
-       return FAILED;
+ /* Scan the real Linux page tables and return a PTE pointer for
+  * a virtual address in a context.
+  * Returns true (1) if PTE was found, zero otherwise.  The pointer to
+@@ -332,6 +379,82 @@
+         return(retval);
  }
  
--/***********************************************************************
-- Routine Description:
--        This is the interrupt service routine for the Orchid SCSI adapter.
--        It reads the interrupt register to determine if the adapter is indeed
--        the source of the interrupt and clears the interrupt at the device.
-- Arguments:
--        HwDeviceExtension - HBA miniport driver's adapter data storage
-- Return Value:
--***********************************************************************/
--static void orc_interrupt(
--                        ORC_HCS * hcsp
--)
-+/**
-+ *    orc_interrupt           -       IRQ processing
-+ *    @host: Host causing the interrupt
-+ *
-+ *    This function is called from the IRQ handler and protected
-+ *    by the host lock. While the controller reports that there are
-+ *    scb's for processing we pull them off the controller, turn the
-+ *    index into a host address pointer to the scb and call the scb
-+ *    handler.
-+ *
-+ *    Returns IRQ_HANDLED if any SCBs were processed, IRQ_NONE otherwise
++/* Find physical address for this virtual address.  Normally used by
++ * I/O functions, but anyone can call it.
 + */
++unsigned long iopa(unsigned long addr)
++{
++      unsigned long pa;
 +
-+static irqreturn_t orc_interrupt(struct orc_host * host)
- {
--      BYTE bScbIdx;
--      ORC_SCB *pScb;
-+      u8 scb_index;
-+      struct orc_scb *scb;
--      if (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT) == 0) {
--              return;         // 0;
-+      /* Check if we have an SCB queued for servicing */
-+      if (inb(host->base + ORC_RQUEUECNT) == 0)
-+              return IRQ_NONE;
--      }
-       do {
--              bScbIdx = ORC_RD(hcsp->HCS_Base, ORC_RQUEUE);
--
--              pScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (ULONG) (sizeof(ORC_SCB) * bScbIdx));
--              pScb->SCB_Status = 0x0;
--
--              inia100SCBPost((BYTE *) hcsp, (BYTE *) pScb);
--      } while (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT));
--      return;                 //1;
-+              /* Get the SCB index of the SCB to service */
-+              scb_index = inb(host->base + ORC_RQUEUE);
-+              /* Translate it back to a host pointer */
-+              scb = (struct orc_scb *) ((unsigned long) host->scb_virt + (unsigned long) (sizeof(struct orc_scb) * scb_index));
-+              scb->status = 0x0;
-+              /* Process the SCB */
-+              inia100_scb_handler(host, scb);
-+      } while (inb(host->base + ORC_RQUEUECNT));
-+      return IRQ_HANDLED;
- }                             /* End of I1060Interrupt() */
--/*****************************************************************************
-- Function name  : inia100BuildSCB
-- Description    : 
-- Input          : pHCB  -       Pointer to host adapter structure
-- Output         : None.
-- Return         : pSRB  -       Pointer to SCSI request block.
--*****************************************************************************/
--static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, struct scsi_cmnd * SCpnt)
-+/**
-+ *    inia100_build_scb       -       build SCB
-+ *    @host: host owing the control block
-+ *    @scb: control block to use
-+ *    @cmd: Mid layer command
-+ *
-+ *    Build a host adapter control block from the SCSI mid layer command
-+ */
++      /* I don't know why this won't work on PMacs or CHRP.  It
++       * appears there is some bug, or there is some implicit
++       * mapping done not properly represented by BATs or in page
++       * tables.......I am actively working on resolving this, but
++       * can't hold up other stuff.  -- Dan
++       */
++      pte_t *pte;
++      struct mm_struct *mm;
 +
-+static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, struct scsi_cmnd * cmd)
- {                             /* Create corresponding SCB     */
--      struct scatterlist *pSrbSG;
--      ORC_SG *pSG;            /* Pointer to SG list           */
-+      struct scatterlist *sg;
-+      struct orc_sgent *sgent;                /* Pointer to SG list           */
-       int i, count_sg;
--      ESCB *pEScb;
-+      struct orc_extended_scb *escb;
--      pEScb = pSCB->SCB_EScb;
--      pEScb->SCB_Srb = SCpnt;
--      pSG = NULL;
--
--      pSCB->SCB_Opcode = ORC_EXECSCSI;
--      pSCB->SCB_Flags = SCF_NO_DCHK;  /* Clear done bit               */
--      pSCB->SCB_Target = SCpnt->device->id;
--      pSCB->SCB_Lun = SCpnt->device->lun;
--      pSCB->SCB_Reserved0 = 0;
--      pSCB->SCB_Reserved1 = 0;
--      pSCB->SCB_SGLen = 0;
--
--      if ((pSCB->SCB_XferLen = (U32) SCpnt->request_bufflen)) {
--              pSG = (ORC_SG *) & pEScb->ESCB_SGList[0];
--              if (SCpnt->use_sg) {
--                      pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
--                      count_sg = pci_map_sg(pHCB->pdev, pSrbSG, SCpnt->use_sg,
--                                      SCpnt->sc_data_direction);
--                      pSCB->SCB_SGLen = (U32) (count_sg * 8);
--                      for (i = 0; i < count_sg; i++, pSG++, pSrbSG++) {
--                              pSG->SG_Ptr = (U32) sg_dma_address(pSrbSG);
--                              pSG->SG_Len = (U32) sg_dma_len(pSrbSG);
--                      }
--              } else if (SCpnt->request_bufflen != 0) {/* Non SG */
--                      pSCB->SCB_SGLen = 0x8;
--                      SCpnt->SCp.dma_handle = pci_map_single(pHCB->pdev,
--                                      SCpnt->request_buffer,
--                                      SCpnt->request_bufflen,
--                                      SCpnt->sc_data_direction);
--                      pSG->SG_Ptr = (U32) SCpnt->SCp.dma_handle;
--                      pSG->SG_Len = (U32) SCpnt->request_bufflen;
-+      /* Links between the escb, scb and Linux scsi midlayer cmd */
-+      escb = scb->escb;
-+      escb->srb = cmd;
-+      sgent = NULL;
-+
-+      /* Set up the SCB to do a SCSI command block */
-+      scb->opcode = ORC_EXECSCSI;
-+      scb->flags = SCF_NO_DCHK;       /* Clear done bit               */
-+      scb->target = cmd->device->id;
-+      scb->lun = cmd->device->lun;
-+      scb->reserved0 = 0;
-+      scb->reserved1 = 0;
-+      scb->sg_len = 0;
-+
-+      scb->xferlen = (u32) scsi_bufflen(cmd);
-+      sgent = (struct orc_sgent *) & escb->sglist[0];
-+
-+      count_sg = scsi_dma_map(cmd);
-+      BUG_ON(count_sg < 0);
-+
-+      /* Build the scatter gather lists */
-+      if (count_sg) {
-+              scb->sg_len = (u32) (count_sg * 8);
-+              scsi_for_each_sg(cmd, sg, count_sg, i) {
-+                      sgent->base = (u32) sg_dma_address(sg);
-+                      sgent->length = (u32) sg_dma_len(sg);
-+                      sgent++;
-+              }
-               } else {
--                      pSCB->SCB_SGLen = 0;
--                      pSG->SG_Ptr = 0;
--                      pSG->SG_Len = 0;
--              }
--      }
--      pSCB->SCB_SGPAddr = (U32) pSCB->SCB_SensePAddr;
--      pSCB->SCB_HaStat = 0;
--      pSCB->SCB_TaStat = 0;
--      pSCB->SCB_Link = 0xFF;
--      pSCB->SCB_SenseLen = SENSE_SIZE;
--      pSCB->SCB_CDBLen = SCpnt->cmd_len;
--      if (pSCB->SCB_CDBLen >= IMAX_CDB) {
--              printk("max cdb length= %x\b", SCpnt->cmd_len);
--              pSCB->SCB_CDBLen = IMAX_CDB;
--      }
--      pSCB->SCB_Ident = SCpnt->device->lun | DISC_ALLOW;
--      if (SCpnt->device->tagged_supported) {  /* Tag Support                  */
--              pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG;    /* Do simple tag only   */
-+              scb->sg_len = 0;
-+              sgent->base = 0;
-+              sgent->length = 0;
-+      }
-+      scb->sg_addr = (u32) scb->sense_addr;
-+      scb->hastat = 0;
-+      scb->tastat = 0;
-+      scb->link = 0xFF;
-+      scb->sense_len = SENSE_SIZE;
-+      scb->cdb_len = cmd->cmd_len;
-+      if (scb->cdb_len >= IMAX_CDB) {
-+              printk("max cdb length= %x\b", cmd->cmd_len);
-+              scb->cdb_len = IMAX_CDB;
-+      }
-+      scb->ident = cmd->device->lun | DISC_ALLOW;
-+      if (cmd->device->tagged_supported) {    /* Tag Support                  */
-+              scb->tag_msg = SIMPLE_QUEUE_TAG;        /* Do simple tag only   */
-       } else {
--              pSCB->SCB_TagMsg = 0;   /* No tag support               */
-+              scb->tag_msg = 0;       /* No tag support               */
-       }
--      memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, pSCB->SCB_CDBLen);
--      return;
-+      memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len);
- }
--/*****************************************************************************
-- Function name  : inia100_queue
-- Description    : Queue a command and setup interrupts for a free bus.
-- Input          : pHCB  -       Pointer to host adapter structure
-- Output         : None.
-- Return         : pSRB  -       Pointer to SCSI request block.
--*****************************************************************************/
--static int inia100_queue(struct scsi_cmnd * SCpnt, void (*done) (struct scsi_cmnd *))
-+/**
-+ *    inia100_queue           -       queue command with host
-+ *    @cmd: Command block
-+ *    @done: Completion function
-+ *
-+ *    Called by the mid layer to queue a command. Process the command
-+ *    block, build the host specific scb structures and if there is room
-+ *    queue the command down to the controller
-+ */
++      /* Check the BATs */
++      pa = v_mapped_by_bats(addr);
++      if (pa)
++              return pa;
 +
-+static int inia100_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
- {
--      register ORC_SCB *pSCB;
--      ORC_HCS *pHCB;          /* Point to Host adapter control block */
-+      struct orc_scb *scb;
-+      struct orc_host *host;          /* Point to Host adapter control block */
--      pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
--      SCpnt->scsi_done = done;
-+      host = (struct orc_host *) cmd->device->host->hostdata;
-+      cmd->scsi_done = done;
-       /* Get free SCSI control block  */
--      if ((pSCB = orc_alloc_scb(pHCB)) == NULL)
-+      if ((scb = orc_alloc_scb(host)) == NULL)
-               return SCSI_MLQUEUE_HOST_BUSY;
--      inia100BuildSCB(pHCB, pSCB, SCpnt);
--      orc_exec_scb(pHCB, pSCB);       /* Start execute SCB            */
--
--      return (0);
-+      inia100_build_scb(host, scb, cmd);
-+      orc_exec_scb(host, scb);        /* Start execute SCB            */
-+      return 0;
- }
- /*****************************************************************************
-  Function name  : inia100_abort
-  Description    : Abort a queued command.
-                        (commands that are on the bus can't be aborted easily)
-- Input          : pHCB  -       Pointer to host adapter structure
-+ Input          : host  -       Pointer to host adapter structure
-  Output         : None.
-  Return         : pSRB  -       Pointer to SCSI request block.
- *****************************************************************************/
--static int inia100_abort(struct scsi_cmnd * SCpnt)
-+static int inia100_abort(struct scsi_cmnd * cmd)
- {
--      ORC_HCS *hcsp;
-+      struct orc_host *host;
--      hcsp = (ORC_HCS *) SCpnt->device->host->hostdata;
--      return orc_abort_srb(hcsp, SCpnt);
-+      host = (struct orc_host *) cmd->device->host->hostdata;
-+      return inia100_abort_cmd(host, cmd);
- }
- /*****************************************************************************
-  Function name  : inia100_reset
-  Description    : Reset registers, reset a hanging bus and
-                   kill active and disconnected commands for target w/o soft reset
-- Input          : pHCB  -       Pointer to host adapter structure
-+ Input          : host  -       Pointer to host adapter structure
-  Output         : None.
-  Return         : pSRB  -       Pointer to SCSI request block.
- *****************************************************************************/
--static int inia100_bus_reset(struct scsi_cmnd * SCpnt)
-+static int inia100_bus_reset(struct scsi_cmnd * cmd)
- {                             /* I need Host Control Block Information */
--      ORC_HCS *pHCB;
--      pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
--      return orc_reset_scsi_bus(pHCB);
-+      struct orc_host *host;
-+      host = (struct orc_host *) cmd->device->host->hostdata;
-+      return orc_reset_scsi_bus(host);
- }
- /*****************************************************************************
-  Function name  : inia100_device_reset
-  Description    : Reset the device
-- Input          : pHCB  -       Pointer to host adapter structure
-+ Input          : host  -       Pointer to host adapter structure
-  Output         : None.
-  Return         : pSRB  -       Pointer to SCSI request block.
- *****************************************************************************/
--static int inia100_device_reset(struct scsi_cmnd * SCpnt)
-+static int inia100_device_reset(struct scsi_cmnd * cmd)
- {                             /* I need Host Control Block Information */
--      ORC_HCS *pHCB;
--      pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
--      return orc_device_reset(pHCB, SCpnt, scmd_id(SCpnt));
-+      struct orc_host *host;
-+      host = (struct orc_host *) cmd->device->host->hostdata;
-+      return orc_device_reset(host, cmd, scmd_id(cmd));
- }
--/*****************************************************************************
-- Function name  : inia100SCBPost
-- Description    : This is callback routine be called when orc finish one
--                      SCSI command.
-- Input          : pHCB  -       Pointer to host adapter control block.
--                pSCB  -       Pointer to SCSI control block.
-- Output         : None.
-- Return         : None.
--*****************************************************************************/
--static void inia100SCBPost(BYTE * pHcb, BYTE * pScb)
-+/**
-+ *    inia100_scb_handler     -       interrupt callback
-+ *    @host: Host causing the interrupt
-+ *    @scb: SCB the controller returned as needing processing
-+ *
-+ *    Perform completion processing on a control block. Do the conversions
-+ *    from host to SCSI midlayer error coding, save any sense data and
-+ *    the complete with the midlayer and recycle the scb.
++      /* Allow mapping of user addresses (within the thread)
++       * for DMA if necessary.
++       */
++      if (addr < TASK_SIZE)
++              mm = current->mm;
++      else
++              mm = &init_mm;
++
++      pa = 0;
++      if (get_pteptr(mm, addr, &pte, NULL)) {
++              pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
++              pte_unmap(pte);
++      }
++
++      return(pa);
++}
++
++/* This is will find the virtual address for a physical one....
++ * Swiped from APUS, could be dangerous :-).
++ * This is only a placeholder until I really find a way to make this
++ * work.  -- Dan
 + */
++unsigned long
++mm_ptov (unsigned long paddr)
++{
++      unsigned long ret;
++#if 0
++      if (paddr < 16*1024*1024)
++              ret = ZTWO_VADDR(paddr);
++      else {
++              int i;
 +
-+static void inia100_scb_handler(struct orc_host *host, struct orc_scb *scb)
- {
--      struct scsi_cmnd *pSRB; /* Pointer to SCSI request block */
--      ORC_HCS *pHCB;
--      ORC_SCB *pSCB;
--      ESCB *pEScb;
--
--      pHCB = (ORC_HCS *) pHcb;
--      pSCB = (ORC_SCB *) pScb;
--      pEScb = pSCB->SCB_EScb;
--      if ((pSRB = (struct scsi_cmnd *) pEScb->SCB_Srb) == 0) {
--              printk("inia100SCBPost: SRB pointer is empty\n");
--              orc_release_scb(pHCB, pSCB);    /* Release SCB for current channel */
-+      struct scsi_cmnd *cmd;  /* Pointer to SCSI request block */
-+      struct orc_extended_scb *escb;
-+
-+      escb = scb->escb;
-+      if ((cmd = (struct scsi_cmnd *) escb->srb) == NULL) {
-+              printk(KERN_ERR "inia100_scb_handler: SRB pointer is empty\n");
-+              orc_release_scb(host, scb);     /* Release SCB for current channel */
-               return;
-       }
--      pEScb->SCB_Srb = NULL;
-+      escb->srb = NULL;
--      switch (pSCB->SCB_HaStat) {
-+      switch (scb->hastat) {
-       case 0x0:
-       case 0xa:               /* Linked command complete without error and linked normally */
-       case 0xb:               /* Linked command complete without error interrupt generated */
--              pSCB->SCB_HaStat = 0;
-+              scb->hastat = 0;
-               break;
-       case 0x11:              /* Selection time out-The initiator selection or target
-                                  reselection was not complete within the SCSI Time out period */
--              pSCB->SCB_HaStat = DID_TIME_OUT;
-+              scb->hastat = DID_TIME_OUT;
-               break;
-       case 0x14:              /* Target bus phase sequence failure-An invalid bus phase or bus
-                                  phase sequence was requested by the target. The host adapter
-                                  will generate a SCSI Reset Condition, notifying the host with
-                                  a SCRD interrupt */
--              pSCB->SCB_HaStat = DID_RESET;
-+              scb->hastat = DID_RESET;
-               break;
-       case 0x1a:              /* SCB Aborted. 07/21/98 */
--              pSCB->SCB_HaStat = DID_ABORT;
-+              scb->hastat = DID_ABORT;
-               break;
-       case 0x12:              /* Data overrun/underrun-The target attempted to transfer more data
-@@ -984,46 +1022,41 @@
-       case 0x16:              /* Invalid CCB Operation Code-The first byte of the CCB was invalid. */
-       default:
--              printk("inia100: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat);
--              pSCB->SCB_HaStat = DID_ERROR;   /* Couldn't find any better */
-+              printk(KERN_DEBUG "inia100: %x %x\n", scb->hastat, scb->tastat);
-+              scb->hastat = DID_ERROR;        /* Couldn't find any better */
-               break;
-       }
--      if (pSCB->SCB_TaStat == 2) {    /* Check condition              */
--              memcpy((unsigned char *) &pSRB->sense_buffer[0],
--                 (unsigned char *) &pEScb->ESCB_SGList[0], SENSE_SIZE);
--      }
--      pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);
--
--      if (pSRB->use_sg) {
--              pci_unmap_sg(pHCB->pdev,
--                           (struct scatterlist *)pSRB->request_buffer,
--                           pSRB->use_sg, pSRB->sc_data_direction);
--      } else if (pSRB->request_bufflen != 0) {
--              pci_unmap_single(pHCB->pdev, pSRB->SCp.dma_handle,
--                               pSRB->request_bufflen,
--                               pSRB->sc_data_direction);
--      }
--
--      pSRB->scsi_done(pSRB);  /* Notify system DONE           */
--
--      orc_release_scb(pHCB, pSCB);    /* Release SCB for current channel */
-+      if (scb->tastat == 2) { /* Check condition              */
-+              memcpy((unsigned char *) &cmd->sense_buffer[0],
-+                 (unsigned char *) &escb->sglist[0], SENSE_SIZE);
++              for (i = 0; i < kmap_chunk_count;){
++                      unsigned long phys = kmap_chunks[i++];
++                      unsigned long size = kmap_chunks[i++];
++                      unsigned long virt = kmap_chunks[i++];
++                      if (paddr >= phys
++                          && paddr < (phys + size)){
++                              ret = virt + paddr - phys;
++                              goto exit;
++                      }
++              }
++      
++              ret = (unsigned long) __va(paddr);
 +      }
-+      cmd->result = scb->tastat | (scb->hastat << 16);
-+      scsi_dma_unmap(cmd);
-+      cmd->scsi_done(cmd);    /* Notify system DONE           */
-+      orc_release_scb(host, scb);     /* Release SCB for current channel */
- }
--/*
-- * Interrupt handler (main routine of the driver)
-+/**
-+ *    inia100_intr            -       interrupt handler
-+ *    @irqno: Interrupt value
-+ *    @devid: Host adapter
-+ *
-+ *    Entry point for IRQ handling. All the real work is performed
-+ *    by orc_interrupt.
-  */
- static irqreturn_t inia100_intr(int irqno, void *devid)
- {
--      struct Scsi_Host *host = (struct Scsi_Host *)devid;
--      ORC_HCS *pHcb = (ORC_HCS *)host->hostdata;
-+      struct Scsi_Host *shost = (struct Scsi_Host *)devid;
-+      struct orc_host *host = (struct orc_host *)shost->hostdata;
-       unsigned long flags;
-+      irqreturn_t res;
--      spin_lock_irqsave(host->host_lock, flags);
--      orc_interrupt(pHcb);
--      spin_unlock_irqrestore(host->host_lock, flags);
-+      spin_lock_irqsave(shost->host_lock, flags);
-+      res = orc_interrupt(host);
-+      spin_unlock_irqrestore(shost->host_lock, flags);
--      return IRQ_HANDLED;
-+      return res;
- }
- static struct scsi_host_template inia100_template = {
-@@ -1044,12 +1077,12 @@
-               const struct pci_device_id *id)
- {
-       struct Scsi_Host *shost;
--      ORC_HCS *pHCB;
-+      struct orc_host *host;
-       unsigned long port, bios;
-       int error = -ENODEV;
-       u32 sz;
--      unsigned long dBiosAdr;
--      char *pbBiosAdr;
-+      unsigned long biosaddr;
-+      char *bios_phys;
-       if (pci_enable_device(pdev))
-               goto out;
-@@ -1068,55 +1101,55 @@
-       }
-       /* <02> read from base address + 0x50 offset to get the bios value. */
--      bios = ORC_RDWORD(port, 0x50);
-+      bios = inw(port + 0x50);
--      shost = scsi_host_alloc(&inia100_template, sizeof(ORC_HCS));
-+      shost = scsi_host_alloc(&inia100_template, sizeof(struct orc_host));
-       if (!shost)
-               goto out_release_region;
--      pHCB = (ORC_HCS *)shost->hostdata;
--      pHCB->pdev = pdev;
--      pHCB->HCS_Base = port;
--      pHCB->HCS_BIOS = bios;
--      spin_lock_init(&pHCB->BitAllocFlagLock);
-+      host = (struct orc_host *)shost->hostdata;
-+      host->pdev = pdev;
-+      host->base = port;
-+      host->BIOScfg = bios;
-+      spin_lock_init(&host->allocation_lock);
++exit:
++#ifdef DEBUGPV
++      printk ("PTOV(%lx)=%lx\n", paddr, ret);
++#endif
++#else
++      ret = (unsigned long)paddr + KERNELBASE;
++#endif
++      return ret;
++}
++
+ #ifdef CONFIG_DEBUG_PAGEALLOC
  
-       /* Get total memory needed for SCB */
--      sz = ORC_MAXQUEUE * sizeof(ORC_SCB);
--      pHCB->HCS_virScbArray = pci_alloc_consistent(pdev, sz,
--                      &pHCB->HCS_physScbArray);
--      if (!pHCB->HCS_virScbArray) {
-+      sz = ORC_MAXQUEUE * sizeof(struct orc_scb);
-+      host->scb_virt = pci_alloc_consistent(pdev, sz,
-+                      &host->scb_phys);
-+      if (!host->scb_virt) {
-               printk("inia100: SCB memory allocation error\n");
-               goto out_host_put;
-       }
--      memset(pHCB->HCS_virScbArray, 0, sz);
-+      memset(host->scb_virt, 0, sz);
+ static int __change_page_attr(struct page *page, pgprot_t prot)
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/pgtable_64.c linux-2.6.22-570/arch/powerpc/mm/pgtable_64.c
+--- linux-2.6.22-590/arch/powerpc/mm/pgtable_64.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/pgtable_64.c      2007-07-08 19:32:17.000000000 -0400
+@@ -7,6 +7,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@samba.org)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  *  Derived from "arch/i386/mm/init.c"
+  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+@@ -33,27 +34,41 @@
+ #include <linux/stddef.h>
+ #include <linux/vmalloc.h>
+ #include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bootmem.h>
++#include <linux/highmem.h>
++#include <linux/idr.h>
++#include <linux/nodemask.h>
++#include <linux/module.h>
  
-       /* Get total memory needed for ESCB */
--      sz = ORC_MAXQUEUE * sizeof(ESCB);
--      pHCB->HCS_virEscbArray = pci_alloc_consistent(pdev, sz,
--                      &pHCB->HCS_physEscbArray);
--      if (!pHCB->HCS_virEscbArray) {
-+      sz = ORC_MAXQUEUE * sizeof(struct orc_extended_scb);
-+      host->escb_virt = pci_alloc_consistent(pdev, sz,
-+                      &host->escb_phys);
-+      if (!host->escb_virt) {
-               printk("inia100: ESCB memory allocation error\n");
-               goto out_free_scb_array;
-       }
--      memset(pHCB->HCS_virEscbArray, 0, sz);
-+      memset(host->escb_virt, 0, sz);
--      dBiosAdr = pHCB->HCS_BIOS;
--      dBiosAdr = (dBiosAdr << 4);
--      pbBiosAdr = phys_to_virt(dBiosAdr);
--      if (init_orchid(pHCB)) {        /* Initialize orchid chip */
-+      biosaddr = host->BIOScfg;
-+      biosaddr = (biosaddr << 4);
-+      bios_phys = phys_to_virt(biosaddr);
-+      if (init_orchid(host)) {        /* Initialize orchid chip */
-               printk("inia100: initial orchid fail!!\n");
-               goto out_free_escb_array;
-       }
+ #include <asm/pgalloc.h>
+ #include <asm/page.h>
+ #include <asm/prom.h>
++#include <asm/lmb.h>
++#include <asm/rtas.h>
+ #include <asm/io.h>
+ #include <asm/mmu_context.h>
+ #include <asm/pgtable.h>
+ #include <asm/mmu.h>
++#include <asm/uaccess.h>
+ #include <asm/smp.h>
+ #include <asm/machdep.h>
+ #include <asm/tlb.h>
++#include <asm/eeh.h>
+ #include <asm/processor.h>
++#include <asm/mmzone.h>
+ #include <asm/cputable.h>
+ #include <asm/sections.h>
+ #include <asm/system.h>
++#include <asm/iommu.h>
+ #include <asm/abs_addr.h>
++#include <asm/vdso.h>
+ #include <asm/firmware.h>
  
--      shost->io_port = pHCB->HCS_Base;
-+      shost->io_port = host->base;
-       shost->n_io_port = 0xff;
-       shost->can_queue = ORC_MAXQUEUE;
-       shost->unique_id = shost->io_port;
--      shost->max_id = pHCB->HCS_MaxTar;
-+      shost->max_id = host->max_targets;
-       shost->max_lun = 16;
--      shost->irq = pHCB->HCS_Intr = pdev->irq;
--      shost->this_id = pHCB->HCS_SCSI_ID;     /* Assign HCS index */
-+      shost->irq = pdev->irq;
-+      shost->this_id = host->scsi_id; /* Assign HCS index */
-       shost->sg_tablesize = TOTAL_SG_ENTRY;
+ #include "mmu_decl.h"
  
-       /* Initial orc chip           */
-@@ -1137,36 +1170,36 @@
-       scsi_scan_host(shost);
-       return 0;
+-unsigned long ioremap_bot = IOREMAP_BASE;
++unsigned long ioremap_bot = IMALLOC_BASE;
++static unsigned long phbs_io_bot = PHBS_IO_BASE;
  
-- out_free_irq:
-+out_free_irq:
-         free_irq(shost->irq, shost);
-- out_free_escb_array:
--      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB),
--                      pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray);
-- out_free_scb_array:
--      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB),
--                      pHCB->HCS_virScbArray, pHCB->HCS_physScbArray);
-- out_host_put:
-+out_free_escb_array:
-+      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_extended_scb),
-+                      host->escb_virt, host->escb_phys);
-+out_free_scb_array:
-+      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_scb),
-+                      host->scb_virt, host->scb_phys);
-+out_host_put:
-       scsi_host_put(shost);
-- out_release_region:
-+out_release_region:
-         release_region(port, 256);
-- out_disable_device:
-+out_disable_device:
-       pci_disable_device(pdev);
-- out:
-+out:
-       return error;
+ /*
+  * map_io_page currently only called by __ioremap
+@@ -87,8 +102,8 @@
+                * entry in the hardware page table.
+                *
+                */
+-              if (htab_bolt_mapping(ea, (unsigned long)ea + PAGE_SIZE,
+-                                    pa, flags, mmu_io_psize)) {
++              if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
++                                    mmu_io_psize)) {
+                       printk(KERN_ERR "Failed to do bolted mapping IO "
+                              "memory at %016lx !\n", pa);
+                       return -ENOMEM;
+@@ -98,11 +113,8 @@
  }
  
- static void __devexit inia100_remove_one(struct pci_dev *pdev)
- {
-       struct Scsi_Host *shost = pci_get_drvdata(pdev);
--      ORC_HCS *pHCB = (ORC_HCS *)shost->hostdata;
-+      struct orc_host *host = (struct orc_host *)shost->hostdata;
  
-       scsi_remove_host(shost);
+-/**
+- * __ioremap_at - Low level function to establish the page tables
+- *                for an IO mapping
+- */
+-void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size,
++static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa,
++                          unsigned long ea, unsigned long size,
+                           unsigned long flags)
+ {
+       unsigned long i;
+@@ -110,35 +122,17 @@
+       if ((flags & _PAGE_PRESENT) == 0)
+               flags |= pgprot_val(PAGE_KERNEL);
  
-         free_irq(shost->irq, shost);
--      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB),
--                      pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray);
--      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB),
--                      pHCB->HCS_virScbArray, pHCB->HCS_physScbArray);
-+      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_extended_scb),
-+                      host->escb_virt, host->escb_phys);
-+      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_scb),
-+                      host->scb_virt, host->scb_phys);
-         release_region(shost->io_port, 256);
+-      WARN_ON(pa & ~PAGE_MASK);
+-      WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
+-      WARN_ON(size & ~PAGE_MASK);
+-
+       for (i = 0; i < size; i += PAGE_SIZE)
+-              if (map_io_page((unsigned long)ea+i, pa+i, flags))
++              if (map_io_page(ea+i, pa+i, flags))
+                       return NULL;
  
-       scsi_host_put(shost);
-diff -Nurb linux-2.6.22-570/drivers/scsi/a100u2w.h linux-2.6.22-590/drivers/scsi/a100u2w.h
---- linux-2.6.22-570/drivers/scsi/a100u2w.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/a100u2w.h    2008-01-02 13:56:37.000000000 -0500
-@@ -18,27 +18,6 @@
-  * along with this program; see the file COPYING.  If not, write to
-  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-  *
-- * --------------------------------------------------------------------------
-- *
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met:
-- * 1. Redistributions of source code must retain the above copyright
-- *    notice, this list of conditions, and the following disclaimer,
-- *    without modification, immediately at the beginning of the file.
-- * 2. Redistributions in binary form must reproduce the above copyright
-- *    notice, this list of conditions and the following disclaimer in the
-- *    documentation and/or other materials provided with the distribution.
-- * 3. The name of the author may not be used to endorse or promote products
-- *    derived from this software without specific prior written permission.
-- *
-- * Where this Software is combined with software released under the terms of 
-- * the GNU General Public License ("GPL") and the terms of the GPL would require the 
-- * combined work to also be released under the terms of the GPL, the terms
-- * and conditions of this License will apply in addition to those of the
-- * GPL with the exception of any terms or conditions of this License that
-- * conflict with, or are expressly prohibited by, the GPL.
-- *
-  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-@@ -50,30 +29,19 @@
-  * 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.
+-      return (void __iomem *)ea;
+-}
+-
+-/**
+- * __iounmap_from - Low level function to tear down the page tables
+- *                  for an IO mapping. This is used for mappings that
+- *                  are manipulated manually, like partial unmapping of
+- *                  PCI IOs or ISA space.
 - */
+-void __iounmap_at(void *ea, unsigned long size)
+-{
+-      WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
+-      WARN_ON(size & ~PAGE_MASK);
 -
--/*
-+ *
-  * Revision History:
-  * 06/18/98 HL, Initial production Version 1.02
-  * 12/19/98 bv, Use spinlocks for 2.1.95 and up
-  * 06/25/02 Doug Ledford <dledford@redhat.com>
-  *     - This and the i60uscsi.h file are almost identical,
-  *       merged them into a single header used by both .c files.
-+ * 14/06/07 Alan Cox <alan@redhat.com>
-+ *     - Grand cleanup and Linuxisation
-  */
+-      unmap_kernel_range((unsigned long)ea, size);
++      return (void __iomem *) (ea + (addr & ~PAGE_MASK));
+ }
  
- #define inia100_REVID "Initio INI-A100U2W SCSI device driver; Revision: 1.02d"
+ void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
+                        unsigned long flags)
+ {
+-      phys_addr_t paligned;
++      unsigned long pa, ea;
+       void __iomem *ret;
+       /*
+@@ -150,30 +144,27 @@
+        * IMALLOC_END
+        * 
+        */
+-      paligned = addr & PAGE_MASK;
+-      size = PAGE_ALIGN(addr + size) - paligned;
++      pa = addr & PAGE_MASK;
++      size = PAGE_ALIGN(addr + size) - pa;
+-      if ((size == 0) || (paligned == 0))
++      if ((size == 0) || (pa == 0))
+               return NULL;
  
--#define ULONG   unsigned long
--#define USHORT  unsigned short
--#define UCHAR   unsigned char
--#define BYTE    unsigned char
--#define WORD    unsigned short
--#define DWORD   unsigned long
--#define UBYTE   unsigned char
--#define UWORD   unsigned short
--#define UDWORD  unsigned long
--#define U32     u32
+       if (mem_init_done) {
+               struct vm_struct *area;
 -
- #if 1
- #define ORC_MAXQUEUE          245
- #define ORC_MAXTAGS           64
-@@ -90,10 +58,10 @@
- /************************************************************************/
- /*              Scatter-Gather Element Structure                        */
- /************************************************************************/
--typedef struct ORC_SG_Struc {
--      U32 SG_Ptr;             /* Data Pointer */
--      U32 SG_Len;             /* Data Length */
--} ORC_SG;
-+struct orc_sgent {
-+      u32 base;               /* Data Pointer */
-+      u32 length;             /* Data Length */
-+};
+-              area = __get_vm_area(size, VM_IOREMAP,
+-                                   ioremap_bot, IOREMAP_END);
++              area = im_get_free_area(size);
+               if (area == NULL)
+                       return NULL;
+-              ret = __ioremap_at(paligned, area->addr, size, flags);
++              ea = (unsigned long)(area->addr);
++              ret = __ioremap_com(addr, pa, ea, size, flags);
+               if (!ret)
+-                      vunmap(area->addr);
++                      im_free(area->addr);
+       } else {
+-              ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags);
++              ea = ioremap_bot;
++              ret = __ioremap_com(addr, pa, ea, size, flags);
+               if (ret)
+                       ioremap_bot += size;
+       }
+-
+-      if (ret)
+-              ret += addr & ~PAGE_MASK;
+       return ret;
+ }
  
- /* SCSI related definition                                              */
- #define DISC_NOT_ALLOW          0x80  /* Disconnect is not allowed    */
-@@ -165,42 +133,45 @@
- #define       ORC_PRGMCTR1    0xE3    /* RISC program counter           */
- #define       ORC_RISCRAM     0xEC    /* RISC RAM data port 4 bytes     */
+@@ -196,9 +187,62 @@
+ }
  
--typedef struct orc_extended_scb {     /* Extended SCB                 */
--      ORC_SG ESCB_SGList[TOTAL_SG_ENTRY];     /*0 Start of SG list              */
--      struct scsi_cmnd *SCB_Srb;      /*50 SRB Pointer */
--} ESCB;
-+struct orc_extended_scb {     /* Extended SCB                 */
-+      struct orc_sgent sglist[TOTAL_SG_ENTRY];        /*0 Start of SG list              */
-+      struct scsi_cmnd *srb;  /*50 SRB Pointer */
-+};
  
- /***********************************************************************
-               SCSI Control Block
++#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
 +
-+              0x40 bytes long, the last 8 are user bytes
- ************************************************************************/
--typedef struct orc_scb {      /* Scsi_Ctrl_Blk                */
--      UBYTE SCB_Opcode;       /*00 SCB command code&residual  */
--      UBYTE SCB_Flags;        /*01 SCB Flags                  */
--      UBYTE SCB_Target;       /*02 Target Id                  */
--      UBYTE SCB_Lun;          /*03 Lun                        */
--      U32 SCB_Reserved0;      /*04 Reserved for ORCHID must 0 */
--      U32 SCB_XferLen;        /*08 Data Transfer Length       */
--      U32 SCB_Reserved1;      /*0C Reserved for ORCHID must 0 */
--      U32 SCB_SGLen;          /*10 SG list # * 8              */
--      U32 SCB_SGPAddr;        /*14 SG List Buf physical Addr  */
--      U32 SCB_SGPAddrHigh;    /*18 SG Buffer high physical Addr */
--      UBYTE SCB_HaStat;       /*1C Host Status                */
--      UBYTE SCB_TaStat;       /*1D Target Status              */
--      UBYTE SCB_Status;       /*1E SCB status                 */
--      UBYTE SCB_Link;         /*1F Link pointer, default 0xFF */
--      UBYTE SCB_SenseLen;     /*20 Sense Allocation Length    */
--      UBYTE SCB_CDBLen;       /*21 CDB Length                 */
--      UBYTE SCB_Ident;        /*22 Identify                   */
--      UBYTE SCB_TagMsg;       /*23 Tag Message                */
--      UBYTE SCB_CDB[IMAX_CDB];        /*24 SCSI CDBs                  */
--      UBYTE SCB_ScbIdx;       /*3C Index for this ORCSCB      */
--      U32 SCB_SensePAddr;     /*34 Sense Buffer physical Addr */
--
--      ESCB *SCB_EScb;         /*38 Extended SCB Pointer       */
--#ifndef ALPHA
--      UBYTE SCB_Reserved2[4]; /*3E Reserved for Driver use    */
-+struct orc_scb {      /* Scsi_Ctrl_Blk                */
-+      u8 opcode;      /*00 SCB command code&residual  */
-+      u8 flags;       /*01 SCB Flags                  */
-+      u8 target;      /*02 Target Id                  */
-+      u8 lun;         /*03 Lun                        */
-+      u32 reserved0;  /*04 Reserved for ORCHID must 0 */
-+      u32 xferlen;    /*08 Data Transfer Length       */
-+      u32 reserved1;  /*0C Reserved for ORCHID must 0 */
-+      u32 sg_len;             /*10 SG list # * 8              */
-+      u32 sg_addr;    /*14 SG List Buf physical Addr  */
-+      u32 sg_addrhigh;        /*18 SG Buffer high physical Addr */
-+      u8 hastat;      /*1C Host Status                */
-+      u8 tastat;      /*1D Target Status              */
-+      u8 status;      /*1E SCB status                 */
-+      u8 link;                /*1F Link pointer, default 0xFF */
-+      u8 sense_len;   /*20 Sense Allocation Length    */
-+      u8 cdb_len;     /*21 CDB Length                 */
-+      u8 ident;       /*22 Identify                   */
-+      u8 tag_msg;     /*23 Tag Message                */
-+      u8 cdb[IMAX_CDB];       /*24 SCSI CDBs                  */
-+      u8 scbidx;      /*3C Index for this ORCSCB      */
-+      u32 sense_addr; /*34 Sense Buffer physical Addr */
-+
-+      struct orc_extended_scb *escb; /*38 Extended SCB Pointer       */
-+        /* 64bit pointer or 32bit pointer + reserved ? */
-+#ifndef CONFIG_64BIT
-+      u8 reserved2[4];        /*3E Reserved for Driver use    */
- #endif
--} ORC_SCB;
-+};
++int __ioremap_explicit(phys_addr_t pa, unsigned long ea,
++                     unsigned long size, unsigned long flags)
++{
++      struct vm_struct *area;
++      void __iomem *ret;
++      
++      /* For now, require page-aligned values for pa, ea, and size */
++      if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) ||
++          !IS_PAGE_ALIGNED(size)) {
++              printk(KERN_ERR "unaligned value in %s\n", __FUNCTION__);
++              return 1;
++      }
++      
++      if (!mem_init_done) {
++              /* Two things to consider in this case:
++               * 1) No records will be kept (imalloc, etc) that the region
++               *    has been remapped
++               * 2) It won't be easy to iounmap() the region later (because
++               *    of 1)
++               */
++              ;
++      } else {
++              area = im_get_area(ea, size,
++                      IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS);
++              if (area == NULL) {
++                      /* Expected when PHB-dlpar is in play */
++                      return 1;
++              }
++              if (ea != (unsigned long) area->addr) {
++                      printk(KERN_ERR "unexpected addr return from "
++                             "im_get_area\n");
++                      return 1;
++              }
++      }
++      
++      ret = __ioremap_com(pa, pa, ea, size, flags);
++      if (ret == NULL) {
++              printk(KERN_ERR "ioremap_explicit() allocation failure !\n");
++              return 1;
++      }
++      if (ret != (void *) ea) {
++              printk(KERN_ERR "__ioremap_com() returned unexpected addr\n");
++              return 1;
++      }
++
++      return 0;
++}
++
+ /*  
+  * Unmap an IO region and remove it from imalloc'd list.
+  * Access to IO memory should be serialized by driver.
++ * This code is modeled after vmalloc code - unmap_vm_area()
++ *
++ * XXX        what about calls before mem_init_done (ie python_countermeasures())
+  */
+ void __iounmap(volatile void __iomem *token)
+ {
+@@ -207,14 +251,9 @@
+       if (!mem_init_done)
+               return;
+       
+-      addr = (void *) ((unsigned long __force)
+-                       PCI_FIX_ADDR(token) & PAGE_MASK);
+-      if ((unsigned long)addr < ioremap_bot) {
+-              printk(KERN_WARNING "Attempt to iounmap early bolted mapping"
+-                     " at 0x%p\n", addr);
+-              return;
+-      }
+-      vunmap(addr);
++      addr = (void *) ((unsigned long __force) token & PAGE_MASK);
++
++      im_free(addr);
+ }
  
- /* Opcodes of ORCSCB_Opcode */
- #define ORC_EXECSCSI  0x00    /* SCSI initiator command with residual */
-@@ -239,13 +210,13 @@
-               Target Device Control Structure
- **********************************************************************/
+ void iounmap(volatile void __iomem *token)
+@@ -225,8 +264,77 @@
+               __iounmap(token);
+ }
  
--typedef struct ORC_Tar_Ctrl_Struc {
--      UBYTE TCS_DrvDASD;      /* 6 */
--      UBYTE TCS_DrvSCSI;      /* 7 */
--      UBYTE TCS_DrvHead;      /* 8 */
--      UWORD TCS_DrvFlags;     /* 4 */
--      UBYTE TCS_DrvSector;    /* 7 */
--} ORC_TCS;
-+struct orc_target {
-+      u8 TCS_DrvDASD; /* 6 */
-+      u8 TCS_DrvSCSI; /* 7 */
-+      u8 TCS_DrvHead; /* 8 */
-+      u16 TCS_DrvFlags;       /* 4 */
-+      u8 TCS_DrvSector;       /* 7 */
-+};
++static int iounmap_subset_regions(unsigned long addr, unsigned long size)
++{
++      struct vm_struct *area;
++
++      /* Check whether subsets of this region exist */
++      area = im_get_area(addr, size, IM_REGION_SUPERSET);
++      if (area == NULL)
++              return 1;
++
++      while (area) {
++              iounmap((void __iomem *) area->addr);
++              area = im_get_area(addr, size,
++                              IM_REGION_SUPERSET);
++      }
++
++      return 0;
++}
++
++int __iounmap_explicit(volatile void __iomem *start, unsigned long size)
++{
++      struct vm_struct *area;
++      unsigned long addr;
++      int rc;
++      
++      addr = (unsigned long __force) start & PAGE_MASK;
++
++      /* Verify that the region either exists or is a subset of an existing
++       * region.  In the latter case, split the parent region to create 
++       * the exact region 
++       */
++      area = im_get_area(addr, size, 
++                          IM_REGION_EXISTS | IM_REGION_SUBSET);
++      if (area == NULL) {
++              /* Determine whether subset regions exist.  If so, unmap */
++              rc = iounmap_subset_regions(addr, size);
++              if (rc) {
++                      printk(KERN_ERR
++                             "%s() cannot unmap nonexistent range 0x%lx\n",
++                              __FUNCTION__, addr);
++                      return 1;
++              }
++      } else {
++              iounmap((void __iomem *) area->addr);
++      }
++      /*
++       * FIXME! This can't be right:
++      iounmap(area->addr);
++       * Maybe it should be "iounmap(area);"
++       */
++      return 0;
++}
++
+ EXPORT_SYMBOL(ioremap);
+ EXPORT_SYMBOL(ioremap_flags);
+ EXPORT_SYMBOL(__ioremap);
+ EXPORT_SYMBOL(iounmap);
+ EXPORT_SYMBOL(__iounmap);
++
++static DEFINE_SPINLOCK(phb_io_lock);
++
++void __iomem * reserve_phb_iospace(unsigned long size)
++{
++      void __iomem *virt_addr;
++              
++      if (phbs_io_bot >= IMALLOC_BASE) 
++              panic("reserve_phb_iospace(): phb io space overflow\n");
++                      
++      spin_lock(&phb_io_lock);
++      virt_addr = (void __iomem *) phbs_io_bot;
++      phbs_io_bot += size;
++      spin_unlock(&phb_io_lock);
++
++      return virt_addr;
++}
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/ppc_mmu_32.c linux-2.6.22-570/arch/powerpc/mm/ppc_mmu_32.c
+--- linux-2.6.22-590/arch/powerpc/mm/ppc_mmu_32.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/ppc_mmu_32.c      2007-07-08 19:32:17.000000000 -0400
+@@ -11,6 +11,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  *  Derived from "arch/i386/mm/init.c"
+  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+@@ -34,12 +35,12 @@
  
- /* Bit Definition for TCF_DrvFlags */
- #define       TCS_DF_NODASD_SUPT      0x20    /* Suppress OS/2 DASD Mgr support */
-@@ -255,32 +226,23 @@
- /***********************************************************************
-               Host Adapter Control Structure
- ************************************************************************/
--typedef struct ORC_Ha_Ctrl_Struc {
--      USHORT HCS_Base;        /* 00 */
--      UBYTE HCS_Index;        /* 02 */
--      UBYTE HCS_Intr;         /* 04 */
--      UBYTE HCS_SCSI_ID;      /* 06    H/A SCSI ID */
--      UBYTE HCS_BIOS;         /* 07    BIOS configuration */
--
--      UBYTE HCS_Flags;        /* 0B */
--      UBYTE HCS_HAConfig1;    /* 1B    SCSI0MAXTags */
--      UBYTE HCS_MaxTar;       /* 1B    SCSI0MAXTags */
--
--      USHORT HCS_Units;       /* Number of units this adapter  */
--      USHORT HCS_AFlags;      /* Adapter info. defined flags   */
--      ULONG HCS_Timeout;      /* Adapter timeout value   */
--      ORC_SCB *HCS_virScbArray;       /* 28 Virtual Pointer to SCB array */
--      dma_addr_t HCS_physScbArray;    /* Scb Physical address */
--      ESCB *HCS_virEscbArray; /* Virtual pointer to ESCB Scatter list */
--      dma_addr_t HCS_physEscbArray;   /* scatter list Physical address */
--      UBYTE TargetFlag[16];   /* 30  target configuration, TCF_EN_TAG */
--      UBYTE MaximumTags[16];  /* 40  ORC_MAX_SCBS */
--      UBYTE ActiveTags[16][16];       /* 50 */
--      ORC_TCS HCS_Tcs[16];    /* 28 */
--      U32 BitAllocFlag[MAX_CHANNELS][8];      /* Max STB is 256, So 256/32 */
--      spinlock_t BitAllocFlagLock;
-+struct orc_host {
-+      unsigned long base;     /* Base address */
-+      u8 index;               /* Index (Channel)*/
-+      u8 scsi_id;             /* H/A SCSI ID */
-+      u8 BIOScfg;             /*BIOS configuration */
-+      u8 flags;
-+      u8 max_targets;         /* SCSI0MAXTags */
-+      struct orc_scb *scb_virt;       /* Virtual Pointer to SCB array */
-+      dma_addr_t scb_phys;    /* Scb Physical address */
-+      struct orc_extended_scb *escb_virt; /* Virtual pointer to ESCB Scatter list */
-+      dma_addr_t escb_phys;   /* scatter list Physical address */
-+      u8 target_flag[16];     /* target configuration, TCF_EN_TAG */
-+      u8 max_tags[16];        /* ORC_MAX_SCBS */
-+      u32 allocation_map[MAX_CHANNELS][8];    /* Max STB is 256, So 256/32 */
-+      spinlock_t allocation_lock;
-       struct pci_dev *pdev;
--} ORC_HCS;
-+};
+ #include "mmu_decl.h"
  
- /* Bit Definition for HCS_Flags */
+-struct hash_pte *Hash, *Hash_end;
++PTE *Hash, *Hash_end;
+ unsigned long Hash_size, Hash_mask;
+ unsigned long _SDR1;
  
-@@ -301,79 +263,79 @@
- #define       HCS_AF_DISABLE_RESET    0x10    /* Adapter disable reset  */
- #define       HCS_AF_DISABLE_ADPT     0x80    /* Adapter disable                */
+ union ubat {                  /* BAT register values to be loaded */
+-      struct ppc_bat bat;
++      BAT     bat;
+       u32     word[2];
+ } BATS[8][2];                 /* 8 pairs of IBAT, DBAT */
  
--typedef struct _NVRAM {
-+struct orc_nvram {
- /*----------header ---------------*/
--        UCHAR SubVendorID0;     /* 00 - Sub Vendor ID           */
--        UCHAR SubVendorID1;     /* 00 - Sub Vendor ID           */
--        UCHAR SubSysID0;        /* 02 - Sub System ID           */
--        UCHAR SubSysID1;        /* 02 - Sub System ID           */
--        UCHAR SubClass;         /* 04 - Sub Class               */
--        UCHAR VendorID0;        /* 05 - Vendor ID               */
--        UCHAR VendorID1;        /* 05 - Vendor ID               */
--        UCHAR DeviceID0;        /* 07 - Device ID               */
--        UCHAR DeviceID1;        /* 07 - Device ID               */
--        UCHAR Reserved0[2];     /* 09 - Reserved                */
--        UCHAR Revision;         /* 0B - Revision of data structure */
-+        u8 SubVendorID0;     /* 00 - Sub Vendor ID           */
-+        u8 SubVendorID1;     /* 00 - Sub Vendor ID           */
-+        u8 SubSysID0;        /* 02 - Sub System ID           */
-+        u8 SubSysID1;        /* 02 - Sub System ID           */
-+        u8 SubClass;         /* 04 - Sub Class               */
-+        u8 VendorID0;        /* 05 - Vendor ID               */
-+        u8 VendorID1;        /* 05 - Vendor ID               */
-+        u8 DeviceID0;        /* 07 - Device ID               */
-+        u8 DeviceID1;        /* 07 - Device ID               */
-+        u8 Reserved0[2];     /* 09 - Reserved                */
-+        u8 revision;         /* 0B - revision of data structure */
-         /* ----Host Adapter Structure ---- */
--        UCHAR NumOfCh;          /* 0C - Number of SCSI channel  */
--        UCHAR BIOSConfig1;      /* 0D - BIOS configuration 1    */
--        UCHAR BIOSConfig2;      /* 0E - BIOS boot channel&target ID */
--        UCHAR BIOSConfig3;      /* 0F - BIOS configuration 3    */
-+        u8 NumOfCh;          /* 0C - Number of SCSI channel  */
-+        u8 BIOSConfig1;      /* 0D - BIOS configuration 1    */
-+        u8 BIOSConfig2;      /* 0E - BIOS boot channel&target ID */
-+        u8 BIOSConfig3;      /* 0F - BIOS configuration 3    */
-         /* ----SCSI channel Structure ---- */
-         /* from "CTRL-I SCSI Host Adapter SetUp menu "  */
--        UCHAR SCSI0Id;          /* 10 - Channel 0 SCSI ID       */
--        UCHAR SCSI0Config;      /* 11 - Channel 0 SCSI configuration */
--        UCHAR SCSI0MaxTags;     /* 12 - Channel 0 Maximum tags  */
--        UCHAR SCSI0ResetTime;   /* 13 - Channel 0 Reset recovering time */
--        UCHAR ReservedforChannel0[2];   /* 14 - Reserved                */
-+        u8 scsi_id;          /* 10 - Channel 0 SCSI ID       */
-+        u8 SCSI0Config;      /* 11 - Channel 0 SCSI configuration */
-+        u8 SCSI0MaxTags;     /* 12 - Channel 0 Maximum tags  */
-+        u8 SCSI0ResetTime;   /* 13 - Channel 0 Reset recovering time */
-+        u8 ReservedforChannel0[2];   /* 14 - Reserved                */
+@@ -244,7 +245,7 @@
+       cacheable_memzero(Hash, Hash_size);
+       _SDR1 = __pa(Hash) | SDR1_LOW_BITS;
  
-         /* ----SCSI target Structure ----  */
-         /* from "CTRL-I SCSI device SetUp menu "                        */
--        UCHAR Target00Config;   /* 16 - Channel 0 Target 0 config */
--        UCHAR Target01Config;   /* 17 - Channel 0 Target 1 config */
--        UCHAR Target02Config;   /* 18 - Channel 0 Target 2 config */
--        UCHAR Target03Config;   /* 19 - Channel 0 Target 3 config */
--        UCHAR Target04Config;   /* 1A - Channel 0 Target 4 config */
--        UCHAR Target05Config;   /* 1B - Channel 0 Target 5 config */
--        UCHAR Target06Config;   /* 1C - Channel 0 Target 6 config */
--        UCHAR Target07Config;   /* 1D - Channel 0 Target 7 config */
--        UCHAR Target08Config;   /* 1E - Channel 0 Target 8 config */
--        UCHAR Target09Config;   /* 1F - Channel 0 Target 9 config */
--        UCHAR Target0AConfig;   /* 20 - Channel 0 Target A config */
--        UCHAR Target0BConfig;   /* 21 - Channel 0 Target B config */
--        UCHAR Target0CConfig;   /* 22 - Channel 0 Target C config */
--        UCHAR Target0DConfig;   /* 23 - Channel 0 Target D config */
--        UCHAR Target0EConfig;   /* 24 - Channel 0 Target E config */
--        UCHAR Target0FConfig;   /* 25 - Channel 0 Target F config */
--
--        UCHAR SCSI1Id;          /* 26 - Channel 1 SCSI ID       */
--        UCHAR SCSI1Config;      /* 27 - Channel 1 SCSI configuration */
--        UCHAR SCSI1MaxTags;     /* 28 - Channel 1 Maximum tags  */
--        UCHAR SCSI1ResetTime;   /* 29 - Channel 1 Reset recovering time */
--        UCHAR ReservedforChannel1[2];   /* 2A - Reserved                */
-+        u8 Target00Config;   /* 16 - Channel 0 Target 0 config */
-+        u8 Target01Config;   /* 17 - Channel 0 Target 1 config */
-+        u8 Target02Config;   /* 18 - Channel 0 Target 2 config */
-+        u8 Target03Config;   /* 19 - Channel 0 Target 3 config */
-+        u8 Target04Config;   /* 1A - Channel 0 Target 4 config */
-+        u8 Target05Config;   /* 1B - Channel 0 Target 5 config */
-+        u8 Target06Config;   /* 1C - Channel 0 Target 6 config */
-+        u8 Target07Config;   /* 1D - Channel 0 Target 7 config */
-+        u8 Target08Config;   /* 1E - Channel 0 Target 8 config */
-+        u8 Target09Config;   /* 1F - Channel 0 Target 9 config */
-+        u8 Target0AConfig;   /* 20 - Channel 0 Target A config */
-+        u8 Target0BConfig;   /* 21 - Channel 0 Target B config */
-+        u8 Target0CConfig;   /* 22 - Channel 0 Target C config */
-+        u8 Target0DConfig;   /* 23 - Channel 0 Target D config */
-+        u8 Target0EConfig;   /* 24 - Channel 0 Target E config */
-+        u8 Target0FConfig;   /* 25 - Channel 0 Target F config */
-+
-+        u8 SCSI1Id;          /* 26 - Channel 1 SCSI ID       */
-+        u8 SCSI1Config;      /* 27 - Channel 1 SCSI configuration */
-+        u8 SCSI1MaxTags;     /* 28 - Channel 1 Maximum tags  */
-+        u8 SCSI1ResetTime;   /* 29 - Channel 1 Reset recovering time */
-+        u8 ReservedforChannel1[2];   /* 2A - Reserved                */
+-      Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size);
++      Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
  
-         /* ----SCSI target Structure ----  */
-         /* from "CTRL-I SCSI device SetUp menu "                                          */
--        UCHAR Target10Config;   /* 2C - Channel 1 Target 0 config */
--        UCHAR Target11Config;   /* 2D - Channel 1 Target 1 config */
--        UCHAR Target12Config;   /* 2E - Channel 1 Target 2 config */
--        UCHAR Target13Config;   /* 2F - Channel 1 Target 3 config */
--        UCHAR Target14Config;   /* 30 - Channel 1 Target 4 config */
--        UCHAR Target15Config;   /* 31 - Channel 1 Target 5 config */
--        UCHAR Target16Config;   /* 32 - Channel 1 Target 6 config */
--        UCHAR Target17Config;   /* 33 - Channel 1 Target 7 config */
--        UCHAR Target18Config;   /* 34 - Channel 1 Target 8 config */
--        UCHAR Target19Config;   /* 35 - Channel 1 Target 9 config */
--        UCHAR Target1AConfig;   /* 36 - Channel 1 Target A config */
--        UCHAR Target1BConfig;   /* 37 - Channel 1 Target B config */
--        UCHAR Target1CConfig;   /* 38 - Channel 1 Target C config */
--        UCHAR Target1DConfig;   /* 39 - Channel 1 Target D config */
--        UCHAR Target1EConfig;   /* 3A - Channel 1 Target E config */
--        UCHAR Target1FConfig;   /* 3B - Channel 1 Target F config */
--        UCHAR reserved[3];      /* 3C - Reserved                */
-+        u8 Target10Config;   /* 2C - Channel 1 Target 0 config */
-+        u8 Target11Config;   /* 2D - Channel 1 Target 1 config */
-+        u8 Target12Config;   /* 2E - Channel 1 Target 2 config */
-+        u8 Target13Config;   /* 2F - Channel 1 Target 3 config */
-+        u8 Target14Config;   /* 30 - Channel 1 Target 4 config */
-+        u8 Target15Config;   /* 31 - Channel 1 Target 5 config */
-+        u8 Target16Config;   /* 32 - Channel 1 Target 6 config */
-+        u8 Target17Config;   /* 33 - Channel 1 Target 7 config */
-+        u8 Target18Config;   /* 34 - Channel 1 Target 8 config */
-+        u8 Target19Config;   /* 35 - Channel 1 Target 9 config */
-+        u8 Target1AConfig;   /* 36 - Channel 1 Target A config */
-+        u8 Target1BConfig;   /* 37 - Channel 1 Target B config */
-+        u8 Target1CConfig;   /* 38 - Channel 1 Target C config */
-+        u8 Target1DConfig;   /* 39 - Channel 1 Target D config */
-+        u8 Target1EConfig;   /* 3A - Channel 1 Target E config */
-+        u8 Target1FConfig;   /* 3B - Channel 1 Target F config */
-+        u8 reserved[3];      /* 3C - Reserved                */
-         /* ---------- CheckSum ----------       */
--        UCHAR CheckSum;         /* 3F - Checksum of NVRam       */
--} NVRAM, *PNVRAM;
-+        u8 CheckSum;         /* 3F - Checksum of NVRam       */
-+};
+       printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
+              total_memory >> 20, Hash_size >> 10, Hash);
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/tlb_32.c linux-2.6.22-570/arch/powerpc/mm/tlb_32.c
+--- linux-2.6.22-590/arch/powerpc/mm/tlb_32.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/tlb_32.c  2007-07-08 19:32:17.000000000 -0400
+@@ -11,6 +11,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  *  Derived from "arch/i386/mm/init.c"
+  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+diff -Nurb linux-2.6.22-590/arch/powerpc/mm/tlb_64.c linux-2.6.22-570/arch/powerpc/mm/tlb_64.c
+--- linux-2.6.22-590/arch/powerpc/mm/tlb_64.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/mm/tlb_64.c  2007-07-08 19:32:17.000000000 -0400
+@@ -8,6 +8,7 @@
+  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+  *    Copyright (C) 1996 Paul Mackerras
++ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+  *
+  *  Derived from "arch/i386/mm/init.c"
+  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+@@ -238,59 +239,3 @@
+       pte_free_submit(*batchp);
+       *batchp = NULL;
+ }
+-
+-/**
+- * __flush_hash_table_range - Flush all HPTEs for a given address range
+- *                            from the hash table (and the TLB). But keeps
+- *                            the linux PTEs intact.
+- *
+- * @mm                : mm_struct of the target address space (generally init_mm)
+- * @start     : starting address
+- * @end         : ending address (not included in the flush)
+- *
+- * This function is mostly to be used by some IO hotplug code in order
+- * to remove all hash entries from a given address range used to map IO
+- * space on a removed PCI-PCI bidge without tearing down the full mapping
+- * since 64K pages may overlap with other bridges when using 64K pages
+- * with 4K HW pages on IO space.
+- *
+- * Because of that usage pattern, it's only available with CONFIG_HOTPLUG
+- * and is implemented for small size rather than speed.
+- */
+-#ifdef CONFIG_HOTPLUG
+-
+-void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
+-                            unsigned long end)
+-{
+-      unsigned long flags;
+-
+-      start = _ALIGN_DOWN(start, PAGE_SIZE);
+-      end = _ALIGN_UP(end, PAGE_SIZE);
+-
+-      BUG_ON(!mm->pgd);
+-
+-      /* Note: Normally, we should only ever use a batch within a
+-       * PTE locked section. This violates the rule, but will work
+-       * since we don't actually modify the PTEs, we just flush the
+-       * hash while leaving the PTEs intact (including their reference
+-       * to being hashed). This is not the most performance oriented
+-       * way to do things but is fine for our needs here.
+-       */
+-      local_irq_save(flags);
+-      arch_enter_lazy_mmu_mode();
+-      for (; start < end; start += PAGE_SIZE) {
+-              pte_t *ptep = find_linux_pte(mm->pgd, start);
+-              unsigned long pte;
+-
+-              if (ptep == NULL)
+-                      continue;
+-              pte = pte_val(*ptep);
+-              if (!(pte & _PAGE_HASHPTE))
+-                      continue;
+-              hpte_need_flush(mm, start, ptep, pte, 0);
+-      }
+-      arch_leave_lazy_mmu_mode();
+-      local_irq_restore(flags);
+-}
+-
+-#endif /* CONFIG_HOTPLUG */
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/Kconfig linux-2.6.22-570/arch/powerpc/platforms/Kconfig
+--- linux-2.6.22-590/arch/powerpc/platforms/Kconfig    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/Kconfig    2007-07-08 19:32:17.000000000 -0400
+@@ -16,6 +16,13 @@
+       bool "Embedded 6xx/7xx/7xxx-based board"
+       depends on PPC32 && (BROKEN||BROKEN_ON_SMP)
  
- /* Bios Configuration for nvram->BIOSConfig1                            */
- #define NBC_BIOSENABLE  0x01    /* BIOS enable                    */
-@@ -407,10 +369,3 @@
- #define NCC_RESET_TIME  0x0A    /* SCSI RESET recovering time     */
- #define NTC_DEFAULT     (NTC_1GIGA | NTC_NO_WIDESYNC | NTC_DISC_ENABLE)
++config APUS
++      bool "Amiga-APUS"
++      depends on PPC32 && BROKEN
++      help
++        Select APUS if configuring for a PowerUP Amiga.
++        More information is available at:
++        <http://linux-apus.sourceforge.net/>.
+ endchoice
  
--#define ORC_RD(x,y)             (UCHAR)(inb(  (int)((ULONG)((ULONG)x+(UCHAR)y)) ))
--#define ORC_RDWORD(x,y)         (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
--#define ORC_RDLONG(x,y)         (long)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
+ source "arch/powerpc/platforms/pseries/Kconfig"
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/Kconfig.cputype linux-2.6.22-570/arch/powerpc/platforms/Kconfig.cputype
+--- linux-2.6.22-590/arch/powerpc/platforms/Kconfig.cputype    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/Kconfig.cputype    1969-12-31 19:00:00.000000000 -0500
+@@ -1,252 +0,0 @@
+-config PPC64
+-      bool "64-bit kernel"
+-      default n
+-      help
+-        This option selects whether a 32-bit or a 64-bit kernel
+-        will be built.
+-
+-menu "Processor support"
+-choice
+-      prompt "Processor Type"
+-      depends on PPC32
+-      default 6xx
+-
+-config CLASSIC32
+-      bool "52xx/6xx/7xx/74xx"
+-      select PPC_FPU
+-      select 6xx
+-      help
+-        There are four families of PowerPC chips supported.  The more common
+-        types (601, 603, 604, 740, 750, 7400), the Motorola embedded
+-        versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC
+-        embedded versions (403 and 405) and the high end 64 bit Power
+-        processors (POWER 3, POWER4, and IBM PPC970 also known as G5).
+-
+-        This option is the catch-all for 6xx types, including some of the
+-        embedded versions.  Unless there is see an option for the specific
+-        chip family you are using, you want this option.
+-
+-        You do not want this if you are building a kernel for a 64 bit
+-        IBM RS/6000 or an Apple G5, choose 6xx.
+-
+-        If unsure, select this option
+-
+-        Note that the kernel runs in 32-bit mode even on 64-bit chips.
+-
+-config PPC_82xx
+-      bool "Freescale 82xx"
+-      select 6xx
+-      select PPC_FPU
+-
+-config PPC_83xx
+-      bool "Freescale 83xx"
+-      select 6xx
+-      select FSL_SOC
+-      select 83xx
+-      select PPC_FPU
+-      select WANT_DEVICE_TREE
+-
+-config PPC_85xx
+-      bool "Freescale 85xx"
+-      select E500
+-      select FSL_SOC
+-      select 85xx
+-      select WANT_DEVICE_TREE
+-
+-config PPC_86xx
+-      bool "Freescale 86xx"
+-      select 6xx
+-      select FSL_SOC
+-      select FSL_PCIE
+-      select PPC_FPU
+-      select ALTIVEC
+-      help
+-        The Freescale E600 SoCs have 74xx cores.
+-
+-config PPC_8xx
+-      bool "Freescale 8xx"
+-      select FSL_SOC
+-      select 8xx
+-
+-config 40x
+-      bool "AMCC 40x"
+-      select PPC_DCR_NATIVE
+-
+-config 44x
+-      bool "AMCC 44x"
+-      select PPC_DCR_NATIVE
+-      select WANT_DEVICE_TREE
+-
+-config E200
+-      bool "Freescale e200"
+-
+-endchoice
+-
+-config POWER4_ONLY
+-      bool "Optimize for POWER4"
+-      depends on PPC64
+-      default n
+-      ---help---
+-        Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
+-        The resulting binary will not work on POWER3 or RS64 processors
+-        when compiled with binutils 2.15 or later.
+-
+-config POWER3
+-      bool
+-      depends on PPC64
+-      default y if !POWER4_ONLY
+-
+-config POWER4
+-      depends on PPC64
+-      def_bool y
+-
+-config 6xx
+-      bool
+-
+-# this is temp to handle compat with arch=ppc
+-config 8xx
+-      bool
+-
+-# this is temp to handle compat with arch=ppc
+-config 83xx
+-      bool
+-
+-# this is temp to handle compat with arch=ppc
+-config 85xx
+-      bool
+-
+-config E500
+-      bool
+-
+-config PPC_FPU
+-      bool
+-      default y if PPC64
+-
+-config 4xx
+-      bool
+-      depends on 40x || 44x
+-      default y
+-
+-config BOOKE
+-      bool
+-      depends on E200 || E500 || 44x
+-      default y
+-
+-config FSL_BOOKE
+-      bool
+-      depends on E200 || E500
+-      default y
+-
+-config PTE_64BIT
+-      bool
+-      depends on 44x || E500
+-      default y if 44x
+-      default y if E500 && PHYS_64BIT
+-
+-config PHYS_64BIT
+-      bool 'Large physical address support' if E500
+-      depends on 44x || E500
+-      select RESOURCES_64BIT
+-      default y if 44x
+-      ---help---
+-        This option enables kernel support for larger than 32-bit physical
+-        addresses.  This features is not be available on all e500 cores.
+-
+-        If in doubt, say N here.
+-
+-config ALTIVEC
+-      bool "AltiVec Support"
+-      depends on CLASSIC32 || POWER4
+-      ---help---
+-        This option enables kernel support for the Altivec extensions to the
+-        PowerPC processor. The kernel currently supports saving and restoring
+-        altivec registers, and turning on the 'altivec enable' bit so user
+-        processes can execute altivec instructions.
+-
+-        This option is only usefully if you have a processor that supports
+-        altivec (G4, otherwise known as 74xx series), but does not have
+-        any affect on a non-altivec cpu (it does, however add code to the
+-        kernel).
+-
+-        If in doubt, say Y here.
+-
+-config SPE
+-      bool "SPE Support"
+-      depends on E200 || E500
+-      default y
+-      ---help---
+-        This option enables kernel support for the Signal Processing
+-        Extensions (SPE) to the PowerPC processor. The kernel currently
+-        supports saving and restoring SPE registers, and turning on the
+-        'spe enable' bit so user processes can execute SPE instructions.
+-
+-        This option is only useful if you have a processor that supports
+-        SPE (e500, otherwise known as 85xx series), but does not have any
+-        effect on a non-spe cpu (it does, however add code to the kernel).
+-
+-        If in doubt, say Y here.
+-
+-config PPC_STD_MMU
+-      bool
+-      depends on 6xx || POWER3 || POWER4 || PPC64
+-      default y
+-
+-config PPC_STD_MMU_32
+-      def_bool y
+-      depends on PPC_STD_MMU && PPC32
+-
+-config PPC_MM_SLICES
+-      bool
+-      default y if HUGETLB_PAGE
+-      default n
+-
+-config VIRT_CPU_ACCOUNTING
+-      bool "Deterministic task and CPU time accounting"
+-      depends on PPC64
+-      default y
+-      help
+-        Select this option to enable more accurate task and CPU time
+-        accounting.  This is done by reading a CPU counter on each
+-        kernel entry and exit and on transitions within the kernel
+-        between system, softirq and hardirq state, so there is a
+-        small performance impact.  This also enables accounting of
+-        stolen time on logically-partitioned systems running on
+-        IBM POWER5-based machines.
+-
+-        If in doubt, say Y here.
+-
+-config SMP
+-      depends on PPC_STD_MMU
+-      bool "Symmetric multi-processing support"
+-      ---help---
+-        This enables support for systems with more than one CPU. If you have
+-        a system with only one CPU, say N. If you have a system with more
+-        than one CPU, say Y.  Note that the kernel does not currently
+-        support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
+-        since they have inadequate hardware support for multiprocessor
+-        operation.
+-
+-        If you say N here, the kernel will run on single and multiprocessor
+-        machines, but will use only one CPU of a multiprocessor machine. If
+-        you say Y here, the kernel will run on single-processor machines.
+-        On a single-processor machine, the kernel will run faster if you say
+-        N here.
+-
+-        If you don't know what to do here, say N.
 -
--#define ORC_WR(     adr,data)   outb( (UCHAR)(data), (int)(adr))
--#define ORC_WRSHORT(adr,data)   outw( (UWORD)(data), (int)(adr))
--#define ORC_WRLONG( adr,data)   outl( (ULONG)(data), (int)(adr))
-diff -Nurb linux-2.6.22-570/drivers/scsi/a4000t.c linux-2.6.22-590/drivers/scsi/a4000t.c
---- linux-2.6.22-570/drivers/scsi/a4000t.c     1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/scsi/a4000t.c     2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,143 @@
-+/*
-+ * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
-+ *            Amiga Technologies A4000T SCSI controller.
-+ *
-+ * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
-+ * plus modifications of the 53c7xx.c driver to support the Amiga.
-+ *
-+ * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <asm/amigahw.h>
-+#include <asm/amigaints.h>
-+#include <scsi/scsi_host.h>
-+#include <scsi/scsi_transport_spi.h>
-+
-+#include "53c700.h"
-+
-+MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>");
-+MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver");
-+MODULE_LICENSE("GPL");
-+
-+
-+static struct scsi_host_template a4000t_scsi_driver_template = {
-+      .name           = "A4000T builtin SCSI",
-+      .proc_name      = "A4000t",
-+      .this_id        = 7,
-+      .module         = THIS_MODULE,
-+};
-+
-+static struct platform_device *a4000t_scsi_device;
-+
-+#define A4000T_SCSI_ADDR 0xdd0040
-+
-+static int __devinit a4000t_probe(struct device *dev)
-+{
-+      struct Scsi_Host * host = NULL;
-+      struct NCR_700_Host_Parameters *hostdata;
-+
-+      if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI)))
-+              goto out;
-+
-+      if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000,
-+                              "A4000T builtin SCSI"))
-+              goto out;
-+
-+      hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
-+      if (hostdata == NULL) {
-+              printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n");
-+              goto out_release;
-+      }
-+      memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
-+
-+      /* Fill in the required pieces of hostdata */
-+      hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR);
-+      hostdata->clock = 50;
-+      hostdata->chip710 = 1;
-+      hostdata->dmode_extra = DMODE_FC2;
-+      hostdata->dcntl_extra = EA_710;
-+
-+      /* and register the chip */
-+      host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, dev);
-+      if (!host) {
-+              printk(KERN_ERR "a4000t-scsi: No host detected; "
-+                              "board configuration problem?\n");
-+              goto out_free;
-+      }
-+
-+      host->this_id = 7;
-+      host->base = A4000T_SCSI_ADDR;
-+      host->irq = IRQ_AMIGA_PORTS;
-+
-+      if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi",
-+                      host)) {
-+              printk(KERN_ERR "a4000t-scsi: request_irq failed\n");
-+              goto out_put_host;
-+      }
-+
-+      scsi_scan_host(host);
+-config NR_CPUS
+-      int "Maximum number of CPUs (2-128)"
+-      range 2 128
+-      depends on SMP
+-      default "32" if PPC64
+-      default "4"
+-
+-config NOT_COHERENT_CACHE
+-      bool
+-      depends on 4xx || 8xx || E200
+-      default y
+-
+-config CONFIG_CHECK_CACHE_COHERENCY
+-      bool
+-
+-endmenu
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/apus/Kconfig linux-2.6.22-570/arch/powerpc/platforms/apus/Kconfig
+--- linux-2.6.22-590/arch/powerpc/platforms/apus/Kconfig       1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/apus/Kconfig       2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,130 @@
 +
-+      return 0;
++config AMIGA
++      bool
++      depends on APUS
++      default y
++      help
++        This option enables support for the Amiga series of computers.
 +
-+ out_put_host:
-+      scsi_host_put(host);
-+ out_free:
-+      kfree(hostdata);
-+ out_release:
-+      release_mem_region(A4000T_SCSI_ADDR, 0x1000);
-+ out:
-+      return -ENODEV;
-+}
++config ZORRO
++      bool
++      depends on APUS
++      default y
++      help
++        This enables support for the Zorro bus in the Amiga. If you have
++        expansion cards in your Amiga that conform to the Amiga
++        AutoConfig(tm) specification, say Y, otherwise N. Note that even
++        expansion cards that do not fit in the Zorro slots but fit in e.g.
++        the CPU slot may fall in this category, so you have to say Y to let
++        Linux use these.
++
++config ABSTRACT_CONSOLE
++      bool
++      depends on APUS
++      default y
 +
-+static __devexit int a4000t_device_remove(struct device *dev)
-+{
-+      struct Scsi_Host *host = dev_to_shost(dev);
-+      struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
++config APUS_FAST_EXCEPT
++      bool
++      depends on APUS
++      default y
 +
-+      scsi_remove_host(host);
++config AMIGA_PCMCIA
++      bool "Amiga 1200/600 PCMCIA support"
++      depends on APUS && EXPERIMENTAL
++      help
++        Include support in the kernel for pcmcia on Amiga 1200 and Amiga
++        600. If you intend to use pcmcia cards say Y; otherwise say N.
 +
-+      NCR_700_release(host);
-+      kfree(hostdata);
-+      free_irq(host->irq, host);
-+      release_mem_region(A4000T_SCSI_ADDR, 0x1000);
++config AMIGA_BUILTIN_SERIAL
++      tristate "Amiga builtin serial support"
++      depends on APUS
++      help
++        If you want to use your Amiga's built-in serial port in Linux,
++        answer Y.
 +
-+      return 0;
-+}
++        To compile this driver as a module, choose M here.
 +
-+static struct device_driver a4000t_scsi_driver = {
-+      .name   = "a4000t-scsi",
-+      .bus    = &platform_bus_type,
-+      .probe  = a4000t_probe,
-+      .remove = __devexit_p(a4000t_device_remove),
-+};
++config GVPIOEXT
++      tristate "GVP IO-Extender support"
++      depends on APUS
++      help
++        If you want to use a GVP IO-Extender serial card in Linux, say Y.
++        Otherwise, say N.
 +
-+static int __init a4000t_scsi_init(void)
-+{
-+      int err;
++config GVPIOEXT_LP
++      tristate "GVP IO-Extender parallel printer support"
++      depends on GVPIOEXT
++      help
++        Say Y to enable driving a printer from the parallel port on your
++        GVP IO-Extender card, N otherwise.
 +
-+      err = driver_register(&a4000t_scsi_driver);
-+      if (err)
-+              return err;
++config GVPIOEXT_PLIP
++      tristate "GVP IO-Extender PLIP support"
++      depends on GVPIOEXT
++      help
++        Say Y to enable doing IP over the parallel port on your GVP
++        IO-Extender card, N otherwise.
 +
-+      a4000t_scsi_device = platform_device_register_simple("a4000t-scsi",
-+                      -1, NULL, 0);
-+      if (IS_ERR(a4000t_scsi_device)) {
-+              driver_unregister(&a4000t_scsi_driver);
-+              return PTR_ERR(a4000t_scsi_device);
-+      }
++config MULTIFACE_III_TTY
++      tristate "Multiface Card III serial support"
++      depends on APUS
++      help
++        If you want to use a Multiface III card's serial port in Linux,
++        answer Y.
 +
-+      return err;
-+}
++        To compile this driver as a module, choose M here.
 +
-+static void __exit a4000t_scsi_exit(void)
-+{
-+      platform_device_unregister(a4000t_scsi_device);
-+      driver_unregister(&a4000t_scsi_driver);
-+}
++config A2232
++      tristate "Commodore A2232 serial support (EXPERIMENTAL)"
++      depends on EXPERIMENTAL && APUS
++      ---help---
++        This option supports the 2232 7-port serial card shipped with the
++        Amiga 2000 and other Zorro-bus machines, dating from 1989.  At
++        a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
++        each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
++        ports were connected with 8 pin DIN connectors on the card bracket,
++        for which 8 pin to DB25 adapters were supplied. The card also had
++        jumpers internally to toggle various pinning configurations.
++
++        This driver can be built as a module; but then "generic_serial"
++        will also be built as a module. This has to be loaded before
++        "ser_a2232". If you want to do this, answer M here.
++
++config WHIPPET_SERIAL
++      tristate "Hisoft Whippet PCMCIA serial support"
++      depends on AMIGA_PCMCIA
++      help
++        HiSoft has a web page at <http://www.hisoft.co.uk/>, but there
++        is no listing for the Whippet in their Amiga section.
 +
-+module_init(a4000t_scsi_init);
-+module_exit(a4000t_scsi_exit);
-diff -Nurb linux-2.6.22-570/drivers/scsi/aacraid/aachba.c linux-2.6.22-590/drivers/scsi/aacraid/aachba.c
---- linux-2.6.22-570/drivers/scsi/aacraid/aachba.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/aacraid/aachba.c     2008-01-02 13:56:37.000000000 -0500
-@@ -169,6 +169,18 @@
- module_param(acbsize, int, S_IRUGO|S_IWUSR);
- MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware.");
-+int update_interval = 30 * 60;
-+module_param(update_interval, int, S_IRUGO|S_IWUSR);
-+MODULE_PARM_DESC(update_interval, "Interval in seconds between time sync updates issued to adapter.");
++config APNE
++      tristate "PCMCIA NE2000 support"
++      depends on AMIGA_PCMCIA
++      help
++        If you have a PCMCIA NE2000 compatible adapter, say Y.  Otherwise,
++        say N.
 +
-+int check_interval = 24 * 60 * 60;
-+module_param(check_interval, int, S_IRUGO|S_IWUSR);
-+MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health checks.");
++        To compile this driver as a module, choose M here: the
++        module will be called apne.
 +
-+int check_reset = 1;
-+module_param(check_reset, int, S_IRUGO|S_IWUSR);
-+MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the adapter.");
++config SERIAL_CONSOLE
++      bool "Support for serial port console"
++      depends on APUS && (AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y)
 +
- int expose_physicals = -1;
- module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
- MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on");
-@@ -312,11 +324,10 @@
++config HEARTBEAT
++      bool "Use power LED as a heartbeat"
++      depends on APUS
++      help
++        Use the power-on LED on your machine as a load meter.  The exact
++        behavior is platform-dependent, but normally the flash frequency is
++        a hyperbolic function of the 5-minute load average.
++
++config PROC_HARDWARE
++      bool "/proc/hardware support"
++      depends on APUS
++
++source "drivers/zorro/Kconfig"
++
++config PCI_PERMEDIA
++      bool "PCI for Permedia2"
++      depends on !4xx && !8xx && APUS
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/cell/io-workarounds.c linux-2.6.22-570/arch/powerpc/platforms/cell/io-workarounds.c
+--- linux-2.6.22-590/arch/powerpc/platforms/cell/io-workarounds.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/cell/io-workarounds.c      2007-07-08 19:32:17.000000000 -0400
+@@ -102,7 +102,7 @@
+               vaddr = (unsigned long)PCI_FIX_ADDR(addr);
  
-       if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
-               maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
--      fsa_dev_ptr =  kmalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers,
-+      fsa_dev_ptr = kzalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers,
-                       GFP_KERNEL);
-       if (!fsa_dev_ptr)
-               return -ENOMEM;
--      memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers);
+               /* Check if it's in allowed range for  PIO */
+-              if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END)
++              if (vaddr < PHBS_IO_BASE || vaddr >= IMALLOC_BASE)
+                       return;
  
-       dev->fsa_dev = fsa_dev_ptr;
-       dev->maximum_num_containers = maximum_num_containers;
-@@ -344,20 +355,15 @@
- {
-       void *buf;
-       int transfer_len;
--      struct scatterlist *sg = scsicmd->request_buffer;
-+      struct scatterlist *sg = scsi_sglist(scsicmd);
+               /* Try to find a PTE. If not, clear the paddr, we'll do
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/cell/spufs/file.c linux-2.6.22-570/arch/powerpc/platforms/cell/spufs/file.c
+--- linux-2.6.22-590/arch/powerpc/platforms/cell/spufs/file.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/cell/spufs/file.c  2007-07-08 19:32:17.000000000 -0400
+@@ -28,7 +28,6 @@
+ #include <linux/pagemap.h>
+ #include <linux/poll.h>
+ #include <linux/ptrace.h>
+-#include <linux/seq_file.h>
  
--      if (scsicmd->use_sg) {
-               buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
-               transfer_len = min(sg->length, len + offset);
--      } else {
--              buf = scsicmd->request_buffer;
--              transfer_len = min(scsicmd->request_bufflen, len + offset);
--      }
-+
-       transfer_len -= offset;
-       if (buf && transfer_len > 0)
-               memcpy(buf + offset, data, transfer_len);
+ #include <asm/io.h>
+ #include <asm/semaphore.h>
+@@ -40,7 +39,6 @@
  
--      if (scsicmd->use_sg) 
-               kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
  
- }
-@@ -451,7 +457,7 @@
+-
+ static int
+ spufs_mem_open(struct inode *inode, struct file *file)
  {
-       struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
--      if (fsa_dev_ptr[scmd_id(scsicmd)].valid)
-+      if ((fsa_dev_ptr[scmd_id(scsicmd)].valid & 1))
-               return aac_scsi_cmd(scsicmd);
-       scsicmd->result = DID_NO_CONNECT << 16;
-@@ -459,18 +465,18 @@
+@@ -1799,29 +1797,6 @@
        return 0;
  }
  
--static int _aac_probe_container2(void * context, struct fib * fibptr)
-+static void _aac_probe_container2(void * context, struct fib * fibptr)
- {
-       struct fsa_dev_info *fsa_dev_ptr;
-       int (*callback)(struct scsi_cmnd *);
-       struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context;
--      if (!aac_valid_context(scsicmd, fibptr))
--              return 0;
--      fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
-+      if (!aac_valid_context(scsicmd, fibptr))
-+              return;
-       scsicmd->SCp.Status = 0;
-+      fsa_dev_ptr = fibptr->dev->fsa_dev;
-       if (fsa_dev_ptr) {
-               struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr);
-               fsa_dev_ptr += scmd_id(scsicmd);
-@@ -493,10 +499,11 @@
-       aac_fib_free(fibptr);
-       callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr);
-       scsicmd->SCp.ptr = NULL;
--      return (*callback)(scsicmd);
-+      (*callback)(scsicmd);
-+      return;
- }
--static int _aac_probe_container1(void * context, struct fib * fibptr)
-+static void _aac_probe_container1(void * context, struct fib * fibptr)
- {
-       struct scsi_cmnd * scsicmd;
-       struct aac_mount * dresp;
-@@ -506,13 +513,14 @@
-       dresp = (struct aac_mount *) fib_data(fibptr);
-       dresp->mnt[0].capacityhigh = 0;
-       if ((le32_to_cpu(dresp->status) != ST_OK) ||
--          (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE))
--              return _aac_probe_container2(context, fibptr);
-+          (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
-+              _aac_probe_container2(context, fibptr);
-+              return;
-+      }
-       scsicmd = (struct scsi_cmnd *) context;
--      scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
-       if (!aac_valid_context(scsicmd, fibptr))
--              return 0;
-+              return;
-       aac_fib_init(fibptr);
-@@ -527,21 +535,18 @@
-                         sizeof(struct aac_query_mount),
-                         FsaNormal,
-                         0, 1,
--                        (fib_callback) _aac_probe_container2,
-+                        _aac_probe_container2,
-                         (void *) scsicmd);
-       /*
-        *      Check that the command queued to the controller
-        */
--      if (status == -EINPROGRESS) {
-+      if (status == -EINPROGRESS)
-               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
--              return 0;
--      }
--      if (status < 0) {
-+      else if (status < 0) {
-               /* Inherit results from VM_NameServe, if any */
-               dresp->status = cpu_to_le32(ST_OK);
--              return _aac_probe_container2(context, fibptr);
-+              _aac_probe_container2(context, fibptr);
-       }
+-static int spufs_caps_show(struct seq_file *s, void *private)
+-{
+-      struct spu_context *ctx = s->private;
+-
+-      if (!(ctx->flags & SPU_CREATE_NOSCHED))
+-              seq_puts(s, "sched\n");
+-      if (!(ctx->flags & SPU_CREATE_ISOLATE))
+-              seq_puts(s, "step\n");
 -      return 0;
- }
- static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
-@@ -566,7 +571,7 @@
-                         sizeof(struct aac_query_mount),
-                         FsaNormal,
-                         0, 1,
--                        (fib_callback) _aac_probe_container1,
-+                        _aac_probe_container1,
-                         (void *) scsicmd);
-               /*
-                *      Check that the command queued to the controller
-@@ -620,7 +625,7 @@
-               return -ENOMEM;
-       }
-       scsicmd->list.next = NULL;
--      scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))_aac_probe_container1;
-+      scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))aac_probe_container_callback1;
-       scsicmd->device = scsidev;
-       scsidev->sdev_state = 0;
-@@ -825,7 +830,7 @@
-       readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
-       readcmd->count = cpu_to_le32(count<<9);
-       readcmd->cid = cpu_to_le16(scmd_id(cmd));
--      readcmd->flags = cpu_to_le16(1);
-+      readcmd->flags = cpu_to_le16(IO_TYPE_READ);
-       readcmd->bpTotal = 0;
-       readcmd->bpComplete = 0;
-@@ -904,7 +909,7 @@
-                         (void *) cmd);
- }
--static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
-+static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
- {
-       u16 fibsize;
-       struct aac_raw_io *writecmd;
-@@ -914,7 +919,9 @@
-       writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
-       writecmd->count = cpu_to_le32(count<<9);
-       writecmd->cid = cpu_to_le16(scmd_id(cmd));
--      writecmd->flags = 0;
-+      writecmd->flags = fua ?
-+              cpu_to_le16(IO_TYPE_WRITE|IO_SUREWRITE) :
-+              cpu_to_le16(IO_TYPE_WRITE);
-       writecmd->bpTotal = 0;
-       writecmd->bpComplete = 0;
-@@ -933,7 +940,7 @@
-                         (void *) cmd);
- }
--static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
-+static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
- {
-       u16 fibsize;
-       struct aac_write64 *writecmd;
-@@ -964,7 +971,7 @@
-                         (void *) cmd);
- }
--static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
-+static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
- {
-       u16 fibsize;
-       struct aac_write *writecmd;
-@@ -1041,7 +1048,7 @@
-       struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
-       aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg);
--      srbcmd->count = cpu_to_le32(cmd->request_bufflen);
-+      srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
-       memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
-       memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
-@@ -1069,7 +1076,7 @@
-       struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
-       aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg);
--      srbcmd->count = cpu_to_le32(cmd->request_bufflen);
-+      srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
-       memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
-       memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
-@@ -1172,6 +1179,7 @@
-       }
-       if (!dev->in_reset) {
-+              char buffer[16];
-               tmp = le32_to_cpu(dev->adapter_info.kernelrev);
-               printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n",
-                       dev->name, 
-@@ -1192,16 +1200,23 @@
-                       dev->name, dev->id,
-                       tmp>>24,(tmp>>16)&0xff,tmp&0xff,
-                       le32_to_cpu(dev->adapter_info.biosbuild));
--              if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
--                      printk(KERN_INFO "%s%d: serial %x\n",
--                              dev->name, dev->id,
--                              le32_to_cpu(dev->adapter_info.serial[0]));
-+              buffer[0] = '\0';
-+              if (aac_show_serial_number(
-+                shost_to_class(dev->scsi_host_ptr), buffer))
-+                      printk(KERN_INFO "%s%d: serial %s",
-+                        dev->name, dev->id, buffer);
-               if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) {
-                       printk(KERN_INFO "%s%d: TSID %.*s\n",
-                         dev->name, dev->id,
-                         (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid),
-                         dev->supplement_adapter_info.VpdInfo.Tsid);
-               }
-+              if (!check_reset ||
-+                (dev->supplement_adapter_info.SupportedOptions2 &
-+                le32_to_cpu(AAC_OPTION_IGNORE_RESET))) {
-+                      printk(KERN_INFO "%s%d: Reset Adapter Ignored\n",
-+                        dev->name, dev->id);
-+              }
-       }
-       dev->nondasd_support = 0;
-@@ -1332,7 +1347,7 @@
-       if (!aac_valid_context(scsicmd, fibptr))
-               return;
--      dev = (struct aac_dev *)scsicmd->device->host->hostdata;
-+      dev = fibptr->dev;
-       cid = scmd_id(scsicmd);
-       if (nblank(dprintk(x))) {
-@@ -1372,15 +1387,8 @@
-       BUG_ON(fibptr == NULL);
-               
--      if(scsicmd->use_sg)
--              pci_unmap_sg(dev->pdev, 
--                      (struct scatterlist *)scsicmd->request_buffer,
--                      scsicmd->use_sg,
--                      scsicmd->sc_data_direction);
--      else if(scsicmd->request_bufflen)
--              pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle,
--                               scsicmd->request_bufflen,
--                               scsicmd->sc_data_direction);
-+      scsi_dma_unmap(scsicmd);
-+
-       readreply = (struct aac_read_reply *)fib_data(fibptr);
-       if (le32_to_cpu(readreply->status) == ST_OK)
-               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
-@@ -1498,6 +1506,7 @@
- {
-       u64 lba;
-       u32 count;
-+      int fua;
-       int status;
-       struct aac_dev *dev;
-       struct fib * cmd_fibcontext;
-@@ -1512,6 +1521,7 @@
-               count = scsicmd->cmnd[4];
-               if (count == 0)
-                       count = 256;
-+              fua = 0;
-       } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */
-               dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd)));
-@@ -1524,6 +1534,7 @@
-                       (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
-               count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) |
-                       (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
-+              fua = scsicmd->cmnd[1] & 0x8;
-       } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */
-               dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd)));
-@@ -1531,10 +1542,12 @@
-                   | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
-               count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16)
-                     | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
-+              fua = scsicmd->cmnd[1] & 0x8;
-       } else {
-               dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd)));
-               lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
-               count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
-+              fua = scsicmd->cmnd[1] & 0x8;
-       }
-       dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
-         smp_processor_id(), (unsigned long long)lba, jiffies));
-@@ -1549,7 +1562,7 @@
-               return 0;
-       }
--      status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count);
-+      status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua);
-       /*
-        *      Check that the command queued to the controller
-@@ -1592,7 +1605,7 @@
-                       COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
-       else {
-               struct scsi_device *sdev = cmd->device;
--              struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
-+              struct aac_dev *dev = fibptr->dev;
-               u32 cid = sdev_id(sdev);
-               printk(KERN_WARNING 
-                    "synchronize_callback: synchronize failed, status = %d\n",
-@@ -1699,7 +1712,7 @@
-  
- int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
- {
--      u32 cid = 0;
-+      u32 cid;
-       struct Scsi_Host *host = scsicmd->device->host;
-       struct aac_dev *dev = (struct aac_dev *)host->hostdata;
-       struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
-@@ -1711,15 +1724,15 @@
-        *      Test does not apply to ID 16, the pseudo id for the controller
-        *      itself.
-        */
--      if (scmd_id(scsicmd) != host->this_id) {
--              if ((scmd_channel(scsicmd) == CONTAINER_CHANNEL)) {
--                      if((scmd_id(scsicmd) >= dev->maximum_num_containers) ||
-+      cid = scmd_id(scsicmd);
-+      if (cid != host->this_id) {
-+              if (scmd_channel(scsicmd) == CONTAINER_CHANNEL) {
-+                      if((cid >= dev->maximum_num_containers) ||
-                                       (scsicmd->device->lun != 0)) {
-                               scsicmd->result = DID_NO_CONNECT << 16;
-                               scsicmd->scsi_done(scsicmd);
-                               return 0;
-                       }
--                      cid = scmd_id(scsicmd);
-                       /*
-                        *      If the target container doesn't exist, it may have
-@@ -1782,7 +1795,7 @@
-       {
-               struct inquiry_data inq_data;
--              dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scmd_id(scsicmd)));
-+              dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid));
-               memset(&inq_data, 0, sizeof (struct inquiry_data));
-               inq_data.inqd_ver = 2;  /* claim compliance to SCSI-2 */
-@@ -1794,7 +1807,7 @@
-                *      Set the Vendor, Product, and Revision Level
-                *      see: <vendor>.c i.e. aac.c
-                */
--              if (scmd_id(scsicmd) == host->this_id) {
-+              if (cid == host->this_id) {
-                       setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types));
-                       inq_data.inqd_pdt = INQD_PDT_PROC;      /* Processor device */
-                       aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
-@@ -1886,15 +1899,29 @@
-       case MODE_SENSE:
-       {
--              char mode_buf[4];
-+              char mode_buf[7];
-+              int mode_buf_length = 4;
-               dprintk((KERN_DEBUG "MODE SENSE command.\n"));
-               mode_buf[0] = 3;        /* Mode data length */
-               mode_buf[1] = 0;        /* Medium type - default */
--              mode_buf[2] = 0;        /* Device-specific param, bit 8: 0/1 = write enabled/protected */
-+              mode_buf[2] = 0;        /* Device-specific param,
-+                                         bit 8: 0/1 = write enabled/protected
-+                                         bit 4: 0/1 = FUA enabled */
-+              if (dev->raw_io_interface)
-+                      mode_buf[2] = 0x10;
-               mode_buf[3] = 0;        /* Block descriptor length */
+-}
 -
--              aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
-+              if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
-+                ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
-+                      mode_buf[0] = 6;
-+                      mode_buf[4] = 8;
-+                      mode_buf[5] = 1;
-+                      mode_buf[6] = 0x04; /* WCE */
-+                      mode_buf_length = 7;
-+                      if (mode_buf_length > scsicmd->cmnd[4])
-+                              mode_buf_length = scsicmd->cmnd[4];
-+              }
-+              aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
-               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
-               scsicmd->scsi_done(scsicmd);
-@@ -1902,18 +1929,33 @@
-       }
-       case MODE_SENSE_10:
-       {
--              char mode_buf[8];
-+              char mode_buf[11];
-+              int mode_buf_length = 8;
-               dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));
-               mode_buf[0] = 0;        /* Mode data length (MSB) */
-               mode_buf[1] = 6;        /* Mode data length (LSB) */
-               mode_buf[2] = 0;        /* Medium type - default */
--              mode_buf[3] = 0;        /* Device-specific param, bit 8: 0/1 = write enabled/protected */
-+              mode_buf[3] = 0;        /* Device-specific param,
-+                                         bit 8: 0/1 = write enabled/protected
-+                                         bit 4: 0/1 = FUA enabled */
-+              if (dev->raw_io_interface)
-+                      mode_buf[3] = 0x10;
-               mode_buf[4] = 0;        /* reserved */
-               mode_buf[5] = 0;        /* reserved */
-               mode_buf[6] = 0;        /* Block descriptor length (MSB) */
-               mode_buf[7] = 0;        /* Block descriptor length (LSB) */
--              aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
-+              if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
-+                ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
-+                      mode_buf[1] = 9;
-+                      mode_buf[8] = 8;
-+                      mode_buf[9] = 1;
-+                      mode_buf[10] = 0x04; /* WCE */
-+                      mode_buf_length = 11;
-+                      if (mode_buf_length > scsicmd->cmnd[8])
-+                              mode_buf_length = scsicmd->cmnd[8];
-+              }
-+              aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
-               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
-               scsicmd->scsi_done(scsicmd);
-@@ -2136,10 +2178,10 @@
-       if (!aac_valid_context(scsicmd, fibptr))
-               return;
--      dev = (struct aac_dev *)scsicmd->device->host->hostdata;
+-static int spufs_caps_open(struct inode *inode, struct file *file)
+-{
+-      return single_open(file, spufs_caps_show, SPUFS_I(inode)->i_ctx);
+-}
 -
-       BUG_ON(fibptr == NULL);
-+      dev = fibptr->dev;
-+
-       srbreply = (struct aac_srb_reply *) fib_data(fibptr);
-       scsicmd->sense_buffer[0] = '\0';  /* Initialize sense valid flag to false */
-@@ -2147,17 +2189,10 @@
-        *      Calculate resid for sg 
-        */
-        
--      scsicmd->resid = scsicmd->request_bufflen - 
--              le32_to_cpu(srbreply->data_xfer_length);
-+      scsi_set_resid(scsicmd, scsi_bufflen(scsicmd)
-+                     - le32_to_cpu(srbreply->data_xfer_length));
--      if(scsicmd->use_sg)
--              pci_unmap_sg(dev->pdev, 
--                      (struct scatterlist *)scsicmd->request_buffer,
--                      scsicmd->use_sg,
--                      scsicmd->sc_data_direction);
--      else if(scsicmd->request_bufflen)
--              pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, scsicmd->request_bufflen,
--                      scsicmd->sc_data_direction);
-+      scsi_dma_unmap(scsicmd);
-       /*
-        * First check the fib status
-@@ -2233,7 +2268,7 @@
-               break;
-       case SRB_STATUS_BUSY:
--              scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
-+              scsicmd->result = DID_BUS_BUSY << 16 | COMMAND_COMPLETE << 8;
-               break;
-       case SRB_STATUS_BUS_RESET:
-@@ -2343,34 +2378,33 @@
- {
-       struct aac_dev *dev;
-       unsigned long byte_count = 0;
-+      int nseg;
-       dev = (struct aac_dev *)scsicmd->device->host->hostdata;
-       // Get rid of old data
-       psg->count = 0;
-       psg->sg[0].addr = 0;
-       psg->sg[0].count = 0;  
--      if (scsicmd->use_sg) {
-+
-+      nseg = scsi_dma_map(scsicmd);
-+      BUG_ON(nseg < 0);
-+      if (nseg) {
-               struct scatterlist *sg;
-               int i;
--              int sg_count;
--              sg = (struct scatterlist *) scsicmd->request_buffer;
--              sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
--                      scsicmd->sc_data_direction);
--              psg->count = cpu_to_le32(sg_count);
-+              psg->count = cpu_to_le32(nseg);
--              for (i = 0; i < sg_count; i++) {
-+              scsi_for_each_sg(scsicmd, sg, nseg, i) {
-                       psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
-                       psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
-                       byte_count += sg_dma_len(sg);
--                      sg++;
-               }
-               /* hba wants the size to be exact */
--              if(byte_count > scsicmd->request_bufflen){
-+              if (byte_count > scsi_bufflen(scsicmd)) {
-                       u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
--                              (byte_count - scsicmd->request_bufflen);
-+                              (byte_count - scsi_bufflen(scsicmd));
-                       psg->sg[i-1].count = cpu_to_le32(temp);
--                      byte_count = scsicmd->request_bufflen;
-+                      byte_count = scsi_bufflen(scsicmd);
-               }
-               /* Check for command underflow */
-               if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
-@@ -2378,18 +2412,6 @@
-                                       byte_count, scsicmd->underflow);
-               }
-       }
--      else if(scsicmd->request_bufflen) {
--              u32 addr;
--              scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
--                              scsicmd->request_buffer,
--                              scsicmd->request_bufflen,
--                              scsicmd->sc_data_direction);
--              addr = scsicmd->SCp.dma_handle;
--              psg->count = cpu_to_le32(1);
--              psg->sg[0].addr = cpu_to_le32(addr);
--              psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
--              byte_count = scsicmd->request_bufflen;
--      }
-       return byte_count;
- }
-@@ -2399,6 +2421,7 @@
-       struct aac_dev *dev;
-       unsigned long byte_count = 0;
-       u64 addr;
-+      int nseg;
-       dev = (struct aac_dev *)scsicmd->device->host->hostdata;
-       // Get rid of old data
-@@ -2406,31 +2429,28 @@
-       psg->sg[0].addr[0] = 0;
-       psg->sg[0].addr[1] = 0;
-       psg->sg[0].count = 0;
--      if (scsicmd->use_sg) {
-+
-+      nseg = scsi_dma_map(scsicmd);
-+      BUG_ON(nseg < 0);
-+      if (nseg) {
-               struct scatterlist *sg;
-               int i;
--              int sg_count;
--              sg = (struct scatterlist *) scsicmd->request_buffer;
+-static const struct file_operations spufs_caps_fops = {
+-      .open           = spufs_caps_open,
+-      .read           = seq_read,
+-      .llseek         = seq_lseek,
+-      .release        = single_release,
+-};
 -
--              sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
--                      scsicmd->sc_data_direction);
--              for (i = 0; i < sg_count; i++) {
-+              scsi_for_each_sg(scsicmd, sg, nseg, i) {
-                       int count = sg_dma_len(sg);
-                       addr = sg_dma_address(sg);
-                       psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
-                       psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
-                       psg->sg[i].count = cpu_to_le32(count);
-                       byte_count += count;
--                      sg++;
-               }
--              psg->count = cpu_to_le32(sg_count);
-+              psg->count = cpu_to_le32(nseg);
-               /* hba wants the size to be exact */
--              if(byte_count > scsicmd->request_bufflen){
-+              if (byte_count > scsi_bufflen(scsicmd)) {
-                       u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
--                              (byte_count - scsicmd->request_bufflen);
-+                              (byte_count - scsi_bufflen(scsicmd));
-                       psg->sg[i-1].count = cpu_to_le32(temp);
--                      byte_count = scsicmd->request_bufflen;
-+                      byte_count = scsi_bufflen(scsicmd);
-               }
-               /* Check for command underflow */
-               if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
-@@ -2438,26 +2458,13 @@
-                                       byte_count, scsicmd->underflow);
-               }
-       }
--      else if(scsicmd->request_bufflen) {
--              scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
--                              scsicmd->request_buffer,
--                              scsicmd->request_bufflen,
--                              scsicmd->sc_data_direction);
--              addr = scsicmd->SCp.dma_handle;
--              psg->count = cpu_to_le32(1);
--              psg->sg[0].addr[0] = cpu_to_le32(addr & 0xffffffff);
--              psg->sg[0].addr[1] = cpu_to_le32(addr >> 32);
--              psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
--              byte_count = scsicmd->request_bufflen;
--      }
-       return byte_count;
- }
- static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg)
+ static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
+                       char __user *buf, size_t len, loff_t *pos)
  {
--      struct Scsi_Host *host = scsicmd->device->host;
--      struct aac_dev *dev = (struct aac_dev *)host->hostdata;
-       unsigned long byte_count = 0;
-+      int nseg;
+@@ -2040,7 +2015,6 @@
+ };
  
-       // Get rid of old data
-       psg->count = 0;
-@@ -2467,16 +2474,14 @@
-       psg->sg[0].addr[1] = 0;
-       psg->sg[0].count = 0;
-       psg->sg[0].flags = 0;
--      if (scsicmd->use_sg) {
-+
-+      nseg = scsi_dma_map(scsicmd);
-+      BUG_ON(nseg < 0);
-+      if (nseg) {
-               struct scatterlist *sg;
-               int i;
--              int sg_count;
--              sg = (struct scatterlist *) scsicmd->request_buffer;
+ struct tree_descr spufs_dir_contents[] = {
+-      { "capabilities", &spufs_caps_fops, 0444, },
+       { "mem",  &spufs_mem_fops,  0666, },
+       { "regs", &spufs_regs_fops,  0666, },
+       { "mbox", &spufs_mbox_fops, 0444, },
+@@ -2076,7 +2050,6 @@
+ };
  
--              sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
--                      scsicmd->sc_data_direction);
--
--              for (i = 0; i < sg_count; i++) {
-+              scsi_for_each_sg(scsicmd, sg, nseg, i) {
-                       int count = sg_dma_len(sg);
-                       u64 addr = sg_dma_address(sg);
-                       psg->sg[i].next = 0;
-@@ -2486,15 +2491,14 @@
-                       psg->sg[i].count = cpu_to_le32(count);
-                       psg->sg[i].flags = 0;
-                       byte_count += count;
--                      sg++;
-               }
--              psg->count = cpu_to_le32(sg_count);
-+              psg->count = cpu_to_le32(nseg);
-               /* hba wants the size to be exact */
--              if(byte_count > scsicmd->request_bufflen){
-+              if (byte_count > scsi_bufflen(scsicmd)) {
-                       u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
--                              (byte_count - scsicmd->request_bufflen);
-+                              (byte_count - scsi_bufflen(scsicmd));
-                       psg->sg[i-1].count = cpu_to_le32(temp);
--                      byte_count = scsicmd->request_bufflen;
-+                      byte_count = scsi_bufflen(scsicmd);
-               }
-               /* Check for command underflow */
-               if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
-@@ -2502,24 +2506,6 @@
-                                       byte_count, scsicmd->underflow);
-               }
+ struct tree_descr spufs_dir_nosched_contents[] = {
+-      { "capabilities", &spufs_caps_fops, 0444, },
+       { "mem",  &spufs_mem_fops,  0666, },
+       { "mbox", &spufs_mbox_fops, 0444, },
+       { "ibox", &spufs_ibox_fops, 0444, },
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/cell/spufs/run.c linux-2.6.22-570/arch/powerpc/platforms/cell/spufs/run.c
+--- linux-2.6.22-590/arch/powerpc/platforms/cell/spufs/run.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/cell/spufs/run.c   2007-07-08 19:32:17.000000000 -0400
+@@ -142,12 +142,8 @@
+                       runcntl = SPU_RUNCNTL_RUNNABLE;
+               ctx->ops->runcntl_write(ctx, runcntl);
+       } else {
+-              unsigned long mode = SPU_PRIVCNTL_MODE_NORMAL;
+               spu_start_tick(ctx);
+               ctx->ops->npc_write(ctx, *npc);
+-              if (test_thread_flag(TIF_SINGLESTEP))
+-                      mode = SPU_PRIVCNTL_MODE_SINGLE_STEP;
+-              out_be64(&ctx->spu->priv2->spu_privcntl_RW, mode);
+               ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
        }
--      else if(scsicmd->request_bufflen) {
--              int count;
--              u64 addr;
--              scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
--                              scsicmd->request_buffer,
--                              scsicmd->request_bufflen,
--                              scsicmd->sc_data_direction);
--              addr = scsicmd->SCp.dma_handle;
--              count = scsicmd->request_bufflen;
--              psg->count = cpu_to_le32(1);
--              psg->sg[0].next = 0;
--              psg->sg[0].prev = 0;
--              psg->sg[0].addr[1] = cpu_to_le32((u32)(addr>>32));
--              psg->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
--              psg->sg[0].count = cpu_to_le32(count);
--              psg->sg[0].flags = 0;
--              byte_count = scsicmd->request_bufflen;
--      }
-       return byte_count;
- }
  
-diff -Nurb linux-2.6.22-570/drivers/scsi/aacraid/aacraid.h linux-2.6.22-590/drivers/scsi/aacraid/aacraid.h
---- linux-2.6.22-570/drivers/scsi/aacraid/aacraid.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/aacraid/aacraid.h    2008-01-02 13:56:37.000000000 -0500
-@@ -12,8 +12,8 @@
-  *----------------------------------------------------------------------------*/
+@@ -338,8 +334,7 @@
+               ret = spu_process_events(ctx);
  
- #ifndef AAC_DRIVER_BUILD
--# define AAC_DRIVER_BUILD 2437
--# define AAC_DRIVER_BRANCH "-mh4"
-+# define AAC_DRIVER_BUILD 2447
-+# define AAC_DRIVER_BRANCH "-ms"
- #endif
- #define MAXIMUM_NUM_CONTAINERS        32
+       } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
+-                                    SPU_STATUS_STOPPED_BY_HALT |
+-                                     SPU_STATUS_SINGLE_STEP)));
++                                    SPU_STATUS_STOPPED_BY_HALT)));
  
-@@ -464,12 +464,12 @@
-       int  (*adapter_restart)(struct aac_dev *dev, int bled);
-       /* Transport operations */
-       int  (*adapter_ioremap)(struct aac_dev * dev, u32 size);
--      irqreturn_t (*adapter_intr)(int irq, void *dev_id);
-+      irq_handler_t adapter_intr;
-       /* Packet operations */
-       int  (*adapter_deliver)(struct fib * fib);
-       int  (*adapter_bounds)(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba);
-       int  (*adapter_read)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count);
--      int  (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count);
-+      int  (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua);
-       int  (*adapter_scsi)(struct fib * fib, struct scsi_cmnd * cmd);
-       /* Administrative operations */
-       int  (*adapter_comm)(struct aac_dev * dev, int comm);
-@@ -860,10 +860,12 @@
-       __le32  FlashFirmwareBootBuild;
-       u8      MfgPcbaSerialNo[12];
-       u8      MfgWWNName[8];
--      __le32  MoreFeatureBits;
-+      __le32  SupportedOptions2;
-       __le32  ReservedGrowth[1];
- };
- #define AAC_FEATURE_FALCON    0x00000010
-+#define AAC_OPTION_MU_RESET   0x00000001
-+#define AAC_OPTION_IGNORE_RESET       0x00000002
- #define AAC_SIS_VERSION_V3    3
- #define AAC_SIS_SLOT_UNKNOWN  0xFF
+       ctx->ops->master_stop(ctx);
+       ret = spu_run_fini(ctx, npc, &status);
+@@ -349,15 +344,10 @@
+       if ((ret == 0) ||
+           ((ret == -ERESTARTSYS) &&
+            ((status & SPU_STATUS_STOPPED_BY_HALT) ||
+-            (status & SPU_STATUS_SINGLE_STEP) ||
+             ((status & SPU_STATUS_STOPPED_BY_STOP) &&
+              (status >> SPU_STOP_STATUS_SHIFT != 0x2104)))))
+               ret = status;
  
-@@ -1054,8 +1056,8 @@
- #define aac_adapter_read(fib,cmd,lba,count) \
-       ((fib)->dev)->a_ops.adapter_read(fib,cmd,lba,count)
+-      /* Note: we don't need to force_sig SIGTRAP on single-step
+-       * since we have TIF_SINGLESTEP set, thus the kernel will do
+-       * it upon return from the syscall anyawy
+-       */
+       if ((status & SPU_STATUS_STOPPED_BY_STOP)
+           && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
+               force_sig(SIGTRAP, current);
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/iseries/call_hpt.h linux-2.6.22-570/arch/powerpc/platforms/iseries/call_hpt.h
+--- linux-2.6.22-590/arch/powerpc/platforms/iseries/call_hpt.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/iseries/call_hpt.h 2007-07-08 19:32:17.000000000 -0400
+@@ -76,25 +76,24 @@
+       return compressedStatus;
+ }
  
--#define aac_adapter_write(fib,cmd,lba,count) \
--      ((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count)
-+#define aac_adapter_write(fib,cmd,lba,count,fua) \
-+      ((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count,fua)
+-static inline u64 HvCallHpt_findValid(struct hash_pte *hpte, u64 vpn)
++static inline u64 HvCallHpt_findValid(hpte_t *hpte, u64 vpn)
+ {
+       return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
+ }
  
- #define aac_adapter_scsi(fib,cmd) \
-       ((fib)->dev)->a_ops.adapter_scsi(fib,cmd)
-@@ -1213,6 +1215,9 @@
-       __le32          block;
-       __le16          pad;
-       __le16          flags;
-+#define       IO_TYPE_WRITE 0x00000000
-+#define       IO_TYPE_READ  0x00000001
-+#define       IO_SUREWRITE  0x00000008
-       struct sgmap64  sg;     // Must be last in struct because it is variable
- };
- struct aac_write_reply
-@@ -1257,6 +1262,19 @@
-       u8              data[16];
- };
+-static inline u64 HvCallHpt_findNextValid(struct hash_pte *hpte, u32 hpteIndex,
++static inline u64 HvCallHpt_findNextValid(hpte_t *hpte, u32 hpteIndex,
+               u8 bitson, u8 bitsoff)
+ {
+       return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
+                       bitson, bitsoff);
+ }
  
-+#define CT_PAUSE_IO    65
-+#define CT_RELEASE_IO  66
-+struct aac_pause {
-+      __le32          command;        /* VM_ContainerConfig */
-+      __le32          type;           /* CT_PAUSE_IO */
-+      __le32          timeout;        /* 10ms ticks */
-+      __le32          min;
-+      __le32          noRescan;
-+      __le32          parm3;
-+      __le32          parm4;
-+      __le32          count;  /* sizeof(((struct aac_pause_reply *)NULL)->data) */
-+};
-+
- struct aac_srb
+-static inline void HvCallHpt_get(struct hash_pte *hpte, u32 hpteIndex)
++static inline void HvCallHpt_get(hpte_t *hpte, u32 hpteIndex)
  {
-       __le32          function;
-@@ -1804,6 +1822,10 @@
- int aac_get_containers(struct aac_dev *dev);
- int aac_scsi_cmd(struct scsi_cmnd *cmd);
- int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg);
-+#ifndef shost_to_class
-+#define shost_to_class(shost) &shost->shost_classdev
-+#endif
-+ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf);
- int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg);
- int aac_rx_init(struct aac_dev *dev);
- int aac_rkt_init(struct aac_dev *dev);
-@@ -1813,6 +1835,7 @@
- unsigned int aac_response_normal(struct aac_queue * q);
- unsigned int aac_command_normal(struct aac_queue * q);
- unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
-+int aac_reset_adapter(struct aac_dev * dev, int forced);
- int aac_check_health(struct aac_dev * dev);
- int aac_command_thread(void *data);
- int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
-@@ -1832,3 +1855,6 @@
- extern int expose_physicals;
- extern int aac_reset_devices;
- extern int aac_commit;
-+extern int update_interval;
-+extern int check_interval;
-+extern int check_reset;
-diff -Nurb linux-2.6.22-570/drivers/scsi/aacraid/commsup.c linux-2.6.22-590/drivers/scsi/aacraid/commsup.c
---- linux-2.6.22-570/drivers/scsi/aacraid/commsup.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/aacraid/commsup.c    2008-01-02 13:56:37.000000000 -0500
-@@ -1021,7 +1021,7 @@
+       HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
+ }
  
+-static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit,
+-                                       struct hash_pte *hpte)
++static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, hpte_t *hpte)
+ {
+       HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r);
  }
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/iseries/htab.c linux-2.6.22-570/arch/powerpc/platforms/iseries/htab.c
+--- linux-2.6.22-590/arch/powerpc/platforms/iseries/htab.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/iseries/htab.c     2007-07-08 19:32:17.000000000 -0400
+@@ -44,7 +44,7 @@
+                        unsigned long vflags, int psize)
+ {
+       long slot;
+-      struct hash_pte lhpte;
++      hpte_t lhpte;
+       int secondary = 0;
  
--static int _aac_reset_adapter(struct aac_dev *aac)
-+static int _aac_reset_adapter(struct aac_dev *aac, int forced)
+       BUG_ON(psize != MMU_PAGE_4K);
+@@ -99,7 +99,7 @@
+ static unsigned long iSeries_hpte_getword0(unsigned long slot)
  {
-       int index, quirks;
-       int retval;
-@@ -1029,25 +1029,32 @@
-       struct scsi_device *dev;
-       struct scsi_cmnd *command;
-       struct scsi_cmnd *command_list;
-+      int jafo = 0;
+-      struct hash_pte hpte;
++      hpte_t hpte;
  
-       /*
-        * Assumptions:
--       *      - host is locked.
-+       *      - host is locked, unless called by the aacraid thread.
-+       *        (a matter of convenience, due to legacy issues surrounding
-+       *        eh_host_adapter_reset).
-        *      - in_reset is asserted, so no new i/o is getting to the
-        *        card.
--       *      - The card is dead.
-+       *      - The card is dead, or will be very shortly ;-/ so no new
-+       *        commands are completing in the interrupt service.
-        */
-       host = aac->scsi_host_ptr;
-       scsi_block_requests(host);
-       aac_adapter_disable_int(aac);
-+      if (aac->thread->pid != current->pid) {
-       spin_unlock_irq(host->host_lock);
-       kthread_stop(aac->thread);
-+              jafo = 1;
-+      }
+       HvCallHpt_get(&hpte, slot);
+       return hpte.v;
+@@ -144,7 +144,7 @@
+ static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
+                                 unsigned long va, int psize, int local)
+ {
+-      struct hash_pte hpte;
++      hpte_t hpte;
+       unsigned long want_v;
+       iSeries_hlock(slot);
+@@ -176,7 +176,7 @@
+  */
+ static long iSeries_hpte_find(unsigned long vpn)
+ {
+-      struct hash_pte hpte;
++      hpte_t hpte;
+       long slot;
  
        /*
-        *      If a positive health, means in a known DEAD PANIC
-        * state and the adapter could be reset to `try again'.
-        */
--      retval = aac_adapter_restart(aac, aac_adapter_check_health(aac));
-+      retval = aac_adapter_restart(aac, forced ? 0 : aac_adapter_check_health(aac));
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/iseries/pci.c linux-2.6.22-570/arch/powerpc/platforms/iseries/pci.c
+--- linux-2.6.22-590/arch/powerpc/platforms/iseries/pci.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/iseries/pci.c      2007-07-08 19:32:17.000000000 -0400
+@@ -742,11 +742,6 @@
+       /* Install IO hooks */
+       ppc_pci_io = iseries_pci_io;
  
-       if (retval)
-               goto out;
-@@ -1104,11 +1111,13 @@
-       if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT)
-               if ((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK)))
-                       goto out;
-+      if (jafo) {
-       aac->thread = kthread_run(aac_command_thread, aac, aac->name);
-       if (IS_ERR(aac->thread)) {
-               retval = PTR_ERR(aac->thread);
-               goto out;
-       }
-+      }
-       (void)aac_get_adapter_info(aac);
-       quirks = aac_get_driver_ident(index)->quirks;
-       if ((quirks & AAC_QUIRK_34SG) && (host->sg_tablesize > 34)) {
-@@ -1150,7 +1159,98 @@
- out:
-       aac->in_reset = 0;
-       scsi_unblock_requests(host);
-+      if (jafo) {
-       spin_lock_irq(host->host_lock);
-+      }
-+      return retval;
-+}
-+
-+int aac_reset_adapter(struct aac_dev * aac, int forced)
+-      /* iSeries has no IO space in the common sense, it needs to set
+-       * the IO base to 0
+-       */
+-      pci_io_base = 0;
+-
+       if (root == NULL) {
+               printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
+                               "of device tree\n");
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/maple/pci.c linux-2.6.22-570/arch/powerpc/platforms/maple/pci.c
+--- linux-2.6.22-590/arch/powerpc/platforms/maple/pci.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/maple/pci.c        2007-07-08 19:32:17.000000000 -0400
+@@ -519,6 +519,23 @@
+       DBG(" <- maple_pci_irq_fixup\n");
+ }
++static void __init maple_fixup_phb_resources(void)
 +{
-+      unsigned long flagv = 0;
-+      int retval;
-+      struct Scsi_Host * host;
-+
-+      if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0)
-+              return -EBUSY;
-+
-+      if (aac->in_reset) {
-+              spin_unlock_irqrestore(&aac->fib_lock, flagv);
-+              return -EBUSY;
-+      }
-+      aac->in_reset = 1;
-+      spin_unlock_irqrestore(&aac->fib_lock, flagv);
++      struct pci_controller *hose, *tmp;
++      
++      list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
++              unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
 +
-+      /*
-+       * Wait for all commands to complete to this specific
-+       * target (block maximum 60 seconds). Although not necessary,
-+       * it does make us a good storage citizen.
-+       */
-+      host = aac->scsi_host_ptr;
-+      scsi_block_requests(host);
-+      if (forced < 2) for (retval = 60; retval; --retval) {
-+              struct scsi_device * dev;
-+              struct scsi_cmnd * command;
-+              int active = 0;
-+
-+              __shost_for_each_device(dev, host) {
-+                      spin_lock_irqsave(&dev->list_lock, flagv);
-+                      list_for_each_entry(command, &dev->cmd_list, list) {
-+                              if (command->SCp.phase == AAC_OWNER_FIRMWARE) {
-+                                      active++;
-+                                      break;
-+                              }
-+                      }
-+                      spin_unlock_irqrestore(&dev->list_lock, flagv);
-+                      if (active)
-+                              break;
++              hose->io_resource.start += offset;
++              hose->io_resource.end += offset;
 +
-+              }
-+              /*
-+               * We can exit If all the commands are complete
-+               */
-+              if (active == 0)
-+                      break;
-+              ssleep(1);
-+      }
-+
-+      /* Quiesce build, flush cache, write through mode */
-+      aac_send_shutdown(aac);
-+      spin_lock_irqsave(host->host_lock, flagv);
-+      retval = _aac_reset_adapter(aac, forced);
-+      spin_unlock_irqrestore(host->host_lock, flagv);
-+
-+      if (retval == -ENODEV) {
-+              /* Unwind aac_send_shutdown() IOP_RESET unsupported/disabled */
-+              struct fib * fibctx = aac_fib_alloc(aac);
-+              if (fibctx) {
-+                      struct aac_pause *cmd;
-+                      int status;
-+
-+                      aac_fib_init(fibctx);
-+
-+                      cmd = (struct aac_pause *) fib_data(fibctx);
-+
-+                      cmd->command = cpu_to_le32(VM_ContainerConfig);
-+                      cmd->type = cpu_to_le32(CT_PAUSE_IO);
-+                      cmd->timeout = cpu_to_le32(1);
-+                      cmd->min = cpu_to_le32(1);
-+                      cmd->noRescan = cpu_to_le32(1);
-+                      cmd->count = cpu_to_le32(0);
-+
-+                      status = aac_fib_send(ContainerCommand,
-+                        fibctx,
-+                        sizeof(struct aac_pause),
-+                        FsaNormal,
-+                        -2 /* Timeout silently */, 1,
-+                        NULL, NULL);
-+
-+                      if (status >= 0)
-+                              aac_fib_complete(fibctx);
-+                      aac_fib_free(fibctx);
-+              }
++              printk(KERN_INFO "PCI Host %d, io start: %llx; io end: %llx\n",
++                     hose->global_number,
++                     (unsigned long long)hose->io_resource.start,
++                     (unsigned long long)hose->io_resource.end);
 +      }
++}
 +
-       return retval;
- }
-@@ -1270,9 +1370,14 @@
-       printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED);
-+      if (!check_reset || (aac->supplement_adapter_info.SupportedOptions2 &
-+        le32_to_cpu(AAC_OPTION_IGNORE_RESET)))
-+              goto out;
-       host = aac->scsi_host_ptr;
-+      if (aac->thread->pid != current->pid)
-       spin_lock_irqsave(host->host_lock, flagv);
--      BlinkLED = _aac_reset_adapter(aac);
-+      BlinkLED = _aac_reset_adapter(aac, 0);
-+      if (aac->thread->pid != current->pid)
-       spin_unlock_irqrestore(host->host_lock, flagv);
-       return BlinkLED;
-@@ -1300,6 +1405,9 @@
-       struct aac_fib_context *fibctx;
-       unsigned long flags;
-       DECLARE_WAITQUEUE(wait, current);
-+      unsigned long next_jiffies = jiffies + HZ;
-+      unsigned long next_check_jiffies = next_jiffies;
-+      long difference = HZ;
-       /*
-        *      We can only have one thread per adapter for AIF's.
-@@ -1507,11 +1615,79 @@
-                *      There are no more AIF's
-                */
-               spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
--              schedule();
+ void __init maple_pci_init(void)
+ {
+       struct device_node *np, *root;
+@@ -556,6 +573,24 @@
+       if (ht && add_bridge(ht) != 0)
+               of_node_put(ht);
  
--              if (kthread_should_stop())
-+              /*
-+               *      Background activity
-+               */
-+              if ((time_before(next_check_jiffies,next_jiffies))
-+               && ((difference = next_check_jiffies - jiffies) <= 0)) {
-+                      next_check_jiffies = next_jiffies;
-+                      if (aac_check_health(dev) == 0) {
-+                              difference = ((long)(unsigned)check_interval)
-+                                         * HZ;
-+                              next_check_jiffies = jiffies + difference;
-+                      } else if (!dev->queues)
-                       break;
-+              }
-+              if (!time_before(next_check_jiffies,next_jiffies)
-+               && ((difference = next_jiffies - jiffies) <= 0)) {
-+                      struct timeval now;
-+                      int ret;
-+
-+                      /* Don't even try to talk to adapter if its sick */
-+                      ret = aac_check_health(dev);
-+                      if (!ret && !dev->queues)
-+                              break;
-+                      next_check_jiffies = jiffies
-+                                         + ((long)(unsigned)check_interval)
-+                                         * HZ;
-+                      do_gettimeofday(&now);
-+
-+                      /* Synchronize our watches */
-+                      if (((1000000 - (1000000 / HZ)) > now.tv_usec)
-+                       && (now.tv_usec > (1000000 / HZ)))
-+                              difference = (((1000000 - now.tv_usec) * HZ)
-+                                + 500000) / 1000000;
-+                      else if (ret == 0) {
-+                              struct fib *fibptr;
-+
-+                              if ((fibptr = aac_fib_alloc(dev))) {
-+                                      u32 * info;
-+
-+                                      aac_fib_init(fibptr);
-+
-+                                      info = (u32 *) fib_data(fibptr);
-+                                      if (now.tv_usec > 500000)
-+                                              ++now.tv_sec;
-+
-+                                      *info = cpu_to_le32(now.tv_sec);
-+
-+                                      (void)aac_fib_send(SendHostTime,
-+                                              fibptr,
-+                                              sizeof(*info),
-+                                              FsaNormal,
-+                                              1, 1,
-+                                              NULL,
-+                                              NULL);
-+                                      aac_fib_complete(fibptr);
-+                                      aac_fib_free(fibptr);
-+                              }
-+                              difference = (long)(unsigned)update_interval*HZ;
-+                      } else {
-+                              /* retry shortly */
-+                              difference = 10 * HZ;
-+                      }
-+                      next_jiffies = jiffies + difference;
-+                      if (time_before(next_check_jiffies,next_jiffies))
-+                              difference = next_check_jiffies - jiffies;
-+              }
-+              if (difference <= 0)
-+                      difference = 1;
-               set_current_state(TASK_INTERRUPTIBLE);
-+              schedule_timeout(difference);
++        /*
++         * We need to call pci_setup_phb_io for the HT bridge first
++         * so it gets the I/O port numbers starting at 0, and we
++         * need to call it for the AGP bridge after that so it gets
++         * small positive I/O port numbers.
++         */
++        if (u3_ht)
++                pci_setup_phb_io(u3_ht, 1);
++        if (u3_agp)
++                pci_setup_phb_io(u3_agp, 0);
++        if (u4_pcie)
++                pci_setup_phb_io(u4_pcie, 0);
++
++      /* Fixup the IO resources on our host bridges as the common code
++       * does it only for childs of the host bridges
++       */
++      maple_fixup_phb_resources();
 +
-+              if (kthread_should_stop())
-+                      break;
-       }
-       if (dev->queues)
-               remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
-diff -Nurb linux-2.6.22-570/drivers/scsi/aacraid/linit.c linux-2.6.22-590/drivers/scsi/aacraid/linit.c
---- linux-2.6.22-570/drivers/scsi/aacraid/linit.c      2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/scsi/aacraid/linit.c      2008-01-02 13:56:37.000000000 -0500
-@@ -39,10 +39,8 @@
- #include <linux/pci.h>
- #include <linux/slab.h>
- #include <linux/spinlock.h>
--#include <linux/dma-mapping.h>
- #include <linux/syscalls.h>
- #include <linux/delay.h>
--#include <linux/smp_lock.h>
- #include <linux/kthread.h>
- #include <asm/semaphore.h>
+       /* Setup the linkage between OF nodes and PHBs */ 
+       pci_devs_phb_init();
  
-@@ -223,12 +221,12 @@
-       { aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
-       { aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
-       { aac_sa_init, "aacraid",  "ADAPTEC ", "AAC-364         ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
--      { aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell PERC2/QC */
-+      { aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_34SG }, /* Dell PERC2/QC */
-       { aac_sa_init, "hpnraid",  "HP      ", "NetRAID         ", 4, AAC_QUIRK_34SG }, /* HP NetRAID-4M */
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/pasemi/pci.c linux-2.6.22-570/arch/powerpc/platforms/pasemi/pci.c
+--- linux-2.6.22-590/arch/powerpc/platforms/pasemi/pci.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/pasemi/pci.c       2007-07-08 19:32:17.000000000 -0400
+@@ -150,11 +150,29 @@
+       printk(KERN_INFO "Found PA-PXP PCI host bridge.\n");
  
-       { aac_rx_init, "aacraid",  "DELL    ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell Catchall */
-       { aac_rx_init, "aacraid",  "Legend  ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend Catchall */
--      { aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec Catch All */
-+      { aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Catch All */
-       { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Rocket Catch All */
-       { aac_nark_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec NEMER/ARK Catch All */
- };
-@@ -403,10 +401,6 @@
+       /* Interpret the "ranges" property */
++      /* This also maps the I/O region and sets isa_io/mem_base */
+       pci_process_bridge_OF_ranges(hose, dev, 1);
++      pci_setup_phb_io(hose, 1);
  
- static int aac_slave_configure(struct scsi_device *sdev)
- {
--      if (sdev_channel(sdev) == CONTAINER_CHANNEL) {
--              sdev->skip_ms_page_8 = 1;
--              sdev->skip_ms_page_3f = 1;
--      }
-       if ((sdev->type == TYPE_DISK) &&
-                       (sdev_channel(sdev) != CONTAINER_CHANNEL)) {
-               if (expose_physicals == 0)
-@@ -450,6 +444,43 @@
        return 0;
  }
  
-+/**
-+ *    aac_change_queue_depth          -       alter queue depths
-+ *    @sdev:  SCSI device we are considering
-+ *    @depth: desired queue depth
-+ *
-+ *    Alters queue depths for target device based on the host adapter's
-+ *    total capacity and the queue depth supported by the target device.
-+ */
 +
-+static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
++static void __init pas_fixup_phb_resources(void)
 +{
-+      if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
-+          (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
-+              struct scsi_device * dev;
-+              struct Scsi_Host *host = sdev->host;
-+              unsigned num = 0;
++      struct pci_controller *hose, *tmp;
 +
-+              __shost_for_each_device(dev, host) {
-+                      if (dev->tagged_supported && (dev->type == TYPE_DISK) &&
-+                          (sdev_channel(dev) == CONTAINER_CHANNEL))
-+                              ++num;
-+                      ++num;
-+              }
-+              if (num >= host->can_queue)
-+                      num = host->can_queue - 1;
-+              if (depth > (host->can_queue - num))
-+                      depth = host->can_queue - num;
-+              if (depth > 256)
-+                      depth = 256;
-+              else if (depth < 2)
-+                      depth = 2;
-+              scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth);
-+      } else
-+              scsi_adjust_queue_depth(sdev, 0, 1);
-+      return sdev->queue_depth;
++      list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
++              unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
++              hose->io_resource.start += offset;
++              hose->io_resource.end += offset;
++              printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
++                     hose->global_number,
++                     hose->io_resource.start, hose->io_resource.end);
++      }
 +}
 +
- static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg)
++
+ void __init pas_pci_init(void)
  {
-       struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
-@@ -548,6 +579,14 @@
-               ssleep(1);
-       }
-       printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
-+      /*
-+       * This adapter needs a blind reset, only do so for Adapters that
-+       * support a register, instead of a commanded, reset.
-+       */
-+      if ((aac->supplement_adapter_info.SupportedOptions2 &
-+        le32_to_cpu(AAC_OPTION_MU_RESET|AAC_OPTION_IGNORE_RESET)) ==
-+        le32_to_cpu(AAC_OPTION_MU_RESET))
-+              aac_reset_adapter(aac, 2); /* Bypass wait for command quiesce */
-       return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */
- }
-@@ -735,15 +774,21 @@
-       return len;
- }
+       struct device_node *np, *root;
+@@ -172,6 +190,8 @@
  
--static ssize_t aac_show_serial_number(struct class_device *class_dev,
--              char *buf)
-+ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf)
- {
-       struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
-       int len = 0;
+       of_node_put(root);
  
-       if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
--              len = snprintf(buf, PAGE_SIZE, "%x\n",
-+              len = snprintf(buf, PAGE_SIZE, "%06X\n",
-                 le32_to_cpu(dev->adapter_info.serial[0]));
-+      if (len &&
-+        !memcmp(&dev->supplement_adapter_info.MfgPcbaSerialNo[
-+          sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo)+2-len],
-+        buf, len))
-+              len = snprintf(buf, PAGE_SIZE, "%.*s\n",
-+                (int)sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo),
-+                dev->supplement_adapter_info.MfgPcbaSerialNo);
-       return len;
- }
++      pas_fixup_phb_resources();
++
+       /* Setup the linkage between OF nodes and PHBs */
+       pci_devs_phb_init();
  
-@@ -759,6 +804,31 @@
-         class_to_shost(class_dev)->max_id);
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/powermac/pci.c linux-2.6.22-570/arch/powerpc/platforms/powermac/pci.c
+--- linux-2.6.22-590/arch/powerpc/platforms/powermac/pci.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/powermac/pci.c     2007-07-08 19:32:17.000000000 -0400
+@@ -1006,6 +1006,19 @@
+ #endif /* CONFIG_PPC32 */
  }
  
-+static ssize_t aac_store_reset_adapter(struct class_device *class_dev,
-+              const char *buf, size_t count)
++#ifdef CONFIG_PPC64
++static void __init pmac_fixup_phb_resources(void)
 +{
-+      int retval = -EACCES;
++      struct pci_controller *hose, *tmp;
 +
-+      if (!capable(CAP_SYS_ADMIN))
-+              return retval;
-+      retval = aac_reset_adapter((struct aac_dev*)class_to_shost(class_dev)->hostdata, buf[0] == '!');
-+      if (retval >= 0)
-+              retval = count;
-+      return retval;
++      list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
++              printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
++                     hose->global_number,
++                     hose->io_resource.start, hose->io_resource.end);
++      }
 +}
++#endif
 +
-+static ssize_t aac_show_reset_adapter(struct class_device *class_dev,
-+              char *buf)
-+{
-+      struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
-+      int len, tmp;
-+
-+      tmp = aac_adapter_check_health(dev);
-+      if ((tmp == 0) && dev->in_reset)
-+              tmp = -EBUSY;
-+      len = snprintf(buf, PAGE_SIZE, "0x%x", tmp);
-+      return len;
-+}
- static struct class_device_attribute aac_model = {
-       .attr = {
-@@ -816,6 +886,14 @@
-       },
-       .show = aac_show_max_id,
- };
-+static struct class_device_attribute aac_reset = {
-+      .attr = {
-+              .name = "reset_host",
-+              .mode = S_IWUSR|S_IRUGO,
-+      },
-+      .store = aac_store_reset_adapter,
-+      .show = aac_show_reset_adapter,
-+};
- static struct class_device_attribute *aac_attrs[] = {
-       &aac_model,
-@@ -826,6 +904,7 @@
-       &aac_serial_number,
-       &aac_max_channel,
-       &aac_max_id,
-+      &aac_reset,
-       NULL
- };
-@@ -852,6 +931,7 @@
-       .bios_param                     = aac_biosparm, 
-       .shost_attrs                    = aac_attrs,
-       .slave_configure                = aac_slave_configure,
-+      .change_queue_depth             = aac_change_queue_depth,
-       .eh_abort_handler               = aac_eh_abort,
-       .eh_host_reset_handler          = aac_eh_reset,
-       .can_queue                      = AAC_NUM_IO_FIB,       
-@@ -1090,7 +1170,7 @@
- {
-       int error;
-       
--      printk(KERN_INFO "Adaptec %s driver (%s)\n",
-+      printk(KERN_INFO "Adaptec %s driver %s\n",
-         AAC_DRIVERNAME, aac_driver_version);
-       error = pci_register_driver(&aac_pci_driver);
-diff -Nurb linux-2.6.22-570/drivers/scsi/aacraid/rx.c linux-2.6.22-590/drivers/scsi/aacraid/rx.c
---- linux-2.6.22-570/drivers/scsi/aacraid/rx.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/aacraid/rx.c 2008-01-02 13:56:37.000000000 -0500
-@@ -464,6 +464,8 @@
+ void __init pmac_pci_init(void)
  {
-       u32 var;
-+      if (!(dev->supplement_adapter_info.SupportedOptions2 &
-+        le32_to_cpu(AAC_OPTION_MU_RESET)) || (bled >= 0) || (bled == -2)) {
-       if (bled)
-               printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
-                       dev->name, dev->id, bled);
-@@ -479,6 +481,7 @@
+       struct device_node *np, *root;
+@@ -1040,6 +1053,25 @@
+       if (ht && add_bridge(ht) != 0)
+               of_node_put(ht);
  
-       if (bled && (bled != -ETIMEDOUT))
-               return -EINVAL;
-+      }
-       if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */
-               rx_writel(dev, MUnit.reserved2, 3);
-               msleep(5000); /* Delay 5 seconds */
-@@ -596,7 +599,7 @@
-               }
-               msleep(1);
-       }
--      if (restart)
-+      if (restart && aac_commit)
-               aac_commit = 1;
-       /*
-        *      Fill in the common function dispatch table.
-diff -Nurb linux-2.6.22-570/drivers/scsi/advansys.c linux-2.6.22-590/drivers/scsi/advansys.c
---- linux-2.6.22-570/drivers/scsi/advansys.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/advansys.c   2008-01-02 13:56:37.000000000 -0500
-@@ -798,7 +798,6 @@
- #include <scsi/scsi_tcq.h>
- #include <scsi/scsi.h>
- #include <scsi/scsi_host.h>
--#include "advansys.h"
- #ifdef CONFIG_PCI
- #include <linux/pci.h>
- #endif /* CONFIG_PCI */
-@@ -2014,7 +2013,7 @@
- STATIC void      AscEnableIsaDma(uchar);
- #endif /* CONFIG_ISA */
- STATIC ASC_DCNT  AscGetMaxDmaCount(ushort);
--
-+static const char *advansys_info(struct Scsi_Host *shp);
++      /*
++       * We need to call pci_setup_phb_io for the HT bridge first
++       * so it gets the I/O port numbers starting at 0, and we
++       * need to call it for the AGP bridge after that so it gets
++       * small positive I/O port numbers.
++       */
++      if (u3_ht)
++              pci_setup_phb_io(u3_ht, 1);
++      if (u3_agp)
++              pci_setup_phb_io(u3_agp, 0);
++      if (u4_pcie)
++              pci_setup_phb_io(u4_pcie, 0);
++
++      /*
++       * On ppc64, fixup the IO resources on our host bridges as
++       * the common code does it only for children of the host bridges
++       */
++      pmac_fixup_phb_resources();
++
+       /* Setup the linkage between OF nodes and PHBs */
+       pci_devs_phb_init();
  
- /*
-  * --- Adv Library Constants and Macros
-@@ -3970,10 +3969,6 @@
-     ASC_IS_PCI,
- };
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/powermac/setup.c linux-2.6.22-570/arch/powerpc/platforms/powermac/setup.c
+--- linux-2.6.22-590/arch/powerpc/platforms/powermac/setup.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/powermac/setup.c   2007-07-08 19:32:17.000000000 -0400
+@@ -98,6 +98,8 @@
+ int sccdbg;
+ #endif
  
--/*
-- * Used with the LILO 'advansys' option to eliminate or
-- * limit I/O port probing at boot time, cf. advansys_setup().
-- */
- STATIC int asc_iopflag = ASC_FALSE;
- STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 };
++extern void zs_kgdb_hook(int tty_num);
++
+ sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
+ EXPORT_SYMBOL(sys_ctrler);
  
-@@ -4055,10 +4050,6 @@
- #endif /* ADVANSYS_DEBUG */
+@@ -328,6 +330,10 @@
+       l2cr_init();
+ #endif /* CONFIG_PPC32 */
  
++#ifdef CONFIG_KGDB
++      zs_kgdb_hook(0);
++#endif
++
+       find_via_cuda();
+       find_via_pmu();
+       smu_init();
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/ps3/htab.c linux-2.6.22-570/arch/powerpc/platforms/ps3/htab.c
+--- linux-2.6.22-590/arch/powerpc/platforms/ps3/htab.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/ps3/htab.c 2007-07-08 19:32:17.000000000 -0400
+@@ -34,7 +34,7 @@
+ #define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+ #endif
  
--/*
-- * --- Linux 'struct scsi_host_template' and advansys_setup() Functions
-- */
--
- #ifdef CONFIG_PROC_FS
- /*
-  * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
-@@ -4080,7 +4071,7 @@
-  * if 'prtbuf' is too small it will not be overwritten. Instead the
-  * user just won't get all the available statistics.
-  */
--int
-+static int
- advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
-               off_t offset, int length, int inout)
- {
-@@ -4296,7 +4287,7 @@
-  * it must not call SCSI mid-level functions including scsi_malloc()
-  * and scsi_free().
-  */
--int __init
-+static int __init
- advansys_detect(struct scsi_host_template *tpnt)
- {
-     static int          detect_called = ASC_FALSE;
-@@ -5428,7 +5419,7 @@
-  *
-  * Release resources allocated for a single AdvanSys adapter.
-  */
--int
-+static int
- advansys_release(struct Scsi_Host *shp)
- {
-     asc_board_t    *boardp;
-@@ -5475,7 +5466,7 @@
-  * Note: The information line should not exceed ASC_INFO_SIZE bytes,
-  * otherwise the static 'info' array will be overrun.
-  */
--const char *
-+static const char *
- advansys_info(struct Scsi_Host *shp)
- {
-     static char     info[ASC_INFO_SIZE];
-@@ -5568,7 +5559,7 @@
-  * This function always returns 0. Command return status is saved
-  * in the 'scp' result field.
-  */
--int
-+static int
- advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
- {
-     struct Scsi_Host    *shp;
-@@ -5656,7 +5647,7 @@
-  * sleeping is allowed and no locking other than for host structures is
-  * required. Returns SUCCESS or FAILED.
-  */
--int
-+static int
- advansys_reset(struct scsi_cmnd *scp)
+-static struct hash_pte *htab;
++static hpte_t *htab;
+ static unsigned long htab_addr;
+ static unsigned char *bolttab;
+ static unsigned char *inusetab;
+@@ -44,8 +44,8 @@
+ #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \
+       _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
+ static void _debug_dump_hpte(unsigned long pa, unsigned long va,
+-      unsigned long group, unsigned long bitmap, struct hash_pte lhpte,
+-      int psize, unsigned long slot, const char* func, int line)
++      unsigned long group, unsigned long bitmap, hpte_t lhpte, int psize,
++      unsigned long slot, const char* func, int line)
  {
-     struct Scsi_Host     *shp;
-@@ -5841,7 +5832,7 @@
-  * ip[1]: sectors
-  * ip[2]: cylinders
-  */
--int
-+static int
- advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
-               sector_t capacity, int ip[])
+       DBG("%s:%d: pa     = %lxh\n", func, line, pa);
+       DBG("%s:%d: lpar   = %lxh\n", func, line,
+@@ -63,7 +63,7 @@
+       unsigned long pa, unsigned long rflags, unsigned long vflags, int psize)
  {
-@@ -5875,82 +5866,6 @@
- }
+       unsigned long slot;
+-      struct hash_pte lhpte;
++      hpte_t lhpte;
+       int secondary = 0;
+       unsigned long result;
+       unsigned long bitmap;
+@@ -255,7 +255,7 @@
  
- /*
-- * advansys_setup()
-- *
-- * This function is called from init/main.c at boot time.
-- * It it passed LILO parameters that can be set from the
-- * LILO command line or in /etc/lilo.conf.
-- *
-- * It is used by the AdvanSys driver to either disable I/O
-- * port scanning or to limit scanning to 1 - 4 I/O ports.
-- * Regardless of the option setting EISA and PCI boards
-- * will still be searched for and detected. This option
-- * only affects searching for ISA and VL boards.
-- *
-- * If ADVANSYS_DEBUG is defined the driver debug level may
-- * be set using the 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port.
-- *
-- * Examples:
-- * 1. Eliminate I/O port scanning:
-- *         boot: linux advansys=
-- *       or
-- *         boot: linux advansys=0x0
-- * 2. Limit I/O port scanning to one I/O port:
-- *        boot: linux advansys=0x110
-- * 3. Limit I/O port scanning to four I/O ports:
-- *        boot: linux advansys=0x110,0x210,0x230,0x330
-- * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
-- *    set the driver debug level to 2.
-- *        boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
-- *
-- * ints[0] - number of arguments
-- * ints[1] - first argument
-- * ints[2] - second argument
-- * ...
-- */
--void __init
--advansys_setup(char *str, int *ints)
--{
--    int    i;
--
--    if (asc_iopflag == ASC_TRUE) {
--        printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
--        return;
--    }
--
--    asc_iopflag = ASC_TRUE;
--
--    if (ints[0] > ASC_NUM_IOPORT_PROBE) {
--#ifdef ADVANSYS_DEBUG
--        if ((ints[0] == ASC_NUM_IOPORT_PROBE + 1) &&
--            (ints[ASC_NUM_IOPORT_PROBE + 1] >> 4 == 0xdeb)) {
--            asc_dbglvl = ints[ASC_NUM_IOPORT_PROBE + 1] & 0xf;
--        } else {
--#endif /* ADVANSYS_DEBUG */
--            printk("AdvanSys SCSI: only %d I/O ports accepted\n",
--                ASC_NUM_IOPORT_PROBE);
--#ifdef ADVANSYS_DEBUG
--        }
--#endif /* ADVANSYS_DEBUG */
--    }
--
--#ifdef ADVANSYS_DEBUG
--    ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
--    for (i = 1; i < ints[0]; i++) {
--        ASC_DBG2(1, " ints[%d] 0x%x", i, ints[i]);
--    }
--    ASC_DBG(1, "\n");
--#endif /* ADVANSYS_DEBUG */
--
--    for (i = 1; i <= ints[0] && i <= ASC_NUM_IOPORT_PROBE; i++) {
--        asc_ioport[i-1] = ints[i];
--        ASC_DBG2(1, "advansys_setup: asc_ioport[%d] 0x%x\n",
--            i - 1, asc_ioport[i-1]);
--    }
--}
--
--
--/*
-  * --- Loadable Driver Support
-  */
+       ppc64_pft_size = __ilog2(htab_size);
  
-diff -Nurb linux-2.6.22-570/drivers/scsi/advansys.h linux-2.6.22-590/drivers/scsi/advansys.h
---- linux-2.6.22-570/drivers/scsi/advansys.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/advansys.h   1969-12-31 19:00:00.000000000 -0500
-@@ -1,36 +0,0 @@
--/*
-- * advansys.h - Linux Host Driver for AdvanSys SCSI Adapters
-- * 
-- * Copyright (c) 1995-2000 Advanced System Products, Inc.
-- * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
-- * All Rights Reserved.
-- *
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that redistributions of source
-- * code retain the above copyright notice and this comment without
-- * modification.
-- *
-- * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
-- * changed its name to ConnectCom Solutions, Inc.
-- *
-- */
--
--#ifndef _ADVANSYS_H
--#define _ADVANSYS_H
--
--/*
-- * struct scsi_host_template function prototypes.
-- */
--int advansys_detect(struct scsi_host_template *);
--int advansys_release(struct Scsi_Host *);
--const char *advansys_info(struct Scsi_Host *);
--int advansys_queuecommand(struct scsi_cmnd *, void (* done)(struct scsi_cmnd *));
--int advansys_reset(struct scsi_cmnd *);
--int advansys_biosparam(struct scsi_device *, struct block_device *,
--              sector_t, int[]);
--static int advansys_slave_configure(struct scsi_device *);
--
--/* init/main.c setup function */
--void advansys_setup(char *, int *);
--
--#endif /* _ADVANSYS_H */
-diff -Nurb linux-2.6.22-570/drivers/scsi/aha152x.c linux-2.6.22-590/drivers/scsi/aha152x.c
---- linux-2.6.22-570/drivers/scsi/aha152x.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/aha152x.c    2008-01-02 13:56:37.000000000 -0500
-@@ -240,6 +240,7 @@
- #include <linux/io.h>
- #include <linux/blkdev.h>
- #include <asm/system.h>
-+#include <linux/completion.h>
- #include <linux/errno.h>
- #include <linux/string.h>
- #include <linux/wait.h>
-@@ -253,7 +254,6 @@
- #include <linux/spinlock.h>
- #include <linux/workqueue.h>
- #include <linux/list.h>
--#include <asm/semaphore.h>
- #include <scsi/scsicam.h>
+-      bitmap_size = htab_size / sizeof(struct hash_pte) / 8;
++      bitmap_size = htab_size / sizeof(hpte_t) / 8;
  
- #include "scsi.h"
-@@ -551,7 +551,7 @@
-  */
- struct aha152x_scdata {
-       Scsi_Cmnd *next;        /* next sc in queue */
--      struct semaphore *sem;  /* semaphore to block on */
-+      struct completion *done;/* semaphore to block on */
-       unsigned char cmd_len;
-       unsigned char cmnd[MAX_COMMAND_SIZE];
-       unsigned short use_sg;
-@@ -608,7 +608,7 @@
+       bolttab = __va(lmb_alloc(bitmap_size, 1));
+       inusetab = __va(lmb_alloc(bitmap_size, 1));
+@@ -273,7 +273,7 @@
  
- #define SCDATA(SCpnt)         ((struct aha152x_scdata *) (SCpnt)->host_scribble)
- #define SCNEXT(SCpnt)         SCDATA(SCpnt)->next
--#define SCSEM(SCpnt)          SCDATA(SCpnt)->sem
-+#define SCSEM(SCpnt)          SCDATA(SCpnt)->done
+       result = lv1_map_htab(0, &htab_addr);
  
- #define SG_ADDRESS(buffer)    ((char *) (page_address((buffer)->page)+(buffer)->offset))
+-      htab = (struct hash_pte *)__ioremap(htab_addr, htab_size,
++      htab = (hpte_t *)__ioremap(htab_addr, htab_size,
+                                  pgprot_val(PAGE_READONLY_X));
  
-@@ -969,7 +969,8 @@
- /* 
-  *  Queue a command and setup interrupts for a free bus.
+       DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__,
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/pseries/Makefile linux-2.6.22-570/arch/powerpc/platforms/pseries/Makefile
+--- linux-2.6.22-590/arch/powerpc/platforms/pseries/Makefile   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/pseries/Makefile   2007-07-08 19:32:17.000000000 -0400
+@@ -8,7 +8,7 @@
+ obj-$(CONFIG_SMP)     += smp.o
+ obj-$(CONFIG_XICS)    += xics.o
+ obj-$(CONFIG_SCANLOG) += scanlog.o
+-obj-$(CONFIG_EEH)     += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o
++obj-$(CONFIG_EEH)     += eeh.o eeh_cache.o eeh_driver.o eeh_event.o
+ obj-$(CONFIG_KEXEC)   += kexec.o
+ obj-$(CONFIG_PCI)     += pci.o pci_dlpar.o
+ obj-$(CONFIG_PCI_MSI) += msi.o
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh.c linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh.c
+--- linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh.c      2007-07-08 19:32:17.000000000 -0400
+@@ -1,8 +1,6 @@
+ /*
+  * eeh.c
+- * Copyright IBM Corporation 2001, 2005, 2006
+- * Copyright Dave Engebretsen & Todd Inglett 2001
+- * Copyright Linas Vepstas 2005, 2006
++ * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation
+  *
+  * 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
+@@ -17,8 +15,6 @@
+  * 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
+- *
+- * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com>
   */
--static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int phase, void (*done)(Scsi_Cmnd *))
-+static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete,
-+              int phase, void (*done)(Scsi_Cmnd *))
- {
-       struct Scsi_Host *shpnt = SCpnt->device->host;
-       unsigned long flags;
-@@ -1013,7 +1014,7 @@
+ #include <linux/delay.h>
+@@ -121,6 +117,7 @@
+ static unsigned long ignored_check;
+ static unsigned long total_mmio_ffs;
+ static unsigned long false_positives;
++static unsigned long ignored_failures;
+ static unsigned long slot_resets;
+ #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)
+@@ -508,7 +505,6 @@
+               printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n",
+                      ret, dn->full_name);
+               false_positives++;
+-              pdn->eeh_false_positives ++;
+               rc = 0;
+               goto dn_unlock;
+       }
+@@ -517,7 +513,6 @@
+        * they are empty when they don't have children. */
+       if ((rets[0] == 5) && (dn->child == NULL)) {
+               false_positives++;
+-              pdn->eeh_false_positives ++;
+               rc = 0;
+               goto dn_unlock;
+       }
+@@ -527,7 +522,6 @@
+               printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n",
+                      ret, dn->full_name);
+               false_positives++;
+-              pdn->eeh_false_positives ++;
+               rc = 0;
+               goto dn_unlock;
+       }
+@@ -535,7 +529,6 @@
+       /* If not the kind of error we know about, punt. */
+       if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) {
+               false_positives++;
+-              pdn->eeh_false_positives ++;
+               rc = 0;
+               goto dn_unlock;
        }
+@@ -928,7 +921,6 @@
+       pdn->eeh_mode = 0;
+       pdn->eeh_check_count = 0;
+       pdn->eeh_freeze_count = 0;
+-      pdn->eeh_false_positives = 0;
  
-       SCNEXT(SCpnt)           = NULL;
--      SCSEM(SCpnt)            = sem;
-+      SCSEM(SCpnt)            = complete;
+       if (status && strcmp(status, "ok") != 0)
+               return NULL;    /* ignore devices with bad status */
+@@ -1147,8 +1139,7 @@
+       pdn = PCI_DN(dn);
+       pdn->pcidev = dev;
  
-       /* setup scratch area
-          SCp.ptr              : buffer pointer
-@@ -1084,9 +1085,9 @@
-       DPRINTK(debug_eh, INFO_LEAD "reset_done called\n", CMDINFO(SCpnt));
+-      pci_addr_cache_insert_device(dev);
+-      eeh_sysfs_add_device(dev);
++      pci_addr_cache_insert_device (dev);
+ }
+ void eeh_add_device_tree_late(struct pci_bus *bus)
+@@ -1187,7 +1178,6 @@
+       printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev));
  #endif
-       if(SCSEM(SCpnt)) {
--              up(SCSEM(SCpnt));
-+              complete(SCSEM(SCpnt));
-       } else {
--              printk(KERN_ERR "aha152x: reset_done w/o semaphore\n");
-+              printk(KERN_ERR "aha152x: reset_done w/o completion\n");
+       pci_addr_cache_remove_device(dev);
+-      eeh_sysfs_remove_device(dev);
+       dn = pci_device_to_OF_node(dev);
+       if (PCI_DN(dn)->pcidev) {
+@@ -1224,10 +1214,11 @@
+                               "check not wanted=%ld\n"
+                               "eeh_total_mmio_ffs=%ld\n"
+                               "eeh_false_positives=%ld\n"
++                              "eeh_ignored_failures=%ld\n"
+                               "eeh_slot_resets=%ld\n",
+                               no_device, no_dn, no_cfg_addr, 
+                               ignored_check, total_mmio_ffs, 
+-                              false_positives,
++                              false_positives, ignored_failures, 
+                               slot_resets);
        }
- }
  
-@@ -1139,21 +1140,6 @@
-       return FAILED;
- }
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh_cache.c linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh_cache.c
+--- linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh_cache.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh_cache.c        2007-07-08 19:32:17.000000000 -0400
+@@ -2,8 +2,7 @@
+  * eeh_cache.c
+  * PCI address cache; allows the lookup of PCI devices based on I/O address
+  *
+- * Copyright IBM Corporation 2004
+- * Copyright Linas Vepstas <linas@austin.ibm.com> 2004
++ * Copyright (C) 2004 Linas Vepstas <linas@austin.ibm.com> IBM Corporation
+  *
+  * 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
+@@ -296,8 +295,6 @@
+                       continue;
+               pci_dev_get (dev);  /* matching put is in eeh_remove_device() */
+               PCI_DN(dn)->pcidev = dev;
+-
+-              eeh_sysfs_add_device(dev);
+       }
  
--static void timer_expired(unsigned long p)
--{
--      Scsi_Cmnd        *SCp   = (Scsi_Cmnd *)p;
--      struct semaphore *sem   = SCSEM(SCp);
--      struct Scsi_Host *shpnt = SCp->device->host;
--      unsigned long flags;
+ #ifdef DEBUG
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh_driver.c linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh_driver.c
+--- linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh_driver.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh_driver.c       2007-07-08 19:32:17.000000000 -0400
+@@ -1,7 +1,6 @@
+ /*
+  * PCI Error Recovery Driver for RPA-compliant PPC64 platform.
+- * Copyright IBM Corp. 2004 2005
+- * Copyright Linas Vepstas <linas@linas.org> 2004, 2005
++ * Copyright (C) 2004, 2005 Linas Vepstas <linas@linas.org>
+  *
+  * All rights reserved.
+  *
+@@ -20,7 +19,8 @@
+  * along with this program; if not, write to the Free Software
+  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  *
+- * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
++ * Send feedback to <linas@us.ibm.com>
++ *
+  */
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh_sysfs.c linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh_sysfs.c
+--- linux-2.6.22-590/arch/powerpc/platforms/pseries/eeh_sysfs.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/pseries/eeh_sysfs.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,87 +0,0 @@
+-/*
+- * Sysfs entries for PCI Error Recovery for PAPR-compliant platform.
+- * Copyright IBM Corporation 2007
+- * Copyright Linas Vepstas <linas@austin.ibm.com> 2007
+- *
+- * All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or (at
+- * your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+- * NON INFRINGEMENT.  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.
+- *
+- * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
+- */
+-#include <linux/pci.h>
+-#include <asm/ppc-pci.h>
+-#include <asm/pci-bridge.h>
+-#include <linux/kobject.h>
 -
--      /* remove command from issue queue */
--      DO_LOCK(flags);
--      remove_SC(&ISSUE_SC, SCp);
--      DO_UNLOCK(flags);
+-/**
+- * EEH_SHOW_ATTR -- create sysfs entry for eeh statistic
+- * @_name: name of file in sysfs directory
+- * @_memb: name of member in struct pci_dn to access
+- * @_format: printf format for display
+- *
+- * All of the attributes look very similar, so just
+- * auto-gen a cut-n-paste routine to display them.
+- */
+-#define EEH_SHOW_ATTR(_name,_memb,_format)               \
+-static ssize_t eeh_show_##_name(struct device *dev,      \
+-              struct device_attribute *attr, char *buf)          \
+-{                                                        \
+-      struct pci_dev *pdev = to_pci_dev(dev);               \
+-      struct device_node *dn = pci_device_to_OF_node(pdev); \
+-      struct pci_dn *pdn;                                   \
+-                                                            \
+-      if (!dn || PCI_DN(dn) == NULL)                        \
+-              return 0;                                          \
+-                                                            \
+-      pdn = PCI_DN(dn);                                     \
+-      return sprintf(buf, _format "\n", pdn->_memb);        \
+-}                                                        \
+-static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL);
+-
+-
+-EEH_SHOW_ATTR(eeh_mode, eeh_mode, "0x%x");
+-EEH_SHOW_ATTR(eeh_config_addr, eeh_config_addr, "0x%x");
+-EEH_SHOW_ATTR(eeh_pe_config_addr, eeh_pe_config_addr, "0x%x");
+-EEH_SHOW_ATTR(eeh_check_count, eeh_check_count, "%d");
+-EEH_SHOW_ATTR(eeh_freeze_count, eeh_freeze_count, "%d");
+-EEH_SHOW_ATTR(eeh_false_positives, eeh_false_positives, "%d");
+-
+-void eeh_sysfs_add_device(struct pci_dev *pdev)
+-{
+-      int rc=0;
+-
+-      rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode);
+-      rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr);
+-      rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
+-      rc += device_create_file(&pdev->dev, &dev_attr_eeh_check_count);
+-      rc += device_create_file(&pdev->dev, &dev_attr_eeh_false_positives);
+-      rc += device_create_file(&pdev->dev, &dev_attr_eeh_freeze_count);
 -
--      up(sem);
+-      if (rc)
+-              printk(KERN_WARNING "EEH: Unable to create sysfs entries\n");
 -}
 -
- /*
-  * Reset a device
-  *
-@@ -1161,14 +1147,14 @@
- static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
- {
-       struct Scsi_Host *shpnt = SCpnt->device->host;
--      DECLARE_MUTEX_LOCKED(sem);
--      struct timer_list timer;
-+      DECLARE_COMPLETION(done);
-       int ret, issued, disconnected;
-       unsigned char old_cmd_len = SCpnt->cmd_len;
-       unsigned short old_use_sg = SCpnt->use_sg;
-       void *old_buffer = SCpnt->request_buffer;
-       unsigned old_bufflen = SCpnt->request_bufflen;
-       unsigned long flags;
-+      unsigned long timeleft;
- #if defined(AHA152X_DEBUG)
-       if(HOSTDATA(shpnt)->debug & debug_eh) {
-@@ -1192,15 +1178,15 @@
-       SCpnt->request_buffer  = NULL;
-       SCpnt->request_bufflen = 0;
--      init_timer(&timer);
--      timer.data     = (unsigned long) SCpnt;
--      timer.expires  = jiffies + 100*HZ;   /* 10s */
--      timer.function = (void (*)(unsigned long)) timer_expired;
+-void eeh_sysfs_remove_device(struct pci_dev *pdev)
+-{
+-      device_remove_file(&pdev->dev, &dev_attr_eeh_mode);
+-      device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr);
+-      device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
+-      device_remove_file(&pdev->dev, &dev_attr_eeh_check_count);
+-      device_remove_file(&pdev->dev, &dev_attr_eeh_false_positives);
+-      device_remove_file(&pdev->dev, &dev_attr_eeh_freeze_count);
+-}
 -
--      aha152x_internal_queue(SCpnt, &sem, resetting, reset_done);
--      add_timer(&timer);
--      down(&sem);
--      del_timer(&timer);
-+      aha152x_internal_queue(SCpnt, &done, resetting, reset_done);
-+
-+      timeleft = wait_for_completion_timeout(&done, 100*HZ);
-+      if (!timeleft) {
-+              /* remove command from issue queue */
-+              DO_LOCK(flags);
-+              remove_SC(&ISSUE_SC, SCpnt);
-+              DO_UNLOCK(flags);
-+      }
-       SCpnt->cmd_len         = old_cmd_len;
-       SCpnt->use_sg          = old_use_sg;
-diff -Nurb linux-2.6.22-570/drivers/scsi/aha1740.c linux-2.6.22-590/drivers/scsi/aha1740.c
---- linux-2.6.22-570/drivers/scsi/aha1740.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/aha1740.c    2008-01-02 13:56:37.000000000 -0500
-@@ -271,19 +271,7 @@
-                               continue;
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/pseries/pci_dlpar.c linux-2.6.22-570/arch/powerpc/platforms/pseries/pci_dlpar.c
+--- linux-2.6.22-590/arch/powerpc/platforms/pseries/pci_dlpar.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/pseries/pci_dlpar.c        2007-07-08 19:32:17.000000000 -0400
+@@ -110,6 +110,8 @@
                        }
-                       sgptr = (struct aha1740_sg *) SCtmp->host_scribble;
--                      if (SCtmp->use_sg) {
--                              /* We used scatter-gather.
--                                 Do the unmapping dance. */
--                              dma_unmap_sg (&edev->dev,
--                                            (struct scatterlist *) SCtmp->request_buffer,
--                                            SCtmp->use_sg,
--                                            SCtmp->sc_data_direction);
--                      } else {
--                              dma_unmap_single (&edev->dev,
--                                                sgptr->buf_dma_addr,
--                                                SCtmp->request_bufflen,
--                                                DMA_BIDIRECTIONAL);
--                      }
-+                      scsi_dma_unmap(SCtmp);
-           
-                       /* Free the sg block */
-                       dma_free_coherent (&edev->dev,
-@@ -349,11 +337,9 @@
-       unchar target = scmd_id(SCpnt);
-       struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
-       unsigned long flags;
--      void *buff = SCpnt->request_buffer;
--      int bufflen = SCpnt->request_bufflen;
-       dma_addr_t sg_dma;
-       struct aha1740_sg *sgptr;
--      int ecbno;
-+      int ecbno, nseg;
-       DEB(int i);
-       if(*cmd == REQUEST_SENSE) {
-@@ -424,23 +410,22 @@
-       sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
-       sgptr->sg_dma_addr = sg_dma;
-     
--      if (SCpnt->use_sg) {
--              struct scatterlist * sgpnt;
-+      nseg = scsi_dma_map(SCpnt);
-+      BUG_ON(nseg < 0);
-+      if (nseg) {
-+              struct scatterlist *sg;
-               struct aha1740_chain * cptr;
--              int i, count;
-+              int i;
-               DEB(unsigned char * ptr);
-               host->ecb[ecbno].sg = 1;  /* SCSI Initiator Command
-                                          * w/scatter-gather*/
--              sgpnt = (struct scatterlist *) SCpnt->request_buffer;
-               cptr = sgptr->sg_chain;
--              count = dma_map_sg (&host->edev->dev, sgpnt, SCpnt->use_sg,
--                                  SCpnt->sc_data_direction);
--              for(i=0; i < count; i++) {
--                      cptr[i].datalen = sg_dma_len (sgpnt + i);
--                      cptr[i].dataptr = sg_dma_address (sgpnt + i);
-+              scsi_for_each_sg(SCpnt, sg, nseg, i) {
-+                      cptr[i].datalen = sg_dma_len (sg);
-+                      cptr[i].dataptr = sg_dma_address (sg);
                }
--              host->ecb[ecbno].datalen = count*sizeof(struct aha1740_chain);
-+              host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain);
-               host->ecb[ecbno].dataptr = sg_dma;
- #ifdef DEBUG
-               printk("cptr %x: ",cptr);
-@@ -448,11 +433,8 @@
-               for(i=0;i<24;i++) printk("%02x ", ptr[i]);
- #endif
-       } else {
--              host->ecb[ecbno].datalen = bufflen;
--              sgptr->buf_dma_addr =  dma_map_single (&host->edev->dev,
--                                                     buff, bufflen,
--                                                     DMA_BIDIRECTIONAL);
--              host->ecb[ecbno].dataptr = sgptr->buf_dma_addr;
-+              host->ecb[ecbno].datalen = 0;
-+              host->ecb[ecbno].dataptr = 0;
        }
-       host->ecb[ecbno].lun = SCpnt->device->lun;
-       host->ecb[ecbno].ses = 1; /* Suppress underrun errors */
-diff -Nurb linux-2.6.22-570/drivers/scsi/aic7xxx/aic79xx_osm.c linux-2.6.22-590/drivers/scsi/aic7xxx/aic79xx_osm.c
---- linux-2.6.22-570/drivers/scsi/aic7xxx/aic79xx_osm.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/aic7xxx/aic79xx_osm.c        2008-01-02 13:56:37.000000000 -0500
-@@ -376,21 +376,10 @@
- ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
- {
-       struct scsi_cmnd *cmd;
--      int direction;
++
++      eeh_add_device_tree_late(bus);
+ }
+ EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
  
-       cmd = scb->io_ctx;
--      direction = cmd->sc_data_direction;
-       ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE);
--      if (cmd->use_sg != 0) {
--              struct scatterlist *sg;
+@@ -137,8 +139,6 @@
+       /* Make the discovered devices available */
+       pci_bus_add_devices(child_bus);
 -
--              sg = (struct scatterlist *)cmd->request_buffer;
--              pci_unmap_sg(ahd->dev_softc, sg, cmd->use_sg, direction);
--      } else if (cmd->request_bufflen != 0) {
--              pci_unmap_single(ahd->dev_softc,
--                               scb->platform_data->buf_busaddr,
--                               cmd->request_bufflen, direction);
--      }
-+      scsi_dma_unmap(cmd);
+-      eeh_add_device_tree_late(child_bus);
+       return 0;
  }
  
- /******************************** Macros **************************************/
-@@ -1422,6 +1411,7 @@
-       u_int    col_idx;
-       uint16_t mask;
-       unsigned long flags;
-+      int nseg;
-       ahd_lock(ahd, &flags);
+@@ -171,7 +171,6 @@
+               if (!list_empty(&bus->devices)) {
+                       pcibios_fixup_new_pci_devices(bus, 0);
+                       pci_bus_add_devices(bus);
+-                      eeh_add_device_tree_late(bus);
+               }
+       } else if (mode == PCI_PROBE_NORMAL) {
+               /* use legacy probe */
+@@ -180,7 +179,6 @@
+               if (num) {
+                       pcibios_fixup_new_pci_devices(bus, 1);
+                       pci_bus_add_devices(bus);
+-                      eeh_add_device_tree_late(bus);
+               }
  
-@@ -1494,18 +1484,17 @@
-       ahd_set_residual(scb, 0);
-       ahd_set_sense_residual(scb, 0);
-       scb->sg_count = 0;
--      if (cmd->use_sg != 0) {
--              void    *sg;
-+
-+      nseg = scsi_dma_map(cmd);
-+      BUG_ON(nseg < 0);
-+      if (nseg > 0) {
-+              void *sg = scb->sg_list;
-               struct   scatterlist *cur_seg;
--              u_int    nseg;
--              int      dir;
-+              int i;
+               list_for_each_entry(dev, &bus->devices, bus_list)
+@@ -202,6 +200,8 @@
+       rtas_setup_phb(phb);
+       pci_process_bridge_OF_ranges(phb, dn, 0);
  
--              cur_seg = (struct scatterlist *)cmd->request_buffer;
--              dir = cmd->sc_data_direction;
--              nseg = pci_map_sg(ahd->dev_softc, cur_seg,
--                                cmd->use_sg, dir);
-               scb->platform_data->xfer_len = 0;
--              for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
++      pci_setup_phb_io_dynamic(phb, primary);
 +
-+              scsi_for_each_sg(cmd, cur_seg, nseg, i) {
-                       dma_addr_t addr;
-                       bus_size_t len;
+       pci_devs_phb_init_dynamic(phb);
  
-@@ -1513,22 +1502,8 @@
-                       len = sg_dma_len(cur_seg);
-                       scb->platform_data->xfer_len += len;
-                       sg = ahd_sg_setup(ahd, scb, sg, addr, len,
--                                        /*last*/nseg == 1);
-+                                        i == (nseg - 1));
-               }
--      } else if (cmd->request_bufflen != 0) {
--              void *sg;
--              dma_addr_t addr;
--              int dir;
--
--              sg = scb->sg_list;
--              dir = cmd->sc_data_direction;
--              addr = pci_map_single(ahd->dev_softc,
--                                    cmd->request_buffer,
--                                    cmd->request_bufflen, dir);
--              scb->platform_data->xfer_len = cmd->request_bufflen;
--              scb->platform_data->buf_busaddr = addr;
--              sg = ahd_sg_setup(ahd, scb, sg, addr,
--                                cmd->request_bufflen, /*last*/TRUE);
-       }
+       if (dn->child)
+@@ -210,7 +210,6 @@
+       scan_phb(phb);
+       pcibios_fixup_new_pci_devices(phb->bus, 0);
+       pci_bus_add_devices(phb->bus);
+-      eeh_add_device_tree_late(phb->bus);
  
-       LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
-diff -Nurb linux-2.6.22-570/drivers/scsi/aic7xxx/aic79xx_osm.h linux-2.6.22-590/drivers/scsi/aic7xxx/aic79xx_osm.h
---- linux-2.6.22-570/drivers/scsi/aic7xxx/aic79xx_osm.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/aic7xxx/aic79xx_osm.h        2008-01-02 13:56:37.000000000 -0500
-@@ -781,7 +781,7 @@
- static __inline
- void ahd_set_residual(struct scb *scb, u_long resid)
- {
--      scb->io_ctx->resid = resid;
-+      scsi_set_resid(scb->io_ctx, resid);
+       return phb;
  }
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/pseries/pseries.h linux-2.6.22-570/arch/powerpc/platforms/pseries/pseries.h
+--- linux-2.6.22-590/arch/powerpc/platforms/pseries/pseries.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/pseries/pseries.h  2007-07-08 19:32:17.000000000 -0400
+@@ -33,8 +33,6 @@
+ static inline void setup_kexec_cpu_down_mpic(void) { }
+ #endif
  
- static __inline
-@@ -793,7 +793,7 @@
- static __inline
- u_long ahd_get_residual(struct scb *scb)
- {
--      return (scb->io_ctx->resid);
-+      return scsi_get_resid(scb->io_ctx);
- }
+-extern void pSeries_final_fixup(void);
+-
+ /* Poweron flag used for enabling auto ups restart */
+ extern unsigned long rtas_poweron_auto;
  
- static __inline
-diff -Nurb linux-2.6.22-570/drivers/scsi/aic7xxx/aic7xxx_osm.c linux-2.6.22-590/drivers/scsi/aic7xxx/aic7xxx_osm.c
---- linux-2.6.22-570/drivers/scsi/aic7xxx/aic7xxx_osm.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/aic7xxx/aic7xxx_osm.c        2008-01-02 13:56:37.000000000 -0500
-@@ -402,18 +402,8 @@
+diff -Nurb linux-2.6.22-590/arch/powerpc/platforms/pseries/setup.c linux-2.6.22-570/arch/powerpc/platforms/pseries/setup.c
+--- linux-2.6.22-590/arch/powerpc/platforms/pseries/setup.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/platforms/pseries/setup.c    2007-07-08 19:32:17.000000000 -0400
+@@ -399,7 +399,6 @@
+        * a good time to find other work to dispatch.
+        */
+       get_lppaca()->idle = 1;
+-      get_lppaca()->donate_dedicated_cpu = 1;
  
-       cmd = scb->io_ctx;
-       ahc_sync_sglist(ahc, scb, BUS_DMASYNC_POSTWRITE);
--      if (cmd->use_sg != 0) {
--              struct scatterlist *sg;
+       /*
+        * We come in with interrupts disabled, and need_resched()
+@@ -432,7 +431,6 @@
  
--              sg = (struct scatterlist *)cmd->request_buffer;
--              pci_unmap_sg(ahc->dev_softc, sg, cmd->use_sg,
--                           cmd->sc_data_direction);
--      } else if (cmd->request_bufflen != 0) {
--              pci_unmap_single(ahc->dev_softc,
--                               scb->platform_data->buf_busaddr,
--                               cmd->request_bufflen,
--                               cmd->sc_data_direction);
--      }
-+      scsi_dma_unmap(cmd);
+ out:
+       HMT_medium();
+-      get_lppaca()->donate_dedicated_cpu = 0;
+       get_lppaca()->idle = 0;
  }
  
- static __inline int
-@@ -1381,6 +1371,7 @@
-       struct   ahc_tmode_tstate *tstate;
-       uint16_t mask;
-       struct scb_tailq *untagged_q = NULL;
-+      int nseg;
+diff -Nurb linux-2.6.22-590/arch/powerpc/sysdev/tsi108_dev.c linux-2.6.22-570/arch/powerpc/sysdev/tsi108_dev.c
+--- linux-2.6.22-590/arch/powerpc/sysdev/tsi108_dev.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/powerpc/sysdev/tsi108_dev.c  2007-07-08 19:32:17.000000000 -0400
+@@ -72,11 +72,12 @@
+       int ret;
  
-       /*
-        * Schedule us to run later.  The only reason we are not
-@@ -1472,23 +1463,21 @@
-       ahc_set_residual(scb, 0);
-       ahc_set_sense_residual(scb, 0);
-       scb->sg_count = 0;
--      if (cmd->use_sg != 0) {
-+
-+      nseg = scsi_dma_map(cmd);
-+      BUG_ON(nseg < 0);
-+      if (nseg > 0) {
-               struct  ahc_dma_seg *sg;
-               struct  scatterlist *cur_seg;
--              struct  scatterlist *end_seg;
--              int     nseg;
-+              int i;
+       for (np = NULL, i = 0;
+-           (np = of_find_compatible_node(np, "network", "tsi108-ethernet")) != NULL;
++           (np = of_find_compatible_node(np, "network", "tsi-ethernet")) != NULL;
+            i++) {
+               struct resource r[2];
+-              struct device_node *phy, *mdio;
++              struct device_node *phy;
+               hw_info tsi_eth_data;
++              const unsigned int *id;
+               const unsigned int *phy_id;
+               const void *mac_addr;
+               const phandle *ph;
+@@ -110,13 +111,6 @@
+               if (mac_addr)
+                       memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
  
--              cur_seg = (struct scatterlist *)cmd->request_buffer;
--              nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg,
--                                cmd->sc_data_direction);
--              end_seg = cur_seg + nseg;
-               /* Copy the segments into the SG list. */
-               sg = scb->sg_list;
-               /*
-                * The sg_count may be larger than nseg if
-                * a transfer crosses a 32bit page.
-                */ 
--              while (cur_seg < end_seg) {
-+              scsi_for_each_sg(cmd, cur_seg, nseg, i) {
-                       dma_addr_t addr;
-                       bus_size_t len;
-                       int consumed;
-@@ -1499,7 +1488,6 @@
-                                                    sg, addr, len);
-                       sg += consumed;
-                       scb->sg_count += consumed;
--                      cur_seg++;
+-              ph = of_get_property(np, "mdio-handle", NULL);
+-              mdio = of_find_node_by_phandle(*ph);
+-              ret = of_address_to_resource(mdio, 0, &res);
+-              of_node_put(mdio);
+-              if (ret)
+-                      goto unreg;
+-
+               ph = of_get_property(np, "phy-handle", NULL);
+               phy = of_find_node_by_phandle(*ph);
+@@ -125,25 +119,20 @@
+                       goto unreg;
                }
-               sg--;
-               sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
-@@ -1516,33 +1504,6 @@
-                */
-               scb->hscb->dataptr = scb->sg_list->addr;
-               scb->hscb->datacnt = scb->sg_list->len;
--      } else if (cmd->request_bufflen != 0) {
--              struct   ahc_dma_seg *sg;
--              dma_addr_t addr;
+-              phy_id = of_get_property(phy, "reg", NULL);
 -
--              sg = scb->sg_list;
--              addr = pci_map_single(ahc->dev_softc,
--                                    cmd->request_buffer,
--                                    cmd->request_bufflen,
--                                    cmd->sc_data_direction);
--              scb->platform_data->buf_busaddr = addr;
--              scb->sg_count = ahc_linux_map_seg(ahc, scb,
--                                                sg, addr,
--                                                cmd->request_bufflen);
--              sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
++              id = of_get_property(phy, "reg", NULL);
++              phy_id = of_get_property(phy, "phy-id", NULL);
++              ret = of_address_to_resource(phy, 0, &res);
++              if (ret) {
++                      of_node_put(phy);
++                      goto unreg;
++              }
+               tsi_eth_data.regs = r[0].start;
+               tsi_eth_data.phyregs = res.start;
+               tsi_eth_data.phy = *phy_id;
+               tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
 -
--              /*
--               * Reset the sg list pointer.
--               */
--              scb->hscb->sgptr =
--                      ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
+-              /* Some boards with the TSI108 bridge (e.g. Holly)
+-               * have a miswiring of the ethernet PHYs which
+-               * requires a workaround.  The special
+-               * "txc-rxc-delay-disable" property enables this
+-               * workaround.  FIXME: Need to port the tsi108_eth
+-               * driver itself to phylib and use a non-misleading
+-               * name for the workaround flag - it's not actually to
+-               * do with the model of PHY in use */
+-              if (of_get_property(phy, "txc-rxc-delay-disable", NULL))
++              if (of_device_is_compatible(phy, "bcm54xx"))
+                       tsi_eth_data.phy_type = TSI108_PHY_BCM54XX;
+               of_node_put(phy);
 -
--              /*
--               * Copy the first SG into the "current"
--               * data pointer area.
--               */
--              scb->hscb->dataptr = sg->addr;
--              scb->hscb->datacnt = sg->len;
+               ret =
+                   platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
+                                            sizeof(hw_info));
+diff -Nurb linux-2.6.22-590/arch/ppc/8260_io/enet.c linux-2.6.22-570/arch/ppc/8260_io/enet.c
+--- linux-2.6.22-590/arch/ppc/8260_io/enet.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/8260_io/enet.c   2007-07-08 19:32:17.000000000 -0400
+@@ -477,9 +477,9 @@
+               }
+               else {
+                       skb_put(skb,pkt_len-4); /* Make room */
+-                      skb_copy_to_linear_data(skb,
++                      eth_copy_and_sum(skb,
+                               (unsigned char *)__va(bdp->cbd_bufaddr),
+-                              pkt_len-4);
++                              pkt_len-4, 0);
+                       skb->protocol=eth_type_trans(skb,dev);
+                       netif_rx(skb);
+               }
+diff -Nurb linux-2.6.22-590/arch/ppc/8260_io/fcc_enet.c linux-2.6.22-570/arch/ppc/8260_io/fcc_enet.c
+--- linux-2.6.22-590/arch/ppc/8260_io/fcc_enet.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/8260_io/fcc_enet.c       2007-07-08 19:32:17.000000000 -0400
+@@ -734,9 +734,9 @@
+               }
+               else {
+                       skb_put(skb,pkt_len);   /* Make room */
+-                      skb_copy_to_linear_data(skb,
++                      eth_copy_and_sum(skb,
+                               (unsigned char *)__va(bdp->cbd_bufaddr),
+-                              pkt_len);
++                              pkt_len, 0);
+                       skb->protocol=eth_type_trans(skb,dev);
+                       netif_rx(skb);
+               }
+diff -Nurb linux-2.6.22-590/arch/ppc/8xx_io/enet.c linux-2.6.22-570/arch/ppc/8xx_io/enet.c
+--- linux-2.6.22-590/arch/ppc/8xx_io/enet.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/8xx_io/enet.c    2007-07-08 19:32:17.000000000 -0400
+@@ -506,9 +506,9 @@
+               }
+               else {
+                       skb_put(skb,pkt_len-4); /* Make room */
+-                      skb_copy_to_linear_data(skb,
++                      eth_copy_and_sum(skb,
+                               cep->rx_vaddr[bdp - cep->rx_bd_base],
+-                              pkt_len-4);
++                              pkt_len-4, 0);
+                       skb->protocol=eth_type_trans(skb,dev);
+                       netif_rx(skb);
+               }
+diff -Nurb linux-2.6.22-590/arch/ppc/8xx_io/fec.c linux-2.6.22-570/arch/ppc/8xx_io/fec.c
+--- linux-2.6.22-590/arch/ppc/8xx_io/fec.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/8xx_io/fec.c     2007-07-08 19:32:17.000000000 -0400
+@@ -725,7 +725,7 @@
+               fep->stats.rx_dropped++;
        } else {
-               scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
-               scb->hscb->dataptr = 0;
-diff -Nurb linux-2.6.22-570/drivers/scsi/aic7xxx/aic7xxx_osm.h linux-2.6.22-590/drivers/scsi/aic7xxx/aic7xxx_osm.h
---- linux-2.6.22-570/drivers/scsi/aic7xxx/aic7xxx_osm.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/aic7xxx/aic7xxx_osm.h        2008-01-02 13:56:37.000000000 -0500
-@@ -751,7 +751,7 @@
- static __inline
- void ahc_set_residual(struct scb *scb, u_long resid)
- {
--      scb->io_ctx->resid = resid;
-+      scsi_set_resid(scb->io_ctx, resid);
- }
- static __inline
-@@ -763,7 +763,7 @@
- static __inline
- u_long ahc_get_residual(struct scb *scb)
- {
--      return (scb->io_ctx->resid);
-+      return scsi_get_resid(scb->io_ctx);
- }
- static __inline
-diff -Nurb linux-2.6.22-570/drivers/scsi/aic7xxx_old.c linux-2.6.22-590/drivers/scsi/aic7xxx_old.c
---- linux-2.6.22-570/drivers/scsi/aic7xxx_old.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/aic7xxx_old.c        2008-01-02 13:56:37.000000000 -0500
-@@ -2690,17 +2690,8 @@
-       struct aic7xxx_scb *scbp;
-       unsigned char queue_depth;
--  if (cmd->use_sg > 1)
--  {
--    struct scatterlist *sg;
-+        scsi_dma_unmap(cmd);
--    sg = (struct scatterlist *)cmd->request_buffer;
--    pci_unmap_sg(p->pdev, sg, cmd->use_sg, cmd->sc_data_direction);
--  }
--  else if (cmd->request_bufflen)
--    pci_unmap_single(p->pdev, aic7xxx_mapping(cmd),
--                   cmd->request_bufflen,
--                     cmd->sc_data_direction);
-   if (scb->flags & SCB_SENSE)
-   {
-     pci_unmap_single(p->pdev,
-@@ -3869,7 +3860,7 @@
-        * the mid layer didn't check residual data counts to see if the
-        * command needs retried.
-        */
--      cmd->resid = scb->sg_length - actual;
-+      scsi_set_resid(cmd, scb->sg_length - actual);
-       aic7xxx_status(cmd) = hscb->target_status;
-     }
-   }
-@@ -10137,6 +10128,7 @@
-   struct scsi_device *sdptr = cmd->device;
-   unsigned char tindex = TARGET_INDEX(cmd);
-   struct request *req = cmd->request;
-+  int use_sg;
+               skb_put(skb,pkt_len-4); /* Make room */
+-              skb_copy_to_linear_data(skb, data, pkt_len-4);
++              eth_copy_and_sum(skb, data, pkt_len-4, 0);
+               skb->protocol=eth_type_trans(skb,dev);
+               netif_rx(skb);
+       }
+diff -Nurb linux-2.6.22-590/arch/ppc/Kconfig.debug linux-2.6.22-570/arch/ppc/Kconfig.debug
+--- linux-2.6.22-590/arch/ppc/Kconfig.debug    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/Kconfig.debug    2007-07-08 19:32:17.000000000 -0400
+@@ -2,6 +2,42 @@
  
-   mask = (0x01 << tindex);
-   hscb = scb->hscb;
-@@ -10209,8 +10201,10 @@
-   memcpy(scb->cmnd, cmd->cmnd, cmd->cmd_len);
-   hscb->SCSI_cmd_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, scb->cmnd));
+ source "lib/Kconfig.debug"
  
--  if (cmd->use_sg)
--  {
-+  use_sg = scsi_dma_map(cmd);
-+  BUG_ON(use_sg < 0);
++config KGDB
++      bool "Include kgdb kernel debugger"
++      depends on DEBUG_KERNEL && (BROKEN || PPC_GEN550 || 4xx)
++      select DEBUG_INFO
++      help
++        Include in-kernel hooks for kgdb, the Linux kernel source level
++        debugger.  See <http://kgdb.sourceforge.net/> for more information.
++        Unless you are intending to debug the kernel, say N here.
 +
-+  if (use_sg) {
-     struct scatterlist *sg;  /* Must be mid-level SCSI code scatterlist */
-     /*
-@@ -10219,11 +10213,11 @@
-      * differences and the kernel SG list uses virtual addresses where
-      * we need physical addresses.
-      */
--    int i, use_sg;
-+    int i;
--    sg = (struct scatterlist *)cmd->request_buffer;
-     scb->sg_length = 0;
--    use_sg = pci_map_sg(p->pdev, sg, cmd->use_sg, cmd->sc_data_direction);
++choice
++      prompt "Serial Port"
++      depends on KGDB
++      default KGDB_TTYS1
 +
++config KGDB_TTYS0
++      bool "ttyS0"
 +
-     /*
-      * Copy the segments into the SG array.  NOTE!!! - We used to
-      * have the first entry both in the data_pointer area and the first
-@@ -10231,10 +10225,9 @@
-      * entry in both places, but now we download the address of
-      * scb->sg_list[1] instead of 0 to the sg pointer in the hscb.
-      */
--    for (i = 0; i < use_sg; i++)
--    {
--      unsigned int len = sg_dma_len(sg+i);
--      scb->sg_list[i].address = cpu_to_le32(sg_dma_address(sg+i));
-+    scsi_for_each_sg(cmd, sg, use_sg, i) {
-+      unsigned int len = sg_dma_len(sg);
-+      scb->sg_list[i].address = cpu_to_le32(sg_dma_address(sg));
-       scb->sg_list[i].length = cpu_to_le32(len);
-       scb->sg_length += len;
-     }
-@@ -10244,26 +10237,7 @@
-     scb->sg_count = i;
-     hscb->SG_segment_count = i;
-     hscb->SG_list_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, &scb->sg_list[1]));
--  }
--  else
--  {
--    if (cmd->request_bufflen)
--    {
--      unsigned int address = pci_map_single(p->pdev, cmd->request_buffer,
--                                          cmd->request_bufflen,
--                                            cmd->sc_data_direction);
--      aic7xxx_mapping(cmd) = address;
--      scb->sg_list[0].address = cpu_to_le32(address);
--      scb->sg_list[0].length = cpu_to_le32(cmd->request_bufflen);
--      scb->sg_count = 1;
--      scb->sg_length = cmd->request_bufflen;
--      hscb->SG_segment_count = 1;
--      hscb->SG_list_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, &scb->sg_list[0]));
--      hscb->data_count = scb->sg_list[0].length;
--      hscb->data_pointer = scb->sg_list[0].address;
--    }
--    else
--    {
-+  } else {
-       scb->sg_count = 0;
-       scb->sg_length = 0;
-       hscb->SG_segment_count = 0;
-@@ -10271,7 +10245,6 @@
-       hscb->data_count = 0;
-       hscb->data_pointer = 0;
-     }
--  }
++config KGDB_TTYS1
++      bool "ttyS1"
++
++config KGDB_TTYS2
++      bool "ttyS2"
++
++config KGDB_TTYS3
++      bool "ttyS3"
++
++endchoice
++
++config KGDB_CONSOLE
++      bool "Enable serial console thru kgdb port"
++      depends on KGDB && 8xx || CPM2
++      help
++        If you enable this, all serial console messages will be sent
++        over the gdb stub.
++        If unsure, say N.
++
+ config XMON
+       bool "Include xmon kernel debugger"
+       depends on DEBUG_KERNEL
+diff -Nurb linux-2.6.22-590/arch/ppc/amiga/config.c linux-2.6.22-570/arch/ppc/amiga/config.c
+--- linux-2.6.22-590/arch/ppc/amiga/config.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/amiga/config.c   2007-07-08 19:32:17.000000000 -0400
+@@ -753,11 +753,17 @@
+ void amiga_serial_console_write(struct console *co, const char *s,
+                                      unsigned int count)
+ {
++#if 0 /* def CONFIG_KGDB */
++      /* FIXME:APUS GDB doesn't seem to like O-packages before it is
++           properly connected with the target. */
++      __gdb_output_string (s, count);
++#else
+       while (count--) {
+               if (*s == '\n')
+                       amiga_serial_putc('\r');
+               amiga_serial_putc(*s++);
+       }
++#endif
  }
  
- /*+F*************************************************************************
-diff -Nurb linux-2.6.22-570/drivers/scsi/amiga7xx.c linux-2.6.22-590/drivers/scsi/amiga7xx.c
---- linux-2.6.22-570/drivers/scsi/amiga7xx.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/amiga7xx.c   1969-12-31 19:00:00.000000000 -0500
-@@ -1,138 +0,0 @@
+ #ifdef CONFIG_SERIAL_CONSOLE
+diff -Nurb linux-2.6.22-590/arch/ppc/kernel/Makefile linux-2.6.22-570/arch/ppc/kernel/Makefile
+--- linux-2.6.22-590/arch/ppc/kernel/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/kernel/Makefile  2007-07-08 19:32:17.000000000 -0400
+@@ -14,7 +14,7 @@
+ obj-$(CONFIG_MODULES)         += ppc_ksyms.o
+ obj-$(CONFIG_PCI)             += pci.o
+ obj-$(CONFIG_RAPIDIO)         += rio.o
+-obj-$(CONFIG_KGDB)            += kgdb.o kgdb_setjmp32.o
++obj-$(CONFIG_KGDB)            += ppc-stub.o
+ obj-$(CONFIG_SMP)             += smp.o smp-tbsync.o
+ obj-$(CONFIG_KEXEC)           += machine_kexec.o relocate_kernel.o
+diff -Nurb linux-2.6.22-590/arch/ppc/kernel/kgdb.c linux-2.6.22-570/arch/ppc/kernel/kgdb.c
+--- linux-2.6.22-590/arch/ppc/kernel/kgdb.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/kernel/kgdb.c    1969-12-31 19:00:00.000000000 -0500
+@@ -1,348 +0,0 @@
 -/*
-- * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
-- *            Amiga MacroSystemUS WarpEngine SCSI controller.
-- *            Amiga Technologies A4000T SCSI controller.
-- *            Amiga Technologies/DKB A4091 SCSI controller.
+- * arch/ppc/kernel/kgdb.c
 - *
-- * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
-- * plus modifications of the 53c7xx.c driver to support the Amiga.
+- * PowerPC backend to the KGDB stub.
+- *
+- * Maintainer: Tom Rini <trini@kernel.crashing.org>
+- *
+- * 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu)
+- * Copyright (C) 2003 Timesys Corporation.
+- * Copyright (C) 2004, 2006 MontaVista Software, Inc.
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program as licensed "as is" without any warranty of any
+- * kind, whether express or implied.
 - */
--#include <linux/types.h>
--#include <linux/mm.h>
--#include <linux/blkdev.h>
--#include <linux/zorro.h>
--#include <linux/stat.h>
 -
--#include <asm/setup.h>
--#include <asm/page.h>
--#include <asm/pgtable.h>
--#include <asm/amigaints.h>
--#include <asm/amigahw.h>
--#include <asm/dma.h>
--#include <asm/irq.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/kgdb.h>
+-#include <linux/smp.h>
+-#include <linux/signal.h>
+-#include <linux/ptrace.h>
+-#include <asm/current.h>
+-#include <asm/ptrace.h>
+-#include <asm/processor.h>
+-#include <asm/machdep.h>
+-
+-/*
+- * This table contains the mapping between PowerPC hardware trap types, and
+- * signals, which are primarily what GDB understands.  GDB and the kernel
+- * don't always agree on values, so we use constants taken from gdb-6.2.
+- */
+-static struct hard_trap_info
+-{
+-      unsigned int tt;                /* Trap type code for powerpc */
+-      unsigned char signo;            /* Signal that we map this trap into */
+-} hard_trap_info[] = {
+-      { 0x0100, 0x02 /* SIGINT */  },         /* system reset */
+-      { 0x0200, 0x0b /* SIGSEGV */ },         /* machine check */
+-      { 0x0300, 0x0b /* SIGSEGV */ },         /* data access */
+-      { 0x0400, 0x0b /* SIGSEGV */ },         /* instruction access */
+-      { 0x0500, 0x02 /* SIGINT */  },         /* external interrupt */
+-      { 0x0600, 0x0a /* SIGBUS */  },         /* alignment */
+-      { 0x0700, 0x05 /* SIGTRAP */ },         /* program check */
+-      { 0x0800, 0x08 /* SIGFPE */  },         /* fp unavailable */
+-      { 0x0900, 0x0e /* SIGALRM */ },         /* decrementer */
+-      { 0x0c00, 0x14 /* SIGCHLD */ },         /* system call */
+-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+-      { 0x2002, 0x05 /* SIGTRAP */ },         /* debug */
+-#if defined(CONFIG_FSL_BOOKE)
+-      { 0x2010, 0x08 /* SIGFPE */  },         /* spe unavailable */
+-      { 0x2020, 0x08 /* SIGFPE */  },         /* spe unavailable */
+-      { 0x2030, 0x08 /* SIGFPE */  },         /* spe fp data */
+-      { 0x2040, 0x08 /* SIGFPE */  },         /* spe fp data */
+-      { 0x2050, 0x08 /* SIGFPE */  },         /* spe fp round */
+-      { 0x2060, 0x0e /* SIGILL */  },         /* performace monitor */
+-      { 0x2900, 0x08 /* SIGFPE */  },         /* apu unavailable */
+-      { 0x3100, 0x0e /* SIGALRM */ },         /* fixed interval timer */
+-      { 0x3200, 0x02 /* SIGINT */  },         /* watchdog */
+-#else
+-      { 0x1000, 0x0e /* SIGALRM */ },         /* programmable interval timer */
+-      { 0x1010, 0x0e /* SIGALRM */ },         /* fixed interval timer */
+-      { 0x1020, 0x02 /* SIGINT */  },         /* watchdog */
+-      { 0x2010, 0x08 /* SIGFPE */  },         /* fp unavailable */
+-      { 0x2020, 0x08 /* SIGFPE */  },         /* ap unavailable */
+-#endif
+-#else
+-      { 0x0d00, 0x05 /* SIGTRAP */ },         /* single-step */
+-#if defined(CONFIG_8xx)
+-      { 0x1000, 0x04 /* SIGILL */  },         /* software emulation */
+-#else
+-      { 0x0f00, 0x04 /* SIGILL */  },         /* performance monitor */
+-      { 0x0f20, 0x08 /* SIGFPE */  },         /* altivec unavailable */
+-      { 0x1300, 0x05 /* SIGTRAP */ },         /* instruction address break */
+-      { 0x1400, 0x02 /* SIGINT */  },         /* SMI */
+-      { 0x1600, 0x08 /* SIGFPE */  },         /* altivec assist */
+-      { 0x1700, 0x04 /* SIGILL */  },         /* TAU */
+-      { 0x2000, 0x05 /* SIGTRAP */ },         /* run mode */
+-#endif
+-#endif
+-      { 0x0000, 0x00 }                        /* Must be last */
+-};
+-
+-extern atomic_t cpu_doing_single_step;
 -
--#include "scsi.h"
--#include <scsi/scsi_host.h>
--#include "53c7xx.h"
--#include "amiga7xx.h"
+-static int computeSignal(unsigned int tt)
+-{
+-      struct hard_trap_info *ht;
+-
+-      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+-              if (ht->tt == tt)
+-                      return ht->signo;
+-
+-      return SIGHUP;          /* default for things we don't know about */
+-}
 -
+-/* KGDB functions to use existing PowerPC hooks. */
+-static void kgdb_debugger(struct pt_regs *regs)
+-{
+-      kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
+-}
 -
--static int amiga7xx_register_one(struct scsi_host_template *tpnt,
--                               unsigned long address)
+-static int kgdb_breakpoint(struct pt_regs *regs)
 -{
--    long long options;
--    int clock;
+-      if (user_mode(regs))
+-              return 0;
 -
--    if (!request_mem_region(address, 0x1000, "ncr53c710"))
--      return 0;
+-      kgdb_handle_exception(0, SIGTRAP, 0, regs);
+-
+-      if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
+-              regs->nip += 4;
 -
--    address = (unsigned long)z_ioremap(address, 0x1000);
--    options = OPTION_MEMORY_MAPPED | OPTION_DEBUG_TEST1 | OPTION_INTFLY |
--            OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS |
--            OPTION_DISCONNECT;
--    clock = 50000000; /* 50 MHz SCSI Clock */
--    ncr53c7xx_init(tpnt, 0, 710, address, 0, IRQ_AMIGA_PORTS, DMA_NONE,
--                 options, clock);
--    return 1;
+-      return 1;
 -}
 -
+-static int kgdb_singlestep(struct pt_regs *regs)
+-{
+-      struct thread_info *thread_info, *exception_thread_info;
 -
--#ifdef CONFIG_ZORRO
+-      if (user_mode(regs))
+-              return 0;
+-      /*
+-      * On Book E and perhaps other processsors, singlestep is handled on
+-      * the critical exception stack.  This causes current_thread_info()
+-      * to fail, since it it locates the thread_info by masking off
+-      * the low bits of the current stack pointer.  We work around
+-      * this issue by copying the thread_info from the kernel stack
+-      * before calling kgdb_handle_exception, and copying it back
+-      * afterwards.  On most processors the copy is avoided since
+-      * exception_thread_info == thread_info.
+-      */
+-      thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
+-      exception_thread_info = current_thread_info();
 -
--static struct {
--    zorro_id id;
--    unsigned long offset;
--    int absolute;     /* offset is absolute address */
--} amiga7xx_table[] = {
--    { .id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS, .offset = 0xf40000,
--      .absolute = 1 },
--    { .id = ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx, .offset = 0x40000 },
--    { .id = ZORRO_PROD_CBM_A4091_1, .offset = 0x800000 },
--    { .id = ZORRO_PROD_CBM_A4091_2, .offset = 0x800000 },
--    { .id = ZORRO_PROD_GVP_GFORCE_040_060, .offset = 0x40000 },
--    { 0 }
--};
+-      if (thread_info != exception_thread_info)
+-              memcpy(exception_thread_info, thread_info, sizeof *thread_info);
 -
--static int __init amiga7xx_zorro_detect(struct scsi_host_template *tpnt)
--{
--    int num = 0, i;
--    struct zorro_dev *z = NULL;
--    unsigned long address;
+-      kgdb_handle_exception(0, SIGTRAP, 0, regs);
 -
--    while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
--      for (i = 0; amiga7xx_table[i].id; i++)
--          if (z->id == amiga7xx_table[i].id)
--              break;
--      if (!amiga7xx_table[i].id)
--          continue;
--      if (amiga7xx_table[i].absolute)
--          address = amiga7xx_table[i].offset;
--      else
--          address = z->resource.start + amiga7xx_table[i].offset;
--      num += amiga7xx_register_one(tpnt, address);
--    }
--    return num;
+-      if (thread_info != exception_thread_info)
+-              memcpy(thread_info, exception_thread_info, sizeof *thread_info);
+-
+-      return 1;
 -}
 -
--#endif /* CONFIG_ZORRO */
+-int kgdb_iabr_match(struct pt_regs *regs)
+-{
+-      if (user_mode(regs))
+-              return 0;
 -
+-      kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
+-      return 1;
+-}
 -
--int __init amiga7xx_detect(struct scsi_host_template *tpnt)
+-int kgdb_dabr_match(struct pt_regs *regs)
 -{
--    static unsigned char called = 0;
--    int num = 0;
+-      if (user_mode(regs))
+-              return 0;
 -
--    if (called || !MACH_IS_AMIGA)
--      return 0;
+-      kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
+-      return 1;
+-}
 -
--    tpnt->proc_name = "Amiga7xx";
+-void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+-{
+-      unsigned long *ptr = gdb_regs;
+-      int reg;
+-
+-      memset(gdb_regs, 0, MAXREG * 4);
 -
--    if (AMIGAHW_PRESENT(A4000_SCSI))
--      num += amiga7xx_register_one(tpnt, 0xdd0040);
+-      for (reg = 0; reg < 32; reg++)
+-              *(ptr++) = regs->gpr[reg];
 -
--#ifdef CONFIG_ZORRO
--    num += amiga7xx_zorro_detect(tpnt);
+-#ifdef CONFIG_FSL_BOOKE
+-#ifdef CONFIG_SPE
+-      for (reg = 0; reg < 32; reg++)
+-              *(ptr++) = current->thread.evr[reg];
+-#else
+-      ptr += 32;
+-#endif
+-#else
+-      ptr += 64;
 -#endif
 -
--    called = 1;
--    return num;
+-      *(ptr++) = regs->nip;
+-      *(ptr++) = regs->msr;
+-      *(ptr++) = regs->ccr;
+-      *(ptr++) = regs->link;
+-      *(ptr++) = regs->ctr;
+-      *(ptr++) = regs->xer;
+-
+-#ifdef CONFIG_SPE
+-      /* u64 acc */
+-      *(ptr++) = current->thread.acc >> 32;
+-      *(ptr++) = current->thread.acc & 0xffffffff;
+-      *(ptr++) = current->thread.spefscr;
+-#endif
 -}
 -
--static int amiga7xx_release(struct Scsi_Host *shost)
+-void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
 -{
--      if (shost->irq)
--              free_irq(shost->irq, NULL);
--      if (shost->dma_channel != 0xff)
--              free_dma(shost->dma_channel);
--      if (shost->io_port && shost->n_io_port)
--              release_region(shost->io_port, shost->n_io_port);
--      scsi_unregister(shost);
--      return 0;
--}
+-      struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
+-                                                STACK_FRAME_OVERHEAD);
+-      unsigned long *ptr = gdb_regs;
+-      int reg;
 -
--static struct scsi_host_template driver_template = {
--      .name                   = "Amiga NCR53c710 SCSI",
--      .detect                 = amiga7xx_detect,
--      .release                = amiga7xx_release,
--      .queuecommand           = NCR53c7xx_queue_command,
--      .abort                  = NCR53c7xx_abort,
--      .reset                  = NCR53c7xx_reset,
--      .can_queue              = 24,
--      .this_id                = 7,
--      .sg_tablesize           = 63,
--      .cmd_per_lun            = 3,
--      .use_clustering         = DISABLE_CLUSTERING
--};
+-      memset(gdb_regs, 0, MAXREG * 4);
 -
+-      /* Regs GPR0-2 */
+-      for (reg = 0; reg < 3; reg++)
+-              *(ptr++) = regs->gpr[reg];
 -
--#include "scsi_module.c"
-diff -Nurb linux-2.6.22-570/drivers/scsi/amiga7xx.h linux-2.6.22-590/drivers/scsi/amiga7xx.h
---- linux-2.6.22-570/drivers/scsi/amiga7xx.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/amiga7xx.h   1969-12-31 19:00:00.000000000 -0500
-@@ -1,23 +0,0 @@
--#ifndef AMIGA7XX_H
+-      /* Regs GPR3-13 are not saved */
+-      ptr += 11;
 -
--#include <linux/types.h>
+-      /* Regs GPR14-31 */
+-      for (reg = 14; reg < 32; reg++)
+-              *(ptr++) = regs->gpr[reg];
+-
+-#ifdef CONFIG_FSL_BOOKE
+-#ifdef CONFIG_SPE
+-      for (reg = 0; reg < 32; reg++)
+-              *(ptr++) = p->thread.evr[reg];
+-#else
+-      ptr += 32;
+-#endif
+-#else
+-      ptr += 64;
+-#endif
 -
--int amiga7xx_detect(struct scsi_host_template *);
--const char *NCR53c7x0_info(void);
--int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
--int NCR53c7xx_abort(Scsi_Cmnd *);
--int NCR53c7x0_release (struct Scsi_Host *);
--int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
--void NCR53c7x0_intr(int irq, void *dev_id);
+-      *(ptr++) = regs->nip;
+-      *(ptr++) = regs->msr;
+-      *(ptr++) = regs->ccr;
+-      *(ptr++) = regs->link;
+-      *(ptr++) = regs->ctr;
+-      *(ptr++) = regs->xer;
 -
--#ifndef CMD_PER_LUN
--#define CMD_PER_LUN 3
+-#ifdef CONFIG_SPE
+-      /* u64 acc */
+-      *(ptr++) = p->thread.acc >> 32;
+-      *(ptr++) = p->thread.acc & 0xffffffff;
+-      *(ptr++) = p->thread.spefscr;
 -#endif
+-}
 -
--#ifndef CAN_QUEUE
--#define CAN_QUEUE 24
+-void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+-{
+-      unsigned long *ptr = gdb_regs;
+-      int reg;
+-#ifdef CONFIG_SPE
+-      union {
+-              u32 v32[2];
+-              u64 v64;
+-      } acc;
 -#endif
 -
--#include <scsi/scsicam.h>
+-      for (reg = 0; reg < 32; reg++)
+-              regs->gpr[reg] = *(ptr++);
 -
--#endif /* AMIGA7XX_H */
-diff -Nurb linux-2.6.22-570/drivers/scsi/arcmsr/arcmsr.h linux-2.6.22-590/drivers/scsi/arcmsr/arcmsr.h
---- linux-2.6.22-570/drivers/scsi/arcmsr/arcmsr.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/arcmsr/arcmsr.h      2008-01-02 13:56:37.000000000 -0500
-@@ -48,9 +48,10 @@
- #define ARCMSR_MAX_OUTSTANDING_CMD                                            256
- #define ARCMSR_MAX_FREECCB_NUM                                                        288
--#define ARCMSR_DRIVER_VERSION                         "Driver Version 1.20.00.13"
-+#define ARCMSR_DRIVER_VERSION                         "Driver Version 1.20.00.14"
- #define ARCMSR_SCSI_INITIATOR_ID                                              255
- #define ARCMSR_MAX_XFER_SECTORS                                                       512
-+#define ARCMSR_MAX_XFER_SECTORS_B                                              4096
- #define ARCMSR_MAX_TARGETID                                                    17
- #define ARCMSR_MAX_TARGETLUN                                                    8
- #define ARCMSR_MAX_CMD_PERLUN                          ARCMSR_MAX_OUTSTANDING_CMD
-@@ -469,4 +470,3 @@
- extern struct class_device_attribute *arcmsr_host_attrs[];
- extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb);
- void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb);
+-#ifdef CONFIG_FSL_BOOKE
+-#ifdef CONFIG_SPE
+-      for (reg = 0; reg < 32; reg++)
+-              current->thread.evr[reg] = *(ptr++);
+-#else
+-      ptr += 32;
+-#endif
+-#else
+-      ptr += 64;
+-#endif
 -
-diff -Nurb linux-2.6.22-570/drivers/scsi/arcmsr/arcmsr_attr.c linux-2.6.22-590/drivers/scsi/arcmsr/arcmsr_attr.c
---- linux-2.6.22-570/drivers/scsi/arcmsr/arcmsr_attr.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/arcmsr/arcmsr_attr.c 2008-01-02 13:56:37.000000000 -0500
-@@ -59,8 +59,9 @@
- struct class_device_attribute *arcmsr_host_attrs[];
- static ssize_t
--arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+arcmsr_sysfs_iop_message_read(struct kobject *kobj,
-+                            struct bin_attribute *bin_attr,
-+                            char *buf, loff_t off, size_t count)
- {
-       struct class_device *cdev = container_of(kobj,struct class_device,kobj);
-       struct Scsi_Host *host = class_to_shost(cdev);
-@@ -105,8 +106,9 @@
- }
- static ssize_t
--arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+arcmsr_sysfs_iop_message_write(struct kobject *kobj,
-+                             struct bin_attribute *bin_attr,
-+                             char *buf, loff_t off, size_t count)
- {
-       struct class_device *cdev = container_of(kobj,struct class_device,kobj);
-       struct Scsi_Host *host = class_to_shost(cdev);
-@@ -152,8 +154,9 @@
- }
- static ssize_t
--arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
-+                             struct bin_attribute *bin_attr,
-+                             char *buf, loff_t off, size_t count)
- {
-       struct class_device *cdev = container_of(kobj,struct class_device,kobj);
-       struct Scsi_Host *host = class_to_shost(cdev);
-@@ -188,7 +191,6 @@
-       .attr = {
-               .name = "mu_read",
-               .mode = S_IRUSR ,
--              .owner = THIS_MODULE,
-       },
-       .size = 1032,
-       .read = arcmsr_sysfs_iop_message_read,
-@@ -198,7 +200,6 @@
-       .attr = {
-               .name = "mu_write",
-               .mode = S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = 1032,
-       .write = arcmsr_sysfs_iop_message_write,
-@@ -208,7 +209,6 @@
-       .attr = {
-               .name = "mu_clear",
-               .mode = S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = 1,
-       .write = arcmsr_sysfs_iop_message_clear,
-diff -Nurb linux-2.6.22-570/drivers/scsi/arcmsr/arcmsr_hba.c linux-2.6.22-590/drivers/scsi/arcmsr/arcmsr_hba.c
---- linux-2.6.22-570/drivers/scsi/arcmsr/arcmsr_hba.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/arcmsr/arcmsr_hba.c  2008-01-02 13:56:37.000000000 -0500
-@@ -57,6 +57,7 @@
- #include <linux/dma-mapping.h>
- #include <linux/timer.h>
- #include <linux/pci.h>
-+#include <linux/aer.h>
- #include <asm/dma.h>
- #include <asm/io.h>
- #include <asm/system.h>
-@@ -71,7 +72,7 @@
- #include "arcmsr.h"
- MODULE_AUTHOR("Erich Chen <erich@areca.com.tw>");
--MODULE_DESCRIPTION("ARECA (ARC11xx/12xx) SATA RAID HOST Adapter");
-+MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter");
- MODULE_LICENSE("Dual BSD/GPL");
- MODULE_VERSION(ARCMSR_DRIVER_VERSION);
-@@ -93,7 +94,9 @@
- static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb);
- static const char *arcmsr_info(struct Scsi_Host *);
- static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
+-      regs->nip = *(ptr++);
+-      regs->msr = *(ptr++);
+-      regs->ccr = *(ptr++);
+-      regs->link = *(ptr++);
+-      regs->ctr = *(ptr++);
+-      regs->xer = *(ptr++);
 -
-+static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev,
-+                                              pci_channel_state_t state);
-+static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev);
- static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth)
- {
-       if (queue_depth > ARCMSR_MAX_CMD_PERLUN)
-@@ -104,7 +107,8 @@
- static struct scsi_host_template arcmsr_scsi_host_template = {
-       .module                 = THIS_MODULE,
--      .name                   = "ARCMSR ARECA SATA RAID HOST Adapter" ARCMSR_DRIVER_VERSION,
-+      .name                   = "ARCMSR ARECA SATA/SAS RAID HOST Adapter"
-+                                                      ARCMSR_DRIVER_VERSION,
-       .info                   = arcmsr_info,
-       .queuecommand           = arcmsr_queue_command,
-       .eh_abort_handler       = arcmsr_abort,
-@@ -119,6 +123,10 @@
-       .use_clustering         = ENABLE_CLUSTERING,
-       .shost_attrs            = arcmsr_host_attrs,
- };
-+static struct pci_error_handlers arcmsr_pci_error_handlers = {
-+      .error_detected         = arcmsr_pci_error_detected,
-+      .slot_reset             = arcmsr_pci_slot_reset,
-+};
- static struct pci_device_id arcmsr_device_id_table[] = {
-       {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)},
-@@ -144,7 +152,8 @@
-       .id_table               = arcmsr_device_id_table,
-       .probe                  = arcmsr_probe,
-       .remove                 = arcmsr_remove,
--      .shutdown               = arcmsr_shutdown
-+      .shutdown               = arcmsr_shutdown,
-+      .err_handler            = &arcmsr_pci_error_handlers,
- };
- static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id)
-@@ -328,6 +337,8 @@
-       arcmsr_iop_init(acb);
-       pci_set_drvdata(pdev, host);
-+      if (strncmp(acb->firm_version, "V1.42", 5) >= 0)
-+              host->max_sectors= ARCMSR_MAX_XFER_SECTORS_B;
-       error = scsi_add_host(host, &pdev->dev);
-       if (error)
-@@ -338,6 +349,7 @@
-               goto out_free_sysfs;
-       scsi_scan_host(host);
-+      pci_enable_pcie_error_reporting(pdev);
-       return 0;
-  out_free_sysfs:
-  out_free_irq:
-@@ -369,19 +381,9 @@
- static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb)
- {
--      struct AdapterControlBlock *acb = ccb->acb;
-       struct scsi_cmnd *pcmd = ccb->pcmd;
--      if (pcmd->use_sg != 0) {
--              struct scatterlist *sl;
+-#ifdef CONFIG_SPE
+-      /* u64 acc */
+-      acc.v32[0] = *(ptr++);
+-      acc.v32[1] = *(ptr++);
+-      current->thread.acc = acc.v64;
+-      current->thread.spefscr = *(ptr++);
+-#endif
+-}
+-
+-/*
+- * This function does PowerPC specific processing for interfacing to gdb.
+- */
+-int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+-                             char *remcom_in_buffer, char *remcom_out_buffer,
+-                             struct pt_regs *linux_regs)
+-{
+-      char *ptr = &remcom_in_buffer[1];
+-      unsigned long addr;
+-
+-      switch (remcom_in_buffer[0])
+-              {
+-              /*
+-               * sAA..AA   Step one instruction from AA..AA
+-               * This will return an error to gdb ..
+-               */
+-              case 's':
+-              case 'c':
+-                      /* handle the optional parameter */
+-                      if (kgdb_hex2long (&ptr, &addr))
+-                              linux_regs->nip = addr;
 -
--              sl = (struct scatterlist *)pcmd->request_buffer;
--              pci_unmap_sg(acb->pdev, sl, pcmd->use_sg, pcmd->sc_data_direction);
+-                      atomic_set(&cpu_doing_single_step, -1);
+-                      /* set the trace bit if we're stepping */
+-                      if (remcom_in_buffer[0] == 's') {
+-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+-                              mtspr(SPRN_DBCR0,
+-                                    mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
+-                              linux_regs->msr |= MSR_DE;
+-#else
+-                              linux_regs->msr |= MSR_SE;
+-#endif
+-                              debugger_step = 1;
+-                              if (kgdb_contthread)
+-                                      atomic_set(&cpu_doing_single_step,
+-                                                      smp_processor_id());
+-                      }
+-                      return 0;
 -      }
--      else if (pcmd->request_bufflen != 0)
--              pci_unmap_single(acb->pdev,
--                      pcmd->SCp.dma_handle,
--                      pcmd->request_bufflen, pcmd->sc_data_direction);
-+      scsi_dma_unmap(pcmd);
- }
- static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag)
-@@ -498,7 +500,7 @@
- static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
- {
--      struct MessageUnit __iomem *reg=acb->pmu;
-+      struct MessageUnit __iomem *reg = acb->pmu;
-       writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, &reg->inbound_msgaddr0);
-       if (arcmsr_wait_msgint_ready(acb))
-@@ -551,6 +553,7 @@
-       int8_t *psge = (int8_t *)&arcmsr_cdb->u;
-       uint32_t address_lo, address_hi;
-       int arccdbsize = 0x30;
-+      int nseg;
-       ccb->pcmd = pcmd;
-       memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB));
-@@ -561,20 +564,20 @@
-       arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len;
-       arcmsr_cdb->Context = (unsigned long)arcmsr_cdb;
-       memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len);
--      if (pcmd->use_sg) {
--              int length, sgcount, i, cdb_sgcount = 0;
--              struct scatterlist *sl;
 -
--              /* Get Scatter Gather List from scsiport. */
--              sl = (struct scatterlist *) pcmd->request_buffer;
--              sgcount = pci_map_sg(acb->pdev, sl, pcmd->use_sg,
--                              pcmd->sc_data_direction);
+-      return -1;
+-}
+-
+-/*
+- * Global data
+- */
+-struct kgdb_arch arch_kgdb_ops = {
+-      .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
+-};
+-
+-int kgdb_arch_init(void)
+-{
+-      debugger = kgdb_debugger;
+-      debugger_bpt = kgdb_breakpoint;
+-      debugger_sstep = kgdb_singlestep;
+-      debugger_iabr_match = kgdb_iabr_match;
+-      debugger_dabr_match = kgdb_dabr_match;
+-
+-      return 0;
+-}
+-
+-arch_initcall(kgdb_arch_init);
+diff -Nurb linux-2.6.22-590/arch/ppc/kernel/kgdb_setjmp32.S linux-2.6.22-570/arch/ppc/kernel/kgdb_setjmp32.S
+--- linux-2.6.22-590/arch/ppc/kernel/kgdb_setjmp32.S   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/kernel/kgdb_setjmp32.S   1969-12-31 19:00:00.000000000 -0500
+@@ -1,41 +0,0 @@
+-/*
+- * Copyright (C) 1996 Paul Mackerras
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program as licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
+-
+-#include <asm/processor.h>
+-#include <asm/ppc_asm.h>
+-
+-      .text
+-
+-/*
+- * Save/restore state in case a memory access causes a fault.
+- *
+- * int kgdb_fault_setjmp(unsigned long *curr_context);
+- * void kgdb_fault_longjmp(unsigned long *curr_context);
+- */
+-
+-_GLOBAL(kgdb_fault_setjmp)
+-      mflr    r0
+-      stw     r0,0(r3)
+-      stw     r1,4(r3)
+-      stw     r2,8(r3)
+-      mfcr    r0
+-      stw     r0,12(r3)
+-      stmw    r13,16(r3)
+-      li      r3,0
+-      blr
+-
+-_GLOBAL(kgdb_fault_longjmp)
+-      lmw     r13,16(r3)
+-      lwz     r0,12(r3)
+-      mtcrf   0x38,r0
+-      lwz     r0,0(r3)
+-      lwz     r1,4(r3)
+-      lwz     r2,8(r3)
+-      mtlr    r0
+-      mr      r3,r1
+-      blr
+diff -Nurb linux-2.6.22-590/arch/ppc/kernel/misc.S linux-2.6.22-570/arch/ppc/kernel/misc.S
+--- linux-2.6.22-590/arch/ppc/kernel/misc.S    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/kernel/misc.S    2008-01-23 19:16:04.000000000 -0500
+@@ -328,7 +328,7 @@
+       mtspr   SPRN_L1CSR0,r3
+       isync
+       blr
+-END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
++END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+       mfspr   r3,SPRN_L1CSR1
+       ori     r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
+       mtspr   SPRN_L1CSR1,r3
+@@ -355,7 +355,7 @@
+ _GLOBAL(__flush_icache_range)
+ BEGIN_FTR_SECTION
+       blr                             /* for 601, do nothing */
+-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
++END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+       li      r5,L1_CACHE_BYTES-1
+       andc    r3,r3,r5
+       subf    r4,r3,r4
+@@ -472,7 +472,7 @@
+ _GLOBAL(__flush_dcache_icache)
+ BEGIN_FTR_SECTION
+       blr                                     /* for 601, do nothing */
+-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
++END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+       rlwinm  r3,r3,0,0,19                    /* Get page base address */
+       li      r4,4096/L1_CACHE_BYTES  /* Number of lines in a page */
+       mtctr   r4
+@@ -500,7 +500,7 @@
+ _GLOBAL(__flush_dcache_icache_phys)
+ BEGIN_FTR_SECTION
+       blr                                     /* for 601, do nothing */
+-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
++END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+       mfmsr   r10
+       rlwinm  r0,r10,0,28,26                  /* clear DR */
+       mtmsr   r0
+diff -Nurb linux-2.6.22-590/arch/ppc/kernel/ppc-stub.c linux-2.6.22-570/arch/ppc/kernel/ppc-stub.c
+--- linux-2.6.22-590/arch/ppc/kernel/ppc-stub.c        1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/kernel/ppc-stub.c        2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,866 @@
++/*
++ * ppc-stub.c:  KGDB support for the Linux kernel.
++ *
++ * adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC
++ * some stuff borrowed from Paul Mackerras' xmon
++ * Copyright (C) 1998 Michael AK Tesch (tesch@cs.wisc.edu)
++ *
++ * Modifications to run under Linux
++ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
++ *
++ * This file originally came from the gdb sources, and the
++ * copyright notices have been retained below.
++ */
 +
-+      nseg = scsi_dma_map(pcmd);
-+      BUG_ON(nseg < 0);
++/****************************************************************************
 +
-+      if (nseg) {
-+              int length, i, cdb_sgcount = 0;
-+              struct scatterlist *sg;
++              THIS SOFTWARE IS NOT COPYRIGHTED
 +
-               /* map stor port SG list to our iop SG List. */
--              for (i = 0; i < sgcount; i++) {
-+              scsi_for_each_sg(pcmd, sg, nseg, i) {
-                       /* Get the physical address of the current data pointer */
--                      length = cpu_to_le32(sg_dma_len(sl));
--                      address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sl)));
--                      address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sl)));
-+                      length = cpu_to_le32(sg_dma_len(sg));
-+                      address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sg)));
-+                      address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sg)));
-                       if (address_hi == 0) {
-                               struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge;
-@@ -591,32 +594,12 @@
-                               psge += sizeof (struct SG64ENTRY);
-                               arccdbsize += sizeof (struct SG64ENTRY);
-                       }
--                      sl++;
-                       cdb_sgcount++;
-               }
-               arcmsr_cdb->sgcount = (uint8_t)cdb_sgcount;
--              arcmsr_cdb->DataLength = pcmd->request_bufflen;
-+              arcmsr_cdb->DataLength = scsi_bufflen(pcmd);
-               if ( arccdbsize > 256)
-                       arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE;
--      } else if (pcmd->request_bufflen) {
--              dma_addr_t dma_addr;
--              dma_addr = pci_map_single(acb->pdev, pcmd->request_buffer,
--                              pcmd->request_bufflen, pcmd->sc_data_direction);
--              pcmd->SCp.dma_handle = dma_addr;
--              address_lo = cpu_to_le32(dma_addr_lo32(dma_addr));
--              address_hi = cpu_to_le32(dma_addr_hi32(dma_addr));
--              if (address_hi == 0) {
--                      struct  SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge;
--                      pdma_sg->address = address_lo;
--                      pdma_sg->length = pcmd->request_bufflen;
--              } else {
--                      struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge;
--                      pdma_sg->addresshigh = address_hi;
--                      pdma_sg->address = address_lo;
--                      pdma_sg->length = pcmd->request_bufflen|IS_SG64_ADDR;
--              }
--              arcmsr_cdb->sgcount = 1;
--              arcmsr_cdb->DataLength = pcmd->request_bufflen;
-       }
-       if (pcmd->sc_data_direction == DMA_TO_DEVICE ) {
-               arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
-@@ -758,20 +741,20 @@
-                               (flag_ccb << 5));
-                       if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
-                               if (ccb->startdone == ARCMSR_CCB_ABORTED) {
--                                      struct scsi_cmnd *abortcmd=ccb->pcmd;
-+                                      struct scsi_cmnd *abortcmd = ccb->pcmd;
-                                       if (abortcmd) {
-                                       abortcmd->result |= DID_ABORT >> 16;
-                                       arcmsr_ccb_complete(ccb, 1);
-                                       printk(KERN_NOTICE
--                                              "arcmsr%d: ccb='0x%p' isr got aborted command \n"
-+                                              "arcmsr%d: ccb ='0x%p' isr got aborted command \n"
-                                               , acb->host->host_no, ccb);
-                                       }
-                                       continue;
-                               }
-                               printk(KERN_NOTICE
--                                      "arcmsr%d: isr get an illegal ccb command done acb='0x%p'"
--                                      "ccb='0x%p' ccbacb='0x%p' startdone = 0x%x"
--                                      " ccboutstandingcount=%d \n"
-+                                      "arcmsr%d: isr get an illegal ccb command done acb = '0x%p'"
-+                                      "ccb = '0x%p' ccbacb = '0x%p' startdone = 0x%x"
-+                                      " ccboutstandingcount = %d \n"
-                                       , acb->host->host_no
-                                       , acb
-                                       , ccb
-@@ -791,7 +774,7 @@
-                               switch(ccb->arcmsr_cdb.DeviceStatus) {
-                               case ARCMSR_DEV_SELECT_TIMEOUT: {
-                                               acb->devstate[id][lun] = ARECA_RAID_GONE;
--                                              ccb->pcmd->result = DID_TIME_OUT << 16;
-+                                              ccb->pcmd->result = DID_NO_CONNECT << 16;
-                                               arcmsr_ccb_complete(ccb, 1);
-                                       }
-                                       break;
-@@ -810,8 +793,8 @@
-                                       break;
-                               default:
-                                       printk(KERN_NOTICE
--                                              "arcmsr%d: scsi id=%d lun=%d"
--                                              " isr get command error done,"
-+                                              "arcmsr%d: scsi id = %d lun = %d"
-+                                              " isr get command error done, "
-                                               "but got unknown DeviceStatus = 0x%x \n"
-                                               , acb->host->host_no
-                                               , id
-@@ -848,24 +831,21 @@
-       struct CMD_MESSAGE_FIELD *pcmdmessagefld;
-       int retvalue = 0, transfer_len = 0;
-       char *buffer;
-+      struct scatterlist *sg;
-       uint32_t controlcode = (uint32_t ) cmd->cmnd[5] << 24 |
-                                               (uint32_t ) cmd->cmnd[6] << 16 |
-                                               (uint32_t ) cmd->cmnd[7] << 8  |
-                                               (uint32_t ) cmd->cmnd[8];
-                                       /* 4 bytes: Areca io control code */
--      if (cmd->use_sg) {
--              struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer;
-+      sg = scsi_sglist(cmd);
-               buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
--              if (cmd->use_sg > 1) {
-+      if (scsi_sg_count(cmd) > 1) {
-                       retvalue = ARCMSR_MESSAGE_FAIL;
-                       goto message_out;
-               }
-               transfer_len += sg->length;
--      } else {
--              buffer = cmd->request_buffer;
--              transfer_len = cmd->request_bufflen;
--      }
++   HP offers the following for use in the public domain.  HP makes no
++   warranty with regard to the software or its performance and the
++   user accepts the software "AS IS" with all faults.
 +
-       if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) {
-               retvalue = ARCMSR_MESSAGE_FAIL;
-               goto message_out;
-@@ -1057,12 +1037,9 @@
-               retvalue = ARCMSR_MESSAGE_FAIL;
-       }
-  message_out:
--      if (cmd->use_sg) {
--              struct scatterlist *sg;
--
--              sg = (struct scatterlist *) cmd->request_buffer;
-+      sg = scsi_sglist(cmd);
-               kunmap_atomic(buffer - sg->offset, KM_IRQ0);
--      }
++   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
++   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
++   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 +
-       return retvalue;
- }
-@@ -1085,6 +1062,7 @@
-       case INQUIRY: {
-               unsigned char inqdata[36];
-               char *buffer;
-+              struct scatterlist *sg;
-               if (cmd->device->lun) {
-                       cmd->result = (DID_TIME_OUT << 16);
-@@ -1096,7 +1074,7 @@
-               inqdata[1] = 0;
-               /* rem media bit & Dev Type Modifier */
-               inqdata[2] = 0;
--              /* ISO,ECMA,& ANSI versions */
-+              /* ISO, ECMA, & ANSI versions */
-               inqdata[4] = 31;
-               /* length of additional data */
-               strncpy(&inqdata[8], "Areca   ", 8);
-@@ -1104,21 +1082,14 @@
-               strncpy(&inqdata[16], "RAID controller ", 16);
-               /* Product Identification */
-               strncpy(&inqdata[32], "R001", 4); /* Product Revision */
--              if (cmd->use_sg) {
--                      struct scatterlist *sg;
--                      sg = (struct scatterlist *) cmd->request_buffer;
-+              sg = scsi_sglist(cmd);
-                       buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
--              } else {
--                      buffer = cmd->request_buffer;
--              }
--              memcpy(buffer, inqdata, sizeof(inqdata));
--              if (cmd->use_sg) {
--                      struct scatterlist *sg;
--                      sg = (struct scatterlist *) cmd->request_buffer;
-+              memcpy(buffer, inqdata, sizeof(inqdata));
-+              sg = scsi_sglist(cmd);
-                       kunmap_atomic(buffer - sg->offset, KM_IRQ0);
--              }
++****************************************************************************/
 +
-               cmd->scsi_done(cmd);
-       }
-       break;
-@@ -1153,7 +1124,7 @@
-                       , acb->host->host_no);
-               return SCSI_MLQUEUE_HOST_BUSY;
-       }
--      if(target == 16) {
-+      if (target == 16) {
-               /* virtual device for iop message transfer */
-               arcmsr_handle_virtual_command(acb, cmd);
-               return 0;
-@@ -1166,7 +1137,7 @@
-                       printk(KERN_NOTICE
-                               "arcmsr%d: block 'read/write'"
-                               "command with gone raid volume"
--                              " Cmd=%2x, TargetId=%d, Lun=%d \n"
-+                              " Cmd = %2x, TargetId = %d, Lun = %d \n"
-                               , acb->host->host_no
-                               , cmd->cmnd[0]
-                               , target, lun);
-@@ -1257,7 +1228,7 @@
-                       if ((ccb->startdone == ARCMSR_CCB_ABORTED) ||
-                               (ccb == poll_ccb)) {
-                               printk(KERN_NOTICE
--                                      "arcmsr%d: scsi id=%d lun=%d ccb='0x%p'"
-+                                      "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'"
-                                       " poll command abort successfully \n"
-                                       , acb->host->host_no
-                                       , ccb->pcmd->device->id
-@@ -1270,8 +1241,8 @@
-                       }
-                       printk(KERN_NOTICE
-                               "arcmsr%d: polling get an illegal ccb"
--                              " command done ccb='0x%p'"
--                              "ccboutstandingcount=%d \n"
-+                              " command done ccb ='0x%p'"
-+                              "ccboutstandingcount = %d \n"
-                               , acb->host->host_no
-                               , ccb
-                               , atomic_read(&acb->ccboutstandingcount));
-@@ -1288,7 +1259,7 @@
-                       switch(ccb->arcmsr_cdb.DeviceStatus) {
-                       case ARCMSR_DEV_SELECT_TIMEOUT: {
-                                       acb->devstate[id][lun] = ARECA_RAID_GONE;
--                                      ccb->pcmd->result = DID_TIME_OUT << 16;
-+                                      ccb->pcmd->result = DID_NO_CONNECT << 16;
-                                       arcmsr_ccb_complete(ccb, 1);
-                               }
-                               break;
-@@ -1307,7 +1278,7 @@
-                               break;
-                       default:
-                               printk(KERN_NOTICE
--                                      "arcmsr%d: scsi id=%d lun=%d"
-+                                      "arcmsr%d: scsi id = %d lun = %d"
-                                       " polling and getting command error done"
-                                       "but got unknown DeviceStatus = 0x%x \n"
-                                       , acb->host->host_no
-@@ -1322,6 +1293,94 @@
-               }
-       }
- }
-+static void arcmsr_done4_abort_postqueue(struct AdapterControlBlock *acb)
++/****************************************************************************
++ *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
++ *
++ *  Module name: remcom.c $
++ *  Revision: 1.34 $
++ *  Date: 91/03/09 12:29:49 $
++ *  Contributor:     Lake Stevens Instrument Division$
++ *
++ *  Description:     low level support for gdb debugger. $
++ *
++ *  Considerations:  only works on target hardware $
++ *
++ *  Written by:      Glenn Engel $
++ *  ModuleState:     Experimental $
++ *
++ *  NOTES:           See Below $
++ *
++ *  Modified for SPARC by Stu Grossman, Cygnus Support.
++ *
++ *  This code has been extensively tested on the Fujitsu SPARClite demo board.
++ *
++ *  To enable debugger support, two things need to happen.  One, a
++ *  call to set_debug_traps() is necessary in order to allow any breakpoints
++ *  or error conditions to be properly intercepted and reported to gdb.
++ *  Two, a breakpoint needs to be generated to begin communication.  This
++ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
++ *  simulates a breakpoint by executing a trap #1.
++ *
++ *************
++ *
++ *    The following gdb commands are supported:
++ *
++ * command          function                    Return value
++ *
++ *    g             return the value of the CPU registers  hex data or ENN
++ *    G             set the value of the CPU registers     OK or ENN
++ *    qOffsets      Get section offsets.  Reply is Text=xxx;Data=yyy;Bss=zzz
++ *
++ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
++ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
++ *
++ *    c             Resume at current address              SNN   ( signal NN)
++ *    cAA..AA       Continue at address AA..AA             SNN
++ *
++ *    s             Step one instruction                   SNN
++ *    sAA..AA       Step one instruction from AA..AA       SNN
++ *
++ *    k             kill
++ *
++ *    ?             What was the last sigval ?             SNN   (signal NN)
++ *
++ *    bBB..BB     Set baud rate to BB..BB                OK or BNN, then sets
++ *                                                       baud rate
++ *
++ * All commands and responses are sent with a packet which includes a
++ * checksum.  A packet consists of
++ *
++ * $<packet info>#<checksum>.
++ *
++ * where
++ * <packet info> :: <characters representing the command or response>
++ * <checksum>    :: <two hex digits computed as modulo 256 sum of <packetinfo>>
++ *
++ * When a packet is received, it is first acknowledged with either '+' or '-'.
++ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
++ *
++ * Example:
++ *
++ * Host:                  Reply:
++ * $m0,10#2a               +$00010203040506070809101112131415#42
++ *
++ ****************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/init.h>
++#include <linux/sysrq.h>
++
++#include <asm/cacheflush.h>
++#include <asm/system.h>
++#include <asm/signal.h>
++#include <asm/kgdb.h>
++#include <asm/pgtable.h>
++#include <asm/ptrace.h>
++
++void breakinst(void);
++
++/*
++ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
++ * at least NUMREGBYTES*2 are needed for register packets
++ */
++#define BUFMAX 2048
++static char remcomInBuffer[BUFMAX];
++static char remcomOutBuffer[BUFMAX];
++
++static int initialized;
++static int kgdb_active;
++static int kgdb_started;
++static u_int fault_jmp_buf[100];
++static int kdebug;
++
++
++static const char hexchars[]="0123456789abcdef";
++
++/* Place where we save old trap entries for restoration - sparc*/
++/* struct tt_entry kgdb_savettable[256]; */
++/* typedef void (*trapfunc_t)(void); */
++
++static void kgdb_fault_handler(struct pt_regs *regs);
++static int handle_exception (struct pt_regs *regs);
++
++#if 0
++/* Install an exception handler for kgdb */
++static void exceptionHandler(int tnum, unsigned int *tfunc)
 +{
-+      int i = 0, found = 0;
-+      int id, lun;
-+      uint32_t flag_ccb, outbound_intstatus;
-+      struct MessageUnit __iomem *reg = acb->pmu;
-+      struct CommandControlBlock *ccb;
-+      /*clear and abort all outbound posted Q*/
-+
-+      while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) &&
-+(i++ < 256)){
-+              ccb = (struct CommandControlBlock *)(acb->vir2phy_offset +
-+(flag_ccb << 5));
-+      if (ccb){
-+              if ((ccb->acb != acb)||(ccb->startdone != \
-+ARCMSR_CCB_START)){
-+                              printk(KERN_NOTICE "arcmsr%d: polling get \
-+an illegal ccb" "command done ccb = '0x%p'""ccboutstandingcount = %d \n",
-+                                      acb->host->host_no, ccb,
-+                                      atomic_read(&acb->ccboutstandingcount));
-+                              continue;
++      /* We are dorking with a live trap table, all irqs off */
++}
++#endif
++
++int
++kgdb_setjmp(long *buf)
++{
++      asm ("mflr 0; stw 0,0(%0);"
++           "stw 1,4(%0); stw 2,8(%0);"
++           "mfcr 0; stw 0,12(%0);"
++           "stmw 13,16(%0)"
++           : : "r" (buf));
++      /* XXX should save fp regs as well */
++      return 0;
++}
++void
++kgdb_longjmp(long *buf, int val)
++{
++      if (val == 0)
++              val = 1;
++      asm ("lmw 13,16(%0);"
++           "lwz 0,12(%0); mtcrf 0x38,0;"
++           "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
++           "mtlr 0; mr 3,%1"
++           : : "r" (buf), "r" (val));
++}
++/* Convert ch from a hex digit to an int */
++static int
++hex(unsigned char ch)
++{
++      if (ch >= 'a' && ch <= 'f')
++              return ch-'a'+10;
++      if (ch >= '0' && ch <= '9')
++              return ch-'0';
++      if (ch >= 'A' && ch <= 'F')
++              return ch-'A'+10;
++      return -1;
++}
++
++/* Convert the memory pointed to by mem into hex, placing result in buf.
++ * Return a pointer to the last char put in buf (null), in case of mem fault,
++ * return 0.
++ */
++static unsigned char *
++mem2hex(const char *mem, char *buf, int count)
++{
++      unsigned char ch;
++      unsigned short tmp_s;
++      unsigned long tmp_l;
++
++      if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
++              debugger_fault_handler = kgdb_fault_handler;
++
++              /* Accessing 16 bit and 32 bit objects in a single
++              ** load instruction is required to avoid bad side
++              ** effects for some IO registers.
++              */
++
++              if ((count == 2) && (((long)mem & 1) == 0)) {
++                      tmp_s = *(unsigned short *)mem;
++                      mem += 2;
++                      *buf++ = hexchars[(tmp_s >> 12) & 0xf];
++                      *buf++ = hexchars[(tmp_s >> 8) & 0xf];
++                      *buf++ = hexchars[(tmp_s >> 4) & 0xf];
++                      *buf++ = hexchars[tmp_s & 0xf];
++
++              } else if ((count == 4) && (((long)mem & 3) == 0)) {
++                      tmp_l = *(unsigned int *)mem;
++                      mem += 4;
++                      *buf++ = hexchars[(tmp_l >> 28) & 0xf];
++                      *buf++ = hexchars[(tmp_l >> 24) & 0xf];
++                      *buf++ = hexchars[(tmp_l >> 20) & 0xf];
++                      *buf++ = hexchars[(tmp_l >> 16) & 0xf];
++                      *buf++ = hexchars[(tmp_l >> 12) & 0xf];
++                      *buf++ = hexchars[(tmp_l >> 8) & 0xf];
++                      *buf++ = hexchars[(tmp_l >> 4) & 0xf];
++                      *buf++ = hexchars[tmp_l & 0xf];
++
++              } else {
++                      while (count-- > 0) {
++                              ch = *mem++;
++                              *buf++ = hexchars[ch >> 4];
++                              *buf++ = hexchars[ch & 0xf];
 +                      }
++              }
 +
-+                      id = ccb->pcmd->device->id;
-+                      lun = ccb->pcmd->device->lun;
-+                      if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)){
-+                              if (acb->devstate[id][lun] == ARECA_RAID_GONE)
-+                                      acb->devstate[id][lun] = ARECA_RAID_GOOD;
-+                              ccb->pcmd->result = DID_OK << 16;
-+                              arcmsr_ccb_complete(ccb, 1);
++      } else {
++              /* error condition */
++      }
++      debugger_fault_handler = NULL;
++      *buf = 0;
++      return buf;
++}
++
++/* convert the hex array pointed to by buf into binary to be placed in mem
++ * return a pointer to the character AFTER the last byte written.
++*/
++static char *
++hex2mem(char *buf, char *mem, int count)
++{
++      unsigned char ch;
++      int i;
++      char *orig_mem;
++      unsigned short tmp_s;
++      unsigned long tmp_l;
++
++      orig_mem = mem;
++
++      if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
++              debugger_fault_handler = kgdb_fault_handler;
++
++              /* Accessing 16 bit and 32 bit objects in a single
++              ** store instruction is required to avoid bad side
++              ** effects for some IO registers.
++              */
++
++              if ((count == 2) && (((long)mem & 1) == 0)) {
++                      tmp_s = hex(*buf++) << 12;
++                      tmp_s |= hex(*buf++) << 8;
++                      tmp_s |= hex(*buf++) << 4;
++                      tmp_s |= hex(*buf++);
++
++                      *(unsigned short *)mem = tmp_s;
++                      mem += 2;
++
++              } else if ((count == 4) && (((long)mem & 3) == 0)) {
++                      tmp_l = hex(*buf++) << 28;
++                      tmp_l |= hex(*buf++) << 24;
++                      tmp_l |= hex(*buf++) << 20;
++                      tmp_l |= hex(*buf++) << 16;
++                      tmp_l |= hex(*buf++) << 12;
++                      tmp_l |= hex(*buf++) << 8;
++                      tmp_l |= hex(*buf++) << 4;
++                      tmp_l |= hex(*buf++);
++
++                      *(unsigned long *)mem = tmp_l;
++                      mem += 4;
++
++              } else {
++                      for (i=0; i<count; i++) {
++                              ch = hex(*buf++) << 4;
++                              ch |= hex(*buf++);
++                              *mem++ = ch;
 +                      }
-+                      else {
-+                              switch(ccb->arcmsr_cdb.DeviceStatus) {
-+                              case ARCMSR_DEV_SELECT_TIMEOUT: {
-+                                              acb->devstate[id][lun] = ARECA_RAID_GONE;
-+                                              ccb->pcmd->result = DID_NO_CONNECT << 16;
-+                                              arcmsr_ccb_complete(ccb, 1);
-+                              }
-+                              break;
++              }
++
++
++              /*
++              ** Flush the data cache, invalidate the instruction cache.
++              */
++              flush_icache_range((int)orig_mem, (int)orig_mem + count - 1);
++
++      } else {
++              /* error condition */
++      }
++      debugger_fault_handler = NULL;
++      return mem;
++}
 +
-+                              case ARCMSR_DEV_ABORTED:
++/*
++ * While we find nice hex chars, build an int.
++ * Return number of chars processed.
++ */
++static int
++hexToInt(char **ptr, int *intValue)
++{
++      int numChars = 0;
++      int hexValue;
 +
-+                              case ARCMSR_DEV_INIT_FAIL: {
-+                                              acb->devstate[id][lun] =
-+                                                      ARECA_RAID_GONE;
-+                                              ccb->pcmd->result =
-+                                                      DID_BAD_TARGET << 16;
-+                              arcmsr_ccb_complete(ccb, 1);
-+                              }
-+                              break;
++      *intValue = 0;
 +
-+                              case ARCMSR_DEV_CHECK_CONDITION: {
-+                                              acb->devstate[id][lun] =
-+                                                      ARECA_RAID_GOOD;
-+                                              arcmsr_report_sense_info(ccb);
-+                                              arcmsr_ccb_complete(ccb, 1);
-+                              }
++      if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
++              debugger_fault_handler = kgdb_fault_handler;
++              while (**ptr) {
++                      hexValue = hex(**ptr);
++                      if (hexValue < 0)
 +                              break;
 +
-+                              default:
-+                                              printk(KERN_NOTICE
-+                                                    "arcmsr%d: scsi id = %d \
-+                                                      lun = %d""polling and \
-+                                                      getting command error \
-+                                                      done""but got unknown \
-+                                                      DeviceStatus = 0x%x \n",
-+                                                      acb->host->host_no, id,
-+                                         lun, ccb->arcmsr_cdb.DeviceStatus);
-+                                              acb->devstate[id][lun] =
-+                                                              ARECA_RAID_GONE;
-+                                              ccb->pcmd->result =
-+                                                      DID_BAD_TARGET << 16;
-+                                              arcmsr_ccb_complete(ccb, 1);
-+                              break;
-+                             }
-+      }
-+                     found = 1;
-+             }
-+      }
-+      if (found){
-+              outbound_intstatus = readl(&reg->outbound_intstatus) & \
-+                      acb->outbound_int_enable;
-+              writel(outbound_intstatus, &reg->outbound_intstatus);
-+              /*clear interrupt*/
++                      *intValue = (*intValue << 4) | hexValue;
++                      numChars ++;
++
++                      (*ptr)++;
++              }
++      } else {
++              /* error condition */
 +      }
-+      return;
-+}
++      debugger_fault_handler = NULL;
 +
- static void arcmsr_iop_init(struct AdapterControlBlock *acb)
- {
-@@ -1355,7 +1414,6 @@
- static void arcmsr_iop_reset(struct AdapterControlBlock *acb)
- {
--      struct MessageUnit __iomem *reg = acb->pmu;
-       struct CommandControlBlock *ccb;
-       uint32_t intmask_org;
-       int i = 0;
-@@ -1368,21 +1426,17 @@
-               /* disable all outbound interrupt */
-               intmask_org = arcmsr_disable_outbound_ints(acb);
-               /* clear all outbound posted Q */
--              for (i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++)
--                      readl(&reg->outbound_queueport);
-+              arcmsr_done4_abort_postqueue(acb);
-               for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
-                       ccb = acb->pccb_pool[i];
--                      if ((ccb->startdone == ARCMSR_CCB_START) ||
--                              (ccb->startdone == ARCMSR_CCB_ABORTED)) {
-+                      if (ccb->startdone == ARCMSR_CCB_START) {
-                               ccb->startdone = ARCMSR_CCB_ABORTED;
--                              ccb->pcmd->result = DID_ABORT << 16;
--                              arcmsr_ccb_complete(ccb, 1);
-                       }
-               }
-               /* enable all outbound interrupt */
-               arcmsr_enable_outbound_ints(acb, intmask_org);
-       }
--      atomic_set(&acb->ccboutstandingcount, 0);
++      return (numChars);
++}
 +
- }
- static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
-@@ -1428,10 +1482,9 @@
-       int i = 0;
-       printk(KERN_NOTICE
--              "arcmsr%d: abort device command of scsi id=%d lun=%d \n",
-+              "arcmsr%d: abort device command of scsi id = %d lun = %d \n",
-               acb->host->host_no, cmd->device->id, cmd->device->lun);
-       acb->num_aborts++;
--
-       /*
-       ************************************************
-       ** the all interrupt service routine is locked
-@@ -1492,4 +1545,300 @@
-       return buf;
- }
-+static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev)
++/* scan for the sequence $<data>#<checksum> */
++static void
++getpacket(char *buffer)
 +{
-+      struct Scsi_Host *host;
-+      struct AdapterControlBlock *acb;
-+      uint8_t bus, dev_fun;
-+      int error;
++      unsigned char checksum;
++      unsigned char xmitcsum;
++      int i;
++      int count;
++      unsigned char ch;
 +
-+      error = pci_enable_device(pdev);
-+      if (error)
-+              return PCI_ERS_RESULT_DISCONNECT;
-+      pci_set_master(pdev);
++      do {
++              /* wait around for the start character, ignore all other
++               * characters */
++              while ((ch = (getDebugChar() & 0x7f)) != '$') ;
 +
-+      host = scsi_host_alloc(&arcmsr_scsi_host_template, sizeof \
-+(struct AdapterControlBlock));
-+      if (!host)
-+              return PCI_ERS_RESULT_DISCONNECT;
-+      acb = (struct AdapterControlBlock *)host->hostdata;
-+      memset(acb, 0, sizeof (struct AdapterControlBlock));
++              checksum = 0;
++              xmitcsum = -1;
 +
-+      error = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
-+      if (error) {
-+              error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-+              if (error) {
-+                      printk(KERN_WARNING
-+                             "scsi%d: No suitable DMA mask available\n",
-+                             host->host_no);
-+                      return PCI_ERS_RESULT_DISCONNECT;
++              count = 0;
++
++              /* now, read until a # or end of buffer is found */
++              while (count < BUFMAX) {
++                      ch = getDebugChar() & 0x7f;
++                      if (ch == '#')
++                              break;
++                      checksum = checksum + ch;
++                      buffer[count] = ch;
++                      count = count + 1;
 +              }
-+      }
-+      bus = pdev->bus->number;
-+      dev_fun = pdev->devfn;
-+      acb = (struct AdapterControlBlock *) host->hostdata;
-+      memset(acb, 0, sizeof(struct AdapterControlBlock));
-+      acb->pdev = pdev;
-+      acb->host = host;
-+      host->max_sectors = ARCMSR_MAX_XFER_SECTORS;
-+      host->max_lun = ARCMSR_MAX_TARGETLUN;
-+      host->max_id = ARCMSR_MAX_TARGETID;/*16:8*/
-+      host->max_cmd_len = 16;    /*this is issue of 64bit LBA, over 2T byte*/
-+      host->sg_tablesize = ARCMSR_MAX_SG_ENTRIES;
-+      host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */
-+      host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN;
-+      host->this_id = ARCMSR_SCSI_INITIATOR_ID;
-+      host->unique_id = (bus << 8) | dev_fun;
-+      host->irq = pdev->irq;
-+      error = pci_request_regions(pdev, "arcmsr");
-+      if (error)
-+              return PCI_ERS_RESULT_DISCONNECT;
-+      acb->pmu = ioremap(pci_resource_start(pdev, 0),
-+                         pci_resource_len(pdev, 0));
-+      if (!acb->pmu) {
-+              printk(KERN_NOTICE "arcmsr%d: memory"
-+                      " mapping region fail \n", acb->host->host_no);
-+              return PCI_ERS_RESULT_DISCONNECT;
-+      }
-+      acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
-+                         ACB_F_MESSAGE_RQBUFFER_CLEARED |
-+                         ACB_F_MESSAGE_WQBUFFER_READED);
-+      acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
-+      INIT_LIST_HEAD(&acb->ccb_free_list);
-+
-+      error = arcmsr_alloc_ccb_pool(acb);
-+      if (error)
-+              return PCI_ERS_RESULT_DISCONNECT;
 +
-+      error = request_irq(pdev->irq, arcmsr_do_interrupt,
-+                      IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb);
-+      if (error)
-+              return PCI_ERS_RESULT_DISCONNECT;
++              if (count >= BUFMAX)
++                      continue;
 +
-+      arcmsr_iop_init(acb);
-+      if (strncmp(acb->firm_version, "V1.42", 5) >= 0)
-+            host->max_sectors = ARCMSR_MAX_XFER_SECTORS_B;
++              buffer[count] = 0;
 +
-+      pci_set_drvdata(pdev, host);
++              if (ch == '#') {
++                      xmitcsum = hex(getDebugChar() & 0x7f) << 4;
++                      xmitcsum |= hex(getDebugChar() & 0x7f);
++                      if (checksum != xmitcsum)
++                              putDebugChar('-');      /* failed checksum */
++                      else {
++                              putDebugChar('+'); /* successful transfer */
++                              /* if a sequence char is present, reply the ID */
++                              if (buffer[2] == ':') {
++                                      putDebugChar(buffer[0]);
++                                      putDebugChar(buffer[1]);
++                                      /* remove sequence chars from buffer */
++                                      count = strlen(buffer);
++                                      for (i=3; i <= count; i++)
++                                              buffer[i-3] = buffer[i];
++                              }
++                      }
++              }
++      } while (checksum != xmitcsum);
++}
 +
-+      error = scsi_add_host(host, &pdev->dev);
-+      if (error)
-+              return PCI_ERS_RESULT_DISCONNECT;
++/* send the packet in buffer. */
++static void putpacket(unsigned char *buffer)
++{
++      unsigned char checksum;
++      int count;
++      unsigned char ch, recv;
 +
-+      error = arcmsr_alloc_sysfs_attr(acb);
-+      if (error)
-+              return PCI_ERS_RESULT_DISCONNECT;
++      /* $<packet info>#<checksum>. */
++      do {
++              putDebugChar('$');
++              checksum = 0;
++              count = 0;
 +
-+      scsi_scan_host(host);
-+      return PCI_ERS_RESULT_RECOVERED;
++              while ((ch = buffer[count])) {
++                      putDebugChar(ch);
++                      checksum += ch;
++                      count += 1;
++              }
++
++              putDebugChar('#');
++              putDebugChar(hexchars[checksum >> 4]);
++              putDebugChar(hexchars[checksum & 0xf]);
++              recv = getDebugChar();
++      } while ((recv & 0x7f) != '+');
 +}
 +
-+static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev)
++static void kgdb_flush_cache_all(void)
 +{
-+      struct Scsi_Host *host = pci_get_drvdata(pdev);
-+      struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
-+      struct MessageUnit __iomem *reg = acb->pmu;
-+      struct CommandControlBlock *ccb;
-+      /*clear and abort all outbound posted Q*/
-+      int i = 0, found = 0;
-+      int id, lun;
-+      uint32_t flag_ccb, outbound_intstatus;
-+
-+      while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) &&
-+                                                              (i++ < 256)){
-+                      ccb = (struct CommandControlBlock *)(acb->vir2phy_offset
-+                                                       + (flag_ccb << 5));
-+                      if (ccb){
-+                              if ((ccb->acb != acb)||(ccb->startdone !=
-+                                                      ARCMSR_CCB_START)){
-+                                      printk(KERN_NOTICE "arcmsr%d: polling \
-+                                      get an illegal ccb"" command done ccb = '0x%p'"
-+                                      "ccboutstandingcount = %d \n",
-+                                      acb->host->host_no, ccb,
-+                                      atomic_read(&acb->ccboutstandingcount));
-+                                      continue;
-+                              }
++      flush_instruction_cache();
++}
 +
-+                              id = ccb->pcmd->device->id;
-+                              lun = ccb->pcmd->device->lun;
-+                              if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) {
-+                                      if (acb->devstate[id][lun] ==
-+                                                              ARECA_RAID_GONE)
-+                                              acb->devstate[id][lun] =
-+                                                              ARECA_RAID_GOOD;
-+                                      ccb->pcmd->result = DID_OK << 16;
-+                                      arcmsr_ccb_complete(ccb, 1);
-+                              }
-+                              else {
-+                                      switch(ccb->arcmsr_cdb.DeviceStatus) {
-+                                      case ARCMSR_DEV_SELECT_TIMEOUT: {
-+                                                      acb->devstate[id][lun] =
-+                                                      ARECA_RAID_GONE;
-+                                                      ccb->pcmd->result =
-+                                                      DID_NO_CONNECT << 16;
-+                                                      arcmsr_ccb_complete(ccb, 1);
-+                                      }
-+                                      break;
++/* Set up exception handlers for tracing and breakpoints
++ * [could be called kgdb_init()]
++ */
++void set_debug_traps(void)
++{
++#if 0
++      unsigned char c;
 +
-+                                      case ARCMSR_DEV_ABORTED:
++      save_and_cli(flags);
 +
-+                                      case ARCMSR_DEV_INIT_FAIL: {
-+                                                      acb->devstate[id][lun] =
-+                                                       ARECA_RAID_GONE;
-+                                                      ccb->pcmd->result =
-+                                                      DID_BAD_TARGET << 16;
-+                                                      arcmsr_ccb_complete(ccb, 1);
-+                                      }
-+                                      break;
++      /* In case GDB is started before us, ack any packets (presumably
++       * "$?#xx") sitting there.
++       *
++       * I've found this code causes more problems than it solves,
++       * so that's why it's commented out.  GDB seems to work fine
++       * now starting either before or after the kernel   -bwb
++       */
 +
-+                                      case ARCMSR_DEV_CHECK_CONDITION: {
-+                                                      acb->devstate[id][lun] =
-+                                                       ARECA_RAID_GOOD;
-+                                                      arcmsr_report_sense_info(ccb);
-+                                                      arcmsr_ccb_complete(ccb, 1);
-+                                      }
-+                                      break;
++      while((c = getDebugChar()) != '$');
++      while((c = getDebugChar()) != '#');
++      c = getDebugChar(); /* eat first csum byte */
++      c = getDebugChar(); /* eat second csum byte */
++      putDebugChar('+'); /* ack it */
++#endif
++      debugger = kgdb;
++      debugger_bpt = kgdb_bpt;
++      debugger_sstep = kgdb_sstep;
++      debugger_iabr_match = kgdb_iabr_match;
++      debugger_dabr_match = kgdb_dabr_match;
 +
-+                                      default:
-+                                                      printk(KERN_NOTICE
-+                                                              "arcmsr%d: scsi \
-+                                                              id = %d lun = %d"
-+                                                              " polling and \
-+                                                              getting command \
-+                                                              error done"
-+                                                              "but got unknown \
-+                                                      DeviceStatus = 0x%x \n"
-+                                                      , acb->host->host_no,
-+                                                              id, lun,
-+                                              ccb->arcmsr_cdb.DeviceStatus);
-+                                                      acb->devstate[id][lun] =
-+                                                              ARECA_RAID_GONE;
-+                                                      ccb->pcmd->result =
-+                                                      DID_BAD_TARGET << 16;
-+                                                      arcmsr_ccb_complete(ccb, 1);
-+                                      break;
-+                                      }
-+                              }
-+                              found = 1;
-+                      }
-+              }
-+      if (found){
-+              outbound_intstatus = readl(&reg->outbound_intstatus) &
-+                                                      acb->outbound_int_enable;
-+              writel(outbound_intstatus, &reg->outbound_intstatus);
-+              /*clear interrupt*/
-+                  }
-+      return;
++      initialized = 1;
 +}
 +
-+
-+static void arcmsr_pci_ers_disconnect_forepart(struct pci_dev *pdev)
++static void kgdb_fault_handler(struct pt_regs *regs)
 +{
-+      struct Scsi_Host *host = pci_get_drvdata(pdev);
-+      struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
-+      struct MessageUnit __iomem *reg = acb->pmu;
-+      struct CommandControlBlock *ccb;
-+      /*clear and abort all outbound posted Q*/
-+      int i = 0, found = 0;
-+      int id, lun;
-+      uint32_t flag_ccb, outbound_intstatus;
-+
-+      while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) &&
-+                                                              (i++ < 256)){
-+                      ccb = (struct CommandControlBlock *)(acb->vir2phy_offset +
-+                                                      (flag_ccb << 5));
-+                      if (ccb){
-+                              if ((ccb->acb != acb)||(ccb->startdone !=
-+                                                      ARCMSR_CCB_START)){
-+                                      printk(KERN_NOTICE
-+                                              "arcmsr%d: polling get an illegal ccb"
-+                                              " command done ccb = '0x%p'"
-+                                              "ccboutstandingcount = %d \n",
-+                                              acb->host->host_no, ccb,
-+                                              atomic_read(&acb->ccboutstandingcount));
-+                                      continue;
-+                      }
-+
-+                      id = ccb->pcmd->device->id;
-+                      lun = ccb->pcmd->device->lun;
-+                      if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR))   {
-+                              if (acb->devstate[id][lun] == ARECA_RAID_GONE)
-+                                      acb->devstate[id][lun] = ARECA_RAID_GOOD;
-+                              ccb->pcmd->result = DID_OK << 16;
-+                              arcmsr_ccb_complete(ccb, 1);
-+                      }
-+                      else {
-+                              switch(ccb->arcmsr_cdb.DeviceStatus) {
-+                              case ARCMSR_DEV_SELECT_TIMEOUT: {
-+                                              acb->devstate[id][lun] =
-+                                                              ARECA_RAID_GONE;
-+                                              ccb->pcmd->result =
-+                                                      DID_NO_CONNECT << 16;
-+                                              arcmsr_ccb_complete(ccb, 1);
-+                              }
-+                              break;
++      kgdb_longjmp((long*)fault_jmp_buf, 1);
++}
 +
-+                              case ARCMSR_DEV_ABORTED:
++int kgdb_bpt(struct pt_regs *regs)
++{
++      return handle_exception(regs);
++}
 +
-+                              case ARCMSR_DEV_INIT_FAIL: {
-+                                              acb->devstate[id][lun] =
-+                                                              ARECA_RAID_GONE;
-+                                              ccb->pcmd->result =
-+                                                      DID_BAD_TARGET << 16;
-+                                              arcmsr_ccb_complete(ccb, 1);
-+                              }
-+                              break;
++int kgdb_sstep(struct pt_regs *regs)
++{
++      return handle_exception(regs);
++}
 +
-+                              case ARCMSR_DEV_CHECK_CONDITION: {
-+                                              acb->devstate[id][lun] =
-+                                                              ARECA_RAID_GOOD;
-+                                              arcmsr_report_sense_info(ccb);
-+                                              arcmsr_ccb_complete(ccb, 1);
-+                              }
-+                              break;
++void kgdb(struct pt_regs *regs)
++{
++      handle_exception(regs);
++}
 +
-+                              default:
-+                                              printk(KERN_NOTICE "arcmsr%d: \
-+                                                      scsi id = %d lun = %d"
-+                                                              " polling and \
-+                                              getting command error done"
-+                                                              "but got unknown \
-+                                               DeviceStatus = 0x%x \n"
-+                                                              , acb->host->host_no,
-+                                      id, lun, ccb->arcmsr_cdb.DeviceStatus);
-+                                                      acb->devstate[id][lun] =
-+                                                              ARECA_RAID_GONE;
-+                                                      ccb->pcmd->result =
-+                                                      DID_BAD_TARGET << 16;
-+                                                      arcmsr_ccb_complete(ccb, 1);
-+                              break;
-+                              }
-+                      }
-+                      found = 1;
-+              }
-+      }
-+      if (found){
-+              outbound_intstatus = readl(&reg->outbound_intstatus) &
-+                                              acb->outbound_int_enable;
-+              writel(outbound_intstatus, &reg->outbound_intstatus);
-+              /*clear interrupt*/
-+      }
-+      return;
++int kgdb_iabr_match(struct pt_regs *regs)
++{
++      printk(KERN_ERR "kgdb doesn't support iabr, what?!?\n");
++      return handle_exception(regs);
 +}
 +
-+static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev,
-+                                              pci_channel_state_t state)
++int kgdb_dabr_match(struct pt_regs *regs)
 +{
-+      switch (state) {
-+      case pci_channel_io_frozen:
-+                      arcmsr_pci_ers_need_reset_forepart(pdev);
-+                      return PCI_ERS_RESULT_NEED_RESET;
-+      case pci_channel_io_perm_failure:
-+                      arcmsr_pci_ers_disconnect_forepart(pdev);
-+                      return PCI_ERS_RESULT_DISCONNECT;
-+                      break;
-+      default:
-+                      return PCI_ERS_RESULT_NEED_RESET;
-+      }
++      printk(KERN_ERR "kgdb doesn't support dabr, what?!?\n");
++      return handle_exception(regs);
 +}
-diff -Nurb linux-2.6.22-570/drivers/scsi/bvme6000.c linux-2.6.22-590/drivers/scsi/bvme6000.c
---- linux-2.6.22-570/drivers/scsi/bvme6000.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/bvme6000.c   1969-12-31 19:00:00.000000000 -0500
-@@ -1,76 +0,0 @@
--/*
-- * Detection routine for the NCR53c710 based BVME6000 SCSI Controllers for Linux.
-- *
-- * Based on work by Alan Hourihane
-- */
--#include <linux/types.h>
--#include <linux/mm.h>
--#include <linux/blkdev.h>
--#include <linux/zorro.h>
--
--#include <asm/setup.h>
--#include <asm/page.h>
--#include <asm/pgtable.h>
--#include <asm/bvme6000hw.h>
--#include <asm/irq.h>
--
--#include "scsi.h"
--#include <scsi/scsi_host.h>
--#include "53c7xx.h"
--#include "bvme6000.h"
--
--#include<linux/stat.h>
--
--
--int bvme6000_scsi_detect(struct scsi_host_template *tpnt)
--{
--    static unsigned char called = 0;
--    int clock;
--    long long options;
--
--    if (called)
--      return 0;
--    if (!MACH_IS_BVME6000)
--      return 0;
--
--    tpnt->proc_name = "BVME6000";
--
--    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
--
--    clock = 40000000; /* 66MHz SCSI Clock */
--
--    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)BVME_NCR53C710_BASE,
--                      0, BVME_IRQ_SCSI, DMA_NONE,
--                      options, clock);
--    called = 1;
--    return 1;
--}
--
--static int bvme6000_scsi_release(struct Scsi_Host *shost)
--{
--      if (shost->irq)
--              free_irq(shost->irq, NULL);
--      if (shost->dma_channel != 0xff)
--              free_dma(shost->dma_channel);
--      if (shost->io_port && shost->n_io_port)
--              release_region(shost->io_port, shost->n_io_port);
--      scsi_unregister(shost);
--      return 0;
--}
--
--static struct scsi_host_template driver_template = {
--      .name                   = "BVME6000 NCR53c710 SCSI",
--      .detect                 = bvme6000_scsi_detect,
--      .release                = bvme6000_scsi_release,
--      .queuecommand           = NCR53c7xx_queue_command,
--      .abort                  = NCR53c7xx_abort,
--      .reset                  = NCR53c7xx_reset,
--      .can_queue              = 24,
--      .this_id                = 7,
--      .sg_tablesize           = 63,
--      .cmd_per_lun            = 3,
--      .use_clustering         = DISABLE_CLUSTERING
--};
--
--
--#include "scsi_module.c"
-diff -Nurb linux-2.6.22-570/drivers/scsi/bvme6000.h linux-2.6.22-590/drivers/scsi/bvme6000.h
---- linux-2.6.22-570/drivers/scsi/bvme6000.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/bvme6000.h   1969-12-31 19:00:00.000000000 -0500
-@@ -1,24 +0,0 @@
--#ifndef BVME6000_SCSI_H
--#define BVME6000_SCSI_H
--
--#include <linux/types.h>
--
--int bvme6000_scsi_detect(struct scsi_host_template *);
--const char *NCR53c7x0_info(void);
--int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
--int NCR53c7xx_abort(Scsi_Cmnd *);
--int NCR53c7x0_release (struct Scsi_Host *);
--int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
--void NCR53c7x0_intr(int irq, void *dev_id);
--
--#ifndef CMD_PER_LUN
--#define CMD_PER_LUN 3
--#endif
--
--#ifndef CAN_QUEUE
--#define CAN_QUEUE 24
--#endif
--
--#include <scsi/scsicam.h>
--
--#endif /* BVME6000_SCSI_H */
-diff -Nurb linux-2.6.22-570/drivers/scsi/bvme6000_scsi.c linux-2.6.22-590/drivers/scsi/bvme6000_scsi.c
---- linux-2.6.22-570/drivers/scsi/bvme6000_scsi.c      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/scsi/bvme6000_scsi.c      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,135 @@
++
++/* Convert the hardware trap type code to a unix signal number. */
 +/*
-+ * Detection routine for the NCR53c710 based BVME6000 SCSI Controllers for Linux.
-+ *
-+ * Based on work by Alan Hourihane and Kars de Jong
-+ *
-+ * Rewritten to use 53c700.c by Richard Hirst <richard@sleepie.demon.co.uk>
++ * This table contains the mapping between PowerPC hardware trap types, and
++ * signals, which are primarily what GDB understands.
 + */
++static struct hard_trap_info
++{
++      unsigned int tt;                /* Trap type code for powerpc */
++      unsigned char signo;            /* Signal that we map this trap into */
++} hard_trap_info[] = {
++#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
++      { 0x100, SIGINT  },             /* critical input interrupt */
++      { 0x200, SIGSEGV },             /* machine check */
++      { 0x300, SIGSEGV },             /* data storage */
++      { 0x400, SIGBUS  },             /* instruction storage */
++      { 0x500, SIGINT  },             /* interrupt */
++      { 0x600, SIGBUS  },             /* alignment */
++      { 0x700, SIGILL  },             /* program */
++      { 0x800, SIGILL  },             /* reserved */
++      { 0x900, SIGILL  },             /* reserved */
++      { 0xa00, SIGILL  },             /* reserved */
++      { 0xb00, SIGILL  },             /* reserved */
++      { 0xc00, SIGCHLD },             /* syscall */
++      { 0xd00, SIGILL  },             /* reserved */
++      { 0xe00, SIGILL  },             /* reserved */
++      { 0xf00, SIGILL  },             /* reserved */
++      /*
++      ** 0x1000  PIT
++      ** 0x1010  FIT
++      ** 0x1020  watchdog
++      ** 0x1100  data TLB miss
++      ** 0x1200  instruction TLB miss
++      */
++      { 0x2002, SIGTRAP},             /* debug */
++#else
++      { 0x200, SIGSEGV },             /* machine check */
++      { 0x300, SIGSEGV },             /* address error (store) */
++      { 0x400, SIGBUS },              /* instruction bus error */
++      { 0x500, SIGINT },              /* interrupt */
++      { 0x600, SIGBUS },              /* alingment */
++      { 0x700, SIGTRAP },             /* breakpoint trap */
++      { 0x800, SIGFPE },              /* fpu unavail */
++      { 0x900, SIGALRM },             /* decrementer */
++      { 0xa00, SIGILL },              /* reserved */
++      { 0xb00, SIGILL },              /* reserved */
++      { 0xc00, SIGCHLD },             /* syscall */
++      { 0xd00, SIGTRAP },             /* single-step/watch */
++      { 0xe00, SIGFPE },              /* fp assist */
++#endif
++      { 0, 0}                         /* Must be last */
 +
-+#include <linux/module.h>
-+#include <linux/blkdev.h>
-+#include <linux/device.h>
-+#include <linux/platform_device.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <asm/bvme6000hw.h>
-+#include <scsi/scsi_host.h>
-+#include <scsi/scsi_device.h>
-+#include <scsi/scsi_transport.h>
-+#include <scsi/scsi_transport_spi.h>
++};
 +
-+#include "53c700.h"
++static int computeSignal(unsigned int tt)
++{
++      struct hard_trap_info *ht;
 +
-+MODULE_AUTHOR("Richard Hirst <richard@sleepie.demon.co.uk>");
-+MODULE_DESCRIPTION("BVME6000 NCR53C710 driver");
-+MODULE_LICENSE("GPL");
++      for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
++              if (ht->tt == tt)
++                      return ht->signo;
 +
-+static struct scsi_host_template bvme6000_scsi_driver_template = {
-+      .name                   = "BVME6000 NCR53c710 SCSI",
-+      .proc_name              = "BVME6000",
-+      .this_id                = 7,
-+      .module                 = THIS_MODULE,
-+};
++      return SIGHUP; /* default for things we don't know about */
++}
 +
-+static struct platform_device *bvme6000_scsi_device;
++#define PC_REGNUM 64
++#define SP_REGNUM 1
 +
-+static __devinit int
-+bvme6000_probe(struct device *dev)
++/*
++ * This function does all command processing for interfacing to gdb.
++ */
++static int
++handle_exception (struct pt_regs *regs)
 +{
-+      struct Scsi_Host * host = NULL;
-+      struct NCR_700_Host_Parameters *hostdata;
++      int sigval;
++      int addr;
++      int length;
++      char *ptr;
++      unsigned int msr;
 +
-+      if (!MACH_IS_BVME6000)
-+              goto out;
++      /* We don't handle user-mode breakpoints. */
++      if (user_mode(regs))
++              return 0;
 +
-+      hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
-+      if (hostdata == NULL) {
-+              printk(KERN_ERR "bvme6000-scsi: "
-+                              "Failed to allocate host data\n");
-+              goto out;
++      if (debugger_fault_handler) {
++              debugger_fault_handler(regs);
++              panic("kgdb longjump failed!\n");
++      }
++      if (kgdb_active) {
++              printk(KERN_ERR "interrupt while in kgdb, returning\n");
++              return 0;
 +      }
-+      memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
 +
-+      /* Fill in the required pieces of hostdata */
-+      hostdata->base = (void __iomem *)BVME_NCR53C710_BASE;
-+      hostdata->clock = 40;   /* XXX - depends on the CPU clock! */
-+      hostdata->chip710 = 1;
-+      hostdata->dmode_extra = DMODE_FC2;
-+      hostdata->dcntl_extra = EA_710;
-+      hostdata->ctest7_extra = CTEST7_TT1;
++      kgdb_active = 1;
++      kgdb_started = 1;
 +
-+      /* and register the chip */
-+      host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata, dev);
-+      if (!host) {
-+              printk(KERN_ERR "bvme6000-scsi: No host detected; "
-+                              "board configuration problem?\n");
-+              goto out_free;
-+      }
-+      host->base = BVME_NCR53C710_BASE;
-+      host->this_id = 7;
-+      host->irq = BVME_IRQ_SCSI;
-+      if (request_irq(BVME_IRQ_SCSI, NCR_700_intr, 0, "bvme6000-scsi",
-+                      host)) {
-+              printk(KERN_ERR "bvme6000-scsi: request_irq failed\n");
-+              goto out_put_host;
++#ifdef KGDB_DEBUG
++      printk("kgdb: entering handle_exception; trap [0x%x]\n",
++                      (unsigned int)regs->trap);
++#endif
++
++      kgdb_interruptible(0);
++      lock_kernel();
++      msr = mfmsr();
++      mtmsr(msr & ~MSR_EE);   /* disable interrupts */
++
++      if (regs->nip == (unsigned long)breakinst) {
++              /* Skip over breakpoint trap insn */
++              regs->nip += 4;
 +      }
 +
-+      scsi_scan_host(host);
++      /* reply to host that an exception has occurred */
++      sigval = computeSignal(regs->trap);
++      ptr = remcomOutBuffer;
++
++      *ptr++ = 'T';
++      *ptr++ = hexchars[sigval >> 4];
++      *ptr++ = hexchars[sigval & 0xf];
++      *ptr++ = hexchars[PC_REGNUM >> 4];
++      *ptr++ = hexchars[PC_REGNUM & 0xf];
++      *ptr++ = ':';
++      ptr = mem2hex((char *)&regs->nip, ptr, 4);
++      *ptr++ = ';';
++      *ptr++ = hexchars[SP_REGNUM >> 4];
++      *ptr++ = hexchars[SP_REGNUM & 0xf];
++      *ptr++ = ':';
++      ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4);
++      *ptr++ = ';';
++      *ptr++ = 0;
++
++      putpacket(remcomOutBuffer);
++      if (kdebug)
++              printk("remcomOutBuffer: %s\n", remcomOutBuffer);
++
++      /* XXX We may want to add some features dealing with poking the
++       * XXX page tables, ... (look at sparc-stub.c for more info)
++       * XXX also required hacking to the gdb sources directly...
++       */
 +
-+      return 0;
++      while (1) {
++              remcomOutBuffer[0] = 0;
++
++              getpacket(remcomInBuffer);
++              switch (remcomInBuffer[0]) {
++              case '?': /* report most recent signal */
++                      remcomOutBuffer[0] = 'S';
++                      remcomOutBuffer[1] = hexchars[sigval >> 4];
++                      remcomOutBuffer[2] = hexchars[sigval & 0xf];
++                      remcomOutBuffer[3] = 0;
++                      break;
++#if 0
++              case 'q': /* this screws up gdb for some reason...*/
++              {
++                      extern long _start, sdata, __bss_start;
 +
-+ out_put_host:
-+      scsi_host_put(host);
-+ out_free:
-+      kfree(hostdata);
-+ out:
-+      return -ENODEV;
-+}
++                      ptr = &remcomInBuffer[1];
++                      if (strncmp(ptr, "Offsets", 7) != 0)
++                              break;
 +
-+static __devexit int
-+bvme6000_device_remove(struct device *dev)
-+{
-+      struct Scsi_Host *host = dev_to_shost(dev);
-+      struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
++                      ptr = remcomOutBuffer;
++                      sprintf(ptr, "Text=%8.8x;Data=%8.8x;Bss=%8.8x",
++                              &_start, &sdata, &__bss_start);
++                      break;
++              }
++#endif
++              case 'd':
++                      /* toggle debug flag */
++                      kdebug ^= 1;
++                      break;
 +
-+      scsi_remove_host(host);
-+      NCR_700_release(host);
-+      kfree(hostdata);
-+      free_irq(host->irq, host);
++              case 'g':       /* return the value of the CPU registers.
++                               * some of them are non-PowerPC names :(
++                               * they are stored in gdb like:
++                               * struct {
++                               *     u32 gpr[32];
++                               *     f64 fpr[32];
++                               *     u32 pc, ps, cnd, lr; (ps=msr)
++                               *     u32 cnt, xer, mq;
++                               * }
++                               */
++              {
++                      int i;
++                      ptr = remcomOutBuffer;
++                      /* General Purpose Regs */
++                      ptr = mem2hex((char *)regs, ptr, 32 * 4);
++                      /* Floating Point Regs - FIXME */
++                      /*ptr = mem2hex((char *), ptr, 32 * 8);*/
++                      for(i=0; i<(32*8*2); i++) { /* 2chars/byte */
++                              ptr[i] = '0';
++                      }
++                      ptr += 32*8*2;
++                      /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
++                      ptr = mem2hex((char *)&regs->nip, ptr, 4);
++                      ptr = mem2hex((char *)&regs->msr, ptr, 4);
++                      ptr = mem2hex((char *)&regs->ccr, ptr, 4);
++                      ptr = mem2hex((char *)&regs->link, ptr, 4);
++                      ptr = mem2hex((char *)&regs->ctr, ptr, 4);
++                      ptr = mem2hex((char *)&regs->xer, ptr, 4);
++              }
++                      break;
 +
-+      return 0;
++              case 'G': /* set the value of the CPU registers */
++              {
++                      ptr = &remcomInBuffer[1];
++
++                      /*
++                       * If the stack pointer has moved, you should pray.
++                       * (cause only god can help you).
++                       */
++
++                      /* General Purpose Regs */
++                      hex2mem(ptr, (char *)regs, 32 * 4);
++
++                      /* Floating Point Regs - FIXME?? */
++                      /*ptr = hex2mem(ptr, ??, 32 * 8);*/
++                      ptr += 32*8*2;
++
++                      /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
++                      ptr = hex2mem(ptr, (char *)&regs->nip, 4);
++                      ptr = hex2mem(ptr, (char *)&regs->msr, 4);
++                      ptr = hex2mem(ptr, (char *)&regs->ccr, 4);
++                      ptr = hex2mem(ptr, (char *)&regs->link, 4);
++                      ptr = hex2mem(ptr, (char *)&regs->ctr, 4);
++                      ptr = hex2mem(ptr, (char *)&regs->xer, 4);
++
++                      strcpy(remcomOutBuffer,"OK");
++              }
++                      break;
++              case 'H':
++                      /* don't do anything, yet, just acknowledge */
++                      hexToInt(&ptr, &addr);
++                      strcpy(remcomOutBuffer,"OK");
++                      break;
++
++              case 'm':       /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
++                              /* Try to read %x,%x.  */
++
++                      ptr = &remcomInBuffer[1];
++
++                      if (hexToInt(&ptr, &addr) && *ptr++ == ','
++                                      && hexToInt(&ptr, &length)) {
++                              if (mem2hex((char *)addr, remcomOutBuffer,
++                                                      length))
++                                      break;
++                              strcpy(remcomOutBuffer, "E03");
++                      } else
++                              strcpy(remcomOutBuffer, "E01");
++                      break;
++
++              case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
++                      /* Try to read '%x,%x:'.  */
++
++                      ptr = &remcomInBuffer[1];
++
++                      if (hexToInt(&ptr, &addr) && *ptr++ == ','
++                                      && hexToInt(&ptr, &length)
++                                      && *ptr++ == ':') {
++                              if (hex2mem(ptr, (char *)addr, length))
++                                      strcpy(remcomOutBuffer, "OK");
++                              else
++                                      strcpy(remcomOutBuffer, "E03");
++                              flush_icache_range(addr, addr+length);
++                      } else
++                              strcpy(remcomOutBuffer, "E02");
++                      break;
++
++
++              case 'k': /* kill the program, actually just continue */
++              case 'c': /* cAA..AA  Continue; address AA..AA optional */
++                      /* try to read optional parameter, pc unchanged if no parm */
++
++                      ptr = &remcomInBuffer[1];
++                      if (hexToInt(&ptr, &addr))
++                              regs->nip = addr;
++
++/* Need to flush the instruction cache here, as we may have deposited a
++ * breakpoint, and the icache probably has no way of knowing that a data ref to
++ * some location may have changed something that is in the instruction cache.
++ */
++                      kgdb_flush_cache_all();
++                      mtmsr(msr);
++
++                      kgdb_interruptible(1);
++                      unlock_kernel();
++                      kgdb_active = 0;
++                      if (kdebug) {
++                              printk("remcomInBuffer: %s\n", remcomInBuffer);
++                              printk("remcomOutBuffer: %s\n", remcomOutBuffer);
++                      }
++                      return 1;
++
++              case 's':
++                      kgdb_flush_cache_all();
++#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
++                      mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC);
++                      regs->msr |= MSR_DE;
++#else
++                      regs->msr |= MSR_SE;
++#endif
++                      unlock_kernel();
++                      kgdb_active = 0;
++                      if (kdebug) {
++                              printk("remcomInBuffer: %s\n", remcomInBuffer);
++                              printk("remcomOutBuffer: %s\n", remcomOutBuffer);
++                      }
++                      return 1;
++
++              case 'r':               /* Reset (if user process..exit ???)*/
++                      panic("kgdb reset.");
++                      break;
++              }                       /* switch */
++              if (remcomOutBuffer[0] && kdebug) {
++                      printk("remcomInBuffer: %s\n", remcomInBuffer);
++                      printk("remcomOutBuffer: %s\n", remcomOutBuffer);
++              }
++              /* reply to the request */
++              putpacket(remcomOutBuffer);
++      } /* while(1) */
 +}
 +
-+static struct device_driver bvme6000_scsi_driver = {
-+      .name   = "bvme6000-scsi",
-+      .bus    = &platform_bus_type,
-+      .probe  = bvme6000_probe,
-+      .remove = __devexit_p(bvme6000_device_remove),
-+};
++/* This function will generate a breakpoint exception.  It is used at the
++   beginning of a program to sync up with a debugger and can be used
++   otherwise as a quick means to stop program execution and "break" into
++   the debugger. */
 +
-+static int __init bvme6000_scsi_init(void)
++void
++breakpoint(void)
 +{
-+      int err;
++      if (!initialized) {
++              printk("breakpoint() called b4 kgdb init\n");
++              return;
++      }
 +
-+      err = driver_register(&bvme6000_scsi_driver);
-+      if (err)
-+              return err;
++      asm("   .globl breakinst        \n\
++           breakinst: .long 0x7d821008");
++}
 +
-+      bvme6000_scsi_device = platform_device_register_simple("bvme6000-scsi",
-+                                                             -1, NULL, 0);
-+      if (IS_ERR(bvme6000_scsi_device)) {
-+              driver_unregister(&bvme6000_scsi_driver);
-+              return PTR_ERR(bvme6000_scsi_device);
-+      }
++#ifdef CONFIG_KGDB_CONSOLE
++/* Output string in GDB O-packet format if GDB has connected. If nothing
++   output, returns 0 (caller must then handle output). */
++int
++kgdb_output_string (const char* s, unsigned int count)
++{
++      char buffer[512];
 +
-+      return 0;
++      if (!kgdb_started)
++              return 0;
++
++      count = (count <= (sizeof(buffer) / 2 - 2))
++              ? count : (sizeof(buffer) / 2 - 2);
++
++      buffer[0] = 'O';
++      mem2hex (s, &buffer[1], count);
++      putpacket(buffer);
++
++      return 1;
 +}
++#endif
 +
-+static void __exit bvme6000_scsi_exit(void)
++static void sysrq_handle_gdb(int key, struct pt_regs *pt_regs,
++                           struct tty_struct *tty)
 +{
-+      platform_device_unregister(bvme6000_scsi_device);
-+      driver_unregister(&bvme6000_scsi_driver);
++      printk("Entering GDB stub\n");
++      breakpoint();
 +}
++static struct sysrq_key_op sysrq_gdb_op = {
++        .handler        = sysrq_handle_gdb,
++        .help_msg       = "Gdb",
++        .action_msg     = "GDB",
++};
 +
-+module_init(bvme6000_scsi_init);
-+module_exit(bvme6000_scsi_exit);
-diff -Nurb linux-2.6.22-570/drivers/scsi/dpt_i2o.c linux-2.6.22-590/drivers/scsi/dpt_i2o.c
---- linux-2.6.22-570/drivers/scsi/dpt_i2o.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/dpt_i2o.c    2008-01-02 13:56:37.000000000 -0500
-@@ -2078,12 +2078,13 @@
-       u32 *lenptr;
-       int direction;
-       int scsidir;
-+      int nseg;
-       u32 len;
-       u32 reqlen;
-       s32 rcode;
++static int gdb_register_sysrq(void)
++{
++      printk("Registering GDB sysrq handler\n");
++      register_sysrq_key('g', &sysrq_gdb_op);
++      return 0;
++}
++module_init(gdb_register_sysrq);
+diff -Nurb linux-2.6.22-590/arch/ppc/kernel/setup.c linux-2.6.22-570/arch/ppc/kernel/setup.c
+--- linux-2.6.22-590/arch/ppc/kernel/setup.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/kernel/setup.c   2007-07-08 19:32:17.000000000 -0400
+@@ -48,6 +48,10 @@
+ #include <asm/ppc_sys.h>
+ #endif
  
-       memset(msg, 0 , sizeof(msg));
--      len = cmd->request_bufflen;
-+      len = scsi_bufflen(cmd);
-       direction = 0x00000000; 
-       
-       scsidir = 0x00000000;                   // DATA NO XFER
-@@ -2140,21 +2141,21 @@
-       lenptr=mptr++;          /* Remember me - fill in when we know */
-       reqlen = 14;            // SINGLE SGE
-       /* Now fill in the SGList and command */
--      if(cmd->use_sg) {
--              struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer;
--              int sg_count = pci_map_sg(pHba->pDev, sg, cmd->use_sg,
--                              cmd->sc_data_direction);
-+      nseg = scsi_dma_map(cmd);
-+      BUG_ON(nseg < 0);
-+      if (nseg) {
-+              struct scatterlist *sg;
++#if defined CONFIG_KGDB
++#include <asm/kgdb.h>
++#endif
++
+ extern void platform_init(unsigned long r3, unsigned long r4,
+               unsigned long r5, unsigned long r6, unsigned long r7);
+ extern void reloc_got2(unsigned long offset);
+@@ -505,12 +509,24 @@
+ #endif /* CONFIG_XMON */
+       if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
  
-               len = 0;
--              for(i = 0 ; i < sg_count; i++) {
-+              scsi_for_each_sg(cmd, sg, nseg, i) {
-                       *mptr++ = direction|0x10000000|sg_dma_len(sg);
-                       len+=sg_dma_len(sg);
-                       *mptr++ = sg_dma_address(sg);
--                      sg++;
--              }
-               /* Make this an end of list */
--              mptr[-2] = direction|0xD0000000|sg_dma_len(sg-1);
-+                      if (i == nseg - 1)
-+                              mptr[-2] = direction|0xD0000000|sg_dma_len(sg);
-+              }
-               reqlen = mptr - msg;
-               *lenptr = len;
-               
-@@ -2163,16 +2164,8 @@
-                               len, cmd->underflow);
-               }
-       } else {
--              *lenptr = len = cmd->request_bufflen;
--              if(len == 0) {
-+              *lenptr = len = 0;
-                       reqlen = 12;
--              } else {
--                      *mptr++ = 0xD0000000|direction|cmd->request_bufflen;
--                      *mptr++ = pci_map_single(pHba->pDev,
--                              cmd->request_buffer,
--                              cmd->request_bufflen,
--                              cmd->sc_data_direction);
--              }
++#if defined(CONFIG_KGDB)
++      if (ppc_md.kgdb_map_scc)
++              ppc_md.kgdb_map_scc();
++      set_debug_traps();
++      if (strstr(cmd_line, "gdb")) {
++              if (ppc_md.progress)
++                      ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
++              printk("kgdb breakpoint activated\n");
++              breakpoint();
++      }
++#endif
++
+       /*
+        * Set cache line size based on type of cpu as a default.
+        * Systems with OF can look in the properties on the cpu node(s)
+        * for a possibly more accurate value.
+        */
+-      if (! cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) {
++      if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
+               dcache_bsize = cur_cpu_spec->dcache_bsize;
+               icache_bsize = cur_cpu_spec->icache_bsize;
+               ucache_bsize = 0;
+diff -Nurb linux-2.6.22-590/arch/ppc/mm/fault.c linux-2.6.22-570/arch/ppc/mm/fault.c
+--- linux-2.6.22-590/arch/ppc/mm/fault.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/mm/fault.c       2008-01-23 19:16:04.000000000 -0500
+@@ -25,7 +25,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/highmem.h>
+ #include <linux/module.h>
+-#include <linux/kgdb.h>
+ #include <asm/page.h>
+ #include <asm/pgtable.h>
+@@ -331,14 +330,6 @@
+               return;
        }
-       
-       /* Stick the headers on */
-@@ -2232,7 +2225,7 @@
-       hba_status = detailed_status >> 8;
  
-       // calculate resid for sg 
--      cmd->resid = cmd->request_bufflen - readl(reply+5);
-+      scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+5));
+-#ifdef CONFIG_KGDB
+-      if (atomic_read(&debugger_active) && kgdb_may_fault) {
+-              /* Restore our previous state. */
+-              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+-              /* Not reached. */
+-      }
+-#endif
+-
+       /* kernel has accessed a bad area */
+ #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
+       if (debugger_kernel_faults)
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/4xx/bamboo.c linux-2.6.22-570/arch/ppc/platforms/4xx/bamboo.c
+--- linux-2.6.22-590/arch/ppc/platforms/4xx/bamboo.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/4xx/bamboo.c   2007-07-08 19:32:17.000000000 -0400
+@@ -30,7 +30,6 @@
+ #include <linux/serial.h>
+ #include <linux/serial_core.h>
+ #include <linux/ethtool.h>
+-#include <linux/kgdb.h>
  
-       pHba = (adpt_hba*) cmd->device->host->hostdata[0];
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+@@ -338,13 +337,10 @@
+               printk("Early serial init of port 0 failed\n");
+       }
  
-diff -Nurb linux-2.6.22-570/drivers/scsi/eata.c linux-2.6.22-590/drivers/scsi/eata.c
---- linux-2.6.22-570/drivers/scsi/eata.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/eata.c       2008-01-02 13:56:37.000000000 -0500
-@@ -1609,8 +1609,9 @@
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Configure debug serial access */
+       gen550_init(0, &port);
+ #endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(0, &port);
+-#endif
  
- static void map_dma(unsigned int i, struct hostdata *ha)
- {
--      unsigned int k, count, pci_dir;
--      struct scatterlist *sgpnt;
-+      unsigned int k, pci_dir;
-+      int count;
-+      struct scatterlist *sg;
-       struct mscp *cpp;
-       struct scsi_cmnd *SCpnt;
+       port.membase = ioremap64(PPC440EP_UART1_ADDR, 8);
+       port.irq = 1;
+@@ -355,13 +351,10 @@
+               printk("Early serial init of port 1 failed\n");
+       }
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Configure debug serial access */
+       gen550_init(1, &port);
+ #endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(1, &port);
+-#endif
+       port.membase = ioremap64(PPC440EP_UART2_ADDR, 8);
+       port.irq = 3;
+@@ -372,13 +365,10 @@
+               printk("Early serial init of port 2 failed\n");
+       }
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Configure debug serial access */
+       gen550_init(2, &port);
+ #endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(2, &port);
+-#endif
+       port.membase = ioremap64(PPC440EP_UART3_ADDR, 8);
+       port.irq = 4;
+@@ -388,10 +378,6 @@
+       if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 3 failed\n");
+       }
+-
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(3, &port);
+-#endif
+ }
+ static void __init
+@@ -449,5 +435,8 @@
+       ppc_md.nvram_read_val = todc_direct_read_val;
+       ppc_md.nvram_write_val = todc_direct_write_val;
++#ifdef CONFIG_KGDB
++      ppc_md.early_serial_map = bamboo_early_serial_map;
++#endif
+ }
  
-@@ -1625,38 +1626,19 @@
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/4xx/bubinga.c linux-2.6.22-570/arch/ppc/platforms/4xx/bubinga.c
+--- linux-2.6.22-590/arch/ppc/platforms/4xx/bubinga.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/4xx/bubinga.c  2007-07-08 19:32:17.000000000 -0400
+@@ -4,7 +4,7 @@
+  * Author: SAW (IBM), derived from walnut.c.
+  *         Maintained by MontaVista Software <source@mvista.com>
+  *
+- * 2003-2004 (c) MontaVista Softare Inc.  This file is licensed under the
++ * 2003 (c) MontaVista Softare Inc.  This file is licensed under the
+  * terms of the GNU General Public License version 2. This program is
+  * licensed "as is" without any warranty of any kind, whether express
+  * or implied.
+@@ -21,7 +21,6 @@
+ #include <linux/tty.h>
+ #include <linux/serial.h>
+ #include <linux/serial_core.h>
+-#include <linux/kgdb.h>
+ #include <asm/system.h>
+ #include <asm/pci-bridge.h>
+@@ -31,6 +30,7 @@
+ #include <asm/time.h>
+ #include <asm/io.h>
+ #include <asm/todc.h>
++#include <asm/kgdb.h>
+ #include <asm/ocp.h>
+ #include <asm/ibm_ocp_pci.h>
  
-       cpp->sense_len = sizeof SCpnt->sense_buffer;
+@@ -100,26 +100,17 @@
+       port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+       port.line = 0;
  
--      if (!SCpnt->use_sg) {
--
--              /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */
--              if (!SCpnt->request_bufflen)
--                      pci_dir = PCI_DMA_BIDIRECTIONAL;
--
--              if (SCpnt->request_buffer)
--                      cpp->data_address = H2DEV(pci_map_single(ha->pdev,
--                                                               SCpnt->
--                                                               request_buffer,
--                                                               SCpnt->
--                                                               request_bufflen,
--                                                               pci_dir));
--
--              cpp->data_len = H2DEV(SCpnt->request_bufflen);
--              return;
--      }
--
--      sgpnt = (struct scatterlist *)SCpnt->request_buffer;
--      count = pci_map_sg(ha->pdev, sgpnt, SCpnt->use_sg, pci_dir);
+-#ifdef CONFIG_SERIAL_8250
+-      if (early_serial_setup(&port) != 0)
++      if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 0 failed\n");
+-#endif
 -
--      for (k = 0; k < count; k++) {
--              cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
--              cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
-+      count = scsi_dma_map(SCpnt);
-+      BUG_ON(count < 0);
-+      scsi_for_each_sg(SCpnt, sg, count, k) {
-+              cpp->sglist[k].address = H2DEV(sg_dma_address(sg));
-+              cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(sg));
-       }
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(0, &port);
+-#endif
++      }
  
-       cpp->sg = 1;
-       cpp->data_address = H2DEV(pci_map_single(ha->pdev, cpp->sglist,
--                                               SCpnt->use_sg *
-+                                               scsi_sg_count(SCpnt) *
-                                                sizeof(struct sg_list),
-                                                pci_dir));
--      cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list)));
-+      cpp->data_len = H2DEV((scsi_sg_count(SCpnt) * sizeof(struct sg_list)));
+       port.membase = (void*)ACTING_UART1_IO_BASE;
+       port.irq = ACTING_UART1_INT;
+       port.line = 1;
+-#ifdef CONFIG_SERIAL_8250
+-      if (early_serial_setup(&port) != 0)
++      if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 1 failed\n");
+-#endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(1, &port);
+-#endif
++      }
  }
  
- static void unmap_dma(unsigned int i, struct hostdata *ha)
-@@ -1673,9 +1655,7 @@
-               pci_unmap_single(ha->pdev, DEV2H(cpp->sense_addr),
-                                DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+ void __init
+@@ -266,4 +257,8 @@
+       ppc_md.nvram_read_val = todc_direct_read_val;
+       ppc_md.nvram_write_val = todc_direct_write_val;
+ #endif
++#ifdef CONFIG_KGDB
++      ppc_md.early_serial_map = bubinga_early_serial_map;
++#endif
+ }
++
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/4xx/ebony.c linux-2.6.22-570/arch/ppc/platforms/4xx/ebony.c
+--- linux-2.6.22-590/arch/ppc/platforms/4xx/ebony.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/4xx/ebony.c    2007-07-08 19:32:17.000000000 -0400
+@@ -32,7 +32,6 @@
+ #include <linux/tty.h>
+ #include <linux/serial.h>
+ #include <linux/serial_core.h>
+-#include <linux/kgdb.h>
  
--      if (SCpnt->use_sg)
--              pci_unmap_sg(ha->pdev, SCpnt->request_buffer, SCpnt->use_sg,
--                           pci_dir);
-+      scsi_dma_unmap(SCpnt);
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+@@ -227,20 +226,14 @@
+       port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+       port.line = 0;
  
-       if (!DEV2H(cpp->data_len))
-               pci_dir = PCI_DMA_BIDIRECTIONAL;
-@@ -1700,9 +1680,9 @@
-                                           DEV2H(cpp->sense_len),
-                                           PCI_DMA_FROMDEVICE);
+-#ifdef CONFIG_SERIAL_8250
+-      if (early_serial_setup(&port) != 0)
++      if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 0 failed\n");
+-#endif
++      }
  
--      if (SCpnt->use_sg)
--              pci_dma_sync_sg_for_cpu(ha->pdev, SCpnt->request_buffer,
--                                      SCpnt->use_sg, pci_dir);
-+      if (scsi_sg_count(SCpnt))
-+              pci_dma_sync_sg_for_cpu(ha->pdev, scsi_sglist(SCpnt),
-+                                      scsi_sg_count(SCpnt), pci_dir);
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Configure debug serial access */
+       gen550_init(0, &port);
+-#endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(0, &port);
+-#endif
  
-       if (!DEV2H(cpp->data_len))
-               pci_dir = PCI_DMA_BIDIRECTIONAL;
-diff -Nurb linux-2.6.22-570/drivers/scsi/esp_scsi.c linux-2.6.22-590/drivers/scsi/esp_scsi.c
---- linux-2.6.22-570/drivers/scsi/esp_scsi.c   2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/scsi/esp_scsi.c   2008-01-02 13:56:37.000000000 -0500
-@@ -324,17 +324,14 @@
- static void esp_map_dma(struct esp *esp, struct scsi_cmnd *cmd)
- {
-       struct esp_cmd_priv *spriv = ESP_CMD_PRIV(cmd);
--      struct scatterlist *sg = cmd->request_buffer;
-+      struct scatterlist *sg = scsi_sglist(cmd);
-       int dir = cmd->sc_data_direction;
-       int total, i;
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
+       /* Purge TLB entry added in head_44x.S for early serial access */
+       _tlbie(UART0_IO_BASE);
+ #endif
+@@ -250,18 +243,14 @@
+       port.uartclk = clocks.uart1;
+       port.line = 1;
  
-       if (dir == DMA_NONE)
-               return;
+-#ifdef CONFIG_SERIAL_8250
+-      if (early_serial_setup(&port) != 1)
++      if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 1 failed\n");
+-#endif
++      }
  
--      BUG_ON(cmd->use_sg == 0);
--
--      spriv->u.num_sg = esp->ops->map_sg(esp, sg,
--                                         cmd->use_sg, dir);
-+      spriv->u.num_sg = esp->ops->map_sg(esp, sg, scsi_sg_count(cmd), dir);
-       spriv->cur_residue = sg_dma_len(sg);
-       spriv->cur_sg = sg;
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Configure debug serial access */
+       gen550_init(1, &port);
+ #endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(1, &port);
+-#endif
+ }
  
-@@ -407,8 +404,7 @@
-       if (dir == DMA_NONE)
-               return;
+ static void __init
+@@ -338,4 +327,8 @@
  
--      esp->ops->unmap_sg(esp, cmd->request_buffer,
--                         spriv->u.num_sg, dir);
-+      esp->ops->unmap_sg(esp, scsi_sglist(cmd), spriv->u.num_sg, dir);
+       ppc_md.nvram_read_val = todc_direct_read_val;
+       ppc_md.nvram_write_val = todc_direct_write_val;
++#ifdef CONFIG_KGDB
++      ppc_md.early_serial_map = ebony_early_serial_map;
++#endif
  }
++
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/4xx/luan.c linux-2.6.22-570/arch/ppc/platforms/4xx/luan.c
+--- linux-2.6.22-590/arch/ppc/platforms/4xx/luan.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/4xx/luan.c     2007-07-08 19:32:17.000000000 -0400
+@@ -30,7 +30,6 @@
+ #include <linux/tty.h>
+ #include <linux/serial.h>
+ #include <linux/serial_core.h>
+-#include <linux/kgdb.h>
  
- static void esp_save_pointers(struct esp *esp, struct esp_cmd_entry *ent)
-@@ -921,7 +917,7 @@
- static int esp_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
- {
-       struct scsi_device *dev = cmd->device;
--      struct esp *esp = host_to_esp(dev->host);
-+      struct esp *esp = shost_priv(dev->host);
-       struct esp_cmd_priv *spriv;
-       struct esp_cmd_entry *ent;
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+@@ -284,9 +283,6 @@
      if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 0 failed\n");
+       }
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(0, &port);
+-#endif
  
-@@ -2358,7 +2354,7 @@
+       port.membase = ioremap64(PPC440SP_UART1_ADDR, 8);
+       port.irq = UART1_INT;
+@@ -296,9 +292,6 @@
+       if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 1 failed\n");
+       }
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(1, &port);
+-#endif
  
- static int esp_slave_alloc(struct scsi_device *dev)
- {
--      struct esp *esp = host_to_esp(dev->host);
-+      struct esp *esp = shost_priv(dev->host);
-       struct esp_target_data *tp = &esp->target[dev->id];
-       struct esp_lun_data *lp;
+       port.membase = ioremap64(PPC440SP_UART2_ADDR, 8);
+       port.irq = UART2_INT;
+@@ -308,9 +301,6 @@
+       if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 2 failed\n");
+       }
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(2, &port);
+-#endif
+ }
  
-@@ -2382,7 +2378,7 @@
+ static void __init
+@@ -370,4 +360,7 @@
+       ppc_md.get_irq = NULL;          /* Set in ppc4xx_pic_init() */
  
- static int esp_slave_configure(struct scsi_device *dev)
- {
--      struct esp *esp = host_to_esp(dev->host);
-+      struct esp *esp = shost_priv(dev->host);
-       struct esp_target_data *tp = &esp->target[dev->id];
-       int goal_tags, queue_depth;
+       ppc_md.calibrate_decr = luan_calibrate_decr;
++#ifdef CONFIG_KGDB
++      ppc_md.early_serial_map = luan_early_serial_map;
++#endif
+ }
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/4xx/ocotea.c linux-2.6.22-570/arch/ppc/platforms/4xx/ocotea.c
+--- linux-2.6.22-590/arch/ppc/platforms/4xx/ocotea.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/4xx/ocotea.c   2007-07-08 19:32:17.000000000 -0400
+@@ -30,7 +30,6 @@
+ #include <linux/tty.h>
+ #include <linux/serial.h>
+ #include <linux/serial_core.h>
+-#include <linux/kgdb.h>
  
-@@ -2424,7 +2420,7 @@
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+@@ -250,20 +249,14 @@
+       port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+       port.line = 0;
  
- static int esp_eh_abort_handler(struct scsi_cmnd *cmd)
- {
--      struct esp *esp = host_to_esp(cmd->device->host);
-+      struct esp *esp = shost_priv(cmd->device->host);
-       struct esp_cmd_entry *ent, *tmp;
-       struct completion eh_done;
-       unsigned long flags;
-@@ -2540,7 +2536,7 @@
+-#ifdef CONFIG_SERIAL_8250
+-      if (early_serial_setup(&port) != 0)
++      if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 0 failed\n");
+-#endif
++      }
  
- static int esp_eh_bus_reset_handler(struct scsi_cmnd *cmd)
- {
--      struct esp *esp = host_to_esp(cmd->device->host);
-+      struct esp *esp = shost_priv(cmd->device->host);
-       struct completion eh_reset;
-       unsigned long flags;
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Configure debug serial access */
+       gen550_init(0, &port);
+-#endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(0, &port);
+-#endif
  
-@@ -2576,7 +2572,7 @@
/* All bets are off, reset the entire device.  */
- static int esp_eh_host_reset_handler(struct scsi_cmnd *cmd)
- {
--      struct esp *esp = host_to_esp(cmd->device->host);
-+      struct esp *esp = shost_priv(cmd->device->host);
-       unsigned long flags;
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
      /* Purge TLB entry added in head_44x.S for early serial access */
+       _tlbie(UART0_IO_BASE);
+ #endif
+@@ -273,18 +266,14 @@
+       port.uartclk = clocks.uart1;
+       port.line = 1;
  
-       spin_lock_irqsave(esp->host->host_lock, flags);
-@@ -2616,7 +2612,7 @@
+-#ifdef CONFIG_SERIAL_8250
+-      if (early_serial_setup(&port) != 1)
++      if (early_serial_setup(&port) != 0) {
+               printk("Early serial init of port 1 failed\n");
+-#endif
++      }
  
- static void esp_get_signalling(struct Scsi_Host *host)
- {
--      struct esp *esp = host_to_esp(host);
-+      struct esp *esp = shost_priv(host);
-       enum spi_signal_type type;
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Configure debug serial access */
+       gen550_init(1, &port);
+ #endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(1, &port);
+-#endif
+ }
  
-       if (esp->flags & ESP_FLAG_DIFFERENTIAL)
-@@ -2630,7 +2626,7 @@
- static void esp_set_offset(struct scsi_target *target, int offset)
- {
-       struct Scsi_Host *host = dev_to_shost(target->dev.parent);
--      struct esp *esp = host_to_esp(host);
-+      struct esp *esp = shost_priv(host);
-       struct esp_target_data *tp = &esp->target[target->id];
+ static void __init
+@@ -354,5 +343,8 @@
  
-       tp->nego_goal_offset = offset;
-@@ -2640,7 +2636,7 @@
- static void esp_set_period(struct scsi_target *target, int period)
- {
-       struct Scsi_Host *host = dev_to_shost(target->dev.parent);
--      struct esp *esp = host_to_esp(host);
-+      struct esp *esp = shost_priv(host);
-       struct esp_target_data *tp = &esp->target[target->id];
+       ppc_md.nvram_read_val = todc_direct_read_val;
+       ppc_md.nvram_write_val = todc_direct_write_val;
++#ifdef CONFIG_KGDB
++      ppc_md.early_serial_map = ocotea_early_serial_map;
++#endif
+       ppc_md.init = ocotea_init;
+ }
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/4xx/taishan.c linux-2.6.22-570/arch/ppc/platforms/4xx/taishan.c
+--- linux-2.6.22-590/arch/ppc/platforms/4xx/taishan.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/4xx/taishan.c  2007-07-08 19:32:17.000000000 -0400
+@@ -310,7 +310,7 @@
+       if (early_serial_setup(&port) != 0)
+               printk("Early serial init of port 0 failed\n");
  
-       tp->nego_goal_period = period;
-@@ -2650,7 +2646,7 @@
- static void esp_set_width(struct scsi_target *target, int width)
- {
-       struct Scsi_Host *host = dev_to_shost(target->dev.parent);
--      struct esp *esp = host_to_esp(host);
-+      struct esp *esp = shost_priv(host);
-       struct esp_target_data *tp = &esp->target[target->id];
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Configure debug serial access */
+       gen550_init(0, &port);
  
-       tp->nego_goal_width = (width ? 1 : 0);
-diff -Nurb linux-2.6.22-570/drivers/scsi/esp_scsi.h linux-2.6.22-590/drivers/scsi/esp_scsi.h
---- linux-2.6.22-570/drivers/scsi/esp_scsi.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/esp_scsi.h   2008-01-02 13:56:37.000000000 -0500
-@@ -517,8 +517,6 @@
-       struct sbus_dma         *dma;
- };
+@@ -326,7 +326,7 @@
+       if (early_serial_setup(&port) != 0)
+               printk("Early serial init of port 1 failed\n");
  
--#define host_to_esp(host)     ((struct esp *)(host)->hostdata)
--
- /* A front-end driver for the ESP chip should do the following in
-  * it's device probe routine:
-  * 1) Allocate the host and private area using scsi_host_alloc()
-diff -Nurb linux-2.6.22-570/drivers/scsi/fdomain.c linux-2.6.22-590/drivers/scsi/fdomain.c
---- linux-2.6.22-570/drivers/scsi/fdomain.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/fdomain.c    2008-01-02 13:56:37.000000000 -0500
-@@ -410,6 +410,8 @@
- static char * fdomain = NULL;
- module_param(fdomain, charp, 0);
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Configure debug serial access */
+       gen550_init(1, &port);
+ #endif
+@@ -387,6 +387,9 @@
  
-+#ifndef PCMCIA
-+
- static unsigned long addresses[] = {
-    0xc8000,
-    0xca000,
-@@ -426,6 +428,8 @@
+       ppc_md.calibrate_decr = taishan_calibrate_decr;
  
- static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
++#ifdef CONFIG_KGDB
++      ppc_md.early_serial_map = taishan_early_serial_map;
++#endif
+       ppc_md.init = taishan_init;
+ }
  
-+#endif /* !PCMCIA */
-+
- /*
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/4xx/xilinx_ml300.c linux-2.6.22-570/arch/ppc/platforms/4xx/xilinx_ml300.c
+--- linux-2.6.22-590/arch/ppc/platforms/4xx/xilinx_ml300.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/4xx/xilinx_ml300.c     2007-07-08 19:32:17.000000000 -0400
+@@ -16,8 +16,6 @@
+ #include <linux/serial_core.h>
+ #include <linux/serial_8250.h>
+ #include <linux/serialP.h>
+-#include <linux/kgdb.h>
+-
+ #include <asm/io.h>
+ #include <asm/machdep.h>
  
-   READ THIS BEFORE YOU ADD A SIGNATURE!
-@@ -458,6 +462,8 @@
+@@ -43,6 +41,9 @@
+  *      ppc4xx_map_io                         arch/ppc/syslib/ppc4xx_setup.c
+  *  start_kernel                              init/main.c
+  *    setup_arch                              arch/ppc/kernel/setup.c
++ * #if defined(CONFIG_KGDB)
++ *      *ppc_md.kgdb_map_scc() == gen550_kgdb_map_scc
++ * #endif
+  *      *ppc_md.setup_arch == ml300_setup_arch        this file
+  *        ppc4xx_setup_arch                   arch/ppc/syslib/ppc4xx_setup.c
+  *          ppc4xx_find_bridges                       arch/ppc/syslib/ppc405_pci.c
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/4xx/xilinx_ml403.c linux-2.6.22-570/arch/ppc/platforms/4xx/xilinx_ml403.c
+--- linux-2.6.22-590/arch/ppc/platforms/4xx/xilinx_ml403.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/4xx/xilinx_ml403.c     2007-07-08 19:32:17.000000000 -0400
+@@ -43,6 +43,9 @@
+  *      ppc4xx_map_io                         arch/ppc/syslib/ppc4xx_setup.c
+  *  start_kernel                              init/main.c
+  *    setup_arch                              arch/ppc/kernel/setup.c
++ * #if defined(CONFIG_KGDB)
++ *      *ppc_md.kgdb_map_scc() == gen550_kgdb_map_scc
++ * #endif
+  *      *ppc_md.setup_arch == ml403_setup_arch        this file
+  *        ppc4xx_setup_arch                   arch/ppc/syslib/ppc4xx_setup.c
+  *          ppc4xx_find_bridges                       arch/ppc/syslib/ppc405_pci.c
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/4xx/yucca.c linux-2.6.22-570/arch/ppc/platforms/4xx/yucca.c
+--- linux-2.6.22-590/arch/ppc/platforms/4xx/yucca.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/4xx/yucca.c    2007-07-08 19:32:17.000000000 -0400
+@@ -386,4 +386,7 @@
+       ppc_md.get_irq = NULL;          /* Set in ppc4xx_pic_init() */
  
- */
+       ppc_md.calibrate_decr = yucca_calibrate_decr;
++#ifdef CONFIG_KGDB
++      ppc_md.early_serial_map = yucca_early_serial_map;
++#endif
+ }
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/83xx/mpc834x_sys.c linux-2.6.22-570/arch/ppc/platforms/83xx/mpc834x_sys.c
+--- linux-2.6.22-590/arch/ppc/platforms/83xx/mpc834x_sys.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/83xx/mpc834x_sys.c     2007-07-08 19:32:17.000000000 -0400
+@@ -42,11 +42,11 @@
+ #include <asm/pci-bridge.h>
+ #include <asm/mpc83xx.h>
+ #include <asm/irq.h>
++#include <asm/kgdb.h>
+ #include <asm/ppc_sys.h>
+ #include <mm/mmu_decl.h>
  
-+#ifndef PCMCIA
-+
- static struct signature {
-    const char *signature;
-    int  sig_offset;
-@@ -503,6 +509,8 @@
+ #include <syslib/ppc83xx_setup.h>
+-#include <syslib/gen550.h>
  
- #define SIGNATURE_COUNT ARRAY_SIZE(signatures)
+ #ifndef CONFIG_PCI
+ unsigned long isa_io_base = 0;
+@@ -114,9 +114,7 @@
+       /* setup PCI host bridges */
+       mpc83xx_setup_hose();
+ #endif
+-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_KGDB_8250)
+       mpc83xx_early_serial_map();
+-#endif
  
-+#endif /* !PCMCIA */
-+
- static void print_banner( struct Scsi_Host *shpnt )
- {
-    if (!shpnt) return;                /* This won't ever happen */
-@@ -633,6 +641,8 @@
-    return 0;
- }
+       /* setup the board related info for the MDIO bus */
+       mdata = (struct gianfar_mdio_data *) ppc_sys_get_pdata(MPC83xx_MDIO);
+@@ -336,6 +334,7 @@
+       ppc_md.get_rtc_time = NULL;
+       ppc_md.calibrate_decr = mpc83xx_calibrate_decr;
  
-+#ifndef PCMCIA
-+
- /* fdomain_get_irq assumes that we have a valid MCA ID for a
-    TMC-1660/TMC-1680 Future Domain board.  Now, check to be sure the
-    bios_base matches these ports.  If someone was unlucky enough to have
-@@ -667,7 +677,6 @@
++      ppc_md.early_serial_map = mpc83xx_early_serial_map;
+ #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+       ppc_md.progress = gen550_progress;
+ #endif        /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/85xx/mpc8540_ads.c linux-2.6.22-570/arch/ppc/platforms/85xx/mpc8540_ads.c
+--- linux-2.6.22-590/arch/ppc/platforms/85xx/mpc8540_ads.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/85xx/mpc8540_ads.c     2007-07-08 19:32:17.000000000 -0400
+@@ -43,11 +43,11 @@
+ #include <asm/mpc85xx.h>
+ #include <asm/irq.h>
+ #include <asm/immap_85xx.h>
++#include <asm/kgdb.h>
+ #include <asm/ppc_sys.h>
+ #include <mm/mmu_decl.h>
  
- static int fdomain_isa_detect( int *irq, int *iobase )
- {
--#ifndef PCMCIA
-    int i, j;
-    int base = 0xdeadbeef;
-    int flag = 0;
-@@ -786,11 +795,22 @@
-    *iobase = base;
+ #include <syslib/ppc85xx_setup.h>
+-#include <syslib/gen550.h>
  
-    return 1;                  /* success */
--#else
-+}
-+
-+#else /* PCMCIA */
-+
-+static int fdomain_isa_detect( int *irq, int *iobase )
-+{
-+      if (irq)
-+              *irq = 0;
-+      if (iobase)
-+              *iobase = 0;
-    return 0;
--#endif
- }
+ /* ************************************************************************
+  *
+@@ -77,7 +77,7 @@
+       mpc85xx_setup_hose();
+ #endif
  
-+#endif /* !PCMCIA */
-+
-+
- /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int*
-    iobase) This function gets the Interrupt Level and I/O base address from
-    the PCI configuration registers. */
-@@ -1345,16 +1365,15 @@
+-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_KGDB_8250)
++#ifdef CONFIG_SERIAL_8250
+       mpc85xx_early_serial_map();
+ #endif
  
- #if ERRORS_ONLY
-       if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
--       if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) {
-+            char *buf = scsi_sglist(current_SC);
-+       if ((unsigned char)(*(buf + 2)) & 0x0f) {
-           unsigned char key;
-           unsigned char code;
-           unsigned char qualifier;
+@@ -215,6 +215,9 @@
+ #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+       ppc_md.progress = gen550_progress;
+ #endif        /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
++#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
++      ppc_md.early_serial_map = mpc85xx_early_serial_map;
++#endif        /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
+       if (ppc_md.progress)
+               ppc_md.progress("mpc8540ads_init(): exit", 0);
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/85xx/mpc8560_ads.c linux-2.6.22-570/arch/ppc/platforms/85xx/mpc8560_ads.c
+--- linux-2.6.22-590/arch/ppc/platforms/85xx/mpc8560_ads.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/85xx/mpc8560_ads.c     2007-07-08 19:32:17.000000000 -0400
+@@ -44,6 +44,7 @@
+ #include <asm/mpc85xx.h>
+ #include <asm/irq.h>
+ #include <asm/immap_85xx.h>
++#include <asm/kgdb.h>
+ #include <asm/ppc_sys.h>
+ #include <asm/cpm2.h>
+ #include <mm/mmu_decl.h>
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/85xx/mpc85xx_cds_common.c linux-2.6.22-570/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+--- linux-2.6.22-590/arch/ppc/platforms/85xx/mpc85xx_cds_common.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/85xx/mpc85xx_cds_common.c      2007-07-08 19:32:17.000000000 -0400
+@@ -47,12 +47,12 @@
+ #include <asm/immap_85xx.h>
+ #include <asm/cpm2.h>
+ #include <asm/ppc_sys.h>
++#include <asm/kgdb.h>
+ #include <mm/mmu_decl.h>
+ #include <syslib/cpm2_pic.h>
+ #include <syslib/ppc85xx_common.h>
+ #include <syslib/ppc85xx_setup.h>
+-#include <syslib/gen550.h>
  
--          key = (unsigned char)(*((char *)current_SC->request_buffer + 2))
--                & 0x0f;
--          code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
--          qualifier = (unsigned char)(*((char *)current_SC->request_buffer
--                                        + 13));
-+          key = (unsigned char)(*(buf + 2)) & 0x0f;
-+          code = (unsigned char)(*(buf + 12));
-+          qualifier = (unsigned char)(*(buf + 13));
  
-           if (key != UNIT_ATTENTION
-               && !(key == NOT_READY
-@@ -1405,8 +1424,8 @@
-    printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
-          SCpnt->target,
-          *(unsigned char *)SCpnt->cmnd,
--         SCpnt->use_sg,
--         SCpnt->request_bufflen );
-+         scsi_sg_count(SCpnt),
-+         scsi_bufflen(SCpnt));
+ #ifndef CONFIG_PCI
+@@ -436,7 +436,7 @@
+       mpc85xx_setup_hose();
  #endif
  
-    fdomain_make_bus_idle();
-@@ -1416,20 +1435,19 @@
+-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_KGDB_8250)
++#ifdef CONFIG_SERIAL_8250
+       mpc85xx_early_serial_map();
+ #endif
  
-    /* Initialize static data */
+@@ -590,6 +590,9 @@
+ #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+       ppc_md.progress = gen550_progress;
+ #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
++#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
++      ppc_md.early_serial_map = mpc85xx_early_serial_map;
++#endif        /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
  
--   if (current_SC->use_sg) {
--      current_SC->SCp.buffer =
--          (struct scatterlist *)current_SC->request_buffer;
--      current_SC->SCp.ptr              = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
-+   if (scsi_sg_count(current_SC)) {
-+         current_SC->SCp.buffer = scsi_sglist(current_SC);
-+         current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page)
-+                 + current_SC->SCp.buffer->offset;
-       current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
--      current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
-+         current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
-    } else {
--      current_SC->SCp.ptr              = (char *)current_SC->request_buffer;
--      current_SC->SCp.this_residual    = current_SC->request_bufflen;
-+         current_SC->SCp.ptr              = 0;
-+         current_SC->SCp.this_residual    = 0;
-       current_SC->SCp.buffer           = NULL;
-       current_SC->SCp.buffers_residual = 0;
-    }
-        
--   
-    current_SC->SCp.Status              = 0;
-    current_SC->SCp.Message             = 0;
-    current_SC->SCp.have_data_in        = 0;
-@@ -1472,8 +1490,8 @@
-          SCpnt->SCp.phase,
-          SCpnt->device->id,
-          *(unsigned char *)SCpnt->cmnd,
--         SCpnt->use_sg,
--         SCpnt->request_bufflen );
-+         scsi_sg_count(SCpnt),
-+         scsi_bufflen(SCpnt));
-    printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
-          SCpnt->SCp.sent_command,
-          SCpnt->SCp.have_data_in,
-diff -Nurb linux-2.6.22-570/drivers/scsi/gdth.c linux-2.6.22-590/drivers/scsi/gdth.c
---- linux-2.6.22-570/drivers/scsi/gdth.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/gdth.c       2008-01-02 13:56:37.000000000 -0500
-@@ -876,7 +876,7 @@
- /* Vortex only makes RAID controllers.
-  * We do not really want to specify all 550 ids here, so wildcard match.
-  */
--static struct pci_device_id gdthtable[] __attribute_used__ = {
-+static struct pci_device_id gdthtable[] __maybe_unused = {
-     {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
-     {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, 
-     {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, 
-@@ -1955,7 +1955,7 @@
-         for (j = 0; j < 12; ++j) 
-             rtc[j] = CMOS_READ(j);
-     } while (rtc[0] != CMOS_READ(0));
--    spin_lock_irqrestore(&rtc_lock, flags);
-+    spin_unlock_irqrestore(&rtc_lock, flags);
-     TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0],
-             *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]));
-     /* 3. send to controller firmware */
-diff -Nurb linux-2.6.22-570/drivers/scsi/hptiop.c linux-2.6.22-590/drivers/scsi/hptiop.c
---- linux-2.6.22-570/drivers/scsi/hptiop.c     2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/scsi/hptiop.c     2008-01-02 13:56:37.000000000 -0500
-@@ -339,20 +339,8 @@
+       if (ppc_md.progress)
+               ppc_md.progress("mpc85xx_cds_init(): exit", 0);
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/85xx/sbc8560.c linux-2.6.22-570/arch/ppc/platforms/85xx/sbc8560.c
+--- linux-2.6.22-590/arch/ppc/platforms/85xx/sbc8560.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/85xx/sbc8560.c 2007-07-08 19:32:17.000000000 -0400
+@@ -29,7 +29,6 @@
+ #include <linux/initrd.h>
+ #include <linux/module.h>
+ #include <linux/fsl_devices.h>
+-#include <linux/kgdb.h>
  
-       scp = hba->reqs[tag].scp;
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+@@ -44,13 +43,14 @@
+ #include <asm/mpc85xx.h>
+ #include <asm/irq.h>
+ #include <asm/immap_85xx.h>
++#include <asm/kgdb.h>
+ #include <asm/ppc_sys.h>
+ #include <mm/mmu_decl.h>
  
--      if (HPT_SCP(scp)->mapped) {
--              if (scp->use_sg)
--                      pci_unmap_sg(hba->pcidev,
--                              (struct scatterlist *)scp->request_buffer,
--                              scp->use_sg,
--                              scp->sc_data_direction
--                      );
--              else
--                      pci_unmap_single(hba->pcidev,
--                              HPT_SCP(scp)->dma_handle,
--                              scp->request_bufflen,
--                              scp->sc_data_direction
--                      );
--      }
-+      if (HPT_SCP(scp)->mapped)
-+              scsi_dma_unmap(scp);
+ #include <syslib/ppc85xx_common.h>
+ #include <syslib/ppc85xx_setup.h>
+-#include <syslib/gen550.h>
  
-       switch (le32_to_cpu(req->header.result)) {
-       case IOP_RESULT_SUCCESS:
-@@ -449,43 +437,26 @@
++#ifdef CONFIG_SERIAL_8250
+ static void __init
+ sbc8560_early_serial_map(void)
  {
-       struct Scsi_Host *host = scp->device->host;
-       struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
--      struct scatterlist *sglist = (struct scatterlist *)scp->request_buffer;
-+      struct scatterlist *sg;
-+      int idx, nseg;
--      /*
--       * though we'll not get non-use_sg fields anymore,
--       * keep use_sg checking anyway
--       */
--      if (scp->use_sg) {
--              int idx;
--
--              HPT_SCP(scp)->sgcnt = pci_map_sg(hba->pcidev,
--                              sglist, scp->use_sg,
--                              scp->sc_data_direction);
-+      nseg = scsi_dma_map(scp);
-+      BUG_ON(nseg < 0);
-+      if (!nseg)
-+              return 0;
-+
-+      HPT_SCP(scp)->sgcnt = nseg;
-               HPT_SCP(scp)->mapped = 1;
-+
-               BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors);
+@@ -66,16 +66,12 @@
+         uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART0_SIZE);
+       uart_req.type = PORT_16650;
  
--              for (idx = 0; idx < HPT_SCP(scp)->sgcnt; idx++) {
--                      psg[idx].pci_address =
--                              cpu_to_le64(sg_dma_address(&sglist[idx]));
--                      psg[idx].size = cpu_to_le32(sg_dma_len(&sglist[idx]));
-+      scsi_for_each_sg(scp, sg, HPT_SCP(scp)->sgcnt, idx) {
-+              psg[idx].pci_address = cpu_to_le64(sg_dma_address(sg));
-+              psg[idx].size = cpu_to_le32(sg_dma_len(sg));
-                       psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ?
-                               cpu_to_le32(1) : 0;
-               }
--
-               return HPT_SCP(scp)->sgcnt;
--      } else {
--              HPT_SCP(scp)->dma_handle = pci_map_single(
--                              hba->pcidev,
--                              scp->request_buffer,
--                              scp->request_bufflen,
--                              scp->sc_data_direction
--                      );
--              HPT_SCP(scp)->mapped = 1;
--              psg->pci_address = cpu_to_le64(HPT_SCP(scp)->dma_handle);
--              psg->size = cpu_to_le32(scp->request_bufflen);
--              psg->eot = cpu_to_le32(1);
--              return 1;
--      }
+-#ifdef CONFIG_SERIAL_8250
+-        if (early_serial_setup(&uart_req) != 0)
+-                printk("Early serial init of port 0 failed\n");
+-#endif
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       gen550_init(0, &uart_req);
+ #endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(0, &uart_req);
+-#endif
++ 
++        if (early_serial_setup(&uart_req) != 0)
++                printk("Early serial init of port 0 failed\n");
+  
+         /* Assume early_serial_setup() doesn't modify uart_req */
+       uart_req.line = 1;
+@@ -83,17 +79,14 @@
+         uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART1_SIZE);
+       uart_req.irq = MPC85xx_IRQ_EXT10;
+  
+-#ifdef CONFIG_SERIAL_8250
+-        if (early_serial_setup(&uart_req) != 0)
+-              printk("Early serial init of port 0 failed\n");
+-#endif
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
+-      gen550_init(0, &uart_req);
+-#endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(0, &uart_req);
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
++        gen550_init(1, &uart_req);
+ #endif
++ 
++        if (early_serial_setup(&uart_req) != 0)
++                printk("Early serial init of port 1 failed\n");
  }
++#endif
+ /* ************************************************************************
+  *
+@@ -122,7 +115,9 @@
+       /* setup PCI host bridges */
+       mpc85xx_setup_hose();
+ #endif
++#ifdef CONFIG_SERIAL_8250
+       sbc8560_early_serial_map();
++#endif
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+       /* Invalidate the entry we stole earlier the serial ports
+        * should be properly mapped */ 
+@@ -229,6 +224,9 @@
+ #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+       ppc_md.progress = gen550_progress;
+ #endif        /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
++#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
++      ppc_md.early_serial_map = sbc8560_early_serial_map;
++#endif        /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
+       if (ppc_md.progress)
+               ppc_md.progress("sbc8560_init(): exit", 0);
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/85xx/tqm85xx.c linux-2.6.22-570/arch/ppc/platforms/85xx/tqm85xx.c
+--- linux-2.6.22-590/arch/ppc/platforms/85xx/tqm85xx.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/85xx/tqm85xx.c 2007-07-08 19:32:17.000000000 -0400
+@@ -46,6 +46,7 @@
+ #include <asm/mpc85xx.h>
+ #include <asm/irq.h>
+ #include <asm/immap_85xx.h>
++#include <asm/kgdb.h>
+ #include <asm/ppc_sys.h>
+ #include <asm/cpm2.h>
+ #include <mm/mmu_decl.h>
+@@ -54,7 +55,6 @@
+ #include <syslib/cpm2_pic.h>
+ #include <syslib/ppc85xx_common.h>
+ #include <syslib/ppc85xx_rio.h>
+-#include <syslib/gen550.h>
+ #ifndef CONFIG_PCI
+ unsigned long isa_io_base = 0;
+@@ -121,7 +121,7 @@
+ #endif
  
- static int hptiop_queuecommand(struct scsi_cmnd *scp,
-@@ -530,9 +501,8 @@
-       req = (struct hpt_iop_request_scsi_command *)_req->req_virt;
+ #ifndef CONFIG_MPC8560
+-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_KGDB_8250)
++#if defined(CONFIG_SERIAL_8250)
+       mpc85xx_early_serial_map();
+ #endif
  
-       /* build S/G table */
--      if (scp->request_bufflen)
-               sg_count = hptiop_buildsgl(scp, req->sg_list);
--      else
-+      if (!sg_count)
-               HPT_SCP(scp)->mapped = 0;
+@@ -400,6 +400,9 @@
+ #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+       ppc_md.progress = gen550_progress;
+ #endif        /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
++#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
++      ppc_md.early_serial_map = mpc85xx_early_serial_map;
++#endif        /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
+ #endif /* CONFIG_MPC8560 */
  
-       req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);
-@@ -541,7 +511,7 @@
-       req->header.context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT |
-                                                       (u32)_req->index);
-       req->header.context_hi32 = 0;
--      req->dataxfer_length = cpu_to_le32(scp->request_bufflen);
-+      req->dataxfer_length = cpu_to_le32(scsi_bufflen(scp));
-       req->channel = scp->device->channel;
-       req->target = scp->device->id;
-       req->lun = scp->device->lun;
-diff -Nurb linux-2.6.22-570/drivers/scsi/ibmmca.c linux-2.6.22-590/drivers/scsi/ibmmca.c
---- linux-2.6.22-570/drivers/scsi/ibmmca.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/ibmmca.c     2008-01-02 13:56:37.000000000 -0500
-@@ -31,14 +31,21 @@
- #include <linux/mca.h>
- #include <linux/spinlock.h>
- #include <linux/init.h>
--#include <linux/mca-legacy.h>
+       if (ppc_md.progress)
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/apus_setup.c linux-2.6.22-570/arch/ppc/platforms/apus_setup.c
+--- linux-2.6.22-590/arch/ppc/platforms/apus_setup.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/apus_setup.c   2007-07-08 19:32:17.000000000 -0400
+@@ -598,6 +598,12 @@
+       ciab.ddra |= (SER_DTR | SER_RTS);   /* outputs */
+       ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
  
- #include <asm/system.h>
++#ifdef CONFIG_KGDB
++      /* turn Rx interrupts on for GDB */
++      amiga_custom.intena = IF_SETCLR | IF_RBF;
++      ser_RTSon();
++#endif
++
+       return 0;
+ }
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/chestnut.c linux-2.6.22-570/arch/ppc/platforms/chestnut.c
+--- linux-2.6.22-590/arch/ppc/platforms/chestnut.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/chestnut.c     2007-07-08 19:32:17.000000000 -0400
+@@ -34,9 +34,9 @@
  #include <asm/io.h>
+ #include <asm/hw_irq.h>
+ #include <asm/machdep.h>
++#include <asm/kgdb.h>
+ #include <asm/bootinfo.h>
+ #include <asm/mv64x60.h>
+-#include <syslib/gen550.h>
+ #include <platforms/chestnut.h>
  
- #include "scsi.h"
- #include <scsi/scsi_host.h>
--#include "ibmmca.h"
-+
-+/* Common forward declarations for all Linux-versions: */
-+static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
-+static int ibmmca_abort (Scsi_Cmnd *);
-+static int ibmmca_host_reset (Scsi_Cmnd *);
-+static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *);
-+static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout);
-+
-+
+ static void __iomem *sram_base; /* Virtual addr of Internal SRAM */
+@@ -492,7 +492,7 @@
+ static void __init
+ chestnut_map_io(void)
+ {
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       io_block_mapping(CHESTNUT_UART_BASE, CHESTNUT_UART_BASE, 0x100000,
+               _PAGE_IO);
+ #endif
+@@ -566,6 +566,9 @@
+ #if defined(CONFIG_SERIAL_TEXT_DEBUG)
+       ppc_md.progress = gen550_progress;
+ #endif
++#if defined(CONFIG_KGDB)
++      ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
++#endif
  
- /* current version of this driver-source: */
- #define IBMMCA_SCSI_DRIVER_VERSION "4.0b-ac"
-@@ -65,11 +72,11 @@
- #define IM_DEBUG_CMD_DEVICE   TYPE_TAPE
+       if (ppc_md.progress)
+                 ppc_md.progress("chestnut_init(): exit", 0);
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/ev64260.c linux-2.6.22-570/arch/ppc/platforms/ev64260.c
+--- linux-2.6.22-590/arch/ppc/platforms/ev64260.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/ev64260.c      2007-07-08 19:32:17.000000000 -0400
+@@ -330,7 +330,7 @@
+               port.iotype = UPIO_MEM;
+               port.flags = STD_COM_FLAGS;
  
- /* relative addresses of hardware registers on a subsystem */
--#define IM_CMD_REG(hi)        (hosts[(hi)]->io_port)  /*Command Interface, (4 bytes long) */
--#define IM_ATTN_REG(hi)       (hosts[(hi)]->io_port+4)        /*Attention (1 byte) */
--#define IM_CTR_REG(hi)        (hosts[(hi)]->io_port+5)        /*Basic Control (1 byte) */
--#define IM_INTR_REG(hi)       (hosts[(hi)]->io_port+6)        /*Interrupt Status (1 byte, r/o) */
--#define IM_STAT_REG(hi)       (hosts[(hi)]->io_port+7)        /*Basic Status (1 byte, read only) */
-+#define IM_CMD_REG(h) ((h)->io_port)  /*Command Interface, (4 bytes long) */
-+#define IM_ATTN_REG(h)        ((h)->io_port+4)        /*Attention (1 byte) */
-+#define IM_CTR_REG(h) ((h)->io_port+5)        /*Basic Control (1 byte) */
-+#define IM_INTR_REG(h)        ((h)->io_port+6)        /*Interrupt Status (1 byte, r/o) */
-+#define IM_STAT_REG(h)        ((h)->io_port+7)        /*Basic Status (1 byte, read only) */
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+               gen550_init(0, &port);
+ #endif
  
- /* basic I/O-port of first adapter */
- #define IM_IO_PORT    0x3540
-@@ -266,30 +273,36 @@
-     if ((display_mode & LED_ACTIVITY)||(!display_mode)) \
-     outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); }
+@@ -568,7 +568,7 @@
+       return;
+ }
  
--/*list of supported subsystems */
--struct subsys_list_struct {
--      unsigned short mca_id;
--      char *description;
--};
--
- /* types of different supported hardware that goes to hostdata special */
- #define IBM_SCSI2_FW     0
- #define IBM_7568_WCACHE  1
- #define IBM_EXP_UNIT     2
- #define IBM_SCSI_WCACHE  3
- #define IBM_SCSI         4
-+#define IBM_INTEGSCSI  5
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ static void __init
+ ev64260_map_io(void)
+ {
+@@ -624,12 +624,20 @@
+       ppc_md.setup_io_mappings = ev64260_map_io;
+       ppc_md.progress = gen550_progress;
+ #endif
++#if defined(CONFIG_KGDB)
++      ppc_md.setup_io_mappings = ev64260_map_io;
++      ppc_md.early_serial_map = ev64260_early_serial_map;
++#endif
+ #elif defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ #ifdef        CONFIG_SERIAL_TEXT_DEBUG
+       ppc_md.setup_io_mappings = ev64260_map_io;
+       ppc_md.progress = mv64x60_mpsc_progress;
+       mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
+ #endif        /* CONFIG_SERIAL_TEXT_DEBUG */
++#ifdef        CONFIG_KGDB
++      ppc_md.setup_io_mappings = ev64260_map_io;
++      ppc_md.early_serial_map = ev64260_early_serial_map;
++#endif        /* CONFIG_KGDB */
  
- /* other special flags for hostdata structure */
- #define FORCED_DETECTION         100
- #define INTEGRATED_SCSI          101
+ #endif
  
- /* List of possible IBM-SCSI-adapters */
--static struct subsys_list_struct subsys_list[] = {
--      {0x8efc, "IBM SCSI-2 F/W Adapter"},     /* special = 0 */
--      {0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/Cache"},  /* special = 1 */
--      {0x8ef8, "IBM Expansion Unit SCSI Controller"}, /* special = 2 */
--      {0x8eff, "IBM SCSI Adapter w/Cache"},   /* special = 3 */
--      {0x8efe, "IBM SCSI Adapter"},   /* special = 4 */
-+static short ibmmca_id_table[] = {
-+      0x8efc,
-+      0x8efd,
-+      0x8ef8,
-+      0x8eff,
-+      0x8efe,
-+      /* No entry for integrated SCSI, that's part of the register */
-+      0
-+};
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/hdpu.c linux-2.6.22-570/arch/ppc/platforms/hdpu.c
+--- linux-2.6.22-590/arch/ppc/platforms/hdpu.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/hdpu.c 2007-07-08 19:32:17.000000000 -0400
+@@ -281,6 +281,25 @@
+ #if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ static void __init hdpu_early_serial_map(void)
+ {
++#ifdef        CONFIG_KGDB
++      static char first_time = 1;
 +
-+static const char *ibmmca_description[] = {
-+      "IBM SCSI-2 F/W Adapter",       /* special = 0 */
-+      "IBM 7568 Industrial Computer SCSI Adapter w/Cache",    /* special = 1 */
-+      "IBM Expansion Unit SCSI Controller",   /* special = 2 */
-+      "IBM SCSI Adapter w/Cache",     /* special = 3 */
-+      "IBM SCSI Adapter",     /* special = 4 */
-+      "IBM Integrated SCSI Controller", /* special = 5 */
- };
++#if defined(CONFIG_KGDB_TTYS0)
++#define KGDB_PORT 0
++#elif defined(CONFIG_KGDB_TTYS1)
++#define KGDB_PORT 1
++#else
++#error "Invalid kgdb_tty port"
++#endif
++
++      if (first_time) {
++              gt_early_mpsc_init(KGDB_PORT,
++                                 B9600 | CS8 | CREAD | HUPCL | CLOCAL);
++              first_time = 0;
++      }
++
++      return;
++#endif
+ }
+ #endif
  
- /* Max number of logical devices (can be up from 0 to 14).  15 is the address
-@@ -375,30 +388,30 @@
- };
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/lopec.c linux-2.6.22-570/arch/ppc/platforms/lopec.c
+--- linux-2.6.22-590/arch/ppc/platforms/lopec.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/lopec.c        2007-07-08 19:32:17.000000000 -0400
+@@ -32,8 +32,7 @@
+ #include <asm/mpc10x.h>
+ #include <asm/hw_irq.h>
+ #include <asm/prep_nvram.h>
+-
+-#include <syslib/gen550.h>
++#include <asm/kgdb.h>
  
- /* macros to access host data structure */
--#define subsystem_pun(hi) (hosts[(hi)]->this_id)
--#define subsystem_maxid(hi) (hosts[(hi)]->max_id)
--#define ld(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_ld)
--#define get_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_ldn)
--#define get_scsi(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_scsi)
--#define local_checking_phase_flag(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_local_checking_phase_flag)
--#define got_interrupt(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_got_interrupt)
--#define stat_result(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_stat_result)
--#define reset_status(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_reset_status)
--#define last_scsi_command(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_command)
--#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type)
--#define last_scsi_blockcount(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_blockcount)
--#define last_scsi_logical_block(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_logical_block)
--#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type)
--#define next_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_next_ldn)
--#define IBM_DS(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_IBM_DS)
--#define special(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_special)
--#define subsystem_connector_size(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_connector_size)
--#define adapter_speed(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_adapter_speed)
--#define pos2(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[2])
--#define pos3(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[3])
--#define pos4(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[4])
--#define pos5(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[5])
--#define pos6(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[6])
-+#define subsystem_pun(h) ((h)->this_id)
-+#define subsystem_maxid(h) ((h)->max_id)
-+#define ld(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_ld)
-+#define get_ldn(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_get_ldn)
-+#define get_scsi(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_get_scsi)
-+#define local_checking_phase_flag(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_local_checking_phase_flag)
-+#define got_interrupt(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_got_interrupt)
-+#define stat_result(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_stat_result)
-+#define reset_status(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_reset_status)
-+#define last_scsi_command(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_command)
-+#define last_scsi_type(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_type)
-+#define last_scsi_blockcount(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_blockcount)
-+#define last_scsi_logical_block(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_logical_block)
-+#define last_scsi_type(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_type)
-+#define next_ldn(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_next_ldn)
-+#define IBM_DS(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_IBM_DS)
-+#define special(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_special)
-+#define subsystem_connector_size(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_connector_size)
-+#define adapter_speed(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_adapter_speed)
-+#define pos2(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[2])
-+#define pos3(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[3])
-+#define pos4(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[4])
-+#define pos5(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[5])
-+#define pos6(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[6])
+ /*
+  * Define all of the IRQ senses and polarities.  Taken from the
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/pplus.c linux-2.6.22-570/arch/ppc/platforms/pplus.c
+--- linux-2.6.22-590/arch/ppc/platforms/pplus.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/pplus.c        2007-07-08 19:32:17.000000000 -0400
+@@ -35,9 +35,9 @@
+ #include <asm/hawk.h>
+ #include <asm/todc.h>
+ #include <asm/bootinfo.h>
++#include <asm/kgdb.h>
+ #include <asm/reg.h>
  
- /* Define a arbitrary number as subsystem-marker-type. This number is, as
-    described in the ANSI-SCSI-standard, not occupied by other device-types. */
-@@ -459,11 +472,6 @@
- /*counter of concurrent disk read/writes, to turn on/off disk led */
- static int disk_rw_in_progress = 0;
+-#include <syslib/gen550.h>
+ #include "pplus.h"
  
--/* host information */
--static int found = 0;
--static struct Scsi_Host *hosts[IM_MAX_HOSTS + 1] = {
--      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
--};
- static unsigned int pos[8];   /* whole pos register-line for diagnosis */
- /* Taking into account the additions, made by ZP Gu.
-  * This selects now the preset value from the configfile and
-@@ -474,70 +482,68 @@
- static char ibm_ansi_order = 0;
- #endif
+ #undef DUMP_DBATS
+@@ -893,6 +893,9 @@
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+       ppc_md.progress = gen550_progress;
+ #endif                                /* CONFIG_SERIAL_TEXT_DEBUG */
++#ifdef CONFIG_KGDB
++      ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
++#endif
+ #ifdef CONFIG_SMP
+       smp_ops = &pplus_smp_ops;
+ #endif                                /* CONFIG_SMP */
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/radstone_ppc7d.c linux-2.6.22-570/arch/ppc/platforms/radstone_ppc7d.c
+--- linux-2.6.22-590/arch/ppc/platforms/radstone_ppc7d.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/radstone_ppc7d.c       2007-07-08 19:32:17.000000000 -0400
+@@ -84,7 +84,7 @@
+  * Serial port code
+  *****************************************************************************/
  
--static void issue_cmd(int, unsigned long, unsigned char);
-+static void issue_cmd(struct Scsi_Host *, unsigned long, unsigned char);
- static void internal_done(Scsi_Cmnd * cmd);
--static void check_devices(int, int);
--static int immediate_assign(int, unsigned int, unsigned int, unsigned int, unsigned int);
--static int immediate_feature(int, unsigned int, unsigned int);
-+static void check_devices(struct Scsi_Host *, int);
-+static int immediate_assign(struct Scsi_Host *, unsigned int, unsigned int, unsigned int, unsigned int);
-+static int immediate_feature(struct Scsi_Host *, unsigned int, unsigned int);
- #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
--static int immediate_reset(int, unsigned int);
-+static int immediate_reset(struct Scsi_Host *, unsigned int);
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+ static void __init ppc7d_early_serial_map(void)
+ {
+ #if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+@@ -113,10 +113,10 @@
+       if (early_serial_setup(&serial_req) != 0)
+               printk(KERN_ERR "Early serial init of port 1 failed\n");
+ #else
+-#error CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
++#error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
  #endif
--static int device_inquiry(int, int);
--static int read_capacity(int, int);
--static int get_pos_info(int);
-+static int device_inquiry(struct Scsi_Host *, int);
-+static int read_capacity(struct Scsi_Host *, int);
-+static int get_pos_info(struct Scsi_Host *);
- static char *ti_p(int);
- static char *ti_l(int);
- static char *ibmrate(unsigned int, int);
- static int probe_display(int);
--static int probe_bus_mode(int);
--static int device_exists(int, int, int *, int *);
--static struct Scsi_Host *ibmmca_register(struct scsi_host_template *, int, int, int, char *);
-+static int probe_bus_mode(struct Scsi_Host *);
-+static int device_exists(struct Scsi_Host *, int, int *, int *);
- static int option_setup(char *);
- /* local functions needed for proc_info */
--static int ldn_access_load(int, int);
--static int ldn_access_total_read_write(int);
-+static int ldn_access_load(struct Scsi_Host *, int);
-+static int ldn_access_total_read_write(struct Scsi_Host *);
+ }
+-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
++#endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */
  
- static irqreturn_t interrupt_handler(int irq, void *dev_id)
- {
--      int host_index, ihost_index;
-       unsigned int intr_reg;
-       unsigned int cmd_result;
-       unsigned int ldn;
-+      unsigned long flags;
-       Scsi_Cmnd *cmd;
-       int lastSCSI;
--      struct Scsi_Host *dev = dev_id;
-+      struct device *dev = dev_id;
-+      struct Scsi_Host *shpnt = dev_get_drvdata(dev);
-+
-+      spin_lock_irqsave(shpnt->host_lock, flags);
--      spin_lock(dev->host_lock);
--          /* search for one adapter-response on shared interrupt */
--          for (host_index = 0; hosts[host_index] && !(inb(IM_STAT_REG(host_index)) & IM_INTR_REQUEST); host_index++);
--      /* return if some other device on this IRQ caused the interrupt */
--      if (!hosts[host_index]) {
--              spin_unlock(dev->host_lock);
-+      if(!(inb(IM_STAT_REG(shpnt)) & IM_INTR_REQUEST)) {
-+              spin_unlock_irqrestore(shpnt->host_lock, flags);
-               return IRQ_NONE;
-       }
+ /*****************************************************************************
+  * Low-level board support code
+@@ -1459,16 +1459,18 @@
+            PPC7D_CPLD_COMS_COM4_TXEN, PPC7D_CPLD_COMS);
+ #endif /* CONFIG_SERIAL_MPSC */
  
-       /* the reset-function already did all the job, even ints got
-          renabled on the subsystem, so just return */
--      if ((reset_status(host_index) == IM_RESET_NOT_IN_PROGRESS_NO_INT) || (reset_status(host_index) == IM_RESET_FINISHED_OK_NO_INT)) {
--              reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS;
--              spin_unlock(dev->host_lock);
-+      if ((reset_status(shpnt) == IM_RESET_NOT_IN_PROGRESS_NO_INT) || (reset_status(shpnt) == IM_RESET_FINISHED_OK_NO_INT)) {
-+              reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS;
-+              spin_unlock_irqrestore(shpnt->host_lock, flags);
-               return IRQ_HANDLED;
-       }
+-#ifdef  CONFIG_SERIAL_TEXT_DEBUG
++#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+       ppc7d_early_serial_map();
++#ifdef  CONFIG_SERIAL_TEXT_DEBUG
+ #if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+       ppc_md.progress = mv64x60_mpsc_progress;
+ #elif defined(CONFIG_SERIAL_8250)
+       ppc_md.progress = gen550_progress;
+ #else
+-#error CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
++#error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
+ #endif /* CONFIG_SERIAL_8250 */
+ #endif /* CONFIG_SERIAL_TEXT_DEBUG */
++#endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */
  
-       /*must wait for attention reg not busy, then send EOI to subsystem */
-       while (1) {
--              if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
-+              if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
-                       break;
-               cpu_relax();
-       }
--      ihost_index = host_index;
-+
-       /*get command result and logical device */
--      intr_reg = (unsigned char) (inb(IM_INTR_REG(ihost_index)));
-+      intr_reg = (unsigned char) (inb(IM_INTR_REG(shpnt)));
-       cmd_result = intr_reg & 0xf0;
-       ldn = intr_reg & 0x0f;
-       /* get the last_scsi_command here */
--      lastSCSI = last_scsi_command(ihost_index)[ldn];
--      outb(IM_EOI | ldn, IM_ATTN_REG(ihost_index));
-+      lastSCSI = last_scsi_command(shpnt)[ldn];
-+      outb(IM_EOI | ldn, IM_ATTN_REG(shpnt));
-       
-       /*these should never happen (hw fails, or a local programming bug) */
-       if (!global_command_error_excuse) {
-@@ -547,38 +553,38 @@
-               case IM_SOFTWARE_SEQUENCING_ERROR:
-               case IM_CMD_ERROR:
-                       printk(KERN_ERR "IBM MCA SCSI: Fatal Subsystem ERROR!\n");
--                      printk(KERN_ERR "              Last cmd=0x%x, ena=%x, len=", lastSCSI, ld(ihost_index)[ldn].scb.enable);
--                      if (ld(ihost_index)[ldn].cmd)
--                              printk("%ld/%ld,", (long) (ld(ihost_index)[ldn].cmd->request_bufflen), (long) (ld(ihost_index)[ldn].scb.sys_buf_length));
-+                      printk(KERN_ERR "              Last cmd=0x%x, ena=%x, len=", lastSCSI, ld(shpnt)[ldn].scb.enable);
-+                      if (ld(shpnt)[ldn].cmd)
-+                              printk("%ld/%ld,", (long) (scsi_bufflen(ld(shpnt)[ldn].cmd)), (long) (ld(shpnt)[ldn].scb.sys_buf_length));
-                       else
-                               printk("none,");
--                      if (ld(ihost_index)[ldn].cmd)
--                              printk("Blocksize=%d", ld(ihost_index)[ldn].scb.u2.blk.length);
-+                      if (ld(shpnt)[ldn].cmd)
-+                              printk("Blocksize=%d", ld(shpnt)[ldn].scb.u2.blk.length);
-                       else
-                               printk("Blocksize=none");
--                      printk(", host=0x%x, ldn=0x%x\n", ihost_index, ldn);
--                      if (ld(ihost_index)[ldn].cmd) {
--                              printk(KERN_ERR "Blockcount=%d/%d\n", last_scsi_blockcount(ihost_index)[ldn], ld(ihost_index)[ldn].scb.u2.blk.count);
--                              printk(KERN_ERR "Logical block=%lx/%lx\n", last_scsi_logical_block(ihost_index)[ldn], ld(ihost_index)[ldn].scb.u1.log_blk_adr);
-+                      printk(", host=%p, ldn=0x%x\n", shpnt, ldn);
-+                      if (ld(shpnt)[ldn].cmd) {
-+                              printk(KERN_ERR "Blockcount=%d/%d\n", last_scsi_blockcount(shpnt)[ldn], ld(shpnt)[ldn].scb.u2.blk.count);
-+                              printk(KERN_ERR "Logical block=%lx/%lx\n", last_scsi_logical_block(shpnt)[ldn], ld(shpnt)[ldn].scb.u1.log_blk_adr);
-                       }
-                       printk(KERN_ERR "Reason given: %s\n", (cmd_result == IM_ADAPTER_HW_FAILURE) ? "HARDWARE FAILURE" : (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR) ? "SOFTWARE SEQUENCING ERROR" : (cmd_result == IM_CMD_ERROR) ? "COMMAND ERROR" : "UNKNOWN");
-                       /* if errors appear, enter this section to give detailed info */
-                       printk(KERN_ERR "IBM MCA SCSI: Subsystem Error-Status follows:\n");
--                      printk(KERN_ERR "              Command Type................: %x\n", last_scsi_type(ihost_index)[ldn]);
--                      printk(KERN_ERR "              Attention Register..........: %x\n", inb(IM_ATTN_REG(ihost_index)));
--                      printk(KERN_ERR "              Basic Control Register......: %x\n", inb(IM_CTR_REG(ihost_index)));
-+                      printk(KERN_ERR "              Command Type................: %x\n", last_scsi_type(shpnt)[ldn]);
-+                      printk(KERN_ERR "              Attention Register..........: %x\n", inb(IM_ATTN_REG(shpnt)));
-+                      printk(KERN_ERR "              Basic Control Register......: %x\n", inb(IM_CTR_REG(shpnt)));
-                       printk(KERN_ERR "              Interrupt Status Register...: %x\n", intr_reg);
--                      printk(KERN_ERR "              Basic Status Register.......: %x\n", inb(IM_STAT_REG(ihost_index)));
--                      if ((last_scsi_type(ihost_index)[ldn] == IM_SCB) || (last_scsi_type(ihost_index)[ldn] == IM_LONG_SCB)) {
--                              printk(KERN_ERR "              SCB-Command.................: %x\n", ld(ihost_index)[ldn].scb.command);
--                              printk(KERN_ERR "              SCB-Enable..................: %x\n", ld(ihost_index)[ldn].scb.enable);
--                              printk(KERN_ERR "              SCB-logical block address...: %lx\n", ld(ihost_index)[ldn].scb.u1.log_blk_adr);
--                              printk(KERN_ERR "              SCB-system buffer address...: %lx\n", ld(ihost_index)[ldn].scb.sys_buf_adr);
--                              printk(KERN_ERR "              SCB-system buffer length....: %lx\n", ld(ihost_index)[ldn].scb.sys_buf_length);
--                              printk(KERN_ERR "              SCB-tsb address.............: %lx\n", ld(ihost_index)[ldn].scb.tsb_adr);
--                              printk(KERN_ERR "              SCB-Chain address...........: %lx\n", ld(ihost_index)[ldn].scb.scb_chain_adr);
--                              printk(KERN_ERR "              SCB-block count.............: %x\n", ld(ihost_index)[ldn].scb.u2.blk.count);
--                              printk(KERN_ERR "              SCB-block length............: %x\n", ld(ihost_index)[ldn].scb.u2.blk.length);
-+                      printk(KERN_ERR "              Basic Status Register.......: %x\n", inb(IM_STAT_REG(shpnt)));
-+                      if ((last_scsi_type(shpnt)[ldn] == IM_SCB) || (last_scsi_type(shpnt)[ldn] == IM_LONG_SCB)) {
-+                              printk(KERN_ERR "              SCB-Command.................: %x\n", ld(shpnt)[ldn].scb.command);
-+                              printk(KERN_ERR "              SCB-Enable..................: %x\n", ld(shpnt)[ldn].scb.enable);
-+                              printk(KERN_ERR "              SCB-logical block address...: %lx\n", ld(shpnt)[ldn].scb.u1.log_blk_adr);
-+                              printk(KERN_ERR "              SCB-system buffer address...: %lx\n", ld(shpnt)[ldn].scb.sys_buf_adr);
-+                              printk(KERN_ERR "              SCB-system buffer length....: %lx\n", ld(shpnt)[ldn].scb.sys_buf_length);
-+                              printk(KERN_ERR "              SCB-tsb address.............: %lx\n", ld(shpnt)[ldn].scb.tsb_adr);
-+                              printk(KERN_ERR "              SCB-Chain address...........: %lx\n", ld(shpnt)[ldn].scb.scb_chain_adr);
-+                              printk(KERN_ERR "              SCB-block count.............: %x\n", ld(shpnt)[ldn].scb.u2.blk.count);
-+                              printk(KERN_ERR "              SCB-block length............: %x\n", ld(shpnt)[ldn].scb.u2.blk.length);
-                       }
-                       printk(KERN_ERR "              Send this report to the maintainer.\n");
-                       panic("IBM MCA SCSI: Fatal error message from the subsystem (0x%X,0x%X)!\n", lastSCSI, cmd_result);
-@@ -600,72 +606,73 @@
-               }
-       }
-       /* if no panic appeared, increase the interrupt-counter */
--      IBM_DS(ihost_index).total_interrupts++;
-+      IBM_DS(shpnt).total_interrupts++;
-       /*only for local checking phase */
--      if (local_checking_phase_flag(ihost_index)) {
--              stat_result(ihost_index) = cmd_result;
--              got_interrupt(ihost_index) = 1;
--              reset_status(ihost_index) = IM_RESET_FINISHED_OK;
--              last_scsi_command(ihost_index)[ldn] = NO_SCSI;
--              spin_unlock(dev->host_lock);
-+      if (local_checking_phase_flag(shpnt)) {
-+              stat_result(shpnt) = cmd_result;
-+              got_interrupt(shpnt) = 1;
-+              reset_status(shpnt) = IM_RESET_FINISHED_OK;
-+              last_scsi_command(shpnt)[ldn] = NO_SCSI;
-+              spin_unlock_irqrestore(shpnt->host_lock, flags);
-               return IRQ_HANDLED;
-       }
-       /* handling of commands coming from upper level of scsi driver */
--      if (last_scsi_type(ihost_index)[ldn] == IM_IMM_CMD) {
-+      if (last_scsi_type(shpnt)[ldn] == IM_IMM_CMD) {
-               /* verify ldn, and may handle rare reset immediate command */
--              if ((reset_status(ihost_index) == IM_RESET_IN_PROGRESS) && (last_scsi_command(ihost_index)[ldn] == IM_RESET_IMM_CMD)) {
-+              if ((reset_status(shpnt) == IM_RESET_IN_PROGRESS) && (last_scsi_command(shpnt)[ldn] == IM_RESET_IMM_CMD)) {
-                       if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) {
-                               disk_rw_in_progress = 0;
-                               PS2_DISK_LED_OFF();
--                              reset_status(ihost_index) = IM_RESET_FINISHED_FAIL;
-+                              reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
-                       } else {
-                               /*reset disk led counter, turn off disk led */
-                               disk_rw_in_progress = 0;
-                               PS2_DISK_LED_OFF();
--                              reset_status(ihost_index) = IM_RESET_FINISHED_OK;
-+                              reset_status(shpnt) = IM_RESET_FINISHED_OK;
-                       }
--                      stat_result(ihost_index) = cmd_result;
--                      last_scsi_command(ihost_index)[ldn] = NO_SCSI;
--                      last_scsi_type(ihost_index)[ldn] = 0;
--                      spin_unlock(dev->host_lock);
-+                      stat_result(shpnt) = cmd_result;
-+                      last_scsi_command(shpnt)[ldn] = NO_SCSI;
-+                      last_scsi_type(shpnt)[ldn] = 0;
-+                      spin_unlock_irqrestore(shpnt->host_lock, flags);
-                       return IRQ_HANDLED;
--              } else if (last_scsi_command(ihost_index)[ldn] == IM_ABORT_IMM_CMD) {
-+              } else if (last_scsi_command(shpnt)[ldn] == IM_ABORT_IMM_CMD) {
-                       /* react on SCSI abort command */
- #ifdef IM_DEBUG_PROBE
-                       printk("IBM MCA SCSI: Interrupt from SCSI-abort.\n");
- #endif
-                       disk_rw_in_progress = 0;
-                       PS2_DISK_LED_OFF();
--                      cmd = ld(ihost_index)[ldn].cmd;
--                      ld(ihost_index)[ldn].cmd = NULL;
-+                      cmd = ld(shpnt)[ldn].cmd;
-+                      ld(shpnt)[ldn].cmd = NULL;
-                       if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
-                               cmd->result = DID_NO_CONNECT << 16;
-                       else
-                               cmd->result = DID_ABORT << 16;
--                      stat_result(ihost_index) = cmd_result;
--                      last_scsi_command(ihost_index)[ldn] = NO_SCSI;
--                      last_scsi_type(ihost_index)[ldn] = 0;
-+                      stat_result(shpnt) = cmd_result;
-+                      last_scsi_command(shpnt)[ldn] = NO_SCSI;
-+                      last_scsi_type(shpnt)[ldn] = 0;
-                       if (cmd->scsi_done)
-                               (cmd->scsi_done) (cmd); /* should be the internal_done */
--                      spin_unlock(dev->host_lock);
-+                      spin_unlock_irqrestore(shpnt->host_lock, flags);
-                       return IRQ_HANDLED;
-               } else {
-                       disk_rw_in_progress = 0;
-                       PS2_DISK_LED_OFF();
--                      reset_status(ihost_index) = IM_RESET_FINISHED_OK;
--                      stat_result(ihost_index) = cmd_result;
--                      last_scsi_command(ihost_index)[ldn] = NO_SCSI;
--                      spin_unlock(dev->host_lock);
-+                      reset_status(shpnt) = IM_RESET_FINISHED_OK;
-+                      stat_result(shpnt) = cmd_result;
-+                      last_scsi_command(shpnt)[ldn] = NO_SCSI;
-+                      spin_unlock_irqrestore(shpnt->host_lock, flags);
-                       return IRQ_HANDLED;
-               }
-       }
--      last_scsi_command(ihost_index)[ldn] = NO_SCSI;
--      last_scsi_type(ihost_index)[ldn] = 0;
--      cmd = ld(ihost_index)[ldn].cmd;
--      ld(ihost_index)[ldn].cmd = NULL;
-+      last_scsi_command(shpnt)[ldn] = NO_SCSI;
-+      last_scsi_type(shpnt)[ldn] = 0;
-+      cmd = ld(shpnt)[ldn].cmd;
-+      ld(shpnt)[ldn].cmd = NULL;
- #ifdef IM_DEBUG_TIMEOUT
-       if (cmd) {
-               if ((cmd->target == TIMEOUT_PUN) && (cmd->device->lun == TIMEOUT_LUN)) {
-+                      spin_unlock_irqsave(shpnt->host_lock, flags);
-                       printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n", cmd->target, cmd->device->lun);
-                       return IRQ_HANDLED;
-               }
-@@ -674,15 +681,15 @@
-       /*if no command structure, just return, else clear cmd */
-       if (!cmd)
-       {
--              spin_unlock(dev->host_lock);
-+              spin_unlock_irqrestore(shpnt->host_lock, flags);
-               return IRQ_HANDLED;
-       }
+       /* Enable write access to user flash.  This is necessary for
+        * flash probe.
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/sandpoint.c linux-2.6.22-570/arch/ppc/platforms/sandpoint.c
+--- linux-2.6.22-590/arch/ppc/platforms/sandpoint.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/sandpoint.c    2007-07-08 19:32:17.000000000 -0400
+@@ -95,9 +95,9 @@
+ #include <asm/bootinfo.h>
+ #include <asm/mpc10x.h>
+ #include <asm/pci-bridge.h>
++#include <asm/kgdb.h>
+ #include <asm/ppc_sys.h>
  
- #ifdef IM_DEBUG_INT
--      printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", cmd->cmnd[0], intr_reg, ld(ihost_index)[ldn].tsb.dev_status, ld(ihost_index)[ldn].tsb.cmd_status, ld(ihost_index)[ldn].tsb.dev_error, ld(ihost_index)[ldn].tsb.cmd_error);
-+      printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", cmd->cmnd[0], intr_reg, ld(shpnt)[ldn].tsb.dev_status, ld(shpnt)[ldn].tsb.cmd_status, ld(shpnt)[ldn].tsb.dev_error, ld(shpnt)[ldn].tsb.cmd_error);
- #endif
-       /*if this is end of media read/write, may turn off PS/2 disk led */
--      if ((ld(ihost_index)[ldn].device_type != TYPE_NO_LUN) && (ld(ihost_index)[ldn].device_type != TYPE_NO_DEVICE)) {
-+      if ((ld(shpnt)[ldn].device_type != TYPE_NO_LUN) && (ld(shpnt)[ldn].device_type != TYPE_NO_DEVICE)) {
-               /* only access this, if there was a valid device addressed */
-               if (--disk_rw_in_progress == 0)
-                       PS2_DISK_LED_OFF();
-@@ -693,8 +700,8 @@
-        * adapters do not support CMD_TERMINATED, TASK_SET_FULL and
-        * ACA_ACTIVE as returning statusbyte information. (ML) */
-       if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) {
--              cmd->result = (unsigned char) (ld(ihost_index)[ldn].tsb.dev_status & 0x1e);
--              IBM_DS(ihost_index).total_errors++;
-+              cmd->result = (unsigned char) (ld(shpnt)[ldn].tsb.dev_status & 0x1e);
-+              IBM_DS(shpnt).total_errors++;
-       } else
-               cmd->result = 0;
-       /* write device status into cmd->result, and call done function */
-@@ -705,24 +712,25 @@
-               cmd->result |= DID_OK << 16;
-       if (cmd->scsi_done)
-               (cmd->scsi_done) (cmd);
--      spin_unlock(dev->host_lock);
-+      spin_unlock_irqrestore(shpnt->host_lock, flags);
-       return IRQ_HANDLED;
- }
+-#include <syslib/gen550.h>
+ #include "sandpoint.h"
  
--static void issue_cmd(int host_index, unsigned long cmd_reg, unsigned char attn_reg)
-+static void issue_cmd(struct Scsi_Host *shpnt, unsigned long cmd_reg,
-+                    unsigned char attn_reg)
- {
-       unsigned long flags;
-       /* must wait for attention reg not busy */
-       while (1) {
--              spin_lock_irqsave(hosts[host_index]->host_lock, flags);
--              if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
-+              spin_lock_irqsave(shpnt->host_lock, flags);
-+              if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
-                       break;
--              spin_unlock_irqrestore(hosts[host_index]->host_lock, flags);
-+              spin_unlock_irqrestore(shpnt->host_lock, flags);
-       }
-       /* write registers and enable system interrupts */
--      outl(cmd_reg, IM_CMD_REG(host_index));
--      outb(attn_reg, IM_ATTN_REG(host_index));
--      spin_unlock_irqrestore(hosts[host_index]->host_lock, flags);
-+      outl(cmd_reg, IM_CMD_REG(shpnt));
-+      outb(attn_reg, IM_ATTN_REG(shpnt));
-+      spin_unlock_irqrestore(shpnt->host_lock, flags);
- }
+ /* Set non-zero if an X2 Sandpoint detected. */
+@@ -730,6 +730,9 @@
+       ppc_md.nvram_read_val = todc_mc146818_read_val;
+       ppc_md.nvram_write_val = todc_mc146818_write_val;
  
- static void internal_done(Scsi_Cmnd * cmd)
-@@ -732,34 +740,34 @@
- }
++#ifdef CONFIG_KGDB
++      ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
++#endif
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+       ppc_md.progress = gen550_progress;
+ #endif
+diff -Nurb linux-2.6.22-590/arch/ppc/platforms/spruce.c linux-2.6.22-570/arch/ppc/platforms/spruce.c
+--- linux-2.6.22-590/arch/ppc/platforms/spruce.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/platforms/spruce.c       2007-07-08 19:32:17.000000000 -0400
+@@ -27,7 +27,6 @@
+ #include <linux/serial.h>
+ #include <linux/tty.h>
+ #include <linux/serial_core.h>
+-#include <linux/kgdb.h>
  
- /* SCSI-SCB-command for device_inquiry */
--static int device_inquiry(int host_index, int ldn)
-+static int device_inquiry(struct Scsi_Host *shpnt, int ldn)
- {
-       int retr;
-       struct im_scb *scb;
-       struct im_tsb *tsb;
-       unsigned char *buf;
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+@@ -38,9 +37,9 @@
+ #include <asm/time.h>
+ #include <asm/todc.h>
+ #include <asm/bootinfo.h>
++#include <asm/kgdb.h>
  
--      scb = &(ld(host_index)[ldn].scb);
--      tsb = &(ld(host_index)[ldn].tsb);
--      buf = (unsigned char *) (&(ld(host_index)[ldn].buf));
--      ld(host_index)[ldn].tsb.dev_status = 0; /* prepare statusblock */
-+      scb = &(ld(shpnt)[ldn].scb);
-+      tsb = &(ld(shpnt)[ldn].tsb);
-+      buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
-+      ld(shpnt)[ldn].tsb.dev_status = 0;      /* prepare statusblock */
-       for (retr = 0; retr < 3; retr++) {
-               /* fill scb with inquiry command */
-               scb->command = IM_DEVICE_INQUIRY_CMD | IM_NO_DISCONNECT;
-               scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
--              last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD;
--              last_scsi_type(host_index)[ldn] = IM_SCB;
-+              last_scsi_command(shpnt)[ldn] = IM_DEVICE_INQUIRY_CMD;
-+              last_scsi_type(shpnt)[ldn] = IM_SCB;
-               scb->sys_buf_adr = isa_virt_to_bus(buf);
-               scb->sys_buf_length = 255;      /* maximum bufferlength gives max info */
-               scb->tsb_adr = isa_virt_to_bus(tsb);
-               /* issue scb to passed ldn, and busy wait for interrupt */
--              got_interrupt(host_index) = 0;
--              issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
--              while (!got_interrupt(host_index))
-+              got_interrupt(shpnt) = 0;
-+              issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
-+              while (!got_interrupt(shpnt))
-                       barrier();
+ #include <syslib/cpc700.h>
+-#include <syslib/gen550.h>
  
-               /*if command successful, break */
--              if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
-+              if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
-                       return 1;
-       }
-       /*if all three retries failed, return "no device at this ldn" */
-@@ -769,34 +777,34 @@
-               return 1;
- }
+ #include "spruce.h"
  
--static int read_capacity(int host_index, int ldn)
-+static int read_capacity(struct Scsi_Host *shpnt, int ldn)
- {
-       int retr;
-       struct im_scb *scb;
-       struct im_tsb *tsb;
-       unsigned char *buf;
+@@ -179,32 +178,26 @@
+       serial_req.membase = (u_char *)UART0_IO_BASE;
+       serial_req.regshift = 0;
  
--      scb = &(ld(host_index)[ldn].scb);
--      tsb = &(ld(host_index)[ldn].tsb);
--      buf = (unsigned char *) (&(ld(host_index)[ldn].buf));
--      ld(host_index)[ldn].tsb.dev_status = 0;
-+      scb = &(ld(shpnt)[ldn].scb);
-+      tsb = &(ld(shpnt)[ldn].tsb);
-+      buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
-+      ld(shpnt)[ldn].tsb.dev_status = 0;
-       for (retr = 0; retr < 3; retr++) {
-               /*fill scb with read capacity command */
-               scb->command = IM_READ_CAPACITY_CMD;
-               scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
--              last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD;
--              last_scsi_type(host_index)[ldn] = IM_SCB;
-+              last_scsi_command(shpnt)[ldn] = IM_READ_CAPACITY_CMD;
-+              last_scsi_type(shpnt)[ldn] = IM_SCB;
-               scb->sys_buf_adr = isa_virt_to_bus(buf);
-               scb->sys_buf_length = 8;
-               scb->tsb_adr = isa_virt_to_bus(tsb);
-               /*issue scb to passed ldn, and busy wait for interrupt */
--              got_interrupt(host_index) = 0;
--              issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
--              while (!got_interrupt(host_index))
-+              got_interrupt(shpnt) = 0;
-+              issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
-+              while (!got_interrupt(shpnt))
-                       barrier();
++#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
++      gen550_init(0, &serial_req);
++#endif
+ #ifdef CONFIG_SERIAL_8250
+       if (early_serial_setup(&serial_req) != 0)
+               printk("Early serial init of port 0 failed\n");
+ #endif
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
+-      gen550_init(0, &serial_req);
+-#endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(0, &port);
+-#endif
  
-               /*if got capacity, get block length and return one device found */
--              if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
-+              if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
-                       return 1;
-       }
-       /*if all three retries failed, return "no device at this ldn" */
-@@ -806,39 +814,39 @@
-               return 1;
+       /* Assume early_serial_setup() doesn't modify serial_req */
+       serial_req.line = 1;
+       serial_req.irq = UART1_INT;
+       serial_req.membase = (u_char *)UART1_IO_BASE;
++#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
++      gen550_init(1, &serial_req);
++#endif
+ #ifdef CONFIG_SERIAL_8250
+       if (early_serial_setup(&serial_req) != 0)
+               printk("Early serial init of port 1 failed\n");
+ #endif
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
+-      gen550_init(1, &serial_req);
+-#endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(1, &serial_req);
+-#endif
  }
  
--static int get_pos_info(int host_index)
-+static int get_pos_info(struct Scsi_Host *shpnt)
- {
-       int retr;
-       struct im_scb *scb;
-       struct im_tsb *tsb;
-       unsigned char *buf;
+ TODC_ALLOC();
+@@ -323,4 +316,7 @@
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+       ppc_md.progress = gen550_progress;
+ #endif /* CONFIG_SERIAL_TEXT_DEBUG */
++#ifdef CONFIG_KGDB
++      ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
++#endif
+ }
+diff -Nurb linux-2.6.22-590/arch/ppc/syslib/Makefile linux-2.6.22-570/arch/ppc/syslib/Makefile
+--- linux-2.6.22-590/arch/ppc/syslib/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/syslib/Makefile  2007-07-08 19:32:17.000000000 -0400
+@@ -77,6 +77,7 @@
+ obj-$(CONFIG_8260_PCI9)               += m8260_pci_erratum9.o
+ obj-$(CONFIG_CPM2)            += cpm2_common.o cpm2_pic.o
+ ifeq ($(CONFIG_PPC_GEN550),y)
++obj-$(CONFIG_KGDB)            += gen550_kgdb.o gen550_dbg.o
+ obj-$(CONFIG_SERIAL_TEXT_DEBUG)       += gen550_dbg.o
+ endif
+ ifeq ($(CONFIG_SERIAL_MPSC_CONSOLE),y)
+diff -Nurb linux-2.6.22-590/arch/ppc/syslib/gen550.h linux-2.6.22-570/arch/ppc/syslib/gen550.h
+--- linux-2.6.22-590/arch/ppc/syslib/gen550.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/syslib/gen550.h  2007-07-08 19:32:17.000000000 -0400
+@@ -11,3 +11,4 @@
  
--      scb = &(ld(host_index)[MAX_LOG_DEV].scb);
--      tsb = &(ld(host_index)[MAX_LOG_DEV].tsb);
--      buf = (unsigned char *) (&(ld(host_index)[MAX_LOG_DEV].buf));
--      ld(host_index)[MAX_LOG_DEV].tsb.dev_status = 0;
-+      scb = &(ld(shpnt)[MAX_LOG_DEV].scb);
-+      tsb = &(ld(shpnt)[MAX_LOG_DEV].tsb);
-+      buf = (unsigned char *) (&(ld(shpnt)[MAX_LOG_DEV].buf));
-+      ld(shpnt)[MAX_LOG_DEV].tsb.dev_status = 0;
-       for (retr = 0; retr < 3; retr++) {
-               /*fill scb with get_pos_info command */
-               scb->command = IM_GET_POS_INFO_CMD;
-               scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
--              last_scsi_command(host_index)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;
--              last_scsi_type(host_index)[MAX_LOG_DEV] = IM_SCB;
-+              last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;
-+              last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_SCB;
-               scb->sys_buf_adr = isa_virt_to_bus(buf);
--              if (special(host_index) == IBM_SCSI2_FW)
-+              if (special(shpnt) == IBM_SCSI2_FW)
-                       scb->sys_buf_length = 256;      /* get all info from F/W adapter */
-               else
-                       scb->sys_buf_length = 18;       /* get exactly 18 bytes for other SCSI */
-               scb->tsb_adr = isa_virt_to_bus(tsb);
-               /*issue scb to ldn=15, and busy wait for interrupt */
--              got_interrupt(host_index) = 0;
--              issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
-+              got_interrupt(shpnt) = 0;
-+              issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
-               
-               /* FIXME: timeout */
--              while (!got_interrupt(host_index))
-+              while (!got_interrupt(shpnt))
-                       barrier();
+ extern void gen550_progress(char *, unsigned short);
+ extern void gen550_init(int, struct uart_port *);
++extern void gen550_kgdb_map_scc(void);
+diff -Nurb linux-2.6.22-590/arch/ppc/syslib/gen550_kgdb.c linux-2.6.22-570/arch/ppc/syslib/gen550_kgdb.c
+--- linux-2.6.22-590/arch/ppc/syslib/gen550_kgdb.c     1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/syslib/gen550_kgdb.c     2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,83 @@
++/*
++ * Generic 16550 kgdb support intended to be useful on a variety
++ * of platforms.  To enable this support, it is necessary to set
++ * the CONFIG_GEN550 option.  Any virtual mapping of the serial
++ * port(s) to be used can be accomplished by setting
++ * ppc_md.early_serial_map to a platform-specific mapping function.
++ *
++ * Adapted from ppc4xx_kgdb.c.
++ *
++ * Author: Matt Porter <mporter@kernel.crashing.org>
++ *
++ * 2002-2004 (c) MontaVista Software, Inc.  This file is licensed under
++ * the terms of the GNU General Public License version 2.  This program
++ * is licensed "as is" without any warranty of any kind, whether express
++ * or implied.
++ */
++
++#include <linux/types.h>
++#include <linux/kernel.h>
++
++#include <asm/machdep.h>
++
++extern unsigned long serial_init(int, void *);
++extern unsigned long serial_getc(unsigned long);
++extern unsigned long serial_putc(unsigned long, unsigned char);
++
++#if defined(CONFIG_KGDB_TTYS0)
++#define KGDB_PORT 0
++#elif defined(CONFIG_KGDB_TTYS1)
++#define KGDB_PORT 1
++#elif defined(CONFIG_KGDB_TTYS2)
++#define KGDB_PORT 2
++#elif defined(CONFIG_KGDB_TTYS3)
++#define KGDB_PORT 3
++#else
++#error "invalid kgdb_tty port"
++#endif
++
++static volatile unsigned int kgdb_debugport;
++
++void putDebugChar(unsigned char c)
++{
++      if (kgdb_debugport == 0)
++              kgdb_debugport = serial_init(KGDB_PORT, NULL);
++
++      serial_putc(kgdb_debugport, c);
++}
++
++int getDebugChar(void)
++{
++      if (kgdb_debugport == 0)
++              kgdb_debugport = serial_init(KGDB_PORT, NULL);
++
++      return(serial_getc(kgdb_debugport));
++}
++
++void kgdb_interruptible(int enable)
++{
++      return;
++}
++
++void putDebugString(char* str)
++{
++      while (*str != '\0') {
++              putDebugChar(*str);
++              str++;
++      }
++      putDebugChar('\r');
++      return;
++}
++
++/*
++ * Note: gen550_init() must be called already on the port we are going
++ * to use.
++ */
++void
++gen550_kgdb_map_scc(void)
++{
++      printk(KERN_DEBUG "kgdb init\n");
++      if (ppc_md.early_serial_map)
++              ppc_md.early_serial_map();
++      kgdb_debugport = serial_init(KGDB_PORT, NULL);
++}
+diff -Nurb linux-2.6.22-590/arch/ppc/syslib/ibm44x_common.c linux-2.6.22-570/arch/ppc/syslib/ibm44x_common.c
+--- linux-2.6.22-590/arch/ppc/syslib/ibm44x_common.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/syslib/ibm44x_common.c   2007-07-08 19:32:17.000000000 -0400
+@@ -192,6 +192,9 @@
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+       ppc_md.progress = gen550_progress;
+ #endif /* CONFIG_SERIAL_TEXT_DEBUG */
++#ifdef CONFIG_KGDB
++      ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
++#endif
  
-               /*if got POS-stuff, get block length and return one device found */
--              if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
-+              if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
-                       return 1;
-       }
-       /* if all three retries failed, return "no device at this ldn" */
-@@ -851,14 +859,16 @@
- /* SCSI-immediate-command for assign. This functions maps/unmaps specific
-  ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the
-  subsystem and for dynamical remapping od ldns. */
--static int immediate_assign(int host_index, unsigned int pun, unsigned int lun, unsigned int ldn, unsigned int operation)
-+static int immediate_assign(struct Scsi_Host *shpnt, unsigned int pun,
-+                          unsigned int lun, unsigned int ldn,
-+                          unsigned int operation)
- {
-       int retr;
-       unsigned long imm_cmd;
+       /*
+        * The Abatron BDI JTAG debugger does not tolerate others
+diff -Nurb linux-2.6.22-590/arch/ppc/syslib/mv64x60.c linux-2.6.22-570/arch/ppc/syslib/mv64x60.c
+--- linux-2.6.22-590/arch/ppc/syslib/mv64x60.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/syslib/mv64x60.c 2007-07-08 19:32:17.000000000 -0400
+@@ -241,12 +241,6 @@
+               .end    = MV64x60_IRQ_SDMA_0,
+               .flags  = IORESOURCE_IRQ,
+       },
+-      [4] = {
+-              .name   = "mpsc 0 irq",
+-              .start  = MV64x60_IRQ_MPSC_0,
+-              .end    = MV64x60_IRQ_MPSC_0,
+-              .flags  = IORESOURCE_IRQ,
+-      },
+ };
  
-       for (retr = 0; retr < 3; retr++) {
-               /* select mutation level of the SCSI-adapter */
--              switch (special(host_index)) {
-+              switch (special(shpnt)) {
-               case IBM_SCSI2_FW:
-                       imm_cmd = (unsigned long) (IM_ASSIGN_IMM_CMD);
-                       imm_cmd |= (unsigned long) ((lun & 7) << 24);
-@@ -867,7 +877,7 @@
-                       imm_cmd |= (unsigned long) ((ldn & 15) << 16);
-                       break;
-               default:
--                      imm_cmd = inl(IM_CMD_REG(host_index));
-+                      imm_cmd = inl(IM_CMD_REG(shpnt));
-                       imm_cmd &= (unsigned long) (0xF8000000);        /* keep reserved bits */
-                       imm_cmd |= (unsigned long) (IM_ASSIGN_IMM_CMD);
-                       imm_cmd |= (unsigned long) ((lun & 7) << 24);
-@@ -876,15 +886,15 @@
-                       imm_cmd |= (unsigned long) ((ldn & 15) << 16);
-                       break;
-               }
--              last_scsi_command(host_index)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD;
--              last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD;
--              got_interrupt(host_index) = 0;
--              issue_cmd(host_index, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
--              while (!got_interrupt(host_index))
-+              last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD;
-+              last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_IMM_CMD;
-+              got_interrupt(shpnt) = 0;
-+              issue_cmd(shpnt, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
-+              while (!got_interrupt(shpnt))
-                       barrier();
+ static struct platform_device mpsc0_device = {
+@@ -304,12 +298,6 @@
+               .end    = MV64360_IRQ_SDMA_1,
+               .flags  = IORESOURCE_IRQ,
+       },
+-      [4] = {
+-              .name   = "mpsc 1 irq",
+-              .start  = MV64360_IRQ_MPSC_1,
+-              .end    = MV64360_IRQ_MPSC_1,
+-              .flags  = IORESOURCE_IRQ,
+-      },
+ };
  
-               /*if command successful, break */
--              if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
-+              if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
-                       return 1;
-       }
-       if (retr >= 3)
-@@ -893,7 +903,7 @@
-               return 1;
+ static struct platform_device mpsc1_device = {
+@@ -1444,46 +1432,12 @@
+ static int __init
+ mv64x60_add_pds(void)
+ {
+-      int i, ret = 0;
+-
+-      for (i = 0; i < ARRAY_SIZE(mv64x60_pd_devs); i++) {
+-              if (mv64x60_pd_devs[i]) {
+-                      ret = platform_device_register(mv64x60_pd_devs[i]);
+-              }
+-              if (ret) {
+-                      while (--i >= 0)
+-                              platform_device_unregister(mv64x60_pd_devs[i]);
+-                      break;
+-              }
+-      }
+-      return ret;
++      return platform_add_devices(mv64x60_pd_devs,
++              ARRAY_SIZE(mv64x60_pd_devs));
  }
+ arch_initcall(mv64x60_add_pds);
  
--static int immediate_feature(int host_index, unsigned int speed, unsigned int timeout)
-+static int immediate_feature(struct Scsi_Host *shpnt, unsigned int speed, unsigned int timeout)
- {
-       int retr;
-       unsigned long imm_cmd;
-@@ -903,16 +913,16 @@
-               imm_cmd = IM_FEATURE_CTR_IMM_CMD;
-               imm_cmd |= (unsigned long) ((speed & 0x7) << 29);
-               imm_cmd |= (unsigned long) ((timeout & 0x1fff) << 16);
--              last_scsi_command(host_index)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD;
--              last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD;
--              got_interrupt(host_index) = 0;
-+              last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD;
-+              last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_IMM_CMD;
-+              got_interrupt(shpnt) = 0;
-               /* we need to run into command errors in order to probe for the
-                * right speed! */
-               global_command_error_excuse = 1;
--              issue_cmd(host_index, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
-+              issue_cmd(shpnt, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
-               
-               /* FIXME: timeout */
--              while (!got_interrupt(host_index))
-+              while (!got_interrupt(shpnt))
-                       barrier();
-               if (global_command_error_excuse == CMD_FAIL) {
-                       global_command_error_excuse = 0;
-@@ -920,7 +930,7 @@
-               } else
-                       global_command_error_excuse = 0;
-               /*if command successful, break */
--              if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
-+              if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
-                       return 1;
+ /*
+- * mv64x60_early_get_pdev_data()
+- *
+- * Get the data associated with a platform device by name and number.
+- */
+-struct platform_device * __init
+-mv64x60_early_get_pdev_data(const char *name, int id, int remove)
+-{
+-      int i;
+-      struct platform_device *pdev;
+-
+-      for (i = 0; i <ARRAY_SIZE(mv64x60_pd_devs); i++) {
+-              if ((pdev = mv64x60_pd_devs[i]) &&
+-                      pdev->id == id &&
+-                      !strcmp(pdev->name, name)) {
+-                      if (remove)
+-                              mv64x60_pd_devs[i] = NULL;
+-                      return pdev;
+-              }
+-      }
+-      return NULL;
+-}
+-
+-/*
+  *****************************************************************************
+  *
+  *    GT64260-Specific Routines
+@@ -1816,11 +1770,6 @@
+               r->start = MV64x60_IRQ_SDMA_0;
+               r->end = MV64x60_IRQ_SDMA_0;
        }
-       if (retr >= 3)
-@@ -930,35 +940,35 @@
+-      if ((r = platform_get_resource(&mpsc1_device, IORESOURCE_IRQ, 1))
+-                      != NULL) {
+-              r->start = GT64260_IRQ_MPSC_1;
+-              r->end = GT64260_IRQ_MPSC_1;
+-      }
+ #endif
  }
  
- #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
--static int immediate_reset(int host_index, unsigned int ldn)
-+static int immediate_reset(struct Scsi_Host *shpnt, unsigned int ldn)
+@@ -2466,6 +2415,7 @@
+       .attr = {
+               .name = "hs_reg",
+               .mode = S_IRUGO | S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size  = VAL_LEN_MAX,
+       .read  = mv64xxx_hs_reg_read,
+diff -Nurb linux-2.6.22-590/arch/ppc/syslib/mv64x60_dbg.c linux-2.6.22-570/arch/ppc/syslib/mv64x60_dbg.c
+--- linux-2.6.22-590/arch/ppc/syslib/mv64x60_dbg.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/syslib/mv64x60_dbg.c     2007-07-08 19:32:17.000000000 -0400
+@@ -34,7 +34,7 @@
+ void
+ mv64x60_progress_init(u32 base)
  {
-       int retries;
-       int ticks;
-       unsigned long imm_command;
+-      mv64x60_dbg_bh.v_base = (void*)base;
++      mv64x60_dbg_bh.v_base = base;
+       return;
+ }
  
-       for (retries = 0; retries < 3; retries++) {
--              imm_command = inl(IM_CMD_REG(host_index));
-+              imm_command = inl(IM_CMD_REG(shpnt));
-               imm_command &= (unsigned long) (0xFFFF0000);    /* keep reserved bits */
-               imm_command |= (unsigned long) (IM_RESET_IMM_CMD);
--              last_scsi_command(host_index)[ldn] = IM_RESET_IMM_CMD;
--              last_scsi_type(host_index)[ldn] = IM_IMM_CMD;
--              got_interrupt(host_index) = 0;
--              reset_status(host_index) = IM_RESET_IN_PROGRESS;
--              issue_cmd(host_index, (unsigned long) (imm_command), IM_IMM_CMD | ldn);
-+              last_scsi_command(shpnt)[ldn] = IM_RESET_IMM_CMD;
-+              last_scsi_type(shpnt)[ldn] = IM_IMM_CMD;
-+              got_interrupt(shpnt) = 0;
-+              reset_status(shpnt) = IM_RESET_IN_PROGRESS;
-+              issue_cmd(shpnt, (unsigned long) (imm_command), IM_IMM_CMD | ldn);
-               ticks = IM_RESET_DELAY * HZ;
--              while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks) {
-+              while (reset_status(shpnt) == IM_RESET_IN_PROGRESS && --ticks) {
-                       udelay((1 + 999 / HZ) * 1000);
-                       barrier();
-               }
-               /* if reset did not complete, just complain */
-               if (!ticks) {
-                       printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY);
--                      reset_status(host_index) = IM_RESET_FINISHED_OK;
-+                      reset_status(shpnt) = IM_RESET_FINISHED_OK;
-                       /* did not work, finish */
-                       return 1;
-               }
-               /*if command successful, break */
--              if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
-+              if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
-                       return 1;
-       }
-       if (retries >= 3)
-@@ -1060,35 +1070,35 @@
-       return 0;
+@@ -69,3 +69,53 @@
+       return;
  }
+ #endif        /* CONFIG_SERIAL_TEXT_DEBUG */
++
++
++#if defined(CONFIG_KGDB)
++
++#if defined(CONFIG_KGDB_TTYS0)
++#define KGDB_PORT 0
++#elif defined(CONFIG_KGDB_TTYS1)
++#define KGDB_PORT 1
++#else
++#error "Invalid kgdb_tty port"
++#endif
++
++void
++putDebugChar(unsigned char c)
++{
++      mv64x60_polled_putc(KGDB_PORT, (char)c);
++}
++
++int
++getDebugChar(void)
++{
++      unsigned char   c;
++
++      while (!mv64x60_polled_getc(KGDB_PORT, &c));
++      return (int)c;
++}
++
++void
++putDebugString(char* str)
++{
++      while (*str != '\0') {
++              putDebugChar(*str);
++              str++;
++      }
++      putDebugChar('\r');
++      return;
++}
++
++void
++kgdb_interruptible(int enable)
++{
++}
++
++void
++kgdb_map_scc(void)
++{
++      if (ppc_md.early_serial_map)
++              ppc_md.early_serial_map();
++}
++#endif        /* CONFIG_KGDB */
+diff -Nurb linux-2.6.22-590/arch/ppc/syslib/ppc4xx_setup.c linux-2.6.22-570/arch/ppc/syslib/ppc4xx_setup.c
+--- linux-2.6.22-590/arch/ppc/syslib/ppc4xx_setup.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/syslib/ppc4xx_setup.c    2007-07-08 19:32:17.000000000 -0400
+@@ -32,6 +32,7 @@
+ #include <asm/processor.h>
+ #include <asm/machdep.h>
+ #include <asm/page.h>
++#include <asm/kgdb.h>
+ #include <asm/ibm4xx.h>
+ #include <asm/time.h>
+ #include <asm/todc.h>
+diff -Nurb linux-2.6.22-590/arch/ppc/syslib/ppc83xx_setup.c linux-2.6.22-570/arch/ppc/syslib/ppc83xx_setup.c
+--- linux-2.6.22-590/arch/ppc/syslib/ppc83xx_setup.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/syslib/ppc83xx_setup.c   2007-07-08 19:32:17.000000000 -0400
+@@ -30,12 +30,12 @@
+ #include <linux/tty.h>        /* for linux/serial_core.h */
+ #include <linux/serial_core.h>
+ #include <linux/serial_8250.h>
+-#include <linux/kgdb.h>
  
--static int probe_bus_mode(int host_index)
-+static int probe_bus_mode(struct Scsi_Host *shpnt)
- {
-       struct im_pos_info *info;
-       int num_bus = 0;
-       int ldn;
+ #include <asm/time.h>
+ #include <asm/mpc83xx.h>
+ #include <asm/mmu.h>
+ #include <asm/ppc_sys.h>
++#include <asm/kgdb.h>
+ #include <asm/delay.h>
+ #include <asm/machdep.h>
  
--      info = (struct im_pos_info *) (&(ld(host_index)[MAX_LOG_DEV].buf));
--      if (get_pos_info(host_index)) {
-+      info = (struct im_pos_info *) (&(ld(shpnt)[MAX_LOG_DEV].buf));
-+      if (get_pos_info(shpnt)) {
-               if (info->connector_size & 0xf000)
--                      subsystem_connector_size(host_index) = 16;
-+                      subsystem_connector_size(shpnt) = 16;
-               else
--                      subsystem_connector_size(host_index) = 32;
-+                      subsystem_connector_size(shpnt) = 32;
-               num_bus |= (info->pos_4b & 8) >> 3;
-               for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
--                      if ((special(host_index) == IBM_SCSI_WCACHE) || (special(host_index) == IBM_7568_WCACHE)) {
-+                      if ((special(shpnt) == IBM_SCSI_WCACHE) || (special(shpnt) == IBM_7568_WCACHE)) {
-                               if (!((info->cache_stat >> ldn) & 1))
--                                      ld(host_index)[ldn].cache_flag = 0;
-+                                      ld(shpnt)[ldn].cache_flag = 0;
-                       }
-                       if (!((info->retry_stat >> ldn) & 1))
--                              ld(host_index)[ldn].retry_flag = 0;
-+                              ld(shpnt)[ldn].retry_flag = 0;
-               }
- #ifdef IM_DEBUG_PROBE
-               printk("IBM MCA SCSI: SCSI-Cache bits: ");
-               for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
--                      printk("%d", ld(host_index)[ldn].cache_flag);
-+                      printk("%d", ld(shpnt)[ldn].cache_flag);
-               }
-               printk("\nIBM MCA SCSI: SCSI-Retry bits: ");
-               for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
--                      printk("%d", ld(host_index)[ldn].retry_flag);
-+                      printk("%d", ld(shpnt)[ldn].retry_flag);
-               }
-               printk("\n");
+@@ -44,7 +44,6 @@
+ #include <asm/delay.h>
+ #include <syslib/ppc83xx_pci.h>
  #endif
-@@ -1097,7 +1107,7 @@
+-#include <syslib/gen550.h>
+ phys_addr_t immrbar;
+@@ -88,11 +87,11 @@
+       tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
  }
  
- /* probing scsi devices */
--static void check_devices(int host_index, int adaptertype)
-+static void check_devices(struct Scsi_Host *shpnt, int adaptertype)
+-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_KGDB_8250)
++#ifdef CONFIG_SERIAL_8250
+ void __init
+ mpc83xx_early_serial_map(void)
  {
-       int id, lun, ldn, ticks;
-       int count_devices;      /* local counter for connected device */
-@@ -1108,24 +1118,24 @@
-       /* assign default values to certain variables */
-       ticks = 0;
-       count_devices = 0;
--      IBM_DS(host_index).dyn_flag = 0;        /* normally no need for dynamical ldn management */
--      IBM_DS(host_index).total_errors = 0;    /* set errorcounter to 0 */
--      next_ldn(host_index) = 7;       /* next ldn to be assigned is 7, because 0-6 is 'hardwired' */
-+      IBM_DS(shpnt).dyn_flag = 0;     /* normally no need for dynamical ldn management */
-+      IBM_DS(shpnt).total_errors = 0; /* set errorcounter to 0 */
-+      next_ldn(shpnt) = 7;    /* next ldn to be assigned is 7, because 0-6 is 'hardwired' */
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       struct uart_port serial_req;
+ #endif
+       struct plat_serial8250_port *pdata;
+@@ -104,40 +103,27 @@
+       pdata[0].mapbase += binfo->bi_immr_base;
+       pdata[0].membase = ioremap(pdata[0].mapbase, 0x100);
  
-       /* initialize the very important driver-informational arrays/structs */
--      memset(ld(host_index), 0, sizeof(ld(host_index)));
-+      memset(ld(shpnt), 0, sizeof(ld(shpnt)));
-       for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
--              last_scsi_command(host_index)[ldn] = NO_SCSI;   /* emptify last SCSI-command storage */
--              last_scsi_type(host_index)[ldn] = 0;
--              ld(host_index)[ldn].cache_flag = 1;
--              ld(host_index)[ldn].retry_flag = 1;
-+              last_scsi_command(shpnt)[ldn] = NO_SCSI;        /* emptify last SCSI-command storage */
-+              last_scsi_type(shpnt)[ldn] = 0;
-+              ld(shpnt)[ldn].cache_flag = 1;
-+              ld(shpnt)[ldn].retry_flag = 1;
-       }
--      memset(get_ldn(host_index), TYPE_NO_DEVICE, sizeof(get_ldn(host_index)));       /* this is essential ! */
--      memset(get_scsi(host_index), TYPE_NO_DEVICE, sizeof(get_scsi(host_index)));     /* this is essential ! */
-+      memset(get_ldn(shpnt), TYPE_NO_DEVICE, sizeof(get_ldn(shpnt))); /* this is essential ! */
-+      memset(get_scsi(shpnt), TYPE_NO_DEVICE, sizeof(get_scsi(shpnt)));       /* this is essential ! */
-       for (lun = 0; lun < 8; lun++) {
-               /* mark the adapter at its pun on all luns */
--              get_scsi(host_index)[subsystem_pun(host_index)][lun] = TYPE_IBM_SCSI_ADAPTER;
--              get_ldn(host_index)[subsystem_pun(host_index)][lun] = MAX_LOG_DEV;      /* make sure, the subsystem
-+              get_scsi(shpnt)[subsystem_pun(shpnt)][lun] = TYPE_IBM_SCSI_ADAPTER;
-+              get_ldn(shpnt)[subsystem_pun(shpnt)][lun] = MAX_LOG_DEV;        /* make sure, the subsystem
-                                                                                          ldn is active for all
-                                                                                          luns. */
-       }
-@@ -1134,9 +1144,9 @@
-       /* monitor connected on model XX95. */
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       memset(&serial_req, 0, sizeof (serial_req));
+       serial_req.iotype = UPIO_MEM;
+       serial_req.mapbase = pdata[0].mapbase;
+       serial_req.membase = pdata[0].membase;
+       serial_req.regshift = 0;
+-      serial_req.irq = pdata[0].irq;
+-      serial_req.flags = pdata[0].flags;
+-      serial_req.uartclk = pdata[0].uartclk;
  
-       /* STEP 1: */
--      adapter_speed(host_index) = global_adapter_speed;
--      speedrun = adapter_speed(host_index);
--      while (immediate_feature(host_index, speedrun, adapter_timeout) == 2) {
-+      adapter_speed(shpnt) = global_adapter_speed;
-+      speedrun = adapter_speed(shpnt);
-+      while (immediate_feature(shpnt, speedrun, adapter_timeout) == 2) {
-               probe_display(1);
-               if (speedrun == 7)
-                       panic("IBM MCA SCSI: Cannot set Synchronous-Transfer-Rate!\n");
-@@ -1144,30 +1154,30 @@
-               if (speedrun > 7)
-                       speedrun = 7;
-       }
--      adapter_speed(host_index) = speedrun;
-+      adapter_speed(shpnt) = speedrun;
-       /* Get detailed information about the current adapter, necessary for
-        * device operations: */
--      num_bus = probe_bus_mode(host_index);
-+      num_bus = probe_bus_mode(shpnt);
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
+       gen550_init(0, &serial_req);
+ #endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(0, &serial_req);
+-#endif
+-#endif
  
-       /* num_bus contains only valid data for the F/W adapter! */
-       if (adaptertype == IBM_SCSI2_FW) {      /* F/W SCSI adapter: */
-               /* F/W adapter PUN-space extension evaluation: */
-               if (num_bus) {
-                       printk(KERN_INFO "IBM MCA SCSI: Separate bus mode (wide-addressing enabled)\n");
--                      subsystem_maxid(host_index) = 16;
-+                      subsystem_maxid(shpnt) = 16;
-               } else {
-                       printk(KERN_INFO "IBM MCA SCSI: Combined bus mode (wide-addressing disabled)\n");
--                      subsystem_maxid(host_index) = 8;
-+                      subsystem_maxid(shpnt) = 8;
-               }
-               printk(KERN_INFO "IBM MCA SCSI: Sync.-Rate (F/W: 20, Int.: 10, Ext.: %s) MBytes/s\n", ibmrate(speedrun, adaptertype));
-       } else                  /* all other IBM SCSI adapters: */
-               printk(KERN_INFO "IBM MCA SCSI: Synchronous-SCSI-Transfer-Rate: %s MBytes/s\n", ibmrate(speedrun, adaptertype));
+       pdata[1].uartclk = binfo->bi_busfreq;
+       pdata[1].mapbase += binfo->bi_immr_base;
+       pdata[1].membase = ioremap(pdata[1].mapbase, 0x100);
  
-       /* assign correct PUN device space */
--      max_pun = subsystem_maxid(host_index);
-+      max_pun = subsystem_maxid(shpnt);
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Assume gen550_init() doesn't modify serial_req */
+       serial_req.mapbase = pdata[1].mapbase;
+       serial_req.membase = pdata[1].membase;
  
- #ifdef IM_DEBUG_PROBE
--      printk("IBM MCA SCSI: Current SCSI-host index: %d\n", host_index);
-+      printk("IBM MCA SCSI: Current SCSI-host index: %d\n", shpnt);
-       printk("IBM MCA SCSI: Removing default logical SCSI-device mapping.");
- #else
-       printk(KERN_INFO "IBM MCA SCSI: Dev. Order: %s, Mapping (takes <2min): ", (ibm_ansi_order) ? "ANSI" : "New");
-@@ -1177,7 +1187,7 @@
- #ifdef IM_DEBUG_PROBE
-               printk(".");
- #endif
--              immediate_assign(host_index, 0, 0, ldn, REMOVE_LDN);    /* remove ldn (wherever) */
-+              immediate_assign(shpnt, 0, 0, ldn, REMOVE_LDN); /* remove ldn (wherever) */
-       }
-       lun = 0;                /* default lun is 0 */
- #ifndef IM_DEBUG_PROBE
-@@ -1196,18 +1206,18 @@
- #ifdef IM_DEBUG_PROBE
-                       printk(".");
- #endif
--                      if (id != subsystem_pun(host_index)) {
-+                      if (id != subsystem_pun(shpnt)) {
-                               /* if pun is not the adapter: */
-                               /* set ldn=0 to pun,lun */
--                              immediate_assign(host_index, id, lun, PROBE_LDN, SET_LDN);
--                              if (device_inquiry(host_index, PROBE_LDN)) {    /* probe device */
--                                      get_scsi(host_index)[id][lun] = (unsigned char) (ld(host_index)[PROBE_LDN].buf[0]);
-+                              immediate_assign(shpnt, id, lun, PROBE_LDN, SET_LDN);
-+                              if (device_inquiry(shpnt, PROBE_LDN)) { /* probe device */
-+                                      get_scsi(shpnt)[id][lun] = (unsigned char) (ld(shpnt)[PROBE_LDN].buf[0]);
-                                       /* entry, even for NO_LUN */
--                                      if (ld(host_index)[PROBE_LDN].buf[0] != TYPE_NO_LUN)
-+                                      if (ld(shpnt)[PROBE_LDN].buf[0] != TYPE_NO_LUN)
-                                               count_devices++;        /* a existing device is found */
-                               }
-                               /* remove ldn */
--                              immediate_assign(host_index, id, lun, PROBE_LDN, REMOVE_LDN);
-+                              immediate_assign(shpnt, id, lun, PROBE_LDN, REMOVE_LDN);
-                       }
-               }
- #ifndef IM_DEBUG_PROBE
-@@ -1227,16 +1237,16 @@
- #ifdef IM_DEBUG_PROBE
-                       printk(".");
- #endif
--                      if (id != subsystem_pun(host_index)) {
--                              if (get_scsi(host_index)[id][lun] != TYPE_NO_LUN && get_scsi(host_index)[id][lun] != TYPE_NO_DEVICE) {
-+                      if (id != subsystem_pun(shpnt)) {
-+                              if (get_scsi(shpnt)[id][lun] != TYPE_NO_LUN && get_scsi(shpnt)[id][lun] != TYPE_NO_DEVICE) {
-                                       /* Only map if accepted type. Always enter for
-                                          lun == 0 to get no gaps into ldn-mapping for ldn<7. */
--                                      immediate_assign(host_index, id, lun, ldn, SET_LDN);
--                                      get_ldn(host_index)[id][lun] = ldn;     /* map ldn */
--                                      if (device_exists(host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) {
-+                                      immediate_assign(shpnt, id, lun, ldn, SET_LDN);
-+                                      get_ldn(shpnt)[id][lun] = ldn;  /* map ldn */
-+                                      if (device_exists(shpnt, ldn, &ld(shpnt)[ldn].block_length, &ld(shpnt)[ldn].device_type)) {
- #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
-                                               printk("resetting device at ldn=%x ... ", ldn);
--                                              immediate_reset(host_index, ldn);
-+                                              immediate_reset(shpnt, ldn);
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
+       gen550_init(1, &serial_req);
  #endif
-                                               ldn++;
-                                       } else {
-@@ -1244,15 +1254,15 @@
-                                                * handle it or because it has problems */
-                                               if (lun > 0) {
-                                                       /* remove mapping */
--                                                      get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;
--                                                      immediate_assign(host_index, 0, 0, ldn, REMOVE_LDN);
-+                                                      get_ldn(shpnt)[id][lun] = TYPE_NO_DEVICE;
-+                                                      immediate_assign(shpnt, 0, 0, ldn, REMOVE_LDN);
-                                               } else
-                                                       ldn++;
-                                       }
-                               } else if (lun == 0) {
-                                       /* map lun == 0, even if no device exists */
--                                      immediate_assign(host_index, id, lun, ldn, SET_LDN);
--                                      get_ldn(host_index)[id][lun] = ldn;     /* map ldn */
-+                                      immediate_assign(shpnt, id, lun, ldn, SET_LDN);
-+                                      get_ldn(shpnt)[id][lun] = ldn;  /* map ldn */
-                                       ldn++;
-                               }
-                       }
-@@ -1262,14 +1272,14 @@
-       /* map remaining ldns to non-existing devices */
-       for (lun = 1; lun < 8 && ldn < MAX_LOG_DEV; lun++)
-               for (id = 0; id < max_pun && ldn < MAX_LOG_DEV; id++) {
--                      if (get_scsi(host_index)[id][lun] == TYPE_NO_LUN || get_scsi(host_index)[id][lun] == TYPE_NO_DEVICE) {
-+                      if (get_scsi(shpnt)[id][lun] == TYPE_NO_LUN || get_scsi(shpnt)[id][lun] == TYPE_NO_DEVICE) {
-                               probe_display(1);
-                               /* Map remaining ldns only to NON-existing pun,lun
-                                  combinations to make sure an inquiry will fail.
-                                  For MULTI_LUN, it is needed to avoid adapter autonome
-                                  SCSI-remapping. */
--                              immediate_assign(host_index, id, lun, ldn, SET_LDN);
--                              get_ldn(host_index)[id][lun] = ldn;
-+                              immediate_assign(shpnt, id, lun, ldn, SET_LDN);
-+                              get_ldn(shpnt)[id][lun] = ldn;
-                               ldn++;
-                       }
-               }
-@@ -1292,51 +1302,51 @@
-       for (id = 0; id < max_pun; id++) {
-               printk("%2d     ", id);
-               for (lun = 0; lun < 8; lun++)
--                      printk("%2s ", ti_p(get_scsi(host_index)[id][lun]));
-+                      printk("%2s ", ti_p(get_scsi(shpnt)[id][lun]));
-               printk("      %2d     ", id);
-               for (lun = 0; lun < 8; lun++)
--                      printk("%2s ", ti_l(get_ldn(host_index)[id][lun]));
-+                      printk("%2s ", ti_l(get_ldn(shpnt)[id][lun]));
-               printk("\n");
-       }
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(1, &serial_req);
+-#endif
+-#endif
+ }
  #endif
  
-       /* assign total number of found SCSI-devices to the statistics struct */
--      IBM_DS(host_index).total_scsi_devices = count_devices;
-+      IBM_DS(shpnt).total_scsi_devices = count_devices;
+diff -Nurb linux-2.6.22-590/arch/ppc/syslib/ppc85xx_setup.c linux-2.6.22-570/arch/ppc/syslib/ppc85xx_setup.c
+--- linux-2.6.22-590/arch/ppc/syslib/ppc85xx_setup.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/ppc/syslib/ppc85xx_setup.c   2007-07-08 19:32:17.000000000 -0400
+@@ -19,17 +19,16 @@
+ #include <linux/tty.h>        /* for linux/serial_core.h */
+ #include <linux/serial_core.h>
+ #include <linux/serial_8250.h>
+-#include <linux/kgdb.h>
  
-       /* decide for output in /proc-filesystem, if the configuration of
-          SCSI-devices makes dynamical reassignment of devices necessary */
-       if (count_devices >= MAX_LOG_DEV)
--              IBM_DS(host_index).dyn_flag = 1;        /* dynamical assignment is necessary */
-+              IBM_DS(shpnt).dyn_flag = 1;     /* dynamical assignment is necessary */
-       else
--              IBM_DS(host_index).dyn_flag = 0;        /* dynamical assignment is not necessary */
-+              IBM_DS(shpnt).dyn_flag = 0;     /* dynamical assignment is not necessary */
+ #include <asm/time.h>
+ #include <asm/mpc85xx.h>
+ #include <asm/immap_85xx.h>
+ #include <asm/mmu.h>
+ #include <asm/ppc_sys.h>
++#include <asm/kgdb.h>
+ #include <asm/machdep.h>
  
-       /* If no SCSI-devices are assigned, return 1 in order to cause message. */
-       if (ldn == 0)
-               printk("IBM MCA SCSI: Warning: No SCSI-devices found/assigned!\n");
+ #include <syslib/ppc85xx_setup.h>
+-#include <syslib/gen550.h>
  
-       /* reset the counters for statistics on the current adapter */
--      IBM_DS(host_index).scbs = 0;
--      IBM_DS(host_index).long_scbs = 0;
--      IBM_DS(host_index).total_accesses = 0;
--      IBM_DS(host_index).total_interrupts = 0;
--      IBM_DS(host_index).dynamical_assignments = 0;
--      memset(IBM_DS(host_index).ldn_access, 0x0, sizeof(IBM_DS(host_index).ldn_access));
--      memset(IBM_DS(host_index).ldn_read_access, 0x0, sizeof(IBM_DS(host_index).ldn_read_access));
--      memset(IBM_DS(host_index).ldn_write_access, 0x0, sizeof(IBM_DS(host_index).ldn_write_access));
--      memset(IBM_DS(host_index).ldn_inquiry_access, 0x0, sizeof(IBM_DS(host_index).ldn_inquiry_access));
--      memset(IBM_DS(host_index).ldn_modeselect_access, 0x0, sizeof(IBM_DS(host_index).ldn_modeselect_access));
--      memset(IBM_DS(host_index).ldn_assignments, 0x0, sizeof(IBM_DS(host_index).ldn_assignments));
-+      IBM_DS(shpnt).scbs = 0;
-+      IBM_DS(shpnt).long_scbs = 0;
-+      IBM_DS(shpnt).total_accesses = 0;
-+      IBM_DS(shpnt).total_interrupts = 0;
-+      IBM_DS(shpnt).dynamical_assignments = 0;
-+      memset(IBM_DS(shpnt).ldn_access, 0x0, sizeof(IBM_DS(shpnt).ldn_access));
-+      memset(IBM_DS(shpnt).ldn_read_access, 0x0, sizeof(IBM_DS(shpnt).ldn_read_access));
-+      memset(IBM_DS(shpnt).ldn_write_access, 0x0, sizeof(IBM_DS(shpnt).ldn_write_access));
-+      memset(IBM_DS(shpnt).ldn_inquiry_access, 0x0, sizeof(IBM_DS(shpnt).ldn_inquiry_access));
-+      memset(IBM_DS(shpnt).ldn_modeselect_access, 0x0, sizeof(IBM_DS(shpnt).ldn_modeselect_access));
-+      memset(IBM_DS(shpnt).ldn_assignments, 0x0, sizeof(IBM_DS(shpnt).ldn_assignments));
-       probe_display(0);
-       return;
+ extern void abort(void);
+@@ -70,11 +69,11 @@
+       mtspr(SPRN_TCR, TCR_DIE);
  }
  
--static int device_exists(int host_index, int ldn, int *block_length, int *device_type)
-+static int device_exists(struct Scsi_Host *shpnt, int ldn, int *block_length, int *device_type)
+-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_KGDB_8250)
++#ifdef CONFIG_SERIAL_8250
+ void __init
+ mpc85xx_early_serial_map(void)
  {
-       unsigned char *buf;
-       /* if no valid device found, return immediately with 0 */
--      if (!(device_inquiry(host_index, ldn)))
-+      if (!(device_inquiry(shpnt, ldn)))
-               return 0;
--      buf = (unsigned char *) (&(ld(host_index)[ldn].buf));
-+      buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
-       if (*buf == TYPE_ROM) {
-               *device_type = TYPE_ROM;
-               *block_length = 2048;   /* (standard blocksize for yellow-/red-book) */
-@@ -1349,7 +1359,7 @@
-       }
-       if (*buf == TYPE_DISK) {
-               *device_type = TYPE_DISK;
--              if (read_capacity(host_index, ldn)) {
-+              if (read_capacity(shpnt, ldn)) {
-                       *block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24);
-                       return 1;
-               } else
-@@ -1357,7 +1367,7 @@
-       }
-       if (*buf == TYPE_MOD) {
-               *device_type = TYPE_MOD;
--              if (read_capacity(host_index, ldn)) {
-+              if (read_capacity(shpnt, ldn)) {
-                       *block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24);
-                       return 1;
-               } else
-@@ -1430,6 +1440,9 @@
-       return;
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       struct uart_port serial_req;
+ #endif
+       struct plat_serial8250_port *pdata;
+@@ -86,40 +85,27 @@
+       pdata[0].mapbase += binfo->bi_immr_base;
+       pdata[0].membase = ioremap(pdata[0].mapbase, MPC85xx_UART0_SIZE);
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       memset(&serial_req, 0, sizeof (serial_req));
+       serial_req.iotype = UPIO_MEM;
+       serial_req.mapbase = pdata[0].mapbase;
+       serial_req.membase = pdata[0].membase;
+       serial_req.regshift = 0;
+-      serial_req.irq = pdata[0].irq;
+-      serial_req.flags = pdata[0].flags;
+-      serial_req.uartclk = pdata[0].uartclk;
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
+       gen550_init(0, &serial_req);
+ #endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(0, &serial_req);
+-#endif
+-#endif
+       pdata[1].uartclk = binfo->bi_busfreq;
+       pdata[1].mapbase += binfo->bi_immr_base;
+       pdata[1].membase = ioremap(pdata[1].mapbase, MPC85xx_UART0_SIZE);
+-#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB_8250)
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+       /* Assume gen550_init() doesn't modify serial_req */
+       serial_req.mapbase = pdata[1].mapbase;
+       serial_req.membase = pdata[1].membase;
+-#ifdef CONFIG_SERIAL_TEXT_DEBUG
+       gen550_init(1, &serial_req);
+ #endif
+-#ifdef CONFIG_KGDB_8250
+-      kgdb8250_add_port(1, &serial_req);
+-#endif
+-#endif
  }
+ #endif
  
-+#if 0
-+ FIXME NEED TO MOVE TO SYSFS
+@@ -377,3 +363,5 @@
+       return;
+ }
+ #endif /* CONFIG_PCI */
 +
- static int ibmmca_getinfo(char *buf, int slot, void *dev_id)
- {
-       struct Scsi_Host *shpnt;
-@@ -1480,58 +1493,34 @@
++
+diff -Nurb linux-2.6.22-590/arch/s390/appldata/appldata_net_sum.c linux-2.6.22-570/arch/s390/appldata/appldata_net_sum.c
+--- linux-2.6.22-590/arch/s390/appldata/appldata_net_sum.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/s390/appldata/appldata_net_sum.c     2007-07-08 19:32:17.000000000 -0400
+@@ -16,7 +16,6 @@
+ #include <linux/errno.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/netdevice.h>
+-#include <net/net_namespace.h>
  
-       return len;
- }
-+#endif
+ #include "appldata.h"
  
--int ibmmca_detect(struct scsi_host_template * scsi_template)
-+static struct scsi_host_template ibmmca_driver_template = {
-+          .proc_name      = "ibmmca",
-+        .proc_info      = ibmmca_proc_info,
-+          .name           = "IBM SCSI-Subsystem",
-+          .queuecommand   = ibmmca_queuecommand,
-+        .eh_abort_handler = ibmmca_abort,
-+        .eh_host_reset_handler = ibmmca_host_reset,
-+          .bios_param     = ibmmca_biosparam,
-+          .can_queue      = 16,
-+          .this_id        = 7,
-+          .sg_tablesize   = 16,
-+          .cmd_per_lun    = 1,
-+          .use_clustering = ENABLE_CLUSTERING,
-+};
+@@ -108,7 +107,7 @@
+       tx_dropped = 0;
+       collisions = 0;
+       read_lock(&dev_base_lock);
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               stats = dev->get_stats(dev);
+               rx_packets += stats->rx_packets;
+               tx_packets += stats->tx_packets;
+diff -Nurb linux-2.6.22-590/arch/s390/kernel/ipl.c linux-2.6.22-570/arch/s390/kernel/ipl.c
+--- linux-2.6.22-590/arch/s390/kernel/ipl.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/s390/kernel/ipl.c    2007-07-08 19:32:17.000000000 -0400
+@@ -314,6 +314,7 @@
+       .attr = {
+               .name = "binary_parameter",
+               .mode = S_IRUGO,
++              .owner = THIS_MODULE,
+       },
+       .size = PAGE_SIZE,
+       .read = &ipl_parameter_read,
+@@ -337,6 +338,7 @@
+       .attr = {
+               .name = "scp_data",
+               .mode = S_IRUGO,
++              .owner = THIS_MODULE,
+       },
+       .size = PAGE_SIZE,
+       .read = &ipl_scp_data_read,
+diff -Nurb linux-2.6.22-590/arch/sh/Kconfig.debug linux-2.6.22-570/arch/sh/Kconfig.debug
+--- linux-2.6.22-590/arch/sh/Kconfig.debug     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/sh/Kconfig.debug     2007-07-08 19:32:17.000000000 -0400
+@@ -78,4 +78,82 @@
+         on the VM subsystem for higher order allocations. This option
+         will also use IRQ stacks to compensate for the reduced stackspace.
++config SH_KGDB
++      bool "Include KGDB kernel debugger"
++      select FRAME_POINTER
++      select DEBUG_INFO
++      help
++        Include in-kernel hooks for kgdb, the Linux kernel source level
++        debugger.  See <http://kgdb.sourceforge.net/> for more information.
++        Unless you are intending to debug the kernel, say N here.
 +
-+static int ibmmca_probe(struct device *dev)
- {
-       struct Scsi_Host *shpnt;
--      int port, id, i, j, k, slot;
--      int devices_on_irq_11 = 0;
--      int devices_on_irq_14 = 0;
--      int IRQ14_registered = 0;
--      int IRQ11_registered = 0;
++menu "KGDB configuration options"
++      depends on SH_KGDB
++
++config MORE_COMPILE_OPTIONS
++      bool "Add any additional compile options"
++      help
++        If you want to add additional CFLAGS to the kernel build, enable this
++        option and then enter what you would like to add in the next question.
++        Note however that -g is already appended with the selection of KGDB.
++
++config COMPILE_OPTIONS
++      string "Additional compile arguments"
++      depends on MORE_COMPILE_OPTIONS
++
++config KGDB_NMI
++      bool "Enter KGDB on NMI"
++      default n
++
++config SH_KGDB_CONSOLE
++      bool "Console messages through GDB"
++      depends on !SERIAL_SH_SCI_CONSOLE
++      select SERIAL_CORE_CONSOLE
++      default n
++
++config KGDB_SYSRQ
++      bool "Allow SysRq 'G' to enter KGDB"
++      default y
++
++comment "Serial port setup"
++
++config KGDB_DEFPORT
++      int "Port number (ttySCn)"
++      default "1"
++
++config KGDB_DEFBAUD
++      int "Baud rate"
++      default "115200"
++
++choice
++      prompt "Parity"
++      depends on SH_KGDB
++      default KGDB_DEFPARITY_N
++
++config KGDB_DEFPARITY_N
++      bool "None"
++
++config KGDB_DEFPARITY_E
++      bool "Even"
++
++config KGDB_DEFPARITY_O
++      bool "Odd"
++
++endchoice
++
++choice
++      prompt "Data bits"
++      depends on SH_KGDB
++      default KGDB_DEFBITS_8
++
++config KGDB_DEFBITS_8
++      bool "8"
++
++config KGDB_DEFBITS_7
++      bool "7"
++
++endchoice
++
++endmenu
++
+ endmenu
+diff -Nurb linux-2.6.22-590/arch/sh/kernel/Makefile linux-2.6.22-570/arch/sh/kernel/Makefile
+--- linux-2.6.22-590/arch/sh/kernel/Makefile   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/sh/kernel/Makefile   2007-07-08 19:32:17.000000000 -0400
+@@ -15,7 +15,7 @@
+ obj-$(CONFIG_SMP)             += smp.o
+ obj-$(CONFIG_CF_ENABLER)      += cf-enabler.o
+ obj-$(CONFIG_SH_STANDARD_BIOS)        += sh_bios.o
+-obj-$(CONFIG_KGDB)            += kgdb.o kgdb-jmp.o
++obj-$(CONFIG_SH_KGDB)         += kgdb_stub.o kgdb_jmp.o
+ obj-$(CONFIG_SH_CPU_FREQ)     += cpufreq.o
+ obj-$(CONFIG_MODULES)         += module.o
+ obj-$(CONFIG_EARLY_PRINTK)    += early_printk.o
+diff -Nurb linux-2.6.22-590/arch/sh/kernel/cpu/sh3/ex.S linux-2.6.22-570/arch/sh/kernel/cpu/sh3/ex.S
+--- linux-2.6.22-590/arch/sh/kernel/cpu/sh3/ex.S       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/sh/kernel/cpu/sh3/ex.S       2007-07-08 19:32:17.000000000 -0400
+@@ -45,7 +45,7 @@
+       .long   exception_error ! reserved_instruction (filled by trap_init) /* 180 */
+       .long   exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
+ ENTRY(nmi_slot)
+-#if defined (CONFIG_KGDB)
++#if defined (CONFIG_KGDB_NMI)
+       .long   debug_enter     /* 1C0 */       ! Allow trap to debugger
+ #else
+       .long   exception_none  /* 1C0 */       ! Not implemented yet
+diff -Nurb linux-2.6.22-590/arch/sh/kernel/kgdb-jmp.S linux-2.6.22-570/arch/sh/kernel/kgdb-jmp.S
+--- linux-2.6.22-590/arch/sh/kernel/kgdb-jmp.S 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/sh/kernel/kgdb-jmp.S 1969-12-31 19:00:00.000000000 -0500
+@@ -1,32 +0,0 @@
+-#include <linux/linkage.h>
+-
+-ENTRY(kgdb_fault_setjmp)
+-      add     #(9*4), r4
+-      sts.l   pr, @-r4
+-      mov.l   r15, @-r4
+-      mov.l   r14, @-r4
+-      mov.l   r13, @-r4
+-      mov.l   r12, @-r4
+-      mov.l   r11, @-r4
+-      mov.l   r10, @-r4
+-      mov.l   r9, @-r4
+-      mov.l   r8, @-r4
+-      rts
+-       mov    #0, r0
+-
+-ENTRY(kgdb_fault_longjmp)
+-      mov.l   @r4+, r8
+-      mov.l   @r4+, r9
+-      mov.l   @r4+, r10
+-      mov.l   @r4+, r11
+-      mov.l   @r4+, r12
+-      mov.l   @r4+, r13
+-      mov.l   @r4+, r14
+-      mov.l   @r4+, r15
+-      lds.l   @r4+, pr
+-      mov     r5, r0
+-      tst     r0, r0
+-      bf      1f
+-      mov     #1, r0
+-1:    rts
+-       nop
+diff -Nurb linux-2.6.22-590/arch/sh/kernel/kgdb.c linux-2.6.22-570/arch/sh/kernel/kgdb.c
+--- linux-2.6.22-590/arch/sh/kernel/kgdb.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/sh/kernel/kgdb.c     1969-12-31 19:00:00.000000000 -0500
+@@ -1,363 +0,0 @@
+-/*
+- * arch/sh/kernel/kgdb.c
+- *
+- * Contains SH-specific low-level support for KGDB.
+- *
+- * Containes extracts from code by Glenn Engel, Jim Kingdon,
+- * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
+- * Amit S. Kale <akale@veritas.com>,  William Gatliff <bgat@open-widgets.com>,
+- * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>,
+- * Henry Bell <henry.bell@st.com> and Jeremy Siegel <jsiegel@mvista.com>
+- *
+- * Maintainer: Tom Rini <trini@kernel.crashing.org>
+- *
+- * 2004 (c) MontaVista Software, Inc. This file is licensed under
+- * the terms of the GNU General Public License version 2. This program
+- * is licensed "as is" without any warranty of any kind, whether express
+- * or implied.
+- */
+-
+-#include <linux/string.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/spinlock.h>
+-#include <linux/delay.h>
+-#include <linux/linkage.h>
+-#include <linux/init.h>
+-#include <linux/kgdb.h>
 -
--      found = 0;              /* make absolutely sure, that found is set to 0 */
-+      int port, id, i, j, k, irq, enabled, ret = -EINVAL;
-+      struct mca_device *mca_dev = to_mca_device(dev);
-+      const char *description = ibmmca_description[mca_dev->index];
-       /* First of all, print the version number of the driver. This is
-        * important to allow better user bugreports in case of already
-        * having problems with the MCA_bus probing. */
-       printk(KERN_INFO "IBM MCA SCSI: Version %s\n", IBMMCA_SCSI_DRIVER_VERSION);
--      /* if this is not MCA machine, return "nothing found" */
--      if (!MCA_bus) {
--              printk(KERN_INFO "IBM MCA SCSI:  No Microchannel-bus present --> Aborting.\n" "              This machine does not have any IBM MCA-bus\n" "                 or the MCA-Kernel-support is not enabled!\n");
--              return 0;
--      }
+-#include <asm/system.h>
+-#include <asm/current.h>
+-#include <asm/signal.h>
+-#include <asm/pgtable.h>
+-#include <asm/ptrace.h>
 -
--#ifdef MODULE
--      /* If the driver is run as module, read from conf.modules or cmd-line */
--      if (boot_options)
--              option_setup(boot_options);
+-extern void per_cpu_trap_init(void);
+-extern atomic_t cpu_doing_single_step;
+-
+-/* Function pointers for linkage */
+-static struct kgdb_regs trap_registers;
+-
+-/* Globals. */
+-char in_nmi;                  /* Set during NMI to prevent reentry */
+-
+-/* TRA differs sh3/4 */
+-#if defined(CONFIG_CPU_SH3)
+-#define TRA 0xffffffd0
+-#elif defined(CONFIG_CPU_SH4)
+-#define TRA 0xff000020
 -#endif
 -
--      /* get interrupt request level */
--      if (request_irq(IM_IRQ, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts)) {
--              printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ);
--              return 0;
--      } else
--              IRQ14_registered++;
--
--      /* if ibmmcascsi setup option was passed to kernel, return "found" */
--      for (i = 0; i < IM_MAX_HOSTS; i++)
--              if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8) {
--                      printk("IBM MCA SCSI: forced detected SCSI Adapter, io=0x%x, scsi id=%d.\n", io_port[i], scsi_id[i]);
--                      if ((shpnt = ibmmca_register(scsi_template, io_port[i], scsi_id[i], FORCED_DETECTION, "forced detected SCSI Adapter"))) {
--                              for (k = 2; k < 7; k++)
--                                      ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = 0;
--                              ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = FORCED_DETECTION;
--                              mca_set_adapter_name(MCA_INTEGSCSI, "forced detected SCSI Adapter");
--                              mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
--                              mca_mark_as_used(MCA_INTEGSCSI);
--                              devices_on_irq_14++;
--                      }
+-/* Macros for single step instruction identification */
+-#define OPCODE_BT(op)         (((op) & 0xff00) == 0x8900)
+-#define OPCODE_BF(op)         (((op) & 0xff00) == 0x8b00)
+-#define OPCODE_BTF_DISP(op)   (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \
+-                            (((op) & 0x7f ) << 1))
+-#define OPCODE_BFS(op)        (((op) & 0xff00) == 0x8f00)
+-#define OPCODE_BTS(op)        (((op) & 0xff00) == 0x8d00)
+-#define OPCODE_BRA(op)        (((op) & 0xf000) == 0xa000)
+-#define OPCODE_BRA_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
+-                            (((op) & 0x7ff) << 1))
+-#define OPCODE_BRAF(op)       (((op) & 0xf0ff) == 0x0023)
+-#define OPCODE_BRAF_REG(op)   (((op) & 0x0f00) >> 8)
+-#define OPCODE_BSR(op)        (((op) & 0xf000) == 0xb000)
+-#define OPCODE_BSR_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
+-                            (((op) & 0x7ff) << 1))
+-#define OPCODE_BSRF(op)       (((op) & 0xf0ff) == 0x0003)
+-#define OPCODE_BSRF_REG(op)   (((op) >> 8) & 0xf)
+-#define OPCODE_JMP(op)        (((op) & 0xf0ff) == 0x402b)
+-#define OPCODE_JMP_REG(op)    (((op) >> 8) & 0xf)
+-#define OPCODE_JSR(op)        (((op) & 0xf0ff) == 0x400b)
+-#define OPCODE_JSR_REG(op)    (((op) >> 8) & 0xf)
+-#define OPCODE_RTS(op)        ((op) == 0xb)
+-#define OPCODE_RTE(op)        ((op) == 0x2b)
+-
+-#define SR_T_BIT_MASK           0x1
+-#define STEP_OPCODE             0xc320
+-#define BIOS_CALL_TRAP          0x3f
+-
+-/* Exception codes as per SH-4 core manual */
+-#define ADDRESS_ERROR_LOAD_VEC   7
+-#define ADDRESS_ERROR_STORE_VEC  8
+-#define TRAP_VEC                 11
+-#define INVALID_INSN_VEC         12
+-#define INVALID_SLOT_VEC         13
+-#define NMI_VEC                  14
+-#define SERIAL_BREAK_VEC         58
+-
+-/* Misc static */
+-static int stepped_address;
+-static short stepped_opcode;
+-
+-/* Translate SH-3/4 exception numbers to unix-like signal values */
+-static int compute_signal(const int excep_code)
+-{
+-      switch (excep_code) {
+-      case INVALID_INSN_VEC:
+-      case INVALID_SLOT_VEC:
+-              return SIGILL;
+-      case ADDRESS_ERROR_LOAD_VEC:
+-      case ADDRESS_ERROR_STORE_VEC:
+-              return SIGSEGV;
+-      case SERIAL_BREAK_VEC:
+-      case NMI_VEC:
+-              return SIGINT;
+-      default:
+-              /* Act like it was a break/trap. */
+-              return SIGTRAP;
+-      }
+-}
+-
+-/*
+- * Translate the registers of the system into the format that GDB wants.  Since
+- * we use a local structure to store things, instead of getting them out
+- * of pt_regs, we can just do a memcpy.
+- */
+-void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *ign)
+-{
+-      memcpy(gdb_regs, &trap_registers, sizeof(trap_registers));
+-}
+-
+-/*
+- * On SH we save: r1 (prev->thread.sp) r2 (prev->thread.pc) r4 (prev) r5 (next)
+- * r6 (next->thread.sp) r7 (next->thread.pc)
+- */
+-void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+-{
+-      int count;
+-
+-      for (count = 0; count < 16; count++)
+-              *(gdb_regs++) = 0;
+-      *(gdb_regs++) = p->thread.pc;
+-      *(gdb_regs++) = 0;
+-      *(gdb_regs++) = 0;
+-      *(gdb_regs++) = 0;
+-      *(gdb_regs++) = 0;
+-      *(gdb_regs++) = 0;
+-      *(gdb_regs++) = 0;
+-}
+-
+-/*
+- * Translate the registers values that GDB has given us back into the
+- * format of the system.  See the comment above about memcpy.
+- */
+-void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *ign)
+-{
+-      memcpy(&trap_registers, gdb_regs, sizeof(trap_registers));
+-}
+-
+-/* Calculate the new address for after a step */
+-static short *get_step_address(void)
+-{
+-      short op = *(short *)trap_registers.pc;
+-      long addr;
+-
+-      /* BT */
+-      if (OPCODE_BT(op)) {
+-              if (trap_registers.sr & SR_T_BIT_MASK)
+-                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+-              else
+-                      addr = trap_registers.pc + 2;
+-      }
+-
+-      /* BTS */
+-      else if (OPCODE_BTS(op)) {
+-              if (trap_registers.sr & SR_T_BIT_MASK)
+-                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+-              else
+-                      addr = trap_registers.pc + 4;   /* Not in delay slot */
+-      }
+-
+-      /* BF */
+-      else if (OPCODE_BF(op)) {
+-              if (!(trap_registers.sr & SR_T_BIT_MASK))
+-                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+-              else
+-                      addr = trap_registers.pc + 2;
+-      }
+-
+-      /* BFS */
+-      else if (OPCODE_BFS(op)) {
+-              if (!(trap_registers.sr & SR_T_BIT_MASK))
+-                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+-              else
+-                      addr = trap_registers.pc + 4;   /* Not in delay slot */
+-      }
+-
+-      /* BRA */
+-      else if (OPCODE_BRA(op))
+-              addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op);
+-
+-      /* BRAF */
+-      else if (OPCODE_BRAF(op))
+-              addr = trap_registers.pc + 4
+-                  + trap_registers.regs[OPCODE_BRAF_REG(op)];
+-
+-      /* BSR */
+-      else if (OPCODE_BSR(op))
+-              addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op);
+-
+-      /* BSRF */
+-      else if (OPCODE_BSRF(op))
+-              addr = trap_registers.pc + 4
+-                  + trap_registers.regs[OPCODE_BSRF_REG(op)];
+-
+-      /* JMP */
+-      else if (OPCODE_JMP(op))
+-              addr = trap_registers.regs[OPCODE_JMP_REG(op)];
+-
+-      /* JSR */
+-      else if (OPCODE_JSR(op))
+-              addr = trap_registers.regs[OPCODE_JSR_REG(op)];
+-
+-      /* RTS */
+-      else if (OPCODE_RTS(op))
+-              addr = trap_registers.pr;
+-
+-      /* RTE */
+-      else if (OPCODE_RTE(op))
+-              addr = trap_registers.regs[15];
+-
+-      /* Other */
+-      else
+-              addr = trap_registers.pc + 2;
+-
+-      kgdb_flush_icache_range(addr, addr + 2);
+-      return (short *)addr;
+-}
+-
+-/* The command loop, read and act on requests */
+-int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
+-                             char *remcom_in_buffer, char *remcom_out_buffer,
+-                             struct pt_regs *ign)
+-{
+-      unsigned long addr;
+-      char *ptr = &remcom_in_buffer[1];
+-
+-      /* Examine first char of buffer to see what we need to do */
+-      switch (remcom_in_buffer[0]) {
+-      case 'c':               /* Continue at address AA..AA (optional) */
+-      case 's':               /* Step one instruction from AA..AA */
+-              /* Try to read optional parameter, PC unchanged if none */
+-              if (kgdb_hex2long(&ptr, &addr))
+-                      trap_registers.pc = addr;
+-
+-              atomic_set(&cpu_doing_single_step, -1);
+-              if (remcom_in_buffer[0] == 's') {
+-                      /* Replace the instruction immediately after the
+-                       * current instruction (i.e. next in the expected
+-                       * flow of control) with a trap instruction, so that
+-                       * returning will cause only a single instruction to
+-                       * be executed. Note that this model is slightly
+-                       * broken for instructions with delay slots
+-                       * (e.g. B[TF]S, BSR, BRA etc), where both the branch
+-                       * and the instruction in the delay slot will be
+-                       * executed.
+-                       */
+-                      /* Determine where the target instruction will send
+-                       * us to */
+-                      unsigned short *next_addr = get_step_address();
+-                      stepped_address = (int)next_addr;
+-
+-                      /* Replace it */
+-                      stepped_opcode = *(short *)next_addr;
+-                      *next_addr = STEP_OPCODE;
+-
+-                      /* Flush and return */
+-                      kgdb_flush_icache_range((long)next_addr,
+-                                              (long)next_addr + 2);
+-                      if (kgdb_contthread)
+-                              atomic_set(&cpu_doing_single_step,
+-                                         smp_processor_id());
 -              }
--      if (found)
--              return found;
+-              return 0;
+-      }
+-      return -1;
+-}
 -
-       /* The POS2-register of all PS/2 model SCSI-subsystems has the following
-        * interpretation of bits:
-        *                             Bit 7 - 4 : Chip Revision ID (Release)
-@@ -1558,7 +1547,14 @@
-       /* first look for the IBM SCSI integrated subsystem on the motherboard */
-       for (j = 0; j < 8; j++) /* read the pos-information */
--              pos[j] = mca_read_stored_pos(MCA_INTEGSCSI, j);
-+              pos[j] = mca_device_read_pos(mca_dev, j);
-+      id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */
-+      enabled = (pos[2] &0x01);
-+      if (!enabled) {
-+              printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
-+              printk(KERN_WARNING "              SCSI-operations may not work.\n");
+-/*
+- * When an exception has occured, we are called.  We need to set things
+- * up so that we can call kgdb_handle_exception to handle requests from
+- * the remote GDB.
+- */
+-void kgdb_exception_handler(struct pt_regs *regs)
+-{
+-      int excep_code, vbr_val;
+-      int count;
+-
+-      /* Copy kernel regs (from stack) */
+-      for (count = 0; count < 16; count++)
+-              trap_registers.regs[count] = regs->regs[count];
+-      trap_registers.pc = regs->pc;
+-      trap_registers.pr = regs->pr;
+-      trap_registers.sr = regs->sr;
+-      trap_registers.gbr = regs->gbr;
+-      trap_registers.mach = regs->mach;
+-      trap_registers.macl = regs->macl;
+-
+-      __asm__ __volatile__("stc vbr, %0":"=r"(vbr_val));
+-      trap_registers.vbr = vbr_val;
+-
+-      /* Get the execption code. */
+-      __asm__ __volatile__("stc r2_bank, %0":"=r"(excep_code));
+-
+-      excep_code >>= 5;
+-
+-      /* If we got an NMI, and KGDB is not yet initialized, call
+-       * breakpoint() to try and initialize everything for us. */
+-      if (excep_code == NMI_VEC && !kgdb_initialized) {
+-              breakpoint();
+-              return;
+-      }
+-
+-      /* TRAP_VEC exception indicates a software trap inserted in place of
+-       * code by GDB so back up PC by one instruction, as this instruction
+-       * will later be replaced by its original one.  Do NOT do this for
+-       * trap 0xff, since that indicates a compiled-in breakpoint which
+-       * will not be replaced (and we would retake the trap forever) */
+-      if (excep_code == TRAP_VEC &&
+-          (*(volatile unsigned long *)TRA != (0xff << 2)))
+-              trap_registers.pc -= 2;
+-
+-      /* If we have been single-stepping, put back the old instruction.
+-       * We use stepped_address in case we have stopped more than one
+-       * instruction away. */
+-      if (stepped_opcode != 0) {
+-              *(short *)stepped_address = stepped_opcode;
+-              kgdb_flush_icache_range(stepped_address, stepped_address + 2);
+-      }
+-      stepped_opcode = 0;
+-
+-      /* Call the stub to do the processing.  Note that not everything we
+-       * need to send back and forth lives in pt_regs. */
+-      kgdb_handle_exception(excep_code, compute_signal(excep_code), 0, regs);
+-
+-      /* Copy back the (maybe modified) registers */
+-      for (count = 0; count < 16; count++)
+-              regs->regs[count] = trap_registers.regs[count];
+-      regs->pc = trap_registers.pc;
+-      regs->pr = trap_registers.pr;
+-      regs->sr = trap_registers.sr;
+-      regs->gbr = trap_registers.gbr;
+-      regs->mach = trap_registers.mach;
+-      regs->macl = trap_registers.macl;
+-
+-      vbr_val = trap_registers.vbr;
+-      __asm__ __volatile__("ldc %0, vbr": :"r"(vbr_val));
+-}
+-
+-int __init kgdb_arch_init(void)
+-{
+-      per_cpu_trap_init();
+-
+-      return 0;
+-}
+-
+-struct kgdb_arch arch_kgdb_ops = {
+-#ifdef CONFIG_CPU_LITTLE_ENDIAN
+-      .gdb_bpt_instr = {0xff, 0xc3},
+-#else
+-      .gdb_bpt_instr = {0xc3, 0xff},
+-#endif
+-};
+diff -Nurb linux-2.6.22-590/arch/sh/kernel/kgdb_jmp.S linux-2.6.22-570/arch/sh/kernel/kgdb_jmp.S
+--- linux-2.6.22-590/arch/sh/kernel/kgdb_jmp.S 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/sh/kernel/kgdb_jmp.S 2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,33 @@
++#include <linux/linkage.h>
++
++ENTRY(setjmp)
++      add     #(9*4), r4
++      sts.l   pr, @-r4
++      mov.l   r15, @-r4
++      mov.l   r14, @-r4
++      mov.l   r13, @-r4
++      mov.l   r12, @-r4
++      mov.l   r11, @-r4
++      mov.l   r10, @-r4
++      mov.l   r9, @-r4
++      mov.l   r8, @-r4
++      rts
++       mov    #0, r0
++
++ENTRY(longjmp)
++      mov.l   @r4+, r8
++      mov.l   @r4+, r9
++      mov.l   @r4+, r10
++      mov.l   @r4+, r11
++      mov.l   @r4+, r12
++      mov.l   @r4+, r13
++      mov.l   @r4+, r14
++      mov.l   @r4+, r15
++      lds.l   @r4+, pr
++      mov     r5, r0
++      tst     r0, r0
++      bf      1f
++      mov     #1, r0  ! in case val==0
++1:    rts
++       nop
++
+diff -Nurb linux-2.6.22-590/arch/sh/kernel/kgdb_stub.c linux-2.6.22-570/arch/sh/kernel/kgdb_stub.c
+--- linux-2.6.22-590/arch/sh/kernel/kgdb_stub.c        1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/arch/sh/kernel/kgdb_stub.c        2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,1093 @@
++/*
++ * May be copied or modified under the terms of the GNU General Public
++ * License.  See linux/COPYING for more information.
++ *
++ * Contains extracts from code by Glenn Engel, Jim Kingdon,
++ * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
++ * Amit S. Kale <akale@veritas.com>,  William Gatliff <bgat@open-widgets.com>,
++ * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>.
++ *
++ * This version by Henry Bell <henry.bell@st.com>
++ * Minor modifications by Jeremy Siegel <jsiegel@mvista.com>
++ *
++ * Contains low-level support for remote debug using GDB.
++ *
++ * To enable debugger support, two things need to happen. A call to
++ * set_debug_traps() is necessary in order to allow any breakpoints
++ * or error conditions to be properly intercepted and reported to gdb.
++ * A breakpoint also needs to be generated to begin communication.  This
++ * is most easily accomplished by a call to breakpoint() which does
++ * a trapa if the initialisation phase has been successfully completed.
++ *
++ * In this case, set_debug_traps() is not used to "take over" exceptions;
++ * other kernel code is modified instead to enter the kgdb functions here
++ * when appropriate (see entry.S for breakpoint traps and NMI interrupts,
++ * see traps.c for kernel error exceptions).
++ *
++ * The following gdb commands are supported:
++ *
++ *    Command       Function                               Return value
++ *
++ *    g             return the value of the CPU registers  hex data or ENN
++ *    G             set the value of the CPU registers     OK or ENN
++ *
++ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
++ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
++ *    XAA..AA,LLLL: Same, but data is binary (not hex)     OK or ENN
++ *
++ *    c             Resume at current address              SNN   ( signal NN)
++ *    cAA..AA       Continue at address AA..AA             SNN
++ *    CNN;          Resume at current address with signal  SNN
++ *    CNN;AA..AA    Resume at address AA..AA with signal   SNN
++ *
++ *    s             Step one instruction                   SNN
++ *    sAA..AA       Step one instruction from AA..AA       SNN
++ *    SNN;          Step one instruction with signal       SNN
++ *    SNNAA..AA     Step one instruction from AA..AA w/NN  SNN
++ *
++ *    k             kill (Detach GDB)
++ *
++ *    d             Toggle debug flag
++ *    D             Detach GDB
++ *
++ *    Hct           Set thread t for operations,           OK or ENN
++ *                  c = 'c' (step, cont), c = 'g' (other
++ *                  operations)
++ *
++ *    qC            Query current thread ID                QCpid
++ *    qfThreadInfo  Get list of current threads (first)    m<id>
++ *    qsThreadInfo   "    "  "     "      "   (subsequent)
++ *    qOffsets      Get section offsets                  Text=x;Data=y;Bss=z
++ *
++ *    TXX           Find if thread XX is alive             OK or ENN
++ *    ?             What was the last sigval ?             SNN   (signal NN)
++ *    O             Output to GDB console
++ *
++ * Remote communication protocol.
++ *
++ *    A debug packet whose contents are <data> is encapsulated for
++ *    transmission in the form:
++ *
++ *       $ <data> # CSUM1 CSUM2
++ *
++ *       <data> must be ASCII alphanumeric and cannot include characters
++ *       '$' or '#'.  If <data> starts with two characters followed by
++ *       ':', then the existing stubs interpret this as a sequence number.
++ *
++ *       CSUM1 and CSUM2 are ascii hex representation of an 8-bit
++ *       checksum of <data>, the most significant nibble is sent first.
++ *       the hex digits 0-9,a-f are used.
++ *
++ *    Receiver responds with:
++ *
++ *       +       - if CSUM is correct and ready for next packet
++ *       -       - if CSUM is incorrect
++ *
++ * Responses can be run-length encoded to save space.  A '*' means that
++ * the next character is an ASCII encoding giving a repeat count which
++ * stands for that many repetitions of the character preceding the '*'.
++ * The encoding is n+29, yielding a printable character where n >=3
++ * (which is where RLE starts to win).  Don't use an n > 126.
++ *
++ * So "0* " means the same as "0000".
++ */
++
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/smp.h>
++#include <linux/spinlock.h>
++#include <linux/delay.h>
++#include <linux/linkage.h>
++#include <linux/init.h>
++#include <linux/console.h>
++#include <linux/sysrq.h>
++#include <asm/system.h>
++#include <asm/cacheflush.h>
++#include <asm/current.h>
++#include <asm/signal.h>
++#include <asm/pgtable.h>
++#include <asm/ptrace.h>
++#include <asm/kgdb.h>
++#include <asm/io.h>
++
++/* Function pointers for linkage */
++kgdb_debug_hook_t *kgdb_debug_hook;
++kgdb_bus_error_hook_t *kgdb_bus_err_hook;
++
++int (*kgdb_getchar)(void);
++void (*kgdb_putchar)(int);
++
++static void put_debug_char(int c)
++{
++      if (!kgdb_putchar)
++              return;
++      (*kgdb_putchar)(c);
++}
++static int get_debug_char(void)
++{
++      if (!kgdb_getchar)
++              return -1;
++      return (*kgdb_getchar)();
++}
++
++/* Num chars in in/out bound buffers, register packets need NUMREGBYTES * 2 */
++#define BUFMAX 1024
++#define NUMREGBYTES (MAXREG*4)
++#define OUTBUFMAX (NUMREGBYTES*2+512)
++
++enum regs {
++      R0 = 0, R1,  R2,  R3,   R4,   R5,  R6, R7,
++      R8, R9, R10, R11, R12,  R13,  R14, R15,
++      PC, PR, GBR, VBR, MACH, MACL, SR,
++      /*  */
++      MAXREG
++};
++
++static unsigned int registers[MAXREG];
++struct kgdb_regs trap_registers;
++
++char kgdb_in_gdb_mode;
++char in_nmi;                  /* Set during NMI to prevent reentry */
++int kgdb_nofault;             /* Boolean to ignore bus errs (i.e. in GDB) */
++int kgdb_enabled = 1;         /* Default to enabled, cmdline can disable */
++
++/* Exposed for user access */
++struct task_struct *kgdb_current;
++unsigned int kgdb_g_imask;
++int kgdb_trapa_val;
++int kgdb_excode;
++
++/* Default values for SCI (can override via kernel args in setup.c) */
++#ifndef CONFIG_KGDB_DEFPORT
++#define CONFIG_KGDB_DEFPORT 1
++#endif
++
++#ifndef CONFIG_KGDB_DEFBAUD
++#define CONFIG_KGDB_DEFBAUD 115200
++#endif
++
++#if defined(CONFIG_KGDB_DEFPARITY_E)
++#define CONFIG_KGDB_DEFPARITY 'E'
++#elif defined(CONFIG_KGDB_DEFPARITY_O)
++#define CONFIG_KGDB_DEFPARITY 'O'
++#else /* CONFIG_KGDB_DEFPARITY_N */
++#define CONFIG_KGDB_DEFPARITY 'N'
++#endif
++
++#ifdef CONFIG_KGDB_DEFBITS_7
++#define CONFIG_KGDB_DEFBITS '7'
++#else /* CONFIG_KGDB_DEFBITS_8 */
++#define CONFIG_KGDB_DEFBITS '8'
++#endif
++
++/* SCI/UART settings, used in kgdb_console_setup() */
++int  kgdb_portnum = CONFIG_KGDB_DEFPORT;
++int  kgdb_baud = CONFIG_KGDB_DEFBAUD;
++char kgdb_parity = CONFIG_KGDB_DEFPARITY;
++char kgdb_bits = CONFIG_KGDB_DEFBITS;
++
++/* Jump buffer for setjmp/longjmp */
++static jmp_buf rem_com_env;
++
++/* TRA differs sh3/4 */
++#if defined(CONFIG_CPU_SH3)
++#define TRA 0xffffffd0
++#elif defined(CONFIG_CPU_SH4)
++#define TRA 0xff000020
++#endif
++
++/* Macros for single step instruction identification */
++#define OPCODE_BT(op)         (((op) & 0xff00) == 0x8900)
++#define OPCODE_BF(op)         (((op) & 0xff00) == 0x8b00)
++#define OPCODE_BTF_DISP(op)   (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \
++                            (((op) & 0x7f ) << 1))
++#define OPCODE_BFS(op)        (((op) & 0xff00) == 0x8f00)
++#define OPCODE_BTS(op)        (((op) & 0xff00) == 0x8d00)
++#define OPCODE_BRA(op)        (((op) & 0xf000) == 0xa000)
++#define OPCODE_BRA_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
++                            (((op) & 0x7ff) << 1))
++#define OPCODE_BRAF(op)       (((op) & 0xf0ff) == 0x0023)
++#define OPCODE_BRAF_REG(op)   (((op) & 0x0f00) >> 8)
++#define OPCODE_BSR(op)        (((op) & 0xf000) == 0xb000)
++#define OPCODE_BSR_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
++                            (((op) & 0x7ff) << 1))
++#define OPCODE_BSRF(op)       (((op) & 0xf0ff) == 0x0003)
++#define OPCODE_BSRF_REG(op)   (((op) >> 8) & 0xf)
++#define OPCODE_JMP(op)        (((op) & 0xf0ff) == 0x402b)
++#define OPCODE_JMP_REG(op)    (((op) >> 8) & 0xf)
++#define OPCODE_JSR(op)        (((op) & 0xf0ff) == 0x400b)
++#define OPCODE_JSR_REG(op)    (((op) >> 8) & 0xf)
++#define OPCODE_RTS(op)        ((op) == 0xb)
++#define OPCODE_RTE(op)        ((op) == 0x2b)
++
++#define SR_T_BIT_MASK           0x1
++#define STEP_OPCODE             0xc320
++#define BIOS_CALL_TRAP          0x3f
++
++/* Exception codes as per SH-4 core manual */
++#define ADDRESS_ERROR_LOAD_VEC   7
++#define ADDRESS_ERROR_STORE_VEC  8
++#define TRAP_VEC                 11
++#define INVALID_INSN_VEC         12
++#define INVALID_SLOT_VEC         13
++#define NMI_VEC                  14
++#define USER_BREAK_VEC           15
++#define SERIAL_BREAK_VEC         58
++
++/* Misc static */
++static int stepped_address;
++static short stepped_opcode;
++static char in_buffer[BUFMAX];
++static char out_buffer[OUTBUFMAX];
++
++static void kgdb_to_gdb(const char *s);
++
++/* Convert ch to hex */
++static int hex(const char ch)
++{
++      if ((ch >= 'a') && (ch <= 'f'))
++              return (ch - 'a' + 10);
++      if ((ch >= '0') && (ch <= '9'))
++              return (ch - '0');
++      if ((ch >= 'A') && (ch <= 'F'))
++              return (ch - 'A' + 10);
++      return (-1);
++}
++
++/* Convert the memory pointed to by mem into hex, placing result in buf.
++   Returns a pointer to the last char put in buf (null) */
++static char *mem_to_hex(const char *mem, char *buf, const int count)
++{
++      int i;
++      int ch;
++      unsigned short s_val;
++      unsigned long l_val;
++
++      /* Check for 16 or 32 */
++      if (count == 2 && ((long) mem & 1) == 0) {
++              s_val = *(unsigned short *) mem;
++              mem = (char *) &s_val;
++      } else if (count == 4 && ((long) mem & 3) == 0) {
++              l_val = *(unsigned long *) mem;
++              mem = (char *) &l_val;
++      }
++      for (i = 0; i < count; i++) {
++              ch = *mem++;
++              *buf++ = highhex(ch);
++              *buf++ = lowhex(ch);
++      }
++      *buf = 0;
++      return (buf);
++}
++
++/* Convert the hex array pointed to by buf into binary, to be placed in mem.
++   Return a pointer to the character after the last byte written */
++static char *hex_to_mem(const char *buf, char *mem, const int count)
++{
++      int i;
++      unsigned char ch;
++
++      for (i = 0; i < count; i++) {
++              ch = hex(*buf++) << 4;
++              ch = ch + hex(*buf++);
++              *mem++ = ch;
++      }
++      return (mem);
++}
++
++/* While finding valid hex chars, convert to an integer, then return it */
++static int hex_to_int(char **ptr, int *int_value)
++{
++      int num_chars = 0;
++      int hex_value;
++
++      *int_value = 0;
++
++      while (**ptr) {
++              hex_value = hex(**ptr);
++              if (hex_value >= 0) {
++                      *int_value = (*int_value << 4) | hex_value;
++                      num_chars++;
++              } else
++                      break;
++              (*ptr)++;
++      }
++      return num_chars;
++}
++
++/*  Copy the binary array pointed to by buf into mem.  Fix $, #,
++    and 0x7d escaped with 0x7d.  Return a pointer to the character
++    after the last byte written. */
++static char *ebin_to_mem(const char *buf, char *mem, int count)
++{
++      for (; count > 0; count--, buf++) {
++              if (*buf == 0x7d)
++                      *mem++ = *(++buf) ^ 0x20;
++              else
++                      *mem++ = *buf;
++      }
++      return mem;
++}
++
++/* Pack a hex byte */
++static char *pack_hex_byte(char *pkt, int byte)
++{
++      *pkt++ = hexchars[(byte >> 4) & 0xf];
++      *pkt++ = hexchars[(byte & 0xf)];
++      return pkt;
++}
++
++/* Scan for the start char '$', read the packet and check the checksum */
++static void get_packet(char *buffer, int buflen)
++{
++      unsigned char checksum;
++      unsigned char xmitcsum;
++      int i;
++      int count;
++      char ch;
++
++      do {
++              /* Ignore everything until the start character */
++              while ((ch = get_debug_char()) != '$');
++
++              checksum = 0;
++              xmitcsum = -1;
++              count = 0;
++
++              /* Now, read until a # or end of buffer is found */
++              while (count < (buflen - 1)) {
++                      ch = get_debug_char();
++
++                      if (ch == '#')
++                              break;
++
++                      checksum = checksum + ch;
++                      buffer[count] = ch;
++                      count = count + 1;
++              }
++
++              buffer[count] = 0;
++
++              /* Continue to read checksum following # */
++              if (ch == '#') {
++                      xmitcsum = hex(get_debug_char()) << 4;
++                      xmitcsum += hex(get_debug_char());
++
++                      /* Checksum */
++                      if (checksum != xmitcsum)
++                              put_debug_char('-');    /* Failed checksum */
++                      else {
++                              /* Ack successful transfer */
++                              put_debug_char('+');
++
++                              /* If a sequence char is present, reply
++                                 the sequence ID */
++                              if (buffer[2] == ':') {
++                                      put_debug_char(buffer[0]);
++                                      put_debug_char(buffer[1]);
++
++                                      /* Remove sequence chars from buffer */
++                                      count = strlen(buffer);
++                                      for (i = 3; i <= count; i++)
++                                              buffer[i - 3] = buffer[i];
++                              }
++                      }
++              }
++      }
++      while (checksum != xmitcsum);   /* Keep trying while we fail */
++}
++
++/* Send the packet in the buffer with run-length encoding */
++static void put_packet(char *buffer)
++{
++      int checksum;
++      char *src;
++      int runlen;
++      int encode;
++
++      do {
++              src = buffer;
++              put_debug_char('$');
++              checksum = 0;
++
++              /* Continue while we still have chars left */
++              while (*src) {
++                      /* Check for runs up to 99 chars long */
++                      for (runlen = 1; runlen < 99; runlen++) {
++                              if (src[0] != src[runlen])
++                                      break;
++                      }
++
++                      if (runlen > 3) {
++                              /* Got a useful amount, send encoding */
++                              encode = runlen + ' ' - 4;
++                              put_debug_char(*src);   checksum += *src;
++                              put_debug_char('*');    checksum += '*';
++                              put_debug_char(encode); checksum += encode;
++                              src += runlen;
++                      } else {
++                              /* Otherwise just send the current char */
++                              put_debug_char(*src);   checksum += *src;
++                              src += 1;
++                      }
++              }
++
++              /* '#' Separator, put high and low components of checksum */
++              put_debug_char('#');
++              put_debug_char(highhex(checksum));
++              put_debug_char(lowhex(checksum));
 +      }
++      while ((get_debug_char()) != '+');      /* While no ack */
++}
++
++/* A bus error has occurred - perform a longjmp to return execution and
++   allow handling of the error */
++static void kgdb_handle_bus_error(void)
++{
++      longjmp(rem_com_env, 1);
++}
++
++/* Translate SH-3/4 exception numbers to unix-like signal values */
++static int compute_signal(const int excep_code)
++{
++      int sigval;
 +
-       /* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present, but
-        * if we ignore the settings of all surrounding pos registers, it is not
-        * completely sufficient to only check pos2 and pos3. */
-@@ -1566,232 +1562,137 @@
-        * make sure, we see a real integrated onboard SCSI-interface and no
-        * internal system information, which gets mapped to some pos registers
-        * on models 95xx. */
--      if ((!pos[0] && !pos[1] && pos[2] > 0 && pos[3] > 0 && !pos[4] && !pos[5] && !pos[6] && !pos[7]) || (pos[0] == 0xff && pos[1] == 0xff && pos[2] < 0xff && pos[3] < 0xff && pos[4] == 0xff && pos[5] == 0xff && pos[6] == 0xff && pos[7] == 0xff)) {
--              if ((pos[2] & 1) == 1)  /* is the subsystem chip enabled ? */
-+      if (mca_dev->slot == MCA_INTEGSCSI &&
-+          ((!pos[0] && !pos[1] && pos[2] > 0 &&
-+            pos[3] > 0 && !pos[4] && !pos[5] &&
-+            !pos[6] && !pos[7]) ||
-+           (pos[0] == 0xff && pos[1] == 0xff &&
-+            pos[2] < 0xff && pos[3] < 0xff &&
-+            pos[4] == 0xff && pos[5] == 0xff &&
-+            pos[6] == 0xff && pos[7] == 0xff))) {
-+              irq = IM_IRQ;
-                       port = IM_IO_PORT;
--              else {          /* if disabled, no IRQs will be generated, as the chip won't
--                               * listen to the incoming commands and will do really nothing,
--                               * except for listening to the pos-register settings. If this
--                               * happens, I need to hugely think about it, as one has to
--                               * write something to the MCA-Bus pos register in order to
--                               * enable the chip. Normally, IBM-SCSI won't pass the POST,
--                               * when the chip is disabled (see IBM tech. ref.). */
--                      port = IM_IO_PORT;      /* anyway, set the portnumber and warn */
--                      printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n" "              SCSI-operations may not work.\n");
--              }
--              id = (pos[3] & 0xe0) >> 5;      /* this is correct and represents the PUN */
--              /* give detailed information on the subsystem. This helps me
--               * additionally during debugging and analyzing bug-reports. */
--              printk(KERN_INFO "IBM MCA SCSI: IBM Integrated SCSI Controller ffound, io=0x%x, scsi id=%d,\n", port, id);
--              printk(KERN_INFO "              chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible", (pos[2] & 1) ? "enabled." : "disabled.");
--
--              /* register the found integrated SCSI-subsystem */
--              if ((shpnt = ibmmca_register(scsi_template, port, id, INTEGRATED_SCSI, "IBM Integrated SCSI Controller"))) 
--              {
--                      for (k = 2; k < 7; k++)
--                              ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
--                      ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI;
--                      mca_set_adapter_name(MCA_INTEGSCSI, "IBM Integrated SCSI Controller");
--                      mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
--                      mca_mark_as_used(MCA_INTEGSCSI);
--                      devices_on_irq_14++;
--              }
--      }
--
--      /* now look for other adapters in MCA slots, */
--      /* determine the number of known IBM-SCSI-subsystem types */
--      /* see the pos[2] dependence to get the adapter port-offset. */
--      for (i = 0; i < ARRAY_SIZE(subsys_list); i++) {
--              /* scan each slot for a fitting adapter id */
--              slot = 0;       /* start at slot 0 */
--              while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot))
--                     != MCA_NOTFOUND) {       /* scan through all slots */
--                      for (j = 0; j < 8; j++) /* read the pos-information */
--                              pos[j] = mca_read_stored_pos(slot, j);
--                      if ((pos[2] & 1) == 1)
--                              /* is the subsystem chip enabled ? */
--                              /* (explanations see above) */
--                              port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
--                      else {
--                              /* anyway, set the portnumber and warn */
--                              port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
--                              printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
--                              printk(KERN_WARNING "              SCSI-operations may not work.\n");
--                      }
--                      if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) {
-+      } else {
-+              irq = IM_IRQ;
-+              port = IM_IO_PORT + ((pos[2] &0x0e) << 2);
-+              if ((mca_dev->index == IBM_SCSI2_FW) && (pos[6] != 0)) {
-                               printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
-                               printk(KERN_ERR "              Impossible to determine adapter PUN!\n");
-                               printk(KERN_ERR "              Guessing adapter PUN = 7.\n");
-                               id = 7;
-                       } else {
-                               id = (pos[3] & 0xe0) >> 5;      /* get subsystem PUN */
--                              if (i == IBM_SCSI2_FW) {
-+                      if (mca_dev->index == IBM_SCSI2_FW) {
-                                       id |= (pos[3] & 0x10) >> 1;     /* get subsystem PUN high-bit
-                                                                        * for F/W adapters */
-                               }
-                       }
--                      if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) {
-+              if ((mca_dev->index == IBM_SCSI2_FW) &&
-+                  (pos[4] & 0x01) && (pos[6] == 0)) {
-                               /* IRQ11 is used by SCSI-2 F/W Adapter/A */
-                               printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
--                              /* get interrupt request level */
--                              if (request_irq(IM_IRQ_FW, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts)) {
--                                      printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW);
--                              } else
--                                      IRQ11_registered++;
-+                      irq = IM_IRQ_FW;
-                       }
--                      printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id);
--                      if ((pos[2] & 0xf0) == 0xf0)
--                              printk(KERN_DEBUG"              ROM Addr.=off,");
--                      else
--                              printk(KERN_DEBUG "              ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000);
--                      printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled.");
--
--                      /* register the hostadapter */
--                      if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) {
--                              for (k = 2; k < 8; k++)
--                                      ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
--                              ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i;
--                              mca_set_adapter_name(slot, subsys_list[i].description);
--                              mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt);
--                              mca_mark_as_used(slot);
--                              if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0))
--                                      devices_on_irq_11++;
--                              else
--                                      devices_on_irq_14++;
--                      }
--                      slot++; /* advance to next slot */
--              }               /* advance to next adapter id in the list of IBM-SCSI-subsystems */
-       }
--      /* now check for SCSI-adapters, mapped to the integrated SCSI
--       * area. E.g. a W/Cache in MCA-slot 9(!). Do the check correct here,
--       * as this is a known effect on some models 95xx. */
--      for (i = 0; i < ARRAY_SIZE(subsys_list); i++) {
--              /* scan each slot for a fitting adapter id */
--              slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI);
--              if (slot != MCA_NOTFOUND) {     /* scan through all slots */
--                      for (j = 0; j < 8; j++) /* read the pos-information */
--                              pos[j] = mca_read_stored_pos(slot, j);
--                      if ((pos[2] & 1) == 1) {        /* is the subsystem chip enabled ? */
--                              /* (explanations see above) */
--                              port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
--                      } else {        /* anyway, set the portnumber and warn */
--                              port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
--                              printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
--                              printk(KERN_WARNING "              SCSI-operations may not work.\n");
--                      }
--                      if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) {
--                              printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
--                              printk(KERN_ERR  "              Impossible to determine adapter PUN!\n");
--                              printk(KERN_ERR "              Guessing adapter PUN = 7.\n");
--                              id = 7;
--                      } else {
--                              id = (pos[3] & 0xe0) >> 5;      /* get subsystem PUN */
--                              if (i == IBM_SCSI2_FW)
--                                      id |= (pos[3] & 0x10) >> 1;     /* get subsystem PUN high-bit
--                                                                       * for F/W adapters */
--                      }
--                      if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) {
--                              /* IRQ11 is used by SCSI-2 F/W Adapter/A */
--                              printk(KERN_DEBUG  "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
--                              /* get interrupt request level */
--                              if (request_irq(IM_IRQ_FW, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts))
--                                      printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW);
--                              else
--                                      IRQ11_registered++;
--                      }
--                      printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id);
++      switch (excep_code) {
 +
++      case INVALID_INSN_VEC:
++      case INVALID_SLOT_VEC:
++              sigval = SIGILL;
++              break;
++      case ADDRESS_ERROR_LOAD_VEC:
++      case ADDRESS_ERROR_STORE_VEC:
++              sigval = SIGSEGV;
++              break;
 +
-+      /* give detailed information on the subsystem. This helps me
-+       * additionally during debugging and analyzing bug-reports. */
-+      printk(KERN_INFO "IBM MCA SCSI: %s found, io=0x%x, scsi id=%d,\n",
-+             description, port, id);
-+      if (mca_dev->slot == MCA_INTEGSCSI)
-+              printk(KERN_INFO "              chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible", (pos[2] & 1) ? "enabled." : "disabled.");
-+      else {
-                       if ((pos[2] & 0xf0) == 0xf0)
-                               printk(KERN_DEBUG "              ROM Addr.=off,");
-                       else
-                               printk(KERN_DEBUG "              ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000);
--                      printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled.");
--                      /* register the hostadapter */
--                      if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) {
--                              for (k = 2; k < 7; k++)
--                                      ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
--                              ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i;
--                              mca_set_adapter_name(slot, subsys_list[i].description);
--                              mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt);
--                              mca_mark_as_used(slot);
--                              if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0))
--                                      devices_on_irq_11++;
--                              else
--                                      devices_on_irq_14++;
--                      }
--                      slot++; /* advance to next slot */
--              }               /* advance to next adapter id in the list of IBM-SCSI-subsystems */
-+              printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled.");
-       }
--      if (IRQ11_registered && !devices_on_irq_11)
--              free_irq(IM_IRQ_FW, hosts);     /* no devices on IRQ 11 */
--      if (IRQ14_registered && !devices_on_irq_14)
--              free_irq(IM_IRQ, hosts);        /* no devices on IRQ 14 */
--      if (!devices_on_irq_11 && !devices_on_irq_14)
--              printk(KERN_WARNING "IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n");
--      return found;           /* return the number of found SCSI hosts. Should be 1 or 0. */
--}
--
--static struct Scsi_Host *ibmmca_register(struct scsi_host_template * scsi_template, int port, int id, int adaptertype, char *hostname)
--{
--      struct Scsi_Host *shpnt;
--      int i, j;
--      unsigned int ctrl;
-       /* check I/O region */
--      if (!request_region(port, IM_N_IO_PORT, hostname)) {
-+      if (!request_region(port, IM_N_IO_PORT, description)) {
-               printk(KERN_ERR "IBM MCA SCSI: Unable to get I/O region 0x%x-0x%x (%d ports).\n", port, port + IM_N_IO_PORT - 1, IM_N_IO_PORT);
--              return NULL;
-+              goto out_fail;
-       }
-       /* register host */
--      shpnt = scsi_register(scsi_template, sizeof(struct ibmmca_hostdata));
-+      shpnt = scsi_host_alloc(&ibmmca_driver_template,
-+                              sizeof(struct ibmmca_hostdata));
-       if (!shpnt) {
-               printk(KERN_ERR "IBM MCA SCSI: Unable to register host.\n");
--              release_region(port, IM_N_IO_PORT);
--              return NULL;
-+              goto out_release;
++      case SERIAL_BREAK_VEC:
++      case NMI_VEC:
++              sigval = SIGINT;
++              break;
++
++      case USER_BREAK_VEC:
++      case TRAP_VEC:
++              sigval = SIGTRAP;
++              break;
++
++      default:
++              sigval = SIGBUS;        /* "software generated" */
++              break;
 +      }
 +
-+      dev_set_drvdata(dev, shpnt);
-+      if(request_irq(irq, interrupt_handler, IRQF_SHARED, description, dev)) {
-+              printk(KERN_ERR "IBM MCA SCSI: failed to request interrupt %d\n", irq);
-+              goto out_free_host;
-       }
-       /* request I/O region */
--      hosts[found] = shpnt;   /* add new found hostadapter to the list */
--      special(found) = adaptertype;   /* important assignment or else crash! */
--      subsystem_connector_size(found) = 0;    /* preset slot-size */
--      shpnt->irq = IM_IRQ;    /* assign necessary stuff for the adapter */
-+      special(shpnt) = mca_dev->index;        /* important assignment or else crash! */
-+      subsystem_connector_size(shpnt) = 0;    /* preset slot-size */
-+      shpnt->irq = irq;       /* assign necessary stuff for the adapter */
-       shpnt->io_port = port;
-       shpnt->n_io_port = IM_N_IO_PORT;
-       shpnt->this_id = id;
-       shpnt->max_id = 8;      /* 8 PUNs are default */
-       /* now, the SCSI-subsystem is connected to Linux */
--      ctrl = (unsigned int) (inb(IM_CTR_REG(found))); /* get control-register status */
- #ifdef IM_DEBUG_PROBE
-+      ctrl = (unsigned int) (inb(IM_CTR_REG(found))); /* get control-register status */
-       printk("IBM MCA SCSI: Control Register contents: %x, status: %x\n", ctrl, inb(IM_STAT_REG(found)));
-       printk("IBM MCA SCSI: This adapters' POS-registers: ");
-       for (i = 0; i < 8; i++)
-               printk("%x ", pos[i]);
-       printk("\n");
- #endif
--      reset_status(found) = IM_RESET_NOT_IN_PROGRESS;
-+      reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS;
-       for (i = 0; i < 16; i++)        /* reset the tables */
-               for (j = 0; j < 8; j++)
--                      get_ldn(found)[i][j] = MAX_LOG_DEV;
-+                      get_ldn(shpnt)[i][j] = MAX_LOG_DEV;
-       /* check which logical devices exist */
-       /* after this line, local interrupting is possible: */
--      local_checking_phase_flag(found) = 1;
--      check_devices(found, adaptertype);      /* call by value, using the global variable hosts */
--      local_checking_phase_flag(found) = 0;
--      found++;                /* now increase index to be prepared for next found subsystem */
-+      local_checking_phase_flag(shpnt) = 1;
-+      check_devices(shpnt, mca_dev->index);   /* call by value, using the global variable hosts */
-+      local_checking_phase_flag(shpnt) = 0;
++      return (sigval);
++}
 +
-       /* an ibm mca subsystem has been detected */
--      return shpnt;
-+
-+      for (k = 2; k < 7; k++)
-+              ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
-+      ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI;
-+      mca_device_set_name(mca_dev, description);
-+      /* FIXME: NEED TO REPLUMB TO SYSFS
-+         mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
-+      */
-+      mca_device_set_claim(mca_dev, 1);
-+      if (scsi_add_host(shpnt, dev)) {
-+              dev_printk(KERN_ERR, dev, "IBM MCA SCSI: scsi_add_host failed\n");
-+              goto out_free_host;
++/* Make a local copy of the registers passed into the handler (bletch) */
++static void kgdb_regs_to_gdb_regs(const struct kgdb_regs *regs,
++                                int *gdb_regs)
++{
++      gdb_regs[R0] = regs->regs[R0];
++      gdb_regs[R1] = regs->regs[R1];
++      gdb_regs[R2] = regs->regs[R2];
++      gdb_regs[R3] = regs->regs[R3];
++      gdb_regs[R4] = regs->regs[R4];
++      gdb_regs[R5] = regs->regs[R5];
++      gdb_regs[R6] = regs->regs[R6];
++      gdb_regs[R7] = regs->regs[R7];
++      gdb_regs[R8] = regs->regs[R8];
++      gdb_regs[R9] = regs->regs[R9];
++      gdb_regs[R10] = regs->regs[R10];
++      gdb_regs[R11] = regs->regs[R11];
++      gdb_regs[R12] = regs->regs[R12];
++      gdb_regs[R13] = regs->regs[R13];
++      gdb_regs[R14] = regs->regs[R14];
++      gdb_regs[R15] = regs->regs[R15];
++      gdb_regs[PC] = regs->pc;
++      gdb_regs[PR] = regs->pr;
++      gdb_regs[GBR] = regs->gbr;
++      gdb_regs[MACH] = regs->mach;
++      gdb_regs[MACL] = regs->macl;
++      gdb_regs[SR] = regs->sr;
++      gdb_regs[VBR] = regs->vbr;
++}
++
++/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
++static void gdb_regs_to_kgdb_regs(const int *gdb_regs,
++                                struct kgdb_regs *regs)
++{
++      regs->regs[R0] = gdb_regs[R0];
++      regs->regs[R1] = gdb_regs[R1];
++      regs->regs[R2] = gdb_regs[R2];
++      regs->regs[R3] = gdb_regs[R3];
++      regs->regs[R4] = gdb_regs[R4];
++      regs->regs[R5] = gdb_regs[R5];
++      regs->regs[R6] = gdb_regs[R6];
++      regs->regs[R7] = gdb_regs[R7];
++      regs->regs[R8] = gdb_regs[R8];
++      regs->regs[R9] = gdb_regs[R9];
++      regs->regs[R10] = gdb_regs[R10];
++      regs->regs[R11] = gdb_regs[R11];
++      regs->regs[R12] = gdb_regs[R12];
++      regs->regs[R13] = gdb_regs[R13];
++      regs->regs[R14] = gdb_regs[R14];
++      regs->regs[R15] = gdb_regs[R15];
++      regs->pc = gdb_regs[PC];
++      regs->pr = gdb_regs[PR];
++      regs->gbr = gdb_regs[GBR];
++      regs->mach = gdb_regs[MACH];
++      regs->macl = gdb_regs[MACL];
++      regs->sr = gdb_regs[SR];
++      regs->vbr = gdb_regs[VBR];
++}
++
++/* Calculate the new address for after a step */
++static short *get_step_address(void)
++{
++      short op = *(short *) trap_registers.pc;
++      long addr;
++
++      /* BT */
++      if (OPCODE_BT(op)) {
++              if (trap_registers.sr & SR_T_BIT_MASK)
++                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
++              else
++                      addr = trap_registers.pc + 2;
 +      }
-+      scsi_scan_host(shpnt);
 +
-+      return 0;
-+ out_free_host:
-+      scsi_host_put(shpnt);
-+ out_release:
-+      release_region(port, IM_N_IO_PORT);
-+ out_fail:
-+      return ret;
- }
--static int ibmmca_release(struct Scsi_Host *shpnt)
-+static int __devexit ibmmca_remove(struct device *dev)
- {
-+      struct Scsi_Host *shpnt = dev_get_drvdata(dev);
-+      scsi_remove_host(shpnt);
-       release_region(shpnt->io_port, shpnt->n_io_port);
--      if (!(--found))
--              free_irq(shpnt->irq, hosts);
-+      free_irq(shpnt->irq, dev);
-       return 0;
- }
-@@ -1805,33 +1706,24 @@
-       int current_ldn;
-       int id, lun;
-       int target;
--      int host_index;
-       int max_pun;
-       int i;
--      struct scatterlist *sl;
-+      struct scatterlist *sg;
-       shpnt = cmd->device->host;
--      /* search for the right hostadapter */
--      for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
--      if (!hosts[host_index]) {       /* invalid hostadapter descriptor address */
--              cmd->result = DID_NO_CONNECT << 16;
--              if (done)
--                      done(cmd);
--              return 0;
--      }
--      max_pun = subsystem_maxid(host_index);
-+      max_pun = subsystem_maxid(shpnt);
-       if (ibm_ansi_order) {
-               target = max_pun - 1 - cmd->device->id;
--              if ((target <= subsystem_pun(host_index)) && (cmd->device->id <= subsystem_pun(host_index)))
-+              if ((target <= subsystem_pun(shpnt)) && (cmd->device->id <= subsystem_pun(shpnt)))
-                       target--;
--              else if ((target >= subsystem_pun(host_index)) && (cmd->device->id >= subsystem_pun(host_index)))
-+              else if ((target >= subsystem_pun(shpnt)) && (cmd->device->id >= subsystem_pun(shpnt)))
-                       target++;
-       } else
-               target = cmd->device->id;
-       /* if (target,lun) is NO LUN or not existing at all, return error */
--      if ((get_scsi(host_index)[target][cmd->device->lun] == TYPE_NO_LUN) || (get_scsi(host_index)[target][cmd->device->lun] == TYPE_NO_DEVICE)) {
-+      if ((get_scsi(shpnt)[target][cmd->device->lun] == TYPE_NO_LUN) || (get_scsi(shpnt)[target][cmd->device->lun] == TYPE_NO_DEVICE)) {
-               cmd->result = DID_NO_CONNECT << 16;
-               if (done)
-                       done(cmd);
-@@ -1839,16 +1731,16 @@
-       }
-       /*if (target,lun) unassigned, do further checks... */
--      ldn = get_ldn(host_index)[target][cmd->device->lun];
-+      ldn = get_ldn(shpnt)[target][cmd->device->lun];
-       if (ldn >= MAX_LOG_DEV) {       /* on invalid ldn do special stuff */
-               if (ldn > MAX_LOG_DEV) {        /* dynamical remapping if ldn unassigned */
--                      current_ldn = next_ldn(host_index);     /* stop-value for one circle */
--                      while (ld(host_index)[next_ldn(host_index)].cmd) {      /* search for a occupied, but not in */
-+                      current_ldn = next_ldn(shpnt);  /* stop-value for one circle */
-+                      while (ld(shpnt)[next_ldn(shpnt)].cmd) {        /* search for a occupied, but not in */
-                               /* command-processing ldn. */
--                              next_ldn(host_index)++;
--                              if (next_ldn(host_index) >= MAX_LOG_DEV)
--                                      next_ldn(host_index) = 7;
--                              if (current_ldn == next_ldn(host_index)) {      /* One circle done ? */
-+                              next_ldn(shpnt)++;
-+                              if (next_ldn(shpnt) >= MAX_LOG_DEV)
-+                                      next_ldn(shpnt) = 7;
-+                              if (current_ldn == next_ldn(shpnt)) {   /* One circle done ? */
-                                       /* no non-processing ldn found */
-                                       scmd_printk(KERN_WARNING, cmd,
-       "IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n"
-@@ -1864,56 +1756,56 @@
-                       /* unmap non-processing ldn */
-                       for (id = 0; id < max_pun; id++)
-                               for (lun = 0; lun < 8; lun++) {
--                                      if (get_ldn(host_index)[id][lun] == next_ldn(host_index)) {
--                                              get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;
--                                              get_scsi(host_index)[id][lun] = TYPE_NO_DEVICE;
-+                                      if (get_ldn(shpnt)[id][lun] == next_ldn(shpnt)) {
-+                                              get_ldn(shpnt)[id][lun] = TYPE_NO_DEVICE;
-+                                              get_scsi(shpnt)[id][lun] = TYPE_NO_DEVICE;
-                                               /* unmap entry */
-                                       }
-                               }
-                       /* set reduced interrupt_handler-mode for checking */
--                      local_checking_phase_flag(host_index) = 1;
-+                      local_checking_phase_flag(shpnt) = 1;
-                       /* map found ldn to pun,lun */
--                      get_ldn(host_index)[target][cmd->device->lun] = next_ldn(host_index);
-+                      get_ldn(shpnt)[target][cmd->device->lun] = next_ldn(shpnt);
-                       /* change ldn to the right value, that is now next_ldn */
--                      ldn = next_ldn(host_index);
-+                      ldn = next_ldn(shpnt);
-                       /* unassign all ldns (pun,lun,ldn does not matter for remove) */
--                      immediate_assign(host_index, 0, 0, 0, REMOVE_LDN);
-+                      immediate_assign(shpnt, 0, 0, 0, REMOVE_LDN);
-                       /* set only LDN for remapped device */
--                      immediate_assign(host_index, target, cmd->device->lun, ldn, SET_LDN);
-+                      immediate_assign(shpnt, target, cmd->device->lun, ldn, SET_LDN);
-                       /* get device information for ld[ldn] */
--                      if (device_exists(host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) {
--                              ld(host_index)[ldn].cmd = NULL; /* To prevent panic set 0, because
-+                      if (device_exists(shpnt, ldn, &ld(shpnt)[ldn].block_length, &ld(shpnt)[ldn].device_type)) {
-+                              ld(shpnt)[ldn].cmd = NULL;      /* To prevent panic set 0, because
-                                                                  devices that were not assigned,
-                                                                  should have nothing in progress. */
--                              get_scsi(host_index)[target][cmd->device->lun] = ld(host_index)[ldn].device_type;
-+                              get_scsi(shpnt)[target][cmd->device->lun] = ld(shpnt)[ldn].device_type;
-                               /* increase assignment counters for statistics in /proc */
--                              IBM_DS(host_index).dynamical_assignments++;
--                              IBM_DS(host_index).ldn_assignments[ldn]++;
-+                              IBM_DS(shpnt).dynamical_assignments++;
-+                              IBM_DS(shpnt).ldn_assignments[ldn]++;
-                       } else
-                               /* panic here, because a device, found at boottime has
-                                  vanished */
-                               panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n", ldn, target, cmd->device->lun);
-                       /* unassign again all ldns (pun,lun,ldn does not matter for remove) */
--                      immediate_assign(host_index, 0, 0, 0, REMOVE_LDN);
-+                      immediate_assign(shpnt, 0, 0, 0, REMOVE_LDN);
-                       /* remap all ldns, as written in the pun/lun table */
-                       lun = 0;
- #ifdef CONFIG_SCSI_MULTI_LUN
-                       for (lun = 0; lun < 8; lun++)
- #endif
-                               for (id = 0; id < max_pun; id++) {
--                                      if (get_ldn(host_index)[id][lun] <= MAX_LOG_DEV)
--                                              immediate_assign(host_index, id, lun, get_ldn(host_index)[id][lun], SET_LDN);
-+                                      if (get_ldn(shpnt)[id][lun] <= MAX_LOG_DEV)
-+                                              immediate_assign(shpnt, id, lun, get_ldn(shpnt)[id][lun], SET_LDN);
-                               }
-                       /* set back to normal interrupt_handling */
--                      local_checking_phase_flag(host_index) = 0;
-+                      local_checking_phase_flag(shpnt) = 0;
- #ifdef IM_DEBUG_PROBE
-                       /* Information on syslog terminal */
-                       printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n", ldn, target, cmd->device->lun);
- #endif
-                       /* increase next_ldn for next dynamical assignment */
--                      next_ldn(host_index)++;
--                      if (next_ldn(host_index) >= MAX_LOG_DEV)
--                              next_ldn(host_index) = 7;
-+                      next_ldn(shpnt)++;
-+                      if (next_ldn(shpnt) >= MAX_LOG_DEV)
-+                              next_ldn(shpnt) = 7;
-               } else {        /* wall against Linux accesses to the subsystem adapter */
-                       cmd->result = DID_BAD_TARGET << 16;
-                       if (done)
-@@ -1923,34 +1815,32 @@
-       }
-       /*verify there is no command already in progress for this log dev */
--      if (ld(host_index)[ldn].cmd)
-+      if (ld(shpnt)[ldn].cmd)
-               panic("IBM MCA SCSI: cmd already in progress for this ldn.\n");
-       /*save done in cmd, and save cmd for the interrupt handler */
-       cmd->scsi_done = done;
--      ld(host_index)[ldn].cmd = cmd;
-+      ld(shpnt)[ldn].cmd = cmd;
-       /*fill scb information independent of the scsi command */
--      scb = &(ld(host_index)[ldn].scb);
--      ld(host_index)[ldn].tsb.dev_status = 0;
-+      scb = &(ld(shpnt)[ldn].scb);
-+      ld(shpnt)[ldn].tsb.dev_status = 0;
-       scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE;
--      scb->tsb_adr = isa_virt_to_bus(&(ld(host_index)[ldn].tsb));
-+      scb->tsb_adr = isa_virt_to_bus(&(ld(shpnt)[ldn].tsb));
-       scsi_cmd = cmd->cmnd[0];
--      if (cmd->use_sg) {
--              i = cmd->use_sg;
--              sl = (struct scatterlist *) (cmd->request_buffer);
--              if (i > 16)
--                      panic("IBM MCA SCSI: scatter-gather list too long.\n");
--              while (--i >= 0) {
--                      ld(host_index)[ldn].sge[i].address = (void *) (isa_page_to_bus(sl[i].page) + sl[i].offset);
--                      ld(host_index)[ldn].sge[i].byte_length = sl[i].length;
-+      if (scsi_sg_count(cmd)) {
-+              BUG_ON(scsi_sg_count(cmd) > 16);
-+
-+              scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) {
-+                      ld(shpnt)[ldn].sge[i].address = (void *) (isa_page_to_bus(sg->page) + sg->offset);
-+                      ld(shpnt)[ldn].sge[i].byte_length = sg->length;
-               }
-               scb->enable |= IM_POINTER_TO_LIST;
--              scb->sys_buf_adr = isa_virt_to_bus(&(ld(host_index)[ldn].sge[0]));
--              scb->sys_buf_length = cmd->use_sg * sizeof(struct im_sge);
-+              scb->sys_buf_adr = isa_virt_to_bus(&(ld(shpnt)[ldn].sge[0]));
-+              scb->sys_buf_length = scsi_sg_count(cmd) * sizeof(struct im_sge);
-       } else {
--              scb->sys_buf_adr = isa_virt_to_bus(cmd->request_buffer);
-+              scb->sys_buf_adr = isa_virt_to_bus(scsi_sglist(cmd));
-               /* recent Linux midlevel SCSI places 1024 byte for inquiry
-                * command. Far too much for old PS/2 hardware. */
-               switch (scsi_cmd) {
-@@ -1961,16 +1851,16 @@
-               case REQUEST_SENSE:
-               case MODE_SENSE:
-               case MODE_SELECT:
--                      if (cmd->request_bufflen > 255)
-+                      if (scsi_bufflen(cmd) > 255)
-                               scb->sys_buf_length = 255;
-                       else
--                              scb->sys_buf_length = cmd->request_bufflen;
-+                              scb->sys_buf_length = scsi_bufflen(cmd);
-                       break;
-               case TEST_UNIT_READY:
-                       scb->sys_buf_length = 0;
-                       break;
-               default:
--                      scb->sys_buf_length = cmd->request_bufflen;
-+                      scb->sys_buf_length = scsi_bufflen(cmd);
-                       break;
-               }
-       }
-@@ -1982,16 +1872,16 @@
-       /* for specific device-type debugging: */
- #ifdef IM_DEBUG_CMD_SPEC_DEV
--      if (ld(host_index)[ldn].device_type == IM_DEBUG_CMD_DEVICE)
--              printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(host_index)[ldn].device_type, scsi_cmd, ldn);
-+      if (ld(shpnt)[ldn].device_type == IM_DEBUG_CMD_DEVICE)
-+              printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(shpnt)[ldn].device_type, scsi_cmd, ldn);
- #endif
-       /* for possible panics store current command */
--      last_scsi_command(host_index)[ldn] = scsi_cmd;
--      last_scsi_type(host_index)[ldn] = IM_SCB;
-+      last_scsi_command(shpnt)[ldn] = scsi_cmd;
-+      last_scsi_type(shpnt)[ldn] = IM_SCB;
-       /* update statistical info */
--      IBM_DS(host_index).total_accesses++;
--      IBM_DS(host_index).ldn_access[ldn]++;
-+      IBM_DS(shpnt).total_accesses++;
-+      IBM_DS(shpnt).ldn_access[ldn]++;
-       switch (scsi_cmd) {
-       case READ_6:
-@@ -2003,17 +1893,17 @@
-               /* Distinguish between disk and other devices. Only disks (that are the
-                  most frequently accessed devices) should be supported by the
-                  IBM-SCSI-Subsystem commands. */
--              switch (ld(host_index)[ldn].device_type) {
-+              switch (ld(shpnt)[ldn].device_type) {
-               case TYPE_DISK: /* for harddisks enter here ... */
-               case TYPE_MOD:  /* ... try it also for MO-drives (send flames as */
-                       /*     you like, if this won't work.) */
-                       if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) {
-                               /* read command preparations */
-                               scb->enable |= IM_READ_CONTROL;
--                              IBM_DS(host_index).ldn_read_access[ldn]++;      /* increase READ-access on ldn stat. */
-+                              IBM_DS(shpnt).ldn_read_access[ldn]++;   /* increase READ-access on ldn stat. */
-                               scb->command = IM_READ_DATA_CMD | IM_NO_DISCONNECT;
-                       } else {        /* write command preparations */
--                              IBM_DS(host_index).ldn_write_access[ldn]++;     /* increase write-count on ldn stat. */
-+                              IBM_DS(shpnt).ldn_write_access[ldn]++;  /* increase write-count on ldn stat. */
-                               scb->command = IM_WRITE_DATA_CMD | IM_NO_DISCONNECT;
-                       }
-                       if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6) {
-@@ -2023,9 +1913,9 @@
-                               scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) | (((unsigned) cmd->cmnd[4]) << 8) | (((unsigned) cmd->cmnd[3]) << 16) | (((unsigned) cmd->cmnd[2]) << 24);
-                               scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) | (((unsigned) cmd->cmnd[7]) << 8);
-                       }
--                      last_scsi_logical_block(host_index)[ldn] = scb->u1.log_blk_adr;
--                      last_scsi_blockcount(host_index)[ldn] = scb->u2.blk.count;
--                      scb->u2.blk.length = ld(host_index)[ldn].block_length;
-+                      last_scsi_logical_block(shpnt)[ldn] = scb->u1.log_blk_adr;
-+                      last_scsi_blockcount(shpnt)[ldn] = scb->u2.blk.count;
-+                      scb->u2.blk.length = ld(shpnt)[ldn].block_length;
-                       break;
-                       /* for other devices, enter here. Other types are not known by
-                          Linux! TYPE_NO_LUN is forbidden as valid device. */
-@@ -2046,14 +1936,14 @@
-                       scb->enable |= IM_BYPASS_BUFFER;
-                       scb->u1.scsi_cmd_length = cmd->cmd_len;
-                       memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
--                      last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
-+                      last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
-                       /* Read/write on this non-disk devices is also displayworthy,
-                          so flash-up the LED/display. */
-                       break;
-               }
-               break;
-       case INQUIRY:
--              IBM_DS(host_index).ldn_inquiry_access[ldn]++;
-+              IBM_DS(shpnt).ldn_inquiry_access[ldn]++;
-               scb->command = IM_DEVICE_INQUIRY_CMD;
-               scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
-               scb->u1.log_blk_adr = 0;
-@@ -2064,7 +1954,7 @@
-               scb->u1.log_blk_adr = 0;
-               scb->u1.scsi_cmd_length = 6;
-               memcpy(scb->u2.scsi_command, cmd->cmnd, 6);
--              last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
-+              last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
-               break;
-       case READ_CAPACITY:
-               /* the length of system memory buffer must be exactly 8 bytes */
-@@ -2081,12 +1971,12 @@
-               /* Commands that need write-only-mode (system -> device): */
-       case MODE_SELECT:
-       case MODE_SELECT_10:
--              IBM_DS(host_index).ldn_modeselect_access[ldn]++;
-+              IBM_DS(shpnt).ldn_modeselect_access[ldn]++;
-               scb->command = IM_OTHER_SCSI_CMD_CMD;
-               scb->enable |= IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;   /*Select needs WRITE-enabled */
-               scb->u1.scsi_cmd_length = cmd->cmd_len;
-               memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
--              last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
-+              last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
-               break;
-               /* For other commands, read-only is useful. Most other commands are
-                  running without an input-data-block. */
-@@ -2095,19 +1985,19 @@
-               scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
-               scb->u1.scsi_cmd_length = cmd->cmd_len;
-               memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
--              last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
-+              last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
-               break;
-       }
-       /*issue scb command, and return */
-       if (++disk_rw_in_progress == 1)
-               PS2_DISK_LED_ON(shpnt->host_no, target);
--      if (last_scsi_type(host_index)[ldn] == IM_LONG_SCB) {
--              issue_cmd(host_index, isa_virt_to_bus(scb), IM_LONG_SCB | ldn);
--              IBM_DS(host_index).long_scbs++;
-+      if (last_scsi_type(shpnt)[ldn] == IM_LONG_SCB) {
-+              issue_cmd(shpnt, isa_virt_to_bus(scb), IM_LONG_SCB | ldn);
-+              IBM_DS(shpnt).long_scbs++;
-       } else {
--              issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
--              IBM_DS(host_index).scbs++;
-+              issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
-+              IBM_DS(shpnt).scbs++;
-       }
-       return 0;
- }
-@@ -2122,7 +2012,6 @@
-       unsigned int ldn;
-       void (*saved_done) (Scsi_Cmnd *);
-       int target;
--      int host_index;
-       int max_pun;
-       unsigned long imm_command;
-@@ -2131,35 +2020,23 @@
- #endif
-       shpnt = cmd->device->host;
--      /* search for the right hostadapter */
--      for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
--      if (!hosts[host_index]) {       /* invalid hostadapter descriptor address */
--              cmd->result = DID_NO_CONNECT << 16;
--              if (cmd->scsi_done)
--                      (cmd->scsi_done) (cmd);
--              shpnt = cmd->device->host;
--#ifdef IM_DEBUG_PROBE
--              printk(KERN_DEBUG "IBM MCA SCSI: Abort adapter selection failed!\n");
--#endif
--              return SUCCESS;
--      }
--      max_pun = subsystem_maxid(host_index);
-+      max_pun = subsystem_maxid(shpnt);
-       if (ibm_ansi_order) {
-               target = max_pun - 1 - cmd->device->id;
--              if ((target <= subsystem_pun(host_index)) && (cmd->device->id <= subsystem_pun(host_index)))
-+              if ((target <= subsystem_pun(shpnt)) && (cmd->device->id <= subsystem_pun(shpnt)))
-                       target--;
--              else if ((target >= subsystem_pun(host_index)) && (cmd->device->id >= subsystem_pun(host_index)))
-+              else if ((target >= subsystem_pun(shpnt)) && (cmd->device->id >= subsystem_pun(shpnt)))
-                       target++;
-       } else
-               target = cmd->device->id;
-       /* get logical device number, and disable system interrupts */
-       printk(KERN_WARNING "IBM MCA SCSI: Sending abort to device pun=%d, lun=%d.\n", target, cmd->device->lun);
--      ldn = get_ldn(host_index)[target][cmd->device->lun];
-+      ldn = get_ldn(shpnt)[target][cmd->device->lun];
-       /*if cmd for this ldn has already finished, no need to abort */
--      if (!ld(host_index)[ldn].cmd) {
-+      if (!ld(shpnt)[ldn].cmd) {
-                   return SUCCESS;
-       }
-@@ -2170,20 +2047,20 @@
-       saved_done = cmd->scsi_done;
-       cmd->scsi_done = internal_done;
-       cmd->SCp.Status = 0;
--      last_scsi_command(host_index)[ldn] = IM_ABORT_IMM_CMD;
--      last_scsi_type(host_index)[ldn] = IM_IMM_CMD;
--      imm_command = inl(IM_CMD_REG(host_index));
-+      last_scsi_command(shpnt)[ldn] = IM_ABORT_IMM_CMD;
-+      last_scsi_type(shpnt)[ldn] = IM_IMM_CMD;
-+      imm_command = inl(IM_CMD_REG(shpnt));
-       imm_command &= (unsigned long) (0xffff0000);    /* mask reserved stuff */
-       imm_command |= (unsigned long) (IM_ABORT_IMM_CMD);
-       /* must wait for attention reg not busy */
-       /* FIXME - timeout, politeness */
-       while (1) {
--              if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
-+              if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
-                       break;
-       }
-       /* write registers and enable system interrupts */
--      outl(imm_command, IM_CMD_REG(host_index));
--      outb(IM_IMM_CMD | ldn, IM_ATTN_REG(host_index));
-+      outl(imm_command, IM_CMD_REG(shpnt));
-+      outb(IM_IMM_CMD | ldn, IM_ATTN_REG(shpnt));
- #ifdef IM_DEBUG_PROBE
-       printk("IBM MCA SCSI: Abort queued to adapter...\n");
- #endif
-@@ -2202,7 +2079,7 @@
-               cmd->result |= DID_ABORT << 16;
-               if (cmd->scsi_done)
-                       (cmd->scsi_done) (cmd);
--              ld(host_index)[ldn].cmd = NULL;
-+              ld(shpnt)[ldn].cmd = NULL;
- #ifdef IM_DEBUG_PROBE
-               printk("IBM MCA SCSI: Abort finished with success.\n");
- #endif
-@@ -2211,7 +2088,7 @@
-               cmd->result |= DID_NO_CONNECT << 16;
-               if (cmd->scsi_done)
-                       (cmd->scsi_done) (cmd);
--              ld(host_index)[ldn].cmd = NULL;
-+              ld(shpnt)[ldn].cmd = NULL;
- #ifdef IM_DEBUG_PROBE
-               printk("IBM MCA SCSI: Abort failed.\n");
- #endif
-@@ -2236,71 +2113,65 @@
-       struct Scsi_Host *shpnt;
-       Scsi_Cmnd *cmd_aid;
-       int ticks, i;
--      int host_index;
-       unsigned long imm_command;
-       BUG_ON(cmd == NULL);
-       ticks = IM_RESET_DELAY * HZ;
-       shpnt = cmd->device->host;
--      /* search for the right hostadapter */
--      for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
--      if (!hosts[host_index]) /* invalid hostadapter descriptor address */
--              return FAILED;
--
--      if (local_checking_phase_flag(host_index)) {
-+      if (local_checking_phase_flag(shpnt)) {
-               printk(KERN_WARNING "IBM MCA SCSI: unable to reset while checking devices.\n");
-               return FAILED;
-       }
-       /* issue reset immediate command to subsystem, and wait for interrupt */
-       printk("IBM MCA SCSI: resetting all devices.\n");
--      reset_status(host_index) = IM_RESET_IN_PROGRESS;
--      last_scsi_command(host_index)[0xf] = IM_RESET_IMM_CMD;
--      last_scsi_type(host_index)[0xf] = IM_IMM_CMD;
--      imm_command = inl(IM_CMD_REG(host_index));
-+      reset_status(shpnt) = IM_RESET_IN_PROGRESS;
-+      last_scsi_command(shpnt)[0xf] = IM_RESET_IMM_CMD;
-+      last_scsi_type(shpnt)[0xf] = IM_IMM_CMD;
-+      imm_command = inl(IM_CMD_REG(shpnt));
-       imm_command &= (unsigned long) (0xffff0000);    /* mask reserved stuff */
-       imm_command |= (unsigned long) (IM_RESET_IMM_CMD);
-       /* must wait for attention reg not busy */
-       while (1) {
--              if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
-+              if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
-                       break;
-               spin_unlock_irq(shpnt->host_lock);
-               yield();
-               spin_lock_irq(shpnt->host_lock);
-       }
-       /*write registers and enable system interrupts */
--      outl(imm_command, IM_CMD_REG(host_index));
--      outb(IM_IMM_CMD | 0xf, IM_ATTN_REG(host_index));
-+      outl(imm_command, IM_CMD_REG(shpnt));
-+      outb(IM_IMM_CMD | 0xf, IM_ATTN_REG(shpnt));
-       /* wait for interrupt finished or intr_stat register to be set, as the
-        * interrupt will not be executed, while we are in here! */
-        
-       /* FIXME: This is really really icky we so want a sleeping version of this ! */
--      while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks && ((inb(IM_INTR_REG(host_index)) & 0x8f) != 0x8f)) {
-+      while (reset_status(shpnt) == IM_RESET_IN_PROGRESS && --ticks && ((inb(IM_INTR_REG(shpnt)) & 0x8f) != 0x8f)) {
-               udelay((1 + 999 / HZ) * 1000);
-               barrier();
-       }
-       /* if reset did not complete, just return an error */
-       if (!ticks) {
-               printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY);
--              reset_status(host_index) = IM_RESET_FINISHED_FAIL;
-+              reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
-               return FAILED;
-       }
--      if ((inb(IM_INTR_REG(host_index)) & 0x8f) == 0x8f) {
-+      if ((inb(IM_INTR_REG(shpnt)) & 0x8f) == 0x8f) {
-               /* analysis done by this routine and not by the intr-routine */
--              if (inb(IM_INTR_REG(host_index)) == 0xaf)
--                      reset_status(host_index) = IM_RESET_FINISHED_OK_NO_INT;
--              else if (inb(IM_INTR_REG(host_index)) == 0xcf)
--                      reset_status(host_index) = IM_RESET_FINISHED_FAIL;
-+              if (inb(IM_INTR_REG(shpnt)) == 0xaf)
-+                      reset_status(shpnt) = IM_RESET_FINISHED_OK_NO_INT;
-+              else if (inb(IM_INTR_REG(shpnt)) == 0xcf)
-+                      reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
-               else            /* failed, 4get it */
--                      reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS_NO_INT;
--              outb(IM_EOI | 0xf, IM_ATTN_REG(host_index));
-+                      reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS_NO_INT;
-+              outb(IM_EOI | 0xf, IM_ATTN_REG(shpnt));
-       }
-       /* if reset failed, just return an error */
--      if (reset_status(host_index) == IM_RESET_FINISHED_FAIL) {
-+      if (reset_status(shpnt) == IM_RESET_FINISHED_FAIL) {
-               printk(KERN_ERR "IBM MCA SCSI: reset failed.\n");
-               return FAILED;
-       }
-@@ -2308,9 +2179,9 @@
-       /* so reset finished ok - call outstanding done's, and return success */
-       printk(KERN_INFO "IBM MCA SCSI: Reset successfully completed.\n");
-       for (i = 0; i < MAX_LOG_DEV; i++) {
--              cmd_aid = ld(host_index)[i].cmd;
-+              cmd_aid = ld(shpnt)[i].cmd;
-               if (cmd_aid && cmd_aid->scsi_done) {
--                      ld(host_index)[i].cmd = NULL;
-+                      ld(shpnt)[i].cmd = NULL;
-                       cmd_aid->result = DID_RESET << 16;
-               }
-       }
-@@ -2351,46 +2222,46 @@
- }
- /* calculate percentage of total accesses on a ldn */
--static int ldn_access_load(int host_index, int ldn)
-+static int ldn_access_load(struct Scsi_Host *shpnt, int ldn)
- {
--      if (IBM_DS(host_index).total_accesses == 0)
-+      if (IBM_DS(shpnt).total_accesses == 0)
-               return (0);
--      if (IBM_DS(host_index).ldn_access[ldn] == 0)
-+      if (IBM_DS(shpnt).ldn_access[ldn] == 0)
-               return (0);
--      return (IBM_DS(host_index).ldn_access[ldn] * 100) / IBM_DS(host_index).total_accesses;
-+      return (IBM_DS(shpnt).ldn_access[ldn] * 100) / IBM_DS(shpnt).total_accesses;
- }
- /* calculate total amount of r/w-accesses */
--static int ldn_access_total_read_write(int host_index)
-+static int ldn_access_total_read_write(struct Scsi_Host *shpnt)
- {
-       int a;
-       int i;
-       a = 0;
-       for (i = 0; i <= MAX_LOG_DEV; i++)
--              a += IBM_DS(host_index).ldn_read_access[i] + IBM_DS(host_index).ldn_write_access[i];
-+              a += IBM_DS(shpnt).ldn_read_access[i] + IBM_DS(shpnt).ldn_write_access[i];
-       return (a);
- }
--static int ldn_access_total_inquiry(int host_index)
-+static int ldn_access_total_inquiry(struct Scsi_Host *shpnt)
- {
-       int a;
-       int i;
-       a = 0;
-       for (i = 0; i <= MAX_LOG_DEV; i++)
--              a += IBM_DS(host_index).ldn_inquiry_access[i];
-+              a += IBM_DS(shpnt).ldn_inquiry_access[i];
-       return (a);
- }
--static int ldn_access_total_modeselect(int host_index)
-+static int ldn_access_total_modeselect(struct Scsi_Host *shpnt)
- {
-       int a;
-       int i;
-       a = 0;
-       for (i = 0; i <= MAX_LOG_DEV; i++)
--              a += IBM_DS(host_index).ldn_modeselect_access[i];
-+              a += IBM_DS(shpnt).ldn_modeselect_access[i];
-       return (a);
- }
-@@ -2398,19 +2269,14 @@
- static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
- {
-       int len = 0;
--      int i, id, lun, host_index;
-+      int i, id, lun;
-       unsigned long flags;
-       int max_pun;
--      for (i = 0; hosts[i] && hosts[i] != shpnt; i++);
-       
--      spin_lock_irqsave(hosts[i]->host_lock, flags);  /* Check it */
--      host_index = i;
--      if (!shpnt) {
--              len += sprintf(buffer + len, "\nIBM MCA SCSI: Can't find adapter");
--              return len;
--      }
--      max_pun = subsystem_maxid(host_index);
-+      spin_lock_irqsave(shpnt->host_lock, flags);     /* Check it */
++      /* BTS */
++      else if (OPCODE_BTS(op)) {
++              if (trap_registers.sr & SR_T_BIT_MASK)
++                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
++              else
++                      addr = trap_registers.pc + 4;   /* Not in delay slot */
++      }
 +
-+      max_pun = subsystem_maxid(shpnt);
-       len += sprintf(buffer + len, "\n             IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n", IBMMCA_SCSI_DRIVER_VERSION);
-       len += sprintf(buffer + len, " SCSI Access-Statistics:\n");
-@@ -2421,40 +2287,40 @@
-       len += sprintf(buffer + len, "               Multiple LUN probing.....: No\n");
- #endif
-       len += sprintf(buffer + len, "               This Hostnumber..........: %d\n", shpnt->host_no);
--      len += sprintf(buffer + len, "               Base I/O-Port............: 0x%x\n", (unsigned int) (IM_CMD_REG(host_index)));
-+      len += sprintf(buffer + len, "               Base I/O-Port............: 0x%x\n", (unsigned int) (IM_CMD_REG(shpnt)));
-       len += sprintf(buffer + len, "               (Shared) IRQ.............: %d\n", IM_IRQ);
--      len += sprintf(buffer + len, "               Total Interrupts.........: %d\n", IBM_DS(host_index).total_interrupts);
--      len += sprintf(buffer + len, "               Total SCSI Accesses......: %d\n", IBM_DS(host_index).total_accesses);
--      len += sprintf(buffer + len, "               Total short SCBs.........: %d\n", IBM_DS(host_index).scbs);
--      len += sprintf(buffer + len, "               Total long SCBs..........: %d\n", IBM_DS(host_index).long_scbs);
--      len += sprintf(buffer + len, "                 Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(host_index));
--      len += sprintf(buffer + len, "                 Total SCSI Inquiries...: %d\n", ldn_access_total_inquiry(host_index));
--      len += sprintf(buffer + len, "                 Total SCSI Modeselects.: %d\n", ldn_access_total_modeselect(host_index));
--      len += sprintf(buffer + len, "                 Total SCSI other cmds..: %d\n", IBM_DS(host_index).total_accesses - ldn_access_total_read_write(host_index)
--                     - ldn_access_total_modeselect(host_index)
--                     - ldn_access_total_inquiry(host_index));
--      len += sprintf(buffer + len, "               Total SCSI command fails.: %d\n\n", IBM_DS(host_index).total_errors);
-+      len += sprintf(buffer + len, "               Total Interrupts.........: %d\n", IBM_DS(shpnt).total_interrupts);
-+      len += sprintf(buffer + len, "               Total SCSI Accesses......: %d\n", IBM_DS(shpnt).total_accesses);
-+      len += sprintf(buffer + len, "               Total short SCBs.........: %d\n", IBM_DS(shpnt).scbs);
-+      len += sprintf(buffer + len, "               Total long SCBs..........: %d\n", IBM_DS(shpnt).long_scbs);
-+      len += sprintf(buffer + len, "                 Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(shpnt));
-+      len += sprintf(buffer + len, "                 Total SCSI Inquiries...: %d\n", ldn_access_total_inquiry(shpnt));
-+      len += sprintf(buffer + len, "                 Total SCSI Modeselects.: %d\n", ldn_access_total_modeselect(shpnt));
-+      len += sprintf(buffer + len, "                 Total SCSI other cmds..: %d\n", IBM_DS(shpnt).total_accesses - ldn_access_total_read_write(shpnt)
-+                     - ldn_access_total_modeselect(shpnt)
-+                     - ldn_access_total_inquiry(shpnt));
-+      len += sprintf(buffer + len, "               Total SCSI command fails.: %d\n\n", IBM_DS(shpnt).total_errors);
-       len += sprintf(buffer + len, " Logical-Device-Number (LDN) Access-Statistics:\n");
-       len += sprintf(buffer + len, "         LDN | Accesses [%%] |   READ    |   WRITE   | ASSIGNMENTS\n");
-       len += sprintf(buffer + len, "        -----|--------------|-----------|-----------|--------------\n");
-       for (i = 0; i <= MAX_LOG_DEV; i++)
--              len += sprintf(buffer + len, "         %2X  |    %3d       |  %8d |  %8d | %8d\n", i, ldn_access_load(host_index, i), IBM_DS(host_index).ldn_read_access[i], IBM_DS(host_index).ldn_write_access[i], IBM_DS(host_index).ldn_assignments[i]);
-+              len += sprintf(buffer + len, "         %2X  |    %3d       |  %8d |  %8d | %8d\n", i, ldn_access_load(shpnt, i), IBM_DS(shpnt).ldn_read_access[i], IBM_DS(shpnt).ldn_write_access[i], IBM_DS(shpnt).ldn_assignments[i]);
-       len += sprintf(buffer + len, "        -----------------------------------------------------------\n\n");
-       len += sprintf(buffer + len, " Dynamical-LDN-Assignment-Statistics:\n");
--      len += sprintf(buffer + len, "               Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(host_index).total_scsi_devices);
--      len += sprintf(buffer + len, "               Dynamical Assignment necessary...: %s\n", IBM_DS(host_index).dyn_flag ? "Yes" : "No ");
--      len += sprintf(buffer + len, "               Next LDN to be assigned..........: 0x%x\n", next_ldn(host_index));
--      len += sprintf(buffer + len, "               Dynamical assignments done yet...: %d\n", IBM_DS(host_index).dynamical_assignments);
-+      len += sprintf(buffer + len, "               Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(shpnt).total_scsi_devices);
-+      len += sprintf(buffer + len, "               Dynamical Assignment necessary...: %s\n", IBM_DS(shpnt).dyn_flag ? "Yes" : "No ");
-+      len += sprintf(buffer + len, "               Next LDN to be assigned..........: 0x%x\n", next_ldn(shpnt));
-+      len += sprintf(buffer + len, "               Dynamical assignments done yet...: %d\n", IBM_DS(shpnt).dynamical_assignments);
-       len += sprintf(buffer + len, "\n Current SCSI-Device-Mapping:\n");
-       len += sprintf(buffer + len, "        Physical SCSI-Device Map               Logical SCSI-Device Map\n");
-       len += sprintf(buffer + len, "    ID\\LUN  0  1  2  3  4  5  6  7       ID\\LUN  0  1  2  3  4  5  6  7\n");
-       for (id = 0; id < max_pun; id++) {
-               len += sprintf(buffer + len, "    %2d     ", id);
-               for (lun = 0; lun < 8; lun++)
--                      len += sprintf(buffer + len, "%2s ", ti_p(get_scsi(host_index)[id][lun]));
-+                      len += sprintf(buffer + len, "%2s ", ti_p(get_scsi(shpnt)[id][lun]));
-               len += sprintf(buffer + len, "      %2d     ", id);
-               for (lun = 0; lun < 8; lun++)
--                      len += sprintf(buffer + len, "%2s ", ti_l(get_ldn(host_index)[id][lun]));
-+                      len += sprintf(buffer + len, "%2s ", ti_l(get_ldn(shpnt)[id][lun]));
-               len += sprintf(buffer + len, "\n");
-       }
-@@ -2488,20 +2354,31 @@
- __setup("ibmmcascsi=", option_setup);
--static struct scsi_host_template driver_template = {
--          .proc_name      = "ibmmca",
--        .proc_info      = ibmmca_proc_info,
--          .name           = "IBM SCSI-Subsystem",
--          .detect         = ibmmca_detect,
--          .release        = ibmmca_release,
--          .queuecommand   = ibmmca_queuecommand,
--        .eh_abort_handler = ibmmca_abort,
--        .eh_host_reset_handler = ibmmca_host_reset,
--          .bios_param     = ibmmca_biosparam,
--          .can_queue      = 16,
--          .this_id        = 7,
--          .sg_tablesize   = 16,
--          .cmd_per_lun    = 1,
--          .use_clustering = ENABLE_CLUSTERING,
-+static struct mca_driver ibmmca_driver = {
-+      .id_table = ibmmca_id_table,
-+      .driver = {
-+              .name   = "ibmmca",
-+              .bus    = &mca_bus_type,
-+              .probe  = ibmmca_probe,
-+              .remove = __devexit_p(ibmmca_remove),
-+      },
- };
--#include "scsi_module.c"
++      /* BF */
++      else if (OPCODE_BF(op)) {
++              if (!(trap_registers.sr & SR_T_BIT_MASK))
++                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
++              else
++                      addr = trap_registers.pc + 2;
++      }
++
++      /* BFS */
++      else if (OPCODE_BFS(op)) {
++              if (!(trap_registers.sr & SR_T_BIT_MASK))
++                      addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
++              else
++                      addr = trap_registers.pc + 4;   /* Not in delay slot */
++      }
++
++      /* BRA */
++      else if (OPCODE_BRA(op))
++              addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op);
++
++      /* BRAF */
++      else if (OPCODE_BRAF(op))
++              addr = trap_registers.pc + 4
++                  + trap_registers.regs[OPCODE_BRAF_REG(op)];
++
++      /* BSR */
++      else if (OPCODE_BSR(op))
++              addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op);
++
++      /* BSRF */
++      else if (OPCODE_BSRF(op))
++              addr = trap_registers.pc + 4
++                  + trap_registers.regs[OPCODE_BSRF_REG(op)];
++
++      /* JMP */
++      else if (OPCODE_JMP(op))
++              addr = trap_registers.regs[OPCODE_JMP_REG(op)];
++
++      /* JSR */
++      else if (OPCODE_JSR(op))
++              addr = trap_registers.regs[OPCODE_JSR_REG(op)];
++
++      /* RTS */
++      else if (OPCODE_RTS(op))
++              addr = trap_registers.pr;
++
++      /* RTE */
++      else if (OPCODE_RTE(op))
++              addr = trap_registers.regs[15];
++
++      /* Other */
++      else
++              addr = trap_registers.pc + 2;
++
++      kgdb_flush_icache_range(addr, addr + 2);
++      return (short *) addr;
++}
 +
-+static int __init ibmmca_init(void)
++/* Set up a single-step.  Replace the instruction immediately after the
++   current instruction (i.e. next in the expected flow of control) with a
++   trap instruction, so that returning will cause only a single instruction
++   to be executed. Note that this model is slightly broken for instructions
++   with delay slots (e.g. B[TF]S, BSR, BRA etc), where both the branch
++   and the instruction in the delay slot will be executed. */
++static void do_single_step(void)
 +{
-+#ifdef MODULE
-+      /* If the driver is run as module, read from conf.modules or cmd-line */
-+      if (boot_options)
-+              option_setup(boot_options);
-+#endif
++      unsigned short *addr = 0;
++
++      /* Determine where the target instruction will send us to */
++      addr = get_step_address();
++      stepped_address = (int)addr;
 +
-+      return mca_register_driver_integrated(&ibmmca_driver, MCA_INTEGSCSI);
++      /* Replace it */
++      stepped_opcode = *(short *)addr;
++      *addr = STEP_OPCODE;
++
++      /* Flush and return */
++      kgdb_flush_icache_range((long) addr, (long) addr + 2);
++      return;
 +}
 +
-+static void __exit ibmmca_exit(void)
++/* Undo a single step */
++static void undo_single_step(void)
 +{
-+      mca_unregister_driver(&ibmmca_driver);
++      /* If we have stepped, put back the old instruction */
++      /* Use stepped_address in case we stopped elsewhere */
++      if (stepped_opcode != 0) {
++              *(short*)stepped_address = stepped_opcode;
++              kgdb_flush_icache_range(stepped_address, stepped_address + 2);
++      }
++      stepped_opcode = 0;
 +}
 +
-+module_init(ibmmca_init);
-+module_exit(ibmmca_exit);
-diff -Nurb linux-2.6.22-570/drivers/scsi/ibmmca.h linux-2.6.22-590/drivers/scsi/ibmmca.h
---- linux-2.6.22-570/drivers/scsi/ibmmca.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/ibmmca.h     1969-12-31 19:00:00.000000000 -0500
-@@ -1,21 +0,0 @@
--/*
-- * Low Level Driver for the IBM Microchannel SCSI Subsystem
-- * (Headerfile, see Documentation/scsi/ibmmca.txt for description of the
-- * IBM MCA SCSI-driver.
-- * For use under the GNU General Public License within the Linux-kernel project.
-- * This include file works only correctly with kernel 2.4.0 or higher!!! */
--
--#ifndef _IBMMCA_H
--#define _IBMMCA_H
--
--/* Common forward declarations for all Linux-versions: */
--
--/* Interfaces to the midlevel Linux SCSI driver */
--static int ibmmca_detect (struct scsi_host_template *);
--static int ibmmca_release (struct Scsi_Host *);
--static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
--static int ibmmca_abort (Scsi_Cmnd *);
--static int ibmmca_host_reset (Scsi_Cmnd *);
--static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *);
--
--#endif /* _IBMMCA_H */
-diff -Nurb linux-2.6.22-570/drivers/scsi/ibmvscsi/ibmvscsi.c linux-2.6.22-590/drivers/scsi/ibmvscsi/ibmvscsi.c
---- linux-2.6.22-570/drivers/scsi/ibmvscsi/ibmvscsi.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/ibmvscsi/ibmvscsi.c  2008-01-02 13:56:37.000000000 -0500
-@@ -173,8 +173,7 @@
-               }
-       }
-       if (in_use)
--              printk(KERN_WARNING
--                     "ibmvscsi: releasing event pool with %d "
-+              dev_warn(hostdata->dev, "releasing event pool with %d "
-                      "events still in use?\n", in_use);
-       kfree(pool->events);
-       dma_free_coherent(hostdata->dev,
-@@ -210,14 +209,12 @@
-                                      struct srp_event_struct *evt)
- {
-       if (!valid_event_struct(pool, evt)) {
--              printk(KERN_ERR
--                     "ibmvscsi: Freeing invalid event_struct %p "
-+              dev_err(evt->hostdata->dev, "Freeing invalid event_struct %p "
-                      "(not in pool %p)\n", evt, pool->events);
-               return;
-       }
-       if (atomic_inc_return(&evt->free) != 1) {
--              printk(KERN_ERR
--                     "ibmvscsi: Freeing event_struct %p "
-+              dev_err(evt->hostdata->dev, "Freeing event_struct %p "
-                      "which is not in use!\n", evt);
-               return;
-       }
-@@ -408,13 +405,6 @@
-               return 1;
-       }
--      if (sg_mapped > SG_ALL) {
--              printk(KERN_ERR
--                     "ibmvscsi: More than %d mapped sg entries, got %d\n",
--                     SG_ALL, sg_mapped);
--              return 0;
--      }
--
-       indirect->table_desc.va = 0;
-       indirect->table_desc.len = sg_mapped * sizeof(struct srp_direct_buf);
-       indirect->table_desc.key = 0;
-@@ -433,10 +423,9 @@
-                                          SG_ALL * sizeof(struct srp_direct_buf),
-                                          &evt_struct->ext_list_token, 0);
-               if (!evt_struct->ext_list) {
--                      printk(KERN_ERR
--                             "ibmvscsi: Can't allocate memory for indirect table\n");
-+                      sdev_printk(KERN_ERR, cmd->device,
-+                                  "Can't allocate memory for indirect table\n");
-                       return 0;
--                      
-               }
-       }
-@@ -471,8 +460,8 @@
-                              cmd->request_bufflen,
-                              DMA_BIDIRECTIONAL);
-       if (dma_mapping_error(data->va)) {
--              printk(KERN_ERR
--                     "ibmvscsi: Unable to map request_buffer for command!\n");
-+              sdev_printk(KERN_ERR, cmd->device,
-+                          "Unable to map request_buffer for command!\n");
-               return 0;
-       }
-       data->len = cmd->request_bufflen;
-@@ -503,12 +492,12 @@
-       case DMA_NONE:
-               return 1;
-       case DMA_BIDIRECTIONAL:
--              printk(KERN_ERR
--                     "ibmvscsi: Can't map DMA_BIDIRECTIONAL to read/write\n");
-+              sdev_printk(KERN_ERR, cmd->device,
-+                          "Can't map DMA_BIDIRECTIONAL to read/write\n");
-               return 0;
-       default:
--              printk(KERN_ERR
--                     "ibmvscsi: Unknown data direction 0x%02x; can't map!\n",
-+              sdev_printk(KERN_ERR, cmd->device,
-+                          "Unknown data direction 0x%02x; can't map!\n",
-                      cmd->sc_data_direction);
-               return 0;
-       }
-@@ -520,6 +509,70 @@
-       return map_single_data(cmd, srp_cmd, dev);
- }
-+/**
-+ * purge_requests: Our virtual adapter just shut down.  purge any sent requests
-+ * @hostdata:    the adapter
-+ */
-+static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
++/* Send a signal message */
++static void send_signal_msg(const int signum)
 +{
-+      struct srp_event_struct *tmp_evt, *pos;
-+      unsigned long flags;
++      out_buffer[0] = 'S';
++      out_buffer[1] = highhex(signum);
++      out_buffer[2] = lowhex(signum);
++      out_buffer[3] = 0;
++      put_packet(out_buffer);
++}
 +
-+      spin_lock_irqsave(hostdata->host->host_lock, flags);
-+      list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
-+              list_del(&tmp_evt->list);
-+              del_timer(&tmp_evt->timer);
-+              if (tmp_evt->cmnd) {
-+                      tmp_evt->cmnd->result = (error_code << 16);
-+                      unmap_cmd_data(&tmp_evt->iu.srp.cmd,
-+                                     tmp_evt,
-+                                     tmp_evt->hostdata->dev);
-+                      if (tmp_evt->cmnd_done)
-+                              tmp_evt->cmnd_done(tmp_evt->cmnd);
-+              } else if (tmp_evt->done)
-+                      tmp_evt->done(tmp_evt);
-+              free_event_struct(&tmp_evt->hostdata->pool, tmp_evt);
-+      }
-+      spin_unlock_irqrestore(hostdata->host->host_lock, flags);
++/* Reply that all was well */
++static void send_ok_msg(void)
++{
++      strcpy(out_buffer, "OK");
++      put_packet(out_buffer);
 +}
 +
-+/**
-+ * ibmvscsi_reset_host - Reset the connection to the server
-+ * @hostdata: struct ibmvscsi_host_data to reset
-+*/
-+static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
++/* Reply that an error occurred */
++static void send_err_msg(void)
 +{
-+      scsi_block_requests(hostdata->host);
-+      atomic_set(&hostdata->request_limit, 0);
++      strcpy(out_buffer, "E01");
++      put_packet(out_buffer);
++}
 +
-+      purge_requests(hostdata, DID_ERROR);
-+      if ((ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata)) ||
-+          (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0)) ||
-+          (vio_enable_interrupts(to_vio_dev(hostdata->dev)))) {
-+              atomic_set(&hostdata->request_limit, -1);
-+              dev_err(hostdata->dev, "error after reset\n");
-+      }
++/* Empty message indicates unrecognised command */
++static void send_empty_msg(void)
++{
++      put_packet("");
++}
++
++/* Read memory due to 'm' message */
++static void read_mem_msg(void)
++{
++      char *ptr;
++      int addr;
++      int length;
++
++      /* Jmp, disable bus error handler */
++      if (setjmp(rem_com_env) == 0) {
++
++              kgdb_nofault = 1;
++
++              /* Walk through, have m<addr>,<length> */
++              ptr = &in_buffer[1];
++              if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
++                      if (hex_to_int(&ptr, &length)) {
++                              ptr = 0;
++                              if (length * 2 > OUTBUFMAX)
++                                      length = OUTBUFMAX / 2;
++                              mem_to_hex((char *) addr, out_buffer, length);
++                      }
++              if (ptr)
++                      send_err_msg();
++              else
++                      put_packet(out_buffer);
++      } else
++              send_err_msg();
 +
-+      scsi_unblock_requests(hostdata->host);
++      /* Restore bus error handler */
++      kgdb_nofault = 0;
 +}
 +
-+/**
-+ * ibmvscsi_timeout - Internal command timeout handler
-+ * @evt_struct:       struct srp_event_struct that timed out
-+ *
-+ * Called when an internally generated command times out
-+*/
-+static void ibmvscsi_timeout(struct srp_event_struct *evt_struct)
++/* Write memory due to 'M' or 'X' message */
++static void write_mem_msg(int binary)
 +{
-+      struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;
++      char *ptr;
++      int addr;
++      int length;
++
++      if (setjmp(rem_com_env) == 0) {
 +
-+      dev_err(hostdata->dev, "Command timed out (%x). Resetting connection\n",
-+              evt_struct->iu.srp.cmd.opcode);
++              kgdb_nofault = 1;
 +
-+      ibmvscsi_reset_host(hostdata);
++              /* Walk through, have M<addr>,<length>:<data> */
++              ptr = &in_buffer[1];
++              if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
++                      if (hex_to_int(&ptr, &length) && (*ptr++ == ':')) {
++                              if (binary)
++                                      ebin_to_mem(ptr, (char*)addr, length);
++                              else
++                                      hex_to_mem(ptr, (char*)addr, length);
++                              kgdb_flush_icache_range(addr, addr + length);
++                              ptr = 0;
++                              send_ok_msg();
++                      }
++              if (ptr)
++                      send_err_msg();
++      } else
++              send_err_msg();
++
++      /* Restore bus error handler */
++      kgdb_nofault = 0;
 +}
 +
++/* Continue message  */
++static void continue_msg(void)
++{
++      /* Try to read optional parameter, PC unchanged if none */
++      char *ptr = &in_buffer[1];
++      int addr;
 +
- /* ------------------------------------------------------------
-  * Routines for sending and receiving SRPs
-  */
-@@ -527,12 +580,14 @@
-  * ibmvscsi_send_srp_event: - Transforms event to u64 array and calls send_crq()
-  * @evt_struct:       evt_struct to be sent
-  * @hostdata: ibmvscsi_host_data of host
-+ * @timeout:  timeout in seconds - 0 means do not time command
-  *
-  * Returns the value returned from ibmvscsi_send_crq(). (Zero for success)
-  * Note that this routine assumes that host_lock is held for synchronization
- */
- static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
--                                 struct ibmvscsi_host_data *hostdata)
-+                                 struct ibmvscsi_host_data *hostdata,
-+                                 unsigned long timeout)
- {
-       u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
-       int request_status;
-@@ -588,12 +643,20 @@
-        */
-       list_add_tail(&evt_struct->list, &hostdata->sent);
-+      init_timer(&evt_struct->timer);
-+      if (timeout) {
-+              evt_struct->timer.data = (unsigned long) evt_struct;
-+              evt_struct->timer.expires = jiffies + (timeout * HZ);
-+              evt_struct->timer.function = (void (*)(unsigned long))ibmvscsi_timeout;
-+              add_timer(&evt_struct->timer);
-+      }
++      if (hex_to_int(&ptr, &addr))
++              trap_registers.pc = addr;
++}
 +
-       if ((rc =
-            ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
-               list_del(&evt_struct->list);
-+              del_timer(&evt_struct->timer);
--              printk(KERN_ERR "ibmvscsi: send error %d\n",
--                     rc);
-+              dev_err(hostdata->dev, "send error %d\n", rc);
-               atomic_inc(&hostdata->request_limit);
-               goto send_error;
-       }
-@@ -634,9 +697,8 @@
-       if (unlikely(rsp->opcode != SRP_RSP)) {
-               if (printk_ratelimit())
--                      printk(KERN_WARNING 
--                             "ibmvscsi: bad SRP RSP type %d\n",
--                             rsp->opcode);
-+                      dev_warn(evt_struct->hostdata->dev,
-+                               "bad SRP RSP type %d\n", rsp->opcode);
-       }
-       
-       if (cmnd) {
-@@ -697,7 +759,7 @@
-       srp_cmd->lun = ((u64) lun) << 48;
-       if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
--              printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n");
-+              sdev_printk(KERN_ERR, cmnd->device, "couldn't convert cmd to srp_cmd\n");
-               free_event_struct(&hostdata->pool, evt_struct);
-               return SCSI_MLQUEUE_HOST_BUSY;
-       }
-@@ -722,7 +784,7 @@
-                       offsetof(struct srp_indirect_buf, desc_list);
-       }
--      return ibmvscsi_send_srp_event(evt_struct, hostdata);
-+      return ibmvscsi_send_srp_event(evt_struct, hostdata, 0);
- }
- /* ------------------------------------------------------------
-@@ -744,10 +806,10 @@
-                        DMA_BIDIRECTIONAL);
-       if (evt_struct->xfer_iu->mad.adapter_info.common.status) {
--              printk("ibmvscsi: error %d getting adapter info\n",
-+              dev_err(hostdata->dev, "error %d getting adapter info\n",
-                      evt_struct->xfer_iu->mad.adapter_info.common.status);
-       } else {
--              printk("ibmvscsi: host srp version: %s, "
-+              dev_info(hostdata->dev, "host srp version: %s, "
-                      "host partition %s (%d), OS %d, max io %u\n",
-                      hostdata->madapter_info.srp_version,
-                      hostdata->madapter_info.partition_name,
-@@ -761,10 +823,9 @@
-               
-               if (hostdata->madapter_info.os_type == 3 &&
-                   strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) {
--                      printk("ibmvscsi: host (Ver. %s) doesn't support large"
--                             "transfers\n",
-+                      dev_err(hostdata->dev, "host (Ver. %s) doesn't support large transfers\n",
-                              hostdata->madapter_info.srp_version);
--                      printk("ibmvscsi: limiting scatterlists to %d\n",
-+                      dev_err(hostdata->dev, "limiting scatterlists to %d\n",
-                              MAX_INDIRECT_BUFS);
-                       hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS;
-               }
-@@ -784,12 +845,13 @@
- {
-       struct viosrp_adapter_info *req;
-       struct srp_event_struct *evt_struct;
-+      unsigned long flags;
-       dma_addr_t addr;
-       evt_struct = get_event_struct(&hostdata->pool);
-       if (!evt_struct) {
--              printk(KERN_ERR "ibmvscsi: couldn't allocate an event "
--                     "for ADAPTER_INFO_REQ!\n");
-+              dev_err(hostdata->dev,
-+                      "couldn't allocate an event for ADAPTER_INFO_REQ!\n");
-               return;
-       }
-@@ -809,20 +871,20 @@
-                                           DMA_BIDIRECTIONAL);
-       if (dma_mapping_error(req->buffer)) {
--              printk(KERN_ERR
--                     "ibmvscsi: Unable to map request_buffer "
--                     "for adapter_info!\n");
-+              dev_err(hostdata->dev, "Unable to map request_buffer for adapter_info!\n");
-               free_event_struct(&hostdata->pool, evt_struct);
-               return;
-       }
-       
--      if (ibmvscsi_send_srp_event(evt_struct, hostdata)) {
--              printk(KERN_ERR "ibmvscsi: couldn't send ADAPTER_INFO_REQ!\n");
-+      spin_lock_irqsave(hostdata->host->host_lock, flags);
-+      if (ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2)) {
-+              dev_err(hostdata->dev, "couldn't send ADAPTER_INFO_REQ!\n");
-               dma_unmap_single(hostdata->dev,
-                                addr,
-                                sizeof(hostdata->madapter_info),
-                                DMA_BIDIRECTIONAL);
-       }
-+      spin_unlock_irqrestore(hostdata->host->host_lock, flags);
- };
- /**
-@@ -839,24 +901,23 @@
-       case SRP_LOGIN_RSP:     /* it worked! */
-               break;
-       case SRP_LOGIN_REJ:     /* refused! */
--              printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REJ reason %u\n",
-+              dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n",
-                      evt_struct->xfer_iu->srp.login_rej.reason);
-               /* Login failed.  */
-               atomic_set(&hostdata->request_limit, -1);
-               return;
-       default:
--              printk(KERN_ERR
--                     "ibmvscsi: Invalid login response typecode 0x%02x!\n",
-+              dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n",
-                      evt_struct->xfer_iu->srp.login_rsp.opcode);
-               /* Login failed.  */
-               atomic_set(&hostdata->request_limit, -1);
-               return;
-       }
--      printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
-+      dev_info(hostdata->dev, "SRP_LOGIN succeeded\n");
-       if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta < 0)
--              printk(KERN_ERR "ibmvscsi: Invalid request_limit.\n");
-+              dev_err(hostdata->dev, "Invalid request_limit.\n");
-       /* Now we know what the real request-limit is.
-        * This value is set rather than added to request_limit because
-@@ -885,8 +946,7 @@
-       struct srp_login_req *login;
-       struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool);
-       if (!evt_struct) {
--              printk(KERN_ERR
--                     "ibmvscsi: couldn't allocate an event for login req!\n");
-+              dev_err(hostdata->dev, "couldn't allocate an event for login req!\n");
-               return FAILED;
-       }
-@@ -907,9 +967,9 @@
-        */
-       atomic_set(&hostdata->request_limit, 1);
--      rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
-+      rc = ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2);
-       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
--      printk("ibmvscsic: sent SRP login\n");
-+      dev_info(hostdata->dev, "sent SRP login\n");
-       return rc;
- };
-@@ -958,13 +1018,13 @@
-       if (!found_evt) {
-               spin_unlock_irqrestore(hostdata->host->host_lock, flags);
--              return FAILED;
-+              return SUCCESS;
-       }
-       evt = get_event_struct(&hostdata->pool);
-       if (evt == NULL) {
-               spin_unlock_irqrestore(hostdata->host->host_lock, flags);
--              printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n");
-+              sdev_printk(KERN_ERR, cmd->device, "failed to allocate abort event\n");
-               return FAILED;
-       }
-       
-@@ -982,15 +1042,16 @@
-       tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK;
-       tsk_mgmt->task_tag = (u64) found_evt;
--      printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
-+      sdev_printk(KERN_INFO, cmd->device, "aborting command. lun 0x%lx, tag 0x%lx\n",
-              tsk_mgmt->lun, tsk_mgmt->task_tag);
-       evt->sync_srp = &srp_rsp;
-       init_completion(&evt->comp);
--      rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
-+      rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
-       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
-       if (rsp_rc != 0) {
--              printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
-+              sdev_printk(KERN_ERR, cmd->device,
-+                          "failed to send abort() event. rc=%d\n", rsp_rc);
-               return FAILED;
-       }
-@@ -999,8 +1060,7 @@
-       /* make sure we got a good response */
-       if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) {
-               if (printk_ratelimit())
--                      printk(KERN_WARNING 
--                             "ibmvscsi: abort bad SRP RSP type %d\n",
-+                      sdev_printk(KERN_WARNING, cmd->device, "abort bad SRP RSP type %d\n",
-                              srp_rsp.srp.rsp.opcode);
-               return FAILED;
-       }
-@@ -1012,10 +1072,9 @@
-       if (rsp_rc) {
-               if (printk_ratelimit())
--                      printk(KERN_WARNING 
--                             "ibmvscsi: abort code %d for task tag 0x%lx\n",
--                             rsp_rc,
--                             tsk_mgmt->task_tag);
-+                      sdev_printk(KERN_WARNING, cmd->device,
-+                                  "abort code %d for task tag 0x%lx\n",
-+                                  rsp_rc, tsk_mgmt->task_tag);
-               return FAILED;
-       }
-@@ -1034,14 +1093,12 @@
-       if (found_evt == NULL) {
-               spin_unlock_irqrestore(hostdata->host->host_lock, flags);
--              printk(KERN_INFO
--                     "ibmvscsi: aborted task tag 0x%lx completed\n",
-+              sdev_printk(KERN_INFO, cmd->device, "aborted task tag 0x%lx completed\n",
-                      tsk_mgmt->task_tag);
-               return SUCCESS;
-       }
--      printk(KERN_INFO
--             "ibmvscsi: successfully aborted task tag 0x%lx\n",
-+      sdev_printk(KERN_INFO, cmd->device, "successfully aborted task tag 0x%lx\n",
-              tsk_mgmt->task_tag);
-       cmd->result = (DID_ABORT << 16);
-@@ -1076,7 +1133,7 @@
-       evt = get_event_struct(&hostdata->pool);
-       if (evt == NULL) {
-               spin_unlock_irqrestore(hostdata->host->host_lock, flags);
--              printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n");
-+              sdev_printk(KERN_ERR, cmd->device, "failed to allocate reset event\n");
-               return FAILED;
-       }
-       
-@@ -1093,15 +1150,16 @@
-       tsk_mgmt->lun = ((u64) lun) << 48;
-       tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET;
--      printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
-+      sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%lx\n",
-              tsk_mgmt->lun);
-       evt->sync_srp = &srp_rsp;
-       init_completion(&evt->comp);
--      rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
-+      rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
-       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
-       if (rsp_rc != 0) {
--              printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
-+              sdev_printk(KERN_ERR, cmd->device,
-+                          "failed to send reset event. rc=%d\n", rsp_rc);
-               return FAILED;
-       }
-@@ -1110,8 +1168,7 @@
-       /* make sure we got a good response */
-       if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) {
-               if (printk_ratelimit())
--                      printk(KERN_WARNING 
--                             "ibmvscsi: reset bad SRP RSP type %d\n",
-+                      sdev_printk(KERN_WARNING, cmd->device, "reset bad SRP RSP type %d\n",
-                              srp_rsp.srp.rsp.opcode);
-               return FAILED;
-       }
-@@ -1123,8 +1180,8 @@
-       if (rsp_rc) {
-               if (printk_ratelimit())
--                      printk(KERN_WARNING 
--                             "ibmvscsi: reset code %d for task tag 0x%lx\n",
-+                      sdev_printk(KERN_WARNING, cmd->device,
-+                                  "reset code %d for task tag 0x%lx\n",
-                              rsp_rc, tsk_mgmt->task_tag);
-               return FAILED;
-       }
-@@ -1154,32 +1211,30 @@
- }
- /**
-- * purge_requests: Our virtual adapter just shut down.  purge any sent requests
-- * @hostdata:    the adapter
-- */
--static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
-+ * ibmvscsi_eh_host_reset_handler - Reset the connection to the server
-+ * @cmd:      struct scsi_cmnd having problems
-+*/
-+static int ibmvscsi_eh_host_reset_handler(struct scsi_cmnd *cmd)
- {
--      struct srp_event_struct *tmp_evt, *pos;
--      unsigned long flags;
-+      unsigned long wait_switch = 0;
-+      struct ibmvscsi_host_data *hostdata =
-+              (struct ibmvscsi_host_data *)cmd->device->host->hostdata;
--      spin_lock_irqsave(hostdata->host->host_lock, flags);
--      list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
--              list_del(&tmp_evt->list);
--              if (tmp_evt->cmnd) {
--                      tmp_evt->cmnd->result = (error_code << 16);
--                      unmap_cmd_data(&tmp_evt->iu.srp.cmd, 
--                                     tmp_evt, 
--                                     tmp_evt->hostdata->dev);
--                      if (tmp_evt->cmnd_done)
--                              tmp_evt->cmnd_done(tmp_evt->cmnd);
--              } else {
--                      if (tmp_evt->done) {
--                              tmp_evt->done(tmp_evt);
--                      }
--              }
--              free_event_struct(&tmp_evt->hostdata->pool, tmp_evt);
-+      dev_err(hostdata->dev, "Resetting connection due to error recovery\n");
++/* Continue message with signal */
++static void continue_with_sig_msg(void)
++{
++      int signal;
++      char *ptr = &in_buffer[1];
++      int addr;
 +
-+      ibmvscsi_reset_host(hostdata);
++      /* Report limitation */
++      kgdb_to_gdb("Cannot force signal in kgdb, continuing anyway.\n");
 +
-+      for (wait_switch = jiffies + (init_timeout * HZ);
-+           time_before(jiffies, wait_switch) &&
-+                   atomic_read(&hostdata->request_limit) < 2;) {
++      /* Signal */
++      hex_to_int(&ptr, &signal);
++      if (*ptr == ';')
++              ptr++;
 +
-+              msleep(10);
-       }
--      spin_unlock_irqrestore(hostdata->host->host_lock, flags);
++      /* Optional address */
++      if (hex_to_int(&ptr, &addr))
++              trap_registers.pc = addr;
++}
 +
-+      if (atomic_read(&hostdata->request_limit) <= 0)
-+              return FAILED;
++/* Step message */
++static void step_msg(void)
++{
++      continue_msg();
++      do_single_step();
++}
 +
-+      return SUCCESS;
- }
- /**
-@@ -1191,6 +1246,7 @@
- void ibmvscsi_handle_crq(struct viosrp_crq *crq,
-                        struct ibmvscsi_host_data *hostdata)
- {
-+      long rc;
-       unsigned long flags;
-       struct srp_event_struct *evt_struct =
-           (struct srp_event_struct *)crq->IU_data_ptr;
-@@ -1198,27 +1254,25 @@
-       case 0xC0:              /* initialization */
-               switch (crq->format) {
-               case 0x01:      /* Initialization message */
--                      printk(KERN_INFO "ibmvscsi: partner initialized\n");
-+                      dev_info(hostdata->dev, "partner initialized\n");
-                       /* Send back a response */
--                      if (ibmvscsi_send_crq(hostdata,
--                                            0xC002000000000000LL, 0) == 0) {
-+                      if ((rc = ibmvscsi_send_crq(hostdata,
-+                                                  0xC002000000000000LL, 0)) == 0) {
-                               /* Now login */
-                               send_srp_login(hostdata);
-                       } else {
--                              printk(KERN_ERR
--                                     "ibmvscsi: Unable to send init rsp\n");
-+                              dev_err(hostdata->dev, "Unable to send init rsp. rc=%ld\n", rc);
-                       }
-                       break;
-               case 0x02:      /* Initialization response */
--                      printk(KERN_INFO
--                             "ibmvscsi: partner initialization complete\n");
-+                      dev_info(hostdata->dev, "partner initialization complete\n");
-                       /* Now login */
-                       send_srp_login(hostdata);
-                       break;
-               default:
--                      printk(KERN_ERR "ibmvscsi: unknown crq message type\n");
-+                      dev_err(hostdata->dev, "unknown crq message type: %d\n", crq->format);
-               }
-               return;
-       case 0xFF:      /* Hypervisor telling us the connection is closed */
-@@ -1226,8 +1280,7 @@
-               atomic_set(&hostdata->request_limit, 0);
-               if (crq->format == 0x06) {
-                       /* We need to re-setup the interpartition connection */
--                      printk(KERN_INFO
--                             "ibmvscsi: Re-enabling adapter!\n");
-+                      dev_info(hostdata->dev, "Re-enabling adapter!\n");
-                       purge_requests(hostdata, DID_REQUEUE);
-                       if ((ibmvscsi_reenable_crq_queue(&hostdata->queue,
-                                                       hostdata)) ||
-@@ -1235,13 +1288,10 @@
-                                              0xC001000000000000LL, 0))) {
-                                       atomic_set(&hostdata->request_limit,
-                                                  -1);
--                                      printk(KERN_ERR
--                                             "ibmvscsi: error after"
--                                             " enable\n");
-+                                      dev_err(hostdata->dev, "error after enable\n");
-                       }
-               } else {
--                      printk(KERN_INFO
--                             "ibmvscsi: Virtual adapter failed rc %d!\n",
-+                      dev_err(hostdata->dev, "Virtual adapter failed rc %d!\n",
-                              crq->format);
-                       purge_requests(hostdata, DID_ERROR);
-@@ -1251,8 +1301,7 @@
-                                              0xC001000000000000LL, 0))) {
-                                       atomic_set(&hostdata->request_limit,
-                                                  -1);
--                                      printk(KERN_ERR
--                                             "ibmvscsi: error after reset\n");
-+                                      dev_err(hostdata->dev, "error after reset\n");
-                       }
-               }
-               scsi_unblock_requests(hostdata->host);
-@@ -1260,8 +1309,7 @@
-       case 0x80:              /* real payload */
-               break;
-       default:
--              printk(KERN_ERR
--                     "ibmvscsi: got an invalid message type 0x%02x\n",
-+              dev_err(hostdata->dev, "got an invalid message type 0x%02x\n",
-                      crq->valid);
-               return;
-       }
-@@ -1271,15 +1319,13 @@
-        * actually sent
-        */
-       if (!valid_event_struct(&hostdata->pool, evt_struct)) {
--              printk(KERN_ERR
--                     "ibmvscsi: returned correlation_token 0x%p is invalid!\n",
-+              dev_err(hostdata->dev, "returned correlation_token 0x%p is invalid!\n",
-                      (void *)crq->IU_data_ptr);
-               return;
-       }
-       if (atomic_read(&evt_struct->free)) {
--              printk(KERN_ERR
--                     "ibmvscsi: received duplicate  correlation_token 0x%p!\n",
-+              dev_err(hostdata->dev, "received duplicate correlation_token 0x%p!\n",
-                      (void *)crq->IU_data_ptr);
-               return;
-       }
-@@ -1288,11 +1334,12 @@
-               atomic_add(evt_struct->xfer_iu->srp.rsp.req_lim_delta,
-                          &hostdata->request_limit);
-+      del_timer(&evt_struct->timer);
++/* Step message with signal */
++static void step_with_sig_msg(void)
++{
++      continue_with_sig_msg();
++      do_single_step();
++}
 +
-       if (evt_struct->done)
-               evt_struct->done(evt_struct);
-       else
--              printk(KERN_ERR
--                     "ibmvscsi: returned done() is NULL; not running it!\n");
-+              dev_err(hostdata->dev, "returned done() is NULL; not running it!\n");
-       /*
-        * Lock the host_lock before messing with these structures, since we
-@@ -1313,13 +1360,13 @@
- {
-       struct viosrp_host_config *host_config;
-       struct srp_event_struct *evt_struct;
-+      unsigned long flags;
-       dma_addr_t addr;
-       int rc;
-       evt_struct = get_event_struct(&hostdata->pool);
-       if (!evt_struct) {
--              printk(KERN_ERR
--                     "ibmvscsi: could't allocate event for HOST_CONFIG!\n");
-+              dev_err(hostdata->dev, "couldn't allocate event for HOST_CONFIG!\n");
-               return -1;
-       }
-@@ -1339,14 +1386,15 @@
-                                                   DMA_BIDIRECTIONAL);
-       if (dma_mapping_error(host_config->buffer)) {
--              printk(KERN_ERR
--                     "ibmvscsi: dma_mapping error " "getting host config\n");
-+              dev_err(hostdata->dev, "dma_mapping error getting host config\n");
-               free_event_struct(&hostdata->pool, evt_struct);
-               return -1;
-       }
-       init_completion(&evt_struct->comp);
--      rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
-+      spin_lock_irqsave(hostdata->host->host_lock, flags);
-+      rc = ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2);
-+      spin_unlock_irqrestore(hostdata->host->host_lock, flags);
-       if (rc == 0)
-               wait_for_completion(&evt_struct->comp);
-       dma_unmap_single(hostdata->dev, addr, length, DMA_BIDIRECTIONAL);
-@@ -1375,6 +1423,23 @@
-       return 0;
- }
-+/**
-+ * ibmvscsi_change_queue_depth - Change the device's queue depth
-+ * @sdev:     scsi device struct
-+ * @qdepth:   depth to set
-+ *
-+ * Return value:
-+ *    actual depth set
-+ **/
-+static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
++/* Send register contents */
++static void send_regs_msg(void)
++{
++      kgdb_regs_to_gdb_regs(&trap_registers, registers);
++      mem_to_hex((char *) registers, out_buffer, NUMREGBYTES);
++      put_packet(out_buffer);
++}
++
++/* Set register contents - currently can't set other thread's registers */
++static void set_regs_msg(void)
++{
++      kgdb_regs_to_gdb_regs(&trap_registers, registers);
++      hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES);
++      gdb_regs_to_kgdb_regs(registers, &trap_registers);
++      send_ok_msg();
++}
++
++#ifdef CONFIG_SH_KGDB_CONSOLE
++/*
++ * Bring up the ports..
++ */
++static int kgdb_serial_setup(void)
++{
++      extern int kgdb_console_setup(struct console *co, char *options);
++      struct console dummy;
++
++      kgdb_console_setup(&dummy, 0);
++
++      return 0;
++}
++#else
++#define kgdb_serial_setup()   0
++#endif
++
++/* The command loop, read and act on requests */
++static void kgdb_command_loop(const int excep_code, const int trapa_value)
 +{
-+      if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN)
-+              qdepth = IBMVSCSI_MAX_CMDS_PER_LUN;
++      int sigval;
++
++      if (excep_code == NMI_VEC) {
++#ifndef CONFIG_KGDB_NMI
++              printk(KERN_NOTICE "KGDB: Ignoring unexpected NMI?\n");
++              return;
++#else /* CONFIG_KGDB_NMI */
++              if (!kgdb_enabled) {
++                      kgdb_enabled = 1;
++                      kgdb_init();
++              }
++#endif /* CONFIG_KGDB_NMI */
++      }
++
++      /* Ignore if we're disabled */
++      if (!kgdb_enabled)
++              return;
++
++      /* Enter GDB mode (e.g. after detach) */
++      if (!kgdb_in_gdb_mode) {
++              /* Do serial setup, notify user, issue preemptive ack */
++              printk(KERN_NOTICE "KGDB: Waiting for GDB\n");
++              kgdb_in_gdb_mode = 1;
++              put_debug_char('+');
++      }
++
++      /* Reply to host that an exception has occurred */
++      sigval = compute_signal(excep_code);
++      send_signal_msg(sigval);
++
++      /* TRAP_VEC exception indicates a software trap inserted in place of
++         code by GDB so back up PC by one instruction, as this instruction
++         will later be replaced by its original one.  Do NOT do this for
++         trap 0xff, since that indicates a compiled-in breakpoint which
++         will not be replaced (and we would retake the trap forever) */
++      if ((excep_code == TRAP_VEC) && (trapa_value != (0x3c << 2)))
++              trap_registers.pc -= 2;
++
++      /* Undo any stepping we may have done */
++      undo_single_step();
++
++      while (1) {
++              out_buffer[0] = 0;
++              get_packet(in_buffer, BUFMAX);
++
++              /* Examine first char of buffer to see what we need to do */
++              switch (in_buffer[0]) {
++              case '?':       /* Send which signal we've received */
++                      send_signal_msg(sigval);
++                      break;
++
++              case 'g':       /* Return the values of the CPU registers */
++                      send_regs_msg();
++                      break;
++
++              case 'G':       /* Set the value of the CPU registers */
++                      set_regs_msg();
++                      break;
++
++              case 'm':       /* Read LLLL bytes address AA..AA */
++                      read_mem_msg();
++                      break;
++
++              case 'M':       /* Write LLLL bytes address AA..AA, ret OK */
++                      write_mem_msg(0);       /* 0 = data in hex */
++                      break;
++
++              case 'X':       /* Write LLLL bytes esc bin address AA..AA */
++                      if (kgdb_bits == '8')
++                              write_mem_msg(1); /* 1 = data in binary */
++                      else
++                              send_empty_msg();
++                      break;
++
++              case 'C':       /* Continue, signum included, we ignore it */
++                      continue_with_sig_msg();
++                      return;
++
++              case 'c':       /* Continue at address AA..AA (optional) */
++                      continue_msg();
++                      return;
++
++              case 'S':       /* Step, signum included, we ignore it */
++                      step_with_sig_msg();
++                      return;
++
++              case 's':       /* Step one instruction from AA..AA */
++                      step_msg();
++                      return;
++
++              case 'k':       /* 'Kill the program' with a kernel ? */
++                      break;
++
++              case 'D':       /* Detach from program, send reply OK */
++                      kgdb_in_gdb_mode = 0;
++                      send_ok_msg();
++                      get_debug_char();
++                      return;
 +
-+      scsi_adjust_queue_depth(sdev, 0, qdepth);
-+      return sdev->queue_depth;
++              default:
++                      send_empty_msg();
++                      break;
++              }
++      }
 +}
 +
- /* ------------------------------------------------------------
-  * sysfs attributes
-  */
-@@ -1520,7 +1585,9 @@
-       .queuecommand = ibmvscsi_queuecommand,
-       .eh_abort_handler = ibmvscsi_eh_abort_handler,
-       .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
-+      .eh_host_reset_handler = ibmvscsi_eh_host_reset_handler,
-       .slave_configure = ibmvscsi_slave_configure,
-+      .change_queue_depth = ibmvscsi_change_queue_depth,
-       .cmd_per_lun = 16,
-       .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
-       .this_id = -1,
-@@ -1545,7 +1612,7 @@
-       driver_template.can_queue = max_requests;
-       host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
-       if (!host) {
--              printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n");
-+              dev_err(&vdev->dev, "couldn't allocate host data\n");
-               goto scsi_host_alloc_failed;
-       }
-@@ -1559,11 +1626,11 @@
-       rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests);
-       if (rc != 0 && rc != H_RESOURCE) {
--              printk(KERN_ERR "ibmvscsi: couldn't initialize crq\n");
-+              dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc);
-               goto init_crq_failed;
-       }
-       if (initialize_event_pool(&hostdata->pool, max_requests, hostdata) != 0) {
--              printk(KERN_ERR "ibmvscsi: couldn't initialize event pool\n");
-+              dev_err(&vdev->dev, "couldn't initialize event pool\n");
-               goto init_pool_failed;
-       }
-diff -Nurb linux-2.6.22-570/drivers/scsi/ibmvscsi/ibmvscsi.h linux-2.6.22-590/drivers/scsi/ibmvscsi/ibmvscsi.h
---- linux-2.6.22-570/drivers/scsi/ibmvscsi/ibmvscsi.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/ibmvscsi/ibmvscsi.h  2008-01-02 13:56:37.000000000 -0500
-@@ -45,6 +45,7 @@
- #define MAX_INDIRECT_BUFS 10
- #define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
-+#define IBMVSCSI_MAX_CMDS_PER_LUN 64
- /* ------------------------------------------------------------
-  * Data Structures
-@@ -69,6 +70,7 @@
-       union viosrp_iu iu;
-       void (*cmnd_done) (struct scsi_cmnd *);
-       struct completion comp;
-+      struct timer_list timer;
-       union viosrp_iu *sync_srp;
-       struct srp_direct_buf *ext_list;
-       dma_addr_t ext_list_token;
-diff -Nurb linux-2.6.22-570/drivers/scsi/ibmvscsi/rpa_vscsi.c linux-2.6.22-590/drivers/scsi/ibmvscsi/rpa_vscsi.c
---- linux-2.6.22-570/drivers/scsi/ibmvscsi/rpa_vscsi.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/ibmvscsi/rpa_vscsi.c 2008-01-02 13:56:37.000000000 -0500
-@@ -177,7 +177,7 @@
-       memset(&hostdata->madapter_info, 0x00,
-                       sizeof(hostdata->madapter_info));
--      printk(KERN_INFO "rpa_vscsi: SPR_VERSION: %s\n", SRP_VERSION);
-+      dev_info(hostdata->dev, "SRP_VERSION: %s\n", SRP_VERSION);
-       strcpy(hostdata->madapter_info.srp_version, SRP_VERSION);
-       strncpy(hostdata->madapter_info.partition_name, partition_name,
-@@ -232,25 +232,24 @@
-       if (rc == 2) {
-               /* Adapter is good, but other end is not ready */
--              printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
-+              dev_warn(hostdata->dev, "Partner adapter not ready\n");
-               retrc = 0;
-       } else if (rc != 0) {
--              printk(KERN_WARNING "ibmvscsi: Error %d opening adapter\n", rc);
-+              dev_warn(hostdata->dev, "Error %d opening adapter\n", rc);
-               goto reg_crq_failed;
-       }
-       if (request_irq(vdev->irq,
-                       ibmvscsi_handle_event,
-                       0, "ibmvscsi", (void *)hostdata) != 0) {
--              printk(KERN_ERR "ibmvscsi: couldn't register irq 0x%x\n",
-+              dev_err(hostdata->dev, "couldn't register irq 0x%x\n",
-                      vdev->irq);
-               goto req_irq_failed;
-       }
-       rc = vio_enable_interrupts(vdev);
-       if (rc != 0) {
--              printk(KERN_ERR "ibmvscsi:  Error %d enabling interrupts!!!\n",
--                     rc);
-+              dev_err(hostdata->dev, "Error %d enabling interrupts!!!\n", rc);
-               goto req_irq_failed;
-       }
-@@ -294,7 +293,7 @@
-       } while ((rc == H_IN_PROGRESS) || (rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
-       if (rc)
--              printk(KERN_ERR "ibmvscsi: Error %d enabling adapter\n", rc);
-+              dev_err(hostdata->dev, "Error %d enabling adapter\n", rc);
-       return rc;
- }
-@@ -327,10 +326,9 @@
-                               queue->msg_token, PAGE_SIZE);
-       if (rc == 2) {
-               /* Adapter is good, but other end is not ready */
--              printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
-+              dev_warn(hostdata->dev, "Partner adapter not ready\n");
-       } else if (rc != 0) {
--              printk(KERN_WARNING
--                     "ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
-+              dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc);
-       }
-       return rc;
- }
-diff -Nurb linux-2.6.22-570/drivers/scsi/initio.c linux-2.6.22-590/drivers/scsi/initio.c
---- linux-2.6.22-570/drivers/scsi/initio.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/initio.c     2008-01-02 13:56:37.000000000 -0500
-@@ -3,7 +3,8 @@
-  *
-  * Copyright (c) 1994-1998 Initio Corporation
-  * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
-- * All rights reserved.
-+ * Copyright (c) 2004 Christoph Hellwig <hch@lst.de>
-+ * Copyright (c) 2007 Red Hat <alan@redhat.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
-@@ -19,38 +20,6 @@
-  * along with this program; see the file COPYING.  If not, write to
-  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-  *
-- * --------------------------------------------------------------------------
-- *
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met:
-- * 1. Redistributions of source code must retain the above copyright
-- *    notice, this list of conditions, and the following disclaimer,
-- *    without modification, immediately at the beginning of the file.
-- * 2. Redistributions in binary form must reproduce the above copyright
-- *    notice, this list of conditions and the following disclaimer in the
-- *    documentation and/or other materials provided with the distribution.
-- * 3. The name of the author may not be used to endorse or promote products
-- *    derived from this software without specific prior written permission.
-- *
-- * Where this Software is combined with software released under the terms of 
-- * the GNU General Public License ("GPL") and the terms of the GPL would require the 
-- * combined work to also be released under the terms of the GPL, the terms
-- * and conditions of this License will apply in addition to those of the
-- * GPL with the exception of any terms or conditions of this License that
-- * conflict with, or are expressly prohibited by, the GPL.
-- *
-- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
-  *
-  *************************************************************************
-  *
-@@ -70,14 +39,14 @@
-  *            - Fix memory allocation problem
-  * 03/04/98 hc        - v1.01l
-  *            - Fix tape rewind which will hang the system problem
-- *            - Set can_queue to tul_num_scb
-+ *            - Set can_queue to initio_num_scb
-  * 06/25/98 hc        - v1.01m
-  *            - Get it work for kernel version >= 2.1.75
-- *            - Dynamic assign SCSI bus reset holding time in init_tulip()
-+ *            - Dynamic assign SCSI bus reset holding time in initio_init()
-  * 07/02/98 hc        - v1.01n
-  *            - Support 0002134A
-  * 08/07/98 hc  - v1.01o
-- *            - Change the tul_abort_srb routine to use scsi_done. <01>
-+ *            - Change the initio_abort_srb routine to use scsi_done. <01>
-  * 09/07/98 hl  - v1.02
-  *              - Change the INI9100U define and proc_dir_entry to
-  *                reflect the newer Kernel 2.1.118, but the v1.o1o
-@@ -150,23 +119,13 @@
- static unsigned int i91u_debug = DEBUG_DEFAULT;
- #endif
--#define TUL_RDWORD(x,y)         (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
--
--typedef struct PCI_ID_Struc {
--      unsigned short vendor_id;
--      unsigned short device_id;
--} PCI_ID;
--
--static int tul_num_ch = 4;    /* Maximum 4 adapters           */
--static int tul_num_scb;
--static int tul_tag_enable = 1;
--static SCB *tul_scb;
-+static int initio_tag_enable = 1;
- #ifdef DEBUG_i91u
- static int setup_debug = 0;
- #endif
--static void i91uSCBPost(BYTE * pHcb, BYTE * pScb);
-+static void i91uSCBPost(u8 * pHcb, u8 * pScb);
- /* PCI Devices supported by this driver */
- static struct pci_device_id i91u_pci_devices[] = {
-@@ -184,74 +143,66 @@
- #define DEBUG_STATE     0
- #define INT_DISC      0
--/*--- external functions --*/
--static void tul_se2_wait(void);
-+/*--- forward references ---*/
-+static struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun);
-+static struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host);
-+
-+static int tulip_main(struct initio_host * host);
-+
-+static int initio_next_state(struct initio_host * host);
-+static int initio_state_1(struct initio_host * host);
-+static int initio_state_2(struct initio_host * host);
-+static int initio_state_3(struct initio_host * host);
-+static int initio_state_4(struct initio_host * host);
-+static int initio_state_5(struct initio_host * host);
-+static int initio_state_6(struct initio_host * host);
-+static int initio_state_7(struct initio_host * host);
-+static int initio_xfer_data_in(struct initio_host * host);
-+static int initio_xfer_data_out(struct initio_host * host);
-+static int initio_xpad_in(struct initio_host * host);
-+static int initio_xpad_out(struct initio_host * host);
-+static int initio_status_msg(struct initio_host * host);
-+
-+static int initio_msgin(struct initio_host * host);
-+static int initio_msgin_sync(struct initio_host * host);
-+static int initio_msgin_accept(struct initio_host * host);
-+static int initio_msgout_reject(struct initio_host * host);
-+static int initio_msgin_extend(struct initio_host * host);
-+
-+static int initio_msgout_ide(struct initio_host * host);
-+static int initio_msgout_abort_targ(struct initio_host * host);
-+static int initio_msgout_abort_tag(struct initio_host * host);
-+
-+static int initio_bus_device_reset(struct initio_host * host);
-+static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb);
-+static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb);
-+static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb);
-+static int int_initio_busfree(struct initio_host * host);
-+static int int_initio_scsi_rst(struct initio_host * host);
-+static int int_initio_bad_seq(struct initio_host * host);
-+static int int_initio_resel(struct initio_host * host);
-+static int initio_sync_done(struct initio_host * host);
-+static int wdtr_done(struct initio_host * host);
-+static int wait_tulip(struct initio_host * host);
-+static int initio_wait_done_disc(struct initio_host * host);
-+static int initio_wait_disc(struct initio_host * host);
-+static void tulip_scsi(struct initio_host * host);
-+static int initio_post_scsi_rst(struct initio_host * host);
-+
-+static void initio_se2_ew_en(unsigned long base);
-+static void initio_se2_ew_ds(unsigned long base);
-+static int initio_se2_rd_all(unsigned long base);
-+static void initio_se2_update_all(unsigned long base);        /* setup default pattern */
-+static void initio_read_eeprom(unsigned long base);
--/*--- forward refrence ---*/
--static SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun);
--static SCB *tul_find_done_scb(HCS * pCurHcb);
--
--static int tulip_main(HCS * pCurHcb);
--
--static int tul_next_state(HCS * pCurHcb);
--static int tul_state_1(HCS * pCurHcb);
--static int tul_state_2(HCS * pCurHcb);
--static int tul_state_3(HCS * pCurHcb);
--static int tul_state_4(HCS * pCurHcb);
--static int tul_state_5(HCS * pCurHcb);
--static int tul_state_6(HCS * pCurHcb);
--static int tul_state_7(HCS * pCurHcb);
--static int tul_xfer_data_in(HCS * pCurHcb);
--static int tul_xfer_data_out(HCS * pCurHcb);
--static int tul_xpad_in(HCS * pCurHcb);
--static int tul_xpad_out(HCS * pCurHcb);
--static int tul_status_msg(HCS * pCurHcb);
--
--static int tul_msgin(HCS * pCurHcb);
--static int tul_msgin_sync(HCS * pCurHcb);
--static int tul_msgin_accept(HCS * pCurHcb);
--static int tul_msgout_reject(HCS * pCurHcb);
--static int tul_msgin_extend(HCS * pCurHcb);
--
--static int tul_msgout_ide(HCS * pCurHcb);
--static int tul_msgout_abort_targ(HCS * pCurHcb);
--static int tul_msgout_abort_tag(HCS * pCurHcb);
--
--static int tul_bus_device_reset(HCS * pCurHcb);
--static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb);
--static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb);
--static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb);
--static int int_tul_busfree(HCS * pCurHcb);
--static int int_tul_scsi_rst(HCS * pCurHcb);
--static int int_tul_bad_seq(HCS * pCurHcb);
--static int int_tul_resel(HCS * pCurHcb);
--static int tul_sync_done(HCS * pCurHcb);
--static int wdtr_done(HCS * pCurHcb);
--static int wait_tulip(HCS * pCurHcb);
--static int tul_wait_done_disc(HCS * pCurHcb);
--static int tul_wait_disc(HCS * pCurHcb);
--static void tulip_scsi(HCS * pCurHcb);
--static int tul_post_scsi_rst(HCS * pCurHcb);
--
--static void tul_se2_ew_en(WORD CurBase);
--static void tul_se2_ew_ds(WORD CurBase);
--static int tul_se2_rd_all(WORD CurBase);
--static void tul_se2_update_all(WORD CurBase); /* setup default pattern */
--static void tul_read_eeprom(WORD CurBase);
--
--                              /* ---- INTERNAL VARIABLES ---- */
--static HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
--static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS];
-+/* ---- INTERNAL VARIABLES ---- */
--/*NVRAM nvram, *nvramp = &nvram; */
- static NVRAM i91unvram;
- static NVRAM *i91unvramp;
--
--
--static UCHAR i91udftNvRam[64] =
-+static u8 i91udftNvRam[64] =
- {
--/*----------- header -----------*/
-+      /*----------- header -----------*/
-       0x25, 0xc9,             /* Signature    */
-       0x40,                   /* Size         */
-       0x01,                   /* Revision     */
-@@ -289,7 +240,7 @@
-       0, 0};                  /*      - CheckSum -            */
--static UCHAR tul_rate_tbl[8] =        /* fast 20      */
-+static u8 initio_rate_tbl[8] =        /* fast 20      */
- {
-                               /* nanosecond devide by 4 */
-       12,                     /* 50ns,  20M   */
-@@ -302,53 +253,17 @@
-       62                      /* 250ns, 4M    */
- };
--static void tul_do_pause(unsigned amount)
--{                             /* Pause for amount jiffies */
-+static void initio_do_pause(unsigned amount)
++/* There has been an exception, most likely a breakpoint. */
++static void handle_exception(struct pt_regs *regs)
 +{
-+      /* Pause for amount jiffies */
-       unsigned long the_time = jiffies + amount;
--      while (time_before_eq(jiffies, the_time));
-+      while (time_before_eq(jiffies, the_time))
-+              cpu_relax();
- }
- /*-- forward reference --*/
--/*******************************************************************
--      Use memeory refresh time        ~ 15us * 2
--********************************************************************/
--void tul_se2_wait(void)
--{
--#if 1
--      udelay(30);
--#else
--      UCHAR readByte;
--
--      readByte = TUL_RD(0, 0x61);
--      if ((readByte & 0x10) == 0x10) {
--              for (;;) {
--                      readByte = TUL_RD(0, 0x61);
--                      if ((readByte & 0x10) == 0x10)
--                              break;
--              }
--              for (;;) {
--                      readByte = TUL_RD(0, 0x61);
--                      if ((readByte & 0x10) != 0x10)
--                              break;
--              }
--      } else {
--              for (;;) {
--                      readByte = TUL_RD(0, 0x61);
--                      if ((readByte & 0x10) == 0x10)
--                              break;
--              }
--              for (;;) {
--                      readByte = TUL_RD(0, 0x61);
--                      if ((readByte & 0x10) != 0x10)
--                              break;
--              }
--      }
--#endif
--}
--
--
- /******************************************************************
-  Input: instruction for  Serial E2PROM
-@@ -379,1174 +294,1019 @@
- ******************************************************************/
--static void tul_se2_instr(WORD CurBase, UCHAR instr)
++      int excep_code, vbr_val;
++      int count;
++      int trapa_value = ctrl_inl(TRA);
 +
-+/**
-+ *    initio_se2_instr        -       bitbang an instruction
-+ *    @base: Base of InitIO controller
-+ *    @instr: Instruction for serial E2PROM
-+ *
-+ *    Bitbang an instruction out to the serial E2Prom
-+ */
++      /* Copy kernel regs (from stack) */
++      for (count = 0; count < 16; count++)
++              trap_registers.regs[count] = regs->regs[count];
++      trap_registers.pc = regs->pc;
++      trap_registers.pr = regs->pr;
++      trap_registers.sr = regs->sr;
++      trap_registers.gbr = regs->gbr;
++      trap_registers.mach = regs->mach;
++      trap_registers.macl = regs->macl;
 +
-+static void initio_se2_instr(unsigned long base, u8 instr)
- {
-       int i;
--      UCHAR b;
-+      u8 b;
--      TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);     /* cs+start bit */
--      tul_se2_wait();
--      TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK | SE2DO);    /* +CLK */
--      tul_se2_wait();
-+      outb(SE2CS | SE2DO, base + TUL_NVRAM);          /* cs+start bit */
-+      udelay(30);
-+      outb(SE2CS | SE2CLK | SE2DO, base + TUL_NVRAM); /* +CLK */
-+      udelay(30);
-       for (i = 0; i < 8; i++) {
-               if (instr & 0x80)
-                       b = SE2CS | SE2DO;      /* -CLK+dataBit */
-               else
-                       b = SE2CS;      /* -CLK */
--              TUL_WR(CurBase + TUL_NVRAM, b);
--              tul_se2_wait();
--              TUL_WR(CurBase + TUL_NVRAM, b | SE2CLK);        /* +CLK */
--              tul_se2_wait();
-+              outb(b, base + TUL_NVRAM);
-+              udelay(30);
-+              outb(b | SE2CLK, base + TUL_NVRAM);     /* +CLK */
-+              udelay(30);
-               instr <<= 1;
-       }
--      TUL_WR(CurBase + TUL_NVRAM, SE2CS);     /* -CLK */
--      tul_se2_wait();
--      return;
-+      outb(SE2CS, base + TUL_NVRAM);                  /* -CLK */
-+      udelay(30);
- }
--/******************************************************************
-- Function name  : tul_se2_ew_en
-- Description    : Enable erase/write state of serial EEPROM
--******************************************************************/
--void tul_se2_ew_en(WORD CurBase)
-+/**
-+ *    initio_se2_ew_en        -       Enable erase/write
-+ *    @base: Base address of InitIO controller
-+ *
-+ *    Enable erase/write state of serial EEPROM
-+ */
-+void initio_se2_ew_en(unsigned long base)
- {
--      tul_se2_instr(CurBase, 0x30);   /* EWEN */
--      TUL_WR(CurBase + TUL_NVRAM, 0);         /* -CS  */
--      tul_se2_wait();
--      return;
-+      initio_se2_instr(base, 0x30);   /* EWEN */
-+      outb(0, base + TUL_NVRAM);      /* -CS  */
-+      udelay(30);
- }
--/************************************************************************
-- Disable erase/write state of serial EEPROM
--*************************************************************************/
--void tul_se2_ew_ds(WORD CurBase)
--{
--      tul_se2_instr(CurBase, 0);      /* EWDS */
--      TUL_WR(CurBase + TUL_NVRAM, 0);         /* -CS  */
--      tul_se2_wait();
--      return;
-+/**
-+ *    initio_se2_ew_ds        -       Disable erase/write
-+ *    @base: Base address of InitIO controller
-+ *
-+ *    Disable erase/write state of serial EEPROM
-+ */
-+void initio_se2_ew_ds(unsigned long base)
-+{
-+      initio_se2_instr(base, 0);      /* EWDS */
-+      outb(0, base + TUL_NVRAM);      /* -CS  */
-+      udelay(30);
- }
--/******************************************************************
--      Input  :address of Serial E2PROM
--      Output :value stored in  Serial E2PROM
--*******************************************************************/
--static USHORT tul_se2_rd(WORD CurBase, ULONG adr)
-+/**
-+ *    initio_se2_rd           -       read E2PROM word
-+ *    @base: Base of InitIO controller
-+ *    @addr: Address of word in E2PROM
-+ *
-+ *    Read a word from the NV E2PROM device
-+ */
-+static u16 initio_se2_rd(unsigned long base, u8 addr)
- {
--      UCHAR instr, readByte;
--      USHORT readWord;
-+      u8 instr, rb;
-+      u16 val = 0;
-       int i;
--      instr = (UCHAR) (adr | 0x80);
--      tul_se2_instr(CurBase, instr);  /* READ INSTR */
--      readWord = 0;
-+      instr = (u8) (addr | 0x80);
-+      initio_se2_instr(base, instr);  /* READ INSTR */
-       for (i = 15; i >= 0; i--) {
--              TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);    /* +CLK */
--              tul_se2_wait();
--              TUL_WR(CurBase + TUL_NVRAM, SE2CS);     /* -CLK */
-+              outb(SE2CS | SE2CLK, base + TUL_NVRAM); /* +CLK */
-+              udelay(30);
-+              outb(SE2CS, base + TUL_NVRAM);          /* -CLK */
-               /* sample data after the following edge of clock  */
--              readByte = TUL_RD(CurBase, TUL_NVRAM);
--              readByte &= SE2DI;
--              readWord += (readByte << i);
--              tul_se2_wait(); /* 6/20/95 */
-+              rb = inb(base + TUL_NVRAM);
-+              rb &= SE2DI;
-+              val += (rb << i);
-+              udelay(30);     /* 6/20/95 */
-       }
--      TUL_WR(CurBase + TUL_NVRAM, 0);         /* no chip select */
--      tul_se2_wait();
--      return readWord;
-+      outb(0, base + TUL_NVRAM);              /* no chip select */
-+      udelay(30);
-+      return val;
- }
--
--/******************************************************************
-- Input: new value in  Serial E2PROM, address of Serial E2PROM
--*******************************************************************/
--static void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord)
-+/**
-+ *    initio_se2_wr           -       read E2PROM word
-+ *    @base: Base of InitIO controller
-+ *    @addr: Address of word in E2PROM
-+ *    @val: Value to write
-+ *
-+ *    Write a word to the NV E2PROM device. Used when recovering from
-+ *    a problem with the NV.
-+ */
-+static void initio_se2_wr(unsigned long base, u8 addr, u16 val)
- {
--      UCHAR readByte;
--      UCHAR instr;
-+      u8 rb;
-+      u8 instr;
-       int i;
--      instr = (UCHAR) (adr | 0x40);
--      tul_se2_instr(CurBase, instr);  /* WRITE INSTR */
-+      instr = (u8) (addr | 0x40);
-+      initio_se2_instr(base, instr);  /* WRITE INSTR */
-       for (i = 15; i >= 0; i--) {
--              if (writeWord & 0x8000)
--                      TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);     /* -CLK+dataBit 1 */
-+              if (val & 0x8000)
-+                      outb(SE2CS | SE2DO, base + TUL_NVRAM);  /* -CLK+dataBit 1 */
-               else
--                      TUL_WR(CurBase + TUL_NVRAM, SE2CS);     /* -CLK+dataBit 0 */
--              tul_se2_wait();
--              TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);    /* +CLK */
--              tul_se2_wait();
--              writeWord <<= 1;
--      }
--      TUL_WR(CurBase + TUL_NVRAM, SE2CS);     /* -CLK */
--      tul_se2_wait();
--      TUL_WR(CurBase + TUL_NVRAM, 0);         /* -CS  */
--      tul_se2_wait();
-+                      outb(SE2CS, base + TUL_NVRAM);          /* -CLK+dataBit 0 */
-+              udelay(30);
-+              outb(SE2CS | SE2CLK, base + TUL_NVRAM);         /* +CLK */
-+              udelay(30);
-+              val <<= 1;
-+      }
-+      outb(SE2CS, base + TUL_NVRAM);                          /* -CLK */
-+      udelay(30);
-+      outb(0, base + TUL_NVRAM);                              /* -CS  */
-+      udelay(30);
--      TUL_WR(CurBase + TUL_NVRAM, SE2CS);     /* +CS  */
--      tul_se2_wait();
-+      outb(SE2CS, base + TUL_NVRAM);                          /* +CS  */
-+      udelay(30);
-       for (;;) {
--              TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);    /* +CLK */
--              tul_se2_wait();
--              TUL_WR(CurBase + TUL_NVRAM, SE2CS);     /* -CLK */
--              tul_se2_wait();
--              if ((readByte = TUL_RD(CurBase, TUL_NVRAM)) & SE2DI)
-+              outb(SE2CS | SE2CLK, base + TUL_NVRAM);         /* +CLK */
-+              udelay(30);
-+              outb(SE2CS, base + TUL_NVRAM);                  /* -CLK */
-+              udelay(30);
-+              if ((rb = inb(base + TUL_NVRAM)) & SE2DI)
-                       break;  /* write complete */
-       }
--      TUL_WR(CurBase + TUL_NVRAM, 0);         /* -CS */
--      return;
-+      outb(0, base + TUL_NVRAM);                              /* -CS */
- }
-+/**
-+ *    initio_se2_rd_all       -       read hostadapter NV configuration
-+ *    @base: Base address of InitIO controller
-+ *
-+ *    Reads the E2PROM data into main memory. Ensures that the checksum
-+ *    and header marker are valid. Returns 1 on success -1 on error.
-+ */
--/***********************************************************************
-- Read SCSI H/A configuration parameters from serial EEPROM
--************************************************************************/
--int tul_se2_rd_all(WORD CurBase)
-+static int initio_se2_rd_all(unsigned long base)
- {
-       int i;
--      ULONG chksum = 0;
--      USHORT *np;
-+      u16 chksum = 0;
-+      u16 *np;
-       i91unvramp = &i91unvram;
--      np = (USHORT *) i91unvramp;
--      for (i = 0; i < 32; i++) {
--              *np++ = tul_se2_rd(CurBase, i);
--      }
-+      np = (u16 *) i91unvramp;
-+      for (i = 0; i < 32; i++)
-+              *np++ = initio_se2_rd(base, i);
--/*--------------------Is signature "ini" ok ? ----------------*/
-+      /* Is signature "ini" ok ? */
-       if (i91unvramp->NVM_Signature != INI_SIGNATURE)
-               return -1;
--/*---------------------- Is ckecksum ok ? ----------------------*/
--      np = (USHORT *) i91unvramp;
-+      /* Is ckecksum ok ? */
-+      np = (u16 *) i91unvramp;
-       for (i = 0; i < 31; i++)
-               chksum += *np++;
--      if (i91unvramp->NVM_CheckSum != (USHORT) chksum)
-+      if (i91unvramp->NVM_CheckSum != chksum)
-               return -1;
-       return 1;
- }
--
--/***********************************************************************
-- Update SCSI H/A configuration parameters from serial EEPROM
--************************************************************************/
--void tul_se2_update_all(WORD CurBase)
-+/**
-+ *    initio_se2_update_all           -       Update E2PROM
-+ *    @base: Base of InitIO controller
-+ *
-+ *    Update the E2PROM by wrting any changes into the E2PROM
-+ *    chip, rewriting the checksum.
-+ */
-+static void initio_se2_update_all(unsigned long base)
- {                             /* setup default pattern */
-       int i;
--      ULONG chksum = 0;
--      USHORT *np, *np1;
-+      u16 chksum = 0;
-+      u16 *np, *np1;
-       i91unvramp = &i91unvram;
-       /* Calculate checksum first */
--      np = (USHORT *) i91udftNvRam;
-+      np = (u16 *) i91udftNvRam;
-       for (i = 0; i < 31; i++)
-               chksum += *np++;
--      *np = (USHORT) chksum;
--      tul_se2_ew_en(CurBase); /* Enable write  */
-+      *np = chksum;
-+      initio_se2_ew_en(base); /* Enable write  */
--      np = (USHORT *) i91udftNvRam;
--      np1 = (USHORT *) i91unvramp;
-+      np = (u16 *) i91udftNvRam;
-+      np1 = (u16 *) i91unvramp;
-       for (i = 0; i < 32; i++, np++, np1++) {
--              if (*np != *np1) {
--                      tul_se2_wr(CurBase, i, *np);
--              }
-+              if (*np != *np1)
-+                      initio_se2_wr(base, i, *np);
-       }
--
--      tul_se2_ew_ds(CurBase); /* Disable write   */
--      return;
-+      initio_se2_ew_ds(base); /* Disable write   */
- }
--/*************************************************************************
-- Function name  : read_eeprom
--**************************************************************************/
--void tul_read_eeprom(WORD CurBase)
--{
--      UCHAR gctrl;
--
--      i91unvramp = &i91unvram;
--/*------Enable EEProm programming ---*/
--      gctrl = TUL_RD(CurBase, TUL_GCTRL);
--      TUL_WR(CurBase + TUL_GCTRL, gctrl | TUL_GCTRL_EEPROM_BIT);
--      if (tul_se2_rd_all(CurBase) != 1) {
--              tul_se2_update_all(CurBase);    /* setup default pattern */
--              tul_se2_rd_all(CurBase);        /* load again  */
--      }
--/*------ Disable EEProm programming ---*/
--      gctrl = TUL_RD(CurBase, TUL_GCTRL);
--      TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT);
--}                             /* read_eeprom */
-+/**
-+ *    initio_read_eeprom              -       Retrieve configuration
-+ *    @base: Base of InitIO Host Adapter
-+ *
-+ *    Retrieve the host adapter configuration data from E2Prom. If the
-+ *    data is invalid then the defaults are used and are also restored
-+ *    into the E2PROM. This forms the access point for the SCSI driver
-+ *    into the E2PROM layer, the other functions for the E2PROM are all
-+ *    internal use.
-+ *
-+ *    Must be called single threaded, uses a shared global area.
-+ */
--static int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
--                                    BYTE bBus, BYTE bDevice)
-+static void initio_read_eeprom(unsigned long base)
- {
--      int i, j;
-+      u8 gctrl;
--      for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
--              if (i91u_adpt[i].ADPT_BIOS < wBIOS)
--                      continue;
--              if (i91u_adpt[i].ADPT_BIOS == wBIOS) {
--                      if (i91u_adpt[i].ADPT_BASE == wBASE) {
--                              if (i91u_adpt[i].ADPT_Bus != 0xFF)
--                                      return 1;
--                      } else if (i91u_adpt[i].ADPT_BASE < wBASE)
--                                      continue;
--              }
--              for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
--                      i91u_adpt[j].ADPT_BASE = i91u_adpt[j - 1].ADPT_BASE;
--                      i91u_adpt[j].ADPT_INTR = i91u_adpt[j - 1].ADPT_INTR;
--                      i91u_adpt[j].ADPT_BIOS = i91u_adpt[j - 1].ADPT_BIOS;
--                      i91u_adpt[j].ADPT_Bus = i91u_adpt[j - 1].ADPT_Bus;
--                      i91u_adpt[j].ADPT_Device = i91u_adpt[j - 1].ADPT_Device;
--              }
--              i91u_adpt[i].ADPT_BASE = wBASE;
--              i91u_adpt[i].ADPT_INTR = bInterrupt;
--              i91u_adpt[i].ADPT_BIOS = wBIOS;
--              i91u_adpt[i].ADPT_Bus = bBus;
--              i91u_adpt[i].ADPT_Device = bDevice;
--              return 0;
--      }
--      return 1;
-+      i91unvramp = &i91unvram;
-+      /* Enable EEProm programming */
-+      gctrl = inb(base + TUL_GCTRL);
-+      outb(gctrl | TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);
-+      if (initio_se2_rd_all(base) != 1) {
-+              initio_se2_update_all(base);    /* setup default pattern */
-+              initio_se2_rd_all(base);        /* load again  */
-+      }
-+      /* Disable EEProm programming */
-+      gctrl = inb(base + TUL_GCTRL);
-+      outb(gctrl & ~TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);
- }
--static void init_i91uAdapter_table(void)
--{
--      int i;
--
--      for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {  /* Initialize adapter structure */
--              i91u_adpt[i].ADPT_BIOS = 0xffff;
--              i91u_adpt[i].ADPT_BASE = 0xffff;
--              i91u_adpt[i].ADPT_INTR = 0xff;
--              i91u_adpt[i].ADPT_Bus = 0xff;
--              i91u_adpt[i].ADPT_Device = 0xff;
--      }
--      return;
--}
-+/**
-+ *    initio_stop_bm          -       stop bus master
-+ *    @host: InitIO we are stopping
-+ *
-+ *    Stop any pending DMA operation, aborting the DMA if neccessary
-+ */
--static void tul_stop_bm(HCS * pCurHcb)
-+static void initio_stop_bm(struct initio_host * host)
- {
--      if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {   /* if DMA xfer is pending, abort DMA xfer */
--              TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
-+      if (inb(host->addr + TUL_XStatus) & XPEND) {    /* if DMA xfer is pending, abort DMA xfer */
-+              outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);
-               /* wait Abort DMA xfer done */
--              while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
-+              while ((inb(host->addr + TUL_Int) & XABT) == 0)
-+                      cpu_relax();
-       }
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-+      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
- }
--/***************************************************************************/
--static void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
--{
--      pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE;        /* Supply base address  */
--      pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS;        /* Supply BIOS address  */
--      pCurHcb->HCS_Intr = i91u_adpt[ch_idx].ADPT_INTR;        /* Supply interrupt line */
--      return;
--}
-+/**
-+ *    initio_reset_scsi               -       Reset SCSI host controller
-+ *    @host: InitIO host to reset
-+ *    @seconds: Recovery time
-+ *
-+ *    Perform a full reset of the SCSI subsystem.
-+ */
--/***************************************************************************/
--static int tul_reset_scsi(HCS * pCurHcb, int seconds)
-+static int initio_reset_scsi(struct initio_host * host, int seconds)
- {
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS);
-+      outb(TSC_RST_BUS, host->addr + TUL_SCtrl0);
--      while (!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt)) & TSS_SCSIRST_INT));
--      /* reset tulip chip */
-+      while (!((host->jsint = inb(host->addr + TUL_SInt)) & TSS_SCSIRST_INT))
-+              cpu_relax();
--      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0);
-+      /* reset tulip chip */
-+      outb(0, host->addr + TUL_SSignal);
-       /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
-       /* SONY 5200 tape drive won't work if only stall for 1 sec */
--      tul_do_pause(seconds * HZ);
--
--      TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-+      /* FIXME: this is a very long busy wait right now */
-+      initio_do_pause(seconds * HZ);
--      return (SCSI_RESET_SUCCESS);
-+      inb(host->addr + TUL_SInt);
-+      return SCSI_RESET_SUCCESS;
- }
--/***************************************************************************/
--static int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb,
--                    BYTE * pbBiosAdr, int seconds)
-+/**
-+ *    initio_init             -       set up an InitIO host adapter
-+ *    @host: InitIO host adapter
-+ *    @num_scbs: Number of SCBS
-+ *    @bios_addr: BIOS address
-+ *
-+ *    Set up the host adapter and devices according to the configuration
-+ *    retrieved from the E2PROM.
-+ *
-+ *    Locking: Calls E2PROM layer code which is not re-enterable so must
-+ *    run single threaded for now.
-+ */
++      asm("stc vbr, %0":"=r"(vbr_val));
++      trap_registers.vbr = vbr_val;
 +
-+static void initio_init(struct initio_host * host, u8 *bios_addr)
- {
-       int i;
--      BYTE *pwFlags;
--      BYTE *pbHeads;
--      SCB *pTmpScb, *pPrevScb = NULL;
--
--      pCurHcb->HCS_NumScbs = tul_num_scb;
--      pCurHcb->HCS_Semaph = 1;
--      spin_lock_init(&pCurHcb->HCS_SemaphLock);
--      pCurHcb->HCS_JSStatus0 = 0;
--      pCurHcb->HCS_Scb = scbp;
--      pCurHcb->HCS_NxtPend = scbp;
--      pCurHcb->HCS_NxtAvail = scbp;
--      for (i = 0, pTmpScb = scbp; i < tul_num_scb; i++, pTmpScb++) {
--              pTmpScb->SCB_TagId = i;
--              if (i != 0)
--                      pPrevScb->SCB_NxtScb = pTmpScb;
--              pPrevScb = pTmpScb;
--      }
--      pPrevScb->SCB_NxtScb = NULL;
--      pCurHcb->HCS_ScbEnd = pTmpScb;
--      pCurHcb->HCS_FirstAvail = scbp;
--      pCurHcb->HCS_LastAvail = pPrevScb;
--      spin_lock_init(&pCurHcb->HCS_AvailLock);
--      pCurHcb->HCS_FirstPend = NULL;
--      pCurHcb->HCS_LastPend = NULL;
--      pCurHcb->HCS_FirstBusy = NULL;
--      pCurHcb->HCS_LastBusy = NULL;
--      pCurHcb->HCS_FirstDone = NULL;
--      pCurHcb->HCS_LastDone = NULL;
--      pCurHcb->HCS_ActScb = NULL;
--      pCurHcb->HCS_ActTcs = NULL;
-+      u8 *flags;
-+      u8 *heads;
--      tul_read_eeprom(pCurHcb->HCS_Base);
--/*---------- get H/A configuration -------------*/
-+      /* Get E2Prom configuration */
-+      initio_read_eeprom(host->addr);
-       if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8)
--              pCurHcb->HCS_MaxTar = 8;
-+              host->max_tar = 8;
-       else
--              pCurHcb->HCS_MaxTar = 16;
-+              host->max_tar = 16;
--      pCurHcb->HCS_Config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
-+      host->config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
--      pCurHcb->HCS_SCSI_ID = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
--      pCurHcb->HCS_IdMask = ~(1 << pCurHcb->HCS_SCSI_ID);
-+      host->scsi_id = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
-+      host->idmask = ~(1 << host->scsi_id);
- #ifdef CHK_PARITY
-       /* Enable parity error response */
--      TUL_WR(pCurHcb->HCS_Base + TUL_PCMD, TUL_RD(pCurHcb->HCS_Base, TUL_PCMD) | 0x40);
-+      outb(inb(host->addr + TUL_PCMD) | 0x40, host->addr + TUL_PCMD);
- #endif
-       /* Mask all the interrupt       */
--      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
-+      outb(0x1F, host->addr + TUL_Mask);
--      tul_stop_bm(pCurHcb);
-+      initio_stop_bm(host);
-       /* --- Initialize the tulip --- */
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_CHIP);
-+      outb(TSC_RST_CHIP, host->addr + TUL_SCtrl0);
-       /* program HBA's SCSI ID        */
--      TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, pCurHcb->HCS_SCSI_ID << 4);
-+      outb(host->scsi_id << 4, host->addr + TUL_SScsiId);
-       /* Enable Initiator Mode ,phase latch,alternate sync period mode,
-          disable SCSI reset */
--      if (pCurHcb->HCS_Config & HCC_EN_PAR)
--              pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
-+      if (host->config & HCC_EN_PAR)
-+              host->sconf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
-       else
--              pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_SConf1);
-+              host->sconf1 = (TSC_INITDEFAULT);
-+      outb(host->sconf1, host->addr + TUL_SConfig);
-       /* Enable HW reselect           */
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
-+      outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, 0);
-+      outb(0, host->addr + TUL_SPeriod);
-       /* selection time out = 250 ms */
--      TUL_WR(pCurHcb->HCS_Base + TUL_STimeOut, 153);
-+      outb(153, host->addr + TUL_STimeOut);
--/*--------- Enable SCSI terminator -----*/
--      TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, (pCurHcb->HCS_Config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)));
--      TUL_WR(pCurHcb->HCS_Base + TUL_GCTRL1,
--             ((pCurHcb->HCS_Config & HCC_AUTO_TERM) >> 4) | (TUL_RD(pCurHcb->HCS_Base, TUL_GCTRL1) & 0xFE));
-+      /* Enable SCSI terminator */
-+      outb((host->config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)),
-+              host->addr + TUL_XCtrl);
-+      outb(((host->config & HCC_AUTO_TERM) >> 4) |
-+              (inb(host->addr + TUL_GCTRL1) & 0xFE),
-+              host->addr + TUL_GCTRL1);
-       for (i = 0,
--           pwFlags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
--           pbHeads = pbBiosAdr + 0x180;
--           i < pCurHcb->HCS_MaxTar;
--           i++, pwFlags++) {
--              pCurHcb->HCS_Tcs[i].TCS_Flags = *pwFlags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
--              if (pCurHcb->HCS_Tcs[i].TCS_Flags & TCF_EN_255)
--                      pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
-+           flags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
-+           heads = bios_addr + 0x180;
-+           i < host->max_tar;
-+           i++, flags++) {
-+              host->targets[i].flags = *flags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
-+              if (host->targets[i].flags & TCF_EN_255)
-+                      host->targets[i].drv_flags = TCF_DRV_255_63;
-               else
--                      pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
--              pCurHcb->HCS_Tcs[i].TCS_JS_Period = 0;
--              pCurHcb->HCS_Tcs[i].TCS_SConfig0 = pCurHcb->HCS_SConf1;
--              pCurHcb->HCS_Tcs[i].TCS_DrvHead = *pbHeads++;
--              if (pCurHcb->HCS_Tcs[i].TCS_DrvHead == 255)
--                      pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
-+                      host->targets[i].drv_flags = 0;
-+              host->targets[i].js_period = 0;
-+              host->targets[i].sconfig0 = host->sconf1;
-+              host->targets[i].heads = *heads++;
-+              if (host->targets[i].heads == 255)
-+                      host->targets[i].drv_flags = TCF_DRV_255_63;
-               else
--                      pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
--              pCurHcb->HCS_Tcs[i].TCS_DrvSector = *pbHeads++;
--              pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;
--              pCurHcb->HCS_ActTags[i] = 0;
--              pCurHcb->HCS_MaxTags[i] = 0xFF;
-+                      host->targets[i].drv_flags = 0;
-+              host->targets[i].sectors = *heads++;
-+              host->targets[i].flags &= ~TCF_BUSY;
-+              host->act_tags[i] = 0;
-+              host->max_tags[i] = 0xFF;
-       }                       /* for                          */
-       printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
--             pCurHcb->HCS_Base, pCurHcb->HCS_Intr,
--             pCurHcb->HCS_BIOS, pCurHcb->HCS_SCSI_ID);
--/*------------------- reset SCSI Bus ---------------------------*/
--      if (pCurHcb->HCS_Config & HCC_SCSI_RESET) {
--              printk("i91u: Reset SCSI Bus ... \n");
--              tul_reset_scsi(pCurHcb, seconds);
--      }
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCFG1, 0x17);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SIntEnable, 0xE9);
--      return (0);
-+             host->addr, host->irq,
-+             host->bios_addr, host->scsi_id);
-+      /* Reset SCSI Bus */
-+      if (host->config & HCC_SCSI_RESET) {
-+              printk(KERN_INFO "i91u: Reset SCSI Bus ... \n");
-+              initio_reset_scsi(host, 10);
-+      }
-+      outb(0x17, host->addr + TUL_SCFG1);
-+      outb(0xE9, host->addr + TUL_SIntEnable);
- }
--/***************************************************************************/
--static SCB *tul_alloc_scb(HCS * hcsp)
-+/**
-+ *    initio_alloc_scb                -       Allocate an SCB
-+ *    @host: InitIO host we are allocating for
-+ *
-+ *    Walk the SCB list for the controller and allocate a free SCB if
-+ *    one exists.
-+ */
-+static struct scsi_ctrl_blk *initio_alloc_scb(struct initio_host *host)
- {
--      SCB *pTmpScb;
--      ULONG flags;
--      spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
--      if ((pTmpScb = hcsp->HCS_FirstAvail) != NULL) {
-+      struct scsi_ctrl_blk *scb;
-+      unsigned long flags;
++      /* Get excode for command loop call, user access */
++      asm("stc r2_bank, %0":"=r"(excep_code));
++      kgdb_excode = excep_code;
 +
-+      spin_lock_irqsave(&host->avail_lock, flags);
-+      if ((scb = host->first_avail) != NULL) {
- #if DEBUG_QUEUE
--              printk("find scb at %08lx\n", (ULONG) pTmpScb);
-+              printk("find scb at %p\n", scb);
- #endif
--              if ((hcsp->HCS_FirstAvail = pTmpScb->SCB_NxtScb) == NULL)
--                      hcsp->HCS_LastAvail = NULL;
--              pTmpScb->SCB_NxtScb = NULL;
--              pTmpScb->SCB_Status = SCB_RENT;
-+              if ((host->first_avail = scb->next) == NULL)
-+                      host->last_avail = NULL;
-+              scb->next = NULL;
-+              scb->status = SCB_RENT;
-       }
--      spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
--      return (pTmpScb);
-+      spin_unlock_irqrestore(&host->avail_lock, flags);
-+      return scb;
- }
--/***************************************************************************/
--static void tul_release_scb(HCS * hcsp, SCB * scbp)
-+/**
-+ *    initio_release_scb              -       Release an SCB
-+ *    @host: InitIO host that owns the SCB
-+ *    @cmnd: SCB command block being returned
-+ *
-+ *    Return an allocated SCB to the host free list
-+ */
++      /* Other interesting environment items for reference */
++      asm("stc r6_bank, %0":"=r"(kgdb_g_imask));
++      kgdb_current = current;
++      kgdb_trapa_val = trapa_value;
 +
-+static void initio_release_scb(struct initio_host * host, struct scsi_ctrl_blk * cmnd)
- {
--      ULONG flags;
-+      unsigned long flags;
- #if DEBUG_QUEUE
--      printk("Release SCB %lx; ", (ULONG) scbp);
-+      printk("Release SCB %p; ", cmnd);
- #endif
--      spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
--      scbp->SCB_Srb = NULL;
--      scbp->SCB_Status = 0;
--      scbp->SCB_NxtScb = NULL;
--      if (hcsp->HCS_LastAvail != NULL) {
--              hcsp->HCS_LastAvail->SCB_NxtScb = scbp;
--              hcsp->HCS_LastAvail = scbp;
-+      spin_lock_irqsave(&(host->avail_lock), flags);
-+      cmnd->srb = NULL;
-+      cmnd->status = 0;
-+      cmnd->next = NULL;
-+      if (host->last_avail != NULL) {
-+              host->last_avail->next = cmnd;
-+              host->last_avail = cmnd;
-       } else {
--              hcsp->HCS_FirstAvail = scbp;
--              hcsp->HCS_LastAvail = scbp;
-+              host->first_avail = cmnd;
-+              host->last_avail = cmnd;
-       }
--      spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
-+      spin_unlock_irqrestore(&(host->avail_lock), flags);
- }
- /***************************************************************************/
--static void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
-+static void initio_append_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
- {
- #if DEBUG_QUEUE
--      printk("Append pend SCB %lx; ", (ULONG) scbp);
-+      printk("Append pend SCB %p; ", scbp);
- #endif
--      scbp->SCB_Status = SCB_PEND;
--      scbp->SCB_NxtScb = NULL;
--      if (pCurHcb->HCS_LastPend != NULL) {
--              pCurHcb->HCS_LastPend->SCB_NxtScb = scbp;
--              pCurHcb->HCS_LastPend = scbp;
-+      scbp->status = SCB_PEND;
-+      scbp->next = NULL;
-+      if (host->last_pending != NULL) {
-+              host->last_pending->next = scbp;
-+              host->last_pending = scbp;
-       } else {
--              pCurHcb->HCS_FirstPend = scbp;
--              pCurHcb->HCS_LastPend = scbp;
-+              host->first_pending = scbp;
-+              host->last_pending = scbp;
-       }
- }
- /***************************************************************************/
--static void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
-+static void initio_push_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
- {
- #if DEBUG_QUEUE
--      printk("Push pend SCB %lx; ", (ULONG) scbp);
-+      printk("Push pend SCB %p; ", scbp);
- #endif
--      scbp->SCB_Status = SCB_PEND;
--      if ((scbp->SCB_NxtScb = pCurHcb->HCS_FirstPend) != NULL) {
--              pCurHcb->HCS_FirstPend = scbp;
-+      scbp->status = SCB_PEND;
-+      if ((scbp->next = host->first_pending) != NULL) {
-+              host->first_pending = scbp;
-       } else {
--              pCurHcb->HCS_FirstPend = scbp;
--              pCurHcb->HCS_LastPend = scbp;
-+              host->first_pending = scbp;
-+              host->last_pending = scbp;
-       }
- }
--/***************************************************************************/
--static SCB *tul_find_first_pend_scb(HCS * pCurHcb)
-+static struct scsi_ctrl_blk *initio_find_first_pend_scb(struct initio_host * host)
- {
--      SCB *pFirstPend;
-+      struct scsi_ctrl_blk *first;
--      pFirstPend = pCurHcb->HCS_FirstPend;
--      while (pFirstPend != NULL) {
--              if (pFirstPend->SCB_Opcode != ExecSCSI) {
--                      return (pFirstPend);
--              }
--              if (pFirstPend->SCB_TagMsg == 0) {
--                      if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] == 0) &&
--                          !(pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
--                              return (pFirstPend);
--                      }
-+      first = host->first_pending;
-+      while (first != NULL) {
-+              if (first->opcode != ExecSCSI)
-+                      return first;
-+              if (first->tagmsg == 0) {
-+                      if ((host->act_tags[first->target] == 0) &&
-+                          !(host->targets[first->target].flags & TCF_BUSY))
-+                              return first;
-               } else {
--                      if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] >=
--                        pCurHcb->HCS_MaxTags[pFirstPend->SCB_Target]) |
--                          (pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
--                              pFirstPend = pFirstPend->SCB_NxtScb;
-+                      if ((host->act_tags[first->target] >=
-+                        host->max_tags[first->target]) |
-+                          (host->targets[first->target].flags & TCF_BUSY)) {
-+                              first = first->next;
-                               continue;
-                       }
--                      return (pFirstPend);
-+                      return first;
-               }
--              pFirstPend = pFirstPend->SCB_NxtScb;
-+              first = first->next;
-       }
--
--
--      return (pFirstPend);
-+      return first;
- }
--/***************************************************************************/
--static void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
++      /* Act on the exception */
++      kgdb_command_loop(excep_code, trapa_value);
 +
-+static void initio_unlink_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
- {
--      SCB *pTmpScb, *pPrevScb;
-+      struct scsi_ctrl_blk *tmp, *prev;
- #if DEBUG_QUEUE
--      printk("unlink pend SCB %lx; ", (ULONG) pCurScb);
-+      printk("unlink pend SCB %p; ", scb);
- #endif
--      pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;
--      while (pTmpScb != NULL) {
--              if (pCurScb == pTmpScb) {       /* Unlink this SCB              */
--                      if (pTmpScb == pCurHcb->HCS_FirstPend) {
--                              if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
--                                      pCurHcb->HCS_LastPend = NULL;
-+      prev = tmp = host->first_pending;
-+      while (tmp != NULL) {
-+              if (scb == tmp) {       /* Unlink this SCB              */
-+                      if (tmp == host->first_pending) {
-+                              if ((host->first_pending = tmp->next) == NULL)
-+                                      host->last_pending = NULL;
-                       } else {
--                              pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
--                              if (pTmpScb == pCurHcb->HCS_LastPend)
--                                      pCurHcb->HCS_LastPend = pPrevScb;
-+                              prev->next = tmp->next;
-+                              if (tmp == host->last_pending)
-+                                      host->last_pending = prev;
-                       }
--                      pTmpScb->SCB_NxtScb = NULL;
-+                      tmp->next = NULL;
-                       break;
-               }
--              pPrevScb = pTmpScb;
--              pTmpScb = pTmpScb->SCB_NxtScb;
-+              prev = tmp;
-+              tmp = tmp->next;
-       }
--      return;
- }
--/***************************************************************************/
--static void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
++      kgdb_current = NULL;
++
++      /* Copy back the (maybe modified) registers */
++      for (count = 0; count < 16; count++)
++              regs->regs[count] = trap_registers.regs[count];
++      regs->pc = trap_registers.pc;
++      regs->pr = trap_registers.pr;
++      regs->sr = trap_registers.sr;
++      regs->gbr = trap_registers.gbr;
++      regs->mach = trap_registers.mach;
++      regs->macl = trap_registers.macl;
++
++      vbr_val = trap_registers.vbr;
++      asm("ldc %0, vbr": :"r"(vbr_val));
++}
++
++asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5,
++                                    unsigned long r6, unsigned long r7,
++                                    struct pt_regs __regs)
++{
++      struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
++      handle_exception(regs);
++}
++
++/* Initialise the KGDB data structures and serial configuration */
++int kgdb_init(void)
++{
++      if (!kgdb_enabled)
++              return 1;
++
++      in_nmi = 0;
++      kgdb_nofault = 0;
++      stepped_opcode = 0;
++      kgdb_in_gdb_mode = 0;
++
++      if (kgdb_serial_setup() != 0) {
++              printk(KERN_NOTICE "KGDB: serial setup error\n");
++              return -1;
++      }
 +
-+static void initio_append_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
- {
- #if DEBUG_QUEUE
--      printk("append busy SCB %lx; ", (ULONG) scbp);
-+      printk("append busy SCB %o; ", scbp);
- #endif
--      if (scbp->SCB_TagMsg)
--              pCurHcb->HCS_ActTags[scbp->SCB_Target]++;
-+      if (scbp->tagmsg)
-+              host->act_tags[scbp->target]++;
-       else
--              pCurHcb->HCS_Tcs[scbp->SCB_Target].TCS_Flags |= TCF_BUSY;
--      scbp->SCB_Status = SCB_BUSY;
--      scbp->SCB_NxtScb = NULL;
--      if (pCurHcb->HCS_LastBusy != NULL) {
--              pCurHcb->HCS_LastBusy->SCB_NxtScb = scbp;
--              pCurHcb->HCS_LastBusy = scbp;
-+              host->targets[scbp->target].flags |= TCF_BUSY;
-+      scbp->status = SCB_BUSY;
-+      scbp->next = NULL;
-+      if (host->last_busy != NULL) {
-+              host->last_busy->next = scbp;
-+              host->last_busy = scbp;
-       } else {
--              pCurHcb->HCS_FirstBusy = scbp;
--              pCurHcb->HCS_LastBusy = scbp;
-+              host->first_busy = scbp;
-+              host->last_busy = scbp;
-       }
- }
- /***************************************************************************/
--static SCB *tul_pop_busy_scb(HCS * pCurHcb)
-+static struct scsi_ctrl_blk *initio_pop_busy_scb(struct initio_host * host)
- {
--      SCB *pTmpScb;
-+      struct scsi_ctrl_blk *tmp;
--      if ((pTmpScb = pCurHcb->HCS_FirstBusy) != NULL) {
--              if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
--                      pCurHcb->HCS_LastBusy = NULL;
--              pTmpScb->SCB_NxtScb = NULL;
--              if (pTmpScb->SCB_TagMsg)
--                      pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
-+      if ((tmp = host->first_busy) != NULL) {
-+              if ((host->first_busy = tmp->next) == NULL)
-+                      host->last_busy = NULL;
-+              tmp->next = NULL;
-+              if (tmp->tagmsg)
-+                      host->act_tags[tmp->target]--;
-               else
--                      pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
-+                      host->targets[tmp->target].flags &= ~TCF_BUSY;
-       }
- #if DEBUG_QUEUE
--      printk("Pop busy SCB %lx; ", (ULONG) pTmpScb);
-+      printk("Pop busy SCB %p; ", tmp);
- #endif
--      return (pTmpScb);
-+      return tmp;
- }
- /***************************************************************************/
--static void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb)
-+static void initio_unlink_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
- {
--      SCB *pTmpScb, *pPrevScb;
-+      struct scsi_ctrl_blk *tmp, *prev;
- #if DEBUG_QUEUE
--      printk("unlink busy SCB %lx; ", (ULONG) pCurScb);
-+      printk("unlink busy SCB %p; ", scb);
- #endif
--      pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
--      while (pTmpScb != NULL) {
--              if (pCurScb == pTmpScb) {       /* Unlink this SCB              */
--                      if (pTmpScb == pCurHcb->HCS_FirstBusy) {
--                              if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
--                                      pCurHcb->HCS_LastBusy = NULL;
--                      } else {
--                              pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
--                              if (pTmpScb == pCurHcb->HCS_LastBusy)
--                                      pCurHcb->HCS_LastBusy = pPrevScb;
--                      }
--                      pTmpScb->SCB_NxtScb = NULL;
--                      if (pTmpScb->SCB_TagMsg)
--                              pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
-+      prev = tmp = host->first_busy;
-+      while (tmp != NULL) {
-+              if (scb == tmp) {       /* Unlink this SCB              */
-+                      if (tmp == host->first_busy) {
-+                              if ((host->first_busy = tmp->next) == NULL)
-+                                      host->last_busy = NULL;
-+                      } else {
-+                              prev->next = tmp->next;
-+                              if (tmp == host->last_busy)
-+                                      host->last_busy = prev;
-+                      }
-+                      tmp->next = NULL;
-+                      if (tmp->tagmsg)
-+                              host->act_tags[tmp->target]--;
-                       else
--                              pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
-+                              host->targets[tmp->target].flags &= ~TCF_BUSY;
-                       break;
-               }
--              pPrevScb = pTmpScb;
--              pTmpScb = pTmpScb->SCB_NxtScb;
-+              prev = tmp;
-+              tmp = tmp->next;
-       }
-       return;
- }
--/***************************************************************************/
--SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun)
-+struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun)
- {
--      SCB *pTmpScb, *pPrevScb;
--      WORD scbp_tarlun;
-+      struct scsi_ctrl_blk *tmp, *prev;
-+      u16 scbp_tarlun;
--      pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
--      while (pTmpScb != NULL) {
--              scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target);
-+      prev = tmp = host->first_busy;
-+      while (tmp != NULL) {
-+              scbp_tarlun = (tmp->lun << 8) | (tmp->target);
-               if (scbp_tarlun == tarlun) {    /* Unlink this SCB              */
-                       break;
-               }
--              pPrevScb = pTmpScb;
--              pTmpScb = pTmpScb->SCB_NxtScb;
-+              prev = tmp;
-+              tmp = tmp->next;
-       }
- #if DEBUG_QUEUE
--      printk("find busy SCB %lx; ", (ULONG) pTmpScb);
-+      printk("find busy SCB %p; ", tmp);
- #endif
--      return (pTmpScb);
-+      return tmp;
- }
--/***************************************************************************/
--static void tul_append_done_scb(HCS * pCurHcb, SCB * scbp)
-+static void initio_append_done_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
- {
--
- #if DEBUG_QUEUE
--      printk("append done SCB %lx; ", (ULONG) scbp);
-+      printk("append done SCB %p; ", scbp);
- #endif
--      scbp->SCB_Status = SCB_DONE;
--      scbp->SCB_NxtScb = NULL;
--      if (pCurHcb->HCS_LastDone != NULL) {
--              pCurHcb->HCS_LastDone->SCB_NxtScb = scbp;
--              pCurHcb->HCS_LastDone = scbp;
-+      scbp->status = SCB_DONE;
-+      scbp->next = NULL;
-+      if (host->last_done != NULL) {
-+              host->last_done->next = scbp;
-+              host->last_done = scbp;
-       } else {
--              pCurHcb->HCS_FirstDone = scbp;
--              pCurHcb->HCS_LastDone = scbp;
-+              host->first_done = scbp;
-+              host->last_done = scbp;
-       }
- }
--/***************************************************************************/
--SCB *tul_find_done_scb(HCS * pCurHcb)
-+struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host)
- {
--      SCB *pTmpScb;
--
-+      struct scsi_ctrl_blk *tmp;
--      if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) {
--              if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL)
--                      pCurHcb->HCS_LastDone = NULL;
--              pTmpScb->SCB_NxtScb = NULL;
-+      if ((tmp = host->first_done) != NULL) {
-+              if ((host->first_done = tmp->next) == NULL)
-+                      host->last_done = NULL;
-+              tmp->next = NULL;
-       }
- #if DEBUG_QUEUE
--      printk("find done SCB %lx; ", (ULONG) pTmpScb);
-+      printk("find done SCB %p; ",tmp);
- #endif
--      return (pTmpScb);
-+      return tmp;
- }
--/***************************************************************************/
--static int tul_abort_srb(HCS * pCurHcb, struct scsi_cmnd *srbp)
-+static int initio_abort_srb(struct initio_host * host, struct scsi_cmnd *srbp)
- {
--      ULONG flags;
--      SCB *pTmpScb, *pPrevScb;
-+      unsigned long flags;
-+      struct scsi_ctrl_blk *tmp, *prev;
--      spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-+      spin_lock_irqsave(&host->semaph_lock, flags);
--      if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
--              TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
-+      if ((host->semaph == 0) && (host->active == NULL)) {
-               /* disable Jasmin SCSI Int        */
--
--                spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--
--              tulip_main(pCurHcb);
--
--              spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
--
--              pCurHcb->HCS_Semaph = 1;
--              TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
--
--              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--
-+              outb(0x1F, host->addr + TUL_Mask);
-+              spin_unlock_irqrestore(&host->semaph_lock, flags);
-+              /* FIXME: synchronize_irq needed ? */
-+              tulip_main(host);
-+              spin_lock_irqsave(&host->semaph_lock, flags);
-+              host->semaph = 1;
-+              outb(0x0F, host->addr + TUL_Mask);
-+              spin_unlock_irqrestore(&host->semaph_lock, flags);
-               return SCSI_ABORT_SNOOZE;
-       }
--      pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;    /* Check Pend queue */
--      while (pTmpScb != NULL) {
-+      prev = tmp = host->first_pending;       /* Check Pend queue */
-+      while (tmp != NULL) {
-               /* 07/27/98 */
--              if (pTmpScb->SCB_Srb == srbp) {
--                      if (pTmpScb == pCurHcb->HCS_ActScb) {
--                              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-+              if (tmp->srb == srbp) {
-+                      if (tmp == host->active) {
-+                              spin_unlock_irqrestore(&host->semaph_lock, flags);
-                               return SCSI_ABORT_BUSY;
--                      } else if (pTmpScb == pCurHcb->HCS_FirstPend) {
--                              if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
--                                      pCurHcb->HCS_LastPend = NULL;
--                      } else {
--                              pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
--                              if (pTmpScb == pCurHcb->HCS_LastPend)
--                                      pCurHcb->HCS_LastPend = pPrevScb;
--                      }
--                      pTmpScb->SCB_HaStat = HOST_ABORTED;
--                      pTmpScb->SCB_Flags |= SCF_DONE;
--                      if (pTmpScb->SCB_Flags & SCF_POST)
--                              (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
--                      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-+                      } else if (tmp == host->first_pending) {
-+                              if ((host->first_pending = tmp->next) == NULL)
-+                                      host->last_pending = NULL;
-+                      } else {
-+                              prev->next = tmp->next;
-+                              if (tmp == host->last_pending)
-+                                      host->last_pending = prev;
-+                      }
-+                      tmp->hastat = HOST_ABORTED;
-+                      tmp->flags |= SCF_DONE;
-+                      if (tmp->flags & SCF_POST)
-+                              (*tmp->post) ((u8 *) host, (u8 *) tmp);
-+                      spin_unlock_irqrestore(&host->semaph_lock, flags);
-                       return SCSI_ABORT_SUCCESS;
-               }
--              pPrevScb = pTmpScb;
--              pTmpScb = pTmpScb->SCB_NxtScb;
-+              prev = tmp;
-+              tmp = tmp->next;
-       }
--      pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;    /* Check Busy queue */
--      while (pTmpScb != NULL) {
--
--              if (pTmpScb->SCB_Srb == srbp) {
--
--                      if (pTmpScb == pCurHcb->HCS_ActScb) {
--                              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-+      prev = tmp = host->first_busy;  /* Check Busy queue */
-+      while (tmp != NULL) {
-+              if (tmp->srb == srbp) {
-+                      if (tmp == host->active) {
-+                              spin_unlock_irqrestore(&host->semaph_lock, flags);
-                               return SCSI_ABORT_BUSY;
--                      } else if (pTmpScb->SCB_TagMsg == 0) {
--                              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-+                      } else if (tmp->tagmsg == 0) {
-+                              spin_unlock_irqrestore(&host->semaph_lock, flags);
-                               return SCSI_ABORT_BUSY;
-                       } else {
--                              pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
--                              if (pTmpScb == pCurHcb->HCS_FirstBusy) {
--                                      if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
--                                              pCurHcb->HCS_LastBusy = NULL;
--                              } else {
--                                      pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
--                                      if (pTmpScb == pCurHcb->HCS_LastBusy)
--                                              pCurHcb->HCS_LastBusy = pPrevScb;
--                              }
--                              pTmpScb->SCB_NxtScb = NULL;
--
--
--                              pTmpScb->SCB_HaStat = HOST_ABORTED;
--                              pTmpScb->SCB_Flags |= SCF_DONE;
--                              if (pTmpScb->SCB_Flags & SCF_POST)
--                                      (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
--                              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-+                              host->act_tags[tmp->target]--;
-+                              if (tmp == host->first_busy) {
-+                                      if ((host->first_busy = tmp->next) == NULL)
-+                                              host->last_busy = NULL;
-+                              } else {
-+                                      prev->next = tmp->next;
-+                                      if (tmp == host->last_busy)
-+                                              host->last_busy = prev;
-+                              }
-+                              tmp->next = NULL;
++      /* Init ptr to exception handler */
++      kgdb_debug_hook = handle_exception;
++      kgdb_bus_err_hook = kgdb_handle_bus_error;
 +
++      /* Enter kgdb now if requested, or just report init done */
++      printk(KERN_NOTICE "KGDB: stub is initialized.\n");
 +
-+                              tmp->hastat = HOST_ABORTED;
-+                              tmp->flags |= SCF_DONE;
-+                              if (tmp->flags & SCF_POST)
-+                                      (*tmp->post) ((u8 *) host, (u8 *) tmp);
-+                              spin_unlock_irqrestore(&host->semaph_lock, flags);
-                               return SCSI_ABORT_SUCCESS;
-                       }
-               }
--              pPrevScb = pTmpScb;
--              pTmpScb = pTmpScb->SCB_NxtScb;
-+              prev = tmp;
-+              tmp = tmp->next;
-       }
--      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--      return (SCSI_ABORT_NOT_RUNNING);
-+      spin_unlock_irqrestore(&host->semaph_lock, flags);
-+      return SCSI_ABORT_NOT_RUNNING;
- }
- /***************************************************************************/
--static int tul_bad_seq(HCS * pCurHcb)
--{
--      SCB *pCurScb;
--
--      printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index);
--
--      if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
--              tul_unlink_busy_scb(pCurHcb, pCurScb);
--              pCurScb->SCB_HaStat = HOST_BAD_PHAS;
--              pCurScb->SCB_TaStat = 0;
--              tul_append_done_scb(pCurHcb, pCurScb);
--      }
--      tul_stop_bm(pCurHcb);
--
--      tul_reset_scsi(pCurHcb, 8);     /* 7/29/98 */
--
--      return (tul_post_scsi_rst(pCurHcb));
--}
--
--#if 0
--
--/************************************************************************/
--static int tul_device_reset(HCS * pCurHcb, struct scsi_cmnd *pSrb,
--                          unsigned int target, unsigned int ResetFlags)
-+static int initio_bad_seq(struct initio_host * host)
- {
--      ULONG flags;
--      SCB *pScb;
--      spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
--
--      if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) {
--
--              if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
--                      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
--                      /* disable Jasmin SCSI Int        */
--
--                      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--
--                      tulip_main(pCurHcb);
--
--                      spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
--
--                      pCurHcb->HCS_Semaph = 1;
--                      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
--
--                      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--
--                      return SCSI_RESET_SNOOZE;
--              }
--              pScb = pCurHcb->HCS_FirstBusy;  /* Check Busy queue */
--              while (pScb != NULL) {
--                      if (pScb->SCB_Srb == pSrb)
--                              break;
--                      pScb = pScb->SCB_NxtScb;
--              }
--              if (pScb == NULL) {
--                      printk("Unable to Reset - No SCB Found\n");
--
--                      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--                      return SCSI_RESET_NOT_RUNNING;
--              }
--      }
--      if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) {
--              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--              return SCSI_RESET_NOT_RUNNING;
--      }
--      pScb->SCB_Opcode = BusDevRst;
--      pScb->SCB_Flags = SCF_POST;
--      pScb->SCB_Target = target;
--      pScb->SCB_Mode = 0;
--
--      pScb->SCB_Srb = NULL;
--      if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
--              pScb->SCB_Srb = pSrb;
--      }
--      tul_push_pend_scb(pCurHcb, pScb);       /* push this SCB to Pending queue */
-+      struct scsi_ctrl_blk *scb;
--      if (pCurHcb->HCS_Semaph == 1) {
--              TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
--              /* disable Jasmin SCSI Int        */
--              pCurHcb->HCS_Semaph = 0;
--
--              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--
--              tulip_main(pCurHcb);
--
--                spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-+      printk("initio_bad_seg c=%d\n", host->index);
--              pCurHcb->HCS_Semaph = 1;
--              TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
-+      if ((scb = host->active) != NULL) {
-+              initio_unlink_busy_scb(host, scb);
-+              scb->hastat = HOST_BAD_PHAS;
-+              scb->tastat = 0;
-+              initio_append_done_scb(host, scb);
-       }
--      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--      return SCSI_RESET_PENDING;
--}
--
--static int tul_reset_scsi_bus(HCS * pCurHcb)
--{
--      ULONG flags;
--
--      spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
--      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
--      pCurHcb->HCS_Semaph = 0;
--
--      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--
--      tul_stop_bm(pCurHcb);
--
--      tul_reset_scsi(pCurHcb, 2);     /* 7/29/98 */
--
--      spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
--      tul_post_scsi_rst(pCurHcb);
--
--        spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--
--      tulip_main(pCurHcb);
--
--        spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
--
--      pCurHcb->HCS_Semaph = 1;
--      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
--      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--      return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);
-+      initio_stop_bm(host);
-+      initio_reset_scsi(host, 8);     /* 7/29/98 */
-+      return initio_post_scsi_rst(host);
- }
--#endif  /*  0  */
- /************************************************************************/
--static void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
-+static void initio_exec_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
- {
--      ULONG flags;
-+      unsigned long flags;
--      pCurScb->SCB_Mode = 0;
-+      scb->mode = 0;
--      pCurScb->SCB_SGIdx = 0;
--      pCurScb->SCB_SGMax = pCurScb->SCB_SGLen;
-+      scb->sgidx = 0;
-+      scb->sgmax = scb->sglen;
--      spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-+      spin_lock_irqsave(&host->semaph_lock, flags);
--      tul_append_pend_scb(pCurHcb, pCurScb);  /* Append this SCB to Pending queue */
-+      initio_append_pend_scb(host, scb);      /* Append this SCB to Pending queue */
- /* VVVVV 07/21/98 */
--      if (pCurHcb->HCS_Semaph == 1) {
--              TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
--              /* disable Jasmin SCSI Int        */
--              pCurHcb->HCS_Semaph = 0;
--
--              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
--
--              tulip_main(pCurHcb);
-+      if (host->semaph == 1) {
-+              /* Disable Jasmin SCSI Int */
-+              outb(0x1F, host->addr + TUL_Mask);
-+              host->semaph = 0;
-+              spin_unlock_irqrestore(&host->semaph_lock, flags);
--              spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
-+              tulip_main(host);
--              pCurHcb->HCS_Semaph = 1;
--              TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
-+              spin_lock_irqsave(&host->semaph_lock, flags);
-+              host->semaph = 1;
-+              outb(0x0F, host->addr + TUL_Mask);
-       }
--      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
-+      spin_unlock_irqrestore(&host->semaph_lock, flags);
-       return;
- }
- /***************************************************************************/
--static int tul_isr(HCS * pCurHcb)
-+static int initio_isr(struct initio_host * host)
- {
--      /* Enter critical section       */
--
--      if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) {
--              if (pCurHcb->HCS_Semaph == 1) {
--                      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
-+      if (inb(host->addr + TUL_Int) & TSS_INT_PENDING) {
-+              if (host->semaph == 1) {
-+                      outb(0x1F, host->addr + TUL_Mask);
-                       /* Disable Tulip SCSI Int */
--                      pCurHcb->HCS_Semaph = 0;
-+                      host->semaph = 0;
--                      tulip_main(pCurHcb);
-+                      tulip_main(host);
--                      pCurHcb->HCS_Semaph = 1;
--                      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
--                      return (1);
-+                      host->semaph = 1;
-+                      outb(0x0F, host->addr + TUL_Mask);
-+                      return 1;
-               }
-       }
--      return (0);
 +      return 0;
- }
--/***************************************************************************/
--int tulip_main(HCS * pCurHcb)
-+static int tulip_main(struct initio_host * host)
- {
--      SCB *pCurScb;
-+      struct scsi_ctrl_blk *scb;
-       for (;;) {
-+              tulip_scsi(host);       /* Call tulip_scsi              */
--              tulip_scsi(pCurHcb);    /* Call tulip_scsi              */
--
--              while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) {        /* find done entry */
--                      if (pCurScb->SCB_TaStat == INI_QUEUE_FULL) {
--                              pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] =
--                                  pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1;
--                              pCurScb->SCB_TaStat = 0;
--                              tul_append_pend_scb(pCurHcb, pCurScb);
-+              /* Walk the list of completed SCBs */
-+              while ((scb = initio_find_done_scb(host)) != NULL) {    /* find done entry */
-+                      if (scb->tastat == INI_QUEUE_FULL) {
-+                              host->max_tags[scb->target] =
-+                                  host->act_tags[scb->target] - 1;
-+                              scb->tastat = 0;
-+                              initio_append_pend_scb(host, scb);
-                               continue;
-                       }
--                      if (!(pCurScb->SCB_Mode & SCM_RSENS)) {         /* not in auto req. sense mode */
--                              if (pCurScb->SCB_TaStat == 2) {
-+                      if (!(scb->mode & SCM_RSENS)) {         /* not in auto req. sense mode */
-+                              if (scb->tastat == 2) {
-                                       /* clr sync. nego flag */
--                                      if (pCurScb->SCB_Flags & SCF_SENSE) {
--                                              BYTE len;
--                                              len = pCurScb->SCB_SenseLen;
-+                                      if (scb->flags & SCF_SENSE) {
-+                                              u8 len;
-+                                              len = scb->senselen;
-                                               if (len == 0)
-                                                       len = 1;
--                                              pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen;
--                                              pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr;
--                                              pCurScb->SCB_Flags &= ~(SCF_SG | SCF_DIR);      /* for xfer_data_in */
--/*                      pCurScb->SCB_Flags |= SCF_NO_DCHK;      */
--                                              /* so, we won't report worng direction in xfer_data_in,
-+                                              scb->buflen = scb->senselen;
-+                                              scb->bufptr = scb->senseptr;
-+                                              scb->flags &= ~(SCF_SG | SCF_DIR);      /* for xfer_data_in */
-+                                              /* so, we won't report wrong direction in xfer_data_in,
-                                                  and won't report HOST_DO_DU in state_6 */
--                                              pCurScb->SCB_Mode = SCM_RSENS;
--                                              pCurScb->SCB_Ident &= 0xBF;     /* Disable Disconnect */
--                                              pCurScb->SCB_TagMsg = 0;
--                                              pCurScb->SCB_TaStat = 0;
--                                              pCurScb->SCB_CDBLen = 6;
--                                              pCurScb->SCB_CDB[0] = SCSICMD_RequestSense;
--                                              pCurScb->SCB_CDB[1] = 0;
--                                              pCurScb->SCB_CDB[2] = 0;
--                                              pCurScb->SCB_CDB[3] = 0;
--                                              pCurScb->SCB_CDB[4] = len;
--                                              pCurScb->SCB_CDB[5] = 0;
--                                              tul_push_pend_scb(pCurHcb, pCurScb);
-+                                              scb->mode = SCM_RSENS;
-+                                              scb->ident &= 0xBF;     /* Disable Disconnect */
-+                                              scb->tagmsg = 0;
-+                                              scb->tastat = 0;
-+                                              scb->cdblen = 6;
-+                                              scb->cdb[0] = SCSICMD_RequestSense;
-+                                              scb->cdb[1] = 0;
-+                                              scb->cdb[2] = 0;
-+                                              scb->cdb[3] = 0;
-+                                              scb->cdb[4] = len;
-+                                              scb->cdb[5] = 0;
-+                                              initio_push_pend_scb(host, scb);
-                                               break;
-                                       }
-                               }
-                       } else {        /* in request sense mode */
--                              if (pCurScb->SCB_TaStat == 2) {         /* check contition status again after sending
-+                              if (scb->tastat == 2) {         /* check contition status again after sending
-                                                                          requset sense cmd 0x3 */
--                                      pCurScb->SCB_HaStat = HOST_BAD_PHAS;
-+                                      scb->hastat = HOST_BAD_PHAS;
-                               }
--                              pCurScb->SCB_TaStat = 2;
-+                              scb->tastat = 2;
-                       }
--                      pCurScb->SCB_Flags |= SCF_DONE;
--                      if (pCurScb->SCB_Flags & SCF_POST) {
--                              (*pCurScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pCurScb);
-+                      scb->flags |= SCF_DONE;
-+                      if (scb->flags & SCF_POST) {
-+                              /* FIXME: only one post method and lose casts */
-+                              (*scb->post) ((u8 *) host, (u8 *) scb);
-                       }
-               }               /* while */
--
-               /* find_active: */
--              if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING)
-+              if (inb(host->addr + TUL_SStatus0) & TSS_INT_PENDING)
-                       continue;
--
--              if (pCurHcb->HCS_ActScb) {      /* return to OS and wait for xfer_done_ISR/Selected_ISR */
-+              if (host->active)       /* return to OS and wait for xfer_done_ISR/Selected_ISR */
-                       return 1;       /* return to OS, enable interrupt */
--              }
-               /* Check pending SCB            */
--              if (tul_find_first_pend_scb(pCurHcb) == NULL) {
-+              if (initio_find_first_pend_scb(host) == NULL)
-                       return 1;       /* return to OS, enable interrupt */
--              }
-       }                       /* End of for loop */
-       /* statement won't reach here */
- }
--
--
--
--/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
--/***************************************************************************/
--/***************************************************************************/
--/***************************************************************************/
--/***************************************************************************/
--
--/***************************************************************************/
--void tulip_scsi(HCS * pCurHcb)
-+static void tulip_scsi(struct initio_host * host)
- {
--      SCB *pCurScb;
--      TCS *pCurTcb;
-+      struct scsi_ctrl_blk *scb;
-+      struct target_control *active_tc;
-       /* make sure to service interrupt asap */
--
--      if ((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) & TSS_INT_PENDING) {
--
--              pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
--              pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
--              pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
--              if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {     /* SCSI bus reset detected      */
--                      int_tul_scsi_rst(pCurHcb);
-+      if ((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING) {
-+              host->phase = host->jsstatus0 & TSS_PH_MASK;
-+              host->jsstatus1 = inb(host->addr + TUL_SStatus1);
-+              host->jsint = inb(host->addr + TUL_SInt);
-+              if (host->jsint & TSS_SCSIRST_INT) {    /* SCSI bus reset detected      */
-+                      int_initio_scsi_rst(host);
-                       return;
-               }
--              if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {       /* if selected/reselected interrupt */
--                      if (int_tul_resel(pCurHcb) == 0)
--                              tul_next_state(pCurHcb);
-+              if (host->jsint & TSS_RESEL_INT) {      /* if selected/reselected interrupt */
-+                      if (int_initio_resel(host) == 0)
-+                              initio_next_state(host);
-                       return;
-               }
--              if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {
--                      int_tul_busfree(pCurHcb);
-+              if (host->jsint & TSS_SEL_TIMEOUT) {
-+                      int_initio_busfree(host);
-                       return;
-               }
--              if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {        /* BUS disconnection            */
--                      int_tul_busfree(pCurHcb);       /* unexpected bus free or sel timeout */
-+              if (host->jsint & TSS_DISC_INT) {       /* BUS disconnection            */
-+                      int_initio_busfree(host);       /* unexpected bus free or sel timeout */
-                       return;
-               }
--              if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {      /* func complete or Bus service */
--                      if ((pCurScb = pCurHcb->HCS_ActScb) != NULL)
--                              tul_next_state(pCurHcb);
-+              if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV)) {     /* func complete or Bus service */
-+                      if ((scb = host->active) != NULL)
-+                              initio_next_state(host);
-                       return;
-               }
-       }
--      if (pCurHcb->HCS_ActScb != NULL)
-+      if (host->active != NULL)
-               return;
--      if ((pCurScb = tul_find_first_pend_scb(pCurHcb)) == NULL)
-+      if ((scb = initio_find_first_pend_scb(host)) == NULL)
-               return;
-       /* program HBA's SCSI ID & target SCSI ID */
--      TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId,
--           (pCurHcb->HCS_SCSI_ID << 4) | (pCurScb->SCB_Target & 0x0F));
--      if (pCurScb->SCB_Opcode == ExecSCSI) {
--              pCurTcb = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
-+      outb((host->scsi_id << 4) | (scb->target & 0x0F),
-+              host->addr + TUL_SScsiId);
-+      if (scb->opcode == ExecSCSI) {
-+              active_tc = &host->targets[scb->target];
--              if (pCurScb->SCB_TagMsg)
--                      pCurTcb->TCS_DrvFlags |= TCF_DRV_EN_TAG;
-+              if (scb->tagmsg)
-+                      active_tc->drv_flags |= TCF_DRV_EN_TAG;
-               else
--                      pCurTcb->TCS_DrvFlags &= ~TCF_DRV_EN_TAG;
-+                      active_tc->drv_flags &= ~TCF_DRV_EN_TAG;
--              TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
--              if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {        /* do wdtr negotiation          */
--                      tul_select_atn_stop(pCurHcb, pCurScb);
-+              outb(active_tc->js_period, host->addr + TUL_SPeriod);
-+              if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {  /* do wdtr negotiation          */
-+                      initio_select_atn_stop(host, scb);
-               } else {
--                      if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {   /* do sync negotiation          */
--                              tul_select_atn_stop(pCurHcb, pCurScb);
-+                      if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {     /* do sync negotiation          */
-+                              initio_select_atn_stop(host, scb);
-                       } else {
--                              if (pCurScb->SCB_TagMsg)
--                                      tul_select_atn3(pCurHcb, pCurScb);
-+                              if (scb->tagmsg)
-+                                      initio_select_atn3(host, scb);
-                               else
--                                      tul_select_atn(pCurHcb, pCurScb);
-+                                      initio_select_atn(host, scb);
-                       }
-               }
--              if (pCurScb->SCB_Flags & SCF_POLL) {
--                      while (wait_tulip(pCurHcb) != -1) {
--                              if (tul_next_state(pCurHcb) == -1)
-+              if (scb->flags & SCF_POLL) {
-+                      while (wait_tulip(host) != -1) {
-+                              if (initio_next_state(host) == -1)
-                                       break;
-                       }
-               }
--      } else if (pCurScb->SCB_Opcode == BusDevRst) {
--              tul_select_atn_stop(pCurHcb, pCurScb);
--              pCurScb->SCB_NxtStat = 8;
--              if (pCurScb->SCB_Flags & SCF_POLL) {
--                      while (wait_tulip(pCurHcb) != -1) {
--                              if (tul_next_state(pCurHcb) == -1)
-+      } else if (scb->opcode == BusDevRst) {
-+              initio_select_atn_stop(host, scb);
-+              scb->next_state = 8;
-+              if (scb->flags & SCF_POLL) {
-+                      while (wait_tulip(host) != -1) {
-+                              if (initio_next_state(host) == -1)
-                                       break;
-                       }
-               }
--      } else if (pCurScb->SCB_Opcode == AbortCmd) {
--              if (tul_abort_srb(pCurHcb, pCurScb->SCB_Srb) != 0) {
--
--
--                      tul_unlink_pend_scb(pCurHcb, pCurScb);
--
--                      tul_release_scb(pCurHcb, pCurScb);
-+      } else if (scb->opcode == AbortCmd) {
-+              if (initio_abort_srb(host, scb->srb) != 0) {
-+                      initio_unlink_pend_scb(host, scb);
-+                      initio_release_scb(host, scb);
-               } else {
--                      pCurScb->SCB_Opcode = BusDevRst;
--                      tul_select_atn_stop(pCurHcb, pCurScb);
--                      pCurScb->SCB_NxtStat = 8;
-+                      scb->opcode = BusDevRst;
-+                      initio_select_atn_stop(host, scb);
-+                      scb->next_state = 8;
-               }
--
--/* 08/03/98 */
-       } else {
--              tul_unlink_pend_scb(pCurHcb, pCurScb);
--              pCurScb->SCB_HaStat = 0x16;     /* bad command */
--              tul_append_done_scb(pCurHcb, pCurScb);
-+              initio_unlink_pend_scb(host, scb);
-+              scb->hastat = 0x16;     /* bad command */
-+              initio_append_done_scb(host, scb);
-       }
-       return;
- }
-+/**
-+ *    initio_next_state               -       Next SCSI state
-+ *    @host: InitIO host we are processing
-+ *
-+ *    Progress the active command block along the state machine
-+ *    until we hit a state which we must wait for activity to occur.
-+ *
-+ *    Returns zero or a negative code.
-+ */
--/***************************************************************************/
--int tul_next_state(HCS * pCurHcb)
-+static int initio_next_state(struct initio_host * host)
- {
-       int next;
--      next = pCurHcb->HCS_ActScb->SCB_NxtStat;
-+      next = host->active->next_state;
-       for (;;) {
-               switch (next) {
-               case 1:
--                      next = tul_state_1(pCurHcb);
-+                      next = initio_state_1(host);
-                       break;
-               case 2:
--                      next = tul_state_2(pCurHcb);
-+                      next = initio_state_2(host);
-                       break;
-               case 3:
--                      next = tul_state_3(pCurHcb);
-+                      next = initio_state_3(host);
-                       break;
-               case 4:
--                      next = tul_state_4(pCurHcb);
-+                      next = initio_state_4(host);
-                       break;
-               case 5:
--                      next = tul_state_5(pCurHcb);
-+                      next = initio_state_5(host);
-                       break;
-               case 6:
--                      next = tul_state_6(pCurHcb);
-+                      next = initio_state_6(host);
-                       break;
-               case 7:
--                      next = tul_state_7(pCurHcb);
-+                      next = initio_state_7(host);
-                       break;
-               case 8:
--                      return (tul_bus_device_reset(pCurHcb));
-+                      return initio_bus_device_reset(host);
-               default:
--                      return (tul_bad_seq(pCurHcb));
-+                      return initio_bad_seq(host);
-               }
-               if (next <= 0)
-                       return next;
-@@ -1554,338 +1314,363 @@
- }
--/***************************************************************************/
--/* sTate after selection with attention & stop */
--int tul_state_1(HCS * pCurHcb)
-+/**
-+ *    initio_state_1          -       SCSI state machine
-+ *    @host: InitIO host we are controlling
-+ *
-+ *    Perform SCSI state processing for Select/Attention/Stop
-+ */
++}
 +
-+static int initio_state_1(struct initio_host * host)
- {
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
--      TCS *pCurTcb = pCurHcb->HCS_ActTcs;
-+      struct scsi_ctrl_blk *scb = host->active;
-+      struct target_control *active_tc = host->active_tc;
- #if DEBUG_STATE
-       printk("-s1-");
- #endif
--      tul_unlink_pend_scb(pCurHcb, pCurScb);
--      tul_append_busy_scb(pCurHcb, pCurScb);
-+      /* Move the SCB from pending to busy */
-+      initio_unlink_pend_scb(host, scb);
-+      initio_append_busy_scb(host, scb);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
-+      outb(active_tc->sconfig0, host->addr + TUL_SConfig );
-       /* ATN on */
--      if (pCurHcb->HCS_Phase == MSG_OUT) {
--
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, (TSC_EN_BUS_IN | TSC_HW_RESELECT));
--
--              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
--
--              if (pCurScb->SCB_TagMsg) {
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
--              }
--              if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
--
--                      pCurTcb->TCS_Flags |= TCF_WDTR_DONE;
--
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);       /* Extended msg length */
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);       /* Sync request */
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);       /* Start from 16 bits */
--              } else if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
--
--                      pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
--
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);       /* extended msg length */
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);       /* sync request */
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);      /* REQ/ACK offset */
-+      if (host->phase == MSG_OUT) {
-+              outb(TSC_EN_BUS_IN | TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
-+              outb(scb->ident, host->addr + TUL_SFifo);
++/* Make function available for "user messages"; console will use it too. */
 +
-+              if (scb->tagmsg) {
-+                      outb(scb->tagmsg, host->addr + TUL_SFifo);
-+                      outb(scb->tagid, host->addr + TUL_SFifo);
-+              }
-+              if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
-+                      active_tc->flags |= TCF_WDTR_DONE;
-+                      outb(MSG_EXTEND, host->addr + TUL_SFifo);
-+                      outb(2, host->addr + TUL_SFifo);        /* Extended msg length */
-+                      outb(3, host->addr + TUL_SFifo);        /* Sync request */
-+                      outb(1, host->addr + TUL_SFifo);        /* Start from 16 bits */
-+              } else if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
-+                      active_tc->flags |= TCF_SYNC_DONE;
-+                      outb(MSG_EXTEND, host->addr + TUL_SFifo);
-+                      outb(3, host->addr + TUL_SFifo);        /* extended msg length */
-+                      outb(1, host->addr + TUL_SFifo);        /* sync request */
-+                      outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);
-+                      outb(MAX_OFFSET, host->addr + TUL_SFifo);       /* REQ/ACK offset */
-               }
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--              if (wait_tulip(pCurHcb) == -1)
--                      return (-1);
-+              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+              if (wait_tulip(host) == -1)
-+                      return -1;
-       }
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
--      return (3);
-+      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
-+      outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);
-+      /* Into before CDB xfer */
-+      return 3;
- }
--/***************************************************************************/
--/* state after selection with attention */
--/* state after selection with attention3 */
--int tul_state_2(HCS * pCurHcb)
-+/**
-+ *    initio_state_2          -       SCSI state machine
-+ *    @host: InitIO host we are controlling
-+ *
-+ * state after selection with attention
-+ * state after selection with attention3
-+ */
++char gdbmsgbuf[BUFMAX];
++#define MAXOUT ((BUFMAX-2)/2)
 +
-+static int initio_state_2(struct initio_host * host)
- {
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
--      TCS *pCurTcb = pCurHcb->HCS_ActTcs;
-+      struct scsi_ctrl_blk *scb = host->active;
-+      struct target_control *active_tc = host->active_tc;
- #if DEBUG_STATE
-       printk("-s2-");
- #endif
--      tul_unlink_pend_scb(pCurHcb, pCurScb);
--      tul_append_busy_scb(pCurHcb, pCurScb);
-+      initio_unlink_pend_scb(host, scb);
-+      initio_append_busy_scb(host, scb);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
-+      outb(active_tc->sconfig0, host->addr + TUL_SConfig);
--      if (pCurHcb->HCS_JSStatus1 & TSS_CMD_PH_CMP) {
--              return (4);
--      }
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
--      return (3);
-+      if (host->jsstatus1 & TSS_CMD_PH_CMP)
-+              return 4;
++static void kgdb_msg_write(const char *s, unsigned count)
++{
++      int i;
++      int wcount;
++      char *bufptr;
 +
-+      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
-+      outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);
-+      /* Into before CDB xfer */
-+      return 3;
- }
--/***************************************************************************/
--/* state before CDB xfer is done */
--int tul_state_3(HCS * pCurHcb)
-+/**
-+ *    initio_state_3          -       SCSI state machine
-+ *    @host: InitIO host we are controlling
-+ *
-+ * state before CDB xfer is done
-+ */
++      /* 'O'utput */
++      gdbmsgbuf[0] = 'O';
 +
-+static int initio_state_3(struct initio_host * host)
- {
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
--      TCS *pCurTcb = pCurHcb->HCS_ActTcs;
-+      struct scsi_ctrl_blk *scb = host->active;
-+      struct target_control *active_tc = host->active_tc;
-       int i;
- #if DEBUG_STATE
-       printk("-s3-");
- #endif
-       for (;;) {
--              switch (pCurHcb->HCS_Phase) {
-+              switch (host->phase) {
-               case CMD_OUT:   /* Command out phase            */
--                      for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--                      if (wait_tulip(pCurHcb) == -1)
--                              return (-1);
--                      if (pCurHcb->HCS_Phase == CMD_OUT) {
--                              return (tul_bad_seq(pCurHcb));
--                      }
--                      return (4);
-+                      for (i = 0; i < (int) scb->cdblen; i++)
-+                              outb(scb->cdb[i], host->addr + TUL_SFifo);
-+                      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+                      if (wait_tulip(host) == -1)
-+                              return -1;
-+                      if (host->phase == CMD_OUT)
-+                              return initio_bad_seq(host);
-+                      return 4;
-               case MSG_IN:    /* Message in phase             */
--                      pCurScb->SCB_NxtStat = 3;
--                      if (tul_msgin(pCurHcb) == -1)
--                              return (-1);
-+                      scb->next_state = 3;
-+                      if (initio_msgin(host) == -1)
-+                              return -1;
-                       break;
-               case STATUS_IN: /* Status phase                 */
--                      if (tul_status_msg(pCurHcb) == -1)
--                              return (-1);
-+                      if (initio_status_msg(host) == -1)
-+                              return -1;
-                       break;
-               case MSG_OUT:   /* Message out phase            */
--                      if (pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
-+                      if (active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
-+                              outb(MSG_NOP, host->addr + TUL_SFifo);          /* msg nop */
-+                              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+                              if (wait_tulip(host) == -1)
-+                                      return -1;
-+                      } else {
-+                              active_tc->flags |= TCF_SYNC_DONE;
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);         /* msg nop */
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--                              if (wait_tulip(pCurHcb) == -1)
--                                      return (-1);
--
--                      } else {
--                              pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
--
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);       /* ext. msg len */
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);       /* sync request */
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);      /* REQ/ACK offset */
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--                              if (wait_tulip(pCurHcb) == -1)
--                                      return (-1);
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7));
-+                              outb(MSG_EXTEND, host->addr + TUL_SFifo);
-+                              outb(3, host->addr + TUL_SFifo);        /* ext. msg len */
-+                              outb(1, host->addr + TUL_SFifo);        /* sync request */
-+                              outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);
-+                              outb(MAX_OFFSET, host->addr + TUL_SFifo);       /* REQ/ACK offset */
-+                              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+                              if (wait_tulip(host) == -1)
-+                                      return -1;
-+                              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
-+                              outb(inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7), host->addr + TUL_SSignal);
-                       }
-                       break;
--
-               default:
--                      return (tul_bad_seq(pCurHcb));
-+                      return initio_bad_seq(host);
-               }
-       }
- }
--
--/***************************************************************************/
--int tul_state_4(HCS * pCurHcb)
-+/**
-+ *    initio_state_4          -       SCSI state machine
-+ *    @host: InitIO host we are controlling
-+ *
-+ *    SCSI state machine. State 4
-+ */
++      /* Fill and send buffers... */
++      while (count > 0) {
++              bufptr = gdbmsgbuf + 1;
 +
-+static int initio_state_4(struct initio_host * host)
- {
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
-+      struct scsi_ctrl_blk *scb = host->active;
- #if DEBUG_STATE
-       printk("-s4-");
- #endif
--      if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_NO_XF) {
--              return (6);     /* Go to state 6                */
-+      if ((scb->flags & SCF_DIR) == SCF_NO_XF) {
-+              return 6;       /* Go to state 6 (After data) */
-       }
-       for (;;) {
--              if (pCurScb->SCB_BufLen == 0)
--                      return (6);     /* Go to state 6                */
-+              if (scb->buflen == 0)
-+                      return 6;
--              switch (pCurHcb->HCS_Phase) {
-+              switch (host->phase) {
-               case STATUS_IN: /* Status phase                 */
--                      if ((pCurScb->SCB_Flags & SCF_DIR) != 0) {      /* if direction bit set then report data underrun */
--                              pCurScb->SCB_HaStat = HOST_DO_DU;
--                      }
--                      if ((tul_status_msg(pCurHcb)) == -1)
--                              return (-1);
-+                      if ((scb->flags & SCF_DIR) != 0)        /* if direction bit set then report data underrun */
-+                              scb->hastat = HOST_DO_DU;
-+                      if ((initio_status_msg(host)) == -1)
-+                              return -1;
-                       break;
-               case MSG_IN:    /* Message in phase             */
--                      pCurScb->SCB_NxtStat = 0x4;
--                      if (tul_msgin(pCurHcb) == -1)
--                              return (-1);
-+                      scb->next_state = 0x4;
-+                      if (initio_msgin(host) == -1)
-+                              return -1;
-                       break;
-               case MSG_OUT:   /* Message out phase            */
--                      if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
--                              pCurScb->SCB_BufLen = 0;
--                              pCurScb->SCB_HaStat = HOST_DO_DU;
--                              if (tul_msgout_ide(pCurHcb) == -1)
--                                      return (-1);
--                              return (6);     /* Go to state 6                */
--                      } else {
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);         /* msg nop */
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--                              if (wait_tulip(pCurHcb) == -1)
--                                      return (-1);
-+                      if (host->jsstatus0 & TSS_PAR_ERROR) {
-+                              scb->buflen = 0;
-+                              scb->hastat = HOST_DO_DU;
-+                              if (initio_msgout_ide(host) == -1)
-+                                      return -1;
-+                              return 6;
-+                      } else {
-+                              outb(MSG_NOP, host->addr + TUL_SFifo);          /* msg nop */
-+                              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+                              if (wait_tulip(host) == -1)
-+                                      return -1;
-                       }
-                       break;
-               case DATA_IN:   /* Data in phase                */
--                      return (tul_xfer_data_in(pCurHcb));
-+                      return initio_xfer_data_in(host);
-               case DATA_OUT:  /* Data out phase               */
--                      return (tul_xfer_data_out(pCurHcb));
-+                      return initio_xfer_data_out(host);
-               default:
--                      return (tul_bad_seq(pCurHcb));
-+                      return initio_bad_seq(host);
-               }
-       }
- }
--/***************************************************************************/
--/* state after dma xfer done or phase change before xfer done */
--int tul_state_5(HCS * pCurHcb)
-+/**
-+ *    initio_state_5          -       SCSI state machine
-+ *    @host: InitIO host we are controlling
-+ *
-+ *    State after dma xfer done or phase change before xfer done
-+ */
++              /* Calculate how many this time */
++              wcount = (count > MAXOUT) ? MAXOUT : count;
 +
-+static int initio_state_5(struct initio_host * host)
- {
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
-+      struct scsi_ctrl_blk *scb = host->active;
-       long cnt, xcnt;         /* cannot use unsigned !! code: if (xcnt < 0) */
- #if DEBUG_STATE
-       printk("-s5-");
- #endif
--/*------ get remaining count -------*/
-+      /*------ get remaining count -------*/
-+      cnt = inl(host->addr + TUL_SCnt0) & 0x0FFFFFF;
--      cnt = TUL_RDLONG(pCurHcb->HCS_Base, TUL_SCnt0) & 0x0FFFFFF;
--
--      if (TUL_RD(pCurHcb->HCS_Base, TUL_XCmd) & 0x20) {
-+      if (inb(host->addr + TUL_XCmd) & 0x20) {
-               /* ----------------------- DATA_IN ----------------------------- */
-               /* check scsi parity error */
--              if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
--                      pCurScb->SCB_HaStat = HOST_DO_DU;
--              }
--              if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {   /* DMA xfer pending, Send STOP  */
-+              if (host->jsstatus0 & TSS_PAR_ERROR)
-+                      scb->hastat = HOST_DO_DU;
-+              if (inb(host->addr + TUL_XStatus) & XPEND) {    /* DMA xfer pending, Send STOP  */
-                       /* tell Hardware  scsi xfer has been terminated */
--                      TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, TUL_RD(pCurHcb->HCS_Base, TUL_XCtrl) | 0x80);
-+                      outb(inb(host->addr + TUL_XCtrl) | 0x80, host->addr + TUL_XCtrl);
-                       /* wait until DMA xfer not pending */
--                      while (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND);
-+                      while (inb(host->addr + TUL_XStatus) & XPEND)
-+                              cpu_relax();
-               }
-       } else {
--/*-------- DATA OUT -----------*/
--              if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) {
--                      if (pCurHcb->HCS_ActTcs->TCS_JS_Period & TSC_WIDE_SCSI)
--                              cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F) << 1;
-+              /*-------- DATA OUT -----------*/
-+              if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0) {
-+                      if (host->active_tc->js_period & TSC_WIDE_SCSI)
-+                              cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F) << 1;
-                       else
--                              cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F);
-+                              cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F);
-               }
--              if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {   /* if DMA xfer is pending, abort DMA xfer */
--                      TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT);
-+              if (inb(host->addr + TUL_XStatus) & XPEND) {    /* if DMA xfer is pending, abort DMA xfer */
-+                      outb(TAX_X_ABT, host->addr + TUL_XCmd);
-                       /* wait Abort DMA xfer done */
--                      while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
--              }
--              if ((cnt == 1) && (pCurHcb->HCS_Phase == DATA_OUT)) {
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--                      if (wait_tulip(pCurHcb) == -1) {
--                              return (-1);
-+                      while ((inb(host->addr + TUL_Int) & XABT) == 0)
-+                              cpu_relax();
-                       }
-+              if ((cnt == 1) && (host->phase == DATA_OUT)) {
-+                      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+                      if (wait_tulip(host) == -1)
-+                              return -1;
-                       cnt = 0;
-               } else {
--                      if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0)
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-+                      if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0)
-+                              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
-               }
-       }
--
-       if (cnt == 0) {
--              pCurScb->SCB_BufLen = 0;
--              return (6);     /* Go to state 6                */
-+              scb->buflen = 0;
-+              return 6;       /* After Data */
-       }
-       /* Update active data pointer */
--      xcnt = (long) pCurScb->SCB_BufLen - cnt;        /* xcnt== bytes already xferred */
--      pCurScb->SCB_BufLen = (U32) cnt;        /* cnt == bytes left to be xferred */
--      if (pCurScb->SCB_Flags & SCF_SG) {
--              register SG *sgp;
--              ULONG i;
--
--              sgp = &pCurScb->SCB_SGList[pCurScb->SCB_SGIdx];
--              for (i = pCurScb->SCB_SGIdx; i < pCurScb->SCB_SGMax; sgp++, i++) {
--                      xcnt -= (long) sgp->SG_Len;
-+      xcnt = (long) scb->buflen - cnt;        /* xcnt== bytes already xferred */
-+      scb->buflen = (u32) cnt;                /* cnt == bytes left to be xferred */
-+      if (scb->flags & SCF_SG) {
-+              struct sg_entry *sgp;
-+              unsigned long i;
-+
-+              sgp = &scb->sglist[scb->sgidx];
-+              for (i = scb->sgidx; i < scb->sgmax; sgp++, i++) {
-+                      xcnt -= (long) sgp->len;
-                       if (xcnt < 0) {         /* this sgp xfer half done */
--                              xcnt += (long) sgp->SG_Len;     /* xcnt == bytes xferred in this sgp */
--                              sgp->SG_Ptr += (U32) xcnt;      /* new ptr to be xfer */
--                              sgp->SG_Len -= (U32) xcnt;      /* new len to be xfer */
--                              pCurScb->SCB_BufPtr += ((U32) (i - pCurScb->SCB_SGIdx) << 3);
-+                              xcnt += (long) sgp->len;        /* xcnt == bytes xferred in this sgp */
-+                              sgp->data += (u32) xcnt;        /* new ptr to be xfer */
-+                              sgp->len -= (u32) xcnt; /* new len to be xfer */
-+                              scb->bufptr += ((u32) (i - scb->sgidx) << 3);
-                               /* new SG table ptr */
--                              pCurScb->SCB_SGLen = (BYTE) (pCurScb->SCB_SGMax - i);
-+                              scb->sglen = (u8) (scb->sgmax - i);
-                               /* new SG table len */
--                              pCurScb->SCB_SGIdx = (WORD) i;
-+                              scb->sgidx = (u16) i;
-                               /* for next disc and come in this loop */
--                              return (4);     /* Go to state 4                */
-+                              return 4;       /* Go to state 4                */
-                       }
-                       /* else (xcnt >= 0 , i.e. this sgp already xferred */
-               }               /* for */
--              return (6);     /* Go to state 6                */
-+              return 6;       /* Go to state 6                */
-       } else {
--              pCurScb->SCB_BufPtr += (U32) xcnt;
-+              scb->bufptr += (u32) xcnt;
-       }
--      return (4);             /* Go to state 4                */
-+      return 4;               /* Go to state 4                */
- }
--/***************************************************************************/
--/* state after Data phase */
--int tul_state_6(HCS * pCurHcb)
-+/**
-+ *    initio_state_6          -       SCSI state machine
-+ *    @host: InitIO host we are controlling
-+ *
-+ *    State after Data phase
-+ */
++              /* Pack in hex chars */
++              for (i = 0; i < wcount; i++)
++                      bufptr = pack_hex_byte(bufptr, s[i]);
++              *bufptr = '\0';
 +
-+static int initio_state_6(struct initio_host * host)
- {
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
-+      struct scsi_ctrl_blk *scb = host->active;
- #if DEBUG_STATE
-       printk("-s6-");
- #endif
-       for (;;) {
--              switch (pCurHcb->HCS_Phase) {
-+              switch (host->phase) {
-               case STATUS_IN: /* Status phase                 */
--                      if ((tul_status_msg(pCurHcb)) == -1)
--                              return (-1);
-+                      if ((initio_status_msg(host)) == -1)
-+                              return -1;
-                       break;
-               case MSG_IN:    /* Message in phase             */
--                      pCurScb->SCB_NxtStat = 6;
--                      if ((tul_msgin(pCurHcb)) == -1)
--                              return (-1);
-+                      scb->next_state = 6;
-+                      if ((initio_msgin(host)) == -1)
-+                              return -1;
-                       break;
-               case MSG_OUT:   /* Message out phase            */
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);         /* msg nop */
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--                      if (wait_tulip(pCurHcb) == -1)
--                              return (-1);
-+                      outb(MSG_NOP, host->addr + TUL_SFifo);          /* msg nop */
-+                      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+                      if (wait_tulip(host) == -1)
-+                              return -1;
-                       break;
-               case DATA_IN:   /* Data in phase                */
--                      return (tul_xpad_in(pCurHcb));
-+                      return initio_xpad_in(host);
-               case DATA_OUT:  /* Data out phase               */
--                      return (tul_xpad_out(pCurHcb));
-+                      return initio_xpad_out(host);
-               default:
--                      return (tul_bad_seq(pCurHcb));
-+                      return initio_bad_seq(host);
-               }
-       }
- }
--/***************************************************************************/
--int tul_state_7(HCS * pCurHcb)
-+/**
-+ *    initio_state_7          -       SCSI state machine
-+ *    @host: InitIO host we are controlling
-+ *
-+ */
++              /* Move up */
++              s += wcount;
++              count -= wcount;
++
++              /* Write packet */
++              put_packet(gdbmsgbuf);
++      }
++}
++
++static void kgdb_to_gdb(const char *s)
++{
++      kgdb_msg_write(s, strlen(s));
++}
++
++#ifdef CONFIG_SH_KGDB_CONSOLE
++void kgdb_console_write(struct console *co, const char *s, unsigned count)
++{
++      /* Bail if we're not talking to GDB */
++      if (!kgdb_in_gdb_mode)
++              return;
++
++      kgdb_msg_write(s, count);
++}
++#endif
++
++#ifdef CONFIG_KGDB_SYSRQ
++static void sysrq_handle_gdb(int key, struct tty_struct *tty)
++{
++      printk("Entering GDB stub\n");
++      breakpoint();
++}
++
++static struct sysrq_key_op sysrq_gdb_op = {
++        .handler        = sysrq_handle_gdb,
++        .help_msg       = "Gdb",
++        .action_msg     = "GDB",
++};
 +
-+int initio_state_7(struct initio_host * host)
- {
-       int cnt, i;
-@@ -1893,1139 +1678,1029 @@
-       printk("-s7-");
- #endif
-       /* flush SCSI FIFO */
--      cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F;
-+      cnt = inb(host->addr + TUL_SFifoCnt) & 0x1F;
-       if (cnt) {
-               for (i = 0; i < cnt; i++)
--                      TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
-+                      inb(host->addr + TUL_SFifo);
-       }
--      switch (pCurHcb->HCS_Phase) {
-+      switch (host->phase) {
-       case DATA_IN:           /* Data in phase                */
-       case DATA_OUT:          /* Data out phase               */
--              return (tul_bad_seq(pCurHcb));
-+              return initio_bad_seq(host);
-       default:
--              return (6);     /* Go to state 6                */
-+              return 6;       /* Go to state 6                */
-       }
- }
++static int gdb_register_sysrq(void)
++{
++      printk("Registering GDB sysrq handler\n");
++      register_sysrq_key('g', &sysrq_gdb_op);
++      return 0;
++}
++module_init(gdb_register_sysrq);
++#endif
+diff -Nurb linux-2.6.22-590/arch/sh/kernel/time.c linux-2.6.22-570/arch/sh/kernel/time.c
+--- linux-2.6.22-590/arch/sh/kernel/time.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/sh/kernel/time.c     2007-07-08 19:32:17.000000000 -0400
+@@ -259,4 +259,11 @@
+                      ((sh_hpt_frequency + 500) / 1000) / 1000,
+                      ((sh_hpt_frequency + 500) / 1000) % 1000);
  
--/***************************************************************************/
--int tul_xfer_data_in(HCS * pCurHcb)
-+/**
-+ *    initio_xfer_data_in     -       Commence data input
-+ *    @host: InitIO host in use
-+ *
-+ *    Commence a block of data transfer. The transfer itself will
-+ *    be managed by the controller and we will get a completion (or
-+ *    failure) interrupt.
-+ */
-+static int initio_xfer_data_in(struct initio_host * host)
- {
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
-+      struct scsi_ctrl_blk *scb = host->active;
--      if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) {
--              return (6);     /* wrong direction */
--      }
--      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
-+      if ((scb->flags & SCF_DIR) == SCF_DOUT)
-+              return 6;       /* wrong direction */
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_IN);    /* 7/25/95 */
-+      outl(scb->buflen, host->addr + TUL_SCnt0);
-+      outb(TSC_XF_DMA_IN, host->addr + TUL_SCmd);     /* 7/25/95 */
--      if (pCurScb->SCB_Flags & SCF_SG) {      /* S/G xfer */
--              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
--              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
--              TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_IN);
-+      if (scb->flags & SCF_SG) {      /* S/G xfer */
-+              outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);
-+              outl(scb->bufptr, host->addr + TUL_XAddH);
-+              outb(TAX_SG_IN, host->addr + TUL_XCmd);
-       } else {
--              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
--              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
--              TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_IN);
-+              outl(scb->buflen, host->addr + TUL_XCntH);
-+              outl(scb->bufptr, host->addr + TUL_XAddH);
-+              outb(TAX_X_IN, host->addr + TUL_XCmd);
-       }
--      pCurScb->SCB_NxtStat = 0x5;
--      return (0);             /* return to OS, wait xfer done , let jas_isr come in */
-+      scb->next_state = 0x5;
-+      return 0;               /* return to OS, wait xfer done , let jas_isr come in */
++#if defined(CONFIG_SH_KGDB)
++      /*
++       * Set up kgdb as requested. We do it here because the serial
++       * init uses the timer vars we just set up for figuring baud.
++       */
++      kgdb_init();
++#endif
  }
+diff -Nurb linux-2.6.22-590/arch/sh/kernel/traps.c linux-2.6.22-570/arch/sh/kernel/traps.c
+--- linux-2.6.22-590/arch/sh/kernel/traps.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/sh/kernel/traps.c    2007-07-08 19:32:17.000000000 -0400
+@@ -25,10 +25,16 @@
+ #include <linux/limits.h>
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+-#include <linux/kgdb.h>
  
-+/**
-+ *    initio_xfer_data_out    -       Commence data output
-+ *    @host: InitIO host in use
-+ *
-+ *    Commence a block of data transfer. The transfer itself will
-+ *    be managed by the controller and we will get a completion (or
-+ *    failure) interrupt.
-+ */
--/***************************************************************************/
--int tul_xfer_data_out(HCS * pCurHcb)
-+static int initio_xfer_data_out(struct initio_host * host)
- {
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
-+      struct scsi_ctrl_blk *scb = host->active;
+-#ifndef CONFIG_KGDB
+-#define kgdb_handle_exception(t, s, e, r)
++#ifdef CONFIG_SH_KGDB
++#include <asm/kgdb.h>
++#define CHK_REMOTE_DEBUG(regs)                        \
++{                                             \
++      if (kgdb_debug_hook && !user_mode(regs))\
++              (*kgdb_debug_hook)(regs);       \
++}
++#else
++#define CHK_REMOTE_DEBUG(regs)
+ #endif
  
--      if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) {
--              return (6);     /* wrong direction */
--      }
--      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_OUT);
-+      if ((scb->flags & SCF_DIR) == SCF_DIN)
-+              return 6;       /* wrong direction */
+ #ifdef CONFIG_CPU_SH2
+@@ -85,9 +91,7 @@
  
--      if (pCurScb->SCB_Flags & SCF_SG) {      /* S/G xfer */
--              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
--              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
--              TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_OUT);
-+      outl(scb->buflen, host->addr + TUL_SCnt0);
-+      outb(TSC_XF_DMA_OUT, host->addr + TUL_SCmd);
-+
-+      if (scb->flags & SCF_SG) {      /* S/G xfer */
-+              outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);
-+              outl(scb->bufptr, host->addr + TUL_XAddH);
-+              outb(TAX_SG_OUT, host->addr + TUL_XCmd);
-       } else {
--              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
--              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
--              TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_OUT);
-+              outl(scb->buflen, host->addr + TUL_XCntH);
-+              outl(scb->bufptr, host->addr + TUL_XAddH);
-+              outb(TAX_X_OUT, host->addr + TUL_XCmd);
-       }
+       printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
  
--      pCurScb->SCB_NxtStat = 0x5;
--      return (0);             /* return to OS, wait xfer done , let jas_isr come in */
-+      scb->next_state = 0x5;
-+      return 0;               /* return to OS, wait xfer done , let jas_isr come in */
- }
+-#ifdef CONFIG_KGDB
+-      kgdb_handle_exception(1, SIGTRAP, err, regs);
+-#endif
++      CHK_REMOTE_DEBUG(regs);
+       print_modules();
+       show_regs(regs);
  
--
--/***************************************************************************/
--int tul_xpad_in(HCS * pCurHcb)
-+int initio_xpad_in(struct initio_host * host)
- {
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
--      TCS *pCurTcb = pCurHcb->HCS_ActTcs;
-+      struct scsi_ctrl_blk *scb = host->active;
-+      struct target_control *active_tc = host->active_tc;
+@@ -696,9 +700,7 @@
+       lookup_exception_vector(error_code);
  
--      if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
--              pCurScb->SCB_HaStat = HOST_DO_DU;       /* over run             */
--      }
-+      if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)
-+              scb->hastat = HOST_DO_DU;       /* over run             */
-       for (;;) {
--              if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
--                      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
-+              if (active_tc->js_period & TSC_WIDE_SCSI)
-+                      outl(2, host->addr + TUL_SCnt0);
-               else
--                      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
-+                      outl(1, host->addr + TUL_SCnt0);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
--              if ((wait_tulip(pCurHcb)) == -1) {
--                      return (-1);
--              }
--              if (pCurHcb->HCS_Phase != DATA_IN) {
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
--                      return (6);
-+              outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
-+              if (wait_tulip(host) == -1)
-+                      return -1;
-+              if (host->phase != DATA_IN) {
-+                      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
-+                      return 6;
-               }
--              TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
-+              inb(host->addr + TUL_SFifo);
-       }
+       local_irq_enable();
+-#ifdef CONFIG_KGDB
+-      kgdb_handle_exception(1, SIGILL, err, regs);
+-#endif
++      CHK_REMOTE_DEBUG(regs);
+       force_sig(SIGILL, tsk);
+       die_if_no_fixup("reserved instruction", regs, error_code);
  }
+@@ -769,9 +771,7 @@
+       lookup_exception_vector(error_code);
  
--int tul_xpad_out(HCS * pCurHcb)
-+int initio_xpad_out(struct initio_host * host)
- {
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
--      TCS *pCurTcb = pCurHcb->HCS_ActTcs;
-+      struct scsi_ctrl_blk *scb = host->active;
-+      struct target_control *active_tc = host->active_tc;
--      if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
--              pCurScb->SCB_HaStat = HOST_DO_DU;       /* over run             */
--      }
-+      if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)
-+              scb->hastat = HOST_DO_DU;       /* over run             */
-       for (;;) {
--              if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
--                      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
-+              if (active_tc->js_period & TSC_WIDE_SCSI)
-+                      outl(2, host->addr + TUL_SCnt0);
-               else
--                      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
-+                      outl(1, host->addr + TUL_SCnt0);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--              if ((wait_tulip(pCurHcb)) == -1) {
--                      return (-1);
--              }
--              if (pCurHcb->HCS_Phase != DATA_OUT) {   /* Disable wide CPU to allow read 16 bits */
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
--                      return (6);
-+              outb(0, host->addr + TUL_SFifo);
-+              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+              if ((wait_tulip(host)) == -1)
-+                      return -1;
-+              if (host->phase != DATA_OUT) {  /* Disable wide CPU to allow read 16 bits */
-+                      outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
-+                      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
-+                      return 6;
-               }
-       }
+       local_irq_enable();
+-#ifdef CONFIG_KGDB
+-      kgdb_handle_exception(1, SIGILL, err, regs);
+-#endif
++      CHK_REMOTE_DEBUG(regs);
+       force_sig(SIGILL, tsk);
+       die_if_no_fixup("illegal slot instruction", regs, error_code);
  }
+diff -Nurb linux-2.6.22-590/arch/sh/mm/extable.c linux-2.6.22-570/arch/sh/mm/extable.c
+--- linux-2.6.22-590/arch/sh/mm/extable.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/sh/mm/extable.c      2007-07-08 19:32:17.000000000 -0400
+@@ -5,7 +5,6 @@
+  */
  
--
--/***************************************************************************/
--int tul_status_msg(HCS * pCurHcb)
-+int initio_status_msg(struct initio_host * host)
- {                             /* status & MSG_IN */
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
--      BYTE msg;
-+      struct scsi_ctrl_blk *scb = host->active;
-+      u8 msg;
-+
-+      outb(TSC_CMD_COMP, host->addr + TUL_SCmd);
-+      if (wait_tulip(host) == -1)
-+              return -1;
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_CMD_COMP);
--      if ((wait_tulip(pCurHcb)) == -1) {
--              return (-1);
--      }
-       /* get status */
--      pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
-+      scb->tastat = inb(host->addr + TUL_SFifo);
--      if (pCurHcb->HCS_Phase == MSG_OUT) {
--              if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
--              } else {
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);
--              }
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--              return (wait_tulip(pCurHcb));
--      }
--      if (pCurHcb->HCS_Phase == MSG_IN) {
--              msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
--              if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {   /* Parity error                 */
--                      if ((tul_msgin_accept(pCurHcb)) == -1)
--                              return (-1);
--                      if (pCurHcb->HCS_Phase != MSG_OUT)
--                              return (tul_bad_seq(pCurHcb));
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--                      return (wait_tulip(pCurHcb));
-+      if (host->phase == MSG_OUT) {
-+              if (host->jsstatus0 & TSS_PAR_ERROR)
-+                      outb(MSG_PARITY, host->addr + TUL_SFifo);
-+              else
-+                      outb(MSG_NOP, host->addr + TUL_SFifo);
-+              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+              return wait_tulip(host);
-+      }
-+      if (host->phase == MSG_IN) {
-+              msg = inb(host->addr + TUL_SFifo);
-+              if (host->jsstatus0 & TSS_PAR_ERROR) {  /* Parity error                 */
-+                      if ((initio_msgin_accept(host)) == -1)
-+                              return -1;
-+                      if (host->phase != MSG_OUT)
-+                              return initio_bad_seq(host);
-+                      outb(MSG_PARITY, host->addr + TUL_SFifo);
-+                      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+                      return wait_tulip(host);
-               }
-               if (msg == 0) { /* Command complete             */
--                      if ((pCurScb->SCB_TaStat & 0x18) == 0x10) {     /* No link support              */
--                              return (tul_bad_seq(pCurHcb));
--                      }
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
--                      return tul_wait_done_disc(pCurHcb);
-+                      if ((scb->tastat & 0x18) == 0x10)       /* No link support              */
-+                              return initio_bad_seq(host);
-+                      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
-+                      outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
-+                      return initio_wait_done_disc(host);
+ #include <linux/module.h>
+-#include <linux/kgdb.h>
+ #include <asm/uaccess.h>
  
-               }
--              if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) {
--                      if ((pCurScb->SCB_TaStat & 0x18) == 0x10)
--                              return (tul_msgin_accept(pCurHcb));
-+              if (msg == MSG_LINK_COMP || msg == MSG_LINK_FLAG) {
-+                      if ((scb->tastat & 0x18) == 0x10)
-+                              return initio_msgin_accept(host);
-               }
+ int fixup_exception(struct pt_regs *regs)
+@@ -17,12 +16,6 @@
+               regs->pc = fixup->fixup;
+               return 1;
        }
--      return (tul_bad_seq(pCurHcb));
-+      return initio_bad_seq(host);
- }
+-#ifdef CONFIG_KGDB
+-      if (atomic_read(&debugger_active) && kgdb_may_fault)
+-              /* Restore our previous state. */
+-              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+-              /* Never reached. */
+-#endif
  
--/***************************************************************************/
- /* scsi bus free */
--int int_tul_busfree(HCS * pCurHcb)
-+int int_initio_busfree(struct initio_host * host)
- {
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
-+      struct scsi_ctrl_blk *scb = host->active;
--      if (pCurScb != NULL) {
--              if (pCurScb->SCB_Status & SCB_SELECT) {         /* selection timeout */
--                      tul_unlink_pend_scb(pCurHcb, pCurScb);
--                      pCurScb->SCB_HaStat = HOST_SEL_TOUT;
--                      tul_append_done_scb(pCurHcb, pCurScb);
-+      if (scb != NULL) {
-+              if (scb->status & SCB_SELECT) {         /* selection timeout */
-+                      initio_unlink_pend_scb(host, scb);
-+                      scb->hastat = HOST_SEL_TOUT;
-+                      initio_append_done_scb(host, scb);
-               } else {        /* Unexpected bus free          */
--                      tul_unlink_busy_scb(pCurHcb, pCurScb);
--                      pCurScb->SCB_HaStat = HOST_BUS_FREE;
--                      tul_append_done_scb(pCurHcb, pCurScb);
--              }
--              pCurHcb->HCS_ActScb = NULL;
--              pCurHcb->HCS_ActTcs = NULL;
--      }
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);         /* Flush SCSI FIFO  */
--      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);        /* Enable HW reselect       */
--      return (-1);
-+                      initio_unlink_busy_scb(host, scb);
-+                      scb->hastat = HOST_BUS_FREE;
-+                      initio_append_done_scb(host, scb);
-+              }
-+              host->active = NULL;
-+              host->active_tc = NULL;
-+      }
-+      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);          /* Flush SCSI FIFO  */
-+      outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
-+      outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect       */
-+      return -1;
+       return 0;
  }
+diff -Nurb linux-2.6.22-590/arch/sh/mm/fault-nommu.c linux-2.6.22-570/arch/sh/mm/fault-nommu.c
+--- linux-2.6.22-590/arch/sh/mm/fault-nommu.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/sh/mm/fault-nommu.c  2007-07-08 19:32:17.000000000 -0400
+@@ -28,6 +28,10 @@
+ #include <asm/mmu_context.h>
+ #include <asm/cacheflush.h>
  
++#if defined(CONFIG_SH_KGDB)
++#include <asm/kgdb.h>
++#endif
++
+ extern void die(const char *,struct pt_regs *,long);
  
--/***************************************************************************/
--/* scsi bus reset */
--static int int_tul_scsi_rst(HCS * pCurHcb)
-+/**
-+ *    int_initio_scsi_rst     -       SCSI reset occurred
-+ *    @host: Host seeing the reset
-+ *
-+ *    A SCSI bus reset has occurred. Clean up any pending transfer
-+ *    the hardware is doing by DMA and then abort all active and
-+ *    disconnected commands. The mid layer should sort the rest out
-+ *    for us
-+ */
+ /*
+@@ -38,6 +42,11 @@
+ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+                             unsigned long address)
+ {
++#if defined(CONFIG_SH_KGDB)
++      if (kgdb_nofault && kgdb_bus_err_hook)
++              kgdb_bus_err_hook();
++#endif
 +
-+static int int_initio_scsi_rst(struct initio_host * host)
+       /*
+        * Oops. The kernel tried to access some bad page. We'll have to
+        * terminate things with extreme prejudice.
+@@ -59,6 +68,11 @@
+ asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+                              unsigned long address)
  {
--      SCB *pCurScb;
-+      struct scsi_ctrl_blk *scb;
-       int i;
-       /* if DMA xfer is pending, abort DMA xfer */
--      if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) {
--              TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
-+      if (inb(host->addr + TUL_XStatus) & 0x01) {
-+              outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);
-               /* wait Abort DMA xfer done */
--              while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
-+              while ((inb(host->addr + TUL_Int) & 0x04) == 0)
-+                      cpu_relax();
-+              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
-       }
-       /* Abort all active & disconnected scb */
--      while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
--              pCurScb->SCB_HaStat = HOST_BAD_PHAS;
--              tul_append_done_scb(pCurHcb, pCurScb);
-+      while ((scb = initio_pop_busy_scb(host)) != NULL) {
-+              scb->hastat = HOST_BAD_PHAS;
-+              initio_append_done_scb(host, scb);
-       }
--      pCurHcb->HCS_ActScb = NULL;
--      pCurHcb->HCS_ActTcs = NULL;
-+      host->active = NULL;
-+      host->active_tc = NULL;
++#if defined(CONFIG_SH_KGDB)
++      if (kgdb_nofault && kgdb_bus_err_hook)
++              kgdb_bus_err_hook();
++#endif
++
+       if (address >= TASK_SIZE)
+               return 1;
  
-       /* clr sync nego. done flag */
--      for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
--              pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
--      }
--      return (-1);
-+      for (i = 0; i < host->max_tar; i++)
-+              host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
-+      return -1;
- }
+diff -Nurb linux-2.6.22-590/arch/sh/mm/fault.c linux-2.6.22-570/arch/sh/mm/fault.c
+--- linux-2.6.22-590/arch/sh/mm/fault.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/sh/mm/fault.c        2008-01-23 19:16:04.000000000 -0500
+@@ -18,6 +18,7 @@
+ #include <asm/system.h>
+ #include <asm/mmu_context.h>
+ #include <asm/tlbflush.h>
++#include <asm/kgdb.h>
  
-+/**
-+ *    int_initio_scsi_resel   -       Reselection occured
-+ *    @host: InitIO host adapter
-+ *
-+ *    A SCSI reselection event has been signalled and the interrupt
-+ *    is now being processed. Work out which command block needs attention
-+ *    and continue processing that command.
-+ */
+ /*
+  * This routine handles page faults.  It determines the address,
+@@ -38,6 +39,11 @@
+       trace_hardirqs_on();
+       local_irq_enable();
  
--/***************************************************************************/
--/* scsi reselection */
--int int_tul_resel(HCS * pCurHcb)
-+int int_initio_resel(struct initio_host * host)
- {
--      SCB *pCurScb;
--      TCS *pCurTcb;
--      BYTE tag, msg = 0;
--      BYTE tar, lun;
--
--      if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
--              if (pCurScb->SCB_Status & SCB_SELECT) {         /* if waiting for selection complete */
--                      pCurScb->SCB_Status &= ~SCB_SELECT;
--              }
--              pCurHcb->HCS_ActScb = NULL;
-+      struct scsi_ctrl_blk *scb;
-+      struct target_control *active_tc;
-+      u8 tag, msg = 0;
-+      u8 tar, lun;
++#ifdef CONFIG_SH_KGDB
++      if (kgdb_nofault && kgdb_bus_err_hook)
++              kgdb_bus_err_hook();
++#endif
 +
-+      if ((scb = host->active) != NULL) {
-+              /* FIXME: Why check and not just clear ? */
-+              if (scb->status & SCB_SELECT)           /* if waiting for selection complete */
-+                      scb->status &= ~SCB_SELECT;
-+              host->active = NULL;
+       tsk = current;
+       mm = tsk->mm;
+       si_code = SEGV_MAPERR;
+@@ -183,7 +189,6 @@
        }
-       /* --------- get target id---------------------- */
--      tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId);
-+      tar = inb(host->addr + TUL_SBusId);
-       /* ------ get LUN from Identify message----------- */
--      lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F;
-+      lun = inb(host->addr + TUL_SIdent) & 0x0F;
-       /* 07/22/98 from 0x1F -> 0x0F */
--      pCurTcb = &pCurHcb->HCS_Tcs[tar];
--      pCurHcb->HCS_ActTcs = pCurTcb;
--      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
--
-+      active_tc = &host->targets[tar];
-+      host->active_tc = active_tc;
-+      outb(active_tc->sconfig0, host->addr + TUL_SConfig);
-+      outb(active_tc->js_period, host->addr + TUL_SPeriod);
-       /* ------------- tag queueing ? ------------------- */
--      if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) {
--              if ((tul_msgin_accept(pCurHcb)) == -1)
--                      return (-1);
--              if (pCurHcb->HCS_Phase != MSG_IN)
-+      if (active_tc->drv_flags & TCF_DRV_EN_TAG) {
-+              if ((initio_msgin_accept(host)) == -1)
-+                      return -1;
-+              if (host->phase != MSG_IN)
-                       goto no_tag;
--              TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
--              if ((wait_tulip(pCurHcb)) == -1)
--                      return (-1);
--              msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);     /* Read Tag Message    */
-+              outl(1, host->addr + TUL_SCnt0);
-+              outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
-+              if (wait_tulip(host) == -1)
-+                      return -1;
-+              msg = inb(host->addr + TUL_SFifo);      /* Read Tag Message    */
--              if ((msg < MSG_STAG) || (msg > MSG_OTAG))       /* Is simple Tag      */
-+              if (msg < MSG_STAG || msg > MSG_OTAG)           /* Is simple Tag      */
-                       goto no_tag;
--              if ((tul_msgin_accept(pCurHcb)) == -1)
--                      return (-1);
-+              if (initio_msgin_accept(host) == -1)
-+                      return -1;
--              if (pCurHcb->HCS_Phase != MSG_IN)
-+              if (host->phase != MSG_IN)
-                       goto no_tag;
+       die("Oops", regs, writeaccess);
+       do_exit(SIGKILL);
+-      dump_stack();
  
--              TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
--              if ((wait_tulip(pCurHcb)) == -1)
--                      return (-1);
--              tag = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);     /* Read Tag ID       */
--              pCurScb = pCurHcb->HCS_Scb + tag;
--              if ((pCurScb->SCB_Target != tar) || (pCurScb->SCB_Lun != lun)) {
--                      return tul_msgout_abort_tag(pCurHcb);
--              }
--              if (pCurScb->SCB_Status != SCB_BUSY) {  /* 03/24/95             */
--                      return tul_msgout_abort_tag(pCurHcb);
--              }
--              pCurHcb->HCS_ActScb = pCurScb;
--              if ((tul_msgin_accept(pCurHcb)) == -1)
--                      return (-1);
-+              outl(1, host->addr + TUL_SCnt0);
-+              outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
-+              if (wait_tulip(host) == -1)
-+                      return -1;
-+              tag = inb(host->addr + TUL_SFifo);      /* Read Tag ID       */
-+              scb = host->scb + tag;
-+              if (scb->target != tar || scb->lun != lun) {
-+                      return initio_msgout_abort_tag(host);
-+              }
-+              if (scb->status != SCB_BUSY) {  /* 03/24/95             */
-+                      return initio_msgout_abort_tag(host);
-+              }
-+              host->active = scb;
-+              if ((initio_msgin_accept(host)) == -1)
-+                      return -1;
-       } else {                /* No tag               */
-             no_tag:
--              if ((pCurScb = tul_find_busy_scb(pCurHcb, tar | (lun << 8))) == NULL) {
--                      return tul_msgout_abort_targ(pCurHcb);
-+              if ((scb = initio_find_busy_scb(host, tar | (lun << 8))) == NULL) {
-+                      return initio_msgout_abort_targ(host);
-               }
--              pCurHcb->HCS_ActScb = pCurScb;
--              if (!(pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG)) {
--                      if ((tul_msgin_accept(pCurHcb)) == -1)
--                              return (-1);
-+              host->active = scb;
-+              if (!(active_tc->drv_flags & TCF_DRV_EN_TAG)) {
-+                      if ((initio_msgin_accept(host)) == -1)
-+                              return -1;
-               }
-       }
-       return 0;
- }
+ /*
+  * We ran out of memory, or some other thing happened to us that made
+@@ -247,6 +252,11 @@
+       spinlock_t *ptl = NULL;
+       int ret = 1;
  
-+/**
-+ *    int_initio_bad_seq              -       out of phase
-+ *    @host: InitIO host flagging event
-+ *
-+ *    We have ended up out of phase somehow. Reset the host controller
-+ *    and throw all our toys out of the pram. Let the midlayer clean up
-+ */
++#ifdef CONFIG_SH_KGDB
++      if (kgdb_nofault && kgdb_bus_err_hook)
++              kgdb_bus_err_hook();
++#endif
++
+       /*
+        * We don't take page faults for P1, P2, and parts of P4, these
+        * are always mapped, whether it be due to legacy behaviour in
+diff -Nurb linux-2.6.22-590/arch/sparc64/kernel/power.c linux-2.6.22-570/arch/sparc64/kernel/power.c
+--- linux-2.6.22-590/arch/sparc64/kernel/power.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/sparc64/kernel/power.c       2007-07-08 19:32:17.000000000 -0400
+@@ -13,7 +13,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/pm.h>
+ #include <linux/syscalls.h>
+-#include <linux/reboot.h>
  
--/***************************************************************************/
--static int int_tul_bad_seq(HCS * pCurHcb)
-+static int int_initio_bad_seq(struct initio_host * host)
- {                             /* target wrong phase           */
--      SCB *pCurScb;
-+      struct scsi_ctrl_blk *scb;
-       int i;
+ #include <asm/system.h>
+ #include <asm/auxio.h>
+@@ -34,13 +33,14 @@
+ #include <linux/pci.h>
+ static void __iomem *power_reg;
  
--      tul_reset_scsi(pCurHcb, 10);
-+      initio_reset_scsi(host, 10);
++static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
+ static int button_pressed;
  
--      while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
--              pCurScb->SCB_HaStat = HOST_BAD_PHAS;
--              tul_append_done_scb(pCurHcb, pCurScb);
-+      while ((scb = initio_pop_busy_scb(host)) != NULL) {
-+              scb->hastat = HOST_BAD_PHAS;
-+              initio_append_done_scb(host, scb);
+ static irqreturn_t power_handler(int irq, void *dev_id)
+ {
+       if (button_pressed == 0) {
+               button_pressed = 1;
+-              orderly_poweroff(true);
++              wake_up(&powerd_wait);
        }
--      for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
--              pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
--      }
--      return (-1);
-+      for (i = 0; i < host->max_tar; i++)
-+              host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
-+      return -1;
- }
  
+       /* FIXME: Check registers for status... */
+@@ -77,6 +77,36 @@
+ EXPORT_SYMBOL(pm_power_off);
  
--/***************************************************************************/
--int tul_msgout_abort_targ(HCS * pCurHcb)
-+/**
-+ *    initio_msgout_abort_targ                -       abort a tag
-+ *    @host: InitIO host
-+ *
-+ *    Abort when the target/lun does not match or when our SCB is not
-+ *    busy. Used by untagged commands.
-+ */
+ #ifdef CONFIG_PCI
++static int powerd(void *__unused)
++{
++      static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
++      char *argv[] = { "/sbin/shutdown", "-h", "now", NULL };
++      DECLARE_WAITQUEUE(wait, current);
++
++      daemonize("powerd");
++
++      add_wait_queue(&powerd_wait, &wait);
++again:
++      for (;;) {
++              set_task_state(current, TASK_INTERRUPTIBLE);
++              if (button_pressed)
++                      break;
++              flush_signals(current);
++              schedule();
++      }
++      __set_current_state(TASK_RUNNING);
++      remove_wait_queue(&powerd_wait, &wait);
 +
-+static int initio_msgout_abort_targ(struct initio_host * host)
++      /* Ok, down we go... */
++      button_pressed = 0;
++      if (kernel_execve("/sbin/shutdown", argv, envp) < 0) {
++              printk("powerd: shutdown execution failed\n");
++              add_wait_queue(&powerd_wait, &wait);
++              goto again;
++      }
++      return 0;
++}
++
+ static int __init has_button_interrupt(unsigned int irq, struct device_node *dp)
  {
+       if (irq == PCI_IRQ_NONE)
+@@ -100,6 +130,12 @@
+       poweroff_method = machine_halt;  /* able to use the standard halt */
  
--      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
--      if (tul_msgin_accept(pCurHcb) == -1)
--              return (-1);
--      if (pCurHcb->HCS_Phase != MSG_OUT)
--              return (tul_bad_seq(pCurHcb));
-+      outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
-+      if (initio_msgin_accept(host) == -1)
-+              return -1;
-+      if (host->phase != MSG_OUT)
-+              return initio_bad_seq(host);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-+      outb(MSG_ABORT, host->addr + TUL_SFifo);
-+      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+       if (has_button_interrupt(irq, op->node)) {
++              if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
++                      printk("Failed to start power daemon.\n");
++                      return 0;
++              }
++              printk("powerd running.\n");
++
+               if (request_irq(irq,
+                               power_handler, 0, "power", NULL) < 0)
+                       printk("power: Error, cannot register IRQ handler.\n");
+diff -Nurb linux-2.6.22-590/arch/sparc64/solaris/ioctl.c linux-2.6.22-570/arch/sparc64/solaris/ioctl.c
+--- linux-2.6.22-590/arch/sparc64/solaris/ioctl.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/sparc64/solaris/ioctl.c      2007-07-08 19:32:17.000000000 -0400
+@@ -28,7 +28,6 @@
+ #include <linux/compat.h>
  
--      return tul_wait_disc(pCurHcb);
-+      return initio_wait_disc(host);
- }
+ #include <net/sock.h>
+-#include <net/net_namespace.h>
  
--/***************************************************************************/
--int tul_msgout_abort_tag(HCS * pCurHcb)
-+/**
-+ *    initio_msgout_abort_tag         -       abort a tag
-+ *    @host: InitIO host
-+ *
-+ *    Abort when the target/lun does not match or when our SCB is not
-+ *    busy. Used for tagged commands.
-+ */
-+
-+static int initio_msgout_abort_tag(struct initio_host * host)
- {
+ #include <asm/uaccess.h>
+ #include <asm/termios.h>
+@@ -687,7 +686,7 @@
+                       int i = 0;
+                       
+                       read_lock_bh(&dev_base_lock);
+-                      for_each_netdev(&init_net, d)
++                      for_each_netdev(d)
+                               i++;
+                       read_unlock_bh(&dev_base_lock);
  
--      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
--      if (tul_msgin_accept(pCurHcb) == -1)
--              return (-1);
--      if (pCurHcb->HCS_Phase != MSG_OUT)
--              return (tul_bad_seq(pCurHcb));
-+      outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
-+      if (initio_msgin_accept(host) == -1)
-+              return -1;
-+      if (host->phase != MSG_OUT)
-+              return initio_bad_seq(host);
+diff -Nurb linux-2.6.22-590/arch/um/Kconfig.debug linux-2.6.22-570/arch/um/Kconfig.debug
+--- linux-2.6.22-590/arch/um/Kconfig.debug     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/um/Kconfig.debug     2007-07-08 19:32:17.000000000 -0400
+@@ -47,13 +47,4 @@
+         If you're involved in UML kernel development and want to use gcov,
+         say Y.  If you're unsure, say N.
  
--      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT_TAG);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
-+      outb(MSG_ABORT_TAG, host->addr + TUL_SFifo);
-+      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-config DEBUG_STACK_USAGE
+-      bool "Stack utilization instrumentation"
+-      default N
+-      help
+-        Track the maximum kernel stack usage - this will look at each
+-        kernel stack at process exit and log it if it's the deepest
+-        stack seen so far.
+-
+-        This option will slow down process creation and destruction somewhat.
+ endmenu
+diff -Nurb linux-2.6.22-590/arch/um/defconfig linux-2.6.22-570/arch/um/defconfig
+--- linux-2.6.22-590/arch/um/defconfig 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/um/defconfig 2007-07-08 19:32:17.000000000 -0400
+@@ -527,4 +527,3 @@
+ # CONFIG_RCU_TORTURE_TEST is not set
+ # CONFIG_GPROF is not set
+ # CONFIG_GCOV is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+diff -Nurb linux-2.6.22-590/arch/x86_64/Kconfig linux-2.6.22-570/arch/x86_64/Kconfig
+--- linux-2.6.22-590/arch/x86_64/Kconfig       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/Kconfig       2008-01-23 19:16:04.000000000 -0500
+@@ -698,8 +698,6 @@
  
--      return tul_wait_disc(pCurHcb);
-+      return initio_wait_disc(host);
+ source "arch/x86_64/kernel/cpufreq/Kconfig"
  
- }
+-source "drivers/cpuidle/Kconfig"
+-
+ endmenu
  
--/***************************************************************************/
--int tul_msgin(HCS * pCurHcb)
-+/**
-+ *    initio_msgin            -       Message in
-+ *    @host: InitIO Host
-+ *
-+ *    Process incoming message
-+ */
-+static int initio_msgin(struct initio_host * host)
- {
--      TCS *pCurTcb;
-+      struct target_control *active_tc;
+ menu "Bus options (PCI etc.)"
+diff -Nurb linux-2.6.22-590/arch/x86_64/Kconfig.debug linux-2.6.22-570/arch/x86_64/Kconfig.debug
+--- linux-2.6.22-590/arch/x86_64/Kconfig.debug 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/Kconfig.debug 2007-07-08 19:32:17.000000000 -0400
+@@ -55,4 +55,7 @@
  
-       for (;;) {
-+              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+         This option will slow down process creation somewhat.
  
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
--
--              TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
--              if ((wait_tulip(pCurHcb)) == -1)
--                      return (-1);
-+              outl(1, host->addr + TUL_SCnt0);
-+              outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
-+              if (wait_tulip(host) == -1)
-+                      return -1;
++#config X86_REMOTE_DEBUG
++#       bool "kgdb debugging stub"
++
+ endmenu
+diff -Nurb linux-2.6.22-590/arch/x86_64/Makefile linux-2.6.22-570/arch/x86_64/Makefile
+--- linux-2.6.22-590/arch/x86_64/Makefile      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/Makefile      2008-01-23 19:15:55.000000000 -0500
+@@ -41,9 +41,7 @@
+ cflags-y += -mcmodel=kernel
+ cflags-y += -pipe
+ cflags-y += -Wno-sign-compare
+-ifneq ($(CONFIG_UNWIND_INFO),y)
+ cflags-y += -fno-asynchronous-unwind-tables
+-endif
+ ifneq ($(CONFIG_DEBUG_INFO),y)
+ # -fweb shrinks the kernel a bit, but the difference is very small
+ # it also messes up debugging, so don't use it for now.
+diff -Nurb linux-2.6.22-590/arch/x86_64/ia32/ia32entry.S linux-2.6.22-570/arch/x86_64/ia32/ia32entry.S
+--- linux-2.6.22-590/arch/x86_64/ia32/ia32entry.S      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/ia32/ia32entry.S      2008-01-23 19:16:04.000000000 -0500
+@@ -731,7 +731,4 @@
+       .quad compat_sys_signalfd
+       .quad compat_sys_timerfd
+       .quad sys_eventfd
+-      .quad sys_revokeat
+-      .quad sys_frevoke               /* 325 */
+-      .quad sys_fallocate
+ ia32_syscall_end:
+diff -Nurb linux-2.6.22-590/arch/x86_64/kernel/Makefile linux-2.6.22-570/arch/x86_64/kernel/Makefile
+--- linux-2.6.22-590/arch/x86_64/kernel/Makefile       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/kernel/Makefile       2008-01-23 19:15:55.000000000 -0500
+@@ -33,12 +33,10 @@
+ obj-$(CONFIG_CALGARY_IOMMU)   += pci-calgary.o tce.o
+ obj-$(CONFIG_SWIOTLB)         += pci-swiotlb.o
+ obj-$(CONFIG_KPROBES)         += kprobes.o
+-obj-$(CONFIG_KGDB)            += kgdb.o kgdb-jmp.o
+ obj-$(CONFIG_X86_PM_TIMER)    += pmtimer.o
+ obj-$(CONFIG_X86_VSMP)                += vsmp.o
+ obj-$(CONFIG_K8_NB)           += k8.o
+ obj-$(CONFIG_AUDIT)           += audit.o
+-obj-$(CONFIG_STACK_UNWIND)    += unwind.o
  
--              switch (TUL_RD(pCurHcb->HCS_Base, TUL_SFifo)) {
-+              switch (inb(host->addr + TUL_SFifo)) {
-               case MSG_DISC:  /* Disconnect msg */
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
+ obj-$(CONFIG_MODULES)         += module.o
+ obj-$(CONFIG_PCI)             += early-quirks.o
+diff -Nurb linux-2.6.22-590/arch/x86_64/kernel/kgdb-jmp.S linux-2.6.22-570/arch/x86_64/kernel/kgdb-jmp.S
+--- linux-2.6.22-590/arch/x86_64/kernel/kgdb-jmp.S     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/kernel/kgdb-jmp.S     1969-12-31 19:00:00.000000000 -0500
+@@ -1,65 +0,0 @@
+-/*
+- * arch/x86_64/kernel/kgdb-jmp.S
+- *
+- * Save and restore system registers so that within a limited frame we
+- * may have a fault and "jump back" to a known safe location.
+- *
+- * Author: Tom Rini <trini@kernel.crashing.org>
+- *
+- * Cribbed from glibc, which carries the following:
+- * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+- * Copyright (C) 2005 by MontaVista Software.
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program as licensed "as is" without any warranty of
+- * any kind, whether express or implied.
+- */
 -
--                      return tul_wait_disc(pCurHcb);
+-#include <linux/linkage.h>
 -
-+                      outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
-+                      return initio_wait_disc(host);
-               case MSG_SDP:
-               case MSG_RESTORE:
-               case MSG_NOP:
--                      tul_msgin_accept(pCurHcb);
-+                      initio_msgin_accept(host);
-                       break;
+-#define JB_RBX                0
+-#define JB_RBP                1
+-#define JB_R12                2
+-#define JB_R13                3
+-#define JB_R14                4
+-#define JB_R15                5
+-#define JB_RSP                6
+-#define JB_PC         7
 -
-               case MSG_REJ:   /* Clear ATN first              */
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal,
--                             (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
--                      pCurTcb = pCurHcb->HCS_ActTcs;
--                      if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {   /* do sync nego */
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
--                      }
--                      tul_msgin_accept(pCurHcb);
-+                      outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)),
-+                              host->addr + TUL_SSignal);
-+                      active_tc = host->active_tc;
-+                      if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)       /* do sync nego */
-+                              outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN),
-+                                      host->addr + TUL_SSignal);
-+                      initio_msgin_accept(host);
-                       break;
+-      .code64
 -
-               case MSG_EXTEND:        /* extended msg */
--                      tul_msgin_extend(pCurHcb);
-+                      initio_msgin_extend(host);
-                       break;
+-/* This must be called prior to kgdb_fault_longjmp and
+- * kgdb_fault_longjmp must not be called outside of the context of the
+- * last call to kgdb_fault_setjmp.
+- */
+-ENTRY(kgdb_fault_setjmp)
+-      /* Save registers. */
+-      movq %rbx, (JB_RBX*8)(%rdi)
+-      movq %rbp, (JB_RBP*8)(%rdi)
+-      movq %r12, (JB_R12*8)(%rdi)
+-      movq %r13, (JB_R13*8)(%rdi)
+-      movq %r14, (JB_R14*8)(%rdi)
+-      movq %r15, (JB_R15*8)(%rdi)
+-      leaq 8(%rsp), %rdx      /* Save SP as it will be after we return. */
+-      movq %rdx, (JB_RSP*8)(%rdi)
+-      movq (%rsp), %rax       /* Save PC we are returning to now. */
+-      movq %rax, (JB_PC*8)(%rdi)
+-      /* Set return value for setjmp. */
+-      mov $0,%eax
+-      movq (JB_PC*8)(%rdi),%rdx
+-      movq (JB_RSP*8)(%rdi),%rsp
+-      jmpq *%rdx
+-
+-ENTRY(kgdb_fault_longjmp)
+-      /* Restore registers. */
+-      movq (JB_RBX*8)(%rdi),%rbx
+-      movq (JB_RBP*8)(%rdi),%rbp
+-      movq (JB_R12*8)(%rdi),%r12
+-      movq (JB_R13*8)(%rdi),%r13
+-      movq (JB_R14*8)(%rdi),%r14
+-      movq (JB_R15*8)(%rdi),%r15
+-      /* Set return value for setjmp. */
+-      movq (JB_PC*8)(%rdi),%rdx
+-      movq (JB_RSP*8)(%rdi),%rsp
+-      mov $1,%eax
+-      jmpq *%rdx
+diff -Nurb linux-2.6.22-590/arch/x86_64/kernel/kgdb.c linux-2.6.22-570/arch/x86_64/kernel/kgdb.c
+--- linux-2.6.22-590/arch/x86_64/kernel/kgdb.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/kernel/kgdb.c 1969-12-31 19:00:00.000000000 -0500
+@@ -1,461 +0,0 @@
+-/*
+- *
+- * 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, 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.
+- *
+- */
 -
-               case MSG_IGNOREWIDE:
--                      tul_msgin_accept(pCurHcb);
--                      break;
+-/*
+- * Copyright (C) 2004 Amit S. Kale <amitkale@linsyssoft.com>
+- * Copyright (C) 2000-2001 VERITAS Software Corporation.
+- * Copyright (C) 2002 Andi Kleen, SuSE Labs
+- * Copyright (C) 2004 LinSysSoft Technologies Pvt. Ltd.
+- * Copyright (C) 2007 Jason Wessel, Wind River Systems, Inc.
+- */
+-/****************************************************************************
+- *  Contributor:     Lake Stevens Instrument Division$
+- *  Written by:      Glenn Engel $
+- *  Updated by:            Amit Kale<akale@veritas.com>
+- *  Modified for 386 by Jim Kingdon, Cygnus Support.
+- *  Origianl kgdb, compatibility with 2.1.xx kernel by
+- *  David Grothe <dave@gcom.com>
+- *  Integrated into 2.2.5 kernel by Tigran Aivazian <tigran@sco.com>
+- *  X86_64 changes from Andi Kleen's patch merged by Jim Houston
+- */
 -
--                      /* get */
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
--                      if (wait_tulip(pCurHcb) == -1)
--                              return -1;
+-#include <linux/string.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/spinlock.h>
+-#include <linux/delay.h>
+-#include <asm/system.h>
+-#include <asm/ptrace.h>               /* for linux pt_regs struct */
+-#include <linux/kgdb.h>
+-#include <linux/init.h>
+-#include <linux/kdebug.h>
+-#include <asm/apicdef.h>
+-#include <asm/mach_apic.h>
+-#include <asm/kdebug.h>
+-#include <asm/debugreg.h>
+-
+-/* Put the error code here just in case the user cares.  */
+-int gdb_x86_64errcode;
+-/* Likewise, the vector number here (since GDB only gets the signal
+-   number through the usual means, and that's not very specific).  */
+-int gdb_x86_64vector = -1;
+-
+-extern atomic_t cpu_doing_single_step;
+-
+-void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+-{
+-      gdb_regs[_RAX] = regs->rax;
+-      gdb_regs[_RBX] = regs->rbx;
+-      gdb_regs[_RCX] = regs->rcx;
+-      gdb_regs[_RDX] = regs->rdx;
+-      gdb_regs[_RSI] = regs->rsi;
+-      gdb_regs[_RDI] = regs->rdi;
+-      gdb_regs[_RBP] = regs->rbp;
+-      gdb_regs[_PS] = regs->eflags;
+-      gdb_regs[_PC] = regs->rip;
+-      gdb_regs[_R8] = regs->r8;
+-      gdb_regs[_R9] = regs->r9;
+-      gdb_regs[_R10] = regs->r10;
+-      gdb_regs[_R11] = regs->r11;
+-      gdb_regs[_R12] = regs->r12;
+-      gdb_regs[_R13] = regs->r13;
+-      gdb_regs[_R14] = regs->r14;
+-      gdb_regs[_R15] = regs->r15;
+-      gdb_regs[_RSP] = regs->rsp;
+-}
+-
+-extern void thread_return(void);
+-void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+-{
+-      gdb_regs[_RAX] = 0;
+-      gdb_regs[_RBX] = 0;
+-      gdb_regs[_RCX] = 0;
+-      gdb_regs[_RDX] = 0;
+-      gdb_regs[_RSI] = 0;
+-      gdb_regs[_RDI] = 0;
+-      gdb_regs[_RBP] = *(unsigned long *)p->thread.rsp;
+-      gdb_regs[_PS] = *(unsigned long *)(p->thread.rsp + 8);
+-      gdb_regs[_PC] = (unsigned long)&thread_return;
+-      gdb_regs[_R8] = 0;
+-      gdb_regs[_R9] = 0;
+-      gdb_regs[_R10] = 0;
+-      gdb_regs[_R11] = 0;
+-      gdb_regs[_R12] = 0;
+-      gdb_regs[_R13] = 0;
+-      gdb_regs[_R14] = 0;
+-      gdb_regs[_R15] = 0;
+-      gdb_regs[_RSP] = p->thread.rsp;
+-}
+-
+-void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+-{
+-      regs->rax = gdb_regs[_RAX];
+-      regs->rbx = gdb_regs[_RBX];
+-      regs->rcx = gdb_regs[_RCX];
+-      regs->rdx = gdb_regs[_RDX];
+-      regs->rsi = gdb_regs[_RSI];
+-      regs->rdi = gdb_regs[_RDI];
+-      regs->rbp = gdb_regs[_RBP];
+-      regs->eflags = gdb_regs[_PS];
+-      regs->rip = gdb_regs[_PC];
+-      regs->r8 = gdb_regs[_R8];
+-      regs->r9 = gdb_regs[_R9];
+-      regs->r10 = gdb_regs[_R10];
+-      regs->r11 = gdb_regs[_R11];
+-      regs->r12 = gdb_regs[_R12];
+-      regs->r13 = gdb_regs[_R13];
+-      regs->r14 = gdb_regs[_R14];
+-      regs->r15 = gdb_regs[_R15];
+-#if 0                         /* can't change these */
+-      regs->rsp = gdb_regs[_RSP];
+-      regs->ss = gdb_regs[_SS];
+-      regs->fs = gdb_regs[_FS];
+-      regs->gs = gdb_regs[_GS];
+-#endif
+-
+-}                             /* gdb_regs_to_regs */
+-
+-struct hw_breakpoint {
+-      unsigned enabled;
+-      unsigned type;
+-      unsigned len;
+-      unsigned long addr;
+-} breakinfo[4] = { {
+-enabled:0}, {
+-enabled:0}, {
+-enabled:0}, {
+-enabled:0}};
+-
+-static void kgdb_correct_hw_break(void)
+-{
+-      int breakno;
+-      int correctit;
+-      int breakbit;
+-      unsigned long dr7;
+-
+-      get_debugreg(dr7, 7);
+-      correctit = 0;
+-      for (breakno = 0; breakno < 3; breakno++) {
+-              breakbit = 2 << (breakno << 1);
+-              if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
+-                      correctit = 1;
+-                      dr7 |= breakbit;
+-                      dr7 &= ~(0xf0000 << (breakno << 2));
+-                      dr7 |= (((breakinfo[breakno].len << 2) |
+-                               breakinfo[breakno].type) << 16) <<
+-                          (breakno << 2);
+-                      switch (breakno) {
+-                      case 0:
+-                              set_debugreg(breakinfo[breakno].addr, 0);
+-                              break;
 -
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);       /* put pad  */
--                      TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);   /* get IGNORE field */
--                      TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);   /* get pad */
+-                      case 1:
+-                              set_debugreg(breakinfo[breakno].addr, 1);
+-                              break;
 -
--                      tul_msgin_accept(pCurHcb);
-+                      initio_msgin_accept(host);
-                       break;
+-                      case 2:
+-                              set_debugreg(breakinfo[breakno].addr, 2);
+-                              break;
 -
-               case MSG_COMP:
--                      {
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
--                              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
--                              return tul_wait_done_disc(pCurHcb);
+-                      case 3:
+-                              set_debugreg(breakinfo[breakno].addr, 3);
+-                              break;
 -                      }
-+                      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
-+                      outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
-+                      return initio_wait_done_disc(host);
-               default:
--                      tul_msgout_reject(pCurHcb);
-+                      initio_msgout_reject(host);
-                       break;
-               }
--              if (pCurHcb->HCS_Phase != MSG_IN)
--                      return (pCurHcb->HCS_Phase);
-+              if (host->phase != MSG_IN)
-+                      return host->phase;
-       }
-       /* statement won't reach here */
- }
--
--
--
--/***************************************************************************/
--int tul_msgout_reject(HCS * pCurHcb)
-+static int initio_msgout_reject(struct initio_host * host)
- {
-+      outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
--
--      if ((tul_msgin_accept(pCurHcb)) == -1)
--              return (-1);
-+      if (initio_msgin_accept(host) == -1)
-+              return -1;
--      if (pCurHcb->HCS_Phase == MSG_OUT) {
--              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_REJ);         /* Msg reject           */
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--              return (wait_tulip(pCurHcb));
-+      if (host->phase == MSG_OUT) {
-+              outb(MSG_REJ, host->addr + TUL_SFifo);          /* Msg reject           */
-+              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+              return wait_tulip(host);
-       }
--      return (pCurHcb->HCS_Phase);
-+      return host->phase;
- }
--
--
--/***************************************************************************/
--int tul_msgout_ide(HCS * pCurHcb)
-+static int initio_msgout_ide(struct initio_host * host)
- {
--      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_IDE);         /* Initiator Detected Error */
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--      return (wait_tulip(pCurHcb));
-+      outb(MSG_IDE, host->addr + TUL_SFifo);          /* Initiator Detected Error */
-+      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+      return wait_tulip(host);
- }
--
--/***************************************************************************/
--int tul_msgin_extend(HCS * pCurHcb)
-+static int initio_msgin_extend(struct initio_host * host)
- {
--      BYTE len, idx;
-+      u8 len, idx;
--      if (tul_msgin_accept(pCurHcb) != MSG_IN)
--              return (pCurHcb->HCS_Phase);
-+      if (initio_msgin_accept(host) != MSG_IN)
-+              return host->phase;
-       /* Get extended msg length      */
--      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
--      if (wait_tulip(pCurHcb) == -1)
--              return (-1);
-+      outl(1, host->addr + TUL_SCnt0);
-+      outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
-+      if (wait_tulip(host) == -1)
-+              return -1;
--      len = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
--      pCurHcb->HCS_Msg[0] = len;
-+      len = inb(host->addr + TUL_SFifo);
-+      host->msg[0] = len;
-       for (idx = 1; len != 0; len--) {
--              if ((tul_msgin_accept(pCurHcb)) != MSG_IN)
--                      return (pCurHcb->HCS_Phase);
--              TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
--              if (wait_tulip(pCurHcb) == -1)
--                      return (-1);
--              pCurHcb->HCS_Msg[idx++] = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
--      }
--      if (pCurHcb->HCS_Msg[1] == 1) {         /* if it's synchronous data transfer request */
--              if (pCurHcb->HCS_Msg[0] != 3)   /* if length is not right */
--                      return (tul_msgout_reject(pCurHcb));
--              if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_SYNC_NEGO) {        /* Set OFFSET=0 to do async, nego back */
--                      pCurHcb->HCS_Msg[3] = 0;
--              } else {
--                      if ((tul_msgin_sync(pCurHcb) == 0) &&
--                          (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SYNC_DONE)) {
--                              tul_sync_done(pCurHcb);
--                              return (tul_msgin_accept(pCurHcb));
-+              if ((initio_msgin_accept(host)) != MSG_IN)
-+                      return host->phase;
-+              outl(1, host->addr + TUL_SCnt0);
-+              outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
-+              if (wait_tulip(host) == -1)
-+                      return -1;
-+              host->msg[idx++] = inb(host->addr + TUL_SFifo);
-+      }
-+      if (host->msg[1] == 1) {                /* if it's synchronous data transfer request */
-+              u8 r;
-+              if (host->msg[0] != 3)  /* if length is not right */
-+                      return initio_msgout_reject(host);
-+              if (host->active_tc->flags & TCF_NO_SYNC_NEGO) {        /* Set OFFSET=0 to do async, nego back */
-+                      host->msg[3] = 0;
-+              } else {
-+                      if (initio_msgin_sync(host) == 0 &&
-+                          (host->active_tc->flags & TCF_SYNC_DONE)) {
-+                              initio_sync_done(host);
-+                              return initio_msgin_accept(host);
-                       }
-               }
--              TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
--              if ((tul_msgin_accept(pCurHcb)) != MSG_OUT)
--                      return (pCurHcb->HCS_Phase);
-+              r = inb(host->addr + TUL_SSignal);
-+              outb((r & (TSC_SET_ACK | 7)) | TSC_SET_ATN,
-+                      host->addr + TUL_SSignal);
-+              if (initio_msgin_accept(host) != MSG_OUT)
-+                      return host->phase;
-               /* sync msg out */
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
--
--              tul_sync_done(pCurHcb);
-+              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[3]);
-+              initio_sync_done(host);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--              return (wait_tulip(pCurHcb));
-+              outb(MSG_EXTEND, host->addr + TUL_SFifo);
-+              outb(3, host->addr + TUL_SFifo);
-+              outb(1, host->addr + TUL_SFifo);
-+              outb(host->msg[2], host->addr + TUL_SFifo);
-+              outb(host->msg[3], host->addr + TUL_SFifo);
-+              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+              return wait_tulip(host);
-       }
--      if ((pCurHcb->HCS_Msg[0] != 2) || (pCurHcb->HCS_Msg[1] != 3))
--              return (tul_msgout_reject(pCurHcb));
-+      if (host->msg[0] != 2 || host->msg[1] != 3)
-+              return initio_msgout_reject(host);
-       /* if it's WIDE DATA XFER REQ   */
--      if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) {
--              pCurHcb->HCS_Msg[2] = 0;
-+      if (host->active_tc->flags & TCF_NO_WDTR) {
-+              host->msg[2] = 0;
-       } else {
--              if (pCurHcb->HCS_Msg[2] > 2)    /* > 32 bits            */
--                      return (tul_msgout_reject(pCurHcb));
--              if (pCurHcb->HCS_Msg[2] == 2) {         /* == 32                */
--                      pCurHcb->HCS_Msg[2] = 1;
-+              if (host->msg[2] > 2)   /* > 32 bits            */
-+                      return initio_msgout_reject(host);
-+              if (host->msg[2] == 2) {                /* == 32                */
-+                      host->msg[2] = 1;
-               } else {
--                      if ((pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) == 0) {
--                              wdtr_done(pCurHcb);
--                              if ((pCurHcb->HCS_ActTcs->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
--                                      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
--                              return (tul_msgin_accept(pCurHcb));
-+                      if ((host->active_tc->flags & TCF_NO_WDTR) == 0) {
-+                              wdtr_done(host);
-+                              if ((host->active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
-+                                      outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
-+                              return initio_msgin_accept(host);
-                       }
-               }
-       }
--      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
-+      outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
--      if (tul_msgin_accept(pCurHcb) != MSG_OUT)
--              return (pCurHcb->HCS_Phase);
-+      if (initio_msgin_accept(host) != MSG_OUT)
-+              return host->phase;
-       /* WDTR msg out                 */
--      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--      return (wait_tulip(pCurHcb));
-+      outb(MSG_EXTEND, host->addr + TUL_SFifo);
-+      outb(2, host->addr + TUL_SFifo);
-+      outb(3, host->addr + TUL_SFifo);
-+      outb(host->msg[2], host->addr + TUL_SFifo);
-+      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+      return wait_tulip(host);
- }
--/***************************************************************************/
--int tul_msgin_sync(HCS * pCurHcb)
-+static int initio_msgin_sync(struct initio_host * host)
- {
-       char default_period;
--      default_period = tul_rate_tbl[pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SCSI_RATE];
--      if (pCurHcb->HCS_Msg[3] > MAX_OFFSET) {
--              pCurHcb->HCS_Msg[3] = MAX_OFFSET;
--              if (pCurHcb->HCS_Msg[2] < default_period) {
--                      pCurHcb->HCS_Msg[2] = default_period;
-+      default_period = initio_rate_tbl[host->active_tc->flags & TCF_SCSI_RATE];
-+      if (host->msg[3] > MAX_OFFSET) {
-+              host->msg[3] = MAX_OFFSET;
-+              if (host->msg[2] < default_period) {
-+                      host->msg[2] = default_period;
-                       return 1;
-               }
--              if (pCurHcb->HCS_Msg[2] >= 59) {        /* Change to async              */
--                      pCurHcb->HCS_Msg[3] = 0;
+-              } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
+-                      correctit = 1;
+-                      dr7 &= ~breakbit;
+-                      dr7 &= ~(0xf0000 << (breakno << 2));
 -              }
-+              if (host->msg[2] >= 59) /* Change to async              */
-+                      host->msg[3] = 0;
-               return 1;
-       }
-       /* offset requests asynchronous transfers ? */
--      if (pCurHcb->HCS_Msg[3] == 0) {
-+      if (host->msg[3] == 0) {
-               return 0;
-       }
--      if (pCurHcb->HCS_Msg[2] < default_period) {
--              pCurHcb->HCS_Msg[2] = default_period;
-+      if (host->msg[2] < default_period) {
-+              host->msg[2] = default_period;
-               return 1;
-       }
--      if (pCurHcb->HCS_Msg[2] >= 59) {
--              pCurHcb->HCS_Msg[3] = 0;
-+      if (host->msg[2] >= 59) {
-+              host->msg[3] = 0;
-               return 1;
-       }
-       return 0;
- }
+-      }
+-      if (correctit)
+-              set_debugreg(dr7, 7);
+-}
 -
--/***************************************************************************/
--int wdtr_done(HCS * pCurHcb)
-+static int wdtr_done(struct initio_host * host)
- {
--      pCurHcb->HCS_ActTcs->TCS_Flags &= ~TCF_SYNC_DONE;
--      pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_WDTR_DONE;
-+      host->active_tc->flags &= ~TCF_SYNC_DONE;
-+      host->active_tc->flags |= TCF_WDTR_DONE;
--      pCurHcb->HCS_ActTcs->TCS_JS_Period = 0;
--      if (pCurHcb->HCS_Msg[2]) {      /* if 16 bit */
--              pCurHcb->HCS_ActTcs->TCS_JS_Period |= TSC_WIDE_SCSI;
+-static int kgdb_remove_hw_break(unsigned long addr, int len,
+-                                               enum kgdb_bptype bptype)
+-{
+-      int i, idx = -1;
+-      for (i = 0; i < 4; i++) {
+-              if (breakinfo[i].addr == addr && breakinfo[i].enabled) {
+-                      idx = i;
+-                      break;
+-              }
 -      }
--      pCurHcb->HCS_ActTcs->TCS_SConfig0 &= ~TSC_ALT_PERIOD;
--      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
-+      host->active_tc->js_period = 0;
-+      if (host->msg[2])       /* if 16 bit */
-+              host->active_tc->js_period |= TSC_WIDE_SCSI;
-+      host->active_tc->sconfig0 &= ~TSC_ALT_PERIOD;
-+      outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);
-+      outb(host->active_tc->js_period, host->addr + TUL_SPeriod);
-       return 1;
- }
--/***************************************************************************/
--int tul_sync_done(HCS * pCurHcb)
-+static int initio_sync_done(struct initio_host * host)
- {
-       int i;
--      pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_SYNC_DONE;
-+      host->active_tc->flags |= TCF_SYNC_DONE;
--      if (pCurHcb->HCS_Msg[3]) {
--              pCurHcb->HCS_ActTcs->TCS_JS_Period |= pCurHcb->HCS_Msg[3];
-+      if (host->msg[3]) {
-+              host->active_tc->js_period |= host->msg[3];
-               for (i = 0; i < 8; i++) {
--                      if (tul_rate_tbl[i] >= pCurHcb->HCS_Msg[2])     /* pick the big one */
-+                      if (initio_rate_tbl[i] >= host->msg[2]) /* pick the big one */
-                               break;
-               }
--              pCurHcb->HCS_ActTcs->TCS_JS_Period |= (i << 4);
--              pCurHcb->HCS_ActTcs->TCS_SConfig0 |= TSC_ALT_PERIOD;
-+              host->active_tc->js_period |= (i << 4);
-+              host->active_tc->sconfig0 |= TSC_ALT_PERIOD;
-       }
--      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
-+      outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);
-+      outb(host->active_tc->js_period, host->addr + TUL_SPeriod);
--      return (-1);
-+      return -1;
- }
--int tul_post_scsi_rst(HCS * pCurHcb)
-+static int initio_post_scsi_rst(struct initio_host * host)
- {
--      SCB *pCurScb;
--      TCS *pCurTcb;
-+      struct scsi_ctrl_blk *scb;
-+      struct target_control *active_tc;
-       int i;
--      pCurHcb->HCS_ActScb = NULL;
--      pCurHcb->HCS_ActTcs = NULL;
--      pCurHcb->HCS_Flags = 0;
+-      if (idx == -1)
+-              return -1;
 -
--      while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
--              pCurScb->SCB_HaStat = HOST_BAD_PHAS;
--              tul_append_done_scb(pCurHcb, pCurScb);
-+      host->active = NULL;
-+      host->active_tc = NULL;
-+      host->flags = 0;
-+
-+      while ((scb = initio_pop_busy_scb(host)) != NULL) {
-+              scb->hastat = HOST_BAD_PHAS;
-+              initio_append_done_scb(host, scb);
-       }
-       /* clear sync done flag         */
--      pCurTcb = &pCurHcb->HCS_Tcs[0];
--      for (i = 0; i < pCurHcb->HCS_MaxTar; pCurTcb++, i++) {
--              pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
-+      active_tc = &host->targets[0];
-+      for (i = 0; i < host->max_tar; active_tc++, i++) {
-+              active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
-               /* Initialize the sync. xfer register values to an asyn xfer */
--              pCurTcb->TCS_JS_Period = 0;
--              pCurTcb->TCS_SConfig0 = pCurHcb->HCS_SConf1;
--              pCurHcb->HCS_ActTags[0] = 0;    /* 07/22/98 */
--              pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;     /* 07/22/98 */
-+              active_tc->js_period = 0;
-+              active_tc->sconfig0 = host->sconf1;
-+              host->act_tags[0] = 0;  /* 07/22/98 */
-+              host->targets[i].flags &= ~TCF_BUSY;    /* 07/22/98 */
-       }                       /* for */
--      return (-1);
-+      return -1;
- }
--/***************************************************************************/
--void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb)
-+static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb)
- {
--      pCurScb->SCB_Status |= SCB_SELECT;
--      pCurScb->SCB_NxtStat = 0x1;
--      pCurHcb->HCS_ActScb = pCurScb;
--      pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SELATNSTOP);
--      return;
-+      scb->status |= SCB_SELECT;
-+      scb->next_state = 0x1;
-+      host->active = scb;
-+      host->active_tc = &host->targets[scb->target];
-+      outb(TSC_SELATNSTOP, host->addr + TUL_SCmd);
- }
--/***************************************************************************/
--void tul_select_atn(HCS * pCurHcb, SCB * pCurScb)
-+static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb)
- {
-       int i;
--      pCurScb->SCB_Status |= SCB_SELECT;
--      pCurScb->SCB_NxtStat = 0x2;
-+      scb->status |= SCB_SELECT;
-+      scb->next_state = 0x2;
--      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
--      for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
--              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
--      pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
--      pCurHcb->HCS_ActScb = pCurScb;
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN);
--      return;
-+      outb(scb->ident, host->addr + TUL_SFifo);
-+      for (i = 0; i < (int) scb->cdblen; i++)
-+              outb(scb->cdb[i], host->addr + TUL_SFifo);
-+      host->active_tc = &host->targets[scb->target];
-+      host->active = scb;
-+      outb(TSC_SEL_ATN, host->addr + TUL_SCmd);
- }
--/***************************************************************************/
--void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb)
-+static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb)
- {
-       int i;
--      pCurScb->SCB_Status |= SCB_SELECT;
--      pCurScb->SCB_NxtStat = 0x2;
--
--      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
--      for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
--              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
--      pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
--      pCurHcb->HCS_ActScb = pCurScb;
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN3);
--      return;
+-      breakinfo[idx].enabled = 0;
+-      return 0;
 -}
-+      scb->status |= SCB_SELECT;
-+      scb->next_state = 0x2;
--/***************************************************************************/
--/* SCSI Bus Device Reset */
--int tul_bus_device_reset(HCS * pCurHcb)
-+      outb(scb->ident, host->addr + TUL_SFifo);
-+      outb(scb->tagmsg, host->addr + TUL_SFifo);
-+      outb(scb->tagid, host->addr + TUL_SFifo);
-+      for (i = 0; i < scb->cdblen; i++)
-+              outb(scb->cdb[i], host->addr + TUL_SFifo);
-+      host->active_tc = &host->targets[scb->target];
-+      host->active = scb;
-+      outb(TSC_SEL_ATN3, host->addr + TUL_SCmd);
-+}
-+
-+/**
-+ *    initio_bus_device_reset -        SCSI Bus Device Reset
-+ *    @host: InitIO host to reset
-+ *
-+ *    Perform a device reset and abort all pending SCBs for the
-+ *    victim device
-+ */
-+int initio_bus_device_reset(struct initio_host * host)
- {
--      SCB *pCurScb = pCurHcb->HCS_ActScb;
--      TCS *pCurTcb = pCurHcb->HCS_ActTcs;
--      SCB *pTmpScb, *pPrevScb;
--      BYTE tar;
-+      struct scsi_ctrl_blk *scb = host->active;
-+      struct target_control *active_tc = host->active_tc;
-+      struct scsi_ctrl_blk *tmp, *prev;
-+      u8 tar;
--      if (pCurHcb->HCS_Phase != MSG_OUT) {
--              return (int_tul_bad_seq(pCurHcb));      /* Unexpected phase             */
--      }
--      tul_unlink_pend_scb(pCurHcb, pCurScb);
--      tul_release_scb(pCurHcb, pCurScb);
-+      if (host->phase != MSG_OUT)
-+              return int_initio_bad_seq(host);        /* Unexpected phase */
-+      initio_unlink_pend_scb(host, scb);
-+      initio_release_scb(host, scb);
--      tar = pCurScb->SCB_Target;      /* target                       */
--      pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
-+
-+      tar = scb->target;      /* target                       */
-+      active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
-       /* clr sync. nego & WDTR flags  07/22/98 */
-       /* abort all SCB with same target */
--      pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;    /* Check Busy queue */
--      while (pTmpScb != NULL) {
 -
--              if (pTmpScb->SCB_Target == tar) {
-+      prev = tmp = host->first_busy;  /* Check Busy queue */
-+      while (tmp != NULL) {
-+              if (tmp->target == tar) {
-                       /* unlink it */
--                      if (pTmpScb == pCurHcb->HCS_FirstBusy) {
--                              if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
--                                      pCurHcb->HCS_LastBusy = NULL;
--                      } else {
--                              pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
--                              if (pTmpScb == pCurHcb->HCS_LastBusy)
--                                      pCurHcb->HCS_LastBusy = pPrevScb;
-+                      if (tmp == host->first_busy) {
-+                              if ((host->first_busy = tmp->next) == NULL)
-+                                      host->last_busy = NULL;
-+                      } else {
-+                              prev->next = tmp->next;
-+                              if (tmp == host->last_busy)
-+                                      host->last_busy = prev;
-                       }
--                      pTmpScb->SCB_HaStat = HOST_ABORTED;
--                      tul_append_done_scb(pCurHcb, pTmpScb);
-+                      tmp->hastat = HOST_ABORTED;
-+                      initio_append_done_scb(host, tmp);
-               }
-               /* Previous haven't change      */
-               else {
--                      pPrevScb = pTmpScb;
-+                      prev = tmp;
-               }
--              pTmpScb = pTmpScb->SCB_NxtScb;
-+              tmp = tmp->next;
-       }
--
--      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_DEVRST);
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
--
--      return tul_wait_disc(pCurHcb);
-+      outb(MSG_DEVRST, host->addr + TUL_SFifo);
-+      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
-+      return initio_wait_disc(host);
- }
--/***************************************************************************/
--int tul_msgin_accept(HCS * pCurHcb)
-+static int initio_msgin_accept(struct initio_host * host)
- {
--      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
--      return (wait_tulip(pCurHcb));
-+      outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
-+      return wait_tulip(host);
- }
--/***************************************************************************/
--int wait_tulip(HCS * pCurHcb)
-+static int wait_tulip(struct initio_host * host)
- {
--      while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
--               & TSS_INT_PENDING));
-+      while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))
-+               & TSS_INT_PENDING))
-+                      cpu_relax();
-+
-+      host->jsint = inb(host->addr + TUL_SInt);
-+      host->phase = host->jsstatus0 & TSS_PH_MASK;
-+      host->jsstatus1 = inb(host->addr + TUL_SStatus1);
--      pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
--      pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
--      pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
--
--      if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {       /* if SCSI bus reset detected   */
--              return (int_tul_resel(pCurHcb));
--      }
--      if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {     /* if selected/reselected timeout interrupt */
--              return (int_tul_busfree(pCurHcb));
--      }
--      if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {     /* if SCSI bus reset detected   */
--              return (int_tul_scsi_rst(pCurHcb));
--      }
--      if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {        /* BUS disconnection            */
--              if (pCurHcb->HCS_Flags & HCF_EXPECT_DONE_DISC) {
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);         /* Flush SCSI FIFO  */
--                      tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
--                      pCurHcb->HCS_ActScb->SCB_HaStat = 0;
--                      tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
--                      pCurHcb->HCS_ActScb = NULL;
--                      pCurHcb->HCS_ActTcs = NULL;
--                      pCurHcb->HCS_Flags &= ~HCF_EXPECT_DONE_DISC;
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);        /* Enable HW reselect       */
--                      return (-1);
--              }
--              if (pCurHcb->HCS_Flags & HCF_EXPECT_DISC) {
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);         /* Flush SCSI FIFO  */
--                      pCurHcb->HCS_ActScb = NULL;
--                      pCurHcb->HCS_ActTcs = NULL;
--                      pCurHcb->HCS_Flags &= ~HCF_EXPECT_DISC;
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
--                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);        /* Enable HW reselect       */
--                      return (-1);
-+      if (host->jsint & TSS_RESEL_INT)        /* if SCSI bus reset detected */
-+              return int_initio_resel(host);
-+      if (host->jsint & TSS_SEL_TIMEOUT)      /* if selected/reselected timeout interrupt */
-+              return int_initio_busfree(host);
-+      if (host->jsint & TSS_SCSIRST_INT)      /* if SCSI bus reset detected   */
-+              return int_initio_scsi_rst(host);
-+
-+      if (host->jsint & TSS_DISC_INT) {       /* BUS disconnection            */
-+              if (host->flags & HCF_EXPECT_DONE_DISC) {
-+                      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */
-+                      initio_unlink_busy_scb(host, host->active);
-+                      host->active->hastat = 0;
-+                      initio_append_done_scb(host, host->active);
-+                      host->active = NULL;
-+                      host->active_tc = NULL;
-+                      host->flags &= ~HCF_EXPECT_DONE_DISC;
-+                      outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
-+                      outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */
-+                      return -1;
-               }
--              return (int_tul_busfree(pCurHcb));
-+              if (host->flags & HCF_EXPECT_DISC) {
-+                      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */
-+                      host->active = NULL;
-+                      host->active_tc = NULL;
-+                      host->flags &= ~HCF_EXPECT_DISC;
-+                      outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
-+                      outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */
-+                      return -1;
-       }
--      if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {
--              return (pCurHcb->HCS_Phase);
-+              return int_initio_busfree(host);
-       }
--      return (pCurHcb->HCS_Phase);
-+      /* The old code really does the below. Can probably be removed */
-+      if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV))
-+              return host->phase;
-+      return host->phase;
- }
--/***************************************************************************/
--int tul_wait_disc(HCS * pCurHcb)
+-static void kgdb_remove_all_hw_break(void)
+-{
+-      int i;
+-
+-      for (i = 0; i < 4; i++) {
+-              memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint));
+-      }
+-}
+-
+-static int kgdb_set_hw_break(unsigned long addr, int len,
+-                                        enum kgdb_bptype bptype)
 -{
+-      int i, idx = -1;
+-      for (i = 0; i < 4; i++) {
+-              if (!breakinfo[i].enabled) {
+-                      idx = i;
+-                      break;
+-              }
+-      }
+-      if (idx == -1)
+-              return -1;
+-      if (bptype == bp_hardware_breakpoint) {
+-              breakinfo[idx].type = 0;
+-              breakinfo[idx].len = 0;
+-      } else if (bptype == bp_write_watchpoint) {
+-              breakinfo[idx].type = 1;
+-              if (len == 1 || len == 2 || len == 4)
+-                      breakinfo[idx].len = len - 1;
+-              else
+-                      return -1;
+-      } else if (bptype == bp_access_watchpoint) {
+-              breakinfo[idx].type = 3;
+-              if (len == 1 || len == 2 || len == 4)
+-                      breakinfo[idx].len = len - 1;
+-              else
+-                      return -1;
+-      } else
+-              return -1;
+-      breakinfo[idx].enabled = 1;
+-      breakinfo[idx].addr = addr;
+-      return 0;
+-}
 -
--      while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
--               & TSS_INT_PENDING));
-+static int initio_wait_disc(struct initio_host * host)
-+{
-+      while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING))
-+              cpu_relax();
--      pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-+      host->jsint = inb(host->addr + TUL_SInt);
--      if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {     /* if SCSI bus reset detected   */
--              return (int_tul_scsi_rst(pCurHcb));
--      }
--      if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {        /* BUS disconnection            */
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);         /* Flush SCSI FIFO  */
--              TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);        /* Enable HW reselect       */
--              pCurHcb->HCS_ActScb = NULL;
--              return (-1);
-+      if (host->jsint & TSS_SCSIRST_INT)      /* if SCSI bus reset detected */
-+              return int_initio_scsi_rst(host);
-+      if (host->jsint & TSS_DISC_INT) {       /* BUS disconnection */
-+              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */
-+              outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
-+              outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */
-+              host->active = NULL;
-+              return -1;
-       }
--      return (tul_bad_seq(pCurHcb));
-+      return initio_bad_seq(host);
- }
--/***************************************************************************/
--int tul_wait_done_disc(HCS * pCurHcb)
-+static int initio_wait_done_disc(struct initio_host * host)
- {
-+      while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))
-+               & TSS_INT_PENDING))
-+               cpu_relax();
-+      host->jsint = inb(host->addr + TUL_SInt);
--      while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
--               & TSS_INT_PENDING));
+-void kgdb_disable_hw_debug(struct pt_regs *regs)
+-{
+-      /* Disable hardware debugging while we are in kgdb */
+-      set_debugreg(0UL, 7);
+-}
 -
--      pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
-+      if (host->jsint & TSS_SCSIRST_INT)      /* if SCSI bus reset detected */
-+              return int_initio_scsi_rst(host);
-+      if (host->jsint & TSS_DISC_INT) {       /* BUS disconnection */
-+              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);          /* Flush SCSI FIFO */
-+              outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
-+              outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);         /* Enable HW reselect */
-+              initio_unlink_busy_scb(host, host->active);
+-void kgdb_post_master_code(struct pt_regs *regs, int e_vector, int err_code)
+-{
+-      /* Master processor is completely in the debugger */
+-      gdb_x86_64vector = e_vector;
+-      gdb_x86_64errcode = err_code;
+-}
 -
--      if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {     /* if SCSI bus reset detected   */
--              return (int_tul_scsi_rst(pCurHcb));
--      }
--      if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {        /* BUS disconnection            */
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);         /* Flush SCSI FIFO  */
--              TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
--              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);        /* Enable HW reselect       */
--              tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
+-void kgdb_roundup_cpus(unsigned long flags)
+-{
+-      send_IPI_allbutself(APIC_DM_NMI);
+-}
 -
--              tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
--              pCurHcb->HCS_ActScb = NULL;
--              return (-1);
-+              initio_append_done_scb(host, host->active);
-+              host->active = NULL;
-+              return -1;
-       }
--      return (tul_bad_seq(pCurHcb));
-+      return initio_bad_seq(host);
- }
-+/**
-+ *    i91u_intr               -       IRQ handler
-+ *    @irqno: IRQ number
-+ *    @dev_id: IRQ identifier
-+ *
-+ *    Take the relevant locks and then invoke the actual isr processing
-+ *    code under the lock.
-+ */
-+
- static irqreturn_t i91u_intr(int irqno, void *dev_id)
- {
-       struct Scsi_Host *dev = dev_id;
-       unsigned long flags;
-+      int r;
-       
-       spin_lock_irqsave(dev->host_lock, flags);
--      tul_isr((HCS *)dev->base);
-+      r = initio_isr((struct initio_host *)dev->hostdata);
-       spin_unlock_irqrestore(dev->host_lock, flags);
-+      if (r)
-       return IRQ_HANDLED;
-+      else
-+              return IRQ_NONE;
- }
--static int tul_NewReturnNumberOfAdapters(void)
+-int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
+-                             char *remcomInBuffer, char *remcomOutBuffer,
+-                             struct pt_regs *linux_regs)
 -{
--      struct pci_dev *pDev = NULL;    /* Start from none              */
--      int iAdapters = 0;
--      long dRegValue;
--      WORD wBIOS;
--      int i = 0;
+-      unsigned long addr;
+-      unsigned long breakno;
+-      char *ptr;
+-      int newPC;
+-      unsigned long dr6;
+-
+-      switch (remcomInBuffer[0]) {
+-      case 'c':
+-      case 's':
+-              /* try to read optional parameter, pc unchanged if no parm */
+-              ptr = &remcomInBuffer[1];
+-              if (kgdb_hex2long(&ptr, &addr))
+-                      linux_regs->rip = addr;
+-              newPC = linux_regs->rip;
+-
+-              /* clear the trace bit */
+-              linux_regs->eflags &= ~TF_MASK;
+-
+-              atomic_set(&cpu_doing_single_step, -1);
+-              /* set the trace bit if we're stepping */
+-              if (remcomInBuffer[0] == 's') {
+-                      linux_regs->eflags |= TF_MASK;
+-                      debugger_step = 1;
+-                      if (kgdb_contthread)
+-                              atomic_set(&cpu_doing_single_step,
+-                                         raw_smp_processor_id());
 -
--      init_i91uAdapter_table();
+-              }
 -
--      for (i = 0; i < ARRAY_SIZE(i91u_pci_devices); i++)
--      {
--              while ((pDev = pci_find_device(i91u_pci_devices[i].vendor, i91u_pci_devices[i].device, pDev)) != NULL) {
--                      if (pci_enable_device(pDev))
--                              continue;
--                      pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
--                      wBIOS = (UWORD) (dRegValue & 0xFF);
--                      if (((dRegValue & 0xFF00) >> 8) == 0xFF)
--                              dRegValue = 0;
--                      wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
--                      if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) {
--                              printk(KERN_WARNING 
--                                     "i91u: Could not set 32 bit DMA mask\n");
--                              continue;
+-              get_debugreg(dr6, 6);
+-              if (!(dr6 & 0x4000)) {
+-                      for (breakno = 0; breakno < 4; ++breakno) {
+-                              if (dr6 & (1 << breakno)) {
+-                                      if (breakinfo[breakno].type == 0) {
+-                                              /* Set restore flag */
+-                                              linux_regs->eflags |=
+-                                                  X86_EFLAGS_RF;
+-                                              break;
+-                                      }
+-                              }
 -                      }
--
--                      if (Addi91u_into_Adapter_table(wBIOS,
--                                                      (pDev->resource[0].start),
--                                                      pDev->irq,
--                                                      pDev->bus->number,
--                                                      (pDev->devfn >> 3)
--                              ) == 0)
--                              iAdapters++;
 -              }
+-              set_debugreg(0UL, 6);
+-              kgdb_correct_hw_break();
+-
+-              return (0);
+-      }                       /* switch */
+-      return -1;
+-}
+-
+-static struct pt_regs *in_interrupt_stack(unsigned long rsp, int cpu)
+-{
+-      struct pt_regs *regs;
+-      unsigned long end = (unsigned long)cpu_pda(cpu)->irqstackptr;
+-      if (rsp <= end && rsp >= end - IRQSTACKSIZE + 8) {
+-              regs = *(((struct pt_regs **)end) - 1);
+-              return regs;
 -      }
+-      return NULL;
+-}
 -
--      return (iAdapters);
+-static struct pt_regs *in_exception_stack(unsigned long rsp, int cpu)
+-{
+-      int i;
+-      struct tss_struct *init_tss = &__get_cpu_var(init_tss);
+-      for (i = 0; i < N_EXCEPTION_STACKS; i++)
+-              if (rsp >= init_tss[cpu].ist[i] &&
+-                  rsp <= init_tss[cpu].ist[i] + EXCEPTION_STKSZ) {
+-                      struct pt_regs *r =
+-                          (void *)init_tss[cpu].ist[i] + EXCEPTION_STKSZ;
+-                      return r - 1;
+-              }
+-      return NULL;
 -}
 -
--static int i91u_detect(struct scsi_host_template * tpnt)
+-void kgdb_shadowinfo(struct pt_regs *regs, char *buffer, unsigned threadid)
 -{
--      HCS *pHCB;
--      struct Scsi_Host *hreg;
--      unsigned long i;        /* 01/14/98                     */
--      int ok = 0, iAdapters;
--      ULONG dBiosAdr;
--      BYTE *pbBiosAdr;
+-      static char intr_desc[] = "Stack at interrupt entrypoint";
+-      static char exc_desc[] = "Stack at exception entrypoint";
+-      struct pt_regs *stregs;
+-      int cpu = raw_smp_processor_id();
 -
--      /* Get total number of adapters in the motherboard */
--      iAdapters = tul_NewReturnNumberOfAdapters();
--      if (iAdapters == 0)     /* If no tulip founded, return */
--              return (0);
+-      if ((stregs = in_interrupt_stack(regs->rsp, cpu)))
+-              kgdb_mem2hex(intr_desc, buffer, strlen(intr_desc));
+-      else if ((stregs = in_exception_stack(regs->rsp, cpu)))
+-              kgdb_mem2hex(exc_desc, buffer, strlen(exc_desc));
+-}
 -
--      tul_num_ch = (iAdapters > tul_num_ch) ? tul_num_ch : iAdapters;
--      /* Update actually channel number */
--      if (tul_tag_enable) {   /* 1.01i                  */
--              tul_num_scb = MAX_TARGETS * i91u_MAXQUEUE;
--      } else {
--              tul_num_scb = MAX_TARGETS + 3;  /* 1-tape, 1-CD_ROM, 1- extra */
--      }                       /* Update actually SCBs per adapter */
+-struct task_struct *kgdb_get_shadow_thread(struct pt_regs *regs, int threadid)
+-{
+-      struct pt_regs *stregs;
+-      int cpu = raw_smp_processor_id();
 -
--      /* Get total memory needed for HCS */
--      i = tul_num_ch * sizeof(HCS);
--      memset((unsigned char *) &tul_hcs[0], 0, i);    /* Initialize tul_hcs 0 */
--      /* Get total memory needed for SCB */
+-      if ((stregs = in_interrupt_stack(regs->rsp, cpu)))
+-              return current;
+-      else if ((stregs = in_exception_stack(regs->rsp, cpu)))
+-              return current;
 -
--      for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) {
--              i = tul_num_ch * tul_num_scb * sizeof(SCB);
--              if ((tul_scb = kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
--                      break;
--      }
--      if (tul_scb == NULL) {
--              printk("i91u: SCB memory allocation error\n");
--              return (0);
--      }
--      memset((unsigned char *) tul_scb, 0, i);
+-      return NULL;
+-}
 -
--      for (i = 0, pHCB = &tul_hcs[0];         /* Get pointer for control block */
--           i < tul_num_ch;
--           i++, pHCB++) {
--              get_tulipPCIConfig(pHCB, i);
+-struct pt_regs *kgdb_shadow_regs(struct pt_regs *regs, int threadid)
+-{
+-      struct pt_regs *stregs;
+-      int cpu = raw_smp_processor_id();
 -
--              dBiosAdr = pHCB->HCS_BIOS;
--              dBiosAdr = (dBiosAdr << 4);
--              pbBiosAdr = phys_to_virt(dBiosAdr);
+-      if ((stregs = in_interrupt_stack(regs->rsp, cpu)))
+-              return stregs;
+-      else if ((stregs = in_exception_stack(regs->rsp, cpu)))
+-              return stregs;
 -
--              init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10);
--              request_region(pHCB->HCS_Base, 256, "i91u"); /* Register */ 
+-      return NULL;
+-}
 -
--              pHCB->HCS_Index = i;    /* 7/29/98 */
--              hreg = scsi_register(tpnt, sizeof(HCS));
--              if(hreg == NULL) {
--                      release_region(pHCB->HCS_Base, 256);
--                      return 0;
--              }
--              hreg->io_port = pHCB->HCS_Base;
--              hreg->n_io_port = 0xff;
--              hreg->can_queue = tul_num_scb;  /* 03/05/98                      */
--              hreg->unique_id = pHCB->HCS_Base;
--              hreg->max_id = pHCB->HCS_MaxTar;
--              hreg->max_lun = 32;     /* 10/21/97                     */
--              hreg->irq = pHCB->HCS_Intr;
--              hreg->this_id = pHCB->HCS_SCSI_ID;      /* Assign HCS index           */
--              hreg->base = (unsigned long)pHCB;
--              hreg->sg_tablesize = TOTAL_SG_ENTRY;    /* Maximun support is 32 */
--
--              /* Initial tulip chip           */
--              ok = request_irq(pHCB->HCS_Intr, i91u_intr, IRQF_DISABLED | IRQF_SHARED, "i91u", hreg);
--              if (ok < 0) {
--                      printk(KERN_WARNING "i91u: unable to request IRQ %d\n\n", pHCB->HCS_Intr);
--                      return 0;
--              }
--      }
+-/* Register KGDB with the die_chain so that we hook into all of the right
+- * spots. */
+-static int kgdb_notify(struct notifier_block *self, unsigned long cmd,
+-                     void *ptr)
+-{
+-      struct die_args *args = ptr;
+-      struct pt_regs *regs = args->regs;
+-
+-      if (cmd == DIE_PAGE_FAULT_NO_CONTEXT && atomic_read(&debugger_active)
+-                      && kgdb_may_fault) {
+-              kgdb_fault_longjmp(kgdb_fault_jmp_regs);
+-              return NOTIFY_STOP;
+-      /* CPU roundup? */
+-      } else if (atomic_read(&debugger_active) && cmd == DIE_NMI_IPI) {
+-              kgdb_nmihook(raw_smp_processor_id(), regs);
+-              return NOTIFY_STOP;
+-              /* See if KGDB is interested. */
+-      } else if (cmd == DIE_DEBUG
+-                         && atomic_read(&cpu_doing_single_step) == raw_smp_processor_id()
+-                         && user_mode(regs)) {
+-              /* single step exception from kernel space to user space so
+-               * eat the exception and continue the process
+-               */
+-              printk(KERN_ERR "KGDB: trap/step from kernel to user space, resuming...\n");
+-              kgdb_arch_handle_exception(args->trapnr, args->signr, args->err, "c","",regs);
+-              return NOTIFY_STOP;
+-      } else if (cmd == DIE_PAGE_FAULT || user_mode(regs) ||
+-                 cmd == DIE_NMI_IPI || (cmd == DIE_DEBUG &&
+-                                        atomic_read(&debugger_active)))
+-              /* Userpace events, normal watchdog event, or spurious
+-               * debug exception.  Ignore. */
+-              return NOTIFY_DONE;
 -
--      tpnt->this_id = -1;
--      tpnt->can_queue = 1;
+-      kgdb_handle_exception(args->trapnr, args->signr, args->err, regs);
 -
--      return 1;
+-      return NOTIFY_STOP;
 -}
-+/**
-+ *    initio_build_scb                -       Build the mappings and SCB
-+ *    @host: InitIO host taking the command
-+ *    @cblk: Firmware command block
-+ *    @cmnd: SCSI midlayer command block
-+ *
-+ *    Translate the abstract SCSI command into a firmware command block
-+ *    suitable for feeding to the InitIO host controller. This also requires
-+ *    we build the scatter gather lists and ensure they are mapped properly.
-+ */
--static void i91uBuildSCB(HCS * pHCB, SCB * pSCB, struct scsi_cmnd * SCpnt)
-+static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * cblk, struct scsi_cmnd * cmnd)
- {                             /* Create corresponding SCB     */
--      struct scatterlist *pSrbSG;
--      SG *pSG;                /* Pointer to SG list           */
--      int i;
--      long TotalLen;
-+      struct scatterlist *sglist;
-+      struct sg_entry *sg;            /* Pointer to SG list           */
-+      int i, nseg;
-+      long total_len;
-       dma_addr_t dma_addr;
--      pSCB->SCB_Post = i91uSCBPost;   /* i91u's callback routine      */
--      pSCB->SCB_Srb = SCpnt;
--      pSCB->SCB_Opcode = ExecSCSI;
--      pSCB->SCB_Flags = SCF_POST;     /* After SCSI done, call post routine */
--      pSCB->SCB_Target = SCpnt->device->id;
--      pSCB->SCB_Lun = SCpnt->device->lun;
--      pSCB->SCB_Ident = SCpnt->device->lun | DISC_ALLOW;
-+      /* Fill in the command headers */
-+      cblk->post = i91uSCBPost;       /* i91u's callback routine      */
-+      cblk->srb = cmnd;
-+      cblk->opcode = ExecSCSI;
-+      cblk->flags = SCF_POST; /* After SCSI done, call post routine */
-+      cblk->target = cmnd->device->id;
-+      cblk->lun = cmnd->device->lun;
-+      cblk->ident = cmnd->device->lun | DISC_ALLOW;
--      pSCB->SCB_Flags |= SCF_SENSE;   /* Turn on auto request sense   */
--      dma_addr = dma_map_single(&pHCB->pci_dev->dev, SCpnt->sense_buffer,
--                                SENSE_SIZE, DMA_FROM_DEVICE);
--      pSCB->SCB_SensePtr = cpu_to_le32((u32)dma_addr);
--      pSCB->SCB_SenseLen = cpu_to_le32(SENSE_SIZE);
--      SCpnt->SCp.ptr = (char *)(unsigned long)dma_addr;
--
--      pSCB->SCB_CDBLen = SCpnt->cmd_len;
--      pSCB->SCB_HaStat = 0;
--      pSCB->SCB_TaStat = 0;
--      memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, SCpnt->cmd_len);
-+      cblk->flags |= SCF_SENSE;       /* Turn on auto request sense   */
--      if (SCpnt->device->tagged_supported) {  /* Tag Support                  */
--              pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG;    /* Do simple tag only   */
-+      /* Map the sense buffer into bus memory */
-+      dma_addr = dma_map_single(&host->pci_dev->dev, cmnd->sense_buffer,
-+                                SENSE_SIZE, DMA_FROM_DEVICE);
-+      cblk->senseptr = cpu_to_le32((u32)dma_addr);
-+      cblk->senselen = cpu_to_le32(SENSE_SIZE);
-+      cmnd->SCp.ptr = (char *)(unsigned long)dma_addr;
-+      cblk->cdblen = cmnd->cmd_len;
-+
-+      /* Clear the returned status */
-+      cblk->hastat = 0;
-+      cblk->tastat = 0;
-+      /* Command the command */
-+      memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len);
-+
-+      /* Set up tags */
-+      if (cmnd->device->tagged_supported) {   /* Tag Support                  */
-+              cblk->tagmsg = SIMPLE_QUEUE_TAG;        /* Do simple tag only   */
-       } else {
--              pSCB->SCB_TagMsg = 0;   /* No tag support               */
-+              cblk->tagmsg = 0;       /* No tag support               */
-       }
-+
-       /* todo handle map_sg error */
--      if (SCpnt->use_sg) {
--              dma_addr = dma_map_single(&pHCB->pci_dev->dev, &pSCB->SCB_SGList[0],
--                                        sizeof(struct SG_Struc) * TOTAL_SG_ENTRY,
-+      nseg = scsi_dma_map(cmnd);
-+      BUG_ON(nseg < 0);
-+      if (nseg) {
-+              dma_addr = dma_map_single(&host->pci_dev->dev, &cblk->sglist[0],
-+                                        sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
-                                         DMA_BIDIRECTIONAL);
--              pSCB->SCB_BufPtr = cpu_to_le32((u32)dma_addr);
--              SCpnt->SCp.dma_handle = dma_addr;
-+              cblk->bufptr = cpu_to_le32((u32)dma_addr);
-+              cmnd->SCp.dma_handle = dma_addr;
--              pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
--              pSCB->SCB_SGLen = dma_map_sg(&pHCB->pci_dev->dev, pSrbSG,
--                                           SCpnt->use_sg, SCpnt->sc_data_direction);
--
--              pSCB->SCB_Flags |= SCF_SG;      /* Turn on SG list flag       */
--              for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0];   /* 1.01g */
--                   i < pSCB->SCB_SGLen; i++, pSG++, pSrbSG++) {
--                      pSG->SG_Ptr = cpu_to_le32((u32)sg_dma_address(pSrbSG));
--                      TotalLen += pSG->SG_Len = cpu_to_le32((u32)sg_dma_len(pSrbSG));
--              }
--
--              pSCB->SCB_BufLen = (SCpnt->request_bufflen > TotalLen) ?
--                  TotalLen : SCpnt->request_bufflen;
--      } else if (SCpnt->request_bufflen) {            /* Non SG */
--              dma_addr = dma_map_single(&pHCB->pci_dev->dev, SCpnt->request_buffer,
--                                        SCpnt->request_bufflen,
--                                        SCpnt->sc_data_direction);
--              SCpnt->SCp.dma_handle = dma_addr;
--              pSCB->SCB_BufPtr = cpu_to_le32((u32)dma_addr);
--              pSCB->SCB_BufLen = cpu_to_le32((u32)SCpnt->request_bufflen);
--              pSCB->SCB_SGLen = 0;
--      } else {
--              pSCB->SCB_BufLen = 0;
--              pSCB->SCB_SGLen = 0;
-+
-+              cblk->flags |= SCF_SG;  /* Turn on SG list flag       */
-+              total_len = 0;
-+              sg = &cblk->sglist[0];
-+              scsi_for_each_sg(cmnd, sglist, cblk->sglen, i) {
-+                      sg->data = cpu_to_le32((u32)sg_dma_address(sglist));
-+                      total_len += sg->len = cpu_to_le32((u32)sg_dma_len(sglist));
-+              }
-+
-+              cblk->buflen = (scsi_bufflen(cmnd) > total_len) ?
-+                      total_len : scsi_bufflen(cmnd);
-+      } else {        /* No data transfer required */
-+              cblk->buflen = 0;
-+              cblk->sglen = 0;
+-
+-static struct notifier_block kgdb_notifier = {
+-      .notifier_call = kgdb_notify,
+-      .priority = 0x7fffffff, /* we need to notified first */
+-};
+-
+-int kgdb_arch_init(void)
+-{
+-      register_die_notifier(&kgdb_notifier);
+-      return 0;
+-}
+-/*
+- * Skip an int3 exception when it occurs after a breakpoint has been
+- * removed. Backtrack eip by 1 since the int3 would have caused it to
+- * increment by 1.
+- */
+-
+-int kgdb_skipexception(int exception, struct pt_regs *regs)
+-{
+-      if (exception == 3 && kgdb_isremovedbreak(regs->rip - 1)) {
+-              regs->rip -= 1;
+-              return 1;
+-      }
+-      return 0;
+-}
+-
+-unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
+-{
+-      if (exception == 3) {
+-              return instruction_pointer(regs) - 1;
+-      }
+-      return instruction_pointer(regs);
+-}
+-
+-struct kgdb_arch arch_kgdb_ops = {
+-      .gdb_bpt_instr = {0xcc},
+-      .flags = KGDB_HW_BREAKPOINT,
+-      .shadowth = 1,
+-      .set_hw_breakpoint = kgdb_set_hw_break,
+-      .remove_hw_breakpoint = kgdb_remove_hw_break,
+-      .remove_all_hw_break = kgdb_remove_all_hw_break,
+-      .correct_hw_break = kgdb_correct_hw_break,
+-};
+diff -Nurb linux-2.6.22-590/arch/x86_64/kernel/mce.c linux-2.6.22-570/arch/x86_64/kernel/mce.c
+--- linux-2.6.22-590/arch/x86_64/kernel/mce.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/kernel/mce.c  2007-07-08 19:32:17.000000000 -0400
+@@ -174,7 +174,7 @@
+       if (events != atomic_read(&mce_logged) && trigger[0]) {
+               /* Small race window, but should be harmless.  */
+               atomic_set(&mce_logged, events);
+-              call_usermodehelper(trigger, trigger_argv, NULL, UMH_NO_WAIT);
++              call_usermodehelper(trigger, trigger_argv, NULL, -1);
        }
  }
  
-+/**
-+ *    i91u_queuecommand       -       Queue a new command if possible
-+ *    @cmd: SCSI command block from the mid layer
-+ *    @done: Completion handler
-+ *
-+ *    Attempts to queue a new command with the host adapter. Will return
-+ *    zero if successful or indicate a host busy condition if not (which
-+ *    will cause the mid layer to call us again later with the command)
-+ */
-+
- static int i91u_queuecommand(struct scsi_cmnd *cmd,
-               void (*done)(struct scsi_cmnd *))
- {
--      HCS *pHCB = (HCS *) cmd->device->host->base;
--      register SCB *pSCB;
-+      struct initio_host *host = (struct initio_host *) cmd->device->host->hostdata;
-+      struct scsi_ctrl_blk *cmnd;
+diff -Nurb linux-2.6.22-590/arch/x86_64/kernel/signal.c linux-2.6.22-570/arch/x86_64/kernel/signal.c
+--- linux-2.6.22-590/arch/x86_64/kernel/signal.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/kernel/signal.c       2007-07-08 19:32:17.000000000 -0400
+@@ -480,7 +480,7 @@
+ void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
+ { 
+       struct task_struct *me = current; 
+-      if (show_unhandled_signals && printk_ratelimit())
++      if (exception_trace)
+               printk("%s[%d] bad frame in %s frame:%p rip:%lx rsp:%lx orax:%lx\n",
+              me->comm,me->pid,where,frame,regs->rip,regs->rsp,regs->orig_rax); 
  
-       cmd->scsi_done = done;
+diff -Nurb linux-2.6.22-590/arch/x86_64/kernel/traps.c linux-2.6.22-570/arch/x86_64/kernel/traps.c
+--- linux-2.6.22-590/arch/x86_64/kernel/traps.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/kernel/traps.c        2008-01-23 19:16:04.000000000 -0500
+@@ -96,11 +96,6 @@
+ }
  
--      pSCB = tul_alloc_scb(pHCB);
--      if (!pSCB)
-+      cmnd = initio_alloc_scb(host);
-+      if (!cmnd)
-               return SCSI_MLQUEUE_HOST_BUSY;
+ int kstack_depth_to_print = 12;
+-#ifdef CONFIG_STACK_UNWIND
+-static int call_trace = 1;
+-#else
+-#define call_trace (-1)
+-#endif
  
--      i91uBuildSCB(pHCB, pSCB, cmd);
--      tul_exec_scb(pHCB, pSCB);
-+      initio_build_scb(host, cmnd, cmd);
-+      initio_exec_scb(host, cmnd);
-       return 0;
+ #ifdef CONFIG_KALLSYMS
+ void printk_address(unsigned long address)
+@@ -203,33 +198,6 @@
+       return NULL;
  }
  
--#if 0 /* no new EH yet */
--/*
-- *  Abort a queued command
-- *  (commands that are on the bus can't be aborted easily)
-- */
--static int i91u_abort(struct scsi_cmnd * SCpnt)
+-struct ops_and_data {
+-      struct stacktrace_ops *ops;
+-      void *data;
+-};
+-
+-static int dump_trace_unwind(struct unwind_frame_info *info, void *context)
 -{
--      HCS *pHCB;
+-      struct ops_and_data *oad = (struct ops_and_data *)context;
+-      int n = 0;
+-      unsigned long sp = UNW_SP(info);
 -
--      pHCB = (HCS *) SCpnt->device->host->base;
--      return tul_abort_srb(pHCB, SCpnt);
+-      if (arch_unw_user_mode(info))
+-              return -1;
+-      while (unwind(info) == 0 && UNW_PC(info)) {
+-              n++;
+-              oad->ops->address(oad->data, UNW_PC(info));
+-              if (arch_unw_user_mode(info))
+-                      break;
+-              if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
+-                  && sp > UNW_SP(info))
+-                      break;
+-              sp = UNW_SP(info);
+-              touch_nmi_watchdog();
+-      }
+-      return n;
 -}
 -
--/*
-- *  Reset registers, reset a hanging bus and
-- *  kill active and disconnected commands for target w/o soft reset
-+/**
-+ *    i91u_bus_reset          -       reset the SCSI bus
-+ *    @cmnd: Command block we want to trigger the reset for
-+ *
-+ *    Initiate a SCSI bus reset sequence
-  */
--static int i91u_reset(struct scsi_cmnd * SCpnt, unsigned int reset_flags)
--{                             /* I need Host Control Block Information */
--      HCS *pHCB;
--
--      pHCB = (HCS *) SCpnt->device->host->base;
--
--      if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET))
--              return tul_reset_scsi_bus(pHCB);
--      else
--              return tul_device_reset(pHCB, SCpnt, SCpnt->device->id, reset_flags);
--}
--#endif
--static int i91u_bus_reset(struct scsi_cmnd * SCpnt)
-+static int i91u_bus_reset(struct scsi_cmnd * cmnd)
- {
--      HCS *pHCB;
-+      struct initio_host *host;
--      pHCB = (HCS *) SCpnt->device->host->base;
-+      host = (struct initio_host *) cmnd->device->host->hostdata;
+ #define MSG(txt) ops->warning(data, txt)
  
--      spin_lock_irq(SCpnt->device->host->host_lock);
--      tul_reset_scsi(pHCB, 0);
--      spin_unlock_irq(SCpnt->device->host->host_lock);
-+      spin_lock_irq(cmnd->device->host->host_lock);
-+      initio_reset_scsi(host, 0);
-+      spin_unlock_irq(cmnd->device->host->host_lock);
+ /*
+@@ -257,40 +225,6 @@
+       if (!tsk)
+               tsk = current;
  
-       return SUCCESS;
+-      if (call_trace >= 0) {
+-              int unw_ret = 0;
+-              struct unwind_frame_info info;
+-              struct ops_and_data oad = { .ops = ops, .data = data };
+-
+-              if (regs) {
+-                      if (unwind_init_frame_info(&info, tsk, regs) == 0)
+-                              unw_ret = dump_trace_unwind(&info, &oad);
+-              } else if (tsk == current)
+-                      unw_ret = unwind_init_running(&info, dump_trace_unwind,
+-                                                    &oad);
+-              else {
+-                      if (unwind_init_blocked(&info, tsk) == 0)
+-                              unw_ret = dump_trace_unwind(&info, &oad);
+-              }
+-              if (unw_ret > 0) {
+-                      if (call_trace == 1 && !arch_unw_user_mode(&info)) {
+-                              ops->warning_symbol(data,
+-                                           "DWARF2 unwinder stuck at %s",
+-                                           UNW_PC(&info));
+-                              if ((long)UNW_SP(&info) < 0) {
+-                                      MSG("Leftover inexact backtrace:");
+-                                      stack = (unsigned long *)UNW_SP(&info);
+-                                      if (!stack)
+-                                              goto out;
+-                              } else
+-                                      MSG("Full inexact backtrace again:");
+-                      } else if (call_trace >= 1)
+-                              goto out;
+-                      else
+-                              MSG("Full inexact backtrace again:");
+-              } else
+-                      MSG("Inexact backtrace:");
+-      }
+       if (!stack) {
+               unsigned long dummy;
+               stack = &dummy;
+@@ -374,7 +308,6 @@
+       tinfo = task_thread_info(tsk);
+       HANDLE_STACK (valid_stack_ptr(tinfo, stack));
+ #undef HANDLE_STACK
+-out:
+       put_cpu();
  }
+ EXPORT_SYMBOL(dump_trace);
+@@ -652,8 +585,7 @@
+               tsk->thread.error_code = error_code;
+               tsk->thread.trap_no = trapnr;
  
--/*
-- * Return the "logical geometry"
-+/**
-+ *    i91u_biospararm                 -       return the "logical geometry
-+ *    @sdev: SCSI device
-+ *    @dev; Matching block device
-+ *    @capacity: Sector size of drive
-+ *    @info_array: Return space for BIOS geometry
-+ *
-+ *    Map the device geometry in a manner compatible with the host
-+ *    controller BIOS behaviour.
-+ *
-+ *    FIXME: limited to 2^32 sector devices.
-  */
-+
- static int i91u_biosparam(struct scsi_device *sdev, struct block_device *dev,
-               sector_t capacity, int *info_array)
- {
--      HCS *pHcb;              /* Point to Host adapter control block */
--      TCS *pTcb;
-+      struct initio_host *host;               /* Point to Host adapter control block */
-+      struct target_control *tc;
--      pHcb = (HCS *) sdev->host->base;
--      pTcb = &pHcb->HCS_Tcs[sdev->id];
-+      host = (struct initio_host *) sdev->host->hostdata;
-+      tc = &host->targets[sdev->id];
--      if (pTcb->TCS_DrvHead) {
--              info_array[0] = pTcb->TCS_DrvHead;
--              info_array[1] = pTcb->TCS_DrvSector;
--              info_array[2] = (unsigned long)capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector;
-+      if (tc->heads) {
-+              info_array[0] = tc->heads;
-+              info_array[1] = tc->sectors;
-+              info_array[2] = (unsigned long)capacity / tc->heads / tc->sectors;
-       } else {
--              if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) {
-+              if (tc->drv_flags & TCF_DRV_255_63) {
-                       info_array[0] = 255;
-                       info_array[1] = 63;
-                       info_array[2] = (unsigned long)capacity / 255 / 63;
-@@ -3047,7 +2722,16 @@
+-              if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
+-                  printk_ratelimit())
++              if (exception_trace && unhandled_signal(tsk, signr))
+                       printk(KERN_INFO
+                              "%s[%d:#%u] trap %s rip:%lx rsp:%lx error:%lx\n",
+                              tsk->comm, tsk->pid, tsk->xid, str,
+@@ -757,8 +689,7 @@
+               tsk->thread.error_code = error_code;
+               tsk->thread.trap_no = 13;
+-              if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+-                  printk_ratelimit())
++              if (exception_trace && unhandled_signal(tsk, SIGSEGV))
+                       printk(KERN_INFO
+                      "%s[%d:#%u] general protection rip:%lx rsp:%lx error:%lx\n",
+                              tsk->comm, tsk->pid, tsk->xid,
+@@ -1197,21 +1128,3 @@
        return 0;
  }
--static void i91u_unmap_cmnd(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd)
-+/**
-+ *    i91u_unmap_scb          -       Unmap a command
-+ *    @pci_dev: PCI device the command is for
-+ *    @cmnd: The command itself
-+ *
-+ *    Unmap any PCI mapping/IOMMU resources allocated when the command
-+ *    was mapped originally as part of initio_build_scb
-+ */
-+
-+static void i91u_unmap_scb(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd)
- {
-       /* auto sense buffer */
-       if (cmnd->SCp.ptr) {
-@@ -3058,65 +2742,63 @@
+ early_param("kstack", kstack_setup);
+-
+-#ifdef CONFIG_STACK_UNWIND
+-static int __init call_trace_setup(char *s)
+-{
+-      if (!s)
+-              return -EINVAL;
+-      if (strcmp(s, "old") == 0)
+-              call_trace = -1;
+-      else if (strcmp(s, "both") == 0)
+-              call_trace = 0;
+-      else if (strcmp(s, "newfallback") == 0)
+-              call_trace = 1;
+-      else if (strcmp(s, "new") == 0)
+-              call_trace = 2;
+-      return 0;
+-}
+-early_param("call_trace", call_trace_setup);
+-#endif
+diff -Nurb linux-2.6.22-590/arch/x86_64/kernel/unwind.S linux-2.6.22-570/arch/x86_64/kernel/unwind.S
+--- linux-2.6.22-590/arch/x86_64/kernel/unwind.S       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/kernel/unwind.S       1969-12-31 19:00:00.000000000 -0500
+@@ -1,38 +0,0 @@
+-/* Assembler support for dwarf2 unwinder */
+-#include <linux/linkage.h>
+-#include <asm/dwarf2.h>
+-#include <asm/segment.h>
+-#include <asm/ptrace.h>
+-#include <asm/asm-offsets.h>
+-
+-ENTRY(arch_unwind_init_running)
+-      CFI_STARTPROC
+-      movq    %r15, R15(%rdi)
+-      movq    %r14, R14(%rdi)
+-      xchgq   %rsi, %rdx
+-      movq    %r13, R13(%rdi)
+-      movq    %r12, R12(%rdi)
+-      xorl    %eax, %eax
+-      movq    %rbp, RBP(%rdi)
+-      movq    %rbx, RBX(%rdi)
+-      movq    (%rsp), %rcx
+-      movq    %rax, R11(%rdi)
+-      movq    %rax, R10(%rdi)
+-      movq    %rax, R9(%rdi)
+-      movq    %rax, R8(%rdi)
+-      movq    %rax, RAX(%rdi)
+-      movq    %rax, RCX(%rdi)
+-      movq    %rax, RDX(%rdi)
+-      movq    %rax, RSI(%rdi)
+-      movq    %rax, RDI(%rdi)
+-      movq    %rax, ORIG_RAX(%rdi)
+-      movq    %rcx, RIP(%rdi)
+-      leaq    8(%rsp), %rcx
+-      movq    $__KERNEL_CS, CS(%rdi)
+-      movq    %rax, EFLAGS(%rdi)
+-      movq    %rcx, RSP(%rdi)
+-      movq    $__KERNEL_DS, SS(%rdi)
+-      jmpq    *%rdx
+-      CFI_ENDPROC
+-ENDPROC(arch_unwind_init_running)
+-
+diff -Nurb linux-2.6.22-590/arch/x86_64/kernel/vmlinux.lds.S linux-2.6.22-570/arch/x86_64/kernel/vmlinux.lds.S
+--- linux-2.6.22-590/arch/x86_64/kernel/vmlinux.lds.S  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/kernel/vmlinux.lds.S  2007-07-08 19:32:17.000000000 -0400
+@@ -219,9 +219,7 @@
+   /* Sections to be discarded */
+   /DISCARD/ : {
+       *(.exitcall.exit)
+-#ifndef CONFIG_UNWIND_INFO
+       *(.eh_frame)
+-#endif
        }
  
-       /* request buffer */
--      if (cmnd->use_sg) {
-+      if (scsi_sg_count(cmnd)) {
-               dma_unmap_single(&pci_dev->dev, cmnd->SCp.dma_handle,
--                               sizeof(struct SG_Struc) * TOTAL_SG_ENTRY,
-+                               sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
-                                DMA_BIDIRECTIONAL);
+   STABS_DEBUG
+diff -Nurb linux-2.6.22-590/arch/x86_64/mm/fault.c linux-2.6.22-570/arch/x86_64/mm/fault.c
+--- linux-2.6.22-590/arch/x86_64/mm/fault.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/mm/fault.c    2008-01-23 19:16:04.000000000 -0500
+@@ -221,6 +221,16 @@
+       return 0;
+ } 
  
--              dma_unmap_sg(&pci_dev->dev, cmnd->request_buffer,
--                           cmnd->use_sg,
--                           cmnd->sc_data_direction);
--      } else if (cmnd->request_bufflen) {
--              dma_unmap_single(&pci_dev->dev, cmnd->SCp.dma_handle,
--                               cmnd->request_bufflen,
--                               cmnd->sc_data_direction);
-+              scsi_dma_unmap(cmnd);
-       }
- }
--/*****************************************************************************
-- Function name  : i91uSCBPost
-- Description    : This is callback routine be called when tulip finish one
--                      SCSI command.
-- Input          : pHCB  -       Pointer to host adapter control block.
--                pSCB  -       Pointer to SCSI control block.
-- Output         : None.
-- Return         : None.
--*****************************************************************************/
--static void i91uSCBPost(BYTE * pHcb, BYTE * pScb)
--{
--      struct scsi_cmnd *pSRB; /* Pointer to SCSI request block */
--      HCS *pHCB;
--      SCB *pSCB;
--
--      pHCB = (HCS *) pHcb;
--      pSCB = (SCB *) pScb;
--      if ((pSRB = pSCB->SCB_Srb) == 0) {
--              printk("i91uSCBPost: SRB pointer is empty\n");
-+/**
-+ *    i91uSCBPost             -       SCSI callback
-+ *    @host: Pointer to host adapter control block.
-+ *    @cmnd: Pointer to SCSI control block.
-+ *
-+ *    This is callback routine be called when tulip finish one
-+ *    SCSI command.
-+ */
-+
-+static void i91uSCBPost(u8 * host_mem, u8 * cblk_mem)
++int unhandled_signal(struct task_struct *tsk, int sig)
 +{
-+      struct scsi_cmnd *cmnd; /* Pointer to SCSI request block */
-+      struct initio_host *host;
-+      struct scsi_ctrl_blk *cblk;
--              tul_release_scb(pHCB, pSCB);    /* Release SCB for current channel */
-+      host = (struct initio_host *) host_mem;
-+      cblk = (struct scsi_ctrl_blk *) cblk_mem;
-+      if ((cmnd = cblk->srb) == NULL) {
-+              printk(KERN_ERR "i91uSCBPost: SRB pointer is empty\n");
-+              WARN_ON(1);
-+              initio_release_scb(host, cblk); /* Release SCB for current channel */
-               return;
-       }
--      switch (pSCB->SCB_HaStat) {
++      if (is_init(tsk))
++              return 1;
++      if (tsk->ptrace & PT_PTRACED)
++              return 0;
++      return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) ||
++              (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL);
++}
 +
-+      /*
-+       *      Remap the firmware error status into a mid layer one
-+       */
-+      switch (cblk->hastat) {
-       case 0x0:
-       case 0xa:               /* Linked command complete without error and linked normally */
-       case 0xb:               /* Linked command complete without error interrupt generated */
--              pSCB->SCB_HaStat = 0;
-+              cblk->hastat = 0;
-               break;
-       case 0x11:              /* Selection time out-The initiator selection or target
-                                  reselection was not complete within the SCSI Time out period */
--              pSCB->SCB_HaStat = DID_TIME_OUT;
-+              cblk->hastat = DID_TIME_OUT;
-               break;
-       case 0x14:              /* Target bus phase sequence failure-An invalid bus phase or bus
-                                  phase sequence was requested by the target. The host adapter
-                                  will generate a SCSI Reset Condition, notifying the host with
-                                  a SCRD interrupt */
--              pSCB->SCB_HaStat = DID_RESET;
-+              cblk->hastat = DID_RESET;
-               break;
-       case 0x1a:              /* SCB Aborted. 07/21/98 */
--              pSCB->SCB_HaStat = DID_ABORT;
-+              cblk->hastat = DID_ABORT;
-               break;
+ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
+                                unsigned long error_code)
+ {
+@@ -292,7 +302,7 @@
+ }
  
-       case 0x12:              /* Data overrun/underrun-The target attempted to transfer more data
-@@ -3126,49 +2808,196 @@
-       case 0x16:              /* Invalid SCB Operation Code. */
+ int page_fault_trace = 0;
+-int show_unhandled_signals = 1;
++int exception_trace = 1;
  
-       default:
--              printk("ini9100u: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat);
--              pSCB->SCB_HaStat = DID_ERROR;   /* Couldn't find any better */
-+              printk("ini9100u: %x %x\n", cblk->hastat, cblk->tastat);
-+              cblk->hastat = DID_ERROR;       /* Couldn't find any better */
-               break;
-       }
+ /*
+  * This routine handles page faults.  It determines the address,
+@@ -524,10 +534,6 @@
+       if (is_errata93(regs, address))
+               return; 
  
--      pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);
--
--      if (pSRB == NULL) {
--              printk("pSRB is NULL\n");
--      }
--
--      i91u_unmap_cmnd(pHCB->pci_dev, pSRB);
--      pSRB->scsi_done(pSRB);  /* Notify system DONE           */
+-      if (notify_die(DIE_PAGE_FAULT_NO_CONTEXT, "no context", regs,
+-                              error_code, 14, SIGSEGV) == NOTIFY_STOP)
+-              return;
 -
--      tul_release_scb(pHCB, pSCB);    /* Release SCB for current channel */
-+      cmnd->result = cblk->tastat | (cblk->hastat << 16);
-+      WARN_ON(cmnd == NULL);
-+      i91u_unmap_scb(host->pci_dev, cmnd);
-+      cmnd->scsi_done(cmnd);  /* Notify system DONE           */
-+      initio_release_scb(host, cblk); /* Release SCB for current channel */
+ /*
+  * Oops. The kernel tried to access some bad page. We'll have to
+  * terminate things with extreme prejudice.
+diff -Nurb linux-2.6.22-590/arch/x86_64/mm/init.c linux-2.6.22-570/arch/x86_64/mm/init.c
+--- linux-2.6.22-590/arch/x86_64/mm/init.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/arch/x86_64/mm/init.c     2008-01-23 19:15:55.000000000 -0500
+@@ -697,6 +697,41 @@
+       return pfn_valid(pte_pfn(*pte));
  }
  
--/*
-- * Release ressources
-- */
--static int i91u_release(struct Scsi_Host *hreg)
--{
--      free_irq(hreg->irq, hreg);
--      release_region(hreg->io_port, 256);
--      return 0;
--}
--MODULE_LICENSE("Dual BSD/GPL");
--
--static struct scsi_host_template driver_template = {
-+static struct scsi_host_template initio_template = {
-       .proc_name      = "INI9100U",
--      .name           = i91u_REVID,
--      .detect         = i91u_detect,
--      .release        = i91u_release,
-+      .name                   = "Initio INI-9X00U/UW SCSI device driver",
-       .queuecommand   = i91u_queuecommand,
--//    .abort          = i91u_abort,
--//    .reset          = i91u_reset,
-       .eh_bus_reset_handler = i91u_bus_reset,
-       .bios_param     = i91u_biosparam,
--      .can_queue      = 1,
-+      .can_queue              = MAX_TARGETS * i91u_MAXQUEUE,
-       .this_id        = 1,
-       .sg_tablesize   = SG_ALL,
-       .cmd_per_lun    = 1,
-       .use_clustering = ENABLE_CLUSTERING,
- };
--#include "scsi_module.c"
-+static int initio_probe_one(struct pci_dev *pdev,
-+      const struct pci_device_id *id)
-+{
-+      struct Scsi_Host *shost;
-+      struct initio_host *host;
-+      u32 reg;
-+      u16 bios_seg;
-+      struct scsi_ctrl_blk *scb, *tmp, *prev = NULL /* silence gcc */;
-+      int num_scb, i, error;
-+
-+      error = pci_enable_device(pdev);
-+      if (error)
-+              return error;
-+
-+      pci_read_config_dword(pdev, 0x44, (u32 *) & reg);
-+      bios_seg = (u16) (reg & 0xFF);
-+      if (((reg & 0xFF00) >> 8) == 0xFF)
-+              reg = 0;
-+      bios_seg = (bios_seg << 8) + ((u16) ((reg & 0xFF00) >> 8));
-+
-+      if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
-+              printk(KERN_WARNING  "i91u: Could not set 32 bit DMA mask\n");
-+              error = -ENODEV;
-+              goto out_disable_device;
-+      }
-+      shost = scsi_host_alloc(&initio_template, sizeof(struct initio_host));
-+      if (!shost) {
-+              printk(KERN_WARNING "initio: Could not allocate host structure.\n");
-+              error = -ENOMEM;
-+              goto out_disable_device;
-+      }
-+      host = (struct initio_host *)shost->hostdata;
-+      memset(host, 0, sizeof(struct initio_host));
-+
-+      if (!request_region(host->addr, 256, "i91u")) {
-+              printk(KERN_WARNING "initio: I/O port range 0x%x is busy.\n", host->addr);
-+              error = -ENODEV;
-+              goto out_host_put;
-+      }
-+
-+      if (initio_tag_enable)  /* 1.01i */
-+              num_scb = MAX_TARGETS * i91u_MAXQUEUE;
-+      else
-+              num_scb = MAX_TARGETS + 3;      /* 1-tape, 1-CD_ROM, 1- extra */
-+
-+      for (; num_scb >= MAX_TARGETS + 3; num_scb--) {
-+              i = num_scb * sizeof(struct scsi_ctrl_blk);
-+              if ((scb = kzalloc(i, GFP_DMA)) != NULL)
-+                      break;
-+      }
++#ifdef CONFIG_SYSCTL
++#include <linux/sysctl.h>
 +
-+      if (!scb) {
-+              printk(KERN_WARNING "initio: Cannot allocate SCB array.\n");
-+              error = -ENOMEM;
-+              goto out_release_region;
-+      }
++extern int exception_trace, page_fault_trace;
 +
-+      host->num_scbs = num_scb;
-+      host->scb = scb;
-+      host->next_pending = scb;
-+      host->next_avail = scb;
-+      for (i = 0, tmp = scb; i < num_scb; i++, tmp++) {
-+              tmp->tagid = i;
-+              if (i != 0)
-+                      prev->next = tmp;
-+              prev = tmp;
-+      }
-+      prev->next = NULL;
-+      host->scb_end = tmp;
-+      host->first_avail = scb;
-+      host->last_avail = prev;
-+
-+      initio_init(host, phys_to_virt(bios_seg << 4));
-+
-+      host->jsstatus0 = 0;
-+
-+      shost->io_port = host->addr;
-+      shost->n_io_port = 0xff;
-+      shost->can_queue = num_scb;             /* 03/05/98                      */
-+      shost->unique_id = host->addr;
-+      shost->max_id = host->max_tar;
-+      shost->max_lun = 32;    /* 10/21/97                     */
-+      shost->irq = pdev->irq;
-+      shost->this_id = host->scsi_id; /* Assign HCS index           */
-+      shost->base = host->addr;
-+      shost->sg_tablesize = TOTAL_SG_ENTRY;
-+
-+      error = request_irq(pdev->irq, i91u_intr, IRQF_DISABLED|IRQF_SHARED, "i91u", shost);
-+      if (error < 0) {
-+              printk(KERN_WARNING "initio: Unable to request IRQ %d\n", pdev->irq);
-+              goto out_free_scbs;
-+      }
++static ctl_table debug_table2[] = {
++      {
++              .ctl_name       = 99,
++              .procname       = "exception-trace",
++              .data           = &exception_trace,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = proc_dointvec
++      },
++      {}
++}; 
 +
-+      pci_set_drvdata(pdev, shost);
-+      host->pci_dev = pdev;
++static ctl_table debug_root_table2[] = { 
++      {
++              .ctl_name = CTL_DEBUG,
++              .procname = "debug",
++              .mode = 0555,
++              .child = debug_table2
++      },
++      {}
++}; 
 +
-+      error = scsi_add_host(shost, &pdev->dev);
-+      if (error)
-+              goto out_free_irq;
-+      scsi_scan_host(shost);
++static __init int x8664_sysctl_init(void)
++{ 
++      register_sysctl_table(debug_root_table2);
 +      return 0;
-+out_free_irq:
-+      free_irq(pdev->irq, shost);
-+out_free_scbs:
-+      kfree(host->scb);
-+out_release_region:
-+      release_region(host->addr, 256);
-+out_host_put:
-+      scsi_host_put(shost);
-+out_disable_device:
-+      pci_disable_device(pdev);
-+      return error;
-+}
-+
-+/**
-+ *    initio_remove_one       -       control shutdown
-+ *    @pdev:  PCI device being released
-+ *
-+ *    Release the resources assigned to this adapter after it has
-+ *    finished being used.
-+ */
-+
-+static void initio_remove_one(struct pci_dev *pdev)
-+{
-+      struct Scsi_Host *host = pci_get_drvdata(pdev);
-+      struct initio_host *s = (struct initio_host *)host->hostdata;
-+      scsi_remove_host(host);
-+      free_irq(pdev->irq, host);
-+      release_region(s->addr, 256);
-+      scsi_host_put(host);
-+      pci_disable_device(pdev);
-+}
-+
-+MODULE_LICENSE("GPL");
-+
-+static struct pci_device_id initio_pci_tbl[] = {
-+      {PCI_VENDOR_ID_INIT, 0x9500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-+      {PCI_VENDOR_ID_INIT, 0x9400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-+      {PCI_VENDOR_ID_INIT, 0x9401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-+      {PCI_VENDOR_ID_INIT, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-+      {PCI_VENDOR_ID_DOMEX, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-+      {0,}
-+};
-+MODULE_DEVICE_TABLE(pci, initio_pci_tbl);
-+
-+static struct pci_driver initio_pci_driver = {
-+      .name           = "initio",
-+      .id_table       = initio_pci_tbl,
-+      .probe          = initio_probe_one,
-+      .remove         = __devexit_p(initio_remove_one),
-+};
-+
-+static int __init initio_init_driver(void)
-+{
-+      return pci_register_driver(&initio_pci_driver);
-+}
-+
-+static void __exit initio_exit_driver(void)
-+{
-+      pci_unregister_driver(&initio_pci_driver);
 +}
++__initcall(x8664_sysctl_init);
++#endif
 +
-+MODULE_DESCRIPTION("Initio INI-9X00U/UW SCSI device driver");
-+MODULE_AUTHOR("Initio Corporation");
-+MODULE_LICENSE("GPL");
+ /* A pseudo VMA to allow ptrace access for the vsyscall page.  This only
+    covers the 64bit vsyscall page now. 32bit has a real VMA now and does
+    not need special handling anymore. */
+diff -Nurb linux-2.6.22-590/creatinst.sh linux-2.6.22-570/creatinst.sh
+--- linux-2.6.22-590/creatinst.sh      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/creatinst.sh      1969-12-31 19:00:00.000000000 -0500
+@@ -1,12 +0,0 @@
+-rm -fR inst
+-mkdir inst
+-make install INSTALL_PATH=inst
+-make modules_install INSTALL_MOD_PATH=inst
+-tar cfz inst.tar.gz inst
+-scp -i ~/newvici inst.tar.gz root@vici-03:/tmp
+-ssh -i ~/newvici root@vici-03 "cd /tmp;tar xvfz inst.tar.gz"
+-ssh -i ~/newvici root@vici-03 "wget www/~sapanb/vgup;sh vgup"
+-ssh -i ~/newvici root@vici-03 "cp -R /tmp/inst/lib/* /mnt/lib/"
+-ssh -i ~/newvici root@vici-03 "rm -fR /tmp/inst/lib; mv /tmp/inst/* /mnt/boot"
+-sleep 5
+-ssh -i ~/newvici root@vici-03 reboot
+diff -Nurb linux-2.6.22-590/crypto/Kconfig linux-2.6.22-570/crypto/Kconfig
+--- linux-2.6.22-590/crypto/Kconfig    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/crypto/Kconfig    2007-07-08 19:32:17.000000000 -0400
+@@ -1,17 +1,7 @@
+ #
+-# Generic algorithms support
+-#
+-config XOR_BLOCKS
+-      tristate
+-
+-#
+-# async_tx api: hardware offloaded memory transfer/transform support
+-#
+-source "crypto/async_tx/Kconfig"
+-
+-#
+ # Cryptographic API Configuration
+ #
 +
-+module_init(initio_init_driver);
-+module_exit(initio_exit_driver);
-diff -Nurb linux-2.6.22-570/drivers/scsi/initio.h linux-2.6.22-590/drivers/scsi/initio.h
---- linux-2.6.22-570/drivers/scsi/initio.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/initio.h     2008-01-02 13:56:37.000000000 -0500
-@@ -4,6 +4,8 @@
-  * Copyright (c) 1994-1998 Initio Corporation
-  * All rights reserved.
-  *
-+ * Cleanups (c) Copyright 2007 Red Hat <alan@redhat.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, or (at your option)
-@@ -18,27 +20,6 @@
-  * along with this program; see the file COPYING.  If not, write to
-  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-  *
-- * --------------------------------------------------------------------------
-- *
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met:
-- * 1. Redistributions of source code must retain the above copyright
-- *    notice, this list of conditions, and the following disclaimer,
-- *    without modification, immediately at the beginning of the file.
-- * 2. Redistributions in binary form must reproduce the above copyright
-- *    notice, this list of conditions and the following disclaimer in the
-- *    documentation and/or other materials provided with the distribution.
-- * 3. The name of the author may not be used to endorse or promote products
-- *    derived from this software without specific prior written permission.
-- *
-- * Where this Software is combined with software released under the terms of 
-- * the GNU General Public License ("GPL") and the terms of the GPL would require the 
-- * combined work to also be released under the terms of the GPL, the terms
-- * and conditions of this License will apply in addition to those of the
-- * GPL with the exception of any terms or conditions of this License that
-- * conflict with, or are expressly prohibited by, the GPL.
-- *
-  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-@@ -56,17 +37,6 @@
+ menu "Cryptographic options"
  
- #include <linux/types.h>
+ config CRYPTO
+diff -Nurb linux-2.6.22-590/crypto/Makefile linux-2.6.22-570/crypto/Makefile
+--- linux-2.6.22-590/crypto/Makefile   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/crypto/Makefile   2007-07-08 19:32:17.000000000 -0400
+@@ -50,9 +50,3 @@
+ obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
  
--#define ULONG   unsigned long
--#define USHORT  unsigned short
--#define UCHAR   unsigned char
--#define BYTE    unsigned char
--#define WORD    unsigned short
--#define DWORD   unsigned long
--#define UBYTE   unsigned char
--#define UWORD   unsigned short
--#define UDWORD  unsigned long
--#define U32     u32
+ obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
 -
- #define TOTAL_SG_ENTRY                32
- #define MAX_SUPPORTED_ADAPTERS  8
- #define MAX_OFFSET            15
-@@ -368,55 +338,55 @@
- /************************************************************************/
- /*              Scatter-Gather Element Structure                        */
- /************************************************************************/
--typedef struct SG_Struc {
--      U32 SG_Ptr;             /* Data Pointer */
--      U32 SG_Len;             /* Data Length */
--} SG;
-+struct sg_entry {
-+      u32 data;               /* Data Pointer */
-+      u32 len;                /* Data Length */
-+};
- /***********************************************************************
-               SCSI Control Block
- ************************************************************************/
--typedef struct Scsi_Ctrl_Blk {
--      struct Scsi_Ctrl_Blk *SCB_NxtScb;
--      UBYTE SCB_Status;       /*4 */
--      UBYTE SCB_NxtStat;      /*5 */
--      UBYTE SCB_Mode;         /*6 */
--      UBYTE SCB_Msgin;        /*7 SCB_Res0 */
--      UWORD SCB_SGIdx;        /*8 */
--      UWORD SCB_SGMax;        /*A */
-+struct scsi_ctrl_blk {
-+      struct scsi_ctrl_blk *next;
-+      u8 status;      /*4 */
-+      u8 next_state;  /*5 */
-+      u8 mode;                /*6 */
-+      u8 msgin;       /*7 SCB_Res0 */
-+      u16 sgidx;      /*8 */
-+      u16 sgmax;      /*A */
- #ifdef ALPHA
--      U32 SCB_Reserved[2];    /*C */
-+      u32 reserved[2];        /*C */
- #else
--      U32 SCB_Reserved[3];    /*C */
-+      u32 reserved[3];        /*C */
- #endif
--      U32 SCB_XferLen;        /*18 Current xfer len           */
--      U32 SCB_TotXLen;        /*1C Total xfer len             */
--      U32 SCB_PAddr;          /*20 SCB phy. Addr. */
--
--      UBYTE SCB_Opcode;       /*24 SCB command code */
--      UBYTE SCB_Flags;        /*25 SCB Flags */
--      UBYTE SCB_Target;       /*26 Target Id */
--      UBYTE SCB_Lun;          /*27 Lun */
--      U32 SCB_BufPtr;         /*28 Data Buffer Pointer */
--      U32 SCB_BufLen;         /*2C Data Allocation Length */
--      UBYTE SCB_SGLen;        /*30 SG list # */
--      UBYTE SCB_SenseLen;     /*31 Sense Allocation Length */
--      UBYTE SCB_HaStat;       /*32 */
--      UBYTE SCB_TaStat;       /*33 */
--      UBYTE SCB_CDBLen;       /*34 CDB Length */
--      UBYTE SCB_Ident;        /*35 Identify */
--      UBYTE SCB_TagMsg;       /*36 Tag Message */
--      UBYTE SCB_TagId;        /*37 Queue Tag */
--      UBYTE SCB_CDB[12];      /*38 */
--      U32 SCB_SGPAddr;        /*44 SG List/Sense Buf phy. Addr. */
--      U32 SCB_SensePtr;       /*48 Sense data pointer */
--      void (*SCB_Post) (BYTE *, BYTE *);      /*4C POST routine */
--      struct scsi_cmnd *SCB_Srb;      /*50 SRB Pointer */
--      SG SCB_SGList[TOTAL_SG_ENTRY];  /*54 Start of SG list */
--} SCB;
-+      u32 xferlen;    /*18 Current xfer len           */
-+      u32 totxlen;    /*1C Total xfer len             */
-+      u32 paddr;              /*20 SCB phy. Addr. */
-+
-+      u8 opcode;      /*24 SCB command code */
-+      u8 flags;       /*25 SCB Flags */
-+      u8 target;      /*26 Target Id */
-+      u8 lun;         /*27 Lun */
-+      u32 bufptr;             /*28 Data Buffer Pointer */
-+      u32 buflen;             /*2C Data Allocation Length */
-+      u8 sglen;       /*30 SG list # */
-+      u8 senselen;    /*31 Sense Allocation Length */
-+      u8 hastat;      /*32 */
-+      u8 tastat;      /*33 */
-+      u8 cdblen;      /*34 CDB Length */
-+      u8 ident;       /*35 Identify */
-+      u8 tagmsg;      /*36 Tag Message */
-+      u8 tagid;       /*37 Queue Tag */
-+      u8 cdb[12];     /*38 */
-+      u32 sgpaddr;    /*44 SG List/Sense Buf phy. Addr. */
-+      u32 senseptr;   /*48 Sense data pointer */
-+      void (*post) (u8 *, u8 *);      /*4C POST routine */
-+      struct scsi_cmnd *srb;  /*50 SRB Pointer */
-+      struct sg_entry sglist[TOTAL_SG_ENTRY]; /*54 Start of SG list */
-+};
--/* Bit Definition for SCB_Status */
-+/* Bit Definition for status */
- #define SCB_RENT        0x01
- #define SCB_PEND        0x02
- #define SCB_CONTIG      0x04  /* Contigent Allegiance */
-@@ -425,17 +395,17 @@
- #define SCB_DONE        0x20
--/* Opcodes of SCB_Opcode */
-+/* Opcodes for opcode */
- #define ExecSCSI        0x1
- #define BusDevRst       0x2
- #define AbortCmd        0x3
--/* Bit Definition for SCB_Mode */
-+/* Bit Definition for mode */
- #define SCM_RSENS       0x01  /* request sense mode */
--/* Bit Definition for SCB_Flags */
-+/* Bit Definition for flags */
- #define SCF_DONE        0x01
- #define SCF_POST        0x02
- #define SCF_SENSE       0x04
-@@ -492,15 +462,14 @@
-               Target Device Control Structure
- **********************************************************************/
--typedef struct Tar_Ctrl_Struc {
--      UWORD TCS_Flags;        /* 0 */
--      UBYTE TCS_JS_Period;    /* 2 */
--      UBYTE TCS_SConfig0;     /* 3 */
--
--      UWORD TCS_DrvFlags;     /* 4 */
--      UBYTE TCS_DrvHead;      /* 6 */
--      UBYTE TCS_DrvSector;    /* 7 */
--} TCS;
-+struct target_control {
-+      u16 flags;
-+      u8 js_period;
-+      u8 sconfig0;
-+      u16 drv_flags;
-+      u8 heads;
-+      u8 sectors;
-+};
- /***********************************************************************
-               Target Device Control Structure
-@@ -523,62 +492,53 @@
- #define TCF_DRV_EN_TAG          0x0800
- #define TCF_DRV_255_63          0x0400
--typedef struct I91u_Adpt_Struc {
--      UWORD ADPT_BIOS;        /* 0 */
--      UWORD ADPT_BASE;        /* 1 */
--      UBYTE ADPT_Bus;         /* 2 */
--      UBYTE ADPT_Device;      /* 3 */
--      UBYTE ADPT_INTR;        /* 4 */
--} INI_ADPT_STRUCT;
+-#
+-# generic algorithms and the async_tx api
+-#
+-obj-$(CONFIG_XOR_BLOCKS) += xor.o
+-obj-$(CONFIG_ASYNC_CORE) += async_tx/
+diff -Nurb linux-2.6.22-590/crypto/async_tx/Kconfig linux-2.6.22-570/crypto/async_tx/Kconfig
+--- linux-2.6.22-590/crypto/async_tx/Kconfig   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/crypto/async_tx/Kconfig   1969-12-31 19:00:00.000000000 -0500
+@@ -1,16 +0,0 @@
+-config ASYNC_CORE
+-      tristate
+-
+-config ASYNC_MEMCPY
+-      tristate
+-      select ASYNC_CORE
+-
+-config ASYNC_XOR
+-      tristate
+-      select ASYNC_CORE
+-      select XOR_BLOCKS
+-
+-config ASYNC_MEMSET
+-      tristate
+-      select ASYNC_CORE
+-
+diff -Nurb linux-2.6.22-590/crypto/async_tx/Makefile linux-2.6.22-570/crypto/async_tx/Makefile
+--- linux-2.6.22-590/crypto/async_tx/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/crypto/async_tx/Makefile  1969-12-31 19:00:00.000000000 -0500
+@@ -1,4 +0,0 @@
+-obj-$(CONFIG_ASYNC_CORE) += async_tx.o
+-obj-$(CONFIG_ASYNC_MEMCPY) += async_memcpy.o
+-obj-$(CONFIG_ASYNC_MEMSET) += async_memset.o
+-obj-$(CONFIG_ASYNC_XOR) += async_xor.o
+diff -Nurb linux-2.6.22-590/crypto/async_tx/async_memcpy.c linux-2.6.22-570/crypto/async_tx/async_memcpy.c
+--- linux-2.6.22-590/crypto/async_tx/async_memcpy.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/crypto/async_tx/async_memcpy.c    1969-12-31 19:00:00.000000000 -0500
+@@ -1,131 +0,0 @@
+-/*
+- * copy offload engine support
+- *
+- * Copyright Â© 2006, Intel Corporation.
+- *
+- *      Dan Williams <dan.j.williams@intel.com>
+- *
+- *      with architecture considerations by:
+- *      Neil Brown <neilb@suse.de>
+- *      Jeff Garzik <jeff@garzik.org>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- *
+- */
+-#include <linux/kernel.h>
+-#include <linux/highmem.h>
+-#include <linux/mm.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/async_tx.h>
+-
+-/**
+- * async_memcpy - attempt to copy memory with a dma engine.
+- * @dest: destination page
+- * @src: src page
+- * @offset: offset in pages to start transaction
+- * @len: length in bytes
+- * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK,
+- *    ASYNC_TX_KMAP_SRC, ASYNC_TX_KMAP_DST
+- * @depend_tx: memcpy depends on the result of this transaction
+- * @cb_fn: function to call when the memcpy completes
+- * @cb_param: parameter to pass to the callback routine
+- */
+-struct dma_async_tx_descriptor *
+-async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
+-      unsigned int src_offset, size_t len, enum async_tx_flags flags,
+-      struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_param)
+-{
+-      struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMCPY);
+-      struct dma_device *device = chan ? chan->device : NULL;
+-      int int_en = cb_fn ? 1 : 0;
+-      struct dma_async_tx_descriptor *tx = device ?
+-              device->device_prep_dma_memcpy(chan, len,
+-              int_en) : NULL;
+-
+-      if (tx) { /* run the memcpy asynchronously */
+-              dma_addr_t addr;
+-              enum dma_data_direction dir;
+-
+-              pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+-
+-              dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+-                      DMA_NONE : DMA_FROM_DEVICE;
+-
+-              addr = dma_map_page(device->dev, dest, dest_offset, len, dir);
+-              tx->tx_set_dest(addr, tx, 0);
+-
+-              dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+-                      DMA_NONE : DMA_TO_DEVICE;
+-
+-              addr = dma_map_page(device->dev, src, src_offset, len, dir);
+-              tx->tx_set_src(addr, tx, 0);
+-
+-              async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+-      } else { /* run the memcpy synchronously */
+-              void *dest_buf, *src_buf;
+-              pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+-
+-              /* wait for any prerequisite operations */
+-              if (depend_tx) {
+-                      /* if ack is already set then we cannot be sure
+-                       * we are referring to the correct operation
+-                       */
+-                      BUG_ON(depend_tx->ack);
+-                      if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+-                              panic("%s: DMA_ERROR waiting for depend_tx\n",
+-                                      __FUNCTION__);
+-              }
+-
+-              if (flags & ASYNC_TX_KMAP_DST)
+-                      dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
+-              else
+-                      dest_buf = page_address(dest) + dest_offset;
+-
+-              if (flags & ASYNC_TX_KMAP_SRC)
+-                      src_buf = kmap_atomic(src, KM_USER0) + src_offset;
+-              else
+-                      src_buf = page_address(src) + src_offset;
+-
+-              memcpy(dest_buf, src_buf, len);
+-
+-              if (flags & ASYNC_TX_KMAP_DST)
+-                      kunmap_atomic(dest_buf, KM_USER0);
+-
+-              if (flags & ASYNC_TX_KMAP_SRC)
+-                      kunmap_atomic(src_buf, KM_USER0);
+-
+-              async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+-      }
+-
+-      return tx;
+-}
+-EXPORT_SYMBOL_GPL(async_memcpy);
+-
+-static int __init async_memcpy_init(void)
+-{
+-      return 0;
+-}
+-
+-static void __exit async_memcpy_exit(void)
+-{
+-      do { } while (0);
+-}
+-
+-module_init(async_memcpy_init);
+-module_exit(async_memcpy_exit);
+-
+-MODULE_AUTHOR("Intel Corporation");
+-MODULE_DESCRIPTION("asynchronous memcpy api");
+-MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/crypto/async_tx/async_memset.c linux-2.6.22-570/crypto/async_tx/async_memset.c
+--- linux-2.6.22-590/crypto/async_tx/async_memset.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/crypto/async_tx/async_memset.c    1969-12-31 19:00:00.000000000 -0500
+@@ -1,109 +0,0 @@
+-/*
+- * memory fill offload engine support
+- *
+- * Copyright Â© 2006, Intel Corporation.
+- *
+- *      Dan Williams <dan.j.williams@intel.com>
+- *
+- *      with architecture considerations by:
+- *      Neil Brown <neilb@suse.de>
+- *      Jeff Garzik <jeff@garzik.org>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- *
+- */
+-#include <linux/kernel.h>
+-#include <linux/interrupt.h>
+-#include <linux/mm.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/async_tx.h>
 -
+-/**
+- * async_memset - attempt to fill memory with a dma engine.
+- * @dest: destination page
+- * @val: fill value
+- * @offset: offset in pages to start transaction
+- * @len: length in bytes
+- * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+- * @depend_tx: memset depends on the result of this transaction
+- * @cb_fn: function to call when the memcpy completes
+- * @cb_param: parameter to pass to the callback routine
+- */
+-struct dma_async_tx_descriptor *
+-async_memset(struct page *dest, int val, unsigned int offset,
+-      size_t len, enum async_tx_flags flags,
+-      struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_param)
+-{
+-      struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMSET);
+-      struct dma_device *device = chan ? chan->device : NULL;
+-      int int_en = cb_fn ? 1 : 0;
+-      struct dma_async_tx_descriptor *tx = device ?
+-              device->device_prep_dma_memset(chan, val, len,
+-                      int_en) : NULL;
+-
+-      if (tx) { /* run the memset asynchronously */
+-              dma_addr_t dma_addr;
+-              enum dma_data_direction dir;
 -
- /***********************************************************************
-             Host Adapter Control Structure
- ************************************************************************/
--typedef struct Ha_Ctrl_Struc {
--      UWORD HCS_Base;         /* 00 */
--      UWORD HCS_BIOS;         /* 02 */
--      UBYTE HCS_Intr;         /* 04 */
--      UBYTE HCS_SCSI_ID;      /* 05 */
--      UBYTE HCS_MaxTar;       /* 06 */
--      UBYTE HCS_NumScbs;      /* 07 */
--
--      UBYTE HCS_Flags;        /* 08 */
--      UBYTE HCS_Index;        /* 09 */
--      UBYTE HCS_HaId;         /* 0A */
--      UBYTE HCS_Config;       /* 0B */
--      UWORD HCS_IdMask;       /* 0C */
--      UBYTE HCS_Semaph;       /* 0E */
--      UBYTE HCS_Phase;        /* 0F */
--      UBYTE HCS_JSStatus0;    /* 10 */
--      UBYTE HCS_JSInt;        /* 11 */
--      UBYTE HCS_JSStatus1;    /* 12 */
--      UBYTE HCS_SConf1;       /* 13 */
--
--      UBYTE HCS_Msg[8];       /* 14 */
--      SCB *HCS_NxtAvail;      /* 1C */
--      SCB *HCS_Scb;           /* 20 */
--      SCB *HCS_ScbEnd;        /* 24 */
--      SCB *HCS_NxtPend;       /* 28 */
--      SCB *HCS_NxtContig;     /* 2C */
--      SCB *HCS_ActScb;        /* 30 */
--      TCS *HCS_ActTcs;        /* 34 */
--
--      SCB *HCS_FirstAvail;    /* 38 */
--      SCB *HCS_LastAvail;     /* 3C */
--      SCB *HCS_FirstPend;     /* 40 */
--      SCB *HCS_LastPend;      /* 44 */
--      SCB *HCS_FirstBusy;     /* 48 */
--      SCB *HCS_LastBusy;      /* 4C */
--      SCB *HCS_FirstDone;     /* 50 */
--      SCB *HCS_LastDone;      /* 54 */
--      UBYTE HCS_MaxTags[16];  /* 58 */
--      UBYTE HCS_ActTags[16];  /* 68 */
--      TCS HCS_Tcs[MAX_TARGETS];       /* 78 */
--      spinlock_t HCS_AvailLock;
--      spinlock_t HCS_SemaphLock;
-+struct initio_host {
-+      u16 addr;               /* 00 */
-+      u16 bios_addr;          /* 02 */
-+      u8 irq;                 /* 04 */
-+      u8 scsi_id;             /* 05 */
-+      u8 max_tar;             /* 06 */
-+      u8 num_scbs;            /* 07 */
-+
-+      u8 flags;               /* 08 */
-+      u8 index;               /* 09 */
-+      u8 ha_id;               /* 0A */
-+      u8 config;              /* 0B */
-+      u16 idmask;             /* 0C */
-+      u8 semaph;              /* 0E */
-+      u8 phase;               /* 0F */
-+      u8 jsstatus0;           /* 10 */
-+      u8 jsint;               /* 11 */
-+      u8 jsstatus1;           /* 12 */
-+      u8 sconf1;              /* 13 */
-+
-+      u8 msg[8];              /* 14 */
-+      struct scsi_ctrl_blk *next_avail;       /* 1C */
-+      struct scsi_ctrl_blk *scb;              /* 20 */
-+      struct scsi_ctrl_blk *scb_end;          /* 24 */ /*UNUSED*/
-+      struct scsi_ctrl_blk *next_pending;     /* 28 */
-+      struct scsi_ctrl_blk *next_contig;      /* 2C */ /*UNUSED*/
-+      struct scsi_ctrl_blk *active;           /* 30 */
-+      struct target_control *active_tc;       /* 34 */
-+
-+      struct scsi_ctrl_blk *first_avail;      /* 38 */
-+      struct scsi_ctrl_blk *last_avail;       /* 3C */
-+      struct scsi_ctrl_blk *first_pending;    /* 40 */
-+      struct scsi_ctrl_blk *last_pending;     /* 44 */
-+      struct scsi_ctrl_blk *first_busy;       /* 48 */
-+      struct scsi_ctrl_blk *last_busy;        /* 4C */
-+      struct scsi_ctrl_blk *first_done;       /* 50 */
-+      struct scsi_ctrl_blk *last_done;        /* 54 */
-+      u8 max_tags[16];        /* 58 */
-+      u8 act_tags[16];        /* 68 */
-+      struct target_control targets[MAX_TARGETS];     /* 78 */
-+      spinlock_t avail_lock;
-+      spinlock_t semaph_lock;
-       struct pci_dev *pci_dev;
--} HCS;
-+};
- /* Bit Definition for HCB_Config */
- #define HCC_SCSI_RESET          0x01
-@@ -599,47 +559,47 @@
- *******************************************************************/
- typedef struct _NVRAM_SCSI {  /* SCSI channel configuration   */
--      UCHAR NVM_ChSCSIID;     /* 0Ch -> Channel SCSI ID       */
--      UCHAR NVM_ChConfig1;    /* 0Dh -> Channel config 1      */
--      UCHAR NVM_ChConfig2;    /* 0Eh -> Channel config 2      */
--      UCHAR NVM_NumOfTarg;    /* 0Fh -> Number of SCSI target */
-+      u8 NVM_ChSCSIID;        /* 0Ch -> Channel SCSI ID       */
-+      u8 NVM_ChConfig1;       /* 0Dh -> Channel config 1      */
-+      u8 NVM_ChConfig2;       /* 0Eh -> Channel config 2      */
-+      u8 NVM_NumOfTarg;       /* 0Fh -> Number of SCSI target */
-       /* SCSI target configuration    */
--      UCHAR NVM_Targ0Config;  /* 10h -> Target 0 configuration */
--      UCHAR NVM_Targ1Config;  /* 11h -> Target 1 configuration */
--      UCHAR NVM_Targ2Config;  /* 12h -> Target 2 configuration */
--      UCHAR NVM_Targ3Config;  /* 13h -> Target 3 configuration */
--      UCHAR NVM_Targ4Config;  /* 14h -> Target 4 configuration */
--      UCHAR NVM_Targ5Config;  /* 15h -> Target 5 configuration */
--      UCHAR NVM_Targ6Config;  /* 16h -> Target 6 configuration */
--      UCHAR NVM_Targ7Config;  /* 17h -> Target 7 configuration */
--      UCHAR NVM_Targ8Config;  /* 18h -> Target 8 configuration */
--      UCHAR NVM_Targ9Config;  /* 19h -> Target 9 configuration */
--      UCHAR NVM_TargAConfig;  /* 1Ah -> Target A configuration */
--      UCHAR NVM_TargBConfig;  /* 1Bh -> Target B configuration */
--      UCHAR NVM_TargCConfig;  /* 1Ch -> Target C configuration */
--      UCHAR NVM_TargDConfig;  /* 1Dh -> Target D configuration */
--      UCHAR NVM_TargEConfig;  /* 1Eh -> Target E configuration */
--      UCHAR NVM_TargFConfig;  /* 1Fh -> Target F configuration */
-+      u8 NVM_Targ0Config;     /* 10h -> Target 0 configuration */
-+      u8 NVM_Targ1Config;     /* 11h -> Target 1 configuration */
-+      u8 NVM_Targ2Config;     /* 12h -> Target 2 configuration */
-+      u8 NVM_Targ3Config;     /* 13h -> Target 3 configuration */
-+      u8 NVM_Targ4Config;     /* 14h -> Target 4 configuration */
-+      u8 NVM_Targ5Config;     /* 15h -> Target 5 configuration */
-+      u8 NVM_Targ6Config;     /* 16h -> Target 6 configuration */
-+      u8 NVM_Targ7Config;     /* 17h -> Target 7 configuration */
-+      u8 NVM_Targ8Config;     /* 18h -> Target 8 configuration */
-+      u8 NVM_Targ9Config;     /* 19h -> Target 9 configuration */
-+      u8 NVM_TargAConfig;     /* 1Ah -> Target A configuration */
-+      u8 NVM_TargBConfig;     /* 1Bh -> Target B configuration */
-+      u8 NVM_TargCConfig;     /* 1Ch -> Target C configuration */
-+      u8 NVM_TargDConfig;     /* 1Dh -> Target D configuration */
-+      u8 NVM_TargEConfig;     /* 1Eh -> Target E configuration */
-+      u8 NVM_TargFConfig;     /* 1Fh -> Target F configuration */
- } NVRAM_SCSI;
- typedef struct _NVRAM {
- /*----------header ---------------*/
--      USHORT NVM_Signature;   /* 0,1: Signature */
--      UCHAR NVM_Size;         /* 2:   Size of data structure */
--      UCHAR NVM_Revision;     /* 3:   Revision of data structure */
-+      u16 NVM_Signature;      /* 0,1: Signature */
-+      u8 NVM_Size;            /* 2:   Size of data structure */
-+      u8 NVM_Revision;        /* 3:   Revision of data structure */
-       /* ----Host Adapter Structure ---- */
--      UCHAR NVM_ModelByte0;   /* 4:   Model number (byte 0) */
--      UCHAR NVM_ModelByte1;   /* 5:   Model number (byte 1) */
--      UCHAR NVM_ModelInfo;    /* 6:   Model information         */
--      UCHAR NVM_NumOfCh;      /* 7:   Number of SCSI channel */
--      UCHAR NVM_BIOSConfig1;  /* 8:   BIOS configuration 1  */
--      UCHAR NVM_BIOSConfig2;  /* 9:   BIOS configuration 2  */
--      UCHAR NVM_HAConfig1;    /* A:   Hoat adapter configuration 1 */
--      UCHAR NVM_HAConfig2;    /* B:   Hoat adapter configuration 2 */
-+      u8 NVM_ModelByte0;      /* 4:   Model number (byte 0) */
-+      u8 NVM_ModelByte1;      /* 5:   Model number (byte 1) */
-+      u8 NVM_ModelInfo;       /* 6:   Model information         */
-+      u8 NVM_NumOfCh; /* 7:   Number of SCSI channel */
-+      u8 NVM_BIOSConfig1;     /* 8:   BIOS configuration 1  */
-+      u8 NVM_BIOSConfig2;     /* 9:   BIOS configuration 2  */
-+      u8 NVM_HAConfig1;       /* A:   Hoat adapter configuration 1 */
-+      u8 NVM_HAConfig2;       /* B:   Hoat adapter configuration 2 */
-       NVRAM_SCSI NVM_SCSIInfo[2];
--      UCHAR NVM_reserved[10];
-+      u8 NVM_reserved[10];
-       /* ---------- CheckSum ----------       */
--      USHORT NVM_CheckSum;    /* 0x3E, 0x3F: Checksum of NVRam        */
-+      u16 NVM_CheckSum;       /* 0x3E, 0x3F: Checksum of NVRam        */
- } NVRAM, *PNVRAM;
- /* Bios Configuration for nvram->BIOSConfig1                            */
-@@ -681,19 +641,6 @@
- #define DISC_ALLOW              0xC0  /* Disconnect is allowed        */
- #define SCSICMD_RequestSense    0x03
--typedef struct _HCSinfo {
--      ULONG base;
--      UCHAR vec;
--      UCHAR bios;             /* High byte of BIOS address */
--      USHORT BaseAndBios;     /* high byte: pHcsInfo->bios,low byte:pHcsInfo->base */
--} HCSINFO;
+-              pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+-              dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+-                      DMA_NONE : DMA_FROM_DEVICE;
 -
--#define TUL_RD(x,y)             (UCHAR)(inb(  (int)((ULONG)(x+y)) ))
--#define TUL_RDLONG(x,y)         (ULONG)(inl((int)((ULONG)(x+y)) ))
--#define TUL_WR(     adr,data)   outb( (UCHAR)(data), (int)(adr))
--#define TUL_WRSHORT(adr,data)   outw( (UWORD)(data), (int)(adr))
--#define TUL_WRLONG( adr,data)   outl( (ULONG)(data), (int)(adr))
+-              dma_addr = dma_map_page(device->dev, dest, offset, len, dir);
+-              tx->tx_set_dest(dma_addr, tx, 0);
 -
- #define SCSI_ABORT_SNOOZE 0
- #define SCSI_ABORT_SUCCESS 1
- #define SCSI_ABORT_PENDING 2
-diff -Nurb linux-2.6.22-570/drivers/scsi/ipr.c linux-2.6.22-590/drivers/scsi/ipr.c
---- linux-2.6.22-570/drivers/scsi/ipr.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/ipr.c        2008-01-02 13:56:37.000000000 -0500
-@@ -540,32 +540,6 @@
- }
- /**
-- * ipr_unmap_sglist - Unmap scatterlist if mapped
-- * @ioa_cfg:  ioa config struct
-- * @ipr_cmd:  ipr command struct
-- *
-- * Return value:
-- *    nothing
-- **/
--static void ipr_unmap_sglist(struct ipr_ioa_cfg *ioa_cfg,
--                           struct ipr_cmnd *ipr_cmd)
--{
--      struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
+-              async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+-      } else { /* run the memset synchronously */
+-              void *dest_buf;
+-              pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
 -
--      if (ipr_cmd->dma_use_sg) {
--              if (scsi_cmd->use_sg > 0) {
--                      pci_unmap_sg(ioa_cfg->pdev, scsi_cmd->request_buffer,
--                                   scsi_cmd->use_sg,
--                                   scsi_cmd->sc_data_direction);
--              } else {
--                      pci_unmap_single(ioa_cfg->pdev, ipr_cmd->dma_handle,
--                                       scsi_cmd->request_bufflen,
--                                       scsi_cmd->sc_data_direction);
+-              dest_buf = (void *) (((char *) page_address(dest)) + offset);
+-
+-              /* wait for any prerequisite operations */
+-              if (depend_tx) {
+-                      /* if ack is already set then we cannot be sure
+-                       * we are referring to the correct operation
+-                       */
+-                      BUG_ON(depend_tx->ack);
+-                      if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+-                              panic("%s: DMA_ERROR waiting for depend_tx\n",
+-                                      __FUNCTION__);
 -              }
+-
+-              memset(dest_buf, val, len);
+-
+-              async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
 -      }
+-
+-      return tx;
+-}
+-EXPORT_SYMBOL_GPL(async_memset);
+-
+-static int __init async_memset_init(void)
+-{
+-      return 0;
+-}
+-
+-static void __exit async_memset_exit(void)
+-{
+-      do { } while (0);
 -}
 -
+-module_init(async_memset_init);
+-module_exit(async_memset_exit);
+-
+-MODULE_AUTHOR("Intel Corporation");
+-MODULE_DESCRIPTION("asynchronous memset api");
+-MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/crypto/async_tx/async_tx.c linux-2.6.22-570/crypto/async_tx/async_tx.c
+--- linux-2.6.22-590/crypto/async_tx/async_tx.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/crypto/async_tx/async_tx.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,497 +0,0 @@
+-/*
+- * core routines for the asynchronous memory transfer/transform api
+- *
+- * Copyright Â© 2006, Intel Corporation.
+- *
+- *    Dan Williams <dan.j.williams@intel.com>
+- *
+- *    with architecture considerations by:
+- *    Neil Brown <neilb@suse.de>
+- *    Jeff Garzik <jeff@garzik.org>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- *
+- */
+-#include <linux/kernel.h>
+-#include <linux/async_tx.h>
+-
+-#ifdef CONFIG_DMA_ENGINE
+-static enum dma_state_client
+-dma_channel_add_remove(struct dma_client *client,
+-      struct dma_chan *chan, enum dma_state state);
+-
+-static struct dma_client async_tx_dma = {
+-      .event_callback = dma_channel_add_remove,
+-      /* .cap_mask == 0 defaults to all channels */
+-};
+-
 -/**
-  * ipr_mask_and_clear_interrupts - Mask all and clear specified interrupts
-  * @ioa_cfg:  ioa config struct
-  * @clr_ints:     interrupts to clear
-@@ -677,7 +651,7 @@
-       scsi_cmd->result |= (DID_ERROR << 16);
--      ipr_unmap_sglist(ioa_cfg, ipr_cmd);
-+      scsi_dma_unmap(ipr_cmd->scsi_cmd);
-       scsi_cmd->scsi_done(scsi_cmd);
-       list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
- }
-@@ -2465,6 +2439,7 @@
- /**
-  * ipr_read_trace - Dump the adapter trace
-  * @kobj:             kobject struct
-+ * @bin_attr:         bin_attribute struct
-  * @buf:              buffer
-  * @off:              offset
-  * @count:            buffer size
-@@ -2472,8 +2447,9 @@
-  * Return value:
-  *    number of bytes printed to buffer
-  **/
--static ssize_t ipr_read_trace(struct kobject *kobj, char *buf,
--                            loff_t off, size_t count)
-+static ssize_t ipr_read_trace(struct kobject *kobj,
-+                            struct bin_attribute *bin_attr,
-+                            char *buf, loff_t off, size_t count)
- {
-       struct class_device *cdev = container_of(kobj,struct class_device,kobj);
-       struct Scsi_Host *shost = class_to_shost(cdev);
-@@ -3166,6 +3142,7 @@
- /**
-  * ipr_read_dump - Dump the adapter
-  * @kobj:             kobject struct
-+ * @bin_attr:         bin_attribute struct
-  * @buf:              buffer
-  * @off:              offset
-  * @count:            buffer size
-@@ -3173,8 +3150,9 @@
-  * Return value:
-  *    number of bytes printed to buffer
-  **/
--static ssize_t ipr_read_dump(struct kobject *kobj, char *buf,
--                            loff_t off, size_t count)
-+static ssize_t ipr_read_dump(struct kobject *kobj,
-+                           struct bin_attribute *bin_attr,
-+                           char *buf, loff_t off, size_t count)
- {
-       struct class_device *cdev = container_of(kobj,struct class_device,kobj);
-       struct Scsi_Host *shost = class_to_shost(cdev);
-@@ -3327,6 +3305,7 @@
- /**
-  * ipr_write_dump - Setup dump state of adapter
-  * @kobj:             kobject struct
-+ * @bin_attr:         bin_attribute struct
-  * @buf:              buffer
-  * @off:              offset
-  * @count:            buffer size
-@@ -3334,8 +3313,9 @@
-  * Return value:
-  *    number of bytes printed to buffer
-  **/
--static ssize_t ipr_write_dump(struct kobject *kobj, char *buf,
--                            loff_t off, size_t count)
-+static ssize_t ipr_write_dump(struct kobject *kobj,
-+                            struct bin_attribute *bin_attr,
-+                            char *buf, loff_t off, size_t count)
- {
-       struct class_device *cdev = container_of(kobj,struct class_device,kobj);
-       struct Scsi_Host *shost = class_to_shost(cdev);
-@@ -4292,24 +4272,25 @@
- static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
-                          struct ipr_cmnd *ipr_cmd)
- {
--      int i;
--      struct scatterlist *sglist;
-+      int i, nseg;
-+      struct scatterlist *sg;
-       u32 length;
-       u32 ioadl_flags = 0;
-       struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
-       struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
-       struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl;
--      length = scsi_cmd->request_bufflen;
+- * dma_cap_mask_all - enable iteration over all operation types
+- */
+-static dma_cap_mask_t dma_cap_mask_all;
 -
--      if (length == 0)
-+      length = scsi_bufflen(scsi_cmd);
-+      if (!length)
-               return 0;
--      if (scsi_cmd->use_sg) {
--              ipr_cmd->dma_use_sg = pci_map_sg(ioa_cfg->pdev,
--                                               scsi_cmd->request_buffer,
--                                               scsi_cmd->use_sg,
--                                               scsi_cmd->sc_data_direction);
-+      nseg = scsi_dma_map(scsi_cmd);
-+      if (nseg < 0) {
-+              dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
-+              return -1;
-+      }
-+
-+      ipr_cmd->dma_use_sg = nseg;
-               if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
-                       ioadl_flags = IPR_IOADL_FLAGS_WRITE;
-@@ -4324,8 +4305,6 @@
-                               cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
-               }
--              sglist = scsi_cmd->request_buffer;
+-/**
+- * chan_ref_percpu - tracks channel allocations per core/opertion
+- */
+-struct chan_ref_percpu {
+-      struct dma_chan_ref *ref;
+-};
 -
-               if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) {
-                       ioadl = ioarcb->add_data.u.ioadl;
-                       ioarcb->write_ioadl_addr =
-@@ -4334,51 +4313,14 @@
-                       ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
-               }
--              for (i = 0; i < ipr_cmd->dma_use_sg; i++) {
-+      scsi_for_each_sg(scsi_cmd, sg, ipr_cmd->dma_use_sg, i) {
-                       ioadl[i].flags_and_data_len =
--                              cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i]));
--                      ioadl[i].address =
--                              cpu_to_be32(sg_dma_address(&sglist[i]));
-+                      cpu_to_be32(ioadl_flags | sg_dma_len(sg));
-+              ioadl[i].address = cpu_to_be32(sg_dma_address(sg));
-               }
--              if (likely(ipr_cmd->dma_use_sg)) {
--                      ioadl[i-1].flags_and_data_len |=
--                              cpu_to_be32(IPR_IOADL_FLAGS_LAST);
--                      return 0;
--              } else
--                      dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
--      } else {
--              if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
--                      ioadl_flags = IPR_IOADL_FLAGS_WRITE;
--                      ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
--                      ioarcb->write_data_transfer_length = cpu_to_be32(length);
--                      ioarcb->write_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc));
--              } else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) {
--                      ioadl_flags = IPR_IOADL_FLAGS_READ;
--                      ioarcb->read_data_transfer_length = cpu_to_be32(length);
--                      ioarcb->read_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc));
--              }
--
--              ipr_cmd->dma_handle = pci_map_single(ioa_cfg->pdev,
--                                                   scsi_cmd->request_buffer, length,
--                                                   scsi_cmd->sc_data_direction);
--
--              if (likely(!pci_dma_mapping_error(ipr_cmd->dma_handle))) {
--                      ioadl = ioarcb->add_data.u.ioadl;
--                      ioarcb->write_ioadl_addr =
--                              cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
--                                          offsetof(struct ipr_ioarcb, add_data));
--                      ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
--                      ipr_cmd->dma_use_sg = 1;
--                      ioadl[0].flags_and_data_len =
--                              cpu_to_be32(ioadl_flags | length | IPR_IOADL_FLAGS_LAST);
--                      ioadl[0].address = cpu_to_be32(ipr_cmd->dma_handle);
-+      ioadl[i-1].flags_and_data_len |= cpu_to_be32(IPR_IOADL_FLAGS_LAST);
-                       return 0;
--              } else
--                      dev_err(&ioa_cfg->pdev->dev, "pci_map_single failed!\n");
--      }
+-static int channel_table_initialized;
+-static struct chan_ref_percpu *channel_table[DMA_TX_TYPE_END];
 -
--      return -1;
- }
- /**
-@@ -4441,7 +4383,7 @@
-                       res->needs_sync_complete = 1;
-               res->in_erp = 0;
-       }
--      ipr_unmap_sglist(ioa_cfg, ipr_cmd);
-+      scsi_dma_unmap(ipr_cmd->scsi_cmd);
-       list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
-       scsi_cmd->scsi_done(scsi_cmd);
- }
-@@ -4819,7 +4761,7 @@
-               break;
-       }
--      ipr_unmap_sglist(ioa_cfg, ipr_cmd);
-+      scsi_dma_unmap(ipr_cmd->scsi_cmd);
-       list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
-       scsi_cmd->scsi_done(scsi_cmd);
- }
-@@ -4840,10 +4782,10 @@
-       struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
-       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
--      scsi_cmd->resid = be32_to_cpu(ipr_cmd->ioasa.residual_data_len);
-+      scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->ioasa.residual_data_len));
-       if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) {
--              ipr_unmap_sglist(ioa_cfg, ipr_cmd);
-+              scsi_dma_unmap(ipr_cmd->scsi_cmd);
-               list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
-               scsi_cmd->scsi_done(scsi_cmd);
-       } else
-diff -Nurb linux-2.6.22-570/drivers/scsi/ips.c linux-2.6.22-590/drivers/scsi/ips.c
---- linux-2.6.22-570/drivers/scsi/ips.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/ips.c        2008-01-02 13:56:37.000000000 -0500
-@@ -211,19 +211,6 @@
- #warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
- #endif
--#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
--#include <linux/blk.h>
--#include "sd.h"
--#define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
--#define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
--#ifndef __devexit_p
--#define __devexit_p(x) x
--#endif
--#else
--#define IPS_LOCK_SAVE(lock,flags) do{spin_lock(lock);(void)flags;}while(0)
--#define IPS_UNLOCK_RESTORE(lock,flags) do{spin_unlock(lock);(void)flags;}while(0)
--#endif
+-/**
+- * async_tx_lock - protect modification of async_tx_master_list and serialize
+- *    rebalance operations
+- */
+-static spinlock_t async_tx_lock;
 -
- #define IPS_DMA_DIR(scb) ((!scb->scsi_cmd || ips_is_passthru(scb->scsi_cmd) || \
-                          DMA_NONE == scb->scsi_cmd->sc_data_direction) ? \
-                          PCI_DMA_BIDIRECTIONAL : \
-@@ -381,24 +368,13 @@
-       .eh_abort_handler       = ips_eh_abort,
-       .eh_host_reset_handler  = ips_eh_reset,
-       .proc_name              = "ips",
--#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
-       .proc_info              = ips_proc_info,
-       .slave_configure        = ips_slave_configure,
--#else
--      .proc_info              = ips_proc24_info,
--      .select_queue_depths    = ips_select_queue_depth,
--#endif
-       .bios_param             = ips_biosparam,
-       .this_id                = -1,
-       .sg_tablesize           = IPS_MAX_SG,
-       .cmd_per_lun            = 3,
-       .use_clustering         = ENABLE_CLUSTERING,
--#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
--      .use_new_eh_code        = 1,
--#endif
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)  &&  LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
--    .highmem_io          = 1,   
--#endif
- };
-@@ -731,7 +707,7 @@
-       /* free IRQ */
-       free_irq(ha->irq, ha);
--      IPS_REMOVE_HOST(sh);
-+      scsi_remove_host(sh);
-       scsi_host_put(sh);
-       ips_released_controllers++;
-@@ -813,7 +789,6 @@
-       ips_ha_t *ha;
-       ips_copp_wait_item_t *item;
-       int ret;
--      unsigned long cpu_flags;
-       struct Scsi_Host *host;
-       METHOD_TRACE("ips_eh_abort", 1);
-@@ -830,7 +805,7 @@
-       if (!ha->active)
-               return (FAILED);
--      IPS_LOCK_SAVE(host->host_lock, cpu_flags);
-+      spin_lock(host->host_lock);
-       /* See if the command is on the copp queue */
-       item = ha->copp_waitlist.head;
-@@ -851,7 +826,7 @@
-               ret = (FAILED);
-       }
--      IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
-+      spin_unlock(host->host_lock);
-       return ret;
- }
-@@ -1129,7 +1104,7 @@
-               /* A Reset IOCTL is only sent by the boot CD in extreme cases.           */
-               /* There can never be any system activity ( network or disk ), but check */
-               /* anyway just as a good practice.                                       */
--              pt = (ips_passthru_t *) SC->request_buffer;
-+              pt = (ips_passthru_t *) scsi_sglist(SC);
-               if ((pt->CoppCP.cmd.reset.op_code == IPS_CMD_RESET_CHANNEL) &&
-                   (pt->CoppCP.cmd.reset.adapter_flag == 1)) {
-                       if (ha->scb_activelist.count != 0) {
-@@ -1176,18 +1151,10 @@
- /*   Set bios geometry for the controller                                   */
- /*                                                                          */
- /****************************************************************************/
--static int
--#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
--ips_biosparam(Disk * disk, kdev_t dev, int geom[])
+-static struct list_head
+-async_tx_master_list = LIST_HEAD_INIT(async_tx_master_list);
+-
+-/* async_tx_issue_pending_all - start all transactions on all channels */
+-void async_tx_issue_pending_all(void)
 -{
--      ips_ha_t *ha = (ips_ha_t *) disk->device->host->hostdata;
--      unsigned long capacity = disk->capacity;
--#else
--ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
-+static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
-             sector_t capacity, int geom[])
- {
-       ips_ha_t *ha = (ips_ha_t *) sdev->host->hostdata;
--#endif
-       int heads;
-       int sectors;
-       int cylinders;
-@@ -1225,70 +1192,6 @@
-       return (0);
- }
--#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+-      struct dma_chan_ref *ref;
 -
--/* ips_proc24_info is a wrapper around ips_proc_info *
-- * for compatibility with the 2.4 scsi parameters    */
--static int
--ips_proc24_info(char *buffer, char **start, off_t offset, int length,
--                            int hostno, int func)
+-      rcu_read_lock();
+-      list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+-              ref->chan->device->device_issue_pending(ref->chan);
+-      rcu_read_unlock();
+-}
+-EXPORT_SYMBOL_GPL(async_tx_issue_pending_all);
+-
+-/* dma_wait_for_async_tx - spin wait for a transcation to complete
+- * @tx: transaction to wait on
+- */
+-enum dma_status
+-dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
 -{
--      int i;
+-      enum dma_status status;
+-      struct dma_async_tx_descriptor *iter;
 -
--      for (i = 0; i < ips_next_controller; i++) {
--              if (ips_sh[i] && ips_sh[i]->host_no == hostno) {
--                      return ips_proc_info(ips_sh[i], buffer, start,
--                                           offset, length, func);
--              }
+-      if (!tx)
+-              return DMA_SUCCESS;
+-
+-      /* poll through the dependency chain, return when tx is complete */
+-      do {
+-              iter = tx;
+-              while (iter->cookie == -EBUSY)
+-                      iter = iter->parent;
+-
+-              status = dma_sync_wait(iter->chan, iter->cookie);
+-      } while (status == DMA_IN_PROGRESS || (iter != tx));
+-
+-      return status;
+-}
+-EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);
+-
+-/* async_tx_run_dependencies - helper routine for dma drivers to process
+- *    (start) dependent operations on their target channel
+- * @tx: transaction with dependencies
+- */
+-void
+-async_tx_run_dependencies(struct dma_async_tx_descriptor *tx)
+-{
+-      struct dma_async_tx_descriptor *dep_tx, *_dep_tx;
+-      struct dma_device *dev;
+-      struct dma_chan *chan;
+-
+-      list_for_each_entry_safe(dep_tx, _dep_tx, &tx->depend_list,
+-              depend_node) {
+-              chan = dep_tx->chan;
+-              dev = chan->device;
+-              /* we can't depend on ourselves */
+-              BUG_ON(chan == tx->chan);
+-              list_del(&dep_tx->depend_node);
+-              tx->tx_submit(dep_tx);
+-
+-              /* we need to poke the engine as client code does not
+-               * know about dependency submission events
+-               */
+-              dev->device_issue_pending(chan);
 -      }
--      return -EINVAL; 
 -}
+-EXPORT_SYMBOL_GPL(async_tx_run_dependencies);
 -
--/****************************************************************************/
--/*                                                                          */
--/* Routine Name: ips_select_queue_depth                                     */
--/*                                                                          */
--/* Routine Description:                                                     */
--/*                                                                          */
--/*   Select queue depths for the devices on the contoller                   */
--/*                                                                          */
--/****************************************************************************/
 -static void
--ips_select_queue_depth(struct Scsi_Host *host, struct scsi_device * scsi_devs)
+-free_dma_chan_ref(struct rcu_head *rcu)
 -{
--      struct scsi_device *device;
--      ips_ha_t *ha;
--      int count = 0;
--      int min;
+-      struct dma_chan_ref *ref;
+-      ref = container_of(rcu, struct dma_chan_ref, rcu);
+-      kfree(ref);
+-}
+-
+-static void
+-init_dma_chan_ref(struct dma_chan_ref *ref, struct dma_chan *chan)
+-{
+-      INIT_LIST_HEAD(&ref->node);
+-      INIT_RCU_HEAD(&ref->rcu);
+-      ref->chan = chan;
+-      atomic_set(&ref->count, 0);
+-}
 -
--      ha = IPS_HA(host);
--      min = ha->max_cmds / 4;
+-/**
+- * get_chan_ref_by_cap - returns the nth channel of the given capability
+- *    defaults to returning the channel with the desired capability and the
+- *    lowest reference count if the index can not be satisfied
+- * @cap: capability to match
+- * @index: nth channel desired, passing -1 has the effect of forcing the
+- *  default return value
+- */
+-static struct dma_chan_ref *
+-get_chan_ref_by_cap(enum dma_transaction_type cap, int index)
+-{
+-      struct dma_chan_ref *ret_ref = NULL, *min_ref = NULL, *ref;
 -
--      for (device = scsi_devs; device; device = device->next) {
--              if (device->host == host) {
--                      if ((device->channel == 0) && (device->type == 0))
--                              count++;
+-      rcu_read_lock();
+-      list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+-              if (dma_has_cap(cap, ref->chan->device->cap_mask)) {
+-                      if (!min_ref)
+-                              min_ref = ref;
+-                      else if (atomic_read(&ref->count) <
+-                              atomic_read(&min_ref->count))
+-                              min_ref = ref;
+-
+-                      if (index-- == 0) {
+-                              ret_ref = ref;
+-                              break;
+-                      }
 -              }
--      }
+-      rcu_read_unlock();
 -
--      for (device = scsi_devs; device; device = device->next) {
--              if (device->host == host) {
--                      if ((device->channel == 0) && (device->type == 0)) {
--                              device->queue_depth =
--                                  (ha->max_cmds - 1) / count;
--                              if (device->queue_depth < min)
--                                      device->queue_depth = min;
--                      } else {
--                              device->queue_depth = 2;
+-      if (!ret_ref)
+-              ret_ref = min_ref;
+-
+-      if (ret_ref)
+-              atomic_inc(&ret_ref->count);
+-
+-      return ret_ref;
+-}
+-
+-/**
+- * async_tx_rebalance - redistribute the available channels, optimize
+- * for cpu isolation in the SMP case, and opertaion isolation in the
+- * uniprocessor case
+- */
+-static void async_tx_rebalance(void)
+-{
+-      int cpu, cap, cpu_idx = 0;
+-      unsigned long flags;
+-
+-      if (!channel_table_initialized)
+-              return;
+-
+-      spin_lock_irqsave(&async_tx_lock, flags);
+-
+-      /* undo the last distribution */
+-      for_each_dma_cap_mask(cap, dma_cap_mask_all)
+-              for_each_possible_cpu(cpu) {
+-                      struct dma_chan_ref *ref =
+-                              per_cpu_ptr(channel_table[cap], cpu)->ref;
+-                      if (ref) {
+-                              atomic_set(&ref->count, 0);
+-                              per_cpu_ptr(channel_table[cap], cpu)->ref =
+-                                                                      NULL;
 -                      }
+-              }
 -
--                      if (device->queue_depth < 2)
--                              device->queue_depth = 2;
+-      for_each_dma_cap_mask(cap, dma_cap_mask_all)
+-              for_each_online_cpu(cpu) {
+-                      struct dma_chan_ref *new;
+-                      if (NR_CPUS > 1)
+-                              new = get_chan_ref_by_cap(cap, cpu_idx++);
+-                      else
+-                              new = get_chan_ref_by_cap(cap, -1);
+-
+-                      per_cpu_ptr(channel_table[cap], cpu)->ref = new;
 -              }
--      }
+-
+-      spin_unlock_irqrestore(&async_tx_lock, flags);
 -}
 -
--#else
- /****************************************************************************/
- /*                                                                          */
- /* Routine Name: ips_slave_configure                                        */
-@@ -1316,7 +1219,6 @@
-       SDptr->skip_ms_page_3f = 1;
-       return 0;
- }
--#endif
- /****************************************************************************/
- /*                                                                          */
-@@ -1331,7 +1233,6 @@
- do_ipsintr(int irq, void *dev_id)
- {
-       ips_ha_t *ha;
--      unsigned long cpu_flags;
-       struct Scsi_Host *host;
-       int irqstatus;
-@@ -1347,16 +1248,16 @@
-               return IRQ_HANDLED;
-       }
--      IPS_LOCK_SAVE(host->host_lock, cpu_flags);
-+      spin_lock(host->host_lock);
-       if (!ha->active) {
--              IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
-+              spin_unlock(host->host_lock);
-               return IRQ_HANDLED;
-       }
-       irqstatus = (*ha->func.intr) (ha);
--      IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
-+      spin_unlock(host->host_lock);
-       /* start the next command */
-       ips_next(ha, IPS_INTR_ON);
-@@ -1606,15 +1507,8 @@
-       if ((SC->cmnd[0] == IPS_IOCTL_COMMAND) &&
-           (SC->device->channel == 0) &&
-           (SC->device->id == IPS_ADAPTER_ID) &&
--          (SC->device->lun == 0) && SC->request_buffer) {
--              if ((!SC->use_sg) && SC->request_bufflen &&
--                  (((char *) SC->request_buffer)[0] == 'C') &&
--                  (((char *) SC->request_buffer)[1] == 'O') &&
--                  (((char *) SC->request_buffer)[2] == 'P') &&
--                  (((char *) SC->request_buffer)[3] == 'P'))
--                      return 1;
--              else if (SC->use_sg) {
--                      struct scatterlist *sg = SC->request_buffer;
-+          (SC->device->lun == 0) && scsi_sglist(SC)) {
-+                struct scatterlist *sg = scsi_sglist(SC);
-                       char  *buffer; 
-                       /* kmap_atomic() ensures addressability of the user buffer.*/
-@@ -1630,7 +1524,6 @@
-                       kunmap_atomic(buffer - sg->offset, KM_IRQ0);
-                       local_irq_restore(flags);
-               }
+-static enum dma_state_client
+-dma_channel_add_remove(struct dma_client *client,
+-      struct dma_chan *chan, enum dma_state state)
+-{
+-      unsigned long found, flags;
+-      struct dma_chan_ref *master_ref, *ref;
+-      enum dma_state_client ack = DMA_DUP; /* default: take no action */
+-
+-      switch (state) {
+-      case DMA_RESOURCE_AVAILABLE:
+-              found = 0;
+-              rcu_read_lock();
+-              list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+-                      if (ref->chan == chan) {
+-                              found = 1;
+-                              break;
+-                      }
+-              rcu_read_unlock();
+-
+-              pr_debug("async_tx: dma resource available [%s]\n",
+-                      found ? "old" : "new");
+-
+-              if (!found)
+-                      ack = DMA_ACK;
+-              else
+-                      break;
+-
+-              /* add the channel to the generic management list */
+-              master_ref = kmalloc(sizeof(*master_ref), GFP_KERNEL);
+-              if (master_ref) {
+-                      /* keep a reference until async_tx is unloaded */
+-                      dma_chan_get(chan);
+-                      init_dma_chan_ref(master_ref, chan);
+-                      spin_lock_irqsave(&async_tx_lock, flags);
+-                      list_add_tail_rcu(&master_ref->node,
+-                              &async_tx_master_list);
+-                      spin_unlock_irqrestore(&async_tx_lock,
+-                              flags);
+-              } else {
+-                      printk(KERN_WARNING "async_tx: unable to create"
+-                              " new master entry in response to"
+-                              " a DMA_RESOURCE_ADDED event"
+-                              " (-ENOMEM)\n");
+-                      return 0;
+-              }
+-
+-              async_tx_rebalance();
+-              break;
+-      case DMA_RESOURCE_REMOVED:
+-              found = 0;
+-              spin_lock_irqsave(&async_tx_lock, flags);
+-              list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+-                      if (ref->chan == chan) {
+-                              /* permit backing devices to go away */
+-                              dma_chan_put(ref->chan);
+-                              list_del_rcu(&ref->node);
+-                              call_rcu(&ref->rcu, free_dma_chan_ref);
+-                              found = 1;
+-                              break;
+-                      }
+-              spin_unlock_irqrestore(&async_tx_lock, flags);
+-
+-              pr_debug("async_tx: dma resource removed [%s]\n",
+-                      found ? "ours" : "not ours");
+-
+-              if (found)
+-                      ack = DMA_ACK;
+-              else
+-                      break;
+-
+-              async_tx_rebalance();
+-              break;
+-      case DMA_RESOURCE_SUSPEND:
+-      case DMA_RESOURCE_RESUME:
+-              printk(KERN_WARNING "async_tx: does not support dma channel"
+-                      " suspend/resume\n");
+-              break;
+-      default:
+-              BUG();
 -      }
-       return 0;
- }
-@@ -1680,18 +1573,14 @@
- {
-       ips_passthru_t *pt;
-       int length = 0;
--      int ret;
-+      int i, ret;
-+        struct scatterlist *sg = scsi_sglist(SC);
-       METHOD_TRACE("ips_make_passthru", 1);
--      if (!SC->use_sg) {
--              length = SC->request_bufflen;
--      } else {
--              struct scatterlist *sg = SC->request_buffer;
--              int i;
--              for (i = 0; i < SC->use_sg; i++)
-+        scsi_for_each_sg(SC, sg, scsi_sg_count(SC), i)
-                       length += sg[i].length;
+-
+-      return ack;
+-}
+-
+-static int __init
+-async_tx_init(void)
+-{
+-      enum dma_transaction_type cap;
+-
+-      spin_lock_init(&async_tx_lock);
+-      bitmap_fill(dma_cap_mask_all.bits, DMA_TX_TYPE_END);
+-
+-      /* an interrupt will never be an explicit operation type.
+-       * clearing this bit prevents allocation to a slot in 'channel_table'
+-       */
+-      clear_bit(DMA_INTERRUPT, dma_cap_mask_all.bits);
+-
+-      for_each_dma_cap_mask(cap, dma_cap_mask_all) {
+-              channel_table[cap] = alloc_percpu(struct chan_ref_percpu);
+-              if (!channel_table[cap])
+-                      goto err;
 -      }
-+
-       if (length < sizeof (ips_passthru_t)) {
-               /* wrong size */
-               DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
-@@ -2115,7 +2004,7 @@
-       METHOD_TRACE("ips_cleanup_passthru", 1);
--      if ((!scb) || (!scb->scsi_cmd) || (!scb->scsi_cmd->request_buffer)) {
-+      if ((!scb) || (!scb->scsi_cmd) || (!scsi_sglist(scb->scsi_cmd))) {
-               DEBUG_VAR(1, "(%s%d) couldn't cleanup after passthru",
-                         ips_name, ha->host_num);
-@@ -2730,7 +2619,6 @@
-       struct scsi_cmnd *q;
-       ips_copp_wait_item_t *item;
-       int ret;
--      unsigned long cpu_flags = 0;
-       struct Scsi_Host *host;
-       METHOD_TRACE("ips_next", 1);
-@@ -2742,7 +2630,7 @@
-        * this command won't time out
-        */
-       if (intr == IPS_INTR_ON)
--              IPS_LOCK_SAVE(host->host_lock, cpu_flags);
-+              spin_lock(host->host_lock);
-       if ((ha->subsys->param[3] & 0x300000)
-           && (ha->scb_activelist.count == 0)) {
-@@ -2769,14 +2657,14 @@
-               item = ips_removeq_copp_head(&ha->copp_waitlist);
-               ha->num_ioctl++;
-               if (intr == IPS_INTR_ON)
--                      IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
-+                      spin_unlock(host->host_lock);
-               scb->scsi_cmd = item->scsi_cmd;
-               kfree(item);
-               ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr);
-               if (intr == IPS_INTR_ON)
--                      IPS_LOCK_SAVE(host->host_lock, cpu_flags);
-+                      spin_lock(host->host_lock);
-               switch (ret) {
-               case IPS_FAILURE:
-                       if (scb->scsi_cmd) {
-@@ -2846,7 +2734,7 @@
-               SC = ips_removeq_wait(&ha->scb_waitlist, q);
-               if (intr == IPS_INTR_ON)
--                      IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); /* Unlock HA after command is taken off queue */
-+                      spin_unlock(host->host_lock);   /* Unlock HA after command is taken off queue */
-               SC->result = DID_OK;
-               SC->host_scribble = NULL;
-@@ -2866,43 +2754,28 @@
-               /* copy in the CDB */
-               memcpy(scb->cdb, SC->cmnd, SC->cmd_len);
--              /* Now handle the data buffer */
--              if (SC->use_sg) {
-+                scb->sg_count = scsi_dma_map(SC);
-+                BUG_ON(scb->sg_count < 0);
-+              if (scb->sg_count) {
-                       struct scatterlist *sg;
-                       int i;
--                      sg = SC->request_buffer;
--                      scb->sg_count = pci_map_sg(ha->pcidev, sg, SC->use_sg,
--                                                 SC->sc_data_direction);
-                       scb->flags |= IPS_SCB_MAP_SG;
--                      for (i = 0; i < scb->sg_count; i++) {
-+
-+                        scsi_for_each_sg(SC, sg, scb->sg_count, i) {
-                               if (ips_fill_scb_sg_single
--                                  (ha, sg_dma_address(&sg[i]), scb, i,
--                                   sg_dma_len(&sg[i])) < 0)
-+                                  (ha, sg_dma_address(sg), scb, i,
-+                                   sg_dma_len(sg)) < 0)
-                                       break;
-                       }
-                       scb->dcdb.transfer_length = scb->data_len;
-               } else {
--                      if (SC->request_bufflen) {
--                              scb->data_busaddr =
--                                  pci_map_single(ha->pcidev,
--                                                 SC->request_buffer,
--                                                 SC->request_bufflen,
--                                                 SC->sc_data_direction);
--                              scb->flags |= IPS_SCB_MAP_SINGLE;
--                              ips_fill_scb_sg_single(ha, scb->data_busaddr,
--                                                     scb, 0,
--                                                     SC->request_bufflen);
--                              scb->dcdb.transfer_length = scb->data_len;
--                      } else {
-                               scb->data_busaddr = 0L;
-                               scb->sg_len = 0;
-                               scb->data_len = 0;
-                               scb->dcdb.transfer_length = 0;
-                       }
--              }
 -
-               scb->dcdb.cmd_attribute =
-                   ips_command_direction[scb->scsi_cmd->cmnd[0]];
-@@ -2919,7 +2792,7 @@
-                       scb->dcdb.transfer_length = 0;
-               }
-               if (intr == IPS_INTR_ON)
--                      IPS_LOCK_SAVE(host->host_lock, cpu_flags);
-+                      spin_lock(host->host_lock);
-               ret = ips_send_cmd(ha, scb);
-@@ -2958,7 +2831,7 @@
-       }                       /* end while */
-       if (intr == IPS_INTR_ON)
--              IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
-+              spin_unlock(host->host_lock);
- }
- /****************************************************************************/
-@@ -3377,29 +3250,24 @@
-                * the rest of the data and continue.
-                */
-               if ((scb->breakup) || (scb->sg_break)) {
-+                        struct scatterlist *sg;
-+                        int sg_dma_index, ips_sg_index = 0;
-+
-                       /* we had a data breakup */
-                       scb->data_len = 0;
--                      if (scb->sg_count) {
--                              /* S/G request */
--                              struct scatterlist *sg;
--                              int ips_sg_index = 0;
--                              int sg_dma_index;
+-      channel_table_initialized = 1;
+-      dma_async_client_register(&async_tx_dma);
+-      dma_async_client_chan_request(&async_tx_dma);
 -
--                              sg = scb->scsi_cmd->request_buffer;
-+                        sg = scsi_sglist(scb->scsi_cmd);
-                               /* Spin forward to last dma chunk */
-                               sg_dma_index = scb->breakup;
-                               /* Take care of possible partial on last chunk */
-                               ips_fill_scb_sg_single(ha,
--                                                     sg_dma_address(&sg
--                                                                    [sg_dma_index]),
-+                                               sg_dma_address(&sg[sg_dma_index]),
-                                                      scb, ips_sg_index++,
--                                                     sg_dma_len(&sg
--                                                                [sg_dma_index]));
-+                                               sg_dma_len(&sg[sg_dma_index]));
--                              for (; sg_dma_index < scb->sg_count;
-+                        for (; sg_dma_index < scsi_sg_count(scb->scsi_cmd);
-                                    sg_dma_index++) {
-                                       if (ips_fill_scb_sg_single
-                                           (ha,
-@@ -3407,21 +3275,6 @@
-                                            scb, ips_sg_index++,
-                                            sg_dma_len(&sg[sg_dma_index])) < 0)
-                                               break;
+-      printk(KERN_INFO "async_tx: api initialized (async)\n");
+-
+-      return 0;
+-err:
+-      printk(KERN_ERR "async_tx: initialization failure\n");
+-
+-      while (--cap >= 0)
+-              free_percpu(channel_table[cap]);
+-
+-      return 1;
+-}
+-
+-static void __exit async_tx_exit(void)
+-{
+-      enum dma_transaction_type cap;
+-
+-      channel_table_initialized = 0;
+-
+-      for_each_dma_cap_mask(cap, dma_cap_mask_all)
+-              if (channel_table[cap])
+-                      free_percpu(channel_table[cap]);
+-
+-      dma_async_client_unregister(&async_tx_dma);
+-}
+-
+-/**
+- * async_tx_find_channel - find a channel to carry out the operation or let
+- *    the transaction execute synchronously
+- * @depend_tx: transaction dependency
+- * @tx_type: transaction type
+- */
+-struct dma_chan *
+-async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+-      enum dma_transaction_type tx_type)
+-{
+-      /* see if we can keep the chain on one channel */
+-      if (depend_tx &&
+-              dma_has_cap(tx_type, depend_tx->chan->device->cap_mask))
+-              return depend_tx->chan;
+-      else if (likely(channel_table_initialized)) {
+-              struct dma_chan_ref *ref;
+-              int cpu = get_cpu();
+-              ref = per_cpu_ptr(channel_table[tx_type], cpu)->ref;
+-              put_cpu();
+-              return ref ? ref->chan : NULL;
+-      } else
+-              return NULL;
+-}
+-EXPORT_SYMBOL_GPL(async_tx_find_channel);
+-#else
+-static int __init async_tx_init(void)
+-{
+-      printk(KERN_INFO "async_tx: api initialized (sync-only)\n");
+-      return 0;
+-}
 -
--                              }
+-static void __exit async_tx_exit(void)
+-{
+-      do { } while (0);
+-}
+-#endif
 -
--                      } else {
--                              /* Non S/G Request */
--                              (void) ips_fill_scb_sg_single(ha,
--                                                            scb->
--                                                            data_busaddr +
--                                                            (scb->sg_break *
--                                                             ha->max_xfer),
--                                                            scb, 0,
--                                                            scb->scsi_cmd->
--                                                            request_bufflen -
--                                                            (scb->sg_break *
--                                                             ha->max_xfer));
-                       }
-                       scb->dcdb.transfer_length = scb->data_len;
-@@ -3653,15 +3506,15 @@
- static void
- ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
- {
--      if (scmd->use_sg) {
-               int i;
-               unsigned int min_cnt, xfer_cnt;
-               char *cdata = (char *) data;
-               unsigned char *buffer;
-               unsigned long flags;
--              struct scatterlist *sg = scmd->request_buffer;
-+        struct scatterlist *sg = scsi_sglist(scmd);
-+
-               for (i = 0, xfer_cnt = 0;
--                   (i < scmd->use_sg) && (xfer_cnt < count); i++) {
-+             (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
-                       min_cnt = min(count - xfer_cnt, sg[i].length);
-                       /* kmap_atomic() ensures addressability of the data buffer.*/
-@@ -3674,11 +3527,6 @@
-                       xfer_cnt += min_cnt;
-               }
+-void
+-async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
+-      enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_param)
+-{
+-      tx->callback = cb_fn;
+-      tx->callback_param = cb_param;
 -
--      } else {
--              unsigned int min_cnt = min(count, scmd->request_bufflen);
--              memcpy(scmd->request_buffer, data, min_cnt);
--      }
- }
- /****************************************************************************/
-@@ -3691,15 +3539,15 @@
- static void
- ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
- {
--      if (scmd->use_sg) {
-               int i;
-               unsigned int min_cnt, xfer_cnt;
-               char *cdata = (char *) data;
-               unsigned char *buffer;
-               unsigned long flags;
--              struct scatterlist *sg = scmd->request_buffer;
-+        struct scatterlist *sg = scsi_sglist(scmd);
-+
-               for (i = 0, xfer_cnt = 0;
--                   (i < scmd->use_sg) && (xfer_cnt < count); i++) {
-+             (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
-                       min_cnt = min(count - xfer_cnt, sg[i].length);
-                       /* kmap_atomic() ensures addressability of the data buffer.*/
-@@ -3712,11 +3560,6 @@
-                       xfer_cnt += min_cnt;
-               }
+-      /* set this new tx to run after depend_tx if:
+-       * 1/ a dependency exists (depend_tx is !NULL)
+-       * 2/ the tx can not be submitted to the current channel
+-       */
+-      if (depend_tx && depend_tx->chan != chan) {
+-              /* if ack is already set then we cannot be sure
+-               * we are referring to the correct operation
+-               */
+-              BUG_ON(depend_tx->ack);
+-
+-              tx->parent = depend_tx;
+-              spin_lock_bh(&depend_tx->lock);
+-              list_add_tail(&tx->depend_node, &depend_tx->depend_list);
+-              if (depend_tx->cookie == 0) {
+-                      struct dma_chan *dep_chan = depend_tx->chan;
+-                      struct dma_device *dep_dev = dep_chan->device;
+-                      dep_dev->device_dependency_added(dep_chan);
+-              }
+-              spin_unlock_bh(&depend_tx->lock);
 -
+-              /* schedule an interrupt to trigger the channel switch */
+-              async_trigger_callback(ASYNC_TX_ACK, depend_tx, NULL, NULL);
 -      } else {
--              unsigned int min_cnt = min(count, scmd->request_bufflen);
--              memcpy(data, scmd->request_buffer, min_cnt);
+-              tx->parent = NULL;
+-              tx->tx_submit(tx);
 -      }
- }
- /****************************************************************************/
-@@ -4350,7 +4193,7 @@
-       METHOD_TRACE("ips_rdcap", 1);
--      if (scb->scsi_cmd->request_bufflen < 8)
-+      if (scsi_bufflen(scb->scsi_cmd) < 8)
-               return (0);
-       cap.lba =
-@@ -4735,8 +4578,7 @@
-       METHOD_TRACE("ips_freescb", 1);
-       if (scb->flags & IPS_SCB_MAP_SG)
--              pci_unmap_sg(ha->pcidev, scb->scsi_cmd->request_buffer,
--                           scb->scsi_cmd->use_sg, IPS_DMA_DIR(scb));
-+                scsi_dma_unmap(scb->scsi_cmd);
-       else if (scb->flags & IPS_SCB_MAP_SINGLE)
-               pci_unmap_single(ha->pcidev, scb->data_busaddr, scb->data_len,
-                                IPS_DMA_DIR(scb));
-@@ -7004,7 +6846,6 @@
-       kfree(oldha);
-       ips_sh[index] = sh;
-       ips_ha[index] = ha;
--      IPS_SCSI_SET_DEVICE(sh, ha);
-       /* Store away needed values for later use */
-       sh->io_port = ha->io_addr;
-@@ -7016,17 +6857,16 @@
-       sh->cmd_per_lun = sh->hostt->cmd_per_lun;
-       sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
-       sh->use_clustering = sh->hostt->use_clustering;
 -
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
-       sh->max_sectors = 128;
--#endif
-       sh->max_id = ha->ntargets;
-       sh->max_lun = ha->nlun;
-       sh->max_channel = ha->nbus - 1;
-       sh->can_queue = ha->max_cmds - 1;
--      IPS_ADD_HOST(sh, NULL);
-+      scsi_add_host(sh, NULL);
-+      scsi_scan_host(sh);
-+
-       return 0;
- }
-@@ -7069,7 +6909,7 @@
-               return -ENODEV;
-       ips_driver_template.module = THIS_MODULE;
-       ips_order_controllers();
--      if (IPS_REGISTER_HOSTS(&ips_driver_template)) {
-+      if (!ips_detect(&ips_driver_template)) {
-               pci_unregister_driver(&ips_pci_driver);
-               return -ENODEV;
-       }
-@@ -7087,7 +6927,6 @@
- static void __exit
- ips_module_exit(void)
- {
--      IPS_UNREGISTER_HOSTS(&ips_driver_template);
-       pci_unregister_driver(&ips_pci_driver);
-       unregister_reboot_notifier(&ips_notifier);
- }
-@@ -7443,15 +7282,9 @@
-       return SUCCESS;
- }
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
- MODULE_LICENSE("GPL");
--#endif
+-      if (flags & ASYNC_TX_ACK)
+-              async_tx_ack(tx);
 -
- MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING);
+-      if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
+-              async_tx_ack(depend_tx);
+-}
+-EXPORT_SYMBOL_GPL(async_tx_submit);
 -
--#ifdef MODULE_VERSION
- MODULE_VERSION(IPS_VER_STRING);
--#endif
- /*
-diff -Nurb linux-2.6.22-570/drivers/scsi/ips.h linux-2.6.22-590/drivers/scsi/ips.h
---- linux-2.6.22-570/drivers/scsi/ips.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/ips.h        2008-01-02 13:56:37.000000000 -0500
-@@ -58,10 +58,6 @@
-    /*
-     * Some handy macros
-     */
--   #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) || defined CONFIG_HIGHIO
--      #define IPS_HIGHIO
--   #endif
+-/**
+- * async_trigger_callback - schedules the callback function to be run after
+- * any dependent operations have been completed.
+- * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+- * @depend_tx: 'callback' requires the completion of this transaction
+- * @cb_fn: function to call after depend_tx completes
+- * @cb_param: parameter to pass to the callback routine
+- */
+-struct dma_async_tx_descriptor *
+-async_trigger_callback(enum async_tx_flags flags,
+-      struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_param)
+-{
+-      struct dma_chan *chan;
+-      struct dma_device *device;
+-      struct dma_async_tx_descriptor *tx;
 -
-    #define IPS_HA(x)                   ((ips_ha_t *) x->hostdata)
-    #define IPS_COMMAND_ID(ha, scb)     (int) (scb - ha->scbs)
-    #define IPS_IS_TROMBONE(ha)         (((ha->device_id == IPS_DEVICEID_COPPERHEAD) && \
-@@ -84,38 +80,8 @@
-     #define IPS_SGLIST_SIZE(ha)       (IPS_USE_ENH_SGLIST(ha) ? \
-                                          sizeof(IPS_ENH_SG_LIST) : sizeof(IPS_STD_SG_LIST))
--   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
--      #define pci_set_dma_mask(dev,mask) ( mask > 0xffffffff ? 1:0 )
--      #define scsi_set_pci_device(sh,dev) (0)
--   #endif
--
--   #ifndef IRQ_NONE
--      typedef void irqreturn_t;
--      #define IRQ_NONE
--      #define IRQ_HANDLED
--      #define IRQ_RETVAL(x)
--   #endif
--   
--   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
--      #define IPS_REGISTER_HOSTS(SHT)      scsi_register_module(MODULE_SCSI_HA,SHT)
--      #define IPS_UNREGISTER_HOSTS(SHT)    scsi_unregister_module(MODULE_SCSI_HA,SHT)
--      #define IPS_ADD_HOST(shost,device)
--      #define IPS_REMOVE_HOST(shost)
--      #define IPS_SCSI_SET_DEVICE(sh,ha)   scsi_set_pci_device(sh, (ha)->pcidev)
--      #define IPS_PRINTK(level, pcidev, format, arg...)                 \
--            printk(level "%s %s:" format , "ips" ,     \
--            (pcidev)->slot_name , ## arg)
--      #define scsi_host_alloc(sh,size)         scsi_register(sh,size)
--      #define scsi_host_put(sh)             scsi_unregister(sh)
--   #else
--      #define IPS_REGISTER_HOSTS(SHT)      (!ips_detect(SHT))
--      #define IPS_UNREGISTER_HOSTS(SHT)
--      #define IPS_ADD_HOST(shost,device)   do { scsi_add_host(shost,device); scsi_scan_host(shost); } while (0)
--      #define IPS_REMOVE_HOST(shost)       scsi_remove_host(shost)
--      #define IPS_SCSI_SET_DEVICE(sh,ha)   do { } while (0)
-       #define IPS_PRINTK(level, pcidev, format, arg...)                 \
-             dev_printk(level , &((pcidev)->dev) , format , ## arg)
--   #endif
-    #define MDELAY(n)                  \
-       do {                            \
-@@ -134,7 +100,7 @@
-    #define pci_dma_hi32(a)         ((a >> 16) >> 16)
-    #define pci_dma_lo32(a)         (a & 0xffffffff)
--   #if (BITS_PER_LONG > 32) || (defined CONFIG_HIGHMEM64G && defined IPS_HIGHIO)
-+   #if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
-       #define IPS_ENABLE_DMA64        (1)
-    #else
-       #define IPS_ENABLE_DMA64        (0)
-@@ -451,16 +417,10 @@
-    /*
-     * Scsi_Host Template
-     */
--#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
--   static int ips_proc24_info(char *, char **, off_t, int, int, int);
--   static void ips_select_queue_depth(struct Scsi_Host *, struct scsi_device *);
--   static int ips_biosparam(Disk *disk, kdev_t dev, int geom[]);
--#else
-    static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
-    static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
-               sector_t capacity, int geom[]);
-    static int ips_slave_configure(struct scsi_device *SDptr);
--#endif
- /*
-  * Raid Command Formats
-diff -Nurb linux-2.6.22-570/drivers/scsi/iscsi_tcp.c linux-2.6.22-590/drivers/scsi/iscsi_tcp.c
---- linux-2.6.22-570/drivers/scsi/iscsi_tcp.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/iscsi_tcp.c  2008-01-02 13:56:37.000000000 -0500
-@@ -29,14 +29,15 @@
- #include <linux/types.h>
- #include <linux/list.h>
- #include <linux/inet.h>
-+#include <linux/file.h>
- #include <linux/blkdev.h>
- #include <linux/crypto.h>
- #include <linux/delay.h>
- #include <linux/kfifo.h>
- #include <linux/scatterlist.h>
--#include <linux/mutex.h>
- #include <net/tcp.h>
- #include <scsi/scsi_cmnd.h>
-+#include <scsi/scsi_device.h>
- #include <scsi/scsi_host.h>
- #include <scsi/scsi.h>
- #include <scsi/scsi_transport_iscsi.h>
-@@ -109,7 +110,7 @@
-       struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-       crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc);
--      buf->sg.length = tcp_conn->hdr_size;
-+      buf->sg.length += sizeof(u32);
- }
- static inline int
-@@ -211,16 +212,14 @@
- static int
- iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
- {
--      int rc;
-       struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-       struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
-       struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
-       struct iscsi_session *session = conn->session;
-+      struct scsi_cmnd *sc = ctask->sc;
-       int datasn = be32_to_cpu(rhdr->datasn);
--      rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
--      if (rc)
--              return rc;
-+      iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
-       /*
-        * setup Data-In byte counter (gets decremented..)
-        */
-@@ -229,31 +228,36 @@
-       if (tcp_conn->in.datalen == 0)
-               return 0;
--      if (ctask->datasn != datasn)
-+      if (tcp_ctask->exp_datasn != datasn) {
-+              debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->datasn(%d)\n",
-+                        __FUNCTION__, tcp_ctask->exp_datasn, datasn);
-               return ISCSI_ERR_DATASN;
-+      }
--      ctask->datasn++;
-+      tcp_ctask->exp_datasn++;
-       tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
--      if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length)
-+      if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {
-+              debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
-+                        __FUNCTION__, tcp_ctask->data_offset,
-+                        tcp_conn->in.datalen, scsi_bufflen(sc));
-               return ISCSI_ERR_DATA_OFFSET;
-+      }
-       if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) {
--              struct scsi_cmnd *sc = ctask->sc;
+-      if (depend_tx) {
+-              chan = depend_tx->chan;
+-              device = chan->device;
 -
-               conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
-               if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
-                       int res_count = be32_to_cpu(rhdr->residual_count);
-                       if (res_count > 0 &&
--                          res_count <= sc->request_bufflen) {
--                              sc->resid = res_count;
-+                          res_count <= scsi_bufflen(sc)) {
-+                              scsi_set_resid(sc, res_count);
-                               sc->result = (DID_OK << 16) | rhdr->cmd_status;
-                       } else
-                               sc->result = (DID_BAD_TARGET << 16) |
-                                       rhdr->cmd_status;
-               } else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) {
--                      sc->resid = be32_to_cpu(rhdr->residual_count);
-+                      scsi_set_resid(sc, be32_to_cpu(rhdr->residual_count));
-                       sc->result = (DID_OK << 16) | rhdr->cmd_status;
-               } else
-                       sc->result = (DID_OK << 16) | rhdr->cmd_status;
-@@ -281,6 +285,8 @@
- {
-       struct iscsi_data *hdr;
-       struct scsi_cmnd *sc = ctask->sc;
-+      int i, sg_count = 0;
-+      struct scatterlist *sg;
-       hdr = &r2t->dtask.hdr;
-       memset(hdr, 0, sizeof(struct iscsi_data));
-@@ -308,12 +314,9 @@
-       iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr,
-                          sizeof(struct iscsi_hdr));
--      if (sc->use_sg) {
--              int i, sg_count = 0;
--              struct scatterlist *sg = sc->request_buffer;
+-              /* see if we can schedule an interrupt
+-               * otherwise poll for completion
+-               */
+-              if (device && !dma_has_cap(DMA_INTERRUPT, device->cap_mask))
+-                      device = NULL;
 -
-+      sg = scsi_sglist(sc);
-               r2t->sg = NULL;
--              for (i = 0; i < sc->use_sg; i++, sg += 1) {
-+      for (i = 0; i < scsi_sg_count(sc); i++, sg += 1) {
-                       /* FIXME: prefetch ? */
-                       if (sg_count + sg->length > r2t->data_offset) {
-                               int page_offset;
-@@ -335,12 +338,6 @@
-                       sg_count += sg->length;
-               }
-               BUG_ON(r2t->sg == NULL);
+-              tx = device ? device->device_prep_dma_interrupt(chan) : NULL;
+-      } else
+-              tx = NULL;
+-
+-      if (tx) {
+-              pr_debug("%s: (async)\n", __FUNCTION__);
+-
+-              async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
 -      } else {
--              iscsi_buf_init_iov(&r2t->sendbuf,
--                          (char*)sc->request_buffer + r2t->data_offset,
--                          r2t->data_count);
--              r2t->sg = NULL;
+-              pr_debug("%s: (sync)\n", __FUNCTION__);
+-
+-              /* wait for any prerequisite operations */
+-              if (depend_tx) {
+-                      /* if ack is already set then we cannot be sure
+-                       * we are referring to the correct operation
+-                       */
+-                      BUG_ON(depend_tx->ack);
+-                      if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+-                              panic("%s: DMA_ERROR waiting for depend_tx\n",
+-                                      __FUNCTION__);
+-              }
+-
+-              async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
 -      }
- }
- /**
-@@ -365,17 +362,16 @@
-               return ISCSI_ERR_DATALEN;
-       }
--      if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn)
-+      if (tcp_ctask->exp_datasn != r2tsn){
-+              debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
-+                        __FUNCTION__, tcp_ctask->exp_datasn, r2tsn);
-               return ISCSI_ERR_R2TSN;
 -
--      rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
--      if (rc)
--              return rc;
+-      return tx;
+-}
+-EXPORT_SYMBOL_GPL(async_trigger_callback);
 -
--      /* FIXME: use R2TSN to detect missing R2T */
-+      }
-       /* fill-in new R2T associated with the task */
-       spin_lock(&session->lock);
-+      iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
-+
-       if (!ctask->sc || ctask->mtask ||
-            session->state != ISCSI_STATE_LOGGED_IN) {
-               printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "
-@@ -401,11 +397,11 @@
-                           r2t->data_length, session->max_burst);
-       r2t->data_offset = be32_to_cpu(rhdr->data_offset);
--      if (r2t->data_offset + r2t->data_length > ctask->total_length) {
-+      if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) {
-               spin_unlock(&session->lock);
-               printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at "
-                      "offset %u and total length %d\n", r2t->data_length,
--                     r2t->data_offset, ctask->total_length);
-+                     r2t->data_offset, scsi_bufflen(ctask->sc));
-               return ISCSI_ERR_DATALEN;
-       }
-@@ -414,9 +410,9 @@
-       iscsi_solicit_data_init(conn, ctask, r2t);
--      tcp_ctask->exp_r2tsn = r2tsn + 1;
-+      tcp_ctask->exp_datasn = r2tsn + 1;
-       __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
--      tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
-+      tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT;
-       list_move_tail(&ctask->running, &conn->xmitqueue);
-       scsi_queue_work(session->host, &conn->xmitwork);
-@@ -600,7 +596,7 @@
- {
-       struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
-       int buf_left = buf_size - (tcp_conn->data_copied + offset);
--      int size = min(tcp_conn->in.copy, buf_left);
-+      unsigned size = min(tcp_conn->in.copy, buf_left);
-       int rc;
-       size = min(size, ctask->data_count);
-@@ -609,7 +605,7 @@
-              size, tcp_conn->in.offset, tcp_conn->in.copied);
-       BUG_ON(size <= 0);
--      BUG_ON(tcp_ctask->sent + size > ctask->total_length);
-+      BUG_ON(tcp_ctask->sent + size > scsi_bufflen(ctask->sc));
-       rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
-                          (char*)buf + (offset + tcp_conn->data_copied), size);
-@@ -707,25 +703,8 @@
-       BUG_ON((void*)ctask != sc->SCp.ptr);
--      /*
--       * copying Data-In into the Scsi_Cmnd
--       */
--      if (!sc->use_sg) {
--              i = ctask->data_count;
--              rc = iscsi_ctask_copy(tcp_conn, ctask, sc->request_buffer,
--                                    sc->request_bufflen,
--                                    tcp_ctask->data_offset);
--              if (rc == -EAGAIN)
--                      return rc;
--              if (conn->datadgst_en)
--                      iscsi_recv_digest_update(tcp_conn, sc->request_buffer,
--                                               i);
--              rc = 0;
--              goto done;
+-module_init(async_tx_init);
+-module_exit(async_tx_exit);
+-
+-MODULE_AUTHOR("Intel Corporation");
+-MODULE_DESCRIPTION("Asynchronous Bulk Memory Transactions API");
+-MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/crypto/async_tx/async_xor.c linux-2.6.22-570/crypto/async_tx/async_xor.c
+--- linux-2.6.22-590/crypto/async_tx/async_xor.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/crypto/async_tx/async_xor.c       1969-12-31 19:00:00.000000000 -0500
+@@ -1,327 +0,0 @@
+-/*
+- * xor offload engine api
+- *
+- * Copyright Â© 2006, Intel Corporation.
+- *
+- *      Dan Williams <dan.j.williams@intel.com>
+- *
+- *      with architecture considerations by:
+- *      Neil Brown <neilb@suse.de>
+- *      Jeff Garzik <jeff@garzik.org>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- *
+- */
+-#include <linux/kernel.h>
+-#include <linux/interrupt.h>
+-#include <linux/mm.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/raid/xor.h>
+-#include <linux/async_tx.h>
+-
+-static void
+-do_async_xor(struct dma_async_tx_descriptor *tx, struct dma_device *device,
+-      struct dma_chan *chan, struct page *dest, struct page **src_list,
+-      unsigned int offset, unsigned int src_cnt, size_t len,
+-      enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_param)
+-{
+-      dma_addr_t dma_addr;
+-      enum dma_data_direction dir;
+-      int i;
+-
+-      pr_debug("%s: len: %zu\n", __FUNCTION__, len);
+-
+-      dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+-              DMA_NONE : DMA_FROM_DEVICE;
+-
+-      dma_addr = dma_map_page(device->dev, dest, offset, len, dir);
+-      tx->tx_set_dest(dma_addr, tx, 0);
+-
+-      dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+-              DMA_NONE : DMA_TO_DEVICE;
+-
+-      for (i = 0; i < src_cnt; i++) {
+-              dma_addr = dma_map_page(device->dev, src_list[i],
+-                      offset, len, dir);
+-              tx->tx_set_src(dma_addr, tx, i);
 -      }
 -
-       offset = tcp_ctask->data_offset;
--      sg = sc->request_buffer;
-+      sg = scsi_sglist(sc);
-       if (tcp_ctask->data_offset)
-               for (i = 0; i < tcp_ctask->sg_count; i++)
-@@ -734,7 +713,7 @@
-       if (offset < 0)
-               offset = 0;
--      for (i = tcp_ctask->sg_count; i < sc->use_sg; i++) {
-+      for (i = tcp_ctask->sg_count; i < scsi_sg_count(sc); i++) {
-               char *dest;
-               dest = kmap_atomic(sg[i].page, KM_SOFTIRQ0);
-@@ -779,7 +758,6 @@
-       }
-       BUG_ON(ctask->data_count);
--done:
-       /* check for non-exceptional status */
-       if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) {
-               debug_scsi("done [sc %lx res %d itt 0x%x flags 0x%x]\n",
-@@ -895,11 +873,27 @@
-               }
-       }
--      if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
-+      if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV &&
-+          tcp_conn->in.copy) {
-               uint32_t recv_digest;
-               debug_tcp("extra data_recv offset %d copy %d\n",
-                         tcp_conn->in.offset, tcp_conn->in.copy);
-+
-+              if (!tcp_conn->data_copied) {
-+                      if (tcp_conn->in.padding) {
-+                              debug_tcp("padding -> %d\n",
-+                                        tcp_conn->in.padding);
-+                              memset(pad, 0, tcp_conn->in.padding);
-+                              sg_init_one(&sg, pad, tcp_conn->in.padding);
-+                              crypto_hash_update(&tcp_conn->rx_hash,
-+                                                 &sg, sg.length);
-+                      }
-+                      crypto_hash_final(&tcp_conn->rx_hash,
-+                                        (u8 *) &tcp_conn->in.datadgst);
-+                      debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
-+              }
-+
-               rc = iscsi_tcp_copy(conn, sizeof(uint32_t));
-               if (rc) {
-                       if (rc == -EAGAIN)
-@@ -925,7 +919,6 @@
-       if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV &&
-          tcp_conn->in.copy) {
+-      async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+-}
 -
-               debug_tcp("data_recv offset %d copy %d\n",
-                      tcp_conn->in.offset, tcp_conn->in.copy);
-@@ -936,24 +929,32 @@
-                       iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
-                       return 0;
-               }
--              tcp_conn->in.copy -= tcp_conn->in.padding;
--              tcp_conn->in.offset += tcp_conn->in.padding;
--              if (conn->datadgst_en) {
--                      if (tcp_conn->in.padding) {
--                              debug_tcp("padding -> %d\n",
--                                        tcp_conn->in.padding);
--                              memset(pad, 0, tcp_conn->in.padding);
--                              sg_init_one(&sg, pad, tcp_conn->in.padding);
--                              crypto_hash_update(&tcp_conn->rx_hash,
--                                                 &sg, sg.length);
+-static void
+-do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,
+-      unsigned int src_cnt, size_t len, enum async_tx_flags flags,
+-      struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_param)
+-{
+-      void *_dest;
+-      int i;
+-
+-      pr_debug("%s: len: %zu\n", __FUNCTION__, len);
+-
+-      /* reuse the 'src_list' array to convert to buffer pointers */
+-      for (i = 0; i < src_cnt; i++)
+-              src_list[i] = (struct page *)
+-                      (page_address(src_list[i]) + offset);
+-
+-      /* set destination address */
+-      _dest = page_address(dest) + offset;
+-
+-      if (flags & ASYNC_TX_XOR_ZERO_DST)
+-              memset(_dest, 0, len);
+-
+-      xor_blocks(src_cnt, len, _dest,
+-              (void **) src_list);
+-
+-      async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+-}
+-
+-/**
+- * async_xor - attempt to xor a set of blocks with a dma engine.
+- *    xor_blocks always uses the dest as a source so the ASYNC_TX_XOR_ZERO_DST
+- *    flag must be set to not include dest data in the calculation.  The
+- *    assumption with dma eninges is that they only use the destination
+- *    buffer as a source when it is explicity specified in the source list.
+- * @dest: destination page
+- * @src_list: array of source pages (if the dest is also a source it must be
+- *    at index zero).  The contents of this array may be overwritten.
+- * @offset: offset in pages to start transaction
+- * @src_cnt: number of source pages
+- * @len: length in bytes
+- * @flags: ASYNC_TX_XOR_ZERO_DST, ASYNC_TX_XOR_DROP_DEST,
+- *    ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+- * @depend_tx: xor depends on the result of this transaction.
+- * @cb_fn: function to call when the xor completes
+- * @cb_param: parameter to pass to the callback routine
+- */
+-struct dma_async_tx_descriptor *
+-async_xor(struct page *dest, struct page **src_list, unsigned int offset,
+-      int src_cnt, size_t len, enum async_tx_flags flags,
+-      struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_param)
+-{
+-      struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR);
+-      struct dma_device *device = chan ? chan->device : NULL;
+-      struct dma_async_tx_descriptor *tx = NULL;
+-      dma_async_tx_callback _cb_fn;
+-      void *_cb_param;
+-      unsigned long local_flags;
+-      int xor_src_cnt;
+-      int i = 0, src_off = 0, int_en;
+-
+-      BUG_ON(src_cnt <= 1);
+-
+-      while (src_cnt) {
+-              local_flags = flags;
+-              if (device) { /* run the xor asynchronously */
+-                      xor_src_cnt = min(src_cnt, device->max_xor);
+-                      /* if we are submitting additional xors
+-                       * only set the callback on the last transaction
+-                       */
+-                      if (src_cnt > xor_src_cnt) {
+-                              local_flags &= ~ASYNC_TX_ACK;
+-                              _cb_fn = NULL;
+-                              _cb_param = NULL;
+-                      } else {
+-                              _cb_fn = cb_fn;
+-                              _cb_param = cb_param;
 -                      }
--                      crypto_hash_final(&tcp_conn->rx_hash,
--                                        (u8 *) &tcp_conn->in.datadgst);
--                      debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
-+
-+              if (tcp_conn->in.padding)
-+                      tcp_conn->in_progress = IN_PROGRESS_PAD_RECV;
-+              else if (conn->datadgst_en)
-                       tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
-+              else
-+                      tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
-                       tcp_conn->data_copied = 0;
+-
+-                      int_en = _cb_fn ? 1 : 0;
+-
+-                      tx = device->device_prep_dma_xor(
+-                              chan, xor_src_cnt, len, int_en);
+-
+-                      if (tx) {
+-                              do_async_xor(tx, device, chan, dest,
+-                              &src_list[src_off], offset, xor_src_cnt, len,
+-                              local_flags, depend_tx, _cb_fn,
+-                              _cb_param);
+-                      } else /* fall through */
+-                              goto xor_sync;
+-              } else { /* run the xor synchronously */
+-xor_sync:
+-                      /* in the sync case the dest is an implied source
+-                       * (assumes the dest is at the src_off index)
+-                       */
+-                      if (flags & ASYNC_TX_XOR_DROP_DST) {
+-                              src_cnt--;
+-                              src_off++;
+-                      }
+-
+-                      /* process up to 'MAX_XOR_BLOCKS' sources */
+-                      xor_src_cnt = min(src_cnt, MAX_XOR_BLOCKS);
+-
+-                      /* if we are submitting additional xors
+-                       * only set the callback on the last transaction
+-                       */
+-                      if (src_cnt > xor_src_cnt) {
+-                              local_flags &= ~ASYNC_TX_ACK;
+-                              _cb_fn = NULL;
+-                              _cb_param = NULL;
+-                      } else {
+-                              _cb_fn = cb_fn;
+-                              _cb_param = cb_param;
+-                      }
+-
+-                      /* wait for any prerequisite operations */
+-                      if (depend_tx) {
+-                              /* if ack is already set then we cannot be sure
+-                               * we are referring to the correct operation
+-                               */
+-                              BUG_ON(depend_tx->ack);
+-                              if (dma_wait_for_async_tx(depend_tx) ==
+-                                      DMA_ERROR)
+-                                      panic("%s: DMA_ERROR waiting for "
+-                                              "depend_tx\n",
+-                                              __FUNCTION__);
+-                      }
+-
+-                      do_sync_xor(dest, &src_list[src_off], offset,
+-                              xor_src_cnt, len, local_flags, depend_tx,
+-                              _cb_fn, _cb_param);
+-              }
+-
+-              /* the previous tx is hidden from the client,
+-               * so ack it
+-               */
+-              if (i && depend_tx)
+-                      async_tx_ack(depend_tx);
+-
+-              depend_tx = tx;
+-
+-              if (src_cnt > xor_src_cnt) {
+-                      /* drop completed sources */
+-                      src_cnt -= xor_src_cnt;
+-                      src_off += xor_src_cnt;
+-
+-                      /* unconditionally preserve the destination */
+-                      flags &= ~ASYNC_TX_XOR_ZERO_DST;
+-
+-                      /* use the intermediate result a source, but remember
+-                       * it's dropped, because it's implied, in the sync case
+-                       */
+-                      src_list[--src_off] = dest;
+-                      src_cnt++;
+-                      flags |= ASYNC_TX_XOR_DROP_DST;
 -              } else
-+      }
-+
-+      if (tcp_conn->in_progress == IN_PROGRESS_PAD_RECV &&
-+          tcp_conn->in.copy) {
-+              int copylen = min(tcp_conn->in.padding - tcp_conn->data_copied,
-+                                tcp_conn->in.copy);
-+
-+              tcp_conn->in.copy -= copylen;
-+              tcp_conn->in.offset += copylen;
-+              tcp_conn->data_copied += copylen;
-+
-+              if (tcp_conn->data_copied != tcp_conn->in.padding)
-+                      tcp_conn->in_progress = IN_PROGRESS_PAD_RECV;
-+              else if (conn->datadgst_en)
-+                      tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
-+              else
-                       tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
-+              tcp_conn->data_copied = 0;
-       }
-       debug_tcp("f, processed %d from out of %d padding %d\n",
-@@ -1215,7 +1216,6 @@
-                       struct iscsi_r2t_info *r2t, int left)
- {
-       struct iscsi_data *hdr;
--      struct scsi_cmnd *sc = ctask->sc;
-       int new_offset;
-       hdr = &r2t->dtask.hdr;
-@@ -1245,15 +1245,8 @@
-       if (iscsi_buf_left(&r2t->sendbuf))
-               return;
--      if (sc->use_sg) {
-               iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
-               r2t->sg += 1;
+-                      src_cnt = 0;
+-              i++;
+-      }
+-
+-      return tx;
+-}
+-EXPORT_SYMBOL_GPL(async_xor);
+-
+-static int page_is_zero(struct page *p, unsigned int offset, size_t len)
+-{
+-      char *a = page_address(p) + offset;
+-      return ((*(u32 *) a) == 0 &&
+-              memcmp(a, a + 4, len - 4) == 0);
+-}
+-
+-/**
+- * async_xor_zero_sum - attempt a xor parity check with a dma engine.
+- * @dest: destination page used if the xor is performed synchronously
+- * @src_list: array of source pages.  The dest page must be listed as a source
+- *    at index zero.  The contents of this array may be overwritten.
+- * @offset: offset in pages to start transaction
+- * @src_cnt: number of source pages
+- * @len: length in bytes
+- * @result: 0 if sum == 0 else non-zero
+- * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+- * @depend_tx: xor depends on the result of this transaction.
+- * @cb_fn: function to call when the xor completes
+- * @cb_param: parameter to pass to the callback routine
+- */
+-struct dma_async_tx_descriptor *
+-async_xor_zero_sum(struct page *dest, struct page **src_list,
+-      unsigned int offset, int src_cnt, size_t len,
+-      u32 *result, enum async_tx_flags flags,
+-      struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_param)
+-{
+-      struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_ZERO_SUM);
+-      struct dma_device *device = chan ? chan->device : NULL;
+-      int int_en = cb_fn ? 1 : 0;
+-      struct dma_async_tx_descriptor *tx = device ?
+-              device->device_prep_dma_zero_sum(chan, src_cnt, len, result,
+-                      int_en) : NULL;
+-      int i;
+-
+-      BUG_ON(src_cnt <= 1);
+-
+-      if (tx) {
+-              dma_addr_t dma_addr;
+-              enum dma_data_direction dir;
+-
+-              pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+-
+-              dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+-                      DMA_NONE : DMA_TO_DEVICE;
+-
+-              for (i = 0; i < src_cnt; i++) {
+-                      dma_addr = dma_map_page(device->dev, src_list[i],
+-                              offset, len, dir);
+-                      tx->tx_set_src(dma_addr, tx, i);
+-              }
+-
+-              async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
 -      } else {
--              iscsi_buf_init_iov(&r2t->sendbuf,
--                          (char*)sc->request_buffer + new_offset,
--                          r2t->data_count);
--              r2t->sg = NULL;
+-              unsigned long xor_flags = flags;
+-
+-              pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+-
+-              xor_flags |= ASYNC_TX_XOR_DROP_DST;
+-              xor_flags &= ~ASYNC_TX_ACK;
+-
+-              tx = async_xor(dest, src_list, offset, src_cnt, len, xor_flags,
+-                      depend_tx, NULL, NULL);
+-
+-              if (tx) {
+-                      if (dma_wait_for_async_tx(tx) == DMA_ERROR)
+-                              panic("%s: DMA_ERROR waiting for tx\n",
+-                                      __FUNCTION__);
+-                      async_tx_ack(tx);
+-              }
+-
+-              *result = page_is_zero(dest, offset, len) ? 0 : 1;
+-
+-              tx = NULL;
+-
+-              async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+-      }
+-
+-      return tx;
+-}
+-EXPORT_SYMBOL_GPL(async_xor_zero_sum);
+-
+-static int __init async_xor_init(void)
+-{
+-      return 0;
+-}
+-
+-static void __exit async_xor_exit(void)
+-{
+-      do { } while (0);
+-}
+-
+-module_init(async_xor_init);
+-module_exit(async_xor_exit);
+-
+-MODULE_AUTHOR("Intel Corporation");
+-MODULE_DESCRIPTION("asynchronous xor/xor-zero-sum api");
+-MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/crypto/xor.c linux-2.6.22-570/crypto/xor.c
+--- linux-2.6.22-590/crypto/xor.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/crypto/xor.c      1969-12-31 19:00:00.000000000 -0500
+@@ -1,155 +0,0 @@
+-/*
+- * xor.c : Multiple Devices driver for Linux
+- *
+- * Copyright (C) 1996, 1997, 1998, 1999, 2000,
+- * Ingo Molnar, Matti Aarnio, Jakub Jelinek, Richard Henderson.
+- *
+- * Dispatch optimized RAID-5 checksumming functions.
+- *
+- * 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, or (at your option)
+- * any later version.
+- *
+- * You should have received a copy of the GNU General Public License
+- * (for example /usr/src/linux/COPYING); if not, write to the Free
+- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#define BH_TRACE 0
+-#include <linux/module.h>
+-#include <linux/raid/md.h>
+-#include <linux/raid/xor.h>
+-#include <asm/xor.h>
+-
+-/* The xor routines to use.  */
+-static struct xor_block_template *active_template;
+-
+-void
+-xor_blocks(unsigned int src_count, unsigned int bytes, void *dest, void **srcs)
+-{
+-      unsigned long *p1, *p2, *p3, *p4;
+-
+-      p1 = (unsigned long *) srcs[0];
+-      if (src_count == 1) {
+-              active_template->do_2(bytes, dest, p1);
+-              return;
+-      }
+-
+-      p2 = (unsigned long *) srcs[1];
+-      if (src_count == 2) {
+-              active_template->do_3(bytes, dest, p1, p2);
+-              return;
+-      }
+-
+-      p3 = (unsigned long *) srcs[2];
+-      if (src_count == 3) {
+-              active_template->do_4(bytes, dest, p1, p2, p3);
+-              return;
 -      }
- }
- static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask,
-@@ -1277,41 +1270,10 @@
- static void
- iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
- {
--      struct scsi_cmnd *sc = ctask->sc;
-       struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
-       BUG_ON(__kfifo_len(tcp_ctask->r2tqueue));
 -
--      tcp_ctask->sent = 0;
--      tcp_ctask->sg_count = 0;
+-      p4 = (unsigned long *) srcs[3];
+-      active_template->do_5(bytes, dest, p1, p2, p3, p4);
+-}
+-EXPORT_SYMBOL(xor_blocks);
 -
--      if (sc->sc_data_direction == DMA_TO_DEVICE) {
--              tcp_ctask->xmstate = XMSTATE_W_HDR;
--              tcp_ctask->exp_r2tsn = 0;
--              BUG_ON(ctask->total_length == 0);
+-/* Set of all registered templates.  */
+-static struct xor_block_template *template_list;
 -
--              if (sc->use_sg) {
--                      struct scatterlist *sg = sc->request_buffer;
+-#define BENCH_SIZE (PAGE_SIZE)
 -
--                      iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
--                      tcp_ctask->sg = sg + 1;
--                      tcp_ctask->bad_sg = sg + sc->use_sg;
--              } else {
--                      iscsi_buf_init_iov(&tcp_ctask->sendbuf,
--                                         sc->request_buffer,
--                                         sc->request_bufflen);
--                      tcp_ctask->sg = NULL;
--                      tcp_ctask->bad_sg = NULL;
--              }
--              debug_scsi("cmd [itt 0x%x total %d imm_data %d "
--                         "unsol count %d, unsol offset %d]\n",
--                         ctask->itt, ctask->total_length, ctask->imm_count,
--                         ctask->unsol_count, ctask->unsol_offset);
--      } else
--              tcp_ctask->xmstate = XMSTATE_R_HDR;
+-static void
+-do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
+-{
+-      int speed;
+-      unsigned long now;
+-      int i, count, max;
 -
--      iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
--                          sizeof(struct iscsi_hdr));
-+      tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT;
- }
- /**
-@@ -1324,9 +1286,11 @@
-  *    call it again later, or recover. '0' return code means successful
-  *    xmit.
-  *
-- *    Management xmit state machine consists of two states:
-- *            IN_PROGRESS_IMM_HEAD - PDU Header xmit in progress
-- *            IN_PROGRESS_IMM_DATA - PDU Data xmit in progress
-+ *    Management xmit state machine consists of these states:
-+ *            XMSTATE_IMM_HDR_INIT    - calculate digest of PDU Header
-+ *            XMSTATE_IMM_HDR         - PDU Header xmit in progress
-+ *            XMSTATE_IMM_DATA        - PDU Data xmit in progress
-+ *            XMSTATE_IDLE            - management PDU is done
-  **/
- static int
- iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
-@@ -1337,23 +1301,34 @@
-       debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n",
-               conn->id, tcp_mtask->xmstate, mtask->itt);
--      if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
--              tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
--              if (mtask->data_count)
-+      if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) {
-+              iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
-+                                 sizeof(struct iscsi_hdr));
-+
-+              if (mtask->data_count) {
-                       tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
-+                      iscsi_buf_init_iov(&tcp_mtask->sendbuf,
-+                                         (char*)mtask->data,
-+                                         mtask->data_count);
-+              }
-+
-               if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
-                   conn->stop_stage != STOP_CONN_RECOVER &&
-                   conn->hdrdgst_en)
-                       iscsi_hdr_digest(conn, &tcp_mtask->headbuf,
-                                       (u8*)tcp_mtask->hdrext);
-+
-+              tcp_mtask->sent = 0;
-+              tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR_INIT;
-+              tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
-+      }
-+
-+      if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
-               rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf,
-                                  mtask->data_count);
--              if (rc) {
--                      tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
--                      if (mtask->data_count)
--                              tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
-+              if (rc)
-                       return rc;
+-      tmpl->next = template_list;
+-      template_list = tmpl;
+-
+-      /*
+-       * Count the number of XORs done during a whole jiffy, and use
+-       * this to calculate the speed of checksumming.  We use a 2-page
+-       * allocation to have guaranteed color L1-cache layout.
+-       */
+-      max = 0;
+-      for (i = 0; i < 5; i++) {
+-              now = jiffies;
+-              count = 0;
+-              while (jiffies == now) {
+-                      mb(); /* prevent loop optimzation */
+-                      tmpl->do_2(BENCH_SIZE, b1, b2);
+-                      mb();
+-                      count++;
+-                      mb();
 -              }
-+              tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
-       }
-       if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) {
-@@ -1387,55 +1362,67 @@
-       return 0;
- }
--static inline int
--iscsi_send_read_hdr(struct iscsi_conn *conn,
--                  struct iscsi_tcp_cmd_task *tcp_ctask)
-+static int
-+iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
- {
--      int rc;
-+      struct scsi_cmnd *sc = ctask->sc;
-+      struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
-+      int rc = 0;
--      tcp_ctask->xmstate &= ~XMSTATE_R_HDR;
--      if (conn->hdrdgst_en)
--              iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
--                               (u8*)tcp_ctask->hdrext);
--      rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0);
--      if (!rc) {
--              BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE);
--              return 0; /* wait for Data-In */
-+      if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) {
-+              tcp_ctask->sent = 0;
-+              tcp_ctask->sg_count = 0;
-+              tcp_ctask->exp_datasn = 0;
-+
-+              if (sc->sc_data_direction == DMA_TO_DEVICE) {
-+                      struct scatterlist *sg = scsi_sglist(sc);
-+
-+                      iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
-+                      tcp_ctask->sg = sg + 1;
-+                      tcp_ctask->bad_sg = sg + scsi_sg_count(sc);
-+
-+                      debug_scsi("cmd [itt 0x%x total %d imm_data %d "
-+                                 "unsol count %d, unsol offset %d]\n",
-+                                 ctask->itt, scsi_bufflen(sc),
-+                                 ctask->imm_count, ctask->unsol_count,
-+                                 ctask->unsol_offset);
-       }
--      tcp_ctask->xmstate |= XMSTATE_R_HDR;
--      return rc;
+-              if (count > max)
+-                      max = count;
+-      }
+-
+-      speed = max * (HZ * BENCH_SIZE / 1024);
+-      tmpl->speed = speed;
+-
+-      printk(KERN_INFO "   %-10s: %5d.%03d MB/sec\n", tmpl->name,
+-             speed / 1000, speed % 1000);
 -}
--static inline int
--iscsi_send_write_hdr(struct iscsi_conn *conn,
--                   struct iscsi_cmd_task *ctask)
+-
+-static int __init
+-calibrate_xor_blocks(void)
 -{
--      struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
--      int rc;
-+              iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
-+                                sizeof(struct iscsi_hdr));
--      tcp_ctask->xmstate &= ~XMSTATE_W_HDR;
-       if (conn->hdrdgst_en)
-               iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
-                                (u8*)tcp_ctask->hdrext);
-+              tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT;
-+              tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT;
-+      }
-+
-+      if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) {
-       rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
--      if (rc) {
--              tcp_ctask->xmstate |= XMSTATE_W_HDR;
-+              if (rc)
-               return rc;
+-      void *b1, *b2;
+-      struct xor_block_template *f, *fastest;
+-
+-      b1 = (void *) __get_free_pages(GFP_KERNEL, 2);
+-      if (!b1) {
+-              printk(KERN_WARNING "xor: Yikes!  No memory available.\n");
+-              return -ENOMEM;
 -      }
-+              tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT;
-+
-+              if (sc->sc_data_direction != DMA_TO_DEVICE)
-+                      return 0;
-       if (ctask->imm_count) {
-               tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
-               iscsi_set_padding(tcp_ctask, ctask->imm_count);
-               if (ctask->conn->datadgst_en) {
--                      iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask);
-+                              iscsi_data_digest_init(ctask->conn->dd_data,
-+                                                     tcp_ctask);
-                       tcp_ctask->immdigest = 0;
-               }
-       }
-       if (ctask->unsol_count)
--              tcp_ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
--      return 0;
-+                      tcp_ctask->xmstate |=
-+                                      XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
-+      }
-+      return rc;
- }
- static int
-@@ -1624,9 +1611,7 @@
-       struct iscsi_data_task *dtask;
-       int left, rc;
--      if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
--              tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
--              tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
-+      if (tcp_ctask->xmstate & XMSTATE_SOL_HDR_INIT) {
-               if (!tcp_ctask->r2t) {
-                       spin_lock_bh(&session->lock);
-                       __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
-@@ -1640,13 +1625,20 @@
-               if (conn->hdrdgst_en)
-                       iscsi_hdr_digest(conn, &r2t->headbuf,
-                                       (u8*)dtask->hdrext);
--              rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
--              if (rc) {
--                      tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
-+              tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR_INIT;
-                       tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
--                      return rc;
-               }
-+      if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
-+              r2t = tcp_ctask->r2t;
-+              dtask = &r2t->dtask;
-+
-+              rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
-+              if (rc)
-+                      return rc;
-+              tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
-+              tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
-+
-               if (conn->datadgst_en) {
-                       iscsi_data_digest_init(conn->dd_data, tcp_ctask);
-                       dtask->digest = 0;
-@@ -1677,8 +1669,6 @@
-               left = r2t->data_length - r2t->sent;
-               if (left) {
-                       iscsi_solicit_data_cont(conn, ctask, r2t, left);
--                      tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
--                      tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
-                       goto send_hdr;
-               }
-@@ -1693,8 +1683,6 @@
-               if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t,
-                               sizeof(void*))) {
-                       tcp_ctask->r2t = r2t;
--                      tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
--                      tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
-                       spin_unlock_bh(&session->lock);
-                       goto send_hdr;
-               }
-@@ -1703,6 +1691,46 @@
-       return 0;
- }
-+/**
-+ * iscsi_tcp_ctask_xmit - xmit normal PDU task
-+ * @conn: iscsi connection
-+ * @ctask: iscsi command task
-+ *
-+ * Notes:
-+ *    The function can return -EAGAIN in which case caller must
-+ *    call it again later, or recover. '0' return code means successful
-+ *    xmit.
-+ *    The function is devided to logical helpers (above) for the different
-+ *    xmit stages.
-+ *
-+ *iscsi_send_cmd_hdr()
-+ *    XMSTATE_CMD_HDR_INIT - prepare Header and Data buffers Calculate
-+ *                           Header Digest
-+ *    XMSTATE_CMD_HDR_XMIT - Transmit header in progress
-+ *
-+ *iscsi_send_padding
-+ *    XMSTATE_W_PAD        - Prepare and send pading
-+ *    XMSTATE_W_RESEND_PAD - retry send pading
-+ *
-+ *iscsi_send_digest
-+ *    XMSTATE_W_RESEND_DATA_DIGEST - Finalize and send Data Digest
-+ *    XMSTATE_W_RESEND_DATA_DIGEST - retry sending digest
-+ *
-+ *iscsi_send_unsol_hdr
-+ *    XMSTATE_UNS_INIT     - prepare un-solicit data header and digest
-+ *    XMSTATE_UNS_HDR      - send un-solicit header
-+ *
-+ *iscsi_send_unsol_pdu
-+ *    XMSTATE_UNS_DATA     - send un-solicit data in progress
-+ *
-+ *iscsi_send_sol_pdu
-+ *    XMSTATE_SOL_HDR_INIT - solicit data header and digest initialize
-+ *    XMSTATE_SOL_HDR      - send solicit header
-+ *    XMSTATE_SOL_DATA     - send solicit data
-+ *
-+ *iscsi_tcp_ctask_xmit
-+ *    XMSTATE_IMM_DATA     - xmit managment data (??)
-+ **/
- static int
- iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
- {
-@@ -1712,20 +1740,11 @@
-       debug_scsi("ctask deq [cid %d xmstate %x itt 0x%x]\n",
-               conn->id, tcp_ctask->xmstate, ctask->itt);
+-      b2 = b1 + 2*PAGE_SIZE + BENCH_SIZE;
+-
 -      /*
--       * serialize with TMF AbortTask
+-       * If this arch/cpu has a short-circuited selection, don't loop through
+-       * all the possible functions, just test the best one
 -       */
--      if (ctask->mtask)
--              return rc;
 -
--      if (tcp_ctask->xmstate & XMSTATE_R_HDR)
--              return iscsi_send_read_hdr(conn, tcp_ctask);
+-      fastest = NULL;
 -
--      if (tcp_ctask->xmstate & XMSTATE_W_HDR) {
--              rc = iscsi_send_write_hdr(conn, ctask);
-+      rc = iscsi_send_cmd_hdr(conn, ctask);
-               if (rc)
-                       return rc;
+-#ifdef XOR_SELECT_TEMPLATE
+-              fastest = XOR_SELECT_TEMPLATE(fastest);
+-#endif
+-
+-#define xor_speed(templ)      do_xor_speed((templ), b1, b2)
+-
+-      if (fastest) {
+-              printk(KERN_INFO "xor: automatically using best "
+-                      "checksumming function: %s\n",
+-                      fastest->name);
+-              xor_speed(fastest);
+-      } else {
+-              printk(KERN_INFO "xor: measuring software checksum speed\n");
+-              XOR_TRY_TEMPLATES;
+-              fastest = template_list;
+-              for (f = fastest; f; f = f->next)
+-                      if (f->speed > fastest->speed)
+-                              fastest = f;
 -      }
-+      if (ctask->sc->sc_data_direction != DMA_TO_DEVICE)
-+              return 0;
-       if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) {
-               rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg,
-@@ -1810,18 +1829,22 @@
- static void
- iscsi_tcp_release_conn(struct iscsi_conn *conn)
- {
-+      struct iscsi_session *session = conn->session;
-       struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-+      struct socket *sock = tcp_conn->sock;
--      if (!tcp_conn->sock)
-+      if (!sock)
-               return;
--      sock_hold(tcp_conn->sock->sk);
-+      sock_hold(sock->sk);
-       iscsi_conn_restore_callbacks(tcp_conn);
--      sock_put(tcp_conn->sock->sk);
-+      sock_put(sock->sk);
--      sock_release(tcp_conn->sock);
-+      spin_lock_bh(&session->lock);
-       tcp_conn->sock = NULL;
-       conn->recv_lock = NULL;
-+      spin_unlock_bh(&session->lock);
-+      sockfd_put(sock);
- }
- static void
-@@ -1852,6 +1875,46 @@
-       tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
- }
-+static int iscsi_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
-+                            char *buf, int *port,
-+                            int (*getname)(struct socket *, struct sockaddr *,
-+                                      int *addrlen))
-+{
-+      struct sockaddr_storage *addr;
-+      struct sockaddr_in6 *sin6;
-+      struct sockaddr_in *sin;
-+      int rc = 0, len;
-+
-+      addr = kmalloc(GFP_KERNEL, sizeof(*addr));
-+      if (!addr)
-+              return -ENOMEM;
-+
-+      if (getname(sock, (struct sockaddr *) addr, &len)) {
-+              rc = -ENODEV;
-+              goto free_addr;
-+      }
-+
-+      switch (addr->ss_family) {
-+      case AF_INET:
-+              sin = (struct sockaddr_in *)addr;
-+              spin_lock_bh(&conn->session->lock);
-+              sprintf(buf, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
-+              *port = be16_to_cpu(sin->sin_port);
-+              spin_unlock_bh(&conn->session->lock);
-+              break;
-+      case AF_INET6:
-+              sin6 = (struct sockaddr_in6 *)addr;
-+              spin_lock_bh(&conn->session->lock);
-+              sprintf(buf, NIP6_FMT, NIP6(sin6->sin6_addr));
-+              *port = be16_to_cpu(sin6->sin6_port);
-+              spin_unlock_bh(&conn->session->lock);
-+              break;
-+      }
-+free_addr:
-+      kfree(addr);
-+      return rc;
-+}
-+
- static int
- iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
-                   struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
-@@ -1869,10 +1932,24 @@
-               printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err);
-               return -EEXIST;
-       }
-+      /*
-+       * copy these values now because if we drop the session
-+       * userspace may still want to query the values since we will
-+       * be using them for the reconnect
-+       */
-+      err = iscsi_tcp_get_addr(conn, sock, conn->portal_address,
-+                               &conn->portal_port, kernel_getpeername);
-+      if (err)
-+              goto free_socket;
-+
-+      err = iscsi_tcp_get_addr(conn, sock, conn->local_address,
-+                              &conn->local_port, kernel_getsockname);
-+      if (err)
-+              goto free_socket;
-       err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
-       if (err)
--              return err;
-+              goto free_socket;
-       /* bind iSCSI connection and socket */
-       tcp_conn->sock = sock;
-@@ -1896,25 +1973,19 @@
-        * set receive state machine into initial state
-        */
-       tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
 -
-       return 0;
-+
-+free_socket:
-+      sockfd_put(sock);
-+      return err;
- }
- /* called with host lock */
- static void
--iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
--                  char *data, uint32_t data_size)
-+iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
- {
-       struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
+-      printk(KERN_INFO "xor: using function: %s (%d.%03d MB/sec)\n",
+-             fastest->name, fastest->speed / 1000, fastest->speed % 1000);
 -
--      iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
--                         sizeof(struct iscsi_hdr));
--      tcp_mtask->xmstate = XMSTATE_IMM_HDR;
--      tcp_mtask->sent = 0;
+-#undef xor_speed
 -
--      if (mtask->data_count)
--              iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data,
--                                  mtask->data_count);
-+      tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT;
- }
- static int
-@@ -2026,41 +2097,18 @@
-                        enum iscsi_param param, char *buf)
- {
-       struct iscsi_conn *conn = cls_conn->dd_data;
--      struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
--      struct inet_sock *inet;
--      struct ipv6_pinfo *np;
--      struct sock *sk;
-       int len;
-       switch(param) {
-       case ISCSI_PARAM_CONN_PORT:
--              mutex_lock(&conn->xmitmutex);
--              if (!tcp_conn->sock) {
--                      mutex_unlock(&conn->xmitmutex);
--                      return -EINVAL;
--              }
+-      free_pages((unsigned long)b1, 2);
 -
--              inet = inet_sk(tcp_conn->sock->sk);
--              len = sprintf(buf, "%hu\n", be16_to_cpu(inet->dport));
--              mutex_unlock(&conn->xmitmutex);
-+              spin_lock_bh(&conn->session->lock);
-+              len = sprintf(buf, "%hu\n", conn->portal_port);
-+              spin_unlock_bh(&conn->session->lock);
-               break;
-       case ISCSI_PARAM_CONN_ADDRESS:
--              mutex_lock(&conn->xmitmutex);
--              if (!tcp_conn->sock) {
--                      mutex_unlock(&conn->xmitmutex);
--                      return -EINVAL;
--              }
+-      active_template = fastest;
+-      return 0;
+-}
 -
--              sk = tcp_conn->sock->sk;
--              if (sk->sk_family == PF_INET) {
--                      inet = inet_sk(sk);
--                      len = sprintf(buf, NIPQUAD_FMT "\n",
--                                    NIPQUAD(inet->daddr));
--              } else {
--                      np = inet6_sk(sk);
--                      len = sprintf(buf, NIP6_FMT "\n", NIP6(np->daddr));
--              }
--              mutex_unlock(&conn->xmitmutex);
-+              spin_lock_bh(&conn->session->lock);
-+              len = sprintf(buf, "%s\n", conn->portal_address);
-+              spin_unlock_bh(&conn->session->lock);
-               break;
-       default:
-               return iscsi_conn_get_param(cls_conn, param, buf);
-@@ -2069,6 +2117,29 @@
-       return len;
- }
-+static int
-+iscsi_tcp_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
-+                       char *buf)
-+{
-+        struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
-+      int len;
-+
-+      switch (param) {
-+      case ISCSI_HOST_PARAM_IPADDRESS:
-+              spin_lock_bh(&session->lock);
-+              if (!session->leadconn)
-+                      len = -ENODEV;
-+              else
-+                      len = sprintf(buf, "%s\n",
-+                                   session->leadconn->local_address);
-+              spin_unlock_bh(&session->lock);
-+              break;
-+      default:
-+              return iscsi_host_get_param(shost, param, buf);
-+      }
-+      return len;
-+}
-+
- static void
- iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
- {
-@@ -2096,6 +2167,7 @@
- static struct iscsi_cls_session *
- iscsi_tcp_session_create(struct iscsi_transport *iscsit,
-                        struct scsi_transport_template *scsit,
-+                       uint16_t cmds_max, uint16_t qdepth,
-                        uint32_t initial_cmdsn, uint32_t *hostno)
- {
-       struct iscsi_cls_session *cls_session;
-@@ -2103,7 +2175,7 @@
-       uint32_t hn;
-       int cmd_i;
--      cls_session = iscsi_session_setup(iscsit, scsit,
-+      cls_session = iscsi_session_setup(iscsit, scsit, cmds_max, qdepth,
-                                        sizeof(struct iscsi_tcp_cmd_task),
-                                        sizeof(struct iscsi_tcp_mgmt_task),
-                                        initial_cmdsn, &hn);
-@@ -2142,17 +2214,24 @@
-       iscsi_session_teardown(cls_session);
- }
-+static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
-+{
-+      blk_queue_dma_alignment(sdev->request_queue, 0);
-+      return 0;
-+}
-+
- static struct scsi_host_template iscsi_sht = {
-       .name                   = "iSCSI Initiator over TCP/IP",
-       .queuecommand           = iscsi_queuecommand,
-       .change_queue_depth     = iscsi_change_queue_depth,
--      .can_queue              = ISCSI_XMIT_CMDS_MAX - 1,
-+      .can_queue              = ISCSI_DEF_XMIT_CMDS_MAX - 1,
-       .sg_tablesize           = ISCSI_SG_TABLESIZE,
-       .max_sectors            = 0xFFFF,
-       .cmd_per_lun            = ISCSI_DEF_CMD_PER_LUN,
-       .eh_abort_handler       = iscsi_eh_abort,
-       .eh_host_reset_handler  = iscsi_eh_host_reset,
-       .use_clustering         = DISABLE_CLUSTERING,
-+      .slave_configure        = iscsi_tcp_slave_configure,
-       .proc_name              = "iscsi_tcp",
-       .this_id                = -1,
- };
-@@ -2179,8 +2258,12 @@
-                                 ISCSI_EXP_STATSN |
-                                 ISCSI_PERSISTENT_PORT |
-                                 ISCSI_PERSISTENT_ADDRESS |
--                                ISCSI_TARGET_NAME |
--                                ISCSI_TPGT,
-+                                ISCSI_TARGET_NAME | ISCSI_TPGT |
-+                                ISCSI_USERNAME | ISCSI_PASSWORD |
-+                                ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
-+      .host_param_mask        = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
-+                                ISCSI_HOST_INITIATOR_NAME |
-+                                ISCSI_HOST_NETDEV_NAME,
-       .host_template          = &iscsi_sht,
-       .conndata_size          = sizeof(struct iscsi_conn),
-       .max_conn               = 1,
-@@ -2197,6 +2280,9 @@
-       .get_session_param      = iscsi_session_get_param,
-       .start_conn             = iscsi_conn_start,
-       .stop_conn              = iscsi_tcp_conn_stop,
-+      /* iscsi host params */
-+      .get_host_param         = iscsi_tcp_host_get_param,
-+      .set_host_param         = iscsi_host_set_param,
-       /* IO */
-       .send_pdu               = iscsi_conn_send_pdu,
-       .get_stats              = iscsi_conn_get_stats,
-diff -Nurb linux-2.6.22-570/drivers/scsi/iscsi_tcp.h linux-2.6.22-590/drivers/scsi/iscsi_tcp.h
---- linux-2.6.22-570/drivers/scsi/iscsi_tcp.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/iscsi_tcp.h  2008-01-02 13:56:37.000000000 -0500
-@@ -29,11 +29,12 @@
- #define IN_PROGRESS_HEADER_GATHER     0x1
- #define IN_PROGRESS_DATA_RECV         0x2
- #define IN_PROGRESS_DDIGEST_RECV      0x3
-+#define IN_PROGRESS_PAD_RECV          0x4
- /* xmit state machine */
- #define XMSTATE_IDLE                  0x0
--#define XMSTATE_R_HDR                 0x1
--#define XMSTATE_W_HDR                 0x2
-+#define XMSTATE_CMD_HDR_INIT          0x1
-+#define XMSTATE_CMD_HDR_XMIT          0x2
- #define XMSTATE_IMM_HDR                       0x4
- #define XMSTATE_IMM_DATA              0x8
- #define XMSTATE_UNS_INIT              0x10
-@@ -44,6 +45,8 @@
- #define XMSTATE_W_PAD                 0x200
- #define XMSTATE_W_RESEND_PAD          0x400
- #define XMSTATE_W_RESEND_DATA_DIGEST  0x800
-+#define XMSTATE_IMM_HDR_INIT          0x1000
-+#define XMSTATE_SOL_HDR_INIT          0x2000
- #define ISCSI_PAD_LEN                 4
- #define ISCSI_SG_TABLESIZE            SG_ALL
-@@ -152,7 +155,7 @@
-       struct scatterlist      *sg;                    /* per-cmd SG list  */
-       struct scatterlist      *bad_sg;                /* assert statement */
-       int                     sg_count;               /* SG's to process  */
--      uint32_t                exp_r2tsn;
-+      uint32_t                exp_datasn;             /* expected target's R2TSN/DataSN */
-       int                     data_offset;
-       struct iscsi_r2t_info   *r2t;                   /* in progress R2T    */
-       struct iscsi_queue      r2tpool;
-diff -Nurb linux-2.6.22-570/drivers/scsi/jazz_esp.c linux-2.6.22-590/drivers/scsi/jazz_esp.c
---- linux-2.6.22-570/drivers/scsi/jazz_esp.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/jazz_esp.c   2008-01-02 13:56:37.000000000 -0500
-@@ -1,6 +1,6 @@
- /* jazz_esp.c: ESP front-end for MIPS JAZZ systems.
-  *
-- * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
-+ * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
-  */
- #include <linux/kernel.h>
-@@ -143,7 +143,7 @@
-               goto fail;
-       host->max_id = 8;
--      esp = host_to_esp(host);
-+      esp = shost_priv(host);
-       esp->host = host;
-       esp->dev = dev;
-diff -Nurb linux-2.6.22-570/drivers/scsi/libiscsi.c linux-2.6.22-590/drivers/scsi/libiscsi.c
---- linux-2.6.22-570/drivers/scsi/libiscsi.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/libiscsi.c   2008-01-02 13:56:37.000000000 -0500
-@@ -22,7 +22,6 @@
-  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-  */
- #include <linux/types.h>
--#include <linux/mutex.h>
- #include <linux/kfifo.h>
- #include <linux/delay.h>
- #include <asm/unaligned.h>
-@@ -46,27 +45,53 @@
- }
- EXPORT_SYMBOL_GPL(class_to_transport_session);
--#define INVALID_SN_DELTA      0xffff
-+/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
-+#define SNA32_CHECK 2147483648UL
--int
--iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
-+static int iscsi_sna_lt(u32 n1, u32 n2)
-+{
-+      return n1 != n2 && ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) ||
-+                          (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
-+}
-+
-+/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
-+static int iscsi_sna_lte(u32 n1, u32 n2)
-+{
-+      return n1 == n2 || ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) ||
-+                          (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
-+}
-+
-+void
-+iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
- {
-       uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn);
-       uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn);
+-static __exit void xor_exit(void) { }
+-
+-MODULE_LICENSE("GPL");
+-
+-/* when built-in xor.o must initialize before drivers/md/md.o */
+-core_initcall(calibrate_xor_blocks);
+-module_exit(xor_exit);
+diff -Nurb linux-2.6.22-590/drivers/Makefile linux-2.6.22-570/drivers/Makefile
+--- linux-2.6.22-590/drivers/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/Makefile  2007-07-08 19:32:17.000000000 -0400
+@@ -70,7 +70,6 @@
+ obj-$(CONFIG_MCA)             += mca/
+ obj-$(CONFIG_EISA)            += eisa/
+ obj-$(CONFIG_CPU_FREQ)                += cpufreq/
+-obj-$(CONFIG_CPU_IDLE)                += cpuidle/
+ obj-$(CONFIG_MMC)             += mmc/
+ obj-$(CONFIG_NEW_LEDS)                += leds/
+ obj-$(CONFIG_INFINIBAND)      += infiniband/
+diff -Nurb linux-2.6.22-590/drivers/acpi/Kconfig linux-2.6.22-570/drivers/acpi/Kconfig
+--- linux-2.6.22-590/drivers/acpi/Kconfig      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/Kconfig      2007-07-08 19:32:17.000000000 -0400
+@@ -124,7 +124,7 @@
  
--      if (max_cmdsn < exp_cmdsn -1 &&
--          max_cmdsn > exp_cmdsn - INVALID_SN_DELTA)
--              return ISCSI_ERR_MAX_CMDSN;
--      if (max_cmdsn > session->max_cmdsn ||
--          max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA)
--              session->max_cmdsn = max_cmdsn;
--      if (exp_cmdsn > session->exp_cmdsn ||
--          exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA)
-+      /*
-+       * standard specifies this check for when to update expected and
-+       * max sequence numbers
-+       */
-+      if (iscsi_sna_lt(max_cmdsn, exp_cmdsn - 1))
-+              return;
-+
-+      if (exp_cmdsn != session->exp_cmdsn &&
-+          !iscsi_sna_lt(exp_cmdsn, session->exp_cmdsn))
-               session->exp_cmdsn = exp_cmdsn;
+ config ACPI_VIDEO
+       tristate "Video"
+-      depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL
++      depends on X86 && BACKLIGHT_CLASS_DEVICE
+       help
+         This driver implement the ACPI Extensions For Display Adapters
+         for integrated graphics devices on motherboard, as specified in
+@@ -280,14 +280,6 @@
+         of verbosity. Saying Y enables these statements. This will increase
+         your kernel size by around 50K.
  
--      return 0;
-+      if (max_cmdsn != session->max_cmdsn &&
-+          !iscsi_sna_lt(max_cmdsn, session->max_cmdsn)) {
-+              session->max_cmdsn = max_cmdsn;
-+              /*
-+               * if the window closed with IO queued, then kick the
-+               * xmit thread
-+               */
-+              if (!list_empty(&session->leadconn->xmitqueue) ||
-+                  __kfifo_len(session->leadconn->mgmtqueue))
-+                      scsi_queue_work(session->host,
-+                                      &session->leadconn->xmitwork);
-+      }
- }
--EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn);
-+EXPORT_SYMBOL_GPL(iscsi_update_cmdsn);
+-config ACPI_DEBUG_FUNC_TRACE
+-      bool "Additionally enable ACPI function tracing"
+-      default n
+-      depends on ACPI_DEBUG
+-      help
+-        ACPI Debug Statements slow down ACPI processing. Function trace
+-        is about half of the penalty and is rarely useful.
+-
+ config ACPI_EC
+       bool
+       default y
+diff -Nurb linux-2.6.22-590/drivers/acpi/battery.c linux-2.6.22-570/drivers/acpi/battery.c
+--- linux-2.6.22-590/drivers/acpi/battery.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/battery.c    2007-07-08 19:32:17.000000000 -0400
+@@ -43,30 +43,21 @@
+ #define ACPI_BATTERY_CLASS            "battery"
+ #define ACPI_BATTERY_HID              "PNP0C0A"
+ #define ACPI_BATTERY_DEVICE_NAME      "Battery"
++#define ACPI_BATTERY_FILE_INFO                "info"
++#define ACPI_BATTERY_FILE_STATUS      "state"
++#define ACPI_BATTERY_FILE_ALARM               "alarm"
+ #define ACPI_BATTERY_NOTIFY_STATUS    0x80
+ #define ACPI_BATTERY_NOTIFY_INFO      0x81
+ #define ACPI_BATTERY_UNITS_WATTS      "mW"
+ #define ACPI_BATTERY_UNITS_AMPS               "mA"
  
- void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
-                                  struct iscsi_data *hdr)
-@@ -115,14 +140,17 @@
-         hdr->flags = ISCSI_ATTR_SIMPLE;
-         int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
-         hdr->itt = build_itt(ctask->itt, conn->id, session->age);
--        hdr->data_length = cpu_to_be32(sc->request_bufflen);
-+        hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
-         hdr->cmdsn = cpu_to_be32(session->cmdsn);
-         session->cmdsn++;
-         hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
-         memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
--        memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len);
-+      if (sc->cmd_len < MAX_COMMAND_SIZE)
-+              memset(&hdr->cdb[sc->cmd_len], 0,
-+                      MAX_COMMAND_SIZE - sc->cmd_len);
+ #define _COMPONENT            ACPI_BATTERY_COMPONENT
+-
+-#define ACPI_BATTERY_UPDATE_TIME      0
+-
+-#define ACPI_BATTERY_NONE_UPDATE      0
+-#define ACPI_BATTERY_EASY_UPDATE      1
+-#define ACPI_BATTERY_INIT_UPDATE      2
+-
+ ACPI_MODULE_NAME("battery");
  
-       ctask->data_count = 0;
-+      ctask->imm_count = 0;
-       if (sc->sc_data_direction == DMA_TO_DEVICE) {
-               hdr->flags |= ISCSI_FLAG_CMD_WRITE;
-               /*
-@@ -139,25 +167,24 @@
-                *
-                *      pad_count       bytes to be sent as zero-padding
-                */
--              ctask->imm_count = 0;
-               ctask->unsol_count = 0;
-               ctask->unsol_offset = 0;
-               ctask->unsol_datasn = 0;
+ MODULE_AUTHOR("Paul Diefenbaugh");
+ MODULE_DESCRIPTION("ACPI Battery Driver");
+ MODULE_LICENSE("GPL");
  
-               if (session->imm_data_en) {
--                      if (ctask->total_length >= session->first_burst)
-+                      if (scsi_bufflen(sc) >= session->first_burst)
-                               ctask->imm_count = min(session->first_burst,
-                                                       conn->max_xmit_dlength);
-                       else
--                              ctask->imm_count = min(ctask->total_length,
-+                              ctask->imm_count = min(scsi_bufflen(sc),
-                                                       conn->max_xmit_dlength);
-                       hton24(ctask->hdr->dlength, ctask->imm_count);
-               } else
-                       zero_data(ctask->hdr->dlength);
+-static unsigned int update_time = ACPI_BATTERY_UPDATE_TIME;
+-
+-/* 0 - every time, > 0 - by update_time */
+-module_param(update_time, uint, 0644);
+-
+ extern struct proc_dir_entry *acpi_lock_battery_dir(void);
+ extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
  
-               if (!session->initial_r2t_en) {
--                      ctask->unsol_count = min(session->first_burst,
--                              ctask->total_length) - ctask->imm_count;
-+                      ctask->unsol_count = min((session->first_burst),
-+                              (scsi_bufflen(sc))) - ctask->imm_count;
-                       ctask->unsol_offset = ctask->imm_count;
-               }
+@@ -85,7 +76,7 @@
+               },
+ };
  
-@@ -165,7 +192,6 @@
-                       /* No unsolicit Data-Out's */
-                       ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL;
-       } else {
--              ctask->datasn = 0;
-               hdr->flags |= ISCSI_FLAG_CMD_FINAL;
-               zero_data(hdr->dlength);
+-struct acpi_battery_state {
++struct acpi_battery_status {
+       acpi_integer state;
+       acpi_integer present_rate;
+       acpi_integer remaining_capacity;
+@@ -108,111 +99,33 @@
+       acpi_string oem_info;
+ };
  
-@@ -174,8 +200,13 @@
-       }
+-enum acpi_battery_files{
+-      ACPI_BATTERY_INFO = 0,
+-      ACPI_BATTERY_STATE,
+-      ACPI_BATTERY_ALARM,
+-      ACPI_BATTERY_NUMFILES,
++struct acpi_battery_flags {
++      u8 present:1;           /* Bay occupied? */
++      u8 power_unit:1;        /* 0=watts, 1=apms */
++      u8 alarm:1;             /* _BTP present? */
++      u8 reserved:5;
+ };
  
-       conn->scsicmd_pdus_cnt++;
-+
-+        debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
-+              "cmdsn %d win %d]\n",
-+                sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
-+              conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
-+                session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
- }
--EXPORT_SYMBOL_GPL(iscsi_prep_scsi_cmd_pdu);
+-struct acpi_battery_flags {
+-      u8 battery_present_prev;
+-      u8 alarm_present;
+-      u8 init_update;
+-      u8 update[ACPI_BATTERY_NUMFILES];
+-      u8 power_unit;
++struct acpi_battery_trips {
++      unsigned long warning;
++      unsigned long low;
+ };
  
- /**
-  * iscsi_complete_command - return command back to scsi-ml
-@@ -204,26 +235,12 @@
-       atomic_inc(&ctask->refcount);
- }
+ struct acpi_battery {
+-      struct mutex mutex;
+-      struct acpi_device *device;
++      struct acpi_device * device;
+       struct acpi_battery_flags flags;
+-      struct acpi_buffer bif_data;
+-      struct acpi_buffer bst_data;
++      struct acpi_battery_trips trips;
+       unsigned long alarm;
+-      unsigned long update_time[ACPI_BATTERY_NUMFILES];
++      struct acpi_battery_info *info;
+ };
  
--static void iscsi_get_ctask(struct iscsi_cmd_task *ctask)
+-inline int acpi_battery_present(struct acpi_battery *battery)
 -{
--      spin_lock_bh(&ctask->conn->session->lock);
--      __iscsi_get_ctask(ctask);
--      spin_unlock_bh(&ctask->conn->session->lock);
+-      return battery->device->status.battery_present;
+-}
+-inline char *acpi_battery_power_units(struct acpi_battery *battery)
+-{
+-      if (battery->flags.power_unit)
+-              return ACPI_BATTERY_UNITS_AMPS;
+-      else
+-              return ACPI_BATTERY_UNITS_WATTS;
 -}
 -
- static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask)
- {
-       if (atomic_dec_and_test(&ctask->refcount))
-               iscsi_complete_command(ctask);
- }
--static void iscsi_put_ctask(struct iscsi_cmd_task *ctask)
+-inline acpi_handle acpi_battery_handle(struct acpi_battery *battery)
 -{
--      spin_lock_bh(&ctask->conn->session->lock);
--      __iscsi_put_ctask(ctask);
--      spin_unlock_bh(&ctask->conn->session->lock);
+-      return battery->device->handle;
 -}
 -
- /**
-  * iscsi_cmd_rsp - SCSI Command Response processing
-  * @conn: iscsi connection
-@@ -235,21 +252,15 @@
-  * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and
-  * then completes the command and task.
-  **/
--static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
-+static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
-                             struct iscsi_cmd_task *ctask, char *data,
-                             int datalen)
- {
--      int rc;
-       struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr;
-       struct iscsi_session *session = conn->session;
-       struct scsi_cmnd *sc = ctask->sc;
+ /* --------------------------------------------------------------------------
+                                Battery Management
+    -------------------------------------------------------------------------- */
  
--      rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
--      if (rc) {
--              sc->result = DID_ERROR << 16;
--              goto out;
+-static void acpi_battery_check_result(struct acpi_battery *battery, int result)
+-{
+-      if (!battery)
+-              return;
+-
+-      if (result) {
+-              battery->flags.init_update = 1;
 -      }
+-}
 -
-+      iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
-       conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
+-static int acpi_battery_extract_package(struct acpi_battery *battery,
+-                                      union acpi_object *package,
+-                                      struct acpi_buffer *format,
+-                                      struct acpi_buffer *data,
+-                                      char *package_name)
+-{
+-      acpi_status status = AE_OK;
+-      struct acpi_buffer data_null = { 0, NULL };
+-
+-      status = acpi_extract_package(package, format, &data_null);
+-      if (status != AE_BUFFER_OVERFLOW) {
+-              ACPI_EXCEPTION((AE_INFO, status, "Extracting size %s",
+-                              package_name));
+-              return -ENODEV;
+-      }
+-
+-      if (data_null.length != data->length) {
+-              kfree(data->pointer);
+-              data->pointer = kzalloc(data_null.length, GFP_KERNEL);
+-              if (!data->pointer) {
+-                      ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()"));
+-                      return -ENOMEM;
+-              }
+-              data->length = data_null.length;
+-      }
+-
+-      status = acpi_extract_package(package, format, data);
+-      if (ACPI_FAILURE(status)) {
+-              ACPI_EXCEPTION((AE_INFO, status, "Extracting %s",
+-                              package_name));
+-              return -ENODEV;
+-      }
+-
+-      return 0;
+-}
+-
+-static int acpi_battery_get_status(struct acpi_battery *battery)
+-{
+-      int result = 0;
+-
+-      result = acpi_bus_get_status(battery->device);
+-      if (result) {
+-              ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
+-              return -ENODEV;
+-      }
+-      return result;
+-}
+-
+-static int acpi_battery_get_info(struct acpi_battery *battery)
++static int
++acpi_battery_get_info(struct acpi_battery *battery,
++                    struct acpi_battery_info **bif)
+ {
+       int result = 0;
+       acpi_status status = 0;
+@@ -220,20 +133,16 @@
+       struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF),
+               ACPI_BATTERY_FORMAT_BIF
+       };
++      struct acpi_buffer data = { 0, NULL };
+       union acpi_object *package = NULL;
+-      struct acpi_buffer *data = NULL;
+-      struct acpi_battery_info *bif = NULL;
  
-       sc->result = (DID_OK << 16) | rhdr->cmd_status;
-@@ -286,14 +297,14 @@
-       if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
-               int res_count = be32_to_cpu(rhdr->residual_count);
+-      battery->update_time[ACPI_BATTERY_INFO] = get_seconds();
  
--              if (res_count > 0 && res_count <= sc->request_bufflen)
--                      sc->resid = res_count;
-+              if (res_count > 0 && res_count <= scsi_bufflen(sc))
-+                      scsi_set_resid(sc, res_count);
-               else
-                       sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
-       } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW)
-               sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
-       else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW)
--              sc->resid = be32_to_cpu(rhdr->residual_count);
-+              scsi_set_resid(sc, be32_to_cpu(rhdr->residual_count));
+-      if (!acpi_battery_present(battery))
+-              return 0;
++      if (!battery || !bif)
++              return -EINVAL;
  
- out:
-       debug_scsi("done [sc %lx res %d itt 0x%x]\n",
-@@ -301,7 +312,6 @@
-       conn->scsirsp_pdus_cnt++;
+-      /* Evaluate _BIF */
++      /* Evalute _BIF */
  
-       __iscsi_put_ctask(ctask);
--      return rc;
- }
+-      status =
+-          acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL,
+-                               &buffer);
++      status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer);
+       if (ACPI_FAILURE(status)) {
+               ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
+               return -ENODEV;
+@@ -241,29 +150,41 @@
  
- static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
-@@ -381,7 +391,7 @@
-               switch(opcode) {
-               case ISCSI_OP_SCSI_CMD_RSP:
-                       BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
--                      rc = iscsi_scsi_cmd_rsp(conn, hdr, ctask, data,
-+                      iscsi_scsi_cmd_rsp(conn, hdr, ctask, data,
-                                               datalen);
-                       break;
-               case ISCSI_OP_SCSI_DATA_IN:
-@@ -405,11 +415,7 @@
-               debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n",
-                          opcode, conn->id, mtask->itt, datalen);
+       package = buffer.pointer;
  
--              rc = iscsi_check_assign_cmdsn(session,
--                                            (struct iscsi_nopin*)hdr);
--              if (rc)
--                      goto done;
+-      data = &battery->bif_data;
 -
-+              iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
-               switch(opcode) {
-               case ISCSI_OP_LOGOUT_RSP:
-                       if (datalen) {
-@@ -458,10 +464,7 @@
-                       break;
-               }
-       } else if (itt == ~0U) {
--              rc = iscsi_check_assign_cmdsn(session,
--                                           (struct iscsi_nopin*)hdr);
--              if (rc)
--                      goto done;
-+              iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
-               switch(opcode) {
-               case ISCSI_OP_NOOP_IN:
-@@ -491,7 +494,6 @@
-       } else
-               rc = ISCSI_ERR_BAD_ITT;
+       /* Extract Package Data */
  
--done:
-       return rc;
- }
- EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
-@@ -578,17 +580,47 @@
- }
- EXPORT_SYMBOL_GPL(iscsi_conn_failure);
+-      result =
+-          acpi_battery_extract_package(battery, package, &format, data,
+-                                       "_BIF");
+-      if (result)
++      status = acpi_extract_package(package, &format, &data);
++      if (status != AE_BUFFER_OVERFLOW) {
++              ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF"));
++              result = -ENODEV;
+               goto end;
++      }
  
-+static void iscsi_prep_mtask(struct iscsi_conn *conn,
-+                           struct iscsi_mgmt_task *mtask)
-+{
-+      struct iscsi_session *session = conn->session;
-+      struct iscsi_hdr *hdr = mtask->hdr;
-+      struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
-+
-+      if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) &&
-+          hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
-+              nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
-+      /*
-+       * pre-format CmdSN for outgoing PDU.
-+       */
-+      nop->cmdsn = cpu_to_be32(session->cmdsn);
-+      if (hdr->itt != RESERVED_ITT) {
-+              hdr->itt = build_itt(mtask->itt, conn->id, session->age);
-+              if (conn->c_stage == ISCSI_CONN_STARTED &&
-+                  !(hdr->opcode & ISCSI_OP_IMMEDIATE))
-+                      session->cmdsn++;
+-      end:
++      data.pointer = kzalloc(data.length, GFP_KERNEL);
++      if (!data.pointer) {
++              result = -ENOMEM;
++              goto end;
 +      }
 +
-+      if (session->tt->init_mgmt_task)
-+              session->tt->init_mgmt_task(conn, mtask);
-+
-+      debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
-+                 hdr->opcode, hdr->itt, mtask->data_count);
-+}
-+
- static int iscsi_xmit_mtask(struct iscsi_conn *conn)
- {
-       struct iscsi_hdr *hdr = conn->mtask->hdr;
-       int rc, was_logout = 0;
++      status = acpi_extract_package(package, &format, &data);
++      if (ACPI_FAILURE(status)) {
++              ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF"));
++              kfree(data.pointer);
++              result = -ENODEV;
++              goto end;
++      }
  
-+      spin_unlock_bh(&conn->session->lock);
-       if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) {
-               conn->session->state = ISCSI_STATE_IN_RECOVERY;
-               iscsi_block_session(session_to_cls(conn->session));
-               was_logout = 1;
-       }
-       rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask);
-+      spin_lock_bh(&conn->session->lock);
-       if (rc)
-               return rc;
++      end:
+       kfree(buffer.pointer);
  
-@@ -602,6 +634,45 @@
-       return 0;
+-      if (!result) {
+-              bif = data->pointer;
+-              battery->flags.power_unit = bif->power_unit;
+-      }
++      if (!result)
++              (*bif) = data.pointer;
+       return result;
  }
  
-+static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
-+{
-+      struct iscsi_session *session = conn->session;
-+
-+      /*
-+       * Check for iSCSI window and take care of CmdSN wrap-around
-+       */
-+      if (!iscsi_sna_lte(session->cmdsn, session->max_cmdsn)) {
-+              debug_scsi("iSCSI CmdSN closed. MaxCmdSN %u CmdSN %u\n",
-+                         session->max_cmdsn, session->cmdsn);
-+              return -ENOSPC;
-+      }
-+      return 0;
-+}
-+
-+static int iscsi_xmit_ctask(struct iscsi_conn *conn)
-+{
-+      struct iscsi_cmd_task *ctask = conn->ctask;
-+      int rc = 0;
-+
-+      /*
-+       * serialize with TMF AbortTask
-+       */
-+      if (ctask->state == ISCSI_TASK_ABORTING)
-+              goto done;
-+
-+      __iscsi_get_ctask(ctask);
-+      spin_unlock_bh(&conn->session->lock);
-+      rc = conn->session->tt->xmit_cmd_task(conn, ctask);
-+      spin_lock_bh(&conn->session->lock);
-+      __iscsi_put_ctask(ctask);
-+
-+done:
-+      if (!rc)
-+              /* done with this ctask */
-+              conn->ctask = NULL;
-+      return rc;
-+}
-+
- /**
-  * iscsi_data_xmit - xmit any command into the scheduled connection
-  * @conn: iscsi connection
-@@ -613,106 +684,79 @@
-  **/
- static int iscsi_data_xmit(struct iscsi_conn *conn)
+-static int acpi_battery_get_state(struct acpi_battery *battery)
++static int
++acpi_battery_get_status(struct acpi_battery *battery,
++                      struct acpi_battery_status **bst)
  {
--      struct iscsi_transport *tt;
-       int rc = 0;
+       int result = 0;
+       acpi_status status = 0;
+@@ -271,19 +192,16 @@
+       struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST),
+               ACPI_BATTERY_FORMAT_BST
+       };
++      struct acpi_buffer data = { 0, NULL };
+       union acpi_object *package = NULL;
+-      struct acpi_buffer *data = NULL;
  
-+      spin_lock_bh(&conn->session->lock);
-       if (unlikely(conn->suspend_tx)) {
-               debug_scsi("conn %d Tx suspended!\n", conn->id);
-+              spin_unlock_bh(&conn->session->lock);
-               return -ENODATA;
-       }
--      tt = conn->session->tt;
--
--      /*
--       * Transmit in the following order:
--       *
--       * 1) un-finished xmit (ctask or mtask)
--       * 2) immediate control PDUs
--       * 3) write data
--       * 4) SCSI commands
--       * 5) non-immediate control PDUs
--       *
--       * No need to lock around __kfifo_get as long as
--       * there's one producer and one consumer.
--       */
+-      battery->update_time[ACPI_BATTERY_STATE] = get_seconds();
+-      if (!acpi_battery_present(battery))
+-              return 0;
++      if (!battery || !bst)
++              return -EINVAL;
+-      /* Evaluate _BST */
++      /* Evalute _BST */
+-      status =
+-          acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL,
+-                               &buffer);
++      status = acpi_evaluate_object(battery->device->handle, "_BST", NULL, &buffer);
+       if (ACPI_FAILURE(status)) {
+               ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
+               return -ENODEV;
+@@ -291,49 +209,55 @@
+       package = buffer.pointer;
+-      data = &battery->bst_data;
 -
--      BUG_ON(conn->ctask && conn->mtask);
+       /* Extract Package Data */
  
-       if (conn->ctask) {
--              iscsi_get_ctask(conn->ctask);
--              rc = tt->xmit_cmd_task(conn, conn->ctask);
--              iscsi_put_ctask(conn->ctask);
-+              rc = iscsi_xmit_ctask(conn);
-               if (rc)
-                       goto again;
--              /* done with this in-progress ctask */
--              conn->ctask = NULL;
-       }
+-      result =
+-          acpi_battery_extract_package(battery, package, &format, data,
+-                                       "_BST");
+-      if (result)
++      status = acpi_extract_package(package, &format, &data);
++      if (status != AE_BUFFER_OVERFLOW) {
++              ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST"));
++              result = -ENODEV;
++              goto end;
++      }
 +
-       if (conn->mtask) {
-               rc = iscsi_xmit_mtask(conn);
-               if (rc)
-                       goto again;
-       }
++      data.pointer = kzalloc(data.length, GFP_KERNEL);
++      if (!data.pointer) {
++              result = -ENOMEM;
++              goto end;
++      }
++
++      status = acpi_extract_package(package, &format, &data);
++      if (ACPI_FAILURE(status)) {
++              ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST"));
++              kfree(data.pointer);
++              result = -ENODEV;
+               goto end;
++      }
  
--      /* process immediate first */
--        if (unlikely(__kfifo_len(conn->immqueue))) {
--              while (__kfifo_get(conn->immqueue, (void*)&conn->mtask,
-+      /*
-+       * process mgmt pdus like nops before commands since we should
-+       * only have one nop-out as a ping from us and targets should not
-+       * overflow us with nop-ins
-+       */
-+check_mgmt:
-+      while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
-                                  sizeof(void*))) {
--                      spin_lock_bh(&conn->session->lock);
--                      list_add_tail(&conn->mtask->running,
--                                    &conn->mgmt_run_list);
--                      spin_unlock_bh(&conn->session->lock);
-+              iscsi_prep_mtask(conn, conn->mtask);
-+              list_add_tail(&conn->mtask->running, &conn->mgmt_run_list);
-                       rc = iscsi_xmit_mtask(conn);
-                       if (rc)
-                               goto again;
-               }
--      }
+       end:
+       kfree(buffer.pointer);
  
-       /* process command queue */
--      spin_lock_bh(&conn->session->lock);
-       while (!list_empty(&conn->xmitqueue)) {
-+              rc = iscsi_check_cmdsn_window_closed(conn);
-+              if (rc) {
-+                      spin_unlock_bh(&conn->session->lock);
-+                      return rc;
-+              }
-               /*
-                * iscsi tcp may readd the task to the xmitqueue to send
-                * write data
-                */
-               conn->ctask = list_entry(conn->xmitqueue.next,
-                                        struct iscsi_cmd_task, running);
-+              if (conn->ctask->state == ISCSI_TASK_PENDING) {
-+                      iscsi_prep_scsi_cmd_pdu(conn->ctask);
-+                      conn->session->tt->init_cmd_task(conn->ctask);
-+              }
-               conn->ctask->state = ISCSI_TASK_RUNNING;
-               list_move_tail(conn->xmitqueue.next, &conn->run_list);
--              __iscsi_get_ctask(conn->ctask);
--              spin_unlock_bh(&conn->session->lock);
--
--              rc = tt->xmit_cmd_task(conn, conn->ctask);
--
--              spin_lock_bh(&conn->session->lock);
--              __iscsi_put_ctask(conn->ctask);
--              if (rc) {
--                      spin_unlock_bh(&conn->session->lock);
--                      goto again;
--              }
--      }
--      spin_unlock_bh(&conn->session->lock);
--      /* done with this ctask */
--      conn->ctask = NULL;
--
--      /* process the rest control plane PDUs, if any */
--        if (unlikely(__kfifo_len(conn->mgmtqueue))) {
--              while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
--                                 sizeof(void*))) {
--                      spin_lock_bh(&conn->session->lock);
--                      list_add_tail(&conn->mtask->running,
--                                    &conn->mgmt_run_list);
--                      spin_unlock_bh(&conn->session->lock);
--                      rc = iscsi_xmit_mtask(conn);
-+              rc = iscsi_xmit_ctask(conn);
-                       if (rc)
-                               goto again;
-+              /*
-+               * we could continuously get new ctask requests so
-+               * we need to check the mgmt queue for nops that need to
-+               * be sent to aviod starvation
-+               */
-+              if (__kfifo_len(conn->mgmtqueue))
-+                      goto check_mgmt;
-               }
--      }
+-      return result;
+-}
 -
-+      spin_unlock_bh(&conn->session->lock);
-       return -ENODATA;
+-static int acpi_battery_get_alarm(struct acpi_battery *battery)
+-{
+-      battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();
++      if (!result)
++              (*bst) = data.pointer;
  
- again:
-       if (unlikely(conn->suspend_tx))
--              return -ENODATA;
--
-+              rc = -ENODATA;
-+      spin_unlock_bh(&conn->session->lock);
-       return rc;
+-      return 0;
++      return result;
  }
  
-@@ -724,11 +768,9 @@
-       /*
-        * serialize Xmit worker on a per-connection basis.
-        */
--      mutex_lock(&conn->xmitmutex);
-       do {
-               rc = iscsi_data_xmit(conn);
-       } while (rc >= 0 || rc == -EAGAIN);
--      mutex_unlock(&conn->xmitmutex);
- }
+-static int acpi_battery_set_alarm(struct acpi_battery *battery,
+-                                unsigned long alarm)
++static int
++acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
+ {
+       acpi_status status = 0;
+       union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+       struct acpi_object_list arg_list = { 1, &arg0 };
  
- enum {
-@@ -786,20 +828,23 @@
-               goto fault;
-       }
+-      battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();
  
--      /*
--       * Check for iSCSI window and take care of CmdSN wrap-around
--       */
--      if ((int)(session->max_cmdsn - session->cmdsn) < 0) {
--              reason = FAILURE_WINDOW_CLOSED;
--              goto reject;
--      }
--
-       conn = session->leadconn;
-       if (!conn) {
-               reason = FAILURE_SESSION_FREED;
-               goto fault;
-       }
+-      if (!acpi_battery_present(battery))
+-              return -ENODEV;
++      if (!battery)
++              return -EINVAL;
  
-+      /*
-+       * We check this here and in data xmit, because if we get to the point
-+       * that this check is hitting the window then we have enough IO in
-+       * flight and enough IO waiting to be transmitted it is better
-+       * to let the scsi/block layer queue up.
-+       */
-+      if (iscsi_check_cmdsn_window_closed(conn)) {
-+              reason = FAILURE_WINDOW_CLOSED;
-+              goto reject;
-+      }
-+
-       if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask,
-                        sizeof(void*))) {
-               reason = FAILURE_OOM;
-@@ -814,18 +859,8 @@
-       ctask->conn = conn;
-       ctask->sc = sc;
-       INIT_LIST_HEAD(&ctask->running);
--      ctask->total_length = sc->request_bufflen;
--      iscsi_prep_scsi_cmd_pdu(ctask);
--
--      session->tt->init_cmd_task(ctask);
+-      if (!battery->flags.alarm_present)
++      if (!battery->flags.alarm)
+               return -ENODEV;
  
-       list_add_tail(&ctask->running, &conn->xmitqueue);
--      debug_scsi(
--             "ctask enq [%s cid %d sc %p cdb 0x%x itt 0x%x len %d cmdsn %d "
--              "win %d]\n",
--              sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
--              conn->id, sc, sc->cmnd[0], ctask->itt, sc->request_bufflen,
--              session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
-       spin_unlock(&session->lock);
+       arg0.integer.value = alarm;
  
-       scsi_queue_work(host, &conn->xmitwork);
-@@ -841,7 +876,7 @@
-       printk(KERN_ERR "iscsi: cmd 0x%x is not queued (%d)\n",
-              sc->cmnd[0], reason);
-       sc->result = (DID_NO_CONNECT << 16);
--      sc->resid = sc->request_bufflen;
-+      scsi_set_resid(sc, scsi_bufflen(sc));
-       sc->scsi_done(sc);
+-      status =
+-          acpi_evaluate_object(acpi_battery_handle(battery), "_BTP",
+-                               &arg_list, NULL);
++      status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+@@ -344,114 +268,65 @@
        return 0;
  }
-@@ -856,19 +891,16 @@
- }
- EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
  
--static int
--iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
-+static struct iscsi_mgmt_task *
-+__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
-                       char *data, uint32_t data_size)
+-static int acpi_battery_init_alarm(struct acpi_battery *battery)
++static int acpi_battery_check(struct acpi_battery *battery)
  {
-       struct iscsi_session *session = conn->session;
--      struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
-       struct iscsi_mgmt_task *mtask;
+       int result = 0;
+       acpi_status status = AE_OK;
+       acpi_handle handle = NULL;
+-      struct acpi_battery_info *bif = battery->bif_data.pointer;
+-      unsigned long alarm = battery->alarm;
+-
+-      /* See if alarms are supported, and if so, set default */
+-
+-      status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle);
+-      if (ACPI_SUCCESS(status)) {
+-              battery->flags.alarm_present = 1;
+-              if (!alarm && bif) {
+-                      alarm = bif->design_capacity_warning;
+-              }
+-              result = acpi_battery_set_alarm(battery, alarm);
+-              if (result)
+-                      goto end;
+-      } else {
+-              battery->flags.alarm_present = 0;
+-      }
++      struct acpi_device *device = NULL;
++      struct acpi_battery_info *bif = NULL;
  
--      spin_lock_bh(&session->lock);
--      if (session->state == ISCSI_STATE_TERMINATE) {
--              spin_unlock_bh(&session->lock);
--              return -EPERM;
+-      end:
+-              return result;
+-}
++      if (!battery)
++              return -EINVAL;
+-static int acpi_battery_init_update(struct acpi_battery *battery)
+-{
+-      int result = 0;
++      device = battery->device;
+-      result = acpi_battery_get_status(battery);
++      result = acpi_bus_get_status(device);
+       if (result)
+               return result;
+-      battery->flags.battery_present_prev = acpi_battery_present(battery);
++      /* Insertion? */
+-      if (acpi_battery_present(battery)) {
+-              result = acpi_battery_get_info(battery);
+-              if (result)
+-                      return result;
+-              result = acpi_battery_get_state(battery);
+-              if (result)
+-                      return result;
++      if (!battery->flags.present && device->status.battery_present) {
+-              acpi_battery_init_alarm(battery);
 -      }
-+      if (session->state == ISCSI_STATE_TERMINATE)
-+              return NULL;
++              ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n"));
++              /* Evalute _BIF to get certain static information */
 +
-       if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
-           hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
-               /*
-@@ -882,27 +914,11 @@
-               BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
-               BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
++              result = acpi_battery_get_info(battery, &bif);
++              if (result)
+       return result;
+-}
  
--              nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
-               if (!__kfifo_get(session->mgmtpool.queue,
--                               (void*)&mtask, sizeof(void*))) {
--                      spin_unlock_bh(&session->lock);
--                      return -ENOSPC;
--              }
-+                               (void*)&mtask, sizeof(void*)))
-+                      return NULL;
-       }
+-static int acpi_battery_update(struct acpi_battery *battery,
+-                             int update, int *update_result_ptr)
+-{
+-      int result = 0;
+-      int update_result = ACPI_BATTERY_NONE_UPDATE;
++              battery->flags.power_unit = bif->power_unit;
++              battery->trips.warning = bif->design_capacity_warning;
++              battery->trips.low = bif->design_capacity_low;
++              kfree(bif);
  
--      /*
--       * pre-format CmdSN for outgoing PDU.
--       */
--      if (hdr->itt != RESERVED_ITT) {
--              hdr->itt = build_itt(mtask->itt, conn->id, session->age);
--              nop->cmdsn = cpu_to_be32(session->cmdsn);
--              if (conn->c_stage == ISCSI_CONN_STARTED &&
--                  !(hdr->opcode & ISCSI_OP_IMMEDIATE))
--                      session->cmdsn++;
--      } else
--              /* do not advance CmdSN */
--              nop->cmdsn = cpu_to_be32(session->cmdsn);
--
-       if (data_size) {
-               memcpy(mtask->data, data, data_size);
-               mtask->data_count = data_size;
-@@ -911,38 +927,23 @@
+-      if (!acpi_battery_present(battery)) {
+-              update = 1;
+-      }
++              /* See if alarms are supported, and if so, set default */
  
-       INIT_LIST_HEAD(&mtask->running);
-       memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
--      if (session->tt->init_mgmt_task)
--              session->tt->init_mgmt_task(conn, mtask, data, data_size);
--      spin_unlock_bh(&session->lock);
--
--      debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
--                 hdr->opcode, hdr->itt, data_size);
--
--      /*
--       * since send_pdu() could be called at least from two contexts,
--       * we need to serialize __kfifo_put, so we don't have to take
--       * additional lock on fast data-path
--       */
--        if (hdr->opcode & ISCSI_OP_IMMEDIATE)
--              __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*));
--      else
-               __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
--
--      scsi_queue_work(session->host, &conn->xmitwork);
--      return 0;
-+      return mtask;
- }
+-      if (battery->flags.init_update) {
+-              result = acpi_battery_init_update(battery);
+-              if (result)
+-                      goto end;
+-              update_result = ACPI_BATTERY_INIT_UPDATE;
+-      } else if (update) {
+-              result = acpi_battery_get_status(battery);
+-              if (result)
+-                      goto end;
+-              if ((!battery->flags.battery_present_prev & acpi_battery_present(battery))
+-                  || (battery->flags.battery_present_prev & !acpi_battery_present(battery))) {
+-                      result = acpi_battery_init_update(battery);
+-                      if (result)
+-                              goto end;
+-                      update_result = ACPI_BATTERY_INIT_UPDATE;
+-              } else {
+-                      update_result = ACPI_BATTERY_EASY_UPDATE;
++              status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
++              if (ACPI_SUCCESS(status)) {
++                      battery->flags.alarm = 1;
++                      acpi_battery_set_alarm(battery, battery->trips.warning);
+               }
      }
  
- int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
-                       char *data, uint32_t data_size)
- {
-       struct iscsi_conn *conn = cls_conn->dd_data;
--      int rc;
--
--      mutex_lock(&conn->xmitmutex);
--      rc = iscsi_conn_send_generic(conn, hdr, data, data_size);
--      mutex_unlock(&conn->xmitmutex);
-+      struct iscsi_session *session = conn->session;
-+      int err = 0;
+-      end:
++      /* Removal? */
  
--      return rc;
-+      spin_lock_bh(&session->lock);
-+      if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
-+              err = -EPERM;
-+      spin_unlock_bh(&session->lock);
-+      scsi_queue_work(session->host, &conn->xmitwork);
-+      return err;
- }
- EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
+-      battery->flags.init_update = (result != 0);
++      else if (battery->flags.present && !device->status.battery_present) {
++              ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n"));
++      }
  
-@@ -1027,14 +1028,12 @@
-       spin_unlock(&session->lock);
+-      *update_result_ptr = update_result;
++      battery->flags.present = device->status.battery_present;
+       return result;
  }
  
--/* must be called with the mutex lock */
- static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
-                                struct iscsi_cmd_task *ctask)
+-static void acpi_battery_notify_update(struct acpi_battery *battery)
++static void acpi_battery_check_present(struct acpi_battery *battery)
  {
-       struct iscsi_conn *conn = ctask->conn;
-       struct iscsi_session *session = conn->session;
-       struct iscsi_tm *hdr = &conn->tmhdr;
--      int rc;
-       /*
-        * ctask timed out but session is OK requests must be serialized.
-@@ -1047,32 +1046,27 @@
-       hdr->rtt = ctask->hdr->itt;
-       hdr->refcmdsn = ctask->hdr->cmdsn;
--      rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr,
-+      ctask->mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
-                                    NULL, 0);
--      if (rc) {
-+      if (!ctask->mtask) {
-               iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
--              debug_scsi("abort sent failure [itt 0x%x] %d\n", ctask->itt,
--                         rc);
--              return rc;
-+              debug_scsi("abort sent failure [itt 0x%x]\n", ctask->itt);
-+              return -EPERM;
+-      acpi_battery_get_status(battery);
+-
+-      if (battery->flags.init_update) {
+-              return;
+-      }
+-
+-      if ((!battery->flags.battery_present_prev &
+-           acpi_battery_present(battery)) ||
+-          (battery->flags.battery_present_prev &
+-           !acpi_battery_present(battery))) {
+-              battery->flags.init_update = 1;
+-      } else {
+-              battery->flags.update[ACPI_BATTERY_INFO] = 1;
+-              battery->flags.update[ACPI_BATTERY_STATE] = 1;
+-              battery->flags.update[ACPI_BATTERY_ALARM] = 1;
++      if (!battery->flags.present) {
++              acpi_battery_check(battery);
        }
-+      ctask->state = ISCSI_TASK_ABORTING;
+ }
  
-       debug_scsi("abort sent [itt 0x%x]\n", ctask->itt);
+@@ -460,33 +335,37 @@
+    -------------------------------------------------------------------------- */
  
--      spin_lock_bh(&session->lock);
--      ctask->mtask = (struct iscsi_mgmt_task *)
--                      session->mgmt_cmds[get_itt(hdr->itt) -
--                                      ISCSI_MGMT_ITT_OFFSET];
+ static struct proc_dir_entry *acpi_battery_dir;
 -
-       if (conn->tmabort_state == TMABORT_INITIAL) {
-               conn->tmfcmd_pdus_cnt++;
--              conn->tmabort_timer.expires = 10*HZ + jiffies;
-+              conn->tmabort_timer.expires = 20*HZ + jiffies;
-               conn->tmabort_timer.function = iscsi_tmabort_timedout;
-               conn->tmabort_timer.data = (unsigned long)ctask;
-               add_timer(&conn->tmabort_timer);
-               debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt);
+-static int acpi_battery_print_info(struct seq_file *seq, int result)
++static int acpi_battery_read_info(struct seq_file *seq, void *offset)
+ {
++      int result = 0;
+       struct acpi_battery *battery = seq->private;
+       struct acpi_battery_info *bif = NULL;
+       char *units = "?";
+-      if (result)
++
++      if (!battery)
+               goto end;
+-      if (acpi_battery_present(battery))
++      acpi_battery_check_present(battery);
++
++      if (battery->flags.present)
+               seq_printf(seq, "present:                 yes\n");
+       else {
+               seq_printf(seq, "present:                 no\n");
+               goto end;
        }
-       spin_unlock_bh(&session->lock);
--      mutex_unlock(&conn->xmitmutex);
-+      scsi_queue_work(session->host, &conn->xmitwork);
  
-       /*
-        * block eh thread until:
-@@ -1089,13 +1083,12 @@
-       if (signal_pending(current))
-               flush_signals(current);
-       del_timer_sync(&conn->tmabort_timer);
--
--      mutex_lock(&conn->xmitmutex);
-+      spin_lock_bh(&session->lock);
-       return 0;
- }
+-      bif = battery->bif_data.pointer;
+-      if (!bif) {
+-              ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BIF buffer is NULL"));
+-              result = -ENODEV;
++      /* Battery Info (_BIF) */
++
++      result = acpi_battery_get_info(battery, &bif);
++      if (result || !bif) {
++              seq_printf(seq, "ERROR: Unable to read battery information\n");
+               goto end;
      }
  
- /*
-- * xmit mutex and session lock must be held
-+ * session lock must be held
-  */
- static struct iscsi_mgmt_task *
- iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt)
-@@ -1127,7 +1120,7 @@
-       if (!ctask->mtask)
-               return -EINVAL;
+-      /* Battery Units */
+-
+-      units = acpi_battery_power_units(battery);
++      units =
++          bif->
++          power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
  
--      if (!iscsi_remove_mgmt_task(conn->immqueue, ctask->mtask->itt))
-+      if (!iscsi_remove_mgmt_task(conn->mgmtqueue, ctask->mtask->itt))
-               list_del(&ctask->mtask->running);
-       __kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask,
-                   sizeof(void*));
-@@ -1136,7 +1129,7 @@
- }
+       if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+               seq_printf(seq, "design capacity:         unknown\n");
+@@ -517,6 +396,7 @@
+       else
+               seq_printf(seq, "design voltage:          %d mV\n",
+                          (u32) bif->design_voltage);
++
+       seq_printf(seq, "design capacity warning: %d %sh\n",
+                  (u32) bif->design_capacity_warning, units);
+       seq_printf(seq, "design capacity low:     %d %sh\n",
+@@ -531,39 +411,49 @@
+       seq_printf(seq, "OEM info:                %s\n", bif->oem_info);
  
- /*
-- * session lock and xmitmutex must be held
-+ * session lock must be held
-  */
- static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
-                        int err)
-@@ -1147,11 +1140,14 @@
-       if (!sc)
-               return;
+       end:
++      kfree(bif);
  
-+      if (ctask->state != ISCSI_TASK_PENDING)
-       conn->session->tt->cleanup_cmd_task(conn, ctask);
-       iscsi_ctask_mtask_cleanup(ctask);
+-      if (result)
+-              seq_printf(seq, "ERROR: Unable to read battery info\n");
++      return 0;
++}
  
-       sc->result = err;
--      sc->resid = sc->request_bufflen;
-+      scsi_set_resid(sc, scsi_bufflen(sc));
-+      if (conn->ctask == ctask)
-+              conn->ctask = NULL;
-       /* release ref from queuecommand */
-       __iscsi_put_ctask(ctask);
+-      return result;
++static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
++{
++      return single_open(file, acpi_battery_read_info, PDE(inode)->data);
  }
-@@ -1179,7 +1175,6 @@
-       conn->eh_abort_cnt++;
-       debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
  
--      mutex_lock(&conn->xmitmutex);
-       spin_lock_bh(&session->lock);
+-static int acpi_battery_print_state(struct seq_file *seq, int result)
++static int acpi_battery_read_state(struct seq_file *seq, void *offset)
+ {
++      int result = 0;
+       struct acpi_battery *battery = seq->private;
+-      struct acpi_battery_state *bst = NULL;
++      struct acpi_battery_status *bst = NULL;
+       char *units = "?";
  
-       /*
-@@ -1192,9 +1187,8 @@
+-      if (result)
++
++      if (!battery)
+               goto end;
  
-       /* ctask completed before time out */
-       if (!ctask->sc) {
--              spin_unlock_bh(&session->lock);
-               debug_scsi("sc completed while abort in progress\n");
--              goto success_rel_mutex;
-+              goto success;
+-      if (acpi_battery_present(battery))
++      acpi_battery_check_present(battery);
++
++      if (battery->flags.present)
+               seq_printf(seq, "present:                 yes\n");
+       else {
+               seq_printf(seq, "present:                 no\n");
+               goto end;
        }
  
-       /* what should we do here ? */
-@@ -1204,15 +1198,13 @@
-               goto failed;
-       }
+-      bst = battery->bst_data.pointer;
+-      if (!bst) {
+-              ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BST buffer is NULL"));
+-              result = -ENODEV;
+-              goto end;
+-      }
+-
+       /* Battery Units */
  
--      if (ctask->state == ISCSI_TASK_PENDING)
--              goto success_cleanup;
-+      if (ctask->state == ISCSI_TASK_PENDING) {
-+              fail_command(conn, ctask, DID_ABORT << 16);
-+              goto success;
+-      units = acpi_battery_power_units(battery);
++      units =
++          battery->flags.
++          power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
++
++      /* Battery Status (_BST) */
++
++      result = acpi_battery_get_status(battery, &bst);
++      if (result || !bst) {
++              seq_printf(seq, "ERROR: Unable to read battery status\n");
++              goto end;
 +      }
  
-       conn->tmabort_state = TMABORT_INITIAL;
--
--      spin_unlock_bh(&session->lock);
-       rc = iscsi_exec_abort_task(sc, ctask);
--      spin_lock_bh(&session->lock);
--
-       if (rc || sc->SCp.phase != session->age ||
-           session->state != ISCSI_STATE_LOGGED_IN)
-               goto failed;
-@@ -1220,45 +1212,44 @@
+       if (!(bst->state & 0x04))
+               seq_printf(seq, "capacity state:          ok\n");
+@@ -600,43 +490,48 @@
+                          (u32) bst->present_voltage);
  
-       switch (conn->tmabort_state) {
-       case TMABORT_SUCCESS:
--              goto success_cleanup;
-+              spin_unlock_bh(&session->lock);
-+              /*
-+               * clean up task if aborted. grab the recv lock as a writer
-+               */
-+              write_lock_bh(conn->recv_lock);
-+              spin_lock(&session->lock);
-+              fail_command(conn, ctask, DID_ABORT << 16);
-+              spin_unlock(&session->lock);
-+              write_unlock_bh(conn->recv_lock);
-+              /*
-+               * make sure xmit thread is not still touching the
-+               * ctask/scsi_cmnd
-+               */
-+              scsi_flush_work(session->host);
-+              goto success_unlocked;
-       case TMABORT_NOT_FOUND:
-               if (!ctask->sc) {
-                       /* ctask completed before tmf abort response */
--                      spin_unlock_bh(&session->lock);
-                       debug_scsi("sc completed while abort in progress\n");
--                      goto success_rel_mutex;
-+                      goto success;
-               }
-               /* fall through */
-       default:
-               /* timedout or failed */
-               spin_unlock_bh(&session->lock);
-               iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
--              spin_lock_bh(&session->lock);
--              goto failed;
-+              goto failed_unlocked;
-       }
+       end:
++      kfree(bst);
  
--success_cleanup:
--      debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
-+success:
-       spin_unlock_bh(&session->lock);
--
--      /*
--       * clean up task if aborted. we have the xmitmutex so grab
--       * the recv lock as a writer
--       */
--      write_lock_bh(conn->recv_lock);
--      spin_lock(&session->lock);
--      fail_command(conn, ctask, DID_ABORT << 16);
--      spin_unlock(&session->lock);
--      write_unlock_bh(conn->recv_lock);
--
--success_rel_mutex:
--      mutex_unlock(&conn->xmitmutex);
-+success_unlocked:
-+      debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
-       return SUCCESS;
+-      if (result) {
+-              seq_printf(seq, "ERROR: Unable to read battery state\n");
+-      }
++      return 0;
++}
  
- failed:
-       spin_unlock_bh(&session->lock);
--      mutex_unlock(&conn->xmitmutex);
--
-+failed_unlocked:
-       debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
-       return FAILED;
+-      return result;
++static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
++{
++      return single_open(file, acpi_battery_read_state, PDE(inode)->data);
  }
-@@ -1339,6 +1330,10 @@
-  * iscsi_session_setup - create iscsi cls session and host and session
-  * @scsit: scsi transport template
-  * @iscsit: iscsi transport template
-+ * @cmds_max: scsi host can queue
-+ * @qdepth: scsi host cmds per lun
-+ * @cmd_task_size: LLD ctask private data size
-+ * @mgmt_task_size: LLD mtask private data size
-  * @initial_cmdsn: initial CmdSN
-  * @hostno: host no allocated
-  *
-@@ -1348,6 +1343,7 @@
- struct iscsi_cls_session *
- iscsi_session_setup(struct iscsi_transport *iscsit,
-                   struct scsi_transport_template *scsit,
-+                  uint16_t cmds_max, uint16_t qdepth,
-                   int cmd_task_size, int mgmt_task_size,
-                   uint32_t initial_cmdsn, uint32_t *hostno)
+-static int acpi_battery_print_alarm(struct seq_file *seq, int result)
++static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
  {
-@@ -1356,11 +1352,32 @@
-       struct iscsi_cls_session *cls_session;
-       int cmd_i;
+       struct acpi_battery *battery = seq->private;
+       char *units = "?";
  
-+      if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
-+              if (qdepth != 0)
-+                      printk(KERN_ERR "iscsi: invalid queue depth of %d. "
-+                            "Queue depth must be between 1 and %d.\n",
-+                            qdepth, ISCSI_MAX_CMD_PER_LUN);
-+              qdepth = ISCSI_DEF_CMD_PER_LUN;
-+      }
+-      if (result)
 +
-+      if (cmds_max < 2 || (cmds_max & (cmds_max - 1)) ||
-+          cmds_max >= ISCSI_MGMT_ITT_OFFSET) {
-+              if (cmds_max != 0)
-+                      printk(KERN_ERR "iscsi: invalid can_queue of %d. "
-+                             "can_queue must be a power of 2 and between "
-+                             "2 and %d - setting to %d.\n", cmds_max,
-+                             ISCSI_MGMT_ITT_OFFSET, ISCSI_DEF_XMIT_CMDS_MAX);
-+              cmds_max = ISCSI_DEF_XMIT_CMDS_MAX;
-+      }
++      if (!battery)
+               goto end;
+-      if (!acpi_battery_present(battery)) {
++      acpi_battery_check_present(battery);
 +
-       shost = scsi_host_alloc(iscsit->host_template,
-                               hostdata_privsize(sizeof(*session)));
-       if (!shost)
-               return NULL;
++      if (!battery->flags.present) {
+               seq_printf(seq, "present:                 no\n");
+               goto end;
+       }
  
-+      /* the iscsi layer takes one task for reserve */
-+      shost->can_queue = cmds_max - 1;
-+      shost->cmd_per_lun = qdepth;
-       shost->max_id = 1;
-       shost->max_channel = 0;
-       shost->max_lun = iscsit->max_lun;
-@@ -1374,7 +1391,7 @@
-       session->host = shost;
-       session->state = ISCSI_STATE_FREE;
-       session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
--      session->cmds_max = ISCSI_XMIT_CMDS_MAX;
-+      session->cmds_max = cmds_max;
-       session->cmdsn = initial_cmdsn;
-       session->exp_cmdsn = initial_cmdsn + 1;
-       session->max_cmdsn = initial_cmdsn + 1;
-@@ -1461,7 +1478,14 @@
-       iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
-       iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+       /* Battery Units */
  
-+      kfree(session->password);
-+      kfree(session->password_in);
-+      kfree(session->username);
-+      kfree(session->username_in);
-       kfree(session->targetname);
-+      kfree(session->netdev);
-+      kfree(session->hwaddress);
-+      kfree(session->initiatorname);
+-      units = acpi_battery_power_units(battery);
++      units =
++          battery->flags.
++          power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
++
++      /* Battery Alarm */
  
-       iscsi_destroy_session(cls_session);
-       scsi_host_put(shost);
-@@ -1499,11 +1523,6 @@
-       INIT_LIST_HEAD(&conn->xmitqueue);
+       seq_printf(seq, "alarm:                   ");
+       if (!battery->alarm)
+               seq_printf(seq, "unsupported\n");
+       else
+-              seq_printf(seq, "%lu %sh\n", battery->alarm, units);
++              seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units);
  
-       /* initialize general immediate & non-immediate PDU commands queue */
--      conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
--                                      GFP_KERNEL, NULL);
--      if (conn->immqueue == ERR_PTR(-ENOMEM))
--              goto immqueue_alloc_fail;
+       end:
 -
-       conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
-                                       GFP_KERNEL, NULL);
-       if (conn->mgmtqueue == ERR_PTR(-ENOMEM))
-@@ -1527,7 +1546,6 @@
-       conn->login_mtask->data = conn->data = data;
-       init_timer(&conn->tmabort_timer);
--      mutex_init(&conn->xmitmutex);
-       init_waitqueue_head(&conn->ehwait);
-       return cls_conn;
-@@ -1538,8 +1556,6 @@
- login_mtask_alloc_fail:
-       kfifo_free(conn->mgmtqueue);
- mgmtqueue_alloc_fail:
--      kfifo_free(conn->immqueue);
--immqueue_alloc_fail:
-       iscsi_destroy_conn(cls_conn);
-       return NULL;
+-      if (result)
+-              seq_printf(seq, "ERROR: Unable to read battery alarm\n");
+-
+-      return result;
++      return 0;
  }
-@@ -1558,10 +1574,8 @@
-       struct iscsi_session *session = conn->session;
-       unsigned long flags;
  
--      set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
--      mutex_lock(&conn->xmitmutex);
--
-       spin_lock_bh(&session->lock);
-+      set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
-       conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
-       if (session->leadconn == conn) {
-               /*
-@@ -1572,8 +1586,6 @@
-       }
-       spin_unlock_bh(&session->lock);
+ static ssize_t
+@@ -648,113 +543,27 @@
+       char alarm_string[12] = { '\0' };
+       struct seq_file *m = file->private_data;
+       struct acpi_battery *battery = m->private;
+-      int update_result = ACPI_BATTERY_NONE_UPDATE;
++
+       if (!battery || (count > sizeof(alarm_string) - 1))
+               return -EINVAL;
  
--      mutex_unlock(&conn->xmitmutex);
+-      mutex_lock(&battery->mutex);
 -
-       /*
-        * Block until all in-progress commands for this connection
-        * time out or fail.
-@@ -1610,7 +1622,6 @@
-       }
-       spin_unlock_bh(&session->lock);
+-      result = acpi_battery_update(battery, 1, &update_result);
+-      if (result) {
+-              result = -ENODEV;
+-              goto end;
+-      }
++      acpi_battery_check_present(battery);
  
--      kfifo_free(conn->immqueue);
-       kfifo_free(conn->mgmtqueue);
+-      if (!acpi_battery_present(battery)) {
+-              result = -ENODEV;
+-              goto end;
+-      }
++      if (!battery->flags.present)
++              return -ENODEV;
  
-       iscsi_destroy_conn(cls_conn);
-@@ -1671,8 +1682,7 @@
-       struct iscsi_mgmt_task *mtask, *tmp;
+-      if (copy_from_user(alarm_string, buffer, count)) {
+-              result = -EFAULT;
+-              goto end;
+-      }
++      if (copy_from_user(alarm_string, buffer, count))
++              return -EFAULT;
  
-       /* handle pending */
--      while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) ||
--             __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
-+      while (__kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
-               if (mtask == conn->login_mtask)
-                       continue;
-               debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt);
-@@ -1742,12 +1752,12 @@
-       conn->c_stage = ISCSI_CONN_STOPPED;
-       set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
-       spin_unlock_bh(&session->lock);
-+      scsi_flush_work(session->host);
+       alarm_string[count] = '\0';
  
-       write_lock_bh(conn->recv_lock);
-       set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
-       write_unlock_bh(conn->recv_lock);
+       result = acpi_battery_set_alarm(battery,
+                                       simple_strtoul(alarm_string, NULL, 0));
+       if (result)
+-              goto end;
+-
+-      end:
+-
+-      acpi_battery_check_result(battery, result);
+-
+-      if (!result)
+-              result = count;
+-
+-      mutex_unlock(&battery->mutex);
+-
+               return result;
+-}
+-
+-typedef int(*print_func)(struct seq_file *seq, int result);
+-typedef int(*get_func)(struct acpi_battery *battery);
+-
+-static struct acpi_read_mux {
+-      print_func print;
+-      get_func get;
+-} acpi_read_funcs[ACPI_BATTERY_NUMFILES] = {
+-      {.get = acpi_battery_get_info, .print = acpi_battery_print_info},
+-      {.get = acpi_battery_get_state, .print = acpi_battery_print_state},
+-      {.get = acpi_battery_get_alarm, .print = acpi_battery_print_alarm},
+-};
+-
+-static int acpi_battery_read(int fid, struct seq_file *seq)
+-{
+-      struct acpi_battery *battery = seq->private;
+-      int result = 0;
+-      int update_result = ACPI_BATTERY_NONE_UPDATE;
+-      int update = 0;
+-
+-      mutex_lock(&battery->mutex);
+-
+-      update = (get_seconds() - battery->update_time[fid] >= update_time);
+-      update = (update | battery->flags.update[fid]);
+-
+-      result = acpi_battery_update(battery, update, &update_result);
+-      if (result)
+-              goto end;
+-
+-      if (update_result == ACPI_BATTERY_EASY_UPDATE) {
+-              result = acpi_read_funcs[fid].get(battery);
+-              if (result)
+-                      goto end;
+-      }
  
--      mutex_lock(&conn->xmitmutex);
-       /*
-        * for connection level recovery we should not calculate
-        * header digest. conn->hdr_size used for optimization
-@@ -1771,8 +1781,6 @@
-       fail_all_commands(conn);
-       flush_control_queues(session, conn);
-       spin_unlock_bh(&session->lock);
+-      end:
+-      result = acpi_read_funcs[fid].print(seq, result);
+-      acpi_battery_check_result(battery, result);
+-      battery->flags.update[fid] = result;
+-      mutex_unlock(&battery->mutex);
+-      return result;
+-}
+-
+-static int acpi_battery_read_info(struct seq_file *seq, void *offset)
+-{
+-      return acpi_battery_read(ACPI_BATTERY_INFO, seq);
+-}
+-
+-static int acpi_battery_read_state(struct seq_file *seq, void *offset)
+-{
+-      return acpi_battery_read(ACPI_BATTERY_STATE, seq);
+-}
+-
+-static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
+-{
+-      return acpi_battery_read(ACPI_BATTERY_ALARM, seq);
+-}
+-
+-static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
+-{
+-      return single_open(file, acpi_battery_read_info, PDE(inode)->data);
+-}
 -
--      mutex_unlock(&conn->xmitmutex);
+-static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
+-{
+-      return single_open(file, acpi_battery_read_state, PDE(inode)->data);
++      return count;
  }
  
- void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
-@@ -1867,6 +1875,30 @@
-       case ISCSI_PARAM_EXP_STATSN:
-               sscanf(buf, "%u", &conn->exp_statsn);
-               break;
-+      case ISCSI_PARAM_USERNAME:
-+              kfree(session->username);
-+              session->username = kstrdup(buf, GFP_KERNEL);
-+              if (!session->username)
-+                      return -ENOMEM;
-+              break;
-+      case ISCSI_PARAM_USERNAME_IN:
-+              kfree(session->username_in);
-+              session->username_in = kstrdup(buf, GFP_KERNEL);
-+              if (!session->username_in)
-+                      return -ENOMEM;
-+              break;
-+      case ISCSI_PARAM_PASSWORD:
-+              kfree(session->password);
-+              session->password = kstrdup(buf, GFP_KERNEL);
-+              if (!session->password)
-+                      return -ENOMEM;
-+              break;
-+      case ISCSI_PARAM_PASSWORD_IN:
-+              kfree(session->password_in);
-+              session->password_in = kstrdup(buf, GFP_KERNEL);
-+              if (!session->password_in)
-+                      return -ENOMEM;
-+              break;
-       case ISCSI_PARAM_TARGET_NAME:
-               /* this should not change between logins */
-               if (session->targetname)
-@@ -1940,6 +1972,18 @@
-       case ISCSI_PARAM_TPGT:
-               len = sprintf(buf, "%d\n", session->tpgt);
-               break;
-+      case ISCSI_PARAM_USERNAME:
-+              len = sprintf(buf, "%s\n", session->username);
-+              break;
-+      case ISCSI_PARAM_USERNAME_IN:
-+              len = sprintf(buf, "%s\n", session->username_in);
-+              break;
-+      case ISCSI_PARAM_PASSWORD:
-+              len = sprintf(buf, "%s\n", session->password);
-+              break;
-+      case ISCSI_PARAM_PASSWORD_IN:
-+              len = sprintf(buf, "%s\n", session->password_in);
-+              break;
-       default:
-               return -ENOSYS;
-       }
-@@ -1990,6 +2034,66 @@
+ static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
+@@ -762,51 +571,35 @@
+       return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
  }
- EXPORT_SYMBOL_GPL(iscsi_conn_get_param);
  
-+int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
-+                       char *buf)
-+{
-+      struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
-+      int len;
+-static struct battery_file {
+-      struct file_operations ops;
+-      mode_t mode;
+-      char *name;
+-} acpi_battery_file[] = {
+-      {
+-      .name = "info",
+-      .mode = S_IRUGO,
+-      .ops = {
++static const struct file_operations acpi_battery_info_ops = {
+       .open = acpi_battery_info_open_fs,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+-      },
+-      },
+-      {
+-      .name = "state",
+-      .mode = S_IRUGO,
+-      .ops = {
++};
 +
-+      switch (param) {
-+      case ISCSI_HOST_PARAM_NETDEV_NAME:
-+              if (!session->netdev)
-+                      len = sprintf(buf, "%s\n", "default");
-+              else
-+                      len = sprintf(buf, "%s\n", session->netdev);
-+              break;
-+      case ISCSI_HOST_PARAM_HWADDRESS:
-+              if (!session->hwaddress)
-+                      len = sprintf(buf, "%s\n", "default");
-+              else
-+                      len = sprintf(buf, "%s\n", session->hwaddress);
-+              break;
-+      case ISCSI_HOST_PARAM_INITIATOR_NAME:
-+              if (!session->initiatorname)
-+                      len = sprintf(buf, "%s\n", "unknown");
-+              else
-+                      len = sprintf(buf, "%s\n", session->initiatorname);
-+              break;
++static const struct file_operations acpi_battery_state_ops = {
+       .open = acpi_battery_state_open_fs,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+-      },
+-      },
+-      {
+-      .name = "alarm",
+-      .mode = S_IFREG | S_IRUGO | S_IWUSR,
+-      .ops = {
++};
 +
-+      default:
-+              return -ENOSYS;
++static const struct file_operations acpi_battery_alarm_ops = {
+       .open = acpi_battery_alarm_open_fs,
+       .read = seq_read,
+       .write = acpi_battery_write_alarm,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+-      },
+-      },
+ };
+ static int acpi_battery_add_fs(struct acpi_device *device)
+ {
+       struct proc_dir_entry *entry = NULL;
+-      int i;
++
+       if (!acpi_device_dir(device)) {
+               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
+@@ -816,16 +609,38 @@
+               acpi_device_dir(device)->owner = THIS_MODULE;
+       }
+-      for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
+-              entry = create_proc_entry(acpi_battery_file[i].name,
+-                                acpi_battery_file[i].mode, acpi_device_dir(device));
++      /* 'info' [R] */
++      entry = create_proc_entry(ACPI_BATTERY_FILE_INFO,
++                                S_IRUGO, acpi_device_dir(device));
+       if (!entry)
+               return -ENODEV;
+       else {
+-                      entry->proc_fops = &acpi_battery_file[i].ops;
++              entry->proc_fops = &acpi_battery_info_ops;
+               entry->data = acpi_driver_data(device);
+               entry->owner = THIS_MODULE;
+       }
++
++      /* 'status' [R] */
++      entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS,
++                                S_IRUGO, acpi_device_dir(device));
++      if (!entry)
++              return -ENODEV;
++      else {
++              entry->proc_fops = &acpi_battery_state_ops;
++              entry->data = acpi_driver_data(device);
++              entry->owner = THIS_MODULE;
 +      }
 +
-+      return len;
-+}
-+EXPORT_SYMBOL_GPL(iscsi_host_get_param);
++      /* 'alarm' [R/W] */
++      entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM,
++                                S_IFREG | S_IRUGO | S_IWUSR,
++                                acpi_device_dir(device));
++      if (!entry)
++              return -ENODEV;
++      else {
++              entry->proc_fops = &acpi_battery_alarm_ops;
++              entry->data = acpi_driver_data(device);
++              entry->owner = THIS_MODULE;
+       }
+       return 0;
+@@ -833,12 +648,15 @@
+ static int acpi_battery_remove_fs(struct acpi_device *device)
+ {
+-      int i;
 +
-+int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param,
-+                       char *buf, int buflen)
-+{
-+      struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+       if (acpi_device_dir(device)) {
+-              for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
+-                      remove_proc_entry(acpi_battery_file[i].name,
++              remove_proc_entry(ACPI_BATTERY_FILE_ALARM,
+                                 acpi_device_dir(device));
+-              }
++              remove_proc_entry(ACPI_BATTERY_FILE_STATUS,
++                                acpi_device_dir(device));
++              remove_proc_entry(ACPI_BATTERY_FILE_INFO,
++                                acpi_device_dir(device));
 +
-+      switch (param) {
-+      case ISCSI_HOST_PARAM_NETDEV_NAME:
-+              if (!session->netdev)
-+                      session->netdev = kstrdup(buf, GFP_KERNEL);
-+              break;
-+      case ISCSI_HOST_PARAM_HWADDRESS:
-+              if (!session->hwaddress)
-+                      session->hwaddress = kstrdup(buf, GFP_KERNEL);
-+              break;
-+      case ISCSI_HOST_PARAM_INITIATOR_NAME:
-+              if (!session->initiatorname)
-+                      session->initiatorname = kstrdup(buf, GFP_KERNEL);
-+              break;
-+      default:
-+              return -ENOSYS;
-+      }
+               remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
+               acpi_device_dir(device) = NULL;
+       }
+@@ -855,6 +673,7 @@
+       struct acpi_battery *battery = data;
+       struct acpi_device *device = NULL;
 +
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(iscsi_host_set_param);
+       if (!battery)
+               return;
+@@ -865,10 +684,8 @@
+       case ACPI_BATTERY_NOTIFY_INFO:
+       case ACPI_NOTIFY_BUS_CHECK:
+       case ACPI_NOTIFY_DEVICE_CHECK:
+-              device = battery->device;
+-              acpi_battery_notify_update(battery);
+-              acpi_bus_generate_event(device, event,
+-                                      acpi_battery_present(battery));
++              acpi_battery_check(battery);
++              acpi_bus_generate_event(device, event, battery->flags.present);
+               break;
+       default:
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+@@ -885,6 +702,7 @@
+       acpi_status status = 0;
+       struct acpi_battery *battery = NULL;
++
+       if (!device)
+               return -EINVAL;
+@@ -892,21 +710,15 @@
+       if (!battery)
+               return -ENOMEM;
+-      mutex_init(&battery->mutex);
+-
+-      mutex_lock(&battery->mutex);
+-
+       battery->device = device;
+       strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
+       strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
+       acpi_driver_data(device) = battery;
+-      result = acpi_battery_get_status(battery);
++      result = acpi_battery_check(battery);
+       if (result)
+               goto end;
+-      battery->flags.init_update = 1;
+-
+       result = acpi_battery_add_fs(device);
+       if (result)
+               goto end;
+@@ -915,7 +727,6 @@
+                                            ACPI_ALL_NOTIFY,
+                                            acpi_battery_notify, battery);
+       if (ACPI_FAILURE(status)) {
+-              ACPI_EXCEPTION((AE_INFO, status, "Installing notify handler"));
+               result = -ENODEV;
+               goto end;
+       }
+@@ -925,14 +736,11 @@
+              device->status.battery_present ? "present" : "absent");
+       end:
+-
+       if (result) {
+               acpi_battery_remove_fs(device);
+               kfree(battery);
+       }
+-      mutex_unlock(&battery->mutex);
+-
+       return result;
+ }
+@@ -941,27 +749,18 @@
+       acpi_status status = 0;
+       struct acpi_battery *battery = NULL;
 +
- MODULE_AUTHOR("Mike Christie");
- MODULE_DESCRIPTION("iSCSI library functions");
- MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/drivers/scsi/libsas/sas_expander.c linux-2.6.22-590/drivers/scsi/libsas/sas_expander.c
---- linux-2.6.22-570/drivers/scsi/libsas/sas_expander.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/libsas/sas_expander.c        2008-01-02 13:56:37.000000000 -0500
-@@ -38,8 +38,10 @@
+       if (!device || !acpi_driver_data(device))
+               return -EINVAL;
  
- #if 0
- /* FIXME: smp needs to migrate into the sas class */
--static ssize_t smp_portal_read(struct kobject *, char *, loff_t, size_t);
--static ssize_t smp_portal_write(struct kobject *, char *, loff_t, size_t);
-+static ssize_t smp_portal_read(struct kobject *, struct bin_attribute *,
-+                             char *, loff_t, size_t);
-+static ssize_t smp_portal_write(struct kobject *, struct bin_attribute *,
-+                              char *, loff_t, size_t);
- #endif
+       battery = acpi_driver_data(device);
  
- /* ---------- SMP task management ---------- */
-@@ -1368,7 +1370,6 @@
-       memset(bin_attr, 0, sizeof(*bin_attr));
+-      mutex_lock(&battery->mutex);
+-
+       status = acpi_remove_notify_handler(device->handle,
+                                           ACPI_ALL_NOTIFY,
+                                           acpi_battery_notify);
  
-       bin_attr->attr.name = SMP_BIN_ATTR_NAME;
--      bin_attr->attr.owner = THIS_MODULE;
-       bin_attr->attr.mode = 0600;
+       acpi_battery_remove_fs(device);
  
-       bin_attr->size = 0;
-@@ -1846,8 +1847,9 @@
- #if 0
- /* ---------- SMP portal ---------- */
+-      kfree(battery->bif_data.pointer);
+-
+-      kfree(battery->bst_data.pointer);
+-
+-      mutex_unlock(&battery->mutex);
+-
+-      mutex_destroy(&battery->mutex);
+-
+       kfree(battery);
  
--static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs,
--                              size_t size)
-+static ssize_t smp_portal_write(struct kobject *kobj,
-+                              struct bin_attribute *bin_attr,
-+                              char *buf, loff_t offs, size_t size)
- {
-       struct domain_device *dev = to_dom_device(kobj);
-       struct expander_device *ex = &dev->ex_dev;
-@@ -1873,8 +1875,9 @@
-       return size;
+       return 0;
+@@ -976,10 +775,7 @@
+               return -EINVAL;
+       battery = device->driver_data;
+-
+-      battery->flags.init_update = 1;
+-
+-      return 0;
++      return acpi_battery_check(battery);
  }
  
--static ssize_t smp_portal_read(struct kobject *kobj, char *buf, loff_t offs,
--                             size_t size)
-+static ssize_t smp_portal_read(struct kobject *kobj,
-+                             struct bin_attribute *bin_attr,
-+                             char *buf, loff_t offs, size_t size)
+ static int __init acpi_battery_init(void)
+@@ -1004,6 +800,7 @@
+ static void __exit acpi_battery_exit(void)
  {
-       struct domain_device *dev = to_dom_device(kobj);
-       struct expander_device *ex = &dev->ex_dev;
-diff -Nurb linux-2.6.22-570/drivers/scsi/libsas/sas_scsi_host.c linux-2.6.22-590/drivers/scsi/libsas/sas_scsi_host.c
---- linux-2.6.22-570/drivers/scsi/libsas/sas_scsi_host.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/libsas/sas_scsi_host.c       2008-01-02 13:56:37.000000000 -0500
-@@ -40,6 +40,7 @@
++
+       acpi_bus_unregister_driver(&acpi_battery_driver);
  
- #include <linux/err.h>
- #include <linux/blkdev.h>
-+#include <linux/freezer.h>
- #include <linux/scatterlist.h>
+       acpi_unlock_battery_dir(acpi_battery_dir);
+diff -Nurb linux-2.6.22-590/drivers/acpi/bay.c linux-2.6.22-570/drivers/acpi/bay.c
+--- linux-2.6.22-590/drivers/acpi/bay.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/bay.c        2007-07-08 19:32:17.000000000 -0400
+@@ -288,11 +288,6 @@
+       new_bay->pdev = pdev;
+       platform_set_drvdata(pdev, new_bay);
  
- /* ---------- SCSI Host glue ---------- */
-@@ -76,8 +77,8 @@
-                       hs = DID_NO_CONNECT;
-                       break;
-               case SAS_DATA_UNDERRUN:
--                      sc->resid = ts->residual;
--                      if (sc->request_bufflen - sc->resid < sc->underflow)
-+                      scsi_set_resid(sc, ts->residual);
-+                      if (scsi_bufflen(sc) - scsi_get_resid(sc) < sc->underflow)
-                               hs = DID_ERROR;
-                       break;
-               case SAS_DATA_OVERRUN:
-@@ -161,9 +162,9 @@
-       task->ssp_task.task_attr = sas_scsi_get_task_attr(cmd);
-       memcpy(task->ssp_task.cdb, cmd->cmnd, 16);
+-      /*
+-       * we want the bay driver to be able to send uevents
+-       */
+-      pdev->dev.uevent_suppress = 0;
+-
+       if (acpi_bay_add_fs(new_bay)) {
+               platform_device_unregister(new_bay->pdev);
+               goto bay_add_err;
+@@ -333,12 +328,18 @@
+ {
+       struct bay *bay_dev = (struct bay *)data;
+       struct device *dev = &bay_dev->pdev->dev;
+-      char event_string[12];
+-      char *envp[] = { event_string, NULL };
  
--      task->scatter = cmd->request_buffer;
--      task->num_scatter = cmd->use_sg;
--      task->total_xfer_len = cmd->request_bufflen;
-+      task->scatter = scsi_sglist(cmd);
-+      task->num_scatter = scsi_sg_count(cmd);
-+      task->total_xfer_len = scsi_bufflen(cmd);
-       task->data_dir = cmd->sc_data_direction;
+       bay_dprintk(handle, "Bay event");
+-      sprintf(event_string, "BAY_EVENT=%d\n", event);
+-      kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
++
++      switch(event) {
++      case ACPI_NOTIFY_BUS_CHECK:
++      case ACPI_NOTIFY_DEVICE_CHECK:
++      case ACPI_NOTIFY_EJECT_REQUEST:
++              kobject_uevent(&dev->kobj, KOBJ_CHANGE);
++              break;
++      default:
++              printk(KERN_ERR PREFIX "Bay: unknown event %d\n", event);
++      }
+ }
  
-       task->task_done = sas_scsi_task_done;
-@@ -868,8 +869,6 @@
- {
-       struct sas_ha_struct *sas_ha = _sas_ha;
+ static acpi_status
+diff -Nurb linux-2.6.22-590/drivers/acpi/dock.c linux-2.6.22-570/drivers/acpi/dock.c
+--- linux-2.6.22-590/drivers/acpi/dock.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/dock.c       2008-01-23 19:15:55.000000000 -0500
+@@ -40,15 +40,8 @@
+ MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION);
+ MODULE_LICENSE("GPL");
  
--      current->flags |= PF_NOFREEZE;
+-static int immediate_undock = 1;
+-module_param(immediate_undock, bool, 0644);
+-MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
+-      "undock immediately when the undock button is pressed, 0 will cause"
+-      " the driver to wait for userspace to write the undock sysfs file "
+-      " before undocking");
 -
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule();
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/Makefile linux-2.6.22-590/drivers/scsi/lpfc/Makefile
---- linux-2.6.22-570/drivers/scsi/lpfc/Makefile        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/Makefile        2008-01-02 13:56:37.000000000 -0500
-@@ -1,7 +1,7 @@
- #/*******************************************************************
- # * This file is part of the Emulex Linux Device Driver for         *
- # * Fibre Channel Host Bus Adapters.                                *
--# * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
-+# * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
- # * EMULEX and SLI are trademarks of Emulex.                        *
- # * www.emulex.com                                                  *
- # *                                                                 *
-@@ -27,4 +27,5 @@
- obj-$(CONFIG_SCSI_LPFC) := lpfc.o
+ static struct atomic_notifier_head dock_notifier_list;
+-static struct platform_device *dock_device;
++static struct platform_device dock_device;
+ static char dock_device_name[] = "dock";
  
- lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o lpfc_hbadisc.o        \
--      lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o
-+      lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o \
-+      lpfc_vport.o lpfc_debugfs.o
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc.h linux-2.6.22-590/drivers/scsi/lpfc/lpfc.h
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc.h  2008-01-02 13:56:37.000000000 -0500
-@@ -19,8 +19,9 @@
-  * included with this package.                                     *
-  *******************************************************************/
+ struct dock_station {
+@@ -70,7 +63,6 @@
+ };
  
--struct lpfc_sli2_slim;
-+#include <scsi/scsi_host.h>
+ #define DOCK_DOCKING  0x00000001
+-#define DOCK_UNDOCKING  0x00000002
+ #define DOCK_EVENT    3
+ #define UNDOCK_EVENT  2
  
-+struct lpfc_sli2_slim;
+@@ -335,20 +327,12 @@
  
- #define LPFC_MAX_TARGET               256     /* max number of targets supported */
- #define LPFC_MAX_DISC_THREADS 64      /* max outstanding discovery els
-@@ -32,6 +33,20 @@
- #define LPFC_IOCB_LIST_CNT    2250    /* list of IOCBs for fast-path usage. */
- #define LPFC_Q_RAMP_UP_INTERVAL 120     /* lun q_depth ramp up interval */
+ static void dock_event(struct dock_station *ds, u32 event, int num)
+ {
+-      struct device *dev = &dock_device->dev;
+-      char event_string[7];
+-      char *envp[] = { event_string, NULL };
+-
+-      if (num == UNDOCK_EVENT)
+-              sprintf(event_string, "UNDOCK");
+-      else
+-              sprintf(event_string, "DOCK");
+-
++      struct device *dev = &dock_device.dev;
+       /*
+        * Indicate that the status of the dock station has
+        * changed.
+        */
+-      kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
++      kobject_uevent(&dev->kobj, KOBJ_CHANGE);
+ }
  
-+/*
-+ * Following time intervals are used of adjusting SCSI device
-+ * queue depths when there are driver resource error or Firmware
-+ * resource error.
-+ */
-+#define QUEUE_RAMP_DOWN_INTERVAL      (1 * HZ)   /* 1 Second */
-+#define QUEUE_RAMP_UP_INTERVAL                (300 * HZ) /* 5 minutes */
-+
-+/* Number of exchanges reserved for discovery to complete */
-+#define LPFC_DISC_IOCB_BUFF_COUNT 20
-+
-+#define LPFC_HB_MBOX_INTERVAL   5     /* Heart beat interval in seconds. */
-+#define LPFC_HB_MBOX_TIMEOUT    30    /* Heart beat timeout  in seconds. */
-+
- /* Define macros for 64 bit support */
- #define putPaddrLow(addr)    ((uint32_t) (0xffffffff & (u64)(addr)))
- #define putPaddrHigh(addr)   ((uint32_t) (0xffffffff & (((u64)(addr))>>32)))
-@@ -61,6 +76,11 @@
-       uint32_t    current_count;
- };
+ /**
+@@ -436,16 +420,6 @@
+       ds->last_dock_time = jiffies;
+ }
  
-+struct hbq_dmabuf {
-+      struct lpfc_dmabuf dbuf;
-+      uint32_t tag;
-+};
+-static inline void begin_undock(struct dock_station *ds)
+-{
+-      ds->flags |= DOCK_UNDOCKING;
+-}
+-
+-static inline void complete_undock(struct dock_station *ds)
+-{
+-      ds->flags &= ~(DOCK_UNDOCKING);
+-}
+-
+ /**
+  * dock_in_progress - see if we are in the middle of handling a dock event
+  * @ds: the dock station
+@@ -576,7 +550,7 @@
+               printk(KERN_ERR PREFIX "Unable to undock!\n");
+               return -EBUSY;
+       }
+-      complete_undock(ds);
 +
- /* Priority bit.  Set value to exceed low water mark in lpfc_mem. */
- #define MEM_PRI               0x100
+       return 0;
+ }
  
-@@ -90,6 +110,29 @@
-               uint32_t sli2FwRev;
-               uint8_t sli2FwName[16];
-       } rev;
-+      struct {
-+#ifdef __BIG_ENDIAN_BITFIELD
-+              uint32_t rsvd2  :24;  /* Reserved                             */
-+              uint32_t cmv    : 1;  /* Configure Max VPIs                   */
-+              uint32_t ccrp   : 1;  /* Config Command Ring Polling          */
-+              uint32_t csah   : 1;  /* Configure Synchronous Abort Handling */
-+              uint32_t chbs   : 1;  /* Cofigure Host Backing store          */
-+              uint32_t cinb   : 1;  /* Enable Interrupt Notification Block  */
-+              uint32_t cerbm  : 1;  /* Configure Enhanced Receive Buf Mgmt  */
-+              uint32_t cmx    : 1;  /* Configure Max XRIs                   */
-+              uint32_t cmr    : 1;  /* Configure Max RPIs                   */
-+#else /*  __LITTLE_ENDIAN */
-+              uint32_t cmr    : 1;  /* Configure Max RPIs                   */
-+              uint32_t cmx    : 1;  /* Configure Max XRIs                   */
-+              uint32_t cerbm  : 1;  /* Configure Enhanced Receive Buf Mgmt  */
-+              uint32_t cinb   : 1;  /* Enable Interrupt Notification Block  */
-+              uint32_t chbs   : 1;  /* Cofigure Host Backing store          */
-+              uint32_t csah   : 1;  /* Configure Synchronous Abort Handling */
-+              uint32_t ccrp   : 1;  /* Config Command Ring Polling          */
-+              uint32_t cmv    : 1;  /* Configure Max VPIs                   */
-+              uint32_t rsvd2  :24;  /* Reserved                             */
-+#endif
-+      } sli3Feat;
- } lpfc_vpd_t;
+@@ -620,11 +594,7 @@
+        * to the driver who wish to hotplug.
+          */
+       case ACPI_NOTIFY_EJECT_REQUEST:
+-              begin_undock(ds);
+-              if (immediate_undock)
+               handle_eject_request(ds, event);
+-              else
+-                      dock_event(ds, event, UNDOCK_EVENT);
+               break;
+       default:
+               printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
+@@ -683,17 +653,6 @@
+ DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
  
- struct lpfc_scsi_buf;
-@@ -122,6 +165,7 @@
-       uint32_t elsRcvRPS;
-       uint32_t elsRcvRPL;
-       uint32_t elsXmitFLOGI;
-+      uint32_t elsXmitFDISC;
-       uint32_t elsXmitPLOGI;
-       uint32_t elsXmitPRLI;
-       uint32_t elsXmitADISC;
-@@ -165,70 +209,53 @@
-       struct lpfcMboxq *    mbox;
- };
+ /*
+- * show_flags - read method for flags file in sysfs
+- */
+-static ssize_t show_flags(struct device *dev,
+-                        struct device_attribute *attr, char *buf)
+-{
+-      return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
+-
+-}
+-DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
+-
+-/*
+  * write_undock - write method for "undock" file in sysfs
+  */
+ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
+@@ -716,15 +675,16 @@
+                            struct device_attribute *attr, char *buf)
+ {
+       unsigned long lbuf;
+-      acpi_status status = acpi_evaluate_integer(dock_station->handle,
+-                                      "_UID", NULL, &lbuf);
+-      if (ACPI_FAILURE(status))
++      acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf);
++      if(ACPI_FAILURE(status)) {
+           return 0;
+-
++      }
+       return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
+ }
+ DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
  
--struct lpfc_hba {
--      struct lpfc_sli sli;
--      struct lpfc_sli2_slim *slim2p;
--      dma_addr_t slim2p_mapping;
--      uint16_t pci_cfg_value;
-+struct lpfc_hba;
--      int32_t hba_state;
--#define LPFC_STATE_UNKNOWN        0    /* HBA state is unknown */
--#define LPFC_WARM_START           1    /* HBA state after selective reset */
--#define LPFC_INIT_START           2    /* Initial state after board reset */
--#define LPFC_INIT_MBX_CMDS        3    /* Initialize HBA with mbox commands */
--#define LPFC_LINK_DOWN            4    /* HBA initialized, link is down */
--#define LPFC_LINK_UP              5    /* Link is up  - issue READ_LA */
--#define LPFC_LOCAL_CFG_LINK       6    /* local NPORT Id configured */
--#define LPFC_FLOGI                7    /* FLOGI sent to Fabric */
--#define LPFC_FABRIC_CFG_LINK      8    /* Fabric assigned NPORT Id
--                                         configured */
--#define LPFC_NS_REG               9   /* Register with NameServer */
--#define LPFC_NS_QRY               10  /* Query NameServer for NPort ID list */
--#define LPFC_BUILD_DISC_LIST      11  /* Build ADISC and PLOGI lists for
-+enum discovery_state {
-+      LPFC_VPORT_UNKNOWN     =  0,    /* vport state is unknown */
-+      LPFC_VPORT_FAILED      =  1,    /* vport has failed */
-+      LPFC_LOCAL_CFG_LINK    =  6,    /* local NPORT Id configured */
-+      LPFC_FLOGI             =  7,    /* FLOGI sent to Fabric */
-+      LPFC_FDISC             =  8,    /* FDISC sent for vport */
-+      LPFC_FABRIC_CFG_LINK   =  9,    /* Fabric assigned NPORT Id
-+                                       * configured */
-+      LPFC_NS_REG            =  10,   /* Register with NameServer */
-+      LPFC_NS_QRY            =  11,   /* Query NameServer for NPort ID list */
-+      LPFC_BUILD_DISC_LIST   =  12,   /* Build ADISC and PLOGI lists for
-                                        * device authentication / discovery */
--#define LPFC_DISC_AUTH            12  /* Processing ADISC list */
--#define LPFC_CLEAR_LA             13  /* authentication cmplt - issue
--                                         CLEAR_LA */
--#define LPFC_HBA_READY            32
--#define LPFC_HBA_ERROR            -1
-+      LPFC_DISC_AUTH         =  13,   /* Processing ADISC list */
-+      LPFC_VPORT_READY       =  32,
-+};
++
++
+ /**
+  * dock_add - add a new dock station
+  * @handle: the dock station handle
+diff -Nurb linux-2.6.22-590/drivers/acpi/ec.c linux-2.6.22-570/drivers/acpi/ec.c
+--- linux-2.6.22-590/drivers/acpi/ec.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/ec.c 2007-07-08 19:32:17.000000000 -0400
+@@ -34,26 +34,25 @@
+ #include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
+ #include <linux/interrupt.h>
+-#include <linux/list.h>
+ #include <asm/io.h>
+ #include <acpi/acpi_bus.h>
+ #include <acpi/acpi_drivers.h>
+ #include <acpi/actypes.h>
  
--      int32_t stopped;   /* HBA has not been restarted since last ERATT */
--      uint8_t fc_linkspeed;   /* Link speed after last READ_LA */
-+enum hba_state {
-+      LPFC_LINK_UNKNOWN    =   0,   /* HBA state is unknown */
-+      LPFC_WARM_START      =   1,   /* HBA state after selective reset */
-+      LPFC_INIT_START      =   2,   /* Initial state after board reset */
-+      LPFC_INIT_MBX_CMDS   =   3,   /* Initialize HBA with mbox commands */
-+      LPFC_LINK_DOWN       =   4,   /* HBA initialized, link is down */
-+      LPFC_LINK_UP         =   5,   /* Link is up  - issue READ_LA */
-+      LPFC_CLEAR_LA        =   6,   /* authentication cmplt - issue
-+                                     * CLEAR_LA */
-+      LPFC_HBA_READY       =  32,
-+      LPFC_HBA_ERROR       =  -1
-+};
++#define _COMPONENT            ACPI_EC_COMPONENT
++ACPI_MODULE_NAME("ec");
++#define ACPI_EC_COMPONENT             0x00100000
+ #define ACPI_EC_CLASS                 "embedded_controller"
+ #define ACPI_EC_HID                   "PNP0C09"
+ #define ACPI_EC_DEVICE_NAME           "Embedded Controller"
+ #define ACPI_EC_FILE_INFO             "info"
+-
+ #undef PREFIX
+ #define PREFIX                                "ACPI: EC: "
+-
+ /* EC status register */
+ #define ACPI_EC_FLAG_OBF      0x01    /* Output buffer full */
+ #define ACPI_EC_FLAG_IBF      0x02    /* Input buffer full */
+ #define ACPI_EC_FLAG_BURST    0x10    /* burst mode */
+ #define ACPI_EC_FLAG_SCI      0x20    /* EC-SCI occurred */
+-
+ /* EC commands */
+ enum ec_command {
+       ACPI_EC_COMMAND_READ = 0x80,
+@@ -62,7 +61,6 @@
+       ACPI_EC_BURST_DISABLE = 0x83,
+       ACPI_EC_COMMAND_QUERY = 0x84,
+ };
+-
+ /* EC events */
+ enum ec_event {
+       ACPI_EC_EVENT_OBF_1 = 1,        /* Output buffer full */
+@@ -96,16 +94,6 @@
  
--      uint32_t fc_eventTag;   /* event tag for link attention */
--      uint32_t fc_prli_sent;  /* cntr for outstanding PRLIs */
-+struct lpfc_vport {
-+      struct list_head listentry;
-+      struct lpfc_hba *phba;
-+      uint8_t port_type;
-+#define LPFC_PHYSICAL_PORT 1
-+#define LPFC_NPIV_PORT  2
-+#define LPFC_FABRIC_PORT 3
-+      enum discovery_state port_state;
+ /* If we find an EC via the ECDT, we need to keep a ptr to its context */
+ /* External interfaces use first EC only, so remember */
+-typedef int (*acpi_ec_query_func) (void *data);
+-
+-struct acpi_ec_query_handler {
+-      struct list_head node;
+-      acpi_ec_query_func func;
+-      acpi_handle handle;
+-      void *data;
+-      u8 query_bit;
+-};
+-
+ static struct acpi_ec {
+       acpi_handle handle;
+       unsigned long gpe;
+@@ -116,7 +104,6 @@
+       atomic_t query_pending;
+       atomic_t event_count;
+       wait_queue_head_t wait;
+-      struct list_head list;
+ } *boot_ec, *first_ec;
  
--      uint32_t num_disc_nodes;        /*in addition to hba_state */
-+      uint16_t vpi;
+ /* --------------------------------------------------------------------------
+@@ -258,7 +245,7 @@
  
--      struct timer_list fc_estabtmo;  /* link establishment timer */
--      struct timer_list fc_disctmo;   /* Discovery rescue timer */
--      struct timer_list fc_fdmitmo;   /* fdmi timer */
--      /* These fields used to be binfo */
--      struct lpfc_name fc_nodename;   /* fc nodename */
--      struct lpfc_name fc_portname;   /* fc portname */
--      uint32_t fc_pref_DID;   /* preferred D_ID */
--      uint8_t fc_pref_ALPA;   /* preferred AL_PA */
--      uint32_t fc_edtov;      /* E_D_TOV timer value */
--      uint32_t fc_arbtov;     /* ARB_TOV timer value */
--      uint32_t fc_ratov;      /* R_A_TOV timer value */
--      uint32_t fc_rttov;      /* R_T_TOV timer value */
--      uint32_t fc_altov;      /* AL_TOV timer value */
--      uint32_t fc_crtov;      /* C_R_TOV timer value */
--      uint32_t fc_citov;      /* C_I_TOV timer value */
--      uint32_t fc_myDID;      /* fibre channel S_ID */
--      uint32_t fc_prevDID;    /* previous fibre channel S_ID */
+       status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0);
+       if (status) {
+-              printk(KERN_ERR PREFIX
++              printk(KERN_DEBUG PREFIX
+                      "input buffer is not empty, aborting transaction\n");
+               goto end;
+       }
+@@ -407,67 +394,21 @@
+ /* --------------------------------------------------------------------------
+                                 Event Management
+    -------------------------------------------------------------------------- */
+-int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
+-                            acpi_handle handle, acpi_ec_query_func func,
+-                            void *data)
+-{
+-      struct acpi_ec_query_handler *handler =
+-          kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL);
+-      if (!handler)
+-              return -ENOMEM;
 -
--      struct serv_parm fc_sparam;     /* buffer for our service parameters */
--      struct serv_parm fc_fabparam;   /* fabric service parameters buffer */
--      uint8_t alpa_map[128];  /* AL_PA map from READ_LA */
+-      handler->query_bit = query_bit;
+-      handler->handle = handle;
+-      handler->func = func;
+-      handler->data = data;
+-      mutex_lock(&ec->lock);
+-      list_add_tail(&handler->node, &ec->list);
+-      mutex_unlock(&ec->lock);
+-      return 0;
+-}
 -
--      uint8_t fc_ns_retry;    /* retries for fabric nameserver */
--      uint32_t fc_nlp_cnt;    /* outstanding NODELIST requests */
--      uint32_t fc_rscn_id_cnt;        /* count of RSCNs payloads in list */
--      struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN];
--      uint32_t lmt;
-       uint32_t fc_flag;       /* FC flags */
-+/* Several of these flags are HBA centric and should be moved to
-+ * phba->link_flag (e.g. FC_PTP, FC_PUBLIC_LOOP)
-+ */
- #define FC_PT2PT                0x1   /* pt2pt with no fabric */
- #define FC_PT2PT_PLOGI          0x2   /* pt2pt initiate PLOGI */
- #define FC_DISC_TMO             0x4   /* Discovery timer running */
-@@ -239,22 +266,14 @@
- #define FC_OFFLINE_MODE         0x80  /* Interface is offline for diag */
- #define FC_FABRIC               0x100 /* We are fabric attached */
- #define FC_ESTABLISH_LINK       0x200 /* Reestablish Link */
--#define FC_RSCN_DISCOVERY       0x400 /* Authenticate all devices after RSCN*/
--#define FC_BLOCK_MGMT_IO        0x800   /* Don't allow mgmt mbx or iocb cmds */
--#define FC_LOADING            0x1000  /* HBA in process of loading drvr */
--#define FC_UNLOADING          0x2000  /* HBA in process of unloading drvr */
-+#define FC_RSCN_DISCOVERY       0x400  /* Auth all devices after RSCN */
- #define FC_SCSI_SCAN_TMO        0x4000        /* scsi scan timer running */
- #define FC_ABORT_DISCOVERY      0x8000        /* we want to abort discovery */
- #define FC_NDISC_ACTIVE         0x10000       /* NPort discovery active */
- #define FC_BYPASSED_MODE        0x20000       /* NPort is in bypassed mode */
--#define FC_LOOPBACK_MODE        0x40000       /* NPort is in Loopback mode */
--                                      /* This flag is set while issuing */
--                                      /* INIT_LINK mailbox command */
--#define FC_IGNORE_ERATT         0x80000       /* intr handler should ignore ERATT */
+-EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
 -
--      uint32_t fc_topology;   /* link topology, from LINK INIT */
+-void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
+-{
+-      struct acpi_ec_query_handler *handler;
+-      mutex_lock(&ec->lock);
+-      list_for_each_entry(handler, &ec->list, node) {
+-              if (query_bit == handler->query_bit) {
+-                      list_del(&handler->node);
+-                      kfree(handler);
+-                      break;
+-              }
+-      }
+-      mutex_unlock(&ec->lock);
+-}
 -
--      struct lpfc_stats fc_stat;
-+#define FC_RFF_NOT_SUPPORTED    0x40000        /* RFF_ID was rejected by switch */
-+#define FC_VPORT_NEEDS_REG_VPI        0x80000  /* Needs to have its vpi registered */
-+#define FC_RSCN_DEFERRED      0x100000 /* A deferred RSCN being processed */
+-EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
  
-       struct list_head fc_nodes;
+ static void acpi_ec_gpe_query(void *ec_cxt)
+ {
+       struct acpi_ec *ec = ec_cxt;
+       u8 value = 0;
+-      struct acpi_ec_query_handler *handler, copy;
++      char object_name[8];
  
-@@ -267,10 +286,131 @@
-       uint16_t fc_map_cnt;
-       uint16_t fc_npr_cnt;
-       uint16_t fc_unused_cnt;
-+      struct serv_parm fc_sparam;     /* buffer for our service parameters */
-+
-+      uint32_t fc_myDID;      /* fibre channel S_ID */
-+      uint32_t fc_prevDID;    /* previous fibre channel S_ID */
-+
-+      int32_t stopped;   /* HBA has not been restarted since last ERATT */
-+      uint8_t fc_linkspeed;   /* Link speed after last READ_LA */
-+
-+      uint32_t num_disc_nodes;        /*in addition to hba_state */
-+
-+      uint32_t fc_nlp_cnt;    /* outstanding NODELIST requests */
-+      uint32_t fc_rscn_id_cnt;        /* count of RSCNs payloads in list */
-+      struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN];
-+      struct lpfc_name fc_nodename;   /* fc nodename */
-+      struct lpfc_name fc_portname;   /* fc portname */
-+
-+      struct lpfc_work_evt disc_timeout_evt;
-+
-+      struct timer_list fc_disctmo;   /* Discovery rescue timer */
-+      uint8_t fc_ns_retry;    /* retries for fabric nameserver */
-+      uint32_t fc_prli_sent;  /* cntr for outstanding PRLIs */
-+
-+      spinlock_t work_port_lock;
-+      uint32_t work_port_events; /* Timeout to be handled  */
-+#define WORKER_DISC_TMO                0x1    /* vport: Discovery timeout */
-+#define WORKER_ELS_TMO                 0x2    /* vport: ELS timeout */
-+#define WORKER_FDMI_TMO                0x4    /* vport: FDMI timeout */
-+
-+#define WORKER_MBOX_TMO                0x100  /* hba: MBOX timeout */
-+#define WORKER_HB_TMO                  0x200  /* hba: Heart beat timeout */
-+#define WORKER_FABRIC_BLOCK_TMO        0x400  /* hba: fabric block timout */
-+#define WORKER_RAMP_DOWN_QUEUE         0x800  /* hba: Decrease Q depth */
-+#define WORKER_RAMP_UP_QUEUE           0x1000 /* hba: Increase Q depth */
-+
-+      struct timer_list fc_fdmitmo;
-+      struct timer_list els_tmofunc;
-+
-+      int unreg_vpi_cmpl;
-+
-+      uint8_t load_flag;
-+#define FC_LOADING            0x1     /* HBA in process of loading drvr */
-+#define FC_UNLOADING          0x2     /* HBA in process of unloading drvr */
-+      char  *vname;                   /* Application assigned name */
-+      struct fc_vport *fc_vport;
-+
-+#ifdef CONFIG_LPFC_DEBUG_FS
-+      struct dentry *debug_disc_trc;
-+      struct dentry *debug_nodelist;
-+      struct dentry *vport_debugfs_root;
-+      struct lpfc_disc_trc *disc_trc;
-+      atomic_t disc_trc_cnt;
-+#endif
-+};
-+
-+struct hbq_s {
-+      uint16_t entry_count;     /* Current number of HBQ slots */
-+      uint32_t next_hbqPutIdx;  /* Index to next HBQ slot to use */
-+      uint32_t hbqPutIdx;       /* HBQ slot to use */
-+      uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */
-+};
-+
-+#define LPFC_MAX_HBQS  16
-+/* this matches the possition in the lpfc_hbq_defs array */
-+#define LPFC_ELS_HBQ  0
-+
-+struct lpfc_hba {
-+      struct lpfc_sli sli;
-+      uint32_t sli_rev;               /* SLI2 or SLI3 */
-+      uint32_t sli3_options;          /* Mask of enabled SLI3 options */
-+#define LPFC_SLI3_ENABLED      0x01
-+#define LPFC_SLI3_HBQ_ENABLED  0x02
-+#define LPFC_SLI3_NPIV_ENABLED         0x04
-+#define LPFC_SLI3_VPORT_TEARDOWN 0x08
-+      uint32_t iocb_cmd_size;
-+      uint32_t iocb_rsp_size;
-+
-+      enum hba_state link_state;
-+      uint32_t link_flag;     /* link state flags */
-+#define LS_LOOPBACK_MODE      0x1     /* NPort is in Loopback mode */
-+                                      /* This flag is set while issuing */
-+                                      /* INIT_LINK mailbox command */
-+#define LS_NPIV_FAB_SUPPORTED 0x2     /* Fabric supports NPIV */
-+#define LS_IGNORE_ERATT       0x3     /* intr handler should ignore ERATT */
-+
-+      struct lpfc_sli2_slim *slim2p;
-+      struct lpfc_dmabuf hbqslimp;
-+
-+      dma_addr_t slim2p_mapping;
-+
-+      uint16_t pci_cfg_value;
-+
-+      uint8_t work_found;
-+#define LPFC_MAX_WORKER_ITERATION  4
-+
-+      uint8_t fc_linkspeed;   /* Link speed after last READ_LA */
-+
-+      uint32_t fc_eventTag;   /* event tag for link attention */
-+
-+
-+      struct timer_list fc_estabtmo;  /* link establishment timer */
-+      /* These fields used to be binfo */
-+      uint32_t fc_pref_DID;   /* preferred D_ID */
-+      uint8_t  fc_pref_ALPA;  /* preferred AL_PA */
-+      uint32_t fc_edtov;      /* E_D_TOV timer value */
-+      uint32_t fc_arbtov;     /* ARB_TOV timer value */
-+      uint32_t fc_ratov;      /* R_A_TOV timer value */
-+      uint32_t fc_rttov;      /* R_T_TOV timer value */
-+      uint32_t fc_altov;      /* AL_TOV timer value */
-+      uint32_t fc_crtov;      /* C_R_TOV timer value */
-+      uint32_t fc_citov;      /* C_I_TOV timer value */
-+
-+      struct serv_parm fc_fabparam;   /* fabric service parameters buffer */
-+      uint8_t alpa_map[128];  /* AL_PA map from READ_LA */
-+
-+      uint32_t lmt;
+       if (!ec || acpi_ec_query(ec, &value))
+               return;
+-      mutex_lock(&ec->lock);
+-      list_for_each_entry(handler, &ec->list, node) {
+-              if (value == handler->query_bit) {
+-                      /* have custom handler for this bit */
+-                      memcpy(&copy, handler, sizeof(copy));
+-                      mutex_unlock(&ec->lock);
+-                      if (copy.func) {
+-                              copy.func(copy.data);
+-                      } else if (copy.handle) {
+-                              acpi_evaluate_object(copy.handle, NULL, NULL, NULL);
+-                      }
+-                      return;
+-              }
+-      }
+-      mutex_unlock(&ec->lock);
+-      printk(KERN_ERR PREFIX "Handler for query 0x%x is not found!\n", value);
 +
-+      uint32_t fc_topology;   /* link topology, from LINK INIT */
++      snprintf(object_name, 8, "_Q%2.2X", value);
 +
-+      struct lpfc_stats fc_stat;
++      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name));
 +
-       struct lpfc_nodelist fc_fcpnodev; /* nodelist entry for no device */
-       uint32_t nport_event_cnt;       /* timestamp for nlplist entry */
++      acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
+ }
  
--      uint32_t wwnn[2];
-+      uint8_t  wwnn[8];
-+      uint8_t  wwpn[8];
-       uint32_t RandomData[7];
+ static u32 acpi_ec_gpe_handler(void *data)
+@@ -486,7 +427,8 @@
+       if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) {
+               atomic_set(&ec->query_pending, 1);
+               status =
+-                  acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec);
++                  acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query,
++                                  ec);
+       }
  
-       uint32_t cfg_log_verbose;
-@@ -278,6 +418,9 @@
-       uint32_t cfg_nodev_tmo;
-       uint32_t cfg_devloss_tmo;
-       uint32_t cfg_hba_queue_depth;
-+      uint32_t cfg_peer_port_login;
-+      uint32_t cfg_vport_restrict_login;
-+      uint32_t cfg_npiv_enable;
-       uint32_t cfg_fcp_class;
-       uint32_t cfg_use_adisc;
-       uint32_t cfg_ack0;
-@@ -304,22 +447,20 @@
+       return status == AE_OK ?
+@@ -512,35 +454,57 @@
+ }
  
-       lpfc_vpd_t vpd;         /* vital product data */
+ static acpi_status
+-acpi_ec_space_handler(u32 function, acpi_physical_address address,
+-                    u32 bits, acpi_integer *value,
++acpi_ec_space_handler(u32 function,
++                    acpi_physical_address address,
++                    u32 bit_width,
++                    acpi_integer * value,
+                     void *handler_context, void *region_context)
+ {
++      int result = 0;
+       struct acpi_ec *ec = handler_context;
+-      int result = 0, i = 0;
+-      u8 temp = 0;
++      u64 temp = *value;
++      acpi_integer f_v = 0;
++      int i = 0;
  
--      struct Scsi_Host *host;
-       struct pci_dev *pcidev;
-       struct list_head      work_list;
-       uint32_t              work_ha;      /* Host Attention Bits for WT */
-       uint32_t              work_ha_mask; /* HA Bits owned by WT        */
-       uint32_t              work_hs;      /* HS stored in case of ERRAT */
-       uint32_t              work_status[2]; /* Extra status from SLIM */
--      uint32_t              work_hba_events; /* Timeout to be handled  */
--#define WORKER_DISC_TMO                0x1    /* Discovery timeout */
--#define WORKER_ELS_TMO                 0x2    /* ELS timeout */
--#define WORKER_MBOX_TMO                0x4    /* MBOX timeout */
--#define WORKER_FDMI_TMO                0x8    /* FDMI timeout */
+       if ((address > 0xFF) || !value || !handler_context)
+               return AE_BAD_PARAMETER;
  
-       wait_queue_head_t    *work_wait;
-       struct task_struct   *worker_thread;
+-      if (function != ACPI_READ && function != ACPI_WRITE)
++      if (bit_width != 8 && acpi_strict) {
+               return AE_BAD_PARAMETER;
++      }
  
-+      struct list_head hbq_buffer_list;
-+      uint32_t hbq_count;             /* Count of configured HBQs */
-+      struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies  */
-+
-       unsigned long pci_bar0_map;     /* Physical address for PCI BAR0 */
-       unsigned long pci_bar2_map;     /* Physical address for PCI BAR2 */
-       void __iomem *slim_memmap_p;    /* Kernel memory mapped address for
-@@ -334,6 +475,10 @@
-                                          reg */
-       void __iomem *HCregaddr;        /* virtual address for host ctl reg */
+-      if (bits != 8 && acpi_strict)
+-              return AE_BAD_PARAMETER;
++      next_byte:
++      switch (function) {
++      case ACPI_READ:
++              temp = 0;
++              result = acpi_ec_read(ec, (u8) address, (u8 *) & temp);
++              break;
++      case ACPI_WRITE:
++              result = acpi_ec_write(ec, (u8) address, (u8) temp);
++              break;
++      default:
++              result = -EINVAL;
++              goto out;
++              break;
++      }
  
-+      struct lpfc_hgp __iomem *host_gp; /* Host side get/put pointers */
-+      uint32_t __iomem  *hbq_put;     /* Address in SLIM to HBQ put ptrs */
-+      uint32_t          *hbq_get;     /* Host mem address of HBQ get ptrs */
+-      while (bits - i > 0) {
+-      if (function == ACPI_READ) {
+-                      result = acpi_ec_read(ec, address, &temp);
+-                      (*value) |= ((acpi_integer)temp) << i;
+-              } else {
+-                      temp = 0xff & ((*value) >> i);
+-                      result = acpi_ec_write(ec, address, temp);
++      bit_width -= 8;
++      if (bit_width) {
++              if (function == ACPI_READ)
++                      f_v |= temp << 8 * i;
++              if (function == ACPI_WRITE)
++                      temp >>= 8;
++              i++;
++              address++;
++              goto next_byte;
+               }
+-              i += 8;
+-              ++address;
 +
-       int brd_no;                     /* FC board number */
++      if (function == ACPI_READ) {
++              f_v |= temp << 8 * i;
++              *value = f_v;
+       }
  
-       char SerialNumber[32];          /* adapter Serial Number */
-@@ -353,7 +498,6 @@
-       uint8_t soft_wwn_enable;
++      out:
+       switch (result) {
+       case -EINVAL:
+               return AE_BAD_PARAMETER;
+@@ -633,6 +597,9 @@
+ static acpi_status
+ ec_parse_io_ports(struct acpi_resource *resource, void *context);
  
-       struct timer_list fcp_poll_timer;
--      struct timer_list els_tmofunc;
++static acpi_status
++ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval);
++
+ static struct acpi_ec *make_acpi_ec(void)
+ {
+       struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+@@ -643,52 +610,13 @@
+       atomic_set(&ec->event_count, 1);
+       mutex_init(&ec->lock);
+       init_waitqueue_head(&ec->wait);
+-      INIT_LIST_HEAD(&ec->list);
  
-       /*
-        * stat  counters
-@@ -370,31 +514,69 @@
-       uint32_t total_scsi_bufs;
-       struct list_head lpfc_iocb_list;
-       uint32_t total_iocbq_bufs;
-+      spinlock_t hbalock;
+       return ec;
+ }
  
-       /* pci_mem_pools */
-       struct pci_pool *lpfc_scsi_dma_buf_pool;
-       struct pci_pool *lpfc_mbuf_pool;
-+      struct pci_pool *lpfc_hbq_pool;
-       struct lpfc_dma_pool lpfc_mbuf_safety_pool;
+-static acpi_status
+-acpi_ec_register_query_methods(acpi_handle handle, u32 level,
+-                             void *context, void **return_value)
+-{
+-      struct acpi_namespace_node *node = handle;
+-      struct acpi_ec *ec = context;
+-      int value = 0;
+-      if (sscanf(node->name.ascii, "_Q%x", &value) == 1) {
+-              acpi_ec_add_query_handler(ec, value, handle, NULL, NULL);
+-      }
+-      return AE_OK;
+-}
+-
+-static int ec_parse_device(struct acpi_ec *ec, acpi_handle handle)
+-{
+-      if (ACPI_FAILURE(acpi_walk_resources(handle, METHOD_NAME__CRS,
+-                                   ec_parse_io_ports, ec)))
+-              return -EINVAL;
+-
+-      /* Get GPE bit assignment (EC events). */
+-      /* TODO: Add support for _GPE returning a package */
+-      if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe)))
+-              return -EINVAL;
+-
+-      /* Use the global lock for all EC transactions? */
+-      acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
+-
+-      /* Find and register all query methods */
+-      acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1,
+-                          acpi_ec_register_query_methods, ec, NULL);
+-
+-      ec->handle = handle;
+-
+-      printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx",
+-                        ec->gpe, ec->command_addr, ec->data_addr);
+-
+-      return 0;
+-}
+-
+ static int acpi_ec_add(struct acpi_device *device)
+ {
++      acpi_status status = AE_OK;
+       struct acpi_ec *ec = NULL;
  
-       mempool_t *mbox_mem_pool;
-       mempool_t *nlp_mem_pool;
+       if (!device)
+@@ -701,7 +629,8 @@
+       if (!ec)
+               return -ENOMEM;
+-      if (ec_parse_device(ec, device->handle)) {
++      status = ec_parse_device(device->handle, 0, ec, NULL);
++      if (status != AE_CTRL_TERMINATE) {
+               kfree(ec);
+               return -EINVAL;
+       }
+@@ -712,8 +641,6 @@
+                       /* We might have incorrect info for GL at boot time */
+                       mutex_lock(&boot_ec->lock);
+                       boot_ec->global_lock = ec->global_lock;
+-                      /* Copy handlers from new ec into boot ec */
+-                      list_splice(&ec->list, &boot_ec->list);
+                       mutex_unlock(&boot_ec->lock);
+                       kfree(ec);
+                       ec = boot_ec;
+@@ -724,24 +651,22 @@
+       acpi_driver_data(device) = ec;
  
-       struct fc_host_statistics link_stats;
+       acpi_ec_add_fs(device);
 +
-+      struct list_head port_list;
-+      struct lpfc_vport *pport; /* physical lpfc_vport pointer */
-+      uint16_t max_vpi;       /* Maximum virtual nports */
-+#define LPFC_MAX_VPI 100  /* Max number of VPorts supported */
-+      unsigned long *vpi_bmask; /* vpi allocation table */
-+
-+      /* Data structure used by fabric iocb scheduler */
-+      struct list_head fabric_iocb_list;
-+      atomic_t fabric_iocb_count;
-+      struct timer_list fabric_block_timer;
-+      unsigned long bit_flags;
-+#define       FABRIC_COMANDS_BLOCKED  0
-+      atomic_t num_rsrc_err;
-+      atomic_t num_cmd_success;
-+      unsigned long last_rsrc_error_time;
-+      unsigned long last_ramp_down_time;
-+      unsigned long last_ramp_up_time;
-+#ifdef CONFIG_LPFC_DEBUG_FS
-+      struct dentry *hba_debugfs_root;
-+      atomic_t debugfs_vport_count;
-+#endif
-+
-+      /* Fields used for heart beat. */
-+      unsigned long last_completion_time;
-+      struct timer_list hb_tmofunc;
-+      uint8_t hb_outstanding;
- };
-+static inline struct Scsi_Host *
-+lpfc_shost_from_vport(struct lpfc_vport *vport)
-+{
-+      return container_of((void *) vport, struct Scsi_Host, hostdata[0]);
-+}
++      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.",
++                        acpi_device_name(device), acpi_device_bid(device),
++                        (u32) ec->gpe));
 +
- static inline void
--lpfc_set_loopback_flag(struct lpfc_hba *phba) {
-+lpfc_set_loopback_flag(struct lpfc_hba *phba)
-+{
-       if (phba->cfg_topology == FLAGS_LOCAL_LB)
--              phba->fc_flag |= FC_LOOPBACK_MODE;
-+              phba->link_flag |= LS_LOOPBACK_MODE;
-       else
--              phba->fc_flag &= ~FC_LOOPBACK_MODE;
-+              phba->link_flag &= ~LS_LOOPBACK_MODE;
+       return 0;
  }
  
--struct rnidrsp {
--      void *buf;
--      uint32_t uniqueid;
--      struct list_head list;
--      uint32_t data;
--};
-+static inline int
-+lpfc_is_link_up(struct lpfc_hba *phba)
-+{
-+      return  phba->link_state == LPFC_LINK_UP ||
-+              phba->link_state == LPFC_CLEAR_LA ||
-+              phba->link_state == LPFC_HBA_READY;
-+}
+ static int acpi_ec_remove(struct acpi_device *device, int type)
+ {
+       struct acpi_ec *ec;
+-      struct acpi_ec_query_handler *handler;
  
- #define FC_REG_DUMP_EVENT     0x10    /* Register for Dump events */
-+
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_attr.c linux-2.6.22-590/drivers/scsi/lpfc/lpfc_attr.c
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_attr.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_attr.c     2008-01-02 13:56:37.000000000 -0500
-@@ -39,6 +39,7 @@
- #include "lpfc_version.h"
- #include "lpfc_compat.h"
- #include "lpfc_crtn.h"
-+#include "lpfc_vport.h"
+       if (!device)
+               return -EINVAL;
  
- #define LPFC_DEF_DEVLOSS_TMO 30
- #define LPFC_MIN_DEVLOSS_TMO 1
-@@ -76,116 +77,156 @@
- lpfc_info_show(struct class_device *cdev, char *buf)
- {
-       struct Scsi_Host *host = class_to_shost(cdev);
-+
-       return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host));
- }
+       ec = acpi_driver_data(device);
+-      mutex_lock(&ec->lock);
+-      list_for_each_entry(handler, &ec->list, node) {
+-              list_del(&handler->node);
+-              kfree(handler);
+-      }
+-      mutex_unlock(&ec->lock);
+       acpi_ec_remove_fs(device);
+       acpi_driver_data(device) = NULL;
+       if (ec == first_ec)
+@@ -797,13 +722,15 @@
+               return -ENODEV;
+       }
  
- static ssize_t
- lpfc_serialnum_show(struct class_device *cdev, char *buf)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
++      /* EC is fully operational, allow queries */
++      atomic_set(&ec->query_pending, 0);
 +
-       return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber);
+       return 0;
  }
  
- static ssize_t
- lpfc_modeldesc_show(struct class_device *cdev, char *buf)
+ static int acpi_ec_start(struct acpi_device *device)
  {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+
-       return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc);
- }
+       struct acpi_ec *ec;
+-      int ret = 0;
  
- static ssize_t
- lpfc_modelname_show(struct class_device *cdev, char *buf)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+
-       return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName);
- }
+       if (!device)
+               return -EINVAL;
+@@ -813,14 +740,14 @@
+       if (!ec)
+               return -EINVAL;
  
- static ssize_t
- lpfc_programtype_show(struct class_device *cdev, char *buf)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+
-       return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType);
- }
+-      /* Boot EC is already working */
+-      if (ec != boot_ec)
+-              ret = ec_install_handlers(ec);
++      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
++                        ec->gpe, ec->command_addr, ec->data_addr));
  
- static ssize_t
--lpfc_portnum_show(struct class_device *cdev, char *buf)
-+lpfc_vportnum_show(struct class_device *cdev, char *buf)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+
-       return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port);
+-      /* EC is fully operational, allow queries */
+-      atomic_set(&ec->query_pending, 0);
++      /* Boot EC is already working */
++      if (ec == boot_ec)
++              return 0;
+-      return ret;
++      return ec_install_handlers(ec);
  }
  
- static ssize_t
- lpfc_fwrev_show(struct class_device *cdev, char *buf)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       char fwrev[32];
-+
-       lpfc_decode_firmware_rev(phba, fwrev, 1);
--      return snprintf(buf, PAGE_SIZE, "%s\n",fwrev);
-+      return snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", fwrev, phba->sli_rev);
+ static int acpi_ec_stop(struct acpi_device *device, int type)
+@@ -852,6 +779,34 @@
+       return 0;
  }
  
- static ssize_t
- lpfc_hdw_show(struct class_device *cdev, char *buf)
- {
-       char hdw[9];
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       lpfc_vpd_t *vp = &phba->vpd;
++static acpi_status
++ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
++{
++      acpi_status status;
 +
-       lpfc_jedec_to_ascii(vp->rev.biuRev, hdw);
-       return snprintf(buf, PAGE_SIZE, "%s\n", hdw);
- }
- static ssize_t
- lpfc_option_rom_version_show(struct class_device *cdev, char *buf)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
++      struct acpi_ec *ec = context;
++      status = acpi_walk_resources(handle, METHOD_NAME__CRS,
++                                   ec_parse_io_ports, ec);
++      if (ACPI_FAILURE(status))
++              return status;
 +
-       return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
- }
- static ssize_t
- lpfc_state_show(struct class_device *cdev, char *buf)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       int len = 0;
--      switch (phba->hba_state) {
--      case LPFC_STATE_UNKNOWN:
++      /* Get GPE bit assignment (EC events). */
++      /* TODO: Add support for _GPE returning a package */
++      status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
++      if (ACPI_FAILURE(status))
++              return status;
 +
-+      switch (phba->link_state) {
-+      case LPFC_LINK_UNKNOWN:
-       case LPFC_WARM_START:
-       case LPFC_INIT_START:
-       case LPFC_INIT_MBX_CMDS:
-       case LPFC_LINK_DOWN:
-+      case LPFC_HBA_ERROR:
-               len += snprintf(buf + len, PAGE_SIZE-len, "Link Down\n");
-               break;
-       case LPFC_LINK_UP:
-+      case LPFC_CLEAR_LA:
-+      case LPFC_HBA_READY:
-+              len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - \n");
++      /* Use the global lock for all EC transactions? */
++      acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
 +
-+              switch (vport->port_state) {
-+                      len += snprintf(buf + len, PAGE_SIZE-len,
-+                                      "initializing\n");
-+                      break;
-       case LPFC_LOCAL_CFG_LINK:
--              len += snprintf(buf + len, PAGE_SIZE-len, "Link Up\n");
-+                      len += snprintf(buf + len, PAGE_SIZE-len,
-+                                      "Configuring Link\n");
-               break;
-+              case LPFC_FDISC:
-       case LPFC_FLOGI:
-       case LPFC_FABRIC_CFG_LINK:
-       case LPFC_NS_REG:
-       case LPFC_NS_QRY:
-       case LPFC_BUILD_DISC_LIST:
-       case LPFC_DISC_AUTH:
--      case LPFC_CLEAR_LA:
--              len += snprintf(buf + len, PAGE_SIZE-len,
--                              "Link Up - Discovery\n");
-+                      len += snprintf(buf + len, PAGE_SIZE - len,
-+                                      "Discovery\n");
-               break;
--      case LPFC_HBA_READY:
--              len += snprintf(buf + len, PAGE_SIZE-len,
--                              "Link Up - Ready:\n");
-+              case LPFC_VPORT_READY:
-+                      len += snprintf(buf + len, PAGE_SIZE - len, "Ready\n");
-+                      break;
++      ec->handle = handle;
 +
-+              case LPFC_VPORT_FAILED:
-+                      len += snprintf(buf + len, PAGE_SIZE - len, "Failed\n");
-+                      break;
++      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
++                        ec->gpe, ec->command_addr, ec->data_addr));
 +
-+              case LPFC_VPORT_UNKNOWN:
-+                      len += snprintf(buf + len, PAGE_SIZE - len,
-+                                      "Unknown\n");
-+                      break;
-+              }
++      return AE_CTRL_TERMINATE;
++}
 +
-               if (phba->fc_topology == TOPOLOGY_LOOP) {
--                      if (phba->fc_flag & FC_PUBLIC_LOOP)
-+                      if (vport->fc_flag & FC_PUBLIC_LOOP)
-                               len += snprintf(buf + len, PAGE_SIZE-len,
-                                               "   Public Loop\n");
-                       else
-                               len += snprintf(buf + len, PAGE_SIZE-len,
-                                               "   Private Loop\n");
-               } else {
--                      if (phba->fc_flag & FC_FABRIC)
-+                      if (vport->fc_flag & FC_FABRIC)
-                               len += snprintf(buf + len, PAGE_SIZE-len,
-                                               "   Fabric\n");
-                       else
-@@ -193,29 +234,32 @@
-                                               "   Point-2-Point\n");
-               }
-       }
+ int __init acpi_ec_ecdt_probe(void)
+ {
+       int ret;
+@@ -870,7 +825,7 @@
+       if (ACPI_FAILURE(status))
+               goto error;
+-      printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n");
++      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT"));
+       boot_ec->command_addr = ecdt_ptr->control.address;
+       boot_ec->data_addr = ecdt_ptr->data.address;
+diff -Nurb linux-2.6.22-590/drivers/acpi/osl.c linux-2.6.22-570/drivers/acpi/osl.c
+--- linux-2.6.22-590/drivers/acpi/osl.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/osl.c        2007-07-08 19:32:17.000000000 -0400
+@@ -77,7 +77,13 @@
+ #define       OSI_STRING_LENGTH_MAX 64        /* arbitrary */
+ static char osi_additional_string[OSI_STRING_LENGTH_MAX];
++#define OSI_LINUX_ENABLED
++#ifdef        OSI_LINUX_ENABLED
++int osi_linux = 1;    /* enable _OSI(Linux) by default */
++#else
+ int osi_linux;                /* disable _OSI(Linux) by default */
++#endif
 +
-       return len;
+ #ifdef CONFIG_DMI
+ static struct __initdata dmi_system_id acpi_osl_dmi_table[];
+@@ -1050,17 +1056,6 @@
+ EXPORT_SYMBOL(max_cstate);
+-void (*acpi_do_set_cstate_limit)(void);
+-EXPORT_SYMBOL(acpi_do_set_cstate_limit);
+-
+-void acpi_set_cstate_limit(unsigned int new_limit)
+-{
+-      max_cstate = new_limit;
+-      if (acpi_do_set_cstate_limit)
+-              acpi_do_set_cstate_limit();
+-}
+-EXPORT_SYMBOL(acpi_set_cstate_limit);
+-
+ /*
+  * Acquire a spinlock.
+  *
+@@ -1188,10 +1183,17 @@
+       if (!strcmp("Linux", interface)) {
+               printk(KERN_WARNING PREFIX
+                       "System BIOS is requesting _OSI(Linux)\n");
++#ifdef        OSI_LINUX_ENABLED
++              printk(KERN_WARNING PREFIX
++                      "Please test with \"acpi_osi=!Linux\"\n"
++                      "Please send dmidecode "
++                      "to linux-acpi@vger.kernel.org\n");
++#else
+               printk(KERN_WARNING PREFIX
+                       "If \"acpi_osi=Linux\" works better,\n"
+                       "Please send dmidecode "
+                       "to linux-acpi@vger.kernel.org\n");
++#endif
+               if(osi_linux)
+                       return AE_OK;
+       }
+@@ -1225,14 +1227,36 @@
  }
  
- static ssize_t
- lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
+ #ifdef CONFIG_DMI
++#ifdef        OSI_LINUX_ENABLED
++static int dmi_osi_not_linux(struct dmi_system_id *d)
++{
++      printk(KERN_NOTICE "%s detected: requires not _OSI(Linux)\n", d->ident);
++      enable_osi_linux(0);
++      return 0;
++}
++#else
+ static int dmi_osi_linux(struct dmi_system_id *d)
  {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
--      return snprintf(buf, PAGE_SIZE, "%d\n", phba->fc_map_cnt +
--                                                      phba->fc_unmap_cnt);
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+
-+      return snprintf(buf, PAGE_SIZE, "%d\n",
-+                      vport->fc_map_cnt + vport->fc_unmap_cnt);
+-      printk(KERN_NOTICE "%s detected: enabling _OSI(Linux)\n", d->ident);
++      printk(KERN_NOTICE "%s detected: requires _OSI(Linux)\n", d->ident);
+       enable_osi_linux(1);
+       return 0;
  }
++#endif
  
+ static struct dmi_system_id acpi_osl_dmi_table[] __initdata = {
++#ifdef        OSI_LINUX_ENABLED
++      /*
++       * Boxes that need NOT _OSI(Linux)
++       */
++      {
++       .callback = dmi_osi_not_linux,
++       .ident = "Toshiba Satellite P100",
++       .matches = {
++                   DMI_MATCH(DMI_BOARD_VENDOR, "TOSHIBA"),
++                   DMI_MATCH(DMI_BOARD_NAME, "Satellite P100"),
++                   },
++       },
++#else
+       /*
+        * Boxes that need _OSI(Linux)
+        */
+@@ -1244,6 +1268,7 @@
+                    DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"),
+                    },
+        },
++#endif
+       {}
+ };
+ #endif /* CONFIG_DMI */
+diff -Nurb linux-2.6.22-590/drivers/acpi/processor_core.c linux-2.6.22-570/drivers/acpi/processor_core.c
+--- linux-2.6.22-590/drivers/acpi/processor_core.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/processor_core.c     2008-01-23 19:15:55.000000000 -0500
+@@ -44,7 +44,6 @@
+ #include <linux/seq_file.h>
+ #include <linux/dmi.h>
+ #include <linux/moduleparam.h>
+-#include <linux/cpuidle.h>
  
- static int
--lpfc_issue_lip(struct Scsi_Host *host)
-+lpfc_issue_lip(struct Scsi_Host *shost)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       LPFC_MBOXQ_t *pmboxq;
-       int mbxstatus = MBXERR_ERROR;
--      if ((phba->fc_flag & FC_OFFLINE_MODE) ||
--          (phba->fc_flag & FC_BLOCK_MGMT_IO) ||
--          (phba->hba_state != LPFC_HBA_READY))
-+      if ((vport->fc_flag & FC_OFFLINE_MODE) ||
-+          (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) ||
-+          (vport->port_state != LPFC_VPORT_READY))
-               return -EPERM;
+ #include <asm/io.h>
+ #include <asm/system.h>
+@@ -67,7 +66,6 @@
+ #define ACPI_PROCESSOR_FILE_LIMIT     "limit"
+ #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
+ #define ACPI_PROCESSOR_NOTIFY_POWER   0x81
+-#define ACPI_PROCESSOR_NOTIFY_THROTTLING      0x82
  
-       pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
-@@ -238,9 +282,7 @@
-       }
+ #define ACPI_PROCESSOR_LIMIT_USER     0
+ #define ACPI_PROCESSOR_LIMIT_THERMAL  1
+@@ -86,8 +84,6 @@
+ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data);
+ static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
+ static int acpi_processor_handle_eject(struct acpi_processor *pr);
+-extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
+-
  
-       lpfc_set_loopback_flag(phba);
--      if (mbxstatus == MBX_TIMEOUT)
--              pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
--      else
-+      if (mbxstatus != MBX_TIMEOUT)
-               mempool_free(pmboxq, phba->mbox_mem_pool);
+ static struct acpi_driver acpi_processor_driver = {
+       .name = "processor",
+@@ -705,9 +701,6 @@
+               acpi_processor_cst_has_changed(pr);
+               acpi_bus_generate_event(device, event, 0);
+               break;
+-      case ACPI_PROCESSOR_NOTIFY_THROTTLING:
+-              acpi_processor_tstate_has_changed(pr);
+-              acpi_bus_generate_event(device, event, 0);
+       default:
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "Unsupported event [0x%x]\n", event));
+@@ -1031,15 +1024,11 @@
  
-       if (mbxstatus == MBXERR_ERROR)
-@@ -320,8 +362,10 @@
- static ssize_t
- lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+
-       int status = -EINVAL;
+       acpi_processor_ppc_init();
  
-       if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
-@@ -336,23 +380,26 @@
- static ssize_t
- lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+
-       return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
+-      cpuidle_register_driver(&acpi_idle_driver);
+-      acpi_do_set_cstate_limit = acpi_max_cstate_changed;
+       return 0;
  }
  
- static ssize_t
- lpfc_board_mode_show(struct class_device *cdev, char *buf)
+ static void __exit acpi_processor_exit(void)
  {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       char  * state;
+-      acpi_do_set_cstate_limit = NULL;
+-      cpuidle_unregister_driver(&acpi_idle_driver);
  
--      if (phba->hba_state == LPFC_HBA_ERROR)
-+      if (phba->link_state == LPFC_HBA_ERROR)
-               state = "error";
--      else if (phba->hba_state == LPFC_WARM_START)
-+      else if (phba->link_state == LPFC_WARM_START)
-               state = "warm start";
--      else if (phba->hba_state == LPFC_INIT_START)
-+      else if (phba->link_state == LPFC_INIT_START)
-               state = "offline";
-       else
-               state = "online";
-@@ -363,8 +410,9 @@
- static ssize_t
- lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       struct completion online_compl;
-       int status=0;
+       acpi_processor_ppc_exit();
  
-@@ -389,11 +437,166 @@
-               return -EIO;
- }
+diff -Nurb linux-2.6.22-590/drivers/acpi/processor_idle.c linux-2.6.22-570/drivers/acpi/processor_idle.c
+--- linux-2.6.22-590/drivers/acpi/processor_idle.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/processor_idle.c     2008-01-23 19:15:55.000000000 -0500
+@@ -40,7 +40,6 @@
+ #include <linux/sched.h>      /* need_resched() */
+ #include <linux/latency.h>
+ #include <linux/clockchips.h>
+-#include <linux/cpuidle.h>
  
-+int
-+lpfc_get_hba_info(struct lpfc_hba *phba,
-+                uint32_t *mxri, uint32_t *axri,
-+                uint32_t *mrpi, uint32_t *arpi,
-+                uint32_t *mvpi, uint32_t *avpi)
-+{
-+      struct lpfc_sli   *psli = &phba->sli;
-+      LPFC_MBOXQ_t *pmboxq;
-+      MAILBOX_t *pmb;
-+      int rc = 0;
-+
-+      /*
-+       * prevent udev from issuing mailbox commands until the port is
-+       * configured.
-+       */
-+      if (phba->link_state < LPFC_LINK_DOWN ||
-+          !phba->mbox_mem_pool ||
-+          (phba->sli.sli_flag & LPFC_SLI2_ACTIVE) == 0)
-+              return 0;
-+
-+      if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
-+              return 0;
-+
-+      pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (!pmboxq)
-+              return 0;
-+      memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
-+
-+      pmb = &pmboxq->mb;
-+      pmb->mbxCommand = MBX_READ_CONFIG;
-+      pmb->mbxOwner = OWN_HOST;
-+      pmboxq->context1 = NULL;
-+
-+      if ((phba->pport->fc_flag & FC_OFFLINE_MODE) ||
-+              (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
-+              rc = MBX_NOT_FINISHED;
+ /*
+  * Include the apic definitions for x86 to have the APIC timer related defines
+@@ -63,34 +62,25 @@
+ #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
+ ACPI_MODULE_NAME("processor_idle");
+ #define ACPI_PROCESSOR_FILE_POWER     "power"
+-#define PM_TIMER_TICKS_TO_US(p)               (((p) * 1000)/(PM_TIMER_FREQUENCY/1000))
+-#define C2_OVERHEAD                   1       /* 1us */
+-#define C3_OVERHEAD                   1       /* 1us */
+-
+-void acpi_max_cstate_changed(void)
+-{
+-      /* Driver will reset devices' max cstate limit */
+-      cpuidle_force_redetect_devices(&acpi_idle_driver);
+-}
+-
+-static int change_max_cstate(const char *val, struct kernel_param *kp)
+-{
+-      int max;
+-
+-      max = simple_strtol(val, NULL, 0);
+-      if (!max)
+-              return -EINVAL;
+-      max_cstate = max;
+-      if (acpi_do_set_cstate_limit)
+-              acpi_do_set_cstate_limit();
+-      return 0;
+-}
+-
+-module_param_call(max_cstate, change_max_cstate, param_get_uint, &max_cstate, 0644);
++#define US_TO_PM_TIMER_TICKS(t)               ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
++#define C2_OVERHEAD                   4       /* 1us (3.579 ticks per us) */
++#define C3_OVERHEAD                   4       /* 1us (3.579 ticks per us) */
++static void (*pm_idle_save) (void) __read_mostly;
++module_param(max_cstate, uint, 0644);
+ static unsigned int nocst __read_mostly;
+ module_param(nocst, uint, 0000);
++/*
++ * bm_history -- bit-mask with a bit per jiffy of bus-master activity
++ * 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms
++ * 800 HZ: 0xFFFFFFFF: 32 jiffies = 40ms
++ * 100 HZ: 0x0000000F: 4 jiffies = 40ms
++ * reduce history for more aggressive entry into C3
++ */
++static unsigned int bm_history __read_mostly =
++    (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
++module_param(bm_history, uint, 0644);
+ /* --------------------------------------------------------------------------
+                                 Power Management
+    -------------------------------------------------------------------------- */
+@@ -176,6 +166,88 @@
+       {},
+ };
++static inline u32 ticks_elapsed(u32 t1, u32 t2)
++{
++      if (t2 >= t1)
++              return (t2 - t1);
++      else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER))
++              return (((0x00FFFFFF - t1) + t2) & 0x00FFFFFF);
 +      else
-+              rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
-+
-+      if (rc != MBX_SUCCESS) {
-+              if (rc != MBX_TIMEOUT)
-+                      mempool_free(pmboxq, phba->mbox_mem_pool);
-+              return 0;
-+      }
-+
-+      if (mrpi)
-+              *mrpi = pmb->un.varRdConfig.max_rpi;
-+      if (arpi)
-+              *arpi = pmb->un.varRdConfig.avail_rpi;
-+      if (mxri)
-+              *mxri = pmb->un.varRdConfig.max_xri;
-+      if (axri)
-+              *axri = pmb->un.varRdConfig.avail_xri;
-+      if (mvpi)
-+              *mvpi = pmb->un.varRdConfig.max_vpi;
-+      if (avpi)
-+              *avpi = pmb->un.varRdConfig.avail_vpi;
-+
-+      mempool_free(pmboxq, phba->mbox_mem_pool);
-+      return 1;
++              return ((0xFFFFFFFF - t1) + t2);
 +}
 +
-+static ssize_t
-+lpfc_max_rpi_show(struct class_device *cdev, char *buf)
++static void
++acpi_processor_power_activate(struct acpi_processor *pr,
++                            struct acpi_processor_cx *new)
 +{
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+      uint32_t cnt;
++      struct acpi_processor_cx *old;
 +
-+      if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL, NULL, NULL))
-+              return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
-+      return snprintf(buf, PAGE_SIZE, "Unknown\n");
-+}
++      if (!pr || !new)
++              return;
 +
-+static ssize_t
-+lpfc_used_rpi_show(struct class_device *cdev, char *buf)
-+{
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+      uint32_t cnt, acnt;
++      old = pr->power.state;
 +
-+      if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt, NULL, NULL))
-+              return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
-+      return snprintf(buf, PAGE_SIZE, "Unknown\n");
-+}
++      if (old)
++              old->promotion.count = 0;
++      new->demotion.count = 0;
 +
-+static ssize_t
-+lpfc_max_xri_show(struct class_device *cdev, char *buf)
-+{
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+      uint32_t cnt;
++      /* Cleanup from old state. */
++      if (old) {
++              switch (old->type) {
++              case ACPI_STATE_C3:
++                      /* Disable bus master reload */
++                      if (new->type != ACPI_STATE_C3 && pr->flags.bm_check)
++                              acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
++                      break;
++              }
++      }
 +
-+      if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL, NULL, NULL))
-+              return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
-+      return snprintf(buf, PAGE_SIZE, "Unknown\n");
-+}
++      /* Prepare to use new state. */
++      switch (new->type) {
++      case ACPI_STATE_C3:
++              /* Enable bus master reload */
++              if (old->type != ACPI_STATE_C3 && pr->flags.bm_check)
++                      acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
++              break;
++      }
 +
-+static ssize_t
-+lpfc_used_xri_show(struct class_device *cdev, char *buf)
-+{
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+      uint32_t cnt, acnt;
++      pr->power.state = new;
 +
-+      if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL, NULL, NULL))
-+              return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
-+      return snprintf(buf, PAGE_SIZE, "Unknown\n");
++      return;
 +}
 +
-+static ssize_t
-+lpfc_max_vpi_show(struct class_device *cdev, char *buf)
++static void acpi_safe_halt(void)
 +{
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+      uint32_t cnt;
-+
-+      if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, NULL))
-+              return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
-+      return snprintf(buf, PAGE_SIZE, "Unknown\n");
++      current_thread_info()->status &= ~TS_POLLING;
++      /*
++       * TS_POLLING-cleared state must be visible before we
++       * test NEED_RESCHED:
++       */
++      smp_mb();
++      if (!need_resched())
++              safe_halt();
++      current_thread_info()->status |= TS_POLLING;
 +}
 +
-+static ssize_t
-+lpfc_used_vpi_show(struct class_device *cdev, char *buf)
-+{
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+      uint32_t cnt, acnt;
-+
-+      if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, &acnt))
-+              return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
-+      return snprintf(buf, PAGE_SIZE, "Unknown\n");
-+}
++static atomic_t c3_cpu_count;
 +
-+static ssize_t
-+lpfc_npiv_info_show(struct class_device *cdev, char *buf)
++/* Common C-state entry for C2, C3, .. */
++static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
 +{
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+
-+      if (!(phba->max_vpi))
-+              return snprintf(buf, PAGE_SIZE, "NPIV Not Supported\n");
-+      if (vport->port_type == LPFC_PHYSICAL_PORT)
-+              return snprintf(buf, PAGE_SIZE, "NPIV Physical\n");
-+      return snprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi);
-+}
-+
- static ssize_t
- lpfc_poll_show(struct class_device *cdev, char *buf)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
- }
-@@ -402,8 +605,9 @@
- lpfc_poll_store(struct class_device *cdev, const char *buf,
-               size_t count)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       uint32_t creg_val;
-       uint32_t old_val;
-       int val=0;
-@@ -417,7 +621,7 @@
-       if ((val & 0x3) != val)
-               return -EINVAL;
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       old_val = phba->cfg_poll;
-@@ -432,16 +636,16 @@
-                       lpfc_poll_start_timer(phba);
-               }
-       } else if (val != 0x0) {
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(&phba->hbalock);
-               return -EINVAL;
-       }
-       if (!(val & DISABLE_FCP_RING_INT) &&
-           (old_val & DISABLE_FCP_RING_INT))
-       {
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(&phba->hbalock);
-               del_timer(&phba->fcp_poll_timer);
--              spin_lock_irq(phba->host->host_lock);
-+              spin_lock_irq(&phba->hbalock);
-               creg_val = readl(phba->HCregaddr);
-               creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
-               writel(creg_val, phba->HCregaddr);
-@@ -450,7 +654,7 @@
-       phba->cfg_poll = val;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
-       return strlen(buf);
- }
-@@ -459,8 +663,9 @@
- static ssize_t \
- lpfc_##attr##_show(struct class_device *cdev, char *buf) \
- { \
--      struct Scsi_Host *host = class_to_shost(cdev);\
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
-+      struct Scsi_Host  *shost = class_to_shost(cdev);\
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
-+      struct lpfc_hba   *phba = vport->phba;\
-       int val = 0;\
-       val = phba->cfg_##attr;\
-       return snprintf(buf, PAGE_SIZE, "%d\n",\
-@@ -471,8 +676,9 @@
- static ssize_t \
- lpfc_##attr##_show(struct class_device *cdev, char *buf) \
- { \
--      struct Scsi_Host *host = class_to_shost(cdev);\
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
-+      struct Scsi_Host  *shost = class_to_shost(cdev);\
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
-+      struct lpfc_hba   *phba = vport->phba;\
-       int val = 0;\
-       val = phba->cfg_##attr;\
-       return snprintf(buf, PAGE_SIZE, "%#x\n",\
-@@ -514,8 +720,9 @@
- static ssize_t \
- lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
- { \
--      struct Scsi_Host *host = class_to_shost(cdev);\
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
-+      struct Scsi_Host  *shost = class_to_shost(cdev);\
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
-+      struct lpfc_hba   *phba = vport->phba;\
-       int val=0;\
-       if (!isdigit(buf[0]))\
-               return -EINVAL;\
-@@ -576,7 +783,7 @@
- static CLASS_DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL);
- static CLASS_DEVICE_ATTR(modelname, S_IRUGO, lpfc_modelname_show, NULL);
- static CLASS_DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
--static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_portnum_show, NULL);
-+static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
- static CLASS_DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
- static CLASS_DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
- static CLASS_DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);
-@@ -592,6 +799,13 @@
- static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
-                        lpfc_board_mode_show, lpfc_board_mode_store);
- static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
-+static CLASS_DEVICE_ATTR(max_vpi, S_IRUGO, lpfc_max_vpi_show, NULL);
-+static CLASS_DEVICE_ATTR(used_vpi, S_IRUGO, lpfc_used_vpi_show, NULL);
-+static CLASS_DEVICE_ATTR(max_rpi, S_IRUGO, lpfc_max_rpi_show, NULL);
-+static CLASS_DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL);
-+static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
-+static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
-+static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
- static char *lpfc_soft_wwn_key = "C99G71SL8032A";
-@@ -600,8 +814,9 @@
- lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf,
-                               size_t count)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       unsigned int cnt = count;
-       /*
-@@ -634,8 +849,10 @@
- static ssize_t
- lpfc_soft_wwpn_show(struct class_device *cdev, char *buf)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+
-       return snprintf(buf, PAGE_SIZE, "0x%llx\n",
-                       (unsigned long long)phba->cfg_soft_wwpn);
- }
-@@ -644,8 +861,9 @@
- static ssize_t
- lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       struct completion online_compl;
-       int stat1=0, stat2=0;
-       unsigned int i, j, cnt=count;
-@@ -680,9 +898,9 @@
-               }
-       }
-       phba->cfg_soft_wwpn = wwn_to_u64(wwpn);
--      fc_host_port_name(host) = phba->cfg_soft_wwpn;
-+      fc_host_port_name(shost) = phba->cfg_soft_wwpn;
-       if (phba->cfg_soft_wwnn)
--              fc_host_node_name(host) = phba->cfg_soft_wwnn;
-+              fc_host_node_name(shost) = phba->cfg_soft_wwnn;
-       dev_printk(KERN_NOTICE, &phba->pcidev->dev,
-                  "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no);
-@@ -777,6 +995,15 @@
- static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
-                        lpfc_poll_show, lpfc_poll_store);
-+int  lpfc_sli_mode = 0;
-+module_param(lpfc_sli_mode, int, 0);
-+MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:"
-+               " 0 - auto (SLI-3 if supported),"
-+               " 2 - select SLI-2 even on SLI-3 capable HBAs,"
-+               " 3 - select SLI-3");
-+
-+LPFC_ATTR_R(npiv_enable, 0, 0, 1, "Enable NPIV functionality");
-+
- /*
- # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
- # until the timer expires. Value range is [0,255]. Default value is 30.
-@@ -790,8 +1017,9 @@
- static ssize_t
- lpfc_nodev_tmo_show(struct class_device *cdev, char *buf)
- {
--      struct Scsi_Host *host = class_to_shost(cdev);
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       int val = 0;
-       val = phba->cfg_devloss_tmo;
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-@@ -832,13 +1060,19 @@
- static void
- lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba)
- {
-+      struct lpfc_vport *vport;
-+      struct Scsi_Host  *shost;
-       struct lpfc_nodelist  *ndlp;
--      spin_lock_irq(phba->host->host_lock);
--      list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp)
-+      list_for_each_entry(vport, &phba->port_list, listentry) {
-+              shost = lpfc_shost_from_vport(vport);
-+              spin_lock_irq(shost->host_lock);
-+              list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp)
-               if (ndlp->rport)
--                      ndlp->rport->dev_loss_tmo = phba->cfg_devloss_tmo;
--      spin_unlock_irq(phba->host->host_lock);
-+                              ndlp->rport->dev_loss_tmo =
-+                                      phba->cfg_devloss_tmo;
-+              spin_unlock_irq(shost->host_lock);
++      if (cstate->space_id == ACPI_CSTATE_FFH) {
++              /* Call into architectural FFH based C-state */
++              acpi_processor_ffh_cstate_enter(cstate);
++      } else {
++              int unused;
++              /* IO port based C-state */
++              inb(cstate->address);
++              /* Dummy wait op - must do something useless after P_LVL2 read
++                 because chipsets cannot guarantee that STPCLK# signal
++                 gets asserted in time to freeze execution properly. */
++              unused = inl(acpi_gbl_FADT.xpm_timer_block.address);
 +      }
- }
- static int
-@@ -946,6 +1180,33 @@
-           "Max number of FCP commands we can queue to a lpfc HBA");
++}
++
+ #ifdef ARCH_APICTIMER_STOPS_ON_C3
  
  /*
-+# peer_port_login:  This parameter allows/prevents logins
-+# between peer ports hosted on the same physical port.
-+# When this parameter is set 0 peer ports of same physical port
-+# are not allowed to login to each other.
-+# When this parameter is set 1 peer ports of same physical port
-+# are allowed to login to each other.
-+# Default value of this parameter is 0.
-+*/
-+LPFC_ATTR_R(peer_port_login, 0, 0, 1,
-+          "Allow peer ports on the same physical port to login to each "
-+          "other.");
-+
-+/*
-+# vport_restrict_login:  This parameter allows/prevents logins
-+# between Virtual Ports and remote initiators.
-+# When this parameter is not set (0) Virtual Ports will accept PLOGIs from
-+# other initiators and will attempt to PLOGI all remote ports.
-+# When this parameter is set (1) Virtual Ports will reject PLOGIs from
-+# remote ports and will not attempt to PLOGI to other initiators.
-+# This parameter does not restrict to the physical port.
-+# This parameter does not restrict logins to Fabric resident remote ports.
-+# Default value of this parameter is 1.
-+*/
-+LPFC_ATTR_RW(vport_restrict_login, 1, 0, 1,
-+          "Restrict virtual ports login to remote initiators.");
-+
-+/*
- # Some disk devices have a "select ID" or "select Target" capability.
- # From a protocol standpoint "select ID" usually means select the
- # Fibre channel "ALPA".  In the FC-AL Profile there is an "informative
-@@ -1088,7 +1349,8 @@
- LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible");
+@@ -269,7 +341,6 @@
+       return 0;
+ }
  
+-<<<<<<< HEAD/drivers/acpi/processor_idle.c
+ static void acpi_processor_idle(void)
+ {
+       struct acpi_processor *pr = NULL;
+@@ -641,8 +712,6 @@
+       return 0;
+ }
  
--struct class_device_attribute *lpfc_host_attrs[] = {
-+
-+struct class_device_attribute *lpfc_hba_attrs[] = {
-       &class_device_attr_info,
-       &class_device_attr_serialnum,
-       &class_device_attr_modeldesc,
-@@ -1104,6 +1366,8 @@
-       &class_device_attr_lpfc_log_verbose,
-       &class_device_attr_lpfc_lun_queue_depth,
-       &class_device_attr_lpfc_hba_queue_depth,
-+      &class_device_attr_lpfc_peer_port_login,
-+      &class_device_attr_lpfc_vport_restrict_login,
-       &class_device_attr_lpfc_nodev_tmo,
-       &class_device_attr_lpfc_devloss_tmo,
-       &class_device_attr_lpfc_fcp_class,
-@@ -1119,9 +1383,17 @@
-       &class_device_attr_lpfc_multi_ring_type,
-       &class_device_attr_lpfc_fdmi_on,
-       &class_device_attr_lpfc_max_luns,
-+      &class_device_attr_lpfc_npiv_enable,
-       &class_device_attr_nport_evt_cnt,
-       &class_device_attr_management_version,
-       &class_device_attr_board_mode,
-+      &class_device_attr_max_vpi,
-+      &class_device_attr_used_vpi,
-+      &class_device_attr_max_rpi,
-+      &class_device_attr_used_rpi,
-+      &class_device_attr_max_xri,
-+      &class_device_attr_used_xri,
-+      &class_device_attr_npiv_info,
-       &class_device_attr_issue_reset,
-       &class_device_attr_lpfc_poll,
-       &class_device_attr_lpfc_poll_tmo,
-@@ -1136,9 +1408,11 @@
- sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+-=======
+->>>>>>> /drivers/acpi/processor_idle.c
+ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
  {
-       size_t buf_off;
--      struct Scsi_Host *host = class_to_shost(container_of(kobj,
--                                           struct class_device, kobj));
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct class_device *cdev = container_of(kobj, struct class_device,
-+                                               kobj);
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
  
-       if ((off + count) > FF_REG_AREA_SIZE)
-               return -ERANGE;
-@@ -1148,18 +1422,16 @@
-       if (off % 4 || count % 4 || (unsigned long)buf % 4)
-               return -EINVAL;
+@@ -860,7 +929,7 @@
+        * Normalize the C2 latency to expidite policy
+        */
+       cx->valid = 1;
+-      cx->latency_ticks = cx->latency;
++      cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
  
--      spin_lock_irq(phba->host->host_lock);
--
--      if (!(phba->fc_flag & FC_OFFLINE_MODE)) {
--              spin_unlock_irq(phba->host->host_lock);
-+      if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
-               return -EPERM;
-       }
+       return;
+ }
+@@ -934,7 +1003,7 @@
+        * use this in our C3 policy
+        */
+       cx->valid = 1;
+-      cx->latency_ticks = cx->latency;
++      cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
  
-+      spin_lock_irq(&phba->hbalock);
-       for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t))
-               writel(*((uint32_t *)(buf + buf_off)),
-                      phba->ctrl_regs_memmap_p + off + buf_off);
+       return;
+ }
+@@ -1000,6 +1069,18 @@
+       pr->power.count = acpi_processor_power_verify(pr);
  
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
+       /*
++       * Set Default Policy
++       * ------------------
++       * Now that we know which states are supported, set the default
++       * policy.  Note that this policy can be changed dynamically
++       * (e.g. encourage deeper sleeps to conserve battery life when
++       * not on AC).
++       */
++      result = acpi_processor_set_power_policy(pr);
++      if (result)
++              return result;
++
++      /*
+        * if one state of type C2 or C3 is available, mark this
+        * CPU as being "idle manageable"
+        */
+@@ -1016,6 +1097,9 @@
  
-       return count;
- }
-@@ -1169,9 +1441,11 @@
+ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
  {
-       size_t buf_off;
-       uint32_t * tmp_ptr;
--      struct Scsi_Host *host = class_to_shost(container_of(kobj,
--                                           struct class_device, kobj));
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct class_device *cdev = container_of(kobj, struct class_device,
-+                                               kobj);
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       if (off > FF_REG_AREA_SIZE)
-               return -ERANGE;
-@@ -1184,14 +1458,14 @@
-       if (off % 4 || count % 4 || (unsigned long)buf % 4)
++      int result = 0;
++
++
+       if (!pr)
                return -EINVAL;
  
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) {
-               tmp_ptr = (uint32_t *)(buf + buf_off);
-               *tmp_ptr = readl(phba->ctrl_regs_memmap_p + off + buf_off);
-       }
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
+@@ -1026,9 +1110,16 @@
+       if (!pr->flags.power_setup_done)
+               return -ENODEV;
  
-       return count;
+-      acpi_processor_get_power_info(pr);
+-      return cpuidle_force_redetect(per_cpu(cpuidle_devices, pr->id),
+-              &acpi_idle_driver);
++      /* Fall back to the default idle loop */
++      pm_idle = pm_idle_save;
++      synchronize_sched();    /* Relies on interrupts forcing exit from idle. */
++
++      pr->flags.power = 0;
++      result = acpi_processor_get_power_info(pr);
++      if ((pr->flags.power == 1) && (pr->flags.power_setup_done))
++              pm_idle = acpi_processor_idle;
++
++      return result;
  }
-@@ -1200,7 +1474,6 @@
-       .attr = {
-               .name = "ctlreg",
-               .mode = S_IRUSR | S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = 256,
-       .read = sysfs_ctlreg_read,
-@@ -1209,7 +1482,7 @@
  
+ /* proc interface */
+@@ -1114,6 +1205,30 @@
+       .release = single_release,
+ };
  
- static void
--sysfs_mbox_idle (struct lpfc_hba * phba)
-+sysfs_mbox_idle(struct lpfc_hba *phba)
- {
-       phba->sysfs_mbox.state = SMBOX_IDLE;
-       phba->sysfs_mbox.offset = 0;
-@@ -1224,10 +1497,12 @@
- static ssize_t
- sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
++#ifdef CONFIG_SMP
++static void smp_callback(void *v)
++{
++      /* we already woke the CPU up, nothing more to do */
++}
++
++/*
++ * This function gets called when a part of the kernel has a new latency
++ * requirement.  This means we need to get all processors out of their C-state,
++ * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that
++ * wakes them all right up.
++ */
++static int acpi_processor_latency_notify(struct notifier_block *b,
++              unsigned long l, void *v)
++{
++      smp_call_function(smp_callback, NULL, 0, 1);
++      return NOTIFY_OK;
++}
++
++static struct notifier_block acpi_processor_latency_notifier = {
++      .notifier_call = acpi_processor_latency_notify,
++};
++#endif
++
+ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
+                             struct acpi_device *device)
  {
--      struct Scsi_Host * host =
--              class_to_shost(container_of(kobj, struct class_device, kobj));
--      struct lpfc_hba * phba = (struct lpfc_hba*)host->hostdata;
--      struct lpfcMboxq * mbox = NULL;
-+      struct class_device *cdev = container_of(kobj, struct class_device,
-+                                               kobj);
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+      struct lpfcMboxq  *mbox = NULL;
-       if ((count + off) > MAILBOX_CMD_SIZE)
-               return -ERANGE;
-@@ -1245,7 +1520,7 @@
-               memset(mbox, 0, sizeof (LPFC_MBOXQ_t));
-       }
--      spin_lock_irq(host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       if (off == 0) {
-               if (phba->sysfs_mbox.mbox)
-@@ -1256,9 +1531,9 @@
-       } else {
-               if (phba->sysfs_mbox.state  != SMBOX_WRITING ||
-                   phba->sysfs_mbox.offset != off           ||
--                  phba->sysfs_mbox.mbox   == NULL ) {
-+                  phba->sysfs_mbox.mbox   == NULL) {
-                       sysfs_mbox_idle(phba);
--                      spin_unlock_irq(host->host_lock);
-+                      spin_unlock_irq(&phba->hbalock);
-                       return -EAGAIN;
-               }
+@@ -1130,6 +1245,9 @@
+                              "ACPI: processor limited to max C-state %d\n",
+                              max_cstate);
+               first_run++;
++#ifdef CONFIG_SMP
++              register_latency_notifier(&acpi_processor_latency_notifier);
++#endif
        }
-@@ -1268,7 +1543,7 @@
-       phba->sysfs_mbox.offset = off + count;
--      spin_unlock_irq(host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
-       return count;
- }
-@@ -1276,10 +1551,11 @@
- static ssize_t
- sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
- {
--      struct Scsi_Host *host =
--              class_to_shost(container_of(kobj, struct class_device,
--                                          kobj));
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct class_device *cdev = container_of(kobj, struct class_device,
-+                                               kobj);
-+      struct Scsi_Host  *shost = class_to_shost(cdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       int rc;
-       if (off > MAILBOX_CMD_SIZE)
-@@ -1294,7 +1570,7 @@
-       if (off && count == 0)
-               return 0;
  
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
+       if (!pr)
+@@ -1146,7 +1264,6 @@
  
-       if (off == 0 &&
-           phba->sysfs_mbox.state  == SMBOX_WRITING &&
-@@ -1317,12 +1593,12 @@
-               case MBX_SET_MASK:
-               case MBX_SET_SLIM:
-               case MBX_SET_DEBUG:
--                      if (!(phba->fc_flag & FC_OFFLINE_MODE)) {
-+                      if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
-                               printk(KERN_WARNING "mbox_read:Command 0x%x "
-                                      "is illegal in on-line state\n",
-                                      phba->sysfs_mbox.mbox->mb.mbxCommand);
-                               sysfs_mbox_idle(phba);
--                              spin_unlock_irq(phba->host->host_lock);
-+                              spin_unlock_irq(&phba->hbalock);
-                               return -EPERM;
-                       }
-               case MBX_LOAD_SM:
-@@ -1352,48 +1628,48 @@
-                       printk(KERN_WARNING "mbox_read: Illegal Command 0x%x\n",
-                              phba->sysfs_mbox.mbox->mb.mbxCommand);
-                       sysfs_mbox_idle(phba);
--                      spin_unlock_irq(phba->host->host_lock);
-+                      spin_unlock_irq(&phba->hbalock);
-                       return -EPERM;
-               default:
-                       printk(KERN_WARNING "mbox_read: Unknown Command 0x%x\n",
-                              phba->sysfs_mbox.mbox->mb.mbxCommand);
-                       sysfs_mbox_idle(phba);
--                      spin_unlock_irq(phba->host->host_lock);
-+                      spin_unlock_irq(&phba->hbalock);
-                       return -EPERM;
-               }
+       acpi_processor_get_power_info(pr);
  
--              if (phba->fc_flag & FC_BLOCK_MGMT_IO) {
-+              phba->sysfs_mbox.mbox->vport = vport;
+-
+       /*
+        * Install the idle handler if processor power management is supported.
+        * Note that we use previously set idle handler will be used on
+@@ -1159,6 +1276,11 @@
+                               printk(" C%d[C%d]", i,
+                                      pr->power.states[i].type);
+               printk(")\n");
 +
-+              if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
-                       sysfs_mbox_idle(phba);
--                      spin_unlock_irq(host->host_lock);
-+                      spin_unlock_irq(&phba->hbalock);
-                       return  -EAGAIN;
-               }
--              if ((phba->fc_flag & FC_OFFLINE_MODE) ||
-+              if ((vport->fc_flag & FC_OFFLINE_MODE) ||
-                   (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){
++              if (pr->id == 0) {
++                      pm_idle_save = pm_idle;
++                      pm_idle = acpi_processor_idle;
++              }
+       }
  
--                      spin_unlock_irq(phba->host->host_lock);
-+                      spin_unlock_irq(&phba->hbalock);
-                       rc = lpfc_sli_issue_mbox (phba,
-                                                 phba->sysfs_mbox.mbox,
-                                                 MBX_POLL);
--                      spin_lock_irq(phba->host->host_lock);
-+                      spin_lock_irq(&phba->hbalock);
+       /* 'power' [R] */
+@@ -1186,332 +1308,21 @@
+       if (acpi_device_dir(device))
+               remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,
+                                 acpi_device_dir(device));
+-      return 0;
+-}
+-
+-/**
+- * ticks_elapsed - a helper function that determines how many ticks (in US)
+- *               have elapsed between two PM Timer timestamps
+- * @t1: the start time
+- * @t2: the end time
+- */
+-static inline u32 ticks_elapsed(u32 t1, u32 t2)
+-{
+-      if (t2 >= t1)
+-              return PM_TIMER_TICKS_TO_US(t2 - t1);
+-      else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER))
+-              return PM_TIMER_TICKS_TO_US(((0x00FFFFFF - t1) + t2) & 0x00FFFFFF);
+-      else
+-              return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2);
+-}
  
-               } else {
--                      spin_unlock_irq(phba->host->host_lock);
-+                      spin_unlock_irq(&phba->hbalock);
-                       rc = lpfc_sli_issue_mbox_wait (phba,
-                                                      phba->sysfs_mbox.mbox,
-                               lpfc_mbox_tmo_val(phba,
-                                   phba->sysfs_mbox.mbox->mb.mbxCommand) * HZ);
--                      spin_lock_irq(phba->host->host_lock);
-+                      spin_lock_irq(&phba->hbalock);
-               }
+-/**
+- * acpi_idle_update_bm_rld - updates the BM_RLD bit depending on target state
+- * @pr: the processor
+- * @target: the new target state
+- */
+-static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr,
+-                                         struct acpi_processor_cx *target)
+-{
+-      if (pr->flags.bm_rld_set && target->type != ACPI_STATE_C3) {
+-              acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
+-              pr->flags.bm_rld_set = 0;
+-      }
++      /* Unregister the idle handler when processor #0 is removed. */
++      if (pr->id == 0) {
++              pm_idle = pm_idle_save;
  
-               if (rc != MBX_SUCCESS) {
-                       if (rc == MBX_TIMEOUT) {
--                              phba->sysfs_mbox.mbox->mbox_cmpl =
--                                      lpfc_sli_def_mbox_cmpl;
-                               phba->sysfs_mbox.mbox = NULL;
-                       }
-                       sysfs_mbox_idle(phba);
--                      spin_unlock_irq(host->host_lock);
-+                      spin_unlock_irq(&phba->hbalock);
-                       return  (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
-               }
-               phba->sysfs_mbox.state = SMBOX_READING;
-@@ -1402,7 +1678,7 @@
-                phba->sysfs_mbox.state  != SMBOX_READING) {
-               printk(KERN_WARNING  "mbox_read: Bad State\n");
-               sysfs_mbox_idle(phba);
--              spin_unlock_irq(host->host_lock);
-+              spin_unlock_irq(&phba->hbalock);
-               return -EAGAIN;
+-      if (!pr->flags.bm_rld_set && target->type == ACPI_STATE_C3) {
+-              acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
+-              pr->flags.bm_rld_set = 1;
+-      }
+-}
+-
+-/**
+- * acpi_idle_do_entry - a helper function that does C2 and C3 type entry
+- * @cx: cstate data
+- */
+-static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
+-{
+-      if (cx->space_id == ACPI_CSTATE_FFH) {
+-              /* Call into architectural FFH based C-state */
+-              acpi_processor_ffh_cstate_enter(cx);
+-      } else {
+-              int unused;
+-              /* IO port based C-state */
+-              inb(cx->address);
+-              /* Dummy wait op - must do something useless after P_LVL2 read
+-                 because chipsets cannot guarantee that STPCLK# signal
+-                 gets asserted in time to freeze execution properly. */
+-              unused = inl(acpi_gbl_FADT.xpm_timer_block.address);
+-      }
+-}
+-
+-/**
+- * acpi_idle_enter_c1 - enters an ACPI C1 state-type
+- * @dev: the target CPU
+- * @state: the state data
+- *
+- * This is equivalent to the HALT instruction.
+- */
+-static int acpi_idle_enter_c1(struct cpuidle_device *dev,
+-                            struct cpuidle_state *state)
+-{
+-      struct acpi_processor *pr;
+-      struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+-      pr = processors[smp_processor_id()];
+-
+-      if (unlikely(!pr))
+-              return 0;
+-
+-      if (pr->flags.bm_check)
+-              acpi_idle_update_bm_rld(pr, cx);
+-
+-      current_thread_info()->status &= ~TS_POLLING;
+               /*
+-       * TS_POLLING-cleared state must be visible before we test
+-       * NEED_RESCHED:
+-       */
+-      smp_mb();
+-      if (!need_resched())
+-              safe_halt();
+-      current_thread_info()->status |= TS_POLLING;
+-
+-      cx->usage++;
+-
+-      return 0;
+-}
+-
+-/**
+- * acpi_idle_enter_c2 - enters an ACPI C2 state-type
+- * @dev: the target CPU
+- * @state: the state data
+- */
+-static int acpi_idle_enter_c2(struct cpuidle_device *dev,
+-                            struct cpuidle_state *state)
+-{
+-      struct acpi_processor *pr;
+-      struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+-      u32 t1, t2;
+-      pr = processors[smp_processor_id()];
+-
+-      if (unlikely(!pr))
+-              return 0;
+-
+-      if (pr->flags.bm_check)
+-              acpi_idle_update_bm_rld(pr, cx);
+-
+-      local_irq_disable();
+-      current_thread_info()->status &= ~TS_POLLING;
+-      /*
+-       * TS_POLLING-cleared state must be visible before we test
+-       * NEED_RESCHED:
+-       */
+-      smp_mb();
+-
+-      if (unlikely(need_resched())) {
+-              current_thread_info()->status |= TS_POLLING;
+-              local_irq_enable();
+-              return 0;
+-      }
+-
+-      t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+-      acpi_state_timer_broadcast(pr, cx, 1);
+-      acpi_idle_do_entry(cx);
+-      t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+-
+-#ifdef CONFIG_GENERIC_TIME
+-      /* TSC halts in C2, so notify users */
+-      mark_tsc_unstable("possible TSC halt in C2");
++               * We are about to unload the current idle thread pm callback
++               * (pm_idle), Wait for all processors to update cached/local
++               * copies of pm_idle before proceeding.
++               */
++              cpu_idle_wait();
++#ifdef CONFIG_SMP
++              unregister_latency_notifier(&acpi_processor_latency_notifier);
+ #endif
+-
+-      local_irq_enable();
+-      current_thread_info()->status |= TS_POLLING;
+-
+-      cx->usage++;
+-
+-      acpi_state_timer_broadcast(pr, cx, 0);
+-      return ticks_elapsed(t1, t2);
+-}
+-
+-static int c3_cpu_count;
+-static DEFINE_SPINLOCK(c3_lock);
+-
+-/**
+- * acpi_idle_enter_c3 - enters an ACPI C3 state-type
+- * @dev: the target CPU
+- * @state: the state data
+- *
+- * Similar to C2 entry, except special bus master handling is needed.
+- */
+-static int acpi_idle_enter_c3(struct cpuidle_device *dev,
+-                            struct cpuidle_state *state)
+-{
+-      struct acpi_processor *pr;
+-      struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+-      u32 t1, t2;
+-      pr = processors[smp_processor_id()];
+-
+-      if (unlikely(!pr))
+-              return 0;
+-
+-      if (pr->flags.bm_check)
+-              acpi_idle_update_bm_rld(pr, cx);
+-
+-      local_irq_disable();
+-      current_thread_info()->status &= ~TS_POLLING;
+-      /*
+-       * TS_POLLING-cleared state must be visible before we test
+-       * NEED_RESCHED:
+-       */
+-      smp_mb();
+-
+-      if (unlikely(need_resched())) {
+-              current_thread_info()->status |= TS_POLLING;
+-              local_irq_enable();
+-              return 0;
+-      }
+-
+-      /* disable bus master */
+-      if (pr->flags.bm_check) {
+-              spin_lock(&c3_lock);
+-                      c3_cpu_count++;
+-              if (c3_cpu_count == num_online_cpus()) {
+-                      /*
+-                       * All CPUs are trying to go to C3
+-                       * Disable bus master arbitration
+-                       */
+-                      acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
+-              }
+-              spin_unlock(&c3_lock);
+-      } else {
+-              /* SMP with no shared cache... Invalidate cache  */
+-              ACPI_FLUSH_CPU_CACHE();
+-      }
+-
+-      /* Get start time (ticks) */
+-      t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+-      acpi_state_timer_broadcast(pr, cx, 1);
+-      acpi_idle_do_entry(cx);
+-      t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
+-
+-      if (pr->flags.bm_check) {
+-              spin_lock(&c3_lock);
+-              /* Enable bus master arbitration */
+-              if (c3_cpu_count == num_online_cpus())
+-                      acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
+-              c3_cpu_count--;
+-              spin_unlock(&c3_lock);
        }
  
-@@ -1413,7 +1689,7 @@
-       if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE)
-               sysfs_mbox_idle(phba);
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
-       return count;
+-#ifdef CONFIG_GENERIC_TIME
+-      /* TSC halts in C3, so notify users */
+-      mark_tsc_unstable("TSC halts in C3");
+-#endif
+-
+-      local_irq_enable();
+-      current_thread_info()->status |= TS_POLLING;
+-
+-      cx->usage++;
+-
+-      acpi_state_timer_broadcast(pr, cx, 0);
+-      return ticks_elapsed(t1, t2);
+-}
+-
+-/**
+- * acpi_idle_bm_check - checks if bus master activity was detected
+- */
+-static int acpi_idle_bm_check(void)
+-{
+-      u32 bm_status = 0;
+-
+-      acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
+-      if (bm_status)
+-              acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
+-      /*
+-       * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
+-       * the true state of bus mastering activity; forcing us to
+-       * manually check the BMIDEA bit of each IDE channel.
+-       */
+-      else if (errata.piix4.bmisx) {
+-              if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01)
+-                  || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
+-                      bm_status = 1;
+-      }
+-      return bm_status;
+-}
+-
+-/**
+- * acpi_idle_init - attaches the driver to a CPU
+- * @dev: the CPU
+- */
+-static int acpi_idle_init(struct cpuidle_device *dev)
+-{
+-      int cpu = dev->cpu;
+-      int i, count = 0;
+-      struct acpi_processor_cx *cx;
+-      struct cpuidle_state *state;
+-
+-      struct acpi_processor *pr = processors[cpu];
+-
+-      if (!pr->flags.power_setup_done)
+-              return -EINVAL;
+-
+-      if (pr->flags.power == 0) {
+-              return -EINVAL;
+-      }
+-
+-      for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
+-              cx = &pr->power.states[i];
+-              state = &dev->states[count];
+-
+-              if (!cx->valid)
+-                      continue;
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-              if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
+-                  !pr->flags.has_cst &&
+-                  !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
+-                      continue;
+-#endif
+-              cpuidle_set_statedata(state, cx);
+-
+-              state->exit_latency = cx->latency;
+-              state->target_residency = cx->latency * 6;
+-              state->power_usage = cx->power;
+-
+-              state->flags = 0;
+-              switch (cx->type) {
+-                      case ACPI_STATE_C1:
+-                      state->flags |= CPUIDLE_FLAG_SHALLOW;
+-                      state->enter = acpi_idle_enter_c1;
+-                      break;
+-
+-                      case ACPI_STATE_C2:
+-                      state->flags |= CPUIDLE_FLAG_BALANCED;
+-                      state->flags |= CPUIDLE_FLAG_TIME_VALID;
+-                      state->enter = acpi_idle_enter_c2;
+-                      break;
+-
+-                      case ACPI_STATE_C3:
+-                      state->flags |= CPUIDLE_FLAG_DEEP;
+-                      state->flags |= CPUIDLE_FLAG_TIME_VALID;
+-                      state->flags |= CPUIDLE_FLAG_CHECK_BM;
+-                      state->enter = acpi_idle_enter_c3;
+-                      break;
+-              }
+-
+-              count++;
+-      }
+-
+-      if (!count)
+-              return -EINVAL;
+-
+-      dev->state_count = count;
+       return 0;
  }
-@@ -1422,7 +1698,6 @@
-       .attr = {
-               .name = "mbox",
-               .mode = S_IRUSR | S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = MAILBOX_CMD_SIZE,
-       .read = sysfs_mbox_read,
-@@ -1430,35 +1705,35 @@
- };
+-
+-struct cpuidle_driver acpi_idle_driver = {
+-      .name =         "acpi_idle",
+-      .init =         acpi_idle_init,
+-      .redetect =     acpi_idle_init,
+-      .bm_check =     acpi_idle_bm_check,
+-      .owner =        THIS_MODULE,
+-};
+diff -Nurb linux-2.6.22-590/drivers/acpi/processor_throttling.c linux-2.6.22-570/drivers/acpi/processor_throttling.c
+--- linux-2.6.22-590/drivers/acpi/processor_throttling.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/processor_throttling.c       2007-07-08 19:32:17.000000000 -0400
+@@ -44,231 +44,17 @@
+ #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
+ ACPI_MODULE_NAME("processor_throttling");
  
- int
--lpfc_alloc_sysfs_attr(struct lpfc_hba *phba)
-+lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
+-static int acpi_processor_get_throttling(struct acpi_processor *pr);
+-int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
+-
+-static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
+-{
+-      acpi_status status = 0;
+-      unsigned long tpc = 0;
+-
+-      if (!pr)
+-              return -EINVAL;
+-      status = acpi_evaluate_integer(pr->handle, "_TPC", NULL, &tpc);
+-      if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+-              ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TPC"));
+-              return -ENODEV;
+-      }
+-      pr->throttling_platform_limit = (int)tpc;
+-      return 0;
+-}
+-
+-int acpi_processor_tstate_has_changed(struct acpi_processor *pr)
+-{
+-      return acpi_processor_get_platform_limit(pr);
+-}
+-
+-/* --------------------------------------------------------------------------
+-                             _PTC, _TSS, _TSD support 
+-   -------------------------------------------------------------------------- */
+-static int acpi_processor_get_throttling_control(struct acpi_processor *pr)
+-{
+-      int result = 0;
+-      acpi_status status = 0;
+-      struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+-      union acpi_object *ptc = NULL;
+-      union acpi_object obj = { 0 };
+-
+-      status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer);
+-      if (ACPI_FAILURE(status)) {
+-              ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTC"));
+-              return -ENODEV;
+-      }
+-
+-      ptc = (union acpi_object *)buffer.pointer;
+-      if (!ptc || (ptc->type != ACPI_TYPE_PACKAGE)
+-          || (ptc->package.count != 2)) {
+-              printk(KERN_ERR PREFIX "Invalid _PTC data\n");
+-              result = -EFAULT;
+-              goto end;
+-      }
+-
+-      /*
+-       * control_register
+-       */
+-
+-      obj = ptc->package.elements[0];
+-
+-      if ((obj.type != ACPI_TYPE_BUFFER)
+-          || (obj.buffer.length < sizeof(struct acpi_ptc_register))
+-          || (obj.buffer.pointer == NULL)) {
+-              printk(KERN_ERR PREFIX
+-                     "Invalid _PTC data (control_register)\n");
+-              result = -EFAULT;
+-              goto end;
+-      }
+-      memcpy(&pr->throttling.control_register, obj.buffer.pointer,
+-             sizeof(struct acpi_ptc_register));
+-
+-      /*
+-       * status_register
+-       */
+-
+-      obj = ptc->package.elements[1];
+-
+-      if ((obj.type != ACPI_TYPE_BUFFER)
+-          || (obj.buffer.length < sizeof(struct acpi_ptc_register))
+-          || (obj.buffer.pointer == NULL)) {
+-              printk(KERN_ERR PREFIX "Invalid _PTC data (status_register)\n");
+-              result = -EFAULT;
+-              goto end;
+-      }
+-
+-      memcpy(&pr->throttling.status_register, obj.buffer.pointer,
+-             sizeof(struct acpi_ptc_register));
+-
+-      end:
+-      kfree(buffer.pointer);
+-
+-      return result;
+-}
+-static int acpi_processor_get_throttling_states(struct acpi_processor *pr)
+-{
+-      int result = 0;
+-      acpi_status status = AE_OK;
+-      struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+-      struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
+-      struct acpi_buffer state = { 0, NULL };
+-      union acpi_object *tss = NULL;
+-      int i;
+-
+-      status = acpi_evaluate_object(pr->handle, "_TSS", NULL, &buffer);
+-      if (ACPI_FAILURE(status)) {
+-              ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSS"));
+-              return -ENODEV;
+-      }
+-
+-      tss = buffer.pointer;
+-      if (!tss || (tss->type != ACPI_TYPE_PACKAGE)) {
+-              printk(KERN_ERR PREFIX "Invalid _TSS data\n");
+-              result = -EFAULT;
+-              goto end;
+-      }
+-
+-      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n",
+-                        tss->package.count));
+-
+-      pr->throttling.state_count = tss->package.count;
+-      pr->throttling.states_tss =
+-          kmalloc(sizeof(struct acpi_processor_tx_tss) * tss->package.count,
+-                  GFP_KERNEL);
+-      if (!pr->throttling.states_tss) {
+-              result = -ENOMEM;
+-              goto end;
+-      }
+-
+-      for (i = 0; i < pr->throttling.state_count; i++) {
+-
+-              struct acpi_processor_tx_tss *tx =
+-                  (struct acpi_processor_tx_tss *)&(pr->throttling.
+-                                                    states_tss[i]);
+-
+-              state.length = sizeof(struct acpi_processor_tx_tss);
+-              state.pointer = tx;
+-
+-              ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
+-
+-              status = acpi_extract_package(&(tss->package.elements[i]),
+-                                            &format, &state);
+-              if (ACPI_FAILURE(status)) {
+-                      ACPI_EXCEPTION((AE_INFO, status, "Invalid _TSS data"));
+-                      result = -EFAULT;
+-                      kfree(pr->throttling.states_tss);
+-                      goto end;
+-              }
+-
+-              if (!tx->freqpercentage) {
+-                      printk(KERN_ERR PREFIX
+-                             "Invalid _TSS data: freq is zero\n");
+-                      result = -EFAULT;
+-                      kfree(pr->throttling.states_tss);
+-                      goto end;
+-              }
+-      }
+-
+-      end:
+-      kfree(buffer.pointer);
+-
+-      return result;
+-}
+-static int acpi_processor_get_tsd(struct acpi_processor *pr)
+-{
+-      int result = 0;
+-      acpi_status status = AE_OK;
+-      struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+-      struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
+-      struct acpi_buffer state = { 0, NULL };
+-      union acpi_object *tsd = NULL;
+-      struct acpi_tsd_package *pdomain;
+-
+-      status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer);
+-      if (ACPI_FAILURE(status)) {
+-              return -ENODEV;
+-      }
+-
+-      tsd = buffer.pointer;
+-      if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) {
+-              ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
+-              result = -EFAULT;
+-              goto end;
+-      }
+-
+-      if (tsd->package.count != 1) {
+-              ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
+-              result = -EFAULT;
+-              goto end;
+-      }
+-
+-      pdomain = &(pr->throttling.domain_info);
+-
+-      state.length = sizeof(struct acpi_tsd_package);
+-      state.pointer = pdomain;
+-
+-      status = acpi_extract_package(&(tsd->package.elements[0]),
+-                                    &format, &state);
+-      if (ACPI_FAILURE(status)) {
+-              ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n"));
+-              result = -EFAULT;
+-              goto end;
+-      }
+-
+-      if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) {
+-              ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:num_entries\n"));
+-              result = -EFAULT;
+-              goto end;
+-      }
+-
+-      if (pdomain->revision != ACPI_TSD_REV0_REVISION) {
+-              ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:revision\n"));
+-              result = -EFAULT;
+-              goto end;
+-      }
+-
+-      end:
+-      kfree(buffer.pointer);
+-      return result;
+-}
+-
+ /* --------------------------------------------------------------------------
+                               Throttling Control
+    -------------------------------------------------------------------------- */
+-static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr)
++static int acpi_processor_get_throttling(struct acpi_processor *pr)
  {
--      struct Scsi_Host *host = phba->host;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-       int error;
--      error = sysfs_create_bin_file(&host->shost_classdev.kobj,
-+      error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
-                                                       &sysfs_ctlreg_attr);
-       if (error)
-               goto out;
+       int state = 0;
+       u32 value = 0;
+       u32 duty_mask = 0;
+       u32 duty_value = 0;
  
--      error = sysfs_create_bin_file(&host->shost_classdev.kobj,
-+      error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
-                                                       &sysfs_mbox_attr);
-       if (error)
-               goto out_remove_ctlreg_attr;
++
+       if (!pr)
+               return -EINVAL;
  
+@@ -308,114 +94,13 @@
        return 0;
- out_remove_ctlreg_attr:
--      sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
-+      sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
- out:
-       return error;
  }
  
- void
--lpfc_free_sysfs_attr(struct lpfc_hba *phba)
-+lpfc_free_sysfs_attr(struct lpfc_vport *vport)
+-static int acpi_read_throttling_status(struct acpi_processor_throttling
+-                                     *throttling)
+-{
+-      int value = -1;
+-      switch (throttling->status_register.space_id) {
+-      case ACPI_ADR_SPACE_SYSTEM_IO:
+-              acpi_os_read_port((acpi_io_address) throttling->status_register.
+-                                address, &value,
+-                                (u32) throttling->status_register.bit_width *
+-                                8);
+-              break;
+-      case ACPI_ADR_SPACE_FIXED_HARDWARE:
+-              printk(KERN_ERR PREFIX
+-                     "HARDWARE addr space,NOT supported yet\n");
+-              break;
+-      default:
+-              printk(KERN_ERR PREFIX "Unknown addr space %d\n",
+-                     (u32) (throttling->status_register.space_id));
+-      }
+-      return value;
+-}
+-
+-static int acpi_write_throttling_state(struct acpi_processor_throttling
+-                                     *throttling, int value)
+-{
+-      int ret = -1;
+-
+-      switch (throttling->control_register.space_id) {
+-      case ACPI_ADR_SPACE_SYSTEM_IO:
+-              acpi_os_write_port((acpi_io_address) throttling->
+-                                 control_register.address, value,
+-                                 (u32) throttling->control_register.
+-                                 bit_width * 8);
+-              ret = 0;
+-              break;
+-      case ACPI_ADR_SPACE_FIXED_HARDWARE:
+-              printk(KERN_ERR PREFIX
+-                     "HARDWARE addr space,NOT supported yet\n");
+-              break;
+-      default:
+-              printk(KERN_ERR PREFIX "Unknown addr space %d\n",
+-                     (u32) (throttling->control_register.space_id));
+-      }
+-      return ret;
+-}
+-
+-static int acpi_get_throttling_state(struct acpi_processor *pr, int value)
+-{
+-      int i;
+-
+-      for (i = 0; i < pr->throttling.state_count; i++) {
+-              struct acpi_processor_tx_tss *tx =
+-                  (struct acpi_processor_tx_tss *)&(pr->throttling.
+-                                                    states_tss[i]);
+-              if (tx->control == value)
+-                      break;
+-      }
+-      if (i > pr->throttling.state_count)
+-              i = -1;
+-      return i;
+-}
+-
+-static int acpi_get_throttling_value(struct acpi_processor *pr, int state)
+-{
+-      int value = -1;
+-      if (state >= 0 && state <= pr->throttling.state_count) {
+-              struct acpi_processor_tx_tss *tx =
+-                  (struct acpi_processor_tx_tss *)&(pr->throttling.
+-                                                    states_tss[state]);
+-              value = tx->control;
+-      }
+-      return value;
+-}
+-
+-static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
+-{
+-      int state = 0;
+-      u32 value = 0;
+-
+-      if (!pr)
+-              return -EINVAL;
+-
+-      if (!pr->flags.throttling)
+-              return -ENODEV;
+-
+-      pr->throttling.state = 0;
+-      local_irq_disable();
+-      value = acpi_read_throttling_status(&pr->throttling);
+-      if (value >= 0) {
+-              state = acpi_get_throttling_state(pr, value);
+-              pr->throttling.state = state;
+-      }
+-      local_irq_enable();
+-
+-      return 0;
+-}
+-
+-static int acpi_processor_get_throttling(struct acpi_processor *pr)
+-{
+-      return pr->throttling.acpi_processor_get_throttling(pr);
+-}
+-
+-int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, int state)
++int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
  {
--      struct Scsi_Host *host = phba->host;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
--      sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_mbox_attr);
--      sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
-+      sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_mbox_attr);
-+      sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
- }
+       u32 value = 0;
+       u32 duty_mask = 0;
+       u32 duty_value = 0;
  
-@@ -1469,26 +1744,30 @@
- static void
- lpfc_get_host_port_id(struct Scsi_Host *shost)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
 +
-       /* note: fc_myDID already in cpu endianness */
--      fc_host_port_id(shost) = phba->fc_myDID;
-+      fc_host_port_id(shost) = vport->fc_myDID;
- }
- static void
- lpfc_get_host_port_type(struct Scsi_Host *shost)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       spin_lock_irq(shost->host_lock);
--      if (phba->hba_state == LPFC_HBA_READY) {
-+      if (vport->port_type == LPFC_NPIV_PORT) {
-+              fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
-+      } else if (lpfc_is_link_up(phba)) {
-               if (phba->fc_topology == TOPOLOGY_LOOP) {
--                      if (phba->fc_flag & FC_PUBLIC_LOOP)
-+                      if (vport->fc_flag & FC_PUBLIC_LOOP)
-                               fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
-                       else
-                               fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
-               } else {
--                      if (phba->fc_flag & FC_FABRIC)
-+                      if (vport->fc_flag & FC_FABRIC)
-                               fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
-                       else
-                               fc_host_port_type(shost) = FC_PORTTYPE_PTP;
-@@ -1502,29 +1781,20 @@
- static void
- lpfc_get_host_port_state(struct Scsi_Host *shost)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       spin_lock_irq(shost->host_lock);
--      if (phba->fc_flag & FC_OFFLINE_MODE)
-+      if (vport->fc_flag & FC_OFFLINE_MODE)
-               fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
-       else {
--              switch (phba->hba_state) {
--              case LPFC_STATE_UNKNOWN:
--              case LPFC_WARM_START:
--              case LPFC_INIT_START:
--              case LPFC_INIT_MBX_CMDS:
-+              switch (phba->link_state) {
-+              case LPFC_LINK_UNKNOWN:
-               case LPFC_LINK_DOWN:
-                       fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
-                       break;
-               case LPFC_LINK_UP:
--              case LPFC_LOCAL_CFG_LINK:
--              case LPFC_FLOGI:
--              case LPFC_FABRIC_CFG_LINK:
--              case LPFC_NS_REG:
--              case LPFC_NS_QRY:
--              case LPFC_BUILD_DISC_LIST:
--              case LPFC_DISC_AUTH:
-               case LPFC_CLEAR_LA:
-               case LPFC_HBA_READY:
-                       /* Links up, beyond this port_type reports state */
-@@ -1545,11 +1815,12 @@
- static void
- lpfc_get_host_speed(struct Scsi_Host *shost)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       spin_lock_irq(shost->host_lock);
--      if (phba->hba_state == LPFC_HBA_READY) {
-+      if (lpfc_is_link_up(phba)) {
-               switch(phba->fc_linkspeed) {
-                       case LA_1GHZ_LINK:
-                               fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
-@@ -1575,38 +1846,30 @@
- static void
- lpfc_get_host_fabric_name (struct Scsi_Host *shost)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       u64 node_name;
-       spin_lock_irq(shost->host_lock);
--      if ((phba->fc_flag & FC_FABRIC) ||
-+      if ((vport->fc_flag & FC_FABRIC) ||
-           ((phba->fc_topology == TOPOLOGY_LOOP) &&
--           (phba->fc_flag & FC_PUBLIC_LOOP)))
-+           (vport->fc_flag & FC_PUBLIC_LOOP)))
-               node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
-       else
-               /* fabric is local port if there is no F/FL_Port */
--              node_name = wwn_to_u64(phba->fc_nodename.u.wwn);
-+              node_name = wwn_to_u64(vport->fc_nodename.u.wwn);
+       if (!pr)
+               return -EINVAL;
  
-       spin_unlock_irq(shost->host_lock);
+@@ -428,8 +113,6 @@
+       if (state == pr->throttling.state)
+               return 0;
  
-       fc_host_fabric_name(shost) = node_name;
+-      if (state < pr->throttling_platform_limit)
+-              return -EPERM;
+       /*
+        * Calculate the duty_value and duty_mask.
+        */
+@@ -482,50 +165,12 @@
+       return 0;
  }
  
--static void
--lpfc_get_host_symbolic_name (struct Scsi_Host *shost)
+-int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, int state)
 -{
--      struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+-      u32 value = 0;
 -
--      spin_lock_irq(shost->host_lock);
--      lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost));
--      spin_unlock_irq(shost->host_lock);
+-      if (!pr)
+-              return -EINVAL;
+-
+-      if ((state < 0) || (state > (pr->throttling.state_count - 1)))
+-              return -EINVAL;
+-
+-      if (!pr->flags.throttling)
+-              return -ENODEV;
+-
+-      if (state == pr->throttling.state)
+-              return 0;
+-
+-      if (state < pr->throttling_platform_limit)
+-              return -EPERM;
+-
+-      local_irq_disable();
+-
+-      value = acpi_get_throttling_value(pr, state);
+-      if (value >= 0) {
+-              acpi_write_throttling_state(&pr->throttling, value);
+-              pr->throttling.state = state;
+-      }
+-      local_irq_enable();
+-
+-      return 0;
 -}
 -
- static struct fc_host_statistics *
- lpfc_get_stats(struct Scsi_Host *shost)
+-int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+-{
+-      return pr->throttling.acpi_processor_set_throttling(pr, state);
+-}
+-
+ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
  {
--      struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       struct lpfc_sli *psli = &phba->sli;
-       struct fc_host_statistics *hs = &phba->link_stats;
-       struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
-@@ -1615,7 +1878,16 @@
-       unsigned long seconds;
-       int rc = 0;
--      if (phba->fc_flag & FC_BLOCK_MGMT_IO)
-+      /*
-+       * prevent udev from issuing mailbox commands until the port is
-+       * configured.
-+       */
-+      if (phba->link_state < LPFC_LINK_DOWN ||
-+          !phba->mbox_mem_pool ||
-+          (phba->sli.sli_flag & LPFC_SLI2_ACTIVE) == 0)
-+              return NULL;
+       int result = 0;
+       int step = 0;
+       int i = 0;
+-      int no_ptc = 0;
+-      int no_tss = 0;
+-      int no_tsd = 0;
 +
-+      if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
-               return NULL;
  
-       pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-@@ -1627,17 +1899,16 @@
-       pmb->mbxCommand = MBX_READ_STATUS;
-       pmb->mbxOwner = OWN_HOST;
-       pmboxq->context1 = NULL;
-+      pmboxq->vport = vport;
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                         "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n",
+@@ -537,21 +182,6 @@
+               return -EINVAL;
  
--      if ((phba->fc_flag & FC_OFFLINE_MODE) ||
-+      if ((vport->fc_flag & FC_OFFLINE_MODE) ||
-               (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
-               rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
-       else
-               rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+       /* TBD: Support ACPI 2.0 objects */
+-      no_ptc = acpi_processor_get_throttling_control(pr);
+-      no_tss = acpi_processor_get_throttling_states(pr);
+-      no_tsd = acpi_processor_get_tsd(pr);
+-
+-      if (no_ptc || no_tss) {
+-              pr->throttling.acpi_processor_get_throttling =
+-                  &acpi_processor_get_throttling_fadt;
+-              pr->throttling.acpi_processor_set_throttling =
+-                  &acpi_processor_set_throttling_fadt;
+-      } else {
+-              pr->throttling.acpi_processor_get_throttling =
+-                  &acpi_processor_get_throttling_ptc;
+-              pr->throttling.acpi_processor_set_throttling =
+-                  &acpi_processor_set_throttling_ptc;
+-      }
  
-       if (rc != MBX_SUCCESS) {
--              if (rc == MBX_TIMEOUT)
--                      pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
--              else
-+              if (rc != MBX_TIMEOUT)
-                       mempool_free(pmboxq, phba->mbox_mem_pool);
-               return NULL;
-       }
-@@ -1653,18 +1924,17 @@
-       pmb->mbxCommand = MBX_READ_LNK_STAT;
-       pmb->mbxOwner = OWN_HOST;
-       pmboxq->context1 = NULL;
-+      pmboxq->vport = vport;
+       if (!pr->throttling.address) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n"));
+@@ -632,6 +262,7 @@
+       int i = 0;
+       int result = 0;
  
--      if ((phba->fc_flag & FC_OFFLINE_MODE) ||
-+      if ((vport->fc_flag & FC_OFFLINE_MODE) ||
-           (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
-               rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
-       else
-               rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
++
+       if (!pr)
+               goto end;
  
-       if (rc != MBX_SUCCESS) {
--              if (rc == MBX_TIMEOUT)
--                      pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
--              else
--                      mempool_free( pmboxq, phba->mbox_mem_pool);
-+              if (rc != MBX_TIMEOUT)
-+                      mempool_free(pmboxq, phba->mbox_mem_pool);
-               return NULL;
+@@ -649,27 +280,15 @@
        }
  
-@@ -1711,14 +1981,15 @@
- static void
- lpfc_reset_stats(struct Scsi_Host *shost)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       struct lpfc_sli *psli = &phba->sli;
--      struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
-+      struct lpfc_lnk_stat *lso = &psli->lnk_stat_offsets;
-       LPFC_MBOXQ_t *pmboxq;
-       MAILBOX_t *pmb;
-       int rc = 0;
+       seq_printf(seq, "state count:             %d\n"
+-                 "active state:            T%d\n"
+-                 "state available: T%d to T%d\n",
+-                 pr->throttling.state_count, pr->throttling.state,
+-                 pr->throttling_platform_limit,
+-                 pr->throttling.state_count - 1);
++                 "active state:            T%d\n",
++                 pr->throttling.state_count, pr->throttling.state);
  
--      if (phba->fc_flag & FC_BLOCK_MGMT_IO)
-+      if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
-               return;
+       seq_puts(seq, "states:\n");
+-      if (pr->throttling.acpi_processor_get_throttling ==
+-                      acpi_processor_get_throttling_fadt) {
+       for (i = 0; i < pr->throttling.state_count; i++)
+               seq_printf(seq, "   %cT%d:                  %02d%%\n",
+                          (i == pr->throttling.state ? '*' : ' '), i,
+                          (pr->throttling.states[i].performance ? pr->
+                           throttling.states[i].performance / 10 : 0));
+-      } else {
+-              for (i = 0; i < pr->throttling.state_count; i++)
+-                      seq_printf(seq, "   %cT%d:                  %02d%%\n",
+-                                 (i == pr->throttling.state ? '*' : ' '), i,
+-                                 (int)pr->throttling.states_tss[i].
+-                                 freqpercentage);
+-      }
  
-       pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-@@ -1731,17 +2002,16 @@
-       pmb->mbxOwner = OWN_HOST;
-       pmb->un.varWords[0] = 0x1; /* reset request */
-       pmboxq->context1 = NULL;
-+      pmboxq->vport = vport;
+       end:
+       return 0;
+@@ -682,7 +301,7 @@
+                          PDE(inode)->data);
+ }
  
--      if ((phba->fc_flag & FC_OFFLINE_MODE) ||
-+      if ((vport->fc_flag & FC_OFFLINE_MODE) ||
-               (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
-               rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
-       else
-               rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+-static ssize_t acpi_processor_write_throttling(struct file *file,
++static ssize_t acpi_processor_write_throttling(struct file * file,
+                                              const char __user * buffer,
+                                              size_t count, loff_t * data)
+ {
+@@ -691,6 +310,7 @@
+       struct acpi_processor *pr = m->private;
+       char state_string[12] = { '\0' };
  
-       if (rc != MBX_SUCCESS) {
--              if (rc == MBX_TIMEOUT)
--                      pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
--              else
-+              if (rc != MBX_TIMEOUT)
-                       mempool_free(pmboxq, phba->mbox_mem_pool);
-               return;
-       }
-@@ -1750,17 +2020,16 @@
-       pmb->mbxCommand = MBX_READ_LNK_STAT;
-       pmb->mbxOwner = OWN_HOST;
-       pmboxq->context1 = NULL;
-+      pmboxq->vport = vport;
++
+       if (!pr || (count > sizeof(state_string) - 1))
+               return -EINVAL;
  
--      if ((phba->fc_flag & FC_OFFLINE_MODE) ||
-+      if ((vport->fc_flag & FC_OFFLINE_MODE) ||
-           (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
-               rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
-       else
-               rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+diff -Nurb linux-2.6.22-590/drivers/acpi/sbs.c linux-2.6.22-570/drivers/acpi/sbs.c
+--- linux-2.6.22-590/drivers/acpi/sbs.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/sbs.c        2007-07-08 19:32:17.000000000 -0400
+@@ -127,7 +127,7 @@
+ static struct acpi_driver acpi_sbs_driver = {
+       .name = "sbs",
+       .class = ACPI_SBS_CLASS,
+-      .ids = "ACPI0001,ACPI0005",
++      .ids = ACPI_SBS_HID,
+       .ops = {
+               .add = acpi_sbs_add,
+               .remove = acpi_sbs_remove,
+@@ -176,8 +176,10 @@
+ };
  
-       if (rc != MBX_SUCCESS) {
--              if (rc == MBX_TIMEOUT)
--                      pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
--              else
-+              if (rc != MBX_TIMEOUT)
-                       mempool_free( pmboxq, phba->mbox_mem_pool);
-               return;
+ struct acpi_sbs {
++      acpi_handle handle;
+       int base;
+       struct acpi_device *device;
++      struct acpi_ec_smbus *smbus;
+       struct mutex mutex;
+       int sbsm_present;
+       int sbsm_batteries_supported;
+@@ -509,7 +511,7 @@
+                               "acpi_sbs_read_word() failed"));
+               goto end;
        }
-@@ -1790,12 +2059,12 @@
- lpfc_get_node_by_target(struct scsi_target *starget)
+-      sbs->sbsm_present = 1;
++
+       sbs->sbsm_batteries_supported = battery_system_info & 0x000f;
+       end:
+@@ -1628,12 +1630,13 @@
  {
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
--      struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-       struct lpfc_nodelist *ndlp;
+       struct acpi_sbs *sbs = NULL;
+       int result = 0, remove_result = 0;
++      unsigned long sbs_obj;
+       int id;
+       acpi_status status = AE_OK;
+       unsigned long val;
  
-       spin_lock_irq(shost->host_lock);
-       /* Search for this, mapped, target ID */
--      list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
-+      list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
-               if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
-                   starget->id == ndlp->nlp_sid) {
-                       spin_unlock_irq(shost->host_lock);
-@@ -1885,8 +2154,66 @@
-       .get_host_fabric_name = lpfc_get_host_fabric_name,
-       .show_host_fabric_name = 1,
+       status =
+-          acpi_evaluate_integer(device->handle, "_EC", NULL, &val);
++          acpi_evaluate_integer(device->parent->handle, "_EC", NULL, &val);
+       if (ACPI_FAILURE(status)) {
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Error obtaining _EC"));
+               return -EIO;
+@@ -1650,7 +1653,7 @@
  
--      .get_host_symbolic_name = lpfc_get_host_symbolic_name,
--      .show_host_symbolic_name = 1,
-+      /*
-+       * The LPFC driver treats linkdown handling as target loss events
-+       * so there are no sysfs handlers for link_down_tmo.
-+       */
-+
-+      .get_fc_host_stats = lpfc_get_stats,
-+      .reset_fc_host_stats = lpfc_reset_stats,
-+
-+      .dd_fcrport_size = sizeof(struct lpfc_rport_data),
-+      .show_rport_maxframe_size = 1,
-+      .show_rport_supported_classes = 1,
-+
-+      .set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo,
-+      .show_rport_dev_loss_tmo = 1,
-+
-+      .get_starget_port_id  = lpfc_get_starget_port_id,
-+      .show_starget_port_id = 1,
-+
-+      .get_starget_node_name = lpfc_get_starget_node_name,
-+      .show_starget_node_name = 1,
-+
-+      .get_starget_port_name = lpfc_get_starget_port_name,
-+      .show_starget_port_name = 1,
-+
-+      .issue_fc_host_lip = lpfc_issue_lip,
-+      .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk,
-+      .terminate_rport_io = lpfc_terminate_rport_io,
-+
-+      .vport_create = lpfc_vport_create,
-+      .vport_delete = lpfc_vport_delete,
-+      .dd_fcvport_size = sizeof(struct lpfc_vport *),
-+};
-+
-+struct fc_function_template lpfc_vport_transport_functions = {
-+      /* fixed attributes the driver supports */
-+      .show_host_node_name = 1,
-+      .show_host_port_name = 1,
-+      .show_host_supported_classes = 1,
-+      .show_host_supported_fc4s = 1,
-+      .show_host_supported_speeds = 1,
-+      .show_host_maxframe_size = 1,
-+
-+      /* dynamic attributes the driver supports */
-+      .get_host_port_id = lpfc_get_host_port_id,
-+      .show_host_port_id = 1,
-+
-+      .get_host_port_type = lpfc_get_host_port_type,
-+      .show_host_port_type = 1,
-+
-+      .get_host_port_state = lpfc_get_host_port_state,
-+      .show_host_port_state = 1,
-+
-+      /* active_fc4s is shown but doesn't change (thus no get function) */
-+      .show_host_active_fc4s = 1,
-+
-+      .get_host_speed = lpfc_get_host_speed,
-+      .show_host_speed = 1,
-+
-+      .get_host_fabric_name = lpfc_get_host_fabric_name,
-+      .show_host_fabric_name = 1,
+       sbs_mutex_lock(sbs);
  
-       /*
-        * The LPFC driver treats linkdown handling as target loss events
-@@ -1915,6 +2242,8 @@
-       .issue_fc_host_lip = lpfc_issue_lip,
-       .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk,
-       .terminate_rport_io = lpfc_terminate_rport_io,
-+
-+      .vport_disable = lpfc_vport_disable,
- };
+-      sbs->base = 0xff & (val >> 8);
++      sbs->base = (val & 0xff00ull) >> 8;
+       sbs->device = device;
  
- void
-@@ -1937,6 +2266,9 @@
-       lpfc_discovery_threads_init(phba, lpfc_discovery_threads);
-       lpfc_max_luns_init(phba, lpfc_max_luns);
-       lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
-+      lpfc_peer_port_login_init(phba, lpfc_peer_port_login);
-+      lpfc_npiv_enable_init(phba, lpfc_npiv_enable);
-+      lpfc_vport_restrict_login_init(phba, lpfc_vport_restrict_login);
-       lpfc_use_msi_init(phba, lpfc_use_msi);
-       lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo);
-       lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo);
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_crtn.h linux-2.6.22-590/drivers/scsi/lpfc/lpfc_crtn.h
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_crtn.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_crtn.h     2008-01-02 13:56:37.000000000 -0500
-@@ -23,92 +23,114 @@
- struct fc_rport;
- void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
- void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
-+void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *);
- int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
-                struct lpfc_dmabuf *mp);
- void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
-+void lpfc_issue_clear_la(struct lpfc_hba *phba, struct lpfc_vport *vport);
- void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
--int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *);
-+int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *, int);
- void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
- void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
--int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_t *,
--                 uint32_t);
--void lpfc_unreg_login(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
--void lpfc_unreg_did(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
-+int lpfc_reg_login(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *,
-+                 LPFC_MBOXQ_t *, uint32_t);
-+void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
-+void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
-+void lpfc_reg_vpi(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
-+void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *);
- void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
+       strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
+@@ -1662,10 +1665,24 @@
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed"));
+               goto end;
+       }
++      status = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj);
++      if (status) {
++              ACPI_EXCEPTION((AE_INFO, status,
++                              "acpi_evaluate_integer() failed"));
++              result = -EIO;
++              goto end;
++      }
++      if (sbs_obj > 0) {
++              result = acpi_sbsm_get_info(sbs);
++              if (result) {
++                      ACPI_EXCEPTION((AE_INFO, AE_ERROR,
++                                      "acpi_sbsm_get_info() failed"));
++                      goto end;
++              }
++              sbs->sbsm_present = 1;
++      }
  
+-      acpi_sbsm_get_info(sbs);
 -
-+void lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove);
- int lpfc_linkdown(struct lpfc_hba *);
- void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
+-      if (!sbs->sbsm_present) {
++      if (sbs->sbsm_present == 0) {
+               result = acpi_battery_add(sbs, 0);
+               if (result) {
+                       ACPI_EXCEPTION((AE_INFO, AE_ERROR,
+@@ -1685,6 +1702,8 @@
+               }
+       }
  
- void lpfc_mbx_cmpl_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
- void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
-+void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *);
- void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
- void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
- void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
--void lpfc_dequeue_node(struct lpfc_hba *, struct lpfc_nodelist *);
--void lpfc_nlp_set_state(struct lpfc_hba *, struct lpfc_nodelist *, int);
--void lpfc_drop_node(struct lpfc_hba *, struct lpfc_nodelist *);
--void lpfc_set_disctmo(struct lpfc_hba *);
--int lpfc_can_disctmo(struct lpfc_hba *);
--int lpfc_unreg_rpi(struct lpfc_hba *, struct lpfc_nodelist *);
-+void lpfc_dequeue_node(struct lpfc_vport *, struct lpfc_nodelist *);
-+void lpfc_nlp_set_state(struct lpfc_vport *, struct lpfc_nodelist *, int);
-+void lpfc_drop_node(struct lpfc_vport *, struct lpfc_nodelist *);
-+void lpfc_set_disctmo(struct lpfc_vport *);
-+int  lpfc_can_disctmo(struct lpfc_vport *);
-+int  lpfc_unreg_rpi(struct lpfc_vport *, struct lpfc_nodelist *);
-+void lpfc_unreg_all_rpis(struct lpfc_vport *);
-+void lpfc_unreg_default_rpis(struct lpfc_vport *);
-+void lpfc_issue_reg_vpi(struct lpfc_hba *, struct lpfc_vport *);
++      sbs->handle = device->handle;
 +
- int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *,
-                   struct lpfc_iocbq *, struct lpfc_nodelist *);
--void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t);
-+void lpfc_nlp_init(struct lpfc_vport *, struct lpfc_nodelist *, uint32_t);
- struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *);
- int  lpfc_nlp_put(struct lpfc_nodelist *);
--struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t);
--void lpfc_disc_list_loopmap(struct lpfc_hba *);
--void lpfc_disc_start(struct lpfc_hba *);
--void lpfc_disc_flush_list(struct lpfc_hba *);
-+struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_vport *, uint32_t);
-+void lpfc_disc_list_loopmap(struct lpfc_vport *);
-+void lpfc_disc_start(struct lpfc_vport *);
-+void lpfc_disc_flush_list(struct lpfc_vport *);
-+void lpfc_cleanup_discovery_resources(struct lpfc_vport *);
- void lpfc_disc_timeout(unsigned long);
+       init_timer(&sbs->update_timer);
+       result = acpi_check_update_proc(sbs);
+       if (result)
+diff -Nurb linux-2.6.22-590/drivers/acpi/system.c linux-2.6.22-570/drivers/acpi/system.c
+--- linux-2.6.22-590/drivers/acpi/system.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/system.c     2007-07-08 19:32:17.000000000 -0400
+@@ -39,12 +39,15 @@
+ #define ACPI_SYSTEM_CLASS             "system"
+ #define ACPI_SYSTEM_DEVICE_NAME               "System"
++#define ACPI_SYSTEM_FILE_INFO         "info"
++#define ACPI_SYSTEM_FILE_EVENT                "event"
++#define ACPI_SYSTEM_FILE_DSDT         "dsdt"
++#define ACPI_SYSTEM_FILE_FADT         "fadt"
  
--struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
--struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
-+struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
-+struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
+ /*
+  * Make ACPICA version work as module param
+  */
+-static int param_get_acpica_version(char *buffer, struct kernel_param *kp)
+-{
++static int param_get_acpica_version(char *buffer, struct kernel_param *kp) {
+       int result;
  
-+void lpfc_worker_wake_up(struct lpfc_hba *);
- int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t);
- int lpfc_do_work(void *);
--int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *,
-+int lpfc_disc_state_machine(struct lpfc_vport *, struct lpfc_nodelist *, void *,
-                           uint32_t);
+       result = sprintf(buffer, "%x", ACPI_CA_VERSION);
+@@ -55,126 +58,9 @@
+ module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
  
--int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *,
-+void lpfc_register_new_vport(struct lpfc_hba *, struct lpfc_vport *,
-+                      struct lpfc_nodelist *);
-+void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *);
-+int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *,
-                    struct serv_parm *, uint32_t);
--int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp);
-+int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
-+int lpfc_els_chk_latt(struct lpfc_vport *);
- int lpfc_els_abort_flogi(struct lpfc_hba *);
--int lpfc_initial_flogi(struct lpfc_hba *);
--int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t);
--int lpfc_issue_els_prli(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
--int lpfc_issue_els_adisc(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
--int lpfc_issue_els_logo(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
--int lpfc_issue_els_scr(struct lpfc_hba *, uint32_t, uint8_t);
-+int lpfc_initial_flogi(struct lpfc_vport *);
-+int lpfc_initial_fdisc(struct lpfc_vport *);
-+int lpfc_issue_els_fdisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
-+int lpfc_issue_els_plogi(struct lpfc_vport *, uint32_t, uint8_t);
-+int lpfc_issue_els_prli(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
-+int lpfc_issue_els_adisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
-+int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
-+int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *);
-+int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t);
- int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
--int lpfc_els_rsp_acc(struct lpfc_hba *, uint32_t, struct lpfc_iocbq *,
-+int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
-+int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
-                    struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t);
--int lpfc_els_rsp_reject(struct lpfc_hba *, uint32_t, struct lpfc_iocbq *,
-+int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
-+                      struct lpfc_nodelist *, LPFC_MBOXQ_t *);
-+int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *,
-                       struct lpfc_nodelist *);
--int lpfc_els_rsp_adisc_acc(struct lpfc_hba *, struct lpfc_iocbq *,
-+int lpfc_els_rsp_prli_acc(struct lpfc_vport *, struct lpfc_iocbq *,
-                          struct lpfc_nodelist *);
--int lpfc_els_rsp_prli_acc(struct lpfc_hba *, struct lpfc_iocbq *,
--                        struct lpfc_nodelist *);
--void lpfc_cancel_retry_delay_tmo(struct lpfc_hba *, struct lpfc_nodelist *);
-+void lpfc_cancel_retry_delay_tmo(struct lpfc_vport *, struct lpfc_nodelist *);
- void lpfc_els_retry_delay(unsigned long);
- void lpfc_els_retry_delay_handler(struct lpfc_nodelist *);
-+void lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *);
- void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
-                         struct lpfc_iocbq *);
--int lpfc_els_handle_rscn(struct lpfc_hba *);
--int lpfc_els_flush_rscn(struct lpfc_hba *);
--int lpfc_rscn_payload_check(struct lpfc_hba *, uint32_t);
--void lpfc_els_flush_cmd(struct lpfc_hba *);
--int lpfc_els_disc_adisc(struct lpfc_hba *);
--int lpfc_els_disc_plogi(struct lpfc_hba *);
-+int lpfc_els_handle_rscn(struct lpfc_vport *);
-+void lpfc_els_flush_rscn(struct lpfc_vport *);
-+int lpfc_rscn_payload_check(struct lpfc_vport *, uint32_t);
-+void lpfc_els_flush_cmd(struct lpfc_vport *);
-+int lpfc_els_disc_adisc(struct lpfc_vport *);
-+int lpfc_els_disc_plogi(struct lpfc_vport *);
- void lpfc_els_timeout(unsigned long);
--void lpfc_els_timeout_handler(struct lpfc_hba *);
-+void lpfc_els_timeout_handler(struct lpfc_vport *);
-+void lpfc_hb_timeout(unsigned long);
-+void lpfc_hb_timeout_handler(struct lpfc_hba *);
+ /* --------------------------------------------------------------------------
+-                              FS Interface (/sys)
+-   -------------------------------------------------------------------------- */
+-static LIST_HEAD(acpi_table_attr_list);
+-static struct kobject tables_kobj;
+-
+-struct acpi_table_attr {
+-      struct bin_attribute attr;
+-      char name[8];
+-      int instance;
+-      struct list_head node;
+-};
+-
+-static ssize_t acpi_table_show(struct kobject *kobj,
+-                             struct bin_attribute *bin_attr, char *buf,
+-                             loff_t offset, size_t count)
+-{
+-      struct acpi_table_attr *table_attr =
+-          container_of(bin_attr, struct acpi_table_attr, attr);
+-      struct acpi_table_header *table_header = NULL;
+-      acpi_status status;
+-      ssize_t ret_count = count;
+-
+-      status =
+-          acpi_get_table(table_attr->name, table_attr->instance,
+-                         &table_header);
+-      if (ACPI_FAILURE(status))
+-              return -ENODEV;
+-
+-      if (offset >= table_header->length) {
+-              ret_count = 0;
+-              goto end;
+-      }
+-
+-      if (offset + ret_count > table_header->length)
+-              ret_count = table_header->length - offset;
+-
+-      memcpy(buf, ((char *)table_header) + offset, ret_count);
+-
+-      end:
+-      return ret_count;
+-}
+-
+-static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
+-                               struct acpi_table_header *table_header)
+-{
+-      struct acpi_table_header *header = NULL;
+-      struct acpi_table_attr *attr = NULL;
+-
+-      memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE);
+-
+-      list_for_each_entry(attr, &acpi_table_attr_list, node) {
+-              if (!memcmp(table_header->signature, attr->name,
+-                          ACPI_NAME_SIZE))
+-                      if (table_attr->instance < attr->instance)
+-                              table_attr->instance = attr->instance;
+-      }
+-      table_attr->instance++;
+-
+-      if (table_attr->instance > 1 || (table_attr->instance == 1 &&
+-                                       !acpi_get_table(table_header->
+-                                                       signature, 2,
+-                                                       &header)))
+-              sprintf(table_attr->name + 4, "%d", table_attr->instance);
+-
+-      table_attr->attr.size = 0;
+-      table_attr->attr.read = acpi_table_show;
+-      table_attr->attr.attr.name = table_attr->name;
+-      table_attr->attr.attr.mode = 0444;
+-      table_attr->attr.attr.owner = THIS_MODULE;
+-
+-      return;
+-}
+-
+-static int acpi_system_sysfs_init(void)
+-{
+-      struct acpi_table_attr *table_attr;
+-      struct acpi_table_header *table_header = NULL;
+-      int table_index = 0;
+-      int result;
+-
+-      tables_kobj.parent = &acpi_subsys.kobj;
+-      kobject_set_name(&tables_kobj, "tables");
+-      result = kobject_register(&tables_kobj);
+-      if (result)
+-              return result;
+-
+-      do {
+-              result = acpi_get_table_by_index(table_index, &table_header);
+-              if (!result) {
+-                      table_index++;
+-                      table_attr = NULL;
+-                      table_attr =
+-                          kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL);
+-                      if (!table_attr)
+-                              return -ENOMEM;
+-
+-                      acpi_table_attr_init(table_attr, table_header);
+-                      result =
+-                          sysfs_create_bin_file(&tables_kobj,
+-                                                &table_attr->attr);
+-                      if (result) {
+-                              kfree(table_attr);
+-                              return result;
+-                      } else
+-                              list_add_tail(&table_attr->node,
+-                                            &acpi_table_attr_list);
+-              }
+-      } while (!result);
+-
+-      return 0;
+-}
+-
+-/* --------------------------------------------------------------------------
+                               FS Interface (/proc)
+    -------------------------------------------------------------------------- */
+ #ifdef CONFIG_ACPI_PROCFS
+-#define ACPI_SYSTEM_FILE_INFO         "info"
+-#define ACPI_SYSTEM_FILE_EVENT                "event"
+-#define ACPI_SYSTEM_FILE_DSDT         "dsdt"
+-#define ACPI_SYSTEM_FILE_FADT         "fadt"
  
- void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
-                        struct lpfc_iocbq *);
--int lpfc_ns_cmd(struct lpfc_hba *, struct lpfc_nodelist *, int);
--int lpfc_fdmi_cmd(struct lpfc_hba *, struct lpfc_nodelist *, int);
-+int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
-+int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
- void lpfc_fdmi_tmo(unsigned long);
--void lpfc_fdmi_tmo_handler(struct lpfc_hba *);
-+void lpfc_fdmi_timeout_handler(struct lpfc_vport *vport);
+ static int acpi_system_read_info(struct seq_file *seq, void *offset)
+ {
+@@ -194,6 +80,7 @@
+       .llseek = seq_lseek,
+       .release = single_release,
+ };
++#endif
  
- int lpfc_config_port_prep(struct lpfc_hba *);
- int lpfc_config_port_post(struct lpfc_hba *);
-@@ -136,16 +158,23 @@
- void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *);
- void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
- LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
-+void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
- int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
+ static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t,
+                                    loff_t *);
+@@ -210,11 +97,13 @@
+       struct acpi_table_header *dsdt = NULL;
+       ssize_t res;
  
-+void lpfc_config_hbq(struct lpfc_hba *, struct lpfc_hbq_init *, uint32_t ,
-+                   LPFC_MBOXQ_t *);
-+struct lpfc_hbq_entry * lpfc_sli_next_hbq_slot(struct lpfc_hba *, uint32_t);
 +
int lpfc_mem_alloc(struct lpfc_hba *);
- void lpfc_mem_free(struct lpfc_hba *);
-+void lpfc_stop_vport_timers(struct lpfc_vport *);
      status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
  
- void lpfc_poll_timeout(unsigned long ptr);
- void lpfc_poll_start_timer(struct lpfc_hba * phba);
- void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba);
- struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
- void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
-+void __lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
- uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
+-      res = simple_read_from_buffer(buffer, count, ppos, dsdt, dsdt->length);
++      res = simple_read_from_buffer(buffer, count, ppos,
++                                    dsdt, dsdt->length);
  
- void lpfc_reset_barrier(struct lpfc_hba * phba);
-@@ -154,6 +183,7 @@
- int lpfc_sli_brdreset(struct lpfc_hba *);
- int lpfc_sli_brdrestart(struct lpfc_hba *);
- int lpfc_sli_hba_setup(struct lpfc_hba *);
-+int lpfc_sli_host_down(struct lpfc_vport *);
- int lpfc_sli_hba_down(struct lpfc_hba *);
- int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
- int lpfc_sli_handle_mb_event(struct lpfc_hba *);
-@@ -164,12 +194,17 @@
- int lpfc_sli_issue_iocb(struct lpfc_hba *, struct lpfc_sli_ring *,
-                       struct lpfc_iocbq *, uint32_t);
- void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
--int lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
-+void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
- int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
-                            struct lpfc_dmabuf *);
- struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
-                                            struct lpfc_sli_ring *,
-                                            dma_addr_t);
-+int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t);
-+int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t);
-+void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *);
-+struct hbq_dmabuf *lpfc_sli_hbqbuf_find(struct lpfc_hba *, uint32_t);
-+int lpfc_sli_hbq_size(void);
- int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *,
-                              struct lpfc_iocbq *);
- int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
-@@ -180,8 +215,12 @@
- void lpfc_mbox_timeout(unsigned long);
- void lpfc_mbox_timeout_handler(struct lpfc_hba *);
+       return res;
+ }
+@@ -234,21 +123,28 @@
+       struct acpi_table_header *fadt = NULL;
+       ssize_t res;
++
+       status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
  
--struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t);
--struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, struct lpfc_name *);
-+struct lpfc_nodelist *__lpfc_find_node(struct lpfc_vport *, node_filter,
-+                                     void *);
-+struct lpfc_nodelist *lpfc_find_node(struct lpfc_vport *, node_filter, void *);
-+struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_vport *, uint32_t);
-+struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_vport *,
-+                                       struct lpfc_name *);
+-      res = simple_read_from_buffer(buffer, count, ppos, fadt, fadt->length);
++      res = simple_read_from_buffer(buffer, count, ppos,
++                                    fadt, fadt->length);
  
- int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
-                        uint32_t timeout);
-@@ -195,25 +234,56 @@
-                            struct lpfc_iocbq * cmdiocb,
-                            struct lpfc_iocbq * rspiocb);
+       return res;
+ }
+-static int acpi_system_procfs_init(void)
++static int __init acpi_system_init(void)
+ {
+       struct proc_dir_entry *entry;
+       int error = 0;
+       char *name;
  
-+void *lpfc_hbq_alloc(struct lpfc_hba *, int, dma_addr_t *);
-+void lpfc_hbq_free(struct lpfc_hba *, void *, dma_addr_t);
-+void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *);
 +
- void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
-+void __lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
- void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
++      if (acpi_disabled)
++              return 0;
++
++#ifdef CONFIG_ACPI_PROCFS
+       /* 'info' [R] */
+       name = ACPI_SYSTEM_FILE_INFO;
+       entry = create_proc_entry(name, S_IRUGO, acpi_root_dir);
+@@ -257,6 +153,7 @@
+       else {
+               entry->proc_fops = &acpi_system_info_ops;
+       }
++#endif
  
-+void lpfc_in_buf_free(struct lpfc_hba *, struct lpfc_dmabuf *);
- /* Function prototypes. */
- const char* lpfc_info(struct Scsi_Host *);
--void lpfc_scan_start(struct Scsi_Host *);
- int lpfc_scan_finished(struct Scsi_Host *, unsigned long);
+       /* 'dsdt' [R] */
+       name = ACPI_SYSTEM_FILE_DSDT;
+@@ -280,32 +177,12 @@
+       Error:
+       remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir);
+       remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir);
++#ifdef CONFIG_ACPI_PROCFS
+       remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir);
++#endif
  
- void lpfc_get_cfgparam(struct lpfc_hba *);
--int lpfc_alloc_sysfs_attr(struct lpfc_hba *);
--void lpfc_free_sysfs_attr(struct lpfc_hba *);
--extern struct class_device_attribute *lpfc_host_attrs[];
-+int lpfc_alloc_sysfs_attr(struct lpfc_vport *);
-+void lpfc_free_sysfs_attr(struct lpfc_vport *);
-+extern struct class_device_attribute *lpfc_hba_attrs[];
- extern struct scsi_host_template lpfc_template;
- extern struct fc_function_template lpfc_transport_functions;
-+extern struct fc_function_template lpfc_vport_transport_functions;
-+extern int lpfc_sli_mode;
+       error = -EFAULT;
+       goto Done;
+ }
+-#else
+-static int acpi_system_procfs_init(void)
+-{
+-      return 0;
+-}
+-#endif
+-
+-static int __init acpi_system_init(void)
+-{
+-      int result = 0;
+-
+-      if (acpi_disabled)
+-              return 0;
+-
+-      result = acpi_system_procfs_init();
+-      if (result)
+-              return result;
+-
+-      result = acpi_system_sysfs_init();
+-
+-      return result;
+-}
  
--void lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp);
-+int  lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t);
- void lpfc_terminate_rport_io(struct fc_rport *);
- void lpfc_dev_loss_tmo_callbk(struct fc_rport *rport);
+ subsys_initcall(acpi_system_init);
+diff -Nurb linux-2.6.22-590/drivers/acpi/thermal.c linux-2.6.22-570/drivers/acpi/thermal.c
+--- linux-2.6.22-590/drivers/acpi/thermal.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/thermal.c    2007-07-08 19:32:17.000000000 -0400
+@@ -40,7 +40,6 @@
+ #include <linux/jiffies.h>
+ #include <linux/kmod.h>
+ #include <linux/seq_file.h>
+-#include <linux/reboot.h>
+ #include <asm/uaccess.h>
  
-+struct lpfc_vport *lpfc_create_port(struct lpfc_hba *, int, struct fc_vport *);
-+int  lpfc_vport_disable(struct fc_vport *fc_vport, bool disable);
-+void lpfc_mbx_unreg_vpi(struct lpfc_vport *);
-+void destroy_port(struct lpfc_vport *);
-+int lpfc_get_instance(void);
-+void lpfc_host_attrib_init(struct Scsi_Host *);
-+
-+extern void lpfc_debugfs_initialize(struct lpfc_vport *);
-+extern void lpfc_debugfs_terminate(struct lpfc_vport *);
-+extern void lpfc_debugfs_disc_trc(struct lpfc_vport *, int, char *, uint32_t,
-+      uint32_t, uint32_t);
-+
-+/* Interface exported by fabric iocb scheduler */
-+int lpfc_issue_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
-+void lpfc_fabric_abort_vport(struct lpfc_vport *);
-+void lpfc_fabric_abort_nport(struct lpfc_nodelist *);
-+void lpfc_fabric_abort_hba(struct lpfc_hba *);
-+void lpfc_fabric_abort_flogi(struct lpfc_hba *);
-+void lpfc_fabric_block_timeout(unsigned long);
-+void lpfc_unblock_fabric_iocbs(struct lpfc_hba *);
-+void lpfc_adjust_queue_depth(struct lpfc_hba *);
-+void lpfc_ramp_down_queue_handler(struct lpfc_hba *);
-+void lpfc_ramp_up_queue_handler(struct lpfc_hba *);
-+
- #define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
- #define HBA_EVENT_RSCN                   5
- #define HBA_EVENT_LINK_UP                2
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_ct.c linux-2.6.22-590/drivers/scsi/lpfc/lpfc_ct.c
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_ct.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_ct.c       2008-01-02 13:56:37.000000000 -0500
-@@ -40,6 +40,8 @@
- #include "lpfc_logmsg.h"
- #include "lpfc_crtn.h"
- #include "lpfc_version.h"
-+#include "lpfc_vport.h"
-+#include "lpfc_debugfs.h"
+ #include <acpi/acpi_bus.h>
+@@ -60,6 +59,7 @@
+ #define ACPI_THERMAL_NOTIFY_CRITICAL  0xF0
+ #define ACPI_THERMAL_NOTIFY_HOT               0xF1
+ #define ACPI_THERMAL_MODE_ACTIVE      0x00
++#define ACPI_THERMAL_PATH_POWEROFF    "/sbin/poweroff"
  
- #define HBA_PORTSPEED_UNKNOWN               0 /* Unknown - transceiver
-                                                * incapable of reporting */
-@@ -58,24 +60,68 @@
- /*
-  * lpfc_ct_unsol_event
-  */
-+static void
-+lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
-+                   struct lpfc_dmabuf *mp, uint32_t size)
+ #define ACPI_THERMAL_MAX_ACTIVE       10
+ #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
+@@ -419,6 +419,26 @@
+       return 0;
+ }
++static int acpi_thermal_call_usermode(char *path)
 +{
-+      if (!mp) {
-+              printk(KERN_ERR "%s (%d): Unsolited CT, no buffer, "
-+                     "piocbq = %p, status = x%x, mp = %p, size = %d\n",
-+                     __FUNCTION__, __LINE__,
-+                     piocbq, piocbq->iocb.ulpStatus, mp, size);
-+      }
++      char *argv[2] = { NULL, NULL };
++      char *envp[3] = { NULL, NULL, NULL };
 +
-+      printk(KERN_ERR "%s (%d): Ignoring unsolicted CT piocbq = %p, "
-+             "buffer = %p, size = %d, status = x%x\n",
-+             __FUNCTION__, __LINE__,
-+             piocbq, mp, size,
-+             piocbq->iocb.ulpStatus);
 +
-+}
++      if (!path)
++              return -EINVAL;
 +
-+static void
-+lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
-+                        struct lpfc_dmabuf *mp, uint32_t size)
-+{
-+      if (!mp) {
-+              printk(KERN_ERR "%s (%d): Unsolited CT, no "
-+                     "HBQ buffer, piocbq = %p, status = x%x\n",
-+                     __FUNCTION__, __LINE__,
-+                     piocbq, piocbq->iocb.ulpStatus);
-+      } else {
-+              lpfc_ct_unsol_buffer(phba, piocbq, mp, size);
-+              printk(KERN_ERR "%s (%d): Ignoring unsolicted CT "
-+                     "piocbq = %p, buffer = %p, size = %d, "
-+                     "status = x%x\n",
-+                     __FUNCTION__, __LINE__,
-+                     piocbq, mp, size, piocbq->iocb.ulpStatus);
-+      }
++      argv[0] = path;
++
++      /* minimal command environment */
++      envp[0] = "HOME=/";
++      envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
++
++      call_usermodehelper(argv[0], argv, envp, 0);
++
++      return 0;
 +}
 +
- void
--lpfc_ct_unsol_event(struct lpfc_hba * phba,
--                  struct lpfc_sli_ring * pring, struct lpfc_iocbq * piocbq)
-+lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-+                  struct lpfc_iocbq *piocbq)
+ static int acpi_thermal_critical(struct acpi_thermal *tz)
  {
+       if (!tz || !tz->trips.critical.flags.valid)
+@@ -436,7 +456,7 @@
+       acpi_bus_generate_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,
+                               tz->trips.critical.flags.enabled);
  
--      struct lpfc_iocbq *next_piocbq;
--      struct lpfc_dmabuf *pmbuf = NULL;
--      struct lpfc_dmabuf *matp, *next_matp;
--      uint32_t ctx = 0, size = 0, cnt = 0;
-+      struct lpfc_dmabuf *mp = NULL;
-       IOCB_t *icmd = &piocbq->iocb;
--      IOCB_t *save_icmd = icmd;
--      int i, go_exit = 0;
--      struct list_head head;
-+      int i;
-+      struct lpfc_iocbq *iocbq;
-+      dma_addr_t paddr;
-+      uint32_t size;
-+      struct lpfc_dmabuf *bdeBuf1 = piocbq->context2;
-+      struct lpfc_dmabuf *bdeBuf2 = piocbq->context3;
-+
-+      piocbq->context2 = NULL;
-+      piocbq->context3 = NULL;
--      if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-+      if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) {
-+              lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
-+      } else if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-               ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) {
-               /* Not enough posted buffers; Try posting more buffers */
-               phba->fc_stat.NoRcvBuf++;
-+              if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
-               lpfc_post_buffer(phba, pring, 0, 1);
-               return;
-       }
-@@ -86,66 +132,56 @@
-       if (icmd->ulpBdeCount == 0)
-               return;
+-      orderly_poweroff(true);
++      acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF);
  
--      INIT_LIST_HEAD(&head);
--      list_add_tail(&head, &piocbq->list);
--
--      list_for_each_entry_safe(piocbq, next_piocbq, &head, list) {
--              icmd = &piocbq->iocb;
--              if (ctx == 0)
--                      ctx = (uint32_t) (icmd->ulpContext);
--              if (icmd->ulpBdeCount == 0)
-+      if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
-+              list_for_each_entry(iocbq, &piocbq->list, list) {
-+                      icmd = &iocbq->iocb;
-+                      if (icmd->ulpBdeCount == 0) {
-+                              printk(KERN_ERR "%s (%d): Unsolited CT, no "
-+                                     "BDE, iocbq = %p, status = x%x\n",
-+                                     __FUNCTION__, __LINE__,
-+                                     iocbq, iocbq->iocb.ulpStatus);
-                       continue;
--
--              for (i = 0; i < icmd->ulpBdeCount; i++) {
--                      matp = lpfc_sli_ringpostbuf_get(phba, pring,
--                                                      getPaddr(icmd->un.
--                                                               cont64[i].
--                                                               addrHigh,
--                                                               icmd->un.
--                                                               cont64[i].
--                                                               addrLow));
--                      if (!matp) {
--                              /* Insert lpfc log message here */
--                              lpfc_post_buffer(phba, pring, cnt, 1);
--                              go_exit = 1;
--                              goto ct_unsol_event_exit_piocbq;
--                      }
+       return 0;
+ }
+@@ -1094,6 +1114,7 @@
+               break;
+       case ACPI_THERMAL_NOTIFY_THRESHOLDS:
+               acpi_thermal_get_trip_points(tz);
++              acpi_thermal_check(tz);
+               acpi_bus_generate_event(device, event, 0);
+               break;
+       case ACPI_THERMAL_NOTIFY_DEVICES:
+diff -Nurb linux-2.6.22-590/drivers/acpi/utilities/uteval.c linux-2.6.22-570/drivers/acpi/utilities/uteval.c
+--- linux-2.6.22-590/drivers/acpi/utilities/uteval.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/utilities/uteval.c   2007-07-08 19:32:17.000000000 -0400
+@@ -62,13 +62,16 @@
+ static char *acpi_interfaces_supported[] = {
+       /* Operating System Vendor Strings */
+-      "Windows 2000",         /* Windows 2000 */
+-      "Windows 2001",         /* Windows XP */
+-      "Windows 2001 SP1",     /* Windows XP SP1 */
+-      "Windows 2001 SP2",     /* Windows XP SP2 */
+-      "Windows 2001.1",       /* Windows Server 2003 */
+-      "Windows 2001.1 SP1",   /* Windows Server 2003 SP1 - Added 03/2006 */
+-      "Windows 2006",         /* Windows Vista - Added 03/2006 */
++      "Windows 2000",
++      "Windows 2001",
++      "Windows 2001 SP0",
++      "Windows 2001 SP1",
++      "Windows 2001 SP2",
++      "Windows 2001 SP3",
++      "Windows 2001 SP4",
++      "Windows 2001.1",
++      "Windows 2001.1 SP1",   /* Added 03/2006 */
++      "Windows 2006",         /* Added 03/2006 */
+       /* Feature Group Strings */
+diff -Nurb linux-2.6.22-590/drivers/acpi/video.c linux-2.6.22-570/drivers/acpi/video.c
+--- linux-2.6.22-590/drivers/acpi/video.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/acpi/video.c      2007-07-08 19:32:17.000000000 -0400
+@@ -33,7 +33,6 @@
+ #include <linux/seq_file.h>
+ #include <linux/backlight.h>
+-#include <linux/video_output.h>
+ #include <asm/uaccess.h>
+ #include <acpi/acpi_bus.h>
+@@ -170,7 +169,6 @@
+       struct acpi_device *dev;
+       struct acpi_video_device_brightness *brightness;
+       struct backlight_device *backlight;
+-      struct output_device *output_dev;
+ };
+ /* bus */
+@@ -274,10 +272,6 @@
+                                    u32 level_current, u32 event);
+ static void acpi_video_switch_brightness(struct acpi_video_device *device,
+                                        int event);
+-static int acpi_video_device_get_state(struct acpi_video_device *device,
+-                          unsigned long *state);
+-static int acpi_video_output_get(struct output_device *od);
+-static int acpi_video_device_set_state(struct acpi_video_device *device, int state);
+ /*backlight device sysfs support*/
+ static int acpi_video_get_brightness(struct backlight_device *bd)
+@@ -303,28 +297,6 @@
+       .update_status  = acpi_video_set_brightness,
+ };
+-/*video output device sysfs support*/
+-static int acpi_video_output_get(struct output_device *od)
+-{
+-      unsigned long state;
+-      struct acpi_video_device *vd =
+-              (struct acpi_video_device *)class_get_devdata(&od->class_dev);
+-      acpi_video_device_get_state(vd, &state);
+-      return (int)state;
+-}
 -
--                      /* Typically for Unsolicited CT requests */
--                      if (!pmbuf) {
--                              pmbuf = matp;
--                              INIT_LIST_HEAD(&pmbuf->list);
--                      } else
--                              list_add_tail(&matp->list, &pmbuf->list);
+-static int acpi_video_output_set(struct output_device *od)
+-{
+-      unsigned long state = od->request_state;
+-      struct acpi_video_device *vd=
+-              (struct acpi_video_device *)class_get_devdata(&od->class_dev);
+-      return acpi_video_device_set_state(vd, state);
+-}
 -
--                      size += icmd->un.cont64[i].tus.f.bdeSize;
--                      cnt++;
-               }
+-static struct output_properties acpi_output_properties = {
+-      .set_state = acpi_video_output_set,
+-      .get_status = acpi_video_output_get,
+-};
+ /* --------------------------------------------------------------------------
+                                Video Management
+    -------------------------------------------------------------------------- */
+@@ -559,6 +531,7 @@
  
--              icmd->ulpBdeCount = 0;
-+                      size  = icmd->un.cont64[0].tus.f.bdeSize;
-+                      lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf1, size);
-+                      lpfc_in_buf_free(phba, bdeBuf1);
-+                      if (icmd->ulpBdeCount == 2) {
-+                              lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf2,
-+                                                        size);
-+                              lpfc_in_buf_free(phba, bdeBuf2);
-+                      }
-       }
-+      } else {
-+              struct lpfc_iocbq  *next;
--      lpfc_post_buffer(phba, pring, cnt, 1);
--      if (save_icmd->ulpStatus) {
--              go_exit = 1;
-+              list_for_each_entry_safe(iocbq, next, &piocbq->list, list) {
-+                      icmd = &iocbq->iocb;
-+                      if (icmd->ulpBdeCount == 0) {
-+                              printk(KERN_ERR "%s (%d): Unsolited CT, no "
-+                                     "BDE, iocbq = %p, status = x%x\n",
-+                                     __FUNCTION__, __LINE__,
-+                                     iocbq, iocbq->iocb.ulpStatus);
-+                              continue;
+ static void acpi_video_device_find_cap(struct acpi_video_device *device)
+ {
++      acpi_integer status;
+       acpi_handle h_dummy1;
+       int i;
+       u32 max_level = 0;
+@@ -592,9 +565,9 @@
+               device->cap._DSS = 1;
        }
  
--ct_unsol_event_exit_piocbq:
--      list_del(&head);
--      if (pmbuf) {
--              list_for_each_entry_safe(matp, next_matp, &pmbuf->list, list) {
--                      lpfc_mbuf_free(phba, matp->virt, matp->phys);
--                      list_del(&matp->list);
--                      kfree(matp);
-+                      for (i = 0; i < icmd->ulpBdeCount; i++) {
-+                              paddr = getPaddr(icmd->un.cont64[i].addrHigh,
-+                                               icmd->un.cont64[i].addrLow);
-+                              mp = lpfc_sli_ringpostbuf_get(phba, pring,
-+                                                            paddr);
-+                              size = icmd->un.cont64[i].tus.f.bdeSize;
-+                              lpfc_ct_unsol_buffer(phba, piocbq, mp, size);
-+                              lpfc_in_buf_free(phba, mp);
-+                      }
-+                      list_del(&iocbq->list);
-+                      lpfc_sli_release_iocbq(phba, iocbq);
+-      if (ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
++      status = acpi_video_device_lcd_query_levels(device, &obj);
+-              if (obj->package.count >= 2) {
++      if (obj && obj->type == ACPI_TYPE_PACKAGE && obj->package.count >= 2) {
+               int count = 0;
+               union acpi_object *o;
+@@ -615,7 +588,6 @@
+                                       continue;
+                               }
+                               br->levels[count] = (u32) o->integer.value;
+-
+                               if (br->levels[count] > max_level)
+                                       max_level = br->levels[count];
+                               count++;
+@@ -634,13 +606,9 @@
                }
--              lpfc_mbuf_free(phba, pmbuf->virt, pmbuf->phys);
--              kfree(pmbuf);
        }
--      return;
- }
  
- static void
--lpfc_free_ct_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mlist)
-+lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
- {
-       struct lpfc_dmabuf *mlast, *next_mlast;
+-      } else {
+-              ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available LCD brightness level\n"));
+-      }
+-
+       kfree(obj);
+-      if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
++      if (device->cap._BCL && device->cap._BCM && device->cap._BQC){
+               unsigned long tmp;
+               static int count = 0;
+               char *name;
+@@ -658,17 +626,6 @@
  
-@@ -160,7 +196,7 @@
+               kfree(name);
+       }
+-      if (device->cap._DCS && device->cap._DSS){
+-              static int count = 0;
+-              char *name;
+-              name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
+-              if (!name)
+-                      return;
+-              sprintf(name, "acpi_video%d", count++);
+-              device->output_dev = video_output_register(name,
+-                              NULL, device, &acpi_output_properties);
+-              kfree(name);
+-      }
+       return;
  }
  
- static struct lpfc_dmabuf *
--lpfc_alloc_ct_rsp(struct lpfc_hba * phba, int cmdcode, struct ulp_bde64 * bpl,
-+lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
-                 uint32_t size, int *entries)
- {
-       struct lpfc_dmabuf *mlist = NULL;
-@@ -181,7 +217,8 @@
+@@ -1712,7 +1669,6 @@
+                                           ACPI_DEVICE_NOTIFY,
+                                           acpi_video_device_notify);
+       backlight_device_unregister(device->backlight);
+-      video_output_unregister(device->output_dev);
+       return 0;
+ }
  
-               INIT_LIST_HEAD(&mp->list);
+diff -Nurb linux-2.6.22-590/drivers/atm/idt77252.c linux-2.6.22-570/drivers/atm/idt77252.c
+--- linux-2.6.22-590/drivers/atm/idt77252.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/atm/idt77252.c    2007-07-08 19:32:17.000000000 -0400
+@@ -3576,7 +3576,7 @@
+        * XXX: <hack>
+        */
+       sprintf(tname, "eth%d", card->index);
+-      tmp = dev_get_by_name(&init_net, tname);        /* jhs: was "tmp = dev_get(tname);" */
++      tmp = dev_get_by_name(tname);   /* jhs: was "tmp = dev_get(tname);" */
+       if (tmp) {
+               memcpy(card->atmdev->esi, tmp->dev_addr, 6);
  
--              if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT))
-+              if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT) ||
-+                  cmdcode == be16_to_cpu(SLI_CTNS_GFF_ID))
-                       mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
-               else
-                       mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys));
-@@ -201,8 +238,8 @@
+diff -Nurb linux-2.6.22-590/drivers/base/bus.c linux-2.6.22-570/drivers/base/bus.c
+--- linux-2.6.22-590/drivers/base/bus.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/base/bus.c        2007-07-08 19:32:17.000000000 -0400
+@@ -562,6 +562,7 @@
  
-               bpl->tus.f.bdeFlags = BUFF_USE_RCV;
-               /* build buffer ptr list for IOCB */
--              bpl->addrLow = le32_to_cpu( putPaddrLow(mp->phys) );
--              bpl->addrHigh = le32_to_cpu( putPaddrHigh(mp->phys) );
-+              bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
-+              bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
-               bpl->tus.f.bdeSize = (uint16_t) cnt;
-               bpl->tus.w = le32_to_cpu(bpl->tus.w);
-               bpl++;
-@@ -215,24 +252,49 @@
-       return mlist;
+       bus->drivers_probe_attr.attr.name = "drivers_probe";
+       bus->drivers_probe_attr.attr.mode = S_IWUSR;
++      bus->drivers_probe_attr.attr.owner = bus->owner;
+       bus->drivers_probe_attr.store = store_drivers_probe;
+       retval = bus_create_file(bus, &bus->drivers_probe_attr);
+       if (retval)
+@@ -569,6 +570,7 @@
+       bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe";
+       bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO;
++      bus->drivers_autoprobe_attr.attr.owner = bus->owner;
+       bus->drivers_autoprobe_attr.show = show_drivers_autoprobe;
+       bus->drivers_autoprobe_attr.store = store_drivers_autoprobe;
+       retval = bus_create_file(bus, &bus->drivers_autoprobe_attr);
+diff -Nurb linux-2.6.22-590/drivers/base/class.c linux-2.6.22-570/drivers/base/class.c
+--- linux-2.6.22-590/drivers/base/class.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/base/class.c      2007-07-08 19:32:17.000000000 -0400
+@@ -134,17 +134,6 @@
+       }
  }
  
-+int
-+lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb)
-+{
-+      struct lpfc_dmabuf *buf_ptr;
-+
-+      if (ctiocb->context1) {
-+              buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1;
-+              lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
-+              kfree(buf_ptr);
-+              ctiocb->context1 = NULL;
-+      }
-+      if (ctiocb->context2) {
-+              lpfc_free_ct_rsp(phba, (struct lpfc_dmabuf *) ctiocb->context2);
-+              ctiocb->context2 = NULL;
-+      }
-+
-+      if (ctiocb->context3) {
-+              buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3;
-+              lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
-+              kfree(buf_ptr);
-+              ctiocb->context1 = NULL;
-+      }
-+      lpfc_sli_release_iocbq(phba, ctiocb);
-+      return 0;
-+}
-+
- static int
--lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp,
-+lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
-            struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp,
-            void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
-                    struct lpfc_iocbq *),
-            struct lpfc_nodelist *ndlp, uint32_t usr_flg, uint32_t num_entry,
--           uint32_t tmo)
-+           uint32_t tmo, uint8_t retry)
+-static int class_setup_shadowing(struct class *cls)
+-{
+-      const struct shadow_dir_operations *shadow_ops;
+-
+-      shadow_ops = cls->shadow_ops;
+-      if (!shadow_ops)
+-              return 0;
+-
+-      return sysfs_enable_shadowing(&cls->subsys.kobj, shadow_ops);
+-}
+-
+ int class_register(struct class * cls)
  {
+       int error;
+@@ -163,22 +152,11 @@
+       subsys_set_kset(cls, class_subsys);
+       error = subsystem_register(&cls->subsys);
+-      if (error)
+-              goto out;
 -
-+      struct lpfc_hba  *phba = vport->phba;
-       struct lpfc_sli *psli = &phba->sli;
-       struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
-       IOCB_t *icmd;
-       struct lpfc_iocbq *geniocb;
-+      int rc;
+-      error = class_setup_shadowing(cls);
+-      if (error)
+-              goto out_unregister;
+-
+-      error = add_class_attrs(cls);
+-      if (error)
+-              goto out_unregister;
+-
+-out:
++      if (!error) {
++              error = add_class_attrs(class_get(cls));
++              class_put(cls);
++      }
+       return error;
+-out_unregister:
+-      subsystem_unregister(&cls->subsys);
+-      goto out;
+ }
  
-       /* Allocate buffer for  command iocb */
--      spin_lock_irq(phba->host->host_lock);
-       geniocb = lpfc_sli_get_iocbq(phba);
--      spin_unlock_irq(phba->host->host_lock);
+ void class_unregister(struct class * cls)
+@@ -334,6 +312,9 @@
  
-       if (geniocb == NULL)
-               return 1;
-@@ -272,31 +334,40 @@
-       icmd->ulpClass = CLASS3;
-       icmd->ulpContext = ndlp->nlp_rpi;
+       pr_debug("device class '%s': release.\n", cd->class_id);
  
-+      if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
-+              /* For GEN_REQUEST64_CR, use the RPI */
-+              icmd->ulpCt_h = 0;
-+              icmd->ulpCt_l = 0;
-+      }
++      kfree(cd->devt_attr);
++      cd->devt_attr = NULL;
 +
-       /* Issue GEN REQ IOCB for NPORT <did> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0119 Issue GEN REQ IOCB for NPORT x%x "
--                      "Data: x%x x%x\n", phba->brd_no, icmd->un.ulpWord[5],
--                      icmd->ulpIoTag, phba->hba_state);
-+                      "%d (%d):0119 Issue GEN REQ IOCB to NPORT x%x "
-+                      "Data: x%x x%x\n", phba->brd_no, vport->vpi,
-+                      ndlp->nlp_DID, icmd->ulpIoTag,
-+                      vport->port_state);
-       geniocb->iocb_cmpl = cmpl;
-       geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT;
--      spin_lock_irq(phba->host->host_lock);
--      if (lpfc_sli_issue_iocb(phba, pring, geniocb, 0) == IOCB_ERROR) {
-+      geniocb->vport = vport;
-+      geniocb->retry = retry;
-+      rc = lpfc_sli_issue_iocb(phba, pring, geniocb, 0);
-+
-+      if (rc == IOCB_ERROR) {
-               lpfc_sli_release_iocbq(phba, geniocb);
--              spin_unlock_irq(phba->host->host_lock);
-               return 1;
-       }
--      spin_unlock_irq(phba->host->host_lock);
-       return 0;
+       if (cd->release)
+               cd->release(cd);
+       else if (cls->release)
+@@ -566,9 +547,6 @@
+       return print_dev_t(buf, class_dev->devt);
  }
  
- static int
--lpfc_ct_cmd(struct lpfc_hba *phba, struct lpfc_dmabuf *inmp,
-+lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp,
-           struct lpfc_dmabuf *bmp, struct lpfc_nodelist *ndlp,
-           void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
-                         struct lpfc_iocbq *),
--          uint32_t rsp_size)
-+          uint32_t rsp_size, uint8_t retry)
+-static struct class_device_attribute class_devt_attr =
+-      __ATTR(dev, S_IRUGO, show_dev, NULL);
+-
+ static ssize_t store_uevent(struct class_device *class_dev,
+                           const char *buf, size_t count)
  {
-+      struct lpfc_hba  *phba = vport->phba;
-       struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt;
-       struct lpfc_dmabuf *outmp;
-       int cnt = 0, status;
-@@ -310,8 +381,8 @@
-       if (!outmp)
-               return -ENOMEM;
--      status = lpfc_gen_req(phba, bmp, inmp, outmp, cmpl, ndlp, 0,
--                            cnt+1, 0);
-+      status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp, 0,
-+                            cnt+1, 0, retry);
-       if (status) {
-               lpfc_free_ct_rsp(phba, outmp);
-               return -ENOMEM;
-@@ -319,20 +390,35 @@
-       return 0;
+@@ -576,9 +554,6 @@
+       return count;
  }
  
-+static struct lpfc_vport *
-+lpfc_find_vport_by_did(struct lpfc_hba *phba, uint32_t did) {
-+
-+      struct lpfc_vport *vport_curr;
-+
-+      list_for_each_entry(vport_curr, &phba->port_list, listentry) {
-+              if ((vport_curr->fc_myDID) &&
-+                      (vport_curr->fc_myDID == did))
-+                      return vport_curr;
-+      }
-+
-+      return NULL;
-+}
-+
- static int
--lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
-+lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
+-static struct class_device_attribute class_uevent_attr =
+-      __ATTR(uevent, S_IWUSR, NULL, store_uevent);
+-
+ void class_device_initialize(struct class_device *class_dev)
  {
-+      struct lpfc_hba  *phba = vport->phba;
-       struct lpfc_sli_ct_request *Response =
-               (struct lpfc_sli_ct_request *) mp->virt;
-       struct lpfc_nodelist *ndlp = NULL;
-       struct lpfc_dmabuf *mlast, *next_mp;
-       uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType;
--      uint32_t Did;
--      uint32_t CTentry;
-+      uint32_t Did, CTentry;
-       int Cnt;
-       struct list_head head;
+       kobj_set_kset_s(class_dev, class_obj_subsys);
+@@ -628,16 +603,33 @@
+                                 &parent_class->subsys.kobj, "subsystem");
+       if (error)
+               goto out3;
+-
+-      error = class_device_create_file(class_dev, &class_uevent_attr);
++      class_dev->uevent_attr.attr.name = "uevent";
++      class_dev->uevent_attr.attr.mode = S_IWUSR;
++      class_dev->uevent_attr.attr.owner = parent_class->owner;
++      class_dev->uevent_attr.store = store_uevent;
++      error = class_device_create_file(class_dev, &class_dev->uevent_attr);
+       if (error)
+               goto out3;
  
--      lpfc_set_disctmo(phba);
-+      lpfc_set_disctmo(vport);
-+      vport->num_disc_nodes = 0;
+       if (MAJOR(class_dev->devt)) {
+-              error = class_device_create_file(class_dev, &class_devt_attr);
+-              if (error)
++              struct class_device_attribute *attr;
++              attr = kzalloc(sizeof(*attr), GFP_KERNEL);
++              if (!attr) {
++                      error = -ENOMEM;
+                       goto out4;
+               }
++              attr->attr.name = "dev";
++              attr->attr.mode = S_IRUGO;
++              attr->attr.owner = parent_class->owner;
++              attr->show = show_dev;
++              error = class_device_create_file(class_dev, attr);
++              if (error) {
++                      kfree(attr);
++                      goto out4;
++              }
++
++              class_dev->devt_attr = attr;
++      }
  
+       error = class_device_add_attrs(class_dev);
+       if (error)
+@@ -679,10 +671,10 @@
+  out6:
+       class_device_remove_attrs(class_dev);
+  out5:
+-      if (MAJOR(class_dev->devt))
+-              class_device_remove_file(class_dev, &class_devt_attr);
++      if (class_dev->devt_attr)
++              class_device_remove_file(class_dev, class_dev->devt_attr);
+  out4:
+-      class_device_remove_file(class_dev, &class_uevent_attr);
++      class_device_remove_file(class_dev, &class_dev->uevent_attr);
+  out3:
+       kobject_del(&class_dev->kobj);
+  out2:
+@@ -782,9 +774,9 @@
+               sysfs_remove_link(&class_dev->kobj, "device");
+       }
+       sysfs_remove_link(&class_dev->kobj, "subsystem");
+-      class_device_remove_file(class_dev, &class_uevent_attr);
+-      if (MAJOR(class_dev->devt))
+-              class_device_remove_file(class_dev, &class_devt_attr);
++      class_device_remove_file(class_dev, &class_dev->uevent_attr);
++      if (class_dev->devt_attr)
++              class_device_remove_file(class_dev, class_dev->devt_attr);
+       class_device_remove_attrs(class_dev);
+       class_device_remove_groups(class_dev);
  
-       list_add_tail(&head, &mp->list);
-@@ -350,39 +436,96 @@
+diff -Nurb linux-2.6.22-590/drivers/base/core.c linux-2.6.22-570/drivers/base/core.c
+--- linux-2.6.22-590/drivers/base/core.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/base/core.c       2007-07-08 19:32:17.000000000 -0400
+@@ -310,9 +310,6 @@
+       return count;
+ }
  
-               /* Loop through entire NameServer list of DIDs */
-               while (Cnt >= sizeof (uint32_t)) {
+-static struct device_attribute uevent_attr =
+-      __ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);
 -
-                       /* Get next DID from NameServer List */
-                       CTentry = *ctptr++;
-                       Did = ((be32_to_cpu(CTentry)) & Mask_DID);
-                       ndlp = NULL;
--                      if (Did != phba->fc_myDID) {
--                              /* Check for rscn processing or not */
--                              ndlp = lpfc_setup_disc_node(phba, Did);
--                      }
--                      /* Mark all node table entries that are in the
--                         Nameserver */
-+
-+                      /*
-+                       * Check for rscn processing or not
-+                       * To conserve rpi's, filter out addresses for other
-+                       * vports on the same physical HBAs.
-+                       */
-+                      if ((Did != vport->fc_myDID) &&
-+                          ((lpfc_find_vport_by_did(phba, Did) == NULL) ||
-+                           phba->cfg_peer_port_login)) {
-+                              if ((vport->port_type != LPFC_NPIV_PORT) ||
-+                                  (vport->fc_flag & FC_RFF_NOT_SUPPORTED) ||
-+                                  (!phba->cfg_vport_restrict_login)) {
-+                                      ndlp = lpfc_setup_disc_node(vport, Did);
-                       if (ndlp) {
--                              /* NameServer Rsp */
--                              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                                              "%d:0238 Process x%x NameServer"
--                                              " Rsp Data: x%x x%x x%x\n",
--                                              phba->brd_no,
-+                                              lpfc_debugfs_disc_trc(vport,
-+                                              LPFC_DISC_TRC_CT,
-+                                              "Parse GID_FTrsp: "
-+                                              "did:x%x flg:x%x x%x",
-                                               Did, ndlp->nlp_flag,
--                                              phba->fc_flag,
--                                              phba->fc_rscn_id_cnt);
-+                                              vport->fc_flag);
-+
-+                                              lpfc_printf_log(phba, KERN_INFO,
-+                                                      LOG_DISCOVERY,
-+                                                      "%d (%d):0238 Process "
-+                                                      "x%x NameServer Rsp"
-+                                                      "Data: x%x x%x x%x\n",
-+                                                      phba->brd_no,
-+                                                      vport->vpi, Did,
-+                                                      ndlp->nlp_flag,
-+                                                      vport->fc_flag,
-+                                                      vport->fc_rscn_id_cnt);
-                       } else {
--                              /* NameServer Rsp */
--                              lpfc_printf_log(phba,
--                                              KERN_INFO,
-+                                              lpfc_debugfs_disc_trc(vport,
-+                                              LPFC_DISC_TRC_CT,
-+                                              "Skip1 GID_FTrsp: "
-+                                              "did:x%x flg:x%x cnt:%d",
-+                                              Did, vport->fc_flag,
-+                                              vport->fc_rscn_id_cnt);
-+
-+                                              lpfc_printf_log(phba, KERN_INFO,
-                                               LOG_DISCOVERY,
--                                              "%d:0239 Skip x%x NameServer "
--                                              "Rsp Data: x%x x%x x%x\n",
-+                                                      "%d (%d):0239 Skip x%x "
-+                                                      "NameServer Rsp Data: "
-+                                                      "x%x x%x\n",
-                                               phba->brd_no,
--                                              Did, Size, phba->fc_flag,
--                                              phba->fc_rscn_id_cnt);
-+                                                      vport->vpi, Did,
-+                                                      vport->fc_flag,
-+                                                      vport->fc_rscn_id_cnt);
-                       }
+ static int device_add_attributes(struct device *dev,
+                                struct device_attribute *attrs)
+ {
+@@ -426,9 +423,6 @@
+       return print_dev_t(buf, dev->devt);
+ }
  
-+                              } else {
-+                                      if (!(vport->fc_flag & FC_RSCN_MODE) ||
-+                                      (lpfc_rscn_payload_check(vport, Did))) {
-+                                              lpfc_debugfs_disc_trc(vport,
-+                                              LPFC_DISC_TRC_CT,
-+                                              "Query GID_FTrsp: "
-+                                              "did:x%x flg:x%x cnt:%d",
-+                                              Did, vport->fc_flag,
-+                                              vport->fc_rscn_id_cnt);
-+
-+                                              if (lpfc_ns_cmd(vport,
-+                                                      SLI_CTNS_GFF_ID,
-+                                                      0, Did) == 0)
-+                                                      vport->num_disc_nodes++;
-+                                      }
-+                                      else {
-+                                              lpfc_debugfs_disc_trc(vport,
-+                                              LPFC_DISC_TRC_CT,
-+                                              "Skip2 GID_FTrsp: "
-+                                              "did:x%x flg:x%x cnt:%d",
-+                                              Did, vport->fc_flag,
-+                                              vport->fc_rscn_id_cnt);
-+
-+                                              lpfc_printf_log(phba, KERN_INFO,
-+                                                      LOG_DISCOVERY,
-+                                                      "%d (%d):0245 Skip x%x "
-+                                                      "NameServer Rsp Data: "
-+                                                      "x%x x%x\n",
-+                                                      phba->brd_no,
-+                                                      vport->vpi, Did,
-+                                                      vport->fc_flag,
-+                                                      vport->fc_rscn_id_cnt);
-+                                      }
-+                              }
-+                      }
-                       if (CTentry & (be32_to_cpu(SLI_CT_LAST_ENTRY)))
-                               goto nsout1;
-                       Cnt -= sizeof (uint32_t);
-@@ -393,190 +536,369 @@
+-static struct device_attribute devt_attr =
+-      __ATTR(dev, S_IRUGO, show_dev, NULL);
+-
+ /*
+  *    devices_subsys - structure to be registered with kobject core.
+  */
+@@ -622,14 +616,8 @@
+                       return kobj;
  
- nsout1:
-       list_del(&head);
+               /* or create a new class-directory at the parent device */
+-              kobj = kobject_kset_add_dir(&dev->class->class_dirs,
++              return kobject_kset_add_dir(&dev->class->class_dirs,
+                                           parent_kobj, dev->class->name);
 -
--      /*
--       * The driver has cycled through all Nports in the RSCN payload.
--       * Complete the handling by cleaning up and marking the
--       * current driver state.
--       */
--      if (phba->hba_state == LPFC_HBA_READY) {
--              lpfc_els_flush_rscn(phba);
--              spin_lock_irq(phba->host->host_lock);
--              phba->fc_flag |= FC_RSCN_MODE; /* we are still in RSCN mode */
--              spin_unlock_irq(phba->host->host_lock);
--      }
+-              /* If we created a new class-directory setup shadowing */
+-              if (kobj && dev->class->shadow_ops)
+-                      sysfs_enable_shadowing(kobj, dev->class->shadow_ops);
+-
+-              return kobj;
+       }
+       if (parent)
+@@ -649,82 +637,6 @@
        return 0;
  }
  
+-static int device_add_class_symlinks(struct device *dev)
+-{
+-      int error;
 -
+-      if (!dev->class)
+-              return 0;
+-      error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
+-                                "subsystem");
+-      if (error)
+-              goto out;
+-      /*
+-       * If this is not a "fake" compatible device, then create the
+-       * symlink from the class to the device.
+-       */
+-      if (dev->kobj.parent != &dev->class->subsys.kobj) {
+-      error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
+-                                dev->bus_id);
+-      if (error)
+-              goto out_subsys;
+-      }
+-      /* only bus-device parents get a "device"-link */
+-      if (dev->parent && dev->parent->bus) {
+-              error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
+-                                        "device");
+-              if (error)
+-                      goto out_busid;
+-#ifdef CONFIG_SYSFS_DEPRECATED
+-              {
+-                      char * class_name = make_class_name(dev->class->name,
+-                                                              &dev->kobj);
+-                      if (class_name)
+-                              error = sysfs_create_link(&dev->parent->kobj,
+-                                                      &dev->kobj, class_name);
+-                      kfree(class_name);
+-                      if (error)
+-                              goto out_device;
+-              }
+-#endif
+-      }
+-      return 0;
 -
+-#ifdef CONFIG_SYSFS_DEPRECATED
+-out_device:
+-      if (dev->parent)
+-              sysfs_remove_link(&dev->kobj, "device");
+-#endif
+-out_busid:
+-      if (dev->kobj.parent != &dev->class->subsys.kobj)
+-      sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+-out_subsys:
+-      sysfs_remove_link(&dev->kobj, "subsystem");
+-out:
+-      return error;
+-}
 -
- static void
--lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                      struct lpfc_iocbq * rspiocb)
-+lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                      struct lpfc_iocbq *rspiocb)
- {
-+      struct lpfc_vport *vport = cmdiocb->vport;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-       IOCB_t *irsp;
--      struct lpfc_sli *psli;
-       struct lpfc_dmabuf *bmp;
--      struct lpfc_dmabuf *inp;
-       struct lpfc_dmabuf *outp;
--      struct lpfc_nodelist *ndlp;
-       struct lpfc_sli_ct_request *CTrsp;
-+      int rc;
--      psli = &phba->sli;
-       /* we pass cmdiocb to state machine which needs rspiocb as well */
-       cmdiocb->context_un.rsp_iocb = rspiocb;
--      inp = (struct lpfc_dmabuf *) cmdiocb->context1;
-       outp = (struct lpfc_dmabuf *) cmdiocb->context2;
-       bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
+-static void device_remove_class_symlinks(struct device *dev)
+-{
+-      if (!dev->class)
+-              return;
+-      if (dev->parent) {
+-#ifdef CONFIG_SYSFS_DEPRECATED
+-              char *class_name;
 -
-       irsp = &rspiocb->iocb;
--      if (irsp->ulpStatus) {
--              if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
--                      ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) ||
--                       (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) {
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
-+               "GID_FT cmpl:     status:x%x/x%x rtry:%d",
-+              irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry);
-+
-+      /* Don't bother processing response if vport is being torn down. */
-+      if (vport->load_flag & FC_UNLOADING)
-+              goto out;
-+
-+
-+      if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) {
-+              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                              "%d (%d):0216 Link event during NS query\n",
-+                              phba->brd_no, vport->vpi);
-+              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-                       goto out;
-               }
-+      if (irsp->ulpStatus) {
-               /* Check for retry */
--              if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
--                      phba->fc_ns_retry++;
-+              if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
-+                      if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
-+                              (irsp->un.ulpWord[4] != IOERR_NO_RESOURCES))
-+                              vport->fc_ns_retry++;
-                       /* CT command is being retried */
--                      ndlp = lpfc_findnode_did(phba, NameServer_DID);
--                      if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
--                              if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) ==
--                                  0) {
-+                      rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
-+                                       vport->fc_ns_retry, 0);
-+                      if (rc == 0)
-                                       goto out;
-                               }
--                      }
+-              class_name = make_class_name(dev->class->name, &dev->kobj);
+-              if (class_name) {
+-                      sysfs_remove_link(&dev->parent->kobj, class_name);
+-                      kfree(class_name);
 -              }
-+              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                      "%d (%d):0257 GID_FT Query error: 0x%x 0x%x\n",
-+                      phba->brd_no, vport->vpi, irsp->ulpStatus,
-+                      vport->fc_ns_retry);
-       } else {
-               /* Good status, continue checking */
-               CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
-               if (CTrsp->CommandResponse.bits.CmdRsp ==
-                   be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
-                       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                                      "%d:0208 NameServer Rsp "
-+                                      "%d (%d):0208 NameServer Rsp "
-                                       "Data: x%x\n",
--                                      phba->brd_no,
--                                      phba->fc_flag);
--                      lpfc_ns_rsp(phba, outp,
-+                                      phba->brd_no, vport->vpi,
-+                                      vport->fc_flag);
-+                      lpfc_ns_rsp(vport, outp,
-                                   (uint32_t) (irsp->un.genreq64.bdl.bdeSize));
-               } else if (CTrsp->CommandResponse.bits.CmdRsp ==
-                          be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
-                       /* NameServer Rsp Error */
-                       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                                      "%d:0240 NameServer Rsp Error "
-+                                      "%d (%d):0240 NameServer Rsp Error "
-                                       "Data: x%x x%x x%x x%x\n",
--                                      phba->brd_no,
-+                                      phba->brd_no, vport->vpi,
-                                       CTrsp->CommandResponse.bits.CmdRsp,
-                                       (uint32_t) CTrsp->ReasonCode,
-                                       (uint32_t) CTrsp->Explanation,
--                                      phba->fc_flag);
-+                                      vport->fc_flag);
-+
-+                      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
-+                              "GID_FT rsp err1  cmd:x%x rsn:x%x exp:x%x",
-+                              (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
-+                              (uint32_t) CTrsp->ReasonCode,
-+                              (uint32_t) CTrsp->Explanation);
-+
-               } else {
-                       /* NameServer Rsp Error */
--                      lpfc_printf_log(phba,
--                                      KERN_INFO,
--                                      LOG_DISCOVERY,
--                                      "%d:0241 NameServer Rsp Error "
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-+                                      "%d (%d):0241 NameServer Rsp Error "
-                                       "Data: x%x x%x x%x x%x\n",
--                                      phba->brd_no,
-+                                      phba->brd_no, vport->vpi,
-                                       CTrsp->CommandResponse.bits.CmdRsp,
-                                       (uint32_t) CTrsp->ReasonCode,
-                                       (uint32_t) CTrsp->Explanation,
--                                      phba->fc_flag);
-+                                      vport->fc_flag);
-+
-+                      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
-+                              "GID_FT rsp err2  cmd:x%x rsn:x%x exp:x%x",
-+                              (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
-+                              (uint32_t) CTrsp->ReasonCode,
-+                              (uint32_t) CTrsp->Explanation);
+-#endif
+-              sysfs_remove_link(&dev->kobj, "device");
+-      }
+-      if (dev->kobj.parent != &dev->class->subsys.kobj)
+-      sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+-      sysfs_remove_link(&dev->kobj, "subsystem");
+-}
+-
+ /**
+  *    device_add - add device to device hierarchy.
+  *    @dev:   device.
+@@ -739,6 +651,7 @@
+ int device_add(struct device *dev)
+ {
+       struct device *parent = NULL;
++      char *class_name = NULL;
+       struct class_interface *class_intf;
+       int error = -EINVAL;
+@@ -768,17 +681,58 @@
+               blocking_notifier_call_chain(&dev->bus->bus_notifier,
+                                            BUS_NOTIFY_ADD_DEVICE, dev);
+-      error = device_create_file(dev, &uevent_attr);
++      dev->uevent_attr.attr.name = "uevent";
++      dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR;
++      if (dev->driver)
++              dev->uevent_attr.attr.owner = dev->driver->owner;
++      dev->uevent_attr.store = store_uevent;
++      dev->uevent_attr.show = show_uevent;
++      error = device_create_file(dev, &dev->uevent_attr);
+       if (error)
+               goto attrError;
+       if (MAJOR(dev->devt)) {
+-              error = device_create_file(dev, &devt_attr);
+-              if (error)
++              struct device_attribute *attr;
++              attr = kzalloc(sizeof(*attr), GFP_KERNEL);
++              if (!attr) {
++                      error = -ENOMEM;
+                       goto ueventattrError;
                }
-       }
-       /* Link up / RSCN discovery */
--      lpfc_disc_start(phba);
-+      if (vport->num_disc_nodes == 0) {
-+              /*
-+               * The driver has cycled through all Nports in the RSCN payload.
-+               * Complete the handling by cleaning up and marking the
-+               * current driver state.
-+               */
-+              if (vport->port_state >= LPFC_DISC_AUTH) {
-+                      if (vport->fc_flag & FC_RSCN_MODE) {
-+                              lpfc_els_flush_rscn(vport);
-+                              spin_lock_irq(shost->host_lock);
-+                              vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
-+                              spin_unlock_irq(shost->host_lock);
-+                      }
-+                      else
-+                              lpfc_els_flush_rscn(vport);
+-      if ((error = device_add_class_symlinks(dev)))
+-              goto SymlinkError;
++              attr->attr.name = "dev";
++              attr->attr.mode = S_IRUGO;
++              if (dev->driver)
++                      attr->attr.owner = dev->driver->owner;
++              attr->show = show_dev;
++              error = device_create_file(dev, attr);
++              if (error) {
++                      kfree(attr);
++                      goto ueventattrError;
 +              }
 +
-+              lpfc_disc_start(vport);
++              dev->devt_attr = attr;
 +      }
- out:
--      lpfc_free_ct_rsp(phba, outp);
--      lpfc_mbuf_free(phba, inp->virt, inp->phys);
--      lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
--      kfree(inp);
--      kfree(bmp);
--      spin_lock_irq(phba->host->host_lock);
--      lpfc_sli_release_iocbq(phba, cmdiocb);
--      spin_unlock_irq(phba->host->host_lock);
-+      lpfc_ct_free_iocb(phba, cmdiocb);
-+      return;
-+}
-+
-+void
-+lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                      struct lpfc_iocbq *rspiocb)
-+{
-+      struct lpfc_vport *vport = cmdiocb->vport;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      IOCB_t *irsp = &rspiocb->iocb;
-+      struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1;
-+      struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2;
-+      struct lpfc_sli_ct_request *CTrsp;
-+      int did;
-+      uint8_t fbits;
-+      struct lpfc_nodelist *ndlp;
-+
-+      did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId;
-+      did = be32_to_cpu(did);
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
-+              "GFF_ID cmpl:     status:x%x/x%x did:x%x",
-+              irsp->ulpStatus, irsp->un.ulpWord[4], did);
 +
-+      if (irsp->ulpStatus == IOSTAT_SUCCESS) {
-+              /* Good status, continue checking */
-+              CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
-+              fbits = CTrsp->un.gff_acc.fbits[FCP_TYPE_FEATURE_OFFSET];
-+
-+              if (CTrsp->CommandResponse.bits.CmdRsp ==
-+                  be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
-+                      if ((fbits & FC4_FEATURE_INIT) &&
-+                          !(fbits & FC4_FEATURE_TARGET)) {
-+                              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                                              "%d (%d):0245 Skip x%x GFF "
-+                                              "NameServer Rsp Data: (init) "
-+                                              "x%x x%x\n", phba->brd_no,
-+                                              vport->vpi, did, fbits,
-+                                              vport->fc_rscn_id_cnt);
-+                              goto out;
-+                      }
++      if (dev->class) {
++              sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
++                                "subsystem");
++              /* If this is not a "fake" compatible device, then create the
++               * symlink from the class to the device. */
++              if (dev->kobj.parent != &dev->class->subsys.kobj)
++                      sysfs_create_link(&dev->class->subsys.kobj,
++                                        &dev->kobj, dev->bus_id);
++              if (parent) {
++                      sysfs_create_link(&dev->kobj, &dev->parent->kobj,
++                                                      "device");
++#ifdef CONFIG_SYSFS_DEPRECATED
++                      class_name = make_class_name(dev->class->name,
++                                                      &dev->kobj);
++                      if (class_name)
++                              sysfs_create_link(&dev->parent->kobj,
++                                                &dev->kobj, class_name);
++#endif
 +              }
 +      }
-+      else {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-+                              "%d (%d):0267 NameServer GFF Rsp"
-+                              " x%x Error (%d %d) Data: x%x x%x\n",
-+                              phba->brd_no, vport->vpi, did,
-+                              irsp->ulpStatus, irsp->un.ulpWord[4],
-+                              vport->fc_flag, vport->fc_rscn_id_cnt)
-+      }
-+
-+      /* This is a target port, unregistered port, or the GFF_ID failed */
-+      ndlp = lpfc_setup_disc_node(vport, did);
-+      if (ndlp) {
-+              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                              "%d (%d):0242 Process x%x GFF "
-+                              "NameServer Rsp Data: x%x x%x x%x\n",
-+                              phba->brd_no, vport->vpi,
-+                              did, ndlp->nlp_flag, vport->fc_flag,
-+                              vport->fc_rscn_id_cnt);
-+      } else {
-+              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                              "%d (%d):0243 Skip x%x GFF "
-+                              "NameServer Rsp Data: x%x x%x\n",
-+                              phba->brd_no, vport->vpi, did,
-+                              vport->fc_flag, vport->fc_rscn_id_cnt);
-+      }
-+out:
-+      /* Link up / RSCN discovery */
-+      if (vport->num_disc_nodes)
-+              vport->num_disc_nodes--;
-+      if (vport->num_disc_nodes == 0) {
-+              /*
-+               * The driver has cycled through all Nports in the RSCN payload.
-+               * Complete the handling by cleaning up and marking the
-+               * current driver state.
-+               */
-+              if (vport->port_state >= LPFC_DISC_AUTH) {
-+                      if (vport->fc_flag & FC_RSCN_MODE) {
-+                              lpfc_els_flush_rscn(vport);
-+                              spin_lock_irq(shost->host_lock);
-+                              vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
-+                              spin_unlock_irq(shost->host_lock);
-+                      }
-+                      else
-+                              lpfc_els_flush_rscn(vport);
-+              }
-+              lpfc_disc_start(vport);
++
+       if ((error = device_add_attrs(dev)))
+               goto AttrsError;
+       if ((error = device_pm_add(dev)))
+@@ -802,6 +756,7 @@
+               up(&dev->class->sem);
+       }
+  Done:
++      kfree(class_name);
+       put_device(dev);
+       return error;
+  BusError:
+@@ -812,10 +767,10 @@
+                                            BUS_NOTIFY_DEL_DEVICE, dev);
+       device_remove_attrs(dev);
+  AttrsError:
+-      device_remove_class_symlinks(dev);
+- SymlinkError:
+-      if (MAJOR(dev->devt))
+-              device_remove_file(dev, &devt_attr);
++      if (dev->devt_attr) {
++              device_remove_file(dev, dev->devt_attr);
++              kfree(dev->devt_attr);
 +      }
-+      lpfc_ct_free_iocb(phba, cmdiocb);
-       return;
- }
  
-+
- static void
--lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                      struct lpfc_iocbq * rspiocb)
-+lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                      struct lpfc_iocbq *rspiocb)
- {
--      struct lpfc_sli *psli;
--      struct lpfc_dmabuf *bmp;
-+      struct lpfc_vport *vport = cmdiocb->vport;
-       struct lpfc_dmabuf *inp;
-       struct lpfc_dmabuf *outp;
-       IOCB_t *irsp;
-       struct lpfc_sli_ct_request *CTrsp;
-+      int cmdcode, rc;
-+      uint8_t retry;
-+      uint32_t latt;
+       if (dev->class) {
+               sysfs_remove_link(&dev->kobj, "subsystem");
+@@ -837,7 +792,7 @@
+               }
+       }
+  ueventattrError:
+-      device_remove_file(dev, &uevent_attr);
++      device_remove_file(dev, &dev->uevent_attr);
+  attrError:
+       kobject_uevent(&dev->kobj, KOBJ_REMOVE);
+       kobject_del(&dev->kobj);
+@@ -914,15 +869,17 @@
  
--      psli = &phba->sli;
-       /* we pass cmdiocb to state machine which needs rspiocb as well */
-       cmdiocb->context_un.rsp_iocb = rspiocb;
+       if (parent)
+               klist_del(&dev->knode_parent);
+-      if (MAJOR(dev->devt))
+-              device_remove_file(dev, &devt_attr);
++      if (dev->devt_attr) {
++              device_remove_file(dev, dev->devt_attr);
++              kfree(dev->devt_attr);
++      }
+       if (dev->class) {
+               sysfs_remove_link(&dev->kobj, "subsystem");
+               /* If this is not a "fake" compatible device, remove the
+                * symlink from the class to the device. */
+               if (dev->kobj.parent != &dev->class->subsys.kobj)
+-                      sysfs_delete_link(&dev->class->subsys.kobj,
+-                                        &dev->kobj, dev->bus_id);
++                      sysfs_remove_link(&dev->class->subsys.kobj,
++                                        dev->bus_id);
+               if (parent) {
+ #ifdef CONFIG_SYSFS_DEPRECATED
+                       char *class_name = make_class_name(dev->class->name,
+@@ -969,7 +926,7 @@
+                       up(&dev->class->sem);
+               }
+       }
+-      device_remove_file(dev, &uevent_attr);
++      device_remove_file(dev, &dev->uevent_attr);
+       device_remove_attrs(dev);
+       bus_remove_device(dev);
  
-       inp = (struct lpfc_dmabuf *) cmdiocb->context1;
-       outp = (struct lpfc_dmabuf *) cmdiocb->context2;
--      bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
-       irsp = &rspiocb->iocb;
+@@ -1198,7 +1155,7 @@
+ {
+       char *old_class_name = NULL;
+       char *new_class_name = NULL;
+-      char *old_device_name = NULL;
++      char *old_symlink_name = NULL;
+       int error;
  
-+      cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)->
-+                                      CommandResponse.bits.CmdRsp);
-       CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
+       dev = get_device(dev);
+@@ -1212,46 +1169,42 @@
+               old_class_name = make_class_name(dev->class->name, &dev->kobj);
+ #endif
  
-+      latt = lpfc_els_chk_latt(vport);
-+
-       /* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                      "%d:0209 RFT request completes ulpStatus x%x "
--                      "CmdRsp x%x\n", phba->brd_no, irsp->ulpStatus,
--                      CTrsp->CommandResponse.bits.CmdRsp);
-+                      "%d (%d):0209 RFT request completes, latt %d, "
-+                      "ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n",
-+                      phba->brd_no, vport->vpi, latt, irsp->ulpStatus,
-+                      CTrsp->CommandResponse.bits.CmdRsp,
-+                      cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag);
--      lpfc_free_ct_rsp(phba, outp);
--      lpfc_mbuf_free(phba, inp->virt, inp->phys);
--      lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
--      kfree(inp);
--      kfree(bmp);
--      spin_lock_irq(phba->host->host_lock);
--      lpfc_sli_release_iocbq(phba, cmdiocb);
--      spin_unlock_irq(phba->host->host_lock);
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
-+              "CT cmd cmpl:     status:x%x/x%x cmd:x%x",
-+              irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode);
-+
-+      if (irsp->ulpStatus) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-+                      "%d (%d):0268 NS cmd %x Error (%d %d)\n",
-+                      phba->brd_no, vport->vpi, cmdcode,
-+                      irsp->ulpStatus, irsp->un.ulpWord[4]);
-+
-+              if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-+                      ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) ||
-+                       (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED)))
-+                      goto out;
+-      old_device_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
+-      if (!old_device_name) {
++      if (dev->class) {
++              old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
++              if (!old_symlink_name) {
+                       error = -ENOMEM;
+-              goto out;
++                      goto out_free_old_class;
+       }
+-      strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE);
+-      strlcpy(dev->bus_id, new_name, BUS_ID_SIZE);
+-
+-      if (dev->class && (dev->kobj.parent != &dev->class->subsys.kobj)) {
+-              error = sysfs_rename_link(&dev->class->subsys.kobj,
+-                      &dev->kobj, old_device_name, new_name);
+-              if (error)
+-                      goto out;
++              strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE);
+       }
++      strlcpy(dev->bus_id, new_name, BUS_ID_SIZE);
 +
-+              retry = cmdiocb->retry;
-+              if (retry >= LPFC_MAX_NS_RETRY)
-+                      goto out;
+       error = kobject_rename(&dev->kobj, new_name);
+-      if (error) {
+-              strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE);
+-              goto out;
+-      }
+ #ifdef CONFIG_SYSFS_DEPRECATED
+       if (old_class_name) {
+-              error = -ENOMEM;
+               new_class_name = make_class_name(dev->class->name, &dev->kobj);
+-              if (!new_class_name)
+-                      goto out;
+-
+-              error = sysfs_rename_link(&dev->parent->kobj, &dev->kobj,
+-                                        old_class_name, new_class_name);
+-                      if (error)
+-                              goto out;
++              if (new_class_name) {
++                      sysfs_create_link(&dev->parent->kobj, &dev->kobj,
++                                        new_class_name);
++                      sysfs_remove_link(&dev->parent->kobj, old_class_name);
++              }
+       }
+ #endif
+-out:
 +
-+              retry++;
-+              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                              "%d (%d):0216 Retrying NS cmd %x\n",
-+                              phba->brd_no, vport->vpi, cmdcode);
-+              rc = lpfc_ns_cmd(vport, cmdcode, retry, 0);
-+              if (rc == 0)
-+                      goto out;
++      if (dev->class) {
++              sysfs_remove_link(&dev->class->subsys.kobj,
++                                old_symlink_name);
++              sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
++                                dev->bus_id);
 +      }
-+
-+out:
-+      lpfc_ct_free_iocb(phba, cmdiocb);
-       return;
- }
+       put_device(dev);
  
- static void
--lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                      struct lpfc_iocbq * rspiocb)
-+lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                      struct lpfc_iocbq *rspiocb)
- {
-       lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
-       return;
- }
+       kfree(new_class_name);
++      kfree(old_symlink_name);
++ out_free_old_class:
+       kfree(old_class_name);
+-      kfree(old_device_name);
  
- static void
--lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                       struct lpfc_iocbq * rspiocb)
-+lpfc_cmpl_ct_cmd_rspn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                       struct lpfc_iocbq *rspiocb)
- {
-       lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
-       return;
+       return error;
  }
+diff -Nurb linux-2.6.22-590/drivers/base/dd.c linux-2.6.22-570/drivers/base/dd.c
+--- linux-2.6.22-590/drivers/base/dd.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/base/dd.c 2007-07-08 19:32:17.000000000 -0400
+@@ -296,8 +296,9 @@
+ {
+       struct device_driver * drv;
  
- static void
--lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                       struct lpfc_iocbq * rspiocb)
-+lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                       struct lpfc_iocbq *rspiocb)
+-      drv = get_driver(dev->driver);
++      drv = dev->driver;
+       if (drv) {
++              get_driver(drv);
+               driver_sysfs_remove(dev);
+               sysfs_remove_link(&dev->kobj, "driver");
+               klist_remove(&dev->knode_driver);
+diff -Nurb linux-2.6.22-590/drivers/base/firmware_class.c linux-2.6.22-570/drivers/base/firmware_class.c
+--- linux-2.6.22-590/drivers/base/firmware_class.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/base/firmware_class.c     2007-07-08 19:32:17.000000000 -0400
+@@ -175,7 +175,7 @@
+ static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
+ static ssize_t
+-firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
++firmware_data_read(struct kobject *kobj,
+                  char *buffer, loff_t offset, size_t count)
  {
-       lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
-       return;
+       struct device *dev = to_dev(kobj);
+@@ -240,7 +240,7 @@
+  *    the driver as a firmware image.
+  **/
+ static ssize_t
+-firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr,
++firmware_data_write(struct kobject *kobj,
+                   char *buffer, loff_t offset, size_t count)
+ {
+       struct device *dev = to_dev(kobj);
+@@ -271,7 +271,7 @@
  }
  
--void
--lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp)
-+static void
-+lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                      struct lpfc_iocbq *rspiocb)
- {
--      char fwrev[16];
-+      IOCB_t *irsp = &rspiocb->iocb;
-+      struct lpfc_vport *vport = cmdiocb->vport;
+ static struct bin_attribute firmware_attr_data_tmpl = {
+-      .attr = {.name = "data", .mode = 0644},
++      .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
+       .size = 0,
+       .read = firmware_data_read,
+       .write = firmware_data_write,
+diff -Nurb linux-2.6.22-590/drivers/block/acsi_slm.c linux-2.6.22-570/drivers/block/acsi_slm.c
+--- linux-2.6.22-590/drivers/block/acsi_slm.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/block/acsi_slm.c  2007-07-08 19:32:17.000000000 -0400
+@@ -367,7 +367,7 @@
+       int length;
+       int end;
  
--      lpfc_decode_firmware_rev(phba, fwrev, 0);
-+      if (irsp->ulpStatus != IOSTAT_SUCCESS)
-+          vport->fc_flag |= FC_RFF_NOT_SUPPORTED;
+-      if (!(page = __get_free_page(GFP_TEMPORARY)))
++      if (!(page = __get_free_page( GFP_KERNEL )))
+               return( -ENOMEM );
+       
+       length = slm_getstats( (char *)page, iminor(node) );
+diff -Nurb linux-2.6.22-590/drivers/block/aoe/aoecmd.c linux-2.6.22-570/drivers/block/aoe/aoecmd.c
+--- linux-2.6.22-590/drivers/block/aoe/aoecmd.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/block/aoe/aoecmd.c        2007-07-08 19:32:17.000000000 -0400
+@@ -9,7 +9,6 @@
+ #include <linux/skbuff.h>
+ #include <linux/netdevice.h>
+ #include <linux/genhd.h>
+-#include <net/net_namespace.h>
+ #include <asm/unaligned.h>
+ #include "aoe.h"
  
--      sprintf(symbp, "Emulex %s FV%s DV%s", phba->ModelName,
--              fwrev, lpfc_release_version);
-+      lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
-       return;
- }
+@@ -195,7 +194,7 @@
+       sl = sl_tail = NULL;
  
-+int
-+lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol,
-+      size_t size)
-+{
-+      int n;
-+      uint8_t *wwn = vport->phba->wwpn;
-+
-+      n = snprintf(symbol, size,
-+                   "Emulex PPN-%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
-+                   wwn[0], wwn[1], wwn[2], wwn[3],
-+                   wwn[4], wwn[5], wwn[6], wwn[7]);
-+
-+      if (vport->port_type == LPFC_PHYSICAL_PORT)
-+              return n;
-+
-+      if (n < size)
-+              n += snprintf(symbol + n, size - n, " VPort-%d", vport->vpi);
-+
-+      if (n < size && vport->vname)
-+              n += snprintf(symbol + n, size - n, " VName-%s", vport->vname);
-+      return n;
-+}
-+
-+int
-+lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
-+      size_t size)
-+{
-+      char fwrev[16];
-+      int n;
-+
-+      lpfc_decode_firmware_rev(vport->phba, fwrev, 0);
-+
-+      n = snprintf(symbol, size, "Emulex %s FV%s DV%s",
-+              vport->phba->ModelName, fwrev, lpfc_release_version);
-+      return n;
-+}
-+
- /*
-  * lpfc_ns_cmd
-  * Description:
-@@ -585,55 +907,76 @@
-  *       LI_CTNS_RFT_ID
-  */
- int
--lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
-+lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
-+          uint8_t retry, uint32_t context)
- {
-+      struct lpfc_nodelist * ndlp;
-+      struct lpfc_hba *phba = vport->phba;
-       struct lpfc_dmabuf *mp, *bmp;
-       struct lpfc_sli_ct_request *CtReq;
-       struct ulp_bde64 *bpl;
-       void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
-                     struct lpfc_iocbq *) = NULL;
-       uint32_t rsp_size = 1024;
-+      size_t   size;
-+      int rc = 0;
-+
-+      ndlp = lpfc_findnode_did(vport, NameServer_DID);
-+      if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) {
-+              rc=1;
-+              goto ns_cmd_exit;
-+      }
+       read_lock(&dev_base_lock);
+-      for_each_netdev(&init_net, ifp) {
++      for_each_netdev(ifp) {
+               dev_hold(ifp);
+               if (!is_aoe_netif(ifp))
+                       goto cont;
+diff -Nurb linux-2.6.22-590/drivers/block/aoe/aoenet.c linux-2.6.22-570/drivers/block/aoe/aoenet.c
+--- linux-2.6.22-590/drivers/block/aoe/aoenet.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/block/aoe/aoenet.c        2007-07-08 19:32:17.000000000 -0400
+@@ -8,7 +8,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/netdevice.h>
+ #include <linux/moduleparam.h>
+-#include <net/net_namespace.h>
+ #include <asm/unaligned.h>
+ #include "aoe.h"
  
-       /* fill in BDEs for command */
-       /* Allocate buffer for command payload */
-       mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
--      if (!mp)
-+      if (!mp) {
-+              rc=2;
-               goto ns_cmd_exit;
-+      }
+@@ -115,9 +114,6 @@
+       struct aoe_hdr *h;
+       u32 n;
  
-       INIT_LIST_HEAD(&mp->list);
-       mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
--      if (!mp->virt)
-+      if (!mp->virt) {
-+              rc=3;
-               goto ns_cmd_free_mp;
-+      }
+-      if (ifp->nd_net != &init_net)
+-              goto exit;
+-
+       skb = skb_share_check(skb, GFP_ATOMIC);
+       if (skb == NULL)
+               return 0;
+diff -Nurb linux-2.6.22-590/drivers/block/cciss_scsi.c linux-2.6.22-570/drivers/block/cciss_scsi.c
+--- linux-2.6.22-590/drivers/block/cciss_scsi.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/block/cciss_scsi.c        2007-07-08 19:32:17.000000000 -0400
+@@ -555,6 +555,7 @@
+ {
+       struct scsi_cmnd *cmd;
+       ctlr_info_t *ctlr;
++      u64bit addr64;
+       ErrorInfo_struct *ei;
  
-       /* Allocate buffer for Buffer ptr list */
-       bmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
--      if (!bmp)
-+      if (!bmp) {
-+              rc=4;
-               goto ns_cmd_free_mpvirt;
-+      }
+       ei = cp->err_info;
+@@ -568,7 +569,20 @@
+       cmd = (struct scsi_cmnd *) cp->scsi_cmd;        
+       ctlr = hba[cp->ctlr];
  
-       INIT_LIST_HEAD(&bmp->list);
-       bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys));
--      if (!bmp->virt)
-+      if (!bmp->virt) {
-+              rc=5;
-               goto ns_cmd_free_bmp;
+-      scsi_dma_unmap(cmd);
++      /* undo the DMA mappings */
++
++      if (cmd->use_sg) {
++              pci_unmap_sg(ctlr->pdev,
++                      cmd->request_buffer, cmd->use_sg,
++                              cmd->sc_data_direction); 
++      }
++      else if (cmd->request_bufflen) {
++              addr64.val32.lower = cp->SG[0].Addr.lower;
++                addr64.val32.upper = cp->SG[0].Addr.upper;
++                pci_unmap_single(ctlr->pdev, (dma_addr_t) addr64.val,
++                      cmd->request_bufflen, 
++                              cmd->sc_data_direction);
 +      }
  
-       /* NameServer Req */
--      lpfc_printf_log(phba,
--                      KERN_INFO,
--                      LOG_DISCOVERY,
--                      "%d:0236 NameServer Req Data: x%x x%x x%x\n",
--                      phba->brd_no, cmdcode, phba->fc_flag,
--                      phba->fc_rscn_id_cnt);
-+      lpfc_printf_log(phba, KERN_INFO ,LOG_DISCOVERY,
-+                      "%d (%d):0236 NameServer Req Data: x%x x%x x%x\n",
-+                      phba->brd_no, vport->vpi, cmdcode, vport->fc_flag,
-+                      vport->fc_rscn_id_cnt);
+       cmd->result = (DID_OK << 16);           /* host byte */
+       cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */
+@@ -583,7 +597,7 @@
+               ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
+                       SCSI_SENSE_BUFFERSIZE : 
+                       ei->SenseLen);
+-      scsi_set_resid(cmd, ei->ResidualCnt);
++      cmd->resid = ei->ResidualCnt;
  
-       bpl = (struct ulp_bde64 *) bmp->virt;
-       memset(bpl, 0, sizeof(struct ulp_bde64));
--      bpl->addrHigh = le32_to_cpu( putPaddrHigh(mp->phys) );
--      bpl->addrLow = le32_to_cpu( putPaddrLow(mp->phys) );
-+      bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
-+      bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
-       bpl->tus.f.bdeFlags = 0;
-       if (cmdcode == SLI_CTNS_GID_FT)
-               bpl->tus.f.bdeSize = GID_REQUEST_SZ;
-+      else if (cmdcode == SLI_CTNS_GFF_ID)
-+              bpl->tus.f.bdeSize = GFF_REQUEST_SZ;
-       else if (cmdcode == SLI_CTNS_RFT_ID)
-               bpl->tus.f.bdeSize = RFT_REQUEST_SZ;
-       else if (cmdcode == SLI_CTNS_RNN_ID)
-               bpl->tus.f.bdeSize = RNN_REQUEST_SZ;
-+      else if (cmdcode == SLI_CTNS_RSPN_ID)
-+              bpl->tus.f.bdeSize = RSPN_REQUEST_SZ;
-       else if (cmdcode == SLI_CTNS_RSNN_NN)
-               bpl->tus.f.bdeSize = RSNN_REQUEST_SZ;
-       else if (cmdcode == SLI_CTNS_RFF_ID)
-@@ -654,56 +997,78 @@
-               CtReq->CommandResponse.bits.CmdRsp =
-                   be16_to_cpu(SLI_CTNS_GID_FT);
-               CtReq->un.gid.Fc4Type = SLI_CTPT_FCP;
--              if (phba->hba_state < LPFC_HBA_READY)
--                      phba->hba_state = LPFC_NS_QRY;
--              lpfc_set_disctmo(phba);
-+              if (vport->port_state < LPFC_NS_QRY)
-+                      vport->port_state = LPFC_NS_QRY;
-+              lpfc_set_disctmo(vport);
-               cmpl = lpfc_cmpl_ct_cmd_gid_ft;
-               rsp_size = FC_MAX_NS_RSP;
-               break;
+       if(ei->CommandStatus != 0) 
+       { /* an error has occurred */ 
+@@ -1190,29 +1204,46 @@
+               CommandList_struct *cp, 
+               struct scsi_cmnd *cmd)
+ {
+-      unsigned int len;
+-      struct scatterlist *sg;
++      unsigned int use_sg, nsegs=0, len;
++      struct scatterlist *scatter = (struct scatterlist *) cmd->request_buffer;
+       __u64 addr64;
+-      int use_sg, i;
  
-+      case SLI_CTNS_GFF_ID:
-+              CtReq->CommandResponse.bits.CmdRsp =
-+                      be16_to_cpu(SLI_CTNS_GFF_ID);
-+              CtReq->un.gff.PortId = be32_to_cpu(context);
-+              cmpl = lpfc_cmpl_ct_cmd_gff_id;
-+              break;
+-      BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES);
++      /* is it just one virtual address? */   
++      if (!cmd->use_sg) {
++              if (cmd->request_bufflen) {     /* anything to xfer? */
 +
-       case SLI_CTNS_RFT_ID:
-               CtReq->CommandResponse.bits.CmdRsp =
-                   be16_to_cpu(SLI_CTNS_RFT_ID);
--              CtReq->un.rft.PortId = be32_to_cpu(phba->fc_myDID);
-+              CtReq->un.rft.PortId = be32_to_cpu(vport->fc_myDID);
-               CtReq->un.rft.fcpReg = 1;
-               cmpl = lpfc_cmpl_ct_cmd_rft_id;
-               break;
++                      addr64 = (__u64) pci_map_single(pdev, 
++                              cmd->request_buffer, 
++                              cmd->request_bufflen, 
++                              cmd->sc_data_direction); 
+       
+-      use_sg = scsi_dma_map(cmd);
+-      if (use_sg) {   /* not too many addrs? */
+-              scsi_for_each_sg(cmd, sg, use_sg, i) {
+-                      addr64 = (__u64) sg_dma_address(sg);
+-                      len  = sg_dma_len(sg);
+-                      cp->SG[i].Addr.lower =
++                      cp->SG[0].Addr.lower = 
+                         (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
+-                      cp->SG[i].Addr.upper =
++                      cp->SG[0].Addr.upper =
+                         (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
+-                      cp->SG[i].Len = len;
+-                      cp->SG[i].Ext = 0;  // we are not chaining
++                      cp->SG[0].Len = cmd->request_bufflen;
++                      nsegs=1;
+               }
++      } /* else, must be a list of virtual addresses.... */
++      else if (cmd->use_sg <= MAXSGENTRIES) { /* not too many addrs? */
++
++              use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg,
++                      cmd->sc_data_direction);
++
++              for (nsegs=0; nsegs < use_sg; nsegs++) {
++                      addr64 = (__u64) sg_dma_address(&scatter[nsegs]);
++                      len  = sg_dma_len(&scatter[nsegs]);
++                      cp->SG[nsegs].Addr.lower =
++                        (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
++                      cp->SG[nsegs].Addr.upper =
++                        (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
++                      cp->SG[nsegs].Len = len;
++                      cp->SG[nsegs].Ext = 0;  // we are not chaining
+               }
++      } else BUG();
  
--      case SLI_CTNS_RFF_ID:
--              CtReq->CommandResponse.bits.CmdRsp =
--                      be16_to_cpu(SLI_CTNS_RFF_ID);
--              CtReq->un.rff.PortId = be32_to_cpu(phba->fc_myDID);
--              CtReq->un.rff.feature_res = 0;
--              CtReq->un.rff.feature_tgt = 0;
--              CtReq->un.rff.type_code = FC_FCP_DATA;
--              CtReq->un.rff.feature_init = 1;
--              cmpl = lpfc_cmpl_ct_cmd_rff_id;
--              break;
--
-       case SLI_CTNS_RNN_ID:
-               CtReq->CommandResponse.bits.CmdRsp =
-                   be16_to_cpu(SLI_CTNS_RNN_ID);
--              CtReq->un.rnn.PortId = be32_to_cpu(phba->fc_myDID);
--              memcpy(CtReq->un.rnn.wwnn,  &phba->fc_nodename,
-+              CtReq->un.rnn.PortId = be32_to_cpu(vport->fc_myDID);
-+              memcpy(CtReq->un.rnn.wwnn,  &vport->fc_nodename,
-                      sizeof (struct lpfc_name));
-               cmpl = lpfc_cmpl_ct_cmd_rnn_id;
-               break;
+-      cp->Header.SGList = (__u8) use_sg;   /* no. SGs contig in this cmd */
+-      cp->Header.SGTotal = (__u16) use_sg; /* total sgs in this cmd list */
++      cp->Header.SGList = (__u8) nsegs;   /* no. SGs contig in this cmd */
++      cp->Header.SGTotal = (__u16) nsegs; /* total sgs in this cmd list */
+       return;
+ }
  
-+      case SLI_CTNS_RSPN_ID:
-+              CtReq->CommandResponse.bits.CmdRsp =
-+                  be16_to_cpu(SLI_CTNS_RSPN_ID);
-+              CtReq->un.rspn.PortId = be32_to_cpu(vport->fc_myDID);
-+              size = sizeof(CtReq->un.rspn.symbname);
-+              CtReq->un.rspn.len =
-+                      lpfc_vport_symbolic_port_name(vport,
-+                      CtReq->un.rspn.symbname, size);
-+              cmpl = lpfc_cmpl_ct_cmd_rspn_id;
-+              break;
-       case SLI_CTNS_RSNN_NN:
-               CtReq->CommandResponse.bits.CmdRsp =
-                   be16_to_cpu(SLI_CTNS_RSNN_NN);
--              memcpy(CtReq->un.rsnn.wwnn, &phba->fc_nodename,
-+              memcpy(CtReq->un.rsnn.wwnn, &vport->fc_nodename,
-                      sizeof (struct lpfc_name));
--              lpfc_get_hba_sym_node_name(phba, CtReq->un.rsnn.symbname);
--              CtReq->un.rsnn.len = strlen(CtReq->un.rsnn.symbname);
-+              size = sizeof(CtReq->un.rsnn.symbname);
-+              CtReq->un.rsnn.len =
-+                      lpfc_vport_symbolic_node_name(vport,
-+                      CtReq->un.rsnn.symbname, size);
-               cmpl = lpfc_cmpl_ct_cmd_rsnn_nn;
-               break;
-+      case SLI_CTNS_RFF_ID:
-+              vport->fc_flag &= ~FC_RFF_NOT_SUPPORTED;
-+              CtReq->CommandResponse.bits.CmdRsp =
-+                  be16_to_cpu(SLI_CTNS_RFF_ID);
-+              CtReq->un.rff.PortId = be32_to_cpu(vport->fc_myDID);;
-+              CtReq->un.rff.fbits = FC4_FEATURE_INIT;
-+              CtReq->un.rff.type_code = FC_FCP_DATA;
-+              cmpl = lpfc_cmpl_ct_cmd_rff_id;
-+              break;
-       }
+diff -Nurb linux-2.6.22-590/drivers/block/loop.c linux-2.6.22-570/drivers/block/loop.c
+--- linux-2.6.22-590/drivers/block/loop.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/block/loop.c      2008-01-23 19:16:04.000000000 -0500
+@@ -68,7 +68,6 @@
+ #include <linux/loop.h>
+ #include <linux/compat.h>
+ #include <linux/suspend.h>
+-#include <linux/freezer.h>
+ #include <linux/writeback.h>
+ #include <linux/buffer_head.h>                /* for invalidate_bdev() */
+ #include <linux/completion.h>
+@@ -578,6 +577,13 @@
+       struct loop_device *lo = data;
+       struct bio *bio;
  
--      if (!lpfc_ct_cmd(phba, mp, bmp, ndlp, cmpl, rsp_size))
-+      if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) {
-               /* On success, The cmpl function will free the buffers */
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
-+                      "Issue CT cmd:    cmd:x%x did:x%x",
-+                      cmdcode, ndlp->nlp_DID, 0);
-               return 0;
-+      }
++      /*
++       * loop can be used in an encrypted device,
++       * hence, it mustn't be stopped at all
++       * because it could be indirectly used during suspension
++       */
++      current->flags |= PF_NOFREEZE;
++
+       set_user_nice(current, -20);
  
-+      rc=6;
-       lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
- ns_cmd_free_bmp:
-       kfree(bmp);
-@@ -712,14 +1077,17 @@
- ns_cmd_free_mp:
-       kfree(mp);
- ns_cmd_exit:
-+      lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-+              "%d (%d):0266 Issue NameServer Req x%x err %d Data: x%x x%x\n",
-+                      phba->brd_no, vport->vpi, cmdcode, rc, vport->fc_flag,
-+                      vport->fc_rscn_id_cnt);
-       return 1;
- }
+       while (!kthread_should_stop() || lo->lo_bio) {
+diff -Nurb linux-2.6.22-590/drivers/block/pktcdvd.c linux-2.6.22-570/drivers/block/pktcdvd.c
+--- linux-2.6.22-590/drivers/block/pktcdvd.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/block/pktcdvd.c   2007-07-08 19:32:17.000000000 -0400
+@@ -146,7 +146,8 @@
+  **********************************************************/
  
- static void
--lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba,
--                    struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb)
-+lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                    struct lpfc_iocbq * rspiocb)
- {
--      struct lpfc_dmabuf *bmp = cmdiocb->context3;
-       struct lpfc_dmabuf *inp = cmdiocb->context1;
-       struct lpfc_dmabuf *outp = cmdiocb->context2;
-       struct lpfc_sli_ct_request *CTrsp = outp->virt;
-@@ -727,48 +1095,60 @@
-       struct lpfc_nodelist *ndlp;
-       uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
-       uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
-+      struct lpfc_vport *vport = cmdiocb->vport;
-+      IOCB_t *irsp = &rspiocb->iocb;
-+      uint32_t latt;
-+
-+      latt = lpfc_els_chk_latt(vport);
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
-+              "FDMI cmpl:       status:x%x/x%x latt:%d",
-+              irsp->ulpStatus, irsp->un.ulpWord[4], latt);
--      ndlp = lpfc_findnode_did(phba, FDMI_DID);
-+      if (latt || irsp->ulpStatus) {
-+              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                              "%d (%d):0229 FDMI cmd %04x failed, latt = %d "
-+                              "ulpStatus: x%x, rid x%x\n",
-+                              phba->brd_no, vport->vpi,
-+                              be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus,
-+                              irsp->un.ulpWord[4]);
-+              lpfc_ct_free_iocb(phba, cmdiocb);
-+              return;
-+      }
-+
-+      ndlp = lpfc_findnode_did(vport, FDMI_DID);
-       if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
-               /* FDMI rsp failed */
--              lpfc_printf_log(phba,
--                              KERN_INFO,
--                              LOG_DISCOVERY,
--                              "%d:0220 FDMI rsp failed Data: x%x\n",
--                              phba->brd_no,
-+              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                              "%d (%d):0220 FDMI rsp failed Data: x%x\n",
-+                              phba->brd_no, vport->vpi,
-                              be16_to_cpu(fdmi_cmd));
-       }
+ #define DEF_ATTR(_obj,_name,_mode) \
+-      static struct attribute _obj = { .name = _name, .mode = _mode }
++      static struct attribute _obj = { \
++              .name = _name, .owner = THIS_MODULE, .mode = _mode }
  
-       switch (be16_to_cpu(fdmi_cmd)) {
-       case SLI_MGMT_RHBA:
--              lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_RPA);
-+              lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA);
-               break;
+ /**********************************************************
+   /sys/class/pktcdvd/pktcdvd[0-7]/
+@@ -1593,7 +1594,6 @@
+       long min_sleep_time, residue;
  
-       case SLI_MGMT_RPA:
-               break;
+       set_user_nice(current, -20);
+-      set_freezable();
  
-       case SLI_MGMT_DHBA:
--              lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DPRT);
-+              lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT);
-               break;
+       for (;;) {
+               DECLARE_WAITQUEUE(wait, current);
+diff -Nurb linux-2.6.22-590/drivers/char/apm-emulation.c linux-2.6.22-570/drivers/char/apm-emulation.c
+--- linux-2.6.22-590/drivers/char/apm-emulation.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/char/apm-emulation.c      2007-07-08 19:32:17.000000000 -0400
+@@ -20,7 +20,6 @@
+ #include <linux/sched.h>
+ #include <linux/pm.h>
+ #include <linux/apm-emulation.h>
+-#include <linux/freezer.h>
+ #include <linux/device.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
+@@ -330,8 +329,13 @@
+                       /*
+                        * Wait for the suspend/resume to complete.  If there
+                        * are pending acknowledges, we wait here for them.
++                       *
++                       * Note: we need to ensure that the PM subsystem does
++                       * not kick us out of the wait when it suspends the
++                       * threads.
+                        */
+                       flags = current->flags;
++                      current->flags |= PF_NOFREEZE;
  
-       case SLI_MGMT_DPRT:
--              lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_RHBA);
-+              lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA);
-               break;
+                       wait_event(apm_suspend_waitqueue,
+                                  as->suspend_state == SUSPEND_DONE);
+@@ -361,8 +365,13 @@
+                       /*
+                        * Wait for the suspend/resume to complete.  If there
+                        * are pending acknowledges, we wait here for them.
++                       *
++                       * Note: we need to ensure that the PM subsystem does
++                       * not kick us out of the wait when it suspends the
++                       * threads.
+                        */
+                       flags = current->flags;
++                      current->flags |= PF_NOFREEZE;
+                       wait_event_interruptible(apm_suspend_waitqueue,
+                                        as->suspend_state == SUSPEND_DONE);
+@@ -589,6 +598,7 @@
+               kapmd_tsk = NULL;
+               return ret;
        }
--
--      lpfc_free_ct_rsp(phba, outp);
--      lpfc_mbuf_free(phba, inp->virt, inp->phys);
--      lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
--      kfree(inp);
--      kfree(bmp);
--      spin_lock_irq(phba->host->host_lock);
--      lpfc_sli_release_iocbq(phba, cmdiocb);
--      spin_unlock_irq(phba->host->host_lock);
-+      lpfc_ct_free_iocb(phba, cmdiocb);
-       return;
- }
-+
- int
--lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
-+lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode)
++      kapmd_tsk->flags |= PF_NOFREEZE;
+       wake_up_process(kapmd_tsk);
+ #ifdef CONFIG_PROC_FS
+diff -Nurb linux-2.6.22-590/drivers/char/hvc_console.c linux-2.6.22-570/drivers/char/hvc_console.c
+--- linux-2.6.22-590/drivers/char/hvc_console.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/char/hvc_console.c        2007-07-08 19:32:17.000000000 -0400
+@@ -674,12 +674,11 @@
+  * calling hvc_poll() who determines whether a console adapter support
+  * interrupts.
+  */
+-static int khvcd(void *unused)
++int khvcd(void *unused)
  {
-+      struct lpfc_hba *phba = vport->phba;
-       struct lpfc_dmabuf *mp, *bmp;
-       struct lpfc_sli_ct_request *CtReq;
-       struct ulp_bde64 *bpl;
-@@ -805,12 +1185,10 @@
-       INIT_LIST_HEAD(&bmp->list);
+       int poll_mask;
+       struct hvc_struct *hp;
  
-       /* FDMI request */
--      lpfc_printf_log(phba,
--                      KERN_INFO,
--                      LOG_DISCOVERY,
--                      "%d:0218 FDMI Request Data: x%x x%x x%x\n",
--                      phba->brd_no,
--                     phba->fc_flag, phba->hba_state, cmdcode);
-+      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                      "%d (%d):0218 FDMI Request Data: x%x x%x x%x\n",
-+                      phba->brd_no, vport->vpi, vport->fc_flag,
-+                      vport->port_state, cmdcode);
+-      set_freezable();
+       __set_current_state(TASK_RUNNING);
+       do {
+               poll_mask = 0;
+diff -Nurb linux-2.6.22-590/drivers/char/ipmi/ipmi_msghandler.c linux-2.6.22-570/drivers/char/ipmi/ipmi_msghandler.c
+--- linux-2.6.22-590/drivers/char/ipmi/ipmi_msghandler.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/char/ipmi/ipmi_msghandler.c       2007-07-08 19:32:17.000000000 -0400
+@@ -2171,42 +2171,52 @@
+       int err;
  
-       CtReq = (struct lpfc_sli_ct_request *) mp->virt;
+       bmc->device_id_attr.attr.name = "device_id";
++      bmc->device_id_attr.attr.owner = THIS_MODULE;
+       bmc->device_id_attr.attr.mode = S_IRUGO;
+       bmc->device_id_attr.show = device_id_show;
  
-@@ -833,11 +1211,11 @@
-                           be16_to_cpu(SLI_MGMT_RHBA);
-                       CtReq->CommandResponse.bits.Size = 0;
-                       rh = (REG_HBA *) & CtReq->un.PortID;
--                      memcpy(&rh->hi.PortName, &phba->fc_sparam.portName,
-+                      memcpy(&rh->hi.PortName, &vport->fc_sparam.portName,
-                              sizeof (struct lpfc_name));
-                       /* One entry (port) per adapter */
-                       rh->rpl.EntryCnt = be32_to_cpu(1);
--                      memcpy(&rh->rpl.pe, &phba->fc_sparam.portName,
-+                      memcpy(&rh->rpl.pe, &vport->fc_sparam.portName,
-                              sizeof (struct lpfc_name));
+       bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs";
++      bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE;
+       bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO;
+       bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show;
  
-                       /* point to the HBA attribute block */
-@@ -853,7 +1231,7 @@
-                       ae->ad.bits.AttrType = be16_to_cpu(NODE_NAME);
-                       ae->ad.bits.AttrLen =  be16_to_cpu(FOURBYTES
-                                               + sizeof (struct lpfc_name));
--                      memcpy(&ae->un.NodeName, &phba->fc_sparam.nodeName,
-+                      memcpy(&ae->un.NodeName, &vport->fc_sparam.nodeName,
-                              sizeof (struct lpfc_name));
-                       ab->EntryCnt++;
-                       size += FOURBYTES + sizeof (struct lpfc_name);
-@@ -991,7 +1369,7 @@
-                       pab = (REG_PORT_ATTRIBUTE *) & CtReq->un.PortID;
-                       size = sizeof (struct lpfc_name) + FOURBYTES;
-                       memcpy((uint8_t *) & pab->PortName,
--                             (uint8_t *) & phba->fc_sparam.portName,
-+                             (uint8_t *) & vport->fc_sparam.portName,
-                              sizeof (struct lpfc_name));
-                       pab->ab.EntryCnt = 0;
+       bmc->revision_attr.attr.name = "revision";
++      bmc->revision_attr.attr.owner = THIS_MODULE;
+       bmc->revision_attr.attr.mode = S_IRUGO;
+       bmc->revision_attr.show = revision_show;
  
-@@ -1053,7 +1431,7 @@
-                       ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size);
-                       ae->ad.bits.AttrType = be16_to_cpu(MAX_FRAME_SIZE);
-                       ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4);
--                      hsp = (struct serv_parm *) & phba->fc_sparam;
-+                      hsp = (struct serv_parm *) & vport->fc_sparam;
-                       ae->un.MaxFrameSize =
-                           (((uint32_t) hsp->cmn.
-                             bbRcvSizeMsb) << 8) | (uint32_t) hsp->cmn.
-@@ -1097,7 +1475,7 @@
-               CtReq->CommandResponse.bits.Size = 0;
-               pe = (PORT_ENTRY *) & CtReq->un.PortID;
-               memcpy((uint8_t *) & pe->PortName,
--                     (uint8_t *) & phba->fc_sparam.portName,
-+                     (uint8_t *) & vport->fc_sparam.portName,
-                      sizeof (struct lpfc_name));
-               size = GID_REQUEST_SZ - 4 + sizeof (struct lpfc_name);
-               break;
-@@ -1107,22 +1485,22 @@
-               CtReq->CommandResponse.bits.Size = 0;
-               pe = (PORT_ENTRY *) & CtReq->un.PortID;
-               memcpy((uint8_t *) & pe->PortName,
--                     (uint8_t *) & phba->fc_sparam.portName,
-+                     (uint8_t *) & vport->fc_sparam.portName,
-                      sizeof (struct lpfc_name));
-               size = GID_REQUEST_SZ - 4 + sizeof (struct lpfc_name);
-               break;
-       }
+       bmc->firmware_rev_attr.attr.name = "firmware_revision";
++      bmc->firmware_rev_attr.attr.owner = THIS_MODULE;
+       bmc->firmware_rev_attr.attr.mode = S_IRUGO;
+       bmc->firmware_rev_attr.show = firmware_rev_show;
+       bmc->version_attr.attr.name = "ipmi_version";
++      bmc->version_attr.attr.owner = THIS_MODULE;
+       bmc->version_attr.attr.mode = S_IRUGO;
+       bmc->version_attr.show = ipmi_version_show;
  
-       bpl = (struct ulp_bde64 *) bmp->virt;
--      bpl->addrHigh = le32_to_cpu( putPaddrHigh(mp->phys) );
--      bpl->addrLow = le32_to_cpu( putPaddrLow(mp->phys) );
-+      bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
-+      bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
-       bpl->tus.f.bdeFlags = 0;
-       bpl->tus.f.bdeSize = size;
-       bpl->tus.w = le32_to_cpu(bpl->tus.w);
+       bmc->add_dev_support_attr.attr.name = "additional_device_support";
++      bmc->add_dev_support_attr.attr.owner = THIS_MODULE;
+       bmc->add_dev_support_attr.attr.mode = S_IRUGO;
+       bmc->add_dev_support_attr.show = add_dev_support_show;
  
-       cmpl = lpfc_cmpl_ct_cmd_fdmi;
+       bmc->manufacturer_id_attr.attr.name = "manufacturer_id";
++      bmc->manufacturer_id_attr.attr.owner = THIS_MODULE;
+       bmc->manufacturer_id_attr.attr.mode = S_IRUGO;
+       bmc->manufacturer_id_attr.show = manufacturer_id_show;
  
--      if (!lpfc_ct_cmd(phba, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP))
-+      if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0))
-               return 0;
+       bmc->product_id_attr.attr.name = "product_id";
++      bmc->product_id_attr.attr.owner = THIS_MODULE;
+       bmc->product_id_attr.attr.mode = S_IRUGO;
+       bmc->product_id_attr.show = product_id_show;
  
-       lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
-@@ -1134,49 +1512,50 @@
-       kfree(mp);
- fdmi_cmd_exit:
-       /* Issue FDMI request failed */
--      lpfc_printf_log(phba,
--                      KERN_INFO,
--                      LOG_DISCOVERY,
--                      "%d:0244 Issue FDMI request failed Data: x%x\n",
--                      phba->brd_no,
--                      cmdcode);
-+      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                      "%d (%d):0244 Issue FDMI request failed Data: x%x\n",
-+                      phba->brd_no, vport->vpi, cmdcode);
-       return 1;
- }
+       bmc->guid_attr.attr.name = "guid";
++      bmc->guid_attr.attr.owner = THIS_MODULE;
+       bmc->guid_attr.attr.mode = S_IRUGO;
+       bmc->guid_attr.show = guid_show;
  
- void
- lpfc_fdmi_tmo(unsigned long ptr)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
-+      struct lpfc_vport *vport = (struct lpfc_vport *)ptr;
-+      struct lpfc_hba   *phba = vport->phba;
-       unsigned long iflag;
+       bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision";
++      bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE;
+       bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO;
+       bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show;
  
--      spin_lock_irqsave(phba->host->host_lock, iflag);
--      if (!(phba->work_hba_events & WORKER_FDMI_TMO)) {
--              phba->work_hba_events |= WORKER_FDMI_TMO;
-+      spin_lock_irqsave(&vport->work_port_lock, iflag);
-+      if (!(vport->work_port_events & WORKER_FDMI_TMO)) {
-+              vport->work_port_events |= WORKER_FDMI_TMO;
-+              spin_unlock_irqrestore(&vport->work_port_lock, iflag);
-+
-+              spin_lock_irqsave(&phba->hbalock, iflag);
-               if (phba->work_wait)
--                      wake_up(phba->work_wait);
-+                      lpfc_worker_wake_up(phba);
-+              spin_unlock_irqrestore(&phba->hbalock, iflag);
+diff -Nurb linux-2.6.22-590/drivers/char/keyboard.c linux-2.6.22-570/drivers/char/keyboard.c
+--- linux-2.6.22-590/drivers/char/keyboard.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/char/keyboard.c   2007-07-08 19:32:17.000000000 -0400
+@@ -1150,7 +1150,6 @@
+               sysrq_down = 0;
+       if (sysrq_down && down && !rep) {
+               handle_sysrq(kbd_sysrq_xlate[keycode], tty);
+-              sysrq_down = 0;         /* In case we miss the 'up' event. */
+               return;
        }
--      spin_unlock_irqrestore(phba->host->host_lock,iflag);
-+      else
-+              spin_unlock_irqrestore(&vport->work_port_lock, iflag);
- }
+ #endif
+diff -Nurb linux-2.6.22-590/drivers/connector/connector.c linux-2.6.22-570/drivers/connector/connector.c
+--- linux-2.6.22-590/drivers/connector/connector.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/connector/connector.c     2007-07-08 19:32:17.000000000 -0400
+@@ -446,7 +446,7 @@
+       dev->id.idx = cn_idx;
+       dev->id.val = cn_val;
  
- void
--lpfc_fdmi_tmo_handler(struct lpfc_hba *phba)
-+lpfc_fdmi_timeout_handler(struct lpfc_vport *vport)
- {
-       struct lpfc_nodelist *ndlp;
+-      dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR,
++      dev->nls = netlink_kernel_create(NETLINK_CONNECTOR,
+                                        CN_NETLINK_USERS + 0xf,
+                                        dev->input, NULL, THIS_MODULE);
+       if (!dev->nls)
+diff -Nurb linux-2.6.22-590/drivers/cpufreq/cpufreq_stats.c linux-2.6.22-570/drivers/cpufreq/cpufreq_stats.c
+--- linux-2.6.22-590/drivers/cpufreq/cpufreq_stats.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpufreq/cpufreq_stats.c   2007-07-08 19:32:17.000000000 -0400
+@@ -25,7 +25,8 @@
  
--      ndlp = lpfc_findnode_did(phba, FDMI_DID);
-+      ndlp = lpfc_findnode_did(vport, FDMI_DID);
-       if (ndlp) {
--              if (init_utsname()->nodename[0] != '\0') {
--                      lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA);
--              } else {
--                      mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60);
+ #define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \
+ static struct freq_attr _attr_##_name = {\
+-      .attr = {.name = __stringify(_name), .mode = _mode, }, \
++      .attr = {.name = __stringify(_name), .owner = THIS_MODULE, \
++              .mode = _mode, }, \
+       .show = _show,\
+ };
+diff -Nurb linux-2.6.22-590/drivers/cpufreq/cpufreq_userspace.c linux-2.6.22-570/drivers/cpufreq/cpufreq_userspace.c
+--- linux-2.6.22-590/drivers/cpufreq/cpufreq_userspace.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpufreq/cpufreq_userspace.c       2007-07-08 19:32:17.000000000 -0400
+@@ -120,7 +120,7 @@
+ static struct freq_attr freq_attr_scaling_setspeed =
+ {
+-      .attr = { .name = "scaling_setspeed", .mode = 0644 },
++      .attr = { .name = "scaling_setspeed", .mode = 0644, .owner = THIS_MODULE },
+       .show = show_speed,
+       .store = store_speed,
+ };
+diff -Nurb linux-2.6.22-590/drivers/cpufreq/freq_table.c linux-2.6.22-570/drivers/cpufreq/freq_table.c
+--- linux-2.6.22-590/drivers/cpufreq/freq_table.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpufreq/freq_table.c      2007-07-08 19:32:17.000000000 -0400
+@@ -199,6 +199,7 @@
+ struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
+       .attr = { .name = "scaling_available_frequencies",
+                 .mode = 0444,
++                .owner=THIS_MODULE
+               },
+       .show = show_available_freqs,
+ };
+diff -Nurb linux-2.6.22-590/drivers/cpuidle/Kconfig linux-2.6.22-570/drivers/cpuidle/Kconfig
+--- linux-2.6.22-590/drivers/cpuidle/Kconfig   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpuidle/Kconfig   1969-12-31 19:00:00.000000000 -0500
+@@ -1,39 +0,0 @@
+-menu "CPU idle PM support"
+-
+-config CPU_IDLE
+-      bool "CPU idle PM support"
+-      help
+-        CPU idle is a generic framework for supporting software-controlled
+-        idle processor power management.  It includes modular cross-platform
+-        governors that can be swapped during runtime.
+-
+-        If you're using a mobile platform that supports CPU idle PM (e.g.
+-        an ACPI-capable notebook), you should say Y here.
+-
+-if CPU_IDLE
+-
+-comment "Governors"
+-
+-config CPU_IDLE_GOV_LADDER
+-      tristate "'ladder' governor"
+-      depends on CPU_IDLE
+-      default y
+-      help
+-        This cpuidle governor promotes and demotes through the supported idle
+-        states using residency time and bus master activity as metrics.  This
+-        algorithm was originally introduced in the old ACPI processor driver.
+-
+-config CPU_IDLE_GOV_MENU
+-      tristate "'menu' governor"
+-      depends on CPU_IDLE && NO_HZ
+-      default y
+-      help
+-        This cpuidle governor evaluates all available states and chooses the
+-        deepest state that meets all of the following constraints: BM activity,
+-        expected time until next timer interrupt, and last break event time
+-        delta.  It is designed to minimize power consumption.  Currently
+-        dynticks is required.
+-
+-endif # CPU_IDLE
+-
+-endmenu
+diff -Nurb linux-2.6.22-590/drivers/cpuidle/Makefile linux-2.6.22-570/drivers/cpuidle/Makefile
+--- linux-2.6.22-590/drivers/cpuidle/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpuidle/Makefile  1969-12-31 19:00:00.000000000 -0500
+@@ -1,5 +0,0 @@
+-#
+-# Makefile for cpuidle.
+-#
+-
+-obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
+diff -Nurb linux-2.6.22-590/drivers/cpuidle/cpuidle.c linux-2.6.22-570/drivers/cpuidle/cpuidle.c
+--- linux-2.6.22-590/drivers/cpuidle/cpuidle.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpuidle/cpuidle.c 1969-12-31 19:00:00.000000000 -0500
+@@ -1,306 +0,0 @@
+-/*
+- * cpuidle.c - core cpuidle infrastructure
+- *
+- * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+- *               Shaohua Li <shaohua.li@intel.com>
+- *               Adam Belay <abelay@novell.com>
+- *
+- * This code is licenced under the GPL.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/mutex.h>
+-#include <linux/sched.h>
+-#include <linux/notifier.h>
+-#include <linux/cpu.h>
+-#include <linux/latency.h>
+-#include <linux/cpuidle.h>
+-
+-#include "cpuidle.h"
+-
+-DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+-EXPORT_PER_CPU_SYMBOL_GPL(cpuidle_devices);
+-
+-DEFINE_MUTEX(cpuidle_lock);
+-LIST_HEAD(cpuidle_detected_devices);
+-static void (*pm_idle_old)(void);
+-
+-/**
+- * cpuidle_idle_call - the main idle loop
+- *
+- * NOTE: no locks or semaphores should be used here
+- */
+-static void cpuidle_idle_call(void)
+-{
+-      struct cpuidle_device *dev = __get_cpu_var(cpuidle_devices);
+-      struct cpuidle_state *target_state;
+-      int next_state;
+-
+-      /* check if the device is ready */
+-      if (!dev || dev->status != CPUIDLE_STATUS_DOIDLE) {
+-              if (pm_idle_old)
+-                      pm_idle_old();
+-              else
+-                      local_irq_enable();
+-              return;
+-      }
+-
+-      /* ask the governor for the next state */
+-      next_state = cpuidle_curr_governor->select(dev);
+-      if (need_resched())
+-              return;
+-      target_state = &dev->states[next_state];
+-
+-      /* enter the state and update stats */
+-      dev->last_residency = target_state->enter(dev, target_state);
+-      dev->last_state = target_state;
+-      target_state->time += dev->last_residency;
+-      target_state->usage++;
+-
+-      /* give the governor an opportunity to reflect on the outcome */
+-      if (cpuidle_curr_governor->reflect)
+-              cpuidle_curr_governor->reflect(dev);
+-}
+-
+-/**
+- * cpuidle_install_idle_handler - installs the cpuidle idle loop handler
+- */
+-void cpuidle_install_idle_handler(void)
+-{
+-      if (pm_idle != cpuidle_idle_call) {
+-              /* Make sure all changes finished before we switch to new idle */
+-              smp_wmb();
+-              pm_idle = cpuidle_idle_call;
+-      }
+-}
+-
+-/**
+- * cpuidle_uninstall_idle_handler - uninstalls the cpuidle idle loop handler
+- */
+-void cpuidle_uninstall_idle_handler(void)
+-{
+-      if (pm_idle != pm_idle_old) {
+-              pm_idle = pm_idle_old;
+-              cpu_idle_wait();
+-      }
+-}
+-
+-/**
+- * cpuidle_rescan_device - prepares for a new state configuration
+- * @dev: the target device
+- *
+- * Must be called with cpuidle_lock aquired.
+- */
+-void cpuidle_rescan_device(struct cpuidle_device *dev)
+-{
+-      int i;
+-
+-      if (cpuidle_curr_governor->scan)
+-              cpuidle_curr_governor->scan(dev);
+-
+-      for (i = 0; i < dev->state_count; i++) {
+-              dev->states[i].usage = 0;
+-              dev->states[i].time = 0;
+-      }
+-}
+-
+-/**
+- * cpuidle_add_device - attaches the driver to a CPU instance
+- * @sys_dev: the system device (driver model CPU representation)
+- */
+-static int cpuidle_add_device(struct sys_device *sys_dev)
+-{
+-      int cpu = sys_dev->id;
+-      struct cpuidle_device *dev;
+-
+-      dev = per_cpu(cpuidle_devices, cpu);
+-
+-      mutex_lock(&cpuidle_lock);
+-      if (cpu_is_offline(cpu)) {
+-              mutex_unlock(&cpuidle_lock);
+-              return 0;
+-      }
+-
+-      if (!dev) {
+-              dev = kzalloc(sizeof(struct cpuidle_device), GFP_KERNEL);
+-              if (!dev) {
+-                      mutex_unlock(&cpuidle_lock);
+-                      return -ENOMEM;
+-              }
+-              init_completion(&dev->kobj_unregister);
+-              per_cpu(cpuidle_devices, cpu) = dev;
+-      }
+-      dev->cpu = cpu;
+-
+-      if (dev->status & CPUIDLE_STATUS_DETECTED) {
+-              mutex_unlock(&cpuidle_lock);
+-              return 0;
+-      }
+-
+-      cpuidle_add_sysfs(sys_dev);
+-
+-      if (cpuidle_curr_driver) {
+-              if (cpuidle_attach_driver(dev))
+-                      goto err_ret;
+-      }
+-
+-      if (cpuidle_curr_governor) {
+-              if (cpuidle_attach_governor(dev)) {
+-                      cpuidle_detach_driver(dev);
+-                      goto err_ret;
+-              }
+-      }
+-
+-      if (cpuidle_device_can_idle(dev))
+-              cpuidle_install_idle_handler();
+-
+-      list_add(&dev->device_list, &cpuidle_detected_devices);
+-      dev->status |= CPUIDLE_STATUS_DETECTED;
+-
+-err_ret:
+-      mutex_unlock(&cpuidle_lock);
+-
+-      return 0;
+-}
+-
+-/**
+- * __cpuidle_remove_device - detaches the driver from a CPU instance
+- * @sys_dev: the system device (driver model CPU representation)
+- *
+- * Must be called with cpuidle_lock aquired.
+- */
+-static int __cpuidle_remove_device(struct sys_device *sys_dev)
+-{
+-      struct cpuidle_device *dev;
+-
+-      dev = per_cpu(cpuidle_devices, sys_dev->id);
+-
+-      if (!(dev->status & CPUIDLE_STATUS_DETECTED)) {
+-              return 0;
+-      }
+-      dev->status &= ~CPUIDLE_STATUS_DETECTED;
+-      /* NOTE: we don't wait because the cpu is already offline */
+-      if (cpuidle_curr_governor)
+-              cpuidle_detach_governor(dev);
+-      if (cpuidle_curr_driver)
+-              cpuidle_detach_driver(dev);
+-      cpuidle_remove_sysfs(sys_dev);
+-      list_del(&dev->device_list);
+-      wait_for_completion(&dev->kobj_unregister);
+-      per_cpu(cpuidle_devices, sys_dev->id) = NULL;
+-      kfree(dev);
+-
+-      return 0;
+-}
+-
+-/**
+- * cpuidle_remove_device - detaches the driver from a CPU instance
+- * @sys_dev: the system device (driver model CPU representation)
+- */
+-static int cpuidle_remove_device(struct sys_device *sys_dev)
+-{
+-      int ret;
+-      mutex_lock(&cpuidle_lock);
+-      ret = __cpuidle_remove_device(sys_dev);
+-      mutex_unlock(&cpuidle_lock);
+-
+-      return ret;
+-}
+-
+-static struct sysdev_driver cpuidle_sysdev_driver = {
+-      .add            = cpuidle_add_device,
+-      .remove         = cpuidle_remove_device,
+-};
+-
+-static int cpuidle_cpu_callback(struct notifier_block *nfb,
+-                                      unsigned long action, void *hcpu)
+-{
+-      struct sys_device *sys_dev;
+-
+-      sys_dev = get_cpu_sysdev((unsigned long)hcpu);
+-
+-      switch (action) {
+-      case CPU_ONLINE:
+-              cpuidle_add_device(sys_dev);
+-              break;
+-      case CPU_DOWN_PREPARE:
+-              mutex_lock(&cpuidle_lock);
+-              break;
+-      case CPU_DEAD:
+-              __cpuidle_remove_device(sys_dev);
+-              mutex_unlock(&cpuidle_lock);
+-              break;
+-      case CPU_DOWN_FAILED:
+-              mutex_unlock(&cpuidle_lock);
+-              break;
+-      }
+-
+-      return NOTIFY_OK;
+-}
+-
+-static struct notifier_block __cpuinitdata cpuidle_cpu_notifier =
+-{
+-    .notifier_call = cpuidle_cpu_callback,
+-};
+-
+-#ifdef CONFIG_SMP
+-
+-static void smp_callback(void *v)
+-{
+-      /* we already woke the CPU up, nothing more to do */
+-}
+-
+-/*
+- * This function gets called when a part of the kernel has a new latency
+- * requirement.  This means we need to get all processors out of their C-state,
+- * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that
+- * wakes them all right up.
+- */
+-static int cpuidle_latency_notify(struct notifier_block *b,
+-              unsigned long l, void *v)
+-{
+-      smp_call_function(smp_callback, NULL, 0, 1);
+-      return NOTIFY_OK;
+-}
+-
+-static struct notifier_block cpuidle_latency_notifier = {
+-      .notifier_call = cpuidle_latency_notify,
+-};
+-
+-#define latency_notifier_init(x) do { register_latency_notifier(x); } while (0)
+-
+-#else /* CONFIG_SMP */
+-
+-#define latency_notifier_init(x) do { } while (0)
+-
+-#endif /* CONFIG_SMP */
+-
+-/**
+- * cpuidle_init - core initializer
+- */
+-static int __init cpuidle_init(void)
+-{
+-      int ret;
+-
+-      pm_idle_old = pm_idle;
+-
+-      ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);
+-      if (ret)
+-              return ret;
+-
+-      register_hotcpu_notifier(&cpuidle_cpu_notifier);
+-
+-      ret = sysdev_driver_register(&cpu_sysdev_class, &cpuidle_sysdev_driver);
+-
+-      if (ret) {
+-              cpuidle_remove_class_sysfs(&cpu_sysdev_class);
+-              printk(KERN_ERR "cpuidle: failed to initialize\n");
+-              return ret;
+-      }
+-
+-      latency_notifier_init(&cpuidle_latency_notifier);
+-
+-      return 0;
+-}
+-
+-core_initcall(cpuidle_init);
+diff -Nurb linux-2.6.22-590/drivers/cpuidle/cpuidle.h linux-2.6.22-570/drivers/cpuidle/cpuidle.h
+--- linux-2.6.22-590/drivers/cpuidle/cpuidle.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpuidle/cpuidle.h 1969-12-31 19:00:00.000000000 -0500
+@@ -1,50 +0,0 @@
+-/*
+- * cpuidle.h - The internal header file
+- */
+-
+-#ifndef __DRIVER_CPUIDLE_H
+-#define __DRIVER_CPUIDLE_H
+-
+-#include <linux/sysdev.h>
+-
+-/* For internal use only */
+-extern struct cpuidle_governor *cpuidle_curr_governor;
+-extern struct cpuidle_driver *cpuidle_curr_driver;
+-extern struct list_head cpuidle_drivers;
+-extern struct list_head cpuidle_governors;
+-extern struct list_head cpuidle_detected_devices;
+-extern struct mutex cpuidle_lock;
+-
+-/* idle loop */
+-extern void cpuidle_install_idle_handler(void);
+-extern void cpuidle_uninstall_idle_handler(void);
+-extern void cpuidle_rescan_device(struct cpuidle_device *dev);
+-
+-/* drivers */
+-extern int cpuidle_attach_driver(struct cpuidle_device *dev);
+-extern void cpuidle_detach_driver(struct cpuidle_device *dev);
+-extern int cpuidle_switch_driver(struct cpuidle_driver *drv);
+-
+-/* governors */
+-extern int cpuidle_attach_governor(struct cpuidle_device *dev);
+-extern void cpuidle_detach_governor(struct cpuidle_device *dev);
+-extern int cpuidle_switch_governor(struct cpuidle_governor *gov);
+-
+-/* sysfs */
+-extern int cpuidle_add_class_sysfs(struct sysdev_class *cls);
+-extern void cpuidle_remove_class_sysfs(struct sysdev_class *cls);
+-extern int cpuidle_add_driver_sysfs(struct cpuidle_device *device);
+-extern void cpuidle_remove_driver_sysfs(struct cpuidle_device *device);
+-extern int cpuidle_add_sysfs(struct sys_device *sysdev);
+-extern void cpuidle_remove_sysfs(struct sys_device *sysdev);
+-
+-/**
+- * cpuidle_device_can_idle - determines if a CPU can utilize the idle loop
+- * @dev: the target CPU
+- */
+-static inline int cpuidle_device_can_idle(struct cpuidle_device *dev)
+-{
+-      return (dev->status == CPUIDLE_STATUS_DOIDLE);
+-}
+-
+-#endif /* __DRIVER_CPUIDLE_H */
+diff -Nurb linux-2.6.22-590/drivers/cpuidle/driver.c linux-2.6.22-570/drivers/cpuidle/driver.c
+--- linux-2.6.22-590/drivers/cpuidle/driver.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpuidle/driver.c  1969-12-31 19:00:00.000000000 -0500
+@@ -1,276 +0,0 @@
+-/*
+- * driver.c - driver support
+- *
+- * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+- *               Shaohua Li <shaohua.li@intel.com>
+- *               Adam Belay <abelay@novell.com>
+- *
+- * This code is licenced under the GPL.
+- */
+-
+-#include <linux/mutex.h>
+-#include <linux/module.h>
+-#include <linux/cpuidle.h>
+-
+-#include "cpuidle.h"
+-
+-LIST_HEAD(cpuidle_drivers);
+-struct cpuidle_driver *cpuidle_curr_driver;
+-
+-
+-/**
+- * cpuidle_attach_driver - attaches a driver to a CPU
+- * @dev: the target CPU
+- *
+- * Must be called with cpuidle_lock aquired.
+- */
+-int cpuidle_attach_driver(struct cpuidle_device *dev)
+-{
+-      int ret;
+-
+-      if (dev->status & CPUIDLE_STATUS_DRIVER_ATTACHED)
+-              return -EIO;
+-
+-      if (!try_module_get(cpuidle_curr_driver->owner))
+-              return -EINVAL;
+-
+-      ret = cpuidle_curr_driver->init(dev);
+-      if (ret) {
+-              module_put(cpuidle_curr_driver->owner);
+-              printk(KERN_INFO "cpuidle: driver %s failed to attach to "
+-                      "cpu %d\n", cpuidle_curr_driver->name, dev->cpu);
+-      } else {
+-              if (dev->status & CPUIDLE_STATUS_GOVERNOR_ATTACHED)
+-                      cpuidle_rescan_device(dev);
+-              smp_wmb();
+-              dev->status |= CPUIDLE_STATUS_DRIVER_ATTACHED;
+-              cpuidle_add_driver_sysfs(dev);
+-      }
+-
+-      return ret;
+-}
+-
+-/**
+- * cpuidle_detach_govenor - detaches a driver from a CPU
+- * @dev: the target CPU
+- *
+- * Must be called with cpuidle_lock aquired.
+- */
+-void cpuidle_detach_driver(struct cpuidle_device *dev)
+-{
+-      if (dev->status & CPUIDLE_STATUS_DRIVER_ATTACHED) {
+-              cpuidle_remove_driver_sysfs(dev);
+-              dev->status &= ~CPUIDLE_STATUS_DRIVER_ATTACHED;
+-              if (cpuidle_curr_driver->exit)
+-                      cpuidle_curr_driver->exit(dev);
+-              module_put(cpuidle_curr_driver->owner);
+-      }
+-}
+-
+-/**
+- * __cpuidle_find_driver - finds a driver of the specified name
+- * @str: the name
+- *
+- * Must be called with cpuidle_lock aquired.
+- */
+-static struct cpuidle_driver * __cpuidle_find_driver(const char *str)
+-{
+-      struct cpuidle_driver *drv;
+-
+-      list_for_each_entry(drv, &cpuidle_drivers, driver_list)
+-              if (!strnicmp(str, drv->name, CPUIDLE_NAME_LEN))
+-                      return drv;
+-
+-      return NULL;
+-}
+-
+-/**
+- * cpuidle_switch_driver - changes the driver
+- * @drv: the new target driver
+- *
+- * NOTE: "drv" can be NULL to specify disabled
+- * Must be called with cpuidle_lock aquired.
+- */
+-int cpuidle_switch_driver(struct cpuidle_driver *drv)
+-{
+-      struct cpuidle_device *dev;
+-
+-      if (drv == cpuidle_curr_driver)
+-              return -EINVAL;
+-
+-      cpuidle_uninstall_idle_handler();
+-
+-      if (cpuidle_curr_driver)
+-              list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
+-                      cpuidle_detach_driver(dev);
+-
+-      cpuidle_curr_driver = drv;
+-
+-      if (drv) {
+-              int ret = 1;
+-              list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
+-                      if (cpuidle_attach_driver(dev) == 0)
+-                              ret = 0;
+-
+-              /* If attach on all devices fail, switch to NULL driver */
+-              if (ret)
+-                      cpuidle_curr_driver = NULL;
+-
+-              if (cpuidle_curr_driver && cpuidle_curr_governor) {
+-                      printk(KERN_INFO "cpuidle: using driver %s\n",
+-                                      drv->name);
+-                      cpuidle_install_idle_handler();
+-              }
+-      }
+-
+-      return 0;
+-}
+-
+-/**
+- * cpuidle_register_driver - registers a driver
+- * @drv: the driver
+- */
+-int cpuidle_register_driver(struct cpuidle_driver *drv)
+-{
+-      int ret = -EEXIST;
+-
+-      if (!drv || !drv->init)
+-              return -EINVAL;
+-
+-      mutex_lock(&cpuidle_lock);
+-      if (__cpuidle_find_driver(drv->name) == NULL) {
+-              ret = 0;
+-              list_add_tail(&drv->driver_list, &cpuidle_drivers);
+-              if (!cpuidle_curr_driver)
+-                      cpuidle_switch_driver(drv);
+-      }
+-      mutex_unlock(&cpuidle_lock);
+-
+-      return ret;
+-}
+-
+-EXPORT_SYMBOL_GPL(cpuidle_register_driver);
+-
+-/**
+- * cpuidle_unregister_driver - unregisters a driver
+- * @drv: the driver
+- */
+-void cpuidle_unregister_driver(struct cpuidle_driver *drv)
+-{
+-      if (!drv)
+-              return;
+-
+-      mutex_lock(&cpuidle_lock);
+-      if (drv == cpuidle_curr_driver)
+-              cpuidle_switch_driver(NULL);
+-      list_del(&drv->driver_list);
+-      mutex_unlock(&cpuidle_lock);
+-}
+-
+-EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+-
+-static void __cpuidle_force_redetect(struct cpuidle_device *dev)
+-{
+-      cpuidle_remove_driver_sysfs(dev);
+-      cpuidle_curr_driver->redetect(dev);
+-      cpuidle_add_driver_sysfs(dev);
+-}
+-
+-/**
+- * cpuidle_force_redetect - redetects the idle states of a CPU
+- *
+- * @dev: the CPU to redetect
+- * @drv: the target driver
+- *
+- * Generally, the driver will call this when the supported states set has
+- * changed. (e.g. as the result of an ACPI transition to battery power)
+- */
+-int cpuidle_force_redetect(struct cpuidle_device *dev,
+-              struct cpuidle_driver *drv)
+-{
+-      int uninstalled = 0;
+-
+-      mutex_lock(&cpuidle_lock);
+-
+-      if (drv != cpuidle_curr_driver) {
+-              mutex_unlock(&cpuidle_lock);
+-              return 0;
+-      }
+-
+-      if (!(dev->status & CPUIDLE_STATUS_DRIVER_ATTACHED) ||
+-          !cpuidle_curr_driver->redetect) {
+-              mutex_unlock(&cpuidle_lock);
+-              return -EIO;
+-      }
+-
+-      if (cpuidle_device_can_idle(dev)) {
+-              uninstalled = 1;
+-              cpuidle_uninstall_idle_handler();
+-      }
+-
+-      __cpuidle_force_redetect(dev);
+-
+-      if (cpuidle_device_can_idle(dev)) {
+-              cpuidle_rescan_device(dev);
+-              cpuidle_install_idle_handler();
+-      }
+-
+-      /* other devices are still ok */
+-      if (uninstalled)
+-              cpuidle_install_idle_handler();
+-
+-      mutex_unlock(&cpuidle_lock);
+-
+-      return 0;
+-}
+-
+-EXPORT_SYMBOL_GPL(cpuidle_force_redetect);
+-
+-/**
+- * cpuidle_force_redetect_devices - redetects the idle states of all CPUs
+- *
+- * @drv: the target driver
+- *
+- * Generally, the driver will call this when the supported states set has
+- * changed. (e.g. as the result of an ACPI transition to battery power)
+- */
+-int cpuidle_force_redetect_devices(struct cpuidle_driver *drv)
+-{
+-      struct cpuidle_device *dev;
+-      int ret = 0;
+-
+-      mutex_lock(&cpuidle_lock);
+-
+-      if (drv != cpuidle_curr_driver)
+-              goto out;
+-
+-      if (!cpuidle_curr_driver->redetect) {
+-              ret = -EIO;
+-              goto out;
+-      }
+-
+-      cpuidle_uninstall_idle_handler();
+-
+-      list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
+-              __cpuidle_force_redetect(dev);
+-
+-      cpuidle_install_idle_handler();
+-out:
+-      mutex_unlock(&cpuidle_lock);
+-      return ret;
+-}
+-
+-EXPORT_SYMBOL_GPL(cpuidle_force_redetect_devices);
+-
+-/**
+- * cpuidle_get_bm_activity - determines if BM activity has occured
+- */
+-int cpuidle_get_bm_activity(void)
+-{
+-      if (cpuidle_curr_driver->bm_check)
+-              return cpuidle_curr_driver->bm_check();
+-      else
+-              return 0;
+-}
+-EXPORT_SYMBOL_GPL(cpuidle_get_bm_activity);
+-
+diff -Nurb linux-2.6.22-590/drivers/cpuidle/governor.c linux-2.6.22-570/drivers/cpuidle/governor.c
+--- linux-2.6.22-590/drivers/cpuidle/governor.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpuidle/governor.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,160 +0,0 @@
+-/*
+- * governor.c - governor support
+- *
+- * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+- *               Shaohua Li <shaohua.li@intel.com>
+- *               Adam Belay <abelay@novell.com>
+- *
+- * This code is licenced under the GPL.
+- */
+-
+-#include <linux/mutex.h>
+-#include <linux/module.h>
+-#include <linux/cpuidle.h>
+-
+-#include "cpuidle.h"
+-
+-LIST_HEAD(cpuidle_governors);
+-struct cpuidle_governor *cpuidle_curr_governor;
+-
+-
+-/**
+- * cpuidle_attach_governor - attaches a governor to a CPU
+- * @dev: the target CPU
+- *
+- * Must be called with cpuidle_lock aquired.
+- */
+-int cpuidle_attach_governor(struct cpuidle_device *dev)
+-{
+-      int ret = 0;
+-
+-      if(dev->status & CPUIDLE_STATUS_GOVERNOR_ATTACHED)
+-              return -EIO;
+-
+-      if (!try_module_get(cpuidle_curr_governor->owner))
+-              return -EINVAL;
+-
+-      if (cpuidle_curr_governor->init)
+-              ret = cpuidle_curr_governor->init(dev);
+-      if (ret) {
+-              module_put(cpuidle_curr_governor->owner);
+-              printk(KERN_ERR "cpuidle: governor %s failed to attach to cpu %d\n",
+-                      cpuidle_curr_governor->name, dev->cpu);
+-      } else {
+-              if (dev->status & CPUIDLE_STATUS_DRIVER_ATTACHED)
+-                      cpuidle_rescan_device(dev);
+-              smp_wmb();
+-              dev->status |= CPUIDLE_STATUS_GOVERNOR_ATTACHED;
+-      }
+-
+-      return ret;
+-}
+-
+-/**
+- * cpuidle_detach_govenor - detaches a governor from a CPU
+- * @dev: the target CPU
+- *
+- * Must be called with cpuidle_lock aquired.
+- */
+-void cpuidle_detach_governor(struct cpuidle_device *dev)
+-{
+-      if (dev->status & CPUIDLE_STATUS_GOVERNOR_ATTACHED) {
+-              dev->status &= ~CPUIDLE_STATUS_GOVERNOR_ATTACHED;
+-              if (cpuidle_curr_governor->exit)
+-                      cpuidle_curr_governor->exit(dev);
+-              module_put(cpuidle_curr_governor->owner);
+-      }
+-}
+-
+-/**
+- * __cpuidle_find_governor - finds a governor of the specified name
+- * @str: the name
+- *
+- * Must be called with cpuidle_lock aquired.
+- */
+-static struct cpuidle_governor * __cpuidle_find_governor(const char *str)
+-{
+-      struct cpuidle_governor *gov;
+-
+-      list_for_each_entry(gov, &cpuidle_governors, governor_list)
+-              if (!strnicmp(str, gov->name, CPUIDLE_NAME_LEN))
+-                      return gov;
+-
+-      return NULL;
+-}
+-
+-/**
+- * cpuidle_switch_governor - changes the governor
+- * @gov: the new target governor
+- *
+- * NOTE: "gov" can be NULL to specify disabled
+- * Must be called with cpuidle_lock aquired.
+- */
+-int cpuidle_switch_governor(struct cpuidle_governor *gov)
+-{
+-      struct cpuidle_device *dev;
+-
+-      if (gov == cpuidle_curr_governor)
+-              return -EINVAL;
+-
+-      cpuidle_uninstall_idle_handler();
+-
+-      if (cpuidle_curr_governor)
+-              list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
+-                      cpuidle_detach_governor(dev);
+-
+-      cpuidle_curr_governor = gov;
+-
+-      if (gov) {
+-              list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
+-                      cpuidle_attach_governor(dev);
+-              if (cpuidle_curr_driver)
+-                      cpuidle_install_idle_handler();
+-              printk(KERN_INFO "cpuidle: using governor %s\n", gov->name);
+-      }
+-
+-      return 0;
+-}
+-
+-/**
+- * cpuidle_register_governor - registers a governor
+- * @gov: the governor
+- */
+-int cpuidle_register_governor(struct cpuidle_governor *gov)
+-{
+-      int ret = -EEXIST;
+-
+-      if (!gov || !gov->select)
+-              return -EINVAL;
+-
+-      mutex_lock(&cpuidle_lock);
+-      if (__cpuidle_find_governor(gov->name) == NULL) {
+-              ret = 0;
+-              list_add_tail(&gov->governor_list, &cpuidle_governors);
+-              if (!cpuidle_curr_governor)
+-                      cpuidle_switch_governor(gov);
+-      }
+-      mutex_unlock(&cpuidle_lock);
+-
+-      return ret;
+-}
+-
+-EXPORT_SYMBOL_GPL(cpuidle_register_governor);
+-
+-/**
+- * cpuidle_unregister_governor - unregisters a governor
+- * @gov: the governor
+- */
+-void cpuidle_unregister_governor(struct cpuidle_governor *gov)
+-{
+-      if (!gov)
+-              return;
+-
+-      mutex_lock(&cpuidle_lock);
+-      if (gov == cpuidle_curr_governor)
+-              cpuidle_switch_governor(NULL);
+-      list_del(&gov->governor_list);
+-      mutex_unlock(&cpuidle_lock);
+-}
+-
+-EXPORT_SYMBOL_GPL(cpuidle_unregister_governor);
+diff -Nurb linux-2.6.22-590/drivers/cpuidle/governors/Makefile linux-2.6.22-570/drivers/cpuidle/governors/Makefile
+--- linux-2.6.22-590/drivers/cpuidle/governors/Makefile        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpuidle/governors/Makefile        1969-12-31 19:00:00.000000000 -0500
+@@ -1,6 +0,0 @@
+-#
+-# Makefile for cpuidle governors.
+-#
+-
+-obj-$(CONFIG_CPU_IDLE_GOV_LADDER) += ladder.o
+-obj-$(CONFIG_CPU_IDLE_GOV_MENU) += menu.o
+diff -Nurb linux-2.6.22-590/drivers/cpuidle/governors/ladder.c linux-2.6.22-570/drivers/cpuidle/governors/ladder.c
+--- linux-2.6.22-590/drivers/cpuidle/governors/ladder.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpuidle/governors/ladder.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,227 +0,0 @@
+-/*
+- * ladder.c - the residency ladder algorithm
+- *
+- *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
+- *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
+- *  Copyright (C) 2004, 2005 Dominik Brodowski <linux@brodo.de>
+- *
+- * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+- *               Shaohua Li <shaohua.li@intel.com>
+- *               Adam Belay <abelay@novell.com>
+- *
+- * This code is licenced under the GPL.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/cpuidle.h>
+-#include <linux/latency.h>
+-#include <linux/moduleparam.h>
+-#include <linux/jiffies.h>
+-
+-#include <asm/io.h>
+-#include <asm/uaccess.h>
+-
+-#define PROMOTION_COUNT 4
+-#define DEMOTION_COUNT 1
+-
+-/*
+- * bm_history -- bit-mask with a bit per jiffy of bus-master activity
+- * 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms
+- * 800 HZ: 0xFFFFFFFF: 32 jiffies = 40ms
+- * 100 HZ: 0x0000000F: 4 jiffies = 40ms
+- * reduce history for more aggressive entry into C3
+- */
+-static unsigned int bm_history __read_mostly =
+-    (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
+-module_param(bm_history, uint, 0644);
+-
+-struct ladder_device_state {
+-      struct {
+-              u32 promotion_count;
+-              u32 demotion_count;
+-              u32 promotion_time;
+-              u32 demotion_time;
+-              u32 bm;
+-      } threshold;
+-      struct {
+-              int promotion_count;
+-              int demotion_count;
+-      } stats;
+-};
+-
+-struct ladder_device {
+-      struct ladder_device_state states[CPUIDLE_STATE_MAX];
+-      unsigned int bm_check:1;
+-      unsigned long bm_check_timestamp;
+-      unsigned long bm_activity; /* FIXME: bm activity should be global */
+-      int last_state_idx;
+-};
+-
+-/**
+- * ladder_do_selection - prepares private data for a state change
+- * @ldev: the ladder device
+- * @old_idx: the current state index
+- * @new_idx: the new target state index
+- */
+-static inline void ladder_do_selection(struct ladder_device *ldev,
+-                                     int old_idx, int new_idx)
+-{
+-      ldev->states[old_idx].stats.promotion_count = 0;
+-      ldev->states[old_idx].stats.demotion_count = 0;
+-      ldev->last_state_idx = new_idx;
+-}
+-
+-/**
+- * ladder_select_state - selects the next state to enter
+- * @dev: the CPU
+- */
+-static int ladder_select_state(struct cpuidle_device *dev)
+-{
+-      struct ladder_device *ldev = dev->governor_data;
+-      struct ladder_device_state *last_state;
+-      int last_residency, last_idx = ldev->last_state_idx;
+-
+-      if (unlikely(!ldev))
+-              return 0;
+-
+-      last_state = &ldev->states[last_idx];
+-
+-      /* demote if within BM threshold */
+-      if (ldev->bm_check) {
+-              unsigned long diff;
+-
+-              diff = jiffies - ldev->bm_check_timestamp;
+-              if (diff > 31)
+-                      diff = 31;
+-
+-              ldev->bm_activity <<= diff;
+-              if (cpuidle_get_bm_activity())
+-                      ldev->bm_activity |= ((1 << diff) - 1);
+-
+-              ldev->bm_check_timestamp = jiffies;
+-              if ((last_idx > 0) &&
+-                  (last_state->threshold.bm & ldev->bm_activity)) {
+-                      ladder_do_selection(ldev, last_idx, last_idx - 1);
+-                      return last_idx - 1;
 -              }
-+              if (init_utsname()->nodename[0] != '\0')
-+                      lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
-+              else
-+                      mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60);
-       }
-       return;
- }
+-      }
 -
- void
--lpfc_decode_firmware_rev(struct lpfc_hba * phba, char *fwrevision, int flag)
-+lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
- {
-       struct lpfc_sli *psli = &phba->sli;
-       lpfc_vpd_t *vp = &phba->vpd;
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_debugfs.c linux-2.6.22-590/drivers/scsi/lpfc/lpfc_debugfs.c
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_debugfs.c  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_debugfs.c  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,508 @@
-+/*******************************************************************
-+ * This file is part of the Emulex Linux Device Driver for         *
-+ * Fibre Channel Host Bus Adapters.                                *
-+ * Copyright (C) 2007 Emulex.  All rights reserved.                *
-+ * EMULEX and SLI are trademarks of Emulex.                        *
-+ * www.emulex.com                                                  *
-+ *                                                                 *
-+ * This program is free software; you can redistribute it and/or   *
-+ * modify it under the terms of version 2 of the GNU General       *
-+ * Public License as published by the Free Software Foundation.    *
-+ * This program is distributed in the hope that it will be useful. *
-+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
-+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
-+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
-+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
-+ * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
-+ * more details, a copy of which can be found in the file COPYING  *
-+ * included with this package.                                     *
-+ *******************************************************************/
-+
-+#include <linux/blkdev.h>
-+#include <linux/delay.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/idr.h>
-+#include <linux/interrupt.h>
-+#include <linux/kthread.h>
-+#include <linux/pci.h>
-+#include <linux/spinlock.h>
-+#include <linux/ctype.h>
-+#include <linux/version.h>
-+
-+#include <scsi/scsi.h>
-+#include <scsi/scsi_device.h>
-+#include <scsi/scsi_host.h>
-+#include <scsi/scsi_transport_fc.h>
-+
-+#include "lpfc_hw.h"
-+#include "lpfc_sli.h"
-+#include "lpfc_disc.h"
-+#include "lpfc_scsi.h"
-+#include "lpfc.h"
-+#include "lpfc_logmsg.h"
-+#include "lpfc_crtn.h"
-+#include "lpfc_vport.h"
-+#include "lpfc_version.h"
-+#include "lpfc_vport.h"
-+#include "lpfc_debugfs.h"
-+
-+#ifdef CONFIG_LPFC_DEBUG_FS
-+/* debugfs interface
-+ *
-+ * To access this interface the user should:
-+ * # mkdir /debug
-+ * # mount -t debugfs none /debug
-+ *
-+ * The lpfc debugfs directory hierachy is:
-+ * lpfc/lpfcX/vportY
-+ * where X is the lpfc hba unique_id
-+ * where Y is the vport VPI on that hba
-+ *
-+ * Debugging services available per vport:
-+ * discovery_trace
-+ * This is an ACSII readable file that contains a trace of the last
-+ * lpfc_debugfs_max_disc_trc events that happened on a specific vport.
-+ * See lpfc_debugfs.h for different categories of
-+ * discovery events. To enable the discovery trace, the following
-+ * module parameters must be set:
-+ * lpfc_debugfs_enable=1         Turns on lpfc debugfs filesystem support
-+ * lpfc_debugfs_max_disc_trc=X   Where X is the event trace depth for
-+ *                               EACH vport. X MUST also be a power of 2.
-+ * lpfc_debugfs_mask_disc_trc=Y  Where Y is an event mask as defined in
-+ *                               lpfc_debugfs.h .
-+ */
-+static int lpfc_debugfs_enable = 0;
-+module_param(lpfc_debugfs_enable, int, 0);
-+MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services");
-+
-+static int lpfc_debugfs_max_disc_trc = 0;  /* This MUST be a power of 2 */
-+module_param(lpfc_debugfs_max_disc_trc, int, 0);
-+MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc,
-+      "Set debugfs discovery trace depth");
-+
-+static int lpfc_debugfs_mask_disc_trc = 0;
-+module_param(lpfc_debugfs_mask_disc_trc, int, 0);
-+MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
-+      "Set debugfs discovery trace mask");
-+
-+#include <linux/debugfs.h>
-+
-+/* size of discovery_trace output line */
-+#define LPFC_DISC_TRC_ENTRY_SIZE 80
-+
-+/* nodelist output buffer size */
-+#define LPFC_NODELIST_SIZE 8192
-+#define LPFC_NODELIST_ENTRY_SIZE 120
-+
-+struct lpfc_debug {
-+      char *buffer;
-+      int  len;
-+};
-+
-+atomic_t lpfc_debugfs_disc_trc_cnt = ATOMIC_INIT(0);
-+unsigned long lpfc_debugfs_start_time = 0L;
-+
-+static int
-+lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
-+{
-+      int i, index, len, enable;
-+      uint32_t ms;
-+      struct lpfc_disc_trc *dtp;
-+      char buffer[80];
-+
-+
-+      enable = lpfc_debugfs_enable;
-+      lpfc_debugfs_enable = 0;
-+
-+      len = 0;
-+      index = (atomic_read(&vport->disc_trc_cnt) + 1) &
-+              (lpfc_debugfs_max_disc_trc - 1);
-+      for (i = index; i < lpfc_debugfs_max_disc_trc; i++) {
-+              dtp = vport->disc_trc + i;
-+              if (!dtp->fmt)
-+                      continue;
-+              ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
-+              snprintf(buffer, 80, "%010d:%010d ms:%s\n",
-+                      dtp->seq_cnt, ms, dtp->fmt);
-+              len +=  snprintf(buf+len, size-len, buffer,
-+                      dtp->data1, dtp->data2, dtp->data3);
-+      }
-+      for (i = 0; i < index; i++) {
-+              dtp = vport->disc_trc + i;
-+              if (!dtp->fmt)
-+                      continue;
-+              ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
-+              snprintf(buffer, 80, "%010d:%010d ms:%s\n",
-+                      dtp->seq_cnt, ms, dtp->fmt);
-+              len +=  snprintf(buf+len, size-len, buffer,
-+                      dtp->data1, dtp->data2, dtp->data3);
-+      }
-+
-+      lpfc_debugfs_enable = enable;
-+      return len;
-+}
-+
-+static int
-+lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
-+{
-+      int len = 0;
-+      int cnt;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_nodelist *ndlp;
-+      unsigned char *statep, *name;
-+
-+      cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
-+
-+      spin_lock_irq(shost->host_lock);
-+      list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
-+              if (!cnt) {
-+                      len +=  snprintf(buf+len, size-len,
-+                              "Missing Nodelist Entries\n");
-+                      break;
-+              }
-+              cnt--;
-+              switch (ndlp->nlp_state) {
-+              case NLP_STE_UNUSED_NODE:
-+                      statep = "UNUSED";
-+                      break;
-+              case NLP_STE_PLOGI_ISSUE:
-+                      statep = "PLOGI ";
-+                      break;
-+              case NLP_STE_ADISC_ISSUE:
-+                      statep = "ADISC ";
-+                      break;
-+              case NLP_STE_REG_LOGIN_ISSUE:
-+                      statep = "REGLOG";
-+                      break;
-+              case NLP_STE_PRLI_ISSUE:
-+                      statep = "PRLI  ";
-+                      break;
-+              case NLP_STE_UNMAPPED_NODE:
-+                      statep = "UNMAP ";
-+                      break;
-+              case NLP_STE_MAPPED_NODE:
-+                      statep = "MAPPED";
-+                      break;
-+              case NLP_STE_NPR_NODE:
-+                      statep = "NPR   ";
-+                      break;
-+              default:
-+                      statep = "UNKNOWN";
-+              }
-+              len +=  snprintf(buf+len, size-len, "%s DID:x%06x ",
-+                      statep, ndlp->nlp_DID);
-+              name = (unsigned char *)&ndlp->nlp_portname;
-+              len +=  snprintf(buf+len, size-len,
-+                      "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
-+                      *name, *(name+1), *(name+2), *(name+3),
-+                      *(name+4), *(name+5), *(name+6), *(name+7));
-+              name = (unsigned char *)&ndlp->nlp_nodename;
-+              len +=  snprintf(buf+len, size-len,
-+                      "WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
-+                      *name, *(name+1), *(name+2), *(name+3),
-+                      *(name+4), *(name+5), *(name+6), *(name+7));
-+              len +=  snprintf(buf+len, size-len, "RPI:%03d flag:x%08x ",
-+                      ndlp->nlp_rpi, ndlp->nlp_flag);
-+              if (!ndlp->nlp_type)
-+                      len +=  snprintf(buf+len, size-len, "UNKNOWN_TYPE");
-+              if (ndlp->nlp_type & NLP_FC_NODE)
-+                      len +=  snprintf(buf+len, size-len, "FC_NODE ");
-+              if (ndlp->nlp_type & NLP_FABRIC)
-+                      len +=  snprintf(buf+len, size-len, "FABRIC ");
-+              if (ndlp->nlp_type & NLP_FCP_TARGET)
-+                      len +=  snprintf(buf+len, size-len, "FCP_TGT sid:%d ",
-+                              ndlp->nlp_sid);
-+              if (ndlp->nlp_type & NLP_FCP_INITIATOR)
-+                      len +=  snprintf(buf+len, size-len, "FCP_INITIATOR");
-+              len +=  snprintf(buf+len, size-len, "\n");
-+      }
-+      spin_unlock_irq(shost->host_lock);
-+      return len;
-+}
-+#endif
-+
-+
-+inline void
-+lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
-+      uint32_t data1, uint32_t data2, uint32_t data3)
-+{
-+#ifdef CONFIG_LPFC_DEBUG_FS
-+      struct lpfc_disc_trc *dtp;
-+      int index;
-+
-+      if (!(lpfc_debugfs_mask_disc_trc & mask))
-+              return;
-+
-+      if (!lpfc_debugfs_enable || !lpfc_debugfs_max_disc_trc ||
-+              !vport || !vport->disc_trc)
-+              return;
-+
-+      index = atomic_inc_return(&vport->disc_trc_cnt) &
-+              (lpfc_debugfs_max_disc_trc - 1);
-+      dtp = vport->disc_trc + index;
-+      dtp->fmt = fmt;
-+      dtp->data1 = data1;
-+      dtp->data2 = data2;
-+      dtp->data3 = data3;
-+      dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_disc_trc_cnt);
-+      dtp->jif = jiffies;
-+#endif
-+      return;
-+}
-+
-+#ifdef CONFIG_LPFC_DEBUG_FS
-+static int
-+lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
-+{
-+      struct lpfc_vport *vport = inode->i_private;
-+      struct lpfc_debug *debug;
-+      int size;
-+      int rc = -ENOMEM;
-+
-+      if (!lpfc_debugfs_max_disc_trc) {
-+               rc = -ENOSPC;
-+              goto out;
-+      }
-+
-+      debug = kmalloc(sizeof(*debug), GFP_KERNEL);
-+      if (!debug)
-+              goto out;
-+
-+      /* Round to page boundry */
-+      size =  (lpfc_debugfs_max_disc_trc * LPFC_DISC_TRC_ENTRY_SIZE);
-+      size = PAGE_ALIGN(size);
-+
-+      debug->buffer = kmalloc(size, GFP_KERNEL);
-+      if (!debug->buffer) {
-+              kfree(debug);
-+              goto out;
-+      }
-+
-+      debug->len = lpfc_debugfs_disc_trc_data(vport, debug->buffer, size);
-+      file->private_data = debug;
-+
-+      rc = 0;
-+out:
-+      return rc;
-+}
-+
-+static int
-+lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
-+{
-+      struct lpfc_vport *vport = inode->i_private;
-+      struct lpfc_debug *debug;
-+      int rc = -ENOMEM;
-+
-+      debug = kmalloc(sizeof(*debug), GFP_KERNEL);
-+      if (!debug)
-+              goto out;
-+
-+      /* Round to page boundry */
-+      debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL);
-+      if (!debug->buffer) {
-+              kfree(debug);
-+              goto out;
-+      }
-+
-+      debug->len = lpfc_debugfs_nodelist_data(vport, debug->buffer,
-+              LPFC_NODELIST_SIZE);
-+      file->private_data = debug;
-+
-+      rc = 0;
-+out:
-+      return rc;
-+}
-+
-+static loff_t
-+lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
-+{
-+      struct lpfc_debug *debug;
-+      loff_t pos = -1;
-+
-+      debug = file->private_data;
-+
-+      switch (whence) {
-+      case 0:
-+              pos = off;
-+              break;
-+      case 1:
-+              pos = file->f_pos + off;
-+              break;
-+      case 2:
-+              pos = debug->len - off;
-+      }
-+      return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos);
-+}
-+
-+static ssize_t
-+lpfc_debugfs_read(struct file *file, char __user *buf,
-+                size_t nbytes, loff_t *ppos)
-+{
-+      struct lpfc_debug *debug = file->private_data;
-+      return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer,
-+                                     debug->len);
-+}
-+
-+static int
-+lpfc_debugfs_release(struct inode *inode, struct file *file)
-+{
-+      struct lpfc_debug *debug = file->private_data;
-+
-+      kfree(debug->buffer);
-+      kfree(debug);
-+
-+      return 0;
-+}
-+
-+#undef lpfc_debugfs_op_disc_trc
-+static struct file_operations lpfc_debugfs_op_disc_trc = {
-+      .owner =        THIS_MODULE,
-+      .open =         lpfc_debugfs_disc_trc_open,
-+      .llseek =       lpfc_debugfs_lseek,
-+      .read =         lpfc_debugfs_read,
-+      .release =      lpfc_debugfs_release,
-+};
-+
-+#undef lpfc_debugfs_op_nodelist
-+static struct file_operations lpfc_debugfs_op_nodelist = {
-+      .owner =        THIS_MODULE,
-+      .open =         lpfc_debugfs_nodelist_open,
-+      .llseek =       lpfc_debugfs_lseek,
-+      .read =         lpfc_debugfs_read,
-+      .release =      lpfc_debugfs_release,
-+};
-+
-+static struct dentry *lpfc_debugfs_root = NULL;
-+static atomic_t lpfc_debugfs_hba_count;
-+#endif
-+
-+inline void
-+lpfc_debugfs_initialize(struct lpfc_vport *vport)
-+{
-+#ifdef CONFIG_LPFC_DEBUG_FS
-+      struct lpfc_hba   *phba = vport->phba;
-+      char name[64];
-+      uint32_t num, i;
-+
-+      if (!lpfc_debugfs_enable)
-+              return;
-+
-+      if (lpfc_debugfs_max_disc_trc) {
-+              num = lpfc_debugfs_max_disc_trc - 1;
-+              if (num & lpfc_debugfs_max_disc_trc) {
-+                      /* Change to be a power of 2 */
-+                      num = lpfc_debugfs_max_disc_trc;
-+                      i = 0;
-+                      while (num > 1) {
-+                              num = num >> 1;
-+                              i++;
-+                      }
-+                      lpfc_debugfs_max_disc_trc = (1 << i);
-+                      printk(KERN_ERR
-+                              "lpfc_debugfs_max_disc_trc changed to %d\n",
-+                              lpfc_debugfs_max_disc_trc);
-+              }
-+      }
-+
-+      if (!lpfc_debugfs_root) {
-+              lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL);
-+              atomic_set(&lpfc_debugfs_hba_count, 0);
-+              if (!lpfc_debugfs_root)
-+                      goto debug_failed;
-+      }
-+
-+      snprintf(name, sizeof(name), "lpfc%d", phba->brd_no);
-+      if (!phba->hba_debugfs_root) {
-+              phba->hba_debugfs_root =
-+                      debugfs_create_dir(name, lpfc_debugfs_root);
-+              if (!phba->hba_debugfs_root)
-+                      goto debug_failed;
-+              atomic_inc(&lpfc_debugfs_hba_count);
-+              atomic_set(&phba->debugfs_vport_count, 0);
-+      }
-+
-+      snprintf(name, sizeof(name), "vport%d", vport->vpi);
-+      if (!vport->vport_debugfs_root) {
-+              vport->vport_debugfs_root =
-+                      debugfs_create_dir(name, phba->hba_debugfs_root);
-+              if (!vport->vport_debugfs_root)
-+                      goto debug_failed;
-+              atomic_inc(&phba->debugfs_vport_count);
-+      }
-+
-+      if (!lpfc_debugfs_start_time)
-+              lpfc_debugfs_start_time = jiffies;
-+
-+      vport->disc_trc = kmalloc(
-+              (sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc),
-+              GFP_KERNEL);
-+
-+      if (!vport->disc_trc)
-+              goto debug_failed;
-+      memset(vport->disc_trc, 0,
-+              (sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc));
-+
-+      snprintf(name, sizeof(name), "discovery_trace");
-+      vport->debug_disc_trc =
-+              debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
-+                               vport->vport_debugfs_root,
-+                               vport, &lpfc_debugfs_op_disc_trc);
-+      if (!vport->debug_disc_trc) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-+                              "%d:0409 Cannot create debugfs",
-+                              phba->brd_no);
-+              goto debug_failed;
-+      }
-+      snprintf(name, sizeof(name), "nodelist");
-+      vport->debug_nodelist =
-+              debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
-+                               vport->vport_debugfs_root,
-+                               vport, &lpfc_debugfs_op_nodelist);
-+      if (!vport->debug_nodelist) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-+                              "%d:0409 Cannot create debugfs",
-+                              phba->brd_no);
-+              goto debug_failed;
-+      }
-+debug_failed:
-+      return;
-+#endif
-+}
-+
-+
-+inline void
-+lpfc_debugfs_terminate(struct lpfc_vport *vport)
-+{
-+#ifdef CONFIG_LPFC_DEBUG_FS
-+      struct lpfc_hba   *phba = vport->phba;
-+
-+      if (vport->disc_trc) {
-+              kfree(vport->disc_trc);
-+              vport->disc_trc = NULL;
-+      }
-+      if (vport->debug_disc_trc) {
-+              debugfs_remove(vport->debug_disc_trc); /* discovery_trace */
-+              vport->debug_disc_trc = NULL;
-+      }
-+      if (vport->debug_nodelist) {
-+              debugfs_remove(vport->debug_nodelist); /* nodelist */
-+              vport->debug_nodelist = NULL;
-+      }
-+      if (vport->vport_debugfs_root) {
-+              debugfs_remove(vport->vport_debugfs_root); /* vportX */
-+              vport->vport_debugfs_root = NULL;
-+              atomic_dec(&phba->debugfs_vport_count);
-+      }
-+      if (atomic_read(&phba->debugfs_vport_count) == 0) {
-+              debugfs_remove(vport->phba->hba_debugfs_root); /* lpfcX */
-+              vport->phba->hba_debugfs_root = NULL;
-+              atomic_dec(&lpfc_debugfs_hba_count);
-+              if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
-+                      debugfs_remove(lpfc_debugfs_root); /* lpfc */
-+                      lpfc_debugfs_root = NULL;
-+              }
-+      }
-+#endif
-+}
-+
-+
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_debugfs.h linux-2.6.22-590/drivers/scsi/lpfc/lpfc_debugfs.h
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_debugfs.h  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_debugfs.h  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,50 @@
-+/*******************************************************************
-+ * This file is part of the Emulex Linux Device Driver for         *
-+ * Fibre Channel Host Bus Adapters.                                *
-+ * Copyright (C) 2007 Emulex.  All rights reserved.                *
-+ * EMULEX and SLI are trademarks of Emulex.                        *
-+ * www.emulex.com                                                  *
-+ *                                                                 *
-+ * This program is free software; you can redistribute it and/or   *
-+ * modify it under the terms of version 2 of the GNU General       *
-+ * Public License as published by the Free Software Foundation.    *
-+ * This program is distributed in the hope that it will be useful. *
-+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
-+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
-+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
-+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
-+ * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
-+ * more details, a copy of which can be found in the file COPYING  *
-+ * included with this package.                                     *
-+ *******************************************************************/
-+
-+#ifndef _H_LPFC_DEBUG_FS
-+#define _H_LPFC_DEBUG_FS
-+
-+#ifdef CONFIG_LPFC_DEBUG_FS
-+struct lpfc_disc_trc {
-+      char *fmt;
-+      uint32_t data1;
-+      uint32_t data2;
-+      uint32_t data3;
-+      uint32_t seq_cnt;
-+      unsigned long jif;
-+};
-+#endif
-+
-+/* Mask for discovery_trace */
-+#define LPFC_DISC_TRC_ELS_CMD         0x1     /* Trace ELS commands */
-+#define LPFC_DISC_TRC_ELS_RSP         0x2     /* Trace ELS response */
-+#define LPFC_DISC_TRC_ELS_UNSOL               0x4     /* Trace ELS rcv'ed   */
-+#define LPFC_DISC_TRC_ELS_ALL         0x7     /* Trace ELS */
-+#define LPFC_DISC_TRC_MBOX_VPORT      0x8     /* Trace vport MBOXs */
-+#define LPFC_DISC_TRC_MBOX            0x10    /* Trace other MBOXs */
-+#define LPFC_DISC_TRC_MBOX_ALL                0x18    /* Trace all MBOXs */
-+#define LPFC_DISC_TRC_CT              0x20    /* Trace disc CT requests */
-+#define LPFC_DISC_TRC_DSM             0x40    /* Trace DSM events */
-+#define LPFC_DISC_TRC_RPORT           0x80    /* Trace rport events */
-+#define LPFC_DISC_TRC_NODE            0x100   /* Trace ndlp state changes */
-+
-+#define LPFC_DISC_TRC_DISCOVERY               0xef    /* common mask for general
-+                                               * discovery */
-+#endif /* H_LPFC_DEBUG_FS */
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_disc.h linux-2.6.22-590/drivers/scsi/lpfc/lpfc_disc.h
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_disc.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_disc.h     2008-01-02 13:56:37.000000000 -0500
-@@ -36,21 +36,23 @@
-       LPFC_EVT_WARM_START,
-       LPFC_EVT_KILL,
-       LPFC_EVT_ELS_RETRY,
-+      LPFC_EVT_DEV_LOSS_DELAY,
-+      LPFC_EVT_DEV_LOSS,
- };
- /* structure used to queue event to the discovery tasklet */
- struct lpfc_work_evt {
-       struct list_head      evt_listp;
--      void                * evt_arg1;
--      void                * evt_arg2;
-+      void                 *evt_arg1;
-+      void                 *evt_arg2;
-       enum lpfc_work_type   evt;
- };
- struct lpfc_nodelist {
-       struct list_head nlp_listp;
--      struct lpfc_name nlp_portname;          /* port name */
--      struct lpfc_name nlp_nodename;          /* node name */
-+      struct lpfc_name nlp_portname;
-+      struct lpfc_name nlp_nodename;
-       uint32_t         nlp_flag;              /* entry  flags */
-       uint32_t         nlp_DID;               /* FC D_ID of entry */
-       uint32_t         nlp_last_elscmd;       /* Last ELS cmd sent */
-@@ -75,8 +77,9 @@
-       struct timer_list   nlp_delayfunc;      /* Used for delayed ELS cmds */
-       struct fc_rport *rport;                 /* Corresponding FC transport
-                                                  port structure */
--      struct lpfc_hba      *nlp_phba;
-+      struct lpfc_vport *vport;
-       struct lpfc_work_evt els_retry_evt;
-+      struct lpfc_work_evt dev_loss_evt;
-       unsigned long last_ramp_up_time;        /* jiffy of last ramp up */
-       unsigned long last_q_full_time;         /* jiffy of last queue full */
-       struct kref     kref;
-@@ -98,7 +101,9 @@
-                                          ACC */
- #define NLP_NPR_ADISC      0x2000000  /* Issue ADISC when dq'ed from
-                                          NPR list */
-+#define NLP_RM_DFLT_RPI    0x4000000  /* need to remove leftover dflt RPI */
- #define NLP_NODEV_REMOVE   0x8000000  /* Defer removal till discovery ends */
-+#define NLP_TARGET_REMOVE  0x10000000   /* Target remove in process */
- /* There are 4 different double linked lists nodelist entries can reside on.
-  * The Port Login (PLOGI) list and Address Discovery (ADISC) list are used
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_els.c linux-2.6.22-590/drivers/scsi/lpfc/lpfc_els.c
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_els.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_els.c      2008-01-02 13:56:37.000000000 -0500
-@@ -35,38 +35,38 @@
- #include "lpfc.h"
- #include "lpfc_logmsg.h"
- #include "lpfc_crtn.h"
-+#include "lpfc_vport.h"
-+#include "lpfc_debugfs.h"
- static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *,
-                         struct lpfc_iocbq *);
-+static void lpfc_cmpl_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *,
-+                      struct lpfc_iocbq *);
-+
- static int lpfc_max_els_tries = 3;
--static int
--lpfc_els_chk_latt(struct lpfc_hba * phba)
-+int
-+lpfc_els_chk_latt(struct lpfc_vport *vport)
- {
--      struct lpfc_sli *psli;
--      LPFC_MBOXQ_t *mbox;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-       uint32_t ha_copy;
--      int rc;
+-      if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID)
+-              last_residency = cpuidle_get_last_residency(dev) - dev->states[last_idx].exit_latency;
+-      else
+-              last_residency = last_state->threshold.promotion_time + 1;
+-
+-      /* consider promotion */
+-      if (last_idx < dev->state_count - 1 &&
+-          last_residency > last_state->threshold.promotion_time &&
+-          dev->states[last_idx + 1].exit_latency <= system_latency_constraint()) {
+-              last_state->stats.promotion_count++;
+-              last_state->stats.demotion_count = 0;
+-              if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
+-                      ladder_do_selection(ldev, last_idx, last_idx + 1);
+-                      return last_idx + 1;
+-              }
+-      }
 -
--      psli = &phba->sli;
--      if ((phba->hba_state >= LPFC_HBA_READY) ||
--          (phba->hba_state == LPFC_LINK_DOWN))
-+      if (vport->port_state >= LPFC_VPORT_READY ||
-+          phba->link_state == LPFC_LINK_DOWN)
-               return 0;
-       /* Read the HBA Host Attention Register */
--      spin_lock_irq(phba->host->host_lock);
-       ha_copy = readl(phba->HAregaddr);
--      spin_unlock_irq(phba->host->host_lock);
-       if (!(ha_copy & HA_LATT))
-               return 0;
-       /* Pending Link Event during Discovery */
--      lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY,
--                      "%d:0237 Pending Link Event during "
-+      lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-+                      "%d (%d):0237 Pending Link Event during "
-                       "Discovery: State x%x\n",
--                      phba->brd_no, phba->hba_state);
-+                      phba->brd_no, vport->vpi,  phba->pport->port_state);
-       /* CLEAR_LA should re-enable link attention events and
-        * we should then imediately take a LATT event. The
-@@ -74,48 +74,34 @@
-        * will cleanup any left over in-progress discovery
-        * events.
-        */
--      spin_lock_irq(phba->host->host_lock);
--      phba->fc_flag |= FC_ABORT_DISCOVERY;
--      spin_unlock_irq(phba->host->host_lock);
--
--      if (phba->hba_state != LPFC_CLEAR_LA) {
--              if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
--                      phba->hba_state = LPFC_CLEAR_LA;
--                      lpfc_clear_la(phba, mbox);
--                      mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
--                      rc = lpfc_sli_issue_mbox (phba, mbox,
--                                                (MBX_NOWAIT | MBX_STOP_IOCB));
--                      if (rc == MBX_NOT_FINISHED) {
--                              mempool_free(mbox, phba->mbox_mem_pool);
--                              phba->hba_state = LPFC_HBA_ERROR;
--                      }
+-      /* consider demotion */
+-      if (last_idx > 0 &&
+-          last_residency < last_state->threshold.demotion_time) {
+-              last_state->stats.demotion_count++;
+-              last_state->stats.promotion_count = 0;
+-              if (last_state->stats.demotion_count >= last_state->threshold.demotion_count) {
+-                      ladder_do_selection(ldev, last_idx, last_idx - 1);
+-                      return last_idx - 1;
 -              }
 -      }
-+      spin_lock_irq(shost->host_lock);
-+      vport->fc_flag |= FC_ABORT_DISCOVERY;
-+      spin_unlock_irq(shost->host_lock);
--      return 1;
-+      if (phba->link_state != LPFC_CLEAR_LA)
-+              lpfc_issue_clear_la(phba, vport);
-+      return 1;
- }
- static struct lpfc_iocbq *
--lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp,
--                 uint16_t cmdSize, uint8_t retry, struct lpfc_nodelist * ndlp,
--                 uint32_t did, uint32_t elscmd)
-+lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
-+                 uint16_t cmdSize, uint8_t retry,
-+                 struct lpfc_nodelist *ndlp, uint32_t did,
-+                 uint32_t elscmd)
- {
--      struct lpfc_sli_ring *pring;
-+      struct lpfc_hba  *phba = vport->phba;
-       struct lpfc_iocbq *elsiocb;
-       struct lpfc_dmabuf *pcmd, *prsp, *pbuflist;
-       struct ulp_bde64 *bpl;
-       IOCB_t *icmd;
--      pring = &phba->sli.ring[LPFC_ELS_RING];
--      if (phba->hba_state < LPFC_LINK_UP)
-+      if (!lpfc_is_link_up(phba))
-               return  NULL;
-       /* Allocate buffer for  command iocb */
--      spin_lock_irq(phba->host->host_lock);
-       elsiocb = lpfc_sli_get_iocbq(phba);
--      spin_unlock_irq(phba->host->host_lock);
-       if (elsiocb == NULL)
-               return NULL;
-@@ -123,14 +109,12 @@
-       /* fill in BDEs for command */
-       /* Allocate buffer for command payload */
--      if (((pcmd = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
-+      if (((pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
-           ((pcmd->virt = lpfc_mbuf_alloc(phba,
-                                          MEM_PRI, &(pcmd->phys))) == 0)) {
-               kfree(pcmd);
--              spin_lock_irq(phba->host->host_lock);
-               lpfc_sli_release_iocbq(phba, elsiocb);
--              spin_unlock_irq(phba->host->host_lock);
-               return NULL;
-       }
-@@ -138,7 +122,7 @@
-       /* Allocate buffer for response payload */
-       if (expectRsp) {
--              prsp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
-+              prsp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
-               if (prsp)
-                       prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
-                                                    &prsp->phys);
-@@ -146,9 +130,7 @@
-                       kfree(prsp);
-                       lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
-                       kfree(pcmd);
--                      spin_lock_irq(phba->host->host_lock);
-                       lpfc_sli_release_iocbq(phba, elsiocb);
--                      spin_unlock_irq(phba->host->host_lock);
-                       return NULL;
-               }
-               INIT_LIST_HEAD(&prsp->list);
-@@ -157,14 +139,12 @@
-       }
-       /* Allocate buffer for Buffer ptr list */
--      pbuflist = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
-+      pbuflist = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
-       if (pbuflist)
-           pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
-                                            &pbuflist->phys);
-       if (pbuflist == 0 || pbuflist->virt == 0) {
--              spin_lock_irq(phba->host->host_lock);
-               lpfc_sli_release_iocbq(phba, elsiocb);
--              spin_unlock_irq(phba->host->host_lock);
-               lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
-               lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
-               kfree(pcmd);
-@@ -178,20 +158,28 @@
-       icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
-       icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
-       icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL;
--      if (expectRsp) {
--              icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64));
-               icmd->un.elsreq64.remoteID = did;       /* DID */
-+      if (expectRsp) {
-+              icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64));
-               icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
-               icmd->ulpTimeout = phba->fc_ratov * 2;
-       } else {
--              icmd->un.elsreq64.bdl.bdeSize = sizeof (struct ulp_bde64);
-+              icmd->un.elsreq64.bdl.bdeSize = sizeof(struct ulp_bde64);
-               icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
-       }
 -
-       icmd->ulpBdeCount = 1;
-       icmd->ulpLe = 1;
-       icmd->ulpClass = CLASS3;
-+      if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
-+              icmd->un.elsreq64.myID = vport->fc_myDID;
-+
-+              /* For ELS_REQUEST64_CR, use the VPI by default */
-+              icmd->ulpContext = vport->vpi;
-+              icmd->ulpCt_h = 0;
-+              icmd->ulpCt_l = 1;
-+      }
-+
-       bpl = (struct ulp_bde64 *) pbuflist->virt;
-       bpl->addrLow = le32_to_cpu(putPaddrLow(pcmd->phys));
-       bpl->addrHigh = le32_to_cpu(putPaddrHigh(pcmd->phys));
-@@ -209,10 +197,12 @@
-       }
-       /* Save for completion so we can release these resources */
-+      if (elscmd != ELS_CMD_LS_RJT)
-       elsiocb->context1 = lpfc_nlp_get(ndlp);
-       elsiocb->context2 = pcmd;
-       elsiocb->context3 = pbuflist;
-       elsiocb->retry = retry;
-+      elsiocb->vport = vport;
-       elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT;
-       if (prsp) {
-@@ -222,16 +212,16 @@
-       if (expectRsp) {
-               /* Xmit ELS command <elsCmd> to remote NPORT <did> */
-               lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                              "%d:0116 Xmit ELS command x%x to remote "
--                              "NPORT x%x I/O tag: x%x, HBA state: x%x\n",
--                              phba->brd_no, elscmd,
--                              did, elsiocb->iotag, phba->hba_state);
-+                              "%d (%d):0116 Xmit ELS command x%x to remote "
-+                              "NPORT x%x I/O tag: x%x, port state: x%x\n",
-+                              phba->brd_no, vport->vpi,  elscmd, did,
-+                              elsiocb->iotag, vport->port_state);
-       } else {
-               /* Xmit ELS response <elsCmd> to remote NPORT <did> */
-               lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                              "%d:0117 Xmit ELS response x%x to remote "
-+                              "%d (%d):0117 Xmit ELS response x%x to remote "
-                               "NPORT x%x I/O tag: x%x, size: x%x\n",
--                              phba->brd_no, elscmd,
-+                              phba->brd_no, vport->vpi, elscmd,
-                               ndlp->nlp_DID, elsiocb->iotag, cmdSize);
-       }
-@@ -240,16 +230,79 @@
- static int
--lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
--              struct serv_parm *sp, IOCB_t *irsp)
-+lpfc_issue_fabric_reglogin(struct lpfc_vport *vport)
- {
-+      struct lpfc_hba  *phba = vport->phba;
-       LPFC_MBOXQ_t *mbox;
-       struct lpfc_dmabuf *mp;
-+      struct lpfc_nodelist *ndlp;
-+      struct serv_parm *sp;
-       int rc;
--      spin_lock_irq(phba->host->host_lock);
--      phba->fc_flag |= FC_FABRIC;
--      spin_unlock_irq(phba->host->host_lock);
-+      sp = &phba->fc_fabparam;
-+      ndlp = lpfc_findnode_did(vport, Fabric_DID);
-+      if (!ndlp)
-+              goto fail;
-+
-+      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (!mbox)
-+              goto fail;
-+
-+      vport->port_state = LPFC_FABRIC_CFG_LINK;
-+      lpfc_config_link(phba, mbox);
-+      mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-+      mbox->vport = vport;
-+
-+      rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
-+      if (rc == MBX_NOT_FINISHED)
-+              goto fail_free_mbox;
-+
-+      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (!mbox)
-+              goto fail;
-+      rc = lpfc_reg_login(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox,
-+                          0);
-+      if (rc)
-+              goto fail_free_mbox;
-+
-+      mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
-+      mbox->vport = vport;
-+      mbox->context2 = lpfc_nlp_get(ndlp);
-+
-+      rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
-+      if (rc == MBX_NOT_FINISHED)
-+              goto fail_issue_reg_login;
-+
-+      return 0;
-+
-+fail_issue_reg_login:
-+      lpfc_nlp_put(ndlp);
-+      mp = (struct lpfc_dmabuf *) mbox->context1;
-+      lpfc_mbuf_free(phba, mp->virt, mp->phys);
-+      kfree(mp);
-+fail_free_mbox:
-+      mempool_free(mbox, phba->mbox_mem_pool);
-+
-+fail:
-+      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+      lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+              "%d (%d):0249 Cannot issue Register Fabric login\n",
-+              phba->brd_no, vport->vpi);
-+      return -ENXIO;
-+}
-+
-+static int
-+lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                         struct serv_parm *sp, IOCB_t *irsp)
-+{
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-+      struct lpfc_nodelist *np;
-+      struct lpfc_nodelist *next_np;
-+
-+      spin_lock_irq(shost->host_lock);
-+      vport->fc_flag |= FC_FABRIC;
-+      spin_unlock_irq(shost->host_lock);
-       phba->fc_edtov = be32_to_cpu(sp->cmn.e_d_tov);
-       if (sp->cmn.edtovResolution)    /* E_D_TOV ticks are in nanoseconds */
-@@ -258,20 +311,20 @@
-       phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000;
-       if (phba->fc_topology == TOPOLOGY_LOOP) {
--              spin_lock_irq(phba->host->host_lock);
--              phba->fc_flag |= FC_PUBLIC_LOOP;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-+              vport->fc_flag |= FC_PUBLIC_LOOP;
-+              spin_unlock_irq(shost->host_lock);
-       } else {
-               /*
-                * If we are a N-port connected to a Fabric, fixup sparam's so
-                * logins to devices on remote loops work.
-                */
--              phba->fc_sparam.cmn.altBbCredit = 1;
-+              vport->fc_sparam.cmn.altBbCredit = 1;
-       }
--      phba->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
-+      vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
-       memcpy(&ndlp->nlp_portname, &sp->portName, sizeof(struct lpfc_name));
--      memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
-+      memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof(struct lpfc_name));
-       ndlp->nlp_class_sup = 0;
-       if (sp->cls1.classValid)
-               ndlp->nlp_class_sup |= FC_COS_CLASS1;
-@@ -285,68 +338,85 @@
-                               sp->cmn.bbRcvSizeLsb;
-       memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
--      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
--      if (!mbox)
--              goto fail;
+-      /* otherwise remain at the current state */
+-      return last_idx;
+-}
+-
+-/**
+- * ladder_scan_device - scans a CPU's states and does setup
+- * @dev: the CPU
+- */
+-static void ladder_scan_device(struct cpuidle_device *dev)
+-{
+-      int i, bm_check = 0;
+-      struct ladder_device *ldev = dev->governor_data;
+-      struct ladder_device_state *lstate;
+-      struct cpuidle_state *state;
+-
+-      ldev->last_state_idx = 0;
+-      ldev->bm_check_timestamp = 0;
+-      ldev->bm_activity = 0;
+-
+-      for (i = 0; i < dev->state_count; i++) {
+-              state = &dev->states[i];
+-              lstate = &ldev->states[i];
+-
+-              lstate->stats.promotion_count = 0;
+-              lstate->stats.demotion_count = 0;
+-
+-              lstate->threshold.promotion_count = PROMOTION_COUNT;
+-              lstate->threshold.demotion_count = DEMOTION_COUNT;
+-
+-              if (i < dev->state_count - 1)
+-                      lstate->threshold.promotion_time = state->exit_latency;
+-              if (i > 0)
+-                      lstate->threshold.demotion_time = state->exit_latency;
+-              if (state->flags & CPUIDLE_FLAG_CHECK_BM) {
+-                      lstate->threshold.bm = bm_history;
+-                      bm_check = 1;
+-              } else
+-                      lstate->threshold.bm = 0;
+-      }
+-
+-      ldev->bm_check = bm_check;
+-}
+-
+-/**
+- * ladder_init_device - initializes a CPU-instance
+- * @dev: the CPU
+- */
+-static int ladder_init_device(struct cpuidle_device *dev)
+-{
+-      dev->governor_data = kmalloc(sizeof(struct ladder_device), GFP_KERNEL);
+-
+-      return !dev->governor_data;
+-}
+-
+-/**
+- * ladder_exit_device - exits a CPU-instance
+- * @dev: the CPU
+- */
+-static void ladder_exit_device(struct cpuidle_device *dev)
+-{
+-      kfree(dev->governor_data);
+-}
+-
+-static struct cpuidle_governor ladder_governor = {
+-      .name =         "ladder",
+-      .init =         ladder_init_device,
+-      .exit =         ladder_exit_device,
+-      .scan =         ladder_scan_device,
+-      .select =       ladder_select_state,
+-      .owner =        THIS_MODULE,
+-};
+-
+-/**
+- * init_ladder - initializes the governor
+- */
+-static int __init init_ladder(void)
+-{
+-      return cpuidle_register_governor(&ladder_governor);
+-}
+-
+-/**
+- * exit_ladder - exits the governor
+- */
+-static void __exit exit_ladder(void)
+-{
+-      cpuidle_unregister_governor(&ladder_governor);
+-}
+-
+-MODULE_LICENSE("GPL");
+-module_init(init_ladder);
+-module_exit(exit_ladder);
+diff -Nurb linux-2.6.22-590/drivers/cpuidle/governors/menu.c linux-2.6.22-570/drivers/cpuidle/governors/menu.c
+--- linux-2.6.22-590/drivers/cpuidle/governors/menu.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpuidle/governors/menu.c  1969-12-31 19:00:00.000000000 -0500
+@@ -1,152 +0,0 @@
+-/*
+- * menu.c - the menu idle governor
+- *
+- * Copyright (C) 2006-2007 Adam Belay <abelay@novell.com>
+- *
+- * This code is licenced under the GPL.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/cpuidle.h>
+-#include <linux/latency.h>
+-#include <linux/time.h>
+-#include <linux/ktime.h>
+-#include <linux/tick.h>
+-#include <linux/hrtimer.h>
+-
+-#define BM_HOLDOFF    20000   /* 20 ms */
+-
+-struct menu_device {
+-      int             last_state_idx;
+-      int             deepest_bm_state;
+-
+-      int             break_last_us;
+-      int             break_elapsed_us;
+-
+-      int             bm_elapsed_us;
+-      int             bm_holdoff_us;
+-
+-      unsigned long   idle_jiffies;
+-};
+-
+-static DEFINE_PER_CPU(struct menu_device, menu_devices);
+-
+-/**
+- * menu_select - selects the next idle state to enter
+- * @dev: the CPU
+- */
+-static int menu_select(struct cpuidle_device *dev)
+-{
+-      struct menu_device *data = &__get_cpu_var(menu_devices);
+-      int i, expected_us, max_state = dev->state_count;
+-
+-      /* discard BM history because it is sticky */
+-      cpuidle_get_bm_activity();
+-
+-      /* determine the expected residency time */
+-      expected_us = (s32) ktime_to_ns(tick_nohz_get_sleep_length()) / 1000;
+-      expected_us = min(expected_us, data->break_last_us);
+-
+-      /* determine the maximum state compatible with current BM status */
+-      if (cpuidle_get_bm_activity())
+-              data->bm_elapsed_us = 0;
+-      if (data->bm_elapsed_us <= data->bm_holdoff_us)
+-              max_state = data->deepest_bm_state + 1;
+-
+-      /* find the deepest idle state that satisfies our constraints */
+-      for (i = 1; i < max_state; i++) {
+-              struct cpuidle_state *s = &dev->states[i];
+-              if (s->target_residency > expected_us)
+-                      break;
+-              if (s->exit_latency > system_latency_constraint())
+-                      break;
+-      }
+-
+-      data->last_state_idx = i - 1;
+-      data->idle_jiffies = tick_nohz_get_idle_jiffies();
+-      return i - 1;
+-}
+-
+-/**
+- * menu_reflect - attempts to guess what happened after entry
+- * @dev: the CPU
+- *
+- * NOTE: it's important to be fast here because this operation will add to
+- *       the overall exit latency.
+- */
+-static void menu_reflect(struct cpuidle_device *dev)
+-{
+-      struct menu_device *data = &__get_cpu_var(menu_devices);
+-      int last_idx = data->last_state_idx;
+-      int measured_us = cpuidle_get_last_residency(dev);
+-      struct cpuidle_state *target = &dev->states[last_idx];
+-
+-      /*
+-       * Ugh, this idle state doesn't support residency measurements, so we
+-       * are basically lost in the dark.  As a compromise, assume we slept
+-       * for one full standard timer tick.  However, be aware that this
+-       * could potentially result in a suboptimal state transition.
+-       */
+-      if (!(target->flags & CPUIDLE_FLAG_TIME_VALID))
+-              measured_us = USEC_PER_SEC / HZ;
+-
+-      data->bm_elapsed_us += measured_us;
+-      data->break_elapsed_us += measured_us;
+-
+-      /*
+-       * Did something other than the timer interrupt cause the break event?
+-       */
+-      if (tick_nohz_get_idle_jiffies() == data->idle_jiffies) {
+-              data->break_last_us = data->break_elapsed_us;
+-              data->break_elapsed_us = 0;
+-      }
+-}
+-
+-/**
+- * menu_scan_device - scans a CPU's states and does setup
+- * @dev: the CPU
+- */
+-static void menu_scan_device(struct cpuidle_device *dev)
+-{
+-      struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
+-      int i;
+-
+-      data->last_state_idx = 0;
+-      data->break_last_us = 0;
+-      data->break_elapsed_us = 0;
+-      data->bm_elapsed_us = 0;
+-      data->bm_holdoff_us = BM_HOLDOFF;
+-
+-      for (i = 1; i < dev->state_count; i++)
+-              if (dev->states[i].flags & CPUIDLE_FLAG_CHECK_BM)
+-                      break;
+-      data->deepest_bm_state = i - 1;
+-}
+-
+-struct cpuidle_governor menu_governor = {
+-      .name =         "menu",
+-      .scan =         menu_scan_device,
+-      .select =       menu_select,
+-      .reflect =      menu_reflect,
+-      .owner =        THIS_MODULE,
+-};
 -
--      phba->hba_state = LPFC_FABRIC_CFG_LINK;
--      lpfc_config_link(phba, mbox);
--      mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-/**
+- * init_menu - initializes the governor
+- */
+-static int __init init_menu(void)
+-{
+-      return cpuidle_register_governor(&menu_governor);
+-}
 -
--      rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
--      if (rc == MBX_NOT_FINISHED)
--              goto fail_free_mbox;
-+      if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
-+              if (sp->cmn.response_multiple_NPort) {
-+                      lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT,
-+                                      "%d:1816 FLOGI NPIV supported, "
-+                                      "response data 0x%x\n",
-+                                      phba->brd_no,
-+                                      sp->cmn.response_multiple_NPort);
-+                      phba->link_flag |= LS_NPIV_FAB_SUPPORTED;
--      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
--      if (!mbox)
--              goto fail;
-+              } else {
-+                      /* Because we asked f/w for NPIV it still expects us
-+                         to call reg_vnpid atleast for the physcial host */
-+                      lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT,
-+                                      "%d:1817 Fabric does not support NPIV "
-+                                      "- configuring single port mode.\n",
-+                                      phba->brd_no);
-+                      phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
-+              }
-+      }
--      if (lpfc_reg_login(phba, Fabric_DID, (uint8_t *) sp, mbox, 0))
--              goto fail_free_mbox;
-+      if ((vport->fc_prevDID != vport->fc_myDID) &&
-+              !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
--      mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
--      mbox->context2 = lpfc_nlp_get(ndlp);
-+              /* If our NportID changed, we need to ensure all
-+               * remaining NPORTs get unreg_login'ed.
-+               */
-+              list_for_each_entry_safe(np, next_np,
-+                                      &vport->fc_nodes, nlp_listp) {
-+                      if ((np->nlp_state != NLP_STE_NPR_NODE) ||
-+                                 !(np->nlp_flag & NLP_NPR_ADISC))
-+                              continue;
-+                      spin_lock_irq(shost->host_lock);
-+                      np->nlp_flag &= ~NLP_NPR_ADISC;
-+                      spin_unlock_irq(shost->host_lock);
-+                      lpfc_unreg_rpi(vport, np);
-+              }
-+              if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
-+                      lpfc_mbx_unreg_vpi(vport);
-+                      vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
-+              }
-+      }
--      rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
--      if (rc == MBX_NOT_FINISHED)
--              goto fail_issue_reg_login;
-+      ndlp->nlp_sid = irsp->un.ulpWord[4] & Mask_DID;
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE);
-+      if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED &&
-+          vport->fc_flag & FC_VPORT_NEEDS_REG_VPI) {
-+              lpfc_register_new_vport(phba, vport, ndlp);
-+              return 0;
-+      }
-+      lpfc_issue_fabric_reglogin(vport);
-       return 0;
+-/**
+- * exit_menu - exits the governor
+- */
+-static void __exit exit_menu(void)
+-{
+-      cpuidle_unregister_governor(&menu_governor);
+-}
 -
-- fail_issue_reg_login:
--      lpfc_nlp_put(ndlp);
--      mp = (struct lpfc_dmabuf *) mbox->context1;
--      lpfc_mbuf_free(phba, mp->virt, mp->phys);
--      kfree(mp);
-- fail_free_mbox:
--      mempool_free(mbox, phba->mbox_mem_pool);
-- fail:
--      return -ENXIO;
- }
- /*
-  * We FLOGIed into an NPort, initiate pt2pt protocol
-  */
- static int
--lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
-+lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-               struct serv_parm *sp)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-       LPFC_MBOXQ_t *mbox;
-       int rc;
--      spin_lock_irq(phba->host->host_lock);
--      phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-+      vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
-+      spin_unlock_irq(shost->host_lock);
-       phba->fc_edtov = FF_DEF_EDTOV;
-       phba->fc_ratov = FF_DEF_RATOV;
--      rc = memcmp(&phba->fc_portname, &sp->portName,
--                      sizeof(struct lpfc_name));
-+      rc = memcmp(&vport->fc_portname, &sp->portName,
-+                  sizeof(vport->fc_portname));
-       if (rc >= 0) {
-               /* This side will initiate the PLOGI */
--              spin_lock_irq(phba->host->host_lock);
--              phba->fc_flag |= FC_PT2PT_PLOGI;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-+              vport->fc_flag |= FC_PT2PT_PLOGI;
-+              spin_unlock_irq(shost->host_lock);
-               /*
-                * N_Port ID cannot be 0, set our to LocalID the other
-@@ -355,7 +425,7 @@
-               /* not equal */
-               if (rc)
--                      phba->fc_myDID = PT2PT_LocalID;
-+                      vport->fc_myDID = PT2PT_LocalID;
-               mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-               if (!mbox)
-@@ -364,6 +434,7 @@
-               lpfc_config_link(phba, mbox);
-               mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-+              mbox->vport = vport;
-               rc = lpfc_sli_issue_mbox(phba, mbox,
-                               MBX_NOWAIT | MBX_STOP_IOCB);
-               if (rc == MBX_NOT_FINISHED) {
-@@ -372,7 +443,7 @@
-               }
-               lpfc_nlp_put(ndlp);
--              ndlp = lpfc_findnode_did(phba, PT2PT_RemoteID);
-+              ndlp = lpfc_findnode_did(vport, PT2PT_RemoteID);
-               if (!ndlp) {
-                       /*
-                        * Cannot find existing Fabric ndlp, so allocate a
-@@ -382,28 +453,30 @@
-                       if (!ndlp)
-                               goto fail;
--                      lpfc_nlp_init(phba, ndlp, PT2PT_RemoteID);
-+                      lpfc_nlp_init(vport, ndlp, PT2PT_RemoteID);
-               }
-               memcpy(&ndlp->nlp_portname, &sp->portName,
-                               sizeof(struct lpfc_name));
-               memcpy(&ndlp->nlp_nodename, &sp->nodeName,
-                               sizeof(struct lpfc_name));
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
-+              spin_unlock_irq(shost->host_lock);
-       } else {
-               /* This side will wait for the PLOGI */
-               lpfc_nlp_put(ndlp);
-       }
--      spin_lock_irq(phba->host->host_lock);
--      phba->fc_flag |= FC_PT2PT;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-+      vport->fc_flag |= FC_PT2PT;
-+      spin_unlock_irq(shost->host_lock);
-       /* Start discovery - this should just do CLEAR_LA */
--      lpfc_disc_start(phba);
-+      lpfc_disc_start(vport);
-       return 0;
-- fail:
-+fail:
-       return -ENXIO;
- }
-@@ -411,6 +484,8 @@
- lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-                   struct lpfc_iocbq *rspiocb)
- {
-+      struct lpfc_vport *vport = cmdiocb->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-       IOCB_t *irsp = &rspiocb->iocb;
-       struct lpfc_nodelist *ndlp = cmdiocb->context1;
-       struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp;
-@@ -418,21 +493,25 @@
-       int rc;
-       /* Check to see if link went down during discovery */
--      if (lpfc_els_chk_latt(phba)) {
-+      if (lpfc_els_chk_latt(vport)) {
-               lpfc_nlp_put(ndlp);
-               goto out;
-       }
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "FLOGI cmpl:      status:x%x/x%x state:x%x",
-+              irsp->ulpStatus, irsp->un.ulpWord[4],
-+              vport->port_state);
-+
-       if (irsp->ulpStatus) {
-               /* Check for retry */
--              if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
--                      /* ELS command is being retried */
-+              if (lpfc_els_retry(phba, cmdiocb, rspiocb))
-                       goto out;
+-MODULE_LICENSE("GPL");
+-module_init(init_menu);
+-module_exit(exit_menu);
+diff -Nurb linux-2.6.22-590/drivers/cpuidle/sysfs.c linux-2.6.22-570/drivers/cpuidle/sysfs.c
+--- linux-2.6.22-590/drivers/cpuidle/sysfs.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/cpuidle/sysfs.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,393 +0,0 @@
+-/*
+- * sysfs.c - sysfs support
+- *
+- * (C) 2006-2007 Shaohua Li <shaohua.li@intel.com>
+- *
+- * This code is licenced under the GPL.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/cpuidle.h>
+-#include <linux/sysfs.h>
+-#include <linux/cpu.h>
+-
+-#include "cpuidle.h"
+-
+-static unsigned int sysfs_switch;
+-static int __init cpuidle_sysfs_setup(char *unused)
+-{
+-      sysfs_switch = 1;
+-      return 1;
+-}
+-__setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup);
+-
+-static ssize_t show_available_drivers(struct sys_device *dev, char *buf)
+-{
+-      ssize_t i = 0;
+-      struct cpuidle_driver *tmp;
+-
+-      mutex_lock(&cpuidle_lock);
+-      list_for_each_entry(tmp, &cpuidle_drivers, driver_list) {
+-              if (i >= (ssize_t)((PAGE_SIZE/sizeof(char)) - CPUIDLE_NAME_LEN - 2))
+-                      goto out;
+-              i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name);
+-      }
+-out:
+-      i+= sprintf(&buf[i], "\n");
+-      mutex_unlock(&cpuidle_lock);
+-      return i;
+-}
+-
+-static ssize_t show_available_governors(struct sys_device *dev, char *buf)
+-{
+-      ssize_t i = 0;
+-      struct cpuidle_governor *tmp;
+-
+-      mutex_lock(&cpuidle_lock);
+-      list_for_each_entry(tmp, &cpuidle_governors, governor_list) {
+-              if (i >= (ssize_t)((PAGE_SIZE/sizeof(char)) - CPUIDLE_NAME_LEN - 2))
+-                      goto out;
+-              i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name);
+-      }
+-      if (list_empty(&cpuidle_governors))
+-              i+= sprintf(&buf[i], "no governors");
+-out:
+-      i+= sprintf(&buf[i], "\n");
+-      mutex_unlock(&cpuidle_lock);
+-      return i;
+-}
+-
+-static ssize_t show_current_driver(struct sys_device *dev, char *buf)
+-{
+-      ssize_t ret;
+-
+-      mutex_lock(&cpuidle_lock);
+-      ret = sprintf(buf, "%s\n", cpuidle_curr_driver->name);
+-      mutex_unlock(&cpuidle_lock);
+-      return ret;
+-}
+-
+-static ssize_t store_current_driver(struct sys_device *dev,
+-      const char *buf, size_t count)
+-{
+-      char str[CPUIDLE_NAME_LEN];
+-      int len = count;
+-      struct cpuidle_driver *tmp, *found = NULL;
+-
+-      if (len > CPUIDLE_NAME_LEN)
+-              len = CPUIDLE_NAME_LEN;
+-
+-      if (sscanf(buf, "%s", str) != 1)
+-              return -EINVAL;
+-
+-      mutex_lock(&cpuidle_lock);
+-      list_for_each_entry(tmp, &cpuidle_drivers, driver_list) {
+-              if (strncmp(tmp->name, str, CPUIDLE_NAME_LEN) == 0) {
+-                      found = tmp;
+-                      break;
 -              }
-+
-               /* FLOGI failed, so there is no fabric */
--              spin_lock_irq(phba->host->host_lock);
--              phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-+              vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
-+              spin_unlock_irq(shost->host_lock);
-               /* If private loop, then allow max outstanding els to be
-                * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no
-@@ -443,11 +522,10 @@
-               }
-               /* FLOGI failure */
--              lpfc_printf_log(phba,
--                              KERN_INFO,
--                              LOG_ELS,
--                              "%d:0100 FLOGI failure Data: x%x x%x x%x\n",
--                              phba->brd_no,
-+              lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-+                              "%d (%d):0100 FLOGI failure Data: x%x x%x "
-+                              "x%x\n",
-+                              phba->brd_no, vport->vpi,
-                               irsp->ulpStatus, irsp->un.ulpWord[4],
-                               irsp->ulpTimeout);
-               goto flogifail;
-@@ -463,21 +541,21 @@
-       /* FLOGI completes successfully */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0101 FLOGI completes sucessfully "
-+                      "%d (%d):0101 FLOGI completes sucessfully "
-                       "Data: x%x x%x x%x x%x\n",
--                      phba->brd_no,
-+                      phba->brd_no, vport->vpi,
-                       irsp->un.ulpWord[4], sp->cmn.e_d_tov,
-                       sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution);
--      if (phba->hba_state == LPFC_FLOGI) {
-+      if (vport->port_state == LPFC_FLOGI) {
-               /*
-                * If Common Service Parameters indicate Nport
-                * we are point to point, if Fport we are Fabric.
-                */
-               if (sp->cmn.fPort)
--                      rc = lpfc_cmpl_els_flogi_fabric(phba, ndlp, sp, irsp);
-+                      rc = lpfc_cmpl_els_flogi_fabric(vport, ndlp, sp, irsp);
-               else
--                      rc = lpfc_cmpl_els_flogi_nport(phba, ndlp, sp);
-+                      rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp);
-               if (!rc)
-                       goto out;
-@@ -486,14 +564,12 @@
- flogifail:
-       lpfc_nlp_put(ndlp);
--      if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
--          (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED &&
--           irsp->un.ulpWord[4] != IOERR_SLI_DOWN)) {
-+      if (!lpfc_error_lost_link(irsp)) {
-               /* FLOGI failed, so just use loop map to make discovery list */
--              lpfc_disc_list_loopmap(phba);
-+              lpfc_disc_list_loopmap(vport);
-               /* Start discovery */
--              lpfc_disc_start(phba);
-+              lpfc_disc_start(vport);
-       }
- out:
-@@ -501,9 +577,10 @@
- }
- static int
--lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
-+lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-                    uint8_t retry)
- {
-+      struct lpfc_hba  *phba = vport->phba;
-       struct serv_parm *sp;
-       IOCB_t *icmd;
-       struct lpfc_iocbq *elsiocb;
-@@ -515,9 +592,10 @@
-       pring = &phba->sli.ring[LPFC_ELS_RING];
--      cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
--      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
-+      cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
-+      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
-                                                ndlp->nlp_DID, ELS_CMD_FLOGI);
-+
-       if (!elsiocb)
-               return 1;
-@@ -526,8 +604,8 @@
-       /* For FLOGI request, remainder of payload is service parameters */
-       *((uint32_t *) (pcmd)) = ELS_CMD_FLOGI;
--      pcmd += sizeof (uint32_t);
--      memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
-+      pcmd += sizeof(uint32_t);
-+      memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
-       sp = (struct serv_parm *) pcmd;
-       /* Setup CSPs accordingly for Fabric */
-@@ -541,16 +619,32 @@
-       if (sp->cmn.fcphHigh < FC_PH3)
-               sp->cmn.fcphHigh = FC_PH3;
-+      if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
-+              sp->cmn.request_multiple_Nport = 1;
-+
-+              /* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */
-+              icmd->ulpCt_h = 1;
-+              icmd->ulpCt_l = 0;
-+      }
-+
-+      if (phba->fc_topology != TOPOLOGY_LOOP) {
-+              icmd->un.elsreq64.myID = 0;
-+              icmd->un.elsreq64.fl = 1;
-+      }
-+
-       tmo = phba->fc_ratov;
-       phba->fc_ratov = LPFC_DISC_FLOGI_TMO;
--      lpfc_set_disctmo(phba);
-+      lpfc_set_disctmo(vport);
-       phba->fc_ratov = tmo;
-       phba->fc_stat.elsXmitFLOGI++;
-       elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;
--      spin_lock_irq(phba->host->host_lock);
--      rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
--      spin_unlock_irq(phba->host->host_lock);
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "Issue FLOGI:     opt:x%x",
-+              phba->sli3_options, 0, 0);
-+
-+      rc = lpfc_issue_fabric_iocb(phba, elsiocb);
-       if (rc == IOCB_ERROR) {
-               lpfc_els_free_iocb(phba, elsiocb);
-               return 1;
-@@ -559,7 +653,7 @@
- }
- int
--lpfc_els_abort_flogi(struct lpfc_hba * phba)
-+lpfc_els_abort_flogi(struct lpfc_hba *phba)
- {
-       struct lpfc_sli_ring *pring;
-       struct lpfc_iocbq *iocb, *next_iocb;
-@@ -577,73 +671,99 @@
-        * Check the txcmplq for an iocb that matches the nport the driver is
-        * searching for.
-        */
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
-               icmd = &iocb->iocb;
--              if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
-+              if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
-+                  icmd->un.elsreq64.bdl.ulpIoTag32) {
-                       ndlp = (struct lpfc_nodelist *)(iocb->context1);
--                      if (ndlp && (ndlp->nlp_DID == Fabric_DID))
-+                      if (ndlp && (ndlp->nlp_DID == Fabric_DID)) {
-                               lpfc_sli_issue_abort_iotag(phba, pring, iocb);
-               }
-       }
--      spin_unlock_irq(phba->host->host_lock);
-+      }
-+      spin_unlock_irq(&phba->hbalock);
-       return 0;
- }
- int
--lpfc_initial_flogi(struct lpfc_hba *phba)
-+lpfc_initial_flogi(struct lpfc_vport *vport)
- {
-+      struct lpfc_hba *phba = vport->phba;
-       struct lpfc_nodelist *ndlp;
-       /* First look for the Fabric ndlp */
--      ndlp = lpfc_findnode_did(phba, Fabric_DID);
-+      ndlp = lpfc_findnode_did(vport, Fabric_DID);
-       if (!ndlp) {
-               /* Cannot find existing Fabric ndlp, so allocate a new one */
-               ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
-               if (!ndlp)
-                       return 0;
--              lpfc_nlp_init(phba, ndlp, Fabric_DID);
-+              lpfc_nlp_init(vport, ndlp, Fabric_DID);
-       } else {
--              lpfc_dequeue_node(phba, ndlp);
-+              lpfc_dequeue_node(vport, ndlp);
-       }
--      if (lpfc_issue_els_flogi(phba, ndlp, 0)) {
-+      if (lpfc_issue_els_flogi(vport, ndlp, 0)) {
-               lpfc_nlp_put(ndlp);
-       }
-       return 1;
- }
-+int
-+lpfc_initial_fdisc(struct lpfc_vport *vport)
-+{
-+      struct lpfc_hba *phba = vport->phba;
-+      struct lpfc_nodelist *ndlp;
-+
-+      /* First look for the Fabric ndlp */
-+      ndlp = lpfc_findnode_did(vport, Fabric_DID);
-+      if (!ndlp) {
-+              /* Cannot find existing Fabric ndlp, so allocate a new one */
-+              ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
-+              if (!ndlp)
-+                      return 0;
-+              lpfc_nlp_init(vport, ndlp, Fabric_DID);
-+      } else {
-+              lpfc_dequeue_node(vport, ndlp);
-+      }
-+      if (lpfc_issue_els_fdisc(vport, ndlp, 0)) {
-+              lpfc_nlp_put(ndlp);
-+      }
-+      return 1;
-+}
- static void
--lpfc_more_plogi(struct lpfc_hba * phba)
-+lpfc_more_plogi(struct lpfc_vport *vport)
- {
-       int sentplogi;
-+      struct lpfc_hba *phba = vport->phba;
--      if (phba->num_disc_nodes)
--              phba->num_disc_nodes--;
-+      if (vport->num_disc_nodes)
-+              vport->num_disc_nodes--;
-       /* Continue discovery with <num_disc_nodes> PLOGIs to go */
-       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                      "%d:0232 Continue discovery with %d PLOGIs to go "
-+                      "%d (%d):0232 Continue discovery with %d PLOGIs to go "
-                       "Data: x%x x%x x%x\n",
--                      phba->brd_no, phba->num_disc_nodes, phba->fc_plogi_cnt,
--                      phba->fc_flag, phba->hba_state);
-+                      phba->brd_no, vport->vpi, vport->num_disc_nodes,
-+                      vport->fc_plogi_cnt, vport->fc_flag, vport->port_state);
-       /* Check to see if there are more PLOGIs to be sent */
--      if (phba->fc_flag & FC_NLP_MORE) {
--              /* go thru NPR list and issue any remaining ELS PLOGIs */
--              sentplogi = lpfc_els_disc_plogi(phba);
 -      }
-+      if (vport->fc_flag & FC_NLP_MORE)
-+              /* go thru NPR nodes and issue any remaining ELS PLOGIs */
-+              sentplogi = lpfc_els_disc_plogi(vport);
-+
-       return;
- }
- static struct lpfc_nodelist *
--lpfc_plogi_confirm_nport(struct lpfc_hba *phba, struct lpfc_dmabuf *prsp,
-+lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
-                        struct lpfc_nodelist *ndlp)
- {
-+      struct lpfc_vport    *vport = ndlp->vport;
-       struct lpfc_nodelist *new_ndlp;
--      uint32_t *lp;
-       struct serv_parm *sp;
--      uint8_t name[sizeof (struct lpfc_name)];
-+      uint8_t  name[sizeof(struct lpfc_name)];
-       uint32_t rc;
-       /* Fabric nodes can have the same WWPN so we don't bother searching
-@@ -652,50 +772,51 @@
-       if (ndlp->nlp_type & NLP_FABRIC)
-               return ndlp;
--      lp = (uint32_t *) prsp->virt;
--      sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
-+      sp = (struct serv_parm *) ((uint8_t *) prsp + sizeof(uint32_t));
-       memset(name, 0, sizeof(struct lpfc_name));
-       /* Now we find out if the NPort we are logging into, matches the WWPN
-        * we have for that ndlp. If not, we have some work to do.
-        */
--      new_ndlp = lpfc_findnode_wwpn(phba, &sp->portName);
-+      new_ndlp = lpfc_findnode_wwpn(vport, &sp->portName);
-       if (new_ndlp == ndlp)
-               return ndlp;
-       if (!new_ndlp) {
--              rc =
--                 memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name));
-+              rc = memcmp(&ndlp->nlp_portname, name,
-+                          sizeof(struct lpfc_name));
-               if (!rc)
-                       return ndlp;
-               new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
-               if (!new_ndlp)
-                       return ndlp;
--              lpfc_nlp_init(phba, new_ndlp, ndlp->nlp_DID);
-+              lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID);
-       }
--      lpfc_unreg_rpi(phba, new_ndlp);
-+      lpfc_unreg_rpi(vport, new_ndlp);
-       new_ndlp->nlp_DID = ndlp->nlp_DID;
-       new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
--      lpfc_nlp_set_state(phba, new_ndlp, ndlp->nlp_state);
-+      lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state);
--      /* Move this back to NPR list */
-+      /* Move this back to NPR state */
-       if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0)
--              lpfc_drop_node(phba, ndlp);
-+              lpfc_drop_node(vport, ndlp);
-       else {
--              lpfc_unreg_rpi(phba, ndlp);
-+              lpfc_unreg_rpi(vport, ndlp);
-               ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-       }
-       return new_ndlp;
- }
- static void
--lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                  struct lpfc_iocbq * rspiocb)
-+lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                  struct lpfc_iocbq *rspiocb)
- {
-+      struct lpfc_vport *vport = cmdiocb->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-       IOCB_t *irsp;
-       struct lpfc_nodelist *ndlp;
-       struct lpfc_dmabuf *prsp;
-@@ -705,32 +826,43 @@
-       cmdiocb->context_un.rsp_iocb = rspiocb;
-       irsp = &rspiocb->iocb;
--      ndlp = lpfc_findnode_did(phba, irsp->un.elsreq64.remoteID);
--      if (!ndlp)
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "PLOGI cmpl:      status:x%x/x%x did:x%x",
-+              irsp->ulpStatus, irsp->un.ulpWord[4],
-+              irsp->un.elsreq64.remoteID);
-+
-+      ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
-+      if (!ndlp) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                      "%d (%d):0136 PLOGI completes to NPort x%x "
-+                      "with no ndlp. Data: x%x x%x x%x\n",
-+                      phba->brd_no, vport->vpi, irsp->un.elsreq64.remoteID,
-+                      irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpIoTag);
-               goto out;
-+      }
-       /* Since ndlp can be freed in the disc state machine, note if this node
-        * is being used during discovery.
-        */
-+      spin_lock_irq(shost->host_lock);
-       disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
--      spin_lock_irq(phba->host->host_lock);
-       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
-       rc   = 0;
-       /* PLOGI completes to NPort <nlp_DID> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0102 PLOGI completes to NPort x%x "
-+                      "%d (%d):0102 PLOGI completes to NPort x%x "
-                       "Data: x%x x%x x%x x%x x%x\n",
--                      phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
--                      irsp->un.ulpWord[4], irsp->ulpTimeout, disc,
--                      phba->num_disc_nodes);
-+                      phba->brd_no, vport->vpi, ndlp->nlp_DID,
-+                      irsp->ulpStatus, irsp->un.ulpWord[4],
-+                      irsp->ulpTimeout, disc, vport->num_disc_nodes);
-       /* Check to see if link went down during discovery */
--      if (lpfc_els_chk_latt(phba)) {
--              spin_lock_irq(phba->host->host_lock);
-+      if (lpfc_els_chk_latt(vport)) {
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-               goto out;
-       }
-@@ -743,22 +875,28 @@
-               if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
-                       /* ELS command is being retried */
-                       if (disc) {
--                              spin_lock_irq(phba->host->host_lock);
-+                              spin_lock_irq(shost->host_lock);
-                               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
--                              spin_unlock_irq(phba->host->host_lock);
-+                              spin_unlock_irq(shost->host_lock);
-                       }
-                       goto out;
-               }
-               /* PLOGI failed */
-+              if (ndlp->nlp_DID == NameServer_DID) {
-+                      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                              "%d (%d):0250 Nameserver login error: "
-+                              "0x%x / 0x%x\n",
-+                              phba->brd_no, vport->vpi,
-+                              irsp->ulpStatus, irsp->un.ulpWord[4]);
-+              }
-+
-               /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
--              if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
--                 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
--                 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
--                 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
-+              if (lpfc_error_lost_link(irsp)) {
-                       rc = NLP_STE_FREED_NODE;
-               } else {
--                      rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
-+                      rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb,
-                                       NLP_EVT_CMPL_PLOGI);
-               }
-       } else {
-@@ -766,33 +904,33 @@
-               prsp = list_entry(((struct lpfc_dmabuf *)
-                       cmdiocb->context2)->list.next,
-                       struct lpfc_dmabuf, list);
--              ndlp = lpfc_plogi_confirm_nport(phba, prsp, ndlp);
--              rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
-+              ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp);
-+              rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb,
-                                       NLP_EVT_CMPL_PLOGI);
-       }
--      if (disc && phba->num_disc_nodes) {
-+      if (disc && vport->num_disc_nodes) {
-               /* Check to see if there are more PLOGIs to be sent */
--              lpfc_more_plogi(phba);
-+              lpfc_more_plogi(vport);
--              if (phba->num_disc_nodes == 0) {
--                      spin_lock_irq(phba->host->host_lock);
--                      phba->fc_flag &= ~FC_NDISC_ACTIVE;
--                      spin_unlock_irq(phba->host->host_lock);
-+              if (vport->num_disc_nodes == 0) {
-+                      spin_lock_irq(shost->host_lock);
-+                      vport->fc_flag &= ~FC_NDISC_ACTIVE;
-+                      spin_unlock_irq(shost->host_lock);
--                      lpfc_can_disctmo(phba);
--                      if (phba->fc_flag & FC_RSCN_MODE) {
-+                      lpfc_can_disctmo(vport);
-+                      if (vport->fc_flag & FC_RSCN_MODE) {
-                               /*
-                                * Check to see if more RSCNs came in while
-                                * we were processing this one.
-                                */
--                              if ((phba->fc_rscn_id_cnt == 0) &&
--                              (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
--                                      spin_lock_irq(phba->host->host_lock);
--                                      phba->fc_flag &= ~FC_RSCN_MODE;
--                                      spin_unlock_irq(phba->host->host_lock);
-+                              if ((vport->fc_rscn_id_cnt == 0) &&
-+                                  (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
-+                                      spin_lock_irq(shost->host_lock);
-+                                      vport->fc_flag &= ~FC_RSCN_MODE;
-+                                      spin_unlock_irq(shost->host_lock);
-                               } else {
--                                      lpfc_els_handle_rscn(phba);
-+                                      lpfc_els_handle_rscn(vport);
-                               }
-                       }
-               }
-@@ -804,8 +942,9 @@
- }
- int
--lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry)
-+lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
- {
-+      struct lpfc_hba  *phba = vport->phba;
-       struct serv_parm *sp;
-       IOCB_t *icmd;
-       struct lpfc_iocbq *elsiocb;
-@@ -813,12 +952,13 @@
-       struct lpfc_sli *psli;
-       uint8_t *pcmd;
-       uint16_t cmdsize;
-+      int ret;
-       psli = &phba->sli;
-       pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
--      cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
--      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, NULL, did,
-+      cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
-+      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, NULL, did,
-                                                               ELS_CMD_PLOGI);
-       if (!elsiocb)
-               return 1;
-@@ -828,8 +968,8 @@
-       /* For PLOGI request, remainder of payload is service parameters */
-       *((uint32_t *) (pcmd)) = ELS_CMD_PLOGI;
--      pcmd += sizeof (uint32_t);
--      memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
-+      pcmd += sizeof(uint32_t);
-+      memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
-       sp = (struct serv_parm *) pcmd;
-       if (sp->cmn.fcphLow < FC_PH_4_3)
-@@ -838,22 +978,27 @@
-       if (sp->cmn.fcphHigh < FC_PH3)
-               sp->cmn.fcphHigh = FC_PH3;
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "Issue PLOGI:     did:x%x",
-+              did, 0, 0);
-+
-       phba->fc_stat.elsXmitPLOGI++;
-       elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
--      spin_lock_irq(phba->host->host_lock);
--      if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
--              spin_unlock_irq(phba->host->host_lock);
-+      ret = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
-+
-+      if (ret == IOCB_ERROR) {
-               lpfc_els_free_iocb(phba, elsiocb);
-               return 1;
-       }
--      spin_unlock_irq(phba->host->host_lock);
-       return 0;
- }
- static void
--lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                 struct lpfc_iocbq * rspiocb)
-+lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                 struct lpfc_iocbq *rspiocb)
- {
-+      struct lpfc_vport *vport = cmdiocb->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-       IOCB_t *irsp;
-       struct lpfc_sli *psli;
-       struct lpfc_nodelist *ndlp;
-@@ -864,21 +1009,26 @@
+-      if (found)
+-              cpuidle_switch_driver(found);
+-      mutex_unlock(&cpuidle_lock);
+-
+-      return count;
+-}
+-
+-static ssize_t show_current_governor(struct sys_device *dev, char *buf)
+-{
+-      ssize_t i;
+-
+-      mutex_lock(&cpuidle_lock);
+-      if (cpuidle_curr_governor)
+-              i = sprintf(buf, "%s\n", cpuidle_curr_governor->name);
+-      else
+-              i = sprintf(buf, "no governor\n");
+-      mutex_unlock(&cpuidle_lock);
+-
+-      return i;
+-}
+-
+-static ssize_t store_current_governor(struct sys_device *dev,
+-      const char *buf, size_t count)
+-{
+-      char str[CPUIDLE_NAME_LEN];
+-      int len = count;
+-      struct cpuidle_governor *tmp, *found = NULL;
+-
+-      if (len > CPUIDLE_NAME_LEN)
+-              len = CPUIDLE_NAME_LEN;
+-
+-      if (sscanf(buf, "%s", str) != 1)
+-              return -EINVAL;
+-
+-      mutex_lock(&cpuidle_lock);
+-      list_for_each_entry(tmp, &cpuidle_governors, governor_list) {
+-              if (strncmp(tmp->name, str, CPUIDLE_NAME_LEN) == 0) {
+-                      found = tmp;
+-                      break;
+-              }
+-      }
+-      if (found)
+-              cpuidle_switch_governor(found);
+-      mutex_unlock(&cpuidle_lock);
+-
+-      return count;
+-}
+-
+-static SYSDEV_ATTR(current_driver_ro, 0444, show_current_driver, NULL);
+-static SYSDEV_ATTR(current_governor_ro, 0444, show_current_governor, NULL);
+-
+-static struct attribute *cpuclass_default_attrs[] = {
+-      &attr_current_driver_ro.attr,
+-      &attr_current_governor_ro.attr,
+-      NULL
+-};
+-
+-static SYSDEV_ATTR(available_drivers, 0444, show_available_drivers, NULL);
+-static SYSDEV_ATTR(available_governors, 0444, show_available_governors, NULL);
+-static SYSDEV_ATTR(current_driver, 0644, show_current_driver,
+-      store_current_driver);
+-static SYSDEV_ATTR(current_governor, 0644, show_current_governor,
+-      store_current_governor);
+-
+-static struct attribute *cpuclass_switch_attrs[] = {
+-      &attr_available_drivers.attr,
+-      &attr_available_governors.attr,
+-      &attr_current_driver.attr,
+-      &attr_current_governor.attr,
+-      NULL
+-};
+-
+-static struct attribute_group cpuclass_attr_group = {
+-      .attrs = cpuclass_default_attrs,
+-      .name = "cpuidle",
+-};
+-
+-/**
+- * cpuidle_add_class_sysfs - add CPU global sysfs attributes
+- */
+-int cpuidle_add_class_sysfs(struct sysdev_class *cls)
+-{
+-      if (sysfs_switch)
+-              cpuclass_attr_group.attrs = cpuclass_switch_attrs;
+-
+-      return sysfs_create_group(&cls->kset.kobj, &cpuclass_attr_group);
+-}
+-
+-/**
+- * cpuidle_remove_class_sysfs - remove CPU global sysfs attributes
+- */
+-void cpuidle_remove_class_sysfs(struct sysdev_class *cls)
+-{
+-      sysfs_remove_group(&cls->kset.kobj, &cpuclass_attr_group);
+-}
+-
+-struct cpuidle_attr {
+-      struct attribute attr;
+-      ssize_t (*show)(struct cpuidle_device *, char *);
+-      ssize_t (*store)(struct cpuidle_device *, const char *, size_t count);
+-};
+-
+-#define define_one_ro(_name, show) \
+-      static struct cpuidle_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
+-#define define_one_rw(_name, show, store) \
+-      static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store)
+-
+-#define kobj_to_cpuidledev(k) container_of(k, struct cpuidle_device, kobj)
+-#define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr)
+-static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char * buf)
+-{
+-      int ret = -EIO;
+-      struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+-      struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
+-
+-      if (cattr->show) {
+-              mutex_lock(&cpuidle_lock);
+-              ret = cattr->show(dev, buf);
+-              mutex_unlock(&cpuidle_lock);
+-      }
+-      return ret;
+-}
+-
+-static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr,
+-                   const char * buf, size_t count)
+-{
+-      int ret = -EIO;
+-      struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+-      struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
+-
+-      if (cattr->store) {
+-              mutex_lock(&cpuidle_lock);
+-              ret = cattr->store(dev, buf, count);
+-              mutex_unlock(&cpuidle_lock);
+-      }
+-      return ret;
+-}
+-
+-static struct sysfs_ops cpuidle_sysfs_ops = {
+-      .show = cpuidle_show,
+-      .store = cpuidle_store,
+-};
+-
+-static void cpuidle_sysfs_release(struct kobject *kobj)
+-{
+-      struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+-
+-      complete(&dev->kobj_unregister);
+-}
+-
+-static struct kobj_type ktype_cpuidle = {
+-      .sysfs_ops = &cpuidle_sysfs_ops,
+-      .release = cpuidle_sysfs_release,
+-};
+-
+-struct cpuidle_state_attr {
+-      struct attribute attr;
+-      ssize_t (*show)(struct cpuidle_state *, char *);
+-      ssize_t (*store)(struct cpuidle_state *, const char *, size_t);
+-};
+-
+-#define define_one_state_ro(_name, show) \
+-static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
+-
+-#define define_show_state_function(_name) \
+-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+-{ \
+-      return sprintf(buf, "%d\n", state->_name);\
+-}
+-
+-define_show_state_function(exit_latency)
+-define_show_state_function(power_usage)
+-define_show_state_function(usage)
+-define_show_state_function(time)
+-define_one_state_ro(latency, show_state_exit_latency);
+-define_one_state_ro(power, show_state_power_usage);
+-define_one_state_ro(usage, show_state_usage);
+-define_one_state_ro(time, show_state_time);
+-
+-static struct attribute *cpuidle_state_default_attrs[] = {
+-      &attr_latency.attr,
+-      &attr_power.attr,
+-      &attr_usage.attr,
+-      &attr_time.attr,
+-      NULL
+-};
+-
+-#define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
+-#define kobj_to_state(k) (kobj_to_state_obj(k)->state)
+-#define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
+-static ssize_t cpuidle_state_show(struct kobject * kobj,
+-      struct attribute * attr ,char * buf)
+-{
+-      int ret = -EIO;
+-      struct cpuidle_state *state = kobj_to_state(kobj);
+-      struct cpuidle_state_attr * cattr = attr_to_stateattr(attr);
+-
+-      if (cattr->show)
+-              ret = cattr->show(state, buf);
+-
+-      return ret;
+-}
+-
+-static struct sysfs_ops cpuidle_state_sysfs_ops = {
+-      .show = cpuidle_state_show,
+-};
+-
+-static void cpuidle_state_sysfs_release(struct kobject *kobj)
+-{
+-      struct cpuidle_state_kobj *state_obj = kobj_to_state_obj(kobj);
+-
+-      complete(&state_obj->kobj_unregister);
+-}
+-
+-static struct kobj_type ktype_state_cpuidle = {
+-      .sysfs_ops = &cpuidle_state_sysfs_ops,
+-      .default_attrs = cpuidle_state_default_attrs,
+-      .release = cpuidle_state_sysfs_release,
+-};
+-
+-static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
+-{
+-      kobject_unregister(&device->kobjs[i]->kobj);
+-      wait_for_completion(&device->kobjs[i]->kobj_unregister);
+-      kfree(device->kobjs[i]);
+-      device->kobjs[i] = NULL;
+-}
+-
+-/**
+- * cpuidle_add_driver_sysfs - adds driver-specific sysfs attributes
+- * @device: the target device
+- */
+-int cpuidle_add_driver_sysfs(struct cpuidle_device *device)
+-{
+-      int i, ret = -ENOMEM;
+-      struct cpuidle_state_kobj *kobj;
+-
+-      /* state statistics */
+-      for (i = 0; i < device->state_count; i++) {
+-              kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
+-              if (!kobj)
+-                      goto error_state;
+-              kobj->state = &device->states[i];
+-              init_completion(&kobj->kobj_unregister);
+-
+-              kobj->kobj.parent = &device->kobj;
+-              kobj->kobj.ktype = &ktype_state_cpuidle;
+-              kobject_set_name(&kobj->kobj, "state%d", i);
+-              ret = kobject_register(&kobj->kobj);
+-              if (ret) {
+-                      kfree(kobj);
+-                      goto error_state;
+-              }
+-              device->kobjs[i] = kobj;
+-      }
+-
+-      return 0;
+-
+-error_state:
+-      for (i = i - 1; i >= 0; i--)
+-              cpuidle_free_state_kobj(device, i);
+-      return ret;
+-}
+-
+-/**
+- * cpuidle_remove_driver_sysfs - removes driver-specific sysfs attributes
+- * @device: the target device
+- */
+-void cpuidle_remove_driver_sysfs(struct cpuidle_device *device)
+-{
+-      int i;
+-
+-      for (i = 0; i < device->state_count; i++)
+-              cpuidle_free_state_kobj(device, i);
+-}
+-
+-/**
+- * cpuidle_add_sysfs - creates a sysfs instance for the target device
+- * @sysdev: the target device
+- */
+-int cpuidle_add_sysfs(struct sys_device *sysdev)
+-{
+-      int cpu = sysdev->id;
+-      struct cpuidle_device *dev;
+-
+-      dev = per_cpu(cpuidle_devices, cpu);
+-      dev->kobj.parent = &sysdev->kobj;
+-      dev->kobj.ktype = &ktype_cpuidle;
+-      kobject_set_name(&dev->kobj, "%s", "cpuidle");
+-      return kobject_register(&dev->kobj);
+-}
+-
+-/**
+- * cpuidle_remove_sysfs - deletes a sysfs instance on the target device
+- * @sysdev: the target device
+- */
+-void cpuidle_remove_sysfs(struct sys_device *sysdev)
+-{
+-      int cpu = sysdev->id;
+-      struct cpuidle_device *dev;
+-
+-      dev = per_cpu(cpuidle_devices, cpu);
+-      kobject_unregister(&dev->kobj);
+-}
+diff -Nurb linux-2.6.22-590/drivers/dma/Kconfig linux-2.6.22-570/drivers/dma/Kconfig
+--- linux-2.6.22-590/drivers/dma/Kconfig       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/dma/Kconfig       2007-07-08 19:32:17.000000000 -0400
+@@ -8,8 +8,8 @@
+ config DMA_ENGINE
+       bool "Support for DMA engines"
+       ---help---
+-          DMA engines offload bulk memory operations from the CPU to dedicated
+-          hardware, allowing the operations to happen asynchronously.
++        DMA engines offload copy operations from the CPU to dedicated
++        hardware, allowing the copies to happen asynchronously.
  
-       irsp = &(rspiocb->iocb);
-       ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag &= ~NLP_PRLI_SND;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "PRLI cmpl:       status:x%x/x%x did:x%x",
-+              irsp->ulpStatus, irsp->un.ulpWord[4],
-+              ndlp->nlp_DID);
+ comment "DMA Clients"
  
-       /* PRLI completes to NPort <nlp_DID> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0103 PRLI completes to NPort x%x "
-+                      "%d (%d):0103 PRLI completes to NPort x%x "
-                       "Data: x%x x%x x%x x%x\n",
--                      phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
--                      irsp->un.ulpWord[4], irsp->ulpTimeout,
--                      phba->num_disc_nodes);
-+                      phba->brd_no, vport->vpi, ndlp->nlp_DID,
-+                      irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
-+                      vport->num_disc_nodes);
--      phba->fc_prli_sent--;
-+      vport->fc_prli_sent--;
-       /* Check to see if link went down during discovery */
--      if (lpfc_els_chk_latt(phba))
-+      if (lpfc_els_chk_latt(vport))
-               goto out;
+@@ -32,11 +32,4 @@
+       ---help---
+         Enable support for the Intel(R) I/OAT DMA engine.
  
-       if (irsp->ulpStatus) {
-@@ -889,18 +1039,16 @@
-               }
-               /* PRLI failed */
-               /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
--              if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
--                 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
--                 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
--                 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
-+              if (lpfc_error_lost_link(irsp)) {
-                       goto out;
-               } else {
--                      lpfc_disc_state_machine(phba, ndlp, cmdiocb,
-+                      lpfc_disc_state_machine(vport, ndlp, cmdiocb,
-                                       NLP_EVT_CMPL_PRLI);
-               }
-       } else {
-               /* Good status, call state machine */
--              lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_PRLI);
-+              lpfc_disc_state_machine(vport, ndlp, cmdiocb,
-+                                      NLP_EVT_CMPL_PRLI);
-       }
+-config INTEL_IOP_ADMA
+-        tristate "Intel IOP ADMA support"
+-        depends on DMA_ENGINE && (ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX)
+-        default m
+-        ---help---
+-          Enable support for the Intel(R) IOP Series RAID engines.
+-
+ endmenu
+diff -Nurb linux-2.6.22-590/drivers/dma/Makefile linux-2.6.22-570/drivers/dma/Makefile
+--- linux-2.6.22-590/drivers/dma/Makefile      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/dma/Makefile      2007-07-08 19:32:17.000000000 -0400
+@@ -1,4 +1,3 @@
+ obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
+ obj-$(CONFIG_NET_DMA) += iovlock.o
+ obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
+-obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
+diff -Nurb linux-2.6.22-590/drivers/dma/dmaengine.c linux-2.6.22-570/drivers/dma/dmaengine.c
+--- linux-2.6.22-590/drivers/dma/dmaengine.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/dma/dmaengine.c   2007-07-08 19:32:17.000000000 -0400
+@@ -37,11 +37,11 @@
+  * Each device has a channels list, which runs unlocked but is never modified
+  * once the device is registered, it's just setup by the driver.
+  *
+- * Each client is responsible for keeping track of the channels it uses.  See
+- * the definition of dma_event_callback in dmaengine.h.
++ * Each client has a channels list, it's only modified under the client->lock
++ * and in an RCU callback, so it's safe to read under rcu_read_lock().
+  *
+  * Each device has a kref, which is initialized to 1 when the device is
+- * registered. A kref_get is done for each class_device registered.  When the
++ * registered. A kref_put is done for each class_device registered.  When the
+  * class_device is released, the coresponding kref_put is done in the release
+  * method. Every time one of the device's channels is allocated to a client,
+  * a kref_get occurs.  When the channel is freed, the coresponding kref_put
+@@ -51,17 +51,14 @@
+  * references to finish.
+  *
+  * Each channel has an open-coded implementation of Rusty Russell's "bigref,"
+- * with a kref and a per_cpu local_t.  A dma_chan_get is called when a client
+- * signals that it wants to use a channel, and dma_chan_put is called when
+- * a channel is removed or a client using it is unregesitered.  A client can
+- * take extra references per outstanding transaction, as is the case with
+- * the NET DMA client.  The release function does a kref_put on the device.
+- *    -ChrisL, DanW
++ * with a kref and a per_cpu local_t.  A single reference is set when on an
++ * ADDED event, and removed with a REMOVE event.  Net DMA client takes an
++ * extra reference per outstanding transaction.  The relase function does a
++ * kref_put on the device. -ChrisL
+  */
  
- out:
-@@ -909,9 +1057,11 @@
- }
+ #include <linux/init.h>
+ #include <linux/module.h>
+-#include <linux/mm.h>
+ #include <linux/device.h>
+ #include <linux/dmaengine.h>
+ #include <linux/hardirq.h>
+@@ -69,7 +66,6 @@
+ #include <linux/percpu.h>
+ #include <linux/rcupdate.h>
+ #include <linux/mutex.h>
+-#include <linux/jiffies.h>
  
- int
--lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
-+lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                  uint8_t retry)
+ static DEFINE_MUTEX(dma_list_mutex);
+ static LIST_HEAD(dma_device_list);
+@@ -104,19 +100,8 @@
static ssize_t show_in_use(struct class_device *cd, char *buf)
  {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba *phba = vport->phba;
-       PRLI *npr;
-       IOCB_t *icmd;
-       struct lpfc_iocbq *elsiocb;
-@@ -923,8 +1073,8 @@
-       psli = &phba->sli;
-       pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
--      cmdsize = (sizeof (uint32_t) + sizeof (PRLI));
--      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
-+      cmdsize = (sizeof(uint32_t) + sizeof(PRLI));
-+      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
-                                       ndlp->nlp_DID, ELS_CMD_PRLI);
-       if (!elsiocb)
-               return 1;
-@@ -933,9 +1083,9 @@
-       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
-       /* For PRLI request, remainder of payload is service parameters */
--      memset(pcmd, 0, (sizeof (PRLI) + sizeof (uint32_t)));
-+      memset(pcmd, 0, (sizeof(PRLI) + sizeof(uint32_t)));
-       *((uint32_t *) (pcmd)) = ELS_CMD_PRLI;
--      pcmd += sizeof (uint32_t);
-+      pcmd += sizeof(uint32_t);
-       /* For PRLI, remainder of payload is PRLI parameter page */
-       npr = (PRLI *) pcmd;
-@@ -955,81 +1105,88 @@
-       npr->prliType = PRLI_FCP_TYPE;
-       npr->initiatorFunc = 1;
+       struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+-      int in_use = 0;
  
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "Issue PRLI:      did:x%x",
-+              ndlp->nlp_DID, 0, 0);
-+
-       phba->fc_stat.elsXmitPRLI++;
-       elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag |= NLP_PRLI_SND;
-+      spin_unlock_irq(shost->host_lock);
-       if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag &= ~NLP_PRLI_SND;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-               lpfc_els_free_iocb(phba, elsiocb);
-               return 1;
-       }
--      spin_unlock_irq(phba->host->host_lock);
--      phba->fc_prli_sent++;
-+      vport->fc_prli_sent++;
-       return 0;
+-      if (unlikely(chan->slow_ref) &&
+-              atomic_read(&chan->refcount.refcount) > 1)
+-              in_use = 1;
+-      else {
+-              if (local_read(&(per_cpu_ptr(chan->local,
+-                      get_cpu())->refcount)) > 0)
+-                      in_use = 1;
+-              put_cpu();
+-      }
+-
+-      return sprintf(buf, "%d\n", in_use);
++      return sprintf(buf, "%d\n", (chan->client ? 1 : 0));
  }
  
- static void
--lpfc_more_adisc(struct lpfc_hba * phba)
-+lpfc_more_adisc(struct lpfc_vport *vport)
- {
-       int sentadisc;
-+      struct lpfc_hba *phba = vport->phba;
--      if (phba->num_disc_nodes)
--              phba->num_disc_nodes--;
-+      if (vport->num_disc_nodes)
-+              vport->num_disc_nodes--;
+ static struct class_device_attribute dma_class_attrs[] = {
+@@ -142,72 +127,43 @@
  
-       /* Continue discovery with <num_disc_nodes> ADISCs to go */
-       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                      "%d:0210 Continue discovery with %d ADISCs to go "
-+                      "%d (%d):0210 Continue discovery with %d ADISCs to go "
-                       "Data: x%x x%x x%x\n",
--                      phba->brd_no, phba->num_disc_nodes, phba->fc_adisc_cnt,
--                      phba->fc_flag, phba->hba_state);
-+                      phba->brd_no, vport->vpi, vport->num_disc_nodes,
-+                      vport->fc_adisc_cnt, vport->fc_flag, vport->port_state);
+ /* --- client and device registration --- */
  
-       /* Check to see if there are more ADISCs to be sent */
--      if (phba->fc_flag & FC_NLP_MORE) {
--              lpfc_set_disctmo(phba);
+-#define dma_chan_satisfies_mask(chan, mask) \
+-      __dma_chan_satisfies_mask((chan), &(mask))
+-static int
+-__dma_chan_satisfies_mask(struct dma_chan *chan, dma_cap_mask_t *want)
+-{
+-      dma_cap_mask_t has;
 -
--              /* go thru NPR list and issue any remaining ELS ADISCs */
--              sentadisc = lpfc_els_disc_adisc(phba);
-+      if (vport->fc_flag & FC_NLP_MORE) {
-+              lpfc_set_disctmo(vport);
-+              /* go thru NPR nodes and issue any remaining ELS ADISCs */
-+              sentadisc = lpfc_els_disc_adisc(vport);
-       }
-       return;
- }
- static void
--lpfc_rscn_disc(struct lpfc_hba * phba)
-+lpfc_rscn_disc(struct lpfc_vport *vport)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-+      lpfc_can_disctmo(vport);
-+
-       /* RSCN discovery */
--      /* go thru NPR list and issue ELS PLOGIs */
--      if (phba->fc_npr_cnt) {
--              if (lpfc_els_disc_plogi(phba))
-+      /* go thru NPR nodes and issue ELS PLOGIs */
-+      if (vport->fc_npr_cnt)
-+              if (lpfc_els_disc_plogi(vport))
-                       return;
--      }
--      if (phba->fc_flag & FC_RSCN_MODE) {
-+
-+      if (vport->fc_flag & FC_RSCN_MODE) {
-               /* Check to see if more RSCNs came in while we were
-                * processing this one.
-                */
--              if ((phba->fc_rscn_id_cnt == 0) &&
--                  (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
--                      spin_lock_irq(phba->host->host_lock);
--                      phba->fc_flag &= ~FC_RSCN_MODE;
--                      spin_unlock_irq(phba->host->host_lock);
-+              if ((vport->fc_rscn_id_cnt == 0) &&
-+                  (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
-+                      spin_lock_irq(shost->host_lock);
-+                      vport->fc_flag &= ~FC_RSCN_MODE;
-+                      spin_unlock_irq(shost->host_lock);
-               } else {
--                      lpfc_els_handle_rscn(phba);
-+                      lpfc_els_handle_rscn(vport);
-               }
-       }
- }
- static void
--lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                  struct lpfc_iocbq * rspiocb)
-+lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                  struct lpfc_iocbq *rspiocb)
- {
-+      struct lpfc_vport *vport = cmdiocb->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-       IOCB_t *irsp;
--      struct lpfc_sli *psli;
-       struct lpfc_nodelist *ndlp;
--      LPFC_MBOXQ_t *mbox;
--      int disc, rc;
+-      bitmap_and(has.bits, want->bits, chan->device->cap_mask.bits,
+-              DMA_TX_TYPE_END);
+-      return bitmap_equal(want->bits, has.bits, DMA_TX_TYPE_END);
+-}
 -
--      psli = &phba->sli;
-+      int  disc;
-       /* we pass cmdiocb to state machine which needs rspiocb as well */
-       cmdiocb->context_un.rsp_iocb = rspiocb;
-@@ -1037,27 +1194,32 @@
-       irsp = &(rspiocb->iocb);
-       ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "ADISC cmpl:      status:x%x/x%x did:x%x",
-+              irsp->ulpStatus, irsp->un.ulpWord[4],
-+              ndlp->nlp_DID);
-+
-       /* Since ndlp can be freed in the disc state machine, note if this node
-        * is being used during discovery.
-        */
-+      spin_lock_irq(shost->host_lock);
-       disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
--      spin_lock_irq(phba->host->host_lock);
-       ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC);
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
-       /* ADISC completes to NPort <nlp_DID> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0104 ADISC completes to NPort x%x "
-+                      "%d (%d):0104 ADISC completes to NPort x%x "
-                       "Data: x%x x%x x%x x%x x%x\n",
--                      phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
--                      irsp->un.ulpWord[4], irsp->ulpTimeout, disc,
--                      phba->num_disc_nodes);
-+                      phba->brd_no, vport->vpi, ndlp->nlp_DID,
-+                      irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
-+                      disc, vport->num_disc_nodes);
+ /**
+- * dma_client_chan_alloc - try to allocate channels to a client
++ * dma_client_chan_alloc - try to allocate a channel to a client
+  * @client: &dma_client
+  *
+  * Called with dma_list_mutex held.
+  */
+-static void dma_client_chan_alloc(struct dma_client *client)
++static struct dma_chan *dma_client_chan_alloc(struct dma_client *client)
+ {
+       struct dma_device *device;
+       struct dma_chan *chan;
++      unsigned long flags;
+       int desc;       /* allocated descriptor count */
+-      enum dma_state_client ack;
  
-       /* Check to see if link went down during discovery */
--      if (lpfc_els_chk_latt(phba)) {
--              spin_lock_irq(phba->host->host_lock);
-+      if (lpfc_els_chk_latt(vport)) {
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-               goto out;
-       }
+-      /* Find a channel */
+-      list_for_each_entry(device, &dma_device_list, global_node)
++      /* Find a channel, any DMA engine will do */
++      list_for_each_entry(device, &dma_device_list, global_node) {
+               list_for_each_entry(chan, &device->channels, device_node) {
+-                      if (!dma_chan_satisfies_mask(chan, client->cap_mask))
++                      if (chan->client)
+                               continue;
  
-@@ -1066,67 +1228,68 @@
-               if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
-                       /* ELS command is being retried */
-                       if (disc) {
--                              spin_lock_irq(phba->host->host_lock);
-+                              spin_lock_irq(shost->host_lock);
-                               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
--                              spin_unlock_irq(phba->host->host_lock);
--                              lpfc_set_disctmo(phba);
-+                              spin_unlock_irq(shost->host_lock);
-+                              lpfc_set_disctmo(vport);
+                       desc = chan->device->device_alloc_chan_resources(chan);
+                       if (desc >= 0) {
+-                              ack = client->event_callback(client,
+-                                              chan,
+-                                              DMA_RESOURCE_AVAILABLE);
+-
+-                              /* we are done once this client rejects
+-                               * an available resource
+-                               */
+-                              if (ack == DMA_ACK) {
+-                                      dma_chan_get(chan);
+                               kref_get(&device->refcount);
+-                              } else if (ack == DMA_NAK)
+-                                      return;
++                              kref_init(&chan->refcount);
++                              chan->slow_ref = 0;
++                              INIT_RCU_HEAD(&chan->rcu);
++                              chan->client = client;
++                              spin_lock_irqsave(&client->lock, flags);
++                              list_add_tail_rcu(&chan->client_node,
++                                                &client->channels);
++                              spin_unlock_irqrestore(&client->lock, flags);
++                              return chan;
                        }
-                       goto out;
                }
-               /* ADISC failed */
-               /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
--              if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
--                 ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) &&
--                 (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) &&
--                 (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) {
--                      lpfc_disc_state_machine(phba, ndlp, cmdiocb,
-+              if (!lpfc_error_lost_link(irsp)) {
-+                      lpfc_disc_state_machine(vport, ndlp, cmdiocb,
-                                       NLP_EVT_CMPL_ADISC);
-               }
-       } else {
-               /* Good status, call state machine */
--              lpfc_disc_state_machine(phba, ndlp, cmdiocb,
-+              lpfc_disc_state_machine(vport, ndlp, cmdiocb,
-                                       NLP_EVT_CMPL_ADISC);
+-}
+-
+-enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie)
+-{
+-      enum dma_status status;
+-      unsigned long dma_sync_wait_timeout = jiffies + msecs_to_jiffies(5000);
+-
+-      dma_async_issue_pending(chan);
+-      do {
+-              status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
+-              if (time_after_eq(jiffies, dma_sync_wait_timeout)) {
+-                      printk(KERN_ERR "dma_sync_wait_timeout!\n");
+-                      return DMA_ERROR;
        }
+-      } while (status == DMA_IN_PROGRESS);
  
--      if (disc && phba->num_disc_nodes) {
-+      if (disc && vport->num_disc_nodes) {
-               /* Check to see if there are more ADISCs to be sent */
--              lpfc_more_adisc(phba);
-+              lpfc_more_adisc(vport);
-               /* Check to see if we are done with ADISC authentication */
--              if (phba->num_disc_nodes == 0) {
--                      lpfc_can_disctmo(phba);
--                      /* If we get here, there is nothing left to wait for */
--                      if ((phba->hba_state < LPFC_HBA_READY) &&
--                          (phba->hba_state != LPFC_CLEAR_LA)) {
--                              /* Link up discovery */
--                              if ((mbox = mempool_alloc(phba->mbox_mem_pool,
--                                                        GFP_KERNEL))) {
--                                      phba->hba_state = LPFC_CLEAR_LA;
--                                      lpfc_clear_la(phba, mbox);
--                                      mbox->mbox_cmpl =
--                                          lpfc_mbx_cmpl_clear_la;
--                                      rc = lpfc_sli_issue_mbox
--                                              (phba, mbox,
--                                               (MBX_NOWAIT | MBX_STOP_IOCB));
--                                      if (rc == MBX_NOT_FINISHED) {
--                                              mempool_free(mbox,
--                                                   phba->mbox_mem_pool);
--                                              lpfc_disc_flush_list(phba);
--                                              psli->ring[(psli->extra_ring)].
--                                                  flag &=
--                                                  ~LPFC_STOP_IOCB_EVENT;
--                                              psli->ring[(psli->fcp_ring)].
--                                                  flag &=
--                                                  ~LPFC_STOP_IOCB_EVENT;
--                                              psli->ring[(psli->next_ring)].
--                                                  flag &=
--                                                  ~LPFC_STOP_IOCB_EVENT;
--                                              phba->hba_state =
--                                                  LPFC_HBA_READY;
-+              if (vport->num_disc_nodes == 0) {
-+                      /* If we get here, there is nothing left to ADISC */
-+                      /*
-+                       * For NPIV, cmpl_reg_vpi will set port_state to READY,
-+                       * and continue discovery.
-+                       */
-+                      if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
-+                         !(vport->fc_flag & FC_RSCN_MODE)) {
-+                              lpfc_issue_reg_vpi(phba, vport);
-+                              goto out;
-+                      }
-+                      /*
-+                       * For SLI2, we need to set port_state to READY
-+                       * and continue discovery.
-+                       */
-+                      if (vport->port_state < LPFC_VPORT_READY) {
-+                              /* If we get here, there is nothing to ADISC */
-+                              if (vport->port_type == LPFC_PHYSICAL_PORT)
-+                                      lpfc_issue_clear_la(phba, vport);
-+
-+                              if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) {
-+                                      vport->num_disc_nodes = 0;
-+                                      /* go thru NPR list, issue ELS PLOGIs */
-+                                      if (vport->fc_npr_cnt)
-+                                              lpfc_els_disc_plogi(vport);
-+
-+                                      if (!vport->num_disc_nodes) {
-+                                              spin_lock_irq(shost->host_lock);
-+                                              vport->fc_flag &=
-+                                                      ~FC_NDISC_ACTIVE;
-+                                              spin_unlock_irq(
-+                                                      shost->host_lock);
-+                                              lpfc_can_disctmo(vport);
-                                       }
-                               }
-+                              vport->port_state = LPFC_VPORT_READY;
-                       } else {
--                              lpfc_rscn_disc(phba);
-+                              lpfc_rscn_disc(vport);
-                       }
-               }
-       }
-@@ -1136,22 +1299,21 @@
+-      return status;
++      return NULL;
  }
+-EXPORT_SYMBOL(dma_sync_wait);
  
- int
--lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
-+lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-                    uint8_t retry)
+ /**
+  * dma_chan_cleanup - release a DMA channel's resources
+@@ -217,6 +173,7 @@
  {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-       ADISC *ap;
-       IOCB_t *icmd;
-       struct lpfc_iocbq *elsiocb;
--      struct lpfc_sli_ring *pring;
--      struct lpfc_sli *psli;
-+      struct lpfc_sli *psli = &phba->sli;
-+      struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
-       uint8_t *pcmd;
-       uint16_t cmdsize;
--      psli = &phba->sli;
--      pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
--
--      cmdsize = (sizeof (uint32_t) + sizeof (ADISC));
--      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
-+      cmdsize = (sizeof(uint32_t) + sizeof(ADISC));
-+      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
-                                               ndlp->nlp_DID, ELS_CMD_ADISC);
-       if (!elsiocb)
-               return 1;
-@@ -1161,81 +1323,97 @@
-       /* For ADISC request, remainder of payload is service parameters */
-       *((uint32_t *) (pcmd)) = ELS_CMD_ADISC;
--      pcmd += sizeof (uint32_t);
-+      pcmd += sizeof(uint32_t);
-       /* Fill in ADISC payload */
-       ap = (ADISC *) pcmd;
-       ap->hardAL_PA = phba->fc_pref_ALPA;
--      memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));
--      memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
--      ap->DID = be32_to_cpu(phba->fc_myDID);
-+      memcpy(&ap->portName, &vport->fc_portname, sizeof(struct lpfc_name));
-+      memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
-+      ap->DID = be32_to_cpu(vport->fc_myDID);
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "Issue ADISC:     did:x%x",
-+              ndlp->nlp_DID, 0, 0);
-       phba->fc_stat.elsXmitADISC++;
-       elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag |= NLP_ADISC_SND;
-+      spin_unlock_irq(shost->host_lock);
-       if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag &= ~NLP_ADISC_SND;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-               lpfc_els_free_iocb(phba, elsiocb);
-               return 1;
-       }
--      spin_unlock_irq(phba->host->host_lock);
-       return 0;
+       struct dma_chan *chan = container_of(kref, struct dma_chan, refcount);
+       chan->device->device_free_chan_resources(chan);
++      chan->client = NULL;
+       kref_put(&chan->device->refcount, dma_async_device_cleanup);
  }
- static void
--lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                 struct lpfc_iocbq * rspiocb)
-+lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                 struct lpfc_iocbq *rspiocb)
- {
-+      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
-+      struct lpfc_vport *vport = ndlp->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-       IOCB_t *irsp;
-       struct lpfc_sli *psli;
--      struct lpfc_nodelist *ndlp;
-       psli = &phba->sli;
-       /* we pass cmdiocb to state machine which needs rspiocb as well */
-       cmdiocb->context_un.rsp_iocb = rspiocb;
-       irsp = &(rspiocb->iocb);
--      ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag &= ~NLP_LOGO_SND;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "LOGO cmpl:       status:x%x/x%x did:x%x",
-+              irsp->ulpStatus, irsp->un.ulpWord[4],
-+              ndlp->nlp_DID);
-       /* LOGO completes to NPort <nlp_DID> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0105 LOGO completes to NPort x%x "
-+                      "%d (%d):0105 LOGO completes to NPort x%x "
-                       "Data: x%x x%x x%x x%x\n",
--                      phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
--                      irsp->un.ulpWord[4], irsp->ulpTimeout,
--                      phba->num_disc_nodes);
-+                      phba->brd_no, vport->vpi, ndlp->nlp_DID,
-+                      irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
-+                      vport->num_disc_nodes);
-       /* Check to see if link went down during discovery */
--      if (lpfc_els_chk_latt(phba))
-+      if (lpfc_els_chk_latt(vport))
-+              goto out;
-+
-+      if (ndlp->nlp_flag & NLP_TARGET_REMOVE) {
-+              /* NLP_EVT_DEVICE_RM should unregister the RPI
-+               * which should abort all outstanding IOs.
-+               */
-+              lpfc_disc_state_machine(vport, ndlp, cmdiocb,
-+                                      NLP_EVT_DEVICE_RM);
-               goto out;
-+      }
-       if (irsp->ulpStatus) {
-               /* Check for retry */
--              if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
-+              if (lpfc_els_retry(phba, cmdiocb, rspiocb))
-                       /* ELS command is being retried */
-                       goto out;
--              }
-               /* LOGO failed */
-               /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
--              if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
--                 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
--                 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
--                 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
-+              if (lpfc_error_lost_link(irsp))
-                       goto out;
--              } else {
--                      lpfc_disc_state_machine(phba, ndlp, cmdiocb,
-+              else
-+                      lpfc_disc_state_machine(vport, ndlp, cmdiocb,
-                                       NLP_EVT_CMPL_LOGO);
--              }
-       } else {
-               /* Good status, call state machine.
-                * This will unregister the rpi if needed.
-                */
--              lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO);
-+              lpfc_disc_state_machine(vport, ndlp, cmdiocb,
-+                                      NLP_EVT_CMPL_LOGO);
-       }
- out:
-@@ -1244,21 +1422,24 @@
+ EXPORT_SYMBOL(dma_chan_cleanup);
+@@ -232,7 +189,7 @@
+       kref_put(&chan->refcount, dma_chan_cleanup);
  }
  
- int
--lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
-+lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-                   uint8_t retry)
+-static void dma_chan_release(struct dma_chan *chan)
++static void dma_client_chan_free(struct dma_chan *chan)
  {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-       IOCB_t *icmd;
-       struct lpfc_iocbq *elsiocb;
-       struct lpfc_sli_ring *pring;
-       struct lpfc_sli *psli;
-       uint8_t *pcmd;
-       uint16_t cmdsize;
-+      int rc;
-       psli = &phba->sli;
-       pring = &psli->ring[LPFC_ELS_RING];
--      cmdsize = (2 * sizeof (uint32_t)) + sizeof (struct lpfc_name);
--      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
-+      cmdsize = (2 * sizeof(uint32_t)) + sizeof(struct lpfc_name);
-+      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
-                                               ndlp->nlp_DID, ELS_CMD_LOGO);
-       if (!elsiocb)
-               return 1;
-@@ -1266,53 +1447,66 @@
-       icmd = &elsiocb->iocb;
-       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
-       *((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
--      pcmd += sizeof (uint32_t);
-+      pcmd += sizeof(uint32_t);
-       /* Fill in LOGO payload */
--      *((uint32_t *) (pcmd)) = be32_to_cpu(phba->fc_myDID);
--      pcmd += sizeof (uint32_t);
--      memcpy(pcmd, &phba->fc_portname, sizeof (struct lpfc_name));
-+      *((uint32_t *) (pcmd)) = be32_to_cpu(vport->fc_myDID);
-+      pcmd += sizeof(uint32_t);
-+      memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "Issue LOGO:      did:x%x",
-+              ndlp->nlp_DID, 0, 0);
-       phba->fc_stat.elsXmitLOGO++;
-       elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag |= NLP_LOGO_SND;
--      if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
-+      spin_unlock_irq(shost->host_lock);
-+      rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
-+
-+      if (rc == IOCB_ERROR) {
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag &= ~NLP_LOGO_SND;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-               lpfc_els_free_iocb(phba, elsiocb);
-               return 1;
-       }
--      spin_unlock_irq(phba->host->host_lock);
-       return 0;
+       atomic_add(0x7FFFFFFF, &chan->refcount.refcount);
+       chan->slow_ref = 1;
+@@ -240,42 +197,41 @@
  }
  
- static void
--lpfc_cmpl_els_cmd(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                struct lpfc_iocbq * rspiocb)
-+lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                struct lpfc_iocbq *rspiocb)
+ /**
+- * dma_chans_notify_available - broadcast available channels to the clients
+- */
+-static void dma_clients_notify_available(void)
+-{
+-      struct dma_client *client;
+-
+-      mutex_lock(&dma_list_mutex);
+-
+-      list_for_each_entry(client, &dma_client_list, global_node)
+-              dma_client_chan_alloc(client);
+-
+-      mutex_unlock(&dma_list_mutex);
+-}
+-
+-/**
+- * dma_chans_notify_available - tell the clients that a channel is going away
+- * @chan: channel on its way out
++ * dma_chans_rebalance - reallocate channels to clients
++ *
++ * When the number of DMA channel in the system changes,
++ * channels need to be rebalanced among clients.
+  */
+-static void dma_clients_notify_removed(struct dma_chan *chan)
++static void dma_chans_rebalance(void)
  {
-+      struct lpfc_vport *vport = cmdiocb->vport;
-       IOCB_t *irsp;
+       struct dma_client *client;
+-      enum dma_state_client ack;
++      struct dma_chan *chan;
++      unsigned long flags;
  
-       irsp = &rspiocb->iocb;
+       mutex_lock(&dma_list_mutex);
  
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "ELS cmd cmpl:    status:x%x/x%x did:x%x",
-+              irsp->ulpStatus, irsp->un.ulpWord[4],
-+              irsp->un.elsreq64.remoteID);
-+
-       /* ELS cmd tag <ulpIoTag> completes */
--      lpfc_printf_log(phba,
--                      KERN_INFO,
--                      LOG_ELS,
--                      "%d:0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n",
--                      phba->brd_no,
-+      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-+                      "%d (%d):0106 ELS cmd tag x%x completes Data: x%x x%x "
-+                      "x%x\n",
-+                      phba->brd_no, vport->vpi,
-                       irsp->ulpIoTag, irsp->ulpStatus,
-                       irsp->un.ulpWord[4], irsp->ulpTimeout);
+       list_for_each_entry(client, &dma_client_list, global_node) {
+-              ack = client->event_callback(client, chan,
++              while (client->chans_desired > client->chan_count) {
++                      chan = dma_client_chan_alloc(client);
++                      if (!chan)
++                              break;
++                      client->chan_count++;
++                      client->event_callback(client,
++                                             chan,
++                                             DMA_RESOURCE_ADDED);
++              }
++              while (client->chans_desired < client->chan_count) {
++                      spin_lock_irqsave(&client->lock, flags);
++                      chan = list_entry(client->channels.next,
++                                        struct dma_chan,
++                                        client_node);
++                      list_del_rcu(&chan->client_node);
++                      spin_unlock_irqrestore(&client->lock, flags);
++                      client->chan_count--;
++                      client->event_callback(client,
++                                             chan,
+                               DMA_RESOURCE_REMOVED);
+-
+-              /* client was holding resources for this channel so
+-               * free it
+-               */
+-              if (ack == DMA_ACK) {
+-                      dma_chan_put(chan);
+-                      kref_put(&chan->device->refcount,
+-                              dma_async_device_cleanup);
++                      dma_client_chan_free(chan);
+               }
+       }
  
-       /* Check to see if link went down during discovery */
--      lpfc_els_chk_latt(phba);
-+      lpfc_els_chk_latt(vport);
-       lpfc_els_free_iocb(phba, cmdiocb);
-       return;
+@@ -283,14 +239,28 @@
  }
  
- int
--lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
-+lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
+ /**
+- * dma_async_client_register - register a &dma_client
+- * @client: ptr to a client structure with valid 'event_callback' and 'cap_mask'
++ * dma_async_client_register - allocate and register a &dma_client
++ * @event_callback: callback for notification of channel addition/removal
+  */
+-void dma_async_client_register(struct dma_client *client)
++struct dma_client *dma_async_client_register(dma_event_callback event_callback)
  {
-+      struct lpfc_hba  *phba = vport->phba;
-       IOCB_t *icmd;
-       struct lpfc_iocbq *elsiocb;
-       struct lpfc_sli_ring *pring;
-@@ -1323,15 +1517,16 @@
-       psli = &phba->sli;
-       pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
--      cmdsize = (sizeof (uint32_t) + sizeof (SCR));
-+      cmdsize = (sizeof(uint32_t) + sizeof(SCR));
-       ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
-       if (!ndlp)
-               return 1;
--      lpfc_nlp_init(phba, ndlp, nportid);
-+      lpfc_nlp_init(vport, ndlp, nportid);
--      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
-+      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
-                                               ndlp->nlp_DID, ELS_CMD_SCR);
++      struct dma_client *client;
 +
-       if (!elsiocb) {
-               lpfc_nlp_put(ndlp);
-               return 1;
-@@ -1341,29 +1536,31 @@
-       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
-       *((uint32_t *) (pcmd)) = ELS_CMD_SCR;
--      pcmd += sizeof (uint32_t);
-+      pcmd += sizeof(uint32_t);
-       /* For SCR, remainder of payload is SCR parameter page */
--      memset(pcmd, 0, sizeof (SCR));
-+      memset(pcmd, 0, sizeof(SCR));
-       ((SCR *) pcmd)->Function = SCR_FUNC_FULL;
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "Issue SCR:       did:x%x",
-+              ndlp->nlp_DID, 0, 0);
++      client = kzalloc(sizeof(*client), GFP_KERNEL);
++      if (!client)
++              return NULL;
 +
-       phba->fc_stat.elsXmitSCR++;
-       elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
--      spin_lock_irq(phba->host->host_lock);
-       if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
--              spin_unlock_irq(phba->host->host_lock);
-               lpfc_nlp_put(ndlp);
-               lpfc_els_free_iocb(phba, elsiocb);
-               return 1;
-       }
--      spin_unlock_irq(phba->host->host_lock);
-       lpfc_nlp_put(ndlp);
-       return 0;
++      INIT_LIST_HEAD(&client->channels);
++      spin_lock_init(&client->lock);
++      client->chans_desired = 0;
++      client->chan_count = 0;
++      client->event_callback = event_callback;
++
+       mutex_lock(&dma_list_mutex);
+       list_add_tail(&client->global_node, &dma_client_list);
+       mutex_unlock(&dma_list_mutex);
++
++      return client;
  }
+ EXPORT_SYMBOL(dma_async_client_register);
  
- static int
--lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
-+lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
+@@ -302,42 +272,40 @@
+  */
+ void dma_async_client_unregister(struct dma_client *client)
  {
-+      struct lpfc_hba  *phba = vport->phba;
-       IOCB_t *icmd;
-       struct lpfc_iocbq *elsiocb;
-       struct lpfc_sli_ring *pring;
-@@ -1377,13 +1574,14 @@
-       psli = &phba->sli;
-       pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
--      cmdsize = (sizeof (uint32_t) + sizeof (FARP));
-+      cmdsize = (sizeof(uint32_t) + sizeof(FARP));
-       ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
-       if (!ndlp)
-               return 1;
--      lpfc_nlp_init(phba, ndlp, nportid);
--      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
-+      lpfc_nlp_init(vport, ndlp, nportid);
-+
-+      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
-                                               ndlp->nlp_DID, ELS_CMD_RNID);
-       if (!elsiocb) {
-               lpfc_nlp_put(ndlp);
-@@ -1394,44 +1592,71 @@
-       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
-       *((uint32_t *) (pcmd)) = ELS_CMD_FARPR;
--      pcmd += sizeof (uint32_t);
-+      pcmd += sizeof(uint32_t);
+-      struct dma_device *device;
+       struct dma_chan *chan;
+-      enum dma_state_client ack;
  
-       /* Fill in FARPR payload */
-       fp = (FARP *) (pcmd);
--      memset(fp, 0, sizeof (FARP));
-+      memset(fp, 0, sizeof(FARP));
-       lp = (uint32_t *) pcmd;
-       *lp++ = be32_to_cpu(nportid);
--      *lp++ = be32_to_cpu(phba->fc_myDID);
-+      *lp++ = be32_to_cpu(vport->fc_myDID);
-       fp->Rflags = 0;
-       fp->Mflags = (FARP_MATCH_PORT | FARP_MATCH_NODE);
+       if (!client)
+               return;
  
--      memcpy(&fp->RportName, &phba->fc_portname, sizeof (struct lpfc_name));
--      memcpy(&fp->RnodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
--      if ((ondlp = lpfc_findnode_did(phba, nportid))) {
-+      memcpy(&fp->RportName, &vport->fc_portname, sizeof(struct lpfc_name));
-+      memcpy(&fp->RnodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
-+      ondlp = lpfc_findnode_did(vport, nportid);
-+      if (ondlp) {
-               memcpy(&fp->OportName, &ondlp->nlp_portname,
--                     sizeof (struct lpfc_name));
-+                     sizeof(struct lpfc_name));
-               memcpy(&fp->OnodeName, &ondlp->nlp_nodename,
--                     sizeof (struct lpfc_name));
-+                     sizeof(struct lpfc_name));
-       }
+-      mutex_lock(&dma_list_mutex);
+-      /* free all channels the client is holding */
+-      list_for_each_entry(device, &dma_device_list, global_node)
+-              list_for_each_entry(chan, &device->channels, device_node) {
+-                      ack = client->event_callback(client, chan,
+-                              DMA_RESOURCE_REMOVED);
+-
+-                      if (ack == DMA_ACK) {
+-                              dma_chan_put(chan);
+-                              kref_put(&chan->device->refcount,
+-                                      dma_async_device_cleanup);
+-                      }
+-              }
++      rcu_read_lock();
++      list_for_each_entry_rcu(chan, &client->channels, client_node)
++              dma_client_chan_free(chan);
++      rcu_read_unlock();
  
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "Issue FARPR:     did:x%x",
-+              ndlp->nlp_DID, 0, 0);
++      mutex_lock(&dma_list_mutex);
+       list_del(&client->global_node);
+       mutex_unlock(&dma_list_mutex);
 +
-       phba->fc_stat.elsXmitFARPR++;
-       elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
--      spin_lock_irq(phba->host->host_lock);
-       if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
--              spin_unlock_irq(phba->host->host_lock);
-               lpfc_nlp_put(ndlp);
-               lpfc_els_free_iocb(phba, elsiocb);
-               return 1;
-       }
--      spin_unlock_irq(phba->host->host_lock);
-       lpfc_nlp_put(ndlp);
-       return 0;
++      kfree(client);
++      dma_chans_rebalance();
  }
+ EXPORT_SYMBOL(dma_async_client_unregister);
  
-+static void
-+lpfc_end_rscn(struct lpfc_vport *vport)
-+{
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-+      if (vport->fc_flag & FC_RSCN_MODE) {
-+              /*
-+               * Check to see if more RSCNs came in while we were
-+               * processing this one.
-+               */
-+              if (vport->fc_rscn_id_cnt ||
-+                  (vport->fc_flag & FC_RSCN_DISCOVERY) != 0)
-+                      lpfc_els_handle_rscn(vport);
-+              else {
-+                      spin_lock_irq(shost->host_lock);
-+                      vport->fc_flag &= ~FC_RSCN_MODE;
-+                      spin_unlock_irq(shost->host_lock);
-+              }
-+      }
-+}
-+
- void
--lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp)
-+lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
+ /**
+- * dma_async_client_chan_request - send all available channels to the
+- * client that satisfy the capability mask
+- * @client - requester
++ * dma_async_client_chan_request - request DMA channels
++ * @client: &dma_client
++ * @number: count of DMA channels requested
++ *
++ * Clients call dma_async_client_chan_request() to specify how many
++ * DMA channels they need, 0 to free all currently allocated.
++ * The resulting allocations/frees are indicated to the client via the
++ * event callback.
+  */
+-void dma_async_client_chan_request(struct dma_client *client)
++void dma_async_client_chan_request(struct dma_client *client,
++                      unsigned int number)
  {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-+      spin_lock_irq(shost->host_lock);
-       nlp->nlp_flag &= ~NLP_DELAY_TMO;
-+      spin_unlock_irq(shost->host_lock);
-       del_timer_sync(&nlp->nlp_delayfunc);
      nlp->nlp_last_elscmd = 0;
+-      mutex_lock(&dma_list_mutex);
+-      dma_client_chan_alloc(client);
+-      mutex_unlock(&dma_list_mutex);
++      client->chans_desired = number;
++      dma_chans_rebalance();
+ }
EXPORT_SYMBOL(dma_async_client_chan_request);
  
-@@ -1439,30 +1664,21 @@
-               list_del_init(&nlp->els_retry_evt.evt_listp);
+@@ -354,25 +322,6 @@
+       if (!device)
+               return -ENODEV;
  
-       if (nlp->nlp_flag & NLP_NPR_2B_DISC) {
-+              spin_lock_irq(shost->host_lock);
-               nlp->nlp_flag &= ~NLP_NPR_2B_DISC;
--              if (phba->num_disc_nodes) {
-+              spin_unlock_irq(shost->host_lock);
-+              if (vport->num_disc_nodes) {
-                       /* Check to see if there are more
-                        * PLOGIs to be sent
-                        */
--                      lpfc_more_plogi(phba);
-+                      lpfc_more_plogi(vport);
+-      /* validate device routines */
+-      BUG_ON(dma_has_cap(DMA_MEMCPY, device->cap_mask) &&
+-              !device->device_prep_dma_memcpy);
+-      BUG_ON(dma_has_cap(DMA_XOR, device->cap_mask) &&
+-              !device->device_prep_dma_xor);
+-      BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) &&
+-              !device->device_prep_dma_zero_sum);
+-      BUG_ON(dma_has_cap(DMA_MEMSET, device->cap_mask) &&
+-              !device->device_prep_dma_memset);
+-      BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) &&
+-              !device->device_prep_dma_interrupt);
+-
+-      BUG_ON(!device->device_alloc_chan_resources);
+-      BUG_ON(!device->device_free_chan_resources);
+-      BUG_ON(!device->device_dependency_added);
+-      BUG_ON(!device->device_is_tx_complete);
+-      BUG_ON(!device->device_issue_pending);
+-      BUG_ON(!device->dev);
+-
+       init_completion(&device->done);
+       kref_init(&device->refcount);
+       device->dev_id = id++;
+@@ -390,9 +339,6 @@
+                        device->dev_id, chan->chan_id);
  
--                      if (phba->num_disc_nodes == 0) {
--                              phba->fc_flag &= ~FC_NDISC_ACTIVE;
--                              lpfc_can_disctmo(phba);
--                              if (phba->fc_flag & FC_RSCN_MODE) {
--                                      /*
--                                       * Check to see if more RSCNs
--                                       * came in while we were
--                                       * processing this one.
--                                       */
--                                      if((phba->fc_rscn_id_cnt==0) &&
--                                       !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
--                                              phba->fc_flag &= ~FC_RSCN_MODE;
--                                      }
--                                      else {
--                                              lpfc_els_handle_rscn(phba);
--                                      }
--                              }
-+                      if (vport->num_disc_nodes == 0) {
-+                              spin_lock_irq(shost->host_lock);
-+                              vport->fc_flag &= ~FC_NDISC_ACTIVE;
-+                              spin_unlock_irq(shost->host_lock);
-+                              lpfc_can_disctmo(vport);
-+                              lpfc_end_rscn(vport);
-                       }
-               }
+               kref_get(&device->refcount);
+-              kref_init(&chan->refcount);
+-              chan->slow_ref = 0;
+-              INIT_RCU_HEAD(&chan->rcu);
+               class_device_register(&chan->class_dev);
        }
-@@ -1472,18 +1688,19 @@
- void
- lpfc_els_retry_delay(unsigned long ptr)
+@@ -400,7 +346,7 @@
+       list_add_tail(&device->global_node, &dma_device_list);
+       mutex_unlock(&dma_list_mutex);
+-      dma_clients_notify_available();
++      dma_chans_rebalance();
+       return 0;
+ }
+@@ -425,165 +371,32 @@
+ void dma_async_device_unregister(struct dma_device *device)
  {
--      struct lpfc_nodelist *ndlp;
--      struct lpfc_hba *phba;
--      unsigned long iflag;
--      struct lpfc_work_evt  *evtp;
-+      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) ptr;
-+      struct lpfc_vport *vport = ndlp->vport;
-+      struct lpfc_hba   *phba = vport->phba;
+       struct dma_chan *chan;
 +      unsigned long flags;
-+      struct lpfc_work_evt  *evtp = &ndlp->els_retry_evt;
  
--      ndlp = (struct lpfc_nodelist *)ptr;
--      phba = ndlp->nlp_phba;
-+      ndlp = (struct lpfc_nodelist *) ptr;
-+      phba = ndlp->vport->phba;
-       evtp = &ndlp->els_retry_evt;
+       mutex_lock(&dma_list_mutex);
+       list_del(&device->global_node);
+       mutex_unlock(&dma_list_mutex);
  
--      spin_lock_irqsave(phba->host->host_lock, iflag);
-+      spin_lock_irqsave(&phba->hbalock, flags);
-       if (!list_empty(&evtp->evt_listp)) {
--              spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+              spin_unlock_irqrestore(&phba->hbalock, flags);
-               return;
+       list_for_each_entry(chan, &device->channels, device_node) {
+-              dma_clients_notify_removed(chan);
++              if (chan->client) {
++                      spin_lock_irqsave(&chan->client->lock, flags);
++                      list_del(&chan->client_node);
++                      chan->client->chan_count--;
++                      spin_unlock_irqrestore(&chan->client->lock, flags);
++                      chan->client->event_callback(chan->client,
++                                                   chan,
++                                                   DMA_RESOURCE_REMOVED);
++                      dma_client_chan_free(chan);
++              }
+               class_device_unregister(&chan->class_dev);
+-              dma_chan_release(chan);
        }
++      dma_chans_rebalance();
  
-@@ -1491,33 +1708,31 @@
-       evtp->evt       = LPFC_EVT_ELS_RETRY;
-       list_add_tail(&evtp->evt_listp, &phba->work_list);
-       if (phba->work_wait)
--              wake_up(phba->work_wait);
-+              lpfc_worker_wake_up(phba);
--      spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+      spin_unlock_irqrestore(&phba->hbalock, flags);
-       return;
+       kref_put(&device->refcount, dma_async_device_cleanup);
+       wait_for_completion(&device->done);
  }
+ EXPORT_SYMBOL(dma_async_device_unregister);
  
- void
- lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
+-/**
+- * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
+- * @chan: DMA channel to offload copy to
+- * @dest: destination address (virtual)
+- * @src: source address (virtual)
+- * @len: length
+- *
+- * Both @dest and @src must be mappable to a bus address according to the
+- * DMA mapping API rules for streaming mappings.
+- * Both @dest and @src must stay memory resident (kernel memory or locked
+- * user space pages).
+- */
+-dma_cookie_t
+-dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
+-                      void *src, size_t len)
+-{
+-      struct dma_device *dev = chan->device;
+-      struct dma_async_tx_descriptor *tx;
+-      dma_addr_t addr;
+-      dma_cookie_t cookie;
+-      int cpu;
+-
+-      tx = dev->device_prep_dma_memcpy(chan, len, 0);
+-      if (!tx)
+-              return -ENOMEM;
+-
+-      tx->ack = 1;
+-      tx->callback = NULL;
+-      addr = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
+-      tx->tx_set_src(addr, tx, 0);
+-      addr = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
+-      tx->tx_set_dest(addr, tx, 0);
+-      cookie = tx->tx_submit(tx);
+-
+-      cpu = get_cpu();
+-      per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+-      per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+-      put_cpu();
+-
+-      return cookie;
+-}
+-EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf);
+-
+-/**
+- * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
+- * @chan: DMA channel to offload copy to
+- * @page: destination page
+- * @offset: offset in page to copy to
+- * @kdata: source address (virtual)
+- * @len: length
+- *
+- * Both @page/@offset and @kdata must be mappable to a bus address according
+- * to the DMA mapping API rules for streaming mappings.
+- * Both @page/@offset and @kdata must stay memory resident (kernel memory or
+- * locked user space pages)
+- */
+-dma_cookie_t
+-dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
+-                      unsigned int offset, void *kdata, size_t len)
+-{
+-      struct dma_device *dev = chan->device;
+-      struct dma_async_tx_descriptor *tx;
+-      dma_addr_t addr;
+-      dma_cookie_t cookie;
+-      int cpu;
+-
+-      tx = dev->device_prep_dma_memcpy(chan, len, 0);
+-      if (!tx)
+-              return -ENOMEM;
+-
+-      tx->ack = 1;
+-      tx->callback = NULL;
+-      addr = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
+-      tx->tx_set_src(addr, tx, 0);
+-      addr = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
+-      tx->tx_set_dest(addr, tx, 0);
+-      cookie = tx->tx_submit(tx);
+-
+-      cpu = get_cpu();
+-      per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+-      per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+-      put_cpu();
+-
+-      return cookie;
+-}
+-EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg);
+-
+-/**
+- * dma_async_memcpy_pg_to_pg - offloaded copy from page to page
+- * @chan: DMA channel to offload copy to
+- * @dest_pg: destination page
+- * @dest_off: offset in page to copy to
+- * @src_pg: source page
+- * @src_off: offset in page to copy from
+- * @len: length
+- *
+- * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
+- * address according to the DMA mapping API rules for streaming mappings.
+- * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
+- * (kernel memory or locked user space pages).
+- */
+-dma_cookie_t
+-dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
+-      unsigned int dest_off, struct page *src_pg, unsigned int src_off,
+-      size_t len)
+-{
+-      struct dma_device *dev = chan->device;
+-      struct dma_async_tx_descriptor *tx;
+-      dma_addr_t addr;
+-      dma_cookie_t cookie;
+-      int cpu;
+-
+-      tx = dev->device_prep_dma_memcpy(chan, len, 0);
+-      if (!tx)
+-              return -ENOMEM;
+-
+-      tx->ack = 1;
+-      tx->callback = NULL;
+-      addr = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
+-      tx->tx_set_src(addr, tx, 0);
+-      addr = dma_map_page(dev->dev, dest_pg, dest_off, len, DMA_FROM_DEVICE);
+-      tx->tx_set_dest(addr, tx, 0);
+-      cookie = tx->tx_submit(tx);
+-
+-      cpu = get_cpu();
+-      per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+-      per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+-      put_cpu();
+-
+-      return cookie;
+-}
+-EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg);
+-
+-void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+-      struct dma_chan *chan)
+-{
+-      tx->chan = chan;
+-      spin_lock_init(&tx->lock);
+-      INIT_LIST_HEAD(&tx->depend_node);
+-      INIT_LIST_HEAD(&tx->depend_list);
+-}
+-EXPORT_SYMBOL(dma_async_tx_descriptor_init);
+-
+ static int __init dma_bus_init(void)
  {
--      struct lpfc_hba *phba;
--      uint32_t cmd;
--      uint32_t did;
--      uint8_t retry;
-+      struct lpfc_vport *vport = ndlp->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+      uint32_t cmd, did, retry;
+       mutex_init(&dma_list_mutex);
+diff -Nurb linux-2.6.22-590/drivers/dma/ioatdma.c linux-2.6.22-570/drivers/dma/ioatdma.c
+--- linux-2.6.22-590/drivers/dma/ioatdma.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/dma/ioatdma.c     2007-07-08 19:32:17.000000000 -0400
+@@ -39,7 +39,6 @@
+ #define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)
+ #define to_ioat_device(dev) container_of(dev, struct ioat_device, common)
+ #define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
+-#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)
  
--      phba = ndlp->nlp_phba;
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       did = ndlp->nlp_DID;
-       cmd = ndlp->nlp_last_elscmd;
-       ndlp->nlp_last_elscmd = 0;
+ /* internal functions */
+ static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+@@ -72,76 +71,13 @@
+               INIT_LIST_HEAD(&ioat_chan->used_desc);
+               /* This should be made common somewhere in dmaengine.c */
+               ioat_chan->common.device = &device->common;
++              ioat_chan->common.client = NULL;
+               list_add_tail(&ioat_chan->common.device_node,
+                             &device->common.channels);
+       }
+       return device->common.chancnt;
+ }
  
-       if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-               return;
+-static void
+-ioat_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index)
+-{
+-      struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx);
+-      struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+-
+-      pci_unmap_addr_set(desc, src, addr);
+-
+-      list_for_each_entry(iter, &desc->group_list, node) {
+-              iter->hw->src_addr = addr;
+-              addr += ioat_chan->xfercap;
+-      }
+-
+-}
+-
+-static void
+-ioat_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index)
+-{
+-      struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx);
+-      struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+-
+-      pci_unmap_addr_set(desc, dst, addr);
+-
+-      list_for_each_entry(iter, &desc->group_list, node) {
+-              iter->hw->dst_addr = addr;
+-              addr += ioat_chan->xfercap;
+-      }
+-}
+-
+-static dma_cookie_t
+-ioat_tx_submit(struct dma_async_tx_descriptor *tx)
+-{
+-      struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+-      struct ioat_desc_sw *desc = tx_to_ioat_desc(tx);
+-      struct ioat_desc_sw *group_start = list_entry(desc->group_list.next,
+-              struct ioat_desc_sw, node);
+-      int append = 0;
+-      dma_cookie_t cookie;
+-
+-      spin_lock_bh(&ioat_chan->desc_lock);
+-      /* cookie incr and addition to used_list must be atomic */
+-      cookie = ioat_chan->common.cookie;
+-      cookie++;
+-      if (cookie < 0)
+-              cookie = 1;
+-      ioat_chan->common.cookie = desc->async_tx.cookie = cookie;
+-
+-      /* write address into NextDescriptor field of last desc in chain */
+-      to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = group_start->phys;
+-      list_splice_init(&desc->group_list, ioat_chan->used_desc.prev);
+-
+-      ioat_chan->pending += desc->group_count;
+-      if (ioat_chan->pending >= 4) {
+-              append = 1;
+-              ioat_chan->pending = 0;
+-      }
+-      spin_unlock_bh(&ioat_chan->desc_lock);
+-
+-      if (append)
+-              ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET,
+-                                      IOAT_CHANCMD_APPEND);
+-      return cookie;
+-}
+-
+ static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
+       struct ioat_dma_chan *ioat_chan,
+       gfp_t flags)
+@@ -163,11 +99,6 @@
        }
  
-       ndlp->nlp_flag &= ~NLP_DELAY_TMO;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
-       /*
-        * If a discovery event readded nlp_delayfunc after timer
-        * firing and before processing the timer, cancel the
-@@ -1528,57 +1743,54 @@
+       memset(desc, 0, sizeof(*desc));
+-      dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common);
+-      desc_sw->async_tx.tx_set_src = ioat_set_src;
+-      desc_sw->async_tx.tx_set_dest = ioat_set_dest;
+-      desc_sw->async_tx.tx_submit = ioat_tx_submit;
+-      INIT_LIST_HEAD(&desc_sw->group_list);
+       desc_sw->hw = desc;
+       desc_sw->phys = phys;
  
-       switch (cmd) {
-       case ELS_CMD_FLOGI:
--              lpfc_issue_els_flogi(phba, ndlp, retry);
-+              lpfc_issue_els_flogi(vport, ndlp, retry);
-               break;
-       case ELS_CMD_PLOGI:
--              if(!lpfc_issue_els_plogi(phba, ndlp->nlp_DID, retry)) {
-+              if (!lpfc_issue_els_plogi(vport, ndlp->nlp_DID, retry)) {
-                       ndlp->nlp_prev_state = ndlp->nlp_state;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
-               }
-               break;
-       case ELS_CMD_ADISC:
--              if (!lpfc_issue_els_adisc(phba, ndlp, retry)) {
-+              if (!lpfc_issue_els_adisc(vport, ndlp, retry)) {
-                       ndlp->nlp_prev_state = ndlp->nlp_state;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
-               }
-               break;
-       case ELS_CMD_PRLI:
--              if (!lpfc_issue_els_prli(phba, ndlp, retry)) {
-+              if (!lpfc_issue_els_prli(vport, ndlp, retry)) {
-                       ndlp->nlp_prev_state = ndlp->nlp_state;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
-               }
-               break;
-       case ELS_CMD_LOGO:
--              if (!lpfc_issue_els_logo(phba, ndlp, retry)) {
-+              if (!lpfc_issue_els_logo(vport, ndlp, retry)) {
-                       ndlp->nlp_prev_state = ndlp->nlp_state;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-               }
-               break;
-+      case ELS_CMD_FDISC:
-+              lpfc_issue_els_fdisc(vport, ndlp, retry);
-+              break;
-       }
-       return;
+@@ -284,25 +215,45 @@
+       ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
  }
  
- static int
--lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--             struct lpfc_iocbq * rspiocb)
-+lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+             struct lpfc_iocbq *rspiocb)
- {
--      IOCB_t *irsp;
--      struct lpfc_dmabuf *pcmd;
--      struct lpfc_nodelist *ndlp;
-+      struct lpfc_vport *vport = cmdiocb->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+      IOCB_t *irsp = &rspiocb->iocb;
-+      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
-+      struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
-       uint32_t *elscmd;
-       struct ls_rjt stat;
--      int retry, maxretry;
--      int delay;
--      uint32_t cmd;
-+      int retry = 0, maxretry = lpfc_max_els_tries, delay = 0;
-+      uint32_t cmd = 0;
-       uint32_t did;
--      retry = 0;
--      delay = 0;
--      maxretry = lpfc_max_els_tries;
--      irsp = &rspiocb->iocb;
--      ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
--      pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
--      cmd = 0;
+-static struct dma_async_tx_descriptor *
+-ioat_dma_prep_memcpy(struct dma_chan *chan, size_t len, int int_en)
+-{
+-      struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+-      struct ioat_desc_sw *first, *prev, *new;
++/**
++ * do_ioat_dma_memcpy - actual function that initiates a IOAT DMA transaction
++ * @ioat_chan: IOAT DMA channel handle
++ * @dest: DMA destination address
++ * @src: DMA source address
++ * @len: transaction length in bytes
++ */
++
++static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan,
++                                       dma_addr_t dest,
++                                       dma_addr_t src,
++                                       size_t len)
++{
++      struct ioat_desc_sw *first;
++      struct ioat_desc_sw *prev;
++      struct ioat_desc_sw *new;
++      dma_cookie_t cookie;
+       LIST_HEAD(new_chain);
+       u32 copy;
+       size_t orig_len;
+-      int desc_count = 0;
++      dma_addr_t orig_src, orig_dst;
++      unsigned int desc_count = 0;
++      unsigned int append = 0;
++
++      if (!ioat_chan || !dest || !src)
++              return -EFAULT;
  
-       /* Note: context2 may be 0 for internal driver abort
-        * of delays ELS command.
-@@ -1594,11 +1806,15 @@
-       else {
-               /* We should only hit this case for retrying PLOGI */
-               did = irsp->un.elsreq64.remoteID;
--              ndlp = lpfc_findnode_did(phba, did);
-+              ndlp = lpfc_findnode_did(vport, did);
-               if (!ndlp && (cmd != ELS_CMD_PLOGI))
-                       return 1;
-       }
+       if (!len)
+-              return NULL;
++              return ioat_chan->common.cookie;
  
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "Retry ELS:       wd7:x%x wd4:x%x did:x%x",
-+              *(((uint32_t *) irsp) + 7), irsp->un.ulpWord[4], ndlp->nlp_DID);
-+
-       switch (irsp->ulpStatus) {
-       case IOSTAT_FCP_RSP_ERROR:
-       case IOSTAT_REMOTE_STOP:
-@@ -1607,25 +1823,37 @@
-       case IOSTAT_LOCAL_REJECT:
-               switch ((irsp->un.ulpWord[4] & 0xff)) {
-               case IOERR_LOOP_OPEN_FAILURE:
--                      if (cmd == ELS_CMD_PLOGI) {
--                              if (cmdiocb->retry == 0) {
--                                      delay = 1;
--                              }
--                      }
-+                      if (cmd == ELS_CMD_PLOGI && cmdiocb->retry == 0)
-+                              delay = 1000;
-                       retry = 1;
-                       break;
+       orig_len = len;
++      orig_src = src;
++      orig_dst = dest;
  
--              case IOERR_SEQUENCE_TIMEOUT:
-+              case IOERR_ILLEGAL_COMMAND:
-+                      if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) &&
-+                          (cmd == ELS_CMD_FDISC)) {
-+                              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                              "%d (%d):0124 FDISC failed (3/6) retrying...\n",
-+                                      phba->brd_no, vport->vpi);
-+                              lpfc_mbx_unreg_vpi(vport);
-                       retry = 1;
-+                              /* Always retry for this case */
-+                              cmdiocb->retry = 0;
-+                      }
-                       break;
+       first = NULL;
+       prev = NULL;
  
-               case IOERR_NO_RESOURCES:
--                      if (cmd == ELS_CMD_PLOGI) {
--                              delay = 1;
--                      }
-+                      retry = 1;
-+                      if (cmdiocb->retry > 100)
-+                              delay = 100;
-+                      maxretry = 250;
-+                      break;
+       spin_lock_bh(&ioat_chan->desc_lock);
 +
-+              case IOERR_ILLEGAL_FRAME:
-+                      delay = 100;
-                       retry = 1;
-                       break;
+       while (len) {
+               if (!list_empty(&ioat_chan->free_desc)) {
+                       new = to_ioat_desc(ioat_chan->free_desc.next);
+@@ -319,8 +270,9 @@
  
-+              case IOERR_SEQUENCE_TIMEOUT:
-               case IOERR_INVALID_RPI:
-                       retry = 1;
-                       break;
-@@ -1655,27 +1883,57 @@
-                       if (stat.un.b.lsRjtRsnCodeExp ==
-                           LSEXP_CMD_IN_PROGRESS) {
-                               if (cmd == ELS_CMD_PLOGI) {
--                                      delay = 1;
-+                                      delay = 1000;
-                                       maxretry = 48;
-                               }
-                               retry = 1;
-                               break;
-                       }
-                       if (cmd == ELS_CMD_PLOGI) {
--                              delay = 1;
-+                              delay = 1000;
-                               maxretry = lpfc_max_els_tries + 1;
-                               retry = 1;
-                               break;
-                       }
-+                      if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
-+                        (cmd == ELS_CMD_FDISC) &&
-+                        (stat.un.b.lsRjtRsnCodeExp == LSEXP_OUT_OF_RESOURCE)){
-+                              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                              "%d (%d):0125 FDISC Failed (x%x)."
-+                              " Fabric out of resources\n",
-+                              phba->brd_no, vport->vpi, stat.un.lsRjtError);
-+                              lpfc_vport_set_state(vport,
-+                                                   FC_VPORT_NO_FABRIC_RSCS);
-+                      }
-                       break;
+               new->hw->size = copy;
+               new->hw->ctl = 0;
+-              new->async_tx.cookie = 0;
+-              new->async_tx.ack = 1;
++              new->hw->src_addr = src;
++              new->hw->dst_addr = dest;
++              new->cookie = 0;
  
-               case LSRJT_LOGICAL_BSY:
--                      if (cmd == ELS_CMD_PLOGI) {
--                              delay = 1;
-+                      if ((cmd == ELS_CMD_PLOGI) ||
-+                          (cmd == ELS_CMD_PRLI)) {
-+                              delay = 1000;
-                               maxretry = 48;
-+                      } else if (cmd == ELS_CMD_FDISC) {
-+                              /* Always retry for this case */
-+                              cmdiocb->retry = 0;
-                       }
-                       retry = 1;
-                       break;
-+
-+              case LSRJT_LOGICAL_ERR:
-+              case LSRJT_PROTOCOL_ERR:
-+                      if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
-+                        (cmd == ELS_CMD_FDISC) &&
-+                        ((stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_PNAME) ||
-+                        (stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_NPORT_ID))
-+                        ) {
-+                              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                              "%d (%d):0123 FDISC Failed (x%x)."
-+                              " Fabric Detected Bad WWN\n",
-+                              phba->brd_no, vport->vpi, stat.un.lsRjtError);
-+                              lpfc_vport_set_state(vport,
-+                                                   FC_VPORT_FABRIC_REJ_WWN);
-+                      }
-+                      break;
-               }
-               break;
+               /* chain together the physical address list for the HW */
+               if (!first)
+@@ -329,26 +281,130 @@
+                       prev->hw->next = (u64) new->phys;
  
-@@ -1695,21 +1953,27 @@
-               retry = 0;
+               prev = new;
++
+               len  -= copy;
++              dest += copy;
++              src  += copy;
++
+               list_add_tail(&new->node, &new_chain);
+               desc_count++;
        }
+-
+-      list_splice(&new_chain, &new->group_list);
+-
+       new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+       new->hw->next = 0;
+-      new->group_count = desc_count;
+-      new->async_tx.ack = 0; /* client is in control of this ack */
+-      new->async_tx.cookie = -EBUSY;
  
-+      if ((vport->load_flag & FC_UNLOADING) != 0)
-+              retry = 0;
++      /* cookie incr and addition to used_list must be atomic */
 +
-       if (retry) {
++      cookie = ioat_chan->common.cookie;
++      cookie++;
++      if (cookie < 0)
++              cookie = 1;
++      ioat_chan->common.cookie = new->cookie = cookie;
++
++      pci_unmap_addr_set(new, src, orig_src);
++      pci_unmap_addr_set(new, dst, orig_dst);
+       pci_unmap_len_set(new, src_len, orig_len);
+       pci_unmap_len_set(new, dst_len, orig_len);
++
++      /* write address into NextDescriptor field of last desc in chain */
++      to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = first->phys;
++      list_splice_init(&new_chain, ioat_chan->used_desc.prev);
++
++      ioat_chan->pending += desc_count;
++      if (ioat_chan->pending >= 20) {
++              append = 1;
++              ioat_chan->pending = 0;
++      }
++
+       spin_unlock_bh(&ioat_chan->desc_lock);
  
-               /* Retry ELS command <elsCmd> to remote NPORT <did> */
-               lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                              "%d:0107 Retry ELS command x%x to remote "
-+                              "%d (%d):0107 Retry ELS command x%x to remote "
-                               "NPORT x%x Data: x%x x%x\n",
--                              phba->brd_no,
-+                              phba->brd_no, vport->vpi,
-                               cmd, did, cmdiocb->retry, delay);
+-      return new ? &new->async_tx : NULL;
++      if (append)
++              ioatdma_chan_write8(ioat_chan,
++                                  IOAT_CHANCMD_OFFSET,
++                                  IOAT_CHANCMD_APPEND);
++      return cookie;
++}
++
++/**
++ * ioat_dma_memcpy_buf_to_buf - wrapper that takes src & dest bufs
++ * @chan: IOAT DMA channel handle
++ * @dest: DMA destination address
++ * @src: DMA source address
++ * @len: transaction length in bytes
++ */
++
++static dma_cookie_t ioat_dma_memcpy_buf_to_buf(struct dma_chan *chan,
++                                               void *dest,
++                                               void *src,
++                                               size_t len)
++{
++      dma_addr_t dest_addr;
++      dma_addr_t src_addr;
++      struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
++
++      dest_addr = pci_map_single(ioat_chan->device->pdev,
++              dest, len, PCI_DMA_FROMDEVICE);
++      src_addr = pci_map_single(ioat_chan->device->pdev,
++              src, len, PCI_DMA_TODEVICE);
++
++      return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
++}
++
++/**
++ * ioat_dma_memcpy_buf_to_pg - wrapper, copying from a buf to a page
++ * @chan: IOAT DMA channel handle
++ * @page: pointer to the page to copy to
++ * @offset: offset into that page
++ * @src: DMA source address
++ * @len: transaction length in bytes
++ */
++
++static dma_cookie_t ioat_dma_memcpy_buf_to_pg(struct dma_chan *chan,
++                                              struct page *page,
++                                              unsigned int offset,
++                                              void *src,
++                                              size_t len)
++{
++      dma_addr_t dest_addr;
++      dma_addr_t src_addr;
++      struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
++
++      dest_addr = pci_map_page(ioat_chan->device->pdev,
++              page, offset, len, PCI_DMA_FROMDEVICE);
++      src_addr = pci_map_single(ioat_chan->device->pdev,
++              src, len, PCI_DMA_TODEVICE);
++
++      return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
+ }
  
--              if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) {
-+              if (((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) &&
-+                      ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
-+                      ((irsp->un.ulpWord[4] & 0xff) != IOERR_NO_RESOURCES))) {
-+                      /* Don't reset timer for no resources */
++/**
++ * ioat_dma_memcpy_pg_to_pg - wrapper, copying between two pages
++ * @chan: IOAT DMA channel handle
++ * @dest_pg: pointer to the page to copy to
++ * @dest_off: offset into that page
++ * @src_pg: pointer to the page to copy from
++ * @src_off: offset into that page
++ * @len: transaction length in bytes. This is guaranteed not to make a copy
++ *     across a page boundary.
++ */
++
++static dma_cookie_t ioat_dma_memcpy_pg_to_pg(struct dma_chan *chan,
++                                             struct page *dest_pg,
++                                             unsigned int dest_off,
++                                             struct page *src_pg,
++                                             unsigned int src_off,
++                                             size_t len)
++{
++      dma_addr_t dest_addr;
++      dma_addr_t src_addr;
++      struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
 +
-                       /* If discovery / RSCN timer is running, reset it */
--                      if (timer_pending(&phba->fc_disctmo) ||
--                            (phba->fc_flag & FC_RSCN_MODE)) {
--                              lpfc_set_disctmo(phba);
--                      }
-+                      if (timer_pending(&vport->fc_disctmo) ||
-+                          (vport->fc_flag & FC_RSCN_MODE))
-+                              lpfc_set_disctmo(vport);
++      dest_addr = pci_map_page(ioat_chan->device->pdev,
++              dest_pg, dest_off, len, PCI_DMA_FROMDEVICE);
++      src_addr = pci_map_page(ioat_chan->device->pdev,
++              src_pg, src_off, len, PCI_DMA_TODEVICE);
++
++      return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
++}
+ /**
+  * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended descriptors to hw
+@@ -411,8 +467,8 @@
+                * exceeding xfercap, perhaps. If so, only the last one will
+                * have a cookie, and require unmapping.
+                */
+-              if (desc->async_tx.cookie) {
+-                      cookie = desc->async_tx.cookie;
++              if (desc->cookie) {
++                      cookie = desc->cookie;
+                       /* yes we are unmapping both _page and _single alloc'd
+                          regions with unmap_page. Is this *really* that bad?
+@@ -428,18 +484,13 @@
                }
  
-               phba->fc_stat.elsXmitRetry++;
-@@ -1717,50 +1981,62 @@
-                       phba->fc_stat.elsDelayRetry++;
-                       ndlp->nlp_retry = cmdiocb->retry;
+               if (desc->phys != phys_complete) {
+-                      /* a completed entry, but not the last, so cleanup
+-                       * if the client is done with the descriptor
+-                       */
+-                      if (desc->async_tx.ack) {
++                      /* a completed entry, but not the last, so cleanup */
+                       list_del(&desc->node);
+                       list_add_tail(&desc->node, &chan->free_desc);
+-                      } else
+-                              desc->async_tx.cookie = 0;
+               } else {
+                       /* last used desc. Do not remove, so we can append from
+                          it, but don't look at it next time, either */
+-                      desc->async_tx.cookie = 0;
++                      desc->cookie = 0;
  
--                      mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
-+                      /* delay is specified in milliseconds */
-+                      mod_timer(&ndlp->nlp_delayfunc,
-+                              jiffies + msecs_to_jiffies(delay));
-+                      spin_lock_irq(shost->host_lock);
-                       ndlp->nlp_flag |= NLP_DELAY_TMO;
-+                      spin_unlock_irq(shost->host_lock);
+                       /* TODO check status bits? */
+                       break;
+@@ -455,17 +506,6 @@
+       spin_unlock(&chan->cleanup_lock);
+ }
  
-                       ndlp->nlp_prev_state = ndlp->nlp_state;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-+                      if (cmd == ELS_CMD_PRLI)
-+                              lpfc_nlp_set_state(vport, ndlp,
-+                                      NLP_STE_REG_LOGIN_ISSUE);
-+                      else
-+                              lpfc_nlp_set_state(vport, ndlp,
-+                                      NLP_STE_NPR_NODE);
-                       ndlp->nlp_last_elscmd = cmd;
+-static void ioat_dma_dependency_added(struct dma_chan *chan)
+-{
+-      struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+-      spin_lock_bh(&ioat_chan->desc_lock);
+-      if (ioat_chan->pending == 0) {
+-              spin_unlock_bh(&ioat_chan->desc_lock);
+-              ioat_dma_memcpy_cleanup(ioat_chan);
+-      } else
+-              spin_unlock_bh(&ioat_chan->desc_lock);
+-}
+-
+ /**
+  * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
+  * @chan: IOAT DMA channel handle
+@@ -567,7 +607,6 @@
  
-                       return 1;
-               }
-               switch (cmd) {
-               case ELS_CMD_FLOGI:
--                      lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry);
-+                      lpfc_issue_els_flogi(vport, ndlp, cmdiocb->retry);
-+                      return 1;
-+              case ELS_CMD_FDISC:
-+                      lpfc_issue_els_fdisc(vport, ndlp, cmdiocb->retry);
-                       return 1;
-               case ELS_CMD_PLOGI:
-                       if (ndlp) {
-                               ndlp->nlp_prev_state = ndlp->nlp_state;
--                              lpfc_nlp_set_state(phba, ndlp,
-+                              lpfc_nlp_set_state(vport, ndlp,
-                                                  NLP_STE_PLOGI_ISSUE);
-                       }
--                      lpfc_issue_els_plogi(phba, did, cmdiocb->retry);
-+                      lpfc_issue_els_plogi(vport, did, cmdiocb->retry);
-                       return 1;
-               case ELS_CMD_ADISC:
-                       ndlp->nlp_prev_state = ndlp->nlp_state;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
--                      lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
-+                      lpfc_issue_els_adisc(vport, ndlp, cmdiocb->retry);
-                       return 1;
-               case ELS_CMD_PRLI:
-                       ndlp->nlp_prev_state = ndlp->nlp_state;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
--                      lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
-+                      lpfc_issue_els_prli(vport, ndlp, cmdiocb->retry);
-                       return 1;
-               case ELS_CMD_LOGO:
-                       ndlp->nlp_prev_state = ndlp->nlp_state;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
--                      lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-+                      lpfc_issue_els_logo(vport, ndlp, cmdiocb->retry);
-                       return 1;
-               }
-       }
+       desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
+       desc->hw->next = 0;
+-      desc->async_tx.ack = 1;
  
-       /* No retry ELS command <elsCmd> to remote NPORT <did> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0108 No retry ELS command x%x to remote NPORT x%x "
--                      "Data: x%x\n",
--                      phba->brd_no,
-+                      "%d (%d):0108 No retry ELS command x%x to remote "
-+                      "NPORT x%x Data: x%x\n",
-+                      phba->brd_no, vport->vpi,
-                       cmd, did, cmdiocb->retry);
+       list_add_tail(&desc->node, &ioat_chan->used_desc);
+       spin_unlock_bh(&ioat_chan->desc_lock);
+@@ -594,8 +633,6 @@
+       u8 *src;
+       u8 *dest;
+       struct dma_chan *dma_chan;
+-      struct dma_async_tx_descriptor *tx;
+-      dma_addr_t addr;
+       dma_cookie_t cookie;
+       int err = 0;
  
-       return 0;
-@@ -1795,33 +2071,36 @@
-               lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
-               kfree(buf_ptr);
+@@ -621,15 +658,7 @@
+               goto out;
        }
--      spin_lock_irq(phba->host->host_lock);
-       lpfc_sli_release_iocbq(phba, elsiocb);
--      spin_unlock_irq(phba->host->host_lock);
-       return 0;
- }
  
- static void
--lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                     struct lpfc_iocbq * rspiocb)
-+lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                     struct lpfc_iocbq *rspiocb)
- {
--      struct lpfc_nodelist *ndlp;
-+      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
-+      struct lpfc_vport *vport = cmdiocb->vport;
-+      IOCB_t *irsp;
+-      tx = ioat_dma_prep_memcpy(dma_chan, IOAT_TEST_SIZE, 0);
+-      async_tx_ack(tx);
+-      addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE,
+-                      DMA_TO_DEVICE);
+-      ioat_set_src(addr, tx, 0);
+-      addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,
+-                      DMA_FROM_DEVICE);
+-      ioat_set_dest(addr, tx, 0);
+-      cookie = ioat_tx_submit(tx);
++      cookie = ioat_dma_memcpy_buf_to_buf(dma_chan, dest, src, IOAT_TEST_SIZE);
+       ioat_dma_memcpy_issue_pending(dma_chan);
+       msleep(1);
  
--      ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
-+      irsp = &rspiocb->iocb;
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
-+              "ACC LOGO cmpl:   status:x%x/x%x did:x%x",
-+              irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID);
+@@ -725,14 +754,13 @@
+       INIT_LIST_HEAD(&device->common.channels);
+       enumerate_dma_channels(device);
  
-       /* ACC to LOGO completes to NPort <nlp_DID> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0109 ACC to LOGO completes to NPort x%x "
-+                      "%d (%d):0109 ACC to LOGO completes to NPort x%x "
-                       "Data: x%x x%x x%x\n",
--                      phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
--                      ndlp->nlp_state, ndlp->nlp_rpi);
-+                      phba->brd_no, vport->vpi, ndlp->nlp_DID,
-+                      ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+-      dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
+       device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources;
+       device->common.device_free_chan_resources = ioat_dma_free_chan_resources;
+-      device->common.device_prep_dma_memcpy = ioat_dma_prep_memcpy;
+-      device->common.device_is_tx_complete = ioat_dma_is_complete;
+-      device->common.device_issue_pending = ioat_dma_memcpy_issue_pending;
+-      device->common.device_dependency_added = ioat_dma_dependency_added;
+-      device->common.dev = &pdev->dev;
++      device->common.device_memcpy_buf_to_buf = ioat_dma_memcpy_buf_to_buf;
++      device->common.device_memcpy_buf_to_pg = ioat_dma_memcpy_buf_to_pg;
++      device->common.device_memcpy_pg_to_pg = ioat_dma_memcpy_pg_to_pg;
++      device->common.device_memcpy_complete = ioat_dma_is_complete;
++      device->common.device_memcpy_issue_pending = ioat_dma_memcpy_issue_pending;
+       printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n",
+               device->common.chancnt);
+diff -Nurb linux-2.6.22-590/drivers/dma/ioatdma.h linux-2.6.22-570/drivers/dma/ioatdma.h
+--- linux-2.6.22-590/drivers/dma/ioatdma.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/dma/ioatdma.h     2007-07-08 19:32:17.000000000 -0400
+@@ -30,6 +30,9 @@
  
-       switch (ndlp->nlp_state) {
-       case NLP_STE_UNUSED_NODE:       /* node is just allocated */
--              lpfc_drop_node(phba, ndlp);
-+              lpfc_drop_node(vport, ndlp);
-               break;
-       case NLP_STE_NPR_NODE:          /* NPort Recovery mode */
--              lpfc_unreg_rpi(phba, ndlp);
-+              lpfc_unreg_rpi(vport, ndlp);
-               break;
-       default:
-               break;
-@@ -1830,24 +2109,38 @@
-       return;
- }
+ #define IOAT_LOW_COMPLETION_MASK      0xffffffc0
  
-+void
-+lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
-+{
-+      struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
-+      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
-+
-+      pmb->context1 = NULL;
-+      lpfc_mbuf_free(phba, mp->virt, mp->phys);
-+      kfree(mp);
-+      mempool_free(pmb, phba->mbox_mem_pool);
-+      lpfc_nlp_put(ndlp);
-+      return;
-+}
++extern struct list_head dma_device_list;
++extern struct list_head dma_client_list;
 +
- static void
--lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-                 struct lpfc_iocbq *rspiocb)
- {
-+      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
-+      struct lpfc_vport *vport = ndlp ? ndlp->vport : NULL;
-+      struct Scsi_Host  *shost = vport ? lpfc_shost_from_vport(vport) : NULL;
-       IOCB_t *irsp;
--      struct lpfc_nodelist *ndlp;
-       LPFC_MBOXQ_t *mbox = NULL;
--      struct lpfc_dmabuf *mp;
-+      struct lpfc_dmabuf *mp = NULL;
+ /**
+  * struct ioat_device - internal representation of a IOAT device
+  * @pdev: PCI-Express device
+@@ -102,20 +105,15 @@
+ /**
+  * struct ioat_desc_sw - wrapper around hardware descriptor
+  * @hw: hardware DMA descriptor
+- * @async_tx:
+  * @node:
+- * @group_list:
+- * @group_cnt:
+  * @cookie:
+  * @phys:
+  */
  
-       irsp = &rspiocb->iocb;
+ struct ioat_desc_sw {
+       struct ioat_dma_descriptor *hw;
+-      struct dma_async_tx_descriptor async_tx;
+       struct list_head node;
+-      struct list_head group_list;
+-      int group_count;
++      dma_cookie_t cookie;
+       dma_addr_t phys;
+       DECLARE_PCI_UNMAP_ADDR(src)
+       DECLARE_PCI_UNMAP_LEN(src_len)
+@@ -124,3 +122,4 @@
+ };
+ #endif /* IOATDMA_H */
++
+diff -Nurb linux-2.6.22-590/drivers/dma/iop-adma.c linux-2.6.22-570/drivers/dma/iop-adma.c
+--- linux-2.6.22-590/drivers/dma/iop-adma.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/dma/iop-adma.c    1969-12-31 19:00:00.000000000 -0500
+@@ -1,1465 +0,0 @@
+-/*
+- * offload engine driver for the Intel Xscale series of i/o processors
+- * Copyright Â© 2006, Intel Corporation.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- *
+- */
+-
+-/*
+- * This driver supports the asynchrounous DMA copy and RAID engines available
+- * on the Intel Xscale(R) family of I/O Processors (IOP 32x, 33x, 134x)
+- */
+-
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/async_tx.h>
+-#include <linux/delay.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/spinlock.h>
+-#include <linux/interrupt.h>
+-#include <linux/platform_device.h>
+-#include <linux/memory.h>
+-#include <linux/ioport.h>
+-
+-#include <asm/arch/adma.h>
+-
+-#define to_iop_adma_chan(chan) container_of(chan, struct iop_adma_chan, common)
+-#define to_iop_adma_device(dev) \
+-      container_of(dev, struct iop_adma_device, common)
+-#define tx_to_iop_adma_slot(tx) \
+-      container_of(tx, struct iop_adma_desc_slot, async_tx)
+-
+-/**
+- * iop_adma_free_slots - flags descriptor slots for reuse
+- * @slot: Slot to free
+- * Caller must hold &iop_chan->lock while calling this function
+- */
+-static void iop_adma_free_slots(struct iop_adma_desc_slot *slot)
+-{
+-      int stride = slot->slots_per_op;
+-
+-      while (stride--) {
+-              slot->slots_per_op = 0;
+-              slot = list_entry(slot->slot_node.next,
+-                              struct iop_adma_desc_slot,
+-                              slot_node);
+-      }
+-}
+-
+-static dma_cookie_t
+-iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
+-      struct iop_adma_chan *iop_chan, dma_cookie_t cookie)
+-{
+-      BUG_ON(desc->async_tx.cookie < 0);
+-      spin_lock_bh(&desc->async_tx.lock);
+-      if (desc->async_tx.cookie > 0) {
+-              cookie = desc->async_tx.cookie;
+-              desc->async_tx.cookie = 0;
+-
+-              /* call the callback (must not sleep or submit new
+-               * operations to this channel)
+-               */
+-              if (desc->async_tx.callback)
+-                      desc->async_tx.callback(
+-                              desc->async_tx.callback_param);
+-
+-              /* unmap dma addresses
+-               * (unmap_single vs unmap_page?)
+-               */
+-              if (desc->group_head && desc->unmap_len) {
+-                      struct iop_adma_desc_slot *unmap = desc->group_head;
+-                      struct device *dev =
+-                              &iop_chan->device->pdev->dev;
+-                      u32 len = unmap->unmap_len;
+-                      u32 src_cnt = unmap->unmap_src_cnt;
+-                      dma_addr_t addr = iop_desc_get_dest_addr(unmap,
+-                              iop_chan);
+-
+-                      dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+-                      while (src_cnt--) {
+-                              addr = iop_desc_get_src_addr(unmap,
+-                                                      iop_chan,
+-                                                      src_cnt);
+-                              dma_unmap_page(dev, addr, len,
+-                                      DMA_TO_DEVICE);
+-                      }
+-                      desc->group_head = NULL;
+-              }
+-      }
+-
+-      /* run dependent operations */
+-      async_tx_run_dependencies(&desc->async_tx);
+-      spin_unlock_bh(&desc->async_tx.lock);
+-
+-      return cookie;
+-}
+-
+-static int
+-iop_adma_clean_slot(struct iop_adma_desc_slot *desc,
+-      struct iop_adma_chan *iop_chan)
+-{
+-      /* the client is allowed to attach dependent operations
+-       * until 'ack' is set
+-       */
+-      if (!desc->async_tx.ack)
+-              return 0;
+-
+-      /* leave the last descriptor in the chain
+-       * so we can append to it
+-       */
+-      if (desc->chain_node.next == &iop_chan->chain)
+-              return 1;
+-
+-      dev_dbg(iop_chan->device->common.dev,
+-              "\tfree slot: %d slots_per_op: %d\n",
+-              desc->idx, desc->slots_per_op);
+-
+-      list_del(&desc->chain_node);
+-      iop_adma_free_slots(desc);
+-
+-      return 0;
+-}
+-
+-static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+-{
+-      struct iop_adma_desc_slot *iter, *_iter, *grp_start = NULL;
+-      dma_cookie_t cookie = 0;
+-      u32 current_desc = iop_chan_get_current_descriptor(iop_chan);
+-      int busy = iop_chan_is_busy(iop_chan);
+-      int seen_current = 0, slot_cnt = 0, slots_per_op = 0;
+-
+-      dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+-      /* free completed slots from the chain starting with
+-       * the oldest descriptor
+-       */
+-      list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
+-                                      chain_node) {
+-              pr_debug("\tcookie: %d slot: %d busy: %d "
+-                      "this_desc: %#x next_desc: %#x ack: %d\n",
+-                      iter->async_tx.cookie, iter->idx, busy, iter->phys,
+-                      iop_desc_get_next_desc(iter),
+-                      iter->async_tx.ack);
+-              prefetch(_iter);
+-              prefetch(&_iter->async_tx);
+-
+-              /* do not advance past the current descriptor loaded into the
+-               * hardware channel, subsequent descriptors are either in
+-               * process or have not been submitted
+-               */
+-              if (seen_current)
+-                      break;
+-
+-              /* stop the search if we reach the current descriptor and the
+-               * channel is busy, or if it appears that the current descriptor
+-               * needs to be re-read (i.e. has been appended to)
+-               */
+-              if (iter->phys == current_desc) {
+-                      BUG_ON(seen_current++);
+-                      if (busy || iop_desc_get_next_desc(iter))
+-                              break;
+-              }
+-
+-              /* detect the start of a group transaction */
+-              if (!slot_cnt && !slots_per_op) {
+-                      slot_cnt = iter->slot_cnt;
+-                      slots_per_op = iter->slots_per_op;
+-                      if (slot_cnt <= slots_per_op) {
+-                              slot_cnt = 0;
+-                              slots_per_op = 0;
+-                      }
+-              }
+-
+-              if (slot_cnt) {
+-                      pr_debug("\tgroup++\n");
+-                      if (!grp_start)
+-                              grp_start = iter;
+-                      slot_cnt -= slots_per_op;
+-              }
+-
+-              /* all the members of a group are complete */
+-              if (slots_per_op != 0 && slot_cnt == 0) {
+-                      struct iop_adma_desc_slot *grp_iter, *_grp_iter;
+-                      int end_of_chain = 0;
+-                      pr_debug("\tgroup end\n");
+-
+-                      /* collect the total results */
+-                      if (grp_start->xor_check_result) {
+-                              u32 zero_sum_result = 0;
+-                              slot_cnt = grp_start->slot_cnt;
+-                              grp_iter = grp_start;
+-
+-                              list_for_each_entry_from(grp_iter,
+-                                      &iop_chan->chain, chain_node) {
+-                                      zero_sum_result |=
+-                                          iop_desc_get_zero_result(grp_iter);
+-                                          pr_debug("\titer%d result: %d\n",
+-                                          grp_iter->idx, zero_sum_result);
+-                                      slot_cnt -= slots_per_op;
+-                                      if (slot_cnt == 0)
+-                                              break;
+-                              }
+-                              pr_debug("\tgrp_start->xor_check_result: %p\n",
+-                                      grp_start->xor_check_result);
+-                              *grp_start->xor_check_result = zero_sum_result;
+-                      }
+-
+-                      /* clean up the group */
+-                      slot_cnt = grp_start->slot_cnt;
+-                      grp_iter = grp_start;
+-                      list_for_each_entry_safe_from(grp_iter, _grp_iter,
+-                              &iop_chan->chain, chain_node) {
+-                              cookie = iop_adma_run_tx_complete_actions(
+-                                      grp_iter, iop_chan, cookie);
+-
+-                              slot_cnt -= slots_per_op;
+-                              end_of_chain = iop_adma_clean_slot(grp_iter,
+-                                      iop_chan);
+-
+-                              if (slot_cnt == 0 || end_of_chain)
+-                                      break;
+-                      }
+-
+-                      /* the group should be complete at this point */
+-                      BUG_ON(slot_cnt);
+-
+-                      slots_per_op = 0;
+-                      grp_start = NULL;
+-                      if (end_of_chain)
+-                              break;
+-                      else
+-                              continue;
+-              } else if (slots_per_op) /* wait for group completion */
+-                      continue;
+-
+-              /* write back zero sum results (single descriptor case) */
+-              if (iter->xor_check_result && iter->async_tx.cookie)
+-                      *iter->xor_check_result =
+-                              iop_desc_get_zero_result(iter);
+-
+-              cookie = iop_adma_run_tx_complete_actions(
+-                                      iter, iop_chan, cookie);
+-
+-              if (iop_adma_clean_slot(iter, iop_chan))
+-                      break;
+-      }
+-
+-      BUG_ON(!seen_current);
+-
+-      iop_chan_idle(busy, iop_chan);
+-
+-      if (cookie > 0) {
+-              iop_chan->completed_cookie = cookie;
+-              pr_debug("\tcompleted cookie %d\n", cookie);
+-      }
+-}
+-
+-static void
+-iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+-{
+-      spin_lock_bh(&iop_chan->lock);
+-      __iop_adma_slot_cleanup(iop_chan);
+-      spin_unlock_bh(&iop_chan->lock);
+-}
+-
+-static void iop_adma_tasklet(unsigned long data)
+-{
+-      struct iop_adma_chan *chan = (struct iop_adma_chan *) data;
+-      __iop_adma_slot_cleanup(chan);
+-}
+-
+-static struct iop_adma_desc_slot *
+-iop_adma_alloc_slots(struct iop_adma_chan *iop_chan, int num_slots,
+-                      int slots_per_op)
+-{
+-      struct iop_adma_desc_slot *iter, *_iter, *alloc_start = NULL;
+-      struct list_head chain = LIST_HEAD_INIT(chain);
+-      int slots_found, retry = 0;
+-
+-      /* start search from the last allocated descrtiptor
+-       * if a contiguous allocation can not be found start searching
+-       * from the beginning of the list
+-       */
+-retry:
+-      slots_found = 0;
+-      if (retry == 0)
+-              iter = iop_chan->last_used;
+-      else
+-              iter = list_entry(&iop_chan->all_slots,
+-                      struct iop_adma_desc_slot,
+-                      slot_node);
+-
+-      list_for_each_entry_safe_continue(
+-              iter, _iter, &iop_chan->all_slots, slot_node) {
+-              prefetch(_iter);
+-              prefetch(&_iter->async_tx);
+-              if (iter->slots_per_op) {
+-                      /* give up after finding the first busy slot
+-                       * on the second pass through the list
+-                       */
+-                      if (retry)
+-                              break;
+-
+-                      slots_found = 0;
+-                      continue;
+-              }
+-
+-              /* start the allocation if the slot is correctly aligned */
+-              if (!slots_found++) {
+-                      if (iop_desc_is_aligned(iter, slots_per_op))
+-                              alloc_start = iter;
+-                      else {
+-                              slots_found = 0;
+-                              continue;
+-                      }
+-              }
+-
+-              if (slots_found == num_slots) {
+-                      struct iop_adma_desc_slot *alloc_tail = NULL;
+-                      struct iop_adma_desc_slot *last_used = NULL;
+-                      iter = alloc_start;
+-                      while (num_slots) {
+-                              int i;
+-                              dev_dbg(iop_chan->device->common.dev,
+-                                      "allocated slot: %d "
+-                                      "(desc %p phys: %#x) slots_per_op %d\n",
+-                                      iter->idx, iter->hw_desc, iter->phys,
+-                                      slots_per_op);
+-
+-                              /* pre-ack all but the last descriptor */
+-                              if (num_slots != slots_per_op)
+-                                      iter->async_tx.ack = 1;
+-                              else
+-                                      iter->async_tx.ack = 0;
+-
+-                              list_add_tail(&iter->chain_node, &chain);
+-                              alloc_tail = iter;
+-                              iter->async_tx.cookie = 0;
+-                              iter->slot_cnt = num_slots;
+-                              iter->xor_check_result = NULL;
+-                              for (i = 0; i < slots_per_op; i++) {
+-                                      iter->slots_per_op = slots_per_op - i;
+-                                      last_used = iter;
+-                                      iter = list_entry(iter->slot_node.next,
+-                                              struct iop_adma_desc_slot,
+-                                              slot_node);
+-                              }
+-                              num_slots -= slots_per_op;
+-                      }
+-                      alloc_tail->group_head = alloc_start;
+-                      alloc_tail->async_tx.cookie = -EBUSY;
+-                      list_splice(&chain, &alloc_tail->group_list);
+-                      iop_chan->last_used = last_used;
+-                      iop_desc_clear_next_desc(alloc_start);
+-                      iop_desc_clear_next_desc(alloc_tail);
+-                      return alloc_tail;
+-              }
+-      }
+-      if (!retry++)
+-              goto retry;
+-
+-      /* try to free some slots if the allocation fails */
+-      tasklet_schedule(&iop_chan->irq_tasklet);
+-
+-      return NULL;
+-}
+-
+-static dma_cookie_t
+-iop_desc_assign_cookie(struct iop_adma_chan *iop_chan,
+-      struct iop_adma_desc_slot *desc)
+-{
+-      dma_cookie_t cookie = iop_chan->common.cookie;
+-      cookie++;
+-      if (cookie < 0)
+-              cookie = 1;
+-      iop_chan->common.cookie = desc->async_tx.cookie = cookie;
+-      return cookie;
+-}
+-
+-static void iop_adma_check_threshold(struct iop_adma_chan *iop_chan)
+-{
+-      dev_dbg(iop_chan->device->common.dev, "pending: %d\n",
+-              iop_chan->pending);
+-
+-      if (iop_chan->pending >= IOP_ADMA_THRESHOLD) {
+-              iop_chan->pending = 0;
+-              iop_chan_append(iop_chan);
+-      }
+-}
+-
+-static dma_cookie_t
+-iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
+-{
+-      struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+-      struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan);
+-      struct iop_adma_desc_slot *grp_start, *old_chain_tail;
+-      int slot_cnt;
+-      int slots_per_op;
+-      dma_cookie_t cookie;
+-
+-      grp_start = sw_desc->group_head;
+-      slot_cnt = grp_start->slot_cnt;
+-      slots_per_op = grp_start->slots_per_op;
+-
+-      spin_lock_bh(&iop_chan->lock);
+-      cookie = iop_desc_assign_cookie(iop_chan, sw_desc);
+-
+-      old_chain_tail = list_entry(iop_chan->chain.prev,
+-              struct iop_adma_desc_slot, chain_node);
+-      list_splice_init(&sw_desc->group_list, &old_chain_tail->chain_node);
+-
+-      /* fix up the hardware chain */
+-      iop_desc_set_next_desc(old_chain_tail, grp_start->phys);
+-
+-      /* 1/ don't add pre-chained descriptors
+-       * 2/ dummy read to flush next_desc write
+-       */
+-      BUG_ON(iop_desc_get_next_desc(sw_desc));
+-
+-      /* increment the pending count by the number of slots
+-       * memcpy operations have a 1:1 (slot:operation) relation
+-       * other operations are heavier and will pop the threshold
+-       * more often.
+-       */
+-      iop_chan->pending += slot_cnt;
+-      iop_adma_check_threshold(iop_chan);
+-      spin_unlock_bh(&iop_chan->lock);
+-
+-      dev_dbg(iop_chan->device->common.dev, "%s cookie: %d slot: %d\n",
+-              __FUNCTION__, sw_desc->async_tx.cookie, sw_desc->idx);
+-
+-      return cookie;
+-}
+-
+-static void
+-iop_adma_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
+-      int index)
+-{
+-      struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+-      struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan);
+-
+-      /* to do: support transfers lengths > IOP_ADMA_MAX_BYTE_COUNT */
+-      iop_desc_set_dest_addr(sw_desc->group_head, iop_chan, addr);
+-}
+-
+-static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan);
+-static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan);
+-
+-/* returns the number of allocated descriptors */
+-static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
+-{
+-      char *hw_desc;
+-      int idx;
+-      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+-      struct iop_adma_desc_slot *slot = NULL;
+-      int init = iop_chan->slots_allocated ? 0 : 1;
+-      struct iop_adma_platform_data *plat_data =
+-              iop_chan->device->pdev->dev.platform_data;
+-      int num_descs_in_pool = plat_data->pool_size/IOP_ADMA_SLOT_SIZE;
+-
+-      /* Allocate descriptor slots */
+-      do {
+-              idx = iop_chan->slots_allocated;
+-              if (idx == num_descs_in_pool)
+-                      break;
+-
+-              slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+-              if (!slot) {
+-                      printk(KERN_INFO "IOP ADMA Channel only initialized"
+-                              " %d descriptor slots", idx);
+-                      break;
+-              }
+-              hw_desc = (char *) iop_chan->device->dma_desc_pool_virt;
+-              slot->hw_desc = (void *) &hw_desc[idx * IOP_ADMA_SLOT_SIZE];
+-
+-              dma_async_tx_descriptor_init(&slot->async_tx, chan);
+-              slot->async_tx.tx_submit = iop_adma_tx_submit;
+-              slot->async_tx.tx_set_dest = iop_adma_set_dest;
+-              INIT_LIST_HEAD(&slot->chain_node);
+-              INIT_LIST_HEAD(&slot->slot_node);
+-              INIT_LIST_HEAD(&slot->group_list);
+-              hw_desc = (char *) iop_chan->device->dma_desc_pool;
+-              slot->phys = (dma_addr_t) &hw_desc[idx * IOP_ADMA_SLOT_SIZE];
+-              slot->idx = idx;
+-
+-              spin_lock_bh(&iop_chan->lock);
+-              iop_chan->slots_allocated++;
+-              list_add_tail(&slot->slot_node, &iop_chan->all_slots);
+-              spin_unlock_bh(&iop_chan->lock);
+-      } while (iop_chan->slots_allocated < num_descs_in_pool);
+-
+-      if (idx && !iop_chan->last_used)
+-              iop_chan->last_used = list_entry(iop_chan->all_slots.next,
+-                                      struct iop_adma_desc_slot,
+-                                      slot_node);
+-
+-      dev_dbg(iop_chan->device->common.dev,
+-              "allocated %d descriptor slots last_used: %p\n",
+-              iop_chan->slots_allocated, iop_chan->last_used);
+-
+-      /* initialize the channel and the chain with a null operation */
+-      if (init) {
+-              if (dma_has_cap(DMA_MEMCPY,
+-                      iop_chan->device->common.cap_mask))
+-                      iop_chan_start_null_memcpy(iop_chan);
+-              else if (dma_has_cap(DMA_XOR,
+-                      iop_chan->device->common.cap_mask))
+-                      iop_chan_start_null_xor(iop_chan);
+-              else
+-                      BUG();
+-      }
+-
+-      return (idx > 0) ? idx : -ENOMEM;
+-}
+-
+-static struct dma_async_tx_descriptor *
+-iop_adma_prep_dma_interrupt(struct dma_chan *chan)
+-{
+-      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+-      struct iop_adma_desc_slot *sw_desc, *grp_start;
+-      int slot_cnt, slots_per_op;
+-
+-      dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+-
+-      spin_lock_bh(&iop_chan->lock);
+-      slot_cnt = iop_chan_interrupt_slot_count(&slots_per_op, iop_chan);
+-      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+-      if (sw_desc) {
+-              grp_start = sw_desc->group_head;
+-              iop_desc_init_interrupt(grp_start, iop_chan);
+-              grp_start->unmap_len = 0;
+-      }
+-      spin_unlock_bh(&iop_chan->lock);
+-
+-      return sw_desc ? &sw_desc->async_tx : NULL;
+-}
+-
+-static void
+-iop_adma_memcpy_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
+-      int index)
+-{
+-      struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+-      struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
+-
+-      iop_desc_set_memcpy_src_addr(grp_start, addr);
+-}
+-
+-static struct dma_async_tx_descriptor *
+-iop_adma_prep_dma_memcpy(struct dma_chan *chan, size_t len, int int_en)
+-{
+-      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+-      struct iop_adma_desc_slot *sw_desc, *grp_start;
+-      int slot_cnt, slots_per_op;
+-
+-      if (unlikely(!len))
+-              return NULL;
+-      BUG_ON(unlikely(len > IOP_ADMA_MAX_BYTE_COUNT));
+-
+-      dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
+-              __FUNCTION__, len);
+-
+-      spin_lock_bh(&iop_chan->lock);
+-      slot_cnt = iop_chan_memcpy_slot_count(len, &slots_per_op);
+-      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+-      if (sw_desc) {
+-              grp_start = sw_desc->group_head;
+-              iop_desc_init_memcpy(grp_start, int_en);
+-              iop_desc_set_byte_count(grp_start, iop_chan, len);
+-              sw_desc->unmap_src_cnt = 1;
+-              sw_desc->unmap_len = len;
+-              sw_desc->async_tx.tx_set_src = iop_adma_memcpy_set_src;
+-      }
+-      spin_unlock_bh(&iop_chan->lock);
+-
+-      return sw_desc ? &sw_desc->async_tx : NULL;
+-}
+-
+-static struct dma_async_tx_descriptor *
+-iop_adma_prep_dma_memset(struct dma_chan *chan, int value, size_t len,
+-      int int_en)
+-{
+-      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+-      struct iop_adma_desc_slot *sw_desc, *grp_start;
+-      int slot_cnt, slots_per_op;
+-
+-      if (unlikely(!len))
+-              return NULL;
+-      BUG_ON(unlikely(len > IOP_ADMA_MAX_BYTE_COUNT));
+-
+-      dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
+-              __FUNCTION__, len);
+-
+-      spin_lock_bh(&iop_chan->lock);
+-      slot_cnt = iop_chan_memset_slot_count(len, &slots_per_op);
+-      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+-      if (sw_desc) {
+-              grp_start = sw_desc->group_head;
+-              iop_desc_init_memset(grp_start, int_en);
+-              iop_desc_set_byte_count(grp_start, iop_chan, len);
+-              iop_desc_set_block_fill_val(grp_start, value);
+-              sw_desc->unmap_src_cnt = 1;
+-              sw_desc->unmap_len = len;
+-      }
+-      spin_unlock_bh(&iop_chan->lock);
+-
+-      return sw_desc ? &sw_desc->async_tx : NULL;
+-}
+-
+-static void
+-iop_adma_xor_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
+-      int index)
+-{
+-      struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+-      struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
+-
+-      iop_desc_set_xor_src_addr(grp_start, index, addr);
+-}
+-
+-static struct dma_async_tx_descriptor *
+-iop_adma_prep_dma_xor(struct dma_chan *chan, unsigned int src_cnt, size_t len,
+-      int int_en)
+-{
+-      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+-      struct iop_adma_desc_slot *sw_desc, *grp_start;
+-      int slot_cnt, slots_per_op;
+-
+-      if (unlikely(!len))
+-              return NULL;
+-      BUG_ON(unlikely(len > IOP_ADMA_XOR_MAX_BYTE_COUNT));
+-
+-      dev_dbg(iop_chan->device->common.dev,
+-              "%s src_cnt: %d len: %u int_en: %d\n",
+-              __FUNCTION__, src_cnt, len, int_en);
+-
+-      spin_lock_bh(&iop_chan->lock);
+-      slot_cnt = iop_chan_xor_slot_count(len, src_cnt, &slots_per_op);
+-      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+-      if (sw_desc) {
+-              grp_start = sw_desc->group_head;
+-              iop_desc_init_xor(grp_start, src_cnt, int_en);
+-              iop_desc_set_byte_count(grp_start, iop_chan, len);
+-              sw_desc->unmap_src_cnt = src_cnt;
+-              sw_desc->unmap_len = len;
+-              sw_desc->async_tx.tx_set_src = iop_adma_xor_set_src;
+-      }
+-      spin_unlock_bh(&iop_chan->lock);
+-
+-      return sw_desc ? &sw_desc->async_tx : NULL;
+-}
+-
+-static void
+-iop_adma_xor_zero_sum_set_src(dma_addr_t addr,
+-                              struct dma_async_tx_descriptor *tx,
+-                              int index)
+-{
+-      struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+-      struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
+-
+-      iop_desc_set_zero_sum_src_addr(grp_start, index, addr);
+-}
+-
+-static struct dma_async_tx_descriptor *
+-iop_adma_prep_dma_zero_sum(struct dma_chan *chan, unsigned int src_cnt,
+-      size_t len, u32 *result, int int_en)
+-{
+-      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+-      struct iop_adma_desc_slot *sw_desc, *grp_start;
+-      int slot_cnt, slots_per_op;
+-
+-      if (unlikely(!len))
+-              return NULL;
+-
+-      dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %u\n",
+-              __FUNCTION__, src_cnt, len);
+-
+-      spin_lock_bh(&iop_chan->lock);
+-      slot_cnt = iop_chan_zero_sum_slot_count(len, src_cnt, &slots_per_op);
+-      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+-      if (sw_desc) {
+-              grp_start = sw_desc->group_head;
+-              iop_desc_init_zero_sum(grp_start, src_cnt, int_en);
+-              iop_desc_set_zero_sum_byte_count(grp_start, len);
+-              grp_start->xor_check_result = result;
+-              pr_debug("\t%s: grp_start->xor_check_result: %p\n",
+-                      __FUNCTION__, grp_start->xor_check_result);
+-              sw_desc->unmap_src_cnt = src_cnt;
+-              sw_desc->unmap_len = len;
+-              sw_desc->async_tx.tx_set_src = iop_adma_xor_zero_sum_set_src;
+-      }
+-      spin_unlock_bh(&iop_chan->lock);
+-
+-      return sw_desc ? &sw_desc->async_tx : NULL;
+-}
+-
+-static void iop_adma_dependency_added(struct dma_chan *chan)
+-{
+-      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+-      tasklet_schedule(&iop_chan->irq_tasklet);
+-}
+-
+-static void iop_adma_free_chan_resources(struct dma_chan *chan)
+-{
+-      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+-      struct iop_adma_desc_slot *iter, *_iter;
+-      int in_use_descs = 0;
+-
+-      iop_adma_slot_cleanup(iop_chan);
+-
+-      spin_lock_bh(&iop_chan->lock);
+-      list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
+-                                      chain_node) {
+-              in_use_descs++;
+-              list_del(&iter->chain_node);
+-      }
+-      list_for_each_entry_safe_reverse(
+-              iter, _iter, &iop_chan->all_slots, slot_node) {
+-              list_del(&iter->slot_node);
+-              kfree(iter);
+-              iop_chan->slots_allocated--;
+-      }
+-      iop_chan->last_used = NULL;
+-
+-      dev_dbg(iop_chan->device->common.dev, "%s slots_allocated %d\n",
+-              __FUNCTION__, iop_chan->slots_allocated);
+-      spin_unlock_bh(&iop_chan->lock);
+-
+-      /* one is ok since we left it on there on purpose */
+-      if (in_use_descs > 1)
+-              printk(KERN_ERR "IOP: Freeing %d in use descriptors!\n",
+-                      in_use_descs - 1);
+-}
+-
+-/**
+- * iop_adma_is_complete - poll the status of an ADMA transaction
+- * @chan: ADMA channel handle
+- * @cookie: ADMA transaction identifier
+- */
+-static enum dma_status iop_adma_is_complete(struct dma_chan *chan,
+-                                      dma_cookie_t cookie,
+-                                      dma_cookie_t *done,
+-                                      dma_cookie_t *used)
+-{
+-      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+-      dma_cookie_t last_used;
+-      dma_cookie_t last_complete;
+-      enum dma_status ret;
+-
+-      last_used = chan->cookie;
+-      last_complete = iop_chan->completed_cookie;
+-
+-      if (done)
+-              *done = last_complete;
+-      if (used)
+-              *used = last_used;
+-
+-      ret = dma_async_is_complete(cookie, last_complete, last_used);
+-      if (ret == DMA_SUCCESS)
+-              return ret;
+-
+-      iop_adma_slot_cleanup(iop_chan);
+-
+-      last_used = chan->cookie;
+-      last_complete = iop_chan->completed_cookie;
+-
+-      if (done)
+-              *done = last_complete;
+-      if (used)
+-              *used = last_used;
+-
+-      return dma_async_is_complete(cookie, last_complete, last_used);
+-}
+-
+-static irqreturn_t iop_adma_eot_handler(int irq, void *data)
+-{
+-      struct iop_adma_chan *chan = data;
+-
+-      dev_dbg(chan->device->common.dev, "%s\n", __FUNCTION__);
+-
+-      tasklet_schedule(&chan->irq_tasklet);
+-
+-      iop_adma_device_clear_eot_status(chan);
+-
+-      return IRQ_HANDLED;
+-}
+-
+-static irqreturn_t iop_adma_eoc_handler(int irq, void *data)
+-{
+-      struct iop_adma_chan *chan = data;
+-
+-      dev_dbg(chan->device->common.dev, "%s\n", __FUNCTION__);
+-
+-      tasklet_schedule(&chan->irq_tasklet);
+-
+-      iop_adma_device_clear_eoc_status(chan);
+-
+-      return IRQ_HANDLED;
+-}
+-
+-static irqreturn_t iop_adma_err_handler(int irq, void *data)
+-{
+-      struct iop_adma_chan *chan = data;
+-      unsigned long status = iop_chan_get_status(chan);
+-
+-      dev_printk(KERN_ERR, chan->device->common.dev,
+-              "error ( %s%s%s%s%s%s%s)\n",
+-              iop_is_err_int_parity(status, chan) ? "int_parity " : "",
+-              iop_is_err_mcu_abort(status, chan) ? "mcu_abort " : "",
+-              iop_is_err_int_tabort(status, chan) ? "int_tabort " : "",
+-              iop_is_err_int_mabort(status, chan) ? "int_mabort " : "",
+-              iop_is_err_pci_tabort(status, chan) ? "pci_tabort " : "",
+-              iop_is_err_pci_mabort(status, chan) ? "pci_mabort " : "",
+-              iop_is_err_split_tx(status, chan) ? "split_tx " : "");
+-
+-      iop_adma_device_clear_err_status(chan);
+-
+-      BUG();
+-
+-      return IRQ_HANDLED;
+-}
+-
+-static void iop_adma_issue_pending(struct dma_chan *chan)
+-{
+-      struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+-
+-      if (iop_chan->pending) {
+-              iop_chan->pending = 0;
+-              iop_chan_append(iop_chan);
+-      }
+-}
+-
+-/*
+- * Perform a transaction to verify the HW works.
+- */
+-#define IOP_ADMA_TEST_SIZE 2000
+-
+-static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
+-{
+-      int i;
+-      void *src, *dest;
+-      dma_addr_t src_dma, dest_dma;
+-      struct dma_chan *dma_chan;
+-      dma_cookie_t cookie;
+-      struct dma_async_tx_descriptor *tx;
+-      int err = 0;
+-      struct iop_adma_chan *iop_chan;
+-
+-      dev_dbg(device->common.dev, "%s\n", __FUNCTION__);
+-
+-      src = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
+-      if (!src)
+-              return -ENOMEM;
+-      dest = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
+-      if (!dest) {
+-              kfree(src);
+-              return -ENOMEM;
+-      }
+-
+-      /* Fill in src buffer */
+-      for (i = 0; i < IOP_ADMA_TEST_SIZE; i++)
+-              ((u8 *) src)[i] = (u8)i;
+-
+-      memset(dest, 0, IOP_ADMA_TEST_SIZE);
+-
+-      /* Start copy, using first DMA channel */
+-      dma_chan = container_of(device->common.channels.next,
+-                              struct dma_chan,
+-                              device_node);
+-      if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+-              err = -ENODEV;
+-              goto out;
+-      }
+-
+-      tx = iop_adma_prep_dma_memcpy(dma_chan, IOP_ADMA_TEST_SIZE, 1);
+-      dest_dma = dma_map_single(dma_chan->device->dev, dest,
+-                              IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
+-      iop_adma_set_dest(dest_dma, tx, 0);
+-      src_dma = dma_map_single(dma_chan->device->dev, src,
+-                              IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE);
+-      iop_adma_memcpy_set_src(src_dma, tx, 0);
+-
+-      cookie = iop_adma_tx_submit(tx);
+-      iop_adma_issue_pending(dma_chan);
+-      async_tx_ack(tx);
+-      msleep(1);
+-
+-      if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+-                      DMA_SUCCESS) {
+-              dev_printk(KERN_ERR, dma_chan->device->dev,
+-                      "Self-test copy timed out, disabling\n");
+-              err = -ENODEV;
+-              goto free_resources;
+-      }
+-
+-      iop_chan = to_iop_adma_chan(dma_chan);
+-      dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
+-              IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
+-      if (memcmp(src, dest, IOP_ADMA_TEST_SIZE)) {
+-              dev_printk(KERN_ERR, dma_chan->device->dev,
+-                      "Self-test copy failed compare, disabling\n");
+-              err = -ENODEV;
+-              goto free_resources;
+-      }
+-
+-free_resources:
+-      iop_adma_free_chan_resources(dma_chan);
+-out:
+-      kfree(src);
+-      kfree(dest);
+-      return err;
+-}
+-
+-#define IOP_ADMA_NUM_SRC_TEST 4 /* must be <= 15 */
+-static int __devinit
+-iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+-{
+-      int i, src_idx;
+-      struct page *dest;
+-      struct page *xor_srcs[IOP_ADMA_NUM_SRC_TEST];
+-      struct page *zero_sum_srcs[IOP_ADMA_NUM_SRC_TEST + 1];
+-      dma_addr_t dma_addr, dest_dma;
+-      struct dma_async_tx_descriptor *tx;
+-      struct dma_chan *dma_chan;
+-      dma_cookie_t cookie;
+-      u8 cmp_byte = 0;
+-      u32 cmp_word;
+-      u32 zero_sum_result;
+-      int err = 0;
+-      struct iop_adma_chan *iop_chan;
+-
+-      dev_dbg(device->common.dev, "%s\n", __FUNCTION__);
+-
+-      for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
+-              xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
+-              if (!xor_srcs[src_idx])
+-                      while (src_idx--) {
+-                              __free_page(xor_srcs[src_idx]);
+-                              return -ENOMEM;
+-                      }
+-      }
+-
+-      dest = alloc_page(GFP_KERNEL);
+-      if (!dest)
+-              while (src_idx--) {
+-                      __free_page(xor_srcs[src_idx]);
+-                      return -ENOMEM;
+-              }
+-
+-      /* Fill in src buffers */
+-      for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
+-              u8 *ptr = page_address(xor_srcs[src_idx]);
+-              for (i = 0; i < PAGE_SIZE; i++)
+-                      ptr[i] = (1 << src_idx);
+-      }
+-
+-      for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++)
+-              cmp_byte ^= (u8) (1 << src_idx);
+-
+-      cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
+-                      (cmp_byte << 8) | cmp_byte;
+-
+-      memset(page_address(dest), 0, PAGE_SIZE);
+-
+-      dma_chan = container_of(device->common.channels.next,
+-                              struct dma_chan,
+-                              device_node);
+-      if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+-              err = -ENODEV;
+-              goto out;
+-      }
+-
+-      /* test xor */
+-      tx = iop_adma_prep_dma_xor(dma_chan, IOP_ADMA_NUM_SRC_TEST,
+-                              PAGE_SIZE, 1);
+-      dest_dma = dma_map_page(dma_chan->device->dev, dest, 0,
+-                              PAGE_SIZE, DMA_FROM_DEVICE);
+-      iop_adma_set_dest(dest_dma, tx, 0);
+-
+-      for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++) {
+-              dma_addr = dma_map_page(dma_chan->device->dev, xor_srcs[i], 0,
+-                      PAGE_SIZE, DMA_TO_DEVICE);
+-              iop_adma_xor_set_src(dma_addr, tx, i);
+-      }
+-
+-      cookie = iop_adma_tx_submit(tx);
+-      iop_adma_issue_pending(dma_chan);
+-      async_tx_ack(tx);
+-      msleep(8);
+-
+-      if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+-              DMA_SUCCESS) {
+-              dev_printk(KERN_ERR, dma_chan->device->dev,
+-                      "Self-test xor timed out, disabling\n");
+-              err = -ENODEV;
+-              goto free_resources;
+-      }
+-
+-      iop_chan = to_iop_adma_chan(dma_chan);
+-      dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
+-              PAGE_SIZE, DMA_FROM_DEVICE);
+-      for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
+-              u32 *ptr = page_address(dest);
+-              if (ptr[i] != cmp_word) {
+-                      dev_printk(KERN_ERR, dma_chan->device->dev,
+-                              "Self-test xor failed compare, disabling\n");
+-                      err = -ENODEV;
+-                      goto free_resources;
+-              }
+-      }
+-      dma_sync_single_for_device(&iop_chan->device->pdev->dev, dest_dma,
+-              PAGE_SIZE, DMA_TO_DEVICE);
+-
+-      /* skip zero sum if the capability is not present */
+-      if (!dma_has_cap(DMA_ZERO_SUM, dma_chan->device->cap_mask))
+-              goto free_resources;
+-
+-      /* zero sum the sources with the destintation page */
+-      for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++)
+-              zero_sum_srcs[i] = xor_srcs[i];
+-      zero_sum_srcs[i] = dest;
+-
+-      zero_sum_result = 1;
+-
+-      tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1,
+-              PAGE_SIZE, &zero_sum_result, 1);
+-      for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) {
+-              dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i],
+-                      0, PAGE_SIZE, DMA_TO_DEVICE);
+-              iop_adma_xor_zero_sum_set_src(dma_addr, tx, i);
+-      }
+-
+-      cookie = iop_adma_tx_submit(tx);
+-      iop_adma_issue_pending(dma_chan);
+-      async_tx_ack(tx);
+-      msleep(8);
+-
+-      if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+-              dev_printk(KERN_ERR, dma_chan->device->dev,
+-                      "Self-test zero sum timed out, disabling\n");
+-              err = -ENODEV;
+-              goto free_resources;
+-      }
+-
+-      if (zero_sum_result != 0) {
+-              dev_printk(KERN_ERR, dma_chan->device->dev,
+-                      "Self-test zero sum failed compare, disabling\n");
+-              err = -ENODEV;
+-              goto free_resources;
+-      }
+-
+-      /* test memset */
+-      tx = iop_adma_prep_dma_memset(dma_chan, 0, PAGE_SIZE, 1);
+-      dma_addr = dma_map_page(dma_chan->device->dev, dest, 0,
+-                      PAGE_SIZE, DMA_FROM_DEVICE);
+-      iop_adma_set_dest(dma_addr, tx, 0);
+-
+-      cookie = iop_adma_tx_submit(tx);
+-      iop_adma_issue_pending(dma_chan);
+-      async_tx_ack(tx);
+-      msleep(8);
+-
+-      if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+-              dev_printk(KERN_ERR, dma_chan->device->dev,
+-                      "Self-test memset timed out, disabling\n");
+-              err = -ENODEV;
+-              goto free_resources;
+-      }
+-
+-      for (i = 0; i < PAGE_SIZE/sizeof(u32); i++) {
+-              u32 *ptr = page_address(dest);
+-              if (ptr[i]) {
+-                      dev_printk(KERN_ERR, dma_chan->device->dev,
+-                              "Self-test memset failed compare, disabling\n");
+-                      err = -ENODEV;
+-                      goto free_resources;
+-              }
+-      }
+-
+-      /* test for non-zero parity sum */
+-      zero_sum_result = 0;
+-      tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1,
+-              PAGE_SIZE, &zero_sum_result, 1);
+-      for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) {
+-              dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i],
+-                      0, PAGE_SIZE, DMA_TO_DEVICE);
+-              iop_adma_xor_zero_sum_set_src(dma_addr, tx, i);
+-      }
+-
+-      cookie = iop_adma_tx_submit(tx);
+-      iop_adma_issue_pending(dma_chan);
+-      async_tx_ack(tx);
+-      msleep(8);
+-
+-      if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+-              dev_printk(KERN_ERR, dma_chan->device->dev,
+-                      "Self-test non-zero sum timed out, disabling\n");
+-              err = -ENODEV;
+-              goto free_resources;
+-      }
+-
+-      if (zero_sum_result != 1) {
+-              dev_printk(KERN_ERR, dma_chan->device->dev,
+-                      "Self-test non-zero sum failed compare, disabling\n");
+-              err = -ENODEV;
+-              goto free_resources;
+-      }
+-
+-free_resources:
+-      iop_adma_free_chan_resources(dma_chan);
+-out:
+-      src_idx = IOP_ADMA_NUM_SRC_TEST;
+-      while (src_idx--)
+-              __free_page(xor_srcs[src_idx]);
+-      __free_page(dest);
+-      return err;
+-}
+-
+-static int __devexit iop_adma_remove(struct platform_device *dev)
+-{
+-      struct iop_adma_device *device = platform_get_drvdata(dev);
+-      struct dma_chan *chan, *_chan;
+-      struct iop_adma_chan *iop_chan;
+-      int i;
+-      struct iop_adma_platform_data *plat_data = dev->dev.platform_data;
+-
+-      dma_async_device_unregister(&device->common);
+-
+-      for (i = 0; i < 3; i++) {
+-              unsigned int irq;
+-              irq = platform_get_irq(dev, i);
+-              free_irq(irq, device);
+-      }
+-
+-      dma_free_coherent(&dev->dev, plat_data->pool_size,
+-                      device->dma_desc_pool_virt, device->dma_desc_pool);
+-
+-      do {
+-              struct resource *res;
+-              res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+-              release_mem_region(res->start, res->end - res->start);
+-      } while (0);
+-
+-      list_for_each_entry_safe(chan, _chan, &device->common.channels,
+-                              device_node) {
+-              iop_chan = to_iop_adma_chan(chan);
+-              list_del(&chan->device_node);
+-              kfree(iop_chan);
+-      }
+-      kfree(device);
+-
+-      return 0;
+-}
+-
+-static int __devinit iop_adma_probe(struct platform_device *pdev)
+-{
+-      struct resource *res;
+-      int ret = 0, i;
+-      struct iop_adma_device *adev;
+-      struct iop_adma_chan *iop_chan;
+-      struct dma_device *dma_dev;
+-      struct iop_adma_platform_data *plat_data = pdev->dev.platform_data;
+-
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      if (!res)
+-              return -ENODEV;
+-
+-      if (!devm_request_mem_region(&pdev->dev, res->start,
+-                              res->end - res->start, pdev->name))
+-              return -EBUSY;
+-
+-      adev = kzalloc(sizeof(*adev), GFP_KERNEL);
+-      if (!adev)
+-              return -ENOMEM;
+-      dma_dev = &adev->common;
+-
+-      /* allocate coherent memory for hardware descriptors
+-       * note: writecombine gives slightly better performance, but
+-       * requires that we explicitly flush the writes
+-       */
+-      if ((adev->dma_desc_pool_virt = dma_alloc_writecombine(&pdev->dev,
+-                                      plat_data->pool_size,
+-                                      &adev->dma_desc_pool,
+-                                      GFP_KERNEL)) == NULL) {
+-              ret = -ENOMEM;
+-              goto err_free_adev;
+-      }
+-
+-      dev_dbg(&pdev->dev, "%s: allocted descriptor pool virt %p phys %p\n",
+-              __FUNCTION__, adev->dma_desc_pool_virt,
+-              (void *) adev->dma_desc_pool);
+-
+-      adev->id = plat_data->hw_id;
+-
+-      /* discover transaction capabilites from the platform data */
+-      dma_dev->cap_mask = plat_data->cap_mask;
+-
+-      adev->pdev = pdev;
+-      platform_set_drvdata(pdev, adev);
+-
+-      INIT_LIST_HEAD(&dma_dev->channels);
+-
+-      /* set base routines */
+-      dma_dev->device_alloc_chan_resources = iop_adma_alloc_chan_resources;
+-      dma_dev->device_free_chan_resources = iop_adma_free_chan_resources;
+-      dma_dev->device_is_tx_complete = iop_adma_is_complete;
+-      dma_dev->device_issue_pending = iop_adma_issue_pending;
+-      dma_dev->device_dependency_added = iop_adma_dependency_added;
+-      dma_dev->dev = &pdev->dev;
+-
+-      /* set prep routines based on capability */
+-      if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask))
+-              dma_dev->device_prep_dma_memcpy = iop_adma_prep_dma_memcpy;
+-      if (dma_has_cap(DMA_MEMSET, dma_dev->cap_mask))
+-              dma_dev->device_prep_dma_memset = iop_adma_prep_dma_memset;
+-      if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
+-              dma_dev->max_xor = iop_adma_get_max_xor();
+-              dma_dev->device_prep_dma_xor = iop_adma_prep_dma_xor;
+-      }
+-      if (dma_has_cap(DMA_ZERO_SUM, dma_dev->cap_mask))
+-              dma_dev->device_prep_dma_zero_sum =
+-                      iop_adma_prep_dma_zero_sum;
+-      if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask))
+-              dma_dev->device_prep_dma_interrupt =
+-                      iop_adma_prep_dma_interrupt;
+-
+-      iop_chan = kzalloc(sizeof(*iop_chan), GFP_KERNEL);
+-      if (!iop_chan) {
+-              ret = -ENOMEM;
+-              goto err_free_dma;
+-      }
+-      iop_chan->device = adev;
+-
+-      iop_chan->mmr_base = devm_ioremap(&pdev->dev, res->start,
+-                                      res->end - res->start);
+-      if (!iop_chan->mmr_base) {
+-              ret = -ENOMEM;
+-              goto err_free_iop_chan;
+-      }
+-      tasklet_init(&iop_chan->irq_tasklet, iop_adma_tasklet, (unsigned long)
+-              iop_chan);
+-
+-      /* clear errors before enabling interrupts */
+-      iop_adma_device_clear_err_status(iop_chan);
+-
+-      for (i = 0; i < 3; i++) {
+-              irq_handler_t handler[] = { iop_adma_eot_handler,
+-                                      iop_adma_eoc_handler,
+-                                      iop_adma_err_handler };
+-              int irq = platform_get_irq(pdev, i);
+-              if (irq < 0) {
+-                      ret = -ENXIO;
+-                      goto err_free_iop_chan;
+-              } else {
+-                      ret = devm_request_irq(&pdev->dev, irq,
+-                                      handler[i], 0, pdev->name, iop_chan);
+-                      if (ret)
+-                              goto err_free_iop_chan;
+-              }
+-      }
+-
+-      spin_lock_init(&iop_chan->lock);
+-      init_timer(&iop_chan->cleanup_watchdog);
+-      iop_chan->cleanup_watchdog.data = (unsigned long) iop_chan;
+-      iop_chan->cleanup_watchdog.function = iop_adma_tasklet;
+-      INIT_LIST_HEAD(&iop_chan->chain);
+-      INIT_LIST_HEAD(&iop_chan->all_slots);
+-      INIT_RCU_HEAD(&iop_chan->common.rcu);
+-      iop_chan->common.device = dma_dev;
+-      list_add_tail(&iop_chan->common.device_node, &dma_dev->channels);
+-
+-      if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
+-              ret = iop_adma_memcpy_self_test(adev);
+-              dev_dbg(&pdev->dev, "memcpy self test returned %d\n", ret);
+-              if (ret)
+-                      goto err_free_iop_chan;
+-      }
+-
+-      if (dma_has_cap(DMA_XOR, dma_dev->cap_mask) ||
+-              dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)) {
+-              ret = iop_adma_xor_zero_sum_self_test(adev);
+-              dev_dbg(&pdev->dev, "xor self test returned %d\n", ret);
+-              if (ret)
+-                      goto err_free_iop_chan;
+-      }
+-
+-      dev_printk(KERN_INFO, &pdev->dev, "Intel(R) IOP: "
+-        "( %s%s%s%s%s%s%s%s%s%s)\n",
+-        dma_has_cap(DMA_PQ_XOR, dma_dev->cap_mask) ? "pq_xor " : "",
+-        dma_has_cap(DMA_PQ_UPDATE, dma_dev->cap_mask) ? "pq_update " : "",
+-        dma_has_cap(DMA_PQ_ZERO_SUM, dma_dev->cap_mask) ? "pq_zero_sum " : "",
+-        dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
+-        dma_has_cap(DMA_DUAL_XOR, dma_dev->cap_mask) ? "dual_xor " : "",
+-        dma_has_cap(DMA_ZERO_SUM, dma_dev->cap_mask) ? "xor_zero_sum " : "",
+-        dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)  ? "fill " : "",
+-        dma_has_cap(DMA_MEMCPY_CRC32C, dma_dev->cap_mask) ? "cpy+crc " : "",
+-        dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
+-        dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
+-
+-      dma_async_device_register(dma_dev);
+-      goto out;
+-
+- err_free_iop_chan:
+-      kfree(iop_chan);
+- err_free_dma:
+-      dma_free_coherent(&adev->pdev->dev, plat_data->pool_size,
+-                      adev->dma_desc_pool_virt, adev->dma_desc_pool);
+- err_free_adev:
+-      kfree(adev);
+- out:
+-      return ret;
+-}
+-
+-static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
+-{
+-      struct iop_adma_desc_slot *sw_desc, *grp_start;
+-      dma_cookie_t cookie;
+-      int slot_cnt, slots_per_op;
+-
+-      dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+-
+-      spin_lock_bh(&iop_chan->lock);
+-      slot_cnt = iop_chan_memcpy_slot_count(0, &slots_per_op);
+-      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+-      if (sw_desc) {
+-              grp_start = sw_desc->group_head;
+-
+-              list_splice_init(&sw_desc->group_list, &iop_chan->chain);
+-              sw_desc->async_tx.ack = 1;
+-              iop_desc_init_memcpy(grp_start, 0);
+-              iop_desc_set_byte_count(grp_start, iop_chan, 0);
+-              iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+-              iop_desc_set_memcpy_src_addr(grp_start, 0);
+-
+-              cookie = iop_chan->common.cookie;
+-              cookie++;
+-              if (cookie <= 1)
+-                      cookie = 2;
+-
+-              /* initialize the completed cookie to be less than
+-               * the most recently used cookie
+-               */
+-              iop_chan->completed_cookie = cookie - 1;
+-              iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
+-
+-              /* channel should not be busy */
+-              BUG_ON(iop_chan_is_busy(iop_chan));
+-
+-              /* clear any prior error-status bits */
+-              iop_adma_device_clear_err_status(iop_chan);
+-
+-              /* disable operation */
+-              iop_chan_disable(iop_chan);
+-
+-              /* set the descriptor address */
+-              iop_chan_set_next_descriptor(iop_chan, sw_desc->phys);
+-
+-              /* 1/ don't add pre-chained descriptors
+-               * 2/ dummy read to flush next_desc write
+-               */
+-              BUG_ON(iop_desc_get_next_desc(sw_desc));
+-
+-              /* run the descriptor */
+-              iop_chan_enable(iop_chan);
+-      } else
+-              dev_printk(KERN_ERR, iop_chan->device->common.dev,
+-                       "failed to allocate null descriptor\n");
+-      spin_unlock_bh(&iop_chan->lock);
+-}
+-
+-static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
+-{
+-      struct iop_adma_desc_slot *sw_desc, *grp_start;
+-      dma_cookie_t cookie;
+-      int slot_cnt, slots_per_op;
+-
+-      dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+-
+-      spin_lock_bh(&iop_chan->lock);
+-      slot_cnt = iop_chan_xor_slot_count(0, 2, &slots_per_op);
+-      sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+-      if (sw_desc) {
+-              grp_start = sw_desc->group_head;
+-              list_splice_init(&sw_desc->group_list, &iop_chan->chain);
+-              sw_desc->async_tx.ack = 1;
+-              iop_desc_init_null_xor(grp_start, 2, 0);
+-              iop_desc_set_byte_count(grp_start, iop_chan, 0);
+-              iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+-              iop_desc_set_xor_src_addr(grp_start, 0, 0);
+-              iop_desc_set_xor_src_addr(grp_start, 1, 0);
+-
+-              cookie = iop_chan->common.cookie;
+-              cookie++;
+-              if (cookie <= 1)
+-                      cookie = 2;
+-
+-              /* initialize the completed cookie to be less than
+-               * the most recently used cookie
+-               */
+-              iop_chan->completed_cookie = cookie - 1;
+-              iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
+-
+-              /* channel should not be busy */
+-              BUG_ON(iop_chan_is_busy(iop_chan));
+-
+-              /* clear any prior error-status bits */
+-              iop_adma_device_clear_err_status(iop_chan);
+-
+-              /* disable operation */
+-              iop_chan_disable(iop_chan);
+-
+-              /* set the descriptor address */
+-              iop_chan_set_next_descriptor(iop_chan, sw_desc->phys);
+-
+-              /* 1/ don't add pre-chained descriptors
+-               * 2/ dummy read to flush next_desc write
+-               */
+-              BUG_ON(iop_desc_get_next_desc(sw_desc));
+-
+-              /* run the descriptor */
+-              iop_chan_enable(iop_chan);
+-      } else
+-              dev_printk(KERN_ERR, iop_chan->device->common.dev,
+-                      "failed to allocate null descriptor\n");
+-      spin_unlock_bh(&iop_chan->lock);
+-}
+-
+-static struct platform_driver iop_adma_driver = {
+-      .probe          = iop_adma_probe,
+-      .remove         = iop_adma_remove,
+-      .driver         = {
+-              .owner  = THIS_MODULE,
+-              .name   = "iop-adma",
+-      },
+-};
+-
+-static int __init iop_adma_init (void)
+-{
+-      /* it's currently unsafe to unload this module */
+-      /* if forced, worst case is that rmmod hangs */
+-      __unsafe(THIS_MODULE);
+-
+-      return platform_driver_register(&iop_adma_driver);
+-}
+-
+-static void __exit iop_adma_exit (void)
+-{
+-      platform_driver_unregister(&iop_adma_driver);
+-      return;
+-}
+-
+-module_init(iop_adma_init);
+-module_exit(iop_adma_exit);
+-
+-MODULE_AUTHOR("Intel Corporation");
+-MODULE_DESCRIPTION("IOP ADMA Engine Driver");
+-MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/drivers/edac/edac_mc.c linux-2.6.22-570/drivers/edac/edac_mc.c
+--- linux-2.6.22-590/drivers/edac/edac_mc.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/edac/edac_mc.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1906,7 +1906,6 @@
  
--      ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
-       if (cmdiocb->context_un.mbox)
-               mbox = cmdiocb->context_un.mbox;
+ static int edac_kernel_thread(void *arg)
+ {
+-      set_freezable();
+       while (!kthread_should_stop()) {
+               do_edac_check();
  
--
-       /* Check to see if link went down during discovery */
--      if (lpfc_els_chk_latt(phba) || !ndlp) {
-+      if (!ndlp || lpfc_els_chk_latt(vport)) {
-               if (mbox) {
-                       mp = (struct lpfc_dmabuf *) mbox->context1;
-                       if (mp) {
-@@ -1859,11 +2152,16 @@
-               goto out;
-       }
+diff -Nurb linux-2.6.22-590/drivers/firmware/dcdbas.c linux-2.6.22-570/drivers/firmware/dcdbas.c
+--- linux-2.6.22-590/drivers/firmware/dcdbas.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/firmware/dcdbas.c 2007-07-08 19:32:17.000000000 -0400
+@@ -149,9 +149,8 @@
+       return count;
+ }
  
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
-+              "ACC cmpl:        status:x%x/x%x did:x%x",
-+              irsp->ulpStatus, irsp->un.ulpWord[4],
-+              irsp->un.rcvels.remoteID);
-+
-       /* ELS response tag <ulpIoTag> completes */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0110 ELS response tag x%x completes "
-+                      "%d (%d):0110 ELS response tag x%x completes "
-                       "Data: x%x x%x x%x x%x x%x x%x x%x\n",
--                      phba->brd_no,
-+                      phba->brd_no, vport->vpi,
-                       cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus,
-                       rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout,
-                       ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
-@@ -1872,11 +2170,19 @@
-       if (mbox) {
-               if ((rspiocb->iocb.ulpStatus == 0)
-                   && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
--                      lpfc_unreg_rpi(phba, ndlp);
--                      mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
-+                      lpfc_unreg_rpi(vport, ndlp);
-                       mbox->context2 = lpfc_nlp_get(ndlp);
-+                      mbox->vport = vport;
-+                      if (ndlp->nlp_flag & NLP_RM_DFLT_RPI) {
-+                              mbox->mbox_flag |= LPFC_MBX_IMED_UNREG;
-+                              mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
-+                      }
-+                      else {
-+                              mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
-                       ndlp->nlp_prev_state = ndlp->nlp_state;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
-+                              lpfc_nlp_set_state(vport, ndlp,
-+                                         NLP_STE_REG_LOGIN_ISSUE);
-+                      }
-                       if (lpfc_sli_issue_mbox(phba, mbox,
-                                               (MBX_NOWAIT | MBX_STOP_IOCB))
-                           != MBX_NOT_FINISHED) {
-@@ -1886,17 +2192,13 @@
-                       /* NOTE: we should have messages for unsuccessful
-                          reglogin */
-               } else {
--                      /* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */
--                      if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
--                            ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
--                             (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
--                             (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) {
--                              if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
--                                      lpfc_drop_node(phba, ndlp);
-+                      /* Do not drop node for lpfc_els_abort'ed ELS cmds */
-+                      if (!lpfc_error_lost_link(irsp) &&
-+                          ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
-+                              lpfc_drop_node(vport, ndlp);
-                                       ndlp = NULL;
-                               }
-                       }
--              }
-               mp = (struct lpfc_dmabuf *) mbox->context1;
-               if (mp) {
-                       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-@@ -1906,19 +2208,21 @@
-       }
- out:
-       if (ndlp) {
--              spin_lock_irq(phba->host->host_lock);
--              ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-+              ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI);
-+              spin_unlock_irq(shost->host_lock);
-       }
-       lpfc_els_free_iocb(phba, cmdiocb);
-       return;
+-static ssize_t smi_data_read(struct kobject *kobj,
+-                           struct bin_attribute *bin_attr,
+-                           char *buf, loff_t pos, size_t count)
++static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos,
++                           size_t count)
+ {
+       size_t max_read;
+       ssize_t ret;
+@@ -171,9 +170,8 @@
+       return ret;
  }
  
- int
--lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
--               struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp,
--               LPFC_MBOXQ_t * mbox, uint8_t newnode)
-+lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
-+               struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
-+               LPFC_MBOXQ_t *mbox, uint8_t newnode)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-       IOCB_t *icmd;
-       IOCB_t *oldcmd;
-       struct lpfc_iocbq *elsiocb;
-@@ -1935,22 +2239,29 @@
+-static ssize_t smi_data_write(struct kobject *kobj,
+-                            struct bin_attribute *bin_attr,
+-                            char *buf, loff_t pos, size_t count)
++static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos,
++                            size_t count)
+ {
+       ssize_t ret;
  
-       switch (flag) {
-       case ELS_CMD_ACC:
--              cmdsize = sizeof (uint32_t);
--              elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
-+              cmdsize = sizeof(uint32_t);
-+              elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
-                                       ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
-               if (!elsiocb) {
-+                      spin_lock_irq(shost->host_lock);
-                       ndlp->nlp_flag &= ~NLP_LOGO_ACC;
-+                      spin_unlock_irq(shost->host_lock);
-                       return 1;
-               }
-+
-               icmd = &elsiocb->iocb;
-               icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
-               pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
-               *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
--              pcmd += sizeof (uint32_t);
-+              pcmd += sizeof(uint32_t);
-+
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
-+                      "Issue ACC:       did:x%x flg:x%x",
-+                      ndlp->nlp_DID, ndlp->nlp_flag, 0);
-               break;
-       case ELS_CMD_PLOGI:
--              cmdsize = (sizeof (struct serv_parm) + sizeof (uint32_t));
--              elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
-+              cmdsize = (sizeof(struct serv_parm) + sizeof(uint32_t));
-+              elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
-                                       ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
-               if (!elsiocb)
-                       return 1;
-@@ -1963,12 +2274,16 @@
-                       elsiocb->context_un.mbox = mbox;
+diff -Nurb linux-2.6.22-590/drivers/firmware/dcdbas.h linux-2.6.22-570/drivers/firmware/dcdbas.h
+--- linux-2.6.22-590/drivers/firmware/dcdbas.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/firmware/dcdbas.h 2007-07-08 19:32:17.000000000 -0400
+@@ -67,7 +67,8 @@
+ #define DCDBAS_BIN_ATTR_RW(_name) \
+ struct bin_attribute bin_attr_##_name = { \
+       .attr =  { .name = __stringify(_name), \
+-                 .mode = 0600 }, \
++                 .mode = 0600, \
++                 .owner = THIS_MODULE }, \
+       .read =  _name##_read, \
+       .write = _name##_write, \
+ }
+diff -Nurb linux-2.6.22-590/drivers/firmware/dell_rbu.c linux-2.6.22-570/drivers/firmware/dell_rbu.c
+--- linux-2.6.22-590/drivers/firmware/dell_rbu.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/firmware/dell_rbu.c       2007-07-08 19:32:17.000000000 -0400
+@@ -543,9 +543,8 @@
+       return ret_count;
+ }
  
-               *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
--              pcmd += sizeof (uint32_t);
--              memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
-+              pcmd += sizeof(uint32_t);
-+              memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
-+
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
-+                      "Issue ACC PLOGI: did:x%x flg:x%x",
-+                      ndlp->nlp_DID, ndlp->nlp_flag, 0);
-               break;
-       case ELS_CMD_PRLO:
--              cmdsize = sizeof (uint32_t) + sizeof (PRLO);
--              elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
-+              cmdsize = sizeof(uint32_t) + sizeof(PRLO);
-+              elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
-                                            ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
-               if (!elsiocb)
-                       return 1;
-@@ -1978,10 +2293,14 @@
-               pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+-static ssize_t read_rbu_data(struct kobject *kobj,
+-                           struct bin_attribute *bin_attr,
+-                           char *buffer, loff_t pos, size_t count)
++static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
++      loff_t pos, size_t count)
+ {
+       ssize_t ret_count = 0;
  
-               memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
--                     sizeof (uint32_t) + sizeof (PRLO));
-+                     sizeof(uint32_t) + sizeof(PRLO));
-               *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
-               els_pkt_ptr = (ELS_PKT *) pcmd;
-               els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
-+
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
-+                      "Issue ACC PRLO:  did:x%x flg:x%x",
-+                      ndlp->nlp_DID, ndlp->nlp_flag, 0);
-               break;
-       default:
-               return 1;
-@@ -1994,25 +2313,23 @@
+@@ -592,9 +591,8 @@
+       spin_unlock(&rbu_data.lock);
+ }
  
-       /* Xmit ELS ACC response tag <ulpIoTag> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
-+                      "%d (%d):0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
-                       "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
--                      phba->brd_no, elsiocb->iotag,
-+                      phba->brd_no, vport->vpi, elsiocb->iotag,
-                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
-                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+-static ssize_t read_rbu_image_type(struct kobject *kobj,
+-                                 struct bin_attribute *bin_attr,
+-                                 char *buffer, loff_t pos, size_t count)
++static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
++      loff_t pos, size_t count)
+ {
+       int size = 0;
+       if (!pos)
+@@ -602,9 +600,8 @@
+       return size;
+ }
  
-       if (ndlp->nlp_flag & NLP_LOGO_ACC) {
--              spin_lock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag &= ~NLP_LOGO_ACC;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-               elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
-       } else {
--              elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
-+              elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
      }
+-static ssize_t write_rbu_image_type(struct kobject *kobj,
+-                                  struct bin_attribute *bin_attr,
+-                                  char *buffer, loff_t pos, size_t count)
++static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
++      loff_t pos, size_t count)
+ {
+       int rc = count;
+       int req_firm_rc = 0;
+@@ -663,9 +660,8 @@
+       return rc;
+ }
  
-       phba->fc_stat.elsXmitACC++;
--      spin_lock_irq(phba->host->host_lock);
-       rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
--      spin_unlock_irq(phba->host->host_lock);
-       if (rc == IOCB_ERROR) {
-               lpfc_els_free_iocb(phba, elsiocb);
-               return 1;
-@@ -2021,9 +2338,11 @@
+-static ssize_t read_rbu_packet_size(struct kobject *kobj,
+-                                  struct bin_attribute *bin_attr,
+-                                  char *buffer, loff_t pos, size_t count)
++static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,
++      loff_t pos, size_t count)
+ {
+       int size = 0;
+       if (!pos) {
+@@ -676,9 +672,8 @@
+       return size;
  }
  
- int
--lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError,
--                  struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
-+lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
-+                  struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
-+                  LPFC_MBOXQ_t *mbox)
+-static ssize_t write_rbu_packet_size(struct kobject *kobj,
+-                                   struct bin_attribute *bin_attr,
+-                                   char *buffer, loff_t pos, size_t count)
++static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,
++      loff_t pos, size_t count)
  {
-+      struct lpfc_hba  *phba = vport->phba;
-       IOCB_t *icmd;
-       IOCB_t *oldcmd;
-       struct lpfc_iocbq *elsiocb;
-@@ -2036,9 +2355,9 @@
-       psli = &phba->sli;
-       pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
+       unsigned long temp;
+       spin_lock(&rbu_data.lock);
+@@ -692,18 +687,18 @@
+ }
  
--      cmdsize = 2 * sizeof (uint32_t);
--      elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
--                                      ndlp, ndlp->nlp_DID, ELS_CMD_LS_RJT);
-+      cmdsize = 2 * sizeof(uint32_t);
-+      elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
-+                                   ndlp->nlp_DID, ELS_CMD_LS_RJT);
-       if (!elsiocb)
-               return 1;
+ static struct bin_attribute rbu_data_attr = {
+-      .attr = {.name = "data", .mode = 0444},
++      .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
+       .read = read_rbu_data,
+ };
  
-@@ -2048,22 +2367,30 @@
-       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+ static struct bin_attribute rbu_image_type_attr = {
+-      .attr = {.name = "image_type", .mode = 0644},
++      .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
+       .read = read_rbu_image_type,
+       .write = write_rbu_image_type,
+ };
  
-       *((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT;
--      pcmd += sizeof (uint32_t);
-+      pcmd += sizeof(uint32_t);
-       *((uint32_t *) (pcmd)) = rejectError;
+ static struct bin_attribute rbu_packet_size_attr = {
+-      .attr = {.name = "packet_size", .mode = 0644},
++      .attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644},
+       .read = read_rbu_packet_size,
+       .write = write_rbu_packet_size,
+ };
+diff -Nurb linux-2.6.22-590/drivers/firmware/edd.c linux-2.6.22-570/drivers/firmware/edd.c
+--- linux-2.6.22-590/drivers/firmware/edd.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/firmware/edd.c    2007-07-08 19:32:17.000000000 -0400
+@@ -74,7 +74,7 @@
  
-+      if (mbox) {
-+              elsiocb->context_un.mbox = mbox;
-+              elsiocb->context1 = lpfc_nlp_get(ndlp);
-+      }
-+
-       /* Xmit ELS RJT <err> response tag <ulpIoTag> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0129 Xmit ELS RJT x%x response tag x%x xri x%x, "
--                      "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
--                      phba->brd_no, rejectError, elsiocb->iotag,
-+                      "%d (%d):0129 Xmit ELS RJT x%x response tag x%x "
-+                      "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
-+                      "rpi x%x\n",
-+                      phba->brd_no, vport->vpi, rejectError, elsiocb->iotag,
-                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
-                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+ #define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \
+ struct edd_attribute edd_attr_##_name = {     \
+-      .attr = {.name = __stringify(_name), .mode = _mode },   \
++      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },     \
+       .show   = _show,                                \
+       .test   = _test,                                \
+ };
+diff -Nurb linux-2.6.22-590/drivers/firmware/efivars.c linux-2.6.22-570/drivers/firmware/efivars.c
+--- linux-2.6.22-590/drivers/firmware/efivars.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/firmware/efivars.c        2007-07-08 19:32:17.000000000 -0400
+@@ -131,21 +131,21 @@
  
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
-+              "Issue LS_RJT:    did:x%x flg:x%x err:x%x",
-+              ndlp->nlp_DID, ndlp->nlp_flag, rejectError);
-+
-       phba->fc_stat.elsXmitLSRJT++;
--      elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
--      spin_lock_irq(phba->host->host_lock);
-+      elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
-       rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
--      spin_unlock_irq(phba->host->host_lock);
-       if (rc == IOCB_ERROR) {
-               lpfc_els_free_iocb(phba, elsiocb);
-               return 1;
-@@ -2072,25 +2399,22 @@
+ #define EFI_ATTR(_name, _mode, _show, _store) \
+ struct subsys_attribute efi_attr_##_name = { \
+-      .attr = {.name = __stringify(_name), .mode = _mode}, \
++      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+       .show = _show, \
+       .store = _store, \
+ };
+ #define EFIVAR_ATTR(_name, _mode, _show, _store) \
+ struct efivar_attribute efivar_attr_##_name = { \
+-      .attr = {.name = __stringify(_name), .mode = _mode}, \
++      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+       .show = _show, \
+       .store = _store, \
+ };
+ #define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \
+ struct subsys_attribute var_subsys_attr_##_name = { \
+-      .attr = {.name = __stringify(_name), .mode = _mode}, \
++      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+       .show = _show, \
+       .store = _store, \
+ };
+diff -Nurb linux-2.6.22-590/drivers/i2c/chips/eeprom.c linux-2.6.22-570/drivers/i2c/chips/eeprom.c
+--- linux-2.6.22-590/drivers/i2c/chips/eeprom.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/i2c/chips/eeprom.c        2008-01-23 19:15:55.000000000 -0500
+@@ -110,8 +110,7 @@
+       mutex_unlock(&data->update_lock);
  }
  
- int
--lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba,
--                     struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
-+lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
-+                     struct lpfc_nodelist *ndlp)
- {
-+      struct lpfc_hba  *phba = vport->phba;
-+      struct lpfc_sli  *psli = &phba->sli;
-+      struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
-       ADISC *ap;
--      IOCB_t *icmd;
--      IOCB_t *oldcmd;
-+      IOCB_t *icmd, *oldcmd;
-       struct lpfc_iocbq *elsiocb;
--      struct lpfc_sli_ring *pring;
--      struct lpfc_sli *psli;
-       uint8_t *pcmd;
-       uint16_t cmdsize;
-       int rc;
+-static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+-                         char *buf, loff_t off, size_t count)
++static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+       struct eeprom_data *data = i2c_get_clientdata(client);
+@@ -151,6 +150,7 @@
+       .attr = {
+               .name = "eeprom",
+               .mode = S_IRUGO,
++              .owner = THIS_MODULE,
+       },
+       .size = EEPROM_SIZE,
+       .read = eeprom_read,
+diff -Nurb linux-2.6.22-590/drivers/i2c/chips/max6875.c linux-2.6.22-570/drivers/i2c/chips/max6875.c
+--- linux-2.6.22-590/drivers/i2c/chips/max6875.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/i2c/chips/max6875.c       2007-07-08 19:32:17.000000000 -0400
+@@ -125,9 +125,8 @@
+       mutex_unlock(&data->update_lock);
+ }
  
--      psli = &phba->sli;
--      pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
--
--      cmdsize = sizeof (uint32_t) + sizeof (ADISC);
--      elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
--                                      ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
-+      cmdsize = sizeof(uint32_t) + sizeof(ADISC);
-+      elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
-+                                   ndlp->nlp_DID, ELS_CMD_ACC);
-       if (!elsiocb)
-               return 1;
+-static ssize_t max6875_read(struct kobject *kobj,
+-                          struct bin_attribute *bin_attr,
+-                          char *buf, loff_t off, size_t count)
++static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off,
++                          size_t count)
+ {
+       struct i2c_client *client = kobj_to_i2c_client(kobj);
+       struct max6875_data *data = i2c_get_clientdata(client);
+@@ -153,6 +152,7 @@
+       .attr = {
+               .name = "eeprom",
+               .mode = S_IRUGO,
++              .owner = THIS_MODULE,
+       },
+       .size = USER_EEPROM_SIZE,
+       .read = max6875_read,
+diff -Nurb linux-2.6.22-590/drivers/ieee1394/ieee1394_core.c linux-2.6.22-570/drivers/ieee1394/ieee1394_core.c
+--- linux-2.6.22-590/drivers/ieee1394/ieee1394_core.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/ieee1394/ieee1394_core.c  2008-01-23 19:15:55.000000000 -0500
+@@ -30,7 +30,6 @@
+ #include <linux/moduleparam.h>
+ #include <linux/bitops.h>
+ #include <linux/kdev_t.h>
+-#include <linux/freezer.h>
+ #include <linux/suspend.h>
+ #include <linux/kthread.h>
+ #include <linux/preempt.h>
+@@ -1134,6 +1133,8 @@
+       struct list_head tmp;
+       int may_schedule;
  
-@@ -2100,28 +2424,30 @@
++      current->flags |= PF_NOFREEZE;
++
+       while (!kthread_should_stop()) {
  
-       /* Xmit ADISC ACC response tag <ulpIoTag> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0130 Xmit ADISC ACC response iotag x%x xri: "
-+                      "%d (%d):0130 Xmit ADISC ACC response iotag x%x xri: "
-                       "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n",
--                      phba->brd_no, elsiocb->iotag,
-+                      phba->brd_no, vport->vpi, elsiocb->iotag,
-                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
-                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+               INIT_LIST_HEAD(&tmp);
+diff -Nurb linux-2.6.22-590/drivers/ieee1394/nodemgr.c linux-2.6.22-570/drivers/ieee1394/nodemgr.c
+--- linux-2.6.22-590/drivers/ieee1394/nodemgr.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/ieee1394/nodemgr.c        2007-07-08 19:32:17.000000000 -0400
+@@ -1669,7 +1669,6 @@
+       unsigned int g, generation = 0;
+       int i, reset_cycles = 0;
  
-       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+-      set_freezable();
+       /* Setup our device-model entries */
+       nodemgr_create_host_dev_files(host);
  
-       *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
--      pcmd += sizeof (uint32_t);
-+      pcmd += sizeof(uint32_t);
+diff -Nurb linux-2.6.22-590/drivers/ieee1394/sbp2.c linux-2.6.22-570/drivers/ieee1394/sbp2.c
+--- linux-2.6.22-590/drivers/ieee1394/sbp2.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/ieee1394/sbp2.c   2008-01-23 19:15:55.000000000 -0500
+@@ -1505,6 +1505,69 @@
+       }
+ }
  
-       ap = (ADISC *) (pcmd);
-       ap->hardAL_PA = phba->fc_pref_ALPA;
--      memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));
--      memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
--      ap->DID = be32_to_cpu(phba->fc_myDID);
-+      memcpy(&ap->portName, &vport->fc_portname, sizeof(struct lpfc_name));
-+      memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
-+      ap->DID = be32_to_cpu(vport->fc_myDID);
++static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
++                                      struct sbp2_fwhost_info *hi,
++                                      struct sbp2_command_info *cmd,
++                                      struct scatterlist *sgpnt,
++                                      u32 orb_direction,
++                                      unsigned int scsi_request_bufflen,
++                                      void *scsi_request_buffer,
++                                      enum dma_data_direction dma_dir)
++{
++      cmd->dma_dir = dma_dir;
++      cmd->dma_size = scsi_request_bufflen;
++      cmd->dma_type = CMD_DMA_SINGLE;
++      cmd->cmd_dma = dma_map_single(hi->host->device.parent,
++                                    scsi_request_buffer,
++                                    cmd->dma_size, cmd->dma_dir);
++      orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
++      orb->misc |= ORB_SET_DIRECTION(orb_direction);
++
++      /* handle case where we get a command w/o s/g enabled
++       * (but check for transfers larger than 64K) */
++      if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
++
++              orb->data_descriptor_lo = cmd->cmd_dma;
++              orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
++
++      } else {
++              /* The buffer is too large. Turn this into page tables. */
++
++              struct sbp2_unrestricted_page_table *sg_element =
++                                              &cmd->scatter_gather_element[0];
++              u32 sg_count, sg_len;
++              dma_addr_t sg_addr;
++
++              orb->data_descriptor_lo = cmd->sge_dma;
++              orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
++
++              /* fill out our SBP-2 page tables; split up the large buffer */
++              sg_count = 0;
++              sg_len = scsi_request_bufflen;
++              sg_addr = cmd->cmd_dma;
++              while (sg_len) {
++                      sg_element[sg_count].segment_base_lo = sg_addr;
++                      if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
++                              sg_element[sg_count].length_segment_base_hi =
++                                      PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
++                              sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
++                              sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
++                      } else {
++                              sg_element[sg_count].length_segment_base_hi =
++                                      PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
++                              sg_len = 0;
++                      }
++                      sg_count++;
++              }
++
++              orb->misc |= ORB_SET_DATA_SIZE(sg_count);
++
++              sbp2util_cpu_to_be32_buffer(sg_element,
++                              (sizeof(struct sbp2_unrestricted_page_table)) *
++                              sg_count);
++      }
++}
 +
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
-+              "Issue ACC ADISC: did:x%x flg:x%x",
-+              ndlp->nlp_DID, ndlp->nlp_flag, 0);
+ static void sbp2_create_command_orb(struct sbp2_lu *lu,
+                                   struct sbp2_command_info *cmd,
+                                   unchar *scsi_cmd,
+@@ -1548,9 +1611,13 @@
+               orb->data_descriptor_hi = 0x0;
+               orb->data_descriptor_lo = 0x0;
+               orb->misc |= ORB_SET_DIRECTION(1);
+-      } else
++      } else if (scsi_use_sg)
+               sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sgpnt,
+                                        orb_direction, dma_dir);
++      else
++              sbp2_prep_command_orb_no_sg(orb, hi, cmd, sgpnt, orb_direction,
++                                          scsi_request_bufflen,
++                                          scsi_request_buffer, dma_dir);
  
-       phba->fc_stat.elsXmitACC++;
--      elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
--      spin_lock_irq(phba->host->host_lock);
-+      elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
-       rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
--      spin_unlock_irq(phba->host->host_lock);
-       if (rc == IOCB_ERROR) {
-               lpfc_els_free_iocb(phba, elsiocb);
-               return 1;
-@@ -2130,9 +2456,10 @@
- }
+       sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
  
- int
--lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb,
-+lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
-                     struct lpfc_nodelist *ndlp)
+@@ -1639,15 +1706,15 @@
+                            void (*done)(struct scsi_cmnd *))
  {
-+      struct lpfc_hba  *phba = vport->phba;
-       PRLI *npr;
-       lpfc_vpd_t *vpd;
-       IOCB_t *icmd;
-@@ -2147,8 +2474,8 @@
-       psli = &phba->sli;
-       pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
+       unchar *scsi_cmd = (unchar *)SCpnt->cmnd;
+-      unsigned int request_bufflen = scsi_bufflen(SCpnt);
++      unsigned int request_bufflen = SCpnt->request_bufflen;
+       struct sbp2_command_info *cmd;
  
--      cmdsize = sizeof (uint32_t) + sizeof (PRLI);
--      elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp,
-+      cmdsize = sizeof(uint32_t) + sizeof(PRLI);
-+      elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
-               ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
-       if (!elsiocb)
-               return 1;
-@@ -2159,19 +2486,19 @@
+       cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
+       if (!cmd)
+               return -EIO;
  
-       /* Xmit PRLI ACC response tag <ulpIoTag> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0131 Xmit PRLI ACC response tag x%x xri x%x, "
-+                      "%d (%d):0131 Xmit PRLI ACC response tag x%x xri x%x, "
-                       "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
--                      phba->brd_no, elsiocb->iotag,
-+                      phba->brd_no, vport->vpi, elsiocb->iotag,
-                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
-                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+-      sbp2_create_command_orb(lu, cmd, scsi_cmd, scsi_sg_count(SCpnt),
+-                              request_bufflen, scsi_sglist(SCpnt),
++      sbp2_create_command_orb(lu, cmd, scsi_cmd, SCpnt->use_sg,
++                              request_bufflen, SCpnt->request_buffer,
+                               SCpnt->sc_data_direction);
+       sbp2_link_orb_command(lu, cmd);
  
-       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+diff -Nurb linux-2.6.22-590/drivers/infiniband/core/addr.c linux-2.6.22-570/drivers/infiniband/core/addr.c
+--- linux-2.6.22-590/drivers/infiniband/core/addr.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/infiniband/core/addr.c    2007-07-08 19:32:17.000000000 -0400
+@@ -110,7 +110,7 @@
+       __be32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+       int ret;
  
-       *((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK));
--      pcmd += sizeof (uint32_t);
-+      pcmd += sizeof(uint32_t);
+-      dev = ip_dev_find(&init_net, ip);
++      dev = ip_dev_find(ip);
+       if (!dev)
+               return -EADDRNOTAVAIL;
  
-       /* For PRLI, remainder of payload is PRLI parameter page */
--      memset(pcmd, 0, sizeof (PRLI));
-+      memset(pcmd, 0, sizeof(PRLI));
+@@ -157,7 +157,6 @@
+       u32 dst_ip = dst_in->sin_addr.s_addr;
  
-       npr = (PRLI *) pcmd;
-       vpd = &phba->vpd;
-@@ -2193,12 +2520,14 @@
-       npr->prliType = PRLI_FCP_TYPE;
-       npr->initiatorFunc = 1;
+       memset(&fl, 0, sizeof fl);
+-      fl.fl_net = &init_net;
+       fl.nl_u.ip4_u.daddr = dst_ip;
+       if (ip_route_output_key(&rt, &fl))
+               return;
+@@ -179,7 +178,6 @@
+       int ret;
  
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
-+              "Issue ACC PRLI:  did:x%x flg:x%x",
-+              ndlp->nlp_DID, ndlp->nlp_flag, 0);
-+
-       phba->fc_stat.elsXmitACC++;
--      elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
-+      elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
+       memset(&fl, 0, sizeof fl);
+-      fl.fl_net = &init_net;
+       fl.nl_u.ip4_u.daddr = dst_ip;
+       fl.nl_u.ip4_u.saddr = src_ip;
+       ret = ip_route_output_key(&rt, &fl);
+@@ -264,7 +262,7 @@
+       __be32 dst_ip = dst_in->sin_addr.s_addr;
+       int ret;
  
--      spin_lock_irq(phba->host->host_lock);
-       rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
--      spin_unlock_irq(phba->host->host_lock);
-       if (rc == IOCB_ERROR) {
-               lpfc_els_free_iocb(phba, elsiocb);
-               return 1;
-@@ -2207,12 +2536,12 @@
- }
+-      dev = ip_dev_find(&init_net, dst_ip);
++      dev = ip_dev_find(dst_ip);
+       if (!dev)
+               return -EADDRNOTAVAIL;
  
- static int
--lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format,
-+lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
-                     struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
- {
-+      struct lpfc_hba  *phba = vport->phba;
-       RNID *rn;
--      IOCB_t *icmd;
--      IOCB_t *oldcmd;
-+      IOCB_t *icmd, *oldcmd;
-       struct lpfc_iocbq *elsiocb;
-       struct lpfc_sli_ring *pring;
-       struct lpfc_sli *psli;
-@@ -2223,13 +2552,13 @@
-       psli = &phba->sli;
-       pring = &psli->ring[LPFC_ELS_RING];
+diff -Nurb linux-2.6.22-590/drivers/infiniband/core/cma.c linux-2.6.22-570/drivers/infiniband/core/cma.c
+--- linux-2.6.22-590/drivers/infiniband/core/cma.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/infiniband/core/cma.c     2007-07-08 19:32:17.000000000 -0400
+@@ -1267,7 +1267,7 @@
+       atomic_inc(&conn_id->dev_remove);
+       conn_id->state = CMA_CONNECT;
  
--      cmdsize = sizeof (uint32_t) + sizeof (uint32_t)
--              + (2 * sizeof (struct lpfc_name));
-+      cmdsize = sizeof(uint32_t) + sizeof(uint32_t)
-+                                      + (2 * sizeof(struct lpfc_name));
-       if (format)
--              cmdsize += sizeof (RNID_TOP_DISC);
-+              cmdsize += sizeof(RNID_TOP_DISC);
+-      dev = ip_dev_find(&init_net, iw_event->local_addr.sin_addr.s_addr);
++      dev = ip_dev_find(iw_event->local_addr.sin_addr.s_addr);
+       if (!dev) {
+               ret = -EADDRNOTAVAIL;
+               cma_enable_remove(conn_id);
+@@ -1880,18 +1880,18 @@
+       if (ret)
+               goto err1;
  
--      elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
--                                      ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
-+      elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
-+                                   ndlp->nlp_DID, ELS_CMD_ACC);
-       if (!elsiocb)
-               return 1;
+-      if (port > init_net.sysctl_local_port_range[1]) {
+-              if (next_port != init_net.sysctl_local_port_range[0]) {
++      if (port > sysctl_local_port_range[1]) {
++              if (next_port != sysctl_local_port_range[0]) {
+                       idr_remove(ps, port);
+-                      next_port = init_net.sysctl_local_port_range[0];
++                      next_port = sysctl_local_port_range[0];
+                       goto retry;
+               }
+               ret = -EADDRNOTAVAIL;
+               goto err2;
+       }
  
-@@ -2239,30 +2568,30 @@
+-      if (port == init_net.sysctl_local_port_range[1])
+-              next_port = init_net.sysctl_local_port_range[0];
++      if (port == sysctl_local_port_range[1])
++              next_port = sysctl_local_port_range[0];
+       else
+               next_port = port + 1;
  
-       /* Xmit RNID ACC response tag <ulpIoTag> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0132 Xmit RNID ACC response tag x%x "
-+                      "%d (%d):0132 Xmit RNID ACC response tag x%x "
-                       "xri x%x\n",
--                      phba->brd_no, elsiocb->iotag,
-+                      phba->brd_no, vport->vpi, elsiocb->iotag,
-                       elsiocb->iocb.ulpContext);
+@@ -2774,9 +2774,8 @@
  
-       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+       get_random_bytes(&next_port, sizeof next_port);
+       next_port = ((unsigned int) next_port %
+-                   (init_net.sysctl_local_port_range[1] - 
+-                    init_net.sysctl_local_port_range[0])) +
+-                  init_net.sysctl_local_port_range[0];
++                  (sysctl_local_port_range[1] - sysctl_local_port_range[0])) +
++                  sysctl_local_port_range[0];
+       cma_wq = create_singlethread_workqueue("rdma_cm");
+       if (!cma_wq)
+               return -ENOMEM;
+diff -Nurb linux-2.6.22-590/drivers/infiniband/core/sysfs.c linux-2.6.22-570/drivers/infiniband/core/sysfs.c
+--- linux-2.6.22-590/drivers/infiniband/core/sysfs.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/infiniband/core/sysfs.c   2007-07-08 19:32:17.000000000 -0400
+@@ -479,6 +479,7 @@
  
-       *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
--      pcmd += sizeof (uint32_t);
-+      pcmd += sizeof(uint32_t);
+               element->attr.attr.name  = element->name;
+               element->attr.attr.mode  = S_IRUGO;
++              element->attr.attr.owner = THIS_MODULE;
+               element->attr.show       = show;
+               element->index           = i;
  
--      memset(pcmd, 0, sizeof (RNID));
-+      memset(pcmd, 0, sizeof(RNID));
-       rn = (RNID *) (pcmd);
-       rn->Format = format;
--      rn->CommonLen = (2 * sizeof (struct lpfc_name));
--      memcpy(&rn->portName, &phba->fc_portname, sizeof (struct lpfc_name));
--      memcpy(&rn->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
-+      rn->CommonLen = (2 * sizeof(struct lpfc_name));
-+      memcpy(&rn->portName, &vport->fc_portname, sizeof(struct lpfc_name));
-+      memcpy(&rn->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
-       switch (format) {
-       case 0:
-               rn->SpecificLen = 0;
-               break;
-       case RNID_TOPOLOGY_DISC:
--              rn->SpecificLen = sizeof (RNID_TOP_DISC);
-+              rn->SpecificLen = sizeof(RNID_TOP_DISC);
-               memcpy(&rn->un.topologyDisc.portName,
--                     &phba->fc_portname, sizeof (struct lpfc_name));
-+                     &vport->fc_portname, sizeof(struct lpfc_name));
-               rn->un.topologyDisc.unitType = RNID_HBA;
-               rn->un.topologyDisc.physPort = 0;
-               rn->un.topologyDisc.attachedNodes = 0;
-@@ -2273,15 +2602,17 @@
-               break;
-       }
+diff -Nurb linux-2.6.22-590/drivers/infiniband/ulp/iser/iscsi_iser.c linux-2.6.22-570/drivers/infiniband/ulp/iser/iscsi_iser.c
+--- linux-2.6.22-590/drivers/infiniband/ulp/iser/iscsi_iser.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/infiniband/ulp/iser/iscsi_iser.c  2007-07-08 19:32:17.000000000 -0400
+@@ -134,9 +134,19 @@
+ {
+       struct iscsi_iser_conn     *iser_conn  = ctask->conn->dd_data;
+       struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
++      struct scsi_cmnd  *sc = ctask->sc;
  
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
-+              "Issue ACC RNID:  did:x%x flg:x%x",
-+              ndlp->nlp_DID, ndlp->nlp_flag, 0);
+       iser_ctask->command_sent = 0;
+       iser_ctask->iser_conn    = iser_conn;
 +
-       phba->fc_stat.elsXmitACC++;
--      elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
-+      elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
-       lpfc_nlp_put(ndlp);
-       elsiocb->context1 = NULL;  /* Don't need ndlp for cmpl,
-                                   * it could be freed */
--      spin_lock_irq(phba->host->host_lock);
-       rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
--      spin_unlock_irq(phba->host->host_lock);
-       if (rc == IOCB_ERROR) {
-               lpfc_els_free_iocb(phba, elsiocb);
-               return 1;
-@@ -2290,168 +2621,153 @@
++      if (sc->sc_data_direction == DMA_TO_DEVICE) {
++              BUG_ON(ctask->total_length == 0);
++
++              debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
++                         ctask->itt, ctask->total_length, ctask->imm_count,
++                         ctask->unsol_count);
++      }
++
+       iser_ctask_rdma_init(iser_ctask);
  }
  
- int
--lpfc_els_disc_adisc(struct lpfc_hba *phba)
-+lpfc_els_disc_adisc(struct lpfc_vport *vport)
- {
--      int sentadisc;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-       struct lpfc_nodelist *ndlp, *next_ndlp;
-+      int sentadisc = 0;
+@@ -209,14 +219,6 @@
+       struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+       int error = 0;
  
--      sentadisc = 0;
-       /* go thru NPR nodes and issue any remaining ELS ADISCs */
--      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
-+      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
-               if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
-                   (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
-                   (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) {
--                      spin_lock_irq(phba->host->host_lock);
-+                      spin_lock_irq(shost->host_lock);
-                       ndlp->nlp_flag &= ~NLP_NPR_ADISC;
--                      spin_unlock_irq(phba->host->host_lock);
-+                      spin_unlock_irq(shost->host_lock);
-                       ndlp->nlp_prev_state = ndlp->nlp_state;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
--                      lpfc_issue_els_adisc(phba, ndlp, 0);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
-+                      lpfc_issue_els_adisc(vport, ndlp, 0);
-                       sentadisc++;
--                      phba->num_disc_nodes++;
--                      if (phba->num_disc_nodes >=
--                          phba->cfg_discovery_threads) {
--                              spin_lock_irq(phba->host->host_lock);
--                              phba->fc_flag |= FC_NLP_MORE;
--                              spin_unlock_irq(phba->host->host_lock);
-+                      vport->num_disc_nodes++;
-+                      if (vport->num_disc_nodes >=
-+                          vport->phba->cfg_discovery_threads) {
-+                              spin_lock_irq(shost->host_lock);
-+                              vport->fc_flag |= FC_NLP_MORE;
-+                              spin_unlock_irq(shost->host_lock);
-                               break;
-                       }
-               }
-       }
-       if (sentadisc == 0) {
--              spin_lock_irq(phba->host->host_lock);
--              phba->fc_flag &= ~FC_NLP_MORE;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-+              vport->fc_flag &= ~FC_NLP_MORE;
-+              spin_unlock_irq(shost->host_lock);
-       }
-       return sentadisc;
- }
+-      if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {
+-              BUG_ON(scsi_bufflen(ctask->sc) == 0);
+-
+-              debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
+-                         ctask->itt, scsi_bufflen(ctask->sc),
+-                         ctask->imm_count, ctask->unsol_count);
+-      }
+-
+       debug_scsi("ctask deq [cid %d itt 0x%x]\n",
+                  conn->id, ctask->itt);
  
- int
--lpfc_els_disc_plogi(struct lpfc_hba * phba)
-+lpfc_els_disc_plogi(struct lpfc_vport *vport)
+@@ -373,7 +375,6 @@
+ static struct iscsi_cls_session *
+ iscsi_iser_session_create(struct iscsi_transport *iscsit,
+                        struct scsi_transport_template *scsit,
+-                       uint16_t cmds_max, uint16_t qdepth,
+                         uint32_t initial_cmdsn, uint32_t *hostno)
  {
--      int sentplogi;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-       struct lpfc_nodelist *ndlp, *next_ndlp;
-+      int sentplogi = 0;
+       struct iscsi_cls_session *cls_session;
+@@ -385,13 +386,7 @@
+       struct iscsi_iser_cmd_task *iser_ctask;
+       struct iser_desc *desc;
  
--      sentplogi = 0;
--      /* go thru NPR list and issue any remaining ELS PLOGIs */
--      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
-+      /* go thru NPR nodes and issue any remaining ELS PLOGIs */
-+      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
-               if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
-                   (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
-                   (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 &&
-                   (ndlp->nlp_flag & NLP_NPR_ADISC) == 0) {
-                       ndlp->nlp_prev_state = ndlp->nlp_state;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
--                      lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
-+                      lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
-                       sentplogi++;
--                      phba->num_disc_nodes++;
--                      if (phba->num_disc_nodes >=
--                          phba->cfg_discovery_threads) {
--                              spin_lock_irq(phba->host->host_lock);
--                              phba->fc_flag |= FC_NLP_MORE;
--                              spin_unlock_irq(phba->host->host_lock);
-+                      vport->num_disc_nodes++;
-+                      if (vport->num_disc_nodes >=
-+                          vport->phba->cfg_discovery_threads) {
-+                              spin_lock_irq(shost->host_lock);
-+                              vport->fc_flag |= FC_NLP_MORE;
-+                              spin_unlock_irq(shost->host_lock);
-                               break;
-                       }
-               }
-       }
-       if (sentplogi == 0) {
--              spin_lock_irq(phba->host->host_lock);
--              phba->fc_flag &= ~FC_NLP_MORE;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-+              vport->fc_flag &= ~FC_NLP_MORE;
-+              spin_unlock_irq(shost->host_lock);
+-      /*
+-       * we do not support setting can_queue cmd_per_lun from userspace yet
+-       * because we preallocate so many resources
+-       */
+       cls_session = iscsi_session_setup(iscsit, scsit,
+-                                        ISCSI_DEF_XMIT_CMDS_MAX,
+-                                        ISCSI_MAX_CMD_PER_LUN,
+                                         sizeof(struct iscsi_iser_cmd_task),
+                                         sizeof(struct iser_desc),
+                                         initial_cmdsn, &hn);
+@@ -550,7 +545,7 @@
+ static struct scsi_host_template iscsi_iser_sht = {
+       .name                   = "iSCSI Initiator over iSER, v." DRV_VER,
+       .queuecommand           = iscsi_queuecommand,
+-      .can_queue              = ISCSI_DEF_XMIT_CMDS_MAX - 1,
++      .can_queue              = ISCSI_XMIT_CMDS_MAX - 1,
+       .sg_tablesize           = ISCSI_ISER_SG_TABLESIZE,
+       .max_sectors            = 1024,
+       .cmd_per_lun            = ISCSI_MAX_CMD_PER_LUN,
+@@ -579,12 +574,8 @@
+                                 ISCSI_EXP_STATSN |
+                                 ISCSI_PERSISTENT_PORT |
+                                 ISCSI_PERSISTENT_ADDRESS |
+-                                ISCSI_TARGET_NAME | ISCSI_TPGT |
+-                                ISCSI_USERNAME | ISCSI_PASSWORD |
+-                                ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
+-      .host_param_mask        = ISCSI_HOST_HWADDRESS |
+-                                ISCSI_HOST_NETDEV_NAME |
+-                                ISCSI_HOST_INITIATOR_NAME,
++                                ISCSI_TARGET_NAME |
++                                ISCSI_TPGT,
+       .host_template          = &iscsi_iser_sht,
+       .conndata_size          = sizeof(struct iscsi_conn),
+       .max_lun                = ISCSI_ISER_MAX_LUN,
+@@ -601,9 +592,6 @@
+       .get_session_param      = iscsi_session_get_param,
+       .start_conn             = iscsi_iser_conn_start,
+       .stop_conn              = iscsi_conn_stop,
+-      /* iscsi host params */
+-      .get_host_param         = iscsi_host_get_param,
+-      .set_host_param         = iscsi_host_set_param,
+       /* IO */
+       .send_pdu               = iscsi_conn_send_pdu,
+       .get_stats              = iscsi_iser_conn_get_stats,
+diff -Nurb linux-2.6.22-590/drivers/infiniband/ulp/iser/iscsi_iser.h linux-2.6.22-570/drivers/infiniband/ulp/iser/iscsi_iser.h
+--- linux-2.6.22-590/drivers/infiniband/ulp/iser/iscsi_iser.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/infiniband/ulp/iser/iscsi_iser.h  2007-07-08 19:32:17.000000000 -0400
+@@ -98,7 +98,7 @@
+ #define ISER_MAX_TX_MISC_PDUS         6 /* NOOP_OUT(2), TEXT(1),         *
+                                          * SCSI_TMFUNC(2), LOGOUT(1) */
+-#define ISER_QP_MAX_RECV_DTOS         (ISCSI_DEF_XMIT_CMDS_MAX + \
++#define ISER_QP_MAX_RECV_DTOS         (ISCSI_XMIT_CMDS_MAX + \
+                                       ISER_MAX_RX_MISC_PDUS    +  \
+                                       ISER_MAX_TX_MISC_PDUS)
+@@ -110,7 +110,7 @@
+ #define ISER_INFLIGHT_DATAOUTS                8
+-#define ISER_QP_MAX_REQ_DTOS          (ISCSI_DEF_XMIT_CMDS_MAX *    \
++#define ISER_QP_MAX_REQ_DTOS          (ISCSI_XMIT_CMDS_MAX *    \
+                                       (1 + ISER_INFLIGHT_DATAOUTS) + \
+                                       ISER_MAX_TX_MISC_PDUS        + \
+                                       ISER_MAX_RX_MISC_PDUS)
+diff -Nurb linux-2.6.22-590/drivers/infiniband/ulp/iser/iser_initiator.c linux-2.6.22-570/drivers/infiniband/ulp/iser/iser_initiator.c
+--- linux-2.6.22-590/drivers/infiniband/ulp/iser/iser_initiator.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/infiniband/ulp/iser/iser_initiator.c      2007-07-08 19:32:17.000000000 -0400
+@@ -351,12 +351,18 @@
+       else
+               data_buf = &iser_ctask->data[ISER_DIR_OUT];
+-      if (scsi_sg_count(sc)) { /* using a scatter list */
+-              data_buf->buf  = scsi_sglist(sc);
+-              data_buf->size = scsi_sg_count(sc);
++      if (sc->use_sg) { /* using a scatter list */
++              data_buf->buf  = sc->request_buffer;
++              data_buf->size = sc->use_sg;
++      } else if (sc->request_bufflen) {
++              /* using a single buffer - convert it into one entry SG */
++              sg_init_one(&data_buf->sg_single,
++                          sc->request_buffer, sc->request_bufflen);
++              data_buf->buf   = &data_buf->sg_single;
++              data_buf->size  = 1;
        }
-       return sentplogi;
- }
  
--int
--lpfc_els_flush_rscn(struct lpfc_hba * phba)
-+void
-+lpfc_els_flush_rscn(struct lpfc_vport *vport)
+-      data_buf->data_len = scsi_bufflen(sc);
++      data_buf->data_len = sc->request_bufflen;
+       if (hdr->flags & ISCSI_FLAG_CMD_READ) {
+               err = iser_prepare_read_cmd(ctask, edtl);
+diff -Nurb linux-2.6.22-590/drivers/infiniband/ulp/iser/iser_verbs.c linux-2.6.22-570/drivers/infiniband/ulp/iser/iser_verbs.c
+--- linux-2.6.22-590/drivers/infiniband/ulp/iser/iser_verbs.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/infiniband/ulp/iser/iser_verbs.c  2007-07-08 19:32:17.000000000 -0400
+@@ -155,8 +155,8 @@
+       params.max_pages_per_fmr = ISCSI_ISER_SG_TABLESIZE + 1;
+       /* make the pool size twice the max number of SCSI commands *
+        * the ML is expected to queue, watermark for unmap at 50%  */
+-      params.pool_size         = ISCSI_DEF_XMIT_CMDS_MAX * 2;
+-      params.dirty_watermark   = ISCSI_DEF_XMIT_CMDS_MAX;
++      params.pool_size         = ISCSI_XMIT_CMDS_MAX * 2;
++      params.dirty_watermark   = ISCSI_XMIT_CMDS_MAX;
+       params.cache             = 0;
+       params.flush_function    = NULL;
+       params.access            = (IB_ACCESS_LOCAL_WRITE  |
+diff -Nurb linux-2.6.22-590/drivers/infiniband/ulp/srp/ib_srp.c linux-2.6.22-570/drivers/infiniband/ulp/srp/ib_srp.c
+--- linux-2.6.22-590/drivers/infiniband/ulp/srp/ib_srp.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/infiniband/ulp/srp/ib_srp.c       2007-07-08 19:32:17.000000000 -0400
+@@ -455,7 +455,10 @@
+                          struct srp_target_port *target,
+                          struct srp_request *req)
  {
--      struct lpfc_dmabuf *mp;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-       int i;
+-      if (!scsi_sglist(scmnd) ||
++      struct scatterlist *scat;
++      int nents;
++
++      if (!scmnd->request_buffer ||
+           (scmnd->sc_data_direction != DMA_TO_DEVICE &&
+            scmnd->sc_data_direction != DMA_FROM_DEVICE))
+               return;
+@@ -465,8 +468,20 @@
+               req->fmr = NULL;
+       }
  
--      for (i = 0; i < phba->fc_rscn_id_cnt; i++) {
--              mp = phba->fc_rscn_id_list[i];
--              lpfc_mbuf_free(phba, mp->virt, mp->phys);
--              kfree(mp);
--              phba->fc_rscn_id_list[i] = NULL;
--      }
--      phba->fc_rscn_id_cnt = 0;
--      spin_lock_irq(phba->host->host_lock);
--      phba->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);
--      spin_unlock_irq(phba->host->host_lock);
--      lpfc_can_disctmo(phba);
--      return 0;
-+      for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
-+              lpfc_in_buf_free(phba, vport->fc_rscn_id_list[i]);
-+              vport->fc_rscn_id_list[i] = NULL;
+-      ib_dma_unmap_sg(target->srp_host->dev->dev, scsi_sglist(scmnd),
+-                      scsi_sg_count(scmnd), scmnd->sc_data_direction);
++      /*
++       * This handling of non-SG commands can be killed when the
++       * SCSI midlayer no longer generates non-SG commands.
++       */
++      if (likely(scmnd->use_sg)) {
++              nents = scmnd->use_sg;
++              scat  = scmnd->request_buffer;
++      } else {
++              nents = 1;
++              scat  = &req->fake_sg;
 +      }
-+      spin_lock_irq(shost->host_lock);
-+      vport->fc_rscn_id_cnt = 0;
-+      vport->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);
-+      spin_unlock_irq(shost->host_lock);
-+      lpfc_can_disctmo(vport);
++
++      ib_dma_unmap_sg(target->srp_host->dev->dev, scat, nents,
++                      scmnd->sc_data_direction);
  }
  
- int
--lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did)
-+lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did)
- {
-       D_ID ns_did;
-       D_ID rscn_did;
--      struct lpfc_dmabuf *mp;
-       uint32_t *lp;
--      uint32_t payload_len, cmd, i, match;
-+      uint32_t payload_len, i;
-+      struct lpfc_hba *phba = vport->phba;
-       ns_did.un.word = did;
--      match = 0;
+ static void srp_remove_req(struct srp_target_port *target, struct srp_request *req)
+@@ -580,7 +595,6 @@
+       int ret;
+       struct srp_device *dev = target->srp_host->dev;
+       struct ib_device *ibdev = dev->dev;
+-      struct scatterlist *sg;
  
-       /* Never match fabric nodes for RSCNs */
-       if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
--              return(0);
-+              return 0;
+       if (!dev->fmr_pool)
+               return -ENODEV;
+@@ -590,16 +604,16 @@
+               return -EINVAL;
  
-       /* If we are doing a FULL RSCN rediscovery, match everything */
--      if (phba->fc_flag & FC_RSCN_DISCOVERY) {
-+      if (vport->fc_flag & FC_RSCN_DISCOVERY)
-               return did;
--      }
+       len = page_cnt = 0;
+-      scsi_for_each_sg(req->scmnd, sg, sg_cnt, i) {
+-              unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
++      for (i = 0; i < sg_cnt; ++i) {
++              unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]);
  
--      for (i = 0; i < phba->fc_rscn_id_cnt; i++) {
--              mp = phba->fc_rscn_id_list[i];
--              lp = (uint32_t *) mp->virt;
--              cmd = *lp++;
--              payload_len = be32_to_cpu(cmd) & 0xffff; /* payload length */
--              payload_len -= sizeof (uint32_t);       /* take off word 0 */
-+      for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
-+              lp = vport->fc_rscn_id_list[i]->virt;
-+              payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
-+              payload_len -= sizeof(uint32_t);        /* take off word 0 */
-               while (payload_len) {
--                      rscn_did.un.word = *lp++;
--                      rscn_did.un.word = be32_to_cpu(rscn_did.un.word);
--                      payload_len -= sizeof (uint32_t);
-+                      rscn_did.un.word = be32_to_cpu(*lp++);
-+                      payload_len -= sizeof(uint32_t);
-                       switch (rscn_did.un.b.resv) {
-                       case 0: /* Single N_Port ID effected */
--                              if (ns_did.un.word == rscn_did.un.word) {
--                                      match = did;
--                              }
-+                              if (ns_did.un.word == rscn_did.un.word)
-+                                      return did;
-                               break;
-                       case 1: /* Whole N_Port Area effected */
-                               if ((ns_did.un.b.domain == rscn_did.un.b.domain)
-                                   && (ns_did.un.b.area == rscn_did.un.b.area))
--                                      {
--                                              match = did;
--                                      }
-+                                      return did;
-                               break;
-                       case 2: /* Whole N_Port Domain effected */
-                               if (ns_did.un.b.domain == rscn_did.un.b.domain)
--                                      {
--                                              match = did;
--                                      }
--                              break;
--                      case 3: /* Whole Fabric effected */
--                              match = did;
-+                                      return did;
-                               break;
-                       default:
--                              /* Unknown Identifier in RSCN list */
-+                              /* Unknown Identifier in RSCN node */
-                               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
--                                              "%d:0217 Unknown Identifier in "
--                                              "RSCN payload Data: x%x\n",
--                                              phba->brd_no, rscn_did.un.word);
--                              break;
--                      }
--                      if (match) {
--                              break;
-+                                              "%d (%d):0217 Unknown "
-+                                              "Identifier in RSCN payload "
-+                                              "Data: x%x\n",
-+                                              phba->brd_no, vport->vpi,
-+                                              rscn_did.un.word);
-+                      case 3: /* Whole Fabric effected */
-+                              return did;
-                       }
+-              if (ib_sg_dma_address(ibdev, sg) & ~dev->fmr_page_mask) {
++              if (ib_sg_dma_address(ibdev, &scat[i]) & ~dev->fmr_page_mask) {
+                       if (i > 0)
+                               return -EINVAL;
+                       else
+                               ++page_cnt;
                }
+-              if ((ib_sg_dma_address(ibdev, sg) + dma_len) &
++              if ((ib_sg_dma_address(ibdev, &scat[i]) + dma_len) &
+                   ~dev->fmr_page_mask) {
+                       if (i < sg_cnt - 1)
+                               return -EINVAL;
+@@ -619,12 +633,12 @@
+               return -ENOMEM;
+       page_cnt = 0;
+-      scsi_for_each_sg(req->scmnd, sg, sg_cnt, i) {
+-              unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
++      for (i = 0; i < sg_cnt; ++i) {
++              unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]);
+               for (j = 0; j < dma_len; j += dev->fmr_page_size)
+                       dma_pages[page_cnt++] =
+-                              (ib_sg_dma_address(ibdev, sg) &
++                              (ib_sg_dma_address(ibdev, &scat[i]) &
+                                dev->fmr_page_mask) + j;
        }
--      return match;
-+      return 0;
- }
  
- static int
--lpfc_rscn_recovery_check(struct lpfc_hba *phba)
-+lpfc_rscn_recovery_check(struct lpfc_vport *vport)
- {
-       struct lpfc_nodelist *ndlp = NULL;
+@@ -659,7 +673,7 @@
+       struct srp_device *dev;
+       struct ib_device *ibdev;
  
-@@ -2459,12 +2775,12 @@
-        * them to NPR state.
-        */
+-      if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
++      if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE)
+               return sizeof (struct srp_cmd);
  
--      list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
-+      list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
-               if (ndlp->nlp_state == NLP_STE_UNUSED_NODE ||
--                  lpfc_rscn_payload_check(phba, ndlp->nlp_DID) == 0)
-+                  lpfc_rscn_payload_check(vport, ndlp->nlp_DID) == 0)
-                       continue;
+       if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
+@@ -669,8 +683,18 @@
+               return -EINVAL;
+       }
  
--              lpfc_disc_state_machine(phba, ndlp, NULL,
-+              lpfc_disc_state_machine(vport, ndlp, NULL,
-                                       NLP_EVT_DEVICE_RECOVERY);
+-      nents = scsi_sg_count(scmnd);
+-      scat  = scsi_sglist(scmnd);
++      /*
++       * This handling of non-SG commands can be killed when the
++       * SCSI midlayer no longer generates non-SG commands.
++       */
++      if (likely(scmnd->use_sg)) {
++              nents = scmnd->use_sg;
++              scat  = scmnd->request_buffer;
++      } else {
++              nents = 1;
++              scat  = &req->fake_sg;
++              sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen);
++      }
  
-               /*
-@@ -2472,175 +2788,248 @@
-                * recovery event.
+       dev = target->srp_host->dev;
+       ibdev = dev->dev;
+@@ -700,7 +724,6 @@
+                * descriptor.
                 */
-               if (ndlp->nlp_flag & NLP_DELAY_TMO)
--                      lpfc_cancel_retry_delay_tmo(phba, ndlp);
-+                      lpfc_cancel_retry_delay_tmo(vport, ndlp);
-       }
+               struct srp_indirect_buf *buf = (void *) cmd->add_data;
+-              struct scatterlist *sg;
+               u32 datalen = 0;
+               int i;
  
-       return 0;
- }
+@@ -709,11 +732,11 @@
+                       sizeof (struct srp_indirect_buf) +
+                       count * sizeof (struct srp_direct_buf);
  
- static int
--lpfc_els_rcv_rscn(struct lpfc_hba * phba,
--                struct lpfc_iocbq * cmdiocb,
--                struct lpfc_nodelist * ndlp, uint8_t newnode)
-+lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
-+                struct lpfc_nodelist *ndlp, uint8_t newnode)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-       struct lpfc_dmabuf *pcmd;
--      uint32_t *lp;
-+      struct lpfc_vport *next_vport;
-+      uint32_t *lp, *datap;
-       IOCB_t *icmd;
--      uint32_t payload_len, cmd;
-+      uint32_t payload_len, length, nportid, *cmd;
-+      int rscn_cnt = vport->fc_rscn_id_cnt;
-+      int rscn_id = 0, hba_id = 0;
-       int i;
+-              scsi_for_each_sg(scmnd, sg, count, i) {
+-                      unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
++              for (i = 0; i < count; ++i) {
++                      unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]);
  
-       icmd = &cmdiocb->iocb;
-       pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
-       lp = (uint32_t *) pcmd->virt;
+                       buf->desc_list[i].va  =
+-                              cpu_to_be64(ib_sg_dma_address(ibdev, sg));
++                              cpu_to_be64(ib_sg_dma_address(ibdev, &scat[i]));
+                       buf->desc_list[i].key =
+                               cpu_to_be32(dev->mr->rkey);
+                       buf->desc_list[i].len = cpu_to_be32(dma_len);
+@@ -779,9 +802,9 @@
+               }
  
--      cmd = *lp++;
--      payload_len = be32_to_cpu(cmd) & 0xffff;        /* payload length */
--      payload_len -= sizeof (uint32_t);       /* take off word 0 */
--      cmd &= ELS_CMD_MASK;
-+      payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
-+      payload_len -= sizeof(uint32_t);        /* take off word 0 */
+               if (rsp->flags & (SRP_RSP_FLAG_DOOVER | SRP_RSP_FLAG_DOUNDER))
+-                      scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt));
++                      scmnd->resid = be32_to_cpu(rsp->data_out_res_cnt);
+               else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))
+-                      scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
++                      scmnd->resid = be32_to_cpu(rsp->data_in_res_cnt);
  
-       /* RSCN received */
--      lpfc_printf_log(phba,
--                      KERN_INFO,
--                      LOG_DISCOVERY,
--                      "%d:0214 RSCN received Data: x%x x%x x%x x%x\n",
--                      phba->brd_no,
--                      phba->fc_flag, payload_len, *lp, phba->fc_rscn_id_cnt);
-+      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                      "%d (%d):0214 RSCN received Data: x%x x%x x%x x%x\n",
-+                      phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
-+                      *lp, rscn_cnt);
+               if (!req->tsk_mgmt) {
+                       scmnd->host_scribble = (void *) -1L;
+diff -Nurb linux-2.6.22-590/drivers/infiniband/ulp/srp/ib_srp.h linux-2.6.22-570/drivers/infiniband/ulp/srp/ib_srp.h
+--- linux-2.6.22-590/drivers/infiniband/ulp/srp/ib_srp.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/infiniband/ulp/srp/ib_srp.h       2007-07-08 19:32:17.000000000 -0400
+@@ -106,6 +106,11 @@
+       struct srp_iu          *cmd;
+       struct srp_iu          *tsk_mgmt;
+       struct ib_pool_fmr     *fmr;
++      /*
++       * Fake scatterlist used when scmnd->use_sg==0.  Can be killed
++       * when the SCSI midlayer no longer generates non-SG commands.
++       */
++      struct scatterlist      fake_sg;
+       struct completion       done;
+       short                   index;
+       u8                      cmd_done;
+diff -Nurb linux-2.6.22-590/drivers/input/gameport/gameport.c linux-2.6.22-570/drivers/input/gameport/gameport.c
+--- linux-2.6.22-590/drivers/input/gameport/gameport.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/input/gameport/gameport.c 2007-07-08 19:32:17.000000000 -0400
+@@ -445,7 +445,6 @@
  
-       for (i = 0; i < payload_len/sizeof(uint32_t); i++)
--              fc_host_post_event(phba->host, fc_get_event_number(),
-+              fc_host_post_event(shost, fc_get_event_number(),
-                       FCH_EVT_RSCN, lp[i]);
+ static int gameport_thread(void *nothing)
+ {
+-      set_freezable();
+       do {
+               gameport_handle_event();
+               wait_event_interruptible(gameport_wait,
+diff -Nurb linux-2.6.22-590/drivers/input/mouse/psmouse.h linux-2.6.22-570/drivers/input/mouse/psmouse.h
+--- linux-2.6.22-590/drivers/input/mouse/psmouse.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/input/mouse/psmouse.h     2007-07-08 19:32:17.000000000 -0400
+@@ -118,6 +118,7 @@
+               .attr   = {                                                     \
+                       .name   = __stringify(_name),                           \
+                       .mode   = _mode,                                        \
++                      .owner  = THIS_MODULE,                                  \
+               },                                                              \
+               .show   = psmouse_attr_show_helper,                             \
+               .store  = psmouse_attr_set_helper,                              \
+diff -Nurb linux-2.6.22-590/drivers/input/serio/serio.c linux-2.6.22-570/drivers/input/serio/serio.c
+--- linux-2.6.22-590/drivers/input/serio/serio.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/input/serio/serio.c       2007-07-08 19:32:17.000000000 -0400
+@@ -384,7 +384,6 @@
  
-       /* If we are about to begin discovery, just ACC the RSCN.
-        * Discovery processing will satisfy it.
-        */
--      if (phba->hba_state <= LPFC_NS_QRY) {
--              lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
-+      if (vport->port_state <= LPFC_NS_QRY) {
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV RSCN ignore: did:x%x/ste:x%x flg:x%x",
-+                      ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
-+
-+              lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
-                                                               newnode);
-               return 0;
-       }
+ static int serio_thread(void *nothing)
+ {
+-      set_freezable();
+       do {
+               serio_handle_event();
+               wait_event_interruptible(serio_wait,
+diff -Nurb linux-2.6.22-590/drivers/input/touchscreen/ucb1400_ts.c linux-2.6.22-570/drivers/input/touchscreen/ucb1400_ts.c
+--- linux-2.6.22-590/drivers/input/touchscreen/ucb1400_ts.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/input/touchscreen/ucb1400_ts.c    2007-07-08 19:32:17.000000000 -0400
+@@ -292,7 +292,6 @@
  
-+      /* If this RSCN just contains NPortIDs for other vports on this HBA,
-+       * just ACC and ignore it.
-+       */
-+      if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
-+              !(phba->cfg_peer_port_login)) {
-+              i = payload_len;
-+              datap = lp;
-+              while (i > 0) {
-+                      nportid = *datap++;
-+                      nportid = ((be32_to_cpu(nportid)) & Mask_DID);
-+                      i -= sizeof(uint32_t);
-+                      rscn_id++;
-+                      list_for_each_entry(next_vport, &phba->port_list,
-+                              listentry) {
-+                              if (nportid == next_vport->fc_myDID) {
-+                                      hba_id++;
-+                                      break;
-+                              }
-+                      }
-+              }
-+              if (rscn_id == hba_id) {
-+                      /* ALL NPortIDs in RSCN are on HBA */
-+                      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                        "%d (%d):0214 Ignore RSCN Data: x%x x%x x%x x%x\n",
-+                        phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
-+                        *lp, rscn_cnt);
-+
-+                      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                              "RCV RSCN vport:  did:x%x/ste:x%x flg:x%x",
-+                              ndlp->nlp_DID, vport->port_state,
-+                              ndlp->nlp_flag);
-+
-+                      lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb,
-+                              ndlp, NULL, newnode);
-+                      return 0;
-+              }
-+      }
-+
-       /* If we are already processing an RSCN, save the received
-        * RSCN payload buffer, cmdiocb->context2 to process later.
-        */
--      if (phba->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
--              if ((phba->fc_rscn_id_cnt < FC_MAX_HOLD_RSCN) &&
--                  !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
--                      spin_lock_irq(phba->host->host_lock);
--                      phba->fc_flag |= FC_RSCN_MODE;
--                      spin_unlock_irq(phba->host->host_lock);
--                      phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;
--
-+      if (vport->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV RSCN defer:  did:x%x/ste:x%x flg:x%x",
-+                      ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
-+
-+              vport->fc_flag |= FC_RSCN_DEFERRED;
-+              if ((rscn_cnt < FC_MAX_HOLD_RSCN) &&
-+                  !(vport->fc_flag & FC_RSCN_DISCOVERY)) {
-+                      spin_lock_irq(shost->host_lock);
-+                      vport->fc_flag |= FC_RSCN_MODE;
-+                      spin_unlock_irq(shost->host_lock);
-+                      if (rscn_cnt) {
-+                              cmd = vport->fc_rscn_id_list[rscn_cnt-1]->virt;
-+                              length = be32_to_cpu(*cmd & ~ELS_CMD_MASK);
-+                      }
-+                      if ((rscn_cnt) &&
-+                          (payload_len + length <= LPFC_BPL_SIZE)) {
-+                              *cmd &= ELS_CMD_MASK;
-+                              *cmd |= be32_to_cpu(payload_len + length);
-+                              memcpy(((uint8_t *)cmd) + length, lp,
-+                                     payload_len);
-+                      } else {
-+                              vport->fc_rscn_id_list[rscn_cnt] = pcmd;
-+                              vport->fc_rscn_id_cnt++;
-                       /* If we zero, cmdiocb->context2, the calling
-                        * routine will not try to free it.
-                        */
-                       cmdiocb->context2 = NULL;
-+                      }
+       sched_setscheduler(tsk, SCHED_FIFO, &param);
  
-                       /* Deferred RSCN */
-                       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                                      "%d:0235 Deferred RSCN "
-+                                      "%d (%d):0235 Deferred RSCN "
-                                       "Data: x%x x%x x%x\n",
--                                      phba->brd_no, phba->fc_rscn_id_cnt,
--                                      phba->fc_flag, phba->hba_state);
-+                                      phba->brd_no, vport->vpi,
-+                                      vport->fc_rscn_id_cnt, vport->fc_flag,
-+                                      vport->port_state);
-               } else {
--                      spin_lock_irq(phba->host->host_lock);
--                      phba->fc_flag |= FC_RSCN_DISCOVERY;
--                      spin_unlock_irq(phba->host->host_lock);
-+                      spin_lock_irq(shost->host_lock);
-+                      vport->fc_flag |= FC_RSCN_DISCOVERY;
-+                      spin_unlock_irq(shost->host_lock);
-                       /* ReDiscovery RSCN */
-                       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                                      "%d:0234 ReDiscovery RSCN "
-+                                      "%d (%d):0234 ReDiscovery RSCN "
-                                       "Data: x%x x%x x%x\n",
--                                      phba->brd_no, phba->fc_rscn_id_cnt,
--                                      phba->fc_flag, phba->hba_state);
-+                                      phba->brd_no, vport->vpi,
-+                                      vport->fc_rscn_id_cnt, vport->fc_flag,
-+                                      vport->port_state);
-               }
-               /* Send back ACC */
--              lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
-+              lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
-                                                               newnode);
+-      set_freezable();
+       while (!kthread_should_stop()) {
+               unsigned int x, y, p;
+               long timeout;
+diff -Nurb linux-2.6.22-590/drivers/isdn/divert/divert_procfs.c linux-2.6.22-570/drivers/isdn/divert/divert_procfs.c
+--- linux-2.6.22-590/drivers/isdn/divert/divert_procfs.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/isdn/divert/divert_procfs.c       2007-07-08 19:32:17.000000000 -0400
+@@ -17,7 +17,6 @@
+ #include <linux/fs.h>
+ #endif
+ #include <linux/isdnif.h>
+-#include <net/net_namespace.h>
+ #include "isdn_divert.h"
  
-               /* send RECOVERY event for ALL nodes that match RSCN payload */
--              lpfc_rscn_recovery_check(phba);
-+              lpfc_rscn_recovery_check(vport);
-+              vport->fc_flag &= ~FC_RSCN_DEFERRED;
-               return 0;
-       }
  
--      phba->fc_flag |= FC_RSCN_MODE;
--      phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+              "RCV RSCN:        did:x%x/ste:x%x flg:x%x",
-+              ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
-+
-+      spin_lock_irq(shost->host_lock);
-+      vport->fc_flag |= FC_RSCN_MODE;
-+      spin_unlock_irq(shost->host_lock);
-+      vport->fc_rscn_id_list[vport->fc_rscn_id_cnt++] = pcmd;
-       /*
-        * If we zero, cmdiocb->context2, the calling routine will
-        * not try to free it.
-        */
-       cmdiocb->context2 = NULL;
+@@ -285,12 +284,12 @@
+       init_waitqueue_head(&rd_queue);
  
--      lpfc_set_disctmo(phba);
-+      lpfc_set_disctmo(vport);
+ #ifdef CONFIG_PROC_FS
+-      isdn_proc_entry = proc_mkdir("isdn", init_net.proc_net);
++      isdn_proc_entry = proc_mkdir("net/isdn", NULL);
+       if (!isdn_proc_entry)
+               return (-1);
+       isdn_divert_entry = create_proc_entry("divert", S_IFREG | S_IRUGO, isdn_proc_entry);
+       if (!isdn_divert_entry) {
+-              remove_proc_entry("isdn", init_net.proc_net);
++              remove_proc_entry("net/isdn", NULL);
+               return (-1);
+       }
+       isdn_divert_entry->proc_fops = &isdn_fops; 
+@@ -310,7 +309,7 @@
  
-       /* Send back ACC */
--      lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode);
-+      lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode);
+ #ifdef CONFIG_PROC_FS
+       remove_proc_entry("divert", isdn_proc_entry);
+-      remove_proc_entry("isdn", init_net.proc_net);
++      remove_proc_entry("net/isdn", NULL);
+ #endif        /* CONFIG_PROC_FS */
  
-       /* send RECOVERY event for ALL nodes that match RSCN payload */
--      lpfc_rscn_recovery_check(phba);
-+      lpfc_rscn_recovery_check(vport);
+       return (0);
+diff -Nurb linux-2.6.22-590/drivers/isdn/hardware/eicon/diva_didd.c linux-2.6.22-570/drivers/isdn/hardware/eicon/diva_didd.c
+--- linux-2.6.22-590/drivers/isdn/hardware/eicon/diva_didd.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/isdn/hardware/eicon/diva_didd.c   2007-07-08 19:32:17.000000000 -0400
+@@ -15,7 +15,6 @@
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+ #include <linux/proc_fs.h>
+-#include <net/net_namespace.h>
  
--      return lpfc_els_handle_rscn(phba);
-+      return lpfc_els_handle_rscn(vport);
- }
+ #include "platform.h"
+ #include "di_defs.h"
+@@ -87,7 +86,7 @@
  
- int
--lpfc_els_handle_rscn(struct lpfc_hba * phba)
-+lpfc_els_handle_rscn(struct lpfc_vport *vport)
+ static int DIVA_INIT_FUNCTION create_proc(void)
  {
-       struct lpfc_nodelist *ndlp;
-+      struct lpfc_hba *phba = vport->phba;
-+
-+      /* Ignore RSCN if the port is being torn down. */
-+      if (vport->load_flag & FC_UNLOADING) {
-+              lpfc_els_flush_rscn(vport);
-+              return 0;
-+      }
+-      proc_net_eicon = proc_mkdir("eicon", init_net.proc_net);
++      proc_net_eicon = proc_mkdir("net/eicon", NULL);
  
-       /* Start timer for RSCN processing */
--      lpfc_set_disctmo(phba);
-+      lpfc_set_disctmo(vport);
+       if (proc_net_eicon) {
+               if ((proc_didd =
+@@ -103,7 +102,7 @@
+ static void remove_proc(void)
+ {
+       remove_proc_entry(DRIVERLNAME, proc_net_eicon);
+-      remove_proc_entry("eicon", init_net.proc_net);
++      remove_proc_entry("net/eicon", NULL);
+ }
  
-       /* RSCN processed */
--      lpfc_printf_log(phba,
--                      KERN_INFO,
--                      LOG_DISCOVERY,
--                      "%d:0215 RSCN processed Data: x%x x%x x%x x%x\n",
--                      phba->brd_no,
--                      phba->fc_flag, 0, phba->fc_rscn_id_cnt,
--                      phba->hba_state);
-+      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                      "%d (%d):0215 RSCN processed Data: x%x x%x x%x x%x\n",
-+                      phba->brd_no, vport->vpi,
-+                      vport->fc_flag, 0, vport->fc_rscn_id_cnt,
-+                      vport->port_state);
+ static int DIVA_INIT_FUNCTION divadidd_init(void)
+diff -Nurb linux-2.6.22-590/drivers/isdn/hysdn/hysdn_procconf.c linux-2.6.22-570/drivers/isdn/hysdn/hysdn_procconf.c
+--- linux-2.6.22-590/drivers/isdn/hysdn/hysdn_procconf.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/isdn/hysdn/hysdn_procconf.c       2007-07-08 19:32:17.000000000 -0400
+@@ -392,7 +392,7 @@
+       hysdn_card *card;
+       unsigned char conf_name[20];
  
-       /* To process RSCN, first compare RSCN data with NameServer */
--      phba->fc_ns_retry = 0;
--      ndlp = lpfc_findnode_did(phba, NameServer_DID);
-+      vport->fc_ns_retry = 0;
-+      ndlp = lpfc_findnode_did(vport, NameServer_DID);
-       if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
-               /* Good ndlp, issue CT Request to NameServer */
--              if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) {
-+              if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0) == 0)
-                       /* Wait for NameServer query cmpl before we can
-                          continue */
-                       return 1;
--              }
-       } else {
-               /* If login to NameServer does not exist, issue one */
-               /* Good status, issue PLOGI to NameServer */
--              ndlp = lpfc_findnode_did(phba, NameServer_DID);
--              if (ndlp) {
-+              ndlp = lpfc_findnode_did(vport, NameServer_DID);
-+              if (ndlp)
-                       /* Wait for NameServer login cmpl before we can
-                          continue */
-                       return 1;
--              }
-+
-               ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
-               if (!ndlp) {
--                      lpfc_els_flush_rscn(phba);
-+                      lpfc_els_flush_rscn(vport);
-                       return 0;
-               } else {
--                      lpfc_nlp_init(phba, ndlp, NameServer_DID);
-+                      lpfc_nlp_init(vport, ndlp, NameServer_DID);
-                       ndlp->nlp_type |= NLP_FABRIC;
-                       ndlp->nlp_prev_state = ndlp->nlp_state;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
--                      lpfc_issue_els_plogi(phba, NameServer_DID, 0);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
-+                      lpfc_issue_els_plogi(vport, NameServer_DID, 0);
-                       /* Wait for NameServer login cmpl before we can
-                          continue */
-                       return 1;
-               }
+-      hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, init_net.proc_net);
++      hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, proc_net);
+       if (!hysdn_proc_entry) {
+               printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n");
+               return (-1);
+@@ -437,5 +437,5 @@
+               card = card->next;      /* point to next card */
        }
  
--      lpfc_els_flush_rscn(phba);
-+      lpfc_els_flush_rscn(vport);
-       return 0;
+-      remove_proc_entry(PROC_SUBDIR_NAME, init_net.proc_net);
++      remove_proc_entry(PROC_SUBDIR_NAME, proc_net);
  }
+diff -Nurb linux-2.6.22-590/drivers/macintosh/therm_adt746x.c linux-2.6.22-570/drivers/macintosh/therm_adt746x.c
+--- linux-2.6.22-590/drivers/macintosh/therm_adt746x.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/macintosh/therm_adt746x.c 2007-07-08 19:32:17.000000000 -0400
+@@ -335,7 +335,6 @@
+ {
+       struct thermostat* th = arg;
  
- static int
--lpfc_els_rcv_flogi(struct lpfc_hba * phba,
--                 struct lpfc_iocbq * cmdiocb,
--                 struct lpfc_nodelist * ndlp, uint8_t newnode)
-+lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
-+                 struct lpfc_nodelist *ndlp, uint8_t newnode)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-       struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
-       uint32_t *lp = (uint32_t *) pcmd->virt;
-       IOCB_t *icmd = &cmdiocb->iocb;
-@@ -2655,7 +3044,7 @@
+-      set_freezable();
+       while(!kthread_should_stop()) {
+               try_to_freeze();
+               msleep_interruptible(2000);
+diff -Nurb linux-2.6.22-590/drivers/macintosh/therm_pm72.c linux-2.6.22-570/drivers/macintosh/therm_pm72.c
+--- linux-2.6.22-590/drivers/macintosh/therm_pm72.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/macintosh/therm_pm72.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1770,8 +1770,7 @@
+                               "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
+                               NULL };
  
-       /* FLOGI received */
+-      return call_usermodehelper(critical_overtemp_path,
+-                                 argv, envp, UMH_WAIT_EXEC);
++      return call_usermodehelper(critical_overtemp_path, argv, envp, 0);
+ }
  
--      lpfc_set_disctmo(phba);
-+      lpfc_set_disctmo(vport);
  
-       if (phba->fc_topology == TOPOLOGY_LOOP) {
-               /* We should never receive a FLOGI in loop mode, ignore it */
-@@ -2664,33 +3053,34 @@
-               /* An FLOGI ELS command <elsCmd> was received from DID <did> in
-                  Loop Mode */
-               lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
--                              "%d:0113 An FLOGI ELS command x%x was received "
--                              "from DID x%x in Loop Mode\n",
--                              phba->brd_no, cmd, did);
-+                              "%d (%d):0113 An FLOGI ELS command x%x was "
-+                              "received from DID x%x in Loop Mode\n",
-+                              phba->brd_no, vport->vpi, cmd, did);
-               return 1;
-       }
+diff -Nurb linux-2.6.22-590/drivers/macintosh/windfarm_core.c linux-2.6.22-570/drivers/macintosh/windfarm_core.c
+--- linux-2.6.22-590/drivers/macintosh/windfarm_core.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/macintosh/windfarm_core.c 2007-07-08 19:32:17.000000000 -0400
+@@ -80,8 +80,7 @@
+                               "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
+                               NULL };
  
-       did = Fabric_DID;
+-      return call_usermodehelper(critical_overtemp_path,
+-                                 argv, envp, UMH_WAIT_EXEC);
++      return call_usermodehelper(critical_overtemp_path, argv, envp, 0);
+ }
+ EXPORT_SYMBOL_GPL(wf_critical_overtemp);
  
--      if ((lpfc_check_sparm(phba, ndlp, sp, CLASS3))) {
-+      if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3))) {
-               /* For a FLOGI we accept, then if our portname is greater
-                * then the remote portname we initiate Nport login.
-                */
+@@ -93,7 +92,6 @@
  
--              rc = memcmp(&phba->fc_portname, &sp->portName,
--                          sizeof (struct lpfc_name));
-+              rc = memcmp(&vport->fc_portname, &sp->portName,
-+                          sizeof(struct lpfc_name));
+       DBG("wf: thread started\n");
  
-               if (!rc) {
--                      if ((mbox = mempool_alloc(phba->mbox_mem_pool,
--                                                GFP_KERNEL)) == 0) {
-+                      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+                      if (!mbox)
-                               return 1;
--                      }
-+
-                       lpfc_linkdown(phba);
-                       lpfc_init_link(phba, mbox,
-                                      phba->cfg_topology,
-                                      phba->cfg_link_speed);
-                       mbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
-                       mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-+                      mbox->vport = vport;
-                       rc = lpfc_sli_issue_mbox
-                               (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
-                       lpfc_set_loopback_flag(phba);
-@@ -2699,31 +3089,34 @@
-                       }
-                       return 1;
-               } else if (rc > 0) {    /* greater than */
--                      spin_lock_irq(phba->host->host_lock);
--                      phba->fc_flag |= FC_PT2PT_PLOGI;
--                      spin_unlock_irq(phba->host->host_lock);
--              }
--              phba->fc_flag |= FC_PT2PT;
--              phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
-+                      spin_lock_irq(shost->host_lock);
-+                      vport->fc_flag |= FC_PT2PT_PLOGI;
-+                      spin_unlock_irq(shost->host_lock);
-+              }
-+              spin_lock_irq(shost->host_lock);
-+              vport->fc_flag |= FC_PT2PT;
-+              vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
-+              spin_unlock_irq(shost->host_lock);
-       } else {
-               /* Reject this request because invalid parameters */
-               stat.un.b.lsRjtRsvd0 = 0;
-               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-               stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
-               stat.un.b.vendorUnique = 0;
--              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
-+              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
-+                      NULL);
-               return 1;
-       }
+-      set_freezable();
+       while(!kthread_should_stop()) {
+               if (time_after_eq(jiffies, next)) {
+                       wf_notify(WF_EVENT_TICK, NULL);
+@@ -214,6 +212,7 @@
+       list_add(&new_ct->link, &wf_controls);
  
-       /* Send back ACC */
--      lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode);
-+      lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode);
+       new_ct->attr.attr.name = new_ct->name;
++      new_ct->attr.attr.owner = THIS_MODULE;
+       new_ct->attr.attr.mode = 0644;
+       new_ct->attr.show = wf_show_control;
+       new_ct->attr.store = wf_store_control;
+@@ -326,6 +325,7 @@
+       list_add(&new_sr->link, &wf_sensors);
  
-       return 0;
- }
+       new_sr->attr.attr.name = new_sr->name;
++      new_sr->attr.attr.owner = THIS_MODULE;
+       new_sr->attr.attr.mode = 0444;
+       new_sr->attr.show = wf_show_sensor;
+       new_sr->attr.store = NULL;
+diff -Nurb linux-2.6.22-590/drivers/md/Kconfig linux-2.6.22-570/drivers/md/Kconfig
+--- linux-2.6.22-590/drivers/md/Kconfig        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/md/Kconfig        2007-07-08 19:32:17.000000000 -0400
+@@ -109,8 +109,6 @@
+ config MD_RAID456
+       tristate "RAID-4/RAID-5/RAID-6 mode"
+       depends on BLK_DEV_MD
+-      select ASYNC_MEMCPY
+-      select ASYNC_XOR
+       ---help---
+         A RAID-5 set of N drives with a capacity of C MB per drive provides
+         the capacity of C * (N - 1) MB, and protects against a failure
+@@ -273,11 +271,6 @@
  
- static int
--lpfc_els_rcv_rnid(struct lpfc_hba * phba,
--                struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
-+lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
-+                struct lpfc_nodelist *ndlp)
- {
-       struct lpfc_dmabuf *pcmd;
-       uint32_t *lp;
-@@ -2746,7 +3139,7 @@
-       case 0:
-       case RNID_TOPOLOGY_DISC:
-               /* Send back ACC */
--              lpfc_els_rsp_rnid_acc(phba, rn->Format, cmdiocb, ndlp);
-+              lpfc_els_rsp_rnid_acc(vport, rn->Format, cmdiocb, ndlp);
-               break;
-       default:
-               /* Reject this request because format not supported */
-@@ -2754,13 +3147,14 @@
-               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-               stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
-               stat.un.b.vendorUnique = 0;
--              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
-+              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
-+                      NULL);
-       }
-       return 0;
- }
+       If unsure, say N.
  
- static int
--lpfc_els_rcv_lirr(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
-                struct lpfc_nodelist *ndlp)
- {
-       struct ls_rjt stat;
-@@ -2770,15 +3164,15 @@
-       stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-       stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
-       stat.un.b.vendorUnique = 0;
--      lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
-+      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
-       return 0;
- }
+-config DM_NETLINK
+-      bool "DM netlink events (EXPERIMENTAL)"
+-      depends on BLK_DEV_DM && EXPERIMENTAL
+-      ---help---
+-      Generate netlink events for DM events.
+ endmenu
  
- static void
- lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
- {
--      struct lpfc_sli *psli;
--      struct lpfc_sli_ring *pring;
-+      struct lpfc_sli *psli = &phba->sli;
-+      struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
-       MAILBOX_t *mb;
-       IOCB_t *icmd;
-       RPS_RSP *rps_rsp;
-@@ -2788,8 +3182,6 @@
-       uint16_t xri, status;
-       uint32_t cmdsize;
+ endif
+diff -Nurb linux-2.6.22-590/drivers/md/Makefile linux-2.6.22-570/drivers/md/Makefile
+--- linux-2.6.22-590/drivers/md/Makefile       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/md/Makefile       2007-07-08 19:32:17.000000000 -0400
+@@ -17,7 +17,7 @@
+ hostprogs-y   := mktables
  
--      psli = &phba->sli;
--      pring = &psli->ring[LPFC_ELS_RING];
-       mb = &pmb->mb;
+ # Note: link order is important.  All raid personalities
+-# and must come before md.o, as they each initialise 
++# and xor.o must come before md.o, as they each initialise 
+ # themselves, and md.o may use the personalities when it 
+ # auto-initialised.
  
-       ndlp = (struct lpfc_nodelist *) pmb->context2;
-@@ -2804,7 +3196,8 @@
+@@ -25,7 +25,7 @@
+ obj-$(CONFIG_MD_RAID0)                += raid0.o
+ obj-$(CONFIG_MD_RAID1)                += raid1.o
+ obj-$(CONFIG_MD_RAID10)               += raid10.o
+-obj-$(CONFIG_MD_RAID456)      += raid456.o
++obj-$(CONFIG_MD_RAID456)      += raid456.o xor.o
+ obj-$(CONFIG_MD_MULTIPATH)    += multipath.o
+ obj-$(CONFIG_MD_FAULTY)               += faulty.o
+ obj-$(CONFIG_BLK_DEV_MD)      += md-mod.o
+@@ -46,10 +46,6 @@
+ altivec_flags := -maltivec -mabi=altivec
+ endif
  
-       cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t);
-       mempool_free(pmb, phba->mbox_mem_pool);
--      elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp,
-+      elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize,
-+                                   lpfc_max_els_tries, ndlp,
-                                               ndlp->nlp_DID, ELS_CMD_ACC);
-       lpfc_nlp_put(ndlp);
-       if (!elsiocb)
-@@ -2815,14 +3208,14 @@
+-ifeq ($(CONFIG_DM_NETLINK),y)
+-dm-mod-objs                   += dm-netlink.o
+-endif
+-
+ targets += raid6int1.c
+ $(obj)/raid6int1.c:   UNROLL := 1
+ $(obj)/raid6int1.c:   $(src)/raid6int.uc $(src)/unroll.pl FORCE
+diff -Nurb linux-2.6.22-590/drivers/md/dm-netlink.c linux-2.6.22-570/drivers/md/dm-netlink.c
+--- linux-2.6.22-590/drivers/md/dm-netlink.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/md/dm-netlink.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,103 +0,0 @@
+-/*
+- * Device Mapper Netlink Support (dm-netlink)
+- *
+- * 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.
+- *
+- * Copyright IBM Corporation, 2005, 2006
+- *    Author: Mike Anderson <andmike@us.ibm.com>
+- */
+-#include <linux/module.h>
+-#include <linux/mempool.h>
+-#include <linux/time.h>
+-#include <linux/jiffies.h>
+-#include <linux/security.h>
+-#include <net/sock.h>
+-#include <net/netlink.h>
+-
+-#include "dm.h"
+-#include "dm-netlink.h"
+-
+-#define DM_MSG_PREFIX "netlink"
+-
+-#define DM_EVENT_SKB_SIZE NLMSG_GOODSIZE
+-
+-struct dm_event_cache {
+-      struct kmem_cache *cache;
+-      unsigned skb_size;
+-};
+-
+-static struct dm_event_cache _dme_cache;
+-
+-static int dme_cache_init(struct dm_event_cache *dc, unsigned skb_size)
+-{
+-      dc->skb_size = skb_size;
+-
+-      dc->cache = KMEM_CACHE(dm_event, 0);
+-      if (!dc->cache)
+-              return -ENOMEM;
+-
+-      return 0;
+-}
+-
+-static void dme_cache_destroy(struct dm_event_cache *dc)
+-{
+-      kmem_cache_destroy(dc->cache);
+-}
+-
+-static void dme_cache_event_put(struct dm_event *evt)
+-{
+-      struct dm_event_cache *dc = evt->cdata;
+-
+-      kmem_cache_free(dc->cache, evt);
+-}
+-
+-static struct dm_event *dme_cache_event_get(struct dm_event_cache *dc,
+-                                          struct mapped_device *md)
+-{
+-      struct dm_event *evt;
+-
+-      evt = kmem_cache_alloc(dc->cache, GFP_ATOMIC);
+-      if (!evt)
+-              return NULL;
+-
+-      INIT_LIST_HEAD(&evt->elist);
+-      evt->cdata = dc;
+-      evt->md = md;
+-      evt->skb = alloc_skb(dc->skb_size, GFP_ATOMIC);
+-      if (!evt->skb)
+-              goto cache_err;
+-
+-      return evt;
+-
+-cache_err:
+-      dme_cache_event_put(evt);
+-      return NULL;
+-}
+-
+-int __init dm_netlink_init(void)
+-{
+-      int r;
+-
+-      r = dme_cache_init(&_dme_cache, DM_EVENT_SKB_SIZE);
+-      if (!r)
+-              DMINFO("version 1.0.0 loaded");
+-
+-      return r;
+-}
+-
+-void dm_netlink_exit(void)
+-{
+-      dme_cache_destroy(&_dme_cache);
+-}
+diff -Nurb linux-2.6.22-590/drivers/md/dm-netlink.h linux-2.6.22-570/drivers/md/dm-netlink.h
+--- linux-2.6.22-590/drivers/md/dm-netlink.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/md/dm-netlink.h   1969-12-31 19:00:00.000000000 -0500
+@@ -1,50 +0,0 @@
+-/*
+- * Device Mapper Netlink Support
+- *
+- * 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.
+- *
+- * Copyright IBM Corporation, 2005, 2006
+- *    Author: Mike Anderson <andmike@us.ibm.com>
+- */
+-#ifndef DM_NETLINK_H
+-#define DM_NETLINK_H
+-
+-struct dm_event_cache;
+-struct mapped_device;
+-struct dm_event {
+-      struct dm_event_cache *cdata;
+-      struct mapped_device *md;
+-      struct sk_buff *skb;
+-      struct list_head elist;
+-};
+-
+-#ifdef CONFIG_DM_NETLINK
+-
+-int dm_netlink_init(void);
+-void dm_netlink_exit(void);
+-
+-#else /* CONFIG_DM_NETLINK */
+-
+-static inline int __init dm_netlink_init(void)
+-{
+-      return 0;
+-}
+-static inline void dm_netlink_exit(void)
+-{
+-}
+-
+-#endif        /* CONFIG_DM_NETLINK */
+-
+-#endif        /* DM_NETLINK_H */
+diff -Nurb linux-2.6.22-590/drivers/md/dm.c linux-2.6.22-570/drivers/md/dm.c
+--- linux-2.6.22-590/drivers/md/dm.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/md/dm.c   2008-01-23 19:16:04.000000000 -0500
+@@ -7,7 +7,6 @@
  
-       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
-       *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
--      pcmd += sizeof (uint32_t); /* Skip past command */
-+      pcmd += sizeof(uint32_t); /* Skip past command */
-       rps_rsp = (RPS_RSP *)pcmd;
+ #include "dm.h"
+ #include "dm-bio-list.h"
+-#include "dm-netlink.h"
  
-       if (phba->fc_topology != TOPOLOGY_LOOP)
-               status = 0x10;
-       else
-               status = 0x8;
--      if (phba->fc_flag & FC_FABRIC)
-+      if (phba->pport->fc_flag & FC_FABRIC)
-               status |= 0x4;
+ #include <linux/init.h>
+ #include <linux/module.h>
+@@ -181,7 +180,6 @@
+       dm_linear_init,
+       dm_stripe_init,
+       dm_interface_init,
+-      dm_netlink_init,
+ };
  
-       rps_rsp->rsvd1 = 0;
-@@ -2836,25 +3229,25 @@
+ void (*_exits[])(void) = {
+@@ -190,7 +188,6 @@
+       dm_linear_exit,
+       dm_stripe_exit,
+       dm_interface_exit,
+-      dm_netlink_exit,
+ };
  
-       /* Xmit ELS RPS ACC response tag <ulpIoTag> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
--                      "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
--                      phba->brd_no, elsiocb->iotag,
-+                      "%d (%d):0118 Xmit ELS RPS ACC response tag x%x "
-+                      "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
-+                      "rpi x%x\n",
-+                      phba->brd_no, ndlp->vport->vpi, elsiocb->iotag,
-                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
-                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+ static int __init dm_init(void)
+diff -Nurb linux-2.6.22-590/drivers/md/md.c linux-2.6.22-570/drivers/md/md.c
+--- linux-2.6.22-590/drivers/md/md.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/md/md.c   2007-07-08 19:32:17.000000000 -0400
+@@ -4642,6 +4642,7 @@
+        * many dirty RAID5 blocks.
+        */
  
--      elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
-+      elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
-       phba->fc_stat.elsXmitACC++;
--
--      if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
-+      if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR)
-               lpfc_els_free_iocb(phba, elsiocb);
--      }
-       return;
- }
++      current->flags |= PF_NOFREEZE;
+       allow_signal(SIGKILL);
+       while (!kthread_should_stop()) {
  
- static int
--lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--               struct lpfc_nodelist * ndlp)
-+lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
-+               struct lpfc_nodelist *ndlp)
- {
-+      struct lpfc_hba *phba = vport->phba;
-       uint32_t *lp;
-       uint8_t flag;
-       LPFC_MBOXQ_t *mbox;
-@@ -2868,7 +3261,8 @@
-               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-               stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
-               stat.un.b.vendorUnique = 0;
--              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
-+              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
-+                      NULL);
+@@ -5813,7 +5814,7 @@
        }
-       pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
-@@ -2878,19 +3272,24 @@
-       if ((flag == 0) ||
-           ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) ||
--          ((flag == 2) && (memcmp(&rps->un.portName, &phba->fc_portname,
--                         sizeof (struct lpfc_name)) == 0))) {
--              if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC))) {
-+          ((flag == 2) && (memcmp(&rps->un.portName, &vport->fc_portname,
-+                                  sizeof(struct lpfc_name)) == 0))) {
-+
-+              printk("Fix me....\n");
-+              dump_stack();
-+              mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC);
-+              if (mbox) {
-                       lpfc_read_lnk_stat(phba, mbox);
-                       mbox->context1 =
--                          (void *)((unsigned long)cmdiocb->iocb.ulpContext);
-+                          (void *)((unsigned long) cmdiocb->iocb.ulpContext);
-                       mbox->context2 = lpfc_nlp_get(ndlp);
-+                      mbox->vport = vport;
-                       mbox->mbox_cmpl = lpfc_els_rsp_rps_acc;
-                       if (lpfc_sli_issue_mbox (phba, mbox,
--                          (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) {
-+                          (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED)
-                               /* Mbox completion will send ELS Response */
-                               return 0;
--                      }
-+
-                       lpfc_nlp_put(ndlp);
-                       mempool_free(mbox, phba->mbox_mem_pool);
-               }
-@@ -2899,27 +3298,25 @@
-       stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-       stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
-       stat.un.b.vendorUnique = 0;
--      lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
-+      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
-       return 0;
  }
  
- static int
--lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize,
--               struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
-+lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
-+                   struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
- {
--      IOCB_t *icmd;
--      IOCB_t *oldcmd;
-+      struct lpfc_hba *phba = vport->phba;
-+      IOCB_t *icmd, *oldcmd;
-       RPL_RSP rpl_rsp;
-       struct lpfc_iocbq *elsiocb;
--      struct lpfc_sli_ring *pring;
--      struct lpfc_sli *psli;
-+      struct lpfc_sli *psli = &phba->sli;
-+      struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
-       uint8_t *pcmd;
--      psli = &phba->sli;
--      pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
-+      elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
-+                                   ndlp->nlp_DID, ELS_CMD_ACC);
--      elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
--                                      ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
-       if (!elsiocb)
-               return 1;
-@@ -2929,7 +3326,7 @@
-       pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
-       *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
--      pcmd += sizeof (uint16_t);
-+      pcmd += sizeof(uint16_t);
-       *((uint16_t *)(pcmd)) = be16_to_cpu(cmdsize);
-       pcmd += sizeof(uint16_t);
-@@ -2937,8 +3334,8 @@
-       rpl_rsp.listLen = be32_to_cpu(1);
-       rpl_rsp.index = 0;
-       rpl_rsp.port_num_blk.portNum = 0;
--      rpl_rsp.port_num_blk.portID = be32_to_cpu(phba->fc_myDID);
--      memcpy(&rpl_rsp.port_num_blk.portName, &phba->fc_portname,
-+      rpl_rsp.port_num_blk.portID = be32_to_cpu(vport->fc_myDID);
-+      memcpy(&rpl_rsp.port_num_blk.portName, &vport->fc_portname,
-           sizeof(struct lpfc_name));
+-subsys_initcall(md_init);
++module_init(md_init)
+ module_exit(md_exit)
  
-       memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t));
-@@ -2946,13 +3343,14 @@
+ static int get_ro(char *buffer, struct kernel_param *kp)
+diff -Nurb linux-2.6.22-590/drivers/md/raid5.c linux-2.6.22-570/drivers/md/raid5.c
+--- linux-2.6.22-590/drivers/md/raid5.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/md/raid5.c        2007-07-08 19:32:17.000000000 -0400
+@@ -52,7 +52,6 @@
+ #include "raid6.h"
  
-       /* Xmit ELS RPL ACC response tag <ulpIoTag> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0120 Xmit ELS RPL ACC response tag x%x xri x%x, "
--                      "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
--                      phba->brd_no, elsiocb->iotag,
-+                      "%d (%d):0120 Xmit ELS RPL ACC response tag x%x "
-+                      "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
-+                      "rpi x%x\n",
-+                      phba->brd_no, vport->vpi, elsiocb->iotag,
-                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
-                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+ #include <linux/raid/bitmap.h>
+-#include <linux/async_tx.h>
  
--      elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
-+      elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
+ /*
+  * Stripe cache
+@@ -81,6 +80,7 @@
+ /*
+  * The following can be used to debug the driver
+  */
++#define RAID5_DEBUG   0
+ #define RAID5_PARANOIA        1
+ #if RAID5_PARANOIA && defined(CONFIG_SMP)
+ # define CHECK_DEVLOCK() assert_spin_locked(&conf->device_lock)
+@@ -88,7 +88,8 @@
+ # define CHECK_DEVLOCK()
+ #endif
  
-       phba->fc_stat.elsXmitACC++;
-       if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
-@@ -2963,8 +3361,8 @@
- }
+-#ifdef DEBUG
++#define PRINTK(x...) ((void)(RAID5_DEBUG && printk(x)))
++#if RAID5_DEBUG
+ #define inline
+ #define __inline__
+ #endif
+@@ -124,7 +125,6 @@
+                       }
+                       md_wakeup_thread(conf->mddev->thread);
+               } else {
+-                      BUG_ON(sh->ops.pending);
+                       if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+                               atomic_dec(&conf->preread_active_stripes);
+                               if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
+@@ -152,8 +152,7 @@
  
- static int
--lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--               struct lpfc_nodelist * ndlp)
-+lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
-+               struct lpfc_nodelist *ndlp)
+ static inline void remove_hash(struct stripe_head *sh)
  {
-       struct lpfc_dmabuf *pcmd;
-       uint32_t *lp;
-@@ -2979,7 +3377,8 @@
-               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-               stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
-               stat.un.b.vendorUnique = 0;
--              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
-+              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
-+                      NULL);
-       }
-       pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
-@@ -2996,15 +3395,16 @@
-       } else {
-               cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t);
-       }
--      lpfc_els_rsp_rpl_acc(phba, cmdsize, cmdiocb, ndlp);
-+      lpfc_els_rsp_rpl_acc(vport, cmdsize, cmdiocb, ndlp);
+-      pr_debug("remove_hash(), stripe %llu\n",
+-              (unsigned long long)sh->sector);
++      PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector);
  
-       return 0;
+       hlist_del_init(&sh->hash);
  }
- static int
--lpfc_els_rcv_farp(struct lpfc_hba * phba,
--                struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
-+lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
-+                struct lpfc_nodelist *ndlp)
+@@ -162,8 +161,7 @@
  {
-+      struct lpfc_hba *phba = vport->phba;
-       struct lpfc_dmabuf *pcmd;
-       uint32_t *lp;
-       IOCB_t *icmd;
-@@ -3020,11 +3420,9 @@
-       fp = (FARP *) lp;
+       struct hlist_head *hp = stripe_hash(conf, sh->sector);
  
-       /* FARP-REQ received from DID <did> */
--      lpfc_printf_log(phba,
--                       KERN_INFO,
--                       LOG_ELS,
--                       "%d:0601 FARP-REQ received from DID x%x\n",
--                       phba->brd_no, did);
-+      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-+                      "%d (%d):0601 FARP-REQ received from DID x%x\n",
-+                      phba->brd_no, vport->vpi, did);
+-      pr_debug("insert_hash(), stripe %llu\n",
+-              (unsigned long long)sh->sector);
++      PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector);
  
-       /* We will only support match on WWPN or WWNN */
-       if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) {
-@@ -3034,15 +3432,15 @@
-       cnt = 0;
-       /* If this FARP command is searching for my portname */
-       if (fp->Mflags & FARP_MATCH_PORT) {
--              if (memcmp(&fp->RportName, &phba->fc_portname,
--                         sizeof (struct lpfc_name)) == 0)
-+              if (memcmp(&fp->RportName, &vport->fc_portname,
-+                         sizeof(struct lpfc_name)) == 0)
-                       cnt = 1;
-       }
+       CHECK_DEVLOCK();
+       hlist_add_head(&sh->hash, hp);
+@@ -226,10 +224,9 @@
  
-       /* If this FARP command is searching for my nodename */
-       if (fp->Mflags & FARP_MATCH_NODE) {
--              if (memcmp(&fp->RnodeName, &phba->fc_nodename,
--                         sizeof (struct lpfc_name)) == 0)
-+              if (memcmp(&fp->RnodeName, &vport->fc_nodename,
-+                         sizeof(struct lpfc_name)) == 0)
-                       cnt = 1;
-       }
+       BUG_ON(atomic_read(&sh->count) != 0);
+       BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
+-      BUG_ON(sh->ops.pending || sh->ops.ack || sh->ops.complete);
+       
+       CHECK_DEVLOCK();
+-      pr_debug("init_stripe called, stripe %llu\n",
++      PRINTK("init_stripe called, stripe %llu\n", 
+               (unsigned long long)sh->sector);
  
-@@ -3052,28 +3450,28 @@
-                       /* Log back into the node before sending the FARP. */
-                       if (fp->Rflags & FARP_REQUEST_PLOGI) {
-                               ndlp->nlp_prev_state = ndlp->nlp_state;
--                              lpfc_nlp_set_state(phba, ndlp,
-+                              lpfc_nlp_set_state(vport, ndlp,
-                                                  NLP_STE_PLOGI_ISSUE);
--                              lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
-+                              lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
-                       }
+       remove_hash(sh);
+@@ -243,11 +240,11 @@
+       for (i = sh->disks; i--; ) {
+               struct r5dev *dev = &sh->dev[i];
  
-                       /* Send a FARP response to that node */
--                      if (fp->Rflags & FARP_REQUEST_FARPR) {
--                              lpfc_issue_els_farpr(phba, did, 0);
--                      }
-+                      if (fp->Rflags & FARP_REQUEST_FARPR)
-+                              lpfc_issue_els_farpr(vport, did, 0);
+-              if (dev->toread || dev->read || dev->towrite || dev->written ||
++              if (dev->toread || dev->towrite || dev->written ||
+                   test_bit(R5_LOCKED, &dev->flags)) {
+-                      printk(KERN_ERR "sector=%llx i=%d %p %p %p %p %d\n",
++                      printk("sector=%llx i=%d %p %p %p %d\n",
+                              (unsigned long long)sh->sector, i, dev->toread,
+-                             dev->read, dev->towrite, dev->written,
++                             dev->towrite, dev->written,
+                              test_bit(R5_LOCKED, &dev->flags));
+                       BUG();
                }
-       }
-       return 0;
+@@ -263,11 +260,11 @@
+       struct hlist_node *hn;
+       CHECK_DEVLOCK();
+-      pr_debug("__find_stripe, sector %llu\n", (unsigned long long)sector);
++      PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
+       hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
+               if (sh->sector == sector && sh->disks == disks)
+                       return sh;
+-      pr_debug("__stripe %llu not in cache\n", (unsigned long long)sector);
++      PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
+       return NULL;
  }
  
- static int
--lpfc_els_rcv_farpr(struct lpfc_hba * phba,
--                 struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
-+lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
-+                 struct lpfc_nodelist  *ndlp)
+@@ -279,7 +276,7 @@
  {
-       struct lpfc_dmabuf *pcmd;
-       uint32_t *lp;
-       IOCB_t *icmd;
-       uint32_t cmd, did;
-+      struct lpfc_hba *phba = vport->phba;
+       struct stripe_head *sh;
  
-       icmd = &cmdiocb->iocb;
-       did = icmd->un.elsreq64.remoteID;
-@@ -3082,21 +3480,18 @@
+-      pr_debug("get_stripe, sector %llu\n", (unsigned long long)sector);
++      PRINTK("get_stripe, sector %llu\n", (unsigned long long)sector);
  
-       cmd = *lp++;
-       /* FARP-RSP received from DID <did> */
--      lpfc_printf_log(phba,
--                       KERN_INFO,
--                       LOG_ELS,
--                       "%d:0600 FARP-RSP received from DID x%x\n",
--                       phba->brd_no, did);
--
-+      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-+                      "%d (%d):0600 FARP-RSP received from DID x%x\n",
-+                      phba->brd_no, vport->vpi, did);
-       /* ACCEPT the Farp resp request */
--      lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
-+      lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+       spin_lock_irq(&conf->device_lock);
  
-       return 0;
+@@ -327,762 +324,179 @@
+       return sh;
  }
  
- static int
--lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--               struct lpfc_nodelist * fan_ndlp)
-+lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
-+               struct lpfc_nodelist *fan_ndlp)
+-/* test_and_ack_op() ensures that we only dequeue an operation once */
+-#define test_and_ack_op(op, pend) \
+-do {                                                  \
+-      if (test_bit(op, &sh->ops.pending) &&           \
+-              !test_bit(op, &sh->ops.complete)) {     \
+-              if (test_and_set_bit(op, &sh->ops.ack)) \
+-                      clear_bit(op, &pend);           \
+-              else                                    \
+-                      ack++;                          \
+-      } else                                          \
+-              clear_bit(op, &pend);                   \
+-} while (0)
+-
+-/* find new work to run, do not resubmit work that is already
+- * in flight
+- */
+-static unsigned long get_stripe_work(struct stripe_head *sh)
+-{
+-      unsigned long pending;
+-      int ack = 0;
+-
+-      pending = sh->ops.pending;
+-
+-      test_and_ack_op(STRIPE_OP_BIOFILL, pending);
+-      test_and_ack_op(STRIPE_OP_COMPUTE_BLK, pending);
+-      test_and_ack_op(STRIPE_OP_PREXOR, pending);
+-      test_and_ack_op(STRIPE_OP_BIODRAIN, pending);
+-      test_and_ack_op(STRIPE_OP_POSTXOR, pending);
+-      test_and_ack_op(STRIPE_OP_CHECK, pending);
+-      if (test_and_clear_bit(STRIPE_OP_IO, &sh->ops.pending))
+-              ack++;
+-
+-      sh->ops.count -= ack;
+-      BUG_ON(sh->ops.count < 0);
+-
+-      return pending;
+-}
+-
+-static int
+-raid5_end_read_request(struct bio *bi, unsigned int bytes_done, int error);
+-static int
+-raid5_end_write_request (struct bio *bi, unsigned int bytes_done, int error);
+-
+-static void ops_run_io(struct stripe_head *sh)
++static int grow_one_stripe(raid5_conf_t *conf)
  {
-       struct lpfc_dmabuf *pcmd;
-       uint32_t *lp;
-@@ -3104,10 +3499,12 @@
-       uint32_t cmd, did;
-       FAN *fp;
-       struct lpfc_nodelist *ndlp, *next_ndlp;
-+      struct lpfc_hba *phba = vport->phba;
-       /* FAN received */
--      lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n",
--                                                              phba->brd_no);
-+      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-+                      "%d (%d):0265 FAN received\n",
-+                      phba->brd_no, vport->vpi);
-       icmd = &cmdiocb->iocb;
-       did = icmd->un.elsreq64.remoteID;
-@@ -3115,11 +3512,11 @@
-       lp = (uint32_t *)pcmd->virt;
-       cmd = *lp++;
--      fp = (FAN *)lp;
-+      fp = (FAN *) lp;
-       /* FAN received; Fan does not have a reply sequence */
--      if (phba->hba_state == LPFC_LOCAL_CFG_LINK) {
-+      if (phba->pport->port_state == LPFC_LOCAL_CFG_LINK) {
-               if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName,
-                       sizeof(struct lpfc_name)) != 0) ||
-                   (memcmp(&phba->fc_fabparam.portName, &fp->FportName,
-@@ -3130,7 +3527,7 @@
-                        */
-                       list_for_each_entry_safe(ndlp, next_ndlp,
--                                               &phba->fc_nodes, nlp_listp) {
-+                                               &vport->fc_nodes, nlp_listp) {
-                               if (ndlp->nlp_state != NLP_STE_NPR_NODE)
-                                       continue;
-                               if (ndlp->nlp_type & NLP_FABRIC) {
-@@ -3138,24 +3535,24 @@
-                                        * Clean up old Fabric, Nameserver and
-                                        * other NLP_FABRIC logins
-                                        */
--                                      lpfc_drop_node(phba, ndlp);
-+                                      lpfc_drop_node(vport, ndlp);
-                               } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
-                                       /* Fail outstanding I/O now since this
-                                        * device is marked for PLOGI
-                                        */
--                                      lpfc_unreg_rpi(phba, ndlp);
-+                                      lpfc_unreg_rpi(vport, ndlp);
-                               }
-                       }
--                      phba->hba_state = LPFC_FLOGI;
--                      lpfc_set_disctmo(phba);
--                      lpfc_initial_flogi(phba);
-+                      vport->port_state = LPFC_FLOGI;
-+                      lpfc_set_disctmo(vport);
-+                      lpfc_initial_flogi(vport);
-                       return 0;
-               }
-               /* Discovery not needed,
-                * move the nodes to their original state.
-                */
--              list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
-+              list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
-                                        nlp_listp) {
-                       if (ndlp->nlp_state != NLP_STE_NPR_NODE)
-                               continue;
-@@ -3163,13 +3560,13 @@
-                       switch (ndlp->nlp_prev_state) {
-                       case NLP_STE_UNMAPPED_NODE:
-                               ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
--                              lpfc_nlp_set_state(phba, ndlp,
-+                              lpfc_nlp_set_state(vport, ndlp,
-                                                  NLP_STE_UNMAPPED_NODE);
-                               break;
-                       case NLP_STE_MAPPED_NODE:
-                               ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
--                              lpfc_nlp_set_state(phba, ndlp,
-+                              lpfc_nlp_set_state(vport, ndlp,
-                                                  NLP_STE_MAPPED_NODE);
-                               break;
+-      raid5_conf_t *conf = sh->raid_conf;
+-      int i, disks = sh->disks;
+-
+-      might_sleep();
+-
+-      for (i = disks; i--; ) {
+-              int rw;
+-              struct bio *bi;
+-              mdk_rdev_t *rdev;
+-              if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
+-                      rw = WRITE;
+-              else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
+-                      rw = READ;
+-              else
+-                      continue;
+-
+-              bi = &sh->dev[i].req;
+-
+-              bi->bi_rw = rw;
+-              if (rw == WRITE)
+-                      bi->bi_end_io = raid5_end_write_request;
+-              else
+-                      bi->bi_end_io = raid5_end_read_request;
++      struct stripe_head *sh;
++      sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
++      if (!sh)
++              return 0;
++      memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
++      sh->raid_conf = conf;
++      spin_lock_init(&sh->lock);
  
-@@ -3179,7 +3576,7 @@
-               }
+-              rcu_read_lock();
+-              rdev = rcu_dereference(conf->disks[i].rdev);
+-              if (rdev && test_bit(Faulty, &rdev->flags))
+-                      rdev = NULL;
+-              if (rdev)
+-                      atomic_inc(&rdev->nr_pending);
+-              rcu_read_unlock();
++      if (grow_buffers(sh, conf->raid_disks)) {
++              shrink_buffers(sh, conf->raid_disks);
++              kmem_cache_free(conf->slab_cache, sh);
++              return 0;
++      }
++      sh->disks = conf->raid_disks;
++      /* we just created an active stripe so... */
++      atomic_set(&sh->count, 1);
++      atomic_inc(&conf->active_stripes);
++      INIT_LIST_HEAD(&sh->lru);
++      release_stripe(sh);
++      return 1;
++}
  
-               /* Start discovery - this should just do CLEAR_LA */
--              lpfc_disc_start(phba);
-+              lpfc_disc_start(vport);
-       }
-       return 0;
- }
-@@ -3187,42 +3584,42 @@
- void
- lpfc_els_timeout(unsigned long ptr)
- {
--      struct lpfc_hba *phba;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) ptr;
-+      struct lpfc_hba   *phba = vport->phba;
-       unsigned long iflag;
+-              if (rdev) {
+-                      if (test_bit(STRIPE_SYNCING, &sh->state) ||
+-                              test_bit(STRIPE_EXPAND_SOURCE, &sh->state) ||
+-                              test_bit(STRIPE_EXPAND_READY, &sh->state))
+-                              md_sync_acct(rdev->bdev, STRIPE_SECTORS);
++static int grow_stripes(raid5_conf_t *conf, int num)
++{
++      struct kmem_cache *sc;
++      int devs = conf->raid_disks;
  
--      phba = (struct lpfc_hba *)ptr;
--      if (phba == 0)
--              return;
--      spin_lock_irqsave(phba->host->host_lock, iflag);
--      if (!(phba->work_hba_events & WORKER_ELS_TMO)) {
--              phba->work_hba_events |= WORKER_ELS_TMO;
-+      spin_lock_irqsave(&vport->work_port_lock, iflag);
-+      if ((vport->work_port_events & WORKER_ELS_TMO) == 0) {
-+              vport->work_port_events |= WORKER_ELS_TMO;
-+              spin_unlock_irqrestore(&vport->work_port_lock, iflag);
-+
-+              spin_lock_irqsave(&phba->hbalock, iflag);
-               if (phba->work_wait)
--                      wake_up(phba->work_wait);
-+                      lpfc_worker_wake_up(phba);
-+              spin_unlock_irqrestore(&phba->hbalock, iflag);
-       }
--      spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+      else
-+              spin_unlock_irqrestore(&vport->work_port_lock, iflag);
-       return;
+-                      bi->bi_bdev = rdev->bdev;
+-                      pr_debug("%s: for %llu schedule op %ld on disc %d\n",
+-                              __FUNCTION__, (unsigned long long)sh->sector,
+-                              bi->bi_rw, i);
+-                      atomic_inc(&sh->count);
+-                      bi->bi_sector = sh->sector + rdev->data_offset;
+-                      bi->bi_flags = 1 << BIO_UPTODATE;
+-                      bi->bi_vcnt = 1;
+-                      bi->bi_max_vecs = 1;
+-                      bi->bi_idx = 0;
+-                      bi->bi_io_vec = &sh->dev[i].vec;
+-                      bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
+-                      bi->bi_io_vec[0].bv_offset = 0;
+-                      bi->bi_size = STRIPE_SIZE;
+-                      bi->bi_next = NULL;
+-                      if (rw == WRITE &&
+-                          test_bit(R5_ReWrite, &sh->dev[i].flags))
+-                              atomic_add(STRIPE_SECTORS,
+-                                      &rdev->corrected_errors);
+-                      generic_make_request(bi);
+-              } else {
+-                      if (rw == WRITE)
+-                              set_bit(STRIPE_DEGRADED, &sh->state);
+-                      pr_debug("skip op %ld on disc %d for sector %llu\n",
+-                              bi->bi_rw, i, (unsigned long long)sh->sector);
+-                      clear_bit(R5_LOCKED, &sh->dev[i].flags);
+-                      set_bit(STRIPE_HANDLE, &sh->state);
+-              }
+-      }
++      sprintf(conf->cache_name[0], "raid5-%s", mdname(conf->mddev));
++      sprintf(conf->cache_name[1], "raid5-%s-alt", mdname(conf->mddev));
++      conf->active_name = 0;
++      sc = kmem_cache_create(conf->cache_name[conf->active_name],
++                             sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
++                             0, 0, NULL, NULL);
++      if (!sc)
++              return 1;
++      conf->slab_cache = sc;
++      conf->pool_size = devs;
++      while (num--)
++              if (!grow_one_stripe(conf))
++                      return 1;
++      return 0;
  }
  
- void
--lpfc_els_timeout_handler(struct lpfc_hba *phba)
-+lpfc_els_timeout_handler(struct lpfc_vport *vport)
+-static struct dma_async_tx_descriptor *
+-async_copy_data(int frombio, struct bio *bio, struct page *page,
+-      sector_t sector, struct dma_async_tx_descriptor *tx)
++#ifdef CONFIG_MD_RAID5_RESHAPE
++static int resize_stripes(raid5_conf_t *conf, int newsize)
  {
-+      struct lpfc_hba  *phba = vport->phba;
-       struct lpfc_sli_ring *pring;
-       struct lpfc_iocbq *tmp_iocb, *piocb;
-       IOCB_t *cmd = NULL;
-       struct lpfc_dmabuf *pcmd;
--      uint32_t *elscmd;
--      uint32_t els_command=0;
-+      uint32_t els_command = 0;
-       uint32_t timeout;
--      uint32_t remote_ID;
-+      uint32_t remote_ID = 0xffffffff;
--      if (phba == 0)
--              return;
--      spin_lock_irq(phba->host->host_lock);
-       /* If the timer is already canceled do nothing */
--      if (!(phba->work_hba_events & WORKER_ELS_TMO)) {
--              spin_unlock_irq(phba->host->host_lock);
-+      if ((vport->work_port_events & WORKER_ELS_TMO) == 0) {
-               return;
-       }
-+      spin_lock_irq(&phba->hbalock);
-       timeout = (uint32_t)(phba->fc_ratov << 1);
+-      struct bio_vec *bvl;
+-      struct page *bio_page;
++      /* Make all the stripes able to hold 'newsize' devices.
++       * New slots in each stripe get 'page' set to a new page.
++       *
++       * This happens in stages:
++       * 1/ create a new kmem_cache and allocate the required number of
++       *    stripe_heads.
++       * 2/ gather all the old stripe_heads and tranfer the pages across
++       *    to the new stripe_heads.  This will have the side effect of
++       *    freezing the array as once all stripe_heads have been collected,
++       *    no IO will be possible.  Old stripe heads are freed once their
++       *    pages have been transferred over, and the old kmem_cache is
++       *    freed when all stripes are done.
++       * 3/ reallocate conf->disks to be suitable bigger.  If this fails,
++       *    we simple return a failre status - no need to clean anything up.
++       * 4/ allocate new pages for the new slots in the new stripe_heads.
++       *    If this fails, we don't bother trying the shrink the
++       *    stripe_heads down again, we just leave them as they are.
++       *    As each stripe_head is processed the new one is released into
++       *    active service.
++       *
++       * Once step2 is started, we cannot afford to wait for a write,
++       * so we use GFP_NOIO allocations.
++       */
++      struct stripe_head *osh, *nsh;
++      LIST_HEAD(newstripes);
++      struct disk_info *ndisks;
++      int err = 0;
++      struct kmem_cache *sc;
+       int i;
+-      int page_offset;
  
-       pring = &phba->sli.ring[LPFC_ELS_RING];
-@@ -3230,63 +3627,70 @@
-       list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
-               cmd = &piocb->iocb;
+-      if (bio->bi_sector >= sector)
+-              page_offset = (signed)(bio->bi_sector - sector) * 512;
+-      else
+-              page_offset = (signed)(sector - bio->bi_sector) * -512;
+-      bio_for_each_segment(bvl, bio, i) {
+-              int len = bio_iovec_idx(bio, i)->bv_len;
+-              int clen;
+-              int b_offset = 0;
++      if (newsize <= conf->pool_size)
++              return 0; /* never bother to shrink */
  
--              if ((piocb->iocb_flag & LPFC_IO_LIBDFC) ||
--                      (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN) ||
--                      (piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)) {
-+              if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 ||
-+                  piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
-+                  piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
-                       continue;
--              }
-+
-+              if (piocb->vport != vport)
-+                      continue;
-+
-               pcmd = (struct lpfc_dmabuf *) piocb->context2;
--              if (pcmd) {
--                      elscmd = (uint32_t *) (pcmd->virt);
--                      els_command = *elscmd;
--              }
-+              if (pcmd)
-+                      els_command = *(uint32_t *) (pcmd->virt);
--              if ((els_command == ELS_CMD_FARP)
--                  || (els_command == ELS_CMD_FARPR)) {
-+              if (els_command == ELS_CMD_FARP ||
-+                  els_command == ELS_CMD_FARPR ||
-+                  els_command == ELS_CMD_FDISC)
-+                      continue;
-+
-+              if (vport != piocb->vport)
-                       continue;
+-              if (page_offset < 0) {
+-                      b_offset = -page_offset;
+-                      page_offset += b_offset;
+-                      len -= b_offset;
 -              }
++      md_allow_write(conf->mddev);
  
-               if (piocb->drvrTimeout > 0) {
--                      if (piocb->drvrTimeout >= timeout) {
-+                      if (piocb->drvrTimeout >= timeout)
-                               piocb->drvrTimeout -= timeout;
--                      } else {
-+                      else
-                               piocb->drvrTimeout = 0;
--                      }
-                       continue;
-               }
--              if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) {
-+              remote_ID = 0xffffffff;
-+              if (cmd->ulpCommand != CMD_GEN_REQUEST64_CR)
-+                      remote_ID = cmd->un.elsreq64.remoteID;
-+              else {
-                       struct lpfc_nodelist *ndlp;
--                      ndlp = __lpfc_findnode_rpi(phba, cmd->ulpContext);
-+                      ndlp = __lpfc_findnode_rpi(vport, cmd->ulpContext);
-+                      if (ndlp)
-                       remote_ID = ndlp->nlp_DID;
--              } else {
--                      remote_ID = cmd->un.elsreq64.remoteID;
-               }
--              lpfc_printf_log(phba,
--                              KERN_ERR,
--                              LOG_ELS,
--                              "%d:0127 ELS timeout Data: x%x x%x x%x x%x\n",
--                              phba->brd_no, els_command,
-+              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                              "%d (%d):0127 ELS timeout Data: x%x x%x x%x "
-+                              "x%x\n",
-+                              phba->brd_no, vport->vpi, els_command,
-                               remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
-               lpfc_sli_issue_abort_iotag(phba, pring, piocb);
-       }
--      if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
--              mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
-+      spin_unlock_irq(&phba->hbalock);
--      spin_unlock_irq(phba->host->host_lock);
-+      if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
-+              mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
- }
+-              if (len > 0 && page_offset + len > STRIPE_SIZE)
+-                      clen = STRIPE_SIZE - page_offset;
+-              else
+-                      clen = len;
++      /* Step 1 */
++      sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
++                             sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev),
++                             0, 0, NULL, NULL);
++      if (!sc)
++              return -ENOMEM;
  
- void
--lpfc_els_flush_cmd(struct lpfc_hba *phba)
-+lpfc_els_flush_cmd(struct lpfc_vport *vport)
- {
-       LIST_HEAD(completions);
-+      struct lpfc_hba  *phba = vport->phba;
-       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
-       struct lpfc_iocbq *tmp_iocb, *piocb;
-       IOCB_t *cmd = NULL;
+-              if (clen > 0) {
+-                      b_offset += bio_iovec_idx(bio, i)->bv_offset;
+-                      bio_page = bio_iovec_idx(bio, i)->bv_page;
+-                      if (frombio)
+-                              tx = async_memcpy(page, bio_page, page_offset,
+-                                      b_offset, clen,
+-                                      ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_SRC,
+-                                      tx, NULL, NULL);
+-                      else
+-                              tx = async_memcpy(bio_page, page, b_offset,
+-                                      page_offset, clen,
+-                                      ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_DST,
+-                                      tx, NULL, NULL);
+-              }
+-              if (clen < len) /* hit end of page */
++      for (i = conf->max_nr_stripes; i; i--) {
++              nsh = kmem_cache_alloc(sc, GFP_KERNEL);
++              if (!nsh)
+                       break;
+-              page_offset +=  len;
+-      }
  
--      spin_lock_irq(phba->host->host_lock);
-+      lpfc_fabric_abort_vport(vport);
-+
-+      spin_lock_irq(&phba->hbalock);
-       list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
-               cmd = &piocb->iocb;
+-      return tx;
+-}
+-
+-static void ops_complete_biofill(void *stripe_head_ref)
+-{
+-      struct stripe_head *sh = stripe_head_ref;
+-      struct bio *return_bi = NULL, *bi;
+-      raid5_conf_t *conf = sh->raid_conf;
+-      int i, more_to_read = 0;
+-
+-      pr_debug("%s: stripe %llu\n", __FUNCTION__,
+-              (unsigned long long)sh->sector);
+-
+-      /* clear completed biofills */
+-      for (i = sh->disks; i--; ) {
+-              struct r5dev *dev = &sh->dev[i];
+-              /* check if this stripe has new incoming reads */
+-              if (dev->toread)
+-                      more_to_read++;
++              memset(nsh, 0, sizeof(*nsh) + (newsize-1)*sizeof(struct r5dev));
  
-@@ -3301,271 +3705,1042 @@
-                   cmd->ulpCommand == CMD_ABORT_XRI_CN)
-                       continue;
+-              /* acknowledge completion of a biofill operation */
+-              /* and check if we need to reply to a read request
+-       */
+-              if (test_bit(R5_Wantfill, &dev->flags) && !dev->toread) {
+-                      struct bio *rbi, *rbi2;
+-                      clear_bit(R5_Wantfill, &dev->flags);
++              nsh->raid_conf = conf;
++              spin_lock_init(&nsh->lock);
  
-+              if (piocb->vport != vport)
-+                      continue;
-+
-               list_move_tail(&piocb->list, &completions);
-               pring->txq_cnt--;
--
+-                      /* The access to dev->read is outside of the
+-                       * spin_lock_irq(&conf->device_lock), but is protected
+-                       * by the STRIPE_OP_BIOFILL pending bit
+-                       */
+-                      BUG_ON(!dev->read);
+-                      rbi = dev->read;
+-                      dev->read = NULL;
+-                      while (rbi && rbi->bi_sector <
+-                              dev->sector + STRIPE_SECTORS) {
+-                              rbi2 = r5_next_bio(rbi, dev->sector);
+-              spin_lock_irq(&conf->device_lock);
+-                              if (--rbi->bi_phys_segments == 0) {
+-                                      rbi->bi_next = return_bi;
+-                                      return_bi = rbi;
++              list_add(&nsh->lru, &newstripes);
+                               }
+-              spin_unlock_irq(&conf->device_lock);
+-                              rbi = rbi2;
++      if (i) {
++              /* didn't get enough, give up */
++              while (!list_empty(&newstripes)) {
++                      nsh = list_entry(newstripes.next, struct stripe_head, lru);
++                      list_del(&nsh->lru);
++                      kmem_cache_free(sc, nsh);
        }
-       list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
--              cmd = &piocb->iocb;
--
-               if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
-                       continue;
++              kmem_cache_destroy(sc);
++              return -ENOMEM;
                }
-+              if (piocb->vport != vport)
-+                      continue;
-+
-               lpfc_sli_issue_abort_iotag(phba, pring, piocb);
++      /* Step 2 - Must use GFP_NOIO now.
++       * OK, we have enough stripes, start collecting inactive
++       * stripes and copying them over
++       */
++      list_for_each_entry(nsh, &newstripes, lru) {
++              spin_lock_irq(&conf->device_lock);
++              wait_event_lock_irq(conf->wait_for_stripe,
++                                  !list_empty(&conf->inactive_list),
++                                  conf->device_lock,
++                                  unplug_slaves(conf->mddev)
++                      );
++              osh = get_free_stripe(conf);
++              spin_unlock_irq(&conf->device_lock);
++              atomic_set(&nsh->count, 1);
++              for(i=0; i<conf->pool_size; i++)
++                      nsh->dev[i].page = osh->dev[i].page;
++              for( ; i<newsize; i++)
++                      nsh->dev[i].page = NULL;
++              kmem_cache_free(conf->slab_cache, osh);
        }
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
+-      clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack);
+-      clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending);
++      kmem_cache_destroy(conf->slab_cache);
  
--      while(!list_empty(&completions)) {
-+      while (!list_empty(&completions)) {
-               piocb = list_get_first(&completions, struct lpfc_iocbq, list);
-               cmd = &piocb->iocb;
--              list_del(&piocb->list);
-+              list_del_init(&piocb->list);
+-      bi = return_bi;
+-      while (bi) {
+-              int bytes = bi->bi_size;
++      /* Step 3.
++       * At this point, we are holding all the stripes so the array
++       * is completely stalled, so now is a good time to resize
++       * conf->disks.
++       */
++      ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO);
++      if (ndisks) {
++              for (i=0; i<conf->raid_disks; i++)
++                      ndisks[i] = conf->disks[i];
++              kfree(conf->disks);
++              conf->disks = ndisks;
++      } else
++              err = -ENOMEM;
  
--              if (piocb->iocb_cmpl) {
-+              if (!piocb->iocb_cmpl)
-+                      lpfc_sli_release_iocbq(phba, piocb);
-+              else {
-                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                       cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-                       (piocb->iocb_cmpl) (phba, piocb, piocb);
--              } else
--                      lpfc_sli_release_iocbq(phba, piocb);
-+              }
+-              return_bi = bi->bi_next;
+-              bi->bi_next = NULL;
+-              bi->bi_size = 0;
+-              bi->bi_end_io(bi, bytes,
+-                      test_bit(BIO_UPTODATE, &bi->bi_flags) ? 0 : -EIO);
+-              bi = return_bi;
++      /* Step 4, return new stripes to service */
++      while(!list_empty(&newstripes)) {
++              nsh = list_entry(newstripes.next, struct stripe_head, lru);
++              list_del_init(&nsh->lru);
++              for (i=conf->raid_disks; i < newsize; i++)
++                      if (nsh->dev[i].page == NULL) {
++                              struct page *p = alloc_page(GFP_NOIO);
++                              nsh->dev[i].page = p;
++                              if (!p)
++                                      err = -ENOMEM;
++                      }
++              release_stripe(nsh);
        }
++      /* critical section pass, GFP_NOIO no longer needed */
  
-       return;
+-      if (more_to_read)
+-              set_bit(STRIPE_HANDLE, &sh->state);
+-      release_stripe(sh);
++      conf->slab_cache = sc;
++      conf->active_name = 1-conf->active_name;
++      conf->pool_size = newsize;
++      return err;
  }
++#endif
  
--void
--lpfc_els_unsol_event(struct lpfc_hba * phba,
--                   struct lpfc_sli_ring * pring, struct lpfc_iocbq * elsiocb)
-+static void
-+lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-+                    struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb)
+-static void ops_run_biofill(struct stripe_head *sh)
++static int drop_one_stripe(raid5_conf_t *conf)
  {
--      struct lpfc_sli *psli;
-       struct lpfc_nodelist *ndlp;
--      struct lpfc_dmabuf *mp;
--      uint32_t *lp;
--      IOCB_t *icmd;
-       struct ls_rjt stat;
--      uint32_t cmd;
--      uint32_t did;
--      uint32_t newnode;
--      uint32_t drop_cmd = 0;  /* by default do NOT drop received cmd */
--      uint32_t rjt_err = 0;
+-      struct dma_async_tx_descriptor *tx = NULL;
+-      raid5_conf_t *conf = sh->raid_conf;
+-      int i;
 -
--      psli = &phba->sli;
--      icmd = &elsiocb->iocb;
+-      pr_debug("%s: stripe %llu\n", __FUNCTION__,
+-              (unsigned long long)sh->sector);
 -
--      if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
--              ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) {
--              /* Not enough posted buffers; Try posting more buffers */
--              phba->fc_stat.NoRcvBuf++;
--              lpfc_post_buffer(phba, pring, 0, 1);
--              return;
+-      for (i = sh->disks; i--; ) {
+-              struct r5dev *dev = &sh->dev[i];
+-              if (test_bit(R5_Wantfill, &dev->flags)) {
+-                      struct bio *rbi;
+-                      spin_lock_irq(&conf->device_lock);
+-                      dev->read = rbi = dev->toread;
+-                      dev->toread = NULL;
+-                      spin_unlock_irq(&conf->device_lock);
+-                      while (rbi && rbi->bi_sector <
+-                              dev->sector + STRIPE_SECTORS) {
+-                              tx = async_copy_data(0, rbi, dev->page,
+-                                      dev->sector, tx);
+-                              rbi = r5_next_bio(rbi, dev->sector);
+-                      }
+-              }
+-      }
+-
+-      atomic_inc(&sh->count);
+-      async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,
+-              ops_complete_biofill, sh);
+-}
+-
+-static void ops_complete_compute5(void *stripe_head_ref)
+-{
+-      struct stripe_head *sh = stripe_head_ref;
+-      int target = sh->ops.target;
+-      struct r5dev *tgt = &sh->dev[target];
+-
+-      pr_debug("%s: stripe %llu\n", __FUNCTION__,
+-              (unsigned long long)sh->sector);
+-
+-      set_bit(R5_UPTODATE, &tgt->flags);
+-      BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
+-      clear_bit(R5_Wantcompute, &tgt->flags);
+-      set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+-      set_bit(STRIPE_HANDLE, &sh->state);
+-      release_stripe(sh);
+-}
+-
+-static struct dma_async_tx_descriptor *
+-ops_run_compute5(struct stripe_head *sh, unsigned long pending)
+-{
+-      /* kernel stack size limits the total number of disks */
+-      int disks = sh->disks;
+-      struct page *xor_srcs[disks];
+-      int target = sh->ops.target;
+-      struct r5dev *tgt = &sh->dev[target];
+-      struct page *xor_dest = tgt->page;
+-      int count = 0;
+-      struct dma_async_tx_descriptor *tx;
+-      int i;
+-
+-      pr_debug("%s: stripe %llu block: %d\n",
+-              __FUNCTION__, (unsigned long long)sh->sector, target);
+-      BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
+-
+-      for (i = disks; i--; )
+-              if (i != target)
+-                      xor_srcs[count++] = sh->dev[i].page;
+-
+-      atomic_inc(&sh->count);
+-
+-      if (unlikely(count == 1))
+-              tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,
+-                      0, NULL, ops_complete_compute5, sh);
+-      else
+-              tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+-                      ASYNC_TX_XOR_ZERO_DST, NULL,
+-                      ops_complete_compute5, sh);
+-
+-      /* ack now if postxor is not set to be run */
+-      if (tx && !test_bit(STRIPE_OP_POSTXOR, &pending))
+-              async_tx_ack(tx);
+-
+-      return tx;
+-}
+-
+-static void ops_complete_prexor(void *stripe_head_ref)
+-{
+-      struct stripe_head *sh = stripe_head_ref;
+-
+-      pr_debug("%s: stripe %llu\n", __FUNCTION__,
+-              (unsigned long long)sh->sector);
+-
+-      set_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
+-}
+-
+-static struct dma_async_tx_descriptor *
+-ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+-{
+-      /* kernel stack size limits the total number of disks */
+-      int disks = sh->disks;
+-      struct page *xor_srcs[disks];
+-      int count = 0, pd_idx = sh->pd_idx, i;
+-
+-      /* existing parity data subtracted */
+-      struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
+-
+-      pr_debug("%s: stripe %llu\n", __FUNCTION__,
+-              (unsigned long long)sh->sector);
+-
+-      for (i = disks; i--; ) {
+-              struct r5dev *dev = &sh->dev[i];
+-              /* Only process blocks that are known to be uptodate */
+-              if (dev->towrite && test_bit(R5_Wantprexor, &dev->flags))
+-                      xor_srcs[count++] = dev->page;
 -      }
 -
--      /* If there are no BDEs associated with this IOCB,
--       * there is nothing to do.
+-      tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+-              ASYNC_TX_DEP_ACK | ASYNC_TX_XOR_DROP_DST, tx,
+-              ops_complete_prexor, sh);
+-
+-      return tx;
+-}
+-
+-static struct dma_async_tx_descriptor *
+-ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+-{
+-      int disks = sh->disks;
+-      int pd_idx = sh->pd_idx, i;
+-
+-      /* check if prexor is active which means only process blocks
+-       * that are part of a read-modify-write (Wantprexor)
 -       */
--      if (icmd->ulpBdeCount == 0)
--              return;
-+      uint32_t *payload;
-+      uint32_t cmd, did, newnode, rjt_err = 0;
-+      IOCB_t *icmd = &elsiocb->iocb;
--      /* type of ELS cmd is first 32bit word in packet */
--      mp = lpfc_sli_ringpostbuf_get(phba, pring, getPaddr(icmd->un.
--                                                          cont64[0].
--                                                          addrHigh,
--                                                          icmd->un.
--                                                          cont64[0].addrLow));
--      if (mp == 0) {
--              drop_cmd = 1;
-+      if (vport == NULL || elsiocb->context2 == NULL)
-               goto dropit;
+-      int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+-
+-      pr_debug("%s: stripe %llu\n", __FUNCTION__,
+-              (unsigned long long)sh->sector);
+-
+-      for (i = disks; i--; ) {
+-              struct r5dev *dev = &sh->dev[i];
+-              struct bio *chosen;
+-              int towrite;
+-
+-              towrite = 0;
+-              if (prexor) { /* rmw */
+-                      if (dev->towrite &&
+-                          test_bit(R5_Wantprexor, &dev->flags))
+-                              towrite = 1;
+-              } else { /* rcw */
+-                      if (i != pd_idx && dev->towrite &&
+-                              test_bit(R5_LOCKED, &dev->flags))
+-                              towrite = 1;
+-              }
+-
+-              if (towrite) {
+-                      struct bio *wbi;
+-
+-                      spin_lock(&sh->lock);
+-                      chosen = dev->towrite;
+-                      dev->towrite = NULL;
+-                      BUG_ON(dev->written);
+-                      wbi = dev->written = chosen;
+-                      spin_unlock(&sh->lock);
+-
+-                      while (wbi && wbi->bi_sector <
+-                              dev->sector + STRIPE_SECTORS) {
+-                              tx = async_copy_data(1, wbi, dev->page,
+-                                      dev->sector, tx);
+-                              wbi = r5_next_bio(wbi, dev->sector);
+-                      }
+-              }
 -      }
-       newnode = 0;
--      lp = (uint32_t *) mp->virt;
--      cmd = *lp++;
--      lpfc_post_buffer(phba, &psli->ring[LPFC_ELS_RING], 1, 1);
-+      payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt;
-+      cmd = *payload;
-+      if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0)
-+              lpfc_post_buffer(phba, pring, 1, 1);
-+      did = icmd->un.rcvels.remoteID;
-       if (icmd->ulpStatus) {
--              lpfc_mbuf_free(phba, mp->virt, mp->phys);
--              kfree(mp);
--              drop_cmd = 1;
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV Unsol ELS:  status:x%x/x%x did:x%x",
-+                      icmd->ulpStatus, icmd->un.ulpWord[4], did);
-               goto dropit;
-       }
-       /* Check to see if link went down during discovery */
--      if (lpfc_els_chk_latt(phba)) {
--              lpfc_mbuf_free(phba, mp->virt, mp->phys);
--              kfree(mp);
--              drop_cmd = 1;
-+      if (lpfc_els_chk_latt(vport))
-               goto dropit;
+-
+-      return tx;
+-}
+-
+-static void ops_complete_postxor(void *stripe_head_ref)
+-{
+-      struct stripe_head *sh = stripe_head_ref;
+-
+-      pr_debug("%s: stripe %llu\n", __FUNCTION__,
+-              (unsigned long long)sh->sector);
+-
+-      set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+-      set_bit(STRIPE_HANDLE, &sh->state);
+-      release_stripe(sh);
+-}
+-
+-static void ops_complete_write(void *stripe_head_ref)
+-{
+-      struct stripe_head *sh = stripe_head_ref;
+-      int disks = sh->disks, i, pd_idx = sh->pd_idx;
+-
+-      pr_debug("%s: stripe %llu\n", __FUNCTION__,
+-              (unsigned long long)sh->sector);
+-
+-      for (i = disks; i--; ) {
+-              struct r5dev *dev = &sh->dev[i];
+-              if (dev->written || i == pd_idx)
+-                      set_bit(R5_UPTODATE, &dev->flags);
 -      }
--      did = icmd->un.rcvels.remoteID;
--      ndlp = lpfc_findnode_did(phba, did);
-+      /* Ignore traffic recevied during vport shutdown. */
-+      if (vport->load_flag & FC_UNLOADING)
-+              goto dropit;
-+
-+      ndlp = lpfc_findnode_did(vport, did);
-       if (!ndlp) {
-               /* Cannot find existing Fabric ndlp, so allocate a new one */
-               ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
--              if (!ndlp) {
--                      lpfc_mbuf_free(phba, mp->virt, mp->phys);
--                      kfree(mp);
--                      drop_cmd = 1;
-+              if (!ndlp)
-                       goto dropit;
+-
+-      set_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
+-      set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+-
+-      set_bit(STRIPE_HANDLE, &sh->state);
+-      release_stripe(sh);
+-}
+-
+-static void
+-ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+-{
+-      /* kernel stack size limits the total number of disks */
+-      int disks = sh->disks;
+-      struct page *xor_srcs[disks];
+-
+-      int count = 0, pd_idx = sh->pd_idx, i;
+-      struct page *xor_dest;
+-      int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+-      unsigned long flags;
+-      dma_async_tx_callback callback;
+-
+-      pr_debug("%s: stripe %llu\n", __FUNCTION__,
+-              (unsigned long long)sh->sector);
+-
+-      /* check if prexor is active which means only process blocks
+-       * that are part of a read-modify-write (written)
+-       */
+-      if (prexor) {
+-              xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
+-              for (i = disks; i--; ) {
+-                      struct r5dev *dev = &sh->dev[i];
+-                      if (dev->written)
+-                              xor_srcs[count++] = dev->page;
 -              }
+-      } else {
+-              xor_dest = sh->dev[pd_idx].page;
+-              for (i = disks; i--; ) {
+-                      struct r5dev *dev = &sh->dev[i];
+-                      if (i != pd_idx)
+-                              xor_srcs[count++] = dev->page;
+-              }
+-      }
+-
+-      /* check whether this postxor is part of a write */
+-      callback = test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending) ?
+-              ops_complete_write : ops_complete_postxor;
+-
+-      /* 1/ if we prexor'd then the dest is reused as a source
+-       * 2/ if we did not prexor then we are redoing the parity
+-       * set ASYNC_TX_XOR_DROP_DST and ASYNC_TX_XOR_ZERO_DST
+-       * for the synchronous xor case
+-       */
+-      flags = ASYNC_TX_DEP_ACK | ASYNC_TX_ACK |
+-              (prexor ? ASYNC_TX_XOR_DROP_DST : ASYNC_TX_XOR_ZERO_DST);
+-
+-      atomic_inc(&sh->count);
+-
+-      if (unlikely(count == 1)) {
+-              flags &= ~(ASYNC_TX_XOR_DROP_DST | ASYNC_TX_XOR_ZERO_DST);
+-              tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,
+-                      flags, tx, callback, sh);
+-      } else
+-              tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+-                      flags, tx, callback, sh);
+-}
+-
+-static void ops_complete_check(void *stripe_head_ref)
+-{
+-      struct stripe_head *sh = stripe_head_ref;
+-      int pd_idx = sh->pd_idx;
+-
+-      pr_debug("%s: stripe %llu\n", __FUNCTION__,
+-              (unsigned long long)sh->sector);
+-
+-      if (test_and_clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending) &&
+-              sh->ops.zero_sum_result == 0)
+-              set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+-
+-      set_bit(STRIPE_OP_CHECK, &sh->ops.complete);
+-      set_bit(STRIPE_HANDLE, &sh->state);
+-      release_stripe(sh);
+-}
+-
+-static void ops_run_check(struct stripe_head *sh)
+-{
+-      /* kernel stack size limits the total number of disks */
+-      int disks = sh->disks;
+-      struct page *xor_srcs[disks];
+-      struct dma_async_tx_descriptor *tx;
+-
+-      int count = 0, pd_idx = sh->pd_idx, i;
+-      struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
+-
+-      pr_debug("%s: stripe %llu\n", __FUNCTION__,
+-              (unsigned long long)sh->sector);
+-
+-      for (i = disks; i--; ) {
+-              struct r5dev *dev = &sh->dev[i];
+-              if (i != pd_idx)
+-                      xor_srcs[count++] = dev->page;
+-      }
+-
+-      tx = async_xor_zero_sum(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+-              &sh->ops.zero_sum_result, 0, NULL, NULL, NULL);
+-
+-      if (tx)
+-              set_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
+-      else
+-              clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
+-
+-      atomic_inc(&sh->count);
+-      tx = async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,
+-              ops_complete_check, sh);
+-}
+-
+-static void raid5_run_ops(struct stripe_head *sh, unsigned long pending)
+-{
+-      int overlap_clear = 0, i, disks = sh->disks;
+-      struct dma_async_tx_descriptor *tx = NULL;
+-
+-      if (test_bit(STRIPE_OP_BIOFILL, &pending)) {
+-              ops_run_biofill(sh);
+-              overlap_clear++;
+-      }
+-
+-      if (test_bit(STRIPE_OP_COMPUTE_BLK, &pending))
+-              tx = ops_run_compute5(sh, pending);
+-
+-      if (test_bit(STRIPE_OP_PREXOR, &pending))
+-              tx = ops_run_prexor(sh, tx);
+-
+-      if (test_bit(STRIPE_OP_BIODRAIN, &pending)) {
+-              tx = ops_run_biodrain(sh, tx);
+-              overlap_clear++;
+-      }
+-
+-      if (test_bit(STRIPE_OP_POSTXOR, &pending))
+-              ops_run_postxor(sh, tx);
+-
+-      if (test_bit(STRIPE_OP_CHECK, &pending))
+-              ops_run_check(sh);
+-
+-      if (test_bit(STRIPE_OP_IO, &pending))
+-              ops_run_io(sh);
+-
+-      if (overlap_clear)
+-              for (i = disks; i--; ) {
+-                      struct r5dev *dev = &sh->dev[i];
+-                      if (test_and_clear_bit(R5_Overlap, &dev->flags))
+-                              wake_up(&sh->raid_conf->wait_for_overlap);
+-              }
+-}
+-
+-static int grow_one_stripe(raid5_conf_t *conf)
+-{
+-      struct stripe_head *sh;
+-      sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
+-      if (!sh)
+-              return 0;
+-      memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
+-      sh->raid_conf = conf;
+-      spin_lock_init(&sh->lock);
+-
+-      if (grow_buffers(sh, conf->raid_disks)) {
+-              shrink_buffers(sh, conf->raid_disks);
+-              kmem_cache_free(conf->slab_cache, sh);
+-              return 0;
+-      }
+-      sh->disks = conf->raid_disks;
+-      /* we just created an active stripe so... */
+-      atomic_set(&sh->count, 1);
+-      atomic_inc(&conf->active_stripes);
+-      INIT_LIST_HEAD(&sh->lru);
+-      release_stripe(sh);
+-      return 1;
+-}
+-
+-static int grow_stripes(raid5_conf_t *conf, int num)
+-{
+-      struct kmem_cache *sc;
+-      int devs = conf->raid_disks;
+-
+-      sprintf(conf->cache_name[0], "raid5-%s", mdname(conf->mddev));
+-      sprintf(conf->cache_name[1], "raid5-%s-alt", mdname(conf->mddev));
+-      conf->active_name = 0;
+-      sc = kmem_cache_create(conf->cache_name[conf->active_name],
+-                             sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
+-                             0, 0, NULL, NULL);
+-      if (!sc)
+-              return 1;
+-      conf->slab_cache = sc;
+-      conf->pool_size = devs;
+-      while (num--)
+-              if (!grow_one_stripe(conf))
+-                      return 1;
+-      return 0;
+-}
+-
+-#ifdef CONFIG_MD_RAID5_RESHAPE
+-static int resize_stripes(raid5_conf_t *conf, int newsize)
+-{
+-      /* Make all the stripes able to hold 'newsize' devices.
+-       * New slots in each stripe get 'page' set to a new page.
+-       *
+-       * This happens in stages:
+-       * 1/ create a new kmem_cache and allocate the required number of
+-       *    stripe_heads.
+-       * 2/ gather all the old stripe_heads and tranfer the pages across
+-       *    to the new stripe_heads.  This will have the side effect of
+-       *    freezing the array as once all stripe_heads have been collected,
+-       *    no IO will be possible.  Old stripe heads are freed once their
+-       *    pages have been transferred over, and the old kmem_cache is
+-       *    freed when all stripes are done.
+-       * 3/ reallocate conf->disks to be suitable bigger.  If this fails,
+-       *    we simple return a failre status - no need to clean anything up.
+-       * 4/ allocate new pages for the new slots in the new stripe_heads.
+-       *    If this fails, we don't bother trying the shrink the
+-       *    stripe_heads down again, we just leave them as they are.
+-       *    As each stripe_head is processed the new one is released into
+-       *    active service.
+-       *
+-       * Once step2 is started, we cannot afford to wait for a write,
+-       * so we use GFP_NOIO allocations.
+-       */
+-      struct stripe_head *osh, *nsh;
+-      LIST_HEAD(newstripes);
+-      struct disk_info *ndisks;
+-      int err = 0;
+-      struct kmem_cache *sc;
+-      int i;
+-
+-      if (newsize <= conf->pool_size)
+-              return 0; /* never bother to shrink */
+-
+-      md_allow_write(conf->mddev);
+-
+-      /* Step 1 */
+-      sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
+-                             sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev),
+-                             0, 0, NULL, NULL);
+-      if (!sc)
+-              return -ENOMEM;
+-
+-      for (i = conf->max_nr_stripes; i; i--) {
+-              nsh = kmem_cache_alloc(sc, GFP_KERNEL);
+-              if (!nsh)
+-                      break;
+-
+-              memset(nsh, 0, sizeof(*nsh) + (newsize-1)*sizeof(struct r5dev));
+-
+-              nsh->raid_conf = conf;
+-              spin_lock_init(&nsh->lock);
+-
+-              list_add(&nsh->lru, &newstripes);
+-      }
+-      if (i) {
+-              /* didn't get enough, give up */
+-              while (!list_empty(&newstripes)) {
+-                      nsh = list_entry(newstripes.next, struct stripe_head, lru);
+-                      list_del(&nsh->lru);
+-                      kmem_cache_free(sc, nsh);
+-              }
+-              kmem_cache_destroy(sc);
+-              return -ENOMEM;
+-      }
+-      /* Step 2 - Must use GFP_NOIO now.
+-       * OK, we have enough stripes, start collecting inactive
+-       * stripes and copying them over
+-       */
+-      list_for_each_entry(nsh, &newstripes, lru) {
+-              spin_lock_irq(&conf->device_lock);
+-              wait_event_lock_irq(conf->wait_for_stripe,
+-                                  !list_empty(&conf->inactive_list),
+-                                  conf->device_lock,
+-                                  unplug_slaves(conf->mddev)
+-                      );
+-              osh = get_free_stripe(conf);
+-              spin_unlock_irq(&conf->device_lock);
+-              atomic_set(&nsh->count, 1);
+-              for(i=0; i<conf->pool_size; i++)
+-                      nsh->dev[i].page = osh->dev[i].page;
+-              for( ; i<newsize; i++)
+-                      nsh->dev[i].page = NULL;
+-              kmem_cache_free(conf->slab_cache, osh);
+-      }
+-      kmem_cache_destroy(conf->slab_cache);
+-
+-      /* Step 3.
+-       * At this point, we are holding all the stripes so the array
+-       * is completely stalled, so now is a good time to resize
+-       * conf->disks.
+-       */
+-      ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO);
+-      if (ndisks) {
+-              for (i=0; i<conf->raid_disks; i++)
+-                      ndisks[i] = conf->disks[i];
+-              kfree(conf->disks);
+-              conf->disks = ndisks;
+-      } else
+-              err = -ENOMEM;
+-
+-      /* Step 4, return new stripes to service */
+-      while(!list_empty(&newstripes)) {
+-              nsh = list_entry(newstripes.next, struct stripe_head, lru);
+-              list_del_init(&nsh->lru);
+-              for (i=conf->raid_disks; i < newsize; i++)
+-                      if (nsh->dev[i].page == NULL) {
+-                              struct page *p = alloc_page(GFP_NOIO);
+-                              nsh->dev[i].page = p;
+-                              if (!p)
+-                                      err = -ENOMEM;
+-                      }
+-              release_stripe(nsh);
+-      }
+-      /* critical section pass, GFP_NOIO no longer needed */
+-
+-      conf->slab_cache = sc;
+-      conf->active_name = 1-conf->active_name;
+-      conf->pool_size = newsize;
+-      return err;
+-}
+-#endif
+-
+-static int drop_one_stripe(raid5_conf_t *conf)
+-{
+-      struct stripe_head *sh;
++      struct stripe_head *sh;
  
--              lpfc_nlp_init(phba, ndlp, did);
-+              lpfc_nlp_init(vport, ndlp, did);
-               newnode = 1;
-               if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
-                       ndlp->nlp_type |= NLP_FABRIC;
-               }
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
-       }
-       phba->fc_stat.elsRcvFrame++;
-       if (elsiocb->context1)
-               lpfc_nlp_put(elsiocb->context1);
-       elsiocb->context1 = lpfc_nlp_get(ndlp);
--      elsiocb->context2 = mp;
-+      elsiocb->vport = vport;
-       if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) {
-               cmd &= ELS_CMD_MASK;
-       }
-       /* ELS command <elsCmd> received from NPORT <did> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
--                      "%d:0112 ELS command x%x received from NPORT x%x "
--                      "Data: x%x\n", phba->brd_no, cmd, did, phba->hba_state);
-+                      "%d (%d):0112 ELS command x%x received from NPORT x%x "
-+                      "Data: x%x\n", phba->brd_no, vport->vpi, cmd, did,
-+                      vport->port_state);
-       switch (cmd) {
-       case ELS_CMD_PLOGI:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV PLOGI:       did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvPLOGI++;
--              if (phba->hba_state < LPFC_DISC_AUTH) {
--                      rjt_err = 1;
-+              ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
-+
-+              if (vport->port_state < LPFC_DISC_AUTH) {
-+                      rjt_err = LSRJT_UNABLE_TPC;
-                       break;
-               }
--              ndlp = lpfc_plogi_confirm_nport(phba, mp, ndlp);
--              lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI);
-+              lpfc_disc_state_machine(vport, ndlp, elsiocb,
-+                                      NLP_EVT_RCV_PLOGI);
-+
-               break;
-       case ELS_CMD_FLOGI:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV FLOGI:       did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvFLOGI++;
--              lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode);
-+              lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode);
-               if (newnode)
--                      lpfc_drop_node(phba, ndlp);
-+                      lpfc_drop_node(vport, ndlp);
-               break;
-       case ELS_CMD_LOGO:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV LOGO:        did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvLOGO++;
--              if (phba->hba_state < LPFC_DISC_AUTH) {
--                      rjt_err = 1;
-+              if (vport->port_state < LPFC_DISC_AUTH) {
-+                      rjt_err = LSRJT_UNABLE_TPC;
-                       break;
-               }
--              lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
-+              lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
-               break;
-       case ELS_CMD_PRLO:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV PRLO:        did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvPRLO++;
--              if (phba->hba_state < LPFC_DISC_AUTH) {
--                      rjt_err = 1;
-+              if (vport->port_state < LPFC_DISC_AUTH) {
-+                      rjt_err = LSRJT_UNABLE_TPC;
-                       break;
-               }
--              lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
-+              lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
-               break;
-       case ELS_CMD_RSCN:
-               phba->fc_stat.elsRcvRSCN++;
--              lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode);
-+              lpfc_els_rcv_rscn(vport, elsiocb, ndlp, newnode);
-               if (newnode)
--                      lpfc_drop_node(phba, ndlp);
-+                      lpfc_drop_node(vport, ndlp);
-               break;
-       case ELS_CMD_ADISC:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV ADISC:       did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvADISC++;
--              if (phba->hba_state < LPFC_DISC_AUTH) {
--                      rjt_err = 1;
-+              if (vport->port_state < LPFC_DISC_AUTH) {
-+                      rjt_err = LSRJT_UNABLE_TPC;
-                       break;
-               }
--              lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_ADISC);
-+              lpfc_disc_state_machine(vport, ndlp, elsiocb,
-+                                      NLP_EVT_RCV_ADISC);
-               break;
-       case ELS_CMD_PDISC:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV PDISC:       did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvPDISC++;
--              if (phba->hba_state < LPFC_DISC_AUTH) {
--                      rjt_err = 1;
-+              if (vport->port_state < LPFC_DISC_AUTH) {
-+                      rjt_err = LSRJT_UNABLE_TPC;
-                       break;
-               }
--              lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PDISC);
-+              lpfc_disc_state_machine(vport, ndlp, elsiocb,
-+                                      NLP_EVT_RCV_PDISC);
-               break;
-       case ELS_CMD_FARPR:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV FARPR:       did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvFARPR++;
--              lpfc_els_rcv_farpr(phba, elsiocb, ndlp);
-+              lpfc_els_rcv_farpr(vport, elsiocb, ndlp);
-               break;
-       case ELS_CMD_FARP:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV FARP:        did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvFARP++;
--              lpfc_els_rcv_farp(phba, elsiocb, ndlp);
-+              lpfc_els_rcv_farp(vport, elsiocb, ndlp);
-               break;
-       case ELS_CMD_FAN:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV FAN:         did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvFAN++;
--              lpfc_els_rcv_fan(phba, elsiocb, ndlp);
-+              lpfc_els_rcv_fan(vport, elsiocb, ndlp);
-               break;
-       case ELS_CMD_PRLI:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV PRLI:        did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvPRLI++;
--              if (phba->hba_state < LPFC_DISC_AUTH) {
--                      rjt_err = 1;
-+              if (vport->port_state < LPFC_DISC_AUTH) {
-+                      rjt_err = LSRJT_UNABLE_TPC;
-                       break;
-               }
--              lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
-+              lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
-               break;
-       case ELS_CMD_LIRR:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV LIRR:        did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvLIRR++;
--              lpfc_els_rcv_lirr(phba, elsiocb, ndlp);
-+              lpfc_els_rcv_lirr(vport, elsiocb, ndlp);
-               if (newnode)
--                      lpfc_drop_node(phba, ndlp);
-+                      lpfc_drop_node(vport, ndlp);
-               break;
-       case ELS_CMD_RPS:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV RPS:         did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvRPS++;
--              lpfc_els_rcv_rps(phba, elsiocb, ndlp);
-+              lpfc_els_rcv_rps(vport, elsiocb, ndlp);
-               if (newnode)
--                      lpfc_drop_node(phba, ndlp);
-+                      lpfc_drop_node(vport, ndlp);
-               break;
-       case ELS_CMD_RPL:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV RPL:         did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvRPL++;
--              lpfc_els_rcv_rpl(phba, elsiocb, ndlp);
-+              lpfc_els_rcv_rpl(vport, elsiocb, ndlp);
-               if (newnode)
--                      lpfc_drop_node(phba, ndlp);
-+                      lpfc_drop_node(vport, ndlp);
-               break;
-       case ELS_CMD_RNID:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV RNID:        did:x%x/ste:x%x flg:x%x",
-+                      did, vport->port_state, ndlp->nlp_flag);
-+
-               phba->fc_stat.elsRcvRNID++;
--              lpfc_els_rcv_rnid(phba, elsiocb, ndlp);
-+              lpfc_els_rcv_rnid(vport, elsiocb, ndlp);
-               if (newnode)
--                      lpfc_drop_node(phba, ndlp);
-+                      lpfc_drop_node(vport, ndlp);
-               break;
-       default:
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
-+                      "RCV ELS cmd:     cmd:x%x did:x%x/ste:x%x",
-+                      cmd, did, vport->port_state);
-+
-               /* Unsupported ELS command, reject */
--              rjt_err = 1;
-+              rjt_err = LSRJT_INVALID_CMD;
-               /* Unknown ELS command <elsCmd> received from NPORT <did> */
-               lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
--                              "%d:0115 Unknown ELS command x%x received from "
--                              "NPORT x%x\n", phba->brd_no, cmd, did);
-+                              "%d (%d):0115 Unknown ELS command x%x "
-+                              "received from NPORT x%x\n",
-+                              phba->brd_no, vport->vpi, cmd, did);
-               if (newnode)
--                      lpfc_drop_node(phba, ndlp);
-+                      lpfc_drop_node(vport, ndlp);
-               break;
-       }
+       spin_lock_irq(&conf->device_lock);
+       sh = get_free_stripe(conf);
+@@ -1123,7 +537,7 @@
+               if (bi == &sh->dev[i].req)
+                       break;
  
-       /* check if need to LS_RJT received ELS cmd */
-       if (rjt_err) {
--              stat.un.b.lsRjtRsvd0 = 0;
--              stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-+              memset(&stat, 0, sizeof(stat));
-+              stat.un.b.lsRjtRsnCode = rjt_err;
-               stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
--              stat.un.b.vendorUnique = 0;
--              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, elsiocb, ndlp);
-+              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp,
-+                      NULL);
-+              if (newnode)
-+                      lpfc_drop_node(vport, ndlp);
-       }
+-      pr_debug("end_read_request %llu/%d, count: %d, uptodate %d.\n",
++      PRINTK("end_read_request %llu/%d, count: %d, uptodate %d.\n", 
+               (unsigned long long)sh->sector, i, atomic_read(&sh->count), 
+               uptodate);
+       if (i == disks) {
+@@ -1199,7 +613,7 @@
+               if (bi == &sh->dev[i].req)
+                       break;
+-      pr_debug("end_write_request %llu/%d, count %d, uptodate: %d.\n",
++      PRINTK("end_write_request %llu/%d, count %d, uptodate: %d.\n", 
+               (unsigned long long)sh->sector, i, atomic_read(&sh->count),
+               uptodate);
+       if (i == disks) {
+@@ -1244,7 +658,7 @@
+ {
+       char b[BDEVNAME_SIZE];
+       raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
+-      pr_debug("raid5: error called\n");
++      PRINTK("raid5: error called\n");
+       if (!test_bit(Faulty, &rdev->flags)) {
+               set_bit(MD_CHANGE_DEVS, &mddev->flags);
+@@ -1504,11 +918,135 @@
+ #define check_xor()   do {                                            \
+                          if (count == MAX_XOR_BLOCKS) {               \
+-                              xor_blocks(count, STRIPE_SIZE, dest, ptr);\
+-                              count = 0;                                \
++                              xor_block(count, STRIPE_SIZE, ptr);     \
++                              count = 1;                              \
+                          }                                            \
+                       } while(0)
  
--      lpfc_nlp_put(elsiocb->context1);
--      elsiocb->context1 = NULL;
--      if (elsiocb->context2) {
--              lpfc_mbuf_free(phba, mp->virt, mp->phys);
--              kfree(mp);
--      }
-+      return;
-+
- dropit:
--      /* check if need to drop received ELS cmd */
--      if (drop_cmd == 1) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
--                              "%d:0111 Dropping received ELS cmd "
--                              "Data: x%x x%x x%x\n", phba->brd_no,
-+                      "%d (%d):0111 Dropping received ELS cmd "
-+                      "Data: x%x x%x x%x\n",
-+                      phba->brd_no, vport ? vport->vpi : 0xffff,
-                               icmd->ulpStatus, icmd->un.ulpWord[4],
-                               icmd->ulpTimeout);
-               phba->fc_stat.elsRcvDrop++;
-+}
 +
-+static struct lpfc_vport *
-+lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
++static void compute_block(struct stripe_head *sh, int dd_idx)
 +{
-+      struct lpfc_vport *vport;
-+
-+      list_for_each_entry(vport, &phba->port_list, listentry) {
-+              if (vport->vpi == vpi)
-+                      return vport;
-+      }
-+      return NULL;
-+}
-+
-+void
-+lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-+                   struct lpfc_iocbq *elsiocb)
-+{
-+      struct lpfc_vport *vport = phba->pport;
-+      IOCB_t *icmd = &elsiocb->iocb;
-+      dma_addr_t paddr;
-+      struct lpfc_dmabuf *bdeBuf1 = elsiocb->context2;
-+      struct lpfc_dmabuf *bdeBuf2 = elsiocb->context3;
-+
-+      elsiocb->context2 = NULL;
-+      elsiocb->context3 = NULL;
-+
-+      if (icmd->ulpStatus == IOSTAT_NEED_BUFFER) {
-+              lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
-+      } else if (icmd->ulpStatus == IOSTAT_LOCAL_REJECT &&
-+          (icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING) {
-+              phba->fc_stat.NoRcvBuf++;
-+              /* Not enough posted buffers; Try posting more buffers */
-+              if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
-+                      lpfc_post_buffer(phba, pring, 0, 1);
-+              return;
-+      }
++      int i, count, disks = sh->disks;
++      void *ptr[MAX_XOR_BLOCKS], *p;
 +
-+      if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
-+          (icmd->ulpCommand == CMD_IOCB_RCV_ELS64_CX ||
-+           icmd->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
-+              if (icmd->unsli3.rcvsli3.vpi == 0xffff)
-+                      vport = phba->pport;
-+              else {
-+                      uint16_t vpi = icmd->unsli3.rcvsli3.vpi;
-+                      vport = lpfc_find_vport_by_vpid(phba, vpi);
-+              }
-+      }
-+                              /* If there are no BDEs associated
-+                               * with this IOCB, there is nothing to do.
-+                               */
-+      if (icmd->ulpBdeCount == 0)
-+              return;
++      PRINTK("compute_block, stripe %llu, idx %d\n", 
++              (unsigned long long)sh->sector, dd_idx);
 +
-+                              /* type of ELS cmd is first 32bit word
-+                               * in packet
-+                               */
-+      if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
-+              elsiocb->context2 = bdeBuf1;
-+      } else {
-+              paddr = getPaddr(icmd->un.cont64[0].addrHigh,
-+                               icmd->un.cont64[0].addrLow);
-+              elsiocb->context2 = lpfc_sli_ringpostbuf_get(phba, pring,
-+                                                           paddr);
-+      }
++      ptr[0] = page_address(sh->dev[dd_idx].page);
++      memset(ptr[0], 0, STRIPE_SIZE);
++      count = 1;
++      for (i = disks ; i--; ) {
++              if (i == dd_idx)
++                      continue;
++              p = page_address(sh->dev[i].page);
++              if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
++                      ptr[count++] = p;
++              else
++                      printk(KERN_ERR "compute_block() %d, stripe %llu, %d"
++                              " not present\n", dd_idx,
++                              (unsigned long long)sh->sector, i);
 +
-+      lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
-+      /*
-+       * The different unsolicited event handlers would tell us
-+       * if they are done with "mp" by setting context2 to NULL.
-+       */
-+      lpfc_nlp_put(elsiocb->context1);
-+      elsiocb->context1 = NULL;
-+      if (elsiocb->context2) {
-+              lpfc_in_buf_free(phba, (struct lpfc_dmabuf *)elsiocb->context2);
-+              elsiocb->context2 = NULL;
-+      }
-+
-+      /* RCV_ELS64_CX provide for 2 BDEs - process 2nd if included */
-+      if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) &&
-+          icmd->ulpBdeCount == 2) {
-+              elsiocb->context2 = bdeBuf2;
-+              lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
-+              /* free mp if we are done with it */
-+              if (elsiocb->context2) {
-+                      lpfc_in_buf_free(phba, elsiocb->context2);
-+                      elsiocb->context2 = NULL;
-+              }
++              check_xor();
 +      }
++      if (count != 1)
++              xor_block(count, STRIPE_SIZE, ptr);
++      set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
 +}
 +
-+void
-+lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
++static void compute_parity5(struct stripe_head *sh, int method)
 +{
-+      struct lpfc_nodelist *ndlp, *ndlp_fdmi;
-+
-+      ndlp = lpfc_findnode_did(vport, NameServer_DID);
-+      if (!ndlp) {
-+              ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
-+              if (!ndlp) {
-+                      if (phba->fc_topology == TOPOLOGY_LOOP) {
-+                              lpfc_disc_start(vport);
-+                              return;
++      raid5_conf_t *conf = sh->raid_conf;
++      int i, pd_idx = sh->pd_idx, disks = sh->disks, count;
++      void *ptr[MAX_XOR_BLOCKS];
++      struct bio *chosen;
++
++      PRINTK("compute_parity5, stripe %llu, method %d\n",
++              (unsigned long long)sh->sector, method);
++
++      count = 1;
++      ptr[0] = page_address(sh->dev[pd_idx].page);
++      switch(method) {
++      case READ_MODIFY_WRITE:
++              BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags));
++              for (i=disks ; i-- ;) {
++                      if (i==pd_idx)
++                              continue;
++                      if (sh->dev[i].towrite &&
++                          test_bit(R5_UPTODATE, &sh->dev[i].flags)) {
++                              ptr[count++] = page_address(sh->dev[i].page);
++                              chosen = sh->dev[i].towrite;
++                              sh->dev[i].towrite = NULL;
++
++                              if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
++                                      wake_up(&conf->wait_for_overlap);
++
++                              BUG_ON(sh->dev[i].written);
++                              sh->dev[i].written = chosen;
++                              check_xor();
 +                      }
-+                      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                              "%d (%d):0251 NameServer login: no memory\n",
-+                              phba->brd_no, vport->vpi);
-+                      return;
-+              }
-+              lpfc_nlp_init(vport, ndlp, NameServer_DID);
-+              ndlp->nlp_type |= NLP_FABRIC;
-+      }
-+
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
-+
-+      if (lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0)) {
-+              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                      "%d (%d):0252 Cannot issue NameServer login\n",
-+                      phba->brd_no, vport->vpi);
-+              return;
-+      }
-+
-+      if (phba->cfg_fdmi_on) {
-+              ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
-+                                        GFP_KERNEL);
-+              if (ndlp_fdmi) {
-+                      lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
-+                      ndlp_fdmi->nlp_type |= NLP_FABRIC;
-+                      ndlp_fdmi->nlp_state =
-+                              NLP_STE_PLOGI_ISSUE;
-+                      lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID,
-+                                           0);
-+              }
-+      }
-+      return;
-+}
-+
-+static void
-+lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
-+{
-+      struct lpfc_vport *vport = pmb->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
-+      MAILBOX_t *mb = &pmb->mb;
-+
-+      vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
-+      lpfc_nlp_put(ndlp);
-+
-+      if (mb->mbxStatus) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
-+                              "%d (%d):0915 Register VPI failed: 0x%x\n",
-+                              phba->brd_no, vport->vpi, mb->mbxStatus);
-+
-+              switch (mb->mbxStatus) {
-+              case 0x11:      /* unsupported feature */
-+              case 0x9603:    /* max_vpi exceeded */
-+                      /* giving up on vport registration */
-+                      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+                      spin_lock_irq(shost->host_lock);
-+                      vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
-+                      spin_unlock_irq(shost->host_lock);
-+                      lpfc_can_disctmo(vport);
-+                      break;
-+              default:
-+                      /* Try to recover from this error */
-+                      lpfc_mbx_unreg_vpi(vport);
-+                      vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
-+                      lpfc_initial_fdisc(vport);
-+                      break;
-+              }
-+
-+      } else {
-+              if (vport == phba->pport)
-+                      lpfc_issue_fabric_reglogin(vport);
-+              else
-+                      lpfc_do_scr_ns_plogi(phba, vport);
-       }
-+      mempool_free(pmb, phba->mbox_mem_pool);
-       return;
- }
-+
-+void
-+lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
-+                      struct lpfc_nodelist *ndlp)
-+{
-+      LPFC_MBOXQ_t *mbox;
-+
-+      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (mbox) {
-+              lpfc_reg_vpi(phba, vport->vpi, vport->fc_myDID, mbox);
-+              mbox->vport = vport;
-+              mbox->context2 = lpfc_nlp_get(ndlp);
-+              mbox->mbox_cmpl = lpfc_cmpl_reg_new_vport;
-+              if (lpfc_sli_issue_mbox(phba, mbox,
-+                                      MBX_NOWAIT | MBX_STOP_IOCB)
-+                  == MBX_NOT_FINISHED) {
-+                      mempool_free(mbox, phba->mbox_mem_pool);
-+                      vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
-+
-+                      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
-+                              "%d (%d):0253 Register VPI: Cannot send mbox\n",
-+                              phba->brd_no, vport->vpi);
 +              }
-+      } else {
-+              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+
-+              lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
-+                      "%d (%d):0254 Register VPI: no memory\n",
-+                      phba->brd_no, vport->vpi);
-+
-+              vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
-+              lpfc_nlp_put(ndlp);
-+      }
-+}
-+
-+static void
-+lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                  struct lpfc_iocbq *rspiocb)
-+{
-+      struct lpfc_vport *vport = cmdiocb->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
-+      struct lpfc_nodelist *np;
-+      struct lpfc_nodelist *next_np;
-+      IOCB_t *irsp = &rspiocb->iocb;
-+      struct lpfc_iocbq *piocb;
-+
-+      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-+              "%d (%d):0123 FDISC completes. x%x/x%x prevDID: x%x\n",
-+              phba->brd_no, vport->vpi,
-+              irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID);
-+
-+      /* Since all FDISCs are being single threaded, we
-+       * must reset the discovery timer for ALL vports
-+       * waiting to send FDISC when one completes.
-+       */
-+      list_for_each_entry(piocb, &phba->fabric_iocb_list, list) {
-+              lpfc_set_disctmo(piocb->vport);
-+      }
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "FDISC cmpl:      status:x%x/x%x prevdid:x%x",
-+              irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID);
-+
-+      if (irsp->ulpStatus) {
-+              /* Check for retry */
-+              if (lpfc_els_retry(phba, cmdiocb, rspiocb))
-+                      goto out;
-+
-+              /* FDISC failed */
-+              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                      "%d (%d):0124 FDISC failed. (%d/%d)\n",
-+                      phba->brd_no, vport->vpi,
-+                      irsp->ulpStatus, irsp->un.ulpWord[4]);
-+
-+              if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING)
-+                      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+
-+              lpfc_nlp_put(ndlp);
-+              /* giving up on FDISC. Cancel discovery timer */
-+              lpfc_can_disctmo(vport);
-+      } else {
-+              spin_lock_irq(shost->host_lock);
-+              vport->fc_flag |= FC_FABRIC;
-+              if (vport->phba->fc_topology == TOPOLOGY_LOOP)
-+                      vport->fc_flag |=  FC_PUBLIC_LOOP;
-+              spin_unlock_irq(shost->host_lock);
-+
-+              vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
-+              lpfc_vport_set_state(vport, FC_VPORT_ACTIVE);
-+              if ((vport->fc_prevDID != vport->fc_myDID) &&
-+                      !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
-+                      /* If our NportID changed, we need to ensure all
-+                       * remaining NPORTs get unreg_login'ed so we can
-+                       * issue unreg_vpi.
-+                       */
-+                      list_for_each_entry_safe(np, next_np,
-+                              &vport->fc_nodes, nlp_listp) {
-+                              if (np->nlp_state != NLP_STE_NPR_NODE
-+                                 || !(np->nlp_flag & NLP_NPR_ADISC))
-+                                      continue;
-+                              spin_lock_irq(shost->host_lock);
-+                              np->nlp_flag &= ~NLP_NPR_ADISC;
-+                              spin_unlock_irq(shost->host_lock);
-+                              lpfc_unreg_rpi(vport, np);
++              break;
++      case RECONSTRUCT_WRITE:
++              memset(ptr[0], 0, STRIPE_SIZE);
++              for (i= disks; i-- ;)
++                      if (i!=pd_idx && sh->dev[i].towrite) {
++                              chosen = sh->dev[i].towrite;
++                              sh->dev[i].towrite = NULL;
++
++                              if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
++                                      wake_up(&conf->wait_for_overlap);
++
++                              BUG_ON(sh->dev[i].written);
++                              sh->dev[i].written = chosen;
 +                      }
-+                      lpfc_mbx_unreg_vpi(vport);
-+                      vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
-+              }
-+
-+              if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)
-+                      lpfc_register_new_vport(phba, vport, ndlp);
-+              else
-+                      lpfc_do_scr_ns_plogi(phba, vport);
-+
-+              lpfc_nlp_put(ndlp); /* Free Fabric ndlp for vports */
-+      }
-+
-+out:
-+      lpfc_els_free_iocb(phba, cmdiocb);
-+}
-+
-+int
-+lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                   uint8_t retry)
-+{
-+      struct lpfc_hba *phba = vport->phba;
-+      IOCB_t *icmd;
-+      struct lpfc_iocbq *elsiocb;
-+      struct serv_parm *sp;
-+      uint8_t *pcmd;
-+      uint16_t cmdsize;
-+      int did = ndlp->nlp_DID;
-+      int rc;
-+
-+      cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
-+      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
-+                                   ELS_CMD_FDISC);
-+      if (!elsiocb) {
-+              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+
-+              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                      "%d (%d):0255 Issue FDISC: no IOCB\n",
-+                      phba->brd_no, vport->vpi);
-+              return 1;
-+      }
-+
-+      icmd = &elsiocb->iocb;
-+      icmd->un.elsreq64.myID = 0;
-+      icmd->un.elsreq64.fl = 1;
-+
-+      /* For FDISC, Let FDISC rsp set the NPortID for this VPI */
-+      icmd->ulpCt_h = 1;
-+      icmd->ulpCt_l = 0;
-+
-+      pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
-+      *((uint32_t *) (pcmd)) = ELS_CMD_FDISC;
-+      pcmd += sizeof(uint32_t); /* CSP Word 1 */
-+      memcpy(pcmd, &vport->phba->pport->fc_sparam, sizeof(struct serv_parm));
-+      sp = (struct serv_parm *) pcmd;
-+      /* Setup CSPs accordingly for Fabric */
-+      sp->cmn.e_d_tov = 0;
-+      sp->cmn.w2.r_a_tov = 0;
-+      sp->cls1.classValid = 0;
-+      sp->cls2.seqDelivery = 1;
-+      sp->cls3.seqDelivery = 1;
-+
-+      pcmd += sizeof(uint32_t); /* CSP Word 2 */
-+      pcmd += sizeof(uint32_t); /* CSP Word 3 */
-+      pcmd += sizeof(uint32_t); /* CSP Word 4 */
-+      pcmd += sizeof(uint32_t); /* Port Name */
-+      memcpy(pcmd, &vport->fc_portname, 8);
-+      pcmd += sizeof(uint32_t); /* Node Name */
-+      pcmd += sizeof(uint32_t); /* Node Name */
-+      memcpy(pcmd, &vport->fc_nodename, 8);
-+
-+      lpfc_set_disctmo(vport);
-+
-+      phba->fc_stat.elsXmitFDISC++;
-+      elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc;
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "Issue FDISC:     did:x%x",
-+              did, 0, 0);
-+
-+      rc = lpfc_issue_fabric_iocb(phba, elsiocb);
-+      if (rc == IOCB_ERROR) {
-+              lpfc_els_free_iocb(phba, elsiocb);
-+              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+
-+              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                      "%d (%d):0256 Issue FDISC: Cannot send IOCB\n",
-+                      phba->brd_no, vport->vpi);
-+
-+              return 1;
-+      }
-+      lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING);
-+      vport->port_state = LPFC_FDISC;
-+      return 0;
-+}
-+
-+static void
-+lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                      struct lpfc_iocbq *rspiocb)
-+{
-+      struct lpfc_vport *vport = cmdiocb->vport;
-+      IOCB_t *irsp;
-+
-+      irsp = &rspiocb->iocb;
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "LOGO npiv cmpl:  status:x%x/x%x did:x%x",
-+              irsp->ulpStatus, irsp->un.ulpWord[4], irsp->un.rcvels.remoteID);
-+
-+      lpfc_els_free_iocb(phba, cmdiocb);
-+      vport->unreg_vpi_cmpl = VPORT_ERROR;
-+}
-+
-+int
-+lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
-+{
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-+      struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
-+      IOCB_t *icmd;
-+      struct lpfc_iocbq *elsiocb;
-+      uint8_t *pcmd;
-+      uint16_t cmdsize;
-+
-+      cmdsize = 2 * sizeof(uint32_t) + sizeof(struct lpfc_name);
-+      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp, ndlp->nlp_DID,
-+                                   ELS_CMD_LOGO);
-+      if (!elsiocb)
-+              return 1;
-+
-+      icmd = &elsiocb->iocb;
-+      pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
-+      *((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
-+      pcmd += sizeof(uint32_t);
-+
-+      /* Fill in LOGO payload */
-+      *((uint32_t *) (pcmd)) = be32_to_cpu(vport->fc_myDID);
-+      pcmd += sizeof(uint32_t);
-+      memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "Issue LOGO npiv  did:x%x flg:x%x",
-+              ndlp->nlp_DID, ndlp->nlp_flag, 0);
-+
-+      elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo;
-+      spin_lock_irq(shost->host_lock);
-+      ndlp->nlp_flag |= NLP_LOGO_SND;
-+      spin_unlock_irq(shost->host_lock);
-+      if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
-+              spin_lock_irq(shost->host_lock);
-+              ndlp->nlp_flag &= ~NLP_LOGO_SND;
-+              spin_unlock_irq(shost->host_lock);
-+              lpfc_els_free_iocb(phba, elsiocb);
-+              return 1;
-+      }
-+      return 0;
-+}
-+
-+void
-+lpfc_fabric_block_timeout(unsigned long ptr)
-+{
-+      struct lpfc_hba  *phba = (struct lpfc_hba *) ptr;
-+      unsigned long iflags;
-+      uint32_t tmo_posted;
-+      spin_lock_irqsave(&phba->pport->work_port_lock, iflags);
-+      tmo_posted = phba->pport->work_port_events & WORKER_FABRIC_BLOCK_TMO;
-+      if (!tmo_posted)
-+              phba->pport->work_port_events |= WORKER_FABRIC_BLOCK_TMO;
-+      spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags);
-+
-+      if (!tmo_posted) {
-+              spin_lock_irqsave(&phba->hbalock, iflags);
-+              if (phba->work_wait)
-+                      lpfc_worker_wake_up(phba);
-+              spin_unlock_irqrestore(&phba->hbalock, iflags);
++              break;
++      case CHECK_PARITY:
++              break;
 +      }
-+}
-+
-+static void
-+lpfc_resume_fabric_iocbs(struct lpfc_hba *phba)
-+{
-+      struct lpfc_iocbq *iocb;
-+      unsigned long iflags;
-+      int ret;
-+      struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
-+      IOCB_t *cmd;
-+
-+repeat:
-+      iocb = NULL;
-+      spin_lock_irqsave(&phba->hbalock, iflags);
-+                              /* Post any pending iocb to the SLI layer */
-+      if (atomic_read(&phba->fabric_iocb_count) == 0) {
-+              list_remove_head(&phba->fabric_iocb_list, iocb, typeof(*iocb),
-+                               list);
-+              if (iocb)
-+                      atomic_inc(&phba->fabric_iocb_count);
-+      }
-+      spin_unlock_irqrestore(&phba->hbalock, iflags);
-+      if (iocb) {
-+              iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
-+              iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
-+              iocb->iocb_flag |= LPFC_IO_FABRIC;
-+
-+              lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
-+                      "Fabric sched1:   ste:x%x",
-+                      iocb->vport->port_state, 0, 0);
-+
-+              ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
-+
-+              if (ret == IOCB_ERROR) {
-+                      iocb->iocb_cmpl = iocb->fabric_iocb_cmpl;
-+                      iocb->fabric_iocb_cmpl = NULL;
-+                      iocb->iocb_flag &= ~LPFC_IO_FABRIC;
-+                      cmd = &iocb->iocb;
-+                      cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-+                      cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-+                      iocb->iocb_cmpl(phba, iocb, iocb);
-+
-+                      atomic_dec(&phba->fabric_iocb_count);
-+                      goto repeat;
-+              }
++      if (count>1) {
++              xor_block(count, STRIPE_SIZE, ptr);
++              count = 1;
 +      }
-+
-+      return;
-+}
-+
-+void
-+lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba)
-+{
-+      clear_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
-+
-+      lpfc_resume_fabric_iocbs(phba);
-+      return;
-+}
-+
-+static void
-+lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
-+{
-+      int blocked;
-+
-+      blocked = test_and_set_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
-+                              /* Start a timer to unblock fabric
-+                               * iocbs after 100ms
-+                               */
-+      if (!blocked)
-+              mod_timer(&phba->fabric_block_timer, jiffies + HZ/10 );
-+
-+      return;
-+}
-+
-+static void
-+lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+      struct lpfc_iocbq *rspiocb)
-+{
-+      struct ls_rjt stat;
-+
-+      if ((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC)
-+              BUG();
-+
-+      switch (rspiocb->iocb.ulpStatus) {
-+              case IOSTAT_NPORT_RJT:
-+              case IOSTAT_FABRIC_RJT:
-+                      if (rspiocb->iocb.un.ulpWord[4] & RJT_UNAVAIL_TEMP) {
-+                              lpfc_block_fabric_iocbs(phba);
++      
++      for (i = disks; i--;)
++              if (sh->dev[i].written) {
++                      sector_t sector = sh->dev[i].sector;
++                      struct bio *wbi = sh->dev[i].written;
++                      while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) {
++                              copy_data(1, wbi, sh->dev[i].page, sector);
++                              wbi = r5_next_bio(wbi, sector);
 +                      }
-+                      break;
-+
-+              case IOSTAT_NPORT_BSY:
-+              case IOSTAT_FABRIC_BSY:
-+                      lpfc_block_fabric_iocbs(phba);
-+                      break;
-+
-+              case IOSTAT_LS_RJT:
-+                      stat.un.lsRjtError =
-+                              be32_to_cpu(rspiocb->iocb.un.ulpWord[4]);
-+                      if ((stat.un.b.lsRjtRsnCode == LSRJT_UNABLE_TPC) ||
-+                              (stat.un.b.lsRjtRsnCode == LSRJT_LOGICAL_BSY))
-+                              lpfc_block_fabric_iocbs(phba);
-+                      break;
-+      }
-+
-+      if (atomic_read(&phba->fabric_iocb_count) == 0)
-+              BUG();
-+
-+      cmdiocb->iocb_cmpl = cmdiocb->fabric_iocb_cmpl;
-+      cmdiocb->fabric_iocb_cmpl = NULL;
-+      cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC;
-+      cmdiocb->iocb_cmpl(phba, cmdiocb, rspiocb);
-+
-+      atomic_dec(&phba->fabric_iocb_count);
-+      if (!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags)) {
-+                              /* Post any pending iocbs to HBA */
-+                  lpfc_resume_fabric_iocbs(phba);
-+      }
-+}
-+
-+int
-+lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
-+{
-+      unsigned long iflags;
-+      struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
-+      int ready;
-+      int ret;
-+
-+      if (atomic_read(&phba->fabric_iocb_count) > 1)
-+              BUG();
-+
-+      spin_lock_irqsave(&phba->hbalock, iflags);
-+      ready = atomic_read(&phba->fabric_iocb_count) == 0 &&
-+              !test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
-+
-+      spin_unlock_irqrestore(&phba->hbalock, iflags);
-+      if (ready) {
-+              iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
-+              iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
-+              iocb->iocb_flag |= LPFC_IO_FABRIC;
-+
-+              lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
-+                      "Fabric sched2:   ste:x%x",
-+                      iocb->vport->port_state, 0, 0);
-+
-+              atomic_inc(&phba->fabric_iocb_count);
-+              ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
-+
-+              if (ret == IOCB_ERROR) {
-+                      iocb->iocb_cmpl = iocb->fabric_iocb_cmpl;
-+                      iocb->fabric_iocb_cmpl = NULL;
-+                      iocb->iocb_flag &= ~LPFC_IO_FABRIC;
-+                      atomic_dec(&phba->fabric_iocb_count);
-+              }
-+      } else {
-+              spin_lock_irqsave(&phba->hbalock, iflags);
-+              list_add_tail(&iocb->list, &phba->fabric_iocb_list);
-+              spin_unlock_irqrestore(&phba->hbalock, iflags);
-+              ret = IOCB_SUCCESS;
-+      }
-+      return ret;
-+}
-+
-+
-+void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
-+{
-+      LIST_HEAD(completions);
-+      struct lpfc_hba  *phba = vport->phba;
-+      struct lpfc_iocbq *tmp_iocb, *piocb;
-+      IOCB_t *cmd;
-+
-+      spin_lock_irq(&phba->hbalock);
-+      list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
-+                               list) {
-+
-+              if (piocb->vport != vport)
-+                      continue;
-+
-+              list_move_tail(&piocb->list, &completions);
-+      }
-+      spin_unlock_irq(&phba->hbalock);
-+
-+      while (!list_empty(&completions)) {
-+              piocb = list_get_first(&completions, struct lpfc_iocbq, list);
-+              list_del_init(&piocb->list);
-+
-+              cmd = &piocb->iocb;
-+              cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-+              cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-+              (piocb->iocb_cmpl) (phba, piocb, piocb);
-+      }
-+}
-+
-+void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
-+{
-+      LIST_HEAD(completions);
-+      struct lpfc_hba  *phba = ndlp->vport->phba;
-+      struct lpfc_iocbq *tmp_iocb, *piocb;
-+      struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
-+      IOCB_t *cmd;
-+
-+      spin_lock_irq(&phba->hbalock);
-+      list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
-+                               list) {
-+              if ((lpfc_check_sli_ndlp(phba, pring, piocb, ndlp))) {
 +
-+                      list_move_tail(&piocb->list, &completions);
++                      set_bit(R5_LOCKED, &sh->dev[i].flags);
++                      set_bit(R5_UPTODATE, &sh->dev[i].flags);
 +              }
-+      }
-+      spin_unlock_irq(&phba->hbalock);
-+
-+      while (!list_empty(&completions)) {
-+              piocb = list_get_first(&completions, struct lpfc_iocbq, list);
-+              list_del_init(&piocb->list);
-+
-+              cmd = &piocb->iocb;
-+              cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-+              cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-+              (piocb->iocb_cmpl) (phba, piocb, piocb);
-+      }
-+}
-+
-+void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
-+{
-+      LIST_HEAD(completions);
-+      struct lpfc_iocbq *piocb;
-+      IOCB_t *cmd;
-+
-+      spin_lock_irq(&phba->hbalock);
-+      list_splice_init(&phba->fabric_iocb_list, &completions);
-+      spin_unlock_irq(&phba->hbalock);
-+
-+      while (!list_empty(&completions)) {
-+              piocb = list_get_first(&completions, struct lpfc_iocbq, list);
-+              list_del_init(&piocb->list);
-+
-+              cmd = &piocb->iocb;
-+              cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-+              cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-+              (piocb->iocb_cmpl) (phba, piocb, piocb);
-+      }
-+}
 +
-+
-+void lpfc_fabric_abort_flogi(struct lpfc_hba *phba)
-+{
-+      LIST_HEAD(completions);
-+      struct lpfc_iocbq *tmp_iocb, *piocb;
-+      IOCB_t *cmd;
-+      struct lpfc_nodelist *ndlp;
-+
-+      spin_lock_irq(&phba->hbalock);
-+      list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
-+                               list) {
-+
-+              cmd = &piocb->iocb;
-+              ndlp = (struct lpfc_nodelist *) piocb->context1;
-+              if (cmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
-+                  ndlp != NULL &&
-+                  ndlp->nlp_DID == Fabric_DID)
-+                      list_move_tail(&piocb->list, &completions);
-+      }
-+      spin_unlock_irq(&phba->hbalock);
-+
-+      while (!list_empty(&completions)) {
-+              piocb = list_get_first(&completions, struct lpfc_iocbq, list);
-+              list_del_init(&piocb->list);
-+
-+              cmd = &piocb->iocb;
-+              cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-+              cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-+              (piocb->iocb_cmpl) (phba, piocb, piocb);
++      switch(method) {
++      case RECONSTRUCT_WRITE:
++      case CHECK_PARITY:
++              for (i=disks; i--;)
++                      if (i != pd_idx) {
++                              ptr[count++] = page_address(sh->dev[i].page);
++                              check_xor();
++                      }
++              break;
++      case READ_MODIFY_WRITE:
++              for (i = disks; i--;)
++                      if (sh->dev[i].written) {
++                              ptr[count++] = page_address(sh->dev[i].page);
++                              check_xor();
++                      }
 +      }
++      if (count != 1)
++              xor_block(count, STRIPE_SIZE, ptr);
++      
++      if (method != CHECK_PARITY) {
++              set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
++              set_bit(R5_LOCKED,   &sh->dev[pd_idx].flags);
++      } else
++              clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
 +}
 +
-+
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_hbadisc.c linux-2.6.22-590/drivers/scsi/lpfc/lpfc_hbadisc.c
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_hbadisc.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_hbadisc.c  2008-01-02 13:56:37.000000000 -0500
-@@ -36,6 +36,8 @@
- #include "lpfc.h"
- #include "lpfc_logmsg.h"
- #include "lpfc_crtn.h"
-+#include "lpfc_vport.h"
-+#include "lpfc_debugfs.h"
+ static void compute_parity6(struct stripe_head *sh, int method)
+ {
+       raid6_conf_t *conf = sh->raid_conf;
+@@ -1520,7 +1058,7 @@
+       qd_idx = raid6_next_disk(pd_idx, disks);
+       d0_idx = raid6_next_disk(qd_idx, disks);
  
- /* AlpaArray for assignment of scsid for scan-down and bind_method */
- static uint8_t lpfcAlpaArray[] = {
-@@ -54,7 +56,7 @@
-       0x10, 0x0F, 0x08, 0x04, 0x02, 0x01
- };
+-      pr_debug("compute_parity, stripe %llu, method %d\n",
++      PRINTK("compute_parity, stripe %llu, method %d\n",
+               (unsigned long long)sh->sector, method);
  
--static void lpfc_disc_timeout_handler(struct lpfc_hba *);
-+static void lpfc_disc_timeout_handler(struct lpfc_vport *);
+       switch(method) {
+@@ -1594,20 +1132,20 @@
+ static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
+ {
+       int i, count, disks = sh->disks;
+-      void *ptr[MAX_XOR_BLOCKS], *dest, *p;
++      void *ptr[MAX_XOR_BLOCKS], *p;
+       int pd_idx = sh->pd_idx;
+       int qd_idx = raid6_next_disk(pd_idx, disks);
  
- void
- lpfc_terminate_rport_io(struct fc_rport *rport)
-@@ -74,14 +76,16 @@
-               return;
-       }
+-      pr_debug("compute_block_1, stripe %llu, idx %d\n",
++      PRINTK("compute_block_1, stripe %llu, idx %d\n",
+               (unsigned long long)sh->sector, dd_idx);
  
--      phba = ndlp->nlp_phba;
-+      phba  = ndlp->vport->phba;
-+
-+      lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT,
-+              "rport terminate: sid:x%x did:x%x flg:x%x",
-+              ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag);
+       if ( dd_idx == qd_idx ) {
+               /* We're actually computing the Q drive */
+               compute_parity6(sh, UPDATE_PARITY);
+       } else {
+-              dest = page_address(sh->dev[dd_idx].page);
+-              if (!nozero) memset(dest, 0, STRIPE_SIZE);
+-              count = 0;
++              ptr[0] = page_address(sh->dev[dd_idx].page);
++              if (!nozero) memset(ptr[0], 0, STRIPE_SIZE);
++              count = 1;
+               for (i = disks ; i--; ) {
+                       if (i == dd_idx || i == qd_idx)
+                               continue;
+@@ -1621,8 +1159,8 @@
  
--      spin_lock_irq(phba->host->host_lock);
-       if (ndlp->nlp_sid != NLP_NO_SID) {
-               lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
-                       ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
+                       check_xor();
+               }
+-              if (count)
+-                      xor_blocks(count, STRIPE_SIZE, dest, ptr);
++              if (count != 1)
++                      xor_block(count, STRIPE_SIZE, ptr);
+               if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
+               else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
        }
--      spin_unlock_irq(phba->host->host_lock);
-       return;
- }
-@@ -94,28 +98,98 @@
- {
-       struct lpfc_rport_data *rdata;
-       struct lpfc_nodelist * ndlp;
--      uint8_t *name;
--      int warn_on = 0;
-+      struct lpfc_vport *vport;
-       struct lpfc_hba *phba;
-+      struct completion devloss_compl;
-+      struct lpfc_work_evt *evtp;
+@@ -1645,7 +1183,7 @@
+       BUG_ON(faila == failb);
+       if ( failb < faila ) { int tmp = faila; faila = failb; failb = tmp; }
  
-       rdata = rport->dd_data;
-       ndlp = rdata->pnode;
+-      pr_debug("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",
++      PRINTK("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",
+              (unsigned long long)sh->sector, dd_idx1, dd_idx2, faila, failb);
  
-       if (!ndlp) {
--              if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
-+              if (rport->scsi_target_id != -1) {
-                       printk(KERN_ERR "Cannot find remote node"
-                       " for rport in dev_loss_tmo_callbk x%x\n",
-                       rport->port_id);
-+              }
-               return;
+       if ( failb == disks-1 ) {
+@@ -1691,79 +1229,7 @@
        }
+ }
  
--      if (ndlp->nlp_state == NLP_STE_MAPPED_NODE)
-+      vport = ndlp->vport;
-+      phba  = vport->phba;
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
-+              "rport devlosscb: sid:x%x did:x%x flg:x%x",
-+              ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag);
-+
-+      init_completion(&devloss_compl);
-+      evtp = &ndlp->dev_loss_evt;
-+
-+      if (!list_empty(&evtp->evt_listp))
-+              return;
-+
-+      spin_lock_irq(&phba->hbalock);
-+      evtp->evt_arg1  = ndlp;
-+      evtp->evt_arg2  = &devloss_compl;
-+      evtp->evt       = LPFC_EVT_DEV_LOSS;
-+      list_add_tail(&evtp->evt_listp, &phba->work_list);
-+      if (phba->work_wait)
-+              wake_up(phba->work_wait);
-+
-+      spin_unlock_irq(&phba->hbalock);
-+
-+      wait_for_completion(&devloss_compl);
-+
-+      return;
-+}
-+
-+/*
-+ * This function is called from the worker thread when dev_loss_tmo
-+ * expire.
-+ */
-+void
-+lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
-+{
-+      struct lpfc_rport_data *rdata;
-+      struct fc_rport   *rport;
-+      struct lpfc_vport *vport;
-+      struct lpfc_hba   *phba;
-+      uint8_t *name;
-+      int warn_on = 0;
-+
-+      rport = ndlp->rport;
-+
-+      if (!rport)
-               return;
--      name = (uint8_t *)&ndlp->nlp_portname;
--      phba = ndlp->nlp_phba;
-+      rdata = rport->dd_data;
-+      name = (uint8_t *) &ndlp->nlp_portname;
-+      vport = ndlp->vport;
-+      phba  = vport->phba;
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
-+              "rport devlosstmo:did:x%x type:x%x id:x%x",
-+              ndlp->nlp_DID, ndlp->nlp_type, rport->scsi_target_id);
--      spin_lock_irq(phba->host->host_lock);
-+      if (!(vport->load_flag & FC_UNLOADING) &&
-+          ndlp->nlp_state == NLP_STE_MAPPED_NODE)
-+              return;
-+
-+      if (ndlp->nlp_type & NLP_FABRIC) {
-+              int  put_node;
-+              int  put_rport;
-+
-+              /* We will clean up these Nodes in linkup */
-+              put_node = rdata->pnode != NULL;
-+              put_rport = ndlp->rport != NULL;
-+              rdata->pnode = NULL;
-+              ndlp->rport = NULL;
-+              if (put_node)
-+                      lpfc_nlp_put(ndlp);
-+              if (put_rport)
-+                      put_device(&rport->dev);
-+              return;
-+      }
-       if (ndlp->nlp_sid != NLP_NO_SID) {
-               warn_on = 1;
-@@ -123,76 +197,114 @@
-               lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
-                       ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
-       }
--      if (phba->fc_flag & FC_UNLOADING)
-+      if (vport->load_flag & FC_UNLOADING)
-               warn_on = 0;
+-static int
+-handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
+-{
+-      int i, pd_idx = sh->pd_idx, disks = sh->disks;
+-      int locked = 0;
+-
+-      if (rcw) {
+-              /* if we are not expanding this is a proper write request, and
+-               * there will be bios with new data to be drained into the
+-               * stripe cache
+-               */
+-              if (!expand) {
+-                      set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
+-                      sh->ops.count++;
+-              }
+-
+-              set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+-              sh->ops.count++;
+-
+-              for (i = disks; i--; ) {
+-                      struct r5dev *dev = &sh->dev[i];
+-
+-                      if (dev->towrite) {
+-                              set_bit(R5_LOCKED, &dev->flags);
+-                              if (!expand)
+-                                      clear_bit(R5_UPTODATE, &dev->flags);
+-                              locked++;
+-                      }
+-              }
+-      } else {
+-              BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||
+-                      test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));
+-
+-              set_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+-              set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
+-              set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+-
+-              sh->ops.count += 3;
+-
+-              for (i = disks; i--; ) {
+-                      struct r5dev *dev = &sh->dev[i];
+-                      if (i == pd_idx)
+-                              continue;
+-
+-                      /* For a read-modify write there may be blocks that are
+-                       * locked for reading while others are ready to be
+-                       * written so we distinguish these blocks by the
+-                       * R5_Wantprexor bit
+-                       */
+-                      if (dev->towrite &&
+-                          (test_bit(R5_UPTODATE, &dev->flags) ||
+-                          test_bit(R5_Wantcompute, &dev->flags))) {
+-                              set_bit(R5_Wantprexor, &dev->flags);
+-                              set_bit(R5_LOCKED, &dev->flags);
+-                              clear_bit(R5_UPTODATE, &dev->flags);
+-                              locked++;
+-                      }
+-              }
+-      }
+-
+-      /* keep the parity disk locked while asynchronous operations
+-       * are in flight
+-       */
+-      set_bit(R5_LOCKED, &sh->dev[pd_idx].flags);
+-      clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+-      locked++;
  
--      spin_unlock_irq(phba->host->host_lock);
+-      pr_debug("%s: stripe %llu locked: %d pending: %lx\n",
+-              __FUNCTION__, (unsigned long long)sh->sector,
+-              locked, sh->ops.pending);
 -
-       if (warn_on) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
--                              "%d:0203 Devloss timeout on "
-+                              "%d (%d):0203 Devloss timeout on "
-                               "WWPN %x:%x:%x:%x:%x:%x:%x:%x "
-                               "NPort x%x Data: x%x x%x x%x\n",
--                              phba->brd_no,
-+                              phba->brd_no, vport->vpi,
-                               *name, *(name+1), *(name+2), *(name+3),
-                               *(name+4), *(name+5), *(name+6), *(name+7),
-                               ndlp->nlp_DID, ndlp->nlp_flag,
-                               ndlp->nlp_state, ndlp->nlp_rpi);
-       } else {
-               lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                              "%d:0204 Devloss timeout on "
-+                              "%d (%d):0204 Devloss timeout on "
-                               "WWPN %x:%x:%x:%x:%x:%x:%x:%x "
-                               "NPort x%x Data: x%x x%x x%x\n",
--                              phba->brd_no,
-+                              phba->brd_no, vport->vpi,
-                               *name, *(name+1), *(name+2), *(name+3),
-                               *(name+4), *(name+5), *(name+6), *(name+7),
-                               ndlp->nlp_DID, ndlp->nlp_flag,
-                               ndlp->nlp_state, ndlp->nlp_rpi);
-       }
+-      return locked;
+-}
  
--      if (!(phba->fc_flag & FC_UNLOADING) &&
-+      if (!(vport->load_flag & FC_UNLOADING) &&
-           !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
-           !(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
-           (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE))
--              lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM);
-+              lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
-       else {
-+              int  put_node;
-+              int  put_rport;
-+
-+              put_node = rdata->pnode != NULL;
-+              put_rport = ndlp->rport != NULL;
-               rdata->pnode = NULL;
-               ndlp->rport = NULL;
-+              if (put_node)
-               lpfc_nlp_put(ndlp);
-+              if (put_rport)
-               put_device(&rport->dev);
-       }
-+}
-+
+ /*
+  * Each stripe/dev can have one or more bion attached.
+@@ -1776,7 +1242,7 @@
+       raid5_conf_t *conf = sh->raid_conf;
+       int firstwrite=0;
  
-+void
-+lpfc_worker_wake_up(struct lpfc_hba *phba)
-+{
-+      wake_up(phba->work_wait);
-       return;
- }
+-      pr_debug("adding bh b#%llu to stripe s#%llu\n",
++      PRINTK("adding bh b#%llu to stripe s#%llu\n",
+               (unsigned long long)bi->bi_sector,
+               (unsigned long long)sh->sector);
  
- static void
--lpfc_work_list_done(struct lpfc_hba * phba)
-+lpfc_work_list_done(struct lpfc_hba *phba)
- {
-       struct lpfc_work_evt  *evtp = NULL;
-       struct lpfc_nodelist  *ndlp;
-+      struct lpfc_vport     *vport;
-       int free_evt;
+@@ -1805,7 +1271,7 @@
+       spin_unlock_irq(&conf->device_lock);
+       spin_unlock(&sh->lock);
  
--      spin_lock_irq(phba->host->host_lock);
--      while(!list_empty(&phba->work_list)) {
-+      spin_lock_irq(&phba->hbalock);
-+      while (!list_empty(&phba->work_list)) {
-               list_remove_head((&phba->work_list), evtp, typeof(*evtp),
-                                evt_listp);
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(&phba->hbalock);
-               free_evt = 1;
-               switch (evtp->evt) {
-+              case LPFC_EVT_DEV_LOSS_DELAY:
-+                      free_evt = 0; /* evt is part of ndlp */
-+                      ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1);
-+                      vport = ndlp->vport;
-+                      if (!vport)
-+                              break;
-+
-+                      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
-+                              "rport devlossdly:did:x%x flg:x%x",
-+                              ndlp->nlp_DID, ndlp->nlp_flag, 0);
-+
-+                      if (!(vport->load_flag & FC_UNLOADING) &&
-+                          !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
-+                          !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
-+                              lpfc_disc_state_machine(vport, ndlp, NULL,
-+                                      NLP_EVT_DEVICE_RM);
-+                      }
-+                      break;
-               case LPFC_EVT_ELS_RETRY:
--                      ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1);
-+                      ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1);
-                       lpfc_els_retry_delay_handler(ndlp);
-+                      free_evt = 0; /* evt is part of ndlp */
-+                      break;
-+              case LPFC_EVT_DEV_LOSS:
-+                      ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1);
-+                      lpfc_nlp_get(ndlp);
-+                      lpfc_dev_loss_tmo_handler(ndlp);
-                       free_evt = 0;
-+                      complete((struct completion *)(evtp->evt_arg2));
-+                      lpfc_nlp_put(ndlp);
-                       break;
-               case LPFC_EVT_ONLINE:
--                      if (phba->hba_state < LPFC_LINK_DOWN)
--                              *(int *)(evtp->evt_arg1)  = lpfc_online(phba);
-+                      if (phba->link_state < LPFC_LINK_DOWN)
-+                              *(int *) (evtp->evt_arg1) = lpfc_online(phba);
-                       else
--                              *(int *)(evtp->evt_arg1)  = 0;
-+                              *(int *) (evtp->evt_arg1) = 0;
-                       complete((struct completion *)(evtp->evt_arg2));
-                       break;
-               case LPFC_EVT_OFFLINE_PREP:
--                      if (phba->hba_state >= LPFC_LINK_DOWN)
-+                      if (phba->link_state >= LPFC_LINK_DOWN)
-                               lpfc_offline_prep(phba);
-                       *(int *)(evtp->evt_arg1) = 0;
-                       complete((struct completion *)(evtp->evt_arg2));
-@@ -218,33 +330,31 @@
-               case LPFC_EVT_KILL:
-                       lpfc_offline(phba);
-                       *(int *)(evtp->evt_arg1)
--                              = (phba->stopped) ? 0 : lpfc_sli_brdkill(phba);
-+                              = (phba->pport->stopped)
-+                                      ? 0 : lpfc_sli_brdkill(phba);
-                       lpfc_unblock_mgmt_io(phba);
-                       complete((struct completion *)(evtp->evt_arg2));
-                       break;
-               }
-               if (free_evt)
-                       kfree(evtp);
--              spin_lock_irq(phba->host->host_lock);
-+              spin_lock_irq(&phba->hbalock);
-       }
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
+-      pr_debug("added bi b#%llu to stripe s#%llu, disk %d.\n",
++      PRINTK("added bi b#%llu to stripe s#%llu, disk %d.\n",
+               (unsigned long long)bi->bi_sector,
+               (unsigned long long)sh->sector, dd_idx);
  
+@@ -1860,14 +1326,116 @@
+       return pd_idx;
  }
  
 -static void
--lpfc_work_done(struct lpfc_hba * phba)
-+void
-+lpfc_work_done(struct lpfc_hba *phba)
+-handle_requests_to_failed_array(raid5_conf_t *conf, struct stripe_head *sh,
+-                              struct stripe_head_state *s, int disks,
+-                              struct bio **return_bi)
++
++/*
++ * handle_stripe - do things to a stripe.
++ *
++ * We lock the stripe and then examine the state of various bits
++ * to see what needs to be done.
++ * Possible results:
++ *    return some read request which now have data
++ *    return some write requests which are safely on disc
++ *    schedule a read on some buffers
++ *    schedule a write of some buffers
++ *    return confirmation of parity correctness
++ *
++ * Parity calculations are done inside the stripe lock
++ * buffers are taken off read_list or write_list, and bh_cache buffers
++ * get BH_Lock set before the stripe lock is released.
++ *
++ */
++ 
++static void handle_stripe5(struct stripe_head *sh)
  {
-       struct lpfc_sli_ring *pring;
 -      int i;
--      uint32_t ha_copy;
--      uint32_t control;
--      uint32_t work_hba_events;
-+      uint32_t ha_copy, status, control, work_port_events;
-+      struct lpfc_vport *vport;
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       ha_copy = phba->work_ha;
-       phba->work_ha = 0;
--      work_hba_events=phba->work_hba_events;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
-       if (ha_copy & HA_ERATT)
-               lpfc_handle_eratt(phba);
-@@ -255,66 +365,111 @@
-       if (ha_copy & HA_LATT)
-               lpfc_handle_latt(phba);
--      if (work_hba_events & WORKER_DISC_TMO)
--              lpfc_disc_timeout_handler(phba);
-+      spin_lock_irq(&phba->hbalock);
-+      list_for_each_entry(vport, &phba->port_list, listentry) {
-+              struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      for (i = disks; i--; ) {
++      raid5_conf_t *conf = sh->raid_conf;
++      int disks = sh->disks;
++      struct bio *return_bi= NULL;
+               struct bio *bi;
++      int i;
++      int syncing, expanding, expanded;
++      int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
++      int non_overwrite = 0;
++      int failed_num=0;
++      struct r5dev *dev;
 +
-+              if (!scsi_host_get(shost)) {
-+                      continue;
-+              }
-+              spin_unlock_irq(&phba->hbalock);
-+              work_port_events = vport->work_port_events;
++      PRINTK("handling stripe %llu, cnt=%d, pd_idx=%d\n",
++              (unsigned long long)sh->sector, atomic_read(&sh->count),
++              sh->pd_idx);
 +
-+              if (work_port_events & WORKER_DISC_TMO)
-+                      lpfc_disc_timeout_handler(vport);
--      if (work_hba_events & WORKER_ELS_TMO)
--              lpfc_els_timeout_handler(phba);
-+              if (work_port_events & WORKER_ELS_TMO)
-+                      lpfc_els_timeout_handler(vport);
--      if (work_hba_events & WORKER_MBOX_TMO)
-+              if (work_port_events & WORKER_HB_TMO)
-+                      lpfc_hb_timeout_handler(phba);
++      spin_lock(&sh->lock);
++      clear_bit(STRIPE_HANDLE, &sh->state);
++      clear_bit(STRIPE_DELAYED, &sh->state);
 +
-+              if (work_port_events & WORKER_MBOX_TMO)
-               lpfc_mbox_timeout_handler(phba);
--      if (work_hba_events & WORKER_FDMI_TMO)
--              lpfc_fdmi_tmo_handler(phba);
-+              if (work_port_events & WORKER_FABRIC_BLOCK_TMO)
-+                      lpfc_unblock_fabric_iocbs(phba);
++      syncing = test_bit(STRIPE_SYNCING, &sh->state);
++      expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
++      expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
++      /* Now to look around and see what can be done */
 +
-+              if (work_port_events & WORKER_FDMI_TMO)
-+                      lpfc_fdmi_timeout_handler(vport);
--      spin_lock_irq(phba->host->host_lock);
--      phba->work_hba_events &= ~work_hba_events;
--      spin_unlock_irq(phba->host->host_lock);
--
--      for (i = 0; i < phba->sli.num_rings; i++, ha_copy >>= 4) {
--              pring = &phba->sli.ring[i];
--              if ((ha_copy & HA_RXATT)
-+              if (work_port_events & WORKER_RAMP_DOWN_QUEUE)
-+                      lpfc_ramp_down_queue_handler(phba);
++      rcu_read_lock();
++      for (i=disks; i--; ) {
++              mdk_rdev_t *rdev;
++              dev = &sh->dev[i];
++              clear_bit(R5_Insync, &dev->flags);
++
++              PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
++                      i, dev->flags, dev->toread, dev->towrite, dev->written);
++              /* maybe we can reply to a read */
++              if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
++                      struct bio *rbi, *rbi2;
++                      PRINTK("Return read for disc %d\n", i);
++                      spin_lock_irq(&conf->device_lock);
++                      rbi = dev->toread;
++                      dev->toread = NULL;
++                      if (test_and_clear_bit(R5_Overlap, &dev->flags))
++                              wake_up(&conf->wait_for_overlap);
++                      spin_unlock_irq(&conf->device_lock);
++                      while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
++                              copy_data(0, rbi, dev->page, dev->sector);
++                              rbi2 = r5_next_bio(rbi, dev->sector);
++                              spin_lock_irq(&conf->device_lock);
++                              if (--rbi->bi_phys_segments == 0) {
++                                      rbi->bi_next = return_bi;
++                                      return_bi = rbi;
++                              }
++                              spin_unlock_irq(&conf->device_lock);
++                              rbi = rbi2;
++                      }
++              }
 +
-+              if (work_port_events & WORKER_RAMP_UP_QUEUE)
-+                      lpfc_ramp_up_queue_handler(phba);
++              /* now count some things */
++              if (test_bit(R5_LOCKED, &dev->flags)) locked++;
++              if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;
 +
-+              spin_lock_irq(&vport->work_port_lock);
-+              vport->work_port_events &= ~work_port_events;
-+              spin_unlock_irq(&vport->work_port_lock);
-+              scsi_host_put(shost);
-+              spin_lock_irq(&phba->hbalock);
++              
++              if (dev->toread) to_read++;
++              if (dev->towrite) {
++                      to_write++;
++                      if (!test_bit(R5_OVERWRITE, &dev->flags))
++                              non_overwrite++;
++              }
++              if (dev->written) written++;
++              rdev = rcu_dereference(conf->disks[i].rdev);
++              if (!rdev || !test_bit(In_sync, &rdev->flags)) {
++                      /* The ReadError flag will just be confusing now */
++                      clear_bit(R5_ReadError, &dev->flags);
++                      clear_bit(R5_ReWrite, &dev->flags);
++              }
++              if (!rdev || !test_bit(In_sync, &rdev->flags)
++                  || test_bit(R5_ReadError, &dev->flags)) {
++                      failed++;
++                      failed_num = i;
++              } else
++                      set_bit(R5_Insync, &dev->flags);
 +      }
-+      spin_unlock_irq(&phba->hbalock);
++      rcu_read_unlock();
++      PRINTK("locked=%d uptodate=%d to_read=%d"
++              " to_write=%d failed=%d failed_num=%d\n",
++              locked, uptodate, to_read, to_write, failed, failed_num);
++      /* check if the array has lost two devices and, if so, some requests might
++       * need to be failed
++       */
++      if (failed > 1 && to_read+to_write+written) {
++              for (i=disks; i--; ) {
+                       int bitmap_end = 0;
+                       if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
+@@ -1879,26 +1447,23 @@
+                                       md_error(conf->mddev, rdev);
+                               rcu_read_unlock();
+                       }
 +
-+      pring = &phba->sli.ring[LPFC_ELS_RING];
-+      status = (ha_copy & (HA_RXMASK  << (4*LPFC_ELS_RING)));
-+      status >>= (4*LPFC_ELS_RING);
-+      if ((status & HA_RXMASK)
-                   || (pring->flag & LPFC_DEFERRED_RING_EVENT)) {
-                       if (pring->flag & LPFC_STOP_IOCB_MASK) {
-                               pring->flag |= LPFC_DEFERRED_RING_EVENT;
-                       } else {
-                               lpfc_sli_handle_slow_ring_event(phba, pring,
--                                                              (ha_copy &
-+                                                      (status &
-                                                                HA_RXMASK));
-                               pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
+                       spin_lock_irq(&conf->device_lock);
+                       /* fail all writes first */
+                       bi = sh->dev[i].towrite;
+                       sh->dev[i].towrite = NULL;
+-              if (bi) {
+-                      s->to_write--;
+-                      bitmap_end = 1;
+-              }
++                      if (bi) { to_write--; bitmap_end = 1; }
+                       if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+                               wake_up(&conf->wait_for_overlap);
+-              while (bi && bi->bi_sector <
+-                      sh->dev[i].sector + STRIPE_SECTORS) {
++                      while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
+                               struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
+                               clear_bit(BIO_UPTODATE, &bi->bi_flags);
+                               if (--bi->bi_phys_segments == 0) {
+                                       md_write_end(conf->mddev);
+-                              bi->bi_next = *return_bi;
+-                              *return_bi = bi;
++                                      bi->bi_next = return_bi;
++                                      return_bi = bi;
+                               }
+                               bi = nextbi;
                        }
-                       /*
-                        * Turn on Ring interrupts
-                        */
--                      spin_lock_irq(phba->host->host_lock);
-+              spin_lock_irq(&phba->hbalock);
-                       control = readl(phba->HCregaddr);
--                      control |= (HC_R0INT_ENA << i);
-+              if (!(control & (HC_R0INT_ENA << LPFC_ELS_RING))) {
-+                      control |= (HC_R0INT_ENA << LPFC_ELS_RING);
-                       writel(control, phba->HCregaddr);
-                       readl(phba->HCregaddr); /* flush */
--                      spin_unlock_irq(phba->host->host_lock);
+@@ -1906,37 +1471,31 @@
+                       bi = sh->dev[i].written;
+                       sh->dev[i].written = NULL;
+                       if (bi) bitmap_end = 1;
+-              while (bi && bi->bi_sector <
+-                     sh->dev[i].sector + STRIPE_SECTORS) {
++                      while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
+                               struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
+                               clear_bit(BIO_UPTODATE, &bi->bi_flags);
+                               if (--bi->bi_phys_segments == 0) {
+                                       md_write_end(conf->mddev);
+-                              bi->bi_next = *return_bi;
+-                              *return_bi = bi;
++                                      bi->bi_next = return_bi;
++                                      return_bi = bi;
+                       }
+                       bi = bi2;
                }
-+              spin_unlock_irq(&phba->hbalock);
+-              /* fail any reads if this device is non-operational and
+-               * the data has not reached the cache yet.
+-               */
+-              if (!test_bit(R5_Wantfill, &sh->dev[i].flags) &&
+-                  (!test_bit(R5_Insync, &sh->dev[i].flags) ||
+-                    test_bit(R5_ReadError, &sh->dev[i].flags))) {
++                      /* fail any reads if this device is non-operational */
++                      if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
++                          test_bit(R5_ReadError, &sh->dev[i].flags)) {
+                       bi = sh->dev[i].toread;
+                       sh->dev[i].toread = NULL;
+                       if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+                               wake_up(&conf->wait_for_overlap);
+-                      if (bi) s->to_read--;
+-                      while (bi && bi->bi_sector <
+-                             sh->dev[i].sector + STRIPE_SECTORS) {
+-                              struct bio *nextbi =
+-                                      r5_next_bio(bi, sh->dev[i].sector);
++                              if (bi) to_read--;
++                              while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
++                                      struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
+                               clear_bit(BIO_UPTODATE, &bi->bi_flags);
+                               if (--bi->bi_phys_segments == 0) {
+-                                      bi->bi_next = *return_bi;
+-                                      *return_bi = bi;
++                                              bi->bi_next = return_bi;
++                                              return_bi = bi;
+                               }
+                               bi = nextbi;
+                       }
+@@ -1946,195 +1505,44 @@
+                       bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+                                       STRIPE_SECTORS, 0, 0);
        }
 -
--      lpfc_work_list_done (phba);
+-}
 -
-+      lpfc_work_list_done(phba);
- }
+-/* __handle_issuing_new_read_requests5 - returns 0 if there are no more disks
+- * to process
+- */
+-static int __handle_issuing_new_read_requests5(struct stripe_head *sh,
+-                      struct stripe_head_state *s, int disk_idx, int disks)
+-{
+-      struct r5dev *dev = &sh->dev[disk_idx];
+-      struct r5dev *failed_dev = &sh->dev[s->failed_num];
+-
+-      /* don't schedule compute operations or reads on the parity block while
+-       * a check is in flight
+-       */
+-      if ((disk_idx == sh->pd_idx) &&
+-           test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
+-              return ~0;
+-
+-      /* is the data in this block needed, and can we get it? */
+-      if (!test_bit(R5_LOCKED, &dev->flags) &&
+-          !test_bit(R5_UPTODATE, &dev->flags) && (dev->toread ||
+-          (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
+-           s->syncing || s->expanding || (s->failed &&
+-           (failed_dev->toread || (failed_dev->towrite &&
+-           !test_bit(R5_OVERWRITE, &failed_dev->flags)
+-           ))))) {
+-              /* 1/ We would like to get this block, possibly by computing it,
+-               * but we might not be able to.
+-               *
+-               * 2/ Since parity check operations potentially make the parity
+-               * block !uptodate it will need to be refreshed before any
+-               * compute operations on data disks are scheduled.
+-               *
+-               * 3/ We hold off parity block re-reads until check operations
+-               * have quiesced.
+-               */
+-              if ((s->uptodate == disks - 1) &&
+-                  !test_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
+-                      set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+-                      set_bit(R5_Wantcompute, &dev->flags);
+-                      sh->ops.target = disk_idx;
+-                      s->req_compute = 1;
+-                      sh->ops.count++;
+-                      /* Careful: from this point on 'uptodate' is in the eye
+-                       * of raid5_run_ops which services 'compute' operations
+-                       * before writes. R5_Wantcompute flags a block that will
+-                       * be R5_UPTODATE by the time it is needed for a
+-                       * subsequent operation.
+-                       */
+-                      s->uptodate++;
+-                      return 0; /* uptodate + compute == disks */
+-              } else if ((s->uptodate < disks - 1) &&
+-                      test_bit(R5_Insync, &dev->flags)) {
+-                      /* Note: we hold off compute operations while checks are
+-                       * in flight, but we still prefer 'compute' over 'read'
+-                       * hence we only read if (uptodate < * disks-1)
+-                       */
+-                      set_bit(R5_LOCKED, &dev->flags);
+-                      set_bit(R5_Wantread, &dev->flags);
+-                      if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+-                              sh->ops.count++;
+-                      s->locked++;
+-                      pr_debug("Reading block %d (sync=%d)\n", disk_idx,
+-                              s->syncing);
+-                              }
+                       }
+-
+-      return ~0;
+-}
+-
+-static void handle_issuing_new_read_requests5(struct stripe_head *sh,
+-                      struct stripe_head_state *s, int disks)
+-{
+-      int i;
+-
+-      /* Clear completed compute operations.  Parity recovery
+-       * (STRIPE_OP_MOD_REPAIR_PD) implies a write-back which is handled
+-       * later on in this routine
+-       */
+-      if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
+-              !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
+-              clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+-              clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
+-              clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+-      }
+-
+-      /* look for blocks to read/compute, skip this if a compute
+-       * is already in flight, or if the stripe contents are in the
+-       * midst of changing due to a write
+-       */
+-      if (!test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
+-              !test_bit(STRIPE_OP_PREXOR, &sh->ops.pending) &&
+-              !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+-              for (i = disks; i--; )
+-                      if (__handle_issuing_new_read_requests5(
+-                              sh, s, i, disks) == 0)
+-                              break;
++      if (failed > 1 && syncing) {
++              md_done_sync(conf->mddev, STRIPE_SECTORS,0);
++              clear_bit(STRIPE_SYNCING, &sh->state);
++              syncing = 0;
+                               }
+-      set_bit(STRIPE_HANDLE, &sh->state);
+-}
  
- static int
--check_work_wait_done(struct lpfc_hba *phba) {
-+check_work_wait_done(struct lpfc_hba *phba)
-+{
-+      struct lpfc_vport *vport;
-+      struct lpfc_sli_ring *pring;
-+      int rc = 0;
+-static void handle_issuing_new_read_requests6(struct stripe_head *sh,
+-                      struct stripe_head_state *s, struct r6_state *r6s,
+-                      int disks)
+-{
+-      int i;
+-      for (i = disks; i--; ) {
+-              struct r5dev *dev = &sh->dev[i];
+-              if (!test_bit(R5_LOCKED, &dev->flags) &&
+-                  !test_bit(R5_UPTODATE, &dev->flags) &&
+-                  (dev->toread || (dev->towrite &&
+-                   !test_bit(R5_OVERWRITE, &dev->flags)) ||
+-                   s->syncing || s->expanding ||
+-                   (s->failed >= 1 &&
+-                    (sh->dev[r6s->failed_num[0]].toread ||
+-                     s->to_write)) ||
+-                   (s->failed >= 2 &&
+-                    (sh->dev[r6s->failed_num[1]].toread ||
+-                     s->to_write)))) {
+-                      /* we would like to get this block, possibly
+-                       * by computing it, but we might not be able to
+-                       */
+-                      if (s->uptodate == disks-1) {
+-                              pr_debug("Computing stripe %llu block %d\n",
+-                                     (unsigned long long)sh->sector, i);
+-                              compute_block_1(sh, i, 0);
+-                              s->uptodate++;
+-                      } else if ( s->uptodate == disks-2 && s->failed >= 2 ) {
+-                              /* Computing 2-failure is *very* expensive; only
+-                               * do it if failed >= 2
++      /* might be able to return some write requests if the parity block
++       * is safe, or on a failed drive
+                                */
+-                              int other;
+-                              for (other = disks; other--; ) {
+-                                      if (other == i)
+-                                              continue;
+-                                      if (!test_bit(R5_UPTODATE,
+-                                            &sh->dev[other].flags))
+-                                              break;
+-                      }
+-                              BUG_ON(other < 0);
+-                              pr_debug("Computing stripe %llu blocks %d,%d\n",
+-                                     (unsigned long long)sh->sector,
+-                                     i, other);
+-                              compute_block_2(sh, i, other);
+-                              s->uptodate += 2;
+-                      } else if (test_bit(R5_Insync, &dev->flags)) {
+-                              set_bit(R5_LOCKED, &dev->flags);
+-                              set_bit(R5_Wantread, &dev->flags);
+-                              s->locked++;
+-                              pr_debug("Reading block %d (sync=%d)\n",
+-                                      i, s->syncing);
+-              }
+-      }
+-      }
+-      set_bit(STRIPE_HANDLE, &sh->state);
+-}
+-
+-
+-/* handle_completed_write_requests
+- * any written block on an uptodate or failed drive can be returned.
++      dev = &sh->dev[sh->pd_idx];
++      if ( written &&
++           ( (test_bit(R5_Insync, &dev->flags) && !test_bit(R5_LOCKED, &dev->flags) &&
++              test_bit(R5_UPTODATE, &dev->flags))
++             || (failed == 1 && failed_num == sh->pd_idx))
++          ) {
++          /* any written block on an uptodate or failed drive can be returned.
+            * Note that if we 'wrote' to a failed drive, it will be UPTODATE, but 
+            * never LOCKED, so we don't need to test 'failed' directly.
+            */
+-static void handle_completed_write_requests(raid5_conf_t *conf,
+-      struct stripe_head *sh, int disks, struct bio **return_bi)
+-{
+-      int i;
+-      struct r5dev *dev;
+-
+-      for (i = disks; i--; )
++          for (i=disks; i--; )
+               if (sh->dev[i].written) {
+                   dev = &sh->dev[i];
+                   if (!test_bit(R5_LOCKED, &dev->flags) &&
+-                              test_bit(R5_UPTODATE, &dev->flags)) {
++                       test_bit(R5_UPTODATE, &dev->flags) ) {
+                       /* We can return any write requests */
+                           struct bio *wbi, *wbi2;
+                           int bitmap_end = 0;
+-                              pr_debug("Return write for disc %d\n", i);
++                          PRINTK("Return write for disc %d\n", i);
+                           spin_lock_irq(&conf->device_lock);
+                           wbi = dev->written;
+                           dev->written = NULL;
+-                              while (wbi && wbi->bi_sector <
+-                                      dev->sector + STRIPE_SECTORS) {
++                          while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
+                                   wbi2 = r5_next_bio(wbi, dev->sector);
+                                   if (--wbi->bi_phys_segments == 0) {
+                                           md_write_end(conf->mddev);
+-                                              wbi->bi_next = *return_bi;
+-                                              *return_bi = wbi;
++                                          wbi->bi_next = return_bi;
++                                          return_bi = wbi;
+                                   }
+                                   wbi = wbi2;
+                           }
+@@ -2142,63 +1550,89 @@
+                                   bitmap_end = 1;
+                           spin_unlock_irq(&conf->device_lock);
+                           if (bitmap_end)
+-                                      bitmap_endwrite(conf->mddev->bitmap,
+-                                                      sh->sector,
++                                  bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+                                                   STRIPE_SECTORS,
+-                                       !test_bit(STRIPE_DEGRADED, &sh->state),
+-                                                      0);
++                                                  !test_bit(STRIPE_DEGRADED, &sh->state), 0);
++                  }
+                       }
+               }
+-}
  
--      spin_lock_irq(phba->host->host_lock);
--      if (phba->work_ha ||
--          phba->work_hba_events ||
--          (!list_empty(&phba->work_list)) ||
-+      spin_lock_irq(&phba->hbalock);
-+      list_for_each_entry(vport, &phba->port_list, listentry) {
-+              if (vport->work_port_events) {
-+                      rc = 1;
-+                      goto exit;
+-static void handle_issuing_new_write_requests5(raid5_conf_t *conf,
+-              struct stripe_head *sh, struct stripe_head_state *s, int disks)
+-{
+-      int rmw = 0, rcw = 0, i;
+-      for (i = disks; i--; ) {
++      /* Now we might consider reading some blocks, either to check/generate
++       * parity, or to satisfy requests
++       * or to load a block that is being partially written.
++       */
++      if (to_read || non_overwrite || (syncing && (uptodate < disks)) || expanding) {
++              for (i=disks; i--;) {
++                      dev = &sh->dev[i];
++                      if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
++                          (dev->toread ||
++                           (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
++                           syncing ||
++                           expanding ||
++                           (failed && (sh->dev[failed_num].toread ||
++                                       (sh->dev[failed_num].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num].flags))))
++                                  )
++                              ) {
++                              /* we would like to get this block, possibly
++                               * by computing it, but we might not be able to
++                               */
++                              if (uptodate == disks-1) {
++                                      PRINTK("Computing block %d\n", i);
++                                      compute_block(sh, i);
++                                      uptodate++;
++                              } else if (test_bit(R5_Insync, &dev->flags)) {
++                                      set_bit(R5_LOCKED, &dev->flags);
++                                      set_bit(R5_Wantread, &dev->flags);
++                                      locked++;
++                                      PRINTK("Reading block %d (sync=%d)\n", 
++                                              i, syncing);
++                              }
++                      }
 +              }
++              set_bit(STRIPE_HANDLE, &sh->state);
 +      }
 +
-+      if (phba->work_ha || (!list_empty(&phba->work_list)) ||
-           kthread_should_stop()) {
--              spin_unlock_irq(phba->host->host_lock);
--              return 1;
--      } else {
--              spin_unlock_irq(phba->host->host_lock);
--              return 0;
-+              rc = 1;
-+              goto exit;
-       }
-+
-+      pring = &phba->sli.ring[LPFC_ELS_RING];
-+      if (pring->flag & LPFC_DEFERRED_RING_EVENT)
-+              rc = 1;
-+exit:
-+      if (rc)
-+              phba->work_found++;
-+      else
-+              phba->work_found = 0;
-+
-+      spin_unlock_irq(&phba->hbalock);
-+      return rc;
- }
-+
- int
- lpfc_do_work(void *p)
- {
-@@ -324,11 +479,13 @@
-       set_user_nice(current, -20);
-       phba->work_wait = &work_waitq;
-+      phba->work_found = 0;
-       while (1) {
-               rc = wait_event_interruptible(work_waitq,
-                                               check_work_wait_done(phba));
-+
-               BUG_ON(rc);
-               if (kthread_should_stop())
-@@ -336,6 +493,17 @@
++      /* now to consider writing and what else, if anything should be read */
++      if (to_write) {
++              int rmw=0, rcw=0;
++              for (i=disks ; i--;) {
+                       /* would I have to read this buffer for read_modify_write */
+-              struct r5dev *dev = &sh->dev[i];
++                      dev = &sh->dev[i];
+                       if ((dev->towrite || i == sh->pd_idx) &&
+-                  !test_bit(R5_LOCKED, &dev->flags) &&
+-                  !(test_bit(R5_UPTODATE, &dev->flags) ||
+-                    test_bit(R5_Wantcompute, &dev->flags))) {
+-                      if (test_bit(R5_Insync, &dev->flags))
++                          (!test_bit(R5_LOCKED, &dev->flags) 
++                                  ) &&
++                          !test_bit(R5_UPTODATE, &dev->flags)) {
++                              if (test_bit(R5_Insync, &dev->flags)
++/*                                && !(!mddev->insync && i == sh->pd_idx) */
++                                      )
+                                       rmw++;
+-                      else
+-                              rmw += 2*disks;  /* cannot read it */
++                              else rmw += 2*disks;  /* cannot read it */
+                       }
+                       /* Would I have to read this buffer for reconstruct_write */
+                       if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
+-                  !test_bit(R5_LOCKED, &dev->flags) &&
+-                  !(test_bit(R5_UPTODATE, &dev->flags) ||
+-                  test_bit(R5_Wantcompute, &dev->flags))) {
++                          (!test_bit(R5_LOCKED, &dev->flags) 
++                                  ) &&
++                          !test_bit(R5_UPTODATE, &dev->flags)) {
+                               if (test_bit(R5_Insync, &dev->flags)) rcw++;
+-                      else
+-                              rcw += 2*disks;
++                              else rcw += 2*disks;
+                       }
+               }
+-      pr_debug("for sector %llu, rmw=%d rcw=%d\n",
++              PRINTK("for sector %llu, rmw=%d rcw=%d\n", 
+                       (unsigned long long)sh->sector, rmw, rcw);
+               set_bit(STRIPE_HANDLE, &sh->state);
+               if (rmw < rcw && rmw > 0)
+                       /* prefer read-modify-write, but need to get some data */
+-              for (i = disks; i--; ) {
+-                      struct r5dev *dev = &sh->dev[i];
++                      for (i=disks; i--;) {
++                              dev = &sh->dev[i];
+                               if ((dev->towrite || i == sh->pd_idx) &&
+-                          !test_bit(R5_LOCKED, &dev->flags) &&
+-                          !(test_bit(R5_UPTODATE, &dev->flags) ||
+-                          test_bit(R5_Wantcompute, &dev->flags)) &&
++                                  !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
+                                   test_bit(R5_Insync, &dev->flags)) {
+-                              if (
+-                                test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+-                                      pr_debug("Read_old block "
+-                                              "%d for r-m-w\n", i);
++                                      if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
++                                      {
++                                              PRINTK("Read_old block %d for r-m-w\n", i);
+                                               set_bit(R5_LOCKED, &dev->flags);
+                                               set_bit(R5_Wantread, &dev->flags);
+-                                      if (!test_and_set_bit(
+-                                              STRIPE_OP_IO, &sh->ops.pending))
+-                                              sh->ops.count++;
+-                                      s->locked++;
++                                              locked++;
+                                       } else {
+                                               set_bit(STRIPE_DELAYED, &sh->state);
+                                               set_bit(STRIPE_HANDLE, &sh->state);
+@@ -2207,367 +1641,165 @@
+                       }
+               if (rcw <= rmw && rcw > 0)
+                       /* want reconstruct write, but need to get some data */
+-              for (i = disks; i--; ) {
+-                      struct r5dev *dev = &sh->dev[i];
+-                      if (!test_bit(R5_OVERWRITE, &dev->flags) &&
+-                          i != sh->pd_idx &&
+-                          !test_bit(R5_LOCKED, &dev->flags) &&
+-                          !(test_bit(R5_UPTODATE, &dev->flags) ||
+-                          test_bit(R5_Wantcompute, &dev->flags)) &&
+-                                  test_bit(R5_Insync, &dev->flags)) {
+-                              if (
+-                                test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+-                                      pr_debug("Read_old block "
+-                                              "%d for Reconstruct\n", i);
+-                                              set_bit(R5_LOCKED, &dev->flags);
+-                                              set_bit(R5_Wantread, &dev->flags);
+-                                      if (!test_and_set_bit(
+-                                              STRIPE_OP_IO, &sh->ops.pending))
+-                                              sh->ops.count++;
+-                                      s->locked++;
+-                              } else {
+-                                      set_bit(STRIPE_DELAYED, &sh->state);
+-                                      set_bit(STRIPE_HANDLE, &sh->state);
+-                              }
+-                      }
+-              }
+-      /* now if nothing is locked, and if we have enough data,
+-       * we can start a write request
+-       */
+-      /* since handle_stripe can be called at any time we need to handle the
+-       * case where a compute block operation has been submitted and then a
+-       * subsequent call wants to start a write request.  raid5_run_ops only
+-       * handles the case where compute block and postxor are requested
+-       * simultaneously.  If this is not the case then new writes need to be
+-       * held off until the compute completes.
+-       */
+-      if ((s->req_compute ||
+-          !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) &&
+-              (s->locked == 0 && (rcw == 0 || rmw == 0) &&
+-              !test_bit(STRIPE_BIT_DELAY, &sh->state)))
+-              s->locked += handle_write_operations5(sh, rcw == 0, 0);
+-}
+-
+-static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
+-              struct stripe_head *sh, struct stripe_head_state *s,
+-              struct r6_state *r6s, int disks)
+-{
+-      int rcw = 0, must_compute = 0, pd_idx = sh->pd_idx, i;
+-      int qd_idx = r6s->qd_idx;
+-      for (i = disks; i--; ) {
+-              struct r5dev *dev = &sh->dev[i];
+-              /* Would I have to read this buffer for reconstruct_write */
+-              if (!test_bit(R5_OVERWRITE, &dev->flags)
+-                  && i != pd_idx && i != qd_idx
+-                  && (!test_bit(R5_LOCKED, &dev->flags)
+-                          ) &&
+-                  !test_bit(R5_UPTODATE, &dev->flags)) {
+-                      if (test_bit(R5_Insync, &dev->flags)) rcw++;
+-                      else {
+-                              pr_debug("raid6: must_compute: "
+-                                      "disk %d flags=%#lx\n", i, dev->flags);
+-                              must_compute++;
+-                      }
+-              }
+-      }
+-      pr_debug("for sector %llu, rcw=%d, must_compute=%d\n",
+-             (unsigned long long)sh->sector, rcw, must_compute);
+-      set_bit(STRIPE_HANDLE, &sh->state);
+-
+-      if (rcw > 0)
+-              /* want reconstruct write, but need to get some data */
+-              for (i = disks; i--; ) {
+-                      struct r5dev *dev = &sh->dev[i];
+-                      if (!test_bit(R5_OVERWRITE, &dev->flags)
+-                          && !(s->failed == 0 && (i == pd_idx || i == qd_idx))
+-                          && !test_bit(R5_LOCKED, &dev->flags) &&
+-                          !test_bit(R5_UPTODATE, &dev->flags) &&
++                      for (i=disks; i--;) {
++                              dev = &sh->dev[i];
++                              if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
++                                  !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
+                           test_bit(R5_Insync, &dev->flags)) {
+-                              if (
+-                                test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+-                                      pr_debug("Read_old stripe %llu "
+-                                              "block %d for Reconstruct\n",
+-                                           (unsigned long long)sh->sector, i);
++                                      if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
++                                      {
++                                              PRINTK("Read_old block %d for Reconstruct\n", i);
+                                       set_bit(R5_LOCKED, &dev->flags);
+                                       set_bit(R5_Wantread, &dev->flags);
+-                                      s->locked++;
++                                              locked++;
+                                       } else {
+-                                      pr_debug("Request delayed stripe %llu "
+-                                              "block %d for Reconstruct\n",
+-                                           (unsigned long long)sh->sector, i);
+                                               set_bit(STRIPE_DELAYED, &sh->state);
+                                               set_bit(STRIPE_HANDLE, &sh->state);
+                                       }
+                               }
+                       }
+-      /* now if nothing is locked, and if we have enough data, we can start a
+-       * write request
+-       */
+-      if (s->locked == 0 && rcw == 0 &&
++              /* now if nothing is locked, and if we have enough data, we can start a write request */
++              if (locked == 0 && (rcw == 0 ||rmw == 0) &&
+                   !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
+-              if (must_compute > 0) {
+-                      /* We have failed blocks and need to compute them */
+-                      switch (s->failed) {
+-                      case 0:
+-                              BUG();
+-                      case 1:
+-                              compute_block_1(sh, r6s->failed_num[0], 0);
+-                              break;
+-                      case 2:
+-                              compute_block_2(sh, r6s->failed_num[0],
+-                                              r6s->failed_num[1]);
+-                              break;
+-                      default: /* This request should have been failed? */
+-                              BUG();
+-                      }
+-              }
+-
+-              pr_debug("Computing parity for stripe %llu\n",
+-                      (unsigned long long)sh->sector);
+-              compute_parity6(sh, RECONSTRUCT_WRITE);
++                      PRINTK("Computing parity...\n");
++                      compute_parity5(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
+                       /* now every locked buffer is ready to be written */
+-              for (i = disks; i--; )
++                      for (i=disks; i--;)
+                               if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
+-                              pr_debug("Writing stripe %llu block %d\n",
+-                                     (unsigned long long)sh->sector, i);
+-                              s->locked++;
++                                      PRINTK("Writing block %d\n", i);
++                                      locked++;
+                                       set_bit(R5_Wantwrite, &sh->dev[i].flags);
+-                              }
+-              /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
++                                      if (!test_bit(R5_Insync, &sh->dev[i].flags)
++                                          || (i==sh->pd_idx && failed == 0))
+               set_bit(STRIPE_INSYNC, &sh->state);
+-
++                              }
+                       if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+                               atomic_dec(&conf->preread_active_stripes);
+-                      if (atomic_read(&conf->preread_active_stripes) <
+-                          IO_THRESHOLD)
++                              if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
+                                       md_wakeup_thread(conf->mddev->thread);
+                       }
+               }
+-}
++      }
  
-               lpfc_work_done(phba);
+-static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
+-                              struct stripe_head_state *s, int disks)
+-{
+-              set_bit(STRIPE_HANDLE, &sh->state);
+-      /* Take one of the following actions:
+-       * 1/ start a check parity operation if (uptodate == disks)
+-       * 2/ finish a check parity operation and act on the result
+-       * 3/ skip to the writeback section if we previously
+-       *    initiated a recovery operation
+-       */
+-      if (s->failed == 0 &&
+-          !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
+-              if (!test_and_set_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
+-                      BUG_ON(s->uptodate != disks);
+-                      clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
+-                      sh->ops.count++;
+-                      s->uptodate--;
+-              } else if (
+-                     test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) {
+-                      clear_bit(STRIPE_OP_CHECK, &sh->ops.ack);
+-                      clear_bit(STRIPE_OP_CHECK, &sh->ops.pending);
+-
+-                      if (sh->ops.zero_sum_result == 0)
+-                              /* parity is correct (on disc,
+-                               * not in buffer any more)
++      /* maybe we need to check and possibly fix the parity for this stripe
++       * Any reads will already have been scheduled, so we just see if enough data
++       * is available
+                                */
++      if (syncing && locked == 0 &&
++          !test_bit(STRIPE_INSYNC, &sh->state)) {
++              set_bit(STRIPE_HANDLE, &sh->state);
++              if (failed == 0) {
++                      BUG_ON(uptodate != disks);
++                      compute_parity5(sh, CHECK_PARITY);
++                      uptodate--;
++                      if (page_is_zero(sh->dev[sh->pd_idx].page)) {
++                              /* parity is correct (on disc, not in buffer any more) */
+                               set_bit(STRIPE_INSYNC, &sh->state);
+-                      else {
+-                              conf->mddev->resync_mismatches +=
+-                                      STRIPE_SECTORS;
+-                              if (test_bit(
+-                                   MD_RECOVERY_CHECK, &conf->mddev->recovery))
++                      } else {
++                              conf->mddev->resync_mismatches += STRIPE_SECTORS;
++                              if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+                                       /* don't try to repair!! */
+                                       set_bit(STRIPE_INSYNC, &sh->state);
+                               else {
+-                                      set_bit(STRIPE_OP_COMPUTE_BLK,
+-                                              &sh->ops.pending);
+-                                      set_bit(STRIPE_OP_MOD_REPAIR_PD,
+-                                              &sh->ops.pending);
+-                                      set_bit(R5_Wantcompute,
+-                                              &sh->dev[sh->pd_idx].flags);
+-                                      sh->ops.target = sh->pd_idx;
+-                                      sh->ops.count++;
+-                                      s->uptodate++;
++                                      compute_block(sh, sh->pd_idx);
++                                      uptodate++;
+                               }
+                       }
+                               }
+-                      }
+-
+-      /* check if we can clear a parity disk reconstruct */
+-      if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
+-              test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
+-
+-              clear_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending);
+-              clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+-              clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
+-              clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+-              }
+-
+-      /* Wait for check parity and compute block operations to complete
+-       * before write-back
+-       */
+-      if (!test_bit(STRIPE_INSYNC, &sh->state) &&
+-              !test_bit(STRIPE_OP_CHECK, &sh->ops.pending) &&
+-              !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) {
+-              struct r5dev *dev;
++              if (!test_bit(STRIPE_INSYNC, &sh->state)) {
+                       /* either failed parity check, or recovery is happening */
+-              if (s->failed == 0)
+-                      s->failed_num = sh->pd_idx;
+-              dev = &sh->dev[s->failed_num];
++                      if (failed==0)
++                              failed_num = sh->pd_idx;
++                      dev = &sh->dev[failed_num];
+                       BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
+-              BUG_ON(s->uptodate != disks);
++                      BUG_ON(uptodate != disks);
  
-+              /* If there is alot of slow ring work, like during link up
-+               * check_work_wait_done() may cause this thread to not give
-+               * up the CPU for very long periods of time. This may cause
-+               * soft lockups or other problems. To avoid these situations
-+               * give up the CPU here after LPFC_MAX_WORKER_ITERATION
-+               * consecutive iterations.
-+               */
-+              if (phba->work_found >= LPFC_MAX_WORKER_ITERATION) {
-+                      phba->work_found = 0;
-+                      schedule();
-+              }
+                       set_bit(R5_LOCKED, &dev->flags);
+                       set_bit(R5_Wantwrite, &dev->flags);
+-              if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+-                      sh->ops.count++;
+-
+                       clear_bit(STRIPE_DEGRADED, &sh->state);
+-              s->locked++;
++                      locked++;
+                       set_bit(STRIPE_INSYNC, &sh->state);
+               }
+-}
+-
+-
+-static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
+-                              struct stripe_head_state *s,
+-                              struct r6_state *r6s, struct page *tmp_page,
+-                              int disks)
+-{
+-      int update_p = 0, update_q = 0;
+-      struct r5dev *dev;
+-      int pd_idx = sh->pd_idx;
+-      int qd_idx = r6s->qd_idx;
+-
+-      set_bit(STRIPE_HANDLE, &sh->state);
+-
+-      BUG_ON(s->failed > 2);
+-      BUG_ON(s->uptodate < disks);
+-      /* Want to check and possibly repair P and Q.
+-       * However there could be one 'failed' device, in which
+-       * case we can only check one of them, possibly using the
+-       * other to generate missing data
+-       */
+-
+-      /* If !tmp_page, we cannot do the calculations,
+-       * but as we have set STRIPE_HANDLE, we will soon be called
+-       * by stripe_handle with a tmp_page - just wait until then.
+-       */
+-      if (tmp_page) {
+-              if (s->failed == r6s->q_failed) {
+-                      /* The only possible failed device holds 'Q', so it
+-                       * makes sense to check P (If anything else were failed,
+-                       * we would have used P to recreate it).
+-                       */
+-                      compute_block_1(sh, pd_idx, 1);
+-                      if (!page_is_zero(sh->dev[pd_idx].page)) {
+-                              compute_block_1(sh, pd_idx, 0);
+-                              update_p = 1;
+-                      }
+-      }
+-              if (!r6s->q_failed && s->failed < 2) {
+-                      /* q is not failed, and we didn't use it to generate
+-                       * anything, so it makes sense to check it
+-                       */
+-                      memcpy(page_address(tmp_page),
+-                             page_address(sh->dev[qd_idx].page),
+-                             STRIPE_SIZE);
+-                      compute_parity6(sh, UPDATE_PARITY);
+-                      if (memcmp(page_address(tmp_page),
+-                                 page_address(sh->dev[qd_idx].page),
+-                                 STRIPE_SIZE) != 0) {
+-                              clear_bit(STRIPE_INSYNC, &sh->state);
+-                              update_q = 1;
+-                      }
+               }
+-              if (update_p || update_q) {
+-                      conf->mddev->resync_mismatches += STRIPE_SECTORS;
+-                      if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+-                              /* don't try to repair!! */
+-                              update_p = update_q = 0;
++      if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
++              md_done_sync(conf->mddev, STRIPE_SECTORS,1);
++              clear_bit(STRIPE_SYNCING, &sh->state);
        }
-       phba->work_wait = NULL;
-       return 0;
-@@ -347,16 +515,17 @@
-  * embedding it in the IOCB.
-  */
- int
--lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
-+lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2,
-                     uint32_t evt)
- {
-       struct lpfc_work_evt  *evtp;
-+      unsigned long flags;
  
-       /*
-        * All Mailbox completions and LPFC_ELS_RING rcv ring IOCB events will
-        * be queued to worker thread for processing
+-              /* now write out any block on a failed drive,
+-               * or P or Q if they need it
++      /* If the failed drive is just a ReadError, then we might need to progress
++       * the repair/check process
         */
--      evtp = kmalloc(sizeof(struct lpfc_work_evt), GFP_KERNEL);
-+      evtp = kmalloc(sizeof(struct lpfc_work_evt), GFP_ATOMIC);
-       if (!evtp)
-               return 0;
-@@ -364,136 +533,210 @@
-       evtp->evt_arg2  = arg2;
-       evtp->evt       = evt;
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irqsave(&phba->hbalock, flags);
-       list_add_tail(&evtp->evt_listp, &phba->work_list);
-       if (phba->work_wait)
--              wake_up(phba->work_wait);
--      spin_unlock_irq(phba->host->host_lock);
-+              lpfc_worker_wake_up(phba);
-+      spin_unlock_irqrestore(&phba->hbalock, flags);
-       return 1;
- }
--int
--lpfc_linkdown(struct lpfc_hba *phba)
-+void
-+lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
- {
--      struct lpfc_sli       *psli;
-+      struct lpfc_hba  *phba = vport->phba;
-       struct lpfc_nodelist  *ndlp, *next_ndlp;
--      LPFC_MBOXQ_t          *mb;
-       int                   rc;
--      psli = &phba->sli;
--      /* sysfs or selective reset may call this routine to clean up */
--      if (phba->hba_state >= LPFC_LINK_DOWN) {
--              if (phba->hba_state == LPFC_LINK_DOWN)
--                      return 0;
-+      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
-+              if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
-+                      continue;
-+
-+              if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN)
-+                      lpfc_unreg_rpi(vport, ndlp);
--              spin_lock_irq(phba->host->host_lock);
--              phba->hba_state = LPFC_LINK_DOWN;
--              spin_unlock_irq(phba->host->host_lock);
-+              /* Leave Fabric nodes alone on link down */
-+              if (!remove && ndlp->nlp_type & NLP_FABRIC)
-+                      continue;
-+              rc = lpfc_disc_state_machine(vport, ndlp, NULL,
-+                                           remove
-+                                           ? NLP_EVT_DEVICE_RM
-+                                           : NLP_EVT_DEVICE_RECOVERY);
-+      }
-+      if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) {
-+              lpfc_mbx_unreg_vpi(vport);
-+              vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
-       }
-+}
-+
-+static void
-+lpfc_linkdown_port(struct lpfc_vport *vport)
-+{
-+      struct lpfc_nodelist *ndlp, *next_ndlp;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
--      fc_host_post_event(phba->host, fc_get_event_number(),
--                      FCH_EVT_LINKDOWN, 0);
-+      fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0);
--      /* Clean up any firmware default rpi's */
--      if ((mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
--              lpfc_unreg_did(phba, 0xffffffff, mb);
--              mb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
--              if (lpfc_sli_issue_mbox(phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB))
--                  == MBX_NOT_FINISHED) {
--                      mempool_free( mb, phba->mbox_mem_pool);
+-
+-              if (s->failed == 2) {
+-                      dev = &sh->dev[r6s->failed_num[1]];
+-                      s->locked++;
+-                      set_bit(R5_LOCKED, &dev->flags);
++      if (failed == 1 && ! conf->mddev->ro &&
++          test_bit(R5_ReadError, &sh->dev[failed_num].flags)
++          && !test_bit(R5_LOCKED, &sh->dev[failed_num].flags)
++          && test_bit(R5_UPTODATE, &sh->dev[failed_num].flags)
++              ) {
++              dev = &sh->dev[failed_num];
++              if (!test_bit(R5_ReWrite, &dev->flags)) {
+                       set_bit(R5_Wantwrite, &dev->flags);
 -              }
--      }
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "Link Down:       state:x%x rtry:x%x flg:x%x",
-+              vport->port_state, vport->fc_ns_retry, vport->fc_flag);
+-              if (s->failed >= 1) {
+-                      dev = &sh->dev[r6s->failed_num[0]];
+-                      s->locked++;
++                      set_bit(R5_ReWrite, &dev->flags);
+                       set_bit(R5_LOCKED, &dev->flags);
+-                      set_bit(R5_Wantwrite, &dev->flags);
+-              }
+-
+-              if (update_p) {
+-                      dev = &sh->dev[pd_idx];
+-                      s->locked++;
++                      locked++;
++              } else {
++                      /* let's read it back */
++                      set_bit(R5_Wantread, &dev->flags);
+                       set_bit(R5_LOCKED, &dev->flags);
+-                      set_bit(R5_Wantwrite, &dev->flags);
++                      locked++;
+               }
+-              if (update_q) {
+-                      dev = &sh->dev[qd_idx];
+-                      s->locked++;
+-                      set_bit(R5_LOCKED, &dev->flags);
+-                      set_bit(R5_Wantwrite, &dev->flags);
+       }
+-              clear_bit(STRIPE_DEGRADED, &sh->state);
  
-       /* Cleanup any outstanding RSCN activity */
--      lpfc_els_flush_rscn(phba);
-+      lpfc_els_flush_rscn(vport);
+-              set_bit(STRIPE_INSYNC, &sh->state);
++      if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
++              /* Need to write out all blocks after computing parity */
++              sh->disks = conf->raid_disks;
++              sh->pd_idx = stripe_to_pdidx(sh->sector, conf, conf->raid_disks);
++              compute_parity5(sh, RECONSTRUCT_WRITE);
++              for (i= conf->raid_disks; i--;) {
++                      set_bit(R5_LOCKED, &sh->dev[i].flags);
++                      locked++;
++                      set_bit(R5_Wantwrite, &sh->dev[i].flags);
++              }
++              clear_bit(STRIPE_EXPANDING, &sh->state);
++      } else if (expanded) {
++              clear_bit(STRIPE_EXPAND_READY, &sh->state);
++              atomic_dec(&conf->reshape_stripes);
++              wake_up(&conf->wait_for_overlap);
++              md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
+       }
+-}
+-
+-static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
+-                              struct r6_state *r6s)
+-{
+-      int i;
  
-       /* Cleanup any outstanding ELS commands */
--      lpfc_els_flush_cmd(phba);
-+      lpfc_els_flush_cmd(vport);
-+
-+      lpfc_cleanup_rpis(vport, 0);
++      if (expanding && locked == 0) {
+               /* We have read all the blocks in this stripe and now we need to
+                * copy some of them into a target stripe for expand.
+                */
+-      struct dma_async_tx_descriptor *tx = NULL;
+               clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+-      for (i = 0; i < sh->disks; i++)
+-              if (i != sh->pd_idx && (r6s && i != r6s->qd_idx)) {
++              for (i=0; i< sh->disks; i++)
++                      if (i != sh->pd_idx) {
+                               int dd_idx, pd_idx, j;
+                               struct stripe_head *sh2;
  
--      /*
--       * Issue a LINK DOWN event to all nodes.
--       */
--      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
-                               /* free any ndlp's on unused list */
-+      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
-+                              /* free any ndlp's in unused state */
-               if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
--                      lpfc_drop_node(phba, ndlp);
--              else            /* otherwise, force node recovery. */
--                      rc = lpfc_disc_state_machine(phba, ndlp, NULL,
--                                                   NLP_EVT_DEVICE_RECOVERY);
-+                      lpfc_drop_node(vport, ndlp);
-+
-+      /* Turn off discovery timer if its running */
-+      lpfc_can_disctmo(vport);
-+}
-+
-+int
-+lpfc_linkdown(struct lpfc_hba *phba)
-+{
-+      struct lpfc_vport *vport = phba->pport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_vport *port_iterator;
-+      LPFC_MBOXQ_t          *mb;
-+
-+      if (phba->link_state == LPFC_LINK_DOWN) {
-+              return 0;
-+      }
-+      spin_lock_irq(&phba->hbalock);
-+      if (phba->link_state > LPFC_LINK_DOWN) {
-+              phba->link_state = LPFC_LINK_DOWN;
-+              phba->pport->fc_flag &= ~FC_LBIT;
+                               sector_t bn = compute_blocknr(sh, i);
+                               sector_t s = raid5_compute_sector(bn, conf->raid_disks,
+-                                              conf->raid_disks -
+-                                              conf->max_degraded, &dd_idx,
+-                                              &pd_idx, conf);
+-                      sh2 = get_active_stripe(conf, s, conf->raid_disks,
+-                                              pd_idx, 1);
++                                                                conf->raid_disks-1,
++                                                                &dd_idx, &pd_idx, conf);
++                              sh2 = get_active_stripe(conf, s, conf->raid_disks, pd_idx, 1);
+                               if (sh2 == NULL)
+                                       /* so far only the early blocks of this stripe
+                                        * have been requested.  When later blocks
+                                        * get requested, we will try again
+                                        */
+                                       continue;
+-                      if (!test_bit(STRIPE_EXPANDING, &sh2->state) ||
++                              if(!test_bit(STRIPE_EXPANDING, &sh2->state) ||
+                                  test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) {
+                                       /* must have already done this block */
+                                       release_stripe(sh2);
+                                       continue;
+                               }
+-
+-                      /* place all the copies on one channel */
+-                      tx = async_memcpy(sh2->dev[dd_idx].page,
+-                              sh->dev[i].page, 0, 0, STRIPE_SIZE,
+-                              ASYNC_TX_DEP_ACK, tx, NULL, NULL);
+-
++                              memcpy(page_address(sh2->dev[dd_idx].page),
++                                     page_address(sh->dev[i].page),
++                                     STRIPE_SIZE);
+                               set_bit(R5_Expanded, &sh2->dev[dd_idx].flags);
+                               set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags);
+-                      for (j = 0; j < conf->raid_disks; j++)
++                              for (j=0; j<conf->raid_disks; j++)
+                                       if (j != sh2->pd_idx &&
+-                                  (r6s && j != r6s->qd_idx) &&
+                                           !test_bit(R5_Expanded, &sh2->dev[j].flags))
+                                               break;
+                               if (j == conf->raid_disks) {
+@@ -2575,91 +1807,153 @@
+                                       set_bit(STRIPE_HANDLE, &sh2->state);
+                               }
+                               release_stripe(sh2);
++                      }
 +      }
-+      spin_unlock_irq(&phba->hbalock);
 +
-+      list_for_each_entry(port_iterator, &phba->port_list, listentry) {
++      spin_unlock(&sh->lock);
 +
-+                              /* Issue a LINK DOWN event to all nodes */
-+              lpfc_linkdown_port(port_iterator);
-+      }
++      while ((bi=return_bi)) {
++              int bytes = bi->bi_size;
 +
-+      /* Clean up any firmware default rpi's */
-+      mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (mb) {
-+              lpfc_unreg_did(phba, 0xffff, 0xffffffff, mb);
-+              mb->vport = vport;
-+              mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-+              if (lpfc_sli_issue_mbox(phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB))
-+                  == MBX_NOT_FINISHED) {
-+                      mempool_free(mb, phba->mbox_mem_pool);
-+              }
-       }
++              return_bi = bi->bi_next;
++              bi->bi_next = NULL;
++              bi->bi_size = 0;
++              bi->bi_end_io(bi, bytes,
++                            test_bit(BIO_UPTODATE, &bi->bi_flags)
++                              ? 0 : -EIO);
++      }
++      for (i=disks; i-- ;) {
++              int rw;
++              struct bio *bi;
++              mdk_rdev_t *rdev;
++              if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
++                      rw = WRITE;
++              else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
++                      rw = READ;
++              else
++                      continue;
++ 
++              bi = &sh->dev[i].req;
++ 
++              bi->bi_rw = rw;
++              if (rw == WRITE)
++                      bi->bi_end_io = raid5_end_write_request;
++              else
++                      bi->bi_end_io = raid5_end_read_request;
++ 
++              rcu_read_lock();
++              rdev = rcu_dereference(conf->disks[i].rdev);
++              if (rdev && test_bit(Faulty, &rdev->flags))
++                      rdev = NULL;
++              if (rdev)
++                      atomic_inc(&rdev->nr_pending);
++              rcu_read_unlock();
++ 
++              if (rdev) {
++                      if (syncing || expanding || expanded)
++                              md_sync_acct(rdev->bdev, STRIPE_SECTORS);
  
-       /* Setup myDID for link up if we are in pt2pt mode */
--      if (phba->fc_flag & FC_PT2PT) {
--              phba->fc_myDID = 0;
--              if ((mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
-+      if (phba->pport->fc_flag & FC_PT2PT) {
-+              phba->pport->fc_myDID = 0;
-+              mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+              if (mb) {
-                       lpfc_config_link(phba, mb);
--                      mb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
--                      if (lpfc_sli_issue_mbox
--                          (phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB))
-+                      mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-+                      mb->vport = vport;
-+                      if (lpfc_sli_issue_mbox(phba, mb,
-+                                              (MBX_NOWAIT | MBX_STOP_IOCB))
-                           == MBX_NOT_FINISHED) {
--                              mempool_free( mb, phba->mbox_mem_pool);
-+                              mempool_free(mb, phba->mbox_mem_pool);
-                       }
+-                      /* done submitting copies, wait for them to complete */
+-                      if (i + 1 >= sh->disks) {
+-                              async_tx_ack(tx);
+-                              dma_wait_for_async_tx(tx);
++                      bi->bi_bdev = rdev->bdev;
++                      PRINTK("for %llu schedule op %ld on disc %d\n",
++                              (unsigned long long)sh->sector, bi->bi_rw, i);
++                      atomic_inc(&sh->count);
++                      bi->bi_sector = sh->sector + rdev->data_offset;
++                      bi->bi_flags = 1 << BIO_UPTODATE;
++                      bi->bi_vcnt = 1;        
++                      bi->bi_max_vecs = 1;
++                      bi->bi_idx = 0;
++                      bi->bi_io_vec = &sh->dev[i].vec;
++                      bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
++                      bi->bi_io_vec[0].bv_offset = 0;
++                      bi->bi_size = STRIPE_SIZE;
++                      bi->bi_next = NULL;
++                      if (rw == WRITE &&
++                          test_bit(R5_ReWrite, &sh->dev[i].flags))
++                              atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
++                      generic_make_request(bi);
++              } else {
++                      if (rw == WRITE)
++                              set_bit(STRIPE_DEGRADED, &sh->state);
++                      PRINTK("skip op %ld on disc %d for sector %llu\n",
++                              bi->bi_rw, i, (unsigned long long)sh->sector);
++                      clear_bit(R5_LOCKED, &sh->dev[i].flags);
++                      set_bit(STRIPE_HANDLE, &sh->state);
                }
--              spin_lock_irq(phba->host->host_lock);
--              phba->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI);
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-+              phba->pport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI);
-+              spin_unlock_irq(shost->host_lock);
        }
--      spin_lock_irq(phba->host->host_lock);
--      phba->fc_flag &= ~FC_LBIT;
--      spin_unlock_irq(phba->host->host_lock);
--
--      /* Turn off discovery timer if its running */
--      lpfc_can_disctmo(phba);
--      /* Must process IOCBs on all rings to handle ABORTed I/Os */
-       return 0;
  }
  
--static int
--lpfc_linkup(struct lpfc_hba *phba)
-+static void
-+lpfc_linkup_cleanup_nodes(struct lpfc_vport *vport)
- {
--      struct lpfc_nodelist *ndlp, *next_ndlp;
--
--      fc_host_post_event(phba->host, fc_get_event_number(),
--                      FCH_EVT_LINKUP, 0);
+-/*
+- * handle_stripe - do things to a stripe.
+- *
+- * We lock the stripe and then examine the state of various bits
+- * to see what needs to be done.
+- * Possible results:
+- *    return some read request which now have data
+- *    return some write requests which are safely on disc
+- *    schedule a read on some buffers
+- *    schedule a write of some buffers
+- *    return confirmation of parity correctness
+- *
+- * buffers are taken off read_list or write_list, and bh_cache buffers
+- * get BH_Lock set before the stripe lock is released.
+- *
+- */
 -
--      spin_lock_irq(phba->host->host_lock);
--      phba->hba_state = LPFC_LINK_UP;
--      phba->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY |
--                         FC_RSCN_MODE | FC_NLP_MORE | FC_RSCN_DISCOVERY);
--      phba->fc_flag |= FC_NDISC_ACTIVE;
--      phba->fc_ns_retry = 0;
--      spin_unlock_irq(phba->host->host_lock);
-+      struct lpfc_nodelist *ndlp;
-+      list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
-+              if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
-+                      continue;
--      if (phba->fc_flag & FC_LBIT) {
--              list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
--                      if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) {
-                               if (ndlp->nlp_type & NLP_FABRIC) {
--                                      /*
--                                       * On Linkup its safe to clean up the
--                                       * ndlp from Fabric connections.
-+                              /* On Linkup its safe to clean up the ndlp
-+                               * from Fabric connections.
-                                        */
--                                      lpfc_nlp_set_state(phba, ndlp,
--                                                         NLP_STE_UNUSED_NODE);
-+                      if (ndlp->nlp_DID != Fabric_DID)
-+                              lpfc_unreg_rpi(vport, ndlp);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-                               } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
--                                      /*
--                                       * Fail outstanding IO now since
--                                       * device is marked for PLOGI.
-+                              /* Fail outstanding IO now since device is
-+                               * marked for PLOGI.
-                                        */
--                                      lpfc_unreg_rpi(phba, ndlp);
--                              }
--                      }
-+                      lpfc_unreg_rpi(vport, ndlp);
-               }
-       }
-+}
--      /* free any ndlp's on unused list */
--      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
--                               nlp_listp) {
-+static void
-+lpfc_linkup_port(struct lpfc_vport *vport)
-+{
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_nodelist *ndlp, *next_ndlp;
-+      struct lpfc_hba  *phba = vport->phba;
-+
-+      if ((vport->load_flag & FC_UNLOADING) != 0)
-+              return;
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "Link Up:         top:x%x speed:x%x flg:x%x",
-+              phba->fc_topology, phba->fc_linkspeed, phba->link_flag);
-+
-+      /* If NPIV is not enabled, only bring the physical port up */
-+      if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
-+              (vport != phba->pport))
-+              return;
-+
-+      fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKUP, 0);
-+
-+      spin_lock_irq(shost->host_lock);
-+      vport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY |
-+                          FC_RSCN_MODE | FC_NLP_MORE | FC_RSCN_DISCOVERY);
-+      vport->fc_flag |= FC_NDISC_ACTIVE;
-+      vport->fc_ns_retry = 0;
-+      spin_unlock_irq(shost->host_lock);
-+
-+      if (vport->fc_flag & FC_LBIT)
-+              lpfc_linkup_cleanup_nodes(vport);
-+
-+                              /* free any ndlp's in unused state */
-+      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
-+                               nlp_listp)
-               if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
--                      lpfc_drop_node(phba, ndlp);
-+                      lpfc_drop_node(vport, ndlp);
-+}
-+
-+static int
-+lpfc_linkup(struct lpfc_hba *phba)
-+{
-+      struct lpfc_vport *vport;
-+
-+      phba->link_state = LPFC_LINK_UP;
-+
-+      /* Unblock fabric iocbs if they are blocked */
-+      clear_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
-+      del_timer_sync(&phba->fabric_block_timer);
-+
-+      list_for_each_entry(vport, &phba->port_list, listentry) {
-+              lpfc_linkup_port(vport);
-       }
-+      if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
-+              lpfc_issue_clear_la(phba, phba->pport);
-       return 0;
- }
-@@ -505,14 +748,14 @@
-  * handed off to the SLI layer.
-  */
- void
--lpfc_mbx_cmpl_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
-+lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+-static void handle_stripe5(struct stripe_head *sh)
++static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
  {
--      struct lpfc_sli *psli;
--      MAILBOX_t *mb;
-+      struct lpfc_vport *vport = pmb->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_sli   *psli = &phba->sli;
-+      MAILBOX_t *mb = &pmb->mb;
-       uint32_t control;
+-      raid5_conf_t *conf = sh->raid_conf;
+-      int disks = sh->disks, i;
+-      struct bio *return_bi = NULL, *bi;
+-      struct stripe_head_state s;
+-      struct r5dev *dev;
+-      unsigned long pending = 0;
++      raid6_conf_t *conf = sh->raid_conf;
++      int disks = sh->disks;
++      struct bio *return_bi= NULL;
++      struct bio *bi;
++      int i;
++      int syncing, expanding, expanded;
++      int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
++      int non_overwrite = 0;
++      int failed_num[2] = {0, 0};
++      struct r5dev *dev, *pdev, *qdev;
++      int pd_idx = sh->pd_idx;
++      int qd_idx = raid6_next_disk(pd_idx, disks);
++      int p_failed, q_failed;
+-      memset(&s, 0, sizeof(s));
+-      pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d "
+-              "ops=%lx:%lx:%lx\n", (unsigned long long)sh->sector, sh->state,
+-              atomic_read(&sh->count), sh->pd_idx,
+-              sh->ops.pending, sh->ops.ack, sh->ops.complete);
++      PRINTK("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d, qd_idx=%d\n",
++             (unsigned long long)sh->sector, sh->state, atomic_read(&sh->count),
++             pd_idx, qd_idx);
  
--      psli = &phba->sli;
--      mb = &pmb->mb;
-       /* Since we don't do discovery right now, turn these off here */
-       psli->ring[psli->extra_ring].flag &= ~LPFC_STOP_IOCB_EVENT;
-       psli->ring[psli->fcp_ring].flag &= ~LPFC_STOP_IOCB_EVENT;
-@@ -522,69 +765,74 @@
-       if ((mb->mbxStatus) && (mb->mbxStatus != 0x1601)) {
-               /* CLEAR_LA mbox error <mbxStatus> state <hba_state> */
-               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
--                              "%d:0320 CLEAR_LA mbxStatus error x%x hba "
-+                              "%d (%d):0320 CLEAR_LA mbxStatus error x%x hba "
-                               "state x%x\n",
--                              phba->brd_no, mb->mbxStatus, phba->hba_state);
-+                              phba->brd_no, vport->vpi, mb->mbxStatus,
-+                              vport->port_state);
+       spin_lock(&sh->lock);
+       clear_bit(STRIPE_HANDLE, &sh->state);
+       clear_bit(STRIPE_DELAYED, &sh->state);
  
--              phba->hba_state = LPFC_HBA_ERROR;
-+              phba->link_state = LPFC_HBA_ERROR;
-               goto out;
-       }
+-      s.syncing = test_bit(STRIPE_SYNCING, &sh->state);
+-      s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+-      s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
++      syncing = test_bit(STRIPE_SYNCING, &sh->state);
++      expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
++      expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
+       /* Now to look around and see what can be done */
  
--      if (phba->fc_flag & FC_ABORT_DISCOVERY)
--              goto out;
-+      if (vport->port_type == LPFC_PHYSICAL_PORT)
-+              phba->link_state = LPFC_HBA_READY;
+       rcu_read_lock();
+       for (i=disks; i--; ) {
+               mdk_rdev_t *rdev;
+-              struct r5dev *dev = &sh->dev[i];
++              dev = &sh->dev[i];
+               clear_bit(R5_Insync, &dev->flags);
  
--      phba->num_disc_nodes = 0;
--      /* go thru NPR list and issue ELS PLOGIs */
--      if (phba->fc_npr_cnt) {
--              lpfc_els_disc_plogi(phba);
--      }
-+      spin_lock_irq(&phba->hbalock);
-+      psli->sli_flag |= LPFC_PROCESS_LA;
-+      control = readl(phba->HCregaddr);
-+      control |= HC_LAINT_ENA;
-+      writel(control, phba->HCregaddr);
-+      readl(phba->HCregaddr); /* flush */
-+      spin_unlock_irq(&phba->hbalock);
-+      return;
-+
-+      vport->num_disc_nodes = 0;
-+      /* go thru NPR nodes and issue ELS PLOGIs */
-+      if (vport->fc_npr_cnt)
-+              lpfc_els_disc_plogi(vport);
+-              pr_debug("check %d: state 0x%lx toread %p read %p write %p "
+-                      "written %p\n", i, dev->flags, dev->toread, dev->read,
+-                      dev->towrite, dev->written);
+-
+-              /* maybe we can request a biofill operation
+-               *
+-               * new wantfill requests are only permitted while
+-               * STRIPE_OP_BIOFILL is clear
+-               */
+-              if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread &&
+-                      !test_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
+-                      set_bit(R5_Wantfill, &dev->flags);
++              PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
++                      i, dev->flags, dev->toread, dev->towrite, dev->written);
++              /* maybe we can reply to a read */
++              if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
++                      struct bio *rbi, *rbi2;
++                      PRINTK("Return read for disc %d\n", i);
++                      spin_lock_irq(&conf->device_lock);
++                      rbi = dev->toread;
++                      dev->toread = NULL;
++                      if (test_and_clear_bit(R5_Overlap, &dev->flags))
++                              wake_up(&conf->wait_for_overlap);
++                      spin_unlock_irq(&conf->device_lock);
++                      while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
++                              copy_data(0, rbi, dev->page, dev->sector);
++                              rbi2 = r5_next_bio(rbi, dev->sector);
++                              spin_lock_irq(&conf->device_lock);
++                              if (--rbi->bi_phys_segments == 0) {
++                                      rbi->bi_next = return_bi;
++                                      return_bi = rbi;
++                              }
++                              spin_unlock_irq(&conf->device_lock);
++                              rbi = rbi2;
++                      }
++              }
  
--      if (!phba->num_disc_nodes) {
--              spin_lock_irq(phba->host->host_lock);
--              phba->fc_flag &= ~FC_NDISC_ACTIVE;
--              spin_unlock_irq(phba->host->host_lock);
-+      if (!vport->num_disc_nodes) {
-+              spin_lock_irq(shost->host_lock);
-+              vport->fc_flag &= ~FC_NDISC_ACTIVE;
-+              spin_unlock_irq(shost->host_lock);
+               /* now count some things */
+-              if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;
+-              if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;
+-              if (test_bit(R5_Wantcompute, &dev->flags)) s.compute++;
+-
+-              if (test_bit(R5_Wantfill, &dev->flags))
+-                      s.to_fill++;
+-              else if (dev->toread)
+-                      s.to_read++;
++              if (test_bit(R5_LOCKED, &dev->flags)) locked++;
++              if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;
++
++
++              if (dev->toread) to_read++;
+               if (dev->towrite) {
+-                      s.to_write++;
++                      to_write++;
+                       if (!test_bit(R5_OVERWRITE, &dev->flags))
+-                              s.non_overwrite++;
++                              non_overwrite++;
+               }
+-              if (dev->written)
+-                      s.written++;
++              if (dev->written) written++;
+               rdev = rcu_dereference(conf->disks[i].rdev);
+               if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+                       /* The ReadError flag will just be confusing now */
+@@ -2668,361 +1962,376 @@
+               }
+               if (!rdev || !test_bit(In_sync, &rdev->flags)
+                   || test_bit(R5_ReadError, &dev->flags)) {
+-                      s.failed++;
+-                      s.failed_num = i;
++                      if ( failed < 2 )
++                              failed_num[failed] = i;
++                      failed++;
+               } else
+                       set_bit(R5_Insync, &dev->flags);
        }
--      phba->hba_state = LPFC_HBA_READY;
-+      vport->port_state = LPFC_VPORT_READY;
- out:
-       /* Device Discovery completes */
--      lpfc_printf_log(phba,
--                       KERN_INFO,
--                       LOG_DISCOVERY,
--                       "%d:0225 Device Discovery completes\n",
--                       phba->brd_no);
+       rcu_read_unlock();
 -
--      mempool_free( pmb, phba->mbox_mem_pool);
+-      if (s.to_fill && !test_and_set_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
+-              sh->ops.count++;
 -
--      spin_lock_irq(phba->host->host_lock);
--      phba->fc_flag &= ~FC_ABORT_DISCOVERY;
--      if (phba->fc_flag & FC_ESTABLISH_LINK) {
--              phba->fc_flag &= ~FC_ESTABLISH_LINK;
--      }
--      spin_unlock_irq(phba->host->host_lock);
-+      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                      "%d (%d):0225 Device Discovery completes\n",
-+                      phba->brd_no, vport->vpi);
+-      pr_debug("locked=%d uptodate=%d to_read=%d"
+-              " to_write=%d failed=%d failed_num=%d\n",
+-              s.locked, s.uptodate, s.to_read, s.to_write,
+-              s.failed, s.failed_num);
+-      /* check if the array has lost two devices and, if so, some requests might
++      PRINTK("locked=%d uptodate=%d to_read=%d"
++             " to_write=%d failed=%d failed_num=%d,%d\n",
++             locked, uptodate, to_read, to_write, failed,
++             failed_num[0], failed_num[1]);
++      /* check if the array has lost >2 devices and, if so, some requests might
+        * need to be failed
+        */
+-      if (s.failed > 1 && s.to_read+s.to_write+s.written)
+-              handle_requests_to_failed_array(conf, sh, &s, disks,
+-                                              &return_bi);
+-      if (s.failed > 1 && s.syncing) {
++      if (failed > 2 && to_read+to_write+written) {
++              for (i=disks; i--; ) {
++                      int bitmap_end = 0;
++
++                      if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
++                              mdk_rdev_t *rdev;
++                              rcu_read_lock();
++                              rdev = rcu_dereference(conf->disks[i].rdev);
++                              if (rdev && test_bit(In_sync, &rdev->flags))
++                                      /* multiple read failures in one stripe */
++                                      md_error(conf->mddev, rdev);
++                              rcu_read_unlock();
++                      }
 +
-+      mempool_free(pmb, phba->mbox_mem_pool);
++                      spin_lock_irq(&conf->device_lock);
++                      /* fail all writes first */
++                      bi = sh->dev[i].towrite;
++                      sh->dev[i].towrite = NULL;
++                      if (bi) { to_write--; bitmap_end = 1; }
 +
-+      spin_lock_irq(shost->host_lock);
-+      vport->fc_flag &= ~(FC_ABORT_DISCOVERY | FC_ESTABLISH_LINK);
-+      spin_unlock_irq(shost->host_lock);
-       del_timer_sync(&phba->fc_estabtmo);
--      lpfc_can_disctmo(phba);
-+      lpfc_can_disctmo(vport);
-       /* turn on Link Attention interrupts */
--      spin_lock_irq(phba->host->host_lock);
++                      if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
++                              wake_up(&conf->wait_for_overlap);
 +
-+      spin_lock_irq(&phba->hbalock);
-       psli->sli_flag |= LPFC_PROCESS_LA;
-       control = readl(phba->HCregaddr);
-       control |= HC_LAINT_ENA;
-       writel(control, phba->HCregaddr);
-       readl(phba->HCregaddr); /* flush */
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
-       return;
- }
++                      while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
++                              struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
++                              clear_bit(BIO_UPTODATE, &bi->bi_flags);
++                              if (--bi->bi_phys_segments == 0) {
++                                      md_write_end(conf->mddev);
++                                      bi->bi_next = return_bi;
++                                      return_bi = bi;
++                              }
++                              bi = nextbi;
++                      }
++                      /* and fail all 'written' */
++                      bi = sh->dev[i].written;
++                      sh->dev[i].written = NULL;
++                      if (bi) bitmap_end = 1;
++                      while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
++                              struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
++                              clear_bit(BIO_UPTODATE, &bi->bi_flags);
++                              if (--bi->bi_phys_segments == 0) {
++                                      md_write_end(conf->mddev);
++                                      bi->bi_next = return_bi;
++                                      return_bi = bi;
++                              }
++                              bi = bi2;
++                      }
 +
- static void
- lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
- {
--      struct lpfc_sli *psli = &phba->sli;
--      int rc;
-+      struct lpfc_vport *vport = pmb->vport;
-       if (pmb->mb.mbxStatus)
-               goto out;
-@@ -592,127 +840,110 @@
-       mempool_free(pmb, phba->mbox_mem_pool);
-       if (phba->fc_topology == TOPOLOGY_LOOP &&
--              phba->fc_flag & FC_PUBLIC_LOOP &&
--               !(phba->fc_flag & FC_LBIT)) {
-+          vport->fc_flag & FC_PUBLIC_LOOP &&
-+          !(vport->fc_flag & FC_LBIT)) {
-                       /* Need to wait for FAN - use discovery timer
--                       * for timeout.  hba_state is identically
-+                       * for timeout.  port_state is identically
-                        * LPFC_LOCAL_CFG_LINK while waiting for FAN
-                        */
--                      lpfc_set_disctmo(phba);
-+                      lpfc_set_disctmo(vport);
-                       return;
-               }
--      /* Start discovery by sending a FLOGI. hba_state is identically
-+      /* Start discovery by sending a FLOGI. port_state is identically
-        * LPFC_FLOGI while waiting for FLOGI cmpl
-        */
--      phba->hba_state = LPFC_FLOGI;
--      lpfc_set_disctmo(phba);
--      lpfc_initial_flogi(phba);
-+      if (vport->port_state != LPFC_FLOGI) {
-+              vport->port_state = LPFC_FLOGI;
-+              lpfc_set_disctmo(vport);
-+              lpfc_initial_flogi(vport);
++                      /* fail any reads if this device is non-operational */
++                      if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
++                          test_bit(R5_ReadError, &sh->dev[i].flags)) {
++                              bi = sh->dev[i].toread;
++                              sh->dev[i].toread = NULL;
++                              if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
++                                      wake_up(&conf->wait_for_overlap);
++                              if (bi) to_read--;
++                              while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
++                                      struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
++                                      clear_bit(BIO_UPTODATE, &bi->bi_flags);
++                                      if (--bi->bi_phys_segments == 0) {
++                                              bi->bi_next = return_bi;
++                                              return_bi = bi;
++                                      }
++                                      bi = nextbi;
++                              }
++                      }
++                      spin_unlock_irq(&conf->device_lock);
++                      if (bitmap_end)
++                              bitmap_endwrite(conf->mddev->bitmap, sh->sector,
++                                              STRIPE_SECTORS, 0, 0);
++              }
 +      }
-       return;
- out:
-       lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
--                      "%d:0306 CONFIG_LINK mbxStatus error x%x "
-+                      "%d (%d):0306 CONFIG_LINK mbxStatus error x%x "
-                       "HBA state x%x\n",
--                      phba->brd_no, pmb->mb.mbxStatus, phba->hba_state);
-+                      phba->brd_no, vport->vpi, pmb->mb.mbxStatus,
-+                      vport->port_state);
--      lpfc_linkdown(phba);
-+      mempool_free(pmb, phba->mbox_mem_pool);
++      if (failed > 2 && syncing) {
+               md_done_sync(conf->mddev, STRIPE_SECTORS,0);
+               clear_bit(STRIPE_SYNCING, &sh->state);
+-              s.syncing = 0;
++              syncing = 0;
+       }
  
--      phba->hba_state = LPFC_HBA_ERROR;
-+      lpfc_linkdown(phba);
+-      /* might be able to return some write requests if the parity block
+-       * is safe, or on a failed drive
++      /*
++       * might be able to return some write requests if the parity blocks
++       * are safe, or on a failed drive
+                */
+-      dev = &sh->dev[sh->pd_idx];
+-      if ( s.written &&
+-           ((test_bit(R5_Insync, &dev->flags) &&
+-             !test_bit(R5_LOCKED, &dev->flags) &&
+-             test_bit(R5_UPTODATE, &dev->flags)) ||
+-             (s.failed == 1 && s.failed_num == sh->pd_idx)))
+-              handle_completed_write_requests(conf, sh, disks, &return_bi);
++      pdev = &sh->dev[pd_idx];
++      p_failed = (failed >= 1 && failed_num[0] == pd_idx)
++              || (failed >= 2 && failed_num[1] == pd_idx);
++      qdev = &sh->dev[qd_idx];
++      q_failed = (failed >= 1 && failed_num[0] == qd_idx)
++              || (failed >= 2 && failed_num[1] == qd_idx);
++
++      if ( written &&
++           ( p_failed || ((test_bit(R5_Insync, &pdev->flags)
++                           && !test_bit(R5_LOCKED, &pdev->flags)
++                           && test_bit(R5_UPTODATE, &pdev->flags))) ) &&
++           ( q_failed || ((test_bit(R5_Insync, &qdev->flags)
++                           && !test_bit(R5_LOCKED, &qdev->flags)
++                           && test_bit(R5_UPTODATE, &qdev->flags))) ) ) {
++              /* any written block on an uptodate or failed drive can be
++               * returned.  Note that if we 'wrote' to a failed drive,
++               * it will be UPTODATE, but never LOCKED, so we don't need
++               * to test 'failed' directly.
++               */
++              for (i=disks; i--; )
++                      if (sh->dev[i].written) {
++                              dev = &sh->dev[i];
++                              if (!test_bit(R5_LOCKED, &dev->flags) &&
++                                  test_bit(R5_UPTODATE, &dev->flags) ) {
++                                      /* We can return any write requests */
++                                      int bitmap_end = 0;
++                                      struct bio *wbi, *wbi2;
++                                      PRINTK("Return write for stripe %llu disc %d\n",
++                                             (unsigned long long)sh->sector, i);
++                                      spin_lock_irq(&conf->device_lock);
++                                      wbi = dev->written;
++                                      dev->written = NULL;
++                                      while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
++                                              wbi2 = r5_next_bio(wbi, dev->sector);
++                                              if (--wbi->bi_phys_segments == 0) {
++                                                      md_write_end(conf->mddev);
++                                                      wbi->bi_next = return_bi;
++                                                      return_bi = wbi;
++                                              }
++                                              wbi = wbi2;
++                                      }
++                                      if (dev->towrite == NULL)
++                                              bitmap_end = 1;
++                                      spin_unlock_irq(&conf->device_lock);
++                                      if (bitmap_end)
++                                              bitmap_endwrite(conf->mddev->bitmap, sh->sector,
++                                                              STRIPE_SECTORS,
++                                                              !test_bit(STRIPE_DEGRADED, &sh->state), 0);
++                              }
++                      }
++      }
  
-       lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
--                      "%d:0200 CONFIG_LINK bad hba state x%x\n",
--                      phba->brd_no, phba->hba_state);
-+                      "%d (%d):0200 CONFIG_LINK bad hba state x%x\n",
-+                      phba->brd_no, vport->vpi, vport->port_state);
--      lpfc_clear_la(phba, pmb);
--      pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
--      rc = lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB));
--      if (rc == MBX_NOT_FINISHED) {
--              mempool_free(pmb, phba->mbox_mem_pool);
--              lpfc_disc_flush_list(phba);
--              psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
--              psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
--              psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
--              phba->hba_state = LPFC_HBA_READY;
--      }
-+      lpfc_issue_clear_la(phba, vport);
-       return;
- }
+       /* Now we might consider reading some blocks, either to check/generate
+        * parity, or to satisfy requests
+        * or to load a block that is being partially written.
+        */
+-      if (s.to_read || s.non_overwrite ||
+-          (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding ||
+-          test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
+-              handle_issuing_new_read_requests5(sh, &s, disks);
+-
+-      /* Now we check to see if any write operations have recently
+-       * completed
+-                               */
+-
+-      /* leave prexor set until postxor is done, allows us to distinguish
+-       * a rmw from a rcw during biodrain
++      if (to_read || non_overwrite || (to_write && failed) ||
++          (syncing && (uptodate < disks)) || expanding) {
++              for (i=disks; i--;) {
++                      dev = &sh->dev[i];
++                      if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
++                          (dev->toread ||
++                           (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
++                           syncing ||
++                           expanding ||
++                           (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) ||
++                           (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write))
++                                  )
++                              ) {
++                              /* we would like to get this block, possibly
++                               * by computing it, but we might not be able to
+        */
+-      if (test_bit(STRIPE_OP_PREXOR, &sh->ops.complete) &&
+-              test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
+-
+-              clear_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
+-              clear_bit(STRIPE_OP_PREXOR, &sh->ops.ack);
+-              clear_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+-
+-              for (i = disks; i--; )
+-                      clear_bit(R5_Wantprexor, &sh->dev[i].flags);
++                              if (uptodate == disks-1) {
++                                      PRINTK("Computing stripe %llu block %d\n",
++                                             (unsigned long long)sh->sector, i);
++                                      compute_block_1(sh, i, 0);
++                                      uptodate++;
++                              } else if ( uptodate == disks-2 && failed >= 2 ) {
++                                      /* Computing 2-failure is *very* expensive; only do it if failed >= 2 */
++                                      int other;
++                                      for (other=disks; other--;) {
++                                              if ( other == i )
++                                                      continue;
++                                              if ( !test_bit(R5_UPTODATE, &sh->dev[other].flags) )
++                                                      break;
+       }
+-
+-      /* if only POSTXOR is set then this is an 'expand' postxor */
+-      if (test_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete) &&
+-              test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
+-
+-              clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
+-              clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.ack);
+-              clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
+-
+-              clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+-              clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
+-              clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+-
+-              /* All the 'written' buffers and the parity block are ready to
+-               * be written back to disk
+-               */
+-              BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
+-              for (i = disks; i--; ) {
+-                      dev = &sh->dev[i];
+-                      if (test_bit(R5_LOCKED, &dev->flags) &&
+-                              (i == sh->pd_idx || dev->written)) {
+-                              pr_debug("Writing block %d\n", i);
+-                              set_bit(R5_Wantwrite, &dev->flags);
+-                              if (!test_and_set_bit(
+-                                  STRIPE_OP_IO, &sh->ops.pending))
+-                                      sh->ops.count++;
+-                              if (!test_bit(R5_Insync, &dev->flags) ||
+-                                  (i == sh->pd_idx && s.failed == 0))
+-                                      set_bit(STRIPE_INSYNC, &sh->state);
++                                      BUG_ON(other < 0);
++                                      PRINTK("Computing stripe %llu blocks %d,%d\n",
++                                             (unsigned long long)sh->sector, i, other);
++                                      compute_block_2(sh, i, other);
++                                      uptodate += 2;
++                              } else if (test_bit(R5_Insync, &dev->flags)) {
++                                      set_bit(R5_LOCKED, &dev->flags);
++                                      set_bit(R5_Wantread, &dev->flags);
++                                      locked++;
++                                      PRINTK("Reading block %d (sync=%d)\n",
++                                              i, syncing);
+                       }
+                               }
+-              if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+-                      atomic_dec(&conf->preread_active_stripes);
+-                      if (atomic_read(&conf->preread_active_stripes) <
+-                              IO_THRESHOLD)
+-                              md_wakeup_thread(conf->mddev->thread);
+                       }
++              set_bit(STRIPE_HANDLE, &sh->state);
+               }
  
- static void
--lpfc_mbx_cmpl_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
-+lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
- {
--      struct lpfc_sli *psli = &phba->sli;
-       MAILBOX_t *mb = &pmb->mb;
-       struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) pmb->context1;
-+      struct lpfc_vport  *vport = pmb->vport;
+-      /* Now to consider new write requests and what else, if anything
+-       * should be read.  We do not handle new writes when:
+-       * 1/ A 'write' operation (copy+xor) is already in flight.
+-       * 2/ A 'check' operation is in flight, as it may clobber the parity
+-       *    block.
+-       */
+-      if (s.to_write && !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending) &&
+-                        !test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
+-              handle_issuing_new_write_requests5(conf, sh, &s, disks);
+-
+-      /* maybe we need to check and possibly fix the parity for this stripe
+-       * Any reads will already have been scheduled, so we just see if enough
+-       * data is available.  The parity check is held off while parity
+-       * dependent operations are in flight.
+-       */
+-      if ((s.syncing && s.locked == 0 &&
+-           !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
+-           !test_bit(STRIPE_INSYNC, &sh->state)) ||
+-            test_bit(STRIPE_OP_CHECK, &sh->ops.pending) ||
+-            test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending))
+-              handle_parity_checks5(conf, sh, &s, disks);
+-
+-      if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
+-              md_done_sync(conf->mddev, STRIPE_SECTORS,1);
+-              clear_bit(STRIPE_SYNCING, &sh->state);
++      /* now to consider writing and what else, if anything should be read */
++      if (to_write) {
++              int rcw=0, must_compute=0;
++              for (i=disks ; i--;) {
++                      dev = &sh->dev[i];
++                      /* Would I have to read this buffer for reconstruct_write */
++                      if (!test_bit(R5_OVERWRITE, &dev->flags)
++                          && i != pd_idx && i != qd_idx
++                          && (!test_bit(R5_LOCKED, &dev->flags)
++                                  ) &&
++                          !test_bit(R5_UPTODATE, &dev->flags)) {
++                              if (test_bit(R5_Insync, &dev->flags)) rcw++;
++                              else {
++                                      PRINTK("raid6: must_compute: disk %d flags=%#lx\n", i, dev->flags);
++                                      must_compute++;
++                              }
++                      }
+       }
++              PRINTK("for sector %llu, rcw=%d, must_compute=%d\n",
++                     (unsigned long long)sh->sector, rcw, must_compute);
++              set_bit(STRIPE_HANDLE, &sh->state);
  
+-      /* If the failed drive is just a ReadError, then we might need to progress
+-       * the repair/check process
+-       */
+-      if (s.failed == 1 && !conf->mddev->ro &&
+-          test_bit(R5_ReadError, &sh->dev[s.failed_num].flags)
+-          && !test_bit(R5_LOCKED, &sh->dev[s.failed_num].flags)
+-          && test_bit(R5_UPTODATE, &sh->dev[s.failed_num].flags)
+-              ) {
+-              dev = &sh->dev[s.failed_num];
+-              if (!test_bit(R5_ReWrite, &dev->flags)) {
+-                      set_bit(R5_Wantwrite, &dev->flags);
+-                      if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+-                              sh->ops.count++;
+-                      set_bit(R5_ReWrite, &dev->flags);
++              if (rcw > 0)
++                      /* want reconstruct write, but need to get some data */
++                      for (i=disks; i--;) {
++                              dev = &sh->dev[i];
++                              if (!test_bit(R5_OVERWRITE, &dev->flags)
++                                  && !(failed == 0 && (i == pd_idx || i == qd_idx))
++                                  && !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
++                                  test_bit(R5_Insync, &dev->flags)) {
++                                      if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
++                                      {
++                                              PRINTK("Read_old stripe %llu block %d for Reconstruct\n",
++                                                     (unsigned long long)sh->sector, i);
+                                               set_bit(R5_LOCKED, &dev->flags);
+-                      s.locked++;
+-                                      } else {
+-                      /* let's read it back */
+                       set_bit(R5_Wantread, &dev->flags);
+-                      if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+-                              sh->ops.count++;
+-                      set_bit(R5_LOCKED, &dev->flags);
+-                      s.locked++;
++                                              locked++;
++                                      } else {
++                                              PRINTK("Request delayed stripe %llu block %d for Reconstruct\n",
++                                                     (unsigned long long)sh->sector, i);
++                                              set_bit(STRIPE_DELAYED, &sh->state);
++                                              set_bit(STRIPE_HANDLE, &sh->state);
+                                       }
+                               }
+-
+-      /* Finish postxor operations initiated by the expansion
+-       * process
+-       */
+-      if (test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete) &&
+-              !test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending)) {
+-
+-              clear_bit(STRIPE_EXPANDING, &sh->state);
+-
+-              clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+-              clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
+-              clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+-
+-              for (i = conf->raid_disks; i--; ) {
+-                      set_bit(R5_Wantwrite, &sh->dev[i].flags);
+-                      if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+-                              sh->ops.count++;
+                       }
++              /* now if nothing is locked, and if we have enough data, we can start a write request */
++              if (locked == 0 && rcw == 0 &&
++                  !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
++                      if ( must_compute > 0 ) {
++                              /* We have failed blocks and need to compute them */
++                              switch ( failed ) {
++                              case 0: BUG();
++                              case 1: compute_block_1(sh, failed_num[0], 0); break;
++                              case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break;
++                              default: BUG(); /* This request should have been failed? */
+                               }
+-
+-      if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state) &&
+-              !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+-              /* Need to write out all blocks after computing parity */
+-              sh->disks = conf->raid_disks;
+-              sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
+-                      conf->raid_disks);
+-              s.locked += handle_write_operations5(sh, 0, 1);
+-      } else if (s.expanded &&
+-              !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+-              clear_bit(STRIPE_EXPAND_READY, &sh->state);
+-              atomic_dec(&conf->reshape_stripes);
+-              wake_up(&conf->wait_for_overlap);
+-              md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
+                       }
  
-       /* Check for error */
-       if (mb->mbxStatus) {
-               /* READ_SPARAM mbox error <mbxStatus> state <hba_state> */
-               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
--                              "%d:0319 READ_SPARAM mbxStatus error x%x "
-+                              "%d (%d):0319 READ_SPARAM mbxStatus error x%x "
-                               "hba state x%x>\n",
--                              phba->brd_no, mb->mbxStatus, phba->hba_state);
-+                              phba->brd_no, vport->vpi, mb->mbxStatus,
-+                              vport->port_state);
+-      if (s.expanding && s.locked == 0)
+-              handle_stripe_expansion(conf, sh, NULL);
+-
+-      if (sh->ops.count)
+-              pending = get_stripe_work(sh);
+-
+-      spin_unlock(&sh->lock);
+-
+-      if (pending)
+-              raid5_run_ops(sh, pending);
+-
+-      while ((bi=return_bi)) {
+-              int bytes = bi->bi_size;
+-
+-              return_bi = bi->bi_next;
+-              bi->bi_next = NULL;
+-              bi->bi_size = 0;
+-              bi->bi_end_io(bi, bytes,
+-                            test_bit(BIO_UPTODATE, &bi->bi_flags)
+-                              ? 0 : -EIO);
++                      PRINTK("Computing parity for stripe %llu\n", (unsigned long long)sh->sector);
++                      compute_parity6(sh, RECONSTRUCT_WRITE);
++                      /* now every locked buffer is ready to be written */
++                      for (i=disks; i--;)
++                              if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
++                                      PRINTK("Writing stripe %llu block %d\n",
++                                             (unsigned long long)sh->sector, i);
++                                      locked++;
++                                      set_bit(R5_Wantwrite, &sh->dev[i].flags);
+                               }
+-}
+-
+-static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
+-{
+-      raid6_conf_t *conf = sh->raid_conf;
+-      int disks = sh->disks;
+-      struct bio *return_bi = NULL;
+-      struct bio *bi;
+-      int i, pd_idx = sh->pd_idx;
+-      struct stripe_head_state s;
+-      struct r6_state r6s;
+-      struct r5dev *dev, *pdev, *qdev;
+-
+-      r6s.qd_idx = raid6_next_disk(pd_idx, disks);
+-      pr_debug("handling stripe %llu, state=%#lx cnt=%d, "
+-              "pd_idx=%d, qd_idx=%d\n",
+-             (unsigned long long)sh->sector, sh->state,
+-             atomic_read(&sh->count), pd_idx, r6s.qd_idx);
+-      memset(&s, 0, sizeof(s));
+-
+-      spin_lock(&sh->lock);
+-      clear_bit(STRIPE_HANDLE, &sh->state);
+-      clear_bit(STRIPE_DELAYED, &sh->state);
+-
+-      s.syncing = test_bit(STRIPE_SYNCING, &sh->state);
+-      s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+-      s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
+-      /* Now to look around and see what can be done */
+-
+-      rcu_read_lock();
+-      for (i=disks; i--; ) {
+-              mdk_rdev_t *rdev;
+-              dev = &sh->dev[i];
+-              clear_bit(R5_Insync, &dev->flags);
++                      /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
++                      set_bit(STRIPE_INSYNC, &sh->state);
  
-               lpfc_linkdown(phba);
--              phba->hba_state = LPFC_HBA_ERROR;
-               goto out;
+-              pr_debug("check %d: state 0x%lx read %p write %p written %p\n",
+-                      i, dev->flags, dev->toread, dev->towrite, dev->written);
+-              /* maybe we can reply to a read */
+-              if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
+-                      struct bio *rbi, *rbi2;
+-                      pr_debug("Return read for disc %d\n", i);
+-                      spin_lock_irq(&conf->device_lock);
+-                      rbi = dev->toread;
+-                      dev->toread = NULL;
+-                      if (test_and_clear_bit(R5_Overlap, &dev->flags))
+-                              wake_up(&conf->wait_for_overlap);
+-                      spin_unlock_irq(&conf->device_lock);
+-                      while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
+-                              copy_data(0, rbi, dev->page, dev->sector);
+-                              rbi2 = r5_next_bio(rbi, dev->sector);
+-                              spin_lock_irq(&conf->device_lock);
+-                              if (--rbi->bi_phys_segments == 0) {
+-                                      rbi->bi_next = return_bi;
+-                                      return_bi = rbi;
++                      if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
++                              atomic_dec(&conf->preread_active_stripes);
++                              if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
++                                      md_wakeup_thread(conf->mddev->thread);
+                       }
+-                              spin_unlock_irq(&conf->device_lock);
+-                              rbi = rbi2;
+               }
        }
  
--      memcpy((uint8_t *) & phba->fc_sparam, (uint8_t *) mp->virt,
-+      memcpy((uint8_t *) &vport->fc_sparam, (uint8_t *) mp->virt,
-              sizeof (struct serv_parm));
-       if (phba->cfg_soft_wwnn)
--              u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
-+              u64_to_wwn(phba->cfg_soft_wwnn,
-+                         vport->fc_sparam.nodeName.u.wwn);
-       if (phba->cfg_soft_wwpn)
--              u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
--      memcpy((uint8_t *) & phba->fc_nodename,
--             (uint8_t *) & phba->fc_sparam.nodeName,
--             sizeof (struct lpfc_name));
--      memcpy((uint8_t *) & phba->fc_portname,
--             (uint8_t *) & phba->fc_sparam.portName,
--             sizeof (struct lpfc_name));
-+              u64_to_wwn(phba->cfg_soft_wwpn,
-+                         vport->fc_sparam.portName.u.wwn);
-+      memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
-+             sizeof(vport->fc_nodename));
-+      memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
-+             sizeof(vport->fc_portname));
-+      if (vport->port_type == LPFC_PHYSICAL_PORT) {
-+              memcpy(&phba->wwnn, &vport->fc_nodename, sizeof(phba->wwnn));
-+              memcpy(&phba->wwpn, &vport->fc_portname, sizeof(phba->wwnn));
-+      }
-+
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
--      mempool_free( pmb, phba->mbox_mem_pool);
-+      mempool_free(pmb, phba->mbox_mem_pool);
-       return;
- out:
-       pmb->context1 = NULL;
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
--      if (phba->hba_state != LPFC_CLEAR_LA) {
--              lpfc_clear_la(phba, pmb);
--              pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
--              if (lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB))
--                  == MBX_NOT_FINISHED) {
--                      mempool_free( pmb, phba->mbox_mem_pool);
--                      lpfc_disc_flush_list(phba);
--                      psli->ring[(psli->extra_ring)].flag &=
--                          ~LPFC_STOP_IOCB_EVENT;
--                      psli->ring[(psli->fcp_ring)].flag &=
--                          ~LPFC_STOP_IOCB_EVENT;
--                      psli->ring[(psli->next_ring)].flag &=
--                          ~LPFC_STOP_IOCB_EVENT;
--                      phba->hba_state = LPFC_HBA_READY;
--              }
--      } else {
--              mempool_free( pmb, phba->mbox_mem_pool);
--      }
-+      lpfc_issue_clear_la(phba, vport);
-+      mempool_free(pmb, phba->mbox_mem_pool);
-       return;
- }
- static void
- lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
- {
--      int i;
-+      struct lpfc_vport *vport = phba->pport;
-       LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox;
-+      int i;
-       struct lpfc_dmabuf *mp;
-       int rc;
+-              /* now count some things */
+-              if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;
+-              if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;
++      /* maybe we need to check and possibly fix the parity for this stripe
++       * Any reads will already have been scheduled, so we just see if enough data
++       * is available
++       */
++      if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) {
++              int update_p = 0, update_q = 0;
++              struct r5dev *dev;
  
-       sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-       cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
++              set_bit(STRIPE_HANDLE, &sh->state);
  
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       switch (la->UlnkSpeed) {
-               case LA_1GHZ_LINK:
-                       phba->fc_linkspeed = LA_1GHZ_LINK;
-@@ -732,14 +963,16 @@
-       }
+-              if (dev->toread)
+-                      s.to_read++;
+-              if (dev->towrite) {
+-                      s.to_write++;
+-                      if (!test_bit(R5_OVERWRITE, &dev->flags))
+-                              s.non_overwrite++;
++              BUG_ON(failed>2);
++              BUG_ON(uptodate < disks);
++              /* Want to check and possibly repair P and Q.
++               * However there could be one 'failed' device, in which
++               * case we can only check one of them, possibly using the
++               * other to generate missing data
++               */
++
++              /* If !tmp_page, we cannot do the calculations,
++               * but as we have set STRIPE_HANDLE, we will soon be called
++               * by stripe_handle with a tmp_page - just wait until then.
++               */
++              if (tmp_page) {
++                      if (failed == q_failed) {
++                              /* The only possible failed device holds 'Q', so it makes
++                               * sense to check P (If anything else were failed, we would
++                               * have used P to recreate it).
++                               */
++                              compute_block_1(sh, pd_idx, 1);
++                              if (!page_is_zero(sh->dev[pd_idx].page)) {
++                                      compute_block_1(sh,pd_idx,0);
++                                      update_p = 1;
+                       }
+-              if (dev->written)
+-                      s.written++;
+-              rdev = rcu_dereference(conf->disks[i].rdev);
+-              if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+-                      /* The ReadError flag will just be confusing now */
+-                      clear_bit(R5_ReadError, &dev->flags);
+-                      clear_bit(R5_ReWrite, &dev->flags);
+                               }
+-              if (!rdev || !test_bit(In_sync, &rdev->flags)
+-                  || test_bit(R5_ReadError, &dev->flags)) {
+-                      if (s.failed < 2)
+-                              r6s.failed_num[s.failed] = i;
+-                      s.failed++;
+-              } else
+-                      set_bit(R5_Insync, &dev->flags);
++                      if (!q_failed && failed < 2) {
++                              /* q is not failed, and we didn't use it to generate
++                               * anything, so it makes sense to check it
++                               */
++                              memcpy(page_address(tmp_page),
++                                     page_address(sh->dev[qd_idx].page),
++                                     STRIPE_SIZE);
++                              compute_parity6(sh, UPDATE_PARITY);
++                              if (memcmp(page_address(tmp_page),
++                                         page_address(sh->dev[qd_idx].page),
++                                         STRIPE_SIZE)!= 0) {
++                                      clear_bit(STRIPE_INSYNC, &sh->state);
++                                      update_q = 1;
+                       }
+-      rcu_read_unlock();
+-      pr_debug("locked=%d uptodate=%d to_read=%d"
+-             " to_write=%d failed=%d failed_num=%d,%d\n",
+-             s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
+-             r6s.failed_num[0], r6s.failed_num[1]);
+-      /* check if the array has lost >2 devices and, if so, some requests
+-       * might need to be failed
+-       */
+-      if (s.failed > 2 && s.to_read+s.to_write+s.written)
+-              handle_requests_to_failed_array(conf, sh, &s, disks,
+-                                              &return_bi);
+-      if (s.failed > 2 && s.syncing) {
+-              md_done_sync(conf->mddev, STRIPE_SECTORS,0);
+-              clear_bit(STRIPE_SYNCING, &sh->state);
+-              s.syncing = 0;
++                      }
++                      if (update_p || update_q) {
++                              conf->mddev->resync_mismatches += STRIPE_SECTORS;
++                              if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
++                                      /* don't try to repair!! */
++                                      update_p = update_q = 0;
+                       }
  
-       phba->fc_topology = la->topology;
-+      phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
+-      /*
+-       * might be able to return some write requests if the parity blocks
+-       * are safe, or on a failed drive
++                      /* now write out any block on a failed drive,
++                       * or P or Q if they need it
+                        */
+-      pdev = &sh->dev[pd_idx];
+-      r6s.p_failed = (s.failed >= 1 && r6s.failed_num[0] == pd_idx)
+-              || (s.failed >= 2 && r6s.failed_num[1] == pd_idx);
+-      qdev = &sh->dev[r6s.qd_idx];
+-      r6s.q_failed = (s.failed >= 1 && r6s.failed_num[0] == r6s.qd_idx)
+-              || (s.failed >= 2 && r6s.failed_num[1] == r6s.qd_idx);
+-
+-      if ( s.written &&
+-           ( r6s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
+-                           && !test_bit(R5_LOCKED, &pdev->flags)
+-                           && test_bit(R5_UPTODATE, &pdev->flags)))) &&
+-           ( r6s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
+-                           && !test_bit(R5_LOCKED, &qdev->flags)
+-                           && test_bit(R5_UPTODATE, &qdev->flags)))))
+-              handle_completed_write_requests(conf, sh, disks, &return_bi);
  
-       if (phba->fc_topology == TOPOLOGY_LOOP) {
--      /* Get Loop Map information */
-+              phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED;
+-      /* Now we might consider reading some blocks, either to check/generate
+-       * parity, or to satisfy requests
+-       * or to load a block that is being partially written.
+-       */
+-      if (s.to_read || s.non_overwrite || (s.to_write && s.failed) ||
+-          (s.syncing && (s.uptodate < disks)) || s.expanding)
+-              handle_issuing_new_read_requests6(sh, &s, &r6s, disks);
++                      if (failed == 2) {
++                              dev = &sh->dev[failed_num[1]];
++                              locked++;
++                              set_bit(R5_LOCKED, &dev->flags);
++                              set_bit(R5_Wantwrite, &dev->flags);
++                      }
++                      if (failed >= 1) {
++                              dev = &sh->dev[failed_num[0]];
++                              locked++;
++                              set_bit(R5_LOCKED, &dev->flags);
++                              set_bit(R5_Wantwrite, &dev->flags);
++                      }
  
-+                              /* Get Loop Map information */
-               if (la->il)
--                      phba->fc_flag |= FC_LBIT;
-+                      vport->fc_flag |= FC_LBIT;
+-      /* now to consider writing and what else, if anything should be read */
+-      if (s.to_write)
+-              handle_issuing_new_write_requests6(conf, sh, &s, &r6s, disks);
++                      if (update_p) {
++                              dev = &sh->dev[pd_idx];
++                              locked ++;
++                              set_bit(R5_LOCKED, &dev->flags);
++                              set_bit(R5_Wantwrite, &dev->flags);
++                      }
++                      if (update_q) {
++                              dev = &sh->dev[qd_idx];
++                              locked++;
++                              set_bit(R5_LOCKED, &dev->flags);
++                              set_bit(R5_Wantwrite, &dev->flags);
++                      }
++                      clear_bit(STRIPE_DEGRADED, &sh->state);
  
--              phba->fc_myDID = la->granted_AL_PA;
-+              vport->fc_myDID = la->granted_AL_PA;
-               i = la->un.lilpBde64.tus.f.bdeSize;
+-      /* maybe we need to check and possibly fix the parity for this stripe
+-       * Any reads will already have been scheduled, so we just see if enough
+-       * data is available
+-       */
+-      if (s.syncing && s.locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state))
+-              handle_parity_checks6(conf, sh, &s, &r6s, tmp_page, disks);
++                      set_bit(STRIPE_INSYNC, &sh->state);
++              }
++      }
  
-               if (i == 0) {
-@@ -781,14 +1014,20 @@
+-      if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
++      if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
+               md_done_sync(conf->mddev, STRIPE_SECTORS,1);
+               clear_bit(STRIPE_SYNCING, &sh->state);
+       }
+@@ -3030,9 +2339,9 @@
+       /* If the failed drives are just a ReadError, then we might need
+        * to progress the repair/check process
+        */
+-      if (s.failed <= 2 && !conf->mddev->ro)
+-              for (i = 0; i < s.failed; i++) {
+-                      dev = &sh->dev[r6s.failed_num[i]];
++      if (failed <= 2 && ! conf->mddev->ro)
++              for (i=0; i<failed;i++) {
++                      dev = &sh->dev[failed_num[i]];
+                       if (test_bit(R5_ReadError, &dev->flags)
+                           && !test_bit(R5_LOCKED, &dev->flags)
+                           && test_bit(R5_UPTODATE, &dev->flags)
+@@ -3049,7 +2358,7 @@
                        }
                }
-       } else {
--              phba->fc_myDID = phba->fc_pref_DID;
--              phba->fc_flag |= FC_LBIT;
-+              if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) {
-+                      if (phba->max_vpi && phba->cfg_npiv_enable &&
-+                         (phba->sli_rev == 3))
-+                              phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
-+              }
-+              vport->fc_myDID = phba->fc_pref_DID;
-+              vport->fc_flag |= FC_LBIT;
-       }
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
  
-       lpfc_linkup(phba);
-       if (sparam_mbox) {
--              lpfc_read_sparam(phba, sparam_mbox);
-+              lpfc_read_sparam(phba, sparam_mbox, 0);
-+              sparam_mbox->vport = vport;
-               sparam_mbox->mbox_cmpl = lpfc_mbx_cmpl_read_sparam;
-               rc = lpfc_sli_issue_mbox(phba, sparam_mbox,
-                                               (MBX_NOWAIT | MBX_STOP_IOCB));
-@@ -799,36 +1038,48 @@
-                       mempool_free(sparam_mbox, phba->mbox_mem_pool);
-                       if (cfglink_mbox)
-                               mempool_free(cfglink_mbox, phba->mbox_mem_pool);
--                      return;
-+                      goto out;
+-      if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
++      if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
+               /* Need to write out all blocks after computing P&Q */
+               sh->disks = conf->raid_disks;
+               sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
+@@ -3057,19 +2366,69 @@
+               compute_parity6(sh, RECONSTRUCT_WRITE);
+               for (i = conf->raid_disks ; i-- ;  ) {
+                       set_bit(R5_LOCKED, &sh->dev[i].flags);
+-                      s.locked++;
++                      locked++;
+                       set_bit(R5_Wantwrite, &sh->dev[i].flags);
                }
+               clear_bit(STRIPE_EXPANDING, &sh->state);
+-      } else if (s.expanded) {
++      } else if (expanded) {
+               clear_bit(STRIPE_EXPAND_READY, &sh->state);
+               atomic_dec(&conf->reshape_stripes);
+               wake_up(&conf->wait_for_overlap);
+               md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
        }
  
-       if (cfglink_mbox) {
--              phba->hba_state = LPFC_LOCAL_CFG_LINK;
-+              vport->port_state = LPFC_LOCAL_CFG_LINK;
-               lpfc_config_link(phba, cfglink_mbox);
-+              cfglink_mbox->vport = vport;
-               cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link;
-               rc = lpfc_sli_issue_mbox(phba, cfglink_mbox,
-                                               (MBX_NOWAIT | MBX_STOP_IOCB));
--              if (rc == MBX_NOT_FINISHED)
-+              if (rc != MBX_NOT_FINISHED)
-+                      return;
-                       mempool_free(cfglink_mbox, phba->mbox_mem_pool);
-       }
-+out:
-+      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+      lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
-+              "%d (%d):0263 Discovery Mailbox error: state: 0x%x : %p %p\n",
-+              phba->brd_no, vport->vpi,
-+              vport->port_state, sparam_mbox, cfglink_mbox);
-+
-+      lpfc_issue_clear_la(phba, vport);
-+      return;
- }
+-      if (s.expanding && s.locked == 0)
+-              handle_stripe_expansion(conf, sh, &r6s);
++      if (expanding && locked == 0) {
++              /* We have read all the blocks in this stripe and now we need to
++               * copy some of them into a target stripe for expand.
++               */
++              clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
++              for (i = 0; i < sh->disks ; i++)
++                      if (i != pd_idx && i != qd_idx) {
++                              int dd_idx2, pd_idx2, j;
++                              struct stripe_head *sh2;
++
++                              sector_t bn = compute_blocknr(sh, i);
++                              sector_t s = raid5_compute_sector(
++                                      bn, conf->raid_disks,
++                                      conf->raid_disks - conf->max_degraded,
++                                      &dd_idx2, &pd_idx2, conf);
++                              sh2 = get_active_stripe(conf, s,
++                                                      conf->raid_disks,
++                                                     pd_idx2, 1);
++                              if (sh2 == NULL)
++                                      /* so for only the early blocks of
++                                       * this stripe have been requests.
++                                       * When later blocks get requests, we
++                                       * will try again
++                                       */
++                                      continue;
++                              if (!test_bit(STRIPE_EXPANDING, &sh2->state) ||
++                                  test_bit(R5_Expanded,
++                                           &sh2->dev[dd_idx2].flags)) {
++                                      /* must have already done this block */
++                                      release_stripe(sh2);
++                                      continue;
++                              }
++                              memcpy(page_address(sh2->dev[dd_idx2].page),
++                                     page_address(sh->dev[i].page),
++                                     STRIPE_SIZE);
++                              set_bit(R5_Expanded, &sh2->dev[dd_idx2].flags);
++                              set_bit(R5_UPTODATE, &sh2->dev[dd_idx2].flags);
++                              for (j = 0 ; j < conf->raid_disks ; j++)
++                                      if (j != sh2->pd_idx &&
++                                          j != raid6_next_disk(sh2->pd_idx,
++                                                         sh2->disks) &&
++                                          !test_bit(R5_Expanded,
++                                                    &sh2->dev[j].flags))
++                                              break;
++                              if (j == conf->raid_disks) {
++                                      set_bit(STRIPE_EXPAND_READY,
++                                              &sh2->state);
++                                      set_bit(STRIPE_HANDLE, &sh2->state);
++                              }
++                              release_stripe(sh2);
++                      }
++      }
  
- static void
--lpfc_mbx_issue_link_down(struct lpfc_hba *phba) {
-+lpfc_mbx_issue_link_down(struct lpfc_hba *phba)
-+{
-       uint32_t control;
-       struct lpfc_sli *psli = &phba->sli;
+       spin_unlock(&sh->lock);
  
-       lpfc_linkdown(phba);
+@@ -3111,11 +2470,11 @@
+               rcu_read_unlock();
  
-       /* turn on Link Attention interrupts - no CLEAR_LA needed */
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       psli->sli_flag |= LPFC_PROCESS_LA;
-       control = readl(phba->HCregaddr);
-       control |= HC_LAINT_ENA;
-       writel(control, phba->HCregaddr);
-       readl(phba->HCregaddr); /* flush */
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
- }
+               if (rdev) {
+-                      if (s.syncing || s.expanding || s.expanded)
++                      if (syncing || expanding || expanded)
+                               md_sync_acct(rdev->bdev, STRIPE_SECTORS);
  
- /*
-@@ -838,22 +1089,21 @@
-  * handed off to the SLI layer.
-  */
- void
--lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
-+lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
- {
-+      struct lpfc_vport *vport = pmb->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-       READ_LA_VAR *la;
-       MAILBOX_t *mb = &pmb->mb;
-       struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
+                       bi->bi_bdev = rdev->bdev;
+-                      pr_debug("for %llu schedule op %ld on disc %d\n",
++                      PRINTK("for %llu schedule op %ld on disc %d\n",
+                               (unsigned long long)sh->sector, bi->bi_rw, i);
+                       atomic_inc(&sh->count);
+                       bi->bi_sector = sh->sector + rdev->data_offset;
+@@ -3135,7 +2494,7 @@
+               } else {
+                       if (rw == WRITE)
+                               set_bit(STRIPE_DEGRADED, &sh->state);
+-                      pr_debug("skip op %ld on disc %d for sector %llu\n",
++                      PRINTK("skip op %ld on disc %d for sector %llu\n",
+                               bi->bi_rw, i, (unsigned long long)sh->sector);
+                       clear_bit(R5_LOCKED, &sh->dev[i].flags);
+                       set_bit(STRIPE_HANDLE, &sh->state);
+@@ -3379,7 +2738,7 @@
+       }
  
-       /* Check for error */
-       if (mb->mbxStatus) {
--              lpfc_printf_log(phba,
--                              KERN_INFO,
--                              LOG_LINK_EVENT,
-+              lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
-                               "%d:1307 READ_LA mbox error x%x state x%x\n",
--                              phba->brd_no,
--                              mb->mbxStatus, phba->hba_state);
-+                              phba->brd_no, mb->mbxStatus, vport->port_state);
-               lpfc_mbx_issue_link_down(phba);
--              phba->hba_state = LPFC_HBA_ERROR;
-+              phba->link_state = LPFC_HBA_ERROR;
-               goto lpfc_mbx_cmpl_read_la_free_mbuf;
+-      pr_debug("raid5_align_endio : io error...handing IO for a retry\n");
++      PRINTK("raid5_align_endio : io error...handing IO for a retry\n");
+       add_bio_to_retry(raid_bi, conf);
+       return 0;
+@@ -3417,7 +2776,7 @@
+       mdk_rdev_t *rdev;
+       if (!in_chunk_boundary(mddev, raid_bio)) {
+-              pr_debug("chunk_aligned_read : non aligned\n");
++              PRINTK("chunk_aligned_read : non aligned\n");
+               return 0;
        }
+       /*
+@@ -3541,7 +2900,7 @@
  
-@@ -861,27 +1111,26 @@
+               new_sector = raid5_compute_sector(logical_sector, disks, data_disks,
+                                                 &dd_idx, &pd_idx, conf);
+-              pr_debug("raid5: make_request, sector %llu logical %llu\n",
++              PRINTK("raid5: make_request, sector %llu logical %llu\n",
+                       (unsigned long long)new_sector, 
+                       (unsigned long long)logical_sector);
  
-       memcpy(&phba->alpa_map[0], mp->virt, 128);
+@@ -3914,7 +3273,7 @@
+       raid5_conf_t *conf = mddev_to_conf(mddev);
+       int handled;
  
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       if (la->pb)
--              phba->fc_flag |= FC_BYPASSED_MODE;
-+              vport->fc_flag |= FC_BYPASSED_MODE;
-       else
--              phba->fc_flag &= ~FC_BYPASSED_MODE;
--      spin_unlock_irq(phba->host->host_lock);
-+              vport->fc_flag &= ~FC_BYPASSED_MODE;
-+      spin_unlock_irq(shost->host_lock);
+-      pr_debug("+++ raid5d active\n");
++      PRINTK("+++ raid5d active\n");
  
-       if (((phba->fc_eventTag + 1) < la->eventTag) ||
-            (phba->fc_eventTag == la->eventTag)) {
-               phba->fc_stat.LinkMultiEvent++;
--              if (la->attType == AT_LINK_UP) {
-+              if (la->attType == AT_LINK_UP)
-                       if (phba->fc_eventTag != 0)
-                               lpfc_linkdown(phba);
+       md_check_recovery(mddev);
+@@ -3949,10 +3308,8 @@
+                       handled++;
                }
--      }
  
-       phba->fc_eventTag = la->eventTag;
+-              if (list_empty(&conf->handle_list)) {
+-                      async_tx_issue_pending_all();
++              if (list_empty(&conf->handle_list))
+                       break;
+-              }
  
-       if (la->attType == AT_LINK_UP) {
-               phba->fc_stat.LinkUp++;
--              if (phba->fc_flag & FC_LOOPBACK_MODE) {
-+              if (phba->link_flag & LS_LOOPBACK_MODE) {
-                       lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
-                               "%d:1306 Link Up Event in loop back mode "
-                               "x%x received Data: x%x x%x x%x x%x\n",
-@@ -903,7 +1152,7 @@
-                               "%d:1305 Link Down Event x%x received "
-                               "Data: x%x x%x x%x\n",
-                               phba->brd_no, la->eventTag, phba->fc_eventTag,
--                              phba->hba_state, phba->fc_flag);
-+                              phba->pport->port_state, vport->fc_flag);
-               lpfc_mbx_issue_link_down(phba);
+               first = conf->handle_list.next;
+               sh = list_entry(first, struct stripe_head, lru);
+@@ -3968,13 +3325,13 @@
+               spin_lock_irq(&conf->device_lock);
        }
+-      pr_debug("%d stripes handled\n", handled);
++      PRINTK("%d stripes handled\n", handled);
  
-@@ -921,31 +1170,115 @@
-  * handed off to the SLI layer.
-  */
- void
--lpfc_mbx_cmpl_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
-+lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
- {
--      struct lpfc_sli *psli;
--      MAILBOX_t *mb;
--      struct lpfc_dmabuf *mp;
--      struct lpfc_nodelist *ndlp;
--
--      psli = &phba->sli;
--      mb = &pmb->mb;
--
--      ndlp = (struct lpfc_nodelist *) pmb->context2;
--      mp = (struct lpfc_dmabuf *) (pmb->context1);
-+      struct lpfc_vport  *vport = pmb->vport;
-+      struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
-+      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
+       spin_unlock_irq(&conf->device_lock);
  
-       pmb->context1 = NULL;
+       unplug_slaves(mddev);
  
-       /* Good status, call state machine */
--      lpfc_disc_state_machine(phba, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN);
-+      lpfc_disc_state_machine(vport, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN);
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
--      mempool_free( pmb, phba->mbox_mem_pool);
-+      mempool_free(pmb, phba->mbox_mem_pool);
-       lpfc_nlp_put(ndlp);
+-      pr_debug("--- raid5d inactive\n");
++      PRINTK("--- raid5d inactive\n");
+ }
  
-       return;
+ static ssize_t
+@@ -4150,7 +3507,7 @@
+       atomic_set(&conf->preread_active_stripes, 0);
+       atomic_set(&conf->active_aligned_reads, 0);
+-      pr_debug("raid5: run(%s) called.\n", mdname(mddev));
++      PRINTK("raid5: run(%s) called.\n", mdname(mddev));
+       ITERATE_RDEV(mddev,rdev,tmp) {
+               raid_disk = rdev->raid_disk;
+@@ -4333,7 +3690,7 @@
+       return 0;
  }
  
-+static void
-+lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
-+{
-+      MAILBOX_t *mb = &pmb->mb;
-+      struct lpfc_vport *vport = pmb->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+
-+      switch (mb->mbxStatus) {
-+      case 0x0011:
-+      case 0x0020:
-+      case 0x9700:
-+              lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
-+                              "%d (%d):0911 cmpl_unreg_vpi, "
-+                              "mb status = 0x%x\n",
-+                              phba->brd_no, vport->vpi, mb->mbxStatus);
-+              break;
-+      }
-+      vport->unreg_vpi_cmpl = VPORT_OK;
-+      mempool_free(pmb, phba->mbox_mem_pool);
-+      /*
-+       * This shost reference might have been taken at the beginning of
-+       * lpfc_vport_delete()
-+       */
-+      if (vport->load_flag & FC_UNLOADING)
-+              scsi_host_put(shost);
-+}
+-#ifdef DEBUG
++#if RAID5_DEBUG
+ static void print_sh (struct seq_file *seq, struct stripe_head *sh)
+ {
+       int i;
+@@ -4380,7 +3737,7 @@
+                              conf->disks[i].rdev &&
+                              test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_");
+       seq_printf (seq, "]");
+-#ifdef DEBUG
++#if RAID5_DEBUG
+       seq_printf (seq, "\n");
+       printall(seq, conf);
+ #endif
+diff -Nurb linux-2.6.22-590/drivers/md/xor.c linux-2.6.22-570/drivers/md/xor.c
+--- linux-2.6.22-590/drivers/md/xor.c  1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/md/xor.c  2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,154 @@
++/*
++ * xor.c : Multiple Devices driver for Linux
++ *
++ * Copyright (C) 1996, 1997, 1998, 1999, 2000,
++ * Ingo Molnar, Matti Aarnio, Jakub Jelinek, Richard Henderson.
++ *
++ * Dispatch optimized RAID-5 checksumming functions.
++ *
++ * 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, or (at your option)
++ * any later version.
++ *
++ * You should have received a copy of the GNU General Public License
++ * (for example /usr/src/linux/COPYING); if not, write to the Free
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#define BH_TRACE 0
++#include <linux/module.h>
++#include <linux/raid/md.h>
++#include <linux/raid/xor.h>
++#include <asm/xor.h>
++
++/* The xor routines to use.  */
++static struct xor_block_template *active_template;
 +
 +void
-+lpfc_mbx_unreg_vpi(struct lpfc_vport *vport)
++xor_block(unsigned int count, unsigned int bytes, void **ptr)
 +{
-+      struct lpfc_hba  *phba = vport->phba;
-+      LPFC_MBOXQ_t *mbox;
-+      int rc;
++      unsigned long *p0, *p1, *p2, *p3, *p4;
 +
-+      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (!mbox)
++      p0 = (unsigned long *) ptr[0];
++      p1 = (unsigned long *) ptr[1];
++      if (count == 2) {
++              active_template->do_2(bytes, p0, p1);
 +              return;
++      }
 +
-+      lpfc_unreg_vpi(phba, vport->vpi, mbox);
-+      mbox->vport = vport;
-+      mbox->mbox_cmpl = lpfc_mbx_cmpl_unreg_vpi;
-+      rc = lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
-+      if (rc == MBX_NOT_FINISHED) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_VPORT,
-+                              "%d (%d):1800 Could not issue unreg_vpi\n",
-+                              phba->brd_no, vport->vpi);
-+              mempool_free(mbox, phba->mbox_mem_pool);
-+              vport->unreg_vpi_cmpl = VPORT_ERROR;
++      p2 = (unsigned long *) ptr[2];
++      if (count == 3) {
++              active_template->do_3(bytes, p0, p1, p2);
++              return;
++      }
++
++      p3 = (unsigned long *) ptr[3];
++      if (count == 4) {
++              active_template->do_4(bytes, p0, p1, p2, p3);
++              return;
 +      }
++
++      p4 = (unsigned long *) ptr[4];
++      active_template->do_5(bytes, p0, p1, p2, p3, p4);
 +}
 +
++/* Set of all registered templates.  */
++static struct xor_block_template *template_list;
++
++#define BENCH_SIZE (PAGE_SIZE)
++
 +static void
-+lpfc_mbx_cmpl_reg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
-+{
-+      struct lpfc_vport *vport = pmb->vport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+      MAILBOX_t *mb = &pmb->mb;
-+
-+      switch (mb->mbxStatus) {
-+      case 0x0011:
-+      case 0x9601:
-+      case 0x9602:
-+              lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
-+                              "%d (%d):0912 cmpl_reg_vpi, mb status = 0x%x\n",
-+                              phba->brd_no, vport->vpi, mb->mbxStatus);
-+              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+              spin_lock_irq(shost->host_lock);
-+              vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
-+              spin_unlock_irq(shost->host_lock);
-+              vport->fc_myDID = 0;
-+              goto out;
++do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
++{
++      int speed;
++      unsigned long now;
++      int i, count, max;
++
++      tmpl->next = template_list;
++      template_list = tmpl;
++
++      /*
++       * Count the number of XORs done during a whole jiffy, and use
++       * this to calculate the speed of checksumming.  We use a 2-page
++       * allocation to have guaranteed color L1-cache layout.
++       */
++      max = 0;
++      for (i = 0; i < 5; i++) {
++              now = jiffies;
++              count = 0;
++              while (jiffies == now) {
++                      mb();
++                      tmpl->do_2(BENCH_SIZE, b1, b2);
++                      mb();
++                      count++;
++                      mb();
++              }
++              if (count > max)
++                      max = count;
 +      }
 +
-+      vport->num_disc_nodes = 0;
-+      /* go thru NPR list and issue ELS PLOGIs */
-+      if (vport->fc_npr_cnt)
-+              lpfc_els_disc_plogi(vport);
++      speed = max * (HZ * BENCH_SIZE / 1024);
++      tmpl->speed = speed;
 +
-+      if (!vport->num_disc_nodes) {
-+              spin_lock_irq(shost->host_lock);
-+              vport->fc_flag &= ~FC_NDISC_ACTIVE;
-+              spin_unlock_irq(shost->host_lock);
-+              lpfc_can_disctmo(vport);
++      printk("   %-10s: %5d.%03d MB/sec\n", tmpl->name,
++             speed / 1000, speed % 1000);
++}
++
++static int
++calibrate_xor_block(void)
++{
++      void *b1, *b2;
++      struct xor_block_template *f, *fastest;
++
++      b1 = (void *) __get_free_pages(GFP_KERNEL, 2);
++      if (! b1) {
++              printk("raid5: Yikes!  No memory available.\n");
++              return -ENOMEM;
 +      }
-+      vport->port_state = LPFC_VPORT_READY;
++      b2 = b1 + 2*PAGE_SIZE + BENCH_SIZE;
 +
-+out:
-+      mempool_free(pmb, phba->mbox_mem_pool);
-+      return;
++      /*
++       * If this arch/cpu has a short-circuited selection, don't loop through all
++       * the possible functions, just test the best one
++       */
++
++      fastest = NULL;
++
++#ifdef XOR_SELECT_TEMPLATE
++              fastest = XOR_SELECT_TEMPLATE(fastest);
++#endif
++
++#define xor_speed(templ)      do_xor_speed((templ), b1, b2)
++
++      if (fastest) {
++              printk(KERN_INFO "raid5: automatically using best checksumming function: %s\n",
++                      fastest->name);
++              xor_speed(fastest);
++      } else {
++              printk(KERN_INFO "raid5: measuring checksumming speed\n");
++              XOR_TRY_TEMPLATES;
++              fastest = template_list;
++              for (f = fastest; f; f = f->next)
++                      if (f->speed > fastest->speed)
++                              fastest = f;
++      }
++
++      printk("raid5: using function: %s (%d.%03d MB/sec)\n",
++             fastest->name, fastest->speed / 1000, fastest->speed % 1000);
++
++#undef xor_speed
++
++      free_pages((unsigned long)b1, 2);
++
++      active_template = fastest;
++      return 0;
 +}
 +
++static __exit void xor_exit(void) { }
++
++EXPORT_SYMBOL(xor_block);
++MODULE_LICENSE("GPL");
++
++module_init(calibrate_xor_block);
++module_exit(xor_exit);
+diff -Nurb linux-2.6.22-590/drivers/media/dvb/dvb-core/dvb_frontend.c linux-2.6.22-570/drivers/media/dvb/dvb-core/dvb_frontend.c
+--- linux-2.6.22-590/drivers/media/dvb/dvb-core/dvb_frontend.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/media/dvb/dvb-core/dvb_frontend.c 2007-07-08 19:32:17.000000000 -0400
+@@ -523,7 +523,6 @@
+       dvb_frontend_init(fe);
+-      set_freezable();
+       while (1) {
+               up(&fepriv->sem);           /* is locked when we enter the thread... */
+ restart:
+diff -Nurb linux-2.6.22-590/drivers/media/video/cx88/cx88-tvaudio.c linux-2.6.22-570/drivers/media/video/cx88/cx88-tvaudio.c
+--- linux-2.6.22-590/drivers/media/video/cx88/cx88-tvaudio.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/media/video/cx88/cx88-tvaudio.c   2007-07-08 19:32:17.000000000 -0400
+@@ -906,7 +906,6 @@
+       u32 mode = 0;
+       dprintk("cx88: tvaudio thread started\n");
+-      set_freezable();
+       for (;;) {
+               msleep_interruptible(1000);
+               if (kthread_should_stop())
+diff -Nurb linux-2.6.22-590/drivers/media/video/msp3400-kthreads.c linux-2.6.22-570/drivers/media/video/msp3400-kthreads.c
+--- linux-2.6.22-590/drivers/media/video/msp3400-kthreads.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/media/video/msp3400-kthreads.c    2007-07-08 19:32:17.000000000 -0400
+@@ -23,7 +23,6 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/i2c.h>
+-#include <linux/freezer.h>
+ #include <linux/videodev.h>
+ #include <linux/videodev2.h>
+ #include <media/v4l2-common.h>
+@@ -469,7 +468,6 @@
+       v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
+-      set_freezable();
+       for (;;) {
+               v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
+               msp_sleep(state, -1);
+@@ -648,7 +646,7 @@
+       int val, i, std, count;
+       v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
+-      set_freezable();
++
+       for (;;) {
+               v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
+               msp_sleep(state,-1);
+@@ -942,7 +940,7 @@
+       int val, i;
+       v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
+-      set_freezable();
++
+       for (;;) {
+               v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
+               msp_sleep(state, -1);
+diff -Nurb linux-2.6.22-590/drivers/media/video/tvaudio.c linux-2.6.22-570/drivers/media/video/tvaudio.c
+--- linux-2.6.22-590/drivers/media/video/tvaudio.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/media/video/tvaudio.c     2007-07-08 19:32:17.000000000 -0400
+@@ -271,7 +271,7 @@
+       struct CHIPDESC  *desc = chiplist + chip->type;
+       v4l_dbg(1, debug, &chip->c, "%s: thread started\n", chip->c.name);
+-      set_freezable();
++
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (!kthread_should_stop())
+diff -Nurb linux-2.6.22-590/drivers/media/video/video-buf-dvb.c linux-2.6.22-570/drivers/media/video/video-buf-dvb.c
+--- linux-2.6.22-590/drivers/media/video/video-buf-dvb.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/media/video/video-buf-dvb.c       2007-07-08 19:32:17.000000000 -0400
+@@ -47,7 +47,6 @@
+       int err;
+       dprintk("dvb thread started\n");
+-      set_freezable();
+       videobuf_read_start(&dvb->dvbq);
+       for (;;) {
+diff -Nurb linux-2.6.22-590/drivers/media/video/vivi.c linux-2.6.22-570/drivers/media/video/vivi.c
+--- linux-2.6.22-590/drivers/media/video/vivi.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/media/video/vivi.c        2007-07-08 19:32:17.000000000 -0400
+@@ -573,7 +573,6 @@
+       dprintk(1,"thread started\n");
+       mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+-      set_freezable();
+       for (;;) {
+               vivi_sleep(dma_q);
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/linux_compat.h linux-2.6.22-570/drivers/message/fusion/linux_compat.h
+--- linux-2.6.22-590/drivers/message/fusion/linux_compat.h     1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/linux_compat.h     2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,9 @@
++/* drivers/message/fusion/linux_compat.h */
++
++#ifndef FUSION_LINUX_COMPAT_H
++#define FUSION_LINUX_COMPAT_H
++
++#include <linux/version.h>
++#include <scsi/scsi_device.h>
++
++#endif /* _LINUX_COMPAT_H */
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/lsi/mpi.h linux-2.6.22-570/drivers/message/fusion/lsi/mpi.h
+--- linux-2.6.22-590/drivers/message/fusion/lsi/mpi.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/lsi/mpi.h  2007-07-08 19:32:17.000000000 -0400
+@@ -1,12 +1,12 @@
  /*
-  * This routine handles processing a Fabric REG_LOGIN mailbox
-  * command upon completion. It is setup in the LPFC_MBOXQ
-@@ -953,20 +1286,14 @@
-  * handed off to the SLI layer.
+- *  Copyright (c) 2000-2007 LSI Logic Corporation.
++ *  Copyright (c) 2000-2006 LSI Logic Corporation.
+  *
+  *
+  *           Name:  mpi.h
+  *          Title:  MPI Message independent structures and definitions
+  *  Creation Date:  July 27, 2000
+  *
+- *    mpi.h Version:  01.05.13
++ *    mpi.h Version:  01.05.12
+  *
+  *  Version History
+  *  ---------------
+@@ -78,7 +78,6 @@
+  *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
+  *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
+  *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
+- *  05-24-07  01.05.13  Bumped MPI_HEADER_VERSION_UNIT.
+  *  --------------------------------------------------------------------------
   */
- void
--lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
-+lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
- {
--      struct lpfc_sli *psli;
--      MAILBOX_t *mb;
--      struct lpfc_dmabuf *mp;
-+      struct lpfc_vport *vport = pmb->vport;
-+      struct lpfc_vport *next_vport;
-+      MAILBOX_t *mb = &pmb->mb;
-+      struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
-       struct lpfc_nodelist *ndlp;
--      struct lpfc_nodelist *ndlp_fdmi;
--
+@@ -109,7 +108,7 @@
+ /* Note: The major versions of 0xe0 through 0xff are reserved */
+ /* versioning for this MPI header set */
+-#define MPI_HEADER_VERSION_UNIT             (0x10)
++#define MPI_HEADER_VERSION_UNIT             (0x0E)
+ #define MPI_HEADER_VERSION_DEV              (0x00)
+ #define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
+ #define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/lsi/mpi_cnfg.h linux-2.6.22-570/drivers/message/fusion/lsi/mpi_cnfg.h
+--- linux-2.6.22-590/drivers/message/fusion/lsi/mpi_cnfg.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/lsi/mpi_cnfg.h     2007-07-08 19:32:17.000000000 -0400
+@@ -1,12 +1,12 @@
+ /*
+- *  Copyright (c) 2000-2007 LSI Logic Corporation.
++ *  Copyright (c) 2000-2006 LSI Logic Corporation.
+  *
+  *
+  *           Name:  mpi_cnfg.h
+  *          Title:  MPI Config message, structures, and Pages
+  *  Creation Date:  July 27, 2000
+  *
+- *    mpi_cnfg.h Version:  01.05.15
++ *    mpi_cnfg.h Version:  01.05.13
+  *
+  *  Version History
+  *  ---------------
+@@ -293,21 +293,6 @@
+  *                      Added more AccessStatus values for SAS Device Page 0.
+  *                      Added bit for SATA Asynchronous Notification Support in
+  *                      Flags field of SAS Device Page 0.
+- *  02-28-07  01.05.14  Added ExtFlags field to Manufacturing Page 4.
+- *                      Added Disable SMART Polling for CapabilitiesFlags of
+- *                      IOC Page 6.
+- *                      Added Disable SMART Polling to DeviceSettings of BIOS
+- *                      Page 1.
+- *                      Added Multi-Port Domain bit for DiscoveryStatus field
+- *                      of SAS IO Unit Page.
+- *                      Added Multi-Port Domain Illegal flag for SAS IO Unit
+- *                      Page 1 AdditionalControlFlags field.
+- *  05-24-07  01.05.15  Added Hide Physical Disks with Non-Integrated RAID
+- *                      Metadata bit to Manufacturing Page 4 ExtFlags field.
+- *                      Added Internal Connector to End Device Present bit to
+- *                      Expander Page 0 Flags field.
+- *                      Fixed define for
+- *                      MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED.
+  *  --------------------------------------------------------------------------
+  */
+@@ -654,7 +639,7 @@
+     U8                              InfoSize1;          /* 0Bh */
+     U8                              InquirySize;        /* 0Ch */
+     U8                              Flags;              /* 0Dh */
+-    U16                             ExtFlags;           /* 0Eh */
++    U16                             Reserved2;          /* 0Eh */
+     U8                              InquiryData[56];    /* 10h */
+     U32                             ISVolumeSettings;   /* 48h */
+     U32                             IMEVolumeSettings;  /* 4Ch */
+@@ -673,7 +658,7 @@
+ } CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
+   ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
+-#define MPI_MANUFACTURING4_PAGEVERSION                  (0x05)
++#define MPI_MANUFACTURING4_PAGEVERSION                  (0x04)
+ /* defines for the Flags field */
+ #define MPI_MANPAGE4_FORCE_BAD_BLOCK_TABLE              (0x80)
+@@ -685,12 +670,6 @@
+ #define MPI_MANPAGE4_IM_RESYNC_CACHE_ENABLE             (0x02)
+ #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA                 (0x01)
+-/* defines for the ExtFlags field */
+-#define MPI_MANPAGE4_EXTFLAGS_HIDE_NON_IR_METADATA      (0x0008)
+-#define MPI_MANPAGE4_EXTFLAGS_SAS_CACHE_DISABLE         (0x0004)
+-#define MPI_MANPAGE4_EXTFLAGS_SATA_CACHE_DISABLE        (0x0002)
+-#define MPI_MANPAGE4_EXTFLAGS_LEGACY_MODE               (0x0001)
 -
--      psli = &phba->sli;
--      mb = &pmb->mb;
+ #ifndef MPI_MANPAGE5_NUM_FORCEWWID
+ #define MPI_MANPAGE5_NUM_FORCEWWID      (1)
+@@ -802,7 +781,7 @@
+ } CONFIG_PAGE_MANUFACTURING_9, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_9,
+   ManufacturingPage9_t, MPI_POINTER pManufacturingPage9_t;
+-#define MPI_MANUFACTURING9_PAGEVERSION                  (0x00)
++#define MPI_MANUFACTURING6_PAGEVERSION                  (0x00)
+ typedef struct _CONFIG_PAGE_MANUFACTURING_10
+@@ -1159,8 +1138,6 @@
+ /* IOC Page 6 Capabilities Flags */
+-#define MPI_IOCPAGE6_CAP_FLAGS_DISABLE_SMART_POLLING    (0x00000008)
 -
-       ndlp = (struct lpfc_nodelist *) pmb->context2;
--      mp = (struct lpfc_dmabuf *) (pmb->context1);
+ #define MPI_IOCPAGE6_CAP_FLAGS_MASK_METADATA_SIZE       (0x00000006)
+ #define MPI_IOCPAGE6_CAP_FLAGS_64MB_METADATA_SIZE       (0x00000000)
+ #define MPI_IOCPAGE6_CAP_FLAGS_512MB_METADATA_SIZE      (0x00000002)
+@@ -1231,7 +1208,6 @@
+ #define MPI_BIOSPAGE1_IOCSET_ALTERNATE_CHS              (0x00000008)
  
-       pmb->context1 = NULL;
-       pmb->context2 = NULL;
-@@ -977,60 +1304,46 @@
-               mempool_free(pmb, phba->mbox_mem_pool);
-               lpfc_nlp_put(ndlp);
+ /* values for the DeviceSettings field */
+-#define MPI_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING      (0x00000010)
+ #define MPI_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN            (0x00000008)
+ #define MPI_BIOSPAGE1_DEVSET_DISABLE_RM_LUN             (0x00000004)
+ #define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN         (0x00000002)
+@@ -2305,11 +2281,11 @@
+ typedef struct _CONFIG_PAGE_RAID_VOL_1
+ {
+     CONFIG_PAGE_HEADER      Header;         /* 00h */
+-    U8                      VolumeID;       /* 04h */
+-    U8                      VolumeBus;      /* 05h */
+-    U8                      VolumeIOC;      /* 06h */
+-    U8                      Reserved0;      /* 07h */
+-    U8                      GUID[24];       /* 08h */
++    U8                      VolumeID;       /* 01h */
++    U8                      VolumeBus;      /* 02h */
++    U8                      VolumeIOC;      /* 03h */
++    U8                      Reserved0;      /* 04h */
++    U8                      GUID[24];       /* 05h */
+     U8                      Name[32];       /* 20h */
+     U64                     WWID;           /* 40h */
+     U32                     Reserved1;      /* 48h */
+@@ -2364,7 +2340,7 @@
+ } RAID_PHYS_DISK0_STATUS, MPI_POINTER PTR_RAID_PHYS_DISK0_STATUS,
+   RaidPhysDiskStatus_t, MPI_POINTER pRaidPhysDiskStatus_t;
  
--              /* FLOGI failed, so just use loop map to make discovery list */
--              lpfc_disc_list_loopmap(phba);
-+              if (phba->fc_topology == TOPOLOGY_LOOP) {
-+                      /* FLOGI failed, use loop map to make discovery list */
-+                      lpfc_disc_list_loopmap(vport);
+-/* RAID Physical Disk PhysDiskStatus flags */
++/* RAID Volume 2 IM Physical Disk DiskStatus flags */
  
-               /* Start discovery */
--              lpfc_disc_start(phba);
-+                      lpfc_disc_start(vport);
-+                      return;
-+              }
-+
-+              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+              lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
-+                      "%d (%d):0258 Register Fabric login error: 0x%x\n",
-+                      phba->brd_no, vport->vpi, mb->mbxStatus);
-+
-               return;
-       }
+ #define MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC           (0x01)
+ #define MPI_PHYSDISK0_STATUS_FLAG_QUIESCED              (0x02)
+@@ -2568,7 +2544,6 @@
+ #define MPI_SAS_IOUNIT0_DS_TABLE_LINK                       (0x00000400)
+ #define MPI_SAS_IOUNIT0_DS_UNSUPPORTED_DEVICE               (0x00000800)
+ #define MPI_SAS_IOUNIT0_DS_MAX_SATA_TARGETS                 (0x00001000)
+-#define MPI_SAS_IOUNIT0_DS_MULTI_PORT_DOMAIN                (0x00002000)
  
-       ndlp->nlp_rpi = mb->un.varWords[0];
-       ndlp->nlp_type |= NLP_FABRIC;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
  
-       lpfc_nlp_put(ndlp);     /* Drop the reference from the mbox */
+ typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA
+@@ -2632,7 +2607,6 @@
+ #define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION           (0x0001)
  
--      if (phba->hba_state == LPFC_FABRIC_CFG_LINK) {
--              /* This NPort has been assigned an NPort_ID by the fabric as a
--               * result of the completed fabric login.  Issue a State Change
--               * Registration (SCR) ELS request to the fabric controller
--               * (SCR_DID) so that this NPort gets RSCN events from the
--               * fabric.
--               */
--              lpfc_issue_els_scr(phba, SCR_DID, 0);
-+      if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
-+              list_for_each_entry(next_vport, &phba->port_list, listentry) {
-+                      if (next_vport->port_type == LPFC_PHYSICAL_PORT)
-+                              continue;
+ /* values for SAS IO Unit Page 1 AdditionalControlFlags */
+-#define MPI_SAS_IOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL          (0x0080)
+ #define MPI_SAS_IOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION    (0x0040)
+ #define MPI_SAS_IOUNIT1_ACONTROL_HIDE_NONZERO_ATTACHED_PHY_IDENT    (0x0020)
+ #define MPI_SAS_IOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET   (0x0010)
+@@ -2760,7 +2734,6 @@
+ #define MPI_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE         (0x00000800)
  
--              ndlp = lpfc_findnode_did(phba, NameServer_DID);
--              if (!ndlp) {
--                      /* Allocate a new node instance. If the pool is empty,
--                       * start the discovery process and skip the Nameserver
--                       * login process.  This is attempted again later on.
--                       * Otherwise, issue a Port Login (PLOGI) to NameServer.
--                       */
--                      ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
--                      if (!ndlp) {
--                              lpfc_disc_start(phba);
--                              lpfc_mbuf_free(phba, mp->virt, mp->phys);
--                              kfree(mp);
--                              mempool_free(pmb, phba->mbox_mem_pool);
--                              return;
--                      } else {
--                              lpfc_nlp_init(phba, ndlp, NameServer_DID);
--                              ndlp->nlp_type |= NLP_FABRIC;
--                      }
--              }
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
--              lpfc_issue_els_plogi(phba, NameServer_DID, 0);
--              if (phba->cfg_fdmi_on) {
--                      ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
--                                                              GFP_KERNEL);
--                      if (ndlp_fdmi) {
--                              lpfc_nlp_init(phba, ndlp_fdmi, FDMI_DID);
--                              ndlp_fdmi->nlp_type |= NLP_FABRIC;
--                              ndlp_fdmi->nlp_state = NLP_STE_PLOGI_ISSUE;
--                              lpfc_issue_els_plogi(phba, FDMI_DID, 0);
-+                      if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
-+                              lpfc_initial_fdisc(next_vport);
-+                      else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
-+                              lpfc_vport_set_state(vport,
-+                                                   FC_VPORT_NO_FABRIC_SUPP);
-+                              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                                              "%d (%d):0259 No NPIV Fabric "
-+                                              "support\n",
-+                                              phba->brd_no, vport->vpi);
-                       }
-               }
-+              lpfc_do_scr_ns_plogi(phba, vport);
-       }
+ /* values for SAS Expander Page 0 Flags field */
+-#define MPI_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE    (0x04)
+ #define MPI_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG      (0x02)
+ #define MPI_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS      (0x01)
  
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-@@ -1046,32 +1359,36 @@
-  * handed off to the SLI layer.
-  */
- void
--lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
-+lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
- {
--      struct lpfc_sli *psli;
--      MAILBOX_t *mb;
--      struct lpfc_dmabuf *mp;
--      struct lpfc_nodelist *ndlp;
--
--      psli = &phba->sli;
--      mb = &pmb->mb;
--
--      ndlp = (struct lpfc_nodelist *) pmb->context2;
--      mp = (struct lpfc_dmabuf *) (pmb->context1);
-+      MAILBOX_t *mb = &pmb->mb;
-+      struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
-+      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
-+      struct lpfc_vport *vport = pmb->vport;
+@@ -2801,7 +2774,7 @@
+ /* see mpi_sas.h for values for SAS Expander Page 1 AttachedDeviceInfo values */
  
-       if (mb->mbxStatus) {
-+out:
-               lpfc_nlp_put(ndlp);
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
-               mempool_free(pmb, phba->mbox_mem_pool);
--              lpfc_drop_node(phba, ndlp);
-+              lpfc_drop_node(vport, ndlp);
+ /* values for SAS Expander Page 1 DiscoveryInfo field */
+-#define MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED     (0x04)
++#define MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY DISABLED     (0x04)
+ #define MPI_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE   (0x02)
+ #define MPI_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES   (0x01)
  
--              /* RegLogin failed, so just use loop map to make discovery
--                 list */
--              lpfc_disc_list_loopmap(phba);
-+              if (phba->fc_topology == TOPOLOGY_LOOP) {
-+                      /*
-+                       * RegLogin failed, use loop map to make discovery
-+                       * list
-+                       */
-+                      lpfc_disc_list_loopmap(vport);
+@@ -2922,11 +2895,11 @@
+     U8                                  AttachedPhyIdentifier;  /* 16h */
+     U8                                  Reserved2;              /* 17h */
+     U32                                 AttachedDeviceInfo;     /* 18h */
+-    U8                                  ProgrammedLinkRate;     /* 1Ch */
+-    U8                                  HwLinkRate;             /* 1Dh */
+-    U8                                  ChangeCount;            /* 1Eh */
+-    U8                                  Flags;                  /* 1Fh */
+-    U32                                 PhyInfo;                /* 20h */
++    U8                                  ProgrammedLinkRate;     /* 20h */
++    U8                                  HwLinkRate;             /* 21h */
++    U8                                  ChangeCount;            /* 22h */
++    U8                                  Flags;                  /* 23h */
++    U32                                 PhyInfo;                /* 24h */
+ } CONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0,
+   SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t;
  
-               /* Start discovery */
--              lpfc_disc_start(phba);
-+                      lpfc_disc_start(vport);
-+                      return;
-+              }
-+              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                      "%d (%d):0260 Register NameServer error: 0x%x\n",
-+                      phba->brd_no, vport->vpi, mb->mbxStatus);
-               return;
-       }
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/lsi/mpi_history.txt linux-2.6.22-570/drivers/message/fusion/lsi/mpi_history.txt
+--- linux-2.6.22-590/drivers/message/fusion/lsi/mpi_history.txt        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/lsi/mpi_history.txt        2007-07-08 19:32:17.000000000 -0400
+@@ -3,28 +3,28 @@
+  MPI Header File Change History
+  ==============================
  
-@@ -1079,37 +1396,43 @@
+- Copyright (c) 2000-2007 LSI Logic Corporation.
++ Copyright (c) 2000-2006 LSI Logic Corporation.
  
-       ndlp->nlp_rpi = mb->un.varWords[0];
-       ndlp->nlp_type |= NLP_FABRIC;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
--      if (phba->hba_state < LPFC_HBA_READY) {
--              /* Link up discovery requires Fabrib registration. */
--              lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RNN_ID);
--              lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RSNN_NN);
--              lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFT_ID);
--              lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFF_ID);
-+      if (vport->port_state < LPFC_VPORT_READY) {
-+              /* Link up discovery requires Fabric registration. */
-+              lpfc_ns_cmd(vport, SLI_CTNS_RFF_ID, 0, 0); /* Do this first! */
-+              lpfc_ns_cmd(vport, SLI_CTNS_RNN_ID, 0, 0);
-+              lpfc_ns_cmd(vport, SLI_CTNS_RSNN_NN, 0, 0);
-+              lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0);
-+              lpfc_ns_cmd(vport, SLI_CTNS_RFT_ID, 0, 0);
-+
-+              /* Issue SCR just before NameServer GID_FT Query */
-+              lpfc_issue_els_scr(vport, SCR_DID, 0);
-       }
--      phba->fc_ns_retry = 0;
-+      vport->fc_ns_retry = 0;
-       /* Good status, issue CT Request to NameServer */
--      if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT)) {
-+      if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0)) {
-               /* Cannot issue NameServer Query, so finish up discovery */
--              lpfc_disc_start(phba);
-+              goto out;
-       }
+  ---------------------------------------
+- Header Set Release Version:    01.05.16
+- Header Set Release Date:       05-24-07
++ Header Set Release Version:    01.05.14
++ Header Set Release Date:       10-11-06
+  ---------------------------------------
  
-       lpfc_nlp_put(ndlp);
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
--      mempool_free( pmb, phba->mbox_mem_pool);
-+      mempool_free(pmb, phba->mbox_mem_pool);
+  Filename               Current version     Prior version
+  ----------             ---------------     -------------
+- mpi.h                  01.05.13            01.05.12
+- mpi_ioc.h              01.05.14            01.05.13
+- mpi_cnfg.h             01.05.15            01.05.14
+- mpi_init.h             01.05.09            01.05.09
++ mpi.h                  01.05.12            01.05.11
++ mpi_ioc.h              01.05.12            01.05.11
++ mpi_cnfg.h             01.05.13            01.05.12
++ mpi_init.h             01.05.08            01.05.07
+  mpi_targ.h             01.05.06            01.05.06
+  mpi_fc.h               01.05.01            01.05.01
+  mpi_lan.h              01.05.01            01.05.01
+- mpi_raid.h             01.05.03            01.05.03
++ mpi_raid.h             01.05.02            01.05.02
+  mpi_tool.h             01.05.03            01.05.03
+  mpi_inb.h              01.05.01            01.05.01
+- mpi_sas.h              01.05.04            01.05.04
++ mpi_sas.h              01.05.04            01.05.03
+  mpi_type.h             01.05.02            01.05.02
+- mpi_history.txt        01.05.14            01.05.14
++ mpi_history.txt        01.05.14            01.05.13
  
-       return;
- }
  
- static void
--lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
-+lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-       struct fc_rport *rport;
-       struct lpfc_rport_data *rdata;
-       struct fc_rport_identifiers rport_ids;
-+      struct lpfc_hba  *phba = vport->phba;
+  *  Date      Version   Description
+@@ -95,7 +95,6 @@
+  *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
+  *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
+  *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
+- *  05-24-07  01.05.13  Bumped MPI_HEADER_VERSION_UNIT.
+  *  --------------------------------------------------------------------------
  
-       /* Remote port has reappeared. Re-register w/ FC transport */
-       rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
-@@ -1125,10 +1448,15 @@
-        * registered the port.
-        */
-       if (ndlp->rport && ndlp->rport->dd_data &&
--          *(struct lpfc_rport_data **) ndlp->rport->dd_data) {
-+          ((struct lpfc_rport_data *) ndlp->rport->dd_data)->pnode == ndlp) {
-               lpfc_nlp_put(ndlp);
-       }
--      ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
-+              "rport add:       did:x%x flg:x%x type x%x",
-+              ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
-+
-+      ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids);
-       if (!rport || !get_device(&rport->dev)) {
-               dev_printk(KERN_WARNING, &phba->pcidev->dev,
-                          "Warning: fc_remote_port_add failed\n");
-@@ -1154,22 +1482,17 @@
-               (rport->scsi_target_id < LPFC_MAX_TARGET)) {
-               ndlp->nlp_sid = rport->scsi_target_id;
-       }
--
-       return;
- }
+ mpi_ioc.h
+@@ -192,13 +191,6 @@
+  *                      data structure.
+  *                      Added new ImageType values for FWDownload and FWUpload
+  *                      requests.
+- *  02-28-07  01.05.13  Added MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT for SAS
+- *                      Broadcast Event Data (replacing _RESERVED2).
+- *                      For Discovery Error Event Data DiscoveryStatus field,
+- *                      replaced _MULTPL_PATHS with _UNSUPPORTED_DEVICE and
+- *                      added _MULTI_PORT_DOMAIN.
+- *  05-24-07  01.05.14  Added Common Boot Block type to FWDownload Request.
+- *                      Added Common Boot Block type to FWUpload Request.
+  *  --------------------------------------------------------------------------
  
- static void
--lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
-+lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp)
- {
-       struct fc_rport *rport = ndlp->rport;
--      struct lpfc_rport_data *rdata = rport->dd_data;
+ mpi_cnfg.h
+@@ -481,21 +473,6 @@
+  *                      Added more AccessStatus values for SAS Device Page 0.
+  *                      Added bit for SATA Asynchronous Notification Support in
+  *                      Flags field of SAS Device Page 0.
+- *  02-28-07  01.05.14  Added ExtFlags field to Manufacturing Page 4.
+- *                      Added Disable SMART Polling for CapabilitiesFlags of
+- *                      IOC Page 6.
+- *                      Added Disable SMART Polling to DeviceSettings of BIOS
+- *                      Page 1.
+- *                      Added Multi-Port Domain bit for DiscoveryStatus field
+- *                      of SAS IO Unit Page.
+- *                      Added Multi-Port Domain Illegal flag for SAS IO Unit
+- *                      Page 1 AdditionalControlFlags field.
+- *  05-24-07  01.05.15  Added Hide Physical Disks with Non-Integrated RAID
+- *                      Metadata bit to Manufacturing Page 4 ExtFlags field.
+- *                      Added Internal Connector to End Device Present bit to
+- *                      Expander Page 0 Flags field.
+- *                      Fixed define for
+- *                      MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED.
+  *  --------------------------------------------------------------------------
  
--      if (rport->scsi_target_id == -1) {
--              ndlp->rport = NULL;
--              rdata->pnode = NULL;
--              lpfc_nlp_put(ndlp);
--              put_device(&rport->dev);
--      }
-+      lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT,
-+              "rport delete:    did:x%x flg:x%x type x%x",
-+              ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
+ mpi_init.h
+@@ -540,8 +517,6 @@
+  *                      unique in the first 32 characters.
+  *  03-27-06  01.05.07  Added Task Management type of Clear ACA.
+  *  10-11-06  01.05.08  Shortened define for Task Management type of Clear ACA.
+- *  02-28-07  01.05.09  Defined two new MsgFlags bits for SCSI Task Management
+- *                      Request: Do Not Send Task IU and Soft Reset Option.
+  *  --------------------------------------------------------------------------
  
-       fc_remote_port_delete(rport);
+ mpi_targ.h
+@@ -596,7 +571,7 @@
+  *  11-02-00  01.01.01  Original release for post 1.0 work
+  *  12-04-00  01.01.02  Added messages for Common Transport Send and
+  *                      Primitive Send.
+- *  01-09-01  01.01.03  Modifed some of the new flags to have an MPI prefix
++ *  01-09-01  01.01.03  Modified some of the new flags to have an MPI prefix
+  *                      and modified the FcPrimitiveSend flags.
+  *  01-25-01  01.01.04  Move InitiatorIndex in LinkServiceRsp reply to a larger
+  *                      field.
+@@ -659,8 +634,6 @@
+  *  08-19-04  01.05.01  Original release for MPI v1.5.
+  *  01-15-05  01.05.02  Added defines for the two new RAID Actions for
+  *                      _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
+- *  02-28-07  01.05.03  Added new RAID Action, Device FW Update Mode, and
+- *                      associated defines.
+  *  --------------------------------------------------------------------------
  
-@@ -1177,42 +1500,46 @@
- }
+ mpi_tool.h
+@@ -709,22 +682,7 @@
  
- static void
--lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count)
-+lpfc_nlp_counters(struct lpfc_vport *vport, int state, int count)
- {
--      spin_lock_irq(phba->host->host_lock);
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-+      spin_lock_irq(shost->host_lock);
-       switch (state) {
-       case NLP_STE_UNUSED_NODE:
--              phba->fc_unused_cnt += count;
-+              vport->fc_unused_cnt += count;
-               break;
-       case NLP_STE_PLOGI_ISSUE:
--              phba->fc_plogi_cnt += count;
-+              vport->fc_plogi_cnt += count;
-               break;
-       case NLP_STE_ADISC_ISSUE:
--              phba->fc_adisc_cnt += count;
-+              vport->fc_adisc_cnt += count;
-               break;
-       case NLP_STE_REG_LOGIN_ISSUE:
--              phba->fc_reglogin_cnt += count;
-+              vport->fc_reglogin_cnt += count;
-               break;
-       case NLP_STE_PRLI_ISSUE:
--              phba->fc_prli_cnt += count;
-+              vport->fc_prli_cnt += count;
-               break;
-       case NLP_STE_UNMAPPED_NODE:
--              phba->fc_unmap_cnt += count;
-+              vport->fc_unmap_cnt += count;
-               break;
-       case NLP_STE_MAPPED_NODE:
--              phba->fc_map_cnt += count;
-+              vport->fc_map_cnt += count;
-               break;
-       case NLP_STE_NPR_NODE:
--              phba->fc_npr_cnt += count;
-+              vport->fc_npr_cnt += count;
-               break;
-       }
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
- }
+ mpi_history.txt         Parts list history
  
- static void
--lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
-+lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-                      int old_state, int new_state)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-Filename    01.05.15   01.05.15
+-----------  --------   --------
+-mpi.h       01.05.12   01.05.13
+-mpi_ioc.h   01.05.13   01.05.14
+-mpi_cnfg.h  01.05.14   01.05.15
+-mpi_init.h  01.05.09   01.05.09
+-mpi_targ.h  01.05.06   01.05.06
+-mpi_fc.h    01.05.01   01.05.01
+-mpi_lan.h   01.05.01   01.05.01
+-mpi_raid.h  01.05.03   01.05.03
+-mpi_tool.h  01.05.03   01.05.03
+-mpi_inb.h   01.05.01   01.05.01
+-mpi_sas.h   01.05.04   01.05.04
+-mpi_type.h  01.05.02   01.05.02
+-
+-Filename    01.05.14   01.05.13   01.05.12   01.05.11   01.05.10   01.05.09
++Filename    01.05.13   01.05.13   01.05.12   01.05.11   01.05.10   01.05.09
+ ----------  --------   --------   --------   --------   --------   --------
+ mpi.h       01.05.12   01.05.11   01.05.10   01.05.09   01.05.08   01.05.07
+ mpi_ioc.h   01.05.12   01.05.11   01.05.10   01.05.09   01.05.09   01.05.08
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/lsi/mpi_inb.h linux-2.6.22-570/drivers/message/fusion/lsi/mpi_inb.h
+--- linux-2.6.22-590/drivers/message/fusion/lsi/mpi_inb.h      1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/lsi/mpi_inb.h      2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,221 @@
++/*
++ *  Copyright (c) 2003-2004 LSI Logic Corporation.
++ *
++ *
++ *           Name:  mpi_inb.h
++ *          Title:  MPI Inband structures and definitions
++ *  Creation Date:  September 30, 2003
++ *
++ *    mpi_inb.h Version:  01.05.01
++ *
++ *  Version History
++ *  ---------------
++ *
++ *  Date      Version   Description
++ *  --------  --------  ------------------------------------------------------
++ *  05-11-04  01.03.01  Original release.
++ *  08-19-04  01.05.01  Original release for MPI v1.5.
++ *  --------------------------------------------------------------------------
++ */
 +
-       if (new_state == NLP_STE_UNMAPPED_NODE) {
-               ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
-               ndlp->nlp_flag &= ~NLP_NODEV_REMOVE;
-@@ -1226,21 +1553,20 @@
-       /* Transport interface */
-       if (ndlp->rport && (old_state == NLP_STE_MAPPED_NODE ||
-                           old_state == NLP_STE_UNMAPPED_NODE)) {
--              phba->nport_event_cnt++;
--              lpfc_unregister_remote_port(phba, ndlp);
-+              vport->phba->nport_event_cnt++;
-+              lpfc_unregister_remote_port(ndlp);
-       }
++#ifndef MPI_INB_H
++#define MPI_INB_H
++
++/******************************************************************************
++*
++*        I n b a n d    M e s s a g e s
++*
++*******************************************************************************/
++
++
++/****************************************************************************/
++/* Inband Buffer Post Request                                               */
++/****************************************************************************/
++
++typedef struct _MSG_INBAND_BUFFER_POST_REQUEST
++{
++    U8                      Reserved1;          /* 00h */
++    U8                      BufferCount;        /* 01h */
++    U8                      ChainOffset;        /* 02h */
++    U8                      Function;           /* 03h */
++    U16                     Reserved2;          /* 04h */
++    U8                      Reserved3;          /* 06h */
++    U8                      MsgFlags;           /* 07h */
++    U32                     MsgContext;         /* 08h */
++    U32                     Reserved4;          /* 0Ch */
++    SGE_TRANS_SIMPLE_UNION  SGL;                /* 10h */
++} MSG_INBAND_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_INBAND_BUFFER_POST_REQUEST,
++  MpiInbandBufferPostRequest_t , MPI_POINTER pMpiInbandBufferPostRequest_t;
++
++
++typedef struct _WWN_FC_FORMAT
++{
++    U64                     NodeName;           /* 00h */
++    U64                     PortName;           /* 08h */
++} WWN_FC_FORMAT, MPI_POINTER PTR_WWN_FC_FORMAT,
++  WwnFcFormat_t, MPI_POINTER pWwnFcFormat_t;
++
++typedef struct _WWN_SAS_FORMAT
++{
++    U64                     WorldWideID;        /* 00h */
++    U32                     Reserved1;          /* 08h */
++    U32                     Reserved2;          /* 0Ch */
++} WWN_SAS_FORMAT, MPI_POINTER PTR_WWN_SAS_FORMAT,
++  WwnSasFormat_t, MPI_POINTER pWwnSasFormat_t;
++
++typedef union _WWN_INBAND_FORMAT
++{
++    WWN_FC_FORMAT           Fc;
++    WWN_SAS_FORMAT          Sas;
++} WWN_INBAND_FORMAT, MPI_POINTER PTR_WWN_INBAND_FORMAT,
++  WwnInbandFormat, MPI_POINTER pWwnInbandFormat;
++
++
++/* Inband Buffer Post reply message */
++
++typedef struct _MSG_INBAND_BUFFER_POST_REPLY
++{
++    U16                     Reserved1;          /* 00h */
++    U8                      MsgLength;          /* 02h */
++    U8                      Function;           /* 03h */
++    U16                     Reserved2;          /* 04h */
++    U8                      Reserved3;          /* 06h */
++    U8                      MsgFlags;           /* 07h */
++    U32                     MsgContext;         /* 08h */
++    U16                     Reserved4;          /* 0Ch */
++    U16                     IOCStatus;          /* 0Eh */
++    U32                     IOCLogInfo;         /* 10h */
++    U32                     TransferLength;     /* 14h */
++    U32                     TransactionContext; /* 18h */
++    WWN_INBAND_FORMAT       Wwn;                /* 1Ch */
++    U32                     IOCIdentifier[4];   /* 2Ch */
++} MSG_INBAND_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_INBAND_BUFFER_POST_REPLY,
++  MpiInbandBufferPostReply_t, MPI_POINTER pMpiInbandBufferPostReply_t;
++
++
++/****************************************************************************/
++/* Inband Send Request                                                      */
++/****************************************************************************/
++
++typedef struct _MSG_INBAND_SEND_REQUEST
++{
++    U16                     Reserved1;          /* 00h */
++    U8                      ChainOffset;        /* 02h */
++    U8                      Function;           /* 03h */
++    U16                     Reserved2;          /* 04h */
++    U8                      Reserved3;          /* 06h */
++    U8                      MsgFlags;           /* 07h */
++    U32                     MsgContext;         /* 08h */
++    U32                     Reserved4;          /* 0Ch */
++    WWN_INBAND_FORMAT       Wwn;                /* 10h */
++    U32                     Reserved5;          /* 20h */
++    SGE_IO_UNION            SGL;                /* 24h */
++} MSG_INBAND_SEND_REQUEST, MPI_POINTER PTR_MSG_INBAND_SEND_REQUEST,
++  MpiInbandSendRequest_t , MPI_POINTER pMpiInbandSendRequest_t;
++
++
++/* Inband Send reply message */
++
++typedef struct _MSG_INBAND_SEND_REPLY
++{
++    U16                     Reserved1;          /* 00h */
++    U8                      MsgLength;          /* 02h */
++    U8                      Function;           /* 03h */
++    U16                     Reserved2;          /* 04h */
++    U8                      Reserved3;          /* 06h */
++    U8                      MsgFlags;           /* 07h */
++    U32                     MsgContext;         /* 08h */
++    U16                     Reserved4;          /* 0Ch */
++    U16                     IOCStatus;          /* 0Eh */
++    U32                     IOCLogInfo;         /* 10h */
++    U32                     ResponseLength;     /* 14h */
++} MSG_INBAND_SEND_REPLY, MPI_POINTER PTR_MSG_INBAND_SEND_REPLY,
++  MpiInbandSendReply_t, MPI_POINTER pMpiInbandSendReply_t;
++
++
++/****************************************************************************/
++/* Inband Response Request                                                  */
++/****************************************************************************/
++
++typedef struct _MSG_INBAND_RSP_REQUEST
++{
++    U16                     Reserved1;          /* 00h */
++    U8                      ChainOffset;        /* 02h */
++    U8                      Function;           /* 03h */
++    U16                     Reserved2;          /* 04h */
++    U8                      Reserved3;          /* 06h */
++    U8                      MsgFlags;           /* 07h */
++    U32                     MsgContext;         /* 08h */
++    U32                     Reserved4;          /* 0Ch */
++    WWN_INBAND_FORMAT       Wwn;                /* 10h */
++    U32                     IOCIdentifier[4];   /* 20h */
++    U32                     ResponseLength;     /* 30h */
++    SGE_IO_UNION            SGL;                /* 34h */
++} MSG_INBAND_RSP_REQUEST, MPI_POINTER PTR_MSG_INBAND_RSP_REQUEST,
++  MpiInbandRspRequest_t , MPI_POINTER pMpiInbandRspRequest_t;
++
++
++/* Inband Response reply message */
++
++typedef struct _MSG_INBAND_RSP_REPLY
++{
++    U16                     Reserved1;          /* 00h */
++    U8                      MsgLength;          /* 02h */
++    U8                      Function;           /* 03h */
++    U16                     Reserved2;          /* 04h */
++    U8                      Reserved3;          /* 06h */
++    U8                      MsgFlags;           /* 07h */
++    U32                     MsgContext;         /* 08h */
++    U16                     Reserved4;          /* 0Ch */
++    U16                     IOCStatus;          /* 0Eh */
++    U32                     IOCLogInfo;         /* 10h */
++} MSG_INBAND_RSP_REPLY, MPI_POINTER PTR_MSG_INBAND_RSP_REPLY,
++  MpiInbandRspReply_t, MPI_POINTER pMpiInbandRspReply_t;
++
++
++/****************************************************************************/
++/* Inband Abort Request                                                     */
++/****************************************************************************/
++
++typedef struct _MSG_INBAND_ABORT_REQUEST
++{
++    U8                      Reserved1;          /* 00h */
++    U8                      AbortType;          /* 01h */
++    U8                      ChainOffset;        /* 02h */
++    U8                      Function;           /* 03h */
++    U16                     Reserved2;          /* 04h */
++    U8                      Reserved3;          /* 06h */
++    U8                      MsgFlags;           /* 07h */
++    U32                     MsgContext;         /* 08h */
++    U32                     Reserved4;          /* 0Ch */
++    U32                     ContextToAbort;     /* 10h */
++} MSG_INBAND_ABORT_REQUEST, MPI_POINTER PTR_MSG_INBAND_ABORT_REQUEST,
++  MpiInbandAbortRequest_t , MPI_POINTER pMpiInbandAbortRequest_t;
++
++#define MPI_INBAND_ABORT_TYPE_ALL_BUFFERS       (0x00)
++#define MPI_INBAND_ABORT_TYPE_EXACT_BUFFER      (0x01)
++#define MPI_INBAND_ABORT_TYPE_SEND_REQUEST      (0x02)
++#define MPI_INBAND_ABORT_TYPE_RESPONSE_REQUEST  (0x03)
++
++
++/* Inband Abort reply message */
++
++typedef struct _MSG_INBAND_ABORT_REPLY
++{
++    U8                      Reserved1;          /* 00h */
++    U8                      AbortType;          /* 01h */
++    U8                      MsgLength;          /* 02h */
++    U8                      Function;           /* 03h */
++    U16                     Reserved2;          /* 04h */
++    U8                      Reserved3;          /* 06h */
++    U8                      MsgFlags;           /* 07h */
++    U32                     MsgContext;         /* 08h */
++    U16                     Reserved4;          /* 0Ch */
++    U16                     IOCStatus;          /* 0Eh */
++    U32                     IOCLogInfo;         /* 10h */
++} MSG_INBAND_ABORT_REPLY, MPI_POINTER PTR_MSG_INBAND_ABORT_REPLY,
++  MpiInbandAbortReply_t, MPI_POINTER pMpiInbandAbortReply_t;
++
++
++#endif
++
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/lsi/mpi_init.h linux-2.6.22-570/drivers/message/fusion/lsi/mpi_init.h
+--- linux-2.6.22-590/drivers/message/fusion/lsi/mpi_init.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/lsi/mpi_init.h     2007-07-08 19:32:17.000000000 -0400
+@@ -1,12 +1,12 @@
+ /*
+- *  Copyright (c) 2000-2007 LSI Logic Corporation.
++ *  Copyright (c) 2000-2006 LSI Logic Corporation.
+  *
+  *
+  *           Name:  mpi_init.h
+  *          Title:  MPI initiator mode messages and structures
+  *  Creation Date:  June 8, 2000
+  *
+- *    mpi_init.h Version:  01.05.09
++ *    mpi_init.h Version:  01.05.08
+  *
+  *  Version History
+  *  ---------------
+@@ -54,8 +54,6 @@
+  *                      unique in the first 32 characters.
+  *  03-27-06  01.05.07  Added Task Management type of Clear ACA.
+  *  10-11-06  01.05.08  Shortened define for Task Management type of Clear ACA.
+- *  02-28-07  01.05.09  Defined two new MsgFlags bits for SCSI Task Management
+- *                      Request: Do Not Send Task IU and Soft Reset Option.
+  *  --------------------------------------------------------------------------
+  */
  
-       if (new_state ==  NLP_STE_MAPPED_NODE ||
-           new_state == NLP_STE_UNMAPPED_NODE) {
--              phba->nport_event_cnt++;
-+              vport->phba->nport_event_cnt++;
-                       /*
-                        * Tell the fc transport about the port, if we haven't
-                        * already. If we have, and it's a scsi entity, be
-                        * sure to unblock any attached scsi devices
-                        */
--                      lpfc_register_remote_port(phba, ndlp);
-+              lpfc_register_remote_port(vport, ndlp);
-       }
--
-                       /*
-                        * if we added to Mapped list, but the remote port
-                        * registration failed or assigned a target id outside
-@@ -1251,10 +1577,10 @@
-           (!ndlp->rport ||
-            ndlp->rport->scsi_target_id == -1 ||
-            ndlp->rport->scsi_target_id >= LPFC_MAX_TARGET)) {
--              spin_lock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_TGT_NO_SCSIID;
--              spin_unlock_irq(phba->host->host_lock);
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
-+              spin_unlock_irq(shost->host_lock);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
-       }
- }
+@@ -434,14 +432,10 @@
+ #define MPI_SCSITASKMGMT_TASKTYPE_CLR_ACA               (0x08)
  
-@@ -1280,61 +1606,74 @@
- }
+ /* MsgFlags bits */
+-#define MPI_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU   (0x01)
+-
+ #define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION   (0x00)
+ #define MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION      (0x02)
+ #define MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION (0x04)
  
- void
--lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state)
-+lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                 int state)
+-#define MPI_SCSITASKMGMT_MSGFLAGS_SOFT_RESET_OPTION     (0x08)
+-
+ /* SCSI Task Management Reply */
+ typedef struct _MSG_SCSI_TASK_MGMT_REPLY
  {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-       int  old_state = ndlp->nlp_state;
-       char name1[16], name2[16];
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/lsi/mpi_ioc.h linux-2.6.22-570/drivers/message/fusion/lsi/mpi_ioc.h
+--- linux-2.6.22-590/drivers/message/fusion/lsi/mpi_ioc.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/lsi/mpi_ioc.h      2007-07-08 19:32:17.000000000 -0400
+@@ -1,12 +1,12 @@
+ /*
+- *  Copyright (c) 2000-2007 LSI Logic Corporation.
++ *  Copyright (c) 2000-2006 LSI Logic Corporation.
+  *
+  *
+  *           Name:  mpi_ioc.h
+  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
+  *  Creation Date:  August 11, 2000
+  *
+- *    mpi_ioc.h Version:  01.05.14
++ *    mpi_ioc.h Version:  01.05.12
+  *
+  *  Version History
+  *  ---------------
+@@ -106,13 +106,6 @@
+  *                      data structure.
+  *                      Added new ImageType values for FWDownload and FWUpload
+  *                      requests.
+- *  02-28-07  01.05.13  Added MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT for SAS
+- *                      Broadcast Event Data (replacing _RESERVED2).
+- *                      For Discovery Error Event Data DiscoveryStatus field,
+- *                      replaced _MULTPL_PATHS with _UNSUPPORTED_DEVICE and
+- *                      added _MULTI_PORT_DOMAIN.
+- *  05-24-07  01.05.14  Added Common Boot Block type to FWDownload Request.
+- *                      Added Common Boot Block type to FWUpload Request.
+  *  --------------------------------------------------------------------------
+  */
  
--      lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
--                      "%d:0904 NPort state transition x%06x, %s -> %s\n",
--                      phba->brd_no,
-+      lpfc_printf_log(vport->phba, KERN_INFO, LOG_NODE,
-+                      "%d (%d):0904 NPort state transition x%06x, %s -> %s\n",
-+                      vport->phba->brd_no, vport->vpi,
-                       ndlp->nlp_DID,
-                       lpfc_nlp_state_name(name1, sizeof(name1), old_state),
-                       lpfc_nlp_state_name(name2, sizeof(name2), state));
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE,
-+              "node statechg    did:x%x old:%d ste:%d",
-+              ndlp->nlp_DID, old_state, state);
-+
-       if (old_state == NLP_STE_NPR_NODE &&
-           (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 &&
-           state != NLP_STE_NPR_NODE)
--              lpfc_cancel_retry_delay_tmo(phba, ndlp);
-+              lpfc_cancel_retry_delay_tmo(vport, ndlp);
-       if (old_state == NLP_STE_UNMAPPED_NODE) {
-               ndlp->nlp_flag &= ~NLP_TGT_NO_SCSIID;
-               ndlp->nlp_type &= ~NLP_FC_NODE;
-       }
+@@ -799,7 +792,7 @@
  
-       if (list_empty(&ndlp->nlp_listp)) {
--              spin_lock_irq(phba->host->host_lock);
--              list_add_tail(&ndlp->nlp_listp, &phba->fc_nodes);
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-+              list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes);
-+              spin_unlock_irq(shost->host_lock);
-       } else if (old_state)
--              lpfc_nlp_counters(phba, old_state, -1);
-+              lpfc_nlp_counters(vport, old_state, -1);
+ #define MPI_EVENT_PRIMITIVE_CHANGE              (0x01)
+ #define MPI_EVENT_PRIMITIVE_EXPANDER            (0x03)
+-#define MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT  (0x04)
++#define MPI_EVENT_PRIMITIVE_RESERVED2           (0x04)
+ #define MPI_EVENT_PRIMITIVE_RESERVED3           (0x05)
+ #define MPI_EVENT_PRIMITIVE_RESERVED4           (0x06)
+ #define MPI_EVENT_PRIMITIVE_CHANGE0_RESERVED    (0x07)
+@@ -864,9 +857,8 @@
+ #define MPI_EVENT_DSCVRY_ERR_DS_SMP_CRC_ERROR               (0x00000100)
+ #define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_SUBTRACTIVE          (0x00000200)
+ #define MPI_EVENT_DSCVRY_ERR_DS_TABLE_TO_TABLE              (0x00000400)
+-#define MPI_EVENT_DSCVRY_ERR_DS_UNSUPPORTED_DEVICE          (0x00000800)
++#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS                (0x00000800)
+ #define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS            (0x00001000)
+-#define MPI_EVENT_DSCVRY_ERR_DS_MULTI_PORT_DOMAIN           (0x00002000)
  
-       ndlp->nlp_state = state;
--      lpfc_nlp_counters(phba, state, 1);
--      lpfc_nlp_state_cleanup(phba, ndlp, old_state, state);
-+      lpfc_nlp_counters(vport, state, 1);
-+      lpfc_nlp_state_cleanup(vport, ndlp, old_state, state);
- }
+ /* SAS SMP Error Event data */
  
- void
--lpfc_dequeue_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
-+lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-       if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
--              lpfc_cancel_retry_delay_tmo(phba, ndlp);
-+              lpfc_cancel_retry_delay_tmo(vport, ndlp);
-       if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
--              lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
--      spin_lock_irq(phba->host->host_lock);
-+              lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
-+      spin_lock_irq(shost->host_lock);
-       list_del_init(&ndlp->nlp_listp);
--      spin_unlock_irq(phba->host->host_lock);
--      lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0);
-+      spin_unlock_irq(shost->host_lock);
-+      lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state,
-+                             NLP_STE_UNUSED_NODE);
- }
+@@ -998,7 +990,6 @@
+ #define MPI_FW_DOWNLOAD_ITYPE_CONFIG_1          (0x07)
+ #define MPI_FW_DOWNLOAD_ITYPE_CONFIG_2          (0x08)
+ #define MPI_FW_DOWNLOAD_ITYPE_MEGARAID          (0x09)
+-#define MPI_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
  
- void
--lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
-+lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-       if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
--              lpfc_cancel_retry_delay_tmo(phba, ndlp);
-+              lpfc_cancel_retry_delay_tmo(vport, ndlp);
-       if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
--              lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
--      spin_lock_irq(phba->host->host_lock);
-+              lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
-+      spin_lock_irq(shost->host_lock);
-       list_del_init(&ndlp->nlp_listp);
--      spin_unlock_irq(phba->host->host_lock);
-+      ndlp->nlp_flag &= ~NLP_TARGET_REMOVE;
-+      spin_unlock_irq(shost->host_lock);
-       lpfc_nlp_put(ndlp);
- }
  
-@@ -1342,11 +1681,13 @@
-  * Start / ReStart rescue timer for Discovery / RSCN handling
-  */
- void
--lpfc_set_disctmo(struct lpfc_hba * phba)
-+lpfc_set_disctmo(struct lpfc_vport *vport)
+ typedef struct _FWDownloadTCSGE
+@@ -1058,7 +1049,6 @@
+ #define MPI_FW_UPLOAD_ITYPE_CONFIG_2        (0x08)
+ #define MPI_FW_UPLOAD_ITYPE_MEGARAID        (0x09)
+ #define MPI_FW_UPLOAD_ITYPE_COMPLETE        (0x0A)
+-#define MPI_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK   (0x0B)
+ typedef struct _FWUploadTCSGE
  {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-       uint32_t tmo;
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/lsi/mpi_raid.h linux-2.6.22-570/drivers/message/fusion/lsi/mpi_raid.h
+--- linux-2.6.22-590/drivers/message/fusion/lsi/mpi_raid.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/lsi/mpi_raid.h     2007-07-08 19:32:17.000000000 -0400
+@@ -1,12 +1,12 @@
+ /*
+- *  Copyright (c) 2001-2007 LSI Logic Corporation.
++ *  Copyright (c) 2001-2005 LSI Logic Corporation.
+  *
+  *
+  *           Name:  mpi_raid.h
+  *          Title:  MPI RAID message and structures
+  *  Creation Date:  February 27, 2001
+  *
+- *    mpi_raid.h Version:  01.05.03
++ *    mpi_raid.h Version:  01.05.02
+  *
+  *  Version History
+  *  ---------------
+@@ -32,8 +32,6 @@
+  *  08-19-04  01.05.01  Original release for MPI v1.5.
+  *  01-15-05  01.05.02  Added defines for the two new RAID Actions for
+  *                      _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
+- *  02-28-07  01.05.03  Added new RAID Action, Device FW Update Mode, and
+- *                      associated defines.
+  *  --------------------------------------------------------------------------
+  */
  
--      if (phba->hba_state == LPFC_LOCAL_CFG_LINK) {
-+      if (vport->port_state == LPFC_LOCAL_CFG_LINK) {
-               /* For FAN, timeout should be greater then edtov */
-               tmo = (((phba->fc_edtov + 999) / 1000) + 1);
-       } else {
-@@ -1356,18 +1697,25 @@
-               tmo = ((phba->fc_ratov * 3) + 3);
-       }
+@@ -92,7 +90,6 @@
+ #define MPI_RAID_ACTION_INACTIVATE_VOLUME           (0x12)
+ #define MPI_RAID_ACTION_SET_RESYNC_RATE             (0x13)
+ #define MPI_RAID_ACTION_SET_DATA_SCRUB_RATE         (0x14)
+-#define MPI_RAID_ACTION_DEVICE_FW_UPDATE_MODE       (0x15)
  
--      mod_timer(&phba->fc_disctmo, jiffies + HZ * tmo);
--      spin_lock_irq(phba->host->host_lock);
--      phba->fc_flag |= FC_DISC_TMO;
--      spin_unlock_irq(phba->host->host_lock);
-+
-+      if (!timer_pending(&vport->fc_disctmo)) {
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+                      "set disc timer:  tmo:x%x state:x%x flg:x%x",
-+                      tmo, vport->port_state, vport->fc_flag);
-+      }
-+
-+      mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo);
-+      spin_lock_irq(shost->host_lock);
-+      vport->fc_flag |= FC_DISC_TMO;
-+      spin_unlock_irq(shost->host_lock);
+ /* ActionDataWord defines for use with MPI_RAID_ACTION_CREATE_VOLUME action */
+ #define MPI_RAID_ACTION_ADATA_DO_NOT_SYNC           (0x00000001)
+@@ -114,10 +111,6 @@
+ /* ActionDataWord defines for use with MPI_RAID_ACTION_SET_DATA_SCRUB_RATE action */
+ #define MPI_RAID_ACTION_ADATA_DATA_SCRUB_RATE_MASK  (0x000000FF)
  
-       /* Start Discovery Timer state <hba_state> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                      "%d:0247 Start Discovery Timer state x%x "
-+                      "%d (%d):0247 Start Discovery Timer state x%x "
-                       "Data: x%x x%lx x%x x%x\n",
--                      phba->brd_no,
--                      phba->hba_state, tmo, (unsigned long)&phba->fc_disctmo,
--                      phba->fc_plogi_cnt, phba->fc_adisc_cnt);
-+                      phba->brd_no, vport->vpi, vport->port_state, tmo,
-+                      (unsigned long)&vport->fc_disctmo, vport->fc_plogi_cnt,
-+                      vport->fc_adisc_cnt);
+-/* ActionDataWord defines for use with MPI_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */
+-#define MPI_RAID_ACTION_ADATA_ENABLE_FW_UPDATE          (0x00000001)
+-#define MPI_RAID_ACTION_ADATA_MASK_FW_UPDATE_TIMEOUT    (0x0000FF00)
+-#define MPI_RAID_ACTION_ADATA_SHIFT_FW_UPDATE_TIMEOUT   (8)
  
-       return;
- }
-@@ -1376,23 +1724,34 @@
-  * Cancel rescue timer for Discovery / RSCN handling
+ /* RAID Action reply message */
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/mptbase.c linux-2.6.22-570/drivers/message/fusion/mptbase.c
+--- linux-2.6.22-590/drivers/message/fusion/mptbase.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/mptbase.c  2007-07-08 19:32:17.000000000 -0400
+@@ -6,7 +6,7 @@
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+  *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:DL-MPTFusionLinux@lsi.com)
++ *  (mailto:mpt_linux_developer@lsi.com)
+  *
   */
- int
--lpfc_can_disctmo(struct lpfc_hba * phba)
-+lpfc_can_disctmo(struct lpfc_vport *vport)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-+      unsigned long iflags;
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "can disc timer:  state:x%x rtry:x%x flg:x%x",
-+              vport->port_state, vport->fc_ns_retry, vport->fc_flag);
-+
-       /* Turn off discovery timer if its running */
--      if (phba->fc_flag & FC_DISC_TMO) {
--              spin_lock_irq(phba->host->host_lock);
--              phba->fc_flag &= ~FC_DISC_TMO;
--              spin_unlock_irq(phba->host->host_lock);
--              del_timer_sync(&phba->fc_disctmo);
--              phba->work_hba_events &= ~WORKER_DISC_TMO;
-+      if (vport->fc_flag & FC_DISC_TMO) {
-+              spin_lock_irqsave(shost->host_lock, iflags);
-+              vport->fc_flag &= ~FC_DISC_TMO;
-+              spin_unlock_irqrestore(shost->host_lock, iflags);
-+              del_timer_sync(&vport->fc_disctmo);
-+              spin_lock_irqsave(&vport->work_port_lock, iflags);
-+              vport->work_port_events &= ~WORKER_DISC_TMO;
-+              spin_unlock_irqrestore(&vport->work_port_lock, iflags);
-       }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -64,7 +64,6 @@
+ #endif
  
-       /* Cancel Discovery Timer state <hba_state> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                      "%d:0248 Cancel Discovery Timer state x%x "
-+                      "%d (%d):0248 Cancel Discovery Timer state x%x "
-                       "Data: x%x x%x x%x\n",
--                      phba->brd_no, phba->hba_state, phba->fc_flag,
--                      phba->fc_plogi_cnt, phba->fc_adisc_cnt);
-+                      phba->brd_no, vport->vpi, vport->port_state,
-+                      vport->fc_flag, vport->fc_plogi_cnt,
-+                      vport->fc_adisc_cnt);
+ #include "mptbase.h"
+-#include "lsi/mpi_log_fc.h"
  
-       return 0;
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ #define my_NAME               "Fusion MPT base driver"
+@@ -6350,37 +6349,14 @@
+ static void
+ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
+ {
+-      char *desc = "unknown";
+-
+-      switch (log_info & 0xFF000000) {
+-      case MPI_IOCLOGINFO_FC_INIT_BASE:
+-              desc = "FCP Initiator";
+-              break;
+-      case MPI_IOCLOGINFO_FC_TARGET_BASE:
+-              desc = "FCP Target";
+-              break;
+-      case MPI_IOCLOGINFO_FC_LAN_BASE:
+-              desc = "LAN";
+-              break;
+-      case MPI_IOCLOGINFO_FC_MSG_BASE:
+-              desc = "MPI Message Layer";
+-              break;
+-      case MPI_IOCLOGINFO_FC_LINK_BASE:
+-              desc = "FC Link";
+-              break;
+-      case MPI_IOCLOGINFO_FC_CTX_BASE:
+-              desc = "Context Manager";
+-              break;
+-      case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET:
+-              desc = "Invalid Field Offset";
+-              break;
+-      case MPI_IOCLOGINFO_FC_STATE_CHANGE:
+-              desc = "State Change Info";
+-              break;
+-      }
++      static char *subcl_str[8] = {
++              "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
++              "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
++      };
++      u8 subcl = (log_info >> 24) & 0x7;
+-      printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
+-                      ioc->name, log_info, desc, (log_info & 0xFFFFFF));
++      printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
++                      ioc->name, log_info, subcl_str[subcl]);
  }
-@@ -1402,15 +1761,18 @@
-  * Return true if iocb matches the specified nport
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/mptbase.h linux-2.6.22-570/drivers/message/fusion/mptbase.h
+--- linux-2.6.22-590/drivers/message/fusion/mptbase.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/mptbase.h  2007-07-08 19:32:17.000000000 -0400
+@@ -6,7 +6,7 @@
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+  *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:DL-MPTFusionLinux@lsi.com)
++ *  (mailto:mpt_linux_developer@lsi.com)
+  *
   */
- int
--lpfc_check_sli_ndlp(struct lpfc_hba * phba,
--                  struct lpfc_sli_ring * pring,
--                  struct lpfc_iocbq * iocb, struct lpfc_nodelist * ndlp)
-+lpfc_check_sli_ndlp(struct lpfc_hba *phba,
-+                  struct lpfc_sli_ring *pring,
-+                  struct lpfc_iocbq *iocb,
-+                  struct lpfc_nodelist *ndlp)
- {
--      struct lpfc_sli *psli;
--      IOCB_t *icmd;
-+      struct lpfc_sli *psli = &phba->sli;
-+      IOCB_t *icmd = &iocb->iocb;
-+      struct lpfc_vport    *vport = ndlp->vport;
-+
-+      if (iocb->vport != vport)
-+              return 0;
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -75,8 +75,8 @@
+ #define COPYRIGHT     "Copyright (c) 1999-2007 " MODULEAUTHOR
+ #endif
  
--      psli = &phba->sli;
--      icmd = &iocb->iocb;
-       if (pring->ringno == LPFC_ELS_RING) {
-               switch (icmd->ulpCommand) {
-               case CMD_GEN_REQUEST64_CR:
-@@ -1445,7 +1807,7 @@
-  * associated with nlp_rpi in the LPFC_NODELIST entry.
+-#define MPT_LINUX_VERSION_COMMON      "3.04.05"
+-#define MPT_LINUX_PACKAGE_NAME                "@(#)mptlinux-3.04.05"
++#define MPT_LINUX_VERSION_COMMON      "3.04.04"
++#define MPT_LINUX_PACKAGE_NAME                "@(#)mptlinux-3.04.04"
+ #define WHAT_MAGIC_STRING             "@" "(" "#" ")"
+ #define show_mptmod_ver(s,ver)  \
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/mptctl.c linux-2.6.22-570/drivers/message/fusion/mptctl.c
+--- linux-2.6.22-590/drivers/message/fusion/mptctl.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/mptctl.c   2007-07-08 19:32:17.000000000 -0400
+@@ -5,7 +5,7 @@
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+  *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:DL-MPTFusionLinux@lsi.com)
++ *  (mailto:mpt_linux_developer@lsi.com)
+  *
   */
- static int
--lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
-+lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
- {
-       LIST_HEAD(completions);
-       struct lpfc_sli *psli;
-@@ -1454,6 +1816,8 @@
-       IOCB_t *icmd;
-       uint32_t rpi, i;
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/mptctl.h linux-2.6.22-570/drivers/message/fusion/mptctl.h
+--- linux-2.6.22-590/drivers/message/fusion/mptctl.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/mptctl.h   2007-07-08 19:32:17.000000000 -0400
+@@ -6,7 +6,7 @@
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+  *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:DL-MPTFusionLinux@lsi.com)
++ *  (mailto:mpt_linux_developer@lsi.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/mptfc.c linux-2.6.22-570/drivers/message/fusion/mptfc.c
+--- linux-2.6.22-590/drivers/message/fusion/mptfc.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/mptfc.c    2007-07-08 19:32:17.000000000 -0400
+@@ -4,7 +4,7 @@
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+  *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:DL-MPTFusionLinux@lsi.com)
++ *  (mailto:mpt_linux_developer@lsi.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -43,6 +43,7 @@
+     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
++#include "linux_compat.h"     /* linux-2.6 tweaks */
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/mptlan.c linux-2.6.22-570/drivers/message/fusion/mptlan.c
+--- linux-2.6.22-590/drivers/message/fusion/mptlan.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/mptlan.c   2007-07-08 19:32:17.000000000 -0400
+@@ -5,7 +5,7 @@
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+  *  Copyright (c) 2000-2007 LSI Logic Corporation
+- *  (mailto:DL-MPTFusionLinux@lsi.com)
++ *  (mailto:mpt_linux_developer@lsi.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/mptlan.h linux-2.6.22-570/drivers/message/fusion/mptlan.h
+--- linux-2.6.22-590/drivers/message/fusion/mptlan.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/mptlan.h   2007-07-08 19:32:17.000000000 -0400
+@@ -5,7 +5,7 @@
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+  *  Copyright (c) 2000-2007 LSI Logic Corporation
+- *  (mailto:DL-MPTFusionLinux@lsi.com)
++ *  (mailto:mpt_linux_developer@lsi.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/mptsas.c linux-2.6.22-570/drivers/message/fusion/mptsas.c
+--- linux-2.6.22-590/drivers/message/fusion/mptsas.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/mptsas.c   2007-07-08 19:32:17.000000000 -0400
+@@ -4,7 +4,7 @@
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+  *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:DL-MPTFusionLinux@lsi.com)
++ *  (mailto:mpt_linux_developer@lsi.com)
+  *  Copyright (c) 2005-2007 Dell
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/mptscsih.c linux-2.6.22-570/drivers/message/fusion/mptscsih.c
+--- linux-2.6.22-590/drivers/message/fusion/mptscsih.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/mptscsih.c 2007-07-08 19:32:17.000000000 -0400
+@@ -4,7 +4,7 @@
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+  *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:DL-MPTFusionLinux@lsi.com)
++ *  (mailto:mpt_linux_developer@lsi.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -44,6 +44,7 @@
+ */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  
-+      lpfc_fabric_abort_nport(ndlp);
++#include "linux_compat.h"     /* linux-2.6 tweaks */
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+@@ -259,13 +260,30 @@
+       /* Map the data portion, if any.
+        * sges_left  = 0 if no data transfer.
+        */
+-      sges_left = scsi_dma_map(SCpnt);
+-      if (sges_left < 0)
++      if ( (sges_left = SCpnt->use_sg) ) {
++              sges_left = pci_map_sg(ioc->pcidev,
++                             (struct scatterlist *) SCpnt->request_buffer,
++                             SCpnt->use_sg,
++                             SCpnt->sc_data_direction);
++              if (sges_left == 0)
+                       return FAILED;
++      } else if (SCpnt->request_bufflen) {
++              SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
++                                    SCpnt->request_buffer,
++                                    SCpnt->request_bufflen,
++                                    SCpnt->sc_data_direction);
++              dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
++                              ioc->name, SCpnt, SCpnt->request_bufflen));
++              mptscsih_add_sge((char *) &pReq->SGL,
++                      0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
++                      SCpnt->SCp.dma_handle);
 +
-       /*
-        * Everything that matches on txcmplq will be returned
-        * by firmware with a no rpi error.
-@@ -1465,15 +1829,15 @@
-               for (i = 0; i < psli->num_rings; i++) {
-                       pring = &psli->ring[i];
++              return SUCCESS;
++      }
  
--                      spin_lock_irq(phba->host->host_lock);
-+                      spin_lock_irq(&phba->hbalock);
-                       list_for_each_entry_safe(iocb, next_iocb, &pring->txq,
-                                               list) {
-                               /*
-                                * Check to see if iocb matches the nport we are
-                                * looking for
-                                */
--                              if ((lpfc_check_sli_ndlp
--                                   (phba, pring, iocb, ndlp))) {
-+                              if ((lpfc_check_sli_ndlp(phba, pring, iocb,
-+                                                       ndlp))) {
-                                       /* It matches, so deque and call compl
-                                          with an error */
-                                       list_move_tail(&iocb->list,
-@@ -1481,22 +1845,22 @@
-                                       pring->txq_cnt--;
-                               }
-                       }
--                      spin_unlock_irq(phba->host->host_lock);
+       /* Handle the SG case.
+        */
+-      sg = scsi_sglist(SCpnt);
++      sg = (struct scatterlist *) SCpnt->request_buffer;
+       sg_done  = 0;
+       sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
+       chainSge = NULL;
+@@ -447,12 +465,7 @@
+       MPT_FRAME_HDR *mf;
+       SEPRequest_t     *SEPMsg;
+-      if (ioc->bus_type != SAS)
+-              return;
 -
-+                      spin_unlock_irq(&phba->hbalock);
-               }
-       }
+-      /* Not supported for hidden raid components
+-       */
+-      if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
++      if (ioc->bus_type == FC)
+               return;
  
-       while (!list_empty(&completions)) {
-               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
--              list_del(&iocb->list);
-+              list_del_init(&iocb->list);
+       if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
+@@ -649,7 +662,7 @@
+               scsi_state = pScsiReply->SCSIState;
+               scsi_status = pScsiReply->SCSIStatus;
+               xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
+-              scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
++              sc->resid = sc->request_bufflen - xfer_cnt;
+               log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
  
--              if (iocb->iocb_cmpl) {
-+              if (!iocb->iocb_cmpl)
-+                      lpfc_sli_release_iocbq(phba, iocb);
-+              else {
-                       icmd = &iocb->iocb;
-                       icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                       icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
--                      (iocb->iocb_cmpl) (phba, iocb, iocb);
--              } else
--                      lpfc_sli_release_iocbq(phba, iocb);
-+                      (iocb->iocb_cmpl)(phba, iocb, iocb);
-+              }
-       }
+               /*
+@@ -754,7 +767,7 @@
+                       break;
  
-       return 0;
-@@ -1512,19 +1876,22 @@
-  * we are waiting to PLOGI back to the remote NPort.
-  */
- int
--lpfc_unreg_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
-+lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
- {
-+      struct lpfc_hba *phba = vport->phba;
-       LPFC_MBOXQ_t *mbox;
-       int rc;
+               case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:      /* 0x0049 */
+-                      scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
++                      sc->resid = sc->request_bufflen - xfer_cnt;
+                       if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
+                               sc->result=DID_SOFT_ERROR << 16;
+                       else /* Sufficient data transfer occurred */
+@@ -803,7 +816,7 @@
+                       break;
  
-       if (ndlp->nlp_rpi) {
--              if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
--                      lpfc_unreg_login(phba, ndlp->nlp_rpi, mbox);
--                      mbox->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
--                      rc = lpfc_sli_issue_mbox
--                                  (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
-+              mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+              if (mbox) {
-+                      lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox);
-+                      mbox->vport = vport;
-+                      mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-+                      rc = lpfc_sli_issue_mbox(phba, mbox,
-+                                               (MBX_NOWAIT | MBX_STOP_IOCB));
-                       if (rc == MBX_NOT_FINISHED)
--                              mempool_free( mbox, phba->mbox_mem_pool);
-+                              mempool_free(mbox, phba->mbox_mem_pool);
+               case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:           /* 0x0044 */
+-                      scsi_set_resid(sc, 0);
++                      sc->resid=0;
+               case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
+               case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
+                       sc->result = (DID_OK << 16) | scsi_status;
+@@ -887,17 +900,22 @@
+                       dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d "
+                           "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
+-                                    sc->device->host->host_no,
+-                                    sc->device->channel, sc->device->id,
+-                                    sc->device->lun, scsi_get_resid(sc),
+-                                    scsi_bufflen(sc), xfer_cnt));
++                          sc->device->host->host_no, sc->device->channel, sc->device->id,
++                          sc->device->lun, sc->resid, sc->request_bufflen,
++                          xfer_cnt));
                }
-               lpfc_no_rpi(phba, ndlp);
-               ndlp->nlp_rpi = 0;
-@@ -1533,25 +1900,70 @@
-       return 0;
- }
+ #endif
  
-+void
-+lpfc_unreg_all_rpis(struct lpfc_vport *vport)
-+{
-+      struct lpfc_hba  *phba  = vport->phba;
-+      LPFC_MBOXQ_t     *mbox;
-+      int rc;
-+
-+      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (mbox) {
-+              lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox);
-+              mbox->vport = vport;
-+              mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-+              rc = lpfc_sli_issue_mbox(phba, mbox,
-+                                       (MBX_NOWAIT | MBX_STOP_IOCB));
-+              if (rc == MBX_NOT_FINISHED) {
-+                      mempool_free(mbox, phba->mbox_mem_pool);
-+              }
-+      }
-+}
-+
-+void
-+lpfc_unreg_default_rpis(struct lpfc_vport *vport)
-+{
-+      struct lpfc_hba  *phba  = vport->phba;
-+      LPFC_MBOXQ_t     *mbox;
-+      int rc;
-+
-+      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (mbox) {
-+              lpfc_unreg_did(phba, vport->vpi, 0xffffffff, mbox);
-+              mbox->vport = vport;
-+              mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-+              rc = lpfc_sli_issue_mbox(phba, mbox,
-+                                       (MBX_NOWAIT | MBX_STOP_IOCB));
-+              if (rc == MBX_NOT_FINISHED) {
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_VPORT,
-+                                      "%d (%d):1815 Could not issue "
-+                                      "unreg_did (default rpis)\n",
-+                                      phba->brd_no, vport->vpi);
-+                      mempool_free(mbox, phba->mbox_mem_pool);
-+              }
+       } /* end of address reply case */
+       /* Unmap the DMA buffers, if any. */
+-      scsi_dma_unmap(sc);
++      if (sc->use_sg) {
++              pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
++                          sc->use_sg, sc->sc_data_direction);
++      } else if (sc->request_bufflen) {
++              pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
++                              sc->request_bufflen, sc->sc_data_direction);
 +      }
-+}
-+
- /*
-  * Free resources associated with LPFC_NODELIST entry
-  * so it can be freed.
-  */
- static int
--lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
-+lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
- {
--      LPFC_MBOXQ_t       *mb;
--      LPFC_MBOXQ_t       *nextmb;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-+      LPFC_MBOXQ_t *mb, *nextmb;
-       struct lpfc_dmabuf *mp;
  
-       /* Cleanup node for NPort <nlp_DID> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
--                      "%d:0900 Cleanup node for NPort x%x "
-+                      "%d (%d):0900 Cleanup node for NPort x%x "
-                       "Data: x%x x%x x%x\n",
--                      phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
-+                      phba->brd_no, vport->vpi, ndlp->nlp_DID, ndlp->nlp_flag,
-                       ndlp->nlp_state, ndlp->nlp_rpi);
+       sc->scsi_done(sc);              /* Issue the command callback */
  
--      lpfc_dequeue_node(phba, ndlp);
-+      lpfc_dequeue_node(vport, ndlp);
+@@ -952,8 +970,17 @@
+                       /* Set status, free OS resources (SG DMA buffers)
+                        * Do OS callback
+                        */
+-                      scsi_dma_unmap(SCpnt);
+-
++                      if (SCpnt->use_sg) {
++                              pci_unmap_sg(ioc->pcidev,
++                                      (struct scatterlist *) SCpnt->request_buffer,
++                                      SCpnt->use_sg,
++                                      SCpnt->sc_data_direction);
++                      } else if (SCpnt->request_bufflen) {
++                              pci_unmap_single(ioc->pcidev,
++                                      SCpnt->SCp.dma_handle,
++                                      SCpnt->request_bufflen,
++                                      SCpnt->sc_data_direction);
++                      }
+                       SCpnt->result = DID_RESET << 16;
+                       SCpnt->host_scribble = NULL;
  
-       /* cleanup any ndlp on mbox q waiting for reglogin cmpl */
-       if ((mb = phba->sli.mbox_active)) {
-@@ -1562,13 +1974,13 @@
+@@ -996,19 +1023,14 @@
+                       mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
+                       if (mf == NULL)
+                               continue;
+-                      /* If the device is a hidden raid component, then its
+-                       * expected that the mf->function will be RAID_SCSI_IO
+-                       */
+-                      if (vdevice->vtarget->tflags &
+-                          MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function !=
+-                          MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)
+-                              continue;
+-
+                       int_to_scsilun(vdevice->lun, &lun);
+                       if ((mf->Bus != vdevice->vtarget->channel) ||
+                           (mf->TargetID != vdevice->vtarget->id) ||
+                           memcmp(lun.scsi_lun, mf->LUN, 8))
+                               continue;
++                      dsprintk(( "search_running: found (sc=%p, mf = %p) "
++                          "channel %d id %d, lun %d \n", hd->ScsiLookup[ii],
++                          mf, mf->Bus, mf->TargetID, vdevice->lun));
+                       /* Cleanup
+                        */
+@@ -1017,12 +1039,19 @@
+                       mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
+                       if ((unsigned char *)mf != sc->host_scribble)
+                               continue;
+-                      scsi_dma_unmap(sc);
++                      if (sc->use_sg) {
++                              pci_unmap_sg(hd->ioc->pcidev,
++                              (struct scatterlist *) sc->request_buffer,
++                                      sc->use_sg,
++                                      sc->sc_data_direction);
++                      } else if (sc->request_bufflen) {
++                              pci_unmap_single(hd->ioc->pcidev,
++                                      sc->SCp.dma_handle,
++                                      sc->request_bufflen,
++                                      sc->sc_data_direction);
++                      }
+                       sc->host_scribble = NULL;
+                       sc->result = DID_NO_CONNECT << 16;
+-                      dsprintk(( "search_running: found (sc=%p, mf = %p) "
+-                          "channel %d id %d, lun %d \n", sc, mf,
+-                          vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun));
+                       sc->scsi_done(sc);
                }
        }
+@@ -1351,10 +1380,10 @@
+        *    will be no data transfer!  GRRRRR...
+        */
+       if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
+-              datalen = scsi_bufflen(SCpnt);
++              datalen = SCpnt->request_bufflen;
+               scsidir = MPI_SCSIIO_CONTROL_READ;      /* DATA IN  (host<--ioc<--dev) */
+       } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
+-              datalen = scsi_bufflen(SCpnt);
++              datalen = SCpnt->request_bufflen;
+               scsidir = MPI_SCSIIO_CONTROL_WRITE;     /* DATA OUT (host-->ioc-->dev) */
+       } else {
+               datalen = 0;
+@@ -1739,45 +1768,20 @@
+       u32              ctx2abort;
+       int              scpnt_idx;
+       int              retval;
+-      VirtDevice       *vdevice;
++      VirtDevice       *vdev;
+       ulong            sn = SCpnt->serial_number;
+-      MPT_ADAPTER     *ioc;
  
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
-               if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
-                  (ndlp == (struct lpfc_nodelist *) mb->context2)) {
-                       mp = (struct lpfc_dmabuf *) (mb->context1);
-                       if (mp) {
--                              lpfc_mbuf_free(phba, mp->virt, mp->phys);
-+                              __lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                               kfree(mp);
-                       }
-                       list_del(&mb->list);
-@@ -1576,20 +1988,27 @@
-                       lpfc_nlp_put(ndlp);
-               }
+       /* If we can't locate our host adapter structure, return FAILED status.
+        */
+       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
+               SCpnt->result = DID_RESET << 16;
+               SCpnt->scsi_done(SCpnt);
+-              dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: Can't locate "
+-                  "host! (sc=%p)\n", SCpnt));
++              dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
++                         "Can't locate host! (sc=%p)\n",
++                         SCpnt));
+               return FAILED;
        }
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
  
-       lpfc_els_abort(phba,ndlp);
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag &= ~NLP_DELAY_TMO;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
+-      ioc = hd->ioc;
+-      printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n",
+-             ioc->name, SCpnt);
+-      scsi_print_command(SCpnt);
+-
+-      vdevice = SCpnt->device->hostdata;
+-      if (!vdevice || !vdevice->vtarget) {
+-              dtmprintk((MYIOC_s_DEBUG_FMT "task abort: device has been "
+-                  "deleted (sc=%p)\n", ioc->name, SCpnt));
+-              SCpnt->result = DID_NO_CONNECT << 16;
+-              SCpnt->scsi_done(SCpnt);
+-              retval = 0;
+-              goto out;
+-      }
+-
+-      /* Task aborts are not supported for hidden raid components.
+-       */
+-      if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
+-              dtmprintk((MYIOC_s_DEBUG_FMT "task abort: hidden raid "
+-                  "component (sc=%p)\n", ioc->name, SCpnt));
+-              SCpnt->result = DID_RESET << 16;
+-              retval = FAILED;
+-              goto out;
+-      }
+-
+       /* Find this command
+        */
+       if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
+@@ -1786,20 +1790,21 @@
+                */
+               SCpnt->result = DID_RESET << 16;
+               dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
+-                 "Command not in the active list! (sc=%p)\n", ioc->name,
+-                 SCpnt));
+-              retval = 0;
+-              goto out;
++                         "Command not in the active list! (sc=%p)\n",
++                         hd->ioc->name, SCpnt));
++              return SUCCESS;
+       }
  
-       ndlp->nlp_last_elscmd = 0;
-       del_timer_sync(&ndlp->nlp_delayfunc);
+-      if (hd->resetPending) {
+-              retval = FAILED;
+-              goto out;
+-      }
++      if (hd->resetPending)
++              return FAILED;
  
-       if (!list_empty(&ndlp->els_retry_evt.evt_listp))
-               list_del_init(&ndlp->els_retry_evt.evt_listp);
-+      if (!list_empty(&ndlp->dev_loss_evt.evt_listp))
-+              list_del_init(&ndlp->dev_loss_evt.evt_listp);
+       if (hd->timeouts < -1)
+               hd->timeouts++;
++      printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
++             hd->ioc->name, SCpnt);
++      scsi_print_command(SCpnt);
 +
-+      if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) {
-+              list_del_init(&ndlp->dev_loss_evt.evt_listp);
-+              complete((struct completion *)(ndlp->dev_loss_evt.evt_arg2));
-+      }
+       /* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
+        * (the IO to be ABORT'd)
+        *
+@@ -1812,17 +1817,18 @@
  
--      lpfc_unreg_rpi(phba, ndlp);
-+      lpfc_unreg_rpi(vport, ndlp);
+       hd->abortSCpnt = SCpnt;
  
-       return 0;
- }
-@@ -1600,18 +2019,22 @@
-  * machine, defer the free till we reach the end of the state machine.
-  */
- static void
--lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
-+lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
++      vdev = SCpnt->device->hostdata;
+       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
+-          vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
+-          ctx2abort, mptscsih_get_tm_timeout(ioc));
++              vdev->vtarget->channel, vdev->vtarget->id, vdev->lun,
++              ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
+       if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
+           SCpnt->serial_number == sn)
+               retval = FAILED;
+- out:
+-      printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
+-          ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
++      printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
++              hd->ioc->name,
++              ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+       if (retval == 0)
+               return SUCCESS;
+@@ -1844,47 +1850,32 @@
  {
-       struct lpfc_rport_data *rdata;
+       MPT_SCSI_HOST   *hd;
+       int              retval;
+-      VirtDevice       *vdevice;
+-      MPT_ADAPTER     *ioc;
++      VirtDevice       *vdev;
  
-       if (ndlp->nlp_flag & NLP_DELAY_TMO) {
--              lpfc_cancel_retry_delay_tmo(phba, ndlp);
-+              lpfc_cancel_retry_delay_tmo(vport, ndlp);
+       /* If we can't locate our host adapter structure, return FAILED status.
+        */
+       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
+-              dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: Can't "
+-                  "locate host! (sc=%p)\n", SCpnt));
++              dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
++                         "Can't locate host! (sc=%p)\n",
++                         SCpnt));
+               return FAILED;
        }
  
--      lpfc_cleanup_node(phba, ndlp);
-+      lpfc_cleanup_node(vport, ndlp);
+-      ioc = hd->ioc;
+-      printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n",
+-             ioc->name, SCpnt);
+-      scsi_print_command(SCpnt);
+-
+-      if (hd->resetPending) {
+-              retval = FAILED;
+-              goto out;
+-      }
+-
+-      vdevice = SCpnt->device->hostdata;
+-      if (!vdevice || !vdevice->vtarget) {
+-              retval = 0;
+-              goto out;
+-      }
++      if (hd->resetPending)
++              return FAILED;
  
--      if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
--              put_device(&ndlp->rport->dev);
-+      /*
-+       * We can get here with a non-NULL ndlp->rport because when we
-+       * unregister a rport we don't break the rport/node linkage.  So if we
-+       * do, make sure we don't leaving any dangling pointers behind.
-+       */
-+      if (ndlp->rport) {
-               rdata = ndlp->rport->dd_data;
-               rdata->pnode = NULL;
-               ndlp->rport = NULL;
-@@ -1619,11 +2042,10 @@
- }
+-      /* Target reset to hidden raid component is not supported
+-       */
+-      if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
+-              retval = FAILED;
+-              goto out;
+-      }
++      printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
++             hd->ioc->name, SCpnt);
++      scsi_print_command(SCpnt);
  
- static int
--lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
-+lpfc_matchdid(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+            uint32_t did)
- {
--      D_ID mydid;
--      D_ID ndlpdid;
--      D_ID matchdid;
-+      D_ID mydid, ndlpdid, matchdid;
++      vdev = SCpnt->device->hostdata;
+       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
+-          vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0,
+-          mptscsih_get_tm_timeout(ioc));
++              vdev->vtarget->channel, vdev->vtarget->id,
++              0, 0, mptscsih_get_tm_timeout(hd->ioc));
  
-       if (did == Bcast_DID)
-               return 0;
-@@ -1637,7 +2059,7 @@
-               return 1;
+- out:
+-      printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
+-          ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
++      printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
++              hd->ioc->name,
++              ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
  
-       /* Next check for area/domain identically equals 0 match */
--      mydid.un.word = phba->fc_myDID;
-+      mydid.un.word = vport->fc_myDID;
-       if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) {
-               return 0;
+       if (retval == 0)
+               return SUCCESS;
+@@ -1908,19 +1899,18 @@
+       MPT_SCSI_HOST   *hd;
+       int              retval;
+       VirtDevice       *vdev;
+-      MPT_ADAPTER     *ioc;
+       /* If we can't locate our host adapter structure, return FAILED status.
+        */
+       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
+-              dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: Can't "
+-                  "locate host! (sc=%p)\n", SCpnt ));
++              dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
++                         "Can't locate host! (sc=%p)\n",
++                         SCpnt ) );
+               return FAILED;
        }
-@@ -1669,101 +2091,116 @@
- }
  
- /* Search for a nodelist entry */
--struct lpfc_nodelist *
--lpfc_findnode_did(struct lpfc_hba *phba, uint32_t did)
-+static struct lpfc_nodelist *
-+__lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
- {
-+      struct lpfc_hba  *phba = vport->phba;
-       struct lpfc_nodelist *ndlp;
-       uint32_t data1;
+-      ioc = hd->ioc;
+-      printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n",
+-             ioc->name, SCpnt);
++      printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
++             hd->ioc->name, SCpnt);
+       scsi_print_command(SCpnt);
  
--      spin_lock_irq(phba->host->host_lock);
--      list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
--              if (lpfc_matchdid(phba, ndlp, did)) {
-+      list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
-+              if (lpfc_matchdid(vport, ndlp, did)) {
-                       data1 = (((uint32_t) ndlp->nlp_state << 24) |
-                                ((uint32_t) ndlp->nlp_xri << 16) |
-                                ((uint32_t) ndlp->nlp_type << 8) |
-                                ((uint32_t) ndlp->nlp_rpi & 0xff));
-                       lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
--                                      "%d:0929 FIND node DID "
-+                                      "%d (%d):0929 FIND node DID "
-                                       " Data: x%p x%x x%x x%x\n",
--                                      phba->brd_no,
-+                                      phba->brd_no, vport->vpi,
-                                       ndlp, ndlp->nlp_DID,
-                                       ndlp->nlp_flag, data1);
--                      spin_unlock_irq(phba->host->host_lock);
-                       return ndlp;
-               }
-       }
--      spin_unlock_irq(phba->host->host_lock);
+       if (hd->timeouts < -1)
+@@ -1928,10 +1918,11 @@
  
-       /* FIND node did <did> NOT FOUND */
-       lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
--                      "%d:0932 FIND node did x%x NOT FOUND.\n",
--                      phba->brd_no, did);
-+                      "%d (%d):0932 FIND node did x%x NOT FOUND.\n",
-+                      phba->brd_no, vport->vpi, did);
-       return NULL;
- }
+       vdev = SCpnt->device->hostdata;
+       retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+-          vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc));
++              vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
  
- struct lpfc_nodelist *
--lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
-+lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
-+{
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_nodelist *ndlp;
-+
-+      spin_lock_irq(shost->host_lock);
-+      ndlp = __lpfc_findnode_did(vport, did);
-+      spin_unlock_irq(shost->host_lock);
-+      return ndlp;
-+}
-+
-+struct lpfc_nodelist *
-+lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
+-      printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
+-          ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
++      printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
++              hd->ioc->name,
++              ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+       if (retval == 0)
+               return SUCCESS;
+@@ -1952,38 +1943,37 @@
+ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
  {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-       struct lpfc_nodelist *ndlp;
+       MPT_SCSI_HOST *  hd;
+-      int              retval;
+-      MPT_ADAPTER     *ioc;
++      int              status = SUCCESS;
  
--      ndlp = lpfc_findnode_did(phba, did);
-+      ndlp = lpfc_findnode_did(vport, did);
-       if (!ndlp) {
--              if ((phba->fc_flag & FC_RSCN_MODE) &&
--                 ((lpfc_rscn_payload_check(phba, did) == 0)))
-+              if ((vport->fc_flag & FC_RSCN_MODE) != 0 &&
-+                  lpfc_rscn_payload_check(vport, did) == 0)
-                       return NULL;
-               ndlp = (struct lpfc_nodelist *)
--                   mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
-+                   mempool_alloc(vport->phba->nlp_mem_pool, GFP_KERNEL);
-               if (!ndlp)
-                       return NULL;
--              lpfc_nlp_init(phba, ndlp, did);
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-+              lpfc_nlp_init(vport, ndlp, did);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
-+              spin_unlock_irq(shost->host_lock);
-               return ndlp;
+       /*  If we can't locate the host to reset, then we failed. */
+       if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
+-              dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: Can't "
+-                  "locate host! (sc=%p)\n", SCpnt));
++              dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
++                           "Can't locate host! (sc=%p)\n",
++                           SCpnt ) );
+               return FAILED;
        }
--      if (phba->fc_flag & FC_RSCN_MODE) {
--              if (lpfc_rscn_payload_check(phba, did)) {
-+      if (vport->fc_flag & FC_RSCN_MODE) {
-+              if (lpfc_rscn_payload_check(vport, did)) {
-+                      spin_lock_irq(shost->host_lock);
-                       ndlp->nlp_flag |= NLP_NPR_2B_DISC;
-+                      spin_unlock_irq(shost->host_lock);
  
-                       /* Since this node is marked for discovery,
-                        * delay timeout is not needed.
-                        */
-                       if (ndlp->nlp_flag & NLP_DELAY_TMO)
--                              lpfc_cancel_retry_delay_tmo(phba, ndlp);
-+                              lpfc_cancel_retry_delay_tmo(vport, ndlp);
-               } else
-                       ndlp = NULL;
+-      ioc = hd->ioc;
+-      printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
+-          ioc->name, SCpnt);
++      printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
++             hd->ioc->name, SCpnt);
+       /*  If our attempts to reset the host failed, then return a failed
+        *  status.  The host will be taken off line by the SCSI mid-layer.
+        */
+-      if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
+-              retval = FAILED;
++      if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
++              status = FAILED;
        } else {
-               if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE ||
-                   ndlp->nlp_state == NLP_STE_PLOGI_ISSUE)
-                       return NULL;
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
-+              spin_unlock_irq(shost->host_lock);
+               /*  Make sure TM pending is cleared and TM state is set to
+                *  NONE.
+                */
+-              retval = 0;
+               hd->tmPending = 0;
+               hd->tmState = TM_STATE_NONE;
        }
-       return ndlp;
- }
- /* Build a list of nodes to discover based on the loopmap */
- void
--lpfc_disc_list_loopmap(struct lpfc_hba * phba)
-+lpfc_disc_list_loopmap(struct lpfc_vport *vport)
- {
-+      struct lpfc_hba  *phba = vport->phba;
-       int j;
-       uint32_t alpa, index;
  
--      if (phba->hba_state <= LPFC_LINK_DOWN) {
-+      if (!lpfc_is_link_up(phba))
-               return;
--      }
--      if (phba->fc_topology != TOPOLOGY_LOOP) {
-+
-+      if (phba->fc_topology != TOPOLOGY_LOOP)
-               return;
--      }
+-      printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
+-          ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
++      dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
++                   "Status = %s\n",
++                   (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
  
-       /* Check for loop map present or not */
-       if (phba->alpa_map[0]) {
-               for (j = 1; j <= phba->alpa_map[0]; j++) {
-                       alpa = phba->alpa_map[j];
--
--                      if (((phba->fc_myDID & 0xff) == alpa) || (alpa == 0)) {
-+                      if (((vport->fc_myDID & 0xff) == alpa) || (alpa == 0))
-                               continue;
--                      }
--                      lpfc_setup_disc_node(phba, alpa);
-+                      lpfc_setup_disc_node(vport, alpa);
-               }
-       } else {
-               /* No alpamap, so try all alpa's */
-@@ -1776,113 +2213,167 @@
-                       else
-                               index = FC_MAXLOOP - j - 1;
-                       alpa = lpfcAlpaArray[index];
--                      if ((phba->fc_myDID & 0xff) == alpa) {
-+                      if ((vport->fc_myDID & 0xff) == alpa)
-                               continue;
--                      }
--
--                      lpfc_setup_disc_node(phba, alpa);
-+                      lpfc_setup_disc_node(vport, alpa);
-               }
-       }
-       return;
+-      return retval;
++      return status;
  }
  
--/* Start Link up / RSCN discovery on NPR list */
- void
--lpfc_disc_start(struct lpfc_hba * phba)
-+lpfc_issue_clear_la(struct lpfc_hba *phba, struct lpfc_vport *vport)
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -3160,16 +3150,6 @@
  {
--      struct lpfc_sli *psli;
-       LPFC_MBOXQ_t *mbox;
--      struct lpfc_nodelist *ndlp, *next_ndlp;
-+      struct lpfc_sli *psli = &phba->sli;
-+      struct lpfc_sli_ring *extra_ring = &psli->ring[psli->extra_ring];
-+      struct lpfc_sli_ring *fcp_ring   = &psli->ring[psli->fcp_ring];
-+      struct lpfc_sli_ring *next_ring  = &psli->ring[psli->next_ring];
-+      int  rc;
-+
-+      /*
-+       * if it's not a physical port or if we already send
-+       * clear_la then don't send it.
-+       */
-+      if ((phba->link_state >= LPFC_CLEAR_LA) ||
-+          (vport->port_type != LPFC_PHYSICAL_PORT))
-+              return;
-+
-+                      /* Link up discovery */
-+      if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) != NULL) {
-+              phba->link_state = LPFC_CLEAR_LA;
-+              lpfc_clear_la(phba, mbox);
-+              mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
-+              mbox->vport = vport;
-+              rc = lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT |
-+                                                    MBX_STOP_IOCB));
-+              if (rc == MBX_NOT_FINISHED) {
-+                      mempool_free(mbox, phba->mbox_mem_pool);
-+                      lpfc_disc_flush_list(vport);
-+                      extra_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
-+                      fcp_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
-+                      next_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
-+                      phba->link_state = LPFC_HBA_ERROR;
-+              }
-+      }
-+}
-+
-+/* Reg_vpi to tell firmware to resume normal operations */
-+void
-+lpfc_issue_reg_vpi(struct lpfc_hba *phba, struct lpfc_vport *vport)
-+{
-+      LPFC_MBOXQ_t *regvpimbox;
-+
-+      regvpimbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (regvpimbox) {
-+              lpfc_reg_vpi(phba, vport->vpi, vport->fc_myDID, regvpimbox);
-+              regvpimbox->mbox_cmpl = lpfc_mbx_cmpl_reg_vpi;
-+              regvpimbox->vport = vport;
-+              if (lpfc_sli_issue_mbox(phba, regvpimbox,
-+                                      (MBX_NOWAIT | MBX_STOP_IOCB))
-+                                      == MBX_NOT_FINISHED) {
-+                      mempool_free(regvpimbox, phba->mbox_mem_pool);
-+              }
-+      }
-+}
-+
-+/* Start Link up / RSCN discovery on NPR nodes */
-+void
-+lpfc_disc_start(struct lpfc_vport *vport)
-+{
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-       uint32_t num_sent;
-       uint32_t clear_la_pending;
-       int did_changed;
--      int rc;
--
--      psli = &phba->sli;
+       INTERNAL_CMD             iocmd;
  
--      if (phba->hba_state <= LPFC_LINK_DOWN) {
-+      if (!lpfc_is_link_up(phba))
-               return;
--      }
--      if (phba->hba_state == LPFC_CLEAR_LA)
-+
-+      if (phba->link_state == LPFC_CLEAR_LA)
-               clear_la_pending = 1;
-       else
-               clear_la_pending = 0;
+-      /* Ignore hidden raid components, this is handled when the command
+-       * is sent to the volume
+-       */
+-      if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
+-              return;
+-
+-      if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted ||
+-          !vdevice->configured_lun)
+-              return;
+-
+       /* Following parameters will not change
+        * in this routine.
+        */
+@@ -3184,6 +3164,8 @@
+       iocmd.id = vdevice->vtarget->id;
+       iocmd.lun = vdevice->lun;
  
--      if (phba->hba_state < LPFC_HBA_READY) {
--              phba->hba_state = LPFC_DISC_AUTH;
--      }
--      lpfc_set_disctmo(phba);
-+      if (vport->port_state < LPFC_VPORT_READY)
-+              vport->port_state = LPFC_DISC_AUTH;
-+
-+      lpfc_set_disctmo(vport);
++      if ((vdevice->vtarget->type == TYPE_DISK) &&
++          (vdevice->configured_lun))
+               mptscsih_do_cmd(hd, &iocmd);
+ }
  
--      if (phba->fc_prevDID == phba->fc_myDID) {
-+      if (vport->fc_prevDID == vport->fc_myDID)
-               did_changed = 0;
--      } else {
-+      else
-               did_changed = 1;
--      }
--      phba->fc_prevDID = phba->fc_myDID;
--      phba->num_disc_nodes = 0;
-+
-+      vport->fc_prevDID = vport->fc_myDID;
-+      vport->num_disc_nodes = 0;
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/mptscsih.h linux-2.6.22-570/drivers/message/fusion/mptscsih.h
+--- linux-2.6.22-590/drivers/message/fusion/mptscsih.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/mptscsih.h 2007-07-08 19:32:17.000000000 -0400
+@@ -6,7 +6,7 @@
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+  *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:DL-MPTFusionLinux@lsi.com)
++ *  (mailto:mpt_linux_developer@lsi.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+diff -Nurb linux-2.6.22-590/drivers/message/fusion/mptspi.c linux-2.6.22-570/drivers/message/fusion/mptspi.c
+--- linux-2.6.22-590/drivers/message/fusion/mptspi.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/fusion/mptspi.c   2007-07-08 19:32:17.000000000 -0400
+@@ -4,7 +4,7 @@
+  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+  *
+  *  Copyright (c) 1999-2007 LSI Logic Corporation
+- *  (mailto:DL-MPTFusionLinux@lsi.com)
++ *  (mailto:mpt_linux_developer@lsi.com)
+  *
+  */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -44,6 +44,7 @@
+ */
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  
-       /* Start Discovery state <hba_state> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                      "%d:0202 Start Discovery hba state x%x "
-+                      "%d (%d):0202 Start Discovery hba state x%x "
-                       "Data: x%x x%x x%x\n",
--                      phba->brd_no, phba->hba_state, phba->fc_flag,
--                      phba->fc_plogi_cnt, phba->fc_adisc_cnt);
--
--      /* If our did changed, we MUST do PLOGI */
--      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
--              if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
--                  (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
--                  did_changed) {
--                      spin_lock_irq(phba->host->host_lock);
--                      ndlp->nlp_flag &= ~NLP_NPR_ADISC;
--                      spin_unlock_irq(phba->host->host_lock);
--              }
--      }
-+                      phba->brd_no, vport->vpi, vport->port_state,
-+                      vport->fc_flag, vport->fc_plogi_cnt,
-+                      vport->fc_adisc_cnt);
++#include "linux_compat.h"     /* linux-2.6 tweaks */
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+diff -Nurb linux-2.6.22-590/drivers/message/i2o/i2o_scsi.c linux-2.6.22-570/drivers/message/i2o/i2o_scsi.c
+--- linux-2.6.22-590/drivers/message/i2o/i2o_scsi.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/message/i2o/i2o_scsi.c    2007-07-08 19:32:17.000000000 -0400
+@@ -377,8 +377,12 @@
+               osm_err("SCSI error %08x\n", error);
  
-       /* First do ADISCs - if any */
--      num_sent = lpfc_els_disc_adisc(phba);
-+      num_sent = lpfc_els_disc_adisc(vport);
+       dev = &c->pdev->dev;
+-
+-      scsi_dma_unmap(cmd);
++      if (cmd->use_sg)
++              dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg,
++                           cmd->sc_data_direction);
++      else if (cmd->SCp.dma_handle)
++              dma_unmap_single(dev, cmd->SCp.dma_handle, cmd->request_bufflen,
++                               cmd->sc_data_direction);
  
-       if (num_sent)
-               return;
+       cmd->scsi_done(cmd);
  
--      if ((phba->hba_state < LPFC_HBA_READY) && (!clear_la_pending)) {
-+      /*
-+       * For SLI3, cmpl_reg_vpi will set port_state to READY, and
-+       * continue discovery.
-+       */
-+      if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
-+          !(vport->fc_flag & FC_RSCN_MODE)) {
-+              lpfc_issue_reg_vpi(phba, vport);
-+              return;
-+      }
-+
-+      /*
-+       * For SLI2, we need to set port_state to READY and continue
-+       * discovery.
-+       */
-+      if (vport->port_state < LPFC_VPORT_READY && !clear_la_pending) {
-               /* If we get here, there is nothing to ADISC */
--              if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
--                      phba->hba_state = LPFC_CLEAR_LA;
--                      lpfc_clear_la(phba, mbox);
--                      mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
--                      rc = lpfc_sli_issue_mbox(phba, mbox,
--                                               (MBX_NOWAIT | MBX_STOP_IOCB));
--                      if (rc == MBX_NOT_FINISHED) {
--                              mempool_free( mbox, phba->mbox_mem_pool);
--                              lpfc_disc_flush_list(phba);
--                              psli->ring[(psli->extra_ring)].flag &=
--                                      ~LPFC_STOP_IOCB_EVENT;
--                              psli->ring[(psli->fcp_ring)].flag &=
--                                      ~LPFC_STOP_IOCB_EVENT;
--                              psli->ring[(psli->next_ring)].flag &=
--                                      ~LPFC_STOP_IOCB_EVENT;
--                              phba->hba_state = LPFC_HBA_READY;
-+              if (vport->port_type == LPFC_PHYSICAL_PORT)
-+                      lpfc_issue_clear_la(phba, vport);
-+
-+              if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) {
-+                      vport->num_disc_nodes = 0;
-+                      /* go thru NPR nodes and issue ELS PLOGIs */
-+                      if (vport->fc_npr_cnt)
-+                              lpfc_els_disc_plogi(vport);
-+
-+                      if (!vport->num_disc_nodes) {
-+                              spin_lock_irq(shost->host_lock);
-+                              vport->fc_flag &= ~FC_NDISC_ACTIVE;
-+                              spin_unlock_irq(shost->host_lock);
-+                              lpfc_can_disctmo(vport);
-                       }
-               }
-+              vport->port_state = LPFC_VPORT_READY;
-       } else {
-               /* Next do PLOGIs - if any */
--              num_sent = lpfc_els_disc_plogi(phba);
-+              num_sent = lpfc_els_disc_plogi(vport);
+@@ -660,15 +664,21 @@
  
-               if (num_sent)
-                       return;
+       if (sgl_offset != SGL_OFFSET_0) {
+               /* write size of data addressed by SGL */
+-              *mptr++ = cpu_to_le32(scsi_bufflen(SCpnt));
++              *mptr++ = cpu_to_le32(SCpnt->request_bufflen);
  
--              if (phba->fc_flag & FC_RSCN_MODE) {
-+              if (vport->fc_flag & FC_RSCN_MODE) {
-                       /* Check to see if more RSCNs came in while we
-                        * were processing this one.
-                        */
--                      if ((phba->fc_rscn_id_cnt == 0) &&
--                          (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
--                              spin_lock_irq(phba->host->host_lock);
--                              phba->fc_flag &= ~FC_RSCN_MODE;
--                              spin_unlock_irq(phba->host->host_lock);
-+                      if ((vport->fc_rscn_id_cnt == 0) &&
-+                          (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
-+                              spin_lock_irq(shost->host_lock);
-+                              vport->fc_flag &= ~FC_RSCN_MODE;
-+                              spin_unlock_irq(shost->host_lock);
-+                              lpfc_can_disctmo(vport);
-                       } else
--                              lpfc_els_handle_rscn(phba);
-+                              lpfc_els_handle_rscn(vport);
-               }
-       }
-       return;
-@@ -1893,7 +2384,7 @@
-  *  ring the match the sppecified nodelist.
-  */
- static void
--lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
-+lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
- {
-       LIST_HEAD(completions);
-       struct lpfc_sli *psli;
-@@ -1907,7 +2398,7 @@
-       /* Error matching iocb on txq or txcmplq
-        * First check the txq.
-        */
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
-               if (iocb->context1 != ndlp) {
-                       continue;
-@@ -1927,36 +2418,36 @@
-                       continue;
-               }
-               icmd = &iocb->iocb;
--              if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) ||
--                  (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) {
-+              if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR ||
-+                  icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX) {
-                       lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+               /* Now fill in the SGList and command */
+-
+-              if (scsi_sg_count(SCpnt)) {
+-                      if (!i2o_dma_map_sg(c, scsi_sglist(SCpnt),
+-                                          scsi_sg_count(SCpnt),
++              if (SCpnt->use_sg) {
++                      if (!i2o_dma_map_sg(c, SCpnt->request_buffer,
++                                          SCpnt->use_sg,
+                                           SCpnt->sc_data_direction, &mptr))
+                               goto nomem;
++              } else {
++                      SCpnt->SCp.dma_handle =
++                          i2o_dma_map_single(c, SCpnt->request_buffer,
++                                             SCpnt->request_bufflen,
++                                             SCpnt->sc_data_direction, &mptr);
++                      if (dma_mapping_error(SCpnt->SCp.dma_handle))
++                              goto nomem;
                }
        }
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
  
-       while (!list_empty(&completions)) {
-               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
--              list_del(&iocb->list);
-+              list_del_init(&iocb->list);
+diff -Nurb linux-2.6.22-590/drivers/mfd/ucb1x00-ts.c linux-2.6.22-570/drivers/mfd/ucb1x00-ts.c
+--- linux-2.6.22-590/drivers/mfd/ucb1x00-ts.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mfd/ucb1x00-ts.c  2007-07-08 19:32:17.000000000 -0400
+@@ -209,7 +209,6 @@
+       DECLARE_WAITQUEUE(wait, tsk);
+       int valid = 0;
  
--              if (iocb->iocb_cmpl) {
-+              if (!iocb->iocb_cmpl)
-+                      lpfc_sli_release_iocbq(phba, iocb);
-+              else {
-                       icmd = &iocb->iocb;
-                       icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                       icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-                       (iocb->iocb_cmpl) (phba, iocb, iocb);
--              } else
--                      lpfc_sli_release_iocbq(phba, iocb);
+-      set_freezable();
+       add_wait_queue(&ts->irq_wait, &wait);
+       while (!kthread_should_stop()) {
+               unsigned int x, y, p;
+diff -Nurb linux-2.6.22-590/drivers/misc/asus-laptop.c linux-2.6.22-570/drivers/misc/asus-laptop.c
+--- linux-2.6.22-590/drivers/misc/asus-laptop.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/misc/asus-laptop.c        2007-07-08 19:32:17.000000000 -0400
+@@ -737,7 +737,8 @@
+       struct device_attribute dev_attr_##_name = {                    \
+               .attr = {                                               \
+                       .name = __stringify(_name),                     \
+-                      .mode = 0 },                                    \
++                      .mode = 0,                                      \
++                      .owner = THIS_MODULE },                         \
+               .show   = NULL,                                         \
+               .store  = NULL,                                         \
        }
--
--      return;
-+      }
- }
- void
--lpfc_disc_flush_list(struct lpfc_hba * phba)
-+lpfc_disc_flush_list(struct lpfc_vport *vport)
- {
-       struct lpfc_nodelist *ndlp, *next_ndlp;
-+      struct lpfc_hba *phba = vport->phba;
+diff -Nurb linux-2.6.22-590/drivers/mmc/card/Kconfig linux-2.6.22-570/drivers/mmc/card/Kconfig
+--- linux-2.6.22-590/drivers/mmc/card/Kconfig  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/card/Kconfig  2007-07-08 19:32:17.000000000 -0400
+@@ -14,21 +14,3 @@
+         mount the filesystem. Almost everyone wishing MMC support
+         should say Y or M here.
  
--      if (phba->fc_plogi_cnt || phba->fc_adisc_cnt) {
--              list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
-+      if (vport->fc_plogi_cnt || vport->fc_adisc_cnt) {
-+              list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
-                                        nlp_listp) {
-                       if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE ||
-                           ndlp->nlp_state == NLP_STE_ADISC_ISSUE) {
-@@ -1967,6 +2458,14 @@
-       }
- }
+-config MMC_BLOCK_BOUNCE
+-      bool "Use bounce buffer for simple hosts"
+-      depends on MMC_BLOCK
+-      default y
+-      help
+-        SD/MMC is a high latency protocol where it is crucial to
+-        send large requests in order to get high performance. Many
+-        controllers, however, are restricted to continuous memory
+-        (i.e. they can't do scatter-gather), something the kernel
+-        rarely can provide.
+-
+-        Say Y here to help these restricted hosts by bouncing
+-        requests back and forth from a large buffer. You will get
+-        a big performance gain at the cost of up to 64 KiB of
+-        physical memory.
+-
+-        If unsure, say Y here.
+-
+diff -Nurb linux-2.6.22-590/drivers/mmc/card/block.c linux-2.6.22-570/drivers/mmc/card/block.c
+--- linux-2.6.22-590/drivers/mmc/card/block.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/card/block.c  2007-07-08 19:32:17.000000000 -0400
+@@ -262,9 +262,7 @@
+               }
  
-+void
-+lpfc_cleanup_discovery_resources(struct lpfc_vport *vport)
-+{
-+      lpfc_els_flush_rscn(vport);
-+      lpfc_els_flush_cmd(vport);
-+      lpfc_disc_flush_list(vport);
-+}
-+
- /*****************************************************************************/
- /*
-  * NAME:     lpfc_disc_timeout
-@@ -1985,158 +2484,154 @@
- void
- lpfc_disc_timeout(unsigned long ptr)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) ptr;
-+      struct lpfc_hba   *phba = vport->phba;
-       unsigned long flags = 0;
+               brq.data.sg = mq->sg;
+-              brq.data.sg_len = mmc_queue_map_sg(mq);
+-
+-              mmc_queue_bounce_pre(mq);
++              brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
  
-       if (unlikely(!phba))
-               return;
+               if (brq.data.blocks !=
+                   (req->nr_sectors >> (md->block_bits - 9))) {
+@@ -281,9 +279,6 @@
+               }
  
--      spin_lock_irqsave(phba->host->host_lock, flags);
--      if (!(phba->work_hba_events & WORKER_DISC_TMO)) {
--              phba->work_hba_events |= WORKER_DISC_TMO;
-+      if ((vport->work_port_events & WORKER_DISC_TMO) == 0) {
-+              spin_lock_irqsave(&vport->work_port_lock, flags);
-+              vport->work_port_events |= WORKER_DISC_TMO;
-+              spin_unlock_irqrestore(&vport->work_port_lock, flags);
-+
-+              spin_lock_irqsave(&phba->hbalock, flags);
-               if (phba->work_wait)
--                      wake_up(phba->work_wait);
-+                      lpfc_worker_wake_up(phba);
-+              spin_unlock_irqrestore(&phba->hbalock, flags);
-       }
--      spin_unlock_irqrestore(phba->host->host_lock, flags);
-       return;
- }
+               mmc_wait_for_req(card->host, &brq.mrq);
+-
+-              mmc_queue_bounce_post(mq);
+-
+               if (brq.cmd.error) {
+                       printk(KERN_ERR "%s: error %d sending read/write command\n",
+                              req->rq_disk->disk_name, brq.cmd.error);
+diff -Nurb linux-2.6.22-590/drivers/mmc/card/queue.c linux-2.6.22-570/drivers/mmc/card/queue.c
+--- linux-2.6.22-590/drivers/mmc/card/queue.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/card/queue.c  2007-07-08 19:32:17.000000000 -0400
+@@ -11,15 +11,12 @@
+  */
+ #include <linux/module.h>
+ #include <linux/blkdev.h>
+-#include <linux/freezer.h>
+ #include <linux/kthread.h>
  
- static void
--lpfc_disc_timeout_handler(struct lpfc_hba *phba)
-+lpfc_disc_timeout_handler(struct lpfc_vport *vport)
- {
--      struct lpfc_sli *psli;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-+      struct lpfc_sli  *psli = &phba->sli;
-       struct lpfc_nodelist *ndlp, *next_ndlp;
--      LPFC_MBOXQ_t *clearlambox, *initlinkmbox;
-+      LPFC_MBOXQ_t *initlinkmbox;
-       int rc, clrlaerr = 0;
+ #include <linux/mmc/card.h>
+ #include <linux/mmc/host.h>
+ #include "queue.h"
  
--      if (unlikely(!phba))
--              return;
+-#define MMC_QUEUE_BOUNCESZ    65536
 -
--      if (!(phba->fc_flag & FC_DISC_TMO))
-+      if (!(vport->fc_flag & FC_DISC_TMO))
-               return;
+ #define MMC_QUEUE_SUSPENDED   (1 << 0)
  
--      psli = &phba->sli;
-+      spin_lock_irq(shost->host_lock);
-+      vport->fc_flag &= ~FC_DISC_TMO;
-+      spin_unlock_irq(shost->host_lock);
+ /*
+@@ -45,7 +42,11 @@
+       struct mmc_queue *mq = d;
+       struct request_queue *q = mq->queue;
  
--      spin_lock_irq(phba->host->host_lock);
--      phba->fc_flag &= ~FC_DISC_TMO;
--      spin_unlock_irq(phba->host->host_lock);
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
-+              "disc timeout:    state:x%x rtry:x%x flg:x%x",
-+              vport->port_state, vport->fc_ns_retry, vport->fc_flag);
+-      current->flags |= PF_MEMALLOC;
++      /*
++       * Set iothread to ensure that we aren't put to sleep by
++       * the process freezing.  We handle suspension ourselves.
++       */
++      current->flags |= PF_MEMALLOC|PF_NOFREEZE;
  
--      switch (phba->hba_state) {
-+      switch (vport->port_state) {
+       down(&mq->thread_sem);
+       do {
+@@ -117,7 +118,6 @@
+       struct mmc_host *host = card->host;
+       u64 limit = BLK_BOUNCE_HIGH;
+       int ret;
+-      unsigned int bouncesz;
  
-       case LPFC_LOCAL_CFG_LINK:
--      /* hba_state is identically LPFC_LOCAL_CFG_LINK while waiting for FAN */
-+      /* port_state is identically  LPFC_LOCAL_CFG_LINK while waiting for
-+       * FAN
-+       */
-               /* FAN timeout */
--              lpfc_printf_log(phba,
--                               KERN_WARNING,
--                               LOG_DISCOVERY,
--                               "%d:0221 FAN timeout\n",
--                               phba->brd_no);
-+              lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY,
-+                              "%d (%d):0221 FAN timeout\n",
-+                              phba->brd_no, vport->vpi);
+       if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
+               limit = *mmc_dev(host)->dma_mask;
+@@ -127,83 +127,36 @@
+       if (!mq->queue)
+               return -ENOMEM;
  
-               /* Start discovery by sending FLOGI, clean up old rpis */
--              list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
-+              list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
-                                        nlp_listp) {
-                       if (ndlp->nlp_state != NLP_STE_NPR_NODE)
-                               continue;
-                       if (ndlp->nlp_type & NLP_FABRIC) {
-                               /* Clean up the ndlp on Fabric connections */
--                              lpfc_drop_node(phba, ndlp);
-+                              lpfc_drop_node(vport, ndlp);
-                       } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
-                               /* Fail outstanding IO now since device
-                                * is marked for PLOGI.
-                                */
--                              lpfc_unreg_rpi(phba, ndlp);
-+                              lpfc_unreg_rpi(vport, ndlp);
-                       }
-               }
--              phba->hba_state = LPFC_FLOGI;
--              lpfc_set_disctmo(phba);
--              lpfc_initial_flogi(phba);
-+              if (vport->port_state != LPFC_FLOGI) {
-+                      vport->port_state = LPFC_FLOGI;
-+                      lpfc_set_disctmo(vport);
-+                      lpfc_initial_flogi(vport);
-+              }
-               break;
+-      mq->queue->queuedata = mq;
+-      mq->req = NULL;
+-
+       blk_queue_prep_rq(mq->queue, mmc_prep_request);
+-
+-#ifdef CONFIG_MMC_BLOCK_BOUNCE
+-      if (host->max_hw_segs == 1) {
+-              bouncesz = MMC_QUEUE_BOUNCESZ;
+-
+-              if (bouncesz > host->max_req_size)
+-                      bouncesz = host->max_req_size;
+-              if (bouncesz > host->max_seg_size)
+-                      bouncesz = host->max_seg_size;
+-
+-              mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+-              if (!mq->bounce_buf) {
+-                      printk(KERN_WARNING "%s: unable to allocate "
+-                              "bounce buffer\n", mmc_card_name(card));
+-              } else {
+-                      blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH);
+-                      blk_queue_max_sectors(mq->queue, bouncesz / 512);
+-                      blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
+-                      blk_queue_max_hw_segments(mq->queue, bouncesz / 512);
+-                      blk_queue_max_segment_size(mq->queue, bouncesz);
+-
+-                      mq->sg = kmalloc(sizeof(struct scatterlist),
+-                              GFP_KERNEL);
+-                      if (!mq->sg) {
+-                              ret = -ENOMEM;
+-                              goto free_bounce_buf;
+-                      }
+-
+-                      mq->bounce_sg = kmalloc(sizeof(struct scatterlist) *
+-                              bouncesz / 512, GFP_KERNEL);
+-                      if (!mq->bounce_sg) {
+-                              ret = -ENOMEM;
+-                              goto free_sg;
+-                      }
+-              }
+-      }
+-#endif
+-
+-      if (!mq->bounce_buf) {
+       blk_queue_bounce_limit(mq->queue, limit);
+       blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
+       blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
+       blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
+       blk_queue_max_segment_size(mq->queue, host->max_seg_size);
  
-+      case LPFC_FDISC:
-       case LPFC_FLOGI:
--      /* hba_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */
-+      /* port_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */
-               /* Initial FLOGI timeout */
--              lpfc_printf_log(phba,
--                               KERN_ERR,
--                               LOG_DISCOVERY,
--                               "%d:0222 Initial FLOGI timeout\n",
--                               phba->brd_no);
-+              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-+                              "%d (%d):0222 Initial %s timeout\n",
-+                              phba->brd_no, vport->vpi,
-+                              vport->vpi ? "FLOGI" : "FDISC");
+-              mq->sg = kmalloc(sizeof(struct scatterlist) *
+-                      host->max_phys_segs, GFP_KERNEL);
++      mq->queue->queuedata = mq;
++      mq->req = NULL;
++
++      mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs,
++                       GFP_KERNEL);
+       if (!mq->sg) {
+               ret = -ENOMEM;
+               goto cleanup_queue;
+       }
+-      }
  
-               /* Assume no Fabric and go on with discovery.
-                * Check for outstanding ELS FLOGI to abort.
-                */
+       init_MUTEX(&mq->thread_sem);
  
-               /* FLOGI failed, so just use loop map to make discovery list */
--              lpfc_disc_list_loopmap(phba);
-+              lpfc_disc_list_loopmap(vport);
+       mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");
+       if (IS_ERR(mq->thread)) {
+               ret = PTR_ERR(mq->thread);
+-              goto free_bounce_sg;
++              goto free_sg;
+       }
  
-               /* Start discovery */
--              lpfc_disc_start(phba);
-+              lpfc_disc_start(vport);
-               break;
+       return 0;
+- free_bounce_sg:
+-      if (mq->bounce_sg)
+-              kfree(mq->bounce_sg);
+-      mq->bounce_sg = NULL;
++
+  free_sg:
+       kfree(mq->sg);
+       mq->sg = NULL;
+- free_bounce_buf:
+-      if (mq->bounce_buf)
+-              kfree(mq->bounce_buf);
+-      mq->bounce_buf = NULL;
+  cleanup_queue:
+       blk_cleanup_queue(mq->queue);
+       return ret;
+@@ -225,17 +178,9 @@
+       /* Then terminate our worker thread */
+       kthread_stop(mq->thread);
  
-       case LPFC_FABRIC_CFG_LINK:
-       /* hba_state is identically LPFC_FABRIC_CFG_LINK while waiting for
-          NameServer login */
-               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
--                              "%d:0223 Timeout while waiting for NameServer "
--                              "login\n", phba->brd_no);
-+                              "%d (%d):0223 Timeout while waiting for "
-+                              "NameServer login\n",
-+                              phba->brd_no, vport->vpi);
+-      if (mq->bounce_sg)
+-              kfree(mq->bounce_sg);
+-      mq->bounce_sg = NULL;
+-
+       kfree(mq->sg);
+       mq->sg = NULL;
  
-               /* Next look for NameServer ndlp */
--              ndlp = lpfc_findnode_did(phba, NameServer_DID);
-+              ndlp = lpfc_findnode_did(vport, NameServer_DID);
-               if (ndlp)
-                       lpfc_nlp_put(ndlp);
-               /* Start discovery */
--              lpfc_disc_start(phba);
-+              lpfc_disc_start(vport);
-               break;
+-      if (mq->bounce_buf)
+-              kfree(mq->bounce_buf);
+-      mq->bounce_buf = NULL;
+-
+       blk_cleanup_queue(mq->queue);
  
-       case LPFC_NS_QRY:
-       /* Check for wait for NameServer Rsp timeout */
-               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
--                              "%d:0224 NameServer Query timeout "
-+                              "%d (%d):0224 NameServer Query timeout "
-                               "Data: x%x x%x\n",
--                              phba->brd_no,
--                              phba->fc_ns_retry, LPFC_MAX_NS_RETRY);
-+                              phba->brd_no, vport->vpi,
-+                              vport->fc_ns_retry, LPFC_MAX_NS_RETRY);
--              ndlp = lpfc_findnode_did(phba, NameServer_DID);
--              if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
--                      if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
-+              if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
-                               /* Try it one more time */
--                              rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT);
-+                      vport->fc_ns_retry++;
-+                      rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
-+                                       vport->fc_ns_retry, 0);
-                               if (rc == 0)
-                                       break;
-                       }
--                      phba->fc_ns_retry = 0;
+       mq->card = NULL;
+@@ -286,108 +231,3 @@
+       }
+ }
+-static void copy_sg(struct scatterlist *dst, unsigned int dst_len,
+-      struct scatterlist *src, unsigned int src_len)
+-{
+-      unsigned int chunk;
+-      char *dst_buf, *src_buf;
+-      unsigned int dst_size, src_size;
+-
+-      dst_buf = NULL;
+-      src_buf = NULL;
+-      dst_size = 0;
+-      src_size = 0;
+-
+-      while (src_len) {
+-              BUG_ON(dst_len == 0);
+-
+-              if (dst_size == 0) {
+-                      dst_buf = page_address(dst->page) + dst->offset;
+-                      dst_size = dst->length;
 -              }
 -
--              /* Nothing to authenticate, so CLEAR_LA right now */
--              clearlambox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
--              if (!clearlambox) {
--                      clrlaerr = 1;
--                      lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
--                                      "%d:0226 Device Discovery "
--                                      "completion error\n",
--                                      phba->brd_no);
--                      phba->hba_state = LPFC_HBA_ERROR;
--                      break;
+-              if (src_size == 0) {
+-                      src_buf = page_address(src->page) + src->offset;
+-                      src_size = src->length;
 -              }
-+              vport->fc_ns_retry = 0;
--              phba->hba_state = LPFC_CLEAR_LA;
--              lpfc_clear_la(phba, clearlambox);
--              clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
--              rc = lpfc_sli_issue_mbox(phba, clearlambox,
--                                       (MBX_NOWAIT | MBX_STOP_IOCB));
--              if (rc == MBX_NOT_FINISHED) {
--                      mempool_free(clearlambox, phba->mbox_mem_pool);
--                      clrlaerr = 1;
--                      break;
-+              /*
-+               * Discovery is over.
-+               * set port_state to PORT_READY if SLI2.
-+               * cmpl_reg_vpi will set port_state to READY for SLI3.
-+               */
-+              if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
-+                      lpfc_issue_reg_vpi(phba, vport);
-+              else  { /* NPIV Not enabled */
-+                      lpfc_issue_clear_la(phba, vport);
-+                      vport->port_state = LPFC_VPORT_READY;
-               }
+-
+-              chunk = min(dst_size, src_size);
+-
+-              memcpy(dst_buf, src_buf, chunk);
+-
+-              dst_buf += chunk;
+-              src_buf += chunk;
+-              dst_size -= chunk;
+-              src_size -= chunk;
+-
+-              if (dst_size == 0) {
+-                      dst++;
+-                      dst_len--;
+-              }
+-
+-              if (src_size == 0) {
+-                      src++;
+-                      src_len--;
+-              }
+-      }
+-}
+-
+-unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
+-{
+-      unsigned int sg_len;
+-
+-      if (!mq->bounce_buf)
+-              return blk_rq_map_sg(mq->queue, mq->req, mq->sg);
+-
+-      BUG_ON(!mq->bounce_sg);
+-
+-      sg_len = blk_rq_map_sg(mq->queue, mq->req, mq->bounce_sg);
+-
+-      mq->bounce_sg_len = sg_len;
+-
+-      /*
+-       * Shortcut in the event we only get a single entry.
+-       */
+-      if (sg_len == 1) {
+-              memcpy(mq->sg, mq->bounce_sg, sizeof(struct scatterlist));
+-              return 1;
+-      }
+-
+-      mq->sg[0].page = virt_to_page(mq->bounce_buf);
+-      mq->sg[0].offset = offset_in_page(mq->bounce_buf);
+-      mq->sg[0].length = 0;
+-
+-      while (sg_len) {
+-              mq->sg[0].length += mq->bounce_sg[sg_len - 1].length;
+-              sg_len--;
+-      }
+-
+-      return 1;
+-}
+-
+-void mmc_queue_bounce_pre(struct mmc_queue *mq)
+-{
+-      if (!mq->bounce_buf)
+-              return;
+-
+-      if (mq->bounce_sg_len == 1)
+-              return;
+-      if (rq_data_dir(mq->req) != WRITE)
+-              return;
+-
+-      copy_sg(mq->sg, 1, mq->bounce_sg, mq->bounce_sg_len);
+-}
+-
+-void mmc_queue_bounce_post(struct mmc_queue *mq)
+-{
+-      if (!mq->bounce_buf)
+-              return;
+-
+-      if (mq->bounce_sg_len == 1)
+-              return;
+-      if (rq_data_dir(mq->req) != READ)
+-              return;
+-
+-      copy_sg(mq->bounce_sg, mq->bounce_sg_len, mq->sg, 1);
+-}
+-
+diff -Nurb linux-2.6.22-590/drivers/mmc/card/queue.h linux-2.6.22-570/drivers/mmc/card/queue.h
+--- linux-2.6.22-590/drivers/mmc/card/queue.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/card/queue.h  2007-07-08 19:32:17.000000000 -0400
+@@ -14,9 +14,6 @@
+       void                    *data;
+       struct request_queue    *queue;
+       struct scatterlist      *sg;
+-      char                    *bounce_buf;
+-      struct scatterlist      *bounce_sg;
+-      unsigned int            bounce_sg_len;
+ };
  
-               /* Setup and issue mailbox INITIALIZE LINK command */
-               initlinkmbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-               if (!initlinkmbox) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
--                                      "%d:0206 Device Discovery "
-+                                      "%d (%d):0206 Device Discovery "
-                                       "completion error\n",
--                                      phba->brd_no);
--                      phba->hba_state = LPFC_HBA_ERROR;
-+                                      phba->brd_no, vport->vpi);
-+                      phba->link_state = LPFC_HBA_ERROR;
-                       break;
-               }
+ extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);
+@@ -24,8 +21,4 @@
+ extern void mmc_queue_suspend(struct mmc_queue *);
+ extern void mmc_queue_resume(struct mmc_queue *);
  
-@@ -2144,6 +2639,8 @@
-               lpfc_init_link(phba, initlinkmbox, phba->cfg_topology,
-                              phba->cfg_link_speed);
-               initlinkmbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
-+              initlinkmbox->vport = vport;
-+              initlinkmbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-               rc = lpfc_sli_issue_mbox(phba, initlinkmbox,
-                                        (MBX_NOWAIT | MBX_STOP_IOCB));
-               lpfc_set_loopback_flag(phba);
-@@ -2154,67 +2651,81 @@
+-extern unsigned int mmc_queue_map_sg(struct mmc_queue *);
+-extern void mmc_queue_bounce_pre(struct mmc_queue *);
+-extern void mmc_queue_bounce_post(struct mmc_queue *);
+-
+ #endif
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/Kconfig linux-2.6.22-570/drivers/mmc/core/Kconfig
+--- linux-2.6.22-590/drivers/mmc/core/Kconfig  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/Kconfig  2007-07-08 19:32:17.000000000 -0400
+@@ -14,16 +14,3 @@
+         This option is usually just for embedded systems which use
+         a MMC/SD card for rootfs. Most people should say N here.
  
-       case LPFC_DISC_AUTH:
-       /* Node Authentication timeout */
--              lpfc_printf_log(phba,
--                               KERN_ERR,
--                               LOG_DISCOVERY,
--                               "%d:0227 Node Authentication timeout\n",
--                               phba->brd_no);
--              lpfc_disc_flush_list(phba);
--              clearlambox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
--              if (!clearlambox) {
--                      clrlaerr = 1;
-                       lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
--                                      "%d:0207 Device Discovery "
--                                      "completion error\n",
--                                      phba->brd_no);
--                      phba->hba_state = LPFC_HBA_ERROR;
--                      break;
-+                              "%d (%d):0227 Node Authentication timeout\n",
-+                              phba->brd_no, vport->vpi);
-+              lpfc_disc_flush_list(vport);
-+
-+              /*
-+               * set port_state to PORT_READY if SLI2.
-+               * cmpl_reg_vpi will set port_state to READY for SLI3.
-+               */
-+              if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
-+                      lpfc_issue_reg_vpi(phba, vport);
-+              else {  /* NPIV Not enabled */
-+                      lpfc_issue_clear_la(phba, vport);
-+                      vport->port_state = LPFC_VPORT_READY;
-               }
--              phba->hba_state = LPFC_CLEAR_LA;
--              lpfc_clear_la(phba, clearlambox);
--              clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
--              rc = lpfc_sli_issue_mbox(phba, clearlambox,
--                                       (MBX_NOWAIT | MBX_STOP_IOCB));
--              if (rc == MBX_NOT_FINISHED) {
--                      mempool_free(clearlambox, phba->mbox_mem_pool);
--                      clrlaerr = 1;
-+              break;
-+
-+      case LPFC_VPORT_READY:
-+              if (vport->fc_flag & FC_RSCN_MODE) {
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-+                                      "%d (%d):0231 RSCN timeout Data: x%x "
-+                                      "x%x\n",
-+                                      phba->brd_no, vport->vpi,
-+                                      vport->fc_ns_retry, LPFC_MAX_NS_RETRY);
-+
-+                      /* Cleanup any outstanding ELS commands */
-+                      lpfc_els_flush_cmd(vport);
-+
-+                      lpfc_els_flush_rscn(vport);
-+                      lpfc_disc_flush_list(vport);
-               }
-               break;
+-config MMC_PASSWORDS
+-      boolean "MMC card lock/unlock passwords (EXPERIMENTAL)"
+-      depends on EXPERIMENTAL
+-      select KEYS
+-      help
+-        Say Y here to enable the use of passwords to lock and unlock
+-        MMC cards.  This uses the access key retention support, using
+-        request_key to look up the key associated with each card.
+-
+-        For example, if you have an MMC card that was locked using
+-        Symbian OS on your cell phone, you won't be able to read it
+-        on Linux without this support.
+-
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/Makefile linux-2.6.22-570/drivers/mmc/core/Makefile
+--- linux-2.6.22-590/drivers/mmc/core/Makefile 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/Makefile 2007-07-08 19:32:17.000000000 -0400
+@@ -7,6 +7,5 @@
+ endif
  
-+      default:
-+              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-+                              "%d (%d):0229 Unexpected discovery timeout, "
-+                              "vport State x%x\n",
-+                              phba->brd_no, vport->vpi, vport->port_state);
-+
-+              break;
-+      }
-+
-+      switch (phba->link_state) {
-       case LPFC_CLEAR_LA:
-       /* CLEAR LA timeout */
--              lpfc_printf_log(phba,
--                               KERN_ERR,
--                               LOG_DISCOVERY,
--                               "%d:0228 CLEAR LA timeout\n",
--                               phba->brd_no);
-+              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-+                              "%d (%d):0228 CLEAR LA timeout\n",
-+                              phba->brd_no, vport->vpi);
-               clrlaerr = 1;
-               break;
+ obj-$(CONFIG_MMC)             += mmc_core.o
+-mmc_core-y                    := core.o sysfs.o bus.o host.o mmc.o mmc_ops.o sd.o sd_ops.o
+-mmc_core-$(CONFIG_MMC_PASSWORDS) += lock.o
++mmc_core-y                    := core.o sysfs.o mmc.o mmc_ops.o sd.o sd_ops.o
  
--      case LPFC_HBA_READY:
--              if (phba->fc_flag & FC_RSCN_MODE) {
--                      lpfc_printf_log(phba,
--                                      KERN_ERR,
--                                      LOG_DISCOVERY,
--                                      "%d:0231 RSCN timeout Data: x%x x%x\n",
--                                      phba->brd_no,
--                                      phba->fc_ns_retry, LPFC_MAX_NS_RETRY);
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/bus.c linux-2.6.22-570/drivers/mmc/core/bus.c
+--- linux-2.6.22-590/drivers/mmc/core/bus.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/bus.c    1969-12-31 19:00:00.000000000 -0500
+@@ -1,245 +0,0 @@
+-/*
+- *  linux/drivers/mmc/core/bus.c
+- *
+- *  Copyright (C) 2003 Russell King, All Rights Reserved.
+- *  Copyright (C) 2007 Pierre Ossman
+- *
+- * 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.
+- *
+- *  MMC card bus driver model
+- */
+-
+-#include <linux/device.h>
+-#include <linux/err.h>
+-
+-#include <linux/mmc/card.h>
+-#include <linux/mmc/host.h>
+-
+-#include "sysfs.h"
+-#include "bus.h"
+-
+-#define dev_to_mmc_card(d)    container_of(d, struct mmc_card, dev)
+-#define to_mmc_driver(d)      container_of(d, struct mmc_driver, drv)
+-
+-static ssize_t mmc_type_show(struct device *dev,
+-      struct device_attribute *attr, char *buf)
+-{
+-      struct mmc_card *card = dev_to_mmc_card(dev);
+-
+-      switch (card->type) {
+-      case MMC_TYPE_MMC:
+-              return sprintf(buf, "MMC\n");
+-      case MMC_TYPE_SD:
+-              return sprintf(buf, "SD\n");
+-      default:
+-              return -EFAULT;
+-      }
+-}
+-
+-static struct device_attribute mmc_dev_attrs[] = {
+-      MMC_ATTR_RO(type),
+-      __ATTR_NULL,
+-};
+-
+-/*
+- * This currently matches any MMC driver to any MMC card - drivers
+- * themselves make the decision whether to drive this card in their
+- * probe method.
+- *
+- * We also fail for all locked cards; drivers expect to be able to do block
+- * I/O still on probe(), which is not possible while the card is locked.
+- * Device probing must be triggered sometime later to make the card available
+- * to the block driver.
+- */
+-static int mmc_bus_match(struct device *dev, struct device_driver *drv)
+-{
+-      struct mmc_card *card = dev_to_mmc_card(dev);
+-
+-      if (mmc_card_locked(card)) {
+-              dev_dbg(&card->dev, "card is locked; binding is deferred\n");
+-              return 0;
+-      }
+-
+-      return 1;
+-}
+-
+-static int
+-mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
+-              int buf_size)
+-{
+-      struct mmc_card *card = dev_to_mmc_card(dev);
+-      int retval = 0, i = 0, length = 0;
+-
+-#define add_env(fmt,val) do {                                 \
+-      retval = add_uevent_var(envp, num_envp, &i,             \
+-                              buf, buf_size, &length,         \
+-                              fmt, val);                      \
+-      if (retval)                                             \
+-              return retval;                                  \
+-} while (0);
+-
+-      switch (card->type) {
+-      case MMC_TYPE_MMC:
+-              add_env("MMC_TYPE=%s", "MMC");
+-              break;
+-      case MMC_TYPE_SD:
+-              add_env("MMC_TYPE=%s", "SD");
+-              break;
+-      }
+-
+-      add_env("MMC_NAME=%s", mmc_card_name(card));
+-
+-#undef add_env
+-
+-      envp[i] = NULL;
+-
+-      return 0;
+-}
+-
+-static int mmc_bus_probe(struct device *dev)
+-{
+-      struct mmc_driver *drv = to_mmc_driver(dev->driver);
+-      struct mmc_card *card = dev_to_mmc_card(dev);
+-
+-      return drv->probe(card);
+-}
+-
+-static int mmc_bus_remove(struct device *dev)
+-{
+-      struct mmc_driver *drv = to_mmc_driver(dev->driver);
+-      struct mmc_card *card = dev_to_mmc_card(dev);
+-
+-      drv->remove(card);
+-
+-      return 0;
+-}
+-
+-static int mmc_bus_suspend(struct device *dev, pm_message_t state)
+-{
+-      struct mmc_driver *drv = to_mmc_driver(dev->driver);
+-      struct mmc_card *card = dev_to_mmc_card(dev);
+-      int ret = 0;
+-
+-      if (dev->driver && drv->suspend)
+-              ret = drv->suspend(card, state);
+-      return ret;
+-}
+-
+-static int mmc_bus_resume(struct device *dev)
+-{
+-      struct mmc_driver *drv = to_mmc_driver(dev->driver);
+-      struct mmc_card *card = dev_to_mmc_card(dev);
+-      int ret = 0;
+-
+-      if (dev->driver && drv->resume)
+-              ret = drv->resume(card);
+-      return ret;
+-}
+-
+-static struct bus_type mmc_bus_type = {
+-      .name           = "mmc",
+-      .dev_attrs      = mmc_dev_attrs,
+-      .match          = mmc_bus_match,
+-      .uevent         = mmc_bus_uevent,
+-      .probe          = mmc_bus_probe,
+-      .remove         = mmc_bus_remove,
+-      .suspend        = mmc_bus_suspend,
+-      .resume         = mmc_bus_resume,
+-};
+-
+-int mmc_register_bus(void)
+-{
+-      return bus_register(&mmc_bus_type);
+-}
+-
+-void mmc_unregister_bus(void)
+-{
+-      bus_unregister(&mmc_bus_type);
+-}
+-
+-/**
+- *    mmc_register_driver - register a media driver
+- *    @drv: MMC media driver
+- */
+-int mmc_register_driver(struct mmc_driver *drv)
+-{
+-      drv->drv.bus = &mmc_bus_type;
+-      return driver_register(&drv->drv);
+-}
+-
+-EXPORT_SYMBOL(mmc_register_driver);
+-
+-/**
+- *    mmc_unregister_driver - unregister a media driver
+- *    @drv: MMC media driver
+- */
+-void mmc_unregister_driver(struct mmc_driver *drv)
+-{
+-      drv->drv.bus = &mmc_bus_type;
+-      driver_unregister(&drv->drv);
+-}
+-
+-EXPORT_SYMBOL(mmc_unregister_driver);
+-
+-static void mmc_release_card(struct device *dev)
+-{
+-      struct mmc_card *card = dev_to_mmc_card(dev);
+-
+-      kfree(card);
+-}
+-
+-/*
+- * Allocate and initialise a new MMC card structure.
+- */
+-struct mmc_card *mmc_alloc_card(struct mmc_host *host)
+-{
+-      struct mmc_card *card;
+-
+-      card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
+-      if (!card)
+-              return ERR_PTR(-ENOMEM);
+-
+-      memset(card, 0, sizeof(struct mmc_card));
+-
+-      card->host = host;
+-
+-      device_initialize(&card->dev);
+-
+-      card->dev.parent = mmc_classdev(host);
+-      card->dev.bus = &mmc_bus_type;
+-      card->dev.release = mmc_release_card;
+-
+-      return card;
+-}
+-
+-/*
+- * Register a new MMC card with the driver model.
+- */
+-int mmc_add_card(struct mmc_card *card)
+-{
+-      int ret;
+-
+-      snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+-               "%s:%04x", mmc_hostname(card->host), card->rca);
+-
+-      ret = device_add(&card->dev);
+-      if (ret == 0)
+-              mmc_card_set_present(card);
+-
+-      return ret;
+-}
+-
+-/*
+- * Unregister a new MMC card with the driver model, and
+- * (eventually) free it.
+- */
+-void mmc_remove_card(struct mmc_card *card)
+-{
+-      if (mmc_card_present(card))
+-              device_del(&card->dev);
 -
--                      /* Cleanup any outstanding ELS commands */
--                      lpfc_els_flush_cmd(phba);
-+      case LPFC_LINK_UNKNOWN:
-+      case LPFC_WARM_START:
-+      case LPFC_INIT_START:
-+      case LPFC_INIT_MBX_CMDS:
-+      case LPFC_LINK_DOWN:
-+      case LPFC_LINK_UP:
-+      case LPFC_HBA_ERROR:
-+              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-+                              "%d (%d):0230 Unexpected timeout, hba link "
-+                              "state x%x\n",
-+                              phba->brd_no, vport->vpi, phba->link_state);
-+              clrlaerr = 1;
-+              break;
--                      lpfc_els_flush_rscn(phba);
--                      lpfc_disc_flush_list(phba);
--              }
-+      case LPFC_HBA_READY:
-               break;
-       }
-       if (clrlaerr) {
--              lpfc_disc_flush_list(phba);
-+              lpfc_disc_flush_list(vport);
-               psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
-               psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
-               psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
--              phba->hba_state = LPFC_HBA_READY;
-+              vport->port_state = LPFC_VPORT_READY;
-       }
-       return;
-@@ -2227,37 +2738,29 @@
-  * handed off to the SLI layer.
-  */
- void
--lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
-+lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
- {
--      struct lpfc_sli *psli;
--      MAILBOX_t *mb;
--      struct lpfc_dmabuf *mp;
--      struct lpfc_nodelist *ndlp;
+-      put_device(&card->dev);
+-}
 -
--      psli = &phba->sli;
--      mb = &pmb->mb;
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/bus.h linux-2.6.22-570/drivers/mmc/core/bus.h
+--- linux-2.6.22-590/drivers/mmc/core/bus.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/bus.h    1969-12-31 19:00:00.000000000 -0500
+@@ -1,22 +0,0 @@
+-/*
+- *  linux/drivers/mmc/core/bus.h
+- *
+- *  Copyright (C) 2003 Russell King, All Rights Reserved.
+- *  Copyright 2007 Pierre Ossman
+- *
+- * 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.
+- */
+-#ifndef _MMC_CORE_BUS_H
+-#define _MMC_CORE_BUS_H
 -
--      ndlp = (struct lpfc_nodelist *) pmb->context2;
--      mp = (struct lpfc_dmabuf *) (pmb->context1);
-+      MAILBOX_t *mb = &pmb->mb;
-+      struct lpfc_dmabuf   *mp = (struct lpfc_dmabuf *) (pmb->context1);
-+      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
-+      struct lpfc_vport    *vport = pmb->vport;
-       pmb->context1 = NULL;
-       ndlp->nlp_rpi = mb->un.varWords[0];
-       ndlp->nlp_type |= NLP_FABRIC;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
+-struct mmc_card *mmc_alloc_card(struct mmc_host *host);
+-int mmc_add_card(struct mmc_card *card);
+-void mmc_remove_card(struct mmc_card *card);
+-
+-int mmc_register_bus(void);
+-void mmc_unregister_bus(void);
+-
+-#endif
+-
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/core.c linux-2.6.22-570/drivers/mmc/core/core.c
+--- linux-2.6.22-590/drivers/mmc/core/core.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/core.c   2007-07-08 19:32:17.000000000 -0400
+@@ -27,9 +27,7 @@
+ #include <linux/mmc/sd.h>
  
--      /* Start issuing Fabric-Device Management Interface (FDMI)
--       * command to 0xfffffa (FDMI well known port)
--       */
--      if (phba->cfg_fdmi_on == 1) {
--              lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA);
--      } else {
-               /*
--               * Delay issuing FDMI command if fdmi-on=2
--               * (supporting RPA/hostnmae)
-+       * Start issuing Fabric-Device Management Interface (FDMI) command to
-+       * 0xfffffa (FDMI well known port) or Delay issuing FDMI command if
-+       * fdmi-on=2 (supporting RPA/hostnmae)
-                */
--              mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60);
--      }
-+
-+      if (phba->cfg_fdmi_on == 1)
-+              lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
-+      else
-+              mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60);
+ #include "core.h"
+-#include "bus.h"
+-#include "host.h"
+-#include "lock.h"
++#include "sysfs.h"
  
-                               /* Mailbox took a reference to the node */
-       lpfc_nlp_put(ndlp);
-@@ -2283,16 +2786,12 @@
                    sizeof(ndlp->nlp_portname)) == 0;
- }
+ #include "mmc_ops.h"
+ #include "sd_ops.h"
+@@ -37,25 +35,6 @@
extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
+ extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
  
+-static struct workqueue_struct *workqueue;
+-
 -/*
-- * Search node lists for a remote port matching filter criteria
-- * Caller needs to hold host_lock before calling this routine.
+- * Internal function. Schedule delayed work in the MMC work queue.
 - */
- struct lpfc_nodelist *
--__lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
-+__lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
- {
-       struct lpfc_nodelist *ndlp;
--      list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
-+      list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
-               if (ndlp->nlp_state != NLP_STE_UNUSED_NODE &&
-                   filter(ndlp, param))
-                       return ndlp;
-@@ -2302,68 +2801,104 @@
- /*
-  * Search node lists for a remote port matching filter criteria
-- * This routine is used when the caller does NOT have host_lock.
-+ * Caller needs to hold host_lock before calling this routine.
-  */
- struct lpfc_nodelist *
--lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
-+lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
- {
-+      struct Scsi_Host     *shost = lpfc_shost_from_vport(vport);
-       struct lpfc_nodelist *ndlp;
--      spin_lock_irq(phba->host->host_lock);
--      ndlp = __lpfc_find_node(phba, filter, param);
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-+      ndlp = __lpfc_find_node(vport, filter, param);
-+      spin_unlock_irq(shost->host_lock);
-       return ndlp;
+-static int mmc_schedule_delayed_work(struct delayed_work *work,
+-                                   unsigned long delay)
+-{
+-      return queue_delayed_work(workqueue, work, delay);
+-}
+-
+-/*
+- * Internal function. Flush all scheduled work from the MMC work queue.
+- */
+-static void mmc_flush_scheduled_work(void)
+-{
+-      flush_workqueue(workqueue);
+-}
+-
+ /**
+  *    mmc_request_done - finish processing an MMC request
+  *    @host: MMC host which completed request
+@@ -390,6 +369,22 @@
  }
  
  /*
-  * This routine looks up the ndlp lists for the given RPI. If rpi found it
-- * returns the node list pointer else return NULL.
-+ * returns the node list element pointer else return NULL.
-  */
- struct lpfc_nodelist *
--__lpfc_findnode_rpi(struct lpfc_hba *phba, uint16_t rpi)
-+__lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
- {
--      return __lpfc_find_node(phba, lpfc_filter_by_rpi, &rpi);
-+      return __lpfc_find_node(vport, lpfc_filter_by_rpi, &rpi);
- }
- struct lpfc_nodelist *
--lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
-+lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-       struct lpfc_nodelist *ndlp;
++ * Allocate a new MMC card
++ */
++struct mmc_card *mmc_alloc_card(struct mmc_host *host)
++{
++      struct mmc_card *card;
++
++      card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
++      if (!card)
++              return ERR_PTR(-ENOMEM);
++
++      mmc_init_card(card, host);
++
++      return card;
++}
++
++/*
+  * Apply power to the MMC stack.  This is a two-stage process.
+  * First, we enable power to the card without the clock running.
+  * We then wait a bit for the power to stabilise.  Finally,
+@@ -517,7 +512,7 @@
+ EXPORT_SYMBOL(mmc_detect_change);
  
--      spin_lock_irq(phba->host->host_lock);
--      ndlp = __lpfc_findnode_rpi(phba, rpi);
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-+      ndlp = __lpfc_findnode_rpi(vport, rpi);
-+      spin_unlock_irq(shost->host_lock);
-       return ndlp;
- }
  
- /*
-  * This routine looks up the ndlp lists for the given WWPN. If WWPN found it
-- * returns the node list pointer else return NULL.
-+ * returns the node element list pointer else return NULL.
-  */
- struct lpfc_nodelist *
--lpfc_findnode_wwpn(struct lpfc_hba *phba, struct lpfc_name *wwpn)
-+lpfc_findnode_wwpn(struct lpfc_vport *vport, struct lpfc_name *wwpn)
+-void mmc_rescan(struct work_struct *work)
++static void mmc_rescan(struct work_struct *work)
  {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-       struct lpfc_nodelist *ndlp;
--      spin_lock_irq(phba->host->host_lock);
--      ndlp = __lpfc_find_node(phba, lpfc_filter_by_wwpn, wwpn);
--      spin_unlock_irq(phba->host->host_lock);
--      return NULL;
-+      spin_lock_irq(shost->host_lock);
-+      ndlp = __lpfc_find_node(vport, lpfc_filter_by_wwpn, wwpn);
-+      spin_unlock_irq(shost->host_lock);
-+      return ndlp;
+       struct mmc_host *host =
+               container_of(work, struct mmc_host, detect.work);
+@@ -566,13 +561,69 @@
+       }
  }
  
- void
--lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
-+lpfc_dev_loss_delay(unsigned long ptr)
+-void mmc_start_host(struct mmc_host *host)
++
++/**
++ *    mmc_alloc_host - initialise the per-host structure.
++ *    @extra: sizeof private data structure
++ *    @dev: pointer to host device model structure
++ *
++ *    Initialise the per-host structure.
++ */
++struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
 +{
-+      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) ptr;
-+      struct lpfc_vport *vport = ndlp->vport;
-+      struct lpfc_hba   *phba = vport->phba;
-+      struct lpfc_work_evt  *evtp = &ndlp->dev_loss_evt;
-+      unsigned long flags;
++      struct mmc_host *host;
 +
-+      evtp = &ndlp->dev_loss_evt;
++      host = mmc_alloc_host_sysfs(extra, dev);
++      if (host) {
++              spin_lock_init(&host->lock);
++              init_waitqueue_head(&host->wq);
++              INIT_DELAYED_WORK(&host->detect, mmc_rescan);
 +
-+      spin_lock_irqsave(&phba->hbalock, flags);
-+      if (!list_empty(&evtp->evt_listp)) {
-+              spin_unlock_irqrestore(&phba->hbalock, flags);
-+              return;
++              /*
++               * By default, hosts do not support SGIO or large requests.
++               * They have to set these according to their abilities.
++               */
++              host->max_hw_segs = 1;
++              host->max_phys_segs = 1;
++              host->max_seg_size = PAGE_CACHE_SIZE;
++
++              host->max_req_size = PAGE_CACHE_SIZE;
++              host->max_blk_size = 512;
++              host->max_blk_count = PAGE_CACHE_SIZE / 512;
 +      }
 +
-+      evtp->evt_arg1  = ndlp;
-+      evtp->evt       = LPFC_EVT_DEV_LOSS_DELAY;
-+      list_add_tail(&evtp->evt_listp, &phba->work_list);
-+      if (phba->work_wait)
-+              lpfc_worker_wake_up(phba);
-+      spin_unlock_irqrestore(&phba->hbalock, flags);
-+      return;
++      return host;
 +}
 +
-+void
-+lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+            uint32_t did)
++EXPORT_SYMBOL(mmc_alloc_host);
++
++/**
++ *    mmc_add_host - initialise host hardware
++ *    @host: mmc host
++ */
++int mmc_add_host(struct mmc_host *host)
  {
-       memset(ndlp, 0, sizeof (struct lpfc_nodelist));
-       INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
-+      INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp);
-       init_timer(&ndlp->nlp_delayfunc);
-       ndlp->nlp_delayfunc.function = lpfc_els_retry_delay;
-       ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
-       ndlp->nlp_DID = did;
--      ndlp->nlp_phba = phba;
-+      ndlp->vport = vport;
-       ndlp->nlp_sid = NLP_NO_SID;
-       INIT_LIST_HEAD(&ndlp->nlp_listp);
-       kref_init(&ndlp->kref);
++      int ret;
 +
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE,
-+              "node init:       did:x%x",
-+              ndlp->nlp_DID, 0, 0);
++      ret = mmc_add_host_sysfs(host);
++      if (ret == 0) {
+               mmc_power_off(host);
+               mmc_detect_change(host, 0);
++      }
 +
-       return;
++      return ret;
  }
  
-@@ -2372,8 +2907,13 @@
- {
-       struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist,
-                                                 kref);
--      lpfc_nlp_remove(ndlp->nlp_phba, ndlp);
--      mempool_free(ndlp, ndlp->nlp_phba->nlp_mem_pool);
-+
-+      lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE,
-+              "node release:    did:x%x flg:x%x type:x%x",
-+              ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
+-void mmc_stop_host(struct mmc_host *host)
++EXPORT_SYMBOL(mmc_add_host);
 +
-+      lpfc_nlp_remove(ndlp->vport, ndlp);
-+      mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool);
- }
++/**
++ *    mmc_remove_host - remove host hardware
++ *    @host: mmc host
++ *
++ *    Unregister and remove all cards associated with this host,
++ *    and power down the MMC bus.
++ */
++void mmc_remove_host(struct mmc_host *host)
+ {
+ #ifdef CONFIG_MMC_DEBUG
+       unsigned long flags;
+@@ -597,8 +648,24 @@
+       BUG_ON(host->card);
  
- struct lpfc_nodelist *
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_hw.h linux-2.6.22-590/drivers/scsi/lpfc/lpfc_hw.h
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_hw.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_hw.h       2008-01-02 13:56:37.000000000 -0500
-@@ -59,6 +59,12 @@
- #define SLI2_IOCB_CMD_R3XTRA_ENTRIES 24
- #define SLI2_IOCB_RSP_R3XTRA_ENTRIES 32
+       mmc_power_off(host);
++      mmc_remove_host_sysfs(host);
+ }
  
-+#define SLI2_IOCB_CMD_SIZE    32
-+#define SLI2_IOCB_RSP_SIZE    32
-+#define SLI3_IOCB_CMD_SIZE    128
-+#define SLI3_IOCB_RSP_SIZE    64
++EXPORT_SYMBOL(mmc_remove_host);
++
++/**
++ *    mmc_free_host - free the host structure
++ *    @host: mmc host
++ *
++ *    Free the host once all references to it have been dropped.
++ */
++void mmc_free_host(struct mmc_host *host)
++{
++      mmc_free_host_sysfs(host);
++}
 +
++EXPORT_SYMBOL(mmc_free_host);
 +
- /* Common Transport structures and definitions */
+ #ifdef CONFIG_PM
  
- union CtRevisionId {
-@@ -79,6 +85,9 @@
-       uint32_t word;
- };
+ /**
+@@ -659,47 +726,4 @@
+ #endif
+-static int __init mmc_init(void)
+-{
+-      int ret;
+-
+-      workqueue = create_singlethread_workqueue("kmmcd");
+-      if (!workqueue)
+-              return -ENOMEM;
+-
+-      ret = mmc_register_bus();
+-      if (ret)
+-              goto destroy_workqueue;
+-
+-      ret = mmc_register_host_class();
+-      if (ret)
+-              goto unregister_bus;
+-
+-      ret = mmc_register_key_type();
+-      if (ret)
+-              goto unregister_host_class;
+-
+-      return 0;
+-
+-unregister_host_class:
+-      mmc_unregister_host_class();
+-unregister_bus:
+-      mmc_unregister_bus();
+-destroy_workqueue:
+-      destroy_workqueue(workqueue);
+-
+-      return ret;
+-}
+-
+-static void __exit mmc_exit(void)
+-{
+-      mmc_unregister_key_type();
+-      mmc_unregister_host_class();
+-      mmc_unregister_bus();
+-      destroy_workqueue(workqueue);
+-}
+-
+-module_init(mmc_init);
+-module_exit(mmc_exit);
+-
+ MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/core.h linux-2.6.22-570/drivers/mmc/core/core.h
+--- linux-2.6.22-590/drivers/mmc/core/core.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/core.h   2007-07-08 19:32:17.000000000 -0400
+@@ -54,6 +54,8 @@
+ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
+ void mmc_set_timing(struct mmc_host *host, unsigned int timing);
  
-+#define FC4_FEATURE_INIT 0x2
-+#define FC4_FEATURE_TARGET 0x1
++struct mmc_card *mmc_alloc_card(struct mmc_host *host);
 +
- struct lpfc_sli_ct_request {
-       /* Structure is in Big Endian format */
-       union CtRevisionId RevisionId;
-@@ -121,20 +130,6 @@
+ static inline void mmc_delay(unsigned int ms)
+ {
+       if (ms < 1000 / HZ) {
+@@ -64,9 +66,5 @@
+       }
+ }
  
-                       uint32_t rsvd[7];
-               } rft;
--              struct rff {
--                      uint32_t PortId;
--                      uint8_t reserved[2];
--#ifdef __BIG_ENDIAN_BITFIELD
--                      uint8_t feature_res:6;
--                      uint8_t feature_init:1;
--                      uint8_t feature_tgt:1;
--#else  /*  __LITTLE_ENDIAN_BITFIELD */
--                      uint8_t feature_tgt:1;
--                      uint8_t feature_init:1;
--                      uint8_t feature_res:6;
+-void mmc_rescan(struct work_struct *work);
+-void mmc_start_host(struct mmc_host *host);
+-void mmc_stop_host(struct mmc_host *host);
+-
+ #endif
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/host.c linux-2.6.22-570/drivers/mmc/core/host.c
+--- linux-2.6.22-590/drivers/mmc/core/host.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/host.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,156 +0,0 @@
+-/*
+- *  linux/drivers/mmc/core/host.c
+- *
+- *  Copyright (C) 2003 Russell King, All Rights Reserved.
+- *  Copyright (C) 2007 Pierre Ossman
+- *
+- * 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.
+- *
+- *  MMC host class device management
+- */
+-
+-#include <linux/device.h>
+-#include <linux/err.h>
+-#include <linux/idr.h>
+-#include <linux/pagemap.h>
+-
+-#include <linux/mmc/host.h>
+-
+-#include "core.h"
+-#include "host.h"
+-
+-#define cls_dev_to_mmc_host(d)        container_of(d, struct mmc_host, class_dev)
+-
+-static void mmc_host_classdev_release(struct device *dev)
+-{
+-      struct mmc_host *host = cls_dev_to_mmc_host(dev);
+-      kfree(host);
+-}
+-
+-static struct class mmc_host_class = {
+-      .name           = "mmc_host",
+-      .dev_release    = mmc_host_classdev_release,
+-};
+-
+-int mmc_register_host_class(void)
+-{
+-      return class_register(&mmc_host_class);
+-}
+-
+-void mmc_unregister_host_class(void)
+-{
+-      class_unregister(&mmc_host_class);
+-}
+-
+-static DEFINE_IDR(mmc_host_idr);
+-static DEFINE_SPINLOCK(mmc_host_lock);
+-
+-/**
+- *    mmc_alloc_host - initialise the per-host structure.
+- *    @extra: sizeof private data structure
+- *    @dev: pointer to host device model structure
+- *
+- *    Initialise the per-host structure.
+- */
+-struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+-{
+-      struct mmc_host *host;
+-
+-      host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+-      if (!host)
+-              return NULL;
+-
+-      memset(host, 0, sizeof(struct mmc_host) + extra);
+-
+-      host->parent = dev;
+-      host->class_dev.parent = dev;
+-      host->class_dev.class = &mmc_host_class;
+-      device_initialize(&host->class_dev);
+-
+-      spin_lock_init(&host->lock);
+-      init_waitqueue_head(&host->wq);
+-      INIT_DELAYED_WORK(&host->detect, mmc_rescan);
+-
+-      /*
+-       * By default, hosts do not support SGIO or large requests.
+-       * They have to set these according to their abilities.
+-       */
+-      host->max_hw_segs = 1;
+-      host->max_phys_segs = 1;
+-      host->max_seg_size = PAGE_CACHE_SIZE;
+-
+-      host->max_req_size = PAGE_CACHE_SIZE;
+-      host->max_blk_size = 512;
+-      host->max_blk_count = PAGE_CACHE_SIZE / 512;
+-
+-      return host;
+-}
+-
+-EXPORT_SYMBOL(mmc_alloc_host);
+-
+-/**
+- *    mmc_add_host - initialise host hardware
+- *    @host: mmc host
+- */
+-int mmc_add_host(struct mmc_host *host)
+-{
+-      int err;
+-
+-      if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+-              return -ENOMEM;
+-
+-      spin_lock(&mmc_host_lock);
+-      err = idr_get_new(&mmc_host_idr, host, &host->index);
+-      spin_unlock(&mmc_host_lock);
+-      if (err)
+-              return err;
+-
+-      snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
+-               "mmc%d", host->index);
+-
+-      err = device_add(&host->class_dev);
+-      if (err)
+-              return err;
+-
+-      mmc_start_host(host);
+-
+-      return 0;
+-}
+-
+-EXPORT_SYMBOL(mmc_add_host);
+-
+-/**
+- *    mmc_remove_host - remove host hardware
+- *    @host: mmc host
+- *
+- *    Unregister and remove all cards associated with this host,
+- *    and power down the MMC bus.
+- */
+-void mmc_remove_host(struct mmc_host *host)
+-{
+-      mmc_stop_host(host);
+-
+-      device_del(&host->class_dev);
+-
+-      spin_lock(&mmc_host_lock);
+-      idr_remove(&mmc_host_idr, host->index);
+-      spin_unlock(&mmc_host_lock);
+-}
+-
+-EXPORT_SYMBOL(mmc_remove_host);
+-
+-/**
+- *    mmc_free_host - free the host structure
+- *    @host: mmc host
+- *
+- *    Free the host once all references to it have been dropped.
+- */
+-void mmc_free_host(struct mmc_host *host)
+-{
+-      put_device(&host->class_dev);
+-}
+-
+-EXPORT_SYMBOL(mmc_free_host);
+-
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/host.h linux-2.6.22-570/drivers/mmc/core/host.h
+--- linux-2.6.22-590/drivers/mmc/core/host.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/host.h   1969-12-31 19:00:00.000000000 -0500
+@@ -1,18 +0,0 @@
+-/*
+- *  linux/drivers/mmc/core/host.h
+- *
+- *  Copyright (C) 2003 Russell King, All Rights Reserved.
+- *  Copyright 2007 Pierre Ossman
+- *
+- * 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.
+- */
+-#ifndef _MMC_CORE_HOST_H
+-#define _MMC_CORE_HOST_H
+-
+-int mmc_register_host_class(void);
+-void mmc_unregister_host_class(void);
+-
+-#endif
+-
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/lock.c linux-2.6.22-570/drivers/mmc/core/lock.c
+--- linux-2.6.22-590/drivers/mmc/core/lock.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/lock.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,199 +0,0 @@
+-/*
+- *  linux/drivers/mmc/core/lock.h
+- *
+- *  Copyright 2006 Instituto Nokia de Tecnologia (INdT), All Rights Reserved.
+- *  Copyright 2007 Pierre Ossman
+- *
+- * 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.
+- *
+- * MMC password key handling.
+- */
+-
+-#include <linux/device.h>
+-#include <linux/key.h>
+-#include <linux/err.h>
+-
+-#include <linux/mmc/card.h>
+-#include <linux/mmc/host.h>
+-#include <linux/mmc/mmc.h>
+-
+-#include "sysfs.h"
+-#include "mmc_ops.h"
+-#include "lock.h"
+-
+-#define MMC_KEYLEN_MAXBYTES 32
+-
+-#define dev_to_mmc_card(d)    container_of(d, struct mmc_card, dev)
+-
+-static int mmc_key_instantiate(struct key *key, const void *data, size_t datalen)
+-{
+-      struct mmc_key_payload *mpayload;
+-      int ret;
+-
+-      ret = -EINVAL;
+-      if (datalen <= 0 || datalen > MMC_KEYLEN_MAXBYTES || !data) {
+-              pr_debug("Invalid data\n");
+-              goto error;
+-      }
+-
+-      ret = key_payload_reserve(key, datalen);
+-      if (ret < 0) {
+-              pr_debug("ret = %d\n", ret);
+-              goto error;
+-      }
+-
+-      ret = -ENOMEM;
+-      mpayload = kmalloc(sizeof(*mpayload) + datalen, GFP_KERNEL);
+-      if (!mpayload) {
+-              pr_debug("Unable to allocate mpayload structure\n");
+-              goto error;
+-      }
+-      mpayload->datalen = datalen;
+-      memcpy(mpayload->data, data, datalen);
+-
+-      rcu_assign_pointer(key->payload.data, mpayload);
+-
+-      /* ret = 0 if there is no error */
+-      ret = 0;
+-
+-error:
+-      return ret;
+-}
+-
+-static int mmc_key_match(const struct key *key, const void *description)
+-{
+-      return strcmp(key->description, description) == 0;
+-}
+-
+-/*
+- * dispose of the data dangling from the corpse of a mmc key
+- */
+-static void mmc_key_destroy(struct key *key)
+-{
+-      struct mmc_key_payload *mpayload = key->payload.data;
+-
+-      kfree(mpayload);
+-}
+-
+-static struct key_type mmc_key_type = {
+-      .name           = "mmc",
+-      .def_datalen    = MMC_KEYLEN_MAXBYTES,
+-      .instantiate    = mmc_key_instantiate,
+-      .match          = mmc_key_match,
+-      .destroy        = mmc_key_destroy,
+-};
+-
+-int mmc_register_key_type(void)
+-{
+-      return register_key_type(&mmc_key_type);
+-}
+-
+-void mmc_unregister_key_type(void)
+-{
+-      unregister_key_type(&mmc_key_type);
+-}
+-
+-static ssize_t
+-mmc_lockable_show(struct device *dev, struct device_attribute *att, char *buf)
+-{
+-      struct mmc_card *card = dev_to_mmc_card(dev);
+-
+-      return sprintf(buf, "%slocked\n", mmc_card_locked(card) ? "" : "un");
+-}
+-
+-/*
+- * implement MMC password functions: force erase, remove password, change
+- * password, unlock card and assign password.
+- */
+-static ssize_t
+-mmc_lockable_store(struct device *dev, struct device_attribute *att,
+-      const char *data, size_t len)
+-{
+-      struct mmc_card *card = dev_to_mmc_card(dev);
+-      int ret;
+-      struct key *mmc_key;
+-
+-      if(!mmc_card_lockable(card))
+-              return -EINVAL;
+-
+-      mmc_claim_host(card->host);
+-
+-      ret = -EINVAL;
+-      if (mmc_card_locked(card) && !strncmp(data, "erase", 5)) {
+-              /* forced erase only works while card is locked */
+-              mmc_lock_unlock(card, NULL, MMC_LOCK_MODE_ERASE);
+-              ret = len;
+-      } else if (!mmc_card_locked(card) && !strncmp(data, "remove", 6)) {
+-              /* remove password only works while card is unlocked */
+-              mmc_key = request_key(&mmc_key_type, "mmc:key", "remove");
+-
+-              if (!IS_ERR(mmc_key)) {
+-                      ret =  mmc_lock_unlock(card, mmc_key, MMC_LOCK_MODE_CLR_PWD);
+-                      if (!ret)
+-                              ret = len;
+-              } else
+-                      dev_dbg(&card->dev, "request_key returned error %ld\n", PTR_ERR(mmc_key));
+-      } else if (!mmc_card_locked(card) && ((!strncmp(data, "assign", 6)) ||
+-                                            (!strncmp(data, "change", 6)))) {
+-              /* assign or change */
+-              if(!(strncmp(data, "assign", 6)))
+-                      mmc_key = request_key(&mmc_key_type, "mmc:key", "assign");
+-              else
+-                      mmc_key = request_key(&mmc_key_type, "mmc:key", "change");
+-
+-              if (!IS_ERR(mmc_key)) {
+-                      ret = mmc_lock_unlock(card, mmc_key, MMC_LOCK_MODE_SET_PWD);
+-                      if (!ret)
+-                              ret = len;
+-              } else
+-                      dev_dbg(&card->dev, "request_key returned error %ld\n", PTR_ERR(mmc_key));
+-      } else if (mmc_card_locked(card) && !strncmp(data, "unlock", 6)) {
+-              /* unlock */
+-              mmc_key = request_key(&mmc_key_type, "mmc:key", "unlock");
+-              if (!IS_ERR(mmc_key)) {
+-                      ret = mmc_lock_unlock(card, mmc_key, MMC_LOCK_MODE_UNLOCK);
+-                      if (ret) {
+-                              dev_dbg(&card->dev, "Wrong password\n");
+-                              ret = -EINVAL;
+-                      }
+-                      else {
+-                              mmc_release_host(card->host);
+-                              device_release_driver(dev);
+-                              ret = device_attach(dev);
+-                              if(!ret)
+-                                      return -EINVAL;
+-                              else
+-                                      return len;
+-                      }
+-              } else
+-                      dev_dbg(&card->dev, "request_key returned error %ld\n", PTR_ERR(mmc_key));
+-      }
+-
+-      mmc_release_host(card->host);
+-      return ret;
+-}
+-
+-static struct device_attribute mmc_dev_attr_lockable[] = {
+-      __ATTR(lockable, S_IWUSR | S_IRUGO,
+-              mmc_lockable_show, mmc_lockable_store),
+-      __ATTR_NULL,
+-};
+-
+-int mmc_lock_add_sysfs(struct mmc_card *card)
+-{
+-      if (!mmc_card_lockable(card))
+-              return 0;
+-
+-      return mmc_add_attrs(card, mmc_dev_attr_lockable);
+-}
+-
+-void mmc_lock_remove_sysfs(struct mmc_card *card)
+-{
+-      if (!mmc_card_lockable(card))
+-              return;
+-
+-      mmc_remove_attrs(card, mmc_dev_attr_lockable);
+-}
+-
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/lock.h linux-2.6.22-570/drivers/mmc/core/lock.h
+--- linux-2.6.22-590/drivers/mmc/core/lock.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/lock.h   1969-12-31 19:00:00.000000000 -0500
+@@ -1,51 +0,0 @@
+-/*
+- *  linux/drivers/mmc/core/lock.h
+- *
+- *  Copyright 2006 Instituto Nokia de Tecnologia (INdT), All Rights Reserved.
+- *  Copyright 2007 Pierre Ossman
+- *
+- * 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.
+- */
+-#ifndef _MMC_CORE_LOCK_H
+-#define _MMC_CORE_LOCK_H
+-
+-#ifdef CONFIG_MMC_PASSWORDS
+-
+-/* core-internal data */
+-struct mmc_key_payload {
+-      struct rcu_head rcu;            /* RCU destructor */
+-      unsigned short  datalen;        /* length of this data */
+-      char            data[0];        /* actual data */
+-};
+-
+-int mmc_register_key_type(void);
+-void mmc_unregister_key_type(void);
+-
+-int mmc_lock_add_sysfs(struct mmc_card *card);
+-void mmc_lock_remove_sysfs(struct mmc_card *card);
+-
+-#else
+-
+-static inline int mmc_register_key_type(void)
+-{
+-      return 0;
+-}
+-
+-static inline void mmc_unregister_key_type(void)
+-{
+-}
+-
+-static inline int mmc_lock_add_sysfs(struct mmc_card *card)
+-{
+-      return 0;
+-}
+-
+-static inline void mmc_lock_remove_sysfs(struct mmc_card *card)
+-{
+-}
+-
 -#endif
--                      uint8_t type_code;     /* type=8 for FCP */
--              } rff;
-               struct rnn {
-                       uint32_t PortId;        /* For RNN_ID requests */
-                       uint8_t wwnn[8];
-@@ -144,15 +139,42 @@
-                       uint8_t len;
-                       uint8_t symbname[255];
-               } rsnn;
-+              struct rspn {   /* For RSPN_ID requests */
-+                      uint32_t PortId;
-+                      uint8_t len;
-+                      uint8_t symbname[255];
-+              } rspn;
-+              struct gff {
-+                      uint32_t PortId;
-+              } gff;
-+              struct gff_acc {
-+                      uint8_t fbits[128];
-+              } gff_acc;
-+#define FCP_TYPE_FEATURE_OFFSET 4
-+              struct rff {
-+                      uint32_t PortId;
-+                      uint8_t reserved[2];
-+                      uint8_t fbits;
-+                      uint8_t type_code;     /* type=8 for FCP */
-+              } rff;
-       } un;
- };
- #define  SLI_CT_REVISION        1
--#define  GID_REQUEST_SZ         (sizeof(struct lpfc_sli_ct_request) - 260)
--#define  RFT_REQUEST_SZ         (sizeof(struct lpfc_sli_ct_request) - 228)
--#define  RFF_REQUEST_SZ         (sizeof(struct lpfc_sli_ct_request) - 235)
--#define  RNN_REQUEST_SZ         (sizeof(struct lpfc_sli_ct_request) - 252)
--#define  RSNN_REQUEST_SZ        (sizeof(struct lpfc_sli_ct_request))
-+#define  GID_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
-+                         sizeof(struct gid))
-+#define  GFF_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
-+                         sizeof(struct gff))
-+#define  RFT_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
-+                         sizeof(struct rft))
-+#define  RFF_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
-+                         sizeof(struct rff))
-+#define  RNN_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
-+                         sizeof(struct rnn))
-+#define  RSNN_REQUEST_SZ  (offsetof(struct lpfc_sli_ct_request, un) + \
-+                         sizeof(struct rsnn))
-+#define  RSPN_REQUEST_SZ  (offsetof(struct lpfc_sli_ct_request, un) + \
-+                         sizeof(struct rspn))
- /*
-  * FsType Definitions
-@@ -227,6 +249,7 @@
- #define  SLI_CTNS_GFT_ID      0x0117
- #define  SLI_CTNS_GSPN_ID     0x0118
- #define  SLI_CTNS_GPT_ID      0x011A
-+#define  SLI_CTNS_GFF_ID      0x011F
- #define  SLI_CTNS_GID_PN      0x0121
- #define  SLI_CTNS_GID_NN      0x0131
- #define  SLI_CTNS_GIP_NN      0x0135
-@@ -240,9 +263,9 @@
- #define  SLI_CTNS_RNN_ID      0x0213
- #define  SLI_CTNS_RCS_ID      0x0214
- #define  SLI_CTNS_RFT_ID      0x0217
--#define  SLI_CTNS_RFF_ID      0x021F
- #define  SLI_CTNS_RSPN_ID     0x0218
- #define  SLI_CTNS_RPT_ID      0x021A
-+#define  SLI_CTNS_RFF_ID      0x021F
- #define  SLI_CTNS_RIP_NN      0x0235
- #define  SLI_CTNS_RIPA_NN     0x0236
- #define  SLI_CTNS_RSNN_NN     0x0239
-@@ -311,9 +334,9 @@
-       uint8_t bbCreditlsb;    /* FC Word 0, byte 3 */
- #ifdef __BIG_ENDIAN_BITFIELD
--      uint16_t increasingOffset:1;    /* FC Word 1, bit 31 */
-+      uint16_t request_multiple_Nport:1;      /* FC Word 1, bit 31 */
-       uint16_t randomOffset:1;        /* FC Word 1, bit 30 */
--      uint16_t word1Reserved2:1;      /* FC Word 1, bit 29 */
-+      uint16_t response_multiple_NPort:1;     /* FC Word 1, bit 29 */
-       uint16_t fPort:1;       /* FC Word 1, bit 28 */
-       uint16_t altBbCredit:1; /* FC Word 1, bit 27 */
-       uint16_t edtovResolution:1;     /* FC Word 1, bit 26 */
-@@ -332,9 +355,9 @@
-       uint16_t edtovResolution:1;     /* FC Word 1, bit 26 */
-       uint16_t altBbCredit:1; /* FC Word 1, bit 27 */
-       uint16_t fPort:1;       /* FC Word 1, bit 28 */
--      uint16_t word1Reserved2:1;      /* FC Word 1, bit 29 */
-+      uint16_t response_multiple_NPort:1;     /* FC Word 1, bit 29 */
-       uint16_t randomOffset:1;        /* FC Word 1, bit 30 */
--      uint16_t increasingOffset:1;    /* FC Word 1, bit 31 */
-+      uint16_t request_multiple_Nport:1;      /* FC Word 1, bit 31 */
-       uint16_t payloadlength:1;       /* FC Word 1, bit 16 */
-       uint16_t contIncSeqCnt:1;       /* FC Word 1, bit 17 */
-@@ -1255,7 +1278,9 @@
- #define MBX_KILL_BOARD      0x24
- #define MBX_CONFIG_FARP     0x25
- #define MBX_BEACON          0x2A
-+#define MBX_HEARTBEAT       0x31
-+#define MBX_CONFIG_HBQ            0x7C
- #define MBX_LOAD_AREA       0x81
- #define MBX_RUN_BIU_DIAG64  0x84
- #define MBX_CONFIG_PORT     0x88
-@@ -1263,6 +1288,10 @@
- #define MBX_READ_RPI64      0x8F
- #define MBX_REG_LOGIN64     0x93
- #define MBX_READ_LA64       0x95
-+#define MBX_REG_VPI       0x96
-+#define MBX_UNREG_VPI     0x97
-+#define MBX_REG_VNPID     0x96
-+#define MBX_UNREG_VNPID           0x97
- #define MBX_FLASH_WR_ULA    0x98
- #define MBX_SET_DEBUG       0x99
-@@ -1335,6 +1364,10 @@
- #define CMD_FCP_TRECEIVE64_CX   0xA1
- #define CMD_FCP_TRSP64_CX       0xA3
+-
+-#endif
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/mmc.c linux-2.6.22-570/drivers/mmc/core/mmc.c
+--- linux-2.6.22-590/drivers/mmc/core/mmc.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/mmc.c    2007-07-08 19:32:17.000000000 -0400
+@@ -18,8 +18,6 @@
  
-+#define CMD_IOCB_RCV_SEQ64_CX 0xB5
-+#define CMD_IOCB_RCV_ELS64_CX 0xB7
-+#define CMD_IOCB_RCV_CONT64_CX        0xBB
-+
- #define CMD_GEN_REQUEST64_CR    0xC2
- #define CMD_GEN_REQUEST64_CX    0xC3
+ #include "core.h"
+ #include "sysfs.h"
+-#include "bus.h"
+-#include "lock.h"
+ #include "mmc_ops.h"
  
-@@ -1561,6 +1594,7 @@
- #define FLAGS_TOPOLOGY_MODE_PT_PT    0x02 /* Attempt pt-pt only */
- #define FLAGS_TOPOLOGY_MODE_LOOP     0x04 /* Attempt loop only */
- #define FLAGS_TOPOLOGY_MODE_PT_LOOP  0x06 /* Attempt pt-pt then loop */
-+#define       FLAGS_UNREG_LOGIN_ALL        0x08 /* UNREG_LOGIN all on link down */
- #define FLAGS_LIRP_LILP              0x80 /* LIRP / LILP is disabled */
+ static const unsigned int tran_exp[] = {
+@@ -232,74 +230,19 @@
+       return err;
+ }
  
- #define FLAGS_TOPOLOGY_FAILOVER      0x0400   /* Bit 10 */
-@@ -1744,8 +1778,6 @@
- #define LMT_4Gb       0x040
- #define LMT_8Gb       0x080
- #define LMT_10Gb      0x100
+-MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+-      card->raw_cid[2], card->raw_cid[3]);
+-MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+-      card->raw_csd[2], card->raw_csd[3]);
+-MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+-MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev);
+-MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev);
+-MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid);
+-MMC_ATTR_FN(name, "%s\n", card->cid.prod_name);
+-MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid);
+-MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial);
 -
+-static struct device_attribute mmc_dev_attrs[] = {
+-      MMC_ATTR_RO(cid),
+-      MMC_ATTR_RO(csd),
+-      MMC_ATTR_RO(date),
+-      MMC_ATTR_RO(fwrev),
+-      MMC_ATTR_RO(hwrev),
+-      MMC_ATTR_RO(manfid),
+-      MMC_ATTR_RO(name),
+-      MMC_ATTR_RO(oemid),
+-      MMC_ATTR_RO(serial),
+-      __ATTR_NULL,
+-};
 -
-       uint32_t rsvd2;
-       uint32_t rsvd3;
-       uint32_t max_xri;
-@@ -1754,7 +1786,10 @@
-       uint32_t avail_xri;
-       uint32_t avail_iocb;
-       uint32_t avail_rpi;
--      uint32_t default_rpi;
-+      uint32_t max_vpi;
-+      uint32_t rsvd4;
-+      uint32_t rsvd5;
-+      uint32_t avail_vpi;
- } READ_CONFIG_VAR;
- /* Structure for MB Command READ_RCONFIG (12) */
-@@ -1818,6 +1853,13 @@
-                                     structure */
-               struct ulp_bde64 sp64;
-       } un;
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint16_t rsvd3;
-+      uint16_t vpi;
-+#else /*  __LITTLE_ENDIAN_BITFIELD */
-+      uint16_t vpi;
-+      uint16_t rsvd3;
-+#endif
- } READ_SPARM_VAR;
- /* Structure for MB Command READ_STATUS (14) */
-@@ -1918,11 +1960,17 @@
- #ifdef __BIG_ENDIAN_BITFIELD
-       uint32_t cv:1;
-       uint32_t rr:1;
--      uint32_t rsvd1:29;
-+      uint32_t rsvd2:2;
-+      uint32_t v3req:1;
-+      uint32_t v3rsp:1;
-+      uint32_t rsvd1:25;
-       uint32_t rv:1;
- #else /*  __LITTLE_ENDIAN_BITFIELD */
-       uint32_t rv:1;
--      uint32_t rsvd1:29;
-+      uint32_t rsvd1:25;
-+      uint32_t v3rsp:1;
-+      uint32_t v3req:1;
-+      uint32_t rsvd2:2;
-       uint32_t rr:1;
-       uint32_t cv:1;
- #endif
-@@ -1972,8 +2020,8 @@
-       uint8_t sli1FwName[16];
-       uint32_t sli2FwRev;
-       uint8_t sli2FwName[16];
--      uint32_t rsvd2;
--      uint32_t RandomData[7];
-+      uint32_t sli3Feat;
-+      uint32_t RandomData[6];
- } READ_REV_VAR;
- /* Structure for MB Command READ_LINK_STAT (18) */
-@@ -2013,6 +2061,14 @@
-               struct ulp_bde64 sp64;
-       } un;
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint16_t rsvd6;
-+      uint16_t vpi;
-+#else /* __LITTLE_ENDIAN_BITFIELD */
-+      uint16_t vpi;
-+      uint16_t rsvd6;
-+#endif
-+
- } REG_LOGIN_VAR;
- /* Word 30 contents for REG_LOGIN */
-@@ -2037,16 +2093,78 @@
- #ifdef __BIG_ENDIAN_BITFIELD
-       uint16_t rsvd1;
-       uint16_t rpi;
-+      uint32_t rsvd2;
-+      uint32_t rsvd3;
-+      uint32_t rsvd4;
-+      uint32_t rsvd5;
-+      uint16_t rsvd6;
-+      uint16_t vpi;
- #else /*  __LITTLE_ENDIAN_BITFIELD */
-       uint16_t rpi;
-       uint16_t rsvd1;
-+      uint32_t rsvd2;
-+      uint32_t rsvd3;
-+      uint32_t rsvd4;
-+      uint32_t rsvd5;
-+      uint16_t vpi;
-+      uint16_t rsvd6;
- #endif
- } UNREG_LOGIN_VAR;
-+/* Structure for MB Command REG_VPI (0x96) */
-+typedef struct {
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint32_t rsvd1;
-+      uint32_t rsvd2:8;
-+      uint32_t sid:24;
-+      uint32_t rsvd3;
-+      uint32_t rsvd4;
-+      uint32_t rsvd5;
-+      uint16_t rsvd6;
-+      uint16_t vpi;
-+#else /*  __LITTLE_ENDIAN */
-+      uint32_t rsvd1;
-+      uint32_t sid:24;
-+      uint32_t rsvd2:8;
-+      uint32_t rsvd3;
-+      uint32_t rsvd4;
-+      uint32_t rsvd5;
-+      uint16_t vpi;
-+      uint16_t rsvd6;
-+#endif
-+} REG_VPI_VAR;
-+
-+/* Structure for MB Command UNREG_VPI (0x97) */
-+typedef struct {
-+      uint32_t rsvd1;
-+      uint32_t rsvd2;
-+      uint32_t rsvd3;
-+      uint32_t rsvd4;
-+      uint32_t rsvd5;
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint16_t rsvd6;
-+      uint16_t vpi;
-+#else /*  __LITTLE_ENDIAN */
-+      uint16_t vpi;
-+      uint16_t rsvd6;
-+#endif
-+} UNREG_VPI_VAR;
-+
- /* Structure for MB Command UNREG_D_ID (0x23) */
- typedef struct {
-       uint32_t did;
-+      uint32_t rsvd2;
-+      uint32_t rsvd3;
-+      uint32_t rsvd4;
-+      uint32_t rsvd5;
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint16_t rsvd6;
-+      uint16_t vpi;
-+#else
-+      uint16_t vpi;
-+      uint16_t rsvd6;
-+#endif
- } UNREG_D_ID_VAR;
+-/*
+- * Adds sysfs entries as relevant.
+- */
+-static int mmc_sysfs_add(struct mmc_card *card)
+-{
+-      int ret;
+-
+-      ret = mmc_add_attrs(card, mmc_dev_attrs);
+-      if (ret < 0)
+-              return ret;
+-
+-      ret = mmc_lock_add_sysfs(card);
+-      if (ret < 0) {
+-              mmc_remove_attrs(card, mmc_dev_attrs);
+-              return ret;
+-      }
+-
+-      return 0;
+-}
+-
+-/*
+- * Removes the sysfs entries added by mmc_sysfs_add().
+- */
+-static void mmc_sysfs_remove(struct mmc_card *card)
+-{
+-      mmc_lock_remove_sysfs(card);
+-      mmc_remove_attrs(card, mmc_dev_attrs);
+-}
+-
+ /*
+  * Handle the detection and initialisation of a card.
+  *
+  * In the case of a resume, "curcard" will contain the card
+  * we're trying to reinitialise.
+  */
+-static int mmc_init_card(struct mmc_host *host, u32 ocr,
++static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+       struct mmc_card *oldcard)
+ {
+       struct mmc_card *card;
+       int err;
+       u32 cid[4];
+       unsigned int max_dtr;
+-      u32 status;
  
- /* Structure for MB Command READ_LA (21) */
-@@ -2178,13 +2296,240 @@
- #define  DMP_RSP_OFFSET          0x14   /* word 5 contains first word of rsp */
- #define  DMP_RSP_SIZE            0x6C   /* maximum of 27 words of rsp data */
+       BUG_ON(!host);
+       BUG_ON(!host->claimed);
+@@ -351,15 +294,6 @@
  
--/* Structure for MB Command CONFIG_PORT (0x88) */
-+struct hbq_mask {
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint8_t tmatch;
-+      uint8_t tmask;
-+      uint8_t rctlmatch;
-+      uint8_t rctlmask;
-+#else /*  __LITTLE_ENDIAN */
-+      uint8_t rctlmask;
-+      uint8_t rctlmatch;
-+      uint8_t tmask;
-+      uint8_t tmatch;
-+#endif
-+};
+       mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
  
-+
-+/* Structure for MB Command CONFIG_HBQ (7c) */
-+
-+struct config_hbq_var {
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint32_t rsvd1      :7;
-+      uint32_t recvNotify :1;     /* Receive Notification */
-+      uint32_t numMask    :8;     /* # Mask Entries       */
-+      uint32_t profile    :8;     /* Selection Profile    */
-+      uint32_t rsvd2      :8;
-+#else /*  __LITTLE_ENDIAN */
-+      uint32_t rsvd2      :8;
-+      uint32_t profile    :8;     /* Selection Profile    */
-+      uint32_t numMask    :8;     /* # Mask Entries       */
-+      uint32_t recvNotify :1;     /* Receive Notification */
-+      uint32_t rsvd1      :7;
-+#endif
-+
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint32_t hbqId      :16;
-+      uint32_t rsvd3      :12;
-+      uint32_t ringMask   :4;
-+#else /*  __LITTLE_ENDIAN */
-+      uint32_t ringMask   :4;
-+      uint32_t rsvd3      :12;
-+      uint32_t hbqId      :16;
-+#endif
-+
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint32_t entry_count :16;
-+      uint32_t rsvd4        :8;
-+      uint32_t headerLen    :8;
-+#else /*  __LITTLE_ENDIAN */
-+      uint32_t headerLen    :8;
-+      uint32_t rsvd4        :8;
-+      uint32_t entry_count :16;
-+#endif
-+
-+      uint32_t hbqaddrLow;
-+      uint32_t hbqaddrHigh;
-+
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint32_t rsvd5      :31;
-+      uint32_t logEntry   :1;
-+#else /*  __LITTLE_ENDIAN */
-+      uint32_t logEntry   :1;
-+      uint32_t rsvd5      :31;
-+#endif
-+
-+      uint32_t rsvd6;    /* w7 */
-+      uint32_t rsvd7;    /* w8 */
-+      uint32_t rsvd8;    /* w9 */
-+
-+      struct hbq_mask hbqMasks[6];
-+
-+
-+      union {
-+              uint32_t allprofiles[12];
-+
-+              struct {
-+                      #ifdef __BIG_ENDIAN_BITFIELD
-+                              uint32_t        seqlenoff       :16;
-+                              uint32_t        maxlen          :16;
-+                      #else   /*  __LITTLE_ENDIAN */
-+                              uint32_t        maxlen          :16;
-+                              uint32_t        seqlenoff       :16;
-+                      #endif
-+                      #ifdef __BIG_ENDIAN_BITFIELD
-+                              uint32_t        rsvd1           :28;
-+                              uint32_t        seqlenbcnt      :4;
-+                      #else   /*  __LITTLE_ENDIAN */
-+                              uint32_t        seqlenbcnt      :4;
-+                              uint32_t        rsvd1           :28;
-+                      #endif
-+                      uint32_t rsvd[10];
-+              } profile2;
-+
-+              struct {
-+                      #ifdef __BIG_ENDIAN_BITFIELD
-+                              uint32_t        seqlenoff       :16;
-+                              uint32_t        maxlen          :16;
-+                      #else   /*  __LITTLE_ENDIAN */
-+                              uint32_t        maxlen          :16;
-+                              uint32_t        seqlenoff       :16;
-+                      #endif
-+                      #ifdef __BIG_ENDIAN_BITFIELD
-+                              uint32_t        cmdcodeoff      :28;
-+                              uint32_t        rsvd1           :12;
-+                              uint32_t        seqlenbcnt      :4;
-+                      #else   /*  __LITTLE_ENDIAN */
-+                              uint32_t        seqlenbcnt      :4;
-+                              uint32_t        rsvd1           :12;
-+                              uint32_t        cmdcodeoff      :28;
-+                      #endif
-+                      uint32_t cmdmatch[8];
-+
-+                      uint32_t rsvd[2];
-+              } profile3;
-+
-+              struct {
-+                      #ifdef __BIG_ENDIAN_BITFIELD
-+                              uint32_t        seqlenoff       :16;
-+                              uint32_t        maxlen          :16;
-+                      #else   /*  __LITTLE_ENDIAN */
-+                              uint32_t        maxlen          :16;
-+                              uint32_t        seqlenoff       :16;
-+                      #endif
-+                      #ifdef __BIG_ENDIAN_BITFIELD
-+                              uint32_t        cmdcodeoff      :28;
-+                              uint32_t        rsvd1           :12;
-+                              uint32_t        seqlenbcnt      :4;
-+                      #else   /*  __LITTLE_ENDIAN */
-+                              uint32_t        seqlenbcnt      :4;
-+                              uint32_t        rsvd1           :12;
-+                              uint32_t        cmdcodeoff      :28;
-+                      #endif
-+                      uint32_t cmdmatch[8];
-+
-+                      uint32_t rsvd[2];
-+              } profile5;
-+
-+      } profiles;
-+
-+};
-+
-+
-+
-+/* Structure for MB Command CONFIG_PORT (0x88) */
- typedef struct {
--      uint32_t pcbLen;
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint32_t cBE       :  1;
-+      uint32_t cET       :  1;
-+      uint32_t cHpcb     :  1;
-+      uint32_t cMA       :  1;
-+      uint32_t sli_mode  :  4;
-+      uint32_t pcbLen    : 24;       /* bit 23:0  of memory based port
-+                                      * config block */
-+#else /*  __LITTLE_ENDIAN */
-+      uint32_t pcbLen    : 24;       /* bit 23:0  of memory based port
-+                                      * config block */
-+      uint32_t sli_mode  :  4;
-+      uint32_t cMA       :  1;
-+      uint32_t cHpcb     :  1;
-+      uint32_t cET       :  1;
-+      uint32_t cBE       :  1;
-+#endif
-+
-       uint32_t pcbLow;       /* bit 31:0  of memory based port config block */
-       uint32_t pcbHigh;      /* bit 63:32 of memory based port config block */
--      uint32_t hbainit[5];
-+      uint32_t hbainit[6];
-+
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint32_t rsvd      : 24;  /* Reserved                             */
-+      uint32_t cmv       :  1;  /* Configure Max VPIs                   */
-+      uint32_t ccrp      :  1;  /* Config Command Ring Polling          */
-+      uint32_t csah      :  1;  /* Configure Synchronous Abort Handling */
-+      uint32_t chbs      :  1;  /* Cofigure Host Backing store          */
-+      uint32_t cinb      :  1;  /* Enable Interrupt Notification Block  */
-+      uint32_t cerbm     :  1;  /* Configure Enhanced Receive Buf Mgmt  */
-+      uint32_t cmx       :  1;  /* Configure Max XRIs                   */
-+      uint32_t cmr       :  1;  /* Configure Max RPIs                   */
-+#else /*  __LITTLE_ENDIAN */
-+      uint32_t cmr       :  1;  /* Configure Max RPIs                   */
-+      uint32_t cmx       :  1;  /* Configure Max XRIs                   */
-+      uint32_t cerbm     :  1;  /* Configure Enhanced Receive Buf Mgmt  */
-+      uint32_t cinb      :  1;  /* Enable Interrupt Notification Block  */
-+      uint32_t chbs      :  1;  /* Cofigure Host Backing store          */
-+      uint32_t csah      :  1;  /* Configure Synchronous Abort Handling */
-+      uint32_t ccrp      :  1;  /* Config Command Ring Polling          */
-+      uint32_t cmv       :  1;  /* Configure Max VPIs                   */
-+      uint32_t rsvd      : 24;  /* Reserved                             */
-+#endif
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint32_t rsvd2     : 24;  /* Reserved                             */
-+      uint32_t gmv       :  1;  /* Grant Max VPIs                       */
-+      uint32_t gcrp      :  1;  /* Grant Command Ring Polling           */
-+      uint32_t gsah      :  1;  /* Grant Synchronous Abort Handling     */
-+      uint32_t ghbs      :  1;  /* Grant Host Backing Store             */
-+      uint32_t ginb      :  1;  /* Grant Interrupt Notification Block   */
-+      uint32_t gerbm     :  1;  /* Grant ERBM Request                   */
-+      uint32_t gmx       :  1;  /* Grant Max XRIs                       */
-+      uint32_t gmr       :  1;  /* Grant Max RPIs                       */
-+#else /*  __LITTLE_ENDIAN */
-+      uint32_t gmr       :  1;  /* Grant Max RPIs                       */
-+      uint32_t gmx       :  1;  /* Grant Max XRIs                       */
-+      uint32_t gerbm     :  1;  /* Grant ERBM Request                   */
-+      uint32_t ginb      :  1;  /* Grant Interrupt Notification Block   */
-+      uint32_t ghbs      :  1;  /* Grant Host Backing Store             */
-+      uint32_t gsah      :  1;  /* Grant Synchronous Abort Handling     */
-+      uint32_t gcrp      :  1;  /* Grant Command Ring Polling           */
-+      uint32_t gmv       :  1;  /* Grant Max VPIs                       */
-+      uint32_t rsvd2     : 24;  /* Reserved                             */
-+#endif
-+
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint32_t max_rpi   : 16;  /* Max RPIs Port should configure       */
-+      uint32_t max_xri   : 16;  /* Max XRIs Port should configure       */
-+#else /*  __LITTLE_ENDIAN */
-+      uint32_t max_xri   : 16;  /* Max XRIs Port should configure       */
-+      uint32_t max_rpi   : 16;  /* Max RPIs Port should configure       */
-+#endif
-+
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint32_t max_hbq   : 16;  /* Max HBQs Host expect to configure    */
-+      uint32_t rsvd3     : 16;  /* Max HBQs Host expect to configure    */
-+#else /*  __LITTLE_ENDIAN */
-+      uint32_t rsvd3     : 16;  /* Max HBQs Host expect to configure    */
-+      uint32_t max_hbq   : 16;  /* Max HBQs Host expect to configure    */
-+#endif
-+
-+      uint32_t rsvd4;           /* Reserved                             */
-+
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint32_t rsvd5      : 16;  /* Reserved                             */
-+      uint32_t max_vpi    : 16;  /* Max number of virt N-Ports           */
-+#else /*  __LITTLE_ENDIAN */
-+      uint32_t max_vpi    : 16;  /* Max number of virt N-Ports           */
-+      uint32_t rsvd5      : 16;  /* Reserved                             */
-+#endif
-+
- } CONFIG_PORT_VAR;
+-      /*
+-       * Check if card is locked.
+-       */
+-      err = mmc_send_status(card, &status);
+-      if (err != MMC_ERR_NONE)
+-              goto free_card;
+-      if (status & R1_CARD_IS_LOCKED)
+-              mmc_card_set_locked(card);
+-
+       if (!oldcard) {
+               /*
+                * Fetch CSD from card.
+@@ -455,8 +389,6 @@
+       BUG_ON(!host);
+       BUG_ON(!host->card);
  
- /* SLI-2 Port Control Block */
-@@ -2262,7 +2607,9 @@
- #define MAILBOX_CMD_SIZE      (MAILBOX_CMD_WSIZE * sizeof(uint32_t))
+-      mmc_sysfs_remove(host->card);
+-
+       mmc_remove_card(host->card);
+       host->card = NULL;
+ }
+@@ -481,7 +413,8 @@
+       mmc_release_host(host);
  
- typedef union {
--      uint32_t varWords[MAILBOX_CMD_WSIZE - 1];
-+      uint32_t varWords[MAILBOX_CMD_WSIZE - 1]; /* first word is type/
-+                                                  * feature/max ring number
-+                                                  */
-       LOAD_SM_VAR varLdSM;    /* cmd =  1 (LOAD_SM)        */
-       READ_NV_VAR varRDnvp;   /* cmd =  2 (READ_NVPARMS)   */
-       WRITE_NV_VAR varWTnvp;  /* cmd =  3 (WRITE_NVPARMS)  */
-@@ -2287,8 +2634,13 @@
-       CLEAR_LA_VAR varClearLA;        /* cmd = 22 (CLEAR_LA)       */
-       DUMP_VAR varDmp;        /* Warm Start DUMP mbx cmd   */
-       UNREG_D_ID_VAR varUnregDID; /* cmd = 0x23 (UNREG_D_ID)   */
--      CONFIG_FARP_VAR varCfgFarp; /* cmd = 0x25 (CONFIG_FARP)  NEW_FEATURE */
-+      CONFIG_FARP_VAR varCfgFarp;     /* cmd = 0x25 (CONFIG_FARP)
-+                                       * NEW_FEATURE
-+                                       */
-+      struct config_hbq_var varCfgHbq;/* cmd = 0x7c (CONFIG_HBQ)  */
-       CONFIG_PORT_VAR varCfgPort; /* cmd = 0x88 (CONFIG_PORT)  */
-+      REG_VPI_VAR varRegVpi;          /* cmd = 0x96 (REG_VPI) */
-+      UNREG_VPI_VAR varUnregVpi;      /* cmd = 0x97 (UNREG_VPI) */
- } MAILVARIANTS;
+       if (err != MMC_ERR_NONE) {
+-              mmc_remove(host);
++              mmc_remove_card(host->card);
++              host->card = NULL;
  
- /*
-@@ -2305,14 +2657,27 @@
-       __le32 rspPutInx;
- };
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
+@@ -501,7 +434,7 @@
  
--typedef struct _SLI2_DESC {
--      struct lpfc_hgp host[MAX_RINGS];
-+struct sli2_desc {
-       uint32_t unused1[16];
-+      struct lpfc_hgp host[MAX_RINGS];
-       struct lpfc_pgp port[MAX_RINGS];
--} SLI2_DESC;
-+};
-+
-+struct sli3_desc {
-+      struct lpfc_hgp host[MAX_RINGS];
-+      uint32_t reserved[8];
-+      uint32_t hbq_put[16];
-+};
-+
-+struct sli3_pgp {
-+      struct lpfc_pgp port[MAX_RINGS];
-+      uint32_t hbq_get[16];
-+};
+       mmc_claim_host(host);
+       mmc_deselect_cards(host);
+-      host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_LOCKED);
++      host->card->state &= ~MMC_STATE_HIGHSPEED;
+       mmc_release_host(host);
+ }
  
- typedef union {
--      SLI2_DESC s2;
-+      struct sli2_desc s2;
-+      struct sli3_desc s3;
-+      struct sli3_pgp  s3_pgp;
- } SLI_VAR;
+@@ -520,9 +453,11 @@
  
- typedef struct {
-@@ -2618,6 +2983,25 @@
-       uint32_t fcpt_Length;   /* transfer ready for IWRITE */
- } FCPT_FIELDS64;
+       mmc_claim_host(host);
  
-+/* IOCB Command template for CMD_IOCB_RCV_ELS64_CX (0xB7)
-+   or CMD_IOCB_RCV_SEQ64_CX (0xB5) */
-+
-+struct rcv_sli3 {
-+      uint32_t word8Rsvd;
-+#ifdef __BIG_ENDIAN_BITFIELD
-+      uint16_t vpi;
-+      uint16_t word9Rsvd;
-+#else  /*  __LITTLE_ENDIAN */
-+      uint16_t word9Rsvd;
-+      uint16_t vpi;
-+#endif
-+      uint32_t word10Rsvd;
-+      uint32_t acc_len;      /* accumulated length */
-+      struct ulp_bde64 bde2;
-+};
-+
-+
+-      err = mmc_init_card(host, host->ocr, host->card);
++      err = mmc_sd_init_card(host, host->ocr, host->card);
+       if (err != MMC_ERR_NONE) {
+-              mmc_remove(host);
++              mmc_remove_card(host->card);
++              host->card = NULL;
 +
- typedef struct _IOCB {        /* IOCB structure */
-       union {
-               GENERIC_RSP grsp;       /* Generic response */
-@@ -2633,7 +3017,7 @@
-               /* SLI-2 structures */
-               struct ulp_bde64 cont64[2];     /* up to 2 64 bit continuation
--                                         bde_64s */
-+                                            * bde_64s */
-               ELS_REQUEST64 elsreq64; /* ELS_REQUEST template */
-               GEN_REQUEST64 genreq64; /* GEN_REQUEST template */
-               RCV_ELS_REQ64 rcvels64; /* RCV_ELS_REQ template */
-@@ -2695,9 +3079,20 @@
-       uint32_t ulpTimeout:8;
- #endif
+               mmc_detach_bus(host);
+       }
  
-+      union {
-+              struct rcv_sli3 rcvsli3; /* words 8 - 15 */
-+              uint32_t sli3Words[24]; /* 96 extra bytes for SLI-3 */
-+      } unsli3;
-+
-+#define ulpCt_h ulpXS
-+#define ulpCt_l ulpFCP2Rcvy
-+
-+#define IOCB_FCP         1    /* IOCB is used for FCP ELS cmds-ulpRsvByte */
-+#define IOCB_IP                  2    /* IOCB is used for IP ELS cmds */
- #define PARM_UNUSED        0  /* PU field (Word 4) not used */
- #define PARM_REL_OFF       1  /* PU field (Word 4) = R. O. */
- #define PARM_READ_CHECK    2  /* PU field (Word 4) = Data Transfer Length */
-+#define PARM_NPIV_DID    3
- #define CLASS1             0  /* Class 1 */
- #define CLASS2             1  /* Class 2 */
- #define CLASS3             2  /* Class 3 */
-@@ -2718,39 +3113,51 @@
- #define IOSTAT_RSVD2           0xC
- #define IOSTAT_RSVD3           0xD
- #define IOSTAT_RSVD4           0xE
--#define IOSTAT_RSVD5           0xF
-+#define IOSTAT_NEED_BUFFER     0xF
- #define IOSTAT_DRIVER_REJECT   0x10   /* ulpStatus  - Driver defined */
- #define IOSTAT_DEFAULT         0xF    /* Same as rsvd5 for now */
- #define IOSTAT_CNT             0x11
+@@ -577,17 +512,13 @@
+       /*
+        * Detect and init the card.
+        */
+-      err = mmc_init_card(host, host->ocr, NULL);
++      err = mmc_sd_init_card(host, host->ocr, NULL);
+       if (err != MMC_ERR_NONE)
+               goto err;
  
} IOCB_t;
      mmc_release_host(host);
  
-+/* Structure used for a single HBQ entry */
-+struct lpfc_hbq_entry {
-+      struct ulp_bde64 bde;
-+      uint32_t buffer_tag;
-+};
-+
+-      err = mmc_add_card(host->card);
+-      if (err)
+-              goto reclaim_host;
+-
+-      err = mmc_sysfs_add(host->card);
++      err = mmc_register_card(host->card);
+       if (err)
+               goto reclaim_host;
  
- #define SLI1_SLIM_SIZE   (4 * 1024)
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/mmc_ops.c linux-2.6.22-570/drivers/mmc/core/mmc_ops.c
+--- linux-2.6.22-590/drivers/mmc/core/mmc_ops.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/mmc_ops.c        2007-07-08 19:32:17.000000000 -0400
+@@ -2,8 +2,6 @@
+  *  linux/drivers/mmc/mmc_ops.h
+  *
+  *  Copyright 2006-2007 Pierre Ossman
+- *  MMC password protection (C) 2006 Instituto Nokia de Tecnologia (INdT),
+- *     All Rights Reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+@@ -14,14 +12,12 @@
+ #include <linux/types.h>
+ #include <asm/scatterlist.h>
+ #include <linux/scatterlist.h>
+-#include <linux/key.h>
  
- /* Up to 498 IOCBs will fit into 16k
-  * 256 (MAILBOX_t) + 140 (PCB_t) + ( 32 (IOCB_t) * 498 ) = < 16384
-  */
--#define SLI2_SLIM_SIZE   (16 * 1024)
-+#define SLI2_SLIM_SIZE   (64 * 1024)
+ #include <linux/mmc/host.h>
+ #include <linux/mmc/card.h>
+ #include <linux/mmc/mmc.h>
  
- /* Maximum IOCBs that will fit in SLI2 slim */
- #define MAX_SLI2_IOCB    498
-+#define MAX_SLIM_IOCB_SIZE (SLI2_SLIM_SIZE - \
-+                          (sizeof(MAILBOX_t) + sizeof(PCB_t)))
-+
-+/* HBQ entries are 4 words each = 4k */
-+#define LPFC_TOTAL_HBQ_SIZE (sizeof(struct lpfc_hbq_entry) *  \
-+                           lpfc_sli_hbq_count())
+ #include "core.h"
+-#include "lock.h"
+ #include "mmc_ops.h"
  
- struct lpfc_sli2_slim {
-       MAILBOX_t mbx;
-       PCB_t pcb;
--      IOCB_t IOCBs[MAX_SLI2_IOCB];
-+      IOCB_t IOCBs[MAX_SLIM_IOCB_SIZE];
- };
+ static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
+@@ -278,114 +274,3 @@
+       return MMC_ERR_NONE;
+ }
  
--/*******************************************************************
--This macro check PCI device to allow special handling for LC HBAs.
+-#ifdef CONFIG_MMC_PASSWORDS
 -
--Parameters:
--device : struct pci_dev 's device field
+-int mmc_lock_unlock(struct mmc_card *card, struct key *key, int mode)
+-{
+-      struct mmc_request mrq;
+-      struct mmc_command cmd;
+-      struct mmc_data data;
+-      struct scatterlist sg;
+-      struct mmc_key_payload *mpayload;
+-      unsigned long erase_timeout;
+-      int err, data_size;
+-      u8 *data_buf;
 -
--return 1 => TRUE
--       0 => FALSE
-- *******************************************************************/
-+/*
-+ * This function checks PCI device to allow special handling for LC HBAs.
-+ *
-+ * Parameters:
-+ * device : struct pci_dev 's device field
-+ *
-+ * return 1 => TRUE
-+ *        0 => FALSE
-+ */
- static inline int
- lpfc_is_LC_HBA(unsigned short device)
- {
-@@ -2766,3 +3173,16 @@
-       else
-               return 0;
- }
-+
-+/*
-+ * Determine if an IOCB failed because of a link event or firmware reset.
-+ */
-+
-+static inline int
-+lpfc_error_lost_link(IOCB_t *iocbp)
-+{
-+      return (iocbp->ulpStatus == IOSTAT_LOCAL_REJECT &&
-+              (iocbp->un.ulpWord[4] == IOERR_SLI_ABORTED ||
-+               iocbp->un.ulpWord[4] == IOERR_LINK_DOWN ||
-+               iocbp->un.ulpWord[4] == IOERR_SLI_DOWN));
-+}
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_init.c linux-2.6.22-590/drivers/scsi/lpfc/lpfc_init.c
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_init.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_init.c     2008-01-02 13:56:37.000000000 -0500
-@@ -27,6 +27,7 @@
- #include <linux/kthread.h>
- #include <linux/pci.h>
- #include <linux/spinlock.h>
-+#include <linux/ctype.h>
- #include <scsi/scsi.h>
- #include <scsi/scsi_device.h>
-@@ -40,15 +41,20 @@
- #include "lpfc.h"
- #include "lpfc_logmsg.h"
- #include "lpfc_crtn.h"
-+#include "lpfc_vport.h"
- #include "lpfc_version.h"
-+#include "lpfc_vport.h"
- static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int);
- static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
- static int lpfc_post_rcv_buf(struct lpfc_hba *);
- static struct scsi_transport_template *lpfc_transport_template = NULL;
-+static struct scsi_transport_template *lpfc_vport_transport_template = NULL;
- static DEFINE_IDR(lpfc_hba_index);
-+
-+
- /************************************************************************/
- /*                                                                      */
- /*    lpfc_config_port_prep                                             */
-@@ -61,7 +67,7 @@
- /*                                                                      */
- /************************************************************************/
- int
--lpfc_config_port_prep(struct lpfc_hba * phba)
-+lpfc_config_port_prep(struct lpfc_hba *phba)
- {
-       lpfc_vpd_t *vp = &phba->vpd;
-       int i = 0, rc;
-@@ -75,12 +81,12 @@
-       pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-       if (!pmb) {
--              phba->hba_state = LPFC_HBA_ERROR;
-+              phba->link_state = LPFC_HBA_ERROR;
-               return -ENOMEM;
-       }
-       mb = &pmb->mb;
--      phba->hba_state = LPFC_INIT_MBX_CMDS;
-+      phba->link_state = LPFC_INIT_MBX_CMDS;
-       if (lpfc_is_LC_HBA(phba->pcidev->device)) {
-               if (init_key) {
-@@ -100,9 +106,7 @@
-               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
+-      mpayload = NULL;
+-      data_size = 1;
+-      if (!(mode & MMC_LOCK_MODE_ERASE)) {
+-              mpayload = rcu_dereference(key->payload.data);
+-              data_size = 2 + mpayload->datalen;
+-      }
+-
+-      data_buf = kmalloc(data_size, GFP_KERNEL);
+-      if (!data_buf)
+-              return -ENOMEM;
+-      memset(data_buf, 0, data_size);
+-
+-      data_buf[0] |= mode;
+-      if (mode & MMC_LOCK_MODE_UNLOCK)
+-              data_buf[0] &= ~MMC_LOCK_MODE_UNLOCK;
+-
+-      if (!(mode & MMC_LOCK_MODE_ERASE)) {
+-              data_buf[1] = mpayload->datalen;
+-              memcpy(data_buf + 2, mpayload->data, mpayload->datalen);
+-      }
+-
+-      memset(&cmd, 0, sizeof(struct mmc_command));
+-
+-      cmd.opcode = MMC_SET_BLOCKLEN;
+-      cmd.arg = data_size;
+-      cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+-      err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+-      if (err != MMC_ERR_NONE)
+-              goto out;
+-
+-      memset(&cmd, 0, sizeof(struct mmc_command));
+-
+-      cmd.opcode = MMC_LOCK_UNLOCK;
+-      cmd.arg = 0;
+-      cmd.flags = MMC_RSP_R1B | MMC_CMD_ADTC;
+-
+-      memset(&data, 0, sizeof(struct mmc_data));
+-
+-      mmc_set_data_timeout(&data, card, 1);
+-
+-      data.blksz = data_size;
+-      data.blocks = 1;
+-      data.flags = MMC_DATA_WRITE;
+-      data.sg = &sg;
+-      data.sg_len = 1;
+-
+-      memset(&mrq, 0, sizeof(struct mmc_request));
+-
+-      mrq.cmd = &cmd;
+-      mrq.data = &data;
+-
+-      sg_init_one(&sg, data_buf, data_size);
+-      err = mmc_wait_for_req(card->host, &mrq);
+-      if (err != MMC_ERR_NONE)
+-              goto out;
+-
+-      memset(&cmd, 0, sizeof(struct mmc_command));
+-
+-      cmd.opcode = MMC_SEND_STATUS;
+-      cmd.arg = card->rca << 16;
+-      cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+-
+-      /* set timeout for forced erase operation to 3 min. (see MMC spec) */
+-      erase_timeout = jiffies + 180 * HZ;
+-      do {
+-              /* we cannot use "retries" here because the
+-               * R1_LOCK_UNLOCK_FAILED bit is cleared by subsequent reads to
+-               * the status register, hiding the error condition */
+-              err = mmc_wait_for_cmd(card->host, &cmd, 0);
+-              if (err != MMC_ERR_NONE)
+-                      break;
+-              /* the other modes don't need timeout checking */
+-              if (!(mode & MMC_LOCK_MODE_ERASE))
+-                      continue;
+-              if (time_after(jiffies, erase_timeout)) {
+-                      dev_dbg(&card->dev, "forced erase timed out\n");
+-                      err = MMC_ERR_TIMEOUT;
+-                      break;
+-              }
+-      } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
+-      if (cmd.resp[0] & R1_LOCK_UNLOCK_FAILED) {
+-              dev_dbg(&card->dev, "LOCK_UNLOCK operation failed\n");
+-              err = MMC_ERR_FAILED;
+-      }
+-
+-      if (cmd.resp[0] & R1_CARD_IS_LOCKED)
+-              mmc_card_set_locked(card);
+-      else
+-              card->state &= ~MMC_STATE_LOCKED;
+-
+-out:
+-      kfree(data_buf);
+-
+-      return err;
+-}
+-
+-#endif /* CONFIG_MMC_PASSWORDS */
+-
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/mmc_ops.h linux-2.6.22-570/drivers/mmc/core/mmc_ops.h
+--- linux-2.6.22-590/drivers/mmc/core/mmc_ops.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/mmc_ops.h        2007-07-08 19:32:17.000000000 -0400
+@@ -12,8 +12,6 @@
+ #ifndef _MMC_MMC_OPS_H
+ #define _MMC_MMC_OPS_H
  
-               if (rc != MBX_SUCCESS) {
--                      lpfc_printf_log(phba,
--                                      KERN_ERR,
--                                      LOG_MBOX,
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
-                                       "%d:0324 Config Port initialization "
-                                       "error, mbxCmd x%x READ_NVPARM, "
-                                       "mbxStatus x%x\n",
-@@ -112,16 +116,18 @@
-                       return -ERESTART;
-               }
-               memcpy(phba->wwnn, (char *)mb->un.varRDnvp.nodename,
--                     sizeof (mb->un.varRDnvp.nodename));
-+                     sizeof(phba->wwnn));
-+              memcpy(phba->wwpn, (char *)mb->un.varRDnvp.portname,
-+                     sizeof(phba->wwpn));
-       }
+-struct key;
+-
+ int mmc_select_card(struct mmc_card *card);
+ int mmc_deselect_cards(struct mmc_host *host);
+ int mmc_go_idle(struct mmc_host *host);
+@@ -24,7 +22,6 @@
+ int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
+ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value);
+ int mmc_send_status(struct mmc_card *card, u32 *status);
+-int mmc_lock_unlock(struct mmc_card *card, struct key *key, int mode);
  
-+      phba->sli3_options = 0x0;
-+
-       /* Setup and issue mailbox READ REV command */
-       lpfc_read_rev(phba, pmb);
-       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
-       if (rc != MBX_SUCCESS) {
--              lpfc_printf_log(phba,
--                              KERN_ERR,
--                              LOG_INIT,
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "%d:0439 Adapter failed to init, mbxCmd x%x "
-                               "READ_REV, mbxStatus x%x\n",
-                               phba->brd_no,
-@@ -130,6 +136,7 @@
-               return -ERESTART;
-       }
+ #endif
  
-+
-       /*
-        * The value of rr must be 1 since the driver set the cv field to 1.
-        * This setting requires the FW to set all revision fields.
-@@ -144,8 +151,12 @@
-               return -ERESTART;
-       }
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/sd.c linux-2.6.22-570/drivers/mmc/core/sd.c
+--- linux-2.6.22-590/drivers/mmc/core/sd.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/sd.c     2007-07-08 19:32:17.000000000 -0400
+@@ -19,11 +19,11 @@
  
-+      if (phba->sli_rev == 3 && !mb->un.varRdRev.v3rsp)
-+              return -EINVAL;
-+
-       /* Save information as VPD data */
-       vp->rev.rBit = 1;
-+      memcpy(&vp->sli3Feat, &mb->un.varRdRev.sli3Feat, sizeof(uint32_t));
-       vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev;
-       memcpy(vp->rev.sli1FwName, (char*) mb->un.varRdRev.sli1FwName, 16);
-       vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev;
-@@ -161,6 +172,13 @@
-       vp->rev.postKernRev = mb->un.varRdRev.postKernRev;
-       vp->rev.opFwRev = mb->un.varRdRev.opFwRev;
+ #include "core.h"
+ #include "sysfs.h"
+-#include "bus.h"
+-#include "lock.h"
+ #include "mmc_ops.h"
+ #include "sd_ops.h"
  
-+      /* If the sli feature level is less then 9, we must
-+       * tear down all RPIs and VPIs on link down if NPIV
-+       * is enabled.
-+       */
-+      if (vp->rev.feaLevelHigh < 9)
-+              phba->sli3_options |= LPFC_SLI3_VPORT_TEARDOWN;
++#include "core.h"
 +
-       if (lpfc_is_LC_HBA(phba->pcidev->device))
-               memcpy(phba->RandomData, (char *)&mb->un.varWords[24],
-                                               sizeof (phba->RandomData));
-@@ -212,48 +230,34 @@
- /*                                                                      */
- /************************************************************************/
- int
--lpfc_config_port_post(struct lpfc_hba * phba)
-+lpfc_config_port_post(struct lpfc_hba *phba)
- {
-+      struct lpfc_vport *vport = phba->pport;
-       LPFC_MBOXQ_t *pmb;
-       MAILBOX_t *mb;
-       struct lpfc_dmabuf *mp;
-       struct lpfc_sli *psli = &phba->sli;
-       uint32_t status, timeout;
--      int i, j, rc;
-+      int i, j;
-+      int rc;
-       pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-       if (!pmb) {
--              phba->hba_state = LPFC_HBA_ERROR;
-+              phba->link_state = LPFC_HBA_ERROR;
-               return -ENOMEM;
-       }
-       mb = &pmb->mb;
+ static const unsigned int tran_exp[] = {
+       10000,          100000,         1000000,        10000000,
+       0,              0,              0,              0
+@@ -280,62 +280,6 @@
+       return err;
+ }
  
--      lpfc_config_link(phba, pmb);
--      rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
--      if (rc != MBX_SUCCESS) {
--              lpfc_printf_log(phba,
--                              KERN_ERR,
--                              LOG_INIT,
--                              "%d:0447 Adapter failed init, mbxCmd x%x "
--                              "CONFIG_LINK mbxStatus x%x\n",
--                              phba->brd_no,
--                              mb->mbxCommand, mb->mbxStatus);
--              phba->hba_state = LPFC_HBA_ERROR;
--              mempool_free( pmb, phba->mbox_mem_pool);
--              return -EIO;
+-MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+-      card->raw_cid[2], card->raw_cid[3]);
+-MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+-      card->raw_csd[2], card->raw_csd[3]);
+-MMC_ATTR_FN(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
+-MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+-MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev);
+-MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev);
+-MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid);
+-MMC_ATTR_FN(name, "%s\n", card->cid.prod_name);
+-MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid);
+-MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial);
+-
+-static struct device_attribute mmc_sd_dev_attrs[] = {
+-      MMC_ATTR_RO(cid),
+-      MMC_ATTR_RO(csd),
+-      MMC_ATTR_RO(scr),
+-      MMC_ATTR_RO(date),
+-      MMC_ATTR_RO(fwrev),
+-      MMC_ATTR_RO(hwrev),
+-      MMC_ATTR_RO(manfid),
+-      MMC_ATTR_RO(name),
+-      MMC_ATTR_RO(oemid),
+-      MMC_ATTR_RO(serial),
+-      __ATTR_NULL,
+-};
+-
+-/*
+- * Adds sysfs entries as relevant.
+- */
+-static int mmc_sd_sysfs_add(struct mmc_card *card)
+-{
+-      int ret;
+-
+-      ret = mmc_add_attrs(card, mmc_sd_dev_attrs);
+-      if (ret < 0)
+-              return ret;
+-
+-      ret = mmc_lock_add_sysfs(card);
+-      if (ret < 0) {
+-              mmc_remove_attrs(card, mmc_sd_dev_attrs);
+-              return ret;
 -      }
 -
-       /* Get login parameters for NID.  */
--      lpfc_read_sparam(phba, pmb);
-+      lpfc_read_sparam(phba, pmb, 0);
-+      pmb->vport = vport;
-       if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
--              lpfc_printf_log(phba,
--                              KERN_ERR,
--                              LOG_INIT,
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "%d:0448 Adapter failed init, mbxCmd x%x "
-                               "READ_SPARM mbxStatus x%x\n",
-                               phba->brd_no,
-                               mb->mbxCommand, mb->mbxStatus);
--              phba->hba_state = LPFC_HBA_ERROR;
-+              phba->link_state = LPFC_HBA_ERROR;
-               mp = (struct lpfc_dmabuf *) pmb->context1;
-               mempool_free( pmb, phba->mbox_mem_pool);
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-@@ -263,25 +267,27 @@
-       mp = (struct lpfc_dmabuf *) pmb->context1;
--      memcpy(&phba->fc_sparam, mp->virt, sizeof (struct serv_parm));
-+      memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
-       lpfc_mbuf_free(phba, mp->virt, mp->phys);
-       kfree(mp);
-       pmb->context1 = NULL;
-       if (phba->cfg_soft_wwnn)
--              u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
-+              u64_to_wwn(phba->cfg_soft_wwnn,
-+                         vport->fc_sparam.nodeName.u.wwn);
-       if (phba->cfg_soft_wwpn)
--              u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
--      memcpy(&phba->fc_nodename, &phba->fc_sparam.nodeName,
-+              u64_to_wwn(phba->cfg_soft_wwpn,
-+                         vport->fc_sparam.portName.u.wwn);
-+      memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
-              sizeof (struct lpfc_name));
--      memcpy(&phba->fc_portname, &phba->fc_sparam.portName,
-+      memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
-              sizeof (struct lpfc_name));
-       /* If no serial number in VPD data, use low 6 bytes of WWNN */
-       /* This should be consolidated into parse_vpd ? - mr */
-       if (phba->SerialNumber[0] == 0) {
-               uint8_t *outptr;
--              outptr = &phba->fc_nodename.u.s.IEEE[0];
-+              outptr = &vport->fc_nodename.u.s.IEEE[0];
-               for (i = 0; i < 12; i++) {
-                       status = *outptr++;
-                       j = ((status & 0xf0) >> 4);
-@@ -303,15 +309,14 @@
-       }
+-      return 0;
+-}
+-
+-/*
+- * Removes the sysfs entries added by mmc_sysfs_add().
+- */
+-static void mmc_sd_sysfs_remove(struct mmc_card *card)
+-{
+-      mmc_lock_remove_sysfs(card);
+-      mmc_remove_attrs(card, mmc_sd_dev_attrs);
+-}
+-
+ /*
+  * Handle the detection and initialisation of a card.
+  *
+@@ -349,7 +293,6 @@
+       int err;
+       u32 cid[4];
+       unsigned int max_dtr;
+-      u32 status;
  
-       lpfc_read_config(phba, pmb);
-+      pmb->vport = vport;
-       if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
--              lpfc_printf_log(phba,
--                              KERN_ERR,
--                              LOG_INIT,
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "%d:0453 Adapter failed to init, mbxCmd x%x "
-                               "READ_CONFIG, mbxStatus x%x\n",
-                               phba->brd_no,
-                               mb->mbxCommand, mb->mbxStatus);
--              phba->hba_state = LPFC_HBA_ERROR;
-+              phba->link_state = LPFC_HBA_ERROR;
-               mempool_free( pmb, phba->mbox_mem_pool);
-               return -EIO;
-       }
-@@ -338,9 +343,7 @@
-           || ((phba->cfg_link_speed == LINK_SPEED_10G)
-               && !(phba->lmt & LMT_10Gb))) {
-               /* Reset link speed to auto */
--              lpfc_printf_log(phba,
--                      KERN_WARNING,
--                      LOG_LINK_EVENT,
-+              lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT,
-                       "%d:1302 Invalid speed for this board: "
-                       "Reset link speed to auto: x%x\n",
-                       phba->brd_no,
-@@ -348,7 +351,7 @@
-                       phba->cfg_link_speed = LINK_SPEED_AUTO;
-       }
+       BUG_ON(!host);
+       BUG_ON(!host->claimed);
+@@ -409,15 +352,6 @@
  
--      phba->hba_state = LPFC_LINK_DOWN;
-+      phba->link_state = LPFC_LINK_DOWN;
+       mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
  
-       /* Only process IOCBs on ring 0 till hba_state is READY */
-       if (psli->ring[psli->extra_ring].cmdringaddr)
-@@ -359,10 +362,11 @@
-               psli->ring[psli->next_ring].flag |= LPFC_STOP_IOCB_EVENT;
+-      /*
+-       * Check if card is locked.
+-       */
+-      err = mmc_send_status(card, &status);
+-      if (err != MMC_ERR_NONE)
+-              goto free_card;
+-      if (status & R1_CARD_IS_LOCKED)
+-              mmc_card_set_locked(card);
+-
+       if (!oldcard) {
+               /*
+                * Fetch CSD from card.
+@@ -529,8 +463,6 @@
+       BUG_ON(!host);
+       BUG_ON(!host->card);
  
-       /* Post receive buffers for desired rings */
-+      if (phba->sli_rev != 3)
-       lpfc_post_rcv_buf(phba);
+-      mmc_sd_sysfs_remove(host->card);
+-
+       mmc_remove_card(host->card);
+       host->card = NULL;
+ }
+@@ -555,7 +487,8 @@
+       mmc_release_host(host);
  
-       /* Enable appropriate host interrupts */
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       status = readl(phba->HCregaddr);
-       status |= HC_MBINT_ENA | HC_ERINT_ENA | HC_LAINT_ENA;
-       if (psli->num_rings > 0)
-@@ -380,22 +384,24 @@
+       if (err != MMC_ERR_NONE) {
+-              mmc_sd_remove(host);
++              mmc_remove_card(host->card);
++              host->card = NULL;
  
-       writel(status, phba->HCregaddr);
-       readl(phba->HCregaddr); /* flush */
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
+@@ -575,7 +508,7 @@
  
-       /*
-        * Setup the ring 0 (els)  timeout handler
-        */
-       timeout = phba->fc_ratov << 1;
--      mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
-+      mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
-+      mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
-+      phba->hb_outstanding = 0;
-+      phba->last_completion_time = jiffies;
+       mmc_claim_host(host);
+       mmc_deselect_cards(host);
+-      host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_LOCKED);
++      host->card->state &= ~MMC_STATE_HIGHSPEED;
+       mmc_release_host(host);
+ }
  
-       lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
-       pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-+      pmb->vport = vport;
-       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
-       lpfc_set_loopback_flag(phba);
-       if (rc != MBX_SUCCESS) {
--              lpfc_printf_log(phba,
--                              KERN_ERR,
--                              LOG_INIT,
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "%d:0454 Adapter failed to init, mbxCmd x%x "
-                               "INIT_LINK, mbxStatus x%x\n",
-                               phba->brd_no,
-@@ -408,7 +414,7 @@
-               writel(0xffffffff, phba->HAregaddr);
-               readl(phba->HAregaddr); /* flush */
+@@ -596,7 +529,9 @@
  
--              phba->hba_state = LPFC_HBA_ERROR;
-+              phba->link_state = LPFC_HBA_ERROR;
-               if (rc != MBX_BUSY)
-                       mempool_free(pmb, phba->mbox_mem_pool);
-               return -EIO;
-@@ -429,18 +435,19 @@
- /*                                                                      */
- /************************************************************************/
- int
--lpfc_hba_down_prep(struct lpfc_hba * phba)
-+lpfc_hba_down_prep(struct lpfc_hba *phba)
- {
-+      struct lpfc_vport *vport = phba->pport;
+       err = mmc_sd_init_card(host, host->ocr, host->card);
+       if (err != MMC_ERR_NONE) {
+-              mmc_sd_remove(host);
++              mmc_remove_card(host->card);
++              host->card = NULL;
 +
-       /* Disable interrupts */
-       writel(0, phba->HCregaddr);
-       readl(phba->HCregaddr); /* flush */
+               mmc_detach_bus(host);
+       }
  
--      /* Cleanup potential discovery resources */
--      lpfc_els_flush_rscn(phba);
--      lpfc_els_flush_cmd(phba);
--      lpfc_disc_flush_list(phba);
-+      list_for_each_entry(vport, &phba->port_list, listentry) {
-+              lpfc_cleanup_discovery_resources(vport);
-+      }
+@@ -664,11 +599,7 @@
  
--      return (0);
-+      return 0;
- }
+       mmc_release_host(host);
  
- /************************************************************************/
-@@ -453,13 +460,16 @@
- /*                                                                      */
- /************************************************************************/
- int
--lpfc_hba_down_post(struct lpfc_hba * phba)
-+lpfc_hba_down_post(struct lpfc_hba *phba)
- {
-       struct lpfc_sli *psli = &phba->sli;
-       struct lpfc_sli_ring *pring;
-       struct lpfc_dmabuf *mp, *next_mp;
-       int i;
+-      err = mmc_add_card(host->card);
+-      if (err)
+-              goto reclaim_host;
+-
+-      err = mmc_sd_sysfs_add(host->card);
++      err = mmc_register_card(host->card);
+       if (err)
+               goto reclaim_host;
  
-+      if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
-+              lpfc_sli_hbqbuf_free_all(phba);
-+      else {
-       /* Cleanup preposted buffers on the ELS ring */
-       pring = &psli->ring[LPFC_ELS_RING];
-       list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
-@@ -468,6 +478,7 @@
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
-       }
-+      }
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/sysfs.c linux-2.6.22-570/drivers/mmc/core/sysfs.c
+--- linux-2.6.22-590/drivers/mmc/core/sysfs.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/sysfs.c  2007-07-08 19:32:17.000000000 -0400
+@@ -2,7 +2,6 @@
+  *  linux/drivers/mmc/core/sysfs.c
+  *
+  *  Copyright (C) 2003 Russell King, All Rights Reserved.
+- *  Copyright 2007 Pierre Ossman
+  *
+  * 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
+@@ -10,34 +9,352 @@
+  *
+  *  MMC sysfs/driver model support.
+  */
++#include <linux/module.h>
++#include <linux/init.h>
+ #include <linux/device.h>
++#include <linux/idr.h>
++#include <linux/workqueue.h>
  
-       for (i = 0; i < psli->num_rings; i++) {
-               pring = &psli->ring[i];
-@@ -477,6 +488,119 @@
-       return 0;
- }
+ #include <linux/mmc/card.h>
++#include <linux/mmc/host.h>
  
-+/* HBA heart beat timeout handler */
-+void
-+lpfc_hb_timeout(unsigned long ptr)
-+{
-+      struct lpfc_hba *phba;
-+      unsigned long iflag;
-+
-+      phba = (struct lpfc_hba *)ptr;
-+      spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
-+      if (!(phba->pport->work_port_events & WORKER_HB_TMO))
-+              phba->pport->work_port_events |= WORKER_HB_TMO;
-+      spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
+ #include "sysfs.h"
+-int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs)
++#define dev_to_mmc_card(d)    container_of(d, struct mmc_card, dev)
++#define to_mmc_driver(d)      container_of(d, struct mmc_driver, drv)
++#define cls_dev_to_mmc_host(d)        container_of(d, struct mmc_host, class_dev)
 +
-+      if (phba->work_wait)
-+              wake_up(phba->work_wait);
-+      return;
++#define MMC_ATTR(name, fmt, args...)                                  \
++static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)       \
++{                                                                     \
++      struct mmc_card *card = dev_to_mmc_card(dev);                   \
++      return sprintf(buf, fmt, args);                                 \
 +}
 +
-+static void
-+lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
-+{
-+      unsigned long drvr_flag;
-+
-+      spin_lock_irqsave(&phba->hbalock, drvr_flag);
-+      phba->hb_outstanding = 0;
-+      spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
++MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
++      card->raw_cid[2], card->raw_cid[3]);
++MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
++      card->raw_csd[2], card->raw_csd[3]);
++MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
++MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
++MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
++MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
++MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
++MMC_ATTR(name, "%s\n", card->cid.prod_name);
++MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
++MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
 +
-+      mempool_free(pmboxq, phba->mbox_mem_pool);
-+      if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) &&
-+              !(phba->link_state == LPFC_HBA_ERROR) &&
-+              !(phba->pport->fc_flag & FC_UNLOADING))
-+              mod_timer(&phba->hb_tmofunc,
-+                      jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
-+      return;
-+}
++#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
 +
-+void
-+lpfc_hb_timeout_handler(struct lpfc_hba *phba)
-+{
-+      LPFC_MBOXQ_t *pmboxq;
-+      int retval;
-+      struct lpfc_sli *psli = &phba->sli;
++static struct device_attribute mmc_dev_attrs[] = {
++      MMC_ATTR_RO(cid),
++      MMC_ATTR_RO(csd),
++      MMC_ATTR_RO(date),
++      MMC_ATTR_RO(fwrev),
++      MMC_ATTR_RO(hwrev),
++      MMC_ATTR_RO(manfid),
++      MMC_ATTR_RO(name),
++      MMC_ATTR_RO(oemid),
++      MMC_ATTR_RO(serial),
++      __ATTR_NULL
++};
 +
-+      if ((phba->link_state == LPFC_HBA_ERROR) ||
-+              (phba->pport->fc_flag & FC_UNLOADING) ||
-+              (phba->pport->fc_flag & FC_OFFLINE_MODE))
-+              return;
++static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
 +
-+      spin_lock_irq(&phba->pport->work_port_lock);
-+      /* If the timer is already canceled do nothing */
-+      if (!(phba->pport->work_port_events & WORKER_HB_TMO)) {
-+              spin_unlock_irq(&phba->pport->work_port_lock);
-+              return;
-+      }
 +
-+      if (time_after(phba->last_completion_time + LPFC_HB_MBOX_INTERVAL * HZ,
-+              jiffies)) {
-+              spin_unlock_irq(&phba->pport->work_port_lock);
-+              if (!phba->hb_outstanding)
-+                      mod_timer(&phba->hb_tmofunc,
-+                              jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
-+              else
-+                      mod_timer(&phba->hb_tmofunc,
-+                              jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
-+              return;
-+      }
-+      spin_unlock_irq(&phba->pport->work_port_lock);
++static void mmc_release_card(struct device *dev)
++{
++      struct mmc_card *card = dev_to_mmc_card(dev);
 +
-+      /* If there is no heart beat outstanding, issue a heartbeat command */
-+      if (!phba->hb_outstanding) {
-+              pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
-+              if (!pmboxq) {
-+                      mod_timer(&phba->hb_tmofunc,
-+                              jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
-+                      return;
-+              }
++      kfree(card);
++}
 +
-+              lpfc_heart_beat(phba, pmboxq);
-+              pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl;
-+              pmboxq->vport = phba->pport;
-+              retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
++/*
++ * This currently matches any MMC driver to any MMC card - drivers
++ * themselves make the decision whether to drive this card in their
++ * probe method.
++ */
++static int mmc_bus_match(struct device *dev, struct device_driver *drv)
++{
++      return 1;
++}
 +
-+              if (retval != MBX_BUSY && retval != MBX_SUCCESS) {
-+                      mempool_free(pmboxq, phba->mbox_mem_pool);
-+                      mod_timer(&phba->hb_tmofunc,
-+                              jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
-+                      return;
-+              }
-+              mod_timer(&phba->hb_tmofunc,
-+                      jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
-+              phba->hb_outstanding = 1;
-+              return;
-+      } else {
-+              /*
-+               * If heart beat timeout called with hb_outstanding set we
-+               * need to take the HBA offline.
-+               */
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-+                      "%d:0459 Adapter heartbeat failure, taking "
-+                      "this port offline.\n", phba->brd_no);
++static int
++mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
++              int buf_size)
++{
++      struct mmc_card *card = dev_to_mmc_card(dev);
++      char ccc[13];
++      int retval = 0, i = 0, length = 0;
 +
-+              spin_lock_irq(&phba->hbalock);
-+              psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
-+              spin_unlock_irq(&phba->hbalock);
++#define add_env(fmt,val) do {                                 \
++      retval = add_uevent_var(envp, num_envp, &i,             \
++                              buf, buf_size, &length,         \
++                              fmt, val);                      \
++      if (retval)                                             \
++              return retval;                                  \
++} while (0);
 +
-+              lpfc_offline_prep(phba);
-+              lpfc_offline(phba);
-+              lpfc_unblock_mgmt_io(phba);
-+              phba->link_state = LPFC_HBA_ERROR;
-+              lpfc_hba_down_post(phba);
-+      }
-+}
++      for (i = 0; i < 12; i++)
++              ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';
++      ccc[12] = '\0';
 +
- /************************************************************************/
- /*                                                                      */
- /*    lpfc_handle_eratt                                                 */
-@@ -486,11 +610,15 @@
- /*                                                                      */
- /************************************************************************/
- void
--lpfc_handle_eratt(struct lpfc_hba * phba)
-+lpfc_handle_eratt(struct lpfc_hba *phba)
- {
-+      struct lpfc_vport *vport = phba->pport;
-       struct lpfc_sli *psli = &phba->sli;
-       struct lpfc_sli_ring  *pring;
-+      struct lpfc_vport *port_iterator;
-       uint32_t event_data;
-+      struct Scsi_Host  *shost;
++      add_env("MMC_CCC=%s", ccc);
++      add_env("MMC_MANFID=%06x", card->cid.manfid);
++      add_env("MMC_NAME=%s", mmc_card_name(card));
++      add_env("MMC_OEMID=%04x", card->cid.oemid);
++#undef add_env
++      envp[i] = NULL;
 +
-       /* If the pci channel is offline, ignore possible errors,
-        * since we cannot communicate with the pci card anyway. */
-       if (pci_channel_offline(phba->pcidev))
-@@ -504,10 +632,17 @@
-                               "Data: x%x x%x x%x\n",
-                               phba->brd_no, phba->work_hs,
-                               phba->work_status[0], phba->work_status[1]);
--              spin_lock_irq(phba->host->host_lock);
--              phba->fc_flag |= FC_ESTABLISH_LINK;
-+              list_for_each_entry(port_iterator, &phba->port_list,
-+                                  listentry) {
-+                      shost = lpfc_shost_from_vport(port_iterator);
-+
-+                      spin_lock_irq(shost->host_lock);
-+                      port_iterator->fc_flag |= FC_ESTABLISH_LINK;
-+                      spin_unlock_irq(shost->host_lock);
-+              }
-+              spin_lock_irq(&phba->hbalock);
-               psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(&phba->hbalock);
-               /*
-               * Firmware stops when it triggled erratt with HS_FFER6.
-@@ -544,15 +679,18 @@
-                               phba->work_status[0], phba->work_status[1]);
-               event_data = FC_REG_DUMP_EVENT;
--              fc_host_post_vendor_event(phba->host, fc_get_event_number(),
-+              shost = lpfc_shost_from_vport(vport);
-+              fc_host_post_vendor_event(shost, fc_get_event_number(),
-                               sizeof(event_data), (char *) &event_data,
-                               SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
-+              spin_lock_irq(&phba->hbalock);
-               psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
-+              spin_unlock_irq(&phba->hbalock);
-               lpfc_offline_prep(phba);
-               lpfc_offline(phba);
-               lpfc_unblock_mgmt_io(phba);
--              phba->hba_state = LPFC_HBA_ERROR;
-+              phba->link_state = LPFC_HBA_ERROR;
-               lpfc_hba_down_post(phba);
-       }
- }
-@@ -566,9 +704,11 @@
- /*                                                                      */
- /************************************************************************/
- void
--lpfc_handle_latt(struct lpfc_hba * phba)
-+lpfc_handle_latt(struct lpfc_hba *phba)
- {
-+      struct lpfc_vport *vport = phba->pport;
-       struct lpfc_sli *psli = &phba->sli;
-+      struct lpfc_vport *port_iterator;
-       LPFC_MBOXQ_t *pmb;
-       volatile uint32_t control;
-       struct lpfc_dmabuf *mp;
-@@ -589,20 +729,22 @@
-       rc = -EIO;
-       /* Cleanup any outstanding ELS commands */
--      lpfc_els_flush_cmd(phba);
-+      list_for_each_entry(port_iterator, &phba->port_list, listentry)
-+              lpfc_els_flush_cmd(port_iterator);
-       psli->slistat.link_event++;
-       lpfc_read_la(phba, pmb, mp);
-       pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la;
-+      pmb->vport = vport;
-       rc = lpfc_sli_issue_mbox (phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB));
-       if (rc == MBX_NOT_FINISHED)
-               goto lpfc_handle_latt_free_mbuf;
-       /* Clear Link Attention in HA REG */
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       writel(HA_LATT, phba->HAregaddr);
-       readl(phba->HAregaddr); /* flush */
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
-       return;
-@@ -614,7 +756,7 @@
-       mempool_free(pmb, phba->mbox_mem_pool);
- lpfc_handle_latt_err_exit:
-       /* Enable Link attention interrupts */
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       psli->sli_flag |= LPFC_PROCESS_LA;
-       control = readl(phba->HCregaddr);
-       control |= HC_LAINT_ENA;
-@@ -624,15 +766,13 @@
-       /* Clear Link Attention in HA REG */
-       writel(HA_LATT, phba->HAregaddr);
-       readl(phba->HAregaddr); /* flush */
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
-       lpfc_linkdown(phba);
--      phba->hba_state = LPFC_HBA_ERROR;
-+      phba->link_state = LPFC_HBA_ERROR;
-       /* The other case is an error from issue_mbox */
-       if (rc == -ENOMEM)
--              lpfc_printf_log(phba,
--                              KERN_WARNING,
--                              LOG_MBOX,
-+              lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
-                               "%d:0300 READ_LA: no buffers\n",
-                               phba->brd_no);
-@@ -646,7 +786,7 @@
- /*                                                                      */
- /************************************************************************/
- static int
--lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len)
-+lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
- {
-       uint8_t lenlo, lenhi;
-       int Length;
-@@ -658,9 +798,7 @@
-               return 0;
-       /* Vital Product */
--      lpfc_printf_log(phba,
--                      KERN_INFO,
--                      LOG_INIT,
-+      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                       "%d:0455 Vital Product Data: x%x x%x x%x x%x\n",
-                       phba->brd_no,
-                       (uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2],
-@@ -785,7 +923,7 @@
- }
- static void
--lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
-+lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
- {
-       lpfc_vpd_t *vp;
-       uint16_t dev_id = phba->pcidev->device;
-@@ -943,7 +1081,7 @@
- /*   Returns the number of buffers NOT posted.    */
- /**************************************************/
- int
--lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
-+lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt,
-                int type)
- {
-       IOCB_t *icmd;
-@@ -955,9 +1093,7 @@
-       /* While there are buffers to post */
-       while (cnt > 0) {
-               /* Allocate buffer for  command iocb */
--              spin_lock_irq(phba->host->host_lock);
-               iocb = lpfc_sli_get_iocbq(phba);
--              spin_unlock_irq(phba->host->host_lock);
-               if (iocb == NULL) {
-                       pring->missbufcnt = cnt;
-                       return cnt;
-@@ -972,9 +1108,7 @@
-                                               &mp1->phys);
-               if (mp1 == 0 || mp1->virt == 0) {
-                       kfree(mp1);
--                      spin_lock_irq(phba->host->host_lock);
-                       lpfc_sli_release_iocbq(phba, iocb);
--                      spin_unlock_irq(phba->host->host_lock);
-                       pring->missbufcnt = cnt;
-                       return cnt;
-               }
-@@ -990,9 +1124,7 @@
-                               kfree(mp2);
-                               lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
-                               kfree(mp1);
--                              spin_lock_irq(phba->host->host_lock);
-                               lpfc_sli_release_iocbq(phba, iocb);
--                              spin_unlock_irq(phba->host->host_lock);
-                               pring->missbufcnt = cnt;
-                               return cnt;
-                       }
-@@ -1018,7 +1150,6 @@
-               icmd->ulpCommand = CMD_QUE_RING_BUF64_CN;
-               icmd->ulpLe = 1;
--              spin_lock_irq(phba->host->host_lock);
-               if (lpfc_sli_issue_iocb(phba, pring, iocb, 0) == IOCB_ERROR) {
-                       lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
-                       kfree(mp1);
-@@ -1030,15 +1161,12 @@
-                       }
-                       lpfc_sli_release_iocbq(phba, iocb);
-                       pring->missbufcnt = cnt;
--                      spin_unlock_irq(phba->host->host_lock);
-                       return cnt;
-               }
--              spin_unlock_irq(phba->host->host_lock);
-               lpfc_sli_ringpostbuf_put(phba, pring, mp1);
--              if (mp2) {
-+              if (mp2)
-                       lpfc_sli_ringpostbuf_put(phba, pring, mp2);
-               }
--      }
-       pring->missbufcnt = 0;
-       return 0;
- }
-@@ -1050,7 +1178,7 @@
- /*                                                                      */
- /************************************************************************/
- static int
--lpfc_post_rcv_buf(struct lpfc_hba * phba)
-+lpfc_post_rcv_buf(struct lpfc_hba *phba)
- {
-       struct lpfc_sli *psli = &phba->sli;
-@@ -1151,7 +1279,7 @@
- {
-       int t;
-       uint32_t *HashWorking;
--      uint32_t *pwwnn = phba->wwnn;
-+      uint32_t *pwwnn = (uint32_t *) phba->wwnn;
-       HashWorking = kmalloc(80 * sizeof(uint32_t), GFP_KERNEL);
-       if (!HashWorking)
-@@ -1170,64 +1298,76 @@
- }
- static void
--lpfc_cleanup(struct lpfc_hba * phba)
-+lpfc_cleanup(struct lpfc_vport *vport)
- {
-       struct lpfc_nodelist *ndlp, *next_ndlp;
-       /* clean up phba - lpfc specific */
--      lpfc_can_disctmo(phba);
--      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
-+      lpfc_can_disctmo(vport);
-+      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
-               lpfc_nlp_put(ndlp);
--
--      INIT_LIST_HEAD(&phba->fc_nodes);
--
-       return;
- }
- static void
- lpfc_establish_link_tmo(unsigned long ptr)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
-+      struct lpfc_hba   *phba = (struct lpfc_hba *) ptr;
-+      struct lpfc_vport *vport = phba->pport;
-       unsigned long iflag;
--
-       /* Re-establishing Link, timer expired */
-       lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
-                       "%d:1300 Re-establishing Link, timer expired "
-                       "Data: x%x x%x\n",
--                      phba->brd_no, phba->fc_flag, phba->hba_state);
--      spin_lock_irqsave(phba->host->host_lock, iflag);
--      phba->fc_flag &= ~FC_ESTABLISH_LINK;
--      spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+                      phba->brd_no, vport->fc_flag,
-+                      vport->port_state);
-+      list_for_each_entry(vport, &phba->port_list, listentry) {
-+              struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
++      return 0;
++}
 +
-+              spin_lock_irqsave(shost->host_lock, iflag);
-+              vport->fc_flag &= ~FC_ESTABLISH_LINK;
-+              spin_unlock_irqrestore(shost->host_lock, iflag);
-+      }
- }
--static int
--lpfc_stop_timer(struct lpfc_hba * phba)
-+void
-+lpfc_stop_vport_timers(struct lpfc_vport *vport)
++static int mmc_bus_suspend(struct device *dev, pm_message_t state)
  {
--      struct lpfc_sli *psli = &phba->sli;
-+      del_timer_sync(&vport->els_tmofunc);
-+      del_timer_sync(&vport->fc_fdmitmo);
-+      lpfc_can_disctmo(vport);
-+      return;
+-      int error = 0;
+-      int i;
++      struct mmc_driver *drv = to_mmc_driver(dev->driver);
++      struct mmc_card *card = dev_to_mmc_card(dev);
++      int ret = 0;
++
++      if (dev->driver && drv->suspend)
++              ret = drv->suspend(card, state);
++      return ret;
++}
+-      for (i = 0; attr_name(attrs[i]); i++) {
+-              error = device_create_file(&card->dev, &attrs[i]);
+-              if (error) {
+-                      while (--i >= 0)
+-                              device_remove_file(&card->dev, &attrs[i]);
+-                      break;
++static int mmc_bus_resume(struct device *dev)
++{
++      struct mmc_driver *drv = to_mmc_driver(dev->driver);
++      struct mmc_card *card = dev_to_mmc_card(dev);
++      int ret = 0;
++
++      if (dev->driver && drv->resume)
++              ret = drv->resume(card);
++      return ret;
 +}
 +
-+static void
-+lpfc_stop_phba_timers(struct lpfc_hba *phba)
++static int mmc_bus_probe(struct device *dev)
 +{
-+      struct lpfc_vport *vport;
-       del_timer_sync(&phba->fcp_poll_timer);
-       del_timer_sync(&phba->fc_estabtmo);
--      del_timer_sync(&phba->fc_disctmo);
--      del_timer_sync(&phba->fc_fdmitmo);
--      del_timer_sync(&phba->els_tmofunc);
--      psli = &phba->sli;
--      del_timer_sync(&psli->mbox_tmo);
--      return(1);
-+      list_for_each_entry(vport, &phba->port_list, listentry)
-+              lpfc_stop_vport_timers(vport);
-+      del_timer_sync(&phba->sli.mbox_tmo);
-+      del_timer_sync(&phba->fabric_block_timer);
-+      phba->hb_outstanding = 0;
-+      del_timer_sync(&phba->hb_tmofunc);
-+      return;
- }
- int
--lpfc_online(struct lpfc_hba * phba)
-+lpfc_online(struct lpfc_hba *phba)
- {
-+      struct lpfc_vport *vport = phba->pport;
++      struct mmc_driver *drv = to_mmc_driver(dev->driver);
++      struct mmc_card *card = dev_to_mmc_card(dev);
 +
-       if (!phba)
-               return 0;
--      if (!(phba->fc_flag & FC_OFFLINE_MODE))
-+      if (!(vport->fc_flag & FC_OFFLINE_MODE))
-               return 0;
--      lpfc_printf_log(phba,
--                     KERN_WARNING,
--                     LOG_INIT,
-+      lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
-                      "%d:0458 Bring Adapter online\n",
-                      phba->brd_no);
-@@ -1243,9 +1383,14 @@
-               return 1;
++      return drv->probe(card);
++}
++
++static int mmc_bus_remove(struct device *dev)
++{
++      struct mmc_driver *drv = to_mmc_driver(dev->driver);
++      struct mmc_card *card = dev_to_mmc_card(dev);
++
++      drv->remove(card);
++
++      return 0;
++}
++
++static struct bus_type mmc_bus_type = {
++      .name           = "mmc",
++      .dev_attrs      = mmc_dev_attrs,
++      .match          = mmc_bus_match,
++      .uevent         = mmc_bus_uevent,
++      .probe          = mmc_bus_probe,
++      .remove         = mmc_bus_remove,
++      .suspend        = mmc_bus_suspend,
++      .resume         = mmc_bus_resume,
++};
++
++/**
++ *    mmc_register_driver - register a media driver
++ *    @drv: MMC media driver
++ */
++int mmc_register_driver(struct mmc_driver *drv)
++{
++      drv->drv.bus = &mmc_bus_type;
++      return driver_register(&drv->drv);
++}
++
++EXPORT_SYMBOL(mmc_register_driver);
++
++/**
++ *    mmc_unregister_driver - unregister a media driver
++ *    @drv: MMC media driver
++ */
++void mmc_unregister_driver(struct mmc_driver *drv)
++{
++      drv->drv.bus = &mmc_bus_type;
++      driver_unregister(&drv->drv);
++}
++
++EXPORT_SYMBOL(mmc_unregister_driver);
++
++
++/*
++ * Internal function.  Initialise a MMC card structure.
++ */
++void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
++{
++      memset(card, 0, sizeof(struct mmc_card));
++      card->host = host;
++      device_initialize(&card->dev);
++      card->dev.parent = mmc_classdev(host);
++      card->dev.bus = &mmc_bus_type;
++      card->dev.release = mmc_release_card;
++}
++
++/*
++ * Internal function.  Register a new MMC card with the driver model.
++ */
++int mmc_register_card(struct mmc_card *card)
++{
++      int ret;
++
++      snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
++               "%s:%04x", mmc_hostname(card->host), card->rca);
++
++      ret = device_add(&card->dev);
++      if (ret == 0) {
++              if (mmc_card_sd(card)) {
++                      ret = device_create_file(&card->dev, &mmc_dev_attr_scr);
++                      if (ret)
++                              device_del(&card->dev);
++              }
+       }
++      if (ret == 0)
++              mmc_card_set_present(card);
++      return ret;
++}
++
++/*
++ * Internal function.  Unregister a new MMC card with the
++ * driver model, and (eventually) free it.
++ */
++void mmc_remove_card(struct mmc_card *card)
++{
++      if (mmc_card_present(card)) {
++              if (mmc_card_sd(card))
++                      device_remove_file(&card->dev, &mmc_dev_attr_scr);
++
++              device_del(&card->dev);
        }
  
--      spin_lock_irq(phba->host->host_lock);
--      phba->fc_flag &= ~FC_OFFLINE_MODE;
--      spin_unlock_irq(phba->host->host_lock);
-+      list_for_each_entry(vport, &phba->port_list, listentry) {
-+              struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+              spin_lock_irq(shost->host_lock);
-+              vport->fc_flag &= ~FC_OFFLINE_MODE;
-+              if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
-+                      vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
-+              spin_unlock_irq(shost->host_lock);
+-      return error;
++      put_device(&card->dev);
++}
++
++
++static void mmc_host_classdev_release(struct device *dev)
++{
++      struct mmc_host *host = cls_dev_to_mmc_host(dev);
++      kfree(host);
++}
++
++static struct class mmc_host_class = {
++      .name           = "mmc_host",
++      .dev_release    = mmc_host_classdev_release,
++};
++
++static DEFINE_IDR(mmc_host_idr);
++static DEFINE_SPINLOCK(mmc_host_lock);
++
++/*
++ * Internal function. Allocate a new MMC host.
++ */
++struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
++{
++      struct mmc_host *host;
++
++      host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
++      if (host) {
++              memset(host, 0, sizeof(struct mmc_host) + extra);
++
++              host->parent = dev;
++              host->class_dev.parent = dev;
++              host->class_dev.class = &mmc_host_class;
++              device_initialize(&host->class_dev);
 +      }
-       lpfc_unblock_mgmt_io(phba);
-       return 0;
-@@ -1256,9 +1401,9 @@
- {
-       unsigned long iflag;
--      spin_lock_irqsave(phba->host->host_lock, iflag);
--      phba->fc_flag |= FC_BLOCK_MGMT_IO;
--      spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+      spin_lock_irqsave(&phba->hbalock, iflag);
-+      phba->sli.sli_flag |= LPFC_BLOCK_MGMT_IO;
-+      spin_unlock_irqrestore(&phba->hbalock, iflag);
++
++      return host;
++}
++
++/*
++ * Internal function. Register a new MMC host with the MMC class.
++ */
++int mmc_add_host_sysfs(struct mmc_host *host)
++{
++      int err;
++
++      if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
++              return -ENOMEM;
++
++      spin_lock(&mmc_host_lock);
++      err = idr_get_new(&mmc_host_idr, host, &host->index);
++      spin_unlock(&mmc_host_lock);
++      if (err)
++              return err;
++
++      snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
++               "mmc%d", host->index);
++
++      return device_add(&host->class_dev);
++}
++
++/*
++ * Internal function. Unregister a MMC host with the MMC class.
++ */
++void mmc_remove_host_sysfs(struct mmc_host *host)
++{
++      device_del(&host->class_dev);
++
++      spin_lock(&mmc_host_lock);
++      idr_remove(&mmc_host_idr, host->index);
++      spin_unlock(&mmc_host_lock);
  }
  
- void
-@@ -1266,17 +1411,18 @@
+-void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs)
++/*
++ * Internal function. Free a MMC host.
++ */
++void mmc_free_host_sysfs(struct mmc_host *host)
  {
-       unsigned long iflag;
+-      int i;
++      put_device(&host->class_dev);
++}
  
--      spin_lock_irqsave(phba->host->host_lock, iflag);
--      phba->fc_flag &= ~FC_BLOCK_MGMT_IO;
--      spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+      spin_lock_irqsave(&phba->hbalock, iflag);
-+      phba->sli.sli_flag &= ~LPFC_BLOCK_MGMT_IO;
-+      spin_unlock_irqrestore(&phba->hbalock, iflag);
+-      for (i = 0; attr_name(attrs[i]); i++)
+-              device_remove_file(&card->dev, &attrs[i]);
++static struct workqueue_struct *workqueue;
++
++/*
++ * Internal function. Schedule delayed work in the MMC work queue.
++ */
++int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)
++{
++      return queue_delayed_work(workqueue, work, delay);
++}
++
++/*
++ * Internal function. Flush all scheduled work from the MMC work queue.
++ */
++void mmc_flush_scheduled_work(void)
++{
++      flush_workqueue(workqueue);
++}
++
++static int __init mmc_init(void)
++{
++      int ret;
++
++      workqueue = create_singlethread_workqueue("kmmcd");
++      if (!workqueue)
++              return -ENOMEM;
++
++      ret = bus_register(&mmc_bus_type);
++      if (ret == 0) {
++              ret = class_register(&mmc_host_class);
++              if (ret)
++                      bus_unregister(&mmc_bus_type);
++      }
++      return ret;
++}
++
++static void __exit mmc_exit(void)
++{
++      class_unregister(&mmc_host_class);
++      bus_unregister(&mmc_bus_type);
++      destroy_workqueue(workqueue);
  }
  
- void
- lpfc_offline_prep(struct lpfc_hba * phba)
- {
-+      struct lpfc_vport *vport = phba->pport;
-       struct lpfc_nodelist  *ndlp, *next_ndlp;
--      if (phba->fc_flag & FC_OFFLINE_MODE)
-+      if (vport->fc_flag & FC_OFFLINE_MODE)
-               return;
++module_init(mmc_init);
++module_exit(mmc_exit);
+diff -Nurb linux-2.6.22-590/drivers/mmc/core/sysfs.h linux-2.6.22-570/drivers/mmc/core/sysfs.h
+--- linux-2.6.22-590/drivers/mmc/core/sysfs.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/core/sysfs.h  2007-07-08 19:32:17.000000000 -0400
+@@ -11,16 +11,17 @@
+ #ifndef _MMC_CORE_SYSFS_H
+ #define _MMC_CORE_SYSFS_H
  
-       lpfc_block_mgmt_io(phba);
-@@ -1284,39 +1430,49 @@
-       lpfc_linkdown(phba);
+-#define MMC_ATTR_FN(name, fmt, args...)                                       \
+-static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)       \
+-{                                                                     \
+-      struct mmc_card *card = container_of(dev, struct mmc_card, dev);\
+-      return sprintf(buf, fmt, args);                                 \
+-}
++void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
++int mmc_register_card(struct mmc_card *card);
++void mmc_remove_card(struct mmc_card *card);
  
-       /* Issue an unreg_login to all nodes */
--      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
-+      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
-               if (ndlp->nlp_state != NLP_STE_UNUSED_NODE)
--                      lpfc_unreg_rpi(phba, ndlp);
-+                      lpfc_unreg_rpi(vport, ndlp);
+-#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
++struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
++int mmc_add_host_sysfs(struct mmc_host *host);
++void mmc_remove_host_sysfs(struct mmc_host *host);
++void mmc_free_host_sysfs(struct mmc_host *host);
  
-       lpfc_sli_flush_mbox_queue(phba);
- }
+-int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs);
+-void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs);
++int mmc_schedule_work(struct work_struct *work);
++int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
++void mmc_flush_scheduled_work(void);
  
- void
--lpfc_offline(struct lpfc_hba * phba)
-+lpfc_offline(struct lpfc_hba *phba)
- {
--      unsigned long iflag;
-+      struct lpfc_vport *vport = phba->pport;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_vport *port_iterator;
+ #endif
+diff -Nurb linux-2.6.22-590/drivers/mmc/host/sdhci.c linux-2.6.22-570/drivers/mmc/host/sdhci.c
+--- linux-2.6.22-590/drivers/mmc/host/sdhci.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mmc/host/sdhci.c  2007-07-08 19:32:17.000000000 -0400
+@@ -70,14 +70,6 @@
+               .driver_data    = SDHCI_QUIRK_SINGLE_POWER_WRITE,
+       },
  
--      if (phba->fc_flag & FC_OFFLINE_MODE)
-+      if (vport->fc_flag & FC_OFFLINE_MODE)
-               return;
+-      {
+-              .vendor         = PCI_VENDOR_ID_ENE,
+-              .device         = PCI_DEVICE_ID_ENE_CB712_SD_2,
+-              .subvendor      = PCI_ANY_ID,
+-              .subdevice      = PCI_ANY_ID,
+-              .driver_data    = SDHCI_QUIRK_SINGLE_POWER_WRITE,
+-      },
+-
+       {       /* Generic SD host controller */
+               PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
+       },
+diff -Nurb linux-2.6.22-590/drivers/mtd/mtd_blkdevs.c linux-2.6.22-570/drivers/mtd/mtd_blkdevs.c
+--- linux-2.6.22-590/drivers/mtd/mtd_blkdevs.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mtd/mtd_blkdevs.c 2007-07-08 19:32:17.000000000 -0400
+@@ -16,7 +16,6 @@
+ #include <linux/mtd/mtd.h>
+ #include <linux/blkdev.h>
+ #include <linux/blkpg.h>
+-#include <linux/freezer.h>
+ #include <linux/spinlock.h>
+ #include <linux/hdreg.h>
+ #include <linux/init.h>
+@@ -81,7 +80,7 @@
+       struct request_queue *rq = tr->blkcore_priv->rq;
  
-       /* stop all timers associated with this hba */
--      lpfc_stop_timer(phba);
-+      lpfc_stop_phba_timers(phba);
-+      list_for_each_entry(port_iterator, &phba->port_list, listentry) {
-+              port_iterator->work_port_events = 0;
-+      }
+       /* we might get involved when memory gets low, so use PF_MEMALLOC */
+-      current->flags |= PF_MEMALLOC;
++      current->flags |= PF_MEMALLOC | PF_NOFREEZE;
  
--      lpfc_printf_log(phba,
--                     KERN_WARNING,
--                     LOG_INIT,
-+      lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
-                      "%d:0460 Bring Adapter offline\n",
-                      phba->brd_no);
+       spin_lock_irq(rq->queue_lock);
+       while (!kthread_should_stop()) {
+diff -Nurb linux-2.6.22-590/drivers/mtd/ubi/wl.c linux-2.6.22-570/drivers/mtd/ubi/wl.c
+--- linux-2.6.22-590/drivers/mtd/ubi/wl.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/mtd/ubi/wl.c      2007-07-08 19:32:17.000000000 -0400
+@@ -1346,7 +1346,6 @@
+       ubi_msg("background thread \"%s\" started, PID %d",
+               ubi->bgt_name, current->pid);
  
-       /* Bring down the SLI Layer and cleanup.  The HBA is offline
-          now.  */
-       lpfc_sli_hba_down(phba);
--      lpfc_cleanup(phba);
--      spin_lock_irqsave(phba->host->host_lock, iflag);
--      phba->work_hba_events = 0;
-+      spin_lock_irq(&phba->hbalock);
-       phba->work_ha = 0;
--      phba->fc_flag |= FC_OFFLINE_MODE;
--      spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+      vport->fc_flag |= FC_OFFLINE_MODE;
-+      spin_unlock_irq(&phba->hbalock);
-+      list_for_each_entry(port_iterator, &phba->port_list, listentry) {
-+              shost = lpfc_shost_from_vport(port_iterator);
-+
-+              lpfc_cleanup(port_iterator);
-+              spin_lock_irq(shost->host_lock);
-+              vport->work_port_events = 0;
-+              vport->fc_flag |= FC_OFFLINE_MODE;
-+              spin_unlock_irq(shost->host_lock);
-+      }
- }
+-      set_freezable();
+       for (;;) {
+               int err;
  
- /******************************************************************************
-@@ -1326,12 +1482,12 @@
- *
- ******************************************************************************/
- static int
--lpfc_scsi_free(struct lpfc_hba * phba)
-+lpfc_scsi_free(struct lpfc_hba *phba)
- {
-       struct lpfc_scsi_buf *sb, *sb_next;
-       struct lpfc_iocbq *io, *io_next;
+diff -Nurb linux-2.6.22-590/drivers/net/3c523.c linux-2.6.22-570/drivers/net/3c523.c
+--- linux-2.6.22-590/drivers/net/3c523.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/3c523.c       2007-07-08 19:32:17.000000000 -0400
+@@ -990,7 +990,7 @@
+                               if (skb != NULL) {
+                                       skb_reserve(skb, 2);    /* 16 byte alignment */
+                                       skb_put(skb,totlen);
+-                                      skb_copy_to_linear_data(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen);
++                                      eth_copy_and_sum(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen,0);
+                                       skb->protocol = eth_type_trans(skb, dev);
+                                       netif_rx(skb);
+                                       dev->last_rx = jiffies;
+diff -Nurb linux-2.6.22-590/drivers/net/7990.c linux-2.6.22-570/drivers/net/7990.c
+--- linux-2.6.22-590/drivers/net/7990.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/7990.c        2007-07-08 19:32:17.000000000 -0400
+@@ -333,9 +333,9 @@
  
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       /* Release all the lpfc_scsi_bufs maintained by this host. */
-       list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) {
-               list_del(&sb->list);
-@@ -1348,126 +1504,174 @@
-               phba->total_iocbq_bufs--;
-       }
+                         skb_reserve (skb, 2);           /* 16 byte align */
+                         skb_put (skb, len);             /* make room */
+-                        skb_copy_to_linear_data(skb,
++                        eth_copy_and_sum(skb,
+                                          (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
+-                                         len);
++                                         len, 0);
+                         skb->protocol = eth_type_trans (skb, dev);
+                       netif_rx (skb);
+                       dev->last_rx = jiffies;
+diff -Nurb linux-2.6.22-590/drivers/net/8139too.c linux-2.6.22-570/drivers/net/8139too.c
+--- linux-2.6.22-590/drivers/net/8139too.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/8139too.c     2007-07-08 19:32:17.000000000 -0400
+@@ -2017,7 +2017,7 @@
+ #if RX_BUF_IDX == 3
+                       wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
+ #else
+-                      skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size);
++                      eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
+ #endif
+                       skb_put (skb, pkt_size);
  
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
+diff -Nurb linux-2.6.22-590/drivers/net/Kconfig linux-2.6.22-570/drivers/net/Kconfig
+--- linux-2.6.22-590/drivers/net/Kconfig       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/Kconfig       2008-01-23 19:15:59.000000000 -0500
+@@ -119,20 +119,6 @@
  
-       return 0;
- }
+         If you don't know what to use this for, you don't need it.
  
--void lpfc_remove_device(struct lpfc_hba *phba)
--{
--      unsigned long iflag;
+-config ETUN
+-      tristate "Ethernet tunnel device driver support"
+-      depends on SYSFS
+-      ---help---
+-        ETUN provices a pair of network devices that can be used for
+-        configuring interesting topolgies.  What one devices transmits
+-        the other receives and vice versa.  The link level framing
+-        is ethernet for wide compatibility with network stacks.
+-
+-        To compile this driver as a module, choose M here: the module
+-        will be called etun.
 -
--      lpfc_free_sysfs_attr(phba);
+-        If you don't know what to use this for, you don't need it.
+-
+ config NET_SB1000
+       tristate "General Instruments Surfboard 1000"
+       depends on PNP
+@@ -2569,18 +2555,6 @@
  
--      spin_lock_irqsave(phba->host->host_lock, iflag);
--      phba->fc_flag |= FC_UNLOADING;
-+struct lpfc_vport *
-+lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport)
-+{
-+      struct lpfc_vport *vport;
-+      struct Scsi_Host  *shost;
-+      int error = 0;
+ source "drivers/s390/net/Kconfig"
  
--      spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+      shost = scsi_host_alloc(&lpfc_template, sizeof(struct lpfc_vport));
-+      if (!shost)
-+              goto out;
+-config XEN_NETDEV_FRONTEND
+-      tristate "Xen network device frontend driver"
+-      depends on XEN
+-      default y
+-      help
+-        The network device frontend driver allows the kernel to
+-        access network devices exported exported by a virtual
+-        machine containing a physical network device driver. The
+-        frontend driver is intended for unprivileged guest domains;
+-        if you are compiling a kernel for a Xen guest, you almost
+-        certainly want to enable this.
+-
+ config ISERIES_VETH
+       tristate "iSeries Virtual Ethernet driver support"
+       depends on PPC_ISERIES
+diff -Nurb linux-2.6.22-590/drivers/net/Makefile linux-2.6.22-570/drivers/net/Makefile
+--- linux-2.6.22-590/drivers/net/Makefile      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/Makefile      2008-01-23 19:15:59.000000000 -0500
+@@ -186,7 +186,6 @@
+ obj-$(CONFIG_MACMACE) += macmace.o
+ obj-$(CONFIG_MAC89x0) += mac89x0.o
+ obj-$(CONFIG_TUN) += tun.o
+-obj-$(CONFIG_ETUN) += etun.o
+ obj-$(CONFIG_NET_NETX) += netx-eth.o
+ obj-$(CONFIG_DL2K) += dl2k.o
+ obj-$(CONFIG_R8169) += r8169.o
+@@ -225,10 +224,7 @@
+ obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/
  
--      fc_remove_host(phba->host);
--      scsi_remove_host(phba->host);
-+      vport = (struct lpfc_vport *) shost->hostdata;
-+      vport->phba = phba;
+ obj-$(CONFIG_NETCONSOLE) += netconsole.o
+-obj-$(CONFIG_KGDBOE) += kgdboe.o
  
--      kthread_stop(phba->worker_thread);
-+      vport->load_flag |= FC_LOADING;
-+      vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
-+      shost->unique_id = instance;
-+      shost->max_id = LPFC_MAX_TARGET;
-+      shost->max_lun = phba->cfg_max_luns;
-+      shost->this_id = -1;
-+      shost->max_cmd_len = 16;
-       /*
--       * Bring down the SLI Layer. This step disable all interrupts,
--       * clears the rings, discards all mailbox commands, and resets
--       * the HBA.
-+       * Set initial can_queue value since 0 is no longer supported and
-+       * scsi_add_host will fail. This will be adjusted later based on the
-+       * max xri value determined in hba setup.
-        */
--      lpfc_sli_hba_down(phba);
--      lpfc_sli_brdrestart(phba);
-+      shost->can_queue = phba->cfg_hba_queue_depth - 10;
-+      if (fc_vport != NULL) {
-+              shost->transportt = lpfc_vport_transport_template;
-+              vport->port_type = LPFC_NPIV_PORT;
-+      } else {
-+              shost->transportt = lpfc_transport_template;
-+              vport->port_type = LPFC_PHYSICAL_PORT;
-+      }
+ obj-$(CONFIG_FS_ENET) += fs_enet/
  
--      /* Release the irq reservation */
--      free_irq(phba->pcidev->irq, phba);
--      pci_disable_msi(phba->pcidev);
-+      /* Initialize all internally managed lists. */
-+      INIT_LIST_HEAD(&vport->fc_nodes);
-+      spin_lock_init(&vport->work_port_lock);
+ obj-$(CONFIG_NETXEN_NIC) += netxen/
+-obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
+-
+diff -Nurb linux-2.6.22-590/drivers/net/a2065.c linux-2.6.22-570/drivers/net/a2065.c
+--- linux-2.6.22-590/drivers/net/a2065.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/a2065.c       2007-07-08 19:32:17.000000000 -0400
+@@ -322,9 +322,9 @@
+                       skb_reserve (skb, 2);           /* 16 byte align */
+                       skb_put (skb, len);             /* make room */
+-                      skb_copy_to_linear_data(skb,
++                      eth_copy_and_sum(skb,
+                                        (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
+-                                       len);
++                                       len, 0);
+                       skb->protocol = eth_type_trans (skb, dev);
+                       netif_rx (skb);
+                       dev->last_rx = jiffies;
+diff -Nurb linux-2.6.22-590/drivers/net/ariadne.c linux-2.6.22-570/drivers/net/ariadne.c
+--- linux-2.6.22-590/drivers/net/ariadne.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/ariadne.c     2007-07-08 19:32:17.000000000 -0400
+@@ -746,7 +746,7 @@
  
--      lpfc_cleanup(phba);
--      lpfc_stop_timer(phba);
--      phba->work_hba_events = 0;
-+      init_timer(&vport->fc_disctmo);
-+      vport->fc_disctmo.function = lpfc_disc_timeout;
-+      vport->fc_disctmo.data = (unsigned long)vport;
+           skb_reserve(skb,2);         /* 16 byte align */
+           skb_put(skb,pkt_len);       /* Make room */
+-          skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry], pkt_len);
++          eth_copy_and_sum(skb, (char *)priv->rx_buff[entry], pkt_len,0);
+           skb->protocol=eth_type_trans(skb,dev);
+ #if 0
+           printk(KERN_DEBUG "RX pkt type 0x%04x from ",
+diff -Nurb linux-2.6.22-590/drivers/net/arm/ep93xx_eth.c linux-2.6.22-570/drivers/net/arm/ep93xx_eth.c
+--- linux-2.6.22-590/drivers/net/arm/ep93xx_eth.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/arm/ep93xx_eth.c      2007-07-08 19:32:17.000000000 -0400
+@@ -258,7 +258,7 @@
+                       skb_reserve(skb, 2);
+                       dma_sync_single(NULL, ep->descs->rdesc[entry].buf_addr,
+                                               length, DMA_FROM_DEVICE);
+-                      skb_copy_to_linear_data(skb, ep->rx_buf[entry], length);
++                      eth_copy_and_sum(skb, ep->rx_buf[entry], length, 0);
+                       skb_put(skb, length);
+                       skb->protocol = eth_type_trans(skb, dev);
  
--      /*
--       * Call scsi_free before mem_free since scsi bufs are released to their
--       * corresponding pools here.
--       */
--      lpfc_scsi_free(phba);
--      lpfc_mem_free(phba);
-+      init_timer(&vport->fc_fdmitmo);
-+      vport->fc_fdmitmo.function = lpfc_fdmi_tmo;
-+      vport->fc_fdmitmo.data = (unsigned long)vport;
+diff -Nurb linux-2.6.22-590/drivers/net/au1000_eth.c linux-2.6.22-570/drivers/net/au1000_eth.c
+--- linux-2.6.22-590/drivers/net/au1000_eth.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/au1000_eth.c  2007-07-08 19:32:17.000000000 -0400
+@@ -1205,8 +1205,8 @@
+                               continue;
+                       }
+                       skb_reserve(skb, 2);    /* 16 byte IP header align */
+-                      skb_copy_to_linear_data(skb,
+-                              (unsigned char *)pDB->vaddr, frmlen);
++                      eth_copy_and_sum(skb,
++                              (unsigned char *)pDB->vaddr, frmlen, 0);
+                       skb_put(skb, frmlen);
+                       skb->protocol = eth_type_trans(skb, dev);
+                       netif_rx(skb);  /* pass the packet to upper layers */
+diff -Nurb linux-2.6.22-590/drivers/net/bnx2.c linux-2.6.22-570/drivers/net/bnx2.c
+--- linux-2.6.22-590/drivers/net/bnx2.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/bnx2.c        2007-07-08 19:32:17.000000000 -0400
+@@ -6490,10 +6490,10 @@
+       memcpy(dev->perm_addr, bp->mac_addr, 6);
+       bp->name = board_info[ent->driver_data].name;
  
--      /* Free resources associated with SLI2 interface */
--      dma_free_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE,
--                        phba->slim2p, phba->slim2p_mapping);
-+      init_timer(&vport->els_tmofunc);
-+      vport->els_tmofunc.function = lpfc_els_timeout;
-+      vport->els_tmofunc.data = (unsigned long)vport;
+-              dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+-              dev->features |= NETIF_F_IPV6_CSUM;
+-
++              dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
++      else
++              dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+ #ifdef BCM_VLAN
+       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ #endif
+diff -Nurb linux-2.6.22-590/drivers/net/bonding/bond_3ad.c linux-2.6.22-570/drivers/net/bonding/bond_3ad.c
+--- linux-2.6.22-590/drivers/net/bonding/bond_3ad.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/bonding/bond_3ad.c    2007-07-08 19:32:17.000000000 -0400
+@@ -29,7 +29,6 @@
+ #include <linux/ethtool.h>
+ #include <linux/if_bonding.h>
+ #include <linux/pkt_sched.h>
+-#include <net/net_namespace.h>
+ #include "bonding.h"
+ #include "bond_3ad.h"
  
--      /* unmap adapter SLIM and Control Registers */
--      iounmap(phba->ctrl_regs_memmap_p);
--      iounmap(phba->slim_memmap_p);
-+      if (fc_vport != NULL) {
-+              error = scsi_add_host(shost, &fc_vport->dev);
-+      } else {
-+              error = scsi_add_host(shost, &phba->pcidev->dev);
-+      }
-+      if (error)
-+              goto out_put_shost;
+@@ -2449,9 +2448,6 @@
+       struct slave *slave = NULL;
+       int ret = NET_RX_DROP;
  
--      pci_release_regions(phba->pcidev);
--      pci_disable_device(phba->pcidev);
-+      list_add_tail(&vport->listentry, &phba->port_list);
-+      return vport;
+-      if (dev->nd_net != &init_net)
+-              goto out;
+-
+       if (!(dev->flags & IFF_MASTER))
+               goto out;
  
--      idr_remove(&lpfc_hba_index, phba->brd_no);
--      scsi_host_put(phba->host);
-+out_put_shost:
-+      scsi_host_put(shost);
-+out:
-+      return NULL;
- }
+diff -Nurb linux-2.6.22-590/drivers/net/bonding/bond_alb.c linux-2.6.22-570/drivers/net/bonding/bond_alb.c
+--- linux-2.6.22-590/drivers/net/bonding/bond_alb.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/bonding/bond_alb.c    2007-07-08 19:32:17.000000000 -0400
+@@ -345,9 +345,6 @@
+       struct arp_pkt *arp = (struct arp_pkt *)skb->data;
+       int res = NET_RX_DROP;
  
--void lpfc_scan_start(struct Scsi_Host *host)
-+void
-+destroy_port(struct lpfc_vport *vport)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
+-      if (bond_dev->nd_net != &init_net)
+-              goto out;
+-
+       if (!(bond_dev->flags & IFF_MASTER))
+               goto out;
  
--      if (lpfc_alloc_sysfs_attr(phba))
--              goto error;
-+      kfree(vport->vname);
+diff -Nurb linux-2.6.22-590/drivers/net/bonding/bond_main.c linux-2.6.22-570/drivers/net/bonding/bond_main.c
+--- linux-2.6.22-590/drivers/net/bonding/bond_main.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/bonding/bond_main.c   2008-01-23 19:15:55.000000000 -0500
+@@ -75,7 +75,6 @@
+ #include <linux/if_vlan.h>
+ #include <linux/if_bonding.h>
+ #include <net/route.h>
+-#include <net/net_namespace.h>
+ #include "bonding.h"
+ #include "bond_3ad.h"
+ #include "bond_alb.h"
+@@ -2377,7 +2376,6 @@
+                * can tag the ARP with the proper VLAN tag.
+                */
+               memset(&fl, 0, sizeof(fl));
+-              fl.fl_net = &init_net;
+               fl.fl4_dst = targets[i];
+               fl.fl4_tos = RTO_ONLINK;
  
--      phba->MBslimaddr = phba->slim_memmap_p;
--      phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
--      phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
--      phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
--      phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
-+      lpfc_debugfs_terminate(vport);
-+      fc_remove_host(shost);
-+      scsi_remove_host(shost);
+@@ -2487,9 +2485,6 @@
+       unsigned char *arp_ptr;
+       u32 sip, tip;
  
--      if (lpfc_sli_hba_setup(phba))
--              goto error;
-+      spin_lock_irq(&phba->hbalock);
-+      list_del_init(&vport->listentry);
-+      spin_unlock_irq(&phba->hbalock);
+-      if (dev->nd_net != &init_net)
+-              goto out;
+-
+       if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
+               goto out;
  
--      /*
--       * hba setup may have changed the hba_queue_depth so we need to adjust
--       * the value of can_queue.
--       */
--      host->can_queue = phba->cfg_hba_queue_depth - 10;
-+      lpfc_cleanup(vport);
-       return;
-+}
+@@ -3177,7 +3172,7 @@
+ {
+       int len = strlen(DRV_NAME);
  
--error:
--      lpfc_remove_device(phba);
-+int
-+lpfc_get_instance(void)
-+{
-+      int instance = 0;
-+
-+      /* Assign an unused number */
-+      if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))
-+              return -1;
-+      if (idr_get_new(&lpfc_hba_index, NULL, &instance))
-+              return -1;
-+      return instance;
- }
+-      for (bond_proc_dir = init_net.proc_net->subdir; bond_proc_dir;
++      for (bond_proc_dir = proc_net->subdir; bond_proc_dir;
+            bond_proc_dir = bond_proc_dir->next) {
+               if ((bond_proc_dir->namelen == len) &&
+                   !memcmp(bond_proc_dir->name, DRV_NAME, len)) {
+@@ -3186,7 +3181,7 @@
+       }
  
-+/*
-+ * Note: there is no scan_start function as adapter initialization
-+ * will have asynchronously kicked off the link initialization.
-+ */
-+
- int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
+       if (!bond_proc_dir) {
+-              bond_proc_dir = proc_mkdir(DRV_NAME, init_net.proc_net);
++              bond_proc_dir = proc_mkdir(DRV_NAME, proc_net);
+               if (bond_proc_dir) {
+                       bond_proc_dir->owner = THIS_MODULE;
+               } else {
+@@ -3221,7 +3216,7 @@
+                       bond_proc_dir->owner = NULL;
+               }
+       } else {
+-              remove_proc_entry(DRV_NAME, init_net.proc_net);
++              remove_proc_entry(DRV_NAME, proc_net);
+               bond_proc_dir = NULL;
+       }
+ }
+@@ -3328,9 +3323,6 @@
  {
--      struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+      int stat = 0;
+       struct net_device *event_dev = (struct net_device *)ptr;
  
--      if (!phba->host)
--              return 1;
--      if (time >= 30 * HZ)
-+      spin_lock_irq(shost->host_lock);
-+
-+      if (vport->fc_flag & FC_UNLOADING) {
-+              stat = 1;
-               goto finished;
-+      }
-+      if (time >= 30 * HZ) {
-+              lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-+                              "%d:0461 Scanning longer than 30 "
-+                              "seconds.  Continuing initialization\n",
-+                              phba->brd_no);
-+              stat = 1;
-+              goto finished;
-+      }
-+      if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) {
-+              lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-+                              "%d:0465 Link down longer than 15 "
-+                              "seconds.  Continuing initialization\n",
-+                              phba->brd_no);
-+              stat = 1;
-+              goto finished;
-+      }
+-      if (event_dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       dprintk("event_dev: %s, event: %lx\n",
+               (event_dev ? event_dev->name : "None"),
+               event);
+@@ -3748,7 +3740,7 @@
+       }
  
--      if (phba->hba_state != LPFC_HBA_READY)
--              return 0;
--      if (phba->num_disc_nodes || phba->fc_prli_sent)
--              return 0;
--      if ((phba->fc_map_cnt == 0) && (time < 2 * HZ))
--              return 0;
--      if (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)
--              return 0;
--      if ((phba->hba_state > LPFC_LINK_DOWN) || (time < 15 * HZ))
--              return 0;
-+      if (vport->port_state != LPFC_VPORT_READY)
-+              goto finished;
-+      if (vport->num_disc_nodes || vport->fc_prli_sent)
-+              goto finished;
-+      if (vport->fc_map_cnt == 0 && time < 2 * HZ)
-+              goto finished;
-+      if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0)
-+              goto finished;
-+
-+      stat = 1;
+       down_write(&(bonding_rwsem));
+-      slave_dev = dev_get_by_name(&init_net, ifr->ifr_slave);
++      slave_dev = dev_get_by_name(ifr->ifr_slave);
  
- finished:
--      if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
--              spin_lock_irq(shost->host_lock);
--              lpfc_poll_start_timer(phba);
-               spin_unlock_irq(shost->host_lock);
--      }
-+      return stat;
-+}
+       dprintk("slave_dev=%p: \n", slave_dev);
  
-+void lpfc_host_attrib_init(struct Scsi_Host *shost)
-+{
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       /*
--       * set fixed host attributes
--       * Must done after lpfc_sli_hba_setup()
-+       * Set fixed host attributes.  Must done after lpfc_sli_hba_setup().
-        */
+diff -Nurb linux-2.6.22-590/drivers/net/bonding/bond_sysfs.c linux-2.6.22-570/drivers/net/bonding/bond_sysfs.c
+--- linux-2.6.22-590/drivers/net/bonding/bond_sysfs.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/bonding/bond_sysfs.c  2007-07-08 19:32:17.000000000 -0400
+@@ -35,7 +35,6 @@
+ #include <linux/ctype.h>
+ #include <linux/inet.h>
+ #include <linux/rtnetlink.h>
+-#include <net/net_namespace.h>
  
--      fc_host_node_name(shost) = wwn_to_u64(phba->fc_nodename.u.wwn);
--      fc_host_port_name(shost) = wwn_to_u64(phba->fc_portname.u.wwn);
-+      fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn);
-+      fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn);
-       fc_host_supported_classes(shost) = FC_COS_CLASS3;
+ /* #define BONDING_DEBUG 1 */
+ #include "bonding.h"
+@@ -300,7 +299,7 @@
+               read_unlock_bh(&bond->lock);
+               printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n",
+                      bond->dev->name, ifname);
+-              dev = dev_get_by_name(&init_net, ifname);
++              dev = dev_get_by_name(ifname);
+               if (!dev) {
+                       printk(KERN_INFO DRV_NAME
+                              ": %s: Interface %s does not exist!\n",
+diff -Nurb linux-2.6.22-590/drivers/net/dl2k.c linux-2.6.22-570/drivers/net/dl2k.c
+--- linux-2.6.22-590/drivers/net/dl2k.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/dl2k.c        2007-07-08 19:32:17.000000000 -0400
+@@ -866,9 +866,9 @@
+                                                           PCI_DMA_FROMDEVICE);
+                               /* 16 byte align the IP header */
+                               skb_reserve (skb, 2);
+-                              skb_copy_to_linear_data (skb,
++                              eth_copy_and_sum (skb,
+                                                 np->rx_skbuff[entry]->data,
+-                                                pkt_len);
++                                                pkt_len, 0);
+                               skb_put (skb, pkt_len);
+                               pci_dma_sync_single_for_device(np->pdev,
+                                                              desc->fraginfo &
+diff -Nurb linux-2.6.22-590/drivers/net/dummy.c linux-2.6.22-570/drivers/net/dummy.c
+--- linux-2.6.22-590/drivers/net/dummy.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/dummy.c       2007-07-08 19:32:17.000000000 -0400
+@@ -34,17 +34,11 @@
+ #include <linux/etherdevice.h>
+ #include <linux/init.h>
+ #include <linux/moduleparam.h>
+-#include <linux/rtnetlink.h>
+-#include <net/rtnetlink.h>
+-
+-struct dummy_priv {
+-      struct net_device *dev;
+-      struct list_head list;
+-};
  
-       memset(fc_host_supported_fc4s(shost), 0,
-@@ -1475,7 +1679,8 @@
-       fc_host_supported_fc4s(shost)[2] = 1;
-       fc_host_supported_fc4s(shost)[7] = 1;
+ static int numdummies = 1;
  
--      lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost));
-+      lpfc_vport_symbolic_node_name(vport, fc_host_symbolic_name(shost),
-+                               sizeof fc_host_symbolic_name(shost));
+ static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);
++static struct net_device_stats *dummy_get_stats(struct net_device *dev);
  
-       fc_host_supported_speeds(shost) = 0;
-       if (phba->lmt & LMT_10Gb)
-@@ -1488,8 +1693,8 @@
-               fc_host_supported_speeds(shost) |= FC_PORTSPEED_1GBIT;
+ static int dummy_set_address(struct net_device *dev, void *p)
+ {
+@@ -62,13 +56,13 @@
+ {
+ }
  
-       fc_host_maxframe_size(shost) =
--              ((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
--               (uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb);
-+              (((uint32_t) vport->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
-+              (uint32_t) vport->fc_sparam.cmn.bbRcvSizeLsb;
+-static void dummy_setup(struct net_device *dev)
++static void __init dummy_setup(struct net_device *dev)
+ {
+       /* Initialize the device structure. */
++      dev->get_stats = dummy_get_stats;
+       dev->hard_start_xmit = dummy_xmit;
+       dev->set_multicast_list = set_multicast_list;
+       dev->set_mac_address = dummy_set_address;
+-      dev->destructor = free_netdev;
  
-       /* This value is also unchanging */
-       memset(fc_host_active_fc4s(shost), 0,
-@@ -1497,20 +1702,20 @@
-       fc_host_active_fc4s(shost)[2] = 1;
-       fc_host_active_fc4s(shost)[7] = 1;
+       /* Fill in device structure with ethernet-generic values. */
+       ether_setup(dev);
+@@ -82,114 +76,77 @@
  
-+      fc_host_max_npiv_vports(shost) = phba->max_vpi;
-       spin_lock_irq(shost->host_lock);
--      phba->fc_flag &= ~FC_LOADING;
-+      vport->fc_flag &= ~FC_LOADING;
-       spin_unlock_irq(shost->host_lock);
+ static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+-      dev->stats.tx_packets++;
+-      dev->stats.tx_bytes += skb->len;
++      struct net_device_stats *stats = netdev_priv(dev);
+-      dev_kfree_skb(skb);
+-      return 0;
+-}
++      stats->tx_packets++;
++      stats->tx_bytes+=skb->len;
+-static LIST_HEAD(dummies);
 -
--      return 1;
+-static int dummy_newlink(struct net_device *dev,
+-                       struct nlattr *tb[], struct nlattr *data[])
+-{
+-      struct dummy_priv *priv = netdev_priv(dev);
+-      int err;
+-
+-      err = register_netdevice(dev);
+-      if (err < 0)
+-              return err;
+-
+-      priv->dev = dev;
+-      list_add_tail(&priv->list, &dummies);
++      dev_kfree_skb(skb);
+       return 0;
  }
  
- static int __devinit
- lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
+-static void dummy_dellink(struct net_device *dev)
++static struct net_device_stats *dummy_get_stats(struct net_device *dev)
  {
--      struct Scsi_Host *host;
-+      struct lpfc_vport *vport = NULL;
-       struct lpfc_hba  *phba;
-       struct lpfc_sli  *psli;
-       struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL;
-+      struct Scsi_Host  *shost = NULL;
-       unsigned long bar0map_len, bar2map_len;
-       int error = -ENODEV, retval;
-       int i;
-@@ -1521,61 +1726,46 @@
-       if (pci_request_regions(pdev, LPFC_DRIVER_NAME))
-               goto out_disable_device;
+-      struct dummy_priv *priv = netdev_priv(dev);
+-
+-      list_del(&priv->list);
+-      unregister_netdevice(dev);
++      return netdev_priv(dev);
+ }
  
--      host = scsi_host_alloc(&lpfc_template, sizeof (struct lpfc_hba));
--      if (!host)
-+      phba = kzalloc(sizeof (struct lpfc_hba), GFP_KERNEL);
-+      if (!phba)
-               goto out_release_regions;
+-static struct rtnl_link_ops dummy_link_ops __read_mostly = {
+-      .kind           = "dummy",
+-      .priv_size      = sizeof(struct dummy_priv),
+-      .setup          = dummy_setup,
+-      .newlink        = dummy_newlink,
+-      .dellink        = dummy_dellink,
+-};
++static struct net_device **dummies;
  
--      phba = (struct lpfc_hba*)host->hostdata;
--      memset(phba, 0, sizeof (struct lpfc_hba));
--      phba->host = host;
-+      spin_lock_init(&phba->hbalock);
+ /* Number of dummy devices to be set up by this module. */
+ module_param(numdummies, int, 0);
+ MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
  
--      phba->fc_flag |= FC_LOADING;
-       phba->pcidev = pdev;
+-static int __init dummy_init_one(void)
++static int __init dummy_init_one(int index)
+ {
+       struct net_device *dev_dummy;
+-      struct dummy_priv *priv;
+       int err;
  
-       /* Assign an unused board number */
--      if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))
--              goto out_put_host;
-+      if ((phba->brd_no = lpfc_get_instance()) < 0)
-+              goto out_free_phba;
+-      dev_dummy = alloc_netdev(sizeof(struct dummy_priv), "dummy%d",
+-                               dummy_setup);
++      dev_dummy = alloc_netdev(sizeof(struct net_device_stats),
++                               "dummy%d", dummy_setup);
  
--      error = idr_get_new(&lpfc_hba_index, NULL, &phba->brd_no);
--      if (error)
--              goto out_put_host;
--
--      host->unique_id = phba->brd_no;
-+      INIT_LIST_HEAD(&phba->port_list);
-+      INIT_LIST_HEAD(&phba->hbq_buffer_list);
-+      /*
-+       * Get all the module params for configuring this host and then
-+       * establish the host.
-+       */
-+      lpfc_get_cfgparam(phba);
-+      phba->max_vpi = LPFC_MAX_VPI;
+       if (!dev_dummy)
+               return -ENOMEM;
  
-       /* Initialize timers used by driver */
-       init_timer(&phba->fc_estabtmo);
-       phba->fc_estabtmo.function = lpfc_establish_link_tmo;
-       phba->fc_estabtmo.data = (unsigned long)phba;
--      init_timer(&phba->fc_disctmo);
--      phba->fc_disctmo.function = lpfc_disc_timeout;
--      phba->fc_disctmo.data = (unsigned long)phba;
--
--      init_timer(&phba->fc_fdmitmo);
--      phba->fc_fdmitmo.function = lpfc_fdmi_tmo;
--      phba->fc_fdmitmo.data = (unsigned long)phba;
--      init_timer(&phba->els_tmofunc);
--      phba->els_tmofunc.function = lpfc_els_timeout;
--      phba->els_tmofunc.data = (unsigned long)phba;
-+
-+      init_timer(&phba->hb_tmofunc);
-+      phba->hb_tmofunc.function = lpfc_hb_timeout;
-+      phba->hb_tmofunc.data = (unsigned long)phba;
-+
-       psli = &phba->sli;
-       init_timer(&psli->mbox_tmo);
-       psli->mbox_tmo.function = lpfc_mbox_timeout;
--      psli->mbox_tmo.data = (unsigned long)phba;
--
-+      psli->mbox_tmo.data = (unsigned long) phba;
-       init_timer(&phba->fcp_poll_timer);
-       phba->fcp_poll_timer.function = lpfc_poll_timeout;
--      phba->fcp_poll_timer.data = (unsigned long)phba;
+-      err = dev_alloc_name(dev_dummy, dev_dummy->name);
+-      if (err < 0)
+-              goto err;
 -
--      /*
--       * Get all the module params for configuring this host and then
--       * establish the host parameters.
--       */
--      lpfc_get_cfgparam(phba);
+-      dev_dummy->rtnl_link_ops = &dummy_link_ops;
+-      err = register_netdevice(dev_dummy);
+-      if (err < 0)
+-              goto err;
 -
--      host->max_id = LPFC_MAX_TARGET;
--      host->max_lun = phba->cfg_max_luns;
--      host->this_id = -1;
+-      priv = netdev_priv(dev_dummy);
+-      priv->dev = dev_dummy;
+-      list_add_tail(&priv->list, &dummies);
+-      return 0;
 -
--      INIT_LIST_HEAD(&phba->fc_nodes);
-+      phba->fcp_poll_timer.data = (unsigned long) phba;
-+      init_timer(&phba->fabric_block_timer);
-+      phba->fabric_block_timer.function = lpfc_fabric_block_timeout;
-+      phba->fabric_block_timer.data = (unsigned long) phba;
-       pci_set_master(pdev);
-       retval = pci_set_mwi(pdev);
-@@ -1623,13 +1813,22 @@
-       memset(phba->slim2p, 0, SLI2_SLIM_SIZE);
-+      phba->hbqslimp.virt = dma_alloc_coherent(&phba->pcidev->dev,
-+                                               lpfc_sli_hbq_size(),
-+                                               &phba->hbqslimp.phys,
-+                                               GFP_KERNEL);
-+      if (!phba->hbqslimp.virt)
-+              goto out_free_slim;
-+
-+      memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size());
+-err:
++      if ((err = register_netdev(dev_dummy))) {
+       free_netdev(dev_dummy);
++              dev_dummy = NULL;
++      } else {
++              dummies[index] = dev_dummy;
++      }
 +
-       /* Initialize the SLI Layer to run with lpfc HBAs. */
-       lpfc_sli_setup(phba);
-       lpfc_sli_queue_setup(phba);
-       error = lpfc_mem_alloc(phba);
-       if (error)
--              goto out_free_slim;
-+              goto out_free_hbqslimp;
+       return err;
+ }
  
-       /* Initialize and populate the iocb list per host.  */
-       INIT_LIST_HEAD(&phba->lpfc_iocb_list);
-@@ -1653,10 +1852,11 @@
-                       error = -ENOMEM;
-                       goto out_free_iocbq;
-               }
--              spin_lock_irq(phba->host->host_lock);
++static void dummy_free_one(int index)
++{
++      unregister_netdev(dummies[index]);
++      free_netdev(dummies[index]);
++}
 +
-+              spin_lock_irq(&phba->hbalock);
-               list_add(&iocbq_entry->list, &phba->lpfc_iocb_list);
-               phba->total_iocbq_bufs++;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(&phba->hbalock);
-       }
-       /* Initialize HBA structure */
-@@ -1677,22 +1877,22 @@
-               goto out_free_iocbq;
+ static int __init dummy_init_module(void)
+ {
+-      struct dummy_priv *priv, *next;
+       int i, err = 0;
+-
+-      rtnl_lock();
+-      err = __rtnl_link_register(&dummy_link_ops);
+-
++      dummies = kmalloc(numdummies * sizeof(void *), GFP_KERNEL);
++      if (!dummies)
++              return -ENOMEM;
+       for (i = 0; i < numdummies && !err; i++)
+-              err = dummy_init_one();
+-      if (err < 0) {
+-              list_for_each_entry_safe(priv, next, &dummies, list)
+-                      dummy_dellink(priv->dev);
+-              __rtnl_link_unregister(&dummy_link_ops);
++              err = dummy_init_one(i);
++      if (err) {
++              i--;
++              while (--i >= 0)
++                      dummy_free_one(i);
        }
+-      rtnl_unlock();
+-
+       return err;
+ }
  
--      /*
--       * Set initial can_queue value since 0 is no longer supported and
--       * scsi_add_host will fail. This will be adjusted later based on the
--       * max xri value determined in hba setup.
--       */
--      host->can_queue = phba->cfg_hba_queue_depth - 10;
+ static void __exit dummy_cleanup_module(void)
+ {
+-      struct dummy_priv *priv, *next;
 -
--      /* Tell the midlayer we support 16 byte commands */
--      host->max_cmd_len = 16;
+-      rtnl_lock();
+-      list_for_each_entry_safe(priv, next, &dummies, list)
+-              dummy_dellink(priv->dev);
 -
-       /* Initialize the list of scsi buffers used by driver for scsi IO. */
-       spin_lock_init(&phba->scsi_buf_list_lock);
-       INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list);
+-      __rtnl_link_unregister(&dummy_link_ops);
+-      rtnl_unlock();
++      int i;
++      for (i = 0; i < numdummies; i++)
++              dummy_free_one(i);
++      kfree(dummies);
+ }
  
--      host->transportt = lpfc_transport_template;
--      pci_set_drvdata(pdev, host);
-+      /* Initialize list of fabric iocbs */
-+      INIT_LIST_HEAD(&phba->fabric_iocb_list);
-+
-+      vport = lpfc_create_port(phba, phba->brd_no, NULL);
-+      if (!vport)
-+              goto out_kthread_stop;
-+
-+      shost = lpfc_shost_from_vport(vport);
-+      phba->pport = vport;
-+      lpfc_debugfs_initialize(vport);
-+
-+      pci_set_drvdata(pdev, shost);
+ module_init(dummy_init_module);
+ module_exit(dummy_cleanup_module);
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS_RTNL_LINK("dummy");
+diff -Nurb linux-2.6.22-590/drivers/net/eepro100.c linux-2.6.22-570/drivers/net/eepro100.c
+--- linux-2.6.22-590/drivers/net/eepro100.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/eepro100.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1801,7 +1801,7 @@
  
-       if (phba->cfg_use_msi) {
-               error = pci_enable_msi(phba->pcidev);
-@@ -1708,33 +1908,63 @@
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                       "%d:0451 Enable interrupt handler failed\n",
-                       phba->brd_no);
--              goto out_kthread_stop;
-+              goto out_disable_msi;
-       }
+ #if 1 || USE_IP_CSUM
+                               /* Packet is in one chunk -- we can copy + cksum. */
+-                              skb_copy_to_linear_data(skb, sp->rx_skbuff[entry]->data, pkt_len);
++                              eth_copy_and_sum(skb, sp->rx_skbuff[entry]->data, pkt_len, 0);
+                               skb_put(skb, pkt_len);
+ #else
+                               skb_copy_from_linear_data(sp->rx_skbuff[entry],
+diff -Nurb linux-2.6.22-590/drivers/net/epic100.c linux-2.6.22-570/drivers/net/epic100.c
+--- linux-2.6.22-590/drivers/net/epic100.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/epic100.c     2007-07-08 19:32:17.000000000 -0400
+@@ -1201,7 +1201,7 @@
+                                                           ep->rx_ring[entry].bufaddr,
+                                                           ep->rx_buf_sz,
+                                                           PCI_DMA_FROMDEVICE);
+-                              skb_copy_to_linear_data(skb, ep->rx_skbuff[entry]->data, pkt_len);
++                              eth_copy_and_sum(skb, ep->rx_skbuff[entry]->data, pkt_len, 0);
+                               skb_put(skb, pkt_len);
+                               pci_dma_sync_single_for_device(ep->pci_dev,
+                                                              ep->rx_ring[entry].bufaddr,
+diff -Nurb linux-2.6.22-590/drivers/net/eql.c linux-2.6.22-570/drivers/net/eql.c
+--- linux-2.6.22-590/drivers/net/eql.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/eql.c 2007-07-08 19:32:17.000000000 -0400
+@@ -116,7 +116,6 @@
+ #include <linux/init.h>
+ #include <linux/timer.h>
+ #include <linux/netdevice.h>
+-#include <net/net_namespace.h>
  
--      error = scsi_add_host(host, &pdev->dev);
--      if (error)
-+      phba->MBslimaddr = phba->slim_memmap_p;
-+      phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
-+      phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
-+      phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
-+      phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
-+
-+      if (lpfc_alloc_sysfs_attr(vport))
-               goto out_free_irq;
+ #include <linux/if.h>
+ #include <linux/if_arp.h>
+@@ -413,7 +412,7 @@
+       if (copy_from_user(&srq, srqp, sizeof (slaving_request_t)))
+               return -EFAULT;
  
--      scsi_scan_host(host);
-+      if (lpfc_sli_hba_setup(phba))
-+              goto out_remove_device;
-+
-+      /*
-+       * hba setup may have changed the hba_queue_depth so we need to adjust
-+       * the value of can_queue.
-+       */
-+      shost->can_queue = phba->cfg_hba_queue_depth - 10;
-+
-+      lpfc_host_attrib_init(shost);
-+
-+      if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
-+              spin_lock_irq(shost->host_lock);
-+              lpfc_poll_start_timer(phba);
-+              spin_unlock_irq(shost->host_lock);
-+      }
-+
-+      scsi_scan_host(shost);
+-      slave_dev  = dev_get_by_name(&init_net, srq.slave_name);
++      slave_dev  = dev_get_by_name(srq.slave_name);
+       if (slave_dev) {
+               if ((master_dev->flags & IFF_UP) == IFF_UP) {
+                       /* slave is not a master & not already a slave: */
+@@ -461,7 +460,7 @@
+       if (copy_from_user(&srq, srqp, sizeof (slaving_request_t)))
+               return -EFAULT;
  
-       return 0;
+-      slave_dev = dev_get_by_name(&init_net, srq.slave_name);
++      slave_dev = dev_get_by_name(srq.slave_name);
+       ret = -EINVAL;
+       if (slave_dev) {
+               spin_lock_bh(&eql->queue.lock);
+@@ -494,7 +493,7 @@
+       if (copy_from_user(&sc, scp, sizeof (slave_config_t)))
+               return -EFAULT;
  
-+out_remove_device:
-+      lpfc_free_sysfs_attr(vport);
-+      spin_lock_irq(shost->host_lock);
-+      vport->fc_flag |= FC_UNLOADING;
-+      spin_unlock_irq(shost->host_lock);
- out_free_irq:
--      lpfc_stop_timer(phba);
--      phba->work_hba_events = 0;
-+      lpfc_stop_phba_timers(phba);
-+      phba->pport->work_port_events = 0;
-       free_irq(phba->pcidev->irq, phba);
-+out_disable_msi:
-       pci_disable_msi(phba->pcidev);
-+      destroy_port(vport);
- out_kthread_stop:
-       kthread_stop(phba->worker_thread);
- out_free_iocbq:
-       list_for_each_entry_safe(iocbq_entry, iocbq_next,
-                                               &phba->lpfc_iocb_list, list) {
--              spin_lock_irq(phba->host->host_lock);
-               kfree(iocbq_entry);
-               phba->total_iocbq_bufs--;
--              spin_unlock_irq(phba->host->host_lock);
-       }
-       lpfc_mem_free(phba);
-+out_free_hbqslimp:
-+      dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(), phba->hbqslimp.virt,
-+                        phba->hbqslimp.phys);
- out_free_slim:
-       dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE, phba->slim2p,
-                                                       phba->slim2p_mapping);
-@@ -1744,27 +1974,85 @@
-       iounmap(phba->slim_memmap_p);
- out_idr_remove:
-       idr_remove(&lpfc_hba_index, phba->brd_no);
--out_put_host:
--      phba->host = NULL;
--      scsi_host_put(host);
-+out_free_phba:
-+      kfree(phba);
- out_release_regions:
-       pci_release_regions(pdev);
- out_disable_device:
-       pci_disable_device(pdev);
- out:
-       pci_set_drvdata(pdev, NULL);
-+      if (shost)
-+              scsi_host_put(shost);
-       return error;
- }
+-      slave_dev = dev_get_by_name(&init_net, sc.slave_name);
++      slave_dev = dev_get_by_name(sc.slave_name);
+       if (!slave_dev)
+               return -ENODEV;
  
- static void __devexit
- lpfc_pci_remove_one(struct pci_dev *pdev)
- {
--      struct Scsi_Host   *host = pci_get_drvdata(pdev);
--      struct lpfc_hba    *phba = (struct lpfc_hba *)host->hostdata;
-+      struct Scsi_Host  *shost = pci_get_drvdata(pdev);
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-+      struct lpfc_vport *port_iterator;
-+      list_for_each_entry(port_iterator, &phba->port_list, listentry)
-+              port_iterator->load_flag |= FC_UNLOADING;
-+
-+      kfree(vport->vname);
-+      lpfc_free_sysfs_attr(vport);
+@@ -529,7 +528,7 @@
+       if (copy_from_user(&sc, scp, sizeof (slave_config_t)))
+               return -EFAULT;
+-      slave_dev = dev_get_by_name(&init_net, sc.slave_name);
++      slave_dev = dev_get_by_name(sc.slave_name);
+       if (!slave_dev)
+               return -ENODEV;
+diff -Nurb linux-2.6.22-590/drivers/net/etun.c linux-2.6.22-570/drivers/net/etun.c
+--- linux-2.6.22-590/drivers/net/etun.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/etun.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,489 +0,0 @@
+-/*
+- *  ETUN - Universal ETUN device driver.
+- *  Copyright (C) 2006 Linux Networx
+- *
+- */
+-
+-#define DRV_NAME      "etun"
+-#define DRV_VERSION   "1.0"
+-#define DRV_DESCRIPTION       "Ethernet pseudo tunnel device driver"
+-#define DRV_COPYRIGHT "(C) 2007 Linux Networx"
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/list.h>
+-#include <linux/spinlock.h>
+-#include <linux/skbuff.h>
+-#include <linux/netdevice.h>
+-#include <linux/etherdevice.h>
+-#include <linux/ethtool.h>
+-#include <linux/rtnetlink.h>
+-#include <linux/if.h>
+-#include <linux/if_ether.h>
+-#include <linux/ctype.h>
+-#include <linux/nsproxy.h>
+-#include <net/net_namespace.h>
+-#include <net/dst.h>
+-
+-
+-/* Device cheksum strategy.
+- *
+- * etun is designed to a be a pair of virutal devices
+- * connecting two network stack instances.
+- *
+- * Typically it will either be used with ethernet bridging or
+- * it will be used to route packets between the two stacks.
+- *
+- * The only checksum offloading I can do is to completely
+- * skip the checksumming step all together.
+- *
+- * When used for ethernet bridging I don't believe any
+- * checksum off loading is safe.
+- * - If my source is an external interface the checksum may be
+- *   invalid so I don't want to report I have already checked it.
+- * - If my destination is an external interface I don't want to put
+- *   a packet on the wire with someone computing the checksum.
+- *
+- * When used for routing between two stacks checksums should
+- * be as unnecessary as they are on the loopback device.
+- *
+- * So by default I am safe and disable checksumming and
+- * other advanced features like SG and TSO.
+- *
+- * However because I think these features could be useful
+- * I provide the ethtool functions to and enable/disable
+- * them at runtime.
+- *
+- * If you think you can correctly enable these go ahead.
+- * For checksums both the transmitter and the receiver must
+- * agree before the are actually disabled.
+- */
+-
+-#define ETUN_NUM_STATS 1
+-static struct {
+-      const char string[ETH_GSTRING_LEN];
+-} ethtool_stats_keys[ETUN_NUM_STATS] = {
+-      { "partner_ifindex" },
+-};
+-
+-struct etun_info {
+-      struct net_device       *rx_dev;
+-      unsigned                ip_summed;
+-      struct net_device_stats stats;
+-      struct list_head        list;
+-      struct net_device       *dev;
+-};
+-
+-/*
+- * I have to hold the rtnl_lock during device delete.
+- * So I use the rtnl_lock to protect my list manipulations
+- * as well.  Crude but simple.
+- */
+-static LIST_HEAD(etun_list);
+-
+-/*
+- * The higher levels take care of making this non-reentrant (it's
+- * called with bh's disabled).
+- */
+-static int etun_xmit(struct sk_buff *skb, struct net_device *tx_dev)
+-{
+-      struct etun_info *tx_info = tx_dev->priv;
+-      struct net_device *rx_dev = tx_info->rx_dev;
+-      struct etun_info *rx_info = rx_dev->priv;
+-
+-      tx_info->stats.tx_packets++;
+-      tx_info->stats.tx_bytes += skb->len;
+-
+-      /* Drop the skb state that was needed to get here */
+-      skb_orphan(skb);
+-      if (skb->dst)
+-              skb->dst = dst_pop(skb->dst);   /* Allow for smart routing */
+-
+-      /* Switch to the receiving device */
+-      skb->pkt_type = PACKET_HOST;
+-      skb->protocol = eth_type_trans(skb, rx_dev);
+-      skb->dev = rx_dev;
+-      skb->ip_summed = CHECKSUM_NONE;
+-
+-      /* If both halves agree no checksum is needed */
+-      if (tx_dev->features & NETIF_F_NO_CSUM)
+-              skb->ip_summed = rx_info->ip_summed;
+-
+-      rx_dev->last_rx = jiffies;
+-      rx_info->stats.rx_packets++;
+-      rx_info->stats.rx_bytes += skb->len;
+-      netif_rx(skb);
+-
+-      return 0;
+-}
+-
+-static struct net_device_stats *etun_get_stats(struct net_device *dev)
+-{
+-      struct etun_info *info = dev->priv;
+-      return &info->stats;
+-}
+-
+-/* ethtool interface */
+-static int etun_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+-{
+-      cmd->supported          = 0;
+-      cmd->advertising        = 0;
+-      cmd->speed              = SPEED_10000; /* Memory is fast! */
+-      cmd->duplex             = DUPLEX_FULL;
+-      cmd->port               = PORT_TP;
+-      cmd->phy_address        = 0;
+-      cmd->transceiver        = XCVR_INTERNAL;
+-      cmd->autoneg            = AUTONEG_DISABLE;
+-      cmd->maxtxpkt           = 0;
+-      cmd->maxrxpkt           = 0;
+-      return 0;
+-}
+-
+-static void etun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+-{
+-      strcpy(info->driver, DRV_NAME);
+-      strcpy(info->version, DRV_VERSION);
+-      strcpy(info->fw_version, "N/A");
+-}
+-
+-static void etun_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
+-{
+-      switch(stringset) {
+-      case ETH_SS_STATS:
+-              memcpy(buf, &ethtool_stats_keys, sizeof(ethtool_stats_keys));
+-              break;
+-      case ETH_SS_TEST:
+-      default:
+-              break;
+-      }
+-}
+-
+-static int etun_get_stats_count(struct net_device *dev)
+-{
+-      return ETUN_NUM_STATS;
+-}
+-
+-static void etun_get_ethtool_stats(struct net_device *dev,
+-      struct ethtool_stats *stats, u64 *data)
+-{
+-      struct etun_info *info = dev->priv;
+-
+-      data[0] = info->rx_dev->ifindex;
+-}
+-
+-static u32 etun_get_rx_csum(struct net_device *dev)
+-{
+-      struct etun_info *info = dev->priv;
+-      return info->ip_summed == CHECKSUM_UNNECESSARY;
+-}
+-
+-static int etun_set_rx_csum(struct net_device *dev, u32 data)
+-{
+-      struct etun_info *info = dev->priv;
+-
+-      info->ip_summed = data ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
+-
+-      return 0;
+-}
+-
+-static u32 etun_get_tx_csum(struct net_device *dev)
+-{
+-      return (dev->features & NETIF_F_NO_CSUM) != 0;
+-}
+-
+-static int etun_set_tx_csum(struct net_device *dev, u32 data)
+-{
+-      dev->features &= ~NETIF_F_NO_CSUM;
+-      if (data)
+-              dev->features |= NETIF_F_NO_CSUM;
+-
+-      return 0;
+-}
+-
+-static struct ethtool_ops etun_ethtool_ops = {
+-      .get_settings           = etun_get_settings,
+-      .get_drvinfo            = etun_get_drvinfo,
+-      .get_link               = ethtool_op_get_link,
+-      .get_rx_csum            = etun_get_rx_csum,
+-      .set_rx_csum            = etun_set_rx_csum,
+-      .get_tx_csum            = etun_get_tx_csum,
+-      .set_tx_csum            = etun_set_tx_csum,
+-      .get_sg                 = ethtool_op_get_sg,
+-      .set_sg                 = ethtool_op_set_sg,
+-#if 0 /* Does just setting the bit successfuly emulate tso? */
+-      .get_tso                = ethtool_op_get_tso,
+-      .set_tso                = ethtool_op_set_tso,
+-#endif
+-      .get_strings            = etun_get_strings,
+-      .get_stats_count        = etun_get_stats_count,
+-      .get_ethtool_stats      = etun_get_ethtool_stats,
+-      .get_perm_addr          = ethtool_op_get_perm_addr,
+-};
+-
+-static int etun_open(struct net_device *tx_dev)
+-{
+-      struct etun_info *tx_info = tx_dev->priv;
+-      struct net_device *rx_dev = tx_info->rx_dev;
+-      /* If we attempt to bring up etun in the small window before
+-       * it is connected to it's partner error.
+-       */
+-      if (!rx_dev)
+-              return -ENOTCONN;
+-      if (rx_dev->flags & IFF_UP) {
+-              netif_carrier_on(tx_dev);
+-              netif_carrier_on(rx_dev);
+-      }
+-      netif_start_queue(tx_dev);
+-      return 0;
+-}
+-
+-static int etun_stop(struct net_device *tx_dev)
+-{
+-      struct etun_info *tx_info = tx_dev->priv;
+-      struct net_device *rx_dev = tx_info->rx_dev;
+-      netif_stop_queue(tx_dev);
+-      if (netif_carrier_ok(tx_dev)) {
+-              netif_carrier_off(tx_dev);
+-              netif_carrier_off(rx_dev);
+-      }
+-      return 0;
+-}
+-
+-static int etun_change_mtu(struct net_device *dev, int new_mtu)
+-{
+-      /* Don't allow ridiculously small mtus */
+-      if (new_mtu < (ETH_ZLEN - ETH_HLEN))
+-              return -EINVAL;
+-      dev->mtu = new_mtu;
+-      return 0;
+-}
+-
+-static void etun_set_multicast_list(struct net_device *dev)
+-{
+-      /* Nothing sane I can do here */
+-      return;
+-}
+-
+-static int etun_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+-{
+-      return -EOPNOTSUPP;
+-}
+-
+-/* Only allow letters and numbers in an etun device name */
+-static int is_valid_name(const char *name)
+-{
+-      const char *ptr;
+-      for (ptr = name; *ptr; ptr++) {
+-              if (!isalnum(*ptr))
+-                      return 0;
+-      }
+-      return 1;
+-}
+-
+-static struct net_device *etun_alloc(struct net *net, const char *name)
+-{
+-      struct net_device *dev;
+-      struct etun_info *info;
+-      int err;
+-
+-      if (!name || !is_valid_name(name))
+-              return ERR_PTR(-EINVAL);
+-
+-      dev = alloc_netdev(sizeof(struct etun_info), name, ether_setup);
+-      if (!dev)
+-              return ERR_PTR(-ENOMEM);
+-
+-      info = dev->priv;
+-      info->dev = dev;
+-      dev->nd_net = net;
+-
+-      random_ether_addr(dev->dev_addr);
+-      dev->tx_queue_len       = 0; /* A queue is silly for a loopback device */
+-      dev->hard_start_xmit    = etun_xmit;
+-      dev->get_stats          = etun_get_stats;
+-      dev->open               = etun_open;
+-      dev->stop               = etun_stop;
+-      dev->set_multicast_list = etun_set_multicast_list;
+-      dev->do_ioctl           = etun_ioctl;
+-      dev->features           = NETIF_F_FRAGLIST
+-                                | NETIF_F_HIGHDMA
+-                                | NETIF_F_LLTX;
+-      dev->flags              = IFF_BROADCAST | IFF_MULTICAST |IFF_PROMISC;
+-      dev->ethtool_ops        = &etun_ethtool_ops;
+-      dev->destructor         = free_netdev;
+-      dev->change_mtu         = etun_change_mtu;
+-      err = register_netdev(dev);
+-      if (err) {
+-              free_netdev(dev);
+-              dev = ERR_PTR(err);
+-              goto out;
+-      }
+-      netif_carrier_off(dev);
+-out:
+-      return dev;
+-}
+-
+-static int etun_alloc_pair(struct net *net, const char *name0, const char *name1)
+-{
+-      struct net_device *dev0, *dev1;
+-      struct etun_info *info0, *info1;
+-
+-      dev0 = etun_alloc(net, name0);
+-      if (IS_ERR(dev0)) {
+-              return PTR_ERR(dev0);
+-      }
+-      info0 = dev0->priv;
+-
+-      dev1 = etun_alloc(net, name1);
+-      if (IS_ERR(dev1)) {
+-              unregister_netdev(dev0);
+-              return PTR_ERR(dev1);
+-      }
+-      info1 = dev1->priv;
+-
+-      dev_hold(dev0);
+-      dev_hold(dev1);
+-      info0->rx_dev = dev1;
+-      info1->rx_dev = dev0;
+-
+-      /* Only place one member of the pair on the list
+-       * so I don't confuse list_for_each_entry_safe,
+-       * by deleting two list entries at once.
+-       */
+-      rtnl_lock();
+-      list_add(&info0->list, &etun_list);
+-      INIT_LIST_HEAD(&info1->list);
+-      rtnl_unlock();
+-
+-      return 0;
+-}
+-
+-static int etun_unregister_pair(struct net_device *dev0)
+-{
+-      struct etun_info *info0, *info1;
+-      struct net_device *dev1;
+-
+-      ASSERT_RTNL();
+-
+-      if (!dev0)
+-              return -ENODEV;
+-
+-      /* Ensure my network devices are not passing packets */
+-      dev_close(dev0);
+-      info0 = dev0->priv;
+-      dev1  = info0->rx_dev;
+-      info1 = dev1->priv;
+-      dev_close(dev1);
+-
+-      /* Drop the cross device references */
+-      dev_put(dev0);
+-      dev_put(dev1);
+-
+-      /* Remove from the etun list */
+-      if (!list_empty(&info0->list))
+-              list_del_init(&info0->list);
+-      if (!list_empty(&info1->list))
+-              list_del_init(&info1->list);
+-
+-      unregister_netdevice(dev0);
+-      unregister_netdevice(dev1);
+-      return 0;
+-}
+-
+-static int etun_noget(char *buffer, struct kernel_param *kp)
+-{
+-      return 0;
+-}
+-
+-static int etun_newif(const char *val, struct kernel_param *kp)
+-{
+-      char name0[IFNAMSIZ], name1[IFNAMSIZ];
+-      const char *mid;
+-      int len, len0, len1;
+-      if (!capable(CAP_NET_ADMIN))
+-              return -EPERM;
+-
+-      /* Avoid frustration by removing trailing whitespace */
+-      len = strlen(val);
+-      while (isspace(val[len - 1]))
+-              len--;
+-
+-      /* Split the string into 2 names */
+-      mid = memchr(val, ',', len);
+-      if (!mid)
+-              return -EINVAL;
+-
+-      /* Get the first device name */
+-      len0 = mid - val;
+-      if (len0 > sizeof(name0) - 1)
+-              len = sizeof(name0) - 1;
+-      strncpy(name0, val, len0);
+-      name0[len0] = '\0';
+-
+-      /* And the second device name */
+-      len1 = len - (len0 + 1);
+-      if (len1 > sizeof(name1) - 1)
+-              len1 = sizeof(name1) - 1;
+-      strncpy(name1, mid + 1, len1);
+-      name1[len1] = '\0';
+-
+-      return etun_alloc_pair(current->nsproxy->net_ns, name0, name1);
+-}
+-
+-static int etun_delif(const char *val, struct kernel_param *kp)
+-{
+-      char name[IFNAMSIZ];
+-      int len;
+-      struct net_device *dev;
+-      int err;
+-      if (!capable(CAP_NET_ADMIN))
+-              return -EPERM;
+-
+-      /* Avoid frustration by removing trailing whitespace */
+-      len = strlen(val);
+-      while (isspace(val[len - 1]))
+-              len--;
+-
+-      /* Get the device name */
+-      if (len > sizeof(name) - 1)
+-              return -EINVAL;
+-      strncpy(name, val, len);
+-      name[len] = '\0';
+-
+-      /* Double check I don't have strange characters in my device name */
+-      if (!is_valid_name(name))
+-              return -EINVAL;
+-
+-      rtnl_lock();
+-      err = -ENODEV;
+-      dev = __dev_get_by_name(current->nsproxy->net_ns, name);
+-      err = etun_unregister_pair(dev);
+-      rtnl_unlock();
+-      return err;
+-}
+-
+-static int __init etun_init(void)
+-{
+-      printk(KERN_INFO "etun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
+-      printk(KERN_INFO "etun: %s\n", DRV_COPYRIGHT);
+-
+-      return 0;
+-}
+-
+-static void etun_cleanup(void)
+-{
+-      struct etun_info *info, *tmp;
+-      rtnl_lock();
+-      list_for_each_entry_safe(info, tmp, &etun_list, list) {
+-              etun_unregister_pair(info->dev);
+-      }
+-      rtnl_unlock();
+-}
+-
+-module_param_call(newif, etun_newif, etun_noget, NULL, S_IWUSR);
+-module_param_call(delif, etun_delif, etun_noget, NULL, S_IWUSR);
+-module_init(etun_init);
+-module_exit(etun_cleanup);
+-MODULE_DESCRIPTION(DRV_DESCRIPTION);
+-MODULE_AUTHOR("Eric Biederman <ebiederm@xmission.com>");
+-MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/drivers/net/fealnx.c linux-2.6.22-570/drivers/net/fealnx.c
+--- linux-2.6.22-590/drivers/net/fealnx.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/fealnx.c      2007-07-08 19:32:17.000000000 -0400
+@@ -1727,8 +1727,8 @@
+                               /* Call copy + cksum if available. */
  
--      lpfc_remove_device(phba);
-+      fc_remove_host(shost);
-+      scsi_remove_host(shost);
-+
-+      /*
-+       * Bring down the SLI Layer. This step disable all interrupts,
-+       * clears the rings, discards all mailbox commands, and resets
-+       * the HBA.
-+       */
-+      lpfc_sli_hba_down(phba);
-+      lpfc_sli_brdrestart(phba);
-+
-+      lpfc_stop_phba_timers(phba);
-+      spin_lock_irq(&phba->hbalock);
-+      list_del_init(&vport->listentry);
-+      spin_unlock_irq(&phba->hbalock);
-+
-+
-+      lpfc_debugfs_terminate(vport);
-+      lpfc_cleanup(vport);
-+
-+      kthread_stop(phba->worker_thread);
-+
-+      /* Release the irq reservation */
-+      free_irq(phba->pcidev->irq, phba);
-+      pci_disable_msi(phba->pcidev);
+ #if ! defined(__alpha__)
+-                              skb_copy_to_linear_data(skb,
+-                                      np->cur_rx->skbuff->data, pkt_len);
++                              eth_copy_and_sum(skb,
++                                      np->cur_rx->skbuff->data, pkt_len, 0);
+                               skb_put(skb, pkt_len);
+ #else
+                               memcpy(skb_put(skb, pkt_len),
+diff -Nurb linux-2.6.22-590/drivers/net/fec.c linux-2.6.22-570/drivers/net/fec.c
+--- linux-2.6.22-590/drivers/net/fec.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/fec.c 2007-07-08 19:32:17.000000000 -0400
+@@ -648,7 +648,7 @@
+               fep->stats.rx_dropped++;
+       } else {
+               skb_put(skb,pkt_len-4); /* Make room */
+-              skb_copy_to_linear_data(skb, data, pkt_len-4);
++              eth_copy_and_sum(skb, data, pkt_len-4, 0);
+               skb->protocol=eth_type_trans(skb,dev);
+               netif_rx(skb);
+       }
+diff -Nurb linux-2.6.22-590/drivers/net/hamachi.c linux-2.6.22-570/drivers/net/hamachi.c
+--- linux-2.6.22-590/drivers/net/hamachi.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/hamachi.c     2007-07-08 19:32:17.000000000 -0400
+@@ -1575,8 +1575,8 @@
+                                                           PCI_DMA_FROMDEVICE);
+                               /* Call copy + cksum if available. */
+ #if 1 || USE_IP_COPYSUM
+-                              skb_copy_to_linear_data(skb,
+-                                      hmp->rx_skbuff[entry]->data, pkt_len);
++                              eth_copy_and_sum(skb,
++                                      hmp->rx_skbuff[entry]->data, pkt_len, 0);
+                               skb_put(skb, pkt_len);
+ #else
+                               memcpy(skb_put(skb, pkt_len), hmp->rx_ring_dma
+diff -Nurb linux-2.6.22-590/drivers/net/hamradio/baycom_epp.c linux-2.6.22-570/drivers/net/hamradio/baycom_epp.c
+--- linux-2.6.22-590/drivers/net/hamradio/baycom_epp.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/hamradio/baycom_epp.c 2007-07-08 19:32:17.000000000 -0400
+@@ -320,7 +320,7 @@
+       sprintf(portarg, "%ld", bc->pdev->port->base);
+       printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n", bc_drvname, eppconfig_path, portarg, modearg);
  
-       pci_set_drvdata(pdev, NULL);
-+      scsi_host_put(shost);
-+
-+      /*
-+       * Call scsi_free before mem_free since scsi bufs are released to their
-+       * corresponding pools here.
-+       */
-+      lpfc_scsi_free(phba);
-+      lpfc_mem_free(phba);
-+
-+      dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(), phba->hbqslimp.virt,
-+                        phba->hbqslimp.phys);
-+
-+      /* Free resources associated with SLI2 interface */
-+      dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE,
-+                        phba->slim2p, phba->slim2p_mapping);
-+
-+      /* unmap adapter SLIM and Control Registers */
-+      iounmap(phba->ctrl_regs_memmap_p);
-+      iounmap(phba->slim_memmap_p);
-+
-+      idr_remove(&lpfc_hba_index, phba->brd_no);
-+
-+      kfree(phba);
-+
-+      pci_release_regions(pdev);
-+      pci_disable_device(pdev);
+-      return call_usermodehelper(eppconfig_path, argv, envp, UMH_WAIT_PROC);
++      return call_usermodehelper(eppconfig_path, argv, envp, 1);
  }
  
- /**
-@@ -1822,10 +2110,13 @@
-       pci_set_master(pdev);
-       /* Re-establishing Link */
--      spin_lock_irq(phba->host->host_lock);
--      phba->fc_flag |= FC_ESTABLISH_LINK;
-+      spin_lock_irq(host->host_lock);
-+      phba->pport->fc_flag |= FC_ESTABLISH_LINK;
-+      spin_unlock_irq(host->host_lock);
-+
-+      spin_lock_irq(&phba->hbalock);
-       psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
-       /* Take device offline; this will perform cleanup */
-@@ -1948,11 +2239,15 @@
+ /* ---------------------------------------------------------------------- */
+diff -Nurb linux-2.6.22-590/drivers/net/hamradio/bpqether.c linux-2.6.22-570/drivers/net/hamradio/bpqether.c
+--- linux-2.6.22-590/drivers/net/hamradio/bpqether.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/hamradio/bpqether.c   2007-07-08 19:32:17.000000000 -0400
+@@ -83,7 +83,6 @@
  
-       lpfc_transport_template =
-                               fc_attach_transport(&lpfc_transport_functions);
--      if (!lpfc_transport_template)
-+      lpfc_vport_transport_template =
-+                      fc_attach_transport(&lpfc_vport_transport_functions);
-+      if (!lpfc_transport_template || !lpfc_vport_transport_template)
-               return -ENOMEM;
-       error = pci_register_driver(&lpfc_driver);
--      if (error)
-+      if (error) {
-               fc_release_transport(lpfc_transport_template);
-+              fc_release_transport(lpfc_vport_transport_template);
-+      }
+ #include <net/ip.h>
+ #include <net/arp.h>
+-#include <net/net_namespace.h>
  
-       return error;
- }
-@@ -1962,6 +2257,7 @@
- {
-       pci_unregister_driver(&lpfc_driver);
-       fc_release_transport(lpfc_transport_template);
-+      fc_release_transport(lpfc_vport_transport_template);
- }
+ #include <linux/bpqether.h>
  
- module_init(lpfc_init);
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_logmsg.h linux-2.6.22-590/drivers/scsi/lpfc/lpfc_logmsg.h
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_logmsg.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_logmsg.h   2008-01-02 13:56:37.000000000 -0500
-@@ -30,6 +30,7 @@
- #define LOG_SLI                       0x800   /* SLI events */
- #define LOG_FCP_ERROR                 0x1000  /* log errors, not underruns */
- #define LOG_LIBDFC                    0x2000  /* Libdfc events */
-+#define LOG_VPORT                     0x4000  /* NPIV events */
- #define LOG_ALL_MSG                   0xffff  /* LOG all messages */
+@@ -173,9 +172,6 @@
+       struct ethhdr *eth;
+       struct bpqdev *bpq;
  
- #define lpfc_printf_log(phba, level, mask, fmt, arg...) \
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_mbox.c linux-2.6.22-590/drivers/scsi/lpfc/lpfc_mbox.c
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_mbox.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_mbox.c     2008-01-02 13:56:37.000000000 -0500
-@@ -82,6 +82,22 @@
- }
+-      if (dev->nd_net != &init_net)
+-              goto drop;
+-
+       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+               return NET_RX_DROP;
  
- /**********************************************/
-+/*  lpfc_heart_beat  Issue a HEART_BEAT       */
-+/*                mailbox command             */
-+/**********************************************/
-+void
-+lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
-+{
-+      MAILBOX_t *mb;
-+
-+      mb = &pmb->mb;
-+      memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
-+      mb->mbxCommand = MBX_HEARTBEAT;
-+      mb->mbxOwner = OWN_HOST;
-+      return;
-+}
-+
-+/**********************************************/
- /*  lpfc_read_la  Issue a READ LA             */
- /*                mailbox command             */
- /**********************************************/
-@@ -134,6 +150,7 @@
- void
- lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+@@ -563,9 +559,6 @@
  {
-+      struct lpfc_vport  *vport = phba->pport;
-       MAILBOX_t *mb = &pmb->mb;
-       memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
-@@ -147,7 +164,7 @@
-               mb->un.varCfgLnk.cr_count = phba->cfg_cr_count;
-       }
+       struct net_device *dev = (struct net_device *)ptr;
  
--      mb->un.varCfgLnk.myId = phba->fc_myDID;
-+      mb->un.varCfgLnk.myId = vport->fc_myDID;
-       mb->un.varCfgLnk.edtov = phba->fc_edtov;
-       mb->un.varCfgLnk.arbtov = phba->fc_arbtov;
-       mb->un.varCfgLnk.ratov = phba->fc_ratov;
-@@ -239,7 +256,7 @@
- /*                    mailbox command         */
- /**********************************************/
- int
--lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
-+lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi)
- {
-       struct lpfc_dmabuf *mp;
-       MAILBOX_t *mb;
-@@ -270,6 +287,7 @@
-       mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
-       mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys);
-       mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys);
-+      mb->un.varRdSparm.vpi = vpi;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       if (!dev_is_ethdev(dev))
+               return NOTIFY_DONE;
  
-       /* save address for completion */
-       pmb->context1 = mp;
-@@ -282,7 +300,8 @@
- /*                  mailbox command         */
- /********************************************/
- void
--lpfc_unreg_did(struct lpfc_hba * phba, uint32_t did, LPFC_MBOXQ_t * pmb)
-+lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did,
-+             LPFC_MBOXQ_t * pmb)
+@@ -601,7 +594,7 @@
+ static int __init bpq_init_driver(void)
  {
-       MAILBOX_t *mb;
-@@ -290,6 +309,7 @@
-       memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+ #ifdef CONFIG_PROC_FS
+-      if (!proc_net_fops_create(&init_net, "bpqether", S_IRUGO, &bpq_info_fops)) {
++      if (!proc_net_fops_create("bpqether", S_IRUGO, &bpq_info_fops)) {
+               printk(KERN_ERR
+                       "bpq: cannot create /proc/net/bpqether entry.\n");
+               return -ENOENT;
+@@ -625,7 +618,7 @@
  
-       mb->un.varUnregDID.did = did;
-+      mb->un.varUnregDID.vpi = vpi;
+       unregister_netdevice_notifier(&bpq_dev_notifier);
  
-       mb->mbxCommand = MBX_UNREG_D_ID;
-       mb->mbxOwner = OWN_HOST;
-@@ -335,19 +355,17 @@
- /*                  mailbox command         */
- /********************************************/
- int
--lpfc_reg_login(struct lpfc_hba * phba,
--             uint32_t did, uint8_t * param, LPFC_MBOXQ_t * pmb, uint32_t flag)
-+lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
-+             uint8_t *param, LPFC_MBOXQ_t *pmb, uint32_t flag)
- {
-+      MAILBOX_t *mb = &pmb->mb;
-       uint8_t *sparam;
-       struct lpfc_dmabuf *mp;
--      MAILBOX_t *mb;
--      struct lpfc_sli *psli;
+-      proc_net_remove(&init_net, "bpqether");
++      proc_net_remove("bpqether");
  
--      psli = &phba->sli;
--      mb = &pmb->mb;
-       memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+       rtnl_lock();
+       while (!list_empty(&bpq_devices)) {
+diff -Nurb linux-2.6.22-590/drivers/net/hamradio/scc.c linux-2.6.22-570/drivers/net/hamradio/scc.c
+--- linux-2.6.22-590/drivers/net/hamradio/scc.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/hamradio/scc.c        2007-07-08 19:32:17.000000000 -0400
+@@ -174,7 +174,6 @@
+ #include <linux/seq_file.h>
+ #include <linux/bitops.h>
  
-       mb->un.varRegLogin.rpi = 0;
-+      mb->un.varRegLogin.vpi = vpi;
-       mb->un.varRegLogin.did = did;
-       mb->un.varWords[30] = flag;     /* Set flag to issue action on cmpl */
+-#include <net/net_namespace.h>
+ #include <net/ax25.h>
  
-@@ -359,12 +377,10 @@
-               kfree(mp);
-               mb->mbxCommand = MBX_REG_LOGIN64;
-               /* REG_LOGIN: no buffers */
--              lpfc_printf_log(phba,
--                             KERN_WARNING,
--                             LOG_MBOX,
--                             "%d:0302 REG_LOGIN: no buffers Data x%x x%x\n",
--                             phba->brd_no,
--                             (uint32_t) did, (uint32_t) flag);
-+              lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
-+                              "%d (%d):0302 REG_LOGIN: no buffers, DID x%x, "
-+                              "flag x%x\n",
-+                              phba->brd_no, vpi, did, flag);
-               return (1);
+ #include <asm/irq.h>
+@@ -2115,7 +2114,7 @@
        }
-       INIT_LIST_HEAD(&mp->list);
-@@ -389,7 +405,8 @@
- /*                    mailbox command         */
- /**********************************************/
- void
--lpfc_unreg_login(struct lpfc_hba * phba, uint32_t rpi, LPFC_MBOXQ_t * pmb)
-+lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi,
-+               LPFC_MBOXQ_t * pmb)
- {
-       MAILBOX_t *mb;
+       rtnl_unlock();
  
-@@ -398,12 +415,52 @@
+-      proc_net_fops_create(&init_net, "z8530drv", 0, &scc_net_seq_fops);
++      proc_net_fops_create("z8530drv", 0, &scc_net_seq_fops);
  
-       mb->un.varUnregLogin.rpi = (uint16_t) rpi;
-       mb->un.varUnregLogin.rsvd1 = 0;
-+      mb->un.varUnregLogin.vpi = vpi;
+       return 0;
+ }
+@@ -2170,7 +2169,7 @@
+       if (Vector_Latch)
+               release_region(Vector_Latch, 1);
  
-       mb->mbxCommand = MBX_UNREG_LOGIN;
-       mb->mbxOwner = OWN_HOST;
-       return;
+-      proc_net_remove(&init_net, "z8530drv");
++      proc_net_remove("z8530drv");
  }
  
-+/**************************************************/
-+/*  lpfc_reg_vpi   Issue a REG_VPI                */
-+/*                    mailbox command             */
-+/**************************************************/
-+void
-+lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid,
-+           LPFC_MBOXQ_t *pmb)
-+{
-+      MAILBOX_t *mb = &pmb->mb;
-+
-+      memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
-+
-+      mb->un.varRegVpi.vpi = vpi;
-+      mb->un.varRegVpi.sid = sid;
-+
-+      mb->mbxCommand = MBX_REG_VPI;
-+      mb->mbxOwner = OWN_HOST;
-+      return;
-+
-+}
-+
-+/**************************************************/
-+/*  lpfc_unreg_vpi   Issue a UNREG_VNPI           */
-+/*                    mailbox command             */
-+/**************************************************/
-+void
-+lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb)
-+{
-+      MAILBOX_t *mb = &pmb->mb;
-+      memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
-+
-+      mb->un.varUnregVpi.vpi = vpi;
-+
-+      mb->mbxCommand = MBX_UNREG_VPI;
-+      mb->mbxOwner = OWN_HOST;
-+      return;
-+
-+}
-+
- static void
- lpfc_config_pcb_setup(struct lpfc_hba * phba)
- {
-@@ -412,14 +469,18 @@
-       PCB_t *pcbp = &phba->slim2p->pcb;
-       dma_addr_t pdma_addr;
-       uint32_t offset;
--      uint32_t iocbCnt;
-+      uint32_t iocbCnt = 0;
-       int i;
+ MODULE_AUTHOR("Joerg Reuter <jreuter@yaina.de>");
+diff -Nurb linux-2.6.22-590/drivers/net/hamradio/yam.c linux-2.6.22-570/drivers/net/hamradio/yam.c
+--- linux-2.6.22-590/drivers/net/hamradio/yam.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/hamradio/yam.c        2007-07-08 19:32:17.000000000 -0400
+@@ -61,7 +61,6 @@
+ #include <linux/etherdevice.h>
+ #include <linux/skbuff.h>
+ #include <net/ax25.h>
+-#include <net/net_namespace.h>
  
-       pcbp->maxRing = (psli->num_rings - 1);
+ #include <linux/kernel.h>
+ #include <linux/proc_fs.h>
+@@ -1143,7 +1142,7 @@
+       yam_timer.expires = jiffies + HZ / 100;
+       add_timer(&yam_timer);
  
--      iocbCnt = 0;
-       for (i = 0; i < psli->num_rings; i++) {
-               pring = &psli->ring[i];
-+
-+              pring->sizeCiocb = phba->sli_rev == 3 ? SLI3_IOCB_CMD_SIZE:
-+                                                      SLI2_IOCB_CMD_SIZE;
-+              pring->sizeRiocb = phba->sli_rev == 3 ? SLI3_IOCB_RSP_SIZE:
-+                                                      SLI2_IOCB_RSP_SIZE;
-               /* A ring MUST have both cmd and rsp entries defined to be
-                  valid */
-               if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) {
-@@ -434,20 +495,18 @@
-                       continue;
-               }
-               /* Command ring setup for ring */
--              pring->cmdringaddr =
--                  (void *)&phba->slim2p->IOCBs[iocbCnt];
-+              pring->cmdringaddr = (void *) &phba->slim2p->IOCBs[iocbCnt];
-               pcbp->rdsc[i].cmdEntries = pring->numCiocb;
+-      proc_net_fops_create(&init_net, "yam", S_IRUGO, &yam_info_fops);
++      proc_net_fops_create("yam", S_IRUGO, &yam_info_fops);
+       return 0;
+  error:
+       while (--i >= 0) {
+@@ -1175,7 +1174,7 @@
+               kfree(p);
+       }
  
--              offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
--                       (uint8_t *)phba->slim2p;
-+              offset = (uint8_t *) &phba->slim2p->IOCBs[iocbCnt] -
-+                       (uint8_t *) phba->slim2p;
-               pdma_addr = phba->slim2p_mapping + offset;
-               pcbp->rdsc[i].cmdAddrHigh = putPaddrHigh(pdma_addr);
-               pcbp->rdsc[i].cmdAddrLow = putPaddrLow(pdma_addr);
-               iocbCnt += pring->numCiocb;
+-      proc_net_remove(&init_net, "yam");
++      proc_net_remove("yam");
+ }
  
-               /* Response ring setup for ring */
--              pring->rspringaddr =
--                  (void *)&phba->slim2p->IOCBs[iocbCnt];
-+              pring->rspringaddr = (void *) &phba->slim2p->IOCBs[iocbCnt];
+ /* --------------------------------------------------------------------- */
+diff -Nurb linux-2.6.22-590/drivers/net/ibmveth.c linux-2.6.22-570/drivers/net/ibmveth.c
+--- linux-2.6.22-590/drivers/net/ibmveth.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/ibmveth.c     2007-07-08 19:32:17.000000000 -0400
+@@ -47,7 +47,6 @@
+ #include <linux/mm.h>
+ #include <linux/ethtool.h>
+ #include <linux/proc_fs.h>
+-#include <net/net_namespace.h>
+ #include <asm/semaphore.h>
+ #include <asm/hvcall.h>
+ #include <asm/atomic.h>
+@@ -98,7 +97,7 @@
+ static struct kobj_type ktype_veth_pool;
  
-               pcbp->rdsc[i].rspEntries = pring->numRiocb;
-               offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
-@@ -462,16 +521,108 @@
- void
- lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
- {
--      MAILBOX_t *mb;
--
--      mb = &pmb->mb;
-+      MAILBOX_t *mb = &pmb->mb;
-       memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
-       mb->un.varRdRev.cv = 1;
-+      mb->un.varRdRev.v3req = 1; /* Request SLI3 info */
-       mb->mbxCommand = MBX_READ_REV;
-       mb->mbxOwner = OWN_HOST;
-       return;
- }
+ #ifdef CONFIG_PROC_FS
+-#define IBMVETH_PROC_DIR "ibmveth"
++#define IBMVETH_PROC_DIR "net/ibmveth"
+ static struct proc_dir_entry *ibmveth_proc_dir;
+ #endif
  
-+static void
-+lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb,
-+                      struct lpfc_hbq_init  *hbq_desc)
-+{
-+      hbqmb->profiles.profile2.seqlenbcnt = hbq_desc->seqlenbcnt;
-+      hbqmb->profiles.profile2.maxlen     = hbq_desc->maxlen;
-+      hbqmb->profiles.profile2.seqlenoff  = hbq_desc->seqlenoff;
-+}
-+
-+static void
-+lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb,
-+                      struct lpfc_hbq_init  *hbq_desc)
-+{
-+      hbqmb->profiles.profile3.seqlenbcnt = hbq_desc->seqlenbcnt;
-+      hbqmb->profiles.profile3.maxlen     = hbq_desc->maxlen;
-+      hbqmb->profiles.profile3.cmdcodeoff = hbq_desc->cmdcodeoff;
-+      hbqmb->profiles.profile3.seqlenoff  = hbq_desc->seqlenoff;
-+      memcpy(&hbqmb->profiles.profile3.cmdmatch, hbq_desc->cmdmatch,
-+             sizeof(hbqmb->profiles.profile3.cmdmatch));
-+}
-+
-+static void
-+lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb,
-+                      struct lpfc_hbq_init  *hbq_desc)
-+{
-+      hbqmb->profiles.profile5.seqlenbcnt = hbq_desc->seqlenbcnt;
-+      hbqmb->profiles.profile5.maxlen     = hbq_desc->maxlen;
-+      hbqmb->profiles.profile5.cmdcodeoff = hbq_desc->cmdcodeoff;
-+      hbqmb->profiles.profile5.seqlenoff  = hbq_desc->seqlenoff;
-+      memcpy(&hbqmb->profiles.profile5.cmdmatch, hbq_desc->cmdmatch,
-+             sizeof(hbqmb->profiles.profile5.cmdmatch));
-+}
-+
-+void
-+lpfc_config_hbq(struct lpfc_hba *phba, struct lpfc_hbq_init *hbq_desc,
-+              uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb)
-+{
-+      int i;
-+      MAILBOX_t *mb = &pmb->mb;
-+      struct config_hbq_var *hbqmb = &mb->un.varCfgHbq;
-+
-+      memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
-+      hbqmb->entry_count = hbq_desc->entry_count;   /* # entries in HBQ */
-+      hbqmb->recvNotify = hbq_desc->rn;             /* Receive
-+                                                     * Notification */
-+      hbqmb->numMask    = hbq_desc->mask_count;     /* # R_CTL/TYPE masks
-+                                                     * # in words 0-19 */
-+      hbqmb->profile    = hbq_desc->profile;        /* Selection profile:
-+                                                     * 0 = all,
-+                                                     * 7 = logentry */
-+      hbqmb->ringMask   = hbq_desc->ring_mask;      /* Binds HBQ to a ring
-+                                                     * e.g. Ring0=b0001,
-+                                                     * ring2=b0100 */
-+      hbqmb->headerLen  = hbq_desc->headerLen;      /* 0 if not profile 4
-+                                                     * or 5 */
-+      hbqmb->logEntry   = hbq_desc->logEntry;       /* Set to 1 if this
-+                                                     * HBQ will be used
-+                                                     * for LogEntry
-+                                                     * buffers */
-+      hbqmb->hbqaddrLow = putPaddrLow(phba->hbqslimp.phys) +
-+              hbq_entry_index * sizeof(struct lpfc_hbq_entry);
-+      hbqmb->hbqaddrHigh = putPaddrHigh(phba->hbqslimp.phys);
-+
-+      mb->mbxCommand = MBX_CONFIG_HBQ;
-+      mb->mbxOwner = OWN_HOST;
-+
-+                              /* Copy info for profiles 2,3,5. Other
-+                               * profiles this area is reserved
-+                               */
-+      if (hbq_desc->profile == 2)
-+              lpfc_build_hbq_profile2(hbqmb, hbq_desc);
-+      else if (hbq_desc->profile == 3)
-+              lpfc_build_hbq_profile3(hbqmb, hbq_desc);
-+      else if (hbq_desc->profile == 5)
-+              lpfc_build_hbq_profile5(hbqmb, hbq_desc);
-+
-+      /* Return if no rctl / type masks for this HBQ */
-+      if (!hbq_desc->mask_count)
-+              return;
-+
-+      /* Otherwise we setup specific rctl / type masks for this HBQ */
-+      for (i = 0; i < hbq_desc->mask_count; i++) {
-+              hbqmb->hbqMasks[i].tmatch = hbq_desc->hbqMasks[i].tmatch;
-+              hbqmb->hbqMasks[i].tmask  = hbq_desc->hbqMasks[i].tmask;
-+              hbqmb->hbqMasks[i].rctlmatch = hbq_desc->hbqMasks[i].rctlmatch;
-+              hbqmb->hbqMasks[i].rctlmask  = hbq_desc->hbqMasks[i].rctlmask;
-+      }
-+
-+      return;
-+}
-+
-+
-+
- void
- lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
+@@ -1094,7 +1093,7 @@
+ #ifdef CONFIG_PROC_FS
+ static void ibmveth_proc_register_driver(void)
  {
-@@ -514,15 +665,16 @@
- }
+-      ibmveth_proc_dir = proc_mkdir(IBMVETH_PROC_DIR, init_net.proc_net);
++      ibmveth_proc_dir = proc_mkdir(IBMVETH_PROC_DIR, NULL);
+       if (ibmveth_proc_dir) {
+               SET_MODULE_OWNER(ibmveth_proc_dir);
+       }
+@@ -1102,7 +1101,7 @@
  
- void
--lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
-+lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ static void ibmveth_proc_unregister_driver(void)
  {
-+      MAILBOX_t __iomem *mb_slim = (MAILBOX_t __iomem *) phba->MBslimaddr;
-       MAILBOX_t *mb = &pmb->mb;
-       dma_addr_t pdma_addr;
-       uint32_t bar_low, bar_high;
-       size_t offset;
-       struct lpfc_hgp hgp;
--      void __iomem *to_slim;
-       int i;
-+      uint32_t pgp_offset;
-       memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
-       mb->mbxCommand = MBX_CONFIG_PORT;
-@@ -535,12 +687,29 @@
-       mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr);
-       mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr);
-+      /* If HBA supports SLI=3 ask for it */
-+
-+      if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) {
-+              mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
-+              mb->un.varCfgPort.max_hbq = 1; /* Requesting 2 HBQs */
-+              if (phba->max_vpi && phba->cfg_npiv_enable &&
-+                  phba->vpd.sli3Feat.cmv) {
-+                      mb->un.varCfgPort.max_vpi = phba->max_vpi;
-+                      mb->un.varCfgPort.cmv = 1;
-+                      phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
-+              } else
-+                      mb->un.varCfgPort.max_vpi = phba->max_vpi = 0;
-+      } else
-+              phba->sli_rev = 2;
-+      mb->un.varCfgPort.sli_mode = phba->sli_rev;
-+
-       /* Now setup pcb */
-       phba->slim2p->pcb.type = TYPE_NATIVE_SLI2;
-       phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2;
-       /* Setup Mailbox pointers */
--      phba->slim2p->pcb.mailBoxSize = sizeof(MAILBOX_t);
-+      phba->slim2p->pcb.mailBoxSize = offsetof(MAILBOX_t, us) +
-+              sizeof(struct sli2_desc);
-       offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p;
-       pdma_addr = phba->slim2p_mapping + offset;
-       phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr);
-@@ -568,29 +737,70 @@
-       pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low);
-       pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high);
-+      /*
-+       * Set up HGP - Port Memory
-+       *
-+       * The port expects the host get/put pointers to reside in memory
-+       * following the "non-diagnostic" mode mailbox (32 words, 0x80 bytes)
-+       * area of SLIM.  In SLI-2 mode, there's an additional 16 reserved
-+       * words (0x40 bytes).  This area is not reserved if HBQs are
-+       * configured in SLI-3.
-+       *
-+       * CR0Put    - SLI2(no HBQs) = 0xc0, With HBQs = 0x80
-+       * RR0Get                      0xc4              0x84
-+       * CR1Put                      0xc8              0x88
-+       * RR1Get                      0xcc              0x8c
-+       * CR2Put                      0xd0              0x90
-+       * RR2Get                      0xd4              0x94
-+       * CR3Put                      0xd8              0x98
-+       * RR3Get                      0xdc              0x9c
-+       *
-+       * Reserved                    0xa0-0xbf
-+       *    If HBQs configured:
-+       *                         HBQ 0 Put ptr  0xc0
-+       *                         HBQ 1 Put ptr  0xc4
-+       *                         HBQ 2 Put ptr  0xc8
-+       *                         ......
-+       *                         HBQ(M-1)Put Pointer 0xc0+(M-1)*4
-+       *
-+       */
-+
-+      if (phba->sli_rev == 3) {
-+              phba->host_gp = &mb_slim->us.s3.host[0];
-+              phba->hbq_put = &mb_slim->us.s3.hbq_put[0];
-+      } else {
-+              phba->host_gp = &mb_slim->us.s2.host[0];
-+              phba->hbq_put = NULL;
-+      }
-       /* mask off BAR0's flag bits 0 - 3 */
-       phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) +
--                                      (SLIMOFF*sizeof(uint32_t));
-+              (void __iomem *) phba->host_gp -
-+              (void __iomem *)phba->MBslimaddr;
-       if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64)
-               phba->slim2p->pcb.hgpAddrHigh = bar_high;
-       else
-               phba->slim2p->pcb.hgpAddrHigh = 0;
-       /* write HGP data to SLIM at the required longword offset */
-       memset(&hgp, 0, sizeof(struct lpfc_hgp));
--      to_slim = phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t));
-       for (i=0; i < phba->sli.num_rings; i++) {
--              lpfc_memcpy_to_slim(to_slim, &hgp, sizeof(struct lpfc_hgp));
--              to_slim += sizeof (struct lpfc_hgp);
-+              lpfc_memcpy_to_slim(phba->host_gp + i, &hgp,
-+                                  sizeof(*phba->host_gp));
-       }
+-      remove_proc_entry(IBMVETH_PROC_DIR, init_net.proc_net);
++      remove_proc_entry(IBMVETH_PROC_DIR, NULL);
+ }
  
-       /* Setup Port Group ring pointer */
--      offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
-+      if (phba->sli_rev == 3)
-+              pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s3_pgp.port -
-                (uint8_t *)phba->slim2p;
--      pdma_addr = phba->slim2p_mapping + offset;
-+      else
-+              pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
-+                      (uint8_t *)phba->slim2p;
-+
-+      pdma_addr = phba->slim2p_mapping + pgp_offset;
-       phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr);
-       phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr);
-+      phba->hbq_get = &phba->slim2p->mbx.us.s3_pgp.hbq_get[0];
+ static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos)
+@@ -1338,7 +1337,7 @@
  
-       /* Use callback routine to setp rings in the pcb */
-       lpfc_config_pcb_setup(phba);
-@@ -606,11 +816,7 @@
+ #define ATTR(_name, _mode)      \
+         struct attribute veth_##_name##_attr = {               \
+-        .name = __stringify(_name), .mode = _mode, \
++        .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \
+         };
  
-       /* Swap PCB if needed */
-       lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb,
--                                                              sizeof (PCB_t));
--
--      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
--                      "%d:0405 Service Level Interface (SLI) 2 selected\n",
--                      phba->brd_no);
-+                            sizeof(PCB_t));
- }
+ static ATTR(active, 0644);
+diff -Nurb linux-2.6.22-590/drivers/net/ifb.c linux-2.6.22-570/drivers/net/ifb.c
+--- linux-2.6.22-590/drivers/net/ifb.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/ifb.c 2007-07-08 19:32:17.000000000 -0400
+@@ -33,15 +33,12 @@
+ #include <linux/etherdevice.h>
+ #include <linux/init.h>
+ #include <linux/moduleparam.h>
+-#include <linux/list.h>
+ #include <net/pkt_sched.h>
  
- void
-@@ -644,15 +850,23 @@
-       LPFC_MBOXQ_t *mbq = NULL;
-       struct lpfc_sli *psli = &phba->sli;
+ #define TX_TIMEOUT  (2*HZ)
  
--      list_remove_head((&psli->mboxq), mbq, LPFC_MBOXQ_t,
--                       list);
--      if (mbq) {
-+      list_remove_head((&psli->mboxq), mbq, LPFC_MBOXQ_t, list);
-+      if (mbq)
-               psli->mboxq_cnt--;
--      }
+ #define TX_Q_LIMIT    32
+ struct ifb_private {
+-      struct list_head        list;
+-      struct net_device       *dev;
+       struct net_device_stats stats;
+       struct tasklet_struct   ifb_tasklet;
+       int     tasklet_pending;
+@@ -139,14 +136,13 @@
  
-       return mbq;
  }
  
-+void
-+lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
-+{
-+      /* This function expects to be called from interupt context */
-+      spin_lock(&phba->hbalock);
-+      list_add_tail(&mbq->list, &phba->sli.mboxq_cmpl);
-+      spin_unlock(&phba->hbalock);
-+      return;
-+}
-+
- int
- lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
+-static void ifb_setup(struct net_device *dev)
++static void __init ifb_setup(struct net_device *dev)
  {
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_mem.c linux-2.6.22-590/drivers/scsi/lpfc/lpfc_mem.c
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_mem.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_mem.c      2008-01-02 13:56:37.000000000 -0500
-@@ -1,7 +1,7 @@
- /*******************************************************************
-  * This file is part of the Emulex Linux Device Driver for         *
-  * Fibre Channel Host Bus Adapters.                                *
-- * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
-+ * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
-  * EMULEX and SLI are trademarks of Emulex.                        *
-  * www.emulex.com                                                  *
-  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
-@@ -38,10 +38,13 @@
- #define LPFC_MBUF_POOL_SIZE     64      /* max elements in MBUF safety pool */
- #define LPFC_MEM_POOL_SIZE      64      /* max elem in non-DMA safety pool */
+       /* Initialize the device structure. */
+       dev->get_stats = ifb_get_stats;
+       dev->hard_start_xmit = ifb_xmit;
+       dev->open = &ifb_open;
+       dev->stop = &ifb_close;
+-      dev->destructor = free_netdev;
  
-+
-+
- int
- lpfc_mem_alloc(struct lpfc_hba * phba)
- {
-       struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
-+      int longs;
-       int i;
+       /* Fill in device structure with ethernet-generic values. */
+       ether_setup(dev);
+@@ -201,7 +197,7 @@
+       return stats;
+ }
  
-       phba->lpfc_scsi_dma_buf_pool = pci_pool_create("lpfc_scsi_dma_buf_pool",
-@@ -80,10 +83,27 @@
-       if (!phba->nlp_mem_pool)
-               goto fail_free_mbox_pool;
+-static LIST_HEAD(ifbs);
++static struct net_device **ifbs;
  
-+      phba->lpfc_hbq_pool = pci_pool_create("lpfc_hbq_pool",phba->pcidev,
-+                                            LPFC_BPL_SIZE, 8, 0);
-+      if (!phba->lpfc_hbq_pool)
-+              goto fail_free_nlp_mem_pool;
-+
-+      /* vpi zero is reserved for the physical port so add 1 to max */
-+      longs = ((phba->max_vpi + 1) + BITS_PER_LONG - 1) / BITS_PER_LONG;
-+      phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), GFP_KERNEL);
-+      if (!phba->vpi_bmask)
-+              goto fail_free_hbq_pool;
-+
+ /* Number of ifb devices to be set up by this module. */
+ module_param(numifbs, int, 0);
+@@ -230,41 +226,9 @@
        return 0;
-+ fail_free_hbq_pool:
-+      lpfc_sli_hbqbuf_free_all(phba);
-+ fail_free_nlp_mem_pool:
-+      mempool_destroy(phba->nlp_mem_pool);
-+      phba->nlp_mem_pool = NULL;
-  fail_free_mbox_pool:
-       mempool_destroy(phba->mbox_mem_pool);
-+      phba->mbox_mem_pool = NULL;
-  fail_free_mbuf_pool:
-       while (i--)
-               pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
-@@ -91,8 +111,10 @@
-       kfree(pool->elements);
-  fail_free_lpfc_mbuf_pool:
-       pci_pool_destroy(phba->lpfc_mbuf_pool);
-+      phba->lpfc_mbuf_pool = NULL;
-  fail_free_dma_buf_pool:
-       pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
-+      phba->lpfc_scsi_dma_buf_pool = NULL;
-  fail:
-       return -ENOMEM;
  }
-@@ -106,6 +128,9 @@
-       struct lpfc_dmabuf   *mp;
-       int i;
-+      kfree(phba->vpi_bmask);
-+      lpfc_sli_hbqbuf_free_all(phba);
-+
-       list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) {
-               mp = (struct lpfc_dmabuf *) (mbox->context1);
-               if (mp) {
-@@ -115,6 +140,15 @@
-               list_del(&mbox->list);
-               mempool_free(mbox, phba->mbox_mem_pool);
-       }
-+      list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq_cmpl, list) {
-+              mp = (struct lpfc_dmabuf *) (mbox->context1);
-+              if (mp) {
-+                      lpfc_mbuf_free(phba, mp->virt, mp->phys);
-+                      kfree(mp);
-+              }
-+              list_del(&mbox->list);
-+              mempool_free(mbox, phba->mbox_mem_pool);
-+      }
-       psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-       if (psli->mbox_active) {
-@@ -132,12 +166,20 @@
-               pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
-                                                pool->elements[i].phys);
-       kfree(pool->elements);
-+
-+      pci_pool_destroy(phba->lpfc_hbq_pool);
-       mempool_destroy(phba->nlp_mem_pool);
-       mempool_destroy(phba->mbox_mem_pool);
-       pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
-       pci_pool_destroy(phba->lpfc_mbuf_pool);
  
-+      phba->lpfc_hbq_pool = NULL;
-+      phba->nlp_mem_pool = NULL;
-+      phba->mbox_mem_pool = NULL;
-+      phba->lpfc_scsi_dma_buf_pool = NULL;
-+      phba->lpfc_mbuf_pool = NULL;
-+
-       /* Free the iocb lookup array */
-       kfree(psli->iocbq_lookup);
-       psli->iocbq_lookup = NULL;
-@@ -148,20 +190,23 @@
- lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
+-static int ifb_newlink(struct net_device *dev,
+-                     struct nlattr *tb[], struct nlattr *data[])
+-{
+-      struct ifb_private *priv = netdev_priv(dev);
+-      int err;
+-
+-      err = register_netdevice(dev);
+-      if (err < 0)
+-              return err;
+-
+-      priv->dev = dev;
+-      list_add_tail(&priv->list, &ifbs);
+-      return 0;
+-}
+-
+-static void ifb_dellink(struct net_device *dev)
+-{
+-      struct ifb_private *priv = netdev_priv(dev);
+-
+-      list_del(&priv->list);
+-      unregister_netdevice(dev);
+-}
+-
+-static struct rtnl_link_ops ifb_link_ops __read_mostly = {
+-      .kind           = "ifb",
+-      .priv_size      = sizeof(struct ifb_private),
+-      .setup          = ifb_setup,
+-      .newlink        = ifb_newlink,
+-      .dellink        = ifb_dellink,
+-};
+-
+ static int __init ifb_init_one(int index)
  {
-       struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
-+      unsigned long iflags;
-       void *ret;
+       struct net_device *dev_ifb;
+-      struct ifb_private *priv;
+       int err;
  
-       ret = pci_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle);
+       dev_ifb = alloc_netdev(sizeof(struct ifb_private),
+@@ -273,59 +237,49 @@
+       if (!dev_ifb)
+               return -ENOMEM;
  
--      if (!ret && ( mem_flags & MEM_PRI) && pool->current_count) {
-+      spin_lock_irqsave(&phba->hbalock, iflags);
-+      if (!ret && (mem_flags & MEM_PRI) && pool->current_count) {
-               pool->current_count--;
-               ret = pool->elements[pool->current_count].virt;
-               *handle = pool->elements[pool->current_count].phys;
-       }
-+      spin_unlock_irqrestore(&phba->hbalock, iflags);
-       return ret;
+-      err = dev_alloc_name(dev_ifb, dev_ifb->name);
+-      if (err < 0)
+-              goto err;
+-
+-      dev_ifb->rtnl_link_ops = &ifb_link_ops;
+-      err = register_netdevice(dev_ifb);
+-      if (err < 0)
+-              goto err;
+-
+-      priv = netdev_priv(dev_ifb);
+-      priv->dev = dev_ifb;
+-      list_add_tail(&priv->list, &ifbs);
+-      return 0;
+-
+-err:
++      if ((err = register_netdev(dev_ifb))) {
+       free_netdev(dev_ifb);
++              dev_ifb = NULL;
++      } else {
++              ifbs[index] = dev_ifb;
++      }
++
+       return err;
  }
  
- void
--lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
-+__lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
+-static int __init ifb_init_module(void)
++static void ifb_free_one(int index)
  {
-       struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
-@@ -174,3 +219,51 @@
-       }
-       return;
- }
-+
-+void
-+lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
-+{
-+      unsigned long iflags;
-+
-+      spin_lock_irqsave(&phba->hbalock, iflags);
-+      __lpfc_mbuf_free(phba, virt, dma);
-+      spin_unlock_irqrestore(&phba->hbalock, iflags);
-+      return;
-+}
-+
-+void *
-+lpfc_hbq_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
-+{
-+      void *ret;
-+      ret = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_ATOMIC, handle);
-+      return ret;
-+}
-+
-+void
-+lpfc_hbq_free(struct lpfc_hba *phba, void *virt, dma_addr_t dma)
-+{
-+      pci_pool_free(phba->lpfc_hbq_pool, virt, dma);
-+      return;
+-      struct ifb_private *priv, *next;
+-      int i, err;
+-
+-      rtnl_lock();
+-      err = __rtnl_link_register(&ifb_link_ops);
++      unregister_netdev(ifbs[index]);
++      free_netdev(ifbs[index]);
 +}
-+
-+void
-+lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
++static int __init ifb_init_module(void)
 +{
-+      struct hbq_dmabuf *hbq_entry;
-+
-+      if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
-+              hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf);
-+              if (hbq_entry->tag == -1) {
-+                      lpfc_hbq_free(phba, hbq_entry->dbuf.virt,
-+                                    hbq_entry->dbuf.phys);
-+                      kfree(hbq_entry);
-+              } else {
-+                      lpfc_sli_free_hbq(phba, hbq_entry);
-+              }
-+      } else {
-+              lpfc_mbuf_free(phba, mp->virt, mp->phys);
-+              kfree(mp);
-+      }
-+      return;
-+}
-+
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_nportdisc.c linux-2.6.22-590/drivers/scsi/lpfc/lpfc_nportdisc.c
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_nportdisc.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_nportdisc.c        2008-01-02 13:56:37.000000000 -0500
-@@ -1,4 +1,4 @@
--/*******************************************************************
-+ /*******************************************************************
-  * This file is part of the Emulex Linux Device Driver for         *
-  * Fibre Channel Host Bus Adapters.                                *
-  * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
-@@ -35,20 +35,22 @@
- #include "lpfc.h"
- #include "lpfc_logmsg.h"
- #include "lpfc_crtn.h"
-+#include "lpfc_vport.h"
-+#include "lpfc_debugfs.h"
++      int i, err = 0;
++      ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL);
++      if (!ifbs)
++              return -ENOMEM;
+       for (i = 0; i < numifbs && !err; i++)
+               err = ifb_init_one(i);
+       if (err) {
+-              list_for_each_entry_safe(priv, next, &ifbs, list)
+-                      ifb_dellink(priv->dev);
+-              __rtnl_link_unregister(&ifb_link_ops);
++              i--;
++              while (--i >= 0)
++                      ifb_free_one(i);
+       }
+-      rtnl_unlock();
  
+       return err;
+ }
  
- /* Called to verify a rcv'ed ADISC was intended for us. */
- static int
--lpfc_check_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
--               struct lpfc_name * nn, struct lpfc_name * pn)
-+lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+               struct lpfc_name *nn, struct lpfc_name *pn)
+ static void __exit ifb_cleanup_module(void)
  {
-       /* Compare the ADISC rsp WWNN / WWPN matches our internal node
-        * table entry for that node.
-        */
--      if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)) != 0)
-+      if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)))
-               return 0;
--      if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)) != 0)
-+      if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)))
-               return 0;
+-      struct ifb_private *priv, *next;
+-
+-      rtnl_lock();
+-      list_for_each_entry_safe(priv, next, &ifbs, list)
+-              ifb_dellink(priv->dev);
++      int i;
  
-       /* we match, return success */
-@@ -56,11 +58,10 @@
+-      __rtnl_link_unregister(&ifb_link_ops);
+-      rtnl_unlock();
++      for (i = 0; i < numifbs; i++)
++              ifb_free_one(i);
++      kfree(ifbs);
  }
  
- int
--lpfc_check_sparm(struct lpfc_hba * phba,
--               struct lpfc_nodelist * ndlp, struct serv_parm * sp,
--               uint32_t class)
-+lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+               struct serv_parm * sp, uint32_t class)
- {
--      volatile struct serv_parm *hsp = &phba->fc_sparam;
-+      volatile struct serv_parm *hsp = &vport->fc_sparam;
-       uint16_t hsp_value, ssp_value = 0;
+ module_init(ifb_init_module);
+ module_exit(ifb_cleanup_module);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Jamal Hadi Salim");
+-MODULE_ALIAS_RTNL_LINK("ifb");
+diff -Nurb linux-2.6.22-590/drivers/net/ixp2000/ixpdev.c linux-2.6.22-570/drivers/net/ixp2000/ixpdev.c
+--- linux-2.6.22-590/drivers/net/ixp2000/ixpdev.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/ixp2000/ixpdev.c      2007-07-08 19:32:17.000000000 -0400
+@@ -111,7 +111,7 @@
+               skb = dev_alloc_skb(desc->pkt_length + 2);
+               if (likely(skb != NULL)) {
+                       skb_reserve(skb, 2);
+-                      skb_copy_to_linear_data(skb, buf, desc->pkt_length);
++                      eth_copy_and_sum(skb, buf, desc->pkt_length, 0);
+                       skb_put(skb, desc->pkt_length);
+                       skb->protocol = eth_type_trans(skb, nds[desc->channel]);
  
-       /*
-@@ -75,12 +76,14 @@
-                               hsp->cls1.rcvDataSizeLsb;
-               ssp_value = (sp->cls1.rcvDataSizeMsb << 8) |
-                               sp->cls1.rcvDataSizeLsb;
-+              if (!ssp_value)
-+                      goto bad_service_param;
-               if (ssp_value > hsp_value) {
-                       sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb;
-                       sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
-               }
-       } else if (class == CLASS1) {
+diff -Nurb linux-2.6.22-590/drivers/net/kgdboe.c linux-2.6.22-570/drivers/net/kgdboe.c
+--- linux-2.6.22-590/drivers/net/kgdboe.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/kgdboe.c      1969-12-31 19:00:00.000000000 -0500
+@@ -1,294 +0,0 @@
+-/*
+- * drivers/net/kgdboe.c
+- *
+- * A network interface for GDB.
+- * Based upon 'gdbserial' by David Grothe <dave@gcom.com>
+- * and Scott Foehner <sfoehner@engr.sgi.com>
+- *
+- * Maintainers: Amit S. Kale <amitkale@linsyssoft.com> and
+- *            Tom Rini <trini@kernel.crashing.org>
+- *
+- * 2004 (c) Amit S. Kale <amitkale@linsyssoft.com>
+- * 2004-2005 (c) MontaVista Software, Inc.
+- * 2005 (c) Wind River Systems, Inc.
+- *
+- * Contributors at various stages not listed above:
+- * San Mehat <nettwerk@biodome.org>, Robert Walsh <rjwalsh@durables.org>,
+- * wangdi <wangdi@clusterfs.com>, Matt Mackall <mpm@selenic.com>,
+- * Pavel Machek <pavel@suse.cz>, Jason Wessel <jason.wessel@windriver.com>
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program is licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/interrupt.h>
+-#include <linux/string.h>
+-#include <linux/kgdb.h>
+-#include <linux/netpoll.h>
+-#include <linux/init.h>
+-
+-#include <asm/atomic.h>
+-
+-#define IN_BUF_SIZE 512               /* power of 2, please */
+-#define NOT_CONFIGURED_STRING "not_configured"
+-#define OUT_BUF_SIZE 30               /* We don't want to send too big of a packet. */
+-#define MAX_KGDBOE_CONFIG_STR 256
+-
+-static char in_buf[IN_BUF_SIZE], out_buf[OUT_BUF_SIZE];
+-static int in_head, in_tail, out_count;
+-static atomic_t in_count;
+-/* 0 = unconfigured, 1 = netpoll options parsed, 2 = fully configured. */
+-static int configured;
+-static struct kgdb_io local_kgdb_io_ops;
+-static int use_dynamic_mac;
+-
+-MODULE_DESCRIPTION("KGDB driver for network interfaces");
+-MODULE_LICENSE("GPL");
+-static char config[MAX_KGDBOE_CONFIG_STR] = NOT_CONFIGURED_STRING;
+-static struct kparam_string kps = {
+-      .string = config,
+-      .maxlen = MAX_KGDBOE_CONFIG_STR,
+-};
+-
+-static void rx_hook(struct netpoll *np, int port, char *msg, int len,
+-                  struct sk_buff *skb)
+-{
+-      int i;
+-
+-      np->remote_port = port;
+-
+-      /* Copy the MAC address if we need to. */
+-      if (use_dynamic_mac) {
+-              memcpy(np->remote_mac, eth_hdr(skb)->h_source,
+-                              sizeof(np->remote_mac));
+-              use_dynamic_mac = 0;
+-      }
+-
+-      /*
+-       * This could be GDB trying to attach.  But it could also be GDB
+-       * finishing up a session, with kgdb_connected=0 but GDB sending
+-       * an ACK for the final packet.  To make sure we don't try and
+-       * make a breakpoint when GDB is leaving, make sure that if
+-       * !kgdb_connected the only len == 1 packet we allow is ^C.
+-       */
+-      if (!kgdb_connected && (len != 1 || msg[0] == 3) &&
+-          !atomic_read(&kgdb_setting_breakpoint)) {
+-              tasklet_schedule(&kgdb_tasklet_breakpoint);
+-      }
+-
+-      for (i = 0; i < len; i++) {
+-              if (msg[i] == 3)
+-                      tasklet_schedule(&kgdb_tasklet_breakpoint);
+-
+-              if (atomic_read(&in_count) >= IN_BUF_SIZE) {
+-                      /* buffer overflow, clear it */
+-                      in_head = in_tail = 0;
+-                      atomic_set(&in_count, 0);
+-                      break;
+-              }
+-              in_buf[in_head++] = msg[i];
+-              in_head &= (IN_BUF_SIZE - 1);
+-              atomic_inc(&in_count);
+-      }
+-}
+-
+-static struct netpoll np = {
+-      .dev_name = "eth0",
+-      .name = "kgdboe",
+-      .rx_hook = rx_hook,
+-      .local_port = 6443,
+-      .remote_port = 6442,
+-      .remote_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+-};
+-
+-static void eth_pre_exception_handler(void)
+-{
+-      /* Increment the module count when the debugger is active */
+-      if (!kgdb_connected)
+-              try_module_get(THIS_MODULE);
+-      netpoll_set_trap(1);
+-}
+-
+-static void eth_post_exception_handler(void)
+-{
+-      /* decrement the module count when the debugger detaches */
+-      if (!kgdb_connected)
+-              module_put(THIS_MODULE);
+-      netpoll_set_trap(0);
+-}
+-
+-static int eth_get_char(void)
+-{
+-      int chr;
+-
+-      while (atomic_read(&in_count) == 0)
+-              netpoll_poll(&np);
+-
+-      chr = in_buf[in_tail++];
+-      in_tail &= (IN_BUF_SIZE - 1);
+-      atomic_dec(&in_count);
+-      return chr;
+-}
+-
+-static void eth_flush_buf(void)
+-{
+-      if (out_count && np.dev) {
+-              netpoll_send_udp(&np, out_buf, out_count);
+-              memset(out_buf, 0, sizeof(out_buf));
+-              out_count = 0;
+-      }
+-}
+-
+-static void eth_put_char(u8 chr)
+-{
+-      out_buf[out_count++] = chr;
+-      if (out_count == OUT_BUF_SIZE)
+-              eth_flush_buf();
+-}
+-
+-static int option_setup(char *opt)
+-{
+-      char opt_scratch[MAX_KGDBOE_CONFIG_STR];
+-
+-      /* If we're being given a new configuration, copy it in. */
+-      if (opt != config)
+-              strcpy(config, opt);
+-      /* But work on a copy as netpoll_parse_options will eat it. */
+-      strcpy(opt_scratch, opt);
+-      configured = !netpoll_parse_options(&np, opt_scratch);
+-
+-      use_dynamic_mac = 1;
+-
+-      return 0;
+-}
+-__setup("kgdboe=", option_setup);
+-
+-/* With our config string set by some means, configure kgdboe. */
+-static int configure_kgdboe(void)
+-{
+-      /* Try out the string. */
+-      option_setup(config);
+-
+-      if (!configured) {
+-              printk(KERN_ERR "kgdboe: configuration incorrect - kgdboe not "
+-                     "loaded.\n");
+-              printk(KERN_ERR "  Usage: kgdboe=[src-port]@[src-ip]/[dev],"
+-                              "[tgt-port]@<tgt-ip>/<tgt-macaddr>\n");
+-              return -EINVAL;
+-      }
+-
+-      /* Bring it up. */
+-      if (netpoll_setup(&np)) {
+-              printk(KERN_ERR "kgdboe: netpoll_setup failed kgdboe failed\n");
+-              return -EINVAL;
+-      }
+-
+-      if (kgdb_register_io_module(&local_kgdb_io_ops)) {
+-              netpoll_cleanup(&np);
+-              return -EINVAL;
+-      }
+-
+-      configured = 2;
+-
+-      return 0;
+-}
+-
+-static int init_kgdboe(void)
+-{
+-      int ret;
+-
+-      /* Already done? */
+-      if (configured == 2)
 -              return 0;
-+              goto bad_service_param;
-       }
-       if (sp->cls2.classValid) {
-@@ -88,12 +91,14 @@
-                               hsp->cls2.rcvDataSizeLsb;
-               ssp_value = (sp->cls2.rcvDataSizeMsb << 8) |
-                               sp->cls2.rcvDataSizeLsb;
-+              if (!ssp_value)
-+                      goto bad_service_param;
-               if (ssp_value > hsp_value) {
-                       sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb;
-                       sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
-               }
-       } else if (class == CLASS2) {
+-
+-      /* OK, go ahead and do it. */
+-      ret = configure_kgdboe();
+-
+-      if (configured == 2)
+-              printk(KERN_INFO "kgdboe: debugging over ethernet enabled\n");
+-
+-      return ret;
+-}
+-
+-static void cleanup_kgdboe(void)
+-{
+-      netpoll_cleanup(&np);
+-      configured = 0;
+-      kgdb_unregister_io_module(&local_kgdb_io_ops);
+-}
+-
+-static int param_set_kgdboe_var(const char *kmessage, struct kernel_param *kp)
+-{
+-      char kmessage_save[MAX_KGDBOE_CONFIG_STR];
+-      int msg_len = strlen(kmessage);
+-
+-      if (msg_len + 1 > MAX_KGDBOE_CONFIG_STR) {
+-              printk(KERN_ERR "%s: string doesn't fit in %u chars.\n",
+-                     kp->name, MAX_KGDBOE_CONFIG_STR - 1);
+-              return -ENOSPC;
+-      }
+-
+-      if (kgdb_connected) {
+-              printk(KERN_ERR "kgdboe: Cannot reconfigure while KGDB is "
+-                              "connected.\n");
 -              return 0;
-+              goto bad_service_param;
-       }
-       if (sp->cls3.classValid) {
-@@ -101,12 +106,14 @@
-                               hsp->cls3.rcvDataSizeLsb;
-               ssp_value = (sp->cls3.rcvDataSizeMsb << 8) |
-                               sp->cls3.rcvDataSizeLsb;
-+              if (!ssp_value)
-+                      goto bad_service_param;
-               if (ssp_value > hsp_value) {
-                       sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb;
-                       sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
-               }
-       } else if (class == CLASS3) {
+-      }
+-
+-      /* Start the reconfiguration process by saving the old string */
+-      strncpy(kmessage_save, config, sizeof(kmessage_save));
+-
+-
+-      /* Copy in the new param and strip out invalid characters so we
+-       * can optionally specify the MAC.
+-       */
+-      strncpy(config, kmessage, sizeof(config));
+-      msg_len--;
+-      while (msg_len > 0 &&
+-                      (config[msg_len] < ',' || config[msg_len] > 'f')) {
+-              config[msg_len] = '\0';
+-              msg_len--;
+-      }
+-
+-      /* Check to see if we are unconfiguring the io module and that it
+-       * was in a fully configured state, as this is the only time that
+-       * netpoll_cleanup should get called
+-       */
+-      if (configured == 2 && strcmp(config, NOT_CONFIGURED_STRING) == 0) {
+-              printk(KERN_INFO "kgdboe: reverting to unconfigured state\n");
+-              cleanup_kgdboe();
 -              return 0;
-+              goto bad_service_param;
-       }
+-      } else
+-              /* Go and configure with the new params. */
+-              configure_kgdboe();
+-
+-      if (configured == 2)
+-              return 0;
+-
+-      /* If the new string was invalid, revert to the previous state, which
+-       * is at a minimum not_configured. */
+-      strncpy(config, kmessage_save, sizeof(config));
+-      if (strcmp(kmessage_save, NOT_CONFIGURED_STRING) != 0) {
+-              printk(KERN_INFO "kgdboe: reverting to prior configuration\n");
+-              /* revert back to the original config */
+-              strncpy(config, kmessage_save, sizeof(config));
+-              configure_kgdboe();
+-      }
+-      return 0;
+-}
+-
+-static struct kgdb_io local_kgdb_io_ops = {
+-      .read_char = eth_get_char,
+-      .write_char = eth_put_char,
+-      .init = init_kgdboe,
+-      .flush = eth_flush_buf,
+-      .pre_exception = eth_pre_exception_handler,
+-      .post_exception = eth_post_exception_handler
+-};
+-
+-module_init(init_kgdboe);
+-module_exit(cleanup_kgdboe);
+-module_param_call(kgdboe, param_set_kgdboe_var, param_get_string, &kps, 0644);
+-MODULE_PARM_DESC(kgdboe, " kgdboe=[src-port]@[src-ip]/[dev],"
+-               "[tgt-port]@<tgt-ip>/<tgt-macaddr>\n");
+diff -Nurb linux-2.6.22-590/drivers/net/lance.c linux-2.6.22-570/drivers/net/lance.c
+--- linux-2.6.22-590/drivers/net/lance.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/lance.c       2007-07-08 19:32:17.000000000 -0400
+@@ -1186,9 +1186,9 @@
+                               }
+                               skb_reserve(skb,2);     /* 16 byte align */
+                               skb_put(skb,pkt_len);   /* Make room */
+-                              skb_copy_to_linear_data(skb,
++                              eth_copy_and_sum(skb,
+                                       (unsigned char *)isa_bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)),
+-                                      pkt_len);
++                                      pkt_len,0);
+                               skb->protocol=eth_type_trans(skb,dev);
+                               netif_rx(skb);
+                               dev->last_rx = jiffies;
+diff -Nurb linux-2.6.22-590/drivers/net/loopback.c linux-2.6.22-570/drivers/net/loopback.c
+--- linux-2.6.22-590/drivers/net/loopback.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/loopback.c    2007-07-08 19:32:17.000000000 -0400
+@@ -57,7 +57,6 @@
+ #include <linux/ip.h>
+ #include <linux/tcp.h>
+ #include <linux/percpu.h>
+-#include <net/net_namespace.h>
  
-       /*
-@@ -125,11 +132,21 @@
-       memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
-       memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name));
-       return 1;
-+bad_service_param:
-+      lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY,
-+                      "%d (%d):0207 Device %x "
-+                      "(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent "
-+                      "invalid service parameters.  Ignoring device.\n",
-+                      vport->phba->brd_no, ndlp->vport->vpi, ndlp->nlp_DID,
-+                      sp->nodeName.u.wwn[0], sp->nodeName.u.wwn[1],
-+                      sp->nodeName.u.wwn[2], sp->nodeName.u.wwn[3],
-+                      sp->nodeName.u.wwn[4], sp->nodeName.u.wwn[5],
-+                      sp->nodeName.u.wwn[6], sp->nodeName.u.wwn[7]);
-+      return 0;
- }
+ struct pcpu_lstats {
+       unsigned long packets;
+@@ -200,52 +199,39 @@
+       .get_rx_csum            = always_on,
+ };
  
- static void *
--lpfc_check_elscmpl_iocb(struct lpfc_hba * phba,
--                    struct lpfc_iocbq *cmdiocb,
-+lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-                     struct lpfc_iocbq *rspiocb)
- {
-       struct lpfc_dmabuf *pcmd, *prsp;
-@@ -168,32 +185,29 @@
-  * routine effectively results in a "software abort".
+-static int loopback_net_init(struct net *net)
+-{
+-      struct net_device *lo = &net->loopback_dev;
+ /*
+  * The loopback device is special. There is only one instance and
+  * it is statically allocated. Don't do this for other devices.
   */
- int
--lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
-+lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
- {
-       LIST_HEAD(completions);
--      struct lpfc_sli *psli;
--      struct lpfc_sli_ring *pring;
-+      struct lpfc_sli  *psli = &phba->sli;
-+      struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
-       struct lpfc_iocbq *iocb, *next_iocb;
-       IOCB_t *cmd;
-       /* Abort outstanding I/O on NPort <nlp_DID> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
--                      "%d:0205 Abort outstanding I/O on NPort x%x "
-+                      "%d (%d):0205 Abort outstanding I/O on NPort x%x "
-                       "Data: x%x x%x x%x\n",
--                      phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
--                      ndlp->nlp_state, ndlp->nlp_rpi);
-+                      phba->brd_no, ndlp->vport->vpi, ndlp->nlp_DID,
-+                      ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+-      strcpy(lo->name, "lo");
+-      lo->get_stats           = &get_stats,
+-      lo->mtu                 = (16 * 1024) + 20 + 20 + 12,
+-      lo->hard_start_xmit     = loopback_xmit,
+-      lo->hard_header         = eth_header,
+-      lo->hard_header_cache   = eth_header_cache,
+-      lo->header_cache_update = eth_header_cache_update,
+-      lo->hard_header_len     = ETH_HLEN,     /* 14   */
+-      lo->addr_len            = ETH_ALEN,     /* 6    */
+-      lo->tx_queue_len        = 0,
+-      lo->type                = ARPHRD_LOOPBACK,      /* 0x0001*/
+-      lo->rebuild_header      = eth_rebuild_header,
+-      lo->flags               = IFF_LOOPBACK,
+-      lo->features            = NETIF_F_SG | NETIF_F_FRAGLIST
++struct net_device loopback_dev = {
++      .name                   = "lo",
++      .get_stats              = &get_stats,
++      .mtu                    = (16 * 1024) + 20 + 20 + 12,
++      .hard_start_xmit        = loopback_xmit,
++      .hard_header            = eth_header,
++      .hard_header_cache      = eth_header_cache,
++      .header_cache_update    = eth_header_cache_update,
++      .hard_header_len        = ETH_HLEN,     /* 14   */
++      .addr_len               = ETH_ALEN,     /* 6    */
++      .tx_queue_len           = 0,
++      .type                   = ARPHRD_LOOPBACK,      /* 0x0001*/
++      .rebuild_header         = eth_rebuild_header,
++      .flags                  = IFF_LOOPBACK,
++      .features               = NETIF_F_SG | NETIF_F_FRAGLIST
+ #ifdef LOOPBACK_TSO
+                                 | NETIF_F_TSO
+ #endif
+                                 | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA
+-                                | NETIF_F_LLTX
+-                                | NETIF_F_NETNS_LOCAL,
+-      lo->ethtool_ops         = &loopback_ethtool_ops,
+-      lo->nd_net = net;
+-      return register_netdev(lo);
+-}
+-
+-static void loopback_net_exit(struct net *net)
+-{
+-      unregister_netdev(&net->loopback_dev);
+-}
+-
+-static struct pernet_operations loopback_net_ops = {
+-      .init = loopback_net_init,
+-      .exit = loopback_net_exit,
++                                | NETIF_F_LLTX,
++      .ethtool_ops            = &loopback_ethtool_ops,
+ };
  
--      psli = &phba->sli;
--      pring = &psli->ring[LPFC_ELS_RING];
-+      lpfc_fabric_abort_nport(ndlp);
+ /* Setup and register the loopback device. */
+ static int __init loopback_init(void)
+ {
+-      return register_pernet_device(&loopback_net_ops);
++      return register_netdev(&loopback_dev);
+ };
  
-       /* First check the txq */
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
--              /* Check to see if iocb matches the nport we are looking
--                 for */
-+              /* Check to see if iocb matches the nport we are looking for */
-               if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
--                      /* It matches, so deque and call compl with an
--                         error */
-+                      /* It matches, so deque and call compl with anp error */
-                       list_move_tail(&iocb->list, &completions);
-                       pring->txq_cnt--;
-               }
-@@ -201,37 +215,39 @@
+ module_init(loopback_init);
++
++EXPORT_SYMBOL(loopback_dev);
+diff -Nurb linux-2.6.22-590/drivers/net/natsemi.c linux-2.6.22-570/drivers/net/natsemi.c
+--- linux-2.6.22-590/drivers/net/natsemi.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/natsemi.c     2008-01-23 19:15:55.000000000 -0500
+@@ -2357,8 +2357,8 @@
+                                       np->rx_dma[entry],
+                                       buflen,
+                                       PCI_DMA_FROMDEVICE);
+-                              skb_copy_to_linear_data(skb,
+-                                      np->rx_skbuff[entry]->data, pkt_len);
++                              eth_copy_and_sum(skb,
++                                      np->rx_skbuff[entry]->data, pkt_len, 0);
+                               skb_put(skb, pkt_len);
+                               pci_dma_sync_single_for_device(np->pci_dev,
+                                       np->rx_dma[entry],
+diff -Nurb linux-2.6.22-590/drivers/net/ni52.c linux-2.6.22-570/drivers/net/ni52.c
+--- linux-2.6.22-590/drivers/net/ni52.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/ni52.c        2007-07-08 19:32:17.000000000 -0400
+@@ -936,7 +936,7 @@
+                                       {
+                                               skb_reserve(skb,2);
+                                               skb_put(skb,totlen);
+-                                              skb_copy_to_linear_data(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen);
++                                              eth_copy_and_sum(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen,0);
+                                               skb->protocol=eth_type_trans(skb,dev);
+                                               netif_rx(skb);
+                                               dev->last_rx = jiffies;
+diff -Nurb linux-2.6.22-590/drivers/net/ni65.c linux-2.6.22-570/drivers/net/ni65.c
+--- linux-2.6.22-590/drivers/net/ni65.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/ni65.c        2007-07-08 19:32:17.000000000 -0400
+@@ -1096,7 +1096,7 @@
+ #ifdef RCV_VIA_SKB
+                               if( (unsigned long) (skb->data + R_BUF_SIZE) > 0x1000000) {
+                                       skb_put(skb,len);
+-                                      skb_copy_to_linear_data(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len);
++                                      eth_copy_and_sum(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len,0);
+                               }
+                               else {
+                                       struct sk_buff *skb1 = p->recv_skb[p->rmdnum];
+@@ -1108,7 +1108,7 @@
+                               }
+ #else
+                               skb_put(skb,len);
+-                              skb_copy_to_linear_data(skb, (unsigned char *) p->recvbounce[p->rmdnum],len);
++                              eth_copy_and_sum(skb, (unsigned char *) p->recvbounce[p->rmdnum],len,0);
+ #endif
+                               p->stats.rx_packets++;
+                               p->stats.rx_bytes += len;
+diff -Nurb linux-2.6.22-590/drivers/net/pci-skeleton.c linux-2.6.22-570/drivers/net/pci-skeleton.c
+--- linux-2.6.22-590/drivers/net/pci-skeleton.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/pci-skeleton.c        2007-07-08 19:32:17.000000000 -0400
+@@ -1567,7 +1567,7 @@
+               if (skb) {
+                       skb_reserve (skb, 2);   /* 16 byte align the IP fields. */
  
-       /* Next check the txcmplq */
-       list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
--              /* Check to see if iocb matches the nport we are looking
--                 for */
--              if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))
-+              /* Check to see if iocb matches the nport we are looking for */
-+              if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
-                       lpfc_sli_issue_abort_iotag(phba, pring, iocb);
-       }
--      spin_unlock_irq(phba->host->host_lock);
-+      }
-+      spin_unlock_irq(&phba->hbalock);
+-                      skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size);
++                      eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
+                       skb_put (skb, pkt_size);
  
-       while (!list_empty(&completions)) {
-               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
-               cmd = &iocb->iocb;
--              list_del(&iocb->list);
-+              list_del_init(&iocb->list);
+                       skb->protocol = eth_type_trans (skb, dev);
+diff -Nurb linux-2.6.22-590/drivers/net/pcnet32.c linux-2.6.22-570/drivers/net/pcnet32.c
+--- linux-2.6.22-590/drivers/net/pcnet32.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/pcnet32.c     2007-07-08 19:32:17.000000000 -0400
+@@ -1235,9 +1235,9 @@
+                                           lp->rx_dma_addr[entry],
+                                           pkt_len,
+                                           PCI_DMA_FROMDEVICE);
+-              skb_copy_to_linear_data(skb,
++              eth_copy_and_sum(skb,
+                                (unsigned char *)(lp->rx_skbuff[entry]->data),
+-                               pkt_len);
++                               pkt_len, 0);
+               pci_dma_sync_single_for_device(lp->pci_dev,
+                                              lp->rx_dma_addr[entry],
+                                              pkt_len,
+diff -Nurb linux-2.6.22-590/drivers/net/pppoe.c linux-2.6.22-570/drivers/net/pppoe.c
+--- linux-2.6.22-590/drivers/net/pppoe.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/pppoe.c       2007-07-08 19:32:17.000000000 -0400
+@@ -78,7 +78,6 @@
+ #include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
  
--              if (iocb->iocb_cmpl) {
-+              if (!iocb->iocb_cmpl)
-+                      lpfc_sli_release_iocbq(phba, iocb);
-+              else {
-                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                       cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-                       (iocb->iocb_cmpl) (phba, iocb, iocb);
--              } else
--                      lpfc_sli_release_iocbq(phba, iocb);
-+              }
-       }
+-#include <net/net_namespace.h>
+ #include <net/sock.h>
  
-       /* If we are delaying issuing an ELS command, cancel it */
-       if (ndlp->nlp_flag & NLP_DELAY_TMO)
--              lpfc_cancel_retry_delay_tmo(phba, ndlp);
-+              lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
-       return 0;
- }
+ #include <asm/uaccess.h>
+@@ -211,7 +210,7 @@
+       struct net_device *dev;
+       int ifindex;
  
- static int
--lpfc_rcv_plogi(struct lpfc_hba * phba,
--                    struct lpfc_nodelist * ndlp,
-+lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-                     struct lpfc_iocbq *cmdiocb)
+-      dev = dev_get_by_name(&init_net, sp->sa_addr.pppoe.dev);
++      dev = dev_get_by_name(sp->sa_addr.pppoe.dev);
+       if(!dev)
+               return NULL;
+       ifindex = dev->ifindex;
+@@ -296,9 +295,6 @@
  {
-+      struct Scsi_Host   *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba    *phba = vport->phba;
-       struct lpfc_dmabuf *pcmd;
-       uint32_t *lp;
-       IOCB_t *icmd;
-@@ -241,14 +257,14 @@
-       int rc;
+       struct net_device *dev = (struct net_device *) ptr;
  
-       memset(&stat, 0, sizeof (struct ls_rjt));
--      if (phba->hba_state <= LPFC_FLOGI) {
-+      if (vport->port_state <= LPFC_FLOGI) {
-               /* Before responding to PLOGI, check for pt2pt mode.
-                * If we are pt2pt, with an outstanding FLOGI, abort
-                * the FLOGI and resend it first.
-                */
--              if (phba->fc_flag & FC_PT2PT) {
-+              if (vport->fc_flag & FC_PT2PT) {
-                       lpfc_els_abort_flogi(phba);
--                      if (!(phba->fc_flag & FC_PT2PT_PLOGI)) {
-+                      if (!(vport->fc_flag & FC_PT2PT_PLOGI)) {
-                               /* If the other side is supposed to initiate
-                                * the PLOGI anyway, just ACC it now and
-                                * move on with discovery.
-@@ -257,45 +273,42 @@
-                               phba->fc_ratov = FF_DEF_RATOV;
-                               /* Start discovery - this should just do
-                                  CLEAR_LA */
--                              lpfc_disc_start(phba);
--                      } else {
--                              lpfc_initial_flogi(phba);
--                      }
-+                              lpfc_disc_start(vport);
-+                      } else
-+                              lpfc_initial_flogi(vport);
-               } else {
-                       stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
-                       stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
--                      lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb,
--                                          ndlp);
-+                      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
-+                                          ndlp, NULL);
-                       return 0;
-               }
-       }
-       pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
-       lp = (uint32_t *) pcmd->virt;
-       sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
--      if ((lpfc_check_sparm(phba, ndlp, sp, CLASS3) == 0)) {
-+      if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) {
-               /* Reject this request because invalid parameters */
-               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-               stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
--              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
-+              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
-+                      NULL);
-               return 0;
-       }
-       icmd = &cmdiocb->iocb;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       /* Only look at sockets that are using this specific device. */
+       switch (event) {
+       case NETDEV_CHANGEMTU:
+@@ -384,9 +380,6 @@
+       struct pppoe_hdr *ph;
+       struct pppox_sock *po;
  
-       /* PLOGI chkparm OK */
--      lpfc_printf_log(phba,
--                      KERN_INFO,
--                      LOG_ELS,
--                      "%d:0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
--                      phba->brd_no,
-+      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-+                      "%d (%d):0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
-+                      phba->brd_no, vport->vpi,
-                       ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag,
-                       ndlp->nlp_rpi);
+-      if (dev->nd_net != &init_net)
+-              goto drop;
+-
+       if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
+               goto drop;
  
--      if ((phba->cfg_fcp_class == 2) &&
--          (sp->cls2.classValid)) {
-+      if (phba->cfg_fcp_class == 2 && sp->cls2.classValid)
-               ndlp->nlp_fcp_info |= CLASS2;
--      } else {
-+      else
-               ndlp->nlp_fcp_info |= CLASS3;
--      }
-+
-       ndlp->nlp_class_sup = 0;
-       if (sp->cls1.classValid)
-               ndlp->nlp_class_sup |= FC_COS_CLASS1;
-@@ -317,35 +330,37 @@
-       case  NLP_STE_PRLI_ISSUE:
-       case  NLP_STE_UNMAPPED_NODE:
-       case  NLP_STE_MAPPED_NODE:
--              lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0);
-+              lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0);
-               return 1;
-       }
+@@ -419,9 +412,6 @@
+       struct pppoe_hdr *ph;
+       struct pppox_sock *po;
  
--      if ((phba->fc_flag & FC_PT2PT)
--          && !(phba->fc_flag & FC_PT2PT_PLOGI)) {
-+      if ((vport->fc_flag & FC_PT2PT) &&
-+          !(vport->fc_flag & FC_PT2PT_PLOGI)) {
-               /* rcv'ed PLOGI decides what our NPortId will be */
--              phba->fc_myDID = icmd->un.rcvels.parmRo;
-+              vport->fc_myDID = icmd->un.rcvels.parmRo;
-               mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-               if (mbox == NULL)
-                       goto out;
-               lpfc_config_link(phba, mbox);
-               mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-+              mbox->vport = vport;
-               rc = lpfc_sli_issue_mbox
-                       (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
-               if (rc == MBX_NOT_FINISHED) {
--                      mempool_free( mbox, phba->mbox_mem_pool);
-+                      mempool_free(mbox, phba->mbox_mem_pool);
-                       goto out;
-               }
+-      if (dev->nd_net != &init_net)
+-              goto abort;
+-
+       if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
+               goto abort;
  
--              lpfc_can_disctmo(phba);
-+              lpfc_can_disctmo(vport);
-       }
-       mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
--      if (mbox == NULL)
-+      if (!mbox)
-               goto out;
+@@ -481,12 +471,12 @@
+  * Initialize a new struct sock.
+  *
+  **********************************************************************/
+-static int pppoe_create(struct net *net, struct socket *sock)
++static int pppoe_create(struct socket *sock)
+ {
+       int error = -ENOMEM;
+       struct sock *sk;
  
--      if (lpfc_reg_login(phba, icmd->un.rcvels.remoteID,
--                         (uint8_t *) sp, mbox, 0)) {
--              mempool_free( mbox, phba->mbox_mem_pool);
-+      rc = lpfc_reg_login(phba, vport->vpi, icmd->un.rcvels.remoteID,
-+                          (uint8_t *) sp, mbox, 0);
-+      if (rc) {
-+              mempool_free(mbox, phba->mbox_mem_pool);
+-      sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto, 1);
++      sk = sk_alloc(PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto, 1);
+       if (!sk)
                goto out;
-       }
  
-@@ -357,7 +372,10 @@
-        * mbox->context2 = lpfc_nlp_get(ndlp) deferred until mailbox
-        * command issued in lpfc_cmpl_els_acc().
-        */
-+      mbox->vport = vport;
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
-+      spin_unlock_irq(shost->host_lock);
+@@ -598,7 +588,7 @@
  
-       /*
-        * If there is an outstanding PLOGI issued, abort it before
-@@ -373,21 +391,38 @@
-               lpfc_els_abort(phba, ndlp);
-       }
+       /* Don't re-bind if sid==0 */
+       if (sp->sa_addr.pppoe.sid != 0) {
+-              dev = dev_get_by_name(&init_net, sp->sa_addr.pppoe.dev);
++              dev = dev_get_by_name(sp->sa_addr.pppoe.dev);
  
--      lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
-+      if ((vport->port_type == LPFC_NPIV_PORT &&
-+            phba->cfg_vport_restrict_login)) {
-+
-+              /* In order to preserve RPIs, we want to cleanup
-+               * the default RPI the firmware created to rcv
-+               * this ELS request. The only way to do this is
-+               * to register, then unregister the RPI.
-+               */
-+              spin_lock_irq(shost->host_lock);
-+              ndlp->nlp_flag |= NLP_RM_DFLT_RPI;
-+              spin_unlock_irq(shost->host_lock);
-+              stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
-+              stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
-+              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
-+                      ndlp, mbox);
-+              return 1;
-+      }
-+      lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
-       return 1;
+               error = -ENODEV;
+               if (!dev)
+@@ -1074,7 +1064,7 @@
+ {
+       struct proc_dir_entry *p;
  
- out:
-       stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-       stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;
--      lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
-+      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
-       return 0;
+-      p = create_proc_entry("pppoe", S_IRUGO, init_net.proc_net);
++      p = create_proc_entry("net/pppoe", S_IRUGO, NULL);
+       if (!p)
+               return -ENOMEM;
+@@ -1145,7 +1135,7 @@
+       dev_remove_pack(&pppoes_ptype);
+       dev_remove_pack(&pppoed_ptype);
+       unregister_netdevice_notifier(&pppoe_notifier);
+-      remove_proc_entry("pppoe", init_net.proc_net);
++      remove_proc_entry("net/pppoe", NULL);
+       proto_unregister(&pppoe_sk_proto);
  }
  
- static int
--lpfc_rcv_padisc(struct lpfc_hba * phba,
--              struct lpfc_nodelist * ndlp,
-+lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-               struct lpfc_iocbq *cmdiocb)
- {
-+      struct Scsi_Host   *shost = lpfc_shost_from_vport(vport);
-       struct lpfc_dmabuf *pcmd;
-       struct serv_parm *sp;
-       struct lpfc_name *pnn, *ppn;
-@@ -412,12 +447,11 @@
-       }
+diff -Nurb linux-2.6.22-590/drivers/net/pppox.c linux-2.6.22-570/drivers/net/pppox.c
+--- linux-2.6.22-590/drivers/net/pppox.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/pppox.c       2007-07-08 19:32:17.000000000 -0400
+@@ -107,13 +107,10 @@
  
-       icmd = &cmdiocb->iocb;
--      if ((icmd->ulpStatus == 0) &&
--          (lpfc_check_adisc(phba, ndlp, pnn, ppn))) {
-+      if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) {
-               if (cmd == ELS_CMD_ADISC) {
--                      lpfc_els_rsp_adisc_acc(phba, cmdiocb, ndlp);
-+                      lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp);
-               } else {
--                      lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp,
-+                      lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp,
-                               NULL, 0);
-               }
-               return 1;
-@@ -427,55 +461,57 @@
-       stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-       stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
-       stat.un.b.vendorUnique = 0;
--      lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
-+      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
+ EXPORT_SYMBOL(pppox_ioctl);
  
-       /* 1 sec timeout */
-       mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+-static int pppox_create(struct net *net, struct socket *sock, int protocol)
++static int pppox_create(struct socket *sock, int protocol)
+ {
+       int rc = -EPROTOTYPE;
  
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag |= NLP_DELAY_TMO;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
-       ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
-       ndlp->nlp_prev_state = ndlp->nlp_state;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-       return 0;
- }
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
+-
+       if (protocol < 0 || protocol > PX_MAX_PROTO)
+               goto out;
  
- static int
--lpfc_rcv_logo(struct lpfc_hba * phba,
--                    struct lpfc_nodelist * ndlp,
--                    struct lpfc_iocbq *cmdiocb,
--                    uint32_t els_cmd)
-+lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+            struct lpfc_iocbq *cmdiocb, uint32_t els_cmd)
- {
--      /* Put ndlp on NPR list with 1 sec timeout for plogi, ACC logo */
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-+      /* Put ndlp in NPR state with 1 sec timeout for plogi, ACC logo */
-       /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
-        * PLOGIs during LOGO storms from a device.
-        */
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag |= NLP_LOGO_ACC;
-+      spin_unlock_irq(shost->host_lock);
-       if (els_cmd == ELS_CMD_PRLO)
--              lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
-+              lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
-       else
--              lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
-+              lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+@@ -129,7 +126,7 @@
+           !try_module_get(pppox_protos[protocol]->owner))
+               goto out;
  
-       if (!(ndlp->nlp_type & NLP_FABRIC) ||
-               (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
-               /* Only try to re-login if this is NOT a Fabric Node */
-               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
--              spin_lock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_DELAY_TMO;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
+-      rc = pppox_protos[protocol]->create(net, sock);
++      rc = pppox_protos[protocol]->create(sock);
  
-               ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
-               ndlp->nlp_prev_state = ndlp->nlp_state;
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-       } else {
-               ndlp->nlp_prev_state = ndlp->nlp_state;
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
-       }
+       module_put(pppox_protos[protocol]->owner);
+ out:
+diff -Nurb linux-2.6.22-590/drivers/net/r8169.c linux-2.6.22-570/drivers/net/r8169.c
+--- linux-2.6.22-590/drivers/net/r8169.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/r8169.c       2008-01-23 19:15:55.000000000 -0500
+@@ -2492,7 +2492,7 @@
+               skb = dev_alloc_skb(pkt_size + align);
+               if (skb) {
+                       skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
+-                      skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
++                      eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
+                       *sk_buff = skb;
+                       rtl8169_mark_to_asic(desc, rx_buf_sz);
+                       ret = 0;
+diff -Nurb linux-2.6.22-590/drivers/net/saa9730.c linux-2.6.22-570/drivers/net/saa9730.c
+--- linux-2.6.22-590/drivers/net/saa9730.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/saa9730.c     2007-07-08 19:32:17.000000000 -0400
+@@ -690,9 +690,9 @@
+                               lp->stats.rx_packets++;
+                               skb_reserve(skb, 2);    /* 16 byte align */
+                               skb_put(skb, len);      /* make room */
+-                              skb_copy_to_linear_data(skb,
++                              eth_copy_and_sum(skb,
+                                                (unsigned char *) pData,
+-                                               len);
++                                               len, 0);
+                               skb->protocol = eth_type_trans(skb, dev);
+                               netif_rx(skb);
+                               dev->last_rx = jiffies;
+diff -Nurb linux-2.6.22-590/drivers/net/sgiseeq.c linux-2.6.22-570/drivers/net/sgiseeq.c
+--- linux-2.6.22-590/drivers/net/sgiseeq.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/sgiseeq.c     2007-07-08 19:32:17.000000000 -0400
+@@ -320,7 +320,7 @@
+                               skb_put(skb, len);
  
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag &= ~NLP_NPR_ADISC;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
-       /* The driver has to wait until the ACC completes before it continues
-        * processing the LOGO.  The action will resume in
-        * lpfc_cmpl_els_logo_acc routine. Since part of processing includes an
-@@ -485,8 +521,7 @@
- }
+                               /* Copy out of kseg1 to avoid silly cache flush. */
+-                              skb_copy_to_linear_data(skb, pkt_pointer + 2, len);
++                              eth_copy_and_sum(skb, pkt_pointer + 2, len, 0);
+                               skb->protocol = eth_type_trans(skb, dev);
  
- static void
--lpfc_rcv_prli(struct lpfc_hba * phba,
--                    struct lpfc_nodelist * ndlp,
-+lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-                     struct lpfc_iocbq *cmdiocb)
- {
-       struct lpfc_dmabuf *pcmd;
-@@ -501,8 +536,7 @@
+                               /* We don't want to receive our own packets */
+diff -Nurb linux-2.6.22-590/drivers/net/shaper.c linux-2.6.22-570/drivers/net/shaper.c
+--- linux-2.6.22-590/drivers/net/shaper.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/shaper.c      2007-07-08 19:32:17.000000000 -0400
+@@ -86,7 +86,6 @@
  
-       ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
-       ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
--      if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) &&
--          (npr->prliType == PRLI_FCP_TYPE)) {
-+      if (npr->prliType == PRLI_FCP_TYPE) {
-               if (npr->initiatorFunc)
-                       ndlp->nlp_type |= NLP_FCP_INITIATOR;
-               if (npr->targetFunc)
-@@ -517,36 +551,42 @@
-                       roles |= FC_RPORT_ROLE_FCP_INITIATOR;
-               if (ndlp->nlp_type & NLP_FCP_TARGET)
-                       roles |= FC_RPORT_ROLE_FCP_TARGET;
-+
-+              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
-+                      "rport rolechg:   role:x%x did:x%x flg:x%x",
-+                      roles, ndlp->nlp_DID, ndlp->nlp_flag);
-+
-               fc_remote_port_rolechg(rport, roles);
-       }
- }
+ #include <net/dst.h>
+ #include <net/arp.h>
+-#include <net/net_namespace.h>
  
- static uint32_t
--lpfc_disc_set_adisc(struct lpfc_hba * phba,
--                    struct lpfc_nodelist * ndlp)
-+lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-+
-       /* Check config parameter use-adisc or FCP-2 */
--      if ((phba->cfg_use_adisc == 0) &&
--              !(phba->fc_flag & FC_RSCN_MODE)) {
--              if (!(ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE))
--                      return 0;
--      }
--      spin_lock_irq(phba->host->host_lock);
-+      if ((phba->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
-+          ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
-+              spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag |= NLP_NPR_ADISC;
--      spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-       return 1;
-+      }
-+      ndlp->nlp_flag &= ~NLP_NPR_ADISC;
-+      lpfc_unreg_rpi(vport, ndlp);
-+      return 0;
- }
+ struct shaper_cb {
+       unsigned long   shapeclock;             /* Time it should go out */
+@@ -489,7 +488,7 @@
+       {
+               case SHAPER_SET_DEV:
+               {
+-                      struct net_device *them=__dev_get_by_name(&init_net, ss->ss_name);
++                      struct net_device *them=__dev_get_by_name(ss->ss_name);
+                       if(them==NULL)
+                               return -ENODEV;
+                       if(sh->dev)
+diff -Nurb linux-2.6.22-590/drivers/net/sis190.c linux-2.6.22-570/drivers/net/sis190.c
+--- linux-2.6.22-590/drivers/net/sis190.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/sis190.c      2007-07-08 19:32:17.000000000 -0400
+@@ -548,7 +548,7 @@
+               skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
+               if (skb) {
+                       skb_reserve(skb, NET_IP_ALIGN);
+-                      skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
++                      eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
+                       *sk_buff = skb;
+                       sis190_give_to_asic(desc, rx_buf_sz);
+                       ret = 0;
+diff -Nurb linux-2.6.22-590/drivers/net/starfire.c linux-2.6.22-570/drivers/net/starfire.c
+--- linux-2.6.22-590/drivers/net/starfire.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/starfire.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1456,7 +1456,7 @@
+                       pci_dma_sync_single_for_cpu(np->pci_dev,
+                                                   np->rx_info[entry].mapping,
+                                                   pkt_len, PCI_DMA_FROMDEVICE);
+-                      skb_copy_to_linear_data(skb, np->rx_info[entry].skb->data, pkt_len);
++                      eth_copy_and_sum(skb, np->rx_info[entry].skb->data, pkt_len, 0);
+                       pci_dma_sync_single_for_device(np->pci_dev,
+                                                      np->rx_info[entry].mapping,
+                                                      pkt_len, PCI_DMA_FROMDEVICE);
+diff -Nurb linux-2.6.22-590/drivers/net/sun3_82586.c linux-2.6.22-570/drivers/net/sun3_82586.c
+--- linux-2.6.22-590/drivers/net/sun3_82586.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/sun3_82586.c  2007-07-08 19:32:17.000000000 -0400
+@@ -777,7 +777,7 @@
+                                       {
+                                               skb_reserve(skb,2);
+                                               skb_put(skb,totlen);
+-                                              skb_copy_to_linear_data(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen);
++                                              eth_copy_and_sum(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen,0);
+                                               skb->protocol=eth_type_trans(skb,dev);
+                                               netif_rx(skb);
+                                               p->stats.rx_packets++;
+diff -Nurb linux-2.6.22-590/drivers/net/sun3lance.c linux-2.6.22-570/drivers/net/sun3lance.c
+--- linux-2.6.22-590/drivers/net/sun3lance.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/sun3lance.c   2007-07-08 19:32:17.000000000 -0400
+@@ -853,9 +853,10 @@
  
- static uint32_t
--lpfc_disc_illegal(struct lpfc_hba * phba,
--                 struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                void *arg, uint32_t evt)
- {
--      lpfc_printf_log(phba,
--                      KERN_ERR,
--                      LOG_DISCOVERY,
--                      "%d:0253 Illegal State Transition: node x%x event x%x, "
--                      "state x%x Data: x%x x%x\n",
--                      phba->brd_no,
-+      lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY,
-+                      "%d (%d):0253 Illegal State Transition: node x%x "
-+                      "event x%x, state x%x Data: x%x x%x\n",
-+                      vport->phba->brd_no, vport->vpi,
-                       ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
-                       ndlp->nlp_flag);
-       return ndlp->nlp_state;
-@@ -555,150 +595,161 @@
- /* Start of Discovery State Machine routines */
+                               skb_reserve( skb, 2 );  /* 16 byte align */
+                               skb_put( skb, pkt_len );        /* Make room */
+-                              skb_copy_to_linear_data(skb,
++//                            skb_copy_to_linear_data(skb, PKTBUF_ADDR(head), pkt_len);
++                              eth_copy_and_sum(skb,
+                                                PKTBUF_ADDR(head),
+-                                               pkt_len);
++                                               pkt_len, 0);
  
- static uint32_t
--lpfc_rcv_plogi_unused_node(struct lpfc_hba * phba,
--                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_plogi_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                         void *arg, uint32_t evt)
- {
-       struct lpfc_iocbq *cmdiocb;
+                               skb->protocol = eth_type_trans( skb, dev );
+                               netif_rx( skb );
+diff -Nurb linux-2.6.22-590/drivers/net/sunbmac.c linux-2.6.22-570/drivers/net/sunbmac.c
+--- linux-2.6.22-590/drivers/net/sunbmac.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/sunbmac.c     2007-07-08 19:32:17.000000000 -0400
+@@ -860,7 +860,7 @@
+                       sbus_dma_sync_single_for_cpu(bp->bigmac_sdev,
+                                                    this->rx_addr, len,
+                                                    SBUS_DMA_FROMDEVICE);
+-                      skb_copy_to_linear_data(copy_skb, (unsigned char *)skb->data, len);
++                      eth_copy_and_sum(copy_skb, (unsigned char *)skb->data, len, 0);
+                       sbus_dma_sync_single_for_device(bp->bigmac_sdev,
+                                                       this->rx_addr, len,
+                                                       SBUS_DMA_FROMDEVICE);
+diff -Nurb linux-2.6.22-590/drivers/net/sundance.c linux-2.6.22-570/drivers/net/sundance.c
+--- linux-2.6.22-590/drivers/net/sundance.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/sundance.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1313,7 +1313,7 @@
+                                                           np->rx_buf_sz,
+                                                           PCI_DMA_FROMDEVICE);
  
-       cmdiocb = (struct lpfc_iocbq *) arg;
+-                              skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
++                              eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0);
+                               pci_dma_sync_single_for_device(np->pci_dev,
+                                                              desc->frag[0].addr,
+                                                              np->rx_buf_sz,
+diff -Nurb linux-2.6.22-590/drivers/net/sunlance.c linux-2.6.22-570/drivers/net/sunlance.c
+--- linux-2.6.22-590/drivers/net/sunlance.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/sunlance.c    2007-07-08 19:32:17.000000000 -0400
+@@ -549,9 +549,9 @@
  
--      if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
-+      if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
-               ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
-               return ndlp->nlp_state;
+                       skb_reserve(skb, 2);            /* 16 byte align */
+                       skb_put(skb, len);              /* make room */
+-                      skb_copy_to_linear_data(skb,
++                      eth_copy_and_sum(skb,
+                                        (unsigned char *)&(ib->rx_buf [entry][0]),
+-                                       len);
++                                       len, 0);
+                       skb->protocol = eth_type_trans(skb, dev);
+                       netif_rx(skb);
+                       dev->last_rx = jiffies;
+diff -Nurb linux-2.6.22-590/drivers/net/sunqe.c linux-2.6.22-570/drivers/net/sunqe.c
+--- linux-2.6.22-590/drivers/net/sunqe.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/sunqe.c       2007-07-08 19:32:17.000000000 -0400
+@@ -439,8 +439,8 @@
+                       } else {
+                               skb_reserve(skb, 2);
+                               skb_put(skb, len);
+-                              skb_copy_to_linear_data(skb, (unsigned char *) this_qbuf,
+-                                               len);
++                              eth_copy_and_sum(skb, (unsigned char *) this_qbuf,
++                                               len, 0);
+                               skb->protocol = eth_type_trans(skb, qep->dev);
+                               netif_rx(skb);
+                               qep->dev->last_rx = jiffies;
+diff -Nurb linux-2.6.22-590/drivers/net/tg3.c linux-2.6.22-570/drivers/net/tg3.c
+--- linux-2.6.22-590/drivers/net/tg3.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/tg3.c 2007-07-08 19:32:17.000000000 -0400
+@@ -11944,11 +11944,12 @@
+        * checksumming.
+        */
+       if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
+-              dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+-                      dev->features |= NETIF_F_IPV6_CSUM;
+-
++                      dev->features |= NETIF_F_HW_CSUM;
++              else
++                      dev->features |= NETIF_F_IP_CSUM;
++              dev->features |= NETIF_F_SG;
+               tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
+       } else
+               tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
+diff -Nurb linux-2.6.22-590/drivers/net/tokenring/lanstreamer.c linux-2.6.22-570/drivers/net/tokenring/lanstreamer.c
+--- linux-2.6.22-590/drivers/net/tokenring/lanstreamer.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/tokenring/lanstreamer.c       2007-07-08 19:32:17.000000000 -0400
+@@ -250,7 +250,7 @@
+ #if STREAMER_NETWORK_MONITOR
+ #ifdef CONFIG_PROC_FS
+       if (!dev_streamer)
+-              create_proc_read_entry("streamer_tr", 0, init_net.proc_net,
++              create_proc_read_entry("net/streamer_tr", 0, 0,
+                                       streamer_proc_info, NULL); 
+       streamer_priv->next = dev_streamer;
+       dev_streamer = streamer_priv;
+@@ -423,7 +423,7 @@
+                       }
+               }
+               if (!dev_streamer)
+-                      remove_proc_entry("streamer_tr", init_net.proc_net);
++                      remove_proc_entry("net/streamer_tr", NULL);
        }
--      lpfc_drop_node(phba, ndlp);
-+      lpfc_drop_node(vport, ndlp);
-       return NLP_STE_FREED_NODE;
- }
+ #endif
+ #endif
+diff -Nurb linux-2.6.22-590/drivers/net/tokenring/olympic.c linux-2.6.22-570/drivers/net/tokenring/olympic.c
+--- linux-2.6.22-590/drivers/net/tokenring/olympic.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/tokenring/olympic.c   2007-07-08 19:32:17.000000000 -0400
+@@ -101,7 +101,6 @@
+ #include <linux/bitops.h>
+ #include <linux/jiffies.h>
  
- static uint32_t
--lpfc_rcv_els_unused_node(struct lpfc_hba * phba,
--                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_els_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                       void *arg, uint32_t evt)
- {
--      lpfc_issue_els_logo(phba, ndlp, 0);
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
-+      lpfc_issue_els_logo(vport, ndlp, 0);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
-       return ndlp->nlp_state;
- }
+-#include <net/net_namespace.h>
+ #include <net/checksum.h>
  
- static uint32_t
--lpfc_rcv_logo_unused_node(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq     *cmdiocb;
--
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
+ #include <asm/io.h>
+@@ -269,9 +268,9 @@
+       printk("Olympic: %s registered as: %s\n",olympic_priv->olympic_card_name,dev->name);
+       if (olympic_priv->olympic_network_monitor) { /* Must go after register_netdev as we need the device name */ 
+               char proc_name[20] ; 
+-              strcpy(proc_name,"olympic_") ; 
++              strcpy(proc_name,"net/olympic_") ; 
+               strcat(proc_name,dev->name) ; 
+-              create_proc_read_entry(proc_name,0,init_net.proc_net,olympic_proc_info,(void *)dev) ; 
++              create_proc_read_entry(proc_name,0,NULL,olympic_proc_info,(void *)dev) ; 
+               printk("Olympic: Network Monitor information: /proc/%s\n",proc_name); 
+       }
+       return  0 ;
+@@ -1753,9 +1752,9 @@
  
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag |= NLP_LOGO_ACC;
--      spin_unlock_irq(phba->host->host_lock);
--      lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
-+      spin_unlock_irq(shost->host_lock);
-+      lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
+       if (olympic_priv->olympic_network_monitor) { 
+               char proc_name[20] ; 
+-              strcpy(proc_name,"olympic_") ; 
++              strcpy(proc_name,"net/olympic_") ; 
+               strcat(proc_name,dev->name) ;
+-              remove_proc_entry(proc_name,init_net.proc_net);
++              remove_proc_entry(proc_name,NULL); 
+       }
+       unregister_netdev(dev) ; 
+       iounmap(olympic_priv->olympic_mmio) ; 
+diff -Nurb linux-2.6.22-590/drivers/net/tulip/interrupt.c linux-2.6.22-570/drivers/net/tulip/interrupt.c
+--- linux-2.6.22-590/drivers/net/tulip/interrupt.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/tulip/interrupt.c     2007-07-08 19:32:17.000000000 -0400
+@@ -197,8 +197,8 @@
+                                                                  tp->rx_buffers[entry].mapping,
+                                                                  pkt_len, PCI_DMA_FROMDEVICE);
+ #if ! defined(__alpha__)
+-                                       skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
+-                                                        pkt_len);
++                                       eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
++                                                        pkt_len, 0);
+                                        skb_put(skb, pkt_len);
+ #else
+                                        memcpy(skb_put(skb, pkt_len),
+@@ -420,8 +420,8 @@
+                                                           tp->rx_buffers[entry].mapping,
+                                                           pkt_len, PCI_DMA_FROMDEVICE);
+ #if ! defined(__alpha__)
+-                              skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
+-                                               pkt_len);
++                              eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
++                                               pkt_len, 0);
+                               skb_put(skb, pkt_len);
+ #else
+                               memcpy(skb_put(skb, pkt_len),
+diff -Nurb linux-2.6.22-590/drivers/net/tulip/winbond-840.c linux-2.6.22-570/drivers/net/tulip/winbond-840.c
+--- linux-2.6.22-590/drivers/net/tulip/winbond-840.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/tulip/winbond-840.c   2007-07-08 19:32:17.000000000 -0400
+@@ -1232,7 +1232,7 @@
+                               pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry],
+                                                           np->rx_skbuff[entry]->len,
+                                                           PCI_DMA_FROMDEVICE);
+-                              skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
++                              eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0);
+                               skb_put(skb, pkt_len);
+                               pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry],
+                                                              np->rx_skbuff[entry]->len,
+diff -Nurb linux-2.6.22-590/drivers/net/tulip/xircom_cb.c linux-2.6.22-570/drivers/net/tulip/xircom_cb.c
+--- linux-2.6.22-590/drivers/net/tulip/xircom_cb.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/tulip/xircom_cb.c     2007-07-08 19:32:17.000000000 -0400
+@@ -1208,7 +1208,7 @@
+                               goto out;
+                       }
+                       skb_reserve(skb, 2);
+-                      skb_copy_to_linear_data(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len);
++                      eth_copy_and_sum(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len, 0);
+                       skb_put(skb, pkt_len);
+                       skb->protocol = eth_type_trans(skb, dev);
+                       netif_rx(skb);
+diff -Nurb linux-2.6.22-590/drivers/net/tulip/xircom_tulip_cb.c linux-2.6.22-570/drivers/net/tulip/xircom_tulip_cb.c
+--- linux-2.6.22-590/drivers/net/tulip/xircom_tulip_cb.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/tulip/xircom_tulip_cb.c       2007-07-08 19:32:17.000000000 -0400
+@@ -1242,8 +1242,8 @@
+                               && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+                               skb_reserve(skb, 2);    /* 16 byte align the IP header */
+ #if ! defined(__alpha__)
+-                              skb_copy_to_linear_data(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
+-                                                               pkt_len);
++                              eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
++                                                               pkt_len, 0);
+                               skb_put(skb, pkt_len);
+ #else
+                               memcpy(skb_put(skb, pkt_len),
+diff -Nurb linux-2.6.22-590/drivers/net/tun.c linux-2.6.22-570/drivers/net/tun.c
+--- linux-2.6.22-590/drivers/net/tun.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/tun.c 2007-07-08 19:32:17.000000000 -0400
+@@ -62,7 +62,6 @@
+ #include <linux/if_ether.h>
+ #include <linux/if_tun.h>
+ #include <linux/crc32.h>
+-#include <net/net_namespace.h>
  
-       return ndlp->nlp_state;
- }
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+@@ -433,7 +432,6 @@
+       init_waitqueue_head(&tun->read_wait);
  
- static uint32_t
--lpfc_cmpl_logo_unused_node(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                         void *arg, uint32_t evt)
- {
--      lpfc_drop_node(phba, ndlp);
-+      lpfc_drop_node(vport, ndlp);
-       return NLP_STE_FREED_NODE;
- }
+       tun->owner = -1;
+-      tun->group = -1;
  
- static uint32_t
--lpfc_device_rm_unused_node(struct lpfc_hba * phba,
--                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                         void *arg, uint32_t evt)
- {
--      lpfc_drop_node(phba, ndlp);
-+      lpfc_drop_node(vport, ndlp);
-       return NLP_STE_FREED_NODE;
- }
+       SET_MODULE_OWNER(dev);
+       dev->open = tun_net_open;
+@@ -469,14 +467,11 @@
+                       return -EBUSY;
  
- static uint32_t
--lpfc_rcv_plogi_plogi_issue(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
-+lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-                          void *arg, uint32_t evt)
- {
-+      struct lpfc_hba   *phba = vport->phba;
-       struct lpfc_iocbq *cmdiocb = arg;
--      struct lpfc_dmabuf *pcmd;
--      struct serv_parm *sp;
--      uint32_t *lp;
-+      struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
-+      uint32_t *lp = (uint32_t *) pcmd->virt;
-+      struct serv_parm *sp = (struct serv_parm *) (lp + 1);
-       struct ls_rjt stat;
-       int port_cmp;
+               /* Check permissions */
+-              if (((tun->owner != -1 &&
+-                    current->euid != tun->owner) ||
+-                   (tun->group != -1 &&
+-                    current->egid != tun->group)) &&
+-                   !capable(CAP_NET_ADMIN))
++              if (tun->owner != -1 &&
++                  current->euid != tun->owner && !capable(CAP_NET_ADMIN))
+                       return -EPERM;
+       }
+-      else if (__dev_get_by_name(&init_net, ifr->ifr_name))
++      else if (__dev_get_by_name(ifr->ifr_name))
+               return -EINVAL;
+       else {
+               char *name;
+@@ -615,13 +610,6 @@
+               DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner);
+               break;
  
--      pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
--      lp = (uint32_t *) pcmd->virt;
--      sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
+-      case TUNSETGROUP:
+-              /* Set group of the device */
+-              tun->group= (gid_t) arg;
 -
-       memset(&stat, 0, sizeof (struct ls_rjt));
+-              DBG(KERN_INFO "%s: group set to %d\n", tun->dev->name, tun->group);
+-              break;
+-
+       case TUNSETLINK:
+               /* Only allow setting the type when the interface is down */
+               if (tun->dev->flags & IFF_UP) {
+diff -Nurb linux-2.6.22-590/drivers/net/typhoon.c linux-2.6.22-570/drivers/net/typhoon.c
+--- linux-2.6.22-590/drivers/net/typhoon.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/typhoon.c     2007-07-08 19:32:17.000000000 -0400
+@@ -1703,7 +1703,7 @@
+                       pci_dma_sync_single_for_cpu(tp->pdev, dma_addr,
+                                                   PKT_BUF_SZ,
+                                                   PCI_DMA_FROMDEVICE);
+-                      skb_copy_to_linear_data(new_skb, skb->data, pkt_len);
++                      eth_copy_and_sum(new_skb, skb->data, pkt_len, 0);
+                       pci_dma_sync_single_for_device(tp->pdev, dma_addr,
+                                                      PKT_BUF_SZ,
+                                                      PCI_DMA_FROMDEVICE);
+diff -Nurb linux-2.6.22-590/drivers/net/usb/catc.c linux-2.6.22-570/drivers/net/usb/catc.c
+--- linux-2.6.22-590/drivers/net/usb/catc.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/usb/catc.c    2007-07-08 19:32:17.000000000 -0400
+@@ -255,7 +255,7 @@
+               if (!(skb = dev_alloc_skb(pkt_len)))
+                       return;
  
-       /* For a PLOGI, we only accept if our portname is less
-        * than the remote portname.
-        */
-       phba->fc_stat.elsLogiCol++;
--      port_cmp = memcmp(&phba->fc_portname, &sp->portName,
--                        sizeof (struct lpfc_name));
-+      port_cmp = memcmp(&vport->fc_portname, &sp->portName,
-+                        sizeof(struct lpfc_name));
+-              skb_copy_to_linear_data(skb, pkt_start + pkt_offset, pkt_len);
++              eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
+               skb_put(skb, pkt_len);
  
-       if (port_cmp >= 0) {
-               /* Reject this request because the remote node will accept
-                  ours */
-               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-               stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
--              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
-+              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
-+                      NULL);
-       } else {
--              lpfc_rcv_plogi(phba, ndlp, cmdiocb);
--      } /* if our portname was less */
-+              lpfc_rcv_plogi(vport, ndlp, cmdiocb);
-+      } /* If our portname was less */
+               skb->protocol = eth_type_trans(skb, catc->netdev);
+diff -Nurb linux-2.6.22-590/drivers/net/usb/kaweth.c linux-2.6.22-570/drivers/net/usb/kaweth.c
+--- linux-2.6.22-590/drivers/net/usb/kaweth.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/usb/kaweth.c  2007-07-08 19:32:17.000000000 -0400
+@@ -635,7 +635,7 @@
  
-       return ndlp->nlp_state;
- }
+               skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
  
- static uint32_t
--lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_prli_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq     *cmdiocb;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct ls_rjt     stat;
+-              skb_copy_to_linear_data(skb, kaweth->rx_buf + 2, pkt_len);
++              eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0);
  
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      memset(&stat, 0, sizeof (struct ls_rjt));
-+      stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
-+      stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
-+      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
-+      return ndlp->nlp_state;
-+}
-+
-+static uint32_t
-+lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
-+{
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
+               skb_put(skb, pkt_len);
  
-       /* software abort outstanding PLOGI */
--      lpfc_els_abort(phba, ndlp);
-+      lpfc_els_abort(vport->phba, ndlp);
+diff -Nurb linux-2.6.22-590/drivers/net/via-rhine.c linux-2.6.22-570/drivers/net/via-rhine.c
+--- linux-2.6.22-590/drivers/net/via-rhine.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/via-rhine.c   2007-07-08 19:32:17.000000000 -0400
+@@ -1492,9 +1492,9 @@
+                                                           rp->rx_buf_sz,
+                                                           PCI_DMA_FROMDEVICE);
  
--      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
-+      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
-       return ndlp->nlp_state;
- }
+-                              skb_copy_to_linear_data(skb,
++                              eth_copy_and_sum(skb,
+                                                rp->rx_skbuff[entry]->data,
+-                                               pkt_len);
++                                               pkt_len, 0);
+                               skb_put(skb, pkt_len);
+                               pci_dma_sync_single_for_device(rp->pdev,
+                                                              rp->rx_skbuff_dma[entry],
+diff -Nurb linux-2.6.22-590/drivers/net/wan/dlci.c linux-2.6.22-570/drivers/net/wan/dlci.c
+--- linux-2.6.22-590/drivers/net/wan/dlci.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/wan/dlci.c    2007-07-08 19:32:17.000000000 -0400
+@@ -361,7 +361,7 @@
  
- static uint32_t
--lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                       void *arg, uint32_t evt)
+       /* validate slave device */
+-      slave = dev_get_by_name(&init_net, dlci->devname);
++      slave = dev_get_by_name(dlci->devname);
+       if (!slave)
+               return -ENODEV;
+@@ -427,7 +427,7 @@
+       int                     err;
+       /* validate slave device */
+-      master = __dev_get_by_name(&init_net, dlci->devname);
++      master = __dev_get_by_name(dlci->devname);
+       if (!master)
+               return(-ENODEV);
+@@ -513,9 +513,6 @@
  {
--      struct lpfc_iocbq     *cmdiocb;
+       struct net_device *dev = (struct net_device *) ptr;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba   *phba = vport->phba;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
+       if (event == NETDEV_UNREGISTER) {
+               struct dlci_local *dlp;
  
-       /* software abort outstanding PLOGI */
-       lpfc_els_abort(phba, ndlp);
+diff -Nurb linux-2.6.22-590/drivers/net/wan/hdlc.c linux-2.6.22-570/drivers/net/wan/hdlc.c
+--- linux-2.6.22-590/drivers/net/wan/hdlc.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/wan/hdlc.c    2007-07-08 19:32:17.000000000 -0400
+@@ -36,7 +36,6 @@
+ #include <linux/rtnetlink.h>
+ #include <linux/notifier.h>
+ #include <linux/hdlc.h>
+-#include <net/net_namespace.h>
  
-       if (evt == NLP_EVT_RCV_LOGO) {
--              lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
-+              lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
-       } else {
--              lpfc_issue_els_logo(phba, ndlp, 0);
-+              lpfc_issue_els_logo(vport, ndlp, 0);
-       }
  
--      /* Put ndlp in npr list set plogi timer for 1 sec */
-+      /* Put ndlp in npr state set plogi timer for 1 sec */
-       mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag |= NLP_DELAY_TMO;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
-       ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
-       ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+ static const char* version = "HDLC support module revision 1.21";
+@@ -67,12 +66,6 @@
+                   struct packet_type *p, struct net_device *orig_dev)
+ {
+       struct hdlc_device_desc *desc = dev_to_desc(dev);
+-
+-      if (dev->nd_net != &init_net) {
+-              kfree_skb(skb);
+-              return 0;
+-      }
+-
+       if (desc->netif_rx)
+               return desc->netif_rx(skb);
  
-       return ndlp->nlp_state;
- }
+@@ -109,9 +102,6 @@
+       unsigned long flags;
+       int on;
+  
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       if (dev->get_stats != hdlc_get_stats)
+               return NOTIFY_DONE; /* not an HDLC device */
+  
+diff -Nurb linux-2.6.22-590/drivers/net/wan/lapbether.c linux-2.6.22-570/drivers/net/wan/lapbether.c
+--- linux-2.6.22-590/drivers/net/wan/lapbether.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/wan/lapbether.c       2007-07-08 19:32:17.000000000 -0400
+@@ -91,9 +91,6 @@
+       int len, err;
+       struct lapbethdev *lapbeth;
  
- static uint32_t
--lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
-+lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
-+                          struct lpfc_nodelist *ndlp,
-+                          void *arg,
-                           uint32_t evt)
- {
-+      struct lpfc_hba    *phba = vport->phba;
-       struct lpfc_iocbq *cmdiocb, *rspiocb;
-       struct lpfc_dmabuf *pcmd, *prsp, *mp;
-       uint32_t *lp;
-@@ -721,31 +772,26 @@
+-      if (dev->nd_net != &init_net)
+-              goto drop;
+-
+       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+               return NET_RX_DROP;
  
-       pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
+@@ -394,9 +391,6 @@
+       struct lapbethdev *lapbeth;
+       struct net_device *dev = ptr;
  
--      prsp = list_get_first(&pcmd->list,
--                            struct lpfc_dmabuf,
--                            list);
--      lp = (uint32_t *) prsp->virt;
-+      prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       if (!dev_is_ethdev(dev))
+               return NOTIFY_DONE;
  
-+      lp = (uint32_t *) prsp->virt;
-       sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
--      if (!lpfc_check_sparm(phba, ndlp, sp, CLASS3))
-+      if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3))
-               goto out;
+diff -Nurb linux-2.6.22-590/drivers/net/wan/sbni.c linux-2.6.22-570/drivers/net/wan/sbni.c
+--- linux-2.6.22-590/drivers/net/wan/sbni.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/wan/sbni.c    2007-07-08 19:32:17.000000000 -0400
+@@ -54,7 +54,6 @@
+ #include <linux/init.h>
+ #include <linux/delay.h>
  
-       /* PLOGI chkparm OK */
--      lpfc_printf_log(phba,
--                      KERN_INFO,
--                      LOG_ELS,
--                      "%d:0121 PLOGI chkparm OK "
-+      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-+                      "%d (%d):0121 PLOGI chkparm OK "
-                       "Data: x%x x%x x%x x%x\n",
--                      phba->brd_no,
-+                      phba->brd_no, vport->vpi,
-                       ndlp->nlp_DID, ndlp->nlp_state,
-                       ndlp->nlp_flag, ndlp->nlp_rpi);
+-#include <net/net_namespace.h>
+ #include <net/arp.h>
  
--      if ((phba->cfg_fcp_class == 2) &&
--          (sp->cls2.classValid)) {
-+      if (phba->cfg_fcp_class == 2 && (sp->cls2.classValid))
-               ndlp->nlp_fcp_info |= CLASS2;
--      } else {
-+      else
-               ndlp->nlp_fcp_info |= CLASS3;
--      }
-+
-       ndlp->nlp_class_sup = 0;
-       if (sp->cls1.classValid)
-               ndlp->nlp_class_sup |= FC_COS_CLASS1;
-@@ -756,16 +802,23 @@
-       if (sp->cls4.classValid)
-               ndlp->nlp_class_sup |= FC_COS_CLASS4;
-       ndlp->nlp_maxframe =
--              ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
--              sp->cmn.bbRcvSizeLsb;
-+              ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
+ #include <asm/io.h>
+@@ -1363,7 +1362,7 @@
  
--      if (!(mbox = mempool_alloc(phba->mbox_mem_pool,
--                                 GFP_KERNEL)))
-+      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (!mbox) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                      "%d (%d):0133 PLOGI: no memory for reg_login "
-+                      "Data: x%x x%x x%x x%x\n",
-+                      phba->brd_no, vport->vpi,
-+                      ndlp->nlp_DID, ndlp->nlp_state,
-+                      ndlp->nlp_flag, ndlp->nlp_rpi);
-               goto out;
-+      }
-+
-+      lpfc_unreg_rpi(vport, ndlp);
+               if (copy_from_user( slave_name, ifr->ifr_data, sizeof slave_name ))
+                       return -EFAULT;
+-              slave_dev = dev_get_by_name(&init_net, slave_name );
++              slave_dev = dev_get_by_name( slave_name );
+               if( !slave_dev  ||  !(slave_dev->flags & IFF_UP) ) {
+                       printk( KERN_ERR "%s: trying to enslave non-active "
+                               "device %s\n", dev->name, slave_name );
+diff -Nurb linux-2.6.22-590/drivers/net/wan/syncppp.c linux-2.6.22-570/drivers/net/wan/syncppp.c
+--- linux-2.6.22-590/drivers/net/wan/syncppp.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/wan/syncppp.c 2007-07-08 19:32:17.000000000 -0400
+@@ -51,7 +51,6 @@
+ #include <linux/spinlock.h>
+ #include <linux/rcupdate.h>
  
--      lpfc_unreg_rpi(phba, ndlp);
--      if (lpfc_reg_login(phba, irsp->un.elsreq64.remoteID, (uint8_t *) sp,
--                         mbox, 0) == 0) {
-+      if (lpfc_reg_login(phba, vport->vpi, irsp->un.elsreq64.remoteID,
-+                         (uint8_t *) sp, mbox, 0) == 0) {
-               switch (ndlp->nlp_DID) {
-               case NameServer_DID:
-                       mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login;
-@@ -777,68 +830,104 @@
-                       mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
-               }
-               mbox->context2 = lpfc_nlp_get(ndlp);
-+              mbox->vport = vport;
-               if (lpfc_sli_issue_mbox(phba, mbox,
-                                       (MBX_NOWAIT | MBX_STOP_IOCB))
-                   != MBX_NOT_FINISHED) {
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
-+                      lpfc_nlp_set_state(vport, ndlp,
-+                                         NLP_STE_REG_LOGIN_ISSUE);
-                       return ndlp->nlp_state;
-               }
-               lpfc_nlp_put(ndlp);
--              mp = (struct lpfc_dmabuf *)mbox->context1;
-+              mp = (struct lpfc_dmabuf *) mbox->context1;
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
-               mempool_free(mbox, phba->mbox_mem_pool);
-+
-+              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                      "%d (%d):0134 PLOGI: cannot issue reg_login "
-+                      "Data: x%x x%x x%x x%x\n",
-+                      phba->brd_no, vport->vpi,
-+                      ndlp->nlp_DID, ndlp->nlp_state,
-+                      ndlp->nlp_flag, ndlp->nlp_rpi);
-       } else {
-               mempool_free(mbox, phba->mbox_mem_pool);
-+
-+              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                      "%d (%d):0135 PLOGI: cannot format reg_login "
-+                      "Data: x%x x%x x%x x%x\n",
-+                      phba->brd_no, vport->vpi,
-+                      ndlp->nlp_DID, ndlp->nlp_state,
-+                      ndlp->nlp_flag, ndlp->nlp_rpi);
-       }
+-#include <net/net_namespace.h>
+ #include <net/syncppp.h>
  
+ #include <asm/byteorder.h>
+@@ -1446,11 +1445,6 @@
  
-- out:
-+out:
-+      if (ndlp->nlp_DID == NameServer_DID) {
-+              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-+              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                      "%d (%d):0261 Cannot Register NameServer login\n",
-+                      phba->brd_no, vport->vpi);
-+      }
-+
-       /* Free this node since the driver cannot login or has the wrong
-          sparm */
--      lpfc_drop_node(phba, ndlp);
-+      lpfc_drop_node(vport, ndlp);
-       return NLP_STE_FREED_NODE;
- }
+ static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev)
+ {
+-      if (dev->nd_net != &init_net) {
+-              kfree_skb(skb);
+-              return 0;
+-      }
+-
+       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+               return NET_RX_DROP;
+       sppp_input(dev,skb);
+diff -Nurb linux-2.6.22-590/drivers/net/wireless/airo.c linux-2.6.22-570/drivers/net/wireless/airo.c
+--- linux-2.6.22-590/drivers/net/wireless/airo.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/wireless/airo.c       2007-07-08 19:32:17.000000000 -0400
+@@ -3079,7 +3079,6 @@
+       struct airo_info *ai = dev->priv;
+       int locked;
+       
+-      set_freezable();
+       while(1) {
+               /* make swsusp happy with our thread */
+               try_to_freeze();
+diff -Nurb linux-2.6.22-590/drivers/net/wireless/hostap/hostap_main.c linux-2.6.22-570/drivers/net/wireless/hostap/hostap_main.c
+--- linux-2.6.22-590/drivers/net/wireless/hostap/hostap_main.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/wireless/hostap/hostap_main.c 2007-07-08 19:32:17.000000000 -0400
+@@ -24,7 +24,6 @@
+ #include <linux/rtnetlink.h>
+ #include <linux/wireless.h>
+ #include <linux/etherdevice.h>
+-#include <net/net_namespace.h>
+ #include <net/iw_handler.h>
+ #include <net/ieee80211.h>
+ #include <net/ieee80211_crypt.h>
+@@ -1095,8 +1094,8 @@
  
- static uint32_t
--lpfc_device_rm_plogi_issue(struct lpfc_hba * phba,
--                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_device_rm_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                         void *arg, uint32_t evt)
+ static int __init hostap_init(void)
  {
--      if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-+      if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
-+              spin_unlock_irq(shost->host_lock);
-               return ndlp->nlp_state;
--      }
--      else {
-+      } else {
-               /* software abort outstanding PLOGI */
--              lpfc_els_abort(phba, ndlp);
-+              lpfc_els_abort(vport->phba, ndlp);
--              lpfc_drop_node(phba, ndlp);
-+              lpfc_drop_node(vport, ndlp);
-               return NLP_STE_FREED_NODE;
+-      if (init_net.proc_net != NULL) {
+-              hostap_proc = proc_mkdir("hostap", init_net.proc_net);
++      if (proc_net != NULL) {
++              hostap_proc = proc_mkdir("hostap", proc_net);
+               if (!hostap_proc)
+                       printk(KERN_WARNING "Failed to mkdir "
+                              "/proc/net/hostap\n");
+@@ -1111,7 +1110,7 @@
+ {
+       if (hostap_proc != NULL) {
+               hostap_proc = NULL;
+-              remove_proc_entry("hostap", init_net.proc_net);
++              remove_proc_entry("hostap", proc_net);
        }
  }
  
- static uint32_t
--lpfc_device_recov_plogi_issue(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
-+lpfc_device_recov_plogi_issue(struct lpfc_vport *vport,
-+                            struct lpfc_nodelist *ndlp,
-+                            void *arg,
-                           uint32_t evt)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-+
-+      /* Don't do anything that will mess up processing of the
-+       * previous RSCN.
-+       */
-+      if (vport->fc_flag & FC_RSCN_DEFERRED)
-+              return ndlp->nlp_state;
-+
-       /* software abort outstanding PLOGI */
-       lpfc_els_abort(phba, ndlp);
+diff -Nurb linux-2.6.22-590/drivers/net/wireless/libertas/main.c linux-2.6.22-570/drivers/net/wireless/libertas/main.c
+--- linux-2.6.22-590/drivers/net/wireless/libertas/main.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/wireless/libertas/main.c      2007-07-08 19:32:17.000000000 -0400
+@@ -613,7 +613,6 @@
  
-       ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
--      spin_lock_irq(phba->host->host_lock);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
+       init_waitqueue_entry(&wait, current);
  
-       return ndlp->nlp_state;
- }
+-      set_freezable();
+       for (;;) {
+               lbs_deb_thread( "main-thread 111: intcounter=%d "
+                      "currenttxskb=%p dnld_sent=%d\n",
+diff -Nurb linux-2.6.22-590/drivers/net/wireless/strip.c linux-2.6.22-570/drivers/net/wireless/strip.c
+--- linux-2.6.22-590/drivers/net/wireless/strip.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/wireless/strip.c      2007-07-08 19:32:17.000000000 -0400
+@@ -107,7 +107,6 @@
+ #include <linux/serialP.h>
+ #include <linux/rcupdate.h>
+ #include <net/arp.h>
+-#include <net/net_namespace.h>
  
- static uint32_t
--lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                         void *arg, uint32_t evt)
- {
-+      struct lpfc_hba   *phba = vport->phba;
-       struct lpfc_iocbq *cmdiocb;
+ #include <linux/ip.h>
+ #include <linux/tcp.h>
+@@ -1972,7 +1971,7 @@
+                     sizeof(zero_address))) {
+               struct net_device *dev;
+               read_lock_bh(&dev_base_lock);
+-              for_each_netdev(&init_net, dev) {
++              for_each_netdev(dev) {
+                       if (dev->type == strip_info->dev->type &&
+                           !memcmp(dev->dev_addr,
+                                   &strip_info->true_dev_addr,
+@@ -2788,7 +2787,7 @@
+       /*
+        * Register the status file with /proc
+        */
+-      proc_net_fops_create(&init_net, "strip", S_IFREG | S_IRUGO, &strip_seq_fops);
++      proc_net_fops_create("strip", S_IFREG | S_IRUGO, &strip_seq_fops);
  
-       /* software abort outstanding ADISC */
-@@ -846,34 +935,31 @@
+       return status;
+ }
+@@ -2810,7 +2809,7 @@
+       }
  
-       cmdiocb = (struct lpfc_iocbq *) arg;
+       /* Unregister with the /proc/net file here. */
+-      proc_net_remove(&init_net, "strip");
++      proc_net_remove("strip");
  
--      if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
-+      if (lpfc_rcv_plogi(vport, ndlp, cmdiocb))
-               return ndlp->nlp_state;
+       if ((i = tty_unregister_ldisc(N_STRIP)))
+               printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i);
+diff -Nurb linux-2.6.22-590/drivers/net/wireless/wl3501_cs.c linux-2.6.22-570/drivers/net/wireless/wl3501_cs.c
+--- linux-2.6.22-590/drivers/net/wireless/wl3501_cs.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/wireless/wl3501_cs.c  2007-07-08 19:32:17.000000000 -0400
+@@ -1011,7 +1011,7 @@
+       } else {
+               skb->dev = dev;
+               skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */
+-              skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12);
++              eth_copy_and_sum(skb, (unsigned char *)&sig.daddr, 12, 0);
+               wl3501_receive(this, skb->data, pkt_len);
+               skb_put(skb, pkt_len);
+               skb->protocol   = eth_type_trans(skb, dev);
+diff -Nurb linux-2.6.22-590/drivers/net/xen-netfront.c linux-2.6.22-570/drivers/net/xen-netfront.c
+--- linux-2.6.22-590/drivers/net/xen-netfront.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/xen-netfront.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,1995 +0,0 @@
+-/*
+- * Virtual network driver for conversing with remote driver backends.
+- *
+- * Copyright (c) 2002-2005, K A Fraser
+- * Copyright (c) 2005, XenSource Ltd
+- *
+- * 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; or, when distributed
+- * separately from the Linux kernel or incorporated into other
+- * software packages, subject to the following license:
+- *
+- * Permission is hereby granted, free of charge, to any person obtaining a copy
+- * of this source file (the "Software"), to deal in the Software without
+- * restriction, including without limitation the rights to use, copy, modify,
+- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+- * and to permit persons to whom the Software is furnished to do so, subject to
+- * the following conditions:
+- *
+- * The above copyright notice and this permission notice shall be included in
+- * all copies or substantial portions of the Software.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+- * IN THE SOFTWARE.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/netdevice.h>
+-#include <linux/etherdevice.h>
+-#include <linux/skbuff.h>
+-#include <linux/ethtool.h>
+-#include <linux/if_ether.h>
+-#include <linux/tcp.h>
+-#include <linux/udp.h>
+-#include <linux/moduleparam.h>
+-#include <linux/mm.h>
+-#include <net/ip.h>
+-
+-#include <xen/xenbus.h>
+-#include <xen/events.h>
+-#include <xen/page.h>
+-#include <xen/grant_table.h>
+-
+-#include <xen/interface/io/netif.h>
+-#include <xen/interface/memory.h>
+-#include <xen/interface/grant_table.h>
+-
+-static struct ethtool_ops xennet_ethtool_ops;
+-
+-struct netfront_cb {
+-      struct page *page;
+-      unsigned offset;
+-};
+-
+-#define NETFRONT_SKB_CB(skb)  ((struct netfront_cb *)((skb)->cb))
+-
+-/*
+- * Mutually-exclusive module options to select receive data path:
+- *  copy : Packets are copied by network backend into local memory
+- *  flip : Page containing packet data is transferred to our ownership
+- * For fully-virtualised guests there is no option - copying must be used.
+- * For paravirtualised guests, flipping is the default.
+- */
+-typedef enum rx_mode {
+-      RX_COPY = 0,
+-      RX_FLIP = 1,
+-} rx_mode_t;
+-
+-static enum rx_mode rx_mode = RX_FLIP;
+-
+-#define param_check_rx_mode_t(name, p) __param_check(name, p, rx_mode_t)
+-
+-static int param_set_rx_mode_t(const char *val, struct kernel_param *kp)
+-{
+-      enum rx_mode *rxmp = kp->arg;
+-      int ret = 0;
+-
+-      if (strcmp(val, "copy") == 0)
+-              *rxmp = RX_COPY;
+-      else if (strcmp(val, "flip") == 0)
+-              *rxmp = RX_FLIP;
+-      else
+-              ret = -EINVAL;
+-
+-      return ret;
+-}
+-
+-static int param_get_rx_mode_t(char *buffer, struct kernel_param *kp)
+-{
+-      enum rx_mode *rxmp = kp->arg;
+-
+-      return sprintf(buffer, "%s", *rxmp == RX_COPY ? "copy" : "flip");
+-}
+-
+-MODULE_PARM_DESC(rx_mode, "How to get packets from card: \"copy\" or \"flip\"");
+-module_param(rx_mode, rx_mode_t, 0400);
+-
+-#define RX_COPY_THRESHOLD 256
+-
+-#define GRANT_INVALID_REF     0
+-
+-#define NET_TX_RING_SIZE __RING_SIZE((struct xen_netif_tx_sring *)0, PAGE_SIZE)
+-#define NET_RX_RING_SIZE __RING_SIZE((struct xen_netif_rx_sring *)0, PAGE_SIZE)
+-#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+-
+-struct netfront_info {
+-      struct list_head list;
+-      struct net_device *netdev;
+-
+-      struct net_device_stats stats;
+-
+-      struct xen_netif_tx_front_ring tx;
+-      struct xen_netif_rx_front_ring rx;
+-
+-      spinlock_t   tx_lock;
+-      spinlock_t   rx_lock;
+-
+-      unsigned int evtchn;
+-      unsigned int copying_receiver;
+-
+-      /* Receive-ring batched refills. */
+-#define RX_MIN_TARGET 8
+-#define RX_DFL_MIN_TARGET 64
+-#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+-      unsigned rx_min_target, rx_max_target, rx_target;
+-      struct sk_buff_head rx_batch;
+-
+-      struct timer_list rx_refill_timer;
+-
+-      /*
+-       * {tx,rx}_skbs store outstanding skbuffs. Free tx_skb entries
+-       * are linked from tx_skb_freelist through skb_entry.link.
+-       *
+-       *  NB. Freelist index entries are always going to be less than
+-       *  PAGE_OFFSET, whereas pointers to skbs will always be equal or
+-       *  greater than PAGE_OFFSET: we use this property to distinguish
+-       *  them.
+-       */
+-      union skb_entry {
+-              struct sk_buff *skb;
+-              unsigned link;
+-      } tx_skbs[NET_TX_RING_SIZE];;
+-      grant_ref_t gref_tx_head;
+-      grant_ref_t grant_tx_ref[NET_TX_RING_SIZE];
+-      unsigned tx_skb_freelist;
+-
+-      struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
+-      grant_ref_t gref_rx_head;
+-      grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
+-
+-      struct xenbus_device *xbdev;
+-      int tx_ring_ref;
+-      int rx_ring_ref;
+-
+-      unsigned long rx_pfn_array[NET_RX_RING_SIZE];
+-      struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1];
+-      struct mmu_update rx_mmu[NET_RX_RING_SIZE];
+-};
+-
+-struct netfront_rx_info {
+-      struct xen_netif_rx_response rx;
+-      struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
+-};
+-
+-/*
+- * Access macros for acquiring freeing slots in tx_skbs[].
+- */
+-
+-static void add_id_to_freelist(unsigned *head, union skb_entry *list, unsigned short id)
+-{
+-      list[id].link = *head;
+-      *head = id;
+-}
+-
+-static unsigned short get_id_from_freelist(unsigned *head, union skb_entry *list)
+-{
+-      unsigned int id = *head;
+-      *head = list[id].link;
+-      return id;
+-}
+-
+-static int xennet_rxidx(RING_IDX idx)
+-{
+-      return idx & (NET_RX_RING_SIZE - 1);
+-}
+-
+-static struct sk_buff *xennet_get_rx_skb(struct netfront_info *np,
+-                                       RING_IDX ri)
+-{
+-      int i = xennet_rxidx(ri);
+-      struct sk_buff *skb = np->rx_skbs[i];
+-      np->rx_skbs[i] = NULL;
+-      return skb;
+-}
+-
+-static grant_ref_t xennet_get_rx_ref(struct netfront_info *np,
+-                                          RING_IDX ri)
+-{
+-      int i = xennet_rxidx(ri);
+-      grant_ref_t ref = np->grant_rx_ref[i];
+-      np->grant_rx_ref[i] = GRANT_INVALID_REF;
+-      return ref;
+-}
+-
+-#ifdef CONFIG_SYSFS
+-static int xennet_sysfs_addif(struct net_device *netdev);
+-static void xennet_sysfs_delif(struct net_device *netdev);
+-#else /* !CONFIG_SYSFS */
+-#define xennet_sysfs_addif(dev) (0)
+-#define xennet_sysfs_delif(dev) do { } while(0)
+-#endif
+-
+-static int xennet_can_sg(struct net_device *dev)
+-{
+-      return dev->features & NETIF_F_SG;
+-}
+-
+-
+-static void rx_refill_timeout(unsigned long data)
+-{
+-      struct net_device *dev = (struct net_device *)data;
+-      netif_rx_schedule(dev);
+-}
+-
+-static int netfront_tx_slot_available(struct netfront_info *np)
+-{
+-      return ((np->tx.req_prod_pvt - np->tx.rsp_cons) <
+-              (TX_MAX_TARGET - MAX_SKB_FRAGS - 2));
+-}
+-
+-static void xennet_maybe_wake_tx(struct net_device *dev)
+-{
+-      struct netfront_info *np = netdev_priv(dev);
+-
+-      if (unlikely(netif_queue_stopped(dev)) &&
+-          netfront_tx_slot_available(np) &&
+-          likely(netif_running(dev)))
+-              netif_wake_queue(dev);
+-}
+-
+-static void xennet_alloc_rx_buffers(struct net_device *dev)
+-{
+-      unsigned short id;
+-      struct netfront_info *np = netdev_priv(dev);
+-      struct sk_buff *skb;
+-      struct page *page;
+-      int i, batch_target, notify;
+-      RING_IDX req_prod = np->rx.req_prod_pvt;
+-      struct xen_memory_reservation reservation;
+-      grant_ref_t ref;
+-      unsigned long pfn;
+-      void *vaddr;
+-      int nr_flips;
+-      struct xen_netif_rx_request *req;
+-
+-      if (unlikely(!netif_carrier_ok(dev)))
+-              return;
+-
+-      /*
+-       * Allocate skbuffs greedily, even though we batch updates to the
+-       * receive ring. This creates a less bursty demand on the memory
+-       * allocator, so should reduce the chance of failed allocation requests
+-       * both for ourself and for other kernel subsystems.
+-       */
+-      batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
+-      for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
+-              skb = __netdev_alloc_skb(dev, RX_COPY_THRESHOLD,
+-                                       GFP_ATOMIC | __GFP_NOWARN);
+-              if (unlikely(!skb))
+-                      goto no_skb;
+-
+-              page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
+-              if (!page) {
+-                      kfree_skb(skb);
+-no_skb:
+-                      /* Any skbuffs queued for refill? Force them out. */
+-                      if (i != 0)
+-                              goto refill;
+-                      /* Could not allocate any skbuffs. Try again later. */
+-                      mod_timer(&np->rx_refill_timer,
+-                                jiffies + (HZ/10));
+-                      break;
+-              }
+-
+-              skb_shinfo(skb)->frags[0].page = page;
+-              skb_shinfo(skb)->nr_frags = 1;
+-              __skb_queue_tail(&np->rx_batch, skb);
+-      }
+-
+-      /* Is the batch large enough to be worthwhile? */
+-      if (i < (np->rx_target/2)) {
+-              if (req_prod > np->rx.sring->req_prod)
+-                      goto push;
+-              return;
+-      }
+-
+-      /* Adjust our fill target if we risked running out of buffers. */
+-      if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) &&
+-          ((np->rx_target *= 2) > np->rx_max_target))
+-              np->rx_target = np->rx_max_target;
+-
+- refill:
+-      for (nr_flips = i = 0; ; i++) {
+-              if ((skb = __skb_dequeue(&np->rx_batch)) == NULL)
+-                      break;
+-
+-              skb->dev = dev;
+-
+-              id = xennet_rxidx(req_prod + i);
+-
+-              BUG_ON(np->rx_skbs[id]);
+-              np->rx_skbs[id] = skb;
+-
+-              ref = gnttab_claim_grant_reference(&np->gref_rx_head);
+-              BUG_ON((signed short)ref < 0);
+-              np->grant_rx_ref[id] = ref;
+-
+-              pfn = page_to_pfn(skb_shinfo(skb)->frags[0].page);
+-              vaddr = page_address(skb_shinfo(skb)->frags[0].page);
+-
+-              req = RING_GET_REQUEST(&np->rx, req_prod + i);
+-              if (!np->copying_receiver) {
+-                      gnttab_grant_foreign_transfer_ref(ref,
+-                                                        np->xbdev->otherend_id,
+-                                                        pfn);
+-                      np->rx_pfn_array[nr_flips] = pfn_to_mfn(pfn);
+-                      if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+-                              /* Remove this page before passing
+-                               * back to Xen. */
+-                              set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+-                              MULTI_update_va_mapping(np->rx_mcl+i,
+-                                                      (unsigned long)vaddr,
+-                                                      __pte(0), 0);
+-                      }
+-                      nr_flips++;
+-              } else {
+-                      gnttab_grant_foreign_access_ref(ref,
+-                                                      np->xbdev->otherend_id,
+-                                                      pfn_to_mfn(pfn),
+-                                                      0);
+-              }
+-
+-              req->id = id;
+-              req->gref = ref;
+-      }
+-
+-      if (nr_flips != 0) {
+-              reservation.extent_start = np->rx_pfn_array;
+-              reservation.nr_extents   = nr_flips;
+-              reservation.extent_order = 0;
+-              reservation.address_bits = 0;
+-              reservation.domid        = DOMID_SELF;
+-
+-              if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+-                      /* After all PTEs have been zapped, flush the TLB. */
+-                      np->rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] =
+-                              UVMF_TLB_FLUSH|UVMF_ALL;
+-
+-                      /* Give away a batch of pages. */
+-                      np->rx_mcl[i].op = __HYPERVISOR_memory_op;
+-                      np->rx_mcl[i].args[0] = XENMEM_decrease_reservation;
+-                      np->rx_mcl[i].args[1] = (unsigned long)&reservation;
+-
+-                      /* Zap PTEs and give away pages in one big
+-                       * multicall. */
+-                      (void)HYPERVISOR_multicall(np->rx_mcl, i+1);
+-
+-                      /* Check return status of HYPERVISOR_memory_op(). */
+-                      if (unlikely(np->rx_mcl[i].result != i))
+-                              panic("Unable to reduce memory reservation\n");
+-              } else {
+-                      if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+-                                               &reservation) != i)
+-                              panic("Unable to reduce memory reservation\n");
+-              }
+-      } else {
+-              wmb();
+-      }
+-
+-      /* Above is a suitable barrier to ensure backend will see requests. */
+-      np->rx.req_prod_pvt = req_prod + i;
+- push:
+-      RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
+-      if (notify)
+-              notify_remote_via_irq(np->netdev->irq);
+-}
+-
+-static int xennet_open(struct net_device *dev)
+-{
+-      struct netfront_info *np = netdev_priv(dev);
+-
+-      memset(&np->stats, 0, sizeof(np->stats));
+-
+-      spin_lock_bh(&np->rx_lock);
+-      if (netif_carrier_ok(dev)) {
+-              xennet_alloc_rx_buffers(dev);
+-              np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
+-              if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
+-                      netif_rx_schedule(dev);
+-      }
+-      spin_unlock_bh(&np->rx_lock);
+-
+-      xennet_maybe_wake_tx(dev);
+-
+-      return 0;
+-}
+-
+-static void xennet_tx_buf_gc(struct net_device *dev)
+-{
+-      RING_IDX cons, prod;
+-      unsigned short id;
+-      struct netfront_info *np = netdev_priv(dev);
+-      struct sk_buff *skb;
+-
+-      BUG_ON(!netif_carrier_ok(dev));
+-
+-      do {
+-              prod = np->tx.sring->rsp_prod;
+-              rmb(); /* Ensure we see responses up to 'rp'. */
+-
+-              for (cons = np->tx.rsp_cons; cons != prod; cons++) {
+-                      struct xen_netif_tx_response *txrsp;
+-
+-                      txrsp = RING_GET_RESPONSE(&np->tx, cons);
+-                      if (txrsp->status == NETIF_RSP_NULL)
+-                              continue;
+-
+-                      id  = txrsp->id;
+-                      skb = np->tx_skbs[id].skb;
+-                      if (unlikely(gnttab_query_foreign_access(
+-                              np->grant_tx_ref[id]) != 0)) {
+-                              printk(KERN_ALERT "xennet_tx_buf_gc: warning "
+-                                     "-- grant still in use by backend "
+-                                     "domain.\n");
+-                              BUG();
+-                      }
+-                      gnttab_end_foreign_access_ref(
+-                              np->grant_tx_ref[id], GNTMAP_readonly);
+-                      gnttab_release_grant_reference(
+-                              &np->gref_tx_head, np->grant_tx_ref[id]);
+-                      np->grant_tx_ref[id] = GRANT_INVALID_REF;
+-                      add_id_to_freelist(&np->tx_skb_freelist, np->tx_skbs, id);
+-                      dev_kfree_skb_irq(skb);
+-              }
+-
+-              np->tx.rsp_cons = prod;
+-
+-              /*
+-               * Set a new event, then check for race with update of tx_cons.
+-               * Note that it is essential to schedule a callback, no matter
+-               * how few buffers are pending. Even if there is space in the
+-               * transmit ring, higher layers may be blocked because too much
+-               * data is outstanding: in such cases notification from Xen is
+-               * likely to be the only kick that we'll get.
+-               */
+-              np->tx.sring->rsp_event =
+-                      prod + ((np->tx.sring->req_prod - prod) >> 1) + 1;
+-              mb();
+-      } while ((cons == prod) && (prod != np->tx.sring->rsp_prod));
+-
+-      xennet_maybe_wake_tx(dev);
+-}
+-
+-static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
+-                            struct xen_netif_tx_request *tx)
+-{
+-      struct netfront_info *np = netdev_priv(dev);
+-      char *data = skb->data;
+-      unsigned long mfn;
+-      RING_IDX prod = np->tx.req_prod_pvt;
+-      int frags = skb_shinfo(skb)->nr_frags;
+-      unsigned int offset = offset_in_page(data);
+-      unsigned int len = skb_headlen(skb);
+-      unsigned int id;
+-      grant_ref_t ref;
+-      int i;
+-
+-      /* While the header overlaps a page boundary (including being
+-         larger than a page), split it it into page-sized chunks. */
+-      while (len > PAGE_SIZE - offset) {
+-              tx->size = PAGE_SIZE - offset;
+-              tx->flags |= NETTXF_more_data;
+-              len -= tx->size;
+-              data += tx->size;
+-              offset = 0;
+-
+-              id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
+-              np->tx_skbs[id].skb = skb_get(skb);
+-              tx = RING_GET_REQUEST(&np->tx, prod++);
+-              tx->id = id;
+-              ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+-              BUG_ON((signed short)ref < 0);
+-
+-              mfn = virt_to_mfn(data);
+-              gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
+-                                              mfn, GNTMAP_readonly);
+-
+-              tx->gref = np->grant_tx_ref[id] = ref;
+-              tx->offset = offset;
+-              tx->size = len;
+-              tx->flags = 0;
+-      }
+-
+-      /* Grant backend access to each skb fragment page. */
+-      for (i = 0; i < frags; i++) {
+-              skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+-
+-              tx->flags |= NETTXF_more_data;
+-
+-              id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
+-              np->tx_skbs[id].skb = skb_get(skb);
+-              tx = RING_GET_REQUEST(&np->tx, prod++);
+-              tx->id = id;
+-              ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+-              BUG_ON((signed short)ref < 0);
+-
+-              mfn = pfn_to_mfn(page_to_pfn(frag->page));
+-              gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
+-                                              mfn, GNTMAP_readonly);
+-
+-              tx->gref = np->grant_tx_ref[id] = ref;
+-              tx->offset = frag->page_offset;
+-              tx->size = frag->size;
+-              tx->flags = 0;
+-      }
+-
+-      np->tx.req_prod_pvt = prod;
+-}
+-
+-static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+-{
+-      unsigned short id;
+-      struct netfront_info *np = netdev_priv(dev);
+-      struct xen_netif_tx_request *tx;
+-      struct xen_netif_extra_info *extra;
+-      char *data = skb->data;
+-      RING_IDX i;
+-      grant_ref_t ref;
+-      unsigned long mfn;
+-      int notify;
+-      int frags = skb_shinfo(skb)->nr_frags;
+-      unsigned int offset = offset_in_page(data);
+-      unsigned int len = skb_headlen(skb);
+-
+-      frags += (offset + len + PAGE_SIZE - 1) / PAGE_SIZE;
+-      if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
+-              printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
+-                     frags);
+-              dump_stack();
+-              goto drop;
+-      }
+-
+-      spin_lock_irq(&np->tx_lock);
+-
+-      if (unlikely(!netif_carrier_ok(dev) ||
+-                   (frags > 1 && !xennet_can_sg(dev)) ||
+-                   netif_needs_gso(dev, skb))) {
+-              spin_unlock_irq(&np->tx_lock);
+-              goto drop;
+-      }
+-
+-      i = np->tx.req_prod_pvt;
+-
+-      id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
+-      np->tx_skbs[id].skb = skb;
+-
+-      tx = RING_GET_REQUEST(&np->tx, i);
+-
+-      tx->id   = id;
+-      ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+-      BUG_ON((signed short)ref < 0);
+-      mfn = virt_to_mfn(data);
+-      gnttab_grant_foreign_access_ref(
+-              ref, np->xbdev->otherend_id, mfn, GNTMAP_readonly);
+-      tx->gref = np->grant_tx_ref[id] = ref;
+-      tx->offset = offset;
+-      tx->size = len;
+-      extra = NULL;
+-
+-      tx->flags = 0;
+-      if (skb->ip_summed == CHECKSUM_PARTIAL)
+-              /* local packet? */
+-              tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
+-      else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+-              /* remote but checksummed. */
+-              tx->flags |= NETTXF_data_validated;
+-
+-      if (skb_shinfo(skb)->gso_size) {
+-              struct xen_netif_extra_info *gso;
+-
+-              gso = (struct xen_netif_extra_info *)
+-                      RING_GET_REQUEST(&np->tx, ++i);
+-
+-              if (extra)
+-                      extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
+-              else
+-                      tx->flags |= NETTXF_extra_info;
+-
+-              gso->u.gso.size = skb_shinfo(skb)->gso_size;
+-              gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
+-              gso->u.gso.pad = 0;
+-              gso->u.gso.features = 0;
+-
+-              gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
+-              gso->flags = 0;
+-              extra = gso;
+-      }
+-
+-      np->tx.req_prod_pvt = i + 1;
+-
+-      xennet_make_frags(skb, dev, tx);
+-      tx->size = skb->len;
+-
+-      RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->tx, notify);
+-      if (notify)
+-              notify_remote_via_irq(np->netdev->irq);
+-
+-      xennet_tx_buf_gc(dev);
+-
+-      if (!netfront_tx_slot_available(np))
+-              netif_stop_queue(dev);
+-
+-      spin_unlock_irq(&np->tx_lock);
+-
+-      np->stats.tx_bytes += skb->len;
+-      np->stats.tx_packets++;
+-
+-      return 0;
+-
+- drop:
+-      np->stats.tx_dropped++;
+-      dev_kfree_skb(skb);
+-      return 0;
+-}
+-
+-static int xennet_close(struct net_device *dev)
+-{
+-      struct netfront_info *np = netdev_priv(dev);
+-      netif_stop_queue(np->netdev);
+-      return 0;
+-}
+-
+-static struct net_device_stats *xennet_get_stats(struct net_device *dev)
+-{
+-      struct netfront_info *np = netdev_priv(dev);
+-      return &np->stats;
+-}
+-
+-static void xennet_move_rx_slot(struct netfront_info *np, struct sk_buff *skb,
+-                              grant_ref_t ref)
+-{
+-      int new = xennet_rxidx(np->rx.req_prod_pvt);
+-
+-      BUG_ON(np->rx_skbs[new]);
+-      np->rx_skbs[new] = skb;
+-      np->grant_rx_ref[new] = ref;
+-      RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->id = new;
+-      RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->gref = ref;
+-      np->rx.req_prod_pvt++;
+-}
+-
+-static int xennet_get_extras(struct netfront_info *np,
+-                           struct xen_netif_extra_info *extras,
+-                           RING_IDX rp)
+-
+-{
+-      struct xen_netif_extra_info *extra;
+-      struct device *dev = &np->netdev->dev;
+-      RING_IDX cons = np->rx.rsp_cons;
+-      int err = 0;
+-
+-      do {
+-              struct sk_buff *skb;
+-              grant_ref_t ref;
+-
+-              if (unlikely(cons + 1 == rp)) {
+-                      if (net_ratelimit())
+-                              dev_warn(dev, "Missing extra info\n");
+-                      err = -EBADR;
+-                      break;
+-              }
+-
+-              extra = (struct xen_netif_extra_info *)
+-                      RING_GET_RESPONSE(&np->rx, ++cons);
+-
+-              if (unlikely(!extra->type ||
+-                           extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
+-                      if (net_ratelimit())
+-                              dev_warn(dev, "Invalid extra type: %d\n",
+-                                      extra->type);
+-                      err = -EINVAL;
+-              } else {
+-                      memcpy(&extras[extra->type - 1], extra,
+-                             sizeof(*extra));
+-              }
+-
+-              skb = xennet_get_rx_skb(np, cons);
+-              ref = xennet_get_rx_ref(np, cons);
+-              xennet_move_rx_slot(np, skb, ref);
+-      } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE);
+-
+-      np->rx.rsp_cons = cons;
+-      return err;
+-}
+-
+-static int xennet_get_responses(struct netfront_info *np,
+-                              struct netfront_rx_info *rinfo, RING_IDX rp,
+-                              struct sk_buff_head *list,
+-                              int *pages_flipped_p)
+-{
+-      int pages_flipped = *pages_flipped_p;
+-      struct mmu_update *mmu;
+-      struct multicall_entry *mcl;
+-      struct xen_netif_rx_response *rx = &rinfo->rx;
+-      struct xen_netif_extra_info *extras = rinfo->extras;
+-      struct device *dev = &np->netdev->dev;
+-      RING_IDX cons = np->rx.rsp_cons;
+-      struct sk_buff *skb = xennet_get_rx_skb(np, cons);
+-      grant_ref_t ref = xennet_get_rx_ref(np, cons);
+-      int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD);
+-      int frags = 1;
+-      int err = 0;
+-      unsigned long ret;
+-
+-      if (rx->flags & NETRXF_extra_info) {
+-              err = xennet_get_extras(np, extras, rp);
+-              cons = np->rx.rsp_cons;
+-      }
+-
+-      for (;;) {
+-              unsigned long mfn;
+-
+-              if (unlikely(rx->status < 0 ||
+-                           rx->offset + rx->status > PAGE_SIZE)) {
+-                      if (net_ratelimit())
+-                              dev_warn(dev, "rx->offset: %x, size: %u\n",
+-                                       rx->offset, rx->status);
+-                      xennet_move_rx_slot(np, skb, ref);
+-                      err = -EINVAL;
+-                      goto next;
+-              }
+-
+-              /*
+-               * This definitely indicates a bug, either in this driver or in
+-               * the backend driver. In future this should flag the bad
+-               * situation to the system controller to reboot the backed.
+-               */
+-              if (ref == GRANT_INVALID_REF) {
+-                      if (net_ratelimit())
+-                              dev_warn(dev, "Bad rx response id %d.\n",
+-                                       rx->id);
+-                      err = -EINVAL;
+-                      goto next;
+-              }
+-
+-              if (!np->copying_receiver) {
+-                      /* Memory pressure, insufficient buffer
+-                       * headroom, ... */
+-                      mfn = gnttab_end_foreign_transfer_ref(ref);
+-                      if (!mfn) {
+-                              if (net_ratelimit())
+-                                      dev_warn(dev, "Unfulfilled rx req "
+-                                               "(id=%d, st=%d).\n",
+-                                               rx->id, rx->status);
+-                              xennet_move_rx_slot(np, skb, ref);
+-                              err = -ENOMEM;
+-                              goto next;
+-                      }
+-
+-                      if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+-                              /* Remap the page. */
+-                              struct page *page =
+-                                      skb_shinfo(skb)->frags[0].page;
+-                              unsigned long pfn = page_to_pfn(page);
+-                              void *vaddr = page_address(page);
+-
+-                              mcl = np->rx_mcl + pages_flipped;
+-                              mmu = np->rx_mmu + pages_flipped;
+-
+-                              MULTI_update_va_mapping(mcl,
+-                                                      (unsigned long)vaddr,
+-                                                      mfn_pte(mfn, PAGE_KERNEL),
+-                                                      0);
+-                              mmu->ptr = ((u64)mfn << PAGE_SHIFT)
+-                                      | MMU_MACHPHYS_UPDATE;
+-                              mmu->val = pfn;
+-
+-                              set_phys_to_machine(pfn, mfn);
+-                      }
+-                      pages_flipped++;
+-              } else {
+-                      ret = gnttab_end_foreign_access_ref(ref, 0);
+-                      BUG_ON(!ret);
+-              }
+-
+-              gnttab_release_grant_reference(&np->gref_rx_head, ref);
+-
+-              __skb_queue_tail(list, skb);
+-
+-next:
+-              if (!(rx->flags & NETRXF_more_data))
+-                      break;
+-
+-              if (cons + frags == rp) {
+-                      if (net_ratelimit())
+-                              dev_warn(dev, "Need more frags\n");
+-                      err = -ENOENT;
+-                      break;
+-              }
+-
+-              rx = RING_GET_RESPONSE(&np->rx, cons + frags);
+-              skb = xennet_get_rx_skb(np, cons + frags);
+-              ref = xennet_get_rx_ref(np, cons + frags);
+-              frags++;
+-      }
+-
+-      if (unlikely(frags > max)) {
+-              if (net_ratelimit())
+-                      dev_warn(dev, "Too many frags\n");
+-              err = -E2BIG;
+-      }
+-
+-      if (unlikely(err))
+-              np->rx.rsp_cons = cons + frags;
+-
+-      *pages_flipped_p = pages_flipped;
+-
+-      return err;
+-}
+-
+-static int xennet_set_skb_gso(struct sk_buff *skb,
+-                            struct xen_netif_extra_info *gso)
+-{
+-      if (!gso->u.gso.size) {
+-              if (net_ratelimit())
+-                      printk(KERN_WARNING "GSO size must not be zero.\n");
+-              return -EINVAL;
+-      }
+-
+-      /* Currently only TCPv4 S.O. is supported. */
+-      if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
+-              if (net_ratelimit())
+-                      printk(KERN_WARNING "Bad GSO type %d.\n", gso->u.gso.type);
+-              return -EINVAL;
+-      }
+-
+-      skb_shinfo(skb)->gso_size = gso->u.gso.size;
+-      skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+-
+-      /* Header must be checked, and gso_segs computed. */
+-      skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
+-      skb_shinfo(skb)->gso_segs = 0;
+-
+-      return 0;
+-}
+-
+-static RING_IDX xennet_fill_frags(struct netfront_info *np,
+-                                struct sk_buff *skb,
+-                                struct sk_buff_head *list)
+-{
+-      struct skb_shared_info *shinfo = skb_shinfo(skb);
+-      int nr_frags = shinfo->nr_frags;
+-      RING_IDX cons = np->rx.rsp_cons;
+-      skb_frag_t *frag = shinfo->frags + nr_frags;
+-      struct sk_buff *nskb;
+-
+-      while ((nskb = __skb_dequeue(list))) {
+-              struct xen_netif_rx_response *rx =
+-                      RING_GET_RESPONSE(&np->rx, ++cons);
+-
+-              frag->page = skb_shinfo(nskb)->frags[0].page;
+-              frag->page_offset = rx->offset;
+-              frag->size = rx->status;
+-
+-              skb->data_len += rx->status;
+-
+-              skb_shinfo(nskb)->nr_frags = 0;
+-              kfree_skb(nskb);
+-
+-              frag++;
+-              nr_frags++;
+-      }
+-
+-      shinfo->nr_frags = nr_frags;
+-      return cons;
+-}
+-
+-static int skb_checksum_setup(struct sk_buff *skb)
+-{
+-      struct iphdr *iph;
+-      unsigned char *th;
+-      int err = -EPROTO;
+-
+-      if (skb->protocol != htons(ETH_P_IP))
+-              goto out;
+-
+-      iph = (void *)skb->data;
+-      th = skb->data + 4 * iph->ihl;
+-      if (th >= skb_tail_pointer(skb))
+-              goto out;
+-
+-      skb->csum_start = th - skb->head;
+-      switch (iph->protocol) {
+-      case IPPROTO_TCP:
+-              skb->csum_offset = offsetof(struct tcphdr, check);
+-              break;
+-      case IPPROTO_UDP:
+-              skb->csum_offset = offsetof(struct udphdr, check);
+-              break;
+-      default:
+-              if (net_ratelimit())
+-                      printk(KERN_ERR "Attempting to checksum a non-"
+-                             "TCP/UDP packet, dropping a protocol"
+-                             " %d packet", iph->protocol);
+-              goto out;
+-      }
+-
+-      if ((th + skb->csum_offset + 2) > skb_tail_pointer(skb))
+-              goto out;
+-
+-      err = 0;
+-
+-out:
+-      return err;
+-}
+-
+-static int handle_incoming_queue(struct net_device *dev,
+-                                struct sk_buff_head *rxq)
+-{
+-      struct netfront_info *np = netdev_priv(dev);
+-      int packets_dropped = 0;
+-      struct sk_buff *skb;
+-
+-      while ((skb = __skb_dequeue(rxq)) != NULL) {
+-              struct page *page = NETFRONT_SKB_CB(skb)->page;
+-              void *vaddr = page_address(page);
+-              unsigned offset = NETFRONT_SKB_CB(skb)->offset;
+-
+-              memcpy(skb->data, vaddr + offset,
+-                     skb_headlen(skb));
+-
+-              if (page != skb_shinfo(skb)->frags[0].page)
+-                      __free_page(page);
+-
+-              /* Ethernet work: Delayed to here as it peeks the header. */
+-              skb->protocol = eth_type_trans(skb, dev);
+-
+-              if (skb->ip_summed == CHECKSUM_PARTIAL) {
+-                      if (skb_checksum_setup(skb)) {
+-                              kfree_skb(skb);
+-                              packets_dropped++;
+-                              np->stats.rx_errors++;
+-                              continue;
+-                      }
+-              }
+-
+-              np->stats.rx_packets++;
+-              np->stats.rx_bytes += skb->len;
+-
+-              /* Pass it up. */
+-              netif_receive_skb(skb);
+-              dev->last_rx = jiffies;
+-      }
+-
+-      return packets_dropped;
+-}
+-
+-static int xennet_poll(struct net_device *dev, int *pbudget)
+-{
+-      struct netfront_info *np = netdev_priv(dev);
+-      struct sk_buff *skb;
+-      struct netfront_rx_info rinfo;
+-      struct xen_netif_rx_response *rx = &rinfo.rx;
+-      struct xen_netif_extra_info *extras = rinfo.extras;
+-      RING_IDX i, rp;
+-      struct multicall_entry *mcl;
+-      int work_done, budget, more_to_do = 1;
+-      struct sk_buff_head rxq;
+-      struct sk_buff_head errq;
+-      struct sk_buff_head tmpq;
+-      unsigned long flags;
+-      unsigned int len;
+-      int pages_flipped = 0;
+-      int err;
+-
+-      spin_lock(&np->rx_lock);
+-
+-      if (unlikely(!netif_carrier_ok(dev))) {
+-              spin_unlock(&np->rx_lock);
+-              return 0;
+-      }
+-
+-      skb_queue_head_init(&rxq);
+-      skb_queue_head_init(&errq);
+-      skb_queue_head_init(&tmpq);
+-
+-      if ((budget = *pbudget) > dev->quota)
+-              budget = dev->quota;
+-      rp = np->rx.sring->rsp_prod;
+-      rmb(); /* Ensure we see queued responses up to 'rp'. */
+-
+-      i = np->rx.rsp_cons;
+-      work_done = 0;
+-      while ((i != rp) && (work_done < budget)) {
+-              memcpy(rx, RING_GET_RESPONSE(&np->rx, i), sizeof(*rx));
+-              memset(extras, 0, sizeof(rinfo.extras));
+-
+-              err = xennet_get_responses(np, &rinfo, rp, &tmpq,
+-                                         &pages_flipped);
+-
+-              if (unlikely(err)) {
+-err:
+-                      while ((skb = __skb_dequeue(&tmpq)))
+-                              __skb_queue_tail(&errq, skb);
+-                      np->stats.rx_errors++;
+-                      i = np->rx.rsp_cons;
+-                      continue;
+-              }
+-
+-              skb = __skb_dequeue(&tmpq);
+-
+-              if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
+-                      struct xen_netif_extra_info *gso;
+-                      gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
+-
+-                      if (unlikely(xennet_set_skb_gso(skb, gso))) {
+-                              __skb_queue_head(&tmpq, skb);
+-                              np->rx.rsp_cons += skb_queue_len(&tmpq);
+-                              goto err;
+-                      }
+-              }
+-
+-              NETFRONT_SKB_CB(skb)->page = skb_shinfo(skb)->frags[0].page;
+-              NETFRONT_SKB_CB(skb)->offset = rx->offset;
+-
+-              len = rx->status;
+-              if (len > RX_COPY_THRESHOLD)
+-                      len = RX_COPY_THRESHOLD;
+-              skb_put(skb, len);
+-
+-              if (rx->status > len) {
+-                      skb_shinfo(skb)->frags[0].page_offset =
+-                              rx->offset + len;
+-                      skb_shinfo(skb)->frags[0].size = rx->status - len;
+-                      skb->data_len = rx->status - len;
+-              } else {
+-                      skb_shinfo(skb)->frags[0].page = NULL;
+-                      skb_shinfo(skb)->nr_frags = 0;
+-              }
+-
+-              i = xennet_fill_frags(np, skb, &tmpq);
+-
+-              /*
+-               * Truesize approximates the size of true data plus
+-               * any supervisor overheads. Adding hypervisor
+-               * overheads has been shown to significantly reduce
+-               * achievable bandwidth with the default receive
+-               * buffer size. It is therefore not wise to account
+-               * for it here.
+-               *
+-               * After alloc_skb(RX_COPY_THRESHOLD), truesize is set
+-               * to RX_COPY_THRESHOLD + the supervisor
+-               * overheads. Here, we add the size of the data pulled
+-               * in xennet_fill_frags().
+-               *
+-               * We also adjust for any unused space in the main
+-               * data area by subtracting (RX_COPY_THRESHOLD -
+-               * len). This is especially important with drivers
+-               * which split incoming packets into header and data,
+-               * using only 66 bytes of the main data area (see the
+-               * e1000 driver for example.)  On such systems,
+-               * without this last adjustement, our achievable
+-               * receive throughout using the standard receive
+-               * buffer size was cut by 25%(!!!).
+-               */
+-              skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len);
+-              skb->len += skb->data_len;
+-
+-              if (rx->flags & NETRXF_csum_blank)
+-                      skb->ip_summed = CHECKSUM_PARTIAL;
+-              else if (rx->flags & NETRXF_data_validated)
+-                      skb->ip_summed = CHECKSUM_UNNECESSARY;
+-
+-              __skb_queue_tail(&rxq, skb);
+-
+-              np->rx.rsp_cons = ++i;
+-              work_done++;
+-      }
+-
+-      if (pages_flipped) {
+-              /* Do all the remapping work, and M2P updates. */
+-              if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+-                      mcl = np->rx_mcl + pages_flipped;
+-                      MULTI_mmu_update(mcl, np->rx_mmu,
+-                                       pages_flipped, 0, DOMID_SELF);
+-                      (void)HYPERVISOR_multicall(np->rx_mcl,
+-                                                 pages_flipped + 1);
+-              }
+-      }
+-
+-      while ((skb = __skb_dequeue(&errq)))
+-              kfree_skb(skb);
+-
+-      work_done -= handle_incoming_queue(dev, &rxq);
+-
+-      /* If we get a callback with very few responses, reduce fill target. */
+-      /* NB. Note exponential increase, linear decrease. */
+-      if (((np->rx.req_prod_pvt - np->rx.sring->rsp_prod) >
+-           ((3*np->rx_target) / 4)) &&
+-          (--np->rx_target < np->rx_min_target))
+-              np->rx_target = np->rx_min_target;
+-
+-      xennet_alloc_rx_buffers(dev);
+-
+-      *pbudget   -= work_done;
+-      dev->quota -= work_done;
+-
+-      if (work_done < budget) {
+-              local_irq_save(flags);
+-
+-              RING_FINAL_CHECK_FOR_RESPONSES(&np->rx, more_to_do);
+-              if (!more_to_do)
+-                      __netif_rx_complete(dev);
+-
+-              local_irq_restore(flags);
+-      }
+-
+-      spin_unlock(&np->rx_lock);
+-
+-      return more_to_do;
+-}
+-
+-static int xennet_change_mtu(struct net_device *dev, int mtu)
+-{
+-      int max = xennet_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN;
+-
+-      if (mtu > max)
+-              return -EINVAL;
+-      dev->mtu = mtu;
+-      return 0;
+-}
+-
+-static void xennet_release_tx_bufs(struct netfront_info *np)
+-{
+-      struct sk_buff *skb;
+-      int i;
+-
+-      for (i = 0; i < NET_TX_RING_SIZE; i++) {
+-              /* Skip over entries which are actually freelist references */
+-              if ((unsigned long)np->tx_skbs[i].skb < PAGE_OFFSET)
+-                      continue;
+-
+-              skb = np->tx_skbs[i].skb;
+-              gnttab_end_foreign_access_ref(np->grant_tx_ref[i],
+-                                            GNTMAP_readonly);
+-              gnttab_release_grant_reference(&np->gref_tx_head,
+-                                             np->grant_tx_ref[i]);
+-              np->grant_tx_ref[i] = GRANT_INVALID_REF;
+-              add_id_to_freelist(&np->tx_skb_freelist, np->tx_skbs, i);
+-              dev_kfree_skb_irq(skb);
+-      }
+-}
+-
+-static void xennet_release_rx_bufs(struct netfront_info *np)
+-{
+-      struct mmu_update      *mmu = np->rx_mmu;
+-      struct multicall_entry *mcl = np->rx_mcl;
+-      struct sk_buff_head free_list;
+-      struct sk_buff *skb;
+-      unsigned long mfn;
+-      int xfer = 0, noxfer = 0, unused = 0;
+-      int id, ref;
+-
+-      if (np->copying_receiver) {
+-              dev_warn(&np->netdev->dev, "%s: fix me for copying receiver.\n",
+-                       __func__);
+-              return;
+-      }
+-
+-      skb_queue_head_init(&free_list);
+-
+-      spin_lock_bh(&np->rx_lock);
+-
+-      for (id = 0; id < NET_RX_RING_SIZE; id++) {
+-              if ((ref = np->grant_rx_ref[id]) == GRANT_INVALID_REF) {
+-                      unused++;
+-                      continue;
+-              }
+-
+-              skb = np->rx_skbs[id];
+-              mfn = gnttab_end_foreign_transfer_ref(ref);
+-              gnttab_release_grant_reference(&np->gref_rx_head, ref);
+-              np->grant_rx_ref[id] = GRANT_INVALID_REF;
+-
+-              if (0 == mfn) {
+-                      skb_shinfo(skb)->nr_frags = 0;
+-                      dev_kfree_skb(skb);
+-                      noxfer++;
+-                      continue;
+-              }
+-
+-              if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+-                      /* Remap the page. */
+-                      struct page *page = skb_shinfo(skb)->frags[0].page;
+-                      unsigned long pfn = page_to_pfn(page);
+-                      void *vaddr = page_address(page);
+-
+-                      MULTI_update_va_mapping(mcl, (unsigned long)vaddr,
+-                                              mfn_pte(mfn, PAGE_KERNEL),
+-                                              0);
+-                      mcl++;
+-                      mmu->ptr = ((u64)mfn << PAGE_SHIFT)
+-                              | MMU_MACHPHYS_UPDATE;
+-                      mmu->val = pfn;
+-                      mmu++;
+-
+-                      set_phys_to_machine(pfn, mfn);
+-              }
+-              __skb_queue_tail(&free_list, skb);
+-              xfer++;
+-      }
+-
+-      dev_info(&np->netdev->dev, "%s: %d xfer, %d noxfer, %d unused\n",
+-               __func__, xfer, noxfer, unused);
+-
+-      if (xfer) {
+-              if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+-                      /* Do all the remapping work and M2P updates. */
+-                      MULTI_mmu_update(mcl, np->rx_mmu, mmu - np->rx_mmu,
+-                                       0, DOMID_SELF);
+-                      mcl++;
+-                      HYPERVISOR_multicall(np->rx_mcl, mcl - np->rx_mcl);
+-              }
+-      }
+-
+-      while ((skb = __skb_dequeue(&free_list)) != NULL)
+-              dev_kfree_skb(skb);
+-
+-      spin_unlock_bh(&np->rx_lock);
+-}
+-
+-static void xennet_uninit(struct net_device *dev)
+-{
+-      struct netfront_info *np = netdev_priv(dev);
+-      xennet_release_tx_bufs(np);
+-      xennet_release_rx_bufs(np);
+-      gnttab_free_grant_references(np->gref_tx_head);
+-      gnttab_free_grant_references(np->gref_rx_head);
+-}
+-
+-static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev)
+-{
+-      int i, err;
+-      struct net_device *netdev;
+-      struct netfront_info *np;
+-
+-      netdev = alloc_etherdev(sizeof(struct netfront_info));
+-      if (!netdev) {
+-              printk(KERN_WARNING "%s> alloc_etherdev failed.\n",
+-                     __func__);
+-              return ERR_PTR(-ENOMEM);
+-      }
+-
+-      np                   = netdev_priv(netdev);
+-      np->xbdev            = dev;
+-
+-      spin_lock_init(&np->tx_lock);
+-      spin_lock_init(&np->rx_lock);
+-
+-      skb_queue_head_init(&np->rx_batch);
+-      np->rx_target     = RX_DFL_MIN_TARGET;
+-      np->rx_min_target = RX_DFL_MIN_TARGET;
+-      np->rx_max_target = RX_MAX_TARGET;
+-
+-      init_timer(&np->rx_refill_timer);
+-      np->rx_refill_timer.data = (unsigned long)netdev;
+-      np->rx_refill_timer.function = rx_refill_timeout;
+-
+-      /* Initialise tx_skbs as a free chain containing every entry. */
+-      np->tx_skb_freelist = 0;
+-      for (i = 0; i < NET_TX_RING_SIZE; i++) {
+-              np->tx_skbs[i].link = i+1;
+-              np->grant_tx_ref[i] = GRANT_INVALID_REF;
+-      }
+-
+-      /* Clear out rx_skbs */
+-      for (i = 0; i < NET_RX_RING_SIZE; i++) {
+-              np->rx_skbs[i] = NULL;
+-              np->grant_rx_ref[i] = GRANT_INVALID_REF;
+-      }
+-
+-      /* A grant for every tx ring slot */
+-      if (gnttab_alloc_grant_references(TX_MAX_TARGET,
+-                                        &np->gref_tx_head) < 0) {
+-              printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
+-              err = -ENOMEM;
+-              goto exit;
+-      }
+-      /* A grant for every rx ring slot */
+-      if (gnttab_alloc_grant_references(RX_MAX_TARGET,
+-                                        &np->gref_rx_head) < 0) {
+-              printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
+-              err = -ENOMEM;
+-              goto exit_free_tx;
+-      }
+-
+-      netdev->open            = xennet_open;
+-      netdev->hard_start_xmit = xennet_start_xmit;
+-      netdev->stop            = xennet_close;
+-      netdev->get_stats       = xennet_get_stats;
+-      netdev->poll            = xennet_poll;
+-      netdev->uninit          = xennet_uninit;
+-      netdev->change_mtu      = xennet_change_mtu;
+-      netdev->weight          = 64;
+-      netdev->features        = NETIF_F_IP_CSUM;
+-
+-      SET_ETHTOOL_OPS(netdev, &xennet_ethtool_ops);
+-      SET_MODULE_OWNER(netdev);
+-      SET_NETDEV_DEV(netdev, &dev->dev);
+-
+-      np->netdev = netdev;
+-
+-      netif_carrier_off(netdev);
+-
+-      return netdev;
+-
+- exit_free_tx:
+-      gnttab_free_grant_references(np->gref_tx_head);
+- exit:
+-      free_netdev(netdev);
+-      return ERR_PTR(err);
+-}
+-
+-/**
+- * Entry point to this code when a new device is created.  Allocate the basic
+- * structures and the ring buffers for communication with the backend, and
+- * inform the backend of the appropriate details for those.
+- */
+-static int __devinit netfront_probe(struct xenbus_device *dev,
+-                                  const struct xenbus_device_id *id)
+-{
+-      int err;
+-      struct net_device *netdev;
+-      struct netfront_info *info;
+-
+-      netdev = xennet_create_dev(dev);
+-      if (IS_ERR(netdev)) {
+-              err = PTR_ERR(netdev);
+-              xenbus_dev_fatal(dev, err, "creating netdev");
+-              return err;
 -      }
-+
-       ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
--      lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
-+      lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_prli_adisc_issue(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_rcv_prli_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      cmdiocb = (struct lpfc_iocbq *) arg;
 -
--      lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
-+      lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_rcv_logo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
- {
-+      struct lpfc_hba *phba = vport->phba;
-       struct lpfc_iocbq *cmdiocb;
-       cmdiocb = (struct lpfc_iocbq *) arg;
-@@ -881,42 +967,43 @@
-       /* software abort outstanding ADISC */
-       lpfc_els_abort(phba, ndlp);
--      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
-+      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_padisc_adisc_issue(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_rcv_padisc_adisc_issue(struct lpfc_vport *vport,
-+                          struct lpfc_nodelist *ndlp,
-+                          void *arg, uint32_t evt)
- {
-       struct lpfc_iocbq *cmdiocb;
-       cmdiocb = (struct lpfc_iocbq *) arg;
--      lpfc_rcv_padisc(phba, ndlp, cmdiocb);
-+      lpfc_rcv_padisc(vport, ndlp, cmdiocb);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_prlo_adisc_issue(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_rcv_prlo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
- {
-       struct lpfc_iocbq *cmdiocb;
-       cmdiocb = (struct lpfc_iocbq *) arg;
-       /* Treat like rcv logo */
--      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
-+      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
-+                          struct lpfc_nodelist *ndlp,
-+                          void *arg, uint32_t evt)
- {
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba   *phba = vport->phba;
-       struct lpfc_iocbq *cmdiocb, *rspiocb;
-       IOCB_t *irsp;
-       ADISC *ap;
-@@ -928,101 +1015,112 @@
-       irsp = &rspiocb->iocb;
-       if ((irsp->ulpStatus) ||
--              (!lpfc_check_adisc(phba, ndlp, &ap->nodeName, &ap->portName))) {
-+          (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) {
-               /* 1 sec timeout */
-               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
--              spin_lock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_DELAY_TMO;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-               ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
--              memset(&ndlp->nlp_nodename, 0, sizeof (struct lpfc_name));
--              memset(&ndlp->nlp_portname, 0, sizeof (struct lpfc_name));
-+              memset(&ndlp->nlp_nodename, 0, sizeof(struct lpfc_name));
-+              memset(&ndlp->nlp_portname, 0, sizeof(struct lpfc_name));
-               ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
--              lpfc_unreg_rpi(phba, ndlp);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-+              lpfc_unreg_rpi(vport, ndlp);
-               return ndlp->nlp_state;
-       }
-       if (ndlp->nlp_type & NLP_FCP_TARGET) {
-               ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
-       } else {
-               ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
-       }
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_device_rm_adisc_issue(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_device_rm_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                         void *arg, uint32_t evt)
- {
--      if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-+      if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
-+              spin_unlock_irq(shost->host_lock);
-               return ndlp->nlp_state;
+-      info = netdev_priv(netdev);
+-      dev->dev.driver_data = info;
+-
+-      err = register_netdev(info->netdev);
+-      if (err) {
+-              printk(KERN_WARNING "%s: register_netdev err=%d\n",
+-                     __func__, err);
+-              goto fail;
 -      }
--      else {
-+      } else {
-               /* software abort outstanding ADISC */
--              lpfc_els_abort(phba, ndlp);
-+              lpfc_els_abort(vport->phba, ndlp);
--              lpfc_drop_node(phba, ndlp);
-+              lpfc_drop_node(vport, ndlp);
-               return NLP_STE_FREED_NODE;
-       }
- }
- static uint32_t
--lpfc_device_recov_adisc_issue(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
-+lpfc_device_recov_adisc_issue(struct lpfc_vport *vport,
-+                            struct lpfc_nodelist *ndlp,
-+                            void *arg,
-                           uint32_t evt)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-+
-+      /* Don't do anything that will mess up processing of the
-+       * previous RSCN.
-+       */
-+      if (vport->fc_flag & FC_RSCN_DEFERRED)
-+              return ndlp->nlp_state;
-+
-       /* software abort outstanding ADISC */
-       lpfc_els_abort(phba, ndlp);
-       ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
--      spin_lock_irq(phba->host->host_lock);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
--      ndlp->nlp_flag |= NLP_NPR_ADISC;
--      spin_unlock_irq(phba->host->host_lock);
 -
-+      spin_unlock_irq(shost->host_lock);
-+      lpfc_disc_set_adisc(vport, ndlp);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_plogi_reglogin_issue(struct lpfc_hba * phba,
--                            struct lpfc_nodelist * ndlp, void *arg,
-+lpfc_rcv_plogi_reglogin_issue(struct lpfc_vport *vport,
-+                            struct lpfc_nodelist *ndlp,
-+                            void *arg,
-                             uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
+-      err = xennet_sysfs_addif(info->netdev);
+-      if (err) {
+-              unregister_netdev(info->netdev);
+-              printk(KERN_WARNING "%s: add sysfs failed err=%d\n",
+-                     __func__, err);
+-              goto fail;
+-      }
 -
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      lpfc_rcv_plogi(phba, ndlp, cmdiocb);
-+      lpfc_rcv_plogi(vport, ndlp, cmdiocb);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_prli_reglogin_issue(struct lpfc_hba * phba,
--                           struct lpfc_nodelist * ndlp, void *arg,
-+lpfc_rcv_prli_reglogin_issue(struct lpfc_vport *vport,
-+                           struct lpfc_nodelist *ndlp,
-+                           void *arg,
-                            uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      cmdiocb = (struct lpfc_iocbq *) arg;
+-      return 0;
 -
--      lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
-+      lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
--                           struct lpfc_nodelist * ndlp, void *arg,
-+lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,
-+                           struct lpfc_nodelist *ndlp,
-+                           void *arg,
-                            uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
-+      struct lpfc_hba   *phba = vport->phba;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
-       LPFC_MBOXQ_t      *mb;
-       LPFC_MBOXQ_t      *nextmb;
-       struct lpfc_dmabuf *mp;
-@@ -1033,12 +1131,13 @@
-       if ((mb = phba->sli.mbox_active)) {
-               if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
-                  (ndlp == (struct lpfc_nodelist *) mb->context2)) {
-+                      lpfc_nlp_put(ndlp);
-                       mb->context2 = NULL;
-                       mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-               }
-       }
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
-               if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
-                  (ndlp == (struct lpfc_nodelist *) mb->context2)) {
-@@ -1047,61 +1146,61 @@
-                               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-                               kfree(mp);
-                       }
-+                      lpfc_nlp_put(ndlp);
-                       list_del(&mb->list);
-                       mempool_free(mb, phba->mbox_mem_pool);
-               }
-       }
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
--      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
-+      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_padisc_reglogin_issue(struct lpfc_hba * phba,
--                             struct lpfc_nodelist * ndlp, void *arg,
-+lpfc_rcv_padisc_reglogin_issue(struct lpfc_vport *vport,
-+                             struct lpfc_nodelist *ndlp,
-+                             void *arg,
-                              uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
+- fail:
+-      free_netdev(netdev);
+-      dev->dev.driver_data = NULL;
+-      return err;
+-}
 -
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      lpfc_rcv_padisc(phba, ndlp, cmdiocb);
-+      lpfc_rcv_padisc(vport, ndlp, cmdiocb);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_prlo_reglogin_issue(struct lpfc_hba * phba,
--                           struct lpfc_nodelist * ndlp, void *arg,
-+lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport,
-+                           struct lpfc_nodelist *ndlp,
-+                           void *arg,
-                            uint32_t evt)
- {
-       struct lpfc_iocbq *cmdiocb;
-       cmdiocb = (struct lpfc_iocbq *) arg;
--      lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
-+      lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
--                                struct lpfc_nodelist * ndlp,
--                                void *arg, uint32_t evt)
-+lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,
-+                                struct lpfc_nodelist *ndlp,
-+                                void *arg,
-+                                uint32_t evt)
- {
--      LPFC_MBOXQ_t *pmb;
--      MAILBOX_t *mb;
--      uint32_t did;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-+      LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
-+      MAILBOX_t *mb = &pmb->mb;
-+      uint32_t did  = mb->un.varWords[1];
--      pmb = (LPFC_MBOXQ_t *) arg;
--      mb = &pmb->mb;
--      did = mb->un.varWords[1];
-       if (mb->mbxStatus) {
-               /* RegLogin failed */
--              lpfc_printf_log(phba,
--                              KERN_ERR,
--                              LOG_DISCOVERY,
--                              "%d:0246 RegLogin failed Data: x%x x%x x%x\n",
--                              phba->brd_no,
--                              did, mb->mbxStatus, phba->hba_state);
-+              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-+                              "%d (%d):0246 RegLogin failed Data: x%x x%x "
-+                              "x%x\n",
-+                              phba->brd_no, vport->vpi,
-+                              did, mb->mbxStatus, vport->port_state);
-               /*
-                * If RegLogin failed due to lack of HBA resources do not
-@@ -1109,20 +1208,20 @@
-                */
-               if (mb->mbxStatus == MBXERR_RPI_FULL) {
-                       ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
-                       return ndlp->nlp_state;
-               }
--              /* Put ndlp in npr list set plogi timer for 1 sec */
-+              /* Put ndlp in npr state set plogi timer for 1 sec */
-               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
--              spin_lock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_DELAY_TMO;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-               ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
--              lpfc_issue_els_logo(phba, ndlp, 0);
-+              lpfc_issue_els_logo(vport, ndlp, 0);
-               ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-               return ndlp->nlp_state;
-       }
-@@ -1131,91 +1230,99 @@
-       /* Only if we are not a fabric nport do we issue PRLI */
-       if (!(ndlp->nlp_type & NLP_FABRIC)) {
-               ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
--              lpfc_issue_els_prli(phba, ndlp, 0);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
-+              lpfc_issue_els_prli(vport, ndlp, 0);
-       } else {
-               ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
-       }
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_device_rm_reglogin_issue(struct lpfc_hba * phba,
--                            struct lpfc_nodelist * ndlp, void *arg,
-+lpfc_device_rm_reglogin_issue(struct lpfc_vport *vport,
-+                            struct lpfc_nodelist *ndlp,
-+                            void *arg,
-                             uint32_t evt)
- {
--      if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-+      if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
-+              spin_unlock_irq(shost->host_lock);
-               return ndlp->nlp_state;
--      }
--      else {
--              lpfc_drop_node(phba, ndlp);
-+      } else {
-+              lpfc_drop_node(vport, ndlp);
-               return NLP_STE_FREED_NODE;
-       }
- }
- static uint32_t
--lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba,
--                             struct lpfc_nodelist * ndlp, void *arg,
-+lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport,
-+                               struct lpfc_nodelist *ndlp,
-+                               void *arg,
-                              uint32_t evt)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-+      /* Don't do anything that will mess up processing of the
-+       * previous RSCN.
-+       */
-+      if (vport->fc_flag & FC_RSCN_DEFERRED)
-+              return ndlp->nlp_state;
-+
-       ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
--      spin_lock_irq(phba->host->host_lock);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
-+      lpfc_disc_set_adisc(vport, ndlp);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_plogi_prli_issue(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_plogi_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
- {
-       struct lpfc_iocbq *cmdiocb;
-       cmdiocb = (struct lpfc_iocbq *) arg;
--      lpfc_rcv_plogi(phba, ndlp, cmdiocb);
-+      lpfc_rcv_plogi(vport, ndlp, cmdiocb);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_prli_prli_issue(struct lpfc_hba * phba,
--                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                       void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      cmdiocb = (struct lpfc_iocbq *) arg;
+-static void xennet_end_access(int ref, void *page)
+-{
+-      /* This frees the page as a side-effect */
+-      if (ref != GRANT_INVALID_REF)
+-              gnttab_end_foreign_access(ref, 0, (unsigned long)page);
+-}
 -
--      lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
-+      lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba,
--                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_logo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                       void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
+-static void xennet_disconnect_backend(struct netfront_info *info)
+-{
+-      /* Stop old i/f to prevent errors whilst we rebuild the state. */
+-      spin_lock_bh(&info->rx_lock);
+-      spin_lock_irq(&info->tx_lock);
+-      netif_carrier_off(info->netdev);
+-      spin_unlock_irq(&info->tx_lock);
+-      spin_unlock_bh(&info->rx_lock);
 -
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
-       /* Software abort outstanding PRLI before sending acc */
--      lpfc_els_abort(phba, ndlp);
-+      lpfc_els_abort(vport->phba, ndlp);
--      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
-+      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_padisc_prli_issue(struct lpfc_hba * phba,
--                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_padisc_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                         void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      cmdiocb = (struct lpfc_iocbq *) arg;
+-      if (info->netdev->irq)
+-              unbind_from_irqhandler(info->netdev->irq, info->netdev);
+-      info->evtchn = info->netdev->irq = 0;
 -
--      lpfc_rcv_padisc(phba, ndlp, cmdiocb);
-+      lpfc_rcv_padisc(vport, ndlp, cmdiocb);
-       return ndlp->nlp_state;
- }
-@@ -1225,21 +1332,22 @@
-  * NEXT STATE = PRLI_ISSUE
-  */
- static uint32_t
--lpfc_rcv_prlo_prli_issue(struct lpfc_hba * phba,
--                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                       void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      cmdiocb = (struct lpfc_iocbq *) arg;
--      lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
-+      lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-       struct lpfc_iocbq *cmdiocb, *rspiocb;
-+      struct lpfc_hba   *phba = vport->phba;
-       IOCB_t *irsp;
-       PRLI *npr;
-@@ -1249,8 +1357,12 @@
-       irsp = &rspiocb->iocb;
-       if (irsp->ulpStatus) {
-+              if ((vport->port_type == LPFC_NPIV_PORT) &&
-+                      phba->cfg_vport_restrict_login) {
-+                      goto out;
-+              }
-               ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
-               return ndlp->nlp_state;
-       }
-@@ -1266,9 +1378,25 @@
-               if (npr->Retry)
-                       ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
-       }
-+      if (!(ndlp->nlp_type & NLP_FCP_TARGET) &&
-+          (vport->port_type == LPFC_NPIV_PORT) &&
-+           phba->cfg_vport_restrict_login) {
-+out:
-+              spin_lock_irq(shost->host_lock);
-+              ndlp->nlp_flag |= NLP_TARGET_REMOVE;
-+              spin_unlock_irq(shost->host_lock);
-+              lpfc_issue_els_logo(vport, ndlp, 0);
-+
-+              ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
-+              return ndlp->nlp_state;
-+      }
-       ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE);
-+      if (ndlp->nlp_type & NLP_FCP_TARGET)
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
-+      else
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
-       return ndlp->nlp_state;
- }
-@@ -1289,19 +1417,23 @@
-   *    on plogi list so it can be freed when LOGO completes.
-   *
-   */
-+
- static uint32_t
--lpfc_device_rm_prli_issue(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
- {
--      if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-+      if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
-+              spin_unlock_irq(shost->host_lock);
-               return ndlp->nlp_state;
+-      /* End access and free the pages */
+-      xennet_end_access(info->tx_ring_ref, info->tx.sring);
+-      xennet_end_access(info->rx_ring_ref, info->rx.sring);
+-
+-      info->tx_ring_ref = GRANT_INVALID_REF;
+-      info->rx_ring_ref = GRANT_INVALID_REF;
+-      info->tx.sring = NULL;
+-      info->rx.sring = NULL;
+-}
+-
+-/**
+- * We are reconnecting to the backend, due to a suspend/resume, or a backend
+- * driver restart.  We tear down our netif structure and recreate it, but
+- * leave the device-layer structures intact so that this is transparent to the
+- * rest of the kernel.
+- */
+-static int netfront_resume(struct xenbus_device *dev)
+-{
+-      struct netfront_info *info = dev->dev.driver_data;
+-
+-      dev_dbg(&dev->dev, "%s\n", dev->nodename);
+-
+-      xennet_disconnect_backend(info);
+-      return 0;
+-}
+-
+-static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[])
+-{
+-      char *s, *e, *macstr;
+-      int i;
+-
+-      macstr = s = xenbus_read(XBT_NIL, dev->nodename, "mac", NULL);
+-      if (IS_ERR(macstr))
+-              return PTR_ERR(macstr);
+-
+-      for (i = 0; i < ETH_ALEN; i++) {
+-              mac[i] = simple_strtoul(s, &e, 16);
+-              if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
+-                      kfree(macstr);
+-                      return -ENOENT;
+-              }
+-              s = e+1;
 -      }
--      else {
-+      } else {
-               /* software abort outstanding PLOGI */
--              lpfc_els_abort(phba, ndlp);
-+              lpfc_els_abort(vport->phba, ndlp);
--              lpfc_drop_node(phba, ndlp);
-+              lpfc_drop_node(vport, ndlp);
-               return NLP_STE_FREED_NODE;
-       }
- }
-@@ -1324,261 +1456,251 @@
-   *    outstanding PRLI command, then free the node entry.
-   */
- static uint32_t
--lpfc_device_recov_prli_issue(struct lpfc_hba * phba,
--                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_device_recov_prli_issue(struct lpfc_vport *vport,
-+                           struct lpfc_nodelist *ndlp,
-+                           void *arg,
-+                           uint32_t evt)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_hba  *phba = vport->phba;
-+
-+      /* Don't do anything that will mess up processing of the
-+       * previous RSCN.
-+       */
-+      if (vport->fc_flag & FC_RSCN_DEFERRED)
-+              return ndlp->nlp_state;
-+
-       /* software abort outstanding PRLI */
-       lpfc_els_abort(phba, ndlp);
-       ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
--      spin_lock_irq(phba->host->host_lock);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
-+      lpfc_disc_set_adisc(vport, ndlp);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_plogi_unmap_node(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_plogi_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
 -
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      lpfc_rcv_plogi(phba, ndlp, cmdiocb);
-+      lpfc_rcv_plogi(vport, ndlp, cmdiocb);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_prli_unmap_node(struct lpfc_hba * phba,
--                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_prli_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                       void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      cmdiocb = (struct lpfc_iocbq *) arg;
+-      kfree(macstr);
+-      return 0;
+-}
 -
--      lpfc_rcv_prli(phba, ndlp, cmdiocb);
--      lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
-+      lpfc_rcv_prli(vport, ndlp, cmdiocb);
-+      lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_logo_unmap_node(struct lpfc_hba * phba,
--                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_logo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                       void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
+-static irqreturn_t xennet_interrupt(int irq, void *dev_id)
+-{
+-      struct net_device *dev = dev_id;
+-      struct netfront_info *np = netdev_priv(dev);
+-      unsigned long flags;
 -
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
-+      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_padisc_unmap_node(struct lpfc_hba * phba,
--                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_padisc_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                         void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
+-      spin_lock_irqsave(&np->tx_lock, flags);
 -
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      lpfc_rcv_padisc(phba, ndlp, cmdiocb);
-+      lpfc_rcv_padisc(vport, ndlp, cmdiocb);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_prlo_unmap_node(struct lpfc_hba * phba,
--                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                       void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      cmdiocb = (struct lpfc_iocbq *) arg;
+-      if (likely(netif_carrier_ok(dev))) {
+-              xennet_tx_buf_gc(dev);
+-              /* Under tx_lock: protects access to rx shared-ring indexes. */
+-              if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
+-                      netif_rx_schedule(dev);
+-      }
 -
--      lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
-+      lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_device_recov_unmap_node(struct lpfc_hba * phba,
--                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_device_recov_unmap_node(struct lpfc_vport *vport,
-+                           struct lpfc_nodelist *ndlp,
-+                           void *arg,
-+                           uint32_t evt)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-       ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
--      lpfc_disc_set_adisc(phba, ndlp);
-+      spin_unlock_irq(shost->host_lock);
-+      lpfc_disc_set_adisc(vport, ndlp);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_plogi_mapped_node(struct lpfc_hba * phba,
--                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_plogi_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                         void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      cmdiocb = (struct lpfc_iocbq *) arg;
+-      spin_unlock_irqrestore(&np->tx_lock, flags);
 -
--      lpfc_rcv_plogi(phba, ndlp, cmdiocb);
-+      lpfc_rcv_plogi(vport, ndlp, cmdiocb);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_prli_mapped_node(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_prli_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
+-      return IRQ_HANDLED;
+-}
 -
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
-+      lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_logo_mapped_node(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_logo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      cmdiocb = (struct lpfc_iocbq *) arg;
+-static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info)
+-{
+-      struct xen_netif_tx_sring *txs;
+-      struct xen_netif_rx_sring *rxs;
+-      int err;
+-      struct net_device *netdev = info->netdev;
 -
--      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
-+      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_padisc_mapped_node(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_rcv_padisc_mapped_node(struct lpfc_vport *vport,
-+                          struct lpfc_nodelist *ndlp,
-+                          void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      cmdiocb = (struct lpfc_iocbq *) arg;
+-      info->tx_ring_ref = GRANT_INVALID_REF;
+-      info->rx_ring_ref = GRANT_INVALID_REF;
+-      info->rx.sring = NULL;
+-      info->tx.sring = NULL;
+-      netdev->irq = 0;
 -
--      lpfc_rcv_padisc(phba, ndlp, cmdiocb);
-+      lpfc_rcv_padisc(vport, ndlp, cmdiocb);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_prlo_mapped_node(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                        void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
+-      err = xen_net_read_mac(dev, netdev->dev_addr);
+-      if (err) {
+-              xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
+-              goto fail;
+-      }
 -
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct lpfc_hba  *phba = vport->phba;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
-       /* flush the target */
--      spin_lock_irq(phba->host->host_lock);
-       lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
-                              ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
--      spin_unlock_irq(phba->host->host_lock);
-       /* Treat like rcv logo */
--      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
-+      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_device_recov_mapped_node(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
-+lpfc_device_recov_mapped_node(struct lpfc_vport *vport,
-+                            struct lpfc_nodelist *ndlp,
-+                            void *arg,
-                           uint32_t evt)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-       ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE;
--      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
--      spin_lock_irq(phba->host->host_lock);
-+      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
--      spin_unlock_irq(phba->host->host_lock);
--      lpfc_disc_set_adisc(phba, ndlp);
-+      spin_unlock_irq(shost->host_lock);
-+      lpfc_disc_set_adisc(vport, ndlp);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                      void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq *cmdiocb;
+-      txs = (struct xen_netif_tx_sring *)get_zeroed_page(GFP_KERNEL);
+-      if (!txs) {
+-              err = -ENOMEM;
+-              xenbus_dev_fatal(dev, err, "allocating tx ring page");
+-              goto fail;
+-      }
+-      SHARED_RING_INIT(txs);
+-      FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE);
 -
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_iocbq *cmdiocb  = (struct lpfc_iocbq *) arg;
-       /* Ignore PLOGI if we have an outstanding LOGO */
--      if (ndlp->nlp_flag & NLP_LOGO_SND) {
-+      if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC)) {
-               return ndlp->nlp_state;
-       }
--      if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
--              spin_lock_irq(phba->host->host_lock);
-+      if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag &= ~NLP_NPR_ADISC;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-               return ndlp->nlp_state;
-       }
-       /* send PLOGI immediately, move to PLOGI issue state */
-       if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
-               ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
--              lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
--              lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
-+              lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
-+              lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
-       }
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_prli_npr_node(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                     void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq     *cmdiocb;
-+      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
-       struct ls_rjt          stat;
--      cmdiocb = (struct lpfc_iocbq *) arg;
+-      err = xenbus_grant_ring(dev, virt_to_mfn(txs));
+-      if (err < 0) {
+-              free_page((unsigned long)txs);
+-              goto fail;
+-      }
 -
-       memset(&stat, 0, sizeof (struct ls_rjt));
-       stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
-       stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
--      lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
-+      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
-       if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
-               if (ndlp->nlp_flag & NLP_NPR_ADISC) {
--                      spin_lock_irq(phba->host->host_lock);
-+                      spin_lock_irq(shost->host_lock);
-                       ndlp->nlp_flag &= ~NLP_NPR_ADISC;
--                      spin_unlock_irq(phba->host->host_lock);
-                       ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
--                      lpfc_issue_els_adisc(phba, ndlp, 0);
-+                      spin_unlock_irq(shost->host_lock);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
-+                      lpfc_issue_els_adisc(vport, ndlp, 0);
-               } else {
-                       ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
--                      lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
-+                      lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
-               }
-       }
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_logo_npr_node(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_rcv_logo_npr_node(struct lpfc_vport *vport,  struct lpfc_nodelist *ndlp,
-+                     void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq     *cmdiocb;
+-      info->tx_ring_ref = err;
+-      rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_KERNEL);
+-      if (!rxs) {
+-              err = -ENOMEM;
+-              xenbus_dev_fatal(dev, err, "allocating rx ring page");
+-              goto fail;
+-      }
+-      SHARED_RING_INIT(rxs);
+-      FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);
 -
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
-+      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                       void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq     *cmdiocb;
+-      err = xenbus_grant_ring(dev, virt_to_mfn(rxs));
+-      if (err < 0) {
+-              free_page((unsigned long)rxs);
+-              goto fail;
+-      }
+-      info->rx_ring_ref = err;
+-
+-      err = xenbus_alloc_evtchn(dev, &info->evtchn);
+-      if (err)
+-              goto fail;
+-
+-      err = bind_evtchn_to_irqhandler(info->evtchn, xennet_interrupt,
+-                                      IRQF_SAMPLE_RANDOM, netdev->name,
+-                                      netdev);
+-      if (err < 0)
+-              goto fail;
+-      netdev->irq = err;
+-      return 0;
 -
--      cmdiocb = (struct lpfc_iocbq *) arg;
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      lpfc_rcv_padisc(phba, ndlp, cmdiocb);
-+      lpfc_rcv_padisc(vport, ndlp, cmdiocb);
-       /*
-        * Do not start discovery if discovery is about to start
-@@ -1586,53 +1708,52 @@
-        * here will affect the counting of discovery threads.
-        */
-       if (!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
--              !(ndlp->nlp_flag & NLP_NPR_2B_DISC)){
-+          !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
-               if (ndlp->nlp_flag & NLP_NPR_ADISC) {
-+                      ndlp->nlp_flag &= ~NLP_NPR_ADISC;
-                       ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
--                      lpfc_issue_els_adisc(phba, ndlp, 0);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
-+                      lpfc_issue_els_adisc(vport, ndlp, 0);
-               } else {
-                       ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
--                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
--                      lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
-+                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
-+                      lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
-               }
-       }
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_rcv_prlo_npr_node(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                     void *arg, uint32_t evt)
- {
--      struct lpfc_iocbq     *cmdiocb;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
--      cmdiocb = (struct lpfc_iocbq *) arg;
+- fail:
+-      return err;
+-}
 -
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag |= NLP_LOGO_ACC;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
--      lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
-+      lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
--      if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
-+      if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) {
-               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
--              spin_lock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_DELAY_TMO;
-               ndlp->nlp_flag &= ~NLP_NPR_ADISC;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-               ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
-       } else {
--              spin_lock_irq(phba->host->host_lock);
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag &= ~NLP_NPR_ADISC;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(shost->host_lock);
-       }
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                       void *arg, uint32_t evt)
- {
-       struct lpfc_iocbq *cmdiocb, *rspiocb;
-       IOCB_t *irsp;
-@@ -1642,15 +1763,15 @@
-       irsp = &rspiocb->iocb;
-       if (irsp->ulpStatus) {
--              lpfc_drop_node(phba, ndlp);
-+              lpfc_drop_node(vport, ndlp);
-               return NLP_STE_FREED_NODE;
-       }
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba,
--                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_cmpl_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                      void *arg, uint32_t evt)
- {
-       struct lpfc_iocbq *cmdiocb, *rspiocb;
-       IOCB_t *irsp;
-@@ -1660,25 +1781,24 @@
-       irsp = &rspiocb->iocb;
-       if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
--              lpfc_drop_node(phba, ndlp);
-+              lpfc_drop_node(vport, ndlp);
-               return NLP_STE_FREED_NODE;
-       }
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_cmpl_logo_npr_node(struct lpfc_hba * phba,
--              struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_cmpl_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                      void *arg, uint32_t evt)
- {
--      lpfc_unreg_rpi(phba, ndlp);
-+      lpfc_unreg_rpi(vport, ndlp);
-       /* This routine does nothing, just return the current state */
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_cmpl_adisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                       void *arg, uint32_t evt)
- {
-       struct lpfc_iocbq *cmdiocb, *rspiocb;
-       IOCB_t *irsp;
-@@ -1688,28 +1808,25 @@
-       irsp = &rspiocb->iocb;
-       if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
--              lpfc_drop_node(phba, ndlp);
-+              lpfc_drop_node(vport, ndlp);
-               return NLP_STE_FREED_NODE;
-       }
-       return ndlp->nlp_state;
- }
- static uint32_t
--lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport,
-+                          struct lpfc_nodelist *ndlp,
-+                          void *arg, uint32_t evt)
- {
--      LPFC_MBOXQ_t *pmb;
--      MAILBOX_t *mb;
+-/* Common code used when first setting up, and when resuming. */
+-static int talk_to_backend(struct xenbus_device *dev,
+-                         struct netfront_info *info)
+-{
+-      const char *message;
+-      struct xenbus_transaction xbt;
+-      int err;
 -
--      pmb = (LPFC_MBOXQ_t *) arg;
--      mb = &pmb->mb;
-+      LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
-+      MAILBOX_t    *mb = &pmb->mb;
-       if (!mb->mbxStatus)
-               ndlp->nlp_rpi = mb->un.varWords[0];
-       else {
-               if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
--                      lpfc_drop_node(phba, ndlp);
-+                      lpfc_drop_node(vport, ndlp);
-                       return NLP_STE_FREED_NODE;
-               }
-       }
-@@ -1717,28 +1834,38 @@
- }
- static uint32_t
--lpfc_device_rm_npr_node(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_device_rm_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                      void *arg, uint32_t evt)
- {
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-       if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
-+              spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
-+              spin_unlock_irq(shost->host_lock);
-               return ndlp->nlp_state;
-       }
--      lpfc_drop_node(phba, ndlp);
-+      lpfc_drop_node(vport, ndlp);
-       return NLP_STE_FREED_NODE;
- }
- static uint32_t
--lpfc_device_recov_npr_node(struct lpfc_hba * phba,
--                          struct lpfc_nodelist * ndlp, void *arg,
--                          uint32_t evt)
-+lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                         void *arg, uint32_t evt)
- {
--      spin_lock_irq(phba->host->host_lock);
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+
-+      /* Don't do anything that will mess up processing of the
-+       * previous RSCN.
-+       */
-+      if (vport->fc_flag & FC_RSCN_DEFERRED)
-+              return ndlp->nlp_state;
-+
-+      spin_lock_irq(shost->host_lock);
-       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(shost->host_lock);
-       if (ndlp->nlp_flag & NLP_DELAY_TMO) {
--              lpfc_cancel_retry_delay_tmo(phba, ndlp);
-+              lpfc_cancel_retry_delay_tmo(vport, ndlp);
-       }
-       return ndlp->nlp_state;
- }
-@@ -1801,7 +1928,7 @@
-  */
- static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT])
--     (struct lpfc_hba *, struct lpfc_nodelist *, void *, uint32_t) = {
-+     (struct lpfc_vport *, struct lpfc_nodelist *, void *, uint32_t) = {
-       /* Action routine                  Event       Current State  */
-       lpfc_rcv_plogi_unused_node,     /* RCV_PLOGI   UNUSED_NODE    */
-       lpfc_rcv_els_unused_node,       /* RCV_PRLI        */
-@@ -1818,7 +1945,7 @@
-       lpfc_disc_illegal,              /* DEVICE_RECOVERY */
-       lpfc_rcv_plogi_plogi_issue,     /* RCV_PLOGI   PLOGI_ISSUE    */
--      lpfc_rcv_els_plogi_issue,       /* RCV_PRLI        */
-+      lpfc_rcv_prli_plogi_issue,      /* RCV_PRLI        */
-       lpfc_rcv_logo_plogi_issue,      /* RCV_LOGO        */
-       lpfc_rcv_els_plogi_issue,       /* RCV_ADISC       */
-       lpfc_rcv_els_plogi_issue,       /* RCV_PDISC       */
-@@ -1917,34 +2044,40 @@
- };
- int
--lpfc_disc_state_machine(struct lpfc_hba * phba,
--                      struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
-+lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+                      void *arg, uint32_t evt)
- {
-+      struct lpfc_hba  *phba = vport->phba;
-       uint32_t cur_state, rc;
--      uint32_t(*func) (struct lpfc_hba *, struct lpfc_nodelist *, void *,
-+      uint32_t(*func) (struct lpfc_vport *, struct lpfc_nodelist *, void *,
-                        uint32_t);
-       lpfc_nlp_get(ndlp);
-       cur_state = ndlp->nlp_state;
-       /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */
--      lpfc_printf_log(phba,
--                      KERN_INFO,
--                      LOG_DISCOVERY,
--                      "%d:0211 DSM in event x%x on NPort x%x in state %d "
--                      "Data: x%x\n",
--                      phba->brd_no,
-+      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                      "%d (%d):0211 DSM in event x%x on NPort x%x in "
-+                      "state %d Data: x%x\n",
-+                      phba->brd_no, vport->vpi,
-                       evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag);
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
-+               "DSM in:          evt:%d ste:%d did:x%x",
-+              evt, cur_state, ndlp->nlp_DID);
-+
-       func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt];
--      rc = (func) (phba, ndlp, arg, evt);
-+      rc = (func) (vport, ndlp, arg, evt);
-       /* DSM out state <rc> on NPort <nlp_DID> */
--      lpfc_printf_log(phba,
--                     KERN_INFO,
--                     LOG_DISCOVERY,
--                     "%d:0212 DSM out state %d on NPort x%x Data: x%x\n",
--                     phba->brd_no,
-+      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-+                      "%d (%d):0212 DSM out state %d on NPort x%x "
-+                      "Data: x%x\n",
-+                      phba->brd_no, vport->vpi,
-+                      rc, ndlp->nlp_DID, ndlp->nlp_flag);
-+
-+      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
-+               "DSM out:         ste:%d did:x%x flg:x%x",
-                      rc, ndlp->nlp_DID, ndlp->nlp_flag);
-       lpfc_nlp_put(ndlp);
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_scsi.c linux-2.6.22-590/drivers/scsi/lpfc/lpfc_scsi.c
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_scsi.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_scsi.c     2008-01-02 13:56:37.000000000 -0500
-@@ -37,10 +37,158 @@
- #include "lpfc.h"
- #include "lpfc_logmsg.h"
- #include "lpfc_crtn.h"
-+#include "lpfc_vport.h"
- #define LPFC_RESET_WAIT  2
- #define LPFC_ABORT_WAIT  2
-+/*
-+ * This function is called with no lock held when there is a resource
-+ * error in driver or in firmware.
-+ */
-+void
-+lpfc_adjust_queue_depth(struct lpfc_hba *phba)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&phba->hbalock, flags);
-+      atomic_inc(&phba->num_rsrc_err);
-+      phba->last_rsrc_error_time = jiffies;
-+
-+      if ((phba->last_ramp_down_time + QUEUE_RAMP_DOWN_INTERVAL) > jiffies) {
-+              spin_unlock_irqrestore(&phba->hbalock, flags);
-+              return;
-+      }
-+
-+      phba->last_ramp_down_time = jiffies;
-+
-+      spin_unlock_irqrestore(&phba->hbalock, flags);
-+
-+      spin_lock_irqsave(&phba->pport->work_port_lock, flags);
-+      if ((phba->pport->work_port_events &
-+              WORKER_RAMP_DOWN_QUEUE) == 0) {
-+              phba->pport->work_port_events |= WORKER_RAMP_DOWN_QUEUE;
-+      }
-+      spin_unlock_irqrestore(&phba->pport->work_port_lock, flags);
-+
-+      spin_lock_irqsave(&phba->hbalock, flags);
-+      if (phba->work_wait)
-+              wake_up(phba->work_wait);
-+      spin_unlock_irqrestore(&phba->hbalock, flags);
-+
-+      return;
-+}
-+
-+/*
-+ * This function is called with no lock held when there is a successful
-+ * SCSI command completion.
-+ */
-+static inline void
-+lpfc_rampup_queue_depth(struct lpfc_hba *phba,
-+                      struct scsi_device *sdev)
-+{
-+      unsigned long flags;
-+      atomic_inc(&phba->num_cmd_success);
-+
-+      if (phba->cfg_lun_queue_depth <= sdev->queue_depth)
-+              return;
-+
-+      spin_lock_irqsave(&phba->hbalock, flags);
-+      if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) ||
-+       ((phba->last_rsrc_error_time + QUEUE_RAMP_UP_INTERVAL ) > jiffies)) {
-+              spin_unlock_irqrestore(&phba->hbalock, flags);
-+              return;
-+      }
-+
-+      phba->last_ramp_up_time = jiffies;
-+      spin_unlock_irqrestore(&phba->hbalock, flags);
-+
-+      spin_lock_irqsave(&phba->pport->work_port_lock, flags);
-+      if ((phba->pport->work_port_events &
-+              WORKER_RAMP_UP_QUEUE) == 0) {
-+              phba->pport->work_port_events |= WORKER_RAMP_UP_QUEUE;
-+      }
-+      spin_unlock_irqrestore(&phba->pport->work_port_lock, flags);
-+
-+      spin_lock_irqsave(&phba->hbalock, flags);
-+      if (phba->work_wait)
-+              wake_up(phba->work_wait);
-+      spin_unlock_irqrestore(&phba->hbalock, flags);
-+}
-+
-+void
-+lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
-+{
-+      struct lpfc_vport *vport;
-+      struct Scsi_Host  *host;
-+      struct scsi_device *sdev;
-+      unsigned long new_queue_depth;
-+      unsigned long num_rsrc_err, num_cmd_success;
-+
-+      num_rsrc_err = atomic_read(&phba->num_rsrc_err);
-+      num_cmd_success = atomic_read(&phba->num_cmd_success);
-+
-+      spin_lock_irq(&phba->hbalock);
-+      list_for_each_entry(vport, &phba->port_list, listentry) {
-+              host = lpfc_shost_from_vport(vport);
-+              if (!scsi_host_get(host))
-+                      continue;
-+
-+              spin_unlock_irq(&phba->hbalock);
-+
-+              shost_for_each_device(sdev, host) {
-+                      new_queue_depth = sdev->queue_depth * num_rsrc_err /
-+                      (num_rsrc_err + num_cmd_success);
-+                      if (!new_queue_depth)
-+                              new_queue_depth = sdev->queue_depth - 1;
-+                      else
-+                              new_queue_depth =
-+                                      sdev->queue_depth - new_queue_depth;
-+
-+                      if (sdev->ordered_tags)
-+                              scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
-+                                      new_queue_depth);
-+                      else
-+                              scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG,
-+                                      new_queue_depth);
-+              }
-+              spin_lock_irq(&phba->hbalock);
-+              scsi_host_put(host);
-+      }
-+      spin_unlock_irq(&phba->hbalock);
-+      atomic_set(&phba->num_rsrc_err, 0);
-+      atomic_set(&phba->num_cmd_success, 0);
-+}
-+
-+void
-+lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
-+{
-+      struct lpfc_vport *vport;
-+      struct Scsi_Host  *host;
-+      struct scsi_device *sdev;
-+
-+      spin_lock_irq(&phba->hbalock);
-+      list_for_each_entry(vport, &phba->port_list, listentry) {
-+              host = lpfc_shost_from_vport(vport);
-+              if (!scsi_host_get(host))
-+                      continue;
-+
-+              spin_unlock_irq(&phba->hbalock);
-+              shost_for_each_device(sdev, host) {
-+                      if (sdev->ordered_tags)
-+                              scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
-+                                      sdev->queue_depth+1);
-+                      else
-+                              scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG,
-+                                      sdev->queue_depth+1);
-+              }
-+              spin_lock_irq(&phba->hbalock);
-+              scsi_host_put(host);
-+      }
-+      spin_unlock_irq(&phba->hbalock);
-+      atomic_set(&phba->num_rsrc_err, 0);
-+      atomic_set(&phba->num_cmd_success, 0);
-+}
- /*
-  * This routine allocates a scsi buffer, which contains all the necessary
-@@ -51,8 +199,9 @@
-  * and the BPL BDE is setup in the IOCB.
-  */
- static struct lpfc_scsi_buf *
--lpfc_new_scsi_buf(struct lpfc_hba * phba)
-+lpfc_new_scsi_buf(struct lpfc_vport *vport)
- {
-+      struct lpfc_hba *phba = vport->phba;
-       struct lpfc_scsi_buf *psb;
-       struct ulp_bde64 *bpl;
-       IOCB_t *iocb;
-@@ -63,7 +212,6 @@
-       if (!psb)
-               return NULL;
-       memset(psb, 0, sizeof (struct lpfc_scsi_buf));
--      psb->scsi_hba = phba;
-       /*
-        * Get memory from the pci pool to map the virt space to pci bus space
-@@ -155,7 +303,7 @@
- }
- static void
--lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
-+lpfc_release_scsi_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
- {
-       unsigned long iflag = 0;
-@@ -166,7 +314,7 @@
- }
- static int
--lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
-+lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
- {
-       struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
-       struct scatterlist *sgel = NULL;
-@@ -175,8 +323,7 @@
-       IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
-       dma_addr_t physaddr;
-       uint32_t i, num_bde = 0;
--      int datadir = scsi_cmnd->sc_data_direction;
--      int dma_error;
-+      int nseg, datadir = scsi_cmnd->sc_data_direction;
-       /*
-        * There are three possibilities here - use scatter-gather segment, use
-@@ -185,26 +332,22 @@
-        * data bde entry.
-        */
-       bpl += 2;
--      if (scsi_cmnd->use_sg) {
-+      nseg = scsi_dma_map(scsi_cmnd);
-+      if (nseg > 0) {
-               /*
-                * The driver stores the segment count returned from pci_map_sg
-                * because this a count of dma-mappings used to map the use_sg
-                * pages.  They are not guaranteed to be the same for those
-                * architectures that implement an IOMMU.
-                */
--              sgel = (struct scatterlist *)scsi_cmnd->request_buffer;
--              lpfc_cmd->seg_cnt = dma_map_sg(&phba->pcidev->dev, sgel,
--                                              scsi_cmnd->use_sg, datadir);
--              if (lpfc_cmd->seg_cnt == 0)
--                      return 1;
-+              lpfc_cmd->seg_cnt = nseg;
-               if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
-                       printk(KERN_ERR "%s: Too many sg segments from "
-                              "dma_map_sg.  Config %d, seg_cnt %d",
-                              __FUNCTION__, phba->cfg_sg_seg_cnt,
-                              lpfc_cmd->seg_cnt);
--                      dma_unmap_sg(&phba->pcidev->dev, sgel,
--                                   lpfc_cmd->seg_cnt, datadir);
-+                      scsi_dma_unmap(scsi_cmnd);
-                       return 1;
-               }
-@@ -214,7 +357,7 @@
-                * single scsi command.  Just run through the seg_cnt and format
-                * the bde's.
-                */
--              for (i = 0; i < lpfc_cmd->seg_cnt; i++) {
-+              scsi_for_each_sg(scsi_cmnd, sgel, nseg, i) {
-                       physaddr = sg_dma_address(sgel);
-                       bpl->addrLow = le32_to_cpu(putPaddrLow(physaddr));
-                       bpl->addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
-@@ -225,35 +368,10 @@
-                               bpl->tus.f.bdeFlags = BUFF_USE_RCV;
-                       bpl->tus.w = le32_to_cpu(bpl->tus.w);
-                       bpl++;
--                      sgel++;
-                       num_bde++;
-               }
--      } else if (scsi_cmnd->request_buffer && scsi_cmnd->request_bufflen) {
--              physaddr = dma_map_single(&phba->pcidev->dev,
--                                        scsi_cmnd->request_buffer,
--                                        scsi_cmnd->request_bufflen,
--                                        datadir);
--              dma_error = dma_mapping_error(physaddr);
--              if (dma_error) {
--                      lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
--                              "%d:0718 Unable to dma_map_single "
--                              "request_buffer: x%x\n",
--                              phba->brd_no, dma_error);
-+      } else if (nseg < 0)
-                       return 1;
--              }
+-      /* Create shared ring, alloc event channel. */
+-      err = setup_netfront(dev, info);
+-      if (err)
+-              goto out;
 -
--              lpfc_cmd->nonsg_phys = physaddr;
--              bpl->addrLow = le32_to_cpu(putPaddrLow(physaddr));
--              bpl->addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
--              bpl->tus.f.bdeSize = scsi_cmnd->request_bufflen;
--              if (datadir == DMA_TO_DEVICE)
--                      bpl->tus.f.bdeFlags = 0;
--              else
--                      bpl->tus.f.bdeFlags = BUFF_USE_RCV;
--              bpl->tus.w = le32_to_cpu(bpl->tus.w);
--              num_bde = 1;
--              bpl++;
+-again:
+-      err = xenbus_transaction_start(&xbt);
+-      if (err) {
+-              xenbus_dev_fatal(dev, err, "starting transaction");
+-              goto destroy_ring;
 -      }
-       /*
-        * Finish initializing those IOCB fields that are dependent on the
-@@ -266,7 +384,7 @@
-               (num_bde * sizeof (struct ulp_bde64));
-       iocb_cmd->ulpBdeCount = 1;
-       iocb_cmd->ulpLe = 1;
--      fcp_cmnd->fcpDl = be32_to_cpu(scsi_cmnd->request_bufflen);
-+      fcp_cmnd->fcpDl = be32_to_cpu(scsi_bufflen(scsi_cmnd));
-       return 0;
- }
-@@ -279,26 +397,20 @@
-        * a request buffer, but did not request use_sg.  There is a third
-        * case, but it does not require resource deallocation.
-        */
--      if ((psb->seg_cnt > 0) && (psb->pCmd->use_sg)) {
--              dma_unmap_sg(&phba->pcidev->dev, psb->pCmd->request_buffer,
--                              psb->seg_cnt, psb->pCmd->sc_data_direction);
--      } else {
--               if ((psb->nonsg_phys) && (psb->pCmd->request_bufflen)) {
--                      dma_unmap_single(&phba->pcidev->dev, psb->nonsg_phys,
--                                              psb->pCmd->request_bufflen,
--                                              psb->pCmd->sc_data_direction);
--               }
+-
+-      err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u",
+-                          info->tx_ring_ref);
+-      if (err) {
+-              message = "writing tx ring-ref";
+-              goto abort_transaction;
+-      }
+-      err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u",
+-                          info->rx_ring_ref);
+-      if (err) {
+-              message = "writing rx ring-ref";
+-              goto abort_transaction;
+-      }
+-      err = xenbus_printf(xbt, dev->nodename,
+-                          "event-channel", "%u", info->evtchn);
+-      if (err) {
+-              message = "writing event-channel";
+-              goto abort_transaction;
+-      }
+-
+-      err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u",
+-                          info->copying_receiver);
+-      if (err) {
+-              message = "writing request-rx-copy";
+-              goto abort_transaction;
+-      }
+-
+-      err = xenbus_printf(xbt, dev->nodename, "feature-rx-notify", "%d", 1);
+-      if (err) {
+-              message = "writing feature-rx-notify";
+-              goto abort_transaction;
+-      }
+-
+-      err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1);
+-      if (err) {
+-              message = "writing feature-sg";
+-              goto abort_transaction;
 -      }
-+      if (psb->seg_cnt > 0)
-+              scsi_dma_unmap(psb->pCmd);
- }
- static void
--lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb)
-+lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
-+                  struct lpfc_iocbq *rsp_iocb)
- {
-       struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
-       struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd;
-       struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
--      struct lpfc_hba *phba = lpfc_cmd->scsi_hba;
-+      struct lpfc_hba *phba = vport->phba;
-       uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm;
-+      uint32_t vpi = vport->vpi;
-       uint32_t resp_info = fcprsp->rspStatus2;
-       uint32_t scsi_status = fcprsp->rspStatus3;
-       uint32_t *lp;
-@@ -331,9 +443,9 @@
-               logit = LOG_FCP;
-       lpfc_printf_log(phba, KERN_WARNING, logit,
--                      "%d:0730 FCP command x%x failed: x%x SNS x%x x%x "
-+                      "%d (%d):0730 FCP command x%x failed: x%x SNS x%x x%x "
-                       "Data: x%x x%x x%x x%x x%x\n",
--                      phba->brd_no, cmnd->cmnd[0], scsi_status,
-+                      phba->brd_no, vpi, cmnd->cmnd[0], scsi_status,
-                       be32_to_cpu(*lp), be32_to_cpu(*(lp + 3)), resp_info,
-                       be32_to_cpu(fcprsp->rspResId),
-                       be32_to_cpu(fcprsp->rspSnsLen),
-@@ -349,15 +461,16 @@
-               }
-       }
--      cmnd->resid = 0;
-+      scsi_set_resid(cmnd, 0);
-       if (resp_info & RESID_UNDER) {
--              cmnd->resid = be32_to_cpu(fcprsp->rspResId);
-+              scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId));
-               lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
--                              "%d:0716 FCP Read Underrun, expected %d, "
--                              "residual %d Data: x%x x%x x%x\n", phba->brd_no,
--                              be32_to_cpu(fcpcmd->fcpDl), cmnd->resid,
--                              fcpi_parm, cmnd->cmnd[0], cmnd->underflow);
-+                              "%d (%d):0716 FCP Read Underrun, expected %d, "
-+                              "residual %d Data: x%x x%x x%x\n",
-+                              phba->brd_no, vpi, be32_to_cpu(fcpcmd->fcpDl),
-+                              scsi_get_resid(cmnd), fcpi_parm, cmnd->cmnd[0],
-+                              cmnd->underflow);
-               /*
-                * If there is an under run check if under run reported by
-@@ -366,15 +479,16 @@
-                */
-               if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) &&
-                       fcpi_parm &&
--                      (cmnd->resid != fcpi_parm)) {
-+                      (scsi_get_resid(cmnd) != fcpi_parm)) {
-                       lpfc_printf_log(phba, KERN_WARNING,
-                               LOG_FCP | LOG_FCP_ERROR,
--                              "%d:0735 FCP Read Check Error and Underrun "
--                              "Data: x%x x%x x%x x%x\n", phba->brd_no,
-+                                      "%d (%d):0735 FCP Read Check Error "
-+                                      "and Underrun Data: x%x x%x x%x x%x\n",
-+                                      phba->brd_no, vpi,
-                               be32_to_cpu(fcpcmd->fcpDl),
--                              cmnd->resid,
--                              fcpi_parm, cmnd->cmnd[0]);
--                      cmnd->resid = cmnd->request_bufflen;
-+                                      scsi_get_resid(cmnd), fcpi_parm,
-+                                      cmnd->cmnd[0]);
-+                      scsi_set_resid(cmnd, scsi_bufflen(cmnd));
-                       host_status = DID_ERROR;
-               }
-               /*
-@@ -385,22 +499,23 @@
-                */
-               if (!(resp_info & SNS_LEN_VALID) &&
-                   (scsi_status == SAM_STAT_GOOD) &&
--                  (cmnd->request_bufflen - cmnd->resid) < cmnd->underflow) {
-+                  (scsi_bufflen(cmnd) - scsi_get_resid(cmnd)
-+                   < cmnd->underflow)) {
-                       lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
--                                      "%d:0717 FCP command x%x residual "
-+                                      "%d (%d):0717 FCP command x%x residual "
-                                       "underrun converted to error "
--                                      "Data: x%x x%x x%x\n", phba->brd_no,
--                                      cmnd->cmnd[0], cmnd->request_bufflen,
--                                      cmnd->resid, cmnd->underflow);
--
-+                                      "Data: x%x x%x x%x\n",
-+                                      phba->brd_no, vpi, cmnd->cmnd[0],
-+                                      cmnd->request_bufflen,
-+                                      scsi_get_resid(cmnd), cmnd->underflow);
-                       host_status = DID_ERROR;
-               }
-       } else if (resp_info & RESID_OVER) {
-               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
--                              "%d:0720 FCP command x%x residual "
-+                              "%d (%d):0720 FCP command x%x residual "
-                               "overrun error. Data: x%x x%x \n",
--                              phba->brd_no, cmnd->cmnd[0],
--                              cmnd->request_bufflen, cmnd->resid);
-+                              phba->brd_no, vpi, cmnd->cmnd[0],
-+                              scsi_bufflen(cmnd), scsi_get_resid(cmnd));
-               host_status = DID_ERROR;
-       /*
-@@ -410,13 +525,14 @@
-       } else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm &&
-                       (cmnd->sc_data_direction == DMA_FROM_DEVICE)) {
-               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR,
--                      "%d:0734 FCP Read Check Error Data: "
--                      "x%x x%x x%x x%x\n", phba->brd_no,
-+                              "%d (%d):0734 FCP Read Check Error Data: "
-+                              "x%x x%x x%x x%x\n",
-+                              phba->brd_no, vpi,
-                       be32_to_cpu(fcpcmd->fcpDl),
-                       be32_to_cpu(fcprsp->rspResId),
-                       fcpi_parm, cmnd->cmnd[0]);
-               host_status = DID_ERROR;
--              cmnd->resid = cmnd->request_bufflen;
-+              scsi_set_resid(cmnd, scsi_bufflen(cmnd));
-       }
-  out:
-@@ -429,9 +545,13 @@
- {
-       struct lpfc_scsi_buf *lpfc_cmd =
-               (struct lpfc_scsi_buf *) pIocbIn->context1;
-+      struct lpfc_vport      *vport = pIocbIn->vport;
-       struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
-       struct lpfc_nodelist *pnode = rdata->pnode;
-       struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
-+      uint32_t vpi = (lpfc_cmd->cur_iocbq.vport
-+                      ? lpfc_cmd->cur_iocbq.vport->vpi
-+                      : 0);
-       int result;
-       struct scsi_device *sdev, *tmp_sdev;
-       int depth = 0;
-@@ -447,22 +567,31 @@
-                       lpfc_cmd->status = IOSTAT_DEFAULT;
-               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
--                              "%d:0729 FCP cmd x%x failed <%d/%d> status: "
--                              "x%x result: x%x Data: x%x x%x\n",
--                              phba->brd_no, cmd->cmnd[0], cmd->device->id,
--                              cmd->device->lun, lpfc_cmd->status,
--                              lpfc_cmd->result, pIocbOut->iocb.ulpContext,
-+                              "%d (%d):0729 FCP cmd x%x failed <%d/%d> "
-+                              "status: x%x result: x%x Data: x%x x%x\n",
-+                              phba->brd_no, vpi, cmd->cmnd[0],
-+                              cmd->device ? cmd->device->id : 0xffff,
-+                              cmd->device ? cmd->device->lun : 0xffff,
-+                              lpfc_cmd->status, lpfc_cmd->result,
-+                              pIocbOut->iocb.ulpContext,
-                               lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
-               switch (lpfc_cmd->status) {
-               case IOSTAT_FCP_RSP_ERROR:
-                       /* Call FCP RSP handler to determine result */
--                      lpfc_handle_fcp_err(lpfc_cmd,pIocbOut);
-+                      lpfc_handle_fcp_err(vport, lpfc_cmd, pIocbOut);
-                       break;
-               case IOSTAT_NPORT_BSY:
-               case IOSTAT_FABRIC_BSY:
-                       cmd->result = ScsiResult(DID_BUS_BUSY, 0);
-                       break;
-+              case IOSTAT_LOCAL_REJECT:
-+                      if (lpfc_cmd->result == RJT_UNAVAIL_PERM ||
-+                          lpfc_cmd->result == IOERR_NO_RESOURCES ||
-+                          lpfc_cmd->result == RJT_LOGIN_REQUIRED) {
-+                              cmd->result = ScsiResult(DID_REQUEUE, 0);
-+                      break;
-+              } /* else: fall through */
-               default:
-                       cmd->result = ScsiResult(DID_ERROR, 0);
-                       break;
-@@ -479,11 +608,12 @@
-               uint32_t *lp = (uint32_t *)cmd->sense_buffer;
-               lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
--                              "%d:0710 Iodone <%d/%d> cmd %p, error x%x "
--                              "SNS x%x x%x Data: x%x x%x\n",
--                              phba->brd_no, cmd->device->id,
-+                              "%d (%d):0710 Iodone <%d/%d> cmd %p, error "
-+                              "x%x SNS x%x x%x Data: x%x x%x\n",
-+                              phba->brd_no, vpi, cmd->device->id,
-                               cmd->device->lun, cmd, cmd->result,
--                              *lp, *(lp + 3), cmd->retries, cmd->resid);
-+                              *lp, *(lp + 3), cmd->retries,
-+                              scsi_get_resid(cmd));
-       }
-       result = cmd->result;
-@@ -496,6 +626,10 @@
-               return;
-       }
-+
-+      if (!result)
-+              lpfc_rampup_queue_depth(phba, sdev);
-+
-       if (!result && pnode != NULL &&
-          ((jiffies - pnode->last_ramp_up_time) >
-               LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
-@@ -544,8 +678,9 @@
-               if (depth) {
-                       lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
--                              "%d:0711 detected queue full - lun queue depth "
--                              " adjusted to %d.\n", phba->brd_no, depth);
-+                                      "%d (%d):0711 detected queue full - "
-+                                      "lun queue depth  adjusted to %d.\n",
-+                                      phba->brd_no, vpi, depth);
-               }
-       }
-@@ -553,9 +688,10 @@
- }
- static void
--lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd,
-+lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
-                       struct lpfc_nodelist *pnode)
- {
-+      struct lpfc_hba *phba = vport->phba;
-       struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
-       struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
-       IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
-@@ -592,22 +728,7 @@
-        * bumping the bpl beyond the fcp_cmnd and fcp_rsp regions to the first
-        * data bde entry.
-        */
--      if (scsi_cmnd->use_sg) {
--              if (datadir == DMA_TO_DEVICE) {
--                      iocb_cmd->ulpCommand = CMD_FCP_IWRITE64_CR;
--                      iocb_cmd->un.fcpi.fcpi_parm = 0;
--                      iocb_cmd->ulpPU = 0;
--                      fcp_cmnd->fcpCntl3 = WRITE_DATA;
--                      phba->fc4OutputRequests++;
--              } else {
--                      iocb_cmd->ulpCommand = CMD_FCP_IREAD64_CR;
--                      iocb_cmd->ulpPU = PARM_READ_CHECK;
--                      iocb_cmd->un.fcpi.fcpi_parm =
--                              scsi_cmnd->request_bufflen;
--                      fcp_cmnd->fcpCntl3 = READ_DATA;
--                      phba->fc4InputRequests++;
--              }
--      } else if (scsi_cmnd->request_buffer && scsi_cmnd->request_bufflen) {
-+      if (scsi_sg_count(scsi_cmnd)) {
-               if (datadir == DMA_TO_DEVICE) {
-                       iocb_cmd->ulpCommand = CMD_FCP_IWRITE64_CR;
-                       iocb_cmd->un.fcpi.fcpi_parm = 0;
-@@ -617,8 +738,7 @@
-               } else {
-                       iocb_cmd->ulpCommand = CMD_FCP_IREAD64_CR;
-                       iocb_cmd->ulpPU = PARM_READ_CHECK;
--                      iocb_cmd->un.fcpi.fcpi_parm =
--                              scsi_cmnd->request_bufflen;
-+                      iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd);
-                       fcp_cmnd->fcpCntl3 = READ_DATA;
-                       phba->fc4InputRequests++;
-               }
-@@ -642,15 +762,15 @@
-       piocbq->context1  = lpfc_cmd;
-       piocbq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl;
-       piocbq->iocb.ulpTimeout = lpfc_cmd->timeout;
-+      piocbq->vport = vport;
- }
- static int
--lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
-+lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
-                            struct lpfc_scsi_buf *lpfc_cmd,
-                            unsigned int lun,
-                            uint8_t task_mgmt_cmd)
- {
--      struct lpfc_sli *psli;
-       struct lpfc_iocbq *piocbq;
-       IOCB_t *piocb;
-       struct fcp_cmnd *fcp_cmnd;
-@@ -661,8 +781,9 @@
-               return 0;
-       }
--      psli = &phba->sli;
-       piocbq = &(lpfc_cmd->cur_iocbq);
-+      piocbq->vport = vport;
-+
-       piocb = &piocbq->iocb;
-       fcp_cmnd = lpfc_cmd->fcp_cmnd;
-@@ -688,7 +809,7 @@
-               piocb->ulpTimeout = lpfc_cmd->timeout;
-       }
--      return (1);
-+      return 1;
- }
- static void
-@@ -704,10 +825,11 @@
- }
- static int
--lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
-+lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport,
-                   unsigned  tgt_id, unsigned int lun,
-                   struct lpfc_rport_data *rdata)
- {
-+      struct lpfc_hba   *phba = vport->phba;
-       struct lpfc_iocbq *iocbq;
-       struct lpfc_iocbq *iocbqrsp;
-       int ret;
-@@ -716,12 +838,11 @@
-               return FAILED;
-       lpfc_cmd->rdata = rdata;
--      ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, lun,
-+      ret = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun,
-                                          FCP_TARGET_RESET);
-       if (!ret)
-               return FAILED;
--      lpfc_cmd->scsi_hba = phba;
-       iocbq = &lpfc_cmd->cur_iocbq;
-       iocbqrsp = lpfc_sli_get_iocbq(phba);
-@@ -730,10 +851,10 @@
-       /* Issue Target Reset to TGT <num> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
--                      "%d:0702 Issue Target Reset to TGT %d "
-+                      "%d (%d):0702 Issue Target Reset to TGT %d "
-                       "Data: x%x x%x\n",
--                      phba->brd_no, tgt_id, rdata->pnode->nlp_rpi,
--                      rdata->pnode->nlp_flag);
-+                      phba->brd_no, vport->vpi, tgt_id,
-+                      rdata->pnode->nlp_rpi, rdata->pnode->nlp_flag);
-       ret = lpfc_sli_issue_iocb_wait(phba,
-                                      &phba->sli.ring[phba->sli.fcp_ring],
-@@ -758,7 +879,8 @@
- const char *
- lpfc_info(struct Scsi_Host *host)
- {
--      struct lpfc_hba    *phba = (struct lpfc_hba *) host->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) host->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       int len;
-       static char  lpfcinfobuf[384];
-@@ -800,25 +922,21 @@
- void lpfc_poll_timeout(unsigned long ptr)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
--      unsigned long iflag;
 -
--      spin_lock_irqsave(phba->host->host_lock, iflag);
-+      struct lpfc_hba *phba = (struct lpfc_hba *) ptr;
-       if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
-               lpfc_sli_poll_fcp_ring (phba);
-               if (phba->cfg_poll & DISABLE_FCP_RING_INT)
-                       lpfc_poll_rearm_timer(phba);
-       }
+-      err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%d", 1);
+-      if (err) {
+-              message = "writing feature-gso-tcpv4";
+-              goto abort_transaction;
+-      }
 -
--      spin_unlock_irqrestore(phba->host->host_lock, iflag);
- }
- static int
- lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
- {
--      struct lpfc_hba *phba =
--              (struct lpfc_hba *) cmnd->device->host->hostdata;
-+      struct Scsi_Host  *shost = cmnd->device->host;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       struct lpfc_sli *psli = &phba->sli;
-       struct lpfc_rport_data *rdata = cmnd->device->hostdata;
-       struct lpfc_nodelist *ndlp = rdata->pnode;
-@@ -840,11 +958,14 @@
-               cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
-               goto out_fail_command;
-       }
--      lpfc_cmd = lpfc_get_scsi_buf (phba);
-+      lpfc_cmd = lpfc_get_scsi_buf(phba);
-       if (lpfc_cmd == NULL) {
-+              lpfc_adjust_queue_depth(phba);
-+
-               lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
--                              "%d:0707 driver's buffer pool is empty, "
--                              "IO busied\n", phba->brd_no);
-+                              "%d (%d):0707 driver's buffer pool is empty, "
-+                              "IO busied\n",
-+                              phba->brd_no, vport->vpi);
-               goto out_host_busy;
-       }
-@@ -862,7 +983,7 @@
-       if (err)
-               goto out_host_busy_free_buf;
--      lpfc_scsi_prep_cmnd(phba, lpfc_cmd, ndlp);
-+      lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp);
-       err = lpfc_sli_issue_iocb(phba, &phba->sli.ring[psli->fcp_ring],
-                               &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
-@@ -908,7 +1029,8 @@
- lpfc_abort_handler(struct scsi_cmnd *cmnd)
- {
-       struct Scsi_Host *shost = cmnd->device->host;
--      struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring];
-       struct lpfc_iocbq *iocb;
-       struct lpfc_iocbq *abtsiocb;
-@@ -918,8 +1040,6 @@
-       int ret = SUCCESS;
-       lpfc_block_error_handler(cmnd);
--      spin_lock_irq(shost->host_lock);
+-      err = xenbus_transaction_end(xbt, 0);
+-      if (err) {
+-              if (err == -EAGAIN)
+-                      goto again;
+-              xenbus_dev_fatal(dev, err, "completing transaction");
+-              goto destroy_ring;
+-      }
 -
-       lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
-       BUG_ON(!lpfc_cmd);
-@@ -956,12 +1076,13 @@
-       icmd->ulpLe = 1;
-       icmd->ulpClass = cmd->ulpClass;
--      if (phba->hba_state >= LPFC_LINK_UP)
-+      if (lpfc_is_link_up(phba))
-               icmd->ulpCommand = CMD_ABORT_XRI_CN;
-       else
-               icmd->ulpCommand = CMD_CLOSE_XRI_CN;
-       abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
-+      abtsiocb->vport = vport;
-       if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) == IOCB_ERROR) {
-               lpfc_sli_release_iocbq(phba, abtsiocb);
-               ret = FAILED;
-@@ -977,9 +1098,7 @@
-               if (phba->cfg_poll & DISABLE_FCP_RING_INT)
-                       lpfc_sli_poll_fcp_ring (phba);
--              spin_unlock_irq(phba->host->host_lock);
--                      schedule_timeout_uninterruptible(LPFC_ABORT_WAIT*HZ);
--              spin_lock_irq(phba->host->host_lock);
-+              schedule_timeout_uninterruptible(LPFC_ABORT_WAIT * HZ);
-               if (++loop_count
-                   > (2 * phba->cfg_devloss_tmo)/LPFC_ABORT_WAIT)
-                       break;
-@@ -988,22 +1107,21 @@
-       if (lpfc_cmd->pCmd == cmnd) {
-               ret = FAILED;
-               lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
--                              "%d:0748 abort handler timed out waiting for "
--                              "abort to complete: ret %#x, ID %d, LUN %d, "
--                              "snum %#lx\n",
--                              phba->brd_no,  ret, cmnd->device->id,
--                              cmnd->device->lun, cmnd->serial_number);
-+                              "%d (%d):0748 abort handler timed out waiting "
-+                              "for abort to complete: ret %#x, ID %d, "
-+                              "LUN %d, snum %#lx\n",
-+                              phba->brd_no, vport->vpi, ret,
-+                              cmnd->device->id, cmnd->device->lun,
-+                              cmnd->serial_number);
-       }
-  out:
-       lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
--                      "%d:0749 SCSI Layer I/O Abort Request "
-+                      "%d (%d):0749 SCSI Layer I/O Abort Request "
-                       "Status x%x ID %d LUN %d snum %#lx\n",
--                      phba->brd_no, ret, cmnd->device->id,
-+                      phba->brd_no, vport->vpi, ret, cmnd->device->id,
-                       cmnd->device->lun, cmnd->serial_number);
--      spin_unlock_irq(shost->host_lock);
+-      return 0;
+-
+- abort_transaction:
+-      xenbus_transaction_end(xbt, 1);
+-      xenbus_dev_fatal(dev, err, "%s", message);
+- destroy_ring:
+-      xennet_disconnect_backend(info);
+- out:
+-      return err;
+-}
+-
+-static int xennet_set_sg(struct net_device *dev, u32 data)
+-{
+-      if (data) {
+-              struct netfront_info *np = netdev_priv(dev);
+-              int val;
+-
+-              if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-sg",
+-                               "%d", &val) < 0)
+-                      val = 0;
+-              if (!val)
+-                      return -ENOSYS;
+-      } else if (dev->mtu > ETH_DATA_LEN)
+-              dev->mtu = ETH_DATA_LEN;
+-
+-      return ethtool_op_set_sg(dev, data);
+-}
+-
+-static int xennet_set_tso(struct net_device *dev, u32 data)
+-{
+-      if (data) {
+-              struct netfront_info *np = netdev_priv(dev);
+-              int val;
+-
+-              if (xenbus_scanf(XBT_NIL, np->xbdev->otherend,
+-                               "feature-gso-tcpv4", "%d", &val) < 0)
+-                      val = 0;
+-              if (!val)
+-                      return -ENOSYS;
+-      }
+-
+-      return ethtool_op_set_tso(dev, data);
+-}
+-
+-static void xennet_set_features(struct net_device *dev)
+-{
+-      /* Turn off all GSO bits except ROBUST. */
+-      dev->features &= (1 << NETIF_F_GSO_SHIFT) - 1;
+-      dev->features |= NETIF_F_GSO_ROBUST;
+-      xennet_set_sg(dev, 0);
+-
+-      /* We need checksum offload to enable scatter/gather and TSO. */
+-      if (!(dev->features & NETIF_F_IP_CSUM))
+-              return;
+-
+-      if (!xennet_set_sg(dev, 1))
+-              xennet_set_tso(dev, 1);
+-}
+-
+-static int xennet_connect(struct net_device *dev)
+-{
+-      struct netfront_info *np = netdev_priv(dev);
+-      int i, requeue_idx, err;
+-      struct sk_buff *skb;
+-      grant_ref_t ref;
+-      struct xen_netif_rx_request *req;
+-      unsigned int feature_rx_copy, feature_rx_flip;
+-
+-      err = xenbus_scanf(XBT_NIL, np->xbdev->otherend,
+-                         "feature-rx-copy", "%u", &feature_rx_copy);
+-      if (err != 1)
+-              feature_rx_copy = 0;
+-
+-      err = xenbus_scanf(XBT_NIL, np->xbdev->otherend,
+-                         "feature-rx-flip", "%u", &feature_rx_flip);
+-      /* Flip is the default, since it was once the only mode of
+-         operation. */
+-      if (err != 1)
+-              feature_rx_flip = 1;
+-
+-      /*
+-       * Copy packets on receive path if:
+-       *  (a) This was requested by user, and the backend supports it; or
+-       *  (b) Flipping was requested, but this is unsupported by the backend.
+-       */
+-      np->copying_receiver = (((rx_mode == RX_COPY) && feature_rx_copy) ||
+-                              ((rx_mode == RX_FLIP) && !feature_rx_flip));
+-
+-      err = talk_to_backend(np->xbdev, np);
+-      if (err)
+-              return err;
+-
+-      xennet_set_features(dev);
+-
+-      dev_info(&dev->dev, "has %s receive path.\n",
+-               np->copying_receiver ? "copying" : "flipping");
+-
+-      spin_lock_bh(&np->rx_lock);
+-      spin_lock_irq(&np->tx_lock);
+-
+-      /* Step 1: Discard all pending TX packet fragments. */
+-      xennet_release_tx_bufs(np);
+-
+-      /* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
+-      for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
+-              if (!np->rx_skbs[i])
+-                      continue;
+-
+-              skb = np->rx_skbs[requeue_idx] = xennet_get_rx_skb(np, i);
+-              ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i);
+-              req = RING_GET_REQUEST(&np->rx, requeue_idx);
+-
+-              if (!np->copying_receiver) {
+-                      gnttab_grant_foreign_transfer_ref(
+-                              ref, np->xbdev->otherend_id,
+-                              page_to_pfn(skb_shinfo(skb)->frags->page));
+-              } else {
+-                      gnttab_grant_foreign_access_ref(
+-                              ref, np->xbdev->otherend_id,
+-                              pfn_to_mfn(page_to_pfn(skb_shinfo(skb)->
+-                                                     frags->page)),
+-                              0);
+-              }
+-              req->gref = ref;
+-              req->id   = requeue_idx;
+-
+-              requeue_idx++;
+-      }
+-
+-      np->rx.req_prod_pvt = requeue_idx;
+-
+-      /*
+-       * Step 3: All public and private state should now be sane.  Get
+-       * ready to start sending and receiving packets and give the driver
+-       * domain a kick because we've probably just requeued some
+-       * packets.
+-       */
+-      netif_carrier_on(np->netdev);
+-      notify_remote_via_irq(np->netdev->irq);
+-      xennet_tx_buf_gc(dev);
+-      xennet_alloc_rx_buffers(dev);
+-
+-      spin_unlock_irq(&np->tx_lock);
+-      spin_unlock_bh(&np->rx_lock);
 -
-       return ret;
- }
-@@ -1011,7 +1129,8 @@
- lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
- {
-       struct Scsi_Host *shost = cmnd->device->host;
--      struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       struct lpfc_scsi_buf *lpfc_cmd;
-       struct lpfc_iocbq *iocbq, *iocbqrsp;
-       struct lpfc_rport_data *rdata = cmnd->device->hostdata;
-@@ -1022,28 +1141,26 @@
-       int cnt, loopcnt;
-       lpfc_block_error_handler(cmnd);
--      spin_lock_irq(shost->host_lock);
-       loopcnt = 0;
-       /*
-        * If target is not in a MAPPED state, delay the reset until
-        * target is rediscovered or devloss timeout expires.
-        */
--      while ( 1 ) {
-+      while (1) {
-               if (!pnode)
-                       goto out;
-               if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
--                      spin_unlock_irq(phba->host->host_lock);
-                       schedule_timeout_uninterruptible(msecs_to_jiffies(500));
--                      spin_lock_irq(phba->host->host_lock);
-                       loopcnt++;
-                       rdata = cmnd->device->hostdata;
-                       if (!rdata ||
-                               (loopcnt > ((phba->cfg_devloss_tmo * 2) + 1))) {
-                               lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
--                                      "%d:0721 LUN Reset rport failure:"
--                                      " cnt x%x rdata x%p\n",
--                                      phba->brd_no, loopcnt, rdata);
-+                                              "%d (%d):0721 LUN Reset rport "
-+                                              "failure: cnt x%x rdata x%p\n",
-+                                              phba->brd_no, vport->vpi,
-+                                              loopcnt, rdata);
-                               goto out;
-                       }
-                       pnode = rdata->pnode;
-@@ -1054,15 +1171,14 @@
-                       break;
-       }
--      lpfc_cmd = lpfc_get_scsi_buf (phba);
-+      lpfc_cmd = lpfc_get_scsi_buf(phba);
-       if (lpfc_cmd == NULL)
-               goto out;
-       lpfc_cmd->timeout = 60;
--      lpfc_cmd->scsi_hba = phba;
-       lpfc_cmd->rdata = rdata;
--      ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun,
-+      ret = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, cmnd->device->lun,
-                                          FCP_TARGET_RESET);
-       if (!ret)
-               goto out_free_scsi_buf;
-@@ -1075,8 +1191,9 @@
-               goto out_free_scsi_buf;
-       lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
--                      "%d:0703 Issue target reset to TGT %d LUN %d rpi x%x "
--                      "nlp_flag x%x\n", phba->brd_no, cmnd->device->id,
-+                      "%d (%d):0703 Issue target reset to TGT %d LUN %d "
-+                      "rpi x%x nlp_flag x%x\n",
-+                      phba->brd_no, vport->vpi, cmnd->device->id,
-                       cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
-       iocb_status = lpfc_sli_issue_iocb_wait(phba,
-@@ -1111,9 +1228,7 @@
-                                   0, LPFC_CTX_LUN);
-       loopcnt = 0;
-       while(cnt) {
--              spin_unlock_irq(phba->host->host_lock);
-               schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
--              spin_lock_irq(phba->host->host_lock);
-               if (++loopcnt
-                   > (2 * phba->cfg_devloss_tmo)/LPFC_RESET_WAIT)
-@@ -1127,8 +1242,9 @@
-       if (cnt) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
--                      "%d:0719 device reset I/O flush failure: cnt x%x\n",
--                      phba->brd_no, cnt);
-+                              "%d (%d):0719 device reset I/O flush failure: "
-+                              "cnt x%x\n",
-+                              phba->brd_no, vport->vpi, cnt);
-               ret = FAILED;
-       }
-@@ -1137,13 +1253,12 @@
-               lpfc_release_scsi_buf(phba, lpfc_cmd);
-       }
-       lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
--                      "%d:0713 SCSI layer issued device reset (%d, %d) "
-+                      "%d (%d):0713 SCSI layer issued device reset (%d, %d) "
-                       "return x%x status x%x result x%x\n",
--                      phba->brd_no, cmnd->device->id, cmnd->device->lun,
--                      ret, cmd_status, cmd_result);
-+                      phba->brd_no, vport->vpi, cmnd->device->id,
-+                      cmnd->device->lun, ret, cmd_status, cmd_result);
- out:
--      spin_unlock_irq(shost->host_lock);
-       return ret;
- }
-@@ -1151,7 +1266,8 @@
- lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
- {
-       struct Scsi_Host *shost = cmnd->device->host;
--      struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       struct lpfc_nodelist *ndlp = NULL;
-       int match;
-       int ret = FAILED, i, err_count = 0;
-@@ -1159,7 +1275,6 @@
-       struct lpfc_scsi_buf * lpfc_cmd;
-       lpfc_block_error_handler(cmnd);
--      spin_lock_irq(shost->host_lock);
-       lpfc_cmd = lpfc_get_scsi_buf(phba);
-       if (lpfc_cmd == NULL)
-@@ -1167,7 +1282,6 @@
-       /* The lpfc_cmd storage is reused.  Set all loop invariants. */
-       lpfc_cmd->timeout = 60;
--      lpfc_cmd->scsi_hba = phba;
-       /*
-        * Since the driver manages a single bus device, reset all
-@@ -1177,7 +1291,8 @@
-       for (i = 0; i < LPFC_MAX_TARGET; i++) {
-               /* Search for mapped node by target ID */
-               match = 0;
--              list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
-+              spin_lock_irq(shost->host_lock);
-+              list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
-                       if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
-                           i == ndlp->nlp_sid &&
-                           ndlp->rport) {
-@@ -1185,15 +1300,18 @@
-                               break;
-                       }
-               }
-+              spin_unlock_irq(shost->host_lock);
-               if (!match)
-                       continue;
--              ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba, i, cmnd->device->lun,
-+              ret = lpfc_scsi_tgt_reset(lpfc_cmd, vport, i,
-+                                        cmnd->device->lun,
-                                         ndlp->rport->dd_data);
-               if (ret != SUCCESS) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
--                              "%d:0700 Bus Reset on target %d failed\n",
--                              phba->brd_no, i);
-+                                      "%d (%d):0700 Bus Reset on target %d "
-+                                      "failed\n",
-+                                      phba->brd_no, vport->vpi, i);
-                       err_count++;
-                       break;
-               }
-@@ -1219,9 +1337,7 @@
-                                   0, 0, 0, LPFC_CTX_HOST);
-       loopcnt = 0;
-       while(cnt) {
--              spin_unlock_irq(phba->host->host_lock);
-               schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
--              spin_lock_irq(phba->host->host_lock);
-               if (++loopcnt
-                   > (2 * phba->cfg_devloss_tmo)/LPFC_RESET_WAIT)
-@@ -1234,25 +1350,24 @@
-       if (cnt) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
--                 "%d:0715 Bus Reset I/O flush failure: cnt x%x left x%x\n",
--                 phba->brd_no, cnt, i);
-+                              "%d (%d):0715 Bus Reset I/O flush failure: "
-+                              "cnt x%x left x%x\n",
-+                              phba->brd_no, vport->vpi, cnt, i);
-               ret = FAILED;
-       }
--      lpfc_printf_log(phba,
--                      KERN_ERR,
--                      LOG_FCP,
--                      "%d:0714 SCSI layer issued Bus Reset Data: x%x\n",
--                      phba->brd_no, ret);
-+      lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-+                      "%d (%d):0714 SCSI layer issued Bus Reset Data: x%x\n",
-+                      phba->brd_no, vport->vpi, ret);
- out:
--      spin_unlock_irq(shost->host_lock);
-       return ret;
- }
- static int
- lpfc_slave_alloc(struct scsi_device *sdev)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       struct lpfc_scsi_buf *scsi_buf = NULL;
-       struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
-       uint32_t total = 0, i;
-@@ -1273,27 +1388,35 @@
-        */
-       total = phba->total_scsi_bufs;
-       num_to_alloc = phba->cfg_lun_queue_depth + 2;
--      if (total >= phba->cfg_hba_queue_depth) {
-+
-+      /* Allow some exchanges to be available always to complete discovery */
-+      if (total >= phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) {
-               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
--                              "%d:0704 At limitation of %d preallocated "
--                              "command buffers\n", phba->brd_no, total);
-+                              "%d (%d):0704 At limitation of %d "
-+                              "preallocated command buffers\n",
-+                              phba->brd_no, vport->vpi, total);
-               return 0;
--      } else if (total + num_to_alloc > phba->cfg_hba_queue_depth) {
-+
-+      /* Allow some exchanges to be available always to complete discovery */
-+      } else if (total + num_to_alloc >
-+              phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) {
-               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
--                              "%d:0705 Allocation request of %d command "
--                              "buffers will exceed max of %d.  Reducing "
--                              "allocation request to %d.\n", phba->brd_no,
--                              num_to_alloc, phba->cfg_hba_queue_depth,
-+                              "%d (%d):0705 Allocation request of %d "
-+                              "command buffers will exceed max of %d.  "
-+                              "Reducing allocation request to %d.\n",
-+                              phba->brd_no, vport->vpi, num_to_alloc,
-+                              phba->cfg_hba_queue_depth,
-                               (phba->cfg_hba_queue_depth - total));
-               num_to_alloc = phba->cfg_hba_queue_depth - total;
-       }
-       for (i = 0; i < num_to_alloc; i++) {
--              scsi_buf = lpfc_new_scsi_buf(phba);
-+              scsi_buf = lpfc_new_scsi_buf(vport);
-               if (!scsi_buf) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
--                                      "%d:0706 Failed to allocate command "
--                                      "buffer\n", phba->brd_no);
-+                                      "%d (%d):0706 Failed to allocate "
-+                                      "command buffer\n",
-+                                      phba->brd_no, vport->vpi);
-                       break;
-               }
-@@ -1308,7 +1431,8 @@
- static int
- lpfc_slave_configure(struct scsi_device *sdev)
- {
--      struct lpfc_hba *phba = (struct lpfc_hba *) sdev->host->hostdata;
-+      struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
-+      struct lpfc_hba   *phba = vport->phba;
-       struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
-       if (sdev->tagged_supported)
-@@ -1340,6 +1464,7 @@
-       return;
- }
-+
- struct scsi_host_template lpfc_template = {
-       .module                 = THIS_MODULE,
-       .name                   = LPFC_DRIVER_NAME,
-@@ -1352,11 +1477,10 @@
-       .slave_configure        = lpfc_slave_configure,
-       .slave_destroy          = lpfc_slave_destroy,
-       .scan_finished          = lpfc_scan_finished,
--      .scan_start             = lpfc_scan_start,
-       .this_id                = -1,
-       .sg_tablesize           = LPFC_SG_SEG_CNT,
-       .cmd_per_lun            = LPFC_CMD_PER_LUN,
-       .use_clustering         = ENABLE_CLUSTERING,
--      .shost_attrs            = lpfc_host_attrs,
-+      .shost_attrs            = lpfc_hba_attrs,
-       .max_sectors            = 0xFFFF,
- };
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_scsi.h linux-2.6.22-590/drivers/scsi/lpfc/lpfc_scsi.h
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_scsi.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_scsi.h     2008-01-02 13:56:37.000000000 -0500
-@@ -1,7 +1,7 @@
- /*******************************************************************
-  * This file is part of the Emulex Linux Device Driver for         *
-  * Fibre Channel Host Bus Adapters.                                *
-- * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
-+ * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
-  * EMULEX and SLI are trademarks of Emulex.                        *
-  * www.emulex.com                                                  *
-  *                                                                 *
-@@ -110,7 +110,6 @@
- struct lpfc_scsi_buf {
-       struct list_head list;
-       struct scsi_cmnd *pCmd;
--      struct lpfc_hba *scsi_hba;
-       struct lpfc_rport_data *rdata;
-       uint32_t timeout;
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_sli.c linux-2.6.22-590/drivers/scsi/lpfc/lpfc_sli.c
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_sli.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_sli.c      2008-01-02 13:56:37.000000000 -0500
-@@ -38,23 +38,25 @@
- #include "lpfc_crtn.h"
- #include "lpfc_logmsg.h"
- #include "lpfc_compat.h"
-+#include "lpfc_debugfs.h"
- /*
-  * Define macro to log: Mailbox command x%x cannot issue Data
-  * This allows multiple uses of lpfc_msgBlk0311
-  * w/o perturbing log msg utility.
-  */
--#define LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag) \
-+#define LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag) \
-                       lpfc_printf_log(phba, \
-                               KERN_INFO, \
-                               LOG_MBOX | LOG_SLI, \
--                              "%d:0311 Mailbox command x%x cannot issue " \
--                              "Data: x%x x%x x%x\n", \
-+                              "%d (%d):0311 Mailbox command x%x cannot " \
-+                              "issue Data: x%x x%x x%x\n", \
-                               phba->brd_no, \
--                              mb->mbxCommand,         \
--                              phba->hba_state,        \
-+                              pmbox->vport ? pmbox->vport->vpi : 0, \
-+                              pmbox->mb.mbxCommand,           \
-+                              phba->pport->port_state,        \
-                               psli->sli_flag, \
--                              flag);
-+                              flag)
- /* There are only four IOCB completion types. */
-@@ -65,8 +67,26 @@
-       LPFC_ABORT_IOCB
- } lpfc_iocb_type;
--struct lpfc_iocbq *
--lpfc_sli_get_iocbq(struct lpfc_hba * phba)
-+              /* SLI-2/SLI-3 provide different sized iocbs.  Given a pointer
-+               * to the start of the ring, and the slot number of the
-+               * desired iocb entry, calc a pointer to that entry.
-+               */
-+static inline IOCB_t *
-+lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
-+{
-+      return (IOCB_t *) (((char *) pring->cmdringaddr) +
-+                         pring->cmdidx * phba->iocb_cmd_size);
-+}
-+
-+static inline IOCB_t *
-+lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
-+{
-+      return (IOCB_t *) (((char *) pring->rspringaddr) +
-+                         pring->rspidx * phba->iocb_rsp_size);
-+}
-+
-+static struct lpfc_iocbq *
-+__lpfc_sli_get_iocbq(struct lpfc_hba *phba)
- {
-       struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
-       struct lpfc_iocbq * iocbq = NULL;
-@@ -75,10 +95,22 @@
-       return iocbq;
- }
-+struct lpfc_iocbq *
-+lpfc_sli_get_iocbq(struct lpfc_hba *phba)
-+{
-+      struct lpfc_iocbq * iocbq = NULL;
-+      unsigned long iflags;
-+
-+      spin_lock_irqsave(&phba->hbalock, iflags);
-+      iocbq = __lpfc_sli_get_iocbq(phba);
-+      spin_unlock_irqrestore(&phba->hbalock, iflags);
-+      return iocbq;
-+}
-+
- void
--lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
-+__lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
- {
--      size_t start_clean = (size_t)(&((struct lpfc_iocbq *)NULL)->iocb);
-+      size_t start_clean = offsetof(struct lpfc_iocbq, iocb);
-       /*
-        * Clean all volatile data fields, preserve iotag and node struct.
-@@ -87,6 +119,19 @@
-       list_add_tail(&iocbq->list, &phba->lpfc_iocb_list);
- }
-+void
-+lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
-+{
-+      unsigned long iflags;
-+
-+      /*
-+       * Clean all volatile data fields, preserve iotag and node struct.
-+       */
-+      spin_lock_irqsave(&phba->hbalock, iflags);
-+      __lpfc_sli_release_iocbq(phba, iocbq);
-+      spin_unlock_irqrestore(&phba->hbalock, iflags);
-+}
-+
- /*
-  * Translate the iocb command to an iocb command type used to decide the final
-  * disposition of each completed IOCB.
-@@ -155,6 +200,9 @@
-       case CMD_RCV_ELS_REQ_CX:
-       case CMD_RCV_SEQUENCE64_CX:
-       case CMD_RCV_ELS_REQ64_CX:
-+      case CMD_IOCB_RCV_SEQ64_CX:
-+      case CMD_IOCB_RCV_ELS64_CX:
-+      case CMD_IOCB_RCV_CONT64_CX:
-               type = LPFC_UNSOL_IOCB;
-               break;
-       default:
-@@ -166,73 +214,77 @@
- }
- static int
--lpfc_sli_ring_map(struct lpfc_hba * phba, LPFC_MBOXQ_t *pmb)
-+lpfc_sli_ring_map(struct lpfc_hba *phba)
- {
-       struct lpfc_sli *psli = &phba->sli;
--      MAILBOX_t *pmbox = &pmb->mb;
--      int i, rc;
-+      LPFC_MBOXQ_t *pmb;
-+      MAILBOX_t *pmbox;
-+      int i, rc, ret = 0;
-+      pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (!pmb)
-+              return -ENOMEM;
-+      pmbox = &pmb->mb;
-+      phba->link_state = LPFC_INIT_MBX_CMDS;
-       for (i = 0; i < psli->num_rings; i++) {
--              phba->hba_state = LPFC_INIT_MBX_CMDS;
-               lpfc_config_ring(phba, i, pmb);
-               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
-               if (rc != MBX_SUCCESS) {
--                      lpfc_printf_log(phba,
--                                      KERN_ERR,
--                                      LOG_INIT,
--                                      "%d:0446 Adapter failed to init, "
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-+                                      "%d:0446 Adapter failed to init (%d), "
-                                       "mbxCmd x%x CFG_RING, mbxStatus x%x, "
-                                       "ring %d\n",
--                                      phba->brd_no,
-+                                      phba->brd_no, rc,
-                                       pmbox->mbxCommand,
-                                       pmbox->mbxStatus,
-                                       i);
--                      phba->hba_state = LPFC_HBA_ERROR;
--                      return -ENXIO;
-+                      phba->link_state = LPFC_HBA_ERROR;
-+                      ret = -ENXIO;
-+                      break;
-               }
-       }
 -      return 0;
-+      mempool_free(pmb, phba->mbox_mem_pool);
-+      return ret;
- }
- static int
--lpfc_sli_ringtxcmpl_put(struct lpfc_hba * phba,
--                      struct lpfc_sli_ring * pring, struct lpfc_iocbq * piocb)
-+lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-+                      struct lpfc_iocbq *piocb)
- {
-       list_add_tail(&piocb->list, &pring->txcmplq);
-       pring->txcmplq_cnt++;
--      if (unlikely(pring->ringno == LPFC_ELS_RING))
--              mod_timer(&phba->els_tmofunc,
-+      if ((unlikely(pring->ringno == LPFC_ELS_RING)) &&
-+         (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
-+         (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) {
-+              if (!piocb->vport)
-+                      BUG();
-+              else
-+                      mod_timer(&piocb->vport->els_tmofunc,
-                                       jiffies + HZ * (phba->fc_ratov << 1));
-+      }
--      return (0);
-+
-+      return 0;
- }
- static struct lpfc_iocbq *
--lpfc_sli_ringtx_get(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
-+lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
- {
--      struct list_head *dlp;
-       struct lpfc_iocbq *cmd_iocb;
+-}
+-
+-/**
+- * Callback received when the backend's state changes.
+- */
+-static void backend_changed(struct xenbus_device *dev,
+-                          enum xenbus_state backend_state)
+-{
+-      struct netfront_info *np = dev->dev.driver_data;
+-      struct net_device *netdev = np->netdev;
+-
+-      dev_dbg(&dev->dev, "%s\n", xenbus_strstate(backend_state));
+-
+-      switch (backend_state) {
+-      case XenbusStateInitialising:
+-      case XenbusStateInitialised:
+-      case XenbusStateConnected:
+-      case XenbusStateUnknown:
+-      case XenbusStateClosed:
+-              break;
+-
+-      case XenbusStateInitWait:
+-              if (dev->state != XenbusStateInitialising)
+-                      break;
+-              if (xennet_connect(netdev) != 0)
+-                      break;
+-              xenbus_switch_state(dev, XenbusStateConnected);
+-              break;
+-
+-      case XenbusStateClosing:
+-              xenbus_frontend_closed(dev);
+-              break;
+-      }
+-}
+-
+-static struct ethtool_ops xennet_ethtool_ops =
+-{
+-      .get_tx_csum = ethtool_op_get_tx_csum,
+-      .set_tx_csum = ethtool_op_set_tx_csum,
+-      .get_sg = ethtool_op_get_sg,
+-      .set_sg = xennet_set_sg,
+-      .get_tso = ethtool_op_get_tso,
+-      .set_tso = xennet_set_tso,
+-      .get_link = ethtool_op_get_link,
+-};
+-
+-#ifdef CONFIG_SYSFS
+-static ssize_t show_rxbuf_min(struct device *dev,
+-                            struct device_attribute *attr, char *buf)
+-{
+-      struct net_device *netdev = to_net_dev(dev);
+-      struct netfront_info *info = netdev_priv(netdev);
+-
+-      return sprintf(buf, "%u\n", info->rx_min_target);
+-}
+-
+-static ssize_t store_rxbuf_min(struct device *dev,
+-                             struct device_attribute *attr,
+-                             const char *buf, size_t len)
+-{
+-      struct net_device *netdev = to_net_dev(dev);
+-      struct netfront_info *np = netdev_priv(netdev);
+-      char *endp;
+-      unsigned long target;
+-
+-      if (!capable(CAP_NET_ADMIN))
+-              return -EPERM;
+-
+-      target = simple_strtoul(buf, &endp, 0);
+-      if (endp == buf)
+-              return -EBADMSG;
+-
+-      if (target < RX_MIN_TARGET)
+-              target = RX_MIN_TARGET;
+-      if (target > RX_MAX_TARGET)
+-              target = RX_MAX_TARGET;
+-
+-      spin_lock_bh(&np->rx_lock);
+-      if (target > np->rx_max_target)
+-              np->rx_max_target = target;
+-      np->rx_min_target = target;
+-      if (target > np->rx_target)
+-              np->rx_target = target;
+-
+-      xennet_alloc_rx_buffers(netdev);
+-
+-      spin_unlock_bh(&np->rx_lock);
+-      return len;
+-}
+-
+-static ssize_t show_rxbuf_max(struct device *dev,
+-                            struct device_attribute *attr, char *buf)
+-{
+-      struct net_device *netdev = to_net_dev(dev);
+-      struct netfront_info *info = netdev_priv(netdev);
+-
+-      return sprintf(buf, "%u\n", info->rx_max_target);
+-}
+-
+-static ssize_t store_rxbuf_max(struct device *dev,
+-                             struct device_attribute *attr,
+-                             const char *buf, size_t len)
+-{
+-      struct net_device *netdev = to_net_dev(dev);
+-      struct netfront_info *np = netdev_priv(netdev);
+-      char *endp;
+-      unsigned long target;
+-
+-      if (!capable(CAP_NET_ADMIN))
+-              return -EPERM;
+-
+-      target = simple_strtoul(buf, &endp, 0);
+-      if (endp == buf)
+-              return -EBADMSG;
+-
+-      if (target < RX_MIN_TARGET)
+-              target = RX_MIN_TARGET;
+-      if (target > RX_MAX_TARGET)
+-              target = RX_MAX_TARGET;
+-
+-      spin_lock_bh(&np->rx_lock);
+-      if (target < np->rx_min_target)
+-              np->rx_min_target = target;
+-      np->rx_max_target = target;
+-      if (target < np->rx_target)
+-              np->rx_target = target;
+-
+-      xennet_alloc_rx_buffers(netdev);
+-
+-      spin_unlock_bh(&np->rx_lock);
+-      return len;
+-}
+-
+-static ssize_t show_rxbuf_cur(struct device *dev,
+-                            struct device_attribute *attr, char *buf)
+-{
+-      struct net_device *netdev = to_net_dev(dev);
+-      struct netfront_info *info = netdev_priv(netdev);
+-
+-      return sprintf(buf, "%u\n", info->rx_target);
+-}
+-
+-static struct device_attribute xennet_attrs[] = {
+-      __ATTR(rxbuf_min, S_IRUGO|S_IWUSR, show_rxbuf_min, store_rxbuf_min),
+-      __ATTR(rxbuf_max, S_IRUGO|S_IWUSR, show_rxbuf_max, store_rxbuf_max),
+-      __ATTR(rxbuf_cur, S_IRUGO, show_rxbuf_cur, NULL),
+-};
+-
+-static int xennet_sysfs_addif(struct net_device *netdev)
+-{
+-      int i;
+-      int err;
+-
+-      for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++) {
+-              err = device_create_file(&netdev->dev,
+-                                         &xennet_attrs[i]);
+-              if (err)
+-                      goto fail;
+-      }
+-      return 0;
+-
+- fail:
+-      while (--i >= 0)
+-              device_remove_file(&netdev->dev, &xennet_attrs[i]);
+-      return err;
+-}
+-
+-static void xennet_sysfs_delif(struct net_device *netdev)
+-{
+-      int i;
+-
+-      for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++)
+-              device_remove_file(&netdev->dev, &xennet_attrs[i]);
+-}
+-
+-#endif /* CONFIG_SYSFS */
+-
+-static struct xenbus_device_id netfront_ids[] = {
+-      { "vif" },
+-      { "" }
+-};
+-
+-
+-static int __devexit xennet_remove(struct xenbus_device *dev)
+-{
+-      struct netfront_info *info = dev->dev.driver_data;
+-
+-      dev_dbg(&dev->dev, "%s\n", dev->nodename);
+-
+-      unregister_netdev(info->netdev);
+-
+-      xennet_disconnect_backend(info);
+-
+-      del_timer_sync(&info->rx_refill_timer);
+-
+-      xennet_sysfs_delif(info->netdev);
+-
+-      free_netdev(info->netdev);
+-
+-      return 0;
+-}
+-
+-static struct xenbus_driver netfront = {
+-      .name = "vif",
+-      .owner = THIS_MODULE,
+-      .ids = netfront_ids,
+-      .probe = netfront_probe,
+-      .remove = __devexit_p(xennet_remove),
+-      .resume = netfront_resume,
+-      .otherend_changed = backend_changed,
+-};
+-
+-static int __init netif_init(void)
+-{
+-      if (!is_running_on_xen())
+-              return -ENODEV;
+-
+-      if (is_initial_xendomain())
+-              return 0;
+-
+-      printk(KERN_INFO "Initialising Xen virtual ethernet driver.\n");
+-
+-      return xenbus_register_frontend(&netfront);
+-}
+-module_init(netif_init);
+-
+-
+-static void __exit netif_exit(void)
+-{
+-      if (is_initial_xendomain())
+-              return;
+-
+-      return xenbus_unregister_driver(&netfront);
+-}
+-module_exit(netif_exit);
+-
+-MODULE_DESCRIPTION("Xen virtual network device frontend");
+-MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/drivers/net/yellowfin.c linux-2.6.22-570/drivers/net/yellowfin.c
+--- linux-2.6.22-590/drivers/net/yellowfin.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/net/yellowfin.c   2007-07-08 19:32:17.000000000 -0400
+@@ -1137,7 +1137,7 @@
+                               if (skb == NULL)
+                                       break;
+                               skb_reserve(skb, 2);    /* 16 byte align the IP header */
+-                              skb_copy_to_linear_data(skb, rx_skb->data, pkt_len);
++                              eth_copy_and_sum(skb, rx_skb->data, pkt_len, 0);
+                               skb_put(skb, pkt_len);
+                               pci_dma_sync_single_for_device(yp->pci_dev, desc->addr,
+                                                                                          yp->rx_buf_sz,
+diff -Nurb linux-2.6.22-590/drivers/parisc/led.c linux-2.6.22-570/drivers/parisc/led.c
+--- linux-2.6.22-590/drivers/parisc/led.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/parisc/led.c      2007-07-08 19:32:17.000000000 -0400
+@@ -359,7 +359,7 @@
+        * for reading should be OK */
+       read_lock(&dev_base_lock);
+       rcu_read_lock();
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+           struct net_device_stats *stats;
+           struct in_device *in_dev = __in_dev_get_rcu(dev);
+           if (!in_dev || !in_dev->ifa_list)
+diff -Nurb linux-2.6.22-590/drivers/parisc/pdc_stable.c linux-2.6.22-570/drivers/parisc/pdc_stable.c
+--- linux-2.6.22-590/drivers/parisc/pdc_stable.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/parisc/pdc_stable.c       2007-07-08 19:32:17.000000000 -0400
+@@ -121,14 +121,14 @@
  
--      dlp = &pring->txq;
--      cmd_iocb = NULL;
--      list_remove_head((&pring->txq), cmd_iocb,
--                       struct lpfc_iocbq,
--                       list);
--      if (cmd_iocb) {
--              /* If the first ptr is not equal to the list header,
--               * deque the IOCBQ_t and return it.
--               */
-+      list_remove_head((&pring->txq), cmd_iocb, struct lpfc_iocbq, list);
-+      if (cmd_iocb != NULL)
-               pring->txq_cnt--;
--      }
--      return (cmd_iocb);
-+      return cmd_iocb;
- }
+ #define PDCS_ATTR(_name, _mode, _show, _store) \
+ struct subsys_attribute pdcs_attr_##_name = { \
+-      .attr = {.name = __stringify(_name), .mode = _mode}, \
++      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+       .show = _show, \
+       .store = _store, \
+ };
  
- static IOCB_t *
- lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+ #define PATHS_ATTR(_name, _mode, _show, _store) \
+ struct pdcspath_attribute paths_attr_##_name = { \
+-      .attr = {.name = __stringify(_name), .mode = _mode}, \
++      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+       .show = _show, \
+       .store = _store, \
+ };
+diff -Nurb linux-2.6.22-590/drivers/pci/hotplug/acpiphp_ibm.c linux-2.6.22-570/drivers/pci/hotplug/acpiphp_ibm.c
+--- linux-2.6.22-590/drivers/pci/hotplug/acpiphp_ibm.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/pci/hotplug/acpiphp_ibm.c 2007-07-08 19:32:17.000000000 -0400
+@@ -106,7 +106,6 @@
+ static void ibm_handle_events(acpi_handle handle, u32 event, void *context);
+ static int ibm_get_table_from_acpi(char **bufp);
+ static ssize_t ibm_read_apci_table(struct kobject *kobj,
+-                                 struct bin_attribute *bin_attr,
+               char *buffer, loff_t pos, size_t size);
+ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
+               u32 lvl, void *context, void **rv);
+@@ -118,6 +117,7 @@
+ static struct bin_attribute ibm_apci_table_attr = {
+           .attr = {
+                   .name = "apci_table",
++                  .owner = THIS_MODULE,
+                   .mode = S_IRUGO,
+           },
+           .read = ibm_read_apci_table,
+@@ -358,7 +358,6 @@
+  * our solution is to only allow reading the table in all at once
+  **/
+ static ssize_t ibm_read_apci_table(struct kobject *kobj,
+-                                 struct bin_attribute *bin_attr,
+               char *buffer, loff_t pos, size_t size)
  {
--      struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
-+      struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
-+              &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
-+              &phba->slim2p->mbx.us.s2.port[pring->ringno];
-       uint32_t  max_cmd_idx = pring->numCiocb;
--      IOCB_t *iocb = NULL;
-       if ((pring->next_cmdidx == pring->cmdidx) &&
-          (++pring->next_cmdidx >= max_cmd_idx))
-@@ -249,15 +301,17 @@
-                                       phba->brd_no, pring->ringno,
-                                       pring->local_getidx, max_cmd_idx);
--                      phba->hba_state = LPFC_HBA_ERROR;
-+                      phba->link_state = LPFC_HBA_ERROR;
-                       /*
-                        * All error attention handlers are posted to
-                        * worker thread
-                        */
-                       phba->work_ha |= HA_ERATT;
-                       phba->work_hs = HS_FFER3;
-+
-+                      /* hbalock should already be held */
-                       if (phba->work_wait)
--                              wake_up(phba->work_wait);
-+                              lpfc_worker_wake_up(phba);
-                       return NULL;
-               }
-@@ -266,39 +320,34 @@
-                       return NULL;
-       }
--      iocb = IOCB_ENTRY(pring->cmdringaddr, pring->cmdidx);
--
--      return iocb;
-+      return lpfc_cmd_iocb(phba, pring);
- }
+       int bytes_read = -EINVAL;
+diff -Nurb linux-2.6.22-590/drivers/pci/hotplug/rpadlpar_core.c linux-2.6.22-570/drivers/pci/hotplug/rpadlpar_core.c
+--- linux-2.6.22-590/drivers/pci/hotplug/rpadlpar_core.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/pci/hotplug/rpadlpar_core.c       2007-07-08 19:32:17.000000000 -0400
+@@ -159,8 +159,8 @@
+       /* Claim new bus resources */
+       pcibios_claim_one_bus(dev->bus);
  
- uint16_t
--lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
-+lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
- {
--      struct lpfc_iocbq ** new_arr;
--      struct lpfc_iocbq ** old_arr;
-+      struct lpfc_iocbq **new_arr;
-+      struct lpfc_iocbq **old_arr;
-       size_t new_len;
-       struct lpfc_sli *psli = &phba->sli;
-       uint16_t iotag;
+-      /* Map IO space for child bus, which may or may not succeed */
+-      pcibios_map_io_space(dev->subordinate);
++      /* ioremap() for child bus, which may or may not succeed */
++      remap_bus_range(dev->subordinate);
  
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       iotag = psli->last_iotag;
-       if(++iotag < psli->iocbq_lookup_len) {
-               psli->last_iotag = iotag;
-               psli->iocbq_lookup[iotag] = iocbq;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(&phba->hbalock);
-               iocbq->iotag = iotag;
-               return iotag;
--      }
--      else if (psli->iocbq_lookup_len < (0xffff
-+      } else if (psli->iocbq_lookup_len < (0xffff
-                                          - LPFC_IOCBQ_LOOKUP_INCREMENT)) {
-               new_len = psli->iocbq_lookup_len + LPFC_IOCBQ_LOOKUP_INCREMENT;
--              spin_unlock_irq(phba->host->host_lock);
--              new_arr = kmalloc(new_len * sizeof (struct lpfc_iocbq *),
-+              spin_unlock_irq(&phba->hbalock);
-+              new_arr = kzalloc(new_len * sizeof (struct lpfc_iocbq *),
-                                 GFP_KERNEL);
-               if (new_arr) {
--                      memset((char *)new_arr, 0,
--                             new_len * sizeof (struct lpfc_iocbq *));
--                      spin_lock_irq(phba->host->host_lock);
-+                      spin_lock_irq(&phba->hbalock);
-                       old_arr = psli->iocbq_lookup;
-                       if (new_len <= psli->iocbq_lookup_len) {
-                               /* highly unprobable case */
-@@ -307,11 +356,11 @@
-                               if(++iotag < psli->iocbq_lookup_len) {
-                                       psli->last_iotag = iotag;
-                                       psli->iocbq_lookup[iotag] = iocbq;
--                                      spin_unlock_irq(phba->host->host_lock);
-+                                      spin_unlock_irq(&phba->hbalock);
-                                       iocbq->iotag = iotag;
-                                       return iotag;
-                               }
--                              spin_unlock_irq(phba->host->host_lock);
-+                              spin_unlock_irq(&phba->hbalock);
-                               return 0;
-                       }
-                       if (psli->iocbq_lookup)
-@@ -322,13 +371,13 @@
-                       psli->iocbq_lookup_len = new_len;
-                       psli->last_iotag = iotag;
-                       psli->iocbq_lookup[iotag] = iocbq;
--                      spin_unlock_irq(phba->host->host_lock);
-+                      spin_unlock_irq(&phba->hbalock);
-                       iocbq->iotag = iotag;
-                       kfree(old_arr);
-                       return iotag;
-               }
+       /* Add new devices to global lists.  Register in proc, sysfs. */
+       pci_bus_add_devices(phb->bus);
+@@ -390,7 +390,7 @@
        } else
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(&phba->hbalock);
-       lpfc_printf_log(phba, KERN_ERR,LOG_SLI,
-                       "%d:0318 Failed to allocate IOTAG.last IOTAG is %d\n",
-@@ -349,7 +398,7 @@
-       /*
-        * Issue iocb command to adapter
-        */
--      lpfc_sli_pcimem_bcopy(&nextiocb->iocb, iocb, sizeof (IOCB_t));
-+      lpfc_sli_pcimem_bcopy(&nextiocb->iocb, iocb, phba->iocb_cmd_size);
-       wmb();
-       pring->stats.iocb_cmd++;
-@@ -361,20 +410,18 @@
-       if (nextiocb->iocb_cmpl)
-               lpfc_sli_ringtxcmpl_put(phba, pring, nextiocb);
-       else
--              lpfc_sli_release_iocbq(phba, nextiocb);
-+              __lpfc_sli_release_iocbq(phba, nextiocb);
+               pcibios_remove_pci_devices(bus);
  
-       /*
-        * Let the HBA know what IOCB slot will be the next one the
-        * driver will put a command into.
-        */
-       pring->cmdidx = pring->next_cmdidx;
--      writel(pring->cmdidx, phba->MBslimaddr
--             + (SLIMOFF + (pring->ringno * 2)) * 4);
-+      writel(pring->cmdidx, &phba->host_gp[pring->ringno].cmdPutInx);
- }
+-      if (pcibios_unmap_io_space(bus)) {
++      if (unmap_bus_range(bus)) {
+               printk(KERN_ERR "%s: failed to unmap bus range\n",
+                       __FUNCTION__);
+               return -ERANGE;
+diff -Nurb linux-2.6.22-590/drivers/pci/pci-sysfs.c linux-2.6.22-570/drivers/pci/pci-sysfs.c
+--- linux-2.6.22-590/drivers/pci/pci-sysfs.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/pci/pci-sysfs.c   2007-07-08 19:32:17.000000000 -0400
+@@ -213,8 +213,7 @@
+ };
  
- static void
--lpfc_sli_update_full_ring(struct lpfc_hba * phba,
--                        struct lpfc_sli_ring *pring)
-+lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+ static ssize_t
+-pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+-              char *buf, loff_t off, size_t count)
++pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
  {
-       int ringno = pring->ringno;
-@@ -393,8 +440,7 @@
+       struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
+       unsigned int size = 64;
+@@ -286,8 +285,7 @@
  }
  
- static void
--lpfc_sli_update_ring(struct lpfc_hba * phba,
--                   struct lpfc_sli_ring *pring)
-+lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+ static ssize_t
+-pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+-               char *buf, loff_t off, size_t count)
++pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
  {
-       int ringno = pring->ringno;
-@@ -407,7 +453,7 @@
- }
- static void
--lpfc_sli_resume_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
-+lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+       struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
+       unsigned int size = count;
+@@ -354,8 +352,7 @@
+  * callback routine (pci_legacy_read).
+  */
+ ssize_t
+-pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
+-                 char *buf, loff_t off, size_t count)
++pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
  {
-       IOCB_t *iocb;
-       struct lpfc_iocbq *nextiocb;
-@@ -420,7 +466,7 @@
-        *  (d) IOCB processing is not blocked by the outstanding mbox command.
-        */
-       if (pring->txq_cnt &&
--          (phba->hba_state > LPFC_LINK_DOWN) &&
-+          lpfc_is_link_up(phba) &&
-           (pring->ringno != phba->sli.fcp_ring ||
-            phba->sli.sli_flag & LPFC_PROCESS_LA) &&
-           !(pring->flag & LPFC_STOP_IOCB_MBX)) {
-@@ -440,11 +486,15 @@
- /* lpfc_sli_turn_on_ring is only called by lpfc_sli_handle_mb_event below */
- static void
--lpfc_sli_turn_on_ring(struct lpfc_hba * phba, int ringno)
-+lpfc_sli_turn_on_ring(struct lpfc_hba *phba, int ringno)
+         struct pci_bus *bus = to_pci_bus(container_of(kobj,
+                                                       struct class_device,
+@@ -379,8 +376,7 @@
+  * callback routine (pci_legacy_write).
+  */
+ ssize_t
+-pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
+-                  char *buf, loff_t off, size_t count)
++pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
  {
--      struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[ringno];
-+      struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
-+              &phba->slim2p->mbx.us.s3_pgp.port[ringno] :
-+              &phba->slim2p->mbx.us.s2.port[ringno];
-+      unsigned long iflags;
+         struct pci_bus *bus = to_pci_bus(container_of(kobj,
+                                                     struct class_device,
+@@ -503,6 +499,7 @@
+                       sprintf(res_attr_name, "resource%d", i);
+                       res_attr->attr.name = res_attr_name;
+                       res_attr->attr.mode = S_IRUSR | S_IWUSR;
++                      res_attr->attr.owner = THIS_MODULE;
+                       res_attr->size = pci_resource_len(pdev, i);
+                       res_attr->mmap = pci_mmap_resource;
+                       res_attr->private = &pdev->resource[i];
+@@ -532,8 +529,7 @@
+  * writing anything except 0 enables it
+  */
+ static ssize_t
+-pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
+-            char *buf, loff_t off, size_t count)
++pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
  
-       /* If the ring is active, flag it */
-+      spin_lock_irqsave(&phba->hbalock, iflags);
-       if (phba->sli.ring[ringno].cmdringaddr) {
-               if (phba->sli.ring[ringno].flag & LPFC_STOP_IOCB_MBX) {
-                       phba->sli.ring[ringno].flag &= ~LPFC_STOP_IOCB_MBX;
-@@ -453,11 +503,176 @@
-                        */
-                       phba->sli.ring[ringno].local_getidx
-                               = le32_to_cpu(pgp->cmdGetInx);
--                      spin_lock_irq(phba->host->host_lock);
-                       lpfc_sli_resume_iocb(phba, &phba->sli.ring[ringno]);
--                      spin_unlock_irq(phba->host->host_lock);
-               }
+@@ -556,8 +552,7 @@
+  * device corresponding to @kobj.
+  */
+ static ssize_t
+-pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
+-           char *buf, loff_t off, size_t count)
++pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
+       void __iomem *rom;
+@@ -587,6 +582,7 @@
+       .attr = {
+               .name = "config",
+               .mode = S_IRUGO | S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = 256,
+       .read = pci_read_config,
+@@ -597,6 +593,7 @@
+       .attr = {
+               .name = "config",
+               .mode = S_IRUGO | S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = 4096,
+       .read = pci_read_config,
+@@ -631,6 +628,7 @@
+                       rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+                       rom_attr->attr.name = "rom";
+                       rom_attr->attr.mode = S_IRUSR;
++                      rom_attr->attr.owner = THIS_MODULE;
+                       rom_attr->read = pci_read_rom;
+                       rom_attr->write = pci_write_rom;
+                       retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
+diff -Nurb linux-2.6.22-590/drivers/pci/probe.c linux-2.6.22-570/drivers/pci/probe.c
+--- linux-2.6.22-590/drivers/pci/probe.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/pci/probe.c       2008-01-23 19:15:55.000000000 -0500
+@@ -39,6 +39,7 @@
+               b->legacy_io->attr.name = "legacy_io";
+               b->legacy_io->size = 0xffff;
+               b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
++              b->legacy_io->attr.owner = THIS_MODULE;
+               b->legacy_io->read = pci_read_legacy_io;
+               b->legacy_io->write = pci_write_legacy_io;
+               class_device_create_bin_file(&b->class_dev, b->legacy_io);
+@@ -48,6 +49,7 @@
+               b->legacy_mem->attr.name = "legacy_mem";
+               b->legacy_mem->size = 1024*1024;
+               b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
++              b->legacy_mem->attr.owner = THIS_MODULE;
+               b->legacy_mem->mmap = pci_mmap_legacy_mem;
+               class_device_create_bin_file(&b->class_dev, b->legacy_mem);
        }
-+      spin_unlock_irqrestore(&phba->hbalock, iflags);
-+}
-+
-+struct lpfc_hbq_entry *
-+lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno)
-+{
-+      struct hbq_s *hbqp = &phba->hbqs[hbqno];
-+
-+      if (hbqp->next_hbqPutIdx == hbqp->hbqPutIdx &&
-+          ++hbqp->next_hbqPutIdx >= hbqp->entry_count)
-+              hbqp->next_hbqPutIdx = 0;
-+
-+      if (unlikely(hbqp->local_hbqGetIdx == hbqp->next_hbqPutIdx)) {
-+              uint32_t raw_index = phba->hbq_get[hbqno];
-+              uint32_t getidx = le32_to_cpu(raw_index);
-+
-+              hbqp->local_hbqGetIdx = getidx;
-+
-+              if (unlikely(hbqp->local_hbqGetIdx >= hbqp->entry_count)) {
-+                      lpfc_printf_log(phba, KERN_ERR,
-+                                      LOG_SLI | LOG_VPORT,
-+                                      "%d:1802 HBQ %d: local_hbqGetIdx "
-+                                      "%u is > than hbqp->entry_count %u\n",
-+                                      phba->brd_no, hbqno,
-+                                      hbqp->local_hbqGetIdx,
-+                                      hbqp->entry_count);
-+
-+                      phba->link_state = LPFC_HBA_ERROR;
-+                      return NULL;
-+              }
-+
-+              if (hbqp->local_hbqGetIdx == hbqp->next_hbqPutIdx)
-+                      return NULL;
-+      }
-+
-+      return (struct lpfc_hbq_entry *) phba->hbqslimp.virt + hbqp->hbqPutIdx;
-+}
-+
-+void
-+lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba)
-+{
-+      struct lpfc_dmabuf *dmabuf, *next_dmabuf;
-+      struct hbq_dmabuf *hbq_buf;
-+
-+      /* Return all memory used by all HBQs */
-+      list_for_each_entry_safe(dmabuf, next_dmabuf,
-+                               &phba->hbq_buffer_list, list) {
-+              hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf);
-+              list_del(&hbq_buf->dbuf.list);
-+              lpfc_hbq_free(phba, hbq_buf->dbuf.virt, hbq_buf->dbuf.phys);
-+              kfree(hbq_buf);
-+      }
-+}
-+
-+static void
-+lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
-+                       struct hbq_dmabuf *hbq_buf)
-+{
-+      struct lpfc_hbq_entry *hbqe;
-+      dma_addr_t physaddr = hbq_buf->dbuf.phys;
-+
-+      /* Get next HBQ entry slot to use */
-+      hbqe = lpfc_sli_next_hbq_slot(phba, hbqno);
-+      if (hbqe) {
-+              struct hbq_s *hbqp = &phba->hbqs[hbqno];
-+
-+              hbqe->bde.addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
-+              hbqe->bde.addrLow  = le32_to_cpu(putPaddrLow(physaddr));
-+              hbqe->bde.tus.f.bdeSize = FCELSSIZE;
-+              hbqe->bde.tus.f.bdeFlags = 0;
-+              hbqe->bde.tus.w = le32_to_cpu(hbqe->bde.tus.w);
-+              hbqe->buffer_tag = le32_to_cpu(hbq_buf->tag);
-+                              /* Sync SLIM */
-+              hbqp->hbqPutIdx = hbqp->next_hbqPutIdx;
-+              writel(hbqp->hbqPutIdx, phba->hbq_put + hbqno);
-+                              /* flush */
-+              readl(phba->hbq_put + hbqno);
-+              list_add_tail(&hbq_buf->dbuf.list, &phba->hbq_buffer_list);
-+      }
-+}
-+
-+static struct lpfc_hbq_init lpfc_els_hbq = {
-+      .rn = 1,
-+      .entry_count = 200,
-+      .mask_count = 0,
-+      .profile = 0,
-+      .ring_mask = 1 << LPFC_ELS_RING,
-+      .buffer_count = 0,
-+      .init_count = 20,
-+      .add_count = 5,
-+};
-+
-+static struct lpfc_hbq_init *lpfc_hbq_defs[] = {
-+      &lpfc_els_hbq,
-+};
-+
-+int
-+lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
-+{
-+      uint32_t i, start, end;
-+      struct hbq_dmabuf *hbq_buffer;
-+
-+      start = lpfc_hbq_defs[hbqno]->buffer_count;
-+      end = count + lpfc_hbq_defs[hbqno]->buffer_count;
-+      if (end > lpfc_hbq_defs[hbqno]->entry_count) {
-+              end = lpfc_hbq_defs[hbqno]->entry_count;
-+      }
-+
-+      /* Populate HBQ entries */
-+      for (i = start; i < end; i++) {
-+              hbq_buffer = kmalloc(sizeof(struct hbq_dmabuf),
-+                                   GFP_KERNEL);
-+              if (!hbq_buffer)
-+                      return 1;
-+              hbq_buffer->dbuf.virt = lpfc_hbq_alloc(phba, MEM_PRI,
-+                                                      &hbq_buffer->dbuf.phys);
-+              if (hbq_buffer->dbuf.virt == NULL)
-+                      return 1;
-+              hbq_buffer->tag = (i | (hbqno << 16));
-+              lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer);
-+              lpfc_hbq_defs[hbqno]->buffer_count++;
-+      }
-+      return 0;
-+}
-+
-+int
-+lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno)
-+{
-+      return(lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
-+                                       lpfc_hbq_defs[qno]->add_count));
-+}
-+
-+int
-+lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
-+{
-+      return(lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
-+                                       lpfc_hbq_defs[qno]->init_count));
-+}
-+
-+struct hbq_dmabuf *
-+lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
-+{
-+      struct lpfc_dmabuf *d_buf;
-+      struct hbq_dmabuf *hbq_buf;
-+
-+      list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) {
-+              hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
-+              if ((hbq_buf->tag & 0xffff) == tag) {
-+                      return hbq_buf;
-+              }
-+      }
-+      lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_VPORT,
-+                      "%d:1803 Bad hbq tag. Data: x%x x%x\n",
-+                      phba->brd_no, tag,
-+                      lpfc_hbq_defs[tag >> 16]->buffer_count);
-+      return NULL;
-+}
-+
-+void
-+lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *sp)
-+{
-+      uint32_t hbqno;
-+
-+      if (sp) {
-+              hbqno = sp->tag >> 16;
-+              lpfc_sli_hbq_to_firmware(phba, hbqno, sp);
-+      }
- }
+diff -Nurb linux-2.6.22-590/drivers/pcmcia/cs.c linux-2.6.22-570/drivers/pcmcia/cs.c
+--- linux-2.6.22-590/drivers/pcmcia/cs.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/pcmcia/cs.c       2008-01-23 19:15:55.000000000 -0500
+@@ -654,7 +654,6 @@
+       add_wait_queue(&skt->thread_wait, &wait);
+       complete(&skt->thread_done);
  
- static int
-@@ -511,32 +726,38 @@
-       case MBX_FLASH_WR_ULA:
-       case MBX_SET_DEBUG:
-       case MBX_LOAD_EXP_ROM:
-+      case MBX_REG_VPI:
-+      case MBX_UNREG_VPI:
-+      case MBX_HEARTBEAT:
-               ret = mbxCommand;
-               break;
-       default:
-               ret = MBX_SHUTDOWN;
-               break;
-       }
--      return (ret);
-+      return ret;
+-      set_freezable();
+       for (;;) {
+               unsigned long flags;
+               unsigned int events;
+diff -Nurb linux-2.6.22-590/drivers/pcmcia/socket_sysfs.c linux-2.6.22-570/drivers/pcmcia/socket_sysfs.c
+--- linux-2.6.22-590/drivers/pcmcia/socket_sysfs.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/pcmcia/socket_sysfs.c     2007-07-08 19:32:17.000000000 -0400
+@@ -283,9 +283,7 @@
+       return (ret);
  }
- static void
--lpfc_sli_wake_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
-+lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
+-static ssize_t pccard_show_cis(struct kobject *kobj,
+-                             struct bin_attribute *bin_attr,
+-                             char *buf, loff_t off, size_t count)
++static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
  {
-       wait_queue_head_t *pdone_q;
-+      unsigned long drvr_flag;
+       unsigned int size = 0x200;
  
-       /*
-        * If pdone_q is empty, the driver thread gave up waiting and
-        * continued running.
-        */
-       pmboxq->mbox_flag |= LPFC_MBX_WAKE;
-+      spin_lock_irqsave(&phba->hbalock, drvr_flag);
-       pdone_q = (wait_queue_head_t *) pmboxq->context1;
-       if (pdone_q)
-               wake_up_interruptible(pdone_q);
-+      spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
-       return;
+@@ -313,9 +311,7 @@
+       return (count);
  }
  
- void
--lpfc_sli_def_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
-+lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+-static ssize_t pccard_store_cis(struct kobject *kobj,
+-                              struct bin_attribute *bin_attr,
+-                              char *buf, loff_t off, size_t count)
++static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
  {
-       struct lpfc_dmabuf *mp;
-       uint16_t rpi;
-@@ -553,78 +774,63 @@
-        * If a REG_LOGIN succeeded  after node is destroyed or node
-        * is in re-discovery driver need to cleanup the RPI.
-        */
--      if (!(phba->fc_flag & FC_UNLOADING) &&
--              (pmb->mb.mbxCommand == MBX_REG_LOGIN64) &&
--              (!pmb->mb.mbxStatus)) {
-+      if (!(phba->pport->load_flag & FC_UNLOADING) &&
-+          pmb->mb.mbxCommand == MBX_REG_LOGIN64 &&
-+          !pmb->mb.mbxStatus) {
+       struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj));
+       cisdump_t *cis;
+@@ -370,7 +366,7 @@
+ };
  
-               rpi = pmb->mb.un.varWords[0];
--              lpfc_unreg_login(phba, rpi, pmb);
--              pmb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
-+              lpfc_unreg_login(phba, pmb->mb.un.varRegLogin.vpi, rpi, pmb);
-+              pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
-               if (rc != MBX_NOT_FINISHED)
-                       return;
+ static struct bin_attribute pccard_cis_attr = {
+-      .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR },
++      .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE},
+       .size = 0x200,
+       .read = pccard_show_cis,
+       .write = pccard_store_cis,
+diff -Nurb linux-2.6.22-590/drivers/pnp/driver.c linux-2.6.22-570/drivers/pnp/driver.c
+--- linux-2.6.22-590/drivers/pnp/driver.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/pnp/driver.c      2007-07-08 19:32:17.000000000 -0400
+@@ -167,8 +167,6 @@
+                       return error;
        }
  
--      mempool_free( pmb, phba->mbox_mem_pool);
-+      mempool_free(pmb, phba->mbox_mem_pool);
-       return;
+-      if (pnp_dev->protocol && pnp_dev->protocol->suspend)
+-              pnp_dev->protocol->suspend(pnp_dev, state);
+       return 0;
  }
  
- int
--lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
-+lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
- {
--      MAILBOX_t *mbox;
-       MAILBOX_t *pmbox;
-       LPFC_MBOXQ_t *pmb;
--      struct lpfc_sli *psli;
--      int i, rc;
--      uint32_t process_next;
--
--      psli = &phba->sli;
--      /* We should only get here if we are in SLI2 mode */
--      if (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE)) {
--              return (1);
--      }
-+      int rc;
-+      LIST_HEAD(cmplq);
-       phba->sli.slistat.mbox_event++;
-+      /* Get all completed mailboxe buffers into the cmplq */
-+      spin_lock_irq(&phba->hbalock);
-+      list_splice_init(&phba->sli.mboxq_cmpl, &cmplq);
-+      spin_unlock_irq(&phba->hbalock);
-+
-       /* Get a Mailbox buffer to setup mailbox commands for callback */
--      if ((pmb = phba->sli.mbox_active)) {
--              pmbox = &pmb->mb;
--              mbox = &phba->slim2p->mbx;
-+      do {
-+              list_remove_head(&cmplq, pmb, LPFC_MBOXQ_t, list);
-+              if (pmb == NULL)
-+                      break;
+@@ -181,9 +179,6 @@
+       if (!pnp_drv)
+               return 0;
  
--              /* First check out the status word */
--              lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof (uint32_t));
-+              pmbox = &pmb->mb;
+-      if (pnp_dev->protocol && pnp_dev->protocol->resume)
+-              pnp_dev->protocol->resume(pnp_dev);
+-
+       if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
+               error = pnp_start_dev(pnp_dev);
+               if (error)
+diff -Nurb linux-2.6.22-590/drivers/pnp/pnpacpi/core.c linux-2.6.22-570/drivers/pnp/pnpacpi/core.c
+--- linux-2.6.22-590/drivers/pnp/pnpacpi/core.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/pnp/pnpacpi/core.c        2007-07-08 19:32:17.000000000 -0400
+@@ -119,23 +119,11 @@
+       return ACPI_FAILURE(status) ? -ENODEV : 0;
+ }
  
--              /* Sanity check to ensure the host owns the mailbox */
--              if (pmbox->mbxOwner != OWN_HOST) {
--                      /* Lets try for a while */
--                      for (i = 0; i < 10240; i++) {
--                              /* First copy command data */
--                              lpfc_sli_pcimem_bcopy(mbox, pmbox,
--                                                      sizeof (uint32_t));
--                              if (pmbox->mbxOwner == OWN_HOST)
--                                      goto mbout;
-+              if (pmbox->mbxCommand != MBX_HEARTBEAT) {
-+                      if (pmb->vport) {
-+                              lpfc_debugfs_disc_trc(pmb->vport,
-+                                      LPFC_DISC_TRC_MBOX_VPORT,
-+                                      "MBOX cmpl vport: cmd:x%x mb:x%x x%x",
-+                                      (uint32_t)pmbox->mbxCommand,
-+                                      pmbox->un.varWords[0],
-+                                      pmbox->un.varWords[1]);
-+                      }
-+                      else {
-+                              lpfc_debugfs_disc_trc(phba->pport,
-+                                      LPFC_DISC_TRC_MBOX,
-+                                      "MBOX cmpl:       cmd:x%x mb:x%x x%x",
-+                                      (uint32_t)pmbox->mbxCommand,
-+                                      pmbox->un.varWords[0],
-+                                      pmbox->un.varWords[1]);
-                       }
--                      /* Stray Mailbox Interrupt, mbxCommand <cmd> mbxStatus
--                         <status> */
--                      lpfc_printf_log(phba,
--                                      KERN_WARNING,
--                                      LOG_MBOX | LOG_SLI,
--                                      "%d:0304 Stray Mailbox Interrupt "
--                                      "mbxCommand x%x mbxStatus x%x\n",
--                                      phba->brd_no,
--                                      pmbox->mbxCommand,
--                                      pmbox->mbxStatus);
+-static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
+-{
+-      return acpi_bus_set_power((acpi_handle)dev->data, 3);
+-}
 -
--                      spin_lock_irq(phba->host->host_lock);
--                      phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE;
--                      spin_unlock_irq(phba->host->host_lock);
--                      return (1);
-               }
+-static int pnpacpi_resume(struct pnp_dev *dev)
+-{
+-      return acpi_bus_set_power((acpi_handle)dev->data, 0);
+-}
 -
--            mbout:
--              del_timer_sync(&phba->sli.mbox_tmo);
--              phba->work_hba_events &= ~WORKER_MBOX_TMO;
-               /*
-                * It is a fatal error if unknown mbox command completion.
-@@ -633,51 +839,50 @@
-                   MBX_SHUTDOWN) {
-                       /* Unknow mailbox command compl */
--                      lpfc_printf_log(phba,
--                              KERN_ERR,
--                              LOG_MBOX | LOG_SLI,
--                              "%d:0323 Unknown Mailbox command %x Cmpl\n",
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
-+                                      "%d (%d):0323 Unknown Mailbox command "
-+                                      "%x Cmpl\n",
-                               phba->brd_no,
-+                                      pmb->vport ? pmb->vport->vpi : 0,
-                               pmbox->mbxCommand);
--                      phba->hba_state = LPFC_HBA_ERROR;
-+                      phba->link_state = LPFC_HBA_ERROR;
-                       phba->work_hs = HS_FFER3;
-                       lpfc_handle_eratt(phba);
--                      return (0);
-+                      continue;
-               }
--              phba->sli.mbox_active = NULL;
-               if (pmbox->mbxStatus) {
-                       phba->sli.slistat.mbox_stat_err++;
-                       if (pmbox->mbxStatus == MBXERR_NO_RESOURCES) {
-                               /* Mbox cmd cmpl error - RETRYing */
--                              lpfc_printf_log(phba,
--                                      KERN_INFO,
-+                              lpfc_printf_log(phba, KERN_INFO,
-                                       LOG_MBOX | LOG_SLI,
--                                      "%d:0305 Mbox cmd cmpl error - "
--                                      "RETRYing Data: x%x x%x x%x x%x\n",
-+                                              "%d (%d):0305 Mbox cmd cmpl "
-+                                              "error - RETRYing Data: x%x "
-+                                              "x%x x%x x%x\n",
-                                       phba->brd_no,
-+                                              pmb->vport ? pmb->vport->vpi :0,
-                                       pmbox->mbxCommand,
-                                       pmbox->mbxStatus,
-                                       pmbox->un.varWords[0],
--                                      phba->hba_state);
-+                                              pmb->vport->port_state);
-                               pmbox->mbxStatus = 0;
-                               pmbox->mbxOwner = OWN_HOST;
--                              spin_lock_irq(phba->host->host_lock);
-+                              spin_lock_irq(&phba->hbalock);
-                               phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
--                              spin_unlock_irq(phba->host->host_lock);
-+                              spin_unlock_irq(&phba->hbalock);
-                               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
-                               if (rc == MBX_SUCCESS)
--                                      return (0);
-+                                      continue;
-                       }
-               }
-               /* Mailbox cmd <cmd> Cmpl <cmpl> */
--              lpfc_printf_log(phba,
--                              KERN_INFO,
--                              LOG_MBOX | LOG_SLI,
--                              "%d:0307 Mailbox cmd x%x Cmpl x%p "
-+              lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
-+                              "%d (%d):0307 Mailbox cmd x%x Cmpl x%p "
-                               "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x\n",
-                               phba->brd_no,
-+                              pmb->vport ? pmb->vport->vpi : 0,
-                               pmbox->mbxCommand,
-                               pmb->mbox_cmpl,
-                               *((uint32_t *) pmbox),
-@@ -690,39 +895,35 @@
-                               pmbox->un.varWords[6],
-                               pmbox->un.varWords[7]);
+ static struct pnp_protocol pnpacpi_protocol = {
+       .name   = "Plug and Play ACPI",
+       .get    = pnpacpi_get_resources,
+       .set    = pnpacpi_set_resources,
+       .disable = pnpacpi_disable_resources,
+-      .suspend = pnpacpi_suspend,
+-      .resume = pnpacpi_resume,
+ };
  
--              if (pmb->mbox_cmpl) {
--                      lpfc_sli_pcimem_bcopy(mbox, pmbox, MAILBOX_CMD_SIZE);
-+              if (pmb->mbox_cmpl)
-                       pmb->mbox_cmpl(phba,pmb);
--              }
--      }
--
-+      } while (1);
-+      return 0;
-+}
+ static int __init pnpacpi_add_device(struct acpi_device *device)
+diff -Nurb linux-2.6.22-590/drivers/pnp/pnpbios/core.c linux-2.6.22-570/drivers/pnp/pnpbios/core.c
+--- linux-2.6.22-590/drivers/pnp/pnpbios/core.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/pnp/pnpbios/core.c        2007-07-08 19:32:17.000000000 -0400
+@@ -147,7 +147,7 @@
+               info->location_id, info->serial, info->capabilities);
+       envp[i] = NULL;
+       
+-      value = call_usermodehelper (argv [0], argv, envp, UMH_WAIT_EXEC);
++      value = call_usermodehelper (argv [0], argv, envp, 0);
+       kfree (buf);
+       kfree (envp);
+       return 0;
+@@ -160,7 +160,6 @@
+ {
+       static struct pnp_docking_station_info now;
+       int docked = -1, d = 0;
+-      set_freezable();
+       while (!unloading)
+       {
+               int status;
+diff -Nurb linux-2.6.22-590/drivers/rapidio/rio-sysfs.c linux-2.6.22-570/drivers/rapidio/rio-sysfs.c
+--- linux-2.6.22-590/drivers/rapidio/rio-sysfs.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/rapidio/rio-sysfs.c       2007-07-08 19:32:17.000000000 -0400
+@@ -67,8 +67,7 @@
+ };
  
--      do {
--              process_next = 0;       /* by default don't loop */
--              spin_lock_irq(phba->host->host_lock);
--              phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-+static struct lpfc_dmabuf *
-+lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
-+{
-+      struct hbq_dmabuf *hbq_entry, *new_hbq_entry;
--              /* Process next mailbox command if there is one */
--              if ((pmb = lpfc_mbox_get(phba))) {
--                      spin_unlock_irq(phba->host->host_lock);
--                      rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
--                      if (rc == MBX_NOT_FINISHED) {
--                              pmb->mb.mbxStatus = MBX_NOT_FINISHED;
--                              pmb->mbox_cmpl(phba,pmb);
--                              process_next = 1;
--                              continue;       /* loop back */
--                      }
--              } else {
--                      spin_unlock_irq(phba->host->host_lock);
--                      /* Turn on IOCB processing */
--                      for (i = 0; i < phba->sli.num_rings; i++)
--                              lpfc_sli_turn_on_ring(phba, i);
-+      hbq_entry = lpfc_sli_hbqbuf_find(phba, tag);
-+      if (hbq_entry == NULL)
-+              return NULL;
-+      list_del(&hbq_entry->dbuf.list);
-+      new_hbq_entry = kmalloc(sizeof(struct hbq_dmabuf), GFP_ATOMIC);
-+      if (new_hbq_entry == NULL)
-+              return &hbq_entry->dbuf;
-+      new_hbq_entry->dbuf = hbq_entry->dbuf;
-+      new_hbq_entry->tag = -1;
-+      hbq_entry->dbuf.virt = lpfc_hbq_alloc(phba, 0, &hbq_entry->dbuf.phys);
-+      if (hbq_entry->dbuf.virt == NULL) {
-+              kfree(new_hbq_entry);
-+              return &hbq_entry->dbuf;
-               }
--
--      } while (process_next);
--
--      return (0);
-+      lpfc_sli_free_hbq(phba, hbq_entry);
-+      return &new_hbq_entry->dbuf;
+ static ssize_t
+-rio_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+-              char *buf, loff_t off, size_t count)
++rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct rio_dev *dev =
+           to_rio_dev(container_of(kobj, struct device, kobj));
+@@ -138,8 +137,7 @@
  }
-+
- static int
- lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-                           struct lpfc_iocbq *saveq)
-@@ -735,7 +936,9 @@
-       match = 0;
-       irsp = &(saveq->iocb);
-       if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX)
--          || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX)) {
-+          || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX)
-+          || (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX)
-+          || (irsp->ulpCommand == CMD_IOCB_RCV_CONT64_CX)) {
-               Rctl = FC_ELS_REQ;
-               Type = FC_ELS_DATA;
-       } else {
-@@ -747,13 +950,24 @@
  
-               /* Firmware Workaround */
-               if ((Rctl == 0) && (pring->ringno == LPFC_ELS_RING) &&
--                      (irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX)) {
-+                      (irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX ||
-+                       irsp->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
-                       Rctl = FC_ELS_REQ;
-                       Type = FC_ELS_DATA;
-                       w5p->hcsw.Rctl = Rctl;
-                       w5p->hcsw.Type = Type;
-               }
-       }
-+
-+      if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
-+              if (irsp->ulpBdeCount != 0)
-+                      saveq->context2 = lpfc_sli_replace_hbqbuff(phba,
-+                                              irsp->un.ulpWord[3]);
-+              if (irsp->ulpBdeCount == 2)
-+                      saveq->context3 = lpfc_sli_replace_hbqbuff(phba,
-+                                              irsp->un.ulpWord[15]);
-+      }
-+
-       /* unSolicited Responses */
-       if (pring->prt[0].profile) {
-               if (pring->prt[0].lpfc_sli_rcv_unsol_event)
-@@ -781,23 +995,21 @@
-               /* Unexpected Rctl / Type received */
-               /* Ring <ringno> handler: unexpected
-                  Rctl <Rctl> Type <Type> received */
--              lpfc_printf_log(phba,
--                              KERN_WARNING,
--                              LOG_SLI,
-+              lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
-                               "%d:0313 Ring %d handler: unexpected Rctl x%x "
--                              "Type x%x received \n",
-+                              "Type x%x received\n",
-                               phba->brd_no,
-                               pring->ringno,
-                               Rctl,
-                               Type);
-       }
--      return(1);
-+      return 1;
- }
+ static ssize_t
+-rio_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+-               char *buf, loff_t off, size_t count)
++rio_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct rio_dev *dev =
+           to_rio_dev(container_of(kobj, struct device, kobj));
+@@ -199,6 +197,7 @@
+       .attr = {
+                .name = "config",
+                .mode = S_IRUGO | S_IWUSR,
++               .owner = THIS_MODULE,
+                },
+       .size = 0x200000,
+       .read = rio_read_config,
+diff -Nurb linux-2.6.22-590/drivers/rtc/rtc-ds1553.c linux-2.6.22-570/drivers/rtc/rtc-ds1553.c
+--- linux-2.6.22-590/drivers/rtc/rtc-ds1553.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/rtc/rtc-ds1553.c  2007-07-08 19:32:17.000000000 -0400
+@@ -258,9 +258,8 @@
+       .ioctl          = ds1553_rtc_ioctl,
+ };
  
- static struct lpfc_iocbq *
--lpfc_sli_iocbq_lookup(struct lpfc_hba * phba,
--                    struct lpfc_sli_ring * pring,
--                    struct lpfc_iocbq * prspiocb)
-+lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
-+                    struct lpfc_sli_ring *pring,
-+                    struct lpfc_iocbq *prspiocb)
+-static ssize_t ds1553_nvram_read(struct kobject *kobj,
+-                               struct bin_attribute *bin_attr,
+-                               char *buf, loff_t pos, size_t size)
++static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf,
++                               loff_t pos, size_t size)
  {
-       struct lpfc_iocbq *cmd_iocb = NULL;
-       uint16_t iotag;
-@@ -806,7 +1018,7 @@
-       if (iotag != 0 && iotag <= phba->sli.last_iotag) {
-               cmd_iocb = phba->sli.iocbq_lookup[iotag];
--              list_del(&cmd_iocb->list);
-+              list_del_init(&cmd_iocb->list);
-               pring->txcmplq_cnt--;
-               return cmd_iocb;
-       }
-@@ -821,16 +1033,18 @@
+       struct platform_device *pdev =
+               to_platform_device(container_of(kobj, struct device, kobj));
+@@ -273,9 +272,8 @@
+       return count;
  }
  
- static int
--lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
-+lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-                         struct lpfc_iocbq *saveq)
+-static ssize_t ds1553_nvram_write(struct kobject *kobj,
+-                                struct bin_attribute *bin_attr,
+-                                char *buf, loff_t pos, size_t size)
++static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf,
++                                loff_t pos, size_t size)
  {
--      struct lpfc_iocbq * cmdiocbp;
-+      struct lpfc_iocbq *cmdiocbp;
-       int rc = 1;
-       unsigned long iflag;
-       /* Based on the iotag field, get the cmd IOCB from the txcmplq */
--      spin_lock_irqsave(phba->host->host_lock, iflag);
-+      spin_lock_irqsave(&phba->hbalock, iflag);
-       cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
-+      spin_unlock_irqrestore(&phba->hbalock, iflag);
-+
-       if (cmdiocbp) {
-               if (cmdiocbp->iocb_cmpl) {
-                       /*
-@@ -846,17 +1060,8 @@
-                                       saveq->iocb.un.ulpWord[4] =
-                                               IOERR_SLI_ABORTED;
-                               }
--                              spin_unlock_irqrestore(phba->host->host_lock,
--                                                     iflag);
--                              (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
--                              spin_lock_irqsave(phba->host->host_lock, iflag);
-                       }
--                      else {
--                              spin_unlock_irqrestore(phba->host->host_lock,
--                                                     iflag);
-                               (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
--                              spin_lock_irqsave(phba->host->host_lock, iflag);
--                      }
-               } else
-                       lpfc_sli_release_iocbq(phba, cmdiocbp);
-       } else {
-@@ -870,12 +1075,12 @@
-                        * Ring <ringno> handler: unexpected completion IoTag
-                        * <IoTag>
-                        */
--                      lpfc_printf_log(phba,
--                              KERN_WARNING,
--                              LOG_SLI,
--                              "%d:0322 Ring %d handler: unexpected "
--                              "completion IoTag x%x Data: x%x x%x x%x x%x\n",
-+                      lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
-+                                      "%d (%d):0322 Ring %d handler: "
-+                                      "unexpected completion IoTag x%x "
-+                                      "Data: x%x x%x x%x x%x\n",
-                               phba->brd_no,
-+                                      cmdiocbp->vport->vpi,
-                               pring->ringno,
-                               saveq->iocb.ulpIoTag,
-                               saveq->iocb.ulpStatus,
-@@ -885,14 +1090,15 @@
-               }
-       }
+       struct platform_device *pdev =
+               to_platform_device(container_of(kobj, struct device, kobj));
+@@ -292,6 +290,7 @@
+       .attr = {
+               .name = "nvram",
+               .mode = S_IRUGO | S_IWUGO,
++              .owner = THIS_MODULE,
+       },
+       .size = RTC_OFFSET,
+       .read = ds1553_nvram_read,
+diff -Nurb linux-2.6.22-590/drivers/rtc/rtc-ds1742.c linux-2.6.22-570/drivers/rtc/rtc-ds1742.c
+--- linux-2.6.22-590/drivers/rtc/rtc-ds1742.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/rtc/rtc-ds1742.c  2007-07-08 19:32:17.000000000 -0400
+@@ -127,9 +127,8 @@
+       .set_time       = ds1742_rtc_set_time,
+ };
  
--      spin_unlock_irqrestore(phba->host->host_lock, iflag);
-       return rc;
+-static ssize_t ds1742_nvram_read(struct kobject *kobj,
+-                               struct bin_attribute *bin_attr,
+-                               char *buf, loff_t pos, size_t size)
++static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
++                               loff_t pos, size_t size)
+ {
+       struct platform_device *pdev =
+               to_platform_device(container_of(kobj, struct device, kobj));
+@@ -142,9 +141,8 @@
+       return count;
  }
  
--static void lpfc_sli_rsp_pointers_error(struct lpfc_hba * phba,
--                                      struct lpfc_sli_ring * pring)
-+static void
-+lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+-static ssize_t ds1742_nvram_write(struct kobject *kobj,
+-                                struct bin_attribute *bin_attr,
+-                                char *buf, loff_t pos, size_t size)
++static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf,
++                                loff_t pos, size_t size)
  {
--      struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
-+      struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
-+              &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
-+              &phba->slim2p->mbx.us.s2.port[pring->ringno];
-       /*
-        * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
-        * rsp ring <portRspMax>
-@@ -904,7 +1110,7 @@
-                       le32_to_cpu(pgp->rspPutInx),
-                       pring->numRiocb);
--      phba->hba_state = LPFC_HBA_ERROR;
-+      phba->link_state = LPFC_HBA_ERROR;
-       /*
-        * All error attention handlers are posted to
-@@ -912,16 +1118,18 @@
-        */
-       phba->work_ha |= HA_ERATT;
-       phba->work_hs = HS_FFER3;
-+
-+      /* hbalock should already be held */
-       if (phba->work_wait)
--              wake_up(phba->work_wait);
-+              lpfc_worker_wake_up(phba);
-       return;
+       struct platform_device *pdev =
+               to_platform_device(container_of(kobj, struct device, kobj));
+@@ -161,6 +159,7 @@
+       .attr = {
+               .name = "nvram",
+               .mode = S_IRUGO | S_IWUGO,
++              .owner = THIS_MODULE,
+       },
+       .read = ds1742_nvram_read,
+       .write = ds1742_nvram_write,
+diff -Nurb linux-2.6.22-590/drivers/s390/cio/chp.c linux-2.6.22-570/drivers/s390/cio/chp.c
+--- linux-2.6.22-590/drivers/s390/cio/chp.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/s390/cio/chp.c    2007-07-08 19:32:17.000000000 -0400
+@@ -141,9 +141,8 @@
+ /*
+  * Channel measurement related functions
+  */
+-static ssize_t chp_measurement_chars_read(struct kobject *kobj,
+-                                        struct bin_attribute *bin_attr,
+-                                        char *buf, loff_t off, size_t count)
++static ssize_t chp_measurement_chars_read(struct kobject *kobj, char *buf,
++                                        loff_t off, size_t count)
+ {
+       struct channel_path *chp;
+       unsigned int size;
+@@ -166,6 +165,7 @@
+       .attr = {
+               .name = "measurement_chars",
+               .mode = S_IRUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = sizeof(struct cmg_chars),
+       .read = chp_measurement_chars_read,
+@@ -193,9 +193,8 @@
+       } while (reference_buf.values[0] != buf->values[0]);
  }
  
--void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
-+void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
+-static ssize_t chp_measurement_read(struct kobject *kobj,
+-                                  struct bin_attribute *bin_attr,
+-                                  char *buf, loff_t off, size_t count)
++static ssize_t chp_measurement_read(struct kobject *kobj, char *buf,
++                                  loff_t off, size_t count)
  {
--      struct lpfc_sli      * psli   = &phba->sli;
--      struct lpfc_sli_ring * pring = &psli->ring[LPFC_FCP_RING];
-+      struct lpfc_sli      *psli  = &phba->sli;
-+      struct lpfc_sli_ring *pring = &psli->ring[LPFC_FCP_RING];
-       IOCB_t *irsp = NULL;
-       IOCB_t *entry = NULL;
-       struct lpfc_iocbq *cmdiocbq = NULL;
-@@ -931,13 +1139,15 @@
-       uint32_t portRspPut, portRspMax;
-       int type;
-       uint32_t rsp_cmpl = 0;
--      void __iomem *to_slim;
-       uint32_t ha_copy;
-+      unsigned long iflags;
+       struct channel_path *chp;
+       struct channel_subsystem *css;
+@@ -218,6 +217,7 @@
+       .attr = {
+               .name = "measurement",
+               .mode = S_IRUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = sizeof(struct cmg_entry),
+       .read = chp_measurement_read,
+diff -Nurb linux-2.6.22-590/drivers/s390/net/qeth_main.c linux-2.6.22-570/drivers/s390/net/qeth_main.c
+--- linux-2.6.22-590/drivers/s390/net/qeth_main.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/s390/net/qeth_main.c      2007-07-08 19:32:17.000000000 -0400
+@@ -8127,7 +8127,7 @@
+       neigh->parms = neigh_parms_clone(parms);
+       rcu_read_unlock();
  
-       pring->stats.iocb_event++;
+-      neigh->type = inet_addr_type(&init_net, *(__be32 *) neigh->primary_key);
++      neigh->type = inet_addr_type(*(__be32 *) neigh->primary_key);
+       neigh->nud_state = NUD_NOARP;
+       neigh->ops = arp_direct_ops;
+       neigh->output = neigh->ops->queue_xmit;
+diff -Nurb linux-2.6.22-590/drivers/s390/net/qeth_sys.c linux-2.6.22-570/drivers/s390/net/qeth_sys.c
+--- linux-2.6.22-590/drivers/s390/net/qeth_sys.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/s390/net/qeth_sys.c       2007-07-08 19:32:17.000000000 -0400
+@@ -991,7 +991,7 @@
  
--      /* The driver assumes SLI-2 mode */
--      pgp =  &phba->slim2p->mbx.us.s2.port[pring->ringno];
-+      pgp = (phba->sli_rev == 3) ?
-+              &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
-+              &phba->slim2p->mbx.us.s2.port[pring->ringno];
-+
+ #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store)                             \
+ struct device_attribute dev_attr_##_id = {                                 \
+-      .attr = {.name=__stringify(_name), .mode=_mode, },\
++      .attr = {.name=__stringify(_name), .mode=_mode, .owner=THIS_MODULE },\
+       .show   = _show,                                                     \
+       .store  = _store,                                                    \
+ };
+diff -Nurb linux-2.6.22-590/drivers/s390/scsi/zfcp_aux.c linux-2.6.22-570/drivers/s390/scsi/zfcp_aux.c
+--- linux-2.6.22-590/drivers/s390/scsi/zfcp_aux.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/s390/scsi/zfcp_aux.c      2007-07-08 19:32:17.000000000 -0400
+@@ -815,7 +815,9 @@
+ struct zfcp_unit *
+ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
+ {
+-      struct zfcp_unit *unit;
++      struct zfcp_unit *unit, *tmp_unit;
++      unsigned int scsi_lun;
++      int found;
  
        /*
-        * The next available response entry should never exceed the maximum
-@@ -952,15 +1162,13 @@
-       rmb();
-       while (pring->rspidx != portRspPut) {
--
--              entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
--
-+              entry = lpfc_resp_iocb(phba, pring);
-               if (++pring->rspidx >= portRspMax)
-                       pring->rspidx = 0;
-               lpfc_sli_pcimem_bcopy((uint32_t *) entry,
-                                     (uint32_t *) &rspiocbq.iocb,
--                                    sizeof (IOCB_t));
-+                                    phba->iocb_rsp_size);
-               irsp = &rspiocbq.iocb;
-               type = lpfc_sli_iocb_cmd_type(irsp->ulpCommand & CMD_IOCB_MASK);
-               pring->stats.iocb_rsp++;
-@@ -998,8 +1206,10 @@
-                               break;
-                       }
-+                      spin_lock_irqsave(&phba->hbalock, iflags);
-                       cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
-                                                        &rspiocbq);
-+                      spin_unlock_irqrestore(&phba->hbalock, iflags);
-                       if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) {
-                               (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
-                                                     &rspiocbq);
-@@ -1033,9 +1243,7 @@
-                * been updated, sync the pgp->rspPutInx and fetch the new port
-                * response put pointer.
-                */
--              to_slim = phba->MBslimaddr +
--                      (SLIMOFF + (pring->ringno * 2) + 1) * 4;
--              writeb(pring->rspidx, to_slim);
-+              writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
-               if (pring->rspidx == portRspPut)
-                       portRspPut = le32_to_cpu(pgp->rspPutInx);
-@@ -1045,13 +1253,16 @@
-       ha_copy >>= (LPFC_FCP_RING * 4);
-       if ((rsp_cmpl > 0) && (ha_copy & HA_R0RE_REQ)) {
-+              spin_lock_irqsave(&phba->hbalock, iflags);
-               pring->stats.iocb_rsp_full++;
-               status = ((CA_R0ATT | CA_R0RE_RSP) << (LPFC_FCP_RING * 4));
-               writel(status, phba->CAregaddr);
-               readl(phba->CAregaddr);
-+              spin_unlock_irqrestore(&phba->hbalock, iflags);
+        * check that there is no unit with this FCP_LUN already in list
+@@ -861,9 +863,21 @@
        }
-       if ((ha_copy & HA_R0CE_RSP) &&
-           (pring->flag & LPFC_CALL_RING_AVAILABLE)) {
-+              spin_lock_irqsave(&phba->hbalock, iflags);
-               pring->flag &= ~LPFC_CALL_RING_AVAILABLE;
-               pring->stats.iocb_cmd_empty++;
  
-@@ -1062,6 +1273,7 @@
-               if ((pring->lpfc_sli_cmd_available))
-                       (pring->lpfc_sli_cmd_available) (phba, pring);
+       zfcp_unit_get(unit);
+-      unit->scsi_lun = scsilun_to_int((struct scsi_lun *)&unit->fcp_lun);
  
-+              spin_unlock_irqrestore(&phba->hbalock, iflags);
++      scsi_lun = 0;
++      found = 0;
+       write_lock_irq(&zfcp_data.config_lock);
++      list_for_each_entry(tmp_unit, &port->unit_list_head, list) {
++              if (tmp_unit->scsi_lun != scsi_lun) {
++                      found = 1;
++                      break;
++              }
++              scsi_lun++;
++      }
++      unit->scsi_lun = scsi_lun;
++      if (found)
++              list_add_tail(&unit->list, &tmp_unit->list);
++      else
+               list_add_tail(&unit->list, &port->unit_list_head);
+       atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
+       atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
+diff -Nurb linux-2.6.22-590/drivers/s390/scsi/zfcp_erp.c linux-2.6.22-570/drivers/s390/scsi/zfcp_erp.c
+--- linux-2.6.22-590/drivers/s390/scsi/zfcp_erp.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/s390/scsi/zfcp_erp.c      2007-07-08 19:32:17.000000000 -0400
+@@ -1986,10 +1986,6 @@
+  failed_openfcp:
+       zfcp_close_fsf(erp_action->adapter);
+  failed_qdio:
+-      atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
+-                        ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
+-                        ZFCP_STATUS_ADAPTER_XPORT_OK,
+-                        &erp_action->adapter->status);
+  out:
+       return retval;
+ }
+@@ -2171,9 +2167,6 @@
+               sleep *= 2;
        }
  
-       return;
-@@ -1072,10 +1284,12 @@
-  * to check it explicitly.
-  */
- static int
--lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
--                              struct lpfc_sli_ring * pring, uint32_t mask)
-+lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
-+                              struct lpfc_sli_ring *pring, uint32_t mask)
- {
--      struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
-+      struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
-+              &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
-+              &phba->slim2p->mbx.us.s2.port[pring->ringno];
-       IOCB_t *irsp = NULL;
-       IOCB_t *entry = NULL;
-       struct lpfc_iocbq *cmdiocbq = NULL;
-@@ -1086,9 +1300,8 @@
-       lpfc_iocb_type type;
-       unsigned long iflag;
-       uint32_t rsp_cmpl = 0;
--      void __iomem  *to_slim;
+-      atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
+-                        &adapter->status);
+-
+       if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
+                             &adapter->status)) {
+               ZFCP_LOG_INFO("error: exchange of configuration data for "
+diff -Nurb linux-2.6.22-590/drivers/sbus/char/bbc_envctrl.c linux-2.6.22-570/drivers/sbus/char/bbc_envctrl.c
+--- linux-2.6.22-590/drivers/sbus/char/bbc_envctrl.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/sbus/char/bbc_envctrl.c   2007-07-08 19:32:17.000000000 -0400
+@@ -7,7 +7,6 @@
+ #include <linux/kthread.h>
+ #include <linux/delay.h>
+ #include <linux/kmod.h>
+-#include <linux/reboot.h>
+ #include <asm/oplib.h>
+ #include <asm/ebus.h>
  
--      spin_lock_irqsave(phba->host->host_lock, iflag);
-+      spin_lock_irqsave(&phba->hbalock, iflag);
-       pring->stats.iocb_event++;
+@@ -171,6 +170,8 @@
+ static void do_envctrl_shutdown(struct bbc_cpu_temperature *tp)
+ {
+       static int shutting_down = 0;
++      static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
++      char *argv[] = { "/sbin/shutdown", "-h", "now", NULL };
+       char *type = "???";
+       s8 val = -1;
  
-       /*
-@@ -1099,7 +1312,7 @@
-       portRspPut = le32_to_cpu(pgp->rspPutInx);
-       if (unlikely(portRspPut >= portRspMax)) {
-               lpfc_sli_rsp_pointers_error(phba, pring);
--              spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+              spin_unlock_irqrestore(&phba->hbalock, iflag);
-               return 1;
-       }
+@@ -194,7 +195,7 @@
+       printk(KERN_CRIT "kenvctrld: Shutting down the system now.\n");
  
-@@ -1110,14 +1323,15 @@
-                * structure.  The copy involves a byte-swap since the
-                * network byte order and pci byte orders are different.
-                */
--              entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
-+              entry = lpfc_resp_iocb(phba, pring);
-+              phba->last_completion_time = jiffies;
+       shutting_down = 1;
+-      if (orderly_poweroff(true) < 0)
++      if (call_usermodehelper("/sbin/shutdown", argv, envp, 0) < 0)
+               printk(KERN_CRIT "envctrl: shutdown execution failed\n");
+ }
  
-               if (++pring->rspidx >= portRspMax)
-                       pring->rspidx = 0;
+diff -Nurb linux-2.6.22-590/drivers/sbus/char/envctrl.c linux-2.6.22-570/drivers/sbus/char/envctrl.c
+--- linux-2.6.22-590/drivers/sbus/char/envctrl.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/sbus/char/envctrl.c       2007-07-08 19:32:17.000000000 -0400
+@@ -26,7 +26,6 @@
+ #include <linux/ioport.h>
+ #include <linux/miscdevice.h>
+ #include <linux/kmod.h>
+-#include <linux/reboot.h>
  
-               lpfc_sli_pcimem_bcopy((uint32_t *) entry,
-                                     (uint32_t *) &rspiocbq.iocb,
--                                    sizeof (IOCB_t));
-+                                    phba->iocb_rsp_size);
-               INIT_LIST_HEAD(&(rspiocbq.list));
-               irsp = &rspiocbq.iocb;
+ #include <asm/ebus.h>
+ #include <asm/uaccess.h>
+@@ -967,6 +966,10 @@
+ static void envctrl_do_shutdown(void)
+ {
+       static int inprog = 0;
++      static char *envp[] = { 
++              "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
++      char *argv[] = { 
++              "/sbin/shutdown", "-h", "now", NULL };  
+       int ret;
  
-@@ -1126,14 +1340,28 @@
-               rsp_cmpl++;
+       if (inprog != 0)
+@@ -974,7 +977,7 @@
  
-               if (unlikely(irsp->ulpStatus)) {
-+                      /*
-+                       * If resource errors reported from HBA, reduce
-+                       * queuedepths of the SCSI device.
-+                       */
-+                      if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-+                              (irsp->un.ulpWord[4] == IOERR_NO_RESOURCES)) {
-+                              spin_unlock_irqrestore(&phba->hbalock, iflag);
-+                              lpfc_adjust_queue_depth(phba);
-+                              spin_lock_irqsave(&phba->hbalock, iflag);
-+                      }
-+
-                       /* Rsp ring <ringno> error: IOCB */
-                       lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
-                               "%d:0336 Rsp Ring %d error: IOCB Data: "
-                               "x%x x%x x%x x%x x%x x%x x%x x%x\n",
-                               phba->brd_no, pring->ringno,
--                              irsp->un.ulpWord[0], irsp->un.ulpWord[1],
--                              irsp->un.ulpWord[2], irsp->un.ulpWord[3],
--                              irsp->un.ulpWord[4], irsp->un.ulpWord[5],
-+                                      irsp->un.ulpWord[0],
-+                                      irsp->un.ulpWord[1],
-+                                      irsp->un.ulpWord[2],
-+                                      irsp->un.ulpWord[3],
-+                                      irsp->un.ulpWord[4],
-+                                      irsp->un.ulpWord[5],
-                               *(((uint32_t *) irsp) + 6),
-                               *(((uint32_t *) irsp) + 7));
-               }
-@@ -1149,7 +1377,8 @@
-                               lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-                                               "%d:0333 IOCB cmd 0x%x"
-                                               " processed. Skipping"
--                                              " completion\n", phba->brd_no,
-+                                              " completion\n",
-+                                              phba->brd_no,
-                                               irsp->ulpCommand);
-                               break;
-                       }
-@@ -1161,19 +1390,19 @@
-                                       (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
-                                                             &rspiocbq);
-                               } else {
--                                      spin_unlock_irqrestore(
--                                              phba->host->host_lock, iflag);
-+                                      spin_unlock_irqrestore(&phba->hbalock,
-+                                                             iflag);
-                                       (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
-                                                             &rspiocbq);
--                                      spin_lock_irqsave(phba->host->host_lock,
-+                                      spin_lock_irqsave(&phba->hbalock,
-                                                         iflag);
+       inprog = 1;
+       printk(KERN_CRIT "kenvctrld: WARNING: Shutting down the system now.\n");
+-      ret = orderly_poweroff(true);
++      ret = call_usermodehelper("/sbin/shutdown", argv, envp, 0);
+       if (ret < 0) {
+               printk(KERN_CRIT "kenvctrld: WARNING: system shutdown failed!\n"); 
+               inprog = 0;  /* unlikely to succeed, but we could try again */
+diff -Nurb linux-2.6.22-590/drivers/scsi/3w-9xxx.c linux-2.6.22-570/drivers/scsi/3w-9xxx.c
+--- linux-2.6.22-590/drivers/scsi/3w-9xxx.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/3w-9xxx.c    2008-01-23 19:15:55.000000000 -0500
+@@ -1307,26 +1307,22 @@
+                                       wake_up(&tw_dev->ioctl_wqueue);
                                }
-                       }
-                       break;
-               case LPFC_UNSOL_IOCB:
--                      spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+                      spin_unlock_irqrestore(&phba->hbalock, iflag);
-                       lpfc_sli_process_unsol_iocb(phba, pring, &rspiocbq);
--                      spin_lock_irqsave(phba->host->host_lock, iflag);
-+                      spin_lock_irqsave(&phba->hbalock, iflag);
-                       break;
-               default:
-                       if (irsp->ulpCommand == CMD_ADAPTER_MSG) {
-@@ -1188,8 +1417,10 @@
-                               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                                       "%d:0334 Unknown IOCB command "
-                                       "Data: x%x, x%x x%x x%x x%x\n",
--                                      phba->brd_no, type, irsp->ulpCommand,
--                                      irsp->ulpStatus, irsp->ulpIoTag,
-+                                              phba->brd_no, type,
-+                                              irsp->ulpCommand,
-+                                              irsp->ulpStatus,
-+                                              irsp->ulpIoTag,
-                                       irsp->ulpContext);
-                       }
-                       break;
-@@ -1201,9 +1432,7 @@
-                * been updated, sync the pgp->rspPutInx and fetch the new port
-                * response put pointer.
-                */
--              to_slim = phba->MBslimaddr +
--                      (SLIMOFF + (pring->ringno * 2) + 1) * 4;
--              writel(pring->rspidx, to_slim);
-+              writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
-               if (pring->rspidx == portRspPut)
-                       portRspPut = le32_to_cpu(pgp->rspPutInx);
-@@ -1228,31 +1457,31 @@
-       }
--      spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+      spin_unlock_irqrestore(&phba->hbalock, iflag);
-       return rc;
- }
+                       } else {
+-                              struct scsi_cmnd *cmd;
 -
- int
--lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
--                         struct lpfc_sli_ring * pring, uint32_t mask)
-+lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
-+                              struct lpfc_sli_ring *pring, uint32_t mask)
- {
-+      struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
-+              &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
-+              &phba->slim2p->mbx.us.s2.port[pring->ringno];
-       IOCB_t *entry;
-       IOCB_t *irsp = NULL;
-       struct lpfc_iocbq *rspiocbp = NULL;
-       struct lpfc_iocbq *next_iocb;
-       struct lpfc_iocbq *cmdiocbp;
-       struct lpfc_iocbq *saveq;
--      struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
-       uint8_t iocb_cmd_type;
-       lpfc_iocb_type type;
-       uint32_t status, free_saveq;
-       uint32_t portRspPut, portRspMax;
-       int rc = 1;
-       unsigned long iflag;
--      void __iomem  *to_slim;
+-                              cmd = tw_dev->srb[request_id];
+-
+                               twa_scsiop_execute_scsi_complete(tw_dev, request_id);
+                               /* If no error command was a success */
+                               if (error == 0) {
+-                                      cmd->result = (DID_OK << 16);
++                                      tw_dev->srb[request_id]->result = (DID_OK << 16);
+                               }
  
--      spin_lock_irqsave(phba->host->host_lock, iflag);
-+      spin_lock_irqsave(&phba->hbalock, iflag);
-       pring->stats.iocb_event++;
+                               /* If error, command failed */
+                               if (error == 1) {
+                                       /* Ask for a host reset */
+-                                      cmd->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
++                                      tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+                               }
  
-       /*
-@@ -1266,16 +1495,14 @@
-                * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
-                * rsp ring <portRspMax>
-                */
--              lpfc_printf_log(phba,
--                              KERN_ERR,
--                              LOG_SLI,
-+              lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                               "%d:0303 Ring %d handler: portRspPut %d "
-                               "is bigger then rsp ring %d\n",
--                              phba->brd_no,
--                              pring->ringno, portRspPut, portRspMax);
-+                              phba->brd_no, pring->ringno, portRspPut,
-+                              portRspMax);
+                               /* Report residual bytes for single sgl */
+-                              if ((scsi_sg_count(cmd) <= 1) && (full_command_packet->command.newcommand.status == 0)) {
+-                                      if (full_command_packet->command.newcommand.sg_list[0].length < scsi_bufflen(tw_dev->srb[request_id]))
+-                                              scsi_set_resid(cmd, scsi_bufflen(cmd) - full_command_packet->command.newcommand.sg_list[0].length);
++                              if ((tw_dev->srb[request_id]->use_sg <= 1) && (full_command_packet->command.newcommand.status == 0)) {
++                                      if (full_command_packet->command.newcommand.sg_list[0].length < tw_dev->srb[request_id]->request_bufflen)
++                                              tw_dev->srb[request_id]->resid = tw_dev->srb[request_id]->request_bufflen - full_command_packet->command.newcommand.sg_list[0].length;
+                               }
  
--              phba->hba_state = LPFC_HBA_ERROR;
--              spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+              phba->link_state = LPFC_HBA_ERROR;
-+              spin_unlock_irqrestore(&phba->hbalock, iflag);
+                               /* Now complete the io */
+@@ -1389,21 +1385,53 @@
+ {
+       int use_sg;
+       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
++      struct pci_dev *pdev = tw_dev->tw_pci_dev;
++      int retval = 0;
  
-               phba->work_hs = HS_FFER3;
-               lpfc_handle_eratt(phba);
-@@ -1298,23 +1525,24 @@
-                * the ulpLe field is set, the entire Command has been
-                * received.
-                */
--              entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
--              rspiocbp = lpfc_sli_get_iocbq(phba);
-+              entry = lpfc_resp_iocb(phba, pring);
+-      use_sg = scsi_dma_map(cmd);
+-      if (!use_sg)
+-              return 0;
+-      else if (use_sg < 0) {
++      if (cmd->use_sg == 0)
++              goto out;
 +
-+              phba->last_completion_time = jiffies;
-+              rspiocbp = __lpfc_sli_get_iocbq(phba);
-               if (rspiocbp == NULL) {
-                       printk(KERN_ERR "%s: out of buffers! Failing "
-                              "completion.\n", __FUNCTION__);
-                       break;
-               }
--              lpfc_sli_pcimem_bcopy(entry, &rspiocbp->iocb, sizeof (IOCB_t));
-+              lpfc_sli_pcimem_bcopy(entry, &rspiocbp->iocb,
-+                                    phba->iocb_rsp_size);
-               irsp = &rspiocbp->iocb;
++      use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
++
++      if (use_sg == 0) {
+               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
+-              return 0;
++              goto out;
+       }
  
-               if (++pring->rspidx >= portRspMax)
-                       pring->rspidx = 0;
+       cmd->SCp.phase = TW_PHASE_SGLIST;
+       cmd->SCp.have_data_in = use_sg;
+-
+-      return use_sg;
++      retval = use_sg;
++out:
++      return retval;
+ } /* End twa_map_scsi_sg_data() */
  
--              to_slim = phba->MBslimaddr + (SLIMOFF + (pring->ringno * 2)
--                                            + 1) * 4;
--              writel(pring->rspidx, to_slim);
-+              writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
++/* This function will perform a pci-dma map for a single buffer */
++static dma_addr_t twa_map_scsi_single_data(TW_Device_Extension *tw_dev, int request_id)
++{
++      dma_addr_t mapping;
++      struct scsi_cmnd *cmd = tw_dev->srb[request_id];
++      struct pci_dev *pdev = tw_dev->tw_pci_dev;
++      dma_addr_t retval = 0;
++
++      if (cmd->request_bufflen == 0) {
++              retval = 0;
++              goto out;
++      }
++
++      mapping = pci_map_single(pdev, cmd->request_buffer, cmd->request_bufflen, DMA_BIDIRECTIONAL);
++
++      if (mapping == 0) {
++              TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Failed to map page");
++              goto out;
++      }
++
++      cmd->SCp.phase = TW_PHASE_SINGLE;
++      cmd->SCp.have_data_in = mapping;
++      retval = mapping;
++out:
++      return retval;
++} /* End twa_map_scsi_single_data() */
++
+ /* This function will poll for a response interrupt of a request */
+ static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
+ {
+@@ -1788,13 +1816,15 @@
+       u32 num_sectors = 0x0;
+       int i, sg_count;
+       struct scsi_cmnd *srb = NULL;
+-      struct scatterlist *sglist = NULL, *sg;
++      struct scatterlist *sglist = NULL;
++      dma_addr_t buffaddr = 0x0;
+       int retval = 1;
  
-               if (list_empty(&(pring->iocb_continueq))) {
-                       list_add(&rspiocbp->list, &(pring->iocb_continueq));
-@@ -1338,13 +1566,26 @@
+       if (tw_dev->srb[request_id]) {
++              if (tw_dev->srb[request_id]->request_buffer) {
++                      sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
++              }
+               srb = tw_dev->srb[request_id];
+-              if (scsi_sglist(srb))
+-                      sglist = scsi_sglist(srb);
+       }
  
-                       pring->stats.iocb_rsp++;
+       /* Initialize command packet */
+@@ -1827,12 +1857,32 @@
  
-+                      /*
-+                       * If resource errors reported from HBA, reduce
-+                       * queuedepths of the SCSI device.
-+                       */
-+                      if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-+                           (irsp->un.ulpWord[4] == IOERR_NO_RESOURCES)) {
-+                              spin_unlock_irqrestore(&phba->hbalock, iflag);
-+                              lpfc_adjust_queue_depth(phba);
-+                              spin_lock_irqsave(&phba->hbalock, iflag);
+       if (!sglistarg) {
+               /* Map sglist from scsi layer to cmd packet */
++              if (tw_dev->srb[request_id]->use_sg == 0) {
++                      if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {
++                              command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
++                              command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
++                              if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)
++                                      memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
++                      } else {
++                              buffaddr = twa_map_scsi_single_data(tw_dev, request_id);
++                              if (buffaddr == 0)
++                                      goto out;
++
++                              command_packet->sg_list[0].address = TW_CPU_TO_SGL(buffaddr);
++                              command_packet->sg_list[0].length = cpu_to_le32(tw_dev->srb[request_id]->request_bufflen);
++                      }
++                      command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 1));
+-              if (scsi_sg_count(srb)) {
+-                      if ((scsi_sg_count(srb) == 1) &&
+-                          (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
+-                              if (srb->sc_data_direction == DMA_TO_DEVICE || srb->sc_data_direction == DMA_BIDIRECTIONAL) {
+-                                      struct scatterlist *sg = scsi_sglist(srb);
++                      if (command_packet->sg_list[0].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
++                              TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi");
++                              goto out;
 +                      }
++              }
 +
-                       if (irsp->ulpStatus) {
-                               /* Rsp ring <ringno> error: IOCB */
--                              lpfc_printf_log(phba,
--                                      KERN_WARNING,
--                                      LOG_SLI,
--                                      "%d:0328 Rsp Ring %d error: IOCB Data: "
--                                      "x%x x%x x%x x%x x%x x%x x%x x%x\n",
-+                              lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
-+                                              "%d:0328 Rsp Ring %d error: "
-+                                              "IOCB Data: "
-+                                              "x%x x%x x%x x%x "
-+                                              "x%x x%x x%x x%x "
-+                                              "x%x x%x x%x x%x "
-+                                              "x%x x%x x%x x%x\n",
-                                       phba->brd_no,
-                                       pring->ringno,
-                                       irsp->un.ulpWord[0],
-@@ -1354,7 +1595,15 @@
-                                       irsp->un.ulpWord[4],
-                                       irsp->un.ulpWord[5],
-                                       *(((uint32_t *) irsp) + 6),
--                                      *(((uint32_t *) irsp) + 7));
-+                                              *(((uint32_t *) irsp) + 7),
-+                                              *(((uint32_t *) irsp) + 8),
-+                                              *(((uint32_t *) irsp) + 9),
-+                                              *(((uint32_t *) irsp) + 10),
-+                                              *(((uint32_t *) irsp) + 11),
-+                                              *(((uint32_t *) irsp) + 12),
-+                                              *(((uint32_t *) irsp) + 13),
-+                                              *(((uint32_t *) irsp) + 14),
-+                                              *(((uint32_t *) irsp) + 15));
-                       }
-                       /*
-@@ -1366,17 +1615,17 @@
-                       iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK;
-                       type = lpfc_sli_iocb_cmd_type(iocb_cmd_type);
-                       if (type == LPFC_SOL_IOCB) {
--                              spin_unlock_irqrestore(phba->host->host_lock,
-+                              spin_unlock_irqrestore(&phba->hbalock,
-                                                      iflag);
-                               rc = lpfc_sli_process_sol_iocb(phba, pring,
-                                       saveq);
--                              spin_lock_irqsave(phba->host->host_lock, iflag);
-+                              spin_lock_irqsave(&phba->hbalock, iflag);
-                       } else if (type == LPFC_UNSOL_IOCB) {
--                              spin_unlock_irqrestore(phba->host->host_lock,
-+                              spin_unlock_irqrestore(&phba->hbalock,
-                                                      iflag);
-                               rc = lpfc_sli_process_unsol_iocb(phba, pring,
-                                       saveq);
--                              spin_lock_irqsave(phba->host->host_lock, iflag);
-+                              spin_lock_irqsave(&phba->hbalock, iflag);
-                       } else if (type == LPFC_ABORT_IOCB) {
-                               if ((irsp->ulpCommand != CMD_XRI_ABORTED_CX) &&
-                                   ((cmdiocbp =
-@@ -1386,15 +1635,15 @@
-                                          routine */
-                                       if (cmdiocbp->iocb_cmpl) {
-                                               spin_unlock_irqrestore(
--                                                     phba->host->host_lock,
-+                                                     &phba->hbalock,
-                                                      iflag);
-                                               (cmdiocbp->iocb_cmpl) (phba,
-                                                            cmdiocbp, saveq);
-                                               spin_lock_irqsave(
--                                                        phba->host->host_lock,
-+                                                        &phba->hbalock,
-                                                         iflag);
-                                       } else
--                                              lpfc_sli_release_iocbq(phba,
-+                                              __lpfc_sli_release_iocbq(phba,
-                                                                     cmdiocbp);
-                               }
-                       } else if (type == LPFC_UNKNOWN_IOCB) {
-@@ -1411,11 +1660,10 @@
-                                                phba->brd_no, adaptermsg);
-                               } else {
-                                       /* Unknown IOCB command */
--                                      lpfc_printf_log(phba,
--                                              KERN_ERR,
--                                              LOG_SLI,
--                                              "%d:0335 Unknown IOCB command "
--                                              "Data: x%x x%x x%x x%x\n",
-+                                      lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-+                                                      "%d:0335 Unknown IOCB "
-+                                                      "command Data: x%x "
-+                                                      "x%x x%x x%x\n",
-                                               phba->brd_no,
-                                               irsp->ulpCommand,
-                                               irsp->ulpStatus,
-@@ -1425,18 +1673,15 @@
-                       }
++              if (tw_dev->srb[request_id]->use_sg > 0) {
++                      if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
++                              if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) {
++                                      struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+                                       char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+                                       memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
+                                       kunmap_atomic(buf - sg->offset, KM_IRQ0);
+@@ -1844,16 +1894,16 @@
+                               if (sg_count == 0)
+                                       goto out;
  
-                       if (free_saveq) {
--                              if (!list_empty(&saveq->list)) {
--                                      list_for_each_entry_safe(rspiocbp,
--                                                               next_iocb,
--                                                               &saveq->list,
--                                                               list) {
-+                              list_for_each_entry_safe(rspiocbp, next_iocb,
-+                                                       &saveq->list, list) {
-                                               list_del(&rspiocbp->list);
--                                              lpfc_sli_release_iocbq(phba,
-+                                      __lpfc_sli_release_iocbq(phba,
-                                                                    rspiocbp);
+-                              scsi_for_each_sg(srb, sg, sg_count, i) {
+-                                      command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(sg));
+-                                      command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(sg));
++                              for (i = 0; i < sg_count; i++) {
++                                      command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(&sglist[i]));
++                                      command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(&sglist[i]));
+                                       if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
+                                               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
+                                               goto out;
                                        }
-+                              __lpfc_sli_release_iocbq(phba, saveq);
                                }
--                              lpfc_sli_release_iocbq(phba, saveq);
--                      }
-+                      rspiocbp = NULL;
-               }
-               /*
-@@ -1449,7 +1694,7 @@
+                       }
+-                      command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), scsi_sg_count(tw_dev->srb[request_id])));
++                      command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg));
                }
-       } /* while (pring->rspidx != portRspPut) */
--      if ((rspiocbp != 0) && (mask & HA_R0RE_REQ)) {
-+      if ((rspiocbp != NULL) && (mask & HA_R0RE_REQ)) {
-               /* At least one response entry has been freed */
-               pring->stats.iocb_rsp_full++;
-               /* SET RxRE_RSP in Chip Att register */
-@@ -1470,24 +1715,25 @@
-       }
--      spin_unlock_irqrestore(phba->host->host_lock, iflag);
-+      spin_unlock_irqrestore(&phba->hbalock, iflag);
-       return rc;
- }
--int
-+void
- lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
- {
-       LIST_HEAD(completions);
-       struct lpfc_iocbq *iocb, *next_iocb;
-       IOCB_t *cmd = NULL;
--      int errcnt;
--      errcnt = 0;
-+      if (pring->ringno == LPFC_ELS_RING) {
-+              lpfc_fabric_abort_hba(phba);
-+      }
-       /* Error everything on txq and txcmplq
-        * First do the txq.
-        */
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       list_splice_init(&pring->txq, &completions);
-       pring->txq_cnt = 0;
-@@ -1495,26 +1741,25 @@
-       list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
-               lpfc_sli_issue_abort_iotag(phba, pring, iocb);
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
-       while (!list_empty(&completions)) {
-               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
-               cmd = &iocb->iocb;
--              list_del(&iocb->list);
-+              list_del_init(&iocb->list);
+       } else {
+               /* Internal cdb post */
+@@ -1883,7 +1933,7 @@
  
--              if (iocb->iocb_cmpl) {
-+              if (!iocb->iocb_cmpl)
-+                      lpfc_sli_release_iocbq(phba, iocb);
-+              else {
-                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                       cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-                       (iocb->iocb_cmpl) (phba, iocb, iocb);
--              } else
--                      lpfc_sli_release_iocbq(phba, iocb);
+       /* Update SG statistics */
+       if (srb) {
+-              tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]);
++              tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
+               if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
+                       tw_dev->max_sgl_entries = tw_dev->sgl_entries;
        }
+@@ -1902,13 +1952,16 @@
+ /* This function completes an execute scsi operation */
+ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id)
+ {
+-      struct scsi_cmnd *cmd = tw_dev->srb[request_id];
 -
--      return errcnt;
-+      }
- }
- int
--lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
-+lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask)
+-      if (scsi_bufflen(cmd) < TW_MIN_SGL_LENGTH &&
+-          (cmd->sc_data_direction == DMA_FROM_DEVICE ||
+-           cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
+-              if (scsi_sg_count(cmd) == 1) {
+-                      struct scatterlist *sg = scsi_sglist(tw_dev->srb[request_id]);
++      if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH &&
++          (tw_dev->srb[request_id]->sc_data_direction == DMA_FROM_DEVICE ||
++           tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)) {
++              if (tw_dev->srb[request_id]->use_sg == 0) {
++                      memcpy(tw_dev->srb[request_id]->request_buffer,
++                             tw_dev->generic_buffer_virt[request_id],
++                             tw_dev->srb[request_id]->request_bufflen);
++              }
++              if (tw_dev->srb[request_id]->use_sg == 1) {
++                      struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+                       char *buf;
+                       unsigned long flags = 0;
+                       local_irq_save(flags);
+@@ -1965,8 +2018,16 @@
+ static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
  {
-       uint32_t status;
-       int i = 0;
-@@ -1541,7 +1786,8 @@
-                       msleep(2500);
-               if (i == 15) {
--                      phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
-+                              /* Do post */
-+                      phba->pport->port_state = LPFC_VPORT_UNKNOWN;
-                       lpfc_sli_brdrestart(phba);
-               }
-               /* Read the HBA Host Status Register */
-@@ -1550,7 +1796,7 @@
+       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
++      struct pci_dev *pdev = tw_dev->tw_pci_dev;
  
-       /* Check to see if any errors occurred during init */
-       if ((status & HS_FFERM) || (i >= 20)) {
--              phba->hba_state = LPFC_HBA_ERROR;
-+              phba->link_state = LPFC_HBA_ERROR;
-               retval = 1;
-       }
+-      scsi_dma_unmap(cmd);
++      switch(cmd->SCp.phase) {
++      case TW_PHASE_SINGLE:
++              pci_unmap_single(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL);
++              break;
++      case TW_PHASE_SGLIST:
++              pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
++              break;
++      }
+ } /* End twa_unmap_scsi_data() */
  
-@@ -1559,7 +1805,7 @@
+ /* scsi_host_template initializer */
+diff -Nurb linux-2.6.22-590/drivers/scsi/3w-xxxx.c linux-2.6.22-570/drivers/scsi/3w-xxxx.c
+--- linux-2.6.22-590/drivers/scsi/3w-xxxx.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/3w-xxxx.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1274,8 +1274,12 @@
  
- #define BARRIER_TEST_PATTERN (0xdeadbeef)
+       dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
+       
+-      use_sg = scsi_dma_map(cmd);
+-      if (use_sg < 0) {
++      if (cmd->use_sg == 0)
++              return 0;
++
++      use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
++      
++      if (use_sg == 0) {
+               printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
+               return 0;
+       }
+@@ -1286,11 +1290,40 @@
+       return use_sg;
+ } /* End tw_map_scsi_sg_data() */
  
--void lpfc_reset_barrier(struct lpfc_hba * phba)
-+void lpfc_reset_barrier(struct lpfc_hba *phba)
++static u32 tw_map_scsi_single_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
++{
++      dma_addr_t mapping;
++
++      dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data()\n");
++
++      if (cmd->request_bufflen == 0)
++              return 0;
++
++      mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), offset_in_page(cmd->request_buffer), cmd->request_bufflen, DMA_BIDIRECTIONAL);
++
++      if (mapping == 0) {
++              printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n");
++              return 0;
++      }
++
++      cmd->SCp.phase = TW_PHASE_SINGLE;
++      cmd->SCp.have_data_in = mapping;
++
++      return mapping;
++} /* End tw_map_scsi_single_data() */
++
+ static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
  {
-       uint32_t __iomem *resp_buf;
-       uint32_t __iomem *mbox_buf;
-@@ -1584,12 +1830,12 @@
-       hc_copy = readl(phba->HCregaddr);
-       writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
-       readl(phba->HCregaddr); /* flush */
--      phba->fc_flag |= FC_IGNORE_ERATT;
-+      phba->link_flag |= LS_IGNORE_ERATT;
-       if (readl(phba->HAregaddr) & HA_ERATT) {
-               /* Clear Chip error bit */
-               writel(HA_ERATT, phba->HAregaddr);
--              phba->stopped = 1;
-+              phba->pport->stopped = 1;
-       }
+       dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
  
-       mbox = 0;
-@@ -1606,7 +1852,7 @@
+-      scsi_dma_unmap(cmd);
++      switch(cmd->SCp.phase) {
++              case TW_PHASE_SINGLE:
++                      pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL);
++                      break;
++              case TW_PHASE_SGLIST:
++                      pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
++                      break;
++      }
+ } /* End tw_unmap_scsi_data() */
  
-       if (readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN)) {
-               if (phba->sli.sli_flag & LPFC_SLI2_ACTIVE ||
--                  phba->stopped)
-+                  phba->pport->stopped)
-                       goto restore_hc;
-               else
-                       goto clear_errat;
-@@ -1623,17 +1869,17 @@
+ /* This function will reset a device extension */
+@@ -1466,16 +1499,27 @@
+       void *buf;
+       unsigned int transfer_len;
+       unsigned long flags = 0;
+-      struct scatterlist *sg = scsi_sglist(cmd);
  
-       if (readl(phba->HAregaddr) & HA_ERATT) {
-               writel(HA_ERATT, phba->HAregaddr);
--              phba->stopped = 1;
-+              phba->pport->stopped = 1;
-       }
++      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 {
++              buf = cmd->request_buffer;
++              transfer_len = min(cmd->request_bufflen, len);
++      }
  
- restore_hc:
--      phba->fc_flag &= ~FC_IGNORE_ERATT;
-+      phba->link_flag &= ~LS_IGNORE_ERATT;
-       writel(hc_copy, phba->HCregaddr);
-       readl(phba->HCregaddr); /* flush */
+       memcpy(buf, data, transfer_len);
+       
++      if (cmd->use_sg) {
++              struct scatterlist *sg;
++
++              sg = (struct scatterlist *)cmd->request_buffer;
+               kunmap_atomic(buf - sg->offset, KM_IRQ0);
+               local_irq_restore(flags);
++      }
  }
  
- int
--lpfc_sli_brdkill(struct lpfc_hba * phba)
-+lpfc_sli_brdkill(struct lpfc_hba *phba)
+ /* This function is called by the isr to complete an inquiry command */
+@@ -1720,20 +1764,19 @@
  {
-       struct lpfc_sli *psli;
-       LPFC_MBOXQ_t *pmb;
-@@ -1645,26 +1891,22 @@
-       psli = &phba->sli;
-       /* Kill HBA */
--      lpfc_printf_log(phba,
--              KERN_INFO,
--              LOG_SLI,
-+      lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-               "%d:0329 Kill HBA Data: x%x x%x\n",
--              phba->brd_no,
--              phba->hba_state,
--              psli->sli_flag);
-+                      phba->brd_no, phba->pport->port_state, psli->sli_flag);
-       if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
-                                                 GFP_KERNEL)) == 0)
-               return 1;
+       TW_Command *command_packet;
+       unsigned long command_que_value;
+-      u32 lba = 0x0, num_sectors = 0x0;
++      u32 lba = 0x0, num_sectors = 0x0, buffaddr = 0x0;
+       int i, use_sg;
+       struct scsi_cmnd *srb;
+-      struct scatterlist *sglist, *sg;
++      struct scatterlist *sglist;
  
-       /* Disable the error attention */
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       status = readl(phba->HCregaddr);
-       status &= ~HC_ERINT_ENA;
-       writel(status, phba->HCregaddr);
-       readl(phba->HCregaddr); /* flush */
--      phba->fc_flag |= FC_IGNORE_ERATT;
--      spin_unlock_irq(phba->host->host_lock);
-+      phba->link_flag |= LS_IGNORE_ERATT;
-+      spin_unlock_irq(&phba->hbalock);
+       dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n");
  
-       lpfc_kill_board(phba, pmb);
-       pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-@@ -1673,9 +1915,9 @@
-       if (retval != MBX_SUCCESS) {
-               if (retval != MBX_BUSY)
-                       mempool_free(pmb, phba->mbox_mem_pool);
--              spin_lock_irq(phba->host->host_lock);
--              phba->fc_flag &= ~FC_IGNORE_ERATT;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_lock_irq(&phba->hbalock);
-+              phba->link_flag &= ~LS_IGNORE_ERATT;
-+              spin_unlock_irq(&phba->hbalock);
+-      srb = tw_dev->srb[request_id];
+-
+-      sglist = scsi_sglist(srb);
+-      if (!sglist) {
++      if (tw_dev->srb[request_id]->request_buffer == NULL) {
+               printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n");
                return 1;
        }
++      sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
++      srb = tw_dev->srb[request_id];
  
-@@ -1698,22 +1940,22 @@
-       del_timer_sync(&psli->mbox_tmo);
-       if (ha_copy & HA_ERATT) {
-               writel(HA_ERATT, phba->HAregaddr);
--              phba->stopped = 1;
-+              phba->pport->stopped = 1;
-       }
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
--      phba->fc_flag &= ~FC_IGNORE_ERATT;
--      spin_unlock_irq(phba->host->host_lock);
-+      phba->link_flag &= ~LS_IGNORE_ERATT;
-+      spin_unlock_irq(&phba->hbalock);
-       psli->mbox_active = NULL;
-       lpfc_hba_down_post(phba);
--      phba->hba_state = LPFC_HBA_ERROR;
-+      phba->link_state = LPFC_HBA_ERROR;
--      return (ha_copy & HA_ERATT ? 0 : 1);
-+      return ha_copy & HA_ERATT ? 0 : 1;
- }
+       /* Initialize command packet */
+       command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+@@ -1776,18 +1819,33 @@
+       command_packet->byte8.io.lba = lba;
+       command_packet->byte6.block_count = num_sectors;
  
- int
--lpfc_sli_brdreset(struct lpfc_hba * phba)
-+lpfc_sli_brdreset(struct lpfc_hba *phba)
- {
-       struct lpfc_sli *psli;
-       struct lpfc_sli_ring *pring;
-@@ -1725,12 +1967,12 @@
-       /* Reset HBA */
-       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-                       "%d:0325 Reset HBA Data: x%x x%x\n", phba->brd_no,
--                      phba->hba_state, psli->sli_flag);
-+                      phba->pport->port_state, psli->sli_flag);
++      /* Do this if there are no sg list entries */
++      if (tw_dev->srb[request_id]->use_sg == 0) {    
++              dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n");
++              buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
++              if (buffaddr == 0)
++                      return 1;
++
++              command_packet->byte8.io.sgl[0].address = buffaddr;
++              command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
++              command_packet->size+=2;
++      }
++
++      /* Do this if we have multiple sg list entries */
++      if (tw_dev->srb[request_id]->use_sg > 0) {
+               use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
+-      if (!use_sg)
++              if (use_sg == 0)
+                       return 1;
  
-       /* perform board reset */
-       phba->fc_eventTag = 0;
--      phba->fc_myDID = 0;
--      phba->fc_prevDID = 0;
-+      phba->pport->fc_myDID = 0;
-+      phba->pport->fc_prevDID = 0;
+-      scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) {
+-              command_packet->byte8.io.sgl[i].address = sg_dma_address(sg);
+-              command_packet->byte8.io.sgl[i].length = sg_dma_len(sg);
++              for (i=0;i<use_sg; i++) {
++                      command_packet->byte8.io.sgl[i].address = sg_dma_address(&sglist[i]);
++                      command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]);
+                       command_packet->size+=2;
+               }
++      }
  
-       /* Turn off parity checking and serr during the physical reset */
-       pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
-@@ -1760,12 +2002,12 @@
-               pring->missbufcnt = 0;
-       }
+       /* Update SG statistics */
+-      tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]);
++      tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
+       if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
+               tw_dev->max_sgl_entries = tw_dev->sgl_entries;
  
--      phba->hba_state = LPFC_WARM_START;
-+      phba->link_state = LPFC_WARM_START;
-       return 0;
+diff -Nurb linux-2.6.22-590/drivers/scsi/53c700.c linux-2.6.22-570/drivers/scsi/53c700.c
+--- linux-2.6.22-590/drivers/scsi/53c700.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/53c700.c     2007-07-08 19:32:17.000000000 -0400
+@@ -585,8 +585,16 @@
+             struct NCR_700_command_slot *slot)
+ {
+       if(SCp->sc_data_direction != DMA_NONE &&
+-         SCp->sc_data_direction != DMA_BIDIRECTIONAL)
+-              scsi_dma_unmap(SCp);
++         SCp->sc_data_direction != DMA_BIDIRECTIONAL) {
++              if(SCp->use_sg) {
++                      dma_unmap_sg(hostdata->dev, SCp->request_buffer,
++                                   SCp->use_sg, SCp->sc_data_direction);
++              } else {
++                      dma_unmap_single(hostdata->dev, slot->dma_handle,
++                                       SCp->request_bufflen,
++                                       SCp->sc_data_direction);
++              }
++      }
  }
  
- int
--lpfc_sli_brdrestart(struct lpfc_hba * phba)
-+lpfc_sli_brdrestart(struct lpfc_hba *phba)
+ STATIC inline void
+@@ -653,6 +661,7 @@
  {
-       MAILBOX_t *mb;
-       struct lpfc_sli *psli;
-@@ -1773,14 +2015,14 @@
-       volatile uint32_t word0;
-       void __iomem *to_slim;
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       psli = &phba->sli;
-       /* Restart HBA */
-       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-                       "%d:0337 Restart HBA Data: x%x x%x\n", phba->brd_no,
--                      phba->hba_state, psli->sli_flag);
-+                      phba->pport->port_state, psli->sli_flag);
-       word0 = 0;
-       mb = (MAILBOX_t *) &word0;
-@@ -1794,7 +2036,7 @@
-       readl(to_slim); /* flush */
-       /* Only skip post after fc_ffinit is completed */
--      if (phba->hba_state) {
-+      if (phba->pport->port_state) {
-               skip_post = 1;
-               word0 = 1;      /* This is really setting up word1 */
-       } else {
-@@ -1806,10 +2048,10 @@
-       readl(to_slim); /* flush */
-       lpfc_sli_brdreset(phba);
--      phba->stopped = 0;
--      phba->hba_state = LPFC_INIT_START;
-+      phba->pport->stopped = 0;
-+      phba->link_state = LPFC_INIT_START;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
-       memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets));
-       psli->stats_start = get_seconds();
-@@ -1843,14 +2085,11 @@
-               if (i++ >= 20) {
-                       /* Adapter failed to init, timeout, status reg
-                          <status> */
--                      lpfc_printf_log(phba,
--                                      KERN_ERR,
--                                      LOG_INIT,
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                                       "%d:0436 Adapter failed to init, "
-                                       "timeout, status reg x%x\n",
--                                      phba->brd_no,
--                                      status);
--                      phba->hba_state = LPFC_HBA_ERROR;
-+                                      phba->brd_no, status);
-+                      phba->link_state = LPFC_HBA_ERROR;
-                       return -ETIMEDOUT;
-               }
-@@ -1859,14 +2098,12 @@
-                       /* ERROR: During chipset initialization */
-                       /* Adapter failed to init, chipset, status reg
-                          <status> */
--                      lpfc_printf_log(phba,
--                                      KERN_ERR,
--                                      LOG_INIT,
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                                       "%d:0437 Adapter failed to init, "
-                                       "chipset, status reg x%x\n",
-                                       phba->brd_no,
-                                       status);
--                      phba->hba_state = LPFC_HBA_ERROR;
-+                      phba->link_state = LPFC_HBA_ERROR;
-                       return -EIO;
-               }
+       struct NCR_700_Host_Parameters *hostdata = 
+               (struct NCR_700_Host_Parameters *)host->hostdata[0];
++      __u32 dcntl_extra = 0;
+       __u8 min_period;
+       __u8 min_xferp = (hostdata->chip710 ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP);
  
-@@ -1879,7 +2116,8 @@
+@@ -677,14 +686,13 @@
+                               burst_disable = BURST_DISABLE;
+                               break;
                }
+-              hostdata->dcntl_extra |= COMPAT_700_MODE;
++              dcntl_extra = COMPAT_700_MODE;
  
-               if (i == 15) {
--                      phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
-+                              /* Do post */
-+                      phba->pport->port_state = LPFC_VPORT_UNKNOWN;
-                       lpfc_sli_brdrestart(phba);
-               }
-               /* Read the HBA Host Status Register */
-@@ -1890,14 +2128,12 @@
-       if (status & HS_FFERM) {
-               /* ERROR: During chipset initialization */
-               /* Adapter failed to init, chipset, status reg <status> */
--              lpfc_printf_log(phba,
--                              KERN_ERR,
--                              LOG_INIT,
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "%d:0438 Adapter failed to init, chipset, "
-                               "status reg x%x\n",
-                               phba->brd_no,
-                               status);
--              phba->hba_state = LPFC_HBA_ERROR;
-+              phba->link_state = LPFC_HBA_ERROR;
-               return -EIO;
+-              NCR_700_writeb(hostdata->dcntl_extra, host, DCNTL_REG);
++              NCR_700_writeb(dcntl_extra, host, DCNTL_REG);
+               NCR_700_writeb(burst_length | hostdata->dmode_extra,
+                              host, DMODE_710_REG);
+-              NCR_700_writeb(burst_disable | hostdata->ctest7_extra |
+-                             (hostdata->differential ? DIFF : 0),
+-                             host, CTEST7_REG);
++              NCR_700_writeb(burst_disable | (hostdata->differential ? 
++                                              DIFF : 0), host, CTEST7_REG);
+               NCR_700_writeb(BTB_TIMER_DISABLE, host, CTEST0_REG);
+               NCR_700_writeb(FULL_ARBITRATION | ENABLE_PARITY | PARITY
+                              | AUTO_ATN, host, SCNTL0_REG);
+@@ -719,13 +727,13 @@
+                * of spec: sync divider 2, async divider 3 */
+               DEBUG(("53c700: sync 2 async 3\n"));
+               NCR_700_writeb(SYNC_DIV_2_0, host, SBCL_REG);
+-              NCR_700_writeb(ASYNC_DIV_3_0 | hostdata->dcntl_extra, host, DCNTL_REG);
++              NCR_700_writeb(ASYNC_DIV_3_0 | dcntl_extra, host, DCNTL_REG);
+               hostdata->sync_clock = hostdata->clock/2;
+       } else  if(hostdata->clock > 50  && hostdata->clock <= 75) {
+               /* sync divider 1.5, async divider 3 */
+               DEBUG(("53c700: sync 1.5 async 3\n"));
+               NCR_700_writeb(SYNC_DIV_1_5, host, SBCL_REG);
+-              NCR_700_writeb(ASYNC_DIV_3_0 | hostdata->dcntl_extra, host, DCNTL_REG);
++              NCR_700_writeb(ASYNC_DIV_3_0 | dcntl_extra, host, DCNTL_REG);
+               hostdata->sync_clock = hostdata->clock*2;
+               hostdata->sync_clock /= 3;
+               
+@@ -733,18 +741,18 @@
+               /* sync divider 1, async divider 2 */
+               DEBUG(("53c700: sync 1 async 2\n"));
+               NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
+-              NCR_700_writeb(ASYNC_DIV_2_0 | hostdata->dcntl_extra, host, DCNTL_REG);
++              NCR_700_writeb(ASYNC_DIV_2_0 | dcntl_extra, host, DCNTL_REG);
+               hostdata->sync_clock = hostdata->clock;
+       } else if(hostdata->clock > 25 && hostdata->clock <=37) {
+               /* sync divider 1, async divider 1.5 */
+               DEBUG(("53c700: sync 1 async 1.5\n"));
+               NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
+-              NCR_700_writeb(ASYNC_DIV_1_5 | hostdata->dcntl_extra, host, DCNTL_REG);
++              NCR_700_writeb(ASYNC_DIV_1_5 | dcntl_extra, host, DCNTL_REG);
+               hostdata->sync_clock = hostdata->clock;
+       } else {
+               DEBUG(("53c700: sync 1 async 1\n"));
+               NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);
+-              NCR_700_writeb(ASYNC_DIV_1_0 | hostdata->dcntl_extra, host, DCNTL_REG);
++              NCR_700_writeb(ASYNC_DIV_1_0 | dcntl_extra, host, DCNTL_REG);
+               /* sync divider 1, async divider 1 */
+               hostdata->sync_clock = hostdata->clock;
        }
+@@ -1255,11 +1263,12 @@
+                      host->host_no, pun, lun, NCR_700_condition[i],
+                      NCR_700_phase[j], dsp - hostdata->pScript);
+               if(SCp != NULL) {
+-                      struct scatterlist *sg;
+-
+                       scsi_print_command(SCp);
+-                      scsi_for_each_sg(SCp, sg, scsi_sg_count(SCp) + 1, i) {
+-                              printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, sg->length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);
++
++                      if(SCp->use_sg) {
++                              for(i = 0; i < SCp->use_sg + 1; i++) {
++                                      printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->request_buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);
++                              }
+                       }
+               }              
+               NCR_700_internal_bus_reset(host);
+@@ -1835,8 +1844,8 @@
+       }
+       /* sanity check: some of the commands generated by the mid-layer
+        * have an eccentric idea of their sc_data_direction */
+-      if(!scsi_sg_count(SCp) && !scsi_bufflen(SCp) &&
+-         SCp->sc_data_direction != DMA_NONE) {
++      if(!SCp->use_sg && !SCp->request_bufflen 
++         && SCp->sc_data_direction != DMA_NONE) {
+ #ifdef NCR_700_DEBUG
+               printk("53c700: Command");
+               scsi_print_command(SCp);
+@@ -1878,15 +1887,31 @@
+               int i;
+               int sg_count;
+               dma_addr_t vPtr = 0;
+-              struct scatterlist *sg;
+               __u32 count = 0;
  
-@@ -1911,68 +2147,239 @@
-       return 0;
- }
+-              sg_count = scsi_dma_map(SCp);
+-              BUG_ON(sg_count < 0);
++              if(SCp->use_sg) {
++                      sg_count = dma_map_sg(hostdata->dev,
++                                            SCp->request_buffer, SCp->use_sg,
++                                            direction);
++              } else {
++                      vPtr = dma_map_single(hostdata->dev,
++                                            SCp->request_buffer, 
++                                            SCp->request_bufflen,
++                                            direction);
++                      count = SCp->request_bufflen;
++                      slot->dma_handle = vPtr;
++                      sg_count = 1;
++              }
++                      
++
++              for(i = 0; i < sg_count; i++) {
+-              scsi_for_each_sg(SCp, sg, sg_count, i) {
+-                      vPtr = sg_dma_address(sg);
+-                      count = sg_dma_len(sg);
++                      if(SCp->use_sg) {
++                              struct scatterlist *sg = SCp->request_buffer;
++
++                              vPtr = sg_dma_address(&sg[i]);
++                              count = sg_dma_len(&sg[i]);
++                      }
  
--int
--lpfc_sli_hba_setup(struct lpfc_hba * phba)
-+static int
-+lpfc_sli_hbq_count(void)
- {
--      LPFC_MBOXQ_t *pmb;
--      uint32_t resetcount = 0, rc = 0, done = 0;
--
--      pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
--      if (!pmb) {
--              phba->hba_state = LPFC_HBA_ERROR;
--              return -ENOMEM;
--      }
-+      return ARRAY_SIZE(lpfc_hbq_defs);
+                       slot->SG[i].ins = bS_to_host(move_ins | count);
+                       DEBUG((" scatter block %d: move %d[%08x] from 0x%lx\n",
+diff -Nurb linux-2.6.22-590/drivers/scsi/53c700.h linux-2.6.22-570/drivers/scsi/53c700.h
+--- linux-2.6.22-590/drivers/scsi/53c700.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/53c700.h     2007-07-08 19:32:17.000000000 -0400
+@@ -177,7 +177,6 @@
+       __u8    state;
+       #define NCR_700_FLAG_AUTOSENSE  0x01
+       __u8    flags;
+-      __u8    pad1[2];        /* Needed for m68k where min alignment is 2 bytes */
+       int     tag;
+       __u32   resume_offset;
+       struct scsi_cmnd *cmnd;
+@@ -197,8 +196,6 @@
+       void __iomem    *base;          /* the base for the port (copied to host) */
+       struct device   *dev;
+       __u32   dmode_extra;    /* adjustable bus settings */
+-      __u32   dcntl_extra;    /* adjustable bus settings */
+-      __u32   ctest7_extra;   /* adjustable bus settings */
+       __u32   differential:1; /* if we are differential */
+ #ifdef CONFIG_53C700_LE_ON_BE
+       /* This option is for HP only.  Set it if your chip is wired for
+@@ -355,7 +352,6 @@
+ #define               SEL_TIMEOUT_DISABLE     0x10 /* 710 only */
+ #define         DFP                     0x08
+ #define         EVP                     0x04
+-#define         CTEST7_TT1              0x02
+ #define               DIFF                    0x01
+ #define CTEST6_REG                      0x1A
+ #define       TEMP_REG                        0x1C
+@@ -389,7 +385,6 @@
+ #define               SOFTWARE_RESET          0x01
+ #define               COMPAT_700_MODE         0x01
+ #define       SCRPTS_16BITS           0x20
+-#define               EA_710                  0x20
+ #define               ASYNC_DIV_2_0           0x00
+ #define               ASYNC_DIV_1_5           0x40
+ #define               ASYNC_DIV_1_0           0x80
+diff -Nurb linux-2.6.22-590/drivers/scsi/53c7xx.c linux-2.6.22-570/drivers/scsi/53c7xx.c
+--- linux-2.6.22-590/drivers/scsi/53c7xx.c     1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/53c7xx.c     2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,6102 @@
++/*
++ * 53c710 driver.  Modified from Drew Eckhardts driver
++ * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
++ * Check out PERM_OPTIONS and EXPECTED_CLOCK, which may be defined in the
++ * relevant machine specific file (eg. mvme16x.[ch], amiga7xx.[ch]).
++ * There are also currently some defines at the top of 53c7xx.scr.
++ * The chip type is #defined in script_asm.pl, as well as the Makefile.
++ * Host scsi ID expected to be 7 - see NCR53c7x0_init().
++ *
++ * I have removed the PCI code and some of the 53c8xx specific code - 
++ * simply to make this file smaller and easier to manage.
++ *
++ * MVME16x issues:
++ *   Problems trying to read any chip registers in NCR53c7x0_init(), as they
++ *   may never have been set by 16xBug (eg. If kernel has come in over tftp).
++ */
++
++/*
++ * Adapted for Linux/m68k Amiga platforms for the A4000T/A4091 and
++ * WarpEngine SCSI controllers.
++ * By Alan Hourihane <alanh@fairlite.demon.co.uk>
++ * Thanks to Richard Hirst for making it possible with the MVME additions
++ */
++
++/*
++ * 53c710 rev 0 doesn't support add with carry.  Rev 1 and 2 does.  To
++ * overcome this problem you can define FORCE_DSA_ALIGNMENT, which ensures
++ * that the DSA address is always xxxxxx00.  If disconnection is not allowed,
++ * then the script only ever tries to add small (< 256) positive offsets to
++ * DSA, so lack of carry isn't a problem.  FORCE_DSA_ALIGNMENT can, of course,
++ * be defined for all chip revisions at a small cost in memory usage.
++ */
++
++#define FORCE_DSA_ALIGNMENT
++
++/*
++ * Selection timer does not always work on the 53c710, depending on the
++ * timing at the last disconnect, if this is a problem for you, try
++ * using validids as detailed below.
++ *
++ * Options for the NCR7xx driver
++ *
++ * noasync:0          -       disables sync and asynchronous negotiation
++ * nosync:0           -       disables synchronous negotiation (does async)
++ * nodisconnect:0     -       disables disconnection
++ * validids:0x??      -       Bitmask field that disallows certain ID's.
++ *                    -       e.g.    0x03    allows ID 0,1
++ *                    -               0x1F    allows ID 0,1,2,3,4
++ * opthi:n            -       replace top word of options with 'n'
++ * optlo:n            -       replace bottom word of options with 'n'
++ *                    -       ALWAYS SPECIFY opthi THEN optlo <<<<<<<<<<
++ */
++
++/*
++ * PERM_OPTIONS are driver options which will be enabled for all NCR boards
++ * in the system at driver initialization time.
++ *
++ * Don't THINK about touching these in PERM_OPTIONS : 
++ *   OPTION_MEMORY_MAPPED 
++ *    680x0 doesn't have an IO map!
++ *
++ *   OPTION_DEBUG_TEST1
++ *    Test 1 does bus mastering and interrupt tests, which will help weed 
++ *    out brain damaged main boards.
++ *
++ * Other PERM_OPTIONS settings are listed below.  Note the actual options
++ * required are set in the relevant file (mvme16x.c, amiga7xx.c, etc):
++ *
++ *   OPTION_NO_ASYNC
++ *    Don't negotiate for asynchronous transfers on the first command 
++ *    when OPTION_ALWAYS_SYNCHRONOUS is set.  Useful for dain bramaged
++ *    devices which do something bad rather than sending a MESSAGE 
++ *    REJECT back to us like they should if they can't cope.
++ *
++ *   OPTION_SYNCHRONOUS
++ *    Enable support for synchronous transfers.  Target negotiated 
++ *    synchronous transfers will be responded to.  To initiate 
++ *    a synchronous transfer request,  call 
++ *
++ *        request_synchronous (hostno, target) 
++ *
++ *    from within KGDB.
++ *
++ *   OPTION_ALWAYS_SYNCHRONOUS
++ *    Negotiate for synchronous transfers with every target after
++ *    driver initialization or a SCSI bus reset.  This is a bit dangerous, 
++ *    since there are some dain bramaged SCSI devices which will accept
++ *    SDTR messages but keep talking asynchronously.
++ *
++ *   OPTION_DISCONNECT
++ *    Enable support for disconnect/reconnect.  To change the 
++ *    default setting on a given host adapter, call
++ *
++ *        request_disconnect (hostno, allow)
++ *
++ *    where allow is non-zero to allow, 0 to disallow.
++ * 
++ *  If you really want to run 10MHz FAST SCSI-II transfers, you should 
++ *  know that the NCR driver currently ignores parity information.  Most
++ *  systems do 5MHz SCSI fine.  I've seen a lot that have problems faster
++ *  than 8MHz.  To play it safe, we only request 5MHz transfers.
++ *
++ *  If you'd rather get 10MHz transfers, edit sdtr_message and change 
++ *  the fourth byte from 50 to 25.
++ */
++
++/*
++ * Sponsored by 
++ *    iX Multiuser Multitasking Magazine
++ *    Hannover, Germany
++ *    hm@ix.de
++ *
++ * Copyright 1993, 1994, 1995 Drew Eckhardt
++ *      Visionary Computing 
++ *      (Unix and Linux consulting and custom programming)
++ *      drew@PoohSticks.ORG
++ *    +1 (303) 786-7975
++ *
++ * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
++ * 
++ * For more information, please consult 
++ *
++ * NCR53C810 
++ * SCSI I/O Processor
++ * Programmer's Guide
++ *
++ * NCR 53C810
++ * PCI-SCSI I/O Processor
++ * Data Manual
++ *
++ * NCR 53C810/53C820
++ * PCI-SCSI I/O Processor Design In Guide
++ *
++ * For literature on Symbios Logic Inc. formerly NCR, SCSI, 
++ * and Communication products please call (800) 334-5454 or
++ * (719) 536-3300. 
++ * 
++ * PCI BIOS Specification Revision
++ * PCI Local Bus Specification
++ * PCI System Design Guide
++ *
++ * PCI Special Interest Group
++ * M/S HF3-15A
++ * 5200 N.E. Elam Young Parkway
++ * Hillsboro, Oregon 97124-6497
++ * +1 (503) 696-2000 
++ * +1 (800) 433-5177
++ */
++
++/*
++ * Design issues : 
++ * The cumulative latency needed to propagate a read/write request 
++ * through the file system, buffer cache, driver stacks, SCSI host, and 
++ * SCSI device is ultimately the limiting factor in throughput once we 
++ * have a sufficiently fast host adapter.
++ *  
++ * So, to maximize performance we want to keep the ratio of latency to data 
++ * transfer time to a minimum by
++ * 1.  Minimizing the total number of commands sent (typical command latency
++ *    including drive and bus mastering host overhead is as high as 4.5ms)
++ *    to transfer a given amount of data.  
++ *
++ *      This is accomplished by placing no arbitrary limit on the number
++ *    of scatter/gather buffers supported, since we can transfer 1K
++ *    per scatter/gather buffer without Eric's cluster patches, 
++ *    4K with.  
++ *
++ * 2.  Minimizing the number of fatal interrupts serviced, since
++ *    fatal interrupts halt the SCSI I/O processor.  Basically,
++ *    this means offloading the practical maximum amount of processing 
++ *    to the SCSI chip.
++ * 
++ *    On the NCR53c810/820/720,  this is accomplished by using 
++ *            interrupt-on-the-fly signals when commands complete, 
++ *            and only handling fatal errors and SDTR / WDTR  messages 
++ *            in the host code.
++ *
++ *    On the NCR53c710, interrupts are generated as on the NCR53c8x0,
++ *            only the lack of a interrupt-on-the-fly facility complicates
++ *            things.   Also, SCSI ID registers and commands are 
++ *            bit fielded rather than binary encoded.
++ *            
++ *    On the NCR53c700 and NCR53c700-66, operations that are done via 
++ *            indirect, table mode on the more advanced chips must be
++ *            replaced by calls through a jump table which 
++ *            acts as a surrogate for the DSA.  Unfortunately, this 
++ *            will mean that we must service an interrupt for each 
++ *            disconnect/reconnect.
++ * 
++ * 3.  Eliminating latency by pipelining operations at the different levels.
++ *    
++ *    This driver allows a configurable number of commands to be enqueued
++ *    for each target/lun combination (experimentally, I have discovered
++ *    that two seems to work best) and will ultimately allow for 
++ *    SCSI-II tagged queuing.
++ *    
++ *
++ * Architecture : 
++ * This driver is built around a Linux queue of commands waiting to 
++ * be executed, and a shared Linux/NCR array of commands to start.  Commands
++ * are transferred to the array  by the run_process_issue_queue() function 
++ * which is called whenever a command completes.
++ *
++ * As commands are completed, the interrupt routine is triggered,
++ * looks for commands in the linked list of completed commands with
++ * valid status, removes these commands from a list of running commands, 
++ * calls the done routine, and flags their target/luns as not busy.
++ *
++ * Due to limitations in the intelligence of the NCR chips, certain
++ * concessions are made.  In many cases, it is easier to dynamically 
++ * generate/fix-up code rather than calculate on the NCR at run time.  
++ * So, code is generated or fixed up for
++ *
++ * - Handling data transfers, using a variable number of MOVE instructions
++ *    interspersed with CALL MSG_IN, WHEN MSGIN instructions.
++ *
++ *    The DATAIN and DATAOUT routines are separate, so that an incorrect
++ *    direction can be trapped, and space isn't wasted. 
++ *
++ *    It may turn out that we're better off using some sort 
++ *    of table indirect instruction in a loop with a variable
++ *    sized table on the NCR53c710 and newer chips.
++ *
++ * - Checking for reselection (NCR53c710 and better)
++ *
++ * - Handling the details of SCSI context switches (NCR53c710 and better),
++ *    such as reprogramming appropriate synchronous parameters, 
++ *    removing the dsa structure from the NCR's queue of outstanding
++ *    commands, etc.
++ *
++ */
++
++#include <linux/module.h>
++
++
++#include <linux/types.h>
++#include <asm/setup.h>
++#include <asm/dma.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <linux/delay.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/mm.h>
++#include <linux/ioport.h>
++#include <linux/time.h>
++#include <linux/blkdev.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++#include <asm/pgtable.h>
++
++#ifdef CONFIG_AMIGA
++#include <asm/amigahw.h>
++#include <asm/amigaints.h>
++#include <asm/irq.h>
++
++#define BIG_ENDIAN
++#define NO_IO_SPACE
++#endif
++
++#ifdef CONFIG_MVME16x
++#include <asm/mvme16xhw.h>
++
++#define BIG_ENDIAN
++#define NO_IO_SPACE
++#define VALID_IDS
++#endif
++
++#ifdef CONFIG_BVME6000
++#include <asm/bvme6000hw.h>
++
++#define BIG_ENDIAN
++#define NO_IO_SPACE
++#define VALID_IDS
++#endif
++
++#include "scsi.h"
++#include <scsi/scsi_dbg.h>
++#include <scsi/scsi_host.h>
++#include <scsi/scsi_transport_spi.h>
++#include "53c7xx.h"
++#include <linux/stat.h>
++#include <linux/stddef.h>
++
++#ifdef NO_IO_SPACE
++/*
++ * The following make the definitions in 53c7xx.h (write8, etc) smaller,
++ * we don't have separate i/o space anyway.
++ */
++#undef inb
++#undef outb
++#undef inw
++#undef outw
++#undef inl
++#undef outl
++#define inb(x)          1
++#define inw(x)          1
++#define inl(x)          1
++#define outb(x,y)       1
++#define outw(x,y)       1
++#define outl(x,y)       1
++#endif
++
++static int check_address (unsigned long addr, int size);
++static void dump_events (struct Scsi_Host *host, int count);
++static Scsi_Cmnd * return_outstanding_commands (struct Scsi_Host *host, 
++    int free, int issue);
++static void hard_reset (struct Scsi_Host *host);
++static void ncr_scsi_reset (struct Scsi_Host *host);
++static void print_lots (struct Scsi_Host *host);
++static void set_synchronous (struct Scsi_Host *host, int target, int sxfer, 
++    int scntl3, int now_connected);
++static int datapath_residual (struct Scsi_Host *host);
++static const char * sbcl_to_phase (int sbcl);
++static void print_progress (Scsi_Cmnd *cmd);
++static void print_queues (struct Scsi_Host *host);
++static void process_issue_queue (unsigned long flags);
++static int shutdown (struct Scsi_Host *host);
++static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result);
++static int disable (struct Scsi_Host *host);
++static int NCR53c7xx_run_tests (struct Scsi_Host *host);
++static irqreturn_t NCR53c7x0_intr(int irq, void *dev_id);
++static void NCR53c7x0_intfly (struct Scsi_Host *host);
++static int ncr_halt (struct Scsi_Host *host);
++static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd 
++    *cmd);
++static void intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);
++static void print_dsa (struct Scsi_Host *host, u32 *dsa,
++    const char *prefix);
++static int print_insn (struct Scsi_Host *host, const u32 *insn,
++    const char *prefix, int kernel);
++
++static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd);
++static void NCR53c7x0_init_fixup (struct Scsi_Host *host);
++static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct 
++    NCR53c7x0_cmd *cmd);
++static void NCR53c7x0_soft_reset (struct Scsi_Host *host);
++
++/* Size of event list (per host adapter) */
++static int track_events = 0;
++static struct Scsi_Host *first_host = NULL;   /* Head of list of NCR boards */
++static struct scsi_host_template *the_template = NULL;
++
++/* NCR53c710 script handling code */
++
++#include "53c7xx_d.h"
++#ifdef A_int_debug_sync
++#define DEBUG_SYNC_INTR A_int_debug_sync
++#endif
++int NCR53c7xx_script_len = sizeof (SCRIPT);
++int NCR53c7xx_dsa_len = A_dsa_end + Ent_dsa_zero - Ent_dsa_code_template;
++#ifdef FORCE_DSA_ALIGNMENT
++int CmdPageStart = (0 - Ent_dsa_zero - sizeof(struct NCR53c7x0_cmd)) & 0xff;
++#endif
++
++static char *setup_strings[] =
++      {"","","","","","","",""};
++
++#define MAX_SETUP_STRINGS ARRAY_SIZE(setup_strings)
++#define SETUP_BUFFER_SIZE 200
++static char setup_buffer[SETUP_BUFFER_SIZE];
++static char setup_used[MAX_SETUP_STRINGS];
++
++void ncr53c7xx_setup (char *str, int *ints)
++{
++   int i;
++   char *p1, *p2;
++
++   p1 = setup_buffer;
++   *p1 = '\0';
++   if (str)
++      strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));
++   setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
++   p1 = setup_buffer;
++   i = 0;
++   while (*p1 && (i < MAX_SETUP_STRINGS)) {
++      p2 = strchr(p1, ',');
++      if (p2) {
++         *p2 = '\0';
++         if (p1 != p2)
++            setup_strings[i] = p1;
++         p1 = p2 + 1;
++         i++;
++         }
++      else {
++         setup_strings[i] = p1;
++         break;
++         }
++      }
++   for (i=0; i<MAX_SETUP_STRINGS; i++)
++      setup_used[i] = 0;
++}
++
++
++/* check_setup_strings() returns index if key found, 0 if not
++ */
++
++static int check_setup_strings(char *key, int *flags, int *val, char *buf)
++{
++int x;
++char *cp;
++
++   for  (x=0; x<MAX_SETUP_STRINGS; x++) {
++      if (setup_used[x])
++         continue;
++      if (!strncmp(setup_strings[x], key, strlen(key)))
++         break;
++      if (!strncmp(setup_strings[x], "next", strlen("next")))
++         return 0;
++      }
++   if (x == MAX_SETUP_STRINGS)
++      return 0;
++   setup_used[x] = 1;
++   cp = setup_strings[x] + strlen(key);
++   *val = -1;
++   if (*cp != ':')
++      return ++x;
++   cp++;
++   if ((*cp >= '0') && (*cp <= '9')) {
++      *val = simple_strtoul(cp,NULL,0);
++      }
++   return ++x;
 +}
-+static int
-+lpfc_sli_hbq_entry_count(void)
++
++
++
++/*
++ * KNOWN BUGS :
++ * - There is some sort of conflict when the PPP driver is compiled with 
++ *    support for 16 channels?
++ * 
++ * - On systems which predate the 1.3.x initialization order change,
++ *      the NCR driver will cause Cannot get free page messages to appear.  
++ *      These are harmless, but I don't know of an easy way to avoid them.
++ *
++ * - With OPTION_DISCONNECT, on two systems under unknown circumstances,
++ *    we get a PHASE MISMATCH with DSA set to zero (suggests that we 
++ *    are occurring somewhere in the reselection code) where 
++ *    DSP=some value DCMD|DBC=same value.  
++ *    
++ *    Closer inspection suggests that we may be trying to execute
++ *    some portion of the DSA?
++ * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO)
++ * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO)
++ * scsi0 : no current command : unexpected phase MSGIN.
++ *         DSP=0x1c46cc, DCMD|DBC=0x1c46ac, DSA=0x0
++ *         DSPS=0x0, TEMP=0x1c3e70, DMODE=0x80
++ * scsi0 : DSP->
++ * 001c46cc : 0x001c46cc 0x00000000
++ * 001c46d4 : 0x001c5ea0 0x000011f8
++ *
++ *    Changed the print code in the phase_mismatch handler so
++ *    that we call print_lots to try to diagnose this.
++ *
++ */
++
++/* 
++ * Possible future direction of architecture for max performance :
++ *
++ * We're using a single start array for the NCR chip.  This is 
++ * sub-optimal, because we cannot add a command which would conflict with 
++ * an executing command to this start queue, and therefore must insert the 
++ * next command for a given I/T/L combination after the first has completed;
++ * incurring our interrupt latency between SCSI commands.
++ *
++ * To allow further pipelining of the NCR and host CPU operation, we want 
++ * to set things up so that immediately on termination of a command destined 
++ * for a given LUN, we get that LUN busy again.  
++ * 
++ * To do this, we need to add a 32 bit pointer to which is jumped to 
++ * on completion of a command.  If no new command is available, this 
++ * would point to the usual DSA issue queue select routine.
++ *
++ * If one were, it would point to a per-NCR53c7x0_cmd select routine 
++ * which starts execution immediately, inserting the command at the head 
++ * of the start queue if the NCR chip is selected or reselected.
++ *
++ * We would change so that we keep a list of outstanding commands 
++ * for each unit, rather than a single running_list.  We'd insert 
++ * a new command into the right running list; if the NCR didn't 
++ * have something running for that yet, we'd put it in the 
++ * start queue as well.  Some magic needs to happen to handle the 
++ * race condition between the first command terminating before the 
++ * new one is written.
++ *
++ * Potential for profiling : 
++ * Call do_gettimeofday(struct timeval *tv) to get 800ns resolution.
++ */
++
++
++/*
++ * TODO : 
++ * 1.  To support WIDE transfers, not much needs to happen.  We
++ *    should do CHMOVE instructions instead of MOVEs when
++ *    we have scatter/gather segments of uneven length.  When
++ *    we do this, we need to handle the case where we disconnect
++ *    between segments.
++ * 
++ * 2.  Currently, when Icky things happen we do a FATAL().  Instead,
++ *     we want to do an integrity check on the parts of the NCR hostdata
++ *     structure which were initialized at boot time; FATAL() if that 
++ *     fails, and otherwise try to recover.  Keep track of how many
++ *     times this has happened within a single SCSI command; if it 
++ *     gets excessive, then FATAL().
++ *
++ * 3.  Parity checking is currently disabled, and a few things should 
++ *     happen here now that we support synchronous SCSI transfers :
++ *     1.  On soft-reset, we shoould set the EPC (Enable Parity Checking)
++ *       and AAP (Assert SATN/ on parity error) bits in SCNTL0.
++ *    
++ *     2.  We should enable the parity interrupt in the SIEN0 register.
++ * 
++ *     3.  intr_phase_mismatch() needs to believe that message out is 
++ *       always an "acceptable" phase to have a mismatch in.  If 
++ *       the old phase was MSG_IN, we should send a MESSAGE PARITY 
++ *       error.  If the old phase was something else, we should send
++ *       a INITIATOR_DETECTED_ERROR message.  Note that this could
++ *       cause a RESTORE POINTERS message; so we should handle that 
++ *       correctly first.  Instead, we should probably do an 
++ *       initiator_abort.
++ *
++ * 4.  MPEE bit of CTEST4 should be set so we get interrupted if 
++ *     we detect an error.
++ *
++ *  
++ * 5.  The initial code has been tested on the NCR53c810.  I don't 
++ *     have access to NCR53c700, 700-66 (Forex boards), NCR53c710
++ *     (NCR Pentium systems), NCR53c720, NCR53c820, or NCR53c825 boards to 
++ *     finish development on those platforms.
++ *
++ *     NCR53c820/825/720 - need to add wide transfer support, including WDTR 
++ *                    negotiation, programming of wide transfer capabilities
++ *            on reselection and table indirect selection.
++ *
++ *     NCR53c710 - need to add fatal interrupt or GEN code for 
++ *            command completion signaling.   Need to modify all 
++ *            SDID, SCID, etc. registers, and table indirect select code 
++ *            since these use bit fielded (ie 1<<target) instead of 
++ *            binary encoded target ids.  Need to accommodate
++ *            different register mappings, probably scan through
++ *            the SCRIPT code and change the non SFBR register operand
++ *            of all MOVE instructions.
++ *
++ *            It is rather worse than this actually, the 710 corrupts
++ *            both TEMP and DSA when you do a MOVE MEMORY.  This
++ *            screws you up all over the place.  MOVE MEMORY 4 with a
++ *            destination of DSA seems to work OK, which helps some.
++ *            Richard Hirst  richard@sleepie.demon.co.uk
++ * 
++ *     NCR53c700/700-66 - need to add code to refix addresses on 
++ *            every nexus change, eliminate all table indirect code,
++ *            very messy.
++ *
++ * 6.  The NCR53c7x0 series is very popular on other platforms that 
++ *     could be running Linux - ie, some high performance AMIGA SCSI 
++ *     boards use it.  
++ *    
++ *     So, I should include #ifdef'd code so that it is 
++ *     compatible with these systems.
++ *    
++ *     Specifically, the little Endian assumptions I made in my 
++ *     bit fields need to change, and if the NCR doesn't see memory
++ *     the right way, we need to provide options to reverse words
++ *     when the scripts are relocated.
++ *
++ * 7.  Use vremap() to access memory mapped boards.  
++ */
++
++/* 
++ * Allow for simultaneous existence of multiple SCSI scripts so we 
++ * can have a single driver binary for all of the family.
++ *
++ * - one for NCR53c700 and NCR53c700-66 chips (not yet supported)
++ * - one for rest (only the NCR53c810, 815, 820, and 825 are currently 
++ *    supported)
++ * 
++ * So that we only need two SCSI scripts, we need to modify things so
++ * that we fixup register accesses in READ/WRITE instructions, and 
++ * we'll also have to accommodate the bit vs. binary encoding of IDs
++ * with the 7xx chips.
++ */
++
++#define ROUNDUP(adr,type)     \
++  ((void *) (((long) (adr) + sizeof(type) - 1) & ~(sizeof(type) - 1)))
++
++
++/*
++ * Function: issue_to_cmd
++ *
++ * Purpose: convert jump instruction in issue array to NCR53c7x0_cmd
++ *    structure pointer.  
++ *
++ * Inputs; issue - pointer to start of NOP or JUMP instruction
++ *    in issue array.
++ *
++ * Returns: pointer to command on success; 0 if opcode is NOP.
++ */
++
++static inline struct NCR53c7x0_cmd *
++issue_to_cmd (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
++    u32 *issue)
 +{
-+      int  hbq_count = lpfc_sli_hbq_count();
-+      int  count = 0;
-+      int  i;
++    return (issue[0] != hostdata->NOP_insn) ? 
++    /* 
++     * If the IF TRUE bit is set, it's a JUMP instruction.  The
++     * operand is a bus pointer to the dsa_begin routine for this DSA.  The
++     * dsa field of the NCR53c7x0_cmd structure starts with the 
++     * DSA code template.  By converting to a virtual address,
++     * subtracting the code template size, and offset of the 
++     * dsa field, we end up with a pointer to the start of the 
++     * structure (alternatively, we could use the 
++     * dsa_cmnd field, an anachronism from when we weren't
++     * sure what the relationship between the NCR structures
++     * and host structures were going to be.
++     */
++      (struct NCR53c7x0_cmd *) ((char *) bus_to_virt (issue[1]) - 
++          (hostdata->E_dsa_code_begin - hostdata->E_dsa_code_template) -
++          offsetof(struct NCR53c7x0_cmd, dsa)) 
++    /* If the IF TRUE bit is not set, it's a NOP */
++      : NULL;
++}
++
++
++/* 
++ * FIXME: we should junk these, in favor of synchronous_want and 
++ * wide_want in the NCR53c7x0_hostdata structure.
++ */
++
++/* Template for "preferred" synchronous transfer parameters. */
++
++static const unsigned char sdtr_message[] = {
++#ifdef CONFIG_SCSI_NCR53C7xx_FAST
++    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 25 /* *4ns */, 8 /* off */
++#else
++    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 50 /* *4ns */, 8 /* off */ 
++#endif
++};
++
++/* Template to request asynchronous transfers */
++
++static const unsigned char async_message[] = {
++    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 0, 0 /* asynchronous */
++};
++
++/* Template for "preferred" WIDE transfer parameters */
++
++static const unsigned char wdtr_message[] = {
++    EXTENDED_MESSAGE, 2 /* length */, EXTENDED_WDTR, 1 /* 2^1 bytes */
++};
++
++#if 0
++/*
++ * Function : struct Scsi_Host *find_host (int host)
++ * 
++ * Purpose : KGDB support function which translates a host number 
++ *    to a host structure. 
++ *
++ * Inputs : host - number of SCSI host
++ *
++ * Returns : NULL on failure, pointer to host structure on success.
++ */
++
++static struct Scsi_Host *
++find_host (int host) {
++    struct Scsi_Host *h;
++    for (h = first_host; h && h->host_no != host; h = h->next);
++    if (!h) {
++      printk (KERN_ALERT "scsi%d not found\n", host);
++      return NULL;
++    } else if (h->hostt != the_template) {
++      printk (KERN_ALERT "scsi%d is not a NCR board\n", host);
++      return NULL;
++    }
++    return h;
++}
++
++#if 0
++/*
++ * Function : request_synchronous (int host, int target)
++ * 
++ * Purpose : KGDB interface which will allow us to negotiate for 
++ *    synchronous transfers.  This ill be replaced with a more 
++ *    integrated function; perhaps a new entry in the scsi_host 
++ *    structure, accessible via an ioctl() or perhaps /proc/scsi.
++ *
++ * Inputs : host - number of SCSI host; target - number of target.
++ *
++ * Returns : 0 when negotiation has been setup for next SCSI command,
++ *    -1 on failure.
++ */
++
++static int
++request_synchronous (int host, int target) {
++    struct Scsi_Host *h;
++    struct NCR53c7x0_hostdata *hostdata;
++    unsigned long flags;
++    if (target < 0) {
++      printk (KERN_ALERT "target %d is bogus\n", target);
++      return -1;
++    }
++    if (!(h = find_host (host)))
++      return -1;
++    else if (h->this_id == target) {
++      printk (KERN_ALERT "target %d is host ID\n", target);
++      return -1;
++    } 
++    else if (target >= h->max_id) {
++      printk (KERN_ALERT "target %d exceeds maximum of %d\n", target,
++          h->max_id);
++      return -1;
++    }
++    hostdata = (struct NCR53c7x0_hostdata *)h->hostdata[0];
++
++    local_irq_save(flags);
++    if (hostdata->initiate_sdtr & (1 << target)) {
++      local_irq_restore(flags);
++      printk (KERN_ALERT "target %d already doing SDTR\n", target);
++      return -1;
++    } 
++    hostdata->initiate_sdtr |= (1 << target);
++    local_irq_restore(flags);
++    return 0;
++}
++#endif
++
++/*
++ * Function : request_disconnect (int host, int on_or_off)
++ * 
++ * Purpose : KGDB support function, tells us to allow or disallow 
++ *    disconnections.
++ *
++ * Inputs : host - number of SCSI host; on_or_off - non-zero to allow,
++ *    zero to disallow.
++ *
++ * Returns : 0 on success, *  -1 on failure.
++ */
++
++static int 
++request_disconnect (int host, int on_or_off) {
++    struct Scsi_Host *h;
++    struct NCR53c7x0_hostdata *hostdata;
++    if (!(h = find_host (host)))
++      return -1;
++    hostdata = (struct NCR53c7x0_hostdata *) h->hostdata[0];
++    if (on_or_off) 
++      hostdata->options |= OPTION_DISCONNECT;
++    else
++      hostdata->options &= ~OPTION_DISCONNECT;
++    return 0;
++}
++#endif
++
++/*
++ * Function : static void NCR53c7x0_driver_init (struct Scsi_Host *host)
++ *
++ * Purpose : Initialize internal structures, as required on startup, or 
++ *    after a SCSI bus reset.
++ * 
++ * Inputs : host - pointer to this host adapter's structure
++ */
++
++static void 
++NCR53c7x0_driver_init (struct Scsi_Host *host) {
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    int i, j;
++    u32 *ncrcurrent;
++
++    for (i = 0; i < 16; ++i) {
++      hostdata->request_sense[i] = 0;
++      for (j = 0; j < 8; ++j) 
++          hostdata->busy[i][j] = 0;
++      set_synchronous (host, i, /* sxfer */ 0, hostdata->saved_scntl3, 0);
++    }
++    hostdata->issue_queue = NULL;
++    hostdata->running_list = hostdata->finished_queue = 
++      hostdata->ncrcurrent = NULL;
++    for (i = 0, ncrcurrent = (u32 *) hostdata->schedule; 
++      i < host->can_queue; ++i, ncrcurrent += 2) {
++      ncrcurrent[0] = hostdata->NOP_insn;
++      ncrcurrent[1] = 0xdeadbeef;
++    }
++    ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) | DBC_TCI_TRUE;
++    ncrcurrent[1] = (u32) virt_to_bus (hostdata->script) +
++      hostdata->E_wait_reselect;
++    hostdata->reconnect_dsa_head = 0;
++    hostdata->addr_reconnect_dsa_head = (u32) 
++      virt_to_bus((void *) &(hostdata->reconnect_dsa_head));
++    hostdata->expecting_iid = 0;
++    hostdata->expecting_sto = 0;
++    if (hostdata->options & OPTION_ALWAYS_SYNCHRONOUS) 
++      hostdata->initiate_sdtr = 0xffff; 
++    else
++      hostdata->initiate_sdtr = 0;
++    hostdata->talked_to = 0;
++    hostdata->idle = 1;
++}
++
++/* 
++ * Function : static int clock_to_ccf_710 (int clock)
++ *
++ * Purpose :  Return the clock conversion factor for a given SCSI clock.
++ *
++ * Inputs : clock - SCSI clock expressed in Hz.
++ *
++ * Returns : ccf on success, -1 on failure.
++ */
++
++static int 
++clock_to_ccf_710 (int clock) {
++    if (clock <= 16666666)
++      return -1;
++    if (clock <= 25000000)
++      return 2;       /* Divide by 1.0 */
++    else if (clock <= 37500000)
++      return 1;       /* Divide by 1.5 */
++    else if (clock <= 50000000)
++      return 0;       /* Divide by 2.0 */
++    else if (clock <= 66000000)
++      return 3;       /* Divide by 3.0 */
++    else 
++      return -1;
++}
++    
++/* 
++ * Function : static int NCR53c7x0_init (struct Scsi_Host *host)
++ *
++ * Purpose :  initialize the internal structures for a given SCSI host
++ *
++ * Inputs : host - pointer to this host adapter's structure
++ *
++ * Preconditions : when this function is called, the chip_type 
++ *    field of the hostdata structure MUST have been set.
++ *
++ * Returns : 0 on success, -1 on failure.
++ */
++
++int 
++NCR53c7x0_init (struct Scsi_Host *host) {
++    NCR53c7x0_local_declare();
++    int i, ccf;
++    unsigned char revision;
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    /* 
++     * There are some things which we need to know about in order to provide
++     * a semblance of support.  Print 'em if they aren't what we expect, 
++     * otherwise don't add to the noise.
++     * 
++     * -1 means we don't know what to expect.
++     */
++    int val, flags;
++    char buf[32];
++    int expected_id = -1;
++    int expected_clock = -1;
++    int uninitialized = 0;
++#ifdef NO_IO_SPACE
++    int expected_mapping = OPTION_MEMORY_MAPPED;
++#else
++    int expected_mapping = OPTION_IO_MAPPED;
++#endif
++    for (i=0;i<7;i++)
++      hostdata->valid_ids[i] = 1;     /* Default all ID's to scan */
++
++    /* Parse commandline flags */
++    if (check_setup_strings("noasync",&flags,&val,buf))
++    {
++      hostdata->options |= OPTION_NO_ASYNC;
++      hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS);
++    }
++
++    if (check_setup_strings("nosync",&flags,&val,buf))
++    {
++      hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS);
++    }
++
++    if (check_setup_strings("nodisconnect",&flags,&val,buf))
++      hostdata->options &= ~OPTION_DISCONNECT;
++
++    if (check_setup_strings("validids",&flags,&val,buf))
++    {
++      for (i=0;i<7;i++) 
++              hostdata->valid_ids[i] = val & (1<<i);
++    }
++ 
++    if  ((i = check_setup_strings("next",&flags,&val,buf)))
++    {
++      while (i)
++              setup_used[--i] = 1;
++    }
++
++    if (check_setup_strings("opthi",&flags,&val,buf))
++      hostdata->options = (long long)val << 32;
++    if (check_setup_strings("optlo",&flags,&val,buf))
++      hostdata->options |= val;
++
++    NCR53c7x0_local_setup(host);
++    switch (hostdata->chip) {
++    case 710:
++    case 770:
++      hostdata->dstat_sir_intr = NCR53c7x0_dstat_sir_intr;
++      hostdata->init_save_regs = NULL;
++      hostdata->dsa_fixup = NCR53c7xx_dsa_fixup;
++      hostdata->init_fixup = NCR53c7x0_init_fixup;
++      hostdata->soft_reset = NCR53c7x0_soft_reset;
++      hostdata->run_tests = NCR53c7xx_run_tests;
++      expected_clock = hostdata->scsi_clock;
++      expected_id = 7;
++      break;
++    default:
++      printk ("scsi%d : chip type of %d is not supported yet, detaching.\n",
++          host->host_no, hostdata->chip);
++      scsi_unregister (host);
++      return -1;
++    }
 +
-+      for (i = 0; i < hbq_count; ++i)
-+              count += lpfc_hbq_defs[i]->entry_count;
-+      return count;
++    /* Assign constants accessed by NCR */
++    hostdata->NCR53c7xx_zero = 0;                     
++    hostdata->NCR53c7xx_msg_reject = MESSAGE_REJECT;
++    hostdata->NCR53c7xx_msg_abort = ABORT;
++    hostdata->NCR53c7xx_msg_nop = NOP;
++    hostdata->NOP_insn = (DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24;
++    if (expected_mapping == -1 || 
++      (hostdata->options & (OPTION_MEMORY_MAPPED)) != 
++      (expected_mapping & OPTION_MEMORY_MAPPED))
++      printk ("scsi%d : using %s mapped access\n", host->host_no, 
++          (hostdata->options & OPTION_MEMORY_MAPPED) ? "memory" : 
++          "io");
++
++    hostdata->dmode = (hostdata->chip == 700 || hostdata->chip == 70066) ? 
++      DMODE_REG_00 : DMODE_REG_10;
++    hostdata->istat = ((hostdata->chip / 100) == 8) ? 
++      ISTAT_REG_800 : ISTAT_REG_700;
++
++/* We have to assume that this may be the first access to the chip, so
++ * we must set EA in DCNTL. */
++
++    NCR53c7x0_write8 (DCNTL_REG, DCNTL_10_EA|DCNTL_10_COM);
++
++
++/* Only the ISTAT register is readable when the NCR is running, so make 
++   sure it's halted. */
++    ncr_halt(host);
++
++/* 
++ * XXX - the NCR53c700 uses bitfielded registers for SCID, SDID, etc,
++ *    as does the 710 with one bit per SCSI ID.  Conversely, the NCR
++ *    uses a normal, 3 bit binary representation of these values.
++ *
++ * Get the rest of the NCR documentation, and FIND OUT where the change
++ * was.
++ */
++
++#if 0
++      /* May not be able to do this - chip my not have been set up yet */
++      tmp = hostdata->this_id_mask = NCR53c7x0_read8(SCID_REG);
++      for (host->this_id = 0; tmp != 1; tmp >>=1, ++host->this_id);
++#else
++      host->this_id = 7;
++#endif
++
++/*
++ * Note : we should never encounter a board setup for ID0.  So,
++ *    if we see ID0, assume that it was uninitialized and set it
++ *    to the industry standard 7.
++ */
++    if (!host->this_id) {
++      printk("scsi%d : initiator ID was %d, changing to 7\n",
++          host->host_no, host->this_id);
++      host->this_id = 7;
++      hostdata->this_id_mask = 1 << 7;
++      uninitialized = 1;
++    };
++
++    if (expected_id == -1 || host->this_id != expected_id)
++      printk("scsi%d : using initiator ID %d\n", host->host_no,
++          host->this_id);
++
++    /*
++     * Save important registers to allow a soft reset.
++     */
++
++    /*
++     * CTEST7 controls cache snooping, burst mode, and support for 
++     * external differential drivers.  This isn't currently used - the
++     * default value may not be optimal anyway.
++     * Even worse, it may never have been set up since reset.
++     */
++    hostdata->saved_ctest7 = NCR53c7x0_read8(CTEST7_REG) & CTEST7_SAVE;
++    revision = (NCR53c7x0_read8(CTEST8_REG) & 0xF0) >> 4;
++    switch (revision) {
++      case 1: revision = 0;    break;
++      case 2: revision = 1;    break;
++      case 4: revision = 2;    break;
++      case 8: revision = 3;    break;
++      default: revision = 255; break;
++    }
++    printk("scsi%d: Revision 0x%x\n",host->host_no,revision);
++
++    if ((revision == 0 || revision == 255) && (hostdata->options & (OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS)))
++    {
++      printk ("scsi%d: Disabling sync working and disconnect/reselect\n",
++                                                      host->host_no);
++      hostdata->options &= ~(OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS);
++    }
++
++    /*
++     * On NCR53c700 series chips, DCNTL controls the SCSI clock divisor,
++     * on 800 series chips, it allows for a totem-pole IRQ driver.
++     * NOTE saved_dcntl currently overwritten in init function.
++     * The value read here may be garbage anyway, MVME16x board at least
++     * does not initialise chip if kernel arrived via tftp.
++     */
++
++    hostdata->saved_dcntl = NCR53c7x0_read8(DCNTL_REG);
++
++    /*
++     * DMODE controls DMA burst length, and on 700 series chips,
++     * 286 mode and bus width  
++     * NOTE:  On MVME16x, chip may have been reset, so this could be a
++     * power-on/reset default value.
++     */
++    hostdata->saved_dmode = NCR53c7x0_read8(hostdata->dmode);
++
++    /* 
++     * Now that burst length and enabled/disabled status is known, 
++     * clue the user in on it.  
++     */
++   
++    ccf = clock_to_ccf_710 (expected_clock);
++
++    for (i = 0; i < 16; ++i) 
++      hostdata->cmd_allocated[i] = 0;
++
++    if (hostdata->init_save_regs)
++      hostdata->init_save_regs (host);
++    if (hostdata->init_fixup)
++      hostdata->init_fixup (host);
++
++    if (!the_template) {
++      the_template = host->hostt;
++      first_host = host;
++    }
++
++    /* 
++     * Linux SCSI drivers have always been plagued with initialization 
++     * problems - some didn't work with the BIOS disabled since they expected
++     * initialization from it, some didn't work when the networking code
++     * was enabled and registers got scrambled, etc.
++     *
++     * To avoid problems like this, in the future, we will do a soft 
++     * reset on the SCSI chip, taking it back to a sane state.
++     */
++
++    hostdata->soft_reset (host);
++
++#if 1
++    hostdata->debug_count_limit = -1;
++#else
++    hostdata->debug_count_limit = 1;
++#endif
++    hostdata->intrs = -1;
++    hostdata->resets = -1;
++    memcpy ((void *) hostdata->synchronous_want, (void *) sdtr_message, 
++      sizeof (hostdata->synchronous_want));
++
++    NCR53c7x0_driver_init (host);
++
++    if (request_irq(host->irq, NCR53c7x0_intr, IRQF_SHARED, "53c7xx", host))
++    {
++      printk("scsi%d : IRQ%d not free, detaching\n",
++              host->host_no, host->irq);
++      goto err_unregister;
++    } 
++
++    if ((hostdata->run_tests && hostdata->run_tests(host) == -1) ||
++        (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) {
++      /* XXX Should disable interrupts, etc. here */
++      goto err_free_irq;
++    } else {
++      if (host->io_port)  {
++          host->n_io_port = 128;
++          if (!request_region (host->io_port, host->n_io_port, "ncr53c7xx"))
++              goto err_free_irq;
++      }
++    }
++    
++    if (NCR53c7x0_read8 (SBCL_REG) & SBCL_BSY) {
++      printk ("scsi%d : bus wedge, doing SCSI reset\n", host->host_no);
++      hard_reset (host);
++    }
++    return 0;
++
++ err_free_irq:
++    free_irq(host->irq,  NCR53c7x0_intr);
++ err_unregister:
++    scsi_unregister(host);
++    return -1;
 +}
 +
-+int
-+lpfc_sli_hbq_size(void)
-+{
-+      return lpfc_sli_hbq_entry_count() * sizeof(struct lpfc_hbq_entry);
++/* 
++ * Function : int ncr53c7xx_init(struct scsi_host_template *tpnt, int board, int chip,
++ *    unsigned long base, int io_port, int irq, int dma, long long options,
++ *    int clock);
++ *
++ * Purpose : initializes a NCR53c7,8x0 based on base addresses,
++ *    IRQ, and DMA channel.   
++ *    
++ * Inputs : tpnt - Template for this SCSI adapter, board - board level
++ *    product, chip - 710
++ * 
++ * Returns : 0 on success, -1 on failure.
++ *
++ */
++
++int 
++ncr53c7xx_init (struct scsi_host_template *tpnt, int board, int chip,
++    unsigned long base, int io_port, int irq, int dma, 
++    long long options, int clock)
++{
++    struct Scsi_Host *instance;
++    struct NCR53c7x0_hostdata *hostdata;
++    char chip_str[80];
++    int script_len = 0, dsa_len = 0, size = 0, max_cmd_size = 0,
++      schedule_size = 0, ok = 0;
++    void *tmp;
++    unsigned long page;
++
++    switch (chip) {
++    case 710:
++    case 770:
++      schedule_size = (tpnt->can_queue + 1) * 8 /* JUMP instruction size */;
++      script_len = NCR53c7xx_script_len;
++      dsa_len = NCR53c7xx_dsa_len;
++      options |= OPTION_INTFLY;
++      sprintf (chip_str, "NCR53c%d", chip);
++      break;
++    default:
++      printk("scsi-ncr53c7xx : unsupported SCSI chip %d\n", chip);
++      return -1;
++    }
++
++    printk("scsi-ncr53c7xx : %s at memory 0x%lx, io 0x%x, irq %d",
++      chip_str, base, io_port, irq);
++    if (dma == DMA_NONE)
++      printk("\n");
++    else 
++      printk(", dma %d\n", dma);
++
++    if (options & OPTION_DEBUG_PROBE_ONLY) {
++      printk ("scsi-ncr53c7xx : probe only enabled, aborting initialization\n");
++      return -1;
++    }
++
++    max_cmd_size = sizeof(struct NCR53c7x0_cmd) + dsa_len +
++      /* Size of dynamic part of command structure : */
++      2 * /* Worst case : we don't know if we need DATA IN or DATA out */
++              ( 2 * /* Current instructions per scatter/gather segment */ 
++                tpnt->sg_tablesize + 
++                  3 /* Current startup / termination required per phase */
++              ) *
++      8 /* Each instruction is eight bytes */;
++
++    /* Allocate fixed part of hostdata, dynamic part to hold appropriate
++       SCSI SCRIPT(tm) plus a single, maximum-sized NCR53c7x0_cmd structure.
++
++       We need a NCR53c7x0_cmd structure for scan_scsis() when we are 
++       not loaded as a module, and when we're loaded as a module, we 
++       can't use a non-dynamically allocated structure because modules
++       are vmalloc()'d, which can allow structures to cross page 
++       boundaries and breaks our physical/virtual address assumptions
++       for DMA.
++
++       So, we stick it past the end of our hostdata structure.
++
++       ASSUMPTION : 
++               Regardless of how many simultaneous SCSI commands we allow,
++       the probe code only executes a _single_ instruction at a time,
++       so we only need one here, and don't need to allocate NCR53c7x0_cmd
++       structures for each target until we are no longer in scan_scsis
++       and kmalloc() has become functional (memory_init() happens 
++       after all device driver initialization).
++    */
++
++    size = sizeof(struct NCR53c7x0_hostdata) + script_len + 
++    /* Note that alignment will be guaranteed, since we put the command
++       allocated at probe time after the fixed-up SCSI script, which 
++       consists of 32 bit words, aligned on a 32 bit boundary.  But
++       on a 64bit machine we need 8 byte alignment for hostdata->free, so
++       we add in another 4 bytes to take care of potential misalignment
++       */
++      (sizeof(void *) - sizeof(u32)) + max_cmd_size + schedule_size;
++
++    page = __get_free_pages(GFP_ATOMIC,1);
++    if(page==0)
++    {
++      printk(KERN_ERR "53c7xx: out of memory.\n");
++      return -ENOMEM;
++    }
++#ifdef FORCE_DSA_ALIGNMENT
++    /*
++     * 53c710 rev.0 doesn't have an add-with-carry instruction.
++     * Ensure we allocate enough memory to force DSA alignment.
++    */
++    size += 256;
++#endif
++    /* Size should be < 8K, so we can fit it in two pages. */
++    if (size > 8192) {
++      printk(KERN_ERR "53c7xx: hostdata > 8K\n");
++      return -1;
++    }
++
++    instance = scsi_register (tpnt, 4);
++    if (!instance)
++    {
++        free_page(page);
++      return -1;
++    }
++    instance->hostdata[0] = page;
++    memset((void *)instance->hostdata[0], 0, 8192);
++    cache_push(virt_to_phys((void *)(instance->hostdata[0])), 8192);
++    cache_clear(virt_to_phys((void *)(instance->hostdata[0])), 8192);
++    kernel_set_cachemode((void *)instance->hostdata[0], 8192, IOMAP_NOCACHE_SER);
++
++    /* FIXME : if we ever support an ISA NCR53c7xx based board, we
++       need to check if the chip is running in a 16 bit mode, and if so 
++       unregister it if it is past the 16M (0x1000000) mark */
++
++    hostdata = (struct NCR53c7x0_hostdata *)instance->hostdata[0];
++    hostdata->size = size;
++    hostdata->script_count = script_len / sizeof(u32);
++    hostdata->board = board;
++    hostdata->chip = chip;
++
++    /*
++     * Being memory mapped is more desirable, since 
++     *
++     * - Memory accesses may be faster.
++     *
++     * - The destination and source address spaces are the same for 
++     *         all instructions, meaning we don't have to twiddle dmode or 
++     *         any other registers.
++     *
++     * So, we try for memory mapped, and if we don't get it,
++     * we go for port mapped, and that failing we tell the user
++     * it can't work.
++     */
++
++    if (base) {
++      instance->base = base;
++      /* Check for forced I/O mapping */
++      if (!(options & OPTION_IO_MAPPED)) {
++          options |= OPTION_MEMORY_MAPPED;
++          ok = 1;
++      }
++    } else {
++      options &= ~OPTION_MEMORY_MAPPED;
++    }
++
++    if (io_port) {
++      instance->io_port = io_port;
++      options |= OPTION_IO_MAPPED;
++      ok = 1;
++    } else {
++      options &= ~OPTION_IO_MAPPED;
++    }
++
++    if (!ok) {
++      printk ("scsi%d : not initializing, no I/O or memory mapping known \n",
++          instance->host_no);
++      scsi_unregister (instance);
++      return -1;
++    }
++    instance->irq = irq;
++    instance->dma_channel = dma;
++
++    hostdata->options = options;
++    hostdata->dsa_len = dsa_len;
++    hostdata->max_cmd_size = max_cmd_size;
++    hostdata->num_cmds = 1;
++    hostdata->scsi_clock = clock;
++    /* Initialize single command */
++    tmp = (hostdata->script + hostdata->script_count);
++#ifdef FORCE_DSA_ALIGNMENT
++    {
++      void *t = ROUNDUP(tmp, void *);
++      if (((u32)t & 0xff) > CmdPageStart)
++          t = (void *)((u32)t + 255);
++      t = (void *)(((u32)t & ~0xff) + CmdPageStart);
++        hostdata->free = t;
++#if 0
++      printk ("scsi: Registered size increased by 256 to %d\n", size);
++      printk ("scsi: CmdPageStart = 0x%02x\n", CmdPageStart);
++      printk ("scsi: tmp = 0x%08x, hostdata->free set to 0x%08x\n",
++                      (u32)tmp, (u32)t);
++#endif
++    }
++#else
++    hostdata->free = ROUNDUP(tmp, void *);
++#endif
++    hostdata->free->real = tmp;
++    hostdata->free->size = max_cmd_size;
++    hostdata->free->free = NULL;
++    hostdata->free->next = NULL;
++    hostdata->extra_allocate = 0;
++
++    /* Allocate command start code space */
++    hostdata->schedule = (chip == 700 || chip == 70066) ?
++      NULL : (u32 *) ((char *)hostdata->free + max_cmd_size);
++
++/* 
++ * For diagnostic purposes, we don't really care how fast things blaze.
++ * For profiling, we want to access the 800ns resolution system clock,
++ * using a 'C' call on the host processor.
++ *
++ * Therefore, there's no need for the NCR chip to directly manipulate
++ * this data, and we should put it wherever is most convenient for 
++ * Linux.
++ */
++    if (track_events) 
++      hostdata->events = (struct NCR53c7x0_event *) (track_events ? 
++          vmalloc (sizeof (struct NCR53c7x0_event) * track_events) : NULL);
++    else
++      hostdata->events = NULL;
++
++    if (hostdata->events) {
++      memset ((void *) hostdata->events, 0, sizeof(struct NCR53c7x0_event) *
++          track_events);      
++      hostdata->event_size = track_events;
++      hostdata->event_index = 0;
++    } else 
++      hostdata->event_size = 0;
++
++    return NCR53c7x0_init(instance);
 +}
 +
-+static int
-+lpfc_sli_hbq_setup(struct lpfc_hba *phba)
-+{
-+      int  hbq_count = lpfc_sli_hbq_count();
-+      LPFC_MBOXQ_t *pmb;
-+      MAILBOX_t *pmbox;
-+      uint32_t hbqno;
-+      uint32_t hbq_entry_index;
 +
-+                              /* Get a Mailbox buffer to setup mailbox
-+                               * commands for HBA initialization
-+                               */
-+      pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
++/* 
++ * Function : static void NCR53c7x0_init_fixup (struct Scsi_Host *host)
++ *
++ * Purpose :  copy and fixup the SCSI SCRIPTS(tm) code for this device.
++ *
++ * Inputs : host - pointer to this host adapter's structure
++ *
++ */
++
++static void 
++NCR53c7x0_init_fixup (struct Scsi_Host *host) {
++    NCR53c7x0_local_declare();
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    unsigned char tmp;
++    int i, ncr_to_memory, memory_to_ncr;
++    u32 base;
++    NCR53c7x0_local_setup(host);
++
++
++    /* XXX - NOTE : this code MUST be made endian aware */
++    /*  Copy code into buffer that was allocated at detection time.  */
++    memcpy ((void *) hostdata->script, (void *) SCRIPT, 
++      sizeof(SCRIPT));
++    /* Fixup labels */
++    for (i = 0; i < PATCHES; ++i) 
++      hostdata->script[LABELPATCHES[i]] += 
++          virt_to_bus(hostdata->script);
++    /* Fixup addresses of constants that used to be EXTERNAL */
++
++    patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_abort, 
++      virt_to_bus(&(hostdata->NCR53c7xx_msg_abort)));
++    patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_reject, 
++      virt_to_bus(&(hostdata->NCR53c7xx_msg_reject)));
++    patch_abs_32 (hostdata->script, 0, NCR53c7xx_zero, 
++      virt_to_bus(&(hostdata->NCR53c7xx_zero)));
++    patch_abs_32 (hostdata->script, 0, NCR53c7xx_sink, 
++      virt_to_bus(&(hostdata->NCR53c7xx_sink)));
++    patch_abs_32 (hostdata->script, 0, NOP_insn,
++      virt_to_bus(&(hostdata->NOP_insn)));
++    patch_abs_32 (hostdata->script, 0, schedule,
++      virt_to_bus((void *) hostdata->schedule));
++
++    /* Fixup references to external variables: */
++    for (i = 0; i < EXTERNAL_PATCHES_LEN; ++i)
++       hostdata->script[EXTERNAL_PATCHES[i].offset] +=
++         virt_to_bus(EXTERNAL_PATCHES[i].address);
++
++    /* 
++     * Fixup absolutes set at boot-time.
++     * 
++     * All non-code absolute variables suffixed with "dsa_" and "int_"
++     * are constants, and need no fixup provided the assembler has done 
++     * it for us (I don't know what the "real" NCR assembler does in 
++     * this case, my assembler does the right magic).
++     */
++
++    patch_abs_rwri_data (hostdata->script, 0, dsa_save_data_pointer, 
++      Ent_dsa_code_save_data_pointer - Ent_dsa_zero);
++    patch_abs_rwri_data (hostdata->script, 0, dsa_restore_pointers,
++      Ent_dsa_code_restore_pointers - Ent_dsa_zero);
++    patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect,
++      Ent_dsa_code_check_reselect - Ent_dsa_zero);
++
++    /*
++     * Just for the hell of it, preserve the settings of 
++     * Burst Length and Enable Read Line bits from the DMODE 
++     * register.  Make sure SCRIPTS start automagically.
++     */
++
++#if defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)
++    /* We know better what we want than 16xBug does! */
++    tmp = DMODE_10_BL_8 | DMODE_10_FC2;
++#else
++    tmp = NCR53c7x0_read8(DMODE_REG_10);
++    tmp &= (DMODE_BL_MASK | DMODE_10_FC2 | DMODE_10_FC1 | DMODE_710_PD |
++                                                              DMODE_710_UO);
++#endif
 +
-+      if (!pmb)
-+              return -ENOMEM;
++    if (!(hostdata->options & OPTION_MEMORY_MAPPED)) {
++      base = (u32) host->io_port;
++      memory_to_ncr = tmp|DMODE_800_DIOM;
++      ncr_to_memory = tmp|DMODE_800_SIOM;
++    } else {
++      base = virt_to_bus((void *)host->base);
++      memory_to_ncr = ncr_to_memory = tmp;
++    }
++
++    /* SCRATCHB_REG_10 == SCRATCHA_REG_800, as it happens */
++    patch_abs_32 (hostdata->script, 0, addr_scratch, base + SCRATCHA_REG_800);
++    patch_abs_32 (hostdata->script, 0, addr_temp, base + TEMP_REG);
++    patch_abs_32 (hostdata->script, 0, addr_dsa, base + DSA_REG);
++
++    /*
++     * I needed some variables in the script to be accessible to 
++     * both the NCR chip and the host processor. For these variables,
++     * I made the arbitrary decision to store them directly in the 
++     * hostdata structure rather than in the RELATIVE area of the 
++     * SCRIPTS.
++     */
++    
 +
-+      pmbox = &pmb->mb;
-+
-+      /* Initialize the struct lpfc_sli_hbq structure for each hbq */
-+      phba->link_state = LPFC_INIT_MBX_CMDS;
-+
-+      hbq_entry_index = 0;
-+      for (hbqno = 0; hbqno < hbq_count; ++hbqno) {
-+              phba->hbqs[hbqno].next_hbqPutIdx = 0;
-+              phba->hbqs[hbqno].hbqPutIdx      = 0;
-+              phba->hbqs[hbqno].local_hbqGetIdx   = 0;
-+              phba->hbqs[hbqno].entry_count =
-+                      lpfc_hbq_defs[hbqno]->entry_count;
-+              lpfc_config_hbq(phba, lpfc_hbq_defs[hbqno], hbq_entry_index,
-+                              pmb);
-+              hbq_entry_index += phba->hbqs[hbqno].entry_count;
-+
-+              if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
-+                      /* Adapter failed to init, mbxCmd <cmd> CFG_RING,
-+                         mbxStatus <status>, ring <num> */
-+
-+                      lpfc_printf_log(phba, KERN_ERR,
-+                                      LOG_SLI | LOG_VPORT,
-+                                      "%d:1805 Adapter failed to init. "
-+                                      "Data: x%x x%x x%x\n",
-+                                      phba->brd_no, pmbox->mbxCommand,
-+                                      pmbox->mbxStatus, hbqno);
-+
-+                      phba->link_state = LPFC_HBA_ERROR;
-+                      mempool_free(pmb, phba->mbox_mem_pool);
-+                      return ENXIO;
-+              }
-+      }
-+      phba->hbq_count = hbq_count;
++    patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_memory, tmp);
++    patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_ncr, memory_to_ncr);
++    patch_abs_rwri_data (hostdata->script, 0, dmode_ncr_to_memory, ncr_to_memory);
++
++    patch_abs_32 (hostdata->script, 0, msg_buf, 
++      virt_to_bus((void *)&(hostdata->msg_buf)));
++    patch_abs_32 (hostdata->script, 0, reconnect_dsa_head, 
++      virt_to_bus((void *)&(hostdata->reconnect_dsa_head)));
++    patch_abs_32 (hostdata->script, 0, addr_reconnect_dsa_head, 
++      virt_to_bus((void *)&(hostdata->addr_reconnect_dsa_head)));
++    patch_abs_32 (hostdata->script, 0, reselected_identify, 
++      virt_to_bus((void *)&(hostdata->reselected_identify)));
++/* reselected_tag is currently unused */
++#if 0
++    patch_abs_32 (hostdata->script, 0, reselected_tag, 
++      virt_to_bus((void *)&(hostdata->reselected_tag)));
++#endif
 +
-+      mempool_free(pmb, phba->mbox_mem_pool);
++    patch_abs_32 (hostdata->script, 0, test_dest, 
++      virt_to_bus((void*)&hostdata->test_dest));
++    patch_abs_32 (hostdata->script, 0, test_src, 
++      virt_to_bus(&hostdata->test_source));
++    patch_abs_32 (hostdata->script, 0, saved_dsa,
++      virt_to_bus((void *)&hostdata->saved2_dsa));
++    patch_abs_32 (hostdata->script, 0, emulfly,
++      virt_to_bus((void *)&hostdata->emulated_intfly));
++
++    patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect, 
++      (unsigned char)(Ent_dsa_code_check_reselect - Ent_dsa_zero));
++
++/* These are for event logging; the ncr_event enum contains the 
++   actual interrupt numbers. */
++#ifdef A_int_EVENT_SELECT
++   patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT, (u32) EVENT_SELECT);
++#endif
++#ifdef A_int_EVENT_DISCONNECT
++   patch_abs_32 (hostdata->script, 0, int_EVENT_DISCONNECT, (u32) EVENT_DISCONNECT);
++#endif
++#ifdef A_int_EVENT_RESELECT
++   patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT, (u32) EVENT_RESELECT);
++#endif
++#ifdef A_int_EVENT_COMPLETE
++   patch_abs_32 (hostdata->script, 0, int_EVENT_COMPLETE, (u32) EVENT_COMPLETE);
++#endif
++#ifdef A_int_EVENT_IDLE
++   patch_abs_32 (hostdata->script, 0, int_EVENT_IDLE, (u32) EVENT_IDLE);
++#endif
++#ifdef A_int_EVENT_SELECT_FAILED
++   patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT_FAILED, 
++      (u32) EVENT_SELECT_FAILED);
++#endif
++#ifdef A_int_EVENT_BEFORE_SELECT
++   patch_abs_32 (hostdata->script, 0, int_EVENT_BEFORE_SELECT,
++      (u32) EVENT_BEFORE_SELECT);
++#endif
++#ifdef A_int_EVENT_RESELECT_FAILED
++   patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT_FAILED, 
++      (u32) EVENT_RESELECT_FAILED);
++#endif
 +
-+      /* Initially populate or replenish the HBQs */
-+      for (hbqno = 0; hbqno < hbq_count; ++hbqno) {
-+              if (lpfc_sli_hbqbuf_init_hbqs(phba, hbqno))
-+                      return -ENOMEM;
-+      }
-+      return 0;
++    /*
++     * Make sure the NCR and Linux code agree on the location of 
++     * certain fields.
++     */
++
++    hostdata->E_accept_message = Ent_accept_message;
++    hostdata->E_command_complete = Ent_command_complete;              
++    hostdata->E_cmdout_cmdout = Ent_cmdout_cmdout;
++    hostdata->E_data_transfer = Ent_data_transfer;
++    hostdata->E_debug_break = Ent_debug_break;        
++    hostdata->E_dsa_code_template = Ent_dsa_code_template;
++    hostdata->E_dsa_code_template_end = Ent_dsa_code_template_end;
++    hostdata->E_end_data_transfer = Ent_end_data_transfer;
++    hostdata->E_initiator_abort = Ent_initiator_abort;
++    hostdata->E_msg_in = Ent_msg_in;
++    hostdata->E_other_transfer = Ent_other_transfer;
++    hostdata->E_other_in = Ent_other_in;
++    hostdata->E_other_out = Ent_other_out;
++    hostdata->E_reject_message = Ent_reject_message;
++    hostdata->E_respond_message = Ent_respond_message;
++    hostdata->E_select = Ent_select;
++    hostdata->E_select_msgout = Ent_select_msgout;
++    hostdata->E_target_abort = Ent_target_abort;
++#ifdef Ent_test_0
++    hostdata->E_test_0 = Ent_test_0;
++#endif
++    hostdata->E_test_1 = Ent_test_1;
++    hostdata->E_test_2 = Ent_test_2;
++#ifdef Ent_test_3
++    hostdata->E_test_3 = Ent_test_3;
++#endif
++    hostdata->E_wait_reselect = Ent_wait_reselect;
++    hostdata->E_dsa_code_begin = Ent_dsa_code_begin;
++
++    hostdata->dsa_cmdout = A_dsa_cmdout;
++    hostdata->dsa_cmnd = A_dsa_cmnd;
++    hostdata->dsa_datain = A_dsa_datain;
++    hostdata->dsa_dataout = A_dsa_dataout;
++    hostdata->dsa_end = A_dsa_end;                    
++    hostdata->dsa_msgin = A_dsa_msgin;
++    hostdata->dsa_msgout = A_dsa_msgout;
++    hostdata->dsa_msgout_other = A_dsa_msgout_other;
++    hostdata->dsa_next = A_dsa_next;
++    hostdata->dsa_select = A_dsa_select;
++    hostdata->dsa_start = Ent_dsa_code_template - Ent_dsa_zero;
++    hostdata->dsa_status = A_dsa_status;
++    hostdata->dsa_jump_dest = Ent_dsa_code_fix_jump - Ent_dsa_zero + 
++      8 /* destination operand */;
++
++    /* sanity check */
++    if (A_dsa_fields_start != Ent_dsa_code_template_end - 
++      Ent_dsa_zero) 
++      printk("scsi%d : NCR dsa_fields start is %d not %d\n",
++          host->host_no, A_dsa_fields_start, Ent_dsa_code_template_end - 
++          Ent_dsa_zero);
++
++    printk("scsi%d : NCR code relocated to 0x%lx (virt 0x%p)\n", host->host_no,
++      virt_to_bus(hostdata->script), hostdata->script);
 +}
 +
-+static int
-+lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode)
-+{
-+      LPFC_MBOXQ_t *pmb;
-+      uint32_t resetcount = 0, rc = 0, done = 0;
++/*
++ * Function : static int NCR53c7xx_run_tests (struct Scsi_Host *host)
++ *
++ * Purpose : run various verification tests on the NCR chip, 
++ *    including interrupt generation, and proper bus mastering
++ *    operation.
++ * 
++ * Inputs : host - a properly initialized Scsi_Host structure
++ *
++ * Preconditions : the NCR chip must be in a halted state.
++ *
++ * Returns : 0 if all tests were successful, -1 on error.
++ * 
++ */
 +
-+      pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (!pmb) {
-+              phba->link_state = LPFC_HBA_ERROR;
-+              return -ENOMEM;
-+      }
++static int 
++NCR53c7xx_run_tests (struct Scsi_Host *host) {
++    NCR53c7x0_local_declare();
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    unsigned long timeout;
++    u32 start;
++    int failed, i;
++    unsigned long flags;
++    NCR53c7x0_local_setup(host);
 +
-+      phba->sli_rev = sli_mode;
-       while (resetcount < 2 && !done) {
--              spin_lock_irq(phba->host->host_lock);
-+              spin_lock_irq(&phba->hbalock);
-               phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE;
--              spin_unlock_irq(phba->host->host_lock);
--              phba->hba_state = LPFC_STATE_UNKNOWN;
-+              spin_unlock_irq(&phba->hbalock);
-+              phba->pport->port_state = LPFC_VPORT_UNKNOWN;
-               lpfc_sli_brdrestart(phba);
-               msleep(2500);
-               rc = lpfc_sli_chipset_init(phba);
-               if (rc)
-                       break;
--              spin_lock_irq(phba->host->host_lock);
-+              spin_lock_irq(&phba->hbalock);
-               phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
--              spin_unlock_irq(phba->host->host_lock);
-+              spin_unlock_irq(&phba->hbalock);
-               resetcount++;
--      /* Call pre CONFIG_PORT mailbox command initialization.  A value of 0
--       * means the call was successful.  Any other nonzero value is a failure,
--       * but if ERESTART is returned, the driver may reset the HBA and try
--       * again.
-+              /* Call pre CONFIG_PORT mailbox command initialization.  A
-+               * value of 0 means the call was successful.  Any other
-+               * nonzero value is a failure, but if ERESTART is returned,
-+               * the driver may reset the HBA and try again.
-        */
-               rc = lpfc_config_port_prep(phba);
-               if (rc == -ERESTART) {
--                      phba->hba_state = 0;
-+                      phba->link_state = LPFC_LINK_UNKNOWN;
-                       continue;
-               } else if (rc) {
-                       break;
-               }
--              phba->hba_state = LPFC_INIT_MBX_CMDS;
-+              phba->link_state = LPFC_INIT_MBX_CMDS;
-               lpfc_config_port(phba, pmb);
-               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
--              if (rc == MBX_SUCCESS)
--                      done = 1;
--              else {
-+              if (rc != MBX_SUCCESS) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "%d:0442 Adapter failed to init, mbxCmd x%x "
-                               "CONFIG_PORT, mbxStatus x%x Data: x%x\n",
-                               phba->brd_no, pmb->mb.mbxCommand,
-                               pmb->mb.mbxStatus, 0);
-+                      spin_lock_irq(&phba->hbalock);
-                       phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE;
-+                      spin_unlock_irq(&phba->hbalock);
-+                      rc = -ENXIO;
-+              } else {
-+                      done = 1;
-+                      phba->max_vpi = (phba->max_vpi &&
-+                                       pmb->mb.un.varCfgPort.gmv) != 0
-+                              ? pmb->mb.un.varCfgPort.max_vpi
-+                              : 0;
-               }
-       }
--      if (!done)
++    /* The NCR chip _must_ be idle to run the test scripts */
 +
-+      if (!done) {
-+              rc = -EINVAL;
-+              goto do_prep_failed;
-+      }
++    local_irq_save(flags);
++    if (!hostdata->idle) {
++      printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);
++      local_irq_restore(flags);
++      return -1;
++    }
++
++    /* 
++     * Check for functional interrupts, this could work as an
++     * autoprobe routine.
++     */
++
++    if ((hostdata->options & OPTION_DEBUG_TEST1) && 
++          hostdata->state != STATE_DISABLED) {
++      hostdata->idle = 0;
++      hostdata->test_running = 1;
++      hostdata->test_completed = -1;
++      hostdata->test_dest = 0;
++      hostdata->test_source = 0xdeadbeef;
++      start = virt_to_bus (hostdata->script) + hostdata->E_test_1;
++      hostdata->state = STATE_RUNNING;
++      printk ("scsi%d : test 1", host->host_no);
++      NCR53c7x0_write32 (DSP_REG, start);
++      if (hostdata->options & OPTION_DEBUG_TRACE)
++          NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM |
++                                              DCNTL_STD);
++      printk (" started\n");
++      local_irq_restore(flags);
++
++      /* 
++       * This is currently a .5 second timeout, since (in theory) no slow 
++       * board will take that long.  In practice, we've seen one 
++       * pentium which occassionally fails with this, but works with 
++       * 10 times as much?
++       */
 +
-+      if ((pmb->mb.un.varCfgPort.sli_mode == 3) &&
-+              (!pmb->mb.un.varCfgPort.cMA)) {
-+              rc = -ENXIO;
-+              goto do_prep_failed;
++      timeout = jiffies + 5 * HZ / 10;
++      while ((hostdata->test_completed == -1) && time_before(jiffies, timeout))
++              barrier();
++
++      failed = 1;
++      if (hostdata->test_completed == -1)
++          printk ("scsi%d : driver test 1 timed out%s\n",host->host_no ,
++              (hostdata->test_dest == 0xdeadbeef) ? 
++                  " due to lost interrupt.\n"
++                  "         Please verify that the correct IRQ is being used for your board,\n"
++                  : "");
++      else if (hostdata->test_completed != 1) 
++          printk ("scsi%d : test 1 bad interrupt value (%d)\n", 
++              host->host_no, hostdata->test_completed);
++      else 
++          failed = (hostdata->test_dest != 0xdeadbeef);
++
++      if (hostdata->test_dest != 0xdeadbeef) {
++          printk ("scsi%d : driver test 1 read 0x%x instead of 0xdeadbeef indicating a\n"
++                    "         probable cache invalidation problem.  Please configure caching\n"
++                  "         as write-through or disabled\n",
++              host->host_no, hostdata->test_dest);
++      }
++
++      if (failed) {
++          printk ("scsi%d : DSP = 0x%p (script at 0x%p, start at 0x%x)\n",
++              host->host_no, bus_to_virt(NCR53c7x0_read32(DSP_REG)),
++              hostdata->script, start);
++          printk ("scsi%d : DSPS = 0x%x\n", host->host_no,
++              NCR53c7x0_read32(DSPS_REG));
++          local_irq_restore(flags);
++          return -1;
++      }
++      hostdata->test_running = 0;
++    }
++
++    if ((hostdata->options & OPTION_DEBUG_TEST2) && 
++      hostdata->state != STATE_DISABLED) {
++      u32 dsa[48];
++      unsigned char identify = IDENTIFY(0, 0);
++      unsigned char cmd[6];
++      unsigned char data[36];
++      unsigned char status = 0xff;
++      unsigned char msg = 0xff;
++
++      cmd[0] = INQUIRY;
++      cmd[1] = cmd[2] = cmd[3] = cmd[5] = 0;
++      cmd[4] = sizeof(data); 
++
++      dsa[2] = 1;
++      dsa[3] = virt_to_bus(&identify);
++      dsa[4] = 6;
++      dsa[5] = virt_to_bus(&cmd);
++      dsa[6] = sizeof(data);
++      dsa[7] = virt_to_bus(&data);
++      dsa[8] = 1;
++      dsa[9] = virt_to_bus(&status);
++      dsa[10] = 1;
++      dsa[11] = virt_to_bus(&msg);
++
++      for (i = 0; i < 6; ++i) {
++#ifdef VALID_IDS
++          if (!hostdata->valid_ids[i])
++              continue;
++#endif
++          local_irq_disable();
++          if (!hostdata->idle) {
++              printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);
++              local_irq_restore(flags);
++              return -1;
++          }
++
++          /* 710: bit mapped scsi ID, async   */
++            dsa[0] = (1 << i) << 16;
++          hostdata->idle = 0;
++          hostdata->test_running = 2;
++          hostdata->test_completed = -1;
++          start = virt_to_bus(hostdata->script) + hostdata->E_test_2;
++          hostdata->state = STATE_RUNNING;
++          NCR53c7x0_write32 (DSA_REG, virt_to_bus(dsa));
++          NCR53c7x0_write32 (DSP_REG, start);
++          if (hostdata->options & OPTION_DEBUG_TRACE)
++              NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
++                              DCNTL_SSM | DCNTL_STD);
++          local_irq_restore(flags);
++
++          timeout = jiffies + 5 * HZ; /* arbitrary */
++          while ((hostdata->test_completed == -1) && time_before(jiffies, timeout))
++              barrier();
++
++          NCR53c7x0_write32 (DSA_REG, 0);
++
++          if (hostdata->test_completed == 2) {
++              data[35] = 0;
++              printk ("scsi%d : test 2 INQUIRY to target %d, lun 0 : %s\n",
++                  host->host_no, i, data + 8);
++              printk ("scsi%d : status ", host->host_no);
++              scsi_print_status (status);
++              printk ("\nscsi%d : message ", host->host_no);
++              spi_print_msg(&msg);
++              printk ("\n");
++          } else if (hostdata->test_completed == 3) {
++              printk("scsi%d : test 2 no connection with target %d\n",
++                  host->host_no, i);
++              if (!hostdata->idle) {
++                  printk("scsi%d : not idle\n", host->host_no);
++                  local_irq_restore(flags);
++                  return -1;
++              }
++          } else if (hostdata->test_completed == -1) {
++              printk ("scsi%d : test 2 timed out\n", host->host_no);
++              local_irq_restore(flags);
++              return -1;
++          } 
++          hostdata->test_running = 0;
 +      }
-+      return rc;
++    }
 +
-+do_prep_failed:
-+      mempool_free(pmb, phba->mbox_mem_pool);
-+      return rc;
++    local_irq_restore(flags);
++    return 0;
 +}
 +
-+int
-+lpfc_sli_hba_setup(struct lpfc_hba *phba)
-+{
-+      uint32_t rc;
-+      int  mode = 3;
++/*
++ * Function : static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd)
++ *
++ * Purpose : copy the NCR53c8xx dsa structure into cmd's dsa buffer,
++ *    performing all necessary relocation.
++ *
++ * Inputs : cmd, a NCR53c7x0_cmd structure with a dsa area large
++ *    enough to hold the NCR53c8xx dsa.
++ */
 +
-+      switch (lpfc_sli_mode) {
-+      case 2:
-+              if (phba->cfg_npiv_enable) {
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
-+                              "%d:1824 NPIV enabled: Override lpfc_sli_mode "
-+                              "parameter (%d) to auto (0).\n",
-+                              phba->brd_no, lpfc_sli_mode);
-+                      break;
-+              }
-+              mode = 2;
-+              break;
-+      case 0:
-+      case 3:
-+              break;
-+      default:
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
-+                              "%d:1819 Unrecognized lpfc_sli_mode "
-+                              "parameter: %d.\n",
-+                              phba->brd_no, lpfc_sli_mode);
++static void 
++NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) {
++    Scsi_Cmnd *c = cmd->cmd;
++    struct Scsi_Host *host = c->device->host;
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    int i;
 +
-+              break;
-+      }
++    memcpy (cmd->dsa, hostdata->script + (hostdata->E_dsa_code_template / 4),
++      hostdata->E_dsa_code_template_end - hostdata->E_dsa_code_template);
++
++    /* 
++     * Note : within the NCR 'C' code, dsa points to the _start_
++     * of the DSA structure, and _not_ the offset of dsa_zero within
++     * that structure used to facilitate shorter signed offsets
++     * for the 8 bit ALU.
++     * 
++     * The implications of this are that 
++     * 
++     * - 32 bit A_dsa_* absolute values require an additional 
++     *         dsa_zero added to their value to be correct, since they are 
++     *   relative to dsa_zero which is in essentially a separate
++     *   space from the code symbols.
++     *
++     * - All other symbols require no special treatment.
++     */
++
++    patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
++      dsa_temp_lun, c->device->lun);
++    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
++      dsa_temp_addr_next, virt_to_bus(&cmd->dsa_next_addr));
++    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
++      dsa_temp_next, virt_to_bus(cmd->dsa) + Ent_dsa_zero -
++      Ent_dsa_code_template + A_dsa_next);
++    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), 
++      dsa_temp_sync, virt_to_bus((void *)hostdata->sync[c->device->id].script));
++    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), 
++      dsa_sscf_710, virt_to_bus((void *)&hostdata->sync[c->device->id].sscf_710));
++    patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
++          dsa_temp_target, 1 << c->device->id);
++    /* XXX - new pointer stuff */
++    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
++      dsa_temp_addr_saved_pointer, virt_to_bus(&cmd->saved_data_pointer));
++    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
++      dsa_temp_addr_saved_residual, virt_to_bus(&cmd->saved_residual));
++    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
++      dsa_temp_addr_residual, virt_to_bus(&cmd->residual));
++
++    /*  XXX - new start stuff */
++
++    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
++      dsa_temp_addr_dsa_value, virt_to_bus(&cmd->dsa_addr));
++}
 +
-+      rc = lpfc_do_config_port(phba, mode);
-+      if (rc && lpfc_sli_mode == 3)
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
-+                              "%d:1820 Unable to select SLI-3.  "
-+                              "Not supported by adapter.\n",
-+                              phba->brd_no);
-+      if (rc && mode != 2)
-+              rc = lpfc_do_config_port(phba, 2);
-+      if (rc)
-+              goto lpfc_sli_hba_setup_error;
++/* 
++ * Function : run_process_issue_queue (void)
++ * 
++ * Purpose : insure that the coroutine is running and will process our 
++ *    request.  process_issue_queue_running is checked/set here (in an 
++ *    inline function) rather than in process_issue_queue itself to reduce 
++ *    the chances of stack overflow.
++ *
++ */
++
++static volatile int process_issue_queue_running = 0;
++
++static __inline__ void 
++run_process_issue_queue(void) {
++    unsigned long flags;
++    local_irq_save(flags);
++    if (!process_issue_queue_running) {
++      process_issue_queue_running = 1;
++        process_issue_queue(flags);
++      /* 
++         * process_issue_queue_running is cleared in process_issue_queue 
++       * once it can't do more work, and process_issue_queue exits with 
++       * interrupts disabled.
++       */
++    }
++    local_irq_restore(flags);
++}
 +
-+      if (phba->sli_rev == 3) {
-+              phba->iocb_cmd_size = SLI3_IOCB_CMD_SIZE;
-+              phba->iocb_rsp_size = SLI3_IOCB_RSP_SIZE;
-+              phba->sli3_options |= LPFC_SLI3_ENABLED;
-+              phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED;
++/*
++ * Function : static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int
++ *    result)
++ *
++ * Purpose : mark SCSI command as finished, OR'ing the host portion 
++ *    of the result word into the result field of the corresponding
++ *    Scsi_Cmnd structure, and removing it from the internal queues.
++ *
++ * Inputs : cmd - command, result - entire result field
++ *
++ * Preconditions : the        NCR chip should be in a halted state when 
++ *    abnormal_finished is run, since it modifies structures which
++ *    the NCR expects to have exclusive access to.
++ */
 +
-+      } else {
-+              phba->iocb_cmd_size = SLI2_IOCB_CMD_SIZE;
-+              phba->iocb_rsp_size = SLI2_IOCB_RSP_SIZE;
-+              phba->sli3_options = 0;
-+      }
++static void 
++abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) {
++    Scsi_Cmnd *c = cmd->cmd;
++    struct Scsi_Host *host = c->device->host;
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    unsigned long flags;
++    int left, found;
++    volatile struct NCR53c7x0_cmd * linux_search;
++    volatile struct NCR53c7x0_cmd * volatile *linux_prev;
++    volatile u32 *ncr_prev, *ncrcurrent, ncr_search;
 +
-+      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-+                      "%d:0444 Firmware in SLI %x mode. Max_vpi %d\n",
-+                      phba->brd_no, phba->sli_rev, phba->max_vpi);
-+      rc = lpfc_sli_ring_map(phba);
++#if 0
++    printk ("scsi%d: abnormal finished\n", host->host_no);
++#endif
 +
-+      if (rc)
-               goto lpfc_sli_hba_setup_error;
--      rc = lpfc_sli_ring_map(phba, pmb);
-+                              /* Init HBQs */
-+      if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
-+              rc = lpfc_sli_hbq_setup(phba);
-       if (rc)
-               goto lpfc_sli_hba_setup_error;
-+      }
-       phba->sli.sli_flag |= LPFC_PROCESS_LA;
-@@ -1980,11 +2387,13 @@
-       if (rc)
-               goto lpfc_sli_hba_setup_error;
--      goto lpfc_sli_hba_setup_exit;
-+      return rc;
++    local_irq_save(flags);
++    found = 0;
++    /* 
++     * Traverse the NCR issue array until we find a match or run out 
++     * of instructions.  Instructions in the NCR issue array are 
++     * either JUMP or NOP instructions, which are 2 words in length.
++     */
 +
- lpfc_sli_hba_setup_error:
--      phba->hba_state = LPFC_HBA_ERROR;
--lpfc_sli_hba_setup_exit:
--      mempool_free(pmb, phba->mbox_mem_pool);
-+      phba->link_state = LPFC_HBA_ERROR;
-+      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-+                      "%d:0445 Firmware initialization failed\n",
-+                      phba->brd_no);
-       return rc;
- }
-@@ -2004,44 +2413,43 @@
- void
- lpfc_mbox_timeout(unsigned long ptr)
- {
--      struct lpfc_hba *phba;
-+      struct lpfc_hba  *phba = (struct lpfc_hba *) ptr;
-       unsigned long iflag;
-+      uint32_t tmo_posted;
 +
-+      spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
-+      tmo_posted = phba->pport->work_port_events & WORKER_MBOX_TMO;
-+      if (!tmo_posted)
-+              phba->pport->work_port_events |= WORKER_MBOX_TMO;
-+      spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
--      phba = (struct lpfc_hba *)ptr;
--      spin_lock_irqsave(phba->host->host_lock, iflag);
--      if (!(phba->work_hba_events & WORKER_MBOX_TMO)) {
--              phba->work_hba_events |= WORKER_MBOX_TMO;
-+      if (!tmo_posted) {
-+              spin_lock_irqsave(&phba->hbalock, iflag);
-               if (phba->work_wait)
--                      wake_up(phba->work_wait);
-+                      lpfc_worker_wake_up(phba);
-+              spin_unlock_irqrestore(&phba->hbalock, iflag);
-       }
--      spin_unlock_irqrestore(phba->host->host_lock, iflag);
- }
- void
- lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
- {
--      LPFC_MBOXQ_t *pmbox;
--      MAILBOX_t *mb;
-+      LPFC_MBOXQ_t *pmbox = phba->sli.mbox_active;
-+      MAILBOX_t *mb = &pmbox->mb;
-       struct lpfc_sli *psli = &phba->sli;
-       struct lpfc_sli_ring *pring;
--      spin_lock_irq(phba->host->host_lock);
--      if (!(phba->work_hba_events & WORKER_MBOX_TMO)) {
--              spin_unlock_irq(phba->host->host_lock);
-+      if (!(phba->pport->work_port_events & WORKER_MBOX_TMO)) {
-               return;
-       }
--      pmbox = phba->sli.mbox_active;
--      mb = &pmbox->mb;
--
-       /* Mbox cmd <mbxCommand> timeout */
--      lpfc_printf_log(phba,
--              KERN_ERR,
--              LOG_MBOX | LOG_SLI,
--              "%d:0310 Mailbox command x%x timeout Data: x%x x%x x%p\n",
-+      lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
-+                      "%d:0310 Mailbox command x%x timeout Data: x%x x%x "
-+                      "x%p\n",
-               phba->brd_no,
-               mb->mbxCommand,
--              phba->hba_state,
-+                      phba->pport->port_state,
-               phba->sli.sli_flag,
-               phba->sli.mbox_active);
-@@ -2049,11 +2457,14 @@
-        * would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing
-        * it to fail all oustanding SCSI IO.
-        */
--      phba->hba_state = LPFC_STATE_UNKNOWN;
--      phba->work_hba_events &= ~WORKER_MBOX_TMO;
--      phba->fc_flag |= FC_ESTABLISH_LINK;
-+      spin_lock_irq(&phba->pport->work_port_lock);
-+      phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
-+      spin_unlock_irq(&phba->pport->work_port_lock);
-+      spin_lock_irq(&phba->hbalock);
-+      phba->link_state = LPFC_LINK_UNKNOWN;
-+      phba->pport->fc_flag |= FC_ESTABLISH_LINK;
-       psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
--      spin_unlock_irq(phba->host->host_lock);
-+      spin_unlock_irq(&phba->hbalock);
-       pring = &psli->ring[psli->fcp_ring];
-       lpfc_sli_abort_iocb_ring(phba, pring);
-@@ -2075,10 +2486,10 @@
- }
- int
--lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
-+lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
- {
-       MAILBOX_t *mb;
--      struct lpfc_sli *psli;
-+      struct lpfc_sli *psli = &phba->sli;
-       uint32_t status, evtctr;
-       uint32_t ha_copy;
-       int i;
-@@ -2086,31 +2497,44 @@
-       volatile uint32_t word0, ldata;
-       void __iomem *to_slim;
-+      if (pmbox->mbox_cmpl && pmbox->mbox_cmpl != lpfc_sli_def_mbox_cmpl &&
-+              pmbox->mbox_cmpl != lpfc_sli_wake_mbox_wait) {
-+              if(!pmbox->vport) {
-+                      lpfc_printf_log(phba, KERN_ERR,
-+                                      LOG_MBOX | LOG_VPORT,
-+                                      "%d:1806 Mbox x%x failed. No vport\n",
-+                                      phba->brd_no,
-+                                      pmbox->mb.mbxCommand);
-+                      dump_stack();
-+                      return MBXERR_ERROR;
-+              }
++    for (found = 0, left = host->can_queue, ncrcurrent = hostdata->schedule; 
++      left > 0; --left, ncrcurrent += 2)
++    {
++      if (issue_to_cmd (host, hostdata, (u32 *) ncrcurrent) == cmd) 
++      {
++          ncrcurrent[0] = hostdata->NOP_insn;
++          ncrcurrent[1] = 0xdeadbeef;
++          ++found;
++          break;
 +      }
++    }
++      
++    /* 
++     * Traverse the NCR reconnect list of DSA structures until we find 
++     * a pointer to this dsa or have found too many command structures.  
++     * We let prev point at the next field of the previous element or 
++     * head of the list, so we don't do anything different for removing 
++     * the head element.  
++     */
++
++    for (left = host->can_queue,
++          ncr_search = hostdata->reconnect_dsa_head, 
++          ncr_prev = &hostdata->reconnect_dsa_head;
++      left >= 0 && ncr_search && 
++          ((char*)bus_to_virt(ncr_search) + hostdata->dsa_start) 
++              != (char *) cmd->dsa;
++      ncr_prev = (u32*) ((char*)bus_to_virt(ncr_search) + 
++          hostdata->dsa_next), ncr_search = *ncr_prev, --left);
++
++    if (left < 0) 
++      printk("scsi%d: loop detected in ncr reconncect list\n",
++          host->host_no);
++    else if (ncr_search) {
++      if (found)
++          printk("scsi%d: scsi %ld in ncr issue array and reconnect lists\n",
++              host->host_no, c->pid);
++      else {
++          volatile u32 * next = (u32 *) 
++              ((char *)bus_to_virt(ncr_search) + hostdata->dsa_next);
++          *ncr_prev = *next;
++/* If we're at the tail end of the issue queue, update that pointer too. */
++          found = 1;
++      }
++    }
++
++    /*
++     * Traverse the host running list until we find this command or discover
++     * we have too many elements, pointing linux_prev at the next field of the 
++     * linux_previous element or head of the list, search at this element.
++     */
++
++    for (left = host->can_queue, linux_search = hostdata->running_list, 
++          linux_prev = &hostdata->running_list;
++      left >= 0 && linux_search && linux_search != cmd;
++      linux_prev = &(linux_search->next), 
++          linux_search = linux_search->next, --left);
++    
++    if (left < 0) 
++      printk ("scsi%d: loop detected in host running list for scsi pid %ld\n",
++          host->host_no, c->pid);
++    else if (linux_search) {
++      *linux_prev = linux_search->next;
++      --hostdata->busy[c->device->id][c->device->lun];
++    }
 +
++    /* Return the NCR command structure to the free list */
++    cmd->next = hostdata->free;
++    hostdata->free = cmd;
++    c->host_scribble = NULL;
 +
-       /* If the PCI channel is in offline state, do not post mbox. */
-       if (unlikely(pci_channel_offline(phba->pcidev)))
-               return MBX_NOT_FINISHED;
-+      spin_lock_irqsave(&phba->hbalock, drvr_flag);
-       psli = &phba->sli;
--      spin_lock_irqsave(phba->host->host_lock, drvr_flag);
--
-       mb = &pmbox->mb;
-       status = MBX_SUCCESS;
--      if (phba->hba_state == LPFC_HBA_ERROR) {
--              spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
-+      if (phba->link_state == LPFC_HBA_ERROR) {
-+              spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
-               /* Mbox command <mbxCommand> cannot issue */
--              LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
--              return (MBX_NOT_FINISHED);
-+              LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag)
-+              return MBX_NOT_FINISHED;
-       }
-       if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
-           !(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
--              spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
--              LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
--              return (MBX_NOT_FINISHED);
-+              spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
-+              LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag)
-+              return MBX_NOT_FINISHED;
-       }
-       if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
-@@ -2120,20 +2544,18 @@
-                */
-               if (flag & MBX_POLL) {
--                      spin_unlock_irqrestore(phba->host->host_lock,
--                                             drvr_flag);
-+                      spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
-                       /* Mbox command <mbxCommand> cannot issue */
--                      LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
--                      return (MBX_NOT_FINISHED);
-+                      LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
-+                      return MBX_NOT_FINISHED;
-               }
-               if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) {
--                      spin_unlock_irqrestore(phba->host->host_lock,
--                                             drvr_flag);
-+                      spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
-                       /* Mbox command <mbxCommand> cannot issue */
--                      LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
--                      return (MBX_NOT_FINISHED);
-+                      LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
-+                      return MBX_NOT_FINISHED;
-               }
-               /* Handle STOP IOCB processing flag. This is only meaningful
-@@ -2157,21 +2579,33 @@
-               lpfc_mbox_put(phba, pmbox);
-               /* Mbox cmd issue - BUSY */
--              lpfc_printf_log(phba,
--                      KERN_INFO,
--                      LOG_MBOX | LOG_SLI,
--                      "%d:0308 Mbox cmd issue - BUSY Data: x%x x%x x%x x%x\n",
-+              lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
-+                              "%d (%d):0308 Mbox cmd issue - BUSY Data: "
-+                              "x%x x%x x%x x%x\n",
-                       phba->brd_no,
--                      mb->mbxCommand,
--                      phba->hba_state,
--                      psli->sli_flag,
--                      flag);
-+                              pmbox->vport ? pmbox->vport->vpi : 0xffffff,
-+                              mb->mbxCommand, phba->pport->port_state,
-+                              psli->sli_flag, flag);
-               psli->slistat.mbox_busy++;
--              spin_unlock_irqrestore(phba->host->host_lock,
--                                     drvr_flag);
-+              spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
--              return (MBX_BUSY);
-+              if (pmbox->vport) {
-+                      lpfc_debugfs_disc_trc(pmbox->vport,
-+                              LPFC_DISC_TRC_MBOX_VPORT,
-+                              "MBOX Bsy vport:  cmd:x%x mb:x%x x%x",
-+                              (uint32_t)mb->mbxCommand,
-+                              mb->un.varWords[0], mb->un.varWords[1]);
-+              }
-+              else {
-+                      lpfc_debugfs_disc_trc(phba->pport,
-+                              LPFC_DISC_TRC_MBOX,
-+                              "MBOX Bsy:        cmd:x%x mb:x%x x%x",
-+                              (uint32_t)mb->mbxCommand,
-+                              mb->un.varWords[0], mb->un.varWords[1]);
-+              }
++    /* And return */
++    c->result = result;
++    c->scsi_done(c);
 +
-+              return MBX_BUSY;
-       }
-       /* Handle STOP IOCB processing flag. This is only meaningful
-@@ -2198,11 +2632,10 @@
-               if (!(psli->sli_flag & LPFC_SLI2_ACTIVE) &&
-                   (mb->mbxCommand != MBX_KILL_BOARD)) {
-                       psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
--                      spin_unlock_irqrestore(phba->host->host_lock,
--                                             drvr_flag);
-+                      spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
-                       /* Mbox command <mbxCommand> cannot issue */
--                      LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag);
--                      return (MBX_NOT_FINISHED);
-+                      LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
-+                      return MBX_NOT_FINISHED;
-               }
-               /* timeout active mbox command */
-               mod_timer(&psli->mbox_tmo, (jiffies +
-@@ -2210,15 +2643,29 @@
-       }
-       /* Mailbox cmd <cmd> issue */
--      lpfc_printf_log(phba,
--              KERN_INFO,
--              LOG_MBOX | LOG_SLI,
--              "%d:0309 Mailbox cmd x%x issue Data: x%x x%x x%x\n",
--              phba->brd_no,
--              mb->mbxCommand,
--              phba->hba_state,
--              psli->sli_flag,
--              flag);
-+      lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
-+                      "%d (%d):0309 Mailbox cmd x%x issue Data: x%x x%x "
-+                      "x%x\n",
-+                      phba->brd_no, pmbox->vport ? pmbox->vport->vpi : 0,
-+                      mb->mbxCommand, phba->pport->port_state,
-+                      psli->sli_flag, flag);
-+
-+      if (mb->mbxCommand != MBX_HEARTBEAT) {
-+              if (pmbox->vport) {
-+                      lpfc_debugfs_disc_trc(pmbox->vport,
-+                              LPFC_DISC_TRC_MBOX_VPORT,
-+                              "MBOX Send vport: cmd:x%x mb:x%x x%x",
-+                              (uint32_t)mb->mbxCommand,
-+                              mb->un.varWords[0], mb->un.varWords[1]);
-+              }
-+              else {
-+                      lpfc_debugfs_disc_trc(phba->pport,
-+                              LPFC_DISC_TRC_MBOX,
-+                              "MBOX Send:       cmd:x%x mb:x%x x%x",
-+                              (uint32_t)mb->mbxCommand,
-+                              mb->un.varWords[0], mb->un.varWords[1]);
-+              }
-+      }
-       psli->slistat.mbox_cmd++;
-       evtctr = psli->slistat.mbox_event;
-@@ -2285,12 +2732,12 @@
-               /* Wait for command to complete */
-               while (((word0 & OWN_CHIP) == OWN_CHIP) ||
-                      (!(ha_copy & HA_MBATT) &&
--                      (phba->hba_state > LPFC_WARM_START))) {
-+                      (phba->link_state > LPFC_WARM_START))) {
-                       if (i-- <= 0) {
-                               psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
--                              spin_unlock_irqrestore(phba->host->host_lock,
-+                              spin_unlock_irqrestore(&phba->hbalock,
-                                                      drvr_flag);
--                              return (MBX_NOT_FINISHED);
-+                              return MBX_NOT_FINISHED;
-                       }
-                       /* Check if we took a mbox interrupt while we were
-@@ -2299,12 +2746,12 @@
-                           && (evtctr != psli->slistat.mbox_event))
-                               break;
--                      spin_unlock_irqrestore(phba->host->host_lock,
-+                      spin_unlock_irqrestore(&phba->hbalock,
-                                              drvr_flag);
-                       msleep(1);
--                      spin_lock_irqsave(phba->host->host_lock, drvr_flag);
-+                      spin_lock_irqsave(&phba->hbalock, drvr_flag);
-                       if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
-                               /* First copy command data */
-@@ -2355,23 +2802,25 @@
-               status = mb->mbxStatus;
-       }
--      spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
--      return (status);
-+      spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
-+      return status;
- }
--static int
--lpfc_sli_ringtx_put(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
--                  struct lpfc_iocbq * piocb)
++    local_irq_restore(flags);
++    run_process_issue_queue();
++}
++
++/* 
++ * Function : static void intr_break (struct Scsi_Host *host,
++ *    struct NCR53c7x0_cmd *cmd)
++ *
++ * Purpose :  Handler for breakpoint interrupts from a SCSI script
++ *
++ * Inputs : host - pointer to this host adapter's structure,
++ *    cmd - pointer to the command (if any) dsa was pointing 
++ *    to.
++ *
++ */
++
++static void 
++intr_break (struct Scsi_Host *host, struct 
++    NCR53c7x0_cmd *cmd) {
++    NCR53c7x0_local_declare();
++    struct NCR53c7x0_break *bp;
++#if 0
++    Scsi_Cmnd *c = cmd ? cmd->cmd : NULL;
++#endif
++    u32 *dsp;
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];              
++    unsigned long flags;
++    NCR53c7x0_local_setup(host);
++
++    /*
++     * Find the break point corresponding to this address, and 
++     * dump the appropriate debugging information to standard 
++     * output.  
++     */
++    local_irq_save(flags);
++    dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG));
++    for (bp = hostdata->breakpoints; bp && bp->address != dsp; 
++      bp = bp->next);
++    if (!bp) 
++      panic("scsi%d : break point interrupt from %p with no breakpoint!",
++          host->host_no, dsp);
++
++    /*
++     * Configure the NCR chip for manual start mode, so that we can 
++     * point the DSP register at the instruction that follows the 
++     * INT int_debug_break instruction.
++     */
++
++    NCR53c7x0_write8 (hostdata->dmode, 
++      NCR53c7x0_read8(hostdata->dmode)|DMODE_MAN);
++
++    /*
++     * And update the DSP register, using the size of the old 
++     * instruction in bytes.
++     */
++
++    local_irq_restore(flags);
++}
 +/*
-+ * Caller needs to hold lock.
++ * Function : static void print_synchronous (const char *prefix, 
++ *    const unsigned char *msg)
++ * 
++ * Purpose : print a pretty, user and machine parsable representation
++ *    of a SDTR message, including the "real" parameters, data
++ *    clock so we can tell transfer rate at a glance.
++ *
++ * Inputs ; prefix - text to prepend, msg - SDTR message (5 bytes)
 + */
++
 +static void
-+__lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-+                  struct lpfc_iocbq *piocb)
- {
-       /* Insert the caller's iocb in the txq tail for later processing. */
-       list_add_tail(&piocb->list, &pring->txq);
-       pring->txq_cnt++;
--      return (0);
- }
- static struct lpfc_iocbq *
- lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
--                 struct lpfc_iocbq ** piocb)
-+                 struct lpfc_iocbq **piocb)
- {
-       struct lpfc_iocbq * nextiocb;
-@@ -2384,13 +2833,29 @@
-       return nextiocb;
- }
++print_synchronous (const char *prefix, const unsigned char *msg) {
++    if (msg[4]) {
++      int Hz = 1000000000 / (msg[3] * 4);
++      int integer = Hz / 1000000;
++      int fraction = (Hz - (integer * 1000000)) / 10000;
++      printk ("%speriod %dns offset %d %d.%02dMHz %s SCSI%s\n",
++          prefix, (int) msg[3] * 4, (int) msg[4], integer, fraction,
++          (((msg[3] * 4) < 200) ? "FAST" : "synchronous"),
++          (((msg[3] * 4) < 200) ? "-II" : ""));
++    } else 
++      printk ("%sasynchronous SCSI\n", prefix);
++}
++
 +/*
-+ * Lockless version of lpfc_sli_issue_iocb.
++ * Function : static void set_synchronous (struct Scsi_Host *host, 
++ *            int target, int sxfer, int scntl3, int now_connected)
++ *
++ * Purpose : reprogram transfers between the selected SCSI initiator and 
++ *    target with the given register values; in the indirect
++ *    select operand, reselection script, and chip registers.
++ *
++ * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id,
++ *    sxfer and scntl3 - NCR registers. now_connected - if non-zero, 
++ *    we should reprogram the registers now too.
++ *
++ *      NOTE:  For 53c710, scntl3 is actually used for SCF bits from
++ *    SBCL, as we don't have a SCNTL3.
 + */
- int
--lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-+__lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-                   struct lpfc_iocbq *piocb, uint32_t flag)
- {
-       struct lpfc_iocbq *nextiocb;
-       IOCB_t *iocb;
-+      if (piocb->iocb_cmpl && (!piocb->vport) &&
-+         (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
-+         (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) {
-+              lpfc_printf_log(phba, KERN_ERR,
-+                              LOG_SLI | LOG_VPORT,
-+                              "%d:1807 IOCB x%x failed. No vport\n",
-+                              phba->brd_no,
-+                              piocb->iocb.ulpCommand);
-+              dump_stack();
-+              return IOCB_ERROR;
-+      }
 +
++static void
++set_synchronous (struct Scsi_Host *host, int target, int sxfer, int scntl3,
++    int now_connected) {
++    NCR53c7x0_local_declare();
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) 
++      host->hostdata[0];
++    u32 *script;
++    NCR53c7x0_local_setup(host);
 +
-       /* If the PCI channel is in offline state, do not post iocbs. */
-       if (unlikely(pci_channel_offline(phba->pcidev)))
-               return IOCB_ERROR;
-@@ -2398,7 +2863,7 @@
-       /*
-        * We should never get an IOCB if we are in a < LINK_DOWN state
-        */
--      if (unlikely(phba->hba_state < LPFC_LINK_DOWN))
-+      if (unlikely(phba->link_state < LPFC_LINK_DOWN))
-               return IOCB_ERROR;
-       /*
-@@ -2408,7 +2873,7 @@
-       if (unlikely(pring->flag & LPFC_STOP_IOCB_MBX))
-               goto iocb_busy;
--      if (unlikely(phba->hba_state == LPFC_LINK_DOWN)) {
-+      if (unlikely(phba->link_state == LPFC_LINK_DOWN)) {
-               /*
-                * Only CREATE_XRI, CLOSE_XRI, and QUE_RING_BUF
-                * can be issued if the link is not up.
-@@ -2436,8 +2901,9 @@
-        * attention events.
-        */
-       } else if (unlikely(pring->ringno == phba->sli.fcp_ring &&
--                 !(phba->sli.sli_flag & LPFC_PROCESS_LA)))
-+                          !(phba->sli.sli_flag & LPFC_PROCESS_LA))) {
-               goto iocb_busy;
++    /* These are eight bit registers */
++    sxfer &= 0xff;
++    scntl3 &= 0xff;
++
++    hostdata->sync[target].sxfer_sanity = sxfer;
++    hostdata->sync[target].scntl3_sanity = scntl3;
++
++/* 
++ * HARD CODED : synchronous script is EIGHT words long.  This 
++ * must agree with 53c7.8xx.h
++ */
++
++    if ((hostdata->chip != 700) && (hostdata->chip != 70066)) {
++      hostdata->sync[target].select_indirect = (1 << target) << 16 |
++              (sxfer << 8);
++      hostdata->sync[target].sscf_710 = scntl3;
++
++      script = (u32 *) hostdata->sync[target].script;
++
++      /* XXX - add NCR53c7x0 code to reprogram SCF bits if we want to */
++      script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY |
++              DCMD_RWRI_OP_MOVE) << 24) |
++              (SBCL_REG << 16) | (scntl3 << 8);
++      script[1] = 0;
++      script += 2;
++
++      script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY |
++          DCMD_RWRI_OP_MOVE) << 24) |
++              (SXFER_REG << 16) | (sxfer << 8);
++      script[1] = 0;
++      script += 2;
++
++#ifdef DEBUG_SYNC_INTR
++      if (hostdata->options & OPTION_DEBUG_DISCONNECT) {
++          script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_INT) << 24) | DBC_TCI_TRUE;
++          script[1] = DEBUG_SYNC_INTR;
++          script += 2;
 +      }
-       while ((iocb = lpfc_sli_next_iocb_slot(phba, pring)) &&
-              (nextiocb = lpfc_sli_next_iocb(phba, pring, &piocb)))
-@@ -2459,13 +2925,28 @@
-  out_busy:
-       if (!(flag & SLI_IOCB_RET_IOCB)) {
--              lpfc_sli_ringtx_put(phba, pring, piocb);
-+              __lpfc_sli_ringtx_put(phba, pring, piocb);
-               return IOCB_SUCCESS;
-       }
-       return IOCB_BUSY;
- }
++#endif
 +
-+int
-+lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-+                  struct lpfc_iocbq *piocb, uint32_t flag)
-+{
-+      unsigned long iflags;
-+      int rc;
++      script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_RETURN) << 24) | DBC_TCI_TRUE;
++      script[1] = 0;
++      script += 2;
++    }
 +
-+      spin_lock_irqsave(&phba->hbalock, iflags);
-+      rc = __lpfc_sli_issue_iocb(phba, pring, piocb, flag);
-+      spin_unlock_irqrestore(&phba->hbalock, iflags);
++    if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) 
++      printk ("scsi%d : target %d sync parameters are sxfer=0x%x, scntl3=0x%x\n",
++      host->host_no, target, sxfer, scntl3);
 +
-+      return rc;
++    if (now_connected) {
++      NCR53c7x0_write8(SBCL_REG, scntl3);
++      NCR53c7x0_write8(SXFER_REG, sxfer);
++    }
 +}
 +
- static int
- lpfc_extra_ring_setup( struct lpfc_hba *phba)
- {
-@@ -2504,7 +2985,7 @@
- int
- lpfc_sli_setup(struct lpfc_hba *phba)
- {
--      int i, totiocb = 0;
-+      int i, totiocbsize = 0;
-       struct lpfc_sli *psli = &phba->sli;
-       struct lpfc_sli_ring *pring;
-@@ -2529,6 +3010,12 @@
-                       pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES;
-                       pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES;
-                       pring->numRiocb += SLI2_IOCB_RSP_R3XTRA_ENTRIES;
-+                      pring->sizeCiocb = (phba->sli_rev == 3) ?
-+                                                      SLI3_IOCB_CMD_SIZE :
-+                                                      SLI2_IOCB_CMD_SIZE;
-+                      pring->sizeRiocb = (phba->sli_rev == 3) ?
-+                                                      SLI3_IOCB_RSP_SIZE :
-+                                                      SLI2_IOCB_RSP_SIZE;
-                       pring->iotag_ctr = 0;
-                       pring->iotag_max =
-                           (phba->cfg_hba_queue_depth * 2);
-@@ -2539,12 +3026,25 @@
-                       /* numCiocb and numRiocb are used in config_port */
-                       pring->numCiocb = SLI2_IOCB_CMD_R1_ENTRIES;
-                       pring->numRiocb = SLI2_IOCB_RSP_R1_ENTRIES;
-+                      pring->sizeCiocb = (phba->sli_rev == 3) ?
-+                                                      SLI3_IOCB_CMD_SIZE :
-+                                                      SLI2_IOCB_CMD_SIZE;
-+                      pring->sizeRiocb = (phba->sli_rev == 3) ?
-+                                                      SLI3_IOCB_RSP_SIZE :
-+                                                      SLI2_IOCB_RSP_SIZE;
-+                      pring->iotag_max = phba->cfg_hba_queue_depth;
-                       pring->num_mask = 0;
-                       break;
-               case LPFC_ELS_RING:     /* ring 2 - ELS / CT */
-                       /* numCiocb and numRiocb are used in config_port */
-                       pring->numCiocb = SLI2_IOCB_CMD_R2_ENTRIES;
-                       pring->numRiocb = SLI2_IOCB_RSP_R2_ENTRIES;
-+                      pring->sizeCiocb = (phba->sli_rev == 3) ?
-+                                                      SLI3_IOCB_CMD_SIZE :
-+                                                      SLI2_IOCB_CMD_SIZE;
-+                      pring->sizeRiocb = (phba->sli_rev == 3) ?
-+                                                      SLI3_IOCB_RSP_SIZE :
-+                                                      SLI2_IOCB_RSP_SIZE;
-                       pring->fast_iotag = 0;
-                       pring->iotag_ctr = 0;
-                       pring->iotag_max = 4096;
-@@ -2575,14 +3075,16 @@
-                           lpfc_ct_unsol_event;
-                       break;
-               }
--              totiocb += (pring->numCiocb + pring->numRiocb);
-+              totiocbsize += (pring->numCiocb * pring->sizeCiocb) +
-+                              (pring->numRiocb * pring->sizeRiocb);
-       }
--      if (totiocb > MAX_SLI2_IOCB) {
-+      if (totiocbsize > MAX_SLIM_IOCB_SIZE) {
-               /* Too many cmd / rsp ring entries in SLI2 SLIM */
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "%d:0462 Too many cmd / rsp ring entries in "
--                              "SLI2 SLIM Data: x%x x%x\n",
--                              phba->brd_no, totiocb, MAX_SLI2_IOCB);
-+                              "SLI2 SLIM Data: x%x x%lx\n",
-+                              phba->brd_no, totiocbsize,
-+                              (unsigned long) MAX_SLIM_IOCB_SIZE);
-       }
-       if (phba->cfg_multi_ring_support == 2)
-               lpfc_extra_ring_setup(phba);
-@@ -2591,15 +3093,16 @@
- }
- int
--lpfc_sli_queue_setup(struct lpfc_hba * phba)
-+lpfc_sli_queue_setup(struct lpfc_hba *phba)
- {
-       struct lpfc_sli *psli;
-       struct lpfc_sli_ring *pring;
-       int i;
-       psli = &phba->sli;
--      spin_lock_irq(phba->host->host_lock);
-+      spin_lock_irq(&phba->hbalock);
-       INIT_LIST_HEAD(&psli->mboxq);
-+      INIT_LIST_HEAD(&psli->mboxq_cmpl);
-       /* Initialize list headers for txq and txcmplq as double linked lists */
-       for (i = 0; i < psli->num_rings; i++) {
-               pring = &psli->ring[i];
-@@ -2612,15 +3115,73 @@
-               INIT_LIST_HEAD(&pring->iocb_continueq);
-               INIT_LIST_HEAD(&pring->postbufq);
-       }
--      spin_unlock_irq(phba->host->host_lock);
--      return (1);
-+      spin_unlock_irq(&phba->hbalock);
-+      return 1;
- }
- int
--lpfc_sli_hba_down(struct lpfc_hba * phba)
-+lpfc_sli_host_down(struct lpfc_vport *vport)
- {
-       LIST_HEAD(completions);
--      struct lpfc_sli *psli;
-+      struct lpfc_hba *phba = vport->phba;
-+      struct lpfc_sli *psli = &phba->sli;
-+      struct lpfc_sli_ring *pring;
-+      struct lpfc_iocbq *iocb, *next_iocb;
-+      int i;
-+      unsigned long flags = 0;
-+      uint16_t prev_pring_flag;
 +
-+      lpfc_cleanup_discovery_resources(vport);
++/*
++ * Function : static int asynchronous (struct Scsi_Host *host, int target)
++ *
++ * Purpose : reprogram between the selected SCSI Host adapter and target 
++ *      (assumed to be currently connected) for asynchronous transfers.
++ *
++ * Inputs : host - SCSI host structure, target - numeric target ID.
++ *
++ * Preconditions : the NCR chip should be in one of the halted states
++ */
++    
++static void
++asynchronous (struct Scsi_Host *host, int target) {
++    NCR53c7x0_local_declare();
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    NCR53c7x0_local_setup(host);
++    set_synchronous (host, target, /* no offset */ 0, hostdata->saved_scntl3,
++      1);
++    printk ("scsi%d : setting target %d to asynchronous SCSI\n",
++      host->host_no, target);
++}
++
++/* 
++ * XXX - do we want to go out of our way (ie, add extra code to selection
++ *    in the NCR53c710/NCR53c720 script) to reprogram the synchronous
++ *    conversion bits, or can we be content in just setting the 
++ *    sxfer bits?  I chose to do so [richard@sleepie.demon.co.uk]
++ */
 +
-+      spin_lock_irqsave(&phba->hbalock, flags);
-+      for (i = 0; i < psli->num_rings; i++) {
-+              pring = &psli->ring[i];
-+              prev_pring_flag = pring->flag;
-+              if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */
-+                      pring->flag |= LPFC_DEFERRED_RING_EVENT;
-+              /*
-+               * Error everything on the txq since these iocbs have not been
-+               * given to the FW yet.
-+               */
-+              list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
-+                      if (iocb->vport != vport)
-+                              continue;
-+                      list_move_tail(&iocb->list, &completions);
-+                      pring->txq_cnt--;
-+              }
++/* Table for NCR53c8xx synchronous values */
 +
-+              /* Next issue ABTS for everything on the txcmplq */
-+              list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq,
-+                                                                      list) {
-+                      if (iocb->vport != vport)
-+                              continue;
-+                      lpfc_sli_issue_abort_iotag(phba, pring, iocb);
-+              }
++/* This table is also correct for 710, allowing that scf=4 is equivalent
++ * of SSCF=0 (ie use DCNTL, divide by 3) for a 50.01-66.00MHz clock.
++ * For any other clock values, we cannot use entries with SCF values of
++ * 4.  I guess that for a 66MHz clock, the slowest it will set is 2MHz,
++ * and for a 50MHz clock, the slowest will be 2.27Mhz.  Should check
++ * that a device doesn't try and negotiate sync below these limits!
++ */
++ 
++static const struct {
++    int div;          /* Total clock divisor * 10 */
++    unsigned char scf;        /* */
++    unsigned char tp; /* 4 + tp = xferp divisor */
++} syncs[] = {
++/*    div     scf     tp      div     scf     tp      div     scf     tp */
++    { 40,     1,      0}, {   50,     1,      1}, {   60,     1,      2}, 
++    { 70,     1,      3}, {   75,     2,      1}, {   80,     1,      4},
++    { 90,     1,      5}, {   100,    1,      6}, {   105,    2,      3},
++    { 110,    1,      7}, {   120,    2,      4}, {   135,    2,      5},
++    { 140,    3,      3}, {   150,    2,      6}, {   160,    3,      4},
++    { 165,    2,      7}, {   180,    3,      5}, {   200,    3,      6},
++    { 210,    4,      3}, {   220,    3,      7}, {   240,    4,      4},
++    { 270,    4,      5}, {   300,    4,      6}, {   330,    4,      7}
++};
++
++/*
++ * Function : static void synchronous (struct Scsi_Host *host, int target, 
++ *    char *msg)
++ *
++ * Purpose : reprogram transfers between the selected SCSI initiator and 
++ *    target for synchronous SCSI transfers such that the synchronous 
++ *    offset is less than that requested and period at least as long 
++ *    as that requested.  Also modify *msg such that it contains 
++ *    an appropriate response. 
++ *
++ * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id,
++ *    msg - synchronous transfer request.
++ */
++
++
++static void
++synchronous (struct Scsi_Host *host, int target, char *msg) {
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    int desire, divisor, i, limit;
++    unsigned char scntl3, sxfer;
++/* The diagnostic message fits on one line, even with max. width integers */
++    char buf[80];
++
++/* Desired transfer clock in Hz */
++    desire = 1000000000L / (msg[3] * 4);
++/* Scale the available SCSI clock by 10 so we get tenths */
++    divisor = (hostdata->scsi_clock * 10) / desire;
++
++/* NCR chips can handle at most an offset of 8 */
++    if (msg[4] > 8)
++      msg[4] = 8;
++
++    if (hostdata->options & OPTION_DEBUG_SDTR)
++      printk("scsi%d : optimal synchronous divisor of %d.%01d\n",
++          host->host_no, divisor / 10, divisor % 10);
++
++    limit = ARRAY_SIZE(syncs) - 1;
++    for (i = 0; (i < limit) && (divisor > syncs[i].div); ++i);
++
++    if (hostdata->options & OPTION_DEBUG_SDTR)
++      printk("scsi%d : selected synchronous divisor of %d.%01d\n",
++          host->host_no, syncs[i].div / 10, syncs[i].div % 10);
++
++    msg[3] = ((1000000000L / hostdata->scsi_clock) * syncs[i].div / 10 / 4);
++
++    if (hostdata->options & OPTION_DEBUG_SDTR)
++      printk("scsi%d : selected synchronous period of %dns\n", host->host_no,
++          msg[3] * 4);
++
++    scntl3 = syncs[i].scf;
++    sxfer = (msg[4] << SXFER_MO_SHIFT) | (syncs[i].tp << 4);
++    if (hostdata->options & OPTION_DEBUG_SDTR)
++      printk ("scsi%d : sxfer=0x%x scntl3=0x%x\n", 
++          host->host_no, (int) sxfer, (int) scntl3);
++    set_synchronous (host, target, sxfer, scntl3, 1);
++    sprintf (buf, "scsi%d : setting target %d to ", host->host_no, target);
++    print_synchronous (buf, msg);
++}
++
++/* 
++ * Function : static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host,
++ *    struct NCR53c7x0_cmd *cmd)
++ *
++ * Purpose :  Handler for INT generated instructions for the 
++ *    NCR53c810/820 SCSI SCRIPT
++ *
++ * Inputs : host - pointer to this host adapter's structure,
++ *    cmd - pointer to the command (if any) dsa was pointing 
++ *    to.
++ *
++ */
 +
-+              pring->flag = prev_pring_flag;
-+      }
++static int 
++NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct 
++    NCR53c7x0_cmd *cmd) {
++    NCR53c7x0_local_declare();
++    int print;
++    Scsi_Cmnd *c = cmd ? cmd->cmd : NULL;
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];              
++    u32 dsps,*dsp;    /* Argument of the INT instruction */
 +
-+      spin_unlock_irqrestore(&phba->hbalock, flags);
++    NCR53c7x0_local_setup(host);
++    dsps = NCR53c7x0_read32(DSPS_REG);
++    dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG));
 +
-+      while (!list_empty(&completions)) {
-+              list_remove_head(&completions, iocb, struct lpfc_iocbq, list);
++    /* RGH 150597:  Frig.  Commands which fail with Check Condition are
++     * Flagged as successful - hack dsps to indicate check condition */
++#if 0
++    /* RGH 200597:  Need to disable for BVME6000, as it gets Check Conditions
++     * and then dies.  Seems to handle Check Condition at startup, but
++     * not mid kernel build. */
++    if (dsps == A_int_norm_emulateintfly && cmd && cmd->result == 2)
++        dsps = A_int_err_check_condition;
++#endif
 +
-+              if (!iocb->iocb_cmpl)
-+                      lpfc_sli_release_iocbq(phba, iocb);
-+              else {
-+                      iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
-+                      iocb->iocb.un.ulpWord[4] = IOERR_SLI_DOWN;
-+                      (iocb->iocb_cmpl) (phba, iocb, iocb);
-+              }
++    if (hostdata->options & OPTION_DEBUG_INTR) 
++      printk ("scsi%d : DSPS = 0x%x\n", host->host_no, dsps);
++
++    switch (dsps) {
++    case A_int_msg_1:
++      print = 1;
++      switch (hostdata->msg_buf[0]) {
++      /* 
++       * Unless we've initiated synchronous negotiation, I don't
++       * think that this should happen.
++       */
++      case MESSAGE_REJECT:
++          hostdata->dsp = hostdata->script + hostdata->E_accept_message /
++              sizeof(u32);
++          hostdata->dsp_changed = 1;
++          if (cmd && (cmd->flags & CMD_FLAG_SDTR)) {
++              printk ("scsi%d : target %d rejected SDTR\n", host->host_no, 
++                  c->device->id);
++              cmd->flags &= ~CMD_FLAG_SDTR;
++              asynchronous (host, c->device->id);
++              print = 0;
++          } 
++          break;
++      case INITIATE_RECOVERY:
++          printk ("scsi%d : extended contingent allegiance not supported yet, rejecting\n",
++              host->host_no);
++          /* Fall through to default */
++          hostdata->dsp = hostdata->script + hostdata->E_reject_message /
++              sizeof(u32);
++          hostdata->dsp_changed = 1;
++          break;
++      default:
++          printk ("scsi%d : unsupported message, rejecting\n",
++              host->host_no);
++          hostdata->dsp = hostdata->script + hostdata->E_reject_message /
++              sizeof(u32);
++          hostdata->dsp_changed = 1;
++      }
++      if (print) {
++          printk ("scsi%d : received message", host->host_no);
++          if (c) 
++              printk (" from target %d lun %d ", c->device->id, c->device->lun);
++          spi_print_msg((unsigned char *) hostdata->msg_buf);
++          printk("\n");
 +      }
-+      return 1;
-+}
++      
++      return SPECIFIC_INT_NOTHING;
 +
-+int
-+lpfc_sli_hba_down(struct lpfc_hba *phba)
-+{
-+      LIST_HEAD(completions);
-+      struct lpfc_sli *psli = &phba->sli;
-       struct lpfc_sli_ring *pring;
-       LPFC_MBOXQ_t *pmb;
-       struct lpfc_iocbq *iocb;
-@@ -2628,12 +3189,14 @@
-       int i;
-       unsigned long flags = 0;
--      psli = &phba->sli;
-       lpfc_hba_down_prep(phba);
--      spin_lock_irqsave(phba->host->host_lock, flags);
-+      lpfc_fabric_abort_hba(phba);
 +
-+      spin_lock_irqsave(&phba->hbalock, flags);
-       for (i = 0; i < psli->num_rings; i++) {
-               pring = &psli->ring[i];
-+              if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */
-               pring->flag |= LPFC_DEFERRED_RING_EVENT;
-               /*
-@@ -2644,51 +3207,50 @@
-               pring->txq_cnt = 0;
-       }
--      spin_unlock_irqrestore(phba->host->host_lock, flags);
-+      spin_unlock_irqrestore(&phba->hbalock, flags);
-       while (!list_empty(&completions)) {
--              iocb = list_get_first(&completions, struct lpfc_iocbq, list);
-+              list_remove_head(&completions, iocb, struct lpfc_iocbq, list);
-               cmd = &iocb->iocb;
--              list_del(&iocb->list);
--              if (iocb->iocb_cmpl) {
-+              if (!iocb->iocb_cmpl)
-+                      lpfc_sli_release_iocbq(phba, iocb);
-+              else {
-                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-                       cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
-                       (iocb->iocb_cmpl) (phba, iocb, iocb);
--              } else
--                      lpfc_sli_release_iocbq(phba, iocb);
-+              }
-       }
-       /* Return any active mbox cmds */
-       del_timer_sync(&psli->mbox_tmo);
--      spin_lock_irqsave(phba->host->host_lock, flags);
--      phba->work_hba_events &= ~WORKER_MBOX_TMO;
-+      spin_lock_irqsave(&phba->hbalock, flags);
++    case A_int_msg_sdtr:
++/*
++ * At this point, hostdata->msg_buf contains
++ * 0 EXTENDED MESSAGE
++ * 1 length 
++ * 2 SDTR
++ * 3 period * 4ns
++ * 4 offset
++ */
++
++      if (cmd) {
++          char buf[80];
++          sprintf (buf, "scsi%d : target %d %s ", host->host_no, c->device->id,
++              (cmd->flags & CMD_FLAG_SDTR) ? "accepting" : "requesting");
++          print_synchronous (buf, (unsigned char *) hostdata->msg_buf);
++
++      /* 
++       * Initiator initiated, won't happen unless synchronous 
++       *      transfers are enabled.  If we get a SDTR message in
++       *      response to our SDTR, we should program our parameters
++       *      such that 
++       *              offset <= requested offset
++       *              period >= requested period                      
++       */
++          if (cmd->flags & CMD_FLAG_SDTR) {
++              cmd->flags &= ~CMD_FLAG_SDTR; 
++              if (hostdata->msg_buf[4]) 
++                  synchronous (host, c->device->id, (unsigned char *) 
++                      hostdata->msg_buf);
++              else 
++                  asynchronous (host, c->device->id);
++              hostdata->dsp = hostdata->script + hostdata->E_accept_message /
++                  sizeof(u32);
++              hostdata->dsp_changed = 1;
++              return SPECIFIC_INT_NOTHING;
++          } else {
++              if (hostdata->options & OPTION_SYNCHRONOUS)  {
++                  cmd->flags |= CMD_FLAG_DID_SDTR;
++                  synchronous (host, c->device->id, (unsigned char *) 
++                      hostdata->msg_buf);
++              } else {
++                  hostdata->msg_buf[4] = 0;           /* 0 offset = async */
++                  asynchronous (host, c->device->id);
++              }
++              patch_dsa_32 (cmd->dsa, dsa_msgout_other, 0, 5);
++              patch_dsa_32 (cmd->dsa, dsa_msgout_other, 1, (u32) 
++                  virt_to_bus ((void *)&hostdata->msg_buf));
++              hostdata->dsp = hostdata->script + 
++                  hostdata->E_respond_message / sizeof(u32);
++              hostdata->dsp_changed = 1;
++          }
++          return SPECIFIC_INT_NOTHING;
++      }
++      /* Fall through to abort if we couldn't find a cmd, and 
++         therefore a dsa structure to twiddle */
++    case A_int_msg_wdtr:
++      hostdata->dsp = hostdata->script + hostdata->E_reject_message /
++          sizeof(u32);
++      hostdata->dsp_changed = 1;
++      return SPECIFIC_INT_NOTHING;
++    case A_int_err_unexpected_phase:
++      if (hostdata->options & OPTION_DEBUG_INTR) 
++          printk ("scsi%d : unexpected phase\n", host->host_no);
++      return SPECIFIC_INT_ABORT;
++    case A_int_err_selected:
++      if ((hostdata->chip / 100) == 8)
++          printk ("scsi%d : selected by target %d\n", host->host_no,
++              (int) NCR53c7x0_read8(SDID_REG_800) &7);
++      else
++            printk ("scsi%d : selected by target LCRC=0x%02x\n", host->host_no,
++                (int) NCR53c7x0_read8(LCRC_REG_10));
++      hostdata->dsp = hostdata->script + hostdata->E_target_abort / 
++          sizeof(u32);
++      hostdata->dsp_changed = 1;
++      return SPECIFIC_INT_NOTHING;
++    case A_int_err_unexpected_reselect:
++      if ((hostdata->chip / 100) == 8)
++          printk ("scsi%d : unexpected reselect by target %d lun %d\n", 
++              host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & 7,
++              hostdata->reselected_identify & 7);
++      else
++            printk ("scsi%d : unexpected reselect LCRC=0x%02x\n", host->host_no,
++                (int) NCR53c7x0_read8(LCRC_REG_10));
++      hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
++          sizeof(u32);
++      hostdata->dsp_changed = 1;
++      return SPECIFIC_INT_NOTHING;
++/*
++ * Since contingent allegiance conditions are cleared by the next 
++ * command issued to a target, we must issue a REQUEST SENSE 
++ * command after receiving a CHECK CONDITION status, before
++ * another command is issued.
++ * 
++ * Since this NCR53c7x0_cmd will be freed after use, we don't 
++ * care if we step on the various fields, so modify a few things.
++ */
++    case A_int_err_check_condition: 
++#if 0
++      if (hostdata->options & OPTION_DEBUG_INTR) 
++#endif
++          printk ("scsi%d : CHECK CONDITION\n", host->host_no);
++      if (!c) {
++          printk("scsi%d : CHECK CONDITION with no SCSI command\n",
++              host->host_no);
++          return SPECIFIC_INT_PANIC;
++      }
 +
-+      spin_lock(&phba->pport->work_port_lock);
-+      phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
-+      spin_unlock(&phba->pport->work_port_lock);
++      /* 
++       * FIXME : this uses the normal one-byte selection message.
++       *      We may want to renegotiate for synchronous & WIDE transfers
++       *      since these could be the crux of our problem.
++       *
++       hostdata->NOP_insn* FIXME : once SCSI-II tagged queuing is implemented, we'll
++       *      have to set this up so that the rest of the DSA
++       *      agrees with this being an untagged queue'd command.
++       */
 +
-       if (psli->mbox_active) {
--              pmb = psli->mbox_active;
--              pmb->mb.mbxStatus = MBX_NOT_FINISHED;
--              if (pmb->mbox_cmpl) {
--                      spin_unlock_irqrestore(phba->host->host_lock, flags);
--                      pmb->mbox_cmpl(phba,pmb);
--                      spin_lock_irqsave(phba->host->host_lock, flags);
--              }
--      }
--      psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-+              list_add_tail(&psli->mbox_active->list, &completions);
-       psli->mbox_active = NULL;
-+              psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-+      }
--      /* Return any pending mbox cmds */
--      while ((pmb = lpfc_mbox_get(phba)) != NULL) {
-+      /* Return any pending or completed mbox cmds */
-+      list_splice_init(&phba->sli.mboxq, &completions);
-+      list_splice_init(&phba->sli.mboxq_cmpl, &completions);
-+      INIT_LIST_HEAD(&psli->mboxq);
-+      INIT_LIST_HEAD(&psli->mboxq_cmpl);
++      patch_dsa_32 (cmd->dsa, dsa_msgout, 0, 1);
 +
-+      spin_unlock_irqrestore(&phba->hbalock, flags);
++      /* 
++       * Modify the table indirect for COMMAND OUT phase, since 
++       * Request Sense is a six byte command.
++       */
 +
-+      while (!list_empty(&completions)) {
-+              list_remove_head(&completions, pmb, LPFC_MBOXQ_t, list);
-               pmb->mb.mbxStatus = MBX_NOT_FINISHED;
-               if (pmb->mbox_cmpl) {
--                      spin_unlock_irqrestore(phba->host->host_lock, flags);
-                       pmb->mbox_cmpl(phba,pmb);
--                      spin_lock_irqsave(phba->host->host_lock, flags);
-               }
-       }
--
--      INIT_LIST_HEAD(&psli->mboxq);
--
--      spin_unlock_irqrestore(phba->host->host_lock, flags);
--
-       return 1;
- }
-@@ -2710,14 +3272,15 @@
- }
- int
--lpfc_sli_ringpostbuf_put(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
--                       struct lpfc_dmabuf * mp)
-+lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-+                       struct lpfc_dmabuf *mp)
- {
-       /* Stick struct lpfc_dmabuf at end of postbufq so driver can look it up
-          later */
-+      spin_lock_irq(&phba->hbalock);
-       list_add_tail(&mp->list, &pring->postbufq);
--
-       pring->postbufq_cnt++;
-+      spin_unlock_irq(&phba->hbalock);
-       return 0;
- }
-@@ -2730,14 +3293,17 @@
-       struct list_head *slp = &pring->postbufq;
-       /* Search postbufq, from the begining, looking for a match on phys */
-+      spin_lock_irq(&phba->hbalock);
-       list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
-               if (mp->phys == phys) {
-                       list_del_init(&mp->list);
-                       pring->postbufq_cnt--;
-+                      spin_unlock_irq(&phba->hbalock);
-                       return mp;
-               }
-       }
-+      spin_unlock_irq(&phba->hbalock);
-       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                       "%d:0410 Cannot find virtual addr for mapped buf on "
-                       "ring %d Data x%llx x%p x%p x%x\n",
-@@ -2747,92 +3313,110 @@
- }
- static void
--lpfc_sli_abort_els_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                      struct lpfc_iocbq * rspiocb)
-+lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                      struct lpfc_iocbq *rspiocb)
- {
--      IOCB_t *irsp;
-+      IOCB_t *irsp = &rspiocb->iocb;
-       uint16_t abort_iotag, abort_context;
--      struct lpfc_iocbq *abort_iocb, *rsp_ab_iocb;
-+      struct lpfc_iocbq *abort_iocb;
-       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
-       abort_iocb = NULL;
--      irsp = &rspiocb->iocb;
--
--      spin_lock_irq(phba->host->host_lock);
-       if (irsp->ulpStatus) {
-               abort_context = cmdiocb->iocb.un.acxri.abortContextTag;
-               abort_iotag = cmdiocb->iocb.un.acxri.abortIoTag;
-+              spin_lock_irq(&phba->hbalock);
-               if (abort_iotag != 0 && abort_iotag <= phba->sli.last_iotag)
-                       abort_iocb = phba->sli.iocbq_lookup[abort_iotag];
--              lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
--                              "%d:0327 Cannot abort els iocb %p"
--                              " with tag %x context %x\n",
--                              phba->brd_no, abort_iocb,
--                              abort_iotag, abort_context);
-+              lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_SLI,
-+                              "%d:0327 Cannot abort els iocb %p "
-+                              "with tag %x context %x, abort status %x, "
-+                              "abort code %x\n",
-+                              phba->brd_no, abort_iocb, abort_iotag,
-+                              abort_context, irsp->ulpStatus,
-+                              irsp->un.ulpWord[4]);
-               /*
-                * make sure we have the right iocbq before taking it
-                * off the txcmplq and try to call completion routine.
-                */
--              if (abort_iocb &&
--                  abort_iocb->iocb.ulpContext == abort_context &&
--                  abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) {
--                      list_del(&abort_iocb->list);
-+              if (!abort_iocb ||
-+                  abort_iocb->iocb.ulpContext != abort_context ||
-+                  (abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) == 0)
-+                      spin_unlock_irq(&phba->hbalock);
-+              else {
-+                      list_del_init(&abort_iocb->list);
-                       pring->txcmplq_cnt--;
-+                      spin_unlock_irq(&phba->hbalock);
--                      rsp_ab_iocb = lpfc_sli_get_iocbq(phba);
--                      if (rsp_ab_iocb == NULL)
--                              lpfc_sli_release_iocbq(phba, abort_iocb);
--                      else {
--                              abort_iocb->iocb_flag &=
--                                      ~LPFC_DRIVER_ABORTED;
--                              rsp_ab_iocb->iocb.ulpStatus =
--                                      IOSTAT_LOCAL_REJECT;
--                              rsp_ab_iocb->iocb.un.ulpWord[4] =
--                                      IOERR_SLI_ABORTED;
--                              spin_unlock_irq(phba->host->host_lock);
--                              (abort_iocb->iocb_cmpl)
--                                      (phba, abort_iocb, rsp_ab_iocb);
--                              spin_lock_irq(phba->host->host_lock);
--                              lpfc_sli_release_iocbq(phba, rsp_ab_iocb);
--                      }
-+                      abort_iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED;
-+                      abort_iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
-+                      abort_iocb->iocb.un.ulpWord[4] = IOERR_SLI_ABORTED;
-+                      (abort_iocb->iocb_cmpl)(phba, abort_iocb, abort_iocb);
-               }
-       }
-       lpfc_sli_release_iocbq(phba, cmdiocb);
--      spin_unlock_irq(phba->host->host_lock);
-+      return;
-+}
++      patch_dsa_32 (cmd->dsa, dsa_cmdout, 0, 6);
++
++        /*
++         * The CDB is now mirrored in our local non-cached
++         * structure, but keep the old structure up to date as well,
++         * just in case anyone looks at it.
++         */
 +
-+static void
-+lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                   struct lpfc_iocbq *rspiocb)
-+{
-+      IOCB_t *irsp = &rspiocb->iocb;
-+
-+      /* ELS cmd tag <ulpIoTag> completes */
-+      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-+                      "%d (X):0133 Ignoring ELS cmd tag x%x completion Data: "
-+                      "x%x x%x x%x\n",
-+                      phba->brd_no, irsp->ulpIoTag, irsp->ulpStatus,
-+                      irsp->un.ulpWord[4], irsp->ulpTimeout);
-+      if (cmdiocb->iocb.ulpCommand == CMD_GEN_REQUEST64_CR)
-+              lpfc_ct_free_iocb(phba, cmdiocb);
-+      else
-+              lpfc_els_free_iocb(phba, cmdiocb);
-       return;
- }
- int
--lpfc_sli_issue_abort_iotag(struct lpfc_hba * phba,
--                         struct lpfc_sli_ring * pring,
--                         struct lpfc_iocbq * cmdiocb)
-+lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-+                         struct lpfc_iocbq *cmdiocb)
- {
-+      struct lpfc_vport *vport = cmdiocb->vport;
-       struct lpfc_iocbq *abtsiocbp;
-       IOCB_t *icmd = NULL;
-       IOCB_t *iabt = NULL;
-       int retval = IOCB_ERROR;
--      /* There are certain command types we don't want
--       * to abort.
 +      /*
-+       * There are certain command types we don't want to abort.  And we
-+       * don't want to abort commands that are already in the process of
-+       * being aborted.
-        */
-       icmd = &cmdiocb->iocb;
--      if ((icmd->ulpCommand == CMD_ABORT_XRI_CN) ||
--          (icmd->ulpCommand == CMD_CLOSE_XRI_CN))
-+      if (icmd->ulpCommand == CMD_ABORT_XRI_CN ||
-+          icmd->ulpCommand == CMD_CLOSE_XRI_CN ||
-+          (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0)
-               return 0;
--      /* If we're unloading, interrupts are disabled so we
--       * need to cleanup the iocb here.
-+      /* If we're unloading, don't abort iocb on the ELS ring, but change the
-+       * callback so that nothing happens when it finishes.
-        */
--      if (phba->fc_flag & FC_UNLOADING)
-+      if ((vport->load_flag & FC_UNLOADING) &&
-+          (pring->ringno == LPFC_ELS_RING)) {
-+              if (cmdiocb->iocb_flag & LPFC_IO_FABRIC)
-+                      cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl;
-+              else
-+                      cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl;
-               goto abort_iotag_exit;
-+      }
-       /* issue ABTS for this IOCB based on iotag */
--      abtsiocbp = lpfc_sli_get_iocbq(phba);
-+      abtsiocbp = __lpfc_sli_get_iocbq(phba);
-       if (abtsiocbp == NULL)
-               return 0;
-@@ -2848,7 +3432,7 @@
-       iabt->ulpLe = 1;
-       iabt->ulpClass = icmd->ulpClass;
--      if (phba->hba_state >= LPFC_LINK_UP)
-+      if (phba->link_state >= LPFC_LINK_UP)
-               iabt->ulpCommand = CMD_ABORT_XRI_CN;
-       else
-               iabt->ulpCommand = CMD_CLOSE_XRI_CN;
-@@ -2856,32 +3440,20 @@
-       abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl;
-       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
--                      "%d:0339 Abort xri x%x, original iotag x%x, abort "
--                      "cmd iotag x%x\n",
--                      phba->brd_no, iabt->un.acxri.abortContextTag,
-+                      "%d (%d):0339 Abort xri x%x, original iotag x%x, "
-+                      "abort cmd iotag x%x\n",
-+                      phba->brd_no, vport->vpi,
-+                      iabt->un.acxri.abortContextTag,
-                       iabt->un.acxri.abortIoTag, abtsiocbp->iotag);
--      retval = lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
-+      retval = __lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
- abort_iotag_exit:
--
--      /* If we could not issue an abort dequeue the iocb and handle
--       * the completion here.
++       * XXX Need to worry about data buffer alignment/cache state
++       * XXX here, but currently never get A_int_err_check_condition,
++       * XXX so ignore problem for now.
++         */
++      cmd->cmnd[0] = c->cmnd[0] = REQUEST_SENSE;
++      cmd->cmnd[0] = c->cmnd[1] &= 0xe0;      /* Zero all but LUN */
++      cmd->cmnd[0] = c->cmnd[2] = 0;
++      cmd->cmnd[0] = c->cmnd[3] = 0;
++      cmd->cmnd[0] = c->cmnd[4] = sizeof(c->sense_buffer);
++      cmd->cmnd[0] = c->cmnd[5] = 0; 
++
 +      /*
-+       * Caller to this routine should check for IOCB_ERROR
-+       * and handle it properly.  This routine no longer removes
-+       * iocb off txcmplq and call compl in case of IOCB_ERROR.
-        */
--      if (retval == IOCB_ERROR) {
--              list_del(&cmdiocb->list);
--              pring->txcmplq_cnt--;
--
--              if (cmdiocb->iocb_cmpl) {
--                      icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
--                      icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
--                      spin_unlock_irq(phba->host->host_lock);
--                      (cmdiocb->iocb_cmpl) (phba, cmdiocb, cmdiocb);
--                      spin_lock_irq(phba->host->host_lock);
--              } else
--                      lpfc_sli_release_iocbq(phba, cmdiocb);
--      }
--
--      return 1;
-+      return retval;
- }
- static int
-@@ -2947,14 +3519,10 @@
- }
- void
--lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
--                         struct lpfc_iocbq * rspiocb)
-+lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-+                      struct lpfc_iocbq *rspiocb)
- {
--      unsigned long iflags;
--
--      spin_lock_irqsave(phba->host->host_lock, iflags);
-       lpfc_sli_release_iocbq(phba, cmdiocb);
--      spin_unlock_irqrestore(phba->host->host_lock, iflags);
-       return;
- }
-@@ -2972,8 +3540,8 @@
-       for (i = 1; i <= phba->sli.last_iotag; i++) {
-               iocbq = phba->sli.iocbq_lookup[i];
--              if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id,
--                                              0, abort_cmd) != 0)
-+              if (lpfc_sli_validate_fcp_iocb(iocbq, tgt_id, lun_id, 0,
-+                                             abort_cmd) != 0)
-                       continue;
-               /* issue ABTS for this IOCB based on iotag */
-@@ -2989,8 +3557,9 @@
-               abtsiocb->iocb.un.acxri.abortIoTag = cmd->ulpIoTag;
-               abtsiocb->iocb.ulpLe = 1;
-               abtsiocb->iocb.ulpClass = cmd->ulpClass;
-+              abtsiocb->vport = phba->pport;
--              if (phba->hba_state >= LPFC_LINK_UP)
-+              if (lpfc_is_link_up(phba))
-                       abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN;
-               else
-                       abtsiocb->iocb.ulpCommand = CMD_CLOSE_XRI_CN;
-@@ -3016,16 +3585,16 @@
-       wait_queue_head_t *pdone_q;
-       unsigned long iflags;
--      spin_lock_irqsave(phba->host->host_lock, iflags);
-+      spin_lock_irqsave(&phba->hbalock, iflags);
-       cmdiocbq->iocb_flag |= LPFC_IO_WAKE;
-       if (cmdiocbq->context2 && rspiocbq)
-               memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb,
-                      &rspiocbq->iocb, sizeof(IOCB_t));
-       pdone_q = cmdiocbq->context_un.wait_queue;
--      spin_unlock_irqrestore(phba->host->host_lock, iflags);
-       if (pdone_q)
-               wake_up(pdone_q);
-+      spin_unlock_irqrestore(&phba->hbalock, iflags);
-       return;
- }
-@@ -3035,11 +3604,12 @@
-  * lpfc_sli_issue_call since the wake routine sets a unique value and by
-  * definition this is a wait function.
-  */
++       * Disable dataout phase, and program datain to transfer to the 
++       * sense buffer, and add a jump to other_transfer after the 
++       * command so overflow/underrun conditions are detected.
++       */
 +
- int
--lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
--                       struct lpfc_sli_ring * pring,
--                       struct lpfc_iocbq * piocb,
--                       struct lpfc_iocbq * prspiocbq,
-+lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
-+                       struct lpfc_sli_ring *pring,
-+                       struct lpfc_iocbq *piocb,
-+                       struct lpfc_iocbq *prspiocbq,
-                        uint32_t timeout)
- {
-       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
-@@ -3071,11 +3641,9 @@
-       retval = lpfc_sli_issue_iocb(phba, pring, piocb, 0);
-       if (retval == IOCB_SUCCESS) {
-               timeout_req = timeout * HZ;
--              spin_unlock_irq(phba->host->host_lock);
-               timeleft = wait_event_timeout(done_q,
-                               piocb->iocb_flag & LPFC_IO_WAKE,
-                               timeout_req);
--              spin_lock_irq(phba->host->host_lock);
-               if (piocb->iocb_flag & LPFC_IO_WAKE) {
-                       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-@@ -3117,16 +3685,16 @@
- }
- int
--lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
-+lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
-                        uint32_t timeout)
- {
-       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
-       int retval;
-+      unsigned long flag;
-       /* The caller must leave context1 empty. */
--      if (pmboxq->context1 != 0) {
--              return (MBX_NOT_FINISHED);
--      }
-+      if (pmboxq->context1 != 0)
-+              return MBX_NOT_FINISHED;
-       /* setup wake call as IOCB callback */
-       pmboxq->mbox_cmpl = lpfc_sli_wake_mbox_wait;
-@@ -3141,6 +3709,7 @@
-                               pmboxq->mbox_flag & LPFC_MBX_WAKE,
-                               timeout * HZ);
-+              spin_lock_irqsave(&phba->hbalock, flag);
-               pmboxq->context1 = NULL;
-               /*
-                * if LPFC_MBX_WAKE flag is set the mailbox is completed
-@@ -3148,8 +3717,11 @@
-                */
-               if (pmboxq->mbox_flag & LPFC_MBX_WAKE)
-                       retval = MBX_SUCCESS;
--              else
++      patch_dsa_32 (cmd->dsa, dsa_dataout, 0, 
++          virt_to_bus(hostdata->script) + hostdata->E_other_transfer);
++      patch_dsa_32 (cmd->dsa, dsa_datain, 0, 
++          virt_to_bus(cmd->data_transfer_start));
++      cmd->data_transfer_start[0] = (((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | 
++          DCMD_BMI_IO)) << 24) | sizeof(c->sense_buffer);
++      cmd->data_transfer_start[1] = (u32) virt_to_bus(c->sense_buffer);
++
++      cmd->data_transfer_start[2] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) 
++          << 24) | DBC_TCI_TRUE;
++      cmd->data_transfer_start[3] = (u32) virt_to_bus(hostdata->script) + 
++          hostdata->E_other_transfer;
++
++      /*
++       * Currently, this command is flagged as completed, ie 
++       * it has valid status and message data.  Reflag it as
++       * incomplete.  Q - need to do something so that original
++       * status, etc are used.
++       */
++
++      cmd->result = cmd->cmd->result = 0xffff;                
++
++      /* 
++       * Restart command as a REQUEST SENSE.
++       */
++      hostdata->dsp = (u32 *) hostdata->script + hostdata->E_select /
++          sizeof(u32);
++      hostdata->dsp_changed = 1;
++      return SPECIFIC_INT_NOTHING;
++    case A_int_debug_break:
++      return SPECIFIC_INT_BREAK;
++    case A_int_norm_aborted:
++      hostdata->dsp = (u32 *) hostdata->schedule;
++      hostdata->dsp_changed = 1;
++      if (cmd)
++          abnormal_finished (cmd, DID_ERROR << 16);
++      return SPECIFIC_INT_NOTHING;
++    case A_int_norm_emulateintfly:
++      NCR53c7x0_intfly(host);
++      return SPECIFIC_INT_NOTHING;
++    case A_int_test_1:
++    case A_int_test_2:
++      hostdata->idle = 1;
++      hostdata->test_completed = (dsps - A_int_test_1) / 0x00010000 + 1;
++      if (hostdata->options & OPTION_DEBUG_INTR)
++          printk("scsi%d : test%d complete\n", host->host_no,
++              hostdata->test_completed);
++      return SPECIFIC_INT_NOTHING;
++#ifdef A_int_debug_reselected_ok
++    case A_int_debug_reselected_ok:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
++              OPTION_DEBUG_DISCONNECT)) {
++          /* 
++           * Note - this dsa is not based on location relative to 
++           * the command structure, but to location relative to the 
++           * DSA register 
++           */ 
++          u32 *dsa;
++          dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG));
++
++          printk("scsi%d : reselected_ok (DSA = 0x%x (virt 0x%p)\n", 
++              host->host_no, NCR53c7x0_read32(DSA_REG), dsa);
++          printk("scsi%d : resume address is 0x%x (virt 0x%p)\n",
++                  host->host_no, cmd->saved_data_pointer,
++                  bus_to_virt(cmd->saved_data_pointer));
++          print_insn (host, hostdata->script + Ent_reselected_ok / 
++                  sizeof(u32), "", 1);
++          if ((hostdata->chip / 100) == 8)
++              printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n",
++                  host->host_no, NCR53c7x0_read8(SXFER_REG),
++                  NCR53c7x0_read8(SCNTL3_REG_800));
++          else
++              printk ("scsi%d : sxfer=0x%x, cannot read SBCL\n",
++                  host->host_no, NCR53c7x0_read8(SXFER_REG));
++          if (c) {
++              print_insn (host, (u32 *) 
++                  hostdata->sync[c->device->id].script, "", 1);
++              print_insn (host, (u32 *) 
++                  hostdata->sync[c->device->id].script + 2, "", 1);
++          }
++      }
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_reselect_check
++    case A_int_debug_reselect_check:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
++          u32 *dsa;
++#if 0
++          u32 *code;
++#endif
++          /* 
++           * Note - this dsa is not based on location relative to 
++           * the command structure, but to location relative to the 
++           * DSA register 
++           */ 
++          dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG));
++          printk("scsi%d : reselected_check_next (DSA = 0x%lx (virt 0x%p))\n",
++              host->host_no, virt_to_bus(dsa), dsa);
++          if (dsa) {
++              printk("scsi%d : resume address is 0x%x (virt 0x%p)\n",
++                  host->host_no, cmd->saved_data_pointer,
++                  bus_to_virt (cmd->saved_data_pointer));
++#if 0
++              printk("scsi%d : template code :\n", host->host_no);
++              for (code = dsa + (Ent_dsa_code_check_reselect - Ent_dsa_zero) 
++                  / sizeof(u32); code < (dsa + Ent_dsa_zero / sizeof(u32)); 
++                  code += print_insn (host, code, "", 1));
++#endif
++          }
++          print_insn (host, hostdata->script + Ent_reselected_ok / 
++                  sizeof(u32), "", 1);
++      }
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_dsa_schedule
++    case A_int_debug_dsa_schedule:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
++          u32 *dsa;
++          /* 
++           * Note - this dsa is not based on location relative to 
++           * the command structure, but to location relative to the 
++           * DSA register 
++           */ 
++          dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG));
++          printk("scsi%d : dsa_schedule (old DSA = 0x%lx (virt 0x%p))\n", 
++              host->host_no, virt_to_bus(dsa), dsa);
++          if (dsa) 
++              printk("scsi%d : resume address is 0x%x (virt 0x%p)\n"
++                     "         (temp was 0x%x (virt 0x%p))\n",
++                  host->host_no, cmd->saved_data_pointer,
++                  bus_to_virt (cmd->saved_data_pointer),
++                  NCR53c7x0_read32 (TEMP_REG),
++                  bus_to_virt (NCR53c7x0_read32(TEMP_REG)));
++      }
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_scheduled
++    case A_int_debug_scheduled:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
++          printk("scsi%d : new I/O 0x%x (virt 0x%p) scheduled\n", 
++              host->host_no, NCR53c7x0_read32(DSA_REG),
++              bus_to_virt(NCR53c7x0_read32(DSA_REG)));
++      }
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_idle
++    case A_int_debug_idle:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
++          printk("scsi%d : idle\n", host->host_no);
++      }
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_cmd
++    case A_int_debug_cmd:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
++          printk("scsi%d : command sent\n");
++      }
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_dsa_loaded
++    case A_int_debug_dsa_loaded:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
++          printk("scsi%d : DSA loaded with 0x%x (virt 0x%p)\n", host->host_no,
++              NCR53c7x0_read32(DSA_REG), 
++              bus_to_virt(NCR53c7x0_read32(DSA_REG)));
++      }
++      return SPECIFIC_INT_RESTART; 
++#endif
++#ifdef A_int_debug_reselected
++    case A_int_debug_reselected:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
++          OPTION_DEBUG_DISCONNECT)) {
++          if ((hostdata->chip / 100) == 8)
++              printk("scsi%d : reselected by target %d lun %d\n",
++                  host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & ~0x80, 
++                  (int) hostdata->reselected_identify & 7);
++          else
++              printk("scsi%d : reselected by LCRC=0x%02x lun %d\n",
++                    host->host_no, (int) NCR53c7x0_read8(LCRC_REG_10),
++                    (int) hostdata->reselected_identify & 7);
++          print_queues(host);
++      }
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_disconnect_msg
++    case A_int_debug_disconnect_msg:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) {
++          if (c)
++              printk("scsi%d : target %d lun %d disconnecting\n", 
++                  host->host_no, c->device->id, c->device->lun);
++          else
++              printk("scsi%d : unknown target disconnecting\n",
++                  host->host_no);
++      }
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_disconnected
++    case A_int_debug_disconnected:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
++              OPTION_DEBUG_DISCONNECT)) {
++          printk ("scsi%d : disconnected, new queues are\n", 
++              host->host_no);
++          print_queues(host);
++#if 0
++          /* Not valid on ncr53c710! */
++          printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n",
++              host->host_no, NCR53c7x0_read8(SXFER_REG),
++              NCR53c7x0_read8(SCNTL3_REG_800));
++#endif
++          if (c) {
++              print_insn (host, (u32 *) 
++                  hostdata->sync[c->device->id].script, "", 1);
++              print_insn (host, (u32 *) 
++                  hostdata->sync[c->device->id].script + 2, "", 1);
++          }
++      }
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_panic
++    case A_int_debug_panic:
++      printk("scsi%d : int_debug_panic received\n", host->host_no);
++      print_lots (host);
++      return SPECIFIC_INT_PANIC;
++#endif
++#ifdef A_int_debug_saved
++    case A_int_debug_saved:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
++          OPTION_DEBUG_DISCONNECT)) {
++          printk ("scsi%d : saved data pointer 0x%x (virt 0x%p)\n",
++              host->host_no, cmd->saved_data_pointer,
++              bus_to_virt (cmd->saved_data_pointer));
++          print_progress (c);
++      }
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_restored
++    case A_int_debug_restored:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
++          OPTION_DEBUG_DISCONNECT)) {
++          if (cmd) {
++              int size;
++              printk ("scsi%d : restored data pointer 0x%x (virt 0x%p)\n",
++                  host->host_no, cmd->saved_data_pointer, bus_to_virt (
++                  cmd->saved_data_pointer));
++              size = print_insn (host, (u32 *) 
++                  bus_to_virt(cmd->saved_data_pointer), "", 1);
++              size = print_insn (host, (u32 *) 
++                  bus_to_virt(cmd->saved_data_pointer) + size, "", 1);
++              print_progress (c);
++          }
++#if 0
++          printk ("scsi%d : datapath residual %d\n",
++              host->host_no, datapath_residual (host)) ;
++#endif
++      }
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_sync
++    case A_int_debug_sync:
++      if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
++          OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) {
++          unsigned char sxfer = NCR53c7x0_read8 (SXFER_REG), scntl3;
++          if ((hostdata->chip / 100) == 8) {
++              scntl3 = NCR53c7x0_read8 (SCNTL3_REG_800);
++              if (c) {
++                if (sxfer != hostdata->sync[c->device->id].sxfer_sanity ||
++                  scntl3 != hostdata->sync[c->device->id].scntl3_sanity) {
++                      printk ("scsi%d :  sync sanity check failed sxfer=0x%x, scntl3=0x%x",
++                          host->host_no, sxfer, scntl3);
++                      NCR53c7x0_write8 (SXFER_REG, sxfer);
++                      NCR53c7x0_write8 (SCNTL3_REG_800, scntl3);
++                  }
++              } else 
++                printk ("scsi%d : unknown command sxfer=0x%x, scntl3=0x%x\n",
++                  host->host_no, (int) sxfer, (int) scntl3);
++          } else {
++              if (c) {
++                if (sxfer != hostdata->sync[c->device->id].sxfer_sanity) {
++                      printk ("scsi%d :  sync sanity check failed sxfer=0x%x",
++                          host->host_no, sxfer);
++                      NCR53c7x0_write8 (SXFER_REG, sxfer);
++                      NCR53c7x0_write8 (SBCL_REG,
++                              hostdata->sync[c->device->id].sscf_710);
++                  }
++              } else 
++                printk ("scsi%d : unknown command sxfer=0x%x\n",
++                  host->host_no, (int) sxfer);
++          }
++      }
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_datain
++      case A_int_debug_datain:
++          if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR|
++              OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) {
++              int size;
++              if ((hostdata->chip / 100) == 8)
++                printk ("scsi%d : In do_datain (%s) sxfer=0x%x, scntl3=0x%x\n"
++                      "         datapath residual=%d\n",
++                  host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)),
++                  (int) NCR53c7x0_read8(SXFER_REG), 
++                  (int) NCR53c7x0_read8(SCNTL3_REG_800),
++                  datapath_residual (host)) ;
++              else
++                printk ("scsi%d : In do_datain (%s) sxfer=0x%x\n"
++                      "         datapath residual=%d\n",
++                  host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)),
++                  (int) NCR53c7x0_read8(SXFER_REG), 
++                  datapath_residual (host)) ;
++              print_insn (host, dsp, "", 1);
++              size = print_insn (host, (u32 *) bus_to_virt(dsp[1]), "", 1);
++              print_insn (host, (u32 *) bus_to_virt(dsp[1]) + size, "", 1);
++         } 
++      return SPECIFIC_INT_RESTART;
++#endif
++#ifdef A_int_debug_check_dsa
++      case A_int_debug_check_dsa:
++          if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) {
++              int sdid;
++              int tmp;
++              char *where;
++              if (hostdata->chip / 100 == 8)
++                  sdid = NCR53c7x0_read8 (SDID_REG_800) & 15;
 +              else {
-                       retval = MBX_TIMEOUT;
-+                      pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
++                  tmp = NCR53c7x0_read8 (SDID_REG_700);
++                  if (!tmp)
++                      panic ("SDID_REG_700 = 0");
++                  tmp >>= 1;
++                  sdid = 0;
++                  while (tmp) {
++                      tmp >>= 1;
++                      sdid++;
++                  }
 +              }
-+              spin_unlock_irqrestore(&phba->hbalock, flag);
-       }
-       return retval;
-@@ -3158,12 +3730,25 @@
- int
- lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
- {
-+      struct lpfc_vport *vport = phba->pport;
-       int i = 0;
-+      uint32_t ha_copy;
--      while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !phba->stopped) {
-+      while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !vport->stopped) {
-               if (i++ > LPFC_MBOX_TMO * 1000)
-                       return 1;
-+              /*
-+               * Call lpfc_sli_handle_mb_event only if a mailbox cmd
-+               * did finish. This way we won't get the misleading
-+               * "Stray Mailbox Interrupt" message.
-+               */
-+              spin_lock_irq(&phba->hbalock);
-+              ha_copy = phba->work_ha;
-+              phba->work_ha &= ~HA_MBATT;
-+              spin_unlock_irq(&phba->hbalock);
-+
-+              if (ha_copy & HA_MBATT)
-               if (lpfc_sli_handle_mb_event(phba) == 0)
-                       i = 0;
-@@ -3183,6 +3768,13 @@
-       int i;
-       uint32_t control;
-+      MAILBOX_t *mbox, *pmbox;
-+      struct lpfc_vport *vport;
-+      struct lpfc_nodelist *ndlp;
-+      struct lpfc_dmabuf *mp;
-+      LPFC_MBOXQ_t *pmb;
-+      int rc;
++              where = dsp - NCR53c7x0_insn_size(NCR53c7x0_read8 
++                      (DCMD_REG)) == hostdata->script + 
++                      Ent_select_check_dsa / sizeof(u32) ?
++                  "selection" : "reselection";
++              if (c && sdid != c->device->id) {
++                  printk ("scsi%d : SDID target %d != DSA target %d at %s\n",
++                      host->host_no, sdid, c->device->id, where);
++                  print_lots(host);
++                  dump_events (host, 20);
++                  return SPECIFIC_INT_PANIC;
++              }
++          }
++          return SPECIFIC_INT_RESTART;
++#endif
++    default:
++      if ((dsps & 0xff000000) == 0x03000000) {
++           printk ("scsi%d : misc debug interrupt 0x%x\n",
++              host->host_no, dsps);
++          return SPECIFIC_INT_RESTART;
++      } else if ((dsps & 0xff000000) == 0x05000000) {
++          if (hostdata->events) {
++              struct NCR53c7x0_event *event;
++              ++hostdata->event_index;
++              if (hostdata->event_index >= hostdata->event_size)
++                  hostdata->event_index = 0;
++              event = (struct NCR53c7x0_event *) hostdata->events + 
++                  hostdata->event_index;
++              event->event = (enum ncr_event) dsps;
++              event->dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
++              if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) {
++                  if (hostdata->chip / 100 == 8)
++                      event->target = NCR53c7x0_read8(SSID_REG_800);
++                  else {
++                      unsigned char tmp, sdid;
++                      tmp = NCR53c7x0_read8 (SDID_REG_700);
++                      if (!tmp)
++                          panic ("SDID_REG_700 = 0");
++                      tmp >>= 1;
++                      sdid = 0;
++                      while (tmp) {
++                          tmp >>= 1;
++                          sdid++;
++                      }
++                      event->target = sdid;
++                  }
++              }
++              else 
++                      event->target = 255;
 +
-       /*
-        * Get the driver's phba structure from the dev_id and
-        * assume the HBA is not interrupting.
-@@ -3204,7 +3796,7 @@
-        */
-       /* Ignore all interrupts during initialization. */
--      if (unlikely(phba->hba_state < LPFC_LINK_DOWN))
-+      if (unlikely(phba->link_state < LPFC_LINK_DOWN))
-               return IRQ_NONE;
-       /*
-@@ -3212,16 +3804,16 @@
-        * Clear Attention Sources, except Error Attention (to
-        * preserve status) and Link Attention
-        */
--      spin_lock(phba->host->host_lock);
-+      spin_lock(&phba->hbalock);
-       ha_copy = readl(phba->HAregaddr);
-       /* If somebody is waiting to handle an eratt don't process it
-        * here.  The brdkill function will do this.
-        */
--      if (phba->fc_flag & FC_IGNORE_ERATT)
-+      if (phba->link_flag & LS_IGNORE_ERATT)
-               ha_copy &= ~HA_ERATT;
-       writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
-       readl(phba->HAregaddr); /* flush */
--      spin_unlock(phba->host->host_lock);
-+      spin_unlock(&phba->hbalock);
-       if (unlikely(!ha_copy))
-               return IRQ_NONE;
-@@ -3235,36 +3827,41 @@
-                                * Turn off Link Attention interrupts
-                                * until CLEAR_LA done
-                                */
--                              spin_lock(phba->host->host_lock);
-+                              spin_lock(&phba->hbalock);
-                               phba->sli.sli_flag &= ~LPFC_PROCESS_LA;
-                               control = readl(phba->HCregaddr);
-                               control &= ~HC_LAINT_ENA;
-                               writel(control, phba->HCregaddr);
-                               readl(phba->HCregaddr); /* flush */
--                              spin_unlock(phba->host->host_lock);
-+                              spin_unlock(&phba->hbalock);
-                       }
-                       else
-                               work_ha_copy &= ~HA_LATT;
-               }
-               if (work_ha_copy & ~(HA_ERATT|HA_MBATT|HA_LATT)) {
--                      for (i = 0; i < phba->sli.num_rings; i++) {
--                              if (work_ha_copy & (HA_RXATT << (4*i))) {
-                                       /*
--                                       * Turn off Slow Rings interrupts
-+                       * Turn off Slow Rings interrupts, LPFC_ELS_RING is
-+                       * the only slow ring.
-                                        */
--                                      spin_lock(phba->host->host_lock);
-+                      status = (work_ha_copy &
-+                              (HA_RXMASK  << (4*LPFC_ELS_RING)));
-+                      status >>= (4*LPFC_ELS_RING);
-+                      if (status & HA_RXMASK) {
-+                              spin_lock(&phba->hbalock);
-                                       control = readl(phba->HCregaddr);
--                                      control &= ~(HC_R0INT_ENA << i);
-+                              if (control & (HC_R0INT_ENA << LPFC_ELS_RING)) {
-+                                      control &=
-+                                          ~(HC_R0INT_ENA << LPFC_ELS_RING);
-                                       writel(control, phba->HCregaddr);
-                                       readl(phba->HCregaddr); /* flush */
--                                      spin_unlock(phba->host->host_lock);
-                               }
-+                              spin_unlock(&phba->hbalock);
-                       }
-               }
-               if (work_ha_copy & HA_ERATT) {
--                      phba->hba_state = LPFC_HBA_ERROR;
-+                      phba->link_state = LPFC_HBA_ERROR;
-                       /*
-                        * There was a link/board error.  Read the
-                        * status register to retrieve the error event
-@@ -3279,14 +3876,108 @@
-                       /* Clear Chip error bit */
-                       writel(HA_ERATT, phba->HAregaddr);
-                       readl(phba->HAregaddr); /* flush */
--                      phba->stopped = 1;
-+                      phba->pport->stopped = 1;
++              if (event->event == EVENT_RESELECT)
++                  event->lun = hostdata->reselected_identify & 0xf;
++              else if (c)
++                  event->lun = c->device->lun;
++              else
++                  event->lun = 255;
++              do_gettimeofday(&(event->time));
++              if (c) {
++                  event->pid = c->pid;
++                  memcpy ((void *) event->cmnd, (void *) c->cmnd, 
++                      sizeof (event->cmnd));
++              } else {
++                  event->pid = -1;
 +              }
++          }
++          return SPECIFIC_INT_RESTART;
++      }
++
++      printk ("scsi%d : unknown user interrupt 0x%x\n", 
++          host->host_no, (unsigned) dsps);
++      return SPECIFIC_INT_PANIC;
++    }
++}
 +
-+              if ((work_ha_copy & HA_MBATT) &&
-+                  (phba->sli.mbox_active)) {
-+                      pmb = phba->sli.mbox_active;
-+                      pmbox = &pmb->mb;
-+                      mbox = &phba->slim2p->mbx;
-+                      vport = pmb->vport;
++/* 
++ * XXX - the stock NCR assembler won't output the scriptu.h file,
++ * which undefine's all #define'd CPP symbols from the script.h
++ * file, which will create problems if you use multiple scripts
++ * with the same  symbol names.
++ *
++ * If you insist on using NCR's assembler, you could generate
++ * scriptu.h from script.h using something like 
++ *
++ * grep #define script.h | \
++ * sed 's/#define[    ][      ]*\([_a-zA-Z][_a-zA-Z0-9]*\).*$/#undefine \1/' \
++ * > scriptu.h
++ */
 +
-+                      /* First check out the status word */
-+                      lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
-+                      if (pmbox->mbxOwner != OWN_HOST) {
-+                              /*
-+                               * Stray Mailbox Interrupt, mbxCommand <cmd>
-+                               * mbxStatus <status>
-+                               */
-+                              lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX |
-+                                              LOG_SLI,
-+                                              "%d (%d):0304 Stray Mailbox "
-+                                              "Interrupt mbxCommand x%x "
-+                                              "mbxStatus x%x\n",
-+                                              phba->brd_no,
-+                                              (vport
-+                                               ? vport->vpi : 0),
-+                                              pmbox->mbxCommand,
-+                                              pmbox->mbxStatus);
-+                      }
-+                      phba->last_completion_time = jiffies;
-+                      del_timer_sync(&phba->sli.mbox_tmo);
++#include "53c7xx_u.h"
 +
-+                      phba->sli.mbox_active = NULL;
-+                      if (pmb->mbox_cmpl) {
-+                              lpfc_sli_pcimem_bcopy(mbox, pmbox,
-+                                                    MAILBOX_CMD_SIZE);
-+                      }
-+                      if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) {
-+                              pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG;
-+
-+                              lpfc_debugfs_disc_trc(vport,
-+                                      LPFC_DISC_TRC_MBOX_VPORT,
-+                                      "MBOX dflt rpi: : status:x%x rpi:x%x",
-+                                      (uint32_t)pmbox->mbxStatus,
-+                                      pmbox->un.varWords[0], 0);
-+
-+                              if ( !pmbox->mbxStatus) {
-+                                      mp = (struct lpfc_dmabuf *)
-+                                              (pmb->context1);
-+                                      ndlp = (struct lpfc_nodelist *)
-+                                              pmb->context2;
-+
-+                                      /* Reg_LOGIN of dflt RPI was successful.
-+                                       * new lets get rid of the RPI using the
-+                                       * same mbox buffer.
-+                                       */
-+                                      lpfc_unreg_login(phba, vport->vpi,
-+                                              pmbox->un.varWords[0], pmb);
-+                                      pmb->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
-+                                      pmb->context1 = mp;
-+                                      pmb->context2 = ndlp;
-+                                      pmb->vport = vport;
-+                                      spin_lock(&phba->hbalock);
-+                                      phba->sli.sli_flag &=
-+                                              ~LPFC_SLI_MBOX_ACTIVE;
-+                                      spin_unlock(&phba->hbalock);
-+                                      goto send_current_mbox;
-+                              }
-+                      }
-+                      spin_lock(&phba->pport->work_port_lock);
-+                      phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
-+                      spin_unlock(&phba->pport->work_port_lock);
-+                      lpfc_mbox_cmpl_put(phba, pmb);
-+              }
-+              if ((work_ha_copy & HA_MBATT) &&
-+                  (phba->sli.mbox_active == NULL)) {
-+send_next_mbox:
-+                      spin_lock(&phba->hbalock);
-+                      phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-+                      pmb = lpfc_mbox_get(phba);
-+                      spin_unlock(&phba->hbalock);
-+send_current_mbox:
-+                      /* Process next mailbox command if there is one */
-+                      if (pmb != NULL) {
-+                              rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
-+                              if (rc == MBX_NOT_FINISHED) {
-+                                      pmb->mb.mbxStatus = MBX_NOT_FINISHED;
-+                                      lpfc_mbox_cmpl_put(phba, pmb);
-+                                      goto send_next_mbox;
-+                              }
-+                      } else {
-+                              /* Turn on IOCB processing */
-+                              for (i = 0; i < phba->sli.num_rings; i++)
-+                                      lpfc_sli_turn_on_ring(phba, i);
-+                      }
++/* XXX - add alternate script handling code here */
 +
-               }
--              spin_lock(phba->host->host_lock);
-+              spin_lock(&phba->hbalock);
-               phba->work_ha |= work_ha_copy;
-               if (phba->work_wait)
--                      wake_up(phba->work_wait);
--              spin_unlock(phba->host->host_lock);
-+                      lpfc_worker_wake_up(phba);
-+              spin_unlock(&phba->hbalock);
-       }
-       ha_copy &= ~(phba->work_ha_mask);
-@@ -3298,7 +3989,7 @@
-        */
-       status = (ha_copy & (HA_RXMASK  << (4*LPFC_FCP_RING)));
-       status >>= (4*LPFC_FCP_RING);
--      if (status & HA_RXATT)
-+      if (status & HA_RXMASK)
-               lpfc_sli_handle_fast_ring_event(phba,
-                                               &phba->sli.ring[LPFC_FCP_RING],
-                                               status);
-@@ -3311,7 +4002,7 @@
-                */
-               status = (ha_copy & (HA_RXMASK  << (4*LPFC_EXTRA_RING)));
-               status >>= (4*LPFC_EXTRA_RING);
--              if (status & HA_RXATT) {
-+              if (status & HA_RXMASK) {
-                       lpfc_sli_handle_fast_ring_event(phba,
-                                       &phba->sli.ring[LPFC_EXTRA_RING],
-                                       status);
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_sli.h linux-2.6.22-590/drivers/scsi/lpfc/lpfc_sli.h
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_sli.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_sli.h      2008-01-02 13:56:37.000000000 -0500
-@@ -20,6 +20,7 @@
- /* forward declaration for LPFC_IOCB_t's use */
- struct lpfc_hba;
-+struct lpfc_vport;
- /* Define the context types that SLI handles for abort and sums. */
- typedef enum _lpfc_ctx_cmd {
-@@ -43,10 +44,12 @@
- #define LPFC_IO_WAKE          2       /* High Priority Queue signal flag */
- #define LPFC_IO_FCP           4       /* FCP command -- iocbq in scsi_buf */
- #define LPFC_DRIVER_ABORTED   8       /* driver aborted this request */
-+#define LPFC_IO_FABRIC                0x10    /* Iocb send using fabric scheduler */
-       uint8_t abort_count;
-       uint8_t rsvd2;
-       uint32_t drvrTimeout;   /* driver timeout in seconds */
-+      struct lpfc_vport *vport;/* virtual port pointer */
-       void *context1;         /* caller context information */
-       void *context2;         /* caller context information */
-       void *context3;         /* caller context information */
-@@ -56,6 +59,8 @@
-               struct lpfcMboxq   *mbox;
-       } context_un;
-+      void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
-+                         struct lpfc_iocbq *);
-       void (*iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
-                          struct lpfc_iocbq *);
-@@ -69,11 +74,13 @@
- #define IOCB_TIMEDOUT       3
- #define LPFC_MBX_WAKE 1
-+#define LPFC_MBX_IMED_UNREG   2
- typedef struct lpfcMboxq {
-       /* MBOXQs are used in single linked lists */
-       struct list_head list;  /* ptr to next mailbox command */
-       MAILBOX_t mb;           /* Mailbox cmd */
-+      struct lpfc_vport *vport;/* virutal port pointer */
-       void *context1;         /* caller context information */
-       void *context2;         /* caller context information */
-@@ -135,6 +142,8 @@
-       uint8_t ringno;         /* ring number */
-       uint16_t numCiocb;      /* number of command iocb's per ring */
-       uint16_t numRiocb;      /* number of rsp iocb's per ring */
-+      uint16_t sizeCiocb;     /* Size of command iocb's in this ring */
-+      uint16_t sizeRiocb;     /* Size of response iocb's in this ring */
-       uint32_t fast_iotag;    /* max fastlookup based iotag           */
-       uint32_t iotag_ctr;     /* keeps track of the next iotag to use */
-@@ -165,6 +174,34 @@
-                                       struct lpfc_sli_ring *);
- };
-+/* Structure used for configuring rings to a specific profile or rctl / type */
-+struct lpfc_hbq_init {
-+      uint32_t rn;            /* Receive buffer notification */
-+      uint32_t entry_count;   /* max # of entries in HBQ */
-+      uint32_t headerLen;     /* 0 if not profile 4 or 5 */
-+      uint32_t logEntry;      /* Set to 1 if this HBQ used for LogEntry */
-+      uint32_t profile;       /* Selection profile 0=all, 7=logentry */
-+      uint32_t ring_mask;     /* Binds HBQ to a ring e.g. Ring0=b0001,
-+                               * ring2=b0100 */
-+      uint32_t hbq_index;     /* index of this hbq in ring .HBQs[] */
-+
-+      uint32_t seqlenoff;
-+      uint32_t maxlen;
-+      uint32_t seqlenbcnt;
-+      uint32_t cmdcodeoff;
-+      uint32_t cmdmatch[8];
-+      uint32_t mask_count;    /* number of mask entries in prt array */
-+      struct hbq_mask hbqMasks[6];
-+
-+      /* Non-config rings fields to keep track of buffer allocations */
-+      uint32_t buffer_count;  /* number of buffers allocated */
-+      uint32_t init_count;    /* number to allocate when initialized */
-+      uint32_t add_count;     /* number to allocate when starved */
-+} ;
-+
-+#define LPFC_MAX_HBQ 16
 +
++/* 
++ * Function : static void NCR537xx_soft_reset (struct Scsi_Host *host)
++ *
++ * Purpose :  perform a soft reset of the NCR53c7xx chip
++ *
++ * Inputs : host - pointer to this host adapter's structure
++ *
++ * Preconditions : NCR53c7x0_init must have been called for this 
++ *      host.
++ * 
++ */
 +
- /* Structure used to hold SLI statistical counters and info */
- struct lpfc_sli_stat {
-       uint64_t mbox_stat_err;  /* Mbox cmds completed status error */
-@@ -197,6 +234,7 @@
- #define LPFC_SLI_MBOX_ACTIVE      0x100       /* HBA mailbox is currently active */
- #define LPFC_SLI2_ACTIVE          0x200       /* SLI2 overlay in firmware is active */
- #define LPFC_PROCESS_LA           0x400       /* Able to process link attention */
-+#define LPFC_BLOCK_MGMT_IO        0x800       /* Don't allow mgmt mbx or iocb cmds */
-       struct lpfc_sli_ring ring[LPFC_MAX_RING];
-       int fcp_ring;           /* ring used for FCP initiator commands */
-@@ -209,6 +247,7 @@
-       uint16_t mboxq_cnt;     /* current length of queue */
-       uint16_t mboxq_max;     /* max length */
-       LPFC_MBOXQ_t *mbox_active;      /* active mboxq information */
-+      struct list_head mboxq_cmpl;
-       struct timer_list mbox_tmo;     /* Hold clk to timeout active mbox
-                                          cmd */
-@@ -221,12 +260,6 @@
-       struct lpfc_lnk_stat lnk_stat_offsets;
- };
--/* Given a pointer to the start of the ring, and the slot number of
-- * the desired iocb entry, calc a pointer to that entry.
-- * (assume iocb entry size is 32 bytes, or 8 words)
-- */
--#define IOCB_ENTRY(ring,slot) ((IOCB_t *)(((char *)(ring)) + ((slot) * 32)))
--
- #define LPFC_MBOX_TMO           30    /* Sec tmo for outstanding mbox
-                                          command */
- #define LPFC_MBOX_TMO_FLASH_CMD 300     /* Sec tmo for outstanding FLASH write
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_version.h linux-2.6.22-590/drivers/scsi/lpfc/lpfc_version.h
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_version.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_version.h  2008-01-02 13:56:37.000000000 -0500
-@@ -18,7 +18,7 @@
-  * included with this package.                                     *
-  *******************************************************************/
--#define LPFC_DRIVER_VERSION "8.1.12"
-+#define LPFC_DRIVER_VERSION "8.2.1"
- #define LPFC_DRIVER_NAME "lpfc"
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_vport.c linux-2.6.22-590/drivers/scsi/lpfc/lpfc_vport.c
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_vport.c    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_vport.c    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,523 @@
-+/*******************************************************************
-+ * This file is part of the Emulex Linux Device Driver for         *
-+ * Fibre Channel Host Bus Adapters.                                *
-+ * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
-+ * EMULEX and SLI are trademarks of Emulex.                        *
-+ * www.emulex.com                                                  *
-+ * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
-+ *                                                                 *
-+ * This program is free software; you can redistribute it and/or   *
-+ * modify it under the terms of version 2 of the GNU General       *
-+ * Public License as published by the Free Software Foundation.    *
-+ * This program is distributed in the hope that it will be useful. *
-+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
-+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
-+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
-+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
-+ * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
-+ * more details, a copy of which can be found in the file COPYING  *
-+ * included with this package.                                     *
-+ *******************************************************************/
++static void 
++NCR53c7x0_soft_reset (struct Scsi_Host *host) {
++    NCR53c7x0_local_declare();
++    unsigned long flags;
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    NCR53c7x0_local_setup(host);
 +
-+#include <linux/blkdev.h>
-+#include <linux/delay.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/idr.h>
-+#include <linux/interrupt.h>
-+#include <linux/kthread.h>
-+#include <linux/pci.h>
-+#include <linux/spinlock.h>
++    local_irq_save(flags);
++
++    /* Disable scsi chip and s/w level 7 ints */
++
++#ifdef CONFIG_MVME16x
++    if (MACH_IS_MVME16x)
++    {
++        volatile unsigned long v;
++
++        v = *(volatile unsigned long *)0xfff4006c;
++        v &= ~0x8000;
++        *(volatile unsigned long *)0xfff4006c = v;
++        v = *(volatile unsigned long *)0xfff4202c;
++        v &= ~0x10;
++        *(volatile unsigned long *)0xfff4202c = v;
++    }
++#endif
++    /* Anything specific for your hardware? */
++
++    /*
++     * Do a soft reset of the chip so that everything is 
++     * reinitialized to the power-on state.
++     *
++     * Basically follow the procedure outlined in the NCR53c700
++     * data manual under Chapter Six, How to Use, Steps Necessary to
++     * Start SCRIPTS, with the exception of actually starting the 
++     * script and setting up the synchronous transfer gunk.
++     */
++
++    /* Should we reset the scsi bus here??????????????????? */
++
++    NCR53c7x0_write8(ISTAT_REG_700, ISTAT_10_SRST);
++    NCR53c7x0_write8(ISTAT_REG_700, 0);
++
++    /*
++     * saved_dcntl is set up in NCR53c7x0_init() before it is overwritten
++     * here.  We should have some better way of working out the CF bit
++     * setting..
++     */
++
++    hostdata->saved_dcntl = DCNTL_10_EA|DCNTL_10_COM;
++    if (hostdata->scsi_clock > 50000000)
++      hostdata->saved_dcntl |= DCNTL_700_CF_3;
++    else
++    if (hostdata->scsi_clock > 37500000)
++        hostdata->saved_dcntl |= DCNTL_700_CF_2;
++#if 0
++    else
++      /* Any clocks less than 37.5MHz? */
++#endif
 +
-+#include <scsi/scsi.h>
-+#include <scsi/scsi_device.h>
-+#include <scsi/scsi_host.h>
-+#include <scsi/scsi_transport_fc.h>
-+#include "lpfc_hw.h"
-+#include "lpfc_sli.h"
-+#include "lpfc_disc.h"
-+#include "lpfc_scsi.h"
-+#include "lpfc.h"
-+#include "lpfc_logmsg.h"
-+#include "lpfc_crtn.h"
-+#include "lpfc_version.h"
-+#include "lpfc_vport.h"
-+
-+inline void lpfc_vport_set_state(struct lpfc_vport *vport,
-+                               enum fc_vport_state new_state)
-+{
-+      struct fc_vport *fc_vport = vport->fc_vport;
-+
-+      if (fc_vport) {
-+              /*
-+               * When the transport defines fc_vport_set state we will replace
-+               * this code with the following line
-+               */
-+              /* fc_vport_set_state(fc_vport, new_state); */
-+              if (new_state != FC_VPORT_INITIALIZING)
-+                      fc_vport->vport_last_state = fc_vport->vport_state;
-+              fc_vport->vport_state = new_state;
-+      }
-+
-+      /* for all the error states we will set the invternal state to FAILED */
-+      switch (new_state) {
-+      case FC_VPORT_NO_FABRIC_SUPP:
-+      case FC_VPORT_NO_FABRIC_RSCS:
-+      case FC_VPORT_FABRIC_LOGOUT:
-+      case FC_VPORT_FABRIC_REJ_WWN:
-+      case FC_VPORT_FAILED:
-+              vport->port_state = LPFC_VPORT_FAILED;
-+              break;
-+      case FC_VPORT_LINKDOWN:
-+              vport->port_state = LPFC_VPORT_UNKNOWN;
-+              break;
-+      default:
-+              /* do nothing */
-+              break;
-+      }
++    if (hostdata->options & OPTION_DEBUG_TRACE)
++      NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM);
++    else
++      NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl);
++    /* Following disables snooping - snooping is not required, as non-
++     * cached pages are used for shared data, and appropriate use is
++     * made of cache_push/cache_clear.  Indeed, for 68060
++     * enabling snooping causes disk corruption of ext2fs free block
++     * bitmaps and the like.  If you have a 68060 with snooping hardwared
++     * on, then you need to enable CONFIG_060_WRITETHROUGH.
++     */
++    NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD);
++    /* Actually burst of eight, according to my 53c710 databook */
++    NCR53c7x0_write8(hostdata->dmode, DMODE_10_BL_8 | DMODE_10_FC2);
++    NCR53c7x0_write8(SCID_REG, 1 << host->this_id);
++    NCR53c7x0_write8(SBCL_REG, 0);
++    NCR53c7x0_write8(SCNTL1_REG, SCNTL1_ESR_700);
++    NCR53c7x0_write8(SCNTL0_REG, ((hostdata->options & OPTION_PARITY) ? 
++            SCNTL0_EPC : 0) | SCNTL0_EPG_700 | SCNTL0_ARB1 | SCNTL0_ARB2);
++
++    /*
++     * Enable all interrupts, except parity which we only want when
++     * the user requests it.
++     */
++
++    NCR53c7x0_write8(DIEN_REG, DIEN_700_BF |
++              DIEN_ABRT | DIEN_SSI | DIEN_SIR | DIEN_700_OPC);
++
++    NCR53c7x0_write8(SIEN_REG_700, ((hostdata->options & OPTION_PARITY) ?
++          SIEN_PAR : 0) | SIEN_700_STO | SIEN_RST | SIEN_UDC |
++              SIEN_SGE | SIEN_MA);
++
++#ifdef CONFIG_MVME16x
++    if (MACH_IS_MVME16x)
++    {
++        volatile unsigned long v;
++
++        /* Enable scsi chip and s/w level 7 ints */
++        v = *(volatile unsigned long *)0xfff40080;
++        v = (v & ~(0xf << 28)) | (4 << 28);
++        *(volatile unsigned long *)0xfff40080 = v;
++        v = *(volatile unsigned long *)0xfff4006c;
++        v |= 0x8000;
++        *(volatile unsigned long *)0xfff4006c = v;
++        v = *(volatile unsigned long *)0xfff4202c;
++        v = (v & ~0xff) | 0x10 | 4;
++        *(volatile unsigned long *)0xfff4202c = v;
++    }
++#endif
++    /* Anything needed for your hardware? */
++    local_irq_restore(flags);
 +}
 +
-+static int
-+lpfc_alloc_vpi(struct lpfc_hba *phba)
-+{
-+      int  vpi;
 +
-+      spin_lock_irq(&phba->hbalock);
-+      /* Start at bit 1 because vpi zero is reserved for the physical port */
-+      vpi = find_next_zero_bit(phba->vpi_bmask, (phba->max_vpi + 1), 1);
-+      if (vpi > phba->max_vpi)
-+              vpi = 0;
-+      else
-+              set_bit(vpi, phba->vpi_bmask);
-+      spin_unlock_irq(&phba->hbalock);
-+      return vpi;
-+}
++/*
++ * Function static struct NCR53c7x0_cmd *allocate_cmd (Scsi_Cmnd *cmd)
++ * 
++ * Purpose : Return the first free NCR53c7x0_cmd structure (which are 
++ *    reused in a LIFO manner to minimize cache thrashing).
++ *
++ * Side effects : If we haven't yet scheduled allocation of NCR53c7x0_cmd
++ *    structures for this device, do so.  Attempt to complete all scheduled
++ *    allocations using get_zeroed_page(), putting NCR53c7x0_cmd structures on
++ *    the free list.  Teach programmers not to drink and hack.
++ *
++ * Inputs : cmd - SCSI command
++ *
++ * Returns : NCR53c7x0_cmd structure allocated on behalf of cmd;
++ *    NULL on failure.
++ */
 +
 +static void
-+lpfc_free_vpi(struct lpfc_hba *phba, int vpi)
-+{
-+      spin_lock_irq(&phba->hbalock);
-+      clear_bit(vpi, phba->vpi_bmask);
-+      spin_unlock_irq(&phba->hbalock);
++my_free_page (void *addr, int dummy)
++{
++    /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
++     * XXX may be invalid (CONFIG_060_WRITETHROUGH)
++     */
++    kernel_set_cachemode((void *)addr, 4096, IOMAP_FULL_CACHING);
++    free_page ((u32)addr);
++}
++
++static struct NCR53c7x0_cmd *
++allocate_cmd (Scsi_Cmnd *cmd) {
++    struct Scsi_Host *host = cmd->device->host;
++    struct NCR53c7x0_hostdata *hostdata = 
++      (struct NCR53c7x0_hostdata *) host->hostdata[0];
++    u32 real;                 /* Real address */
++    int size;                 /* Size of *tmp */
++    struct NCR53c7x0_cmd *tmp;
++    unsigned long flags;
++
++    if (hostdata->options & OPTION_DEBUG_ALLOCATION)
++      printk ("scsi%d : num_cmds = %d, can_queue = %d\n"
++              "         target = %d, lun = %d, %s\n",
++          host->host_no, hostdata->num_cmds, host->can_queue,
++          cmd->device->id, cmd->device->lun, (hostdata->cmd_allocated[cmd->device->id] &
++              (1 << cmd->device->lun)) ? "already allocated" : "not allocated");
++
++/*
++ * If we have not yet reserved commands for this I_T_L nexus, and
++ * the device exists (as indicated by permanent Scsi_Cmnd structures
++ * being allocated under 1.3.x, or being outside of scan_scsis in
++ * 1.2.x), do so now.
++ */
++    if (!(hostdata->cmd_allocated[cmd->device->id] & (1 << cmd->device->lun)) &&
++                              cmd->device && cmd->device->has_cmdblocks) {
++      if ((hostdata->extra_allocate + hostdata->num_cmds) < host->can_queue)
++          hostdata->extra_allocate += host->cmd_per_lun;
++      hostdata->cmd_allocated[cmd->device->id] |= (1 << cmd->device->lun);
++    }
++
++    for (; hostdata->extra_allocate > 0 ; --hostdata->extra_allocate, 
++      ++hostdata->num_cmds) {
++    /* historically, kmalloc has returned unaligned addresses; pad so we
++       have enough room to ROUNDUP */
++      size = hostdata->max_cmd_size + sizeof (void *);
++#ifdef FORCE_DSA_ALIGNMENT
++      /*
++       * 53c710 rev.0 doesn't have an add-with-carry instruction.
++       * Ensure we allocate enough memory to force alignment.
++       */
++      size += 256;
++#endif
++/* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */
++
++        if (size > 4096) {
++            printk (KERN_ERR "53c7xx: allocate_cmd size > 4K\n");
++          return NULL;
++      }
++        real = get_zeroed_page(GFP_ATOMIC);
++        if (real == 0)
++              return NULL;
++        cache_push(virt_to_phys((void *)real), 4096);
++        cache_clear(virt_to_phys((void *)real), 4096);
++        kernel_set_cachemode((void *)real, 4096, IOMAP_NOCACHE_SER);
++      tmp = ROUNDUP(real, void *);
++#ifdef FORCE_DSA_ALIGNMENT
++      {
++          if (((u32)tmp & 0xff) > CmdPageStart)
++              tmp = (struct NCR53c7x0_cmd *)((u32)tmp + 255);
++          tmp = (struct NCR53c7x0_cmd *)(((u32)tmp & ~0xff) + CmdPageStart);
++#if 0
++          printk ("scsi: size = %d, real = 0x%08x, tmp set to 0x%08x\n",
++                      size, real, (u32)tmp);
++#endif
++      }
++#endif
++      tmp->real = (void *)real;
++      tmp->size = size;                       
++      tmp->free = ((void (*)(void *, int)) my_free_page);
++      local_irq_save(flags);
++      tmp->next = hostdata->free;
++      hostdata->free = tmp;
++      local_irq_restore(flags);
++    }
++    local_irq_save(flags);
++    tmp = (struct NCR53c7x0_cmd *) hostdata->free;
++    if (tmp) {
++      hostdata->free = tmp->next;
++    }
++    local_irq_restore(flags);
++    if (!tmp)
++      printk ("scsi%d : can't allocate command for target %d lun %d\n",
++          host->host_no, cmd->device->id, cmd->device->lun);
++    return tmp;
 +}
 +
-+static int
-+lpfc_vport_sparm(struct lpfc_hba *phba, struct lpfc_vport *vport)
-+{
-+      LPFC_MBOXQ_t *pmb;
-+      MAILBOX_t *mb;
-+      struct lpfc_dmabuf *mp;
-+      int  rc;
++/*
++ * Function static struct NCR53c7x0_cmd *create_cmd (Scsi_Cmnd *cmd) 
++ *
++ *
++ * Purpose : allocate a NCR53c7x0_cmd structure, initialize it based on the 
++ *    Scsi_Cmnd structure passed in cmd, including dsa and Linux field 
++ *    initialization, and dsa code relocation.
++ *
++ * Inputs : cmd - SCSI command
++ *
++ * Returns : NCR53c7x0_cmd structure corresponding to cmd,
++ *    NULL on failure.
++ */
++static struct NCR53c7x0_cmd *
++create_cmd (Scsi_Cmnd *cmd) {
++    NCR53c7x0_local_declare();
++    struct Scsi_Host *host = cmd->device->host;
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++        host->hostdata[0];    
++    struct NCR53c7x0_cmd *tmp;        /* NCR53c7x0_cmd structure for this command */
++    int datain,               /* Number of instructions per phase */
++      dataout;
++    int data_transfer_instructions, /* Count of dynamic instructions */
++      i;                      /* Counter */
++    u32 *cmd_datain,          /* Address of datain/dataout code */
++      *cmd_dataout;           /* Incremented as we assemble */
++#ifdef notyet
++    unsigned char *msgptr;    /* Current byte in select message */
++    int msglen;                       /* Length of whole select message */
++#endif
++    unsigned long flags;
++    u32 exp_select_indirect;  /* Used in sanity check */
++    NCR53c7x0_local_setup(cmd->device->host);
 +
-+      pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-+      if (!pmb) {
-+              return -ENOMEM;
-+      }
-+      mb = &pmb->mb;
++    if (!(tmp = allocate_cmd (cmd)))
++      return NULL;
++
++    /*
++     * Copy CDB and initialised result fields from Scsi_Cmnd to NCR53c7x0_cmd.
++     * We do this because NCR53c7x0_cmd may have a special cache mode
++     * selected to cope with lack of bus snooping, etc.
++     */
++
++    memcpy(tmp->cmnd, cmd->cmnd, 12);
++    tmp->result = cmd->result;
++
++    /*
++     * Decide whether we need to generate commands for DATA IN,
++     * DATA OUT, neither, or both based on the SCSI command 
++     */
++
++    switch (cmd->cmnd[0]) {
++    /* These commands do DATA IN */
++    case INQUIRY:
++    case MODE_SENSE:
++    case READ_6:
++    case READ_10:
++    case READ_CAPACITY:
++    case REQUEST_SENSE:
++    case READ_BLOCK_LIMITS:
++    case READ_TOC:
++      datain = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
++      dataout = 0;
++      break;
++    /* These commands do DATA OUT */
++    case MODE_SELECT: 
++    case WRITE_6:
++    case WRITE_10:
++#if 0
++      printk("scsi%d : command is ", host->host_no);
++      __scsi_print_command(cmd->cmnd);
++#endif
++#if 0
++      printk ("scsi%d : %d scatter/gather segments\n", host->host_no,
++          cmd->use_sg);
++#endif
++      datain = 0;
++      dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
++#if 0
++      hostdata->options |= OPTION_DEBUG_INTR;
++#endif
++      break;
++    /* 
++     * These commands do no data transfer, we should force an
++     * interrupt if a data phase is attempted on them.
++     */
++    case TEST_UNIT_READY:
++    case ALLOW_MEDIUM_REMOVAL:
++    case START_STOP:
++      datain = dataout = 0;
++      break;
++    /*
++     * We don't know about these commands, so generate code to handle
++     * both DATA IN and DATA OUT phases.  More efficient to identify them
++     * and add them to the above cases.
++     */
++    default:
++      printk("scsi%d : datain+dataout for command ", host->host_no);
++      __scsi_print_command(cmd->cmnd);
++      datain = dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
++    }
++
++    /*
++     * New code : so that active pointers work correctly regardless
++     *        of where the saved data pointer is at, we want to immediately
++     *        enter the dynamic code after selection, and on a non-data
++     *        phase perform a CALL to the non-data phase handler, with
++     *        returns back to this address.
++     *
++     *        If a phase mismatch is encountered in the middle of a 
++     *        Block MOVE instruction, we want to _leave_ that instruction
++     *        unchanged as the current case is, modify a temporary buffer,
++     *        and point the active pointer (TEMP) at that.
++     *
++     *        Furthermore, we want to implement a saved data pointer, 
++     *        set by the SAVE_DATA_POINTERs message.
++     *
++     *        So, the data transfer segments will change to 
++     *                CALL data_transfer, WHEN NOT data phase
++     *                MOVE x, x, WHEN data phase
++     *                ( repeat )
++     *                JUMP other_transfer
++     */
++
++    data_transfer_instructions = datain + dataout;
++
++    /*
++     * When we perform a request sense, we overwrite various things,
++     * including the data transfer code.  Make sure we have enough
++     * space to do that.
++     */
++
++    if (data_transfer_instructions < 2)
++      data_transfer_instructions = 2;
++
++
++    /*
++     * The saved data pointer is set up so that a RESTORE POINTERS message 
++     * will start the data transfer over at the beginning.
++     */
++
++    tmp->saved_data_pointer = virt_to_bus (hostdata->script) + 
++      hostdata->E_data_transfer;
++
++    /*
++     * Initialize Linux specific fields.
++     */
++
++    tmp->cmd = cmd;
++    tmp->next = NULL;
++    tmp->flags = 0;
++    tmp->dsa_next_addr = virt_to_bus(tmp->dsa) + hostdata->dsa_next - 
++      hostdata->dsa_start;
++    tmp->dsa_addr = virt_to_bus(tmp->dsa) - hostdata->dsa_start;
++
++    /* 
++     * Calculate addresses of dynamic code to fill in DSA
++     */
++
++    tmp->data_transfer_start = tmp->dsa + (hostdata->dsa_end - 
++      hostdata->dsa_start) / sizeof(u32);
++    tmp->data_transfer_end = tmp->data_transfer_start + 
++      2 * data_transfer_instructions;
++
++    cmd_datain = datain ? tmp->data_transfer_start : NULL;
++    cmd_dataout = dataout ? (datain ? cmd_datain + 2 * datain : tmp->
++      data_transfer_start) : NULL;
++
++    /*
++     * Fill in the NCR53c7x0_cmd structure as follows
++     * dsa, with fixed up DSA code
++     * datain code
++     * dataout code
++     */
++
++    /* Copy template code into dsa and perform all necessary fixups */
++    if (hostdata->dsa_fixup)
++      hostdata->dsa_fixup(tmp);
++
++    patch_dsa_32(tmp->dsa, dsa_next, 0, 0);
++    /*
++     * XXX is this giving 53c710 access to the Scsi_Cmnd in some way?
++     * Do we need to change it for caching reasons?
++     */
++    patch_dsa_32(tmp->dsa, dsa_cmnd, 0, virt_to_bus(cmd));
++
++    if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) {
++
++      exp_select_indirect = ((1 << cmd->device->id) << 16) |
++                      (hostdata->sync[cmd->device->id].sxfer_sanity << 8);
++
++      if (hostdata->sync[cmd->device->id].select_indirect !=
++                              exp_select_indirect) {
++          printk ("scsi%d :  sanity check failed select_indirect=0x%x\n",
++              host->host_no, hostdata->sync[cmd->device->id].select_indirect);
++          FATAL(host);
++
++      }
++    }
++
++    patch_dsa_32(tmp->dsa, dsa_select, 0,
++              hostdata->sync[cmd->device->id].select_indirect);
++
++    /*
++     * Right now, we'll do the WIDE and SYNCHRONOUS negotiations on
++     * different commands; although it should be trivial to do them
++     * both at the same time.
++     */
++    if (hostdata->initiate_wdtr & (1 << cmd->device->id)) {
++      memcpy ((void *) (tmp->select + 1), (void *) wdtr_message,
++          sizeof(wdtr_message));
++      patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(wdtr_message));
++      local_irq_save(flags);
++      hostdata->initiate_wdtr &= ~(1 << cmd->device->id);
++      local_irq_restore(flags);
++    } else if (hostdata->initiate_sdtr & (1 << cmd->device->id)) {
++      memcpy ((void *) (tmp->select + 1), (void *) sdtr_message, 
++          sizeof(sdtr_message));
++      patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(sdtr_message));
++      tmp->flags |= CMD_FLAG_SDTR;
++      local_irq_save(flags);
++      hostdata->initiate_sdtr &= ~(1 << cmd->device->id);
++      local_irq_restore(flags);
++    
++    }
++#if 1
++    else if (!(hostdata->talked_to & (1 << cmd->device->id)) &&
++              !(hostdata->options & OPTION_NO_ASYNC)) {
++
++      memcpy ((void *) (tmp->select + 1), (void *) async_message, 
++          sizeof(async_message));
++      patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(async_message));
++      tmp->flags |= CMD_FLAG_SDTR;
++    } 
++#endif
++    else 
++      patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1);
++
++    hostdata->talked_to |= (1 << cmd->device->id);
++    tmp->select[0] = (hostdata->options & OPTION_DISCONNECT) ? 
++      IDENTIFY (1, cmd->device->lun) : IDENTIFY (0, cmd->device->lun);
++    patch_dsa_32(tmp->dsa, dsa_msgout, 1, virt_to_bus(tmp->select));
++    patch_dsa_32(tmp->dsa, dsa_cmdout, 0, cmd->cmd_len);
++    patch_dsa_32(tmp->dsa, dsa_cmdout, 1, virt_to_bus(tmp->cmnd));
++    patch_dsa_32(tmp->dsa, dsa_dataout, 0, cmd_dataout ? 
++          virt_to_bus (cmd_dataout)
++      : virt_to_bus (hostdata->script) + hostdata->E_other_transfer);
++    patch_dsa_32(tmp->dsa, dsa_datain, 0, cmd_datain ? 
++          virt_to_bus (cmd_datain) 
++      : virt_to_bus (hostdata->script) + hostdata->E_other_transfer);
++    /* 
++     * XXX - need to make endian aware, should use separate variables
++     * for both status and message bytes.
++     */
++    patch_dsa_32(tmp->dsa, dsa_msgin, 0, 1);
++/* 
++ * FIXME : these only works for little endian.  We probably want to 
++ *    provide message and status fields in the NCR53c7x0_cmd 
++ *    structure, and assign them to cmd->result when we're done.
++ */
++#ifdef BIG_ENDIAN
++    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 2);
++    patch_dsa_32(tmp->dsa, dsa_status, 0, 1);
++    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result) + 3);
++#else
++    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 1);
++    patch_dsa_32(tmp->dsa, dsa_status, 0, 1);
++    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result));
++#endif
++    patch_dsa_32(tmp->dsa, dsa_msgout_other, 0, 1);
++    patch_dsa_32(tmp->dsa, dsa_msgout_other, 1, 
++      virt_to_bus(&(hostdata->NCR53c7xx_msg_nop)));
++    
++    /*
++     * Generate code for zero or more of the DATA IN, DATA OUT phases 
++     * in the format 
++     *
++     * CALL data_transfer, WHEN NOT phase
++     * MOVE first buffer length, first buffer address, WHEN phase
++     * ...
++     * MOVE last buffer length, last buffer address, WHEN phase
++     * JUMP other_transfer
++     */
++
++/* 
++ * See if we're getting to data transfer by generating an unconditional 
++ * interrupt.
++ */
++#if 0
++    if (datain) {
++      cmd_datain[0] = 0x98080000;
++      cmd_datain[1] = 0x03ffd00d;
++      cmd_datain += 2;
++    }
++#endif
++
++/* 
++ * XXX - I'm undecided whether all of this nonsense is faster
++ * in the long run, or whether I should just go and implement a loop
++ * on the NCR chip using table indirect mode?
++ *
++ * In any case, this is how it _must_ be done for 53c700/700-66 chips,
++ * so this stays even when we come up with something better.
++ *
++ * When we're limited to 1 simultaneous command, no overlapping processing,
++ * we're seeing 630K/sec, with 7% CPU usage on a slow Syquest 45M
++ * drive.
++ *
++ * Not bad, not good. We'll see.
++ */
++
++    tmp->bounce.len = 0;      /* Assume aligned buffer */
++
++    for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4, 
++      cmd_dataout += 4, ++i) {
++      u32 vbuf = cmd->use_sg
++          ? (u32)page_address(((struct scatterlist *)cmd->request_buffer)[i].page)+
++            ((struct scatterlist *)cmd->request_buffer)[i].offset
++          : (u32)(cmd->request_buffer);
++      u32 bbuf = virt_to_bus((void *)vbuf);
++      u32 count = cmd->use_sg ?
++          ((struct scatterlist *)cmd->request_buffer)[i].length :
++          cmd->request_bufflen;
 +
-+      lpfc_read_sparam(phba, pmb, vport->vpi);
 +      /*
-+       * Grab buffer pointer and clear context1 so we can use
-+       * lpfc_sli_issue_box_wait
++       * If we have buffers which are not aligned with 16 byte cache
++       * lines, then we just hope nothing accesses the other parts of
++       * those cache lines while the transfer is in progress.  That would
++       * fill the cache, and subsequent reads of the dma data would pick
++       * up the wrong thing.
++       * XXX We need a bounce buffer to handle that correctly.
 +       */
-+      mp = (struct lpfc_dmabuf *) pmb->context1;
-+      pmb->context1 = NULL;
 +
-+      pmb->vport = vport;
-+      rc = lpfc_sli_issue_mbox_wait(phba, pmb, phba->fc_ratov * 2);
-+      if (rc != MBX_SUCCESS) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
-+                              "%d (%d):1818 VPort failed init, mbxCmd x%x "
-+                              "READ_SPARM mbxStatus x%x, rc = x%x\n",
-+                              phba->brd_no, vport->vpi,
-+                              mb->mbxCommand, mb->mbxStatus, rc);
-+              lpfc_mbuf_free(phba, mp->virt, mp->phys);
-+              kfree(mp);
-+              if (rc != MBX_TIMEOUT)
-+                      mempool_free(pmb, phba->mbox_mem_pool);
-+              return -EIO;
++      if (((bbuf & 15) || (count & 15)) && (datain || dataout))
++      {
++          /* Bounce buffer needed */
++          if (cmd->use_sg)
++              printk ("53c7xx: Non-aligned buffer with use_sg\n");
++          else if (datain && dataout)
++                printk ("53c7xx: Non-aligned buffer with datain && dataout\n");
++            else if (count > 256)
++              printk ("53c7xx: Non-aligned transfer > 256 bytes\n");
++          else
++          {
++                  if (datain)
++                  {
++                      tmp->bounce.len = count;
++                      tmp->bounce.addr = vbuf;
++                      bbuf = virt_to_bus(tmp->bounce.buf);
++                      tmp->bounce.buf[0] = 0xff;
++                      tmp->bounce.buf[1] = 0xfe;
++                      tmp->bounce.buf[2] = 0xfd;
++                      tmp->bounce.buf[3] = 0xfc;
++                  }
++                  if (dataout)
++                  {
++                      memcpy ((void *)tmp->bounce.buf, (void *)vbuf, count);
++                      bbuf = virt_to_bus(tmp->bounce.buf);
++                  }
++          }
++      }
++
++      if (datain) {
++            cache_clear(virt_to_phys((void *)vbuf), count);
++          /* CALL other_in, WHEN NOT DATA_IN */  
++          cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL | 
++              DCMD_TCI_IO) << 24) | 
++              DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
++          cmd_datain[1] = virt_to_bus (hostdata->script) + 
++              hostdata->E_other_in;
++          /* MOVE count, buf, WHEN DATA_IN */
++          cmd_datain[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | DCMD_BMI_IO) 
++              << 24) | count;
++          cmd_datain[3] = bbuf;
++#if 0
++          print_insn (host, cmd_datain, "dynamic ", 1);
++          print_insn (host, cmd_datain + 2, "dynamic ", 1);
++#endif
++      }
++      if (dataout) {
++            cache_push(virt_to_phys((void *)vbuf), count);
++          /* CALL other_out, WHEN NOT DATA_OUT */
++          cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL) << 24) | 
++              DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
++          cmd_dataout[1] = virt_to_bus(hostdata->script) + 
++              hostdata->E_other_out;
++          /* MOVE count, buf, WHEN DATA+OUT */
++          cmd_dataout[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I) << 24) 
++              | count;
++          cmd_dataout[3] = bbuf;
++#if 0
++          print_insn (host, cmd_dataout, "dynamic ", 1);
++          print_insn (host, cmd_dataout + 2, "dynamic ", 1);
++#endif
 +      }
++    }
 +
-+      memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
-+      memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
-+             sizeof (struct lpfc_name));
-+      memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
-+             sizeof (struct lpfc_name));
++    /*
++     * Install JUMP instructions after the data transfer routines to return
++     * control to the do_other_transfer routines.
++     */
++  
++    
++    if (datain) {
++      cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) |
++          DBC_TCI_TRUE;
++      cmd_datain[1] = virt_to_bus(hostdata->script) + 
++          hostdata->E_other_transfer;
++#if 0
++      print_insn (host, cmd_datain, "dynamic jump ", 1);
++#endif
++      cmd_datain += 2; 
++    }
++#if 0
++    if (datain) {
++      cmd_datain[0] = 0x98080000;
++      cmd_datain[1] = 0x03ffdeed;
++      cmd_datain += 2;
++    }
++#endif
++    if (dataout) {
++      cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) |
++          DBC_TCI_TRUE;
++      cmd_dataout[1] = virt_to_bus(hostdata->script) + 
++          hostdata->E_other_transfer;
++#if 0
++      print_insn (host, cmd_dataout, "dynamic jump ", 1);
++#endif
++      cmd_dataout += 2;
++    }
 +
-+      lpfc_mbuf_free(phba, mp->virt, mp->phys);
-+      kfree(mp);
-+      mempool_free(pmb, phba->mbox_mem_pool);
++    return tmp;
++}
++
++/*
++ * Function : int NCR53c7xx_queue_command (Scsi_Cmnd *cmd,
++ *      void (*done)(Scsi_Cmnd *))
++ *
++ * Purpose :  enqueues a SCSI command
++ *
++ * Inputs : cmd - SCSI command, done - function called on completion, with
++ *      a pointer to the command descriptor.
++ *
++ * Returns : 0
++ *
++ * Side effects :
++ *      cmd is added to the per instance driver issue_queue, with major
++ *      twiddling done to the host specific fields of cmd.  If the
++ *      process_issue_queue coroutine isn't running, it is restarted.
++ * 
++ * NOTE : we use the host_scribble field of the Scsi_Cmnd structure to 
++ *    hold our own data, and pervert the ptr field of the SCp field
++ *    to create a linked list.
++ */
++
++int
++NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) {
++    struct Scsi_Host *host = cmd->device->host;
++    struct NCR53c7x0_hostdata *hostdata = 
++      (struct NCR53c7x0_hostdata *) host->hostdata[0];
++    unsigned long flags;
++    Scsi_Cmnd *tmp;
++
++    cmd->scsi_done = done;
++    cmd->host_scribble = NULL;
++    cmd->SCp.ptr = NULL;
++    cmd->SCp.buffer = NULL;
++
++#ifdef VALID_IDS
++    /* Ignore commands on invalid IDs */
++    if (!hostdata->valid_ids[cmd->device->id]) {
++        printk("scsi%d : ignoring target %d lun %d\n", host->host_no,
++            cmd->device->id, cmd->device->lun);
++        cmd->result = (DID_BAD_TARGET << 16);
++        done(cmd);
++        return 0;
++    }
++#endif
++
++    local_irq_save(flags);
++    if ((hostdata->options & (OPTION_DEBUG_INIT_ONLY|OPTION_DEBUG_PROBE_ONLY)) 
++      || ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) &&
++          !(hostdata->debug_lun_limit[cmd->device->id] & (1 << cmd->device->lun)))
++#ifdef LINUX_1_2
++      || cmd->device->id > 7
++#else
++      || cmd->device->id >= host->max_id
++#endif
++      || cmd->device->id == host->this_id
++      || hostdata->state == STATE_DISABLED) {
++      printk("scsi%d : disabled or bad target %d lun %d\n", host->host_no,
++          cmd->device->id, cmd->device->lun);
++      cmd->result = (DID_BAD_TARGET << 16);
++      done(cmd);
++      local_irq_restore(flags);
++      return 0;
++    }
 +
++    if ((hostdata->options & OPTION_DEBUG_NCOMMANDS_LIMIT) &&
++      (hostdata->debug_count_limit == 0)) {
++      printk("scsi%d : maximum commands exceeded\n", host->host_no);
++      cmd->result = (DID_BAD_TARGET << 16);
++      done(cmd);
++      local_irq_restore(flags);
 +      return 0;
++    }
++
++    if (hostdata->options & OPTION_DEBUG_READ_ONLY) {
++      switch (cmd->cmnd[0]) {
++      case WRITE_6:
++      case WRITE_10:
++          printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n",
++              host->host_no);
++          cmd->result = (DID_BAD_TARGET << 16);
++          done(cmd);
++          local_irq_restore(flags);
++          return 0;
++      }
++    }
++
++    if ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) &&
++          hostdata->debug_count_limit != -1) 
++      --hostdata->debug_count_limit;
++
++    cmd->result = 0xffff;     /* The NCR will overwrite message
++                                     and status with valid data */
++    cmd->host_scribble = (unsigned char *) tmp = create_cmd (cmd);
++
++    /*
++     * REQUEST SENSE commands are inserted at the head of the queue 
++     * so that we do not clear the contingent allegiance condition
++     * they may be looking at.
++     */
++
++    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
++      cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
++      hostdata->issue_queue = cmd;
++    } else {
++      for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->SCp.ptr; 
++              tmp = (Scsi_Cmnd *) tmp->SCp.ptr);
++      tmp->SCp.ptr = (unsigned char *) cmd;
++    }
++    local_irq_restore(flags);
++    run_process_issue_queue();
++    return 0;
 +}
 +
-+static int
-+lpfc_valid_wwn_format(struct lpfc_hba *phba, struct lpfc_name *wwn,
-+                    const char *name_type)
-+{
-+                              /* ensure that IEEE format 1 addresses
-+                               * contain zeros in bits 59-48
-+                               */
-+      if (!((wwn->u.wwn[0] >> 4) == 1 &&
-+            ((wwn->u.wwn[0] & 0xf) != 0 || (wwn->u.wwn[1] & 0xf) != 0)))
-+              return 1;
++/*
++ * Function : void to_schedule_list (struct Scsi_Host *host,
++ *    struct NCR53c7x0_hostdata * hostdata, Scsi_Cmnd *cmd)
++ *
++ * Purpose : takes a SCSI command which was just removed from the 
++ *    issue queue, and deals with it by inserting it in the first
++ *    free slot in the schedule list or by terminating it immediately.
++ *
++ * Inputs : 
++ *    host - SCSI host adapter; hostdata - hostdata structure for 
++ *    this adapter; cmd - a pointer to the command; should have 
++ *    the host_scribble field initialized to point to a valid 
++ *    
++ * Side effects : 
++ *      cmd is added to the per instance schedule list, with minor 
++ *      twiddling done to the host specific fields of cmd.
++ *
++ */
 +
-+      lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
-+                      "%d:1822 Invalid %s: %02x:%02x:%02x:%02x:"
-+                      "%02x:%02x:%02x:%02x\n",
-+                      phba->brd_no, name_type,
-+                      wwn->u.wwn[0], wwn->u.wwn[1],
-+                      wwn->u.wwn[2], wwn->u.wwn[3],
-+                      wwn->u.wwn[4], wwn->u.wwn[5],
-+                      wwn->u.wwn[6], wwn->u.wwn[7]);
-+      return 0;
++static __inline__ void
++to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
++    struct NCR53c7x0_cmd *cmd) {
++    NCR53c7x0_local_declare();
++    Scsi_Cmnd *tmp = cmd->cmd;
++    unsigned long flags;
++    /* dsa start is negative, so subtraction is used */
++    volatile u32 *ncrcurrent;
++
++    int i;
++    NCR53c7x0_local_setup(host);
++#if 0
++    printk("scsi%d : new dsa is 0x%lx (virt 0x%p)\n", host->host_no, 
++      virt_to_bus(hostdata->dsa), hostdata->dsa);
++#endif
++
++    local_irq_save(flags);
++    
++    /* 
++     * Work around race condition : if an interrupt fired and we 
++     * got disabled forget about this command.
++     */
++
++    if (hostdata->state == STATE_DISABLED) {
++      printk("scsi%d : driver disabled\n", host->host_no);
++      tmp->result = (DID_BAD_TARGET << 16);
++      cmd->next = (struct NCR53c7x0_cmd *) hostdata->free;
++      hostdata->free = cmd;
++      tmp->scsi_done(tmp);
++      local_irq_restore(flags);
++      return;
++    }
++
++    for (i = host->can_queue, ncrcurrent = hostdata->schedule; 
++      i > 0  && ncrcurrent[0] != hostdata->NOP_insn;
++      --i, ncrcurrent += 2 /* JUMP instructions are two words */);
++
++    if (i > 0) {
++      ++hostdata->busy[tmp->device->id][tmp->device->lun];
++      cmd->next = hostdata->running_list;
++      hostdata->running_list = cmd;
++
++      /* Restore this instruction to a NOP once the command starts */
++      cmd->dsa [(hostdata->dsa_jump_dest - hostdata->dsa_start) / 
++          sizeof(u32)] = (u32) virt_to_bus ((void *)ncrcurrent);
++      /* Replace the current jump operand.  */
++      ncrcurrent[1] =
++          virt_to_bus ((void *) cmd->dsa) + hostdata->E_dsa_code_begin -
++          hostdata->E_dsa_code_template;
++      /* Replace the NOP instruction with a JUMP */
++      ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) |
++          DBC_TCI_TRUE;
++    }  else {
++      printk ("scsi%d: no free slot\n", host->host_no);
++      disable(host);
++      tmp->result = (DID_ERROR << 16);
++      cmd->next = (struct NCR53c7x0_cmd *) hostdata->free;
++      hostdata->free = cmd;
++      tmp->scsi_done(tmp);
++      local_irq_restore(flags);
++      return;
++    }
++
++    /* 
++     * If the NCR chip is in an idle state, start it running the scheduler
++     * immediately.  Otherwise, signal the chip to jump to schedule as 
++     * soon as it is idle.
++     */
++
++    if (hostdata->idle) {
++      hostdata->idle = 0;
++      hostdata->state = STATE_RUNNING;
++      NCR53c7x0_write32 (DSP_REG,  virt_to_bus ((void *)hostdata->schedule));
++      if (hostdata->options & OPTION_DEBUG_TRACE)
++          NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
++                              DCNTL_SSM | DCNTL_STD);
++    } else {
++      NCR53c7x0_write8(hostdata->istat, ISTAT_10_SIGP);
++    }
++
++    local_irq_restore(flags);
 +}
 +
-+static int
-+lpfc_unique_wwpn(struct lpfc_hba *phba, struct lpfc_vport *new_vport)
-+{
-+      struct lpfc_vport *vport;
++/*
++ * Function : busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata 
++ *    *hostdata, Scsi_Cmnd *cmd)
++ *
++ * Purpose : decide if we can pass the given SCSI command on to the 
++ *    device in question or not.
++ *  
++ * Returns : non-zero when we're busy, 0 when we aren't.
++ */
 +
-+      list_for_each_entry(vport, &phba->port_list, listentry) {
-+              if (vport == new_vport)
-+                      continue;
-+              /* If they match, return not unique */
-+              if (memcmp(&vport->fc_sparam.portName,
-+                      &new_vport->fc_sparam.portName,
-+                      sizeof(struct lpfc_name)) == 0)
-+                      return 0;
-+      }
-+      return 1;
++static __inline__ int
++busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, 
++    Scsi_Cmnd *cmd) {
++    /* FIXME : in the future, this needs to accommodate SCSI-II tagged
++       queuing, and we may be able to play with fairness here a bit.
++     */
++    return hostdata->busy[cmd->device->id][cmd->device->lun];
 +}
 +
-+int
-+lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
-+{
-+      struct lpfc_nodelist *ndlp;
-+      struct lpfc_vport *pport =
-+              (struct lpfc_vport *) fc_vport->shost->hostdata;
-+      struct lpfc_hba   *phba = pport->phba;
-+      struct lpfc_vport *vport = NULL;
-+      int instance;
-+      int vpi;
-+      int rc = VPORT_ERROR;
-+
-+      if ((phba->sli_rev < 3) ||
-+              !(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
-+                              "%d:1808 Create VPORT failed: "
-+                              "NPIV is not enabled: SLImode:%d\n",
-+                              phba->brd_no, phba->sli_rev);
-+              rc = VPORT_INVAL;
-+              goto error_out;
-+      }
-+
-+      vpi = lpfc_alloc_vpi(phba);
-+      if (vpi == 0) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
-+                              "%d:1809 Create VPORT failed: "
-+                              "Max VPORTs (%d) exceeded\n",
-+                              phba->brd_no, phba->max_vpi);
-+              rc = VPORT_NORESOURCES;
-+              goto error_out;
-+      }
-+
-+
-+      /* Assign an unused board number */
-+      if ((instance = lpfc_get_instance()) < 0) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
-+                              "%d:1810 Create VPORT failed: Cannot get "
-+                              "instance number\n", phba->brd_no);
-+              lpfc_free_vpi(phba, vpi);
-+              rc = VPORT_NORESOURCES;
-+              goto error_out;
-+      }
-+
-+      vport = lpfc_create_port(phba, instance, fc_vport);
-+      if (!vport) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
-+                              "%d:1811 Create VPORT failed: vpi x%x\n",
-+                              phba->brd_no, vpi);
-+              lpfc_free_vpi(phba, vpi);
-+              rc = VPORT_NORESOURCES;
-+              goto error_out;
-+      }
-+
-+      vport->vpi = vpi;
-+      lpfc_debugfs_initialize(vport);
-+
-+      if (lpfc_vport_sparm(phba, vport)) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
-+                              "%d:1813 Create VPORT failed: vpi:%d "
-+                              "Cannot get sparam\n",
-+                              phba->brd_no, vpi);
-+              lpfc_free_vpi(phba, vpi);
-+              destroy_port(vport);
-+              rc = VPORT_NORESOURCES;
-+              goto error_out;
-+      }
-+
-+      memcpy(vport->fc_portname.u.wwn, vport->fc_sparam.portName.u.wwn, 8);
-+      memcpy(vport->fc_nodename.u.wwn, vport->fc_sparam.nodeName.u.wwn, 8);
-+
-+      if (fc_vport->node_name != 0)
-+              u64_to_wwn(fc_vport->node_name, vport->fc_nodename.u.wwn);
-+      if (fc_vport->port_name != 0)
-+              u64_to_wwn(fc_vport->port_name, vport->fc_portname.u.wwn);
-+
-+      memcpy(&vport->fc_sparam.portName, vport->fc_portname.u.wwn, 8);
-+      memcpy(&vport->fc_sparam.nodeName, vport->fc_nodename.u.wwn, 8);
-+
-+      if (!lpfc_valid_wwn_format(phba, &vport->fc_sparam.nodeName, "WWNN") ||
-+          !lpfc_valid_wwn_format(phba, &vport->fc_sparam.portName, "WWPN")) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
-+                              "%d:1821 Create VPORT failed: vpi:%d "
-+                              "Invalid WWN format\n",
-+                              phba->brd_no, vpi);
-+              lpfc_free_vpi(phba, vpi);
-+              destroy_port(vport);
-+              rc = VPORT_INVAL;
-+              goto error_out;
-+      }
-+
-+      if (!lpfc_unique_wwpn(phba, vport)) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
-+                              "%d:1823 Create VPORT failed: vpi:%d "
-+                              "Duplicate WWN on HBA\n",
-+                              phba->brd_no, vpi);
-+              lpfc_free_vpi(phba, vpi);
-+              destroy_port(vport);
-+              rc = VPORT_INVAL;
-+              goto error_out;
-+      }
-+
-+      *(struct lpfc_vport **)fc_vport->dd_data = vport;
-+      vport->fc_vport = fc_vport;
-+
-+      if ((phba->link_state < LPFC_LINK_UP) ||
-+          (phba->fc_topology == TOPOLOGY_LOOP)) {
-+              lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
-+              rc = VPORT_OK;
-+              goto out;
-+      }
++/*
++ * Function : process_issue_queue (void)
++ *
++ * Purpose : transfer commands from the issue queue to NCR start queue 
++ *    of each NCR53c7/8xx in the system, avoiding kernel stack 
++ *    overflows when the scsi_done() function is invoked recursively.
++ * 
++ * NOTE : process_issue_queue exits with interrupts *disabled*, so the 
++ *    caller must reenable them if it desires.
++ * 
++ * NOTE : process_issue_queue should be called from both 
++ *    NCR53c7x0_queue_command() and from the interrupt handler 
++ *    after command completion in case NCR53c7x0_queue_command()
++ *    isn't invoked again but we've freed up resources that are
++ *    needed.
++ */
++
++static void 
++process_issue_queue (unsigned long flags) {
++    Scsi_Cmnd *tmp, *prev;
++    struct Scsi_Host *host;
++    struct NCR53c7x0_hostdata *hostdata;
++    int done;
++
++    /*
++     * We run (with interrupts disabled) until we're sure that none of 
++     * the host adapters have anything that can be done, at which point 
++     * we set process_issue_queue_running to 0 and exit.
++     *
++     * Interrupts are enabled before doing various other internal 
++     * instructions, after we've decided that we need to run through
++     * the loop again.
++     *
++     */
++
++    do {
++      local_irq_disable(); /* Freeze request queues */
++      done = 1;
++      for (host = first_host; host && host->hostt == the_template;
++          host = host->next) {
++          hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
++          local_irq_disable();
++          if (hostdata->issue_queue) {
++              if (hostdata->state == STATE_DISABLED) {
++                  tmp = (Scsi_Cmnd *) hostdata->issue_queue;
++                  hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;
++                  tmp->result = (DID_BAD_TARGET << 16);
++                  if (tmp->host_scribble) {
++                      ((struct NCR53c7x0_cmd *)tmp->host_scribble)->next = 
++                          hostdata->free;
++                      hostdata->free = 
++                          (struct NCR53c7x0_cmd *)tmp->host_scribble;
++                      tmp->host_scribble = NULL;
++                  }
++                  tmp->scsi_done (tmp);
++                  done = 0;
++              } else 
++                  for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, 
++                      prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) 
++                      tmp->SCp.ptr) 
++                      if (!tmp->host_scribble || 
++                          !busyp (host, hostdata, tmp)) {
++                              if (prev)
++                                  prev->SCp.ptr = tmp->SCp.ptr;
++                              else
++                                  hostdata->issue_queue = (Scsi_Cmnd *) 
++                                      tmp->SCp.ptr;
++                          tmp->SCp.ptr = NULL;
++                          if (tmp->host_scribble) {
++                              if (hostdata->options & OPTION_DEBUG_QUEUES) 
++                                  printk ("scsi%d : moving command for target %d lun %d to start list\n",
++                                      host->host_no, tmp->device->id, tmp->device->lun);
++              
++
++                              to_schedule_list (host, hostdata, 
++                                  (struct NCR53c7x0_cmd *)
++                                  tmp->host_scribble);
++                          } else {
++                              if (((tmp->result & 0xff) == 0xff) ||
++                                  ((tmp->result & 0xff00) == 0xff00)) {
++                                  printk ("scsi%d : danger Will Robinson!\n",
++                                      host->host_no);
++                                  tmp->result = DID_ERROR << 16;
++                                  disable (host);
++                              }
++                              tmp->scsi_done(tmp);
++                          }
++                          done = 0;
++                      } /* if target/lun is not busy */
++          } /* if hostdata->issue_queue */
++          if (!done)
++              local_irq_restore(flags);
++      } /* for host */
++    } while (!done);
++    process_issue_queue_running = 0;
++}
 +
-+      if (disable) {
-+              rc = VPORT_OK;
-+              goto out;
++/*
++ * Function : static void intr_scsi (struct Scsi_Host *host, 
++ *    struct NCR53c7x0_cmd *cmd)
++ *
++ * Purpose : handle all SCSI interrupts, indicated by the setting 
++ *    of the SIP bit in the ISTAT register.
++ *
++ * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
++ *    may be NULL.
++ */
++
++static void 
++intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
++    NCR53c7x0_local_declare();
++    struct NCR53c7x0_hostdata *hostdata = 
++      (struct NCR53c7x0_hostdata *) host->hostdata[0];
++    unsigned char sstat0_sist0, sist1,                /* Registers */
++          fatal;                              /* Did a fatal interrupt 
++                                                 occur ? */
++   
++    NCR53c7x0_local_setup(host);
++
++    fatal = 0;
++
++    sstat0_sist0 = NCR53c7x0_read8(SSTAT0_REG);
++    sist1 = 0;
++
++    if (hostdata->options & OPTION_DEBUG_INTR) 
++      printk ("scsi%d : SIST0 0x%0x, SIST1 0x%0x\n", host->host_no,
++          sstat0_sist0, sist1);
++
++    /* 250ms selection timeout */
++    if (sstat0_sist0 & SSTAT0_700_STO) {
++      fatal = 1;
++      if (hostdata->options & OPTION_DEBUG_INTR) {
++          printk ("scsi%d : Selection Timeout\n", host->host_no);
++          if (cmd) {
++              printk("scsi%d : target %d, lun %d, command ",
++                  host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun);
++              __scsi_print_command (cmd->cmd->cmnd);
++              printk("scsi%d : dsp = 0x%x (virt 0x%p)\n", host->host_no,
++                  NCR53c7x0_read32(DSP_REG),
++                  bus_to_virt(NCR53c7x0_read32(DSP_REG)));
++          } else {
++              printk("scsi%d : no command\n", host->host_no);
++          }
++      }
++/*
++ * XXX - question : how do we want to handle the Illegal Instruction
++ *    interrupt, which may occur before or after the Selection Timeout
++ *    interrupt?
++ */
++
++      if (1) {
++          hostdata->idle = 1;
++          hostdata->expecting_sto = 0;
++
++          if (hostdata->test_running) {
++              hostdata->test_running = 0;
++              hostdata->test_completed = 3;
++          } else if (cmd) {
++              abnormal_finished(cmd, DID_BAD_TARGET << 16);
++          }
++#if 0     
++          hostdata->intrs = 0;
++#endif
 +      }
++    } 
 +
-+      /* Use the Physical nodes Fabric NDLP to determine if the link is
-+       * up and ready to FDISC.
++/*
++ * FIXME : in theory, we can also get a UDC when a STO occurs.
++ */
++    if (sstat0_sist0 & SSTAT0_UDC) {
++      fatal = 1;
++      if (cmd) {
++          printk("scsi%d : target %d lun %d unexpected disconnect\n",
++              host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun);
++          print_lots (host);
++          abnormal_finished(cmd, DID_ERROR << 16);
++      } else 
++           printk("scsi%d : unexpected disconnect (no command)\n",
++              host->host_no);
++
++      hostdata->dsp = (u32 *) hostdata->schedule;
++      hostdata->dsp_changed = 1;
++    }
++
++    /* SCSI PARITY error */
++    if (sstat0_sist0 & SSTAT0_PAR) {
++      fatal = 1;
++      if (cmd && cmd->cmd) {
++          printk("scsi%d : target %d lun %d parity error.\n",
++              host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun);
++          abnormal_finished (cmd, DID_PARITY << 16); 
++      } else
++          printk("scsi%d : parity error\n", host->host_no);
++      /* Should send message out, parity error */
++
++      /* XXX - Reduce synchronous transfer rate! */
++      hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
++          sizeof(u32);
++      hostdata->dsp_changed = 1; 
++    /* SCSI GROSS error */
++    } 
++
++    if (sstat0_sist0 & SSTAT0_SGE) {
++      fatal = 1;
++      printk("scsi%d : gross error, saved2_dsa = 0x%x\n", host->host_no,
++                                      (unsigned int)hostdata->saved2_dsa);
++      print_lots (host);
++      
++      /* 
++         * A SCSI gross error may occur when we have 
++       *
++       * - A synchronous offset which causes the SCSI FIFO to be overwritten.
++       *
++       * - A REQ which causes the maximum synchronous offset programmed in 
++       *      the SXFER register to be exceeded.
++       *
++       * - A phase change with an outstanding synchronous offset.
++       *
++       * - Residual data in the synchronous data FIFO, with a transfer
++       *      other than a synchronous receive is started.$#
 +       */
-+      ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
-+      if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
-+              if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
-+                      lpfc_set_disctmo(vport);
-+                      lpfc_initial_fdisc(vport);
-+              } else {
-+                      lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                                      "%d (%d):0262 No NPIV Fabric "
-+                                      "support\n",
-+                                      phba->brd_no, vport->vpi);
-+              }
-+      } else {
-+              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
++              
++
++      /* XXX Should deduce synchronous transfer rate! */
++      hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
++          sizeof(u32);
++      hostdata->dsp_changed = 1;
++    /* Phase mismatch */
++    } 
++
++    if (sstat0_sist0 & SSTAT0_MA) {
++      fatal = 1;
++      if (hostdata->options & OPTION_DEBUG_INTR)
++          printk ("scsi%d : SSTAT0_MA\n", host->host_no);
++      intr_phase_mismatch (host, cmd);
++    }
++
++#if 0
++    if (sstat0_sist0 & SIST0_800_RSL) 
++      printk ("scsi%d : Oh no Mr. Bill!\n", host->host_no);
++#endif
++    
++/*
++ * If a fatal SCSI interrupt occurs, we must insure that the DMA and
++ * SCSI FIFOs were flushed.
++ */
++
++    if (fatal) {
++      if (!hostdata->dstat_valid) {
++          hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
++          hostdata->dstat_valid = 1;
 +      }
-+      rc = VPORT_OK;
 +
-+out:
-+      lpfc_host_attrib_init(lpfc_shost_from_vport(vport));
-+error_out:
-+      return rc;
++      if (!(hostdata->dstat & DSTAT_DFE)) {
++        printk ("scsi%d : DMA FIFO not empty\n", host->host_no);
++        /*
++         * Really need to check this code for 710  RGH.
++         * Havn't seen any problems, but maybe we should FLUSH before
++         * clearing sometimes.
++         */
++          NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
++          while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF)
++              ;
++        hostdata->dstat |= DSTAT_DFE;
++      }
++    }
 +}
 +
-+int
-+disable_vport(struct fc_vport *fc_vport)
++#ifdef CYCLIC_TRACE
++
++/*
++ * The following implements a cyclic log of instructions executed, if you turn
++ * TRACE on.  It will also print the log for you.  Very useful when debugging
++ * 53c710 support, possibly not really needed any more.
++ */
++
++u32 insn_log[4096];
++u32 insn_log_index = 0;
++
++void log1 (u32 i)
++{
++      insn_log[insn_log_index++] = i;
++      if (insn_log_index == 4096)
++              insn_log_index = 0;
++}
++
++void log_insn (u32 *ip)
++{
++      log1 ((u32)ip);
++      log1 (*ip);
++      log1 (*(ip+1));
++      if (((*ip >> 24) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI)
++              log1 (*(ip+2));
++}
++
++void dump_log(void)
 +{
-+      struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
-+      struct lpfc_hba   *phba = vport->phba;
-+      struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
-+      long timeout;
++      int cnt = 0;
++      int i = insn_log_index;
++      int size;
++      struct Scsi_Host *host = first_host;
 +
-+      ndlp = lpfc_findnode_did(vport, Fabric_DID);
-+      if (ndlp && phba->link_state >= LPFC_LINK_UP) {
-+              vport->unreg_vpi_cmpl = VPORT_INVAL;
-+              timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
-+              if (!lpfc_issue_els_npiv_logo(vport, ndlp))
-+                      while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
-+                              timeout = schedule_timeout(timeout);
++      while (cnt < 4096) {
++              printk ("%08x (+%6x): ", insn_log[i], (insn_log[i] - (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4);
++              if (++i == 4096)
++                      i = 0;
++              cnt++;
++              if (((insn_log[i]  >> 24) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI) 
++                      size = 3;
++              else
++                      size = 2;
++              while (size--) {
++                      printk ("%08x ", insn_log[i]);
++                      if (++i == 4096)
++                              i = 0;
++                      cnt++;
++              }
++              printk ("\n");
 +      }
++}
++#endif
++
 +
-+      lpfc_sli_host_down(vport);
++/*
++ * Function : static void NCR53c7x0_intfly (struct Scsi_Host *host)
++ *
++ * Purpose : Scan command queue for specified host, looking for completed
++ *           commands.
++ * 
++ * Inputs : Scsi_Host pointer.
++ *
++ *    This is called from the interrupt handler, when a simulated INTFLY
++ *    interrupt occurs.
++ */
 +
-+      /* Mark all nodes for discovery so we can remove them by
-+       * calling lpfc_cleanup_rpis(vport, 1)
++static void
++NCR53c7x0_intfly (struct Scsi_Host *host)
++{
++    NCR53c7x0_local_declare();
++    struct NCR53c7x0_hostdata *hostdata;      /* host->hostdata[0] */
++    struct NCR53c7x0_cmd *cmd,                        /* command which halted */
++      **cmd_prev_ptr;
++    unsigned long flags;                              
++    char search_found = 0;                    /* Got at least one ? */
++
++    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
++    NCR53c7x0_local_setup(host);
++
++    if (hostdata->options & OPTION_DEBUG_INTR)
++    printk ("scsi%d : INTFLY\n", host->host_no); 
++
++    /*
++    * Traverse our list of running commands, and look
++    * for those with valid (non-0xff ff) status and message
++    * bytes encoded in the result which signify command
++    * completion.
++    */
++
++    local_irq_save(flags);
++restart:
++    for (cmd_prev_ptr = (struct NCR53c7x0_cmd **)&(hostdata->running_list),
++      cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ;
++      cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next), 
++      cmd = (struct NCR53c7x0_cmd *) cmd->next)
++    {
++      Scsi_Cmnd *tmp;
++
++      if (!cmd) {
++          printk("scsi%d : very weird.\n", host->host_no);
++          break;
++      }
++
++      if (!(tmp = cmd->cmd)) {
++          printk("scsi%d : weird.  NCR53c7x0_cmd has no Scsi_Cmnd\n",
++                  host->host_no);
++          continue;
++      }
++      /* Copy the result over now; may not be complete,
++       * but subsequent tests may as well be done on
++       * cached memory.
 +       */
-+      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
-+              if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
-+                      continue;
-+              lpfc_disc_state_machine(vport, ndlp, NULL,
-+                                      NLP_EVT_DEVICE_RECOVERY);
++      tmp->result = cmd->result;
++
++      if (((tmp->result & 0xff) == 0xff) ||
++                          ((tmp->result & 0xff00) == 0xff00))
++          continue;
++
++      search_found = 1;
++
++      if (cmd->bounce.len)
++          memcpy ((void *)cmd->bounce.addr,
++                              (void *)cmd->bounce.buf, cmd->bounce.len);
++
++      /* Important - remove from list _before_ done is called */
++      if (cmd_prev_ptr)
++          *cmd_prev_ptr = (struct NCR53c7x0_cmd *) cmd->next;
++
++      --hostdata->busy[tmp->device->id][tmp->device->lun];
++      cmd->next = hostdata->free;
++      hostdata->free = cmd;
++
++      tmp->host_scribble = NULL;
++
++      if (hostdata->options & OPTION_DEBUG_INTR) {
++          printk ("scsi%d : command complete : pid %lu, id %d,lun %d result 0x%x ", 
++                host->host_no, tmp->pid, tmp->device->id, tmp->device->lun, tmp->result);
++          __scsi_print_command (tmp->cmnd);
 +      }
-+      lpfc_cleanup_rpis(vport, 1);
 +
-+      lpfc_stop_vport_timers(vport);
-+      lpfc_unreg_all_rpis(vport);
-+      lpfc_unreg_default_rpis(vport);
-+      /*
-+       * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) does the
-+       * scsi_host_put() to release the vport.
-+       */
-+      lpfc_mbx_unreg_vpi(vport);
++      tmp->scsi_done(tmp);
++      goto restart;
++    }
++    local_irq_restore(flags);
 +
-+      lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
-+      return VPORT_OK;
++    if (!search_found)  {
++      printk ("scsi%d : WARNING : INTFLY with no completed commands.\n",
++                          host->host_no);
++    } else {
++      run_process_issue_queue();
++    }
++    return;
 +}
 +
-+int
-+enable_vport(struct fc_vport *fc_vport)
-+{
-+      struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
-+      struct lpfc_hba   *phba = vport->phba;
-+      struct lpfc_nodelist *ndlp = NULL;
++/*
++ * Function : static irqreturn_t NCR53c7x0_intr (int irq, void *dev_id)
++ *
++ * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing
++ *    the same IRQ line.  
++ * 
++ * Inputs : Since we're using the IRQF_DISABLED interrupt handler
++ *    semantics, irq indicates the interrupt which invoked 
++ *    this handler.  
++ *
++ * On the 710 we simualte an INTFLY with a script interrupt, and the
++ * script interrupt handler will call back to this function.
++ */
 +
-+      if ((phba->link_state < LPFC_LINK_UP) ||
-+          (phba->fc_topology == TOPOLOGY_LOOP)) {
-+              lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
-+              return VPORT_OK;
-+      }
++static irqreturn_t
++NCR53c7x0_intr (int irq, void *dev_id)
++{
++    NCR53c7x0_local_declare();
++    struct Scsi_Host *host;                   /* Host we are looking at */
++    unsigned char istat;                      /* Values of interrupt regs */
++    struct NCR53c7x0_hostdata *hostdata;      /* host->hostdata[0] */
++    struct NCR53c7x0_cmd *cmd;                        /* command which halted */
++    u32 *dsa;                                 /* DSA */
++    int handled = 0;
++
++#ifdef NCR_DEBUG
++    char buf[80];                             /* Debugging sprintf buffer */
++    size_t buflen;                            /* Length of same */
++#endif
 +
-+      vport->load_flag |= FC_LOADING;
-+      vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
++    host     = (struct Scsi_Host *)dev_id;
++    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
++    NCR53c7x0_local_setup(host);
 +
-+      /* Use the Physical nodes Fabric NDLP to determine if the link is
-+       * up and ready to FDISC.
++    /*
++     * Only read istat once per loop, since reading it again will unstack
++     * interrupts
++     */
++
++    while ((istat = NCR53c7x0_read8(hostdata->istat)) & (ISTAT_SIP|ISTAT_DIP)) {
++      handled = 1;
++      hostdata->dsp_changed = 0;
++      hostdata->dstat_valid = 0;
++      hostdata->state = STATE_HALTED;
++
++      if (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) 
++          printk ("scsi%d : SCSI FIFO not empty\n", host->host_no);
++
++      /*
++       * NCR53c700 and NCR53c700-66 change the current SCSI
++       * process, hostdata->ncrcurrent, in the Linux driver so
++       * cmd = hostdata->ncrcurrent.
++       *
++       * With other chips, we must look through the commands
++       * executing and find the command structure which 
++       * corresponds to the DSA register.
 +       */
-+      ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
-+      if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
-+              if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
-+                      lpfc_set_disctmo(vport);
-+                      lpfc_initial_fdisc(vport);
-+              } else {
-+                      lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                                      "%d (%d):0264 No NPIV Fabric "
-+                                      "support\n",
-+                                      phba->brd_no, vport->vpi);
-+              }
++
++      if (hostdata->options & OPTION_700) {
++          cmd = (struct NCR53c7x0_cmd *) hostdata->ncrcurrent;
 +      } else {
-+              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
++          dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
++          for (cmd = (struct NCR53c7x0_cmd *) hostdata->running_list;
++              cmd && (dsa + (hostdata->dsa_start / sizeof(u32))) != cmd->dsa;
++                  cmd = (struct NCR53c7x0_cmd *)(cmd->next))
++              ;
++      }
++      if (hostdata->options & OPTION_DEBUG_INTR) {
++          if (cmd) {
++              printk("scsi%d : interrupt for pid %lu, id %d, lun %d ", 
++                  host->host_no, cmd->cmd->pid, (int) cmd->cmd->device->id,
++                  (int) cmd->cmd->device->lun);
++              __scsi_print_command (cmd->cmd->cmnd);
++          } else {
++              printk("scsi%d : no active command\n", host->host_no);
++          }
++      }
++      
++      if (istat & ISTAT_SIP) {
++          if (hostdata->options & OPTION_DEBUG_INTR) 
++              printk ("scsi%d : ISTAT_SIP\n", host->host_no);
++          intr_scsi (host, cmd);
++      }
++      
++      if (istat & ISTAT_DIP) {
++          if (hostdata->options & OPTION_DEBUG_INTR) 
++              printk ("scsi%d : ISTAT_DIP\n", host->host_no);
++          intr_dma (host, cmd);
++      }
++      
++      if (!hostdata->dstat_valid) {
++          hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
++          hostdata->dstat_valid = 1;
++      }
++      
++      if (!(hostdata->dstat & DSTAT_DFE)) {
++          printk ("scsi%d : DMA FIFO not empty\n", host->host_no);
++          /* Really need to check this out for 710 RGH */
++          NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
++          while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF)
++              ;
++          hostdata->dstat |= DSTAT_DFE;
 +      }
 +
-+      return VPORT_OK;
++      if (!hostdata->idle && hostdata->state == STATE_HALTED) {
++          if (!hostdata->dsp_changed)
++              hostdata->dsp = (u32 *)bus_to_virt(NCR53c7x0_read32(DSP_REG));
++#if 0
++          printk("scsi%d : new dsp is 0x%lx (virt 0x%p)\n",
++              host->host_no,  virt_to_bus(hostdata->dsp), hostdata->dsp);
++#endif
++              
++          hostdata->state = STATE_RUNNING;
++          NCR53c7x0_write32 (DSP_REG, virt_to_bus(hostdata->dsp));
++          if (hostdata->options & OPTION_DEBUG_TRACE) {
++#ifdef CYCLIC_TRACE
++              log_insn (hostdata->dsp);
++#else
++              print_insn (host, hostdata->dsp, "t ", 1);
++#endif
++              NCR53c7x0_write8 (DCNTL_REG,
++                      hostdata->saved_dcntl | DCNTL_SSM | DCNTL_STD);
++          }
++      }
++    }
++    return IRQ_HANDLED;
 +}
 +
-+int
-+lpfc_vport_disable(struct fc_vport *fc_vport, bool disable)
-+{
-+      if (disable)
-+              return disable_vport(fc_vport);
-+      else
-+              return enable_vport(fc_vport);
++
++/* 
++ * Function : static int abort_connected (struct Scsi_Host *host)
++ *
++ * Purpose : Assuming that the NCR SCSI processor is currently 
++ *    halted, break the currently established nexus.  Clean
++ *    up of the NCR53c7x0_cmd and Scsi_Cmnd structures should
++ *    be done on receipt of the abort interrupt.
++ *
++ * Inputs : host - SCSI host
++ *
++ */
++
++static int 
++abort_connected (struct Scsi_Host *host) {
++#ifdef NEW_ABORT
++    NCR53c7x0_local_declare();
++#endif
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++/* FIXME : this probably should change for production kernels; at the 
++   least, counter should move to a per-host structure. */
++    static int counter = 5;
++#ifdef NEW_ABORT
++    int sstat, phase, offset;
++    u32 *script;
++    NCR53c7x0_local_setup(host);
++#endif
++
++    if (--counter <= 0) {
++      disable(host);
++      return 0;
++    }
++
++    printk ("scsi%d : DANGER : abort_connected() called \n",
++      host->host_no);
++
++#ifdef NEW_ABORT
++
++/*
++ * New strategy : Rather than using a generic abort routine,
++ * we'll specifically try to source or sink the appropriate
++ * amount of data for the phase we're currently in (taking into 
++ * account the current synchronous offset) 
++ */
++
++    sstat = NCR53c8x0_read8 (SSTAT2_REG);
++    offset = OFFSET (sstat & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
++    phase = sstat & SSTAT2_PHASE_MASK;
++
++/*
++ * SET ATN
++ * MOVE source_or_sink, WHEN CURRENT PHASE 
++ * < repeat for each outstanding byte >
++ * JUMP send_abort_message
++ */
++
++    script = hostdata->abort_script = kmalloc (
++      8  /* instruction size */ * (
++          1 /* set ATN */ +
++          (!offset ? 1 : offset) /* One transfer per outstanding byte */ +
++          1 /* send abort message */),
++      GFP_ATOMIC);
++
++
++#else /* def NEW_ABORT */
++    hostdata->dsp = hostdata->script + hostdata->E_initiator_abort /
++          sizeof(u32);
++#endif /* def NEW_ABORT */
++    hostdata->dsp_changed = 1;
++
++/* XXX - need to flag the command as aborted after the abort_connected
++       code runs 
++ */
++    return 0;
 +}
 +
++/*
++ * Function : static int datapath_residual (Scsi_Host *host)
++ *
++ * Purpose : return residual data count of what's in the chip.
++ *
++ * Inputs : host - SCSI host
++ */
 +
-+int
-+lpfc_vport_delete(struct fc_vport *fc_vport)
-+{
-+      struct lpfc_nodelist *ndlp = NULL;
-+      struct lpfc_nodelist *next_ndlp;
-+      struct Scsi_Host *shost = (struct Scsi_Host *) fc_vport->shost;
-+      struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
-+      struct lpfc_hba   *phba = vport->phba;
-+      long timeout;
-+      int rc = VPORT_ERROR;
++static int
++datapath_residual (struct Scsi_Host *host) {
++    NCR53c7x0_local_declare();
++    int count, synchronous, sstat;
++    unsigned int ddir;
++
++    NCR53c7x0_local_setup(host);
++    /* COMPAT : the 700 and 700-66 need to use DFIFO_00_BO_MASK */
++    count = ((NCR53c7x0_read8 (DFIFO_REG) & DFIFO_10_BO_MASK) -
++      (NCR53c7x0_read32 (DBC_REG) & DFIFO_10_BO_MASK)) & DFIFO_10_BO_MASK;
++    synchronous = NCR53c7x0_read8 (SXFER_REG) & SXFER_MO_MASK;
++    /* COMPAT : DDIR is elsewhere on non-'8xx chips. */
++    ddir = NCR53c7x0_read8 (CTEST0_REG_700) & CTEST0_700_DDIR;
++
++    if (ddir) {
++    /* Receive */
++      if (synchronous) 
++          count += (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
++      else
++          if (NCR53c7x0_read8 (SSTAT1_REG) & SSTAT1_ILF)
++              ++count;
++    } else {
++    /* Send */
++      sstat = NCR53c7x0_read8 (SSTAT1_REG);
++      if (sstat & SSTAT1_OLF)
++          ++count;
++      if (synchronous && (sstat & SSTAT1_ORF))
++          ++count;
++    }
++    return count;
++}
 +
-+      /*
-+       * This is a bit of a mess.  We want to ensure the shost doesn't get
-+       * torn down until we're done with the embedded lpfc_vport structure.
-+       *
-+       * Beyond holding a reference for this function, we also need a
-+       * reference for outstanding I/O requests we schedule during delete
-+       * processing.  But once we scsi_remove_host() we can no longer obtain
-+       * a reference through scsi_host_get().
-+       *
-+       * So we take two references here.  We release one reference at the
-+       * bottom of the function -- after delinking the vport.  And we
-+       * release the other at the completion of the unreg_vpi that get's
-+       * initiated after we've disposed of all other resources associated
-+       * with the port.
-+       */
-+      if (!scsi_host_get(shost) || !scsi_host_get(shost))
-+              return VPORT_INVAL;
++/* 
++ * Function : static const char * sbcl_to_phase (int sbcl)_
++ *
++ * Purpose : Convert SBCL register to user-parsable phase representation
++ *
++ * Inputs : sbcl - value of sbcl register
++ */
 +
-+      if (vport->port_type == LPFC_PHYSICAL_PORT) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
-+                              "%d:1812 vport_delete failed: Cannot delete "
-+                              "physical host\n", phba->brd_no);
-+              goto out;
-+      }
 +
-+      vport->load_flag |= FC_UNLOADING;
++static const char *
++sbcl_to_phase (int sbcl) {
++    switch (sbcl & SBCL_PHASE_MASK) {
++    case SBCL_PHASE_DATAIN:
++      return "DATAIN";
++    case SBCL_PHASE_DATAOUT:
++      return "DATAOUT";
++    case SBCL_PHASE_MSGIN:
++      return "MSGIN";
++    case SBCL_PHASE_MSGOUT:
++      return "MSGOUT";
++    case SBCL_PHASE_CMDOUT:
++      return "CMDOUT";
++    case SBCL_PHASE_STATIN:
++      return "STATUSIN";
++    default:
++      return "unknown";
++    }
++}
 +
-+      kfree(vport->vname);
-+      lpfc_debugfs_terminate(vport);
-+      fc_remove_host(lpfc_shost_from_vport(vport));
-+      scsi_remove_host(lpfc_shost_from_vport(vport));
++/* 
++ * Function : static const char * sstat2_to_phase (int sstat)_
++ *
++ * Purpose : Convert SSTAT2 register to user-parsable phase representation
++ *
++ * Inputs : sstat - value of sstat register
++ */
 +
-+      ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
-+      if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
-+              phba->link_state >= LPFC_LINK_UP) {
 +
-+              /* First look for the Fabric ndlp */
-+              ndlp = lpfc_findnode_did(vport, Fabric_DID);
-+              if (!ndlp) {
-+                      /* Cannot find existing Fabric ndlp, allocate one */
-+                      ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
-+                      if (!ndlp)
-+                              goto skip_logo;
-+                      lpfc_nlp_init(vport, ndlp, Fabric_DID);
-+              } else {
-+                      lpfc_dequeue_node(vport, ndlp);
-+              }
-+              vport->unreg_vpi_cmpl = VPORT_INVAL;
-+              timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
-+              if (!lpfc_issue_els_npiv_logo(vport, ndlp))
-+                      while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
-+                              timeout = schedule_timeout(timeout);
-+      }
++static const char *
++sstat2_to_phase (int sstat) {
++    switch (sstat & SSTAT2_PHASE_MASK) {
++    case SSTAT2_PHASE_DATAIN:
++      return "DATAIN";
++    case SSTAT2_PHASE_DATAOUT:
++      return "DATAOUT";
++    case SSTAT2_PHASE_MSGIN:
++      return "MSGIN";
++    case SSTAT2_PHASE_MSGOUT:
++      return "MSGOUT";
++    case SSTAT2_PHASE_CMDOUT:
++      return "CMDOUT";
++    case SSTAT2_PHASE_STATIN:
++      return "STATUSIN";
++    default:
++      return "unknown";
++    }
++}
 +
-+skip_logo:
-+      lpfc_sli_host_down(vport);
++/* 
++ * Function : static void intr_phase_mismatch (struct Scsi_Host *host, 
++ *    struct NCR53c7x0_cmd *cmd)
++ *
++ * Purpose : Handle phase mismatch interrupts
++ *
++ * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
++ *    may be NULL.
++ *
++ * Side effects : The abort_connected() routine is called or the NCR chip 
++ *    is restarted, jumping to the command_complete entry point, or 
++ *    patching the address and transfer count of the current instruction 
++ *    and calling the msg_in entry point as appropriate.
++ */
++
++static void 
++intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
++    NCR53c7x0_local_declare();
++    u32 dbc_dcmd, *dsp, *dsp_next;
++    unsigned char dcmd, sbcl;
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    int residual;
++    enum {ACTION_ABORT, ACTION_ABORT_PRINT, ACTION_CONTINUE} action = 
++      ACTION_ABORT_PRINT;
++    const char *where = NULL;
++
++    NCR53c7x0_local_setup(host);
++
++    /*
++     * Corrective action is based on where in the SCSI SCRIPT(tm) the error 
++     * occurred, as well as which SCSI phase we are currently in.
++     */
++    dsp_next = bus_to_virt(NCR53c7x0_read32(DSP_REG));
++
++    /* 
++     * Fetch the current instruction, and remove the operands for easier 
++     * interpretation.
++     */
++    dbc_dcmd = NCR53c7x0_read32(DBC_REG);
++    dcmd = (dbc_dcmd & 0xff000000) >> 24;
++    /*
++     * Like other processors, the NCR adjusts the instruction pointer before
++     * instruction decode.  Set the DSP address back to what it should
++     * be for this instruction based on its size (2 or 3 32 bit words).
++     */
++    dsp = dsp_next - NCR53c7x0_insn_size(dcmd);
++
++
++    /*
++     * Read new SCSI phase from the SBCL lines.  Since all of our code uses 
++     * a WHEN conditional instead of an IF conditional, we don't need to 
++     * wait for a new REQ.
++     */
++    sbcl = NCR53c7x0_read8(SBCL_REG) & SBCL_PHASE_MASK;
++
++    if (!cmd) {
++      action = ACTION_ABORT_PRINT;
++      where = "no current command";
++    /*
++     * The way my SCSI SCRIPTS(tm) are architected, recoverable phase
++     * mismatches should only occur where we're doing a multi-byte  
++     * BMI instruction.  Specifically, this means 
++     *
++     *  - select messages (a SCSI-I target may ignore additional messages
++     *                after the IDENTIFY; any target may reject a SDTR or WDTR)
++     *
++     *  - command out (targets may send a message to signal an error 
++     *                condition, or go into STATUSIN after they've decided 
++     *                they don't like the command.
++     *
++     *        - reply_message (targets may reject a multi-byte message in the 
++     *                middle)
++     *
++     *        - data transfer routines (command completion with buffer space
++     *                left, disconnect message, or error message)
++     */
++    } else if (((dsp >= cmd->data_transfer_start && 
++      dsp < cmd->data_transfer_end)) || dsp == (cmd->residual + 2)) {
++      if ((dcmd & (DCMD_TYPE_MASK|DCMD_BMI_OP_MASK|DCMD_BMI_INDIRECT|
++              DCMD_BMI_MSG|DCMD_BMI_CD)) == (DCMD_TYPE_BMI|
++              DCMD_BMI_OP_MOVE_I)) {
++          residual = datapath_residual (host);
++          if (hostdata->options & OPTION_DEBUG_DISCONNECT)
++              printk ("scsi%d : handling residual transfer (+ %d bytes from DMA FIFO)\n", 
++                  host->host_no, residual);
++
++          /*
++           * The first instruction is a CALL to the alternate handler for 
++           * this data transfer phase, so we can do calls to 
++           * munge_msg_restart as we would if control were passed 
++           * from normal dynamic code.
++           */
++          if (dsp != cmd->residual + 2) {
++              cmd->residual[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL |
++                      ((dcmd & DCMD_BMI_IO) ? DCMD_TCI_IO : 0)) << 24) | 
++                  DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
++              cmd->residual[1] = virt_to_bus(hostdata->script)
++                  + ((dcmd & DCMD_BMI_IO)
++                     ? hostdata->E_other_in : hostdata->E_other_out);
++          }
++
++          /*
++           * The second instruction is the a data transfer block
++           * move instruction, reflecting the pointer and count at the 
++           * time of the phase mismatch.
++           */
++          cmd->residual[2] = dbc_dcmd + residual;
++          cmd->residual[3] = NCR53c7x0_read32(DNAD_REG) - residual;
++
++          /*
++           * The third and final instruction is a jump to the instruction
++           * which follows the instruction which had to be 'split'
++           */
++          if (dsp != cmd->residual + 2) {
++              cmd->residual[4] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) 
++                  << 24) | DBC_TCI_TRUE;
++              cmd->residual[5] = virt_to_bus(dsp_next);
++          }
++
++          /*
++           * For the sake of simplicity, transfer control to the 
++           * conditional CALL at the start of the residual buffer.
++           */
++          hostdata->dsp = cmd->residual;
++          hostdata->dsp_changed = 1;
++          action = ACTION_CONTINUE;
++      } else {
++          where = "non-BMI dynamic DSA code";
++          action = ACTION_ABORT_PRINT;
++      }
++    } else if (dsp == (hostdata->script + hostdata->E_select_msgout / 4 + 2)) {
++      /* RGH 290697:  Added +2 above, to compensate for the script
++       * instruction which disables the selection timer. */
++      /* Release ATN */
++      NCR53c7x0_write8 (SOCL_REG, 0);
++      switch (sbcl) {
++    /* 
++     * Some devices (SQ555 come to mind) grab the IDENTIFY message
++     * sent on selection, and decide to go into COMMAND OUT phase
++     * rather than accepting the rest of the messages or rejecting
++     * them.  Handle these devices gracefully.
++     */
++      case SBCL_PHASE_CMDOUT:
++          hostdata->dsp = dsp + 2 /* two _words_ */;
++          hostdata->dsp_changed = 1;
++          printk ("scsi%d : target %d ignored SDTR and went into COMMAND OUT\n", 
++              host->host_no, cmd->cmd->device->id);
++          cmd->flags &= ~CMD_FLAG_SDTR;
++          action = ACTION_CONTINUE;
++          break;
++      case SBCL_PHASE_MSGIN:
++          hostdata->dsp = hostdata->script + hostdata->E_msg_in / 
++              sizeof(u32);
++          hostdata->dsp_changed = 1;
++          action = ACTION_CONTINUE;
++          break;
++      default:
++          where="select message out";
++          action = ACTION_ABORT_PRINT;
++      }
++    /*
++     * Some SCSI devices will interpret a command as they read the bytes
++     * off the SCSI bus, and may decide that the command is Bogus before 
++     * they've read the entire command off the bus.
++     */
++    } else if (dsp == hostdata->script + hostdata->E_cmdout_cmdout / sizeof 
++      (u32)) {
++      hostdata->dsp = hostdata->script + hostdata->E_data_transfer /
++          sizeof (u32);
++      hostdata->dsp_changed = 1;
++      action = ACTION_CONTINUE;
++    /* FIXME : we need to handle message reject, etc. within msg_respond. */
++#ifdef notyet
++    } else if (dsp == hostdata->script + hostdata->E_reply_message) {
++      switch (sbcl) {
++    /* Any other phase mismatches abort the currently executing command.  */
++#endif
++    } else {
++      where = "unknown location";
++      action = ACTION_ABORT_PRINT;
++    }
++
++    /* Flush DMA FIFO */
++    if (!hostdata->dstat_valid) {
++      hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
++      hostdata->dstat_valid = 1;
++    }
++    if (!(hostdata->dstat & DSTAT_DFE)) {
++      /* Really need to check this out for 710 RGH */
++      NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
++      while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF);
++      hostdata->dstat |= DSTAT_DFE;
++    }
++
++    switch (action) {
++    case ACTION_ABORT_PRINT:
++      printk("scsi%d : %s : unexpected phase %s.\n",
++           host->host_no, where ? where : "unknown location", 
++           sbcl_to_phase(sbcl));
++      print_lots (host);
++    /* Fall through to ACTION_ABORT */
++    case ACTION_ABORT:
++      abort_connected (host);
++      break;
++    case ACTION_CONTINUE:
++      break;
++    }
 +
-+      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
-+              lpfc_disc_state_machine(vport, ndlp, NULL,
-+                                           NLP_EVT_DEVICE_RECOVERY);
-+              lpfc_disc_state_machine(vport, ndlp, NULL,
-+                                           NLP_EVT_DEVICE_RM);
-+      }
++#if 0
++    if (hostdata->dsp_changed) {
++      printk("scsi%d: new dsp 0x%p\n", host->host_no, hostdata->dsp);
++      print_insn (host, hostdata->dsp, "", 1);
++    }
++#endif
++}
 +
-+      lpfc_stop_vport_timers(vport);
-+      lpfc_unreg_all_rpis(vport);
-+      lpfc_unreg_default_rpis(vport);
-+      /*
-+       * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) does the
-+       * scsi_host_put() to release the vport.
-+       */
-+      lpfc_mbx_unreg_vpi(vport);
++/*
++ * Function : static void intr_bf (struct Scsi_Host *host, 
++ *    struct NCR53c7x0_cmd *cmd)
++ *
++ * Purpose : handle BUS FAULT interrupts 
++ *
++ * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
++ *    may be NULL.
++ */
++
++static void
++intr_bf (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
++    NCR53c7x0_local_declare();
++    u32 *dsp,
++      *next_dsp,              /* Current dsp */
++      *dsa,
++      dbc_dcmd;               /* DCMD (high eight bits) + DBC */
++    char *reason = NULL;
++    /* Default behavior is for a silent error, with a retry until we've
++       exhausted retries. */
++    enum {MAYBE, ALWAYS, NEVER} retry = MAYBE;
++    int report = 0;
++    NCR53c7x0_local_setup(host);
++
++    dbc_dcmd = NCR53c7x0_read32 (DBC_REG);
++    next_dsp = bus_to_virt (NCR53c7x0_read32(DSP_REG));
++    dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff);
++/* FIXME - check chip type  */
++    dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG));
++
++    /*
++     * Bus faults can be caused by either a Bad Address or 
++     * Target Abort. We should check the Received Target Abort
++     * bit of the PCI status register and Master Abort Bit.
++     *
++     *        - Master Abort bit indicates that no device claimed
++     *                the address with DEVSEL within five clocks
++     *
++     *        - Target Abort bit indicates that a target claimed it,
++     *                but changed its mind once it saw the byte enables.
++     *
++     */
++
++    /* 53c710, not PCI system */
++    report = 1;
++    reason = "Unknown";
++
++#ifndef notyet
++    report = 1;
++#endif
++    if (report && reason)
++    {
++      printk(KERN_ALERT "scsi%d : BUS FAULT reason = %s\n",
++           host->host_no, reason ? reason : "unknown");
++      print_lots (host);
++    }
++
++#ifndef notyet
++    retry = NEVER;
++#endif
 +
-+      lpfc_free_vpi(phba, vport->vpi);
-+      vport->work_port_events = 0;
-+      spin_lock_irq(&phba->hbalock);
-+      list_del_init(&vport->listentry);
-+      spin_unlock_irq(&phba->hbalock);
++    /* 
++     * TODO : we should attempt to recover from any spurious bus 
++     * faults.  After X retries, we should figure that things are 
++     * sufficiently wedged, and call NCR53c7xx_reset.
++     *
++     * This code should only get executed once we've decided that we 
++     * cannot retry.
++     */
 +
-+      rc = VPORT_OK;
-+out:
-+      scsi_host_put(shost);
-+      return rc;
++    if (retry == NEVER) {
++      printk(KERN_ALERT "          mail richard@sleepie.demon.co.uk\n");
++      FATAL (host);
++    }
 +}
 +
++/*
++ * Function : static void intr_dma (struct Scsi_Host *host, 
++ *    struct NCR53c7x0_cmd *cmd)
++ *
++ * Purpose : handle all DMA interrupts, indicated by the setting 
++ *    of the DIP bit in the ISTAT register.
++ *
++ * Inputs : host, cmd - host and NCR command causing the interrupt, cmd
++ *    may be NULL.
++ */
++
++static void 
++intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
++    NCR53c7x0_local_declare();
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    unsigned char dstat;      /* DSTAT */     
++    u32 *dsp,
++      *next_dsp,              /* Current dsp */
++      *dsa,
++      dbc_dcmd;               /* DCMD (high eight bits) + DBC */
++    int tmp;
++    unsigned long flags;
++    NCR53c7x0_local_setup(host);
++
++    if (!hostdata->dstat_valid) {
++      hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
++      hostdata->dstat_valid = 1;
++    }
++    
++    dstat = hostdata->dstat;
++    
++    if (hostdata->options & OPTION_DEBUG_INTR)
++      printk("scsi%d : DSTAT=0x%x\n", host->host_no, (int) dstat);
++
++    dbc_dcmd = NCR53c7x0_read32 (DBC_REG);
++    next_dsp = bus_to_virt(NCR53c7x0_read32(DSP_REG));
++    dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff);
++/* XXX - check chip type */
++    dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
++
++    /*
++     * DSTAT_ABRT is the aborted interrupt.  This is set whenever the 
++     * SCSI chip is aborted.  
++     * 
++     * With NCR53c700 and NCR53c700-66 style chips, we should only 
++     * get this when the chip is currently running the accept 
++     * reselect/select code and we have set the abort bit in the 
++     * ISTAT register.
++     *
++     */
++    
++    if (dstat & DSTAT_ABRT) {
++#if 0
++      /* XXX - add code here to deal with normal abort */
++      if ((hostdata->options & OPTION_700) && (hostdata->state ==
++          STATE_ABORTING)) {
++      } else 
++#endif
++      {
++          printk(KERN_ALERT "scsi%d : unexpected abort interrupt at\n" 
++                 "         ", host->host_no);
++          print_insn (host, dsp, KERN_ALERT "s ", 1);
++          FATAL (host);
++      }
++    }
++
++    /*
++     * DSTAT_SSI is the single step interrupt.  Should be generated 
++     * whenever we have single stepped or are tracing.
++     */
++
++    if (dstat & DSTAT_SSI) {
++      if (hostdata->options & OPTION_DEBUG_TRACE) {
++          /* Don't print instr. until we write DSP at end of intr function */
++      } else if (hostdata->options & OPTION_DEBUG_SINGLE) {
++          print_insn (host, dsp, "s ", 0);
++          local_irq_save(flags);
++/* XXX - should we do this, or can we get away with writing dsp? */
++
++          NCR53c7x0_write8 (DCNTL_REG, (NCR53c7x0_read8(DCNTL_REG) & 
++              ~DCNTL_SSM) | DCNTL_STD);
++          local_irq_restore(flags);
++      } else {
++          printk(KERN_ALERT "scsi%d : unexpected single step interrupt at\n"
++                 "         ", host->host_no);
++          print_insn (host, dsp, KERN_ALERT "", 1);
++          printk(KERN_ALERT "         mail drew@PoohSticks.ORG\n");
++          FATAL (host);
++      }
++    }
++
++    /*
++     * DSTAT_IID / DSTAT_OPC (same bit, same meaning, only the name 
++     * is different) is generated whenever an illegal instruction is 
++     * encountered.  
++     * 
++     * XXX - we may want to emulate INTFLY here, so we can use 
++     *    the same SCSI SCRIPT (tm) for NCR53c710 through NCR53c810  
++     *          chips.
++     */
++
++    if (dstat & DSTAT_OPC) {
++    /* 
++     * Ascertain if this IID interrupts occurred before or after a STO 
++     * interrupt.  Since the interrupt handling code now leaves 
++     * DSP unmodified until _after_ all stacked interrupts have been
++     * processed, reading the DSP returns the original DSP register.
++     * This means that if dsp lies between the select code, and 
++     * message out following the selection code (where the IID interrupt
++     * would have to have occurred by due to the implicit wait for REQ),
++     * we have an IID interrupt resulting from a STO condition and 
++     * can ignore it.
++     */
++
++      if (((dsp >= (hostdata->script + hostdata->E_select / sizeof(u32))) &&
++          (dsp <= (hostdata->script + hostdata->E_select_msgout / 
++          sizeof(u32) + 8))) || (hostdata->test_running == 2)) {
++          if (hostdata->options & OPTION_DEBUG_INTR) 
++              printk ("scsi%d : ignoring DSTAT_IID for SSTAT_STO\n",
++                  host->host_no);
++          if (hostdata->expecting_iid) {
++              hostdata->expecting_iid = 0;
++              hostdata->idle = 1;
++              if (hostdata->test_running == 2) {
++                  hostdata->test_running = 0;
++                  hostdata->test_completed = 3;
++              } else if (cmd) 
++                      abnormal_finished (cmd, DID_BAD_TARGET << 16);
++          } else {
++              hostdata->expecting_sto = 1;
++          }
++    /*
++     * We can't guarantee we'll be able to execute the WAIT DISCONNECT
++     * instruction within the 3.4us of bus free and arbitration delay
++     * that a target can RESELECT in and assert REQ after we've dropped
++     * ACK.  If this happens, we'll get an illegal instruction interrupt.
++     * Doing away with the WAIT DISCONNECT instructions broke everything,
++     * so instead I'll settle for moving one WAIT DISCONNECT a few 
++     * instructions closer to the CLEAR ACK before it to minimize the
++     * chances of this happening, and handle it if it occurs anyway.
++     *
++     * Simply continue with what we were doing, and control should
++     * be transferred to the schedule routine which will ultimately
++     * pass control onto the reselection or selection (not yet)
++     * code.
++     */
++      } else if (dbc_dcmd == 0x48000000 && (NCR53c7x0_read8 (SBCL_REG) &
++          SBCL_REQ)) {
++          if (!(hostdata->options & OPTION_NO_PRINT_RACE))
++          {
++              printk("scsi%d: REQ before WAIT DISCONNECT IID\n", 
++                  host->host_no);
++              hostdata->options |= OPTION_NO_PRINT_RACE;
++          }
++      } else {
++          printk(KERN_ALERT "scsi%d : invalid instruction\n", host->host_no);
++          print_lots (host);
++          printk(KERN_ALERT "         mail Richard@sleepie.demon.co.uk with ALL\n"
++                            "         boot messages and diagnostic output\n");
++          FATAL (host);
++      }
++    }
++
++    /* 
++     * DSTAT_BF are bus fault errors.  DSTAT_800_BF is valid for 710 also.
++     */
++    
++    if (dstat & DSTAT_800_BF) {
++      intr_bf (host, cmd);
++    }
++      
 +
-+EXPORT_SYMBOL(lpfc_vport_create);
-+EXPORT_SYMBOL(lpfc_vport_delete);
-diff -Nurb linux-2.6.22-570/drivers/scsi/lpfc/lpfc_vport.h linux-2.6.22-590/drivers/scsi/lpfc/lpfc_vport.h
---- linux-2.6.22-570/drivers/scsi/lpfc/lpfc_vport.h    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/scsi/lpfc/lpfc_vport.h    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,113 @@
-+/*******************************************************************
-+ * This file is part of the Emulex Linux Device Driver for         *
-+ * Fibre Channel Host Bus Adapters.                                *
-+ * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
-+ * EMULEX and SLI are trademarks of Emulex.                        *
-+ * www.emulex.com                                                  *
-+ * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
-+ *                                                                 *
-+ * This program is free software; you can redistribute it and/or   *
-+ * modify it under the terms of version 2 of the GNU General       *
-+ * Public License as published by the Free Software Foundation.    *
-+ * This program is distributed in the hope that it will be useful. *
-+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
-+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
-+ * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
-+ * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
-+ * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
-+ * more details, a copy of which can be found in the file COPYING  *
-+ * included with this package.                                     *
-+ *******************************************************************/
++    /* 
++     * DSTAT_SIR interrupts are generated by the execution of 
++     * the INT instruction.  Since the exact values available 
++     * are determined entirely by the SCSI script running, 
++     * and are local to a particular script, a unique handler
++     * is called for each script.
++     */
++
++    if (dstat & DSTAT_SIR) {
++      if (hostdata->options & OPTION_DEBUG_INTR)
++          printk ("scsi%d : DSTAT_SIR\n", host->host_no);
++      switch ((tmp = hostdata->dstat_sir_intr (host, cmd))) {
++      case SPECIFIC_INT_NOTHING:
++      case SPECIFIC_INT_RESTART:
++          break;
++      case SPECIFIC_INT_ABORT:
++          abort_connected(host);
++          break;
++      case SPECIFIC_INT_PANIC:
++          printk(KERN_ALERT "scsi%d : failure at ", host->host_no);
++          print_insn (host, dsp, KERN_ALERT "", 1);
++          printk(KERN_ALERT "          dstat_sir_intr() returned SPECIFIC_INT_PANIC\n");
++          FATAL (host);
++          break;
++      case SPECIFIC_INT_BREAK:
++          intr_break (host, cmd);
++          break;
++      default:
++          printk(KERN_ALERT "scsi%d : failure at ", host->host_no);
++          print_insn (host, dsp, KERN_ALERT "", 1);
++          printk(KERN_ALERT"          dstat_sir_intr() returned unknown value %d\n", 
++              tmp);
++          FATAL (host);
++      }
++    } 
++}
 +
-+#ifndef _H_LPFC_VPORT
-+#define _H_LPFC_VPORT
++/*
++ * Function : static int print_insn (struct Scsi_Host *host, 
++ *    u32 *insn, int kernel)
++ *
++ * Purpose : print numeric representation of the instruction pointed
++ *    to by insn to the debugging or kernel message buffer
++ *    as appropriate.  
++ *
++ *    If desired, a user level program can interpret this 
++ *    information.
++ *
++ * Inputs : host, insn - host, pointer to instruction, prefix - 
++ *    string to prepend, kernel - use printk instead of debugging buffer.
++ *
++ * Returns : size, in u32s, of instruction printed.
++ */
 +
-+/* API version values (each will be an individual bit) */
-+#define VPORT_API_VERSION_1   0x01
++/*
++ * FIXME: should change kernel parameter so that it takes an ENUM
++ *    specifying severity - either KERN_ALERT or KERN_PANIC so
++ *    all panic messages are output with the same severity.
++ */
++
++static int 
++print_insn (struct Scsi_Host *host, const u32 *insn, 
++    const char *prefix, int kernel) {
++    char buf[160],            /* Temporary buffer and pointer.  ICKY 
++                                 arbitrary length.  */
++
++              
++      *tmp;                   
++    unsigned char dcmd;               /* dcmd register for *insn */
++    int size;
++
++    /* 
++     * Check to see if the instruction pointer is not bogus before 
++     * indirecting through it; avoiding red-zone at start of 
++     * memory.
++     *
++     * FIXME: icky magic needs to happen here on non-intel boxes which
++     * don't have kernel memory mapped in like this.  Might be reasonable
++     * to use vverify()?
++     */
++
++    if (virt_to_phys((void *)insn) < PAGE_SIZE || 
++      virt_to_phys((void *)(insn + 8)) > virt_to_phys(high_memory) ||
++      ((((dcmd = (insn[0] >> 24) & 0xff) & DCMD_TYPE_MMI) == DCMD_TYPE_MMI) &&
++      virt_to_phys((void *)(insn + 12)) > virt_to_phys(high_memory))) {
++      size = 0;
++      sprintf (buf, "%s%p: address out of range\n",
++          prefix, insn);
++    } else {
++/* 
++ * FIXME : (void *) cast in virt_to_bus should be unnecessary, because
++ *    it should take const void * as argument.
++ */
++#if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000)
++      sprintf(buf, "%s0x%lx (virt 0x%p) : 0x%08x 0x%08x (virt 0x%p)", 
++          (prefix ? prefix : ""), virt_to_bus((void *) insn), insn,  
++          insn[0], insn[1], bus_to_virt (insn[1]));
++#else
++      /* Remove virtual addresses to reduce output, as they are the same */
++      sprintf(buf, "%s0x%x (+%x) : 0x%08x 0x%08x", 
++          (prefix ? prefix : ""), (u32)insn, ((u32)insn -
++              (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4, 
++          insn[0], insn[1]);
++#endif
++      tmp = buf + strlen(buf);
++      if ((dcmd & DCMD_TYPE_MASK) == DCMD_TYPE_MMI)  {
++#if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000)
++          sprintf (tmp, " 0x%08x (virt 0x%p)\n", insn[2], 
++              bus_to_virt(insn[2]));
++#else
++          /* Remove virtual addr to reduce output, as it is the same */
++          sprintf (tmp, " 0x%08x\n", insn[2]);
++#endif
++          size = 3;
++      } else {
++          sprintf (tmp, "\n");
++          size = 2;
++      }
++    }
++
++    if (kernel) 
++      printk ("%s", buf);
++#ifdef NCR_DEBUG
++    else {
++      size_t len = strlen(buf);
++      debugger_kernel_write(host, buf, len);
++    }
++#endif
++    return size;
++}
 +
-+/* Values returned via lpfc_vport_getinfo() */
-+struct vport_info {
++/*
++ * Function : int NCR53c7xx_abort (Scsi_Cmnd *cmd)
++ * 
++ * Purpose : Abort an errant SCSI command, doing all necessary
++ *    cleanup of the issue_queue, running_list, shared Linux/NCR
++ *    dsa issue and reconnect queues.
++ *
++ * Inputs : cmd - command to abort, code - entire result field
++ *
++ * Returns : 0 on success, -1 on failure.
++ */
++
++int 
++NCR53c7xx_abort (Scsi_Cmnd *cmd) {
++    NCR53c7x0_local_declare();
++    struct Scsi_Host *host = cmd->device->host;
++    struct NCR53c7x0_hostdata *hostdata = host ? (struct NCR53c7x0_hostdata *) 
++      host->hostdata[0] : NULL;
++    unsigned long flags;
++    struct NCR53c7x0_cmd *curr, **prev;
++    Scsi_Cmnd *me, **last;
++#if 0
++    static long cache_pid = -1;
++#endif
 +
-+      uint32_t api_versions;
-+      uint8_t linktype;
-+#define  VPORT_TYPE_PHYSICAL  0
-+#define  VPORT_TYPE_VIRTUAL   1
 +
-+      uint8_t state;
-+#define  VPORT_STATE_OFFLINE  0
-+#define  VPORT_STATE_ACTIVE   1
-+#define  VPORT_STATE_FAILED   2
++    if (!host) {
++      printk ("Bogus SCSI command pid %ld; no host structure\n",
++          cmd->pid);
++      return SCSI_ABORT_ERROR;
++    } else if (!hostdata) {
++      printk ("Bogus SCSI host %d; no hostdata\n", host->host_no);
++      return SCSI_ABORT_ERROR;
++    }
++    NCR53c7x0_local_setup(host);
 +
-+      uint8_t fail_reason;
-+      uint8_t prev_fail_reason;
-+#define  VPORT_FAIL_UNKNOWN   0
-+#define  VPORT_FAIL_LINKDOWN  1
-+#define  VPORT_FAIL_FAB_UNSUPPORTED   2
-+#define  VPORT_FAIL_FAB_NORESOURCES   3
-+#define  VPORT_FAIL_FAB_LOGOUT        4
-+#define  VPORT_FAIL_ADAP_NORESOURCES  5
++/*
++ * CHECK : I don't think that reading ISTAT will unstack any interrupts,
++ *    since we need to write the INTF bit to clear it, and SCSI/DMA
++ *    interrupts don't clear until we read SSTAT/SIST and DSTAT registers.
++ *    
++ *    See that this is the case.  Appears to be correct on the 710, at least.
++ *
++ * I suspect that several of our failures may be coming from a new fatal
++ * interrupt (possibly due to a phase mismatch) happening after we've left
++ * the interrupt handler, but before the PIC has had the interrupt condition
++ * cleared.
++ */
++
++    if (NCR53c7x0_read8(hostdata->istat) & (ISTAT_DIP|ISTAT_SIP)) {
++      printk ("scsi%d : dropped interrupt for command %ld\n", host->host_no,
++          cmd->pid);
++      NCR53c7x0_intr (host->irq, NULL, NULL);
++      return SCSI_ABORT_BUSY;
++    }
++      
++    local_irq_save(flags);
++#if 0
++    if (cache_pid == cmd->pid) 
++      panic ("scsi%d : bloody fetus %d\n", host->host_no, cmd->pid);
++    else
++      cache_pid = cmd->pid;
++#endif
++      
 +
-+      uint8_t node_name[8];   /* WWNN */
-+      uint8_t port_name[8];   /* WWPN */
++/*
++ * The command could be hiding in the issue_queue.  This would be very
++ * nice, as commands can't be moved from the high level driver's issue queue 
++ * into the shared queue until an interrupt routine is serviced, and this
++ * moving is atomic.  
++ *
++ * If this is the case, we don't have to worry about anything - we simply
++ * pull the command out of the old queue, and call it aborted.
++ */
++
++    for (me = (Scsi_Cmnd *) hostdata->issue_queue, 
++         last = (Scsi_Cmnd **) &(hostdata->issue_queue);
++       me && me != cmd;  last = (Scsi_Cmnd **)&(me->SCp.ptr), 
++       me = (Scsi_Cmnd *)me->SCp.ptr);
++
++    if (me) {
++      *last = (Scsi_Cmnd *) me->SCp.ptr;
++      if (me->host_scribble) {
++          ((struct NCR53c7x0_cmd *)me->host_scribble)->next = hostdata->free;
++          hostdata->free = (struct NCR53c7x0_cmd *) me->host_scribble;
++          me->host_scribble = NULL;
++      }
++      cmd->result = DID_ABORT << 16;
++      cmd->scsi_done(cmd);
++      printk ("scsi%d : found command %ld in Linux issue queue\n", 
++          host->host_no, me->pid);
++      local_irq_restore(flags);
++      run_process_issue_queue();
++      return SCSI_ABORT_SUCCESS;
++    }
 +
-+      struct Scsi_Host *shost;
++/* 
++ * That failing, the command could be in our list of already executing 
++ * commands.  If this is the case, drastic measures are called for.  
++ */ 
++
++    for (curr = (struct NCR53c7x0_cmd *) hostdata->running_list, 
++       prev = (struct NCR53c7x0_cmd **) &(hostdata->running_list);
++       curr && curr->cmd != cmd; prev = (struct NCR53c7x0_cmd **) 
++         &(curr->next), curr = (struct NCR53c7x0_cmd *) curr->next);
++
++    if (curr) {
++      if ((curr->result & 0xff) != 0xff && (curr->result & 0xff00) != 0xff00) {
++            cmd->result = curr->result;
++          if (prev)
++              *prev = (struct NCR53c7x0_cmd *) curr->next;
++          curr->next = (struct NCR53c7x0_cmd *) hostdata->free;
++          cmd->host_scribble = NULL;
++          hostdata->free = curr;
++          cmd->scsi_done(cmd);
++      printk ("scsi%d : found finished command %ld in running list\n", 
++          host->host_no, cmd->pid);
++          local_irq_restore(flags);
++          return SCSI_ABORT_NOT_RUNNING;
++      } else {
++          printk ("scsi%d : DANGER : command running, can not abort.\n",
++              cmd->device->host->host_no);
++          local_irq_restore(flags);
++          return SCSI_ABORT_BUSY;
++      }
++    }
 +
-+/* Following values are valid only on physical links */
-+      uint32_t vports_max;
-+      uint32_t vports_inuse;
-+      uint32_t rpi_max;
-+      uint32_t rpi_inuse;
-+#define  VPORT_CNT_INVALID    0xFFFFFFFF
-+};
++/* 
++ * And if we couldn't find it in any of our queues, it must have been 
++ * a dropped interrupt.
++ */
++
++    curr = (struct NCR53c7x0_cmd *) cmd->host_scribble;
++    if (curr) {
++      curr->next = hostdata->free;
++      hostdata->free = curr;
++      cmd->host_scribble = NULL;
++    }
++
++    if (curr == NULL || ((curr->result & 0xff00) == 0xff00) ||
++              ((curr->result & 0xff) == 0xff)) {
++      printk ("scsi%d : did this command ever run?\n", host->host_no);
++          cmd->result = DID_ABORT << 16;
++    } else {
++      printk ("scsi%d : probably lost INTFLY, normal completion\n", 
++          host->host_no);
++        cmd->result = curr->result;
++/* 
++ * FIXME : We need to add an additional flag which indicates if a 
++ * command was ever counted as BUSY, so if we end up here we can
++ * decrement the busy count if and only if it is necessary.
++ */
++        --hostdata->busy[cmd->device->id][cmd->device->lun];
++    }
++    local_irq_restore(flags);
++    cmd->scsi_done(cmd);
 +
-+/* data used  in link creation */
-+struct vport_data {
-+      uint32_t api_version;
++/* 
++ * We need to run process_issue_queue since termination of this command 
++ * may allow another queued command to execute first? 
++ */
++    return SCSI_ABORT_NOT_RUNNING;
++}
 +
-+      uint32_t options;
-+#define  VPORT_OPT_AUTORETRY  0x01
++/*
++ * Function : int NCR53c7xx_reset (Scsi_Cmnd *cmd) 
++ * 
++ * Purpose : perform a hard reset of the SCSI bus and NCR
++ *    chip.
++ *
++ * Inputs : cmd - command which caused the SCSI RESET
++ *
++ * Returns : 0 on success.
++ */
++ 
++int 
++NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) {
++    NCR53c7x0_local_declare();
++    unsigned long flags;
++    int found = 0;
++    struct NCR53c7x0_cmd * c;
++    Scsi_Cmnd *tmp;
++    /*
++     * When we call scsi_done(), it's going to wake up anything sleeping on the
++     * resources which were in use by the aborted commands, and we'll start to 
++     * get new commands.
++     *
++     * We can't let this happen until after we've re-initialized the driver
++     * structures, and can't reinitialize those structures until after we've 
++     * dealt with their contents.
++     *
++     * So, we need to find all of the commands which were running, stick
++     * them on a linked list of completed commands (we'll use the host_scribble
++     * pointer), do our reinitialization, and then call the done function for
++     * each command.  
++     */
++    Scsi_Cmnd *nuke_list = NULL;
++    struct Scsi_Host *host = cmd->device->host;
++    struct NCR53c7x0_hostdata *hostdata = 
++      (struct NCR53c7x0_hostdata *) host->hostdata[0];
++
++    NCR53c7x0_local_setup(host);
++    local_irq_save(flags);
++    ncr_halt (host);
++    print_lots (host);
++    dump_events (host, 30);
++    ncr_scsi_reset (host);
++    for (tmp = nuke_list = return_outstanding_commands (host, 1 /* free */,
++      0 /* issue */ ); tmp; tmp = (Scsi_Cmnd *) tmp->SCp.buffer)
++      if (tmp == cmd) {
++          found = 1;
++          break;
++      }
++          
++    /* 
++     * If we didn't find the command which caused this reset in our running
++     * list, then we've lost it.  See that it terminates normally anyway.
++     */
++    if (!found) {
++      c = (struct NCR53c7x0_cmd *) cmd->host_scribble;
++      if (c) {
++          cmd->host_scribble = NULL;
++          c->next = hostdata->free;
++          hostdata->free = c;
++      } else
++          printk ("scsi%d: lost command %ld\n", host->host_no, cmd->pid);
++      cmd->SCp.buffer = (struct scatterlist *) nuke_list;
++      nuke_list = cmd;
++    }
++
++    NCR53c7x0_driver_init (host);
++    hostdata->soft_reset (host);
++    if (hostdata->resets == 0) 
++      disable(host);
++    else if (hostdata->resets != -1)
++      --hostdata->resets;
++    local_irq_restore(flags);
++    for (; nuke_list; nuke_list = tmp) {
++      tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
++      nuke_list->result = DID_RESET << 16;
++      nuke_list->scsi_done (nuke_list);
++    }
++    local_irq_restore(flags);
++    return SCSI_RESET_SUCCESS;
++}
 +
-+      uint8_t node_name[8];   /* WWNN */
-+      uint8_t port_name[8];   /* WWPN */
++/*
++ * The NCR SDMS bios follows Annex A of the SCSI-CAM draft, and 
++ * therefore shares the scsicam_bios_param function.
++ */
 +
 +/*
-+ *  Upon successful creation, vport_shost will point to the new Scsi_Host
-+ *  structure for the new virtual link.
++ * Function : int insn_to_offset (Scsi_Cmnd *cmd, u32 *insn)
++ *
++ * Purpose : convert instructions stored at NCR pointer into data 
++ *    pointer offset.
++ * 
++ * Inputs : cmd - SCSI command; insn - pointer to instruction.  Either current
++ *    DSP, or saved data pointer.
++ *
++ * Returns : offset on success, -1 on failure.
 + */
-+      struct Scsi_Host *vport_shost;
-+};
 +
-+/* API function return codes */
-+#define VPORT_OK      0
-+#define VPORT_ERROR   -1
-+#define VPORT_INVAL   -2
-+#define VPORT_NOMEM   -3
-+#define VPORT_NORESOURCES     -4
 +
-+int lpfc_vport_create(struct fc_vport *, bool);
-+int lpfc_vport_delete(struct fc_vport *);
-+int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *);
-+int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint);
++static int 
++insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) {
++    struct NCR53c7x0_hostdata *hostdata = 
++      (struct NCR53c7x0_hostdata *) cmd->device->host->hostdata[0];
++    struct NCR53c7x0_cmd *ncmd = 
++      (struct NCR53c7x0_cmd *) cmd->host_scribble;
++    int offset = 0, buffers;
++    struct scatterlist *segment;
++    char *ptr;
++    int found = 0;
++
++/*
++ * With the current code implementation, if the insn is inside dynamically 
++ * generated code, the data pointer will be the instruction preceding 
++ * the next transfer segment.
++ */
++
++    if (!check_address ((unsigned long) ncmd, sizeof (struct NCR53c7x0_cmd)) &&
++      ((insn >= ncmd->data_transfer_start &&  
++          insn < ncmd->data_transfer_end) ||
++      (insn >= ncmd->residual &&
++          insn < (ncmd->residual + 
++              sizeof(ncmd->residual))))) {
++          ptr = bus_to_virt(insn[3]);
++
++          if ((buffers = cmd->use_sg)) {
++              for (offset = 0, 
++                      segment = (struct scatterlist *) cmd->request_buffer;
++                   buffers && !((found = ((ptr >= (char *)page_address(segment->page)+segment->offset) && 
++                          (ptr < ((char *)page_address(segment->page)+segment->offset+segment->length)))));
++                   --buffers, offset += segment->length, ++segment)
++#if 0
++                  printk("scsi%d: comparing 0x%p to 0x%p\n", 
++                      cmd->device->host->host_no, saved, page_address(segment->page+segment->offset));
++#else
++                  ;
++#endif
++                  offset += ptr - ((char *)page_address(segment->page)+segment->offset);
++          } else {
++              found = 1;
++              offset = ptr - (char *) (cmd->request_buffer);
++          }
++    } else if ((insn >= hostdata->script + 
++              hostdata->E_data_transfer / sizeof(u32)) &&
++             (insn <= hostdata->script +
++              hostdata->E_end_data_transfer / sizeof(u32))) {
++      found = 1;
++      offset = 0;
++    }
++    return found ? offset : -1;
++}
++
++
++
++/*
++ * Function : void print_progress (Scsi_Cmnd *cmd) 
++ * 
++ * Purpose : print the current location of the saved data pointer
++ *
++ * Inputs : cmd - command we are interested in
++ *
++ */
++
++static void 
++print_progress (Scsi_Cmnd *cmd) {
++    NCR53c7x0_local_declare();
++    struct NCR53c7x0_cmd *ncmd = 
++      (struct NCR53c7x0_cmd *) cmd->host_scribble;
++    int offset, i;
++    char *where;
++    u32 *ptr;
++    NCR53c7x0_local_setup (cmd->device->host);
++
++    if (check_address ((unsigned long) ncmd,sizeof (struct NCR53c7x0_cmd)) == 0)
++    {
++      printk("\nNCR53c7x0_cmd fields:\n");
++      printk("  bounce.len=0x%x, addr=0x%0x, buf[]=0x%02x %02x %02x %02x\n",
++          ncmd->bounce.len, ncmd->bounce.addr, ncmd->bounce.buf[0],
++          ncmd->bounce.buf[1], ncmd->bounce.buf[2], ncmd->bounce.buf[3]);
++      printk("  result=%04x, cdb[0]=0x%02x\n", ncmd->result, ncmd->cmnd[0]);
++    }
++
++    for (i = 0; i < 2; ++i) {
++      if (check_address ((unsigned long) ncmd, 
++          sizeof (struct NCR53c7x0_cmd)) == -1) 
++          continue;
++      if (!i) {
++          where = "saved";
++          ptr = bus_to_virt(ncmd->saved_data_pointer);
++      } else {
++          where = "active";
++          ptr = bus_to_virt (NCR53c7x0_read32 (DSP_REG) -
++              NCR53c7x0_insn_size (NCR53c7x0_read8 (DCMD_REG)) *
++              sizeof(u32));
++      } 
++      offset = insn_to_offset (cmd, ptr);
++
++      if (offset != -1) 
++          printk ("scsi%d : %s data pointer at offset %d\n",
++              cmd->device->host->host_no, where, offset);
++      else {
++          int size;
++          printk ("scsi%d : can't determine %s data pointer offset\n",
++              cmd->device->host->host_no, where);
++          if (ncmd) {
++              size = print_insn (cmd->device->host,
++                  bus_to_virt(ncmd->saved_data_pointer), "", 1);
++              print_insn (cmd->device->host,
++                  bus_to_virt(ncmd->saved_data_pointer) + size * sizeof(u32),
++                  "", 1);
++          }
++      }
++    }
++}
++
++
++static void 
++print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) {
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    int i, len;
++    char *ptr;
++    Scsi_Cmnd *cmd;
++
++    if (check_address ((unsigned long) dsa, hostdata->dsa_end - 
++      hostdata->dsa_start) == -1) {
++      printk("scsi%d : bad dsa virt 0x%p\n", host->host_no, dsa);
++      return;
++    }
++    printk("%sscsi%d : dsa at phys 0x%lx (virt 0x%p)\n"
++          "        + %d : dsa_msgout length = %u, data = 0x%x (virt 0x%p)\n" ,
++          prefix ? prefix : "",
++          host->host_no,  virt_to_bus (dsa), dsa, hostdata->dsa_msgout,
++          dsa[hostdata->dsa_msgout / sizeof(u32)],
++          dsa[hostdata->dsa_msgout / sizeof(u32) + 1],
++          bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1]));
++
++    /* 
++     * Only print messages if they're sane in length so we don't
++     * blow the kernel printk buffer on something which won't buy us
++     * anything.
++     */
++
++    if (dsa[hostdata->dsa_msgout / sizeof(u32)] < 
++          sizeof (hostdata->free->select)) 
++      for (i = dsa[hostdata->dsa_msgout / sizeof(u32)],
++          ptr = bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1]); 
++          i > 0 && !check_address ((unsigned long) ptr, 1);
++          ptr += len, i -= len) {
++          printk("               ");
++          len = spi_print_msg(ptr);
++          printk("\n");
++          if (!len)
++              break;
++      }
 +
++    printk("        + %d : select_indirect = 0x%x\n",
++      hostdata->dsa_select, dsa[hostdata->dsa_select / sizeof(u32)]);
++    cmd = (Scsi_Cmnd *) bus_to_virt(dsa[hostdata->dsa_cmnd / sizeof(u32)]);
++    printk("        + %d : dsa_cmnd = 0x%x ", hostdata->dsa_cmnd,
++         (u32) virt_to_bus(cmd));
++    /* XXX Maybe we should access cmd->host_scribble->result here. RGH */
++    if (cmd) {
++      printk("               result = 0x%x, target = %d, lun = %d, cmd = ",
++          cmd->result, cmd->device->id, cmd->device->lun);
++      __scsi_print_command(cmd->cmnd);
++    } else
++      printk("\n");
++    printk("        + %d : dsa_next = 0x%x\n", hostdata->dsa_next,
++      dsa[hostdata->dsa_next / sizeof(u32)]);
++    if (cmd) { 
++      printk("scsi%d target %d : sxfer_sanity = 0x%x, scntl3_sanity = 0x%x\n"
++             "                   script : ",
++          host->host_no, cmd->device->id,
++          hostdata->sync[cmd->device->id].sxfer_sanity,
++          hostdata->sync[cmd->device->id].scntl3_sanity);
++      for (i = 0; i < (sizeof(hostdata->sync[cmd->device->id].script) / 4); ++i)
++          printk ("0x%x ", hostdata->sync[cmd->device->id].script[i]);
++      printk ("\n");
++      print_progress (cmd);
++    }
++}
 +/*
-+ *  queuecommand  VPORT-specific return codes. Specified in  the host byte code.
-+ *  Returned when the virtual link has failed or is not active.
++ * Function : void print_queues (Scsi_Host *host) 
++ * 
++ * Purpose : print the contents of the NCR issue and reconnect queues
++ *
++ * Inputs : host - SCSI host we are interested in
++ *
 + */
-+#define  DID_VPORT_ERROR      0x0f
 +
-+#define VPORT_INFO    0x1
-+#define VPORT_CREATE  0x2
-+#define VPORT_DELETE  0x4
++static void 
++print_queues (struct Scsi_Host *host) {
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    u32 *dsa, *next_dsa;
++    volatile u32 *ncrcurrent;
++    int left;
++    Scsi_Cmnd *cmd, *next_cmd;
++    unsigned long flags;
 +
-+struct vport_cmd_tag {
-+      uint32_t cmd;
-+      struct vport_data cdata;
-+      struct vport_info cinfo;
-+      void *vport;
-+      int vport_num;
-+};
++    printk ("scsi%d : issue queue\n", host->host_no);
 +
-+void lpfc_vport_set_state(struct lpfc_vport *vport,
-+                        enum fc_vport_state new_state);
++    for (left = host->can_queue, cmd = (Scsi_Cmnd *) hostdata->issue_queue; 
++          left >= 0 && cmd; 
++          cmd = next_cmd) {
++      next_cmd = (Scsi_Cmnd *) cmd->SCp.ptr;
++      local_irq_save(flags);
++      if (cmd->host_scribble) {
++          if (check_address ((unsigned long) (cmd->host_scribble), 
++              sizeof (cmd->host_scribble)) == -1)
++              printk ("scsi%d: scsi pid %ld bad pointer to NCR53c7x0_cmd\n",
++                  host->host_no, cmd->pid);
++          /* print_dsa does sanity check on address, no need to check */
++          else
++              print_dsa (host, ((struct NCR53c7x0_cmd *) cmd->host_scribble)
++                  -> dsa, "");
++      } else 
++          printk ("scsi%d : scsi pid %ld for target %d lun %d has no NCR53c7x0_cmd\n",
++              host->host_no, cmd->pid, cmd->device->id, cmd->device->lun);
++      local_irq_restore(flags);
++    }
++
++    if (left <= 0) {
++      printk ("scsi%d : loop detected in issue queue\n",
++          host->host_no);
++    }
++
++    /*
++     * Traverse the NCR reconnect and start DSA structures, printing out 
++     * each element until we hit the end or detect a loop.  Currently,
++     * the reconnect structure is a linked list; and the start structure
++     * is an array.  Eventually, the reconnect structure will become a 
++     * list as well, since this simplifies the code.
++     */
++
++    printk ("scsi%d : schedule dsa array :\n", host->host_no);
++    for (left = host->can_queue, ncrcurrent = hostdata->schedule;
++          left > 0; ncrcurrent += 2, --left)
++      if (ncrcurrent[0] != hostdata->NOP_insn) 
++/* FIXME : convert pointer to dsa_begin to pointer to dsa. */
++          print_dsa (host, bus_to_virt (ncrcurrent[1] - 
++              (hostdata->E_dsa_code_begin - 
++              hostdata->E_dsa_code_template)), "");
++    printk ("scsi%d : end schedule dsa array\n", host->host_no);
++    
++    printk ("scsi%d : reconnect_dsa_head :\n", host->host_no);
++          
++    for (left = host->can_queue, 
++      dsa = bus_to_virt (hostdata->reconnect_dsa_head);
++      left >= 0 && dsa; 
++      dsa = next_dsa) {
++      local_irq_save(flags);
++      if (check_address ((unsigned long) dsa, sizeof(dsa)) == -1) {
++          printk ("scsi%d: bad DSA pointer 0x%p", host->host_no,
++              dsa);
++          next_dsa = NULL;
++      }
++      else 
++      {
++          next_dsa = bus_to_virt(dsa[hostdata->dsa_next / sizeof(u32)]);
++          print_dsa (host, dsa, "");
++      }
++      local_irq_restore(flags);
++    }
++    printk ("scsi%d : end reconnect_dsa_head\n", host->host_no);
++    if (left < 0)
++      printk("scsi%d: possible loop in ncr reconnect list\n",
++          host->host_no);
++}
 +
-+#endif /* H_LPFC_VPORT */
-diff -Nurb linux-2.6.22-570/drivers/scsi/mac53c94.c linux-2.6.22-590/drivers/scsi/mac53c94.c
---- linux-2.6.22-570/drivers/scsi/mac53c94.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/mac53c94.c   2008-01-02 13:56:37.000000000 -0500
-@@ -77,7 +77,7 @@
-               for (i = 0; i < cmd->cmd_len; ++i)
-                       printk(" %.2x", cmd->cmnd[i]);
-               printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n",
--                     cmd->use_sg, cmd->request_bufflen, cmd->request_buffer);
-+                     scsi_sg_count(cmd), scsi_bufflen(cmd), scsi_sglist(cmd));
-       }
- #endif
-@@ -173,7 +173,6 @@
-       writeb(CMD_SELECT, &regs->command);
-       state->phase = selecting;
--      if (cmd->use_sg > 0 || cmd->request_bufflen != 0)
-               set_dma_cmds(state, cmd);
- }
-@@ -262,7 +261,7 @@
-               writeb(CMD_NOP, &regs->command);
-               /* set DMA controller going if any data to transfer */
-               if ((stat & (STAT_MSG|STAT_CD)) == 0
--                  && (cmd->use_sg > 0 || cmd->request_bufflen != 0)) {
-+                  && (scsi_sg_count(cmd) > 0 || scsi_bufflen(cmd))) {
-                       nb = cmd->SCp.this_residual;
-                       if (nb > 0xfff0)
-                               nb = 0xfff0;
-@@ -310,14 +309,7 @@
-                       printk(KERN_DEBUG "intr %x before data xfer complete\n", intr);
-               }
-               writel(RUN << 16, &dma->control);       /* stop dma */
--              if (cmd->use_sg != 0) {
--                      pci_unmap_sg(state->pdev,
--                              (struct scatterlist *)cmd->request_buffer,
--                              cmd->use_sg, cmd->sc_data_direction);
--              } else {
--                      pci_unmap_single(state->pdev, state->dma_addr,
--                              cmd->request_bufflen, cmd->sc_data_direction);
--              }
-+              scsi_dma_unmap(cmd);
-               /* should check dma status */
-               writeb(CMD_I_COMPLETE, &regs->command);
-               state->phase = completing;
-@@ -365,23 +357,23 @@
-  */
- static void set_dma_cmds(struct fsc_state *state, struct scsi_cmnd *cmd)
- {
--      int i, dma_cmd, total;
-+      int i, dma_cmd, total, nseg;
-       struct scatterlist *scl;
-       struct dbdma_cmd *dcmds;
-       dma_addr_t dma_addr;
-       u32 dma_len;
-+      nseg = scsi_dma_map(cmd);
-+      BUG_ON(nseg < 0);
-+      if (!nseg)
-+              return;
++static void
++print_lots (struct Scsi_Host *host) {
++    NCR53c7x0_local_declare();
++    struct NCR53c7x0_hostdata *hostdata = 
++      (struct NCR53c7x0_hostdata *) host->hostdata[0];
++    u32 *dsp_next, *dsp, *dsa, dbc_dcmd;
++    unsigned char dcmd, sbcl;
++    int i, size;
++    NCR53c7x0_local_setup(host);
++
++    if ((dsp_next = bus_to_virt(NCR53c7x0_read32 (DSP_REG)))) {
++      dbc_dcmd = NCR53c7x0_read32(DBC_REG);
++      dcmd = (dbc_dcmd & 0xff000000) >> 24;
++      dsp = dsp_next - NCR53c7x0_insn_size(dcmd);
++      dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
++      sbcl = NCR53c7x0_read8 (SBCL_REG);
++          
++      /*
++       * For the 53c710, the following will report value 0 for SCNTL3
++       * and STEST0 - we don't have these registers.
++       */
++      printk ("scsi%d : DCMD|DBC=0x%x, DNAD=0x%x (virt 0x%p)\n"
++              "         DSA=0x%lx (virt 0x%p)\n"
++              "         DSPS=0x%x, TEMP=0x%x (virt 0x%p), DMODE=0x%x\n"
++              "         SXFER=0x%x, SCNTL3=0x%x\n"
++              "         %s%s%sphase=%s, %d bytes in SCSI FIFO\n"
++              "         SCRATCH=0x%x, saved2_dsa=0x%0lx\n",
++          host->host_no, dbc_dcmd, NCR53c7x0_read32(DNAD_REG),
++              bus_to_virt(NCR53c7x0_read32(DNAD_REG)),
++          virt_to_bus(dsa), dsa,
++          NCR53c7x0_read32(DSPS_REG), NCR53c7x0_read32(TEMP_REG), 
++          bus_to_virt (NCR53c7x0_read32(TEMP_REG)),
++          (int) NCR53c7x0_read8(hostdata->dmode),
++          (int) NCR53c7x0_read8(SXFER_REG), 
++          ((hostdata->chip / 100) == 8) ?
++              (int) NCR53c7x0_read8(SCNTL3_REG_800) : 0,
++          (sbcl & SBCL_BSY) ? "BSY " : "",
++          (sbcl & SBCL_SEL) ? "SEL " : "",
++          (sbcl & SBCL_REQ) ? "REQ " : "",
++          sstat2_to_phase(NCR53c7x0_read8 (((hostdata->chip / 100) == 8) ?
++              SSTAT1_REG : SSTAT2_REG)),
++          (NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ? 
++              SSTAT1_REG : SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT,
++          ((hostdata->chip / 100) == 8) ? NCR53c7x0_read8 (STEST0_REG_800) :
++              NCR53c7x0_read32(SCRATCHA_REG_800),
++          hostdata->saved2_dsa);
++      printk ("scsi%d : DSP 0x%lx (virt 0x%p) ->\n", host->host_no, 
++          virt_to_bus(dsp), dsp);
++      for (i = 6; i > 0; --i, dsp += size)
++          size = print_insn (host, dsp, "", 1);
++      if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON)  {
++          if ((hostdata->chip / 100) == 8)
++              printk ("scsi%d : connected (SDID=0x%x, SSID=0x%x)\n",
++                  host->host_no, NCR53c7x0_read8 (SDID_REG_800),
++                  NCR53c7x0_read8 (SSID_REG_800));
++          else
++              printk ("scsi%d : connected (SDID=0x%x)\n",
++                  host->host_no, NCR53c7x0_read8 (SDID_REG_700));
++          print_dsa (host, dsa, "");
++      }
++
++#if 1
++      print_queues (host);
++#endif
++    }
++}
 +
-       dma_cmd = cmd->sc_data_direction == DMA_TO_DEVICE ?
-                       OUTPUT_MORE : INPUT_MORE;
-       dcmds = state->dma_cmds;
--      if (cmd->use_sg > 0) {
--              int nseg;
--
-               total = 0;
--              scl = (struct scatterlist *) cmd->request_buffer;
--              nseg = pci_map_sg(state->pdev, scl, cmd->use_sg,
--                              cmd->sc_data_direction);
--              for (i = 0; i < nseg; ++i) {
++/*
++ * Function : static int shutdown (struct Scsi_Host *host)
++ * 
++ * Purpose : does a clean (we hope) shutdown of the NCR SCSI 
++ *    chip.  Use prior to dumping core, unloading the NCR driver,
++ * 
++ * Returns : 0 on success
++ */
++static int 
++shutdown (struct Scsi_Host *host) {
++    NCR53c7x0_local_declare();
++    unsigned long flags;
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    NCR53c7x0_local_setup(host);
++    local_irq_save(flags);
++/* Get in a state where we can reset the SCSI bus */
++    ncr_halt (host);
++    ncr_scsi_reset (host);
++    hostdata->soft_reset(host);
++
++    disable (host);
++    local_irq_restore(flags);
++    return 0;
++}
 +
-+      scsi_for_each_sg(cmd, scl, nseg, i) {
-                       dma_addr = sg_dma_address(scl);
-                       dma_len = sg_dma_len(scl);
-                       if (dma_len > 0xffff)
-@@ -391,21 +383,9 @@
-                       st_le16(&dcmds->command, dma_cmd);
-                       st_le32(&dcmds->phy_addr, dma_addr);
-                       dcmds->xfer_status = 0;
--                      ++scl;
--                      ++dcmds;
--              }
--      } else {
--              total = cmd->request_bufflen;
--              if (total > 0xffff)
--                      panic("mac53c94: transfer size >= 64k");
--              dma_addr = pci_map_single(state->pdev, cmd->request_buffer,
--                                        total, cmd->sc_data_direction);
--              state->dma_addr = dma_addr;
--              st_le16(&dcmds->req_count, total);
--              st_le32(&dcmds->phy_addr, dma_addr);
--              dcmds->xfer_status = 0;
-               ++dcmds;
-       }
++/*
++ * Function : void ncr_scsi_reset (struct Scsi_Host *host)
++ *
++ * Purpose : reset the SCSI bus.
++ */
 +
-       dma_cmd += OUTPUT_LAST - OUTPUT_MORE;
-       st_le16(&dcmds[-1].command, dma_cmd);
-       st_le16(&dcmds->command, DBDMA_STOP);
-diff -Nurb linux-2.6.22-570/drivers/scsi/megaraid/megaraid_mbox.c linux-2.6.22-590/drivers/scsi/megaraid/megaraid_mbox.c
---- linux-2.6.22-570/drivers/scsi/megaraid/megaraid_mbox.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/megaraid/megaraid_mbox.c     2008-01-02 13:56:37.000000000 -0500
-@@ -1378,8 +1378,6 @@
- {
-       struct scatterlist      *sgl;
-       mbox_ccb_t              *ccb;
--      struct page             *page;
--      unsigned long           offset;
-       struct scsi_cmnd        *scp;
-       int                     sgcnt;
-       int                     i;
-@@ -1388,48 +1386,16 @@
-       scp     = scb->scp;
-       ccb     = (mbox_ccb_t *)scb->ccb;
-+      sgcnt = scsi_dma_map(scp);
-+      BUG_ON(sgcnt < 0 || sgcnt > adapter->sglen);
++static void 
++ncr_scsi_reset (struct Scsi_Host *host) {
++    NCR53c7x0_local_declare();
++    unsigned long flags;
++    NCR53c7x0_local_setup(host);
++    local_irq_save(flags);
++    NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
++    udelay(25);       /* Minimum amount of time to assert RST */
++    NCR53c7x0_write8(SCNTL1_REG, 0);
++    local_irq_restore(flags);
++}
++
++/* 
++ * Function : void hard_reset (struct Scsi_Host *host)
++ *
++ */
++
++static void 
++hard_reset (struct Scsi_Host *host) {
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    unsigned long flags;
++    local_irq_save(flags);
++    ncr_scsi_reset(host);
++    NCR53c7x0_driver_init (host);
++    if (hostdata->soft_reset)
++      hostdata->soft_reset (host);
++    local_irq_restore(flags);
++}
++
++
++/*
++ * Function : Scsi_Cmnd *return_outstanding_commands (struct Scsi_Host *host,
++ *    int free, int issue)
++ *
++ * Purpose : return a linked list (using the SCp.buffer field as next,
++ *    so we don't perturb hostdata.  We don't use a field of the 
++ *    NCR53c7x0_cmd structure since we may not have allocated one 
++ *    for the command causing the reset.) of Scsi_Cmnd structures that 
++ *    had propagated below the Linux issue queue level.  If free is set, 
++ *    free the NCR53c7x0_cmd structures which are associated with 
++ *    the Scsi_Cmnd structures, and clean up any internal 
++ *    NCR lists that the commands were on.  If issue is set,
++ *    also return commands in the issue queue.
++ *
++ * Returns : linked list of commands
++ *
++ * NOTE : the caller should insure that the NCR chip is halted
++ *    if the free flag is set. 
++ */
++
++static Scsi_Cmnd *
++return_outstanding_commands (struct Scsi_Host *host, int free, int issue) {
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    struct NCR53c7x0_cmd *c;
++    int i;
++    u32 *ncrcurrent;
++    Scsi_Cmnd *list = NULL, *tmp;
++    for (c = (struct NCR53c7x0_cmd *) hostdata->running_list; c; 
++      c = (struct NCR53c7x0_cmd *) c->next)  {
++      if (c->cmd->SCp.buffer) {
++          printk ("scsi%d : loop detected in running list!\n", host->host_no);
++          break;
++      } else {
++          printk ("Duh? Bad things happening in the NCR driver\n");
++          break;
++      }
 +
-       // no mapping required if no data to be transferred
--      if (!scp->request_buffer || !scp->request_bufflen)
-+      if (!sgcnt)
-               return 0;
--      if (!scp->use_sg) {     /* scatter-gather list not used */
--
--              page = virt_to_page(scp->request_buffer);
--
--              offset = ((unsigned long)scp->request_buffer & ~PAGE_MASK);
--
--              ccb->buf_dma_h = pci_map_page(adapter->pdev, page, offset,
--                                                scp->request_bufflen,
--                                                scb->dma_direction);
--              scb->dma_type = MRAID_DMA_WBUF;
--
--              /*
--               * We need to handle special 64-bit commands that need a
--               * minimum of 1 SG
--               */
--              sgcnt = 1;
--              ccb->sgl64[0].address   = ccb->buf_dma_h;
--              ccb->sgl64[0].length    = scp->request_bufflen;
--
--              return sgcnt;
--      }
--
--      sgl = (struct scatterlist *)scp->request_buffer;
--
--      // The number of sg elements returned must not exceed our limit
--      sgcnt = pci_map_sg(adapter->pdev, sgl, scp->use_sg,
--                      scb->dma_direction);
--
--      if (sgcnt > adapter->sglen) {
--              con_log(CL_ANN, (KERN_CRIT
--                      "megaraid critical: too many sg elements:%d\n",
--                      sgcnt));
--              BUG();
--      }
--
-       scb->dma_type = MRAID_DMA_WSG;
--      for (i = 0; i < sgcnt; i++, sgl++) {
-+      scsi_for_each_sg(scp, sgl, sgcnt, i) {
-               ccb->sgl64[i].address   = sg_dma_address(sgl);
-               ccb->sgl64[i].length    = sg_dma_len(sgl);
-       }
-@@ -1489,19 +1455,11 @@
-       adapter->outstanding_cmds++;
--      if (scb->dma_direction == PCI_DMA_TODEVICE) {
--              if (!scb->scp->use_sg) {        // sg list not used
--                      pci_dma_sync_single_for_device(adapter->pdev,
--                                      ccb->buf_dma_h,
--                                      scb->scp->request_bufflen,
--                                      PCI_DMA_TODEVICE);
--              }
--              else {
-+      if (scb->dma_direction == PCI_DMA_TODEVICE)
-                       pci_dma_sync_sg_for_device(adapter->pdev,
--                              scb->scp->request_buffer,
--                              scb->scp->use_sg, PCI_DMA_TODEVICE);
--              }
--      }
-+                                         scsi_sglist(scb->scp),
-+                                         scsi_sg_count(scb->scp),
-+                                         PCI_DMA_TODEVICE);
-       mbox->busy      = 1;    // Set busy
-       mbox->poll      = 0;
-@@ -1624,11 +1582,11 @@
-                       return scb;
-               case MODE_SENSE:
--                      if (scp->use_sg) {
-+              {
-                               struct scatterlist      *sgl;
-                               caddr_t                 vaddr;
--                              sgl = (struct scatterlist *)scp->request_buffer;
-+                      sgl = scsi_sglist(scp);
-                               if (sgl->page) {
-                                       vaddr = (caddr_t)
-                                               (page_address((&sgl[0])->page)
-@@ -1642,9 +1600,6 @@
-                                       __LINE__));
-                               }
-                       }
--                      else {
--                              memset(scp->request_buffer, 0, scp->cmnd[4]);
--                      }
-                       scp->result = (DID_OK << 16);
-                       return NULL;
-@@ -1716,7 +1671,7 @@
-                       mbox->cmd               = MBOXCMD_PASSTHRU64;
-                       scb->dma_direction      = scp->sc_data_direction;
--                      pthru->dataxferlen      = scp->request_bufflen;
-+                      pthru->dataxferlen      = scsi_bufflen(scp);
-                       pthru->dataxferaddr     = ccb->sgl_dma_h;
-                       pthru->numsge           = megaraid_mbox_mksgl(adapter,
-                                                       scb);
-@@ -2050,8 +2005,8 @@
-       memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
--      if (scp->request_bufflen) {
--              pthru->dataxferlen      = scp->request_bufflen;
-+      if (scsi_bufflen(scp)) {
-+              pthru->dataxferlen      = scsi_bufflen(scp);
-               pthru->dataxferaddr     = ccb->sgl_dma_h;
-               pthru->numsge           = megaraid_mbox_mksgl(adapter, scb);
-       }
-@@ -2099,8 +2054,8 @@
-       memcpy(epthru->cdb, scp->cmnd, scp->cmd_len);
--      if (scp->request_bufflen) {
--              epthru->dataxferlen     = scp->request_bufflen;
-+      if (scsi_bufflen(scp)) {
-+              epthru->dataxferlen     = scsi_bufflen(scp);
-               epthru->dataxferaddr    = ccb->sgl_dma_h;
-               epthru->numsge          = megaraid_mbox_mksgl(adapter, scb);
-       }
-@@ -2266,37 +2221,13 @@
-       ccb     = (mbox_ccb_t *)scb->ccb;
--      switch (scb->dma_type) {
--
--      case MRAID_DMA_WBUF:
--              if (scb->dma_direction == PCI_DMA_FROMDEVICE) {
--                      pci_dma_sync_single_for_cpu(adapter->pdev,
--                                      ccb->buf_dma_h,
--                                      scb->scp->request_bufflen,
--                                      PCI_DMA_FROMDEVICE);
--              }
--
--              pci_unmap_page(adapter->pdev, ccb->buf_dma_h,
--                      scb->scp->request_bufflen, scb->dma_direction);
--
--              break;
--
--      case MRAID_DMA_WSG:
--              if (scb->dma_direction == PCI_DMA_FROMDEVICE) {
-+      if (scb->dma_direction == PCI_DMA_FROMDEVICE)
-                       pci_dma_sync_sg_for_cpu(adapter->pdev,
--                                      scb->scp->request_buffer,
--                                      scb->scp->use_sg, PCI_DMA_FROMDEVICE);
--              }
--
--              pci_unmap_sg(adapter->pdev, scb->scp->request_buffer,
--                      scb->scp->use_sg, scb->dma_direction);
--
--              break;
--
--      default:
--              break;
--      }
-+                                      scsi_sglist(scb->scp),
-+                                      scsi_sg_count(scb->scp),
-+                                      PCI_DMA_FROMDEVICE);
-+      scsi_dma_unmap(scb->scp);
-       return;
- }
-@@ -2399,25 +2330,17 @@
-               if (scp->cmnd[0] == INQUIRY && status == 0 && islogical == 0
-                               && IS_RAID_CH(raid_dev, scb->dev_channel)) {
--                      if (scp->use_sg) {
--                              sgl = (struct scatterlist *)
--                                      scp->request_buffer;
--
-+                      sgl = scsi_sglist(scp);
-                               if (sgl->page) {
-                                       c = *(unsigned char *)
-                                       (page_address((&sgl[0])->page) +
-                                               (&sgl[0])->offset);
--                              }
--                              else {
-+                      } else {
-                                       con_log(CL_ANN, (KERN_WARNING
-                                       "megaraid mailbox: invalid sg:%d\n",
-                                       __LINE__));
-                                       c = 0;
-                               }
--                      }
--                      else {
--                              c = *(uint8_t *)scp->request_buffer;
--                      }
-                       if ((c & 0x1F ) == TYPE_DISK) {
-                               pdev_index = (scb->dev_channel * 16) +
-diff -Nurb linux-2.6.22-570/drivers/scsi/megaraid/megaraid_sas.c linux-2.6.22-590/drivers/scsi/megaraid/megaraid_sas.c
---- linux-2.6.22-570/drivers/scsi/megaraid/megaraid_sas.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/megaraid/megaraid_sas.c      2008-01-02 13:56:37.000000000 -0500
-@@ -433,34 +433,15 @@
-       int sge_count;
-       struct scatterlist *os_sgl;
--      /*
--       * Return 0 if there is no data transfer
--       */
--      if (!scp->request_buffer || !scp->request_bufflen)
--              return 0;
-+      sge_count = scsi_dma_map(scp);
-+      BUG_ON(sge_count < 0);
--      if (!scp->use_sg) {
--              mfi_sgl->sge32[0].phys_addr = pci_map_single(instance->pdev,
--                                                           scp->
--                                                           request_buffer,
--                                                           scp->
--                                                           request_bufflen,
--                                                           scp->
--                                                           sc_data_direction);
--              mfi_sgl->sge32[0].length = scp->request_bufflen;
--
--              return 1;
--      }
--
--      os_sgl = (struct scatterlist *)scp->request_buffer;
--      sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg,
--                             scp->sc_data_direction);
--
--      for (i = 0; i < sge_count; i++, os_sgl++) {
-+      if (sge_count) {
-+              scsi_for_each_sg(scp, os_sgl, sge_count, i) {
-               mfi_sgl->sge32[i].length = sg_dma_len(os_sgl);
-               mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl);
-       }
--
++      c->cmd->SCp.buffer = (struct scatterlist *) list;
++      list = c->cmd;
++      if (free) {
++          c->next = hostdata->free;
++          hostdata->free = c;
 +      }
-       return sge_count;
- }
-@@ -481,35 +462,15 @@
-       int sge_count;
-       struct scatterlist *os_sgl;
--      /*
--       * Return 0 if there is no data transfer
--       */
--      if (!scp->request_buffer || !scp->request_bufflen)
--              return 0;
--
--      if (!scp->use_sg) {
--              mfi_sgl->sge64[0].phys_addr = pci_map_single(instance->pdev,
--                                                           scp->
--                                                           request_buffer,
--                                                           scp->
--                                                           request_bufflen,
--                                                           scp->
--                                                           sc_data_direction);
-+      sge_count = scsi_dma_map(scp);
-+      BUG_ON(sge_count < 0);
--              mfi_sgl->sge64[0].length = scp->request_bufflen;
--
--              return 1;
--      }
--
--      os_sgl = (struct scatterlist *)scp->request_buffer;
--      sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg,
--                             scp->sc_data_direction);
--
--      for (i = 0; i < sge_count; i++, os_sgl++) {
-+      if (sge_count) {
-+              scsi_for_each_sg(scp, os_sgl, sge_count, i) {
-               mfi_sgl->sge64[i].length = sg_dma_len(os_sgl);
-               mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl);
-       }
--
++    }
++
++    if (free) { 
++      for (i = 0, ncrcurrent = (u32 *) hostdata->schedule; 
++          i < host->can_queue; ++i, ncrcurrent += 2) {
++          ncrcurrent[0] = hostdata->NOP_insn;
++          ncrcurrent[1] = 0xdeadbeef;
 +      }
-       return sge_count;
- }
-@@ -593,7 +554,7 @@
-       pthru->cdb_len = scp->cmd_len;
-       pthru->timeout = 0;
-       pthru->flags = flags;
--      pthru->data_xfer_len = scp->request_bufflen;
-+      pthru->data_xfer_len = scsi_bufflen(scp);
-       memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
-@@ -1195,45 +1156,6 @@
- }
- /**
-- * megasas_unmap_sgbuf -      Unmap SG buffers
-- * @instance:                 Adapter soft state
-- * @cmd:                      Completed command
-- */
--static void
--megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
--{
--      dma_addr_t buf_h;
--      u8 opcode;
--
--      if (cmd->scmd->use_sg) {
--              pci_unmap_sg(instance->pdev, cmd->scmd->request_buffer,
--                           cmd->scmd->use_sg, cmd->scmd->sc_data_direction);
--              return;
--      }
--
--      if (!cmd->scmd->request_bufflen)
--              return;
--
--      opcode = cmd->frame->hdr.cmd;
--
--      if ((opcode == MFI_CMD_LD_READ) || (opcode == MFI_CMD_LD_WRITE)) {
--              if (IS_DMA64)
--                      buf_h = cmd->frame->io.sgl.sge64[0].phys_addr;
--              else
--                      buf_h = cmd->frame->io.sgl.sge32[0].phys_addr;
--      } else {
--              if (IS_DMA64)
--                      buf_h = cmd->frame->pthru.sgl.sge64[0].phys_addr;
--              else
--                      buf_h = cmd->frame->pthru.sgl.sge32[0].phys_addr;
--      }
--
--      pci_unmap_single(instance->pdev, buf_h, cmd->scmd->request_bufflen,
--                       cmd->scmd->sc_data_direction);
--      return;
--}
--
--/**
-  * megasas_complete_cmd -     Completes a command
-  * @instance:                 Adapter soft state
-  * @cmd:                      Command to be completed
-@@ -1281,7 +1203,7 @@
-                       atomic_dec(&instance->fw_outstanding);
--                      megasas_unmap_sgbuf(instance, cmd);
-+                      scsi_dma_unmap(cmd->scmd);
-                       cmd->scmd->scsi_done(cmd->scmd);
-                       megasas_return_cmd(instance, cmd);
-@@ -1329,7 +1251,7 @@
-               atomic_dec(&instance->fw_outstanding);
--              megasas_unmap_sgbuf(instance, cmd);
-+              scsi_dma_unmap(cmd->scmd);
-               cmd->scmd->scsi_done(cmd->scmd);
-               megasas_return_cmd(instance, cmd);
-diff -Nurb linux-2.6.22-570/drivers/scsi/megaraid.c linux-2.6.22-590/drivers/scsi/megaraid.c
---- linux-2.6.22-570/drivers/scsi/megaraid.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/megaraid.c   2008-01-02 13:56:37.000000000 -0500
-@@ -523,10 +523,8 @@
-       /*
-        * filter the internal and ioctl commands
-        */
--      if((cmd->cmnd[0] == MEGA_INTERNAL_CMD)) {
--              return cmd->request_buffer;
--      }
--
-+      if((cmd->cmnd[0] == MEGA_INTERNAL_CMD))
-+              return (scb_t *)cmd->host_scribble;
-       /*
-        * We know what channels our logical drives are on - mega_find_card()
-@@ -657,22 +655,14 @@
-               case MODE_SENSE: {
-                       char *buf;
--
--                      if (cmd->use_sg) {
-                               struct scatterlist *sg;
--                              sg = (struct scatterlist *)cmd->request_buffer;
--                              buf = kmap_atomic(sg->page, KM_IRQ0) +
--                                      sg->offset;
--                      } else
--                              buf = cmd->request_buffer;
--                      memset(buf, 0, cmd->cmnd[4]);
--                      if (cmd->use_sg) {
--                              struct scatterlist *sg;
-+                      sg = scsi_sglist(cmd);
-+                      buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
--                              sg = (struct scatterlist *)cmd->request_buffer;
-+                      memset(buf, 0, cmd->cmnd[4]);
-                               kunmap_atomic(buf - sg->offset, KM_IRQ0);
--                      }
++      hostdata->ncrcurrent = NULL;
++    }
 +
-                       cmd->result = (DID_OK << 16);
-                       cmd->scsi_done(cmd);
-                       return NULL;
-@@ -1551,24 +1541,16 @@
-               islogical = adapter->logdrv_chan[cmd->device->channel];
-               if( cmd->cmnd[0] == INQUIRY && !islogical ) {
--                      if( cmd->use_sg ) {
--                              sgl = (struct scatterlist *)
--                                      cmd->request_buffer;
--
-+                      sgl = scsi_sglist(cmd);
-                               if( sgl->page ) {
-                                       c = *(unsigned char *)
-                                       page_address((&sgl[0])->page) +
-                                       (&sgl[0])->offset; 
--                              }
--                              else {
-+                      } else {
-                                       printk(KERN_WARNING
-                                               "megaraid: invalid sg.\n");
-                                       c = 0;
-                               }
--                      }
--                      else {
--                              c = *(u8 *)cmd->request_buffer;
--                      }
-                       if(IS_RAID_CH(adapter, cmd->device->channel) &&
-                                       ((c & 0x1F ) == TYPE_DISK)) {
-@@ -1704,30 +1686,14 @@
- static void
- mega_free_scb(adapter_t *adapter, scb_t *scb)
- {
--      unsigned long length;
--
-       switch( scb->dma_type ) {
-       case MEGA_DMA_TYPE_NONE:
-               break;
--      case MEGA_BULK_DATA:
--              if (scb->cmd->use_sg == 0)
--                      length = scb->cmd->request_bufflen;
--              else {
--                      struct scatterlist *sgl =
--                              (struct scatterlist *)scb->cmd->request_buffer;
--                      length = sgl->length;
--              }
--              pci_unmap_page(adapter->dev, scb->dma_h_bulkdata,
--                             length, scb->dma_direction);
--              break;
--
-       case MEGA_SGLIST:
--              pci_unmap_sg(adapter->dev, scb->cmd->request_buffer,
--                      scb->cmd->use_sg, scb->dma_direction);
-+              scsi_dma_unmap(scb->cmd);
-               break;
--
-       default:
-               break;
-       }
-@@ -1767,80 +1733,33 @@
- static int
- mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
- {
--      struct scatterlist      *sgl;
--      struct page     *page;
--      unsigned long   offset;
--      unsigned int    length;
-+      struct scatterlist *sg;
-       Scsi_Cmnd       *cmd;
-       int     sgcnt;
-       int     idx;
-       cmd = scb->cmd;
--      /* Scatter-gather not used */
--      if( cmd->use_sg == 0 || (cmd->use_sg == 1 && 
--                               !adapter->has_64bit_addr)) {
--
--              if (cmd->use_sg == 0) {
--                      page = virt_to_page(cmd->request_buffer);
--                      offset = offset_in_page(cmd->request_buffer);
--                      length = cmd->request_bufflen;
--              } else {
--                      sgl = (struct scatterlist *)cmd->request_buffer;
--                      page = sgl->page;
--                      offset = sgl->offset;
--                      length = sgl->length;
--              }
--
--              scb->dma_h_bulkdata = pci_map_page(adapter->dev,
--                                                page, offset,
--                                                length,
--                                                scb->dma_direction);
--              scb->dma_type = MEGA_BULK_DATA;
--
--              /*
--               * We need to handle special 64-bit commands that need a
--               * minimum of 1 SG
--               */
--              if( adapter->has_64bit_addr ) {
--                      scb->sgl64[0].address = scb->dma_h_bulkdata;
--                      scb->sgl64[0].length = length;
--                      *buf = (u32)scb->sgl_dma_addr;
--                      *len = (u32)length;
--                      return 1;
--              }
--              else {
--                      *buf = (u32)scb->dma_h_bulkdata;
--                      *len = (u32)length;
--              }
--              return 0;
--      }
--
--      sgl = (struct scatterlist *)cmd->request_buffer;
--
-       /*
-        * Copy Scatter-Gather list info into controller structure.
-        *
-        * The number of sg elements returned must not exceed our limit
-        */
--      sgcnt = pci_map_sg(adapter->dev, sgl, cmd->use_sg,
--                      scb->dma_direction);
-+      sgcnt = scsi_dma_map(cmd);
-       scb->dma_type = MEGA_SGLIST;
--      BUG_ON(sgcnt > adapter->sglen);
-+      BUG_ON(sgcnt > adapter->sglen || sgcnt < 0);
-       *len = 0;
--      for( idx = 0; idx < sgcnt; idx++, sgl++ ) {
--
--              if( adapter->has_64bit_addr ) {
--                      scb->sgl64[idx].address = sg_dma_address(sgl);
--                      *len += scb->sgl64[idx].length = sg_dma_len(sgl);
--              }
--              else {
--                      scb->sgl[idx].address = sg_dma_address(sgl);
--                      *len += scb->sgl[idx].length = sg_dma_len(sgl);
-+      scsi_for_each_sg(cmd, sg, sgcnt, idx) {
-+              if (adapter->has_64bit_addr) {
-+                      scb->sgl64[idx].address = sg_dma_address(sg);
-+                      *len += scb->sgl64[idx].length = sg_dma_len(sg);
++    if (issue) {
++      for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; tmp = tmp->next) {
++          if (tmp->SCp.buffer) {
++              printk ("scsi%d : loop detected in issue queue!\n", 
++                      host->host_no);
++              break;
++          }
++          tmp->SCp.buffer = (struct scatterlist *) list;
++          list = tmp;
++      }
++      if (free)
++          hostdata->issue_queue = NULL;
++              
++    }
++    return list;
++}
++
++/* 
++ * Function : static int disable (struct Scsi_Host *host)
++ *
++ * Purpose : disables the given NCR host, causing all commands
++ *    to return a driver error.  Call this so we can unload the
++ *    module during development and try again.  Eventually, 
++ *    we should be able to find clean workarounds for these
++ *    problems.
++ *
++ * Inputs : host - hostadapter to twiddle
++ *
++ * Returns : 0 on success.
++ */
++
++static int 
++disable (struct Scsi_Host *host) {
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    unsigned long flags;
++    Scsi_Cmnd *nuke_list, *tmp;
++    local_irq_save(flags);
++    if (hostdata->state != STATE_HALTED)
++      ncr_halt (host);
++    nuke_list = return_outstanding_commands (host, 1 /* free */, 1 /* issue */);
++    hard_reset (host);
++    hostdata->state = STATE_DISABLED;
++    local_irq_restore(flags);
++    printk ("scsi%d : nuking commands\n", host->host_no);
++    for (; nuke_list; nuke_list = tmp) {
++          tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
++          nuke_list->result = DID_ERROR << 16;
++          nuke_list->scsi_done(nuke_list);
++    }
++    printk ("scsi%d : done. \n", host->host_no);
++    printk (KERN_ALERT "scsi%d : disabled.  Unload and reload\n",
++      host->host_no);
++    return 0;
++}
++
++/*
++ * Function : static int ncr_halt (struct Scsi_Host *host)
++ * 
++ * Purpose : halts the SCSI SCRIPTS(tm) processor on the NCR chip
++ *
++ * Inputs : host - SCSI chip to halt
++ *
++ * Returns : 0 on success
++ */
++
++static int 
++ncr_halt (struct Scsi_Host *host) {
++    NCR53c7x0_local_declare();
++    unsigned long flags;
++    unsigned char istat, tmp;
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    int stage;
++    NCR53c7x0_local_setup(host);
++
++    local_irq_save(flags);
++    /* Stage 0 : eat all interrupts
++       Stage 1 : set ABORT
++       Stage 2 : eat all but abort interrupts
++       Stage 3 : eat all interrupts
++     */
++    for (stage = 0;;) {
++      if (stage == 1) {
++          NCR53c7x0_write8(hostdata->istat, ISTAT_ABRT);
++          ++stage;
++      }
++      istat = NCR53c7x0_read8 (hostdata->istat);
++      if (istat & ISTAT_SIP) {
++          tmp = NCR53c7x0_read8(SSTAT0_REG);
++      } else if (istat & ISTAT_DIP) {
++          tmp = NCR53c7x0_read8(DSTAT_REG);
++          if (stage == 2) {
++              if (tmp & DSTAT_ABRT) {
++                  NCR53c7x0_write8(hostdata->istat, 0);
++                  ++stage;
 +              } else {
-+                      scb->sgl[idx].address = sg_dma_address(sg);
-+                      *len += scb->sgl[idx].length = sg_dma_len(sg);
-               }
-       }
-@@ -3571,7 +3490,7 @@
-                       /*
-                        * The user passthru structure
-                        */
--                      upthru = (mega_passthru __user *)MBOX(uioc)->xferaddr;
-+                      upthru = (mega_passthru __user *)(unsigned long)MBOX(uioc)->xferaddr;
-                       /*
-                        * Copy in the user passthru here.
-@@ -3623,7 +3542,7 @@
-                               /*
-                                * Get the user data
-                                */
--                              if( copy_from_user(data, (char __user *)uxferaddr,
-+                              if( copy_from_user(data, (char __user *)(unsigned long) uxferaddr,
-                                                       pthru->dataxferlen) ) {
-                                       rval = (-EFAULT);
-                                       goto freemem_and_return;
-@@ -3649,7 +3568,7 @@
-                        * Is data going up-stream
-                        */
-                       if( pthru->dataxferlen && (uioc.flags & UIOC_RD) ) {
--                              if( copy_to_user((char __user *)uxferaddr, data,
-+                              if( copy_to_user((char __user *)(unsigned long) uxferaddr, data,
-                                                       pthru->dataxferlen) ) {
-                                       rval = (-EFAULT);
-                               }
-@@ -3702,7 +3621,7 @@
-                               /*
-                                * Get the user data
-                                */
--                              if( copy_from_user(data, (char __user *)uxferaddr,
-+                              if( copy_from_user(data, (char __user *)(unsigned long) uxferaddr,
-                                                       uioc.xferlen) ) {
-                                       pci_free_consistent(pdev,
-@@ -3742,7 +3661,7 @@
-                        * Is data going up-stream
-                        */
-                       if( uioc.xferlen && (uioc.flags & UIOC_RD) ) {
--                              if( copy_to_user((char __user *)uxferaddr, data,
-+                              if( copy_to_user((char __user *)(unsigned long) uxferaddr, data,
-                                                       uioc.xferlen) ) {
-                                       rval = (-EFAULT);
-@@ -4494,7 +4413,7 @@
-       scmd->device = sdev;
-       scmd->device->host = adapter->host;
--      scmd->request_buffer = (void *)scb;
-+      scmd->host_scribble = (void *)scb;
-       scmd->cmnd[0] = MEGA_INTERNAL_CMD;
-       scb->state |= SCB_ACTIVE;
-diff -Nurb linux-2.6.22-570/drivers/scsi/mesh.c linux-2.6.22-590/drivers/scsi/mesh.c
---- linux-2.6.22-570/drivers/scsi/mesh.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/mesh.c       2008-01-02 13:56:37.000000000 -0500
-@@ -421,7 +421,7 @@
-               for (i = 0; i < cmd->cmd_len; ++i)
-                       printk(" %x", cmd->cmnd[i]);
-               printk(" use_sg=%d buffer=%p bufflen=%u\n",
--                     cmd->use_sg, cmd->request_buffer, cmd->request_bufflen);
-+                     scsi_sg_count(cmd), scsi_sglist(cmd), scsi_bufflen(cmd));
-       }
- #endif
-       if (ms->dma_started)
-@@ -602,13 +602,16 @@
-                       cmd->result += (cmd->SCp.Message << 8);
-               if (DEBUG_TARGET(cmd)) {
-                       printk(KERN_DEBUG "mesh_done: result = %x, data_ptr=%d, buflen=%d\n",
--                             cmd->result, ms->data_ptr, cmd->request_bufflen);
-+                             cmd->result, ms->data_ptr, scsi_bufflen(cmd));
++                  printk(KERN_ALERT "scsi%d : could not halt NCR chip\n", 
++                      host->host_no);
++                  disable (host);
++              }
++          }
++      }
++      if (!(istat & (ISTAT_SIP|ISTAT_DIP))) {
++          if (stage == 0)
++              ++stage;
++          else if (stage == 3)
++              break;
++      }
++    }
++    hostdata->state = STATE_HALTED;
++    local_irq_restore(flags);
 +#if 0
-+                      /* needs to use sg? */
-                       if ((cmd->cmnd[0] == 0 || cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 3)
-                           && cmd->request_buffer != 0) {
-                               unsigned char *b = cmd->request_buffer;
-                               printk(KERN_DEBUG "buffer = %x %x %x %x %x %x %x %x\n",
-                                      b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
-                       }
++    print_lots (host);
 +#endif
-               }
-               cmd->SCp.this_residual -= ms->data_ptr;
-               mesh_completed(ms, cmd);
-@@ -1265,15 +1268,18 @@
-       dcmds = ms->dma_cmds;
-       dtot = 0;
-       if (cmd) {
--              cmd->SCp.this_residual = cmd->request_bufflen;
--              if (cmd->use_sg > 0) {
-                       int nseg;
++    return 0;
++}
 +
-+              cmd->SCp.this_residual = scsi_bufflen(cmd);
++/* 
++ * Function: event_name (int event)
++ * 
++ * Purpose: map event enum into user-readable strings.
++ */
 +
-+              nseg = scsi_dma_map(cmd);
-+              BUG_ON(nseg < 0);
++static const char *
++event_name (int event) {
++    switch (event) {
++    case EVENT_NONE:          return "none";
++    case EVENT_ISSUE_QUEUE:   return "to issue queue";
++    case EVENT_START_QUEUE:   return "to start queue";
++    case EVENT_SELECT:                return "selected";
++    case EVENT_DISCONNECT:    return "disconnected";
++    case EVENT_RESELECT:      return "reselected";
++    case EVENT_COMPLETE:      return "completed";
++    case EVENT_IDLE:          return "idle";
++    case EVENT_SELECT_FAILED: return "select failed";
++    case EVENT_BEFORE_SELECT: return "before select";
++    case EVENT_RESELECT_FAILED:       return "reselect failed";
++    default:                  return "unknown";
++    }
++}
 +
-+              if (nseg) {
-                       total = 0;
--                      scl = (struct scatterlist *) cmd->request_buffer;
-                       off = ms->data_ptr;
--                      nseg = pci_map_sg(ms->pdev, scl, cmd->use_sg,
--                                        cmd->sc_data_direction);
--                      for (i = 0; i <nseg; ++i, ++scl) {
++/*
++ * Function : void dump_events (struct Scsi_Host *host, count)
++ *
++ * Purpose : print last count events which have occurred.
++ */ 
++static void
++dump_events (struct Scsi_Host *host, int count) {
++    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
++      host->hostdata[0];
++    struct NCR53c7x0_event event;
++    int i;
++    unsigned long flags;
++    if (hostdata->events) {
++      if (count > hostdata->event_size)
++          count = hostdata->event_size;
++      for (i = hostdata->event_index; count > 0; 
++          i = (i ? i - 1 : hostdata->event_size -1), --count) {
++/*
++ * By copying the event we're currently examining with interrupts
++ * disabled, we can do multiple printk(), etc. operations and 
++ * still be guaranteed that they're happening on the same 
++ * event structure.
++ */
++          local_irq_save(flags);
++#if 0
++          event = hostdata->events[i];
++#else
++          memcpy ((void *) &event, (void *) &(hostdata->events[i]),
++              sizeof(event));
++#endif
 +
-+                      scsi_for_each_sg(cmd, scl, nseg, i) {
-                               u32 dma_addr = sg_dma_address(scl);
-                               u32 dma_len = sg_dma_len(scl);
-                               
-@@ -1292,16 +1298,6 @@
-                               dtot += dma_len - off;
-                               off = 0;
-                       }
--              } else if (ms->data_ptr < cmd->request_bufflen) {
--                      dtot = cmd->request_bufflen - ms->data_ptr;
--                      if (dtot > 0xffff)
--                              panic("mesh: transfer size >= 64k");
--                      st_le16(&dcmds->req_count, dtot);
--                      /* XXX Use pci DMA API here ... */
--                      st_le32(&dcmds->phy_addr,
--                              virt_to_phys(cmd->request_buffer) + ms->data_ptr);
--                      dcmds->xfer_status = 0;
--                      ++dcmds;
-               }
-       }
-       if (dtot == 0) {
-@@ -1356,18 +1352,14 @@
-               dumplog(ms, ms->conn_tgt);
-               dumpslog(ms);
- #endif /* MESH_DBG */
--      } else if (cmd && cmd->request_bufflen != 0 &&
--                 ms->data_ptr > cmd->request_bufflen) {
-+      } else if (cmd && scsi_bufflen(cmd) &&
-+                 ms->data_ptr > scsi_bufflen(cmd)) {
-               printk(KERN_DEBUG "mesh: target %d overrun, "
-                      "data_ptr=%x total=%x goes_out=%d\n",
--                     ms->conn_tgt, ms->data_ptr, cmd->request_bufflen,
-+                     ms->conn_tgt, ms->data_ptr, scsi_bufflen(cmd),
-                      ms->tgts[ms->conn_tgt].data_goes_out);
-       }
--      if (cmd->use_sg != 0) {
--              struct scatterlist *sg;
--              sg = (struct scatterlist *)cmd->request_buffer;
--              pci_unmap_sg(ms->pdev, sg, cmd->use_sg, cmd->sc_data_direction);
--      }
-+      scsi_dma_unmap(cmd);
-       ms->dma_started = 0;
- }
-diff -Nurb linux-2.6.22-570/drivers/scsi/mvme16x.c linux-2.6.22-590/drivers/scsi/mvme16x.c
---- linux-2.6.22-570/drivers/scsi/mvme16x.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/mvme16x.c    1969-12-31 19:00:00.000000000 -0500
-@@ -1,78 +0,0 @@
--/*
-- * Detection routine for the NCR53c710 based MVME16x SCSI Controllers for Linux.
-- *
-- * Based on work by Alan Hourihane
-- */
--#include <linux/types.h>
--#include <linux/mm.h>
--#include <linux/blkdev.h>
--
--#include <asm/page.h>
--#include <asm/pgtable.h>
--#include <asm/mvme16xhw.h>
--#include <asm/irq.h>
--
--#include "scsi.h"
--#include <scsi/scsi_host.h>
--#include "53c7xx.h"
--#include "mvme16x.h"
--
--#include<linux/stat.h>
--
--
--int mvme16x_scsi_detect(struct scsi_host_template *tpnt)
--{
--    static unsigned char called = 0;
--    int clock;
--    long long options;
--
--    if (!MACH_IS_MVME16x)
--              return 0;
--    if (mvme16x_config & MVME16x_CONFIG_NO_SCSICHIP) {
--      printk ("SCSI detection disabled, SCSI chip not present\n");
--      return 0;
--    }
--    if (called)
--      return 0;
--
--    tpnt->proc_name = "MVME16x";
--
--    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
--
--    clock = 66000000; /* 66MHz SCSI Clock */
--
--    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)0xfff47000,
--                      0, MVME16x_IRQ_SCSI, DMA_NONE,
--                      options, clock);
--    called = 1;
--    return 1;
--}
--
--static int mvme16x_scsi_release(struct Scsi_Host *shost)
--{
--      if (shost->irq)
--              free_irq(shost->irq, NULL);
--      if (shost->dma_channel != 0xff)
--              free_dma(shost->dma_channel);
--      if (shost->io_port && shost->n_io_port)
--              release_region(shost->io_port, shost->n_io_port);
--      scsi_unregister(shost);
--      return 0;
--}
--
--static struct scsi_host_template driver_template = {
--      .name                   = "MVME16x NCR53c710 SCSI",
--      .detect                 = mvme16x_scsi_detect,
--      .release                = mvme16x_scsi_release,
--      .queuecommand           = NCR53c7xx_queue_command,
--      .abort                  = NCR53c7xx_abort,
--      .reset                  = NCR53c7xx_reset,
--      .can_queue              = 24,
--      .this_id                = 7,
--      .sg_tablesize           = 63,
--      .cmd_per_lun            = 3,
--      .use_clustering         = DISABLE_CLUSTERING
--};
--
--
--#include "scsi_module.c"
-diff -Nurb linux-2.6.22-570/drivers/scsi/mvme16x.h linux-2.6.22-590/drivers/scsi/mvme16x.h
---- linux-2.6.22-570/drivers/scsi/mvme16x.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/mvme16x.h    1969-12-31 19:00:00.000000000 -0500
-@@ -1,24 +0,0 @@
--#ifndef MVME16x_SCSI_H
--#define MVME16x_SCSI_H
--
--#include <linux/types.h>
--
--int mvme16x_scsi_detect(struct scsi_host_template *);
--const char *NCR53c7x0_info(void);
--int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
--int NCR53c7xx_abort(Scsi_Cmnd *);
--int NCR53c7x0_release (struct Scsi_Host *);
--int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
--void NCR53c7x0_intr(int irq, void *dev_id);
--
--#ifndef CMD_PER_LUN
--#define CMD_PER_LUN 3
--#endif
--
--#ifndef CAN_QUEUE
--#define CAN_QUEUE 24
--#endif
--
--#include <scsi/scsicam.h>
--
--#endif /* MVME16x_SCSI_H */
-diff -Nurb linux-2.6.22-570/drivers/scsi/mvme16x_scsi.c linux-2.6.22-590/drivers/scsi/mvme16x_scsi.c
---- linux-2.6.22-570/drivers/scsi/mvme16x_scsi.c       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/scsi/mvme16x_scsi.c       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,158 @@
++          local_irq_restore(flags);
++          printk ("scsi%d : %s event %d at %ld secs %ld usecs target %d lun %d\n",
++              host->host_no, event_name (event.event), count,
++              (long) event.time.tv_sec, (long) event.time.tv_usec,
++              event.target, event.lun);
++          if (event.dsa) 
++              printk ("         event for dsa 0x%lx (virt 0x%p)\n", 
++                  virt_to_bus(event.dsa), event.dsa);
++          if (event.pid != -1) {
++              printk ("         event for pid %ld ", event.pid);
++              __scsi_print_command (event.cmnd);
++          }
++      }
++    }
++}
++
++/*
++ * Function: check_address
++ *
++ * Purpose: Check to see if a possibly corrupt pointer will fault the 
++ *    kernel.
++ *
++ * Inputs: addr - address; size - size of area
++ *
++ * Returns: 0 if area is OK, -1 on error.
++ *
++ * NOTES: should be implemented in terms of vverify on kernels 
++ *    that have it.
++ */
++
++static int 
++check_address (unsigned long addr, int size) {
++    return (virt_to_phys((void *)addr) < PAGE_SIZE || virt_to_phys((void *)(addr + size)) > virt_to_phys(high_memory) ?  -1 : 0);
++}
++
++#ifdef MODULE
++int 
++NCR53c7x0_release(struct Scsi_Host *host) {
++    struct NCR53c7x0_hostdata *hostdata = 
++      (struct NCR53c7x0_hostdata *) host->hostdata[0];
++    struct NCR53c7x0_cmd *cmd, *tmp;
++    shutdown (host);
++    if (host->irq != SCSI_IRQ_NONE)
++      {
++          int irq_count;
++          struct Scsi_Host *tmp;
++          for (irq_count = 0, tmp = first_host; tmp; tmp = tmp->next)
++              if (tmp->hostt == the_template && tmp->irq == host->irq)
++                  ++irq_count;
++          if (irq_count == 1)
++              free_irq(host->irq, NULL);
++      }
++    if (host->dma_channel != DMA_NONE)
++      free_dma(host->dma_channel);
++    if (host->io_port)
++      release_region(host->io_port, host->n_io_port);
++    
++    for (cmd = (struct NCR53c7x0_cmd *) hostdata->free; cmd; cmd = tmp, 
++      --hostdata->num_cmds) {
++      tmp = (struct NCR53c7x0_cmd *) cmd->next;
++    /* 
++     * If we're going to loop, try to stop it to get a more accurate
++     * count of the leaked commands.
++     */
++      cmd->next = NULL;
++      if (cmd->free)
++          cmd->free ((void *) cmd->real, cmd->size);
++    }
++    if (hostdata->num_cmds)
++      printk ("scsi%d : leaked %d NCR53c7x0_cmd structures\n",
++          host->host_no, hostdata->num_cmds);
++
++    vfree(hostdata->events);
++
++    /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
++     * XXX may be invalid (CONFIG_060_WRITETHROUGH)
++     */
++    kernel_set_cachemode((void *)hostdata, 8192, IOMAP_FULL_CACHING);
++    free_pages ((u32)hostdata, 1);
++    return 1;
++}
++#endif /* def MODULE */
+diff -Nurb linux-2.6.22-590/drivers/scsi/53c7xx.h linux-2.6.22-570/drivers/scsi/53c7xx.h
+--- linux-2.6.22-590/drivers/scsi/53c7xx.h     1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/53c7xx.h     2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,1608 @@
++/*
++ * 53c710 driver.  Modified from Drew Eckhardts driver
++ * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
++ *
++ * I have left the code for the 53c8xx family in here, because it didn't
++ * seem worth removing it.  The possibility of IO_MAPPED chips rather
++ * than MEMORY_MAPPED remains, in case someone wants to add support for
++ * 53c710 chips on Intel PCs (some older machines have them on the
++ * motherboard).
++ *
++ * NOTE THERE MAY BE PROBLEMS WITH CASTS IN read8 AND Co.
++ */
++
++/*
++ * NCR 53c{7,8}0x0 driver, header file
++ *
++ * Sponsored by
++ *      iX Multiuser Multitasking Magazine
++ *    Hannover, Germany
++ *    hm@ix.de        
++ *
++ * Copyright 1993, 1994, 1995 Drew Eckhardt
++ *      Visionary Computing 
++ *      (Unix and Linux consulting and custom programming)
++ *      drew@PoohSticks.ORG
++ *    +1 (303) 786-7975
++ *
++ * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
++ * 
++ * PRE-ALPHA
++ *
++ * For more information, please consult 
++ *
++ * NCR 53C700/53C700-66
++ * SCSI I/O Processor
++ * Data Manual
++ *
++ * NCR 53C810
++ * PCI-SCSI I/O Processor 
++ * Data Manual
++ *
++ * NCR Microelectronics
++ * 1635 Aeroplaza Drive
++ * Colorado Springs, CO 80916
++ * +1 (719) 578-3400
++ *
++ * Toll free literature number
++ * +1 (800) 334-5454
++ *
++ */
++
++#ifndef NCR53c710_H
++#define NCR53c710_H
++
++#ifndef HOSTS_C
++
++/* SCSI control 0 rw, default = 0xc0 */ 
++#define SCNTL0_REG            0x00    
++#define SCNTL0_ARB1           0x80    /* 0 0 = simple arbitration */
++#define SCNTL0_ARB2           0x40    /* 1 1 = full arbitration */
++#define SCNTL0_STRT           0x20    /* Start Sequence */
++#define SCNTL0_WATN           0x10    /* Select with ATN */
++#define SCNTL0_EPC            0x08    /* Enable parity checking */
++/* Bit 2 is reserved on 800 series chips */
++#define SCNTL0_EPG_700                0x04    /* Enable parity generation */
++#define SCNTL0_AAP            0x02    /*  ATN/ on parity error */
++#define SCNTL0_TRG            0x01    /* Target mode */
++
++/* SCSI control 1 rw, default = 0x00 */
++
++#define SCNTL1_REG            0x01    
++#define SCNTL1_EXC            0x80    /* Extra Clock Cycle of Data setup */
++#define SCNTL1_ADB            0x40    /*  contents of SODL on bus */
++#define SCNTL1_ESR_700                0x20    /* Enable SIOP response to selection 
++                                         and reselection */
++#define SCNTL1_DHP_800                0x20    /* Disable halt on parity error or ATN
++                                         target mode only */
++#define SCNTL1_CON            0x10    /* Connected */
++#define SCNTL1_RST            0x08    /* SCSI RST/ */
++#define SCNTL1_AESP           0x04    /* Force bad parity */
++#define SCNTL1_SND_700                0x02    /* Start SCSI send */
++#define SCNTL1_IARB_800               0x02    /* Immediate Arbitration, start
++                                         arbitration immediately after
++                                         busfree is detected */
++#define SCNTL1_RCV_700                0x01    /* Start SCSI receive */
++#define SCNTL1_SST_800                0x01    /* Start SCSI transfer */
++
++/* SCSI control 2 rw, */
++
++#define SCNTL2_REG_800                0x02    
++#define SCNTL2_800_SDU                0x80    /* SCSI disconnect unexpected */
++
++/* SCSI control 3 rw */
++
++#define SCNTL3_REG_800                0x03    
++#define SCNTL3_800_SCF_SHIFT  4
++#define SCNTL3_800_SCF_MASK   0x70
++#define SCNTL3_800_SCF2               0x40    /* Synchronous divisor */
++#define SCNTL3_800_SCF1               0x20    /* 0x00 = SCLK/3 */
++#define SCNTL3_800_SCF0               0x10    /* 0x10 = SCLK/1 */
++                                      /* 0x20 = SCLK/1.5 
++                                         0x30 = SCLK/2 
++                                         0x40 = SCLK/3 */
++          
++#define SCNTL3_800_CCF_SHIFT  0
++#define SCNTL3_800_CCF_MASK   0x07
++#define SCNTL3_800_CCF2               0x04    /* 0x00 50.01 to 66 */
++#define SCNTL3_800_CCF1               0x02    /* 0x01 16.67 to 25 */
++#define SCNTL3_800_CCF0               0x01    /* 0x02 25.01 - 37.5 
++                                         0x03 37.51 - 50 
++                                         0x04 50.01 - 66 */
++
++/*  
++ * SCSI destination ID rw - the appropriate bit is set for the selected
++ * target ID.  This is written by the SCSI SCRIPTS processor.
++ * default = 0x00
++ */
++#define SDID_REG_700                  0x02    
++#define SDID_REG_800          0x06
++
++#define GP_REG_800            0x07    /* General purpose IO */
++#define GP_800_IO1            0x02
++#define GP_800_IO2            0x01
++
++/* SCSI interrupt enable rw, default = 0x00 */
++#define SIEN_REG_700          0x03    
++#define SIEN0_REG_800         0x40
++#define SIEN_MA                       0x80    /* Phase mismatch (ini) or ATN (tgt) */
++#define SIEN_FC                       0x40    /* Function complete */
++#define SIEN_700_STO          0x20    /* Selection or reselection timeout */
++#define SIEN_800_SEL          0x20    /* Selected */
++#define SIEN_700_SEL          0x10    /* Selected or reselected */
++#define SIEN_800_RESEL                0x10    /* Reselected */
++#define SIEN_SGE              0x08    /* SCSI gross error */
++#define SIEN_UDC              0x04    /* Unexpected disconnect */
++#define SIEN_RST              0x02    /* SCSI RST/ received */
++#define SIEN_PAR              0x01    /* Parity error */
++
++/* 
++ * SCSI chip ID rw
++ * NCR53c700 : 
++ *    When arbitrating, the highest bit is used, when reselection or selection
++ *    occurs, the chip responds to all IDs for which a bit is set.
++ *    default = 0x00 
++ * NCR53c810 : 
++ *    Uses bit mapping
++ */
++#define SCID_REG              0x04    
++/* Bit 7 is reserved on 800 series chips */
++#define SCID_800_RRE          0x40    /* Enable response to reselection */
++#define SCID_800_SRE          0x20    /* Enable response to selection */
++/* Bits four and three are reserved on 800 series chips */
++#define SCID_800_ENC_MASK     0x07    /* Encoded SCSI ID */
++
++/* SCSI transfer rw, default = 0x00 */
++#define SXFER_REG             0x05
++#define SXFER_DHP             0x80    /* Disable halt on parity */
++
++#define SXFER_TP2             0x40    /* Transfer period msb */
++#define SXFER_TP1             0x20
++#define SXFER_TP0             0x10    /* lsb */
++#define SXFER_TP_MASK         0x70
++/* FIXME : SXFER_TP_SHIFT == 5 is right for '8xx chips */
++#define SXFER_TP_SHIFT                5
++#define SXFER_TP_4            0x00    /* Divisors */
++#define SXFER_TP_5            0x10<<1
++#define SXFER_TP_6            0x20<<1
++#define SXFER_TP_7            0x30<<1
++#define SXFER_TP_8            0x40<<1
++#define SXFER_TP_9            0x50<<1
++#define SXFER_TP_10           0x60<<1
++#define SXFER_TP_11           0x70<<1
++
++#define SXFER_MO3             0x08    /* Max offset msb */
++#define SXFER_MO2             0x04
++#define SXFER_MO1             0x02
++#define SXFER_MO0             0x01    /* lsb */
++#define SXFER_MO_MASK         0x0f
++#define SXFER_MO_SHIFT                0
++
++/* 
++ * SCSI output data latch rw
++ * The contents of this register are driven onto the SCSI bus when 
++ * the Assert Data Bus bit of the SCNTL1 register is set and 
++ * the CD, IO, and MSG bits of the SOCL register match the SCSI phase
++ */
++#define SODL_REG_700          0x06    
++#define SODL_REG_800          0x54
++
++
++/* 
++ * SCSI output control latch rw, default = 0 
++ * Note that when the chip is being manually programmed as an initiator,
++ * the MSG, CD, and IO bits must be set correctly for the phase the target
++ * is driving the bus in.  Otherwise no data transfer will occur due to 
++ * phase mismatch.
++ */
++
++#define SOCL_REG              0x07
++#define SOCL_REQ              0x80    /*  REQ */
++#define SOCL_ACK              0x40    /*  ACK */
++#define SOCL_BSY              0x20    /*  BSY */
++#define SOCL_SEL              0x10    /*  SEL */
++#define SOCL_ATN              0x08    /*  ATN */
++#define SOCL_MSG              0x04    /*  MSG */
++#define SOCL_CD                       0x02    /*  C/D */
++#define SOCL_IO                       0x01    /*  I/O */
++
++/* 
++ * SCSI first byte received latch ro 
++ * This register contains the first byte received during a block MOVE 
++ * SCSI SCRIPTS instruction, including
++ * 
++ * Initiator mode     Target mode
++ * Message in         Command
++ * Status             Message out
++ * Data in            Data out
++ *
++ * It also contains the selecting or reselecting device's ID and our 
++ * ID.
++ *
++ * Note that this is the register the various IF conditionals can 
++ * operate on.
++ */
++#define SFBR_REG              0x08    
++
++/* 
++ * SCSI input data latch ro
++ * In initiator mode, data is latched into this register on the rising
++ * edge of REQ/. In target mode, data is latched on the rising edge of 
++ * ACK/
++ */
++#define SIDL_REG_700          0x09
++#define SIDL_REG_800          0x50
++
++/* 
++ * SCSI bus data lines ro 
++ * This register reflects the instantaneous status of the SCSI data 
++ * lines.  Note that SCNTL0 must be set to disable parity checking, 
++ * otherwise reading this register will latch new parity.
++ */
++#define SBDL_REG_700          0x0a
++#define SBDL_REG_800          0x58
++
++#define SSID_REG_800          0x0a
++#define SSID_800_VAL          0x80    /* Exactly two bits asserted at sel */
++#define SSID_800_ENCID_MASK   0x07    /* Device which performed operation */
++
++
++/* 
++ * SCSI bus control lines rw, 
++ * instantaneous readout of control lines 
++ */
++#define SBCL_REG              0x0b    
++#define SBCL_REQ              0x80    /*  REQ ro */
++#define SBCL_ACK              0x40    /*  ACK ro */
++#define SBCL_BSY              0x20    /*  BSY ro */
++#define SBCL_SEL              0x10    /*  SEL ro */
++#define SBCL_ATN              0x08    /*  ATN ro */
++#define SBCL_MSG              0x04    /*  MSG ro */
++#define SBCL_CD                       0x02    /*  C/D ro */
++#define SBCL_IO                       0x01    /*  I/O ro */
++#define SBCL_PHASE_CMDOUT     SBCL_CD
++#define SBCL_PHASE_DATAIN     SBCL_IO
++#define SBCL_PHASE_DATAOUT    0
++#define SBCL_PHASE_MSGIN      (SBCL_CD|SBCL_IO|SBCL_MSG)
++#define SBCL_PHASE_MSGOUT     (SBCL_CD|SBCL_MSG)
++#define SBCL_PHASE_STATIN     (SBCL_CD|SBCL_IO)
++#define SBCL_PHASE_MASK               (SBCL_CD|SBCL_IO|SBCL_MSG)
++/* 
++ * Synchronous SCSI Clock Control bits 
++ * 0 - set by DCNTL 
++ * 1 - SCLK / 1.0
++ * 2 - SCLK / 1.5
++ * 3 - SCLK / 2.0 
++ */
++#define SBCL_SSCF1            0x02    /* wo, -66 only */
++#define SBCL_SSCF0            0x01    /* wo, -66 only */
++#define SBCL_SSCF_MASK                0x03
++
++/* 
++ * XXX note : when reading the DSTAT and STAT registers to clear interrupts,
++ * insure that 10 clocks elapse between the two  
++ */
++/* DMA status ro */
++#define DSTAT_REG             0x0c    
++#define DSTAT_DFE             0x80    /* DMA FIFO empty */
++#define DSTAT_800_MDPE                0x40    /* Master Data Parity Error */
++#define DSTAT_800_BF          0x20    /* Bus Fault */
++#define DSTAT_ABRT            0x10    /* Aborted - set on error */
++#define DSTAT_SSI             0x08    /* SCRIPTS single step interrupt */
++#define DSTAT_SIR             0x04    /* SCRIPTS interrupt received - 
++                                         set when INT instruction is 
++                                         executed */
++#define DSTAT_WTD             0x02    /* Watchdog timeout detected */
++#define DSTAT_OPC             0x01    /* Illegal instruction */
++#define DSTAT_800_IID         0x01    /* Same thing, different name */
++
++
++/* NCR53c800 moves this stuff into SIST0 */
++#define SSTAT0_REG            0x0d    /* SCSI status 0 ro */
++#define SIST0_REG_800         0x42    
++#define SSTAT0_MA             0x80    /* ini : phase mismatch,
++                                       * tgt : ATN/ asserted 
++                                       */
++#define SSTAT0_CMP            0x40    /* function complete */
++#define SSTAT0_700_STO                0x20    /* Selection or reselection timeout */
++#define SIST0_800_SEL         0x20    /* Selected */
++#define SSTAT0_700_SEL                0x10    /* Selected or reselected */
++#define SIST0_800_RSL         0x10    /* Reselected */
++#define SSTAT0_SGE            0x08    /* SCSI gross error */
++#define SSTAT0_UDC            0x04    /* Unexpected disconnect */
++#define SSTAT0_RST            0x02    /* SCSI RST/ received */
++#define SSTAT0_PAR            0x01    /* Parity error */
++
++/* And uses SSTAT0 for what was SSTAT1 */
++
++#define SSTAT1_REG            0x0e    /* SCSI status 1 ro */
++#define SSTAT1_ILF            0x80    /* SIDL full */
++#define SSTAT1_ORF            0x40    /* SODR full */
++#define SSTAT1_OLF            0x20    /* SODL full */
++#define SSTAT1_AIP            0x10    /* Arbitration in progress */
++#define SSTAT1_LOA            0x08    /* Lost arbitration */
++#define SSTAT1_WOA            0x04    /* Won arbitration */
++#define SSTAT1_RST            0x02    /* Instant readout of RST/ */
++#define SSTAT1_SDP            0x01    /* Instant readout of SDP/ */
++
++#define SSTAT2_REG            0x0f    /* SCSI status 2 ro */
++#define SSTAT2_FF3            0x80    /* number of bytes in synchronous */
++#define SSTAT2_FF2            0x40    /* data FIFO */
++#define SSTAT2_FF1            0x20    
++#define SSTAT2_FF0            0x10
++#define SSTAT2_FF_MASK                0xf0
++#define SSTAT2_FF_SHIFT               4
++
++/* 
++ * Latched signals, latched on the leading edge of REQ/ for initiators,
++ * ACK/ for targets.
++ */
++#define SSTAT2_SDP            0x08    /* SDP */
++#define SSTAT2_MSG            0x04    /* MSG */
++#define SSTAT2_CD             0x02    /* C/D */
++#define SSTAT2_IO             0x01    /* I/O */
++#define SSTAT2_PHASE_CMDOUT   SSTAT2_CD
++#define SSTAT2_PHASE_DATAIN   SSTAT2_IO
++#define SSTAT2_PHASE_DATAOUT  0
++#define SSTAT2_PHASE_MSGIN    (SSTAT2_CD|SSTAT2_IO|SSTAT2_MSG)
++#define SSTAT2_PHASE_MSGOUT   (SSTAT2_CD|SSTAT2_MSG)
++#define SSTAT2_PHASE_STATIN   (SSTAT2_CD|SSTAT2_IO)
++#define SSTAT2_PHASE_MASK     (SSTAT2_CD|SSTAT2_IO|SSTAT2_MSG)
++
++
++/* NCR53c700-66 only */
++#define SCRATCHA_REG_00               0x10    /* through  0x13 Scratch A rw */
++/* NCR53c710 and higher */
++#define DSA_REG                       0x10    /* DATA structure address */
++
++#define CTEST0_REG_700                0x14    /* Chip test 0 ro */
++#define CTEST0_REG_800                0x18    /* Chip test 0 rw, general purpose */
++/* 0x80 - 0x04 are reserved */
++#define CTEST0_700_RTRG               0x02    /* Real target mode */
++#define CTEST0_700_DDIR               0x01    /* Data direction, 1 = 
++                                       * SCSI bus to host, 0  =
++                                       * host to SCSI.
++                                       */
++
++#define CTEST1_REG_700                0x15    /* Chip test 1 ro */
++#define CTEST1_REG_800                0x19    /* Chip test 1 ro */
++#define CTEST1_FMT3           0x80    /* Identify which byte lanes are empty */
++#define CTEST1_FMT2           0x40    /* in the DMA FIFO */
++#define CTEST1_FMT1           0x20
++#define CTEST1_FMT0           0x10
++
++#define CTEST1_FFL3           0x08    /* Identify which bytes lanes are full */
++#define CTEST1_FFL2           0x04    /* in the DMA FIFO */
++#define CTEST1_FFL1           0x02
++#define CTEST1_FFL0           0x01
++
++#define CTEST2_REG_700                0x16    /* Chip test 2 ro */
++#define CTEST2_REG_800                0x1a    /* Chip test 2 ro */
++
++#define CTEST2_800_DDIR               0x80    /* 1 = SCSI->host */
++#define CTEST2_800_SIGP               0x40    /* A copy of SIGP in ISTAT.
++                                         Reading this register clears */
++#define CTEST2_800_CIO                0x20    /* Configured as IO */.
++#define CTEST2_800_CM         0x10    /* Configured as memory */
++
++/* 0x80 - 0x40 are reserved on 700 series chips */
++#define CTEST2_700_SOFF               0x20    /* SCSI Offset Compare,
++                                       * As an initiator, this bit is 
++                                       * one when the synchronous offset
++                                       * is zero, as a target this bit 
++                                       * is one when the synchronous 
++                                       * offset is at the maximum
++                                       * defined in SXFER
++                                       */
++#define CTEST2_700_SFP                0x10    /* SCSI FIFO parity bit,
++                                       * reading CTEST3 unloads a byte
++                                       * from the FIFO and sets this
++                                       */
++#define CTEST2_700_DFP                0x08    /* DMA FIFO parity bit,
++                                       * reading CTEST6 unloads a byte
++                                       * from the FIFO and sets this
++                                       */
++#define CTEST2_TEOP           0x04    /* SCSI true end of process,
++                                       * indicates a totally finished
++                                       * transfer
++                                       */
++#define CTEST2_DREQ           0x02    /* Data request signal */
++/* 0x01 is reserved on 700 series chips */
++#define CTEST2_800_DACK               0x01    
++
++/* 
++ * Chip test 3 ro 
++ * Unloads the bottom byte of the eight deep SCSI synchronous FIFO,
++ * check SSTAT2 FIFO full bits to determine size.  Note that a GROSS
++ * error results if a read is attempted on this register.  Also note 
++ * that 16 and 32 bit reads of this register will cause corruption.
++ */
++#define CTEST3_REG_700                0x17    
++/*  Chip test 3 rw */
++#define CTEST3_REG_800                0x1b
++#define CTEST3_800_V3         0x80    /* Chip revision */
++#define CTEST3_800_V2         0x40
++#define CTEST3_800_V1         0x20
++#define CTEST3_800_V0         0x10
++#define CTEST3_800_FLF                0x08    /* Flush DMA FIFO */
++#define CTEST3_800_CLF                0x04    /* Clear DMA FIFO */
++#define CTEST3_800_FM         0x02    /* Fetch mode pin */
++/* bit 0 is reserved on 800 series chips */
++
++#define CTEST4_REG_700                0x18    /* Chip test 4 rw */
++#define CTEST4_REG_800                0x21    /* Chip test 4 rw */
++/* 0x80 is reserved on 700 series chips */
++#define CTEST4_800_BDIS               0x80    /* Burst mode disable */
++#define CTEST4_ZMOD           0x40    /* High impedance mode */
++#define CTEST4_SZM            0x20    /* SCSI bus high impedance */
++#define CTEST4_700_SLBE               0x10    /* SCSI loopback enabled */
++#define CTEST4_800_SRTM               0x10    /* Shadow Register Test Mode */
++#define CTEST4_700_SFWR               0x08    /* SCSI FIFO write enable, 
++                                       * redirects writes from SODL
++                                       * to the SCSI FIFO.
++                                       */
++#define CTEST4_800_MPEE               0x08    /* Enable parity checking
++                                         during master cycles on PCI
++                                         bus */
++
++/* 
++ * These bits send the contents of the CTEST6 register to the appropriate
++ * byte lane of the 32 bit DMA FIFO.  Normal operation is zero, otherwise 
++ * the high bit means the low two bits select the byte lane.
++ */
++#define CTEST4_FBL2           0x04    
++#define CTEST4_FBL1           0x02
++#define CTEST4_FBL0           0x01    
++#define CTEST4_FBL_MASK               0x07
++#define CTEST4_FBL_0          0x04    /* Select DMA FIFO byte lane 0 */
++#define CTEST4_FBL_1          0x05    /* Select DMA FIFO byte lane 1 */
++#define CTEST4_FBL_2          0x06    /* Select DMA FIFO byte lane 2 */
++#define CTEST4_FBL_3          0x07    /* Select DMA FIFO byte lane 3 */
++#define CTEST4_800_SAVE               (CTEST4_800_BDIS)
++
++
++#define CTEST5_REG_700                0x19    /* Chip test 5 rw */
++#define CTEST5_REG_800                0x22    /* Chip test 5 rw */
++/* 
++ * Clock Address Incrementor.  When set, it increments the 
++ * DNAD register to the next bus size boundary.  It automatically 
++ * resets itself when the operation is complete.
++ */
++#define CTEST5_ADCK           0x80
 +/*
-+ * Detection routine for the NCR53c710 based MVME16x SCSI Controllers for Linux.
++ * Clock Byte Counter.  When set, it decrements the DBC register to
++ * the next bus size boundary.
++ */
++#define CTEST5_BBCK           0x40
++/*
++ * Reset SCSI Offset.  Setting this bit to 1 clears the current offset
++ * pointer in the SCSI synchronous offset counter (SSTAT).  This bit
++ * is set to 1 if a SCSI Gross Error Condition occurs.  The offset should
++ * be cleared when a synchronous transfer fails.  When written, it is 
++ * automatically cleared after the SCSI synchronous offset counter is 
++ * reset.
++ */
++/* Bit 5 is reserved on 800 series chips */
++#define CTEST5_700_ROFF               0x20
++/* 
++ * Master Control for Set or Reset pulses. When 1, causes the low 
++ * four bits of register to set when set, 0 causes the low bits to
++ * clear when set.
++ */
++#define CTEST5_MASR           0x10    
++#define CTEST5_DDIR           0x08    /* DMA direction */
++/*
++ * Bits 2-0 are reserved on 800 series chips
++ */
++#define CTEST5_700_EOP                0x04    /* End of process */
++#define CTEST5_700_DREQ               0x02    /* Data request */
++#define CTEST5_700_DACK               0x01    /* Data acknowledge */
++
++/* 
++ * Chip test 6 rw - writing to this register writes to the byte 
++ * lane in the DMA FIFO as determined by the FBL bits in the CTEST4
++ * register.
++ */
++#define CTEST6_REG_700                0x1a
++#define CTEST6_REG_800                0x23
++
++#define CTEST7_REG            0x1b    /* Chip test 7 rw */
++/* 0x80 - 0x40 are reserved on NCR53c700 and NCR53c700-66 chips */
++#define CTEST7_10_CDIS                0x80    /* Cache burst disable */
++#define CTEST7_10_SC1         0x40    /* Snoop control bits */
++#define CTEST7_10_SC0         0x20    
++#define CTEST7_10_SC_MASK     0x60
++/* 0x20 is reserved on the NCR53c700 */
++#define CTEST7_0060_FM                0x20    /* Fetch mode */
++#define CTEST7_STD            0x10    /* Selection timeout disable */
++#define CTEST7_DFP            0x08    /* DMA FIFO parity bit for CTEST6 */
++#define CTEST7_EVP            0x04    /* 1 = host bus even parity, 0 = odd */
++#define CTEST7_10_TT1         0x02    /* Transfer type */
++#define CTEST7_00_DC          0x02    /* Set to drive DC low during instruction 
++                                         fetch */
++#define CTEST7_DIFF           0x01    /* Differential mode */
++
++#define CTEST7_SAVE ( CTEST7_EVP | CTEST7_DIFF )
++
++
++#define TEMP_REG              0x1c    /* through 0x1f Temporary stack rw */
++
++#define DFIFO_REG             0x20    /* DMA FIFO rw */
++/* 
++ * 0x80 is reserved on the NCR53c710, the CLF and FLF bits have been
++ * moved into the CTEST8 register.
++ */
++#define DFIFO_00_FLF          0x80    /* Flush DMA FIFO to memory */
++#define DFIFO_00_CLF          0x40    /* Clear DMA and SCSI FIFOs */
++#define DFIFO_BO6             0x40
++#define DFIFO_BO5             0x20
++#define DFIFO_BO4             0x10
++#define DFIFO_BO3             0x08
++#define DFIFO_BO2             0x04 
++#define DFIFO_BO1             0x02
++#define DFIFO_BO0             0x01
++#define DFIFO_10_BO_MASK      0x7f    /* 7 bit counter */
++#define DFIFO_00_BO_MASK      0x3f    /* 6 bit counter */
++
++/* 
++ * Interrupt status rw 
++ * Note that this is the only register which can be read while SCSI
++ * SCRIPTS are being executed.
++ */
++#define ISTAT_REG_700         0x21
++#define ISTAT_REG_800         0x14
++#define ISTAT_ABRT            0x80    /* Software abort, write 
++                                       *1 to abort, wait for interrupt. */
++/* 0x40 and 0x20 are reserved on NCR53c700 and NCR53c700-66 chips */
++#define ISTAT_10_SRST         0x40    /* software reset */
++#define ISTAT_10_SIGP         0x20    /* signal script */
++/* 0x10 is reserved on NCR53c700 series chips */
++#define ISTAT_800_SEM         0x10    /* semaphore */
++#define ISTAT_CON             0x08    /* 1 when connected */
++#define ISTAT_800_INTF                0x04    /* Interrupt on the fly */
++#define ISTAT_700_PRE         0x04    /* Pointer register empty.
++                                       * Set to 1 when DSPS and DSP
++                                       * registers are empty in pipeline
++                                       * mode, always set otherwise.
++                                       */
++#define ISTAT_SIP             0x02    /* SCSI interrupt pending from
++                                       * SCSI portion of SIOP see
++                                       * SSTAT0
++                                       */
++#define ISTAT_DIP             0x01    /* DMA interrupt pending 
++                                       * see DSTAT
++                                       */
++
++/* NCR53c700-66 and NCR53c710 only */
++#define CTEST8_REG            0x22    /* Chip test 8 rw */
++#define CTEST8_0066_EAS               0x80    /* Enable alternate SCSI clock,
++                                       * ie read from SCLK/ rather than CLK/
++                                       */
++#define CTEST8_0066_EFM               0x40    /* Enable fetch and master outputs */
++#define CTEST8_0066_GRP               0x20    /* Generate Receive Parity for 
++                                       * pass through.  This insures that 
++                                       * bad parity won't reach the host 
++                                       * bus.
++                                       */
++#define CTEST8_0066_TE                0x10    /* TolerANT enable.  Enable 
++                                       * active negation, should only
++                                       * be used for slow SCSI 
++                                       * non-differential.
++                                       */
++#define CTEST8_0066_HSC               0x08    /* Halt SCSI clock */
++#define CTEST8_0066_SRA               0x04    /* Shorten REQ/ACK filtering,
++                                       * must be set for fast SCSI-II
++                                       * speeds.
++                                       */
++#define CTEST8_0066_DAS               0x02    /* Disable automatic target/initiator
++                                       * switching.
++                                       */
++#define CTEST8_0066_LDE               0x01    /* Last disconnect enable.
++                                       * The status of pending 
++                                       * disconnect is maintained by
++                                       * the core, eliminating
++                                       * the possibility of missing a 
++                                       * selection or reselection
++                                       * while waiting to fetch a 
++                                       * WAIT DISCONNECT opcode.
++                                       */
++
++#define CTEST8_10_V3          0x80    /* Chip revision */
++#define CTEST8_10_V2          0x40
++#define CTEST8_10_V1          0x20    
++#define CTEST8_10_V0          0x10
++#define CTEST8_10_V_MASK      0xf0    
++#define CTEST8_10_FLF         0x08    /* Flush FIFOs */
++#define CTEST8_10_CLF         0x04    /* Clear FIFOs */
++#define CTEST8_10_FM          0x02    /* Fetch pin mode */
++#define CTEST8_10_SM          0x01    /* Snoop pin mode */
++
++
++/* 
++ * The CTEST9 register may be used to differentiate between a
++ * NCR53c700 and a NCR53c710.  
 + *
-+ * Based on work by Alan Hourihane
++ * Write 0xff to this register.
++ * Read it.
++ * If the contents are 0xff, it is a NCR53c700
++ * If the contents are 0x00, it is a NCR53c700-66 first revision
++ * If the contents are some other value, it is some other NCR53c700-66
++ */
++#define CTEST9_REG_00         0x23    /* Chip test 9 ro */
++#define LCRC_REG_10           0x23    
++
++/*
++ * 0x24 through 0x27 are the DMA byte counter register.  Instructions
++ * write their high 8 bits into the DCMD register, the low 24 bits into
++ * the DBC register.
 + *
-+ * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
++ * Function is dependent on the command type being executed.
 + */
 +
-+#include <linux/module.h>
-+#include <linux/blkdev.h>
-+#include <linux/device.h>
-+#include <linux/platform_device.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <asm/mvme16xhw.h>
-+#include <scsi/scsi_host.h>
-+#include <scsi/scsi_device.h>
-+#include <scsi/scsi_transport.h>
-+#include <scsi/scsi_transport_spi.h>
++ 
++#define DBC_REG                       0x24
++/* 
++ * For Block Move Instructions, DBC is a 24 bit quantity representing 
++ *     the number of bytes to transfer.
++ * For Transfer Control Instructions, DBC is bit fielded as follows : 
++ */
++/* Bits 20 - 23 should be clear */
++#define DBC_TCI_TRUE          (1 << 19)       /* Jump when true */
++#define DBC_TCI_COMPARE_DATA  (1 << 18)       /* Compare data */
++#define DBC_TCI_COMPARE_PHASE (1 << 17)       /* Compare phase with DCMD field */
++#define DBC_TCI_WAIT_FOR_VALID        (1 << 16)       /* Wait for REQ */
++/* Bits 8 - 15 are reserved on some implementations ? */
++#define DBC_TCI_MASK_MASK     0xff00          /* Mask for data compare */
++#define DBC_TCI_MASK_SHIFT    8
++#define DBC_TCI_DATA_MASK     0xff            /* Data to be compared */ 
++#define DBC_TCI_DATA_SHIFT    0
++
++#define DBC_RWRI_IMMEDIATE_MASK       0xff00          /* Immediate data */
++#define DBC_RWRI_IMMEDIATE_SHIFT 8            /* Amount to shift */
++#define DBC_RWRI_ADDRESS_MASK 0x3f0000        /* Register address */
++#define DBC_RWRI_ADDRESS_SHIFT        16
 +
-+#include "53c700.h"
 +
-+MODULE_AUTHOR("Kars de Jong <jongk@linux-m68k.org>");
-+MODULE_DESCRIPTION("MVME16x NCR53C710 driver");
-+MODULE_LICENSE("GPL");
++/*
++ * DMA command r/w
++ */
++#define DCMD_REG              0x27    
++#define DCMD_TYPE_MASK                0xc0    /* Masks off type */
++#define DCMD_TYPE_BMI         0x00    /* Indicates a Block Move instruction */
++#define DCMD_BMI_IO           0x01    /* I/O, CD, and MSG bits selecting   */
++#define DCMD_BMI_CD           0x02    /* the phase for the block MOVE      */
++#define DCMD_BMI_MSG          0x04    /* instruction                       */
++
++#define DCMD_BMI_OP_MASK      0x18    /* mask for opcode */
++#define DCMD_BMI_OP_MOVE_T    0x00    /* MOVE */
++#define DCMD_BMI_OP_MOVE_I    0x08    /* MOVE Initiator */
++
++#define DCMD_BMI_INDIRECT     0x20    /*  Indirect addressing */
++
++#define DCMD_TYPE_TCI         0x80    /* Indicates a Transfer Control 
++                                         instruction */
++#define DCMD_TCI_IO           0x01    /* I/O, CD, and MSG bits selecting   */
++#define DCMD_TCI_CD           0x02    /* the phase for the block MOVE      */
++#define DCMD_TCI_MSG          0x04    /* instruction                       */
++#define DCMD_TCI_OP_MASK      0x38    /* mask for opcode */
++#define DCMD_TCI_OP_JUMP      0x00    /* JUMP */
++#define DCMD_TCI_OP_CALL      0x08    /* CALL */
++#define DCMD_TCI_OP_RETURN    0x10    /* RETURN */
++#define DCMD_TCI_OP_INT               0x18    /* INT */
++
++#define DCMD_TYPE_RWRI                0x40    /* Indicates I/O or register Read/Write
++                                         instruction */
++#define DCMD_RWRI_OPC_MASK    0x38    /* Opcode mask */
++#define DCMD_RWRI_OPC_WRITE   0x28    /* Write SFBR to register */
++#define DCMD_RWRI_OPC_READ    0x30    /* Read register to SFBR */
++#define DCMD_RWRI_OPC_MODIFY  0x38    /* Modify in place */
++
++#define DCMD_RWRI_OP_MASK     0x07
++#define DCMD_RWRI_OP_MOVE     0x00
++#define DCMD_RWRI_OP_SHL      0x01
++#define DCMD_RWRI_OP_OR               0x02
++#define DCMD_RWRI_OP_XOR      0x03
++#define DCMD_RWRI_OP_AND      0x04
++#define DCMD_RWRI_OP_SHR      0x05
++#define DCMD_RWRI_OP_ADD      0x06
++#define DCMD_RWRI_OP_ADDC     0x07
++
++#define DCMD_TYPE_MMI         0xc0    /* Indicates a Memory Move instruction 
++                                         (three words) */
++
++
++#define DNAD_REG              0x28    /* through 0x2b DMA next address for 
++                                         data */
++#define DSP_REG                       0x2c    /* through 0x2f DMA SCRIPTS pointer rw */
++#define DSPS_REG              0x30    /* through 0x33 DMA SCRIPTS pointer 
++                                         save rw */
++#define DMODE_REG_00          0x34    /* DMA mode rw */
++#define DMODE_00_BL1  0x80    /* Burst length bits */
++#define DMODE_00_BL0  0x40
++#define DMODE_BL_MASK 0xc0
++/* Burst lengths (800) */
++#define DMODE_BL_2    0x00    /* 2 transfer */
++#define DMODE_BL_4    0x40    /* 4 transfers */
++#define DMODE_BL_8    0x80    /* 8 transfers */
++#define DMODE_BL_16   0xc0    /* 16 transfers */
++
++#define DMODE_10_BL_1 0x00    /* 1 transfer */
++#define DMODE_10_BL_2 0x40    /* 2 transfers */
++#define DMODE_10_BL_4 0x80    /* 4 transfers */
++#define DMODE_10_BL_8 0xc0    /* 8 transfers */
++#define DMODE_10_FC2  0x20    /* Driven to FC2 pin */
++#define DMODE_10_FC1  0x10    /* Driven to FC1 pin */
++#define DMODE_710_PD  0x08    /* Program/data on FC0 pin */
++#define DMODE_710_UO  0x02    /* User prog. output */
++
++#define DMODE_700_BW16        0x20    /* Host buswidth = 16 */
++#define DMODE_700_286 0x10    /* 286 mode */
++#define DMODE_700_IOM 0x08    /* Transfer to IO port */
++#define DMODE_700_FAM 0x04    /* Fixed address mode */
++#define DMODE_700_PIPE        0x02    /* Pipeline mode disables 
++                                       * automatic fetch / exec 
++                                       */
++#define DMODE_MAN     0x01            /* Manual start mode, 
++                                       * requires a 1 to be written
++                                       * to the start DMA bit in the DCNTL
++                                       * register to run scripts 
++                                       */
 +
-+static struct scsi_host_template mvme16x_scsi_driver_template = {
-+      .name                   = "MVME16x NCR53c710 SCSI",
-+      .proc_name              = "MVME16x",
-+      .this_id                = 7,
-+      .module                 = THIS_MODULE,
++#define DMODE_700_SAVE ( DMODE_00_BL_MASK | DMODE_00_BW16 | DMODE_00_286 )
++
++/* NCR53c800 series only */
++#define SCRATCHA_REG_800      0x34    /* through 0x37 Scratch A rw */
++/* NCR53c710 only */
++#define SCRATCHB_REG_10               0x34    /* through 0x37 scratch B rw */
++
++#define DMODE_REG_10          0x38    /* DMA mode rw, NCR53c710 and newer */
++#define DMODE_800_SIOM                0x20    /* Source IO = 1 */
++#define DMODE_800_DIOM                0x10    /* Destination IO = 1 */
++#define DMODE_800_ERL         0x08    /* Enable Read Line */
++
++/* 35-38 are reserved on 700 and 700-66 series chips */
++#define DIEN_REG              0x39    /* DMA interrupt enable rw */
++/* 0x80, 0x40, and 0x20 are reserved on 700-series chips */
++#define DIEN_800_MDPE         0x40    /* Master data parity error */
++#define DIEN_800_BF           0x20    /* BUS fault */
++#define DIEN_700_BF           0x20    /* BUS fault */
++#define DIEN_ABRT             0x10    /* Enable aborted interrupt */
++#define DIEN_SSI              0x08    /* Enable single step interrupt */
++#define DIEN_SIR              0x04    /* Enable SCRIPTS INT command 
++                                       * interrupt
++                                       */
++/* 0x02 is reserved on 800 series chips */
++#define DIEN_700_WTD          0x02    /* Enable watchdog timeout interrupt */
++#define DIEN_700_OPC          0x01    /* Enable illegal instruction 
++                                       * interrupt 
++                                       */
++#define DIEN_800_IID          0x01    /*  Same meaning, different name */ 
++
++/*
++ * DMA watchdog timer rw
++ * set in 16 CLK input periods.
++ */
++#define DWT_REG                       0x3a
++
++/* DMA control rw */
++#define DCNTL_REG             0x3b
++#define DCNTL_700_CF1         0x80    /* Clock divisor bits */
++#define DCNTL_700_CF0         0x40
++#define DCNTL_700_CF_MASK     0xc0
++/* Clock divisors                        Divisor SCLK range (MHZ) */
++#define DCNTL_700_CF_2                0x00    /* 2.0     37.51-50.00 */
++#define DCNTL_700_CF_1_5      0x40    /* 1.5     25.01-37.50 */
++#define DCNTL_700_CF_1                0x80    /* 1.0     16.67-25.00 */
++#define DCNTL_700_CF_3                0xc0    /* 3.0     50.01-66.67 (53c700-66) */
++
++#define DCNTL_700_S16         0x20    /* Load scripts 16 bits at a time */
++#define DCNTL_SSM             0x10    /* Single step mode */
++#define DCNTL_700_LLM         0x08    /* Low level mode, can only be set 
++                                       * after selection */
++#define DCNTL_800_IRQM                0x08    /* Totem pole IRQ pin */
++#define DCNTL_STD             0x04    /* Start DMA / SCRIPTS */
++/* 0x02 is reserved */
++#define DCNTL_00_RST          0x01    /* Software reset, resets everything
++                                       * but 286 mode bit  in DMODE. On the
++                                       * NCR53c710, this bit moved to CTEST8
++                                       */
++#define DCNTL_10_COM          0x01    /* 700 software compatibility mode */
++#define DCNTL_10_EA           0x20    /* Enable Ack - needed for MVME16x */
++
++#define DCNTL_700_SAVE ( DCNTL_CF_MASK | DCNTL_S16)
++
++
++/* NCR53c700-66 only */
++#define SCRATCHB_REG_00               0x3c    /* through 0x3f scratch b rw */
++#define SCRATCHB_REG_800      0x5c    /* through 0x5f scratch b rw */
++/* NCR53c710 only */
++#define ADDER_REG_10          0x3c    /* Adder, NCR53c710 only */
++
++#define SIEN1_REG_800         0x41
++#define SIEN1_800_STO         0x04    /* selection/reselection timeout */
++#define SIEN1_800_GEN         0x02    /* general purpose timer */
++#define SIEN1_800_HTH         0x01    /* handshake to handshake */
++
++#define SIST1_REG_800         0x43
++#define SIST1_800_STO         0x04    /* selection/reselection timeout */
++#define SIST1_800_GEN         0x02    /* general purpose timer */
++#define SIST1_800_HTH         0x01    /* handshake to handshake */
++
++#define SLPAR_REG_800         0x44    /* Parity */
++
++#define MACNTL_REG_800                0x46    /* Memory access control */
++#define MACNTL_800_TYP3               0x80
++#define MACNTL_800_TYP2               0x40
++#define MACNTL_800_TYP1               0x20
++#define MACNTL_800_TYP0               0x10
++#define MACNTL_800_DWR                0x08
++#define MACNTL_800_DRD                0x04
++#define MACNTL_800_PSCPT      0x02
++#define MACNTL_800_SCPTS      0x01
++
++#define GPCNTL_REG_800                0x47    /* General Purpose Pin Control */
++
++/* Timeouts are expressed such that 0=off, 1=100us, doubling after that */
++#define STIME0_REG_800                0x48    /* SCSI Timer Register 0 */
++#define STIME0_800_HTH_MASK   0xf0    /* Handshake to Handshake timeout */
++#define STIME0_800_HTH_SHIFT  4
++#define STIME0_800_SEL_MASK   0x0f    /* Selection timeout */
++#define STIME0_800_SEL_SHIFT  0
++
++#define STIME1_REG_800                0x49
++#define STIME1_800_GEN_MASK   0x0f    /* General purpose timer */
++
++#define RESPID_REG_800                0x4a    /* Response ID, bit fielded.  8
++                                         bits on narrow chips, 16 on WIDE */
++
++#define STEST0_REG_800                0x4c    
++#define STEST0_800_SLT                0x08    /* Selection response logic test */
++#define STEST0_800_ART                0x04    /* Arbitration priority encoder test */
++#define STEST0_800_SOZ                0x02    /* Synchronous offset zero */
++#define STEST0_800_SOM                0x01    /* Synchronous offset maximum */
++
++#define STEST1_REG_800                0x4d
++#define STEST1_800_SCLK               0x80    /* Disable SCSI clock */
++
++#define STEST2_REG_800                0x4e    
++#define STEST2_800_SCE                0x80    /* Enable SOCL/SODL */
++#define STEST2_800_ROF                0x40    /* Reset SCSI sync offset */
++#define STEST2_800_SLB                0x10    /* Enable SCSI loopback mode */
++#define STEST2_800_SZM                0x08    /* SCSI high impedance mode */
++#define STEST2_800_EXT                0x02    /* Extend REQ/ACK filter 30 to 60ns */
++#define STEST2_800_LOW                0x01    /* SCSI low level mode */
++
++#define STEST3_REG_800                0x4f     
++#define STEST3_800_TE         0x80    /* Enable active negation */
++#define STEST3_800_STR                0x40    /* SCSI FIFO test read */
++#define STEST3_800_HSC                0x20    /* Halt SCSI clock */
++#define STEST3_800_DSI                0x10    /* Disable single initiator response */
++#define STEST3_800_TTM                0x04    /* Time test mode */
++#define STEST3_800_CSF                0x02    /* Clear SCSI FIFO */
++#define STEST3_800_STW                0x01    /* SCSI FIFO test write */
++
++#define OPTION_PARITY                 0x1     /* Enable parity checking */
++#define OPTION_TAGGED_QUEUE   0x2     /* Enable SCSI-II tagged queuing */
++#define OPTION_700            0x8     /* Always run NCR53c700 scripts */
++#define OPTION_INTFLY         0x10    /* Use INTFLY interrupts */
++#define OPTION_DEBUG_INTR     0x20    /* Debug interrupts */
++#define OPTION_DEBUG_INIT_ONLY        0x40    /* Run initialization code and 
++                                         simple test code, return
++                                         DID_NO_CONNECT if any SCSI
++                                         commands are attempted. */
++#define OPTION_DEBUG_READ_ONLY        0x80    /* Return DID_ERROR if any 
++                                         SCSI write is attempted */
++#define OPTION_DEBUG_TRACE    0x100   /* Animated trace mode, print 
++                                         each address and instruction 
++                                         executed to debug buffer. */
++#define OPTION_DEBUG_SINGLE   0x200   /* stop after executing one 
++                                         instruction */
++#define OPTION_SYNCHRONOUS    0x400   /* Enable sync SCSI.  */
++#define OPTION_MEMORY_MAPPED  0x800   /* NCR registers have valid 
++                                         memory mapping */
++#define OPTION_IO_MAPPED      0x1000  /* NCR registers have valid
++                                           I/O mapping */
++#define OPTION_DEBUG_PROBE_ONLY       0x2000  /* Probe only, don't even init */
++#define OPTION_DEBUG_TESTS_ONLY       0x4000  /* Probe, init, run selected tests */
++#define OPTION_DEBUG_TEST0    0x08000 /* Run test 0 */
++#define OPTION_DEBUG_TEST1    0x10000 /* Run test 1 */
++#define OPTION_DEBUG_TEST2    0x20000 /* Run test 2 */
++#define OPTION_DEBUG_DUMP     0x40000 /* Dump commands */
++#define OPTION_DEBUG_TARGET_LIMIT 0x80000 /* Only talk to target+luns specified */
++#define OPTION_DEBUG_NCOMMANDS_LIMIT 0x100000 /* Limit the number of commands */
++#define OPTION_DEBUG_SCRIPT 0x200000 /* Print when checkpoints are passed */
++#define OPTION_DEBUG_FIXUP 0x400000 /* print fixup values */
++#define OPTION_DEBUG_DSA 0x800000
++#define OPTION_DEBUG_CORRUPTION       0x1000000       /* Detect script corruption */
++#define OPTION_DEBUG_SDTR       0x2000000     /* Debug SDTR problem */
++#define OPTION_DEBUG_MISMATCH         0x4000000       /* Debug phase mismatches */
++#define OPTION_DISCONNECT     0x8000000       /* Allow disconnect */
++#define OPTION_DEBUG_DISCONNECT 0x10000000    
++#define OPTION_ALWAYS_SYNCHRONOUS 0x20000000  /* Negotiate sync. transfers
++                                                 on power up */
++#define OPTION_DEBUG_QUEUES   0x80000000      
++#define OPTION_DEBUG_ALLOCATION 0x100000000LL
++#define OPTION_DEBUG_SYNCHRONOUS 0x200000000LL        /* Sanity check SXFER and 
++                                                 SCNTL3 registers */
++#define OPTION_NO_ASYNC       0x400000000LL           /* Don't automagically send
++                                                 SDTR for async transfers when
++                                                 we haven't been told to do
++                                                 a synchronous transfer. */
++#define OPTION_NO_PRINT_RACE 0x800000000LL    /* Don't print message when
++                                                 the reselect/WAIT DISCONNECT
++                                                 race condition hits */
++#if !defined(PERM_OPTIONS)
++#define PERM_OPTIONS 0
++#endif
++                              
++/*
++ * Some data which is accessed by the NCR chip must be 4-byte aligned.
++ * For some hosts the default is less than that (eg. 68K uses 2-byte).
++ * Alignment has only been forced where it is important; also if one
++ * 32 bit structure field is aligned then it is assumed that following
++ * 32 bit fields are also aligned.  Take care when adding fields
++ * which are other than 32 bit.
++ */
++
++struct NCR53c7x0_synchronous {
++    u32 select_indirect                       /* Value used for indirect selection */
++      __attribute__ ((aligned (4)));
++    u32 sscf_710;                     /* Used to set SSCF bits for 710 */
++    u32 script[8];                    /* Size ?? Script used when target is 
++                                              reselected */
++    unsigned char synchronous_want[5];        /* Per target desired SDTR */
++/* 
++ * Set_synchronous programs these, select_indirect and current settings after
++ * int_debug_should show a match.
++ */
++    unsigned char sxfer_sanity, scntl3_sanity;
 +};
 +
-+static struct platform_device *mvme16x_scsi_device;
++#define CMD_FLAG_SDTR                 1       /* Initiating synchronous 
++                                         transfer negotiation */
++#define CMD_FLAG_WDTR         2       /* Initiating wide transfer
++                                         negotiation */
++#define CMD_FLAG_DID_SDTR     4       /* did SDTR */
++#define CMD_FLAG_DID_WDTR     8       /* did WDTR */
 +
-+static __devinit int
-+mvme16x_probe(struct device *dev)
-+{
-+      struct Scsi_Host * host = NULL;
-+      struct NCR_700_Host_Parameters *hostdata;
++struct NCR53c7x0_table_indirect {
++    u32 count;
++    void *address;
++};
 +
-+      if (!MACH_IS_MVME16x)
-+              goto out;
++enum ncr_event { 
++    EVENT_NONE = 0,
++/* 
++ * Order is IMPORTANT, since these must correspond to the event interrupts
++ * in 53c7,8xx.scr 
++ */
++
++    EVENT_ISSUE_QUEUE = 0x5000000,    /* 0 Command was added to issue queue */
++    EVENT_START_QUEUE,                        /* 1 Command moved to start queue */
++    EVENT_SELECT,                     /* 2 Command completed selection */
++    EVENT_DISCONNECT,                 /* 3 Command disconnected */
++    EVENT_RESELECT,                   /* 4 Command reselected */
++    EVENT_COMPLETE,                   /* 5 Command completed */
++    EVENT_IDLE,                               /* 6 */
++    EVENT_SELECT_FAILED,              /* 7 */
++    EVENT_BEFORE_SELECT,              /* 8 */
++    EVENT_RESELECT_FAILED             /* 9 */
++};
 +
-+      if (mvme16x_config & MVME16x_CONFIG_NO_SCSICHIP) {
-+              printk(KERN_INFO "mvme16x-scsi: detection disabled, "
-+                               "SCSI chip not present\n");
-+              goto out;
-+      }
++struct NCR53c7x0_event {
++    enum ncr_event event;     /* What type of event */
++    unsigned char target;
++    unsigned char lun;
++    struct timeval time;      
++    u32 *dsa;                 /* What's in the DSA register now (virt) */
++/* 
++ * A few things from that SCSI pid so we know what happened after 
++ * the Scsi_Cmnd structure in question may have disappeared.
++ */
++    unsigned long pid;                /* The SCSI PID which caused this 
++                                 event */
++    unsigned char cmnd[12];
++};
 +
-+      hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
-+      if (hostdata == NULL) {
-+              printk(KERN_ERR "mvme16x-scsi: "
-+                              "Failed to allocate host data\n");
-+              goto out;
-+      }
-+      memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
++/*
++ * Things in the NCR53c7x0_cmd structure are split into two parts :
++ *
++ * 1.  A fixed portion, for things which are not accessed directly by static NCR
++ *    code (ie, are referenced only by the Linux side of the driver,
++ *    or only by dynamically generated code).  
++ *
++ * 2.  The DSA portion, for things which are accessed directly by static NCR
++ *    code.
++ *
++ * This is a little ugly, but it 
++ * 1.  Avoids conflicts between the NCR code's picture of the structure, and 
++ *    Linux code's idea of what it looks like.
++ *
++ * 2.  Minimizes the pain in the Linux side of the code needed 
++ *    to calculate real dsa locations for things, etc.
++ * 
++ */
 +
-+      /* Fill in the required pieces of hostdata */
-+      hostdata->base = (void __iomem *)0xfff47000UL;
-+      hostdata->clock = 50;   /* XXX - depends on the CPU clock! */
-+      hostdata->chip710 = 1;
-+      hostdata->dmode_extra = DMODE_FC2;
-+      hostdata->dcntl_extra = EA_710;
-+      hostdata->ctest7_extra = CTEST7_TT1;
++struct NCR53c7x0_cmd {
++    void *real;                               /* Real, unaligned address for
++                                         free function */
++    void (* free)(void *, int);               /* Command to deallocate; NULL
++                                         for structures allocated with
++                                         scsi_register, etc. */
++    Scsi_Cmnd *cmd;                   /* Associated Scsi_Cmnd 
++                                         structure, Scsi_Cmnd points
++                                         at NCR53c7x0_cmd using 
++                                         host_scribble structure */
 +
-+      /* and register the chip */
-+      host = NCR_700_detect(&mvme16x_scsi_driver_template, hostdata, dev);
-+      if (!host) {
-+              printk(KERN_ERR "mvme16x-scsi: No host detected; "
-+                              "board configuration problem?\n");
-+              goto out_free;
-+      }
-+      host->this_id = 7;
-+      host->base = 0xfff47000UL;
-+      host->irq = MVME16x_IRQ_SCSI;
-+      if (request_irq(host->irq, NCR_700_intr, 0, "mvme16x-scsi", host)) {
-+              printk(KERN_ERR "mvme16x-scsi: request_irq failed\n");
-+              goto out_put_host;
-+      }
++    int size;                         /* scsi_malloc'd size of this 
++                                         structure */
 +
-+      /* Enable scsi chip ints */
-+      {
-+              volatile unsigned long v;
++    int flags;                                /* CMD_* flags */
 +
-+              /* Enable scsi interrupts at level 4 in PCCchip2 */
-+              v = in_be32(0xfff4202c);
-+              v = (v & ~0xff) | 0x10 | 4;
-+              out_be32(0xfff4202c, v);
-+      }
++    unsigned char      cmnd[12];      /* CDB, copied from Scsi_Cmnd */
++    int                result;                /* Copy to Scsi_Cmnd when done */
 +
-+      scsi_scan_host(host);
++    struct {                          /* Private non-cached bounce buffer */
++        unsigned char buf[256];
++      u32           addr;
++        u32           len;
++    } bounce;
 +
-+      return 0;
++/*
++ * SDTR and WIDE messages are an either/or affair
++ * in this message, since we will go into message out and send
++ * _the whole mess_ without dropping out of message out to 
++ * let the target go into message in after sending the first 
++ * message.
++ */
 +
-+ out_put_host:
-+      scsi_host_put(host);
-+ out_free:
-+      kfree(hostdata);
-+ out:
-+      return -ENODEV;
-+}
++    unsigned char select[11];         /* Select message, includes
++                                         IDENTIFY
++                                         (optional) QUEUE TAG
++                                         (optional) SDTR or WDTR
++                                       */
 +
-+static __devexit int
-+mvme16x_device_remove(struct device *dev)
-+{
-+      struct Scsi_Host *host = dev_to_shost(dev);
-+      struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
 +
-+      /* Disable scsi chip ints */
-+      {
-+              volatile unsigned long v;
++    volatile struct NCR53c7x0_cmd *next; /* Linux maintained lists (free,
++                                          running, eventually finished */
++                                       
 +
-+              v = in_be32(0xfff4202c);
-+              v &= ~0x10;
-+              out_be32(0xfff4202c, v);
-+      }
-+      scsi_remove_host(host);
-+      NCR_700_release(host);
-+      kfree(hostdata);
-+      free_irq(host->irq, host);
++    u32 *data_transfer_start;         /* Start of data transfer routines */
++    u32 *data_transfer_end;           /* Address after end of data transfer o
++                                         routines */
++/* 
++ * The following three fields were moved from the DSA proper to here
++ * since only dynamically generated NCR code refers to them, meaning
++ * we don't need dsa_* absolutes, and it is simpler to let the 
++ * host code refer to them directly.
++ */
 +
-+      return 0;
-+}
++/* 
++ * HARD CODED : residual and saved_residual need to agree with the sizes
++ * used in NCR53c7,8xx.scr.  
++ * 
++ * FIXME: we want to consider the case where we have odd-length 
++ *    scatter/gather buffers and a WIDE transfer, in which case 
++ *    we'll need to use the CHAIN MOVE instruction.  Ick.
++ */
++    u32 residual[6] __attribute__ ((aligned (4)));
++                                      /* Residual data transfer which
++                                         allows pointer code to work
++                                         right.
++
++                                          [0-1] : Conditional call to 
++                                              appropriate other transfer 
++                                              routine.
++                                          [2-3] : Residual block transfer
++                                              instruction.
++                                          [4-5] : Jump to instruction
++                                              after splice.
++                                       */
++    u32 saved_residual[6];            /* Copy of old residual, so we 
++                                         can get another partial 
++                                         transfer and still recover 
++                                       */
++              
++    u32 saved_data_pointer;           /* Saved data pointer */
++
++    u32 dsa_next_addr;                        /* _Address_ of dsa_next field  
++                                         in this dsa for RISCy 
++                                         style constant. */
++
++    u32 dsa_addr;                     /* Address of dsa; RISCy style
++                                         constant */
++
++    u32 dsa[0];                               /* Variable length (depending
++                                         on host type, number of scatter /
++                                         gather buffers, etc).  */
++};
 +
-+static struct device_driver mvme16x_scsi_driver = {
-+      .name   = "mvme16x-scsi",
-+      .bus    = &platform_bus_type,
-+      .probe  = mvme16x_probe,
-+      .remove = __devexit_p(mvme16x_device_remove),
++struct NCR53c7x0_break {
++    u32 *address, old_instruction[2];
++    struct NCR53c7x0_break *next;
++    unsigned char old_size;           /* Size of old instruction */
 +};
 +
-+static int __init mvme16x_scsi_init(void)
-+{
-+      int err;
++/* Indicates that the NCR is not executing code */
++#define STATE_HALTED  0               
++/* 
++ * Indicates that the NCR is executing the wait for select / reselect 
++ * script.  Only used when running NCR53c700 compatible scripts, only 
++ * state during which an ABORT is _not_ considered an error condition.
++ */
++#define STATE_WAITING 1               
++/* Indicates that the NCR is executing other code. */
++#define STATE_RUNNING 2               
++/* 
++ * Indicates that the NCR was being aborted.
++ */
++#define STATE_ABORTING        3
++/* Indicates that the NCR was successfully aborted. */
++#define STATE_ABORTED 4
++/* Indicates that the NCR has been disabled due to a fatal error */
++#define STATE_DISABLED 5
 +
-+      err = driver_register(&mvme16x_scsi_driver);
-+      if (err)
-+              return err;
++/* 
++ * Where knowledge of SCSI SCRIPT(tm) specified values are needed 
++ * in an interrupt handler, an interrupt handler exists for each 
++ * different SCSI script so we don't have name space problems.
++ * 
++ * Return values of these handlers are as follows : 
++ */
++#define SPECIFIC_INT_NOTHING  0       /* don't even restart */
++#define SPECIFIC_INT_RESTART  1       /* restart at the next instruction */
++#define SPECIFIC_INT_ABORT    2       /* recoverable error, abort cmd */
++#define SPECIFIC_INT_PANIC    3       /* unrecoverable error, panic */
++#define SPECIFIC_INT_DONE     4       /* normal command completion */
++#define SPECIFIC_INT_BREAK    5       /* break point encountered */
++
++struct NCR53c7x0_hostdata {
++    int size;                         /* Size of entire Scsi_Host
++                                         structure */
++    int board;                                /* set to board type, useful if 
++                                         we have host specific things,
++                                         ie, a general purpose I/O 
++                                         bit is being used to enable
++                                         termination, etc. */
++
++    int chip;                         /* set to chip type; 700-66 is
++                                         700-66, rest are last three
++                                         digits of part number */
++
++    char valid_ids[8];                        /* Valid SCSI ID's for adapter */
++
++    u32 *dsp;                         /* dsp to restart with after
++                                         all stacked interrupts are
++                                         handled. */
++
++    unsigned dsp_changed:1;           /* Has dsp changed within this
++                                         set of stacked interrupts ? */
++
++    unsigned char dstat;              /* Most recent value of dstat */
++    unsigned dstat_valid:1;
++
++    unsigned expecting_iid:1;         /* Expect IID interrupt */
++    unsigned expecting_sto:1;         /* Expect STO interrupt */
++    
++    /* 
++     * The code stays cleaner if we use variables with function
++     * pointers and offsets that are unique for the different
++     * scripts rather than having a slew of switch(hostdata->chip) 
++     * statements.
++     * 
++     * It also means that the #defines from the SCSI SCRIPTS(tm)
++     * don't have to be visible outside of the script-specific
++     * instructions, preventing name space pollution.
++     */
++
++    void (* init_fixup)(struct Scsi_Host *host);
++    void (* init_save_regs)(struct Scsi_Host *host);
++    void (* dsa_fixup)(struct NCR53c7x0_cmd *cmd);
++    void (* soft_reset)(struct Scsi_Host *host);
++    int (* run_tests)(struct Scsi_Host *host);
++
++    /*
++     * Called when DSTAT_SIR is set, indicating an interrupt generated
++     * by the INT instruction, where values are unique for each SCSI
++     * script.  Should return one of the SPEC_* values.
++     */
++
++    int (* dstat_sir_intr)(struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);
++
++    int dsa_len; /* Size of DSA structure */
++
++    /*
++     * Location of DSA fields for the SCSI SCRIPT corresponding to this 
++     * chip.  
++     */
++
++    s32 dsa_start;                    
++    s32 dsa_end;                      
++    s32 dsa_next;
++    s32 dsa_prev;
++    s32 dsa_cmnd;
++    s32 dsa_select;
++    s32 dsa_msgout;
++    s32 dsa_cmdout;
++    s32 dsa_dataout;
++    s32 dsa_datain;
++    s32 dsa_msgin;
++    s32 dsa_msgout_other;
++    s32 dsa_write_sync;
++    s32 dsa_write_resume;
++    s32 dsa_check_reselect;
++    s32 dsa_status;
++    s32 dsa_saved_pointer;
++    s32 dsa_jump_dest;
++
++    /* 
++     * Important entry points that generic fixup code needs
++     * to know about, fixed up.
++     */
++
++    s32 E_accept_message;
++    s32 E_command_complete;           
++    s32 E_data_transfer;
++    s32 E_dsa_code_template;
++    s32 E_dsa_code_template_end;
++    s32 E_end_data_transfer;
++    s32 E_msg_in;
++    s32 E_initiator_abort;
++    s32 E_other_transfer;
++    s32 E_other_in;
++    s32 E_other_out;
++    s32 E_target_abort;
++    s32 E_debug_break;        
++    s32 E_reject_message;
++    s32 E_respond_message;
++    s32 E_select;
++    s32 E_select_msgout;
++    s32 E_test_0;
++    s32 E_test_1;
++    s32 E_test_2;
++    s32 E_test_3;
++    s32 E_dsa_zero;
++    s32 E_cmdout_cmdout;
++    s32 E_wait_reselect;
++    s32 E_dsa_code_begin;
++
++    long long options;                        /* Bitfielded set of options enabled */
++    volatile u32 test_completed;      /* Test completed */
++    int test_running;                 /* Test currently running */
++    s32 test_source
++      __attribute__ ((aligned (4)));
++    volatile s32 test_dest;
++
++    volatile int state;                       /* state of driver, only used for 
++                                         OPTION_700 */
++
++    unsigned char  dmode;             /* 
++                                       * set to the address of the DMODE 
++                                       * register for this chip.
++                                       */
++    unsigned char istat;              /* 
++                                       * set to the address of the ISTAT 
++                                       * register for this chip.
++                                       */
++  
++    int scsi_clock;                   /* 
++                                       * SCSI clock in HZ. 0 may be used 
++                                       * for unknown, although this will
++                                       * disable synchronous negotiation.
++                                       */
 +
-+      mvme16x_scsi_device = platform_device_register_simple("mvme16x-scsi",
-+                                                            -1, NULL, 0);
-+      if (IS_ERR(mvme16x_scsi_device)) {
-+              driver_unregister(&mvme16x_scsi_driver);
-+              return PTR_ERR(mvme16x_scsi_device);
-+      }
++    volatile int intrs;                       /* Number of interrupts */
++    volatile int resets;              /* Number of SCSI resets */
++    unsigned char saved_dmode;        
++    unsigned char saved_ctest4;
++    unsigned char saved_ctest7;
++    unsigned char saved_dcntl;
++    unsigned char saved_scntl3;
++
++    unsigned char this_id_mask;
++
++    /* Debugger information */
++    struct NCR53c7x0_break *breakpoints, /* Linked list of all break points */
++      *breakpoint_current;            /* Current breakpoint being stepped 
++                                         through, NULL if we are running 
++                                         normally. */
++#ifdef NCR_DEBUG
++    int debug_size;                   /* Size of debug buffer */
++    volatile int debug_count;         /* Current data count */
++    volatile char *debug_buf;         /* Output ring buffer */
++    volatile char *debug_write;               /* Current write pointer */
++    volatile char *debug_read;                /* Current read pointer */
++#endif /* def NCR_DEBUG */
++
++    /* XXX - primitive debugging junk, remove when working ? */
++    int debug_print_limit;            /* Number of commands to print
++                                         out exhaustive debugging
++                                         information for if 
++                                         OPTION_DEBUG_DUMP is set */ 
++
++    unsigned char debug_lun_limit[16];        /* If OPTION_DEBUG_TARGET_LIMIT
++                                         set, puke if commands are sent
++                                         to other target/lun combinations */
++
++    int debug_count_limit;            /* Number of commands to execute
++                                         before puking to limit debugging 
++                                         output */
++                                  
++
++    volatile unsigned idle:1;                 /* set to 1 if idle */
++
++    /* 
++     * Table of synchronous+wide transfer parameters set on a per-target
++     * basis.
++     */
++    
++    volatile struct NCR53c7x0_synchronous sync[16]
++      __attribute__ ((aligned (4)));
++
++    volatile Scsi_Cmnd *issue_queue
++      __attribute__ ((aligned (4)));
++                                              /* waiting to be issued by
++                                                 Linux driver */
++    volatile struct NCR53c7x0_cmd *running_list;      
++                                              /* commands running, maintained
++                                                 by Linux driver */
++
++    volatile struct NCR53c7x0_cmd *ncrcurrent;        /* currently connected 
++                                                 nexus, ONLY valid for
++                                                 NCR53c700/NCR53c700-66
++                                               */
 +
-+      return 0;
-+}
++    volatile struct NCR53c7x0_cmd *spare;     /* pointer to spare,
++                                                 allocated at probe time,
++                                                 which we can use for 
++                                                 initialization */
++    volatile struct NCR53c7x0_cmd *free;
++    int max_cmd_size;                         /* Maximum size of NCR53c7x0_cmd
++                                                 based on number of 
++                                                 scatter/gather segments, etc.
++                                                 */
++    volatile int num_cmds;                    /* Number of commands 
++                                                 allocated */
++    volatile int extra_allocate;
++    volatile unsigned char cmd_allocated[16]; /* Have we allocated commands
++                                                 for this target yet?  If not,
++                                                 do so ASAP */
++    volatile unsigned char busy[16][8];       /* number of commands 
++                                                 executing on each target
++                                               */
++    /* 
++     * Eventually, I'll switch to a coroutine for calling 
++     * cmd->done(cmd), etc. so that we can overlap interrupt
++     * processing with this code for maximum performance.
++     */
++    
++    volatile struct NCR53c7x0_cmd *finished_queue;    
++                                              
++    /* Shared variables between SCRIPT and host driver */
++    volatile u32 *schedule
++      __attribute__ ((aligned (4)));          /* Array of JUMPs to dsa_begin
++                                                 routines of various DSAs.  
++                                                 When not in use, replace
++                                                 with jump to next slot */
++
++
++    volatile unsigned char msg_buf[16];               /* buffer for messages
++                                                 other than the command
++                                                 complete message */
++
++    /* Per-target default synchronous and WIDE messages */
++    volatile unsigned char synchronous_want[16][5];
++    volatile unsigned char wide_want[16][4];
++
++    /* Bit fielded set of targets we want to speak synchronously with */ 
++    volatile u16 initiate_sdtr;       
++    /* Bit fielded set of targets we want to speak wide with */
++    volatile u16 initiate_wdtr;
++    /* Bit fielded list of targets we've talked to. */
++    volatile u16 talked_to;
++
++    /* Array of bit-fielded lun lists that we need to request_sense */
++    volatile unsigned char request_sense[16];
++
++    u32 addr_reconnect_dsa_head
++      __attribute__ ((aligned (4)));          /* RISCy style constant,
++                                                 address of following */
++    volatile u32 reconnect_dsa_head;  
++    /* Data identifying nexus we are trying to match during reselection */
++    volatile unsigned char reselected_identify; /* IDENTIFY message */
++    volatile unsigned char reselected_tag;    /* second byte of queue tag 
++                                                 message or 0 */
++
++    /* These were static variables before we moved them */
++
++    s32 NCR53c7xx_zero
++      __attribute__ ((aligned (4)));
++    s32 NCR53c7xx_sink;
++    u32 NOP_insn;
++    char NCR53c7xx_msg_reject;
++    char NCR53c7xx_msg_abort;
++    char NCR53c7xx_msg_nop;
++
++    /*
++     * Following item introduced by RGH to support NCRc710, which is
++     * VERY brain-dead when it come to memory moves
++     */
++
++                        /* DSA save area used only by the NCR chip */
++    volatile unsigned long saved2_dsa
++      __attribute__ ((aligned (4)));
++
++    volatile unsigned long emulated_intfly
++      __attribute__ ((aligned (4)));
++
++    volatile int event_size, event_index;
++    volatile struct NCR53c7x0_event *events;
++
++    /* If we need to generate code to kill off the currently connected 
++       command, this is where we do it. Should have a BMI instruction
++       to source or sink the current data, followed by a JUMP
++       to abort_connected */
++
++    u32 *abort_script;
++
++    int script_count;                         /* Size of script in words */
++    u32 script[0];                            /* Relocated SCSI script */
 +
-+static void __exit mvme16x_scsi_exit(void)
-+{
-+      platform_device_unregister(mvme16x_scsi_device);
-+      driver_unregister(&mvme16x_scsi_driver);
-+}
++};
 +
-+module_init(mvme16x_scsi_init);
-+module_exit(mvme16x_scsi_exit);
-diff -Nurb linux-2.6.22-570/drivers/scsi/nsp32.c linux-2.6.22-590/drivers/scsi/nsp32.c
---- linux-2.6.22-570/drivers/scsi/nsp32.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/nsp32.c      2008-01-02 13:56:37.000000000 -0500
-@@ -49,10 +49,6 @@
- #include <scsi/scsi_host.h>
- #include <scsi/scsi_ioctl.h>
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
--# include <linux/blk.h>
--#endif
--
- #include "nsp32.h"
-@@ -199,17 +195,9 @@
- static void __exit    exit_nsp32  (void);
- /* struct struct scsi_host_template */
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
- static int         nsp32_proc_info   (struct Scsi_Host *, char *, char **, off_t, int, int);
--#else
--static int         nsp32_proc_info   (char *, char **, off_t, int, int, int);
--#endif
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
- static int         nsp32_detect      (struct pci_dev *pdev);
--#else
--static int         nsp32_detect      (struct scsi_host_template *);
--#endif
- static int         nsp32_queuecommand(struct scsi_cmnd *,
-               void (*done)(struct scsi_cmnd *));
- static const char *nsp32_info        (struct Scsi_Host *);
-@@ -296,15 +284,7 @@
-       .eh_abort_handler               = nsp32_eh_abort,
-       .eh_bus_reset_handler           = nsp32_eh_bus_reset,
-       .eh_host_reset_handler          = nsp32_eh_host_reset,
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74))
--      .detect                         = nsp32_detect,
--      .release                        = nsp32_release,
--#endif
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2))
--      .use_new_eh_code                = 1,
--#else
- /*    .highmem_io                     = 1, */
--#endif
- };
- #include "nsp32_io.h"
-@@ -739,7 +719,7 @@
-       command = 0;
-       command |= (TRANSFER_GO | ALL_COUNTER_CLR);
-       if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
--              if (SCpnt->request_bufflen > 0) {
-+              if (scsi_bufflen(SCpnt) > 0) {
-                       command |= BM_START;
-               }
-       } else if (data->trans_method & NSP32_TRANSFER_MMIO) {
-@@ -888,31 +868,28 @@
- static int nsp32_setup_sg_table(struct scsi_cmnd *SCpnt)
- {
-       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
--      struct scatterlist   *sgl;
-+      struct scatterlist *sg;
-       nsp32_sgtable *sgt = data->cur_lunt->sglun->sgt;
-       int num, i;
-       u32_le l;
--      if (SCpnt->request_bufflen == 0) {
--              return TRUE;
--      }
--
-       if (sgt == NULL) {
-               nsp32_dbg(NSP32_DEBUG_SGLIST, "SGT == null");
-               return FALSE;
-       }
--      if (SCpnt->use_sg) {
--              sgl = (struct scatterlist *)SCpnt->request_buffer;
--              num = pci_map_sg(data->Pci, sgl, SCpnt->use_sg,
--                               SCpnt->sc_data_direction);
--              for (i = 0; i < num; i++) {
-+      num = scsi_dma_map(SCpnt);
-+      if (!num)
-+              return TRUE;
-+      else if (num < 0)
-+              return FALSE;
-+      else {
-+              scsi_for_each_sg(SCpnt, sg, num, i) {
-                       /*
-                        * Build nsp32_sglist, substitute sg dma addresses.
-                        */
--                      sgt[i].addr = cpu_to_le32(sg_dma_address(sgl));
--                      sgt[i].len  = cpu_to_le32(sg_dma_len(sgl));
--                      sgl++;
-+                      sgt[i].addr = cpu_to_le32(sg_dma_address(sg));
-+                      sgt[i].len  = cpu_to_le32(sg_dma_len(sg));
-                       if (le32_to_cpu(sgt[i].len) > 0x10000) {
-                               nsp32_msg(KERN_ERR,
-@@ -929,23 +906,6 @@
-               /* set end mark */
-               l = le32_to_cpu(sgt[num-1].len);
-               sgt[num-1].len = cpu_to_le32(l | SGTEND);
--
--      } else {
--              SCpnt->SCp.have_data_in = pci_map_single(data->Pci,
--                      SCpnt->request_buffer, SCpnt->request_bufflen,
--                      SCpnt->sc_data_direction);
--
--              sgt[0].addr = cpu_to_le32(SCpnt->SCp.have_data_in);
--              sgt[0].len  = cpu_to_le32(SCpnt->request_bufflen | SGTEND); /* set end mark */
--
--              if (SCpnt->request_bufflen > 0x10000) {
--                      nsp32_msg(KERN_ERR,
--                                "can't transfer over 64KB at a time, size=0x%lx", SCpnt->request_bufflen);
--                      return FALSE;
--              }
--              nsp32_dbg(NSP32_DEBUG_SGLIST, "single : addr 0x%lx len=0x%lx",
--                        le32_to_cpu(sgt[0].addr),
--                        le32_to_cpu(sgt[0].len ));
-       }
-       return TRUE;
-@@ -962,7 +922,7 @@
-                 "enter. target: 0x%x LUN: 0x%x cmnd: 0x%x cmndlen: 0x%x "
-                 "use_sg: 0x%x reqbuf: 0x%lx reqlen: 0x%x",
-                 SCpnt->device->id, SCpnt->device->lun, SCpnt->cmnd[0], SCpnt->cmd_len,
--                SCpnt->use_sg, SCpnt->request_buffer, SCpnt->request_bufflen);
-+                scsi_sg_count(SCpnt), scsi_sglist(SCpnt), scsi_bufflen(SCpnt));
-       if (data->CurrentSC != NULL) {
-               nsp32_msg(KERN_ERR, "Currentsc != NULL. Cancel this command request");
-@@ -994,10 +954,10 @@
-       data->CurrentSC      = SCpnt;
-       SCpnt->SCp.Status    = CHECK_CONDITION;
-       SCpnt->SCp.Message   = 0;
--      SCpnt->resid         = SCpnt->request_bufflen;
-+      scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
--      SCpnt->SCp.ptr              = (char *) SCpnt->request_buffer;
--      SCpnt->SCp.this_residual    = SCpnt->request_bufflen;
-+      SCpnt->SCp.ptr              = (char *)scsi_sglist(SCpnt);
-+      SCpnt->SCp.this_residual    = scsi_bufflen(SCpnt);
-       SCpnt->SCp.buffer           = NULL;
-       SCpnt->SCp.buffers_residual = 0;
-@@ -1210,13 +1170,9 @@
-       unsigned long flags;
-       int ret;
-       int handled = 0;
--
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
-       struct Scsi_Host *host = data->Host;
++#define SCSI_IRQ_NONE 255
++#define DMA_NONE      255
++#define IRQ_AUTO      254
++#define DMA_AUTO      254
 +
-       spin_lock_irqsave(host->host_lock, flags);
--#else
--      spin_lock_irqsave(&io_request_lock, flags);
--#endif
-       /*
-        * IRQ check, then enable IRQ mask
-@@ -1312,7 +1268,7 @@
-               }
-               if ((auto_stat & DATA_IN_PHASE) &&
--                  (SCpnt->resid > 0) &&
-+                  (scsi_get_resid(SCpnt) > 0) &&
-                   ((nsp32_read2(base, FIFO_REST_CNT) & FIFO_REST_MASK) != 0)) {
-                       printk( "auto+fifo\n");
-                       //nsp32_pio_read(SCpnt);
-@@ -1333,7 +1289,7 @@
-                       nsp32_dbg(NSP32_DEBUG_INTR, "SSACK=0x%lx", 
-                                   nsp32_read4(base, SAVED_SACK_CNT));
--                      SCpnt->resid = 0; /* all data transfered! */
-+                      scsi_set_resid(SCpnt, 0); /* all data transfered! */
-               }
-               /*
-@@ -1480,11 +1436,7 @@
-       nsp32_write2(base, IRQ_CONTROL, 0);
-  out2:
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
-       spin_unlock_irqrestore(host->host_lock, flags);
--#else
--      spin_unlock_irqrestore(&io_request_lock, flags);
--#endif
-       nsp32_dbg(NSP32_DEBUG_INTR, "exit");
-@@ -1499,28 +1451,15 @@
-                       nsp32_dbg(NSP32_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length,  length - (pos - buffer));\
-               } \
-       } while(0)
--static int nsp32_proc_info(
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
--      struct Scsi_Host *host,
--#endif
--      char             *buffer,
--      char            **start,
--      off_t             offset,
--      int               length,
--#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
--      int               hostno,
--#endif
--      int               inout)
++#define BOARD_GENERIC 0
 +
-+static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start,
-+                         off_t offset, int length, int inout)
- {
-       char             *pos = buffer;
-       int               thislength;
-       unsigned long     flags;
-       nsp32_hw_data    *data;
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
-       int               hostno;
--#else
--      struct Scsi_Host *host;
--#endif
-       unsigned int      base;
-       unsigned char     mode_reg;
-       int               id, speed;
-@@ -1531,15 +1470,7 @@
-               return -EINVAL;
-       }
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
-       hostno = host->host_no;
--#else
--      /* search this HBA host */
--      host = scsi_host_hn_get(hostno);
--      if (host == NULL) {
--              return -ESRCH;
--      }
--#endif
-       data = (nsp32_hw_data *)host->hostdata;
-       base = host->io_port;
-@@ -1626,25 +1557,8 @@
-       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
-       unsigned int   base = SCpnt->device->host->io_port;
--      /*
--       * unmap pci
--       */
--      if (SCpnt->request_bufflen == 0) {
--              goto skip;
--      }
--
--      if (SCpnt->use_sg) {
--              pci_unmap_sg(data->Pci,
--                           (struct scatterlist *)SCpnt->request_buffer,
--                           SCpnt->use_sg, SCpnt->sc_data_direction);
--      } else {
--              pci_unmap_single(data->Pci,
--                               (u32)SCpnt->SCp.have_data_in,
--                               SCpnt->request_bufflen,
--                               SCpnt->sc_data_direction);
--      }
-+      scsi_dma_unmap(SCpnt);
-- skip:
-       /*
-        * clear TRANSFERCONTROL_BM_START
-        */
-@@ -1800,7 +1714,7 @@
-               SCpnt->SCp.Message = 0;
-               nsp32_dbg(NSP32_DEBUG_BUSFREE, 
-                         "normal end stat=0x%x resid=0x%x\n",
--                        SCpnt->SCp.Status, SCpnt->resid);
-+                        SCpnt->SCp.Status, scsi_get_resid(SCpnt));
-               SCpnt->result = (DID_OK             << 16) |
-                               (SCpnt->SCp.Message <<  8) |
-                               (SCpnt->SCp.Status  <<  0);
-@@ -1844,7 +1758,7 @@
-       unsigned int          restlen, sentlen;
-       u32_le                len, addr;
--      nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", SCpnt->resid);
-+      nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", scsi_get_resid(SCpnt));
-       /* adjust saved SACK count with 4 byte start address boundary */
-       s_sacklen -= le32_to_cpu(sgt[old_entry].addr) & 3;
-@@ -1888,12 +1802,12 @@
-       return;
-  last:
--      if (SCpnt->resid < sentlen) {
-+      if (scsi_get_resid(SCpnt) < sentlen) {
-               nsp32_msg(KERN_ERR, "resid underflow");
-       }
--      SCpnt->resid -= sentlen;
--      nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", SCpnt->resid);
-+      scsi_set_resid(SCpnt, scsi_get_resid(SCpnt) - sentlen);
-+      nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", scsi_get_resid(SCpnt));
-       /* update hostdata and lun */
-@@ -2022,7 +1936,7 @@
-       transfer = 0;
-       transfer |= (TRANSFER_GO | ALL_COUNTER_CLR);
-       if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
--              if (SCpnt->request_bufflen > 0) {
-+              if (scsi_bufflen(SCpnt) > 0) {
-                       transfer |= BM_START;
-               }
-       } else if (data->trans_method & NSP32_TRANSFER_MMIO) {
-@@ -2674,17 +2588,7 @@
-  *    0x900-0xbff: (map same 0x800-0x8ff I/O port image repeatedly)
-  *    0xc00-0xfff: CardBus status registers
-  */
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
--#define DETECT_OK 0
--#define DETECT_NG 1
--#define PCIDEV    pdev
- static int nsp32_detect(struct pci_dev *pdev)
--#else
--#define DETECT_OK 1
--#define DETECT_NG 0
--#define PCIDEV    (data->Pci)
--static int nsp32_detect(struct scsi_host_template *sht)
--#endif
- {
-       struct Scsi_Host *host; /* registered host structure */
-       struct resource  *res;
-@@ -2697,11 +2601,7 @@
-       /*
-        * register this HBA as SCSI device
-        */
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-       host = scsi_host_alloc(&nsp32_template, sizeof(nsp32_hw_data));
--#else
--      host = scsi_register(sht, sizeof(nsp32_hw_data));
--#endif
-       if (host == NULL) {
-               nsp32_msg (KERN_ERR, "failed to scsi register");
-               goto err;
-@@ -2719,9 +2619,6 @@
-       host->unique_id = data->BaseAddress;
-       host->n_io_port = data->NumAddress;
-       host->base      = (unsigned long)data->MmioAddress;
--#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,63))
--      scsi_set_pci_device(host, PCIDEV);
--#endif
-       data->Host      = host;
-       spin_lock_init(&(data->Lock));
-@@ -2776,7 +2673,7 @@
-       /*
-        * setup DMA 
-        */
--      if (pci_set_dma_mask(PCIDEV, DMA_32BIT_MASK) != 0) {
-+      if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) {
-               nsp32_msg (KERN_ERR, "failed to set PCI DMA mask");
-               goto scsi_unregister;
-       }
-@@ -2784,7 +2681,7 @@
-       /*
-        * allocate autoparam DMA resource.
-        */
--      data->autoparam = pci_alloc_consistent(PCIDEV, sizeof(nsp32_autoparam), &(data->auto_paddr));
-+      data->autoparam = pci_alloc_consistent(pdev, sizeof(nsp32_autoparam), &(data->auto_paddr));
-       if (data->autoparam == NULL) {
-               nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
-               goto scsi_unregister;
-@@ -2793,7 +2690,7 @@
-       /*
-        * allocate scatter-gather DMA resource.
-        */
--      data->sg_list = pci_alloc_consistent(PCIDEV, NSP32_SG_TABLE_SIZE,
-+      data->sg_list = pci_alloc_consistent(pdev, NSP32_SG_TABLE_SIZE,
-                                            &(data->sg_paddr));
-       if (data->sg_list == NULL) {
-               nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
-@@ -2883,16 +2780,14 @@
-               goto free_irq;
-         }
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
--      ret = scsi_add_host(host, &PCIDEV->dev);
-+      ret = scsi_add_host(host, &pdev->dev);
-       if (ret) {
-               nsp32_msg(KERN_ERR, "failed to add scsi host");
-               goto free_region;
-       }
-       scsi_scan_host(host);
--#endif
--      pci_set_drvdata(PCIDEV, host);
--      return DETECT_OK;
-+      pci_set_drvdata(pdev, host);
-+      return 0;
-  free_region:
-       release_region(host->io_port, host->n_io_port);
-@@ -2901,22 +2796,19 @@
-       free_irq(host->irq, data);
-  free_sg_list:
--      pci_free_consistent(PCIDEV, NSP32_SG_TABLE_SIZE,
-+      pci_free_consistent(pdev, NSP32_SG_TABLE_SIZE,
-                           data->sg_list, data->sg_paddr);
-  free_autoparam:
--      pci_free_consistent(PCIDEV, sizeof(nsp32_autoparam),
-+      pci_free_consistent(pdev, sizeof(nsp32_autoparam),
-                           data->autoparam, data->auto_paddr);
-       
-  scsi_unregister:
-       scsi_host_put(host);
-  err:
--      return DETECT_NG;
-+      return 1;
- }
--#undef DETECT_OK
--#undef DETECT_NG
--#undef PCIDEV
- static int nsp32_release(struct Scsi_Host *host)
- {
-@@ -3525,11 +3417,7 @@
-       pci_set_master(pdev);
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-       ret = nsp32_detect(pdev);
--#else
--      ret = scsi_register_host(&nsp32_template);
--#endif
-       nsp32_msg(KERN_INFO, "irq: %i mmio: %p+0x%lx slot: %s model: %s",
-                 pdev->irq,
-@@ -3544,25 +3432,17 @@
- static void __devexit nsp32_remove(struct pci_dev *pdev)
- {
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-       struct Scsi_Host *host = pci_get_drvdata(pdev);
--#endif
-       nsp32_dbg(NSP32_DEBUG_REGISTER, "enter");
--#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-         scsi_remove_host(host);
-       nsp32_release(host);
-       scsi_host_put(host);
--#else
--      scsi_unregister_host(&nsp32_template);  
--#endif
- }
--
--
- static struct pci_driver nsp32_driver = {
-       .name           = "nsp32",
-       .id_table       = nsp32_pci_table,
-diff -Nurb linux-2.6.22-570/drivers/scsi/pcmcia/sym53c500_cs.c linux-2.6.22-590/drivers/scsi/pcmcia/sym53c500_cs.c
---- linux-2.6.22-570/drivers/scsi/pcmcia/sym53c500_cs.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/pcmcia/sym53c500_cs.c        2008-01-02 13:56:37.000000000 -0500
-@@ -370,8 +370,6 @@
-       DEB(unsigned char seq_reg;)
-       unsigned char status, int_reg;
-       unsigned char pio_status;
--      struct scatterlist *sglist;
--      unsigned int sgcount;
-       int port_base = dev->io_port;
-       struct sym53c500_data *data =
-           (struct sym53c500_data *)dev->hostdata;
-@@ -434,20 +432,19 @@
-       switch (status & 0x07) {        /* scsi phase */
-       case 0x00:                      /* DATA-OUT */
-               if (int_reg & 0x10) {   /* Target requesting info transfer */
-+                      struct scatterlist *sg;
-+                      int i;
++#define NCR53c7x0_insn_size(insn)                                     \
++    (((insn) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI ? 3 : 2)
++    
++
++#define NCR53c7x0_local_declare()                                     \
++    volatile unsigned char *NCR53c7x0_address_memory;                 \
++    unsigned int NCR53c7x0_address_io;                                        \
++    int NCR53c7x0_memory_mapped
++
++#define NCR53c7x0_local_setup(host)                                   \
++    NCR53c7x0_address_memory = (void *) (host)->base;                 \
++    NCR53c7x0_address_io = (unsigned int) (host)->io_port;            \
++    NCR53c7x0_memory_mapped = ((struct NCR53c7x0_hostdata *)          \
++      host->hostdata[0])-> options & OPTION_MEMORY_MAPPED 
++
++#ifdef BIG_ENDIAN
++/* These could be more efficient, given that we are always memory mapped,
++ * but they don't give the same problems as the write macros, so leave
++ * them. */
++#ifdef __mc68000__
++#define NCR53c7x0_read8(address)                                      \
++    ((unsigned int)raw_inb((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) )
++
++#define NCR53c7x0_read16(address)                                     \
++    ((unsigned int)raw_inw((u32)NCR53c7x0_address_memory + ((u32)(address)^2)))
++#else
++#define NCR53c7x0_read8(address)                                      \
++    (NCR53c7x0_memory_mapped ?                                                \
++      (unsigned int)readb((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) :       \
++      inb(NCR53c7x0_address_io + (address)))
++
++#define NCR53c7x0_read16(address)                                     \
++    (NCR53c7x0_memory_mapped ?                                                \
++      (unsigned int)readw((u32)NCR53c7x0_address_memory + ((u32)(address)^2)) :       \
++      inw(NCR53c7x0_address_io + (address)))
++#endif /* mc68000 */
++#else
++#define NCR53c7x0_read8(address)                                      \
++    (NCR53c7x0_memory_mapped ?                                                \
++      (unsigned int)readb((u32)NCR53c7x0_address_memory + (u32)(address)) :   \
++      inb(NCR53c7x0_address_io + (address)))
++
++#define NCR53c7x0_read16(address)                                     \
++    (NCR53c7x0_memory_mapped ?                                                \
++      (unsigned int)readw((u32)NCR53c7x0_address_memory + (u32)(address)) :   \
++      inw(NCR53c7x0_address_io + (address)))
++#endif
++
++#ifdef __mc68000__
++#define NCR53c7x0_read32(address)                                     \
++    ((unsigned int) raw_inl((u32)NCR53c7x0_address_memory + (u32)(address)))
++#else
++#define NCR53c7x0_read32(address)                                     \
++    (NCR53c7x0_memory_mapped ?                                                \
++      (unsigned int) readl((u32)NCR53c7x0_address_memory + (u32)(address)) :  \
++      inl(NCR53c7x0_address_io + (address)))
++#endif /* mc68000*/
++
++#ifdef BIG_ENDIAN
++/* If we are big-endian, then we are not Intel, so probably don't have
++ * an i/o map as well as a memory map.  So, let's assume memory mapped.
++ * Also, I am having terrible problems trying to persuade the compiler
++ * not to lay down code which does a read after write for these macros.
++ * If you remove 'volatile' from writeb() and friends it is ok....
++ */
++
++#define NCR53c7x0_write8(address,value)                               \
++      *(volatile unsigned char *)                                     \
++              ((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) = (value)
++
++#define NCR53c7x0_write16(address,value)                              \
++      *(volatile unsigned short *)                                    \
++              ((u32)NCR53c7x0_address_memory + ((u32)(address)^2)) = (value)
++
++#define NCR53c7x0_write32(address,value)                              \
++      *(volatile unsigned long *)                                     \
++              ((u32)NCR53c7x0_address_memory + ((u32)(address))) = (value)
++
++#else
++
++#define NCR53c7x0_write8(address,value)                               \
++    (NCR53c7x0_memory_mapped ?                                                \
++     ({writeb((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) :     \
++      outb((value), NCR53c7x0_address_io + (address)))
++
++#define NCR53c7x0_write16(address,value)                              \
++    (NCR53c7x0_memory_mapped ?                                                \
++     ({writew((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) :     \
++      outw((value), NCR53c7x0_address_io + (address)))
++
++#define NCR53c7x0_write32(address,value)                              \
++    (NCR53c7x0_memory_mapped ?                                                \
++     ({writel((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) :     \
++      outl((value), NCR53c7x0_address_io + (address)))
++
++#endif
++
++/* Patch arbitrary 32 bit words in the script */
++#define patch_abs_32(script, offset, symbol, value)                   \
++      for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof            \
++          (u32)); ++i) {                                      \
++          (script)[A_##symbol##_used[i] - (offset)] += (value);       \
++          if (hostdata->options & OPTION_DEBUG_FIXUP)                 \
++            printk("scsi%d : %s reference %d at 0x%x in %s is now 0x%x\n",\
++              host->host_no, #symbol, i, A_##symbol##_used[i] -       \
++              (int)(offset), #script, (script)[A_##symbol##_used[i] - \
++              (offset)]);                                             \
++      }
++
++/* Patch read/write instruction immediate field */
++#define patch_abs_rwri_data(script, offset, symbol, value)            \
++      for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof            \
++          (u32)); ++i)                                        \
++          (script)[A_##symbol##_used[i] - (offset)] =                 \
++              ((script)[A_##symbol##_used[i] - (offset)] &            \
++              ~DBC_RWRI_IMMEDIATE_MASK) |                             \
++              (((value) << DBC_RWRI_IMMEDIATE_SHIFT) &                \
++               DBC_RWRI_IMMEDIATE_MASK)
++
++/* Patch transfer control instruction data field */
++#define patch_abs_tci_data(script, offset, symbol, value)             \
++      for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof            \
++          (u32)); ++i)                                        \
++          (script)[A_##symbol##_used[i] - (offset)] =                 \
++              ((script)[A_##symbol##_used[i] - (offset)] &            \
++              ~DBC_TCI_DATA_MASK) |                                   \
++              (((value) << DBC_TCI_DATA_SHIFT) &                      \
++               DBC_TCI_DATA_MASK)
++
++/* Patch field in dsa structure (assignment should be +=?) */
++#define patch_dsa_32(dsa, symbol, word, value)                                \
++      {                                                               \
++      (dsa)[(hostdata->##symbol - hostdata->dsa_start) / sizeof(u32)  \
++          + (word)] = (value);                                        \
++      if (hostdata->options & OPTION_DEBUG_DSA)                       \
++          printk("scsi : dsa %s symbol %s(%d) word %d now 0x%x\n",    \
++              #dsa, #symbol, hostdata->##symbol,                      \
++              (word), (u32) (value));                                 \
++      }
++
++/* Paranoid people could use panic() here. */
++#define FATAL(host) shutdown((host));
++
++extern int ncr53c7xx_init(struct scsi_host_template *tpnt, int board, int chip,
++                        unsigned long base, int io_port, int irq, int dma,
++                        long long options, int clock);
++
++#endif /* NCR53c710_C */
++#endif /* NCR53c710_H */
+diff -Nurb linux-2.6.22-590/drivers/scsi/53c7xx.scr linux-2.6.22-570/drivers/scsi/53c7xx.scr
+--- linux-2.6.22-590/drivers/scsi/53c7xx.scr   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/53c7xx.scr   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,1591 @@
++#undef DEBUG
++#undef EVENTS
++#undef NO_SELECTION_TIMEOUT
++#define BIG_ENDIAN
++
++; 53c710 driver.  Modified from Drew Eckhardts driver
++; for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
++;
++; I have left the script for the 53c8xx family in here, as it is likely
++; to be useful to see what I changed when bug hunting.
++
++; NCR 53c810 driver, main script
++; Sponsored by 
++;     iX Multiuser Multitasking Magazine
++;     hm@ix.de
++;
++; Copyright 1993, 1994, 1995 Drew Eckhardt
++;      Visionary Computing 
++;      (Unix and Linux consulting and custom programming)
++;      drew@PoohSticks.ORG
++;      +1 (303) 786-7975
++;
++; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
++;
++; PRE-ALPHA
++;
++; For more information, please consult 
++;
++; NCR 53C810
++; PCI-SCSI I/O Processor
++; Data Manual
++;
++; NCR 53C710 
++; SCSI I/O Processor
++; Programmers Guide
++;
++; NCR Microelectronics
++; 1635 Aeroplaza Drive
++; Colorado Springs, CO 80916
++; 1+ (719) 578-3400
++;
++; Toll free literature number
++; +1 (800) 334-5454
++;
++; IMPORTANT : This code is self modifying due to the limitations of 
++;     the NCR53c7,8xx series chips.  Persons debugging this code with
++;     the remote debugger should take this into account, and NOT set
++;     breakpoints in modified instructions.
++;
++; Design:
++; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard 
++; microcontroller using a simple instruction set.   
++;
++; So, to minimize the effects of interrupt latency, and to maximize 
++; throughput, this driver offloads the practical maximum amount 
++; of processing to the SCSI chip while still maintaining a common
++; structure.
++;
++; Where tradeoffs were needed between efficiency on the older
++; chips and the newer NCR53c800 series, the NCR53c800 series 
++; was chosen.
++;
++; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully
++; automate SCSI transfers without host processor intervention, this 
++; isn't the case with the NCR53c710 and newer chips which allow 
++;
++; - reads and writes to the internal registers from within the SCSI
++;     scripts, allowing the SCSI SCRIPTS(tm) code to save processor
++;     state so that multiple threads of execution are possible, and also
++;     provide an ALU for loop control, etc.
++; 
++; - table indirect addressing for some instructions. This allows 
++;     pointers to be located relative to the DSA ((Data Structure
++;     Address) register.
++;
++; These features make it possible to implement a mailbox style interface,
++; where the same piece of code is run to handle I/O for multiple threads
++; at once minimizing our need to relocate code.  Since the NCR53c700/
++; NCR53c800 series have a unique combination of features, making a 
++; a standard ingoing/outgoing mailbox system, costly, I've modified it.
++;
++; - Mailboxes are a mixture of code and data.  This lets us greatly
++;     simplify the NCR53c810 code and do things that would otherwise
++;     not be possible.
++;
++; The saved data pointer is now implemented as follows :
++;
++;     Control flow has been architected such that if control reaches
++;     munge_save_data_pointer, on a restore pointers message or 
++;     reconnection, a jump to the address formerly in the TEMP register
++;     will allow the SCSI command to resume execution.
++;
++
++;
++; Note : the DSA structures must be aligned on 32 bit boundaries,
++; since the source and destination of MOVE MEMORY instructions 
++; must share the same alignment and this is the alignment of the
++; NCR registers.
++;
++
++; For some systems (MVME166, for example) dmode is always the same, so don't
++; waste time writing it
++
++#if 1
++#define DMODE_MEMORY_TO_NCR
++#define DMODE_MEMORY_TO_MEMORY
++#define DMODE_NCR_TO_MEMORY
++#else
++#define DMODE_MEMORY_TO_NCR    MOVE dmode_memory_to_ncr TO DMODE
++#define DMODE_MEMORY_TO_MEMORY MOVE dmode_memory_to_memory TO DMODE
++#define DMODE_NCR_TO_MEMORY    MOVE dmode_ncr_to_memory TO DMODE
++#endif
++
++ABSOLUTE dsa_temp_lun = 0             ; Patch to lun for current dsa
++ABSOLUTE dsa_temp_next = 0            ; Patch to dsa next for current dsa
++ABSOLUTE dsa_temp_addr_next = 0               ; Patch to address of dsa next address 
++                                      ;       for current dsa
++ABSOLUTE dsa_temp_sync = 0            ; Patch to address of per-target
++                                      ;       sync routine
++ABSOLUTE dsa_sscf_710 = 0             ; Patch to address of per-target
++                                      ;       sscf value (53c710)
++ABSOLUTE dsa_temp_target = 0          ; Patch to id for current dsa
++ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command
++                                      ;       saved data pointer
++ABSOLUTE dsa_temp_addr_residual = 0   ; Patch to address of per-command
++                                      ;       current residual code
++ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command
++                                      ; saved residual code
++ABSOLUTE dsa_temp_addr_new_value = 0  ; Address of value for JUMP operand
++ABSOLUTE dsa_temp_addr_array_value = 0        ; Address to copy to
++ABSOLUTE dsa_temp_addr_dsa_value = 0  ; Address of this DSA value
++
++;
++; Once a device has initiated reselection, we need to compare it 
++; against the singly linked list of commands which have disconnected
++; and are pending reselection.  These commands are maintained in 
++; an unordered singly linked list of DSA structures, through the
++; DSA pointers at their 'centers' headed by the reconnect_dsa_head
++; pointer.
++; 
++; To avoid complications in removing commands from the list,
++; I minimize the amount of expensive (at eight operations per
++; addition @ 500-600ns each) pointer operations which must
++; be done in the NCR driver by precomputing them on the 
++; host processor during dsa structure generation.
++;
++; The fixed-up per DSA code knows how to recognize the nexus
++; associated with the corresponding SCSI command, and modifies
++; the source and destination pointers for the MOVE MEMORY 
++; instruction which is executed when reselected_ok is called
++; to remove the command from the list.  Similarly, DSA is 
++; loaded with the address of the next DSA structure and
++; reselected_check_next is called if a failure occurs.
++;
++; Perhaps more concisely, the net effect of the mess is 
++;
++; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, 
++;     src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) {
++;     src = &dsa->next;
++;     if (target_id == dsa->id && target_lun == dsa->lun) {
++;             *dest = *src;
++;             break;
++;         }   
++; }
++;
++; if (!dsa)
++;           error (int_err_unexpected_reselect);
++; else  
++;     longjmp (dsa->jump_resume, 0);
++;
++;     
++
++#if (CHIP != 700) && (CHIP != 70066)
++; Define DSA structure used for mailboxes
++ENTRY dsa_code_template
++dsa_code_template:
++ENTRY dsa_code_begin
++dsa_code_begin:
++; RGH: Don't care about TEMP and DSA here
++      DMODE_MEMORY_TO_NCR
++      MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch
++      DMODE_MEMORY_TO_MEMORY
++#if (CHIP == 710)
++      MOVE MEMORY 4, addr_scratch, saved_dsa
++      ; We are about to go and select the device, so must set SSCF bits
++      MOVE MEMORY 4, dsa_sscf_710, addr_scratch
++#ifdef BIG_ENDIAN
++      MOVE SCRATCH3 TO SFBR
++#else
++      MOVE SCRATCH0 TO SFBR
++#endif
++      MOVE SFBR TO SBCL
++      MOVE MEMORY 4, saved_dsa, addr_dsa
++#else
++      CALL scratch_to_dsa
++#endif
++      CALL select
++; Handle the phase mismatch which may have resulted from the 
++; MOVE FROM dsa_msgout if we returned here.  The CLEAR ATN 
++; may or may not be necessary, and we should update script_asm.pl
++; to handle multiple pieces.
++    CLEAR ATN
++    CLEAR ACK
++
++; Replace second operand with address of JUMP instruction dest operand
++; in schedule table for this DSA.  Becomes dsa_jump_dest in 53c7,8xx.c.
++ENTRY dsa_code_fix_jump
++dsa_code_fix_jump:
++      MOVE MEMORY 4, NOP_insn, 0
++      JUMP select_done
++
++; wrong_dsa loads the DSA register with the value of the dsa_next
++; field.
++;
++wrong_dsa:
++#if (CHIP == 710)
++;                NOTE DSA is corrupt when we arrive here!
++#endif
++;             Patch the MOVE MEMORY INSTRUCTION such that 
++;             the destination address is the address of the OLD 
++;             next pointer.
++;
++      MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 8
++      DMODE_MEMORY_TO_NCR
++;
++;     Move the _contents_ of the next pointer into the DSA register as 
++;     the next I_T_L or I_T_L_Q tupple to check against the established
++;     nexus.
++;
++      MOVE MEMORY 4, dsa_temp_next, addr_scratch
++      DMODE_MEMORY_TO_MEMORY
++#if (CHIP == 710)
++      MOVE MEMORY 4, addr_scratch, saved_dsa
++      MOVE MEMORY 4, saved_dsa, addr_dsa
++#else
++      CALL scratch_to_dsa
++#endif
++      JUMP reselected_check_next
++
++ABSOLUTE dsa_save_data_pointer = 0
++ENTRY dsa_code_save_data_pointer
++dsa_code_save_data_pointer:
++#if (CHIP == 710)
++      ; When we get here, TEMP has been saved in jump_temp+4, DSA is corrupt
++      ; We MUST return with DSA correct
++      MOVE MEMORY 4, jump_temp+4, dsa_temp_addr_saved_pointer
++; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
++      MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
++        CLEAR ACK
++#ifdef DEBUG
++        INT int_debug_saved
++#endif
++      MOVE MEMORY 4, saved_dsa, addr_dsa
++      JUMP jump_temp
++#else
++      DMODE_NCR_TO_MEMORY
++      MOVE MEMORY 4, addr_temp, dsa_temp_addr_saved_pointer
++      DMODE_MEMORY_TO_MEMORY
++; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
++      MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
++        CLEAR ACK
++#ifdef DEBUG
++        INT int_debug_saved
++#endif
++      RETURN
++#endif
++ABSOLUTE dsa_restore_pointers = 0
++ENTRY dsa_code_restore_pointers
++dsa_code_restore_pointers:
++#if (CHIP == 710)
++      ; TEMP and DSA are corrupt when we get here, but who cares!
++      MOVE MEMORY 4, dsa_temp_addr_saved_pointer, jump_temp + 4
++; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
++      MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
++        CLEAR ACK
++      ; Restore DSA, note we don't care about TEMP
++      MOVE MEMORY 4, saved_dsa, addr_dsa
++#ifdef DEBUG
++        INT int_debug_restored
++#endif
++      JUMP jump_temp
++#else
++      DMODE_MEMORY_TO_NCR
++      MOVE MEMORY 4, dsa_temp_addr_saved_pointer, addr_temp
++      DMODE_MEMORY_TO_MEMORY
++; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
++      MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
++        CLEAR ACK
++#ifdef DEBUG
++        INT int_debug_restored
++#endif
++      RETURN
++#endif
++
++ABSOLUTE dsa_check_reselect = 0
++; dsa_check_reselect determines whether or not the current target and
++; lun match the current DSA
++ENTRY dsa_code_check_reselect
++dsa_code_check_reselect:
++#if (CHIP == 710)
++      /* Arrives here with DSA correct */
++      /* Assumes we are always ID 7 */
++      MOVE LCRC TO SFBR               ; LCRC has our ID and his ID bits set
++      JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0x80
++#else
++      MOVE SSID TO SFBR               ; SSID contains 3 bit target ID
++; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
++      JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0xf8
++#endif
++;
++; Hack - move to scratch first, since SFBR is not writeable
++;     via the CPU and hence a MOVE MEMORY instruction.
++;
++      DMODE_MEMORY_TO_NCR
++      MOVE MEMORY 1, reselected_identify, addr_scratch
++      DMODE_MEMORY_TO_MEMORY
++#ifdef BIG_ENDIAN
++      ; BIG ENDIAN ON MVME16x
++      MOVE SCRATCH3 TO SFBR
++#else
++      MOVE SCRATCH0 TO SFBR
++#endif
++; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
++; Are you sure about that?  richard@sleepie.demon.co.uk
++      JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8
++;             Patch the MOVE MEMORY INSTRUCTION such that
++;             the source address is the address of this dsa's
++;             next pointer.
++      MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 4
++      CALL reselected_ok
++#if (CHIP == 710)
++;     Restore DSA following memory moves in reselected_ok
++;     dsa_temp_sync doesn't really care about DSA, but it has an
++;     optional debug INT so a valid DSA is a good idea.
++      MOVE MEMORY 4, saved_dsa, addr_dsa
++#endif
++      CALL dsa_temp_sync      
++; Release ACK on the IDENTIFY message _after_ we've set the synchronous 
++; transfer parameters! 
++      CLEAR ACK
++; Implicitly restore pointers on reselection, so a RETURN
++; will transfer control back to the right spot.
++      CALL REL (dsa_code_restore_pointers)
++      RETURN
++ENTRY dsa_zero
++dsa_zero:
++ENTRY dsa_code_template_end
++dsa_code_template_end:
++
++; Perform sanity check for dsa_fields_start == dsa_code_template_end - 
++; dsa_zero, puke.
++
++ABSOLUTE dsa_fields_start =  0        ; Sanity marker
++                              ;       pad 48 bytes (fix this RSN)
++ABSOLUTE dsa_next = 48                ; len 4 Next DSA
++                              ; del 4 Previous DSA address
++ABSOLUTE dsa_cmnd = 56                ; len 4 Scsi_Cmnd * for this thread.
++ABSOLUTE dsa_select = 60      ; len 4 Device ID, Period, Offset for 
++                              ;       table indirect select
++ABSOLUTE dsa_msgout = 64      ; len 8 table indirect move parameter for 
++                              ;       select message
++ABSOLUTE dsa_cmdout = 72      ; len 8 table indirect move parameter for 
++                              ;       command
++ABSOLUTE dsa_dataout = 80     ; len 4 code pointer for dataout
++ABSOLUTE dsa_datain = 84      ; len 4 code pointer for datain
++ABSOLUTE dsa_msgin = 88               ; len 8 table indirect move for msgin
++ABSOLUTE dsa_status = 96      ; len 8 table indirect move for status byte
++ABSOLUTE dsa_msgout_other = 104       ; len 8 table indirect for normal message out
++                              ; (Synchronous transfer negotiation, etc).
++ABSOLUTE dsa_end = 112
++
++ABSOLUTE schedule = 0                 ; Array of JUMP dsa_begin or JUMP (next),
++                              ; terminated by a call to JUMP wait_reselect
++
++; Linked lists of DSA structures
++ABSOLUTE reconnect_dsa_head = 0       ; Link list of DSAs which can reconnect
++ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing
++                              ; address of reconnect_dsa_head
++
++; These select the source and destination of a MOVE MEMORY instruction
++ABSOLUTE dmode_memory_to_memory = 0x0
++ABSOLUTE dmode_memory_to_ncr = 0x0
++ABSOLUTE dmode_ncr_to_memory = 0x0
++
++ABSOLUTE addr_scratch = 0x0
++ABSOLUTE addr_temp = 0x0
++#if (CHIP == 710)
++ABSOLUTE saved_dsa = 0x0
++ABSOLUTE emulfly = 0x0
++ABSOLUTE addr_dsa = 0x0
++#endif
++#endif /* CHIP != 700 && CHIP != 70066 */
++
++; Interrupts - 
++; MSB indicates type
++; 0   handle error condition
++; 1   handle message 
++; 2   handle normal condition
++; 3   debugging interrupt
++; 4   testing interrupt 
++; Next byte indicates specific error
++
++; XXX not yet implemented, I'm not sure if I want to - 
++; Next byte indicates the routine the error occurred in
++; The LSB indicates the specific place the error occurred
++ 
++ABSOLUTE int_err_unexpected_phase = 0x00000000        ; Unexpected phase encountered
++ABSOLUTE int_err_selected = 0x00010000                ; SELECTED (nee RESELECTED)
++ABSOLUTE int_err_unexpected_reselect = 0x00020000 
++ABSOLUTE int_err_check_condition = 0x00030000 
++ABSOLUTE int_err_no_phase = 0x00040000
++ABSOLUTE int_msg_wdtr = 0x01000000            ; WDTR message received
++ABSOLUTE int_msg_sdtr = 0x01010000            ; SDTR received
++ABSOLUTE int_msg_1 = 0x01020000                       ; single byte special message
++                                              ; received
++
++ABSOLUTE int_norm_select_complete = 0x02000000        ; Select complete, reprogram
++                                              ; registers.
++ABSOLUTE int_norm_reselect_complete = 0x02010000      ; Nexus established
++ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete
++ABSOLUTE int_norm_disconnected = 0x02030000   ; Disconnected 
++ABSOLUTE int_norm_aborted =0x02040000         ; Aborted *dsa
++ABSOLUTE int_norm_reset = 0x02050000          ; Generated BUS reset.
++ABSOLUTE int_norm_emulateintfly = 0x02060000  ; 53C710 Emulated intfly
++ABSOLUTE int_debug_break = 0x03000000         ; Break point
++#ifdef DEBUG
++ABSOLUTE int_debug_scheduled = 0x03010000     ; new I/O scheduled 
++ABSOLUTE int_debug_idle = 0x03020000          ; scheduler is idle
++ABSOLUTE int_debug_dsa_loaded = 0x03030000    ; dsa reloaded
++ABSOLUTE int_debug_reselected = 0x03040000    ; NCR reselected
++ABSOLUTE int_debug_head = 0x03050000          ; issue head overwritten
++ABSOLUTE int_debug_disconnected = 0x03060000  ; disconnected
++ABSOLUTE int_debug_disconnect_msg = 0x03070000        ; got message to disconnect
++ABSOLUTE int_debug_dsa_schedule = 0x03080000  ; in dsa_schedule
++ABSOLUTE int_debug_reselect_check = 0x03090000  ; Check for reselection of DSA
++ABSOLUTE int_debug_reselected_ok = 0x030a0000         ; Reselection accepted
++#endif
++ABSOLUTE int_debug_panic = 0x030b0000         ; Panic driver
++#ifdef DEBUG
++ABSOLUTE int_debug_saved = 0x030c0000                 ; save/restore pointers
++ABSOLUTE int_debug_restored = 0x030d0000
++ABSOLUTE int_debug_sync = 0x030e0000          ; Sanity check synchronous 
++                                              ; parameters. 
++ABSOLUTE int_debug_datain = 0x030f0000                ; going into data in phase 
++                                              ; now.
++ABSOLUTE int_debug_check_dsa = 0x03100000     ; Sanity check DSA against
++                                              ; SDID.
++#endif
++
++ABSOLUTE int_test_1 = 0x04000000              ; Test 1 complete
++ABSOLUTE int_test_2 = 0x04010000              ; Test 2 complete
++ABSOLUTE int_test_3 = 0x04020000              ; Test 3 complete
++
++
++; These should start with 0x05000000, with low bits incrementing for 
++; each one.
++
++#ifdef EVENTS
++ABSOLUTE int_EVENT_SELECT = 0
++ABSOLUTE int_EVENT_DISCONNECT = 0
++ABSOLUTE int_EVENT_RESELECT = 0
++ABSOLUTE int_EVENT_COMPLETE = 0
++ABSOLUTE int_EVENT_IDLE = 0
++ABSOLUTE int_EVENT_SELECT_FAILED = 0
++ABSOLUTE int_EVENT_BEFORE_SELECT = 0
++ABSOLUTE int_EVENT_RESELECT_FAILED = 0
++#endif
++                                              
++ABSOLUTE NCR53c7xx_msg_abort = 0      ; Pointer to abort message
++ABSOLUTE NCR53c7xx_msg_reject = 0       ; Pointer to reject message
++ABSOLUTE NCR53c7xx_zero       = 0             ; long with zero in it, use for source
++ABSOLUTE NCR53c7xx_sink = 0           ; long to dump worthless data in
++ABSOLUTE NOP_insn = 0                 ; NOP instruction
++
++; Pointer to message, potentially multi-byte
++ABSOLUTE msg_buf = 0
++
++; Pointer to holding area for reselection information
++ABSOLUTE reselected_identify = 0
++ABSOLUTE reselected_tag = 0
++
++; Request sense command pointer, it's a 6 byte command, should
++; be constant for all commands since we always want 16 bytes of 
++; sense and we don't need to change any fields as we did under 
++; SCSI-I when we actually cared about the LUN field.
++;EXTERNAL NCR53c7xx_sense             ; Request sense command
++
++#if (CHIP != 700) && (CHIP != 70066)
++; dsa_schedule  
++; PURPOSE : after a DISCONNECT message has been received, and pointers
++;     saved, insert the current DSA structure at the head of the 
++;     disconnected queue and fall through to the scheduler.
++;
++; CALLS : OK
++;
++; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list
++;     of disconnected commands
++;
++; MODIFIES : SCRATCH, reconnect_dsa_head
++; 
++; EXITS : always passes control to schedule
++
++ENTRY dsa_schedule
++dsa_schedule:
++#ifdef DEBUG
++    INT int_debug_dsa_schedule
++#endif
++
++;
++; Calculate the address of the next pointer within the DSA 
++; structure of the command that is currently disconnecting
++;
++#if (CHIP == 710)
++    ; Read what should be the current DSA from memory - actual DSA
++    ; register is probably corrupt
++    MOVE MEMORY 4, saved_dsa, addr_scratch
++#else
++    CALL dsa_to_scratch
++#endif
++    MOVE SCRATCH0 + dsa_next TO SCRATCH0
++    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
++    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
++    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
++
++; Point the next field of this DSA structure at the current disconnected 
++; list
++    DMODE_NCR_TO_MEMORY
++    MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8
++    DMODE_MEMORY_TO_MEMORY
++dsa_schedule_insert:
++    MOVE MEMORY 4, reconnect_dsa_head, 0 
++
++; And update the head pointer.
++#if (CHIP == 710)
++    ; Read what should be the current DSA from memory - actual DSA
++    ; register is probably corrupt
++    MOVE MEMORY 4, saved_dsa, addr_scratch
++#else
++    CALL dsa_to_scratch
++#endif
++    DMODE_NCR_TO_MEMORY
++    MOVE MEMORY 4, addr_scratch, reconnect_dsa_head
++    DMODE_MEMORY_TO_MEMORY
++/* Temporarily, see what happens. */
++#ifndef ORIGINAL
++#if (CHIP != 710)
++    MOVE SCNTL2 & 0x7f TO SCNTL2
++#endif
++    CLEAR ACK
++#endif
++#if (CHIP == 710)
++    ; Time to correct DSA following memory move
++    MOVE MEMORY 4, saved_dsa, addr_dsa
++#endif
++    WAIT DISCONNECT
++#ifdef EVENTS
++    INT int_EVENT_DISCONNECT;
++#endif
++#ifdef DEBUG
++    INT int_debug_disconnected
++#endif
++    JUMP schedule
++#endif 
++
++;
++; select
++;
++; PURPOSE : establish a nexus for the SCSI command referenced by DSA.
++;     On success, the current DSA structure is removed from the issue 
++;     queue.  Usually, this is entered as a fall-through from schedule,
++;     although the contingent allegiance handling code will write
++;     the select entry address to the DSP to restart a command as a 
++;     REQUEST SENSE.  A message is sent (usually IDENTIFY, although
++;     additional SDTR or WDTR messages may be sent).  COMMAND OUT
++;     is handled.
++;
++; INPUTS : DSA - SCSI command, issue_dsa_head
++;
++; CALLS : NOT OK
++;
++; MODIFIES : SCRATCH, issue_dsa_head
++;
++; EXITS : on reselection or selection, go to select_failed
++;     otherwise, RETURN so control is passed back to 
++;     dsa_begin.
++;
++
++ENTRY select
++select:
++
++#ifdef EVENTS
++    INT int_EVENT_BEFORE_SELECT
++#endif
++
++#ifdef DEBUG
++    INT int_debug_scheduled
++#endif
++    CLEAR TARGET
++
++; XXX
++;
++; In effect, SELECTION operations are backgrounded, with execution
++; continuing until code which waits for REQ or a fatal interrupt is 
++; encountered.
++;
++; So, for more performance, we could overlap the code which removes 
++; the command from the NCRs issue queue with the selection, but 
++; at this point I don't want to deal with the error recovery.
++;
++
++#if (CHIP != 700) && (CHIP != 70066)
++#if (CHIP == 710)
++    ; Enable selection timer
++#ifdef NO_SELECTION_TIMEOUT
++    MOVE CTEST7 & 0xff TO CTEST7
++#else
++    MOVE CTEST7 & 0xef TO CTEST7
++#endif
++#endif
++    SELECT ATN FROM dsa_select, select_failed
++    JUMP select_msgout, WHEN MSG_OUT
++ENTRY select_msgout
++select_msgout:
++#if (CHIP == 710)
++    ; Disable selection timer
++    MOVE CTEST7 | 0x10 TO CTEST7
++#endif
++    MOVE FROM dsa_msgout, WHEN MSG_OUT
++#else
++ENTRY select_msgout
++    SELECT ATN 0, select_failed
++select_msgout:
++    MOVE 0, 0, WHEN MSGOUT
++#endif
++
++#ifdef EVENTS
++   INT int_EVENT_SELECT
++#endif
++   RETURN
++
++; 
++; select_done
++; 
++; PURPOSE: continue on to normal data transfer; called as the exit 
++;     point from dsa_begin.
++;
++; INPUTS: dsa
++;
++; CALLS: OK
++;
++;
++
++select_done:
++#if (CHIP == 710)
++; NOTE DSA is corrupt when we arrive here!
++    MOVE MEMORY 4, saved_dsa, addr_dsa
++#endif
++
++#ifdef DEBUG
++ENTRY select_check_dsa
++select_check_dsa:
++    INT int_debug_check_dsa
++#endif
++
++; After a successful selection, we should get either a CMD phase or 
++; some transfer request negotiation message.
++
++    JUMP cmdout, WHEN CMD
++    INT int_err_unexpected_phase, WHEN NOT MSG_IN 
++
++select_msg_in:
++    CALL msg_in, WHEN MSG_IN
++    JUMP select_msg_in, WHEN MSG_IN
++
++cmdout:
++    INT int_err_unexpected_phase, WHEN NOT CMD
++#if (CHIP == 700)
++    INT int_norm_selected
++#endif
++ENTRY cmdout_cmdout
++cmdout_cmdout:
++#if (CHIP != 700) && (CHIP != 70066)
++    MOVE FROM dsa_cmdout, WHEN CMD
++#else
++    MOVE 0, 0, WHEN CMD
++#endif /* (CHIP != 700) && (CHIP != 70066) */
++
++;
++; data_transfer  
++; other_out
++; other_in
++; other_transfer
++;
++; PURPOSE : handle the main data transfer for a SCSI command in 
++;     several parts.  In the first part, data_transfer, DATA_IN
++;     and DATA_OUT phases are allowed, with the user provided
++;     code (usually dynamically generated based on the scatter/gather
++;     list associated with a SCSI command) called to handle these 
++;     phases.
++;
++;     After control has passed to one of the user provided 
++;     DATA_IN or DATA_OUT routines, back calls are made to 
++;     other_transfer_in or other_transfer_out to handle non-DATA IN
++;     and DATA OUT phases respectively, with the state of the active
++;     data pointer being preserved in TEMP.
++;
++;     On completion, the user code passes control to other_transfer
++;     which causes DATA_IN and DATA_OUT to result in unexpected_phase
++;     interrupts so that data overruns may be trapped.
++;
++; INPUTS : DSA - SCSI command
++;
++; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in
++;     other_transfer
++;
++; MODIFIES : SCRATCH
++;
++; EXITS : if STATUS IN is detected, signifying command completion,
++;     the NCR jumps to command_complete.  If MSG IN occurs, a 
++;     CALL is made to msg_in.  Otherwise, other_transfer runs in 
++;     an infinite loop.
++;     
++
++ENTRY data_transfer
++data_transfer:
++    JUMP cmdout_cmdout, WHEN CMD
++    CALL msg_in, WHEN MSG_IN
++    INT int_err_unexpected_phase, WHEN MSG_OUT
++    JUMP do_dataout, WHEN DATA_OUT
++    JUMP do_datain, WHEN DATA_IN
++    JUMP command_complete, WHEN STATUS
++    JUMP data_transfer
++ENTRY end_data_transfer
++end_data_transfer:
++
++;
++; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain 
++; should be fixed up whenever the nexus changes so it can point to the 
++; correct routine for that command.
++;
++
++#if (CHIP != 700) && (CHIP != 70066)
++; Nasty jump to dsa->dataout
++do_dataout:
++#if (CHIP == 710)
++    MOVE MEMORY 4, saved_dsa, addr_scratch
++#else
++    CALL dsa_to_scratch
++#endif
++    MOVE SCRATCH0 + dsa_dataout TO SCRATCH0   
++    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
++    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
++    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
++    DMODE_NCR_TO_MEMORY
++    MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4
++    DMODE_MEMORY_TO_MEMORY
++dataout_to_jump:
++    MOVE MEMORY 4, 0, dataout_jump + 4 
++#if (CHIP == 710)
++    ; Time to correct DSA following memory move
++    MOVE MEMORY 4, saved_dsa, addr_dsa
++#endif
++dataout_jump:
++    JUMP 0
 +
-                       curSC->SCp.phase = data_out;
-                       VDEB(printk("SYM53C500: Data-Out phase\n"));
-                       outb(FLUSH_FIFO, port_base + CMD_REG);
--                      LOAD_DMA_COUNT(port_base, curSC->request_bufflen);      /* Max transfer size */
-+                      LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC)); /* Max transfer size */
-                       outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG);
--                      if (!curSC->use_sg)     /* Don't use scatter-gather */
--                              SYM53C500_pio_write(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen);
--                      else {  /* use scatter-gather */
--                              sgcount = curSC->use_sg;
--                              sglist = curSC->request_buffer;
--                              while (sgcount--) {
--                                      SYM53C500_pio_write(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length);
--                                      sglist++;
--                              }
++; Nasty jump to dsa->dsain
++do_datain:
++#if (CHIP == 710)
++    MOVE MEMORY 4, saved_dsa, addr_scratch
++#else
++    CALL dsa_to_scratch
++#endif
++    MOVE SCRATCH0 + dsa_datain TO SCRATCH0    
++    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
++    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
++    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
++    DMODE_NCR_TO_MEMORY
++    MOVE MEMORY 4, addr_scratch, datain_to_jump + 4
++    DMODE_MEMORY_TO_MEMORY
++ENTRY datain_to_jump
++datain_to_jump:
++    MOVE MEMORY 4, 0, datain_jump + 4
++#if (CHIP == 710)
++    ; Time to correct DSA following memory move
++    MOVE MEMORY 4, saved_dsa, addr_dsa
++#endif
++#ifdef DEBUG
++    INT int_debug_datain
++#endif
++datain_jump:
++    JUMP 0
++#endif /* (CHIP != 700) && (CHIP != 70066) */
 +
-+                      scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) {
-+                              SYM53C500_pio_write(fast_pio, port_base,
-+                                                  page_address(sg->page) + sg->offset,
-+                                                  sg->length);
-                       }
-                       REG0(port_base);
-               }
-@@ -455,20 +452,19 @@
-       case 0x01:              /* DATA-IN */
-               if (int_reg & 0x10) {   /* Target requesting info transfer */
-+                      struct scatterlist *sg;
-+                      int i;
 +
-                       curSC->SCp.phase = data_in;
-                       VDEB(printk("SYM53C500: Data-In phase\n"));
-                       outb(FLUSH_FIFO, port_base + CMD_REG);
--                      LOAD_DMA_COUNT(port_base, curSC->request_bufflen);      /* Max transfer size */
-+                      LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC)); /* Max transfer size */
-                       outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG);
--                      if (!curSC->use_sg)     /* Don't use scatter-gather */
--                              SYM53C500_pio_read(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen);
--                      else {  /* Use scatter-gather */
--                              sgcount = curSC->use_sg;
--                              sglist = curSC->request_buffer;
--                              while (sgcount--) {
--                                      SYM53C500_pio_read(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length);
--                                      sglist++;
--                              }
++; Note that other_out and other_in loop until a non-data phase
++; is discovered, so we only execute return statements when we
++; can go on to the next data phase block move statement.
 +
-+                      scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) {
-+                              SYM53C500_pio_read(fast_pio, port_base,
-+                                                 page_address(sg->page) + sg->offset,
-+                                                 sg->length);
-                       }
-                       REG0(port_base);
-               }
-@@ -578,7 +574,7 @@
-       DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", 
-           SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->id, 
--          SCpnt->device->lun,  SCpnt->request_bufflen));
-+          SCpnt->device->lun,  scsi_bufflen(SCpnt)));
-       VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
-           printk("cmd[%d]=%02x  ", i, SCpnt->cmnd[i]));
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla2xxx/qla_attr.c linux-2.6.22-590/drivers/scsi/qla2xxx/qla_attr.c
---- linux-2.6.22-570/drivers/scsi/qla2xxx/qla_attr.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla2xxx/qla_attr.c   2008-01-02 13:56:37.000000000 -0500
-@@ -11,8 +11,9 @@
- /* SYSFS attributes --------------------------------------------------------- */
- static ssize_t
--qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
-+                         struct bin_attribute *bin_attr,
-+                         char *buf, loff_t off, size_t count)
- {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
-           struct device, kobj)));
-@@ -31,8 +32,9 @@
- }
- static ssize_t
--qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
-+                          struct bin_attribute *bin_attr,
-+                          char *buf, loff_t off, size_t count)
- {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
-           struct device, kobj)));
-@@ -73,7 +75,6 @@
-       .attr = {
-               .name = "fw_dump",
-               .mode = S_IRUSR | S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = 0,
-       .read = qla2x00_sysfs_read_fw_dump,
-@@ -81,8 +82,9 @@
- };
- static ssize_t
--qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+qla2x00_sysfs_read_nvram(struct kobject *kobj,
-+                       struct bin_attribute *bin_attr,
-+                       char *buf, loff_t off, size_t count)
- {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
-           struct device, kobj)));
-@@ -101,8 +103,9 @@
- }
- static ssize_t
--qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+qla2x00_sysfs_write_nvram(struct kobject *kobj,
-+                        struct bin_attribute *bin_attr,
-+                        char *buf, loff_t off, size_t count)
- {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
-           struct device, kobj)));
-@@ -149,7 +152,6 @@
-       .attr = {
-               .name = "nvram",
-               .mode = S_IRUSR | S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = 512,
-       .read = qla2x00_sysfs_read_nvram,
-@@ -157,8 +159,9 @@
- };
- static ssize_t
--qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+qla2x00_sysfs_read_optrom(struct kobject *kobj,
-+                        struct bin_attribute *bin_attr,
-+                        char *buf, loff_t off, size_t count)
- {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
-           struct device, kobj)));
-@@ -176,8 +179,9 @@
- }
- static ssize_t
--qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+qla2x00_sysfs_write_optrom(struct kobject *kobj,
-+                         struct bin_attribute *bin_attr,
-+                         char *buf, loff_t off, size_t count)
- {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
-           struct device, kobj)));
-@@ -198,7 +202,6 @@
-       .attr = {
-               .name = "optrom",
-               .mode = S_IRUSR | S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = OPTROM_SIZE_24XX,
-       .read = qla2x00_sysfs_read_optrom,
-@@ -206,8 +209,9 @@
- };
- static ssize_t
--qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
-+                             struct bin_attribute *bin_attr,
-+                             char *buf, loff_t off, size_t count)
- {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
-           struct device, kobj)));
-@@ -279,15 +283,15 @@
-       .attr = {
-               .name = "optrom_ctl",
-               .mode = S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = 0,
-       .write = qla2x00_sysfs_write_optrom_ctl,
- };
- static ssize_t
--qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+qla2x00_sysfs_read_vpd(struct kobject *kobj,
-+                     struct bin_attribute *bin_attr,
-+                     char *buf, loff_t off, size_t count)
- {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
-           struct device, kobj)));
-@@ -305,8 +309,9 @@
- }
- static ssize_t
--qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+qla2x00_sysfs_write_vpd(struct kobject *kobj,
-+                      struct bin_attribute *bin_attr,
-+                      char *buf, loff_t off, size_t count)
- {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
-           struct device, kobj)));
-@@ -327,7 +332,6 @@
-       .attr = {
-               .name = "vpd",
-               .mode = S_IRUSR | S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = 0,
-       .read = qla2x00_sysfs_read_vpd,
-@@ -335,8 +339,9 @@
- };
- static ssize_t
--qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off,
--    size_t count)
-+qla2x00_sysfs_read_sfp(struct kobject *kobj,
-+                     struct bin_attribute *bin_attr,
-+                     char *buf, loff_t off, size_t count)
- {
-       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
-           struct device, kobj)));
-@@ -375,7 +380,6 @@
-       .attr = {
-               .name = "sfp",
-               .mode = S_IRUSR | S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = SFP_DEV_SIZE * 2,
-       .read = qla2x00_sysfs_read_sfp,
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla2xxx/qla_dbg.c linux-2.6.22-590/drivers/scsi/qla2xxx/qla_dbg.c
---- linux-2.6.22-570/drivers/scsi/qla2xxx/qla_dbg.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla2xxx/qla_dbg.c    2008-01-02 13:56:37.000000000 -0500
-@@ -1411,9 +1411,9 @@
-               printk("0x%02x ", cmd->cmnd[i]);
-       }
-       printk("\n  seg_cnt=%d, allowed=%d, retries=%d\n",
--          cmd->use_sg, cmd->allowed, cmd->retries);
-+             scsi_sg_count(cmd), cmd->allowed, cmd->retries);
-       printk("  request buffer=0x%p, request buffer len=0x%x\n",
--          cmd->request_buffer, cmd->request_bufflen);
-+             scsi_sglist(cmd), scsi_bufflen(cmd));
-       printk("  tag=%d, transfersize=0x%x\n",
-           cmd->tag, cmd->transfersize);
-       printk("  serial_number=%lx, SP=%p\n", cmd->serial_number, sp);
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla2xxx/qla_iocb.c linux-2.6.22-590/drivers/scsi/qla2xxx/qla_iocb.c
---- linux-2.6.22-570/drivers/scsi/qla2xxx/qla_iocb.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla2xxx/qla_iocb.c   2008-01-02 13:56:37.000000000 -0500
-@@ -155,6 +155,8 @@
-       uint32_t        *cur_dsd;
-       scsi_qla_host_t *ha;
-       struct scsi_cmnd *cmd;
-+      struct scatterlist *sg;
-+      int i;
-       cmd = sp->cmd;
-@@ -163,7 +165,7 @@
-           __constant_cpu_to_le32(COMMAND_TYPE);
-       /* No data transfer */
--      if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
-+      if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
-               cmd_pkt->byte_count = __constant_cpu_to_le32(0);
-               return;
-       }
-@@ -177,13 +179,8 @@
-       cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
-       /* Load data segments */
--      if (cmd->use_sg != 0) {
--              struct  scatterlist *cur_seg;
--              struct  scatterlist *end_seg;
--
--              cur_seg = (struct scatterlist *)cmd->request_buffer;
--              end_seg = cur_seg + tot_dsds;
--              while (cur_seg < end_seg) {
++ENTRY other_out
++other_out:
++#if 0
++    INT 0x03ffdead
++#endif
++    INT int_err_unexpected_phase, WHEN CMD
++    JUMP msg_in_restart, WHEN MSG_IN 
++    INT int_err_unexpected_phase, WHEN MSG_OUT
++    INT int_err_unexpected_phase, WHEN DATA_IN
++    JUMP command_complete, WHEN STATUS
++    JUMP other_out, WHEN NOT DATA_OUT
++#if (CHIP == 710)
++; TEMP should be OK, as we got here from a call in the user dataout code.
++#endif
++    RETURN
 +
-+      scsi_for_each_sg(cmd, sg, tot_dsds, i) {
-                       cont_entry_t    *cont_pkt;
-                       /* Allocate additional continuation packets? */
-@@ -197,15 +194,9 @@
-                               avail_dsds = 7;
-                       }
--                      *cur_dsd++ = cpu_to_le32(sg_dma_address(cur_seg));
--                      *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
-+              *cur_dsd++ = cpu_to_le32(sg_dma_address(sg));
-+              *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
-                       avail_dsds--;
--
--                      cur_seg++;
--              }
--      } else {
--              *cur_dsd++ = cpu_to_le32(sp->dma_handle);
--              *cur_dsd++ = cpu_to_le32(cmd->request_bufflen);
-       }
- }
-@@ -224,6 +215,8 @@
-       uint32_t        *cur_dsd;
-       scsi_qla_host_t *ha;
-       struct scsi_cmnd *cmd;
-+      struct scatterlist *sg;
-+      int i;
-       cmd = sp->cmd;
-@@ -232,7 +225,7 @@
-           __constant_cpu_to_le32(COMMAND_A64_TYPE);
-       /* No data transfer */
--      if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
-+      if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
-               cmd_pkt->byte_count = __constant_cpu_to_le32(0);
-               return;
-       }
-@@ -246,13 +239,7 @@
-       cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
-       /* Load data segments */
--      if (cmd->use_sg != 0) {
--              struct  scatterlist *cur_seg;
--              struct  scatterlist *end_seg;
--
--              cur_seg = (struct scatterlist *)cmd->request_buffer;
--              end_seg = cur_seg + tot_dsds;
--              while (cur_seg < end_seg) {
-+      scsi_for_each_sg(cmd, sg, tot_dsds, i) {
-                       dma_addr_t      sle_dma;
-                       cont_a64_entry_t *cont_pkt;
-@@ -267,18 +254,11 @@
-                               avail_dsds = 5;
-                       }
--                      sle_dma = sg_dma_address(cur_seg);
-+              sle_dma = sg_dma_address(sg);
-                       *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
-                       *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
--                      *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
-+              *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
-                       avail_dsds--;
--
--                      cur_seg++;
--              }
--      } else {
--              *cur_dsd++ = cpu_to_le32(LSD(sp->dma_handle));
--              *cur_dsd++ = cpu_to_le32(MSD(sp->dma_handle));
--              *cur_dsd++ = cpu_to_le32(cmd->request_bufflen);
-       }
- }
-@@ -291,7 +271,7 @@
- int
- qla2x00_start_scsi(srb_t *sp)
- {
--      int             ret;
-+      int             ret, nseg;
-       unsigned long   flags;
-       scsi_qla_host_t *ha;
-       struct scsi_cmnd *cmd;
-@@ -299,7 +279,6 @@
-       uint32_t        index;
-       uint32_t        handle;
-       cmd_entry_t     *cmd_pkt;
--      struct scatterlist *sg;
-       uint16_t        cnt;
-       uint16_t        req_cnt;
-       uint16_t        tot_dsds;
-@@ -337,23 +316,10 @@
-               goto queuing_error;
-       /* Map the sg table so we have an accurate count of sg entries needed */
--      if (cmd->use_sg) {
--              sg = (struct scatterlist *) cmd->request_buffer;
--              tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg,
--                  cmd->sc_data_direction);
--              if (tot_dsds == 0)
-+      nseg = scsi_dma_map(cmd);
-+      if (nseg < 0)
-                       goto queuing_error;
--      } else if (cmd->request_bufflen) {
--              dma_addr_t      req_dma;
--
--              req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
--                  cmd->request_bufflen, cmd->sc_data_direction);
--              if (dma_mapping_error(req_dma))
--                      goto queuing_error;
--
--              sp->dma_handle = req_dma;
--              tot_dsds = 1;
--      }
-+      tot_dsds = nseg;
-       /* Calculate the number of request entries needed. */
-       req_cnt = ha->isp_ops.calc_req_entries(tot_dsds);
-@@ -391,7 +357,7 @@
-       /* Load SCSI command packet. */
-       memcpy(cmd_pkt->scsi_cdb, cmd->cmnd, cmd->cmd_len);
--      cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen);
-+      cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
-       /* Build IOCB segments */
-       ha->isp_ops.build_iocbs(sp, cmd_pkt, tot_dsds);
-@@ -423,14 +389,9 @@
-       return (QLA_SUCCESS);
- queuing_error:
--      if (cmd->use_sg && tot_dsds) {
--              sg = (struct scatterlist *) cmd->request_buffer;
--              pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
--                  cmd->sc_data_direction);
--      } else if (tot_dsds) {
--              pci_unmap_single(ha->pdev, sp->dma_handle,
--                  cmd->request_bufflen, cmd->sc_data_direction);
--      }
-+      if (tot_dsds)
-+              scsi_dma_unmap(cmd);
++ENTRY other_in
++other_in:
++#if 0
++    INT 0x03ffdead
++#endif
++    INT int_err_unexpected_phase, WHEN CMD
++    JUMP msg_in_restart, WHEN MSG_IN 
++    INT int_err_unexpected_phase, WHEN MSG_OUT
++    INT int_err_unexpected_phase, WHEN DATA_OUT
++    JUMP command_complete, WHEN STATUS
++    JUMP other_in, WHEN NOT DATA_IN
++#if (CHIP == 710)
++; TEMP should be OK, as we got here from a call in the user datain code.
++#endif
++    RETURN
++
++
++ENTRY other_transfer
++other_transfer:
++    INT int_err_unexpected_phase, WHEN CMD
++    CALL msg_in, WHEN MSG_IN
++    INT int_err_unexpected_phase, WHEN MSG_OUT
++    INT int_err_unexpected_phase, WHEN DATA_OUT
++    INT int_err_unexpected_phase, WHEN DATA_IN
++    JUMP command_complete, WHEN STATUS
++    JUMP other_transfer
++
++;
++; msg_in_restart
++; msg_in
++; munge_msg
++;
++; PURPOSE : process messages from a target.  msg_in is called when the 
++;     caller hasn't read the first byte of the message.  munge_message
++;     is called when the caller has read the first byte of the message,
++;     and left it in SFBR.  msg_in_restart is called when the caller 
++;     hasn't read the first byte of the message, and wishes RETURN
++;     to transfer control back to the address of the conditional
++;     CALL instruction rather than to the instruction after it.
++;
++;     Various int_* interrupts are generated when the host system
++;     needs to intervene, as is the case with SDTR, WDTR, and
++;     INITIATE RECOVERY messages.
++;
++;     When the host system handles one of these interrupts,
++;     it can respond by reentering at reject_message, 
++;     which rejects the message and returns control to
++;     the caller of msg_in or munge_msg, accept_message
++;     which clears ACK and returns control, or reply_message
++;     which sends the message pointed to by the DSA 
++;     msgout_other table indirect field.
++;
++;     DISCONNECT messages are handled by moving the command
++;     to the reconnect_dsa_queue.
++#if (CHIP == 710)
++; NOTE: DSA should be valid when we get here - we cannot save both it
++;     and TEMP in this routine.
++#endif
++;
++; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg
++;     only)
++;
++; CALLS : NO.  The TEMP register isn't backed up to allow nested calls.
++;
++; MODIFIES : SCRATCH, DSA on DISCONNECT
++;
++; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS,
++;     and normal return from message handlers running under
++;     Linux, control is returned to the caller.  Receipt
++;     of DISCONNECT messages pass control to dsa_schedule.
++;
++ENTRY msg_in_restart
++msg_in_restart:
++; XXX - hackish
++;
++; Since it's easier to debug changes to the statically 
++; compiled code, rather than the dynamically generated 
++; stuff, such as
++;
++;     MOVE x, y, WHEN data_phase
++;     CALL other_z, WHEN NOT data_phase
++;     MOVE x, y, WHEN data_phase
++;
++; I'd like to have certain routines (notably the message handler)
++; restart on the conditional call rather than the next instruction.
++;
++; So, subtract 8 from the return address
++
++    MOVE TEMP0 + 0xf8 TO TEMP0
++    MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY
++    MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY
++    MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY
++
++ENTRY msg_in
++msg_in:
++    MOVE 1, msg_buf, WHEN MSG_IN
++
++munge_msg:
++    JUMP munge_extended, IF 0x01              ; EXTENDED MESSAGE
++    JUMP munge_2, IF 0x20, AND MASK 0xdf      ; two byte message
++;
++; XXX - I've seen a handful of broken SCSI devices which fail to issue
++;     a SAVE POINTERS message before disconnecting in the middle of 
++;     a transfer, assuming that the DATA POINTER will be implicitly 
++;     restored.  
++;
++; Historically, I've often done an implicit save when the DISCONNECT
++; message is processed.  We may want to consider having the option of 
++; doing that here. 
++;
++    JUMP munge_save_data_pointer, IF 0x02     ; SAVE DATA POINTER
++    JUMP munge_restore_pointers, IF 0x03      ; RESTORE POINTERS 
++    JUMP munge_disconnect, IF 0x04            ; DISCONNECT
++    INT int_msg_1, IF 0x07                    ; MESSAGE REJECT
++    INT int_msg_1, IF 0x0f                    ; INITIATE RECOVERY
++#ifdef EVENTS 
++    INT int_EVENT_SELECT_FAILED 
++#endif
++    JUMP reject_message
++
++munge_2:
++    JUMP reject_message
++;
++; The SCSI standard allows targets to recover from transient 
++; error conditions by backing up the data pointer with a 
++; RESTORE POINTERS message.  
++;     
++; So, we must save and restore the _residual_ code as well as 
++; the current instruction pointer.  Because of this messiness,
++; it is simpler to put dynamic code in the dsa for this and to
++; just do a simple jump down there. 
++;
++
++munge_save_data_pointer:
++#if (CHIP == 710)
++    ; We have something in TEMP here, so first we must save that
++    MOVE TEMP0 TO SFBR
++    MOVE SFBR TO SCRATCH0
++    MOVE TEMP1 TO SFBR
++    MOVE SFBR TO SCRATCH1
++    MOVE TEMP2 TO SFBR
++    MOVE SFBR TO SCRATCH2
++    MOVE TEMP3 TO SFBR
++    MOVE SFBR TO SCRATCH3
++    MOVE MEMORY 4, addr_scratch, jump_temp + 4
++    ; Now restore DSA
++    MOVE MEMORY 4, saved_dsa, addr_dsa
++#endif
++    MOVE DSA0 + dsa_save_data_pointer TO SFBR
++    MOVE SFBR TO SCRATCH0
++    MOVE DSA1 + 0xff TO SFBR WITH CARRY
++    MOVE SFBR TO SCRATCH1
++    MOVE DSA2 + 0xff TO SFBR WITH CARRY 
++    MOVE SFBR TO SCRATCH2
++    MOVE DSA3 + 0xff TO SFBR WITH CARRY
++    MOVE SFBR TO SCRATCH3
++
++    DMODE_NCR_TO_MEMORY
++    MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4
++    DMODE_MEMORY_TO_MEMORY
++jump_dsa_save:
++    JUMP 0
++
++munge_restore_pointers:
++#if (CHIP == 710)
++    ; The code at dsa_restore_pointers will RETURN, but we don't care
++    ; about TEMP here, as it will overwrite it anyway.
++#endif
++    MOVE DSA0 + dsa_restore_pointers TO SFBR
++    MOVE SFBR TO SCRATCH0
++    MOVE DSA1 + 0xff TO SFBR WITH CARRY
++    MOVE SFBR TO SCRATCH1
++    MOVE DSA2 + 0xff TO SFBR WITH CARRY
++    MOVE SFBR TO SCRATCH2
++    MOVE DSA3 + 0xff TO SFBR WITH CARRY
++    MOVE SFBR TO SCRATCH3
++
++    DMODE_NCR_TO_MEMORY
++    MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4
++    DMODE_MEMORY_TO_MEMORY
++jump_dsa_restore:
++    JUMP 0
++
++
++munge_disconnect:
++#ifdef DEBUG
++    INT int_debug_disconnect_msg
++#endif
 +
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
-       return (QLA_FUNCTION_FAILED);
-@@ -642,6 +603,8 @@
-       uint32_t        *cur_dsd;
-       scsi_qla_host_t *ha;
-       struct scsi_cmnd *cmd;
-+      struct scatterlist *sg;
-+      int i;
-       cmd = sp->cmd;
-@@ -650,7 +613,7 @@
-           __constant_cpu_to_le32(COMMAND_TYPE_7);
-       /* No data transfer */
--      if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
-+      if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
-               cmd_pkt->byte_count = __constant_cpu_to_le32(0);
-               return;
-       }
-@@ -670,13 +633,8 @@
-       cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
-       /* Load data segments */
--      if (cmd->use_sg != 0) {
--              struct  scatterlist *cur_seg;
--              struct  scatterlist *end_seg;
--
--              cur_seg = (struct scatterlist *)cmd->request_buffer;
--              end_seg = cur_seg + tot_dsds;
--              while (cur_seg < end_seg) {
++/* 
++ * Before, we overlapped processing with waiting for disconnect, but
++ * debugging was beginning to appear messy.  Temporarily move things
++ * to just before the WAIT DISCONNECT.
++ */
++ 
++#ifdef ORIGINAL
++#if (CHIP == 710)
++; Following clears Unexpected Disconnect bit.  What do we do?
++#else
++    MOVE SCNTL2 & 0x7f TO SCNTL2
++#endif
++    CLEAR ACK
++#endif
 +
-+      scsi_for_each_sg(cmd, sg, tot_dsds, i) {
-                       dma_addr_t      sle_dma;
-                       cont_a64_entry_t *cont_pkt;
-@@ -691,18 +649,11 @@
-                               avail_dsds = 5;
-                       }
--                      sle_dma = sg_dma_address(cur_seg);
-+              sle_dma = sg_dma_address(sg);
-                       *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
-                       *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
--                      *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
-+              *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
-                       avail_dsds--;
--
--                      cur_seg++;
--              }
--      } else {
--              *cur_dsd++ = cpu_to_le32(LSD(sp->dma_handle));
--              *cur_dsd++ = cpu_to_le32(MSD(sp->dma_handle));
--              *cur_dsd++ = cpu_to_le32(cmd->request_bufflen);
-       }
- }
-@@ -716,7 +667,7 @@
- int
- qla24xx_start_scsi(srb_t *sp)
- {
--      int             ret;
-+      int             ret, nseg;
-       unsigned long   flags;
-       scsi_qla_host_t *ha;
-       struct scsi_cmnd *cmd;
-@@ -724,7 +675,6 @@
-       uint32_t        index;
-       uint32_t        handle;
-       struct cmd_type_7 *cmd_pkt;
--      struct scatterlist *sg;
-       uint16_t        cnt;
-       uint16_t        req_cnt;
-       uint16_t        tot_dsds;
-@@ -762,23 +712,10 @@
-               goto queuing_error;
-       /* Map the sg table so we have an accurate count of sg entries needed */
--      if (cmd->use_sg) {
--              sg = (struct scatterlist *) cmd->request_buffer;
--              tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg,
--                  cmd->sc_data_direction);
--              if (tot_dsds == 0)
--                      goto queuing_error;
--      } else if (cmd->request_bufflen) {
--              dma_addr_t      req_dma;
--
--              req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
--                  cmd->request_bufflen, cmd->sc_data_direction);
--              if (dma_mapping_error(req_dma))
-+      nseg = scsi_dma_map(cmd);
-+      if (nseg < 0)
-                       goto queuing_error;
--
--              sp->dma_handle = req_dma;
--              tot_dsds = 1;
--      }
-+      tot_dsds = nseg;
-       req_cnt = qla24xx_calc_iocbs(tot_dsds);
-       if (ha->req_q_cnt < (req_cnt + 2)) {
-@@ -821,7 +758,7 @@
-       memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
-       host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb));
--      cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen);
-+      cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
-       /* Build IOCB segments */
-       qla24xx_build_scsi_iocbs(sp, cmd_pkt, tot_dsds);
-@@ -853,14 +790,9 @@
-       return QLA_SUCCESS;
- queuing_error:
--      if (cmd->use_sg && tot_dsds) {
--              sg = (struct scatterlist *) cmd->request_buffer;
--              pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
--                  cmd->sc_data_direction);
--      } else if (tot_dsds) {
--              pci_unmap_single(ha->pdev, sp->dma_handle,
--                  cmd->request_bufflen, cmd->sc_data_direction);
--      }
-+      if (tot_dsds)
-+              scsi_dma_unmap(cmd);
++#if (CHIP != 700) && (CHIP != 70066)
++    JUMP dsa_schedule
++#else
++    WAIT DISCONNECT
++    INT int_norm_disconnected
++#endif
 +
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
-       return QLA_FUNCTION_FAILED;
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla2xxx/qla_isr.c linux-2.6.22-590/drivers/scsi/qla2xxx/qla_isr.c
---- linux-2.6.22-570/drivers/scsi/qla2xxx/qla_isr.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla2xxx/qla_isr.c    2008-01-02 13:56:37.000000000 -0500
-@@ -889,11 +889,11 @@
-               }
-               if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) {
-                       resid = resid_len;
--                      cp->resid = resid;
-+                      scsi_set_resid(cp, resid);
-                       CMD_RESID_LEN(cp) = resid;
-                       if (!lscsi_status &&
--                          ((unsigned)(cp->request_bufflen - resid) <
-+                          ((unsigned)(scsi_bufflen(cp) - resid) <
-                            cp->underflow)) {
-                               qla_printk(KERN_INFO, ha,
-                                   "scsi(%ld:%d:%d:%d): Mid-layer underflow "
-@@ -901,7 +901,7 @@
-                                   "error status.\n", ha->host_no,
-                                   cp->device->channel, cp->device->id,
-                                   cp->device->lun, resid,
--                                  cp->request_bufflen);
-+                                         scsi_bufflen(cp));
-                               cp->result = DID_ERROR << 16;
-                               break;
-@@ -963,7 +963,7 @@
-                       resid = fw_resid_len;
-               if (scsi_status & SS_RESIDUAL_UNDER) {
--                      cp->resid = resid;
-+                      scsi_set_resid(cp, resid);
-                       CMD_RESID_LEN(cp) = resid;
-               } else {
-                       DEBUG2(printk(KERN_INFO
-@@ -1046,14 +1046,14 @@
-                                   "retrying command.\n", ha->host_no,
-                                   cp->device->channel, cp->device->id,
-                                   cp->device->lun, resid,
--                                  cp->request_bufflen));
-+                                            scsi_bufflen(cp)));
-                               cp->result = DID_BUS_BUSY << 16;
-                               break;
-                       }
-                       /* Handle mid-layer underflow */
--                      if ((unsigned)(cp->request_bufflen - resid) <
-+                      if ((unsigned)(scsi_bufflen(cp) - resid) <
-                           cp->underflow) {
-                               qla_printk(KERN_INFO, ha,
-                                   "scsi(%ld:%d:%d:%d): Mid-layer underflow "
-@@ -1061,7 +1061,7 @@
-                                   "error status.\n", ha->host_no,
-                                   cp->device->channel, cp->device->id,
-                                   cp->device->lun, resid,
--                                  cp->request_bufflen);
-+                                         scsi_bufflen(cp));
-                               cp->result = DID_ERROR << 16;
-                               break;
-@@ -1084,7 +1084,7 @@
-               DEBUG2(printk(KERN_INFO
-                   "PID=0x%lx req=0x%x xtra=0x%x -- returning DID_ERROR "
-                   "status!\n",
--                  cp->serial_number, cp->request_bufflen, resid_len));
-+                  cp->serial_number, scsi_bufflen(cp), resid_len));
-               cp->result = DID_ERROR << 16;
-               break;
-@@ -1633,7 +1633,7 @@
-       uint16_t entry;
-       uint16_t index;
-       const char *name;
--      irqreturn_t (*handler)(int, void *);
-+      irq_handler_t handler;
- };
- static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = {
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla2xxx/qla_os.c linux-2.6.22-590/drivers/scsi/qla2xxx/qla_os.c
---- linux-2.6.22-570/drivers/scsi/qla2xxx/qla_os.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla2xxx/qla_os.c     2008-01-02 13:56:37.000000000 -0500
-@@ -2426,13 +2426,7 @@
-       struct scsi_cmnd *cmd = sp->cmd;
-       if (sp->flags & SRB_DMA_VALID) {
--              if (cmd->use_sg) {
--                      dma_unmap_sg(&ha->pdev->dev, cmd->request_buffer,
--                          cmd->use_sg, cmd->sc_data_direction);
--              } else if (cmd->request_bufflen) {
--                      dma_unmap_single(&ha->pdev->dev, sp->dma_handle,
--                          cmd->request_bufflen, cmd->sc_data_direction);
--              }
-+              scsi_dma_unmap(cmd);
-               sp->flags &= ~SRB_DMA_VALID;
-       }
-       CMD_SP(cmd) = NULL;
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_dbg.c linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_dbg.c
---- linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_dbg.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_dbg.c    2008-01-02 13:56:37.000000000 -0500
-@@ -6,176 +6,9 @@
-  */
- #include "ql4_def.h"
--#include <scsi/scsi_dbg.h>
--
--#if 0
--
--static void qla4xxx_print_srb_info(struct srb * srb)
--{
--      printk("%s: srb = 0x%p, flags=0x%02x\n", __func__, srb, srb->flags);
--      printk("%s: cmd = 0x%p, saved_dma_handle = 0x%lx\n",
--             __func__, srb->cmd, (unsigned long) srb->dma_handle);
--      printk("%s: fw_ddb_index = %d, lun = %d\n",
--             __func__, srb->fw_ddb_index, srb->cmd->device->lun);
--      printk("%s: iocb_tov = %d\n",
--             __func__, srb->iocb_tov);
--      printk("%s: cc_stat = 0x%x, r_start = 0x%lx, u_start = 0x%lx\n\n",
--             __func__, srb->cc_stat, srb->r_start, srb->u_start);
--}
--
--void qla4xxx_print_scsi_cmd(struct scsi_cmnd *cmd)
--{
--      printk("SCSI Command = 0x%p, Handle=0x%p\n", cmd, cmd->host_scribble);
--      printk("  b=%d, t=%02xh, l=%02xh, cmd_len = %02xh\n",
--             cmd->device->channel, cmd->device->id, cmd->device->lun,
--             cmd->cmd_len);
--      scsi_print_command(cmd);
--      printk("  seg_cnt = %d\n", cmd->use_sg);
--      printk("  request buffer = 0x%p, request buffer len = 0x%x\n",
--             cmd->request_buffer, cmd->request_bufflen);
--      if (cmd->use_sg) {
--              struct scatterlist *sg;
--              sg = (struct scatterlist *)cmd->request_buffer;
--              printk("  SG buffer: \n");
--              qla4xxx_dump_buffer((caddr_t) sg,
--                                  (cmd->use_sg * sizeof(*sg)));
--      }
--      printk("  tag = %d, transfersize = 0x%x \n", cmd->tag,
--             cmd->transfersize);
--      printk("  Pid = %d, SP = 0x%p\n", (int)cmd->pid, cmd->SCp.ptr);
--      printk("  underflow size = 0x%x, direction=0x%x\n", cmd->underflow,
--             cmd->sc_data_direction);
--      printk("  Current time (jiffies) = 0x%lx, "
--             "timeout expires = 0x%lx\n", jiffies, cmd->eh_timeout.expires);
--      qla4xxx_print_srb_info((struct srb *) cmd->SCp.ptr);
--}
--
--void __dump_registers(struct scsi_qla_host *ha)
--{
--      uint8_t i;
--      for (i = 0; i < MBOX_REG_COUNT; i++) {
--              printk(KERN_INFO "0x%02X mailbox[%d]      = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg, mailbox[i]), i,
--                     readw(&ha->reg->mailbox[i]));
--      }
--      printk(KERN_INFO "0x%02X flash_address   = 0x%08X\n",
--             (uint8_t) offsetof(struct isp_reg, flash_address),
--             readw(&ha->reg->flash_address));
--      printk(KERN_INFO "0x%02X flash_data      = 0x%08X\n",
--             (uint8_t) offsetof(struct isp_reg, flash_data),
--             readw(&ha->reg->flash_data));
--      printk(KERN_INFO "0x%02X ctrl_status     = 0x%08X\n",
--             (uint8_t) offsetof(struct isp_reg, ctrl_status),
--             readw(&ha->reg->ctrl_status));
--      if (is_qla4010(ha)) {
--              printk(KERN_INFO "0x%02X nvram           = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg, u1.isp4010.nvram),
--                     readw(&ha->reg->u1.isp4010.nvram));
--      }
--
--      else if (is_qla4022(ha) | is_qla4032(ha)) {
--              printk(KERN_INFO "0x%02X intr_mask       = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u1.isp4022.intr_mask),
--                     readw(&ha->reg->u1.isp4022.intr_mask));
--              printk(KERN_INFO "0x%02X nvram           = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg, u1.isp4022.nvram),
--                     readw(&ha->reg->u1.isp4022.nvram));
--              printk(KERN_INFO "0x%02X semaphore       = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u1.isp4022.semaphore),
--                     readw(&ha->reg->u1.isp4022.semaphore));
--      }
--      printk(KERN_INFO "0x%02X req_q_in        = 0x%08X\n",
--             (uint8_t) offsetof(struct isp_reg, req_q_in),
--             readw(&ha->reg->req_q_in));
--      printk(KERN_INFO "0x%02X rsp_q_out       = 0x%08X\n",
--             (uint8_t) offsetof(struct isp_reg, rsp_q_out),
--             readw(&ha->reg->rsp_q_out));
--      if (is_qla4010(ha)) {
--              printk(KERN_INFO "0x%02X ext_hw_conf     = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u2.isp4010.ext_hw_conf),
--                     readw(&ha->reg->u2.isp4010.ext_hw_conf));
--              printk(KERN_INFO "0x%02X port_ctrl       = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u2.isp4010.port_ctrl),
--                     readw(&ha->reg->u2.isp4010.port_ctrl));
--              printk(KERN_INFO "0x%02X port_status     = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u2.isp4010.port_status),
--                     readw(&ha->reg->u2.isp4010.port_status));
--              printk(KERN_INFO "0x%02X req_q_out       = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u2.isp4010.req_q_out),
--                     readw(&ha->reg->u2.isp4010.req_q_out));
--              printk(KERN_INFO "0x%02X gp_out          = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_out),
--                     readw(&ha->reg->u2.isp4010.gp_out));
--              printk(KERN_INFO "0x%02X gp_in           = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_in),
--                     readw(&ha->reg->u2.isp4010.gp_in));
--              printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u2.isp4010.port_err_status),
--                     readw(&ha->reg->u2.isp4010.port_err_status));
--      }
--
--      else if (is_qla4022(ha) | is_qla4032(ha)) {
--              printk(KERN_INFO "Page 0 Registers:\n");
--              printk(KERN_INFO "0x%02X ext_hw_conf     = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u2.isp4022.p0.ext_hw_conf),
--                     readw(&ha->reg->u2.isp4022.p0.ext_hw_conf));
--              printk(KERN_INFO "0x%02X port_ctrl       = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u2.isp4022.p0.port_ctrl),
--                     readw(&ha->reg->u2.isp4022.p0.port_ctrl));
--              printk(KERN_INFO "0x%02X port_status     = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u2.isp4022.p0.port_status),
--                     readw(&ha->reg->u2.isp4022.p0.port_status));
--              printk(KERN_INFO "0x%02X gp_out          = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u2.isp4022.p0.gp_out),
--                     readw(&ha->reg->u2.isp4022.p0.gp_out));
--              printk(KERN_INFO "0x%02X gp_in           = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg, u2.isp4022.p0.gp_in),
--                     readw(&ha->reg->u2.isp4022.p0.gp_in));
--              printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u2.isp4022.p0.port_err_status),
--                     readw(&ha->reg->u2.isp4022.p0.port_err_status));
--              printk(KERN_INFO "Page 1 Registers:\n");
--              writel(HOST_MEM_CFG_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT),
--                     &ha->reg->ctrl_status);
--              printk(KERN_INFO "0x%02X req_q_out       = 0x%08X\n",
--                     (uint8_t) offsetof(struct isp_reg,
--                                        u2.isp4022.p1.req_q_out),
--                     readw(&ha->reg->u2.isp4022.p1.req_q_out));
--              writel(PORT_CTRL_STAT_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT),
--                     &ha->reg->ctrl_status);
--      }
--}
--
--void qla4xxx_dump_mbox_registers(struct scsi_qla_host *ha)
--{
--      unsigned long flags = 0;
--      int i = 0;
--      spin_lock_irqsave(&ha->hardware_lock, flags);
--      for (i = 1; i < MBOX_REG_COUNT; i++)
--              printk(KERN_INFO "  Mailbox[%d] = %08x\n", i,
--                     readw(&ha->reg->mailbox[i]));
--      spin_unlock_irqrestore(&ha->hardware_lock, flags);
--}
--
--void qla4xxx_dump_registers(struct scsi_qla_host *ha)
--{
--      unsigned long flags = 0;
--      spin_lock_irqsave(&ha->hardware_lock, flags);
--      __dump_registers(ha);
--      spin_unlock_irqrestore(&ha->hardware_lock, flags);
--}
-+#include "ql4_glbl.h"
-+#include "ql4_dbg.h"
-+#include "ql4_inline.h"
- void qla4xxx_dump_buffer(void *b, uint32_t size)
- {
-@@ -198,4 +31,3 @@
-               printk(KERN_DEBUG "\n");
- }
--#endif  /*  0  */
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_def.h linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_def.h
---- linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_def.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_def.h    2008-01-02 13:56:37.000000000 -0500
-@@ -122,8 +122,7 @@
- #define ISCSI_IPADDR_SIZE             4       /* IP address size */
- #define ISCSI_ALIAS_SIZE              32      /* ISCSI Alais name size */
--#define ISCSI_NAME_SIZE                       255     /* ISCSI Name size -
--                                               * usually a string */
-+#define ISCSI_NAME_SIZE                       0xE0    /* ISCSI Name size */
- #define LSDW(x) ((u32)((u64)(x)))
- #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
-@@ -187,7 +186,19 @@
-       u_long u_start;         /* Time when we handed the cmd to F/W */
- };
--      /*
++munge_extended:
++    CLEAR ACK
++    INT int_err_unexpected_phase, WHEN NOT MSG_IN
++    MOVE 1, msg_buf + 1, WHEN MSG_IN
++    JUMP munge_extended_2, IF 0x02
++    JUMP munge_extended_3, IF 0x03 
++    JUMP reject_message
++
++munge_extended_2:
++    CLEAR ACK
++    MOVE 1, msg_buf + 2, WHEN MSG_IN
++    JUMP reject_message, IF NOT 0x02  ; Must be WDTR
++    CLEAR ACK
++    MOVE 1, msg_buf + 3, WHEN MSG_IN
++    INT int_msg_wdtr
++
++munge_extended_3:
++    CLEAR ACK
++    MOVE 1, msg_buf + 2, WHEN MSG_IN
++    JUMP reject_message, IF NOT 0x01  ; Must be SDTR
++    CLEAR ACK
++    MOVE 2, msg_buf + 3, WHEN MSG_IN
++    INT int_msg_sdtr
++
++ENTRY reject_message
++reject_message:
++    SET ATN
++    CLEAR ACK
++    MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT
++    RETURN
++
++ENTRY accept_message
++accept_message:
++    CLEAR ATN
++    CLEAR ACK
++    RETURN
++
++ENTRY respond_message
++respond_message:
++    SET ATN
++    CLEAR ACK
++    MOVE FROM dsa_msgout_other, WHEN MSG_OUT
++    RETURN
++
++;
++; command_complete
++;
++; PURPOSE : handle command termination when STATUS IN is detected by reading
++;     a status byte followed by a command termination message. 
++;
++;     Normal termination results in an INTFLY instruction, and 
++;     the host system can pick out which command terminated by 
++;     examining the MESSAGE and STATUS buffers of all currently 
++;     executing commands;
++;
++;     Abnormal (CHECK_CONDITION) termination results in an
++;     int_err_check_condition interrupt so that a REQUEST SENSE
++;     command can be issued out-of-order so that no other command
++;     clears the contingent allegiance condition.
++;     
++;
++; INPUTS : DSA - command      
++;
++; CALLS : OK
++;
++; EXITS : On successful termination, control is passed to schedule.
++;     On abnormal termination, the user will usually modify the 
++;     DSA fields and corresponding buffers and return control
++;     to select.
++;
++
++ENTRY command_complete
++command_complete:
++    MOVE FROM dsa_status, WHEN STATUS
++#if (CHIP != 700) && (CHIP != 70066)
++    MOVE SFBR TO SCRATCH0             ; Save status
++#endif /* (CHIP != 700) && (CHIP != 70066) */
++ENTRY command_complete_msgin
++command_complete_msgin:
++    MOVE FROM dsa_msgin, WHEN MSG_IN
++; Indicate that we should be expecting a disconnect
++#if (CHIP != 710)
++    MOVE SCNTL2 & 0x7f TO SCNTL2
++#else
++    ; Above code cleared the Unexpected Disconnect bit, what do we do?
++#endif
++    CLEAR ACK
++#if (CHIP != 700) && (CHIP != 70066)
++    WAIT DISCONNECT
++
++;
++; The SCSI specification states that when a UNIT ATTENTION condition
++; is pending, as indicated by a CHECK CONDITION status message,
++; the target shall revert to asynchronous transfers.  Since
++; synchronous transfers parameters are maintained on a per INITIATOR/TARGET 
++; basis, and returning control to our scheduler could work on a command
++; running on another lun on that target using the old parameters, we must
++; interrupt the host processor to get them changed, or change them ourselves.
++;
++; Once SCSI-II tagged queueing is implemented, things will be even more
++; hairy, since contingent allegiance conditions exist on a per-target/lun
++; basis, and issuing a new command with a different tag would clear it.
++; In these cases, we must interrupt the host processor to get a request 
++; added to the HEAD of the queue with the request sense command, or we
++; must automatically issue the request sense command.
++
++#if 0
++    MOVE SCRATCH0 TO SFBR                     
++    JUMP command_failed, IF 0x02
++#endif
++#if (CHIP == 710)
++#if defined(MVME16x_INTFLY)
++; For MVME16x (ie CHIP=710) we will force an INTFLY by triggering a software
++; interrupt (SW7).  We can use SCRATCH, as we are about to jump to
++; schedule, which corrupts it anyway.  Will probably remove this later,
++; but want to check performance effects first.
++
++#define INTFLY_ADDR     0xfff40070
++
++    MOVE 0 TO SCRATCH0
++    MOVE 0x80 TO SCRATCH1
++    MOVE 0 TO SCRATCH2
++    MOVE 0 TO SCRATCH3
++    MOVE MEMORY 4, addr_scratch, INTFLY_ADDR
++#else
++    INT int_norm_emulateintfly
++#endif
++#else
++    INTFLY
++#endif
++#endif /* (CHIP != 700) && (CHIP != 70066) */
++#if (CHIP == 710)
++    ; Time to correct DSA following memory move
++    MOVE MEMORY 4, saved_dsa, addr_dsa
++#endif
++#ifdef EVENTS
++    INT int_EVENT_COMPLETE
++#endif
++#if (CHIP != 700) && (CHIP != 70066)
++    JUMP schedule
++command_failed:
++    INT int_err_check_condition
++#else
++    INT int_norm_command_complete
++#endif
++
++;
++; wait_reselect
++;
++; PURPOSE : This is essentially the idle routine, where control lands
++;     when there are no new processes to schedule.  wait_reselect
++;     waits for reselection, selection, and new commands.
++;
++;     When a successful reselection occurs, with the aid 
++;     of fixed up code in each DSA, wait_reselect walks the 
++;     reconnect_dsa_queue, asking each dsa if the target ID
++;     and LUN match its.
++;
++;     If a match is found, a call is made back to reselected_ok,
++;     which through the miracles of self modifying code, extracts
++;     the found DSA from the reconnect_dsa_queue and then 
++;     returns control to the DSAs thread of execution.
++;
++; INPUTS : NONE
++;
++; CALLS : OK
++;
++; MODIFIES : DSA,
++;
++; EXITS : On successful reselection, control is returned to the 
++;     DSA which called reselected_ok.  If the WAIT RESELECT
++;     was interrupted by a new commands arrival signaled by 
++;     SIG_P, control is passed to schedule.  If the NCR is 
++;     selected, the host system is interrupted with an 
++;     int_err_selected which is usually responded to by
++;     setting DSP to the target_abort address.
++
++ENTRY wait_reselect
++wait_reselect:
++#ifdef EVENTS
++    int int_EVENT_IDLE
++#endif
++#ifdef DEBUG
++    int int_debug_idle
++#endif
++    WAIT RESELECT wait_reselect_failed
++
++reselected:
++#ifdef EVENTS
++    int int_EVENT_RESELECT
++#endif
++    CLEAR TARGET
++    DMODE_MEMORY_TO_MEMORY
++    ; Read all data needed to reestablish the nexus - 
++    MOVE 1, reselected_identify, WHEN MSG_IN
++    ; We used to CLEAR ACK here.
++#if (CHIP != 700) && (CHIP != 70066)
++#ifdef DEBUG
++    int int_debug_reselected
++#endif
++
++    ; Point DSA at the current head of the disconnected queue.
++    DMODE_MEMORY_TO_NCR
++    MOVE MEMORY 4, reconnect_dsa_head, addr_scratch
++    DMODE_MEMORY_TO_MEMORY
++#if (CHIP == 710)
++    MOVE MEMORY 4, addr_scratch, saved_dsa
++#else
++    CALL scratch_to_dsa
++#endif
++
++    ; Fix the update-next pointer so that the reconnect_dsa_head
++    ; pointer is the one that will be updated if this DSA is a hit 
++    ; and we remove it from the queue.
++
++    MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok_patch + 8
++#if (CHIP == 710)
++    ; Time to correct DSA following memory move
++    MOVE MEMORY 4, saved_dsa, addr_dsa
++#endif
++
++ENTRY reselected_check_next
++reselected_check_next:
++#ifdef DEBUG
++    INT int_debug_reselect_check
++#endif
++    ; Check for a NULL pointer.
++    MOVE DSA0 TO SFBR
++    JUMP reselected_not_end, IF NOT 0
++    MOVE DSA1 TO SFBR
++    JUMP reselected_not_end, IF NOT 0
++    MOVE DSA2 TO SFBR
++    JUMP reselected_not_end, IF NOT 0
++    MOVE DSA3 TO SFBR
++    JUMP reselected_not_end, IF NOT 0
++    INT int_err_unexpected_reselect
++
++reselected_not_end:
++    ;
++    ; XXX the ALU is only eight bits wide, and the assembler
++    ; wont do the dirt work for us.  As long as dsa_check_reselect
++    ; is negative, we need to sign extend with 1 bits to the full
++    ; 32 bit width of the address.
++    ;
++    ; A potential work around would be to have a known alignment 
++    ; of the DSA structure such that the base address plus 
++    ; dsa_check_reselect doesn't require carrying from bytes 
++    ; higher than the LSB.
++    ;
++
++    MOVE DSA0 TO SFBR
++    MOVE SFBR + dsa_check_reselect TO SCRATCH0
++    MOVE DSA1 TO SFBR
++    MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY
++    MOVE DSA2 TO SFBR
++    MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY
++    MOVE DSA3 TO SFBR
++    MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY
++
++    DMODE_NCR_TO_MEMORY
++    MOVE MEMORY 4, addr_scratch, reselected_check + 4
++    DMODE_MEMORY_TO_MEMORY
++#if (CHIP == 710)
++    ; Time to correct DSA following memory move
++    MOVE MEMORY 4, saved_dsa, addr_dsa
++#endif
++reselected_check:
++    JUMP 0
++
++
++;
++;
++#if (CHIP == 710)
++; We have problems here - the memory move corrupts TEMP and DSA.  This
++; routine is called from DSA code, and patched from many places.  Scratch
++; is probably free when it is called.
++; We have to:
++;   copy temp to scratch, one byte at a time
++;   write scratch to patch a jump in place of the return
++;   do the move memory
++;   jump to the patched in return address
++; DSA is corrupt when we get here, and can be left corrupt
++
++ENTRY reselected_ok
++reselected_ok:
++    MOVE TEMP0 TO SFBR
++    MOVE SFBR TO SCRATCH0
++    MOVE TEMP1 TO SFBR
++    MOVE SFBR TO SCRATCH1
++    MOVE TEMP2 TO SFBR
++    MOVE SFBR TO SCRATCH2
++    MOVE TEMP3 TO SFBR
++    MOVE SFBR TO SCRATCH3
++    MOVE MEMORY 4, addr_scratch, reselected_ok_jump + 4
++reselected_ok_patch:
++    MOVE MEMORY 4, 0, 0
++reselected_ok_jump:
++    JUMP 0
++#else
++ENTRY reselected_ok
++reselected_ok:
++reselected_ok_patch:
++    MOVE MEMORY 4, 0, 0                               ; Patched : first word
++                                              ;       is address of 
++                                              ;       successful dsa_next
++                                              ; Second word is last 
++                                              ;       unsuccessful dsa_next,
++                                              ;       starting with 
++                                              ;       dsa_reconnect_head
++    ; We used to CLEAR ACK here.
++#ifdef DEBUG
++    INT int_debug_reselected_ok
++#endif
++#ifdef DEBUG
++    INT int_debug_check_dsa
++#endif
++    RETURN                                    ; Return control to where
++#endif
++#else
++    INT int_norm_reselected
++#endif /* (CHIP != 700) && (CHIP != 70066) */
++
++selected:
++    INT int_err_selected;
++
++;
++; A select or reselect failure can be caused by one of two conditions : 
++; 1.  SIG_P was set.  This will be the case if the user has written
++;     a new value to a previously NULL head of the issue queue.
++;
++; 2.  The NCR53c810 was selected or reselected by another device.
++;
++; 3.  The bus was already busy since we were selected or reselected
++;     before starting the command.
++
++wait_reselect_failed:
++#ifdef EVENTS 
++      INT int_EVENT_RESELECT_FAILED
++#endif
++; Check selected bit.  
++#if (CHIP == 710)
++    ; Must work out how to tell if we are selected....
++#else
++    MOVE SIST0 & 0x20 TO SFBR
++    JUMP selected, IF 0x20
++#endif
++; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
++    MOVE CTEST2 & 0x40 TO SFBR        
++    JUMP schedule, IF 0x40
++; Check connected bit.  
++; FIXME: this needs to change if we support target mode
++    MOVE ISTAT & 0x08 TO SFBR
++    JUMP reselected, IF 0x08
++; FIXME : Something bogus happened, and we shouldn't fail silently.
++#if 0
++    JUMP schedule
++#else
++    INT int_debug_panic
++#endif
++
++
++select_failed:
++#if (CHIP == 710)
++    ; Disable selection timer
++    MOVE CTEST7 | 0x10 TO CTEST7
++#endif
++#ifdef EVENTS
++  int int_EVENT_SELECT_FAILED
++#endif
++; Otherwise, mask the selected and reselected bits off SIST0
++#if (CHIP ==710)
++    ; Let's assume we don't get selected for now
++    MOVE SSTAT0 & 0x10 TO SFBR
++#else
++    MOVE SIST0 & 0x30 TO SFBR
++    JUMP selected, IF 0x20
++#endif
++    JUMP reselected, IF 0x10 
++; If SIGP is set, the user just gave us another command, and
++; we should restart or return to the scheduler.
++; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
++    MOVE CTEST2 & 0x40 TO SFBR        
++    JUMP select, IF 0x40
++; Check connected bit.  
++; FIXME: this needs to change if we support target mode
++; FIXME: is this really necessary? 
++    MOVE ISTAT & 0x08 TO SFBR
++    JUMP reselected, IF 0x08
++; FIXME : Something bogus happened, and we shouldn't fail silently.
++#if 0
++    JUMP schedule
++#else
++    INT int_debug_panic
++#endif
++
++;
++; test_1
++; test_2
++;
++; PURPOSE : run some verification tests on the NCR.  test_1
++;     copies test_src to test_dest and interrupts the host
++;     processor, testing for cache coherency and interrupt
++;     problems in the processes.
++;
++;     test_2 runs a command with offsets relative to the 
++;     DSA on entry, and is useful for miscellaneous experimentation.
++;
++
++; Verify that interrupts are working correctly and that we don't 
++; have a cache invalidation problem.
++
++ABSOLUTE test_src = 0, test_dest = 0
++ENTRY test_1
++test_1:
++    MOVE MEMORY 4, test_src, test_dest
++    INT int_test_1
++
++;
++; Run arbitrary commands, with test code establishing a DSA
++;
++ 
++ENTRY test_2
++test_2:
++    CLEAR TARGET
++#if (CHIP == 710)
++    ; Enable selection timer
++#ifdef NO_SELECTION_TIMEOUT
++    MOVE CTEST7 & 0xff TO CTEST7
++#else
++    MOVE CTEST7 & 0xef TO CTEST7
++#endif
++#endif
++    SELECT ATN FROM 0, test_2_fail
++    JUMP test_2_msgout, WHEN MSG_OUT
++ENTRY test_2_msgout
++test_2_msgout:
++#if (CHIP == 710)
++    ; Disable selection timer
++    MOVE CTEST7 | 0x10 TO CTEST7
++#endif
++    MOVE FROM 8, WHEN MSG_OUT
++    MOVE FROM 16, WHEN CMD 
++    MOVE FROM 24, WHEN DATA_IN
++    MOVE FROM 32, WHEN STATUS
++    MOVE FROM 40, WHEN MSG_IN
++#if (CHIP != 710)
++    MOVE SCNTL2 & 0x7f TO SCNTL2
++#endif
++    CLEAR ACK
++    WAIT DISCONNECT
++test_2_fail:
++#if (CHIP == 710)
++    ; Disable selection timer
++    MOVE CTEST7 | 0x10 TO CTEST7
++#endif
++    INT int_test_2
++
++ENTRY debug_break
++debug_break:
++    INT int_debug_break
++
++;
++; initiator_abort
++; target_abort
++;
++; PURPOSE : Abort the currently established nexus from with initiator
++;     or target mode.
++;
++;  
++
++ENTRY target_abort
++target_abort:
++    SET TARGET
++    DISCONNECT
++    CLEAR TARGET
++    JUMP schedule
++    
++ENTRY initiator_abort
++initiator_abort:
++    SET ATN
++;
++; The SCSI-I specification says that targets may go into MSG out at 
++; their leisure upon receipt of the ATN single.  On all versions of the 
++; specification, we can't change phases until REQ transitions true->false, 
++; so we need to sink/source one byte of data to allow the transition.
++;
++; For the sake of safety, we'll only source one byte of data in all 
++; cases, but to accommodate the SCSI-I dain bramage, we'll sink an  
++; arbitrary number of bytes.
++    JUMP spew_cmd, WHEN CMD
++    JUMP eat_msgin, WHEN MSG_IN
++    JUMP eat_datain, WHEN DATA_IN
++    JUMP eat_status, WHEN STATUS
++    JUMP spew_dataout, WHEN DATA_OUT
++    JUMP sated
++spew_cmd:
++    MOVE 1, NCR53c7xx_zero, WHEN CMD
++    JUMP sated
++eat_msgin:
++    MOVE 1, NCR53c7xx_sink, WHEN MSG_IN
++    JUMP eat_msgin, WHEN MSG_IN
++    JUMP sated
++eat_status:
++    MOVE 1, NCR53c7xx_sink, WHEN STATUS
++    JUMP eat_status, WHEN STATUS
++    JUMP sated
++eat_datain:
++    MOVE 1, NCR53c7xx_sink, WHEN DATA_IN
++    JUMP eat_datain, WHEN DATA_IN
++    JUMP sated
++spew_dataout:
++    MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT
++sated:
++#if (CHIP != 710)
++    MOVE SCNTL2 & 0x7f TO SCNTL2
++#endif
++    MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT
++    WAIT DISCONNECT
++    INT int_norm_aborted
++
++#if (CHIP != 710)
++;
++; dsa_to_scratch
++; scratch_to_dsa
++;
++; PURPOSE :
++;     The NCR chips cannot do a move memory instruction with the DSA register 
++;     as the source or destination.  So, we provide a couple of subroutines
++;     that let us switch between the DSA register and scratch register.
++;
++;     Memory moves to/from the DSPS  register also don't work, but we 
++;     don't use them.
++;
++;
++
++ 
++dsa_to_scratch:
++    MOVE DSA0 TO SFBR
++    MOVE SFBR TO SCRATCH0
++    MOVE DSA1 TO SFBR
++    MOVE SFBR TO SCRATCH1
++    MOVE DSA2 TO SFBR
++    MOVE SFBR TO SCRATCH2
++    MOVE DSA3 TO SFBR
++    MOVE SFBR TO SCRATCH3
++    RETURN
++
++scratch_to_dsa:
++    MOVE SCRATCH0 TO SFBR
++    MOVE SFBR TO DSA0
++    MOVE SCRATCH1 TO SFBR
++    MOVE SFBR TO DSA1
++    MOVE SCRATCH2 TO SFBR
++    MOVE SFBR TO DSA2
++    MOVE SCRATCH3 TO SFBR
++    MOVE SFBR TO DSA3
++    RETURN
++#endif
++ 
++#if (CHIP == 710)
++; Little patched jump, used to overcome problems with TEMP getting
++; corrupted on memory moves.
++
++jump_temp:
++    JUMP 0
++#endif
+diff -Nurb linux-2.6.22-590/drivers/scsi/53c7xx_d.h_shipped linux-2.6.22-570/drivers/scsi/53c7xx_d.h_shipped
+--- linux-2.6.22-590/drivers/scsi/53c7xx_d.h_shipped   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/53c7xx_d.h_shipped   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,2874 @@
++/* DO NOT EDIT - Generated automatically by script_asm.pl */
++static u32 SCRIPT[] = {
++/*
++
++
++
++
++
++; 53c710 driver.  Modified from Drew Eckhardts driver
++; for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
++;
++; I have left the script for the 53c8xx family in here, as it is likely
++; to be useful to see what I changed when bug hunting.
++
++; NCR 53c810 driver, main script
++; Sponsored by 
++;     iX Multiuser Multitasking Magazine
++;     hm@ix.de
++;
++; Copyright 1993, 1994, 1995 Drew Eckhardt
++;      Visionary Computing 
++;      (Unix and Linux consulting and custom programming)
++;      drew@PoohSticks.ORG
++;      +1 (303) 786-7975
++;
++; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
++;
++; PRE-ALPHA
++;
++; For more information, please consult 
++;
++; NCR 53C810
++; PCI-SCSI I/O Processor
++; Data Manual
++;
++; NCR 53C710 
++; SCSI I/O Processor
++; Programmers Guide
++;
++; NCR Microelectronics
++; 1635 Aeroplaza Drive
++; Colorado Springs, CO 80916
++; 1+ (719) 578-3400
++;
++; Toll free literature number
++; +1 (800) 334-5454
++;
++; IMPORTANT : This code is self modifying due to the limitations of 
++;     the NCR53c7,8xx series chips.  Persons debugging this code with
++;     the remote debugger should take this into account, and NOT set
++;     breakpoints in modified instructions.
++;
++; Design:
++; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard 
++; microcontroller using a simple instruction set.   
++;
++; So, to minimize the effects of interrupt latency, and to maximize 
++; throughput, this driver offloads the practical maximum amount 
++; of processing to the SCSI chip while still maintaining a common
++; structure.
++;
++; Where tradeoffs were needed between efficiency on the older
++; chips and the newer NCR53c800 series, the NCR53c800 series 
++; was chosen.
++;
++; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully
++; automate SCSI transfers without host processor intervention, this 
++; isn't the case with the NCR53c710 and newer chips which allow 
++;
++; - reads and writes to the internal registers from within the SCSI
++;     scripts, allowing the SCSI SCRIPTS(tm) code to save processor
++;     state so that multiple threads of execution are possible, and also
++;     provide an ALU for loop control, etc.
++; 
++; - table indirect addressing for some instructions. This allows 
++;     pointers to be located relative to the DSA ((Data Structure
++;     Address) register.
++;
++; These features make it possible to implement a mailbox style interface,
++; where the same piece of code is run to handle I/O for multiple threads
++; at once minimizing our need to relocate code.  Since the NCR53c700/
++; NCR53c800 series have a unique combination of features, making a 
++; a standard ingoing/outgoing mailbox system, costly, I've modified it.
++;
++; - Mailboxes are a mixture of code and data.  This lets us greatly
++;     simplify the NCR53c810 code and do things that would otherwise
++;     not be possible.
++;
++; The saved data pointer is now implemented as follows :
++;
++;     Control flow has been architected such that if control reaches
++;     munge_save_data_pointer, on a restore pointers message or 
++;     reconnection, a jump to the address formerly in the TEMP register
++;     will allow the SCSI command to resume execution.
++;
++
++;
++; Note : the DSA structures must be aligned on 32 bit boundaries,
++; since the source and destination of MOVE MEMORY instructions 
++; must share the same alignment and this is the alignment of the
++; NCR registers.
++;
++
++; For some systems (MVME166, for example) dmode is always the same, so don't
++; waste time writing it
++
++
++
++
++
++
++
++
++
++
++
++ABSOLUTE dsa_temp_lun = 0             ; Patch to lun for current dsa
++ABSOLUTE dsa_temp_next = 0            ; Patch to dsa next for current dsa
++ABSOLUTE dsa_temp_addr_next = 0               ; Patch to address of dsa next address 
++                                      ;       for current dsa
++ABSOLUTE dsa_temp_sync = 0            ; Patch to address of per-target
++                                      ;       sync routine
++ABSOLUTE dsa_sscf_710 = 0             ; Patch to address of per-target
++                                      ;       sscf value (53c710)
++ABSOLUTE dsa_temp_target = 0          ; Patch to id for current dsa
++ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command
++                                      ;       saved data pointer
++ABSOLUTE dsa_temp_addr_residual = 0   ; Patch to address of per-command
++                                      ;       current residual code
++ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command
++                                      ; saved residual code
++ABSOLUTE dsa_temp_addr_new_value = 0  ; Address of value for JUMP operand
++ABSOLUTE dsa_temp_addr_array_value = 0        ; Address to copy to
++ABSOLUTE dsa_temp_addr_dsa_value = 0  ; Address of this DSA value
++
++;
++; Once a device has initiated reselection, we need to compare it 
++; against the singly linked list of commands which have disconnected
++; and are pending reselection.  These commands are maintained in 
++; an unordered singly linked list of DSA structures, through the
++; DSA pointers at their 'centers' headed by the reconnect_dsa_head
++; pointer.
++; 
++; To avoid complications in removing commands from the list,
++; I minimize the amount of expensive (at eight operations per
++; addition @ 500-600ns each) pointer operations which must
++; be done in the NCR driver by precomputing them on the 
++; host processor during dsa structure generation.
++;
++; The fixed-up per DSA code knows how to recognize the nexus
++; associated with the corresponding SCSI command, and modifies
++; the source and destination pointers for the MOVE MEMORY 
++; instruction which is executed when reselected_ok is called
++; to remove the command from the list.  Similarly, DSA is 
++; loaded with the address of the next DSA structure and
++; reselected_check_next is called if a failure occurs.
++;
++; Perhaps more concisely, the net effect of the mess is 
++;
++; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, 
++;     src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) {
++;     src = &dsa->next;
++;     if (target_id == dsa->id && target_lun == dsa->lun) {
++;             *dest = *src;
++;             break;
++;         }   
++; }
++;
++; if (!dsa)
++;           error (int_err_unexpected_reselect);
++; else  
++;     longjmp (dsa->jump_resume, 0);
++;
++;     
++
++
++; Define DSA structure used for mailboxes
++ENTRY dsa_code_template
++dsa_code_template:
++ENTRY dsa_code_begin
++dsa_code_begin:
++; RGH: Don't care about TEMP and DSA here
++      
++      MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch
++
++at 0x00000000 : */    0xc0000004,0x00000000,0x00000000,
++/*
++      
++
++      MOVE MEMORY 4, addr_scratch, saved_dsa
++
++at 0x00000003 : */    0xc0000004,0x00000000,0x00000000,
++/*
++      ; We are about to go and select the device, so must set SSCF bits
++      MOVE MEMORY 4, dsa_sscf_710, addr_scratch
++
++at 0x00000006 : */    0xc0000004,0x00000000,0x00000000,
++/*
++
++      MOVE SCRATCH3 TO SFBR
++
++at 0x00000009 : */    0x72370000,0x00000000,
 +/*
-+ * Asynchronous Event Queue structure
-+ */
-+struct aen {
-+        uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
-+};
 +
-+struct ql4_aen_log {
-+        int count;
-+        struct aen entry[MAX_AEN_ENTRIES];
-+};
 +
++
++      MOVE SFBR TO SBCL
++
++at 0x0000000b : */    0x6a0b0000,0x00000000,
 +/*
-        * Device Database (DDB) structure
-        */
- struct ddb_entry {
-@@ -254,13 +265,6 @@
- #define DF_ISNS_DISCOVERED    2       /* Device was discovered via iSNS */
- #define DF_FO_MASKED          3
--/*
-- * Asynchronous Event Queue structure
-- */
--struct aen {
--      uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
--};
--
- #include "ql4_fw.h"
- #include "ql4_nvram.h"
-@@ -270,20 +274,17 @@
-  */
- struct scsi_qla_host {
-       /* Linux adapter configuration data */
--      struct Scsi_Host *host; /* pointer to host data */
--      uint32_t tot_ddbs;
-       unsigned long flags;
- #define AF_ONLINE                   0 /* 0x00000001 */
- #define AF_INIT_DONE                1 /* 0x00000002 */
- #define AF_MBOX_COMMAND                     2 /* 0x00000004 */
- #define AF_MBOX_COMMAND_DONE        3 /* 0x00000008 */
--#define AF_INTERRUPTS_ON            6 /* 0x00000040 Not Used */
-+#define AF_INTERRUPTS_ON              6 /* 0x00000040 */
- #define AF_GET_CRASH_RECORD         7 /* 0x00000080 */
- #define AF_LINK_UP                  8 /* 0x00000100 */
- #define AF_IRQ_ATTACHED                    10 /* 0x00000400 */
--#define AF_ISNS_CMD_IN_PROCESS             12 /* 0x00001000 */
--#define AF_ISNS_CMD_DONE           13 /* 0x00002000 */
-+#define AF_DISABLE_ACB_COMPLETE               11 /* 0x00000800 */
-       unsigned long dpc_flags;
-@@ -296,6 +297,9 @@
- #define DPC_AEN                             9 /* 0x00000200 */
- #define DPC_GET_DHCP_IP_ADDR       15 /* 0x00008000 */
-+      struct Scsi_Host *host; /* pointer to host data */
-+      uint32_t tot_ddbs;
++      MOVE MEMORY 4, saved_dsa, addr_dsa
 +
-       uint16_t        iocb_cnt;
-       uint16_t        iocb_hiwat;
-@@ -344,6 +348,7 @@
-       uint32_t firmware_version[2];
-       uint32_t patch_number;
-       uint32_t build_number;
-+      uint32_t board_id;
-       /* --- From Init_FW --- */
-       /* init_cb_t *init_cb; */
-@@ -363,7 +368,6 @@
-       /* --- From GetFwState --- */
-       uint32_t firmware_state;
--      uint32_t board_id;
-       uint32_t addl_fw_state;
-       /* Linux kernel thread */
-@@ -414,6 +418,8 @@
-       uint16_t aen_out;
-       struct aen aen_q[MAX_AEN_ENTRIES];
-+      struct ql4_aen_log aen_log;/* tracks all aens */
++at 0x0000000d : */    0xc0000004,0x00000000,0x00000000,
++/*
 +
-       /* This mutex protects several threads to do mailbox commands
-        * concurrently.
-        */
-@@ -585,10 +591,4 @@
- #define FLUSH_DDB_CHANGED_AENS         1
- #define RELOGIN_DDB_CHANGED_AENS 2
--#include "ql4_version.h"
--#include "ql4_glbl.h"
--#include "ql4_dbg.h"
--#include "ql4_inline.h"
--
--
- #endif        /*_QLA4XXX_H */
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_fw.h linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_fw.h
---- linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_fw.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_fw.h     2008-01-02 13:56:37.000000000 -0500
-@@ -20,143 +20,23 @@
-  *************************************************************************/
- struct port_ctrl_stat_regs {
--      __le32 ext_hw_conf;     /*  80 x50  R/W */
--      __le32 intChipConfiguration; /*  84 x54 */
--      __le32 port_ctrl;       /*  88 x58 */
--      __le32 port_status;     /*  92 x5c */
--      __le32 HostPrimMACHi;   /*  96 x60 */
--      __le32 HostPrimMACLow;  /* 100 x64 */
--      __le32 HostSecMACHi;    /* 104 x68 */
--      __le32 HostSecMACLow;   /* 108 x6c */
--      __le32 EPPrimMACHi;     /* 112 x70 */
--      __le32 EPPrimMACLow;    /* 116 x74 */
--      __le32 EPSecMACHi;      /* 120 x78 */
--      __le32 EPSecMACLow;     /* 124 x7c */
--      __le32 HostPrimIPHi;    /* 128 x80 */
--      __le32 HostPrimIPMidHi; /* 132 x84 */
--      __le32 HostPrimIPMidLow;        /* 136 x88 */
--      __le32 HostPrimIPLow;   /* 140 x8c */
--      __le32 HostSecIPHi;     /* 144 x90 */
--      __le32 HostSecIPMidHi;  /* 148 x94 */
--      __le32 HostSecIPMidLow; /* 152 x98 */
--      __le32 HostSecIPLow;    /* 156 x9c */
--      __le32 EPPrimIPHi;      /* 160 xa0 */
--      __le32 EPPrimIPMidHi;   /* 164 xa4 */
--      __le32 EPPrimIPMidLow;  /* 168 xa8 */
--      __le32 EPPrimIPLow;     /* 172 xac */
--      __le32 EPSecIPHi;       /* 176 xb0 */
--      __le32 EPSecIPMidHi;    /* 180 xb4 */
--      __le32 EPSecIPMidLow;   /* 184 xb8 */
--      __le32 EPSecIPLow;      /* 188 xbc */
--      __le32 IPReassemblyTimeout; /* 192 xc0 */
--      __le32 EthMaxFramePayload; /* 196 xc4 */
--      __le32 TCPMaxWindowSize; /* 200 xc8 */
--      __le32 TCPCurrentTimestampHi; /* 204 xcc */
--      __le32 TCPCurrentTimestampLow; /* 208 xd0 */
--      __le32 LocalRAMAddress; /* 212 xd4 */
--      __le32 LocalRAMData;    /* 216 xd8 */
--      __le32 PCSReserved1;    /* 220 xdc */
--      __le32 gp_out;          /* 224 xe0 */
--      __le32 gp_in;           /* 228 xe4 */
--      __le32 ProbeMuxAddr;    /* 232 xe8 */
--      __le32 ProbeMuxData;    /* 236 xec */
--      __le32 ERMQueueBaseAddr0; /* 240 xf0 */
--      __le32 ERMQueueBaseAddr1; /* 244 xf4 */
--      __le32 MACConfiguration; /* 248 xf8 */
--      __le32 port_err_status; /* 252 xfc  COR */
-+      __le32 ext_hw_conf;     /* 0x50  R/W */
-+      __le32 rsrvd0;          /* 0x54 */
-+      __le32 port_ctrl;       /* 0x58 */
-+      __le32 port_status;     /* 0x5c */
-+      __le32 rsrvd1[32];      /* 0x60-0xdf */
-+      __le32 gp_out;          /* 0xe0 */
-+      __le32 gp_in;           /* 0xe4 */
-+      __le32 rsrvd2[5];       /* 0xe8-0xfb */
-+      __le32 port_err_status; /* 0xfc */
- };
- struct host_mem_cfg_regs {
--      __le32 NetRequestQueueOut; /*  80 x50 */
--      __le32 NetRequestQueueOutAddrHi; /*  84 x54 */
--      __le32 NetRequestQueueOutAddrLow; /*  88 x58 */
--      __le32 NetRequestQueueBaseAddrHi; /*  92 x5c */
--      __le32 NetRequestQueueBaseAddrLow; /*  96 x60 */
--      __le32 NetRequestQueueLength; /* 100 x64 */
--      __le32 NetResponseQueueIn; /* 104 x68 */
--      __le32 NetResponseQueueInAddrHi; /* 108 x6c */
--      __le32 NetResponseQueueInAddrLow; /* 112 x70 */
--      __le32 NetResponseQueueBaseAddrHi; /* 116 x74 */
--      __le32 NetResponseQueueBaseAddrLow; /* 120 x78 */
--      __le32 NetResponseQueueLength; /* 124 x7c */
--      __le32 req_q_out;       /* 128 x80 */
--      __le32 RequestQueueOutAddrHi; /* 132 x84 */
--      __le32 RequestQueueOutAddrLow; /* 136 x88 */
--      __le32 RequestQueueBaseAddrHi; /* 140 x8c */
--      __le32 RequestQueueBaseAddrLow; /* 144 x90 */
--      __le32 RequestQueueLength; /* 148 x94 */
--      __le32 ResponseQueueIn; /* 152 x98 */
--      __le32 ResponseQueueInAddrHi; /* 156 x9c */
--      __le32 ResponseQueueInAddrLow; /* 160 xa0 */
--      __le32 ResponseQueueBaseAddrHi; /* 164 xa4 */
--      __le32 ResponseQueueBaseAddrLow; /* 168 xa8 */
--      __le32 ResponseQueueLength; /* 172 xac */
--      __le32 NetRxLargeBufferQueueOut; /* 176 xb0 */
--      __le32 NetRxLargeBufferQueueBaseAddrHi; /* 180 xb4 */
--      __le32 NetRxLargeBufferQueueBaseAddrLow; /* 184 xb8 */
--      __le32 NetRxLargeBufferQueueLength; /* 188 xbc */
--      __le32 NetRxLargeBufferLength; /* 192 xc0 */
--      __le32 NetRxSmallBufferQueueOut; /* 196 xc4 */
--      __le32 NetRxSmallBufferQueueBaseAddrHi; /* 200 xc8 */
--      __le32 NetRxSmallBufferQueueBaseAddrLow; /* 204 xcc */
--      __le32 NetRxSmallBufferQueueLength; /* 208 xd0 */
--      __le32 NetRxSmallBufferLength; /* 212 xd4 */
--      __le32 HMCReserved0[10]; /* 216 xd8 */
--};
--
--struct local_ram_cfg_regs {
--      __le32 BufletSize;      /*  80 x50 */
--      __le32 BufletMaxCount;  /*  84 x54 */
--      __le32 BufletCurrCount; /*  88 x58 */
--      __le32 BufletPauseThresholdCount; /*  92 x5c */
--      __le32 BufletTCPWinThresholdHi; /*  96 x60 */
--      __le32 BufletTCPWinThresholdLow; /* 100 x64 */
--      __le32 IPHashTableBaseAddr; /* 104 x68 */
--      __le32 IPHashTableSize; /* 108 x6c */
--      __le32 TCPHashTableBaseAddr; /* 112 x70 */
--      __le32 TCPHashTableSize; /* 116 x74 */
--      __le32 NCBAreaBaseAddr; /* 120 x78 */
--      __le32 NCBMaxCount;     /* 124 x7c */
--      __le32 NCBCurrCount;    /* 128 x80 */
--      __le32 DRBAreaBaseAddr; /* 132 x84 */
--      __le32 DRBMaxCount;     /* 136 x88 */
--      __le32 DRBCurrCount;    /* 140 x8c */
--      __le32 LRCReserved[28]; /* 144 x90 */
--};
--
--struct prot_stat_regs {
--      __le32 MACTxFrameCount; /*  80 x50   R */
--      __le32 MACTxByteCount;  /*  84 x54   R */
--      __le32 MACRxFrameCount; /*  88 x58   R */
--      __le32 MACRxByteCount;  /*  92 x5c   R */
--      __le32 MACCRCErrCount;  /*  96 x60   R */
--      __le32 MACEncErrCount;  /* 100 x64   R */
--      __le32 MACRxLengthErrCount; /* 104 x68   R */
--      __le32 IPTxPacketCount; /* 108 x6c   R */
--      __le32 IPTxByteCount;   /* 112 x70   R */
--      __le32 IPTxFragmentCount; /* 116 x74   R */
--      __le32 IPRxPacketCount; /* 120 x78   R */
--      __le32 IPRxByteCount;   /* 124 x7c   R */
--      __le32 IPRxFragmentCount; /* 128 x80   R */
--      __le32 IPDatagramReassemblyCount; /* 132 x84   R */
--      __le32 IPV6RxPacketCount; /* 136 x88   R */
--      __le32 IPErrPacketCount; /* 140 x8c   R */
--      __le32 IPReassemblyErrCount; /* 144 x90   R */
--      __le32 TCPTxSegmentCount; /* 148 x94   R */
--      __le32 TCPTxByteCount;  /* 152 x98   R */
--      __le32 TCPRxSegmentCount; /* 156 x9c   R */
--      __le32 TCPRxByteCount;  /* 160 xa0   R */
--      __le32 TCPTimerExpCount; /* 164 xa4   R */
--      __le32 TCPRxAckCount;   /* 168 xa8   R */
--      __le32 TCPTxAckCount;   /* 172 xac   R */
--      __le32 TCPRxErrOOOCount; /* 176 xb0   R */
--      __le32 PSReserved0;     /* 180 xb4 */
--      __le32 TCPRxWindowProbeUpdateCount; /* 184 xb8   R */
--      __le32 ECCErrCorrectionCount; /* 188 xbc   R */
--      __le32 PSReserved1[16]; /* 192 xc0 */
-+      __le32 rsrvd0[12];      /* 0x50-0x79 */
-+      __le32 req_q_out;       /* 0x80 */
-+      __le32 rsrvd1[31];      /* 0x84-0xFF */
- };
--
- /*  remote register set (access via PCI memory read/write) */
- struct isp_reg {
- #define MBOX_REG_COUNT 8
-@@ -207,11 +87,7 @@
-                       union {
-                               struct port_ctrl_stat_regs p0;
-                               struct host_mem_cfg_regs p1;
--                              struct local_ram_cfg_regs p2;
--                              struct prot_stat_regs p3;
--                              __le32 r_union[44];
-                       };
--
-               } __attribute__ ((packed)) isp4022;
-       } u2;
- };                            /* 256 x100 */
-@@ -296,6 +172,7 @@
- /*  ISP Semaphore definitions */
- /*  ISP General Purpose Output definitions */
-+#define GPOR_TOPCAT_RESET                     0x00000004
- /*  shadow registers (DMA'd from HA to system memory.  read only) */
- struct shadow_regs {
-@@ -337,6 +214,7 @@
- /*  Mailbox command definitions */
- #define MBOX_CMD_ABOUT_FW                     0x0009
-+#define MBOX_CMD_PING                         0x000B
- #define MBOX_CMD_LUN_RESET                    0x0016
- #define MBOX_CMD_GET_MANAGEMENT_DATA          0x001E
- #define MBOX_CMD_GET_FW_STATUS                        0x001F
-@@ -364,6 +242,17 @@
- #define MBOX_CMD_GET_FW_STATE                 0x0069
- #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A
- #define MBOX_CMD_RESTORE_FACTORY_DEFAULTS     0x0087
-+#define MBOX_CMD_SET_ACB                      0x0088
-+#define MBOX_CMD_GET_ACB                      0x0089
-+#define MBOX_CMD_DISABLE_ACB                  0x008A
-+#define MBOX_CMD_GET_IPV6_NEIGHBOR_CACHE      0x008B
-+#define MBOX_CMD_GET_IPV6_DEST_CACHE          0x008C
-+#define MBOX_CMD_GET_IPV6_DEF_ROUTER_LIST     0x008D
-+#define MBOX_CMD_GET_IPV6_LCL_PREFIX_LIST     0x008E
-+#define MBOX_CMD_SET_IPV6_NEIGHBOR_CACHE      0x0090
-+#define MBOX_CMD_GET_IP_ADDR_STATE            0x0091
-+#define MBOX_CMD_SEND_IPV6_ROUTER_SOL         0x0092
-+#define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR 0x0093
- /* Mailbox 1 */
- #define FW_STATE_READY                                0x0000
-@@ -409,6 +298,16 @@
- #define MBOX_ASTS_DHCP_LEASE_EXPIRED          0x801D
- #define MBOX_ASTS_DHCP_LEASE_ACQUIRED         0x801F
- #define MBOX_ASTS_ISNS_UNSOLICITED_PDU_RECEIVED 0x8021
-+#define MBOX_ASTS_DUPLICATE_IP                        0x8025
-+#define MBOX_ASTS_ARP_COMPLETE                        0x8026
-+#define MBOX_ASTS_SUBNET_STATE_CHANGE         0x8027
-+#define MBOX_ASTS_RESPONSE_QUEUE_FULL         0x8028
-+#define MBOX_ASTS_IP_ADDR_STATE_CHANGED               0x8029
-+#define MBOX_ASTS_IPV6_PREFIX_EXPIRED         0x802B
-+#define MBOX_ASTS_IPV6_ND_PREFIX_IGNORED      0x802C
-+#define MBOX_ASTS_IPV6_LCL_PREFIX_IGNORED     0x802D
-+#define MBOX_ASTS_ICMPV6_ERROR_MSG_RCVD               0x802E
 +
- #define ISNS_EVENT_DATA_RECEIVED              0x0000
- #define ISNS_EVENT_CONNECTION_OPENED          0x0001
- #define ISNS_EVENT_CONNECTION_FAILED          0x0002
-@@ -418,137 +317,166 @@
- /*************************************************************************/
- /* Host Adapter Initialization Control Block (from host) */
--struct init_fw_ctrl_blk {
--      uint8_t Version;        /* 00 */
--      uint8_t Control;        /* 01 */
-+struct addr_ctrl_blk {
-+      uint8_t version;        /* 00 */
-+      uint8_t control;        /* 01 */
--      uint16_t FwOptions;     /* 02-03 */
-+      uint16_t fw_options;    /* 02-03 */
- #define        FWOPT_HEARTBEAT_ENABLE           0x1000
- #define        FWOPT_SESSION_MODE               0x0040
- #define        FWOPT_INITIATOR_MODE             0x0020
- #define        FWOPT_TARGET_MODE                0x0010
--      uint16_t ExecThrottle;  /* 04-05 */
--      uint8_t RetryCount;     /* 06 */
--      uint8_t RetryDelay;     /* 07 */
--      uint16_t MaxEthFrPayloadSize;   /* 08-09 */
--      uint16_t AddFwOptions;  /* 0A-0B */
--
--      uint8_t HeartbeatInterval;      /* 0C */
--      uint8_t InstanceNumber; /* 0D */
--      uint16_t RES2;          /* 0E-0F */
--      uint16_t ReqQConsumerIndex;     /* 10-11 */
--      uint16_t ComplQProducerIndex;   /* 12-13 */
--      uint16_t ReqQLen;       /* 14-15 */
--      uint16_t ComplQLen;     /* 16-17 */
--      uint32_t ReqQAddrLo;    /* 18-1B */
--      uint32_t ReqQAddrHi;    /* 1C-1F */
--      uint32_t ComplQAddrLo;  /* 20-23 */
--      uint32_t ComplQAddrHi;  /* 24-27 */
--      uint32_t ShadowRegBufAddrLo;    /* 28-2B */
--      uint32_t ShadowRegBufAddrHi;    /* 2C-2F */
--
--      uint16_t iSCSIOptions;  /* 30-31 */
--
--      uint16_t TCPOptions;    /* 32-33 */
--
--      uint16_t IPOptions;     /* 34-35 */
--
--      uint16_t MaxPDUSize;    /* 36-37 */
--      uint16_t RcvMarkerInt;  /* 38-39 */
--      uint16_t SndMarkerInt;  /* 3A-3B */
--      uint16_t InitMarkerlessInt;     /* 3C-3D */
--      uint16_t FirstBurstSize;        /* 3E-3F */
--      uint16_t DefaultTime2Wait;      /* 40-41 */
--      uint16_t DefaultTime2Retain;    /* 42-43 */
--      uint16_t MaxOutStndngR2T;       /* 44-45 */
--      uint16_t KeepAliveTimeout;      /* 46-47 */
--      uint16_t PortNumber;    /* 48-49 */
--      uint16_t MaxBurstSize;  /* 4A-4B */
--      uint32_t RES4;          /* 4C-4F */
--      uint8_t IPAddr[4];      /* 50-53 */
--      uint8_t RES5[12];       /* 54-5F */
--      uint8_t SubnetMask[4];  /* 60-63 */
--      uint8_t RES6[12];       /* 64-6F */
--      uint8_t GatewayIPAddr[4];       /* 70-73 */
--      uint8_t RES7[12];       /* 74-7F */
--      uint8_t PriDNSIPAddr[4];        /* 80-83 */
--      uint8_t SecDNSIPAddr[4];        /* 84-87 */
--      uint8_t RES8[8];        /* 88-8F */
--      uint8_t Alias[32];      /* 90-AF */
--      uint8_t TargAddr[8];    /* B0-B7 *//* /FIXME: Remove?? */
--      uint8_t CHAPNameSecretsTable[8];        /* B8-BF */
--      uint8_t EthernetMACAddr[6];     /* C0-C5 */
--      uint16_t TargetPortalGroup;     /* C6-C7 */
--      uint8_t SendScale;      /* C8    */
--      uint8_t RecvScale;      /* C9    */
--      uint8_t TypeOfService;  /* CA    */
--      uint8_t Time2Live;      /* CB    */
--      uint16_t VLANPriority;  /* CC-CD */
--      uint16_t Reserved8;     /* CE-CF */
--      uint8_t SecIPAddr[4];   /* D0-D3 */
--      uint8_t Reserved9[12];  /* D4-DF */
--      uint8_t iSNSIPAddr[4];  /* E0-E3 */
--      uint16_t iSNSServerPortNumber;  /* E4-E5 */
--      uint8_t Reserved10[10]; /* E6-EF */
--      uint8_t SLPDAIPAddr[4]; /* F0-F3 */
--      uint8_t Reserved11[12]; /* F4-FF */
--      uint8_t iSCSINameString[256];   /* 100-1FF */
-+      uint16_t exec_throttle; /* 04-05 */
-+      uint8_t zio_count;      /* 06 */
-+      uint8_t res0;   /* 07 */
-+      uint16_t eth_mtu_size;  /* 08-09 */
-+      uint16_t add_fw_options;        /* 0A-0B */
-+
-+      uint8_t hb_interval;    /* 0C */
-+      uint8_t inst_num; /* 0D */
-+      uint16_t res1;          /* 0E-0F */
-+      uint16_t rqq_consumer_idx;      /* 10-11 */
-+      uint16_t compq_producer_idx;    /* 12-13 */
-+      uint16_t rqq_len;       /* 14-15 */
-+      uint16_t compq_len;     /* 16-17 */
-+      uint32_t rqq_addr_lo;   /* 18-1B */
-+      uint32_t rqq_addr_hi;   /* 1C-1F */
-+      uint32_t compq_addr_lo; /* 20-23 */
-+      uint32_t compq_addr_hi; /* 24-27 */
-+      uint32_t shdwreg_addr_lo;       /* 28-2B */
-+      uint32_t shdwreg_addr_hi;       /* 2C-2F */
-+
-+      uint16_t iscsi_opts;    /* 30-31 */
-+      uint16_t ipv4_tcp_opts; /* 32-33 */
-+      uint16_t ipv4_ip_opts;  /* 34-35 */
-+
-+      uint16_t iscsi_max_pdu_size;    /* 36-37 */
-+      uint8_t ipv4_tos;       /* 38 */
-+      uint8_t ipv4_ttl;       /* 39 */
-+      uint8_t acb_version;    /* 3A */
-+      uint8_t res2;   /* 3B */
-+      uint16_t def_timeout;   /* 3C-3D */
-+      uint16_t iscsi_fburst_len;      /* 3E-3F */
-+      uint16_t iscsi_def_time2wait;   /* 40-41 */
-+      uint16_t iscsi_def_time2retain; /* 42-43 */
-+      uint16_t iscsi_max_outstnd_r2t; /* 44-45 */
-+      uint16_t conn_ka_timeout;       /* 46-47 */
-+      uint16_t ipv4_port;     /* 48-49 */
-+      uint16_t iscsi_max_burst_len;   /* 4A-4B */
-+      uint32_t res5;          /* 4C-4F */
-+      uint8_t ipv4_addr[4];   /* 50-53 */
-+      uint16_t ipv4_vlan_tag; /* 54-55 */
-+      uint8_t ipv4_addr_state;        /* 56 */
-+      uint8_t ipv4_cacheid;   /* 57 */
-+      uint8_t res6[8];        /* 58-5F */
-+      uint8_t ipv4_subnet[4]; /* 60-63 */
-+      uint8_t res7[12];       /* 64-6F */
-+      uint8_t ipv4_gw_addr[4];        /* 70-73 */
-+      uint8_t res8[0xc];      /* 74-7F */
-+      uint8_t pri_dns_srvr_ip[4];/* 80-83 */
-+      uint8_t sec_dns_srvr_ip[4];/* 84-87 */
-+      uint16_t min_eph_port;  /* 88-89 */
-+      uint16_t max_eph_port;  /* 8A-8B */
-+      uint8_t res9[4];        /* 8C-8F */
-+      uint8_t iscsi_alias[32];/* 90-AF */
-+      uint8_t res9_1[0x16];   /* B0-C5 */
-+      uint16_t tgt_portal_grp;/* C6-C7 */
-+      uint8_t abort_timer;    /* C8    */
-+      uint8_t ipv4_tcp_wsf;   /* C9    */
-+      uint8_t res10[6];       /* CA-CF */
-+      uint8_t ipv4_sec_ip_addr[4];    /* D0-D3 */
-+      uint8_t ipv4_dhcp_vid_len;      /* D4 */
-+      uint8_t ipv4_dhcp_vid[11];      /* D5-DF */
-+      uint8_t res11[20];      /* E0-F3 */
-+      uint8_t ipv4_dhcp_alt_cid_len;  /* F4 */
-+      uint8_t ipv4_dhcp_alt_cid[11];  /* F5-FF */
-+      uint8_t iscsi_name[224];        /* 100-1DF */
-+      uint8_t res12[32];      /* 1E0-1FF */
-+      uint32_t cookie;        /* 200-203 */
-+      uint16_t ipv6_port;     /* 204-205 */
-+      uint16_t ipv6_opts;     /* 206-207 */
-+      uint16_t ipv6_addtl_opts;       /* 208-209 */
-+      uint16_t ipv6_tcp_opts; /* 20A-20B */
-+      uint8_t ipv6_tcp_wsf;   /* 20C */
-+      uint16_t ipv6_flow_lbl; /* 20D-20F */
-+      uint8_t ipv6_gw_addr[16];       /* 210-21F */
-+      uint16_t ipv6_vlan_tag; /* 220-221 */
-+      uint8_t ipv6_lnk_lcl_addr_state;/* 222 */
-+      uint8_t ipv6_addr0_state;       /* 223 */
-+      uint8_t ipv6_addr1_state;       /* 224 */
-+      uint8_t ipv6_gw_state;  /* 225 */
-+      uint8_t ipv6_traffic_class;     /* 226 */
-+      uint8_t ipv6_hop_limit; /* 227 */
-+      uint8_t ipv6_if_id[8];  /* 228-22F */
-+      uint8_t ipv6_addr0[16]; /* 230-23F */
-+      uint8_t ipv6_addr1[16]; /* 240-24F */
-+      uint32_t ipv6_nd_reach_time;    /* 250-253 */
-+      uint32_t ipv6_nd_rexmit_timer;  /* 254-257 */
-+      uint32_t ipv6_nd_stale_timeout; /* 258-25B */
-+      uint8_t ipv6_dup_addr_detect_count;     /* 25C */
-+      uint8_t ipv6_cache_id;  /* 25D */
-+      uint8_t res13[18];      /* 25E-26F */
-+      uint32_t ipv6_gw_advrt_mtu;     /* 270-273 */
-+      uint8_t res14[140];     /* 274-2FF */
-+};
 +
-+struct init_fw_ctrl_blk {
-+      struct addr_ctrl_blk pri;
-+      struct addr_ctrl_blk sec;
- };
- /*************************************************************************/
- struct dev_db_entry {
--      uint8_t options;        /* 00 */
-+      uint16_t options;       /* 00-01 */
- #define DDB_OPT_DISC_SESSION  0x10
- #define DDB_OPT_TARGET              0x02 /* device is a target */
--      uint8_t control;        /* 01 */
--
--      uint16_t exeThrottle;   /* 02-03 */
--      uint16_t exeCount;      /* 04-05 */
--      uint8_t retryCount;     /* 06    */
--      uint8_t retryDelay;     /* 07    */
--      uint16_t iSCSIOptions;  /* 08-09 */
--
--      uint16_t TCPOptions;    /* 0A-0B */
--
--      uint16_t IPOptions;     /* 0C-0D */
--
--      uint16_t maxPDUSize;    /* 0E-0F */
--      uint16_t rcvMarkerInt;  /* 10-11 */
--      uint16_t sndMarkerInt;  /* 12-13 */
--      uint16_t iSCSIMaxSndDataSegLen; /* 14-15 */
--      uint16_t firstBurstSize;        /* 16-17 */
--      uint16_t minTime2Wait;  /* 18-19 : RA :default_time2wait */
--      uint16_t maxTime2Retain;        /* 1A-1B */
--      uint16_t maxOutstndngR2T;       /* 1C-1D */
--      uint16_t keepAliveTimeout;      /* 1E-1F */
--      uint8_t ISID[6];        /* 20-25 big-endian, must be converted
-+      uint16_t exec_throttle; /* 02-03 */
-+      uint16_t exec_count;    /* 04-05 */
-+      uint16_t res0;  /* 06-07 */
-+      uint16_t iscsi_options; /* 08-09 */
-+      uint16_t tcp_options;   /* 0A-0B */
-+      uint16_t ip_options;    /* 0C-0D */
-+      uint16_t iscsi_max_rcv_data_seg_len;    /* 0E-0F */
-+      uint32_t res1;  /* 10-13 */
-+      uint16_t iscsi_max_snd_data_seg_len;    /* 14-15 */
-+      uint16_t iscsi_first_burst_len; /* 16-17 */
-+      uint16_t iscsi_def_time2wait;   /* 18-19 */
-+      uint16_t iscsi_def_time2retain; /* 1A-1B */
-+      uint16_t iscsi_max_outsnd_r2t;  /* 1C-1D */
-+      uint16_t ka_timeout;    /* 1E-1F */
-+      uint8_t isid[6];        /* 20-25 big-endian, must be converted
-                                * to little-endian */
--      uint16_t TSID;          /* 26-27 */
--      uint16_t portNumber;    /* 28-29 */
--      uint16_t maxBurstSize;  /* 2A-2B */
--      uint16_t taskMngmntTimeout;     /* 2C-2D */
--      uint16_t reserved1;     /* 2E-2F */
--      uint8_t ipAddr[0x10];   /* 30-3F */
--      uint8_t iSCSIAlias[0x20];       /* 40-5F */
--      uint8_t targetAddr[0x20];       /* 60-7F */
--      uint8_t userID[0x20];   /* 80-9F */
--      uint8_t password[0x20]; /* A0-BF */
--      uint8_t iscsiName[0x100];       /* C0-1BF : xxzzy Make this a
-+      uint16_t tsid;          /* 26-27 */
-+      uint16_t port;  /* 28-29 */
-+      uint16_t iscsi_max_burst_len;   /* 2A-2B */
-+      uint16_t def_timeout;   /* 2C-2D */
-+      uint16_t res2;  /* 2E-2F */
-+      uint8_t ip_addr[0x10];  /* 30-3F */
-+      uint8_t iscsi_alias[0x20];      /* 40-5F */
-+      uint8_t tgt_addr[0x20]; /* 60-7F */
-+      uint16_t mss;   /* 80-81 */
-+      uint16_t res3;  /* 82-83 */
-+      uint16_t lcl_port;      /* 84-85 */
-+      uint8_t ipv4_tos;       /* 86 */
-+      uint16_t ipv6_flow_lbl; /* 87-89 */
-+      uint8_t res4[0x36];     /* 8A-BF */
-+      uint8_t iscsi_name[0xE0];       /* C0-19F : xxzzy Make this a
-                                        * pointer to a string so we
-                                        * don't have to reserve soooo
-                                        * much RAM */
--      uint16_t ddbLink;       /* 1C0-1C1 */
--      uint16_t CHAPTableIndex; /* 1C2-1C3 */
--      uint16_t TargetPortalGroup; /* 1C4-1C5 */
--      uint16_t reserved2[2];  /* 1C6-1C7 */
--      uint32_t statSN;        /* 1C8-1CB */
--      uint32_t expStatSN;     /* 1CC-1CF */
--      uint16_t reserved3[0x2C]; /* 1D0-1FB */
--      uint16_t ddbValidCookie; /* 1FC-1FD */
--      uint16_t ddbValidSize;  /* 1FE-1FF */
-+      uint8_t ipv6_addr[0x10];/* 1A0-1AF */
-+      uint8_t res5[0x10];     /* 1B0-1BF */
-+      uint16_t ddb_link;      /* 1C0-1C1 */
-+      uint16_t chap_tbl_idx;  /* 1C2-1C3 */
-+      uint16_t tgt_portal_grp; /* 1C4-1C5 */
-+      uint8_t tcp_xmt_wsf;    /* 1C6 */
-+      uint8_t tcp_rcv_wsf;    /* 1C7 */
-+      uint32_t stat_sn;       /* 1C8-1CB */
-+      uint32_t exp_stat_sn;   /* 1CC-1CF */
-+      uint8_t res6[0x30];     /* 1D0-1FF */
- };
- /*************************************************************************/
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_glbl.h linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_glbl.h
---- linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_glbl.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_glbl.h   2008-01-02 13:56:37.000000000 -0500
-@@ -8,6 +8,9 @@
- #ifndef __QLA4x_GBL_H
- #define       __QLA4x_GBL_H
-+struct iscsi_cls_conn;
++      CALL select
 +
-+void qla4xxx_hw_reset(struct scsi_qla_host *ha);
- int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a);
- int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port);
- int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb);
-@@ -58,11 +61,13 @@
- void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
-                                      uint32_t intr_status);
- int qla4xxx_init_rings(struct scsi_qla_host * ha);
--struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index);
-+struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
-+                                      uint32_t index);
- void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb);
- int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
- int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
-                               uint32_t fw_ddb_index, uint32_t state);
-+void qla4xxx_dump_buffer(void *b, uint32_t size);
- extern int ql4xextended_error_logging;
- extern int ql4xdiscoverywait;
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_init.c linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_init.c
---- linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_init.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_init.c   2008-01-02 13:56:37.000000000 -0500
-@@ -6,6 +6,9 @@
-  */
- #include "ql4_def.h"
-+#include "ql4_glbl.h"
-+#include "ql4_dbg.h"
-+#include "ql4_inline.h"
- static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
-                                           uint32_t fw_ddb_index);
-@@ -300,12 +303,12 @@
-       if (!qla4xxx_fw_ready(ha))
-               return status;
--      set_bit(AF_ONLINE, &ha->flags);
-       return qla4xxx_get_firmware_status(ha);
- }
- static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha,
--                                             uint32_t fw_ddb_index)
-+                                              uint32_t fw_ddb_index,
-+                                              uint32_t *new_tgt)
- {
-       struct dev_db_entry *fw_ddb_entry = NULL;
-       dma_addr_t fw_ddb_entry_dma;
-@@ -313,6 +316,7 @@
-       int found = 0;
-       uint32_t device_state;
-+      *new_tgt = 0;
-       /* Make sure the dma buffer is valid */
-       fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
-                                         sizeof(*fw_ddb_entry),
-@@ -337,7 +341,7 @@
-       DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no,
-                     __func__, fw_ddb_index));
-       list_for_each_entry(ddb_entry, &ha->ddb_list, list) {
--              if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsiName,
-+              if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name,
-                          ISCSI_NAME_SIZE) == 0) {
-                       found++;
-                       break;
-@@ -348,6 +352,7 @@
-               DEBUG2(printk("scsi%ld: %s: ddb[%d] not found - allocating "
-                             "new ddb\n", ha->host_no, __func__,
-                             fw_ddb_index));
-+              *new_tgt = 1;
-               ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
-       }
-@@ -409,26 +414,26 @@
-       }
-       status = QLA_SUCCESS;
--      ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->TSID);
-+      ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid);
-       ddb_entry->task_mgmt_timeout =
--              le16_to_cpu(fw_ddb_entry->taskMngmntTimeout);
-+              le16_to_cpu(fw_ddb_entry->def_timeout);
-       ddb_entry->CmdSn = 0;
--      ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exeThrottle);
-+      ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exec_throttle);
-       ddb_entry->default_relogin_timeout =
--              le16_to_cpu(fw_ddb_entry->taskMngmntTimeout);
--      ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->minTime2Wait);
-+              le16_to_cpu(fw_ddb_entry->def_timeout);
-+      ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
-       /* Update index in case it changed */
-       ddb_entry->fw_ddb_index = fw_ddb_index;
-       ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
--      ddb_entry->port = le16_to_cpu(fw_ddb_entry->portNumber);
--      ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->TargetPortalGroup);
--      memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsiName[0],
-+      ddb_entry->port = le16_to_cpu(fw_ddb_entry->port);
-+      ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
-+      memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],
-              min(sizeof(ddb_entry->iscsi_name),
--                 sizeof(fw_ddb_entry->iscsiName)));
--      memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ipAddr[0],
--             min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ipAddr)));
-+                 sizeof(fw_ddb_entry->iscsi_name)));
-+      memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0],
-+             min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr)));
-       DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n",
-                     ha->host_no, __func__, fw_ddb_index,
-@@ -495,6 +500,7 @@
-       uint32_t ddb_state;
-       uint32_t conn_err, err_code;
-       struct ddb_entry *ddb_entry;
-+      uint32_t new_tgt;
-       dev_info(&ha->pdev->dev, "Initializing DDBs ...\n");
-       for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES;
-@@ -526,8 +532,19 @@
-                                             "completed "
-                                             "or access denied failure\n",
-                                             ha->host_no, __func__));
--                      } else
-+                      } else {
-                               qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0);
-+                              if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index,
-+                                      NULL, 0, NULL, &next_fw_ddb_index,
-+                                      &ddb_state, &conn_err, NULL, NULL)
-+                                      == QLA_ERROR) {
-+                                      DEBUG2(printk("scsi%ld: %s:"
-+                                              "get_ddb_entry %d failed\n",
-+                                              ha->host_no,
-+                                              __func__, fw_ddb_index));
-+                                      return QLA_ERROR;
-+                              }
-+                      }
-               }
-               if (ddb_state != DDB_DS_SESSION_ACTIVE)
-@@ -540,7 +557,7 @@
-                             ha->host_no, __func__, fw_ddb_index));
-               /* Add DDB to internal our ddb list. */
--              ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index);
-+              ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
-               if (ddb_entry == NULL) {
-                       DEBUG2(printk("scsi%ld: %s: Unable to allocate memory "
-                                     "for device at fw_ddb_index %d\n",
-@@ -865,21 +882,20 @@
- static void qla4x00_pci_config(struct scsi_qla_host *ha)
- {
--      uint16_t w, mwi;
-+      uint16_t w;
-+      int status;
-       dev_info(&ha->pdev->dev, "Configuring PCI space...\n");
-       pci_set_master(ha->pdev);
--      mwi = 0;
--      if (pci_set_mwi(ha->pdev))
--              mwi = PCI_COMMAND_INVALIDATE;
-+      status = pci_set_mwi(ha->pdev);
-       /*
-        * We want to respect framework's setting of PCI configuration space
-        * command register and also want to make sure that all bits of
-        * interest to us are properly set in command register.
-        */
-       pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
--      w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
-+      w |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
-       w &= ~PCI_COMMAND_INTX_DISABLE;
-       pci_write_config_word(ha->pdev, PCI_COMMAND, w);
- }
-@@ -911,6 +927,9 @@
-               writel(set_rmask(NVR_WRITE_ENABLE),
-                      &ha->reg->u1.isp4022.nvram);
-+        writel(2, &ha->reg->mailbox[6]);
-+        readl(&ha->reg->mailbox[6]);
++at 0x00000010 : */    0x88080000,0x000001f8,
++/*
++; Handle the phase mismatch which may have resulted from the 
++; MOVE FROM dsa_msgout if we returned here.  The CLEAR ATN 
++; may or may not be necessary, and we should update script_asm.pl
++; to handle multiple pieces.
++    CLEAR ATN
 +
-       writel(set_rmask(CSR_BOOT_ENABLE), &ha->reg->ctrl_status);
-       readl(&ha->reg->ctrl_status);
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
-@@ -958,25 +977,25 @@
-       return status;
- }
--int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha)
-+int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
- {
--#define QL4_LOCK_DRVR_WAIT    30
-+#define QL4_LOCK_DRVR_WAIT    60
- #define QL4_LOCK_DRVR_SLEEP   1
-       int drvr_wait = QL4_LOCK_DRVR_WAIT;
-       while (drvr_wait) {
--              if (ql4xxx_lock_drvr(ha) == 0) {
-+              if (ql4xxx_lock_drvr(a) == 0) {
-                       ssleep(QL4_LOCK_DRVR_SLEEP);
-                       if (drvr_wait) {
-                               DEBUG2(printk("scsi%ld: %s: Waiting for "
--                                            "Global Init Semaphore(%d)...n",
--                                            ha->host_no,
-+                                            "Global Init Semaphore(%d)...\n",
-+                                            a->host_no,
-                                             __func__, drvr_wait));
-                       }
-                       drvr_wait -= QL4_LOCK_DRVR_SLEEP;
-               } else {
-                       DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
--                                    "acquired.n", ha->host_no, __func__));
-+                                    "acquired\n", a->host_no, __func__));
-                       return QLA_SUCCESS;
-               }
-       }
-@@ -1125,17 +1144,17 @@
-       /* Initialize the Host adapter request/response queues and firmware */
-       if (qla4xxx_start_firmware(ha) == QLA_ERROR)
--              return status;
-+              goto exit_init_hba;
-       if (qla4xxx_validate_mac_address(ha) == QLA_ERROR)
--              return status;
-+              goto exit_init_hba;
-       if (qla4xxx_init_local_data(ha) == QLA_ERROR)
--              return status;
-+              goto exit_init_hba;
-       status = qla4xxx_init_firmware(ha);
-       if (status == QLA_ERROR)
--              return status;
-+              goto exit_init_hba;
-       /*
-        * FW is waiting to get an IP address from DHCP server: Skip building
-@@ -1143,12 +1162,12 @@
-        * followed by 0x8014 aen" to trigger the tgt discovery process.
-        */
-       if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS)
--              return status;
-+              goto exit_init_online;
-       /* Skip device discovery if ip and subnet is zero */
-       if (memcmp(ha->ip_address, ip_address, IP_ADDR_LEN) == 0 ||
-           memcmp(ha->subnet_mask, ip_address, IP_ADDR_LEN) == 0)
--              return status;
-+              goto exit_init_online;
-       if (renew_ddb_list == PRESERVE_DDB_LIST) {
-               /*
-@@ -1177,9 +1196,10 @@
-                             ha->host_no));
-       }
-- exit_init_hba:
-+exit_init_online:
-+      set_bit(AF_ONLINE, &ha->flags);
-+exit_init_hba:
-       return status;
--
- }
- /**
-@@ -1193,9 +1213,10 @@
-                                          uint32_t fw_ddb_index)
- {
-       struct ddb_entry * ddb_entry;
-+      uint32_t new_tgt;
-       /* First allocate a device structure */
--      ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index);
-+      ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
-       if (ddb_entry == NULL) {
-               DEBUG2(printk(KERN_WARNING
-                             "scsi%ld: Unable to allocate memory to add "
-@@ -1203,6 +1224,18 @@
-               return;
-       }
-+      if (!new_tgt && (ddb_entry->fw_ddb_index != fw_ddb_index)) {
-+              /* Target has been bound to a new fw_ddb_index */
-+              qla4xxx_free_ddb(ha, ddb_entry);
-+              ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
-+              if (ddb_entry == NULL) {
-+                      DEBUG2(printk(KERN_WARNING
-+                              "scsi%ld: Unable to allocate memory"
-+                              " to add fw_ddb_index %d\n",
-+                              ha->host_no, fw_ddb_index));
-+                      return;
-+              }
-+      }
-       if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) ==
-                                   QLA_ERROR) {
-               ha->fw_ddb_index_map[fw_ddb_index] =
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_iocb.c linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_iocb.c
---- linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_iocb.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_iocb.c   2008-01-02 13:56:37.000000000 -0500
-@@ -6,6 +6,10 @@
-  */
- #include "ql4_def.h"
-+#include "ql4_glbl.h"
-+#include "ql4_dbg.h"
-+#include "ql4_inline.h"
++at 0x00000012 : */    0x60000008,0x00000000,
++/*
++    CLEAR ACK
++
++at 0x00000014 : */    0x60000040,0x00000000,
++/*
++
++; Replace second operand with address of JUMP instruction dest operand
++; in schedule table for this DSA.  Becomes dsa_jump_dest in 53c7,8xx.c.
++ENTRY dsa_code_fix_jump
++dsa_code_fix_jump:
++      MOVE MEMORY 4, NOP_insn, 0
++
++at 0x00000016 : */    0xc0000004,0x00000000,0x00000000,
++/*
++      JUMP select_done
++
++at 0x00000019 : */    0x80080000,0x00000230,
++/*
++
++; wrong_dsa loads the DSA register with the value of the dsa_next
++; field.
++;
++wrong_dsa:
++
++;                NOTE DSA is corrupt when we arrive here!
++
++;             Patch the MOVE MEMORY INSTRUCTION such that 
++;             the destination address is the address of the OLD 
++;             next pointer.
++;
++      MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 8
++
++at 0x0000001b : */    0xc0000004,0x00000000,0x000007ec,
++/*
++      
++;
++;     Move the _contents_ of the next pointer into the DSA register as 
++;     the next I_T_L or I_T_L_Q tupple to check against the established
++;     nexus.
++;
++      MOVE MEMORY 4, dsa_temp_next, addr_scratch
++
++at 0x0000001e : */    0xc0000004,0x00000000,0x00000000,
++/*
++      
++
++      MOVE MEMORY 4, addr_scratch, saved_dsa
++
++at 0x00000021 : */    0xc0000004,0x00000000,0x00000000,
++/*
++      MOVE MEMORY 4, saved_dsa, addr_dsa
++
++at 0x00000024 : */    0xc0000004,0x00000000,0x00000000,
++/*
++
++
++
++      JUMP reselected_check_next
++
++at 0x00000027 : */    0x80080000,0x000006f0,
++/*
++
++ABSOLUTE dsa_save_data_pointer = 0
++ENTRY dsa_code_save_data_pointer
++dsa_code_save_data_pointer:
++
++      ; When we get here, TEMP has been saved in jump_temp+4, DSA is corrupt
++      ; We MUST return with DSA correct
++      MOVE MEMORY 4, jump_temp+4, dsa_temp_addr_saved_pointer
++
++at 0x00000029 : */    0xc0000004,0x000009c8,0x00000000,
++/*
++; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
++      MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
++
++at 0x0000002c : */    0xc0000018,0x00000000,0x00000000,
++/*
++        CLEAR ACK
++
++at 0x0000002f : */    0x60000040,0x00000000,
++/*
 +
- #include <scsi/scsi_tcq.h>
-@@ -141,11 +145,13 @@
-       uint16_t avail_dsds;
-       struct data_seg_a64 *cur_dsd;
-       struct scsi_cmnd *cmd;
-+      struct scatterlist *sg;
-+      int i;
-       cmd = srb->cmd;
-       ha = srb->ha;
--      if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
-+      if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
-               /* No data being transferred */
-               cmd_entry->ttlByteCnt = __constant_cpu_to_le32(0);
-               return;
-@@ -154,14 +160,7 @@
-       avail_dsds = COMMAND_SEG;
-       cur_dsd = (struct data_seg_a64 *) & (cmd_entry->dataseg[0]);
--      /* Load data segments */
--      if (cmd->use_sg) {
--              struct scatterlist *cur_seg;
--              struct scatterlist *end_seg;
--
--              cur_seg = (struct scatterlist *)cmd->request_buffer;
--              end_seg = cur_seg + tot_dsds;
--              while (cur_seg < end_seg) {
-+      scsi_for_each_sg(cmd, sg, tot_dsds, i) {
-                       dma_addr_t sle_dma;
-                       /* Allocate additional continuation packets? */
-@@ -175,19 +174,13 @@
-                               avail_dsds = CONTINUE_SEG;
-                       }
--                      sle_dma = sg_dma_address(cur_seg);
-+              sle_dma = sg_dma_address(sg);
-                       cur_dsd->base.addrLow = cpu_to_le32(LSDW(sle_dma));
-                       cur_dsd->base.addrHigh = cpu_to_le32(MSDW(sle_dma));
--                      cur_dsd->count = cpu_to_le32(sg_dma_len(cur_seg));
-+              cur_dsd->count = cpu_to_le32(sg_dma_len(sg));
-                       avail_dsds--;
-                       cur_dsd++;
--                      cur_seg++;
--              }
--      } else {
--              cur_dsd->base.addrLow = cpu_to_le32(LSDW(srb->dma_handle));
--              cur_dsd->base.addrHigh = cpu_to_le32(MSDW(srb->dma_handle));
--              cur_dsd->count = cpu_to_le32(cmd->request_bufflen);
-       }
- }
-@@ -204,8 +197,8 @@
-       struct scsi_cmnd *cmd = srb->cmd;
-       struct ddb_entry *ddb_entry;
-       struct command_t3_entry *cmd_entry;
--      struct scatterlist *sg = NULL;
-+      int nseg;
-       uint16_t tot_dsds;
-       uint16_t req_cnt;
-@@ -233,24 +226,11 @@
-       index = (uint32_t)cmd->request->tag;
-       /* Calculate the number of request entries needed. */
--      if (cmd->use_sg) {
--              sg = (struct scatterlist *)cmd->request_buffer;
--              tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg,
--                                    cmd->sc_data_direction);
--              if (tot_dsds == 0)
-+      nseg = scsi_dma_map(cmd);
-+      if (nseg < 0)
-                       goto queuing_error;
--      } else if (cmd->request_bufflen) {
--              dma_addr_t      req_dma;
-+      tot_dsds = nseg;
--              req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
--                                       cmd->request_bufflen,
--                                       cmd->sc_data_direction);
--              if (dma_mapping_error(req_dma))
--                      goto queuing_error;
--
--              srb->dma_handle = req_dma;
--              tot_dsds = 1;
--      }
-       req_cnt = qla4xxx_calc_request_entries(tot_dsds);
-       if (ha->req_q_count < (req_cnt + 2)) {
-@@ -279,7 +259,7 @@
-       int_to_scsilun(cmd->device->lun, &cmd_entry->lun);
-       cmd_entry->cmdSeqNum = cpu_to_le32(ddb_entry->CmdSn);
--      cmd_entry->ttlByteCnt = cpu_to_le32(cmd->request_bufflen);
-+      cmd_entry->ttlByteCnt = cpu_to_le32(scsi_bufflen(cmd));
-       memcpy(cmd_entry->cdb, cmd->cmnd, cmd->cmd_len);
-       cmd_entry->dataSegCnt = cpu_to_le16(tot_dsds);
-       cmd_entry->hdr.entryCount = req_cnt;
-@@ -289,13 +269,13 @@
-        *       transferred, as the data direction bit is sometimed filled
-        *       in when there is no data to be transferred */
-       cmd_entry->control_flags = CF_NO_DATA;
--      if (cmd->request_bufflen) {
-+      if (scsi_bufflen(cmd)) {
-               if (cmd->sc_data_direction == DMA_TO_DEVICE)
-                       cmd_entry->control_flags = CF_WRITE;
-               else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
-                       cmd_entry->control_flags = CF_READ;
--              ha->bytes_xfered += cmd->request_bufflen;
-+              ha->bytes_xfered += scsi_bufflen(cmd);
-               if (ha->bytes_xfered & ~0xFFFFF){
-                       ha->total_mbytes_xferred += ha->bytes_xfered >> 20;
-                       ha->bytes_xfered &= 0xFFFFF;
-@@ -359,14 +339,9 @@
-       return QLA_SUCCESS;
- queuing_error:
-+      if (tot_dsds)
-+              scsi_dma_unmap(cmd);
--      if (cmd->use_sg && tot_dsds) {
--              sg = (struct scatterlist *) cmd->request_buffer;
--              pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
--                           cmd->sc_data_direction);
--      } else if (tot_dsds)
--              pci_unmap_single(ha->pdev, srb->dma_handle,
--                               cmd->request_bufflen, cmd->sc_data_direction);
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
-       return QLA_ERROR;
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_isr.c linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_isr.c
---- linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_isr.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_isr.c    2008-01-02 13:56:37.000000000 -0500
-@@ -6,6 +6,9 @@
-  */
- #include "ql4_def.h"
-+#include "ql4_glbl.h"
-+#include "ql4_dbg.h"
-+#include "ql4_inline.h"
- /**
-  * qla2x00_process_completed_request() - Process a Fast Post response.
-@@ -92,7 +95,7 @@
-               if (sts_entry->iscsiFlags &
-                   (ISCSI_FLAG_RESIDUAL_OVER|ISCSI_FLAG_RESIDUAL_UNDER))
--                      cmd->resid = residual;
-+                      scsi_set_resid(cmd, residual);
-               cmd->result = DID_OK << 16 | scsi_status;
-@@ -176,14 +179,14 @@
-                        * Firmware detected a SCSI transport underrun
-                        * condition
-                        */
--                      cmd->resid = residual;
-+                      scsi_set_resid(cmd, residual);
-                       DEBUG2(printk("scsi%ld:%d:%d:%d: %s: UNDERRUN status "
-                                     "detected, xferlen = 0x%x, residual = "
-                                     "0x%x\n",
-                                     ha->host_no, cmd->device->channel,
-                                     cmd->device->id,
-                                     cmd->device->lun, __func__,
--                                    cmd->request_bufflen,
-+                                    scsi_bufflen(cmd),
-                                     residual));
-               }
-@@ -227,7 +230,7 @@
-                       if ((sts_entry->iscsiFlags &
-                            ISCSI_FLAG_RESIDUAL_UNDER) == 0) {
-                               cmd->result = DID_BUS_BUSY << 16;
--                      } else if ((cmd->request_bufflen - residual) <
-+                      } else if ((scsi_bufflen(cmd) - residual) <
-                                  cmd->underflow) {
-                               /*
-                                * Handle mid-layer underflow???
-@@ -248,7 +251,7 @@
-                                             cmd->device->channel,
-                                             cmd->device->id,
-                                             cmd->device->lun, __func__,
--                                            cmd->request_bufflen, residual));
-+                                            scsi_bufflen(cmd), residual));
-                               cmd->result = DID_ERROR << 16;
-                       } else {
-@@ -417,6 +420,7 @@
-                                      uint32_t mbox_status)
- {
-       int i;
-+      uint32_t mbox_stat2, mbox_stat3;
-       if ((mbox_status == MBOX_STS_BUSY) ||
-           (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) ||
-@@ -437,6 +441,12 @@
-       } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
-               /* Immediately process the AENs that don't require much work.
-                * Only queue the database_changed AENs */
-+              if (ha->aen_log.count < MAX_AEN_ENTRIES) {
-+                      for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
-+                              ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] =
-+                                      readl(&ha->reg->mailbox[i]);
-+                      ha->aen_log.count++;
-+              }
-               switch (mbox_status) {
-               case MBOX_ASTS_SYSTEM_ERROR:
-                       /* Log Mailbox registers */
-@@ -493,6 +503,16 @@
-                                     mbox_status));
-                       break;
-+              case MBOX_ASTS_IP_ADDR_STATE_CHANGED:
-+                      mbox_stat2 = readl(&ha->reg->mailbox[2]);
-+                      mbox_stat3 = readl(&ha->reg->mailbox[3]);
 +
-+                      if ((mbox_stat3 == 5) && (mbox_stat2 == 3))
-+                              set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
-+                      else if ((mbox_stat3 == 2) && (mbox_stat2 == 5))
-+                              set_bit(DPC_RESET_HA, &ha->dpc_flags);
-+                      break;
 +
-               case MBOX_ASTS_MAC_ADDRESS_CHANGED:
-               case MBOX_ASTS_DNS:
-                       /* No action */
-@@ -518,11 +538,6 @@
-                       /* Queue AEN information and process it in the DPC
-                        * routine */
-                       if (ha->aen_q_count > 0) {
--                              /* advance pointer */
--                              if (ha->aen_in == (MAX_AEN_ENTRIES - 1))
--                                      ha->aen_in = 0;
--                              else
--                                      ha->aen_in++;
-                               /* decrement available counter */
-                               ha->aen_q_count--;
-@@ -542,6 +557,10 @@
-                                             ha->aen_q[ha->aen_in].mbox_sts[2],
-                                             ha->aen_q[ha->aen_in].mbox_sts[3],
-                                             ha->aen_q[ha->aen_in].  mbox_sts[4]));
-+                              /* advance pointer */
-+                              ha->aen_in++;
-+                              if (ha->aen_in == MAX_AEN_ENTRIES)
-+                                      ha->aen_in = 0;
-                               /* The DPC routine will process the aen */
-                               set_bit(DPC_AEN, &ha->dpc_flags);
-@@ -724,25 +743,24 @@
-       spin_lock_irqsave(&ha->hardware_lock, flags);
-       while (ha->aen_out != ha->aen_in) {
--              /* Advance pointers for next entry */
--              if (ha->aen_out == (MAX_AEN_ENTRIES - 1))
--                      ha->aen_out = 0;
--              else
--                      ha->aen_out++;
--
--              ha->aen_q_count++;
-               aen = &ha->aen_q[ha->aen_out];
--
-               /* copy aen information to local structure */
-               for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
-                       mbox_sts[i] = aen->mbox_sts[i];
-+              ha->aen_q_count++;
-+              ha->aen_out++;
++      MOVE MEMORY 4, saved_dsa, addr_dsa
 +
-+              if (ha->aen_out == MAX_AEN_ENTRIES)
-+                      ha->aen_out = 0;
++at 0x00000031 : */    0xc0000004,0x00000000,0x00000000,
++/*
++      JUMP jump_temp
 +
-               spin_unlock_irqrestore(&ha->hardware_lock, flags);
--              DEBUG(printk("scsi%ld: AEN[%d] %04x, index [%d] state=%04x "
--                           "mod=%x conerr=%08x \n", ha->host_no, ha->aen_out,
--                           mbox_sts[0], mbox_sts[2], mbox_sts[3],
--                           mbox_sts[1], mbox_sts[4]));
-+              DEBUG2(printk("qla4xxx(%ld): AEN[%d]=0x%08x, mbx1=0x%08x mbx2=0x%08x"
-+                      " mbx3=0x%08x mbx4=0x%08x\n", ha->host_no,
-+                      (ha->aen_out ? (ha->aen_out-1): (MAX_AEN_ENTRIES-1)),
-+                      mbox_sts[0], mbox_sts[1], mbox_sts[2],
-+                      mbox_sts[3], mbox_sts[4]));
-               switch (mbox_sts[0]) {
-               case MBOX_ASTS_DATABASE_CHANGED:
-@@ -792,6 +810,5 @@
-               spin_lock_irqsave(&ha->hardware_lock, flags);
-       }
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
--
- }
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_mbx.c linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_mbx.c
---- linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_mbx.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_mbx.c    2008-01-02 13:56:37.000000000 -0500
-@@ -6,6 +6,9 @@
-  */
- #include "ql4_def.h"
-+#include "ql4_glbl.h"
-+#include "ql4_dbg.h"
-+#include "ql4_inline.h"
- /**
-@@ -169,84 +172,6 @@
-       return status;
- }
--
--#if 0
--
--/**
-- * qla4xxx_issue_iocb - issue mailbox iocb command
-- * @ha: adapter state pointer.
-- * @buffer: buffer pointer.
-- * @phys_addr: physical address of buffer.
-- * @size: size of buffer.
-- *
-- * Issues iocbs via mailbox commands.
-- * TARGET_QUEUE_LOCK must be released.
-- * ADAPTER_STATE_LOCK must be released.
-- **/
--int
--qla4xxx_issue_iocb(struct scsi_qla_host * ha, void *buffer,
--                 dma_addr_t phys_addr, size_t size)
--{
--      uint32_t mbox_cmd[MBOX_REG_COUNT];
--      uint32_t mbox_sts[MBOX_REG_COUNT];
--      int status;
--
--      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
--      memset(&mbox_sts, 0, sizeof(mbox_sts));
--      mbox_cmd[0] = MBOX_CMD_EXECUTE_IOCB_A64;
--      mbox_cmd[1] = 0;
--      mbox_cmd[2] = LSDW(phys_addr);
--      mbox_cmd[3] = MSDW(phys_addr);
--      status = qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
--      return status;
--}
--
--int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
--                                 uint16_t fw_ddb_index,
--                                 uint16_t connection_id,
--                                 uint16_t option)
--{
--      uint32_t mbox_cmd[MBOX_REG_COUNT];
--      uint32_t mbox_sts[MBOX_REG_COUNT];
--
--      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
--      memset(&mbox_sts, 0, sizeof(mbox_sts));
--      mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
--      mbox_cmd[1] = fw_ddb_index;
--      mbox_cmd[2] = connection_id;
--      mbox_cmd[3] = LOGOUT_OPTION_RELOGIN;
--      if (qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]) !=
--          QLA_SUCCESS) {
--              DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
--                            "option %04x failed sts %04X %04X",
--                            ha->host_no, __func__,
--                            option, mbox_sts[0], mbox_sts[1]));
--              if (mbox_sts[0] == 0x4005)
--                      DEBUG2(printk("%s reason %04X\n", __func__,
--                                    mbox_sts[1]));
--      }
--      return QLA_SUCCESS;
--}
--
--int qla4xxx_clear_database_entry(struct scsi_qla_host * ha,
--                               uint16_t fw_ddb_index)
--{
--      uint32_t mbox_cmd[MBOX_REG_COUNT];
--      uint32_t mbox_sts[MBOX_REG_COUNT];
--
--      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
--      memset(&mbox_sts, 0, sizeof(mbox_sts));
--      mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;
--      mbox_cmd[1] = fw_ddb_index;
--      if (qla4xxx_mailbox_command(ha, 2, 5, &mbox_cmd[0], &mbox_sts[0]) !=
--          QLA_SUCCESS)
--              return QLA_ERROR;
--
--      return QLA_SUCCESS;
--}
--
--#endif  /*  0  */
--
- /**
-  * qla4xxx_initialize_fw_cb - initializes firmware control block.
-  * @ha: Pointer to host adapter structure.
-@@ -272,10 +197,13 @@
-       /* Get Initialize Firmware Control Block. */
-       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-       memset(&mbox_sts, 0, sizeof(mbox_sts));
++at 0x00000034 : */    0x80080000,0x000009c4,
++/*
 +
-       mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
-       mbox_cmd[2] = LSDW(init_fw_cb_dma);
-       mbox_cmd[3] = MSDW(init_fw_cb_dma);
--      if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
-+      mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk);
++ABSOLUTE dsa_restore_pointers = 0
++ENTRY dsa_code_restore_pointers
++dsa_code_restore_pointers:
 +
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
-           QLA_SUCCESS) {
-               dma_free_coherent(&ha->pdev->dev,
-                                 sizeof(struct init_fw_ctrl_blk),
-@@ -287,51 +215,56 @@
-       qla4xxx_init_rings(ha);
-       /* Fill in the request and response queue information. */
--      init_fw_cb->ReqQConsumerIndex = cpu_to_le16(ha->request_out);
--      init_fw_cb->ComplQProducerIndex = cpu_to_le16(ha->response_in);
--      init_fw_cb->ReqQLen = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
--      init_fw_cb->ComplQLen = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
--      init_fw_cb->ReqQAddrLo = cpu_to_le32(LSDW(ha->request_dma));
--      init_fw_cb->ReqQAddrHi = cpu_to_le32(MSDW(ha->request_dma));
--      init_fw_cb->ComplQAddrLo = cpu_to_le32(LSDW(ha->response_dma));
--      init_fw_cb->ComplQAddrHi = cpu_to_le32(MSDW(ha->response_dma));
--      init_fw_cb->ShadowRegBufAddrLo =
-+      init_fw_cb->pri.rqq_consumer_idx = cpu_to_le16(ha->request_out);
-+      init_fw_cb->pri.compq_producer_idx = cpu_to_le16(ha->response_in);
-+      init_fw_cb->pri.rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
-+      init_fw_cb->pri.compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
-+      init_fw_cb->pri.rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma));
-+      init_fw_cb->pri.rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma));
-+      init_fw_cb->pri.compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma));
-+      init_fw_cb->pri.compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma));
-+      init_fw_cb->pri.shdwreg_addr_lo =
-               cpu_to_le32(LSDW(ha->shadow_regs_dma));
--      init_fw_cb->ShadowRegBufAddrHi =
-+      init_fw_cb->pri.shdwreg_addr_hi =
-               cpu_to_le32(MSDW(ha->shadow_regs_dma));
-       /* Set up required options. */
--      init_fw_cb->FwOptions |=
-+      init_fw_cb->pri.fw_options |=
-               __constant_cpu_to_le16(FWOPT_SESSION_MODE |
-                                      FWOPT_INITIATOR_MODE);
--      init_fw_cb->FwOptions &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
-+      init_fw_cb->pri.fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
-       /* Save some info in adapter structure. */
--      ha->firmware_options = le16_to_cpu(init_fw_cb->FwOptions);
--      ha->tcp_options = le16_to_cpu(init_fw_cb->TCPOptions);
--      ha->heartbeat_interval = init_fw_cb->HeartbeatInterval;
--      memcpy(ha->ip_address, init_fw_cb->IPAddr,
--             min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
--      memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
--             min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
--      memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
--             min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
--      memcpy(ha->name_string, init_fw_cb->iSCSINameString,
-+      ha->firmware_options = le16_to_cpu(init_fw_cb->pri.fw_options);
-+      ha->tcp_options = le16_to_cpu(init_fw_cb->pri.ipv4_tcp_opts);
-+      ha->heartbeat_interval = init_fw_cb->pri.hb_interval;
-+      memcpy(ha->ip_address, init_fw_cb->pri.ipv4_addr,
-+             min(sizeof(ha->ip_address), sizeof(init_fw_cb->pri.ipv4_addr)));
-+      memcpy(ha->subnet_mask, init_fw_cb->pri.ipv4_subnet,
-+             min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->pri.ipv4_subnet)));
-+      memcpy(ha->gateway, init_fw_cb->pri.ipv4_gw_addr,
-+             min(sizeof(ha->gateway), sizeof(init_fw_cb->pri.ipv4_gw_addr)));
-+      memcpy(ha->name_string, init_fw_cb->pri.iscsi_name,
-              min(sizeof(ha->name_string),
--                 sizeof(init_fw_cb->iSCSINameString)));
--      memcpy(ha->alias, init_fw_cb->Alias,
--             min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));
-+                 sizeof(init_fw_cb->pri.iscsi_name)));
-+      /*memcpy(ha->alias, init_fw_cb->Alias,
-+             min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
-       /* Save Command Line Paramater info */
--      ha->port_down_retry_count = le16_to_cpu(init_fw_cb->KeepAliveTimeout);
-+      ha->port_down_retry_count = le16_to_cpu(init_fw_cb->pri.conn_ka_timeout);
-       ha->discovery_wait = ql4xdiscoverywait;
-       /* Send Initialize Firmware Control Block. */
-+      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-+      memset(&mbox_sts, 0, sizeof(mbox_sts));
++      ; TEMP and DSA are corrupt when we get here, but who cares!
++      MOVE MEMORY 4, dsa_temp_addr_saved_pointer, jump_temp + 4
 +
-       mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;
-       mbox_cmd[1] = 0;
-       mbox_cmd[2] = LSDW(init_fw_cb_dma);
-       mbox_cmd[3] = MSDW(init_fw_cb_dma);
--      if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) ==
-+      mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk);
++at 0x00000036 : */    0xc0000004,0x00000000,0x000009c8,
++/*
++; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
++      MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
 +
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) ==
-           QLA_SUCCESS)
-               status = QLA_SUCCESS;
-        else {
-@@ -368,12 +301,14 @@
-       /* Get Initialize Firmware Control Block. */
-       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-       memset(&mbox_sts, 0, sizeof(mbox_sts));
++at 0x00000039 : */    0xc0000018,0x00000000,0x00000000,
++/*
++        CLEAR ACK
 +
-       memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk));
-       mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
-       mbox_cmd[2] = LSDW(init_fw_cb_dma);
-       mbox_cmd[3] = MSDW(init_fw_cb_dma);
-+      mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk);
--      if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
-           QLA_SUCCESS) {
-               DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
-                             ha->host_no, __func__));
-@@ -384,12 +319,12 @@
-       }
-       /* Save IP Address. */
--      memcpy(ha->ip_address, init_fw_cb->IPAddr,
--             min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
--      memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
--             min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
--      memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
--             min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
-+      memcpy(ha->ip_address, init_fw_cb->pri.ipv4_addr,
-+             min(sizeof(ha->ip_address), sizeof(init_fw_cb->pri.ipv4_addr)));
-+      memcpy(ha->subnet_mask, init_fw_cb->pri.ipv4_subnet,
-+             min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->pri.ipv4_subnet)));
-+      memcpy(ha->gateway, init_fw_cb->pri.ipv4_gw_addr,
-+             min(sizeof(ha->gateway), sizeof(init_fw_cb->pri.ipv4_gw_addr)));
-       dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk),
-                         init_fw_cb, init_fw_cb_dma);
-@@ -409,8 +344,10 @@
-       /* Get firmware version */
-       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-       memset(&mbox_sts, 0, sizeof(mbox_sts));
++at 0x0000003c : */    0x60000040,0x00000000,
++/*
++      ; Restore DSA, note we don't care about TEMP
++      MOVE MEMORY 4, saved_dsa, addr_dsa
 +
-       mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;
--      if (qla4xxx_mailbox_command(ha, 1, 4, &mbox_cmd[0], &mbox_sts[0]) !=
++at 0x0000003e : */    0xc0000004,0x00000000,0x00000000,
++/*
 +
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) !=
-           QLA_SUCCESS) {
-               DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
-                             "status %04X\n", ha->host_no, __func__,
-@@ -438,8 +375,10 @@
-       /* Get firmware version */
-       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-       memset(&mbox_sts, 0, sizeof(mbox_sts));
 +
-       mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;
--      if (qla4xxx_mailbox_command(ha, 1, 3, &mbox_cmd[0], &mbox_sts[0]) !=
 +
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
-           QLA_SUCCESS) {
-               DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
-                             "status %04X\n", ha->host_no, __func__,
-@@ -491,11 +430,14 @@
-       }
-       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-       memset(&mbox_sts, 0, sizeof(mbox_sts));
++      JUMP jump_temp
 +
-       mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
-       mbox_cmd[1] = (uint32_t) fw_ddb_index;
-       mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
-       mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
--      if (qla4xxx_mailbox_command(ha, 4, 7, &mbox_cmd[0], &mbox_sts[0]) ==
-+      mbox_cmd[4] = sizeof(struct dev_db_entry);
++at 0x00000041 : */    0x80080000,0x000009c4,
++/*
 +
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) ==
-           QLA_ERROR) {
-               DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"
-                             " with status 0x%04X\n", ha->host_no, __func__,
-@@ -512,11 +454,11 @@
-               dev_info(&ha->pdev->dev, "DDB[%d] MB0 %04x Tot %d Next %d "
-                          "State %04x ConnErr %08x %d.%d.%d.%d:%04d \"%s\"\n",
-                          fw_ddb_index, mbox_sts[0], mbox_sts[2], mbox_sts[3],
--                         mbox_sts[4], mbox_sts[5], fw_ddb_entry->ipAddr[0],
--                         fw_ddb_entry->ipAddr[1], fw_ddb_entry->ipAddr[2],
--                         fw_ddb_entry->ipAddr[3],
--                         le16_to_cpu(fw_ddb_entry->portNumber),
--                         fw_ddb_entry->iscsiName);
-+                         mbox_sts[4], mbox_sts[5], fw_ddb_entry->ip_addr[0],
-+                         fw_ddb_entry->ip_addr[1], fw_ddb_entry->ip_addr[2],
-+                         fw_ddb_entry->ip_addr[3],
-+                         le16_to_cpu(fw_ddb_entry->port),
-+                         fw_ddb_entry->iscsi_name);
-       }
-       if (num_valid_ddb_entries)
-               *num_valid_ddb_entries = mbox_sts[2];
-@@ -571,35 +513,10 @@
-       mbox_cmd[1] = (uint32_t) fw_ddb_index;
-       mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
-       mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
--      return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
--}
--
--#if 0
--int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha,
--                                  uint16_t fw_ddb_index)
--{
--      int status = QLA_ERROR;
--      uint32_t mbox_cmd[MBOX_REG_COUNT];
--      uint32_t mbox_sts[MBOX_REG_COUNT];
--
--      /* Do not wait for completion. The firmware will send us an
--       * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
--       */
--      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
--      memset(&mbox_sts, 0, sizeof(mbox_sts));
--      mbox_cmd[0] = MBOX_CMD_CONN_OPEN_SESS_LOGIN;
--      mbox_cmd[1] = (uint32_t) fw_ddb_index;
--      mbox_cmd[2] = 0;
--      mbox_cmd[3] = 0;
--      mbox_cmd[4] = 0;
--      status = qla4xxx_mailbox_command(ha, 4, 0, &mbox_cmd[0], &mbox_sts[0]);
--      DEBUG2(printk("%s fw_ddb_index=%d status=%d mbx0_1=0x%x :0x%x\n",
--                    __func__, fw_ddb_index, status, mbox_sts[0],
--                    mbox_sts[1]);)
-+      mbox_cmd[4] = sizeof(struct dev_db_entry);
--              return status;
-+      return qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
- }
--#endif  /*  0  */
- /**
-  * qla4xxx_get_crash_record - retrieves crash record.
-@@ -614,12 +531,14 @@
-       struct crash_record *crash_record = NULL;
-       dma_addr_t crash_record_dma = 0;
-       uint32_t crash_record_size = 0;
 +
-       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-       memset(&mbox_sts, 0, sizeof(mbox_cmd));
-       /* Get size of crash record. */
-       mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
--      if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
++ABSOLUTE dsa_check_reselect = 0
++; dsa_check_reselect determines whether or not the current target and
++; lun match the current DSA
++ENTRY dsa_code_check_reselect
++dsa_code_check_reselect:
 +
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
-           QLA_SUCCESS) {
-               DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",
-                             ha->host_no, __func__));
-@@ -639,11 +558,15 @@
-               goto exit_get_crash_record;
-       /* Get Crash Record. */
-+      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-+      memset(&mbox_sts, 0, sizeof(mbox_cmd));
++      
++      
++      MOVE LCRC TO SFBR               ; LCRC has our ID and his ID bits set
 +
-       mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
-       mbox_cmd[2] = LSDW(crash_record_dma);
-       mbox_cmd[3] = MSDW(crash_record_dma);
-       mbox_cmd[4] = crash_record_size;
--      if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
++at 0x00000043 : */    0x72230000,0x00000000,
++/*
++      JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0x80
 +
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
-           QLA_SUCCESS)
-               goto exit_get_crash_record;
-@@ -655,7 +578,6 @@
-                                 crash_record, crash_record_dma);
- }
--#if 0
- /**
-  * qla4xxx_get_conn_event_log - retrieves connection event log
-  * @ha: Pointer to host adapter structure.
-@@ -678,7 +600,8 @@
-       /* Get size of crash record. */
-       mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
--      if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
++at 0x00000045 : */    0x80848000,0x00ffff50,
++/*
 +
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
-           QLA_SUCCESS)
-               goto exit_get_event_log;
-@@ -693,10 +616,14 @@
-               goto exit_get_event_log;
-       /* Get Crash Record. */
-+      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-+      memset(&mbox_sts, 0, sizeof(mbox_cmd));
 +
-       mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
-       mbox_cmd[2] = LSDW(event_log_dma);
-       mbox_cmd[3] = MSDW(event_log_dma);
--      if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
 +
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
-           QLA_SUCCESS) {
-               DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event "
-                             "log!\n", ha->host_no, __func__));
-@@ -745,7 +672,6 @@
-               dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
-                                 event_log_dma);
- }
--#endif  /*  0  */
- /**
-  * qla4xxx_reset_lun - issues LUN Reset
-@@ -773,11 +699,13 @@
-        */
-       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-       memset(&mbox_sts, 0, sizeof(mbox_sts));
 +
-       mbox_cmd[0] = MBOX_CMD_LUN_RESET;
-       mbox_cmd[1] = ddb_entry->fw_ddb_index;
-       mbox_cmd[2] = lun << 8;
-       mbox_cmd[5] = 0x01;     /* Immediate Command Enable */
--      qla4xxx_mailbox_command(ha, 6, 1, &mbox_cmd[0], &mbox_sts[0]);
 +
-+      qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
-       if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
-           mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
-               status = QLA_ERROR;
-@@ -794,12 +722,14 @@
-       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-       memset(&mbox_sts, 0, sizeof(mbox_sts));
++;
++; Hack - move to scratch first, since SFBR is not writeable
++;     via the CPU and hence a MOVE MEMORY instruction.
++;
++      
++      MOVE MEMORY 1, reselected_identify, addr_scratch
 +
-       mbox_cmd[0] = MBOX_CMD_READ_FLASH;
-       mbox_cmd[1] = LSDW(dma_addr);
-       mbox_cmd[2] = MSDW(dma_addr);
-       mbox_cmd[3] = offset;
-       mbox_cmd[4] = len;
--      if (qla4xxx_mailbox_command(ha, 5, 2, &mbox_cmd[0], &mbox_sts[0]) !=
++at 0x00000047 : */    0xc0000001,0x00000000,0x00000000,
++/*
++      
 +
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) !=
-           QLA_SUCCESS) {
-               DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
-                   "status %04X %04X, offset %08x, len %08x\n", ha->host_no,
-@@ -825,8 +755,10 @@
-       /* Get firmware version. */
-       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
-       memset(&mbox_sts, 0, sizeof(mbox_sts));
++      ; BIG ENDIAN ON MVME16x
++      MOVE SCRATCH3 TO SFBR
 +
-       mbox_cmd[0] = MBOX_CMD_ABOUT_FW;
--      if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
++at 0x0000004a : */    0x72370000,0x00000000,
++/*
 +
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
-           QLA_SUCCESS) {
-               DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ "
-                   "status %04X\n", ha->host_no, __func__, mbox_sts[0]));
-@@ -855,7 +787,7 @@
-       mbox_cmd[2] = LSDW(dma_addr);
-       mbox_cmd[3] = MSDW(dma_addr);
--      if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
-           QLA_SUCCESS) {
-               DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
-                    ha->host_no, __func__, mbox_sts[0]));
-@@ -875,7 +807,7 @@
-       mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
-       mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES;
--      if (qla4xxx_mailbox_command(ha, 2, 3, &mbox_cmd[0], &mbox_sts[0]) !=
-+      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
-           QLA_SUCCESS) {
-               if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) {
-                       *ddb_index = mbox_sts[2];
-@@ -918,23 +850,23 @@
-       if (ret_val != QLA_SUCCESS)
-               goto qla4xxx_send_tgts_exit;
--      memset((void *)fw_ddb_entry->iSCSIAlias, 0,
--             sizeof(fw_ddb_entry->iSCSIAlias));
-+      memset(fw_ddb_entry->iscsi_alias, 0,
-+             sizeof(fw_ddb_entry->iscsi_alias));
--      memset((void *)fw_ddb_entry->iscsiName, 0,
--             sizeof(fw_ddb_entry->iscsiName));
-+      memset(fw_ddb_entry->iscsi_name, 0,
-+             sizeof(fw_ddb_entry->iscsi_name));
--      memset((void *)fw_ddb_entry->ipAddr, 0, sizeof(fw_ddb_entry->ipAddr));
--      memset((void *)fw_ddb_entry->targetAddr, 0,
--             sizeof(fw_ddb_entry->targetAddr));
-+      memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr));
-+      memset(fw_ddb_entry->tgt_addr, 0,
-+             sizeof(fw_ddb_entry->tgt_addr));
-       fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET);
--      fw_ddb_entry->portNumber = cpu_to_le16(ntohs(port));
-+      fw_ddb_entry->port = cpu_to_le16(ntohs(port));
--      fw_ddb_entry->ipAddr[0] = *ip;
--      fw_ddb_entry->ipAddr[1] = *(ip + 1);
--      fw_ddb_entry->ipAddr[2] = *(ip + 2);
--      fw_ddb_entry->ipAddr[3] = *(ip + 3);
-+      fw_ddb_entry->ip_addr[0] = *ip;
-+      fw_ddb_entry->ip_addr[1] = *(ip + 1);
-+      fw_ddb_entry->ip_addr[2] = *(ip + 2);
-+      fw_ddb_entry->ip_addr[3] = *(ip + 3);
-       ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma);
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_nvram.c linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_nvram.c
---- linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_nvram.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_nvram.c  2008-01-02 13:56:37.000000000 -0500
-@@ -6,6 +6,9 @@
-  */
- #include "ql4_def.h"
-+#include "ql4_glbl.h"
-+#include "ql4_dbg.h"
-+#include "ql4_inline.h"
- static inline void eeprom_cmd(uint32_t cmd, struct scsi_qla_host *ha)
- {
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_os.c linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_os.c
---- linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_os.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_os.c     2008-01-02 13:56:37.000000000 -0500
-@@ -10,6 +10,10 @@
- #include <scsi/scsicam.h>
- #include "ql4_def.h"
-+#include "ql4_version.h"
-+#include "ql4_glbl.h"
-+#include "ql4_dbg.h"
-+#include "ql4_inline.h"
- /*
-  * Driver version
-@@ -50,12 +54,15 @@
- /*
-  * iSCSI template entry points
-  */
--static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no,
--                           uint32_t enable, struct sockaddr *dst_addr);
-+static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
-+                           enum iscsi_tgt_dscvr type, uint32_t enable,
-+                           struct sockaddr *dst_addr);
- static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
-                                 enum iscsi_param param, char *buf);
- static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
-                                 enum iscsi_param param, char *buf);
-+static int qla4xxx_host_get_param(struct Scsi_Host *shost,
-+                                enum iscsi_host_param param, char *buf);
- static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag);
- static int qla4xxx_conn_start(struct iscsi_cls_conn *conn);
- static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
-@@ -95,16 +102,20 @@
- static struct iscsi_transport qla4xxx_iscsi_transport = {
-       .owner                  = THIS_MODULE,
-       .name                   = DRIVER_NAME,
--      .param_mask             = ISCSI_CONN_PORT |
--                                ISCSI_CONN_ADDRESS |
--                                ISCSI_TARGET_NAME |
--                                ISCSI_TPGT,
-+      .caps                   = CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD |
-+                                CAP_DATA_PATH_OFFLOAD,
-+      .param_mask             = ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
-+                                ISCSI_TARGET_NAME | ISCSI_TPGT,
-+      .host_param_mask        = ISCSI_HOST_HWADDRESS |
-+                                ISCSI_HOST_IPADDRESS |
-+                                ISCSI_HOST_INITIATOR_NAME,
-       .sessiondata_size       = sizeof(struct ddb_entry),
-       .host_template          = &qla4xxx_driver_template,
-       .tgt_dscvr              = qla4xxx_tgt_dscvr,
-       .get_conn_param         = qla4xxx_conn_get_param,
-       .get_session_param      = qla4xxx_sess_get_param,
-+      .get_host_param         = qla4xxx_host_get_param,
-       .start_conn             = qla4xxx_conn_start,
-       .stop_conn              = qla4xxx_conn_stop,
-       .session_recovery_timedout = qla4xxx_recovery_timedout,
-@@ -161,6 +172,43 @@
-               printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
- }
-+static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
-+{
-+      int i;
-+      char *cp = buf;
 +
-+      for (i = 0; i < len; i++)
-+              cp += sprintf(cp, "%02x%c", addr[i],
-+                            i == (len - 1) ? '\n' : ':');
-+      return cp - buf;
-+}
++
++; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
++; Are you sure about that?  richard@sleepie.demon.co.uk
++      JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8
++
++at 0x0000004c : */    0x8084f800,0x00ffff34,
++/*
++;             Patch the MOVE MEMORY INSTRUCTION such that
++;             the source address is the address of this dsa's
++;             next pointer.
++      MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 4
++
++at 0x0000004e : */    0xc0000004,0x00000000,0x000007e8,
++/*
++      CALL reselected_ok
++
++at 0x00000051 : */    0x88080000,0x00000798,
++/*
++
++;     Restore DSA following memory moves in reselected_ok
++;     dsa_temp_sync doesn't really care about DSA, but it has an
++;     optional debug INT so a valid DSA is a good idea.
++      MOVE MEMORY 4, saved_dsa, addr_dsa
++
++at 0x00000053 : */    0xc0000004,0x00000000,0x00000000,
++/*
++
++      CALL dsa_temp_sync      
++
++at 0x00000056 : */    0x88080000,0x00000000,
++/*
++; Release ACK on the IDENTIFY message _after_ we've set the synchronous 
++; transfer parameters! 
++      CLEAR ACK
++
++at 0x00000058 : */    0x60000040,0x00000000,
++/*
++; Implicitly restore pointers on reselection, so a RETURN
++; will transfer control back to the right spot.
++      CALL REL (dsa_code_restore_pointers)
++
++at 0x0000005a : */    0x88880000,0x00ffff68,
++/*
++      RETURN
++
++at 0x0000005c : */    0x90080000,0x00000000,
++/*
++ENTRY dsa_zero
++dsa_zero:
++ENTRY dsa_code_template_end
++dsa_code_template_end:
++
++; Perform sanity check for dsa_fields_start == dsa_code_template_end - 
++; dsa_zero, puke.
++
++ABSOLUTE dsa_fields_start =  0        ; Sanity marker
++                              ;       pad 48 bytes (fix this RSN)
++ABSOLUTE dsa_next = 48                ; len 4 Next DSA
++                              ; del 4 Previous DSA address
++ABSOLUTE dsa_cmnd = 56                ; len 4 Scsi_Cmnd * for this thread.
++ABSOLUTE dsa_select = 60      ; len 4 Device ID, Period, Offset for 
++                              ;       table indirect select
++ABSOLUTE dsa_msgout = 64      ; len 8 table indirect move parameter for 
++                              ;       select message
++ABSOLUTE dsa_cmdout = 72      ; len 8 table indirect move parameter for 
++                              ;       command
++ABSOLUTE dsa_dataout = 80     ; len 4 code pointer for dataout
++ABSOLUTE dsa_datain = 84      ; len 4 code pointer for datain
++ABSOLUTE dsa_msgin = 88               ; len 8 table indirect move for msgin
++ABSOLUTE dsa_status = 96      ; len 8 table indirect move for status byte
++ABSOLUTE dsa_msgout_other = 104       ; len 8 table indirect for normal message out
++                              ; (Synchronous transfer negotiation, etc).
++ABSOLUTE dsa_end = 112
++
++ABSOLUTE schedule = 0                 ; Array of JUMP dsa_begin or JUMP (next),
++                              ; terminated by a call to JUMP wait_reselect
++
++; Linked lists of DSA structures
++ABSOLUTE reconnect_dsa_head = 0       ; Link list of DSAs which can reconnect
++ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing
++                              ; address of reconnect_dsa_head
++
++; These select the source and destination of a MOVE MEMORY instruction
++ABSOLUTE dmode_memory_to_memory = 0x0
++ABSOLUTE dmode_memory_to_ncr = 0x0
++ABSOLUTE dmode_ncr_to_memory = 0x0
++
++ABSOLUTE addr_scratch = 0x0
++ABSOLUTE addr_temp = 0x0
++
++ABSOLUTE saved_dsa = 0x0
++ABSOLUTE emulfly = 0x0
++ABSOLUTE addr_dsa = 0x0
++
++
++
++; Interrupts - 
++; MSB indicates type
++; 0   handle error condition
++; 1   handle message 
++; 2   handle normal condition
++; 3   debugging interrupt
++; 4   testing interrupt 
++; Next byte indicates specific error
++
++; XXX not yet implemented, I'm not sure if I want to - 
++; Next byte indicates the routine the error occurred in
++; The LSB indicates the specific place the error occurred
++ 
++ABSOLUTE int_err_unexpected_phase = 0x00000000        ; Unexpected phase encountered
++ABSOLUTE int_err_selected = 0x00010000                ; SELECTED (nee RESELECTED)
++ABSOLUTE int_err_unexpected_reselect = 0x00020000 
++ABSOLUTE int_err_check_condition = 0x00030000 
++ABSOLUTE int_err_no_phase = 0x00040000
++ABSOLUTE int_msg_wdtr = 0x01000000            ; WDTR message received
++ABSOLUTE int_msg_sdtr = 0x01010000            ; SDTR received
++ABSOLUTE int_msg_1 = 0x01020000                       ; single byte special message
++                                              ; received
++
++ABSOLUTE int_norm_select_complete = 0x02000000        ; Select complete, reprogram
++                                              ; registers.
++ABSOLUTE int_norm_reselect_complete = 0x02010000      ; Nexus established
++ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete
++ABSOLUTE int_norm_disconnected = 0x02030000   ; Disconnected 
++ABSOLUTE int_norm_aborted =0x02040000         ; Aborted *dsa
++ABSOLUTE int_norm_reset = 0x02050000          ; Generated BUS reset.
++ABSOLUTE int_norm_emulateintfly = 0x02060000  ; 53C710 Emulated intfly
++ABSOLUTE int_debug_break = 0x03000000         ; Break point
++
++ABSOLUTE int_debug_panic = 0x030b0000         ; Panic driver
++
++
++ABSOLUTE int_test_1 = 0x04000000              ; Test 1 complete
++ABSOLUTE int_test_2 = 0x04010000              ; Test 2 complete
++ABSOLUTE int_test_3 = 0x04020000              ; Test 3 complete
++
++
++; These should start with 0x05000000, with low bits incrementing for 
++; each one.
++
++
++                                              
++ABSOLUTE NCR53c7xx_msg_abort = 0      ; Pointer to abort message
++ABSOLUTE NCR53c7xx_msg_reject = 0       ; Pointer to reject message
++ABSOLUTE NCR53c7xx_zero       = 0             ; long with zero in it, use for source
++ABSOLUTE NCR53c7xx_sink = 0           ; long to dump worthless data in
++ABSOLUTE NOP_insn = 0                 ; NOP instruction
++
++; Pointer to message, potentially multi-byte
++ABSOLUTE msg_buf = 0
++
++; Pointer to holding area for reselection information
++ABSOLUTE reselected_identify = 0
++ABSOLUTE reselected_tag = 0
++
++; Request sense command pointer, it's a 6 byte command, should
++; be constant for all commands since we always want 16 bytes of 
++; sense and we don't need to change any fields as we did under 
++; SCSI-I when we actually cared about the LUN field.
++;EXTERNAL NCR53c7xx_sense             ; Request sense command
++
++
++; dsa_schedule  
++; PURPOSE : after a DISCONNECT message has been received, and pointers
++;     saved, insert the current DSA structure at the head of the 
++;     disconnected queue and fall through to the scheduler.
++;
++; CALLS : OK
++;
++; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list
++;     of disconnected commands
++;
++; MODIFIES : SCRATCH, reconnect_dsa_head
++; 
++; EXITS : always passes control to schedule
++
++ENTRY dsa_schedule
++dsa_schedule:
++
++
++
++
++;
++; Calculate the address of the next pointer within the DSA 
++; structure of the command that is currently disconnecting
++;
++
++    ; Read what should be the current DSA from memory - actual DSA
++    ; register is probably corrupt
++    MOVE MEMORY 4, saved_dsa, addr_scratch
++
++at 0x0000005e : */    0xc0000004,0x00000000,0x00000000,
++/*
++
++
++
++    MOVE SCRATCH0 + dsa_next TO SCRATCH0
++
++at 0x00000061 : */    0x7e343000,0x00000000,
++/*
++    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
++
++at 0x00000063 : */    0x7f350000,0x00000000,
++/*
++    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
++
++at 0x00000065 : */    0x7f360000,0x00000000,
++/*
++    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
++
++at 0x00000067 : */    0x7f370000,0x00000000,
++/*
++
++; Point the next field of this DSA structure at the current disconnected 
++; list
++    
++    MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8
++
++at 0x00000069 : */    0xc0000004,0x00000000,0x000001b8,
++/*
++    
++dsa_schedule_insert:
++    MOVE MEMORY 4, reconnect_dsa_head, 0 
++
++at 0x0000006c : */    0xc0000004,0x00000000,0x00000000,
++/*
++
++; And update the head pointer.
++
++    ; Read what should be the current DSA from memory - actual DSA
++    ; register is probably corrupt
++    MOVE MEMORY 4, saved_dsa, addr_scratch
++
++at 0x0000006f : */    0xc0000004,0x00000000,0x00000000,
++/*
++
++
++
++    
++    MOVE MEMORY 4, addr_scratch, reconnect_dsa_head
++
++at 0x00000072 : */    0xc0000004,0x00000000,0x00000000,
++/*
++    
++
++
++
++
++
++    CLEAR ACK
++
++at 0x00000075 : */    0x60000040,0x00000000,
++/*
++
++
++    ; Time to correct DSA following memory move
++    MOVE MEMORY 4, saved_dsa, addr_dsa
++
++at 0x00000077 : */    0xc0000004,0x00000000,0x00000000,
++/*
++
++    WAIT DISCONNECT
++
++at 0x0000007a : */    0x48000000,0x00000000,
++/*
++
++
++
++
++
++
++    JUMP schedule
++
++at 0x0000007c : */    0x80080000,0x00000000,
++/*
++
++
++;
++; select
++;
++; PURPOSE : establish a nexus for the SCSI command referenced by DSA.
++;     On success, the current DSA structure is removed from the issue 
++;     queue.  Usually, this is entered as a fall-through from schedule,
++;     although the contingent allegiance handling code will write
++;     the select entry address to the DSP to restart a command as a 
++;     REQUEST SENSE.  A message is sent (usually IDENTIFY, although
++;     additional SDTR or WDTR messages may be sent).  COMMAND OUT
++;     is handled.
++;
++; INPUTS : DSA - SCSI command, issue_dsa_head
++;
++; CALLS : NOT OK
++;
++; MODIFIES : SCRATCH, issue_dsa_head
++;
++; EXITS : on reselection or selection, go to select_failed
++;     otherwise, RETURN so control is passed back to 
++;     dsa_begin.
++;
++
++ENTRY select
++select:
++
 +
 +
-+static int qla4xxx_host_get_param(struct Scsi_Host *shost,
-+                                enum iscsi_host_param param, char *buf)
-+{
-+      struct scsi_qla_host *ha = to_qla_host(shost);
-+      int len;
 +
-+      switch (param) {
-+      case ISCSI_HOST_PARAM_HWADDRESS:
-+              len = format_addr(buf, ha->my_mac, MAC_ADDR_LEN);
-+              break;
-+      case ISCSI_HOST_PARAM_IPADDRESS:
-+              len = sprintf(buf, "%d.%d.%d.%d\n", ha->ip_address[0],
-+                            ha->ip_address[1], ha->ip_address[2],
-+                            ha->ip_address[3]);
-+              break;
-+      case ISCSI_HOST_PARAM_INITIATOR_NAME:
-+              len = sprintf(buf, "%s\n", ha->name_string);
-+              break;
-+      default:
-+              return -ENOSYS;
-+      }
 +
-+      return len;
-+}
 +
- static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
-                                 enum iscsi_param param, char *buf)
- {
-@@ -208,21 +256,15 @@
-       return len;
- }
--static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no,
--                           uint32_t enable, struct sockaddr *dst_addr)
-+static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
-+                           enum iscsi_tgt_dscvr type, uint32_t enable,
-+                           struct sockaddr *dst_addr)
- {
-       struct scsi_qla_host *ha;
--      struct Scsi_Host *shost;
-       struct sockaddr_in *addr;
-       struct sockaddr_in6 *addr6;
-       int ret = 0;
--      shost = scsi_host_lookup(host_no);
--      if (IS_ERR(shost)) {
--              printk(KERN_ERR "Could not find host no %u\n", host_no);
--              return -ENODEV;
--      }
--
-       ha = (struct scsi_qla_host *) shost->hostdata;
-       switch (type) {
-@@ -246,8 +288,6 @@
-       default:
-               ret = -ENOSYS;
-       }
--
--      scsi_host_put(shost);
-       return ret;
- }
-@@ -369,14 +409,7 @@
-       struct scsi_cmnd *cmd = srb->cmd;
-       if (srb->flags & SRB_DMA_VALID) {
--              if (cmd->use_sg) {
--                      pci_unmap_sg(ha->pdev, cmd->request_buffer,
--                                   cmd->use_sg, cmd->sc_data_direction);
--              } else if (cmd->request_bufflen) {
--                      pci_unmap_single(ha->pdev, srb->dma_handle,
--                                       cmd->request_bufflen,
--                                       cmd->sc_data_direction);
--              }
-+              scsi_dma_unmap(cmd);
-               srb->flags &= ~SRB_DMA_VALID;
-       }
-       cmd->SCp.ptr = NULL;
-@@ -711,7 +744,7 @@
-       return stat;
- }
--static void qla4xxx_hw_reset(struct scsi_qla_host *ha)
-+void qla4xxx_hw_reset(struct scsi_qla_host *ha)
- {
-       uint32_t ctrl_status;
-       unsigned long flags = 0;
-@@ -1081,13 +1114,13 @@
-       if (ha->timer_active)
-               qla4xxx_stop_timer(ha);
--      /* free extra memory */
--      qla4xxx_mem_free(ha);
--
-       /* Detach interrupts */
-       if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags))
-               free_irq(ha->pdev->irq, ha);
-+      /* free extra memory */
-+      qla4xxx_mem_free(ha);
 +
-       pci_disable_device(ha->pdev);
- }
-@@ -1332,6 +1365,11 @@
-       ha = pci_get_drvdata(pdev);
-+      qla4xxx_disable_intrs(ha);
 +
-+      while (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags))
-+              ssleep(1);
++    CLEAR TARGET
 +
-       /* remove devs from iscsi_sessions to scsi_devices */
-       qla4xxx_free_ddb_list(ha);
-diff -Nurb linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_version.h linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_version.h
---- linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_version.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_version.h        2008-01-02 13:56:37.000000000 -0500
-@@ -5,4 +5,5 @@
-  * See LICENSE.qla4xxx for copyright and licensing details.
-  */
--#define QLA4XXX_DRIVER_VERSION        "5.00.07-k1"
-+#define QLA4XXX_DRIVER_VERSION        "5.01.00-k7"
++at 0x0000007e : */    0x60000200,0x00000000,
++/*
 +
-diff -Nurb linux-2.6.22-570/drivers/scsi/qlogicfas408.c linux-2.6.22-590/drivers/scsi/qlogicfas408.c
---- linux-2.6.22-570/drivers/scsi/qlogicfas408.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/qlogicfas408.c       2008-01-02 13:56:37.000000000 -0500
-@@ -265,8 +265,6 @@
-       unsigned int message;   /* scsi returned message */
-       unsigned int phase;     /* recorded scsi phase */
-       unsigned int reqlen;    /* total length of transfer */
--      struct scatterlist *sglist;     /* scatter-gather list pointer */
--      unsigned int sgcount;   /* sg counter */
-       char *buf;
-       struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
-       int qbase = priv->qbase;
-@@ -301,9 +299,10 @@
-       if (inb(qbase + 7) & 0x1f)      /* if some bytes in fifo */
-               outb(1, qbase + 3);     /* clear fifo */
-       /* note that request_bufflen is the total xfer size when sg is used */
--      reqlen = cmd->request_bufflen;
-+      reqlen = scsi_bufflen(cmd);
-       /* note that it won't work if transfers > 16M are requested */
-       if (reqlen && !((phase = inb(qbase + 4)) & 6)) {        /* data phase */
-+              struct scatterlist *sg;
-               rtrc(2)
-               outb(reqlen, qbase);    /* low-mid xfer cnt */
-               outb(reqlen >> 8, qbase + 1);   /* low-mid xfer cnt */
-@@ -311,23 +310,16 @@
-               outb(0x90, qbase + 3);  /* command do xfer */
-               /* PIO pseudo DMA to buffer or sglist */
-               REG1;
--              if (!cmd->use_sg)
--                      ql_pdma(priv, phase, cmd->request_buffer,
--                              cmd->request_bufflen);
--              else {
--                      sgcount = cmd->use_sg;
--                      sglist = cmd->request_buffer;
--                      while (sgcount--) {
++; XXX
++;
++; In effect, SELECTION operations are backgrounded, with execution
++; continuing until code which waits for REQ or a fatal interrupt is 
++; encountered.
++;
++; So, for more performance, we could overlap the code which removes 
++; the command from the NCRs issue queue with the selection, but 
++; at this point I don't want to deal with the error recovery.
++;
 +
-+              scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) {
-                               if (priv->qabort) {
-                                       REG0;
-                                       return ((priv->qabort == 1 ?
-                                               DID_ABORT : DID_RESET) << 16);
-                               }
--                              buf = page_address(sglist->page) + sglist->offset;
--                              if (ql_pdma(priv, phase, buf, sglist->length))
-+                      buf = page_address(sg->page) + sg->offset;
-+                      if (ql_pdma(priv, phase, buf, sg->length))
-                                       break;
--                              sglist++;
--                      }
-               }
-               REG0;
-               rtrc(2)
-diff -Nurb linux-2.6.22-570/drivers/scsi/scsi_debug.c linux-2.6.22-590/drivers/scsi/scsi_debug.c
---- linux-2.6.22-570/drivers/scsi/scsi_debug.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/scsi_debug.c 2008-01-02 13:56:37.000000000 -0500
-@@ -2405,7 +2405,7 @@
- MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
- MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)");
- MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
--MODULE_PARM_DESC(every_nth, "timeout every nth command(def=100)");
-+MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
- MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
- MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
- MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
-diff -Nurb linux-2.6.22-570/drivers/scsi/scsi_error.c linux-2.6.22-590/drivers/scsi/scsi_error.c
---- linux-2.6.22-570/drivers/scsi/scsi_error.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/scsi_error.c 2008-01-02 13:56:37.000000000 -0500
-@@ -18,12 +18,13 @@
- #include <linux/sched.h>
- #include <linux/timer.h>
- #include <linux/string.h>
--#include <linux/slab.h>
- #include <linux/kernel.h>
-+#include <linux/freezer.h>
- #include <linux/kthread.h>
- #include <linux/interrupt.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
-+#include <linux/scatterlist.h>
- #include <scsi/scsi.h>
- #include <scsi/scsi_cmnd.h>
-@@ -640,16 +641,8 @@
-       memcpy(scmd->cmnd, cmnd, cmnd_size);
-       if (copy_sense) {
--              gfp_t gfp_mask = GFP_ATOMIC;
--
--              if (shost->hostt->unchecked_isa_dma)
--                      gfp_mask |= __GFP_DMA;
--
--              sgl.page = alloc_page(gfp_mask);
--              if (!sgl.page)
--                      return FAILED;
--              sgl.offset = 0;
--              sgl.length = 252;
-+              sg_init_one(&sgl, scmd->sense_buffer,
-+                          sizeof(scmd->sense_buffer));
-               scmd->sc_data_direction = DMA_FROM_DEVICE;
-               scmd->request_bufflen = sgl.length;
-@@ -720,18 +713,6 @@
-       /*
--       * Last chance to have valid sense data.
--       */
--      if (copy_sense) {
--              if (!SCSI_SENSE_VALID(scmd)) {
--                      memcpy(scmd->sense_buffer, page_address(sgl.page),
--                             sizeof(scmd->sense_buffer));
--              }
--              __free_page(sgl.page);
--      }
--
--
--      /*
-        * Restore original data
-        */
-       scmd->request_buffer = old_buffer;
-@@ -1536,8 +1517,6 @@
- {
-       struct Scsi_Host *shost = data;
--      current->flags |= PF_NOFREEZE;
--
-       /*
-        * We use TASK_INTERRUPTIBLE so that the thread is not
-        * counted against the load average as a running process.
-diff -Nurb linux-2.6.22-570/drivers/scsi/scsi_lib.c linux-2.6.22-590/drivers/scsi/scsi_lib.c
---- linux-2.6.22-570/drivers/scsi/scsi_lib.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/scsi_lib.c   2008-01-02 13:56:37.000000000 -0500
-@@ -2290,3 +2290,41 @@
-       kunmap_atomic(virt, KM_BIO_SRC_IRQ);
- }
- EXPORT_SYMBOL(scsi_kunmap_atomic_sg);
 +
-+/**
-+ * scsi_dma_map - perform DMA mapping against command's sg lists
-+ * @cmd:      scsi command
-+ *
-+ * Returns the number of sg lists actually used, zero if the sg lists
-+ * is NULL, or -ENOMEM if the mapping failed.
-+ */
-+int scsi_dma_map(struct scsi_cmnd *cmd)
-+{
-+      int nseg = 0;
 +
-+      if (scsi_sg_count(cmd)) {
-+              struct device *dev = cmd->device->host->shost_gendev.parent;
++    ; Enable selection timer
 +
-+              nseg = dma_map_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
-+                                cmd->sc_data_direction);
-+              if (unlikely(!nseg))
-+                      return -ENOMEM;
-+      }
-+      return nseg;
-+}
-+EXPORT_SYMBOL(scsi_dma_map);
 +
-+/**
-+ * scsi_dma_unmap - unmap command's sg lists mapped by scsi_dma_map
-+ * @cmd:      scsi command
-+ */
-+void scsi_dma_unmap(struct scsi_cmnd *cmd)
-+{
-+      if (scsi_sg_count(cmd)) {
-+              struct device *dev = cmd->device->host->shost_gendev.parent;
 +
-+              dma_unmap_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
-+                           cmd->sc_data_direction);
-+      }
-+}
-+EXPORT_SYMBOL(scsi_dma_unmap);
-diff -Nurb linux-2.6.22-570/drivers/scsi/scsi_netlink.c linux-2.6.22-590/drivers/scsi/scsi_netlink.c
---- linux-2.6.22-570/drivers/scsi/scsi_netlink.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/scsi_netlink.c       2008-01-02 13:56:37.000000000 -0500
-@@ -167,7 +167,7 @@
-               return;
-       }
--      scsi_nl_sock = netlink_kernel_create(NETLINK_SCSITRANSPORT,
-+      scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT,
-                               SCSI_NL_GRP_CNT, scsi_nl_rcv, NULL,
-                               THIS_MODULE);
-       if (!scsi_nl_sock) {
-diff -Nurb linux-2.6.22-570/drivers/scsi/scsi_scan.c linux-2.6.22-590/drivers/scsi/scsi_scan.c
---- linux-2.6.22-570/drivers/scsi/scsi_scan.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/scsi_scan.c  2008-01-02 13:56:37.000000000 -0500
-@@ -1213,7 +1213,7 @@
-  *     Given a struct scsi_lun of: 0a 04 0b 03 00 00 00 00, this function returns
-  *     the integer: 0x0b030a04
-  **/
--static int scsilun_to_int(struct scsi_lun *scsilun)
-+int scsilun_to_int(struct scsi_lun *scsilun)
- {
-       int i;
-       unsigned int lun;
-@@ -1224,6 +1224,7 @@
-                             scsilun->scsi_lun[i + 1]) << (i * 8));
-       return lun;
- }
-+EXPORT_SYMBOL(scsilun_to_int);
- /**
-  * int_to_scsilun: reverts an int into a scsi_lun
-diff -Nurb linux-2.6.22-570/drivers/scsi/scsi_sysfs.c linux-2.6.22-590/drivers/scsi/scsi_sysfs.c
---- linux-2.6.22-570/drivers/scsi/scsi_sysfs.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/scsi_sysfs.c 2008-01-02 13:56:37.000000000 -0500
-@@ -293,30 +293,18 @@
- {
-       struct device_driver *drv = dev->driver;
-       struct scsi_device *sdev = to_scsi_device(dev);
--      struct scsi_host_template *sht = sdev->host->hostt;
-       int err;
-       err = scsi_device_quiesce(sdev);
-       if (err)
-               return err;
--      /* call HLD suspend first */
-       if (drv && drv->suspend) {
-               err = drv->suspend(dev, state);
-               if (err)
-                       return err;
-       }
--      /* then, call host suspend */
--      if (sht->suspend) {
--              err = sht->suspend(sdev, state);
--              if (err) {
--                      if (drv && drv->resume)
--                              drv->resume(dev);
--                      return err;
--              }
--      }
--
-       return 0;
- }
-@@ -324,21 +312,14 @@
- {
-       struct device_driver *drv = dev->driver;
-       struct scsi_device *sdev = to_scsi_device(dev);
--      struct scsi_host_template *sht = sdev->host->hostt;
--      int err = 0, err2 = 0;
-+      int err = 0;
--      /* call host resume first */
--      if (sht->resume)
--              err = sht->resume(sdev);
--
--      /* then, call HLD resume */
-       if (drv && drv->resume)
--              err2 = drv->resume(dev);
-+              err = drv->resume(dev);
-       scsi_device_resume(sdev);
--      /* favor LLD failure */
--      return err ? err : err2;;
-+      return err;
- }
- struct bus_type scsi_bus_type = {
-diff -Nurb linux-2.6.22-570/drivers/scsi/scsi_transport_fc.c linux-2.6.22-590/drivers/scsi/scsi_transport_fc.c
---- linux-2.6.22-570/drivers/scsi/scsi_transport_fc.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/scsi_transport_fc.c  2008-01-02 13:56:37.000000000 -0500
-@@ -19,9 +19,10 @@
-  *
-  *  ========
-  *
-- *  Copyright (C) 2004-2005   James Smart, Emulex Corporation
-+ *  Copyright (C) 2004-2007   James Smart, Emulex Corporation
-  *    Rewrite for host, target, device, and remote port attributes,
-  *    statistics, and service functions...
-+ *    Add vports, etc
-  *
-  */
- #include <linux/module.h>
-@@ -37,6 +38,34 @@
- #include "scsi_priv.h"
- static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
-+static void fc_vport_sched_delete(struct work_struct *work);
++    MOVE CTEST7 & 0xef TO CTEST7
 +
++at 0x00000080 : */    0x7c1bef00,0x00000000,
 +/*
-+ * This is a temporary carrier for creating a vport. It will eventually
-+ * be replaced  by a real message definition for sgio or netlink.
-+ *
-+ * fc_vport_identifiers: This set of data contains all elements
-+ * to uniquely identify and instantiate a FC virtual port.
-+ *
-+ * Notes:
-+ *   symbolic_name: The driver is to append the symbolic_name string data
-+ *      to the symbolic_node_name data that it generates by default.
-+ *      the resulting combination should then be registered with the switch.
-+ *      It is expected that things like Xen may stuff a VM title into
-+ *      this field.
-+ */
-+struct fc_vport_identifiers {
-+      u64 node_name;
-+      u64 port_name;
-+      u32 roles;
-+      bool disable;
-+      enum fc_port_type vport_type;   /* only FC_PORTTYPE_NPIV allowed */
-+      char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
-+};
-+
-+static int fc_vport_create(struct Scsi_Host *shost, int channel,
-+      struct device *pdev, struct fc_vport_identifiers  *ids,
-+      struct fc_vport **vport);
- /*
-  * Redefine so that we can have same named attributes in the
-@@ -90,10 +119,14 @@
-       { FC_PORTTYPE_NLPORT,   "NLPort (fabric via loop)" },
-       { FC_PORTTYPE_LPORT,    "LPort (private loop)" },
-       { FC_PORTTYPE_PTP,      "Point-To-Point (direct nport connection" },
-+      { FC_PORTTYPE_NPIV,             "NPIV VPORT" },
- };
- fc_enum_name_search(port_type, fc_port_type, fc_port_type_names)
- #define FC_PORTTYPE_MAX_NAMELEN               50
-+/* Reuse fc_port_type enum function for vport_type */
-+#define get_fc_vport_type_name get_fc_port_type_name
 +
- /* Convert fc_host_event_code values to ascii string name */
- static const struct {
-@@ -139,6 +172,29 @@
- #define FC_PORTSTATE_MAX_NAMELEN      20
-+/* Convert fc_vport_state values to ascii string name */
-+static struct {
-+      enum fc_vport_state     value;
-+      char                    *name;
-+} fc_vport_state_names[] = {
-+      { FC_VPORT_UNKNOWN,             "Unknown" },
-+      { FC_VPORT_ACTIVE,              "Active" },
-+      { FC_VPORT_DISABLED,            "Disabled" },
-+      { FC_VPORT_LINKDOWN,            "Linkdown" },
-+      { FC_VPORT_INITIALIZING,        "Initializing" },
-+      { FC_VPORT_NO_FABRIC_SUPP,      "No Fabric Support" },
-+      { FC_VPORT_NO_FABRIC_RSCS,      "No Fabric Resources" },
-+      { FC_VPORT_FABRIC_LOGOUT,       "Fabric Logout" },
-+      { FC_VPORT_FABRIC_REJ_WWN,      "Fabric Rejected WWN" },
-+      { FC_VPORT_FAILED,              "VPort Failed" },
-+};
-+fc_enum_name_search(vport_state, fc_vport_state, fc_vport_state_names)
-+#define FC_VPORTSTATE_MAX_NAMELEN     24
 +
-+/* Reuse fc_vport_state enum function for vport_last_state */
-+#define get_fc_vport_last_state_name get_fc_vport_state_name
++    SELECT ATN FROM dsa_select, select_failed
 +
++at 0x00000082 : */    0x4300003c,0x00000828,
++/*
++    JUMP select_msgout, WHEN MSG_OUT
 +
- /* Convert fc_tgtid_binding_type values to ascii string name */
- static const struct {
-       enum fc_tgtid_binding_type      value;
-@@ -219,16 +275,16 @@
- }
--/* Convert FC_RPORT_ROLE bit values to ascii string name */
-+/* Convert FC_PORT_ROLE bit values to ascii string name */
- static const struct {
-       u32                     value;
-       char                    *name;
--} fc_remote_port_role_names[] = {
--      { FC_RPORT_ROLE_FCP_TARGET,     "FCP Target" },
--      { FC_RPORT_ROLE_FCP_INITIATOR,  "FCP Initiator" },
--      { FC_RPORT_ROLE_IP_PORT,        "IP Port" },
-+} fc_port_role_names[] = {
-+      { FC_PORT_ROLE_FCP_TARGET,      "FCP Target" },
-+      { FC_PORT_ROLE_FCP_INITIATOR,   "FCP Initiator" },
-+      { FC_PORT_ROLE_IP_PORT,         "IP Port" },
- };
--fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
-+fc_bitfield_name_search(port_roles, fc_port_role_names)
- /*
-  * Define roles that are specific to port_id. Values are relative to ROLE_MASK.
-@@ -252,7 +308,8 @@
-  */
- #define FC_STARGET_NUM_ATTRS  3
- #define FC_RPORT_NUM_ATTRS    10
--#define FC_HOST_NUM_ATTRS     17
-+#define FC_VPORT_NUM_ATTRS    9
-+#define FC_HOST_NUM_ATTRS     21
- struct fc_internal {
-       struct scsi_transport_template t;
-@@ -278,6 +335,10 @@
-       struct transport_container rport_attr_cont;
-       struct class_device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS];
-       struct class_device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1];
++at 0x00000084 : */    0x860b0000,0x00000218,
++/*
++ENTRY select_msgout
++select_msgout:
 +
-+      struct transport_container vport_attr_cont;
-+      struct class_device_attribute private_vport_attrs[FC_VPORT_NUM_ATTRS];
-+      struct class_device_attribute *vport_attrs[FC_VPORT_NUM_ATTRS + 1];
- };
- #define to_fc_internal(tmpl)  container_of(tmpl, struct fc_internal, t)
-@@ -331,6 +392,7 @@
-               sizeof(fc_host->supported_fc4s));
-       fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN;
-       fc_host->maxframe_size = -1;
-+      fc_host->max_npiv_vports = 0;
-       memset(fc_host->serial_number, 0,
-               sizeof(fc_host->serial_number));
-@@ -348,8 +410,11 @@
-       INIT_LIST_HEAD(&fc_host->rports);
-       INIT_LIST_HEAD(&fc_host->rport_bindings);
-+      INIT_LIST_HEAD(&fc_host->vports);
-       fc_host->next_rport_number = 0;
-       fc_host->next_target_id = 0;
-+      fc_host->next_vport_number = 0;
-+      fc_host->npiv_vports_inuse = 0;
-       snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d",
-               shost->host_no);
-@@ -388,6 +453,16 @@
-                              NULL);
- /*
-+ * Setup and Remove actions for virtual ports are handled
-+ * in the service functions below.
-+ */
-+static DECLARE_TRANSPORT_CLASS(fc_vport_class,
-+                             "fc_vports",
-+                             NULL,
-+                             NULL,
-+                             NULL);
++    ; Disable selection timer
++    MOVE CTEST7 | 0x10 TO CTEST7
 +
++at 0x00000086 : */    0x7a1b1000,0x00000000,
 +/*
-  * Module Parameters
-  */
-@@ -585,6 +660,9 @@
-       error = transport_class_register(&fc_host_class);
-       if (error)
-               return error;
-+      error = transport_class_register(&fc_vport_class);
-+      if (error)
-+              return error;
-       error = transport_class_register(&fc_rport_class);
-       if (error)
-               return error;
-@@ -596,6 +674,7 @@
-       transport_class_unregister(&fc_transport_class);
-       transport_class_unregister(&fc_rport_class);
-       transport_class_unregister(&fc_host_class);
-+      transport_class_unregister(&fc_vport_class);
- }
- /*
-@@ -800,9 +879,9 @@
-                       return snprintf(buf, 30, "Unknown Fabric Entity\n");
-               }
-       } else {
--              if (rport->roles == FC_RPORT_ROLE_UNKNOWN)
-+              if (rport->roles == FC_PORT_ROLE_UNKNOWN)
-                       return snprintf(buf, 20, "unknown\n");
--              return get_fc_remote_port_roles_names(rport->roles, buf);
-+              return get_fc_port_roles_names(rport->roles, buf);
-       }
- }
- static FC_CLASS_DEVICE_ATTR(rport, roles, S_IRUGO,
-@@ -857,7 +936,7 @@
- /*
-  * Note: in the target show function we recognize when the remote
-- *  port is in the hierarchy and do not allow the driver to get
-+ *  port is in the heirarchy and do not allow the driver to get
-  *  involved in sysfs functions. The driver only gets involved if
-  *  it's the "old" style that doesn't use rports.
-  */
-@@ -912,6 +991,257 @@
- /*
-+ * FC Virtual Port Attribute Management
-+ */
 +
-+#define fc_vport_show_function(field, format_string, sz, cast)                \
-+static ssize_t                                                                \
-+show_fc_vport_##field (struct class_device *cdev, char *buf)          \
-+{                                                                     \
-+      struct fc_vport *vport = transport_class_to_vport(cdev);        \
-+      struct Scsi_Host *shost = vport_to_shost(vport);                \
-+      struct fc_internal *i = to_fc_internal(shost->transportt);      \
-+      if ((i->f->get_vport_##field) &&                                \
-+          !(vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)))       \
-+              i->f->get_vport_##field(vport);                         \
-+      return snprintf(buf, sz, format_string, cast vport->field);     \
-+}
-+
-+#define fc_vport_store_function(field)                                        \
-+static ssize_t                                                                \
-+store_fc_vport_##field(struct class_device *cdev, const char *buf,    \
-+                         size_t count)                                \
-+{                                                                     \
-+      int val;                                                        \
-+      struct fc_vport *vport = transport_class_to_vport(cdev);        \
-+      struct Scsi_Host *shost = vport_to_shost(vport);                \
-+      struct fc_internal *i = to_fc_internal(shost->transportt);      \
-+      char *cp;                                                       \
-+      if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))  \
-+              return -EBUSY;                                          \
-+      val = simple_strtoul(buf, &cp, 0);                              \
-+      if (*cp && (*cp != '\n'))                                       \
-+              return -EINVAL;                                         \
-+      i->f->set_vport_##field(vport, val);                            \
-+      return count;                                                   \
-+}
-+
-+#define fc_vport_store_str_function(field, slen)                      \
-+static ssize_t                                                                \
-+store_fc_vport_##field(struct class_device *cdev, const char *buf,    \
-+                         size_t count)                                \
-+{                                                                     \
-+      struct fc_vport *vport = transport_class_to_vport(cdev);        \
-+      struct Scsi_Host *shost = vport_to_shost(vport);                \
-+      struct fc_internal *i = to_fc_internal(shost->transportt);      \
-+      unsigned int cnt=count;                                         \
-+                                                                      \
-+      /* count may include a LF at end of string */                   \
-+      if (buf[cnt-1] == '\n')                                         \
-+              cnt--;                                                  \
-+      if (cnt > ((slen) - 1))                                         \
-+              return -EINVAL;                                         \
-+      memcpy(vport->field, buf, cnt);                                 \
-+      i->f->set_vport_##field(vport);                                 \
-+      return count;                                                   \
-+}
-+
-+#define fc_vport_rd_attr(field, format_string, sz)                    \
-+      fc_vport_show_function(field, format_string, sz, )              \
-+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,                    \
-+                       show_fc_vport_##field, NULL)
-+
-+#define fc_vport_rd_attr_cast(field, format_string, sz, cast)         \
-+      fc_vport_show_function(field, format_string, sz, (cast))        \
-+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,                    \
-+                        show_fc_vport_##field, NULL)
-+
-+#define fc_vport_rw_attr(field, format_string, sz)                    \
-+      fc_vport_show_function(field, format_string, sz, )              \
-+      fc_vport_store_function(field)                                  \
-+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,          \
-+                      show_fc_vport_##field,                          \
-+                      store_fc_vport_##field)
-+
-+#define fc_private_vport_show_function(field, format_string, sz, cast)        \
-+static ssize_t                                                                \
-+show_fc_vport_##field (struct class_device *cdev, char *buf)          \
-+{                                                                     \
-+      struct fc_vport *vport = transport_class_to_vport(cdev);        \
-+      return snprintf(buf, sz, format_string, cast vport->field);     \
-+}
++    MOVE FROM dsa_msgout, WHEN MSG_OUT
 +
-+#define fc_private_vport_store_u32_function(field)                    \
-+static ssize_t                                                                \
-+store_fc_vport_##field(struct class_device *cdev, const char *buf,    \
-+                         size_t count)                                \
-+{                                                                     \
-+      u32 val;                                                        \
-+      struct fc_vport *vport = transport_class_to_vport(cdev);        \
-+      char *cp;                                                       \
-+      if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))          \
-+              return -EBUSY;                                          \
-+      val = simple_strtoul(buf, &cp, 0);                              \
-+      if (*cp && (*cp != '\n'))                                       \
-+              return -EINVAL;                                         \
-+      vport->field = val;                                             \
-+      return count;                                                   \
-+}
-+
-+
-+#define fc_private_vport_rd_attr(field, format_string, sz)            \
-+      fc_private_vport_show_function(field, format_string, sz, )      \
-+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,                    \
-+                       show_fc_vport_##field, NULL)
-+
-+#define fc_private_vport_rd_attr_cast(field, format_string, sz, cast) \
-+      fc_private_vport_show_function(field, format_string, sz, (cast)) \
-+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,                    \
-+                        show_fc_vport_##field, NULL)
-+
-+#define fc_private_vport_rw_u32_attr(field, format_string, sz)                \
-+      fc_private_vport_show_function(field, format_string, sz, )      \
-+      fc_private_vport_store_u32_function(field)                      \
-+static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,          \
-+                      show_fc_vport_##field,                          \
-+                      store_fc_vport_##field)
-+
-+
-+#define fc_private_vport_rd_enum_attr(title, maxlen)                  \
-+static ssize_t                                                                \
-+show_fc_vport_##title (struct class_device *cdev, char *buf)          \
-+{                                                                     \
-+      struct fc_vport *vport = transport_class_to_vport(cdev);        \
-+      const char *name;                                               \
-+      name = get_fc_##title##_name(vport->title);                     \
-+      if (!name)                                                      \
-+              return -EINVAL;                                         \
-+      return snprintf(buf, maxlen, "%s\n", name);                     \
-+}                                                                     \
-+static FC_CLASS_DEVICE_ATTR(vport, title, S_IRUGO,                    \
-+                      show_fc_vport_##title, NULL)
-+
-+
-+#define SETUP_VPORT_ATTRIBUTE_RD(field)                                       \
-+      i->private_vport_attrs[count] = class_device_attr_vport_##field; \
-+      i->private_vport_attrs[count].attr.mode = S_IRUGO;              \
-+      i->private_vport_attrs[count].store = NULL;                     \
-+      i->vport_attrs[count] = &i->private_vport_attrs[count];         \
-+      if (i->f->get_##field)                                          \
-+              count++
-+      /* NOTE: Above MACRO differs: checks function not show bit */
-+
-+#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(field)                               \
-+      i->private_vport_attrs[count] = class_device_attr_vport_##field; \
-+      i->private_vport_attrs[count].attr.mode = S_IRUGO;              \
-+      i->private_vport_attrs[count].store = NULL;                     \
-+      i->vport_attrs[count] = &i->private_vport_attrs[count];         \
-+      count++
-+
-+#define SETUP_VPORT_ATTRIBUTE_WR(field)                                       \
-+      i->private_vport_attrs[count] = class_device_attr_vport_##field; \
-+      i->vport_attrs[count] = &i->private_vport_attrs[count];         \
-+      if (i->f->field)                                                \
-+              count++
-+      /* NOTE: Above MACRO differs: checks function */
-+
-+#define SETUP_VPORT_ATTRIBUTE_RW(field)                                       \
-+      i->private_vport_attrs[count] = class_device_attr_vport_##field; \
-+      if (!i->f->set_vport_##field) {                                 \
-+              i->private_vport_attrs[count].attr.mode = S_IRUGO;      \
-+              i->private_vport_attrs[count].store = NULL;             \
-+      }                                                               \
-+      i->vport_attrs[count] = &i->private_vport_attrs[count];         \
-+      count++
-+      /* NOTE: Above MACRO differs: does not check show bit */
-+
-+#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RW(field)                               \
-+{                                                                     \
-+      i->private_vport_attrs[count] = class_device_attr_vport_##field; \
-+      i->vport_attrs[count] = &i->private_vport_attrs[count];         \
-+      count++;                                                        \
-+}
++at 0x00000088 : */    0x1e000000,0x00000040,
++/*
 +
 +
-+/* The FC Transport Virtual Port Attributes: */
 +
-+/* Fixed Virtual Port Attributes */
 +
-+/* Dynamic Virtual Port Attributes */
 +
-+/* Private Virtual Port Attributes */
 +
-+fc_private_vport_rd_enum_attr(vport_state, FC_VPORTSTATE_MAX_NAMELEN);
-+fc_private_vport_rd_enum_attr(vport_last_state, FC_VPORTSTATE_MAX_NAMELEN);
-+fc_private_vport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
-+fc_private_vport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
 +
-+static ssize_t
-+show_fc_vport_roles (struct class_device *cdev, char *buf)
-+{
-+      struct fc_vport *vport = transport_class_to_vport(cdev);
 +
-+      if (vport->roles == FC_PORT_ROLE_UNKNOWN)
-+              return snprintf(buf, 20, "unknown\n");
-+      return get_fc_port_roles_names(vport->roles, buf);
-+}
-+static FC_CLASS_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL);
 +
-+fc_private_vport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN);
 +
-+fc_private_vport_show_function(symbolic_name, "%s\n",
-+              FC_VPORT_SYMBOLIC_NAMELEN + 1, )
-+fc_vport_store_str_function(symbolic_name, FC_VPORT_SYMBOLIC_NAMELEN)
-+static FC_CLASS_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR,
-+              show_fc_vport_symbolic_name, store_fc_vport_symbolic_name);
++   RETURN
 +
-+static ssize_t
-+store_fc_vport_delete(struct class_device *cdev, const char *buf,
-+                         size_t count)
-+{
-+      struct fc_vport *vport = transport_class_to_vport(cdev);
-+      struct Scsi_Host *shost = vport_to_shost(vport);
++at 0x0000008a : */    0x90080000,0x00000000,
++/*
 +
-+      fc_queue_work(shost, &vport->vport_delete_work);
-+      return count;
-+}
-+static FC_CLASS_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
-+                      NULL, store_fc_vport_delete);
++; 
++; select_done
++; 
++; PURPOSE: continue on to normal data transfer; called as the exit 
++;     point from dsa_begin.
++;
++; INPUTS: dsa
++;
++; CALLS: OK
++;
++;
++
++select_done:
 +
++; NOTE DSA is corrupt when we arrive here!
++    MOVE MEMORY 4, saved_dsa, addr_dsa
 +
++at 0x0000008c : */    0xc0000004,0x00000000,0x00000000,
 +/*
-+ * Enable/Disable vport
-+ *  Write "1" to disable, write "0" to enable
-+ */
-+static ssize_t
-+store_fc_vport_disable(struct class_device *cdev, const char *buf,
-+                         size_t count)
-+{
-+      struct fc_vport *vport = transport_class_to_vport(cdev);
-+      struct Scsi_Host *shost = vport_to_shost(vport);
-+      struct fc_internal *i = to_fc_internal(shost->transportt);
-+      int stat;
 +
-+      if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))
-+              return -EBUSY;
 +
-+      if (*buf == '0') {
-+              if (vport->vport_state != FC_VPORT_DISABLED)
-+                      return -EALREADY;
-+      } else if (*buf == '1') {
-+              if (vport->vport_state == FC_VPORT_DISABLED)
-+                      return -EALREADY;
-+      } else
-+              return -EINVAL;
 +
-+      stat = i->f->vport_disable(vport, ((*buf == '0') ? false : true));
-+      return stat ? stat : count;
-+}
-+static FC_CLASS_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
-+                      NULL, store_fc_vport_disable);
 +
 +
-+/*
-  * Host Attribute Management
-  */
-@@ -1003,6 +1333,13 @@
-       if (i->f->show_host_##field)                                    \
-               count++
-+#define SETUP_HOST_ATTRIBUTE_RD_NS(field)                             \
-+      i->private_host_attrs[count] = class_device_attr_host_##field;  \
-+      i->private_host_attrs[count].attr.mode = S_IRUGO;               \
-+      i->private_host_attrs[count].store = NULL;                      \
-+      i->host_attrs[count] = &i->private_host_attrs[count];           \
-+      count++
 +
- #define SETUP_HOST_ATTRIBUTE_RW(field)                                        \
-       i->private_host_attrs[count] = class_device_attr_host_##field;  \
-       if (!i->f->set_host_##field) {                                  \
-@@ -1090,6 +1427,7 @@
- fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20,
-                            unsigned long long);
- fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
-+fc_private_host_rd_attr(max_npiv_vports, "%u\n", 20);
- fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
-@@ -1210,6 +1548,9 @@
- static FC_CLASS_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
-                       store_fc_private_host_issue_lip);
-+fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
 +
 +
- /*
-  * Host Statistics Management
-  */
-@@ -1285,7 +1626,6 @@
- static FC_CLASS_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL,
-                               fc_reset_statistics);
--
- static struct attribute *fc_statistics_attrs[] = {
-       &class_device_attr_host_seconds_since_last_reset.attr,
-       &class_device_attr_host_tx_frames.attr,
-@@ -1316,6 +1656,142 @@
-       .attrs = fc_statistics_attrs,
- };
++; After a successful selection, we should get either a CMD phase or 
++; some transfer request negotiation message.
 +
-+/* Host Vport Attributes */
++    JUMP cmdout, WHEN CMD
 +
-+static int
-+fc_parse_wwn(const char *ns, u64 *nm)
-+{
-+      unsigned int i, j;
-+      u8 wwn[8];
++at 0x0000008f : */    0x820b0000,0x0000025c,
++/*
++    INT int_err_unexpected_phase, WHEN NOT MSG_IN 
 +
-+      memset(wwn, 0, sizeof(wwn));
++at 0x00000091 : */    0x9f030000,0x00000000,
++/*
 +
-+      /* Validate and store the new name */
-+      for (i=0, j=0; i < 16; i++) {
-+              if ((*ns >= 'a') && (*ns <= 'f'))
-+                      j = ((j << 4) | ((*ns++ -'a') + 10));
-+              else if ((*ns >= 'A') && (*ns <= 'F'))
-+                      j = ((j << 4) | ((*ns++ -'A') + 10));
-+              else if ((*ns >= '0') && (*ns <= '9'))
-+                      j = ((j << 4) | (*ns++ -'0'));
-+              else
-+                      return -EINVAL;
-+              if (i % 2) {
-+                      wwn[i/2] = j & 0xff;
-+                      j = 0;
-+              }
-+      }
++select_msg_in:
++    CALL msg_in, WHEN MSG_IN
 +
-+      *nm = wwn_to_u64(wwn);
++at 0x00000093 : */    0x8f0b0000,0x0000041c,
++/*
++    JUMP select_msg_in, WHEN MSG_IN
 +
-+      return 0;
-+}
++at 0x00000095 : */    0x870b0000,0x0000024c,
++/*
 +
++cmdout:
++    INT int_err_unexpected_phase, WHEN NOT CMD
 +
++at 0x00000097 : */    0x9a030000,0x00000000,
 +/*
-+ * "Short-cut" sysfs variable to create a new vport on a FC Host.
-+ * Input is a string of the form "<WWPN>:<WWNN>". Other attributes
-+ * will default to a NPIV-based FCP_Initiator; The WWNs are specified
-+ * as hex characters, and may *not* contain any prefixes (e.g. 0x, x, etc)
-+ */
-+static ssize_t
-+store_fc_host_vport_create(struct class_device *cdev, const char *buf,
-+                         size_t count)
-+{
-+      struct Scsi_Host *shost = transport_class_to_shost(cdev);
-+      struct fc_vport_identifiers vid;
-+      struct fc_vport *vport;
-+      unsigned int cnt=count;
-+      int stat;
 +
-+      memset(&vid, 0, sizeof(vid));
 +
-+      /* count may include a LF at end of string */
-+      if (buf[cnt-1] == '\n')
-+              cnt--;
 +
-+      /* validate we have enough characters for WWPN */
-+      if ((cnt != (16+1+16)) || (buf[16] != ':'))
-+              return -EINVAL;
++ENTRY cmdout_cmdout
++cmdout_cmdout:
 +
-+      stat = fc_parse_wwn(&buf[0], &vid.port_name);
-+      if (stat)
-+              return stat;
++    MOVE FROM dsa_cmdout, WHEN CMD
 +
-+      stat = fc_parse_wwn(&buf[17], &vid.node_name);
-+      if (stat)
-+              return stat;
++at 0x00000099 : */    0x1a000000,0x00000048,
++/*
 +
-+      vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
-+      vid.vport_type = FC_PORTTYPE_NPIV;
-+      /* vid.symbolic_name is already zero/NULL's */
-+      vid.disable = false;            /* always enabled */
 +
-+      /* we only allow support on Channel 0 !!! */
-+      stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport);
-+      return stat ? stat : count;
-+}
-+static FC_CLASS_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
-+                      store_fc_host_vport_create);
 +
 +
++;
++; data_transfer  
++; other_out
++; other_in
++; other_transfer
++;
++; PURPOSE : handle the main data transfer for a SCSI command in 
++;     several parts.  In the first part, data_transfer, DATA_IN
++;     and DATA_OUT phases are allowed, with the user provided
++;     code (usually dynamically generated based on the scatter/gather
++;     list associated with a SCSI command) called to handle these 
++;     phases.
++;
++;     After control has passed to one of the user provided 
++;     DATA_IN or DATA_OUT routines, back calls are made to 
++;     other_transfer_in or other_transfer_out to handle non-DATA IN
++;     and DATA OUT phases respectively, with the state of the active
++;     data pointer being preserved in TEMP.
++;
++;     On completion, the user code passes control to other_transfer
++;     which causes DATA_IN and DATA_OUT to result in unexpected_phase
++;     interrupts so that data overruns may be trapped.
++;
++; INPUTS : DSA - SCSI command
++;
++; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in
++;     other_transfer
++;
++; MODIFIES : SCRATCH
++;
++; EXITS : if STATUS IN is detected, signifying command completion,
++;     the NCR jumps to command_complete.  If MSG IN occurs, a 
++;     CALL is made to msg_in.  Otherwise, other_transfer runs in 
++;     an infinite loop.
++;     
++
++ENTRY data_transfer
++data_transfer:
++    JUMP cmdout_cmdout, WHEN CMD
++
++at 0x0000009b : */    0x820b0000,0x00000264,
 +/*
-+ * "Short-cut" sysfs variable to delete a vport on a FC Host.
-+ * Vport is identified by a string containing "<WWPN>:<WWNN>".
-+ * The WWNs are specified as hex characters, and may *not* contain
-+ * any prefixes (e.g. 0x, x, etc)
-+ */
-+static ssize_t
-+store_fc_host_vport_delete(struct class_device *cdev, const char *buf,
-+                         size_t count)
-+{
-+      struct Scsi_Host *shost = transport_class_to_shost(cdev);
-+      struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
-+      struct fc_vport *vport;
-+      u64 wwpn, wwnn;
-+      unsigned long flags;
-+      unsigned int cnt=count;
-+      int stat, match;
++    CALL msg_in, WHEN MSG_IN
 +
-+      /* count may include a LF at end of string */
-+      if (buf[cnt-1] == '\n')
-+              cnt--;
++at 0x0000009d : */    0x8f0b0000,0x0000041c,
++/*
++    INT int_err_unexpected_phase, WHEN MSG_OUT
 +
-+      /* validate we have enough characters for WWPN */
-+      if ((cnt != (16+1+16)) || (buf[16] != ':'))
-+              return -EINVAL;
++at 0x0000009f : */    0x9e0b0000,0x00000000,
++/*
++    JUMP do_dataout, WHEN DATA_OUT
 +
-+      stat = fc_parse_wwn(&buf[0], &wwpn);
-+      if (stat)
-+              return stat;
++at 0x000000a1 : */    0x800b0000,0x000002a4,
++/*
++    JUMP do_datain, WHEN DATA_IN
 +
-+      stat = fc_parse_wwn(&buf[17], &wwnn);
-+      if (stat)
-+              return stat;
++at 0x000000a3 : */    0x810b0000,0x000002fc,
++/*
++    JUMP command_complete, WHEN STATUS
 +
-+      spin_lock_irqsave(shost->host_lock, flags);
-+      match = 0;
-+      /* we only allow support on Channel 0 !!! */
-+      list_for_each_entry(vport, &fc_host->vports, peers) {
-+              if ((vport->channel == 0) &&
-+                  (vport->port_name == wwpn) && (vport->node_name == wwnn)) {
-+                      match = 1;
-+                      break;
-+              }
-+      }
-+      spin_unlock_irqrestore(shost->host_lock, flags);
++at 0x000000a5 : */    0x830b0000,0x0000065c,
++/*
++    JUMP data_transfer
 +
-+      if (!match)
-+              return -ENODEV;
++at 0x000000a7 : */    0x80080000,0x0000026c,
++/*
++ENTRY end_data_transfer
++end_data_transfer:
 +
-+      stat = fc_vport_terminate(vport);
-+      return stat ? stat : count;
-+}
-+static FC_CLASS_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL,
-+                      store_fc_host_vport_delete);
++;
++; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain 
++; should be fixed up whenever the nexus changes so it can point to the 
++; correct routine for that command.
++;
 +
 +
- static int fc_host_match(struct attribute_container *cont,
-                         struct device *dev)
- {
-@@ -1387,6 +1863,40 @@
- }
-+static void fc_vport_dev_release(struct device *dev)
-+{
-+      struct fc_vport *vport = dev_to_vport(dev);
-+      put_device(dev->parent);                /* release kobj parent */
-+      kfree(vport);
-+}
++; Nasty jump to dsa->dataout
++do_dataout:
 +
-+int scsi_is_fc_vport(const struct device *dev)
-+{
-+      return dev->release == fc_vport_dev_release;
-+}
-+EXPORT_SYMBOL(scsi_is_fc_vport);
++    MOVE MEMORY 4, saved_dsa, addr_scratch
 +
-+static int fc_vport_match(struct attribute_container *cont,
-+                          struct device *dev)
-+{
-+      struct fc_vport *vport;
-+      struct Scsi_Host *shost;
-+      struct fc_internal *i;
++at 0x000000a9 : */    0xc0000004,0x00000000,0x00000000,
++/*
 +
-+      if (!scsi_is_fc_vport(dev))
-+              return 0;
-+      vport = dev_to_vport(dev);
 +
-+      shost = vport_to_shost(vport);
-+      if (!shost->transportt  || shost->transportt->host_attrs.ac.class
-+          != &fc_host_class.class)
-+              return 0;
 +
-+      i = to_fc_internal(shost->transportt);
-+      return &i->vport_attr_cont.ac == cont;
-+}
++    MOVE SCRATCH0 + dsa_dataout TO SCRATCH0   
 +
++at 0x000000ac : */    0x7e345000,0x00000000,
++/*
++    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
 +
- /**
-  * fc_timed_out - FC Transport I/O timeout intercept handler
-  *
-@@ -1433,6 +1943,9 @@
-               if (rport->scsi_target_id == -1)
-                       continue;
-+              if (rport->port_state != FC_PORTSTATE_ONLINE)
-+                      continue;
++at 0x000000ae : */    0x7f350000,0x00000000,
++/*
++    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
 +
-               if ((channel == SCAN_WILD_CARD || channel == rport->channel) &&
-                   (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) {
-                       scsi_scan_target(&rport->dev, rport->channel,
-@@ -1472,6 +1985,11 @@
-       i->rport_attr_cont.ac.match = fc_rport_match;
-       transport_container_register(&i->rport_attr_cont);
-+      i->vport_attr_cont.ac.attrs = &i->vport_attrs[0];
-+      i->vport_attr_cont.ac.class = &fc_vport_class.class;
-+      i->vport_attr_cont.ac.match = fc_vport_match;
-+      transport_container_register(&i->vport_attr_cont);
++at 0x000000b0 : */    0x7f360000,0x00000000,
++/*
++    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
 +
-       i->f = ft;
-       /* Transport uses the shost workq for scsi scanning */
-@@ -1505,6 +2023,10 @@
-       SETUP_HOST_ATTRIBUTE_RD(supported_fc4s);
-       SETUP_HOST_ATTRIBUTE_RD(supported_speeds);
-       SETUP_HOST_ATTRIBUTE_RD(maxframe_size);
-+      if (ft->vport_create) {
-+              SETUP_HOST_ATTRIBUTE_RD_NS(max_npiv_vports);
-+              SETUP_HOST_ATTRIBUTE_RD_NS(npiv_vports_inuse);
-+      }
-       SETUP_HOST_ATTRIBUTE_RD(serial_number);
-       SETUP_HOST_ATTRIBUTE_RD(port_id);
-@@ -1520,6 +2042,10 @@
-       SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);
-       if (ft->issue_fc_host_lip)
-               SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip);
-+      if (ft->vport_create)
-+              SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_create);
-+      if (ft->vport_delete)
-+              SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_delete);
-       BUG_ON(count > FC_HOST_NUM_ATTRS);
-@@ -1545,6 +2071,24 @@
-       i->rport_attrs[count] = NULL;
-+      /*
-+       * Setup Virtual Port Attributes.
-+       */
-+      count=0;
-+      SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_state);
-+      SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_last_state);
-+      SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(node_name);
-+      SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(port_name);
-+      SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(roles);
-+      SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_type);
-+      SETUP_VPORT_ATTRIBUTE_RW(symbolic_name);
-+      SETUP_VPORT_ATTRIBUTE_WR(vport_delete);
-+      SETUP_VPORT_ATTRIBUTE_WR(vport_disable);
++at 0x000000b2 : */    0x7f370000,0x00000000,
++/*
++    
++    MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4
 +
-+      BUG_ON(count > FC_VPORT_NUM_ATTRS);
++at 0x000000b4 : */    0xc0000004,0x00000000,0x000002e0,
++/*
++    
++dataout_to_jump:
++    MOVE MEMORY 4, 0, dataout_jump + 4 
 +
-+      i->vport_attrs[count] = NULL;
++at 0x000000b7 : */    0xc0000004,0x00000000,0x000002f8,
++/*
 +
-       return &i->t;
- }
- EXPORT_SYMBOL(fc_attach_transport);
-@@ -1556,6 +2100,7 @@
-       transport_container_unregister(&i->t.target_attrs);
-       transport_container_unregister(&i->t.host_attrs);
-       transport_container_unregister(&i->rport_attr_cont);
-+      transport_container_unregister(&i->vport_attr_cont);
-       kfree(i);
- }
-@@ -1667,9 +2212,17 @@
- void
- fc_remove_host(struct Scsi_Host *shost)
- {
--      struct fc_rport *rport, *next_rport;
-+      struct fc_vport *vport = NULL, *next_vport = NULL;
-+      struct fc_rport *rport = NULL, *next_rport = NULL;
-       struct workqueue_struct *work_q;
-       struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
-+      unsigned long flags;
++    ; Time to correct DSA following memory move
++    MOVE MEMORY 4, saved_dsa, addr_dsa
 +
-+      spin_lock_irqsave(shost->host_lock, flags);
++at 0x000000ba : */    0xc0000004,0x00000000,0x00000000,
++/*
 +
-+      /* Remove any vports */
-+      list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers)
-+              fc_queue_work(shost, &vport->vport_delete_work);
-       /* Remove any remote ports */
-       list_for_each_entry_safe(rport, next_rport,
-@@ -1686,6 +2239,8 @@
-               fc_queue_work(shost, &rport->rport_delete_work);
-       }
-+      spin_unlock_irqrestore(shost->host_lock, flags);
++dataout_jump:
++    JUMP 0
 +
-       /* flush all scan work items */
-       scsi_flush_work(shost);
-@@ -1844,7 +2399,7 @@
-       spin_lock_irqsave(shost->host_lock, flags);
-       rport->number = fc_host->next_rport_number++;
--      if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
-+      if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
-               rport->scsi_target_id = fc_host->next_target_id++;
-       else
-               rport->scsi_target_id = -1;
-@@ -1869,7 +2424,7 @@
-       transport_add_device(dev);
-       transport_configure_device(dev);
--      if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
-+      if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
-               /* initiate a scan of the target */
-               rport->flags |= FC_RPORT_SCAN_PENDING;
-               scsi_queue_work(shost, &rport->scan_work);
-@@ -2003,7 +2558,7 @@
-                               /* was a target, not in roles */
-                               if ((rport->scsi_target_id != -1) &&
--                                  (!(ids->roles & FC_RPORT_ROLE_FCP_TARGET)))
-+                                  (!(ids->roles & FC_PORT_ROLE_FCP_TARGET)))
-                                       return rport;
-                               /*
-@@ -2086,7 +2641,7 @@
-                               memset(rport->dd_data, 0,
-                                               fci->f->dd_fcrport_size);
--                      if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
-+                      if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
-                               /* initiate a scan of the target */
-                               rport->flags |= FC_RPORT_SCAN_PENDING;
-                               scsi_queue_work(shost, &rport->scan_work);
-@@ -2243,11 +2798,11 @@
-       int create = 0;
-       spin_lock_irqsave(shost->host_lock, flags);
--      if (roles & FC_RPORT_ROLE_FCP_TARGET) {
-+      if (roles & FC_PORT_ROLE_FCP_TARGET) {
-               if (rport->scsi_target_id == -1) {
-                       rport->scsi_target_id = fc_host->next_target_id++;
-                       create = 1;
--              } else if (!(rport->roles & FC_RPORT_ROLE_FCP_TARGET))
-+              } else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET))
-                       create = 1;
-       }
-@@ -2317,7 +2872,7 @@
-        */
-       if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
-           (rport->scsi_target_id != -1) &&
--          !(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
-+          !(rport->roles & FC_PORT_ROLE_FCP_TARGET)) {
-               dev_printk(KERN_ERR, &rport->dev,
-                       "blocked FC remote port time out: no longer"
-                       " a FCP target, removing starget\n");
-@@ -2367,7 +2922,7 @@
-        */
-       rport->maxframe_size = -1;
-       rport->supported_classes = FC_COS_UNSPECIFIED;
--      rport->roles = FC_RPORT_ROLE_UNKNOWN;
-+      rport->roles = FC_PORT_ROLE_UNKNOWN;
-       rport->port_state = FC_PORTSTATE_NOTPRESENT;
-       /* remove the identifiers that aren't used in the consisting binding */
-@@ -2436,7 +2991,7 @@
-       unsigned long flags;
-       if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
--          (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
-+          (rport->roles & FC_PORT_ROLE_FCP_TARGET)) {
-               scsi_scan_target(&rport->dev, rport->channel,
-                       rport->scsi_target_id, SCAN_WILD_CARD, 1);
-       }
-@@ -2447,7 +3002,227 @@
- }
--MODULE_AUTHOR("Martin Hicks");
-+/**
-+ * fc_vport_create - allocates and creates a FC virtual port.
-+ * @shost:    scsi host the virtual port is connected to.
-+ * @channel:  Channel on shost port connected to.
-+ * @pdev:     parent device for vport
-+ * @ids:      The world wide names, FC4 port roles, etc for
-+ *              the virtual port.
-+ * @ret_vport:        The pointer to the created vport.
-+ *
-+ * Allocates and creates the vport structure, calls the parent host
-+ * to instantiate the vport, the completes w/ class and sysfs creation.
-+ *
-+ * Notes:
-+ *    This routine assumes no locks are held on entry.
-+ **/
-+static int
-+fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev,
-+      struct fc_vport_identifiers  *ids, struct fc_vport **ret_vport)
-+{
-+      struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
-+      struct fc_internal *fci = to_fc_internal(shost->transportt);
-+      struct fc_vport *vport;
-+      struct device *dev;
-+      unsigned long flags;
-+      size_t size;
-+      int error;
++at 0x000000bd : */    0x80080000,0x00000000,
++/*
++
++; Nasty jump to dsa->dsain
++do_datain:
++
++    MOVE MEMORY 4, saved_dsa, addr_scratch
 +
-+      *ret_vport = NULL;
++at 0x000000bf : */    0xc0000004,0x00000000,0x00000000,
++/*
 +
-+      if ( ! fci->f->vport_create)
-+              return -ENOENT;
 +
-+      size = (sizeof(struct fc_vport) + fci->f->dd_fcvport_size);
-+      vport = kzalloc(size, GFP_KERNEL);
-+      if (unlikely(!vport)) {
-+              printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
-+              return -ENOMEM;
-+      }
 +
-+      vport->vport_state = FC_VPORT_UNKNOWN;
-+      vport->vport_last_state = FC_VPORT_UNKNOWN;
-+      vport->node_name = ids->node_name;
-+      vport->port_name = ids->port_name;
-+      vport->roles = ids->roles;
-+      vport->vport_type = ids->vport_type;
-+      if (fci->f->dd_fcvport_size)
-+              vport->dd_data = &vport[1];
-+      vport->shost = shost;
-+      vport->channel = channel;
-+      vport->flags = FC_VPORT_CREATING;
-+      INIT_WORK(&vport->vport_delete_work, fc_vport_sched_delete);
-+
-+      spin_lock_irqsave(shost->host_lock, flags);
-+
-+      if (fc_host->npiv_vports_inuse >= fc_host->max_npiv_vports) {
-+              spin_unlock_irqrestore(shost->host_lock, flags);
-+              kfree(vport);
-+              return -ENOSPC;
-+      }
-+      fc_host->npiv_vports_inuse++;
-+      vport->number = fc_host->next_vport_number++;
-+      list_add_tail(&vport->peers, &fc_host->vports);
-+      get_device(&shost->shost_gendev);       /* for fc_host->vport list */
++    MOVE SCRATCH0 + dsa_datain TO SCRATCH0    
 +
-+      spin_unlock_irqrestore(shost->host_lock, flags);
++at 0x000000c2 : */    0x7e345400,0x00000000,
++/*
++    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
 +
-+      dev = &vport->dev;
-+      device_initialize(dev);                 /* takes self reference */
-+      dev->parent = get_device(pdev);         /* takes parent reference */
-+      dev->release = fc_vport_dev_release;
-+      sprintf(dev->bus_id, "vport-%d:%d-%d",
-+              shost->host_no, channel, vport->number);
-+      transport_setup_device(dev);
++at 0x000000c4 : */    0x7f350000,0x00000000,
++/*
++    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
 +
-+      error = device_add(dev);
-+      if (error) {
-+              printk(KERN_ERR "FC Virtual Port device_add failed\n");
-+              goto delete_vport;
-+      }
-+      transport_add_device(dev);
-+      transport_configure_device(dev);
++at 0x000000c6 : */    0x7f360000,0x00000000,
++/*
++    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
 +
-+      error = fci->f->vport_create(vport, ids->disable);
-+      if (error) {
-+              printk(KERN_ERR "FC Virtual Port LLDD Create failed\n");
-+              goto delete_vport_all;
-+      }
++at 0x000000c8 : */    0x7f370000,0x00000000,
++/*
++    
++    MOVE MEMORY 4, addr_scratch, datain_to_jump + 4
 +
-+      /*
-+       * if the parent isn't the physical adapter's Scsi_Host, ensure
-+       * the Scsi_Host at least contains ia symlink to the vport.
-+       */
-+      if (pdev != &shost->shost_gendev) {
-+              error = sysfs_create_link(&shost->shost_gendev.kobj,
-+                               &dev->kobj, dev->bus_id);
-+              if (error)
-+                      printk(KERN_ERR
-+                              "%s: Cannot create vport symlinks for "
-+                              "%s, err=%d\n",
-+                              __FUNCTION__, dev->bus_id, error);
-+      }
-+      spin_lock_irqsave(shost->host_lock, flags);
-+      vport->flags &= ~FC_VPORT_CREATING;
-+      spin_unlock_irqrestore(shost->host_lock, flags);
++at 0x000000ca : */    0xc0000004,0x00000000,0x00000338,
++/*
++    
++ENTRY datain_to_jump
++datain_to_jump:
++    MOVE MEMORY 4, 0, datain_jump + 4
 +
-+      dev_printk(KERN_NOTICE, pdev,
-+                      "%s created via shost%d channel %d\n", dev->bus_id,
-+                      shost->host_no, channel);
++at 0x000000cd : */    0xc0000004,0x00000000,0x00000350,
++/*
 +
-+      *ret_vport = vport;
++    ; Time to correct DSA following memory move
++    MOVE MEMORY 4, saved_dsa, addr_dsa
 +
-+      return 0;
++at 0x000000d0 : */    0xc0000004,0x00000000,0x00000000,
++/*
 +
-+delete_vport_all:
-+      transport_remove_device(dev);
-+      device_del(dev);
-+delete_vport:
-+      transport_destroy_device(dev);
-+      spin_lock_irqsave(shost->host_lock, flags);
-+      list_del(&vport->peers);
-+      put_device(&shost->shost_gendev);       /* for fc_host->vport list */
-+      fc_host->npiv_vports_inuse--;
-+      spin_unlock_irqrestore(shost->host_lock, flags);
-+      put_device(dev->parent);
-+      kfree(vport);
 +
-+      return error;
-+}
 +
 +
-+/**
-+ * fc_vport_terminate - Admin App or LLDD requests termination of a vport
-+ * @vport:    fc_vport to be terminated
-+ *
-+ * Calls the LLDD vport_delete() function, then deallocates and removes
-+ * the vport from the shost and object tree.
-+ *
-+ * Notes:
-+ *    This routine assumes no locks are held on entry.
-+ **/
-+int
-+fc_vport_terminate(struct fc_vport *vport)
-+{
-+      struct Scsi_Host *shost = vport_to_shost(vport);
-+      struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
-+      struct fc_internal *i = to_fc_internal(shost->transportt);
-+      struct device *dev = &vport->dev;
-+      unsigned long flags;
-+      int stat;
++datain_jump:
++    JUMP 0
 +
-+      spin_lock_irqsave(shost->host_lock, flags);
-+      if (vport->flags & FC_VPORT_CREATING) {
-+              spin_unlock_irqrestore(shost->host_lock, flags);
-+              return -EBUSY;
-+      }
-+      if (vport->flags & (FC_VPORT_DEL)) {
-+              spin_unlock_irqrestore(shost->host_lock, flags);
-+              return -EALREADY;
-+      }
-+      vport->flags |= FC_VPORT_DELETING;
-+      spin_unlock_irqrestore(shost->host_lock, flags);
++at 0x000000d3 : */    0x80080000,0x00000000,
++/*
 +
-+      if (i->f->vport_delete)
-+              stat = i->f->vport_delete(vport);
-+      else
-+              stat = -ENOENT;
 +
-+      spin_lock_irqsave(shost->host_lock, flags);
-+      vport->flags &= ~FC_VPORT_DELETING;
-+      if (!stat) {
-+              vport->flags |= FC_VPORT_DELETED;
-+              list_del(&vport->peers);
-+              fc_host->npiv_vports_inuse--;
-+              put_device(&shost->shost_gendev);  /* for fc_host->vport list */
-+      }
-+      spin_unlock_irqrestore(shost->host_lock, flags);
 +
-+      if (stat)
-+              return stat;
++; Note that other_out and other_in loop until a non-data phase
++; is discovered, so we only execute return statements when we
++; can go on to the next data phase block move statement.
 +
-+      if (dev->parent != &shost->shost_gendev)
-+              sysfs_remove_link(&shost->shost_gendev.kobj, dev->bus_id);
-+      transport_remove_device(dev);
-+      device_del(dev);
-+      transport_destroy_device(dev);
++ENTRY other_out
++other_out:
 +
-+      /*
-+       * Removing our self-reference should mean our
-+       * release function gets called, which will drop the remaining
-+       * parent reference and free the data structure.
-+       */
-+      put_device(dev);                        /* for self-reference */
 +
-+      return 0; /* SUCCESS */
-+}
-+EXPORT_SYMBOL(fc_vport_terminate);
 +
-+/**
-+ * fc_vport_sched_delete - workq-based delete request for a vport
-+ *
-+ * @work:     vport to be deleted.
-+ **/
-+static void
-+fc_vport_sched_delete(struct work_struct *work)
-+{
-+      struct fc_vport *vport =
-+              container_of(work, struct fc_vport, vport_delete_work);
-+      int stat;
++    INT int_err_unexpected_phase, WHEN CMD
 +
-+      stat = fc_vport_terminate(vport);
-+      if (stat)
-+              dev_printk(KERN_ERR, vport->dev.parent,
-+                      "%s: %s could not be deleted created via "
-+                      "shost%d channel %d - error %d\n", __FUNCTION__,
-+                      vport->dev.bus_id, vport->shost->host_no,
-+                      vport->channel, stat);
-+}
++at 0x000000d5 : */    0x9a0b0000,0x00000000,
++/*
++    JUMP msg_in_restart, WHEN MSG_IN 
 +
++at 0x000000d7 : */    0x870b0000,0x000003fc,
++/*
++    INT int_err_unexpected_phase, WHEN MSG_OUT
 +
-+/* Original Author:  Martin Hicks */
-+MODULE_AUTHOR("James Smart");
- MODULE_DESCRIPTION("FC Transport Attributes");
- MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/drivers/scsi/scsi_transport_iscsi.c linux-2.6.22-590/drivers/scsi/scsi_transport_iscsi.c
---- linux-2.6.22-570/drivers/scsi/scsi_transport_iscsi.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/scsi_transport_iscsi.c       2008-01-02 13:56:37.000000000 -0500
-@@ -30,9 +30,9 @@
- #include <scsi/scsi_transport_iscsi.h>
- #include <scsi/iscsi_if.h>
--#define ISCSI_SESSION_ATTRS 11
-+#define ISCSI_SESSION_ATTRS 15
- #define ISCSI_CONN_ATTRS 11
--#define ISCSI_HOST_ATTRS 0
-+#define ISCSI_HOST_ATTRS 4
- #define ISCSI_TRANSPORT_VERSION "2.0-724"
- struct iscsi_internal {
-@@ -609,12 +609,10 @@
-       int t = done ? NLMSG_DONE : type;
-       skb = alloc_skb(len, GFP_ATOMIC);
--      /*
--       * FIXME:
--       * user is supposed to react on iferror == -ENOMEM;
--       * see iscsi_if_rx().
--       */
--      BUG_ON(!skb);
-+      if (!skb) {
-+              printk(KERN_ERR "Could not allocate skb to send reply.\n");
-+              return -ENOMEM;
-+      }
-       nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
-       nlh->nlmsg_flags = flags;
-@@ -816,6 +814,8 @@
-       uint32_t hostno;
-       session = transport->create_session(transport, &priv->t,
-+                                          ev->u.c_session.cmds_max,
-+                                          ev->u.c_session.queue_depth,
-                                           ev->u.c_session.initial_cmdsn,
-                                           &hostno);
-       if (!session)
-@@ -947,15 +947,50 @@
- iscsi_tgt_dscvr(struct iscsi_transport *transport,
-               struct iscsi_uevent *ev)
- {
-+      struct Scsi_Host *shost;
-       struct sockaddr *dst_addr;
-+      int err;
-       if (!transport->tgt_dscvr)
-               return -EINVAL;
-+      shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
-+      if (IS_ERR(shost)) {
-+              printk(KERN_ERR "target discovery could not find host no %u\n",
-+                     ev->u.tgt_dscvr.host_no);
-+              return -ENODEV;
-+      }
++at 0x000000d9 : */    0x9e0b0000,0x00000000,
++/*
++    INT int_err_unexpected_phase, WHEN DATA_IN
 +
++at 0x000000db : */    0x990b0000,0x00000000,
++/*
++    JUMP command_complete, WHEN STATUS
 +
-       dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
--      return transport->tgt_dscvr(ev->u.tgt_dscvr.type,
--                                  ev->u.tgt_dscvr.host_no,
-+      err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type,
-                                   ev->u.tgt_dscvr.enable, dst_addr);
-+      scsi_host_put(shost);
-+      return err;
-+}
++at 0x000000dd : */    0x830b0000,0x0000065c,
++/*
++    JUMP other_out, WHEN NOT DATA_OUT
 +
-+static int
-+iscsi_set_host_param(struct iscsi_transport *transport,
-+                   struct iscsi_uevent *ev)
-+{
-+      char *data = (char*)ev + sizeof(*ev);
-+      struct Scsi_Host *shost;
-+      int err;
++at 0x000000df : */    0x80030000,0x00000354,
++/*
 +
-+      if (!transport->set_host_param)
-+              return -ENOSYS;
++; TEMP should be OK, as we got here from a call in the user dataout code.
 +
-+      shost = scsi_host_lookup(ev->u.set_host_param.host_no);
-+      if (IS_ERR(shost)) {
-+              printk(KERN_ERR "set_host_param could not find host no %u\n",
-+                     ev->u.set_host_param.host_no);
-+              return -ENODEV;
-+      }
++    RETURN
 +
-+      err = transport->set_host_param(shost, ev->u.set_host_param.param,
-+                                      data, ev->u.set_host_param.len);
-+      scsi_host_put(shost);
-+      return err;
- }
- static int
-@@ -1049,8 +1084,11 @@
-       case ISCSI_UEVENT_TGT_DSCVR:
-               err = iscsi_tgt_dscvr(transport, ev);
-               break;
-+      case ISCSI_UEVENT_SET_HOST_PARAM:
-+              err = iscsi_set_host_param(transport, ev);
-+              break;
-       default:
--              err = -EINVAL;
-+              err = -ENOSYS;
-               break;
-       }
-@@ -1160,30 +1198,37 @@
- /*
-  * iSCSI session attrs
-  */
--#define iscsi_session_attr_show(param)                                        \
-+#define iscsi_session_attr_show(param, perm)                          \
- static ssize_t                                                                \
- show_session_param_##param(struct class_device *cdev, char *buf)      \
- {                                                                     \
-       struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
-       struct iscsi_transport *t = session->transport;                 \
-+                                                                      \
-+      if (perm && !capable(CAP_SYS_ADMIN))                            \
-+              return -EACCES;                                         \
-       return t->get_session_param(session, param, buf);               \
- }
--#define iscsi_session_attr(field, param)                              \
--      iscsi_session_attr_show(param)                                  \
-+#define iscsi_session_attr(field, param, perm)                                \
-+      iscsi_session_attr_show(param, perm)                            \
- static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
-                       NULL);
--iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME);
--iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN);
--iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T);
--iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN);
--iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST);
--iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST);
--iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN);
--iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN);
--iscsi_session_attr(erl, ISCSI_PARAM_ERL);
--iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT);
-+iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
-+iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
-+iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
-+iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0);
-+iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0);
-+iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0);
-+iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0);
-+iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0);
-+iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0);
-+iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0);
-+iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
-+iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
-+iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
-+iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
- #define iscsi_priv_session_attr_show(field, format)                   \
- static ssize_t                                                                \
-@@ -1199,6 +1244,28 @@
-                       NULL)
- iscsi_priv_session_attr(recovery_tmo, "%d");
++at 0x000000e1 : */    0x90080000,0x00000000,
 +/*
-+ * iSCSI host attrs
-+ */
-+#define iscsi_host_attr_show(param)                                   \
-+static ssize_t                                                                \
-+show_host_param_##param(struct class_device *cdev, char *buf)         \
-+{                                                                     \
-+      struct Scsi_Host *shost = transport_class_to_shost(cdev);       \
-+      struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
-+      return priv->iscsi_transport->get_host_param(shost, param, buf); \
-+}
 +
-+#define iscsi_host_attr(field, param)                                 \
-+      iscsi_host_attr_show(param)                                     \
-+static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param,        \
-+                      NULL);
++ENTRY other_in
++other_in:
 +
-+iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
-+iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
-+iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
-+iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
 +
- #define SETUP_PRIV_SESSION_RD_ATTR(field)                             \
- do {                                                                  \
-       priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
-@@ -1222,6 +1289,14 @@
-       }                                                               \
- } while (0)
-+#define SETUP_HOST_RD_ATTR(field, param_flag)                         \
-+do {                                                                  \
-+      if (tt->host_param_mask & param_flag) {                         \
-+              priv->host_attrs[count] = &class_device_attr_host_##field; \
-+              count++;                                                \
-+      }                                                               \
-+} while (0)
 +
- static int iscsi_session_match(struct attribute_container *cont,
-                          struct device *dev)
- {
-@@ -1323,9 +1398,16 @@
-       priv->t.host_attrs.ac.class = &iscsi_host_class.class;
-       priv->t.host_attrs.ac.match = iscsi_host_match;
-       priv->t.host_size = sizeof(struct iscsi_host);
--      priv->host_attrs[0] = NULL;
-       transport_container_register(&priv->t.host_attrs);
-+      SETUP_HOST_RD_ATTR(netdev, ISCSI_HOST_NETDEV_NAME);
-+      SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS);
-+      SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
-+      SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME);
-+      BUG_ON(count > ISCSI_HOST_ATTRS);
-+      priv->host_attrs[count] = NULL;
-+      count = 0;
++    INT int_err_unexpected_phase, WHEN CMD
 +
-       /* connection parameters */
-       priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
-       priv->conn_cont.ac.class = &iscsi_connection_class.class;
-@@ -1364,6 +1446,10 @@
-       SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
-       SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
-       SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
-+      SETUP_SESSION_RD_ATTR(password, ISCSI_USERNAME);
-+      SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN);
-+      SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
-+      SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
-       SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
-       BUG_ON(count > ISCSI_SESSION_ATTRS);
-@@ -1437,7 +1523,7 @@
-       if (err)
-               goto unregister_conn_class;
--      nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, NULL,
-+      nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx, NULL,
-                       THIS_MODULE);
-       if (!nls) {
-               err = -ENOBUFS;
-diff -Nurb linux-2.6.22-570/drivers/scsi/sd.c linux-2.6.22-590/drivers/scsi/sd.c
---- linux-2.6.22-570/drivers/scsi/sd.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/sd.c 2008-01-02 13:56:37.000000000 -0500
-@@ -1515,7 +1515,7 @@
-       if (!scsi_device_online(sdp))
-               goto out;
--      buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL | __GFP_DMA);
-+      buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL);
-       if (!buffer) {
-               sd_printk(KERN_WARNING, sdkp, "sd_revalidate_disk: Memory "
-                         "allocation failure.\n");
-diff -Nurb linux-2.6.22-570/drivers/scsi/sg.c linux-2.6.22-590/drivers/scsi/sg.c
---- linux-2.6.22-570/drivers/scsi/sg.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/sg.c 2008-01-02 13:56:37.000000000 -0500
-@@ -1842,7 +1842,7 @@
-       int blk_size = buff_size;
-       struct page *p = NULL;
--      if ((blk_size < 0) || (!sfp))
-+      if (blk_size < 0)
-               return -EFAULT;
-       if (0 == blk_size)
-               ++blk_size;     /* don't know why */
-diff -Nurb linux-2.6.22-570/drivers/scsi/stex.c linux-2.6.22-590/drivers/scsi/stex.c
---- linux-2.6.22-570/drivers/scsi/stex.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/stex.c       2008-01-02 13:56:37.000000000 -0500
-@@ -395,53 +395,34 @@
- static int stex_map_sg(struct st_hba *hba,
-       struct req_msg *req, struct st_ccb *ccb)
- {
--      struct pci_dev *pdev = hba->pdev;
-       struct scsi_cmnd *cmd;
--      dma_addr_t dma_handle;
--      struct scatterlist *src;
-+      struct scatterlist *sg;
-       struct st_sgtable *dst;
--      int i;
-+      int i, nseg;
-       cmd = ccb->cmd;
-       dst = (struct st_sgtable *)req->variable;
-       dst->max_sg_count = cpu_to_le16(ST_MAX_SG);
--      dst->sz_in_byte = cpu_to_le32(cmd->request_bufflen);
--
--      if (cmd->use_sg) {
--              int n_elem;
-+      dst->sz_in_byte = cpu_to_le32(scsi_bufflen(cmd));
--              src = (struct scatterlist *) cmd->request_buffer;
--              n_elem = pci_map_sg(pdev, src,
--                      cmd->use_sg, cmd->sc_data_direction);
--              if (n_elem <= 0)
-+      nseg = scsi_dma_map(cmd);
-+      if (nseg < 0)
-                       return -EIO;
-+      if (nseg) {
-+              ccb->sg_count = nseg;
-+              dst->sg_count = cpu_to_le16((u16)nseg);
--              ccb->sg_count = n_elem;
--              dst->sg_count = cpu_to_le16((u16)n_elem);
--
--              for (i = 0; i < n_elem; i++, src++) {
--                      dst->table[i].count = cpu_to_le32((u32)sg_dma_len(src));
-+              scsi_for_each_sg(cmd, sg, nseg, i) {
-+                      dst->table[i].count = cpu_to_le32((u32)sg_dma_len(sg));
-                       dst->table[i].addr =
--                              cpu_to_le32(sg_dma_address(src) & 0xffffffff);
-+                              cpu_to_le32(sg_dma_address(sg) & 0xffffffff);
-                       dst->table[i].addr_hi =
--                              cpu_to_le32((sg_dma_address(src) >> 16) >> 16);
-+                              cpu_to_le32((sg_dma_address(sg) >> 16) >> 16);
-                       dst->table[i].ctrl = SG_CF_64B | SG_CF_HOST;
-               }
-               dst->table[--i].ctrl |= SG_CF_EOT;
--              return 0;
-       }
--      dma_handle = pci_map_single(pdev, cmd->request_buffer,
--              cmd->request_bufflen, cmd->sc_data_direction);
--      cmd->SCp.dma_handle = dma_handle;
--
--      ccb->sg_count = 1;
--      dst->sg_count = cpu_to_le16(1);
--      dst->table[0].addr = cpu_to_le32(dma_handle & 0xffffffff);
--      dst->table[0].addr_hi = cpu_to_le32((dma_handle >> 16) >> 16);
--      dst->table[0].count = cpu_to_le32((u32)cmd->request_bufflen);
--      dst->table[0].ctrl = SG_CF_EOT | SG_CF_64B | SG_CF_HOST;
--
-       return 0;
- }
-@@ -451,24 +432,24 @@
-       size_t lcount;
-       size_t len;
-       void *s, *d, *base = NULL;
--      if (*count > cmd->request_bufflen)
--              *count = cmd->request_bufflen;
-+      size_t offset;
++at 0x000000e3 : */    0x9a0b0000,0x00000000,
++/*
++    JUMP msg_in_restart, WHEN MSG_IN 
 +
-+      if (*count > scsi_bufflen(cmd))
-+              *count = scsi_bufflen(cmd);
-       lcount = *count;
-       while (lcount) {
-               len = lcount;
-               s = (void *)src;
--              if (cmd->use_sg) {
--                      size_t offset = *count - lcount;
++at 0x000000e5 : */    0x870b0000,0x000003fc,
++/*
++    INT int_err_unexpected_phase, WHEN MSG_OUT
 +
-+              offset = *count - lcount;
-                       s += offset;
--                      base = scsi_kmap_atomic_sg(cmd->request_buffer,
-+              base = scsi_kmap_atomic_sg(scsi_sglist(cmd),
-                               sg_count, &offset, &len);
--                      if (base == NULL) {
-+              if (!base) {
-                               *count -= lcount;
-                               return;
-                       }
-                       d = base + offset;
--              } else
--                      d = cmd->request_buffer;
-               if (direction == ST_TO_CMD)
-                       memcpy(d, s, len);
-@@ -476,7 +457,6 @@
-                       memcpy(s, d, len);
-               lcount -= len;
--              if (cmd->use_sg)
-                       scsi_kunmap_atomic_sg(base);
-       }
- }
-@@ -484,22 +464,17 @@
- static int stex_direct_copy(struct scsi_cmnd *cmd,
-       const void *src, size_t count)
- {
--      struct st_hba *hba = (struct st_hba *) &cmd->device->host->hostdata[0];
-       size_t cp_len = count;
-       int n_elem = 0;
--      if (cmd->use_sg) {
--              n_elem = pci_map_sg(hba->pdev, cmd->request_buffer,
--                      cmd->use_sg, cmd->sc_data_direction);
--              if (n_elem <= 0)
-+      n_elem = scsi_dma_map(cmd);
-+      if (n_elem < 0)
-                       return 0;
--      }
-       stex_internal_copy(cmd, src, &cp_len, n_elem, ST_TO_CMD);
--      if (cmd->use_sg)
--              pci_unmap_sg(hba->pdev, cmd->request_buffer,
--                      cmd->use_sg, cmd->sc_data_direction);
-+      scsi_dma_unmap(cmd);
++at 0x000000e7 : */    0x9e0b0000,0x00000000,
++/*
++    INT int_err_unexpected_phase, WHEN DATA_OUT
 +
-       return cp_len == count;
- }
-@@ -678,18 +653,6 @@
-       return 0;
- }
--static void stex_unmap_sg(struct st_hba *hba, struct scsi_cmnd *cmd)
--{
--      if (cmd->sc_data_direction != DMA_NONE) {
--              if (cmd->use_sg)
--                      pci_unmap_sg(hba->pdev, cmd->request_buffer,
--                              cmd->use_sg, cmd->sc_data_direction);
--              else
--                      pci_unmap_single(hba->pdev, cmd->SCp.dma_handle,
--                              cmd->request_bufflen, cmd->sc_data_direction);
--      }
--}
--
- static void stex_scsi_done(struct st_ccb *ccb)
- {
-       struct scsi_cmnd *cmd = ccb->cmd;
-@@ -756,7 +719,7 @@
-       if (ccb->cmd->cmnd[0] == MGT_CMD &&
-               resp->scsi_status != SAM_STAT_CHECK_CONDITION) {
--              ccb->cmd->request_bufflen =
-+              scsi_bufflen(ccb->cmd) =
-                       le32_to_cpu(*(__le32 *)&resp->variable[0]);
-               return;
-       }
-@@ -855,7 +818,7 @@
-                               ccb->cmd->cmnd[1] == PASSTHRU_GET_ADAPTER))
-                               stex_controller_info(hba, ccb);
--                      stex_unmap_sg(hba, ccb->cmd);
-+                      scsi_dma_unmap(ccb->cmd);
-                       stex_scsi_done(ccb);
-                       hba->out_req_cnt--;
-               } else if (ccb->req_type & PASSTHRU_REQ_TYPE) {
-@@ -1028,7 +991,7 @@
-       }
- fail_out:
--      stex_unmap_sg(hba, cmd);
-+      scsi_dma_unmap(cmd);
-       hba->wait_ccb->req = NULL; /* nullify the req's future return */
-       hba->wait_ccb = NULL;
-       result = FAILED;
-diff -Nurb linux-2.6.22-570/drivers/scsi/sun_esp.c linux-2.6.22-590/drivers/scsi/sun_esp.c
---- linux-2.6.22-570/drivers/scsi/sun_esp.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/sun_esp.c    2008-01-02 13:56:37.000000000 -0500
-@@ -493,7 +493,7 @@
-               goto fail;
-       host->max_id = (hme ? 16 : 8);
--      esp = host_to_esp(host);
-+      esp = shost_priv(host);
-       esp->host = host;
-       esp->dev = esp_dev;
-diff -Nurb linux-2.6.22-570/drivers/scsi/sym53c416.c linux-2.6.22-590/drivers/scsi/sym53c416.c
---- linux-2.6.22-570/drivers/scsi/sym53c416.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/sym53c416.c  2008-01-02 13:56:37.000000000 -0500
-@@ -332,8 +332,7 @@
-       int i;
-       unsigned long flags = 0;
-       unsigned char status_reg, pio_int_reg, int_reg;
--      struct scatterlist *sglist;
--      unsigned int sgcount;
-+      struct scatterlist *sg;
-       unsigned int tot_trans = 0;
-       /* We search the base address of the host adapter which caused the interrupt */
-@@ -429,19 +428,15 @@
-                       {
-                               current_command->SCp.phase = data_out;
-                               outb(FLUSH_FIFO, base + COMMAND_REG);
--                              sym53c416_set_transfer_counter(base, current_command->request_bufflen);
-+                              sym53c416_set_transfer_counter(base,
-+                                                             scsi_bufflen(current_command));
-                               outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
--                              if(!current_command->use_sg)
--                                      tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen);
--                              else
--                              {
--                                      sgcount = current_command->use_sg;
--                                      sglist = current_command->request_buffer;
--                                      while(sgcount--)
--                                      {
--                                              tot_trans += sym53c416_write(base, SG_ADDRESS(sglist), sglist->length);
--                                              sglist++;
--                                      }
++at 0x000000e9 : */    0x980b0000,0x00000000,
++/*
++    JUMP command_complete, WHEN STATUS
 +
-+                              scsi_for_each_sg(current_command,
-+                                               sg, scsi_sg_count(current_command), i) {
-+                                      tot_trans += sym53c416_write(base,
-+                                                                   SG_ADDRESS(sg),
-+                                                                   sg->length);
-                               }
-                               if(tot_trans < current_command->underflow)
-                                       printk(KERN_WARNING "sym53c416: Underflow, wrote %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow);
-@@ -455,19 +450,16 @@
-                       {
-                               current_command->SCp.phase = data_in;
-                               outb(FLUSH_FIFO, base + COMMAND_REG);
--                              sym53c416_set_transfer_counter(base, current_command->request_bufflen);
-+                              sym53c416_set_transfer_counter(base,
-+                                                             scsi_bufflen(current_command));
++at 0x000000eb : */    0x830b0000,0x0000065c,
++/*
++    JUMP other_in, WHEN NOT DATA_IN
 +
-                               outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
--                              if(!current_command->use_sg)
--                                      tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen);
--                              else
--                              {
--                                      sgcount = current_command->use_sg;
--                                      sglist = current_command->request_buffer;
--                                      while(sgcount--)
--                                      {
--                                              tot_trans += sym53c416_read(base, SG_ADDRESS(sglist), sglist->length);
--                                              sglist++;
--                                      }
++at 0x000000ed : */    0x81030000,0x0000038c,
++/*
 +
-+                              scsi_for_each_sg(current_command,
-+                                               sg, scsi_sg_count(current_command), i) {
-+                                      tot_trans += sym53c416_read(base,
-+                                                                  SG_ADDRESS(sg),
-+                                                                  sg->length);
-                               }
-                               if(tot_trans < current_command->underflow)
-                                       printk(KERN_WARNING "sym53c416: Underflow, read %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow);
-diff -Nurb linux-2.6.22-570/drivers/scsi/tmscsim.c linux-2.6.22-590/drivers/scsi/tmscsim.c
---- linux-2.6.22-570/drivers/scsi/tmscsim.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/tmscsim.c    2008-01-02 13:56:37.000000000 -0500
-@@ -457,27 +457,20 @@
-                       error = 1;
-               DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __FUNCTION__, pcmd->sense_buffer, cmdp->saved_dma_handle));
-       /* Map SG list */
--      } else if (pcmd->use_sg) {
--              pSRB->pSegmentList      = (struct scatterlist *) pcmd->request_buffer;
--              pSRB->SGcount           = pci_map_sg(pdev, pSRB->pSegmentList, pcmd->use_sg,
--                                                   pcmd->sc_data_direction);
-+      } else if (scsi_sg_count(pcmd)) {
-+              int nseg;
++; TEMP should be OK, as we got here from a call in the user datain code.
 +
-+              nseg = scsi_dma_map(pcmd);
++    RETURN
 +
-+              pSRB->pSegmentList      = scsi_sglist(pcmd);
-+              pSRB->SGcount           = nseg;
++at 0x000000ef : */    0x90080000,0x00000000,
++/*
 +
-               /* TODO: error handling */
--              if (!pSRB->SGcount)
-+              if (nseg < 0)
-                       error = 1;
-               DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
--                            __FUNCTION__, pcmd->request_buffer, pSRB->SGcount, pcmd->use_sg));
-+                            __FUNCTION__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd)));
-       /* Map single segment */
--      } else if (pcmd->request_buffer && pcmd->request_bufflen) {
--              pSRB->pSegmentList      = dc390_sg_build_single(&pSRB->Segmentx, pcmd->request_buffer, pcmd->request_bufflen);
--              pSRB->SGcount           = pci_map_sg(pdev, pSRB->pSegmentList, 1,
--                                                   pcmd->sc_data_direction);
--              cmdp->saved_dma_handle  = sg_dma_address(pSRB->pSegmentList);
--
--              /* TODO: error handling */
--              if (pSRB->SGcount != 1)
--                      error = 1;
--              DEBUG1(printk("%s(): Mapped request buffer %p at %x\n", __FUNCTION__, pcmd->request_buffer, cmdp->saved_dma_handle));
--      /* No mapping !? */     
-       } else
-               pSRB->SGcount = 0;
-@@ -494,12 +487,10 @@
-       if (pSRB->SRBFlag) {
-               pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE);
-               DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle));
--      } else if (pcmd->use_sg) {
--              pci_unmap_sg(pdev, pcmd->request_buffer, pcmd->use_sg, pcmd->sc_data_direction);
--              DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n", __FUNCTION__, pcmd->request_buffer, pcmd->use_sg));
--      } else if (pcmd->request_buffer && pcmd->request_bufflen) {
--              pci_unmap_sg(pdev, &pSRB->Segmentx, 1, pcmd->sc_data_direction);
--              DEBUG1(printk("%s(): Unmapped request buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle));
-+      } else {
-+              scsi_dma_unmap(pcmd);
-+              DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n",
-+                            __FUNCTION__, scsi_sglist(pcmd), scsi_sg_count(pcmd)));
-       }
- }
-@@ -1153,9 +1144,9 @@
-     struct scatterlist *psgl;
-     pSRB->TotalXferredLen = 0;
-     pSRB->SGIndex = 0;
--    if (pcmd->use_sg) {
-+    if (scsi_sg_count(pcmd)) {
-       size_t saved;
--      pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer;
-+      pSRB->pSegmentList = scsi_sglist(pcmd);
-       psgl = pSRB->pSegmentList;
-       //dc390_pci_sync(pSRB);
-@@ -1179,12 +1170,6 @@
-       printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
-               pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
--    } else if(pcmd->request_buffer) {
--      //dc390_pci_sync(pSRB);
--
--      sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen - pSRB->Saved_Ptr;
--      pSRB->SGcount = 1;
--      pSRB->pSegmentList = (struct scatterlist *) &pSRB->Segmentx;
-     } else {
-        pSRB->SGcount = 0;
-        printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n");
-@@ -1579,7 +1564,8 @@
-       if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
-          !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
-       {       /* Selection time out */
--              pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT;
-+              pSRB->AdaptStatus = H_SEL_TIMEOUT;
-+              pSRB->TargetStatus = 0;
-               goto  disc1;
-       }
-       else if (!(pSRB->SRBState & SRB_DISCONNECT) && (pSRB->SRBState & SRB_COMPLETED))
-@@ -1612,7 +1598,7 @@
-       if( !( pACB->scan_devices ) )
-       {
-           struct scsi_cmnd *pcmd = pSRB->pcmd;
--          pcmd->resid = pcmd->request_bufflen;
-+          scsi_set_resid(pcmd, scsi_bufflen(pcmd));
-           SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
-           dc390_Going_remove(pDCB, pSRB);
-           dc390_Free_insert(pACB, pSRB);
-@@ -1695,7 +1681,7 @@
-                             pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
-       pSRB->SRBFlag |= AUTO_REQSENSE;
--      pSRB->SavedSGCount = pcmd->use_sg;
-+      pSRB->SavedSGCount = scsi_sg_count(pcmd);
-       pSRB->SavedTotXLen = pSRB->TotalXferredLen;
-       pSRB->AdaptStatus = 0;
-       pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
-@@ -1728,22 +1714,22 @@
-     { /* Last command was a Request Sense */
-       pSRB->SRBFlag &= ~AUTO_REQSENSE;
-       pSRB->AdaptStatus = 0;
--      pSRB->TargetStatus = CHECK_CONDITION << 1;
-+      pSRB->TargetStatus = SAM_STAT_CHECK_CONDITION;
-       //pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
--      if (status == (CHECK_CONDITION << 1))
-+      if (status == SAM_STAT_CHECK_CONDITION)
-           pcmd->result = MK_RES_LNX(0, DID_BAD_TARGET, 0, /*CHECK_CONDITION*/0);
-       else /* Retry */
-       {
-           if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */)
-           {
-               /* Don't retry on TEST_UNIT_READY */
--              pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION);
-+              pcmd->result = MK_RES_LNX(DRIVER_SENSE, DID_OK, 0, SAM_STAT_CHECK_CONDITION);
-               REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\
-                      (u32) pcmd->result, (u32) pSRB->TotalXferredLen));
-           } else {
-               SET_RES_DRV(pcmd->result, DRIVER_SENSE);
--              pcmd->use_sg = pSRB->SavedSGCount;
-+              scsi_sg_count(pcmd) = pSRB->SavedSGCount;
-               //pSRB->ScsiCmdLen       = (u8) (pSRB->Segment1[0] >> 8);
-               DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
-               pSRB->TotalXferredLen = 0;
-@@ -1754,7 +1740,7 @@
-     }
-     if( status )
-     {
--      if( status_byte(status) == CHECK_CONDITION )
-+      if (status == SAM_STAT_CHECK_CONDITION)
-       {
-           if (dc390_RequestSense(pACB, pDCB, pSRB)) {
-               SET_RES_DID(pcmd->result, DID_ERROR);
-@@ -1762,22 +1748,15 @@
-           }
-           return;
-       }
--      else if( status_byte(status) == QUEUE_FULL )
-+      else if (status == SAM_STAT_TASK_SET_FULL)
-       {
-           scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1);
--          pcmd->use_sg = pSRB->SavedSGCount;
-+          scsi_sg_count(pcmd) = pSRB->SavedSGCount;
-           DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
-           pSRB->TotalXferredLen = 0;
-           SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
-       }
--      else if(status == SCSI_STAT_SEL_TIMEOUT)
--      {
--          pSRB->AdaptStatus = H_SEL_TIMEOUT;
--          pSRB->TargetStatus = 0;
--          pcmd->result = MK_RES(0,DID_NO_CONNECT,0,0);
--          /* Devices are removed below ... */
--      }
--      else if (status_byte(status) == BUSY && 
-+      else if (status == SAM_STAT_BUSY &&
-                (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) &&
-                pACB->scan_devices)
-       {
-@@ -1795,12 +1774,17 @@
-     else
-     { /*  Target status == 0 */
-       status = pSRB->AdaptStatus;
--      if(status & H_OVER_UNDER_RUN)
-+      if (status == H_OVER_UNDER_RUN)
-       {
-           pSRB->TargetStatus = 0;
-           SET_RES_DID(pcmd->result,DID_OK);
-           SET_RES_MSG(pcmd->result,pSRB->EndMessage);
-       }
-+      else if (status == H_SEL_TIMEOUT)
-+      {
-+          pcmd->result = MK_RES(0, DID_NO_CONNECT, 0, 0);
-+          /* Devices are removed below ... */
-+      }
-       else if( pSRB->SRBStatus & PARITY_ERROR)
-       {
-           //pcmd->result = MK_RES(0,DID_PARITY,pSRB->EndMessage,0);
-@@ -1816,7 +1800,7 @@
-     }
- cmd_done:
--    pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen;
-+    scsi_set_resid(pcmd, scsi_bufflen(pcmd) - pSRB->TotalXferredLen);
-     dc390_Going_remove (pDCB, pSRB);
-     /* Add to free list */
-diff -Nurb linux-2.6.22-570/drivers/scsi/tmscsim.h linux-2.6.22-590/drivers/scsi/tmscsim.h
---- linux-2.6.22-570/drivers/scsi/tmscsim.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/tmscsim.h    2008-01-02 13:56:37.000000000 -0500
-@@ -258,13 +258,6 @@
- #define H_BAD_CCB_OR_SG  0x1A
- #define H_ABORT        0x0FF
--/*; SCSI Status byte codes*/ 
--/* The values defined in include/scsi/scsi.h, to be shifted << 1 */
--
--#define SCSI_STAT_UNEXP_BUS_F 0xFD    /*;  Unexpect Bus Free */
--#define SCSI_STAT_BUS_RST_DETECT 0xFE /*;  Scsi Bus Reset detected */
--#define SCSI_STAT_SEL_TIMEOUT 0xFF    /*;  Selection Time out */
--
- /* cmd->result */
- #define RES_TARGET            0x000000FF      /* Target State */
- #define RES_TARGET_LNX                STATUS_MASK     /* Only official ... */
-@@ -273,7 +266,7 @@
- #define RES_DRV                       0xFF000000      /* DRIVER_ codes */
- #define MK_RES(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))
--#define MK_RES_LNX(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt)<<1)
-+#define MK_RES_LNX(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))
- #define SET_RES_TARGET(who, tgt) do { who &= ~RES_TARGET; who |= (int)(tgt); } while (0)
- #define SET_RES_TARGET_LNX(who, tgt) do { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; } while (0)
-diff -Nurb linux-2.6.22-570/drivers/scsi/u14-34f.c linux-2.6.22-590/drivers/scsi/u14-34f.c
---- linux-2.6.22-570/drivers/scsi/u14-34f.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/u14-34f.c    2008-01-02 13:56:37.000000000 -0500
-@@ -1111,7 +1111,7 @@
- static void map_dma(unsigned int i, unsigned int j) {
-    unsigned int data_len = 0;
-    unsigned int k, count, pci_dir;
--   struct scatterlist *sgpnt;
-+   struct scatterlist *sg;
-    struct mscp *cpp;
-    struct scsi_cmnd *SCpnt;
-@@ -1124,33 +1124,28 @@
-    cpp->sense_len = sizeof SCpnt->sense_buffer;
--   if (!SCpnt->use_sg) {
--
--      /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */
--      if (!SCpnt->request_bufflen) pci_dir = PCI_DMA_BIDIRECTIONAL;
--
--      if (SCpnt->request_buffer)
--         cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,
--                  SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));
--
--      cpp->data_len = H2DEV(SCpnt->request_bufflen);
--      return;
--      }
--
--   sgpnt = (struct scatterlist *) SCpnt->request_buffer;
--   count = pci_map_sg(HD(j)->pdev, sgpnt, SCpnt->use_sg, pci_dir);
--
--   for (k = 0; k < count; k++) {
--      cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
--      cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
--      data_len += sgpnt[k].length;
-+   if (scsi_bufflen(SCpnt)) {
-+         count = scsi_dma_map(SCpnt);
-+         BUG_ON(count < 0);
 +
-+         scsi_for_each_sg(SCpnt, sg, count, k) {
-+                 cpp->sglist[k].address = H2DEV(sg_dma_address(sg));
-+                 cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(sg));
-+                 data_len += sg->length;
-       }
-    cpp->sg = TRUE;
--   cpp->use_sg = SCpnt->use_sg;
--   cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist,
--                             SCpnt->use_sg * sizeof(struct sg_list), pci_dir));
-+         cpp->use_sg = scsi_sg_count(SCpnt);
-+         cpp->data_address =
-+                 H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist,
-+                                      cpp->use_sg * sizeof(struct sg_list),
-+                                      pci_dir));
-    cpp->data_len = H2DEV(data_len);
++ENTRY other_transfer
++other_transfer:
++    INT int_err_unexpected_phase, WHEN CMD
++
++at 0x000000f1 : */    0x9a0b0000,0x00000000,
++/*
++    CALL msg_in, WHEN MSG_IN
++
++at 0x000000f3 : */    0x8f0b0000,0x0000041c,
++/*
++    INT int_err_unexpected_phase, WHEN MSG_OUT
++
++at 0x000000f5 : */    0x9e0b0000,0x00000000,
++/*
++    INT int_err_unexpected_phase, WHEN DATA_OUT
++
++at 0x000000f7 : */    0x980b0000,0x00000000,
++/*
++    INT int_err_unexpected_phase, WHEN DATA_IN
++
++at 0x000000f9 : */    0x990b0000,0x00000000,
++/*
++    JUMP command_complete, WHEN STATUS
++
++at 0x000000fb : */    0x830b0000,0x0000065c,
++/*
++    JUMP other_transfer
++
++at 0x000000fd : */    0x80080000,0x000003c4,
++/*
++
++;
++; msg_in_restart
++; msg_in
++; munge_msg
++;
++; PURPOSE : process messages from a target.  msg_in is called when the 
++;     caller hasn't read the first byte of the message.  munge_message
++;     is called when the caller has read the first byte of the message,
++;     and left it in SFBR.  msg_in_restart is called when the caller 
++;     hasn't read the first byte of the message, and wishes RETURN
++;     to transfer control back to the address of the conditional
++;     CALL instruction rather than to the instruction after it.
++;
++;     Various int_* interrupts are generated when the host system
++;     needs to intervene, as is the case with SDTR, WDTR, and
++;     INITIATE RECOVERY messages.
++;
++;     When the host system handles one of these interrupts,
++;     it can respond by reentering at reject_message, 
++;     which rejects the message and returns control to
++;     the caller of msg_in or munge_msg, accept_message
++;     which clears ACK and returns control, or reply_message
++;     which sends the message pointed to by the DSA 
++;     msgout_other table indirect field.
++;
++;     DISCONNECT messages are handled by moving the command
++;     to the reconnect_dsa_queue.
++
++; NOTE: DSA should be valid when we get here - we cannot save both it
++;     and TEMP in this routine.
++
++;
++; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg
++;     only)
++;
++; CALLS : NO.  The TEMP register isn't backed up to allow nested calls.
++;
++; MODIFIES : SCRATCH, DSA on DISCONNECT
++;
++; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS,
++;     and normal return from message handlers running under
++;     Linux, control is returned to the caller.  Receipt
++;     of DISCONNECT messages pass control to dsa_schedule.
++;
++ENTRY msg_in_restart
++msg_in_restart:
++; XXX - hackish
++;
++; Since it's easier to debug changes to the statically 
++; compiled code, rather than the dynamically generated 
++; stuff, such as
++;
++;     MOVE x, y, WHEN data_phase
++;     CALL other_z, WHEN NOT data_phase
++;     MOVE x, y, WHEN data_phase
++;
++; I'd like to have certain routines (notably the message handler)
++; restart on the conditional call rather than the next instruction.
++;
++; So, subtract 8 from the return address
++
++    MOVE TEMP0 + 0xf8 TO TEMP0
++
++at 0x000000ff : */    0x7e1cf800,0x00000000,
++/*
++    MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY
++
++at 0x00000101 : */    0x7f1dff00,0x00000000,
++/*
++    MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY
++
++at 0x00000103 : */    0x7f1eff00,0x00000000,
++/*
++    MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY
++
++at 0x00000105 : */    0x7f1fff00,0x00000000,
++/*
++
++ENTRY msg_in
++msg_in:
++    MOVE 1, msg_buf, WHEN MSG_IN
++
++at 0x00000107 : */    0x0f000001,0x00000000,
++/*
++
++munge_msg:
++    JUMP munge_extended, IF 0x01              ; EXTENDED MESSAGE
++
++at 0x00000109 : */    0x800c0001,0x00000574,
++/*
++    JUMP munge_2, IF 0x20, AND MASK 0xdf      ; two byte message
++
++at 0x0000010b : */    0x800cdf20,0x00000464,
++/*
++;
++; XXX - I've seen a handful of broken SCSI devices which fail to issue
++;     a SAVE POINTERS message before disconnecting in the middle of 
++;     a transfer, assuming that the DATA POINTER will be implicitly 
++;     restored.  
++;
++; Historically, I've often done an implicit save when the DISCONNECT
++; message is processed.  We may want to consider having the option of 
++; doing that here. 
++;
++    JUMP munge_save_data_pointer, IF 0x02     ; SAVE DATA POINTER
++
++at 0x0000010d : */    0x800c0002,0x0000046c,
++/*
++    JUMP munge_restore_pointers, IF 0x03      ; RESTORE POINTERS 
++
++at 0x0000010f : */    0x800c0003,0x00000518,
++/*
++    JUMP munge_disconnect, IF 0x04            ; DISCONNECT
++
++at 0x00000111 : */    0x800c0004,0x0000056c,
++/*
++    INT int_msg_1, IF 0x07                    ; MESSAGE REJECT
++
++at 0x00000113 : */    0x980c0007,0x01020000,
++/*
++    INT int_msg_1, IF 0x0f                    ; INITIATE RECOVERY
++
++at 0x00000115 : */    0x980c000f,0x01020000,
++/*
++
++
++
++    JUMP reject_message
++
++at 0x00000117 : */    0x80080000,0x00000604,
++/*
++
++munge_2:
++    JUMP reject_message
++
++at 0x00000119 : */    0x80080000,0x00000604,
++/*
++;
++; The SCSI standard allows targets to recover from transient 
++; error conditions by backing up the data pointer with a 
++; RESTORE POINTERS message.  
++;     
++; So, we must save and restore the _residual_ code as well as 
++; the current instruction pointer.  Because of this messiness,
++; it is simpler to put dynamic code in the dsa for this and to
++; just do a simple jump down there. 
++;
++
++munge_save_data_pointer:
++
++    ; We have something in TEMP here, so first we must save that
++    MOVE TEMP0 TO SFBR
++
++at 0x0000011b : */    0x721c0000,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH0
++
++at 0x0000011d : */    0x6a340000,0x00000000,
++/*
++    MOVE TEMP1 TO SFBR
++
++at 0x0000011f : */    0x721d0000,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH1
 +
-+   } else {
-+         pci_dir = PCI_DMA_BIDIRECTIONAL;
-+         cpp->data_len = H2DEV(scsi_bufflen(SCpnt));
-+   }
- }
- static void unmap_dma(unsigned int i, unsigned int j) {
-@@ -1165,8 +1160,7 @@
-       pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
-                        DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
--   if (SCpnt->use_sg)
--      pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);
-+   scsi_dma_unmap(SCpnt);
-    if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
-@@ -1187,9 +1181,9 @@
-       pci_dma_sync_single_for_cpu(HD(j)->pdev, DEV2H(cpp->sense_addr),
-                           DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
--   if (SCpnt->use_sg)
--      pci_dma_sync_sg_for_cpu(HD(j)->pdev, SCpnt->request_buffer,
--                         SCpnt->use_sg, pci_dir);
-+   if (scsi_sg_count(SCpnt))
-+         pci_dma_sync_sg_for_cpu(HD(j)->pdev, scsi_sglist(SCpnt),
-+                                 scsi_sg_count(SCpnt), pci_dir);
-    if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
-diff -Nurb linux-2.6.22-570/drivers/scsi/ultrastor.c linux-2.6.22-590/drivers/scsi/ultrastor.c
---- linux-2.6.22-570/drivers/scsi/ultrastor.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/ultrastor.c  2008-01-02 13:56:37.000000000 -0500
-@@ -675,16 +675,15 @@
- static inline void build_sg_list(struct mscp *mscp, struct scsi_cmnd *SCpnt)
- {
--      struct scatterlist *sl;
-+      struct scatterlist *sg;
-       long transfer_length = 0;
-       int i, max;
--      sl = (struct scatterlist *) SCpnt->request_buffer;
--      max = SCpnt->use_sg;
--      for (i = 0; i < max; i++) {
--              mscp->sglist[i].address = isa_page_to_bus(sl[i].page) + sl[i].offset;
--              mscp->sglist[i].num_bytes = sl[i].length;
--              transfer_length += sl[i].length;
-+      max = scsi_sg_count(SCpnt);
-+      scsi_for_each_sg(SCpnt, sg, max, i) {
-+              mscp->sglist[i].address = isa_page_to_bus(sg->page) + sg->offset;
-+              mscp->sglist[i].num_bytes = sg->length;
-+              transfer_length += sg->length;
-       }
-       mscp->number_of_sg_list = max;
-       mscp->transfer_data = isa_virt_to_bus(mscp->sglist);
-@@ -730,15 +729,15 @@
-     my_mscp->target_id = SCpnt->device->id;
-     my_mscp->ch_no = 0;
-     my_mscp->lun = SCpnt->device->lun;
--    if (SCpnt->use_sg) {
-+    if (scsi_sg_count(SCpnt)) {
-       /* Set scatter/gather flag in SCSI command packet */
-       my_mscp->sg = TRUE;
-       build_sg_list(my_mscp, SCpnt);
-     } else {
-       /* Unset scatter/gather flag in SCSI command packet */
-       my_mscp->sg = FALSE;
--      my_mscp->transfer_data = isa_virt_to_bus(SCpnt->request_buffer);
--      my_mscp->transfer_data_length = SCpnt->request_bufflen;
-+      my_mscp->transfer_data = isa_virt_to_bus(scsi_sglist(SCpnt));
-+      my_mscp->transfer_data_length = scsi_bufflen(SCpnt);
-     }
-     my_mscp->command_link = 0;                /*???*/
-     my_mscp->scsi_command_link_id = 0;        /*???*/
-diff -Nurb linux-2.6.22-570/drivers/scsi/wd7000.c linux-2.6.22-590/drivers/scsi/wd7000.c
---- linux-2.6.22-570/drivers/scsi/wd7000.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/scsi/wd7000.c     2008-01-02 13:56:37.000000000 -0500
-@@ -1091,6 +1091,7 @@
-       unchar *cdb = (unchar *) SCpnt->cmnd;
-       unchar idlun;
-       short cdblen;
-+      int nseg;
-       Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
-       cdblen = SCpnt->cmd_len;
-@@ -1106,28 +1107,29 @@
-       SCpnt->host_scribble = (unchar *) scb;
-       scb->host = host;
--      if (SCpnt->use_sg) {
--              struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
-+      nseg = scsi_sg_count(SCpnt);
-+      if (nseg) {
-+              struct scatterlist *sg;
-               unsigned i;
-               if (SCpnt->device->host->sg_tablesize == SG_NONE) {
-                       panic("wd7000_queuecommand: scatter/gather not supported.\n");
-               }
--              dprintk("Using scatter/gather with %d elements.\n", SCpnt->use_sg);
-+              dprintk("Using scatter/gather with %d elements.\n", nseg);
-               sgb = scb->sgb;
-               scb->op = 1;
-               any2scsi(scb->dataptr, (int) sgb);
--              any2scsi(scb->maxlen, SCpnt->use_sg * sizeof(Sgb));
-+              any2scsi(scb->maxlen, nseg * sizeof(Sgb));
--              for (i = 0; i < SCpnt->use_sg; i++) {
--                      any2scsi(sgb[i].ptr, isa_page_to_bus(sg[i].page) + sg[i].offset);
--                      any2scsi(sgb[i].len, sg[i].length);
-+              scsi_for_each_sg(SCpnt, sg, nseg, i) {
-+                      any2scsi(sgb[i].ptr, isa_page_to_bus(sg->page) + sg->offset);
-+                      any2scsi(sgb[i].len, sg->length);
-               }
-       } else {
-               scb->op = 0;
--              any2scsi(scb->dataptr, isa_virt_to_bus(SCpnt->request_buffer));
--              any2scsi(scb->maxlen, SCpnt->request_bufflen);
-+              any2scsi(scb->dataptr, isa_virt_to_bus(scsi_sglist(SCpnt)));
-+              any2scsi(scb->maxlen, scsi_bufflen(SCpnt));
-       }
-       /* FIXME: drop lock and yield here ? */
-diff -Nurb linux-2.6.22-570/drivers/scsi/zorro7xx.c linux-2.6.22-590/drivers/scsi/zorro7xx.c
---- linux-2.6.22-570/drivers/scsi/zorro7xx.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/scsi/zorro7xx.c   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,180 @@
++at 0x00000121 : */    0x6a350000,0x00000000,
 +/*
-+ * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
-+ *            Amiga MacroSystemUS WarpEngine SCSI controller.
-+ *            Amiga Technologies/DKB A4091 SCSI controller.
-+ *
-+ * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
-+ * plus modifications of the 53c7xx.c driver to support the Amiga.
-+ *
-+ * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
-+ */
++    MOVE TEMP2 TO SFBR
 +
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/zorro.h>
-+#include <asm/amigaints.h>
-+#include <scsi/scsi_host.h>
-+#include <scsi/scsi_transport_spi.h>
++at 0x00000123 : */    0x721e0000,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH2
 +
-+#include "53c700.h"
++at 0x00000125 : */    0x6a360000,0x00000000,
++/*
++    MOVE TEMP3 TO SFBR
 +
-+MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>");
-+MODULE_DESCRIPTION("Amiga Zorro NCR53C710 driver");
-+MODULE_LICENSE("GPL");
++at 0x00000127 : */    0x721f0000,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH3
 +
++at 0x00000129 : */    0x6a370000,0x00000000,
++/*
++    MOVE MEMORY 4, addr_scratch, jump_temp + 4
 +
-+static struct scsi_host_template zorro7xx_scsi_driver_template = {
-+      .proc_name      = "zorro7xx",
-+      .this_id        = 7,
-+      .module         = THIS_MODULE,
-+};
++at 0x0000012b : */    0xc0000004,0x00000000,0x000009c8,
++/*
++    ; Now restore DSA
++    MOVE MEMORY 4, saved_dsa, addr_dsa
 +
-+static struct zorro_driver_data {
-+      const char *name;
-+      unsigned long offset;
-+      int absolute;   /* offset is absolute address */
-+} zorro7xx_driver_data[] __devinitdata = {
-+      { .name = "PowerUP 603e+", .offset = 0xf40000, .absolute = 1 },
-+      { .name = "WarpEngine 40xx", .offset = 0x40000 },
-+      { .name = "A4091", .offset = 0x800000 },
-+      { .name = "GForce 040/060", .offset = 0x40000 },
-+      { 0 }
-+};
++at 0x0000012e : */    0xc0000004,0x00000000,0x00000000,
++/*
 +
-+static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = {
-+      {
-+              .id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS,
-+              .driver_data = (unsigned long)&zorro7xx_driver_data[0],
-+      },
-+      {
-+              .id = ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx,
-+              .driver_data = (unsigned long)&zorro7xx_driver_data[1],
-+      },
-+      {
-+              .id = ZORRO_PROD_CBM_A4091_1,
-+              .driver_data = (unsigned long)&zorro7xx_driver_data[2],
-+      },
-+      {
-+              .id = ZORRO_PROD_CBM_A4091_2,
-+              .driver_data = (unsigned long)&zorro7xx_driver_data[2],
-+      },
-+      {
-+              .id = ZORRO_PROD_GVP_GFORCE_040_060,
-+              .driver_data = (unsigned long)&zorro7xx_driver_data[3],
-+      },
-+      { 0 }
-+};
++    MOVE DSA0 + dsa_save_data_pointer TO SFBR
 +
-+static int __devinit zorro7xx_init_one(struct zorro_dev *z,
-+                                     const struct zorro_device_id *ent)
-+{
-+      struct Scsi_Host * host = NULL;
-+      struct NCR_700_Host_Parameters *hostdata;
-+      struct zorro_driver_data *zdd;
-+      unsigned long board, ioaddr;
++at 0x00000131 : */    0x76100000,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH0
 +
-+      board = zorro_resource_start(z);
-+      zdd = (struct zorro_driver_data *)ent->driver_data;
++at 0x00000133 : */    0x6a340000,0x00000000,
++/*
++    MOVE DSA1 + 0xff TO SFBR WITH CARRY
 +
-+      if (zdd->absolute) {
-+              ioaddr = zdd->offset;
-+      } else {
-+              ioaddr = board + zdd->offset;
-+      }
++at 0x00000135 : */    0x7711ff00,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH1
 +
-+      if (!zorro_request_device(z, zdd->name)) {
-+              printk(KERN_ERR "zorro7xx: cannot reserve region 0x%lx, abort\n",
-+                     board);
-+              return -EBUSY;
-+      }
++at 0x00000137 : */    0x6a350000,0x00000000,
++/*
++    MOVE DSA2 + 0xff TO SFBR WITH CARRY 
 +
-+      hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
-+      if (hostdata == NULL) {
-+              printk(KERN_ERR "zorro7xx: Failed to allocate host data\n");
-+              goto out_release;
-+      }
++at 0x00000139 : */    0x7712ff00,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH2
 +
-+      memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
++at 0x0000013b : */    0x6a360000,0x00000000,
++/*
++    MOVE DSA3 + 0xff TO SFBR WITH CARRY
 +
-+      /* Fill in the required pieces of hostdata */
-+      if (ioaddr > 0x01000000)
-+              hostdata->base = ioremap(ioaddr, zorro_resource_len(z));
-+      else
-+              hostdata->base = (void __iomem *)ZTWO_VADDR(ioaddr);
++at 0x0000013d : */    0x7713ff00,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH3
 +
-+      hostdata->clock = 50;
-+      hostdata->chip710 = 1;
++at 0x0000013f : */    0x6a370000,0x00000000,
++/*
 +
-+      /* Settings for at least WarpEngine 40xx */
-+      hostdata->ctest7_extra = CTEST7_TT1;
++    
++    MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4
 +
-+      zorro7xx_scsi_driver_template.name = zdd->name;
++at 0x00000141 : */    0xc0000004,0x00000000,0x00000514,
++/*
++    
++jump_dsa_save:
++    JUMP 0
 +
-+      /* and register the chip */
-+      host = NCR_700_detect(&zorro7xx_scsi_driver_template, hostdata,
-+                            &z->dev);
-+      if (!host) {
-+              printk(KERN_ERR "zorro7xx: No host detected; "
-+                              "board configuration problem?\n");
-+              goto out_free;
-+      }
++at 0x00000144 : */    0x80080000,0x00000000,
++/*
 +
-+      host->this_id = 7;
-+      host->base = ioaddr;
-+      host->irq = IRQ_AMIGA_PORTS;
++munge_restore_pointers:
 +
-+      if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "zorro7xx-scsi",
-+                      host)) {
-+              printk(KERN_ERR "zorro7xx: request_irq failed\n");
-+              goto out_put_host;
-+      }
++    ; The code at dsa_restore_pointers will RETURN, but we don't care
++    ; about TEMP here, as it will overwrite it anyway.
 +
-+      scsi_scan_host(host);
++    MOVE DSA0 + dsa_restore_pointers TO SFBR
 +
-+      return 0;
++at 0x00000146 : */    0x76100000,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH0
 +
-+ out_put_host:
-+      scsi_host_put(host);
-+ out_free:
-+      if (ioaddr > 0x01000000)
-+              iounmap(hostdata->base);
-+      kfree(hostdata);
-+ out_release:
-+      zorro_release_device(z);
++at 0x00000148 : */    0x6a340000,0x00000000,
++/*
++    MOVE DSA1 + 0xff TO SFBR WITH CARRY
 +
-+      return -ENODEV;
-+}
++at 0x0000014a : */    0x7711ff00,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH1
 +
-+static __devexit void zorro7xx_remove_one(struct zorro_dev *z)
-+{
-+      struct Scsi_Host *host = dev_to_shost(&z->dev);
-+      struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
++at 0x0000014c : */    0x6a350000,0x00000000,
++/*
++    MOVE DSA2 + 0xff TO SFBR WITH CARRY
 +
-+      scsi_remove_host(host);
++at 0x0000014e : */    0x7712ff00,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH2
 +
-+      NCR_700_release(host);
-+      kfree(hostdata);
-+      free_irq(host->irq, host);
-+      zorro_release_device(z);
-+}
++at 0x00000150 : */    0x6a360000,0x00000000,
++/*
++    MOVE DSA3 + 0xff TO SFBR WITH CARRY
 +
-+static struct zorro_driver zorro7xx_driver = {
-+      .name     = "zorro7xx-scsi",
-+      .id_table = zorro7xx_zorro_tbl,
-+      .probe    = zorro7xx_init_one,
-+      .remove   = __devexit_p(zorro7xx_remove_one),
-+};
++at 0x00000152 : */    0x7713ff00,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH3
 +
-+static int __init zorro7xx_scsi_init(void)
-+{
-+      return zorro_register_driver(&zorro7xx_driver);
-+}
++at 0x00000154 : */    0x6a370000,0x00000000,
++/*
 +
-+static void __exit zorro7xx_scsi_exit(void)
-+{
-+      zorro_unregister_driver(&zorro7xx_driver);
-+}
++    
++    MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4
 +
-+module_init(zorro7xx_scsi_init);
-+module_exit(zorro7xx_scsi_exit);
-diff -Nurb linux-2.6.22-570/drivers/serial/8250.c linux-2.6.22-590/drivers/serial/8250.c
---- linux-2.6.22-570/drivers/serial/8250.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/serial/8250.c     2008-01-02 13:56:37.000000000 -0500
-@@ -2845,6 +2845,25 @@
- }
- EXPORT_SYMBOL(serial8250_unregister_port);
-+/**
-+ *    serial8250_unregister_by_port - remove a 16x50 serial port
-+ *    at runtime.
-+ *    @port: A &struct uart_port that describes the port to remove.
-+ *
-+ *    Remove one serial port.  This may not be called from interrupt
-+ *    context.  We hand the port back to the our control.
-+ */
-+void serial8250_unregister_by_port(struct uart_port *port)
-+{
-+      struct uart_8250_port *uart;
++at 0x00000156 : */    0xc0000004,0x00000000,0x00000568,
++/*
++    
++jump_dsa_restore:
++    JUMP 0
 +
-+      uart = serial8250_find_match_or_unused(port);
++at 0x00000159 : */    0x80080000,0x00000000,
++/*
 +
-+      if (uart)
-+              serial8250_unregister_port(uart->port.line);
-+}
-+EXPORT_SYMBOL(serial8250_unregister_by_port);
 +
- static int __init serial8250_init(void)
- {
-       int ret, i;
-diff -Nurb linux-2.6.22-570/drivers/serial/8250_kgdb.c linux-2.6.22-590/drivers/serial/8250_kgdb.c
---- linux-2.6.22-570/drivers/serial/8250_kgdb.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/serial/8250_kgdb.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,515 @@
++munge_disconnect:
++
++
++
++
++
++
++
++
++
++ 
++
++
++
++
++
++
++
++
++
++
++    JUMP dsa_schedule
++
++at 0x0000015b : */    0x80080000,0x00000178,
 +/*
-+ * 8250 interface for kgdb.
-+ *
-+ * This is a merging of many different drivers, and all of the people have
-+ * had an impact in some form or another:
-+ *
-+ * 2004-2005 (c) MontaVista Software, Inc.
-+ * 2005-2006 (c) Wind River Systems, Inc.
-+ *
-+ * Amit Kale <amitkale@emsyssoft.com>, David Grothe <dave@gcom.com>,
-+ * Scott Foehner <sfoehner@engr.sgi.com>, George Anzinger <george@mvista.com>,
-+ * Robert Walsh <rjwalsh@durables.org>, wangdi <wangdi@clusterfs.com>,
-+ * San Mehat, Tom Rini <trini@mvista.com>,
-+ * Jason Wessel <jason.wessel@windriver.com>
-+ */
 +
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/kgdb.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/serial.h>
-+#include <linux/serial_reg.h>
-+#include <linux/serialP.h>
-+#include <linux/ioport.h>
 +
-+#include <asm/io.h>
-+#include <asm/serial.h>               /* For BASE_BAUD and SERIAL_PORT_DFNS */
 +
-+#include "8250.h"
 +
-+#define GDB_BUF_SIZE  512     /* power of 2, please */
 +
-+MODULE_DESCRIPTION("KGDB driver for the 8250");
-+MODULE_LICENSE("GPL");
-+/* These will conflict with early_param otherwise. */
-+#ifdef CONFIG_KGDB_8250_MODULE
-+static char config[256];
-+module_param_string(kgdb8250, config, 256, 0);
-+MODULE_PARM_DESC(kgdb8250,
-+               " kgdb8250=<io or mmio>,<address>,<baud rate>,<irq>\n");
-+static struct kgdb_io local_kgdb_io_ops;
-+#endif                                /* CONFIG_KGDB_8250_MODULE */
-+
-+/* Speed of the UART. */
-+static int kgdb8250_baud;
-+
-+/* Flag for if we need to call request_mem_region */
-+static int kgdb8250_needs_request_mem_region;
-+
-+static char kgdb8250_buf[GDB_BUF_SIZE];
-+static atomic_t kgdb8250_buf_in_cnt;
-+static int kgdb8250_buf_out_inx;
-+
-+/* Old-style serial definitions, if existant, and a counter. */
-+#ifdef CONFIG_KGDB_SIMPLE_SERIAL
-+static int __initdata should_copy_rs_table = 1;
-+static struct serial_state old_rs_table[] __initdata = {
-+#ifdef SERIAL_PORT_DFNS
-+      SERIAL_PORT_DFNS
-+#endif
-+};
-+#endif
++munge_extended:
++    CLEAR ACK
++
++at 0x0000015d : */    0x60000040,0x00000000,
++/*
++    INT int_err_unexpected_phase, WHEN NOT MSG_IN
 +
-+/* Our internal table of UARTS. */
-+#define UART_NR       CONFIG_SERIAL_8250_NR_UARTS
-+static struct uart_port kgdb8250_ports[UART_NR];
++at 0x0000015f : */    0x9f030000,0x00000000,
++/*
++    MOVE 1, msg_buf + 1, WHEN MSG_IN
 +
-+static struct uart_port *current_port;
++at 0x00000161 : */    0x0f000001,0x00000001,
++/*
++    JUMP munge_extended_2, IF 0x02
 +
-+/* Base of the UART. */
-+static void *kgdb8250_addr;
++at 0x00000163 : */    0x800c0002,0x000005a4,
++/*
++    JUMP munge_extended_3, IF 0x03 
 +
-+/* Forward declarations. */
-+static int kgdb8250_uart_init(void);
-+static int __init kgdb_init_io(void);
-+static int __init kgdb8250_opt(char *str);
++at 0x00000165 : */    0x800c0003,0x000005d4,
++/*
++    JUMP reject_message
 +
-+/* These are much shorter calls to ioread8/iowrite8 that take into
-+ * account our shifts, etc. */
-+static inline unsigned int kgdb_ioread(u8 mask)
-+{
-+      return ioread8(kgdb8250_addr + (mask << current_port->regshift));
-+}
++at 0x00000167 : */    0x80080000,0x00000604,
++/*
 +
-+static inline void kgdb_iowrite(u8 val, u8 mask)
-+{
-+      iowrite8(val, kgdb8250_addr + (mask << current_port->regshift));
-+}
++munge_extended_2:
++    CLEAR ACK
 +
++at 0x00000169 : */    0x60000040,0x00000000,
 +/*
-+ * Wait until the interface can accept a char, then write it.
-+ */
-+static void kgdb_put_debug_char(u8 chr)
-+{
-+      while (!(kgdb_ioread(UART_LSR) & UART_LSR_THRE)) ;
++    MOVE 1, msg_buf + 2, WHEN MSG_IN
 +
-+      kgdb_iowrite(chr, UART_TX);
-+}
++at 0x0000016b : */    0x0f000001,0x00000002,
++/*
++    JUMP reject_message, IF NOT 0x02  ; Must be WDTR
 +
++at 0x0000016d : */    0x80040002,0x00000604,
 +/*
-+ * Get a byte from the hardware data buffer and return it
-+ */
-+static int read_data_bfr(void)
-+{
-+      char it = kgdb_ioread(UART_LSR);
++    CLEAR ACK
 +
-+      if (it & UART_LSR_DR)
-+              return kgdb_ioread(UART_RX);
++at 0x0000016f : */    0x60000040,0x00000000,
++/*
++    MOVE 1, msg_buf + 3, WHEN MSG_IN
 +
-+      /*
-+       * If we have a framing error assume somebody messed with
-+       * our uart.  Reprogram it and send '-' both ways...
-+       */
-+      if (it & 0xc) {
-+              kgdb8250_uart_init();
-+              kgdb_put_debug_char('-');
-+              return '-';
-+      }
++at 0x00000171 : */    0x0f000001,0x00000003,
++/*
++    INT int_msg_wdtr
 +
-+      return -1;
-+}
++at 0x00000173 : */    0x98080000,0x01000000,
++/*
 +
++munge_extended_3:
++    CLEAR ACK
++
++at 0x00000175 : */    0x60000040,0x00000000,
 +/*
-+ * Get a char if available, return -1 if nothing available.
-+ * Empty the receive buffer first, then look at the interface hardware.
-+ */
-+static int kgdb_get_debug_char(void)
-+{
-+      int retchr;
++    MOVE 1, msg_buf + 2, WHEN MSG_IN
 +
-+      /* intr routine has q'd chars */
-+      if (atomic_read(&kgdb8250_buf_in_cnt) != 0) {
-+              retchr = kgdb8250_buf[kgdb8250_buf_out_inx++];
-+              kgdb8250_buf_out_inx &= (GDB_BUF_SIZE - 1);
-+              atomic_dec(&kgdb8250_buf_in_cnt);
-+              return retchr;
-+      }
++at 0x00000177 : */    0x0f000001,0x00000002,
++/*
++    JUMP reject_message, IF NOT 0x01  ; Must be SDTR
 +
-+      do {
-+              retchr = read_data_bfr();
-+      } while (retchr < 0);
++at 0x00000179 : */    0x80040001,0x00000604,
++/*
++    CLEAR ACK
 +
-+      return retchr;
-+}
++at 0x0000017b : */    0x60000040,0x00000000,
++/*
++    MOVE 2, msg_buf + 3, WHEN MSG_IN
 +
++at 0x0000017d : */    0x0f000002,0x00000003,
 +/*
-+ * This is the receiver interrupt routine for the GDB stub.
-+ * All that we need to do is verify that the interrupt happened on the
-+ * line we're in charge of.  If this is true, schedule a breakpoint and
-+ * return.
-+ */
-+static irqreturn_t
-+kgdb8250_interrupt(int irq, void *dev_id)
-+{
-+      if (kgdb_ioread(UART_IIR) & UART_IIR_RDI) {
-+              /* Throw away the data if another I/O routine is active. */
-+              if (kgdb_io_ops.read_char != kgdb_get_debug_char &&
-+                              (kgdb_ioread(UART_LSR) & UART_LSR_DR))
-+                      kgdb_ioread(UART_RX);
-+              else
-+                      breakpoint();
-+      }
++    INT int_msg_sdtr
 +
-+      return IRQ_HANDLED;
-+}
++at 0x0000017f : */    0x98080000,0x01010000,
++/*
++
++ENTRY reject_message
++reject_message:
++    SET ATN
 +
++at 0x00000181 : */    0x58000008,0x00000000,
 +/*
-+ *  Initializes the UART.
-+ *  Returns:
-+ *    0 on success, 1 on failure.
-+ */
-+static int
-+kgdb8250_uart_init (void)
-+{
-+      unsigned int ier, base_baud = current_port->uartclk ?
-+              current_port->uartclk / 16 : BASE_BAUD;
++    CLEAR ACK
 +
-+      /* test uart existance */
-+      if(kgdb_ioread(UART_LSR) == 0xff)
-+              return -1;
++at 0x00000183 : */    0x60000040,0x00000000,
++/*
++    MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT
 +
-+      /* disable interrupts */
-+      kgdb_iowrite(0, UART_IER);
-+
-+#if defined(CONFIG_ARCH_OMAP1510)
-+      /* Workaround to enable 115200 baud on OMAP1510 internal ports */
-+      if (cpu_is_omap1510() && is_omap_port((void *)kgdb8250_addr)) {
-+              if (kgdb8250_baud == 115200) {
-+                      base_baud = 1;
-+                      kgdb8250_baud = 1;
-+                      kgdb_iowrite(1, UART_OMAP_OSC_12M_SEL);
-+              } else
-+                      kgdb_iowrite(0, UART_OMAP_OSC_12M_SEL);
-+      }
-+#endif
-+      /* set DLAB */
-+      kgdb_iowrite(UART_LCR_DLAB, UART_LCR);
++at 0x00000185 : */    0x0e000001,0x00000000,
++/*
++    RETURN
 +
-+      /* set baud */
-+      kgdb_iowrite((base_baud / kgdb8250_baud) & 0xff, UART_DLL);
-+      kgdb_iowrite((base_baud / kgdb8250_baud) >> 8, UART_DLM);
++at 0x00000187 : */    0x90080000,0x00000000,
++/*
 +
-+      /* reset DLAB, set LCR */
-+      kgdb_iowrite(UART_LCR_WLEN8, UART_LCR);
++ENTRY accept_message
++accept_message:
++    CLEAR ATN
 +
-+      /* set DTR and RTS */
-+      kgdb_iowrite(UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS, UART_MCR);
++at 0x00000189 : */    0x60000008,0x00000000,
++/*
++    CLEAR ACK
 +
-+      /* setup fifo */
-+      kgdb_iowrite(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR
-+              | UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_8,
-+              UART_FCR);
++at 0x0000018b : */    0x60000040,0x00000000,
++/*
++    RETURN
 +
-+      /* clear pending interrupts */
-+      kgdb_ioread(UART_IIR);
-+      kgdb_ioread(UART_RX);
-+      kgdb_ioread(UART_LSR);
-+      kgdb_ioread(UART_MSR);
++at 0x0000018d : */    0x90080000,0x00000000,
++/*
 +
-+      /* turn on RX interrupt only */
-+      kgdb_iowrite(UART_IER_RDI, UART_IER);
++ENTRY respond_message
++respond_message:
++    SET ATN
 +
-+      /*
-+       * Borrowed from the main 8250 driver.
-+       * Try writing and reading the UART_IER_UUE bit (b6).
-+       * If it works, this is probably one of the Xscale platform's
-+       * internal UARTs.
-+       * We're going to explicitly set the UUE bit to 0 before
-+       * trying to write and read a 1 just to make sure it's not
-+       * already a 1 and maybe locked there before we even start start.
-+       */
-+      ier = kgdb_ioread(UART_IER);
-+      kgdb_iowrite(ier & ~UART_IER_UUE, UART_IER);
-+      if (!(kgdb_ioread(UART_IER) & UART_IER_UUE)) {
-+              /*
-+               * OK it's in a known zero state, try writing and reading
-+               * without disturbing the current state of the other bits.
-+               */
-+              kgdb_iowrite(ier | UART_IER_UUE, UART_IER);
-+              if (kgdb_ioread(UART_IER) & UART_IER_UUE)
-+                      /*
-+                       * It's an Xscale.
-+                       */
-+                      ier |= UART_IER_UUE | UART_IER_RTOIE;
-+      }
-+      kgdb_iowrite(ier, UART_IER);
-+      return 0;
-+}
++at 0x0000018f : */    0x58000008,0x00000000,
++/*
++    CLEAR ACK
 +
++at 0x00000191 : */    0x60000040,0x00000000,
 +/*
-+ * Copy the old serial_state table to our uart_port table if we haven't
-+ * had values specifically configured in.  We need to make sure this only
-+ * happens once.
-+ */
-+static void __init kgdb8250_copy_rs_table(void)
-+{
-+#ifdef CONFIG_KGDB_SIMPLE_SERIAL
-+      int i;
++    MOVE FROM dsa_msgout_other, WHEN MSG_OUT
 +
-+      if (!should_copy_rs_table)
-+              return;
++at 0x00000193 : */    0x1e000000,0x00000068,
++/*
++    RETURN
 +
-+      for (i = 0; i < ARRAY_SIZE(old_rs_table); i++) {
-+              kgdb8250_ports[i].iobase = old_rs_table[i].port;
-+              kgdb8250_ports[i].irq = irq_canonicalize(old_rs_table[i].irq);
-+              kgdb8250_ports[i].uartclk = old_rs_table[i].baud_base * 16;
-+              kgdb8250_ports[i].membase = old_rs_table[i].iomem_base;
-+              kgdb8250_ports[i].iotype = old_rs_table[i].io_type;
-+              kgdb8250_ports[i].regshift = old_rs_table[i].iomem_reg_shift;
-+              kgdb8250_ports[i].line = i;
-+      }
++at 0x00000195 : */    0x90080000,0x00000000,
++/*
 +
-+      should_copy_rs_table = 0;
-+#endif
-+}
++;
++; command_complete
++;
++; PURPOSE : handle command termination when STATUS IN is detected by reading
++;     a status byte followed by a command termination message. 
++;
++;     Normal termination results in an INTFLY instruction, and 
++;     the host system can pick out which command terminated by 
++;     examining the MESSAGE and STATUS buffers of all currently 
++;     executing commands;
++;
++;     Abnormal (CHECK_CONDITION) termination results in an
++;     int_err_check_condition interrupt so that a REQUEST SENSE
++;     command can be issued out-of-order so that no other command
++;     clears the contingent allegiance condition.
++;     
++;
++; INPUTS : DSA - command      
++;
++; CALLS : OK
++;
++; EXITS : On successful termination, control is passed to schedule.
++;     On abnormal termination, the user will usually modify the 
++;     DSA fields and corresponding buffers and return control
++;     to select.
++;
++
++ENTRY command_complete
++command_complete:
++    MOVE FROM dsa_status, WHEN STATUS
++
++at 0x00000197 : */    0x1b000000,0x00000060,
++/*
++
++    MOVE SFBR TO SCRATCH0             ; Save status
 +
++at 0x00000199 : */    0x6a340000,0x00000000,
 +/*
-+ * Hookup our IRQ line now that it is safe to do so, after we grab any
-+ * memory regions we might need to.  If we haven't been initialized yet,
-+ * go ahead and copy the old_rs_table in.
-+ */
-+static void __init kgdb8250_late_init(void)
-+{
-+      /* Try and copy the old_rs_table. */
-+      kgdb8250_copy_rs_table();
 +
-+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
-+      /* Take the port away from the main driver. */
-+      serial8250_unregister_by_port(current_port);
++ENTRY command_complete_msgin
++command_complete_msgin:
++    MOVE FROM dsa_msgin, WHEN MSG_IN
 +
-+      /* Now reinit the port as the above has disabled things. */
-+      kgdb8250_uart_init();
-+#endif
-+      /* We may need to call request_mem_region() first. */
-+      if (kgdb8250_needs_request_mem_region)
-+              request_mem_region(current_port->mapbase,
-+                                 8 << current_port->regshift, "kgdb");
-+      if (request_irq(current_port->irq, kgdb8250_interrupt, SA_SHIRQ,
-+                      "GDB-stub", current_port) < 0)
-+              printk(KERN_ERR "KGDB failed to request the serial IRQ (%d)\n",
-+                     current_port->irq);
-+}
++at 0x0000019b : */    0x1f000000,0x00000058,
++/*
++; Indicate that we should be expecting a disconnect
 +
-+static __init int kgdb_init_io(void)
-+{
-+      /* Give us the basic table of uarts. */
-+      kgdb8250_copy_rs_table();
 +
-+      /* We're either a module and parse a config string, or we have a
-+       * semi-static config. */
-+#ifdef CONFIG_KGDB_8250_MODULE
-+      if (strlen(config)) {
-+              if (kgdb8250_opt(config))
-+                      return -EINVAL;
-+      } else {
-+              printk(KERN_ERR "kgdb8250: argument error, usage: "
-+                     "kgdb8250=<io or mmio>,<address>,<baud rate>,<irq>\n");
-+              return -EINVAL;
-+      }
-+#elif defined(CONFIG_KGDB_SIMPLE_SERIAL)
-+      kgdb8250_baud = CONFIG_KGDB_BAUDRATE;
 +
-+      /* Setup our pointer to the serial port now. */
-+      current_port = &kgdb8250_ports[CONFIG_KGDB_PORT_NUM];
-+#else
-+      if (kgdb8250_opt(CONFIG_KGDB_8250_CONF_STRING))
-+              return -EINVAL;
-+#endif
++    ; Above code cleared the Unexpected Disconnect bit, what do we do?
 +
++    CLEAR ACK
 +
-+      /* Internal driver setup. */
-+      switch (current_port->iotype) {
-+      case UPIO_MEM:
-+              if (current_port->mapbase)
-+                      kgdb8250_needs_request_mem_region = 1;
-+              if (current_port->flags & UPF_IOREMAP) {
-+                      current_port->membase = ioremap(current_port->mapbase,
-+                                              8 << current_port->regshift);
-+                      if (!current_port->membase)
-+                              return -EIO;    /* Failed. */
-+              }
-+              kgdb8250_addr = current_port->membase;
-+              break;
-+      case UPIO_PORT:
-+      default:
-+              kgdb8250_addr = ioport_map(current_port->iobase,
-+                                         8 << current_port->regshift);
-+              if (!kgdb8250_addr)
-+                      return -EIO;    /* Failed. */
-+      }
++at 0x0000019d : */    0x60000040,0x00000000,
++/*
 +
-+      if (kgdb8250_uart_init() == -1) {
-+              printk(KERN_ERR "kgdb8250: init failed\n");
-+              return -EIO;
-+      }
-+#ifdef CONFIG_KGDB_8250_MODULE
-+      /* Attach the kgdb irq. When this is built into the kernel, it
-+       * is called as a part of late_init sequence.
-+       */
-+      kgdb8250_late_init();
-+      if (kgdb_register_io_module(&local_kgdb_io_ops))
-+              return -EINVAL;
++    WAIT DISCONNECT
 +
-+      printk(KERN_INFO "kgdb8250: debugging enabled\n");
-+#endif                                /* CONFIG_KGD_8250_MODULE */
++at 0x0000019f : */    0x48000000,0x00000000,
++/*
++
++;
++; The SCSI specification states that when a UNIT ATTENTION condition
++; is pending, as indicated by a CHECK CONDITION status message,
++; the target shall revert to asynchronous transfers.  Since
++; synchronous transfers parameters are maintained on a per INITIATOR/TARGET 
++; basis, and returning control to our scheduler could work on a command
++; running on another lun on that target using the old parameters, we must
++; interrupt the host processor to get them changed, or change them ourselves.
++;
++; Once SCSI-II tagged queueing is implemented, things will be even more
++; hairy, since contingent allegiance conditions exist on a per-target/lun
++; basis, and issuing a new command with a different tag would clear it.
++; In these cases, we must interrupt the host processor to get a request 
++; added to the HEAD of the queue with the request sense command, or we
++; must automatically issue the request sense command.
 +
-+      return 0;
-+}
 +
-+#ifdef CONFIG_KGDB_8250_MODULE
-+/* If it is a module the kgdb_io_ops should be a static which
-+ * is passed to the KGDB I/O initialization
-+ */
-+static struct kgdb_io local_kgdb_io_ops = {
-+#else                         /* ! CONFIG_KGDB_8250_MODULE */
-+struct kgdb_io kgdb_io_ops = {
-+#endif                                /* ! CONFIG_KGD_8250_MODULE */
-+      .read_char = kgdb_get_debug_char,
-+      .write_char = kgdb_put_debug_char,
-+      .init = kgdb_init_io,
-+      .late_init = kgdb8250_late_init,
-+};
 +
-+/**
-+ *    kgdb8250_add_port - Define a serial port for use with KGDB
-+ *    @i: The index of the port being added
-+ *    @serial_req: The &struct uart_port describing the port
-+ *
-+ *    On platforms where we must register the serial device
-+ *    dynamically, this is the best option if a platform also normally
-+ *    calls early_serial_setup().
-+ */
-+void __init kgdb8250_add_port(int i, struct uart_port *serial_req)
-+{
-+      /* Make sure we've got the built-in data before we override. */
-+      kgdb8250_copy_rs_table();
 +
-+      /* Copy the whole thing over. */
-+      if (current_port != &kgdb8250_ports[i])
-+                memcpy(&kgdb8250_ports[i], serial_req, sizeof(struct uart_port));
-+}
 +
-+/**
-+ *    kgdb8250_add_platform_port - Define a serial port for use with KGDB
-+ *    @i: The index of the port being added
-+ *    @p: The &struct plat_serial8250_port describing the port
-+ *
-+ *    On platforms where we must register the serial device
-+ *    dynamically, this is the best option if a platform normally
-+ *    handles uart setup with an array of &struct plat_serial8250_port.
-+ */
-+void __init kgdb8250_add_platform_port(int i, struct plat_serial8250_port *p)
-+{
-+      /* Make sure we've got the built-in data before we override. */
-+      kgdb8250_copy_rs_table();
 +
-+      kgdb8250_ports[i].iobase = p->iobase;
-+      kgdb8250_ports[i].membase = p->membase;
-+      kgdb8250_ports[i].irq = p->irq;
-+      kgdb8250_ports[i].uartclk = p->uartclk;
-+      kgdb8250_ports[i].regshift = p->regshift;
-+      kgdb8250_ports[i].iotype = p->iotype;
-+      kgdb8250_ports[i].flags = p->flags;
-+      kgdb8250_ports[i].mapbase = p->mapbase;
-+}
 +
++    INT int_norm_emulateintfly
++
++at 0x000001a1 : */    0x98080000,0x02060000,
 +/*
-+ * Syntax for this cmdline option is:
-+ * kgdb8250=<io or mmio>,<address>,<baud rate>,<irq>"
-+ */
-+static int __init kgdb8250_opt(char *str)
-+{
-+      /* We'll fill out and use the first slot. */
-+      current_port = &kgdb8250_ports[0];
-+
-+      if (!strncmp(str, "io", 2)) {
-+              current_port->iotype = UPIO_PORT;
-+              str += 2;
-+      } else if (!strncmp(str, "mmap", 4)) {
-+              current_port->iotype = UPIO_MEM;
-+              current_port->flags |= UPF_IOREMAP;
-+              str += 4;
-+      } else if (!strncmp(str, "mmio", 4)) {
-+              current_port->iotype = UPIO_MEM;
-+              current_port->flags &= ~UPF_IOREMAP;
-+              str += 4;
-+      } else
-+              goto errout;
 +
-+      if (*str != ',')
-+              goto errout;
-+      str++;
 +
-+      if (current_port->iotype == UPIO_PORT)
-+              current_port->iobase = simple_strtoul(str, &str, 16);
-+      else {
-+              if (current_port->flags & UPF_IOREMAP)
-+                      current_port->mapbase =
-+                              (unsigned long) simple_strtoul(str, &str, 16);
-+              else
-+                      current_port->membase =
-+                              (void *) simple_strtoul(str, &str, 16);
-+      }
 +
-+      if (*str != ',')
-+              goto errout;
-+      str++;
 +
-+      kgdb8250_baud = simple_strtoul(str, &str, 10);
-+      if (!kgdb8250_baud)
-+              goto errout;
 +
-+      if (*str != ',')
-+              goto errout;
-+      str++;
 +
-+      current_port->irq = simple_strtoul(str, &str, 10);
++    ; Time to correct DSA following memory move
++    MOVE MEMORY 4, saved_dsa, addr_dsa
 +
-+#ifdef CONFIG_KGDB_SIMPLE_SERIAL
-+      should_copy_rs_table = 0;
-+#endif
++at 0x000001a3 : */    0xc0000004,0x00000000,0x00000000,
++/*
 +
-+      return 0;
 +
-+      errout:
-+      printk(KERN_ERR "Invalid syntax for option kgdb8250=\n");
-+      return 1;
-+}
 +
-+#ifdef CONFIG_KGDB_8250_MODULE
-+static void cleanup_kgdb8250(void)
-+{
-+      kgdb_unregister_io_module(&local_kgdb_io_ops);
 +
-+      /* Clean up the irq and memory */
-+      free_irq(current_port->irq, current_port);
 +
-+      if (kgdb8250_needs_request_mem_region)
-+              release_mem_region(current_port->mapbase,
-+                                 8 << current_port->regshift);
-+      /* Hook up the serial port back to what it was previously
-+       * hooked up to.
-+       */
-+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
-+      /* Give the port back to the 8250 driver. */
-+      serial8250_register_port(current_port);
-+#endif
-+}
++    JUMP schedule
 +
-+module_init(kgdb_init_io);
-+module_exit(cleanup_kgdb8250);
-+#else                         /* ! CONFIG_KGDB_8250_MODULE */
-+early_param("kgdb8250", kgdb8250_opt);
-+#endif                                /* ! CONFIG_KGDB_8250_MODULE */
-diff -Nurb linux-2.6.22-570/drivers/serial/Kconfig linux-2.6.22-590/drivers/serial/Kconfig
---- linux-2.6.22-570/drivers/serial/Kconfig    2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/serial/Kconfig    2008-01-02 13:56:37.000000000 -0500
-@@ -107,7 +107,7 @@
- config SERIAL_8250_NR_UARTS
-       int "Maximum number of 8250/16550 serial ports"
--      depends on SERIAL_8250
-+      depends on SERIAL_8250 || KGDB_8250
-       default "4"
-       help
-         Set this to the number of serial ports you want the driver
-diff -Nurb linux-2.6.22-570/drivers/serial/Makefile linux-2.6.22-590/drivers/serial/Makefile
---- linux-2.6.22-570/drivers/serial/Makefile   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/serial/Makefile   2008-01-02 13:56:37.000000000 -0500
-@@ -23,6 +23,7 @@
- obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o
- obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
- obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
-+obj-$(CONFIG_KGDB_AMBA_PL011) += pl011_kgdb.o
- obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
- obj-$(CONFIG_SERIAL_PXA) += pxa.o
- obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
-@@ -50,10 +51,12 @@
- obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
- obj-$(CONFIG_SERIAL_ICOM) += icom.o
- obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
-+obj-$(CONFIG_KGDB_MPSC) += mpsc_kgdb.o
- obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
- obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
- obj-$(CONFIG_SERIAL_JSM) += jsm/
- obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
-+obj-$(CONFIG_KGDB_TXX9) += serial_txx9_kgdb.o
- obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
- obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
- obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
-@@ -62,3 +65,4 @@
- obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
- obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
- obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
-+obj-$(CONFIG_KGDB_8250) += 8250_kgdb.o
-diff -Nurb linux-2.6.22-570/drivers/serial/amba-pl011.c linux-2.6.22-590/drivers/serial/amba-pl011.c
---- linux-2.6.22-570/drivers/serial/amba-pl011.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/serial/amba-pl011.c       2008-01-02 13:56:37.000000000 -0500
-@@ -332,7 +332,7 @@
-       /*
-        * Allocate the IRQ
-        */
--      retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
-+      retval = request_irq(uap->port.irq, pl011_int, SA_SHIRQ, "uart-pl011", uap);
-       if (retval)
-               goto clk_dis;
-diff -Nurb linux-2.6.22-570/drivers/serial/cpm_uart/Makefile linux-2.6.22-590/drivers/serial/cpm_uart/Makefile
---- linux-2.6.22-570/drivers/serial/cpm_uart/Makefile  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/serial/cpm_uart/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -7,5 +7,6 @@
- # Select the correct platform objects.
- cpm_uart-objs-$(CONFIG_CPM2)  += cpm_uart_cpm2.o
- cpm_uart-objs-$(CONFIG_8xx)   += cpm_uart_cpm1.o
-+cpm_uart-objs-$(CONFIG_KGDB_CPM_UART) += cpm_uart_kgdb.o
- cpm_uart-objs := cpm_uart_core.o $(cpm_uart-objs-y)
-diff -Nurb linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart.h linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart.h
---- linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart.h        2008-01-02 13:56:37.000000000 -0500
-@@ -50,6 +50,41 @@
- #define SCC_WAIT_CLOSING 100
-+#ifdef CONFIG_KGDB_CPM_UART
-+
-+/* Speed of the debug UART. */
-+#if CONFIG_KGDB_BAUDRATE == 9600
-+#define KGDB_BAUD B9600
-+#elif CONFIG_KGDB_BAUDRATE == 19200
-+#define KGDB_BAUD B19200
-+#elif CONFIG_KGDB_BAUDRATE == 38400
-+#define KGDB_BAUD B38400
-+#elif CONFIG_KGDB_BAUDRATE == 57600
-+#define KGDB_BAUD B57600
-+#elif CONFIG_KGDB_BAUDRATE == 115200
-+#define KGDB_BAUD B115200     /* Start with this if not given */
-+#else
-+#error Unsupported baud rate!
-+#endif
-+
-+#if defined(CONFIG_KGDB_CPM_UART_SCC1)
-+#define KGDB_PINFO_INDEX      UART_SCC1
-+#elif defined(CONFIG_KGDB_CPM_UART_SCC2)
-+#define KGDB_PINFO_INDEX      UART_SCC2
-+#elif defined(CONFIG_KGDB_CPM_UART_SCC3)
-+#define KGDB_PINFO_INDEX      UART_SCC3
-+#elif defined(CONFIG_KGDB_CPM_UART_SCC4)
-+#define KGDB_PINFO_INDEX      UART_SCC4
-+#elif defined(CONFIG_KGDB_CPM_UART_SMC1)
-+#define KGDB_PINFO_INDEX      UART_SMC1
-+#elif defined(CONFIG_KGDB_CPM_UART_SMC2)
-+#define KGDB_PINFO_INDEX      UART_SMC2
-+#else
-+#error The port for KGDB is undefined!
-+#endif
++at 0x000001a6 : */    0x80080000,0x00000000,
++/*
++command_failed:
++    INT int_err_check_condition
 +
-+#endif /* CONFIG_KGDB_CPM_UART */
++at 0x000001a8 : */    0x98080000,0x00030000,
++/*
 +
- struct uart_cpm_port {
-       struct uart_port        port;
-       u16                     rx_nrfifos;
-@@ -86,6 +121,9 @@
- extern int cpm_uart_nr;
- extern struct uart_cpm_port cpm_uart_ports[UART_NR];
-+void cpm_uart_early_write(int index, const char *s, u_int count);
-+int cpm_uart_early_setup(int index,int early);
 +
- /* these are located in their respective files */
- void cpm_line_cr_cmd(int line, int cmd);
- int cpm_uart_init_portdesc(void);
-@@ -132,5 +170,4 @@
-       return 0;
- }
--
- #endif /* CPM_UART_H */
-diff -Nurb linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_core.c linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_core.c
---- linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_core.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_core.c   2008-01-02 13:56:37.000000000 -0500
-@@ -1073,22 +1073,17 @@
-       return 0;
- }
--#ifdef CONFIG_SERIAL_CPM_CONSOLE
--/*
-- *    Print a string to the serial port trying not to disturb
-- *    any possible real use of the port...
-- *
-- *    Note that this is called with interrupts already disabled
-- */
--static void cpm_uart_console_write(struct console *co, const char *s,
-+void cpm_uart_early_write(int index, const char *s,
-                                  u_int count)
- {
--      struct uart_cpm_port *pinfo =
--          &cpm_uart_ports[cpm_uart_port_map[co->index]];
-+      struct uart_cpm_port *pinfo;
-       unsigned int i;
-       volatile cbd_t *bdp, *bdbase;
-       volatile unsigned char *cp;
-+      BUG_ON(index>UART_NR);
-+      pinfo = &cpm_uart_ports[index];
 +
-       /* Get the address of the host memory buffer.
-        */
-       bdp = pinfo->tx_cur;
-@@ -1152,19 +1147,14 @@
-       pinfo->tx_cur = (volatile cbd_t *) bdp;
- }
--
--static int __init cpm_uart_console_setup(struct console *co, char *options)
-+int cpm_uart_early_setup(int index, int early)
- {
-+      int ret;
-       struct uart_port *port;
-       struct uart_cpm_port *pinfo;
--      int baud = 38400;
--      int bits = 8;
--      int parity = 'n';
--      int flow = 'n';
--      int ret;
-       struct fs_uart_platform_info *pdata;
--      struct platform_device* pdev = early_uart_get_pdev(co->index);
-+      struct platform_device* pdev = early_uart_get_pdev(index);
-       if (!pdev) {
-               pr_info("cpm_uart: console: compat mode\n");
-@@ -1172,8 +1162,9 @@
-               cpm_uart_init_portdesc();
-       }
-+      BUG_ON(index>UART_NR);
-       port =
--          (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
-+              (struct uart_port *)&cpm_uart_ports[index];
-       pinfo = (struct uart_cpm_port *)port;
-       if (!pdev) {
-               if (pinfo->set_lineif)
-@@ -1187,15 +1178,6 @@
-               cpm_uart_drv_get_platform_data(pdev, 1);
-       }
--      pinfo->flags |= FLAG_CONSOLE;
--
--      if (options) {
--              uart_parse_options(options, &baud, &parity, &bits, &flow);
--      } else {
--              if ((baud = uart_baudrate()) == -1)
--                      baud = 9600;
--      }
--
-       if (IS_SMC(pinfo)) {
-               pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
-               pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-@@ -1203,8 +1185,7 @@
-               pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
-               pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-       }
--
--      ret = cpm_uart_allocbuf(pinfo, 1);
-+      ret = cpm_uart_allocbuf(pinfo, early);
-       if (ret)
-               return ret;
-@@ -1216,6 +1197,62 @@
-       else
-               cpm_uart_init_scc(pinfo);
-+      return 0;
-+}
 +
-+#ifdef CONFIG_SERIAL_CPM_CONSOLE
++;
++; wait_reselect
++;
++; PURPOSE : This is essentially the idle routine, where control lands
++;     when there are no new processes to schedule.  wait_reselect
++;     waits for reselection, selection, and new commands.
++;
++;     When a successful reselection occurs, with the aid 
++;     of fixed up code in each DSA, wait_reselect walks the 
++;     reconnect_dsa_queue, asking each dsa if the target ID
++;     and LUN match its.
++;
++;     If a match is found, a call is made back to reselected_ok,
++;     which through the miracles of self modifying code, extracts
++;     the found DSA from the reconnect_dsa_queue and then 
++;     returns control to the DSAs thread of execution.
++;
++; INPUTS : NONE
++;
++; CALLS : OK
++;
++; MODIFIES : DSA,
++;
++; EXITS : On successful reselection, control is returned to the 
++;     DSA which called reselected_ok.  If the WAIT RESELECT
++;     was interrupted by a new commands arrival signaled by 
++;     SIG_P, control is passed to schedule.  If the NCR is 
++;     selected, the host system is interrupted with an 
++;     int_err_selected which is usually responded to by
++;     setting DSP to the target_abort address.
++
++ENTRY wait_reselect
++wait_reselect:
++
++
++
++
++
++
++    WAIT RESELECT wait_reselect_failed
++
++at 0x000001aa : */    0x50000000,0x00000800,
 +/*
-+ *    Print a string to the serial port trying not to disturb
-+ *    any possible real use of the port...
-+ *
-+ *    Note that this is called with interrupts already disabled
-+ */
 +
-+static void cpm_uart_console_write(struct console *co, const char *s,
-+                                 u_int count)
-+{
-+      cpm_uart_early_write(cpm_uart_port_map[co->index],s,count);
-+}
++reselected:
++
 +
++
++    CLEAR TARGET
++
++at 0x000001ac : */    0x60000200,0x00000000,
 +/*
-+ * Setup console. Be careful is called early !
-+ */
-+static int __init cpm_uart_console_setup(struct console *co, char *options)
-+{
-+      struct uart_port *port;
-+      struct uart_cpm_port *pinfo;
-+      int baud = 115200;
-+      int bits = 8;
-+      int parity = 'n';
-+      int flow = 'n';
-+      int ret;
++    
++    ; Read all data needed to reestablish the nexus - 
++    MOVE 1, reselected_identify, WHEN MSG_IN
++
++at 0x000001ae : */    0x0f000001,0x00000000,
++/*
++    ; We used to CLEAR ACK here.
++
++
++
++
++
++    ; Point DSA at the current head of the disconnected queue.
++    
++    MOVE MEMORY 4, reconnect_dsa_head, addr_scratch
++
++at 0x000001b0 : */    0xc0000004,0x00000000,0x00000000,
++/*
++    
++
++    MOVE MEMORY 4, addr_scratch, saved_dsa
++
++at 0x000001b3 : */    0xc0000004,0x00000000,0x00000000,
++/*
++
++
 +
-+#ifdef CONFIG_KGDB_CPM_UART
-+      /* We are not interested in ports yet utilized by kgdb */
-+      if (co->index == KGDB_PINFO_INDEX)
-+              return 0;
-+#endif
 +
-+      port =
-+          (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
-+      pinfo = (struct uart_cpm_port *)port;
++    ; Fix the update-next pointer so that the reconnect_dsa_head
++    ; pointer is the one that will be updated if this DSA is a hit 
++    ; and we remove it from the queue.
 +
-+      pinfo->flags |= FLAG_CONSOLE;
++    MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok_patch + 8
 +
-+      if (options) {
-+              uart_parse_options(options, &baud, &parity, &bits, &flow);
-+      } else {
-+              bd_t *bd = (bd_t *) __res;
++at 0x000001b6 : */    0xc0000004,0x00000000,0x000007ec,
++/*
 +
-+              if (bd->bi_baudrate)
-+                      baud = bd->bi_baudrate;
-+              else
-+                      baud = 9600;
-+      }
++    ; Time to correct DSA following memory move
++    MOVE MEMORY 4, saved_dsa, addr_dsa
 +
-+      ret = cpm_uart_early_setup(cpm_uart_port_map[co->index], 1);
-+      if(ret)
-+              return ret;
-       uart_set_options(port, co, baud, parity, bits, flow);
-       return 0;
-@@ -1266,6 +1303,12 @@
-       pdata = pdev->dev.platform_data;
-+#ifdef CONFIG_KGDB_CPM_UART
-+      /* We are not interested in ports yet utilized by kgdb */
-+      if (cpm_uart_id2nr(fs_uart_get_id(pdata)) == KGDB_PINFO_INDEX)
-+              return ret;
-+#endif
++at 0x000001b9 : */    0xc0000004,0x00000000,0x00000000,
++/*
 +
-       if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))
-               return ret;
-@@ -1363,6 +1406,12 @@
-               for (i = 0; i < cpm_uart_nr; i++) {
-                       int con = cpm_uart_port_map[i];
 +
-+#ifdef CONFIG_KGDB_CPM_UART
-+                      /* We are not interested in ports yet utilized by kgdb */
-+                      if (con == KGDB_PINFO_INDEX)
-+                              continue;
-+#endif
-                       cpm_uart_ports[con].port.line = i;
-                       cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF;
-                       if (cpm_uart_ports[con].set_lineif)
-diff -Nurb linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_cpm1.c linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_cpm1.c
---- linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_cpm1.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_cpm1.c   2008-01-02 13:56:37.000000000 -0500
-@@ -53,6 +53,7 @@
- {
-       ushort val;
-       volatile cpm8xx_t *cp = cpmp;
-+      unsigned *bcsr_io;
-       switch (line) {
-       case UART_SMC1:
-@@ -95,12 +96,35 @@
- {
-       /* XXX SCC1: insert port configuration here */
-       pinfo->brg = 1;
++ENTRY reselected_check_next
++reselected_check_next:
 +
-+#if defined (CONFIG_MPC885ADS) || defined (CONFIG_MPC86XADS)
-+      bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
 +
-+      if (bcsr_io == NULL) {
-+              printk(KERN_CRIT "Could not remap BCSR\n");
-+              return;
-+      }
-+      out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_RS232EN_1);
-+      iounmap(bcsr_io);
-+#endif
- }
- void scc2_lineif(struct uart_cpm_port *pinfo)
- {
-       /* XXX SCC2: insert port configuration here */
-       pinfo->brg = 2;
-+      unsigned *bcsr_io;
 +
-+#if defined (CONFIG_MPC885ADS) || defined (CONFIG_MPC86XADS)
-+      bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
++    ; Check for a NULL pointer.
++    MOVE DSA0 TO SFBR
 +
-+      if (bcsr_io == NULL) {
-+              printk(KERN_CRIT "Could not remap BCSR\n");
-+              return;
-+      }
-+        out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_RS232EN_2);
-+      iounmap(bcsr_io);
-+#endif
- }
- void scc3_lineif(struct uart_cpm_port *pinfo)
-@@ -189,6 +213,10 @@
- {
-       pr_debug("CPM uart[-]:init portdesc\n");
-+      /* Check if we have called this yet. This may happen if early kgdb
-+      breakpoint is on */
-+      if(cpm_uart_nr)
-+              return 0;
-       cpm_uart_nr = 0;
- #ifdef CONFIG_SERIAL_CPM_SMC1
-       cpm_uart_ports[UART_SMC1].smcp = &cpmp->cp_smc[0];
-diff -Nurb linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_cpm2.c linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_cpm2.c
---- linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_cpm2.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_cpm2.c   2008-01-02 13:56:37.000000000 -0500
-@@ -289,6 +289,10 @@
- #endif
-       pr_debug("CPM uart[-]:init portdesc\n");
-+      /* Check if we have called this yet. This may happen if early kgdb
-+      breakpoint is on */
-+      if(cpm_uart_nr)
-+              return 0;
-       cpm_uart_nr = 0;
- #ifdef CONFIG_SERIAL_CPM_SMC1
-       cpm_uart_ports[UART_SMC1].smcp = (smc_t *) cpm2_map(im_smc[0]);
-diff -Nurb linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_kgdb.c linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_kgdb.c
---- linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_kgdb.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_kgdb.c   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,185 @@
++at 0x000001bc : */    0x72100000,0x00000000,
 +/*
-+ * drivers/serial/cpm_uart/cpm_uart_kgdb.c
-+ *
-+ * CPM UART interface for kgdb.
-+ *
-+ * Author: Vitaly Bordug <vbordug@ru.mvista.com>
-+ *
-+ * Used some bits from drivers/serial/kgdb_8250.c as a template
-+ *
-+ * 2005-2007 (c) MontaVista Software, Inc. This file is licensed under
-+ * the terms of the GNU General Public License version 2. This program
-+ * is licensed "as is" without any warranty of any kind, whether express
-+ * or implied.
-+ */
-+
-+#include <linux/kgdb.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/serial.h>
-+#include <linux/serial_core.h>
-+#include <linux/serial_reg.h>
++    JUMP reselected_not_end, IF NOT 0
 +
-+#include <asm/io.h>
-+#include <asm/serial.h>               /* For BASE_BAUD and SERIAL_PORT_DFNS */
++at 0x000001be : */    0x80040000,0x00000738,
++/*
++    MOVE DSA1 TO SFBR
 +
-+#include "cpm_uart.h"
++at 0x000001c0 : */    0x72110000,0x00000000,
++/*
++    JUMP reselected_not_end, IF NOT 0
 +
-+#define GDB_BUF_SIZE  512     /* power of 2, please */
++at 0x000001c2 : */    0x80040000,0x00000738,
++/*
++    MOVE DSA2 TO SFBR
 +
++at 0x000001c4 : */    0x72120000,0x00000000,
++/*
++    JUMP reselected_not_end, IF NOT 0
 +
-+static char kgdb_buf[GDB_BUF_SIZE], *kgdbp;
-+static int kgdb_chars;
++at 0x000001c6 : */    0x80040000,0x00000738,
++/*
++    MOVE DSA3 TO SFBR
 +
-+/* Forward declarations. */
++at 0x000001c8 : */    0x72130000,0x00000000,
++/*
++    JUMP reselected_not_end, IF NOT 0
 +
++at 0x000001ca : */    0x80040000,0x00000738,
 +/*
-+ * Receive character from the serial port.  This only works well
-+ * before the port is initialize for real use.
-+ */
-+static int kgdb_wait_key(char *obuf)
-+{
-+      struct uart_cpm_port *pinfo;
-+      u_char          c, *cp;
-+      volatile cbd_t  *bdp;
-+      int             i;
++    INT int_err_unexpected_reselect
 +
-+      pinfo = &cpm_uart_ports[KGDB_PINFO_INDEX];
++at 0x000001cc : */    0x98080000,0x00020000,
++/*
 +
-+      /* Get the address of the host memory buffer.
-+       */
-+      bdp = pinfo->rx_cur;
-+      while (bdp->cbd_sc & BD_SC_EMPTY);
++reselected_not_end:
++    ;
++    ; XXX the ALU is only eight bits wide, and the assembler
++    ; wont do the dirt work for us.  As long as dsa_check_reselect
++    ; is negative, we need to sign extend with 1 bits to the full
++    ; 32 bit width of the address.
++    ;
++    ; A potential work around would be to have a known alignment 
++    ; of the DSA structure such that the base address plus 
++    ; dsa_check_reselect doesn't require carrying from bytes 
++    ; higher than the LSB.
++    ;
++
++    MOVE DSA0 TO SFBR
++
++at 0x000001ce : */    0x72100000,0x00000000,
++/*
++    MOVE SFBR + dsa_check_reselect TO SCRATCH0
 +
-+      /* If the buffer address is in the CPM DPRAM, don't
-+       * convert it.
-+       */
-+      cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
++at 0x000001d0 : */    0x6e340000,0x00000000,
++/*
++    MOVE DSA1 TO SFBR
 +
-+      if (obuf) {
-+              i = c = bdp->cbd_datlen;
-+              while (i-- > 0)
-+                      *obuf++ = *cp++;
-+      } else
-+              c = *cp;
-+      bdp->cbd_sc |= BD_SC_EMPTY;
++at 0x000001d2 : */    0x72110000,0x00000000,
++/*
++    MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY
 +
-+      if (bdp->cbd_sc & BD_SC_WRAP)
-+              bdp = pinfo->rx_bd_base;
-+      else
-+              bdp++;
-+      pinfo->rx_cur = (cbd_t *)bdp;
++at 0x000001d4 : */    0x6f35ff00,0x00000000,
++/*
++    MOVE DSA2 TO SFBR
 +
-+      return (int)c;
-+}
++at 0x000001d6 : */    0x72120000,0x00000000,
++/*
++    MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY
 +
++at 0x000001d8 : */    0x6f36ff00,0x00000000,
++/*
++    MOVE DSA3 TO SFBR
 +
++at 0x000001da : */    0x72130000,0x00000000,
 +/*
-+ * Wait until the interface can accept a char, then write it.
-+ */
-+static void kgdb_put_debug_char(u8 chr)
-+{
-+      static char ch[2];
++    MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY
 +
-+      ch[0] = (char)chr;
-+      cpm_uart_early_write(KGDB_PINFO_INDEX, ch, 1);
-+}
++at 0x000001dc : */    0x6f37ff00,0x00000000,
++/*
 +
++    
++    MOVE MEMORY 4, addr_scratch, reselected_check + 4
 +
++at 0x000001de : */    0xc0000004,0x00000000,0x00000794,
 +/*
-+ * Get a char if available, return -1 if nothing available.
-+ * Empty the receive buffer first, then look at the interface hardware.
-+ */
-+static int kgdb_get_debug_char(void)
-+{
-+      if (kgdb_chars <= 0) {
-+              kgdb_chars = kgdb_wait_key(kgdb_buf);
-+              kgdbp = kgdb_buf;
-+      }
-+      kgdb_chars--;
++    
 +
-+      return (*kgdbp++);
-+}
++    ; Time to correct DSA following memory move
++    MOVE MEMORY 4, saved_dsa, addr_dsa
 +
-+static void termios_set_options(int index,
-+               int baud, int parity, int bits, int flow)
-+{
-+      struct ktermios termios;
-+      struct uart_port *port;
-+      struct uart_cpm_port *pinfo;
++at 0x000001e1 : */    0xc0000004,0x00000000,0x00000000,
++/*
 +
-+      BUG_ON(index>UART_NR);
++reselected_check:
++    JUMP 0
 +
-+      port  = (struct uart_port *)&cpm_uart_ports[index];
-+      pinfo = (struct uart_cpm_port *)port;
++at 0x000001e4 : */    0x80080000,0x00000000,
++/*
 +
-+      /*
-+       * Ensure that the serial console lock is initialised
-+       * early.
-+       */
-+      spin_lock_init(&port->lock);
 +
-+      memset(&termios, 0, sizeof(struct termios));
++;
++;
 +
-+      termios.c_cflag = CREAD | HUPCL | CLOCAL;
++; We have problems here - the memory move corrupts TEMP and DSA.  This
++; routine is called from DSA code, and patched from many places.  Scratch
++; is probably free when it is called.
++; We have to:
++;   copy temp to scratch, one byte at a time
++;   write scratch to patch a jump in place of the return
++;   do the move memory
++;   jump to the patched in return address
++; DSA is corrupt when we get here, and can be left corrupt
 +
-+      termios.c_cflag |= baud;
++ENTRY reselected_ok
++reselected_ok:
++    MOVE TEMP0 TO SFBR
 +
-+      if (bits == 7)
-+              termios.c_cflag |= CS7;
-+      else
-+              termios.c_cflag |= CS8;
-+
-+      switch (parity) {
-+      case 'o': case 'O':
-+              termios.c_cflag |= PARODD;
-+              /*fall through*/
-+      case 'e': case 'E':
-+              termios.c_cflag |= PARENB;
-+              break;
-+      }
++at 0x000001e6 : */    0x721c0000,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH0
 +
-+      if (flow == 'r')
-+              termios.c_cflag |= CRTSCTS;
++at 0x000001e8 : */    0x6a340000,0x00000000,
++/*
++    MOVE TEMP1 TO SFBR
 +
-+      port->ops->set_termios(port, &termios, NULL);
-+}
++at 0x000001ea : */    0x721d0000,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH1
 +
++at 0x000001ec : */    0x6a350000,0x00000000,
 +/*
-+ *  Returns:
-+ *    0 on success, 1 on failure.
-+ */
-+static int kgdb_init(void)
-+{
-+      struct uart_port *port;
-+      struct uart_cpm_port *pinfo;
-+      int use_bootmem = 0; /* use dma by default */
++    MOVE TEMP2 TO SFBR
 +
-+      if (!cpm_uart_nr) {
-+              use_bootmem = 1;
-+              cpm_uart_init_portdesc();
-+      }
-+      port  = (struct uart_port *)&cpm_uart_ports[KGDB_PINFO_INDEX];
-+      pinfo = (struct uart_cpm_port *)port;
++at 0x000001ee : */    0x721e0000,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH2
 +
-+      if (cpm_uart_early_setup(KGDB_PINFO_INDEX, use_bootmem))
-+              return 1;
++at 0x000001f0 : */    0x6a360000,0x00000000,
++/*
++    MOVE TEMP3 TO SFBR
 +
-+      termios_set_options(KGDB_PINFO_INDEX, KGDB_BAUD,'n',8,'n');
-+        if (IS_SMC(pinfo))
-+                pinfo->smcp->smc_smcm |= SMCM_TX;
-+        else
-+                pinfo->sccp->scc_sccm |= UART_SCCM_TX;
++at 0x000001f2 : */    0x721f0000,0x00000000,
++/*
++    MOVE SFBR TO SCRATCH3
 +
-+      return 0;
-+}
++at 0x000001f4 : */    0x6a370000,0x00000000,
++/*
++    MOVE MEMORY 4, addr_scratch, reselected_ok_jump + 4
 +
++at 0x000001f6 : */    0xc0000004,0x00000000,0x000007f4,
++/*
++reselected_ok_patch:
++    MOVE MEMORY 4, 0, 0
 +
-+struct kgdb_io kgdb_io_ops = {
-+      .read_char  = kgdb_get_debug_char,
-+      .write_char = kgdb_put_debug_char,
-+      .init = kgdb_init,
-+};
++at 0x000001f9 : */    0xc0000004,0x00000000,0x00000000,
++/*
++reselected_ok_jump:
++    JUMP 0
 +
-diff -Nurb linux-2.6.22-570/drivers/serial/mpsc_kgdb.c linux-2.6.22-590/drivers/serial/mpsc_kgdb.c
---- linux-2.6.22-570/drivers/serial/mpsc_kgdb.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/serial/mpsc_kgdb.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,345 @@
++at 0x000001fc : */    0x80080000,0x00000000,
 +/*
-+ * drivers/serial/mpsc_kgdb.c
-+ *
-+ * KGDB driver for the Marvell MultiProtocol Serial Controller (MPCS)
-+ *
-+ * Based on the polled boot loader driver by Ajit Prem (ajit.prem@motorola.com)
-+ *
-+ * Author: Randy Vinson <rvinson@mvista.com>
-+ *
-+ * Copyright (C) 2005-2006 MontaVista Software, 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.
-+ */
 +
-+#include <linux/kgdb.h>
-+#include <linux/mv643xx.h>
-+#include <linux/device.h>
-+#include <asm/mv64x60.h>
-+#include <asm/serial.h>
-+#include <asm/io.h>
-+#include <asm/delay.h>
-+
-+/* Main MPSC Configuration Register Offsets */
-+#define MPSC_MMCRL            0x0000
-+#define MPSC_MMCRH            0x0004
-+#define MPSC_MPCR             0x0008
-+#define MPSC_CHR_1            0x000c
-+#define MPSC_CHR_2            0x0010
-+#define MPSC_CHR_3            0x0014
-+#define MPSC_CHR_4            0x0018
-+#define MPSC_CHR_5            0x001c
-+#define MPSC_CHR_6            0x0020
-+#define MPSC_CHR_7            0x0024
-+#define MPSC_CHR_8            0x0028
-+#define MPSC_CHR_9            0x002c
-+#define MPSC_CHR_10           0x0030
-+#define MPSC_CHR_11           0x0034
-+
-+#define MPSC_MPCR_FRZ         (1 << 9)
-+#define MPSC_MPCR_CL_5                0
-+#define MPSC_MPCR_CL_6                1
-+#define MPSC_MPCR_CL_7                2
-+#define MPSC_MPCR_CL_8                3
-+#define MPSC_MPCR_SBL_1       0
-+#define MPSC_MPCR_SBL_2       1
-+
-+#define MPSC_CHR_2_TEV                (1<<1)
-+#define MPSC_CHR_2_TA         (1<<7)
-+#define MPSC_CHR_2_TTCS               (1<<9)
-+#define MPSC_CHR_2_REV                (1<<17)
-+#define MPSC_CHR_2_RA         (1<<23)
-+#define MPSC_CHR_2_CRD                (1<<25)
-+#define MPSC_CHR_2_EH         (1<<31)
-+#define MPSC_CHR_2_PAR_ODD    0
-+#define MPSC_CHR_2_PAR_SPACE  1
-+#define MPSC_CHR_2_PAR_EVEN   2
-+#define MPSC_CHR_2_PAR_MARK   3
-+
-+/* MPSC Signal Routing */
-+#define MPSC_MRR              0x0000
-+#define MPSC_RCRR             0x0004
-+#define MPSC_TCRR             0x0008
-+
-+/* MPSC Interrupt registers (offset from MV64x60_SDMA_INTR_OFFSET) */
-+#define MPSC_INTR_CAUSE       0x0004
-+#define MPSC_INTR_MASK                0x0084
-+#define MPSC_INTR_CAUSE_RCC   (1<<6)
-+
-+/* Baud Rate Generator Interface Registers */
-+#define BRG_BCR               0x0000
-+#define BRG_BTR               0x0004
-+
-+/* Speed of the UART. */
-+static int kgdbmpsc_baud = CONFIG_KGDB_BAUDRATE;
-+
-+/* Index of the UART, matches ttyMX naming. */
-+static int kgdbmpsc_ttyMM = CONFIG_KGDB_PORT_NUM;
-+
-+#define MPSC_INTR_REG_SELECT(x)       ((x) + (8 * kgdbmpsc_ttyMM))
-+
-+static int kgdbmpsc_init(void);
-+
-+static struct platform_device mpsc_dev, shared_dev;
-+
-+static void __iomem *mpsc_base;
-+static void __iomem *brg_base;
-+static void __iomem *routing_base;
-+static void __iomem *sdma_base;
-+
-+static unsigned int mpsc_irq;
-+
-+static void kgdb_write_debug_char(u8 c)
-+{
-+      u32 data;
-+
-+      data = readl(mpsc_base + MPSC_MPCR);
-+      writeb(c, mpsc_base + MPSC_CHR_1);
-+      mb();
-+      data = readl(mpsc_base + MPSC_CHR_2);
-+      data |= MPSC_CHR_2_TTCS;
-+      writel(data, mpsc_base + MPSC_CHR_2);
-+      mb();
 +
-+      while (readl(mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS) ;
-+}
 +
-+static int kgdb_get_debug_char(void)
-+{
-+      unsigned char c;
 +
-+      while (!(readl(sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE)) &
-+               MPSC_INTR_CAUSE_RCC)) ;
 +
-+      c = readb(mpsc_base + MPSC_CHR_10 + (1 << 1));
-+      mb();
-+      writeb(c, mpsc_base + MPSC_CHR_10 + (1 << 1));
-+      mb();
-+      writel(~MPSC_INTR_CAUSE_RCC, sdma_base +
-+             MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE));
-+      return (c);
-+}
++selected:
++    INT int_err_selected;
 +
++at 0x000001fe : */    0x98080000,0x00010000,
 +/*
-+ * This is the receiver interrupt routine for the GDB stub.
-+ * All that we need to do is verify that the interrupt happened on the
-+ * line we're in charge of.  If this is true, schedule a breakpoint and
-+ * return.
-+ */
-+static irqreturn_t kgdbmpsc_interrupt(int irq, void *dev_id)
-+{
-+      if (irq != mpsc_irq)
-+              return IRQ_NONE;
-+      /*
-+       * If  there is some other CPU in KGDB then this is a
-+       * spurious interrupt. so return without even checking a byte
-+       */
-+      if (atomic_read(&debugger_active))
-+              return IRQ_NONE;
-+
-+      if (readl(sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE)) &
-+          MPSC_INTR_CAUSE_RCC)
-+              breakpoint();
 +
-+      return IRQ_HANDLED;
-+}
++;
++; A select or reselect failure can be caused by one of two conditions : 
++; 1.  SIG_P was set.  This will be the case if the user has written
++;     a new value to a previously NULL head of the issue queue.
++;
++; 2.  The NCR53c810 was selected or reselected by another device.
++;
++; 3.  The bus was already busy since we were selected or reselected
++;     before starting the command.
 +
-+static int __init kgdbmpsc_init(void)
-+{
-+      struct mpsc_pdata *pdata;
-+      u32 cdv;
++wait_reselect_failed:
 +
-+      if (!brg_base || !mpsc_base || !routing_base || !sdma_base)
-+              return -1;
 +
-+      /* Set MPSC Routing to enable both ports */
-+      writel(0x0, routing_base + MPSC_MRR);
 +
-+      /* MPSC 0/1 Rx & Tx get clocks BRG0/1 */
-+      writel(0x00000100, routing_base + MPSC_RCRR);
-+      writel(0x00000100, routing_base + MPSC_TCRR);
++; Check selected bit.  
 +
-+      /* Disable all MPSC interrupts and clear any pending interrupts */
-+      writel(0, sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_MASK));
-+      writel(0, sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE));
++    ; Must work out how to tell if we are selected....
 +
-+      pdata = (struct mpsc_pdata *)mpsc_dev.dev.platform_data;
 +
-+      /* cdv = (clock/(2*16*baud rate)) for 16X mode. */
-+      cdv = ((pdata->brg_clk_freq / (32 * kgdbmpsc_baud)) - 1);
-+      writel((pdata->brg_clk_src << 18) | (1 << 16) | cdv,
-+             brg_base + BRG_BCR);
 +
-+      /* Put MPSC into UART mode, no null modem, 16x clock mode */
-+      writel(0x000004c4, mpsc_base + MPSC_MMCRL);
-+      writel(0x04400400, mpsc_base + MPSC_MMCRH);
 +
-+      writel(0, mpsc_base + MPSC_CHR_1);
-+      writel(0, mpsc_base + MPSC_CHR_9);
-+      writel(0, mpsc_base + MPSC_CHR_10);
-+      writel(4, mpsc_base + MPSC_CHR_3);
-+      writel(0x20000000, mpsc_base + MPSC_CHR_4);
-+      writel(0x9000, mpsc_base + MPSC_CHR_5);
-+      writel(0, mpsc_base + MPSC_CHR_6);
-+      writel(0, mpsc_base + MPSC_CHR_7);
-+      writel(0, mpsc_base + MPSC_CHR_8);
++; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
++    MOVE CTEST2 & 0x40 TO SFBR        
 +
-+      /* 8 data bits, 1 stop bit */
-+      writel((3 << 12), mpsc_base + MPSC_MPCR);
++at 0x00000200 : */    0x74164000,0x00000000,
++/*
++    JUMP schedule, IF 0x40
 +
-+      /* Enter "hunt" mode */
-+      writel((1 << 31), mpsc_base + MPSC_CHR_2);
++at 0x00000202 : */    0x800c0040,0x00000000,
++/*
++; Check connected bit.  
++; FIXME: this needs to change if we support target mode
++    MOVE ISTAT & 0x08 TO SFBR
 +
-+      udelay(100);
-+      return 0;
-+}
++at 0x00000204 : */    0x74210800,0x00000000,
++/*
++    JUMP reselected, IF 0x08
 +
-+static void __iomem *__init
-+kgdbmpsc_map_resource(struct platform_device *pd, int type, int num)
-+{
-+      void __iomem *base = NULL;
-+      struct resource *r;
++at 0x00000206 : */    0x800c0008,0x000006b0,
++/*
++; FIXME : Something bogus happened, and we shouldn't fail silently.
 +
-+      if ((r = platform_get_resource(pd, IORESOURCE_MEM, num)))
-+              base = ioremap(r->start, r->end - r->start + 1);
-+      return base;
-+}
 +
-+static void __iomem *__init
-+kgdbmpsc_unmap_resource(struct platform_device *pd, int type, int num,
-+                      void __iomem * base)
-+{
-+      if (base)
-+              iounmap(base);
-+      return NULL;
-+}
 +
-+static void __init
-+kgdbmpsc_reserve_resource(struct platform_device *pd, int type, int num)
-+{
-+      struct resource *r;
++    INT int_debug_panic
 +
-+      if ((r = platform_get_resource(pd, IORESOURCE_MEM, num)))
-+              request_mem_region(r->start, r->end - r->start + 1, "kgdb");
-+}
++at 0x00000208 : */    0x98080000,0x030b0000,
++/*
 +
-+static int __init kgdbmpsc_local_init(void)
-+{
-+      if (!mpsc_dev.num_resources || !shared_dev.num_resources)
-+              return 1;       /* failure */
 +
-+      mpsc_base = kgdbmpsc_map_resource(&mpsc_dev, IORESOURCE_MEM,
-+                                        MPSC_BASE_ORDER);
-+      brg_base = kgdbmpsc_map_resource(&mpsc_dev, IORESOURCE_MEM,
-+                                       MPSC_BRG_BASE_ORDER);
 +
-+      /* get the platform data for the shared registers and get them mapped */
-+      routing_base = kgdbmpsc_map_resource(&shared_dev,
-+                                           IORESOURCE_MEM,
-+                                           MPSC_ROUTING_BASE_ORDER);
-+      sdma_base =
-+          kgdbmpsc_map_resource(&shared_dev, IORESOURCE_MEM,
-+                                MPSC_SDMA_INTR_BASE_ORDER);
++select_failed:
 +
-+      mpsc_irq = platform_get_irq(&mpsc_dev, 1);
++    ; Disable selection timer
++    MOVE CTEST7 | 0x10 TO CTEST7
 +
-+      if (mpsc_base && brg_base && routing_base && sdma_base)
-+              return 0;       /* success */
++at 0x0000020a : */    0x7a1b1000,0x00000000,
++/*
 +
-+      return 1;               /* failure */
-+}
 +
-+static void __init kgdbmpsc_local_exit(void)
-+{
-+      if (sdma_base)
-+              sdma_base = kgdbmpsc_unmap_resource(&shared_dev, IORESOURCE_MEM,
-+                                                  MPSC_SDMA_INTR_BASE_ORDER,
-+                                                  sdma_base);
-+      if (routing_base)
-+              routing_base = kgdbmpsc_unmap_resource(&shared_dev,
-+                                                     IORESOURCE_MEM,
-+                                                     MPSC_ROUTING_BASE_ORDER,
-+                                                     routing_base);
-+      if (brg_base)
-+              brg_base = kgdbmpsc_unmap_resource(&mpsc_dev, IORESOURCE_MEM,
-+                                                 MPSC_BRG_BASE_ORDER,
-+                                                 brg_base);
-+      if (mpsc_base)
-+              mpsc_base = kgdbmpsc_unmap_resource(&mpsc_dev, IORESOURCE_MEM,
-+                                                  MPSC_BASE_ORDER, mpsc_base);
-+}
 +
-+static void __init kgdbmpsc_update_pdata(struct platform_device *pdev)
-+{
 +
-+      snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id);
-+}
++; Otherwise, mask the selected and reselected bits off SIST0
 +
-+static int __init kgdbmpsc_pdev_init(void)
-+{
-+      struct platform_device *pdev;
++    ; Let's assume we don't get selected for now
++    MOVE SSTAT0 & 0x10 TO SFBR
 +
-+      /* get the platform data for the specified port. */
-+      pdev = mv64x60_early_get_pdev_data(MPSC_CTLR_NAME, kgdbmpsc_ttyMM, 1);
-+      if (pdev) {
-+              memcpy(&mpsc_dev, pdev, sizeof(struct platform_device));
-+              if (platform_notify) {
-+                      kgdbmpsc_update_pdata(&mpsc_dev);
-+                      platform_notify(&mpsc_dev.dev);
-+              }
++at 0x0000020c : */    0x740d1000,0x00000000,
++/*
 +
-+              /* get the platform data for the shared registers. */
-+              pdev = mv64x60_early_get_pdev_data(MPSC_SHARED_NAME, 0, 0);
-+              if (pdev) {
-+                      memcpy(&shared_dev, pdev,
-+                             sizeof(struct platform_device));
-+                      if (platform_notify) {
-+                              kgdbmpsc_update_pdata(&shared_dev);
-+                              platform_notify(&shared_dev.dev);
-+                      }
-+              }
-+      }
-+      return 0;
-+}
 +
-+postcore_initcall(kgdbmpsc_pdev_init);
 +
-+static int __init kgdbmpsc_init_io(void)
-+{
 +
-+      kgdbmpsc_pdev_init();
++    JUMP reselected, IF 0x10 
 +
-+      if (kgdbmpsc_local_init()) {
-+              kgdbmpsc_local_exit();
-+              return -1;
-+      }
++at 0x0000020e : */    0x800c0010,0x000006b0,
++/*
++; If SIGP is set, the user just gave us another command, and
++; we should restart or return to the scheduler.
++; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
++    MOVE CTEST2 & 0x40 TO SFBR        
 +
-+      if (kgdbmpsc_init() == -1)
-+              return -1;
-+      return 0;
-+}
++at 0x00000210 : */    0x74164000,0x00000000,
++/*
++    JUMP select, IF 0x40
 +
-+static void __init kgdbmpsc_hookup_irq(void)
-+{
-+      unsigned int msk;
-+      if (!request_irq(mpsc_irq, kgdbmpsc_interrupt, 0, "kgdb mpsc", NULL)) {
-+              /* Enable interrupt */
-+              msk = readl(sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_MASK));
-+              msk |= MPSC_INTR_CAUSE_RCC;
-+              writel(msk, sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_MASK));
++at 0x00000212 : */    0x800c0040,0x000001f8,
++/*
++; Check connected bit.  
++; FIXME: this needs to change if we support target mode
++; FIXME: is this really necessary? 
++    MOVE ISTAT & 0x08 TO SFBR
 +
-+              kgdbmpsc_reserve_resource(&mpsc_dev, IORESOURCE_MEM,
-+                                        MPSC_BASE_ORDER);
-+              kgdbmpsc_reserve_resource(&mpsc_dev, IORESOURCE_MEM,
-+                                        MPSC_BRG_BASE_ORDER);
-+      }
-+}
++at 0x00000214 : */    0x74210800,0x00000000,
++/*
++    JUMP reselected, IF 0x08
 +
-+struct kgdb_io kgdb_io_ops = {
-+      .read_char = kgdb_get_debug_char,
-+      .write_char = kgdb_write_debug_char,
-+      .init = kgdbmpsc_init_io,
-+      .late_init = kgdbmpsc_hookup_irq,
-+};
-diff -Nurb linux-2.6.22-570/drivers/serial/pl011_kgdb.c linux-2.6.22-590/drivers/serial/pl011_kgdb.c
---- linux-2.6.22-570/drivers/serial/pl011_kgdb.c       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/serial/pl011_kgdb.c       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,111 @@
++at 0x00000216 : */    0x800c0008,0x000006b0,
 +/*
-+ * driver/serial/pl011_kgdb.c
-+ *
-+ * Support for KGDB on ARM AMBA PL011 UARTs
-+ *
-+ * Authors: Manish Lachwani <mlachwani@mvista.com>
-+ *          Deepak Saxena <dsaxena@plexity.net>
-+ *
-+ * Copyright (c) 2005-2007 MontaVista Software, Inc.
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program is licensed "as is" without any warranty of any
-+ * kind, whether expressor implied.
-+ *
-+ */
-+#include <linux/kgdb.h>
-+#include <linux/amba/bus.h>
-+#include <linux/amba/serial.h>
++; FIXME : Something bogus happened, and we shouldn't fail silently.
 +
-+#include <asm/io.h>
-+#include <asm/processor.h>
-+#include <asm/hardware.h>
 +
-+static int kgdb_irq = CONFIG_KGDB_AMBA_IRQ;
 +
-+#define UART_DIVISOR  (CONFIG_KGDB_AMBA_UARTCLK * 4 / CONFIG_KGDB_BAUDRATE)
-+/*
-+ * Todo: IO_ADDRESS is not very generic across ARM...
-+ */
-+static volatile unsigned char *kgdb_port =
-+      (unsigned char*)IO_ADDRESS(CONFIG_KGDB_AMBA_BASE);
++    INT int_debug_panic
 +
++at 0x00000218 : */    0x98080000,0x030b0000,
 +/*
-+ * Init code taken from amba-pl011.c.
-+ */
-+static int kgdb_serial_init(void)
-+{
-+      writew(0, kgdb_port + UART010_CR);
 +
-+      /* Set baud rate */
-+      writew(UART_DIVISOR & 0x3f, kgdb_port + UART011_FBRD);
-+      writew(UART_DIVISOR >> 6, kgdb_port + UART011_IBRD);
 +
-+      writew(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, kgdb_port + UART010_LCRH);
-+      writew(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE,
-+             kgdb_port + UART010_CR);
++;
++; test_1
++; test_2
++;
++; PURPOSE : run some verification tests on the NCR.  test_1
++;     copies test_src to test_dest and interrupts the host
++;     processor, testing for cache coherency and interrupt
++;     problems in the processes.
++;
++;     test_2 runs a command with offsets relative to the 
++;     DSA on entry, and is useful for miscellaneous experimentation.
++;
++
++; Verify that interrupts are working correctly and that we don't 
++; have a cache invalidation problem.
++
++ABSOLUTE test_src = 0, test_dest = 0
++ENTRY test_1
++test_1:
++    MOVE MEMORY 4, test_src, test_dest
++
++at 0x0000021a : */    0xc0000004,0x00000000,0x00000000,
++/*
++    INT int_test_1
 +
-+      writew(UART011_RXIM, kgdb_port + UART011_IMSC);
++at 0x0000021d : */    0x98080000,0x04000000,
++/*
 +
-+      return 0;
-+}
++;
++; Run arbitrary commands, with test code establishing a DSA
++;
++ 
++ENTRY test_2
++test_2:
++    CLEAR TARGET
 +
-+static void kgdb_serial_putchar(u8 ch)
-+{
-+      unsigned int status;
++at 0x0000021f : */    0x60000200,0x00000000,
++/*
 +
-+      do {
-+              status = readw(kgdb_port + UART01x_FR);
-+      } while (status & UART01x_FR_TXFF);
++    ; Enable selection timer
 +
-+      writew(ch, kgdb_port + UART01x_DR);
-+}
 +
-+static int kgdb_serial_getchar(void)
-+{
-+      unsigned int status;
-+      int ch;
 +
-+#ifdef CONFIG_DEBUG_LL
-+      printascii("Entering serial_getchar loop");
-+#endif
-+      do {
-+              status = readw(kgdb_port + UART01x_FR);
-+      } while (status & UART01x_FR_RXFE);
-+      ch = readw(kgdb_port + UART01x_DR);
-+#ifdef CONFIG_DEBUG_LL
-+      printascii("Exited serial_getchar loop");
-+      printascii("Read char: ");
-+      printch(ch);
-+      printascii("\n");
-+#endif
-+      return ch;
-+}
++    MOVE CTEST7 & 0xef TO CTEST7
 +
-+static irqreturn_t kgdb_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+      int status = readw(kgdb_port + UART011_MIS);
++at 0x00000221 : */    0x7c1bef00,0x00000000,
++/*
 +
-+#ifdef CONFIG_DEBUG_LL
-+      printascii("KGDB irq\n");
-+#endif
-+      if (irq != kgdb_irq)
-+              return IRQ_NONE;
 +
-+      if (status & 0x40)
-+              breakpoint();
++    SELECT ATN FROM 0, test_2_fail
 +
-+      return IRQ_HANDLED;
-+}
++at 0x00000223 : */    0x43000000,0x000008dc,
++/*
++    JUMP test_2_msgout, WHEN MSG_OUT
 +
-+static void __init kgdb_hookup_irq(void)
-+{
-+      request_irq(kgdb_irq, kgdb_interrupt, SA_SHIRQ, "KGDB-serial", kgdb_port);
-+}
++at 0x00000225 : */    0x860b0000,0x0000089c,
++/*
++ENTRY test_2_msgout
++test_2_msgout:
 +
-+struct kgdb_io kgdb_io_ops = {
-+      .init = kgdb_serial_init,
-+      .write_char = kgdb_serial_putchar,
-+      .read_char  = kgdb_serial_getchar,
-+      .late_init  = kgdb_hookup_irq,
-+};
-diff -Nurb linux-2.6.22-570/drivers/serial/pxa.c linux-2.6.22-590/drivers/serial/pxa.c
---- linux-2.6.22-570/drivers/serial/pxa.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/serial/pxa.c      2008-01-02 13:56:37.000000000 -0500
-@@ -42,6 +42,9 @@
- #include <linux/tty.h>
- #include <linux/tty_flip.h>
- #include <linux/serial_core.h>
-+#ifdef CONFIG_KGDB_CONSOLE
-+#include <linux/kgdb.h>
-+#endif
- #include <asm/io.h>
- #include <asm/hardware.h>
-@@ -690,6 +693,8 @@
- console_initcall(serial_pxa_console_init);
- #define PXA_CONSOLE   &serial_pxa_console
-+#elif defined(CONFIG_KGDB_CONSOLE)
-+#define PXA_CONSOLE   &kgdbcons
- #else
- #define PXA_CONSOLE   NULL
- #endif
-diff -Nurb linux-2.6.22-570/drivers/serial/serial_core.c linux-2.6.22-590/drivers/serial/serial_core.c
---- linux-2.6.22-570/drivers/serial/serial_core.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/serial/serial_core.c      2008-01-02 13:56:37.000000000 -0500
-@@ -33,6 +33,7 @@
- #include <linux/serial.h> /* for serial_state and serial_icounter_struct */
- #include <linux/delay.h>
- #include <linux/mutex.h>
-+#include <linux/kgdb.h>
- #include <asm/irq.h>
- #include <asm/uaccess.h>
-@@ -58,6 +59,12 @@
- #define uart_console(port)    (0)
- #endif
-+#ifdef CONFIG_KGDB_CONSOLE
-+#define uart_kgdb(port)               (port->cons && !strcmp(port->cons->name, "kgdb"))
-+#else
-+#define uart_kgdb(port)               (0)
-+#endif
++    ; Disable selection timer
++    MOVE CTEST7 | 0x10 TO CTEST7
 +
- static void uart_change_speed(struct uart_state *state, struct ktermios *old_termios);
- static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
- static void uart_change_pm(struct uart_state *state, int pm_state);
-@@ -1671,6 +1678,9 @@
-                       mmio ? "mmio:0x" : "port:",
-                       mmio ? port->mapbase : (unsigned long) port->iobase,
-                       port->irq);
-+      if (port->iotype == UPIO_MEM)
-+              ret += sprintf(buf+ret, " membase 0x%08lX",
-+                                         (unsigned long) port->membase);
-       if (port->type == PORT_UNKNOWN) {
-               strcat(buf, "\n");
-@@ -2063,7 +2073,8 @@
-       case UPIO_TSI:
-       case UPIO_DWAPB:
-               snprintf(address, sizeof(address),
--                       "MMIO 0x%lx", port->mapbase);
-+                      "MMIO map 0x%lx mem 0x%lx", port->mapbase,
-+                      (unsigned long) port->membase);
-               break;
-       default:
-               strlcpy(address, "*unknown*", sizeof(address));
-@@ -2118,9 +2129,9 @@
-               /*
-                * Power down all ports by default, except the
--               * console if we have one.
-+               * console (real or kgdb) if we have one.
-                */
--              if (!uart_console(port))
-+              if (!uart_console(port) && !uart_kgdb(port))
-                       uart_change_pm(state, 3);
-       }
- }
-@@ -2311,6 +2322,12 @@
-        */
-       port->flags &= ~UPF_DEAD;
-+#if defined(CONFIG_KGDB_8250)
-+      /* Add any 8250-like ports we find later. */
-+      if (port->type <= PORT_MAX_8250)
-+              kgdb8250_add_port(port->line, port);
-+#endif
++at 0x00000227 : */    0x7a1b1000,0x00000000,
++/*
 +
-  out:
-       mutex_unlock(&state->mutex);
-       mutex_unlock(&port_mutex);
-diff -Nurb linux-2.6.22-570/drivers/serial/serial_txx9.c linux-2.6.22-590/drivers/serial/serial_txx9.c
---- linux-2.6.22-570/drivers/serial/serial_txx9.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/serial/serial_txx9.c      2008-01-02 13:56:37.000000000 -0500
-@@ -40,6 +40,10 @@
- static char *serial_version = "1.09";
- static char *serial_name = "TX39/49 Serial driver";
-+#ifndef CONFIG_KGDB_TXX9
-+#define CONFIG_KGDB_PORT_NUM -1
-+#endif
++    MOVE FROM 8, WHEN MSG_OUT
 +
- #define PASS_LIMIT    256
- #if !defined(CONFIG_SERIAL_TXX9_STDSERIAL)
-@@ -471,6 +475,9 @@
-       unsigned long flags;
-       int retval;
-+      if (up->port.line == CONFIG_KGDB_PORT_NUM)
-+              return -EBUSY;
++at 0x00000229 : */    0x1e000000,0x00000008,
++/*
++    MOVE FROM 16, WHEN CMD 
 +
-       /*
-        * Clear the FIFO buffers and disable them.
-        * (they will be reenabled in set_termios())
-@@ -799,6 +806,9 @@
-       for (i = 0; i < UART_NR; i++) {
-               struct uart_txx9_port *up = &serial_txx9_ports[i];
-+              if (up->port.line == CONFIG_KGDB_PORT_NUM)
-+                      continue;
++at 0x0000022b : */    0x1a000000,0x00000010,
++/*
++    MOVE FROM 24, WHEN DATA_IN
 +
-               up->port.line = i;
-               up->port.ops = &serial_txx9_pops;
-               up->port.dev = dev;
-@@ -967,6 +977,9 @@
-       mutex_lock(&serial_txx9_mutex);
-       for (i = 0; i < UART_NR; i++) {
-+              if (i == CONFIG_KGDB_PORT_NUM)
-+                      continue;
++at 0x0000022d : */    0x19000000,0x00000018,
++/*
++    MOVE FROM 32, WHEN STATUS
 +
-               uart = &serial_txx9_ports[i];
-               if (uart_match_port(&uart->port, port)) {
-                       uart_remove_one_port(&serial_txx9_reg, &uart->port);
-diff -Nurb linux-2.6.22-570/drivers/serial/serial_txx9_kgdb.c linux-2.6.22-590/drivers/serial/serial_txx9_kgdb.c
---- linux-2.6.22-570/drivers/serial/serial_txx9_kgdb.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/drivers/serial/serial_txx9_kgdb.c 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,150 @@
++at 0x0000022f : */    0x1b000000,0x00000020,
 +/*
-+ * drivers/serial/serial_txx9_kgdb.c
-+ *
-+ * kgdb interface for gdb
-+ *
-+ * Author: MontaVista Software, Inc.
-+ *         source@mvista.com
-+ *
-+ * Copyright (C) 2005-2006 MontaVista Software 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.
-+ */
++    MOVE FROM 40, WHEN MSG_IN
 +
-+#include <linux/delay.h>
-+#include <linux/init.h>
-+#include <linux/kgdb.h>
-+#include <asm/io.h>
++at 0x00000231 : */    0x1f000000,0x00000028,
++/*
 +
-+/* Speed of the UART. */
-+static unsigned int kgdb_txx9_baud = CONFIG_KGDB_BAUDRATE;
 +
-+#define TXX9_NPORT 4          /* TX4939 has 4 UARTs, others only have 2 */
 +
-+static struct uart_port  kgdb_txx9_ports[TXX9_NPORT];
-+static struct uart_port *kgdb_port;
++    CLEAR ACK
 +
-+/* TXX9 Serial Registers */
-+#define TXX9_SILCR    0x00
-+#define TXX9_SIDISR   0x08
-+#define TXX9_SISCISR  0x0c
-+#define TXX9_SIFCR    0x10
-+#define TXX9_SIFLCR   0x14
-+#define TXX9_SIBGR    0x18
-+#define TXX9_SITFIFO  0x1c
-+#define TXX9_SIRFIFO  0x20
++at 0x00000233 : */    0x60000040,0x00000000,
++/*
++    WAIT DISCONNECT
 +
-+/* SILCR : Line Control */
-+#define TXX9_SILCR_SCS_IMCLK_BG       0x00000020
-+#define TXX9_SILCR_SCS_SCLK_BG        0x00000060
-+#define TXX9_SILCR_USBL_1BIT  0x00000000
-+#define TXX9_SILCR_UMODE_8BIT 0x00000000
++at 0x00000235 : */    0x48000000,0x00000000,
++/*
++test_2_fail:
 +
-+/* SIDISR : DMA/Int. Status */
-+#define TXX9_SIDISR_RFDN_MASK 0x0000001f
++    ; Disable selection timer
++    MOVE CTEST7 | 0x10 TO CTEST7
 +
-+/* SISCISR : Status Change Int. Status */
-+#define TXX9_SISCISR_TRDY     0x00000004
++at 0x00000237 : */    0x7a1b1000,0x00000000,
++/*
 +
-+/* SIFCR : FIFO Control */
-+#define TXX9_SIFCR_SWRST      0x00008000
++    INT int_test_2
 +
-+/* SIBGR : Baud Rate Control */
-+#define TXX9_SIBGR_BCLK_T0    0x00000000
-+#define TXX9_SIBGR_BCLK_T2    0x00000100
-+#define TXX9_SIBGR_BCLK_T4    0x00000200
-+#define TXX9_SIBGR_BCLK_T6    0x00000300
++at 0x00000239 : */    0x98080000,0x04010000,
++/*
 +
-+static inline unsigned int sio_in(struct uart_port *port, int offset)
-+{
-+      return *(volatile u32 *)(port->membase + offset);
-+}
++ENTRY debug_break
++debug_break:
++    INT int_debug_break
 +
-+static inline void sio_out(struct uart_port *port, int offset, unsigned int value)
-+{
-+      *(volatile u32 *)(port->membase + offset) = value;
-+}
++at 0x0000023b : */    0x98080000,0x03000000,
++/*
 +
-+void __init txx9_kgdb_add_port(int n, struct uart_port *port)
-+{
-+      memcpy(&kgdb_txx9_ports[n], port, sizeof(struct uart_port));
-+}
++;
++; initiator_abort
++; target_abort
++;
++; PURPOSE : Abort the currently established nexus from with initiator
++;     or target mode.
++;
++;  
 +
-+static int txx9_kgdb_init(void)
-+{
-+      unsigned int quot, sibgr;
++ENTRY target_abort
++target_abort:
++    SET TARGET
 +
-+      kgdb_port = &kgdb_txx9_ports[CONFIG_KGDB_PORT_NUM];
++at 0x0000023d : */    0x58000200,0x00000000,
++/*
++    DISCONNECT
 +
-+      if (kgdb_port->iotype != UPIO_MEM &&
-+          kgdb_port->iotype != UPIO_MEM32)
-+              return -1;
++at 0x0000023f : */    0x48000000,0x00000000,
++/*
++    CLEAR TARGET
 +
-+      /* Reset the UART. */
-+      sio_out(kgdb_port, TXX9_SIFCR, TXX9_SIFCR_SWRST);
-+#ifdef CONFIG_CPU_TX49XX
-+      /*
-+       * TX4925 BUG WORKAROUND.  Accessing SIOC register
-+       * immediately after soft reset causes bus error.
-+       */
-+      iob();
-+      udelay(1);
-+#endif
-+      /* Wait until reset is complete. */
-+      while (sio_in(kgdb_port, TXX9_SIFCR) & TXX9_SIFCR_SWRST);
-+
-+      /* Select the frame format and input clock. */
-+      sio_out(kgdb_port, TXX9_SILCR,
-+              TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
-+              ((kgdb_port->flags & UPF_MAGIC_MULTIPLIER) ?
-+              TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
-+
-+      /* Select the input clock prescaler that fits the baud rate. */
-+      quot = (kgdb_port->uartclk + 8 * kgdb_txx9_baud) / (16 * kgdb_txx9_baud);
-+      if (quot < (256 << 1))
-+              sibgr = (quot >> 1) | TXX9_SIBGR_BCLK_T0;
-+      else if (quot < ( 256 << 3))
-+              sibgr = (quot >> 3) | TXX9_SIBGR_BCLK_T2;
-+      else if (quot < ( 256 << 5))
-+              sibgr = (quot >> 5) | TXX9_SIBGR_BCLK_T4;
-+      else if (quot < ( 256 << 7))
-+              sibgr = (quot >> 7) | TXX9_SIBGR_BCLK_T6;
-+      else
-+              sibgr = 0xff | TXX9_SIBGR_BCLK_T6;
++at 0x00000241 : */    0x60000200,0x00000000,
++/*
++    JUMP schedule
 +
-+      sio_out(kgdb_port, TXX9_SIBGR, sibgr);
++at 0x00000243 : */    0x80080000,0x00000000,
++/*
++    
++ENTRY initiator_abort
++initiator_abort:
++    SET ATN
 +
-+      /* Enable receiver and transmitter. */
-+      sio_out(kgdb_port, TXX9_SIFLCR, 0);
++at 0x00000245 : */    0x58000008,0x00000000,
++/*
++;
++; The SCSI-I specification says that targets may go into MSG out at 
++; their leisure upon receipt of the ATN single.  On all versions of the 
++; specification, we can't change phases until REQ transitions true->false, 
++; so we need to sink/source one byte of data to allow the transition.
++;
++; For the sake of safety, we'll only source one byte of data in all 
++; cases, but to accommodate the SCSI-I dain bramage, we'll sink an  
++; arbitrary number of bytes.
++    JUMP spew_cmd, WHEN CMD
++
++at 0x00000247 : */    0x820b0000,0x0000094c,
++/*
++    JUMP eat_msgin, WHEN MSG_IN
 +
-+      return 0;
-+}
++at 0x00000249 : */    0x870b0000,0x0000095c,
++/*
++    JUMP eat_datain, WHEN DATA_IN
 +
-+static void txx9_kgdb_late_init(void)
-+{
-+      request_mem_region(kgdb_port->mapbase, 0x40, "serial_txx9(debug)");
-+}
++at 0x0000024b : */    0x810b0000,0x0000098c,
++/*
++    JUMP eat_status, WHEN STATUS
 +
-+static int txx9_kgdb_read(void)
-+{
-+      while (!(sio_in(kgdb_port, TXX9_SIDISR) & TXX9_SIDISR_RFDN_MASK));
++at 0x0000024d : */    0x830b0000,0x00000974,
++/*
++    JUMP spew_dataout, WHEN DATA_OUT
 +
-+      return sio_in(kgdb_port, TXX9_SIRFIFO);
-+}
++at 0x0000024f : */    0x800b0000,0x000009a4,
++/*
++    JUMP sated
 +
-+static void txx9_kgdb_write(u8 ch)
-+{
-+      while (!(sio_in(kgdb_port, TXX9_SISCISR) & TXX9_SISCISR_TRDY));
++at 0x00000251 : */    0x80080000,0x000009ac,
++/*
++spew_cmd:
++    MOVE 1, NCR53c7xx_zero, WHEN CMD
 +
-+      sio_out(kgdb_port, TXX9_SITFIFO, ch);
-+}
++at 0x00000253 : */    0x0a000001,0x00000000,
++/*
++    JUMP sated
 +
-+struct kgdb_io kgdb_io_ops = {
-+      .read_char      = txx9_kgdb_read,
-+      .write_char     = txx9_kgdb_write,
-+      .init           = txx9_kgdb_init,
-+      .late_init      = txx9_kgdb_late_init
-+};
-diff -Nurb linux-2.6.22-570/drivers/serial/sh-sci.c linux-2.6.22-590/drivers/serial/sh-sci.c
---- linux-2.6.22-570/drivers/serial/sh-sci.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/serial/sh-sci.c   2008-01-02 13:56:37.000000000 -0500
-@@ -118,7 +118,8 @@
-       do {
-               status = sci_in(port, SCxSR);
-               if (status & SCxSR_ERRORS(port)) {
--                      handle_error(port);
-+                      /* Clear error flags. */
-+                      sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
-                       continue;
-               }
-       } while (!(status & SCxSR_RDxF(port)));
-@@ -184,18 +185,18 @@
-                       int h, l;
-                       c = *p++;
--                      h = highhex(c);
--                      l = lowhex(c);
-+                      h = hexchars[c >> 4];
-+                      l = hexchars[c % 16];
-                       put_char(port, h);
-                       put_char(port, l);
-                       checksum += h + l;
-               }
-               put_char(port, '#');
--              put_char(port, highhex(checksum));
--              put_char(port, lowhex(checksum));
-+              put_char(port, hexchars[checksum >> 4]);
-+              put_char(port, hexchars[checksum & 16]);
-           } while  (get_char(port) != '+');
-       } else
--#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
-+#endif /* CONFIG_SH_STANDARD_BIOS */
-       for (i=0; i<count; i++) {
-               if (*p == 10)
-                       put_char(port, '\r');
-@@ -547,6 +548,16 @@
-                                       continue;
-                               }
-+#ifdef CONFIG_KGDB_SH_SCI
-+                              /* We assume that a ^C on the port KGDB
-+                               * is using means that KGDB wants to
-+                               * interrupt the running system.
-+                               */
-+                              if (port->line == KGDBPORT.port.line &&
-+                                              c == 3)
-+                                      breakpoint();
-+#endif
++at 0x00000255 : */    0x80080000,0x000009ac,
++/*
++eat_msgin:
++    MOVE 1, NCR53c7xx_sink, WHEN MSG_IN
 +
-                               /* Store data and status */
-                               if (status&SCxSR_FER(port)) {
-                                       flag = TTY_FRAME;
-@@ -1279,6 +1290,7 @@
- console_initcall(sci_console_init);
- #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
-+#if 0
- #ifdef CONFIG_SH_KGDB
- /*
-  * FIXME: Most of this can go away.. at the moment, we rely on
-diff -Nurb linux-2.6.22-570/drivers/spi/at25.c linux-2.6.22-590/drivers/spi/at25.c
---- linux-2.6.22-570/drivers/spi/at25.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/spi/at25.c        2008-01-02 13:56:37.000000000 -0500
-@@ -111,7 +111,8 @@
- }
- static ssize_t
--at25_bin_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr,
-+            char *buf, loff_t off, size_t count)
- {
-       struct device           *dev;
-       struct at25_data        *at25;
-@@ -236,7 +237,8 @@
- }
- static ssize_t
--at25_bin_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr,
-+             char *buf, loff_t off, size_t count)
- {
-       struct device           *dev;
-       struct at25_data        *at25;
-@@ -314,7 +316,6 @@
-        */
-       at25->bin.attr.name = "eeprom";
-       at25->bin.attr.mode = S_IRUSR;
--      at25->bin.attr.owner = THIS_MODULE;
-       at25->bin.read = at25_bin_read;
-       at25->bin.size = at25->chip.byte_len;
-diff -Nurb linux-2.6.22-570/drivers/usb/atm/cxacru.c linux-2.6.22-590/drivers/usb/atm/cxacru.c
---- linux-2.6.22-570/drivers/usb/atm/cxacru.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/usb/atm/cxacru.c  2008-01-02 13:56:37.000000000 -0500
-@@ -171,7 +171,7 @@
-       struct delayed_work poll_work;
-       u32 card_info[CXINF_MAX];
-       struct mutex poll_state_serialize;
--      int poll_state;
-+      enum cxacru_poll_state poll_state;
-       /* contol handles */
-       struct mutex cm_serialize;
-@@ -226,58 +226,48 @@
- static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf)
- {
--      if (unlikely(value < 0)) {
-               return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
--                                              value / 100, -value % 100);
--      } else {
--              return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
--                                              value / 100, value % 100);
--      }
-+                                      value / 100, abs(value) % 100);
- }
- static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
- {
--      switch (value) {
--      case 0: return snprintf(buf, PAGE_SIZE, "no\n");
--      case 1: return snprintf(buf, PAGE_SIZE, "yes\n");
--      default: return 0;
--      }
-+      static char *str[] = { "no", "yes" };
-+      if (unlikely(value >= ARRAY_SIZE(str)))
-+              return snprintf(buf, PAGE_SIZE, "%u\n", value);
-+      return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
- }
- static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf)
- {
--      switch (value) {
--      case 1: return snprintf(buf, PAGE_SIZE, "not connected\n");
--      case 2: return snprintf(buf, PAGE_SIZE, "connected\n");
--      case 3: return snprintf(buf, PAGE_SIZE, "lost\n");
--      default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
--      }
-+      static char *str[] = { NULL, "not connected", "connected", "lost" };
-+      if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
-+              return snprintf(buf, PAGE_SIZE, "%u\n", value);
-+      return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
- }
- static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf)
- {
--      switch (value) {
--      case 0: return snprintf(buf, PAGE_SIZE, "down\n");
--      case 1: return snprintf(buf, PAGE_SIZE, "attempting to activate\n");
--      case 2: return snprintf(buf, PAGE_SIZE, "training\n");
--      case 3: return snprintf(buf, PAGE_SIZE, "channel analysis\n");
--      case 4: return snprintf(buf, PAGE_SIZE, "exchange\n");
--      case 5: return snprintf(buf, PAGE_SIZE, "up\n");
--      case 6: return snprintf(buf, PAGE_SIZE, "waiting\n");
--      case 7: return snprintf(buf, PAGE_SIZE, "initialising\n");
--      default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
--      }
-+      static char *str[] = { "down", "attempting to activate",
-+              "training", "channel analysis", "exchange", "up",
-+              "waiting", "initialising"
-+      };
-+      if (unlikely(value >= ARRAY_SIZE(str)))
-+              return snprintf(buf, PAGE_SIZE, "%u\n", value);
-+      return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
- }
- static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf)
- {
--      switch (value) {
--      case 0: return 0;
--      case 1: return snprintf(buf, PAGE_SIZE, "ANSI T1.413\n");
--      case 2: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.1 (G.DMT)\n");
--      case 3: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.2 (G.LITE)\n");
--      default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
--      }
-+      static char *str[] = {
-+                      NULL,
-+                      "ANSI T1.413",
-+                      "ITU-T G.992.1 (G.DMT)",
-+                      "ITU-T G.992.2 (G.LITE)"
-+      };
-+      if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
-+              return snprintf(buf, PAGE_SIZE, "%u\n", value);
-+      return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
- }
- /*
-@@ -308,11 +298,10 @@
-       struct cxacru_data *instance = usbatm_instance->driver_data;
-       u32 value = instance->card_info[CXINF_LINE_STARTABLE];
--      switch (value) {
--      case 0: return snprintf(buf, PAGE_SIZE, "running\n");
--      case 1: return snprintf(buf, PAGE_SIZE, "stopped\n");
--      default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
--      }
-+      static char *str[] = { "running", "stopped" };
-+      if (unlikely(value >= ARRAY_SIZE(str)))
-+              return snprintf(buf, PAGE_SIZE, "%u\n", value);
-+      return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
- }
- static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
-diff -Nurb linux-2.6.22-570/drivers/usb/atm/ueagle-atm.c linux-2.6.22-590/drivers/usb/atm/ueagle-atm.c
---- linux-2.6.22-570/drivers/usb/atm/ueagle-atm.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/usb/atm/ueagle-atm.c      2008-01-02 13:56:37.000000000 -0500
-@@ -1168,6 +1168,7 @@
-       struct uea_softc *sc = data;
-       int ret = -EAGAIN;
-+      set_freezable();
-       uea_enters(INS_TO_USBDEV(sc));
-       while (!kthread_should_stop()) {
-               if (ret < 0 || sc->reset)
-diff -Nurb linux-2.6.22-570/drivers/usb/core/config.c linux-2.6.22-590/drivers/usb/core/config.c
---- linux-2.6.22-570/drivers/usb/core/config.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/usb/core/config.c 2008-01-02 13:56:37.000000000 -0500
-@@ -274,6 +274,7 @@
-       struct usb_descriptor_header *header;
-       int len, retval;
-       u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
-+      unsigned iad_num = 0;
-       memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
-       if (config->desc.bDescriptorType != USB_DT_CONFIG ||
-@@ -351,6 +352,20 @@
-                               ++n;
-                       }
-+              } else if (header->bDescriptorType ==
-+                              USB_DT_INTERFACE_ASSOCIATION) {
-+                      if (iad_num == USB_MAXIADS) {
-+                              dev_warn(ddev, "found more Interface "
-+                                             "Association Descriptors "
-+                                             "than allocated for in "
-+                                             "configuration %d\n", cfgno);
-+                      } else {
-+                              config->intf_assoc[iad_num] =
-+                                      (struct usb_interface_assoc_descriptor
-+                                      *)header;
-+                              iad_num++;
-+                      }
++at 0x00000257 : */    0x0f000001,0x00000000,
++/*
++    JUMP eat_msgin, WHEN MSG_IN
++
++at 0x00000259 : */    0x870b0000,0x0000095c,
++/*
++    JUMP sated
++
++at 0x0000025b : */    0x80080000,0x000009ac,
++/*
++eat_status:
++    MOVE 1, NCR53c7xx_sink, WHEN STATUS
 +
-               } else if (header->bDescriptorType == USB_DT_DEVICE ||
-                           header->bDescriptorType == USB_DT_CONFIG)
-                       dev_warn(ddev, "config %d contains an unexpected "
-diff -Nurb linux-2.6.22-570/drivers/usb/core/devices.c linux-2.6.22-590/drivers/usb/core/devices.c
---- linux-2.6.22-570/drivers/usb/core/devices.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/usb/core/devices.c        2008-01-02 13:56:37.000000000 -0500
-@@ -102,6 +102,10 @@
- /* C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
-   "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
-   
-+static const char *format_iad =
-+/* A:  FirstIf#=dd IfCount=dd Cls=xx(sssss) Sub=xx Prot=xx */
-+  "A:  FirstIf#=%2d IfCount=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n";
++at 0x0000025d : */    0x0b000001,0x00000000,
++/*
++    JUMP eat_status, WHEN STATUS
 +
- static const char *format_iface =
- /* I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
-   "I:%c If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
-@@ -146,6 +150,7 @@
-       {USB_CLASS_STILL_IMAGE,         "still"},
-       {USB_CLASS_CSCID,               "scard"},
-       {USB_CLASS_CONTENT_SEC,         "c-sec"},
-+      {USB_CLASS_VIDEO,               "video"},
-       {-1,                            "unk."}         /* leave as last */
- };
-@@ -286,6 +291,21 @@
-       return start;
- }
-+static char *usb_dump_iad_descriptor(char *start, char *end,
-+      const struct usb_interface_assoc_descriptor *iad)
-+{
-+      if (start > end)
-+              return start;
-+      start += sprintf(start, format_iad,
-+                       iad->bFirstInterface,
-+                       iad->bInterfaceCount,
-+                       iad->bFunctionClass,
-+                       class_decode(iad->bFunctionClass),
-+                       iad->bFunctionSubClass,
-+                       iad->bFunctionProtocol);
-+      return start;
-+}
++at 0x0000025f : */    0x830b0000,0x00000974,
++/*
++    JUMP sated
 +
- /* TBD:
-  * 0. TBDs
-  * 1. marking active interface altsettings (code lists all, but should mark
-@@ -322,6 +342,12 @@
-       if (!config)            /* getting these some in 2.3.7; none in 2.3.6 */
-               return start + sprintf(start, "(null Cfg. desc.)\n");
-       start = usb_dump_config_descriptor(start, end, &config->desc, active);
-+      for (i = 0; i < USB_MAXIADS; i++) {
-+              if (config->intf_assoc[i] == NULL)
-+                      break;
-+              start = usb_dump_iad_descriptor(start, end,
-+                                      config->intf_assoc[i]);
-+      }
-       for (i = 0; i < config->desc.bNumInterfaces; i++) {
-               intfc = config->intf_cache[i];
-               interface = config->interface[i];
-diff -Nurb linux-2.6.22-570/drivers/usb/core/hub.c linux-2.6.22-590/drivers/usb/core/hub.c
---- linux-2.6.22-570/drivers/usb/core/hub.c    2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/usb/core/hub.c    2008-01-02 13:56:37.000000000 -0500
-@@ -2831,6 +2831,7 @@
- static int hub_thread(void *__unused)
- {
-+      set_freezable();
-       do {
-               hub_events();
-               wait_event_interruptible(khubd_wait,
-diff -Nurb linux-2.6.22-570/drivers/usb/core/message.c linux-2.6.22-590/drivers/usb/core/message.c
---- linux-2.6.22-570/drivers/usb/core/message.c        2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/drivers/usb/core/message.c        2008-01-02 13:56:37.000000000 -0500
-@@ -1409,6 +1409,36 @@
-       .uevent =       usb_if_uevent,
- };
-+static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
-+                                                     struct usb_host_config *config,
-+                                                     u8 inum)
-+{
-+      struct usb_interface_assoc_descriptor *retval = NULL;
-+      struct usb_interface_assoc_descriptor *intf_assoc;
-+      int first_intf;
-+      int last_intf;
-+      int i;
++at 0x00000261 : */    0x80080000,0x000009ac,
++/*
++eat_datain:
++    MOVE 1, NCR53c7xx_sink, WHEN DATA_IN
 +
-+      for (i = 0; (i < USB_MAXIADS && config->intf_assoc[i]); i++) {
-+              intf_assoc = config->intf_assoc[i];
-+              if (intf_assoc->bInterfaceCount == 0)
-+                      continue;
++at 0x00000263 : */    0x09000001,0x00000000,
++/*
++    JUMP eat_datain, WHEN DATA_IN
 +
-+              first_intf = intf_assoc->bFirstInterface;
-+              last_intf = first_intf + (intf_assoc->bInterfaceCount - 1);
-+              if (inum >= first_intf && inum <= last_intf) {
-+                      if (!retval)
-+                              retval = intf_assoc;
-+                      else
-+                              dev_err(&dev->dev, "Interface #%d referenced"
-+                                      " by multiple IADs\n", inum);
-+              }
-+      }
++at 0x00000265 : */    0x810b0000,0x0000098c,
++/*
++    JUMP sated
 +
-+      return retval;
-+}
++at 0x00000267 : */    0x80080000,0x000009ac,
++/*
++spew_dataout:
++    MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT
 +
++at 0x00000269 : */    0x08000001,0x00000000,
++/*
++sated:
 +
- /*
-  * usb_set_configuration - Makes a particular device setting be current
-  * @dev: the device whose configuration is being updated
-@@ -1555,6 +1585,7 @@
-               intfc = cp->intf_cache[i];
-               intf->altsetting = intfc->altsetting;
-               intf->num_altsetting = intfc->num_altsetting;
-+              intf->intf_assoc = find_iad(dev, cp, i);
-               kref_get(&intfc->ref);
-               alt = usb_altnum_to_altsetting(intf, 0);
-diff -Nurb linux-2.6.22-570/drivers/usb/core/sysfs.c linux-2.6.22-590/drivers/usb/core/sysfs.c
---- linux-2.6.22-570/drivers/usb/core/sysfs.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/usb/core/sysfs.c  2008-01-02 13:56:37.000000000 -0500
-@@ -424,6 +424,25 @@
-       sysfs_remove_group(&dev->kobj, &dev_attr_grp);
- }
-+/* Interface Accociation Descriptor fields */
-+#define usb_intf_assoc_attr(field, format_string)                     \
-+static ssize_t                                                                \
-+show_iad_##field (struct device *dev, struct device_attribute *attr,  \
-+              char *buf)                                              \
-+{                                                                     \
-+      struct usb_interface *intf = to_usb_interface (dev);            \
-+                                                                      \
-+      return sprintf (buf, format_string,                             \
-+                      intf->intf_assoc->field);               \
-+}                                                                     \
-+static DEVICE_ATTR(iad_##field, S_IRUGO, show_iad_##field, NULL);
 +
-+usb_intf_assoc_attr (bFirstInterface, "%02x\n")
-+usb_intf_assoc_attr (bInterfaceCount, "%02d\n")
-+usb_intf_assoc_attr (bFunctionClass, "%02x\n")
-+usb_intf_assoc_attr (bFunctionSubClass, "%02x\n")
-+usb_intf_assoc_attr (bFunctionProtocol, "%02x\n")
 +
- /* Interface fields */
- #define usb_intf_attr(field, format_string)                           \
- static ssize_t                                                                \
-@@ -487,6 +506,18 @@
- }
- static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
-+static struct attribute *intf_assoc_attrs[] = {
-+      &dev_attr_iad_bFirstInterface.attr,
-+      &dev_attr_iad_bInterfaceCount.attr,
-+      &dev_attr_iad_bFunctionClass.attr,
-+      &dev_attr_iad_bFunctionSubClass.attr,
-+      &dev_attr_iad_bFunctionProtocol.attr,
-+      NULL,
++    MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT
++
++at 0x0000026b : */    0x0e000001,0x00000000,
++/*
++    WAIT DISCONNECT
++
++at 0x0000026d : */    0x48000000,0x00000000,
++/*
++    INT int_norm_aborted
++
++at 0x0000026f : */    0x98080000,0x02040000,
++/*
++
++
++ 
++
++; Little patched jump, used to overcome problems with TEMP getting
++; corrupted on memory moves.
++
++jump_temp:
++    JUMP 0
++
++at 0x00000271 : */    0x80080000,0x00000000,
 +};
-+static struct attribute_group intf_assoc_attr_grp = {
-+      .attrs = intf_assoc_attrs,
++
++#define A_NCR53c7xx_msg_abort 0x00000000
++static u32 A_NCR53c7xx_msg_abort_used[] __attribute((unused)) = {
++      0x0000026c,
 +};
 +
- static struct attribute *intf_attrs[] = {
-       &dev_attr_bInterfaceNumber.attr,
-       &dev_attr_bAlternateSetting.attr,
-@@ -538,6 +569,8 @@
-               alt->string = usb_cache_string(udev, alt->desc.iInterface);
-       if (alt->string)
-               retval = device_create_file(dev, &dev_attr_interface);
-+      if (intf->intf_assoc)
-+              retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp);
-       usb_create_intf_ep_files(intf, udev);
-       return 0;
- }
-@@ -549,4 +582,5 @@
-       usb_remove_intf_ep_files(intf);
-       device_remove_file(dev, &dev_attr_interface);
-       sysfs_remove_group(&dev->kobj, &intf_attr_grp);
-+      sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp);
- }
-diff -Nurb linux-2.6.22-570/drivers/usb/gadget/file_storage.c linux-2.6.22-590/drivers/usb/gadget/file_storage.c
---- linux-2.6.22-570/drivers/usb/gadget/file_storage.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/usb/gadget/file_storage.c 2008-01-02 13:56:37.000000000 -0500
-@@ -3434,6 +3434,9 @@
-       allow_signal(SIGKILL);
-       allow_signal(SIGUSR1);
-+      /* Allow the thread to be frozen */
-+      set_freezable();
++#define A_NCR53c7xx_msg_reject        0x00000000
++static u32 A_NCR53c7xx_msg_reject_used[] __attribute((unused)) = {
++      0x00000186,
++};
 +
-       /* Arrange for userspace references to be interpreted as kernel
-        * pointers.  That way we can pass a kernel pointer to a routine
-        * that expects a __user pointer and it will work okay. */
-diff -Nurb linux-2.6.22-570/drivers/usb/storage/usb.c linux-2.6.22-590/drivers/usb/storage/usb.c
---- linux-2.6.22-570/drivers/usb/storage/usb.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/usb/storage/usb.c 2008-01-02 13:56:37.000000000 -0500
-@@ -301,8 +301,6 @@
-       struct us_data *us = (struct us_data *)__us;
-       struct Scsi_Host *host = us_to_host(us);
--      current->flags |= PF_NOFREEZE;
--
-       for(;;) {
-               US_DEBUGP("*** thread sleeping.\n");
-               if(down_interruptible(&us->sema))
-@@ -909,6 +907,7 @@
-       printk(KERN_DEBUG
-               "usb-storage: device found at %d\n", us->pusb_dev->devnum);
-+      set_freezable();
-       /* Wait for the timeout to expire or for a disconnect */
-       if (delay_use > 0) {
-               printk(KERN_DEBUG "usb-storage: waiting for device "
-diff -Nurb linux-2.6.22-570/drivers/video/Kconfig linux-2.6.22-590/drivers/video/Kconfig
---- linux-2.6.22-570/drivers/video/Kconfig     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/video/Kconfig     2008-01-02 13:56:37.000000000 -0500
-@@ -12,6 +12,13 @@
-        tristate
-        default n
-+config VIDEO_OUTPUT_CONTROL
-+      tristate "Lowlevel video output switch controls"
-+      default m
-+      help
-+        This framework adds support for low-level control of the video 
-+        output switch.
++#define A_NCR53c7xx_sink      0x00000000
++static u32 A_NCR53c7xx_sink_used[] __attribute((unused)) = {
++      0x00000258,
++      0x0000025e,
++      0x00000264,
++};
 +
- config FB
-       tristate "Support for frame buffer devices"
-       ---help---
-diff -Nurb linux-2.6.22-570/drivers/video/Makefile linux-2.6.22-590/drivers/video/Makefile
---- linux-2.6.22-570/drivers/video/Makefile    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/video/Makefile    2008-01-02 13:56:37.000000000 -0500
-@@ -122,3 +122,6 @@
- # the test framebuffer is last
- obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
++#define A_NCR53c7xx_zero      0x00000000
++static u32 A_NCR53c7xx_zero_used[] __attribute((unused)) = {
++      0x00000254,
++      0x0000026a,
++};
 +
-+#video output switch sysfs driver
-+obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
-diff -Nurb linux-2.6.22-570/drivers/video/aty/radeon_base.c linux-2.6.22-590/drivers/video/aty/radeon_base.c
---- linux-2.6.22-570/drivers/video/aty/radeon_base.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/video/aty/radeon_base.c   2008-01-02 13:56:37.000000000 -0500
-@@ -2102,7 +2102,9 @@
- }
--static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+static ssize_t radeon_show_edid1(struct kobject *kobj,
-+                               struct bin_attribute *bin_attr,
-+                               char *buf, loff_t off, size_t count)
- {
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct pci_dev *pdev = to_pci_dev(dev);
-@@ -2113,7 +2115,9 @@
- }
--static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+static ssize_t radeon_show_edid2(struct kobject *kobj,
-+                               struct bin_attribute *bin_attr,
-+                               char *buf, loff_t off, size_t count)
- {
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct pci_dev *pdev = to_pci_dev(dev);
-@@ -2126,7 +2130,6 @@
- static struct bin_attribute edid1_attr = {
-       .attr   = {
-               .name   = "edid1",
--              .owner  = THIS_MODULE,
-               .mode   = 0444,
-       },
-       .size   = EDID_LENGTH,
-@@ -2136,7 +2139,6 @@
- static struct bin_attribute edid2_attr = {
-       .attr   = {
-               .name   = "edid2",
--              .owner  = THIS_MODULE,
-               .mode   = 0444,
-       },
-       .size   = EDID_LENGTH,
-diff -Nurb linux-2.6.22-570/drivers/video/backlight/backlight.c linux-2.6.22-590/drivers/video/backlight/backlight.c
---- linux-2.6.22-570/drivers/video/backlight/backlight.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/video/backlight/backlight.c       2008-01-02 13:56:37.000000000 -0500
-@@ -172,7 +172,7 @@
- #define DECLARE_ATTR(_name,_mode,_show,_store)                        \
- {                                                             \
--      .attr   = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },  \
-+      .attr   = { .name = __stringify(_name), .mode = _mode }, \
-       .show   = _show,                                        \
-       .store  = _store,                                       \
- }
-diff -Nurb linux-2.6.22-570/drivers/video/backlight/lcd.c linux-2.6.22-590/drivers/video/backlight/lcd.c
---- linux-2.6.22-570/drivers/video/backlight/lcd.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/video/backlight/lcd.c     2008-01-02 13:56:37.000000000 -0500
-@@ -157,7 +157,7 @@
- #define DECLARE_ATTR(_name,_mode,_show,_store)                        \
- {                                                             \
--      .attr   = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },  \
-+      .attr   = { .name = __stringify(_name), .mode = _mode }, \
-       .show   = _show,                                        \
-       .store  = _store,                                       \
- }
-diff -Nurb linux-2.6.22-570/drivers/video/ps3fb.c linux-2.6.22-590/drivers/video/ps3fb.c
---- linux-2.6.22-570/drivers/video/ps3fb.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/video/ps3fb.c     2008-01-02 13:56:37.000000000 -0500
-@@ -812,6 +812,7 @@
- static int ps3fbd(void *arg)
- {
-+      set_freezable();
-       while (!kthread_should_stop()) {
-               try_to_freeze();
-               set_current_state(TASK_INTERRUPTIBLE);
-diff -Nurb linux-2.6.22-570/drivers/w1/slaves/w1_ds2433.c linux-2.6.22-590/drivers/w1/slaves/w1_ds2433.c
---- linux-2.6.22-570/drivers/w1/slaves/w1_ds2433.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/w1/slaves/w1_ds2433.c     2008-01-02 13:56:37.000000000 -0500
-@@ -91,8 +91,9 @@
- }
- #endif        /* CONFIG_W1_SLAVE_DS2433_CRC */
--static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
--                             size_t count)
-+static ssize_t w1_f23_read_bin(struct kobject *kobj,
-+                             struct bin_attribute *bin_attr,
-+                             char *buf, loff_t off, size_t count)
- {
-       struct w1_slave *sl = kobj_to_w1_slave(kobj);
- #ifdef CONFIG_W1_SLAVE_DS2433_CRC
-@@ -199,8 +200,9 @@
-       return 0;
- }
--static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
--                              size_t count)
-+static ssize_t w1_f23_write_bin(struct kobject *kobj,
-+                              struct bin_attribute *bin_attr,
-+                              char *buf, loff_t off, size_t count)
- {
-       struct w1_slave *sl = kobj_to_w1_slave(kobj);
-       int addr, len, idx;
-@@ -252,7 +254,6 @@
-       .attr = {
-               .name = "eeprom",
-               .mode = S_IRUGO | S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = W1_EEPROM_SIZE,
-       .read = w1_f23_read_bin,
-diff -Nurb linux-2.6.22-570/drivers/w1/slaves/w1_therm.c linux-2.6.22-590/drivers/w1/slaves/w1_therm.c
---- linux-2.6.22-570/drivers/w1/slaves/w1_therm.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/w1/slaves/w1_therm.c      2008-01-02 13:56:37.000000000 -0500
-@@ -42,13 +42,13 @@
-                               {}
-                       };
--static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
-+static ssize_t w1_therm_read_bin(struct kobject *, struct bin_attribute *,
-+                               char *, loff_t, size_t);
- static struct bin_attribute w1_therm_bin_attr = {
-       .attr = {
-               .name = "w1_slave",
-               .mode = S_IRUGO,
--              .owner = THIS_MODULE,
-       },
-       .size = W1_SLAVE_DATA_SIZE,
-       .read = w1_therm_read_bin,
-@@ -159,7 +159,9 @@
-       return 0;
- }
--static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+static ssize_t w1_therm_read_bin(struct kobject *kobj,
-+                               struct bin_attribute *bin_attr,
-+                               char *buf, loff_t off, size_t count)
- {
-       struct w1_slave *sl = kobj_to_w1_slave(kobj);
-       struct w1_master *dev = sl->master;
-diff -Nurb linux-2.6.22-570/drivers/w1/w1.c linux-2.6.22-590/drivers/w1/w1.c
---- linux-2.6.22-570/drivers/w1/w1.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/w1/w1.c   2008-01-02 13:56:37.000000000 -0500
-@@ -105,7 +105,9 @@
-       return sprintf(buf, "%s\n", sl->name);
- }
--static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+static ssize_t w1_slave_read_id(struct kobject *kobj,
-+                              struct bin_attribute *bin_attr,
-+                              char *buf, loff_t off, size_t count)
- {
-       struct w1_slave *sl = kobj_to_w1_slave(kobj);
-@@ -128,7 +130,6 @@
-       .attr = {
-               .name = "id",
-               .mode = S_IRUGO,
--              .owner = THIS_MODULE,
-       },
-       .size = 8,
-       .read = w1_slave_read_id,
-@@ -136,7 +137,9 @@
- /* Default family */
--static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+static ssize_t w1_default_write(struct kobject *kobj,
-+                              struct bin_attribute *bin_attr,
-+                              char *buf, loff_t off, size_t count)
- {
-       struct w1_slave *sl = kobj_to_w1_slave(kobj);
-@@ -153,7 +156,9 @@
-       return count;
- }
--static ssize_t w1_default_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-+static ssize_t w1_default_read(struct kobject *kobj,
-+                             struct bin_attribute *bin_attr,
-+                             char *buf, loff_t off, size_t count)
- {
-       struct w1_slave *sl = kobj_to_w1_slave(kobj);
-@@ -167,7 +172,6 @@
-       .attr = {
-               .name = "rw",
-               .mode = S_IRUGO | S_IWUSR,
--              .owner = THIS_MODULE,
-       },
-       .size = PAGE_SIZE,
-       .read = w1_default_read,
-@@ -801,6 +805,7 @@
-       struct w1_master *dev, *n;
-       int have_to_wait = 0;
-+      set_freezable();
-       while (!kthread_should_stop() || have_to_wait) {
-               have_to_wait = 0;
-diff -Nurb linux-2.6.22-570/drivers/zorro/zorro-sysfs.c linux-2.6.22-590/drivers/zorro/zorro-sysfs.c
---- linux-2.6.22-570/drivers/zorro/zorro-sysfs.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/drivers/zorro/zorro-sysfs.c       2008-01-02 13:56:37.000000000 -0500
-@@ -49,8 +49,9 @@
- static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL);
--static ssize_t zorro_read_config(struct kobject *kobj, char *buf, loff_t off,
--                               size_t count)
-+static ssize_t zorro_read_config(struct kobject *kobj,
-+                               struct bin_attribute *bin_attr,
-+                               char *buf, loff_t off, size_t count)
- {
-       struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device,
-                                          kobj));
-@@ -78,7 +79,6 @@
-       .attr = {
-               .name = "config",
-               .mode = S_IRUGO | S_IWUSR,
--              .owner = THIS_MODULE
-       },
-       .size = sizeof(struct ConfigDev),
-       .read = zorro_read_config,
-diff -Nurb linux-2.6.22-570/ed linux-2.6.22-590/ed
---- linux-2.6.22-570/ed        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/ed        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,6 @@
-+vi -o ./fs/proc/proc_misc.c ./fs/proc/proc_misc.c.rej
-+vi -o ./fs/proc/array.c ./fs/proc/array.c.rej
-+vi -o ./include/linux/sched.h ./include/linux/sched.h.rej
-+vi -o ./kernel/time/timekeeping.c ./kernel/time/timekeeping.c.rej
-+vi -o ./kernel/timer.c ./kernel/timer.c.rej
-+vi -o ./kernel/fork.c ./kernel/fork.c.rej
-diff -Nurb linux-2.6.22-570/edit linux-2.6.22-590/edit
---- linux-2.6.22-570/edit      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/edit      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,19 @@
-+vi -o ./fs/proc/root.c ./fs/proc/root.c.rej
-+vi -o ./include/linux/nsproxy.h ./include/linux/nsproxy.h.rej
-+vi -o ./include/linux/sched.h ./include/linux/sched.h.rej
-+vi -o ./include/net/inet_timewait_sock.h ./include/net/inet_timewait_sock.h.rej
-+vi -o ./include/net/route.h ./include/net/route.h.rej
-+vi -o ./include/net/sock.h ./include/net/sock.h.rej
-+vi -o ./kernel/nsproxy.c ./kernel/nsproxy.c.rej
-+vi -o ./lib/Makefile ./lib/Makefile.rej
-+vi -o ./net/core/dev.c ./net/core/dev.c.rej
-+vi -o ./net/core/rtnetlink.c ./net/core/rtnetlink.c.rej
-+vi -o ./net/core/sock.c ./net/core/sock.c.rej
-+vi -o ./net/ipv4/af_inet.c ./net/ipv4/af_inet.c.rej
-+vi -o ./net/ipv4/inet_connection_sock.c ./net/ipv4/inet_connection_sock.c.rej
-+vi -o ./net/ipv4/inet_hashtables.c ./net/ipv4/inet_hashtables.c.rej
-+vi -o ./net/ipv4/raw.c ./net/ipv4/raw.c.rej
-+vi -o ./net/ipv4/tcp_ipv4.c ./net/ipv4/tcp_ipv4.c.rej
-+vi -o ./net/ipv4/udp.c ./net/ipv4/udp.c.rej
-+vi -o ./net/ipv6/addrconf.c ./net/ipv6/addrconf.c.rej
-+vi -o ./net/unix/af_unix.c ./net/unix/af_unix.c.rej
-diff -Nurb linux-2.6.22-570/fs/Kconfig linux-2.6.22-590/fs/Kconfig
---- linux-2.6.22-570/fs/Kconfig        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/Kconfig        2008-01-02 13:56:37.000000000 -0500
-@@ -1030,6 +1030,41 @@
- endmenu
-+menu "Layered filesystems"
++#define A_NOP_insn    0x00000000
++static u32 A_NOP_insn_used[] __attribute((unused)) = {
++      0x00000017,
++};
 +
-+config ECRYPT_FS
-+      tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
-+      depends on EXPERIMENTAL && KEYS && CRYPTO && NET
-+      help
-+        Encrypted filesystem that operates on the VFS layer.  See
-+        <file:Documentation/ecryptfs.txt> to learn more about
-+        eCryptfs.  Userspace components are required and can be
-+        obtained from <http://ecryptfs.sf.net>.
++#define A_addr_dsa    0x00000000
++static u32 A_addr_dsa_used[] __attribute((unused)) = {
++      0x0000000f,
++      0x00000026,
++      0x00000033,
++      0x00000040,
++      0x00000055,
++      0x00000079,
++      0x0000008e,
++      0x000000bc,
++      0x000000d2,
++      0x00000130,
++      0x000001a5,
++      0x000001bb,
++      0x000001e3,
++};
 +
-+        To compile this file system support as a module, choose M here: the
-+        module will be called ecryptfs.
++#define A_addr_reconnect_dsa_head     0x00000000
++static u32 A_addr_reconnect_dsa_head_used[] __attribute((unused)) = {
++      0x000001b7,
++};
 +
-+config UNION_FS
-+      tristate "Union file system (EXPERIMENTAL)"
-+      depends on EXPERIMENTAL
-+      help
-+        Unionfs is a stackable unification file system, which appears to
-+        merge the contents of several directories (branches), while keeping
-+        their physical content separate.
++#define A_addr_scratch        0x00000000
++static u32 A_addr_scratch_used[] __attribute((unused)) = {
++      0x00000002,
++      0x00000004,
++      0x00000008,
++      0x00000020,
++      0x00000022,
++      0x00000049,
++      0x00000060,
++      0x0000006a,
++      0x00000071,
++      0x00000073,
++      0x000000ab,
++      0x000000b5,
++      0x000000c1,
++      0x000000cb,
++      0x0000012c,
++      0x00000142,
++      0x00000157,
++      0x000001b2,
++      0x000001b4,
++      0x000001df,
++      0x000001f7,
++};
 +
-+        See <http://unionfs.filesystems.org> for details
++#define A_addr_temp   0x00000000
++static u32 A_addr_temp_used[] __attribute((unused)) = {
++};
 +
-+config UNION_FS_XATTR
-+      bool "Unionfs extended attributes"
-+      depends on UNION_FS
-+      help
-+        Extended attributes are name:value pairs associated with inodes by
-+        the kernel or by users (see the attr(5) manual page).
++#define A_dmode_memory_to_memory      0x00000000
++static u32 A_dmode_memory_to_memory_used[] __attribute((unused)) = {
++};
 +
-+        If unsure, say N.
++#define A_dmode_memory_to_ncr 0x00000000
++static u32 A_dmode_memory_to_ncr_used[] __attribute((unused)) = {
++};
 +
-+endmenu
++#define A_dmode_ncr_to_memory 0x00000000
++static u32 A_dmode_ncr_to_memory_used[] __attribute((unused)) = {
++};
 +
- menu "Miscellaneous filesystems"
- config ADFS_FS
-@@ -1082,18 +1117,6 @@
-         To compile this file system support as a module, choose M here: the
-         module will be called affs.  If unsure, say N.
--config ECRYPT_FS
--      tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
--      depends on EXPERIMENTAL && KEYS && CRYPTO && NET
--      help
--        Encrypted filesystem that operates on the VFS layer.  See
--        <file:Documentation/ecryptfs.txt> to learn more about
--        eCryptfs.  Userspace components are required and can be
--        obtained from <http://ecryptfs.sf.net>.
--
--        To compile this file system support as a module, choose M here: the
--        module will be called ecryptfs.
--
- config HFS_FS
-       tristate "Apple Macintosh file system support (EXPERIMENTAL)"
-       depends on BLOCK && EXPERIMENTAL
-diff -Nurb linux-2.6.22-570/fs/Makefile linux-2.6.22-590/fs/Makefile
---- linux-2.6.22-570/fs/Makefile       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/Makefile       2008-01-02 13:56:37.000000000 -0500
-@@ -19,6 +19,7 @@
- obj-y +=      no-block.o
- endif
-+obj-$(CONFIG_MMU)             += revoke.o revoked_inode.o
- obj-$(CONFIG_INOTIFY)         += inotify.o
- obj-$(CONFIG_INOTIFY_USER)    += inotify_user.o
- obj-$(CONFIG_EPOLL)           += eventpoll.o
-@@ -118,3 +119,4 @@
- obj-$(CONFIG_DEBUG_FS)                += debugfs/
- obj-$(CONFIG_OCFS2_FS)                += ocfs2/
- obj-$(CONFIG_GFS2_FS)           += gfs2/
-+obj-$(CONFIG_UNION_FS)                += unionfs/
-diff -Nurb linux-2.6.22-570/fs/afs/netdevices.c linux-2.6.22-590/fs/afs/netdevices.c
---- linux-2.6.22-570/fs/afs/netdevices.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/afs/netdevices.c       2008-01-02 13:56:37.000000000 -0500
-@@ -8,6 +8,7 @@
- #include <linux/inetdevice.h>
- #include <linux/netdevice.h>
- #include <linux/if_arp.h>
-+#include <net/net_namespace.h>
- #include "internal.h"
- /*
-@@ -23,7 +24,7 @@
-               BUG();
-       rtnl_lock();
--      dev = __dev_getfirstbyhwtype(ARPHRD_ETHER);
-+      dev = __dev_getfirstbyhwtype(&init_net, ARPHRD_ETHER);
-       if (dev) {
-               memcpy(mac, dev->dev_addr, maclen);
-               ret = 0;
-@@ -47,7 +48,7 @@
-       ASSERT(maxbufs > 0);
-       rtnl_lock();
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if (dev->type == ARPHRD_LOOPBACK && !wantloopback)
-                       continue;
-               idev = __in_dev_get_rtnl(dev);
-diff -Nurb linux-2.6.22-570/fs/buffer.c linux-2.6.22-590/fs/buffer.c
---- linux-2.6.22-570/fs/buffer.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/buffer.c       2008-01-02 13:56:37.000000000 -0500
-@@ -982,7 +982,7 @@
-       struct buffer_head *bh;
-       page = find_or_create_page(inode->i_mapping, index,
--              mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
-+              (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);
-       if (!page)
-               return NULL;
-@@ -2899,7 +2899,8 @@
-       
- struct buffer_head *alloc_buffer_head(gfp_t gfp_flags)
- {
--      struct buffer_head *ret = kmem_cache_zalloc(bh_cachep, gfp_flags);
-+      struct buffer_head *ret = kmem_cache_zalloc(bh_cachep,
-+                              set_migrateflags(gfp_flags, __GFP_RECLAIMABLE));
-       if (ret) {
-               INIT_LIST_HEAD(&ret->b_assoc_buffers);
-               get_cpu_var(bh_accounting).nr++;
-diff -Nurb linux-2.6.22-570/fs/cifs/cifsfs.c linux-2.6.22-590/fs/cifs/cifsfs.c
---- linux-2.6.22-570/fs/cifs/cifsfs.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/cifs/cifsfs.c  2008-01-02 13:56:37.000000000 -0500
-@@ -849,6 +849,7 @@
-       __u16  netfid;
-       int rc;
-+      set_freezable();
-       do {
-               if (try_to_freeze()) 
-                       continue;
-diff -Nurb linux-2.6.22-570/fs/cifs/connect.c linux-2.6.22-590/fs/cifs/connect.c
---- linux-2.6.22-570/fs/cifs/connect.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/cifs/connect.c 2008-01-02 13:56:37.000000000 -0500
-@@ -363,6 +363,7 @@
-                       GFP_KERNEL);
-       }
-+      set_freezable();
-       while (!kthread_should_stop()) {
-               if (try_to_freeze())
-                       continue;
-diff -Nurb linux-2.6.22-570/fs/compat_ioctl.c linux-2.6.22-590/fs/compat_ioctl.c
---- linux-2.6.22-570/fs/compat_ioctl.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/compat_ioctl.c 2008-01-02 13:56:37.000000000 -0500
-@@ -319,22 +319,21 @@
- static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
- {
--      struct net_device *dev;
--      struct ifreq32 ifr32;
-+      struct ifreq __user *uifr;
-       int err;
--      if (copy_from_user(&ifr32, compat_ptr(arg), sizeof(ifr32)))
-+      uifr = compat_alloc_user_space(sizeof(struct ifreq));
-+      if (copy_in_user(uifr, compat_ptr(arg), sizeof(struct ifreq32)));
-               return -EFAULT;
--      dev = dev_get_by_index(ifr32.ifr_ifindex);
--      if (!dev)
--              return -ENODEV;
-+      err = sys_ioctl(fd, SIOCGIFNAME, (unsigned long)uifr);
-+      if (err)
-+              return err;
--      strlcpy(ifr32.ifr_name, dev->name, sizeof(ifr32.ifr_name));
--      dev_put(dev);
-+      if (copy_in_user(compat_ptr(arg), uifr, sizeof(struct ifreq32)))
-+              return -EFAULT;
-       
--      err = copy_to_user(compat_ptr(arg), &ifr32, sizeof(ifr32));
--      return (err ? -EFAULT : 0);
-+      return 0;
- }
- static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
-diff -Nurb linux-2.6.22-570/fs/configfs/configfs_internal.h linux-2.6.22-590/fs/configfs/configfs_internal.h
---- linux-2.6.22-570/fs/configfs/configfs_internal.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/configfs/configfs_internal.h   2008-01-02 13:56:37.000000000 -0500
-@@ -29,6 +29,7 @@
- struct configfs_dirent {
-       atomic_t                s_count;
-+      int                     s_dependent_count;
-       struct list_head        s_sibling;
-       struct list_head        s_children;
-       struct list_head        s_links;
-diff -Nurb linux-2.6.22-570/fs/configfs/dir.c linux-2.6.22-590/fs/configfs/dir.c
---- linux-2.6.22-570/fs/configfs/dir.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/configfs/dir.c 2008-01-02 13:56:37.000000000 -0500
-@@ -355,6 +355,10 @@
-                       /* Mark that we've taken i_mutex */
-                       sd->s_type |= CONFIGFS_USET_DROPPING;
-+                      /*
-+                       * Yup, recursive.  If there's a problem, blame
-+                       * deep nesting of default_groups
-+                       */
-                       ret = configfs_detach_prep(sd->s_dentry);
-                       if (!ret)
-                               continue;
-@@ -714,6 +718,28 @@
- }
- /*
-+ * After the item has been detached from the filesystem view, we are
-+ * ready to tear it out of the hierarchy.  Notify the client before
-+ * we do that so they can perform any cleanup that requires
-+ * navigating the hierarchy.  A client does not need to provide this
-+ * callback.  The subsystem semaphore MUST be held by the caller, and
-+ * references must be valid for both items.  It also assumes the
-+ * caller has validated ci_type.
-+ */
-+static void client_disconnect_notify(struct config_item *parent_item,
-+                                   struct config_item *item)
-+{
-+      struct config_item_type *type;
++#define A_dsa_check_reselect  0x00000000
++static u32 A_dsa_check_reselect_used[] __attribute((unused)) = {
++      0x000001d0,
++};
 +
-+      type = parent_item->ci_type;
-+      BUG_ON(!type);
++#define A_dsa_cmdout  0x00000048
++static u32 A_dsa_cmdout_used[] __attribute((unused)) = {
++      0x0000009a,
++};
 +
-+      if (type->ct_group_ops && type->ct_group_ops->disconnect_notify)
-+              type->ct_group_ops->disconnect_notify(to_config_group(parent_item),
-+                                                    item);
-+}
++#define A_dsa_cmnd    0x00000038
++static u32 A_dsa_cmnd_used[] __attribute((unused)) = {
++};
 +
-+/*
-  * Drop the initial reference from make_item()/make_group()
-  * This function assumes that reference is held on item
-  * and that item holds a valid reference to the parent.  Also, it
-@@ -738,6 +764,239 @@
-               config_item_put(item);
- }
-+#ifdef DEBUG
-+static void configfs_dump_one(struct configfs_dirent *sd, int level)
-+{
-+      printk(KERN_INFO "%*s\"%s\":\n", level, " ", configfs_get_name(sd));
++#define A_dsa_datain  0x00000054
++static u32 A_dsa_datain_used[] __attribute((unused)) = {
++      0x000000c2,
++};
 +
-+#define type_print(_type) if (sd->s_type & _type) printk(KERN_INFO "%*s %s\n", level, " ", #_type);
-+      type_print(CONFIGFS_ROOT);
-+      type_print(CONFIGFS_DIR);
-+      type_print(CONFIGFS_ITEM_ATTR);
-+      type_print(CONFIGFS_ITEM_LINK);
-+      type_print(CONFIGFS_USET_DIR);
-+      type_print(CONFIGFS_USET_DEFAULT);
-+      type_print(CONFIGFS_USET_DROPPING);
-+#undef type_print
-+}
++#define A_dsa_dataout 0x00000050
++static u32 A_dsa_dataout_used[] __attribute((unused)) = {
++      0x000000ac,
++};
 +
-+static int configfs_dump(struct configfs_dirent *sd, int level)
-+{
-+      struct configfs_dirent *child_sd;
-+      int ret = 0;
++#define A_dsa_end     0x00000070
++static u32 A_dsa_end_used[] __attribute((unused)) = {
++};
 +
-+      configfs_dump_one(sd, level);
++#define A_dsa_fields_start    0x00000000
++static u32 A_dsa_fields_start_used[] __attribute((unused)) = {
++};
 +
-+      if (!(sd->s_type & (CONFIGFS_DIR|CONFIGFS_ROOT)))
-+              return 0;
++#define A_dsa_msgin   0x00000058
++static u32 A_dsa_msgin_used[] __attribute((unused)) = {
++      0x0000019c,
++};
 +
-+      list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
-+              ret = configfs_dump(child_sd, level + 2);
-+              if (ret)
-+                      break;
-+      }
++#define A_dsa_msgout  0x00000040
++static u32 A_dsa_msgout_used[] __attribute((unused)) = {
++      0x00000089,
++};
 +
-+      return ret;
-+}
-+#endif
++#define A_dsa_msgout_other    0x00000068
++static u32 A_dsa_msgout_other_used[] __attribute((unused)) = {
++      0x00000194,
++};
 +
++#define A_dsa_next    0x00000030
++static u32 A_dsa_next_used[] __attribute((unused)) = {
++      0x00000061,
++};
 +
-+/*
-+ * configfs_depend_item() and configfs_undepend_item()
-+ *
-+ * WARNING: Do not call these from a configfs callback!
-+ *
-+ * This describes these functions and their helpers.
-+ *
-+ * Allow another kernel system to depend on a config_item.  If this
-+ * happens, the item cannot go away until the dependant can live without
-+ * it.  The idea is to give client modules as simple an interface as
-+ * possible.  When a system asks them to depend on an item, they just
-+ * call configfs_depend_item().  If the item is live and the client
-+ * driver is in good shape, we'll happily do the work for them.
-+ *
-+ * Why is the locking complex?  Because configfs uses the VFS to handle
-+ * all locking, but this function is called outside the normal
-+ * VFS->configfs path.  So it must take VFS locks to prevent the
-+ * VFS->configfs stuff (configfs_mkdir(), configfs_rmdir(), etc).  This is
-+ * why you can't call these functions underneath configfs callbacks.
-+ *
-+ * Note, btw, that this can be called at *any* time, even when a configfs
-+ * subsystem isn't registered, or when configfs is loading or unloading.
-+ * Just like configfs_register_subsystem().  So we take the same
-+ * precautions.  We pin the filesystem.  We lock each i_mutex _in_order_
-+ * on our way down the tree.  If we can find the target item in the
-+ * configfs tree, it must be part of the subsystem tree as well, so we
-+ * do not need the subsystem semaphore.  Holding the i_mutex chain locks
-+ * out mkdir() and rmdir(), who might be racing us.
-+ */
++#define A_dsa_restore_pointers        0x00000000
++static u32 A_dsa_restore_pointers_used[] __attribute((unused)) = {
++      0x00000146,
++};
 +
-+/*
-+ * configfs_depend_prep()
-+ *
-+ * Only subdirectories count here.  Files (CONFIGFS_NOT_PINNED) are
-+ * attributes.  This is similar but not the same to configfs_detach_prep().
-+ * Note that configfs_detach_prep() expects the parent to be locked when it
-+ * is called, but we lock the parent *inside* configfs_depend_prep().  We
-+ * do that so we can unlock it if we find nothing.
-+ *
-+ * Here we do a depth-first search of the dentry hierarchy looking for
-+ * our object.  We take i_mutex on each step of the way down.  IT IS
-+ * ESSENTIAL THAT i_mutex LOCKING IS ORDERED.  If we come back up a branch,
-+ * we'll drop the i_mutex.
-+ *
-+ * If the target is not found, -ENOENT is bubbled up and we have released
-+ * all locks.  If the target was found, the locks will be cleared by
-+ * configfs_depend_rollback().
-+ *
-+ * This adds a requirement that all config_items be unique!
-+ *
-+ * This is recursive because the locking traversal is tricky.  There isn't
-+ * much on the stack, though, so folks that need this function - be careful
-+ * about your stack!  Patches will be accepted to make it iterative.
-+ */
-+static int configfs_depend_prep(struct dentry *origin,
-+                              struct config_item *target)
-+{
-+      struct configfs_dirent *child_sd, *sd = origin->d_fsdata;
-+      int ret = 0;
++#define A_dsa_save_data_pointer       0x00000000
++static u32 A_dsa_save_data_pointer_used[] __attribute((unused)) = {
++      0x00000131,
++};
 +
-+      BUG_ON(!origin || !sd);
++#define A_dsa_select  0x0000003c
++static u32 A_dsa_select_used[] __attribute((unused)) = {
++      0x00000082,
++};
 +
-+      /* Lock this guy on the way down */
-+      mutex_lock(&sd->s_dentry->d_inode->i_mutex);
-+      if (sd->s_element == target)  /* Boo-yah */
-+              goto out;
++#define A_dsa_sscf_710        0x00000000
++static u32 A_dsa_sscf_710_used[] __attribute((unused)) = {
++      0x00000007,
++};
 +
-+      list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
-+              if (child_sd->s_type & CONFIGFS_DIR) {
-+                      ret = configfs_depend_prep(child_sd->s_dentry,
-+                                                 target);
-+                      if (!ret)
-+                              goto out;  /* Child path boo-yah */
-+              }
-+      }
++#define A_dsa_status  0x00000060
++static u32 A_dsa_status_used[] __attribute((unused)) = {
++      0x00000198,
++};
 +
-+      /* We looped all our children and didn't find target */
-+      mutex_unlock(&sd->s_dentry->d_inode->i_mutex);
-+      ret = -ENOENT;
++#define A_dsa_temp_addr_array_value   0x00000000
++static u32 A_dsa_temp_addr_array_value_used[] __attribute((unused)) = {
++};
 +
-+out:
-+      return ret;
-+}
++#define A_dsa_temp_addr_dsa_value     0x00000000
++static u32 A_dsa_temp_addr_dsa_value_used[] __attribute((unused)) = {
++      0x00000001,
++};
 +
-+/*
-+ * This is ONLY called if configfs_depend_prep() did its job.  So we can
-+ * trust the entire path from item back up to origin.
-+ *
-+ * We walk backwards from item, unlocking each i_mutex.  We finish by
-+ * unlocking origin.
-+ */
-+static void configfs_depend_rollback(struct dentry *origin,
-+                                   struct config_item *item)
-+{
-+      struct dentry *dentry = item->ci_dentry;
++#define A_dsa_temp_addr_new_value     0x00000000
++static u32 A_dsa_temp_addr_new_value_used[] __attribute((unused)) = {
++};
 +
-+      while (dentry != origin) {
-+              mutex_unlock(&dentry->d_inode->i_mutex);
-+              dentry = dentry->d_parent;
-+      }
++#define A_dsa_temp_addr_next  0x00000000
++static u32 A_dsa_temp_addr_next_used[] __attribute((unused)) = {
++      0x0000001c,
++      0x0000004f,
++};
 +
-+      mutex_unlock(&origin->d_inode->i_mutex);
-+}
++#define A_dsa_temp_addr_residual      0x00000000
++static u32 A_dsa_temp_addr_residual_used[] __attribute((unused)) = {
++      0x0000002d,
++      0x0000003b,
++};
 +
-+int configfs_depend_item(struct configfs_subsystem *subsys,
-+                       struct config_item *target)
-+{
-+      int ret;
-+      struct configfs_dirent *p, *root_sd, *subsys_sd = NULL;
-+      struct config_item *s_item = &subsys->su_group.cg_item;
++#define A_dsa_temp_addr_saved_pointer 0x00000000
++static u32 A_dsa_temp_addr_saved_pointer_used[] __attribute((unused)) = {
++      0x0000002b,
++      0x00000037,
++};
 +
-+      /*
-+       * Pin the configfs filesystem.  This means we can safely access
-+       * the root of the configfs filesystem.
-+       */
-+      ret = configfs_pin_fs();
-+      if (ret)
-+              return ret;
++#define A_dsa_temp_addr_saved_residual        0x00000000
++static u32 A_dsa_temp_addr_saved_residual_used[] __attribute((unused)) = {
++      0x0000002e,
++      0x0000003a,
++};
++
++#define A_dsa_temp_lun        0x00000000
++static u32 A_dsa_temp_lun_used[] __attribute((unused)) = {
++      0x0000004c,
++};
++
++#define A_dsa_temp_next       0x00000000
++static u32 A_dsa_temp_next_used[] __attribute((unused)) = {
++      0x0000001f,
++};
++
++#define A_dsa_temp_sync       0x00000000
++static u32 A_dsa_temp_sync_used[] __attribute((unused)) = {
++      0x00000057,
++};
++
++#define A_dsa_temp_target     0x00000000
++static u32 A_dsa_temp_target_used[] __attribute((unused)) = {
++      0x00000045,
++};
++
++#define A_emulfly     0x00000000
++static u32 A_emulfly_used[] __attribute((unused)) = {
++};
++
++#define A_int_debug_break     0x03000000
++static u32 A_int_debug_break_used[] __attribute((unused)) = {
++      0x0000023c,
++};
++
++#define A_int_debug_panic     0x030b0000
++static u32 A_int_debug_panic_used[] __attribute((unused)) = {
++      0x00000209,
++      0x00000219,
++};
++
++#define A_int_err_check_condition     0x00030000
++static u32 A_int_err_check_condition_used[] __attribute((unused)) = {
++      0x000001a9,
++};
++
++#define A_int_err_no_phase    0x00040000
++static u32 A_int_err_no_phase_used[] __attribute((unused)) = {
++};
++
++#define A_int_err_selected    0x00010000
++static u32 A_int_err_selected_used[] __attribute((unused)) = {
++      0x000001ff,
++};
++
++#define A_int_err_unexpected_phase    0x00000000
++static u32 A_int_err_unexpected_phase_used[] __attribute((unused)) = {
++      0x00000092,
++      0x00000098,
++      0x000000a0,
++      0x000000d6,
++      0x000000da,
++      0x000000dc,
++      0x000000e4,
++      0x000000e8,
++      0x000000ea,
++      0x000000f2,
++      0x000000f6,
++      0x000000f8,
++      0x000000fa,
++      0x00000160,
++};
++
++#define A_int_err_unexpected_reselect 0x00020000
++static u32 A_int_err_unexpected_reselect_used[] __attribute((unused)) = {
++      0x000001cd,
++};
++
++#define A_int_msg_1   0x01020000
++static u32 A_int_msg_1_used[] __attribute((unused)) = {
++      0x00000114,
++      0x00000116,
++};
++
++#define A_int_msg_sdtr        0x01010000
++static u32 A_int_msg_sdtr_used[] __attribute((unused)) = {
++      0x00000180,
++};
++
++#define A_int_msg_wdtr        0x01000000
++static u32 A_int_msg_wdtr_used[] __attribute((unused)) = {
++      0x00000174,
++};
++
++#define A_int_norm_aborted    0x02040000
++static u32 A_int_norm_aborted_used[] __attribute((unused)) = {
++      0x00000270,
++};
++
++#define A_int_norm_command_complete   0x02020000
++static u32 A_int_norm_command_complete_used[] __attribute((unused)) = {
++};
 +
-+      /*
-+       * Next, lock the root directory.  We're going to check that the
-+       * subsystem is really registered, and so we need to lock out
-+       * configfs_[un]register_subsystem().
-+       */
-+      mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);
++#define A_int_norm_disconnected       0x02030000
++static u32 A_int_norm_disconnected_used[] __attribute((unused)) = {
++};
 +
-+      root_sd = configfs_sb->s_root->d_fsdata;
++#define A_int_norm_emulateintfly      0x02060000
++static u32 A_int_norm_emulateintfly_used[] __attribute((unused)) = {
++      0x000001a2,
++};
 +
-+      list_for_each_entry(p, &root_sd->s_children, s_sibling) {
-+              if (p->s_type & CONFIGFS_DIR) {
-+                      if (p->s_element == s_item) {
-+                              subsys_sd = p;
-+                              break;
-+                      }
-+              }
-+      }
++#define A_int_norm_reselect_complete  0x02010000
++static u32 A_int_norm_reselect_complete_used[] __attribute((unused)) = {
++};
 +
-+      if (!subsys_sd) {
-+              ret = -ENOENT;
-+              goto out_unlock_fs;
-+      }
++#define A_int_norm_reset      0x02050000
++static u32 A_int_norm_reset_used[] __attribute((unused)) = {
++};
 +
-+      /* Ok, now we can trust subsys/s_item */
++#define A_int_norm_select_complete    0x02000000
++static u32 A_int_norm_select_complete_used[] __attribute((unused)) = {
++};
 +
-+      /* Scan the tree, locking i_mutex recursively, return 0 if found */
-+      ret = configfs_depend_prep(subsys_sd->s_dentry, target);
-+      if (ret)
-+              goto out_unlock_fs;
++#define A_int_test_1  0x04000000
++static u32 A_int_test_1_used[] __attribute((unused)) = {
++      0x0000021e,
++};
 +
-+      /* We hold all i_mutexes from the subsystem down to the target */
-+      p = target->ci_dentry->d_fsdata;
-+      p->s_dependent_count += 1;
++#define A_int_test_2  0x04010000
++static u32 A_int_test_2_used[] __attribute((unused)) = {
++      0x0000023a,
++};
 +
-+      configfs_depend_rollback(subsys_sd->s_dentry, target);
++#define A_int_test_3  0x04020000
++static u32 A_int_test_3_used[] __attribute((unused)) = {
++};
 +
-+out_unlock_fs:
-+      mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);
++#define A_msg_buf     0x00000000
++static u32 A_msg_buf_used[] __attribute((unused)) = {
++      0x00000108,
++      0x00000162,
++      0x0000016c,
++      0x00000172,
++      0x00000178,
++      0x0000017e,
++};
 +
-+      /*
-+       * If we succeeded, the fs is pinned via other methods.  If not,
-+       * we're done with it anyway.  So release_fs() is always right.
-+       */
-+      configfs_release_fs();
++#define A_reconnect_dsa_head  0x00000000
++static u32 A_reconnect_dsa_head_used[] __attribute((unused)) = {
++      0x0000006d,
++      0x00000074,
++      0x000001b1,
++};
 +
-+      return ret;
-+}
-+EXPORT_SYMBOL(configfs_depend_item);
++#define A_reselected_identify 0x00000000
++static u32 A_reselected_identify_used[] __attribute((unused)) = {
++      0x00000048,
++      0x000001af,
++};
 +
-+/*
-+ * Release the dependent linkage.  This is much simpler than
-+ * configfs_depend_item() because we know that that the client driver is
-+ * pinned, thus the subsystem is pinned, and therefore configfs is pinned.
-+ */
-+void configfs_undepend_item(struct configfs_subsystem *subsys,
-+                          struct config_item *target)
-+{
-+      struct configfs_dirent *sd;
++#define A_reselected_tag      0x00000000
++static u32 A_reselected_tag_used[] __attribute((unused)) = {
++};
 +
-+      /*
-+       * Since we can trust everything is pinned, we just need i_mutex
-+       * on the item.
-+       */
-+      mutex_lock(&target->ci_dentry->d_inode->i_mutex);
++#define A_saved_dsa   0x00000000
++static u32 A_saved_dsa_used[] __attribute((unused)) = {
++      0x00000005,
++      0x0000000e,
++      0x00000023,
++      0x00000025,
++      0x00000032,
++      0x0000003f,
++      0x00000054,
++      0x0000005f,
++      0x00000070,
++      0x00000078,
++      0x0000008d,
++      0x000000aa,
++      0x000000bb,
++      0x000000c0,
++      0x000000d1,
++      0x0000012f,
++      0x000001a4,
++      0x000001b5,
++      0x000001ba,
++      0x000001e2,
++};
 +
-+      sd = target->ci_dentry->d_fsdata;
-+      BUG_ON(sd->s_dependent_count < 1);
++#define A_schedule    0x00000000
++static u32 A_schedule_used[] __attribute((unused)) = {
++      0x0000007d,
++      0x000001a7,
++      0x00000203,
++      0x00000244,
++};
 +
-+      sd->s_dependent_count -= 1;
++#define A_test_dest   0x00000000
++static u32 A_test_dest_used[] __attribute((unused)) = {
++      0x0000021c,
++};
 +
-+      /*
-+       * After this unlock, we cannot trust the item to stay alive!
-+       * DO NOT REFERENCE item after this unlock.
-+       */
-+      mutex_unlock(&target->ci_dentry->d_inode->i_mutex);
-+}
-+EXPORT_SYMBOL(configfs_undepend_item);
- static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
- {
-@@ -842,11 +1101,14 @@
-       if (ret) {
-               /* Tear down everything we built up */
-               down(&subsys->su_sem);
++#define A_test_src    0x00000000
++static u32 A_test_src_used[] __attribute((unused)) = {
++      0x0000021b,
++};
 +
-+              client_disconnect_notify(parent_item, item);
-               if (group)
-                       unlink_group(group);
-               else
-                       unlink_obj(item);
-               client_drop_item(parent_item, item);
++#define Ent_accept_message    0x00000624
++#define Ent_cmdout_cmdout     0x00000264
++#define Ent_command_complete  0x0000065c
++#define Ent_command_complete_msgin    0x0000066c
++#define Ent_data_transfer     0x0000026c
++#define Ent_datain_to_jump    0x00000334
++#define Ent_debug_break       0x000008ec
++#define Ent_dsa_code_begin    0x00000000
++#define Ent_dsa_code_check_reselect   0x0000010c
++#define Ent_dsa_code_fix_jump 0x00000058
++#define Ent_dsa_code_restore_pointers 0x000000d8
++#define Ent_dsa_code_save_data_pointer        0x000000a4
++#define Ent_dsa_code_template 0x00000000
++#define Ent_dsa_code_template_end     0x00000178
++#define Ent_dsa_schedule      0x00000178
++#define Ent_dsa_zero  0x00000178
++#define Ent_end_data_transfer 0x000002a4
++#define Ent_initiator_abort   0x00000914
++#define Ent_msg_in    0x0000041c
++#define Ent_msg_in_restart    0x000003fc
++#define Ent_other_in  0x0000038c
++#define Ent_other_out 0x00000354
++#define Ent_other_transfer    0x000003c4
++#define Ent_reject_message    0x00000604
++#define Ent_reselected_check_next     0x000006f0
++#define Ent_reselected_ok     0x00000798
++#define Ent_respond_message   0x0000063c
++#define Ent_select    0x000001f8
++#define Ent_select_msgout     0x00000218
++#define Ent_target_abort      0x000008f4
++#define Ent_test_1    0x00000868
++#define Ent_test_2    0x0000087c
++#define Ent_test_2_msgout     0x0000089c
++#define Ent_wait_reselect     0x000006a8
++static u32 LABELPATCHES[] __attribute((unused)) = {
++      0x00000011,
++      0x0000001a,
++      0x0000001d,
++      0x00000028,
++      0x0000002a,
++      0x00000035,
++      0x00000038,
++      0x00000042,
++      0x00000050,
++      0x00000052,
++      0x0000006b,
++      0x00000083,
++      0x00000085,
++      0x00000090,
++      0x00000094,
++      0x00000096,
++      0x0000009c,
++      0x0000009e,
++      0x000000a2,
++      0x000000a4,
++      0x000000a6,
++      0x000000a8,
++      0x000000b6,
++      0x000000b9,
++      0x000000cc,
++      0x000000cf,
++      0x000000d8,
++      0x000000de,
++      0x000000e0,
++      0x000000e6,
++      0x000000ec,
++      0x000000ee,
++      0x000000f4,
++      0x000000fc,
++      0x000000fe,
++      0x0000010a,
++      0x0000010c,
++      0x0000010e,
++      0x00000110,
++      0x00000112,
++      0x00000118,
++      0x0000011a,
++      0x0000012d,
++      0x00000143,
++      0x00000158,
++      0x0000015c,
++      0x00000164,
++      0x00000166,
++      0x00000168,
++      0x0000016e,
++      0x0000017a,
++      0x000001ab,
++      0x000001b8,
++      0x000001bf,
++      0x000001c3,
++      0x000001c7,
++      0x000001cb,
++      0x000001e0,
++      0x000001f8,
++      0x00000207,
++      0x0000020f,
++      0x00000213,
++      0x00000217,
++      0x00000224,
++      0x00000226,
++      0x00000248,
++      0x0000024a,
++      0x0000024c,
++      0x0000024e,
++      0x00000250,
++      0x00000252,
++      0x00000256,
++      0x0000025a,
++      0x0000025c,
++      0x00000260,
++      0x00000262,
++      0x00000266,
++      0x00000268,
++};
 +
-               up(&subsys->su_sem);
-               if (module_got)
-@@ -881,6 +1143,13 @@
-       if (sd->s_type & CONFIGFS_USET_DEFAULT)
-               return -EPERM;
-+      /*
-+       * Here's where we check for dependents.  We're protected by
-+       * i_mutex.
-+       */
-+      if (sd->s_dependent_count)
-+              return -EBUSY;
++static struct {
++      u32     offset;
++      void            *address;
++} EXTERNAL_PATCHES[] __attribute((unused)) = {
++};
 +
-       /* Get a working ref until we have the child */
-       parent_item = configfs_get_config_item(dentry->d_parent);
-       subsys = to_config_group(parent_item)->cg_subsys;
-@@ -911,11 +1180,13 @@
-               configfs_detach_group(item);
-               down(&subsys->su_sem);
-+              client_disconnect_notify(parent_item, item);
-               unlink_group(to_config_group(item));
-       } else {
-               configfs_detach_item(item);
-               down(&subsys->su_sem);
-+              client_disconnect_notify(parent_item, item);
-               unlink_obj(item);
-       }
-diff -Nurb linux-2.6.22-570/fs/configfs/file.c linux-2.6.22-590/fs/configfs/file.c
---- linux-2.6.22-570/fs/configfs/file.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/configfs/file.c        2008-01-02 13:56:37.000000000 -0500
-@@ -27,19 +27,26 @@
- #include <linux/fs.h>
- #include <linux/module.h>
- #include <linux/slab.h>
-+#include <linux/mutex.h>
- #include <asm/uaccess.h>
--#include <asm/semaphore.h>
- #include <linux/configfs.h>
- #include "configfs_internal.h"
-+/*
-+ * A simple attribute can only be 4096 characters.  Why 4k?  Because the
-+ * original code limited it to PAGE_SIZE.  That's a bad idea, though,
-+ * because an attribute of 16k on ia64 won't work on x86.  So we limit to
-+ * 4k, our minimum common page size.
-+ */
-+#define SIMPLE_ATTR_SIZE 4096
- struct configfs_buffer {
-       size_t                  count;
-       loff_t                  pos;
-       char                    * page;
-       struct configfs_item_operations * ops;
--      struct semaphore        sem;
-+      struct mutex            mutex;
-       int                     needs_read_fill;
- };
-@@ -69,7 +76,7 @@
-       count = ops->show_attribute(item,attr,buffer->page);
-       buffer->needs_read_fill = 0;
--      BUG_ON(count > (ssize_t)PAGE_SIZE);
-+      BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE);
-       if (count >= 0)
-               buffer->count = count;
-       else
-@@ -102,7 +109,7 @@
-       struct configfs_buffer * buffer = file->private_data;
-       ssize_t retval = 0;
--      down(&buffer->sem);
-+      mutex_lock(&buffer->mutex);
-       if (buffer->needs_read_fill) {
-               if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
-                       goto out;
-@@ -112,7 +119,7 @@
-       retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
-                                        buffer->count);
- out:
--      up(&buffer->sem);
-+      mutex_unlock(&buffer->mutex);
-       return retval;
- }
-@@ -137,8 +144,8 @@
-       if (!buffer->page)
-               return -ENOMEM;
--      if (count >= PAGE_SIZE)
--              count = PAGE_SIZE - 1;
-+      if (count >= SIMPLE_ATTR_SIZE)
-+              count = SIMPLE_ATTR_SIZE - 1;
-       error = copy_from_user(buffer->page,buf,count);
-       buffer->needs_read_fill = 1;
-       /* if buf is assumed to contain a string, terminate it by \0,
-@@ -193,13 +200,13 @@
-       struct configfs_buffer * buffer = file->private_data;
-       ssize_t len;
++static u32 INSTRUCTIONS __attribute((unused)) = 290;
++static u32 PATCHES __attribute((unused))      = 78;
++static u32 EXTERNAL_PATCHES_LEN __attribute((unused)) = 0;
+diff -Nurb linux-2.6.22-590/drivers/scsi/53c7xx_u.h_shipped linux-2.6.22-570/drivers/scsi/53c7xx_u.h_shipped
+--- linux-2.6.22-590/drivers/scsi/53c7xx_u.h_shipped   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/53c7xx_u.h_shipped   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,102 @@
++#undef A_NCR53c7xx_msg_abort
++#undef A_NCR53c7xx_msg_reject
++#undef A_NCR53c7xx_sink
++#undef A_NCR53c7xx_zero
++#undef A_NOP_insn
++#undef A_addr_dsa
++#undef A_addr_reconnect_dsa_head
++#undef A_addr_scratch
++#undef A_addr_temp
++#undef A_dmode_memory_to_memory
++#undef A_dmode_memory_to_ncr
++#undef A_dmode_ncr_to_memory
++#undef A_dsa_check_reselect
++#undef A_dsa_cmdout
++#undef A_dsa_cmnd
++#undef A_dsa_datain
++#undef A_dsa_dataout
++#undef A_dsa_end
++#undef A_dsa_fields_start
++#undef A_dsa_msgin
++#undef A_dsa_msgout
++#undef A_dsa_msgout_other
++#undef A_dsa_next
++#undef A_dsa_restore_pointers
++#undef A_dsa_save_data_pointer
++#undef A_dsa_select
++#undef A_dsa_sscf_710
++#undef A_dsa_status
++#undef A_dsa_temp_addr_array_value
++#undef A_dsa_temp_addr_dsa_value
++#undef A_dsa_temp_addr_new_value
++#undef A_dsa_temp_addr_next
++#undef A_dsa_temp_addr_residual
++#undef A_dsa_temp_addr_saved_pointer
++#undef A_dsa_temp_addr_saved_residual
++#undef A_dsa_temp_lun
++#undef A_dsa_temp_next
++#undef A_dsa_temp_sync
++#undef A_dsa_temp_target
++#undef A_emulfly
++#undef A_int_debug_break
++#undef A_int_debug_panic
++#undef A_int_err_check_condition
++#undef A_int_err_no_phase
++#undef A_int_err_selected
++#undef A_int_err_unexpected_phase
++#undef A_int_err_unexpected_reselect
++#undef A_int_msg_1
++#undef A_int_msg_sdtr
++#undef A_int_msg_wdtr
++#undef A_int_norm_aborted
++#undef A_int_norm_command_complete
++#undef A_int_norm_disconnected
++#undef A_int_norm_emulateintfly
++#undef A_int_norm_reselect_complete
++#undef A_int_norm_reset
++#undef A_int_norm_select_complete
++#undef A_int_test_1
++#undef A_int_test_2
++#undef A_int_test_3
++#undef A_msg_buf
++#undef A_reconnect_dsa_head
++#undef A_reselected_identify
++#undef A_reselected_tag
++#undef A_saved_dsa
++#undef A_schedule
++#undef A_test_dest
++#undef A_test_src
++#undef Ent_accept_message
++#undef Ent_cmdout_cmdout
++#undef Ent_command_complete
++#undef Ent_command_complete_msgin
++#undef Ent_data_transfer
++#undef Ent_datain_to_jump
++#undef Ent_debug_break
++#undef Ent_dsa_code_begin
++#undef Ent_dsa_code_check_reselect
++#undef Ent_dsa_code_fix_jump
++#undef Ent_dsa_code_restore_pointers
++#undef Ent_dsa_code_save_data_pointer
++#undef Ent_dsa_code_template
++#undef Ent_dsa_code_template_end
++#undef Ent_dsa_schedule
++#undef Ent_dsa_zero
++#undef Ent_end_data_transfer
++#undef Ent_initiator_abort
++#undef Ent_msg_in
++#undef Ent_msg_in_restart
++#undef Ent_other_in
++#undef Ent_other_out
++#undef Ent_other_transfer
++#undef Ent_reject_message
++#undef Ent_reselected_check_next
++#undef Ent_reselected_ok
++#undef Ent_respond_message
++#undef Ent_select
++#undef Ent_select_msgout
++#undef Ent_target_abort
++#undef Ent_test_1
++#undef Ent_test_2
++#undef Ent_test_2_msgout
++#undef Ent_wait_reselect
+diff -Nurb linux-2.6.22-590/drivers/scsi/BusLogic.c linux-2.6.22-570/drivers/scsi/BusLogic.c
+--- linux-2.6.22-590/drivers/scsi/BusLogic.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/BusLogic.c   2007-07-08 19:32:17.000000000 -0400
+@@ -304,8 +304,16 @@
+ static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB)
+ {
+       struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
++      struct scsi_cmnd *cmd = CCB->Command;
  
--      down(&buffer->sem);
-+      mutex_lock(&buffer->mutex);
-       len = fill_write_buffer(buffer, buf, count);
-       if (len > 0)
-               len = flush_write_buffer(file->f_path.dentry, buffer, count);
-       if (len > 0)
-               *ppos += len;
--      up(&buffer->sem);
-+      mutex_unlock(&buffer->mutex);
-       return len;
- }
+-      scsi_dma_unmap(CCB->Command);
++      if (cmd->use_sg != 0) {
++              pci_unmap_sg(HostAdapter->PCI_Device,
++                              (struct scatterlist *)cmd->request_buffer,
++                              cmd->use_sg, cmd->sc_data_direction);
++      } else if (cmd->request_bufflen != 0) {
++              pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer,
++                              CCB->DataLength, cmd->sc_data_direction);
++      }
+       pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer,
+                       CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
  
-@@ -253,7 +260,7 @@
-               error = -ENOMEM;
-               goto Enomem;
+@@ -2640,8 +2648,7 @@
+                        */
+                       if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 && CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) {
+                               struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[CCB->TargetID];
+-                              struct SCSI_Inquiry *InquiryResult =
+-                                      (struct SCSI_Inquiry *) scsi_sglist(Command);
++                              struct SCSI_Inquiry *InquiryResult = (struct SCSI_Inquiry *) Command->request_buffer;
+                               TargetFlags->TargetExists = true;
+                               TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
+                               TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
+@@ -2812,8 +2819,9 @@
+       int CDB_Length = Command->cmd_len;
+       int TargetID = Command->device->id;
+       int LogicalUnit = Command->device->lun;
+-      int BufferLength = scsi_bufflen(Command);
+-      int Count;
++      void *BufferPointer = Command->request_buffer;
++      int BufferLength = Command->request_bufflen;
++      int SegmentCount = Command->use_sg;
+       struct BusLogic_CCB *CCB;
+       /*
+          SCSI REQUEST_SENSE commands will be executed automatically by the Host
+@@ -2843,35 +2851,36 @@
+                       return 0;
+               }
        }
--      init_MUTEX(&buffer->sem);
-+      mutex_init(&buffer->mutex);
-       buffer->needs_read_fill = 1;
-       buffer->ops = ops;
-       file->private_data = buffer;
-@@ -292,6 +299,7 @@
-       if (buffer) {
-               if (buffer->page)
-                       free_page((unsigned long)buffer->page);
-+              mutex_destroy(&buffer->mutex);
-               kfree(buffer);
+-
+       /*
+          Initialize the fields in the BusLogic Command Control Block (CCB).
+        */
+-      Count = scsi_dma_map(Command);
+-      BUG_ON(Count < 0);
+-      if (Count) {
+-              struct scatterlist *sg;
+-              int i;
++      if (SegmentCount == 0 && BufferLength != 0) {
++              CCB->Opcode = BusLogic_InitiatorCCB;
++              CCB->DataLength = BufferLength;
++              CCB->DataPointer = pci_map_single(HostAdapter->PCI_Device,
++                              BufferPointer, BufferLength,
++                              Command->sc_data_direction);
++      } else if (SegmentCount != 0) {
++              struct scatterlist *ScatterList = (struct scatterlist *) BufferPointer;
++              int Segment, Count;
++              Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount,
++                              Command->sc_data_direction);
+               CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
+               CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment);
+               if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
+                       CCB->DataPointer = (unsigned int) CCB->DMA_Handle + ((unsigned long) &CCB->ScatterGatherList - (unsigned long) CCB);
+               else
+                       CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList);
+-
+-              scsi_for_each_sg(Command, sg, Count, i) {
+-                      CCB->ScatterGatherList[i].SegmentByteCount =
+-                              sg_dma_len(sg);
+-                      CCB->ScatterGatherList[i].SegmentDataPointer =
+-                              sg_dma_address(sg);
++              for (Segment = 0; Segment < Count; Segment++) {
++                      CCB->ScatterGatherList[Segment].SegmentByteCount = sg_dma_len(ScatterList + Segment);
++                      CCB->ScatterGatherList[Segment].SegmentDataPointer = sg_dma_address(ScatterList + Segment);
+               }
+-      } else if (!Count) {
++      } else {
+               CCB->Opcode = BusLogic_InitiatorCCB;
+               CCB->DataLength = BufferLength;
+               CCB->DataPointer = 0;
        }
-       return 0;
-diff -Nurb linux-2.6.22-570/fs/configfs/item.c linux-2.6.22-590/fs/configfs/item.c
---- linux-2.6.22-570/fs/configfs/item.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/configfs/item.c        2008-01-02 13:56:37.000000000 -0500
-@@ -62,7 +62,6 @@
-  *    dynamically allocated string that @item->ci_name points to.
-  *    Otherwise, use the static @item->ci_namebuf array.
-  */
 -
- int config_item_set_name(struct config_item * item, const char * fmt, ...)
- {
-       int error = 0;
-@@ -139,12 +138,7 @@
-       return item;
- }
+       switch (CDB[0]) {
+       case READ_6:
+       case READ_10:
+diff -Nurb linux-2.6.22-590/drivers/scsi/Kconfig linux-2.6.22-570/drivers/scsi/Kconfig
+--- linux-2.6.22-590/drivers/scsi/Kconfig      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/Kconfig      2007-07-08 19:32:17.000000000 -0400
+@@ -739,7 +739,7 @@
  
--/**
-- *    config_item_cleanup - free config_item resources.
-- *    @item:  item.
-- */
--
--void config_item_cleanup(struct config_item * item)
-+static void config_item_cleanup(struct config_item * item)
- {
-       struct config_item_type * t = item->ci_type;
-       struct config_group * s = item->ci_group;
-@@ -179,12 +173,10 @@
-               kref_put(&item->ci_kref, config_item_release);
- }
+ config SCSI_IBMMCA
+       tristate "IBMMCA SCSI support"
+-      depends on MCA && SCSI
++      depends on MCA_LEGACY && SCSI
+       ---help---
+         This is support for the IBM SCSI adapter found in many of the PS/2
+         series computers.  These machines have an MCA bus, so you need to
+@@ -1007,11 +1007,6 @@
+         To compile this driver as a module, choose M here: the
+         module will be called stex.
  
+-config 53C700_BE_BUS
+-      bool
+-      depends on SCSI_A4000T || SCSI_ZORRO7XX || MVME16x_SCSI || BVME6000_SCSI
+-      default y
 -
- /**
-  *    config_group_init - initialize a group for use
-  *    @k:     group
-  */
--
- void config_group_init(struct config_group *group)
- {
-       config_item_init(&group->cg_item);
-@@ -201,8 +193,8 @@
-  *    looking for a matching config_item. If matching item is found
-  *    take a reference and return the item.
-  */
--
--struct config_item * config_group_find_obj(struct config_group * group, const char * name)
-+struct config_item *config_group_find_obj(struct config_group *group,
-+                                        const char * name)
- {
-       struct list_head * entry;
-       struct config_item * ret = NULL;
-@@ -219,7 +211,6 @@
-       return ret;
- }
+ config SCSI_SYM53C8XX_2
+       tristate "SYM53C8XX Version 2 SCSI support"
+       depends on PCI && SCSI
+@@ -1616,25 +1611,13 @@
+         If you have the Phase5 Fastlane Z3 SCSI controller, or plan to use
+         one in the near future, say Y to this question. Otherwise, say N.
  
+-config SCSI_A4000T
+-      tristate "A4000T NCR53c710 SCSI support (EXPERIMENTAL)"
+-      depends on AMIGA && SCSI && EXPERIMENTAL
+-      select SCSI_SPI_ATTRS
++config SCSI_AMIGA7XX
++      bool "Amiga NCR53c710 SCSI support (EXPERIMENTAL)"
++      depends on AMIGA && SCSI && EXPERIMENTAL && BROKEN
+       help
+-        If you have an Amiga 4000T and have SCSI devices connected to the
+-        built-in SCSI controller, say Y. Otherwise, say N.
 -
- EXPORT_SYMBOL(config_item_init);
- EXPORT_SYMBOL(config_group_init);
- EXPORT_SYMBOL(config_item_get);
-diff -Nurb linux-2.6.22-570/fs/drop_caches.c linux-2.6.22-590/fs/drop_caches.c
---- linux-2.6.22-570/fs/drop_caches.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/drop_caches.c  2008-01-02 13:56:37.000000000 -0500
-@@ -3,6 +3,7 @@
-  */
+-        To compile this driver as a module, choose M here: the
+-        module will be called a4000t.
+-
+-config SCSI_ZORRO7XX
+-      tristate "Zorro NCR53c710 SCSI support (EXPERIMENTAL)"
+-      depends on ZORRO && SCSI && EXPERIMENTAL
+-      select SCSI_SPI_ATTRS
+-      help
+-        Support for various NCR53c710-based SCSI controllers on Zorro
+-        expansion boards for the Amiga.
++        Support for various NCR53c710-based SCSI controllers on the Amiga.
+         This includes:
++          - the builtin SCSI controller on the Amiga 4000T,
+           - the Amiga 4091 Zorro III SCSI-2 controller,
+           - the MacroSystem Development's WarpEngine Amiga SCSI-2 controller
+             (info at
+@@ -1642,6 +1625,10 @@
+           - the SCSI controller on the Phase5 Blizzard PowerUP 603e+
+             accelerator card for the Amiga 1200,
+           - the SCSI controller on the GVP Turbo 040/060 accelerator.
++        Note that all of the above SCSI controllers, except for the builtin
++        SCSI controller on the Amiga 4000T, reside on the Zorro expansion
++        bus, so you also have to enable Zorro bus support if you want to use
++        them.
  
- #include <linux/kernel.h>
-+#include <linux/module.h>
- #include <linux/mm.h>
- #include <linux/fs.h>
- #include <linux/writeback.h>
-@@ -12,7 +13,7 @@
- /* A global variable is a bit ugly, but it keeps the code simple */
- int sysctl_drop_caches;
+ config OKTAGON_SCSI
+       tristate "BSC Oktagon SCSI support (EXPERIMENTAL)"
+@@ -1725,8 +1712,8 @@
+         single-board computer.
  
--static void drop_pagecache_sb(struct super_block *sb)
-+void drop_pagecache_sb(struct super_block *sb)
- {
-       struct inode *inode;
+ config MVME16x_SCSI
+-      tristate "NCR53C710 SCSI driver for MVME16x"
+-      depends on MVME16x && SCSI
++      bool "NCR53C710 SCSI driver for MVME16x"
++      depends on MVME16x && SCSI && BROKEN
+       select SCSI_SPI_ATTRS
+       help
+         The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710
+@@ -1734,14 +1721,22 @@
+         will want to say Y to this question.
  
-@@ -24,6 +25,7 @@
-       }
-       spin_unlock(&inode_lock);
- }
-+EXPORT_SYMBOL(drop_pagecache_sb);
+ config BVME6000_SCSI
+-      tristate "NCR53C710 SCSI driver for BVME6000"
+-      depends on BVME6000 && SCSI
++      bool "NCR53C710 SCSI driver for BVME6000"
++      depends on BVME6000 && SCSI && BROKEN
+       select SCSI_SPI_ATTRS
+       help
+         The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710
+         SCSI controller chip.  Almost everyone using one of these boards
+         will want to say Y to this question.
  
- void drop_pagecache(void)
- {
-diff -Nurb linux-2.6.22-570/fs/ecryptfs/inode.c linux-2.6.22-590/fs/ecryptfs/inode.c
---- linux-2.6.22-570/fs/ecryptfs/inode.c       2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/ecryptfs/inode.c       2008-01-02 13:56:37.000000000 -0500
-@@ -280,7 +280,9 @@
-       int rc = 0;
-       struct dentry *lower_dir_dentry;
-       struct dentry *lower_dentry;
-+      struct dentry *dentry_save;
-       struct vfsmount *lower_mnt;
-+      struct vfsmount *mnt_save;
-       char *encoded_name;
-       unsigned int encoded_namelen;
-       struct ecryptfs_crypt_stat *crypt_stat = NULL;
-@@ -308,9 +310,13 @@
-       }
-       ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen "
-                       "= [%d]\n", encoded_name, encoded_namelen);
--      lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry,
--                                    encoded_namelen - 1);
-+      dentry_save = nd->dentry;
-+      mnt_save = nd->mnt;
-+      lower_dentry = lookup_one_len_nd(encoded_name, lower_dir_dentry,
-+                                       (encoded_namelen - 1), nd);
-       kfree(encoded_name);
-+      nd->mnt = mnt_save;
-+      nd->dentry = dentry_save;
-       if (IS_ERR(lower_dentry)) {
-               ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n");
-               rc = PTR_ERR(lower_dentry);
-diff -Nurb linux-2.6.22-570/fs/ecryptfs/main.c linux-2.6.22-590/fs/ecryptfs/main.c
---- linux-2.6.22-570/fs/ecryptfs/main.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ecryptfs/main.c        2008-01-02 13:56:37.000000000 -0500
-@@ -840,8 +840,6 @@
-               goto out;
-       }
-       kobj_set_kset_s(&ecryptfs_subsys, fs_subsys);
--      sysfs_attr_version.attr.owner = THIS_MODULE;
--      sysfs_attr_version_str.attr.owner = THIS_MODULE;
-       rc = do_sysfs_registration();
-       if (rc) {
-               printk(KERN_ERR "sysfs registration failed\n");
-diff -Nurb linux-2.6.22-570/fs/exec.c linux-2.6.22-590/fs/exec.c
---- linux-2.6.22-570/fs/exec.c 2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/exec.c 2008-01-02 13:56:37.000000000 -0500
-@@ -861,9 +861,9 @@
-       current->sas_ss_sp = current->sas_ss_size = 0;
++config SCSI_NCR53C7xx_FAST
++      bool "allow FAST-SCSI [10MHz]"
++      depends on SCSI_AMIGA7XX || MVME16x_SCSI || BVME6000_SCSI
++      help
++        This will enable 10MHz FAST-SCSI transfers with your host
++        adapter. Some systems have problems with that speed, so it's safest
++        to say N here.
++
+ config SUN3_SCSI
+       tristate "Sun3 NCR5380 SCSI"
+       depends on SUN3 && SCSI
+diff -Nurb linux-2.6.22-590/drivers/scsi/Makefile linux-2.6.22-570/drivers/scsi/Makefile
+--- linux-2.6.22-590/drivers/scsi/Makefile     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/Makefile     2007-07-08 19:32:17.000000000 -0400
+@@ -37,8 +37,7 @@
  
-       if (current->euid == current->uid && current->egid == current->gid)
--              current->mm->dumpable = 1;
-+              set_dumpable(current->mm, 1);
-       else
--              current->mm->dumpable = suid_dumpable;
-+              set_dumpable(current->mm, suid_dumpable);
+ obj-$(CONFIG_ISCSI_TCP)       += libiscsi.o   iscsi_tcp.o
+ obj-$(CONFIG_INFINIBAND_ISER)         += libiscsi.o
+-obj-$(CONFIG_SCSI_A4000T)     += 53c700.o     a4000t.o
+-obj-$(CONFIG_SCSI_ZORRO7XX)   += 53c700.o     zorro7xx.o
++obj-$(CONFIG_SCSI_AMIGA7XX)   += amiga7xx.o   53c7xx.o
+ obj-$(CONFIG_A3000_SCSI)      += a3000.o      wd33c93.o
+ obj-$(CONFIG_A2091_SCSI)      += a2091.o      wd33c93.o
+ obj-$(CONFIG_GVP11_SCSI)      += gvp11.o      wd33c93.o
+@@ -54,8 +53,8 @@
+ obj-$(CONFIG_MAC_SCSI)                += mac_scsi.o
+ obj-$(CONFIG_SCSI_MAC_ESP)    += mac_esp.o    NCR53C9x.o
+ obj-$(CONFIG_SUN3_SCSI)               += sun3_scsi.o  sun3_scsi_vme.o
+-obj-$(CONFIG_MVME16x_SCSI)    += 53c700.o     mvme16x_scsi.o
+-obj-$(CONFIG_BVME6000_SCSI)   += 53c700.o     bvme6000_scsi.o
++obj-$(CONFIG_MVME16x_SCSI)    += mvme16x.o    53c7xx.o
++obj-$(CONFIG_BVME6000_SCSI)   += bvme6000.o   53c7xx.o
+ obj-$(CONFIG_SCSI_SIM710)     += 53c700.o     sim710.o
+ obj-$(CONFIG_SCSI_ADVANSYS)   += advansys.o
+ obj-$(CONFIG_SCSI_PSI240I)    += psi240i.o
+@@ -169,8 +168,10 @@
+ oktagon_esp_mod-objs  := oktagon_esp.o oktagon_io.o
  
-       name = bprm->filename;
+ # Files generated that shall be removed upon make clean
+-clean-files :=        53c700_d.h 53c700_u.h
++clean-files :=        53c7xx_d.h 53c700_d.h   \
++              53c7xx_u.h 53c700_u.h
  
-@@ -889,12 +889,12 @@
++$(obj)/53c7xx.o:   $(obj)/53c7xx_d.h $(obj)/53c7xx_u.h
+ $(obj)/53c700.o $(MODVERDIR)/$(obj)/53c700.ver: $(obj)/53c700_d.h
  
-       if (bprm->e_uid != current->euid || bprm->e_gid != current->egid) {
-               suid_keys(current);
--              current->mm->dumpable = suid_dumpable;
-+              set_dumpable(current->mm, suid_dumpable);
-               current->pdeath_signal = 0;
-       } else if (file_permission(bprm->file, MAY_READ) ||
-                       (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
-               suid_keys(current);
--              current->mm->dumpable = suid_dumpable;
-+              set_dumpable(current->mm, suid_dumpable);
-       }
+ # If you want to play with the firmware, uncomment
+@@ -178,6 +179,11 @@
  
-       /* An exec changes our domain. We are no longer part of the thread
-@@ -1486,6 +1486,55 @@
-       return core_waiters;
- }
+ ifdef GENERATE_FIRMWARE
  
-+/*
-+ * set_dumpable converts traditional three-value dumpable to two flags and
-+ * stores them into mm->flags.  It modifies lower two bits of mm->flags, but
-+ * these bits are not changed atomically.  So get_dumpable can observe the
-+ * intermediate state.  To avoid doing unexpected behavior, get get_dumpable
-+ * return either old dumpable or new one by paying attention to the order of
-+ * modifying the bits.
-+ *
-+ * dumpable |   mm->flags (binary)
-+ * old  new | initial interim  final
-+ * ---------+-----------------------
-+ *  0    1  |   00      01      01
-+ *  0    2  |   00      10(*)   11
-+ *  1    0  |   01      00      00
-+ *  1    2  |   01      11      11
-+ *  2    0  |   11      10(*)   00
-+ *  2    1  |   11      11      01
-+ *
-+ * (*) get_dumpable regards interim value of 10 as 11.
-+ */
-+void set_dumpable(struct mm_struct *mm, int value)
-+{
-+      switch (value) {
-+      case 0:
-+              clear_bit(MMF_DUMPABLE, &mm->flags);
-+              smp_wmb();
-+              clear_bit(MMF_DUMP_SECURELY, &mm->flags);
-+              break;
-+      case 1:
-+              set_bit(MMF_DUMPABLE, &mm->flags);
-+              smp_wmb();
-+              clear_bit(MMF_DUMP_SECURELY, &mm->flags);
-+              break;
-+      case 2:
-+              set_bit(MMF_DUMP_SECURELY, &mm->flags);
-+              smp_wmb();
-+              set_bit(MMF_DUMPABLE, &mm->flags);
-+              break;
-+      }
-+}
-+
-+int get_dumpable(struct mm_struct *mm)
-+{
-+      int ret;
-+
-+      ret = mm->flags & 0x3;
-+      return (ret >= 2) ? 2 : ret;
-+}
++$(obj)/53c7xx_d.h: $(src)/53c7xx.scr $(src)/script_asm.pl
++      $(CPP) -traditional -DCHIP=710 - < $< | grep -v '^#' | $(PERL) -s $(src)/script_asm.pl -ncr7x0_family $@ $(@:_d.h=_u.h)
 +
- int do_coredump(long signr, int exit_code, struct pt_regs * regs)
- {
-       char corename[CORENAME_MAX_SIZE + 1];
-@@ -1504,7 +1553,7 @@
-       if (!binfmt || !binfmt->core_dump)
-               goto fail;
-       down_write(&mm->mmap_sem);
--      if (!mm->dumpable) {
-+      if (!get_dumpable(mm)) {
-               up_write(&mm->mmap_sem);
-               goto fail;
-       }
-@@ -1514,11 +1563,11 @@
-        *      process nor do we know its entire history. We only know it
-        *      was tainted so we dump it as root in mode 2.
-        */
--      if (mm->dumpable == 2) {        /* Setuid core dump mode */
-+      if (get_dumpable(mm) == 2) {    /* Setuid core dump mode */
-               flag = O_EXCL;          /* Stop rewrite attacks */
-               current->fsuid = 0;     /* Dump root private */
-       }
--      mm->dumpable = 0;
-+      set_dumpable(mm, 0);
-       retval = coredump_wait(exit_code);
-       if (retval < 0)
-diff -Nurb linux-2.6.22-570/fs/gfs2/ops_address.c linux-2.6.22-590/fs/gfs2/ops_address.c
---- linux-2.6.22-570/fs/gfs2/ops_address.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/gfs2/ops_address.c     2008-01-02 13:56:37.000000000 -0500
-@@ -250,7 +250,7 @@
-               if (file) {
-                       gf = file->private_data;
-                       if (test_bit(GFF_EXLOCK, &gf->f_flags))
--                              /* gfs2_sharewrite_nopage has grabbed the ip->i_gl already */
-+                              /* gfs2_sharewrite_fault has grabbed the ip->i_gl already */
-                               goto skip_lock;
-               }
-               gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh);
-diff -Nurb linux-2.6.22-570/fs/gfs2/ops_file.c linux-2.6.22-590/fs/gfs2/ops_file.c
---- linux-2.6.22-570/fs/gfs2/ops_file.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/gfs2/ops_file.c        2008-01-02 13:56:37.000000000 -0500
-@@ -364,6 +364,8 @@
-       else
-               vma->vm_ops = &gfs2_vm_ops_private;
-+      vma->vm_flags |= VM_CAN_INVALIDATE|VM_CAN_NONLINEAR;
++$(obj)/53c7xx_u.h: $(obj)/53c7xx_d.h
 +
-       gfs2_glock_dq_uninit(&i_gh);
-       return error;
-diff -Nurb linux-2.6.22-570/fs/gfs2/ops_vm.c linux-2.6.22-590/fs/gfs2/ops_vm.c
---- linux-2.6.22-570/fs/gfs2/ops_vm.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/gfs2/ops_vm.c  2008-01-02 13:56:37.000000000 -0500
-@@ -27,13 +27,13 @@
- #include "trans.h"
- #include "util.h"
--static struct page *gfs2_private_nopage(struct vm_area_struct *area,
--                                      unsigned long address, int *type)
-+static struct page *gfs2_private_fault(struct vm_area_struct *vma,
-+                                      struct fault_data *fdata)
- {
--      struct gfs2_inode *ip = GFS2_I(area->vm_file->f_mapping->host);
-+      struct gfs2_inode *ip = GFS2_I(vma->vm_file->f_mapping->host);
-       set_bit(GIF_PAGED, &ip->i_flags);
--      return filemap_nopage(area, address, type);
-+      return filemap_fault(vma, fdata);
- }
+ $(obj)/53c700_d.h: $(src)/53c700.scr $(src)/script_asm.pl
+       $(PERL) -s $(src)/script_asm.pl -ncr7x0_family $@ $(@:_d.h=_u.h) < $<
  
- static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
-@@ -104,16 +104,14 @@
-       return error;
- }
+diff -Nurb linux-2.6.22-590/drivers/scsi/NCR5380.c linux-2.6.22-570/drivers/scsi/NCR5380.c
+--- linux-2.6.22-590/drivers/scsi/NCR5380.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/NCR5380.c    2007-07-08 19:32:17.000000000 -0400
+@@ -347,7 +347,7 @@
+               if((r & bit) == val)
+                       return 0;
+               if(!in_interrupt())
+-                      cond_resched();
++                      yield();
+               else
+                       cpu_relax();
+       }
+@@ -357,7 +357,7 @@
+ static struct {
+       unsigned char value;
+       const char *name;
+-} phases[] __maybe_unused = {
++} phases[] = {
+       {PHASE_DATAOUT, "DATAOUT"}, 
+       {PHASE_DATAIN, "DATAIN"}, 
+       {PHASE_CMDOUT, "CMDOUT"}, 
+@@ -575,8 +575,7 @@
+  *    Locks: none, irqs must be enabled on entry
+  */
  
--static struct page *gfs2_sharewrite_nopage(struct vm_area_struct *area,
--                                         unsigned long address, int *type)
-+static struct page *gfs2_sharewrite_fault(struct vm_area_struct *vma,
-+                                              struct fault_data *fdata)
+-static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
+-                                              int possible)
++static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
  {
--      struct file *file = area->vm_file;
-+      struct file *file = vma->vm_file;
-       struct gfs2_file *gf = file->private_data;
-       struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
-       struct gfs2_holder i_gh;
-       struct page *result = NULL;
--      unsigned long index = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) +
--                            area->vm_pgoff;
-       int alloc_required;
-       int error;
-@@ -124,21 +122,27 @@
-       set_bit(GIF_PAGED, &ip->i_flags);
-       set_bit(GIF_SW_PAGED, &ip->i_flags);
--      error = gfs2_write_alloc_required(ip, (u64)index << PAGE_CACHE_SHIFT,
-+      error = gfs2_write_alloc_required(ip,
-+                                      (u64)fdata->pgoff << PAGE_CACHE_SHIFT,
-                                         PAGE_CACHE_SIZE, &alloc_required);
--      if (error)
-+      if (error) {
-+              fdata->type = VM_FAULT_OOM; /* XXX: are these right? */
-               goto out;
-+      }
-       set_bit(GFF_EXLOCK, &gf->f_flags);
--      result = filemap_nopage(area, address, type);
-+      result = filemap_fault(vma, fdata);
-       clear_bit(GFF_EXLOCK, &gf->f_flags);
--      if (!result || result == NOPAGE_OOM)
-+      if (!result)
-               goto out;
-       if (alloc_required) {
-               error = alloc_page_backing(ip, result);
-               if (error) {
-+                      if (vma->vm_flags & VM_CAN_INVALIDATE)
-+                              unlock_page(result);
-                       page_cache_release(result);
-+                      fdata->type = VM_FAULT_OOM;
-                       result = NULL;
-                       goto out;
-               }
-@@ -152,10 +156,10 @@
- }
- struct vm_operations_struct gfs2_vm_ops_private = {
--      .nopage = gfs2_private_nopage,
-+      .fault = gfs2_private_fault,
- };
- struct vm_operations_struct gfs2_vm_ops_sharewrite = {
--      .nopage = gfs2_sharewrite_nopage,
-+      .fault = gfs2_sharewrite_fault,
- };
-diff -Nurb linux-2.6.22-570/fs/inode.c linux-2.6.22-590/fs/inode.c
---- linux-2.6.22-570/fs/inode.c        2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/inode.c        2008-01-02 13:56:37.000000000 -0500
-@@ -149,7 +149,7 @@
-               mapping->a_ops = &empty_aops;
-               mapping->host = inode;
-               mapping->flags = 0;
--              mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
-+              mapping_set_gfp_mask(mapping, GFP_HIGHUSER_PAGECACHE);
-               mapping->assoc_mapping = NULL;
-               mapping->backing_dev_info = &default_backing_dev_info;
-@@ -525,7 +525,13 @@
-  *    new_inode       - obtain an inode
-  *    @sb: superblock
-  *
-- *    Allocates a new inode for given superblock.
-+ *    Allocates a new inode for given superblock. The default gfp_mask
-+ *    for allocations related to inode->i_mapping is GFP_HIGHUSER_PAGECACHE.
-+ *    If HIGHMEM pages are unsuitable or it is known that pages allocated
-+ *    for the page cache are not reclaimable or migratable,
-+ *    mapping_set_gfp_mask() must be called with suitable flags on the
-+ *    newly created inode's mapping
-+ *
+       NCR5380_local_declare();
+       struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
+@@ -630,8 +629,7 @@
+  *    Locks: none
   */
- struct inode *new_inode(struct super_block *sb)
- {
-diff -Nurb linux-2.6.22-570/fs/jbd/journal.c linux-2.6.22-590/fs/jbd/journal.c
---- linux-2.6.22-570/fs/jbd/journal.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/jbd/journal.c  2008-01-02 13:56:37.000000000 -0500
-@@ -1710,7 +1710,7 @@
-       journal_head_cache = kmem_cache_create("journal_head",
-                               sizeof(struct journal_head),
-                               0,              /* offset */
--                              0,              /* flags */
-+                              SLAB_TEMPORARY, /* flags */
-                               NULL,           /* ctor */
-                               NULL);          /* dtor */
-       retval = 0;
-@@ -2007,7 +2007,7 @@
-       jbd_handle_cache = kmem_cache_create("journal_handle",
-                               sizeof(handle_t),
-                               0,              /* offset */
--                              0,              /* flags */
-+                              SLAB_TEMPORARY, /* flags */
-                               NULL,           /* ctor */
-                               NULL);          /* dtor */
-       if (jbd_handle_cache == NULL) {
-diff -Nurb linux-2.6.22-570/fs/jbd/revoke.c linux-2.6.22-590/fs/jbd/revoke.c
---- linux-2.6.22-570/fs/jbd/revoke.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/jbd/revoke.c   2008-01-02 13:56:37.000000000 -0500
-@@ -169,13 +169,17 @@
- {
-       revoke_record_cache = kmem_cache_create("revoke_record",
-                                          sizeof(struct jbd_revoke_record_s),
--                                         0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-+                                         0,
-+                                         SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY,
-+                                         NULL, NULL);
-       if (revoke_record_cache == 0)
-               return -ENOMEM;
  
-       revoke_table_cache = kmem_cache_create("revoke_table",
-                                          sizeof(struct jbd_revoke_table_s),
--                                         0, 0, NULL, NULL);
-+                                         0,
-+                                         SLAB_TEMPORARY,
-+                                         NULL, NULL);
-       if (revoke_table_cache == 0) {
-               kmem_cache_destroy(revoke_record_cache);
-               revoke_record_cache = NULL;
-diff -Nurb linux-2.6.22-570/fs/jffs2/background.c linux-2.6.22-590/fs/jffs2/background.c
---- linux-2.6.22-570/fs/jffs2/background.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/jffs2/background.c     2008-01-02 13:56:37.000000000 -0500
-@@ -81,6 +81,7 @@
-       set_user_nice(current, 10);
-+      set_freezable();
-       for (;;) {
-               allow_signal(SIGHUP);
-diff -Nurb linux-2.6.22-570/fs/lockd/host.c linux-2.6.22-590/fs/lockd/host.c
---- linux-2.6.22-570/fs/lockd/host.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/lockd/host.c   2008-01-02 13:56:37.000000000 -0500
-@@ -161,15 +161,9 @@
-        */
-       nsm_unmonitor(host);
--      if ((clnt = host->h_rpcclnt) != NULL) {
--              if (atomic_read(&clnt->cl_users)) {
--                      printk(KERN_WARNING
--                              "lockd: active RPC handle\n");
--                      clnt->cl_dead = 1;
--              } else {
--                      rpc_destroy_client(host->h_rpcclnt);
--              }
--      }
-+      clnt = host->h_rpcclnt;
-+      if (clnt != NULL)
-+              rpc_shutdown_client(clnt);
-       kfree(host);
- }
-diff -Nurb linux-2.6.22-570/fs/lockd/mon.c linux-2.6.22-590/fs/lockd/mon.c
---- linux-2.6.22-570/fs/lockd/mon.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/lockd/mon.c    2008-01-02 13:56:37.000000000 -0500
-@@ -61,6 +61,7 @@
-                       status);
-       else
-               status = 0;
-+      rpc_shutdown_client(clnt);
-  out:
-       return status;
- }
-@@ -138,7 +139,6 @@
-               .program        = &nsm_program,
-               .version        = SM_VERSION,
-               .authflavor     = RPC_AUTH_NULL,
--              .flags          = (RPC_CLNT_CREATE_ONESHOT),
-       };
+-static void __init __maybe_unused
+-NCR5380_print_options(struct Scsi_Host *instance)
++static void __init NCR5380_print_options(struct Scsi_Host *instance)
+ {
+       printk(" generic options"
+ #ifdef AUTOPROBE_IRQ
+@@ -705,8 +703,8 @@
+ static
+ char *lprint_opcode(int opcode, char *pos, char *buffer, int length);
  
-       return rpc_create(&args);
-diff -Nurb linux-2.6.22-570/fs/lockd/svc.c linux-2.6.22-590/fs/lockd/svc.c
---- linux-2.6.22-570/fs/lockd/svc.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/lockd/svc.c    2008-01-02 13:56:37.000000000 -0500
-@@ -25,6 +25,7 @@
- #include <linux/smp.h>
- #include <linux/smp_lock.h>
- #include <linux/mutex.h>
-+#include <linux/freezer.h>
+-static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
+-      char *buffer, char **start, off_t offset, int length, int inout)
++static
++int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, off_t offset, int length, int inout)
+ {
+       char *pos = buffer;
+       struct NCR5380_hostdata *hostdata;
+diff -Nurb linux-2.6.22-590/drivers/scsi/NCR5380.h linux-2.6.22-570/drivers/scsi/NCR5380.h
+--- linux-2.6.22-590/drivers/scsi/NCR5380.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/NCR5380.h    2007-07-08 19:32:17.000000000 -0400
+@@ -299,7 +299,7 @@
+ static irqreturn_t NCR5380_intr(int irq, void *dev_id);
+ #endif
+ static void NCR5380_main(struct work_struct *work);
+-static void __maybe_unused NCR5380_print_options(struct Scsi_Host *instance);
++static void NCR5380_print_options(struct Scsi_Host *instance);
+ #ifdef NDEBUG
+ static void NCR5380_print_phase(struct Scsi_Host *instance);
+ static void NCR5380_print(struct Scsi_Host *instance);
+@@ -307,8 +307,8 @@
+ static int NCR5380_abort(Scsi_Cmnd * cmd);
+ static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
+ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
+-static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
+-      char *buffer, char **start, off_t offset, int length, int inout);
++static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
++off_t offset, int length, int inout);
  
- #include <linux/sunrpc/types.h>
- #include <linux/sunrpc/stats.h>
-@@ -119,13 +120,11 @@
-       complete(&lockd_start_done);
+ static void NCR5380_reselect(struct Scsi_Host *instance);
+ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
+diff -Nurb linux-2.6.22-590/drivers/scsi/NCR53c406a.c linux-2.6.22-570/drivers/scsi/NCR53c406a.c
+--- linux-2.6.22-590/drivers/scsi/NCR53c406a.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/NCR53c406a.c 2007-07-08 19:32:17.000000000 -0400
+@@ -698,7 +698,7 @@
+       int i;
  
-       daemonize("lockd");
-+      set_freezable();
+       VDEB(printk("NCR53c406a_queue called\n"));
+-      DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, scsi_bufflen(SCpnt)));
++      DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, SCpnt->request_bufflen));
  
-       /* Process request with signals blocked, but allow SIGKILL.  */
-       allow_signal(SIGKILL);
+ #if 0
+       VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
+@@ -785,8 +785,8 @@
+       unsigned char status, int_reg;
+ #if USE_PIO
+       unsigned char pio_status;
+-      struct scatterlist *sg;
+-        int i;
++      struct scatterlist *sglist;
++      unsigned int sgcount;
+ #endif
  
--      /* kick rpciod */
--      rpciod_up();
+       VDEB(printk("NCR53c406a_intr called\n"));
+@@ -866,17 +866,21 @@
+                       current_SC->SCp.phase = data_out;
+                       VDEB(printk("NCR53c406a: Data-Out phase\n"));
+                       outb(FLUSH_FIFO, CMD_REG);
+-                      LOAD_DMA_COUNT(scsi_bufflen(current_SC));       /* Max transfer size */
++                      LOAD_DMA_COUNT(current_SC->request_bufflen);    /* Max transfer size */
+ #if USE_DMA                   /* No s/g support for DMA */
+-                      NCR53c406a_dma_write(scsi_sglist(current_SC),
+-                                             scsdi_bufflen(current_SC));
 -
-       dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
++                      NCR53c406a_dma_write(current_SC->request_buffer, current_SC->request_bufflen);
+ #endif                                /* USE_DMA */
+                       outb(TRANSFER_INFO | DMA_OP, CMD_REG);
+ #if USE_PIO
+-                        scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) {
+-                                NCR53c406a_pio_write(page_address(sg->page) + sg->offset,
+-                                                     sg->length);
++                      if (!current_SC->use_sg)        /* Don't use scatter-gather */
++                              NCR53c406a_pio_write(current_SC->request_buffer, current_SC->request_bufflen);
++                      else {  /* use scatter-gather */
++                              sgcount = current_SC->use_sg;
++                              sglist = current_SC->request_buffer;
++                              while (sgcount--) {
++                                      NCR53c406a_pio_write(page_address(sglist->page) + sglist->offset, sglist->length);
++                                      sglist++;
++                              }
+                       }
+                       REG0;
+ #endif                                /* USE_PIO */
+@@ -889,16 +893,21 @@
+                       current_SC->SCp.phase = data_in;
+                       VDEB(printk("NCR53c406a: Data-In phase\n"));
+                       outb(FLUSH_FIFO, CMD_REG);
+-                      LOAD_DMA_COUNT(scsi_bufflen(current_SC));       /* Max transfer size */
++                      LOAD_DMA_COUNT(current_SC->request_bufflen);    /* Max transfer size */
+ #if USE_DMA                   /* No s/g support for DMA */
+-                      NCR53c406a_dma_read(scsi_sglist(current_SC),
+-                                            scsdi_bufflen(current_SC));
++                      NCR53c406a_dma_read(current_SC->request_buffer, current_SC->request_bufflen);
+ #endif                                /* USE_DMA */
+                       outb(TRANSFER_INFO | DMA_OP, CMD_REG);
+ #if USE_PIO
+-                        scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) {
+-                                NCR53c406a_pio_read(page_address(sg->page) + sg->offset,
+-                                                    sg->length);
++                      if (!current_SC->use_sg)        /* Don't use scatter-gather */
++                              NCR53c406a_pio_read(current_SC->request_buffer, current_SC->request_bufflen);
++                      else {  /* Use scatter-gather */
++                              sgcount = current_SC->use_sg;
++                              sglist = current_SC->request_buffer;
++                              while (sgcount--) {
++                                      NCR53c406a_pio_read(page_address(sglist->page) + sglist->offset, sglist->length);
++                                      sglist++;
++                              }
+                       }
+                       REG0;
+ #endif                                /* USE_PIO */
+diff -Nurb linux-2.6.22-590/drivers/scsi/a100u2w.c linux-2.6.22-570/drivers/scsi/a100u2w.c
+--- linux-2.6.22-590/drivers/scsi/a100u2w.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/a100u2w.c    2007-07-08 19:32:17.000000000 -0400
+@@ -19,6 +19,27 @@
+  * along with this program; see the file COPYING.  If not, write to
+  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+  *
++ * --------------------------------------------------------------------------
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions, and the following disclaimer,
++ *    without modification, immediately at the beginning of the file.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ * Where this Software is combined with software released under the terms of 
++ * the GNU General Public License ("GPL") and the terms of the GPL would require the 
++ * combined work to also be released under the terms of the GPL, the terms
++ * and conditions of this License will apply in addition to those of the
++ * GPL with the exception of any terms or conditions of this License that
++ * conflict with, or are expressly prohibited by, the GPL.
++ *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+@@ -54,8 +75,6 @@
+  * 9/28/04 Christoph Hellwig <hch@lst.de>
+  *        - merge the two source files
+  *        - remove internal queueing code
+- * 14/06/07 Alan Cox <alan@redhat.com>
+- *     - Grand cleanup and Linuxisation
+  */
  
-       if (!nlm_timeout)
-@@ -202,9 +201,6 @@
-       /* Exit the RPC thread */
-       svc_exit_thread(rqstp);
+ #include <linux/module.h>
+@@ -83,12 +102,14 @@
+ #include "a100u2w.h"
  
--      /* release rpciod */
--      rpciod_down();
--
-       /* Release module */
-       unlock_kernel();
-       module_put_and_exit(0);
-diff -Nurb linux-2.6.22-570/fs/namei.c linux-2.6.22-590/fs/namei.c
---- linux-2.6.22-570/fs/namei.c        2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/namei.c        2008-01-02 13:56:37.000000000 -0500
-@@ -1386,7 +1386,8 @@
-       return 0;
- }
  
--struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
-+struct dentry *lookup_one_len_nd(const char *name, struct dentry *base, 
-+                               int len, struct nameidata *nd)
+-static struct orc_scb *__orc_alloc_scb(struct orc_host * host);
+-static void inia100_scb_handler(struct orc_host *host, struct orc_scb *scb);
++#define JIFFIES_TO_MS(t) ((t) * 1000 / HZ)
++#define MS_TO_JIFFIES(j) ((j * HZ) / 1000)
+-static struct orc_nvram nvram, *nvramp = &nvram;
++static ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
++static void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
+-static u8 default_nvram[64] =
++static NVRAM nvram, *nvramp = &nvram;
++static UCHAR dftNvRam[64] =
  {
-       int err;
-       struct qstr this;
-@@ -1394,7 +1395,7 @@
-       err = __lookup_one_len(name, &this, base, len);
-       if (err)
-               return ERR_PTR(err);
--      return __lookup_hash(&this, base, NULL);
-+      return __lookup_hash(&this, base, nd);
- }
+ /*----------header -------------*/
+       0x01,                   /* 0x00: Sub System Vendor ID 0 */
+@@ -137,882 +158,823 @@
+ };
  
- struct dentry *lookup_one_len_kern(const char *name, struct dentry *base, int len)
-@@ -3086,7 +3087,7 @@
- EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
- EXPORT_SYMBOL(getname);
- EXPORT_SYMBOL(lock_rename);
--EXPORT_SYMBOL(lookup_one_len);
-+EXPORT_SYMBOL(lookup_one_len_nd);
- EXPORT_SYMBOL(page_follow_link_light);
- EXPORT_SYMBOL(page_put_link);
- EXPORT_SYMBOL(page_readlink);
-diff -Nurb linux-2.6.22-570/fs/namespace.c linux-2.6.22-590/fs/namespace.c
---- linux-2.6.22-570/fs/namespace.c    2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/namespace.c    2008-01-02 13:56:37.000000000 -0500
-@@ -1538,7 +1538,7 @@
  
-       new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
-       if (!new_ns)
--              return NULL;
-+              return ERR_PTR(-ENOMEM);
+-static u8 wait_chip_ready(struct orc_host * host)
++/***************************************************************************/
++static void waitForPause(unsigned amount)
++{
++      ULONG the_time = jiffies + MS_TO_JIFFIES(amount);
++      while (time_before_eq(jiffies, the_time))
++              cpu_relax();
++}
++
++/***************************************************************************/
++static UCHAR waitChipReady(ORC_HCS * hcsp)
+ {
+       int i;
  
-       atomic_set(&new_ns->count, 1);
-       INIT_LIST_HEAD(&new_ns->list);
-@@ -1552,7 +1552,7 @@
-       if (!new_ns->root) {
-               up_write(&namespace_sem);
-               kfree(new_ns);
--              return NULL;
-+              return ERR_PTR(-ENOMEM);;
+       for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
+-              if (inb(host->base + ORC_HCTRL) & HOSTSTOP)     /* Wait HOSTSTOP set */
++              if (ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HOSTSTOP)       /* Wait HOSTSTOP set */
+                       return 1;
+-              mdelay(100);
++              waitForPause(100);      /* wait 100ms before try again  */
        }
-       spin_lock(&vfsmount_lock);
-       list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
-@@ -1597,7 +1597,7 @@
-       return new_ns;
+       return 0;
  }
  
--struct mnt_namespace *copy_mnt_ns(int flags, struct mnt_namespace *ns,
-+struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
-               struct fs_struct *new_fs)
- {
-       struct mnt_namespace *new_ns;
-diff -Nurb linux-2.6.22-570/fs/ncpfs/mmap.c linux-2.6.22-590/fs/ncpfs/mmap.c
---- linux-2.6.22-570/fs/ncpfs/mmap.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ncpfs/mmap.c   2008-01-02 13:56:37.000000000 -0500
-@@ -25,8 +25,8 @@
- /*
-  * Fill in the supplied page for mmap
-  */
--static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
--                                   unsigned long address, int *type)
-+static struct page* ncp_file_mmap_fault(struct vm_area_struct *area,
-+                                              struct fault_data *fdata)
+-static u8 wait_firmware_ready(struct orc_host * host)
++/***************************************************************************/
++static UCHAR waitFWReady(ORC_HCS * hcsp)
  {
-       struct file *file = area->vm_file;
-       struct dentry *dentry = file->f_path.dentry;
-@@ -40,15 +40,17 @@
-       page = alloc_page(GFP_HIGHUSER); /* ncpfs has nothing against high pages
-                  as long as recvmsg and memset works on it */
--      if (!page)
--              return page;
-+      if (!page) {
-+              fdata->type = VM_FAULT_OOM;
-+              return NULL;
-+      }
-       pg_addr = kmap(page);
--      address &= PAGE_MASK;
--      pos = address - area->vm_start + (area->vm_pgoff << PAGE_SHIFT);
-+      pos = fdata->pgoff << PAGE_SHIFT;
+       int i;
  
-       count = PAGE_SIZE;
--      if (address + PAGE_SIZE > area->vm_end) {
--              count = area->vm_end - address;
-+      if (fdata->address + PAGE_SIZE > area->vm_end) {
-+              WARN_ON(1); /* shouldn't happen? */
-+              count = area->vm_end - fdata->address;
+       for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
+-              if (inb(host->base + ORC_HSTUS) & RREADY)               /* Wait READY set */
++              if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY)         /* Wait READY set */
+                       return 1;
+-              mdelay(100);    /* wait 100ms before try again  */
++              waitForPause(100);      /* wait 100ms before try again  */
        }
-       /* what we can read in one go */
-       bufsize = NCP_SERVER(inode)->buffer_size;
-@@ -91,15 +93,14 @@
-        * fetches from the network, here the analogue of disk.
-        * -- wli
-        */
--      if (type)
--              *type = VM_FAULT_MAJOR;
-+      fdata->type = VM_FAULT_MAJOR;
-       count_vm_event(PGMAJFAULT);
-       return page;
+       return 0;
  }
  
- static struct vm_operations_struct ncp_file_mmap =
+ /***************************************************************************/
+-static u8 wait_scsi_reset_done(struct orc_host * host)
++static UCHAR waitSCSIRSTdone(ORC_HCS * hcsp)
  {
--      .nopage = ncp_file_mmap_nopage,
-+      .fault = ncp_file_mmap_fault,
- };
-@@ -123,6 +124,7 @@
-               return -EFBIG;
+       int i;
  
-       vma->vm_ops = &ncp_file_mmap;
-+      vma->vm_flags |= VM_CAN_INVALIDATE;
-       file_accessed(file);
+       for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
+-              if (!(inb(host->base + ORC_HCTRL) & SCSIRST))   /* Wait SCSIRST done */
++              if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & SCSIRST))     /* Wait SCSIRST done */
+                       return 1;
+-              mdelay(100);    /* wait 100ms before try again  */
++              waitForPause(100);      /* wait 100ms before try again  */
+       }
        return 0;
  }
-diff -Nurb linux-2.6.22-570/fs/nfs/callback.c linux-2.6.22-590/fs/nfs/callback.c
---- linux-2.6.22-570/fs/nfs/callback.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/callback.c 2008-01-02 13:56:37.000000000 -0500
-@@ -14,6 +14,7 @@
- #include <linux/sunrpc/svcsock.h>
- #include <linux/nfs_fs.h>
- #include <linux/mutex.h>
-+#include <linux/freezer.h>
- #include <net/inet_sock.h>
  
-@@ -67,6 +68,7 @@
-       daemonize("nfsv4-svc");
-       /* Process request with signals blocked, but allow SIGKILL.  */
-       allow_signal(SIGKILL);
-+      set_freezable();
-       complete(&nfs_callback_info.started);
-diff -Nurb linux-2.6.22-570/fs/nfs/client.c linux-2.6.22-590/fs/nfs/client.c
---- linux-2.6.22-570/fs/nfs/client.c   2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/nfs/client.c   2008-01-02 13:56:37.000000000 -0500
-@@ -102,19 +102,10 @@
-                                          int nfsversion)
+ /***************************************************************************/
+-static u8 wait_HDO_off(struct orc_host * host)
++static UCHAR waitHDOoff(ORC_HCS * hcsp)
  {
-       struct nfs_client *clp;
--      int error;
-       if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
-               goto error_0;
--      error = rpciod_up();
--      if (error < 0) {
--              dprintk("%s: couldn't start rpciod! Error = %d\n",
--                              __FUNCTION__, error);
--              goto error_1;
--      }
--      __set_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
--
-       if (nfsversion == 4) {
-               if (nfs_callback_up() < 0)
-                       goto error_2;
-@@ -154,9 +145,6 @@
-       if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
-               nfs_callback_down();
- error_2:
--      rpciod_down();
--      __clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
--error_1:
-       kfree(clp);
- error_0:
-       return NULL;
-@@ -198,9 +186,6 @@
-       if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
-               nfs_callback_down();
--      if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state))
--              rpciod_down();
--
-       kfree(clp->cl_hostname);
-       kfree(clp);
-diff -Nurb linux-2.6.22-570/fs/nfs/delegation.c linux-2.6.22-590/fs/nfs/delegation.c
---- linux-2.6.22-570/fs/nfs/delegation.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/delegation.c       2008-01-02 13:56:37.000000000 -0500
-@@ -74,7 +74,7 @@
-                       continue;
-               get_nfs_open_context(ctx);
-               spin_unlock(&inode->i_lock);
--              err = nfs4_open_delegation_recall(ctx->dentry, state);
-+              err = nfs4_open_delegation_recall(ctx, state);
-               if (err >= 0)
-                       err = nfs_delegation_claim_locks(ctx, state);
-               put_nfs_open_context(ctx);
-diff -Nurb linux-2.6.22-570/fs/nfs/delegation.h linux-2.6.22-590/fs/nfs/delegation.h
---- linux-2.6.22-570/fs/nfs/delegation.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/delegation.h       2008-01-02 13:56:37.000000000 -0500
-@@ -39,7 +39,7 @@
- /* NFSv4 delegation-related procedures */
- int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
--int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
-+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state);
- int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
- int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
+       int i;
  
-diff -Nurb linux-2.6.22-570/fs/nfs/dir.c linux-2.6.22-590/fs/nfs/dir.c
---- linux-2.6.22-570/fs/nfs/dir.c      2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/nfs/dir.c      2008-01-02 13:56:37.000000000 -0500
-@@ -898,14 +898,13 @@
-       return (nd->intent.open.flags & O_EXCL) != 0;
+       for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
+-              if (!(inb(host->base + ORC_HCTRL) & HDO))               /* Wait HDO off */
++              if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HDO))         /* Wait HDO off */
+                       return 1;
+-              mdelay(100);    /* wait 100ms before try again  */
++              waitForPause(100);      /* wait 100ms before try again  */
+       }
+       return 0;
  }
  
--static inline int nfs_reval_fsid(struct vfsmount *mnt, struct inode *dir,
--                               struct nfs_fh *fh, struct nfs_fattr *fattr)
-+static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr)
+ /***************************************************************************/
+-static u8 wait_hdi_set(struct orc_host * host, u8 * data)
++static UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData)
  {
-       struct nfs_server *server = NFS_SERVER(dir);
+       int i;
  
-       if (!nfs_fsid_equal(&server->fsid, &fattr->fsid))
--              /* Revalidate fsid on root dir */
--              return __nfs_revalidate_inode(server, mnt->mnt_root->d_inode);
-+              /* Revalidate fsid using the parent directory */
-+              return __nfs_revalidate_inode(server, dir);
+       for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
+-              if ((*data = inb(host->base + ORC_HSTUS)) & HDI)
++              if ((*pData = ORC_RD(hcsp->HCS_Base, ORC_HSTUS)) & HDI)
+                       return 1;       /* Wait HDI set */
+-              mdelay(100);    /* wait 100ms before try again  */
++              waitForPause(100);      /* wait 100ms before try again  */
+       }
        return 0;
  }
  
-@@ -947,7 +946,7 @@
-               res = ERR_PTR(error);
-               goto out_unlock;
-       }
--      error = nfs_reval_fsid(nd->mnt, dir, &fhandle, &fattr);
-+      error = nfs_reval_fsid(dir, &fattr);
-       if (error < 0) {
-               res = ERR_PTR(error);
-               goto out_unlock;
-@@ -1247,7 +1246,7 @@
-       attr.ia_mode = mode;
-       attr.ia_valid = ATTR_MODE;
--      if (nd && (nd->flags & LOOKUP_CREATE))
-+      if ((nd->flags & LOOKUP_CREATE) != 0)
-               open_flags = nd->intent.open.flags;
+ /***************************************************************************/
+-static unsigned short orc_read_fwrev(struct orc_host * host)
++static unsigned short get_FW_version(ORC_HCS * hcsp)
+ {
+-      u16 version;
+-      u8 data;
++      UCHAR bData;
++      union {
++              unsigned short sVersion;
++              unsigned char cVersion[2];
++      } Version;
+-      outb(ORC_CMD_VERSION, host->base + ORC_HDATA);
+-      outb(HDO, host->base + ORC_HCTRL);
+-      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
++      ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_VERSION);
++      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
++      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
+               return 0;
  
-       lock_kernel();
-@@ -1747,8 +1746,8 @@
-       struct nfs_inode *nfsi;
-       struct nfs_access_entry *cache;
+-      if (wait_hdi_set(host, &data) == 0)     /* Wait HDI set   */
++      if (waitHDIset(hcsp, &bData) == 0)      /* Wait HDI set   */
+               return 0;
+-      version = inb(host->base + ORC_HDATA);
+-      outb(data, host->base + ORC_HSTUS);     /* Clear HDI            */
++      Version.cVersion[0] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
++      ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);      /* Clear HDI            */
  
--      spin_lock(&nfs_access_lru_lock);
- restart:
-+      spin_lock(&nfs_access_lru_lock);
-       list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) {
-               struct inode *inode;
+-      if (wait_hdi_set(host, &data) == 0)     /* Wait HDI set   */
++      if (waitHDIset(hcsp, &bData) == 0)      /* Wait HDI set   */
+               return 0;
+-      version |= inb(host->base + ORC_HDATA) << 8;
+-      outb(data, host->base + ORC_HSTUS);     /* Clear HDI            */
++      Version.cVersion[1] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
++      ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);      /* Clear HDI            */
  
-@@ -1773,6 +1772,7 @@
-                       clear_bit(NFS_INO_ACL_LRU_SET, &nfsi->flags);
-               }
-               spin_unlock(&inode->i_lock);
-+              spin_unlock(&nfs_access_lru_lock);
-               iput(inode);
-               goto restart;
-       }
-diff -Nurb linux-2.6.22-570/fs/nfs/direct.c linux-2.6.22-590/fs/nfs/direct.c
---- linux-2.6.22-570/fs/nfs/direct.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/direct.c   2008-01-02 13:56:37.000000000 -0500
-@@ -266,7 +266,7 @@
- static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos)
- {
-       struct nfs_open_context *ctx = dreq->ctx;
--      struct inode *inode = ctx->dentry->d_inode;
-+      struct inode *inode = ctx->path.dentry->d_inode;
-       size_t rsize = NFS_SERVER(inode)->rsize;
-       unsigned int pgbase;
-       int result;
-@@ -295,10 +295,15 @@
-                       break;
-               }
-               if ((unsigned)result < data->npages) {
-+                      bytes = result * PAGE_SIZE;
-+                      if (bytes <= pgbase) {
-                       nfs_direct_release_pages(data->pagevec, result);
-                       nfs_readdata_release(data);
-                       break;
-               }
-+                      bytes -= pgbase;
-+                      data->npages = result;
-+              }
+-      return version;
++      return (Version.sVersion);
+ }
  
-               get_dreq(dreq);
+ /***************************************************************************/
+-static u8 orc_nv_write(struct orc_host * host, unsigned char address, unsigned char value)
++static UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value)
+ {
+-      outb(ORC_CMD_SET_NVM, host->base + ORC_HDATA);  /* Write command */
+-      outb(HDO, host->base + ORC_HCTRL);
+-      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
++      ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_SET_NVM);    /* Write command */
++      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
++      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
+               return 0;
  
-@@ -601,7 +606,7 @@
- static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync)
- {
-       struct nfs_open_context *ctx = dreq->ctx;
--      struct inode *inode = ctx->dentry->d_inode;
-+      struct inode *inode = ctx->path.dentry->d_inode;
-       size_t wsize = NFS_SERVER(inode)->wsize;
-       unsigned int pgbase;
-       int result;
-@@ -630,10 +635,15 @@
-                       break;
-               }
-               if ((unsigned)result < data->npages) {
-+                      bytes = result * PAGE_SIZE;
-+                      if (bytes <= pgbase) {
-                       nfs_direct_release_pages(data->pagevec, result);
-                       nfs_writedata_release(data);
-                       break;
-               }
-+                      bytes -= pgbase;
-+                      data->npages = result;
-+              }
+-      outb(address, host->base + ORC_HDATA);  /* Write address */
+-      outb(HDO, host->base + ORC_HCTRL);
+-      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
++      ORC_WR(hcsp->HCS_Base + ORC_HDATA, address);    /* Write address */
++      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
++      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
+               return 0;
  
-               get_dreq(dreq);
+-      outb(value, host->base + ORC_HDATA);    /* Write value  */
+-      outb(HDO, host->base + ORC_HCTRL);
+-      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
++      ORC_WR(hcsp->HCS_Base + ORC_HDATA, value);      /* Write value  */
++      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
++      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
+               return 0;
  
-@@ -763,10 +773,8 @@
-               (unsigned long) count, (long long) pos);
+       return 1;
+ }
  
-       if (nr_segs != 1)
--              return -EINVAL;
--
--      if (count < 0)
-               goto out;
-+
-       retval = -EFAULT;
-       if (!access_ok(VERIFY_WRITE, buf, count))
-               goto out;
-@@ -814,7 +822,7 @@
- ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t pos)
- {
--      ssize_t retval;
-+      ssize_t retval = -EINVAL;
-       struct file *file = iocb->ki_filp;
-       struct address_space *mapping = file->f_mapping;
-       /* XXX: temporary */
-@@ -827,7 +835,7 @@
-               (unsigned long) count, (long long) pos);
+ /***************************************************************************/
+-static u8 orc_nv_read(struct orc_host * host, u8 address, u8 *ptr)
++static UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn)
+ {
+-      unsigned char data;
++      unsigned char bData;
+-      outb(ORC_CMD_GET_NVM, host->base + ORC_HDATA);  /* Write command */
+-      outb(HDO, host->base + ORC_HCTRL);
+-      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
++      ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_GET_NVM);    /* Write command */
++      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
++      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
+               return 0;
  
-       if (nr_segs != 1)
--              return -EINVAL;
-+              goto out;
+-      outb(address, host->base + ORC_HDATA);  /* Write address */
+-      outb(HDO, host->base + ORC_HCTRL);
+-      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
++      ORC_WR(hcsp->HCS_Base + ORC_HDATA, address);    /* Write address */
++      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
++      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
+               return 0;
  
-       retval = generic_write_checks(file, &pos, &count, 0);
-       if (retval)
-diff -Nurb linux-2.6.22-570/fs/nfs/inode.c linux-2.6.22-590/fs/nfs/inode.c
---- linux-2.6.22-570/fs/nfs/inode.c    2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/nfs/inode.c    2008-01-02 13:56:37.000000000 -0500
-@@ -466,14 +466,14 @@
+-      if (wait_hdi_set(host, &data) == 0)     /* Wait HDI set   */
++      if (waitHDIset(hcsp, &bData) == 0)      /* Wait HDI set   */
+               return 0;
+-      *ptr = inb(host->base + ORC_HDATA);
+-      outb(data, host->base + ORC_HSTUS);     /* Clear HDI    */
++      *pDataIn = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
++      ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);      /* Clear HDI    */
  
-       ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
-       if (ctx != NULL) {
--              atomic_set(&ctx->count, 1);
--              ctx->dentry = dget(dentry);
--              ctx->vfsmnt = mntget(mnt);
-+              ctx->path.dentry = dget(dentry);
-+              ctx->path.mnt = mntget(mnt);
-               ctx->cred = get_rpccred(cred);
-               ctx->state = NULL;
-               ctx->lockowner = current->files;
-               ctx->error = 0;
-               ctx->dir_cookie = 0;
-+              kref_init(&ctx->kref);
-       }
-       return ctx;
- }
-@@ -481,27 +481,33 @@
- struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
- {
-       if (ctx != NULL)
--              atomic_inc(&ctx->count);
-+              kref_get(&ctx->kref);
-       return ctx;
+       return 1;
+-
  }
  
--void put_nfs_open_context(struct nfs_open_context *ctx)
-+static void nfs_free_open_context(struct kref *kref)
+-/**
+- *    orc_exec_sb             -       Queue an SCB with the HA
+- *    @host: host adapter the SCB belongs to
+- *    @scb: SCB to queue for execution
+- */
+-
+-static void orc_exec_scb(struct orc_host * host, struct orc_scb * scb)
++/***************************************************************************/
++static void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
  {
--      if (atomic_dec_and_test(&ctx->count)) {
-+      struct nfs_open_context *ctx = container_of(kref,
-+                      struct nfs_open_context, kref);
-+
-               if (!list_empty(&ctx->list)) {
--                      struct inode *inode = ctx->dentry->d_inode;
-+              struct inode *inode = ctx->path.dentry->d_inode;
-                       spin_lock(&inode->i_lock);
-                       list_del(&ctx->list);
-                       spin_unlock(&inode->i_lock);
-               }
-               if (ctx->state != NULL)
--                      nfs4_close_state(ctx->state, ctx->mode);
-+              nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
-               if (ctx->cred != NULL)
-                       put_rpccred(ctx->cred);
--              dput(ctx->dentry);
--              mntput(ctx->vfsmnt);
-+      dput(ctx->path.dentry);
-+      mntput(ctx->path.mnt);
-               kfree(ctx);
--      }
-+}
-+
-+void put_nfs_open_context(struct nfs_open_context *ctx)
-+{
-+      kref_put(&ctx->kref, nfs_free_open_context);
+-      scb->status = ORCSCB_POST;
+-      outb(scb->scbidx, host->base + ORC_PQUEUE);
++      scbp->SCB_Status = ORCSCB_POST;
++      ORC_WR(hcsp->HCS_Base + ORC_PQUEUE, scbp->SCB_ScbIdx);
++      return;
  }
  
- /*
-@@ -977,8 +983,8 @@
-               goto out_changed;
-       server = NFS_SERVER(inode);
--      /* Update the fsid if and only if this is the root directory */
--      if (inode == inode->i_sb->s_root->d_inode
-+      /* Update the fsid? */
-+      if (S_ISDIR(inode->i_mode)
-                       && !nfs_fsid_equal(&server->fsid, &fattr->fsid))
-               server->fsid = fattr->fsid;
  
-@@ -1125,27 +1131,10 @@
-  */
- void nfs4_clear_inode(struct inode *inode)
- {
--      struct nfs_inode *nfsi = NFS_I(inode);
+-/**
+- *    se2_rd_all      -       read SCSI parameters from EEPROM
+- *    @host: Host whose EEPROM is being loaded
+- *
+- *    Read SCSI H/A configuration parameters from serial EEPROM
+- */
 -
-       /* If we are holding a delegation, return it! */
-       nfs_inode_return_delegation(inode);
-       /* First call standard NFS clear_inode() code */
-       nfs_clear_inode(inode);
--      /* Now clear out any remaining state */
--      while (!list_empty(&nfsi->open_states)) {
--              struct nfs4_state *state;
--              
--              state = list_entry(nfsi->open_states.next,
--                              struct nfs4_state,
--                              inode_states);
--              dprintk("%s(%s/%Ld): found unclaimed NFSv4 state %p\n",
--                              __FUNCTION__,
--                              inode->i_sb->s_id,
--                              (long long)NFS_FILEID(inode),
--                              state);
--              BUG_ON(atomic_read(&state->count) != 1);
--              nfs4_close_state(state, state->state);
--      }
- }
- #endif
+-static int se2_rd_all(struct orc_host * host)
++/***********************************************************************
++ Read SCSI H/A configuration parameters from serial EEPROM
++************************************************************************/
++static int se2_rd_all(ORC_HCS * hcsp)
+ {
+       int i;
+-      u8 *np, chksum = 0;
++      UCHAR *np, chksum = 0;
  
-@@ -1188,14 +1177,11 @@
+-      np = (u8 *) nvramp;
++      np = (UCHAR *) nvramp;
+       for (i = 0; i < 64; i++, np++) {        /* <01> */
+-              if (orc_nv_read(host, (u8) i, np) == 0)
++              if (get_NVRAM(hcsp, (unsigned char) i, np) == 0)
+                       return -1;
++//      *np++ = get_NVRAM(hcsp, (unsigned char ) i);
+       }
  
-       inode_init_once(&nfsi->vfs_inode);
-       spin_lock_init(&nfsi->req_lock);
--      INIT_LIST_HEAD(&nfsi->dirty);
--      INIT_LIST_HEAD(&nfsi->commit);
-       INIT_LIST_HEAD(&nfsi->open_files);
-       INIT_LIST_HEAD(&nfsi->access_cache_entry_lru);
-       INIT_LIST_HEAD(&nfsi->access_cache_inode_lru);
-       INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
-       atomic_set(&nfsi->data_updates, 0);
--      nfsi->ndirty = 0;
-       nfsi->ncommit = 0;
-       nfsi->npages = 0;
-       nfs4_init_once(nfsi);
-diff -Nurb linux-2.6.22-570/fs/nfs/mount_clnt.c linux-2.6.22-590/fs/nfs/mount_clnt.c
---- linux-2.6.22-570/fs/nfs/mount_clnt.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/mount_clnt.c       2008-01-02 13:56:37.000000000 -0500
-@@ -69,6 +69,7 @@
-               msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT];
+-      /*------ Is ckecksum ok ? ------*/
+-      np = (u8 *) nvramp;
++/*------ Is ckecksum ok ? ------*/
++      np = (UCHAR *) nvramp;
+       for (i = 0; i < 63; i++)
+               chksum += *np++;
  
-       status = rpc_call_sync(mnt_clnt, &msg, 0);
-+      rpc_shutdown_client(mnt_clnt);
-       return status < 0? status : (result.status? -EACCES : 0);
+-      if (nvramp->CheckSum != (u8) chksum)
++      if (nvramp->CheckSum != (UCHAR) chksum)
+               return -1;
+       return 1;
  }
  
-@@ -84,8 +85,7 @@
-               .program        = &mnt_program,
-               .version        = version,
-               .authflavor     = RPC_AUTH_UNIX,
--              .flags          = (RPC_CLNT_CREATE_ONESHOT |
--                                 RPC_CLNT_CREATE_INTR),
-+              .flags          = RPC_CLNT_CREATE_INTR,
-       };
-       return rpc_create(&args);
-diff -Nurb linux-2.6.22-570/fs/nfs/nfs3proc.c linux-2.6.22-590/fs/nfs/nfs3proc.c
---- linux-2.6.22-570/fs/nfs/nfs3proc.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/nfs3proc.c 2008-01-02 13:56:37.000000000 -0500
-@@ -335,9 +335,7 @@
-                * not sure this buys us anything (and I'd have
-                * to revamp the NFSv3 XDR code) */
-               status = nfs3_proc_setattr(dentry, &fattr, sattr);
--              if (status == 0)
--                      nfs_setattr_update_inode(dentry->d_inode, sattr);
--              nfs_refresh_inode(dentry->d_inode, &fattr);
-+              nfs_post_op_update_inode(dentry->d_inode, &fattr);
-               dprintk("NFS reply setattr (post-create): %d\n", status);
-       }
-       if (status != 0)
-diff -Nurb linux-2.6.22-570/fs/nfs/nfs4_fs.h linux-2.6.22-590/fs/nfs/nfs4_fs.h
---- linux-2.6.22-570/fs/nfs/nfs4_fs.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/nfs4_fs.h  2008-01-02 13:56:37.000000000 -0500
-@@ -165,7 +165,7 @@
- extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *);
- extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
- extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
--extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state);
-+extern int nfs4_do_close(struct path *path, struct nfs4_state *state);
- extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
- extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
- extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
-@@ -196,7 +196,7 @@
- extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
- extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
- extern void nfs4_put_open_state(struct nfs4_state *);
--extern void nfs4_close_state(struct nfs4_state *, mode_t);
-+extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t);
- extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t);
- extern void nfs4_schedule_state_recovery(struct nfs_client *);
- extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
-@@ -222,7 +222,7 @@
- #else
+-/**
+- *    se2_update_all          -       update the EEPROM
+- *    @host: Host whose EEPROM is being updated
+- *
+- *    Update changed bytes in the EEPROM image.
+- */
+-
+-static void se2_update_all(struct orc_host * host)
++/************************************************************************
++ Update SCSI H/A configuration parameters from serial EEPROM
++*************************************************************************/
++static void se2_update_all(ORC_HCS * hcsp)
+ {                             /* setup default pattern  */
+       int i;
+-      u8 *np, *np1, chksum = 0;
++      UCHAR *np, *np1, chksum = 0;
  
--#define nfs4_close_state(a, b) do { } while (0)
-+#define nfs4_close_state(a, b, c) do { } while (0)
+       /* Calculate checksum first   */
+-      np = (u8 *) default_nvram;
++      np = (UCHAR *) dftNvRam;
+       for (i = 0; i < 63; i++)
+               chksum += *np++;
+       *np = chksum;
  
- #endif /* CONFIG_NFS_V4 */
- #endif /* __LINUX_FS_NFS_NFS4_FS.H */
-diff -Nurb linux-2.6.22-570/fs/nfs/nfs4proc.c linux-2.6.22-590/fs/nfs/nfs4proc.c
---- linux-2.6.22-570/fs/nfs/nfs4proc.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/nfs4proc.c 2008-01-02 13:56:37.000000000 -0500
-@@ -214,14 +214,14 @@
+-      np = (u8 *) default_nvram;
+-      np1 = (u8 *) nvramp;
++      np = (UCHAR *) dftNvRam;
++      np1 = (UCHAR *) nvramp;
+       for (i = 0; i < 64; i++, np++, np1++) {
+-              if (*np != *np1)
+-                      orc_nv_write(host, (u8) i, *np);
++              if (*np != *np1) {
++                      set_NVRAM(hcsp, (unsigned char) i, *np);
++              }
+       }
++      return;
  }
  
- struct nfs4_opendata {
--      atomic_t count;
-+      struct kref kref;
-       struct nfs_openargs o_arg;
-       struct nfs_openres o_res;
-       struct nfs_open_confirmargs c_arg;
-       struct nfs_open_confirmres c_res;
-       struct nfs_fattr f_attr;
-       struct nfs_fattr dir_attr;
--      struct dentry *dentry;
-+      struct path path;
-       struct dentry *dir;
-       struct nfs4_state_owner *owner;
-       struct iattr attrs;
-@@ -230,11 +230,11 @@
-       int cancelled;
- };
--static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
-+static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
-               struct nfs4_state_owner *sp, int flags,
-               const struct iattr *attrs)
- {
--      struct dentry *parent = dget_parent(dentry);
-+      struct dentry *parent = dget_parent(path->dentry);
-       struct inode *dir = parent->d_inode;
-       struct nfs_server *server = NFS_SERVER(dir);
-       struct nfs4_opendata *p;
-@@ -245,8 +245,8 @@
-       p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
-       if (p->o_arg.seqid == NULL)
-               goto err_free;
--      atomic_set(&p->count, 1);
--      p->dentry = dget(dentry);
-+      p->path.mnt = mntget(path->mnt);
-+      p->path.dentry = dget(path->dentry);
-       p->dir = parent;
-       p->owner = sp;
-       atomic_inc(&sp->so_count);
-@@ -254,7 +254,7 @@
-       p->o_arg.open_flags = flags,
-       p->o_arg.clientid = server->nfs_client->cl_clientid;
-       p->o_arg.id = sp->so_id;
--      p->o_arg.name = &dentry->d_name;
-+      p->o_arg.name = &p->path.dentry->d_name;
-       p->o_arg.server = server;
-       p->o_arg.bitmask = server->attr_bitmask;
-       p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
-@@ -274,6 +274,7 @@
-       p->c_arg.fh = &p->o_res.fh;
-       p->c_arg.stateid = &p->o_res.stateid;
-       p->c_arg.seqid = p->o_arg.seqid;
-+      kref_init(&p->kref);
-       return p;
- err_free:
-       kfree(p);
-@@ -282,27 +283,23 @@
-       return NULL;
+-/**
+- *    read_eeprom             -       load EEPROM
+- *    @host: Host EEPROM to read
+- *
+- *    Read the EEPROM for a given host. If it is invalid or fails
+- *    the restore the defaults and use them.
+- */
+-
+-static void read_eeprom(struct orc_host * host)
+-{
+-      if (se2_rd_all(host) != 1) {
+-              se2_update_all(host);   /* setup default pattern        */
+-              se2_rd_all(host);       /* load again                   */
++/*************************************************************************
++ Function name  : read_eeprom
++**************************************************************************/
++static void read_eeprom(ORC_HCS * hcsp)
++{
++      if (se2_rd_all(hcsp) != 1) {
++              se2_update_all(hcsp);   /* setup default pattern        */
++              se2_rd_all(hcsp);       /* load again                   */
+       }
  }
  
--static void nfs4_opendata_free(struct nfs4_opendata *p)
-+static void nfs4_opendata_free(struct kref *kref)
+-/**
+- *    orc_load_firmware       -       initialise firmware
+- *    @host: Host to set up
+- *
+- *    Load the firmware from the EEPROM into controller SRAM. This
+- *    is basically a 4K block copy and then a 4K block read to check
+- *    correctness. The rest is convulted by the indirect interfaces
+- *    in the hardware
+- */
+-
+-static u8 orc_load_firmware(struct orc_host * host)
++/***************************************************************************/
++static UCHAR load_FW(ORC_HCS * hcsp)
  {
--      if (p != NULL && atomic_dec_and_test(&p->count)) {
-+      struct nfs4_opendata *p = container_of(kref,
-+                      struct nfs4_opendata, kref);
+-      u32 data32;
+-      u16 bios_addr;
+-      u16 i;
+-      u8 *data32_ptr, data;
+-
+-
+-      /* Set up the EEPROM for access */
++      U32 dData;
++      USHORT wBIOSAddress;
++      USHORT i;
++      UCHAR *pData, bData;
 +
-               nfs_free_seqid(p->o_arg.seqid);
-               nfs4_put_state_owner(p->owner);
-               dput(p->dir);
--              dput(p->dentry);
-+      dput(p->path.dentry);
-+      mntput(p->path.mnt);
-               kfree(p);
++
++      bData = ORC_RD(hcsp->HCS_Base, ORC_GCFG);
++      ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData | EEPRG);       /* Enable EEPROM programming */
++      ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, 0x00);
++      ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x00);
++      if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0x55) {
++              ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);       /* Disable EEPROM programming */
++              return 0;
++      }
++      ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x01);
++      if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0xAA) {
++              ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);       /* Disable EEPROM programming */
++              return 0;
++      }
++      ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD);       /* Enable SRAM programming */
++      pData = (UCHAR *) & dData;
++      dData = 0;              /* Initial FW address to 0 */
++      ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x10);
++      *pData = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);         /* Read from BIOS */
++      ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x11);
++      *(pData + 1) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);   /* Read from BIOS */
++      ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x12);
++      *(pData + 2) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);   /* Read from BIOS */
++      ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, *(pData + 2));
++      ORC_WRLONG(hcsp->HCS_Base + ORC_FWBASEADR, dData);      /* Write FW address */
+-      data = inb(host->base + ORC_GCFG);
+-      outb(data | EEPRG, host->base + ORC_GCFG);      /* Enable EEPROM programming */
+-      outb(0x00, host->base + ORC_EBIOSADR2);
+-      outw(0x0000, host->base + ORC_EBIOSADR0);
+-      if (inb(host->base + ORC_EBIOSDATA) != 0x55) {
+-              outb(data, host->base + ORC_GCFG);      /* Disable EEPROM programming */
+-              return 0;
+-      }
+-      outw(0x0001, host->base + ORC_EBIOSADR0);
+-      if (inb(host->base + ORC_EBIOSDATA) != 0xAA) {
+-              outb(data, host->base + ORC_GCFG);      /* Disable EEPROM programming */
+-              return 0;
 -      }
- }
--/* Helper for asynchronous RPC calls */
--static int nfs4_call_async(struct rpc_clnt *clnt,
--              const struct rpc_call_ops *tk_ops, void *calldata)
-+static void nfs4_opendata_put(struct nfs4_opendata *p)
- {
--      struct rpc_task *task;
 -
--      if (!(task = rpc_new_task(clnt, RPC_TASK_ASYNC, tk_ops, calldata)))
--              return -ENOMEM;
--      rpc_execute(task);
--      return 0;
-+      if (p != NULL)
-+              kref_put(&p->kref, nfs4_opendata_free);
- }
- static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
-@@ -451,7 +448,7 @@
-                                               opendata->owner->so_cred,
-                                               &opendata->o_res);
+-      outb(PRGMRST | DOWNLOAD, host->base + ORC_RISCCTL);     /* Enable SRAM programming */
+-      data32_ptr = (u8 *) & data32;
+-      data32 = 0;             /* Initial FW address to 0 */
+-      outw(0x0010, host->base + ORC_EBIOSADR0);
+-      *data32_ptr = inb(host->base + ORC_EBIOSDATA);          /* Read from BIOS */
+-      outw(0x0011, host->base + ORC_EBIOSADR0);
+-      *(data32_ptr + 1) = inb(host->base + ORC_EBIOSDATA);    /* Read from BIOS */
+-      outw(0x0012, host->base + ORC_EBIOSADR0);
+-      *(data32_ptr + 2) = inb(host->base + ORC_EBIOSDATA);    /* Read from BIOS */
+-      outw(*(data32_ptr + 2), host->base + ORC_EBIOSADR2);
+-      outl(data32, host->base + ORC_FWBASEADR);               /* Write FW address */
+-
+-      /* Copy the code from the BIOS to the SRAM */
+-
+-      bios_addr = (u16) data32;       /* FW code locate at BIOS address + ? */
+-      for (i = 0, data32_ptr = (u8 *) & data32;       /* Download the code    */
++      wBIOSAddress = (USHORT) dData;  /* FW code locate at BIOS address + ? */
++      for (i = 0, pData = (UCHAR *) & dData;  /* Download the code    */
+            i < 0x1000;        /* Firmware code size = 4K      */
+-           i++, bios_addr++) {
+-              outw(bios_addr, host->base + ORC_EBIOSADR0);
+-              *data32_ptr++ = inb(host->base + ORC_EBIOSDATA);        /* Read from BIOS */
++           i++, wBIOSAddress++) {
++              ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
++              *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);       /* Read from BIOS */
+               if ((i % 4) == 3) {
+-                      outl(data32, host->base + ORC_RISCRAM); /* Write every 4 bytes */
+-                      data32_ptr = (u8 *) & data32;
++                      ORC_WRLONG(hcsp->HCS_Base + ORC_RISCRAM, dData);        /* Write every 4 bytes */
++                      pData = (UCHAR *) & dData;
                }
--              nfs4_close_state(newstate, opendata->o_arg.open_flags);
-+              nfs4_close_state(&opendata->path, newstate, opendata->o_arg.open_flags);
        }
-       if (newstate != state)
-               return -ESTALE;
-@@ -462,7 +459,7 @@
-  * OPEN_RECLAIM:
-  *    reclaim state on the server after a reboot.
-  */
--static int _nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
-+static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
- {
-       struct nfs_delegation *delegation = NFS_I(state->inode)->delegation;
-       struct nfs4_opendata *opendata;
-@@ -478,7 +475,7 @@
+-      /* Go back and check they match */
+-
+-      outb(PRGMRST | DOWNLOAD, host->base + ORC_RISCCTL);     /* Reset program count 0 */
+-      bios_addr -= 0x1000;    /* Reset the BIOS adddress      */
+-      for (i = 0, data32_ptr = (u8 *) & data32;       /* Check the code       */
++      ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD);       /* Reset program count 0 */
++      wBIOSAddress -= 0x1000; /* Reset the BIOS adddress      */
++      for (i = 0, pData = (UCHAR *) & dData;  /* Check the code       */
+            i < 0x1000;        /* Firmware code size = 4K      */
+-           i++, bios_addr++) {
+-              outw(bios_addr, host->base + ORC_EBIOSADR0);
+-              *data32_ptr++ = inb(host->base + ORC_EBIOSDATA);        /* Read from BIOS */
++           i++, wBIOSAddress++) {
++              ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
++              *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);       /* Read from BIOS */
+               if ((i % 4) == 3) {
+-                      if (inl(host->base + ORC_RISCRAM) != data32) {
+-                              outb(PRGMRST, host->base + ORC_RISCCTL);        /* Reset program to 0 */
+-                              outb(data, host->base + ORC_GCFG);      /*Disable EEPROM programming */
++                      if (ORC_RDLONG(hcsp->HCS_Base, ORC_RISCRAM) != dData) {
++                              ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST);  /* Reset program to 0 */
++                              ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);       /*Disable EEPROM programming */
+                               return 0;
+                       }
+-                      data32_ptr = (u8 *) & data32;
++                      pData = (UCHAR *) & dData;
                }
-               delegation_type = delegation->type;
        }
--      opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL);
-+      opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
-       if (opendata == NULL)
-               return -ENOMEM;
-       opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS;
-@@ -486,17 +483,17 @@
-       nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh);
-       opendata->o_arg.u.delegation_type = delegation_type;
-       status = nfs4_open_recover(opendata, state);
--      nfs4_opendata_free(opendata);
-+      nfs4_opendata_put(opendata);
-       return status;
+-
+-      /* Success */
+-      outb(PRGMRST, host->base + ORC_RISCCTL);        /* Reset program to 0   */
+-      outb(data, host->base + ORC_GCFG);      /* Disable EEPROM programming */
++      ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST);  /* Reset program to 0   */
++      ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);       /* Disable EEPROM programming */
+       return 1;
  }
  
--static int nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
-+static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
+ /***************************************************************************/
+-static void setup_SCBs(struct orc_host * host)
++static void setup_SCBs(ORC_HCS * hcsp)
  {
-       struct nfs_server *server = NFS_SERVER(state->inode);
-       struct nfs4_exception exception = { };
-       int err;
-       do {
--              err = _nfs4_do_open_reclaim(sp, state, dentry);
-+              err = _nfs4_do_open_reclaim(ctx, state);
-               if (err != -NFS4ERR_DELAY)
-                       break;
-               nfs4_handle_exception(server, err, &exception);
-@@ -512,12 +509,12 @@
-       ctx = nfs4_state_find_open_context(state);
-       if (IS_ERR(ctx))
-               return PTR_ERR(ctx);
--      ret = nfs4_do_open_reclaim(sp, state, ctx->dentry);
-+      ret = nfs4_do_open_reclaim(ctx, state);
-       put_nfs_open_context(ctx);
-       return ret;
- }
+-      struct orc_scb *scb;
++      ORC_SCB *pVirScb;
+       int i;
+-      struct orc_extended_scb *escb;
+-      dma_addr_t escb_phys;
++      ESCB *pVirEscb;
++      dma_addr_t pPhysEscb;
+-      /* Setup SCB base and SCB Size registers */
+-      outb(ORC_MAXQUEUE, host->base + ORC_SCBSIZE);   /* Total number of SCBs */
+-      /* SCB base address 0      */
+-      outl(host->scb_phys, host->base + ORC_SCBBASE0);
+-      /* SCB base address 1      */
+-      outl(host->scb_phys, host->base + ORC_SCBBASE1);
++      /* Setup SCB HCS_Base and SCB Size registers */
++      ORC_WR(hcsp->HCS_Base + ORC_SCBSIZE, ORC_MAXQUEUE);     /* Total number of SCBs */
++      /* SCB HCS_Base address 0      */
++      ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE0, hcsp->HCS_physScbArray);
++      /* SCB HCS_Base address 1      */
++      ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE1, hcsp->HCS_physScbArray);
+       /* setup scatter list address with one buffer */
+-      scb = host->scb_virt;
+-      escb = host->escb_virt;
++      pVirScb = hcsp->HCS_virScbArray;
++      pVirEscb = hcsp->HCS_virEscbArray;
+       for (i = 0; i < ORC_MAXQUEUE; i++) {
+-              escb_phys = (host->escb_phys + (sizeof(struct orc_extended_scb) * i));
+-              scb->sg_addr = (u32) escb_phys;
+-              scb->sense_addr = (u32) escb_phys;
+-              scb->escb = escb;
+-              scb->scbidx = i;
+-              scb++;
+-              escb++;
++              pPhysEscb = (hcsp->HCS_physEscbArray + (sizeof(ESCB) * i));
++              pVirScb->SCB_SGPAddr = (U32) pPhysEscb;
++              pVirScb->SCB_SensePAddr = (U32) pPhysEscb;
++              pVirScb->SCB_EScb = pVirEscb;
++              pVirScb->SCB_ScbIdx = i;
++              pVirScb++;
++              pVirEscb++;
+       }
+-}
+-/**
+- *    init_alloc_map          -       initialise allocation map
+- *    @host: host map to configure
+- *
+- *    Initialise the allocation maps for this device. If the device
+- *    is not quiescent the caller must hold the allocation lock
+- */
++      return;
++}
  
--static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
-+static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state)
+-static void init_alloc_map(struct orc_host * host)
++/***************************************************************************/
++static void initAFlag(ORC_HCS * hcsp)
  {
-       struct nfs4_state_owner  *sp  = state->owner;
-       struct nfs4_opendata *opendata;
-@@ -525,24 +522,24 @@
+-      u8 i, j;
++      UCHAR i, j;
  
-       if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
-               return 0;
--      opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL);
-+      opendata = nfs4_opendata_alloc(&ctx->path, sp, 0, NULL);
-       if (opendata == NULL)
-               return -ENOMEM;
-       opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR;
-       memcpy(opendata->o_arg.u.delegation.data, state->stateid.data,
-                       sizeof(opendata->o_arg.u.delegation.data));
-       ret = nfs4_open_recover(opendata, state);
--      nfs4_opendata_free(opendata);
-+      nfs4_opendata_put(opendata);
-       return ret;
+       for (i = 0; i < MAX_CHANNELS; i++) {
+               for (j = 0; j < 8; j++) {
+-                      host->allocation_map[i][j] = 0xffffffff;
++                      hcsp->BitAllocFlag[i][j] = 0xffffffff;
+               }
+       }
  }
  
--int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
-+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state)
+-/**
+- *    init_orchid             -       initialise the host adapter
+- *    @host:host adapter to initialise
+- *
+- *    Initialise the controller and if neccessary load the firmware.
+- *
+- *    Returns -1 if the initialisation fails.
+- */
+-
+-static int init_orchid(struct orc_host * host)
++/***************************************************************************/
++static int init_orchid(ORC_HCS * hcsp)
  {
-       struct nfs4_exception exception = { };
--      struct nfs_server *server = NFS_SERVER(dentry->d_inode);
-+      struct nfs_server *server = NFS_SERVER(state->inode);
-       int err;
-       do {
--              err = _nfs4_open_delegation_recall(dentry, state);
-+              err = _nfs4_open_delegation_recall(ctx, state);
-               switch (err) {
-                       case 0:
-                               return err;
-@@ -601,9 +598,9 @@
-       nfs_confirm_seqid(&data->owner->so_seqid, 0);
-       state = nfs4_opendata_to_nfs4_state(data);
-       if (state != NULL)
--              nfs4_close_state(state, data->o_arg.open_flags);
-+              nfs4_close_state(&data->path, state, data->o_arg.open_flags);
- out_free:
--      nfs4_opendata_free(data);
-+      nfs4_opendata_put(data);
- }
+-      u8 *ptr;
+-      u16 revision;
+-      u8 i;
+-
+-      init_alloc_map(host);
+-      outb(0xFF, host->base + ORC_GIMSK);     /* Disable all interrupts */
+-
+-      if (inb(host->base + ORC_HSTUS) & RREADY) {     /* Orchid is ready */
+-              revision = orc_read_fwrev(host);
++      UBYTE *readBytep;
++      USHORT revision;
++      UCHAR i;
++
++      initAFlag(hcsp);
++      ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFF);       /* Disable all interrupt        */
++      if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) {       /* Orchid is ready              */
++              revision = get_FW_version(hcsp);
+               if (revision == 0xFFFF) {
+-                      outb(DEVRST, host->base + ORC_HCTRL);   /* Reset Host Adapter   */
+-                      if (wait_chip_ready(host) == 0)
+-                              return -1;
+-                      orc_load_firmware(host);        /* Download FW                  */
+-                      setup_SCBs(host);       /* Setup SCB base and SCB Size registers */
+-                      outb(0x00, host->base + ORC_HCTRL);     /* clear HOSTSTOP       */
+-                      if (wait_firmware_ready(host) == 0)
+-                              return -1;
++                      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST);     /* Reset Host Adapter   */
++                      if (waitChipReady(hcsp) == 0)
++                              return (-1);
++                      load_FW(hcsp);  /* Download FW                  */
++                      setup_SCBs(hcsp);       /* Setup SCB HCS_Base and SCB Size registers */
++                      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, 0);  /* clear HOSTSTOP       */
++                      if (waitFWReady(hcsp) == 0)
++                              return (-1);
+                       /* Wait for firmware ready     */
+               } else {
+-                      setup_SCBs(host);       /* Setup SCB base and SCB Size registers */
++                      setup_SCBs(hcsp);       /* Setup SCB HCS_Base and SCB Size registers */
+               }
+       } else {                /* Orchid is not Ready          */
+-              outb(DEVRST, host->base + ORC_HCTRL);   /* Reset Host Adapter   */
+-              if (wait_chip_ready(host) == 0)
+-                      return -1;
+-              orc_load_firmware(host);        /* Download FW                  */
+-              setup_SCBs(host);       /* Setup SCB base and SCB Size registers */
+-              outb(HDO, host->base + ORC_HCTRL);      /* Do Hardware Reset &  */
++              ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST);     /* Reset Host Adapter   */
++              if (waitChipReady(hcsp) == 0)
++                      return (-1);
++              load_FW(hcsp);  /* Download FW                  */
++              setup_SCBs(hcsp);       /* Setup SCB HCS_Base and SCB Size registers */
++              ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);        /* Do Hardware Reset &  */
  
- static const struct rpc_call_ops nfs4_open_confirm_ops = {
-@@ -621,7 +618,7 @@
-       struct rpc_task *task;
-       int status;
+               /*     clear HOSTSTOP  */
+-              if (wait_firmware_ready(host) == 0)             /* Wait for firmware ready      */
+-                      return -1;
++              if (waitFWReady(hcsp) == 0)             /* Wait for firmware ready      */
++                      return (-1);
+       }
  
--      atomic_inc(&data->count);
-+      kref_get(&data->kref);
-       /*
-        * If rpc_run_task() ends up calling ->rpc_release(), we
-        * want to ensure that it takes the 'error' code path.
-@@ -704,9 +701,9 @@
-       nfs_confirm_seqid(&data->owner->so_seqid, 0);
-       state = nfs4_opendata_to_nfs4_state(data);
-       if (state != NULL)
--              nfs4_close_state(state, data->o_arg.open_flags);
-+              nfs4_close_state(&data->path, state, data->o_arg.open_flags);
- out_free:
--      nfs4_opendata_free(data);
-+      nfs4_opendata_put(data);
+-      /* Load an EEProm copy into RAM */
+-      /* Assumes single threaded at this point */
+-      read_eeprom(host);
++/*------------- get serial EEProm settting -------*/
+-      if (nvramp->revision != 1)
+-              return -1;
++      read_eeprom(hcsp);
+-      host->scsi_id = nvramp->scsi_id;
+-      host->BIOScfg = nvramp->BIOSConfig1;
+-      host->max_targets = MAX_TARGETS;
+-      ptr = (u8 *) & (nvramp->Target00Config);
+-      for (i = 0; i < 16; ptr++, i++) {
+-              host->target_flag[i] = *ptr;
+-              host->max_tags[i] = ORC_MAXTAGS;
+-      }
++      if (nvramp->Revision != 1)
++              return (-1);
+-      if (nvramp->SCSI0Config & NCC_BUSRESET)
+-              host->flags |= HCF_SCSI_RESET;
+-      outb(0xFB, host->base + ORC_GIMSK);     /* enable RP FIFO interrupt     */
+-      return 0;
+-}
++      hcsp->HCS_SCSI_ID = nvramp->SCSI0Id;
++      hcsp->HCS_BIOS = nvramp->BIOSConfig1;
++      hcsp->HCS_MaxTar = MAX_TARGETS;
++      readBytep = (UCHAR *) & (nvramp->Target00Config);
++      for (i = 0; i < 16; readBytep++, i++) {
++              hcsp->TargetFlag[i] = *readBytep;
++              hcsp->MaximumTags[i] = ORC_MAXTAGS;
++      }                       /* for                          */
+-/**
+- *    orc_reset_scsi_bus              -       perform bus reset
+- *    @host: host being reset
+- *
+- *    Perform a full bus reset on the adapter.
+- */
++      if (nvramp->SCSI0Config & NCC_BUSRESET) {       /* Reset SCSI bus               */
++              hcsp->HCS_Flags |= HCF_SCSI_RESET;
++      }
++      ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFB);       /* enable RP FIFO interrupt     */
++      return (0);
++}
+-static int orc_reset_scsi_bus(struct orc_host * host)
++/*****************************************************************************
++ Function name  : orc_reset_scsi_bus
++ Description    : Reset registers, reset a hanging bus and
++                  kill active and disconnected commands for target w/o soft reset
++ Input          : pHCB  -       Pointer to host adapter structure
++ Output         : None.
++ Return         : pSRB  -       Pointer to SCSI request block.
++*****************************************************************************/
++static int orc_reset_scsi_bus(ORC_HCS * pHCB)
+ {                             /* I need Host Control Block Information */
+-      unsigned long flags;
++      ULONG flags;
+-      spin_lock_irqsave(&host->allocation_lock, flags);
++      spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
+-      init_alloc_map(host);
++      initAFlag(pHCB);
+       /* reset scsi bus */
+-      outb(SCSIRST, host->base + ORC_HCTRL);
+-      /* FIXME: We can spend up to a second with the lock held and
+-         interrupts off here */
+-      if (wait_scsi_reset_done(host) == 0) {
+-              spin_unlock_irqrestore(&host->allocation_lock, flags);
++      ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST);
++      if (waitSCSIRSTdone(pHCB) == 0) {
++              spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+               return FAILED;
+       } else {
+-              spin_unlock_irqrestore(&host->allocation_lock, flags);
++              spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+               return SUCCESS;
+       }
  }
  
- static const struct rpc_call_ops nfs4_open_ops = {
-@@ -727,7 +724,7 @@
-       struct rpc_task *task;
-       int status;
+-/**
+- *    orc_device_reset        -       device reset handler
+- *    @host: host to reset
+- *    @cmd: command causing the reset
+- *    @target; target device
+- *
+- *    Reset registers, reset a hanging bus and kill active and disconnected
+- *    commands for target w/o soft reset
+- */
+-
+-static int orc_device_reset(struct orc_host * host, struct scsi_cmnd *cmd, unsigned int target)
++/*****************************************************************************
++ Function name  : orc_device_reset
++ Description    : Reset registers, reset a hanging bus and
++                  kill active and disconnected commands for target w/o soft reset
++ Input          : pHCB  -       Pointer to host adapter structure
++ Output         : None.
++ Return         : pSRB  -       Pointer to SCSI request block.
++*****************************************************************************/
++static int orc_device_reset(ORC_HCS * pHCB, struct scsi_cmnd *SCpnt, unsigned int target)
+ {                             /* I need Host Control Block Information */
+-      struct orc_scb *scb;
+-      struct orc_extended_scb *escb;
+-      struct orc_scb *host_scb;
+-      u8 i;
+-      unsigned long flags;
+-
+-      spin_lock_irqsave(&(host->allocation_lock), flags);
+-      scb = (struct orc_scb *) NULL;
+-      escb = (struct orc_extended_scb *) NULL;
++      ORC_SCB *pScb;
++      ESCB *pVirEscb;
++      ORC_SCB *pVirScb;
++      UCHAR i;
++      ULONG flags;
++
++      spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
++      pScb = (ORC_SCB *) NULL;
++      pVirEscb = (ESCB *) NULL;
  
--      atomic_inc(&data->count);
-+      kref_get(&data->kref);
-       /*
-        * If rpc_run_task() ends up calling ->rpc_release(), we
-        * want to ensure that it takes the 'error' code path.
-@@ -811,7 +808,7 @@
-  *    reclaim state on the server after a network partition.
-  *    Assumes caller holds the appropriate lock
-  */
--static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
-+static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
- {
-       struct inode *inode = state->inode;
-       struct nfs_delegation *delegation = NFS_I(inode)->delegation;
-@@ -820,34 +817,34 @@
-       int ret;
+       /* setup scatter list address with one buffer */
+-      host_scb = host->scb_virt;
++      pVirScb = pHCB->HCS_virScbArray;
  
-       if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
--              ret = _nfs4_do_access(inode, sp->so_cred, openflags);
-+              ret = _nfs4_do_access(inode, ctx->cred, openflags);
-               if (ret < 0)
-                       return ret;
-               memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid));
-               set_bit(NFS_DELEGATED_STATE, &state->flags);
-               return 0;
+-      /* FIXME: is this safe if we then fail to issue the reset or race
+-         a completion ? */
+-      init_alloc_map(host);
+-
+-      /* Find the scb corresponding to the command */
++      initAFlag(pHCB);
++      /* device reset */
+       for (i = 0; i < ORC_MAXQUEUE; i++) {
+-              escb = host_scb->escb;
+-              if (host_scb->status && escb->srb == cmd)
++              pVirEscb = pVirScb->SCB_EScb;
++              if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt))
+                       break;
+-              host_scb++;
++              pVirScb++;
        }
--      opendata = nfs4_opendata_alloc(dentry, sp, openflags, NULL);
-+      opendata = nfs4_opendata_alloc(&ctx->path, state->owner, openflags, NULL);
-       if (opendata == NULL)
-               return -ENOMEM;
-       ret = nfs4_open_recover(opendata, state);
-       if (ret == -ESTALE) {
-               /* Invalidate the state owner so we don't ever use it again */
--              nfs4_drop_state_owner(sp);
--              d_drop(dentry);
-+              nfs4_drop_state_owner(state->owner);
-+              d_drop(ctx->path.dentry);
+       if (i == ORC_MAXQUEUE) {
+-              printk(KERN_ERR "Unable to Reset - No SCB Found\n");
+-              spin_unlock_irqrestore(&(host->allocation_lock), flags);
++              printk("Unable to Reset - No SCB Found\n");
++              spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+               return FAILED;
        }
--      nfs4_opendata_free(opendata);
-+      nfs4_opendata_put(opendata);
-       return ret;
+-
+-      /* Allocate a new SCB for the reset command to the firmware */
+-      if ((scb = __orc_alloc_scb(host)) == NULL) {
+-              /* Can't happen.. */
+-              spin_unlock_irqrestore(&(host->allocation_lock), flags);
++      if ((pScb = orc_alloc_scb(pHCB)) == NULL) {
++              spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+               return FAILED;
+       }
+-
+-      /* Reset device is handled by the firmare, we fill in an SCB and
+-         fire it at the controller, it does the rest */
+-      scb->opcode = ORC_BUSDEVRST;
+-      scb->target = target;
+-      scb->hastat = 0;
+-      scb->tastat = 0;
+-      scb->status = 0x0;
+-      scb->link = 0xFF;
+-      scb->reserved0 = 0;
+-      scb->reserved1 = 0;
+-      scb->xferlen = 0;
+-      scb->sg_len = 0;
+-
+-      escb->srb = NULL;
+-      escb->srb = cmd;
+-      orc_exec_scb(host, scb);        /* Start execute SCB            */
+-      spin_unlock_irqrestore(&host->allocation_lock, flags);
++      pScb->SCB_Opcode = ORC_BUSDEVRST;
++      pScb->SCB_Target = target;
++      pScb->SCB_HaStat = 0;
++      pScb->SCB_TaStat = 0;
++      pScb->SCB_Status = 0x0;
++      pScb->SCB_Link = 0xFF;
++      pScb->SCB_Reserved0 = 0;
++      pScb->SCB_Reserved1 = 0;
++      pScb->SCB_XferLen = 0;
++      pScb->SCB_SGLen = 0;
++
++      pVirEscb->SCB_Srb = NULL;
++      pVirEscb->SCB_Srb = SCpnt;
++      orc_exec_scb(pHCB, pScb);       /* Start execute SCB            */
++      spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+       return SUCCESS;
  }
  
--static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
-+static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
- {
--      struct nfs_server *server = NFS_SERVER(dentry->d_inode);
-+      struct nfs_server *server = NFS_SERVER(state->inode);
-       struct nfs4_exception exception = { };
-       int err;
+-/**
+- *    __orc_alloc_scb         -               allocate an SCB
+- *    @host: host to allocate from
+- *
+- *    Allocate an SCB and return a pointer to the SCB object. NULL
+- *    is returned if no SCB is free. The caller must already hold
+- *    the allocator lock at this point.
+- */
+-
  
-       do {
--              err = _nfs4_open_expired(sp, state, dentry);
-+              err = _nfs4_open_expired(ctx, state);
-               if (err == -NFS4ERR_DELAY)
-                       nfs4_handle_exception(server, err, &exception);
-       } while (exception.retry);
-@@ -862,7 +859,7 @@
-       ctx = nfs4_state_find_open_context(state);
-       if (IS_ERR(ctx))
-               return PTR_ERR(ctx);
--      ret = nfs4_do_open_expired(sp, state, ctx->dentry);
-+      ret = nfs4_do_open_expired(ctx, state);
-       put_nfs_open_context(ctx);
-       return ret;
- }
-@@ -953,9 +950,25 @@
+-static struct orc_scb *__orc_alloc_scb(struct orc_host * host)
++/***************************************************************************/
++static ORC_SCB *__orc_alloc_scb(ORC_HCS * hcsp)
+ {
+-      u8 channel;
+-      unsigned long idx;
+-      u8 index;
+-      u8 i;
++      ORC_SCB *pTmpScb;
++      UCHAR Ch;
++      ULONG idx;
++      UCHAR index;
++      UCHAR i;
+-      channel = host->index;
++      Ch = hcsp->HCS_Index;
+       for (i = 0; i < 8; i++) {
+               for (index = 0; index < 32; index++) {
+-                      if ((host->allocation_map[channel][i] >> index) & 0x01) {
+-                              host->allocation_map[channel][i] &= ~(1 << index);
++                      if ((hcsp->BitAllocFlag[Ch][i] >> index) & 0x01) {
++                              hcsp->BitAllocFlag[Ch][i] &= ~(1 << index);
+                               break;
+                       }
+               }
+               idx = index + 32 * i;
+-              /* Translate the index to a structure instance */
+-              return (struct orc_scb *) ((unsigned long) host->scb_virt + (idx * sizeof(struct orc_scb)));
++              pTmpScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (idx * sizeof(ORC_SCB)));
++              return (pTmpScb);
+       }
+-      return NULL;
++      return (NULL);
  }
  
- /*
-+ * on an EXCLUSIVE create, the server should send back a bitmask with FATTR4-*
-+ * fields corresponding to attributes that were used to store the verifier.
-+ * Make sure we clobber those fields in the later setattr call
-+ */
-+static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct iattr *sattr)
-+{
-+      if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_ACCESS) &&
-+          !(sattr->ia_valid & ATTR_ATIME_SET))
-+              sattr->ia_valid |= ATTR_ATIME;
-+
-+      if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_MODIFY) &&
-+          !(sattr->ia_valid & ATTR_MTIME_SET))
-+              sattr->ia_valid |= ATTR_MTIME;
-+}
-+
-+/*
-  * Returns a referenced nfs4_state
-  */
--static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
-+static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
+-/**
+- *    orc_alloc_scb           -               allocate an SCB
+- *    @host: host to allocate from
+- *
+- *    Allocate an SCB and return a pointer to the SCB object. NULL
+- *    is returned if no SCB is free.
+- */
+-
+-static struct orc_scb *orc_alloc_scb(struct orc_host * host)
++static ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp)
  {
-       struct nfs4_state_owner  *sp;
-       struct nfs4_state     *state = NULL;
-@@ -975,27 +988,30 @@
-               goto err_put_state_owner;
-       down_read(&clp->cl_sem);
-       status = -ENOMEM;
--      opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr);
-+      opendata = nfs4_opendata_alloc(path, sp, flags, sattr);
-       if (opendata == NULL)
-               goto err_release_rwsem;
-       status = _nfs4_proc_open(opendata);
-       if (status != 0)
--              goto err_opendata_free;
-+              goto err_opendata_put;
-+
-+      if (opendata->o_arg.open_flags & O_EXCL)
-+              nfs4_exclusive_attrset(opendata, sattr);
+-      struct orc_scb *scb;
+-      unsigned long flags;
++      ORC_SCB *pTmpScb;
++      ULONG flags;
  
-       status = -ENOMEM;
-       state = nfs4_opendata_to_nfs4_state(opendata);
-       if (state == NULL)
--              goto err_opendata_free;
-+              goto err_opendata_put;
-       if (opendata->o_res.delegation_type != 0)
-               nfs_inode_set_delegation(state->inode, cred, &opendata->o_res);
--      nfs4_opendata_free(opendata);
-+      nfs4_opendata_put(opendata);
-       nfs4_put_state_owner(sp);
-       up_read(&clp->cl_sem);
-       *res = state;
-       return 0;
--err_opendata_free:
--      nfs4_opendata_free(opendata);
-+err_opendata_put:
-+      nfs4_opendata_put(opendata);
- err_release_rwsem:
-       up_read(&clp->cl_sem);
- err_put_state_owner:
-@@ -1006,14 +1022,14 @@
+-      spin_lock_irqsave(&host->allocation_lock, flags);
+-      scb = __orc_alloc_scb(host);
+-      spin_unlock_irqrestore(&host->allocation_lock, flags);
+-      return scb;
++      spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
++      pTmpScb = __orc_alloc_scb(hcsp);
++      spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
++      return (pTmpScb);
  }
  
+-/**
+- *    orc_release_scb                 -       release an SCB
+- *    @host: host owning the SCB
+- *    @scb: SCB that is now free
+- *
+- *    Called to return a completed SCB to the allocation pool. Before
+- *    calling the SCB must be out of use on both the host and the HA.
+- */
  
--static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
-+static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred)
+-static void orc_release_scb(struct orc_host *host, struct orc_scb *scb)
++/***************************************************************************/
++static void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
  {
-       struct nfs4_exception exception = { };
-       struct nfs4_state *res;
-       int status;
-       do {
--              status = _nfs4_do_open(dir, dentry, flags, sattr, cred, &res);
-+              status = _nfs4_do_open(dir, path, flags, sattr, cred, &res);
-               if (status == 0)
-                       break;
-               /* NOTE: BAD_SEQID means the server and client disagree about the
-@@ -1101,6 +1117,7 @@
+-      unsigned long flags;
+-      u8 index, i, channel;
+-
+-      spin_lock_irqsave(&(host->allocation_lock), flags);
+-      channel = host->index;  /* Channel */
+-      index = scb->scbidx;
+-      i = index / 32;
+-      index %= 32;
+-      host->allocation_map[channel][i] |= (1 << index);
+-      spin_unlock_irqrestore(&(host->allocation_lock), flags);
++      ULONG flags;
++      UCHAR Index;
++      UCHAR i;
++      UCHAR Ch;
++
++      spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
++      Ch = hcsp->HCS_Index;
++      Index = scbp->SCB_ScbIdx;
++      i = Index / 32;
++      Index %= 32;
++      hcsp->BitAllocFlag[Ch][i] |= (1 << Index);
++      spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
  }
  
- struct nfs4_closedata {
-+      struct path path;
-       struct inode *inode;
-       struct nfs4_state *state;
-       struct nfs_closeargs arg;
-@@ -1117,6 +1134,8 @@
-       nfs4_put_open_state(calldata->state);
-       nfs_free_seqid(calldata->arg.seqid);
-       nfs4_put_state_owner(sp);
-+      dput(calldata->path.dentry);
-+      mntput(calldata->path.mnt);
-       kfree(calldata);
- }
+-/**
+- *    orchid_abort_scb        -       abort a command
+- *
+- *    Abort a queued command that has been passed to the firmware layer
+- *    if possible. This is all handled by the firmware. We aks the firmware
+- *    and it either aborts the command or fails
+- */
+-
+-static int orchid_abort_scb(struct orc_host * host, struct orc_scb * scb)
++/*****************************************************************************
++ Function name  : abort_SCB
++ Description    : Abort a queued command.
++                       (commands that are on the bus can't be aborted easily)
++ Input          : pHCB  -       Pointer to host adapter structure
++ Output         : None.
++ Return         : pSRB  -       Pointer to SCSI request block.
++*****************************************************************************/
++static int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb)
+ {
+-      unsigned char data, status;
++      unsigned char bData, bStatus;
+-      outb(ORC_CMD_ABORT_SCB, host->base + ORC_HDATA);        /* Write command */
+-      outb(HDO, host->base + ORC_HCTRL);
+-      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
++      ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_ABORT_SCB);  /* Write command */
++      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
++      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
+               return 0;
  
-@@ -1209,18 +1228,20 @@
-  *
-  * NOTE: Caller must be holding the sp->so_owner semaphore!
-  */
--int nfs4_do_close(struct inode *inode, struct nfs4_state *state) 
-+int nfs4_do_close(struct path *path, struct nfs4_state *state) 
- {
--      struct nfs_server *server = NFS_SERVER(inode);
-+      struct nfs_server *server = NFS_SERVER(state->inode);
-       struct nfs4_closedata *calldata;
-+      struct nfs4_state_owner *sp = state->owner;
-+      struct rpc_task *task;
-       int status = -ENOMEM;
+-      outb(scb->scbidx, host->base + ORC_HDATA);      /* Write address */
+-      outb(HDO, host->base + ORC_HCTRL);
+-      if (wait_HDO_off(host) == 0)    /* Wait HDO off   */
++      ORC_WR(hcsp->HCS_Base + ORC_HDATA, pScb->SCB_ScbIdx);   /* Write address */
++      ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
++      if (waitHDOoff(hcsp) == 0)      /* Wait HDO off   */
+               return 0;
  
-       calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
-       if (calldata == NULL)
-               goto out;
--      calldata->inode = inode;
-+      calldata->inode = state->inode;
-       calldata->state = state;
--      calldata->arg.fh = NFS_FH(inode);
-+      calldata->arg.fh = NFS_FH(state->inode);
-       calldata->arg.stateid = &state->stateid;
-       /* Serialization for the sequence id */
-       calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
-@@ -1229,36 +1250,44 @@
-       calldata->arg.bitmask = server->attr_bitmask;
-       calldata->res.fattr = &calldata->fattr;
-       calldata->res.server = server;
-+      calldata->path.mnt = mntget(path->mnt);
-+      calldata->path.dentry = dget(path->dentry);
+-      if (wait_hdi_set(host, &data) == 0)     /* Wait HDI set   */
++      if (waitHDIset(hcsp, &bData) == 0)      /* Wait HDI set   */
+               return 0;
+-      status = inb(host->base + ORC_HDATA);
+-      outb(data, host->base + ORC_HSTUS);     /* Clear HDI    */
++      bStatus = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
++      ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);      /* Clear HDI    */
  
--      status = nfs4_call_async(server->client, &nfs4_close_ops, calldata);
--      if (status == 0)
--              goto out;
+-      if (status == 1)        /* 0 - Successfully               */
++      if (bStatus == 1)       /* 0 - Successfully               */
+               return 0;       /* 1 - Fail                     */
+       return 1;
+ }
+-static int inia100_abort_cmd(struct orc_host * host, struct scsi_cmnd *cmd)
++/*****************************************************************************
++ Function name  : inia100_abort
++ Description    : Abort a queued command.
++                       (commands that are on the bus can't be aborted easily)
++ Input          : pHCB  -       Pointer to host adapter structure
++ Output         : None.
++ Return         : pSRB  -       Pointer to SCSI request block.
++*****************************************************************************/
++static int orc_abort_srb(ORC_HCS * hcsp, struct scsi_cmnd *SCpnt)
+ {
+-      struct orc_extended_scb *escb;
+-      struct orc_scb *scb;
+-      u8 i;
+-      unsigned long flags;
 -
--      nfs_free_seqid(calldata->arg.seqid);
-+      task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata);
-+      if (IS_ERR(task))
-+              return PTR_ERR(task);
-+      rpc_put_task(task);
-+      return 0;
- out_free_calldata:
-       kfree(calldata);
- out:
-+      nfs4_put_open_state(state);
-+      nfs4_put_state_owner(sp);
-       return status;
+-      spin_lock_irqsave(&(host->allocation_lock), flags);
+-
+-      scb = host->scb_virt;
+-
+-      /* Walk the queue until we find the SCB that belongs to the command
+-         block. This isn't a performance critical path so a walk in the park
+-         here does no harm */
+-
+-      for (i = 0; i < ORC_MAXQUEUE; i++, scb++) {
+-              escb = scb->escb;
+-              if (scb->status && escb->srb == cmd) {
+-                      if (scb->tag_msg == 0) {
+-                              goto out;
++      ESCB *pVirEscb;
++      ORC_SCB *pVirScb;
++      UCHAR i;
++      ULONG flags;
++
++      spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
++
++      pVirScb = hcsp->HCS_virScbArray;
++
++      for (i = 0; i < ORC_MAXQUEUE; i++, pVirScb++) {
++              pVirEscb = pVirScb->SCB_EScb;
++              if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt)) {
++                      if (pVirScb->SCB_TagMsg == 0) {
++                              spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
++                              return FAILED;
+                       } else {
+-                              /* Issue an ABORT to the firmware */
+-                              if (orchid_abort_scb(host, scb)) {
+-                                      escb->srb = NULL;
+-                                      spin_unlock_irqrestore(&host->allocation_lock, flags);
++                              if (abort_SCB(hcsp, pVirScb)) {
++                                      pVirEscb->SCB_Srb = NULL;
++                                      spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+                                       return SUCCESS;
+-                              } else
+-                                      goto out;
++                              } else {
++                                      spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
++                                      return FAILED;
++                              }
+                       }
+               }
+       }
+-out:
+-      spin_unlock_irqrestore(&host->allocation_lock, flags);
++      spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+       return FAILED;
  }
  
--static int nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
-+static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state)
- {
-       struct file *filp;
+-/**
+- *    orc_interrupt           -       IRQ processing
+- *    @host: Host causing the interrupt
+- *
+- *    This function is called from the IRQ handler and protected
+- *    by the host lock. While the controller reports that there are
+- *    scb's for processing we pull them off the controller, turn the
+- *    index into a host address pointer to the scb and call the scb
+- *    handler.
+- *
+- *    Returns IRQ_HANDLED if any SCBs were processed, IRQ_NONE otherwise
+- */
+-
+-static irqreturn_t orc_interrupt(struct orc_host * host)
++/***********************************************************************
++ Routine Description:
++        This is the interrupt service routine for the Orchid SCSI adapter.
++        It reads the interrupt register to determine if the adapter is indeed
++        the source of the interrupt and clears the interrupt at the device.
++ Arguments:
++        HwDeviceExtension - HBA miniport driver's adapter data storage
++ Return Value:
++***********************************************************************/
++static void orc_interrupt(
++                        ORC_HCS * hcsp
++)
+ {
+-      u8 scb_index;
+-      struct orc_scb *scb;
++      BYTE bScbIdx;
++      ORC_SCB *pScb;
+-      /* Check if we have an SCB queued for servicing */
+-      if (inb(host->base + ORC_RQUEUECNT) == 0)
+-              return IRQ_NONE;
++      if (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT) == 0) {
++              return;         // 0;
  
--      filp = lookup_instantiate_filp(nd, dentry, NULL);
-+      filp = lookup_instantiate_filp(nd, path->dentry, NULL);
-       if (!IS_ERR(filp)) {
-               struct nfs_open_context *ctx;
-               ctx = (struct nfs_open_context *)filp->private_data;
-               ctx->state = state;
-               return 0;
++      }
+       do {
+-              /* Get the SCB index of the SCB to service */
+-              scb_index = inb(host->base + ORC_RQUEUE);
++              bScbIdx = ORC_RD(hcsp->HCS_Base, ORC_RQUEUE);
+-              /* Translate it back to a host pointer */
+-              scb = (struct orc_scb *) ((unsigned long) host->scb_virt + (unsigned long) (sizeof(struct orc_scb) * scb_index));
+-              scb->status = 0x0;
+-              /* Process the SCB */
+-              inia100_scb_handler(host, scb);
+-      } while (inb(host->base + ORC_RQUEUECNT));
+-      return IRQ_HANDLED;
+-}                             /* End of I1060Interrupt() */
++              pScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (ULONG) (sizeof(ORC_SCB) * bScbIdx));
++              pScb->SCB_Status = 0x0;
+-/**
+- *    inia100_build_scb       -       build SCB
+- *    @host: host owing the control block
+- *    @scb: control block to use
+- *    @cmd: Mid layer command
+- *
+- *    Build a host adapter control block from the SCSI mid layer command
+- */
++              inia100SCBPost((BYTE *) hcsp, (BYTE *) pScb);
++      } while (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT));
++      return;                 //1;
++
++}                             /* End of I1060Interrupt() */
+-static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, struct scsi_cmnd * cmd)
++/*****************************************************************************
++ Function name  : inia100BuildSCB
++ Description    : 
++ Input          : pHCB  -       Pointer to host adapter structure
++ Output         : None.
++ Return         : pSRB  -       Pointer to SCSI request block.
++*****************************************************************************/
++static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, struct scsi_cmnd * SCpnt)
+ {                             /* Create corresponding SCB     */
+-      struct scatterlist *sg;
+-      struct orc_sgent *sgent;                /* Pointer to SG list           */
++      struct scatterlist *pSrbSG;
++      ORC_SG *pSG;            /* Pointer to SG list           */
+       int i, count_sg;
+-      struct orc_extended_scb *escb;
++      ESCB *pEScb;
+-      /* Links between the escb, scb and Linux scsi midlayer cmd */
+-      escb = scb->escb;
+-      escb->srb = cmd;
+-      sgent = NULL;
+-
+-      /* Set up the SCB to do a SCSI command block */
+-      scb->opcode = ORC_EXECSCSI;
+-      scb->flags = SCF_NO_DCHK;       /* Clear done bit               */
+-      scb->target = cmd->device->id;
+-      scb->lun = cmd->device->lun;
+-      scb->reserved0 = 0;
+-      scb->reserved1 = 0;
+-      scb->sg_len = 0;
+-
+-      scb->xferlen = (u32) scsi_bufflen(cmd);
+-      sgent = (struct orc_sgent *) & escb->sglist[0];
+-
+-      count_sg = scsi_dma_map(cmd);
+-      BUG_ON(count_sg < 0);
+-
+-      /* Build the scatter gather lists */
+-      if (count_sg) {
+-              scb->sg_len = (u32) (count_sg * 8);
+-              scsi_for_each_sg(cmd, sg, count_sg, i) {
+-                      sgent->base = (u32) sg_dma_address(sg);
+-                      sgent->length = (u32) sg_dma_len(sg);
+-                      sgent++;
+-              }
++      pEScb = pSCB->SCB_EScb;
++      pEScb->SCB_Srb = SCpnt;
++      pSG = NULL;
++
++      pSCB->SCB_Opcode = ORC_EXECSCSI;
++      pSCB->SCB_Flags = SCF_NO_DCHK;  /* Clear done bit               */
++      pSCB->SCB_Target = SCpnt->device->id;
++      pSCB->SCB_Lun = SCpnt->device->lun;
++      pSCB->SCB_Reserved0 = 0;
++      pSCB->SCB_Reserved1 = 0;
++      pSCB->SCB_SGLen = 0;
++
++      if ((pSCB->SCB_XferLen = (U32) SCpnt->request_bufflen)) {
++              pSG = (ORC_SG *) & pEScb->ESCB_SGList[0];
++              if (SCpnt->use_sg) {
++                      pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
++                      count_sg = pci_map_sg(pHCB->pdev, pSrbSG, SCpnt->use_sg,
++                                      SCpnt->sc_data_direction);
++                      pSCB->SCB_SGLen = (U32) (count_sg * 8);
++                      for (i = 0; i < count_sg; i++, pSG++, pSrbSG++) {
++                              pSG->SG_Ptr = (U32) sg_dma_address(pSrbSG);
++                              pSG->SG_Len = (U32) sg_dma_len(pSrbSG);
++                      }
++              } else if (SCpnt->request_bufflen != 0) {/* Non SG */
++                      pSCB->SCB_SGLen = 0x8;
++                      SCpnt->SCp.dma_handle = pci_map_single(pHCB->pdev,
++                                      SCpnt->request_buffer,
++                                      SCpnt->request_bufflen,
++                                      SCpnt->sc_data_direction);
++                      pSG->SG_Ptr = (U32) SCpnt->SCp.dma_handle;
++                      pSG->SG_Len = (U32) SCpnt->request_bufflen;
+               } else {
+-              scb->sg_len = 0;
+-              sgent->base = 0;
+-              sgent->length = 0;
+-      }
+-      scb->sg_addr = (u32) scb->sense_addr;
+-      scb->hastat = 0;
+-      scb->tastat = 0;
+-      scb->link = 0xFF;
+-      scb->sense_len = SENSE_SIZE;
+-      scb->cdb_len = cmd->cmd_len;
+-      if (scb->cdb_len >= IMAX_CDB) {
+-              printk("max cdb length= %x\b", cmd->cmd_len);
+-              scb->cdb_len = IMAX_CDB;
+-      }
+-      scb->ident = cmd->device->lun | DISC_ALLOW;
+-      if (cmd->device->tagged_supported) {    /* Tag Support                  */
+-              scb->tag_msg = SIMPLE_QUEUE_TAG;        /* Do simple tag only   */
++                      pSCB->SCB_SGLen = 0;
++                      pSG->SG_Ptr = 0;
++                      pSG->SG_Len = 0;
++              }
++      }
++      pSCB->SCB_SGPAddr = (U32) pSCB->SCB_SensePAddr;
++      pSCB->SCB_HaStat = 0;
++      pSCB->SCB_TaStat = 0;
++      pSCB->SCB_Link = 0xFF;
++      pSCB->SCB_SenseLen = SENSE_SIZE;
++      pSCB->SCB_CDBLen = SCpnt->cmd_len;
++      if (pSCB->SCB_CDBLen >= IMAX_CDB) {
++              printk("max cdb length= %x\b", SCpnt->cmd_len);
++              pSCB->SCB_CDBLen = IMAX_CDB;
++      }
++      pSCB->SCB_Ident = SCpnt->device->lun | DISC_ALLOW;
++      if (SCpnt->device->tagged_supported) {  /* Tag Support                  */
++              pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG;    /* Do simple tag only   */
+       } else {
+-              scb->tag_msg = 0;       /* No tag support               */
++              pSCB->SCB_TagMsg = 0;   /* No tag support               */
        }
--      nfs4_close_state(state, nd->intent.open.flags);
-+      nfs4_close_state(path, state, nd->intent.open.flags);
-       return PTR_ERR(filp);
+-      memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len);
++      memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, pSCB->SCB_CDBLen);
++      return;
  }
  
- struct dentry *
- nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
- {
-+      struct path path = {
-+              .mnt = nd->mnt,
-+              .dentry = dentry,
-+      };
-       struct iattr attr;
-       struct rpc_cred *cred;
-       struct nfs4_state *state;
-@@ -1277,7 +1306,7 @@
-       cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
-       if (IS_ERR(cred))
-               return (struct dentry *)cred;
--      state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
-+      state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred);
-       put_rpccred(cred);
-       if (IS_ERR(state)) {
-               if (PTR_ERR(state) == -ENOENT)
-@@ -1287,13 +1316,17 @@
-       res = d_add_unique(dentry, igrab(state->inode));
-       if (res != NULL)
-               dentry = res;
--      nfs4_intent_set_file(nd, dentry, state);
-+      nfs4_intent_set_file(nd, &path, state);
-       return res;
+-/**
+- *    inia100_queue           -       queue command with host
+- *    @cmd: Command block
+- *    @done: Completion function
+- *
+- *    Called by the mid layer to queue a command. Process the command
+- *    block, build the host specific scb structures and if there is room
+- *    queue the command down to the controller
+- */
+-
+-static int inia100_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
++/*****************************************************************************
++ Function name  : inia100_queue
++ Description    : Queue a command and setup interrupts for a free bus.
++ Input          : pHCB  -       Pointer to host adapter structure
++ Output         : None.
++ Return         : pSRB  -       Pointer to SCSI request block.
++*****************************************************************************/
++static int inia100_queue(struct scsi_cmnd * SCpnt, void (*done) (struct scsi_cmnd *))
+ {
+-      struct orc_scb *scb;
+-      struct orc_host *host;          /* Point to Host adapter control block */
++      register ORC_SCB *pSCB;
++      ORC_HCS *pHCB;          /* Point to Host adapter control block */
+-      host = (struct orc_host *) cmd->device->host->hostdata;
+-      cmd->scsi_done = done;
++      pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
++      SCpnt->scsi_done = done;
+       /* Get free SCSI control block  */
+-      if ((scb = orc_alloc_scb(host)) == NULL)
++      if ((pSCB = orc_alloc_scb(pHCB)) == NULL)
+               return SCSI_MLQUEUE_HOST_BUSY;
+-      inia100_build_scb(host, scb, cmd);
+-      orc_exec_scb(host, scb);        /* Start execute SCB            */
+-      return 0;
++      inia100BuildSCB(pHCB, pSCB, SCpnt);
++      orc_exec_scb(pHCB, pSCB);       /* Start execute SCB            */
++
++      return (0);
  }
  
- int
- nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
+ /*****************************************************************************
+  Function name  : inia100_abort
+  Description    : Abort a queued command.
+                        (commands that are on the bus can't be aborted easily)
+- Input          : host  -       Pointer to host adapter structure
++ Input          : pHCB  -       Pointer to host adapter structure
+  Output         : None.
+  Return         : pSRB  -       Pointer to SCSI request block.
+ *****************************************************************************/
+-static int inia100_abort(struct scsi_cmnd * cmd)
++static int inia100_abort(struct scsi_cmnd * SCpnt)
  {
-+      struct path path = {
-+              .mnt = nd->mnt,
-+              .dentry = dentry,
-+      };
-       struct rpc_cred *cred;
-       struct nfs4_state *state;
+-      struct orc_host *host;
++      ORC_HCS *hcsp;
  
-@@ -1302,7 +1335,7 @@
-               return PTR_ERR(cred);
-       state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
-       if (IS_ERR(state))
--              state = nfs4_do_open(dir, dentry, openflags, NULL, cred);
-+              state = nfs4_do_open(dir, &path, openflags, NULL, cred);
-       put_rpccred(cred);
-       if (IS_ERR(state)) {
-               switch (PTR_ERR(state)) {
-@@ -1318,10 +1351,10 @@
-               }
-       }
-       if (state->inode == dentry->d_inode) {
--              nfs4_intent_set_file(nd, dentry, state);
-+              nfs4_intent_set_file(nd, &path, state);
-               return 1;
-       }
--      nfs4_close_state(state, openflags);
-+      nfs4_close_state(&path, state, openflags);
- out_drop:
-       d_drop(dentry);
-       return 0;
-@@ -1752,6 +1785,10 @@
- nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                  int flags, struct nameidata *nd)
- {
-+      struct path path = {
-+              .mnt = nd->mnt,
-+              .dentry = dentry,
-+      };
-       struct nfs4_state *state;
-       struct rpc_cred *cred;
-       int status = 0;
-@@ -1761,7 +1798,7 @@
-               status = PTR_ERR(cred);
-               goto out;
-       }
--      state = nfs4_do_open(dir, dentry, flags, sattr, cred);
-+      state = nfs4_do_open(dir, &path, flags, sattr, cred);
-       put_rpccred(cred);
-       if (IS_ERR(state)) {
-               status = PTR_ERR(state);
-@@ -1773,11 +1810,12 @@
-               status = nfs4_do_setattr(state->inode, &fattr, sattr, state);
-               if (status == 0)
-                       nfs_setattr_update_inode(state->inode, sattr);
-+              nfs_post_op_update_inode(state->inode, &fattr);
-       }
--      if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN))
--              status = nfs4_intent_set_file(nd, dentry, state);
-+      if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
-+              status = nfs4_intent_set_file(nd, &path, state);
-       else
--              nfs4_close_state(state, flags);
-+              nfs4_close_state(&path, state, flags);
- out:
-       return status;
+-      host = (struct orc_host *) cmd->device->host->hostdata;
+-      return inia100_abort_cmd(host, cmd);
++      hcsp = (ORC_HCS *) SCpnt->device->host->hostdata;
++      return orc_abort_srb(hcsp, SCpnt);
  }
-@@ -3285,7 +3323,7 @@
-               memcpy(data->lsp->ls_stateid.data, data->res.stateid.data,
-                                       sizeof(data->lsp->ls_stateid.data));
-               data->lsp->ls_flags |= NFS_LOCK_INITIALIZED;
--              renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp);
-+              renew_lease(NFS_SERVER(data->ctx->path.dentry->d_inode), data->timestamp);
-       }
-       nfs_increment_lock_seqid(data->rpc_status, data->arg.lock_seqid);
- out:
-diff -Nurb linux-2.6.22-570/fs/nfs/nfs4state.c linux-2.6.22-590/fs/nfs/nfs4state.c
---- linux-2.6.22-570/fs/nfs/nfs4state.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/nfs4state.c        2008-01-02 13:56:37.000000000 -0500
-@@ -341,7 +341,7 @@
- /*
-  * Close the current file.
-  */
--void nfs4_close_state(struct nfs4_state *state, mode_t mode)
-+void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
- {
-       struct inode *inode = state->inode;
-       struct nfs4_state_owner *owner = state->owner;
-@@ -375,10 +375,11 @@
-       spin_unlock(&inode->i_lock);
-       spin_unlock(&owner->so_lock);
  
--      if (oldstate != newstate && nfs4_do_close(inode, state) == 0)
--              return;
-+      if (oldstate == newstate) {
-       nfs4_put_open_state(state);
-       nfs4_put_state_owner(owner);
-+      } else
-+              nfs4_do_close(path, state);
+ /*****************************************************************************
+  Function name  : inia100_reset
+  Description    : Reset registers, reset a hanging bus and
+                   kill active and disconnected commands for target w/o soft reset
+- Input          : host  -       Pointer to host adapter structure
++ Input          : pHCB  -       Pointer to host adapter structure
+  Output         : None.
+  Return         : pSRB  -       Pointer to SCSI request block.
+ *****************************************************************************/
+-static int inia100_bus_reset(struct scsi_cmnd * cmd)
++static int inia100_bus_reset(struct scsi_cmnd * SCpnt)
+ {                             /* I need Host Control Block Information */
+-      struct orc_host *host;
+-      host = (struct orc_host *) cmd->device->host->hostdata;
+-      return orc_reset_scsi_bus(host);
++      ORC_HCS *pHCB;
++      pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
++      return orc_reset_scsi_bus(pHCB);
  }
  
- /*
-diff -Nurb linux-2.6.22-570/fs/nfs/nfs4xdr.c linux-2.6.22-590/fs/nfs/nfs4xdr.c
---- linux-2.6.22-570/fs/nfs/nfs4xdr.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/nfs4xdr.c  2008-01-02 13:56:37.000000000 -0500
-@@ -3269,7 +3269,7 @@
- static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
- {
-         __be32 *p;
--        uint32_t bmlen;
-+        uint32_t savewords, bmlen, i;
-         int status;
+ /*****************************************************************************
+  Function name  : inia100_device_reset
+  Description    : Reset the device
+- Input          : host  -       Pointer to host adapter structure
++ Input          : pHCB  -       Pointer to host adapter structure
+  Output         : None.
+  Return         : pSRB  -       Pointer to SCSI request block.
+ *****************************************************************************/
+-static int inia100_device_reset(struct scsi_cmnd * cmd)
++static int inia100_device_reset(struct scsi_cmnd * SCpnt)
+ {                             /* I need Host Control Block Information */
+-      struct orc_host *host;
+-      host = (struct orc_host *) cmd->device->host->hostdata;
+-      return orc_device_reset(host, cmd, scmd_id(cmd));
++      ORC_HCS *pHCB;
++      pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
++      return orc_device_reset(pHCB, SCpnt, scmd_id(SCpnt));
  
-         status = decode_op_hdr(xdr, OP_OPEN);
-@@ -3287,7 +3287,12 @@
-                 goto xdr_error;
+ }
  
-         READ_BUF(bmlen << 2);
--        p += bmlen;
-+      savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
-+      for (i = 0; i < savewords; ++i)
-+              READ32(res->attrset[i]);
-+
-+      p += (bmlen - savewords);
-+
-       return decode_delegation(xdr, res);
- xdr_error:
-       dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen);
-diff -Nurb linux-2.6.22-570/fs/nfs/pagelist.c linux-2.6.22-590/fs/nfs/pagelist.c
---- linux-2.6.22-570/fs/nfs/pagelist.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/pagelist.c 2008-01-02 13:56:37.000000000 -0500
-@@ -85,9 +85,8 @@
-       req->wb_offset  = offset;
-       req->wb_pgbase  = offset;
-       req->wb_bytes   = count;
--      atomic_set(&req->wb_count, 1);
-       req->wb_context = get_nfs_open_context(ctx);
+-/**
+- *    inia100_scb_handler     -       interrupt callback
+- *    @host: Host causing the interrupt
+- *    @scb: SCB the controller returned as needing processing
+- *
+- *    Perform completion processing on a control block. Do the conversions
+- *    from host to SCSI midlayer error coding, save any sense data and
+- *    the complete with the midlayer and recycle the scb.
+- */
 -
-+      kref_init(&req->wb_kref);
-       return req;
- }
+-static void inia100_scb_handler(struct orc_host *host, struct orc_scb *scb)
++/*****************************************************************************
++ Function name  : inia100SCBPost
++ Description    : This is callback routine be called when orc finish one
++                      SCSI command.
++ Input          : pHCB  -       Pointer to host adapter control block.
++                pSCB  -       Pointer to SCSI control block.
++ Output         : None.
++ Return         : None.
++*****************************************************************************/
++static void inia100SCBPost(BYTE * pHcb, BYTE * pScb)
+ {
+-      struct scsi_cmnd *cmd;  /* Pointer to SCSI request block */
+-      struct orc_extended_scb *escb;
+-
+-      escb = scb->escb;
+-      if ((cmd = (struct scsi_cmnd *) escb->srb) == NULL) {
+-              printk(KERN_ERR "inia100_scb_handler: SRB pointer is empty\n");
+-              orc_release_scb(host, scb);     /* Release SCB for current channel */
++      struct scsi_cmnd *pSRB; /* Pointer to SCSI request block */
++      ORC_HCS *pHCB;
++      ORC_SCB *pSCB;
++      ESCB *pEScb;
++
++      pHCB = (ORC_HCS *) pHcb;
++      pSCB = (ORC_SCB *) pScb;
++      pEScb = pSCB->SCB_EScb;
++      if ((pSRB = (struct scsi_cmnd *) pEScb->SCB_Srb) == 0) {
++              printk("inia100SCBPost: SRB pointer is empty\n");
++              orc_release_scb(pHCB, pSCB);    /* Release SCB for current channel */
+               return;
+       }
+-      escb->srb = NULL;
++      pEScb->SCB_Srb = NULL;
+-      switch (scb->hastat) {
++      switch (pSCB->SCB_HaStat) {
+       case 0x0:
+       case 0xa:               /* Linked command complete without error and linked normally */
+       case 0xb:               /* Linked command complete without error interrupt generated */
+-              scb->hastat = 0;
++              pSCB->SCB_HaStat = 0;
+               break;
+       case 0x11:              /* Selection time out-The initiator selection or target
+                                  reselection was not complete within the SCSI Time out period */
+-              scb->hastat = DID_TIME_OUT;
++              pSCB->SCB_HaStat = DID_TIME_OUT;
+               break;
+       case 0x14:              /* Target bus phase sequence failure-An invalid bus phase or bus
+                                  phase sequence was requested by the target. The host adapter
+                                  will generate a SCSI Reset Condition, notifying the host with
+                                  a SCRD interrupt */
+-              scb->hastat = DID_RESET;
++              pSCB->SCB_HaStat = DID_RESET;
+               break;
+       case 0x1a:              /* SCB Aborted. 07/21/98 */
+-              scb->hastat = DID_ABORT;
++              pSCB->SCB_HaStat = DID_ABORT;
+               break;
  
-@@ -109,29 +108,29 @@
- }
+       case 0x12:              /* Data overrun/underrun-The target attempted to transfer more data
+@@ -1022,41 +984,46 @@
+       case 0x16:              /* Invalid CCB Operation Code-The first byte of the CCB was invalid. */
  
- /**
-- * nfs_set_page_writeback_locked - Lock a request for writeback
-+ * nfs_set_page_tag_locked - Tag a request as locked
-  * @req:
-  */
--int nfs_set_page_writeback_locked(struct nfs_page *req)
-+static int nfs_set_page_tag_locked(struct nfs_page *req)
- {
--      struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
-+      struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode);
+       default:
+-              printk(KERN_DEBUG "inia100: %x %x\n", scb->hastat, scb->tastat);
+-              scb->hastat = DID_ERROR;        /* Couldn't find any better */
++              printk("inia100: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat);
++              pSCB->SCB_HaStat = DID_ERROR;   /* Couldn't find any better */
+               break;
+       }
  
-       if (!nfs_lock_request(req))
-               return 0;
--      radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
-+      radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
-       return 1;
+-      if (scb->tastat == 2) { /* Check condition              */
+-              memcpy((unsigned char *) &cmd->sense_buffer[0],
+-                 (unsigned char *) &escb->sglist[0], SENSE_SIZE);
+-      }
+-      cmd->result = scb->tastat | (scb->hastat << 16);
+-      scsi_dma_unmap(cmd);
+-      cmd->scsi_done(cmd);    /* Notify system DONE           */
+-      orc_release_scb(host, scb);     /* Release SCB for current channel */
++      if (pSCB->SCB_TaStat == 2) {    /* Check condition              */
++              memcpy((unsigned char *) &pSRB->sense_buffer[0],
++                 (unsigned char *) &pEScb->ESCB_SGList[0], SENSE_SIZE);
++      }
++      pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);
++
++      if (pSRB->use_sg) {
++              pci_unmap_sg(pHCB->pdev,
++                           (struct scatterlist *)pSRB->request_buffer,
++                           pSRB->use_sg, pSRB->sc_data_direction);
++      } else if (pSRB->request_bufflen != 0) {
++              pci_unmap_single(pHCB->pdev, pSRB->SCp.dma_handle,
++                               pSRB->request_bufflen,
++                               pSRB->sc_data_direction);
++      }
++
++      pSRB->scsi_done(pSRB);  /* Notify system DONE           */
++
++      orc_release_scb(pHCB, pSCB);    /* Release SCB for current channel */
  }
  
- /**
-- * nfs_clear_page_writeback - Unlock request and wake up sleepers
-+ * nfs_clear_page_tag_locked - Clear request tag and wake up sleepers
+-/**
+- *    inia100_intr            -       interrupt handler
+- *    @irqno: Interrupt value
+- *    @devid: Host adapter
+- *
+- *    Entry point for IRQ handling. All the real work is performed
+- *    by orc_interrupt.
++/*
++ * Interrupt handler (main routine of the driver)
   */
--void nfs_clear_page_writeback(struct nfs_page *req)
-+void nfs_clear_page_tag_locked(struct nfs_page *req)
+ static irqreturn_t inia100_intr(int irqno, void *devid)
  {
--      struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
-+      struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode);
+-      struct Scsi_Host *shost = (struct Scsi_Host *)devid;
+-      struct orc_host *host = (struct orc_host *)shost->hostdata;
++      struct Scsi_Host *host = (struct Scsi_Host *)devid;
++      ORC_HCS *pHcb = (ORC_HCS *)host->hostdata;
+       unsigned long flags;
+-      irqreturn_t res;
  
-       if (req->wb_page != NULL) {
-               spin_lock(&nfsi->req_lock);
--              radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
-+              radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
-               spin_unlock(&nfsi->req_lock);
-       }
-       nfs_unlock_request(req);
-@@ -160,11 +159,9 @@
-  *
-  * Note: Should never be called with the spinlock held!
-  */
--void
--nfs_release_request(struct nfs_page *req)
-+static void nfs_free_request(struct kref *kref)
- {
--      if (!atomic_dec_and_test(&req->wb_count))
--              return;
-+      struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref);
+-      spin_lock_irqsave(shost->host_lock, flags);
+-      res = orc_interrupt(host);
+-      spin_unlock_irqrestore(shost->host_lock, flags);
++      spin_lock_irqsave(host->host_lock, flags);
++      orc_interrupt(pHcb);
++      spin_unlock_irqrestore(host->host_lock, flags);
  
-       /* Release struct file or cached credential */
-       nfs_clear_request(req);
-@@ -172,6 +169,11 @@
-       nfs_page_free(req);
+-      return res;
++      return IRQ_HANDLED;
  }
  
-+void nfs_release_request(struct nfs_page *req)
-+{
-+      kref_put(&req->wb_kref, nfs_free_request);
-+}
-+
- static int nfs_wait_bit_interruptible(void *word)
- {
-       int ret = 0;
-@@ -193,7 +195,7 @@
- int
- nfs_wait_on_request(struct nfs_page *req)
- {
--        struct rpc_clnt       *clnt = NFS_CLIENT(req->wb_context->dentry->d_inode);
-+        struct rpc_clnt       *clnt = NFS_CLIENT(req->wb_context->path.dentry->d_inode);
-       sigset_t oldmask;
-       int ret = 0;
-@@ -379,10 +381,10 @@
- /**
-  * nfs_scan_list - Scan a list for matching requests
-  * @nfsi: NFS inode
-- * @head: One of the NFS inode request lists
-  * @dst: Destination list
-  * @idx_start: lower bound of page->index to scan
-  * @npages: idx_start + npages sets the upper bound to scan.
-+ * @tag: tag to scan for
-  *
-  * Moves elements from one of the inode request lists.
-  * If the number of requests is set to 0, the entire address_space
-@@ -390,9 +392,9 @@
-  * The requests are *not* checked to ensure that they form a contiguous set.
-  * You must be holding the inode's req_lock when calling this function
-  */
--int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,
-+int nfs_scan_list(struct nfs_inode *nfsi,
-               struct list_head *dst, pgoff_t idx_start,
--              unsigned int npages)
-+              unsigned int npages, int tag)
+ static struct scsi_host_template inia100_template = {
+@@ -1077,12 +1044,12 @@
+               const struct pci_device_id *id)
  {
-       struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
-       struct nfs_page *req;
-@@ -407,9 +409,9 @@
-               idx_end = idx_start + npages - 1;
+       struct Scsi_Host *shost;
+-      struct orc_host *host;
++      ORC_HCS *pHCB;
+       unsigned long port, bios;
+       int error = -ENODEV;
+       u32 sz;
+-      unsigned long biosaddr;
+-      char *bios_phys;
++      unsigned long dBiosAdr;
++      char *pbBiosAdr;
  
-       for (;;) {
--              found = radix_tree_gang_lookup(&nfsi->nfs_page_tree,
-+              found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
-                               (void **)&pgvec[0], idx_start,
--                              NFS_SCAN_MAXENTRIES);
-+                              NFS_SCAN_MAXENTRIES, tag);
-               if (found <= 0)
-                       break;
-               for (i = 0; i < found; i++) {
-@@ -417,15 +419,18 @@
-                       if (req->wb_index > idx_end)
-                               goto out;
-                       idx_start = req->wb_index + 1;
--                      if (req->wb_list_head != head)
--                              continue;
--                      if (nfs_set_page_writeback_locked(req)) {
-+                      if (nfs_set_page_tag_locked(req)) {
-                               nfs_list_remove_request(req);
-+                              radix_tree_tag_clear(&nfsi->nfs_page_tree,
-+                                              req->wb_index, tag);
-                               nfs_list_add_request(req, dst);
-                               res++;
-+                              if (res == INT_MAX)
-+                                      goto out;
-                       }
-               }
--
-+              /* for latency reduction */
-+              cond_resched_lock(&nfsi->req_lock);
+       if (pci_enable_device(pdev))
+               goto out;
+@@ -1101,55 +1068,55 @@
        }
- out:
-       return res;
-diff -Nurb linux-2.6.22-570/fs/nfs/read.c linux-2.6.22-590/fs/nfs/read.c
---- linux-2.6.22-570/fs/nfs/read.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/read.c     2008-01-02 13:56:37.000000000 -0500
-@@ -145,8 +145,8 @@
-       unlock_page(req->wb_page);
  
-       dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
--                      req->wb_context->dentry->d_inode->i_sb->s_id,
--                      (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
-+                      req->wb_context->path.dentry->d_inode->i_sb->s_id,
-+                      (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
-                       req->wb_bytes,
-                       (long long)req_offset(req));
-       nfs_clear_request(req);
-@@ -164,7 +164,7 @@
-       int flags;
+       /* <02> read from base address + 0x50 offset to get the bios value. */
+-      bios = inw(port + 0x50);
++      bios = ORC_RDWORD(port, 0x50);
  
-       data->req         = req;
--      data->inode       = inode = req->wb_context->dentry->d_inode;
-+      data->inode       = inode = req->wb_context->path.dentry->d_inode;
-       data->cred        = req->wb_context->cred;
  
-       data->args.fh     = NFS_FH(inode);
-@@ -483,17 +483,19 @@
-        */
-       error = nfs_wb_page(inode, page);
-       if (error)
--              goto out_error;
-+              goto out_unlock;
-+      if (PageUptodate(page))
-+              goto out_unlock;
+-      shost = scsi_host_alloc(&inia100_template, sizeof(struct orc_host));
++      shost = scsi_host_alloc(&inia100_template, sizeof(ORC_HCS));
+       if (!shost)
+               goto out_release_region;
  
-       error = -ESTALE;
-       if (NFS_STALE(inode))
--              goto out_error;
-+              goto out_unlock;
+-      host = (struct orc_host *)shost->hostdata;
+-      host->pdev = pdev;
+-      host->base = port;
+-      host->BIOScfg = bios;
+-      spin_lock_init(&host->allocation_lock);
++      pHCB = (ORC_HCS *)shost->hostdata;
++      pHCB->pdev = pdev;
++      pHCB->HCS_Base = port;
++      pHCB->HCS_BIOS = bios;
++      spin_lock_init(&pHCB->BitAllocFlagLock);
  
-       if (file == NULL) {
-               error = -EBADF;
-               ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
-               if (ctx == NULL)
--                      goto out_error;
-+                      goto out_unlock;
-       } else
-               ctx = get_nfs_open_context((struct nfs_open_context *)
-                               file->private_data);
-@@ -502,8 +504,7 @@
+       /* Get total memory needed for SCB */
+-      sz = ORC_MAXQUEUE * sizeof(struct orc_scb);
+-      host->scb_virt = pci_alloc_consistent(pdev, sz,
+-                      &host->scb_phys);
+-      if (!host->scb_virt) {
++      sz = ORC_MAXQUEUE * sizeof(ORC_SCB);
++      pHCB->HCS_virScbArray = pci_alloc_consistent(pdev, sz,
++                      &pHCB->HCS_physScbArray);
++      if (!pHCB->HCS_virScbArray) {
+               printk("inia100: SCB memory allocation error\n");
+               goto out_host_put;
+       }
+-      memset(host->scb_virt, 0, sz);
++      memset(pHCB->HCS_virScbArray, 0, sz);
  
-       put_nfs_open_context(ctx);
-       return error;
--
--out_error:
-+out_unlock:
-       unlock_page(page);
-       return error;
- }
-@@ -520,21 +521,32 @@
-       struct inode *inode = page->mapping->host;
-       struct nfs_page *new;
-       unsigned int len;
-+      int error;
-+
-+      error = nfs_wb_page(inode, page);
-+      if (error)
-+              goto out_unlock;
-+      if (PageUptodate(page))
-+              goto out_unlock;
+       /* Get total memory needed for ESCB */
+-      sz = ORC_MAXQUEUE * sizeof(struct orc_extended_scb);
+-      host->escb_virt = pci_alloc_consistent(pdev, sz,
+-                      &host->escb_phys);
+-      if (!host->escb_virt) {
++      sz = ORC_MAXQUEUE * sizeof(ESCB);
++      pHCB->HCS_virEscbArray = pci_alloc_consistent(pdev, sz,
++                      &pHCB->HCS_physEscbArray);
++      if (!pHCB->HCS_virEscbArray) {
+               printk("inia100: ESCB memory allocation error\n");
+               goto out_free_scb_array;
+       }
+-      memset(host->escb_virt, 0, sz);
++      memset(pHCB->HCS_virEscbArray, 0, sz);
+-      biosaddr = host->BIOScfg;
+-      biosaddr = (biosaddr << 4);
+-      bios_phys = phys_to_virt(biosaddr);
+-      if (init_orchid(host)) {        /* Initialize orchid chip */
++      dBiosAdr = pHCB->HCS_BIOS;
++      dBiosAdr = (dBiosAdr << 4);
++      pbBiosAdr = phys_to_virt(dBiosAdr);
++      if (init_orchid(pHCB)) {        /* Initialize orchid chip */
+               printk("inia100: initial orchid fail!!\n");
+               goto out_free_escb_array;
+       }
  
--      nfs_wb_page(inode, page);
-       len = nfs_page_length(page);
-       if (len == 0)
-               return nfs_return_empty_page(page);
-+
-       new = nfs_create_request(desc->ctx, inode, page, 0, len);
--      if (IS_ERR(new)) {
--                      SetPageError(page);
--                      unlock_page(page);
--                      return PTR_ERR(new);
--      }
-+      if (IS_ERR(new))
-+              goto out_error;
-+
-       if (len < PAGE_CACHE_SIZE)
-               zero_user_page(page, len, PAGE_CACHE_SIZE - len, KM_USER0);
-       nfs_pageio_add_request(desc->pgio, new);
+-      shost->io_port = host->base;
++      shost->io_port = pHCB->HCS_Base;
+       shost->n_io_port = 0xff;
+       shost->can_queue = ORC_MAXQUEUE;
+       shost->unique_id = shost->io_port;
+-      shost->max_id = host->max_targets;
++      shost->max_id = pHCB->HCS_MaxTar;
+       shost->max_lun = 16;
+-      shost->irq = pdev->irq;
+-      shost->this_id = host->scsi_id; /* Assign HCS index */
++      shost->irq = pHCB->HCS_Intr = pdev->irq;
++      shost->this_id = pHCB->HCS_SCSI_ID;     /* Assign HCS index */
+       shost->sg_tablesize = TOTAL_SG_ENTRY;
+       /* Initial orc chip           */
+@@ -1170,36 +1137,36 @@
+       scsi_scan_host(shost);
        return 0;
-+out_error:
-+      error = PTR_ERR(new);
-+      SetPageError(page);
-+out_unlock:
-+      unlock_page(page);
-+      return error;
- }
  
- int nfs_readpages(struct file *filp, struct address_space *mapping,
-diff -Nurb linux-2.6.22-570/fs/nfs/super.c linux-2.6.22-590/fs/nfs/super.c
---- linux-2.6.22-570/fs/nfs/super.c    2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/nfs/super.c    2008-01-02 13:56:37.000000000 -0500
-@@ -292,6 +292,7 @@
-               { NFS_MOUNT_NONLM, ",nolock", "" },
-               { NFS_MOUNT_NOACL, ",noacl", "" },
-               { NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
-+              { NFS_MOUNT_UNSHARED, ",nosharecache", ""},
-               { NFS_MOUNT_TAGGED, ",tag", "" },
-               { 0, NULL, NULL }
-       };
-@@ -432,7 +433,20 @@
-  */
- static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
- {
-+      struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb);
-+      struct rpc_clnt *rpc;
-+
-       shrink_submounts(vfsmnt, &nfs_automount_list);
-+      
-+      if (!(flags & MNT_FORCE))
-+              return;
-+      /* -EIO all pending I/O */
-+      rpc = server->client_acl;
-+      if (!IS_ERR(rpc))
-+              rpc_killall_tasks(rpc);
-+      rpc = server->client;
-+      if (!IS_ERR(rpc))
-+              rpc_killall_tasks(rpc);
+-out_free_irq:
++ out_free_irq:
+         free_irq(shost->irq, shost);
+-out_free_escb_array:
+-      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_extended_scb),
+-                      host->escb_virt, host->escb_phys);
+-out_free_scb_array:
+-      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_scb),
+-                      host->scb_virt, host->scb_phys);
+-out_host_put:
++ out_free_escb_array:
++      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB),
++                      pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray);
++ out_free_scb_array:
++      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB),
++                      pHCB->HCS_virScbArray, pHCB->HCS_physScbArray);
++ out_host_put:
+       scsi_host_put(shost);
+-out_release_region:
++ out_release_region:
+         release_region(port, 256);
+-out_disable_device:
++ out_disable_device:
+       pci_disable_device(pdev);
+-out:
++ out:
+       return error;
  }
  
- /*
-@@ -602,13 +616,51 @@
+ static void __devexit inia100_remove_one(struct pci_dev *pdev)
  {
-       struct nfs_server *server = data, *old = NFS_SB(sb);
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+-      struct orc_host *host = (struct orc_host *)shost->hostdata;
++      ORC_HCS *pHCB = (ORC_HCS *)shost->hostdata;
  
--      if (old->nfs_client != server->nfs_client)
-+      if (memcmp(&old->nfs_client->cl_addr,
-+                              &server->nfs_client->cl_addr,
-+                              sizeof(old->nfs_client->cl_addr)) != 0)
-+              return 0;
-+      /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
-+      if (old->flags & NFS_MOUNT_UNSHARED)
-               return 0;
-       if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
-               return 0;
-       return 1;
- }
+       scsi_remove_host(shost);
  
-+#define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS)
-+
-+static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, int flags)
-+{
-+      const struct nfs_server *a = s->s_fs_info;
-+      const struct rpc_clnt *clnt_a = a->client;
-+      const struct rpc_clnt *clnt_b = b->client;
-+
-+      if ((s->s_flags & NFS_MS_MASK) != (flags & NFS_MS_MASK))
-+              goto Ebusy;
-+      if (a->nfs_client != b->nfs_client)
-+              goto Ebusy;
-+      if (a->flags != b->flags)
-+              goto Ebusy;
-+      if (a->wsize != b->wsize)
-+              goto Ebusy;
-+      if (a->rsize != b->rsize)
-+              goto Ebusy;
-+      if (a->acregmin != b->acregmin)
-+              goto Ebusy;
-+      if (a->acregmax != b->acregmax)
-+              goto Ebusy;
-+      if (a->acdirmin != b->acdirmin)
-+              goto Ebusy;
-+      if (a->acdirmax != b->acdirmax)
-+              goto Ebusy;
-+      if (clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor)
-+              goto Ebusy;
-+      return 0;
-+Ebusy:
-+      return -EBUSY;
-+}
+         free_irq(shost->irq, shost);
+-      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_extended_scb),
+-                      host->escb_virt, host->escb_phys);
+-      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_scb),
+-                      host->scb_virt, host->scb_phys);
++      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB),
++                      pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray);
++      pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB),
++                      pHCB->HCS_virScbArray, pHCB->HCS_physScbArray);
+         release_region(shost->io_port, 256);
+       scsi_host_put(shost);
+diff -Nurb linux-2.6.22-590/drivers/scsi/a100u2w.h linux-2.6.22-570/drivers/scsi/a100u2w.h
+--- linux-2.6.22-590/drivers/scsi/a100u2w.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/a100u2w.h    2007-07-08 19:32:17.000000000 -0400
+@@ -18,6 +18,27 @@
+  * along with this program; see the file COPYING.  If not, write to
+  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+  *
++ * --------------------------------------------------------------------------
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions, and the following disclaimer,
++ *    without modification, immediately at the beginning of the file.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ * Where this Software is combined with software released under the terms of 
++ * the GNU General Public License ("GPL") and the terms of the GPL would require the 
++ * combined work to also be released under the terms of the GPL, the terms
++ * and conditions of this License will apply in addition to those of the
++ * GPL with the exception of any terms or conditions of this License that
++ * conflict with, or are expressly prohibited by, the GPL.
++ *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+@@ -29,19 +50,30 @@
+  * 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.
+- *
++ */
 +
- static int nfs_get_sb(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
- {
-@@ -617,6 +669,7 @@
-       struct nfs_fh mntfh;
-       struct nfs_mount_data *data = raw_data;
-       struct dentry *mntroot;
-+      int (*compare_super)(struct super_block *,void *) = nfs_compare_super;
-       int error;
++/*
+  * Revision History:
+  * 06/18/98 HL, Initial production Version 1.02
+  * 12/19/98 bv, Use spinlocks for 2.1.95 and up
+  * 06/25/02 Doug Ledford <dledford@redhat.com>
+  *     - This and the i60uscsi.h file are almost identical,
+  *       merged them into a single header used by both .c files.
+- * 14/06/07 Alan Cox <alan@redhat.com>
+- *     - Grand cleanup and Linuxisation
+  */
  
-       /* Validate the mount data */
-@@ -631,16 +684,22 @@
-               goto out_err_noserver;
-       }
+ #define inia100_REVID "Initio INI-A100U2W SCSI device driver; Revision: 1.02d"
  
-+      if (server->flags & NFS_MOUNT_UNSHARED)
-+              compare_super = NULL;
++#define ULONG   unsigned long
++#define USHORT  unsigned short
++#define UCHAR   unsigned char
++#define BYTE    unsigned char
++#define WORD    unsigned short
++#define DWORD   unsigned long
++#define UBYTE   unsigned char
++#define UWORD   unsigned short
++#define UDWORD  unsigned long
++#define U32     u32
 +
-       /* Get a superblock - note that we may end up sharing one that already exists */
--      s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
-+      s = sget(fs_type, compare_super, nfs_set_super, server);
-       if (IS_ERR(s)) {
-               error = PTR_ERR(s);
-               goto out_err_nosb;
-       }
+ #if 1
+ #define ORC_MAXQUEUE          245
+ #define ORC_MAXTAGS           64
+@@ -58,10 +90,10 @@
+ /************************************************************************/
+ /*              Scatter-Gather Element Structure                        */
+ /************************************************************************/
+-struct orc_sgent {
+-      u32 base;               /* Data Pointer */
+-      u32 length;             /* Data Length */
+-};
++typedef struct ORC_SG_Struc {
++      U32 SG_Ptr;             /* Data Pointer */
++      U32 SG_Len;             /* Data Length */
++} ORC_SG;
  
-       if (s->s_fs_info != server) {
-+              error = nfs_compare_mount_options(s, server, flags);
-               nfs_free_server(server);
-               server = NULL;
-+              if (error < 0)
-+                      goto error_splat_super;
-       }
+ /* SCSI related definition                                              */
+ #define DISC_NOT_ALLOW          0x80  /* Disconnect is not allowed    */
+@@ -133,45 +165,42 @@
+ #define       ORC_PRGMCTR1    0xE3    /* RISC program counter           */
+ #define       ORC_RISCRAM     0xEC    /* RISC RAM data port 4 bytes     */
  
-       if (!s->s_root) {
-@@ -693,6 +752,7 @@
-       struct super_block *s;
-       struct nfs_server *server;
-       struct dentry *mntroot;
-+      int (*compare_super)(struct super_block *,void *) = nfs_compare_super;
-       int error;
+-struct orc_extended_scb {     /* Extended SCB                 */
+-      struct orc_sgent sglist[TOTAL_SG_ENTRY];        /*0 Start of SG list              */
+-      struct scsi_cmnd *srb;  /*50 SRB Pointer */
+-};
++typedef struct orc_extended_scb {     /* Extended SCB                 */
++      ORC_SG ESCB_SGList[TOTAL_SG_ENTRY];     /*0 Start of SG list              */
++      struct scsi_cmnd *SCB_Srb;      /*50 SRB Pointer */
++} ESCB;
  
-       dprintk("--> nfs_xdev_get_sb()\n");
-@@ -704,8 +764,11 @@
-               goto out_err_noserver;
-       }
+ /***********************************************************************
+               SCSI Control Block
+-
+-              0x40 bytes long, the last 8 are user bytes
+ ************************************************************************/
+-struct orc_scb {      /* Scsi_Ctrl_Blk                */
+-      u8 opcode;      /*00 SCB command code&residual  */
+-      u8 flags;       /*01 SCB Flags                  */
+-      u8 target;      /*02 Target Id                  */
+-      u8 lun;         /*03 Lun                        */
+-      u32 reserved0;  /*04 Reserved for ORCHID must 0 */
+-      u32 xferlen;    /*08 Data Transfer Length       */
+-      u32 reserved1;  /*0C Reserved for ORCHID must 0 */
+-      u32 sg_len;             /*10 SG list # * 8              */
+-      u32 sg_addr;    /*14 SG List Buf physical Addr  */
+-      u32 sg_addrhigh;        /*18 SG Buffer high physical Addr */
+-      u8 hastat;      /*1C Host Status                */
+-      u8 tastat;      /*1D Target Status              */
+-      u8 status;      /*1E SCB status                 */
+-      u8 link;                /*1F Link pointer, default 0xFF */
+-      u8 sense_len;   /*20 Sense Allocation Length    */
+-      u8 cdb_len;     /*21 CDB Length                 */
+-      u8 ident;       /*22 Identify                   */
+-      u8 tag_msg;     /*23 Tag Message                */
+-      u8 cdb[IMAX_CDB];       /*24 SCSI CDBs                  */
+-      u8 scbidx;      /*3C Index for this ORCSCB      */
+-      u32 sense_addr; /*34 Sense Buffer physical Addr */
+-
+-      struct orc_extended_scb *escb; /*38 Extended SCB Pointer       */
+-        /* 64bit pointer or 32bit pointer + reserved ? */
+-#ifndef CONFIG_64BIT
+-      u8 reserved2[4];        /*3E Reserved for Driver use    */
++typedef struct orc_scb {      /* Scsi_Ctrl_Blk                */
++      UBYTE SCB_Opcode;       /*00 SCB command code&residual  */
++      UBYTE SCB_Flags;        /*01 SCB Flags                  */
++      UBYTE SCB_Target;       /*02 Target Id                  */
++      UBYTE SCB_Lun;          /*03 Lun                        */
++      U32 SCB_Reserved0;      /*04 Reserved for ORCHID must 0 */
++      U32 SCB_XferLen;        /*08 Data Transfer Length       */
++      U32 SCB_Reserved1;      /*0C Reserved for ORCHID must 0 */
++      U32 SCB_SGLen;          /*10 SG list # * 8              */
++      U32 SCB_SGPAddr;        /*14 SG List Buf physical Addr  */
++      U32 SCB_SGPAddrHigh;    /*18 SG Buffer high physical Addr */
++      UBYTE SCB_HaStat;       /*1C Host Status                */
++      UBYTE SCB_TaStat;       /*1D Target Status              */
++      UBYTE SCB_Status;       /*1E SCB status                 */
++      UBYTE SCB_Link;         /*1F Link pointer, default 0xFF */
++      UBYTE SCB_SenseLen;     /*20 Sense Allocation Length    */
++      UBYTE SCB_CDBLen;       /*21 CDB Length                 */
++      UBYTE SCB_Ident;        /*22 Identify                   */
++      UBYTE SCB_TagMsg;       /*23 Tag Message                */
++      UBYTE SCB_CDB[IMAX_CDB];        /*24 SCSI CDBs                  */
++      UBYTE SCB_ScbIdx;       /*3C Index for this ORCSCB      */
++      U32 SCB_SensePAddr;     /*34 Sense Buffer physical Addr */
++
++      ESCB *SCB_EScb;         /*38 Extended SCB Pointer       */
++#ifndef ALPHA
++      UBYTE SCB_Reserved2[4]; /*3E Reserved for Driver use    */
+ #endif
+-};
++} ORC_SCB;
  
-+      if (server->flags & NFS_MOUNT_UNSHARED)
-+              compare_super = NULL;
-+
-       /* Get a superblock - note that we may end up sharing one that already exists */
--      s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
-+      s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
-       if (IS_ERR(s)) {
-               error = PTR_ERR(s);
-               goto out_err_nosb;
-@@ -810,6 +873,7 @@
-       struct dentry *mntroot;
-       char *mntpath = NULL, *hostname = NULL, ip_addr[16];
-       void *p;
-+      int (*compare_super)(struct super_block *,void *) = nfs_compare_super;
-       int error;
+ /* Opcodes of ORCSCB_Opcode */
+ #define ORC_EXECSCSI  0x00    /* SCSI initiator command with residual */
+@@ -210,13 +239,13 @@
+               Target Device Control Structure
+ **********************************************************************/
  
-       if (data == NULL) {
-@@ -881,16 +945,22 @@
-               goto out_err_noserver;
-       }
+-struct orc_target {
+-      u8 TCS_DrvDASD; /* 6 */
+-      u8 TCS_DrvSCSI; /* 7 */
+-      u8 TCS_DrvHead; /* 8 */
+-      u16 TCS_DrvFlags;       /* 4 */
+-      u8 TCS_DrvSector;       /* 7 */
+-};
++typedef struct ORC_Tar_Ctrl_Struc {
++      UBYTE TCS_DrvDASD;      /* 6 */
++      UBYTE TCS_DrvSCSI;      /* 7 */
++      UBYTE TCS_DrvHead;      /* 8 */
++      UWORD TCS_DrvFlags;     /* 4 */
++      UBYTE TCS_DrvSector;    /* 7 */
++} ORC_TCS;
  
-+      if (server->flags & NFS4_MOUNT_UNSHARED)
-+              compare_super = NULL;
-+
-       /* Get a superblock - note that we may end up sharing one that already exists */
--      s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
-+      s = sget(fs_type, compare_super, nfs_set_super, server);
-       if (IS_ERR(s)) {
-               error = PTR_ERR(s);
-               goto out_free;
-       }
+ /* Bit Definition for TCF_DrvFlags */
+ #define       TCS_DF_NODASD_SUPT      0x20    /* Suppress OS/2 DASD Mgr support */
+@@ -226,23 +255,32 @@
+ /***********************************************************************
+               Host Adapter Control Structure
+ ************************************************************************/
+-struct orc_host {
+-      unsigned long base;     /* Base address */
+-      u8 index;               /* Index (Channel)*/
+-      u8 scsi_id;             /* H/A SCSI ID */
+-      u8 BIOScfg;             /*BIOS configuration */
+-      u8 flags;
+-      u8 max_targets;         /* SCSI0MAXTags */
+-      struct orc_scb *scb_virt;       /* Virtual Pointer to SCB array */
+-      dma_addr_t scb_phys;    /* Scb Physical address */
+-      struct orc_extended_scb *escb_virt; /* Virtual pointer to ESCB Scatter list */
+-      dma_addr_t escb_phys;   /* scatter list Physical address */
+-      u8 target_flag[16];     /* target configuration, TCF_EN_TAG */
+-      u8 max_tags[16];        /* ORC_MAX_SCBS */
+-      u32 allocation_map[MAX_CHANNELS][8];    /* Max STB is 256, So 256/32 */
+-      spinlock_t allocation_lock;
++typedef struct ORC_Ha_Ctrl_Struc {
++      USHORT HCS_Base;        /* 00 */
++      UBYTE HCS_Index;        /* 02 */
++      UBYTE HCS_Intr;         /* 04 */
++      UBYTE HCS_SCSI_ID;      /* 06    H/A SCSI ID */
++      UBYTE HCS_BIOS;         /* 07    BIOS configuration */
++
++      UBYTE HCS_Flags;        /* 0B */
++      UBYTE HCS_HAConfig1;    /* 1B    SCSI0MAXTags */
++      UBYTE HCS_MaxTar;       /* 1B    SCSI0MAXTags */
++
++      USHORT HCS_Units;       /* Number of units this adapter  */
++      USHORT HCS_AFlags;      /* Adapter info. defined flags   */
++      ULONG HCS_Timeout;      /* Adapter timeout value   */
++      ORC_SCB *HCS_virScbArray;       /* 28 Virtual Pointer to SCB array */
++      dma_addr_t HCS_physScbArray;    /* Scb Physical address */
++      ESCB *HCS_virEscbArray; /* Virtual pointer to ESCB Scatter list */
++      dma_addr_t HCS_physEscbArray;   /* scatter list Physical address */
++      UBYTE TargetFlag[16];   /* 30  target configuration, TCF_EN_TAG */
++      UBYTE MaximumTags[16];  /* 40  ORC_MAX_SCBS */
++      UBYTE ActiveTags[16][16];       /* 50 */
++      ORC_TCS HCS_Tcs[16];    /* 28 */
++      U32 BitAllocFlag[MAX_CHANNELS][8];      /* Max STB is 256, So 256/32 */
++      spinlock_t BitAllocFlagLock;
+       struct pci_dev *pdev;
+-};
++} ORC_HCS;
  
-       if (s->s_fs_info != server) {
-+              error = nfs_compare_mount_options(s, server, flags);
-               nfs_free_server(server);
-               server = NULL;
-+              if (error < 0)
-+                      goto error_splat_super;
-       }
+ /* Bit Definition for HCS_Flags */
  
-       if (!s->s_root) {
-@@ -951,6 +1021,7 @@
-       struct super_block *s;
-       struct nfs_server *server;
-       struct dentry *mntroot;
-+      int (*compare_super)(struct super_block *,void *) = nfs_compare_super;
-       int error;
+@@ -263,79 +301,79 @@
+ #define       HCS_AF_DISABLE_RESET    0x10    /* Adapter disable reset  */
+ #define       HCS_AF_DISABLE_ADPT     0x80    /* Adapter disable                */
  
-       dprintk("--> nfs4_xdev_get_sb()\n");
-@@ -962,8 +1033,11 @@
-               goto out_err_noserver;
-       }
+-struct orc_nvram {
++typedef struct _NVRAM {
+ /*----------header ---------------*/
+-        u8 SubVendorID0;     /* 00 - Sub Vendor ID           */
+-        u8 SubVendorID1;     /* 00 - Sub Vendor ID           */
+-        u8 SubSysID0;        /* 02 - Sub System ID           */
+-        u8 SubSysID1;        /* 02 - Sub System ID           */
+-        u8 SubClass;         /* 04 - Sub Class               */
+-        u8 VendorID0;        /* 05 - Vendor ID               */
+-        u8 VendorID1;        /* 05 - Vendor ID               */
+-        u8 DeviceID0;        /* 07 - Device ID               */
+-        u8 DeviceID1;        /* 07 - Device ID               */
+-        u8 Reserved0[2];     /* 09 - Reserved                */
+-        u8 revision;         /* 0B - revision of data structure */
++        UCHAR SubVendorID0;     /* 00 - Sub Vendor ID           */
++        UCHAR SubVendorID1;     /* 00 - Sub Vendor ID           */
++        UCHAR SubSysID0;        /* 02 - Sub System ID           */
++        UCHAR SubSysID1;        /* 02 - Sub System ID           */
++        UCHAR SubClass;         /* 04 - Sub Class               */
++        UCHAR VendorID0;        /* 05 - Vendor ID               */
++        UCHAR VendorID1;        /* 05 - Vendor ID               */
++        UCHAR DeviceID0;        /* 07 - Device ID               */
++        UCHAR DeviceID1;        /* 07 - Device ID               */
++        UCHAR Reserved0[2];     /* 09 - Reserved                */
++        UCHAR Revision;         /* 0B - Revision of data structure */
+         /* ----Host Adapter Structure ---- */
+-        u8 NumOfCh;          /* 0C - Number of SCSI channel  */
+-        u8 BIOSConfig1;      /* 0D - BIOS configuration 1    */
+-        u8 BIOSConfig2;      /* 0E - BIOS boot channel&target ID */
+-        u8 BIOSConfig3;      /* 0F - BIOS configuration 3    */
++        UCHAR NumOfCh;          /* 0C - Number of SCSI channel  */
++        UCHAR BIOSConfig1;      /* 0D - BIOS configuration 1    */
++        UCHAR BIOSConfig2;      /* 0E - BIOS boot channel&target ID */
++        UCHAR BIOSConfig3;      /* 0F - BIOS configuration 3    */
+         /* ----SCSI channel Structure ---- */
+         /* from "CTRL-I SCSI Host Adapter SetUp menu "  */
+-        u8 scsi_id;          /* 10 - Channel 0 SCSI ID       */
+-        u8 SCSI0Config;      /* 11 - Channel 0 SCSI configuration */
+-        u8 SCSI0MaxTags;     /* 12 - Channel 0 Maximum tags  */
+-        u8 SCSI0ResetTime;   /* 13 - Channel 0 Reset recovering time */
+-        u8 ReservedforChannel0[2];   /* 14 - Reserved                */
++        UCHAR SCSI0Id;          /* 10 - Channel 0 SCSI ID       */
++        UCHAR SCSI0Config;      /* 11 - Channel 0 SCSI configuration */
++        UCHAR SCSI0MaxTags;     /* 12 - Channel 0 Maximum tags  */
++        UCHAR SCSI0ResetTime;   /* 13 - Channel 0 Reset recovering time */
++        UCHAR ReservedforChannel0[2];   /* 14 - Reserved                */
  
-+      if (server->flags & NFS4_MOUNT_UNSHARED)
-+              compare_super = NULL;
-+
-       /* Get a superblock - note that we may end up sharing one that already exists */
--      s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
-+      s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
-       if (IS_ERR(s)) {
-               error = PTR_ERR(s);
-               goto out_err_nosb;
-@@ -1018,6 +1092,7 @@
-       struct nfs_server *server;
-       struct dentry *mntroot;
-       struct nfs_fh mntfh;
-+      int (*compare_super)(struct super_block *,void *) = nfs_compare_super;
-       int error;
+         /* ----SCSI target Structure ----  */
+         /* from "CTRL-I SCSI device SetUp menu "                        */
+-        u8 Target00Config;   /* 16 - Channel 0 Target 0 config */
+-        u8 Target01Config;   /* 17 - Channel 0 Target 1 config */
+-        u8 Target02Config;   /* 18 - Channel 0 Target 2 config */
+-        u8 Target03Config;   /* 19 - Channel 0 Target 3 config */
+-        u8 Target04Config;   /* 1A - Channel 0 Target 4 config */
+-        u8 Target05Config;   /* 1B - Channel 0 Target 5 config */
+-        u8 Target06Config;   /* 1C - Channel 0 Target 6 config */
+-        u8 Target07Config;   /* 1D - Channel 0 Target 7 config */
+-        u8 Target08Config;   /* 1E - Channel 0 Target 8 config */
+-        u8 Target09Config;   /* 1F - Channel 0 Target 9 config */
+-        u8 Target0AConfig;   /* 20 - Channel 0 Target A config */
+-        u8 Target0BConfig;   /* 21 - Channel 0 Target B config */
+-        u8 Target0CConfig;   /* 22 - Channel 0 Target C config */
+-        u8 Target0DConfig;   /* 23 - Channel 0 Target D config */
+-        u8 Target0EConfig;   /* 24 - Channel 0 Target E config */
+-        u8 Target0FConfig;   /* 25 - Channel 0 Target F config */
+-
+-        u8 SCSI1Id;          /* 26 - Channel 1 SCSI ID       */
+-        u8 SCSI1Config;      /* 27 - Channel 1 SCSI configuration */
+-        u8 SCSI1MaxTags;     /* 28 - Channel 1 Maximum tags  */
+-        u8 SCSI1ResetTime;   /* 29 - Channel 1 Reset recovering time */
+-        u8 ReservedforChannel1[2];   /* 2A - Reserved                */
++        UCHAR Target00Config;   /* 16 - Channel 0 Target 0 config */
++        UCHAR Target01Config;   /* 17 - Channel 0 Target 1 config */
++        UCHAR Target02Config;   /* 18 - Channel 0 Target 2 config */
++        UCHAR Target03Config;   /* 19 - Channel 0 Target 3 config */
++        UCHAR Target04Config;   /* 1A - Channel 0 Target 4 config */
++        UCHAR Target05Config;   /* 1B - Channel 0 Target 5 config */
++        UCHAR Target06Config;   /* 1C - Channel 0 Target 6 config */
++        UCHAR Target07Config;   /* 1D - Channel 0 Target 7 config */
++        UCHAR Target08Config;   /* 1E - Channel 0 Target 8 config */
++        UCHAR Target09Config;   /* 1F - Channel 0 Target 9 config */
++        UCHAR Target0AConfig;   /* 20 - Channel 0 Target A config */
++        UCHAR Target0BConfig;   /* 21 - Channel 0 Target B config */
++        UCHAR Target0CConfig;   /* 22 - Channel 0 Target C config */
++        UCHAR Target0DConfig;   /* 23 - Channel 0 Target D config */
++        UCHAR Target0EConfig;   /* 24 - Channel 0 Target E config */
++        UCHAR Target0FConfig;   /* 25 - Channel 0 Target F config */
++
++        UCHAR SCSI1Id;          /* 26 - Channel 1 SCSI ID       */
++        UCHAR SCSI1Config;      /* 27 - Channel 1 SCSI configuration */
++        UCHAR SCSI1MaxTags;     /* 28 - Channel 1 Maximum tags  */
++        UCHAR SCSI1ResetTime;   /* 29 - Channel 1 Reset recovering time */
++        UCHAR ReservedforChannel1[2];   /* 2A - Reserved                */
  
-       dprintk("--> nfs4_referral_get_sb()\n");
-@@ -1029,8 +1104,11 @@
-               goto out_err_noserver;
-       }
+         /* ----SCSI target Structure ----  */
+         /* from "CTRL-I SCSI device SetUp menu "                                          */
+-        u8 Target10Config;   /* 2C - Channel 1 Target 0 config */
+-        u8 Target11Config;   /* 2D - Channel 1 Target 1 config */
+-        u8 Target12Config;   /* 2E - Channel 1 Target 2 config */
+-        u8 Target13Config;   /* 2F - Channel 1 Target 3 config */
+-        u8 Target14Config;   /* 30 - Channel 1 Target 4 config */
+-        u8 Target15Config;   /* 31 - Channel 1 Target 5 config */
+-        u8 Target16Config;   /* 32 - Channel 1 Target 6 config */
+-        u8 Target17Config;   /* 33 - Channel 1 Target 7 config */
+-        u8 Target18Config;   /* 34 - Channel 1 Target 8 config */
+-        u8 Target19Config;   /* 35 - Channel 1 Target 9 config */
+-        u8 Target1AConfig;   /* 36 - Channel 1 Target A config */
+-        u8 Target1BConfig;   /* 37 - Channel 1 Target B config */
+-        u8 Target1CConfig;   /* 38 - Channel 1 Target C config */
+-        u8 Target1DConfig;   /* 39 - Channel 1 Target D config */
+-        u8 Target1EConfig;   /* 3A - Channel 1 Target E config */
+-        u8 Target1FConfig;   /* 3B - Channel 1 Target F config */
+-        u8 reserved[3];      /* 3C - Reserved                */
++        UCHAR Target10Config;   /* 2C - Channel 1 Target 0 config */
++        UCHAR Target11Config;   /* 2D - Channel 1 Target 1 config */
++        UCHAR Target12Config;   /* 2E - Channel 1 Target 2 config */
++        UCHAR Target13Config;   /* 2F - Channel 1 Target 3 config */
++        UCHAR Target14Config;   /* 30 - Channel 1 Target 4 config */
++        UCHAR Target15Config;   /* 31 - Channel 1 Target 5 config */
++        UCHAR Target16Config;   /* 32 - Channel 1 Target 6 config */
++        UCHAR Target17Config;   /* 33 - Channel 1 Target 7 config */
++        UCHAR Target18Config;   /* 34 - Channel 1 Target 8 config */
++        UCHAR Target19Config;   /* 35 - Channel 1 Target 9 config */
++        UCHAR Target1AConfig;   /* 36 - Channel 1 Target A config */
++        UCHAR Target1BConfig;   /* 37 - Channel 1 Target B config */
++        UCHAR Target1CConfig;   /* 38 - Channel 1 Target C config */
++        UCHAR Target1DConfig;   /* 39 - Channel 1 Target D config */
++        UCHAR Target1EConfig;   /* 3A - Channel 1 Target E config */
++        UCHAR Target1FConfig;   /* 3B - Channel 1 Target F config */
++        UCHAR reserved[3];      /* 3C - Reserved                */
+         /* ---------- CheckSum ----------       */
+-        u8 CheckSum;         /* 3F - Checksum of NVRam       */
+-};
++        UCHAR CheckSum;         /* 3F - Checksum of NVRam       */
++} NVRAM, *PNVRAM;
+ /* Bios Configuration for nvram->BIOSConfig1                            */
+ #define NBC_BIOSENABLE  0x01    /* BIOS enable                    */
+@@ -369,3 +407,10 @@
+ #define NCC_RESET_TIME  0x0A    /* SCSI RESET recovering time     */
+ #define NTC_DEFAULT     (NTC_1GIGA | NTC_NO_WIDESYNC | NTC_DISC_ENABLE)
  
-+      if (server->flags & NFS4_MOUNT_UNSHARED)
-+              compare_super = NULL;
++#define ORC_RD(x,y)             (UCHAR)(inb(  (int)((ULONG)((ULONG)x+(UCHAR)y)) ))
++#define ORC_RDWORD(x,y)         (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
++#define ORC_RDLONG(x,y)         (long)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
 +
-       /* Get a superblock - note that we may end up sharing one that already exists */
--      s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
-+      s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
-       if (IS_ERR(s)) {
-               error = PTR_ERR(s);
-               goto out_err_nosb;
-diff -Nurb linux-2.6.22-570/fs/nfs/write.c linux-2.6.22-590/fs/nfs/write.c
---- linux-2.6.22-570/fs/nfs/write.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfs/write.c    2008-01-02 13:56:37.000000000 -0500
-@@ -117,7 +117,7 @@
-       if (PagePrivate(page)) {
-               req = (struct nfs_page *)page_private(page);
-               if (req != NULL)
--                      atomic_inc(&req->wb_count);
-+                      kref_get(&req->wb_kref);
-       }
-       return req;
- }
-@@ -191,8 +191,6 @@
-       }
-       /* Update file length */
-       nfs_grow_file(page, offset, count);
--      /* Set the PG_uptodate flag? */
--      nfs_mark_uptodate(page, offset, count);
-       nfs_unlock_request(req);
-       return 0;
- }
-@@ -291,7 +289,7 @@
-               BUG();
-       }
-       radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index,
--                      NFS_PAGE_TAG_WRITEBACK);
-+                      NFS_PAGE_TAG_LOCKED);
-       ret = test_bit(PG_NEED_FLUSH, &req->wb_flags);
-       spin_unlock(req_lock);
-       nfs_pageio_add_request(pgio, req);
-@@ -400,7 +398,7 @@
-       if (PageDirty(req->wb_page))
-               set_bit(PG_NEED_FLUSH, &req->wb_flags);
-       nfsi->npages++;
--      atomic_inc(&req->wb_count);
-+      kref_get(&req->wb_kref);
-       return 0;
- }
++#define ORC_WR(     adr,data)   outb( (UCHAR)(data), (int)(adr))
++#define ORC_WRSHORT(adr,data)   outw( (UWORD)(data), (int)(adr))
++#define ORC_WRLONG( adr,data)   outl( (ULONG)(data), (int)(adr))
+diff -Nurb linux-2.6.22-590/drivers/scsi/a4000t.c linux-2.6.22-570/drivers/scsi/a4000t.c
+--- linux-2.6.22-590/drivers/scsi/a4000t.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/a4000t.c     1969-12-31 19:00:00.000000000 -0500
+@@ -1,143 +0,0 @@
+-/*
+- * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
+- *            Amiga Technologies A4000T SCSI controller.
+- *
+- * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
+- * plus modifications of the 53c7xx.c driver to support the Amiga.
+- *
+- * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
+- */
+-
+-#include <linux/module.h>
+-#include <linux/platform_device.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <asm/amigahw.h>
+-#include <asm/amigaints.h>
+-#include <scsi/scsi_host.h>
+-#include <scsi/scsi_transport_spi.h>
+-
+-#include "53c700.h"
+-
+-MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>");
+-MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver");
+-MODULE_LICENSE("GPL");
+-
+-
+-static struct scsi_host_template a4000t_scsi_driver_template = {
+-      .name           = "A4000T builtin SCSI",
+-      .proc_name      = "A4000t",
+-      .this_id        = 7,
+-      .module         = THIS_MODULE,
+-};
+-
+-static struct platform_device *a4000t_scsi_device;
+-
+-#define A4000T_SCSI_ADDR 0xdd0040
+-
+-static int __devinit a4000t_probe(struct device *dev)
+-{
+-      struct Scsi_Host * host = NULL;
+-      struct NCR_700_Host_Parameters *hostdata;
+-
+-      if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI)))
+-              goto out;
+-
+-      if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000,
+-                              "A4000T builtin SCSI"))
+-              goto out;
+-
+-      hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+-      if (hostdata == NULL) {
+-              printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n");
+-              goto out_release;
+-      }
+-      memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
+-
+-      /* Fill in the required pieces of hostdata */
+-      hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR);
+-      hostdata->clock = 50;
+-      hostdata->chip710 = 1;
+-      hostdata->dmode_extra = DMODE_FC2;
+-      hostdata->dcntl_extra = EA_710;
+-
+-      /* and register the chip */
+-      host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, dev);
+-      if (!host) {
+-              printk(KERN_ERR "a4000t-scsi: No host detected; "
+-                              "board configuration problem?\n");
+-              goto out_free;
+-      }
+-
+-      host->this_id = 7;
+-      host->base = A4000T_SCSI_ADDR;
+-      host->irq = IRQ_AMIGA_PORTS;
+-
+-      if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi",
+-                      host)) {
+-              printk(KERN_ERR "a4000t-scsi: request_irq failed\n");
+-              goto out_put_host;
+-      }
+-
+-      scsi_scan_host(host);
+-
+-      return 0;
+-
+- out_put_host:
+-      scsi_host_put(host);
+- out_free:
+-      kfree(hostdata);
+- out_release:
+-      release_mem_region(A4000T_SCSI_ADDR, 0x1000);
+- out:
+-      return -ENODEV;
+-}
+-
+-static __devexit int a4000t_device_remove(struct device *dev)
+-{
+-      struct Scsi_Host *host = dev_to_shost(dev);
+-      struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
+-
+-      scsi_remove_host(host);
+-
+-      NCR_700_release(host);
+-      kfree(hostdata);
+-      free_irq(host->irq, host);
+-      release_mem_region(A4000T_SCSI_ADDR, 0x1000);
+-
+-      return 0;
+-}
+-
+-static struct device_driver a4000t_scsi_driver = {
+-      .name   = "a4000t-scsi",
+-      .bus    = &platform_bus_type,
+-      .probe  = a4000t_probe,
+-      .remove = __devexit_p(a4000t_device_remove),
+-};
+-
+-static int __init a4000t_scsi_init(void)
+-{
+-      int err;
+-
+-      err = driver_register(&a4000t_scsi_driver);
+-      if (err)
+-              return err;
+-
+-      a4000t_scsi_device = platform_device_register_simple("a4000t-scsi",
+-                      -1, NULL, 0);
+-      if (IS_ERR(a4000t_scsi_device)) {
+-              driver_unregister(&a4000t_scsi_driver);
+-              return PTR_ERR(a4000t_scsi_device);
+-      }
+-
+-      return err;
+-}
+-
+-static void __exit a4000t_scsi_exit(void)
+-{
+-      platform_device_unregister(a4000t_scsi_device);
+-      driver_unregister(&a4000t_scsi_driver);
+-}
+-
+-module_init(a4000t_scsi_init);
+-module_exit(a4000t_scsi_exit);
+diff -Nurb linux-2.6.22-590/drivers/scsi/aacraid/aachba.c linux-2.6.22-570/drivers/scsi/aacraid/aachba.c
+--- linux-2.6.22-590/drivers/scsi/aacraid/aachba.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/aacraid/aachba.c     2007-07-08 19:32:17.000000000 -0400
+@@ -169,18 +169,6 @@
+ module_param(acbsize, int, S_IRUGO|S_IWUSR);
+ MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware.");
  
-@@ -409,7 +407,7 @@
-  */
- static void nfs_inode_remove_request(struct nfs_page *req)
- {
--      struct inode *inode = req->wb_context->dentry->d_inode;
-+      struct inode *inode = req->wb_context->path.dentry->d_inode;
-       struct nfs_inode *nfsi = NFS_I(inode);
+-int update_interval = 30 * 60;
+-module_param(update_interval, int, S_IRUGO|S_IWUSR);
+-MODULE_PARM_DESC(update_interval, "Interval in seconds between time sync updates issued to adapter.");
+-
+-int check_interval = 24 * 60 * 60;
+-module_param(check_interval, int, S_IRUGO|S_IWUSR);
+-MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health checks.");
+-
+-int check_reset = 1;
+-module_param(check_reset, int, S_IRUGO|S_IWUSR);
+-MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the adapter.");
+-
+ int expose_physicals = -1;
+ module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
+ MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on");
+@@ -324,10 +312,11 @@
  
-       BUG_ON (!NFS_WBACK_BUSY(req));
-@@ -457,13 +455,15 @@
- static void
- nfs_mark_request_commit(struct nfs_page *req)
- {
--      struct inode *inode = req->wb_context->dentry->d_inode;
-+      struct inode *inode = req->wb_context->path.dentry->d_inode;
-       struct nfs_inode *nfsi = NFS_I(inode);
+       if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
+               maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
+-      fsa_dev_ptr = kzalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers,
++      fsa_dev_ptr =  kmalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers,
+                       GFP_KERNEL);
+       if (!fsa_dev_ptr)
+               return -ENOMEM;
++      memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers);
  
-       spin_lock(&nfsi->req_lock);
--      nfs_list_add_request(req, &nfsi->commit);
-       nfsi->ncommit++;
-       set_bit(PG_NEED_COMMIT, &(req)->wb_flags);
-+      radix_tree_tag_set(&nfsi->nfs_page_tree,
-+                      req->wb_index,
-+                      NFS_PAGE_TAG_COMMIT);
-       spin_unlock(&nfsi->req_lock);
-       inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
-       __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
-@@ -526,14 +526,14 @@
-               idx_end = idx_start + npages - 1;
+       dev->fsa_dev = fsa_dev_ptr;
+       dev->maximum_num_containers = maximum_num_containers;
+@@ -355,15 +344,20 @@
+ {
+       void *buf;
+       int transfer_len;
+-      struct scatterlist *sg = scsi_sglist(scsicmd);
++      struct scatterlist *sg = scsicmd->request_buffer;
  
-       next = idx_start;
--      while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) {
-+      while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_LOCKED)) {
-               if (req->wb_index > idx_end)
-                       break;
++      if (scsicmd->use_sg) {
+               buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+               transfer_len = min(sg->length, len + offset);
+-
++      } else {
++              buf = scsicmd->request_buffer;
++              transfer_len = min(scsicmd->request_bufflen, len + offset);
++      }
+       transfer_len -= offset;
+       if (buf && transfer_len > 0)
+               memcpy(buf + offset, data, transfer_len);
  
-               next = req->wb_index + 1;
-               BUG_ON(!NFS_WBACK_BUSY(req));
++      if (scsicmd->use_sg) 
+               kunmap_atomic(buf - sg->offset, KM_IRQ0);
  
--              atomic_inc(&req->wb_count);
-+              kref_get(&req->wb_kref);
-               spin_unlock(&nfsi->req_lock);
-               error = nfs_wait_on_request(req);
-               nfs_release_request(req);
-@@ -577,10 +577,9 @@
-       int res = 0;
+ }
+@@ -457,7 +451,7 @@
+ {
+       struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
  
-       if (nfsi->ncommit != 0) {
--              res = nfs_scan_list(nfsi, &nfsi->commit, dst, idx_start, npages);
-+              res = nfs_scan_list(nfsi, dst, idx_start, npages,
-+                              NFS_PAGE_TAG_COMMIT);
-               nfsi->ncommit -= res;
--              if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
--                      printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
-       }
-       return res;
+-      if ((fsa_dev_ptr[scmd_id(scsicmd)].valid & 1))
++      if (fsa_dev_ptr[scmd_id(scsicmd)].valid)
+               return aac_scsi_cmd(scsicmd);
+       scsicmd->result = DID_NO_CONNECT << 16;
+@@ -465,18 +459,18 @@
+       return 0;
  }
-@@ -751,12 +750,17 @@
- static void nfs_writepage_release(struct nfs_page *req)
+-static void _aac_probe_container2(void * context, struct fib * fibptr)
++static int _aac_probe_container2(void * context, struct fib * fibptr)
  {
+       struct fsa_dev_info *fsa_dev_ptr;
+       int (*callback)(struct scsi_cmnd *);
+       struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context;
  
--      if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) {
-+      if (PageError(req->wb_page)) {
-+              nfs_end_page_writeback(req->wb_page);
-+              nfs_inode_remove_request(req);
-+      } else if (!nfs_reschedule_unstable_write(req)) {
-+              /* Set the PG_uptodate flag */
-+              nfs_mark_uptodate(req->wb_page, req->wb_pgbase, req->wb_bytes);
-               nfs_end_page_writeback(req->wb_page);
-               nfs_inode_remove_request(req);
-       } else
-               nfs_end_page_writeback(req->wb_page);
--      nfs_clear_page_writeback(req);
-+      nfs_clear_page_tag_locked(req);
+-
+       if (!aac_valid_context(scsicmd, fibptr))
+-              return;
++              return 0;
++
++      fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
+       scsicmd->SCp.Status = 0;
+-      fsa_dev_ptr = fibptr->dev->fsa_dev;
+       if (fsa_dev_ptr) {
+               struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr);
+               fsa_dev_ptr += scmd_id(scsicmd);
+@@ -499,11 +493,10 @@
+       aac_fib_free(fibptr);
+       callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr);
+       scsicmd->SCp.ptr = NULL;
+-      (*callback)(scsicmd);
+-      return;
++      return (*callback)(scsicmd);
  }
  
- static inline int flush_task_priority(int how)
-@@ -786,7 +790,7 @@
-        * NB: take care not to mess about with data->commit et al. */
+-static void _aac_probe_container1(void * context, struct fib * fibptr)
++static int _aac_probe_container1(void * context, struct fib * fibptr)
+ {
+       struct scsi_cmnd * scsicmd;
+       struct aac_mount * dresp;
+@@ -513,14 +506,13 @@
+       dresp = (struct aac_mount *) fib_data(fibptr);
+       dresp->mnt[0].capacityhigh = 0;
+       if ((le32_to_cpu(dresp->status) != ST_OK) ||
+-          (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
+-              _aac_probe_container2(context, fibptr);
+-              return;
+-      }
++          (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE))
++              return _aac_probe_container2(context, fibptr);
+       scsicmd = (struct scsi_cmnd *) context;
++      scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
  
-       data->req = req;
--      data->inode = inode = req->wb_context->dentry->d_inode;
-+      data->inode = inode = req->wb_context->path.dentry->d_inode;
-       data->cred = req->wb_context->cred;
+       if (!aac_valid_context(scsicmd, fibptr))
+-              return;
++              return 0;
  
-       data->args.fh     = NFS_FH(inode);
-@@ -885,7 +889,7 @@
+       aac_fib_init(fibptr);
+@@ -535,18 +527,21 @@
+                         sizeof(struct aac_query_mount),
+                         FsaNormal,
+                         0, 1,
+-                        _aac_probe_container2,
++                        (fib_callback) _aac_probe_container2,
+                         (void *) scsicmd);
+       /*
+        *      Check that the command queued to the controller
+        */
+-      if (status == -EINPROGRESS)
++      if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+-      else if (status < 0) {
++              return 0;
++      }
++      if (status < 0) {
+               /* Inherit results from VM_NameServe, if any */
+               dresp->status = cpu_to_le32(ST_OK);
+-              _aac_probe_container2(context, fibptr);
++              return _aac_probe_container2(context, fibptr);
        }
-       nfs_redirty_request(req);
-       nfs_end_page_writeback(req->wb_page);
--      nfs_clear_page_writeback(req);
-+      nfs_clear_page_tag_locked(req);
-       return -ENOMEM;
++      return 0;
  }
  
-@@ -928,7 +932,7 @@
-               nfs_list_remove_request(req);
-               nfs_redirty_request(req);
-               nfs_end_page_writeback(req->wb_page);
--              nfs_clear_page_writeback(req);
-+              nfs_clear_page_tag_locked(req);
+ static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
+@@ -571,7 +566,7 @@
+                         sizeof(struct aac_query_mount),
+                         FsaNormal,
+                         0, 1,
+-                        _aac_probe_container1,
++                        (fib_callback) _aac_probe_container1,
+                         (void *) scsicmd);
+               /*
+                *      Check that the command queued to the controller
+@@ -625,7 +620,7 @@
+               return -ENOMEM;
        }
-       return -ENOMEM;
- }
-@@ -954,8 +958,8 @@
-       struct page             *page = req->wb_page;
+       scsicmd->list.next = NULL;
+-      scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))aac_probe_container_callback1;
++      scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))_aac_probe_container1;
  
-       dprintk("NFS: write (%s/%Ld %d@%Ld)",
--              req->wb_context->dentry->d_inode->i_sb->s_id,
--              (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
-+              req->wb_context->path.dentry->d_inode->i_sb->s_id,
-+              (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
-               req->wb_bytes,
-               (long long)req_offset(req));
+       scsicmd->device = scsidev;
+       scsidev->sdev_state = 0;
+@@ -830,7 +825,7 @@
+       readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+       readcmd->count = cpu_to_le32(count<<9);
+       readcmd->cid = cpu_to_le16(scmd_id(cmd));
+-      readcmd->flags = cpu_to_le16(IO_TYPE_READ);
++      readcmd->flags = cpu_to_le16(1);
+       readcmd->bpTotal = 0;
+       readcmd->bpComplete = 0;
  
-@@ -1020,8 +1024,8 @@
-               page = req->wb_page;
+@@ -909,7 +904,7 @@
+                         (void *) cmd);
+ }
  
-               dprintk("NFS: write (%s/%Ld %d@%Ld)",
--                      req->wb_context->dentry->d_inode->i_sb->s_id,
--                      (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
-+                      req->wb_context->path.dentry->d_inode->i_sb->s_id,
-+                      (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
-                       req->wb_bytes,
-                       (long long)req_offset(req));
+-static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
++static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+ {
+       u16 fibsize;
+       struct aac_raw_io *writecmd;
+@@ -919,9 +914,7 @@
+       writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+       writecmd->count = cpu_to_le32(count<<9);
+       writecmd->cid = cpu_to_le16(scmd_id(cmd));
+-      writecmd->flags = fua ?
+-              cpu_to_le16(IO_TYPE_WRITE|IO_SUREWRITE) :
+-              cpu_to_le16(IO_TYPE_WRITE);
++      writecmd->flags = 0;
+       writecmd->bpTotal = 0;
+       writecmd->bpComplete = 0;
  
-@@ -1039,12 +1043,14 @@
-                       dprintk(" marked for commit\n");
-                       goto next;
-               }
-+              /* Set the PG_uptodate flag? */
-+              nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes);
-               dprintk(" OK\n");
- remove_request:
-               nfs_end_page_writeback(page);
-               nfs_inode_remove_request(req);
-       next:
--              nfs_clear_page_writeback(req);
-+              nfs_clear_page_tag_locked(req);
-       }
+@@ -940,7 +933,7 @@
+                         (void *) cmd);
  }
  
-@@ -1157,7 +1163,7 @@
+-static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
++static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+ {
+       u16 fibsize;
+       struct aac_write64 *writecmd;
+@@ -971,7 +964,7 @@
+                         (void *) cmd);
+ }
  
-       list_splice_init(head, &data->pages);
-       first = nfs_list_entry(data->pages.next);
--      inode = first->wb_context->dentry->d_inode;
-+      inode = first->wb_context->path.dentry->d_inode;
+-static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
++static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+ {
+       u16 fibsize;
+       struct aac_write *writecmd;
+@@ -1048,7 +1041,7 @@
+       struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
  
-       data->inode       = inode;
-       data->cred        = first->wb_context->cred;
-@@ -1207,7 +1213,7 @@
-               nfs_list_remove_request(req);
-               nfs_mark_request_commit(req);
-               dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
--              nfs_clear_page_writeback(req);
-+              nfs_clear_page_tag_locked(req);
-       }
-       return -ENOMEM;
- }
-@@ -1234,8 +1240,8 @@
-               dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
+       aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg);
+-      srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
++      srbcmd->count = cpu_to_le32(cmd->request_bufflen);
  
-               dprintk("NFS: commit (%s/%Ld %d@%Ld)",
--                      req->wb_context->dentry->d_inode->i_sb->s_id,
--                      (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
-+                      req->wb_context->path.dentry->d_inode->i_sb->s_id,
-+                      (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
-                       req->wb_bytes,
-                       (long long)req_offset(req));
-               if (task->tk_status < 0) {
-@@ -1249,6 +1255,9 @@
-                * returned by the server against all stored verfs. */
-               if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) {
-                       /* We have a match */
-+                      /* Set the PG_uptodate flag */
-+                      nfs_mark_uptodate(req->wb_page, req->wb_pgbase,
-+                                      req->wb_bytes);
-                       nfs_inode_remove_request(req);
-                       dprintk(" OK\n");
-                       goto next;
-@@ -1257,7 +1266,7 @@
-               dprintk(" mismatch\n");
-               nfs_redirty_request(req);
-       next:
--              nfs_clear_page_writeback(req);
-+              nfs_clear_page_tag_locked(req);
+       memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
+       memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
+@@ -1076,7 +1069,7 @@
+       struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
+       aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg);
+-      srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
++      srbcmd->count = cpu_to_le32(cmd->request_bufflen);
+       memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
+       memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
+@@ -1179,7 +1172,6 @@
        }
- }
  
-diff -Nurb linux-2.6.22-570/fs/nfsd/nfs4callback.c linux-2.6.22-590/fs/nfsd/nfs4callback.c
---- linux-2.6.22-570/fs/nfsd/nfs4callback.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfsd/nfs4callback.c    2008-01-02 13:56:37.000000000 -0500
-@@ -429,29 +429,23 @@
-               goto out_err;
+       if (!dev->in_reset) {
+-              char buffer[16];
+               tmp = le32_to_cpu(dev->adapter_info.kernelrev);
+               printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n",
+                       dev->name, 
+@@ -1200,23 +1192,16 @@
+                       dev->name, dev->id,
+                       tmp>>24,(tmp>>16)&0xff,tmp&0xff,
+                       le32_to_cpu(dev->adapter_info.biosbuild));
+-              buffer[0] = '\0';
+-              if (aac_show_serial_number(
+-                shost_to_class(dev->scsi_host_ptr), buffer))
+-                      printk(KERN_INFO "%s%d: serial %s",
+-                        dev->name, dev->id, buffer);
++              if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
++                      printk(KERN_INFO "%s%d: serial %x\n",
++                              dev->name, dev->id,
++                              le32_to_cpu(dev->adapter_info.serial[0]));
+               if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) {
+                       printk(KERN_INFO "%s%d: TSID %.*s\n",
+                         dev->name, dev->id,
+                         (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid),
+                         dev->supplement_adapter_info.VpdInfo.Tsid);
+               }
+-              if (!check_reset ||
+-                (dev->supplement_adapter_info.SupportedOptions2 &
+-                le32_to_cpu(AAC_OPTION_IGNORE_RESET))) {
+-                      printk(KERN_INFO "%s%d: Reset Adapter Ignored\n",
+-                        dev->name, dev->id);
+-              }
        }
  
--      /* Kick rpciod, put the call on the wire. */
--      if (rpciod_up() != 0)
--              goto out_clnt;
--
-       /* the task holds a reference to the nfs4_client struct */
-       atomic_inc(&clp->cl_count);
+       dev->nondasd_support = 0;
+@@ -1347,7 +1332,7 @@
+       if (!aac_valid_context(scsicmd, fibptr))
+               return;
  
-       msg.rpc_cred = nfsd4_lookupcred(clp,0);
-       if (IS_ERR(msg.rpc_cred))
--              goto out_rpciod;
-+              goto out_release_clp;
-       status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL);
-       put_rpccred(msg.rpc_cred);
+-      dev = fibptr->dev;
++      dev = (struct aac_dev *)scsicmd->device->host->hostdata;
+       cid = scmd_id(scsicmd);
  
-       if (status != 0) {
-               dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n");
--              goto out_rpciod;
-+              goto out_release_clp;
-       }
-       return;
+       if (nblank(dprintk(x))) {
+@@ -1387,8 +1372,15 @@
  
--out_rpciod:
-+out_release_clp:
-       atomic_dec(&clp->cl_count);
--      rpciod_down();
--out_clnt:
-       rpc_shutdown_client(cb->cb_client);
- out_err:
-       cb->cb_client = NULL;
-diff -Nurb linux-2.6.22-570/fs/nfsd/nfs4state.c linux-2.6.22-590/fs/nfsd/nfs4state.c
---- linux-2.6.22-570/fs/nfsd/nfs4state.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfsd/nfs4state.c       2008-01-02 13:56:37.000000000 -0500
-@@ -378,7 +378,6 @@
-       if (clnt) {
-               clp->cl_callback.cb_client = NULL;
-               rpc_shutdown_client(clnt);
--              rpciod_down();
+       BUG_ON(fibptr == NULL);
+               
+-      scsi_dma_unmap(scsicmd);
+-
++      if(scsicmd->use_sg)
++              pci_unmap_sg(dev->pdev, 
++                      (struct scatterlist *)scsicmd->request_buffer,
++                      scsicmd->use_sg,
++                      scsicmd->sc_data_direction);
++      else if(scsicmd->request_bufflen)
++              pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle,
++                               scsicmd->request_bufflen,
++                               scsicmd->sc_data_direction);
+       readreply = (struct aac_read_reply *)fib_data(fibptr);
+       if (le32_to_cpu(readreply->status) == ST_OK)
+               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+@@ -1506,7 +1498,6 @@
+ {
+       u64 lba;
+       u32 count;
+-      int fua;
+       int status;
+       struct aac_dev *dev;
+       struct fib * cmd_fibcontext;
+@@ -1521,7 +1512,6 @@
+               count = scsicmd->cmnd[4];
+               if (count == 0)
+                       count = 256;
+-              fua = 0;
+       } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */
+               dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd)));
+@@ -1534,7 +1524,6 @@
+                       (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
+               count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) |
+                       (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
+-              fua = scsicmd->cmnd[1] & 0x8;
+       } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */
+               dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd)));
+@@ -1542,12 +1531,10 @@
+                   | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+               count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16)
+                     | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
+-              fua = scsicmd->cmnd[1] & 0x8;
+       } else {
+               dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd)));
+               lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+               count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
+-              fua = scsicmd->cmnd[1] & 0x8;
+       }
+       dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
+         smp_processor_id(), (unsigned long long)lba, jiffies));
+@@ -1562,7 +1549,7 @@
+               return 0;
        }
- }
  
-diff -Nurb linux-2.6.22-570/fs/nfsd/nfssvc.c linux-2.6.22-590/fs/nfsd/nfssvc.c
---- linux-2.6.22-570/fs/nfsd/nfssvc.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/nfsd/nfssvc.c  2008-01-02 13:56:37.000000000 -0500
-@@ -19,6 +19,7 @@
- #include <linux/slab.h>
- #include <linux/smp.h>
- #include <linux/smp_lock.h>
-+#include <linux/freezer.h>
- #include <linux/fs_struct.h>
+-      status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua);
++      status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count);
  
- #include <linux/sunrpc/types.h>
-@@ -432,6 +433,7 @@
-        * dirty pages.
+       /*
+        *      Check that the command queued to the controller
+@@ -1605,7 +1592,7 @@
+                       COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+       else {
+               struct scsi_device *sdev = cmd->device;
+-              struct aac_dev *dev = fibptr->dev;
++              struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
+               u32 cid = sdev_id(sdev);
+               printk(KERN_WARNING 
+                    "synchronize_callback: synchronize failed, status = %d\n",
+@@ -1712,7 +1699,7 @@
+  
+ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ {
+-      u32 cid;
++      u32 cid = 0;
+       struct Scsi_Host *host = scsicmd->device->host;
+       struct aac_dev *dev = (struct aac_dev *)host->hostdata;
+       struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
+@@ -1724,15 +1711,15 @@
+        *      Test does not apply to ID 16, the pseudo id for the controller
+        *      itself.
         */
-       current->flags |= PF_LESS_THROTTLE;
-+      set_freezable();
+-      cid = scmd_id(scsicmd);
+-      if (cid != host->this_id) {
+-              if (scmd_channel(scsicmd) == CONTAINER_CHANNEL) {
+-                      if((cid >= dev->maximum_num_containers) ||
++      if (scmd_id(scsicmd) != host->this_id) {
++              if ((scmd_channel(scsicmd) == CONTAINER_CHANNEL)) {
++                      if((scmd_id(scsicmd) >= dev->maximum_num_containers) ||
+                                       (scsicmd->device->lun != 0)) {
+                               scsicmd->result = DID_NO_CONNECT << 16;
+                               scsicmd->scsi_done(scsicmd);
+                               return 0;
+                       }
++                      cid = scmd_id(scsicmd);
  
-       /*
-        * The main request loop
-diff -Nurb linux-2.6.22-570/fs/ocfs2/alloc.c linux-2.6.22-590/fs/ocfs2/alloc.c
---- linux-2.6.22-570/fs/ocfs2/alloc.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/alloc.c  2008-01-02 13:56:37.000000000 -0500
-@@ -50,6 +50,8 @@
- #include "buffer_head_io.h"
+                       /*
+                        *      If the target container doesn't exist, it may have
+@@ -1795,7 +1782,7 @@
+       {
+               struct inquiry_data inq_data;
  
- static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc);
-+static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
-+                                       struct ocfs2_extent_block *eb);
+-              dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid));
++              dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scmd_id(scsicmd)));
+               memset(&inq_data, 0, sizeof (struct inquiry_data));
  
- /*
-  * Structures which describe a path through a btree, and functions to
-@@ -117,6 +119,31 @@
- }
+               inq_data.inqd_ver = 2;  /* claim compliance to SCSI-2 */
+@@ -1807,7 +1794,7 @@
+                *      Set the Vendor, Product, and Revision Level
+                *      see: <vendor>.c i.e. aac.c
+                */
+-              if (cid == host->this_id) {
++              if (scmd_id(scsicmd) == host->this_id) {
+                       setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types));
+                       inq_data.inqd_pdt = INQD_PDT_PROC;      /* Processor device */
+                       aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
+@@ -1899,29 +1886,15 @@
  
- /*
-+ * All the elements of src into dest. After this call, src could be freed
-+ * without affecting dest.
-+ *
-+ * Both paths should have the same root. Any non-root elements of dest
-+ * will be freed.
-+ */
-+static void ocfs2_cp_path(struct ocfs2_path *dest, struct ocfs2_path *src)
-+{
-+      int i;
-+
-+      BUG_ON(path_root_bh(dest) != path_root_bh(src));
-+      BUG_ON(path_root_el(dest) != path_root_el(src));
-+
-+      ocfs2_reinit_path(dest, 1);
-+
-+      for(i = 1; i < OCFS2_MAX_PATH_DEPTH; i++) {
-+              dest->p_node[i].bh = src->p_node[i].bh;
-+              dest->p_node[i].el = src->p_node[i].el;
-+
-+              if (dest->p_node[i].bh)
-+                      get_bh(dest->p_node[i].bh);
-+      }
-+}
-+
-+/*
-  * Make the *dest path the same as src and re-initialize src path to
-  * have a root only.
-  */
-@@ -212,10 +239,41 @@
-       return ret;
- }
+       case MODE_SENSE:
+       {
+-              char mode_buf[7];
+-              int mode_buf_length = 4;
++              char mode_buf[4];
  
-+/*
-+ * Return the index of the extent record which contains cluster #v_cluster.
-+ * -1 is returned if it was not found.
-+ *
-+ * Should work fine on interior and exterior nodes.
-+ */
-+int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster)
-+{
-+      int ret = -1;
-+      int i;
-+      struct ocfs2_extent_rec *rec;
-+      u32 rec_end, rec_start, clusters;
-+
-+      for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
-+              rec = &el->l_recs[i];
-+
-+              rec_start = le32_to_cpu(rec->e_cpos);
-+              clusters = ocfs2_rec_clusters(el, rec);
-+
-+              rec_end = rec_start + clusters;
-+
-+              if (v_cluster >= rec_start && v_cluster < rec_end) {
-+                      ret = i;
-+                      break;
-+              }
-+      }
-+
-+      return ret;
-+}
+               dprintk((KERN_DEBUG "MODE SENSE command.\n"));
+               mode_buf[0] = 3;        /* Mode data length */
+               mode_buf[1] = 0;        /* Medium type - default */
+-              mode_buf[2] = 0;        /* Device-specific param,
+-                                         bit 8: 0/1 = write enabled/protected
+-                                         bit 4: 0/1 = FUA enabled */
+-              if (dev->raw_io_interface)
+-                      mode_buf[2] = 0x10;
++              mode_buf[2] = 0;        /* Device-specific param, bit 8: 0/1 = write enabled/protected */
+               mode_buf[3] = 0;        /* Block descriptor length */
+-              if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
+-                ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
+-                      mode_buf[0] = 6;
+-                      mode_buf[4] = 8;
+-                      mode_buf[5] = 1;
+-                      mode_buf[6] = 0x04; /* WCE */
+-                      mode_buf_length = 7;
+-                      if (mode_buf_length > scsicmd->cmnd[4])
+-                              mode_buf_length = scsicmd->cmnd[4];
+-              }
+-              aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
 +
- enum ocfs2_contig_type {
-       CONTIG_NONE = 0,
-       CONTIG_LEFT,
--      CONTIG_RIGHT
-+      CONTIG_RIGHT,
-+      CONTIG_LEFTRIGHT,
- };
++              aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
+               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+               scsicmd->scsi_done(scsicmd);
  
+@@ -1929,33 +1902,18 @@
+       }
+       case MODE_SENSE_10:
+       {
+-              char mode_buf[11];
+-              int mode_buf_length = 8;
++              char mode_buf[8];
  
-@@ -253,6 +311,14 @@
- {
-       u64 blkno = le64_to_cpu(insert_rec->e_blkno);
+               dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));
+               mode_buf[0] = 0;        /* Mode data length (MSB) */
+               mode_buf[1] = 6;        /* Mode data length (LSB) */
+               mode_buf[2] = 0;        /* Medium type - default */
+-              mode_buf[3] = 0;        /* Device-specific param,
+-                                         bit 8: 0/1 = write enabled/protected
+-                                         bit 4: 0/1 = FUA enabled */
+-              if (dev->raw_io_interface)
+-                      mode_buf[3] = 0x10;
++              mode_buf[3] = 0;        /* Device-specific param, bit 8: 0/1 = write enabled/protected */
+               mode_buf[4] = 0;        /* reserved */
+               mode_buf[5] = 0;        /* reserved */
+               mode_buf[6] = 0;        /* Block descriptor length (MSB) */
+               mode_buf[7] = 0;        /* Block descriptor length (LSB) */
+-              if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
+-                ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
+-                      mode_buf[1] = 9;
+-                      mode_buf[8] = 8;
+-                      mode_buf[9] = 1;
+-                      mode_buf[10] = 0x04; /* WCE */
+-                      mode_buf_length = 11;
+-                      if (mode_buf_length > scsicmd->cmnd[8])
+-                              mode_buf_length = scsicmd->cmnd[8];
+-              }
+-              aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
++              aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
  
-+      /*
-+       * Refuse to coalesce extent records with different flag
-+       * fields - we don't want to mix unwritten extents with user
-+       * data.
-+       */
-+      if (ext->e_flags != insert_rec->e_flags)
-+              return CONTIG_NONE;
-+
-       if (ocfs2_extents_adjacent(ext, insert_rec) &&
-           ocfs2_block_extent_contig(inode->i_sb, ext, blkno))
-                       return CONTIG_RIGHT;
-@@ -277,7 +343,14 @@
-       APPEND_TAIL,
- };
+               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+               scsicmd->scsi_done(scsicmd);
+@@ -2178,9 +2136,9 @@
+       if (!aac_valid_context(scsicmd, fibptr))
+               return;
  
-+enum ocfs2_split_type {
-+      SPLIT_NONE = 0,
-+      SPLIT_LEFT,
-+      SPLIT_RIGHT,
-+};
-+
- struct ocfs2_insert_type {
-+      enum ocfs2_split_type   ins_split;
-       enum ocfs2_append_type  ins_appending;
-       enum ocfs2_contig_type  ins_contig;
-       int                     ins_contig_index;
-@@ -285,6 +358,13 @@
-       int                     ins_tree_depth;
- };
+-      BUG_ON(fibptr == NULL);
++      dev = (struct aac_dev *)scsicmd->device->host->hostdata;
  
-+struct ocfs2_merge_ctxt {
-+      enum ocfs2_contig_type  c_contig_type;
-+      int                     c_has_empty_extent;
-+      int                     c_split_covers_rec;
-+      int                     c_used_tail_recs;
-+};
-+
- /*
-  * How many free extents have we got before we need more meta data?
-  */
-@@ -384,13 +464,7 @@
-                       strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE);
-                       eb->h_blkno = cpu_to_le64(first_blkno);
-                       eb->h_fs_generation = cpu_to_le32(osb->fs_generation);
--
--#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
--                      /* we always use slot zero's suballocator */
--                      eb->h_suballoc_slot = 0;
--#else
-                       eb->h_suballoc_slot = cpu_to_le16(osb->slot_num);
--#endif
-                       eb->h_suballoc_bit = cpu_to_le16(suballoc_bit_start);
-                       eb->h_list.l_count =
-                               cpu_to_le16(ocfs2_extent_recs_per_eb(osb->sb));
-@@ -461,7 +535,7 @@
-                           struct inode *inode,
-                           struct buffer_head *fe_bh,
-                           struct buffer_head *eb_bh,
--                          struct buffer_head *last_eb_bh,
-+                          struct buffer_head **last_eb_bh,
-                           struct ocfs2_alloc_context *meta_ac)
- {
-       int status, new_blocks, i;
-@@ -476,7 +550,7 @@
+-      dev = fibptr->dev;
++      BUG_ON(fibptr == NULL);
  
-       mlog_entry_void();
+       srbreply = (struct aac_srb_reply *) fib_data(fibptr);
  
--      BUG_ON(!last_eb_bh);
-+      BUG_ON(!last_eb_bh || !*last_eb_bh);
+@@ -2189,10 +2147,17 @@
+        *      Calculate resid for sg 
+        */
+        
+-      scsi_set_resid(scsicmd, scsi_bufflen(scsicmd)
+-                     - le32_to_cpu(srbreply->data_xfer_length));
++      scsicmd->resid = scsicmd->request_bufflen - 
++              le32_to_cpu(srbreply->data_xfer_length);
+-      scsi_dma_unmap(scsicmd);
++      if(scsicmd->use_sg)
++              pci_unmap_sg(dev->pdev, 
++                      (struct scatterlist *)scsicmd->request_buffer,
++                      scsicmd->use_sg,
++                      scsicmd->sc_data_direction);
++      else if(scsicmd->request_bufflen)
++              pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, scsicmd->request_bufflen,
++                      scsicmd->sc_data_direction);
  
-       fe = (struct ocfs2_dinode *) fe_bh->b_data;
+       /*
+        * First check the fib status
+@@ -2268,7 +2233,7 @@
+               break;
  
-@@ -507,7 +581,7 @@
-               goto bail;
-       }
+       case SRB_STATUS_BUSY:
+-              scsicmd->result = DID_BUS_BUSY << 16 | COMMAND_COMPLETE << 8;
++              scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
+               break;
  
--      eb = (struct ocfs2_extent_block *)last_eb_bh->b_data;
-+      eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
-       new_cpos = ocfs2_sum_rightmost_rec(&eb->h_list);
+       case SRB_STATUS_BUS_RESET:
+@@ -2378,33 +2343,34 @@
+ {
+       struct aac_dev *dev;
+       unsigned long byte_count = 0;
+-      int nseg;
  
-       /* Note: new_eb_bhs[new_blocks - 1] is the guy which will be
-@@ -568,7 +642,7 @@
-        * journal_dirty erroring as it won't unless we've aborted the
-        * handle (in which case we would never be here) so reserving
-        * the write with journal_access is all we need to do. */
--      status = ocfs2_journal_access(handle, inode, last_eb_bh,
-+      status = ocfs2_journal_access(handle, inode, *last_eb_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
-       if (status < 0) {
-               mlog_errno(status);
-@@ -601,10 +675,10 @@
-        * next_leaf on the previously last-extent-block. */
-       fe->i_last_eb_blk = cpu_to_le64(new_last_eb_blk);
+       dev = (struct aac_dev *)scsicmd->device->host->hostdata;
+       // Get rid of old data
+       psg->count = 0;
+       psg->sg[0].addr = 0;
+       psg->sg[0].count = 0;  
+-
+-      nseg = scsi_dma_map(scsicmd);
+-      BUG_ON(nseg < 0);
+-      if (nseg) {
++      if (scsicmd->use_sg) {
+               struct scatterlist *sg;
+               int i;
++              int sg_count;
++              sg = (struct scatterlist *) scsicmd->request_buffer;
  
--      eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
-+      eb = (struct ocfs2_extent_block *) (*last_eb_bh)->b_data;
-       eb->h_next_leaf_blk = cpu_to_le64(new_last_eb_blk);
+-              psg->count = cpu_to_le32(nseg);
++              sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
++                      scsicmd->sc_data_direction);
++              psg->count = cpu_to_le32(sg_count);
  
--      status = ocfs2_journal_dirty(handle, last_eb_bh);
-+      status = ocfs2_journal_dirty(handle, *last_eb_bh);
-       if (status < 0)
-               mlog_errno(status);
-       status = ocfs2_journal_dirty(handle, fe_bh);
-@@ -616,6 +690,14 @@
-                       mlog_errno(status);
+-              scsi_for_each_sg(scsicmd, sg, nseg, i) {
++              for (i = 0; i < sg_count; i++) {
+                       psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
+                       psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
+                       byte_count += sg_dma_len(sg);
++                      sg++;
+               }
+               /* hba wants the size to be exact */
+-              if (byte_count > scsi_bufflen(scsicmd)) {
++              if(byte_count > scsicmd->request_bufflen){
+                       u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
+-                              (byte_count - scsi_bufflen(scsicmd));
++                              (byte_count - scsicmd->request_bufflen);
+                       psg->sg[i-1].count = cpu_to_le32(temp);
+-                      byte_count = scsi_bufflen(scsicmd);
++                      byte_count = scsicmd->request_bufflen;
+               }
+               /* Check for command underflow */
+               if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
+@@ -2412,6 +2378,18 @@
+                                       byte_count, scsicmd->underflow);
+               }
        }
-+      /*
-+       * Some callers want to track the rightmost leaf so pass it
-+       * back here.
-+       */
-+      brelse(*last_eb_bh);
-+      get_bh(new_eb_bhs[0]);
-+      *last_eb_bh = new_eb_bhs[0];
-+
-       status = 0;
- bail:
-       if (new_eb_bhs) {
-@@ -829,6 +911,87 @@
- }
- /*
-+ * Grow a b-tree so that it has more records.
-+ *
-+ * We might shift the tree depth in which case existing paths should
-+ * be considered invalid.
-+ *
-+ * Tree depth after the grow is returned via *final_depth.
-+ *
-+ * *last_eb_bh will be updated by ocfs2_add_branch().
-+ */
-+static int ocfs2_grow_tree(struct inode *inode, handle_t *handle,
-+                         struct buffer_head *di_bh, int *final_depth,
-+                         struct buffer_head **last_eb_bh,
-+                         struct ocfs2_alloc_context *meta_ac)
-+{
-+      int ret, shift;
-+      struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
-+      int depth = le16_to_cpu(di->id2.i_list.l_tree_depth);
-+      struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-+      struct buffer_head *bh = NULL;
-+
-+      BUG_ON(meta_ac == NULL);
-+
-+      shift = ocfs2_find_branch_target(osb, inode, di_bh, &bh);
-+      if (shift < 0) {
-+              ret = shift;
-+              mlog_errno(ret);
-+              goto out;
-+      }
-+
-+      /* We traveled all the way to the bottom of the allocation tree
-+       * and didn't find room for any more extents - we need to add
-+       * another tree level */
-+      if (shift) {
-+              BUG_ON(bh);
-+              mlog(0, "need to shift tree depth (current = %d)\n", depth);
-+
-+              /* ocfs2_shift_tree_depth will return us a buffer with
-+               * the new extent block (so we can pass that to
-+               * ocfs2_add_branch). */
-+              ret = ocfs2_shift_tree_depth(osb, handle, inode, di_bh,
-+                                           meta_ac, &bh);
-+              if (ret < 0) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
-+              depth++;
-+              if (depth == 1) {
-+                      /*
-+                       * Special case: we have room now if we shifted from
-+                       * tree_depth 0, so no more work needs to be done.
-+                       *
-+                       * We won't be calling add_branch, so pass
-+                       * back *last_eb_bh as the new leaf. At depth
-+                       * zero, it should always be null so there's
-+                       * no reason to brelse.
-+                       */
-+                      BUG_ON(*last_eb_bh);
-+                      get_bh(bh);
-+                      *last_eb_bh = bh;
-+                      goto out;
-+              }
-+      }
-+
-+      /* call ocfs2_add_branch to add the final part of the tree with
-+       * the new data. */
-+      mlog(0, "add branch. bh = %p\n", bh);
-+      ret = ocfs2_add_branch(osb, handle, inode, di_bh, bh, last_eb_bh,
-+                             meta_ac);
-+      if (ret < 0) {
-+              mlog_errno(ret);
-+              goto out;
++      else if(scsicmd->request_bufflen) {
++              u32 addr;
++              scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
++                              scsicmd->request_buffer,
++                              scsicmd->request_bufflen,
++                              scsicmd->sc_data_direction);
++              addr = scsicmd->SCp.dma_handle;
++              psg->count = cpu_to_le32(1);
++              psg->sg[0].addr = cpu_to_le32(addr);
++              psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
++              byte_count = scsicmd->request_bufflen;
 +      }
-+
-+out:
-+      if (final_depth)
-+              *final_depth = depth;
-+      brelse(bh);
-+      return ret;
-+}
-+
-+/*
-  * This is only valid for leaf nodes, which are the only ones that can
-  * have empty extents anyway.
-  */
-@@ -934,6 +1097,22 @@
+       return byte_count;
  }
  
-+static void ocfs2_remove_empty_extent(struct ocfs2_extent_list *el)
-+{
-+      int size, num_recs = le16_to_cpu(el->l_next_free_rec);
-+
-+      BUG_ON(num_recs == 0);
-+
-+      if (ocfs2_is_empty_extent(&el->l_recs[0])) {
-+              num_recs--;
-+              size = num_recs * sizeof(struct ocfs2_extent_rec);
-+              memmove(&el->l_recs[0], &el->l_recs[1], size);
-+              memset(&el->l_recs[num_recs], 0,
-+                     sizeof(struct ocfs2_extent_rec));
-+              el->l_next_free_rec = cpu_to_le16(num_recs);
-+      }
-+}
+@@ -2421,7 +2399,6 @@
+       struct aac_dev *dev;
+       unsigned long byte_count = 0;
+       u64 addr;
+-      int nseg;
+       dev = (struct aac_dev *)scsicmd->device->host->hostdata;
+       // Get rid of old data
+@@ -2429,28 +2406,31 @@
+       psg->sg[0].addr[0] = 0;
+       psg->sg[0].addr[1] = 0;
+       psg->sg[0].count = 0;
+-
+-      nseg = scsi_dma_map(scsicmd);
+-      BUG_ON(nseg < 0);
+-      if (nseg) {
++      if (scsicmd->use_sg) {
+               struct scatterlist *sg;
+               int i;
++              int sg_count;
++              sg = (struct scatterlist *) scsicmd->request_buffer;
 +
- /*
-  * Create an empty extent record .
-  *
-@@ -1211,6 +1390,10 @@
-        * immediately to their right.
-        */
-       left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);
-+      if (ocfs2_is_empty_extent(&right_child_el->l_recs[0])) {
-+              BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1);
-+              left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);
-+      }
-       left_clusters -= le32_to_cpu(left_rec->e_cpos);
-       left_rec->e_int_clusters = cpu_to_le32(left_clusters);
++              sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
++                      scsicmd->sc_data_direction);
  
-@@ -1531,10 +1714,16 @@
-       return ret;
+-              scsi_for_each_sg(scsicmd, sg, nseg, i) {
++              for (i = 0; i < sg_count; i++) {
+                       int count = sg_dma_len(sg);
+                       addr = sg_dma_address(sg);
+                       psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+                       psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
+                       psg->sg[i].count = cpu_to_le32(count);
+                       byte_count += count;
++                      sg++;
+               }
+-              psg->count = cpu_to_le32(nseg);
++              psg->count = cpu_to_le32(sg_count);
+               /* hba wants the size to be exact */
+-              if (byte_count > scsi_bufflen(scsicmd)) {
++              if(byte_count > scsicmd->request_bufflen){
+                       u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
+-                              (byte_count - scsi_bufflen(scsicmd));
++                              (byte_count - scsicmd->request_bufflen);
+                       psg->sg[i-1].count = cpu_to_le32(temp);
+-                      byte_count = scsi_bufflen(scsicmd);
++                      byte_count = scsicmd->request_bufflen;
+               }
+               /* Check for command underflow */
+               if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
+@@ -2458,13 +2438,26 @@
+                                       byte_count, scsicmd->underflow);
+               }
+       }
++      else if(scsicmd->request_bufflen) {
++              scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
++                              scsicmd->request_buffer,
++                              scsicmd->request_bufflen,
++                              scsicmd->sc_data_direction);
++              addr = scsicmd->SCp.dma_handle;
++              psg->count = cpu_to_le32(1);
++              psg->sg[0].addr[0] = cpu_to_le32(addr & 0xffffffff);
++              psg->sg[0].addr[1] = cpu_to_le32(addr >> 32);
++              psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
++              byte_count = scsicmd->request_bufflen;
++      }
+       return byte_count;
  }
  
-+/*
-+ * Extend the transaction by enough credits to complete the rotation,
-+ * and still leave at least the original number of credits allocated
-+ * to this transaction.
-+ */
- static int ocfs2_extend_rotate_transaction(handle_t *handle, int subtree_depth,
-+                                         int op_credits,
-                                          struct ocfs2_path *path)
+ static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg)
  {
--      int credits = (path->p_tree_depth - subtree_depth) * 2 + 1;
-+      int credits = (path->p_tree_depth - subtree_depth) * 2 + 1 + op_credits;
++      struct Scsi_Host *host = scsicmd->device->host;
++      struct aac_dev *dev = (struct aac_dev *)host->hostdata;
+       unsigned long byte_count = 0;
+-      int nseg;
  
-       if (handle->h_buffer_credits < credits)
-               return ocfs2_extend_trans(handle, credits);
-@@ -1568,6 +1757,29 @@
-       return 0;
- }
+       // Get rid of old data
+       psg->count = 0;
+@@ -2474,14 +2467,16 @@
+       psg->sg[0].addr[1] = 0;
+       psg->sg[0].count = 0;
+       psg->sg[0].flags = 0;
+-
+-      nseg = scsi_dma_map(scsicmd);
+-      BUG_ON(nseg < 0);
+-      if (nseg) {
++      if (scsicmd->use_sg) {
+               struct scatterlist *sg;
+               int i;
++              int sg_count;
++              sg = (struct scatterlist *) scsicmd->request_buffer;
  
-+static int ocfs2_leftmost_rec_contains(struct ocfs2_extent_list *el, u32 cpos)
-+{
-+      int next_free = le16_to_cpu(el->l_next_free_rec);
-+      unsigned int range;
-+      struct ocfs2_extent_rec *rec;
-+
-+      if (next_free == 0)
-+              return 0;
+-              scsi_for_each_sg(scsicmd, sg, nseg, i) {
++              sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
++                      scsicmd->sc_data_direction);
 +
-+      rec = &el->l_recs[0];
-+      if (ocfs2_is_empty_extent(rec)) {
-+              /* Empty list. */
-+              if (next_free == 1)
-+                      return 0;
-+              rec = &el->l_recs[1];
++              for (i = 0; i < sg_count; i++) {
+                       int count = sg_dma_len(sg);
+                       u64 addr = sg_dma_address(sg);
+                       psg->sg[i].next = 0;
+@@ -2491,14 +2486,15 @@
+                       psg->sg[i].count = cpu_to_le32(count);
+                       psg->sg[i].flags = 0;
+                       byte_count += count;
++                      sg++;
+               }
+-              psg->count = cpu_to_le32(nseg);
++              psg->count = cpu_to_le32(sg_count);
+               /* hba wants the size to be exact */
+-              if (byte_count > scsi_bufflen(scsicmd)) {
++              if(byte_count > scsicmd->request_bufflen){
+                       u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
+-                              (byte_count - scsi_bufflen(scsicmd));
++                              (byte_count - scsicmd->request_bufflen);
+                       psg->sg[i-1].count = cpu_to_le32(temp);
+-                      byte_count = scsi_bufflen(scsicmd);
++                      byte_count = scsicmd->request_bufflen;
+               }
+               /* Check for command underflow */
+               if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
+@@ -2506,6 +2502,24 @@
+                                       byte_count, scsicmd->underflow);
+               }
+       }
++      else if(scsicmd->request_bufflen) {
++              int count;
++              u64 addr;
++              scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
++                              scsicmd->request_buffer,
++                              scsicmd->request_bufflen,
++                              scsicmd->sc_data_direction);
++              addr = scsicmd->SCp.dma_handle;
++              count = scsicmd->request_bufflen;
++              psg->count = cpu_to_le32(1);
++              psg->sg[0].next = 0;
++              psg->sg[0].prev = 0;
++              psg->sg[0].addr[1] = cpu_to_le32((u32)(addr>>32));
++              psg->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
++              psg->sg[0].count = cpu_to_le32(count);
++              psg->sg[0].flags = 0;
++              byte_count = scsicmd->request_bufflen;
 +      }
-+
-+      range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
-+      if (cpos >= le32_to_cpu(rec->e_cpos) && cpos < range)
-+              return 1;
-+      return 0;
-+}
-+
- /*
-  * Rotate all the records in a btree right one record, starting at insert_cpos.
-  *
-@@ -1586,11 +1798,12 @@
-  */
- static int ocfs2_rotate_tree_right(struct inode *inode,
-                                  handle_t *handle,
-+                                 enum ocfs2_split_type split,
-                                  u32 insert_cpos,
-                                  struct ocfs2_path *right_path,
-                                  struct ocfs2_path **ret_left_path)
- {
--      int ret, start;
-+      int ret, start, orig_credits = handle->h_buffer_credits;
-       u32 cpos;
-       struct ocfs2_path *left_path = NULL;
+       return byte_count;
+ }
  
-@@ -1657,9 +1870,9 @@
-                               (unsigned long long)
-                               path_leaf_bh(left_path)->b_blocknr);
+diff -Nurb linux-2.6.22-590/drivers/scsi/aacraid/aacraid.h linux-2.6.22-570/drivers/scsi/aacraid/aacraid.h
+--- linux-2.6.22-590/drivers/scsi/aacraid/aacraid.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/aacraid/aacraid.h    2007-07-08 19:32:17.000000000 -0400
+@@ -12,8 +12,8 @@
+  *----------------------------------------------------------------------------*/
  
--              if (ocfs2_rotate_requires_path_adjustment(left_path,
-+              if (split == SPLIT_NONE &&
-+                  ocfs2_rotate_requires_path_adjustment(left_path,
-                                                         insert_cpos)) {
--                      mlog(0, "Path adjustment required\n");
+ #ifndef AAC_DRIVER_BUILD
+-# define AAC_DRIVER_BUILD 2447
+-# define AAC_DRIVER_BRANCH "-ms"
++# define AAC_DRIVER_BUILD 2437
++# define AAC_DRIVER_BRANCH "-mh4"
+ #endif
+ #define MAXIMUM_NUM_CONTAINERS        32
  
-                       /*
-                        * We've rotated the tree as much as we
-@@ -1687,7 +1900,7 @@
-                    right_path->p_tree_depth);
+@@ -464,12 +464,12 @@
+       int  (*adapter_restart)(struct aac_dev *dev, int bled);
+       /* Transport operations */
+       int  (*adapter_ioremap)(struct aac_dev * dev, u32 size);
+-      irq_handler_t adapter_intr;
++      irqreturn_t (*adapter_intr)(int irq, void *dev_id);
+       /* Packet operations */
+       int  (*adapter_deliver)(struct fib * fib);
+       int  (*adapter_bounds)(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba);
+       int  (*adapter_read)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count);
+-      int  (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua);
++      int  (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count);
+       int  (*adapter_scsi)(struct fib * fib, struct scsi_cmnd * cmd);
+       /* Administrative operations */
+       int  (*adapter_comm)(struct aac_dev * dev, int comm);
+@@ -860,12 +860,10 @@
+       __le32  FlashFirmwareBootBuild;
+       u8      MfgPcbaSerialNo[12];
+       u8      MfgWWNName[8];
+-      __le32  SupportedOptions2;
++      __le32  MoreFeatureBits;
+       __le32  ReservedGrowth[1];
+ };
+ #define AAC_FEATURE_FALCON    0x00000010
+-#define AAC_OPTION_MU_RESET   0x00000001
+-#define AAC_OPTION_IGNORE_RESET       0x00000002
+ #define AAC_SIS_VERSION_V3    3
+ #define AAC_SIS_SLOT_UNKNOWN  0xFF
  
-               ret = ocfs2_extend_rotate_transaction(handle, start,
--                                                    right_path);
-+                                                    orig_credits, right_path);
-               if (ret) {
-                       mlog_errno(ret);
-                       goto out;
-@@ -1700,6 +1913,24 @@
-                       goto out;
-               }
+@@ -1056,8 +1054,8 @@
+ #define aac_adapter_read(fib,cmd,lba,count) \
+       ((fib)->dev)->a_ops.adapter_read(fib,cmd,lba,count)
+-#define aac_adapter_write(fib,cmd,lba,count,fua) \
+-      ((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count,fua)
++#define aac_adapter_write(fib,cmd,lba,count) \
++      ((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count)
+ #define aac_adapter_scsi(fib,cmd) \
+       ((fib)->dev)->a_ops.adapter_scsi(fib,cmd)
+@@ -1215,9 +1213,6 @@
+       __le32          block;
+       __le16          pad;
+       __le16          flags;
+-#define       IO_TYPE_WRITE 0x00000000
+-#define       IO_TYPE_READ  0x00000001
+-#define       IO_SUREWRITE  0x00000008
+       struct sgmap64  sg;     // Must be last in struct because it is variable
+ };
+ struct aac_write_reply
+@@ -1262,19 +1257,6 @@
+       u8              data[16];
+ };
+-#define CT_PAUSE_IO    65
+-#define CT_RELEASE_IO  66
+-struct aac_pause {
+-      __le32          command;        /* VM_ContainerConfig */
+-      __le32          type;           /* CT_PAUSE_IO */
+-      __le32          timeout;        /* 10ms ticks */
+-      __le32          min;
+-      __le32          noRescan;
+-      __le32          parm3;
+-      __le32          parm4;
+-      __le32          count;  /* sizeof(((struct aac_pause_reply *)NULL)->data) */
+-};
+-
+ struct aac_srb
+ {
+       __le32          function;
+@@ -1822,10 +1804,6 @@
+ int aac_get_containers(struct aac_dev *dev);
+ int aac_scsi_cmd(struct scsi_cmnd *cmd);
+ int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg);
+-#ifndef shost_to_class
+-#define shost_to_class(shost) &shost->shost_classdev
+-#endif
+-ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf);
+ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg);
+ int aac_rx_init(struct aac_dev *dev);
+ int aac_rkt_init(struct aac_dev *dev);
+@@ -1835,7 +1813,6 @@
+ unsigned int aac_response_normal(struct aac_queue * q);
+ unsigned int aac_command_normal(struct aac_queue * q);
+ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
+-int aac_reset_adapter(struct aac_dev * dev, int forced);
+ int aac_check_health(struct aac_dev * dev);
+ int aac_command_thread(void *data);
+ int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
+@@ -1855,6 +1832,3 @@
+ extern int expose_physicals;
+ extern int aac_reset_devices;
+ extern int aac_commit;
+-extern int update_interval;
+-extern int check_interval;
+-extern int check_reset;
+diff -Nurb linux-2.6.22-590/drivers/scsi/aacraid/commsup.c linux-2.6.22-570/drivers/scsi/aacraid/commsup.c
+--- linux-2.6.22-590/drivers/scsi/aacraid/commsup.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/aacraid/commsup.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1021,7 +1021,7 @@
  
-+              if (split != SPLIT_NONE &&
-+                  ocfs2_leftmost_rec_contains(path_leaf_el(right_path),
-+                                              insert_cpos)) {
-+                      /*
-+                       * A rotate moves the rightmost left leaf
-+                       * record over to the leftmost right leaf
-+                       * slot. If we're doing an extent split
-+                       * instead of a real insert, then we have to
-+                       * check that the extent to be split wasn't
-+                       * just moved over. If it was, then we can
-+                       * exit here, passing left_path back -
-+                       * ocfs2_split_extent() is smart enough to
-+                       * search both leaves.
-+                       */
-+                      *ret_left_path = left_path;
-+                      goto out_ret_path;
-+              }
-+
-               /*
-                * There is no need to re-read the next right path
-                * as we know that it'll be our current left
-@@ -1722,124 +1953,935 @@
-       return ret;
  }
  
--/*
-- * Do the final bits of extent record insertion at the target leaf
-- * list. If this leaf is part of an allocation tree, it is assumed
-- * that the tree above has been prepared.
-- */
--static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
--                               struct ocfs2_extent_list *el,
--                               struct ocfs2_insert_type *insert,
--                               struct inode *inode)
-+static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
-+                                    struct ocfs2_path *path)
+-static int _aac_reset_adapter(struct aac_dev *aac, int forced)
++static int _aac_reset_adapter(struct aac_dev *aac)
  {
--      int i = insert->ins_contig_index;
--      unsigned int range;
-+      int i, idx;
-       struct ocfs2_extent_rec *rec;
-+      struct ocfs2_extent_list *el;
-+      struct ocfs2_extent_block *eb;
-+      u32 range;
+       int index, quirks;
+       int retval;
+@@ -1029,32 +1029,25 @@
+       struct scsi_device *dev;
+       struct scsi_cmnd *command;
+       struct scsi_cmnd *command_list;
+-      int jafo = 0;
  
--      BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
-+      /* Path should always be rightmost. */
-+      eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
-+      BUG_ON(eb->h_next_leaf_blk != 0ULL);
+       /*
+        * Assumptions:
+-       *      - host is locked, unless called by the aacraid thread.
+-       *        (a matter of convenience, due to legacy issues surrounding
+-       *        eh_host_adapter_reset).
++       *      - host is locked.
+        *      - in_reset is asserted, so no new i/o is getting to the
+        *        card.
+-       *      - The card is dead, or will be very shortly ;-/ so no new
+-       *        commands are completing in the interrupt service.
++       *      - The card is dead.
+        */
+       host = aac->scsi_host_ptr;
+       scsi_block_requests(host);
+       aac_adapter_disable_int(aac);
+-      if (aac->thread->pid != current->pid) {
+       spin_unlock_irq(host->host_lock);
+       kthread_stop(aac->thread);
+-              jafo = 1;
+-      }
+       /*
+        *      If a positive health, means in a known DEAD PANIC
+        * state and the adapter could be reset to `try again'.
+        */
+-      retval = aac_adapter_restart(aac, forced ? 0 : aac_adapter_check_health(aac));
++      retval = aac_adapter_restart(aac, aac_adapter_check_health(aac));
  
+       if (retval)
+               goto out;
+@@ -1111,13 +1104,11 @@
+       if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT)
+               if ((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK)))
+                       goto out;
+-      if (jafo) {
+       aac->thread = kthread_run(aac_command_thread, aac, aac->name);
+       if (IS_ERR(aac->thread)) {
+               retval = PTR_ERR(aac->thread);
+               goto out;
+       }
+-      }
+       (void)aac_get_adapter_info(aac);
+       quirks = aac_get_driver_ident(index)->quirks;
+       if ((quirks & AAC_QUIRK_34SG) && (host->sg_tablesize > 34)) {
+@@ -1159,98 +1150,7 @@
+ out:
+       aac->in_reset = 0;
+       scsi_unblock_requests(host);
+-      if (jafo) {
+       spin_lock_irq(host->host_lock);
+-      }
+-      return retval;
+-}
+-
+-int aac_reset_adapter(struct aac_dev * aac, int forced)
+-{
+-      unsigned long flagv = 0;
+-      int retval;
+-      struct Scsi_Host * host;
+-
+-      if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0)
+-              return -EBUSY;
+-
+-      if (aac->in_reset) {
+-              spin_unlock_irqrestore(&aac->fib_lock, flagv);
+-              return -EBUSY;
+-      }
+-      aac->in_reset = 1;
+-      spin_unlock_irqrestore(&aac->fib_lock, flagv);
+-
 -      /*
--       * Contiguous insert - either left or right.
+-       * Wait for all commands to complete to this specific
+-       * target (block maximum 60 seconds). Although not necessary,
+-       * it does make us a good storage citizen.
 -       */
--      if (insert->ins_contig != CONTIG_NONE) {
--              rec = &el->l_recs[i];
--              if (insert->ins_contig == CONTIG_LEFT) {
--                      rec->e_blkno = insert_rec->e_blkno;
--                      rec->e_cpos = insert_rec->e_cpos;
+-      host = aac->scsi_host_ptr;
+-      scsi_block_requests(host);
+-      if (forced < 2) for (retval = 60; retval; --retval) {
+-              struct scsi_device * dev;
+-              struct scsi_cmnd * command;
+-              int active = 0;
+-
+-              __shost_for_each_device(dev, host) {
+-                      spin_lock_irqsave(&dev->list_lock, flagv);
+-                      list_for_each_entry(command, &dev->cmd_list, list) {
+-                              if (command->SCp.phase == AAC_OWNER_FIRMWARE) {
+-                                      active++;
+-                                      break;
+-                              }
+-                      }
+-                      spin_unlock_irqrestore(&dev->list_lock, flagv);
+-                      if (active)
+-                              break;
+-
+-              }
+-              /*
+-               * We can exit If all the commands are complete
+-               */
+-              if (active == 0)
+-                      break;
+-              ssleep(1);
+-      }
+-
+-      /* Quiesce build, flush cache, write through mode */
+-      aac_send_shutdown(aac);
+-      spin_lock_irqsave(host->host_lock, flagv);
+-      retval = _aac_reset_adapter(aac, forced);
+-      spin_unlock_irqrestore(host->host_lock, flagv);
+-
+-      if (retval == -ENODEV) {
+-              /* Unwind aac_send_shutdown() IOP_RESET unsupported/disabled */
+-              struct fib * fibctx = aac_fib_alloc(aac);
+-              if (fibctx) {
+-                      struct aac_pause *cmd;
+-                      int status;
+-
+-                      aac_fib_init(fibctx);
+-
+-                      cmd = (struct aac_pause *) fib_data(fibctx);
+-
+-                      cmd->command = cpu_to_le32(VM_ContainerConfig);
+-                      cmd->type = cpu_to_le32(CT_PAUSE_IO);
+-                      cmd->timeout = cpu_to_le32(1);
+-                      cmd->min = cpu_to_le32(1);
+-                      cmd->noRescan = cpu_to_le32(1);
+-                      cmd->count = cpu_to_le32(0);
+-
+-                      status = aac_fib_send(ContainerCommand,
+-                        fibctx,
+-                        sizeof(struct aac_pause),
+-                        FsaNormal,
+-                        -2 /* Timeout silently */, 1,
+-                        NULL, NULL);
+-
+-                      if (status >= 0)
+-                              aac_fib_complete(fibctx);
+-                      aac_fib_free(fibctx);
 -              }
--              le16_add_cpu(&rec->e_leaf_clusters,
--                           le16_to_cpu(insert_rec->e_leaf_clusters));
--              return;
 -      }
-+      el = &eb->h_list;
-+      BUG_ON(le16_to_cpu(el->l_next_free_rec) == 0);
-+      idx = le16_to_cpu(el->l_next_free_rec) - 1;
-+      rec = &el->l_recs[idx];
-+      range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+-
+       return retval;
+ }
  
--      /*
--       * Handle insert into an empty leaf.
--       */
--      if (le16_to_cpu(el->l_next_free_rec) == 0 ||
--          ((le16_to_cpu(el->l_next_free_rec) == 1) &&
--           ocfs2_is_empty_extent(&el->l_recs[0]))) {
--              el->l_recs[0] = *insert_rec;
--              el->l_next_free_rec = cpu_to_le16(1);
--              return;
--      }
-+      for (i = 0; i < path->p_tree_depth; i++) {
-+              el = path->p_node[i].el;
-+              idx = le16_to_cpu(el->l_next_free_rec) - 1;
-+              rec = &el->l_recs[idx];
+@@ -1370,14 +1270,9 @@
  
--      /*
--       * Appending insert.
--       */
--      if (insert->ins_appending == APPEND_TAIL) {
--              i = le16_to_cpu(el->l_next_free_rec) - 1;
--              rec = &el->l_recs[i];
--              range = le32_to_cpu(rec->e_cpos)
--                      + le16_to_cpu(rec->e_leaf_clusters);
--              BUG_ON(le32_to_cpu(insert_rec->e_cpos) < range);
-+              rec->e_int_clusters = cpu_to_le32(range);
-+              le32_add_cpu(&rec->e_int_clusters, -le32_to_cpu(rec->e_cpos));
+       printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED);
  
--              mlog_bug_on_msg(le16_to_cpu(el->l_next_free_rec) >=
--                              le16_to_cpu(el->l_count),
--                              "inode %lu, depth %u, count %u, next free %u, "
--                              "rec.cpos %u, rec.clusters %u, "
--                              "insert.cpos %u, insert.clusters %u\n",
--                              inode->i_ino,
--                              le16_to_cpu(el->l_tree_depth),
--                              le16_to_cpu(el->l_count),
--                              le16_to_cpu(el->l_next_free_rec),
--                              le32_to_cpu(el->l_recs[i].e_cpos),
--                              le16_to_cpu(el->l_recs[i].e_leaf_clusters),
--                              le32_to_cpu(insert_rec->e_cpos),
--                              le16_to_cpu(insert_rec->e_leaf_clusters));
--              i++;
--              el->l_recs[i] = *insert_rec;
--              le16_add_cpu(&el->l_next_free_rec, 1);
--              return;
-+              ocfs2_journal_dirty(handle, path->p_node[i].bh);
+-      if (!check_reset || (aac->supplement_adapter_info.SupportedOptions2 &
+-        le32_to_cpu(AAC_OPTION_IGNORE_RESET)))
+-              goto out;
+       host = aac->scsi_host_ptr;
+-      if (aac->thread->pid != current->pid)
+       spin_lock_irqsave(host->host_lock, flagv);
+-      BlinkLED = _aac_reset_adapter(aac, 0);
+-      if (aac->thread->pid != current->pid)
++      BlinkLED = _aac_reset_adapter(aac);
+       spin_unlock_irqrestore(host->host_lock, flagv);
+       return BlinkLED;
+@@ -1405,9 +1300,6 @@
+       struct aac_fib_context *fibctx;
+       unsigned long flags;
+       DECLARE_WAITQUEUE(wait, current);
+-      unsigned long next_jiffies = jiffies + HZ;
+-      unsigned long next_check_jiffies = next_jiffies;
+-      long difference = HZ;
+       /*
+        *      We can only have one thread per adapter for AIF's.
+@@ -1615,79 +1507,11 @@
+                *      There are no more AIF's
+                */
+               spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags);
+-
+-              /*
+-               *      Background activity
+-               */
+-              if ((time_before(next_check_jiffies,next_jiffies))
+-               && ((difference = next_check_jiffies - jiffies) <= 0)) {
+-                      next_check_jiffies = next_jiffies;
+-                      if (aac_check_health(dev) == 0) {
+-                              difference = ((long)(unsigned)check_interval)
+-                                         * HZ;
+-                              next_check_jiffies = jiffies + difference;
+-                      } else if (!dev->queues)
+-                      break;
+-              }
+-              if (!time_before(next_check_jiffies,next_jiffies)
+-               && ((difference = next_jiffies - jiffies) <= 0)) {
+-                      struct timeval now;
+-                      int ret;
+-
+-                      /* Don't even try to talk to adapter if its sick */
+-                      ret = aac_check_health(dev);
+-                      if (!ret && !dev->queues)
+-                              break;
+-                      next_check_jiffies = jiffies
+-                                         + ((long)(unsigned)check_interval)
+-                                         * HZ;
+-                      do_gettimeofday(&now);
+-
+-                      /* Synchronize our watches */
+-                      if (((1000000 - (1000000 / HZ)) > now.tv_usec)
+-                       && (now.tv_usec > (1000000 / HZ)))
+-                              difference = (((1000000 - now.tv_usec) * HZ)
+-                                + 500000) / 1000000;
+-                      else if (ret == 0) {
+-                              struct fib *fibptr;
+-
+-                              if ((fibptr = aac_fib_alloc(dev))) {
+-                                      u32 * info;
+-
+-                                      aac_fib_init(fibptr);
+-
+-                                      info = (u32 *) fib_data(fibptr);
+-                                      if (now.tv_usec > 500000)
+-                                              ++now.tv_sec;
+-
+-                                      *info = cpu_to_le32(now.tv_sec);
+-
+-                                      (void)aac_fib_send(SendHostTime,
+-                                              fibptr,
+-                                              sizeof(*info),
+-                                              FsaNormal,
+-                                              1, 1,
+-                                              NULL,
+-                                              NULL);
+-                                      aac_fib_complete(fibptr);
+-                                      aac_fib_free(fibptr);
+-                              }
+-                              difference = (long)(unsigned)update_interval*HZ;
+-                      } else {
+-                              /* retry shortly */
+-                              difference = 10 * HZ;
+-                      }
+-                      next_jiffies = jiffies + difference;
+-                      if (time_before(next_check_jiffies,next_jiffies))
+-                              difference = next_check_jiffies - jiffies;
+-              }
+-              if (difference <= 0)
+-                      difference = 1;
+-              set_current_state(TASK_INTERRUPTIBLE);
+-              schedule_timeout(difference);
++              schedule();
+               if (kthread_should_stop())
+                       break;
++              set_current_state(TASK_INTERRUPTIBLE);
        }
+       if (dev->queues)
+               remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait);
+diff -Nurb linux-2.6.22-590/drivers/scsi/aacraid/linit.c linux-2.6.22-570/drivers/scsi/aacraid/linit.c
+--- linux-2.6.22-590/drivers/scsi/aacraid/linit.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/aacraid/linit.c      2008-01-23 19:15:55.000000000 -0500
+@@ -39,8 +39,10 @@
+ #include <linux/pci.h>
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
++#include <linux/dma-mapping.h>
+ #include <linux/syscalls.h>
+ #include <linux/delay.h>
++#include <linux/smp_lock.h>
+ #include <linux/kthread.h>
+ #include <asm/semaphore.h>
+@@ -221,12 +223,12 @@
+       { aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
+       { aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
+       { aac_sa_init, "aacraid",  "ADAPTEC ", "AAC-364         ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
+-      { aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_34SG }, /* Dell PERC2/QC */
++      { aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell PERC2/QC */
+       { aac_sa_init, "hpnraid",  "HP      ", "NetRAID         ", 4, AAC_QUIRK_34SG }, /* HP NetRAID-4M */
+       { aac_rx_init, "aacraid",  "DELL    ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell Catchall */
+       { aac_rx_init, "aacraid",  "Legend  ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend Catchall */
+-      { aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Catch All */
++      { aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec Catch All */
+       { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Rocket Catch All */
+       { aac_nark_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec NEMER/ARK Catch All */
+ };
+@@ -401,6 +403,10 @@
+ static int aac_slave_configure(struct scsi_device *sdev)
+ {
++      if (sdev_channel(sdev) == CONTAINER_CHANNEL) {
++              sdev->skip_ms_page_8 = 1;
++              sdev->skip_ms_page_3f = 1;
++      }
+       if ((sdev->type == TYPE_DISK) &&
+                       (sdev_channel(sdev) != CONTAINER_CHANNEL)) {
+               if (expose_physicals == 0)
+@@ -444,43 +450,6 @@
+       return 0;
+ }
+-/**
+- *    aac_change_queue_depth          -       alter queue depths
+- *    @sdev:  SCSI device we are considering
+- *    @depth: desired queue depth
+- *
+- *    Alters queue depths for target device based on the host adapter's
+- *    total capacity and the queue depth supported by the target device.
+- */
 -
--      /*
--       * Ok, we have to rotate.
--       *
--       * At this point, it is safe to assume that inserting into an
--       * empty leaf and appending to a leaf have both been handled
--       * above.
--       *
--       * This leaf needs to have space, either by the empty 1st
--       * extent record, or by virtue of an l_next_rec < l_count.
--       */
--      ocfs2_rotate_leaf(el, insert_rec);
+-static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
+-{
+-      if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
+-          (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
+-              struct scsi_device * dev;
+-              struct Scsi_Host *host = sdev->host;
+-              unsigned num = 0;
+-
+-              __shost_for_each_device(dev, host) {
+-                      if (dev->tagged_supported && (dev->type == TYPE_DISK) &&
+-                          (sdev_channel(dev) == CONTAINER_CHANNEL))
+-                              ++num;
+-                      ++num;
+-              }
+-              if (num >= host->can_queue)
+-                      num = host->can_queue - 1;
+-              if (depth > (host->can_queue - num))
+-                      depth = host->can_queue - num;
+-              if (depth > 256)
+-                      depth = 256;
+-              else if (depth < 2)
+-                      depth = 2;
+-              scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth);
+-      } else
+-              scsi_adjust_queue_depth(sdev, 0, 1);
+-      return sdev->queue_depth;
 -}
 -
--static inline void ocfs2_update_dinode_clusters(struct inode *inode,
--                                              struct ocfs2_dinode *di,
--                                              u32 clusters)
--{
--      le32_add_cpu(&di->i_clusters, clusters);
--      spin_lock(&OCFS2_I(inode)->ip_lock);
--      OCFS2_I(inode)->ip_clusters = le32_to_cpu(di->i_clusters);
--      spin_unlock(&OCFS2_I(inode)->ip_lock);
+ static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg)
+ {
+       struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
+@@ -579,14 +548,6 @@
+               ssleep(1);
+       }
+       printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
+-      /*
+-       * This adapter needs a blind reset, only do so for Adapters that
+-       * support a register, instead of a commanded, reset.
+-       */
+-      if ((aac->supplement_adapter_info.SupportedOptions2 &
+-        le32_to_cpu(AAC_OPTION_MU_RESET|AAC_OPTION_IGNORE_RESET)) ==
+-        le32_to_cpu(AAC_OPTION_MU_RESET))
+-              aac_reset_adapter(aac, 2); /* Bypass wait for command quiesce */
+       return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */
  }
  
--static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
--                                  struct ocfs2_extent_rec *insert_rec,
-+static void ocfs2_unlink_subtree(struct inode *inode, handle_t *handle,
-+                               struct ocfs2_path *left_path,
-                                   struct ocfs2_path *right_path,
--                                  struct ocfs2_path **ret_left_path)
-+                               int subtree_index,
-+                               struct ocfs2_cached_dealloc_ctxt *dealloc)
+@@ -774,21 +735,15 @@
+       return len;
+ }
+-ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf)
++static ssize_t aac_show_serial_number(struct class_device *class_dev,
++              char *buf)
  {
--      int ret, i, next_free;
--      struct buffer_head *bh;
-+      int ret, i;
-+      struct buffer_head *root_bh = left_path->p_node[subtree_index].bh;
-+      struct ocfs2_extent_list *root_el = left_path->p_node[subtree_index].el;
-       struct ocfs2_extent_list *el;
--      struct ocfs2_path *left_path = NULL;
-+      struct ocfs2_extent_block *eb;
-+      struct buffer_head *bh;
+       struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+       int len = 0;
  
--      *ret_left_path = NULL;
-+      el = path_leaf_el(left_path);
+       if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
+-              len = snprintf(buf, PAGE_SIZE, "%06X\n",
++              len = snprintf(buf, PAGE_SIZE, "%x\n",
+                 le32_to_cpu(dev->adapter_info.serial[0]));
+-      if (len &&
+-        !memcmp(&dev->supplement_adapter_info.MfgPcbaSerialNo[
+-          sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo)+2-len],
+-        buf, len))
+-              len = snprintf(buf, PAGE_SIZE, "%.*s\n",
+-                (int)sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo),
+-                dev->supplement_adapter_info.MfgPcbaSerialNo);
+       return len;
+ }
  
--      /*
--       * This shouldn't happen for non-trees. The extent rec cluster
--       * count manipulation below only works for interior nodes.
--       */
--      BUG_ON(right_path->p_tree_depth == 0);
-+      eb = (struct ocfs2_extent_block *)right_path->p_node[subtree_index + 1].bh->b_data;
+@@ -804,31 +759,6 @@
+         class_to_shost(class_dev)->max_id);
+ }
  
--      /*
--       * If our appending insert is at the leftmost edge of a leaf,
--       * then we might need to update the rightmost records of the
--       * neighboring path.
--       */
--      el = path_leaf_el(right_path);
--      next_free = le16_to_cpu(el->l_next_free_rec);
-+      for(i = 1; i < le16_to_cpu(root_el->l_next_free_rec); i++)
-+              if (root_el->l_recs[i].e_blkno == eb->h_blkno)
-+                      break;
-+
-+      BUG_ON(i >= le16_to_cpu(root_el->l_next_free_rec));
-+
-+      memset(&root_el->l_recs[i], 0, sizeof(struct ocfs2_extent_rec));
-+      le16_add_cpu(&root_el->l_next_free_rec, -1);
-+
-+      eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
-+      eb->h_next_leaf_blk = 0;
-+
-+      ocfs2_journal_dirty(handle, root_bh);
-+      ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
-+
-+      for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
-+              bh = right_path->p_node[i].bh;
-+
-+              eb = (struct ocfs2_extent_block *)bh->b_data;
-+              /*
-+               * Not all nodes might have had their final count
-+               * decremented by the caller - handle this here.
-+               */
-+              el = &eb->h_list;
-+              if (le16_to_cpu(el->l_next_free_rec) > 1) {
-+                      mlog(ML_ERROR,
-+                           "Inode %llu, attempted to remove extent block "
-+                           "%llu with %u records\n",
-+                           (unsigned long long)OCFS2_I(inode)->ip_blkno,
-+                           (unsigned long long)le64_to_cpu(eb->h_blkno),
-+                           le16_to_cpu(el->l_next_free_rec));
-+
-+                      ocfs2_journal_dirty(handle, bh);
-+                      ocfs2_remove_from_cache(inode, bh);
-+                      continue;
-+              }
-+
-+              el->l_next_free_rec = 0;
-+              memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
-+
-+              ocfs2_journal_dirty(handle, bh);
-+
-+              ret = ocfs2_cache_extent_block_free(dealloc, eb);
-+              if (ret)
-+                      mlog_errno(ret);
-+
-+              ocfs2_remove_from_cache(inode, bh);
-+      }
-+}
-+
-+static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
-+                                   struct ocfs2_path *left_path,
-+                                   struct ocfs2_path *right_path,
-+                                   int subtree_index,
-+                                   struct ocfs2_cached_dealloc_ctxt *dealloc,
-+                                   int *deleted)
-+{
-+      int ret, i, del_right_subtree = 0;
-+      struct buffer_head *root_bh, *di_bh = path_root_bh(right_path);
-+      struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
-+      struct ocfs2_extent_list *right_leaf_el, *left_leaf_el;
-+      struct ocfs2_extent_block *eb;
-+
-+      *deleted = 0;
-+
-+      right_leaf_el = path_leaf_el(right_path);
-+      left_leaf_el = path_leaf_el(left_path);
-+      root_bh = left_path->p_node[subtree_index].bh;
-+      BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
-+
-+      if (!ocfs2_is_empty_extent(&left_leaf_el->l_recs[0]))
-+              return 0;
-+
-+      if (ocfs2_is_empty_extent(&right_leaf_el->l_recs[0]))
-+              return -EAGAIN;
-+
-+      eb = (struct ocfs2_extent_block *)path_leaf_bh(right_path)->b_data;
-+      if (eb->h_next_leaf_blk == 0ULL &&
-+          le16_to_cpu(right_leaf_el->l_next_free_rec) == 1) {
-+              /*
-+               * We have to update i_last_eb_blk during the meta
-+               * data delete.
-+               */
-+              ret = ocfs2_journal_access(handle, inode, di_bh,
-+                                         OCFS2_JOURNAL_ACCESS_WRITE);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
-+
-+              del_right_subtree = 1;
-+      }
-+
-+      ret = ocfs2_journal_access(handle, inode, root_bh,
-+                                 OCFS2_JOURNAL_ACCESS_WRITE);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out;
-+      }
-+
-+      for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
-+              ret = ocfs2_journal_access(handle, inode,
-+                                         right_path->p_node[i].bh,
-+                                         OCFS2_JOURNAL_ACCESS_WRITE);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
-+
-+              ret = ocfs2_journal_access(handle, inode,
-+                                         left_path->p_node[i].bh,
-+                                         OCFS2_JOURNAL_ACCESS_WRITE);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
-+      }
-+
-+      ocfs2_rotate_leaf(left_leaf_el, &right_leaf_el->l_recs[0]);
-+      memset(&right_leaf_el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
-+      if (eb->h_next_leaf_blk == 0ULL) {
-+              /*
-+               * XXX: move recs over to get rid of empty extent,
-+               * decrease next_free. how does this play with the
-+               * delete code below?
-+               */
-+              ocfs2_remove_empty_extent(right_leaf_el);
-+      }
-+
-+      ret = ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
-+      if (ret)
-+              mlog_errno(ret);
-+      ret = ocfs2_journal_dirty(handle, path_leaf_bh(right_path));
-+      if (ret)
-+              mlog_errno(ret);
-+
-+      if (del_right_subtree) {
-+              ocfs2_unlink_subtree(inode, handle, left_path, right_path,
-+                                   subtree_index, dealloc);
-+              ocfs2_update_edge_lengths(inode, handle, left_path);
-+
-+              eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
-+              di->i_last_eb_blk = eb->h_blkno;
-+              ret = ocfs2_journal_dirty(handle, di_bh);
-+              if (ret)
-+                      mlog_errno(ret);
-+
-+              *deleted = 1;
-+      } else
-+              ocfs2_complete_edge_insert(inode, handle, left_path, right_path,
-+                                         subtree_index);
-+
-+out:
-+      return ret;
-+}
+-static ssize_t aac_store_reset_adapter(struct class_device *class_dev,
+-              const char *buf, size_t count)
+-{
+-      int retval = -EACCES;
+-
+-      if (!capable(CAP_SYS_ADMIN))
+-              return retval;
+-      retval = aac_reset_adapter((struct aac_dev*)class_to_shost(class_dev)->hostdata, buf[0] == '!');
+-      if (retval >= 0)
+-              retval = count;
+-      return retval;
+-}
+-
+-static ssize_t aac_show_reset_adapter(struct class_device *class_dev,
+-              char *buf)
+-{
+-      struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+-      int len, tmp;
+-
+-      tmp = aac_adapter_check_health(dev);
+-      if ((tmp == 0) && dev->in_reset)
+-              tmp = -EBUSY;
+-      len = snprintf(buf, PAGE_SIZE, "0x%x", tmp);
+-      return len;
+-}
+ static struct class_device_attribute aac_model = {
+       .attr = {
+@@ -886,14 +816,6 @@
+       },
+       .show = aac_show_max_id,
+ };
+-static struct class_device_attribute aac_reset = {
+-      .attr = {
+-              .name = "reset_host",
+-              .mode = S_IWUSR|S_IRUGO,
+-      },
+-      .store = aac_store_reset_adapter,
+-      .show = aac_show_reset_adapter,
+-};
+ static struct class_device_attribute *aac_attrs[] = {
+       &aac_model,
+@@ -904,7 +826,6 @@
+       &aac_serial_number,
+       &aac_max_channel,
+       &aac_max_id,
+-      &aac_reset,
+       NULL
+ };
+@@ -931,7 +852,6 @@
+       .bios_param                     = aac_biosparm, 
+       .shost_attrs                    = aac_attrs,
+       .slave_configure                = aac_slave_configure,
+-      .change_queue_depth             = aac_change_queue_depth,
+       .eh_abort_handler               = aac_eh_abort,
+       .eh_host_reset_handler          = aac_eh_reset,
+       .can_queue                      = AAC_NUM_IO_FIB,       
+@@ -1170,7 +1090,7 @@
+ {
+       int error;
+       
+-      printk(KERN_INFO "Adaptec %s driver %s\n",
++      printk(KERN_INFO "Adaptec %s driver (%s)\n",
+         AAC_DRIVERNAME, aac_driver_version);
+       error = pci_register_driver(&aac_pci_driver);
+diff -Nurb linux-2.6.22-590/drivers/scsi/aacraid/rx.c linux-2.6.22-570/drivers/scsi/aacraid/rx.c
+--- linux-2.6.22-590/drivers/scsi/aacraid/rx.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/aacraid/rx.c 2007-07-08 19:32:17.000000000 -0400
+@@ -464,8 +464,6 @@
+ {
+       u32 var;
+-      if (!(dev->supplement_adapter_info.SupportedOptions2 &
+-        le32_to_cpu(AAC_OPTION_MU_RESET)) || (bled >= 0) || (bled == -2)) {
+       if (bled)
+               printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
+                       dev->name, dev->id, bled);
+@@ -481,7 +479,6 @@
+       if (bled && (bled != -ETIMEDOUT))
+               return -EINVAL;
+-      }
+       if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */
+               rx_writel(dev, MUnit.reserved2, 3);
+               msleep(5000); /* Delay 5 seconds */
+@@ -599,7 +596,7 @@
+               }
+               msleep(1);
+       }
+-      if (restart && aac_commit)
++      if (restart)
+               aac_commit = 1;
+       /*
+        *      Fill in the common function dispatch table.
+diff -Nurb linux-2.6.22-590/drivers/scsi/advansys.c linux-2.6.22-570/drivers/scsi/advansys.c
+--- linux-2.6.22-590/drivers/scsi/advansys.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/advansys.c   2007-07-08 19:32:17.000000000 -0400
+@@ -798,6 +798,7 @@
+ #include <scsi/scsi_tcq.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_host.h>
++#include "advansys.h"
+ #ifdef CONFIG_PCI
+ #include <linux/pci.h>
+ #endif /* CONFIG_PCI */
+@@ -2013,7 +2014,7 @@
+ STATIC void      AscEnableIsaDma(uchar);
+ #endif /* CONFIG_ISA */
+ STATIC ASC_DCNT  AscGetMaxDmaCount(ushort);
+-static const char *advansys_info(struct Scsi_Host *shp);
 +
+ /*
+  * --- Adv Library Constants and Macros
+@@ -3969,6 +3970,10 @@
+     ASC_IS_PCI,
+ };
 +/*
-+ * Given a full path, determine what cpos value would return us a path
-+ * containing the leaf immediately to the right of the current one.
-+ *
-+ * Will return zero if the path passed in is already the rightmost path.
-+ *
-+ * This looks similar, but is subtly different to
-+ * ocfs2_find_cpos_for_left_leaf().
++ * Used with the LILO 'advansys' option to eliminate or
++ * limit I/O port probing at boot time, cf. advansys_setup().
 + */
-+static int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
-+                                        struct ocfs2_path *path, u32 *cpos)
-+{
-+      int i, j, ret = 0;
-+      u64 blkno;
-+      struct ocfs2_extent_list *el;
-+
-+      *cpos = 0;
-+
-+      if (path->p_tree_depth == 0)
-+              return 0;
-+
-+      blkno = path_leaf_bh(path)->b_blocknr;
-+
-+      /* Start at the tree node just above the leaf and work our way up. */
-+      i = path->p_tree_depth - 1;
-+      while (i >= 0) {
-+              int next_free;
-+
-+              el = path->p_node[i].el;
-+
-+              /*
-+               * Find the extent record just after the one in our
-+               * path.
-+               */
-+              next_free = le16_to_cpu(el->l_next_free_rec);
-+              for(j = 0; j < le16_to_cpu(el->l_next_free_rec); j++) {
-+                      if (le64_to_cpu(el->l_recs[j].e_blkno) == blkno) {
-+                              if (j == (next_free - 1)) {
-+                                      if (i == 0) {
-+                                              /*
-+                                               * We've determined that the
-+                                               * path specified is already
-+                                               * the rightmost one - return a
-+                                               * cpos of zero.
-+                                               */
-+                                              goto out;
-+                                      }
-+                                      /*
-+                                       * The rightmost record points to our
-+                                       * leaf - we need to travel up the
-+                                       * tree one level.
-+                                       */
-+                                      goto next_node;
-+                              }
-+
-+                              *cpos = le32_to_cpu(el->l_recs[j + 1].e_cpos);
-+                              goto out;
-+                      }
-+              }
-+
-+              /*
-+               * If we got here, we never found a valid node where
-+               * the tree indicated one should be.
-+               */
-+              ocfs2_error(sb,
-+                          "Invalid extent tree at extent block %llu\n",
-+                          (unsigned long long)blkno);
-+              ret = -EROFS;
-+              goto out;
-+
-+next_node:
-+              blkno = path->p_node[i].bh->b_blocknr;
-+              i--;
-+      }
-+
-+out:
-+      return ret;
-+}
-+
-+static int ocfs2_rotate_rightmost_leaf_left(struct inode *inode,
-+                                          handle_t *handle,
-+                                          struct buffer_head *bh,
-+                                          struct ocfs2_extent_list *el,
-+                                          int *rotated_any)
-+{
-+      int ret;
-+
-+      if (rotated_any)
-+              *rotated_any = 0;
-+
-+      if (!ocfs2_is_empty_extent(&el->l_recs[0]))
-+              return 0;
-+
-+      if (le16_to_cpu(el->l_next_free_rec) == 1)
-+              return -EAGAIN;
-+
-+      ret = ocfs2_journal_access(handle, inode, bh,
-+                                 OCFS2_JOURNAL_ACCESS_WRITE);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out;
-+      }
-+
-+      ocfs2_remove_empty_extent(el);
-+
-+      ret = ocfs2_journal_dirty(handle, bh);
-+      if (ret)
-+              mlog_errno(ret);
-+
-+      if (rotated_any)
-+              *rotated_any = 1;
-+out:
-+      return ret;
-+}
-+
+ STATIC int asc_iopflag = ASC_FALSE;
+ STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 };
+@@ -4050,6 +4055,10 @@
+ #endif /* ADVANSYS_DEBUG */
 +/*
-+ * Left rotation of btree records.
-+ *
-+ * In many ways, this is (unsurprisingly) the opposite of right
-+ * rotation. We start at some non-rightmost path containing an empty
-+ * extent in the leaf block. The code works its way to the rightmost
-+ * path by rotating records to the left in every subtree.
-+ *
-+ * There are a few places where we might want to do this:
-+ *   - merging extent records
-+ *     - rightleft contiguousness during insert
-+ *     - merging two previously unwritten extents
-+ *   - truncate
-+ *     - via ocfs2_truncate, if we ever fix it up to use this code
-+ *     - via ioctl at the request of user (reverse fallocate)
-+ *   - "compressing" a tree with empty extents
-+ *     - as a result of a user defrag request
-+ *     - perhaps as a preventative measure if we notice a tree needs
-+ *       this during any of the above operations.
-+ *
-+ * The major difference between those states above are the ability to
-+ * lock one of the meta data allocators so that we can remove unused
-+ * extent blocks. It might be unrealistic for us to assume that any
-+ * merging cases will want to lock the meta data allocator. Luckily,
-+ * the merges are an optimization.
-+ *
-+ * So, merging won't happen if it would result in an empty rightmost
-+ * path (this is illegal).
-+ *
-+ * This function will move extents left until it runs out of leaves to
-+ * rotate, or it hits a right leaf that already contains an empty
-+ * extent, in which case it will exit early. This means that we might
-+ * never rotate anything if the 1st right leaf contains an empty
-+ * extent.
-+ *
-+ * Truncate cases will have to happen as a second step. I'm not
-+ * completely sure how we want to handle those yet.
++ * --- Linux 'struct scsi_host_template' and advansys_setup() Functions
 + */
-+static int ocfs2_rotate_tree_left(struct inode *inode,
-+                                handle_t *handle,
-+                                struct ocfs2_path *path,
-+                                struct ocfs2_cached_dealloc_ctxt *dealloc,
-+                                int *rotated_any)
-+{
-+      int ret, subtree_root, deleted, orig_credits = handle->h_buffer_credits;
-+      u32 right_cpos;
-+      struct ocfs2_path *left_path = NULL;
-+      struct ocfs2_path *right_path = NULL;
-+
-+      BUG_ON(!ocfs2_is_empty_extent(&(path_leaf_el(path)->l_recs[0])));
-+
-+      if (rotated_any)
-+              *rotated_any = 0;
-+
-+      ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, path,
-+                                           &right_cpos);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out;
-+      }
-+
-+      if (path->p_tree_depth == 0 || right_cpos == 0) {
-+              /*
-+               * Two cases where rotation of adjacent leaves isn't
-+               * necessary:
-+               *  - in-inode extents (no btree)
-+               *  - path passed is already rightmost
-+               */
-+              ret = ocfs2_rotate_rightmost_leaf_left(inode, handle,
-+                                                     path_leaf_bh(path),
-+                                                     path_leaf_el(path),
-+                                                     rotated_any);
-+              if (ret)
-+                      mlog_errno(ret);
-+              goto out;
-+      }
-+
-+      left_path = ocfs2_new_path(path_root_bh(path),
-+                                 path_root_el(path));
-+      if (!left_path) {
-+              ret = -ENOMEM;
-+              mlog_errno(ret);
-+              goto out;
-+      }
-+
-+      ocfs2_cp_path(left_path, path);
-+
-+      right_path = ocfs2_new_path(path_root_bh(path),
-+                                  path_root_el(path));
-+      if (!right_path) {
-+              ret = -ENOMEM;
-+              mlog_errno(ret);
-+              goto out;
-+      }
-+
-+      while (right_cpos) {
-+              ret = ocfs2_find_path(inode, right_path, right_cpos);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
-+
-+              subtree_root = ocfs2_find_subtree_root(inode, left_path,
-+                                                     right_path);
-+
-+              mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n",
-+                   subtree_root,
-+                   (unsigned long long)
-+                   right_path->p_node[subtree_root].bh->b_blocknr,
-+                   right_path->p_tree_depth);
-+
-+              ret = ocfs2_extend_rotate_transaction(handle, subtree_root,
-+                                                    orig_credits, left_path);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
-+
-+              ret = ocfs2_rotate_subtree_left(inode, handle, left_path,
-+                                              right_path, subtree_root,
-+                                              dealloc, &deleted);
-+              if (ret) {
-+                      if (ret != -EAGAIN)
-+                              mlog_errno(ret);
-+                      goto out;
-+              }
-+
-+              if (rotated_any)
-+                      *rotated_any = 1;
-+
-+              /*
-+               * The subtree rotate might have removed records on
-+               * the rightmost edge. If so, then rotation is
-+               * complete.
-+               */
-+              if (deleted)
-+                      break;
-+
-+              ocfs2_mv_path(left_path, right_path);
 +
-+              ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, left_path,
-+                                                   &right_cpos);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
-+      }
+ #ifdef CONFIG_PROC_FS
+ /*
+  * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
+@@ -4071,7 +4080,7 @@
+  * if 'prtbuf' is too small it will not be overwritten. Instead the
+  * user just won't get all the available statistics.
+  */
+-static int
++int
+ advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
+               off_t offset, int length, int inout)
+ {
+@@ -4287,7 +4296,7 @@
+  * it must not call SCSI mid-level functions including scsi_malloc()
+  * and scsi_free().
+  */
+-static int __init
++int __init
+ advansys_detect(struct scsi_host_template *tpnt)
+ {
+     static int          detect_called = ASC_FALSE;
+@@ -5419,7 +5428,7 @@
+  *
+  * Release resources allocated for a single AdvanSys adapter.
+  */
+-static int
++int
+ advansys_release(struct Scsi_Host *shp)
+ {
+     asc_board_t    *boardp;
+@@ -5466,7 +5475,7 @@
+  * Note: The information line should not exceed ASC_INFO_SIZE bytes,
+  * otherwise the static 'info' array will be overrun.
+  */
+-static const char *
++const char *
+ advansys_info(struct Scsi_Host *shp)
+ {
+     static char     info[ASC_INFO_SIZE];
+@@ -5559,7 +5568,7 @@
+  * This function always returns 0. Command return status is saved
+  * in the 'scp' result field.
+  */
+-static int
++int
+ advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
+ {
+     struct Scsi_Host    *shp;
+@@ -5647,7 +5656,7 @@
+  * sleeping is allowed and no locking other than for host structures is
+  * required. Returns SUCCESS or FAILED.
+  */
+-static int
++int
+ advansys_reset(struct scsi_cmnd *scp)
+ {
+     struct Scsi_Host     *shp;
+@@ -5832,7 +5841,7 @@
+  * ip[1]: sectors
+  * ip[2]: cylinders
+  */
+-static int
++int
+ advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+               sector_t capacity, int ip[])
+ {
+@@ -5866,6 +5875,82 @@
+ }
+ /*
++ * advansys_setup()
++ *
++ * This function is called from init/main.c at boot time.
++ * It it passed LILO parameters that can be set from the
++ * LILO command line or in /etc/lilo.conf.
++ *
++ * It is used by the AdvanSys driver to either disable I/O
++ * port scanning or to limit scanning to 1 - 4 I/O ports.
++ * Regardless of the option setting EISA and PCI boards
++ * will still be searched for and detected. This option
++ * only affects searching for ISA and VL boards.
++ *
++ * If ADVANSYS_DEBUG is defined the driver debug level may
++ * be set using the 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port.
++ *
++ * Examples:
++ * 1. Eliminate I/O port scanning:
++ *         boot: linux advansys=
++ *       or
++ *         boot: linux advansys=0x0
++ * 2. Limit I/O port scanning to one I/O port:
++ *        boot: linux advansys=0x110
++ * 3. Limit I/O port scanning to four I/O ports:
++ *        boot: linux advansys=0x110,0x210,0x230,0x330
++ * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
++ *    set the driver debug level to 2.
++ *        boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
++ *
++ * ints[0] - number of arguments
++ * ints[1] - first argument
++ * ints[2] - second argument
++ * ...
++ */
++void __init
++advansys_setup(char *str, int *ints)
++{
++    int    i;
++
++    if (asc_iopflag == ASC_TRUE) {
++        printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
++        return;
++    }
++
++    asc_iopflag = ASC_TRUE;
++
++    if (ints[0] > ASC_NUM_IOPORT_PROBE) {
++#ifdef ADVANSYS_DEBUG
++        if ((ints[0] == ASC_NUM_IOPORT_PROBE + 1) &&
++            (ints[ASC_NUM_IOPORT_PROBE + 1] >> 4 == 0xdeb)) {
++            asc_dbglvl = ints[ASC_NUM_IOPORT_PROBE + 1] & 0xf;
++        } else {
++#endif /* ADVANSYS_DEBUG */
++            printk("AdvanSys SCSI: only %d I/O ports accepted\n",
++                ASC_NUM_IOPORT_PROBE);
++#ifdef ADVANSYS_DEBUG
++        }
++#endif /* ADVANSYS_DEBUG */
++    }
 +
-+out:
-+      ocfs2_free_path(right_path);
-+      ocfs2_free_path(left_path);
++#ifdef ADVANSYS_DEBUG
++    ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
++    for (i = 1; i < ints[0]; i++) {
++        ASC_DBG2(1, " ints[%d] 0x%x", i, ints[i]);
++    }
++    ASC_DBG(1, "\n");
++#endif /* ADVANSYS_DEBUG */
 +
-+      return ret;
++    for (i = 1; i <= ints[0] && i <= ASC_NUM_IOPORT_PROBE; i++) {
++        asc_ioport[i-1] = ints[i];
++        ASC_DBG2(1, "advansys_setup: asc_ioport[%d] 0x%x\n",
++            i - 1, asc_ioport[i-1]);
++    }
 +}
 +
-+static void ocfs2_cleanup_merge(struct ocfs2_extent_list *el,
-+                              int index)
-+{
-+      struct ocfs2_extent_rec *rec = &el->l_recs[index];
-+      unsigned int size;
-+
-+      if (rec->e_leaf_clusters == 0) {
-+              /*
-+               * We consumed all of the merged-from record. An empty
-+               * extent cannot exist anywhere but the 1st array
-+               * position, so move things over if the merged-from
-+               * record doesn't occupy that position.
-+               *
-+               * This creates a new empty extent so the caller
-+               * should be smart enough to have removed any existing
-+               * ones.
-+               */
-+              if (index > 0) {
-+                      BUG_ON(ocfs2_is_empty_extent(&el->l_recs[0]));
-+                      size = index * sizeof(struct ocfs2_extent_rec);
-+                      memmove(&el->l_recs[1], &el->l_recs[0], size);
-+              }
-+
-+              /*
-+               * Always memset - the caller doesn't check whether it
-+               * created an empty extent, so there could be junk in
-+               * the other fields.
-+               */
-+              memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
-+      }
-+}
 +
 +/*
-+ * Remove split_rec clusters from the record at index and merge them
-+ * onto the beginning of the record at index + 1.
-+ */
-+static int ocfs2_merge_rec_right(struct inode *inode, struct buffer_head *bh,
-+                              handle_t *handle,
-+                              struct ocfs2_extent_rec *split_rec,
-+                              struct ocfs2_extent_list *el, int index)
-+{
-+      int ret;
-+      unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
-+      struct ocfs2_extent_rec *left_rec;
-+      struct ocfs2_extent_rec *right_rec;
-+
-+      BUG_ON(index >= le16_to_cpu(el->l_next_free_rec));
-+
-+      left_rec = &el->l_recs[index];
-+      right_rec = &el->l_recs[index + 1];
-+
-+      ret = ocfs2_journal_access(handle, inode, bh,
-+                                 OCFS2_JOURNAL_ACCESS_WRITE);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out;
-+      }
-+
-+      le16_add_cpu(&left_rec->e_leaf_clusters, -split_clusters);
-+
-+      le32_add_cpu(&right_rec->e_cpos, -split_clusters);
-+      le64_add_cpu(&right_rec->e_blkno,
-+                   -ocfs2_clusters_to_blocks(inode->i_sb, split_clusters));
-+      le16_add_cpu(&right_rec->e_leaf_clusters, split_clusters);
-+
-+      ocfs2_cleanup_merge(el, index);
-+
-+      ret = ocfs2_journal_dirty(handle, bh);
-+      if (ret)
-+              mlog_errno(ret);
-+
-+out:
-+      return ret;
-+}
-+
+  * --- Loadable Driver Support
+  */
+diff -Nurb linux-2.6.22-590/drivers/scsi/advansys.h linux-2.6.22-570/drivers/scsi/advansys.h
+--- linux-2.6.22-590/drivers/scsi/advansys.h   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/advansys.h   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,36 @@
 +/*
-+ * Remove split_rec clusters from the record at index and merge them
-+ * onto the tail of the record at index - 1.
++ * advansys.h - Linux Host Driver for AdvanSys SCSI Adapters
++ * 
++ * Copyright (c) 1995-2000 Advanced System Products, Inc.
++ * Copyright (c) 2000-2001 ConnectCom Solutions, Inc.
++ * All Rights Reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that redistributions of source
++ * code retain the above copyright notice and this comment without
++ * modification.
++ *
++ * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
++ * changed its name to ConnectCom Solutions, Inc.
++ *
 + */
-+static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh,
-+                              handle_t *handle,
-+                              struct ocfs2_extent_rec *split_rec,
-+                              struct ocfs2_extent_list *el, int index)
-+{
-+      int ret, has_empty_extent = 0;
-+      unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
-+      struct ocfs2_extent_rec *left_rec;
-+      struct ocfs2_extent_rec *right_rec;
-+
-+      BUG_ON(index <= 0);
-+
-+      left_rec = &el->l_recs[index - 1];
-+      right_rec = &el->l_recs[index];
-+      if (ocfs2_is_empty_extent(&el->l_recs[0]))
-+              has_empty_extent = 1;
-+
-+      ret = ocfs2_journal_access(handle, inode, bh,
-+                                 OCFS2_JOURNAL_ACCESS_WRITE);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out;
-+      }
-+
-+      if (has_empty_extent && index == 1) {
-+              /*
-+               * The easy case - we can just plop the record right in.
-+               */
-+              *left_rec = *split_rec;
-+
-+              has_empty_extent = 0;
-+      } else {
-+              le16_add_cpu(&left_rec->e_leaf_clusters, split_clusters);
-+      }
-+
-+      le32_add_cpu(&right_rec->e_cpos, split_clusters);
-+      le64_add_cpu(&right_rec->e_blkno,
-+                   ocfs2_clusters_to_blocks(inode->i_sb, split_clusters));
-+      le16_add_cpu(&right_rec->e_leaf_clusters, -split_clusters);
-+
-+      ocfs2_cleanup_merge(el, index);
-+
-+      ret = ocfs2_journal_dirty(handle, bh);
-+      if (ret)
-+              mlog_errno(ret);
-+
-+out:
-+      return ret;
-+}
-+
-+static int ocfs2_try_to_merge_extent(struct inode *inode,
-+                                   handle_t *handle,
-+                                   struct ocfs2_path *left_path,
-+                                   int split_index,
-+                                   struct ocfs2_extent_rec *split_rec,
-+                                   struct ocfs2_cached_dealloc_ctxt *dealloc,
-+                                   struct ocfs2_merge_ctxt *ctxt)
-+
-+{
-+      int ret = 0, rotated, delete_tail_recs = 0;
-+      struct ocfs2_extent_list *el = path_leaf_el(left_path);
-+      struct ocfs2_extent_rec *rec = &el->l_recs[split_index];
-+
-+      BUG_ON(ctxt->c_contig_type == CONTIG_NONE);
-+
-+      if (ctxt->c_split_covers_rec) {
-+              delete_tail_recs++;
-+
-+              if (ctxt->c_contig_type == CONTIG_LEFTRIGHT ||
-+                  ctxt->c_has_empty_extent)
-+                      delete_tail_recs++;
-+
-+              if (ctxt->c_has_empty_extent) {
-+                      /*
-+                       * The merge code will need to create an empty
-+                       * extent to take the place of the newly
-+                       * emptied slot. Remove any pre-existing empty
-+                       * extents - having more than one in a leaf is
-+                       * illegal.
-+                       */
-+                      ret = ocfs2_rotate_tree_left(inode, handle, left_path,
-+                                                   dealloc, &rotated);
-+                      if (rotated) {
-+                              split_index--;
-+                              rec = &el->l_recs[split_index];
-+                      }
-+                      if (ret) {
-+                              if (ret == -EAGAIN) {
-+                                      ret = 0;
-+                                      goto straight_insert;
-+                              }
-+
-+                              mlog_errno(ret);
-+                              goto out;
-+                      }
-+              }
-+      }
 +
-+      if (ctxt->c_contig_type == CONTIG_LEFTRIGHT) {
-+              /*
-+               * Left-right contig implies this.
-+               */
-+              BUG_ON(!ctxt->c_split_covers_rec);
-+              BUG_ON(split_index == 0);
-+
-+              /*
-+               * Since the leftright insert always covers the entire
-+               * extent, this call will delete the insert record
-+               * entirely, resulting in an empty extent record added to
-+               * the extent block.
-+               *
-+               * Since the adding of an empty extent shifts
-+               * everything back to the right, there's no need to
-+               * update split_index here.
-+               */
-+              ret = ocfs2_merge_rec_left(inode, path_leaf_bh(left_path),
-+                                         handle, split_rec, el, split_index);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
-+
-+              /*
-+               * We can only get this from logic error above.
-+               */
-+              BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
-+
-+              /*
-+               * The left merge left us with an empty extent, remove
-+               * it.
-+               */
-+              ret = ocfs2_rotate_tree_left(inode, handle, left_path,
-+                                           dealloc, &rotated);
-+              if (rotated) {
-+                      split_index--;
-+                      rec = &el->l_recs[split_index];
-+              }
-+              if (ret) {
-+                      if (ret == -EAGAIN) {
-+                              ret = 0;
-+                              goto straight_insert;
-+                      }
-+
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
-+
-+              /*
-+               * Note that we don't pass split_rec here on purpose -
-+               * we've merged it into the left side.
-+               */
-+              ret = ocfs2_merge_rec_right(inode, path_leaf_bh(left_path),
-+                                          handle, rec, el, split_index);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
-+
-+              BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
-+
-+              ret = ocfs2_rotate_tree_left(inode, handle, left_path,
-+                                           dealloc, NULL);
-+              /*
-+               * Error from this last rotate is not critical, so
-+               * print but don't bubble it up.
-+               */
-+              if (ret && ret != -EAGAIN)
-+                      mlog_errno(ret);
-+              ret = 0;
-+      } else {
-+              /*
-+               * Merge a record to the left or right.
-+               *
-+               * 'contig_type' is relative to the existing record,
-+               * so for example, if we're "right contig", it's to
-+               * the record on the left (hence the left merge).
-+               */
-+              if (ctxt->c_contig_type == CONTIG_RIGHT) {
-+                      ret = ocfs2_merge_rec_left(inode,
-+                                                 path_leaf_bh(left_path),
-+                                                 handle, split_rec, el,
-+                                                 split_index);
-+                      if (ret) {
-+                              mlog_errno(ret);
-+                              goto out;
-+                      }
-+              } else {
-+                      ret = ocfs2_merge_rec_right(inode,
-+                                                  path_leaf_bh(left_path),
-+                                                  handle, split_rec, el,
-+                                                  split_index);
-+                      if (ret) {
-+                              mlog_errno(ret);
-+                              goto out;
-+                      }
-+              }
-+
-+              if (ctxt->c_split_covers_rec) {
-+                      /*
-+                       * The merge may have left an empty extent in
-+                       * our leaf. Try to rotate it away.
-+                       */
-+                      ret = ocfs2_rotate_tree_left(inode, handle, left_path,
-+                                                   dealloc, &rotated);
-+                      if (ret)
-+                              mlog_errno(ret);
-+                      ret = 0;
-+              }
-+      }
-+
-+out:
-+      return ret;
-+
-+straight_insert:
-+      el->l_recs[split_index] = *split_rec;
-+      goto out;
-+}
-+
-+static void ocfs2_subtract_from_rec(struct super_block *sb,
-+                                  enum ocfs2_split_type split,
-+                                  struct ocfs2_extent_rec *rec,
-+                                  struct ocfs2_extent_rec *split_rec)
-+{
-+      u64 len_blocks;
-+
-+      len_blocks = ocfs2_clusters_to_blocks(sb,
-+                              le16_to_cpu(split_rec->e_leaf_clusters));
-+
-+      if (split == SPLIT_LEFT) {
-+              /*
-+               * Region is on the left edge of the existing
-+               * record.
-+               */
-+              le32_add_cpu(&rec->e_cpos,
-+                           le16_to_cpu(split_rec->e_leaf_clusters));
-+              le64_add_cpu(&rec->e_blkno, len_blocks);
-+              le16_add_cpu(&rec->e_leaf_clusters,
-+                           -le16_to_cpu(split_rec->e_leaf_clusters));
-+      } else {
-+              /*
-+               * Region is on the right edge of the existing
-+               * record.
-+               */
-+              le16_add_cpu(&rec->e_leaf_clusters,
-+                           -le16_to_cpu(split_rec->e_leaf_clusters));
-+      }
-+}
++#ifndef _ADVANSYS_H
++#define _ADVANSYS_H
 +
 +/*
-+ * Do the final bits of extent record insertion at the target leaf
-+ * list. If this leaf is part of an allocation tree, it is assumed
-+ * that the tree above has been prepared.
-+ */
-+static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
-+                               struct ocfs2_extent_list *el,
-+                               struct ocfs2_insert_type *insert,
-+                               struct inode *inode)
-+{
-+      int i = insert->ins_contig_index;
-+      unsigned int range;
-+      struct ocfs2_extent_rec *rec;
-+
-+      BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
-+
-+      if (insert->ins_split != SPLIT_NONE) {
-+              i = ocfs2_search_extent_list(el, le32_to_cpu(insert_rec->e_cpos));
-+              BUG_ON(i == -1);
-+              rec = &el->l_recs[i];
-+              ocfs2_subtract_from_rec(inode->i_sb, insert->ins_split, rec,
-+                                      insert_rec);
-+              goto rotate;
-+      }
-+
-+      /*
-+       * Contiguous insert - either left or right.
-+       */
-+      if (insert->ins_contig != CONTIG_NONE) {
-+              rec = &el->l_recs[i];
-+              if (insert->ins_contig == CONTIG_LEFT) {
-+                      rec->e_blkno = insert_rec->e_blkno;
-+                      rec->e_cpos = insert_rec->e_cpos;
-+              }
-+              le16_add_cpu(&rec->e_leaf_clusters,
-+                           le16_to_cpu(insert_rec->e_leaf_clusters));
-+              return;
-+      }
-+
-+      /*
-+       * Handle insert into an empty leaf.
-+       */
-+      if (le16_to_cpu(el->l_next_free_rec) == 0 ||
-+          ((le16_to_cpu(el->l_next_free_rec) == 1) &&
-+           ocfs2_is_empty_extent(&el->l_recs[0]))) {
-+              el->l_recs[0] = *insert_rec;
-+              el->l_next_free_rec = cpu_to_le16(1);
-+              return;
-+      }
-+
-+      /*
-+       * Appending insert.
-+       */
-+      if (insert->ins_appending == APPEND_TAIL) {
-+              i = le16_to_cpu(el->l_next_free_rec) - 1;
-+              rec = &el->l_recs[i];
-+              range = le32_to_cpu(rec->e_cpos)
-+                      + le16_to_cpu(rec->e_leaf_clusters);
-+              BUG_ON(le32_to_cpu(insert_rec->e_cpos) < range);
-+
-+              mlog_bug_on_msg(le16_to_cpu(el->l_next_free_rec) >=
-+                              le16_to_cpu(el->l_count),
-+                              "inode %lu, depth %u, count %u, next free %u, "
-+                              "rec.cpos %u, rec.clusters %u, "
-+                              "insert.cpos %u, insert.clusters %u\n",
-+                              inode->i_ino,
-+                              le16_to_cpu(el->l_tree_depth),
-+                              le16_to_cpu(el->l_count),
-+                              le16_to_cpu(el->l_next_free_rec),
-+                              le32_to_cpu(el->l_recs[i].e_cpos),
-+                              le16_to_cpu(el->l_recs[i].e_leaf_clusters),
-+                              le32_to_cpu(insert_rec->e_cpos),
-+                              le16_to_cpu(insert_rec->e_leaf_clusters));
-+              i++;
-+              el->l_recs[i] = *insert_rec;
-+              le16_add_cpu(&el->l_next_free_rec, 1);
-+              return;
-+      }
-+
-+rotate:
-+      /*
-+       * Ok, we have to rotate.
-+       *
-+       * At this point, it is safe to assume that inserting into an
-+       * empty leaf and appending to a leaf have both been handled
-+       * above.
-+       *
-+       * This leaf needs to have space, either by the empty 1st
-+       * extent record, or by virtue of an l_next_rec < l_count.
-+       */
-+      ocfs2_rotate_leaf(el, insert_rec);
-+}
-+
-+static inline void ocfs2_update_dinode_clusters(struct inode *inode,
-+                                              struct ocfs2_dinode *di,
-+                                              u32 clusters)
-+{
-+      le32_add_cpu(&di->i_clusters, clusters);
-+      spin_lock(&OCFS2_I(inode)->ip_lock);
-+      OCFS2_I(inode)->ip_clusters = le32_to_cpu(di->i_clusters);
-+      spin_unlock(&OCFS2_I(inode)->ip_lock);
-+}
-+
-+static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
-+                                  struct ocfs2_extent_rec *insert_rec,
-+                                  struct ocfs2_path *right_path,
-+                                  struct ocfs2_path **ret_left_path)
-+{
-+      int ret, i, next_free;
-+      struct buffer_head *bh;
-+      struct ocfs2_extent_list *el;
-+      struct ocfs2_path *left_path = NULL;
-+
-+      *ret_left_path = NULL;
-+
-+      /*
-+       * This shouldn't happen for non-trees. The extent rec cluster
-+       * count manipulation below only works for interior nodes.
-+       */
-+      BUG_ON(right_path->p_tree_depth == 0);
-+
-+      /*
-+       * If our appending insert is at the leftmost edge of a leaf,
-+       * then we might need to update the rightmost records of the
-+       * neighboring path.
-+       */
-+      el = path_leaf_el(right_path);
-+      next_free = le16_to_cpu(el->l_next_free_rec);
-       if (next_free == 0 ||
-           (next_free == 1 && ocfs2_is_empty_extent(&el->l_recs[0]))) {
-               u32 left_cpos;
-@@ -1931,6 +2973,83 @@
-       return ret;
++ * struct scsi_host_template function prototypes.
++ */
++int advansys_detect(struct scsi_host_template *);
++int advansys_release(struct Scsi_Host *);
++const char *advansys_info(struct Scsi_Host *);
++int advansys_queuecommand(struct scsi_cmnd *, void (* done)(struct scsi_cmnd *));
++int advansys_reset(struct scsi_cmnd *);
++int advansys_biosparam(struct scsi_device *, struct block_device *,
++              sector_t, int[]);
++static int advansys_slave_configure(struct scsi_device *);
++
++/* init/main.c setup function */
++void advansys_setup(char *, int *);
++
++#endif /* _ADVANSYS_H */
+diff -Nurb linux-2.6.22-590/drivers/scsi/aha152x.c linux-2.6.22-570/drivers/scsi/aha152x.c
+--- linux-2.6.22-590/drivers/scsi/aha152x.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/aha152x.c    2007-07-08 19:32:17.000000000 -0400
+@@ -240,7 +240,6 @@
+ #include <linux/io.h>
+ #include <linux/blkdev.h>
+ #include <asm/system.h>
+-#include <linux/completion.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
+ #include <linux/wait.h>
+@@ -254,6 +253,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/workqueue.h>
+ #include <linux/list.h>
++#include <asm/semaphore.h>
+ #include <scsi/scsicam.h>
+ #include "scsi.h"
+@@ -551,7 +551,7 @@
+  */
+ struct aha152x_scdata {
+       Scsi_Cmnd *next;        /* next sc in queue */
+-      struct completion *done;/* semaphore to block on */
++      struct semaphore *sem;  /* semaphore to block on */
+       unsigned char cmd_len;
+       unsigned char cmnd[MAX_COMMAND_SIZE];
+       unsigned short use_sg;
+@@ -608,7 +608,7 @@
+ #define SCDATA(SCpnt)         ((struct aha152x_scdata *) (SCpnt)->host_scribble)
+ #define SCNEXT(SCpnt)         SCDATA(SCpnt)->next
+-#define SCSEM(SCpnt)          SCDATA(SCpnt)->done
++#define SCSEM(SCpnt)          SCDATA(SCpnt)->sem
+ #define SG_ADDRESS(buffer)    ((char *) (page_address((buffer)->page)+(buffer)->offset))
+@@ -969,8 +969,7 @@
+ /* 
+  *  Queue a command and setup interrupts for a free bus.
+  */
+-static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete,
+-              int phase, void (*done)(Scsi_Cmnd *))
++static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int phase, void (*done)(Scsi_Cmnd *))
+ {
+       struct Scsi_Host *shpnt = SCpnt->device->host;
+       unsigned long flags;
+@@ -1014,7 +1013,7 @@
+       }
+       SCNEXT(SCpnt)           = NULL;
+-      SCSEM(SCpnt)            = complete;
++      SCSEM(SCpnt)            = sem;
+       /* setup scratch area
+          SCp.ptr              : buffer pointer
+@@ -1085,9 +1084,9 @@
+       DPRINTK(debug_eh, INFO_LEAD "reset_done called\n", CMDINFO(SCpnt));
+ #endif
+       if(SCSEM(SCpnt)) {
+-              complete(SCSEM(SCpnt));
++              up(SCSEM(SCpnt));
+       } else {
+-              printk(KERN_ERR "aha152x: reset_done w/o completion\n");
++              printk(KERN_ERR "aha152x: reset_done w/o semaphore\n");
+       }
+ }
+@@ -1140,6 +1139,21 @@
+       return FAILED;
  }
  
-+static void ocfs2_split_record(struct inode *inode,
-+                             struct ocfs2_path *left_path,
-+                             struct ocfs2_path *right_path,
-+                             struct ocfs2_extent_rec *split_rec,
-+                             enum ocfs2_split_type split)
++static void timer_expired(unsigned long p)
 +{
-+      int index;
-+      u32 cpos = le32_to_cpu(split_rec->e_cpos);
-+      struct ocfs2_extent_list *left_el = NULL, *right_el, *insert_el, *el;
-+      struct ocfs2_extent_rec *rec, *tmprec;
-+
-+      right_el = path_leaf_el(right_path);;
-+      if (left_path)
-+              left_el = path_leaf_el(left_path);
-+
-+      el = right_el;
-+      insert_el = right_el;
-+      index = ocfs2_search_extent_list(el, cpos);
-+      if (index != -1) {
-+              if (index == 0 && left_path) {
-+                      BUG_ON(ocfs2_is_empty_extent(&el->l_recs[0]));
-+
-+                      /*
-+                       * This typically means that the record
-+                       * started in the left path but moved to the
-+                       * right as a result of rotation. We either
-+                       * move the existing record to the left, or we
-+                       * do the later insert there.
-+                       *
-+                       * In this case, the left path should always
-+                       * exist as the rotate code will have passed
-+                       * it back for a post-insert update.
-+                       */
-+
-+                      if (split == SPLIT_LEFT) {
-+                              /*
-+                               * It's a left split. Since we know
-+                               * that the rotate code gave us an
-+                               * empty extent in the left path, we
-+                               * can just do the insert there.
-+                               */
-+                              insert_el = left_el;
-+                      } else {
-+                              /*
-+                               * Right split - we have to move the
-+                               * existing record over to the left
-+                               * leaf. The insert will be into the
-+                               * newly created empty extent in the
-+                               * right leaf.
-+                               */
-+                              tmprec = &right_el->l_recs[index];
-+                              ocfs2_rotate_leaf(left_el, tmprec);
-+                              el = left_el;
++      Scsi_Cmnd        *SCp   = (Scsi_Cmnd *)p;
++      struct semaphore *sem   = SCSEM(SCp);
++      struct Scsi_Host *shpnt = SCp->device->host;
++      unsigned long flags;
 +
-+                              memset(tmprec, 0, sizeof(*tmprec));
-+                              index = ocfs2_search_extent_list(left_el, cpos);
-+                              BUG_ON(index == -1);
-+                      }
-+              }
-+      } else {
-+              BUG_ON(!left_path);
-+              BUG_ON(!ocfs2_is_empty_extent(&left_el->l_recs[0]));
-+              /*
-+               * Left path is easy - we can just allow the insert to
-+               * happen.
-+               */
-+              el = left_el;
-+              insert_el = left_el;
-+              index = ocfs2_search_extent_list(el, cpos);
-+              BUG_ON(index == -1);
-+      }
++      /* remove command from issue queue */
++      DO_LOCK(flags);
++      remove_SC(&ISSUE_SC, SCp);
++      DO_UNLOCK(flags);
 +
-+      rec = &el->l_recs[index];
-+      ocfs2_subtract_from_rec(inode->i_sb, split, rec, split_rec);
-+      ocfs2_rotate_leaf(insert_el, split_rec);
++      up(sem);
 +}
 +
  /*
-  * This function only does inserts on an allocation b-tree. For dinode
-  * lists, ocfs2_insert_at_leaf() is called directly.
-@@ -1948,7 +3067,6 @@
+  * Reset a device
+  *
+@@ -1147,14 +1161,14 @@
+ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
  {
-       int ret, subtree_index;
-       struct buffer_head *leaf_bh = path_leaf_bh(right_path);
--      struct ocfs2_extent_list *el;
+       struct Scsi_Host *shpnt = SCpnt->device->host;
+-      DECLARE_COMPLETION(done);
++      DECLARE_MUTEX_LOCKED(sem);
++      struct timer_list timer;
+       int ret, issued, disconnected;
+       unsigned char old_cmd_len = SCpnt->cmd_len;
+       unsigned short old_use_sg = SCpnt->use_sg;
+       void *old_buffer = SCpnt->request_buffer;
+       unsigned old_bufflen = SCpnt->request_bufflen;
+       unsigned long flags;
+-      unsigned long timeleft;
  
-       /*
-        * Pass both paths to the journal. The majority of inserts
-@@ -1984,9 +3102,18 @@
+ #if defined(AHA152X_DEBUG)
+       if(HOSTDATA(shpnt)->debug & debug_eh) {
+@@ -1178,15 +1192,15 @@
+       SCpnt->request_buffer  = NULL;
+       SCpnt->request_bufflen = 0;
+-      aha152x_internal_queue(SCpnt, &done, resetting, reset_done);
+-
+-      timeleft = wait_for_completion_timeout(&done, 100*HZ);
+-      if (!timeleft) {
+-              /* remove command from issue queue */
+-              DO_LOCK(flags);
+-              remove_SC(&ISSUE_SC, SCpnt);
+-              DO_UNLOCK(flags);
+-      }
++      init_timer(&timer);
++      timer.data     = (unsigned long) SCpnt;
++      timer.expires  = jiffies + 100*HZ;   /* 10s */
++      timer.function = (void (*)(unsigned long)) timer_expired;
++
++      aha152x_internal_queue(SCpnt, &sem, resetting, reset_done);
++      add_timer(&timer);
++      down(&sem);
++      del_timer(&timer);
+       SCpnt->cmd_len         = old_cmd_len;
+       SCpnt->use_sg          = old_use_sg;
+diff -Nurb linux-2.6.22-590/drivers/scsi/aha1740.c linux-2.6.22-570/drivers/scsi/aha1740.c
+--- linux-2.6.22-590/drivers/scsi/aha1740.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/aha1740.c    2007-07-08 19:32:17.000000000 -0400
+@@ -271,7 +271,19 @@
+                               continue;
+                       }
+                       sgptr = (struct aha1740_sg *) SCtmp->host_scribble;
+-                      scsi_dma_unmap(SCtmp);
++                      if (SCtmp->use_sg) {
++                              /* We used scatter-gather.
++                                 Do the unmapping dance. */
++                              dma_unmap_sg (&edev->dev,
++                                            (struct scatterlist *) SCtmp->request_buffer,
++                                            SCtmp->use_sg,
++                                            SCtmp->sc_data_direction);
++                      } else {
++                              dma_unmap_single (&edev->dev,
++                                                sgptr->buf_dma_addr,
++                                                SCtmp->request_bufflen,
++                                                DMA_BIDIRECTIONAL);
++                      }
+           
+                       /* Free the sg block */
+                       dma_free_coherent (&edev->dev,
+@@ -337,9 +349,11 @@
+       unchar target = scmd_id(SCpnt);
+       struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
+       unsigned long flags;
++      void *buff = SCpnt->request_buffer;
++      int bufflen = SCpnt->request_bufflen;
+       dma_addr_t sg_dma;
+       struct aha1740_sg *sgptr;
+-      int ecbno, nseg;
++      int ecbno;
+       DEB(int i);
+       if(*cmd == REQUEST_SENSE) {
+@@ -410,22 +424,23 @@
+       sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
+       sgptr->sg_dma_addr = sg_dma;
+     
+-      nseg = scsi_dma_map(SCpnt);
+-      BUG_ON(nseg < 0);
+-      if (nseg) {
+-              struct scatterlist *sg;
++      if (SCpnt->use_sg) {
++              struct scatterlist * sgpnt;
+               struct aha1740_chain * cptr;
+-              int i;
++              int i, count;
+               DEB(unsigned char * ptr);
+               host->ecb[ecbno].sg = 1;  /* SCSI Initiator Command
+                                          * w/scatter-gather*/
++              sgpnt = (struct scatterlist *) SCpnt->request_buffer;
+               cptr = sgptr->sg_chain;
+-              scsi_for_each_sg(SCpnt, sg, nseg, i) {
+-                      cptr[i].datalen = sg_dma_len (sg);
+-                      cptr[i].dataptr = sg_dma_address (sg);
++              count = dma_map_sg (&host->edev->dev, sgpnt, SCpnt->use_sg,
++                                  SCpnt->sc_data_direction);
++              for(i=0; i < count; i++) {
++                      cptr[i].datalen = sg_dma_len (sgpnt + i);
++                      cptr[i].dataptr = sg_dma_address (sgpnt + i);
                }
+-              host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain);
++              host->ecb[ecbno].datalen = count*sizeof(struct aha1740_chain);
+               host->ecb[ecbno].dataptr = sg_dma;
+ #ifdef DEBUG
+               printk("cptr %x: ",cptr);
+@@ -433,8 +448,11 @@
+               for(i=0;i<24;i++) printk("%02x ", ptr[i]);
+ #endif
+       } else {
+-              host->ecb[ecbno].datalen = 0;
+-              host->ecb[ecbno].dataptr = 0;
++              host->ecb[ecbno].datalen = bufflen;
++              sgptr->buf_dma_addr =  dma_map_single (&host->edev->dev,
++                                                     buff, bufflen,
++                                                     DMA_BIDIRECTIONAL);
++              host->ecb[ecbno].dataptr = sgptr->buf_dma_addr;
        }
+       host->ecb[ecbno].lun = SCpnt->device->lun;
+       host->ecb[ecbno].ses = 1; /* Suppress underrun errors */
+diff -Nurb linux-2.6.22-590/drivers/scsi/aic7xxx/aic79xx_osm.c linux-2.6.22-570/drivers/scsi/aic7xxx/aic79xx_osm.c
+--- linux-2.6.22-590/drivers/scsi/aic7xxx/aic79xx_osm.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/aic7xxx/aic79xx_osm.c        2007-07-08 19:32:17.000000000 -0400
+@@ -376,10 +376,21 @@
+ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
+ {
+       struct scsi_cmnd *cmd;
++      int direction;
  
--      el = path_leaf_el(right_path);
-+      if (insert->ins_split != SPLIT_NONE) {
-+              /*
-+               * We could call ocfs2_insert_at_leaf() for some types
-+               * of splits, but it's easier to just let one seperate
-+               * function sort it all out.
-+               */
-+              ocfs2_split_record(inode, left_path, right_path,
-+                                 insert_rec, insert->ins_split);
-+      } else
-+              ocfs2_insert_at_leaf(insert_rec, path_leaf_el(right_path),
-+                                   insert, inode);
+       cmd = scb->io_ctx;
++      direction = cmd->sc_data_direction;
+       ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE);
+-      scsi_dma_unmap(cmd);
++      if (cmd->use_sg != 0) {
++              struct scatterlist *sg;
++
++              sg = (struct scatterlist *)cmd->request_buffer;
++              pci_unmap_sg(ahd->dev_softc, sg, cmd->use_sg, direction);
++      } else if (cmd->request_bufflen != 0) {
++              pci_unmap_single(ahd->dev_softc,
++                               scb->platform_data->buf_busaddr,
++                               cmd->request_bufflen, direction);
++      }
+ }
  
--      ocfs2_insert_at_leaf(insert_rec, el, insert, inode);
-       ret = ocfs2_journal_dirty(handle, leaf_bh);
-       if (ret)
-               mlog_errno(ret);
-@@ -2075,7 +3202,7 @@
-        * can wind up skipping both of these two special cases...
-        */
-       if (rotate) {
--              ret = ocfs2_rotate_tree_right(inode, handle,
-+              ret = ocfs2_rotate_tree_right(inode, handle, type->ins_split,
-                                             le32_to_cpu(insert_rec->e_cpos),
-                                             right_path, &left_path);
-               if (ret) {
-@@ -2100,6 +3227,7 @@
+ /******************************** Macros **************************************/
+@@ -1411,7 +1422,6 @@
+       u_int    col_idx;
+       uint16_t mask;
+       unsigned long flags;
+-      int nseg;
+       ahd_lock(ahd, &flags);
+@@ -1484,17 +1494,18 @@
+       ahd_set_residual(scb, 0);
+       ahd_set_sense_residual(scb, 0);
+       scb->sg_count = 0;
+-
+-      nseg = scsi_dma_map(cmd);
+-      BUG_ON(nseg < 0);
+-      if (nseg > 0) {
+-              void *sg = scb->sg_list;
++      if (cmd->use_sg != 0) {
++              void    *sg;
+               struct   scatterlist *cur_seg;
+-              int i;
++              u_int    nseg;
++              int      dir;
++              cur_seg = (struct scatterlist *)cmd->request_buffer;
++              dir = cmd->sc_data_direction;
++              nseg = pci_map_sg(ahd->dev_softc, cur_seg,
++                                cmd->use_sg, dir);
+               scb->platform_data->xfer_len = 0;
+-
+-              scsi_for_each_sg(cmd, cur_seg, nseg, i) {
++              for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
+                       dma_addr_t addr;
+                       bus_size_t len;
+@@ -1502,8 +1513,22 @@
+                       len = sg_dma_len(cur_seg);
+                       scb->platform_data->xfer_len += len;
+                       sg = ahd_sg_setup(ahd, scb, sg, addr, len,
+-                                        i == (nseg - 1));
++                                        /*last*/nseg == 1);
+               }
++      } else if (cmd->request_bufflen != 0) {
++              void *sg;
++              dma_addr_t addr;
++              int dir;
++
++              sg = scb->sg_list;
++              dir = cmd->sc_data_direction;
++              addr = pci_map_single(ahd->dev_softc,
++                                    cmd->request_buffer,
++                                    cmd->request_bufflen, dir);
++              scb->platform_data->xfer_len = cmd->request_bufflen;
++              scb->platform_data->buf_busaddr = addr;
++              sg = ahd_sg_setup(ahd, scb, sg, addr,
++                                cmd->request_bufflen, /*last*/TRUE);
        }
  
- out_update_clusters:
-+      if (type->ins_split == SPLIT_NONE)
-       ocfs2_update_dinode_clusters(inode, di,
-                                    le16_to_cpu(insert_rec->e_leaf_clusters));
+       LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
+diff -Nurb linux-2.6.22-590/drivers/scsi/aic7xxx/aic79xx_osm.h linux-2.6.22-570/drivers/scsi/aic7xxx/aic79xx_osm.h
+--- linux-2.6.22-590/drivers/scsi/aic7xxx/aic79xx_osm.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/aic7xxx/aic79xx_osm.h        2007-07-08 19:32:17.000000000 -0400
+@@ -781,7 +781,7 @@
+ static __inline
+ void ahd_set_residual(struct scb *scb, u_long resid)
+ {
+-      scsi_set_resid(scb->io_ctx, resid);
++      scb->io_ctx->resid = resid;
+ }
  
-@@ -2114,6 +3242,44 @@
-       return ret;
+ static __inline
+@@ -793,7 +793,7 @@
+ static __inline
+ u_long ahd_get_residual(struct scb *scb)
+ {
+-      return scsi_get_resid(scb->io_ctx);
++      return (scb->io_ctx->resid);
  }
  
-+static enum ocfs2_contig_type
-+ocfs2_figure_merge_contig_type(struct inode *inode,
-+                             struct ocfs2_extent_list *el, int index,
-+                             struct ocfs2_extent_rec *split_rec)
-+{
-+      struct ocfs2_extent_rec *rec;
-+      enum ocfs2_contig_type ret = CONTIG_NONE;
-+
-+      /*
-+       * We're careful to check for an empty extent record here -
-+       * the merge code will know what to do if it sees one.
-+       */
-+
-+      if (index > 0) {
-+              rec = &el->l_recs[index - 1];
-+              if (index == 1 && ocfs2_is_empty_extent(rec)) {
-+                      if (split_rec->e_cpos == el->l_recs[index].e_cpos)
-+                              ret = CONTIG_RIGHT;
-+              } else {
-+                      ret = ocfs2_extent_contig(inode, rec, split_rec);
-+              }
+ static __inline
+diff -Nurb linux-2.6.22-590/drivers/scsi/aic7xxx/aic7xxx_osm.c linux-2.6.22-570/drivers/scsi/aic7xxx/aic7xxx_osm.c
+--- linux-2.6.22-590/drivers/scsi/aic7xxx/aic7xxx_osm.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/aic7xxx/aic7xxx_osm.c        2007-07-08 19:32:17.000000000 -0400
+@@ -402,8 +402,18 @@
+       cmd = scb->io_ctx;
+       ahc_sync_sglist(ahc, scb, BUS_DMASYNC_POSTWRITE);
++      if (cmd->use_sg != 0) {
++              struct scatterlist *sg;
+-      scsi_dma_unmap(cmd);
++              sg = (struct scatterlist *)cmd->request_buffer;
++              pci_unmap_sg(ahc->dev_softc, sg, cmd->use_sg,
++                           cmd->sc_data_direction);
++      } else if (cmd->request_bufflen != 0) {
++              pci_unmap_single(ahc->dev_softc,
++                               scb->platform_data->buf_busaddr,
++                               cmd->request_bufflen,
++                               cmd->sc_data_direction);
 +      }
+ }
+ static __inline int
+@@ -1371,7 +1381,6 @@
+       struct   ahc_tmode_tstate *tstate;
+       uint16_t mask;
+       struct scb_tailq *untagged_q = NULL;
+-      int nseg;
+       /*
+        * Schedule us to run later.  The only reason we are not
+@@ -1463,21 +1472,23 @@
+       ahc_set_residual(scb, 0);
+       ahc_set_sense_residual(scb, 0);
+       scb->sg_count = 0;
+-
+-      nseg = scsi_dma_map(cmd);
+-      BUG_ON(nseg < 0);
+-      if (nseg > 0) {
++      if (cmd->use_sg != 0) {
+               struct  ahc_dma_seg *sg;
+               struct  scatterlist *cur_seg;
+-              int i;
++              struct  scatterlist *end_seg;
++              int     nseg;
++              cur_seg = (struct scatterlist *)cmd->request_buffer;
++              nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg,
++                                cmd->sc_data_direction);
++              end_seg = cur_seg + nseg;
+               /* Copy the segments into the SG list. */
+               sg = scb->sg_list;
+               /*
+                * The sg_count may be larger than nseg if
+                * a transfer crosses a 32bit page.
+                */ 
+-              scsi_for_each_sg(cmd, cur_seg, nseg, i) {
++              while (cur_seg < end_seg) {
+                       dma_addr_t addr;
+                       bus_size_t len;
+                       int consumed;
+@@ -1488,6 +1499,7 @@
+                                                    sg, addr, len);
+                       sg += consumed;
+                       scb->sg_count += consumed;
++                      cur_seg++;
+               }
+               sg--;
+               sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
+@@ -1504,6 +1516,33 @@
+                */
+               scb->hscb->dataptr = scb->sg_list->addr;
+               scb->hscb->datacnt = scb->sg_list->len;
++      } else if (cmd->request_bufflen != 0) {
++              struct   ahc_dma_seg *sg;
++              dma_addr_t addr;
 +
-+      if (index < (le16_to_cpu(el->l_next_free_rec) - 1)) {
-+              enum ocfs2_contig_type contig_type;
-+
-+              rec = &el->l_recs[index + 1];
-+              contig_type = ocfs2_extent_contig(inode, rec, split_rec);
-+
-+              if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT)
-+                      ret = CONTIG_LEFTRIGHT;
-+              else if (ret == CONTIG_NONE)
-+                      ret = contig_type;
-+      }
++              sg = scb->sg_list;
++              addr = pci_map_single(ahc->dev_softc,
++                                    cmd->request_buffer,
++                                    cmd->request_bufflen,
++                                    cmd->sc_data_direction);
++              scb->platform_data->buf_busaddr = addr;
++              scb->sg_count = ahc_linux_map_seg(ahc, scb,
++                                                sg, addr,
++                                                cmd->request_bufflen);
++              sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
 +
-+      return ret;
-+}
++              /*
++               * Reset the sg list pointer.
++               */
++              scb->hscb->sgptr =
++                      ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
 +
- static void ocfs2_figure_contig_type(struct inode *inode,
-                                    struct ocfs2_insert_type *insert,
-                                    struct ocfs2_extent_list *el,
-@@ -2205,6 +3371,8 @@
-       struct ocfs2_path *path = NULL;
-       struct buffer_head *bh = NULL;
++              /*
++               * Copy the first SG into the "current"
++               * data pointer area.
++               */
++              scb->hscb->dataptr = sg->addr;
++              scb->hscb->datacnt = sg->len;
+       } else {
+               scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
+               scb->hscb->dataptr = 0;
+diff -Nurb linux-2.6.22-590/drivers/scsi/aic7xxx/aic7xxx_osm.h linux-2.6.22-570/drivers/scsi/aic7xxx/aic7xxx_osm.h
+--- linux-2.6.22-590/drivers/scsi/aic7xxx/aic7xxx_osm.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/aic7xxx/aic7xxx_osm.h        2007-07-08 19:32:17.000000000 -0400
+@@ -751,7 +751,7 @@
+ static __inline
+ void ahc_set_residual(struct scb *scb, u_long resid)
+ {
+-      scsi_set_resid(scb->io_ctx, resid);
++      scb->io_ctx->resid = resid;
+ }
  
-+      insert->ins_split = SPLIT_NONE;
-+
-       el = &di->id2.i_list;
-       insert->ins_tree_depth = le16_to_cpu(el->l_tree_depth);
+ static __inline
+@@ -763,7 +763,7 @@
+ static __inline
+ u_long ahc_get_residual(struct scb *scb)
+ {
+-      return scsi_get_resid(scb->io_ctx);
++      return (scb->io_ctx->resid);
+ }
  
-@@ -2305,130 +3473,425 @@
-               ocfs2_figure_appending_type(insert, el, insert_rec);
-       }
+ static __inline
+diff -Nurb linux-2.6.22-590/drivers/scsi/aic7xxx_old.c linux-2.6.22-570/drivers/scsi/aic7xxx_old.c
+--- linux-2.6.22-590/drivers/scsi/aic7xxx_old.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/aic7xxx_old.c        2007-07-08 19:32:17.000000000 -0400
+@@ -2690,8 +2690,17 @@
+       struct aic7xxx_scb *scbp;
+       unsigned char queue_depth;
  
--out:
--      ocfs2_free_path(path);
-+out:
-+      ocfs2_free_path(path);
-+
-+      if (ret == 0)
-+              *last_eb_bh = bh;
-+      else
-+              brelse(bh);
-+      return ret;
-+}
-+
+-        scsi_dma_unmap(cmd);
++  if (cmd->use_sg > 1)
++  {
++    struct scatterlist *sg;
++    sg = (struct scatterlist *)cmd->request_buffer;
++    pci_unmap_sg(p->pdev, sg, cmd->use_sg, cmd->sc_data_direction);
++  }
++  else if (cmd->request_bufflen)
++    pci_unmap_single(p->pdev, aic7xxx_mapping(cmd),
++                   cmd->request_bufflen,
++                     cmd->sc_data_direction);
+   if (scb->flags & SCB_SENSE)
+   {
+     pci_unmap_single(p->pdev,
+@@ -3860,7 +3869,7 @@
+        * the mid layer didn't check residual data counts to see if the
+        * command needs retried.
+        */
+-      scsi_set_resid(cmd, scb->sg_length - actual);
++      cmd->resid = scb->sg_length - actual;
+       aic7xxx_status(cmd) = hscb->target_status;
+     }
+   }
+@@ -10128,7 +10137,6 @@
+   struct scsi_device *sdptr = cmd->device;
+   unsigned char tindex = TARGET_INDEX(cmd);
+   struct request *req = cmd->request;
+-  int use_sg;
+   mask = (0x01 << tindex);
+   hscb = scb->hscb;
+@@ -10201,10 +10209,8 @@
+   memcpy(scb->cmnd, cmd->cmnd, cmd->cmd_len);
+   hscb->SCSI_cmd_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, scb->cmnd));
+-  use_sg = scsi_dma_map(cmd);
+-  BUG_ON(use_sg < 0);
+-
+-  if (use_sg) {
++  if (cmd->use_sg)
++  {
+     struct scatterlist *sg;  /* Must be mid-level SCSI code scatterlist */
+     /*
+@@ -10213,11 +10219,11 @@
+      * differences and the kernel SG list uses virtual addresses where
+      * we need physical addresses.
+      */
+-    int i;
++    int i, use_sg;
++    sg = (struct scatterlist *)cmd->request_buffer;
+     scb->sg_length = 0;
+-
+-
++    use_sg = pci_map_sg(p->pdev, sg, cmd->use_sg, cmd->sc_data_direction);
+     /*
+      * Copy the segments into the SG array.  NOTE!!! - We used to
+      * have the first entry both in the data_pointer area and the first
+@@ -10225,9 +10231,10 @@
+      * entry in both places, but now we download the address of
+      * scb->sg_list[1] instead of 0 to the sg pointer in the hscb.
+      */
+-    scsi_for_each_sg(cmd, sg, use_sg, i) {
+-      unsigned int len = sg_dma_len(sg);
+-      scb->sg_list[i].address = cpu_to_le32(sg_dma_address(sg));
++    for (i = 0; i < use_sg; i++)
++    {
++      unsigned int len = sg_dma_len(sg+i);
++      scb->sg_list[i].address = cpu_to_le32(sg_dma_address(sg+i));
+       scb->sg_list[i].length = cpu_to_le32(len);
+       scb->sg_length += len;
+     }
+@@ -10237,7 +10244,26 @@
+     scb->sg_count = i;
+     hscb->SG_segment_count = i;
+     hscb->SG_list_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, &scb->sg_list[1]));
+-  } else {
++  }
++  else
++  {
++    if (cmd->request_bufflen)
++    {
++      unsigned int address = pci_map_single(p->pdev, cmd->request_buffer,
++                                          cmd->request_bufflen,
++                                            cmd->sc_data_direction);
++      aic7xxx_mapping(cmd) = address;
++      scb->sg_list[0].address = cpu_to_le32(address);
++      scb->sg_list[0].length = cpu_to_le32(cmd->request_bufflen);
++      scb->sg_count = 1;
++      scb->sg_length = cmd->request_bufflen;
++      hscb->SG_segment_count = 1;
++      hscb->SG_list_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, &scb->sg_list[0]));
++      hscb->data_count = scb->sg_list[0].length;
++      hscb->data_pointer = scb->sg_list[0].address;
++    }
++    else
++    {
+       scb->sg_count = 0;
+       scb->sg_length = 0;
+       hscb->SG_segment_count = 0;
+@@ -10245,6 +10271,7 @@
+       hscb->data_count = 0;
+       hscb->data_pointer = 0;
+     }
++  }
+ }
+ /*+F*************************************************************************
+diff -Nurb linux-2.6.22-590/drivers/scsi/amiga7xx.c linux-2.6.22-570/drivers/scsi/amiga7xx.c
+--- linux-2.6.22-590/drivers/scsi/amiga7xx.c   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/amiga7xx.c   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,138 @@
 +/*
-+ * Insert an extent into an inode btree.
++ * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
++ *            Amiga MacroSystemUS WarpEngine SCSI controller.
++ *            Amiga Technologies A4000T SCSI controller.
++ *            Amiga Technologies/DKB A4091 SCSI controller.
 + *
-+ * The caller needs to update fe->i_clusters
++ * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
++ * plus modifications of the 53c7xx.c driver to support the Amiga.
 + */
-+int ocfs2_insert_extent(struct ocfs2_super *osb,
-+                      handle_t *handle,
-+                      struct inode *inode,
-+                      struct buffer_head *fe_bh,
-+                      u32 cpos,
-+                      u64 start_blk,
-+                      u32 new_clusters,
-+                      u8 flags,
-+                      struct ocfs2_alloc_context *meta_ac)
-+{
-+      int status;
-+      struct buffer_head *last_eb_bh = NULL;
-+      struct buffer_head *bh = NULL;
-+      struct ocfs2_insert_type insert = {0, };
-+      struct ocfs2_extent_rec rec;
-+
-+      mlog(0, "add %u clusters at position %u to inode %llu\n",
-+           new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno);
-+
-+      mlog_bug_on_msg(!ocfs2_sparse_alloc(osb) &&
-+                      (OCFS2_I(inode)->ip_clusters != cpos),
-+                      "Device %s, asking for sparse allocation: inode %llu, "
-+                      "cpos %u, clusters %u\n",
-+                      osb->dev_str,
-+                      (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos,
-+                      OCFS2_I(inode)->ip_clusters);
-+
-+      memset(&rec, 0, sizeof(rec));
-+      rec.e_cpos = cpu_to_le32(cpos);
-+      rec.e_blkno = cpu_to_le64(start_blk);
-+      rec.e_leaf_clusters = cpu_to_le16(new_clusters);
-+      rec.e_flags = flags;
-+
-+      status = ocfs2_figure_insert_type(inode, fe_bh, &last_eb_bh, &rec,
-+                                        &insert);
-+      if (status < 0) {
-+              mlog_errno(status);
-+              goto bail;
-+      }
-+
-+      mlog(0, "Insert.appending: %u, Insert.Contig: %u, "
-+           "Insert.contig_index: %d, Insert.free_records: %d, "
-+           "Insert.tree_depth: %d\n",
-+           insert.ins_appending, insert.ins_contig, insert.ins_contig_index,
-+           insert.ins_free_records, insert.ins_tree_depth);
-+
-+      if (insert.ins_contig == CONTIG_NONE && insert.ins_free_records == 0) {
-+              status = ocfs2_grow_tree(inode, handle, fe_bh,
-+                                       &insert.ins_tree_depth, &last_eb_bh,
-+                                       meta_ac);
-+              if (status) {
-+                      mlog_errno(status);
-+                      goto bail;
-+              }
-+      }
-+
-+      /* Finally, we can add clusters. This might rotate the tree for us. */
-+      status = ocfs2_do_insert_extent(inode, handle, fe_bh, &rec, &insert);
-+      if (status < 0)
-+              mlog_errno(status);
-+      else
-+              ocfs2_extent_map_insert_rec(inode, &rec);
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/blkdev.h>
++#include <linux/zorro.h>
++#include <linux/stat.h>
 +
-+bail:
-+      if (bh)
-+              brelse(bh);
++#include <asm/setup.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/amigaints.h>
++#include <asm/amigahw.h>
++#include <asm/dma.h>
++#include <asm/irq.h>
 +
-+      if (last_eb_bh)
-+              brelse(last_eb_bh);
++#include "scsi.h"
++#include <scsi/scsi_host.h>
++#include "53c7xx.h"
++#include "amiga7xx.h"
 +
-+      mlog_exit(status);
-+      return status;
-+}
 +
-+static int ocfs2_split_and_insert(struct inode *inode,
-+                                handle_t *handle,
-+                                struct ocfs2_path *path,
-+                                struct buffer_head *di_bh,
-+                                struct buffer_head **last_eb_bh,
-+                                int split_index,
-+                                struct ocfs2_extent_rec *orig_split_rec,
-+                                struct ocfs2_alloc_context *meta_ac)
++static int amiga7xx_register_one(struct scsi_host_template *tpnt,
++                               unsigned long address)
 +{
-+      int ret = 0, depth;
-+      unsigned int insert_range, rec_range, do_leftright = 0;
-+      struct ocfs2_extent_rec tmprec;
-+      struct ocfs2_extent_list *rightmost_el;
-+      struct ocfs2_extent_rec rec;
-+      struct ocfs2_extent_rec split_rec = *orig_split_rec;
-+      struct ocfs2_insert_type insert;
-+      struct ocfs2_extent_block *eb;
-+      struct ocfs2_dinode *di;
-+
-+leftright:
-+      /*
-+       * Store a copy of the record on the stack - it might move
-+       * around as the tree is manipulated below.
-+       */
-+      rec = path_leaf_el(path)->l_recs[split_index];
++    long long options;
++    int clock;
 +
-+      di = (struct ocfs2_dinode *)di_bh->b_data;
-+      rightmost_el = &di->id2.i_list;
++    if (!request_mem_region(address, 0x1000, "ncr53c710"))
++      return 0;
 +
-+      depth = le16_to_cpu(rightmost_el->l_tree_depth);
-+      if (depth) {
-+              BUG_ON(!(*last_eb_bh));
-+              eb = (struct ocfs2_extent_block *) (*last_eb_bh)->b_data;
-+              rightmost_el = &eb->h_list;
-+      }
++    address = (unsigned long)z_ioremap(address, 0x1000);
++    options = OPTION_MEMORY_MAPPED | OPTION_DEBUG_TEST1 | OPTION_INTFLY |
++            OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS |
++            OPTION_DISCONNECT;
++    clock = 50000000; /* 50 MHz SCSI Clock */
++    ncr53c7xx_init(tpnt, 0, 710, address, 0, IRQ_AMIGA_PORTS, DMA_NONE,
++                 options, clock);
++    return 1;
++}
 +
-+      if (le16_to_cpu(rightmost_el->l_next_free_rec) ==
-+          le16_to_cpu(rightmost_el->l_count)) {
-+              int old_depth = depth;
 +
-+              ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, last_eb_bh,
-+                                    meta_ac);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
++#ifdef CONFIG_ZORRO
 +
-+              if (old_depth != depth) {
-+                      eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
-+                      rightmost_el = &eb->h_list;
-+              }
-+      }
++static struct {
++    zorro_id id;
++    unsigned long offset;
++    int absolute;     /* offset is absolute address */
++} amiga7xx_table[] = {
++    { .id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS, .offset = 0xf40000,
++      .absolute = 1 },
++    { .id = ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx, .offset = 0x40000 },
++    { .id = ZORRO_PROD_CBM_A4091_1, .offset = 0x800000 },
++    { .id = ZORRO_PROD_CBM_A4091_2, .offset = 0x800000 },
++    { .id = ZORRO_PROD_GVP_GFORCE_040_060, .offset = 0x40000 },
++    { 0 }
++};
 +
-+      memset(&insert, 0, sizeof(struct ocfs2_insert_type));
-+      insert.ins_appending = APPEND_NONE;
-+      insert.ins_contig = CONTIG_NONE;
-+      insert.ins_free_records = le16_to_cpu(rightmost_el->l_count)
-+              - le16_to_cpu(rightmost_el->l_next_free_rec);
-+      insert.ins_tree_depth = depth;
++static int __init amiga7xx_zorro_detect(struct scsi_host_template *tpnt)
++{
++    int num = 0, i;
++    struct zorro_dev *z = NULL;
++    unsigned long address;
 +
-+      insert_range = le32_to_cpu(split_rec.e_cpos) +
-+              le16_to_cpu(split_rec.e_leaf_clusters);
-+      rec_range = le32_to_cpu(rec.e_cpos) +
-+              le16_to_cpu(rec.e_leaf_clusters);
++    while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
++      for (i = 0; amiga7xx_table[i].id; i++)
++          if (z->id == amiga7xx_table[i].id)
++              break;
++      if (!amiga7xx_table[i].id)
++          continue;
++      if (amiga7xx_table[i].absolute)
++          address = amiga7xx_table[i].offset;
++      else
++          address = z->resource.start + amiga7xx_table[i].offset;
++      num += amiga7xx_register_one(tpnt, address);
++    }
++    return num;
++}
 +
-+      if (split_rec.e_cpos == rec.e_cpos) {
-+              insert.ins_split = SPLIT_LEFT;
-+      } else if (insert_range == rec_range) {
-+              insert.ins_split = SPLIT_RIGHT;
-+      } else {
-+              /*
-+               * Left/right split. We fake this as a right split
-+               * first and then make a second pass as a left split.
-+               */
-+              insert.ins_split = SPLIT_RIGHT;
++#endif /* CONFIG_ZORRO */
 +
-+              memset(&tmprec, 0, sizeof(tmprec));
 +
-+              tmprec.e_cpos = cpu_to_le32(insert_range);
-+              tmprec.e_leaf_clusters = cpu_to_le16(rec_range - insert_range);
-+              tmprec.e_flags = rec.e_flags;
-+              tmprec.e_blkno = split_rec.e_blkno;
-+              le64_add_cpu(&tmprec.e_blkno,
-+                           ocfs2_clusters_to_blocks(inode->i_sb,
-+                                   le16_to_cpu(split_rec.e_leaf_clusters)));
-+              split_rec = tmprec;
++int __init amiga7xx_detect(struct scsi_host_template *tpnt)
++{
++    static unsigned char called = 0;
++    int num = 0;
 +
-+              BUG_ON(do_leftright);
-+              do_leftright = 1;
-+      }
++    if (called || !MACH_IS_AMIGA)
++      return 0;
 +
-+      ret = ocfs2_do_insert_extent(inode, handle, di_bh, &split_rec,
-+                                   &insert);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out;
-+      }
++    tpnt->proc_name = "Amiga7xx";
 +
-+      if (do_leftright == 1) {
-+              u32 cpos;
-+              struct ocfs2_extent_list *el;
++    if (AMIGAHW_PRESENT(A4000_SCSI))
++      num += amiga7xx_register_one(tpnt, 0xdd0040);
 +
-+              do_leftright++;
-+              split_rec = *orig_split_rec;
++#ifdef CONFIG_ZORRO
++    num += amiga7xx_zorro_detect(tpnt);
++#endif
 +
-+              ocfs2_reinit_path(path, 1);
++    called = 1;
++    return num;
++}
 +
-+              cpos = le32_to_cpu(split_rec.e_cpos);
-+              ret = ocfs2_find_path(inode, path, cpos);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
++static int amiga7xx_release(struct Scsi_Host *shost)
++{
++      if (shost->irq)
++              free_irq(shost->irq, NULL);
++      if (shost->dma_channel != 0xff)
++              free_dma(shost->dma_channel);
++      if (shost->io_port && shost->n_io_port)
++              release_region(shost->io_port, shost->n_io_port);
++      scsi_unregister(shost);
++      return 0;
++}
 +
-+              el = path_leaf_el(path);
-+              split_index = ocfs2_search_extent_list(el, cpos);
-+              goto leftright;
-+      }
-+out:
++static struct scsi_host_template driver_template = {
++      .name                   = "Amiga NCR53c710 SCSI",
++      .detect                 = amiga7xx_detect,
++      .release                = amiga7xx_release,
++      .queuecommand           = NCR53c7xx_queue_command,
++      .abort                  = NCR53c7xx_abort,
++      .reset                  = NCR53c7xx_reset,
++      .can_queue              = 24,
++      .this_id                = 7,
++      .sg_tablesize           = 63,
++      .cmd_per_lun            = 3,
++      .use_clustering         = DISABLE_CLUSTERING
++};
 +
-+      return ret;
-+}
 +
-+/*
-+ * Mark part or all of the extent record at split_index in the leaf
-+ * pointed to by path as written. This removes the unwritten
-+ * extent flag.
-+ *
-+ * Care is taken to handle contiguousness so as to not grow the tree.
-+ *
-+ * meta_ac is not strictly necessary - we only truly need it if growth
-+ * of the tree is required. All other cases will degrade into a less
-+ * optimal tree layout.
-+ *
-+ * last_eb_bh should be the rightmost leaf block for any inode with a
-+ * btree. Since a split may grow the tree or a merge might shrink it, the caller cannot trust the contents of that buffer after this call.
-+ *
-+ * This code is optimized for readability - several passes might be
-+ * made over certain portions of the tree. All of those blocks will
-+ * have been brought into cache (and pinned via the journal), so the
-+ * extra overhead is not expressed in terms of disk reads.
-+ */
-+static int __ocfs2_mark_extent_written(struct inode *inode,
-+                                     struct buffer_head *di_bh,
-+                                     handle_t *handle,
-+                                     struct ocfs2_path *path,
-+                                     int split_index,
-+                                     struct ocfs2_extent_rec *split_rec,
-+                                     struct ocfs2_alloc_context *meta_ac,
-+                                     struct ocfs2_cached_dealloc_ctxt *dealloc)
-+{
-+      int ret = 0;
-+      struct ocfs2_extent_list *el = path_leaf_el(path);
-+      struct buffer_head *eb_bh, *last_eb_bh = NULL;
-+      struct ocfs2_extent_rec *rec = &el->l_recs[split_index];
-+      struct ocfs2_merge_ctxt ctxt;
-+      struct ocfs2_extent_list *rightmost_el;
++#include "scsi_module.c"
+diff -Nurb linux-2.6.22-590/drivers/scsi/amiga7xx.h linux-2.6.22-570/drivers/scsi/amiga7xx.h
+--- linux-2.6.22-590/drivers/scsi/amiga7xx.h   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/amiga7xx.h   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,23 @@
++#ifndef AMIGA7XX_H
 +
-+      if (!rec->e_flags & OCFS2_EXT_UNWRITTEN) {
-+              ret = -EIO;
-+              mlog_errno(ret);
-+              goto out;
-+      }
++#include <linux/types.h>
 +
-+      if (le32_to_cpu(rec->e_cpos) > le32_to_cpu(split_rec->e_cpos) ||
-+          ((le32_to_cpu(rec->e_cpos) + le16_to_cpu(rec->e_leaf_clusters)) <
-+           (le32_to_cpu(split_rec->e_cpos) + le16_to_cpu(split_rec->e_leaf_clusters)))) {
-+              ret = -EIO;
-+              mlog_errno(ret);
-+              goto out;
-+      }
++int amiga7xx_detect(struct scsi_host_template *);
++const char *NCR53c7x0_info(void);
++int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
++int NCR53c7xx_abort(Scsi_Cmnd *);
++int NCR53c7x0_release (struct Scsi_Host *);
++int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
++void NCR53c7x0_intr(int irq, void *dev_id);
 +
-+      eb_bh = path_leaf_bh(path);
-+      ret = ocfs2_journal_access(handle, inode, eb_bh,
-+                                 OCFS2_JOURNAL_ACCESS_WRITE);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out;
-+      }
++#ifndef CMD_PER_LUN
++#define CMD_PER_LUN 3
++#endif
 +
-+      ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, el,
-+                                                          split_index,
-+                                                          split_rec);
++#ifndef CAN_QUEUE
++#define CAN_QUEUE 24
++#endif
 +
-+      /*
-+       * The core merge / split code wants to know how much room is
-+       * left in this inodes allocation tree, so we pass the
-+       * rightmost extent list.
-+       */
-+      if (path->p_tree_depth) {
-+              struct ocfs2_extent_block *eb;
-+              struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
++#include <scsi/scsicam.h>
 +
-+              ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
-+                                     le64_to_cpu(di->i_last_eb_blk),
-+                                     &last_eb_bh, OCFS2_BH_CACHED, inode);
-+              if (ret) {
-+                      mlog_exit(ret);
-+                      goto out;
-+              }
++#endif /* AMIGA7XX_H */
+diff -Nurb linux-2.6.22-590/drivers/scsi/arcmsr/arcmsr.h linux-2.6.22-570/drivers/scsi/arcmsr/arcmsr.h
+--- linux-2.6.22-590/drivers/scsi/arcmsr/arcmsr.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/arcmsr/arcmsr.h      2007-07-08 19:32:17.000000000 -0400
+@@ -48,10 +48,9 @@
+ #define ARCMSR_MAX_OUTSTANDING_CMD                                            256
+ #define ARCMSR_MAX_FREECCB_NUM                                                        288
+-#define ARCMSR_DRIVER_VERSION                         "Driver Version 1.20.00.14"
++#define ARCMSR_DRIVER_VERSION                         "Driver Version 1.20.00.13"
+ #define ARCMSR_SCSI_INITIATOR_ID                                              255
+ #define ARCMSR_MAX_XFER_SECTORS                                                       512
+-#define ARCMSR_MAX_XFER_SECTORS_B                                              4096
+ #define ARCMSR_MAX_TARGETID                                                    17
+ #define ARCMSR_MAX_TARGETLUN                                                    8
+ #define ARCMSR_MAX_CMD_PERLUN                          ARCMSR_MAX_OUTSTANDING_CMD
+@@ -470,3 +469,4 @@
+ extern struct class_device_attribute *arcmsr_host_attrs[];
+ extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb);
+ void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb);
 +
-+              eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
-+              if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
-+                      OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
-+                      ret = -EROFS;
-+                      goto out;
-+              }
+diff -Nurb linux-2.6.22-590/drivers/scsi/arcmsr/arcmsr_attr.c linux-2.6.22-570/drivers/scsi/arcmsr/arcmsr_attr.c
+--- linux-2.6.22-590/drivers/scsi/arcmsr/arcmsr_attr.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/arcmsr/arcmsr_attr.c 2007-07-08 19:32:17.000000000 -0400
+@@ -59,9 +59,8 @@
+ struct class_device_attribute *arcmsr_host_attrs[];
+ static ssize_t
+-arcmsr_sysfs_iop_message_read(struct kobject *kobj,
+-                            struct bin_attribute *bin_attr,
+-                            char *buf, loff_t off, size_t count)
++arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+       struct Scsi_Host *host = class_to_shost(cdev);
+@@ -106,9 +105,8 @@
+ }
+ static ssize_t
+-arcmsr_sysfs_iop_message_write(struct kobject *kobj,
+-                             struct bin_attribute *bin_attr,
+-                             char *buf, loff_t off, size_t count)
++arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+       struct Scsi_Host *host = class_to_shost(cdev);
+@@ -154,9 +152,8 @@
+ }
  
--      if (ret == 0)
--              *last_eb_bh = bh;
-+              rightmost_el = &eb->h_list;
-+      } else
-+              rightmost_el = path_root_el(path);
-+
-+      ctxt.c_used_tail_recs = le16_to_cpu(rightmost_el->l_next_free_rec);
-+      if (ctxt.c_used_tail_recs > 0 &&
-+          ocfs2_is_empty_extent(&rightmost_el->l_recs[0]))
-+              ctxt.c_used_tail_recs--;
-+
-+      if (rec->e_cpos == split_rec->e_cpos &&
-+          rec->e_leaf_clusters == split_rec->e_leaf_clusters)
-+              ctxt.c_split_covers_rec = 1;
-       else
--              brelse(bh);
-+              ctxt.c_split_covers_rec = 0;
-+
-+      ctxt.c_has_empty_extent = ocfs2_is_empty_extent(&el->l_recs[0]);
+ static ssize_t
+-arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
+-                             struct bin_attribute *bin_attr,
+-                             char *buf, loff_t off, size_t count)
++arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+       struct Scsi_Host *host = class_to_shost(cdev);
+@@ -191,6 +188,7 @@
+       .attr = {
+               .name = "mu_read",
+               .mode = S_IRUSR ,
++              .owner = THIS_MODULE,
+       },
+       .size = 1032,
+       .read = arcmsr_sysfs_iop_message_read,
+@@ -200,6 +198,7 @@
+       .attr = {
+               .name = "mu_write",
+               .mode = S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = 1032,
+       .write = arcmsr_sysfs_iop_message_write,
+@@ -209,6 +208,7 @@
+       .attr = {
+               .name = "mu_clear",
+               .mode = S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = 1,
+       .write = arcmsr_sysfs_iop_message_clear,
+diff -Nurb linux-2.6.22-590/drivers/scsi/arcmsr/arcmsr_hba.c linux-2.6.22-570/drivers/scsi/arcmsr/arcmsr_hba.c
+--- linux-2.6.22-590/drivers/scsi/arcmsr/arcmsr_hba.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/arcmsr/arcmsr_hba.c  2007-07-08 19:32:17.000000000 -0400
+@@ -57,7 +57,6 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/timer.h>
+ #include <linux/pci.h>
+-#include <linux/aer.h>
+ #include <asm/dma.h>
+ #include <asm/io.h>
+ #include <asm/system.h>
+@@ -72,7 +71,7 @@
+ #include "arcmsr.h"
+ MODULE_AUTHOR("Erich Chen <erich@areca.com.tw>");
+-MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter");
++MODULE_DESCRIPTION("ARECA (ARC11xx/12xx) SATA RAID HOST Adapter");
+ MODULE_LICENSE("Dual BSD/GPL");
+ MODULE_VERSION(ARCMSR_DRIVER_VERSION);
+@@ -94,9 +93,7 @@
+ static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb);
+ static const char *arcmsr_info(struct Scsi_Host *);
+ static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
+-static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev,
+-                                              pci_channel_state_t state);
+-static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev);
 +
-+      mlog(0, "index: %d, contig: %u, used_tail_recs: %u, "
-+           "has_empty: %u, split_covers: %u\n", split_index,
-+           ctxt.c_contig_type, ctxt.c_used_tail_recs,
-+           ctxt.c_has_empty_extent, ctxt.c_split_covers_rec);
+ static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth)
+ {
+       if (queue_depth > ARCMSR_MAX_CMD_PERLUN)
+@@ -107,8 +104,7 @@
+ static struct scsi_host_template arcmsr_scsi_host_template = {
+       .module                 = THIS_MODULE,
+-      .name                   = "ARCMSR ARECA SATA/SAS RAID HOST Adapter"
+-                                                      ARCMSR_DRIVER_VERSION,
++      .name                   = "ARCMSR ARECA SATA RAID HOST Adapter" ARCMSR_DRIVER_VERSION,
+       .info                   = arcmsr_info,
+       .queuecommand           = arcmsr_queue_command,
+       .eh_abort_handler       = arcmsr_abort,
+@@ -123,10 +119,6 @@
+       .use_clustering         = ENABLE_CLUSTERING,
+       .shost_attrs            = arcmsr_host_attrs,
+ };
+-static struct pci_error_handlers arcmsr_pci_error_handlers = {
+-      .error_detected         = arcmsr_pci_error_detected,
+-      .slot_reset             = arcmsr_pci_slot_reset,
+-};
+ static struct pci_device_id arcmsr_device_id_table[] = {
+       {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)},
+@@ -152,8 +144,7 @@
+       .id_table               = arcmsr_device_id_table,
+       .probe                  = arcmsr_probe,
+       .remove                 = arcmsr_remove,
+-      .shutdown               = arcmsr_shutdown,
+-      .err_handler            = &arcmsr_pci_error_handlers,
++      .shutdown               = arcmsr_shutdown
+ };
+ static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id)
+@@ -337,8 +328,6 @@
+       arcmsr_iop_init(acb);
+       pci_set_drvdata(pdev, host);
+-      if (strncmp(acb->firm_version, "V1.42", 5) >= 0)
+-              host->max_sectors= ARCMSR_MAX_XFER_SECTORS_B;
+       error = scsi_add_host(host, &pdev->dev);
+       if (error)
+@@ -349,7 +338,6 @@
+               goto out_free_sysfs;
+       scsi_scan_host(host);
+-      pci_enable_pcie_error_reporting(pdev);
+       return 0;
+  out_free_sysfs:
+  out_free_irq:
+@@ -381,9 +369,19 @@
+ static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb)
+ {
++      struct AdapterControlBlock *acb = ccb->acb;
+       struct scsi_cmnd *pcmd = ccb->pcmd;
+-      scsi_dma_unmap(pcmd);
++      if (pcmd->use_sg != 0) {
++              struct scatterlist *sl;
 +
-+      if (ctxt.c_contig_type == CONTIG_NONE) {
-+              if (ctxt.c_split_covers_rec)
-+                      el->l_recs[split_index] = *split_rec;
-+              else
-+                      ret = ocfs2_split_and_insert(inode, handle, path, di_bh,
-+                                                   &last_eb_bh, split_index,
-+                                                   split_rec, meta_ac);
-+              if (ret)
-+                      mlog_errno(ret);
-+      } else {
-+              ret = ocfs2_try_to_merge_extent(inode, handle, path,
-+                                              split_index, split_rec,
-+                                              dealloc, &ctxt);
-+              if (ret)
-+                      mlog_errno(ret);
++              sl = (struct scatterlist *)pcmd->request_buffer;
++              pci_unmap_sg(acb->pdev, sl, pcmd->use_sg, pcmd->sc_data_direction);
 +      }
-+
-+      ocfs2_journal_dirty(handle, eb_bh);
-+
-+out:
-+      brelse(last_eb_bh);
-       return ret;
++      else if (pcmd->request_bufflen != 0)
++              pci_unmap_single(acb->pdev,
++                      pcmd->SCp.dma_handle,
++                      pcmd->request_bufflen, pcmd->sc_data_direction);
  }
  
- /*
-- * Insert an extent into an inode btree.
-+ * Mark the already-existing extent at cpos as written for len clusters.
-  *
-- * The caller needs to update fe->i_clusters
-+ * If the existing extent is larger than the request, initiate a
-+ * split. An attempt will be made at merging with adjacent extents.
-+ *
-+ * The caller is responsible for passing down meta_ac if we'll need it.
-  */
--int ocfs2_insert_extent(struct ocfs2_super *osb,
--                      handle_t *handle,
--                      struct inode *inode,
--                      struct buffer_head *fe_bh,
--                      u32 cpos,
--                      u64 start_blk,
--                      u32 new_clusters,
--                      struct ocfs2_alloc_context *meta_ac)
-+int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
-+                            handle_t *handle, u32 cpos, u32 len, u32 phys,
-+                            struct ocfs2_alloc_context *meta_ac,
-+                            struct ocfs2_cached_dealloc_ctxt *dealloc)
+ static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag)
+@@ -500,7 +498,7 @@
+ static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
  {
--      int status, shift;
--      struct buffer_head *last_eb_bh = NULL;
--      struct buffer_head *bh = NULL;
--      struct ocfs2_insert_type insert = {0, };
--      struct ocfs2_extent_rec rec;
+-      struct MessageUnit __iomem *reg = acb->pmu;
++      struct MessageUnit __iomem *reg=acb->pmu;
+       writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, &reg->inbound_msgaddr0);
+       if (arcmsr_wait_msgint_ready(acb))
+@@ -553,7 +551,6 @@
+       int8_t *psge = (int8_t *)&arcmsr_cdb->u;
+       uint32_t address_lo, address_hi;
+       int arccdbsize = 0x30;
+-      int nseg;
+       ccb->pcmd = pcmd;
+       memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB));
+@@ -564,20 +561,20 @@
+       arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len;
+       arcmsr_cdb->Context = (unsigned long)arcmsr_cdb;
+       memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len);
 -
--      mlog(0, "add %u clusters at position %u to inode %llu\n",
--           new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno);
+-      nseg = scsi_dma_map(pcmd);
+-      BUG_ON(nseg < 0);
 -
--      mlog_bug_on_msg(!ocfs2_sparse_alloc(osb) &&
--                      (OCFS2_I(inode)->ip_clusters != cpos),
--                      "Device %s, asking for sparse allocation: inode %llu, "
--                      "cpos %u, clusters %u\n",
--                      osb->dev_str,
--                      (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos,
--                      OCFS2_I(inode)->ip_clusters);
-+      int ret, index;
-+      u64 start_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys);
-+      struct ocfs2_extent_rec split_rec;
-+      struct ocfs2_path *left_path = NULL;
-+      struct ocfs2_extent_list *el;
--      memset(&rec, 0, sizeof(rec));
--      rec.e_cpos = cpu_to_le32(cpos);
--      rec.e_blkno = cpu_to_le64(start_blk);
--      rec.e_leaf_clusters = cpu_to_le16(new_clusters);
-+      mlog(0, "Inode %lu cpos %u, len %u, phys %u (%llu)\n",
-+           inode->i_ino, cpos, len, phys, (unsigned long long)start_blkno);
+-      if (nseg) {
+-              int length, i, cdb_sgcount = 0;
+-              struct scatterlist *sg;
+-
++      if (pcmd->use_sg) {
++              int length, sgcount, i, cdb_sgcount = 0;
++              struct scatterlist *sl;
++
++              /* Get Scatter Gather List from scsiport. */
++              sl = (struct scatterlist *) pcmd->request_buffer;
++              sgcount = pci_map_sg(acb->pdev, sl, pcmd->use_sg,
++                              pcmd->sc_data_direction);
+               /* map stor port SG list to our iop SG List. */
+-              scsi_for_each_sg(pcmd, sg, nseg, i) {
++              for (i = 0; i < sgcount; i++) {
+                       /* Get the physical address of the current data pointer */
+-                      length = cpu_to_le32(sg_dma_len(sg));
+-                      address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sg)));
+-                      address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sg)));
++                      length = cpu_to_le32(sg_dma_len(sl));
++                      address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sl)));
++                      address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sl)));
+                       if (address_hi == 0) {
+                               struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge;
  
--      status = ocfs2_figure_insert_type(inode, fe_bh, &last_eb_bh, &rec,
--                                        &insert);
--      if (status < 0) {
--              mlog_errno(status);
--              goto bail;
-+      if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {
-+              ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents "
-+                          "that are being written to, but the feature bit "
-+                          "is not set in the super block.",
-+                          (unsigned long long)OCFS2_I(inode)->ip_blkno);
-+              ret = -EROFS;
-+              goto out;
+@@ -594,12 +591,32 @@
+                               psge += sizeof (struct SG64ENTRY);
+                               arccdbsize += sizeof (struct SG64ENTRY);
+                       }
++                      sl++;
+                       cdb_sgcount++;
+               }
+               arcmsr_cdb->sgcount = (uint8_t)cdb_sgcount;
+-              arcmsr_cdb->DataLength = scsi_bufflen(pcmd);
++              arcmsr_cdb->DataLength = pcmd->request_bufflen;
+               if ( arccdbsize > 256)
+                       arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE;
++      } else if (pcmd->request_bufflen) {
++              dma_addr_t dma_addr;
++              dma_addr = pci_map_single(acb->pdev, pcmd->request_buffer,
++                              pcmd->request_bufflen, pcmd->sc_data_direction);
++              pcmd->SCp.dma_handle = dma_addr;
++              address_lo = cpu_to_le32(dma_addr_lo32(dma_addr));
++              address_hi = cpu_to_le32(dma_addr_hi32(dma_addr));
++              if (address_hi == 0) {
++                      struct  SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge;
++                      pdma_sg->address = address_lo;
++                      pdma_sg->length = pcmd->request_bufflen;
++              } else {
++                      struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge;
++                      pdma_sg->addresshigh = address_hi;
++                      pdma_sg->address = address_lo;
++                      pdma_sg->length = pcmd->request_bufflen|IS_SG64_ADDR;
++              }
++              arcmsr_cdb->sgcount = 1;
++              arcmsr_cdb->DataLength = pcmd->request_bufflen;
        }
+       if (pcmd->sc_data_direction == DMA_TO_DEVICE ) {
+               arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
+@@ -741,20 +758,20 @@
+                               (flag_ccb << 5));
+                       if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
+                               if (ccb->startdone == ARCMSR_CCB_ABORTED) {
+-                                      struct scsi_cmnd *abortcmd = ccb->pcmd;
++                                      struct scsi_cmnd *abortcmd=ccb->pcmd;
+                                       if (abortcmd) {
+                                       abortcmd->result |= DID_ABORT >> 16;
+                                       arcmsr_ccb_complete(ccb, 1);
+                                       printk(KERN_NOTICE
+-                                              "arcmsr%d: ccb ='0x%p' isr got aborted command \n"
++                                              "arcmsr%d: ccb='0x%p' isr got aborted command \n"
+                                               , acb->host->host_no, ccb);
+                                       }
+                                       continue;
+                               }
+                               printk(KERN_NOTICE
+-                                      "arcmsr%d: isr get an illegal ccb command done acb = '0x%p'"
+-                                      "ccb = '0x%p' ccbacb = '0x%p' startdone = 0x%x"
+-                                      " ccboutstandingcount = %d \n"
++                                      "arcmsr%d: isr get an illegal ccb command done acb='0x%p'"
++                                      "ccb='0x%p' ccbacb='0x%p' startdone = 0x%x"
++                                      " ccboutstandingcount=%d \n"
+                                       , acb->host->host_no
+                                       , acb
+                                       , ccb
+@@ -774,7 +791,7 @@
+                               switch(ccb->arcmsr_cdb.DeviceStatus) {
+                               case ARCMSR_DEV_SELECT_TIMEOUT: {
+                                               acb->devstate[id][lun] = ARECA_RAID_GONE;
+-                                              ccb->pcmd->result = DID_NO_CONNECT << 16;
++                                              ccb->pcmd->result = DID_TIME_OUT << 16;
+                                               arcmsr_ccb_complete(ccb, 1);
+                                       }
+                                       break;
+@@ -793,8 +810,8 @@
+                                       break;
+                               default:
+                                       printk(KERN_NOTICE
+-                                              "arcmsr%d: scsi id = %d lun = %d"
+-                                              " isr get command error done, "
++                                              "arcmsr%d: scsi id=%d lun=%d"
++                                              " isr get command error done,"
+                                               "but got unknown DeviceStatus = 0x%x \n"
+                                               , acb->host->host_no
+                                               , id
+@@ -831,21 +848,24 @@
+       struct CMD_MESSAGE_FIELD *pcmdmessagefld;
+       int retvalue = 0, transfer_len = 0;
+       char *buffer;
+-      struct scatterlist *sg;
+       uint32_t controlcode = (uint32_t ) cmd->cmnd[5] << 24 |
+                                               (uint32_t ) cmd->cmnd[6] << 16 |
+                                               (uint32_t ) cmd->cmnd[7] << 8  |
+                                               (uint32_t ) cmd->cmnd[8];
+                                       /* 4 bytes: Areca io control code */
++      if (cmd->use_sg) {
++              struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer;
  
--      mlog(0, "Insert.appending: %u, Insert.Contig: %u, "
--           "Insert.contig_index: %d, Insert.free_records: %d, "
--           "Insert.tree_depth: %d\n",
--           insert.ins_appending, insert.ins_contig, insert.ins_contig_index,
--           insert.ins_free_records, insert.ins_tree_depth);
+-      sg = scsi_sglist(cmd);
+               buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+-      if (scsi_sg_count(cmd) > 1) {
++              if (cmd->use_sg > 1) {
+                       retvalue = ARCMSR_MESSAGE_FAIL;
+                       goto message_out;
+               }
+               transfer_len += sg->length;
 -
-       /*
--       * Avoid growing the tree unless we're out of records and the
--       * insert type requres one.
-+       * XXX: This should be fixed up so that we just re-insert the
-+       * next extent records.
-        */
--      if (insert.ins_contig != CONTIG_NONE || insert.ins_free_records)
--              goto out_add;
-+      ocfs2_extent_map_trunc(inode, 0);
--      shift = ocfs2_find_branch_target(osb, inode, fe_bh, &bh);
--      if (shift < 0) {
--              status = shift;
--              mlog_errno(status);
--              goto bail;
-+      left_path = ocfs2_new_inode_path(di_bh);
-+      if (!left_path) {
-+              ret = -ENOMEM;
-+              mlog_errno(ret);
-+              goto out;
++      } else {
++              buffer = cmd->request_buffer;
++              transfer_len = cmd->request_bufflen;
++      }
+       if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) {
+               retvalue = ARCMSR_MESSAGE_FAIL;
+               goto message_out;
+@@ -1037,9 +1057,12 @@
+               retvalue = ARCMSR_MESSAGE_FAIL;
        }
+  message_out:
+-      sg = scsi_sglist(cmd);
+-              kunmap_atomic(buffer - sg->offset, KM_IRQ0);
++      if (cmd->use_sg) {
++              struct scatterlist *sg;
  
--      /* We traveled all the way to the bottom of the allocation tree
--       * and didn't find room for any more extents - we need to add
--       * another tree level */
--      if (shift) {
--              BUG_ON(bh);
--              mlog(0, "need to shift tree depth "
--                   "(current = %d)\n", insert.ins_tree_depth);
++              sg = (struct scatterlist *) cmd->request_buffer;
++              kunmap_atomic(buffer - sg->offset, KM_IRQ0);
++      }
+       return retvalue;
+ }
+@@ -1062,7 +1085,6 @@
+       case INQUIRY: {
+               unsigned char inqdata[36];
+               char *buffer;
+-              struct scatterlist *sg;
+               if (cmd->device->lun) {
+                       cmd->result = (DID_TIME_OUT << 16);
+@@ -1074,7 +1096,7 @@
+               inqdata[1] = 0;
+               /* rem media bit & Dev Type Modifier */
+               inqdata[2] = 0;
+-              /* ISO, ECMA, & ANSI versions */
++              /* ISO,ECMA,& ANSI versions */
+               inqdata[4] = 31;
+               /* length of additional data */
+               strncpy(&inqdata[8], "Areca   ", 8);
+@@ -1082,14 +1104,21 @@
+               strncpy(&inqdata[16], "RAID controller ", 16);
+               /* Product Identification */
+               strncpy(&inqdata[32], "R001", 4); /* Product Revision */
++              if (cmd->use_sg) {
++                      struct scatterlist *sg;
+-              sg = scsi_sglist(cmd);
++                      sg = (struct scatterlist *) cmd->request_buffer;
+                       buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
 -
--              /* ocfs2_shift_tree_depth will return us a buffer with
--               * the new extent block (so we can pass that to
--               * ocfs2_add_branch). */
--              status = ocfs2_shift_tree_depth(osb, handle, inode, fe_bh,
--                                              meta_ac, &bh);
--              if (status < 0) {
--                      mlog_errno(status);
--                      goto bail;
--              }
--              insert.ins_tree_depth++;
--              /* Special case: we have room now if we shifted from
--               * tree_depth 0 */
--              if (insert.ins_tree_depth == 1)
--                      goto out_add;
-+      ret = ocfs2_find_path(inode, left_path, cpos);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out;
-       }
-+      el = path_leaf_el(left_path);
++              } else {
++                      buffer = cmd->request_buffer;
++              }
+               memcpy(buffer, inqdata, sizeof(inqdata));
+-              sg = scsi_sglist(cmd);
+-                      kunmap_atomic(buffer - sg->offset, KM_IRQ0);
++              if (cmd->use_sg) {
++                      struct scatterlist *sg;
  
--      /* call ocfs2_add_branch to add the final part of the tree with
--       * the new data. */
--      mlog(0, "add branch. bh = %p\n", bh);
--      status = ocfs2_add_branch(osb, handle, inode, fe_bh, bh, last_eb_bh,
--                                meta_ac);
--      if (status < 0) {
--              mlog_errno(status);
--              goto bail;
-+      index = ocfs2_search_extent_list(el, cpos);
-+      if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
-+              ocfs2_error(inode->i_sb,
-+                          "Inode %llu has an extent at cpos %u which can no "
-+                          "longer be found.\n",
-+                          (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos);
-+              ret = -EROFS;
-+              goto out;
++                      sg = (struct scatterlist *) cmd->request_buffer;
++                      kunmap_atomic(buffer - sg->offset, KM_IRQ0);
++              }
+               cmd->scsi_done(cmd);
        }
--out_add:
--      /* Finally, we can add clusters. This might rotate the tree for us. */
--      status = ocfs2_do_insert_extent(inode, handle, fe_bh, &rec, &insert);
--      if (status < 0)
--              mlog_errno(status);
--      else
--              ocfs2_extent_map_insert_rec(inode, &rec);
+       break;
+@@ -1124,7 +1153,7 @@
+                       , acb->host->host_no);
+               return SCSI_MLQUEUE_HOST_BUSY;
+       }
+-      if (target == 16) {
++      if(target == 16) {
+               /* virtual device for iop message transfer */
+               arcmsr_handle_virtual_command(acb, cmd);
+               return 0;
+@@ -1137,7 +1166,7 @@
+                       printk(KERN_NOTICE
+                               "arcmsr%d: block 'read/write'"
+                               "command with gone raid volume"
+-                              " Cmd = %2x, TargetId = %d, Lun = %d \n"
++                              " Cmd=%2x, TargetId=%d, Lun=%d \n"
+                               , acb->host->host_no
+                               , cmd->cmnd[0]
+                               , target, lun);
+@@ -1228,7 +1257,7 @@
+                       if ((ccb->startdone == ARCMSR_CCB_ABORTED) ||
+                               (ccb == poll_ccb)) {
+                               printk(KERN_NOTICE
+-                                      "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'"
++                                      "arcmsr%d: scsi id=%d lun=%d ccb='0x%p'"
+                                       " poll command abort successfully \n"
+                                       , acb->host->host_no
+                                       , ccb->pcmd->device->id
+@@ -1241,8 +1270,8 @@
+                       }
+                       printk(KERN_NOTICE
+                               "arcmsr%d: polling get an illegal ccb"
+-                              " command done ccb ='0x%p'"
+-                              "ccboutstandingcount = %d \n"
++                              " command done ccb='0x%p'"
++                              "ccboutstandingcount=%d \n"
+                               , acb->host->host_no
+                               , ccb
+                               , atomic_read(&acb->ccboutstandingcount));
+@@ -1259,7 +1288,7 @@
+                       switch(ccb->arcmsr_cdb.DeviceStatus) {
+                       case ARCMSR_DEV_SELECT_TIMEOUT: {
+                                       acb->devstate[id][lun] = ARECA_RAID_GONE;
+-                                      ccb->pcmd->result = DID_NO_CONNECT << 16;
++                                      ccb->pcmd->result = DID_TIME_OUT << 16;
+                                       arcmsr_ccb_complete(ccb, 1);
+                               }
+                               break;
+@@ -1278,7 +1307,7 @@
+                               break;
+                       default:
+                               printk(KERN_NOTICE
+-                                      "arcmsr%d: scsi id = %d lun = %d"
++                                      "arcmsr%d: scsi id=%d lun=%d"
+                                       " polling and getting command error done"
+                                       "but got unknown DeviceStatus = 0x%x \n"
+                                       , acb->host->host_no
+@@ -1293,94 +1322,6 @@
+               }
+       }
+ }
+-static void arcmsr_done4_abort_postqueue(struct AdapterControlBlock *acb)
+-{
+-      int i = 0, found = 0;
+-      int id, lun;
+-      uint32_t flag_ccb, outbound_intstatus;
+-      struct MessageUnit __iomem *reg = acb->pmu;
+-      struct CommandControlBlock *ccb;
+-      /*clear and abort all outbound posted Q*/
+-
+-      while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) &&
+-(i++ < 256)){
+-              ccb = (struct CommandControlBlock *)(acb->vir2phy_offset +
+-(flag_ccb << 5));
+-      if (ccb){
+-              if ((ccb->acb != acb)||(ccb->startdone != \
+-ARCMSR_CCB_START)){
+-                              printk(KERN_NOTICE "arcmsr%d: polling get \
+-an illegal ccb" "command done ccb = '0x%p'""ccboutstandingcount = %d \n",
+-                                      acb->host->host_no, ccb,
+-                                      atomic_read(&acb->ccboutstandingcount));
+-                              continue;
+-                      }
+-
+-                      id = ccb->pcmd->device->id;
+-                      lun = ccb->pcmd->device->lun;
+-                      if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)){
+-                              if (acb->devstate[id][lun] == ARECA_RAID_GONE)
+-                                      acb->devstate[id][lun] = ARECA_RAID_GOOD;
+-                              ccb->pcmd->result = DID_OK << 16;
+-                              arcmsr_ccb_complete(ccb, 1);
+-                      }
+-                      else {
+-                              switch(ccb->arcmsr_cdb.DeviceStatus) {
+-                              case ARCMSR_DEV_SELECT_TIMEOUT: {
+-                                              acb->devstate[id][lun] = ARECA_RAID_GONE;
+-                                              ccb->pcmd->result = DID_NO_CONNECT << 16;
+-                                              arcmsr_ccb_complete(ccb, 1);
+-                              }
+-                              break;
+-
+-                              case ARCMSR_DEV_ABORTED:
+-
+-                              case ARCMSR_DEV_INIT_FAIL: {
+-                                              acb->devstate[id][lun] =
+-                                                      ARECA_RAID_GONE;
+-                                              ccb->pcmd->result =
+-                                                      DID_BAD_TARGET << 16;
+-                              arcmsr_ccb_complete(ccb, 1);
+-                              }
+-                              break;
+-
+-                              case ARCMSR_DEV_CHECK_CONDITION: {
+-                                              acb->devstate[id][lun] =
+-                                                      ARECA_RAID_GOOD;
+-                                              arcmsr_report_sense_info(ccb);
+-                                              arcmsr_ccb_complete(ccb, 1);
+-                              }
+-                              break;
+-
+-                              default:
+-                                              printk(KERN_NOTICE
+-                                                    "arcmsr%d: scsi id = %d \
+-                                                      lun = %d""polling and \
+-                                                      getting command error \
+-                                                      done""but got unknown \
+-                                                      DeviceStatus = 0x%x \n",
+-                                                      acb->host->host_no, id,
+-                                         lun, ccb->arcmsr_cdb.DeviceStatus);
+-                                              acb->devstate[id][lun] =
+-                                                              ARECA_RAID_GONE;
+-                                              ccb->pcmd->result =
+-                                                      DID_BAD_TARGET << 16;
+-                                              arcmsr_ccb_complete(ccb, 1);
+-                              break;
+-                             }
+-      }
+-                     found = 1;
+-             }
+-      }
+-      if (found){
+-              outbound_intstatus = readl(&reg->outbound_intstatus) & \
+-                      acb->outbound_int_enable;
+-              writel(outbound_intstatus, &reg->outbound_intstatus);
+-              /*clear interrupt*/
+-      }
+-      return;
+-}
 -
--bail:
--      if (bh)
--              brelse(bh);
-+      memset(&split_rec, 0, sizeof(struct ocfs2_extent_rec));
-+      split_rec.e_cpos = cpu_to_le32(cpos);
-+      split_rec.e_leaf_clusters = cpu_to_le16(len);
-+      split_rec.e_blkno = cpu_to_le64(start_blkno);
-+      split_rec.e_flags = path_leaf_el(left_path)->l_recs[index].e_flags;
-+      split_rec.e_flags &= ~OCFS2_EXT_UNWRITTEN;
  
--      if (last_eb_bh)
--              brelse(last_eb_bh);
-+      ret = __ocfs2_mark_extent_written(inode, di_bh, handle, left_path,
-+                                        index, &split_rec, meta_ac, dealloc);
-+      if (ret)
-+              mlog_errno(ret);
+ static void arcmsr_iop_init(struct AdapterControlBlock *acb)
+ {
+@@ -1414,6 +1355,7 @@
  
--      mlog_exit(status);
--      return status;
-+out:
-+      ocfs2_free_path(left_path);
-+      return ret;
+ static void arcmsr_iop_reset(struct AdapterControlBlock *acb)
+ {
++      struct MessageUnit __iomem *reg = acb->pmu;
+       struct CommandControlBlock *ccb;
+       uint32_t intmask_org;
+       int i = 0;
+@@ -1426,17 +1368,21 @@
+               /* disable all outbound interrupt */
+               intmask_org = arcmsr_disable_outbound_ints(acb);
+               /* clear all outbound posted Q */
+-              arcmsr_done4_abort_postqueue(acb);
++              for (i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++)
++                      readl(&reg->outbound_queueport);
+               for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
+                       ccb = acb->pccb_pool[i];
+-                      if (ccb->startdone == ARCMSR_CCB_START) {
++                      if ((ccb->startdone == ARCMSR_CCB_START) ||
++                              (ccb->startdone == ARCMSR_CCB_ABORTED)) {
+                               ccb->startdone = ARCMSR_CCB_ABORTED;
++                              ccb->pcmd->result = DID_ABORT << 16;
++                              arcmsr_ccb_complete(ccb, 1);
+                       }
+               }
+               /* enable all outbound interrupt */
+               arcmsr_enable_outbound_ints(acb, intmask_org);
+       }
+-
++      atomic_set(&acb->ccboutstandingcount, 0);
  }
  
- static inline int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb)
-@@ -2957,6 +4420,219 @@
-       return status;
- }
+ static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
+@@ -1482,9 +1428,10 @@
+       int i = 0;
  
-+/*
-+ * Delayed de-allocation of suballocator blocks.
-+ *
-+ * Some sets of block de-allocations might involve multiple suballocator inodes.
-+ *
-+ * The locking for this can get extremely complicated, especially when
-+ * the suballocator inodes to delete from aren't known until deep
-+ * within an unrelated codepath.
-+ *
-+ * ocfs2_extent_block structures are a good example of this - an inode
-+ * btree could have been grown by any number of nodes each allocating
-+ * out of their own suballoc inode.
-+ *
-+ * These structures allow the delay of block de-allocation until a
-+ * later time, when locking of multiple cluster inodes won't cause
-+ * deadlock.
-+ */
-+
-+/*
-+ * Describes a single block free from a suballocator
-+ */
-+struct ocfs2_cached_block_free {
-+      struct ocfs2_cached_block_free          *free_next;
-+      u64                                     free_blk;
-+      unsigned int                            free_bit;
-+};
-+
-+struct ocfs2_per_slot_free_list {
-+      struct ocfs2_per_slot_free_list         *f_next_suballocator;
-+      int                                     f_inode_type;
-+      int                                     f_slot;
-+      struct ocfs2_cached_block_free          *f_first;
-+};
-+
-+static int ocfs2_free_cached_items(struct ocfs2_super *osb,
-+                                 int sysfile_type,
-+                                 int slot,
-+                                 struct ocfs2_cached_block_free *head)
-+{
-+      int ret;
-+      u64 bg_blkno;
-+      handle_t *handle;
-+      struct inode *inode;
-+      struct buffer_head *di_bh = NULL;
-+      struct ocfs2_cached_block_free *tmp;
+       printk(KERN_NOTICE
+-              "arcmsr%d: abort device command of scsi id = %d lun = %d \n",
++              "arcmsr%d: abort device command of scsi id=%d lun=%d \n",
+               acb->host->host_no, cmd->device->id, cmd->device->lun);
+       acb->num_aborts++;
 +
-+      inode = ocfs2_get_system_file_inode(osb, sysfile_type, slot);
-+      if (!inode) {
-+              ret = -EINVAL;
-+              mlog_errno(ret);
-+              goto out;
-+      }
+       /*
+       ************************************************
+       ** the all interrupt service routine is locked
+@@ -1545,300 +1492,4 @@
+       return buf;
+ }
+-static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev)
+-{
+-      struct Scsi_Host *host;
+-      struct AdapterControlBlock *acb;
+-      uint8_t bus, dev_fun;
+-      int error;
+-
+-      error = pci_enable_device(pdev);
+-      if (error)
+-              return PCI_ERS_RESULT_DISCONNECT;
+-      pci_set_master(pdev);
+-
+-      host = scsi_host_alloc(&arcmsr_scsi_host_template, sizeof \
+-(struct AdapterControlBlock));
+-      if (!host)
+-              return PCI_ERS_RESULT_DISCONNECT;
+-      acb = (struct AdapterControlBlock *)host->hostdata;
+-      memset(acb, 0, sizeof (struct AdapterControlBlock));
+-
+-      error = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+-      if (error) {
+-              error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+-              if (error) {
+-                      printk(KERN_WARNING
+-                             "scsi%d: No suitable DMA mask available\n",
+-                             host->host_no);
+-                      return PCI_ERS_RESULT_DISCONNECT;
+-              }
+-      }
+-      bus = pdev->bus->number;
+-      dev_fun = pdev->devfn;
+-      acb = (struct AdapterControlBlock *) host->hostdata;
+-      memset(acb, 0, sizeof(struct AdapterControlBlock));
+-      acb->pdev = pdev;
+-      acb->host = host;
+-      host->max_sectors = ARCMSR_MAX_XFER_SECTORS;
+-      host->max_lun = ARCMSR_MAX_TARGETLUN;
+-      host->max_id = ARCMSR_MAX_TARGETID;/*16:8*/
+-      host->max_cmd_len = 16;    /*this is issue of 64bit LBA, over 2T byte*/
+-      host->sg_tablesize = ARCMSR_MAX_SG_ENTRIES;
+-      host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */
+-      host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN;
+-      host->this_id = ARCMSR_SCSI_INITIATOR_ID;
+-      host->unique_id = (bus << 8) | dev_fun;
+-      host->irq = pdev->irq;
+-      error = pci_request_regions(pdev, "arcmsr");
+-      if (error)
+-              return PCI_ERS_RESULT_DISCONNECT;
+-      acb->pmu = ioremap(pci_resource_start(pdev, 0),
+-                         pci_resource_len(pdev, 0));
+-      if (!acb->pmu) {
+-              printk(KERN_NOTICE "arcmsr%d: memory"
+-                      " mapping region fail \n", acb->host->host_no);
+-              return PCI_ERS_RESULT_DISCONNECT;
+-      }
+-      acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
+-                         ACB_F_MESSAGE_RQBUFFER_CLEARED |
+-                         ACB_F_MESSAGE_WQBUFFER_READED);
+-      acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
+-      INIT_LIST_HEAD(&acb->ccb_free_list);
+-
+-      error = arcmsr_alloc_ccb_pool(acb);
+-      if (error)
+-              return PCI_ERS_RESULT_DISCONNECT;
+-
+-      error = request_irq(pdev->irq, arcmsr_do_interrupt,
+-                      IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb);
+-      if (error)
+-              return PCI_ERS_RESULT_DISCONNECT;
+-
+-      arcmsr_iop_init(acb);
+-      if (strncmp(acb->firm_version, "V1.42", 5) >= 0)
+-            host->max_sectors = ARCMSR_MAX_XFER_SECTORS_B;
+-
+-      pci_set_drvdata(pdev, host);
+-
+-      error = scsi_add_host(host, &pdev->dev);
+-      if (error)
+-              return PCI_ERS_RESULT_DISCONNECT;
+-
+-      error = arcmsr_alloc_sysfs_attr(acb);
+-      if (error)
+-              return PCI_ERS_RESULT_DISCONNECT;
+-
+-      scsi_scan_host(host);
+-      return PCI_ERS_RESULT_RECOVERED;
+-}
+-
+-static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev)
+-{
+-      struct Scsi_Host *host = pci_get_drvdata(pdev);
+-      struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+-      struct MessageUnit __iomem *reg = acb->pmu;
+-      struct CommandControlBlock *ccb;
+-      /*clear and abort all outbound posted Q*/
+-      int i = 0, found = 0;
+-      int id, lun;
+-      uint32_t flag_ccb, outbound_intstatus;
+-
+-      while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) &&
+-                                                              (i++ < 256)){
+-                      ccb = (struct CommandControlBlock *)(acb->vir2phy_offset
+-                                                       + (flag_ccb << 5));
+-                      if (ccb){
+-                              if ((ccb->acb != acb)||(ccb->startdone !=
+-                                                      ARCMSR_CCB_START)){
+-                                      printk(KERN_NOTICE "arcmsr%d: polling \
+-                                      get an illegal ccb"" command done ccb = '0x%p'"
+-                                      "ccboutstandingcount = %d \n",
+-                                      acb->host->host_no, ccb,
+-                                      atomic_read(&acb->ccboutstandingcount));
+-                                      continue;
+-                              }
+-
+-                              id = ccb->pcmd->device->id;
+-                              lun = ccb->pcmd->device->lun;
+-                              if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) {
+-                                      if (acb->devstate[id][lun] ==
+-                                                              ARECA_RAID_GONE)
+-                                              acb->devstate[id][lun] =
+-                                                              ARECA_RAID_GOOD;
+-                                      ccb->pcmd->result = DID_OK << 16;
+-                                      arcmsr_ccb_complete(ccb, 1);
+-                              }
+-                              else {
+-                                      switch(ccb->arcmsr_cdb.DeviceStatus) {
+-                                      case ARCMSR_DEV_SELECT_TIMEOUT: {
+-                                                      acb->devstate[id][lun] =
+-                                                      ARECA_RAID_GONE;
+-                                                      ccb->pcmd->result =
+-                                                      DID_NO_CONNECT << 16;
+-                                                      arcmsr_ccb_complete(ccb, 1);
+-                                      }
+-                                      break;
+-
+-                                      case ARCMSR_DEV_ABORTED:
+-
+-                                      case ARCMSR_DEV_INIT_FAIL: {
+-                                                      acb->devstate[id][lun] =
+-                                                       ARECA_RAID_GONE;
+-                                                      ccb->pcmd->result =
+-                                                      DID_BAD_TARGET << 16;
+-                                                      arcmsr_ccb_complete(ccb, 1);
+-                                      }
+-                                      break;
+-
+-                                      case ARCMSR_DEV_CHECK_CONDITION: {
+-                                                      acb->devstate[id][lun] =
+-                                                       ARECA_RAID_GOOD;
+-                                                      arcmsr_report_sense_info(ccb);
+-                                                      arcmsr_ccb_complete(ccb, 1);
+-                                      }
+-                                      break;
+-
+-                                      default:
+-                                                      printk(KERN_NOTICE
+-                                                              "arcmsr%d: scsi \
+-                                                              id = %d lun = %d"
+-                                                              " polling and \
+-                                                              getting command \
+-                                                              error done"
+-                                                              "but got unknown \
+-                                                      DeviceStatus = 0x%x \n"
+-                                                      , acb->host->host_no,
+-                                                              id, lun,
+-                                              ccb->arcmsr_cdb.DeviceStatus);
+-                                                      acb->devstate[id][lun] =
+-                                                              ARECA_RAID_GONE;
+-                                                      ccb->pcmd->result =
+-                                                      DID_BAD_TARGET << 16;
+-                                                      arcmsr_ccb_complete(ccb, 1);
+-                                      break;
+-                                      }
+-                              }
+-                              found = 1;
+-                      }
+-              }
+-      if (found){
+-              outbound_intstatus = readl(&reg->outbound_intstatus) &
+-                                                      acb->outbound_int_enable;
+-              writel(outbound_intstatus, &reg->outbound_intstatus);
+-              /*clear interrupt*/
+-                  }
+-      return;
+-}
+-
+-
+-static void arcmsr_pci_ers_disconnect_forepart(struct pci_dev *pdev)
+-{
+-      struct Scsi_Host *host = pci_get_drvdata(pdev);
+-      struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+-      struct MessageUnit __iomem *reg = acb->pmu;
+-      struct CommandControlBlock *ccb;
+-      /*clear and abort all outbound posted Q*/
+-      int i = 0, found = 0;
+-      int id, lun;
+-      uint32_t flag_ccb, outbound_intstatus;
+-
+-      while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) &&
+-                                                              (i++ < 256)){
+-                      ccb = (struct CommandControlBlock *)(acb->vir2phy_offset +
+-                                                      (flag_ccb << 5));
+-                      if (ccb){
+-                              if ((ccb->acb != acb)||(ccb->startdone !=
+-                                                      ARCMSR_CCB_START)){
+-                                      printk(KERN_NOTICE
+-                                              "arcmsr%d: polling get an illegal ccb"
+-                                              " command done ccb = '0x%p'"
+-                                              "ccboutstandingcount = %d \n",
+-                                              acb->host->host_no, ccb,
+-                                              atomic_read(&acb->ccboutstandingcount));
+-                                      continue;
+-                      }
+-
+-                      id = ccb->pcmd->device->id;
+-                      lun = ccb->pcmd->device->lun;
+-                      if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR))   {
+-                              if (acb->devstate[id][lun] == ARECA_RAID_GONE)
+-                                      acb->devstate[id][lun] = ARECA_RAID_GOOD;
+-                              ccb->pcmd->result = DID_OK << 16;
+-                              arcmsr_ccb_complete(ccb, 1);
+-                      }
+-                      else {
+-                              switch(ccb->arcmsr_cdb.DeviceStatus) {
+-                              case ARCMSR_DEV_SELECT_TIMEOUT: {
+-                                              acb->devstate[id][lun] =
+-                                                              ARECA_RAID_GONE;
+-                                              ccb->pcmd->result =
+-                                                      DID_NO_CONNECT << 16;
+-                                              arcmsr_ccb_complete(ccb, 1);
+-                              }
+-                              break;
+-
+-                              case ARCMSR_DEV_ABORTED:
+-
+-                              case ARCMSR_DEV_INIT_FAIL: {
+-                                              acb->devstate[id][lun] =
+-                                                              ARECA_RAID_GONE;
+-                                              ccb->pcmd->result =
+-                                                      DID_BAD_TARGET << 16;
+-                                              arcmsr_ccb_complete(ccb, 1);
+-                              }
+-                              break;
+-
+-                              case ARCMSR_DEV_CHECK_CONDITION: {
+-                                              acb->devstate[id][lun] =
+-                                                              ARECA_RAID_GOOD;
+-                                              arcmsr_report_sense_info(ccb);
+-                                              arcmsr_ccb_complete(ccb, 1);
+-                              }
+-                              break;
+-
+-                              default:
+-                                              printk(KERN_NOTICE "arcmsr%d: \
+-                                                      scsi id = %d lun = %d"
+-                                                              " polling and \
+-                                              getting command error done"
+-                                                              "but got unknown \
+-                                               DeviceStatus = 0x%x \n"
+-                                                              , acb->host->host_no,
+-                                      id, lun, ccb->arcmsr_cdb.DeviceStatus);
+-                                                      acb->devstate[id][lun] =
+-                                                              ARECA_RAID_GONE;
+-                                                      ccb->pcmd->result =
+-                                                      DID_BAD_TARGET << 16;
+-                                                      arcmsr_ccb_complete(ccb, 1);
+-                              break;
+-                              }
+-                      }
+-                      found = 1;
+-              }
+-      }
+-      if (found){
+-              outbound_intstatus = readl(&reg->outbound_intstatus) &
+-                                              acb->outbound_int_enable;
+-              writel(outbound_intstatus, &reg->outbound_intstatus);
+-              /*clear interrupt*/
+-      }
+-      return;
+-}
+-
+-static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev,
+-                                              pci_channel_state_t state)
+-{
+-      switch (state) {
+-      case pci_channel_io_frozen:
+-                      arcmsr_pci_ers_need_reset_forepart(pdev);
+-                      return PCI_ERS_RESULT_NEED_RESET;
+-      case pci_channel_io_perm_failure:
+-                      arcmsr_pci_ers_disconnect_forepart(pdev);
+-                      return PCI_ERS_RESULT_DISCONNECT;
+-                      break;
+-      default:
+-                      return PCI_ERS_RESULT_NEED_RESET;
+-      }
+-}
+diff -Nurb linux-2.6.22-590/drivers/scsi/bvme6000.c linux-2.6.22-570/drivers/scsi/bvme6000.c
+--- linux-2.6.22-590/drivers/scsi/bvme6000.c   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/bvme6000.c   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,76 @@
++/*
++ * Detection routine for the NCR53c710 based BVME6000 SCSI Controllers for Linux.
++ *
++ * Based on work by Alan Hourihane
++ */
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/blkdev.h>
++#include <linux/zorro.h>
 +
-+      mutex_lock(&inode->i_mutex);
++#include <asm/setup.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/bvme6000hw.h>
++#include <asm/irq.h>
 +
-+      ret = ocfs2_meta_lock(inode, &di_bh, 1);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out_mutex;
-+      }
++#include "scsi.h"
++#include <scsi/scsi_host.h>
++#include "53c7xx.h"
++#include "bvme6000.h"
 +
-+      handle = ocfs2_start_trans(osb, OCFS2_SUBALLOC_FREE);
-+      if (IS_ERR(handle)) {
-+              ret = PTR_ERR(handle);
-+              mlog_errno(ret);
-+              goto out_unlock;
-+      }
++#include<linux/stat.h>
 +
-+      while (head) {
-+              bg_blkno = ocfs2_which_suballoc_group(head->free_blk,
-+                                                    head->free_bit);
-+              mlog(0, "Free bit: (bit %u, blkno %llu)\n",
-+                   head->free_bit, (unsigned long long)head->free_blk);
 +
-+              ret = ocfs2_free_suballoc_bits(handle, inode, di_bh,
-+                                             head->free_bit, bg_blkno, 1);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out_journal;
-+              }
++int bvme6000_scsi_detect(struct scsi_host_template *tpnt)
++{
++    static unsigned char called = 0;
++    int clock;
++    long long options;
 +
-+              ret = ocfs2_extend_trans(handle, OCFS2_SUBALLOC_FREE);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out_journal;
-+              }
++    if (called)
++      return 0;
++    if (!MACH_IS_BVME6000)
++      return 0;
 +
-+              tmp = head;
-+              head = head->free_next;
-+              kfree(tmp);
-+      }
++    tpnt->proc_name = "BVME6000";
 +
-+out_journal:
-+      ocfs2_commit_trans(osb, handle);
++    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
 +
-+out_unlock:
-+      ocfs2_meta_unlock(inode, 1);
-+      brelse(di_bh);
-+out_mutex:
-+      mutex_unlock(&inode->i_mutex);
-+      iput(inode);
-+out:
-+      while(head) {
-+              /* Premature exit may have left some dangling items. */
-+              tmp = head;
-+              head = head->free_next;
-+              kfree(tmp);
-+      }
++    clock = 40000000; /* 66MHz SCSI Clock */
 +
-+      return ret;
++    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)BVME_NCR53C710_BASE,
++                      0, BVME_IRQ_SCSI, DMA_NONE,
++                      options, clock);
++    called = 1;
++    return 1;
 +}
 +
-+int ocfs2_run_deallocs(struct ocfs2_super *osb,
-+                     struct ocfs2_cached_dealloc_ctxt *ctxt)
++static int bvme6000_scsi_release(struct Scsi_Host *shost)
 +{
-+      int ret = 0, ret2;
-+      struct ocfs2_per_slot_free_list *fl;
-+
-+      if (!ctxt)
-+              return 0;
-+
-+      while (ctxt->c_first_suballocator) {
-+              fl = ctxt->c_first_suballocator;
-+
-+              if (fl->f_first) {
-+                      mlog(0, "Free items: (type %u, slot %d)\n",
-+                           fl->f_inode_type, fl->f_slot);
-+                      ret2 = ocfs2_free_cached_items(osb, fl->f_inode_type,
-+                                                     fl->f_slot, fl->f_first);
-+                      if (ret2)
-+                              mlog_errno(ret2);
-+                      if (!ret)
-+                              ret = ret2;
-+              }
++      if (shost->irq)
++              free_irq(shost->irq, NULL);
++      if (shost->dma_channel != 0xff)
++              free_dma(shost->dma_channel);
++      if (shost->io_port && shost->n_io_port)
++              release_region(shost->io_port, shost->n_io_port);
++      scsi_unregister(shost);
++      return 0;
++}
 +
-+              ctxt->c_first_suballocator = fl->f_next_suballocator;
-+              kfree(fl);
-+      }
++static struct scsi_host_template driver_template = {
++      .name                   = "BVME6000 NCR53c710 SCSI",
++      .detect                 = bvme6000_scsi_detect,
++      .release                = bvme6000_scsi_release,
++      .queuecommand           = NCR53c7xx_queue_command,
++      .abort                  = NCR53c7xx_abort,
++      .reset                  = NCR53c7xx_reset,
++      .can_queue              = 24,
++      .this_id                = 7,
++      .sg_tablesize           = 63,
++      .cmd_per_lun            = 3,
++      .use_clustering         = DISABLE_CLUSTERING
++};
 +
-+      return ret;
-+}
 +
-+static struct ocfs2_per_slot_free_list *
-+ocfs2_find_per_slot_free_list(int type,
-+                            int slot,
-+                            struct ocfs2_cached_dealloc_ctxt *ctxt)
-+{
-+      struct ocfs2_per_slot_free_list *fl = ctxt->c_first_suballocator;
++#include "scsi_module.c"
+diff -Nurb linux-2.6.22-590/drivers/scsi/bvme6000.h linux-2.6.22-570/drivers/scsi/bvme6000.h
+--- linux-2.6.22-590/drivers/scsi/bvme6000.h   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/bvme6000.h   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,24 @@
++#ifndef BVME6000_SCSI_H
++#define BVME6000_SCSI_H
 +
-+      while (fl) {
-+              if (fl->f_inode_type == type && fl->f_slot == slot)
-+                      return fl;
++#include <linux/types.h>
 +
-+              fl = fl->f_next_suballocator;
-+      }
++int bvme6000_scsi_detect(struct scsi_host_template *);
++const char *NCR53c7x0_info(void);
++int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
++int NCR53c7xx_abort(Scsi_Cmnd *);
++int NCR53c7x0_release (struct Scsi_Host *);
++int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
++void NCR53c7x0_intr(int irq, void *dev_id);
 +
-+      fl = kmalloc(sizeof(*fl), GFP_NOFS);
-+      if (fl) {
-+              fl->f_inode_type = type;
-+              fl->f_slot = slot;
-+              fl->f_first = NULL;
-+              fl->f_next_suballocator = ctxt->c_first_suballocator;
++#ifndef CMD_PER_LUN
++#define CMD_PER_LUN 3
++#endif
 +
-+              ctxt->c_first_suballocator = fl;
-+      }
-+      return fl;
-+}
++#ifndef CAN_QUEUE
++#define CAN_QUEUE 24
++#endif
 +
-+static int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
-+                                   int type, int slot, u64 blkno,
-+                                   unsigned int bit)
-+{
-+      int ret;
-+      struct ocfs2_per_slot_free_list *fl;
-+      struct ocfs2_cached_block_free *item;
++#include <scsi/scsicam.h>
 +
-+      fl = ocfs2_find_per_slot_free_list(type, slot, ctxt);
-+      if (fl == NULL) {
-+              ret = -ENOMEM;
-+              mlog_errno(ret);
-+              goto out;
++#endif /* BVME6000_SCSI_H */
+diff -Nurb linux-2.6.22-590/drivers/scsi/bvme6000_scsi.c linux-2.6.22-570/drivers/scsi/bvme6000_scsi.c
+--- linux-2.6.22-590/drivers/scsi/bvme6000_scsi.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/bvme6000_scsi.c      1969-12-31 19:00:00.000000000 -0500
+@@ -1,135 +0,0 @@
+-/*
+- * Detection routine for the NCR53c710 based BVME6000 SCSI Controllers for Linux.
+- *
+- * Based on work by Alan Hourihane and Kars de Jong
+- *
+- * Rewritten to use 53c700.c by Richard Hirst <richard@sleepie.demon.co.uk>
+- */
+-
+-#include <linux/module.h>
+-#include <linux/blkdev.h>
+-#include <linux/device.h>
+-#include <linux/platform_device.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <asm/bvme6000hw.h>
+-#include <scsi/scsi_host.h>
+-#include <scsi/scsi_device.h>
+-#include <scsi/scsi_transport.h>
+-#include <scsi/scsi_transport_spi.h>
+-
+-#include "53c700.h"
+-
+-MODULE_AUTHOR("Richard Hirst <richard@sleepie.demon.co.uk>");
+-MODULE_DESCRIPTION("BVME6000 NCR53C710 driver");
+-MODULE_LICENSE("GPL");
+-
+-static struct scsi_host_template bvme6000_scsi_driver_template = {
+-      .name                   = "BVME6000 NCR53c710 SCSI",
+-      .proc_name              = "BVME6000",
+-      .this_id                = 7,
+-      .module                 = THIS_MODULE,
+-};
+-
+-static struct platform_device *bvme6000_scsi_device;
+-
+-static __devinit int
+-bvme6000_probe(struct device *dev)
+-{
+-      struct Scsi_Host * host = NULL;
+-      struct NCR_700_Host_Parameters *hostdata;
+-
+-      if (!MACH_IS_BVME6000)
+-              goto out;
+-
+-      hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+-      if (hostdata == NULL) {
+-              printk(KERN_ERR "bvme6000-scsi: "
+-                              "Failed to allocate host data\n");
+-              goto out;
+-      }
+-      memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
+-
+-      /* Fill in the required pieces of hostdata */
+-      hostdata->base = (void __iomem *)BVME_NCR53C710_BASE;
+-      hostdata->clock = 40;   /* XXX - depends on the CPU clock! */
+-      hostdata->chip710 = 1;
+-      hostdata->dmode_extra = DMODE_FC2;
+-      hostdata->dcntl_extra = EA_710;
+-      hostdata->ctest7_extra = CTEST7_TT1;
+-
+-      /* and register the chip */
+-      host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata, dev);
+-      if (!host) {
+-              printk(KERN_ERR "bvme6000-scsi: No host detected; "
+-                              "board configuration problem?\n");
+-              goto out_free;
+-      }
+-      host->base = BVME_NCR53C710_BASE;
+-      host->this_id = 7;
+-      host->irq = BVME_IRQ_SCSI;
+-      if (request_irq(BVME_IRQ_SCSI, NCR_700_intr, 0, "bvme6000-scsi",
+-                      host)) {
+-              printk(KERN_ERR "bvme6000-scsi: request_irq failed\n");
+-              goto out_put_host;
+-      }
+-
+-      scsi_scan_host(host);
+-
+-      return 0;
+-
+- out_put_host:
+-      scsi_host_put(host);
+- out_free:
+-      kfree(hostdata);
+- out:
+-      return -ENODEV;
+-}
+-
+-static __devexit int
+-bvme6000_device_remove(struct device *dev)
+-{
+-      struct Scsi_Host *host = dev_to_shost(dev);
+-      struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
+-
+-      scsi_remove_host(host);
+-      NCR_700_release(host);
+-      kfree(hostdata);
+-      free_irq(host->irq, host);
+-
+-      return 0;
+-}
+-
+-static struct device_driver bvme6000_scsi_driver = {
+-      .name   = "bvme6000-scsi",
+-      .bus    = &platform_bus_type,
+-      .probe  = bvme6000_probe,
+-      .remove = __devexit_p(bvme6000_device_remove),
+-};
+-
+-static int __init bvme6000_scsi_init(void)
+-{
+-      int err;
+-
+-      err = driver_register(&bvme6000_scsi_driver);
+-      if (err)
+-              return err;
+-
+-      bvme6000_scsi_device = platform_device_register_simple("bvme6000-scsi",
+-                                                             -1, NULL, 0);
+-      if (IS_ERR(bvme6000_scsi_device)) {
+-              driver_unregister(&bvme6000_scsi_driver);
+-              return PTR_ERR(bvme6000_scsi_device);
+-      }
+-
+-      return 0;
+-}
+-
+-static void __exit bvme6000_scsi_exit(void)
+-{
+-      platform_device_unregister(bvme6000_scsi_device);
+-      driver_unregister(&bvme6000_scsi_driver);
+-}
+-
+-module_init(bvme6000_scsi_init);
+-module_exit(bvme6000_scsi_exit);
+diff -Nurb linux-2.6.22-590/drivers/scsi/dpt_i2o.c linux-2.6.22-570/drivers/scsi/dpt_i2o.c
+--- linux-2.6.22-590/drivers/scsi/dpt_i2o.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/dpt_i2o.c    2007-07-08 19:32:17.000000000 -0400
+@@ -2078,13 +2078,12 @@
+       u32 *lenptr;
+       int direction;
+       int scsidir;
+-      int nseg;
+       u32 len;
+       u32 reqlen;
+       s32 rcode;
+       memset(msg, 0 , sizeof(msg));
+-      len = scsi_bufflen(cmd);
++      len = cmd->request_bufflen;
+       direction = 0x00000000; 
+       
+       scsidir = 0x00000000;                   // DATA NO XFER
+@@ -2141,21 +2140,21 @@
+       lenptr=mptr++;          /* Remember me - fill in when we know */
+       reqlen = 14;            // SINGLE SGE
+       /* Now fill in the SGList and command */
++      if(cmd->use_sg) {
++              struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer;
++              int sg_count = pci_map_sg(pHba->pDev, sg, cmd->use_sg,
++                              cmd->sc_data_direction);
+-      nseg = scsi_dma_map(cmd);
+-      BUG_ON(nseg < 0);
+-      if (nseg) {
+-              struct scatterlist *sg;
+               len = 0;
+-              scsi_for_each_sg(cmd, sg, nseg, i) {
++              for(i = 0 ; i < sg_count; i++) {
+                       *mptr++ = direction|0x10000000|sg_dma_len(sg);
+                       len+=sg_dma_len(sg);
+                       *mptr++ = sg_dma_address(sg);
+-              /* Make this an end of list */
+-                      if (i == nseg - 1)
+-                              mptr[-2] = direction|0xD0000000|sg_dma_len(sg);
++                      sg++;
+               }
++              /* Make this an end of list */
++              mptr[-2] = direction|0xD0000000|sg_dma_len(sg-1);
+               reqlen = mptr - msg;
+               *lenptr = len;
+               
+@@ -2164,8 +2163,16 @@
+                               len, cmd->underflow);
+               }
+       } else {
+-              *lenptr = len = 0;
++              *lenptr = len = cmd->request_bufflen;
++              if(len == 0) {
+                       reqlen = 12;
++              } else {
++                      *mptr++ = 0xD0000000|direction|cmd->request_bufflen;
++                      *mptr++ = pci_map_single(pHba->pDev,
++                              cmd->request_buffer,
++                              cmd->request_bufflen,
++                              cmd->sc_data_direction);
++              }
+       }
+       
+       /* Stick the headers on */
+@@ -2225,7 +2232,7 @@
+       hba_status = detailed_status >> 8;
+       // calculate resid for sg 
+-      scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+5));
++      cmd->resid = cmd->request_bufflen - readl(reply+5);
+       pHba = (adpt_hba*) cmd->device->host->hostdata[0];
+diff -Nurb linux-2.6.22-590/drivers/scsi/eata.c linux-2.6.22-570/drivers/scsi/eata.c
+--- linux-2.6.22-590/drivers/scsi/eata.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/eata.c       2007-07-08 19:32:17.000000000 -0400
+@@ -1609,9 +1609,8 @@
+ static void map_dma(unsigned int i, struct hostdata *ha)
+ {
+-      unsigned int k, pci_dir;
+-      int count;
+-      struct scatterlist *sg;
++      unsigned int k, count, pci_dir;
++      struct scatterlist *sgpnt;
+       struct mscp *cpp;
+       struct scsi_cmnd *SCpnt;
+@@ -1626,19 +1625,38 @@
+       cpp->sense_len = sizeof SCpnt->sense_buffer;
+-      count = scsi_dma_map(SCpnt);
+-      BUG_ON(count < 0);
+-      scsi_for_each_sg(SCpnt, sg, count, k) {
+-              cpp->sglist[k].address = H2DEV(sg_dma_address(sg));
+-              cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(sg));
++      if (!SCpnt->use_sg) {
++
++              /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */
++              if (!SCpnt->request_bufflen)
++                      pci_dir = PCI_DMA_BIDIRECTIONAL;
++
++              if (SCpnt->request_buffer)
++                      cpp->data_address = H2DEV(pci_map_single(ha->pdev,
++                                                               SCpnt->
++                                                               request_buffer,
++                                                               SCpnt->
++                                                               request_bufflen,
++                                                               pci_dir));
++
++              cpp->data_len = H2DEV(SCpnt->request_bufflen);
++              return;
 +      }
 +
-+      item = kmalloc(sizeof(*item), GFP_NOFS);
-+      if (item == NULL) {
-+              ret = -ENOMEM;
-+              mlog_errno(ret);
-+              goto out;
-+      }
++      sgpnt = (struct scatterlist *)SCpnt->request_buffer;
++      count = pci_map_sg(ha->pdev, sgpnt, SCpnt->use_sg, pci_dir);
 +
-+      mlog(0, "Insert: (type %d, slot %u, bit %u, blk %llu)\n",
-+           type, slot, bit, (unsigned long long)blkno);
++      for (k = 0; k < count; k++) {
++              cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
++              cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
+       }
+       cpp->sg = 1;
+       cpp->data_address = H2DEV(pci_map_single(ha->pdev, cpp->sglist,
+-                                               scsi_sg_count(SCpnt) *
++                                               SCpnt->use_sg *
+                                                sizeof(struct sg_list),
+                                                pci_dir));
+-      cpp->data_len = H2DEV((scsi_sg_count(SCpnt) * sizeof(struct sg_list)));
++      cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list)));
+ }
+ static void unmap_dma(unsigned int i, struct hostdata *ha)
+@@ -1655,7 +1673,9 @@
+               pci_unmap_single(ha->pdev, DEV2H(cpp->sense_addr),
+                                DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+-      scsi_dma_unmap(SCpnt);
++      if (SCpnt->use_sg)
++              pci_unmap_sg(ha->pdev, SCpnt->request_buffer, SCpnt->use_sg,
++                           pci_dir);
+       if (!DEV2H(cpp->data_len))
+               pci_dir = PCI_DMA_BIDIRECTIONAL;
+@@ -1680,9 +1700,9 @@
+                                           DEV2H(cpp->sense_len),
+                                           PCI_DMA_FROMDEVICE);
+-      if (scsi_sg_count(SCpnt))
+-              pci_dma_sync_sg_for_cpu(ha->pdev, scsi_sglist(SCpnt),
+-                                      scsi_sg_count(SCpnt), pci_dir);
++      if (SCpnt->use_sg)
++              pci_dma_sync_sg_for_cpu(ha->pdev, SCpnt->request_buffer,
++                                      SCpnt->use_sg, pci_dir);
+       if (!DEV2H(cpp->data_len))
+               pci_dir = PCI_DMA_BIDIRECTIONAL;
+diff -Nurb linux-2.6.22-590/drivers/scsi/esp_scsi.c linux-2.6.22-570/drivers/scsi/esp_scsi.c
+--- linux-2.6.22-590/drivers/scsi/esp_scsi.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/esp_scsi.c   2008-01-23 19:15:55.000000000 -0500
+@@ -324,14 +324,17 @@
+ static void esp_map_dma(struct esp *esp, struct scsi_cmnd *cmd)
+ {
+       struct esp_cmd_priv *spriv = ESP_CMD_PRIV(cmd);
+-      struct scatterlist *sg = scsi_sglist(cmd);
++      struct scatterlist *sg = cmd->request_buffer;
+       int dir = cmd->sc_data_direction;
+       int total, i;
+       if (dir == DMA_NONE)
+               return;
+-      spriv->u.num_sg = esp->ops->map_sg(esp, sg, scsi_sg_count(cmd), dir);
++      BUG_ON(cmd->use_sg == 0);
 +
-+      item->free_blk = blkno;
-+      item->free_bit = bit;
-+      item->free_next = fl->f_first;
++      spriv->u.num_sg = esp->ops->map_sg(esp, sg,
++                                         cmd->use_sg, dir);
+       spriv->cur_residue = sg_dma_len(sg);
+       spriv->cur_sg = sg;
+@@ -404,7 +407,8 @@
+       if (dir == DMA_NONE)
+               return;
+-      esp->ops->unmap_sg(esp, scsi_sglist(cmd), spriv->u.num_sg, dir);
++      esp->ops->unmap_sg(esp, cmd->request_buffer,
++                         spriv->u.num_sg, dir);
+ }
+ static void esp_save_pointers(struct esp *esp, struct esp_cmd_entry *ent)
+@@ -917,7 +921,7 @@
+ static int esp_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+ {
+       struct scsi_device *dev = cmd->device;
+-      struct esp *esp = shost_priv(dev->host);
++      struct esp *esp = host_to_esp(dev->host);
+       struct esp_cmd_priv *spriv;
+       struct esp_cmd_entry *ent;
+@@ -2354,7 +2358,7 @@
+ static int esp_slave_alloc(struct scsi_device *dev)
+ {
+-      struct esp *esp = shost_priv(dev->host);
++      struct esp *esp = host_to_esp(dev->host);
+       struct esp_target_data *tp = &esp->target[dev->id];
+       struct esp_lun_data *lp;
+@@ -2378,7 +2382,7 @@
+ static int esp_slave_configure(struct scsi_device *dev)
+ {
+-      struct esp *esp = shost_priv(dev->host);
++      struct esp *esp = host_to_esp(dev->host);
+       struct esp_target_data *tp = &esp->target[dev->id];
+       int goal_tags, queue_depth;
+@@ -2420,7 +2424,7 @@
+ static int esp_eh_abort_handler(struct scsi_cmnd *cmd)
+ {
+-      struct esp *esp = shost_priv(cmd->device->host);
++      struct esp *esp = host_to_esp(cmd->device->host);
+       struct esp_cmd_entry *ent, *tmp;
+       struct completion eh_done;
+       unsigned long flags;
+@@ -2536,7 +2540,7 @@
+ static int esp_eh_bus_reset_handler(struct scsi_cmnd *cmd)
+ {
+-      struct esp *esp = shost_priv(cmd->device->host);
++      struct esp *esp = host_to_esp(cmd->device->host);
+       struct completion eh_reset;
+       unsigned long flags;
+@@ -2572,7 +2576,7 @@
+ /* All bets are off, reset the entire device.  */
+ static int esp_eh_host_reset_handler(struct scsi_cmnd *cmd)
+ {
+-      struct esp *esp = shost_priv(cmd->device->host);
++      struct esp *esp = host_to_esp(cmd->device->host);
+       unsigned long flags;
+       spin_lock_irqsave(esp->host->host_lock, flags);
+@@ -2612,7 +2616,7 @@
+ static void esp_get_signalling(struct Scsi_Host *host)
+ {
+-      struct esp *esp = shost_priv(host);
++      struct esp *esp = host_to_esp(host);
+       enum spi_signal_type type;
+       if (esp->flags & ESP_FLAG_DIFFERENTIAL)
+@@ -2626,7 +2630,7 @@
+ static void esp_set_offset(struct scsi_target *target, int offset)
+ {
+       struct Scsi_Host *host = dev_to_shost(target->dev.parent);
+-      struct esp *esp = shost_priv(host);
++      struct esp *esp = host_to_esp(host);
+       struct esp_target_data *tp = &esp->target[target->id];
+       tp->nego_goal_offset = offset;
+@@ -2636,7 +2640,7 @@
+ static void esp_set_period(struct scsi_target *target, int period)
+ {
+       struct Scsi_Host *host = dev_to_shost(target->dev.parent);
+-      struct esp *esp = shost_priv(host);
++      struct esp *esp = host_to_esp(host);
+       struct esp_target_data *tp = &esp->target[target->id];
+       tp->nego_goal_period = period;
+@@ -2646,7 +2650,7 @@
+ static void esp_set_width(struct scsi_target *target, int width)
+ {
+       struct Scsi_Host *host = dev_to_shost(target->dev.parent);
+-      struct esp *esp = shost_priv(host);
++      struct esp *esp = host_to_esp(host);
+       struct esp_target_data *tp = &esp->target[target->id];
+       tp->nego_goal_width = (width ? 1 : 0);
+diff -Nurb linux-2.6.22-590/drivers/scsi/esp_scsi.h linux-2.6.22-570/drivers/scsi/esp_scsi.h
+--- linux-2.6.22-590/drivers/scsi/esp_scsi.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/esp_scsi.h   2007-07-08 19:32:17.000000000 -0400
+@@ -517,6 +517,8 @@
+       struct sbus_dma         *dma;
+ };
++#define host_to_esp(host)     ((struct esp *)(host)->hostdata)
 +
-+      fl->f_first = item;
+ /* A front-end driver for the ESP chip should do the following in
+  * it's device probe routine:
+  * 1) Allocate the host and private area using scsi_host_alloc()
+diff -Nurb linux-2.6.22-590/drivers/scsi/fdomain.c linux-2.6.22-570/drivers/scsi/fdomain.c
+--- linux-2.6.22-590/drivers/scsi/fdomain.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/fdomain.c    2007-07-08 19:32:17.000000000 -0400
+@@ -410,8 +410,6 @@
+ static char * fdomain = NULL;
+ module_param(fdomain, charp, 0);
+-#ifndef PCMCIA
+-
+ static unsigned long addresses[] = {
+    0xc8000,
+    0xca000,
+@@ -428,8 +426,6 @@
+ static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
+-#endif /* !PCMCIA */
+-
+ /*
+   READ THIS BEFORE YOU ADD A SIGNATURE!
+@@ -462,8 +458,6 @@
+ */
+-#ifndef PCMCIA
+-
+ static struct signature {
+    const char *signature;
+    int  sig_offset;
+@@ -509,8 +503,6 @@
+ #define SIGNATURE_COUNT ARRAY_SIZE(signatures)
+-#endif /* !PCMCIA */
+-
+ static void print_banner( struct Scsi_Host *shpnt )
+ {
+    if (!shpnt) return;                /* This won't ever happen */
+@@ -641,8 +633,6 @@
+    return 0;
+ }
+-#ifndef PCMCIA
+-
+ /* fdomain_get_irq assumes that we have a valid MCA ID for a
+    TMC-1660/TMC-1680 Future Domain board.  Now, check to be sure the
+    bios_base matches these ports.  If someone was unlucky enough to have
+@@ -677,6 +667,7 @@
+ static int fdomain_isa_detect( int *irq, int *iobase )
+ {
++#ifndef PCMCIA
+    int i, j;
+    int base = 0xdeadbeef;
+    int flag = 0;
+@@ -795,22 +786,11 @@
+    *iobase = base;
+    return 1;                  /* success */
+-}
+-
+-#else /* PCMCIA */
+-
+-static int fdomain_isa_detect( int *irq, int *iobase )
+-{
+-      if (irq)
+-              *irq = 0;
+-      if (iobase)
+-              *iobase = 0;
++#else
+    return 0;
++#endif
+ }
+-#endif /* !PCMCIA */
+-
+-
+ /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int*
+    iobase) This function gets the Interrupt Level and I/O base address from
+    the PCI configuration registers. */
+@@ -1365,15 +1345,16 @@
+ #if ERRORS_ONLY
+       if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
+-            char *buf = scsi_sglist(current_SC);
+-       if ((unsigned char)(*(buf + 2)) & 0x0f) {
++       if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) {
+           unsigned char key;
+           unsigned char code;
+           unsigned char qualifier;
+-          key = (unsigned char)(*(buf + 2)) & 0x0f;
+-          code = (unsigned char)(*(buf + 12));
+-          qualifier = (unsigned char)(*(buf + 13));
++          key = (unsigned char)(*((char *)current_SC->request_buffer + 2))
++                & 0x0f;
++          code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
++          qualifier = (unsigned char)(*((char *)current_SC->request_buffer
++                                        + 13));
+           if (key != UNIT_ATTENTION
+               && !(key == NOT_READY
+@@ -1424,8 +1405,8 @@
+    printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
+          SCpnt->target,
+          *(unsigned char *)SCpnt->cmnd,
+-         scsi_sg_count(SCpnt),
+-         scsi_bufflen(SCpnt));
++         SCpnt->use_sg,
++         SCpnt->request_bufflen );
+ #endif
+    fdomain_make_bus_idle();
+@@ -1435,19 +1416,20 @@
+    /* Initialize static data */
+-   if (scsi_sg_count(current_SC)) {
+-         current_SC->SCp.buffer = scsi_sglist(current_SC);
+-         current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page)
+-                 + current_SC->SCp.buffer->offset;
++   if (current_SC->use_sg) {
++      current_SC->SCp.buffer =
++          (struct scatterlist *)current_SC->request_buffer;
++      current_SC->SCp.ptr              = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
+       current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
+-         current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
++      current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
+    } else {
+-         current_SC->SCp.ptr              = 0;
+-         current_SC->SCp.this_residual    = 0;
++      current_SC->SCp.ptr              = (char *)current_SC->request_buffer;
++      current_SC->SCp.this_residual    = current_SC->request_bufflen;
+       current_SC->SCp.buffer           = NULL;
+       current_SC->SCp.buffers_residual = 0;
+    }
+        
++   
+    current_SC->SCp.Status              = 0;
+    current_SC->SCp.Message             = 0;
+    current_SC->SCp.have_data_in        = 0;
+@@ -1490,8 +1472,8 @@
+          SCpnt->SCp.phase,
+          SCpnt->device->id,
+          *(unsigned char *)SCpnt->cmnd,
+-         scsi_sg_count(SCpnt),
+-         scsi_bufflen(SCpnt));
++         SCpnt->use_sg,
++         SCpnt->request_bufflen );
+    printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
+          SCpnt->SCp.sent_command,
+          SCpnt->SCp.have_data_in,
+diff -Nurb linux-2.6.22-590/drivers/scsi/gdth.c linux-2.6.22-570/drivers/scsi/gdth.c
+--- linux-2.6.22-590/drivers/scsi/gdth.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/gdth.c       2007-07-08 19:32:17.000000000 -0400
+@@ -876,7 +876,7 @@
+ /* Vortex only makes RAID controllers.
+  * We do not really want to specify all 550 ids here, so wildcard match.
+  */
+-static struct pci_device_id gdthtable[] __maybe_unused = {
++static struct pci_device_id gdthtable[] __attribute_used__ = {
+     {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
+     {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, 
+     {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, 
+@@ -1955,7 +1955,7 @@
+         for (j = 0; j < 12; ++j) 
+             rtc[j] = CMOS_READ(j);
+     } while (rtc[0] != CMOS_READ(0));
+-    spin_unlock_irqrestore(&rtc_lock, flags);
++    spin_lock_irqrestore(&rtc_lock, flags);
+     TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0],
+             *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]));
+     /* 3. send to controller firmware */
+diff -Nurb linux-2.6.22-590/drivers/scsi/hptiop.c linux-2.6.22-570/drivers/scsi/hptiop.c
+--- linux-2.6.22-590/drivers/scsi/hptiop.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/hptiop.c     2008-01-23 19:15:55.000000000 -0500
+@@ -339,8 +339,20 @@
+       scp = hba->reqs[tag].scp;
+-      if (HPT_SCP(scp)->mapped)
+-              scsi_dma_unmap(scp);
++      if (HPT_SCP(scp)->mapped) {
++              if (scp->use_sg)
++                      pci_unmap_sg(hba->pcidev,
++                              (struct scatterlist *)scp->request_buffer,
++                              scp->use_sg,
++                              scp->sc_data_direction
++                      );
++              else
++                      pci_unmap_single(hba->pcidev,
++                              HPT_SCP(scp)->dma_handle,
++                              scp->request_bufflen,
++                              scp->sc_data_direction
++                      );
++      }
+       switch (le32_to_cpu(req->header.result)) {
+       case IOP_RESULT_SUCCESS:
+@@ -437,26 +449,43 @@
+ {
+       struct Scsi_Host *host = scp->device->host;
+       struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+-      struct scatterlist *sg;
+-      int idx, nseg;
++      struct scatterlist *sglist = (struct scatterlist *)scp->request_buffer;
+-      nseg = scsi_dma_map(scp);
+-      BUG_ON(nseg < 0);
+-      if (!nseg)
+-              return 0;
+-
+-      HPT_SCP(scp)->sgcnt = nseg;
++      /*
++       * though we'll not get non-use_sg fields anymore,
++       * keep use_sg checking anyway
++       */
++      if (scp->use_sg) {
++              int idx;
 +
-+      ret = 0;
-+out:
-+      return ret;
-+}
++              HPT_SCP(scp)->sgcnt = pci_map_sg(hba->pcidev,
++                              sglist, scp->use_sg,
++                              scp->sc_data_direction);
+               HPT_SCP(scp)->mapped = 1;
+-
+               BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors);
+-      scsi_for_each_sg(scp, sg, HPT_SCP(scp)->sgcnt, idx) {
+-              psg[idx].pci_address = cpu_to_le64(sg_dma_address(sg));
+-              psg[idx].size = cpu_to_le32(sg_dma_len(sg));
++              for (idx = 0; idx < HPT_SCP(scp)->sgcnt; idx++) {
++                      psg[idx].pci_address =
++                              cpu_to_le64(sg_dma_address(&sglist[idx]));
++                      psg[idx].size = cpu_to_le32(sg_dma_len(&sglist[idx]));
+                       psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ?
+                               cpu_to_le32(1) : 0;
+               }
 +
-+static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
-+                                       struct ocfs2_extent_block *eb)
-+{
-+      return ocfs2_cache_block_dealloc(ctxt, EXTENT_ALLOC_SYSTEM_INODE,
-+                                       le16_to_cpu(eb->h_suballoc_slot),
-+                                       le64_to_cpu(eb->h_blkno),
-+                                       le16_to_cpu(eb->h_suballoc_bit));
-+}
+               return HPT_SCP(scp)->sgcnt;
++      } else {
++              HPT_SCP(scp)->dma_handle = pci_map_single(
++                              hba->pcidev,
++                              scp->request_buffer,
++                              scp->request_bufflen,
++                              scp->sc_data_direction
++                      );
++              HPT_SCP(scp)->mapped = 1;
++              psg->pci_address = cpu_to_le64(HPT_SCP(scp)->dma_handle);
++              psg->size = cpu_to_le32(scp->request_bufflen);
++              psg->eot = cpu_to_le32(1);
++              return 1;
++      }
+ }
+ static int hptiop_queuecommand(struct scsi_cmnd *scp,
+@@ -501,8 +530,9 @@
+       req = (struct hpt_iop_request_scsi_command *)_req->req_virt;
+       /* build S/G table */
++      if (scp->request_bufflen)
+               sg_count = hptiop_buildsgl(scp, req->sg_list);
+-      if (!sg_count)
++      else
+               HPT_SCP(scp)->mapped = 0;
+       req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);
+@@ -511,7 +541,7 @@
+       req->header.context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT |
+                                                       (u32)_req->index);
+       req->header.context_hi32 = 0;
+-      req->dataxfer_length = cpu_to_le32(scsi_bufflen(scp));
++      req->dataxfer_length = cpu_to_le32(scp->request_bufflen);
+       req->channel = scp->device->channel;
+       req->target = scp->device->id;
+       req->lun = scp->device->lun;
+diff -Nurb linux-2.6.22-590/drivers/scsi/ibmmca.c linux-2.6.22-570/drivers/scsi/ibmmca.c
+--- linux-2.6.22-590/drivers/scsi/ibmmca.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/ibmmca.c     2007-07-08 19:32:17.000000000 -0400
+@@ -31,21 +31,14 @@
+ #include <linux/mca.h>
+ #include <linux/spinlock.h>
+ #include <linux/init.h>
++#include <linux/mca-legacy.h>
+ #include <asm/system.h>
+ #include <asm/io.h>
+ #include "scsi.h"
+ #include <scsi/scsi_host.h>
+-
+-/* Common forward declarations for all Linux-versions: */
+-static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
+-static int ibmmca_abort (Scsi_Cmnd *);
+-static int ibmmca_host_reset (Scsi_Cmnd *);
+-static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *);
+-static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout);
+-
+-
++#include "ibmmca.h"
+ /* current version of this driver-source: */
+ #define IBMMCA_SCSI_DRIVER_VERSION "4.0b-ac"
+@@ -72,11 +65,11 @@
+ #define IM_DEBUG_CMD_DEVICE   TYPE_TAPE
+ /* relative addresses of hardware registers on a subsystem */
+-#define IM_CMD_REG(h) ((h)->io_port)  /*Command Interface, (4 bytes long) */
+-#define IM_ATTN_REG(h)        ((h)->io_port+4)        /*Attention (1 byte) */
+-#define IM_CTR_REG(h) ((h)->io_port+5)        /*Basic Control (1 byte) */
+-#define IM_INTR_REG(h)        ((h)->io_port+6)        /*Interrupt Status (1 byte, r/o) */
+-#define IM_STAT_REG(h)        ((h)->io_port+7)        /*Basic Status (1 byte, read only) */
++#define IM_CMD_REG(hi)        (hosts[(hi)]->io_port)  /*Command Interface, (4 bytes long) */
++#define IM_ATTN_REG(hi)       (hosts[(hi)]->io_port+4)        /*Attention (1 byte) */
++#define IM_CTR_REG(hi)        (hosts[(hi)]->io_port+5)        /*Basic Control (1 byte) */
++#define IM_INTR_REG(hi)       (hosts[(hi)]->io_port+6)        /*Interrupt Status (1 byte, r/o) */
++#define IM_STAT_REG(hi)       (hosts[(hi)]->io_port+7)        /*Basic Status (1 byte, read only) */
+ /* basic I/O-port of first adapter */
+ #define IM_IO_PORT    0x3540
+@@ -273,36 +266,30 @@
+     if ((display_mode & LED_ACTIVITY)||(!display_mode)) \
+     outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); }
++/*list of supported subsystems */
++struct subsys_list_struct {
++      unsigned short mca_id;
++      char *description;
++};
 +
- /* This function will figure out whether the currently last extent
-  * block will be deleted, and if it will, what the new last extent
-  * block will be so we can update his h_next_leaf_blk field, as well
-@@ -3238,27 +4914,10 @@
-                       BUG_ON(le32_to_cpu(el->l_recs[0].e_cpos));
-                       BUG_ON(le64_to_cpu(el->l_recs[0].e_blkno));
+ /* types of different supported hardware that goes to hostdata special */
+ #define IBM_SCSI2_FW     0
+ #define IBM_7568_WCACHE  1
+ #define IBM_EXP_UNIT     2
+ #define IBM_SCSI_WCACHE  3
+ #define IBM_SCSI         4
+-#define IBM_INTEGSCSI  5
+ /* other special flags for hostdata structure */
+ #define FORCED_DETECTION         100
+ #define INTEGRATED_SCSI          101
+ /* List of possible IBM-SCSI-adapters */
+-static short ibmmca_id_table[] = {
+-      0x8efc,
+-      0x8efd,
+-      0x8ef8,
+-      0x8eff,
+-      0x8efe,
+-      /* No entry for integrated SCSI, that's part of the register */
+-      0
+-};
+-
+-static const char *ibmmca_description[] = {
+-      "IBM SCSI-2 F/W Adapter",       /* special = 0 */
+-      "IBM 7568 Industrial Computer SCSI Adapter w/Cache",    /* special = 1 */
+-      "IBM Expansion Unit SCSI Controller",   /* special = 2 */
+-      "IBM SCSI Adapter w/Cache",     /* special = 3 */
+-      "IBM SCSI Adapter",     /* special = 4 */
+-      "IBM Integrated SCSI Controller", /* special = 5 */
++static struct subsys_list_struct subsys_list[] = {
++      {0x8efc, "IBM SCSI-2 F/W Adapter"},     /* special = 0 */
++      {0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/Cache"},  /* special = 1 */
++      {0x8ef8, "IBM Expansion Unit SCSI Controller"}, /* special = 2 */
++      {0x8eff, "IBM SCSI Adapter w/Cache"},   /* special = 3 */
++      {0x8efe, "IBM SCSI Adapter"},   /* special = 4 */
+ };
+ /* Max number of logical devices (can be up from 0 to 14).  15 is the address
+@@ -388,30 +375,30 @@
+ };
  
--                      if (le16_to_cpu(eb->h_suballoc_slot) == 0) {
--                              /*
--                               * This code only understands how to
--                               * lock the suballocator in slot 0,
--                               * which is fine because allocation is
--                               * only ever done out of that
--                               * suballocator too. A future version
--                               * might change that however, so avoid
--                               * a free if we don't know how to
--                               * handle it. This way an fs incompat
--                               * bit will not be necessary.
--                               */
--                              ret = ocfs2_free_extent_block(handle,
--                                                            tc->tc_ext_alloc_inode,
--                                                            tc->tc_ext_alloc_bh,
--                                                            eb);
+ /* macros to access host data structure */
+-#define subsystem_pun(h) ((h)->this_id)
+-#define subsystem_maxid(h) ((h)->max_id)
+-#define ld(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_ld)
+-#define get_ldn(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_get_ldn)
+-#define get_scsi(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_get_scsi)
+-#define local_checking_phase_flag(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_local_checking_phase_flag)
+-#define got_interrupt(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_got_interrupt)
+-#define stat_result(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_stat_result)
+-#define reset_status(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_reset_status)
+-#define last_scsi_command(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_command)
+-#define last_scsi_type(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_type)
+-#define last_scsi_blockcount(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_blockcount)
+-#define last_scsi_logical_block(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_logical_block)
+-#define last_scsi_type(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_type)
+-#define next_ldn(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_next_ldn)
+-#define IBM_DS(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_IBM_DS)
+-#define special(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_special)
+-#define subsystem_connector_size(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_connector_size)
+-#define adapter_speed(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_adapter_speed)
+-#define pos2(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[2])
+-#define pos3(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[3])
+-#define pos4(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[4])
+-#define pos5(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[5])
+-#define pos6(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[6])
++#define subsystem_pun(hi) (hosts[(hi)]->this_id)
++#define subsystem_maxid(hi) (hosts[(hi)]->max_id)
++#define ld(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_ld)
++#define get_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_ldn)
++#define get_scsi(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_scsi)
++#define local_checking_phase_flag(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_local_checking_phase_flag)
++#define got_interrupt(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_got_interrupt)
++#define stat_result(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_stat_result)
++#define reset_status(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_reset_status)
++#define last_scsi_command(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_command)
++#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type)
++#define last_scsi_blockcount(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_blockcount)
++#define last_scsi_logical_block(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_logical_block)
++#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type)
++#define next_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_next_ldn)
++#define IBM_DS(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_IBM_DS)
++#define special(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_special)
++#define subsystem_connector_size(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_connector_size)
++#define adapter_speed(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_adapter_speed)
++#define pos2(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[2])
++#define pos3(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[3])
++#define pos4(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[4])
++#define pos5(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[5])
++#define pos6(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[6])
+ /* Define a arbitrary number as subsystem-marker-type. This number is, as
+    described in the ANSI-SCSI-standard, not occupied by other device-types. */
+@@ -472,6 +459,11 @@
+ /*counter of concurrent disk read/writes, to turn on/off disk led */
+ static int disk_rw_in_progress = 0;
++/* host information */
++static int found = 0;
++static struct Scsi_Host *hosts[IM_MAX_HOSTS + 1] = {
++      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
++};
+ static unsigned int pos[8];   /* whole pos register-line for diagnosis */
+ /* Taking into account the additions, made by ZP Gu.
+  * This selects now the preset value from the configfile and
+@@ -482,68 +474,70 @@
+ static char ibm_ansi_order = 0;
+ #endif
+-static void issue_cmd(struct Scsi_Host *, unsigned long, unsigned char);
++static void issue_cmd(int, unsigned long, unsigned char);
+ static void internal_done(Scsi_Cmnd * cmd);
+-static void check_devices(struct Scsi_Host *, int);
+-static int immediate_assign(struct Scsi_Host *, unsigned int, unsigned int, unsigned int, unsigned int);
+-static int immediate_feature(struct Scsi_Host *, unsigned int, unsigned int);
++static void check_devices(int, int);
++static int immediate_assign(int, unsigned int, unsigned int, unsigned int, unsigned int);
++static int immediate_feature(int, unsigned int, unsigned int);
+ #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
+-static int immediate_reset(struct Scsi_Host *, unsigned int);
++static int immediate_reset(int, unsigned int);
+ #endif
+-static int device_inquiry(struct Scsi_Host *, int);
+-static int read_capacity(struct Scsi_Host *, int);
+-static int get_pos_info(struct Scsi_Host *);
++static int device_inquiry(int, int);
++static int read_capacity(int, int);
++static int get_pos_info(int);
+ static char *ti_p(int);
+ static char *ti_l(int);
+ static char *ibmrate(unsigned int, int);
+ static int probe_display(int);
+-static int probe_bus_mode(struct Scsi_Host *);
+-static int device_exists(struct Scsi_Host *, int, int *, int *);
++static int probe_bus_mode(int);
++static int device_exists(int, int, int *, int *);
++static struct Scsi_Host *ibmmca_register(struct scsi_host_template *, int, int, int, char *);
+ static int option_setup(char *);
+ /* local functions needed for proc_info */
+-static int ldn_access_load(struct Scsi_Host *, int);
+-static int ldn_access_total_read_write(struct Scsi_Host *);
++static int ldn_access_load(int, int);
++static int ldn_access_total_read_write(int);
+ static irqreturn_t interrupt_handler(int irq, void *dev_id)
+ {
++      int host_index, ihost_index;
+       unsigned int intr_reg;
+       unsigned int cmd_result;
+       unsigned int ldn;
+-      unsigned long flags;
+       Scsi_Cmnd *cmd;
+       int lastSCSI;
+-      struct device *dev = dev_id;
+-      struct Scsi_Host *shpnt = dev_get_drvdata(dev);
+-
+-      spin_lock_irqsave(shpnt->host_lock, flags);
++      struct Scsi_Host *dev = dev_id;
+-      if(!(inb(IM_STAT_REG(shpnt)) & IM_INTR_REQUEST)) {
+-              spin_unlock_irqrestore(shpnt->host_lock, flags);
++      spin_lock(dev->host_lock);
++          /* search for one adapter-response on shared interrupt */
++          for (host_index = 0; hosts[host_index] && !(inb(IM_STAT_REG(host_index)) & IM_INTR_REQUEST); host_index++);
++      /* return if some other device on this IRQ caused the interrupt */
++      if (!hosts[host_index]) {
++              spin_unlock(dev->host_lock);
+               return IRQ_NONE;
+       }
+       /* the reset-function already did all the job, even ints got
+          renabled on the subsystem, so just return */
+-      if ((reset_status(shpnt) == IM_RESET_NOT_IN_PROGRESS_NO_INT) || (reset_status(shpnt) == IM_RESET_FINISHED_OK_NO_INT)) {
+-              reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS;
+-              spin_unlock_irqrestore(shpnt->host_lock, flags);
++      if ((reset_status(host_index) == IM_RESET_NOT_IN_PROGRESS_NO_INT) || (reset_status(host_index) == IM_RESET_FINISHED_OK_NO_INT)) {
++              reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS;
++              spin_unlock(dev->host_lock);
+               return IRQ_HANDLED;
+       }
+       /*must wait for attention reg not busy, then send EOI to subsystem */
+       while (1) {
+-              if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
++              if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
+                       break;
+               cpu_relax();
+       }
 -
-+                      ret = ocfs2_cache_extent_block_free(&tc->tc_dealloc, eb);
-                               /* An error here is not fatal. */
-                               if (ret < 0)
-                                       mlog_errno(ret);
--                      }
++      ihost_index = host_index;
+       /*get command result and logical device */
+-      intr_reg = (unsigned char) (inb(IM_INTR_REG(shpnt)));
++      intr_reg = (unsigned char) (inb(IM_INTR_REG(ihost_index)));
+       cmd_result = intr_reg & 0xf0;
+       ldn = intr_reg & 0x0f;
+       /* get the last_scsi_command here */
+-      lastSCSI = last_scsi_command(shpnt)[ldn];
+-      outb(IM_EOI | ldn, IM_ATTN_REG(shpnt));
++      lastSCSI = last_scsi_command(ihost_index)[ldn];
++      outb(IM_EOI | ldn, IM_ATTN_REG(ihost_index));
+       
+       /*these should never happen (hw fails, or a local programming bug) */
+       if (!global_command_error_excuse) {
+@@ -553,38 +547,38 @@
+               case IM_SOFTWARE_SEQUENCING_ERROR:
+               case IM_CMD_ERROR:
+                       printk(KERN_ERR "IBM MCA SCSI: Fatal Subsystem ERROR!\n");
+-                      printk(KERN_ERR "              Last cmd=0x%x, ena=%x, len=", lastSCSI, ld(shpnt)[ldn].scb.enable);
+-                      if (ld(shpnt)[ldn].cmd)
+-                              printk("%ld/%ld,", (long) (scsi_bufflen(ld(shpnt)[ldn].cmd)), (long) (ld(shpnt)[ldn].scb.sys_buf_length));
++                      printk(KERN_ERR "              Last cmd=0x%x, ena=%x, len=", lastSCSI, ld(ihost_index)[ldn].scb.enable);
++                      if (ld(ihost_index)[ldn].cmd)
++                              printk("%ld/%ld,", (long) (ld(ihost_index)[ldn].cmd->request_bufflen), (long) (ld(ihost_index)[ldn].scb.sys_buf_length));
+                       else
+                               printk("none,");
+-                      if (ld(shpnt)[ldn].cmd)
+-                              printk("Blocksize=%d", ld(shpnt)[ldn].scb.u2.blk.length);
++                      if (ld(ihost_index)[ldn].cmd)
++                              printk("Blocksize=%d", ld(ihost_index)[ldn].scb.u2.blk.length);
+                       else
+                               printk("Blocksize=none");
+-                      printk(", host=%p, ldn=0x%x\n", shpnt, ldn);
+-                      if (ld(shpnt)[ldn].cmd) {
+-                              printk(KERN_ERR "Blockcount=%d/%d\n", last_scsi_blockcount(shpnt)[ldn], ld(shpnt)[ldn].scb.u2.blk.count);
+-                              printk(KERN_ERR "Logical block=%lx/%lx\n", last_scsi_logical_block(shpnt)[ldn], ld(shpnt)[ldn].scb.u1.log_blk_adr);
++                      printk(", host=0x%x, ldn=0x%x\n", ihost_index, ldn);
++                      if (ld(ihost_index)[ldn].cmd) {
++                              printk(KERN_ERR "Blockcount=%d/%d\n", last_scsi_blockcount(ihost_index)[ldn], ld(ihost_index)[ldn].scb.u2.blk.count);
++                              printk(KERN_ERR "Logical block=%lx/%lx\n", last_scsi_logical_block(ihost_index)[ldn], ld(ihost_index)[ldn].scb.u1.log_blk_adr);
+                       }
+                       printk(KERN_ERR "Reason given: %s\n", (cmd_result == IM_ADAPTER_HW_FAILURE) ? "HARDWARE FAILURE" : (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR) ? "SOFTWARE SEQUENCING ERROR" : (cmd_result == IM_CMD_ERROR) ? "COMMAND ERROR" : "UNKNOWN");
+                       /* if errors appear, enter this section to give detailed info */
+                       printk(KERN_ERR "IBM MCA SCSI: Subsystem Error-Status follows:\n");
+-                      printk(KERN_ERR "              Command Type................: %x\n", last_scsi_type(shpnt)[ldn]);
+-                      printk(KERN_ERR "              Attention Register..........: %x\n", inb(IM_ATTN_REG(shpnt)));
+-                      printk(KERN_ERR "              Basic Control Register......: %x\n", inb(IM_CTR_REG(shpnt)));
++                      printk(KERN_ERR "              Command Type................: %x\n", last_scsi_type(ihost_index)[ldn]);
++                      printk(KERN_ERR "              Attention Register..........: %x\n", inb(IM_ATTN_REG(ihost_index)));
++                      printk(KERN_ERR "              Basic Control Register......: %x\n", inb(IM_CTR_REG(ihost_index)));
+                       printk(KERN_ERR "              Interrupt Status Register...: %x\n", intr_reg);
+-                      printk(KERN_ERR "              Basic Status Register.......: %x\n", inb(IM_STAT_REG(shpnt)));
+-                      if ((last_scsi_type(shpnt)[ldn] == IM_SCB) || (last_scsi_type(shpnt)[ldn] == IM_LONG_SCB)) {
+-                              printk(KERN_ERR "              SCB-Command.................: %x\n", ld(shpnt)[ldn].scb.command);
+-                              printk(KERN_ERR "              SCB-Enable..................: %x\n", ld(shpnt)[ldn].scb.enable);
+-                              printk(KERN_ERR "              SCB-logical block address...: %lx\n", ld(shpnt)[ldn].scb.u1.log_blk_adr);
+-                              printk(KERN_ERR "              SCB-system buffer address...: %lx\n", ld(shpnt)[ldn].scb.sys_buf_adr);
+-                              printk(KERN_ERR "              SCB-system buffer length....: %lx\n", ld(shpnt)[ldn].scb.sys_buf_length);
+-                              printk(KERN_ERR "              SCB-tsb address.............: %lx\n", ld(shpnt)[ldn].scb.tsb_adr);
+-                              printk(KERN_ERR "              SCB-Chain address...........: %lx\n", ld(shpnt)[ldn].scb.scb_chain_adr);
+-                              printk(KERN_ERR "              SCB-block count.............: %x\n", ld(shpnt)[ldn].scb.u2.blk.count);
+-                              printk(KERN_ERR "              SCB-block length............: %x\n", ld(shpnt)[ldn].scb.u2.blk.length);
++                      printk(KERN_ERR "              Basic Status Register.......: %x\n", inb(IM_STAT_REG(ihost_index)));
++                      if ((last_scsi_type(ihost_index)[ldn] == IM_SCB) || (last_scsi_type(ihost_index)[ldn] == IM_LONG_SCB)) {
++                              printk(KERN_ERR "              SCB-Command.................: %x\n", ld(ihost_index)[ldn].scb.command);
++                              printk(KERN_ERR "              SCB-Enable..................: %x\n", ld(ihost_index)[ldn].scb.enable);
++                              printk(KERN_ERR "              SCB-logical block address...: %lx\n", ld(ihost_index)[ldn].scb.u1.log_blk_adr);
++                              printk(KERN_ERR "              SCB-system buffer address...: %lx\n", ld(ihost_index)[ldn].scb.sys_buf_adr);
++                              printk(KERN_ERR "              SCB-system buffer length....: %lx\n", ld(ihost_index)[ldn].scb.sys_buf_length);
++                              printk(KERN_ERR "              SCB-tsb address.............: %lx\n", ld(ihost_index)[ldn].scb.tsb_adr);
++                              printk(KERN_ERR "              SCB-Chain address...........: %lx\n", ld(ihost_index)[ldn].scb.scb_chain_adr);
++                              printk(KERN_ERR "              SCB-block count.............: %x\n", ld(ihost_index)[ldn].scb.u2.blk.count);
++                              printk(KERN_ERR "              SCB-block length............: %x\n", ld(ihost_index)[ldn].scb.u2.blk.length);
+                       }
+                       printk(KERN_ERR "              Send this report to the maintainer.\n");
+                       panic("IBM MCA SCSI: Fatal error message from the subsystem (0x%X,0x%X)!\n", lastSCSI, cmd_result);
+@@ -606,73 +600,72 @@
+               }
+       }
+       /* if no panic appeared, increase the interrupt-counter */
+-      IBM_DS(shpnt).total_interrupts++;
++      IBM_DS(ihost_index).total_interrupts++;
+       /*only for local checking phase */
+-      if (local_checking_phase_flag(shpnt)) {
+-              stat_result(shpnt) = cmd_result;
+-              got_interrupt(shpnt) = 1;
+-              reset_status(shpnt) = IM_RESET_FINISHED_OK;
+-              last_scsi_command(shpnt)[ldn] = NO_SCSI;
+-              spin_unlock_irqrestore(shpnt->host_lock, flags);
++      if (local_checking_phase_flag(ihost_index)) {
++              stat_result(ihost_index) = cmd_result;
++              got_interrupt(ihost_index) = 1;
++              reset_status(ihost_index) = IM_RESET_FINISHED_OK;
++              last_scsi_command(ihost_index)[ldn] = NO_SCSI;
++              spin_unlock(dev->host_lock);
+               return IRQ_HANDLED;
+       }
+       /* handling of commands coming from upper level of scsi driver */
+-      if (last_scsi_type(shpnt)[ldn] == IM_IMM_CMD) {
++      if (last_scsi_type(ihost_index)[ldn] == IM_IMM_CMD) {
+               /* verify ldn, and may handle rare reset immediate command */
+-              if ((reset_status(shpnt) == IM_RESET_IN_PROGRESS) && (last_scsi_command(shpnt)[ldn] == IM_RESET_IMM_CMD)) {
++              if ((reset_status(ihost_index) == IM_RESET_IN_PROGRESS) && (last_scsi_command(ihost_index)[ldn] == IM_RESET_IMM_CMD)) {
+                       if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) {
+                               disk_rw_in_progress = 0;
+                               PS2_DISK_LED_OFF();
+-                              reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
++                              reset_status(ihost_index) = IM_RESET_FINISHED_FAIL;
+                       } else {
+                               /*reset disk led counter, turn off disk led */
+                               disk_rw_in_progress = 0;
+                               PS2_DISK_LED_OFF();
+-                              reset_status(shpnt) = IM_RESET_FINISHED_OK;
++                              reset_status(ihost_index) = IM_RESET_FINISHED_OK;
+                       }
+-                      stat_result(shpnt) = cmd_result;
+-                      last_scsi_command(shpnt)[ldn] = NO_SCSI;
+-                      last_scsi_type(shpnt)[ldn] = 0;
+-                      spin_unlock_irqrestore(shpnt->host_lock, flags);
++                      stat_result(ihost_index) = cmd_result;
++                      last_scsi_command(ihost_index)[ldn] = NO_SCSI;
++                      last_scsi_type(ihost_index)[ldn] = 0;
++                      spin_unlock(dev->host_lock);
+                       return IRQ_HANDLED;
+-              } else if (last_scsi_command(shpnt)[ldn] == IM_ABORT_IMM_CMD) {
++              } else if (last_scsi_command(ihost_index)[ldn] == IM_ABORT_IMM_CMD) {
+                       /* react on SCSI abort command */
+ #ifdef IM_DEBUG_PROBE
+                       printk("IBM MCA SCSI: Interrupt from SCSI-abort.\n");
+ #endif
+                       disk_rw_in_progress = 0;
+                       PS2_DISK_LED_OFF();
+-                      cmd = ld(shpnt)[ldn].cmd;
+-                      ld(shpnt)[ldn].cmd = NULL;
++                      cmd = ld(ihost_index)[ldn].cmd;
++                      ld(ihost_index)[ldn].cmd = NULL;
+                       if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
+                               cmd->result = DID_NO_CONNECT << 16;
+                       else
+                               cmd->result = DID_ABORT << 16;
+-                      stat_result(shpnt) = cmd_result;
+-                      last_scsi_command(shpnt)[ldn] = NO_SCSI;
+-                      last_scsi_type(shpnt)[ldn] = 0;
++                      stat_result(ihost_index) = cmd_result;
++                      last_scsi_command(ihost_index)[ldn] = NO_SCSI;
++                      last_scsi_type(ihost_index)[ldn] = 0;
+                       if (cmd->scsi_done)
+                               (cmd->scsi_done) (cmd); /* should be the internal_done */
+-                      spin_unlock_irqrestore(shpnt->host_lock, flags);
++                      spin_unlock(dev->host_lock);
+                       return IRQ_HANDLED;
                } else {
-                       deleted_eb = 0;
+                       disk_rw_in_progress = 0;
+                       PS2_DISK_LED_OFF();
+-                      reset_status(shpnt) = IM_RESET_FINISHED_OK;
+-                      stat_result(shpnt) = cmd_result;
+-                      last_scsi_command(shpnt)[ldn] = NO_SCSI;
+-                      spin_unlock_irqrestore(shpnt->host_lock, flags);
++                      reset_status(ihost_index) = IM_RESET_FINISHED_OK;
++                      stat_result(ihost_index) = cmd_result;
++                      last_scsi_command(ihost_index)[ldn] = NO_SCSI;
++                      spin_unlock(dev->host_lock);
+                       return IRQ_HANDLED;
+               }
+       }
+-      last_scsi_command(shpnt)[ldn] = NO_SCSI;
+-      last_scsi_type(shpnt)[ldn] = 0;
+-      cmd = ld(shpnt)[ldn].cmd;
+-      ld(shpnt)[ldn].cmd = NULL;
++      last_scsi_command(ihost_index)[ldn] = NO_SCSI;
++      last_scsi_type(ihost_index)[ldn] = 0;
++      cmd = ld(ihost_index)[ldn].cmd;
++      ld(ihost_index)[ldn].cmd = NULL;
+ #ifdef IM_DEBUG_TIMEOUT
+       if (cmd) {
+               if ((cmd->target == TIMEOUT_PUN) && (cmd->device->lun == TIMEOUT_LUN)) {
+-                      spin_unlock_irqsave(shpnt->host_lock, flags);
+                       printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n", cmd->target, cmd->device->lun);
+                       return IRQ_HANDLED;
                }
-@@ -3631,8 +5290,6 @@
+@@ -681,15 +674,15 @@
+       /*if no command structure, just return, else clear cmd */
+       if (!cmd)
+       {
+-              spin_unlock_irqrestore(shpnt->host_lock, flags);
++              spin_unlock(dev->host_lock);
+               return IRQ_HANDLED;
+       }
  
-       mlog_entry_void();
+ #ifdef IM_DEBUG_INT
+-      printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", cmd->cmnd[0], intr_reg, ld(shpnt)[ldn].tsb.dev_status, ld(shpnt)[ldn].tsb.cmd_status, ld(shpnt)[ldn].tsb.dev_error, ld(shpnt)[ldn].tsb.cmd_error);
++      printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", cmd->cmnd[0], intr_reg, ld(ihost_index)[ldn].tsb.dev_status, ld(ihost_index)[ldn].tsb.cmd_status, ld(ihost_index)[ldn].tsb.dev_error, ld(ihost_index)[ldn].tsb.cmd_error);
+ #endif
+       /*if this is end of media read/write, may turn off PS/2 disk led */
+-      if ((ld(shpnt)[ldn].device_type != TYPE_NO_LUN) && (ld(shpnt)[ldn].device_type != TYPE_NO_DEVICE)) {
++      if ((ld(ihost_index)[ldn].device_type != TYPE_NO_LUN) && (ld(ihost_index)[ldn].device_type != TYPE_NO_DEVICE)) {
+               /* only access this, if there was a valid device addressed */
+               if (--disk_rw_in_progress == 0)
+                       PS2_DISK_LED_OFF();
+@@ -700,8 +693,8 @@
+        * adapters do not support CMD_TERMINATED, TASK_SET_FULL and
+        * ACA_ACTIVE as returning statusbyte information. (ML) */
+       if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) {
+-              cmd->result = (unsigned char) (ld(shpnt)[ldn].tsb.dev_status & 0x1e);
+-              IBM_DS(shpnt).total_errors++;
++              cmd->result = (unsigned char) (ld(ihost_index)[ldn].tsb.dev_status & 0x1e);
++              IBM_DS(ihost_index).total_errors++;
+       } else
+               cmd->result = 0;
+       /* write device status into cmd->result, and call done function */
+@@ -712,25 +705,24 @@
+               cmd->result |= DID_OK << 16;
+       if (cmd->scsi_done)
+               (cmd->scsi_done) (cmd);
+-      spin_unlock_irqrestore(shpnt->host_lock, flags);
++      spin_unlock(dev->host_lock);
+       return IRQ_HANDLED;
+ }
  
--      down_write(&OCFS2_I(inode)->ip_alloc_sem);
--
-       new_highest_cpos = ocfs2_clusters_for_bytes(osb->sb,
-                                                    i_size_read(inode));
+-static void issue_cmd(struct Scsi_Host *shpnt, unsigned long cmd_reg,
+-                    unsigned char attn_reg)
++static void issue_cmd(int host_index, unsigned long cmd_reg, unsigned char attn_reg)
+ {
+       unsigned long flags;
+       /* must wait for attention reg not busy */
+       while (1) {
+-              spin_lock_irqsave(shpnt->host_lock, flags);
+-              if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
++              spin_lock_irqsave(hosts[host_index]->host_lock, flags);
++              if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
+                       break;
+-              spin_unlock_irqrestore(shpnt->host_lock, flags);
++              spin_unlock_irqrestore(hosts[host_index]->host_lock, flags);
+       }
+       /* write registers and enable system interrupts */
+-      outl(cmd_reg, IM_CMD_REG(shpnt));
+-      outb(attn_reg, IM_ATTN_REG(shpnt));
+-      spin_unlock_irqrestore(shpnt->host_lock, flags);
++      outl(cmd_reg, IM_CMD_REG(host_index));
++      outb(attn_reg, IM_ATTN_REG(host_index));
++      spin_unlock_irqrestore(hosts[host_index]->host_lock, flags);
+ }
  
-@@ -3754,7 +5411,6 @@
-       goto start;
+ static void internal_done(Scsi_Cmnd * cmd)
+@@ -740,34 +732,34 @@
+ }
  
- bail:
--      up_write(&OCFS2_I(inode)->ip_alloc_sem);
+ /* SCSI-SCB-command for device_inquiry */
+-static int device_inquiry(struct Scsi_Host *shpnt, int ldn)
++static int device_inquiry(int host_index, int ldn)
+ {
+       int retr;
+       struct im_scb *scb;
+       struct im_tsb *tsb;
+       unsigned char *buf;
  
-       ocfs2_schedule_truncate_log_flush(osb, 1);
+-      scb = &(ld(shpnt)[ldn].scb);
+-      tsb = &(ld(shpnt)[ldn].tsb);
+-      buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
+-      ld(shpnt)[ldn].tsb.dev_status = 0;      /* prepare statusblock */
++      scb = &(ld(host_index)[ldn].scb);
++      tsb = &(ld(host_index)[ldn].tsb);
++      buf = (unsigned char *) (&(ld(host_index)[ldn].buf));
++      ld(host_index)[ldn].tsb.dev_status = 0; /* prepare statusblock */
+       for (retr = 0; retr < 3; retr++) {
+               /* fill scb with inquiry command */
+               scb->command = IM_DEVICE_INQUIRY_CMD | IM_NO_DISCONNECT;
+               scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
+-              last_scsi_command(shpnt)[ldn] = IM_DEVICE_INQUIRY_CMD;
+-              last_scsi_type(shpnt)[ldn] = IM_SCB;
++              last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD;
++              last_scsi_type(host_index)[ldn] = IM_SCB;
+               scb->sys_buf_adr = isa_virt_to_bus(buf);
+               scb->sys_buf_length = 255;      /* maximum bufferlength gives max info */
+               scb->tsb_adr = isa_virt_to_bus(tsb);
+               /* issue scb to passed ldn, and busy wait for interrupt */
+-              got_interrupt(shpnt) = 0;
+-              issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
+-              while (!got_interrupt(shpnt))
++              got_interrupt(host_index) = 0;
++              issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
++              while (!got_interrupt(host_index))
+                       barrier();
  
-@@ -3764,6 +5420,8 @@
-       if (handle)
-               ocfs2_commit_trans(osb, handle);
+               /*if command successful, break */
+-              if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
++              if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+                       return 1;
+       }
+       /*if all three retries failed, return "no device at this ldn" */
+@@ -777,34 +769,34 @@
+               return 1;
+ }
  
-+      ocfs2_run_deallocs(osb, &tc->tc_dealloc);
-+
-       ocfs2_free_path(path);
+-static int read_capacity(struct Scsi_Host *shpnt, int ldn)
++static int read_capacity(int host_index, int ldn)
+ {
+       int retr;
+       struct im_scb *scb;
+       struct im_tsb *tsb;
+       unsigned char *buf;
  
-       /* This will drop the ext_alloc cluster lock for us */
-@@ -3774,23 +5432,18 @@
+-      scb = &(ld(shpnt)[ldn].scb);
+-      tsb = &(ld(shpnt)[ldn].tsb);
+-      buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
+-      ld(shpnt)[ldn].tsb.dev_status = 0;
++      scb = &(ld(host_index)[ldn].scb);
++      tsb = &(ld(host_index)[ldn].tsb);
++      buf = (unsigned char *) (&(ld(host_index)[ldn].buf));
++      ld(host_index)[ldn].tsb.dev_status = 0;
+       for (retr = 0; retr < 3; retr++) {
+               /*fill scb with read capacity command */
+               scb->command = IM_READ_CAPACITY_CMD;
+               scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
+-              last_scsi_command(shpnt)[ldn] = IM_READ_CAPACITY_CMD;
+-              last_scsi_type(shpnt)[ldn] = IM_SCB;
++              last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD;
++              last_scsi_type(host_index)[ldn] = IM_SCB;
+               scb->sys_buf_adr = isa_virt_to_bus(buf);
+               scb->sys_buf_length = 8;
+               scb->tsb_adr = isa_virt_to_bus(tsb);
+               /*issue scb to passed ldn, and busy wait for interrupt */
+-              got_interrupt(shpnt) = 0;
+-              issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
+-              while (!got_interrupt(shpnt))
++              got_interrupt(host_index) = 0;
++              issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
++              while (!got_interrupt(host_index))
+                       barrier();
+               /*if got capacity, get block length and return one device found */
+-              if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
++              if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+                       return 1;
+       }
+       /*if all three retries failed, return "no device at this ldn" */
+@@ -814,39 +806,39 @@
+               return 1;
  }
  
- /*
-- * Expects the inode to already be locked. This will figure out which
-- * inodes need to be locked and will put them on the returned truncate
-- * context.
-+ * Expects the inode to already be locked.
-  */
- int ocfs2_prepare_truncate(struct ocfs2_super *osb,
-                          struct inode *inode,
-                          struct buffer_head *fe_bh,
-                          struct ocfs2_truncate_context **tc)
+-static int get_pos_info(struct Scsi_Host *shpnt)
++static int get_pos_info(int host_index)
  {
--      int status, metadata_delete, i;
-+      int status;
-       unsigned int new_i_clusters;
-       struct ocfs2_dinode *fe;
-       struct ocfs2_extent_block *eb;
--      struct ocfs2_extent_list *el;
-       struct buffer_head *last_eb_bh = NULL;
--      struct inode *ext_alloc_inode = NULL;
--      struct buffer_head *ext_alloc_bh = NULL;
+       int retr;
+       struct im_scb *scb;
+       struct im_tsb *tsb;
+       unsigned char *buf;
  
-       mlog_entry_void();
+-      scb = &(ld(shpnt)[MAX_LOG_DEV].scb);
+-      tsb = &(ld(shpnt)[MAX_LOG_DEV].tsb);
+-      buf = (unsigned char *) (&(ld(shpnt)[MAX_LOG_DEV].buf));
+-      ld(shpnt)[MAX_LOG_DEV].tsb.dev_status = 0;
++      scb = &(ld(host_index)[MAX_LOG_DEV].scb);
++      tsb = &(ld(host_index)[MAX_LOG_DEV].tsb);
++      buf = (unsigned char *) (&(ld(host_index)[MAX_LOG_DEV].buf));
++      ld(host_index)[MAX_LOG_DEV].tsb.dev_status = 0;
+       for (retr = 0; retr < 3; retr++) {
+               /*fill scb with get_pos_info command */
+               scb->command = IM_GET_POS_INFO_CMD;
+               scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
+-              last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;
+-              last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_SCB;
++              last_scsi_command(host_index)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;
++              last_scsi_type(host_index)[MAX_LOG_DEV] = IM_SCB;
+               scb->sys_buf_adr = isa_virt_to_bus(buf);
+-              if (special(shpnt) == IBM_SCSI2_FW)
++              if (special(host_index) == IBM_SCSI2_FW)
+                       scb->sys_buf_length = 256;      /* get all info from F/W adapter */
+               else
+                       scb->sys_buf_length = 18;       /* get exactly 18 bytes for other SCSI */
+               scb->tsb_adr = isa_virt_to_bus(tsb);
+               /*issue scb to ldn=15, and busy wait for interrupt */
+-              got_interrupt(shpnt) = 0;
+-              issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
++              got_interrupt(host_index) = 0;
++              issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
+               
+               /* FIXME: timeout */
+-              while (!got_interrupt(shpnt))
++              while (!got_interrupt(host_index))
+                       barrier();
  
-@@ -3810,12 +5463,9 @@
-               mlog_errno(status);
-               goto bail;
+               /*if got POS-stuff, get block length and return one device found */
+-              if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
++              if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+                       return 1;
        }
-+      ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc);
+       /* if all three retries failed, return "no device at this ldn" */
+@@ -859,16 +851,14 @@
+ /* SCSI-immediate-command for assign. This functions maps/unmaps specific
+  ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the
+  subsystem and for dynamical remapping od ldns. */
+-static int immediate_assign(struct Scsi_Host *shpnt, unsigned int pun,
+-                          unsigned int lun, unsigned int ldn,
+-                          unsigned int operation)
++static int immediate_assign(int host_index, unsigned int pun, unsigned int lun, unsigned int ldn, unsigned int operation)
+ {
+       int retr;
+       unsigned long imm_cmd;
  
--      metadata_delete = 0;
-       if (fe->id2.i_list.l_tree_depth) {
--              /* If we have a tree, then the truncate may result in
--               * metadata deletes. Figure this out from the
--               * rightmost leaf block.*/
-               status = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),
-                                         &last_eb_bh, OCFS2_BH_CACHED, inode);
-               if (status < 0) {
-@@ -3830,43 +5480,10 @@
-                       status = -EIO;
-                       goto bail;
+       for (retr = 0; retr < 3; retr++) {
+               /* select mutation level of the SCSI-adapter */
+-              switch (special(shpnt)) {
++              switch (special(host_index)) {
+               case IBM_SCSI2_FW:
+                       imm_cmd = (unsigned long) (IM_ASSIGN_IMM_CMD);
+                       imm_cmd |= (unsigned long) ((lun & 7) << 24);
+@@ -877,7 +867,7 @@
+                       imm_cmd |= (unsigned long) ((ldn & 15) << 16);
+                       break;
+               default:
+-                      imm_cmd = inl(IM_CMD_REG(shpnt));
++                      imm_cmd = inl(IM_CMD_REG(host_index));
+                       imm_cmd &= (unsigned long) (0xF8000000);        /* keep reserved bits */
+                       imm_cmd |= (unsigned long) (IM_ASSIGN_IMM_CMD);
+                       imm_cmd |= (unsigned long) ((lun & 7) << 24);
+@@ -886,15 +876,15 @@
+                       imm_cmd |= (unsigned long) ((ldn & 15) << 16);
+                       break;
                }
--              el = &(eb->h_list);
--
--              i = 0;
--              if (ocfs2_is_empty_extent(&el->l_recs[0]))
--                      i = 1;
--              /*
--               * XXX: Should we check that next_free_rec contains
--               * the extent?
--               */
--              if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_i_clusters)
--                      metadata_delete = 1;
+-              last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD;
+-              last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_IMM_CMD;
+-              got_interrupt(shpnt) = 0;
+-              issue_cmd(shpnt, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
+-              while (!got_interrupt(shpnt))
++              last_scsi_command(host_index)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD;
++              last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD;
++              got_interrupt(host_index) = 0;
++              issue_cmd(host_index, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
++              while (!got_interrupt(host_index))
+                       barrier();
+               /*if command successful, break */
+-              if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
++              if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+                       return 1;
        }
+       if (retr >= 3)
+@@ -903,7 +893,7 @@
+               return 1;
+ }
  
-       (*tc)->tc_last_eb_bh = last_eb_bh;
+-static int immediate_feature(struct Scsi_Host *shpnt, unsigned int speed, unsigned int timeout)
++static int immediate_feature(int host_index, unsigned int speed, unsigned int timeout)
+ {
+       int retr;
+       unsigned long imm_cmd;
+@@ -913,16 +903,16 @@
+               imm_cmd = IM_FEATURE_CTR_IMM_CMD;
+               imm_cmd |= (unsigned long) ((speed & 0x7) << 29);
+               imm_cmd |= (unsigned long) ((timeout & 0x1fff) << 16);
+-              last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD;
+-              last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_IMM_CMD;
+-              got_interrupt(shpnt) = 0;
++              last_scsi_command(host_index)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD;
++              last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD;
++              got_interrupt(host_index) = 0;
+               /* we need to run into command errors in order to probe for the
+                * right speed! */
+               global_command_error_excuse = 1;
+-              issue_cmd(shpnt, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
++              issue_cmd(host_index, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
+               
+               /* FIXME: timeout */
+-              while (!got_interrupt(shpnt))
++              while (!got_interrupt(host_index))
+                       barrier();
+               if (global_command_error_excuse == CMD_FAIL) {
+                       global_command_error_excuse = 0;
+@@ -930,7 +920,7 @@
+               } else
+                       global_command_error_excuse = 0;
+               /*if command successful, break */
+-              if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
++              if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+                       return 1;
+       }
+       if (retr >= 3)
+@@ -940,35 +930,35 @@
+ }
  
--      if (metadata_delete) {
--              mlog(0, "Will have to delete metadata for this trunc. "
--                   "locking allocator.\n");
--              ext_alloc_inode = ocfs2_get_system_file_inode(osb, EXTENT_ALLOC_SYSTEM_INODE, 0);
--              if (!ext_alloc_inode) {
--                      status = -ENOMEM;
--                      mlog_errno(status);
--                      goto bail;
--              }
--
--              mutex_lock(&ext_alloc_inode->i_mutex);
--              (*tc)->tc_ext_alloc_inode = ext_alloc_inode;
--
--              status = ocfs2_meta_lock(ext_alloc_inode, &ext_alloc_bh, 1);
--              if (status < 0) {
--                      mlog_errno(status);
--                      goto bail;
--              }
--              (*tc)->tc_ext_alloc_bh = ext_alloc_bh;
--              (*tc)->tc_ext_alloc_locked = 1;
--      }
--
-       status = 0;
- bail:
-       if (status < 0) {
-@@ -3880,16 +5497,13 @@
+ #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
+-static int immediate_reset(struct Scsi_Host *shpnt, unsigned int ldn)
++static int immediate_reset(int host_index, unsigned int ldn)
+ {
+       int retries;
+       int ticks;
+       unsigned long imm_command;
  
- static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc)
+       for (retries = 0; retries < 3; retries++) {
+-              imm_command = inl(IM_CMD_REG(shpnt));
++              imm_command = inl(IM_CMD_REG(host_index));
+               imm_command &= (unsigned long) (0xFFFF0000);    /* keep reserved bits */
+               imm_command |= (unsigned long) (IM_RESET_IMM_CMD);
+-              last_scsi_command(shpnt)[ldn] = IM_RESET_IMM_CMD;
+-              last_scsi_type(shpnt)[ldn] = IM_IMM_CMD;
+-              got_interrupt(shpnt) = 0;
+-              reset_status(shpnt) = IM_RESET_IN_PROGRESS;
+-              issue_cmd(shpnt, (unsigned long) (imm_command), IM_IMM_CMD | ldn);
++              last_scsi_command(host_index)[ldn] = IM_RESET_IMM_CMD;
++              last_scsi_type(host_index)[ldn] = IM_IMM_CMD;
++              got_interrupt(host_index) = 0;
++              reset_status(host_index) = IM_RESET_IN_PROGRESS;
++              issue_cmd(host_index, (unsigned long) (imm_command), IM_IMM_CMD | ldn);
+               ticks = IM_RESET_DELAY * HZ;
+-              while (reset_status(shpnt) == IM_RESET_IN_PROGRESS && --ticks) {
++              while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks) {
+                       udelay((1 + 999 / HZ) * 1000);
+                       barrier();
+               }
+               /* if reset did not complete, just complain */
+               if (!ticks) {
+                       printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY);
+-                      reset_status(shpnt) = IM_RESET_FINISHED_OK;
++                      reset_status(host_index) = IM_RESET_FINISHED_OK;
+                       /* did not work, finish */
+                       return 1;
+               }
+               /*if command successful, break */
+-              if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
++              if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+                       return 1;
+       }
+       if (retries >= 3)
+@@ -1070,35 +1060,35 @@
+       return 0;
+ }
+-static int probe_bus_mode(struct Scsi_Host *shpnt)
++static int probe_bus_mode(int host_index)
  {
--      if (tc->tc_ext_alloc_inode) {
--              if (tc->tc_ext_alloc_locked)
--                      ocfs2_meta_unlock(tc->tc_ext_alloc_inode, 1);
--
--              mutex_unlock(&tc->tc_ext_alloc_inode->i_mutex);
--              iput(tc->tc_ext_alloc_inode);
--      }
--
--      if (tc->tc_ext_alloc_bh)
--              brelse(tc->tc_ext_alloc_bh);
-+      /*
-+       * The caller is responsible for completing deallocation
-+       * before freeing the context.
-+       */
-+      if (tc->tc_dealloc.c_first_suballocator != NULL)
-+              mlog(ML_NOTICE,
-+                   "Truncate completion has non-empty dealloc context\n");
+       struct im_pos_info *info;
+       int num_bus = 0;
+       int ldn;
  
-       if (tc->tc_last_eb_bh)
-               brelse(tc->tc_last_eb_bh);
-diff -Nurb linux-2.6.22-570/fs/ocfs2/alloc.h linux-2.6.22-590/fs/ocfs2/alloc.h
---- linux-2.6.22-570/fs/ocfs2/alloc.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/alloc.h  2008-01-02 13:56:37.000000000 -0500
-@@ -34,7 +34,13 @@
-                       u32 cpos,
-                       u64 start_blk,
-                       u32 new_clusters,
-+                      u8 flags,
-                       struct ocfs2_alloc_context *meta_ac);
-+struct ocfs2_cached_dealloc_ctxt;
-+int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
-+                            handle_t *handle, u32 cpos, u32 len, u32 phys,
-+                            struct ocfs2_alloc_context *meta_ac,
-+                            struct ocfs2_cached_dealloc_ctxt *dealloc);
- int ocfs2_num_free_extents(struct ocfs2_super *osb,
-                          struct inode *inode,
-                          struct ocfs2_dinode *fe);
-@@ -63,9 +69,27 @@
- int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
-                                        struct ocfs2_dinode *tl_copy);
+-      info = (struct im_pos_info *) (&(ld(shpnt)[MAX_LOG_DEV].buf));
+-      if (get_pos_info(shpnt)) {
++      info = (struct im_pos_info *) (&(ld(host_index)[MAX_LOG_DEV].buf));
++      if (get_pos_info(host_index)) {
+               if (info->connector_size & 0xf000)
+-                      subsystem_connector_size(shpnt) = 16;
++                      subsystem_connector_size(host_index) = 16;
+               else
+-                      subsystem_connector_size(shpnt) = 32;
++                      subsystem_connector_size(host_index) = 32;
+               num_bus |= (info->pos_4b & 8) >> 3;
+               for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
+-                      if ((special(shpnt) == IBM_SCSI_WCACHE) || (special(shpnt) == IBM_7568_WCACHE)) {
++                      if ((special(host_index) == IBM_SCSI_WCACHE) || (special(host_index) == IBM_7568_WCACHE)) {
+                               if (!((info->cache_stat >> ldn) & 1))
+-                                      ld(shpnt)[ldn].cache_flag = 0;
++                                      ld(host_index)[ldn].cache_flag = 0;
+                       }
+                       if (!((info->retry_stat >> ldn) & 1))
+-                              ld(shpnt)[ldn].retry_flag = 0;
++                              ld(host_index)[ldn].retry_flag = 0;
+               }
+ #ifdef IM_DEBUG_PROBE
+               printk("IBM MCA SCSI: SCSI-Cache bits: ");
+               for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
+-                      printk("%d", ld(shpnt)[ldn].cache_flag);
++                      printk("%d", ld(host_index)[ldn].cache_flag);
+               }
+               printk("\nIBM MCA SCSI: SCSI-Retry bits: ");
+               for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
+-                      printk("%d", ld(shpnt)[ldn].retry_flag);
++                      printk("%d", ld(host_index)[ldn].retry_flag);
+               }
+               printk("\n");
+ #endif
+@@ -1107,7 +1097,7 @@
+ }
  
-+/*
-+ * Process local structure which describes the block unlinks done
-+ * during an operation. This is populated via
-+ * ocfs2_cache_block_dealloc().
-+ *
-+ * ocfs2_run_deallocs() should be called after the potentially
-+ * de-allocating routines. No journal handles should be open, and most
-+ * locks should have been dropped.
-+ */
-+struct ocfs2_cached_dealloc_ctxt {
-+      struct ocfs2_per_slot_free_list         *c_first_suballocator;
-+};
-+static inline void ocfs2_init_dealloc_ctxt(struct ocfs2_cached_dealloc_ctxt *c)
-+{
-+      c->c_first_suballocator = NULL;
-+}
-+int ocfs2_run_deallocs(struct ocfs2_super *osb,
-+                     struct ocfs2_cached_dealloc_ctxt *ctxt);
-+
- struct ocfs2_truncate_context {
--      struct inode *tc_ext_alloc_inode;
--      struct buffer_head *tc_ext_alloc_bh;
-+      struct ocfs2_cached_dealloc_ctxt tc_dealloc;
-       int tc_ext_alloc_locked; /* is it cluster locked? */
-       /* these get destroyed once it's passed to ocfs2_commit_truncate. */
-       struct buffer_head *tc_last_eb_bh;
-@@ -84,6 +108,7 @@
+ /* probing scsi devices */
+-static void check_devices(struct Scsi_Host *shpnt, int adaptertype)
++static void check_devices(int host_index, int adaptertype)
+ {
+       int id, lun, ldn, ticks;
+       int count_devices;      /* local counter for connected device */
+@@ -1118,24 +1108,24 @@
+       /* assign default values to certain variables */
+       ticks = 0;
+       count_devices = 0;
+-      IBM_DS(shpnt).dyn_flag = 0;     /* normally no need for dynamical ldn management */
+-      IBM_DS(shpnt).total_errors = 0; /* set errorcounter to 0 */
+-      next_ldn(shpnt) = 7;    /* next ldn to be assigned is 7, because 0-6 is 'hardwired' */
++      IBM_DS(host_index).dyn_flag = 0;        /* normally no need for dynamical ldn management */
++      IBM_DS(host_index).total_errors = 0;    /* set errorcounter to 0 */
++      next_ldn(host_index) = 7;       /* next ldn to be assigned is 7, because 0-6 is 'hardwired' */
  
- int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el,
-                   u32 cpos, struct buffer_head **leaf_bh);
-+int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster);
+       /* initialize the very important driver-informational arrays/structs */
+-      memset(ld(shpnt), 0, sizeof(ld(shpnt)));
++      memset(ld(host_index), 0, sizeof(ld(host_index)));
+       for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
+-              last_scsi_command(shpnt)[ldn] = NO_SCSI;        /* emptify last SCSI-command storage */
+-              last_scsi_type(shpnt)[ldn] = 0;
+-              ld(shpnt)[ldn].cache_flag = 1;
+-              ld(shpnt)[ldn].retry_flag = 1;
++              last_scsi_command(host_index)[ldn] = NO_SCSI;   /* emptify last SCSI-command storage */
++              last_scsi_type(host_index)[ldn] = 0;
++              ld(host_index)[ldn].cache_flag = 1;
++              ld(host_index)[ldn].retry_flag = 1;
+       }
+-      memset(get_ldn(shpnt), TYPE_NO_DEVICE, sizeof(get_ldn(shpnt))); /* this is essential ! */
+-      memset(get_scsi(shpnt), TYPE_NO_DEVICE, sizeof(get_scsi(shpnt)));       /* this is essential ! */
++      memset(get_ldn(host_index), TYPE_NO_DEVICE, sizeof(get_ldn(host_index)));       /* this is essential ! */
++      memset(get_scsi(host_index), TYPE_NO_DEVICE, sizeof(get_scsi(host_index)));     /* this is essential ! */
+       for (lun = 0; lun < 8; lun++) {
+               /* mark the adapter at its pun on all luns */
+-              get_scsi(shpnt)[subsystem_pun(shpnt)][lun] = TYPE_IBM_SCSI_ADAPTER;
+-              get_ldn(shpnt)[subsystem_pun(shpnt)][lun] = MAX_LOG_DEV;        /* make sure, the subsystem
++              get_scsi(host_index)[subsystem_pun(host_index)][lun] = TYPE_IBM_SCSI_ADAPTER;
++              get_ldn(host_index)[subsystem_pun(host_index)][lun] = MAX_LOG_DEV;      /* make sure, the subsystem
+                                                                                          ldn is active for all
+                                                                                          luns. */
+       }
+@@ -1144,9 +1134,9 @@
+       /* monitor connected on model XX95. */
  
- /*
-  * Helper function to look at the # of clusters in an extent record.
-diff -Nurb linux-2.6.22-570/fs/ocfs2/aops.c linux-2.6.22-590/fs/ocfs2/aops.c
---- linux-2.6.22-570/fs/ocfs2/aops.c   2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/fs/ocfs2/aops.c   2008-01-02 13:56:37.000000000 -0500
-@@ -232,7 +232,7 @@
-        * might now be discovering a truncate that hit on another node.
-        * block_read_full_page->get_block freaks out if it is asked to read
-        * beyond the end of a file, so we check here.  Callers
--       * (generic_file_read, fault->nopage) are clever enough to check i_size
-+       * (generic_file_read, vm_ops->fault) are clever enough to check i_size
-        * and notice that the page they just read isn't needed.
-        *
-        * XXX sys_readahead() seems to get that wrong?
-@@ -705,6 +705,8 @@
-            bh = bh->b_this_page, block_start += bsize) {
-               block_end = block_start + bsize;
+       /* STEP 1: */
+-      adapter_speed(shpnt) = global_adapter_speed;
+-      speedrun = adapter_speed(shpnt);
+-      while (immediate_feature(shpnt, speedrun, adapter_timeout) == 2) {
++      adapter_speed(host_index) = global_adapter_speed;
++      speedrun = adapter_speed(host_index);
++      while (immediate_feature(host_index, speedrun, adapter_timeout) == 2) {
+               probe_display(1);
+               if (speedrun == 7)
+                       panic("IBM MCA SCSI: Cannot set Synchronous-Transfer-Rate!\n");
+@@ -1154,30 +1144,30 @@
+               if (speedrun > 7)
+                       speedrun = 7;
+       }
+-      adapter_speed(shpnt) = speedrun;
++      adapter_speed(host_index) = speedrun;
+       /* Get detailed information about the current adapter, necessary for
+        * device operations: */
+-      num_bus = probe_bus_mode(shpnt);
++      num_bus = probe_bus_mode(host_index);
  
-+              clear_buffer_new(bh);
-+
-               /*
-                * Ignore blocks outside of our i/o range -
-                * they may belong to unallocated clusters.
-@@ -719,9 +721,8 @@
-                * For an allocating write with cluster size >= page
-                * size, we always write the entire page.
-                */
--
--              if (buffer_new(bh))
--                      clear_buffer_new(bh);
-+              if (new)
-+                      set_buffer_new(bh);
+       /* num_bus contains only valid data for the F/W adapter! */
+       if (adaptertype == IBM_SCSI2_FW) {      /* F/W SCSI adapter: */
+               /* F/W adapter PUN-space extension evaluation: */
+               if (num_bus) {
+                       printk(KERN_INFO "IBM MCA SCSI: Separate bus mode (wide-addressing enabled)\n");
+-                      subsystem_maxid(shpnt) = 16;
++                      subsystem_maxid(host_index) = 16;
+               } else {
+                       printk(KERN_INFO "IBM MCA SCSI: Combined bus mode (wide-addressing disabled)\n");
+-                      subsystem_maxid(shpnt) = 8;
++                      subsystem_maxid(host_index) = 8;
+               }
+               printk(KERN_INFO "IBM MCA SCSI: Sync.-Rate (F/W: 20, Int.: 10, Ext.: %s) MBytes/s\n", ibmrate(speedrun, adaptertype));
+       } else                  /* all other IBM SCSI adapters: */
+               printk(KERN_INFO "IBM MCA SCSI: Synchronous-SCSI-Transfer-Rate: %s MBytes/s\n", ibmrate(speedrun, adaptertype));
  
-               if (!buffer_mapped(bh)) {
-                       map_bh(bh, inode->i_sb, *p_blkno);
-@@ -760,18 +761,13 @@
-       bh = head;
-       block_start = 0;
-       do {
--              void *kaddr;
--
-               block_end = block_start + bsize;
-               if (block_end <= from)
-                       goto next_bh;
-               if (block_start >= to)
-                       break;
+       /* assign correct PUN device space */
+-      max_pun = subsystem_maxid(shpnt);
++      max_pun = subsystem_maxid(host_index);
+ #ifdef IM_DEBUG_PROBE
+-      printk("IBM MCA SCSI: Current SCSI-host index: %d\n", shpnt);
++      printk("IBM MCA SCSI: Current SCSI-host index: %d\n", host_index);
+       printk("IBM MCA SCSI: Removing default logical SCSI-device mapping.");
+ #else
+       printk(KERN_INFO "IBM MCA SCSI: Dev. Order: %s, Mapping (takes <2min): ", (ibm_ansi_order) ? "ANSI" : "New");
+@@ -1187,7 +1177,7 @@
+ #ifdef IM_DEBUG_PROBE
+               printk(".");
+ #endif
+-              immediate_assign(shpnt, 0, 0, ldn, REMOVE_LDN); /* remove ldn (wherever) */
++              immediate_assign(host_index, 0, 0, ldn, REMOVE_LDN);    /* remove ldn (wherever) */
+       }
+       lun = 0;                /* default lun is 0 */
+ #ifndef IM_DEBUG_PROBE
+@@ -1206,18 +1196,18 @@
+ #ifdef IM_DEBUG_PROBE
+                       printk(".");
+ #endif
+-                      if (id != subsystem_pun(shpnt)) {
++                      if (id != subsystem_pun(host_index)) {
+                               /* if pun is not the adapter: */
+                               /* set ldn=0 to pun,lun */
+-                              immediate_assign(shpnt, id, lun, PROBE_LDN, SET_LDN);
+-                              if (device_inquiry(shpnt, PROBE_LDN)) { /* probe device */
+-                                      get_scsi(shpnt)[id][lun] = (unsigned char) (ld(shpnt)[PROBE_LDN].buf[0]);
++                              immediate_assign(host_index, id, lun, PROBE_LDN, SET_LDN);
++                              if (device_inquiry(host_index, PROBE_LDN)) {    /* probe device */
++                                      get_scsi(host_index)[id][lun] = (unsigned char) (ld(host_index)[PROBE_LDN].buf[0]);
+                                       /* entry, even for NO_LUN */
+-                                      if (ld(shpnt)[PROBE_LDN].buf[0] != TYPE_NO_LUN)
++                                      if (ld(host_index)[PROBE_LDN].buf[0] != TYPE_NO_LUN)
+                                               count_devices++;        /* a existing device is found */
+                               }
+                               /* remove ldn */
+-                              immediate_assign(shpnt, id, lun, PROBE_LDN, REMOVE_LDN);
++                              immediate_assign(host_index, id, lun, PROBE_LDN, REMOVE_LDN);
+                       }
+               }
+ #ifndef IM_DEBUG_PROBE
+@@ -1237,16 +1227,16 @@
+ #ifdef IM_DEBUG_PROBE
+                       printk(".");
+ #endif
+-                      if (id != subsystem_pun(shpnt)) {
+-                              if (get_scsi(shpnt)[id][lun] != TYPE_NO_LUN && get_scsi(shpnt)[id][lun] != TYPE_NO_DEVICE) {
++                      if (id != subsystem_pun(host_index)) {
++                              if (get_scsi(host_index)[id][lun] != TYPE_NO_LUN && get_scsi(host_index)[id][lun] != TYPE_NO_DEVICE) {
+                                       /* Only map if accepted type. Always enter for
+                                          lun == 0 to get no gaps into ldn-mapping for ldn<7. */
+-                                      immediate_assign(shpnt, id, lun, ldn, SET_LDN);
+-                                      get_ldn(shpnt)[id][lun] = ldn;  /* map ldn */
+-                                      if (device_exists(shpnt, ldn, &ld(shpnt)[ldn].block_length, &ld(shpnt)[ldn].device_type)) {
++                                      immediate_assign(host_index, id, lun, ldn, SET_LDN);
++                                      get_ldn(host_index)[id][lun] = ldn;     /* map ldn */
++                                      if (device_exists(host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) {
+ #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
+                                               printk("resetting device at ldn=%x ... ", ldn);
+-                                              immediate_reset(shpnt, ldn);
++                                              immediate_reset(host_index, ldn);
+ #endif
+                                               ldn++;
+                                       } else {
+@@ -1254,15 +1244,15 @@
+                                                * handle it or because it has problems */
+                                               if (lun > 0) {
+                                                       /* remove mapping */
+-                                                      get_ldn(shpnt)[id][lun] = TYPE_NO_DEVICE;
+-                                                      immediate_assign(shpnt, 0, 0, ldn, REMOVE_LDN);
++                                                      get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;
++                                                      immediate_assign(host_index, 0, 0, ldn, REMOVE_LDN);
+                                               } else
+                                                       ldn++;
+                                       }
+                               } else if (lun == 0) {
+                                       /* map lun == 0, even if no device exists */
+-                                      immediate_assign(shpnt, id, lun, ldn, SET_LDN);
+-                                      get_ldn(shpnt)[id][lun] = ldn;  /* map ldn */
++                                      immediate_assign(host_index, id, lun, ldn, SET_LDN);
++                                      get_ldn(host_index)[id][lun] = ldn;     /* map ldn */
+                                       ldn++;
+                               }
+                       }
+@@ -1272,14 +1262,14 @@
+       /* map remaining ldns to non-existing devices */
+       for (lun = 1; lun < 8 && ldn < MAX_LOG_DEV; lun++)
+               for (id = 0; id < max_pun && ldn < MAX_LOG_DEV; id++) {
+-                      if (get_scsi(shpnt)[id][lun] == TYPE_NO_LUN || get_scsi(shpnt)[id][lun] == TYPE_NO_DEVICE) {
++                      if (get_scsi(host_index)[id][lun] == TYPE_NO_LUN || get_scsi(host_index)[id][lun] == TYPE_NO_DEVICE) {
+                               probe_display(1);
+                               /* Map remaining ldns only to NON-existing pun,lun
+                                  combinations to make sure an inquiry will fail.
+                                  For MULTI_LUN, it is needed to avoid adapter autonome
+                                  SCSI-remapping. */
+-                              immediate_assign(shpnt, id, lun, ldn, SET_LDN);
+-                              get_ldn(shpnt)[id][lun] = ldn;
++                              immediate_assign(host_index, id, lun, ldn, SET_LDN);
++                              get_ldn(host_index)[id][lun] = ldn;
+                               ldn++;
+                       }
+               }
+@@ -1302,51 +1292,51 @@
+       for (id = 0; id < max_pun; id++) {
+               printk("%2d     ", id);
+               for (lun = 0; lun < 8; lun++)
+-                      printk("%2s ", ti_p(get_scsi(shpnt)[id][lun]));
++                      printk("%2s ", ti_p(get_scsi(host_index)[id][lun]));
+               printk("      %2d     ", id);
+               for (lun = 0; lun < 8; lun++)
+-                      printk("%2s ", ti_l(get_ldn(shpnt)[id][lun]));
++                      printk("%2s ", ti_l(get_ldn(host_index)[id][lun]));
+               printk("\n");
+       }
+ #endif
  
--              kaddr = kmap_atomic(page, KM_USER0);
--              memset(kaddr+block_start, 0, bh->b_size);
--              flush_dcache_page(page);
--              kunmap_atomic(kaddr, KM_USER0);
-+              zero_user_page(page, block_start, bh->b_size, KM_USER0);
-               set_buffer_uptodate(bh);
-               mark_buffer_dirty(bh);
+       /* assign total number of found SCSI-devices to the statistics struct */
+-      IBM_DS(shpnt).total_scsi_devices = count_devices;
++      IBM_DS(host_index).total_scsi_devices = count_devices;
  
-@@ -783,217 +779,240 @@
-       return ret;
+       /* decide for output in /proc-filesystem, if the configuration of
+          SCSI-devices makes dynamical reassignment of devices necessary */
+       if (count_devices >= MAX_LOG_DEV)
+-              IBM_DS(shpnt).dyn_flag = 1;     /* dynamical assignment is necessary */
++              IBM_DS(host_index).dyn_flag = 1;        /* dynamical assignment is necessary */
+       else
+-              IBM_DS(shpnt).dyn_flag = 0;     /* dynamical assignment is not necessary */
++              IBM_DS(host_index).dyn_flag = 0;        /* dynamical assignment is not necessary */
+       /* If no SCSI-devices are assigned, return 1 in order to cause message. */
+       if (ldn == 0)
+               printk("IBM MCA SCSI: Warning: No SCSI-devices found/assigned!\n");
+       /* reset the counters for statistics on the current adapter */
+-      IBM_DS(shpnt).scbs = 0;
+-      IBM_DS(shpnt).long_scbs = 0;
+-      IBM_DS(shpnt).total_accesses = 0;
+-      IBM_DS(shpnt).total_interrupts = 0;
+-      IBM_DS(shpnt).dynamical_assignments = 0;
+-      memset(IBM_DS(shpnt).ldn_access, 0x0, sizeof(IBM_DS(shpnt).ldn_access));
+-      memset(IBM_DS(shpnt).ldn_read_access, 0x0, sizeof(IBM_DS(shpnt).ldn_read_access));
+-      memset(IBM_DS(shpnt).ldn_write_access, 0x0, sizeof(IBM_DS(shpnt).ldn_write_access));
+-      memset(IBM_DS(shpnt).ldn_inquiry_access, 0x0, sizeof(IBM_DS(shpnt).ldn_inquiry_access));
+-      memset(IBM_DS(shpnt).ldn_modeselect_access, 0x0, sizeof(IBM_DS(shpnt).ldn_modeselect_access));
+-      memset(IBM_DS(shpnt).ldn_assignments, 0x0, sizeof(IBM_DS(shpnt).ldn_assignments));
++      IBM_DS(host_index).scbs = 0;
++      IBM_DS(host_index).long_scbs = 0;
++      IBM_DS(host_index).total_accesses = 0;
++      IBM_DS(host_index).total_interrupts = 0;
++      IBM_DS(host_index).dynamical_assignments = 0;
++      memset(IBM_DS(host_index).ldn_access, 0x0, sizeof(IBM_DS(host_index).ldn_access));
++      memset(IBM_DS(host_index).ldn_read_access, 0x0, sizeof(IBM_DS(host_index).ldn_read_access));
++      memset(IBM_DS(host_index).ldn_write_access, 0x0, sizeof(IBM_DS(host_index).ldn_write_access));
++      memset(IBM_DS(host_index).ldn_inquiry_access, 0x0, sizeof(IBM_DS(host_index).ldn_inquiry_access));
++      memset(IBM_DS(host_index).ldn_modeselect_access, 0x0, sizeof(IBM_DS(host_index).ldn_modeselect_access));
++      memset(IBM_DS(host_index).ldn_assignments, 0x0, sizeof(IBM_DS(host_index).ldn_assignments));
+       probe_display(0);
+       return;
  }
  
-+#if (PAGE_CACHE_SIZE >= OCFS2_MAX_CLUSTERSIZE)
-+#define OCFS2_MAX_CTXT_PAGES  1
-+#else
-+#define OCFS2_MAX_CTXT_PAGES  (OCFS2_MAX_CLUSTERSIZE / PAGE_CACHE_SIZE)
-+#endif
-+
-+#define OCFS2_MAX_CLUSTERS_PER_PAGE   (PAGE_CACHE_SIZE / OCFS2_MIN_CLUSTERSIZE)
-+
- /*
-- * This will copy user data from the buffer page in the splice
-- * context.
-- *
-- * For now, we ignore SPLICE_F_MOVE as that would require some extra
-- * communication out all the way to ocfs2_write().
-+ * Describe the state of a single cluster to be written to.
-  */
--int ocfs2_map_and_write_splice_data(struct inode *inode,
--                                struct ocfs2_write_ctxt *wc, u64 *p_blkno,
--                                unsigned int *ret_from, unsigned int *ret_to)
-+struct ocfs2_write_cluster_desc {
-+      u32             c_cpos;
-+      u32             c_phys;
-+      /*
-+       * Give this a unique field because c_phys eventually gets
-+       * filled.
-+       */
-+      unsigned        c_new;
-+      unsigned        c_unwritten;
-+};
-+
-+static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d)
+-static int device_exists(struct Scsi_Host *shpnt, int ldn, int *block_length, int *device_type)
++static int device_exists(int host_index, int ldn, int *block_length, int *device_type)
  {
--      int ret;
--      unsigned int to, from, cluster_start, cluster_end;
--      char *src, *dst;
--      struct ocfs2_splice_write_priv *sp = wc->w_private;
--      struct pipe_buffer *buf = sp->s_buf;
--      unsigned long bytes, src_from;
--      struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-+      return d->c_new || d->c_unwritten;
-+}
+       unsigned char *buf;
+       /* if no valid device found, return immediately with 0 */
+-      if (!(device_inquiry(shpnt, ldn)))
++      if (!(device_inquiry(host_index, ldn)))
+               return 0;
+-      buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
++      buf = (unsigned char *) (&(ld(host_index)[ldn].buf));
+       if (*buf == TYPE_ROM) {
+               *device_type = TYPE_ROM;
+               *block_length = 2048;   /* (standard blocksize for yellow-/red-book) */
+@@ -1359,7 +1349,7 @@
+       }
+       if (*buf == TYPE_DISK) {
+               *device_type = TYPE_DISK;
+-              if (read_capacity(shpnt, ldn)) {
++              if (read_capacity(host_index, ldn)) {
+                       *block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24);
+                       return 1;
+               } else
+@@ -1367,7 +1357,7 @@
+       }
+       if (*buf == TYPE_MOD) {
+               *device_type = TYPE_MOD;
+-              if (read_capacity(shpnt, ldn)) {
++              if (read_capacity(host_index, ldn)) {
+                       *block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24);
+                       return 1;
+               } else
+@@ -1440,9 +1430,6 @@
+       return;
+ }
  
--      ocfs2_figure_cluster_boundaries(osb, wc->w_cpos, &cluster_start,
--                                      &cluster_end);
-+struct ocfs2_write_ctxt {
-+      /* Logical cluster position / len of write */
-+      u32                             w_cpos;
-+      u32                             w_clen;
+-#if 0
+- FIXME NEED TO MOVE TO SYSFS
+-
+ static int ibmmca_getinfo(char *buf, int slot, void *dev_id)
+ {
+       struct Scsi_Host *shpnt;
+@@ -1493,34 +1480,58 @@
  
--      from = sp->s_offset;
--      src_from = sp->s_buf_offset;
--      bytes = wc->w_count;
-+      struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE];
+       return len;
+ }
+-#endif
  
--      if (wc->w_large_pages) {
-               /*
--               * For cluster size < page size, we have to
--               * calculate pos within the cluster and obey
--               * the rightmost boundary.
--               */
--              bytes = min(bytes, (unsigned long)(osb->s_clustersize
--                                 - (wc->w_pos & (osb->s_clustersize - 1))));
--      }
--      to = from + bytes;
--
--      BUG_ON(from > PAGE_CACHE_SIZE);
--      BUG_ON(to > PAGE_CACHE_SIZE);
--      BUG_ON(from < cluster_start);
--      BUG_ON(to > cluster_end);
+-static struct scsi_host_template ibmmca_driver_template = {
+-          .proc_name      = "ibmmca",
+-        .proc_info      = ibmmca_proc_info,
+-          .name           = "IBM SCSI-Subsystem",
+-          .queuecommand   = ibmmca_queuecommand,
+-        .eh_abort_handler = ibmmca_abort,
+-        .eh_host_reset_handler = ibmmca_host_reset,
+-          .bios_param     = ibmmca_biosparam,
+-          .can_queue      = 16,
+-          .this_id        = 7,
+-          .sg_tablesize   = 16,
+-          .cmd_per_lun    = 1,
+-          .use_clustering = ENABLE_CLUSTERING,
+-};
 -
--      if (wc->w_this_page_new)
--              ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
--                                          cluster_start, cluster_end, 1);
--      else
--              ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
--                                          from, to, 0);
--      if (ret) {
--              mlog_errno(ret);
--              goto out;
-+       * This is true if page_size > cluster_size.
-+       *
-+       * It triggers a set of special cases during write which might
-+       * have to deal with allocating writes to partial pages.
-+       */
-+      unsigned int                    w_large_pages;
-+
-+      /*
-+       * Pages involved in this write.
-+       *
-+       * w_target_page is the page being written to by the user.
-+       *
-+       * w_pages is an array of pages which always contains
-+       * w_target_page, and in the case of an allocating write with
-+       * page_size < cluster size, it will contain zero'd and mapped
-+       * pages adjacent to w_target_page which need to be written
-+       * out in so that future reads from that region will get
-+       * zero's.
-+       */
-+      struct page                     *w_pages[OCFS2_MAX_CTXT_PAGES];
-+      unsigned int                    w_num_pages;
-+      struct page                     *w_target_page;
-+
-+      /*
-+       * ocfs2_write_end() uses this to know what the real range to
-+       * write in the target should be.
-+       */
-+      unsigned int                    w_target_from;
-+      unsigned int                    w_target_to;
-+
-+      /*
-+       * We could use journal_current_handle() but this is cleaner,
-+       * IMHO -Mark
-+       */
-+      handle_t                        *w_handle;
+-static int ibmmca_probe(struct device *dev)
++int ibmmca_detect(struct scsi_host_template * scsi_template)
+ {
+       struct Scsi_Host *shpnt;
+-      int port, id, i, j, k, irq, enabled, ret = -EINVAL;
+-      struct mca_device *mca_dev = to_mca_device(dev);
+-      const char *description = ibmmca_description[mca_dev->index];
++      int port, id, i, j, k, slot;
++      int devices_on_irq_11 = 0;
++      int devices_on_irq_14 = 0;
++      int IRQ14_registered = 0;
++      int IRQ11_registered = 0;
 +
-+      struct buffer_head              *w_di_bh;
++      found = 0;              /* make absolutely sure, that found is set to 0 */
+       /* First of all, print the version number of the driver. This is
+        * important to allow better user bugreports in case of already
+        * having problems with the MCA_bus probing. */
+       printk(KERN_INFO "IBM MCA SCSI: Version %s\n", IBMMCA_SCSI_DRIVER_VERSION);
++      /* if this is not MCA machine, return "nothing found" */
++      if (!MCA_bus) {
++              printk(KERN_INFO "IBM MCA SCSI:  No Microchannel-bus present --> Aborting.\n" "              This machine does not have any IBM MCA-bus\n" "                 or the MCA-Kernel-support is not enabled!\n");
++              return 0;
++      }
 +
-+      struct ocfs2_cached_dealloc_ctxt w_dealloc;
-+};
++#ifdef MODULE
++      /* If the driver is run as module, read from conf.modules or cmd-line */
++      if (boot_options)
++              option_setup(boot_options);
++#endif
 +
-+static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
-+{
-+      int i;
++      /* get interrupt request level */
++      if (request_irq(IM_IRQ, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts)) {
++              printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ);
++              return 0;
++      } else
++              IRQ14_registered++;
++
++      /* if ibmmcascsi setup option was passed to kernel, return "found" */
++      for (i = 0; i < IM_MAX_HOSTS; i++)
++              if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8) {
++                      printk("IBM MCA SCSI: forced detected SCSI Adapter, io=0x%x, scsi id=%d.\n", io_port[i], scsi_id[i]);
++                      if ((shpnt = ibmmca_register(scsi_template, io_port[i], scsi_id[i], FORCED_DETECTION, "forced detected SCSI Adapter"))) {
++                              for (k = 2; k < 7; k++)
++                                      ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = 0;
++                              ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = FORCED_DETECTION;
++                              mca_set_adapter_name(MCA_INTEGSCSI, "forced detected SCSI Adapter");
++                              mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
++                              mca_mark_as_used(MCA_INTEGSCSI);
++                              devices_on_irq_14++;
++                      }
++              }
++      if (found)
++              return found;
 +
-+      for(i = 0; i < wc->w_num_pages; i++) {
-+              if (wc->w_pages[i] == NULL)
-+                      continue;
+       /* The POS2-register of all PS/2 model SCSI-subsystems has the following
+        * interpretation of bits:
+        *                             Bit 7 - 4 : Chip Revision ID (Release)
+@@ -1547,14 +1558,7 @@
+       /* first look for the IBM SCSI integrated subsystem on the motherboard */
+       for (j = 0; j < 8; j++) /* read the pos-information */
+-              pos[j] = mca_device_read_pos(mca_dev, j);
+-      id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */
+-      enabled = (pos[2] &0x01);
+-      if (!enabled) {
+-              printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
+-              printk(KERN_WARNING "              SCSI-operations may not work.\n");
+-      }
+-
++              pos[j] = mca_read_stored_pos(MCA_INTEGSCSI, j);
+       /* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present, but
+        * if we ignore the settings of all surrounding pos registers, it is not
+        * completely sufficient to only check pos2 and pos3. */
+@@ -1562,137 +1566,232 @@
+        * make sure, we see a real integrated onboard SCSI-interface and no
+        * internal system information, which gets mapped to some pos registers
+        * on models 95xx. */
+-      if (mca_dev->slot == MCA_INTEGSCSI &&
+-          ((!pos[0] && !pos[1] && pos[2] > 0 &&
+-            pos[3] > 0 && !pos[4] && !pos[5] &&
+-            !pos[6] && !pos[7]) ||
+-           (pos[0] == 0xff && pos[1] == 0xff &&
+-            pos[2] < 0xff && pos[3] < 0xff &&
+-            pos[4] == 0xff && pos[5] == 0xff &&
+-            pos[6] == 0xff && pos[7] == 0xff))) {
+-              irq = IM_IRQ;
++      if ((!pos[0] && !pos[1] && pos[2] > 0 && pos[3] > 0 && !pos[4] && !pos[5] && !pos[6] && !pos[7]) || (pos[0] == 0xff && pos[1] == 0xff && pos[2] < 0xff && pos[3] < 0xff && pos[4] == 0xff && pos[5] == 0xff && pos[6] == 0xff && pos[7] == 0xff)) {
++              if ((pos[2] & 1) == 1)  /* is the subsystem chip enabled ? */
+                       port = IM_IO_PORT;
+-      } else {
+-              irq = IM_IRQ;
+-              port = IM_IO_PORT + ((pos[2] &0x0e) << 2);
+-              if ((mca_dev->index == IBM_SCSI2_FW) && (pos[6] != 0)) {
++              else {          /* if disabled, no IRQs will be generated, as the chip won't
++                               * listen to the incoming commands and will do really nothing,
++                               * except for listening to the pos-register settings. If this
++                               * happens, I need to hugely think about it, as one has to
++                               * write something to the MCA-Bus pos register in order to
++                               * enable the chip. Normally, IBM-SCSI won't pass the POST,
++                               * when the chip is disabled (see IBM tech. ref.). */
++                      port = IM_IO_PORT;      /* anyway, set the portnumber and warn */
++                      printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n" "              SCSI-operations may not work.\n");
++              }
++              id = (pos[3] & 0xe0) >> 5;      /* this is correct and represents the PUN */
++              /* give detailed information on the subsystem. This helps me
++               * additionally during debugging and analyzing bug-reports. */
++              printk(KERN_INFO "IBM MCA SCSI: IBM Integrated SCSI Controller ffound, io=0x%x, scsi id=%d,\n", port, id);
++              printk(KERN_INFO "              chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible", (pos[2] & 1) ? "enabled." : "disabled.");
 +
-+              unlock_page(wc->w_pages[i]);
-+              mark_page_accessed(wc->w_pages[i]);
-+              page_cache_release(wc->w_pages[i]);
++              /* register the found integrated SCSI-subsystem */
++              if ((shpnt = ibmmca_register(scsi_template, port, id, INTEGRATED_SCSI, "IBM Integrated SCSI Controller"))) 
++              {
++                      for (k = 2; k < 7; k++)
++                              ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
++                      ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI;
++                      mca_set_adapter_name(MCA_INTEGSCSI, "IBM Integrated SCSI Controller");
++                      mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
++                      mca_mark_as_used(MCA_INTEGSCSI);
++                      devices_on_irq_14++;
++              }
++      }
++
++      /* now look for other adapters in MCA slots, */
++      /* determine the number of known IBM-SCSI-subsystem types */
++      /* see the pos[2] dependence to get the adapter port-offset. */
++      for (i = 0; i < ARRAY_SIZE(subsys_list); i++) {
++              /* scan each slot for a fitting adapter id */
++              slot = 0;       /* start at slot 0 */
++              while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot))
++                     != MCA_NOTFOUND) {       /* scan through all slots */
++                      for (j = 0; j < 8; j++) /* read the pos-information */
++                              pos[j] = mca_read_stored_pos(slot, j);
++                      if ((pos[2] & 1) == 1)
++                              /* is the subsystem chip enabled ? */
++                              /* (explanations see above) */
++                              port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
++                      else {
++                              /* anyway, set the portnumber and warn */
++                              port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
++                              printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
++                              printk(KERN_WARNING "              SCSI-operations may not work.\n");
++                      }
++                      if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) {
+                               printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
+                               printk(KERN_ERR "              Impossible to determine adapter PUN!\n");
+                               printk(KERN_ERR "              Guessing adapter PUN = 7.\n");
+                               id = 7;
+                       } else {
+                               id = (pos[3] & 0xe0) >> 5;      /* get subsystem PUN */
+-                      if (mca_dev->index == IBM_SCSI2_FW) {
++                              if (i == IBM_SCSI2_FW) {
+                                       id |= (pos[3] & 0x10) >> 1;     /* get subsystem PUN high-bit
+                                                                        * for F/W adapters */
+                               }
+                       }
+-              if ((mca_dev->index == IBM_SCSI2_FW) &&
+-                  (pos[4] & 0x01) && (pos[6] == 0)) {
++                      if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) {
+                               /* IRQ11 is used by SCSI-2 F/W Adapter/A */
+                               printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
+-                      irq = IM_IRQ_FW;
+-                      }
++                              /* get interrupt request level */
++                              if (request_irq(IM_IRQ_FW, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts)) {
++                                      printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW);
++                              } else
++                                      IRQ11_registered++;
        }
++                      printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id);
++                      if ((pos[2] & 0xf0) == 0xf0)
++                              printk(KERN_DEBUG"              ROM Addr.=off,");
++                      else
++                              printk(KERN_DEBUG "              ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000);
++                      printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled.");
++                      /* register the hostadapter */
++                      if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) {
++                              for (k = 2; k < 8; k++)
++                                      ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
++                              ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i;
++                              mca_set_adapter_name(slot, subsys_list[i].description);
++                              mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt);
++                              mca_mark_as_used(slot);
++                              if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0))
++                                      devices_on_irq_11++;
++                              else
++                                      devices_on_irq_14++;
++                      }
++                      slot++; /* advance to next slot */
++              }               /* advance to next adapter id in the list of IBM-SCSI-subsystems */
++      }
  
--      src = buf->ops->map(sp->s_pipe, buf, 1);
--      dst = kmap_atomic(wc->w_this_page, KM_USER1);
--      memcpy(dst + from, src + src_from, bytes);
--      kunmap_atomic(wc->w_this_page, KM_USER1);
--      buf->ops->unmap(sp->s_pipe, buf, src);
-+      brelse(wc->w_di_bh);
-+      kfree(wc);
+-
+-      /* give detailed information on the subsystem. This helps me
+-       * additionally during debugging and analyzing bug-reports. */
+-      printk(KERN_INFO "IBM MCA SCSI: %s found, io=0x%x, scsi id=%d,\n",
+-             description, port, id);
+-      if (mca_dev->slot == MCA_INTEGSCSI)
+-              printk(KERN_INFO "              chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible", (pos[2] & 1) ? "enabled." : "disabled.");
+-      else {
++      /* now check for SCSI-adapters, mapped to the integrated SCSI
++       * area. E.g. a W/Cache in MCA-slot 9(!). Do the check correct here,
++       * as this is a known effect on some models 95xx. */
++      for (i = 0; i < ARRAY_SIZE(subsys_list); i++) {
++              /* scan each slot for a fitting adapter id */
++              slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI);
++              if (slot != MCA_NOTFOUND) {     /* scan through all slots */
++                      for (j = 0; j < 8; j++) /* read the pos-information */
++                              pos[j] = mca_read_stored_pos(slot, j);
++                      if ((pos[2] & 1) == 1) {        /* is the subsystem chip enabled ? */
++                              /* (explanations see above) */
++                              port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
++                      } else {        /* anyway, set the portnumber and warn */
++                              port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
++                              printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
++                              printk(KERN_WARNING "              SCSI-operations may not work.\n");
++                      }
++                      if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) {
++                              printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
++                              printk(KERN_ERR  "              Impossible to determine adapter PUN!\n");
++                              printk(KERN_ERR "              Guessing adapter PUN = 7.\n");
++                              id = 7;
++                      } else {
++                              id = (pos[3] & 0xe0) >> 5;      /* get subsystem PUN */
++                              if (i == IBM_SCSI2_FW)
++                                      id |= (pos[3] & 0x10) >> 1;     /* get subsystem PUN high-bit
++                                                                       * for F/W adapters */
++                      }
++                      if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) {
++                              /* IRQ11 is used by SCSI-2 F/W Adapter/A */
++                              printk(KERN_DEBUG  "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
++                              /* get interrupt request level */
++                              if (request_irq(IM_IRQ_FW, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts))
++                                      printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW);
++                              else
++                                      IRQ11_registered++;
++                      }
++                      printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id);
+                       if ((pos[2] & 0xf0) == 0xf0)
+                               printk(KERN_DEBUG "              ROM Addr.=off,");
+                       else
+                               printk(KERN_DEBUG "              ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000);
+-
+               printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled.");
++
++                      /* register the hostadapter */
++                      if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) {
++                              for (k = 2; k < 7; k++)
++                                      ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
++                              ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i;
++                              mca_set_adapter_name(slot, subsys_list[i].description);
++                              mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt);
++                              mca_mark_as_used(slot);
++                              if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0))
++                                      devices_on_irq_11++;
++                              else
++                                      devices_on_irq_14++;
+       }
++                      slot++; /* advance to next slot */
++              }               /* advance to next adapter id in the list of IBM-SCSI-subsystems */
++      }
++      if (IRQ11_registered && !devices_on_irq_11)
++              free_irq(IM_IRQ_FW, hosts);     /* no devices on IRQ 11 */
++      if (IRQ14_registered && !devices_on_irq_14)
++              free_irq(IM_IRQ, hosts);        /* no devices on IRQ 14 */
++      if (!devices_on_irq_11 && !devices_on_irq_14)
++              printk(KERN_WARNING "IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n");
++      return found;           /* return the number of found SCSI hosts. Should be 1 or 0. */
 +}
 +
-+static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
-+                                struct ocfs2_super *osb, loff_t pos,
-+                                unsigned len, struct buffer_head *di_bh)
++static struct Scsi_Host *ibmmca_register(struct scsi_host_template * scsi_template, int port, int id, int adaptertype, char *hostname)
 +{
-+      struct ocfs2_write_ctxt *wc;
-+
-+      wc = kzalloc(sizeof(struct ocfs2_write_ctxt), GFP_NOFS);
-+      if (!wc)
-+              return -ENOMEM;
-+
-+      wc->w_cpos = pos >> osb->s_clustersize_bits;
-+      wc->w_clen = ocfs2_clusters_for_bytes(osb->sb, len);
-+      get_bh(di_bh);
-+      wc->w_di_bh = di_bh;
++      struct Scsi_Host *shpnt;
++      int i, j;
++      unsigned int ctrl;
  
--      wc->w_finished_copy = 1;
-+      if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
-+              wc->w_large_pages = 1;
-+      else
-+              wc->w_large_pages = 0;
+       /* check I/O region */
+-      if (!request_region(port, IM_N_IO_PORT, description)) {
++      if (!request_region(port, IM_N_IO_PORT, hostname)) {
+               printk(KERN_ERR "IBM MCA SCSI: Unable to get I/O region 0x%x-0x%x (%d ports).\n", port, port + IM_N_IO_PORT - 1, IM_N_IO_PORT);
+-              goto out_fail;
++              return NULL;
+       }
  
--      *ret_from = from;
--      *ret_to = to;
--out:
-+      ocfs2_init_dealloc_ctxt(&wc->w_dealloc);
+       /* register host */
+-      shpnt = scsi_host_alloc(&ibmmca_driver_template,
+-                              sizeof(struct ibmmca_hostdata));
++      shpnt = scsi_register(scsi_template, sizeof(struct ibmmca_hostdata));
+       if (!shpnt) {
+               printk(KERN_ERR "IBM MCA SCSI: Unable to register host.\n");
+-              goto out_release;
+-      }
+-
+-      dev_set_drvdata(dev, shpnt);
+-      if(request_irq(irq, interrupt_handler, IRQF_SHARED, description, dev)) {
+-              printk(KERN_ERR "IBM MCA SCSI: failed to request interrupt %d\n", irq);
+-              goto out_free_host;
++              release_region(port, IM_N_IO_PORT);
++              return NULL;
+       }
  
--      return bytes ? (unsigned int)bytes : ret;
-+      *wcp = wc;
-+
-+      return 0;
- }
+       /* request I/O region */
+-      special(shpnt) = mca_dev->index;        /* important assignment or else crash! */
+-      subsystem_connector_size(shpnt) = 0;    /* preset slot-size */
+-      shpnt->irq = irq;       /* assign necessary stuff for the adapter */
++      hosts[found] = shpnt;   /* add new found hostadapter to the list */
++      special(found) = adaptertype;   /* important assignment or else crash! */
++      subsystem_connector_size(found) = 0;    /* preset slot-size */
++      shpnt->irq = IM_IRQ;    /* assign necessary stuff for the adapter */
+       shpnt->io_port = port;
+       shpnt->n_io_port = IM_N_IO_PORT;
+       shpnt->this_id = id;
+       shpnt->max_id = 8;      /* 8 PUNs are default */
+       /* now, the SCSI-subsystem is connected to Linux */
  
- /*
-- * This will copy user data from the iovec in the buffered write
-- * context.
-+ * If a page has any new buffers, zero them out here, and mark them uptodate
-+ * and dirty so they'll be written out (in order to prevent uninitialised
-+ * block data from leaking). And clear the new bit.
-  */
--int ocfs2_map_and_write_user_data(struct inode *inode,
--                                struct ocfs2_write_ctxt *wc, u64 *p_blkno,
--                                unsigned int *ret_from, unsigned int *ret_to)
-+static void ocfs2_zero_new_buffers(struct page *page, unsigned from, unsigned to)
- {
--      int ret;
--      unsigned int to, from, cluster_start, cluster_end;
--      unsigned long bytes, src_from;
--      char *dst;
--      struct ocfs2_buffered_write_priv *bp = wc->w_private;
--      const struct iovec *cur_iov = bp->b_cur_iov;
--      char __user *buf;
--      struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+-#ifdef IM_DEBUG_PROBE
+       ctrl = (unsigned int) (inb(IM_CTR_REG(found))); /* get control-register status */
++#ifdef IM_DEBUG_PROBE
+       printk("IBM MCA SCSI: Control Register contents: %x, status: %x\n", ctrl, inb(IM_STAT_REG(found)));
+       printk("IBM MCA SCSI: This adapters' POS-registers: ");
+       for (i = 0; i < 8; i++)
+               printk("%x ", pos[i]);
+       printk("\n");
+ #endif
+-      reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS;
++      reset_status(found) = IM_RESET_NOT_IN_PROGRESS;
+       for (i = 0; i < 16; i++)        /* reset the tables */
+               for (j = 0; j < 8; j++)
+-                      get_ldn(shpnt)[i][j] = MAX_LOG_DEV;
++                      get_ldn(found)[i][j] = MAX_LOG_DEV;
+       /* check which logical devices exist */
+       /* after this line, local interrupting is possible: */
+-      local_checking_phase_flag(shpnt) = 1;
+-      check_devices(shpnt, mca_dev->index);   /* call by value, using the global variable hosts */
+-      local_checking_phase_flag(shpnt) = 0;
+-
++      local_checking_phase_flag(found) = 1;
++      check_devices(found, adaptertype);      /* call by value, using the global variable hosts */
++      local_checking_phase_flag(found) = 0;
++      found++;                /* now increase index to be prepared for next found subsystem */
+       /* an ibm mca subsystem has been detected */
+-
+-      for (k = 2; k < 7; k++)
+-              ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
+-      ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI;
+-      mca_device_set_name(mca_dev, description);
+-      /* FIXME: NEED TO REPLUMB TO SYSFS
+-         mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
+-      */
+-      mca_device_set_claim(mca_dev, 1);
+-      if (scsi_add_host(shpnt, dev)) {
+-              dev_printk(KERN_ERR, dev, "IBM MCA SCSI: scsi_add_host failed\n");
+-              goto out_free_host;
+-      }
+-      scsi_scan_host(shpnt);
 -
--      ocfs2_figure_cluster_boundaries(osb, wc->w_cpos, &cluster_start,
--                                      &cluster_end);
-+      unsigned int block_start, block_end;
-+      struct buffer_head *head, *bh;
+-      return 0;
+- out_free_host:
+-      scsi_host_put(shpnt);
+- out_release:
+-      release_region(port, IM_N_IO_PORT);
+- out_fail:
+-      return ret;
++      return shpnt;
+ }
  
--      buf = cur_iov->iov_base + bp->b_cur_off;
--      src_from = (unsigned long)buf & ~PAGE_CACHE_MASK;
-+      BUG_ON(!PageLocked(page));
-+      if (!page_has_buffers(page))
-+              return;
+-static int __devexit ibmmca_remove(struct device *dev)
++static int ibmmca_release(struct Scsi_Host *shpnt)
+ {
+-      struct Scsi_Host *shpnt = dev_get_drvdata(dev);
+-      scsi_remove_host(shpnt);
+       release_region(shpnt->io_port, shpnt->n_io_port);
+-      free_irq(shpnt->irq, dev);
++      if (!(--found))
++              free_irq(shpnt->irq, hosts);
+       return 0;
+ }
  
--      from = wc->w_pos & (PAGE_CACHE_SIZE - 1);
-+      bh = head = page_buffers(page);
-+      block_start = 0;
-+      do {
-+              block_end = block_start + bh->b_size;
+@@ -1706,24 +1805,33 @@
+       int current_ldn;
+       int id, lun;
+       int target;
++      int host_index;
+       int max_pun;
+       int i;
+-      struct scatterlist *sg;
++      struct scatterlist *sl;
  
--      /*
--       * This is a lot of comparisons, but it reads quite
--       * easily, which is important here.
--       */
--      /* Stay within the src page */
--      bytes = PAGE_SIZE - src_from;
--      /* Stay within the vector */
--      bytes = min(bytes,
--                  (unsigned long)(cur_iov->iov_len - bp->b_cur_off));
--      /* Stay within count */
--      bytes = min(bytes, (unsigned long)wc->w_count);
--      /*
--       * For clustersize > page size, just stay within
--       * target page, otherwise we have to calculate pos
--       * within the cluster and obey the rightmost
--       * boundary.
--       */
--      if (wc->w_large_pages) {
--              /*
--               * For cluster size < page size, we have to
--               * calculate pos within the cluster and obey
--               * the rightmost boundary.
--               */
--              bytes = min(bytes, (unsigned long)(osb->s_clustersize
--                                 - (wc->w_pos & (osb->s_clustersize - 1))));
--      } else {
--              /*
--               * cluster size > page size is the most common
--               * case - we just stay within the target page
--               * boundary.
--               */
--              bytes = min(bytes, PAGE_CACHE_SIZE - from);
--      }
-+              if (buffer_new(bh)) {
-+                      if (block_end > from && block_start < to) {
-+                              if (!PageUptodate(page)) {
-+                                      unsigned start, end;
--      to = from + bytes;
-+                                      start = max(from, block_start);
-+                                      end = min(to, block_end);
--      BUG_ON(from > PAGE_CACHE_SIZE);
--      BUG_ON(to > PAGE_CACHE_SIZE);
--      BUG_ON(from < cluster_start);
--      BUG_ON(to > cluster_end);
-+                                      zero_user_page(page, start, end - start, KM_USER0);
-+                                      set_buffer_uptodate(bh);
-+                              }
+       shpnt = cmd->device->host;
++      /* search for the right hostadapter */
++      for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
+-      max_pun = subsystem_maxid(shpnt);
++      if (!hosts[host_index]) {       /* invalid hostadapter descriptor address */
++              cmd->result = DID_NO_CONNECT << 16;
++              if (done)
++                      done(cmd);
++              return 0;
++      }
++      max_pun = subsystem_maxid(host_index);
+       if (ibm_ansi_order) {
+               target = max_pun - 1 - cmd->device->id;
+-              if ((target <= subsystem_pun(shpnt)) && (cmd->device->id <= subsystem_pun(shpnt)))
++              if ((target <= subsystem_pun(host_index)) && (cmd->device->id <= subsystem_pun(host_index)))
+                       target--;
+-              else if ((target >= subsystem_pun(shpnt)) && (cmd->device->id >= subsystem_pun(shpnt)))
++              else if ((target >= subsystem_pun(host_index)) && (cmd->device->id >= subsystem_pun(host_index)))
+                       target++;
+       } else
+               target = cmd->device->id;
  
--      if (wc->w_this_page_new)
--              ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
--                                          cluster_start, cluster_end, 1);
--      else
--              ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
--                                          from, to, 0);
--      if (ret) {
--              mlog_errno(ret);
--              goto out;
-+                              clear_buffer_new(bh);
-+                              mark_buffer_dirty(bh);
-+                      }
+       /* if (target,lun) is NO LUN or not existing at all, return error */
+-      if ((get_scsi(shpnt)[target][cmd->device->lun] == TYPE_NO_LUN) || (get_scsi(shpnt)[target][cmd->device->lun] == TYPE_NO_DEVICE)) {
++      if ((get_scsi(host_index)[target][cmd->device->lun] == TYPE_NO_LUN) || (get_scsi(host_index)[target][cmd->device->lun] == TYPE_NO_DEVICE)) {
+               cmd->result = DID_NO_CONNECT << 16;
+               if (done)
+                       done(cmd);
+@@ -1731,16 +1839,16 @@
        }
  
--      dst = kmap(wc->w_this_page);
--      memcpy(dst + from, bp->b_src_buf + src_from, bytes);
--      kunmap(wc->w_this_page);
-+              block_start = block_end;
-+              bh = bh->b_this_page;
-+      } while (bh != head);
-+}
+       /*if (target,lun) unassigned, do further checks... */
+-      ldn = get_ldn(shpnt)[target][cmd->device->lun];
++      ldn = get_ldn(host_index)[target][cmd->device->lun];
+       if (ldn >= MAX_LOG_DEV) {       /* on invalid ldn do special stuff */
+               if (ldn > MAX_LOG_DEV) {        /* dynamical remapping if ldn unassigned */
+-                      current_ldn = next_ldn(shpnt);  /* stop-value for one circle */
+-                      while (ld(shpnt)[next_ldn(shpnt)].cmd) {        /* search for a occupied, but not in */
++                      current_ldn = next_ldn(host_index);     /* stop-value for one circle */
++                      while (ld(host_index)[next_ldn(host_index)].cmd) {      /* search for a occupied, but not in */
+                               /* command-processing ldn. */
+-                              next_ldn(shpnt)++;
+-                              if (next_ldn(shpnt) >= MAX_LOG_DEV)
+-                                      next_ldn(shpnt) = 7;
+-                              if (current_ldn == next_ldn(shpnt)) {   /* One circle done ? */
++                              next_ldn(host_index)++;
++                              if (next_ldn(host_index) >= MAX_LOG_DEV)
++                                      next_ldn(host_index) = 7;
++                              if (current_ldn == next_ldn(host_index)) {      /* One circle done ? */
+                                       /* no non-processing ldn found */
+                                       scmd_printk(KERN_WARNING, cmd,
+       "IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n"
+@@ -1756,56 +1864,56 @@
+                       /* unmap non-processing ldn */
+                       for (id = 0; id < max_pun; id++)
+                               for (lun = 0; lun < 8; lun++) {
+-                                      if (get_ldn(shpnt)[id][lun] == next_ldn(shpnt)) {
+-                                              get_ldn(shpnt)[id][lun] = TYPE_NO_DEVICE;
+-                                              get_scsi(shpnt)[id][lun] = TYPE_NO_DEVICE;
++                                      if (get_ldn(host_index)[id][lun] == next_ldn(host_index)) {
++                                              get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;
++                                              get_scsi(host_index)[id][lun] = TYPE_NO_DEVICE;
+                                               /* unmap entry */
+                                       }
+                               }
+                       /* set reduced interrupt_handler-mode for checking */
+-                      local_checking_phase_flag(shpnt) = 1;
++                      local_checking_phase_flag(host_index) = 1;
+                       /* map found ldn to pun,lun */
+-                      get_ldn(shpnt)[target][cmd->device->lun] = next_ldn(shpnt);
++                      get_ldn(host_index)[target][cmd->device->lun] = next_ldn(host_index);
+                       /* change ldn to the right value, that is now next_ldn */
+-                      ldn = next_ldn(shpnt);
++                      ldn = next_ldn(host_index);
+                       /* unassign all ldns (pun,lun,ldn does not matter for remove) */
+-                      immediate_assign(shpnt, 0, 0, 0, REMOVE_LDN);
++                      immediate_assign(host_index, 0, 0, 0, REMOVE_LDN);
+                       /* set only LDN for remapped device */
+-                      immediate_assign(shpnt, target, cmd->device->lun, ldn, SET_LDN);
++                      immediate_assign(host_index, target, cmd->device->lun, ldn, SET_LDN);
+                       /* get device information for ld[ldn] */
+-                      if (device_exists(shpnt, ldn, &ld(shpnt)[ldn].block_length, &ld(shpnt)[ldn].device_type)) {
+-                              ld(shpnt)[ldn].cmd = NULL;      /* To prevent panic set 0, because
++                      if (device_exists(host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) {
++                              ld(host_index)[ldn].cmd = NULL; /* To prevent panic set 0, because
+                                                                  devices that were not assigned,
+                                                                  should have nothing in progress. */
+-                              get_scsi(shpnt)[target][cmd->device->lun] = ld(shpnt)[ldn].device_type;
++                              get_scsi(host_index)[target][cmd->device->lun] = ld(host_index)[ldn].device_type;
+                               /* increase assignment counters for statistics in /proc */
+-                              IBM_DS(shpnt).dynamical_assignments++;
+-                              IBM_DS(shpnt).ldn_assignments[ldn]++;
++                              IBM_DS(host_index).dynamical_assignments++;
++                              IBM_DS(host_index).ldn_assignments[ldn]++;
+                       } else
+                               /* panic here, because a device, found at boottime has
+                                  vanished */
+                               panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n", ldn, target, cmd->device->lun);
+                       /* unassign again all ldns (pun,lun,ldn does not matter for remove) */
+-                      immediate_assign(shpnt, 0, 0, 0, REMOVE_LDN);
++                      immediate_assign(host_index, 0, 0, 0, REMOVE_LDN);
+                       /* remap all ldns, as written in the pun/lun table */
+                       lun = 0;
+ #ifdef CONFIG_SCSI_MULTI_LUN
+                       for (lun = 0; lun < 8; lun++)
+ #endif
+                               for (id = 0; id < max_pun; id++) {
+-                                      if (get_ldn(shpnt)[id][lun] <= MAX_LOG_DEV)
+-                                              immediate_assign(shpnt, id, lun, get_ldn(shpnt)[id][lun], SET_LDN);
++                                      if (get_ldn(host_index)[id][lun] <= MAX_LOG_DEV)
++                                              immediate_assign(host_index, id, lun, get_ldn(host_index)[id][lun], SET_LDN);
+                               }
+                       /* set back to normal interrupt_handling */
+-                      local_checking_phase_flag(shpnt) = 0;
++                      local_checking_phase_flag(host_index) = 0;
+ #ifdef IM_DEBUG_PROBE
+                       /* Information on syslog terminal */
+                       printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n", ldn, target, cmd->device->lun);
+ #endif
+                       /* increase next_ldn for next dynamical assignment */
+-                      next_ldn(shpnt)++;
+-                      if (next_ldn(shpnt) >= MAX_LOG_DEV)
+-                              next_ldn(shpnt) = 7;
++                      next_ldn(host_index)++;
++                      if (next_ldn(host_index) >= MAX_LOG_DEV)
++                              next_ldn(host_index) = 7;
+               } else {        /* wall against Linux accesses to the subsystem adapter */
+                       cmd->result = DID_BAD_TARGET << 16;
+                       if (done)
+@@ -1815,32 +1923,34 @@
+       }
  
--      /*
--       * XXX: This is slow, but simple. The caller of
--       * ocfs2_buffered_write_cluster() is responsible for
--       * passing through the iovecs, so it's difficult to
--       * predict what our next step is in here after our
--       * initial write. A future version should be pushing
--       * that iovec manipulation further down.
--       *
--       * By setting this, we indicate that a copy from user
--       * data was done, and subsequent calls for this
--       * cluster will skip copying more data.
-+/*
-+ * Only called when we have a failure during allocating write to write
-+ * zero's to the newly allocated region.
-        */
--      wc->w_finished_copy = 1;
-+static void ocfs2_write_failure(struct inode *inode,
-+                              struct ocfs2_write_ctxt *wc,
-+                              loff_t user_pos, unsigned user_len)
-+{
-+      int i;
-+      unsigned from, to;
-+      struct page *tmppage;
+       /*verify there is no command already in progress for this log dev */
+-      if (ld(shpnt)[ldn].cmd)
++      if (ld(host_index)[ldn].cmd)
+               panic("IBM MCA SCSI: cmd already in progress for this ldn.\n");
  
--      *ret_from = from;
--      *ret_to = to;
--out:
-+      ocfs2_zero_new_buffers(wc->w_target_page, user_pos, user_len);
-+
-+      if (wc->w_large_pages) {
-+              from = wc->w_target_from;
-+              to = wc->w_target_to;
-+      } else {
-+              from = 0;
-+              to = PAGE_CACHE_SIZE;
-+      }
+       /*save done in cmd, and save cmd for the interrupt handler */
+       cmd->scsi_done = done;
+-      ld(shpnt)[ldn].cmd = cmd;
++      ld(host_index)[ldn].cmd = cmd;
  
--      return bytes ? (unsigned int)bytes : ret;
-+      for(i = 0; i < wc->w_num_pages; i++) {
-+              tmppage = wc->w_pages[i];
-+
-+              if (ocfs2_should_order_data(inode))
-+                      walk_page_buffers(wc->w_handle, page_buffers(tmppage),
-+                                        from, to, NULL,
-+                                        ocfs2_journal_dirty_data);
-+
-+              block_commit_write(tmppage, from, to);
-+      }
- }
+       /*fill scb information independent of the scsi command */
+-      scb = &(ld(shpnt)[ldn].scb);
+-      ld(shpnt)[ldn].tsb.dev_status = 0;
++      scb = &(ld(host_index)[ldn].scb);
++      ld(host_index)[ldn].tsb.dev_status = 0;
+       scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE;
+-      scb->tsb_adr = isa_virt_to_bus(&(ld(shpnt)[ldn].tsb));
++      scb->tsb_adr = isa_virt_to_bus(&(ld(host_index)[ldn].tsb));
+       scsi_cmd = cmd->cmnd[0];
  
--/*
-- * Map, fill and write a page to disk.
-- *
-- * The work of copying data is done via callback.  Newly allocated
-- * pages which don't take user data will be zero'd (set 'new' to
-- * indicate an allocating write)
-- *
-- * Returns a negative error code or the number of bytes copied into
-- * the page.
-- */
--static int ocfs2_write_data_page(struct inode *inode, handle_t *handle,
--                               u64 *p_blkno, struct page *page,
--                               struct ocfs2_write_ctxt *wc, int new)
-+static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno,
-+                                      struct ocfs2_write_ctxt *wc,
-+                                      struct page *page, u32 cpos,
-+                                      loff_t user_pos, unsigned user_len,
-+                                      int new)
- {
--      int ret, copied = 0;
--      unsigned int from = 0, to = 0;
-+      int ret;
-+      unsigned int map_from = 0, map_to = 0;
-       unsigned int cluster_start, cluster_end;
--      unsigned int zero_from = 0, zero_to = 0;
-+      unsigned int user_data_from = 0, user_data_to = 0;
+-      if (scsi_sg_count(cmd)) {
+-              BUG_ON(scsi_sg_count(cmd) > 16);
+-
+-              scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) {
+-                      ld(shpnt)[ldn].sge[i].address = (void *) (isa_page_to_bus(sg->page) + sg->offset);
+-                      ld(shpnt)[ldn].sge[i].byte_length = sg->length;
++      if (cmd->use_sg) {
++              i = cmd->use_sg;
++              sl = (struct scatterlist *) (cmd->request_buffer);
++              if (i > 16)
++                      panic("IBM MCA SCSI: scatter-gather list too long.\n");
++              while (--i >= 0) {
++                      ld(host_index)[ldn].sge[i].address = (void *) (isa_page_to_bus(sl[i].page) + sl[i].offset);
++                      ld(host_index)[ldn].sge[i].byte_length = sl[i].length;
+               }
+               scb->enable |= IM_POINTER_TO_LIST;
+-              scb->sys_buf_adr = isa_virt_to_bus(&(ld(shpnt)[ldn].sge[0]));
+-              scb->sys_buf_length = scsi_sg_count(cmd) * sizeof(struct im_sge);
++              scb->sys_buf_adr = isa_virt_to_bus(&(ld(host_index)[ldn].sge[0]));
++              scb->sys_buf_length = cmd->use_sg * sizeof(struct im_sge);
+       } else {
+-              scb->sys_buf_adr = isa_virt_to_bus(scsi_sglist(cmd));
++              scb->sys_buf_adr = isa_virt_to_bus(cmd->request_buffer);
+               /* recent Linux midlevel SCSI places 1024 byte for inquiry
+                * command. Far too much for old PS/2 hardware. */
+               switch (scsi_cmd) {
+@@ -1851,16 +1961,16 @@
+               case REQUEST_SENSE:
+               case MODE_SENSE:
+               case MODE_SELECT:
+-                      if (scsi_bufflen(cmd) > 255)
++                      if (cmd->request_bufflen > 255)
+                               scb->sys_buf_length = 255;
+                       else
+-                              scb->sys_buf_length = scsi_bufflen(cmd);
++                              scb->sys_buf_length = cmd->request_bufflen;
+                       break;
+               case TEST_UNIT_READY:
+                       scb->sys_buf_length = 0;
+                       break;
+               default:
+-                      scb->sys_buf_length = scsi_bufflen(cmd);
++                      scb->sys_buf_length = cmd->request_bufflen;
+                       break;
+               }
+       }
+@@ -1872,16 +1982,16 @@
  
--      ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), wc->w_cpos,
-+      ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos,
-                                       &cluster_start, &cluster_end);
+       /* for specific device-type debugging: */
+ #ifdef IM_DEBUG_CMD_SPEC_DEV
+-      if (ld(shpnt)[ldn].device_type == IM_DEBUG_CMD_DEVICE)
+-              printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(shpnt)[ldn].device_type, scsi_cmd, ldn);
++      if (ld(host_index)[ldn].device_type == IM_DEBUG_CMD_DEVICE)
++              printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(host_index)[ldn].device_type, scsi_cmd, ldn);
+ #endif
  
--      if ((wc->w_pos >> PAGE_CACHE_SHIFT) == page->index
--          && !wc->w_finished_copy) {
-+      if (page == wc->w_target_page) {
-+              map_from = user_pos & (PAGE_CACHE_SIZE - 1);
-+              map_to = map_from + user_len;
+       /* for possible panics store current command */
+-      last_scsi_command(shpnt)[ldn] = scsi_cmd;
+-      last_scsi_type(shpnt)[ldn] = IM_SCB;
++      last_scsi_command(host_index)[ldn] = scsi_cmd;
++      last_scsi_type(host_index)[ldn] = IM_SCB;
+       /* update statistical info */
+-      IBM_DS(shpnt).total_accesses++;
+-      IBM_DS(shpnt).ldn_access[ldn]++;
++      IBM_DS(host_index).total_accesses++;
++      IBM_DS(host_index).ldn_access[ldn]++;
  
--              wc->w_this_page = page;
--              wc->w_this_page_new = new;
--              ret = wc->w_write_data_page(inode, wc, p_blkno, &from, &to);
--              if (ret < 0) {
-+              if (new)
-+                      ret = ocfs2_map_page_blocks(page, p_blkno, inode,
-+                                                  cluster_start, cluster_end,
-+                                                  new);
-+              else
-+                      ret = ocfs2_map_page_blocks(page, p_blkno, inode,
-+                                                  map_from, map_to, new);
-+              if (ret) {
-                       mlog_errno(ret);
-                       goto out;
+       switch (scsi_cmd) {
+       case READ_6:
+@@ -1893,17 +2003,17 @@
+               /* Distinguish between disk and other devices. Only disks (that are the
+                  most frequently accessed devices) should be supported by the
+                  IBM-SCSI-Subsystem commands. */
+-              switch (ld(shpnt)[ldn].device_type) {
++              switch (ld(host_index)[ldn].device_type) {
+               case TYPE_DISK: /* for harddisks enter here ... */
+               case TYPE_MOD:  /* ... try it also for MO-drives (send flames as */
+                       /*     you like, if this won't work.) */
+                       if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) {
+                               /* read command preparations */
+                               scb->enable |= IM_READ_CONTROL;
+-                              IBM_DS(shpnt).ldn_read_access[ldn]++;   /* increase READ-access on ldn stat. */
++                              IBM_DS(host_index).ldn_read_access[ldn]++;      /* increase READ-access on ldn stat. */
+                               scb->command = IM_READ_DATA_CMD | IM_NO_DISCONNECT;
+                       } else {        /* write command preparations */
+-                              IBM_DS(shpnt).ldn_write_access[ldn]++;  /* increase write-count on ldn stat. */
++                              IBM_DS(host_index).ldn_write_access[ldn]++;     /* increase write-count on ldn stat. */
+                               scb->command = IM_WRITE_DATA_CMD | IM_NO_DISCONNECT;
+                       }
+                       if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6) {
+@@ -1913,9 +2023,9 @@
+                               scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) | (((unsigned) cmd->cmnd[4]) << 8) | (((unsigned) cmd->cmnd[3]) << 16) | (((unsigned) cmd->cmnd[2]) << 24);
+                               scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) | (((unsigned) cmd->cmnd[7]) << 8);
+                       }
+-                      last_scsi_logical_block(shpnt)[ldn] = scb->u1.log_blk_adr;
+-                      last_scsi_blockcount(shpnt)[ldn] = scb->u2.blk.count;
+-                      scb->u2.blk.length = ld(shpnt)[ldn].block_length;
++                      last_scsi_logical_block(host_index)[ldn] = scb->u1.log_blk_adr;
++                      last_scsi_blockcount(host_index)[ldn] = scb->u2.blk.count;
++                      scb->u2.blk.length = ld(host_index)[ldn].block_length;
+                       break;
+                       /* for other devices, enter here. Other types are not known by
+                          Linux! TYPE_NO_LUN is forbidden as valid device. */
+@@ -1936,14 +2046,14 @@
+                       scb->enable |= IM_BYPASS_BUFFER;
+                       scb->u1.scsi_cmd_length = cmd->cmd_len;
+                       memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+-                      last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
++                      last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+                       /* Read/write on this non-disk devices is also displayworthy,
+                          so flash-up the LED/display. */
+                       break;
                }
+               break;
+       case INQUIRY:
+-              IBM_DS(shpnt).ldn_inquiry_access[ldn]++;
++              IBM_DS(host_index).ldn_inquiry_access[ldn]++;
+               scb->command = IM_DEVICE_INQUIRY_CMD;
+               scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
+               scb->u1.log_blk_adr = 0;
+@@ -1954,7 +2064,7 @@
+               scb->u1.log_blk_adr = 0;
+               scb->u1.scsi_cmd_length = 6;
+               memcpy(scb->u2.scsi_command, cmd->cmnd, 6);
+-              last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
++              last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+               break;
+       case READ_CAPACITY:
+               /* the length of system memory buffer must be exactly 8 bytes */
+@@ -1971,12 +2081,12 @@
+               /* Commands that need write-only-mode (system -> device): */
+       case MODE_SELECT:
+       case MODE_SELECT_10:
+-              IBM_DS(shpnt).ldn_modeselect_access[ldn]++;
++              IBM_DS(host_index).ldn_modeselect_access[ldn]++;
+               scb->command = IM_OTHER_SCSI_CMD_CMD;
+               scb->enable |= IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;   /*Select needs WRITE-enabled */
+               scb->u1.scsi_cmd_length = cmd->cmd_len;
+               memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+-              last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
++              last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+               break;
+               /* For other commands, read-only is useful. Most other commands are
+                  running without an input-data-block. */
+@@ -1985,19 +2095,19 @@
+               scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
+               scb->u1.scsi_cmd_length = cmd->cmd_len;
+               memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+-              last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
++              last_scsi_type(host_index)[ldn] = IM_LONG_SCB;
+               break;
+       }
+       /*issue scb command, and return */
+       if (++disk_rw_in_progress == 1)
+               PS2_DISK_LED_ON(shpnt->host_no, target);
  
--              copied = ret;
--
--              zero_from = from;
--              zero_to = to;
-+              user_data_from = map_from;
-+              user_data_to = map_to;
-               if (new) {
--                      from = cluster_start;
--                      to = cluster_end;
-+                      map_from = cluster_start;
-+                      map_to = cluster_end;
-               }
-+
-+              wc->w_target_from = map_from;
-+              wc->w_target_to = map_to;
+-      if (last_scsi_type(shpnt)[ldn] == IM_LONG_SCB) {
+-              issue_cmd(shpnt, isa_virt_to_bus(scb), IM_LONG_SCB | ldn);
+-              IBM_DS(shpnt).long_scbs++;
++      if (last_scsi_type(host_index)[ldn] == IM_LONG_SCB) {
++              issue_cmd(host_index, isa_virt_to_bus(scb), IM_LONG_SCB | ldn);
++              IBM_DS(host_index).long_scbs++;
        } else {
-               /*
-                * If we haven't allocated the new page yet, we
-@@ -1002,11 +1021,11 @@
-                */
-               BUG_ON(!new);
+-              issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
+-              IBM_DS(shpnt).scbs++;
++              issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
++              IBM_DS(host_index).scbs++;
+       }
+       return 0;
+ }
+@@ -2012,6 +2122,7 @@
+       unsigned int ldn;
+       void (*saved_done) (Scsi_Cmnd *);
+       int target;
++      int host_index;
+       int max_pun;
+       unsigned long imm_command;
  
--              from = cluster_start;
--              to = cluster_end;
-+              map_from = cluster_start;
-+              map_to = cluster_end;
+@@ -2020,23 +2131,35 @@
+ #endif
  
-               ret = ocfs2_map_page_blocks(page, p_blkno, inode,
--                                          cluster_start, cluster_end, 1);
-+                                          cluster_start, cluster_end, new);
-               if (ret) {
-                       mlog_errno(ret);
-                       goto out;
-@@ -1025,108 +1044,113 @@
-        */
-       if (new && !PageUptodate(page))
-               ocfs2_clear_page_regions(page, OCFS2_SB(inode->i_sb),
--                                       wc->w_cpos, zero_from, zero_to);
-+                                       cpos, user_data_from, user_data_to);
+       shpnt = cmd->device->host;
++      /* search for the right hostadapter */
++      for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
+-      max_pun = subsystem_maxid(shpnt);
++      if (!hosts[host_index]) {       /* invalid hostadapter descriptor address */
++              cmd->result = DID_NO_CONNECT << 16;
++              if (cmd->scsi_done)
++                      (cmd->scsi_done) (cmd);
++              shpnt = cmd->device->host;
++#ifdef IM_DEBUG_PROBE
++              printk(KERN_DEBUG "IBM MCA SCSI: Abort adapter selection failed!\n");
++#endif
++              return SUCCESS;
++      }
++      max_pun = subsystem_maxid(host_index);
+       if (ibm_ansi_order) {
+               target = max_pun - 1 - cmd->device->id;
+-              if ((target <= subsystem_pun(shpnt)) && (cmd->device->id <= subsystem_pun(shpnt)))
++              if ((target <= subsystem_pun(host_index)) && (cmd->device->id <= subsystem_pun(host_index)))
+                       target--;
+-              else if ((target >= subsystem_pun(shpnt)) && (cmd->device->id >= subsystem_pun(shpnt)))
++              else if ((target >= subsystem_pun(host_index)) && (cmd->device->id >= subsystem_pun(host_index)))
+                       target++;
+       } else
+               target = cmd->device->id;
  
-       flush_dcache_page(page);
+       /* get logical device number, and disable system interrupts */
+       printk(KERN_WARNING "IBM MCA SCSI: Sending abort to device pun=%d, lun=%d.\n", target, cmd->device->lun);
+-      ldn = get_ldn(shpnt)[target][cmd->device->lun];
++      ldn = get_ldn(host_index)[target][cmd->device->lun];
  
--      if (ocfs2_should_order_data(inode)) {
--              ret = walk_page_buffers(handle,
--                                      page_buffers(page),
--                                      from, to, NULL,
--                                      ocfs2_journal_dirty_data);
--              if (ret < 0)
--                      mlog_errno(ret);
--      }
--
--      /*
--       * We don't use generic_commit_write() because we need to
--       * handle our own i_size update.
--       */
--      ret = block_commit_write(page, from, to);
--      if (ret)
--              mlog_errno(ret);
- out:
--
--      return copied ? copied : ret;
-+      return ret;
- }
+       /*if cmd for this ldn has already finished, no need to abort */
+-      if (!ld(shpnt)[ldn].cmd) {
++      if (!ld(host_index)[ldn].cmd) {
+                   return SUCCESS;
+       }
+@@ -2047,20 +2170,20 @@
+       saved_done = cmd->scsi_done;
+       cmd->scsi_done = internal_done;
+       cmd->SCp.Status = 0;
+-      last_scsi_command(shpnt)[ldn] = IM_ABORT_IMM_CMD;
+-      last_scsi_type(shpnt)[ldn] = IM_IMM_CMD;
+-      imm_command = inl(IM_CMD_REG(shpnt));
++      last_scsi_command(host_index)[ldn] = IM_ABORT_IMM_CMD;
++      last_scsi_type(host_index)[ldn] = IM_IMM_CMD;
++      imm_command = inl(IM_CMD_REG(host_index));
+       imm_command &= (unsigned long) (0xffff0000);    /* mask reserved stuff */
+       imm_command |= (unsigned long) (IM_ABORT_IMM_CMD);
+       /* must wait for attention reg not busy */
+       /* FIXME - timeout, politeness */
+       while (1) {
+-              if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
++              if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
+                       break;
+       }
+       /* write registers and enable system interrupts */
+-      outl(imm_command, IM_CMD_REG(shpnt));
+-      outb(IM_IMM_CMD | ldn, IM_ATTN_REG(shpnt));
++      outl(imm_command, IM_CMD_REG(host_index));
++      outb(IM_IMM_CMD | ldn, IM_ATTN_REG(host_index));
+ #ifdef IM_DEBUG_PROBE
+       printk("IBM MCA SCSI: Abort queued to adapter...\n");
+ #endif
+@@ -2079,7 +2202,7 @@
+               cmd->result |= DID_ABORT << 16;
+               if (cmd->scsi_done)
+                       (cmd->scsi_done) (cmd);
+-              ld(shpnt)[ldn].cmd = NULL;
++              ld(host_index)[ldn].cmd = NULL;
+ #ifdef IM_DEBUG_PROBE
+               printk("IBM MCA SCSI: Abort finished with success.\n");
+ #endif
+@@ -2088,7 +2211,7 @@
+               cmd->result |= DID_NO_CONNECT << 16;
+               if (cmd->scsi_done)
+                       (cmd->scsi_done) (cmd);
+-              ld(shpnt)[ldn].cmd = NULL;
++              ld(host_index)[ldn].cmd = NULL;
+ #ifdef IM_DEBUG_PROBE
+               printk("IBM MCA SCSI: Abort failed.\n");
+ #endif
+@@ -2113,65 +2236,71 @@
+       struct Scsi_Host *shpnt;
+       Scsi_Cmnd *cmd_aid;
+       int ticks, i;
++      int host_index;
+       unsigned long imm_command;
  
- /*
-- * Do the actual write of some data into an inode. Optionally allocate
-- * in order to fulfill the write.
-- *
-- * cpos is the logical cluster offset within the file to write at
-- *
-- * 'phys' is the physical mapping of that offset. a 'phys' value of
-- * zero indicates that allocation is required. In this case, data_ac
-- * and meta_ac should be valid (meta_ac can be null if metadata
-- * allocation isn't required).
-+ * This function will only grab one clusters worth of pages.
-  */
--static ssize_t ocfs2_write(struct file *file, u32 phys, handle_t *handle,
--                         struct buffer_head *di_bh,
--                         struct ocfs2_alloc_context *data_ac,
--                         struct ocfs2_alloc_context *meta_ac,
--                         struct ocfs2_write_ctxt *wc)
-+static int ocfs2_grab_pages_for_write(struct address_space *mapping,
-+                                    struct ocfs2_write_ctxt *wc,
-+                                    u32 cpos, loff_t user_pos, int new,
-+                                    struct page *mmap_page)
- {
--      int ret, i, numpages = 1, new;
--      unsigned int copied = 0;
--      u32 tmp_pos;
--      u64 v_blkno, p_blkno;
--      struct address_space *mapping = file->f_mapping;
-+      int ret = 0, i;
-+      unsigned long start, target_index, index;
-       struct inode *inode = mapping->host;
--      unsigned long index, start;
--      struct page **cpages;
+       BUG_ON(cmd == NULL);
  
--      new = phys == 0 ? 1 : 0;
-+      target_index = user_pos >> PAGE_CACHE_SHIFT;
+       ticks = IM_RESET_DELAY * HZ;
+       shpnt = cmd->device->host;
++      /* search for the right hostadapter */
++      for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
  
-       /*
-        * Figure out how many pages we'll be manipulating here. For
-        * non allocating write, we just change the one
-        * page. Otherwise, we'll need a whole clusters worth.
-        */
--      if (new)
--              numpages = ocfs2_pages_per_cluster(inode->i_sb);
--
--      cpages = kzalloc(sizeof(*cpages) * numpages, GFP_NOFS);
--      if (!cpages) {
--              ret = -ENOMEM;
--              mlog_errno(ret);
--              return ret;
--      }
--
--      /*
--       * Fill our page array first. That way we've grabbed enough so
--       * that we can zero and flush if we error after adding the
--       * extent.
--       */
-       if (new) {
--              start = ocfs2_align_clusters_to_page_index(inode->i_sb,
--                                                         wc->w_cpos);
--              v_blkno = ocfs2_clusters_to_blocks(inode->i_sb, wc->w_cpos);
-+              wc->w_num_pages = ocfs2_pages_per_cluster(inode->i_sb);
-+              start = ocfs2_align_clusters_to_page_index(inode->i_sb, cpos);
-       } else {
--              start = wc->w_pos >> PAGE_CACHE_SHIFT;
--              v_blkno = wc->w_pos >> inode->i_sb->s_blocksize_bits;
-+              wc->w_num_pages = 1;
-+              start = target_index;
+-      if (local_checking_phase_flag(shpnt)) {
++      if (!hosts[host_index]) /* invalid hostadapter descriptor address */
++              return FAILED;
++
++      if (local_checking_phase_flag(host_index)) {
+               printk(KERN_WARNING "IBM MCA SCSI: unable to reset while checking devices.\n");
+               return FAILED;
        }
  
--      for(i = 0; i < numpages; i++) {
-+      for(i = 0; i < wc->w_num_pages; i++) {
-               index = start + i;
+       /* issue reset immediate command to subsystem, and wait for interrupt */
+       printk("IBM MCA SCSI: resetting all devices.\n");
+-      reset_status(shpnt) = IM_RESET_IN_PROGRESS;
+-      last_scsi_command(shpnt)[0xf] = IM_RESET_IMM_CMD;
+-      last_scsi_type(shpnt)[0xf] = IM_IMM_CMD;
+-      imm_command = inl(IM_CMD_REG(shpnt));
++      reset_status(host_index) = IM_RESET_IN_PROGRESS;
++      last_scsi_command(host_index)[0xf] = IM_RESET_IMM_CMD;
++      last_scsi_type(host_index)[0xf] = IM_IMM_CMD;
++      imm_command = inl(IM_CMD_REG(host_index));
+       imm_command &= (unsigned long) (0xffff0000);    /* mask reserved stuff */
+       imm_command |= (unsigned long) (IM_RESET_IMM_CMD);
+       /* must wait for attention reg not busy */
+       while (1) {
+-              if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
++              if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY))
+                       break;
+               spin_unlock_irq(shpnt->host_lock);
+               yield();
+               spin_lock_irq(shpnt->host_lock);
+       }
+       /*write registers and enable system interrupts */
+-      outl(imm_command, IM_CMD_REG(shpnt));
+-      outb(IM_IMM_CMD | 0xf, IM_ATTN_REG(shpnt));
++      outl(imm_command, IM_CMD_REG(host_index));
++      outb(IM_IMM_CMD | 0xf, IM_ATTN_REG(host_index));
+       /* wait for interrupt finished or intr_stat register to be set, as the
+        * interrupt will not be executed, while we are in here! */
+        
+       /* FIXME: This is really really icky we so want a sleeping version of this ! */
+-      while (reset_status(shpnt) == IM_RESET_IN_PROGRESS && --ticks && ((inb(IM_INTR_REG(shpnt)) & 0x8f) != 0x8f)) {
++      while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks && ((inb(IM_INTR_REG(host_index)) & 0x8f) != 0x8f)) {
+               udelay((1 + 999 / HZ) * 1000);
+               barrier();
+       }
+       /* if reset did not complete, just return an error */
+       if (!ticks) {
+               printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY);
+-              reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
++              reset_status(host_index) = IM_RESET_FINISHED_FAIL;
+               return FAILED;
+       }
  
--              cpages[i] = find_or_create_page(mapping, index, GFP_NOFS);
--              if (!cpages[i]) {
-+              if (index == target_index && mmap_page) {
-+                      /*
-+                       * ocfs2_pagemkwrite() is a little different
-+                       * and wants us to directly use the page
-+                       * passed in.
-+                       */
-+                      lock_page(mmap_page);
-+
-+                      if (mmap_page->mapping != mapping) {
-+                              unlock_page(mmap_page);
-+                              /*
-+                               * Sanity check - the locking in
-+                               * ocfs2_pagemkwrite() should ensure
-+                               * that this code doesn't trigger.
-+                               */
-+                              ret = -EINVAL;
-+                              mlog_errno(ret);
-+                              goto out;
-+                      }
-+
-+                      page_cache_get(mmap_page);
-+                      wc->w_pages[i] = mmap_page;
-+              } else {
-+                      wc->w_pages[i] = find_or_create_page(mapping, index,
-+                                                           GFP_NOFS);
-+                      if (!wc->w_pages[i]) {
-                       ret = -ENOMEM;
-                       mlog_errno(ret);
-                       goto out;
-               }
+-      if ((inb(IM_INTR_REG(shpnt)) & 0x8f) == 0x8f) {
++      if ((inb(IM_INTR_REG(host_index)) & 0x8f) == 0x8f) {
+               /* analysis done by this routine and not by the intr-routine */
+-              if (inb(IM_INTR_REG(shpnt)) == 0xaf)
+-                      reset_status(shpnt) = IM_RESET_FINISHED_OK_NO_INT;
+-              else if (inb(IM_INTR_REG(shpnt)) == 0xcf)
+-                      reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
++              if (inb(IM_INTR_REG(host_index)) == 0xaf)
++                      reset_status(host_index) = IM_RESET_FINISHED_OK_NO_INT;
++              else if (inb(IM_INTR_REG(host_index)) == 0xcf)
++                      reset_status(host_index) = IM_RESET_FINISHED_FAIL;
+               else            /* failed, 4get it */
+-                      reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS_NO_INT;
+-              outb(IM_EOI | 0xf, IM_ATTN_REG(shpnt));
++                      reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS_NO_INT;
++              outb(IM_EOI | 0xf, IM_ATTN_REG(host_index));
        }
  
-+              if (index == target_index)
-+                      wc->w_target_page = wc->w_pages[i];
-+      }
-+out:
-+      return ret;
-+}
-+
-+/*
-+ * Prepare a single cluster for write one cluster into the file.
-+ */
-+static int ocfs2_write_cluster(struct address_space *mapping,
-+                             u32 phys, unsigned int unwritten,
-+                             struct ocfs2_alloc_context *data_ac,
-+                             struct ocfs2_alloc_context *meta_ac,
-+                             struct ocfs2_write_ctxt *wc, u32 cpos,
-+                             loff_t user_pos, unsigned user_len)
-+{
-+      int ret, i, new, should_zero = 0;
-+      u64 v_blkno, p_blkno;
-+      struct inode *inode = mapping->host;
-+
-+      new = phys == 0 ? 1 : 0;
-+      if (new || unwritten)
-+              should_zero = 1;
-+
-       if (new) {
-+              u32 tmp_pos;
-+
-               /*
-                * This is safe to call with the page locks - it won't take
-                * any additional semaphores or cluster locks.
-                */
--              tmp_pos = wc->w_cpos;
-+              tmp_pos = cpos;
-               ret = ocfs2_do_extend_allocation(OCFS2_SB(inode->i_sb), inode,
--                                               &tmp_pos, 1, di_bh, handle,
--                                               data_ac, meta_ac, NULL);
-+                                               &tmp_pos, 1, 0, wc->w_di_bh,
-+                                               wc->w_handle, data_ac,
-+                                               meta_ac, NULL);
-               /*
-                * This shouldn't happen because we must have already
-                * calculated the correct meta data allocation required. The
-@@ -1143,159 +1167,433 @@
-                       mlog_errno(ret);
-                       goto out;
+       /* if reset failed, just return an error */
+-      if (reset_status(shpnt) == IM_RESET_FINISHED_FAIL) {
++      if (reset_status(host_index) == IM_RESET_FINISHED_FAIL) {
+               printk(KERN_ERR "IBM MCA SCSI: reset failed.\n");
+               return FAILED;
+       }
+@@ -2179,9 +2308,9 @@
+       /* so reset finished ok - call outstanding done's, and return success */
+       printk(KERN_INFO "IBM MCA SCSI: Reset successfully completed.\n");
+       for (i = 0; i < MAX_LOG_DEV; i++) {
+-              cmd_aid = ld(shpnt)[i].cmd;
++              cmd_aid = ld(host_index)[i].cmd;
+               if (cmd_aid && cmd_aid->scsi_done) {
+-                      ld(shpnt)[i].cmd = NULL;
++                      ld(host_index)[i].cmd = NULL;
+                       cmd_aid->result = DID_RESET << 16;
                }
-+      } else if (unwritten) {
-+              ret = ocfs2_mark_extent_written(inode, wc->w_di_bh,
-+                                              wc->w_handle, cpos, 1, phys,
-+                                              meta_ac, &wc->w_dealloc);
-+              if (ret < 0) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
        }
+@@ -2222,46 +2351,46 @@
+ }
  
-+      if (should_zero)
-+              v_blkno = ocfs2_clusters_to_blocks(inode->i_sb, cpos);
-+      else
-+              v_blkno = user_pos >> inode->i_sb->s_blocksize_bits;
-+
-+      /*
-+       * The only reason this should fail is due to an inability to
-+       * find the extent added.
-+       */
-       ret = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, NULL,
-                                         NULL);
-       if (ret < 0) {
-+              ocfs2_error(inode->i_sb, "Corrupting extend for inode %llu, "
-+                          "at logical block %llu",
-+                          (unsigned long long)OCFS2_I(inode)->ip_blkno,
-+                          (unsigned long long)v_blkno);
-+              goto out;
-+      }
-+
-+      BUG_ON(p_blkno == 0);
-+
-+      for(i = 0; i < wc->w_num_pages; i++) {
-+              int tmpret;
-+
-+              tmpret = ocfs2_prepare_page_for_write(inode, &p_blkno, wc,
-+                                                    wc->w_pages[i], cpos,
-+                                                    user_pos, user_len,
-+                                                    should_zero);
-+              if (tmpret) {
-+                      mlog_errno(tmpret);
-+                      if (ret == 0)
-+                              tmpret = ret;
-+              }
-+      }
-               /*
--               * XXX: Should we go readonly here?
-+       * We only have cleanup to do in case of allocating write.
-                */
-+      if (ret && new)
-+              ocfs2_write_failure(inode, wc, user_pos, user_len);
+ /* calculate percentage of total accesses on a ldn */
+-static int ldn_access_load(struct Scsi_Host *shpnt, int ldn)
++static int ldn_access_load(int host_index, int ldn)
+ {
+-      if (IBM_DS(shpnt).total_accesses == 0)
++      if (IBM_DS(host_index).total_accesses == 0)
+               return (0);
+-      if (IBM_DS(shpnt).ldn_access[ldn] == 0)
++      if (IBM_DS(host_index).ldn_access[ldn] == 0)
+               return (0);
+-      return (IBM_DS(shpnt).ldn_access[ldn] * 100) / IBM_DS(shpnt).total_accesses;
++      return (IBM_DS(host_index).ldn_access[ldn] * 100) / IBM_DS(host_index).total_accesses;
+ }
  
--              mlog_errno(ret);
--              goto out;
--      }
-+out:
+ /* calculate total amount of r/w-accesses */
+-static int ldn_access_total_read_write(struct Scsi_Host *shpnt)
++static int ldn_access_total_read_write(int host_index)
+ {
+       int a;
+       int i;
  
--      BUG_ON(p_blkno == 0);
-+      return ret;
-+}
+       a = 0;
+       for (i = 0; i <= MAX_LOG_DEV; i++)
+-              a += IBM_DS(shpnt).ldn_read_access[i] + IBM_DS(shpnt).ldn_write_access[i];
++              a += IBM_DS(host_index).ldn_read_access[i] + IBM_DS(host_index).ldn_write_access[i];
+       return (a);
+ }
  
--      for(i = 0; i < numpages; i++) {
--              ret = ocfs2_write_data_page(inode, handle, &p_blkno, cpages[i],
--                                          wc, new);
--              if (ret < 0) {
-+static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
-+                                     struct ocfs2_alloc_context *data_ac,
-+                                     struct ocfs2_alloc_context *meta_ac,
-+                                     struct ocfs2_write_ctxt *wc,
-+                                     loff_t pos, unsigned len)
-+{
-+      int ret, i;
-+      struct ocfs2_write_cluster_desc *desc;
-+
-+      for (i = 0; i < wc->w_clen; i++) {
-+              desc = &wc->w_desc[i];
-+
-+              ret = ocfs2_write_cluster(mapping, desc->c_phys,
-+                                        desc->c_unwritten, data_ac, meta_ac,
-+                                        wc, desc->c_cpos, pos, len);
-+              if (ret) {
-                       mlog_errno(ret);
-                       goto out;
-               }
--
--              copied += ret;
-       }
+-static int ldn_access_total_inquiry(struct Scsi_Host *shpnt)
++static int ldn_access_total_inquiry(int host_index)
+ {
+       int a;
+       int i;
  
-+      ret = 0;
- out:
--      for(i = 0; i < numpages; i++) {
--              unlock_page(cpages[i]);
--              mark_page_accessed(cpages[i]);
--              page_cache_release(cpages[i]);
--      }
--      kfree(cpages);
--
--      return copied ? copied : ret;
-+      return ret;
+       a = 0;
+       for (i = 0; i <= MAX_LOG_DEV; i++)
+-              a += IBM_DS(shpnt).ldn_inquiry_access[i];
++              a += IBM_DS(host_index).ldn_inquiry_access[i];
+       return (a);
  }
  
--static void ocfs2_write_ctxt_init(struct ocfs2_write_ctxt *wc,
--                                struct ocfs2_super *osb, loff_t pos,
--                                size_t count, ocfs2_page_writer *cb,
--                                void *cb_priv)
-+/*
-+ * ocfs2_write_end() wants to know which parts of the target page it
-+ * should complete the write on. It's easiest to compute them ahead of
-+ * time when a more complete view of the write is available.
-+ */
-+static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
-+                                      struct ocfs2_write_ctxt *wc,
-+                                      loff_t pos, unsigned len, int alloc)
+-static int ldn_access_total_modeselect(struct Scsi_Host *shpnt)
++static int ldn_access_total_modeselect(int host_index)
  {
--      wc->w_count = count;
--      wc->w_pos = pos;
--      wc->w_cpos = wc->w_pos >> osb->s_clustersize_bits;
--      wc->w_finished_copy = 0;
-+      struct ocfs2_write_cluster_desc *desc;
--      if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
--              wc->w_large_pages = 1;
--      else
--              wc->w_large_pages = 0;
-+      wc->w_target_from = pos & (PAGE_CACHE_SIZE - 1);
-+      wc->w_target_to = wc->w_target_from + len;
-+
-+      if (alloc == 0)
-+              return;
-+
-+      /*
-+       * Allocating write - we may have different boundaries based
-+       * on page size and cluster size.
-+       *
-+       * NOTE: We can no longer compute one value from the other as
-+       * the actual write length and user provided length may be
-+       * different.
-+       */
+       int a;
+       int i;
  
--      wc->w_write_data_page = cb;
--      wc->w_private = cb_priv;
-+      if (wc->w_large_pages) {
-+              /*
-+               * We only care about the 1st and last cluster within
-+               * our range and whether they should be zero'd or not. Either
-+               * value may be extended out to the start/end of a
-+               * newly allocated cluster.
-+               */
-+              desc = &wc->w_desc[0];
-+              if (ocfs2_should_zero_cluster(desc))
-+                      ocfs2_figure_cluster_boundaries(osb,
-+                                                      desc->c_cpos,
-+                                                      &wc->w_target_from,
-+                                                      NULL);
-+
-+              desc = &wc->w_desc[wc->w_clen - 1];
-+              if (ocfs2_should_zero_cluster(desc))
-+                      ocfs2_figure_cluster_boundaries(osb,
-+                                                      desc->c_cpos,
-+                                                      NULL,
-+                                                      &wc->w_target_to);
-+      } else {
-+              wc->w_target_from = 0;
-+              wc->w_target_to = PAGE_CACHE_SIZE;
-+      }
+       a = 0;
+       for (i = 0; i <= MAX_LOG_DEV; i++)
+-              a += IBM_DS(shpnt).ldn_modeselect_access[i];
++              a += IBM_DS(host_index).ldn_modeselect_access[i];
+       return (a);
  }
  
- /*
-- * Write a cluster to an inode. The cluster may not be allocated yet,
-- * in which case it will be. This only exists for buffered writes -
-- * O_DIRECT takes a more "traditional" path through the kernel.
-+ * Populate each single-cluster write descriptor in the write context
-+ * with information about the i/o to be done.
-  *
-- * The caller is responsible for incrementing pos, written counts, etc
-- *
-- * For file systems that don't support sparse files, pre-allocation
-- * and page zeroing up until cpos should be done prior to this
-- * function call.
-- *
-- * Callers should be holding i_sem, and the rw cluster lock.
-+ * Returns the number of clusters that will have to be allocated, as
-+ * well as a worst case estimate of the number of extent records that
-+ * would have to be created during a write to an unwritten region.
-+ */
-+static int ocfs2_populate_write_desc(struct inode *inode,
-+                                   struct ocfs2_write_ctxt *wc,
-+                                   unsigned int *clusters_to_alloc,
-+                                   unsigned int *extents_to_split)
-+{
-+      int ret;
-+      struct ocfs2_write_cluster_desc *desc;
-+      unsigned int num_clusters = 0;
-+      unsigned int ext_flags = 0;
-+      u32 phys = 0;
-+      int i;
-+
-+      *clusters_to_alloc = 0;
-+      *extents_to_split = 0;
-+
-+      for (i = 0; i < wc->w_clen; i++) {
-+              desc = &wc->w_desc[i];
-+              desc->c_cpos = wc->w_cpos + i;
-+
-+              if (num_clusters == 0) {
-+                      /*
-+                       * Need to look up the next extent record.
-+                       */
-+                      ret = ocfs2_get_clusters(inode, desc->c_cpos, &phys,
-+                                               &num_clusters, &ext_flags);
-+                      if (ret) {
-+                              mlog_errno(ret);
-+                              goto out;
-+                      }
-+
-+                      /*
-+                       * Assume worst case - that we're writing in
-+                       * the middle of the extent.
-  *
-- * Returns the number of user bytes written, or less than zero for
-- * error.
-+                       * We can assume that the write proceeds from
-+                       * left to right, in which case the extent
-+                       * insert code is smart enough to coalesce the
-+                       * next splits into the previous records created.
-  */
--ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
--                                   size_t count, ocfs2_page_writer *actor,
--                                   void *priv)
-+                      if (ext_flags & OCFS2_EXT_UNWRITTEN)
-+                              *extents_to_split = *extents_to_split + 2;
-+              } else if (phys) {
-+                      /*
-+                       * Only increment phys if it doesn't describe
-+                       * a hole.
-+                       */
-+                      phys++;
-+              }
-+
-+              desc->c_phys = phys;
-+              if (phys == 0) {
-+                      desc->c_new = 1;
-+                      *clusters_to_alloc = *clusters_to_alloc + 1;
-+              }
-+              if (ext_flags & OCFS2_EXT_UNWRITTEN)
-+                      desc->c_unwritten = 1;
-+
-+              num_clusters--;
-+      }
-+
-+      ret = 0;
-+out:
-+      return ret;
-+}
-+
-+int ocfs2_write_begin_nolock(struct address_space *mapping,
-+                           loff_t pos, unsigned len, unsigned flags,
-+                           struct page **pagep, void **fsdata,
-+                           struct buffer_head *di_bh, struct page *mmap_page)
+@@ -2269,14 +2398,19 @@
+ static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
  {
-       int ret, credits = OCFS2_INODE_UPDATE_CREDITS;
--      ssize_t written = 0;
--      u32 phys;
--      struct inode *inode = file->f_mapping->host;
-+      unsigned int clusters_to_alloc, extents_to_split;
-+      struct ocfs2_write_ctxt *wc;
-+      struct inode *inode = mapping->host;
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
--      struct buffer_head *di_bh = NULL;
-       struct ocfs2_dinode *di;
-       struct ocfs2_alloc_context *data_ac = NULL;
-       struct ocfs2_alloc_context *meta_ac = NULL;
-       handle_t *handle;
--      struct ocfs2_write_ctxt wc;
+       int len = 0;
+-      int i, id, lun;
++      int i, id, lun, host_index;
+       unsigned long flags;
+       int max_pun;
  
--      ocfs2_write_ctxt_init(&wc, osb, pos, count, actor, priv);
-+      ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh);
-+      if (ret) {
-+              mlog_errno(ret);
-+              return ret;
++      for (i = 0; hosts[i] && hosts[i] != shpnt; i++);
+       
+-      spin_lock_irqsave(shpnt->host_lock, flags);     /* Check it */
+-
+-      max_pun = subsystem_maxid(shpnt);
++      spin_lock_irqsave(hosts[i]->host_lock, flags);  /* Check it */
++      host_index = i;
++      if (!shpnt) {
++              len += sprintf(buffer + len, "\nIBM MCA SCSI: Can't find adapter");
++              return len;
 +      }
++      max_pun = subsystem_maxid(host_index);
  
--      ret = ocfs2_meta_lock(inode, &di_bh, 1);
-+      ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc,
-+                                      &extents_to_split);
-       if (ret) {
-               mlog_errno(ret);
-               goto out;
+       len += sprintf(buffer + len, "\n             IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n", IBMMCA_SCSI_DRIVER_VERSION);
+       len += sprintf(buffer + len, " SCSI Access-Statistics:\n");
+@@ -2287,40 +2421,40 @@
+       len += sprintf(buffer + len, "               Multiple LUN probing.....: No\n");
+ #endif
+       len += sprintf(buffer + len, "               This Hostnumber..........: %d\n", shpnt->host_no);
+-      len += sprintf(buffer + len, "               Base I/O-Port............: 0x%x\n", (unsigned int) (IM_CMD_REG(shpnt)));
++      len += sprintf(buffer + len, "               Base I/O-Port............: 0x%x\n", (unsigned int) (IM_CMD_REG(host_index)));
+       len += sprintf(buffer + len, "               (Shared) IRQ.............: %d\n", IM_IRQ);
+-      len += sprintf(buffer + len, "               Total Interrupts.........: %d\n", IBM_DS(shpnt).total_interrupts);
+-      len += sprintf(buffer + len, "               Total SCSI Accesses......: %d\n", IBM_DS(shpnt).total_accesses);
+-      len += sprintf(buffer + len, "               Total short SCBs.........: %d\n", IBM_DS(shpnt).scbs);
+-      len += sprintf(buffer + len, "               Total long SCBs..........: %d\n", IBM_DS(shpnt).long_scbs);
+-      len += sprintf(buffer + len, "                 Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(shpnt));
+-      len += sprintf(buffer + len, "                 Total SCSI Inquiries...: %d\n", ldn_access_total_inquiry(shpnt));
+-      len += sprintf(buffer + len, "                 Total SCSI Modeselects.: %d\n", ldn_access_total_modeselect(shpnt));
+-      len += sprintf(buffer + len, "                 Total SCSI other cmds..: %d\n", IBM_DS(shpnt).total_accesses - ldn_access_total_read_write(shpnt)
+-                     - ldn_access_total_modeselect(shpnt)
+-                     - ldn_access_total_inquiry(shpnt));
+-      len += sprintf(buffer + len, "               Total SCSI command fails.: %d\n\n", IBM_DS(shpnt).total_errors);
++      len += sprintf(buffer + len, "               Total Interrupts.........: %d\n", IBM_DS(host_index).total_interrupts);
++      len += sprintf(buffer + len, "               Total SCSI Accesses......: %d\n", IBM_DS(host_index).total_accesses);
++      len += sprintf(buffer + len, "               Total short SCBs.........: %d\n", IBM_DS(host_index).scbs);
++      len += sprintf(buffer + len, "               Total long SCBs..........: %d\n", IBM_DS(host_index).long_scbs);
++      len += sprintf(buffer + len, "                 Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(host_index));
++      len += sprintf(buffer + len, "                 Total SCSI Inquiries...: %d\n", ldn_access_total_inquiry(host_index));
++      len += sprintf(buffer + len, "                 Total SCSI Modeselects.: %d\n", ldn_access_total_modeselect(host_index));
++      len += sprintf(buffer + len, "                 Total SCSI other cmds..: %d\n", IBM_DS(host_index).total_accesses - ldn_access_total_read_write(host_index)
++                     - ldn_access_total_modeselect(host_index)
++                     - ldn_access_total_inquiry(host_index));
++      len += sprintf(buffer + len, "               Total SCSI command fails.: %d\n\n", IBM_DS(host_index).total_errors);
+       len += sprintf(buffer + len, " Logical-Device-Number (LDN) Access-Statistics:\n");
+       len += sprintf(buffer + len, "         LDN | Accesses [%%] |   READ    |   WRITE   | ASSIGNMENTS\n");
+       len += sprintf(buffer + len, "        -----|--------------|-----------|-----------|--------------\n");
+       for (i = 0; i <= MAX_LOG_DEV; i++)
+-              len += sprintf(buffer + len, "         %2X  |    %3d       |  %8d |  %8d | %8d\n", i, ldn_access_load(shpnt, i), IBM_DS(shpnt).ldn_read_access[i], IBM_DS(shpnt).ldn_write_access[i], IBM_DS(shpnt).ldn_assignments[i]);
++              len += sprintf(buffer + len, "         %2X  |    %3d       |  %8d |  %8d | %8d\n", i, ldn_access_load(host_index, i), IBM_DS(host_index).ldn_read_access[i], IBM_DS(host_index).ldn_write_access[i], IBM_DS(host_index).ldn_assignments[i]);
+       len += sprintf(buffer + len, "        -----------------------------------------------------------\n\n");
+       len += sprintf(buffer + len, " Dynamical-LDN-Assignment-Statistics:\n");
+-      len += sprintf(buffer + len, "               Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(shpnt).total_scsi_devices);
+-      len += sprintf(buffer + len, "               Dynamical Assignment necessary...: %s\n", IBM_DS(shpnt).dyn_flag ? "Yes" : "No ");
+-      len += sprintf(buffer + len, "               Next LDN to be assigned..........: 0x%x\n", next_ldn(shpnt));
+-      len += sprintf(buffer + len, "               Dynamical assignments done yet...: %d\n", IBM_DS(shpnt).dynamical_assignments);
++      len += sprintf(buffer + len, "               Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(host_index).total_scsi_devices);
++      len += sprintf(buffer + len, "               Dynamical Assignment necessary...: %s\n", IBM_DS(host_index).dyn_flag ? "Yes" : "No ");
++      len += sprintf(buffer + len, "               Next LDN to be assigned..........: 0x%x\n", next_ldn(host_index));
++      len += sprintf(buffer + len, "               Dynamical assignments done yet...: %d\n", IBM_DS(host_index).dynamical_assignments);
+       len += sprintf(buffer + len, "\n Current SCSI-Device-Mapping:\n");
+       len += sprintf(buffer + len, "        Physical SCSI-Device Map               Logical SCSI-Device Map\n");
+       len += sprintf(buffer + len, "    ID\\LUN  0  1  2  3  4  5  6  7       ID\\LUN  0  1  2  3  4  5  6  7\n");
+       for (id = 0; id < max_pun; id++) {
+               len += sprintf(buffer + len, "    %2d     ", id);
+               for (lun = 0; lun < 8; lun++)
+-                      len += sprintf(buffer + len, "%2s ", ti_p(get_scsi(shpnt)[id][lun]));
++                      len += sprintf(buffer + len, "%2s ", ti_p(get_scsi(host_index)[id][lun]));
+               len += sprintf(buffer + len, "      %2d     ", id);
+               for (lun = 0; lun < 8; lun++)
+-                      len += sprintf(buffer + len, "%2s ", ti_l(get_ldn(shpnt)[id][lun]));
++                      len += sprintf(buffer + len, "%2s ", ti_l(get_ldn(host_index)[id][lun]));
+               len += sprintf(buffer + len, "\n");
        }
--      di = (struct ocfs2_dinode *)di_bh->b_data;
-+
-+      di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
  
-       /*
--       * Take alloc sem here to prevent concurrent lookups. That way
--       * the mapping, zeroing and tree manipulation within
--       * ocfs2_write() will be safe against ->readpage(). This
--       * should also serve to lock out allocation from a shared
--       * writeable region.
-+       * We set w_target_from, w_target_to here so that
-+       * ocfs2_write_end() knows which range in the target page to
-+       * write out. An allocation requires that we write the entire
-+       * cluster range.
-        */
--      down_write(&OCFS2_I(inode)->ip_alloc_sem);
--
--      ret = ocfs2_get_clusters(inode, wc.w_cpos, &phys, NULL, NULL);
-+      if (clusters_to_alloc || extents_to_split) {
-+              /*
-+               * XXX: We are stretching the limits of
-+               * ocfs2_lock_allocators(). It greatly over-estimates
-+               * the work to be done.
-+               */
-+              ret = ocfs2_lock_allocators(inode, di, clusters_to_alloc,
-+                                          extents_to_split, &data_ac, &meta_ac);
-       if (ret) {
-               mlog_errno(ret);
--              goto out_meta;
-+                      goto out;
-       }
+@@ -2354,31 +2488,20 @@
  
--      /* phys == 0 means that allocation is required. */
--      if (phys == 0) {
--              ret = ocfs2_lock_allocators(inode, di, 1, &data_ac, &meta_ac);
-+              credits = ocfs2_calc_extend_credits(inode->i_sb, di,
-+                                                  clusters_to_alloc);
-+
-+      }
+ __setup("ibmmcascsi=", option_setup);
+-static struct mca_driver ibmmca_driver = {
+-      .id_table = ibmmca_id_table,
+-      .driver = {
+-              .name   = "ibmmca",
+-              .bus    = &mca_bus_type,
+-              .probe  = ibmmca_probe,
+-              .remove = __devexit_p(ibmmca_remove),
+-      },
++static struct scsi_host_template driver_template = {
++          .proc_name      = "ibmmca",
++        .proc_info      = ibmmca_proc_info,
++          .name           = "IBM SCSI-Subsystem",
++          .detect         = ibmmca_detect,
++          .release        = ibmmca_release,
++          .queuecommand   = ibmmca_queuecommand,
++        .eh_abort_handler = ibmmca_abort,
++        .eh_host_reset_handler = ibmmca_host_reset,
++          .bios_param     = ibmmca_biosparam,
++          .can_queue      = 16,
++          .this_id        = 7,
++          .sg_tablesize   = 16,
++          .cmd_per_lun    = 1,
++          .use_clustering = ENABLE_CLUSTERING,
+ };
+-
+-static int __init ibmmca_init(void)
+-{
+-#ifdef MODULE
+-      /* If the driver is run as module, read from conf.modules or cmd-line */
+-      if (boot_options)
+-              option_setup(boot_options);
+-#endif
+-
+-      return mca_register_driver_integrated(&ibmmca_driver, MCA_INTEGSCSI);
+-}
+-
+-static void __exit ibmmca_exit(void)
+-{
+-      mca_unregister_driver(&ibmmca_driver);
+-}
+-
+-module_init(ibmmca_init);
+-module_exit(ibmmca_exit);
++#include "scsi_module.c"
+diff -Nurb linux-2.6.22-590/drivers/scsi/ibmmca.h linux-2.6.22-570/drivers/scsi/ibmmca.h
+--- linux-2.6.22-590/drivers/scsi/ibmmca.h     1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/ibmmca.h     2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,21 @@
++/*
++ * Low Level Driver for the IBM Microchannel SCSI Subsystem
++ * (Headerfile, see Documentation/scsi/ibmmca.txt for description of the
++ * IBM MCA SCSI-driver.
++ * For use under the GNU General Public License within the Linux-kernel project.
++ * This include file works only correctly with kernel 2.4.0 or higher!!! */
 +
-+      ocfs2_set_target_boundaries(osb, wc, pos, len,
-+                                  clusters_to_alloc + extents_to_split);
++#ifndef _IBMMCA_H
++#define _IBMMCA_H
 +
-+      handle = ocfs2_start_trans(osb, credits);
-+      if (IS_ERR(handle)) {
-+              ret = PTR_ERR(handle);
-+              mlog_errno(ret);
-+              goto out;
-+      }
++/* Common forward declarations for all Linux-versions: */
 +
-+      wc->w_handle = handle;
++/* Interfaces to the midlevel Linux SCSI driver */
++static int ibmmca_detect (struct scsi_host_template *);
++static int ibmmca_release (struct Scsi_Host *);
++static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
++static int ibmmca_abort (Scsi_Cmnd *);
++static int ibmmca_host_reset (Scsi_Cmnd *);
++static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *);
 +
-+      /*
-+       * We don't want this to fail in ocfs2_write_end(), so do it
-+       * here.
-+       */
-+      ret = ocfs2_journal_access(handle, inode, wc->w_di_bh,
-+                                 OCFS2_JOURNAL_ACCESS_WRITE);
-               if (ret) {
-                       mlog_errno(ret);
--                      goto out_meta;
-+              goto out_commit;
++#endif /* _IBMMCA_H */
+diff -Nurb linux-2.6.22-590/drivers/scsi/ibmvscsi/ibmvscsi.c linux-2.6.22-570/drivers/scsi/ibmvscsi/ibmvscsi.c
+--- linux-2.6.22-590/drivers/scsi/ibmvscsi/ibmvscsi.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/ibmvscsi/ibmvscsi.c  2007-07-08 19:32:17.000000000 -0400
+@@ -173,7 +173,8 @@
                }
--              credits = ocfs2_calc_extend_credits(inode->i_sb, di, 1);
-+      /*
-+       * Fill our page array first. That way we've grabbed enough so
-+       * that we can zero and flush if we error after adding the
-+       * extent.
-+       */
-+      ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos,
-+                                       clusters_to_alloc + extents_to_split,
-+                                       mmap_page);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out_commit;
        }
--      ret = ocfs2_data_lock(inode, 1);
-+      ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos,
-+                                        len);
-       if (ret) {
-               mlog_errno(ret);
--              goto out_meta;
-+              goto out_commit;
+       if (in_use)
+-              dev_warn(hostdata->dev, "releasing event pool with %d "
++              printk(KERN_WARNING
++                     "ibmvscsi: releasing event pool with %d "
+                      "events still in use?\n", in_use);
+       kfree(pool->events);
+       dma_free_coherent(hostdata->dev,
+@@ -209,12 +210,14 @@
+                                      struct srp_event_struct *evt)
+ {
+       if (!valid_event_struct(pool, evt)) {
+-              dev_err(evt->hostdata->dev, "Freeing invalid event_struct %p "
++              printk(KERN_ERR
++                     "ibmvscsi: Freeing invalid event_struct %p "
+                      "(not in pool %p)\n", evt, pool->events);
+               return;
        }
--      handle = ocfs2_start_trans(osb, credits);
--      if (IS_ERR(handle)) {
--              ret = PTR_ERR(handle);
-+      if (data_ac)
-+              ocfs2_free_alloc_context(data_ac);
-+      if (meta_ac)
-+              ocfs2_free_alloc_context(meta_ac);
-+
-+      *pagep = wc->w_target_page;
-+      *fsdata = wc;
-+      return 0;
-+out_commit:
-+      ocfs2_commit_trans(osb, handle);
-+
-+out:
-+      ocfs2_free_write_ctxt(wc);
-+
-+      if (data_ac)
-+              ocfs2_free_alloc_context(data_ac);
-+      if (meta_ac)
-+              ocfs2_free_alloc_context(meta_ac);
-+      return ret;
-+}
-+
-+int ocfs2_write_begin(struct file *file, struct address_space *mapping,
-+                    loff_t pos, unsigned len, unsigned flags,
-+                    struct page **pagep, void **fsdata)
-+{
-+      int ret;
-+      struct buffer_head *di_bh = NULL;
-+      struct inode *inode = mapping->host;
-+
-+      ret = ocfs2_meta_lock(inode, &di_bh, 1);
-+      if (ret) {
-               mlog_errno(ret);
--              goto out_data;
-+              return ret;
+       if (atomic_inc_return(&evt->free) != 1) {
+-              dev_err(evt->hostdata->dev, "Freeing event_struct %p "
++              printk(KERN_ERR
++                     "ibmvscsi: Freeing event_struct %p "
+                      "which is not in use!\n", evt);
+               return;
        }
--      written = ocfs2_write(file, phys, handle, di_bh, data_ac,
--                            meta_ac, &wc);
--      if (written < 0) {
--              ret = written;
-+      /*
-+       * Take alloc sem here to prevent concurrent lookups. That way
-+       * the mapping, zeroing and tree manipulation within
-+       * ocfs2_write() will be safe against ->readpage(). This
-+       * should also serve to lock out allocation from a shared
-+       * writeable region.
-+       */
-+      down_write(&OCFS2_I(inode)->ip_alloc_sem);
-+
-+      ret = ocfs2_data_lock(inode, 1);
-+      if (ret) {
-               mlog_errno(ret);
--              goto out_commit;
-+              goto out_fail;
+@@ -405,6 +408,13 @@
+               return 1;
        }
  
--      ret = ocfs2_journal_access(handle, inode, di_bh,
--                                 OCFS2_JOURNAL_ACCESS_WRITE);
-+      ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep,
-+                                     fsdata, di_bh, NULL);
-       if (ret) {
-               mlog_errno(ret);
--              goto out_commit;
-+              goto out_fail_data;
-+      }
-+
-+      brelse(di_bh);
-+
-+      return 0;
-+
-+out_fail_data:
-+      ocfs2_data_unlock(inode, 1);
-+out_fail:
-+      up_write(&OCFS2_I(inode)->ip_alloc_sem);
-+
-+      brelse(di_bh);
-+      ocfs2_meta_unlock(inode, 1);
-+
-+      return ret;
-+}
-+
-+int ocfs2_write_end_nolock(struct address_space *mapping,
-+                         loff_t pos, unsigned len, unsigned copied,
-+                         struct page *page, void *fsdata)
-+{
-+      int i;
-+      unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1);
-+      struct inode *inode = mapping->host;
-+      struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-+      struct ocfs2_write_ctxt *wc = fsdata;
-+      struct ocfs2_dinode *di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
-+      handle_t *handle = wc->w_handle;
-+      struct page *tmppage;
-+
-+      if (unlikely(copied < len)) {
-+              if (!PageUptodate(wc->w_target_page))
-+                      copied = 0;
-+
-+              ocfs2_zero_new_buffers(wc->w_target_page, start+copied,
-+                                     start+len);
++      if (sg_mapped > SG_ALL) {
++              printk(KERN_ERR
++                     "ibmvscsi: More than %d mapped sg entries, got %d\n",
++                     SG_ALL, sg_mapped);
++              return 0;
 +      }
-+      flush_dcache_page(wc->w_target_page);
-+
-+      for(i = 0; i < wc->w_num_pages; i++) {
-+              tmppage = wc->w_pages[i];
-+
-+              if (tmppage == wc->w_target_page) {
-+                      from = wc->w_target_from;
-+                      to = wc->w_target_to;
-+
-+                      BUG_ON(from > PAGE_CACHE_SIZE ||
-+                             to > PAGE_CACHE_SIZE ||
-+                             to < from);
-+              } else {
-+                      /*
-+                       * Pages adjacent to the target (if any) imply
-+                       * a hole-filling write in which case we want
-+                       * to flush their entire range.
-+                       */
-+                      from = 0;
-+                      to = PAGE_CACHE_SIZE;
-+              }
 +
-+              if (ocfs2_should_order_data(inode))
-+                      walk_page_buffers(wc->w_handle, page_buffers(tmppage),
-+                                        from, to, NULL,
-+                                        ocfs2_journal_dirty_data);
-+
-+              block_commit_write(tmppage, from, to);
+       indirect->table_desc.va = 0;
+       indirect->table_desc.len = sg_mapped * sizeof(struct srp_direct_buf);
+       indirect->table_desc.key = 0;
+@@ -423,9 +433,10 @@
+                                          SG_ALL * sizeof(struct srp_direct_buf),
+                                          &evt_struct->ext_list_token, 0);
+               if (!evt_struct->ext_list) {
+-                      sdev_printk(KERN_ERR, cmd->device,
+-                                  "Can't allocate memory for indirect table\n");
++                      printk(KERN_ERR
++                             "ibmvscsi: Can't allocate memory for indirect table\n");
+                       return 0;
++                      
+               }
        }
  
--      pos += written;
-+      pos += copied;
-       if (pos > inode->i_size) {
-               i_size_write(inode, pos);
-               mark_inode_dirty(inode);
-@@ -1306,28 +1604,31 @@
-       di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
-       di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
--      ret = ocfs2_journal_dirty(handle, di_bh);
--      if (ret)
--              mlog_errno(ret);
-+      ocfs2_journal_dirty(handle, wc->w_di_bh);
--out_commit:
-       ocfs2_commit_trans(osb, handle);
--out_data:
--      ocfs2_data_unlock(inode, 1);
-+      ocfs2_run_deallocs(osb, &wc->w_dealloc);
-+
-+      ocfs2_free_write_ctxt(wc);
-+
-+      return copied;
-+}
-+
-+int ocfs2_write_end(struct file *file, struct address_space *mapping,
-+                  loff_t pos, unsigned len, unsigned copied,
-+                  struct page *page, void *fsdata)
-+{
-+      int ret;
-+      struct inode *inode = mapping->host;
-+
-+      ret = ocfs2_write_end_nolock(mapping, pos, len, copied, page, fsdata);
--out_meta:
-+      ocfs2_data_unlock(inode, 1);
-       up_write(&OCFS2_I(inode)->ip_alloc_sem);
-       ocfs2_meta_unlock(inode, 1);
+@@ -460,8 +471,8 @@
+                              cmd->request_bufflen,
+                              DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(data->va)) {
+-              sdev_printk(KERN_ERR, cmd->device,
+-                          "Unable to map request_buffer for command!\n");
++              printk(KERN_ERR
++                     "ibmvscsi: Unable to map request_buffer for command!\n");
+               return 0;
+       }
+       data->len = cmd->request_bufflen;
+@@ -492,12 +503,12 @@
+       case DMA_NONE:
+               return 1;
+       case DMA_BIDIRECTIONAL:
+-              sdev_printk(KERN_ERR, cmd->device,
+-                          "Can't map DMA_BIDIRECTIONAL to read/write\n");
++              printk(KERN_ERR
++                     "ibmvscsi: Can't map DMA_BIDIRECTIONAL to read/write\n");
+               return 0;
+       default:
+-              sdev_printk(KERN_ERR, cmd->device,
+-                          "Unknown data direction 0x%02x; can't map!\n",
++              printk(KERN_ERR
++                     "ibmvscsi: Unknown data direction 0x%02x; can't map!\n",
+                      cmd->sc_data_direction);
+               return 0;
+       }
+@@ -509,70 +520,6 @@
+       return map_single_data(cmd, srp_cmd, dev);
+ }
  
--out:
--      brelse(di_bh);
--      if (data_ac)
--              ocfs2_free_alloc_context(data_ac);
--      if (meta_ac)
--              ocfs2_free_alloc_context(meta_ac);
+-/**
+- * purge_requests: Our virtual adapter just shut down.  purge any sent requests
+- * @hostdata:    the adapter
+- */
+-static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
+-{
+-      struct srp_event_struct *tmp_evt, *pos;
+-      unsigned long flags;
+-
+-      spin_lock_irqsave(hostdata->host->host_lock, flags);
+-      list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
+-              list_del(&tmp_evt->list);
+-              del_timer(&tmp_evt->timer);
+-              if (tmp_evt->cmnd) {
+-                      tmp_evt->cmnd->result = (error_code << 16);
+-                      unmap_cmd_data(&tmp_evt->iu.srp.cmd,
+-                                     tmp_evt,
+-                                     tmp_evt->hostdata->dev);
+-                      if (tmp_evt->cmnd_done)
+-                              tmp_evt->cmnd_done(tmp_evt->cmnd);
+-              } else if (tmp_evt->done)
+-                      tmp_evt->done(tmp_evt);
+-              free_event_struct(&tmp_evt->hostdata->pool, tmp_evt);
+-      }
+-      spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+-}
 -
--      return written ? written : ret;
-+      return ret;
- }
- const struct address_space_operations ocfs2_aops = {
-diff -Nurb linux-2.6.22-570/fs/ocfs2/aops.h linux-2.6.22-590/fs/ocfs2/aops.h
---- linux-2.6.22-570/fs/ocfs2/aops.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/aops.h   2008-01-02 13:56:37.000000000 -0500
-@@ -42,57 +42,22 @@
-                       int (*fn)(      handle_t *handle,
-                                       struct buffer_head *bh));
--struct ocfs2_write_ctxt;
--typedef int (ocfs2_page_writer)(struct inode *, struct ocfs2_write_ctxt *,
--                              u64 *, unsigned int *, unsigned int *);
+-/**
+- * ibmvscsi_reset_host - Reset the connection to the server
+- * @hostdata: struct ibmvscsi_host_data to reset
+-*/
+-static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
+-{
+-      scsi_block_requests(hostdata->host);
+-      atomic_set(&hostdata->request_limit, 0);
 -
--ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
--                                   size_t count, ocfs2_page_writer *actor,
--                                   void *priv);
+-      purge_requests(hostdata, DID_ERROR);
+-      if ((ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata)) ||
+-          (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0)) ||
+-          (vio_enable_interrupts(to_vio_dev(hostdata->dev)))) {
+-              atomic_set(&hostdata->request_limit, -1);
+-              dev_err(hostdata->dev, "error after reset\n");
+-      }
 -
--struct ocfs2_write_ctxt {
--      size_t                          w_count;
--      loff_t                          w_pos;
--      u32                             w_cpos;
--      unsigned int                    w_finished_copy;
+-      scsi_unblock_requests(hostdata->host);
+-}
 -
--      /* This is true if page_size > cluster_size */
--      unsigned int                    w_large_pages;
+-/**
+- * ibmvscsi_timeout - Internal command timeout handler
+- * @evt_struct:       struct srp_event_struct that timed out
+- *
+- * Called when an internally generated command times out
+-*/
+-static void ibmvscsi_timeout(struct srp_event_struct *evt_struct)
+-{
+-      struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;
 -
--      /* Filler callback and private data */
--      ocfs2_page_writer               *w_write_data_page;
--      void                            *w_private;
+-      dev_err(hostdata->dev, "Command timed out (%x). Resetting connection\n",
+-              evt_struct->iu.srp.cmd.opcode);
 -
--      /* Only valid for the filler callback */
--      struct page                     *w_this_page;
--      unsigned int                    w_this_page_new;
--};
+-      ibmvscsi_reset_host(hostdata);
+-}
 -
--struct ocfs2_buffered_write_priv {
--      char                            *b_src_buf;
--      const struct iovec              *b_cur_iov; /* Current iovec */
--      size_t                          b_cur_off; /* Offset in the
--                                                  * current iovec */
--};
--int ocfs2_map_and_write_user_data(struct inode *inode,
--                                struct ocfs2_write_ctxt *wc,
--                                u64 *p_blkno,
--                                unsigned int *ret_from,
--                                unsigned int *ret_to);
--
--struct ocfs2_splice_write_priv {
--      struct splice_desc              *s_sd;
--      struct pipe_buffer              *s_buf;
--      struct pipe_inode_info          *s_pipe;
--      /* Neither offset value is ever larger than one page */
--      unsigned int                    s_offset;
--      unsigned int                    s_buf_offset;
--};
--int ocfs2_map_and_write_splice_data(struct inode *inode,
--                                  struct ocfs2_write_ctxt *wc,
--                                  u64 *p_blkno,
--                                  unsigned int *ret_from,
--                                  unsigned int *ret_to);
-+int ocfs2_write_begin(struct file *file, struct address_space *mapping,
-+                    loff_t pos, unsigned len, unsigned flags,
-+                    struct page **pagep, void **fsdata);
-+
-+int ocfs2_write_end(struct file *file, struct address_space *mapping,
-+                  loff_t pos, unsigned len, unsigned copied,
-+                  struct page *page, void *fsdata);
-+
-+int ocfs2_write_end_nolock(struct address_space *mapping,
-+                         loff_t pos, unsigned len, unsigned copied,
-+                         struct page *page, void *fsdata);
-+
-+int ocfs2_write_begin_nolock(struct address_space *mapping,
-+                           loff_t pos, unsigned len, unsigned flags,
-+                           struct page **pagep, void **fsdata,
-+                           struct buffer_head *di_bh, struct page *mmap_page);
+-
+ /* ------------------------------------------------------------
+  * Routines for sending and receiving SRPs
+  */
+@@ -580,14 +527,12 @@
+  * ibmvscsi_send_srp_event: - Transforms event to u64 array and calls send_crq()
+  * @evt_struct:       evt_struct to be sent
+  * @hostdata: ibmvscsi_host_data of host
+- * @timeout:  timeout in seconds - 0 means do not time command
+  *
+  * Returns the value returned from ibmvscsi_send_crq(). (Zero for success)
+  * Note that this routine assumes that host_lock is held for synchronization
+ */
+ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
+-                                 struct ibmvscsi_host_data *hostdata,
+-                                 unsigned long timeout)
++                                 struct ibmvscsi_host_data *hostdata)
+ {
+       u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
+       int request_status;
+@@ -643,20 +588,12 @@
+        */
+       list_add_tail(&evt_struct->list, &hostdata->sent);
  
- /* all ocfs2_dio_end_io()'s fault */
- #define ocfs2_iocb_is_rw_locked(iocb) \
-diff -Nurb linux-2.6.22-570/fs/ocfs2/cluster/heartbeat.c linux-2.6.22-590/fs/ocfs2/cluster/heartbeat.c
---- linux-2.6.22-570/fs/ocfs2/cluster/heartbeat.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/cluster/heartbeat.c      2008-01-02 13:56:37.000000000 -0500
-@@ -1335,6 +1335,7 @@
-       ret = wait_event_interruptible(o2hb_steady_queue,
-                               atomic_read(&reg->hr_steady_iterations) == 0);
-       if (ret) {
-+              /* We got interrupted (hello ptrace!).  Clean up */
-               spin_lock(&o2hb_live_lock);
-               hb_task = reg->hr_task;
-               reg->hr_task = NULL;
-@@ -1345,7 +1346,16 @@
-               goto out;
+-      init_timer(&evt_struct->timer);
+-      if (timeout) {
+-              evt_struct->timer.data = (unsigned long) evt_struct;
+-              evt_struct->timer.expires = jiffies + (timeout * HZ);
+-              evt_struct->timer.function = (void (*)(unsigned long))ibmvscsi_timeout;
+-              add_timer(&evt_struct->timer);
+-      }
+-
+       if ((rc =
+            ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
+               list_del(&evt_struct->list);
+-              del_timer(&evt_struct->timer);
+-              dev_err(hostdata->dev, "send error %d\n", rc);
++              printk(KERN_ERR "ibmvscsi: send error %d\n",
++                     rc);
+               atomic_inc(&hostdata->request_limit);
+               goto send_error;
        }
+@@ -697,8 +634,9 @@
  
-+      /* Ok, we were woken.  Make sure it wasn't by drop_item() */
-+      spin_lock(&o2hb_live_lock);
-+      hb_task = reg->hr_task;
-+      spin_unlock(&o2hb_live_lock);
-+
-+      if (hb_task)
-       ret = count;
-+      else
-+              ret = -EIO;
-+
- out:
-       if (filp)
-               fput(filp);
-@@ -1523,6 +1533,15 @@
-       if (hb_task)
-               kthread_stop(hb_task);
+       if (unlikely(rsp->opcode != SRP_RSP)) {
+               if (printk_ratelimit())
+-                      dev_warn(evt_struct->hostdata->dev,
+-                               "bad SRP RSP type %d\n", rsp->opcode);
++                      printk(KERN_WARNING 
++                             "ibmvscsi: bad SRP RSP type %d\n",
++                             rsp->opcode);
+       }
+       
+       if (cmnd) {
+@@ -759,7 +697,7 @@
+       srp_cmd->lun = ((u64) lun) << 48;
  
-+      /*
-+       * If we're racing a dev_write(), we need to wake them.  They will
-+       * check reg->hr_task
-+       */
-+      if (atomic_read(&reg->hr_steady_iterations) != 0) {
-+              atomic_set(&reg->hr_steady_iterations, 0);
-+              wake_up(&o2hb_steady_queue);
-+      }
-+
-       config_item_put(item);
- }
+       if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
+-              sdev_printk(KERN_ERR, cmnd->device, "couldn't convert cmd to srp_cmd\n");
++              printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n");
+               free_event_struct(&hostdata->pool, evt_struct);
+               return SCSI_MLQUEUE_HOST_BUSY;
+       }
+@@ -784,7 +722,7 @@
+                       offsetof(struct srp_indirect_buf, desc_list);
+       }
  
-@@ -1665,7 +1684,67 @@
+-      return ibmvscsi_send_srp_event(evt_struct, hostdata, 0);
++      return ibmvscsi_send_srp_event(evt_struct, hostdata);
  }
- EXPORT_SYMBOL_GPL(o2hb_setup_callback);
  
--int o2hb_register_callback(struct o2hb_callback_func *hc)
-+static struct o2hb_region *o2hb_find_region(const char *region_uuid)
-+{
-+      struct o2hb_region *p, *reg = NULL;
-+
-+      assert_spin_locked(&o2hb_live_lock);
-+
-+      list_for_each_entry(p, &o2hb_all_regions, hr_all_item) {
-+              if (!strcmp(region_uuid, config_item_name(&p->hr_item))) {
-+                      reg = p;
-+                      break;
-+              }
-+      }
-+
-+      return reg;
-+}
-+
-+static int o2hb_region_get(const char *region_uuid)
-+{
-+      int ret = 0;
-+      struct o2hb_region *reg;
-+
-+      spin_lock(&o2hb_live_lock);
-+
-+      reg = o2hb_find_region(region_uuid);
-+      if (!reg)
-+              ret = -ENOENT;
-+      spin_unlock(&o2hb_live_lock);
-+
-+      if (ret)
-+              goto out;
-+
-+      ret = o2nm_depend_this_node();
-+      if (ret)
-+              goto out;
-+
-+      ret = o2nm_depend_item(&reg->hr_item);
-+      if (ret)
-+              o2nm_undepend_this_node();
-+
-+out:
-+      return ret;
-+}
-+
-+static void o2hb_region_put(const char *region_uuid)
-+{
-+      struct o2hb_region *reg;
-+
-+      spin_lock(&o2hb_live_lock);
-+
-+      reg = o2hb_find_region(region_uuid);
-+
-+      spin_unlock(&o2hb_live_lock);
-+
-+      if (reg) {
-+              o2nm_undepend_item(&reg->hr_item);
-+              o2nm_undepend_this_node();
-+      }
-+}
-+
-+int o2hb_register_callback(const char *region_uuid,
-+                         struct o2hb_callback_func *hc)
- {
-       struct o2hb_callback_func *tmp;
-       struct list_head *iter;
-@@ -1681,6 +1760,12 @@
-               goto out;
-       }
+ /* ------------------------------------------------------------
+@@ -806,10 +744,10 @@
+                        DMA_BIDIRECTIONAL);
  
-+      if (region_uuid) {
-+              ret = o2hb_region_get(region_uuid);
-+              if (ret)
-+                      goto out;
-+      }
-+
-       down_write(&o2hb_callback_sem);
+       if (evt_struct->xfer_iu->mad.adapter_info.common.status) {
+-              dev_err(hostdata->dev, "error %d getting adapter info\n",
++              printk("ibmvscsi: error %d getting adapter info\n",
+                      evt_struct->xfer_iu->mad.adapter_info.common.status);
+       } else {
+-              dev_info(hostdata->dev, "host srp version: %s, "
++              printk("ibmvscsi: host srp version: %s, "
+                      "host partition %s (%d), OS %d, max io %u\n",
+                      hostdata->madapter_info.srp_version,
+                      hostdata->madapter_info.partition_name,
+@@ -823,9 +761,10 @@
+               
+               if (hostdata->madapter_info.os_type == 3 &&
+                   strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) {
+-                      dev_err(hostdata->dev, "host (Ver. %s) doesn't support large transfers\n",
++                      printk("ibmvscsi: host (Ver. %s) doesn't support large"
++                             "transfers\n",
+                              hostdata->madapter_info.srp_version);
+-                      dev_err(hostdata->dev, "limiting scatterlists to %d\n",
++                      printk("ibmvscsi: limiting scatterlists to %d\n",
+                              MAX_INDIRECT_BUFS);
+                       hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS;
+               }
+@@ -845,13 +784,12 @@
+ {
+       struct viosrp_adapter_info *req;
+       struct srp_event_struct *evt_struct;
+-      unsigned long flags;
+       dma_addr_t addr;
  
-       list_for_each(iter, &hbcall->list) {
-@@ -1702,16 +1787,21 @@
- }
- EXPORT_SYMBOL_GPL(o2hb_register_callback);
+       evt_struct = get_event_struct(&hostdata->pool);
+       if (!evt_struct) {
+-              dev_err(hostdata->dev,
+-                      "couldn't allocate an event for ADAPTER_INFO_REQ!\n");
++              printk(KERN_ERR "ibmvscsi: couldn't allocate an event "
++                     "for ADAPTER_INFO_REQ!\n");
+               return;
+       }
  
--void o2hb_unregister_callback(struct o2hb_callback_func *hc)
-+void o2hb_unregister_callback(const char *region_uuid,
-+                            struct o2hb_callback_func *hc)
- {
-       BUG_ON(hc->hc_magic != O2HB_CB_MAGIC);
+@@ -871,20 +809,20 @@
+                                           DMA_BIDIRECTIONAL);
  
-       mlog(ML_HEARTBEAT, "on behalf of %p for funcs %p\n",
-            __builtin_return_address(0), hc);
+       if (dma_mapping_error(req->buffer)) {
+-              dev_err(hostdata->dev, "Unable to map request_buffer for adapter_info!\n");
++              printk(KERN_ERR
++                     "ibmvscsi: Unable to map request_buffer "
++                     "for adapter_info!\n");
+               free_event_struct(&hostdata->pool, evt_struct);
+               return;
+       }
+       
+-      spin_lock_irqsave(hostdata->host->host_lock, flags);
+-      if (ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2)) {
+-              dev_err(hostdata->dev, "couldn't send ADAPTER_INFO_REQ!\n");
++      if (ibmvscsi_send_srp_event(evt_struct, hostdata)) {
++              printk(KERN_ERR "ibmvscsi: couldn't send ADAPTER_INFO_REQ!\n");
+               dma_unmap_single(hostdata->dev,
+                                addr,
+                                sizeof(hostdata->madapter_info),
+                                DMA_BIDIRECTIONAL);
+       }
+-      spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ };
  
-+      /* XXX Can this happen _with_ a region reference? */
-       if (list_empty(&hc->hc_item))
+ /**
+@@ -901,23 +839,24 @@
+       case SRP_LOGIN_RSP:     /* it worked! */
+               break;
+       case SRP_LOGIN_REJ:     /* refused! */
+-              dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n",
++              printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REJ reason %u\n",
+                      evt_struct->xfer_iu->srp.login_rej.reason);
+               /* Login failed.  */
+               atomic_set(&hostdata->request_limit, -1);
+               return;
+       default:
+-              dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n",
++              printk(KERN_ERR
++                     "ibmvscsi: Invalid login response typecode 0x%02x!\n",
+                      evt_struct->xfer_iu->srp.login_rsp.opcode);
+               /* Login failed.  */
+               atomic_set(&hostdata->request_limit, -1);
                return;
+       }
  
-+      if (region_uuid)
-+              o2hb_region_put(region_uuid);
-+
-       down_write(&o2hb_callback_sem);
+-      dev_info(hostdata->dev, "SRP_LOGIN succeeded\n");
++      printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
  
-       list_del_init(&hc->hc_item);
-diff -Nurb linux-2.6.22-570/fs/ocfs2/cluster/heartbeat.h linux-2.6.22-590/fs/ocfs2/cluster/heartbeat.h
---- linux-2.6.22-570/fs/ocfs2/cluster/heartbeat.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/cluster/heartbeat.h      2008-01-02 13:56:37.000000000 -0500
-@@ -69,8 +69,10 @@
-                        o2hb_cb_func *func,
-                        void *data,
-                        int priority);
--int o2hb_register_callback(struct o2hb_callback_func *hc);
--void o2hb_unregister_callback(struct o2hb_callback_func *hc);
-+int o2hb_register_callback(const char *region_uuid,
-+                         struct o2hb_callback_func *hc);
-+void o2hb_unregister_callback(const char *region_uuid,
-+                            struct o2hb_callback_func *hc);
- void o2hb_fill_node_map(unsigned long *map,
-                       unsigned bytes);
- void o2hb_init(void);
-diff -Nurb linux-2.6.22-570/fs/ocfs2/cluster/masklog.c linux-2.6.22-590/fs/ocfs2/cluster/masklog.c
---- linux-2.6.22-570/fs/ocfs2/cluster/masklog.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/cluster/masklog.c        2008-01-02 13:56:37.000000000 -0500
-@@ -74,7 +74,6 @@
- #define define_mask(_name) {                  \
-       .attr = {                               \
-               .name = #_name,                 \
--              .owner = THIS_MODULE,           \
-               .mode = S_IRUGO | S_IWUSR,      \
-       },                                      \
-       .mask = ML_##_name,                     \
-diff -Nurb linux-2.6.22-570/fs/ocfs2/cluster/nodemanager.c linux-2.6.22-590/fs/ocfs2/cluster/nodemanager.c
---- linux-2.6.22-570/fs/ocfs2/cluster/nodemanager.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/cluster/nodemanager.c    2008-01-02 13:56:37.000000000 -0500
-@@ -900,6 +900,46 @@
-       },
- };
+       if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta < 0)
+-              dev_err(hostdata->dev, "Invalid request_limit.\n");
++              printk(KERN_ERR "ibmvscsi: Invalid request_limit.\n");
  
-+int o2nm_depend_item(struct config_item *item)
-+{
-+      return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item);
-+}
-+
-+void o2nm_undepend_item(struct config_item *item)
-+{
-+      configfs_undepend_item(&o2nm_cluster_group.cs_subsys, item);
-+}
-+
-+int o2nm_depend_this_node(void)
-+{
-+      int ret = 0;
-+      struct o2nm_node *local_node;
-+
-+      local_node = o2nm_get_node_by_num(o2nm_this_node());
-+      if (!local_node) {
-+              ret = -EINVAL;
-+              goto out;
-+      }
-+
-+      ret = o2nm_depend_item(&local_node->nd_item);
-+      o2nm_node_put(local_node);
-+
-+out:
-+      return ret;
-+}
-+
-+void o2nm_undepend_this_node(void)
-+{
-+      struct o2nm_node *local_node;
-+
-+      local_node = o2nm_get_node_by_num(o2nm_this_node());
-+      BUG_ON(!local_node);
-+
-+      o2nm_undepend_item(&local_node->nd_item);
-+      o2nm_node_put(local_node);
-+}
-+
-+
- static void __exit exit_o2nm(void)
- {
-       if (ocfs2_table_header)
-diff -Nurb linux-2.6.22-570/fs/ocfs2/cluster/nodemanager.h linux-2.6.22-590/fs/ocfs2/cluster/nodemanager.h
---- linux-2.6.22-570/fs/ocfs2/cluster/nodemanager.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/cluster/nodemanager.h    2008-01-02 13:56:37.000000000 -0500
-@@ -77,4 +77,9 @@
- void o2nm_node_get(struct o2nm_node *node);
- void o2nm_node_put(struct o2nm_node *node);
+       /* Now we know what the real request-limit is.
+        * This value is set rather than added to request_limit because
+@@ -946,7 +885,8 @@
+       struct srp_login_req *login;
+       struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool);
+       if (!evt_struct) {
+-              dev_err(hostdata->dev, "couldn't allocate an event for login req!\n");
++              printk(KERN_ERR
++                     "ibmvscsi: couldn't allocate an event for login req!\n");
+               return FAILED;
+       }
  
-+int o2nm_depend_item(struct config_item *item);
-+void o2nm_undepend_item(struct config_item *item);
-+int o2nm_depend_this_node(void);
-+void o2nm_undepend_this_node(void);
-+
- #endif /* O2CLUSTER_NODEMANAGER_H */
-diff -Nurb linux-2.6.22-570/fs/ocfs2/cluster/tcp.c linux-2.6.22-590/fs/ocfs2/cluster/tcp.c
---- linux-2.6.22-570/fs/ocfs2/cluster/tcp.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/cluster/tcp.c    2008-01-02 13:56:37.000000000 -0500
-@@ -261,14 +261,12 @@
+@@ -967,9 +907,9 @@
+        */
+       atomic_set(&hostdata->request_limit, 1);
  
- static void o2net_complete_nodes_nsw(struct o2net_node *nn)
- {
--      struct list_head *iter, *tmp;
-+      struct o2net_status_wait *nsw, *tmp;
-       unsigned int num_kills = 0;
--      struct o2net_status_wait *nsw;
+-      rc = ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2);
++      rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
+       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+-      dev_info(hostdata->dev, "sent SRP login\n");
++      printk("ibmvscsic: sent SRP login\n");
+       return rc;
+ };
  
-       assert_spin_locked(&nn->nn_lock);
+@@ -1018,13 +958,13 @@
  
--      list_for_each_safe(iter, tmp, &nn->nn_status_list) {
--              nsw = list_entry(iter, struct o2net_status_wait, ns_node_item);
-+      list_for_each_entry_safe(nsw, tmp, &nn->nn_status_list, ns_node_item) {
-               o2net_complete_nsw_locked(nn, nsw, O2NET_ERR_DIED, 0);
-               num_kills++;
+       if (!found_evt) {
+               spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+-              return SUCCESS;
++              return FAILED;
        }
-@@ -764,13 +762,10 @@
  
- void o2net_unregister_handler_list(struct list_head *list)
- {
--      struct list_head *pos, *n;
--      struct o2net_msg_handler *nmh;
-+      struct o2net_msg_handler *nmh, *n;
+       evt = get_event_struct(&hostdata->pool);
+       if (evt == NULL) {
+               spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+-              sdev_printk(KERN_ERR, cmd->device, "failed to allocate abort event\n");
++              printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n");
+               return FAILED;
+       }
+       
+@@ -1042,16 +982,15 @@
+       tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK;
+       tsk_mgmt->task_tag = (u64) found_evt;
  
-       write_lock(&o2net_handler_lock);
--      list_for_each_safe(pos, n, list) {
--              nmh = list_entry(pos, struct o2net_msg_handler,
--                               nh_unregister_item);
-+      list_for_each_entry_safe(nmh, n, list, nh_unregister_item) {
-               mlog(ML_TCP, "unregistering handler func %p type %u key %08x\n",
-                    nmh->nh_func, nmh->nh_msg_type, nmh->nh_key);
-               rb_erase(&nmh->nh_node, &o2net_handler_tree);
-@@ -1638,8 +1633,8 @@
+-      sdev_printk(KERN_INFO, cmd->device, "aborting command. lun 0x%lx, tag 0x%lx\n",
++      printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
+              tsk_mgmt->lun, tsk_mgmt->task_tag);
  
- void o2net_unregister_hb_callbacks(void)
- {
--      o2hb_unregister_callback(&o2net_hb_up);
--      o2hb_unregister_callback(&o2net_hb_down);
-+      o2hb_unregister_callback(NULL, &o2net_hb_up);
-+      o2hb_unregister_callback(NULL, &o2net_hb_down);
- }
+       evt->sync_srp = &srp_rsp;
+       init_completion(&evt->comp);
+-      rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
++      rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
+       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+       if (rsp_rc != 0) {
+-              sdev_printk(KERN_ERR, cmd->device,
+-                          "failed to send abort() event. rc=%d\n", rsp_rc);
++              printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
+               return FAILED;
+       }
  
- int o2net_register_hb_callbacks(void)
-@@ -1651,9 +1646,9 @@
-       o2hb_setup_callback(&o2net_hb_up, O2HB_NODE_UP_CB,
-                           o2net_hb_node_up_cb, NULL, O2NET_HB_PRI);
+@@ -1060,7 +999,8 @@
+       /* make sure we got a good response */
+       if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) {
+               if (printk_ratelimit())
+-                      sdev_printk(KERN_WARNING, cmd->device, "abort bad SRP RSP type %d\n",
++                      printk(KERN_WARNING 
++                             "ibmvscsi: abort bad SRP RSP type %d\n",
+                              srp_rsp.srp.rsp.opcode);
+               return FAILED;
+       }
+@@ -1072,9 +1012,10 @@
  
--      ret = o2hb_register_callback(&o2net_hb_up);
-+      ret = o2hb_register_callback(NULL, &o2net_hb_up);
-       if (ret == 0)
--              ret = o2hb_register_callback(&o2net_hb_down);
-+              ret = o2hb_register_callback(NULL, &o2net_hb_down);
+       if (rsp_rc) {
+               if (printk_ratelimit())
+-                      sdev_printk(KERN_WARNING, cmd->device,
+-                                  "abort code %d for task tag 0x%lx\n",
+-                                  rsp_rc, tsk_mgmt->task_tag);
++                      printk(KERN_WARNING 
++                             "ibmvscsi: abort code %d for task tag 0x%lx\n",
++                             rsp_rc,
++                             tsk_mgmt->task_tag);
+               return FAILED;
+       }
  
-       if (ret)
-               o2net_unregister_hb_callbacks();
-diff -Nurb linux-2.6.22-570/fs/ocfs2/dir.c linux-2.6.22-590/fs/ocfs2/dir.c
---- linux-2.6.22-570/fs/ocfs2/dir.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/dir.c    2008-01-02 13:56:37.000000000 -0500
-@@ -368,7 +368,7 @@
-               u32 offset = OCFS2_I(dir)->ip_clusters;
+@@ -1093,12 +1034,14 @@
  
-               status = ocfs2_do_extend_allocation(OCFS2_SB(sb), dir, &offset,
--                                                  1, parent_fe_bh, handle,
-+                                                  1, 0, parent_fe_bh, handle,
-                                                   data_ac, meta_ac, NULL);
-               BUG_ON(status == -EAGAIN);
-               if (status < 0) {
-diff -Nurb linux-2.6.22-570/fs/ocfs2/dlm/dlmdomain.c linux-2.6.22-590/fs/ocfs2/dlm/dlmdomain.c
---- linux-2.6.22-570/fs/ocfs2/dlm/dlmdomain.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/dlm/dlmdomain.c  2008-01-02 13:56:37.000000000 -0500
-@@ -1128,8 +1128,8 @@
+       if (found_evt == NULL) {
+               spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+-              sdev_printk(KERN_INFO, cmd->device, "aborted task tag 0x%lx completed\n",
++              printk(KERN_INFO
++                     "ibmvscsi: aborted task tag 0x%lx completed\n",
+                      tsk_mgmt->task_tag);
+               return SUCCESS;
+       }
  
- static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm)
- {
--      o2hb_unregister_callback(&dlm->dlm_hb_up);
--      o2hb_unregister_callback(&dlm->dlm_hb_down);
-+      o2hb_unregister_callback(NULL, &dlm->dlm_hb_up);
-+      o2hb_unregister_callback(NULL, &dlm->dlm_hb_down);
-       o2net_unregister_handler_list(&dlm->dlm_domain_handlers);
- }
+-      sdev_printk(KERN_INFO, cmd->device, "successfully aborted task tag 0x%lx\n",
++      printk(KERN_INFO
++             "ibmvscsi: successfully aborted task tag 0x%lx\n",
+              tsk_mgmt->task_tag);
  
-@@ -1141,13 +1141,13 @@
+       cmd->result = (DID_ABORT << 16);
+@@ -1133,7 +1076,7 @@
+       evt = get_event_struct(&hostdata->pool);
+       if (evt == NULL) {
+               spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+-              sdev_printk(KERN_ERR, cmd->device, "failed to allocate reset event\n");
++              printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n");
+               return FAILED;
+       }
+       
+@@ -1150,16 +1093,15 @@
+       tsk_mgmt->lun = ((u64) lun) << 48;
+       tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET;
  
-       o2hb_setup_callback(&dlm->dlm_hb_down, O2HB_NODE_DOWN_CB,
-                           dlm_hb_node_down_cb, dlm, DLM_HB_NODE_DOWN_PRI);
--      status = o2hb_register_callback(&dlm->dlm_hb_down);
-+      status = o2hb_register_callback(NULL, &dlm->dlm_hb_down);
-       if (status)
-               goto bail;
+-      sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%lx\n",
++      printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
+              tsk_mgmt->lun);
  
-       o2hb_setup_callback(&dlm->dlm_hb_up, O2HB_NODE_UP_CB,
-                           dlm_hb_node_up_cb, dlm, DLM_HB_NODE_UP_PRI);
--      status = o2hb_register_callback(&dlm->dlm_hb_up);
-+      status = o2hb_register_callback(NULL, &dlm->dlm_hb_up);
-       if (status)
-               goto bail;
+       evt->sync_srp = &srp_rsp;
+       init_completion(&evt->comp);
+-      rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
++      rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
+       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+       if (rsp_rc != 0) {
+-              sdev_printk(KERN_ERR, cmd->device,
+-                          "failed to send reset event. rc=%d\n", rsp_rc);
++              printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
+               return FAILED;
+       }
  
-diff -Nurb linux-2.6.22-570/fs/ocfs2/dlm/dlmmaster.c linux-2.6.22-590/fs/ocfs2/dlm/dlmmaster.c
---- linux-2.6.22-570/fs/ocfs2/dlm/dlmmaster.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/dlm/dlmmaster.c  2008-01-02 13:56:37.000000000 -0500
-@@ -192,25 +192,20 @@
- static void dlm_dump_mles(struct dlm_ctxt *dlm)
- {
-       struct dlm_master_list_entry *mle;
--      struct list_head *iter;
-       
-       mlog(ML_NOTICE, "dumping all mles for domain %s:\n", dlm->name);
-       spin_lock(&dlm->master_lock);
--      list_for_each(iter, &dlm->master_list) {
--              mle = list_entry(iter, struct dlm_master_list_entry, list);
-+      list_for_each_entry(mle, &dlm->master_list, list)
-               dlm_print_one_mle(mle);
--      }
-       spin_unlock(&dlm->master_lock);
+@@ -1168,7 +1110,8 @@
+       /* make sure we got a good response */
+       if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) {
+               if (printk_ratelimit())
+-                      sdev_printk(KERN_WARNING, cmd->device, "reset bad SRP RSP type %d\n",
++                      printk(KERN_WARNING 
++                             "ibmvscsi: reset bad SRP RSP type %d\n",
+                              srp_rsp.srp.rsp.opcode);
+               return FAILED;
+       }
+@@ -1180,8 +1123,8 @@
+       if (rsp_rc) {
+               if (printk_ratelimit())
+-                      sdev_printk(KERN_WARNING, cmd->device,
+-                                  "reset code %d for task tag 0x%lx\n",
++                      printk(KERN_WARNING 
++                             "ibmvscsi: reset code %d for task tag 0x%lx\n",
+                              rsp_rc, tsk_mgmt->task_tag);
+               return FAILED;
+       }
+@@ -1211,30 +1154,32 @@
  }
  
- int dlm_dump_all_mles(const char __user *data, unsigned int len)
+ /**
+- * ibmvscsi_eh_host_reset_handler - Reset the connection to the server
+- * @cmd:      struct scsi_cmnd having problems
+-*/
+-static int ibmvscsi_eh_host_reset_handler(struct scsi_cmnd *cmd)
++ * purge_requests: Our virtual adapter just shut down.  purge any sent requests
++ * @hostdata:    the adapter
++ */
++static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
  {
--      struct list_head *iter;
-       struct dlm_ctxt *dlm;
+-      unsigned long wait_switch = 0;
+-      struct ibmvscsi_host_data *hostdata =
+-              (struct ibmvscsi_host_data *)cmd->device->host->hostdata;
+-
+-      dev_err(hostdata->dev, "Resetting connection due to error recovery\n");
+-
+-      ibmvscsi_reset_host(hostdata);
+-
+-      for (wait_switch = jiffies + (init_timeout * HZ);
+-           time_before(jiffies, wait_switch) &&
+-                   atomic_read(&hostdata->request_limit) < 2;) {
++      struct srp_event_struct *tmp_evt, *pos;
++      unsigned long flags;
  
-       spin_lock(&dlm_domain_lock);
--      list_for_each(iter, &dlm_domains) {
--              dlm = list_entry (iter, struct dlm_ctxt, list);
-+      list_for_each_entry(dlm, &dlm_domains, list) {
-               mlog(ML_NOTICE, "found dlm: %p, name=%s\n", dlm, dlm->name);
-               dlm_dump_mles(dlm);
+-              msleep(10);
++      spin_lock_irqsave(hostdata->host->host_lock, flags);
++      list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
++              list_del(&tmp_evt->list);
++              if (tmp_evt->cmnd) {
++                      tmp_evt->cmnd->result = (error_code << 16);
++                      unmap_cmd_data(&tmp_evt->iu.srp.cmd, 
++                                     tmp_evt, 
++                                     tmp_evt->hostdata->dev);
++                      if (tmp_evt->cmnd_done)
++                              tmp_evt->cmnd_done(tmp_evt->cmnd);
++              } else {
++                      if (tmp_evt->done) {
++                              tmp_evt->done(tmp_evt);
        }
-@@ -454,12 +449,10 @@
-                       char *name, unsigned int namelen)
- {
-       struct dlm_master_list_entry *tmpmle;
--      struct list_head *iter;
-       assert_spin_locked(&dlm->master_lock);
+-
+-      if (atomic_read(&hostdata->request_limit) <= 0)
+-              return FAILED;
+-
+-      return SUCCESS;
++              }
++              free_event_struct(&tmp_evt->hostdata->pool, tmp_evt);
++      }
++      spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ }
  
--      list_for_each(iter, &dlm->master_list) {
--              tmpmle = list_entry(iter, struct dlm_master_list_entry, list);
-+      list_for_each_entry(tmpmle, &dlm->master_list, list) {
-               if (!dlm_mle_equal(dlm, tmpmle, name, namelen))
-                       continue;
-               dlm_get_mle(tmpmle);
-@@ -472,13 +465,10 @@
- void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up)
+ /**
+@@ -1246,7 +1191,6 @@
+ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
+                        struct ibmvscsi_host_data *hostdata)
  {
-       struct dlm_master_list_entry *mle;
--      struct list_head *iter;
+-      long rc;
+       unsigned long flags;
+       struct srp_event_struct *evt_struct =
+           (struct srp_event_struct *)crq->IU_data_ptr;
+@@ -1254,25 +1198,27 @@
+       case 0xC0:              /* initialization */
+               switch (crq->format) {
+               case 0x01:      /* Initialization message */
+-                      dev_info(hostdata->dev, "partner initialized\n");
++                      printk(KERN_INFO "ibmvscsi: partner initialized\n");
+                       /* Send back a response */
+-                      if ((rc = ibmvscsi_send_crq(hostdata,
+-                                                  0xC002000000000000LL, 0)) == 0) {
++                      if (ibmvscsi_send_crq(hostdata,
++                                            0xC002000000000000LL, 0) == 0) {
+                               /* Now login */
+                               send_srp_login(hostdata);
+                       } else {
+-                              dev_err(hostdata->dev, "Unable to send init rsp. rc=%ld\n", rc);
++                              printk(KERN_ERR
++                                     "ibmvscsi: Unable to send init rsp\n");
+                       }
  
-       assert_spin_locked(&dlm->spinlock);
-       
--      list_for_each(iter, &dlm->mle_hb_events) {
--              mle = list_entry(iter, struct dlm_master_list_entry, 
--                               hb_events);
-+      list_for_each_entry(mle, &dlm->mle_hb_events, hb_events) {
-               if (node_up)
-                       dlm_mle_node_up(dlm, mle, NULL, idx);
-               else
-@@ -2434,7 +2424,7 @@
-       int ret;
-       int i;
-       int count = 0;
--      struct list_head *queue, *iter;
-+      struct list_head *queue;
-       struct dlm_lock *lock;
+                       break;
+               case 0x02:      /* Initialization response */
+-                      dev_info(hostdata->dev, "partner initialization complete\n");
++                      printk(KERN_INFO
++                             "ibmvscsi: partner initialization complete\n");
  
-       assert_spin_locked(&res->spinlock);
-@@ -2453,8 +2443,7 @@
-       ret = 0;
-       queue = &res->granted;
-       for (i = 0; i < 3; i++) {
--              list_for_each(iter, queue) {
--                      lock = list_entry(iter, struct dlm_lock, list);
-+              list_for_each_entry(lock, queue, list) {
-                       ++count;
-                       if (lock->ml.node == dlm->node_num) {
-                               mlog(0, "found a lock owned by this node still "
-@@ -2923,18 +2912,16 @@
- static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
-                                     struct dlm_lock_resource *res)
- {
--      struct list_head *iter, *iter2;
-       struct list_head *queue = &res->granted;
-       int i, bit;
--      struct dlm_lock *lock;
-+      struct dlm_lock *lock, *next;
+                       /* Now login */
+                       send_srp_login(hostdata);
+                       break;
+               default:
+-                      dev_err(hostdata->dev, "unknown crq message type: %d\n", crq->format);
++                      printk(KERN_ERR "ibmvscsi: unknown crq message type\n");
+               }
+               return;
+       case 0xFF:      /* Hypervisor telling us the connection is closed */
+@@ -1280,7 +1226,8 @@
+               atomic_set(&hostdata->request_limit, 0);
+               if (crq->format == 0x06) {
+                       /* We need to re-setup the interpartition connection */
+-                      dev_info(hostdata->dev, "Re-enabling adapter!\n");
++                      printk(KERN_INFO
++                             "ibmvscsi: Re-enabling adapter!\n");
+                       purge_requests(hostdata, DID_REQUEUE);
+                       if ((ibmvscsi_reenable_crq_queue(&hostdata->queue,
+                                                       hostdata)) ||
+@@ -1288,10 +1235,13 @@
+                                              0xC001000000000000LL, 0))) {
+                                       atomic_set(&hostdata->request_limit,
+                                                  -1);
+-                                      dev_err(hostdata->dev, "error after enable\n");
++                                      printk(KERN_ERR
++                                             "ibmvscsi: error after"
++                                             " enable\n");
+                       }
+               } else {
+-                      dev_err(hostdata->dev, "Virtual adapter failed rc %d!\n",
++                      printk(KERN_INFO
++                             "ibmvscsi: Virtual adapter failed rc %d!\n",
+                              crq->format);
  
-       assert_spin_locked(&res->spinlock);
+                       purge_requests(hostdata, DID_ERROR);
+@@ -1301,7 +1251,8 @@
+                                              0xC001000000000000LL, 0))) {
+                                       atomic_set(&hostdata->request_limit,
+                                                  -1);
+-                                      dev_err(hostdata->dev, "error after reset\n");
++                                      printk(KERN_ERR
++                                             "ibmvscsi: error after reset\n");
+                       }
+               }
+               scsi_unblock_requests(hostdata->host);
+@@ -1309,7 +1260,8 @@
+       case 0x80:              /* real payload */
+               break;
+       default:
+-              dev_err(hostdata->dev, "got an invalid message type 0x%02x\n",
++              printk(KERN_ERR
++                     "ibmvscsi: got an invalid message type 0x%02x\n",
+                      crq->valid);
+               return;
+       }
+@@ -1319,13 +1271,15 @@
+        * actually sent
+        */
+       if (!valid_event_struct(&hostdata->pool, evt_struct)) {
+-              dev_err(hostdata->dev, "returned correlation_token 0x%p is invalid!\n",
++              printk(KERN_ERR
++                     "ibmvscsi: returned correlation_token 0x%p is invalid!\n",
+                      (void *)crq->IU_data_ptr);
+               return;
+       }
  
-       BUG_ON(res->owner == dlm->node_num);
+       if (atomic_read(&evt_struct->free)) {
+-              dev_err(hostdata->dev, "received duplicate correlation_token 0x%p!\n",
++              printk(KERN_ERR
++                     "ibmvscsi: received duplicate  correlation_token 0x%p!\n",
+                      (void *)crq->IU_data_ptr);
+               return;
+       }
+@@ -1334,12 +1288,11 @@
+               atomic_add(evt_struct->xfer_iu->srp.rsp.req_lim_delta,
+                          &hostdata->request_limit);
  
-       for (i=0; i<3; i++) {
--              list_for_each_safe(iter, iter2, queue) {
--                      lock = list_entry (iter, struct dlm_lock, list);
-+              list_for_each_entry_safe(lock, next, queue, list) {
-                       if (lock->ml.node != dlm->node_num) {
-                               mlog(0, "putting lock for node %u\n",
-                                    lock->ml.node);
-@@ -2976,7 +2963,6 @@
+-      del_timer(&evt_struct->timer);
+-
+       if (evt_struct->done)
+               evt_struct->done(evt_struct);
+       else
+-              dev_err(hostdata->dev, "returned done() is NULL; not running it!\n");
++              printk(KERN_ERR
++                     "ibmvscsi: returned done() is NULL; not running it!\n");
+       /*
+        * Lock the host_lock before messing with these structures, since we
+@@ -1360,13 +1313,13 @@
  {
-       int i;
-       struct list_head *queue = &res->granted;
--      struct list_head *iter;
-       struct dlm_lock *lock;
-       int nodenum;
+       struct viosrp_host_config *host_config;
+       struct srp_event_struct *evt_struct;
+-      unsigned long flags;
+       dma_addr_t addr;
+       int rc;
  
-@@ -2984,10 +2970,9 @@
+       evt_struct = get_event_struct(&hostdata->pool);
+       if (!evt_struct) {
+-              dev_err(hostdata->dev, "couldn't allocate event for HOST_CONFIG!\n");
++              printk(KERN_ERR
++                     "ibmvscsi: could't allocate event for HOST_CONFIG!\n");
+               return -1;
+       }
  
-       spin_lock(&res->spinlock);
-       for (i=0; i<3; i++) {
--              list_for_each(iter, queue) {
-+              list_for_each_entry(lock, queue, list) {
-                       /* up to the caller to make sure this node
-                        * is alive */
--                      lock = list_entry (iter, struct dlm_lock, list);
-                       if (lock->ml.node != dlm->node_num) {
-                               spin_unlock(&res->spinlock);
-                               return lock->ml.node;
-@@ -3234,8 +3219,7 @@
+@@ -1386,15 +1339,14 @@
+                                                   DMA_BIDIRECTIONAL);
  
- void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node)
- {
--      struct list_head *iter, *iter2;
--      struct dlm_master_list_entry *mle;
-+      struct dlm_master_list_entry *mle, *next;
-       struct dlm_lock_resource *res;
-       unsigned int hash;
+       if (dma_mapping_error(host_config->buffer)) {
+-              dev_err(hostdata->dev, "dma_mapping error getting host config\n");
++              printk(KERN_ERR
++                     "ibmvscsi: dma_mapping error " "getting host config\n");
+               free_event_struct(&hostdata->pool, evt_struct);
+               return -1;
+       }
  
-@@ -3245,9 +3229,7 @@
+       init_completion(&evt_struct->comp);
+-      spin_lock_irqsave(hostdata->host->host_lock, flags);
+-      rc = ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2);
+-      spin_unlock_irqrestore(hostdata->host->host_lock, flags);
++      rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
+       if (rc == 0)
+               wait_for_completion(&evt_struct->comp);
+       dma_unmap_single(hostdata->dev, addr, length, DMA_BIDIRECTIONAL);
+@@ -1423,23 +1375,6 @@
+       return 0;
+ }
  
-       /* clean the master list */
-       spin_lock(&dlm->master_lock);
--      list_for_each_safe(iter, iter2, &dlm->master_list) {
--              mle = list_entry(iter, struct dlm_master_list_entry, list);
+-/**
+- * ibmvscsi_change_queue_depth - Change the device's queue depth
+- * @sdev:     scsi device struct
+- * @qdepth:   depth to set
+- *
+- * Return value:
+- *    actual depth set
+- **/
+-static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
+-{
+-      if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN)
+-              qdepth = IBMVSCSI_MAX_CMDS_PER_LUN;
 -
-+      list_for_each_entry_safe(mle, next, &dlm->master_list, list) {
-               BUG_ON(mle->type != DLM_MLE_BLOCK &&
-                      mle->type != DLM_MLE_MASTER &&
-                      mle->type != DLM_MLE_MIGRATION);
-diff -Nurb linux-2.6.22-570/fs/ocfs2/dlm/dlmrecovery.c linux-2.6.22-590/fs/ocfs2/dlm/dlmrecovery.c
---- linux-2.6.22-570/fs/ocfs2/dlm/dlmrecovery.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/dlm/dlmrecovery.c        2008-01-02 13:56:37.000000000 -0500
-@@ -158,8 +158,7 @@
-       struct dlm_ctxt *dlm =
-               container_of(work, struct dlm_ctxt, dispatched_work);
-       LIST_HEAD(tmp_list);
--      struct list_head *iter, *iter2;
--      struct dlm_work_item *item;
-+      struct dlm_work_item *item, *next;
-       dlm_workfunc_t *workfunc;
-       int tot=0;
+-      scsi_adjust_queue_depth(sdev, 0, qdepth);
+-      return sdev->queue_depth;
+-}
+-
+ /* ------------------------------------------------------------
+  * sysfs attributes
+  */
+@@ -1585,9 +1520,7 @@
+       .queuecommand = ibmvscsi_queuecommand,
+       .eh_abort_handler = ibmvscsi_eh_abort_handler,
+       .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
+-      .eh_host_reset_handler = ibmvscsi_eh_host_reset_handler,
+       .slave_configure = ibmvscsi_slave_configure,
+-      .change_queue_depth = ibmvscsi_change_queue_depth,
+       .cmd_per_lun = 16,
+       .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
+       .this_id = -1,
+@@ -1612,7 +1545,7 @@
+       driver_template.can_queue = max_requests;
+       host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
+       if (!host) {
+-              dev_err(&vdev->dev, "couldn't allocate host data\n");
++              printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n");
+               goto scsi_host_alloc_failed;
+       }
  
-@@ -167,13 +166,12 @@
-       list_splice_init(&dlm->work_list, &tmp_list);
-       spin_unlock(&dlm->work_lock);
+@@ -1626,11 +1559,11 @@
  
--      list_for_each_safe(iter, iter2, &tmp_list) {
-+      list_for_each_entry(item, &tmp_list, list) {
-               tot++;
+       rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests);
+       if (rc != 0 && rc != H_RESOURCE) {
+-              dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc);
++              printk(KERN_ERR "ibmvscsi: couldn't initialize crq\n");
+               goto init_crq_failed;
+       }
+       if (initialize_event_pool(&hostdata->pool, max_requests, hostdata) != 0) {
+-              dev_err(&vdev->dev, "couldn't initialize event pool\n");
++              printk(KERN_ERR "ibmvscsi: couldn't initialize event pool\n");
+               goto init_pool_failed;
        }
-       mlog(0, "%s: work thread has %d work items\n", dlm->name, tot);
  
--      list_for_each_safe(iter, iter2, &tmp_list) {
--              item = list_entry(iter, struct dlm_work_item, list);
-+      list_for_each_entry_safe(item, next, &tmp_list, list) {
-               workfunc = item->func;
-               list_del_init(&item->list);
+diff -Nurb linux-2.6.22-590/drivers/scsi/ibmvscsi/ibmvscsi.h linux-2.6.22-570/drivers/scsi/ibmvscsi/ibmvscsi.h
+--- linux-2.6.22-590/drivers/scsi/ibmvscsi/ibmvscsi.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/ibmvscsi/ibmvscsi.h  2007-07-08 19:32:17.000000000 -0400
+@@ -45,7 +45,6 @@
+ #define MAX_INDIRECT_BUFS 10
  
-@@ -549,7 +547,6 @@
- {
-       int status = 0;
-       struct dlm_reco_node_data *ndata;
--      struct list_head *iter;
-       int all_nodes_done;
-       int destroy = 0;
-       int pass = 0;
-@@ -567,8 +564,7 @@
+ #define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
+-#define IBMVSCSI_MAX_CMDS_PER_LUN 64
  
-       /* safe to access the node data list without a lock, since this
-        * process is the only one to change the list */
--      list_for_each(iter, &dlm->reco.node_data) {
--              ndata = list_entry (iter, struct dlm_reco_node_data, list);
-+      list_for_each_entry(ndata, &dlm->reco.node_data, list) {
-               BUG_ON(ndata->state != DLM_RECO_NODE_DATA_INIT);
-               ndata->state = DLM_RECO_NODE_DATA_REQUESTING;
+ /* ------------------------------------------------------------
+  * Data Structures
+@@ -70,7 +69,6 @@
+       union viosrp_iu iu;
+       void (*cmnd_done) (struct scsi_cmnd *);
+       struct completion comp;
+-      struct timer_list timer;
+       union viosrp_iu *sync_srp;
+       struct srp_direct_buf *ext_list;
+       dma_addr_t ext_list_token;
+diff -Nurb linux-2.6.22-590/drivers/scsi/ibmvscsi/rpa_vscsi.c linux-2.6.22-570/drivers/scsi/ibmvscsi/rpa_vscsi.c
+--- linux-2.6.22-590/drivers/scsi/ibmvscsi/rpa_vscsi.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/ibmvscsi/rpa_vscsi.c 2007-07-08 19:32:17.000000000 -0400
+@@ -177,7 +177,7 @@
+       memset(&hostdata->madapter_info, 0x00,
+                       sizeof(hostdata->madapter_info));
  
-@@ -655,9 +651,7 @@
-                * done, or if anyone died */
-               all_nodes_done = 1;
-               spin_lock(&dlm_reco_state_lock);
--              list_for_each(iter, &dlm->reco.node_data) {
--                      ndata = list_entry (iter, struct dlm_reco_node_data, list);
--
-+              list_for_each_entry(ndata, &dlm->reco.node_data, list) {
-                       mlog(0, "checking recovery state of node %u\n",
-                            ndata->node_num);
-                       switch (ndata->state) {
-@@ -774,16 +768,14 @@
+-      dev_info(hostdata->dev, "SRP_VERSION: %s\n", SRP_VERSION);
++      printk(KERN_INFO "rpa_vscsi: SPR_VERSION: %s\n", SRP_VERSION);
+       strcpy(hostdata->madapter_info.srp_version, SRP_VERSION);
  
- static void dlm_destroy_recovery_area(struct dlm_ctxt *dlm, u8 dead_node)
- {
--      struct list_head *iter, *iter2;
--      struct dlm_reco_node_data *ndata;
-+      struct dlm_reco_node_data *ndata, *next;
-       LIST_HEAD(tmplist);
+       strncpy(hostdata->madapter_info.partition_name, partition_name,
+@@ -232,24 +232,25 @@
  
-       spin_lock(&dlm_reco_state_lock);
-       list_splice_init(&dlm->reco.node_data, &tmplist);
-       spin_unlock(&dlm_reco_state_lock);
+       if (rc == 2) {
+               /* Adapter is good, but other end is not ready */
+-              dev_warn(hostdata->dev, "Partner adapter not ready\n");
++              printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+               retrc = 0;
+       } else if (rc != 0) {
+-              dev_warn(hostdata->dev, "Error %d opening adapter\n", rc);
++              printk(KERN_WARNING "ibmvscsi: Error %d opening adapter\n", rc);
+               goto reg_crq_failed;
+       }
  
--      list_for_each_safe(iter, iter2, &tmplist) {
--              ndata = list_entry (iter, struct dlm_reco_node_data, list);
-+      list_for_each_entry_safe(ndata, next, &tmplist, list) {
-               list_del_init(&ndata->list);
-               kfree(ndata);
+       if (request_irq(vdev->irq,
+                       ibmvscsi_handle_event,
+                       0, "ibmvscsi", (void *)hostdata) != 0) {
+-              dev_err(hostdata->dev, "couldn't register irq 0x%x\n",
++              printk(KERN_ERR "ibmvscsi: couldn't register irq 0x%x\n",
+                      vdev->irq);
+               goto req_irq_failed;
        }
-@@ -876,7 +868,6 @@
-       struct dlm_lock_resource *res;
-       struct dlm_ctxt *dlm;
-       LIST_HEAD(resources);
--      struct list_head *iter;
-       int ret;
-       u8 dead_node, reco_master;
-       int skip_all_done = 0;
-@@ -920,8 +911,7 @@
  
-       /* any errors returned will be due to the new_master dying,
-        * the dlm_reco_thread should detect this */
--      list_for_each(iter, &resources) {
--              res = list_entry (iter, struct dlm_lock_resource, recovering);
-+      list_for_each_entry(res, &resources, recovering) {
-               ret = dlm_send_one_lockres(dlm, res, mres, reco_master,
-                                       DLM_MRES_RECOVERY);
-               if (ret < 0) {
-@@ -983,7 +973,6 @@
- {
-       struct dlm_ctxt *dlm = data;
-       struct dlm_reco_data_done *done = (struct dlm_reco_data_done *)msg->buf;
--      struct list_head *iter;
-       struct dlm_reco_node_data *ndata = NULL;
-       int ret = -EINVAL;
+       rc = vio_enable_interrupts(vdev);
+       if (rc != 0) {
+-              dev_err(hostdata->dev, "Error %d enabling interrupts!!!\n", rc);
++              printk(KERN_ERR "ibmvscsi:  Error %d enabling interrupts!!!\n",
++                     rc);
+               goto req_irq_failed;
+       }
  
-@@ -1000,8 +989,7 @@
-                       dlm->reco.dead_node, done->node_idx, dlm->node_num);
+@@ -293,7 +294,7 @@
+       } while ((rc == H_IN_PROGRESS) || (rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
  
-       spin_lock(&dlm_reco_state_lock);
--      list_for_each(iter, &dlm->reco.node_data) {
--              ndata = list_entry (iter, struct dlm_reco_node_data, list);
-+      list_for_each_entry(ndata, &dlm->reco.node_data, list) {
-               if (ndata->node_num != done->node_idx)
-                       continue;
+       if (rc)
+-              dev_err(hostdata->dev, "Error %d enabling adapter\n", rc);
++              printk(KERN_ERR "ibmvscsi: Error %d enabling adapter\n", rc);
+       return rc;
+ }
  
-@@ -1049,13 +1037,11 @@
-                                       struct list_head *list,
-                                       u8 dead_node)
- {
--      struct dlm_lock_resource *res;
--      struct list_head *iter, *iter2;
-+      struct dlm_lock_resource *res, *next;
-       struct dlm_lock *lock;
+@@ -326,9 +327,10 @@
+                               queue->msg_token, PAGE_SIZE);
+       if (rc == 2) {
+               /* Adapter is good, but other end is not ready */
+-              dev_warn(hostdata->dev, "Partner adapter not ready\n");
++              printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+       } else if (rc != 0) {
+-              dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc);
++              printk(KERN_WARNING
++                     "ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
+       }
+       return rc;
+ }
+diff -Nurb linux-2.6.22-590/drivers/scsi/initio.c linux-2.6.22-570/drivers/scsi/initio.c
+--- linux-2.6.22-590/drivers/scsi/initio.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/initio.c     2007-07-08 19:32:17.000000000 -0400
+@@ -3,8 +3,7 @@
+  *
+  * Copyright (c) 1994-1998 Initio Corporation
+  * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
+- * Copyright (c) 2004 Christoph Hellwig <hch@lst.de>
+- * Copyright (c) 2007 Red Hat <alan@redhat.com>
++ * All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+@@ -20,6 +19,38 @@
+  * along with this program; see the file COPYING.  If not, write to
+  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+  *
++ * --------------------------------------------------------------------------
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions, and the following disclaimer,
++ *    without modification, immediately at the beginning of the file.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ * Where this Software is combined with software released under the terms of 
++ * the GNU General Public License ("GPL") and the terms of the GPL would require the 
++ * combined work to also be released under the terms of the GPL, the terms
++ * and conditions of this License will apply in addition to those of the
++ * GPL with the exception of any terms or conditions of this License that
++ * conflict with, or are expressly prohibited by, the GPL.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+  *
+  *************************************************************************
+  *
+@@ -39,14 +70,14 @@
+  *            - Fix memory allocation problem
+  * 03/04/98 hc        - v1.01l
+  *            - Fix tape rewind which will hang the system problem
+- *            - Set can_queue to initio_num_scb
++ *            - Set can_queue to tul_num_scb
+  * 06/25/98 hc        - v1.01m
+  *            - Get it work for kernel version >= 2.1.75
+- *            - Dynamic assign SCSI bus reset holding time in initio_init()
++ *            - Dynamic assign SCSI bus reset holding time in init_tulip()
+  * 07/02/98 hc        - v1.01n
+  *            - Support 0002134A
+  * 08/07/98 hc  - v1.01o
+- *            - Change the initio_abort_srb routine to use scsi_done. <01>
++ *            - Change the tul_abort_srb routine to use scsi_done. <01>
+  * 09/07/98 hl  - v1.02
+  *              - Change the INI9100U define and proc_dir_entry to
+  *                reflect the newer Kernel 2.1.118, but the v1.o1o
+@@ -119,13 +150,23 @@
+ static unsigned int i91u_debug = DEBUG_DEFAULT;
+ #endif
  
-       spin_lock(&dlm->spinlock);
--      list_for_each_safe(iter, iter2, &dlm->reco.resources) {
--              res = list_entry (iter, struct dlm_lock_resource, recovering);
-+      list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
-               /* always prune any $RECOVERY entries for dead nodes,
-                * otherwise hangs can occur during later recovery */
-               if (dlm_is_recovery_lock(res->lockname.name,
-@@ -1169,7 +1155,7 @@
-                                       u8 flags, u8 master)
- {
-       /* mres here is one full page */
--      memset(mres, 0, PAGE_SIZE);
-+      clear_page(mres);
-       mres->lockname_len = namelen;
-       memcpy(mres->lockname, lockname, namelen);
-       mres->num_locks = 0;
-@@ -1252,7 +1238,7 @@
-                        struct dlm_migratable_lockres *mres,
-                        u8 send_to, u8 flags)
- {
--      struct list_head *queue, *iter;
-+      struct list_head *queue;
-       int total_locks, i;
-       u64 mig_cookie = 0;
-       struct dlm_lock *lock;
-@@ -1278,9 +1264,7 @@
-       total_locks = 0;
-       for (i=DLM_GRANTED_LIST; i<=DLM_BLOCKED_LIST; i++) {
-               queue = dlm_list_idx_to_ptr(res, i);
--              list_for_each(iter, queue) {
--                      lock = list_entry (iter, struct dlm_lock, list);
--
-+              list_for_each_entry(lock, queue, list) {
-                       /* add another lock. */
-                       total_locks++;
-                       if (!dlm_add_lock_to_array(lock, mres, i))
-@@ -1717,7 +1701,6 @@
-       struct dlm_lockstatus *lksb = NULL;
-       int ret = 0;
-       int i, j, bad;
--      struct list_head *iter;
-       struct dlm_lock *lock = NULL;
-       u8 from = O2NM_MAX_NODES;
-       unsigned int added = 0;
-@@ -1755,8 +1738,7 @@
-                       spin_lock(&res->spinlock);
-                       for (j = DLM_GRANTED_LIST; j <= DLM_BLOCKED_LIST; j++) {
-                               tmpq = dlm_list_idx_to_ptr(res, j);
--                              list_for_each(iter, tmpq) {
--                                      lock = list_entry (iter, struct dlm_lock, list);
-+                              list_for_each_entry(lock, tmpq, list) {
-                                       if (lock->ml.cookie != ml->cookie)
-                                               lock = NULL;
-                                       else
-@@ -1930,8 +1912,8 @@
-                                      struct dlm_lock_resource *res)
- {
-       int i;
--      struct list_head *queue, *iter, *iter2;
--      struct dlm_lock *lock;
-+      struct list_head *queue;
-+      struct dlm_lock *lock, *next;
+-static int initio_tag_enable = 1;
++#define TUL_RDWORD(x,y)         (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
++
++typedef struct PCI_ID_Struc {
++      unsigned short vendor_id;
++      unsigned short device_id;
++} PCI_ID;
++
++static int tul_num_ch = 4;    /* Maximum 4 adapters           */
++static int tul_num_scb;
++static int tul_tag_enable = 1;
++static SCB *tul_scb;
  
-       res->state |= DLM_LOCK_RES_RECOVERING;
-       if (!list_empty(&res->recovering)) {
-@@ -1947,8 +1929,7 @@
-       /* find any pending locks and put them back on proper list */
-       for (i=DLM_BLOCKED_LIST; i>=DLM_GRANTED_LIST; i--) {
-               queue = dlm_list_idx_to_ptr(res, i);
--              list_for_each_safe(iter, iter2, queue) {
--                      lock = list_entry (iter, struct dlm_lock, list);
-+              list_for_each_entry_safe(lock, next, queue, list) {
-                       dlm_lock_get(lock);
-                       if (lock->convert_pending) {
-                               /* move converting lock back to granted */
-@@ -2013,18 +1994,15 @@
-                                             u8 dead_node, u8 new_master)
- {
-       int i;
--      struct list_head *iter, *iter2;
-       struct hlist_node *hash_iter;
-       struct hlist_head *bucket;
--
--      struct dlm_lock_resource *res;
-+      struct dlm_lock_resource *res, *next;
+ #ifdef DEBUG_i91u
+ static int setup_debug = 0;
+ #endif
  
-       mlog_entry_void();
+-static void i91uSCBPost(u8 * pHcb, u8 * pScb);
++static void i91uSCBPost(BYTE * pHcb, BYTE * pScb);
  
-       assert_spin_locked(&dlm->spinlock);
+ /* PCI Devices supported by this driver */
+ static struct pci_device_id i91u_pci_devices[] = {
+@@ -143,66 +184,74 @@
+ #define DEBUG_STATE     0
+ #define INT_DISC      0
  
--      list_for_each_safe(iter, iter2, &dlm->reco.resources) {
--              res = list_entry (iter, struct dlm_lock_resource, recovering);
-+      list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
-               if (res->owner == dead_node) {
-                       list_del_init(&res->recovering);
-                       spin_lock(&res->spinlock);
-@@ -2099,7 +2077,7 @@
- static void dlm_revalidate_lvb(struct dlm_ctxt *dlm,
-                              struct dlm_lock_resource *res, u8 dead_node)
- {
--      struct list_head *iter, *queue;
-+      struct list_head *queue;
-       struct dlm_lock *lock;
-       int blank_lvb = 0, local = 0;
-       int i;
-@@ -2121,8 +2099,7 @@
+-/*--- forward references ---*/
+-static struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun);
+-static struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host);
+-
+-static int tulip_main(struct initio_host * host);
+-
+-static int initio_next_state(struct initio_host * host);
+-static int initio_state_1(struct initio_host * host);
+-static int initio_state_2(struct initio_host * host);
+-static int initio_state_3(struct initio_host * host);
+-static int initio_state_4(struct initio_host * host);
+-static int initio_state_5(struct initio_host * host);
+-static int initio_state_6(struct initio_host * host);
+-static int initio_state_7(struct initio_host * host);
+-static int initio_xfer_data_in(struct initio_host * host);
+-static int initio_xfer_data_out(struct initio_host * host);
+-static int initio_xpad_in(struct initio_host * host);
+-static int initio_xpad_out(struct initio_host * host);
+-static int initio_status_msg(struct initio_host * host);
+-
+-static int initio_msgin(struct initio_host * host);
+-static int initio_msgin_sync(struct initio_host * host);
+-static int initio_msgin_accept(struct initio_host * host);
+-static int initio_msgout_reject(struct initio_host * host);
+-static int initio_msgin_extend(struct initio_host * host);
+-
+-static int initio_msgout_ide(struct initio_host * host);
+-static int initio_msgout_abort_targ(struct initio_host * host);
+-static int initio_msgout_abort_tag(struct initio_host * host);
+-
+-static int initio_bus_device_reset(struct initio_host * host);
+-static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb);
+-static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb);
+-static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb);
+-static int int_initio_busfree(struct initio_host * host);
+-static int int_initio_scsi_rst(struct initio_host * host);
+-static int int_initio_bad_seq(struct initio_host * host);
+-static int int_initio_resel(struct initio_host * host);
+-static int initio_sync_done(struct initio_host * host);
+-static int wdtr_done(struct initio_host * host);
+-static int wait_tulip(struct initio_host * host);
+-static int initio_wait_done_disc(struct initio_host * host);
+-static int initio_wait_disc(struct initio_host * host);
+-static void tulip_scsi(struct initio_host * host);
+-static int initio_post_scsi_rst(struct initio_host * host);
+-
+-static void initio_se2_ew_en(unsigned long base);
+-static void initio_se2_ew_ds(unsigned long base);
+-static int initio_se2_rd_all(unsigned long base);
+-static void initio_se2_update_all(unsigned long base);        /* setup default pattern */
+-static void initio_read_eeprom(unsigned long base);
++/*--- external functions --*/
++static void tul_se2_wait(void);
+-/* ---- INTERNAL VARIABLES ---- */
++/*--- forward refrence ---*/
++static SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun);
++static SCB *tul_find_done_scb(HCS * pCurHcb);
++
++static int tulip_main(HCS * pCurHcb);
++
++static int tul_next_state(HCS * pCurHcb);
++static int tul_state_1(HCS * pCurHcb);
++static int tul_state_2(HCS * pCurHcb);
++static int tul_state_3(HCS * pCurHcb);
++static int tul_state_4(HCS * pCurHcb);
++static int tul_state_5(HCS * pCurHcb);
++static int tul_state_6(HCS * pCurHcb);
++static int tul_state_7(HCS * pCurHcb);
++static int tul_xfer_data_in(HCS * pCurHcb);
++static int tul_xfer_data_out(HCS * pCurHcb);
++static int tul_xpad_in(HCS * pCurHcb);
++static int tul_xpad_out(HCS * pCurHcb);
++static int tul_status_msg(HCS * pCurHcb);
++
++static int tul_msgin(HCS * pCurHcb);
++static int tul_msgin_sync(HCS * pCurHcb);
++static int tul_msgin_accept(HCS * pCurHcb);
++static int tul_msgout_reject(HCS * pCurHcb);
++static int tul_msgin_extend(HCS * pCurHcb);
++
++static int tul_msgout_ide(HCS * pCurHcb);
++static int tul_msgout_abort_targ(HCS * pCurHcb);
++static int tul_msgout_abort_tag(HCS * pCurHcb);
++
++static int tul_bus_device_reset(HCS * pCurHcb);
++static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb);
++static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb);
++static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb);
++static int int_tul_busfree(HCS * pCurHcb);
++static int int_tul_scsi_rst(HCS * pCurHcb);
++static int int_tul_bad_seq(HCS * pCurHcb);
++static int int_tul_resel(HCS * pCurHcb);
++static int tul_sync_done(HCS * pCurHcb);
++static int wdtr_done(HCS * pCurHcb);
++static int wait_tulip(HCS * pCurHcb);
++static int tul_wait_done_disc(HCS * pCurHcb);
++static int tul_wait_disc(HCS * pCurHcb);
++static void tulip_scsi(HCS * pCurHcb);
++static int tul_post_scsi_rst(HCS * pCurHcb);
++
++static void tul_se2_ew_en(WORD CurBase);
++static void tul_se2_ew_ds(WORD CurBase);
++static int tul_se2_rd_all(WORD CurBase);
++static void tul_se2_update_all(WORD CurBase); /* setup default pattern */
++static void tul_read_eeprom(WORD CurBase);
++
++                              /* ---- INTERNAL VARIABLES ---- */
++static HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
++static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS];
++/*NVRAM nvram, *nvramp = &nvram; */
+ static NVRAM i91unvram;
+ static NVRAM *i91unvramp;
  
-       for (i=DLM_GRANTED_LIST; i<=DLM_CONVERTING_LIST; i++) {
-               queue = dlm_list_idx_to_ptr(res, i);
--              list_for_each(iter, queue) {
--                      lock = list_entry (iter, struct dlm_lock, list);
-+              list_for_each_entry(lock, queue, list) {
-                       if (lock->ml.node == search_node) {
-                               if (dlm_lvb_needs_invalidation(lock, local)) {
-                                       /* zero the lksb lvb and lockres lvb */
-@@ -2143,8 +2120,7 @@
- static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
-                               struct dlm_lock_resource *res, u8 dead_node)
+-static u8 i91udftNvRam[64] =
++
++
++static UCHAR i91udftNvRam[64] =
  {
--      struct list_head *iter, *tmpiter;
--      struct dlm_lock *lock;
-+      struct dlm_lock *lock, *next;
-       unsigned int freed = 0;
+-      /*----------- header -----------*/
++/*----------- header -----------*/
+       0x25, 0xc9,             /* Signature    */
+       0x40,                   /* Size         */
+       0x01,                   /* Revision     */
+@@ -240,7 +289,7 @@
+       0, 0};                  /*      - CheckSum -            */
  
-       /* this node is the lockres master:
-@@ -2155,24 +2131,21 @@
-       assert_spin_locked(&res->spinlock);
  
-       /* TODO: check pending_asts, pending_basts here */
--      list_for_each_safe(iter, tmpiter, &res->granted) {
--              lock = list_entry (iter, struct dlm_lock, list);
-+      list_for_each_entry_safe(lock, next, &res->granted, list) {
-               if (lock->ml.node == dead_node) {
-                       list_del_init(&lock->list);
-                       dlm_lock_put(lock);
-                       freed++;
-               }
-       }
--      list_for_each_safe(iter, tmpiter, &res->converting) {
--              lock = list_entry (iter, struct dlm_lock, list);
-+      list_for_each_entry_safe(lock, next, &res->converting, list) {
-               if (lock->ml.node == dead_node) {
-                       list_del_init(&lock->list);
-                       dlm_lock_put(lock);
-                       freed++;
-               }
-       }
--      list_for_each_safe(iter, tmpiter, &res->blocked) {
--              lock = list_entry (iter, struct dlm_lock, list);
-+      list_for_each_entry_safe(lock, next, &res->blocked, list) {
-               if (lock->ml.node == dead_node) {
-                       list_del_init(&lock->list);
-                       dlm_lock_put(lock);
-diff -Nurb linux-2.6.22-570/fs/ocfs2/dlmglue.c linux-2.6.22-590/fs/ocfs2/dlmglue.c
---- linux-2.6.22-570/fs/ocfs2/dlmglue.c        2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/ocfs2/dlmglue.c        2008-01-02 13:56:37.000000000 -0500
-@@ -600,15 +600,13 @@
- static void lockres_set_flags(struct ocfs2_lock_res *lockres,
-                             unsigned long newflags)
+-static u8 initio_rate_tbl[8] =        /* fast 20      */
++static UCHAR tul_rate_tbl[8] =        /* fast 20      */
  {
--      struct list_head *pos, *tmp;
--      struct ocfs2_mask_waiter *mw;
-+      struct ocfs2_mask_waiter *mw, *tmp;
-       assert_spin_locked(&lockres->l_lock);
-       lockres->l_flags = newflags;
+                               /* nanosecond devide by 4 */
+       12,                     /* 50ns,  20M   */
+@@ -253,17 +302,53 @@
+       62                      /* 250ns, 4M    */
+ };
  
--      list_for_each_safe(pos, tmp, &lockres->l_mask_waiters) {
--              mw = list_entry(pos, struct ocfs2_mask_waiter, mw_item);
-+      list_for_each_entry_safe(mw, tmp, &lockres->l_mask_waiters, mw_item) {
-               if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal)
-                       continue;
+-static void initio_do_pause(unsigned amount)
+-{
+-      /* Pause for amount jiffies */
++static void tul_do_pause(unsigned amount)
++{                             /* Pause for amount jiffies */
+       unsigned long the_time = jiffies + amount;
  
-diff -Nurb linux-2.6.22-570/fs/ocfs2/endian.h linux-2.6.22-590/fs/ocfs2/endian.h
---- linux-2.6.22-570/fs/ocfs2/endian.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/endian.h 2008-01-02 13:56:37.000000000 -0500
-@@ -32,6 +32,11 @@
-       *var = cpu_to_le32(le32_to_cpu(*var) + val);
+-      while (time_before_eq(jiffies, the_time))
+-              cpu_relax();
++      while (time_before_eq(jiffies, the_time));
  }
  
-+static inline void le64_add_cpu(__le64 *var, u64 val)
+ /*-- forward reference --*/
++/*******************************************************************
++      Use memeory refresh time        ~ 15us * 2
++********************************************************************/
++void tul_se2_wait(void)
 +{
-+      *var = cpu_to_le64(le64_to_cpu(*var) + val);
++#if 1
++      udelay(30);
++#else
++      UCHAR readByte;
++
++      readByte = TUL_RD(0, 0x61);
++      if ((readByte & 0x10) == 0x10) {
++              for (;;) {
++                      readByte = TUL_RD(0, 0x61);
++                      if ((readByte & 0x10) == 0x10)
++                              break;
++              }
++              for (;;) {
++                      readByte = TUL_RD(0, 0x61);
++                      if ((readByte & 0x10) != 0x10)
++                              break;
++              }
++      } else {
++              for (;;) {
++                      readByte = TUL_RD(0, 0x61);
++                      if ((readByte & 0x10) == 0x10)
++                              break;
++              }
++              for (;;) {
++                      readByte = TUL_RD(0, 0x61);
++                      if ((readByte & 0x10) != 0x10)
++                              break;
++              }
++      }
++#endif
 +}
 +
- static inline void le32_and_cpu(__le32 *var, u32 val)
- {
-       *var = cpu_to_le32(le32_to_cpu(*var) & val);
-diff -Nurb linux-2.6.22-570/fs/ocfs2/extent_map.c linux-2.6.22-590/fs/ocfs2/extent_map.c
---- linux-2.6.22-570/fs/ocfs2/extent_map.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/extent_map.c     2008-01-02 13:56:37.000000000 -0500
-@@ -109,17 +109,14 @@
-  */
- void ocfs2_extent_map_trunc(struct inode *inode, unsigned int cpos)
- {
--      struct list_head *p, *n;
--      struct ocfs2_extent_map_item *emi;
-+      struct ocfs2_extent_map_item *emi, *n;
-       struct ocfs2_inode_info *oi = OCFS2_I(inode);
-       struct ocfs2_extent_map *em = &oi->ip_extent_map;
-       LIST_HEAD(tmp_list);
-       unsigned int range;
++
+ /******************************************************************
+  Input: instruction for  Serial E2PROM
  
-       spin_lock(&oi->ip_lock);
--      list_for_each_safe(p, n, &em->em_list) {
--              emi = list_entry(p, struct ocfs2_extent_map_item, ei_list);
--
-+      list_for_each_entry_safe(emi, n, &em->em_list, ei_list) {
-               if (emi->ei_cpos >= cpos) {
-                       /* Full truncate of this record. */
-                       list_move(&emi->ei_list, &tmp_list);
-@@ -136,8 +133,7 @@
-       }
-       spin_unlock(&oi->ip_lock);
+@@ -294,1019 +379,1174 @@
  
--      list_for_each_safe(p, n, &tmp_list) {
--              emi = list_entry(p, struct ocfs2_extent_map_item, ei_list);
-+      list_for_each_entry_safe(emi, n, &tmp_list, ei_list) {
-               list_del(&emi->ei_list);
-               kfree(emi);
-       }
-@@ -377,37 +373,6 @@
-       return ret;
- }
  
--/*
-- * Return the index of the extent record which contains cluster #v_cluster.
-- * -1 is returned if it was not found.
+ ******************************************************************/
+-
+-/**
+- *    initio_se2_instr        -       bitbang an instruction
+- *    @base: Base of InitIO controller
+- *    @instr: Instruction for serial E2PROM
 - *
-- * Should work fine on interior and exterior nodes.
+- *    Bitbang an instruction out to the serial E2Prom
 - */
--static int ocfs2_search_extent_list(struct ocfs2_extent_list *el,
--                                  u32 v_cluster)
--{
--      int ret = -1;
--      int i;
--      struct ocfs2_extent_rec *rec;
--      u32 rec_end, rec_start, clusters;
--
--      for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
--              rec = &el->l_recs[i];
--
--              rec_start = le32_to_cpu(rec->e_cpos);
--              clusters = ocfs2_rec_clusters(el, rec);
--
--              rec_end = rec_start + clusters;
--
--              if (v_cluster >= rec_start && v_cluster < rec_end) {
--                      ret = i;
--                      break;
--              }
--      }
 -
--      return ret;
--}
--
- int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
-                      u32 *p_cluster, u32 *num_clusters,
-                      unsigned int *extent_flags)
-diff -Nurb linux-2.6.22-570/fs/ocfs2/file.c linux-2.6.22-590/fs/ocfs2/file.c
---- linux-2.6.22-570/fs/ocfs2/file.c   2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/ocfs2/file.c   2008-01-02 13:56:37.000000000 -0500
-@@ -326,9 +326,6 @@
-                  (unsigned long long)OCFS2_I(inode)->ip_blkno,
-                  (unsigned long long)new_i_size);
+-static void initio_se2_instr(unsigned long base, u8 instr)
++static void tul_se2_instr(WORD CurBase, UCHAR instr)
+ {
+       int i;
+-      u8 b;
++      UCHAR b;
  
--      unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1);
--      truncate_inode_pages(inode->i_mapping, new_i_size);
--
-       fe = (struct ocfs2_dinode *) di_bh->b_data;
-       if (!OCFS2_IS_VALID_DINODE(fe)) {
-               OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
-@@ -363,16 +360,23 @@
-       if (new_i_size == le64_to_cpu(fe->i_size))
-               goto bail;
+-      outb(SE2CS | SE2DO, base + TUL_NVRAM);          /* cs+start bit */
+-      udelay(30);
+-      outb(SE2CS | SE2CLK | SE2DO, base + TUL_NVRAM); /* +CLK */
+-      udelay(30);
++      TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);     /* cs+start bit */
++      tul_se2_wait();
++      TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK | SE2DO);    /* +CLK */
++      tul_se2_wait();
  
-+      down_write(&OCFS2_I(inode)->ip_alloc_sem);
-+
-       /* This forces other nodes to sync and drop their pages. Do
-        * this even if we have a truncate without allocation change -
-        * ocfs2 cluster sizes can be much greater than page size, so
-        * we have to truncate them anyway.  */
-       status = ocfs2_data_lock(inode, 1);
-       if (status < 0) {
-+              up_write(&OCFS2_I(inode)->ip_alloc_sem);
-+
-               mlog_errno(status);
-               goto bail;
+       for (i = 0; i < 8; i++) {
+               if (instr & 0x80)
+                       b = SE2CS | SE2DO;      /* -CLK+dataBit */
+               else
+                       b = SE2CS;      /* -CLK */
+-              outb(b, base + TUL_NVRAM);
+-              udelay(30);
+-              outb(b | SE2CLK, base + TUL_NVRAM);     /* +CLK */
+-              udelay(30);
++              TUL_WR(CurBase + TUL_NVRAM, b);
++              tul_se2_wait();
++              TUL_WR(CurBase + TUL_NVRAM, b | SE2CLK);        /* +CLK */
++              tul_se2_wait();
+               instr <<= 1;
        }
+-      outb(SE2CS, base + TUL_NVRAM);                  /* -CLK */
+-      udelay(30);
++      TUL_WR(CurBase + TUL_NVRAM, SE2CS);     /* -CLK */
++      tul_se2_wait();
++      return;
+ }
  
-+      unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1);
-+      truncate_inode_pages(inode->i_mapping, new_i_size);
-+
-       /* alright, we're going to need to do a full blown alloc size
-        * change. Orphan the inode so that recovery can complete the
-        * truncate if necessary. This does the task of marking
-@@ -399,6 +403,8 @@
- bail_unlock_data:
-       ocfs2_data_unlock(inode, 1);
-+      up_write(&OCFS2_I(inode)->ip_alloc_sem);
-+
- bail:
-       mlog_exit(status);
-@@ -419,6 +425,7 @@
-                              struct inode *inode,
-                              u32 *logical_offset,
-                              u32 clusters_to_add,
-+                             int mark_unwritten,
-                              struct buffer_head *fe_bh,
-                              handle_t *handle,
-                              struct ocfs2_alloc_context *data_ac,
-@@ -431,9 +438,13 @@
-       enum ocfs2_alloc_restarted reason = RESTART_NONE;
-       u32 bit_off, num_bits;
-       u64 block;
-+      u8 flags = 0;
-       BUG_ON(!clusters_to_add);
-+      if (mark_unwritten)
-+              flags = OCFS2_EXT_UNWRITTEN;
-+
-       free_extents = ocfs2_num_free_extents(osb, inode, fe);
-       if (free_extents < 0) {
-               status = free_extents;
-@@ -483,7 +494,7 @@
-            num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
-       status = ocfs2_insert_extent(osb, handle, inode, fe_bh,
-                                    *logical_offset, block, num_bits,
--                                   meta_ac);
-+                                   flags, meta_ac);
-       if (status < 0) {
-               mlog_errno(status);
-               goto leave;
-@@ -516,25 +527,28 @@
-  * For a given allocation, determine which allocators will need to be
-  * accessed, and lock them, reserving the appropriate number of bits.
-  *
-- * Called from ocfs2_extend_allocation() for file systems which don't
-- * support holes, and from ocfs2_write() for file systems which
-- * understand sparse inodes.
-+ * Sparse file systems call this from ocfs2_write_begin_nolock()
-+ * and ocfs2_allocate_unwritten_extents().
-+ *
-+ * File systems which don't support holes call this from
-+ * ocfs2_extend_allocation().
-  */
- int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
--                        u32 clusters_to_add,
-+                        u32 clusters_to_add, u32 extents_to_split,
-                         struct ocfs2_alloc_context **data_ac,
-                         struct ocfs2_alloc_context **meta_ac)
- {
-       int ret, num_free_extents;
-+      unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split;
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       *meta_ac = NULL;
-       *data_ac = NULL;
-       mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, "
--           "clusters_to_add = %u\n",
-+           "clusters_to_add = %u, extents_to_split = %u\n",
-            (unsigned long long)OCFS2_I(inode)->ip_blkno, i_size_read(inode),
--           le32_to_cpu(di->i_clusters), clusters_to_add);
-+           le32_to_cpu(di->i_clusters), clusters_to_add, extents_to_split);
  
-       num_free_extents = ocfs2_num_free_extents(osb, inode, di);
-       if (num_free_extents < 0) {
-@@ -552,9 +566,12 @@
-        *
-        * Most of the time we'll only be seeing this 1 cluster at a time
-        * anyway.
-+       *
-+       * Always lock for any unwritten extents - we might want to
-+       * remove blocks for a merge.
-        */
-       if (!num_free_extents ||
--          (ocfs2_sparse_alloc(osb) && num_free_extents < clusters_to_add)) {
-+          (ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed)) {
-               ret = ocfs2_reserve_new_metadata(osb, di, meta_ac);
-               if (ret < 0) {
-                       if (ret != -ENOSPC)
-@@ -585,14 +602,13 @@
-       return ret;
+-/**
+- *    initio_se2_ew_en        -       Enable erase/write
+- *    @base: Base address of InitIO controller
+- *
+- *    Enable erase/write state of serial EEPROM
+- */
+-void initio_se2_ew_en(unsigned long base)
++/******************************************************************
++ Function name  : tul_se2_ew_en
++ Description    : Enable erase/write state of serial EEPROM
++******************************************************************/
++void tul_se2_ew_en(WORD CurBase)
+ {
+-      initio_se2_instr(base, 0x30);   /* EWEN */
+-      outb(0, base + TUL_NVRAM);      /* -CS  */
+-      udelay(30);
++      tul_se2_instr(CurBase, 0x30);   /* EWEN */
++      TUL_WR(CurBase + TUL_NVRAM, 0);         /* -CS  */
++      tul_se2_wait();
++      return;
  }
  
--static int ocfs2_extend_allocation(struct inode *inode,
--                                 u32 clusters_to_add)
-+static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
-+                                   u32 clusters_to_add, int mark_unwritten)
- {
-       int status = 0;
-       int restart_func = 0;
--      int drop_alloc_sem = 0;
-       int credits;
--      u32 prev_clusters, logical_start;
-+      u32 prev_clusters;
-       struct buffer_head *bh = NULL;
-       struct ocfs2_dinode *fe = NULL;
-       handle_t *handle = NULL;
-@@ -607,7 +623,7 @@
-        * This function only exists for file systems which don't
-        * support holes.
-        */
--      BUG_ON(ocfs2_sparse_alloc(osb));
-+      BUG_ON(mark_unwritten && !ocfs2_sparse_alloc(osb));
  
-       status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &bh,
-                                 OCFS2_BH_CACHED, inode);
-@@ -623,19 +639,10 @@
-               goto leave;
-       }
+-/**
+- *    initio_se2_ew_ds        -       Disable erase/write
+- *    @base: Base address of InitIO controller
+- *
+- *    Disable erase/write state of serial EEPROM
+- */
+-void initio_se2_ew_ds(unsigned long base)
+-{
+-      initio_se2_instr(base, 0);      /* EWDS */
+-      outb(0, base + TUL_NVRAM);      /* -CS  */
+-      udelay(30);
++/************************************************************************
++ Disable erase/write state of serial EEPROM
++*************************************************************************/
++void tul_se2_ew_ds(WORD CurBase)
++{
++      tul_se2_instr(CurBase, 0);      /* EWDS */
++      TUL_WR(CurBase + TUL_NVRAM, 0);         /* -CS  */
++      tul_se2_wait();
++      return;
+ }
  
--      logical_start = OCFS2_I(inode)->ip_clusters;
--
- restart_all:
-       BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters);
  
--      /* blocks peope in read/write from reading our allocation
--       * until we're done changing it. We depend on i_mutex to block
--       * other extend/truncate calls while we're here. Ordering wrt
--       * start_trans is important here -- always do it before! */
--      down_write(&OCFS2_I(inode)->ip_alloc_sem);
--      drop_alloc_sem = 1;
--
--      status = ocfs2_lock_allocators(inode, fe, clusters_to_add, &data_ac,
-+      status = ocfs2_lock_allocators(inode, fe, clusters_to_add, 0, &data_ac,
-                                      &meta_ac);
-       if (status) {
-               mlog_errno(status);
-@@ -668,6 +675,7 @@
-                                           inode,
-                                           &logical_start,
-                                           clusters_to_add,
-+                                          mark_unwritten,
-                                           bh,
-                                           handle,
-                                           data_ac,
-@@ -720,10 +728,6 @@
-            OCFS2_I(inode)->ip_clusters, i_size_read(inode));
+-/**
+- *    initio_se2_rd           -       read E2PROM word
+- *    @base: Base of InitIO controller
+- *    @addr: Address of word in E2PROM
+- *
+- *    Read a word from the NV E2PROM device
+- */
+-static u16 initio_se2_rd(unsigned long base, u8 addr)
++/******************************************************************
++      Input  :address of Serial E2PROM
++      Output :value stored in  Serial E2PROM
++*******************************************************************/
++static USHORT tul_se2_rd(WORD CurBase, ULONG adr)
+ {
+-      u8 instr, rb;
+-      u16 val = 0;
++      UCHAR instr, readByte;
++      USHORT readWord;
+       int i;
  
- leave:
--      if (drop_alloc_sem) {
--              up_write(&OCFS2_I(inode)->ip_alloc_sem);
--              drop_alloc_sem = 0;
--      }
-       if (handle) {
-               ocfs2_commit_trans(osb, handle);
-               handle = NULL;
-@@ -749,6 +753,25 @@
-       return status;
- }
+-      instr = (u8) (addr | 0x80);
+-      initio_se2_instr(base, instr);  /* READ INSTR */
++      instr = (UCHAR) (adr | 0x80);
++      tul_se2_instr(CurBase, instr);  /* READ INSTR */
++      readWord = 0;
  
-+static int ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
-+                                 u32 clusters_to_add, int mark_unwritten)
-+{
-+      int ret;
-+
-+      /*
-+       * The alloc sem blocks peope in read/write from reading our
-+       * allocation until we're done changing it. We depend on
-+       * i_mutex to block other extend/truncate calls while we're
-+       * here.
-+       */
-+      down_write(&OCFS2_I(inode)->ip_alloc_sem);
-+      ret = __ocfs2_extend_allocation(inode, logical_start, clusters_to_add,
-+                                      mark_unwritten);
-+      up_write(&OCFS2_I(inode)->ip_alloc_sem);
-+
-+      return ret;
-+}
-+
- /* Some parts of this taken from generic_cont_expand, which turned out
-  * to be too fragile to do exactly what we need without us having to
-  * worry about recursive locking in ->prepare_write() and
-@@ -890,7 +913,9 @@
-       }
+       for (i = 15; i >= 0; i--) {
+-              outb(SE2CS | SE2CLK, base + TUL_NVRAM); /* +CLK */
+-              udelay(30);
+-              outb(SE2CS, base + TUL_NVRAM);          /* -CLK */
++              TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);    /* +CLK */
++              tul_se2_wait();
++              TUL_WR(CurBase + TUL_NVRAM, SE2CS);     /* -CLK */
  
-       if (clusters_to_add) {
--              ret = ocfs2_extend_allocation(inode, clusters_to_add);
-+              ret = ocfs2_extend_allocation(inode,
-+                                            OCFS2_I(inode)->ip_clusters,
-+                                            clusters_to_add, 0);
-               if (ret < 0) {
-                       mlog_errno(ret);
-                       goto out_unlock;
-@@ -997,6 +1022,13 @@
-               goto bail_unlock;
+               /* sample data after the following edge of clock  */
+-              rb = inb(base + TUL_NVRAM);
+-              rb &= SE2DI;
+-              val += (rb << i);
+-              udelay(30);     /* 6/20/95 */
++              readByte = TUL_RD(CurBase, TUL_NVRAM);
++              readByte &= SE2DI;
++              readWord += (readByte << i);
++              tul_se2_wait(); /* 6/20/95 */
        }
  
-+      /*
-+       * This will intentionally not wind up calling vmtruncate(),
-+       * since all the work for a size change has been done above.
-+       * Otherwise, we could get into problems with truncate as
-+       * ip_alloc_sem is used there to protect against i_size
-+       * changes.
-+       */
-       status = inode_setattr(inode, attr);
-       if (status < 0) {
-               mlog_errno(status);
-@@ -1072,17 +1104,16 @@
-       return ret;
+-      outb(0, base + TUL_NVRAM);              /* no chip select */
+-      udelay(30);
+-      return val;
++      TUL_WR(CurBase + TUL_NVRAM, 0);         /* no chip select */
++      tul_se2_wait();
++      return readWord;
  }
  
--static int ocfs2_write_remove_suid(struct inode *inode)
-+static int __ocfs2_write_remove_suid(struct inode *inode,
-+                                   struct buffer_head *bh)
+-/**
+- *    initio_se2_wr           -       read E2PROM word
+- *    @base: Base of InitIO controller
+- *    @addr: Address of word in E2PROM
+- *    @val: Value to write
+- *
+- *    Write a word to the NV E2PROM device. Used when recovering from
+- *    a problem with the NV.
+- */
+-static void initio_se2_wr(unsigned long base, u8 addr, u16 val)
++
++/******************************************************************
++ Input: new value in  Serial E2PROM, address of Serial E2PROM
++*******************************************************************/
++static void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord)
  {
-       int ret;
--      struct buffer_head *bh = NULL;
--      struct ocfs2_inode_info *oi = OCFS2_I(inode);
-       handle_t *handle;
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       struct ocfs2_dinode *di;
+-      u8 rb;
+-      u8 instr;
++      UCHAR readByte;
++      UCHAR instr;
+       int i;
  
-       mlog_entry("(Inode %llu, mode 0%o)\n",
--                 (unsigned long long)oi->ip_blkno, inode->i_mode);
-+                 (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode);
+-      instr = (u8) (addr | 0x40);
+-      initio_se2_instr(base, instr);  /* WRITE INSTR */
++      instr = (UCHAR) (adr | 0x40);
++      tul_se2_instr(CurBase, instr);  /* WRITE INSTR */
+       for (i = 15; i >= 0; i--) {
+-              if (val & 0x8000)
+-                      outb(SE2CS | SE2DO, base + TUL_NVRAM);  /* -CLK+dataBit 1 */
++              if (writeWord & 0x8000)
++                      TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);     /* -CLK+dataBit 1 */
+               else
+-                      outb(SE2CS, base + TUL_NVRAM);          /* -CLK+dataBit 0 */
+-              udelay(30);
+-              outb(SE2CS | SE2CLK, base + TUL_NVRAM);         /* +CLK */
+-              udelay(30);
+-              val <<= 1;
+-      }
+-      outb(SE2CS, base + TUL_NVRAM);                          /* -CLK */
+-      udelay(30);
+-      outb(0, base + TUL_NVRAM);                              /* -CS  */
+-      udelay(30);
++                      TUL_WR(CurBase + TUL_NVRAM, SE2CS);     /* -CLK+dataBit 0 */
++              tul_se2_wait();
++              TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);    /* +CLK */
++              tul_se2_wait();
++              writeWord <<= 1;
++      }
++      TUL_WR(CurBase + TUL_NVRAM, SE2CS);     /* -CLK */
++      tul_se2_wait();
++      TUL_WR(CurBase + TUL_NVRAM, 0);         /* -CS  */
++      tul_se2_wait();
+-      outb(SE2CS, base + TUL_NVRAM);                          /* +CS  */
+-      udelay(30);
++      TUL_WR(CurBase + TUL_NVRAM, SE2CS);     /* +CS  */
++      tul_se2_wait();
  
-       handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
-       if (handle == NULL) {
-@@ -1091,17 +1122,11 @@
-               goto out;
+       for (;;) {
+-              outb(SE2CS | SE2CLK, base + TUL_NVRAM);         /* +CLK */
+-              udelay(30);
+-              outb(SE2CS, base + TUL_NVRAM);                  /* -CLK */
+-              udelay(30);
+-              if ((rb = inb(base + TUL_NVRAM)) & SE2DI)
++              TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);    /* +CLK */
++              tul_se2_wait();
++              TUL_WR(CurBase + TUL_NVRAM, SE2CS);     /* -CLK */
++              tul_se2_wait();
++              if ((readByte = TUL_RD(CurBase, TUL_NVRAM)) & SE2DI)
+                       break;  /* write complete */
        }
+-      outb(0, base + TUL_NVRAM);                              /* -CS */
++      TUL_WR(CurBase + TUL_NVRAM, 0);         /* -CS */
++      return;
+ }
  
--      ret = ocfs2_read_block(osb, oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
--      if (ret < 0) {
--              mlog_errno(ret);
--              goto out_trans;
--      }
--
-       ret = ocfs2_journal_access(handle, inode, bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
-       if (ret < 0) {
-               mlog_errno(ret);
--              goto out_bh;
-+              goto out_trans;
-       }
+-/**
+- *    initio_se2_rd_all       -       read hostadapter NV configuration
+- *    @base: Base address of InitIO controller
+- *
+- *    Reads the E2PROM data into main memory. Ensures that the checksum
+- *    and header marker are valid. Returns 1 on success -1 on error.
+- */
  
-       inode->i_mode &= ~S_ISUID;
-@@ -1114,8 +1139,7 @@
-       ret = ocfs2_journal_dirty(handle, bh);
-       if (ret < 0)
-               mlog_errno(ret);
--out_bh:
--      brelse(bh);
-+
- out_trans:
-       ocfs2_commit_trans(osb, handle);
- out:
-@@ -1161,6 +1185,211 @@
-       return ret;
- }
+-static int initio_se2_rd_all(unsigned long base)
++/***********************************************************************
++ Read SCSI H/A configuration parameters from serial EEPROM
++************************************************************************/
++int tul_se2_rd_all(WORD CurBase)
+ {
+       int i;
+-      u16 chksum = 0;
+-      u16 *np;
++      ULONG chksum = 0;
++      USHORT *np;
  
-+static int ocfs2_write_remove_suid(struct inode *inode)
-+{
-+      int ret;
-+      struct buffer_head *bh = NULL;
-+      struct ocfs2_inode_info *oi = OCFS2_I(inode);
-+
-+      ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
-+                             oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
-+      if (ret < 0) {
-+              mlog_errno(ret);
-+              goto out;
+       i91unvramp = &i91unvram;
+-      np = (u16 *) i91unvramp;
+-      for (i = 0; i < 32; i++)
+-              *np++ = initio_se2_rd(base, i);
++      np = (USHORT *) i91unvramp;
++      for (i = 0; i < 32; i++) {
++              *np++ = tul_se2_rd(CurBase, i);
 +      }
+-      /* Is signature "ini" ok ? */
++/*--------------------Is signature "ini" ok ? ----------------*/
+       if (i91unvramp->NVM_Signature != INI_SIGNATURE)
+               return -1;
+-      /* Is ckecksum ok ? */
+-      np = (u16 *) i91unvramp;
++/*---------------------- Is ckecksum ok ? ----------------------*/
++      np = (USHORT *) i91unvramp;
+       for (i = 0; i < 31; i++)
+               chksum += *np++;
+-      if (i91unvramp->NVM_CheckSum != chksum)
++      if (i91unvramp->NVM_CheckSum != (USHORT) chksum)
+               return -1;
+       return 1;
+ }
+-/**
+- *    initio_se2_update_all           -       Update E2PROM
+- *    @base: Base of InitIO controller
+- *
+- *    Update the E2PROM by wrting any changes into the E2PROM
+- *    chip, rewriting the checksum.
+- */
+-static void initio_se2_update_all(unsigned long base)
 +
-+      ret =  __ocfs2_write_remove_suid(inode, bh);
-+out:
-+      brelse(bh);
-+      return ret;
-+}
-+
-+/*
-+ * Allocate enough extents to cover the region starting at byte offset
-+ * start for len bytes. Existing extents are skipped, any extents
-+ * added are marked as "unwritten".
-+ */
-+static int ocfs2_allocate_unwritten_extents(struct inode *inode,
-+                                          u64 start, u64 len)
-+{
-+      int ret;
-+      u32 cpos, phys_cpos, clusters, alloc_size;
-+
-+      /*
-+       * We consider both start and len to be inclusive.
-+       */
-+      cpos = start >> OCFS2_SB(inode->i_sb)->s_clustersize_bits;
-+      clusters = ocfs2_clusters_for_bytes(inode->i_sb, start + len);
-+      clusters -= cpos;
-+
-+      while (clusters) {
-+              ret = ocfs2_get_clusters(inode, cpos, &phys_cpos,
-+                                       &alloc_size, NULL);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
-+
-+              /*
-+               * Hole or existing extent len can be arbitrary, so
-+               * cap it to our own allocation request.
-+               */
-+              if (alloc_size > clusters)
-+                      alloc_size = clusters;
-+
-+              if (phys_cpos) {
-+                      /*
-+                       * We already have an allocation at this
-+                       * region so we can safely skip it.
-+                       */
-+                      goto next;
-+              }
-+
-+              ret = __ocfs2_extend_allocation(inode, cpos, alloc_size, 1);
-+              if (ret) {
-+                      if (ret != -ENOSPC)
-+                              mlog_errno(ret);
-+                      goto out;
++/***********************************************************************
++ Update SCSI H/A configuration parameters from serial EEPROM
++************************************************************************/
++void tul_se2_update_all(WORD CurBase)
+ {                             /* setup default pattern */
+       int i;
+-      u16 chksum = 0;
+-      u16 *np, *np1;
++      ULONG chksum = 0;
++      USHORT *np, *np1;
+       i91unvramp = &i91unvram;
+       /* Calculate checksum first */
+-      np = (u16 *) i91udftNvRam;
++      np = (USHORT *) i91udftNvRam;
+       for (i = 0; i < 31; i++)
+               chksum += *np++;
+-      *np = chksum;
+-      initio_se2_ew_en(base); /* Enable write  */
++      *np = (USHORT) chksum;
++      tul_se2_ew_en(CurBase); /* Enable write  */
+-      np = (u16 *) i91udftNvRam;
+-      np1 = (u16 *) i91unvramp;
++      np = (USHORT *) i91udftNvRam;
++      np1 = (USHORT *) i91unvramp;
+       for (i = 0; i < 32; i++, np++, np1++) {
+-              if (*np != *np1)
+-                      initio_se2_wr(base, i, *np);
++              if (*np != *np1) {
++                      tul_se2_wr(CurBase, i, *np);
 +              }
-+
-+next:
-+              cpos += alloc_size;
-+              clusters -= alloc_size;
-+      }
-+
-+      ret = 0;
-+out:
-+      return ret;
+       }
+-      initio_se2_ew_ds(base); /* Disable write   */
+-}
+-/**
+- *    initio_read_eeprom              -       Retrieve configuration
+- *    @base: Base of InitIO Host Adapter
+- *
+- *    Retrieve the host adapter configuration data from E2Prom. If the
+- *    data is invalid then the defaults are used and are also restored
+- *    into the E2PROM. This forms the access point for the SCSI driver
+- *    into the E2PROM layer, the other functions for the E2PROM are all
+- *    internal use.
+- *
+- *    Must be called single threaded, uses a shared global area.
+- */
++      tul_se2_ew_ds(CurBase); /* Disable write   */
++      return;
 +}
-+
-+/*
-+ * Parts of this function taken from xfs_change_file_space()
-+ */
-+int ocfs2_change_file_space(struct file *file, unsigned int cmd,
-+                          struct ocfs2_space_resv *sr)
+-static void initio_read_eeprom(unsigned long base)
++/*************************************************************************
++ Function name  : read_eeprom
++**************************************************************************/
++void tul_read_eeprom(WORD CurBase)
+ {
+-      u8 gctrl;
++      UCHAR gctrl;
+       i91unvramp = &i91unvram;
+-      /* Enable EEProm programming */
+-      gctrl = inb(base + TUL_GCTRL);
+-      outb(gctrl | TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);
+-      if (initio_se2_rd_all(base) != 1) {
+-              initio_se2_update_all(base);    /* setup default pattern */
+-              initio_se2_rd_all(base);        /* load again  */
+-      }
+-      /* Disable EEProm programming */
+-      gctrl = inb(base + TUL_GCTRL);
+-      outb(gctrl & ~TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);
++/*------Enable EEProm programming ---*/
++      gctrl = TUL_RD(CurBase, TUL_GCTRL);
++      TUL_WR(CurBase + TUL_GCTRL, gctrl | TUL_GCTRL_EEPROM_BIT);
++      if (tul_se2_rd_all(CurBase) != 1) {
++              tul_se2_update_all(CurBase);    /* setup default pattern */
++              tul_se2_rd_all(CurBase);        /* load again  */
++      }
++/*------ Disable EEProm programming ---*/
++      gctrl = TUL_RD(CurBase, TUL_GCTRL);
++      TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT);
++}                             /* read_eeprom */
++
++static int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
++                                    BYTE bBus, BYTE bDevice)
 +{
-+      int ret;
-+      s64 llen;
-+      struct inode *inode = file->f_path.dentry->d_inode;
-+      struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-+      struct buffer_head *di_bh = NULL;
-+      handle_t *handle;
-+      unsigned long long max_off = ocfs2_max_file_offset(inode->i_sb->s_blocksize_bits);
-+
-+      if (!ocfs2_writes_unwritten_extents(osb))
-+              return -ENOTTY;
-+
-+      if (!S_ISREG(inode->i_mode))
-+              return -EINVAL;
-+
-+      if (!(file->f_mode & FMODE_WRITE))
-+              return -EBADF;
-+
-+      if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
-+              return -EROFS;
-+
-+      mutex_lock(&inode->i_mutex);
-+
-+      /*
-+       * This prevents concurrent writes on other nodes
-+       */
-+      ret = ocfs2_rw_lock(inode, 1);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out;
-+      }
-+
-+      ret = ocfs2_meta_lock(inode, &di_bh, 1);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out_rw_unlock;
-+      }
-+
-+      if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
-+              ret = -EPERM;
-+              goto out_meta_unlock;
-+      }
-+
-+      switch (sr->l_whence) {
-+      case 0: /*SEEK_SET*/
-+              break;
-+      case 1: /*SEEK_CUR*/
-+              sr->l_start += file->f_pos;
-+              break;
-+      case 2: /*SEEK_END*/
-+              sr->l_start += i_size_read(inode);
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              goto out_meta_unlock;
-+      }
-+      sr->l_whence = 0;
-+
-+      llen = sr->l_len > 0 ? sr->l_len - 1 : sr->l_len;
-+
-+      if (sr->l_start < 0
-+          || sr->l_start > max_off
-+          || (sr->l_start + llen) < 0
-+          || (sr->l_start + llen) > max_off) {
-+              ret = -EINVAL;
-+              goto out_meta_unlock;
-+      }
-+
-+      if (cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) {
-+              if (sr->l_len <= 0) {
-+                      ret = -EINVAL;
-+                      goto out_meta_unlock;
-+              }
-+      }
++      int i, j;
 +
-+      if (should_remove_suid(file->f_path.dentry)) {
-+              ret = __ocfs2_write_remove_suid(inode, di_bh);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out_meta_unlock;
++      for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
++              if (i91u_adpt[i].ADPT_BIOS < wBIOS)
++                      continue;
++              if (i91u_adpt[i].ADPT_BIOS == wBIOS) {
++                      if (i91u_adpt[i].ADPT_BASE == wBASE) {
++                              if (i91u_adpt[i].ADPT_Bus != 0xFF)
++                                      return 1;
++                      } else if (i91u_adpt[i].ADPT_BASE < wBASE)
++                                      continue;
 +              }
++              for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
++                      i91u_adpt[j].ADPT_BASE = i91u_adpt[j - 1].ADPT_BASE;
++                      i91u_adpt[j].ADPT_INTR = i91u_adpt[j - 1].ADPT_INTR;
++                      i91u_adpt[j].ADPT_BIOS = i91u_adpt[j - 1].ADPT_BIOS;
++                      i91u_adpt[j].ADPT_Bus = i91u_adpt[j - 1].ADPT_Bus;
++                      i91u_adpt[j].ADPT_Device = i91u_adpt[j - 1].ADPT_Device;
++              }
++              i91u_adpt[i].ADPT_BASE = wBASE;
++              i91u_adpt[i].ADPT_INTR = bInterrupt;
++              i91u_adpt[i].ADPT_BIOS = wBIOS;
++              i91u_adpt[i].ADPT_Bus = bBus;
++              i91u_adpt[i].ADPT_Device = bDevice;
++              return 0;
 +      }
++      return 1;
+ }
+-/**
+- *    initio_stop_bm          -       stop bus master
+- *    @host: InitIO we are stopping
+- *
+- *    Stop any pending DMA operation, aborting the DMA if neccessary
+- */
++static void init_i91uAdapter_table(void)
++{
++      int i;
 +
-+      down_write(&OCFS2_I(inode)->ip_alloc_sem);
-+      /*
-+       * This takes unsigned offsets, but the signed ones we pass
-+       * have been checked against overflow above.
-+       */
-+      ret = ocfs2_allocate_unwritten_extents(inode, sr->l_start, sr->l_len);
-+      up_write(&OCFS2_I(inode)->ip_alloc_sem);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out_meta_unlock;
-+      }
-+
-+      /*
-+       * We update c/mtime for these changes
-+       */
-+      handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
-+      if (IS_ERR(handle)) {
-+              ret = PTR_ERR(handle);
-+              mlog_errno(ret);
-+              goto out_meta_unlock;
++      for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {  /* Initialize adapter structure */
++              i91u_adpt[i].ADPT_BIOS = 0xffff;
++              i91u_adpt[i].ADPT_BASE = 0xffff;
++              i91u_adpt[i].ADPT_INTR = 0xff;
++              i91u_adpt[i].ADPT_Bus = 0xff;
++              i91u_adpt[i].ADPT_Device = 0xff;
 +      }
-+
-+      inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-+      ret = ocfs2_mark_inode_dirty(handle, inode, di_bh);
-+      if (ret < 0)
-+              mlog_errno(ret);
-+
-+      ocfs2_commit_trans(osb, handle);
-+
-+out_meta_unlock:
-+      brelse(di_bh);
-+      ocfs2_meta_unlock(inode, 1);
-+out_rw_unlock:
-+      ocfs2_rw_unlock(inode, 1);
-+
-+      mutex_unlock(&inode->i_mutex);
-+out:
-+      return ret;
++      return;
 +}
-+
- static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
-                                        loff_t *ppos,
-                                        size_t count,
-@@ -1331,15 +1560,16 @@
-       *basep = base;
+-static void initio_stop_bm(struct initio_host * host)
++static void tul_stop_bm(HCS * pCurHcb)
+ {
+-      if (inb(host->addr + TUL_XStatus) & XPEND) {    /* if DMA xfer is pending, abort DMA xfer */
+-              outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);
++      if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {   /* if DMA xfer is pending, abort DMA xfer */
++              TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
+               /* wait Abort DMA xfer done */
+-              while ((inb(host->addr + TUL_Int) & XABT) == 0)
+-                      cpu_relax();
++              while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
+       }
+-      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
  }
  
--static struct page * ocfs2_get_write_source(struct ocfs2_buffered_write_priv *bp,
-+static struct page * ocfs2_get_write_source(char **ret_src_buf,
-                                           const struct iovec *cur_iov,
-                                           size_t iov_offset)
+-/**
+- *    initio_reset_scsi               -       Reset SCSI host controller
+- *    @host: InitIO host to reset
+- *    @seconds: Recovery time
+- *
+- *    Perform a full reset of the SCSI subsystem.
+- */
+-
+-static int initio_reset_scsi(struct initio_host * host, int seconds)
++/***************************************************************************/
++static void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
  {
-       int ret;
--      char *buf;
-+      char *buf = cur_iov->iov_base + iov_offset;
-       struct page *src_page = NULL;
-+      unsigned long off;
+-      outb(TSC_RST_BUS, host->addr + TUL_SCtrl0);
++      pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE;        /* Supply base address  */
++      pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS;        /* Supply BIOS address  */
++      pCurHcb->HCS_Intr = i91u_adpt[ch_idx].ADPT_INTR;        /* Supply interrupt line */
++      return;
++}
+-      while (!((host->jsint = inb(host->addr + TUL_SInt)) & TSS_SCSIRST_INT))
+-              cpu_relax();
++/***************************************************************************/
++static int tul_reset_scsi(HCS * pCurHcb, int seconds)
++{
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS);
  
--      buf = cur_iov->iov_base + iov_offset;
-+      off = (unsigned long)(buf) & ~PAGE_CACHE_MASK;
++      while (!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt)) & TSS_SCSIRST_INT));
+       /* reset tulip chip */
+-      outb(0, host->addr + TUL_SSignal);
++
++      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0);
  
-       if (!segment_eq(get_fs(), KERNEL_DS)) {
-               /*
-@@ -1378,10 +1608,12 @@
+       /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
+       /* SONY 5200 tape drive won't work if only stall for 1 sec */
+-      /* FIXME: this is a very long busy wait right now */
+-      initio_do_pause(seconds * HZ);
++      tul_do_pause(seconds * HZ);
+-      inb(host->addr + TUL_SInt);
+-      return SCSI_RESET_SUCCESS;
+-}
++      TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
+-/**
+- *    initio_init             -       set up an InitIO host adapter
+- *    @host: InitIO host adapter
+- *    @num_scbs: Number of SCBS
+- *    @bios_addr: BIOS address
+- *
+- *    Set up the host adapter and devices according to the configuration
+- *    retrieved from the E2PROM.
+- *
+- *    Locking: Calls E2PROM layer code which is not re-enterable so must
+- *    run single threaded for now.
+- */
++      return (SCSI_RESET_SUCCESS);
++}
+-static void initio_init(struct initio_host * host, u8 *bios_addr)
++/***************************************************************************/
++static int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb,
++                    BYTE * pbBiosAdr, int seconds)
  {
-       int ret = 0;
-       ssize_t copied, total = 0;
--      size_t iov_offset = 0;
-+      size_t iov_offset = 0, bytes;
-+      loff_t pos;
-       const struct iovec *cur_iov = iov;
--      struct ocfs2_buffered_write_priv bp;
--      struct page *page;
-+      struct page *user_page, *page;
-+      char *buf, *dst;
-+      void *fsdata;
+       int i;
+-      u8 *flags;
+-      u8 *heads;
++      BYTE *pwFlags;
++      BYTE *pbHeads;
++      SCB *pTmpScb, *pPrevScb = NULL;
++
++      pCurHcb->HCS_NumScbs = tul_num_scb;
++      pCurHcb->HCS_Semaph = 1;
++      spin_lock_init(&pCurHcb->HCS_SemaphLock);
++      pCurHcb->HCS_JSStatus0 = 0;
++      pCurHcb->HCS_Scb = scbp;
++      pCurHcb->HCS_NxtPend = scbp;
++      pCurHcb->HCS_NxtAvail = scbp;
++      for (i = 0, pTmpScb = scbp; i < tul_num_scb; i++, pTmpScb++) {
++              pTmpScb->SCB_TagId = i;
++              if (i != 0)
++                      pPrevScb->SCB_NxtScb = pTmpScb;
++              pPrevScb = pTmpScb;
++      }
++      pPrevScb->SCB_NxtScb = NULL;
++      pCurHcb->HCS_ScbEnd = pTmpScb;
++      pCurHcb->HCS_FirstAvail = scbp;
++      pCurHcb->HCS_LastAvail = pPrevScb;
++      spin_lock_init(&pCurHcb->HCS_AvailLock);
++      pCurHcb->HCS_FirstPend = NULL;
++      pCurHcb->HCS_LastPend = NULL;
++      pCurHcb->HCS_FirstBusy = NULL;
++      pCurHcb->HCS_LastBusy = NULL;
++      pCurHcb->HCS_FirstDone = NULL;
++      pCurHcb->HCS_LastDone = NULL;
++      pCurHcb->HCS_ActScb = NULL;
++      pCurHcb->HCS_ActTcs = NULL;
+-      /* Get E2Prom configuration */
+-      initio_read_eeprom(host->addr);
++      tul_read_eeprom(pCurHcb->HCS_Base);
++/*---------- get H/A configuration -------------*/
+       if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8)
+-              host->max_tar = 8;
++              pCurHcb->HCS_MaxTar = 8;
+       else
+-              host->max_tar = 16;
++              pCurHcb->HCS_MaxTar = 16;
  
-       /*
-        * handle partial DIO write.  Adjust cur_iov if needed.
-@@ -1389,21 +1621,38 @@
-       ocfs2_set_next_iovec(&cur_iov, &iov_offset, o_direct_written);
+-      host->config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
++      pCurHcb->HCS_Config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
  
-       do {
--              bp.b_cur_off = iov_offset;
--              bp.b_cur_iov = cur_iov;
-+              pos = *ppos;
+-      host->scsi_id = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
+-      host->idmask = ~(1 << host->scsi_id);
++      pCurHcb->HCS_SCSI_ID = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
++      pCurHcb->HCS_IdMask = ~(1 << pCurHcb->HCS_SCSI_ID);
  
--              page = ocfs2_get_write_source(&bp, cur_iov, iov_offset);
--              if (IS_ERR(page)) {
--                      ret = PTR_ERR(page);
-+              user_page = ocfs2_get_write_source(&buf, cur_iov, iov_offset);
-+              if (IS_ERR(user_page)) {
-+                      ret = PTR_ERR(user_page);
-                       goto out;
-               }
+ #ifdef CHK_PARITY
+       /* Enable parity error response */
+-      outb(inb(host->addr + TUL_PCMD) | 0x40, host->addr + TUL_PCMD);
++      TUL_WR(pCurHcb->HCS_Base + TUL_PCMD, TUL_RD(pCurHcb->HCS_Base, TUL_PCMD) | 0x40);
+ #endif
  
--              copied = ocfs2_buffered_write_cluster(file, *ppos, count,
--                                                    ocfs2_map_and_write_user_data,
--                                                    &bp);
-+              /* Stay within our page boundaries */
-+              bytes = min((PAGE_CACHE_SIZE - ((unsigned long)pos & ~PAGE_CACHE_MASK)),
-+                          (PAGE_CACHE_SIZE - ((unsigned long)buf & ~PAGE_CACHE_MASK)));
-+              /* Stay within the vector boundary */
-+              bytes = min_t(size_t, bytes, cur_iov->iov_len - iov_offset);
-+              /* Stay within count */
-+              bytes = min(bytes, count);
-+
-+              page = NULL;
-+              ret = ocfs2_write_begin(file, file->f_mapping, pos, bytes, 0,
-+                                      &page, &fsdata);
-+              if (ret) {
-+                      mlog_errno(ret);
-+                      goto out;
-+              }
+       /* Mask all the interrupt       */
+-      outb(0x1F, host->addr + TUL_Mask);
++      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
  
--              ocfs2_put_write_source(&bp, page);
-+              dst = kmap_atomic(page, KM_USER0);
-+              memcpy(dst + (pos & (PAGE_CACHE_SIZE - 1)), buf, bytes);
-+              kunmap_atomic(dst, KM_USER0);
-+              flush_dcache_page(page);
-+              ocfs2_put_write_source(user_page);
+-      initio_stop_bm(host);
++      tul_stop_bm(pCurHcb);
+       /* --- Initialize the tulip --- */
+-      outb(TSC_RST_CHIP, host->addr + TUL_SCtrl0);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_CHIP);
  
-+              copied = ocfs2_write_end(file, file->f_mapping, pos, bytes,
-+                                       bytes, page, fsdata);
-               if (copied < 0) {
-                       mlog_errno(copied);
-                       ret = copied;
-@@ -1411,7 +1660,7 @@
-               }
+       /* program HBA's SCSI ID        */
+-      outb(host->scsi_id << 4, host->addr + TUL_SScsiId);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, pCurHcb->HCS_SCSI_ID << 4);
  
-               total += copied;
--              *ppos = *ppos + copied;
-+              *ppos = pos + copied;
-               count -= copied;
+       /* Enable Initiator Mode ,phase latch,alternate sync period mode,
+          disable SCSI reset */
+-      if (host->config & HCC_EN_PAR)
+-              host->sconf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
++      if (pCurHcb->HCS_Config & HCC_EN_PAR)
++              pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
+       else
+-              host->sconf1 = (TSC_INITDEFAULT);
+-      outb(host->sconf1, host->addr + TUL_SConfig);
++              pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_SConf1);
  
-               ocfs2_set_next_iovec(&cur_iov, &iov_offset, copied);
-@@ -1581,52 +1830,46 @@
-                                   struct pipe_buffer *buf,
-                                   struct splice_desc *sd)
- {
--      int ret, count, total = 0;
-+      int ret, count;
-       ssize_t copied = 0;
--      struct ocfs2_splice_write_priv sp;
-+      struct file *file = sd->file;
-+      unsigned int offset;
-+      struct page *page = NULL;
-+      void *fsdata;
-+      char *src, *dst;
+       /* Enable HW reselect           */
+-      outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
  
-       ret = buf->ops->pin(pipe, buf);
-       if (ret)
-               goto out;
+-      outb(0, host->addr + TUL_SPeriod);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, 0);
  
--      sp.s_sd = sd;
--      sp.s_buf = buf;
--      sp.s_pipe = pipe;
--      sp.s_offset = sd->pos & ~PAGE_CACHE_MASK;
--      sp.s_buf_offset = buf->offset;
--
-+      offset = sd->pos & ~PAGE_CACHE_MASK;
-       count = sd->len;
--      if (count + sp.s_offset > PAGE_CACHE_SIZE)
--              count = PAGE_CACHE_SIZE - sp.s_offset;
-+      if (count + offset > PAGE_CACHE_SIZE)
-+              count = PAGE_CACHE_SIZE - offset;
+       /* selection time out = 250 ms */
+-      outb(153, host->addr + TUL_STimeOut);
++      TUL_WR(pCurHcb->HCS_Base + TUL_STimeOut, 153);
+-      /* Enable SCSI terminator */
+-      outb((host->config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)),
+-              host->addr + TUL_XCtrl);
+-      outb(((host->config & HCC_AUTO_TERM) >> 4) |
+-              (inb(host->addr + TUL_GCTRL1) & 0xFE),
+-              host->addr + TUL_GCTRL1);
++/*--------- Enable SCSI terminator -----*/
++      TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, (pCurHcb->HCS_Config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)));
++      TUL_WR(pCurHcb->HCS_Base + TUL_GCTRL1,
++             ((pCurHcb->HCS_Config & HCC_AUTO_TERM) >> 4) | (TUL_RD(pCurHcb->HCS_Base, TUL_GCTRL1) & 0xFE));
  
--      do {
--              /*
--               * splice wants us to copy up to one page at a
--               * time. For pagesize > cluster size, this means we
--               * might enter ocfs2_buffered_write_cluster() more
--               * than once, so keep track of our progress here.
--               */
--              copied = ocfs2_buffered_write_cluster(sd->file,
--                                                    (loff_t)sd->pos + total,
--                                                    count,
--                                                    ocfs2_map_and_write_splice_data,
--                                                    &sp);
-+      ret = ocfs2_write_begin(file, file->f_mapping, sd->pos, count, 0,
-+                              &page, &fsdata);
-+      if (ret) {
-+              mlog_errno(ret);
-+              goto out;
-+      }
-+
-+      src = buf->ops->map(pipe, buf, 1);
-+      dst = kmap_atomic(page, KM_USER1);
-+      memcpy(dst + offset, src + buf->offset, count);
-+      kunmap_atomic(page, KM_USER1);
-+      buf->ops->unmap(pipe, buf, src);
-+
-+      copied = ocfs2_write_end(file, file->f_mapping, sd->pos, count, count,
-+                               page, fsdata);
-               if (copied < 0) {
-                       mlog_errno(copied);
-                       ret = copied;
-                       goto out;
-               }
+       for (i = 0,
+-           flags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
+-           heads = bios_addr + 0x180;
+-           i < host->max_tar;
+-           i++, flags++) {
+-              host->targets[i].flags = *flags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+-              if (host->targets[i].flags & TCF_EN_255)
+-                      host->targets[i].drv_flags = TCF_DRV_255_63;
++           pwFlags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
++           pbHeads = pbBiosAdr + 0x180;
++           i < pCurHcb->HCS_MaxTar;
++           i++, pwFlags++) {
++              pCurHcb->HCS_Tcs[i].TCS_Flags = *pwFlags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
++              if (pCurHcb->HCS_Tcs[i].TCS_Flags & TCF_EN_255)
++                      pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
+               else
+-                      host->targets[i].drv_flags = 0;
+-              host->targets[i].js_period = 0;
+-              host->targets[i].sconfig0 = host->sconf1;
+-              host->targets[i].heads = *heads++;
+-              if (host->targets[i].heads == 255)
+-                      host->targets[i].drv_flags = TCF_DRV_255_63;
++                      pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
++              pCurHcb->HCS_Tcs[i].TCS_JS_Period = 0;
++              pCurHcb->HCS_Tcs[i].TCS_SConfig0 = pCurHcb->HCS_SConf1;
++              pCurHcb->HCS_Tcs[i].TCS_DrvHead = *pbHeads++;
++              if (pCurHcb->HCS_Tcs[i].TCS_DrvHead == 255)
++                      pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
+               else
+-                      host->targets[i].drv_flags = 0;
+-              host->targets[i].sectors = *heads++;
+-              host->targets[i].flags &= ~TCF_BUSY;
+-              host->act_tags[i] = 0;
+-              host->max_tags[i] = 0xFF;
++                      pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
++              pCurHcb->HCS_Tcs[i].TCS_DrvSector = *pbHeads++;
++              pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;
++              pCurHcb->HCS_ActTags[i] = 0;
++              pCurHcb->HCS_MaxTags[i] = 0xFF;
+       }                       /* for                          */
+       printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
+-             host->addr, host->irq,
+-             host->bios_addr, host->scsi_id);
+-      /* Reset SCSI Bus */
+-      if (host->config & HCC_SCSI_RESET) {
+-              printk(KERN_INFO "i91u: Reset SCSI Bus ... \n");
+-              initio_reset_scsi(host, 10);
+-      }
+-      outb(0x17, host->addr + TUL_SCFG1);
+-      outb(0xE9, host->addr + TUL_SIntEnable);
++             pCurHcb->HCS_Base, pCurHcb->HCS_Intr,
++             pCurHcb->HCS_BIOS, pCurHcb->HCS_SCSI_ID);
++/*------------------- reset SCSI Bus ---------------------------*/
++      if (pCurHcb->HCS_Config & HCC_SCSI_RESET) {
++              printk("i91u: Reset SCSI Bus ... \n");
++              tul_reset_scsi(pCurHcb, seconds);
++      }
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCFG1, 0x17);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SIntEnable, 0xE9);
++      return (0);
+ }
+-/**
+- *    initio_alloc_scb                -       Allocate an SCB
+- *    @host: InitIO host we are allocating for
+- *
+- *    Walk the SCB list for the controller and allocate a free SCB if
+- *    one exists.
+- */
+-static struct scsi_ctrl_blk *initio_alloc_scb(struct initio_host *host)
++/***************************************************************************/
++static SCB *tul_alloc_scb(HCS * hcsp)
+ {
+-      struct scsi_ctrl_blk *scb;
+-      unsigned long flags;
 -
--              count -= copied;
--              sp.s_offset += copied;
--              sp.s_buf_offset += copied;
--              total += copied;
--      } while (count);
+-      spin_lock_irqsave(&host->avail_lock, flags);
+-      if ((scb = host->first_avail) != NULL) {
++      SCB *pTmpScb;
++      ULONG flags;
++      spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
++      if ((pTmpScb = hcsp->HCS_FirstAvail) != NULL) {
+ #if DEBUG_QUEUE
+-              printk("find scb at %p\n", scb);
++              printk("find scb at %08lx\n", (ULONG) pTmpScb);
+ #endif
+-              if ((host->first_avail = scb->next) == NULL)
+-                      host->last_avail = NULL;
+-              scb->next = NULL;
+-              scb->status = SCB_RENT;
++              if ((hcsp->HCS_FirstAvail = pTmpScb->SCB_NxtScb) == NULL)
++                      hcsp->HCS_LastAvail = NULL;
++              pTmpScb->SCB_NxtScb = NULL;
++              pTmpScb->SCB_Status = SCB_RENT;
+       }
+-      spin_unlock_irqrestore(&host->avail_lock, flags);
+-      return scb;
++      spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
++      return (pTmpScb);
+ }
+-/**
+- *    initio_release_scb              -       Release an SCB
+- *    @host: InitIO host that owns the SCB
+- *    @cmnd: SCB command block being returned
+- *
+- *    Return an allocated SCB to the host free list
+- */
 -
--      ret = 0;
- out:
+-static void initio_release_scb(struct initio_host * host, struct scsi_ctrl_blk * cmnd)
++/***************************************************************************/
++static void tul_release_scb(HCS * hcsp, SCB * scbp)
+ {
+-      unsigned long flags;
++      ULONG flags;
  
--      return total ? total : ret;
-+      return copied ? copied : ret;
+ #if DEBUG_QUEUE
+-      printk("Release SCB %p; ", cmnd);
++      printk("Release SCB %lx; ", (ULONG) scbp);
+ #endif
+-      spin_lock_irqsave(&(host->avail_lock), flags);
+-      cmnd->srb = NULL;
+-      cmnd->status = 0;
+-      cmnd->next = NULL;
+-      if (host->last_avail != NULL) {
+-              host->last_avail->next = cmnd;
+-              host->last_avail = cmnd;
++      spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
++      scbp->SCB_Srb = NULL;
++      scbp->SCB_Status = 0;
++      scbp->SCB_NxtScb = NULL;
++      if (hcsp->HCS_LastAvail != NULL) {
++              hcsp->HCS_LastAvail->SCB_NxtScb = scbp;
++              hcsp->HCS_LastAvail = scbp;
+       } else {
+-              host->first_avail = cmnd;
+-              host->last_avail = cmnd;
++              hcsp->HCS_FirstAvail = scbp;
++              hcsp->HCS_LastAvail = scbp;
+       }
+-      spin_unlock_irqrestore(&(host->avail_lock), flags);
++      spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
  }
  
- static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe,
-diff -Nurb linux-2.6.22-570/fs/ocfs2/file.h linux-2.6.22-590/fs/ocfs2/file.h
---- linux-2.6.22-570/fs/ocfs2/file.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/file.h   2008-01-02 13:56:37.000000000 -0500
-@@ -39,15 +39,16 @@
- };
- int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
-                              struct inode *inode,
--                             u32 *cluster_start,
-+                             u32 *logical_offset,
-                              u32 clusters_to_add,
-+                             int mark_unwritten,
-                              struct buffer_head *fe_bh,
-                              handle_t *handle,
-                              struct ocfs2_alloc_context *data_ac,
-                              struct ocfs2_alloc_context *meta_ac,
--                             enum ocfs2_alloc_restarted *reason);
-+                             enum ocfs2_alloc_restarted *reason_ret);
- int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
--                        u32 clusters_to_add,
-+                        u32 clusters_to_add, u32 extents_to_split,
-                         struct ocfs2_alloc_context **data_ac,
-                         struct ocfs2_alloc_context **meta_ac);
- int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
-@@ -61,4 +62,7 @@
- int ocfs2_update_inode_atime(struct inode *inode,
-                            struct buffer_head *bh);
+ /***************************************************************************/
+-static void initio_append_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
++static void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
+ {
+ #if DEBUG_QUEUE
+-      printk("Append pend SCB %p; ", scbp);
++      printk("Append pend SCB %lx; ", (ULONG) scbp);
+ #endif
+-      scbp->status = SCB_PEND;
+-      scbp->next = NULL;
+-      if (host->last_pending != NULL) {
+-              host->last_pending->next = scbp;
+-              host->last_pending = scbp;
++      scbp->SCB_Status = SCB_PEND;
++      scbp->SCB_NxtScb = NULL;
++      if (pCurHcb->HCS_LastPend != NULL) {
++              pCurHcb->HCS_LastPend->SCB_NxtScb = scbp;
++              pCurHcb->HCS_LastPend = scbp;
+       } else {
+-              host->first_pending = scbp;
+-              host->last_pending = scbp;
++              pCurHcb->HCS_FirstPend = scbp;
++              pCurHcb->HCS_LastPend = scbp;
+       }
+ }
+ /***************************************************************************/
+-static void initio_push_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
++static void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
+ {
+ #if DEBUG_QUEUE
+-      printk("Push pend SCB %p; ", scbp);
++      printk("Push pend SCB %lx; ", (ULONG) scbp);
+ #endif
+-      scbp->status = SCB_PEND;
+-      if ((scbp->next = host->first_pending) != NULL) {
+-              host->first_pending = scbp;
++      scbp->SCB_Status = SCB_PEND;
++      if ((scbp->SCB_NxtScb = pCurHcb->HCS_FirstPend) != NULL) {
++              pCurHcb->HCS_FirstPend = scbp;
+       } else {
+-              host->first_pending = scbp;
+-              host->last_pending = scbp;
++              pCurHcb->HCS_FirstPend = scbp;
++              pCurHcb->HCS_LastPend = scbp;
+       }
+ }
+-static struct scsi_ctrl_blk *initio_find_first_pend_scb(struct initio_host * host)
++/***************************************************************************/
++static SCB *tul_find_first_pend_scb(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *first;
++      SCB *pFirstPend;
+-      first = host->first_pending;
+-      while (first != NULL) {
+-              if (first->opcode != ExecSCSI)
+-                      return first;
+-              if (first->tagmsg == 0) {
+-                      if ((host->act_tags[first->target] == 0) &&
+-                          !(host->targets[first->target].flags & TCF_BUSY))
+-                              return first;
++      pFirstPend = pCurHcb->HCS_FirstPend;
++      while (pFirstPend != NULL) {
++              if (pFirstPend->SCB_Opcode != ExecSCSI) {
++                      return (pFirstPend);
++              }
++              if (pFirstPend->SCB_TagMsg == 0) {
++                      if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] == 0) &&
++                          !(pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
++                              return (pFirstPend);
++                      }
+               } else {
+-                      if ((host->act_tags[first->target] >=
+-                        host->max_tags[first->target]) |
+-                          (host->targets[first->target].flags & TCF_BUSY)) {
+-                              first = first->next;
++                      if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] >=
++                        pCurHcb->HCS_MaxTags[pFirstPend->SCB_Target]) |
++                          (pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
++                              pFirstPend = pFirstPend->SCB_NxtScb;
+                               continue;
+                       }
+-                      return first;
++                      return (pFirstPend);
+               }
+-              first = first->next;
++              pFirstPend = pFirstPend->SCB_NxtScb;
+       }
+-      return first;
+-}
  
-+int ocfs2_change_file_space(struct file *file, unsigned int cmd,
-+                          struct ocfs2_space_resv *sr);
+-static void initio_unlink_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
 +
- #endif /* OCFS2_FILE_H */
-diff -Nurb linux-2.6.22-570/fs/ocfs2/heartbeat.c linux-2.6.22-590/fs/ocfs2/heartbeat.c
---- linux-2.6.22-570/fs/ocfs2/heartbeat.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/heartbeat.c      2008-01-02 13:56:37.000000000 -0500
-@@ -157,16 +157,16 @@
-       if (ocfs2_mount_local(osb))
-               return 0;
++      return (pFirstPend);
++}
++/***************************************************************************/
++static void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
+ {
+-      struct scsi_ctrl_blk *tmp, *prev;
++      SCB *pTmpScb, *pPrevScb;
  
--      status = o2hb_register_callback(&osb->osb_hb_down);
-+      status = o2hb_register_callback(osb->uuid_str, &osb->osb_hb_down);
-       if (status < 0) {
-               mlog_errno(status);
-               goto bail;
+ #if DEBUG_QUEUE
+-      printk("unlink pend SCB %p; ", scb);
++      printk("unlink pend SCB %lx; ", (ULONG) pCurScb);
+ #endif
+-      prev = tmp = host->first_pending;
+-      while (tmp != NULL) {
+-              if (scb == tmp) {       /* Unlink this SCB              */
+-                      if (tmp == host->first_pending) {
+-                              if ((host->first_pending = tmp->next) == NULL)
+-                                      host->last_pending = NULL;
++      pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;
++      while (pTmpScb != NULL) {
++              if (pCurScb == pTmpScb) {       /* Unlink this SCB              */
++                      if (pTmpScb == pCurHcb->HCS_FirstPend) {
++                              if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
++                                      pCurHcb->HCS_LastPend = NULL;
+                       } else {
+-                              prev->next = tmp->next;
+-                              if (tmp == host->last_pending)
+-                                      host->last_pending = prev;
++                              pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
++                              if (pTmpScb == pCurHcb->HCS_LastPend)
++                                      pCurHcb->HCS_LastPend = pPrevScb;
+                       }
+-                      tmp->next = NULL;
++                      pTmpScb->SCB_NxtScb = NULL;
+                       break;
+               }
+-              prev = tmp;
+-              tmp = tmp->next;
++              pPrevScb = pTmpScb;
++              pTmpScb = pTmpScb->SCB_NxtScb;
        }
++      return;
+ }
+-
+-static void initio_append_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
++/***************************************************************************/
++static void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
+ {
  
--      status = o2hb_register_callback(&osb->osb_hb_up);
-+      status = o2hb_register_callback(osb->uuid_str, &osb->osb_hb_up);
-       if (status < 0) {
-               mlog_errno(status);
--              o2hb_unregister_callback(&osb->osb_hb_down);
-+              o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_down);
+ #if DEBUG_QUEUE
+-      printk("append busy SCB %o; ", scbp);
++      printk("append busy SCB %lx; ", (ULONG) scbp);
+ #endif
+-      if (scbp->tagmsg)
+-              host->act_tags[scbp->target]++;
++      if (scbp->SCB_TagMsg)
++              pCurHcb->HCS_ActTags[scbp->SCB_Target]++;
+       else
+-              host->targets[scbp->target].flags |= TCF_BUSY;
+-      scbp->status = SCB_BUSY;
+-      scbp->next = NULL;
+-      if (host->last_busy != NULL) {
+-              host->last_busy->next = scbp;
+-              host->last_busy = scbp;
++              pCurHcb->HCS_Tcs[scbp->SCB_Target].TCS_Flags |= TCF_BUSY;
++      scbp->SCB_Status = SCB_BUSY;
++      scbp->SCB_NxtScb = NULL;
++      if (pCurHcb->HCS_LastBusy != NULL) {
++              pCurHcb->HCS_LastBusy->SCB_NxtScb = scbp;
++              pCurHcb->HCS_LastBusy = scbp;
+       } else {
+-              host->first_busy = scbp;
+-              host->last_busy = scbp;
++              pCurHcb->HCS_FirstBusy = scbp;
++              pCurHcb->HCS_LastBusy = scbp;
        }
+ }
  
- bail:
-@@ -178,8 +178,8 @@
-       if (ocfs2_mount_local(osb))
-               return;
+ /***************************************************************************/
+-static struct scsi_ctrl_blk *initio_pop_busy_scb(struct initio_host * host)
++static SCB *tul_pop_busy_scb(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *tmp;
++      SCB *pTmpScb;
+-      if ((tmp = host->first_busy) != NULL) {
+-              if ((host->first_busy = tmp->next) == NULL)
+-                      host->last_busy = NULL;
+-              tmp->next = NULL;
+-              if (tmp->tagmsg)
+-                      host->act_tags[tmp->target]--;
++      if ((pTmpScb = pCurHcb->HCS_FirstBusy) != NULL) {
++              if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
++                      pCurHcb->HCS_LastBusy = NULL;
++              pTmpScb->SCB_NxtScb = NULL;
++              if (pTmpScb->SCB_TagMsg)
++                      pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
+               else
+-                      host->targets[tmp->target].flags &= ~TCF_BUSY;
++                      pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
+       }
+ #if DEBUG_QUEUE
+-      printk("Pop busy SCB %p; ", tmp);
++      printk("Pop busy SCB %lx; ", (ULONG) pTmpScb);
+ #endif
+-      return tmp;
++      return (pTmpScb);
+ }
+ /***************************************************************************/
+-static void initio_unlink_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
++static void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb)
+ {
+-      struct scsi_ctrl_blk *tmp, *prev;
++      SCB *pTmpScb, *pPrevScb;
+ #if DEBUG_QUEUE
+-      printk("unlink busy SCB %p; ", scb);
++      printk("unlink busy SCB %lx; ", (ULONG) pCurScb);
+ #endif
+-      prev = tmp = host->first_busy;
+-      while (tmp != NULL) {
+-              if (scb == tmp) {       /* Unlink this SCB              */
+-                      if (tmp == host->first_busy) {
+-                              if ((host->first_busy = tmp->next) == NULL)
+-                                      host->last_busy = NULL;
+-                      } else {
+-                              prev->next = tmp->next;
+-                              if (tmp == host->last_busy)
+-                                      host->last_busy = prev;
+-                      }
+-                      tmp->next = NULL;
+-                      if (tmp->tagmsg)
+-                              host->act_tags[tmp->target]--;
++      pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
++      while (pTmpScb != NULL) {
++              if (pCurScb == pTmpScb) {       /* Unlink this SCB              */
++                      if (pTmpScb == pCurHcb->HCS_FirstBusy) {
++                              if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
++                                      pCurHcb->HCS_LastBusy = NULL;
++                      } else {
++                              pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
++                              if (pTmpScb == pCurHcb->HCS_LastBusy)
++                                      pCurHcb->HCS_LastBusy = pPrevScb;
++                      }
++                      pTmpScb->SCB_NxtScb = NULL;
++                      if (pTmpScb->SCB_TagMsg)
++                              pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
+                       else
+-                              host->targets[tmp->target].flags &= ~TCF_BUSY;
++                              pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
+                       break;
+               }
+-              prev = tmp;
+-              tmp = tmp->next;
++              pPrevScb = pTmpScb;
++              pTmpScb = pTmpScb->SCB_NxtScb;
+       }
+       return;
+ }
+-struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun)
++/***************************************************************************/
++SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun)
+ {
+-      struct scsi_ctrl_blk *tmp, *prev;
+-      u16 scbp_tarlun;
++      SCB *pTmpScb, *pPrevScb;
++      WORD scbp_tarlun;
  
--      o2hb_unregister_callback(&osb->osb_hb_down);
--      o2hb_unregister_callback(&osb->osb_hb_up);
-+      o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_down);
-+      o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_up);
+-      prev = tmp = host->first_busy;
+-      while (tmp != NULL) {
+-              scbp_tarlun = (tmp->lun << 8) | (tmp->target);
++      pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
++      while (pTmpScb != NULL) {
++              scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target);
+               if (scbp_tarlun == tarlun) {    /* Unlink this SCB              */
+                       break;
+               }
+-              prev = tmp;
+-              tmp = tmp->next;
++              pPrevScb = pTmpScb;
++              pTmpScb = pTmpScb->SCB_NxtScb;
+       }
+ #if DEBUG_QUEUE
+-      printk("find busy SCB %p; ", tmp);
++      printk("find busy SCB %lx; ", (ULONG) pTmpScb);
+ #endif
+-      return tmp;
++      return (pTmpScb);
  }
  
- void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
-@@ -209,7 +209,7 @@
-       envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-       envp[2] = NULL;
+-static void initio_append_done_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)
++/***************************************************************************/
++static void tul_append_done_scb(HCS * pCurHcb, SCB * scbp)
+ {
++
+ #if DEBUG_QUEUE
+-      printk("append done SCB %p; ", scbp);
++      printk("append done SCB %lx; ", (ULONG) scbp);
+ #endif
+-      scbp->status = SCB_DONE;
+-      scbp->next = NULL;
+-      if (host->last_done != NULL) {
+-              host->last_done->next = scbp;
+-              host->last_done = scbp;
++      scbp->SCB_Status = SCB_DONE;
++      scbp->SCB_NxtScb = NULL;
++      if (pCurHcb->HCS_LastDone != NULL) {
++              pCurHcb->HCS_LastDone->SCB_NxtScb = scbp;
++              pCurHcb->HCS_LastDone = scbp;
+       } else {
+-              host->first_done = scbp;
+-              host->last_done = scbp;
++              pCurHcb->HCS_FirstDone = scbp;
++              pCurHcb->HCS_LastDone = scbp;
+       }
+ }
  
--      ret = call_usermodehelper(argv[0], argv, envp, 1);
-+      ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
-       if (ret < 0)
-               mlog_errno(ret);
+-struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host)
++/***************************************************************************/
++SCB *tul_find_done_scb(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *tmp;
++      SCB *pTmpScb;
++
+-      if ((tmp = host->first_done) != NULL) {
+-              if ((host->first_done = tmp->next) == NULL)
+-                      host->last_done = NULL;
+-              tmp->next = NULL;
++      if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) {
++              if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL)
++                      pCurHcb->HCS_LastDone = NULL;
++              pTmpScb->SCB_NxtScb = NULL;
+       }
+ #if DEBUG_QUEUE
+-      printk("find done SCB %p; ",tmp);
++      printk("find done SCB %lx; ", (ULONG) pTmpScb);
+ #endif
+-      return tmp;
++      return (pTmpScb);
  }
-diff -Nurb linux-2.6.22-570/fs/ocfs2/ioctl.c linux-2.6.22-590/fs/ocfs2/ioctl.c
---- linux-2.6.22-570/fs/ocfs2/ioctl.c  2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/ocfs2/ioctl.c  2008-01-02 13:56:37.000000000 -0500
-@@ -14,6 +14,7 @@
- #include "ocfs2.h"
- #include "alloc.h"
- #include "dlmglue.h"
-+#include "file.h"
- #include "inode.h"
- #include "journal.h"
  
-@@ -115,6 +116,7 @@
+-static int initio_abort_srb(struct initio_host * host, struct scsi_cmnd *srbp)
++/***************************************************************************/
++static int tul_abort_srb(HCS * pCurHcb, struct scsi_cmnd *srbp)
  {
-       unsigned int flags;
-       int status;
-+      struct ocfs2_space_resv sr;
+-      unsigned long flags;
+-      struct scsi_ctrl_blk *tmp, *prev;
++      ULONG flags;
++      SCB *pTmpScb, *pPrevScb;
  
-       switch (cmd) {
-       case OCFS2_IOC_GETFLAGS:
-@@ -130,6 +132,12 @@
+-      spin_lock_irqsave(&host->semaph_lock, flags);
++      spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
  
-               return ocfs2_set_inode_attr(inode, flags,
-                       OCFS2_FL_MODIFIABLE);
-+      case OCFS2_IOC_RESVSP:
-+      case OCFS2_IOC_RESVSP64:
-+              if (copy_from_user(&sr, (int __user *) arg, sizeof(sr)))
-+                      return -EFAULT;
+-      if ((host->semaph == 0) && (host->active == NULL)) {
++      if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
++              TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+               /* disable Jasmin SCSI Int        */
+-              outb(0x1F, host->addr + TUL_Mask);
+-              spin_unlock_irqrestore(&host->semaph_lock, flags);
+-              /* FIXME: synchronize_irq needed ? */
+-              tulip_main(host);
+-              spin_lock_irqsave(&host->semaph_lock, flags);
+-              host->semaph = 1;
+-              outb(0x0F, host->addr + TUL_Mask);
+-              spin_unlock_irqrestore(&host->semaph_lock, flags);
 +
-+              return ocfs2_change_file_space(filp, cmd, &sr);
-       default:
-               return -ENOTTY;
++                spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
++
++              tulip_main(pCurHcb);
++
++              spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
++
++              pCurHcb->HCS_Semaph = 1;
++              TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
++
++              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
++
+               return SCSI_ABORT_SNOOZE;
        }
-@@ -148,6 +156,9 @@
-       case OCFS2_IOC32_SETFLAGS:
-               cmd = OCFS2_IOC_SETFLAGS;
-               break;
-+      case OCFS2_IOC_RESVSP:
-+      case OCFS2_IOC_RESVSP64:
-+              break;
-       default:
-               return -ENOIOCTLCMD;
+-      prev = tmp = host->first_pending;       /* Check Pend queue */
+-      while (tmp != NULL) {
++      pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;    /* Check Pend queue */
++      while (pTmpScb != NULL) {
+               /* 07/27/98 */
+-              if (tmp->srb == srbp) {
+-                      if (tmp == host->active) {
+-                              spin_unlock_irqrestore(&host->semaph_lock, flags);
++              if (pTmpScb->SCB_Srb == srbp) {
++                      if (pTmpScb == pCurHcb->HCS_ActScb) {
++                              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+                               return SCSI_ABORT_BUSY;
+-                      } else if (tmp == host->first_pending) {
+-                              if ((host->first_pending = tmp->next) == NULL)
+-                                      host->last_pending = NULL;
+-                      } else {
+-                              prev->next = tmp->next;
+-                              if (tmp == host->last_pending)
+-                                      host->last_pending = prev;
+-                      }
+-                      tmp->hastat = HOST_ABORTED;
+-                      tmp->flags |= SCF_DONE;
+-                      if (tmp->flags & SCF_POST)
+-                              (*tmp->post) ((u8 *) host, (u8 *) tmp);
+-                      spin_unlock_irqrestore(&host->semaph_lock, flags);
++                      } else if (pTmpScb == pCurHcb->HCS_FirstPend) {
++                              if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
++                                      pCurHcb->HCS_LastPend = NULL;
++                      } else {
++                              pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
++                              if (pTmpScb == pCurHcb->HCS_LastPend)
++                                      pCurHcb->HCS_LastPend = pPrevScb;
++                      }
++                      pTmpScb->SCB_HaStat = HOST_ABORTED;
++                      pTmpScb->SCB_Flags |= SCF_DONE;
++                      if (pTmpScb->SCB_Flags & SCF_POST)
++                              (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
++                      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+                       return SCSI_ABORT_SUCCESS;
+               }
+-              prev = tmp;
+-              tmp = tmp->next;
++              pPrevScb = pTmpScb;
++              pTmpScb = pTmpScb->SCB_NxtScb;
        }
-diff -Nurb linux-2.6.22-570/fs/ocfs2/journal.c linux-2.6.22-590/fs/ocfs2/journal.c
---- linux-2.6.22-570/fs/ocfs2/journal.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/journal.c        2008-01-02 13:56:37.000000000 -0500
-@@ -722,8 +722,7 @@
-               container_of(work, struct ocfs2_journal, j_recovery_work);
-       struct ocfs2_super *osb = journal->j_osb;
-       struct ocfs2_dinode *la_dinode, *tl_dinode;
--      struct ocfs2_la_recovery_item *item;
--      struct list_head *p, *n;
-+      struct ocfs2_la_recovery_item *item, *n;
-       LIST_HEAD(tmp_la_list);
  
-       mlog_entry_void();
-@@ -734,8 +733,7 @@
-       list_splice_init(&journal->j_la_cleanups, &tmp_la_list);
-       spin_unlock(&journal->j_lock);
+-      prev = tmp = host->first_busy;  /* Check Busy queue */
+-      while (tmp != NULL) {
+-              if (tmp->srb == srbp) {
+-                      if (tmp == host->active) {
+-                              spin_unlock_irqrestore(&host->semaph_lock, flags);
++      pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;    /* Check Busy queue */
++      while (pTmpScb != NULL) {
++
++              if (pTmpScb->SCB_Srb == srbp) {
++
++                      if (pTmpScb == pCurHcb->HCS_ActScb) {
++                              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+                               return SCSI_ABORT_BUSY;
+-                      } else if (tmp->tagmsg == 0) {
+-                              spin_unlock_irqrestore(&host->semaph_lock, flags);
++                      } else if (pTmpScb->SCB_TagMsg == 0) {
++                              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+                               return SCSI_ABORT_BUSY;
+                       } else {
+-                              host->act_tags[tmp->target]--;
+-                              if (tmp == host->first_busy) {
+-                                      if ((host->first_busy = tmp->next) == NULL)
+-                                              host->last_busy = NULL;
+-                              } else {
+-                                      prev->next = tmp->next;
+-                                      if (tmp == host->last_busy)
+-                                              host->last_busy = prev;
+-                              }
+-                              tmp->next = NULL;
+-
+-
+-                              tmp->hastat = HOST_ABORTED;
+-                              tmp->flags |= SCF_DONE;
+-                              if (tmp->flags & SCF_POST)
+-                                      (*tmp->post) ((u8 *) host, (u8 *) tmp);
+-                              spin_unlock_irqrestore(&host->semaph_lock, flags);
++                              pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
++                              if (pTmpScb == pCurHcb->HCS_FirstBusy) {
++                                      if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
++                                              pCurHcb->HCS_LastBusy = NULL;
++                              } else {
++                                      pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
++                                      if (pTmpScb == pCurHcb->HCS_LastBusy)
++                                              pCurHcb->HCS_LastBusy = pPrevScb;
++                              }
++                              pTmpScb->SCB_NxtScb = NULL;
++
++
++                              pTmpScb->SCB_HaStat = HOST_ABORTED;
++                              pTmpScb->SCB_Flags |= SCF_DONE;
++                              if (pTmpScb->SCB_Flags & SCF_POST)
++                                      (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
++                              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+                               return SCSI_ABORT_SUCCESS;
+                       }
+               }
+-              prev = tmp;
+-              tmp = tmp->next;
++              pPrevScb = pTmpScb;
++              pTmpScb = pTmpScb->SCB_NxtScb;
+       }
+-      spin_unlock_irqrestore(&host->semaph_lock, flags);
+-      return SCSI_ABORT_NOT_RUNNING;
++      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
++      return (SCSI_ABORT_NOT_RUNNING);
+ }
  
--      list_for_each_safe(p, n, &tmp_la_list) {
--              item = list_entry(p, struct ocfs2_la_recovery_item, lri_list);
-+      list_for_each_entry_safe(item, n, &tmp_la_list, lri_list) {
-               list_del_init(&item->lri_list);
+ /***************************************************************************/
+-static int initio_bad_seq(struct initio_host * host)
++static int tul_bad_seq(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb;
++      SCB *pCurScb;
  
-               mlog(0, "Complete recovery for slot %d\n", item->lri_slot);
-diff -Nurb linux-2.6.22-570/fs/ocfs2/mmap.c linux-2.6.22-590/fs/ocfs2/mmap.c
---- linux-2.6.22-570/fs/ocfs2/mmap.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/mmap.c   2008-01-02 13:56:37.000000000 -0500
-@@ -37,38 +37,48 @@
+-      printk("initio_bad_seg c=%d\n", host->index);
++      printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index);
  
- #include "ocfs2.h"
+-      if ((scb = host->active) != NULL) {
+-              initio_unlink_busy_scb(host, scb);
+-              scb->hastat = HOST_BAD_PHAS;
+-              scb->tastat = 0;
+-              initio_append_done_scb(host, scb);
++      if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
++              tul_unlink_busy_scb(pCurHcb, pCurScb);
++              pCurScb->SCB_HaStat = HOST_BAD_PHAS;
++              pCurScb->SCB_TaStat = 0;
++              tul_append_done_scb(pCurHcb, pCurScb);
+       }
+-      initio_stop_bm(host);
+-      initio_reset_scsi(host, 8);     /* 7/29/98 */
+-      return initio_post_scsi_rst(host);
++      tul_stop_bm(pCurHcb);
++
++      tul_reset_scsi(pCurHcb, 8);     /* 7/29/98 */
++
++      return (tul_post_scsi_rst(pCurHcb));
+ }
  
-+#include "aops.h"
- #include "dlmglue.h"
- #include "file.h"
- #include "inode.h"
- #include "mmap.h"
++#if 0
  
--static struct page *ocfs2_nopage(struct vm_area_struct * area,
--                               unsigned long address,
--                               int *type)
-+static inline int ocfs2_vm_op_block_sigs(sigset_t *blocked, sigset_t *oldset)
+ /************************************************************************/
+-static void initio_exec_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)
++static int tul_device_reset(HCS * pCurHcb, struct scsi_cmnd *pSrb,
++                          unsigned int target, unsigned int ResetFlags)
  {
--      struct page *page = NOPAGE_SIGBUS;
--      sigset_t blocked, oldset;
--      int ret;
--
--      mlog_entry("(area=%p, address=%lu, type=%p)\n", area, address,
--                 type);
--
--      /* The best way to deal with signals in this path is
-+      /* The best way to deal with signals in the vm path is
-        * to block them upfront, rather than allowing the
-        * locking paths to return -ERESTARTSYS. */
--      sigfillset(&blocked);
-+      sigfillset(blocked);
--      /* We should technically never get a bad ret return
-+      /* We should technically never get a bad return value
-        * from sigprocmask */
--      ret = sigprocmask(SIG_BLOCK, &blocked, &oldset);
-+      return sigprocmask(SIG_BLOCK, blocked, oldset);
-+}
+-      unsigned long flags;
++      ULONG flags;
++      SCB *pScb;
++      spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
 +
-+static inline int ocfs2_vm_op_unblock_sigs(sigset_t *oldset)
-+{
-+      return sigprocmask(SIG_SETMASK, oldset, NULL);
-+}
++      if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) {
 +
-+static struct page *ocfs2_fault(struct vm_area_struct *area,
-+                                              struct fault_data *fdata)
-+{
-+      struct page *page = NULL;
-+      sigset_t blocked, oldset;
-+      int ret;
++              if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
++                      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
++                      /* disable Jasmin SCSI Int        */
 +
-+      mlog_entry("(area=%p, page offset=%lu)\n", area, fdata->pgoff);
++                      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
 +
-+      ret = ocfs2_vm_op_block_sigs(&blocked, &oldset);
-       if (ret < 0) {
-+              fdata->type = VM_FAULT_SIGBUS;
-               mlog_errno(ret);
-               goto out;
-       }
--      page = filemap_nopage(area, address, type);
-+      page = filemap_fault(area, fdata);
--      ret = sigprocmask(SIG_SETMASK, &oldset, NULL);
-+      ret = ocfs2_vm_op_unblock_sigs(&oldset);
-       if (ret < 0)
-               mlog_errno(ret);
- out:
-@@ -76,28 +86,136 @@
-       return page;
- }
--static struct vm_operations_struct ocfs2_file_vm_ops = {
--      .nopage = ocfs2_nopage,
--};
-+static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
-+                              struct page *page)
-+{
-+      int ret;
-+      struct address_space *mapping = inode->i_mapping;
-+      loff_t pos = page->index << PAGE_CACHE_SHIFT;
-+      unsigned int len = PAGE_CACHE_SIZE;
-+      pgoff_t last_index;
-+      struct page *locked_page = NULL;
-+      void *fsdata;
-+      loff_t size = i_size_read(inode);
--int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
-+      /*
-+       * Another node might have truncated while we were waiting on
-+       * cluster locks.
-+       */
-+      last_index = size >> PAGE_CACHE_SHIFT;
-+      if (page->index > last_index) {
-+              ret = -EINVAL;
-+              goto out;
++                      tulip_main(pCurHcb);
++
++                      spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
++
++                      pCurHcb->HCS_Semaph = 1;
++                      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
++
++                      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
++
++                      return SCSI_RESET_SNOOZE;
++              }
++              pScb = pCurHcb->HCS_FirstBusy;  /* Check Busy queue */
++              while (pScb != NULL) {
++                      if (pScb->SCB_Srb == pSrb)
++                              break;
++                      pScb = pScb->SCB_NxtScb;
++              }
++              if (pScb == NULL) {
++                      printk("Unable to Reset - No SCB Found\n");
++
++                      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
++                      return SCSI_RESET_NOT_RUNNING;
++              }
++      }
++      if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) {
++              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
++              return SCSI_RESET_NOT_RUNNING;
 +      }
++      pScb->SCB_Opcode = BusDevRst;
++      pScb->SCB_Flags = SCF_POST;
++      pScb->SCB_Target = target;
++      pScb->SCB_Mode = 0;
 +
-+      /*
-+       * The i_size check above doesn't catch the case where nodes
-+       * truncated and then re-extended the file. We'll re-check the
-+       * page mapping after taking the page lock inside of
-+       * ocfs2_write_begin_nolock().
-+       */
-+      if (!PageUptodate(page) || page->mapping != inode->i_mapping) {
-+              ret = -EINVAL;
-+              goto out;
++      pScb->SCB_Srb = NULL;
++      if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
++              pScb->SCB_Srb = pSrb;
 +      }
++      tul_push_pend_scb(pCurHcb, pScb);       /* push this SCB to Pending queue */
 +
-+      /*
-+       * Call ocfs2_write_begin() and ocfs2_write_end() to take
-+       * advantage of the allocation code there. We pass a write
-+       * length of the whole page (chopped to i_size) to make sure
-+       * the whole thing is allocated.
-+       *
-+       * Since we know the page is up to date, we don't have to
-+       * worry about ocfs2_write_begin() skipping some buffer reads
-+       * because the "write" would invalidate their data.
-+       */
-+      if (page->index == last_index)
-+              len = size & ~PAGE_CACHE_MASK;
++      if (pCurHcb->HCS_Semaph == 1) {
++              TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
++              /* disable Jasmin SCSI Int        */
++              pCurHcb->HCS_Semaph = 0;
 +
-+      ret = ocfs2_write_begin_nolock(mapping, pos, len, 0, &locked_page,
-+                                     &fsdata, di_bh, page);
-+      if (ret) {
-+              if (ret != -ENOSPC)
-+                      mlog_errno(ret);
-+              goto out;
-+      }
++              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
 +
-+      ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page,
-+                                   fsdata);
-+      if (ret < 0) {
-+              mlog_errno(ret);
-+              goto out;
++              tulip_main(pCurHcb);
++
++                spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
++
++              pCurHcb->HCS_Semaph = 1;
++              TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
 +      }
-+      BUG_ON(ret != len);
-+      ret = 0;
-+out:
-+      return ret;
++      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
++      return SCSI_RESET_PENDING;
 +}
 +
-+static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
- {
--      int ret = 0, lock_level = 0;
--      struct ocfs2_super *osb = OCFS2_SB(file->f_dentry->d_inode->i_sb);
-+      struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
-+      struct buffer_head *di_bh = NULL;
-+      sigset_t blocked, oldset;
-+      int ret, ret2;
++static int tul_reset_scsi_bus(HCS * pCurHcb)
++{
++      ULONG flags;
 +
-+      ret = ocfs2_vm_op_block_sigs(&blocked, &oldset);
-+      if (ret < 0) {
-+              mlog_errno(ret);
-+              return ret;
-+      }
-       /*
--       * Only support shared writeable mmap for local mounts which
--       * don't know about holes.
-+       * The cluster locks taken will block a truncate from another
-+       * node. Taking the data lock will also ensure that we don't
-+       * attempt page truncation as part of a downconvert.
-        */
--      if ((!ocfs2_mount_local(osb) || ocfs2_sparse_alloc(osb)) &&
--          ((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE)) &&
--          ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
--              mlog(0, "disallow shared writable mmaps %lx\n", vma->vm_flags);
--              /* This is -EINVAL because generic_file_readonly_mmap
--               * returns it in a similar situation. */
--              return -EINVAL;
-+      ret = ocfs2_meta_lock(inode, &di_bh, 1);
-+      if (ret < 0) {
-+              mlog_errno(ret);
-+              goto out;
-       }
-+      /*
-+       * The alloc sem should be enough to serialize with
-+       * ocfs2_truncate_file() changing i_size as well as any thread
-+       * modifying the inode btree.
-+       */
-+      down_write(&OCFS2_I(inode)->ip_alloc_sem);
++      spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
++      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
++      pCurHcb->HCS_Semaph = 0;
 +
-+      ret = ocfs2_data_lock(inode, 1);
-+      if (ret < 0) {
-+              mlog_errno(ret);
-+              goto out_meta_unlock;
-+      }
++      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
 +
-+      ret = __ocfs2_page_mkwrite(inode, di_bh, page);
++      tul_stop_bm(pCurHcb);
 +
-+      ocfs2_data_unlock(inode, 1);
++      tul_reset_scsi(pCurHcb, 2);     /* 7/29/98 */
 +
-+out_meta_unlock:
-+      up_write(&OCFS2_I(inode)->ip_alloc_sem);
++      spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
++      tul_post_scsi_rst(pCurHcb);
 +
-+      brelse(di_bh);
-+      ocfs2_meta_unlock(inode, 1);
++        spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
 +
-+out:
-+      ret2 = ocfs2_vm_op_unblock_sigs(&oldset);
-+      if (ret2 < 0)
-+              mlog_errno(ret2);
++      tulip_main(pCurHcb);
 +
-+      return ret;
++        spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
++
++      pCurHcb->HCS_Semaph = 1;
++      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
++      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
++      return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);
 +}
 +
-+static struct vm_operations_struct ocfs2_file_vm_ops = {
-+      .nopage         = ocfs2_fault,
-+      .page_mkwrite   = ocfs2_page_mkwrite,
-+};
++#endif  /*  0  */
 +
-+int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
++/************************************************************************/
++static void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
 +{
-+      int ret = 0, lock_level = 0;
++      ULONG flags;
+-      scb->mode = 0;
++      pCurScb->SCB_Mode = 0;
+-      scb->sgidx = 0;
+-      scb->sgmax = scb->sglen;
++      pCurScb->SCB_SGIdx = 0;
++      pCurScb->SCB_SGMax = pCurScb->SCB_SGLen;
+-      spin_lock_irqsave(&host->semaph_lock, flags);
++      spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+-      initio_append_pend_scb(host, scb);      /* Append this SCB to Pending queue */
++      tul_append_pend_scb(pCurHcb, pCurScb);  /* Append this SCB to Pending queue */
+ /* VVVVV 07/21/98 */
+-      if (host->semaph == 1) {
+-              /* Disable Jasmin SCSI Int */
+-              outb(0x1F, host->addr + TUL_Mask);
+-              host->semaph = 0;
+-              spin_unlock_irqrestore(&host->semaph_lock, flags);
++      if (pCurHcb->HCS_Semaph == 1) {
++              TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
++              /* disable Jasmin SCSI Int        */
++              pCurHcb->HCS_Semaph = 0;
++
++              spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
++
++              tulip_main(pCurHcb);
+-              tulip_main(host);
++              spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+-              spin_lock_irqsave(&host->semaph_lock, flags);
+-              host->semaph = 1;
+-              outb(0x0F, host->addr + TUL_Mask);
++              pCurHcb->HCS_Semaph = 1;
++              TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+       }
+-      spin_unlock_irqrestore(&host->semaph_lock, flags);
++      spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+       return;
+ }
+ /***************************************************************************/
+-static int initio_isr(struct initio_host * host)
++static int tul_isr(HCS * pCurHcb)
+ {
+-      if (inb(host->addr + TUL_Int) & TSS_INT_PENDING) {
+-              if (host->semaph == 1) {
+-                      outb(0x1F, host->addr + TUL_Mask);
++      /* Enter critical section       */
 +
-       ret = ocfs2_meta_lock_atime(file->f_dentry->d_inode,
-                                   file->f_vfsmnt, &lock_level);
-       if (ret < 0) {
-@@ -107,6 +225,7 @@
-       ocfs2_meta_unlock(file->f_dentry->d_inode, lock_level);
- out:
-       vma->vm_ops = &ocfs2_file_vm_ops;
-+      vma->vm_flags |= VM_CAN_INVALIDATE | VM_CAN_NONLINEAR;
-       return 0;
++      if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) {
++              if (pCurHcb->HCS_Semaph == 1) {
++                      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+                       /* Disable Tulip SCSI Int */
+-                      host->semaph = 0;
++                      pCurHcb->HCS_Semaph = 0;
+-                      tulip_main(host);
++                      tulip_main(pCurHcb);
+-                      host->semaph = 1;
+-                      outb(0x0F, host->addr + TUL_Mask);
+-                      return 1;
++                      pCurHcb->HCS_Semaph = 1;
++                      TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
++                      return (1);
+               }
+       }
+-      return 0;
++      return (0);
  }
  
-diff -Nurb linux-2.6.22-570/fs/ocfs2/namei.c linux-2.6.22-590/fs/ocfs2/namei.c
---- linux-2.6.22-570/fs/ocfs2/namei.c  2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/ocfs2/namei.c  2008-01-02 13:56:37.000000000 -0500
-@@ -1684,7 +1684,7 @@
-               u32 offset = 0;
+-static int tulip_main(struct initio_host * host)
++/***************************************************************************/
++int tulip_main(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb;
++      SCB *pCurScb;
  
-               inode->i_op = &ocfs2_symlink_inode_operations;
--              status = ocfs2_do_extend_allocation(osb, inode, &offset, 1,
-+              status = ocfs2_do_extend_allocation(osb, inode, &offset, 1, 0,
-                                                   new_fe_bh,
-                                                   handle, data_ac, NULL,
-                                                   NULL);
-diff -Nurb linux-2.6.22-570/fs/ocfs2/ocfs2.h linux-2.6.22-590/fs/ocfs2/ocfs2.h
---- linux-2.6.22-570/fs/ocfs2/ocfs2.h  2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/ocfs2/ocfs2.h  2008-01-02 13:56:37.000000000 -0500
-@@ -220,6 +220,7 @@
-       u16 max_slots;
-       s16 node_num;
-       s16 slot_num;
-+      s16 preferred_slot;
-       int s_sectsize_bits;
-       int s_clustersize;
-       int s_clustersize_bits;
-@@ -306,6 +307,19 @@
-       return 0;
+       for (;;) {
+-              tulip_scsi(host);       /* Call tulip_scsi              */
+-              /* Walk the list of completed SCBs */
+-              while ((scb = initio_find_done_scb(host)) != NULL) {    /* find done entry */
+-                      if (scb->tastat == INI_QUEUE_FULL) {
+-                              host->max_tags[scb->target] =
+-                                  host->act_tags[scb->target] - 1;
+-                              scb->tastat = 0;
+-                              initio_append_pend_scb(host, scb);
++              tulip_scsi(pCurHcb);    /* Call tulip_scsi              */
++
++              while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) {        /* find done entry */
++                      if (pCurScb->SCB_TaStat == INI_QUEUE_FULL) {
++                              pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] =
++                                  pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1;
++                              pCurScb->SCB_TaStat = 0;
++                              tul_append_pend_scb(pCurHcb, pCurScb);
+                               continue;
+                       }
+-                      if (!(scb->mode & SCM_RSENS)) {         /* not in auto req. sense mode */
+-                              if (scb->tastat == 2) {
++                      if (!(pCurScb->SCB_Mode & SCM_RSENS)) {         /* not in auto req. sense mode */
++                              if (pCurScb->SCB_TaStat == 2) {
+                                       /* clr sync. nego flag */
+-                                      if (scb->flags & SCF_SENSE) {
+-                                              u8 len;
+-                                              len = scb->senselen;
++                                      if (pCurScb->SCB_Flags & SCF_SENSE) {
++                                              BYTE len;
++                                              len = pCurScb->SCB_SenseLen;
+                                               if (len == 0)
+                                                       len = 1;
+-                                              scb->buflen = scb->senselen;
+-                                              scb->bufptr = scb->senseptr;
+-                                              scb->flags &= ~(SCF_SG | SCF_DIR);      /* for xfer_data_in */
+-                                              /* so, we won't report wrong direction in xfer_data_in,
++                                              pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen;
++                                              pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr;
++                                              pCurScb->SCB_Flags &= ~(SCF_SG | SCF_DIR);      /* for xfer_data_in */
++/*                      pCurScb->SCB_Flags |= SCF_NO_DCHK;      */
++                                              /* so, we won't report worng direction in xfer_data_in,
+                                                  and won't report HOST_DO_DU in state_6 */
+-                                              scb->mode = SCM_RSENS;
+-                                              scb->ident &= 0xBF;     /* Disable Disconnect */
+-                                              scb->tagmsg = 0;
+-                                              scb->tastat = 0;
+-                                              scb->cdblen = 6;
+-                                              scb->cdb[0] = SCSICMD_RequestSense;
+-                                              scb->cdb[1] = 0;
+-                                              scb->cdb[2] = 0;
+-                                              scb->cdb[3] = 0;
+-                                              scb->cdb[4] = len;
+-                                              scb->cdb[5] = 0;
+-                                              initio_push_pend_scb(host, scb);
++                                              pCurScb->SCB_Mode = SCM_RSENS;
++                                              pCurScb->SCB_Ident &= 0xBF;     /* Disable Disconnect */
++                                              pCurScb->SCB_TagMsg = 0;
++                                              pCurScb->SCB_TaStat = 0;
++                                              pCurScb->SCB_CDBLen = 6;
++                                              pCurScb->SCB_CDB[0] = SCSICMD_RequestSense;
++                                              pCurScb->SCB_CDB[1] = 0;
++                                              pCurScb->SCB_CDB[2] = 0;
++                                              pCurScb->SCB_CDB[3] = 0;
++                                              pCurScb->SCB_CDB[4] = len;
++                                              pCurScb->SCB_CDB[5] = 0;
++                                              tul_push_pend_scb(pCurHcb, pCurScb);
+                                               break;
+                                       }
+                               }
+                       } else {        /* in request sense mode */
+-                              if (scb->tastat == 2) {         /* check contition status again after sending
++                              if (pCurScb->SCB_TaStat == 2) {         /* check contition status again after sending
+                                                                          requset sense cmd 0x3 */
+-                                      scb->hastat = HOST_BAD_PHAS;
++                                      pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+                               }
+-                              scb->tastat = 2;
++                              pCurScb->SCB_TaStat = 2;
+                       }
+-                      scb->flags |= SCF_DONE;
+-                      if (scb->flags & SCF_POST) {
+-                              /* FIXME: only one post method and lose casts */
+-                              (*scb->post) ((u8 *) host, (u8 *) scb);
++                      pCurScb->SCB_Flags |= SCF_DONE;
++                      if (pCurScb->SCB_Flags & SCF_POST) {
++                              (*pCurScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pCurScb);
+                       }
+               }               /* while */
++
+               /* find_active: */
+-              if (inb(host->addr + TUL_SStatus0) & TSS_INT_PENDING)
++              if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING)
+                       continue;
+-              if (host->active)       /* return to OS and wait for xfer_done_ISR/Selected_ISR */
++
++              if (pCurHcb->HCS_ActScb) {      /* return to OS and wait for xfer_done_ISR/Selected_ISR */
+                       return 1;       /* return to OS, enable interrupt */
++              }
+               /* Check pending SCB            */
+-              if (initio_find_first_pend_scb(host) == NULL)
++              if (tul_find_first_pend_scb(pCurHcb) == NULL) {
+                       return 1;       /* return to OS, enable interrupt */
++              }
+       }                       /* End of for loop */
+       /* statement won't reach here */
  }
  
-+static inline int ocfs2_writes_unwritten_extents(struct ocfs2_super *osb)
-+{
-+      /*
-+       * Support for sparse files is a pre-requisite
-+       */
-+      if (!ocfs2_sparse_alloc(osb))
-+              return 0;
+-static void tulip_scsi(struct initio_host * host)
 +
-+      if (osb->s_feature_ro_compat & OCFS2_FEATURE_RO_COMPAT_UNWRITTEN)
-+              return 1;
-+      return 0;
-+}
 +
- /* set / clear functions because cluster events can make these happen
-  * in parallel so we want the transitions to be atomic. this also
-  * means that any future flags osb_flags must be protected by spinlock
-diff -Nurb linux-2.6.22-570/fs/ocfs2/ocfs2_fs.h linux-2.6.22-590/fs/ocfs2/ocfs2_fs.h
---- linux-2.6.22-570/fs/ocfs2/ocfs2_fs.h       2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/ocfs2/ocfs2_fs.h       2008-01-02 13:56:37.000000000 -0500
-@@ -88,7 +88,7 @@
- #define OCFS2_FEATURE_COMPAT_SUPP     OCFS2_FEATURE_COMPAT_BACKUP_SB
- #define OCFS2_FEATURE_INCOMPAT_SUPP   (OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \
-                                        | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC)
--#define OCFS2_FEATURE_RO_COMPAT_SUPP  0
-+#define OCFS2_FEATURE_RO_COMPAT_SUPP  OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
++
++/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
++/***************************************************************************/
++/***************************************************************************/
++/***************************************************************************/
++/***************************************************************************/
++
++/***************************************************************************/
++void tulip_scsi(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb;
+-      struct target_control *active_tc;
++      SCB *pCurScb;
++      TCS *pCurTcb;
  
- /*
-  * Heartbeat-only devices are missing journals and other files.  The
-@@ -116,6 +116,11 @@
-  */
- #define OCFS2_FEATURE_COMPAT_BACKUP_SB                0x0001
+       /* make sure to service interrupt asap */
+-      if ((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING) {
+-              host->phase = host->jsstatus0 & TSS_PH_MASK;
+-              host->jsstatus1 = inb(host->addr + TUL_SStatus1);
+-              host->jsint = inb(host->addr + TUL_SInt);
+-              if (host->jsint & TSS_SCSIRST_INT) {    /* SCSI bus reset detected      */
+-                      int_initio_scsi_rst(host);
++
++      if ((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) & TSS_INT_PENDING) {
++
++              pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
++              pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
++              pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
++              if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {     /* SCSI bus reset detected      */
++                      int_tul_scsi_rst(pCurHcb);
+                       return;
+               }
+-              if (host->jsint & TSS_RESEL_INT) {      /* if selected/reselected interrupt */
+-                      if (int_initio_resel(host) == 0)
+-                              initio_next_state(host);
++              if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {       /* if selected/reselected interrupt */
++                      if (int_tul_resel(pCurHcb) == 0)
++                              tul_next_state(pCurHcb);
+                       return;
+               }
+-              if (host->jsint & TSS_SEL_TIMEOUT) {
+-                      int_initio_busfree(host);
++              if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {
++                      int_tul_busfree(pCurHcb);
+                       return;
+               }
+-              if (host->jsint & TSS_DISC_INT) {       /* BUS disconnection            */
+-                      int_initio_busfree(host);       /* unexpected bus free or sel timeout */
++              if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {        /* BUS disconnection            */
++                      int_tul_busfree(pCurHcb);       /* unexpected bus free or sel timeout */
+                       return;
+               }
+-              if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV)) {     /* func complete or Bus service */
+-                      if ((scb = host->active) != NULL)
+-                              initio_next_state(host);
++              if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {      /* func complete or Bus service */
++                      if ((pCurScb = pCurHcb->HCS_ActScb) != NULL)
++                              tul_next_state(pCurHcb);
+                       return;
+               }
+       }
+-      if (host->active != NULL)
++      if (pCurHcb->HCS_ActScb != NULL)
+               return;
  
-+/*
-+ * Unwritten extents support.
-+ */
-+#define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN     0x0001
+-      if ((scb = initio_find_first_pend_scb(host)) == NULL)
++      if ((pCurScb = tul_find_first_pend_scb(pCurHcb)) == NULL)
+               return;
+       /* program HBA's SCSI ID & target SCSI ID */
+-      outb((host->scsi_id << 4) | (scb->target & 0x0F),
+-              host->addr + TUL_SScsiId);
+-      if (scb->opcode == ExecSCSI) {
+-              active_tc = &host->targets[scb->target];
++      TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId,
++           (pCurHcb->HCS_SCSI_ID << 4) | (pCurScb->SCB_Target & 0x0F));
++      if (pCurScb->SCB_Opcode == ExecSCSI) {
++              pCurTcb = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
+-              if (scb->tagmsg)
+-                      active_tc->drv_flags |= TCF_DRV_EN_TAG;
++              if (pCurScb->SCB_TagMsg)
++                      pCurTcb->TCS_DrvFlags |= TCF_DRV_EN_TAG;
+               else
+-                      active_tc->drv_flags &= ~TCF_DRV_EN_TAG;
++                      pCurTcb->TCS_DrvFlags &= ~TCF_DRV_EN_TAG;
+-              outb(active_tc->js_period, host->addr + TUL_SPeriod);
+-              if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {  /* do wdtr negotiation          */
+-                      initio_select_atn_stop(host, scb);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
++              if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {        /* do wdtr negotiation          */
++                      tul_select_atn_stop(pCurHcb, pCurScb);
+               } else {
+-                      if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {     /* do sync negotiation          */
+-                              initio_select_atn_stop(host, scb);
++                      if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {   /* do sync negotiation          */
++                              tul_select_atn_stop(pCurHcb, pCurScb);
+                       } else {
+-                              if (scb->tagmsg)
+-                                      initio_select_atn3(host, scb);
++                              if (pCurScb->SCB_TagMsg)
++                                      tul_select_atn3(pCurHcb, pCurScb);
+                               else
+-                                      initio_select_atn(host, scb);
++                                      tul_select_atn(pCurHcb, pCurScb);
+                       }
+               }
+-              if (scb->flags & SCF_POLL) {
+-                      while (wait_tulip(host) != -1) {
+-                              if (initio_next_state(host) == -1)
++              if (pCurScb->SCB_Flags & SCF_POLL) {
++                      while (wait_tulip(pCurHcb) != -1) {
++                              if (tul_next_state(pCurHcb) == -1)
+                                       break;
+                       }
+               }
+-      } else if (scb->opcode == BusDevRst) {
+-              initio_select_atn_stop(host, scb);
+-              scb->next_state = 8;
+-              if (scb->flags & SCF_POLL) {
+-                      while (wait_tulip(host) != -1) {
+-                              if (initio_next_state(host) == -1)
++      } else if (pCurScb->SCB_Opcode == BusDevRst) {
++              tul_select_atn_stop(pCurHcb, pCurScb);
++              pCurScb->SCB_NxtStat = 8;
++              if (pCurScb->SCB_Flags & SCF_POLL) {
++                      while (wait_tulip(pCurHcb) != -1) {
++                              if (tul_next_state(pCurHcb) == -1)
+                                       break;
+                       }
+               }
+-      } else if (scb->opcode == AbortCmd) {
+-              if (initio_abort_srb(host, scb->srb) != 0) {
+-                      initio_unlink_pend_scb(host, scb);
+-                      initio_release_scb(host, scb);
++      } else if (pCurScb->SCB_Opcode == AbortCmd) {
++              if (tul_abort_srb(pCurHcb, pCurScb->SCB_Srb) != 0) {
 +
- /* The byte offset of the first backup block will be 1G.
-  * The following will be 4G, 16G, 64G, 256G and 1T.
-  */
-@@ -174,6 +179,32 @@
- #define OCFS2_IOC32_SETFLAGS  _IOW('f', 2, int)
++
++                      tul_unlink_pend_scb(pCurHcb, pCurScb);
++
++                      tul_release_scb(pCurHcb, pCurScb);
+               } else {
+-                      scb->opcode = BusDevRst;
+-                      initio_select_atn_stop(host, scb);
+-                      scb->next_state = 8;
++                      pCurScb->SCB_Opcode = BusDevRst;
++                      tul_select_atn_stop(pCurHcb, pCurScb);
++                      pCurScb->SCB_NxtStat = 8;
+               }
++
++/* 08/03/98 */
+       } else {
+-              initio_unlink_pend_scb(host, scb);
+-              scb->hastat = 0x16;     /* bad command */
+-              initio_append_done_scb(host, scb);
++              tul_unlink_pend_scb(pCurHcb, pCurScb);
++              pCurScb->SCB_HaStat = 0x16;     /* bad command */
++              tul_append_done_scb(pCurHcb, pCurScb);
+       }
+       return;
+ }
  
- /*
-+ * Space reservation / allocation / free ioctls and argument structure
-+ * are designed to be compatible with XFS.
-+ *
-+ * ALLOCSP* and FREESP* are not and will never be supported, but are
-+ * included here for completeness.
-+ */
-+struct ocfs2_space_resv {
-+      __s16           l_type;
-+      __s16           l_whence;
-+      __s64           l_start;
-+      __s64           l_len;          /* len == 0 means until end of file */
-+      __s32           l_sysid;
-+      __u32           l_pid;
-+      __s32           l_pad[4];       /* reserve area                     */
-+};
+-/**
+- *    initio_next_state               -       Next SCSI state
+- *    @host: InitIO host we are processing
+- *
+- *    Progress the active command block along the state machine
+- *    until we hit a state which we must wait for activity to occur.
+- *
+- *    Returns zero or a negative code.
+- */
+-static int initio_next_state(struct initio_host * host)
++/***************************************************************************/
++int tul_next_state(HCS * pCurHcb)
+ {
+       int next;
+-      next = host->active->next_state;
++      next = pCurHcb->HCS_ActScb->SCB_NxtStat;
+       for (;;) {
+               switch (next) {
+               case 1:
+-                      next = initio_state_1(host);
++                      next = tul_state_1(pCurHcb);
+                       break;
+               case 2:
+-                      next = initio_state_2(host);
++                      next = tul_state_2(pCurHcb);
+                       break;
+               case 3:
+-                      next = initio_state_3(host);
++                      next = tul_state_3(pCurHcb);
+                       break;
+               case 4:
+-                      next = initio_state_4(host);
++                      next = tul_state_4(pCurHcb);
+                       break;
+               case 5:
+-                      next = initio_state_5(host);
++                      next = tul_state_5(pCurHcb);
+                       break;
+               case 6:
+-                      next = initio_state_6(host);
++                      next = tul_state_6(pCurHcb);
+                       break;
+               case 7:
+-                      next = initio_state_7(host);
++                      next = tul_state_7(pCurHcb);
+                       break;
+               case 8:
+-                      return initio_bus_device_reset(host);
++                      return (tul_bus_device_reset(pCurHcb));
+               default:
+-                      return initio_bad_seq(host);
++                      return (tul_bad_seq(pCurHcb));
+               }
+               if (next <= 0)
+                       return next;
+@@ -1314,363 +1554,338 @@
+ }
+-/**
+- *    initio_state_1          -       SCSI state machine
+- *    @host: InitIO host we are controlling
+- *
+- *    Perform SCSI state processing for Select/Attention/Stop
+- */
+-
+-static int initio_state_1(struct initio_host * host)
++/***************************************************************************/
++/* sTate after selection with attention & stop */
++int tul_state_1(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb = host->active;
+-      struct target_control *active_tc = host->active_tc;
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
++      TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+ #if DEBUG_STATE
+       printk("-s1-");
+ #endif
+-      /* Move the SCB from pending to busy */
+-      initio_unlink_pend_scb(host, scb);
+-      initio_append_busy_scb(host, scb);
++      tul_unlink_pend_scb(pCurHcb, pCurScb);
++      tul_append_busy_scb(pCurHcb, pCurScb);
+-      outb(active_tc->sconfig0, host->addr + TUL_SConfig );
++      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
+       /* ATN on */
+-      if (host->phase == MSG_OUT) {
+-              outb(TSC_EN_BUS_IN | TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
+-              outb(scb->ident, host->addr + TUL_SFifo);
+-
+-              if (scb->tagmsg) {
+-                      outb(scb->tagmsg, host->addr + TUL_SFifo);
+-                      outb(scb->tagid, host->addr + TUL_SFifo);
+-              }
+-              if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
+-                      active_tc->flags |= TCF_WDTR_DONE;
+-                      outb(MSG_EXTEND, host->addr + TUL_SFifo);
+-                      outb(2, host->addr + TUL_SFifo);        /* Extended msg length */
+-                      outb(3, host->addr + TUL_SFifo);        /* Sync request */
+-                      outb(1, host->addr + TUL_SFifo);        /* Start from 16 bits */
+-              } else if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
+-                      active_tc->flags |= TCF_SYNC_DONE;
+-                      outb(MSG_EXTEND, host->addr + TUL_SFifo);
+-                      outb(3, host->addr + TUL_SFifo);        /* extended msg length */
+-                      outb(1, host->addr + TUL_SFifo);        /* sync request */
+-                      outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);
+-                      outb(MAX_OFFSET, host->addr + TUL_SFifo);       /* REQ/ACK offset */
++      if (pCurHcb->HCS_Phase == MSG_OUT) {
++
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, (TSC_EN_BUS_IN | TSC_HW_RESELECT));
++
++              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
++
++              if (pCurScb->SCB_TagMsg) {
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
+               }
+-              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-              if (wait_tulip(host) == -1)
+-                      return -1;
++              if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
 +
-+#define OCFS2_IOC_ALLOCSP             _IOW ('X', 10, struct ocfs2_space_resv)
-+#define OCFS2_IOC_FREESP              _IOW ('X', 11, struct ocfs2_space_resv)
-+#define OCFS2_IOC_RESVSP              _IOW ('X', 40, struct ocfs2_space_resv)
-+#define OCFS2_IOC_UNRESVSP    _IOW ('X', 41, struct ocfs2_space_resv)
-+#define OCFS2_IOC_ALLOCSP64   _IOW ('X', 36, struct ocfs2_space_resv)
-+#define OCFS2_IOC_FREESP64    _IOW ('X', 37, struct ocfs2_space_resv)
-+#define OCFS2_IOC_RESVSP64    _IOW ('X', 42, struct ocfs2_space_resv)
-+#define OCFS2_IOC_UNRESVSP64  _IOW ('X', 43, struct ocfs2_space_resv)
++                      pCurTcb->TCS_Flags |= TCF_WDTR_DONE;
 +
-+/*
-  * Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
-  */
- #define OCFS2_JOURNAL_DIRTY_FL        (0x00000001)    /* Journal needs recovery */
-diff -Nurb linux-2.6.22-570/fs/ocfs2/slot_map.c linux-2.6.22-590/fs/ocfs2/slot_map.c
---- linux-2.6.22-570/fs/ocfs2/slot_map.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/slot_map.c       2008-01-02 13:56:37.000000000 -0500
-@@ -121,17 +121,25 @@
-       return ret;
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);       /* Extended msg length */
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);       /* Sync request */
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);       /* Start from 16 bits */
++              } else if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
++
++                      pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
++
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);       /* extended msg length */
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);       /* sync request */
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);      /* REQ/ACK offset */
+       }
+-      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+-      outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);
+-      /* Into before CDB xfer */
+-      return 3;
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++              if (wait_tulip(pCurHcb) == -1)
++                      return (-1);
++      }
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
++      return (3);
  }
  
--static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si)
-+static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, s16 preferred)
+-/**
+- *    initio_state_2          -       SCSI state machine
+- *    @host: InitIO host we are controlling
+- *
+- * state after selection with attention
+- * state after selection with attention3
+- */
+-
+-static int initio_state_2(struct initio_host * host)
++/***************************************************************************/
++/* state after selection with attention */
++/* state after selection with attention3 */
++int tul_state_2(HCS * pCurHcb)
  {
-       int i;
-       s16 ret = OCFS2_INVALID_SLOT;
+-      struct scsi_ctrl_blk *scb = host->active;
+-      struct target_control *active_tc = host->active_tc;
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
++      TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+ #if DEBUG_STATE
+       printk("-s2-");
+ #endif
  
-+      if (preferred >= 0 && preferred < si->si_num_slots) {
-+              if (OCFS2_INVALID_SLOT == si->si_global_node_nums[preferred]) {
-+                      ret = preferred;
-+                      goto out;
-+              }
+-      initio_unlink_pend_scb(host, scb);
+-      initio_append_busy_scb(host, scb);
+-
+-      outb(active_tc->sconfig0, host->addr + TUL_SConfig);
++      tul_unlink_pend_scb(pCurHcb, pCurScb);
++      tul_append_busy_scb(pCurHcb, pCurScb);
+-      if (host->jsstatus1 & TSS_CMD_PH_CMP)
+-              return 4;
++      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
+-      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+-      outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);
+-      /* Into before CDB xfer */
+-      return 3;
++      if (pCurHcb->HCS_JSStatus1 & TSS_CMD_PH_CMP) {
++              return (4);
 +      }
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
++      return (3);
+ }
+-/**
+- *    initio_state_3          -       SCSI state machine
+- *    @host: InitIO host we are controlling
+- *
+- * state before CDB xfer is done
+- */
+-
+-static int initio_state_3(struct initio_host * host)
++/***************************************************************************/
++/* state before CDB xfer is done */
++int tul_state_3(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb = host->active;
+-      struct target_control *active_tc = host->active_tc;
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
++      TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+       int i;
+ #if DEBUG_STATE
+       printk("-s3-");
+ #endif
+       for (;;) {
+-              switch (host->phase) {
++              switch (pCurHcb->HCS_Phase) {
+               case CMD_OUT:   /* Command out phase            */
+-                      for (i = 0; i < (int) scb->cdblen; i++)
+-                              outb(scb->cdb[i], host->addr + TUL_SFifo);
+-                      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-                      if (wait_tulip(host) == -1)
+-                              return -1;
+-                      if (host->phase == CMD_OUT)
+-                              return initio_bad_seq(host);
+-                      return 4;
++                      for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++                      if (wait_tulip(pCurHcb) == -1)
++                              return (-1);
++                      if (pCurHcb->HCS_Phase == CMD_OUT) {
++                              return (tul_bad_seq(pCurHcb));
++                      }
++                      return (4);
+               case MSG_IN:    /* Message in phase             */
+-                      scb->next_state = 3;
+-                      if (initio_msgin(host) == -1)
+-                              return -1;
++                      pCurScb->SCB_NxtStat = 3;
++                      if (tul_msgin(pCurHcb) == -1)
++                              return (-1);
+                       break;
+               case STATUS_IN: /* Status phase                 */
+-                      if (initio_status_msg(host) == -1)
+-                              return -1;
++                      if (tul_status_msg(pCurHcb) == -1)
++                              return (-1);
+                       break;
+               case MSG_OUT:   /* Message out phase            */
+-                      if (active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
+-                              outb(MSG_NOP, host->addr + TUL_SFifo);          /* msg nop */
+-                              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-                              if (wait_tulip(host) == -1)
+-                                      return -1;
+-                      } else {
+-                              active_tc->flags |= TCF_SYNC_DONE;
++                      if (pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
+-                              outb(MSG_EXTEND, host->addr + TUL_SFifo);
+-                              outb(3, host->addr + TUL_SFifo);        /* ext. msg len */
+-                              outb(1, host->addr + TUL_SFifo);        /* sync request */
+-                              outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);
+-                              outb(MAX_OFFSET, host->addr + TUL_SFifo);       /* REQ/ACK offset */
+-                              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-                              if (wait_tulip(host) == -1)
+-                                      return -1;
+-                              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+-                              outb(inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7), host->addr + TUL_SSignal);
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);         /* msg nop */
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++                              if (wait_tulip(pCurHcb) == -1)
++                                      return (-1);
 +
-       for(i = 0; i < si->si_num_slots; i++) {
-               if (OCFS2_INVALID_SLOT == si->si_global_node_nums[i]) {
-                       ret = (s16) i;
++                      } else {
++                              pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
++
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);       /* ext. msg len */
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);       /* sync request */
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);      /* REQ/ACK offset */
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++                              if (wait_tulip(pCurHcb) == -1)
++                                      return (-1);
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7));
+                       }
                        break;
++
+               default:
+-                      return initio_bad_seq(host);
++                      return (tul_bad_seq(pCurHcb));
                }
        }
-+out:
-       return ret;
  }
  
-@@ -248,7 +256,7 @@
-       if (slot == OCFS2_INVALID_SLOT) {
-               /* if no slot yet, then just take 1st available
-                * one. */
--              slot = __ocfs2_find_empty_slot(si);
-+              slot = __ocfs2_find_empty_slot(si, osb->preferred_slot);
-               if (slot == OCFS2_INVALID_SLOT) {
-                       spin_unlock(&si->si_lock);
-                       mlog(ML_ERROR, "no free slots available!\n");
-diff -Nurb linux-2.6.22-570/fs/ocfs2/suballoc.c linux-2.6.22-590/fs/ocfs2/suballoc.c
---- linux-2.6.22-570/fs/ocfs2/suballoc.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/suballoc.c       2008-01-02 13:56:37.000000000 -0500
-@@ -98,14 +98,6 @@
-                                   u16 chain);
- static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg,
-                                                    u32 wanted);
--static int ocfs2_free_suballoc_bits(handle_t *handle,
--                                  struct inode *alloc_inode,
--                                  struct buffer_head *alloc_bh,
--                                  unsigned int start_bit,
--                                  u64 bg_blkno,
--                                  unsigned int count);
--static inline u64 ocfs2_which_suballoc_group(u64 block,
--                                           unsigned int bit);
- static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
-                                                  u64 bg_blkno,
-                                                  u16 bg_bit_off);
-@@ -496,13 +488,7 @@
+-/**
+- *    initio_state_4          -       SCSI state machine
+- *    @host: InitIO host we are controlling
+- *
+- *    SCSI state machine. State 4
+- */
  
-       (*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe);
-       (*ac)->ac_which = OCFS2_AC_USE_META;
--
--#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
--      slot = 0;
--#else
-       slot = osb->slot_num;
--#endif
+-static int initio_state_4(struct initio_host * host)
++/***************************************************************************/
++int tul_state_4(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb = host->active;
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
+ #if DEBUG_STATE
+       printk("-s4-");
+ #endif
+-      if ((scb->flags & SCF_DIR) == SCF_NO_XF) {
+-              return 6;       /* Go to state 6 (After data) */
++      if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_NO_XF) {
++              return (6);     /* Go to state 6                */
+       }
+       for (;;) {
+-              if (scb->buflen == 0)
+-                      return 6;
++              if (pCurScb->SCB_BufLen == 0)
++                      return (6);     /* Go to state 6                */
+-              switch (host->phase) {
++              switch (pCurHcb->HCS_Phase) {
+               case STATUS_IN: /* Status phase                 */
+-                      if ((scb->flags & SCF_DIR) != 0)        /* if direction bit set then report data underrun */
+-                              scb->hastat = HOST_DO_DU;
+-                      if ((initio_status_msg(host)) == -1)
+-                              return -1;
++                      if ((pCurScb->SCB_Flags & SCF_DIR) != 0) {      /* if direction bit set then report data underrun */
++                              pCurScb->SCB_HaStat = HOST_DO_DU;
++                      }
++                      if ((tul_status_msg(pCurHcb)) == -1)
++                              return (-1);
+                       break;
+               case MSG_IN:    /* Message in phase             */
+-                      scb->next_state = 0x4;
+-                      if (initio_msgin(host) == -1)
+-                              return -1;
++                      pCurScb->SCB_NxtStat = 0x4;
++                      if (tul_msgin(pCurHcb) == -1)
++                              return (-1);
+                       break;
+               case MSG_OUT:   /* Message out phase            */
+-                      if (host->jsstatus0 & TSS_PAR_ERROR) {
+-                              scb->buflen = 0;
+-                              scb->hastat = HOST_DO_DU;
+-                              if (initio_msgout_ide(host) == -1)
+-                                      return -1;
+-                              return 6;
+-                      } else {
+-                              outb(MSG_NOP, host->addr + TUL_SFifo);          /* msg nop */
+-                              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-                              if (wait_tulip(host) == -1)
+-                                      return -1;
++                      if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
++                              pCurScb->SCB_BufLen = 0;
++                              pCurScb->SCB_HaStat = HOST_DO_DU;
++                              if (tul_msgout_ide(pCurHcb) == -1)
++                                      return (-1);
++                              return (6);     /* Go to state 6                */
++                      } else {
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);         /* msg nop */
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++                              if (wait_tulip(pCurHcb) == -1)
++                                      return (-1);
+                       }
+                       break;
+               case DATA_IN:   /* Data in phase                */
+-                      return initio_xfer_data_in(host);
++                      return (tul_xfer_data_in(pCurHcb));
+               case DATA_OUT:  /* Data out phase               */
+-                      return initio_xfer_data_out(host);
++                      return (tul_xfer_data_out(pCurHcb));
+               default:
+-                      return initio_bad_seq(host);
++                      return (tul_bad_seq(pCurHcb));
+               }
+       }
+ }
+-/**
+- *    initio_state_5          -       SCSI state machine
+- *    @host: InitIO host we are controlling
+- *
+- *    State after dma xfer done or phase change before xfer done
+- */
 -
-       (*ac)->ac_group_search = ocfs2_block_group_search;
+-static int initio_state_5(struct initio_host * host)
++/***************************************************************************/
++/* state after dma xfer done or phase change before xfer done */
++int tul_state_5(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb = host->active;
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
+       long cnt, xcnt;         /* cannot use unsigned !! code: if (xcnt < 0) */
  
-       status = ocfs2_reserve_suballoc_bits(osb, (*ac),
-@@ -1626,7 +1612,7 @@
- /*
-  * expects the suballoc inode to already be locked.
-  */
--static int ocfs2_free_suballoc_bits(handle_t *handle,
-+int ocfs2_free_suballoc_bits(handle_t *handle,
-                                   struct inode *alloc_inode,
-                                   struct buffer_head *alloc_bh,
-                                   unsigned int start_bit,
-@@ -1703,13 +1689,6 @@
-       return status;
+ #if DEBUG_STATE
+       printk("-s5-");
+ #endif
+-      /*------ get remaining count -------*/
+-      cnt = inl(host->addr + TUL_SCnt0) & 0x0FFFFFF;
++/*------ get remaining count -------*/
++
++      cnt = TUL_RDLONG(pCurHcb->HCS_Base, TUL_SCnt0) & 0x0FFFFFF;
+-      if (inb(host->addr + TUL_XCmd) & 0x20) {
++      if (TUL_RD(pCurHcb->HCS_Base, TUL_XCmd) & 0x20) {
+               /* ----------------------- DATA_IN ----------------------------- */
+               /* check scsi parity error */
+-              if (host->jsstatus0 & TSS_PAR_ERROR)
+-                      scb->hastat = HOST_DO_DU;
+-              if (inb(host->addr + TUL_XStatus) & XPEND) {    /* DMA xfer pending, Send STOP  */
++              if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
++                      pCurScb->SCB_HaStat = HOST_DO_DU;
++              }
++              if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {   /* DMA xfer pending, Send STOP  */
+                       /* tell Hardware  scsi xfer has been terminated */
+-                      outb(inb(host->addr + TUL_XCtrl) | 0x80, host->addr + TUL_XCtrl);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, TUL_RD(pCurHcb->HCS_Base, TUL_XCtrl) | 0x80);
+                       /* wait until DMA xfer not pending */
+-                      while (inb(host->addr + TUL_XStatus) & XPEND)
+-                              cpu_relax();
++                      while (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND);
+               }
+       } else {
+-              /*-------- DATA OUT -----------*/
+-              if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0) {
+-                      if (host->active_tc->js_period & TSC_WIDE_SCSI)
+-                              cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F) << 1;
++/*-------- DATA OUT -----------*/
++              if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) {
++                      if (pCurHcb->HCS_ActTcs->TCS_JS_Period & TSC_WIDE_SCSI)
++                              cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F) << 1;
+                       else
+-                              cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F);
++                              cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F);
+               }
+-              if (inb(host->addr + TUL_XStatus) & XPEND) {    /* if DMA xfer is pending, abort DMA xfer */
+-                      outb(TAX_X_ABT, host->addr + TUL_XCmd);
++              if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {   /* if DMA xfer is pending, abort DMA xfer */
++                      TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT);
+                       /* wait Abort DMA xfer done */
+-                      while ((inb(host->addr + TUL_Int) & XABT) == 0)
+-                              cpu_relax();
++                      while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
++              }
++              if ((cnt == 1) && (pCurHcb->HCS_Phase == DATA_OUT)) {
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++                      if (wait_tulip(pCurHcb) == -1) {
++                              return (-1);
+                       }
+-              if ((cnt == 1) && (host->phase == DATA_OUT)) {
+-                      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-                      if (wait_tulip(host) == -1)
+-                              return -1;
+                       cnt = 0;
+               } else {
+-                      if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0)
+-                              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
++                      if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0)
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+               }
+       }
++
+       if (cnt == 0) {
+-              scb->buflen = 0;
+-              return 6;       /* After Data */
++              pCurScb->SCB_BufLen = 0;
++              return (6);     /* Go to state 6                */
+       }
+       /* Update active data pointer */
+-      xcnt = (long) scb->buflen - cnt;        /* xcnt== bytes already xferred */
+-      scb->buflen = (u32) cnt;                /* cnt == bytes left to be xferred */
+-      if (scb->flags & SCF_SG) {
+-              struct sg_entry *sgp;
+-              unsigned long i;
+-
+-              sgp = &scb->sglist[scb->sgidx];
+-              for (i = scb->sgidx; i < scb->sgmax; sgp++, i++) {
+-                      xcnt -= (long) sgp->len;
++      xcnt = (long) pCurScb->SCB_BufLen - cnt;        /* xcnt== bytes already xferred */
++      pCurScb->SCB_BufLen = (U32) cnt;        /* cnt == bytes left to be xferred */
++      if (pCurScb->SCB_Flags & SCF_SG) {
++              register SG *sgp;
++              ULONG i;
++
++              sgp = &pCurScb->SCB_SGList[pCurScb->SCB_SGIdx];
++              for (i = pCurScb->SCB_SGIdx; i < pCurScb->SCB_SGMax; sgp++, i++) {
++                      xcnt -= (long) sgp->SG_Len;
+                       if (xcnt < 0) {         /* this sgp xfer half done */
+-                              xcnt += (long) sgp->len;        /* xcnt == bytes xferred in this sgp */
+-                              sgp->data += (u32) xcnt;        /* new ptr to be xfer */
+-                              sgp->len -= (u32) xcnt; /* new len to be xfer */
+-                              scb->bufptr += ((u32) (i - scb->sgidx) << 3);
++                              xcnt += (long) sgp->SG_Len;     /* xcnt == bytes xferred in this sgp */
++                              sgp->SG_Ptr += (U32) xcnt;      /* new ptr to be xfer */
++                              sgp->SG_Len -= (U32) xcnt;      /* new len to be xfer */
++                              pCurScb->SCB_BufPtr += ((U32) (i - pCurScb->SCB_SGIdx) << 3);
+                               /* new SG table ptr */
+-                              scb->sglen = (u8) (scb->sgmax - i);
++                              pCurScb->SCB_SGLen = (BYTE) (pCurScb->SCB_SGMax - i);
+                               /* new SG table len */
+-                              scb->sgidx = (u16) i;
++                              pCurScb->SCB_SGIdx = (WORD) i;
+                               /* for next disc and come in this loop */
+-                              return 4;       /* Go to state 4                */
++                              return (4);     /* Go to state 4                */
+                       }
+                       /* else (xcnt >= 0 , i.e. this sgp already xferred */
+               }               /* for */
+-              return 6;       /* Go to state 6                */
++              return (6);     /* Go to state 6                */
+       } else {
+-              scb->bufptr += (u32) xcnt;
++              pCurScb->SCB_BufPtr += (U32) xcnt;
+       }
+-      return 4;               /* Go to state 4                */
++      return (4);             /* Go to state 4                */
  }
  
--static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
--{
--      u64 group = block - (u64) bit;
--
--      return group;
--}
+-/**
+- *    initio_state_6          -       SCSI state machine
+- *    @host: InitIO host we are controlling
+- *
+- *    State after Data phase
+- */
 -
- int ocfs2_free_dinode(handle_t *handle,
-                     struct inode *inode_alloc_inode,
-                     struct buffer_head *inode_alloc_bh,
-@@ -1723,19 +1702,6 @@
-                                       inode_alloc_bh, bit, bg_blkno, 1);
- }
+-static int initio_state_6(struct initio_host * host)
++/***************************************************************************/
++/* state after Data phase */
++int tul_state_6(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb = host->active;
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
  
--int ocfs2_free_extent_block(handle_t *handle,
--                          struct inode *eb_alloc_inode,
--                          struct buffer_head *eb_alloc_bh,
--                          struct ocfs2_extent_block *eb)
--{
--      u64 blk = le64_to_cpu(eb->h_blkno);
--      u16 bit = le16_to_cpu(eb->h_suballoc_bit);
--      u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit);
--
--      return ocfs2_free_suballoc_bits(handle, eb_alloc_inode, eb_alloc_bh,
--                                      bit, bg_blkno, 1);
--}
--
- int ocfs2_free_clusters(handle_t *handle,
-                      struct inode *bitmap_inode,
-                      struct buffer_head *bitmap_bh,
-diff -Nurb linux-2.6.22-570/fs/ocfs2/suballoc.h linux-2.6.22-590/fs/ocfs2/suballoc.h
---- linux-2.6.22-570/fs/ocfs2/suballoc.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/suballoc.h       2008-01-02 13:56:37.000000000 -0500
-@@ -86,20 +86,29 @@
-                        u32 *cluster_start,
-                        u32 *num_clusters);
+ #if DEBUG_STATE
+       printk("-s6-");
+ #endif
+       for (;;) {
+-              switch (host->phase) {
++              switch (pCurHcb->HCS_Phase) {
+               case STATUS_IN: /* Status phase                 */
+-                      if ((initio_status_msg(host)) == -1)
+-                              return -1;
++                      if ((tul_status_msg(pCurHcb)) == -1)
++                              return (-1);
+                       break;
  
-+int ocfs2_free_suballoc_bits(handle_t *handle,
-+                           struct inode *alloc_inode,
-+                           struct buffer_head *alloc_bh,
-+                           unsigned int start_bit,
-+                           u64 bg_blkno,
-+                           unsigned int count);
- int ocfs2_free_dinode(handle_t *handle,
-                     struct inode *inode_alloc_inode,
-                     struct buffer_head *inode_alloc_bh,
-                     struct ocfs2_dinode *di);
--int ocfs2_free_extent_block(handle_t *handle,
--                          struct inode *eb_alloc_inode,
--                          struct buffer_head *eb_alloc_bh,
--                          struct ocfs2_extent_block *eb);
- int ocfs2_free_clusters(handle_t *handle,
-                       struct inode *bitmap_inode,
-                       struct buffer_head *bitmap_bh,
-                       u64 start_blk,
-                       unsigned int num_clusters);
+               case MSG_IN:    /* Message in phase             */
+-                      scb->next_state = 6;
+-                      if ((initio_msgin(host)) == -1)
+-                              return -1;
++                      pCurScb->SCB_NxtStat = 6;
++                      if ((tul_msgin(pCurHcb)) == -1)
++                              return (-1);
+                       break;
  
-+static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
-+{
-+      u64 group = block - (u64) bit;
-+
-+      return group;
-+}
-+
- static inline u32 ocfs2_cluster_from_desc(struct ocfs2_super *osb,
-                                         u64 bg_blkno)
- {
-diff -Nurb linux-2.6.22-570/fs/ocfs2/super.c linux-2.6.22-590/fs/ocfs2/super.c
---- linux-2.6.22-570/fs/ocfs2/super.c  2008-01-02 13:56:30.000000000 -0500
-+++ linux-2.6.22-590/fs/ocfs2/super.c  2008-01-02 13:56:37.000000000 -0500
-@@ -82,7 +82,8 @@
- MODULE_LICENSE("GPL");
+               case MSG_OUT:   /* Message out phase            */
+-                      outb(MSG_NOP, host->addr + TUL_SFifo);          /* msg nop */
+-                      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-                      if (wait_tulip(host) == -1)
+-                              return -1;
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);         /* msg nop */
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++                      if (wait_tulip(pCurHcb) == -1)
++                              return (-1);
+                       break;
  
- static int ocfs2_parse_options(struct super_block *sb, char *options,
--                             unsigned long *mount_opt, int is_remount);
-+                             unsigned long *mount_opt, s16 *slot,
-+                             int is_remount);
- static void ocfs2_put_super(struct super_block *sb);
- static int ocfs2_mount_volume(struct super_block *sb);
- static int ocfs2_remount(struct super_block *sb, int *flags, char *data);
-@@ -114,8 +115,6 @@
- static struct inode *ocfs2_alloc_inode(struct super_block *sb);
- static void ocfs2_destroy_inode(struct inode *inode);
+               case DATA_IN:   /* Data in phase                */
+-                      return initio_xpad_in(host);
++                      return (tul_xpad_in(pCurHcb));
+               case DATA_OUT:  /* Data out phase               */
+-                      return initio_xpad_out(host);
++                      return (tul_xpad_out(pCurHcb));
+               default:
+-                      return initio_bad_seq(host);
++                      return (tul_bad_seq(pCurHcb));
+               }
+       }
+ }
  
--static unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
+-/**
+- *    initio_state_7          -       SCSI state machine
+- *    @host: InitIO host we are controlling
+- *
+- */
 -
- static const struct super_operations ocfs2_sops = {
-       .statfs         = ocfs2_statfs,
-       .alloc_inode    = ocfs2_alloc_inode,
-@@ -323,7 +322,7 @@
- /* From xfs_super.c:xfs_max_file_offset
-  * Copyright (c) 2000-2004 Silicon Graphics, Inc.
-  */
--static unsigned long long ocfs2_max_file_offset(unsigned int blockshift)
-+unsigned long long ocfs2_max_file_offset(unsigned int blockshift)
+-int initio_state_7(struct initio_host * host)
++/***************************************************************************/
++int tul_state_7(HCS * pCurHcb)
  {
-       unsigned int pagefactor = 1;
-       unsigned int bitshift = BITS_PER_LONG - 1;
-@@ -360,9 +359,10 @@
-       int incompat_features;
-       int ret = 0;
-       unsigned long parsed_options;
-+      s16 slot;
-       struct ocfs2_super *osb = OCFS2_SB(sb);
+       int cnt, i;
  
--      if (!ocfs2_parse_options(sb, data, &parsed_options, 1)) {
-+      if (!ocfs2_parse_options(sb, data, &parsed_options, &slot, 1)) {
-               ret = -EINVAL;
-               goto out;
+@@ -1678,1029 +1893,1139 @@
+       printk("-s7-");
+ #endif
+       /* flush SCSI FIFO */
+-      cnt = inb(host->addr + TUL_SFifoCnt) & 0x1F;
++      cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F;
+       if (cnt) {
+               for (i = 0; i < cnt; i++)
+-                      inb(host->addr + TUL_SFifo);
++                      TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
        }
-@@ -546,6 +546,7 @@
-       struct dentry *root;
-       int status, sector_size;
-       unsigned long parsed_opt;
-+      s16 slot;
-       struct inode *inode = NULL;
-       struct ocfs2_super *osb = NULL;
-       struct buffer_head *bh = NULL;
-@@ -553,7 +554,7 @@
-       mlog_entry("%p, %p, %i", sb, data, silent);
+-      switch (host->phase) {
++      switch (pCurHcb->HCS_Phase) {
+       case DATA_IN:           /* Data in phase                */
+       case DATA_OUT:          /* Data out phase               */
+-              return initio_bad_seq(host);
++              return (tul_bad_seq(pCurHcb));
+       default:
+-              return 6;       /* Go to state 6                */
++              return (6);     /* Go to state 6                */
+       }
+ }
  
--      if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
-+      if (!ocfs2_parse_options(sb, data, &parsed_opt, &slot, 0)) {
-               status = -EINVAL;
-               goto read_super_error;
+-/**
+- *    initio_xfer_data_in     -       Commence data input
+- *    @host: InitIO host in use
+- *
+- *    Commence a block of data transfer. The transfer itself will
+- *    be managed by the controller and we will get a completion (or
+- *    failure) interrupt.
+- */
+-static int initio_xfer_data_in(struct initio_host * host)
++/***************************************************************************/
++int tul_xfer_data_in(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb = host->active;
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
+-      if ((scb->flags & SCF_DIR) == SCF_DOUT)
+-              return 6;       /* wrong direction */
++      if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) {
++              return (6);     /* wrong direction */
++      }
++      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
+-      outl(scb->buflen, host->addr + TUL_SCnt0);
+-      outb(TSC_XF_DMA_IN, host->addr + TUL_SCmd);     /* 7/25/95 */
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_IN);    /* 7/25/95 */
+-      if (scb->flags & SCF_SG) {      /* S/G xfer */
+-              outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);
+-              outl(scb->bufptr, host->addr + TUL_XAddH);
+-              outb(TAX_SG_IN, host->addr + TUL_XCmd);
++      if (pCurScb->SCB_Flags & SCF_SG) {      /* S/G xfer */
++              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
++              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
++              TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_IN);
+       } else {
+-              outl(scb->buflen, host->addr + TUL_XCntH);
+-              outl(scb->bufptr, host->addr + TUL_XAddH);
+-              outb(TAX_X_IN, host->addr + TUL_XCmd);
++              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
++              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
++              TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_IN);
        }
-@@ -583,6 +584,7 @@
-       brelse(bh);
-       bh = NULL;
-       osb->s_mount_opt = parsed_opt;
-+      osb->preferred_slot = slot;
+-      scb->next_state = 0x5;
+-      return 0;               /* return to OS, wait xfer done , let jas_isr come in */
++      pCurScb->SCB_NxtStat = 0x5;
++      return (0);             /* return to OS, wait xfer done , let jas_isr come in */
+ }
  
-       sb->s_magic = OCFS2_SUPER_MAGIC;
+-/**
+- *    initio_xfer_data_out    -       Commence data output
+- *    @host: InitIO host in use
+- *
+- *    Commence a block of data transfer. The transfer itself will
+- *    be managed by the controller and we will get a completion (or
+- *    failure) interrupt.
+- */
  
-@@ -728,6 +730,7 @@
- static int ocfs2_parse_options(struct super_block *sb,
-                              char *options,
-                              unsigned long *mount_opt,
-+                             s16 *slot,
-                              int is_remount)
+-static int initio_xfer_data_out(struct initio_host * host)
++/***************************************************************************/
++int tul_xfer_data_out(HCS * pCurHcb)
  {
-       int status;
-@@ -737,6 +740,7 @@
-                  options ? options : "(none)");
-       *mount_opt = 0;
-+      *slot = OCFS2_INVALID_SLOT;
-       if (!options) {
-               status = 1;
-diff -Nurb linux-2.6.22-570/fs/ocfs2/super.h linux-2.6.22-590/fs/ocfs2/super.h
---- linux-2.6.22-570/fs/ocfs2/super.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ocfs2/super.h  2008-01-02 13:56:37.000000000 -0500
-@@ -45,4 +45,6 @@
- #define ocfs2_abort(sb, fmt, args...) __ocfs2_abort(sb, __PRETTY_FUNCTION__, fmt, ##args)
-+unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
-+
- #endif /* OCFS2_SUPER_H */
-diff -Nurb linux-2.6.22-570/fs/open.c linux-2.6.22-590/fs/open.c
---- linux-2.6.22-570/fs/open.c 2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/open.c 2008-01-02 13:56:37.000000000 -0500
-@@ -362,6 +362,92 @@
- #endif
+-      struct scsi_ctrl_blk *scb = host->active;
+-
+-      if ((scb->flags & SCF_DIR) == SCF_DIN)
+-              return 6;       /* wrong direction */
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
  
- /*
-+ * sys_fallocate - preallocate blocks or free preallocated blocks
-+ * @fd: the file descriptor
-+ * @mode: mode specifies if fallocate should preallocate blocks OR free
-+ *      (unallocate) preallocated blocks. Currently only FA_ALLOCATE and
-+ *      FA_DEALLOCATE modes are supported.
-+ * @offset: The offset within file, from where (un)allocation is being
-+ *        requested. It should not have a negative value.
-+ * @len: The amount (in bytes) of space to be (un)allocated, from the offset.
-+ *
-+ * This system call, depending on the mode, preallocates or unallocates blocks
-+ * for a file. The range of blocks depends on the value of offset and len
-+ * arguments provided by the user/application. For FA_ALLOCATE mode, if this
-+ * system call succeeds, subsequent writes to the file in the given range
-+ * (specified by offset & len) should not fail - even if the file system
-+ * later becomes full. Hence the preallocation done is persistent (valid
-+ * even after reopen of the file and remount/reboot).
-+ *
-+ * It is expected that the ->fallocate() inode operation implemented by the
-+ * individual file systems will update the file size and/or ctime/mtime
-+ * depending on the mode and also on the success of the operation.
-+ *
-+ * Note: Incase the file system does not support preallocation,
-+ * posix_fallocate() should fall back to the library implementation (i.e.
-+ * allocating zero-filled new blocks to the file).
-+ *
-+ * Return Values
-+ *    0       : On SUCCESS a value of zero is returned.
-+ *    error   : On Failure, an error code will be returned.
-+ * An error code of -ENOSYS or -EOPNOTSUPP should make posix_fallocate()
-+ * fall back on library implementation of fallocate.
-+ *
-+ * <TBD> Generic fallocate to be added for file systems that do not
-+ *     support fallocate it.
-+ */
-+asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len)
-+{
-+      struct file *file;
-+      struct inode *inode;
-+      long ret = -EINVAL;
-+
-+      if (offset < 0 || len <= 0)
-+              goto out;
-+
-+      /* Return error if mode is not supported */
-+      ret = -EOPNOTSUPP;
-+      if (mode != FA_ALLOCATE && mode !=FA_DEALLOCATE)
-+              goto out;
-+
-+      ret = -EBADF;
-+      file = fget(fd);
-+      if (!file)
-+              goto out;
-+      if (!(file->f_mode & FMODE_WRITE))
-+              goto out_fput;
-+
-+      inode = file->f_path.dentry->d_inode;
-+
-+      ret = -ESPIPE;
-+      if (S_ISFIFO(inode->i_mode))
-+              goto out_fput;
-+
-+      ret = -ENODEV;
-+      /*
-+       * Let individual file system decide if it supports preallocation
-+       * for directories or not.
-+       */
-+      if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
-+              goto out_fput;
-+
-+      ret = -EFBIG;
-+      /* Check for wrap through zero too */
-+      if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
-+              goto out_fput;
-+
-+      if (inode->i_op && inode->i_op->fallocate)
-+              ret = inode->i_op->fallocate(inode, mode, offset, len);
-+      else
-+              ret = -ENOSYS;
-+
-+out_fput:
-+      fput(file);
-+out:
-+      return ret;
-+}
-+
-+/*
-  * access() needs to use the real uid/gid, not the effective uid/gid.
-  * We do this by temporarily clearing all FS-related capabilities and
-  * switching the fsuid/fsgid around to the real ones.
-diff -Nurb linux-2.6.22-570/fs/partitions/check.c linux-2.6.22-590/fs/partitions/check.c
---- linux-2.6.22-570/fs/partitions/check.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/partitions/check.c     2008-01-02 13:56:37.000000000 -0500
-@@ -397,7 +397,6 @@
-               static struct attribute addpartattr = {
-                       .name = "whole_disk",
-                       .mode = S_IRUSR | S_IRGRP | S_IROTH,
--                      .owner = THIS_MODULE,
-               };
+-      outl(scb->buflen, host->addr + TUL_SCnt0);
+-      outb(TSC_XF_DMA_OUT, host->addr + TUL_SCmd);
++      if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) {
++              return (6);     /* wrong direction */
++      }
++      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_OUT);
  
-               sysfs_create_file(&p->kobj, &addpartattr);
-diff -Nurb linux-2.6.22-570/fs/proc/Makefile linux-2.6.22-590/fs/proc/Makefile
---- linux-2.6.22-570/fs/proc/Makefile  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/proc/Makefile  2008-01-02 13:56:37.000000000 -0500
-@@ -11,6 +11,7 @@
-               proc_tty.o proc_misc.o
+-      if (scb->flags & SCF_SG) {      /* S/G xfer */
+-              outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);
+-              outl(scb->bufptr, host->addr + TUL_XAddH);
+-              outb(TAX_SG_OUT, host->addr + TUL_XCmd);
++      if (pCurScb->SCB_Flags & SCF_SG) {      /* S/G xfer */
++              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
++              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
++              TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_OUT);
+       } else {
+-              outl(scb->buflen, host->addr + TUL_XCntH);
+-              outl(scb->bufptr, host->addr + TUL_XAddH);
+-              outb(TAX_X_OUT, host->addr + TUL_XCmd);
++              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
++              TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
++              TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_OUT);
+       }
  
- proc-$(CONFIG_PROC_SYSCTL)    += proc_sysctl.o
-+proc-$(CONFIG_NET)            += proc_net.o
- proc-$(CONFIG_PROC_KCORE)     += kcore.o
- proc-$(CONFIG_PROC_VMCORE)    += vmcore.o
- proc-$(CONFIG_PROC_DEVICETREE)        += proc_devtree.o
-diff -Nurb linux-2.6.22-570/fs/proc/array.c linux-2.6.22-590/fs/proc/array.c
---- linux-2.6.22-570/fs/proc/array.c   2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/proc/array.c   2008-01-02 13:56:37.000000000 -0500
-@@ -291,6 +291,15 @@
-       return buffer;
+-      scb->next_state = 0x5;
+-      return 0;               /* return to OS, wait xfer done , let jas_isr come in */
++      pCurScb->SCB_NxtStat = 0x5;
++      return (0);             /* return to OS, wait xfer done , let jas_isr come in */
  }
  
-+static inline char *task_context_switch_counts(struct task_struct *p,
-+                                              char *buffer)
-+{
-+      return buffer + sprintf(buffer, "voluntary_ctxt_switches:\t%lu\n"
-+                          "nonvoluntary_ctxt_switches:\t%lu\n",
-+                          p->nvcsw,
-+                          p->nivcsw);
-+}
+-int initio_xpad_in(struct initio_host * host)
 +
- static inline char *task_cap(struct task_struct *p, char *buffer)
++/***************************************************************************/
++int tul_xpad_in(HCS * pCurHcb)
  {
-       struct vx_info *vxi = p->vx_info;
-@@ -328,6 +337,7 @@
- #if defined(CONFIG_S390)
-       buffer = task_show_regs(task, buffer);
- #endif
-+      buffer = task_context_switch_counts(task, buffer);
-       return buffer - orig;
- }
+-      struct scsi_ctrl_blk *scb = host->active;
+-      struct target_control *active_tc = host->active_tc;
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
++      TCS *pCurTcb = pCurHcb->HCS_ActTcs;
  
-@@ -426,8 +436,9 @@
+-      if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)
+-              scb->hastat = HOST_DO_DU;       /* over run             */
++      if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
++              pCurScb->SCB_HaStat = HOST_DO_DU;       /* over run             */
++      }
+       for (;;) {
+-              if (active_tc->js_period & TSC_WIDE_SCSI)
+-                      outl(2, host->addr + TUL_SCnt0);
++              if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
++                      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
+               else
+-                      outl(1, host->addr + TUL_SCnt0);
++                      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+-              outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+-              if (wait_tulip(host) == -1)
+-                      return -1;
+-              if (host->phase != DATA_IN) {
+-                      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+-                      return 6;
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
++              if ((wait_tulip(pCurHcb)) == -1) {
++                      return (-1);
+               }
+-              inb(host->addr + TUL_SFifo);
++              if (pCurHcb->HCS_Phase != DATA_IN) {
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
++                      return (6);
++              }
++              TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+       }
+ }
  
-       /* Temporary variable needed for gcc-2.96 */
-       /* convert timespec -> nsec*/
--      start_time = (unsigned long long)task->start_time.tv_sec * NSEC_PER_SEC
--                              + task->start_time.tv_nsec;
-+      start_time =
-+              (unsigned long long)task->real_start_time.tv_sec * NSEC_PER_SEC
-+                              + task->real_start_time.tv_nsec;
-       /* convert nsec -> ticks */
-       start_time = nsec_to_clock_t(start_time);
+-int initio_xpad_out(struct initio_host * host)
++int tul_xpad_out(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb = host->active;
+-      struct target_control *active_tc = host->active_tc;
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
++      TCS *pCurTcb = pCurHcb->HCS_ActTcs;
  
-diff -Nurb linux-2.6.22-570/fs/proc/base.c linux-2.6.22-590/fs/proc/base.c
---- linux-2.6.22-570/fs/proc/base.c    2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/proc/base.c    2008-01-02 13:56:37.000000000 -0500
-@@ -67,7 +67,7 @@
- #include <linux/mount.h>
- #include <linux/security.h>
- #include <linux/ptrace.h>
--#include <linux/seccomp.h>
-+#include <linux/container.h>
- #include <linux/cpuset.h>
- #include <linux/audit.h>
- #include <linux/poll.h>
-@@ -490,7 +490,7 @@
-               count = PROC_BLOCK_SIZE;
+-      if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)
+-              scb->hastat = HOST_DO_DU;       /* over run             */
++      if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
++              pCurScb->SCB_HaStat = HOST_DO_DU;       /* over run             */
++      }
+       for (;;) {
+-              if (active_tc->js_period & TSC_WIDE_SCSI)
+-                      outl(2, host->addr + TUL_SCnt0);
++              if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
++                      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
+               else
+-                      outl(1, host->addr + TUL_SCnt0);
++                      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+-              outb(0, host->addr + TUL_SFifo);
+-              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-              if ((wait_tulip(host)) == -1)
+-                      return -1;
+-              if (host->phase != DATA_OUT) {  /* Disable wide CPU to allow read 16 bits */
+-                      outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);
+-                      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+-                      return 6;
++              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++              if ((wait_tulip(pCurHcb)) == -1) {
++                      return (-1);
++              }
++              if (pCurHcb->HCS_Phase != DATA_OUT) {   /* Disable wide CPU to allow read 16 bits */
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
++                      return (6);
+               }
+       }
+ }
  
-       length = -ENOMEM;
--      if (!(page = __get_free_page(GFP_KERNEL)))
-+      if (!(page = __get_free_page(GFP_TEMPORARY)))
-               goto out;
+-int initio_status_msg(struct initio_host * host)
+-{                             /* status & MSG_IN */
+-      struct scsi_ctrl_blk *scb = host->active;
+-      u8 msg;
  
-       length = PROC_I(inode)->op.proc_read(task, (char*)page);
-@@ -530,7 +530,7 @@
-               goto out;
+-      outb(TSC_CMD_COMP, host->addr + TUL_SCmd);
+-      if (wait_tulip(host) == -1)
+-              return -1;
++/***************************************************************************/
++int tul_status_msg(HCS * pCurHcb)
++{                             /* status & MSG_IN */
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
++      BYTE msg;
  
-       ret = -ENOMEM;
--      page = (char *)__get_free_page(GFP_USER);
-+      page = (char *)__get_free_page(GFP_TEMPORARY);
-       if (!page)
-               goto out;
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_CMD_COMP);
++      if ((wait_tulip(pCurHcb)) == -1) {
++              return (-1);
++      }
+       /* get status */
+-      scb->tastat = inb(host->addr + TUL_SFifo);
++      pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
  
-@@ -600,7 +600,7 @@
-               goto out;
+-      if (host->phase == MSG_OUT) {
+-              if (host->jsstatus0 & TSS_PAR_ERROR)
+-                      outb(MSG_PARITY, host->addr + TUL_SFifo);
+-              else
+-                      outb(MSG_NOP, host->addr + TUL_SFifo);
+-              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-              return wait_tulip(host);
+-      }
+-      if (host->phase == MSG_IN) {
+-              msg = inb(host->addr + TUL_SFifo);
+-              if (host->jsstatus0 & TSS_PAR_ERROR) {  /* Parity error                 */
+-                      if ((initio_msgin_accept(host)) == -1)
+-                              return -1;
+-                      if (host->phase != MSG_OUT)
+-                              return initio_bad_seq(host);
+-                      outb(MSG_PARITY, host->addr + TUL_SFifo);
+-                      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-                      return wait_tulip(host);
++      if (pCurHcb->HCS_Phase == MSG_OUT) {
++              if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
++              } else {
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);
++              }
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++              return (wait_tulip(pCurHcb));
++      }
++      if (pCurHcb->HCS_Phase == MSG_IN) {
++              msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
++              if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {   /* Parity error                 */
++                      if ((tul_msgin_accept(pCurHcb)) == -1)
++                              return (-1);
++                      if (pCurHcb->HCS_Phase != MSG_OUT)
++                              return (tul_bad_seq(pCurHcb));
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++                      return (wait_tulip(pCurHcb));
+               }
+               if (msg == 0) { /* Command complete             */
  
-       copied = -ENOMEM;
--      page = (char *)__get_free_page(GFP_USER);
-+      page = (char *)__get_free_page(GFP_TEMPORARY);
-       if (!page)
-               goto out;
+-                      if ((scb->tastat & 0x18) == 0x10)       /* No link support              */
+-                              return initio_bad_seq(host);
+-                      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+-                      outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
+-                      return initio_wait_done_disc(host);
++                      if ((pCurScb->SCB_TaStat & 0x18) == 0x10) {     /* No link support              */
++                              return (tul_bad_seq(pCurHcb));
++                      }
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
++                      return tul_wait_done_disc(pCurHcb);
  
-@@ -633,7 +633,7 @@
+               }
+-              if (msg == MSG_LINK_COMP || msg == MSG_LINK_FLAG) {
+-                      if ((scb->tastat & 0x18) == 0x10)
+-                              return initio_msgin_accept(host);
++              if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) {
++                      if ((pCurScb->SCB_TaStat & 0x18) == 0x10)
++                              return (tul_msgin_accept(pCurHcb));
+               }
+       }
+-      return initio_bad_seq(host);
++      return (tul_bad_seq(pCurHcb));
  }
- #endif
  
--static loff_t mem_lseek(struct file * file, loff_t offset, int orig)
-+loff_t mem_lseek(struct file * file, loff_t offset, int orig)
- {
-       switch (orig) {
-       case 0:
-@@ -711,42 +711,6 @@
-       .write          = oom_adjust_write,
- };
  
--#ifdef CONFIG_MMU
--static ssize_t clear_refs_write(struct file *file, const char __user *buf,
--                              size_t count, loff_t *ppos)
--{
--      struct task_struct *task;
--      char buffer[PROC_NUMBUF], *end;
--      struct mm_struct *mm;
--
--      memset(buffer, 0, sizeof(buffer));
--      if (count > sizeof(buffer) - 1)
--              count = sizeof(buffer) - 1;
--      if (copy_from_user(buffer, buf, count))
--              return -EFAULT;
--      if (!simple_strtol(buffer, &end, 0))
--              return -EINVAL;
--      if (*end == '\n')
--              end++;
--      task = get_proc_task(file->f_path.dentry->d_inode);
--      if (!task)
--              return -ESRCH;
--      mm = get_task_mm(task);
--      if (mm) {
--              clear_refs_smap(mm);
--              mmput(mm);
++/***************************************************************************/
+ /* scsi bus free */
+-int int_initio_busfree(struct initio_host * host)
++int int_tul_busfree(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb = host->active;
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
+-      if (scb != NULL) {
+-              if (scb->status & SCB_SELECT) {         /* selection timeout */
+-                      initio_unlink_pend_scb(host, scb);
+-                      scb->hastat = HOST_SEL_TOUT;
+-                      initio_append_done_scb(host, scb);
++      if (pCurScb != NULL) {
++              if (pCurScb->SCB_Status & SCB_SELECT) {         /* selection timeout */
++                      tul_unlink_pend_scb(pCurHcb, pCurScb);
++                      pCurScb->SCB_HaStat = HOST_SEL_TOUT;
++                      tul_append_done_scb(pCurHcb, pCurScb);
+               } else {        /* Unexpected bus free          */
+-                      initio_unlink_busy_scb(host, scb);
+-                      scb->hastat = HOST_BUS_FREE;
+-                      initio_append_done_scb(host, scb);
+-              }
+-              host->active = NULL;
+-              host->active_tc = NULL;
 -      }
--      put_task_struct(task);
--      if (end - buffer == 0)
--              return -EIO;
--      return end - buffer;
--}
--
--static struct file_operations proc_clear_refs_operations = {
--      .write          = clear_refs_write,
--};
--#endif
--
- #ifdef CONFIG_AUDITSYSCALL
- #define TMPBUFLEN 21
- static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
-@@ -786,7 +750,7 @@
-               /* No partial writes. */
-               return -EINVAL;
-       }
--      page = (char*)__get_free_page(GFP_USER);
-+      page = (char*)__get_free_page(GFP_TEMPORARY);
-       if (!page)
-               return -ENOMEM;
-       length = -EFAULT;
-@@ -815,71 +779,6 @@
- };
- #endif
+-      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);          /* Flush SCSI FIFO  */
+-      outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+-      outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect       */
+-      return -1;
++                      tul_unlink_busy_scb(pCurHcb, pCurScb);
++                      pCurScb->SCB_HaStat = HOST_BUS_FREE;
++                      tul_append_done_scb(pCurHcb, pCurScb);
++              }
++              pCurHcb->HCS_ActScb = NULL;
++              pCurHcb->HCS_ActTcs = NULL;
++      }
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);         /* Flush SCSI FIFO  */
++      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);        /* Enable HW reselect       */
++      return (-1);
+ }
  
--#ifdef CONFIG_SECCOMP
--static ssize_t seccomp_read(struct file *file, char __user *buf,
--                          size_t count, loff_t *ppos)
--{
--      struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
--      char __buf[20];
--      size_t len;
--
--      if (!tsk)
--              return -ESRCH;
--      /* no need to print the trailing zero, so use only len */
--      len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
--      put_task_struct(tsk);
--
--      return simple_read_from_buffer(buf, count, ppos, __buf, len);
--}
--
--static ssize_t seccomp_write(struct file *file, const char __user *buf,
--                           size_t count, loff_t *ppos)
--{
--      struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
--      char __buf[20], *end;
--      unsigned int seccomp_mode;
--      ssize_t result;
--
--      result = -ESRCH;
--      if (!tsk)
--              goto out_no_task;
--
--      /* can set it only once to be even more secure */
--      result = -EPERM;
--      if (unlikely(tsk->seccomp.mode))
--              goto out;
--
--      result = -EFAULT;
--      memset(__buf, 0, sizeof(__buf));
--      count = min(count, sizeof(__buf) - 1);
--      if (copy_from_user(__buf, buf, count))
--              goto out;
--
--      seccomp_mode = simple_strtoul(__buf, &end, 0);
--      if (*end == '\n')
--              end++;
--      result = -EINVAL;
--      if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
--              tsk->seccomp.mode = seccomp_mode;
--              set_tsk_thread_flag(tsk, TIF_SECCOMP);
--      } else
--              goto out;
--      result = -EIO;
--      if (unlikely(!(end - __buf)))
--              goto out;
--      result = end - __buf;
--out:
--      put_task_struct(tsk);
--out_no_task:
--      return result;
--}
--
--static const struct file_operations proc_seccomp_operations = {
--      .read           = seccomp_read,
--      .write          = seccomp_write,
--};
--#endif /* CONFIG_SECCOMP */
+-/**
+- *    int_initio_scsi_rst     -       SCSI reset occurred
+- *    @host: Host seeing the reset
+- *
+- *    A SCSI bus reset has occurred. Clean up any pending transfer
+- *    the hardware is doing by DMA and then abort all active and
+- *    disconnected commands. The mid layer should sort the rest out
+- *    for us
+- */
 -
- #ifdef CONFIG_FAULT_INJECTION
- static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
-                                     size_t count, loff_t *ppos)
-@@ -954,7 +853,8 @@
-                           char __user *buffer, int buflen)
+-static int int_initio_scsi_rst(struct initio_host * host)
++/***************************************************************************/
++/* scsi bus reset */
++static int int_tul_scsi_rst(HCS * pCurHcb)
  {
-       struct inode * inode;
--      char *tmp = (char*)__get_free_page(GFP_KERNEL), *path;
-+      char *tmp = (char*)__get_free_page(GFP_TEMPORARY);
-+      char *path;
-       int len;
-       if (!tmp)
-@@ -1015,7 +915,7 @@
-       task_lock(task);
-       mm = task->mm;
-       if (mm)
--              dumpable = mm->dumpable;
-+              dumpable = get_dumpable(mm);
-       task_unlock(task);
-       if(dumpable == 1)
-               return 1;
-@@ -1744,7 +1644,7 @@
-               goto out;
+-      struct scsi_ctrl_blk *scb;
++      SCB *pCurScb;
+       int i;
  
-       length = -ENOMEM;
--      page = (char*)__get_free_page(GFP_USER);
-+      page = (char*)__get_free_page(GFP_TEMPORARY);
-       if (!page)
-               goto out;
+       /* if DMA xfer is pending, abort DMA xfer */
+-      if (inb(host->addr + TUL_XStatus) & 0x01) {
+-              outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);
++      if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) {
++              TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
+               /* wait Abort DMA xfer done */
+-              while ((inb(host->addr + TUL_Int) & 0x04) == 0)
+-                      cpu_relax();
+-              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
++              while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+       }
+       /* Abort all active & disconnected scb */
+-      while ((scb = initio_pop_busy_scb(host)) != NULL) {
+-              scb->hastat = HOST_BAD_PHAS;
+-              initio_append_done_scb(host, scb);
++      while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
++              pCurScb->SCB_HaStat = HOST_BAD_PHAS;
++              tul_append_done_scb(pCurHcb, pCurScb);
+       }
+-      host->active = NULL;
+-      host->active_tc = NULL;
++      pCurHcb->HCS_ActScb = NULL;
++      pCurHcb->HCS_ActTcs = NULL;
  
-@@ -1804,6 +1704,91 @@
+       /* clr sync nego. done flag */
+-      for (i = 0; i < host->max_tar; i++)
+-              host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+-      return -1;
++      for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
++              pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
++      }
++      return (-1);
+ }
  
- #endif
+-/**
+- *    int_initio_scsi_resel   -       Reselection occured
+- *    @host: InitIO host adapter
+- *
+- *    A SCSI reselection event has been signalled and the interrupt
+- *    is now being processed. Work out which command block needs attention
+- *    and continue processing that command.
+- */
  
-+#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
-+static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf,
-+                                       size_t count, loff_t *ppos)
-+{
-+      struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
-+      struct mm_struct *mm;
-+      char buffer[PROC_NUMBUF];
-+      size_t len;
-+      int ret;
-+
-+      if (!task)
-+              return -ESRCH;
-+
-+      ret = 0;
-+      mm = get_task_mm(task);
-+      if (mm) {
-+              len = snprintf(buffer, sizeof(buffer), "%08lx\n",
-+                             ((mm->flags & MMF_DUMP_FILTER_MASK) >>
-+                              MMF_DUMP_FILTER_SHIFT));
-+              mmput(mm);
-+              ret = simple_read_from_buffer(buf, count, ppos, buffer, len);
-+      }
-+
-+      put_task_struct(task);
-+
-+      return ret;
-+}
-+
-+static ssize_t proc_coredump_filter_write(struct file *file,
-+                                        const char __user *buf,
-+                                        size_t count,
-+                                        loff_t *ppos)
-+{
-+      struct task_struct *task;
-+      struct mm_struct *mm;
-+      char buffer[PROC_NUMBUF], *end;
-+      unsigned int val;
-+      int ret;
-+      int i;
-+      unsigned long mask;
-+
-+      ret = -EFAULT;
-+      memset(buffer, 0, sizeof(buffer));
-+      if (count > sizeof(buffer) - 1)
-+              count = sizeof(buffer) - 1;
-+      if (copy_from_user(buffer, buf, count))
-+              goto out_no_task;
-+
-+      ret = -EINVAL;
-+      val = (unsigned int)simple_strtoul(buffer, &end, 0);
-+      if (*end == '\n')
-+              end++;
-+      if (end - buffer == 0)
-+              goto out_no_task;
-+
-+      ret = -ESRCH;
-+      task = get_proc_task(file->f_dentry->d_inode);
-+      if (!task)
-+              goto out_no_task;
-+
-+      ret = end - buffer;
-+      mm = get_task_mm(task);
-+      if (!mm)
-+              goto out_no_mm;
-+
-+      for (i = 0, mask = 1; i < MMF_DUMP_FILTER_BITS; i++, mask <<= 1) {
-+              if (val & mask)
-+                      set_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);
-+              else
-+                      clear_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);
-+      }
-+
-+      mmput(mm);
-+ out_no_mm:
-+      put_task_struct(task);
-+ out_no_task:
-+      return ret;
-+}
-+
-+static const struct file_operations proc_coredump_filter_operations = {
-+      .read           = proc_coredump_filter_read,
-+      .write          = proc_coredump_filter_write,
-+};
-+#endif
+-int int_initio_resel(struct initio_host * host)
++/***************************************************************************/
++/* scsi reselection */
++int int_tul_resel(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb;
+-      struct target_control *active_tc;
+-      u8 tag, msg = 0;
+-      u8 tar, lun;
+-
+-      if ((scb = host->active) != NULL) {
+-              /* FIXME: Why check and not just clear ? */
+-              if (scb->status & SCB_SELECT)           /* if waiting for selection complete */
+-                      scb->status &= ~SCB_SELECT;
+-              host->active = NULL;
++      SCB *pCurScb;
++      TCS *pCurTcb;
++      BYTE tag, msg = 0;
++      BYTE tar, lun;
++
++      if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
++              if (pCurScb->SCB_Status & SCB_SELECT) {         /* if waiting for selection complete */
++                      pCurScb->SCB_Status &= ~SCB_SELECT;
++              }
++              pCurHcb->HCS_ActScb = NULL;
+       }
+       /* --------- get target id---------------------- */
+-      tar = inb(host->addr + TUL_SBusId);
++      tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId);
+       /* ------ get LUN from Identify message----------- */
+-      lun = inb(host->addr + TUL_SIdent) & 0x0F;
++      lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F;
+       /* 07/22/98 from 0x1F -> 0x0F */
+-      active_tc = &host->targets[tar];
+-      host->active_tc = active_tc;
+-      outb(active_tc->sconfig0, host->addr + TUL_SConfig);
+-      outb(active_tc->js_period, host->addr + TUL_SPeriod);
++      pCurTcb = &pCurHcb->HCS_Tcs[tar];
++      pCurHcb->HCS_ActTcs = pCurTcb;
++      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
 +
- /*
-  * /proc/self:
-  */
-@@ -1995,18 +1980,22 @@
-       REG("numa_maps",  S_IRUGO, numa_maps),
- #endif
-       REG("mem",        S_IRUSR|S_IWUSR, mem),
--#ifdef CONFIG_SECCOMP
--      REG("seccomp",    S_IRUSR|S_IWUSR, seccomp),
--#endif
-       LNK("cwd",        cwd),
-       LNK("root",       root),
-       LNK("exe",        exe),
-       REG("mounts",     S_IRUGO, mounts),
-       REG("mountstats", S_IRUSR, mountstats),
- #ifdef CONFIG_MMU
-+#ifdef CONFIG_PROC_CLEAR_REFS
-       REG("clear_refs", S_IWUSR, clear_refs),
-+#endif
-+#ifdef CONFIG_PROC_SMAPS
-       REG("smaps",      S_IRUGO, smaps),
- #endif
-+#ifdef CONFIG_PROC_PAGEMAP
-+      REG("pagemap",    S_IRUSR, pagemap),
-+#endif
-+#endif
- #ifdef CONFIG_SECURITY
-       DIR("attr",       S_IRUGO|S_IXUGO, attr_dir),
- #endif
-@@ -2016,7 +2005,7 @@
- #ifdef CONFIG_SCHEDSTATS
-       INF("schedstat",  S_IRUGO, pid_schedstat),
- #endif
--#ifdef CONFIG_CPUSETS
-+#ifdef CONFIG_PROC_PID_CPUSET
-       REG("cpuset",     S_IRUGO, cpuset),
- #endif
-       INF("vinfo",      S_IRUGO, pid_vx_info),
-@@ -2029,6 +2018,9 @@
- #ifdef CONFIG_FAULT_INJECTION
-       REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
- #endif
-+#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
-+      REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter),
-+#endif
- #ifdef CONFIG_TASK_IO_ACCOUNTING
-       INF("io",       S_IRUGO, pid_io_accounting),
- #endif
-@@ -2285,17 +2277,21 @@
-       REG("numa_maps", S_IRUGO, numa_maps),
- #endif
-       REG("mem",       S_IRUSR|S_IWUSR, mem),
--#ifdef CONFIG_SECCOMP
--      REG("seccomp",   S_IRUSR|S_IWUSR, seccomp),
--#endif
-       LNK("cwd",       cwd),
-       LNK("root",      root),
-       LNK("exe",       exe),
-       REG("mounts",    S_IRUGO, mounts),
- #ifdef CONFIG_MMU
-+#ifdef CONFIG_PROC_CLEAR_REFS
-       REG("clear_refs", S_IWUSR, clear_refs),
-+#endif
-+#ifdef CONFIG_PROC_SMAPS
-       REG("smaps",     S_IRUGO, smaps),
- #endif
-+#ifdef CONFIG_PROC_PAGEMAP
-+      REG("pagemap",    S_IRUSR, pagemap),
-+#endif
-+#endif
- #ifdef CONFIG_SECURITY
-       DIR("attr",      S_IRUGO|S_IXUGO, attr_dir),
- #endif
-@@ -2305,9 +2301,12 @@
- #ifdef CONFIG_SCHEDSTATS
-       INF("schedstat", S_IRUGO, pid_schedstat),
- #endif
--#ifdef CONFIG_CPUSETS
-+#ifdef CONFIG_PROC_PID_CPUSET
-       REG("cpuset",    S_IRUGO, cpuset),
- #endif
-+#ifdef CONFIG_CONTAINERS
-+      REG("container",  S_IRUGO, container),
-+#endif
-       INF("oom_score", S_IRUGO, oom_score),
-       REG("oom_adj",   S_IRUGO|S_IWUSR, oom_adjust),
- #ifdef CONFIG_AUDITSYSCALL
-diff -Nurb linux-2.6.22-570/fs/proc/generic.c linux-2.6.22-590/fs/proc/generic.c
---- linux-2.6.22-570/fs/proc/generic.c 2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/proc/generic.c 2008-01-02 13:56:37.000000000 -0500
-@@ -74,7 +74,7 @@
-               nbytes = MAX_NON_LFS - pos;
  
-       dp = PDE(inode);
--      if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-+      if (!(page = (char*) __get_free_page(GFP_TEMPORARY)))
-               return -ENOMEM;
+       /* ------------- tag queueing ? ------------------- */
+-      if (active_tc->drv_flags & TCF_DRV_EN_TAG) {
+-              if ((initio_msgin_accept(host)) == -1)
+-                      return -1;
+-              if (host->phase != MSG_IN)
++      if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) {
++              if ((tul_msgin_accept(pCurHcb)) == -1)
++                      return (-1);
++              if (pCurHcb->HCS_Phase != MSG_IN)
+                       goto no_tag;
+-              outl(1, host->addr + TUL_SCnt0);
+-              outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+-              if (wait_tulip(host) == -1)
+-                      return -1;
+-              msg = inb(host->addr + TUL_SFifo);      /* Read Tag Message    */
++              TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
++              if ((wait_tulip(pCurHcb)) == -1)
++                      return (-1);
++              msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);     /* Read Tag Message    */
+-              if (msg < MSG_STAG || msg > MSG_OTAG)           /* Is simple Tag      */
++              if ((msg < MSG_STAG) || (msg > MSG_OTAG))       /* Is simple Tag      */
+                       goto no_tag;
  
-       while ((nbytes > 0) && !eof) {
-diff -Nurb linux-2.6.22-570/fs/proc/internal.h linux-2.6.22-590/fs/proc/internal.h
---- linux-2.6.22-570/fs/proc/internal.h        2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/proc/internal.h        2008-01-02 13:56:37.000000000 -0500
-@@ -17,6 +17,11 @@
- #else
- static inline void proc_sys_init(void) { }
- #endif
-+#ifdef CONFIG_NET
-+extern int proc_net_init(void);
-+#else
-+static inline int proc_net_init(void) { return 0; }
-+#endif
+-              if (initio_msgin_accept(host) == -1)
+-                      return -1;
++              if ((tul_msgin_accept(pCurHcb)) == -1)
++                      return (-1);
  
- struct vmalloc_info {
-       unsigned long   used;
-@@ -46,15 +51,13 @@
- extern int proc_tgid_stat(struct task_struct *, char *);
- extern int proc_pid_status(struct task_struct *, char *);
- extern int proc_pid_statm(struct task_struct *, char *);
-+extern loff_t mem_lseek(struct file * file, loff_t offset, int orig);
+-              if (host->phase != MSG_IN)
++              if (pCurHcb->HCS_Phase != MSG_IN)
+                       goto no_tag;
  
- extern const struct file_operations proc_maps_operations;
- extern const struct file_operations proc_numa_maps_operations;
- extern const struct file_operations proc_smaps_operations;
+-              outl(1, host->addr + TUL_SCnt0);
+-              outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+-              if (wait_tulip(host) == -1)
+-                      return -1;
+-              tag = inb(host->addr + TUL_SFifo);      /* Read Tag ID       */
+-              scb = host->scb + tag;
+-              if (scb->target != tar || scb->lun != lun) {
+-                      return initio_msgout_abort_tag(host);
+-              }
+-              if (scb->status != SCB_BUSY) {  /* 03/24/95             */
+-                      return initio_msgout_abort_tag(host);
+-              }
+-              host->active = scb;
+-              if ((initio_msgin_accept(host)) == -1)
+-                      return -1;
++              TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
++              if ((wait_tulip(pCurHcb)) == -1)
++                      return (-1);
++              tag = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);     /* Read Tag ID       */
++              pCurScb = pCurHcb->HCS_Scb + tag;
++              if ((pCurScb->SCB_Target != tar) || (pCurScb->SCB_Lun != lun)) {
++                      return tul_msgout_abort_tag(pCurHcb);
++              }
++              if (pCurScb->SCB_Status != SCB_BUSY) {  /* 03/24/95             */
++                      return tul_msgout_abort_tag(pCurHcb);
++              }
++              pCurHcb->HCS_ActScb = pCurScb;
++              if ((tul_msgin_accept(pCurHcb)) == -1)
++                      return (-1);
+       } else {                /* No tag               */
+             no_tag:
+-              if ((scb = initio_find_busy_scb(host, tar | (lun << 8))) == NULL) {
+-                      return initio_msgout_abort_targ(host);
++              if ((pCurScb = tul_find_busy_scb(pCurHcb, tar | (lun << 8))) == NULL) {
++                      return tul_msgout_abort_targ(pCurHcb);
+               }
+-              host->active = scb;
+-              if (!(active_tc->drv_flags & TCF_DRV_EN_TAG)) {
+-                      if ((initio_msgin_accept(host)) == -1)
+-                              return -1;
++              pCurHcb->HCS_ActScb = pCurScb;
++              if (!(pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG)) {
++                      if ((tul_msgin_accept(pCurHcb)) == -1)
++                              return (-1);
+               }
+       }
+       return 0;
+ }
+-/**
+- *    int_initio_bad_seq              -       out of phase
+- *    @host: InitIO host flagging event
+- *
+- *    We have ended up out of phase somehow. Reset the host controller
+- *    and throw all our toys out of the pram. Let the midlayer clean up
+- */
+-static int int_initio_bad_seq(struct initio_host * host)
++/***************************************************************************/
++static int int_tul_bad_seq(HCS * pCurHcb)
+ {                             /* target wrong phase           */
+-      struct scsi_ctrl_blk *scb;
++      SCB *pCurScb;
+       int i;
+-      initio_reset_scsi(host, 10);
++      tul_reset_scsi(pCurHcb, 10);
+-      while ((scb = initio_pop_busy_scb(host)) != NULL) {
+-              scb->hastat = HOST_BAD_PHAS;
+-              initio_append_done_scb(host, scb);
++      while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
++              pCurScb->SCB_HaStat = HOST_BAD_PHAS;
++              tul_append_done_scb(pCurHcb, pCurScb);
+       }
+-      for (i = 0; i < host->max_tar; i++)
+-              host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+-      return -1;
++      for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
++              pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
++      }
++      return (-1);
+ }
+-/**
+- *    initio_msgout_abort_targ                -       abort a tag
+- *    @host: InitIO host
+- *
+- *    Abort when the target/lun does not match or when our SCB is not
+- *    busy. Used by untagged commands.
+- */
 -
--extern const struct file_operations proc_maps_operations;
--extern const struct file_operations proc_numa_maps_operations;
--extern const struct file_operations proc_smaps_operations;
+-static int initio_msgout_abort_targ(struct initio_host * host)
++/***************************************************************************/
++int tul_msgout_abort_targ(HCS * pCurHcb)
+ {
+-      outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
+-      if (initio_msgin_accept(host) == -1)
+-              return -1;
+-      if (host->phase != MSG_OUT)
+-              return initio_bad_seq(host);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
++      if (tul_msgin_accept(pCurHcb) == -1)
++              return (-1);
++      if (pCurHcb->HCS_Phase != MSG_OUT)
++              return (tul_bad_seq(pCurHcb));
+-      outb(MSG_ABORT, host->addr + TUL_SFifo);
+-      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+-      return initio_wait_disc(host);
++      return tul_wait_disc(pCurHcb);
+ }
+-/**
+- *    initio_msgout_abort_tag         -       abort a tag
+- *    @host: InitIO host
+- *
+- *    Abort when the target/lun does not match or when our SCB is not
+- *    busy. Used for tagged commands.
+- */
 -
-+extern const struct file_operations proc_clear_refs_operations;
-+extern const struct file_operations proc_pagemap_operations;
+-static int initio_msgout_abort_tag(struct initio_host * host)
++/***************************************************************************/
++int tul_msgout_abort_tag(HCS * pCurHcb)
+ {
  
- void free_proc_entry(struct proc_dir_entry *de);
+-      outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
+-      if (initio_msgin_accept(host) == -1)
+-              return -1;
+-      if (host->phase != MSG_OUT)
+-              return initio_bad_seq(host);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
++      if (tul_msgin_accept(pCurHcb) == -1)
++              return (-1);
++      if (pCurHcb->HCS_Phase != MSG_OUT)
++              return (tul_bad_seq(pCurHcb));
  
-diff -Nurb linux-2.6.22-570/fs/proc/proc_misc.c linux-2.6.22-590/fs/proc/proc_misc.c
---- linux-2.6.22-570/fs/proc/proc_misc.c       2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/proc/proc_misc.c       2008-01-02 13:56:37.000000000 -0500
-@@ -122,6 +122,7 @@
-       cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
+-      outb(MSG_ABORT_TAG, host->addr + TUL_SFifo);
+-      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT_TAG);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
  
-       do_posix_clock_monotonic_gettime(&uptime);
-+      monotonic_to_bootbased(&uptime);
-       cputime_to_timespec(idletime, &idle);
-       if (vx_flags(VXF_VIRT_UPTIME, 0))
-               vx_vsi_uptime(&uptime, &idle);
-@@ -463,12 +464,14 @@
-       unsigned long jif;
-       cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
-       u64 sum = 0;
-+      struct timespec boottime;
+-      return initio_wait_disc(host);
++      return tul_wait_disc(pCurHcb);
  
-       user = nice = system = idle = iowait =
-               irq = softirq = steal = cputime64_zero;
--      jif = - wall_to_monotonic.tv_sec;
--      if (wall_to_monotonic.tv_nsec)
--              --jif;
-+      getboottime(&boottime);
-+      jif = boottime.tv_sec;
-+      if (boottime.tv_nsec)
-+              ++jif;
+ }
  
-       for_each_possible_cpu(i) {
-               int j;
-diff -Nurb linux-2.6.22-570/fs/proc/proc_net.c linux-2.6.22-590/fs/proc/proc_net.c
---- linux-2.6.22-570/fs/proc/proc_net.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/proc/proc_net.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,154 @@
-+/*
-+ *  linux/fs/proc/net.c
-+ *
-+ *  Copyright (C) 2007
-+ *
-+ *  Author: Eric Biederman <ebiederm@xmission.com>
-+ *
-+ *  proc net directory handling functions
-+ */
-+
-+#include <asm/uaccess.h>
-+
-+#include <linux/errno.h>
-+#include <linux/time.h>
-+#include <linux/proc_fs.h>
-+#include <linux/stat.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/module.h>
-+#include <linux/bitops.h>
-+#include <linux/smp_lock.h>
-+#include <linux/mount.h>
-+#include <linux/nsproxy.h>
-+#include <net/net_namespace.h>
-+
-+#include "internal.h"
-+
-+static struct proc_dir_entry *proc_net_shadow;
-+
-+static struct dentry *proc_net_shadow_dentry(struct dentry *parent,
-+                                              struct proc_dir_entry *de)
-+{
-+      struct dentry *shadow = NULL;
-+      struct inode *inode;
-+      if (!de)
-+              goto out;
-+      de_get(de);
-+      inode = proc_get_inode(parent->d_inode->i_sb, de->low_ino, de);
-+      if (!inode)
-+              goto out_de_put;
-+      shadow = d_alloc_name(parent, de->name);
-+      if (!shadow)
-+              goto out_iput;
-+      shadow->d_op = parent->d_op; /* proc_dentry_operations */
-+      d_instantiate(shadow, inode);
-+out:
-+      return shadow;
-+out_iput:
-+      iput(inode);
-+out_de_put:
-+      de_put(de);
-+      goto out;
-+}
-+
-+static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd)
-+{
-+      struct net *net = current->nsproxy->net_ns;
-+      struct dentry *shadow;
-+      shadow = proc_net_shadow_dentry(parent, net->proc_net);
-+      if (!shadow)
-+              return ERR_PTR(-ENOENT);
-+
-+      dput(nd->dentry);
-+      /* My dentry count is 1 and that should be enough as the 
-+       * shadow dentry is thrown away immediately.
-+       */
-+      nd->dentry = shadow;
-+      return NULL;
-+}
+-/**
+- *    initio_msgin            -       Message in
+- *    @host: InitIO Host
+- *
+- *    Process incoming message
+- */
+-static int initio_msgin(struct initio_host * host)
++/***************************************************************************/
++int tul_msgin(HCS * pCurHcb)
+ {
+-      struct target_control *active_tc;
++      TCS *pCurTcb;
+       for (;;) {
+-              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+-              outl(1, host->addr + TUL_SCnt0);
+-              outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+-              if (wait_tulip(host) == -1)
+-                      return -1;
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+-              switch (inb(host->addr + TUL_SFifo)) {
++              TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
++              if ((wait_tulip(pCurHcb)) == -1)
++                      return (-1);
 +
-+static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry,
-+                                    struct nameidata *nd)
-+{
-+      struct net *net = current->nsproxy->net_ns;
-+      struct dentry *shadow;
-+      
-+      shadow = proc_net_shadow_dentry(nd->dentry, net->proc_net);
-+      if (!shadow)
-+              return ERR_PTR(-ENOENT);
++              switch (TUL_RD(pCurHcb->HCS_Base, TUL_SFifo)) {
+               case MSG_DISC:  /* Disconnect msg */
+-                      outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
+-                      return initio_wait_disc(host);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
 +
-+      dput(nd->dentry);
-+      nd->dentry = shadow;
-+      
-+      return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd);
-+}
++                      return tul_wait_disc(pCurHcb);
 +
-+static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr)
-+{
-+      struct net *net = current->nsproxy->net_ns;
-+      struct dentry *shadow;
-+      int ret;
+               case MSG_SDP:
+               case MSG_RESTORE:
+               case MSG_NOP:
+-                      initio_msgin_accept(host);
++                      tul_msgin_accept(pCurHcb);
+                       break;
 +
-+      shadow = proc_net_shadow_dentry(dentry->d_parent, net->proc_net);
-+      if (!shadow)
-+              return -ENOENT;
-+      ret = shadow->d_inode->i_op->setattr(shadow, iattr);
-+      dput(shadow);
-+      return ret;
-+}
+               case MSG_REJ:   /* Clear ATN first              */
+-                      outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)),
+-                              host->addr + TUL_SSignal);
+-                      active_tc = host->active_tc;
+-                      if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)       /* do sync nego */
+-                              outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN),
+-                                      host->addr + TUL_SSignal);
+-                      initio_msgin_accept(host);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal,
++                             (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
++                      pCurTcb = pCurHcb->HCS_ActTcs;
++                      if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {   /* do sync nego */
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
++                      }
++                      tul_msgin_accept(pCurHcb);
+                       break;
 +
-+static const struct file_operations proc_net_dir_operations = {
-+      .read                   = generic_read_dir,
-+};
+               case MSG_EXTEND:        /* extended msg */
+-                      initio_msgin_extend(host);
++                      tul_msgin_extend(pCurHcb);
+                       break;
 +
-+static struct inode_operations proc_net_dir_inode_operations = {
-+      .follow_link    = proc_net_follow_link,
-+      .lookup         = proc_net_lookup,
-+      .setattr        = proc_net_setattr,
-+};
+               case MSG_IGNOREWIDE:
+-                      initio_msgin_accept(host);
++                      tul_msgin_accept(pCurHcb);
++                      break;
 +
++                      /* get */
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
++                      if (wait_tulip(pCurHcb) == -1)
++                              return -1;
 +
-+static int proc_net_ns_init(struct net *net)
-+{
-+      struct proc_dir_entry *netd, *net_statd;
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);       /* put pad  */
++                      TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);   /* get IGNORE field */
++                      TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);   /* get pad */
 +
-+      netd = proc_mkdir("net", &net->proc_net_root);
-+      if (!netd)
-+              return -EEXIST;
++                      tul_msgin_accept(pCurHcb);
+                       break;
 +
-+      net_statd = proc_mkdir("stat", netd);
-+      if (!net_statd) {
-+              remove_proc_entry("net", &net->proc_net_root);
-+              return -EEXIST;
-+      }
+               case MSG_COMP:
+-                      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
+-                      outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
+-                      return initio_wait_done_disc(host);
++                      {
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
++                              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
++                              return tul_wait_done_disc(pCurHcb);
++                      }
+               default:
+-                      initio_msgout_reject(host);
++                      tul_msgout_reject(pCurHcb);
+                       break;
+               }
+-              if (host->phase != MSG_IN)
+-                      return host->phase;
++              if (pCurHcb->HCS_Phase != MSG_IN)
++                      return (pCurHcb->HCS_Phase);
+       }
+       /* statement won't reach here */
+ }
+-static int initio_msgout_reject(struct initio_host * host)
 +
-+      netd->data = net;
-+      net_statd->data = net;
-+      net->proc_net_root.data = net;
-+      net->proc_net = netd;
-+      net->proc_net_stat = net_statd;
 +
-+      return 0;
-+}
 +
-+static void proc_net_ns_exit(struct net *net)
-+{
-+      remove_proc_entry("stat", net->proc_net);
-+      remove_proc_entry("net", &net->proc_net_root);
++/***************************************************************************/
++int tul_msgout_reject(HCS * pCurHcb)
+ {
+-      outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
+-      if (initio_msgin_accept(host) == -1)
+-              return -1;
++      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+-      if (host->phase == MSG_OUT) {
+-              outb(MSG_REJ, host->addr + TUL_SFifo);          /* Msg reject           */
+-              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-              return wait_tulip(host);
++      if ((tul_msgin_accept(pCurHcb)) == -1)
++              return (-1);
 +
-+}
++      if (pCurHcb->HCS_Phase == MSG_OUT) {
++              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_REJ);         /* Msg reject           */
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++              return (wait_tulip(pCurHcb));
+       }
+-      return host->phase;
++      return (pCurHcb->HCS_Phase);
+ }
+-static int initio_msgout_ide(struct initio_host * host)
 +
-+struct pernet_operations proc_net_ns_ops = {
-+      .init = proc_net_ns_init,
-+      .exit = proc_net_ns_exit,
-+};
 +
-+int proc_net_init(void)
-+{
-+      proc_net_shadow = proc_mkdir("net", NULL);
-+      proc_net_shadow->proc_iops = &proc_net_dir_inode_operations;
-+      proc_net_shadow->proc_fops = &proc_net_dir_operations;
++/***************************************************************************/
++int tul_msgout_ide(HCS * pCurHcb)
+ {
+-      outb(MSG_IDE, host->addr + TUL_SFifo);          /* Initiator Detected Error */
+-      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-      return wait_tulip(host);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_IDE);         /* Initiator Detected Error */
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++      return (wait_tulip(pCurHcb));
+ }
+-static int initio_msgin_extend(struct initio_host * host)
 +
-+      return register_pernet_subsys(&proc_net_ns_ops);
-+}
-diff -Nurb linux-2.6.22-570/fs/proc/root.c linux-2.6.22-590/fs/proc/root.c
---- linux-2.6.22-570/fs/proc/root.c    2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/proc/root.c    2008-01-02 13:56:37.000000000 -0500
-@@ -21,11 +21,11 @@
++/***************************************************************************/
++int tul_msgin_extend(HCS * pCurHcb)
+ {
+-      u8 len, idx;
++      BYTE len, idx;
  
- #include "internal.h"
+-      if (initio_msgin_accept(host) != MSG_IN)
+-              return host->phase;
++      if (tul_msgin_accept(pCurHcb) != MSG_IN)
++              return (pCurHcb->HCS_Phase);
  
--struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
- struct proc_dir_entry *proc_virtual;
+       /* Get extended msg length      */
+-      outl(1, host->addr + TUL_SCnt0);
+-      outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+-      if (wait_tulip(host) == -1)
+-              return -1;
++      TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
++      if (wait_tulip(pCurHcb) == -1)
++              return (-1);
+-      len = inb(host->addr + TUL_SFifo);
+-      host->msg[0] = len;
++      len = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
++      pCurHcb->HCS_Msg[0] = len;
+       for (idx = 1; len != 0; len--) {
  
- extern void proc_vx_init(void);
+-              if ((initio_msgin_accept(host)) != MSG_IN)
+-                      return host->phase;
+-              outl(1, host->addr + TUL_SCnt0);
+-              outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);
+-              if (wait_tulip(host) == -1)
+-                      return -1;
+-              host->msg[idx++] = inb(host->addr + TUL_SFifo);
+-      }
+-      if (host->msg[1] == 1) {                /* if it's synchronous data transfer request */
+-              u8 r;
+-              if (host->msg[0] != 3)  /* if length is not right */
+-                      return initio_msgout_reject(host);
+-              if (host->active_tc->flags & TCF_NO_SYNC_NEGO) {        /* Set OFFSET=0 to do async, nego back */
+-                      host->msg[3] = 0;
+-              } else {
+-                      if (initio_msgin_sync(host) == 0 &&
+-                          (host->active_tc->flags & TCF_SYNC_DONE)) {
+-                              initio_sync_done(host);
+-                              return initio_msgin_accept(host);
++              if ((tul_msgin_accept(pCurHcb)) != MSG_IN)
++                      return (pCurHcb->HCS_Phase);
++              TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
++              if (wait_tulip(pCurHcb) == -1)
++                      return (-1);
++              pCurHcb->HCS_Msg[idx++] = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
++      }
++      if (pCurHcb->HCS_Msg[1] == 1) {         /* if it's synchronous data transfer request */
++              if (pCurHcb->HCS_Msg[0] != 3)   /* if length is not right */
++                      return (tul_msgout_reject(pCurHcb));
++              if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_SYNC_NEGO) {        /* Set OFFSET=0 to do async, nego back */
++                      pCurHcb->HCS_Msg[3] = 0;
++              } else {
++                      if ((tul_msgin_sync(pCurHcb) == 0) &&
++                          (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SYNC_DONE)) {
++                              tul_sync_done(pCurHcb);
++                              return (tul_msgin_accept(pCurHcb));
+                       }
+               }
  
-+struct proc_dir_entry *proc_bus, *proc_root_fs, *proc_root_driver;
- static int proc_get_sb(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+-              r = inb(host->addr + TUL_SSignal);
+-              outb((r & (TSC_SET_ACK | 7)) | TSC_SET_ATN,
+-                      host->addr + TUL_SSignal);
+-              if (initio_msgin_accept(host) != MSG_OUT)
+-                      return host->phase;
++              TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
++              if ((tul_msgin_accept(pCurHcb)) != MSG_OUT)
++                      return (pCurHcb->HCS_Phase);
+               /* sync msg out */
+-              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
++
++              tul_sync_done(pCurHcb);
+-              initio_sync_done(host);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[3]);
+-              outb(MSG_EXTEND, host->addr + TUL_SFifo);
+-              outb(3, host->addr + TUL_SFifo);
+-              outb(1, host->addr + TUL_SFifo);
+-              outb(host->msg[2], host->addr + TUL_SFifo);
+-              outb(host->msg[3], host->addr + TUL_SFifo);
+-              outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-              return wait_tulip(host);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++              return (wait_tulip(pCurHcb));
+       }
+-      if (host->msg[0] != 2 || host->msg[1] != 3)
+-              return initio_msgout_reject(host);
++      if ((pCurHcb->HCS_Msg[0] != 2) || (pCurHcb->HCS_Msg[1] != 3))
++              return (tul_msgout_reject(pCurHcb));
+       /* if it's WIDE DATA XFER REQ   */
+-      if (host->active_tc->flags & TCF_NO_WDTR) {
+-              host->msg[2] = 0;
++      if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) {
++              pCurHcb->HCS_Msg[2] = 0;
+       } else {
+-              if (host->msg[2] > 2)   /* > 32 bits            */
+-                      return initio_msgout_reject(host);
+-              if (host->msg[2] == 2) {                /* == 32                */
+-                      host->msg[2] = 1;
++              if (pCurHcb->HCS_Msg[2] > 2)    /* > 32 bits            */
++                      return (tul_msgout_reject(pCurHcb));
++              if (pCurHcb->HCS_Msg[2] == 2) {         /* == 32                */
++                      pCurHcb->HCS_Msg[2] = 1;
+               } else {
+-                      if ((host->active_tc->flags & TCF_NO_WDTR) == 0) {
+-                              wdtr_done(host);
+-                              if ((host->active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
+-                                      outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
+-                              return initio_msgin_accept(host);
++                      if ((pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) == 0) {
++                              wdtr_done(pCurHcb);
++                              if ((pCurHcb->HCS_ActTcs->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
++                                      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
++                              return (tul_msgin_accept(pCurHcb));
+                       }
+               }
+       }
+-      outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+-      if (initio_msgin_accept(host) != MSG_OUT)
+-              return host->phase;
++      if (tul_msgin_accept(pCurHcb) != MSG_OUT)
++              return (pCurHcb->HCS_Phase);
+       /* WDTR msg out                 */
+-      outb(MSG_EXTEND, host->addr + TUL_SFifo);
+-      outb(2, host->addr + TUL_SFifo);
+-      outb(3, host->addr + TUL_SFifo);
+-      outb(host->msg[2], host->addr + TUL_SFifo);
+-      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-      return wait_tulip(host);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++      return (wait_tulip(pCurHcb));
+ }
+-static int initio_msgin_sync(struct initio_host * host)
++/***************************************************************************/
++int tul_msgin_sync(HCS * pCurHcb)
  {
-@@ -64,8 +64,8 @@
-               return;
+       char default_period;
+-      default_period = initio_rate_tbl[host->active_tc->flags & TCF_SCSI_RATE];
+-      if (host->msg[3] > MAX_OFFSET) {
+-              host->msg[3] = MAX_OFFSET;
+-              if (host->msg[2] < default_period) {
+-                      host->msg[2] = default_period;
++      default_period = tul_rate_tbl[pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SCSI_RATE];
++      if (pCurHcb->HCS_Msg[3] > MAX_OFFSET) {
++              pCurHcb->HCS_Msg[3] = MAX_OFFSET;
++              if (pCurHcb->HCS_Msg[2] < default_period) {
++                      pCurHcb->HCS_Msg[2] = default_period;
+                       return 1;
+               }
+-              if (host->msg[2] >= 59) /* Change to async              */
+-                      host->msg[3] = 0;
++              if (pCurHcb->HCS_Msg[2] >= 59) {        /* Change to async              */
++                      pCurHcb->HCS_Msg[3] = 0;
++              }
+               return 1;
        }
-       proc_misc_init();
--      proc_net = proc_mkdir("net", NULL);
--      proc_net_stat = proc_mkdir("net/stat", NULL);
+       /* offset requests asynchronous transfers ? */
+-      if (host->msg[3] == 0) {
++      if (pCurHcb->HCS_Msg[3] == 0) {
+               return 0;
+       }
+-      if (host->msg[2] < default_period) {
+-              host->msg[2] = default_period;
++      if (pCurHcb->HCS_Msg[2] < default_period) {
++              pCurHcb->HCS_Msg[2] = default_period;
+               return 1;
+       }
+-      if (host->msg[2] >= 59) {
+-              host->msg[3] = 0;
++      if (pCurHcb->HCS_Msg[2] >= 59) {
++              pCurHcb->HCS_Msg[3] = 0;
+               return 1;
+       }
+       return 0;
+ }
+-static int wdtr_done(struct initio_host * host)
 +
-+      proc_net_init();
++/***************************************************************************/
++int wdtr_done(HCS * pCurHcb)
+ {
+-      host->active_tc->flags &= ~TCF_SYNC_DONE;
+-      host->active_tc->flags |= TCF_WDTR_DONE;
++      pCurHcb->HCS_ActTcs->TCS_Flags &= ~TCF_SYNC_DONE;
++      pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_WDTR_DONE;
  
- #ifdef CONFIG_SYSVIPC
-       proc_mkdir("sysvipc", NULL);
-@@ -163,7 +163,5 @@
- EXPORT_SYMBOL(remove_proc_entry);
- EXPORT_SYMBOL(proc_root);
- EXPORT_SYMBOL(proc_root_fs);
--EXPORT_SYMBOL(proc_net);
--EXPORT_SYMBOL(proc_net_stat);
- EXPORT_SYMBOL(proc_bus);
- EXPORT_SYMBOL(proc_root_driver);
-diff -Nurb linux-2.6.22-570/fs/proc/task_mmu.c linux-2.6.22-590/fs/proc/task_mmu.c
---- linux-2.6.22-570/fs/proc/task_mmu.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/proc/task_mmu.c        2008-01-02 13:56:37.000000000 -0500
-@@ -5,6 +5,7 @@
- #include <linux/highmem.h>
- #include <linux/ptrace.h>
- #include <linux/pagemap.h>
-+#include <linux/ptrace.h>
- #include <linux/mempolicy.h>
+-      host->active_tc->js_period = 0;
+-      if (host->msg[2])       /* if 16 bit */
+-              host->active_tc->js_period |= TSC_WIDE_SCSI;
+-      host->active_tc->sconfig0 &= ~TSC_ALT_PERIOD;
+-      outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);
+-      outb(host->active_tc->js_period, host->addr + TUL_SPeriod);
++      pCurHcb->HCS_ActTcs->TCS_JS_Period = 0;
++      if (pCurHcb->HCS_Msg[2]) {      /* if 16 bit */
++              pCurHcb->HCS_ActTcs->TCS_JS_Period |= TSC_WIDE_SCSI;
++      }
++      pCurHcb->HCS_ActTcs->TCS_SConfig0 &= ~TSC_ALT_PERIOD;
++      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
  
- #include <asm/elf.h>
-@@ -114,24 +115,123 @@
-       seq_printf(m, "%*c", len, ' ');
+       return 1;
  }
  
--struct mem_size_stats
-+static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)
+-static int initio_sync_done(struct initio_host * host)
++/***************************************************************************/
++int tul_sync_done(HCS * pCurHcb)
  {
--      unsigned long resident;
--      unsigned long shared_clean;
--      unsigned long shared_dirty;
--      unsigned long private_clean;
--      unsigned long private_dirty;
--      unsigned long referenced;
--};
-+      if (vma && vma != priv->tail_vma) {
-+              struct mm_struct *mm = vma->vm_mm;
-+              up_read(&mm->mmap_sem);
-+              mmput(mm);
-+      }
-+}
+       int i;
  
--struct pmd_walker {
--      struct vm_area_struct *vma;
--      void *private;
--      void (*action)(struct vm_area_struct *, pmd_t *, unsigned long,
--                     unsigned long, void *);
--};
-+static void *m_start(struct seq_file *m, loff_t *pos)
-+{
-+      struct proc_maps_private *priv = m->private;
-+      unsigned long last_addr = m->version;
-+      struct mm_struct *mm;
-+      struct vm_area_struct *vma, *tail_vma = NULL;
-+      loff_t l = *pos;
-+
-+      /* Clear the per syscall fields in priv */
-+      priv->task = NULL;
-+      priv->tail_vma = NULL;
-+
-+      /*
-+       * We remember last_addr rather than next_addr to hit with
-+       * mmap_cache most of the time. We have zero last_addr at
-+       * the beginning and also after lseek. We will have -1 last_addr
-+       * after the end of the vmas.
-+       */
-+
-+      if (last_addr == -1UL)
-+              return NULL;
-+
-+      priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
-+      if (!priv->task)
-+              return NULL;
-+
-+      mm = get_task_mm(priv->task);
-+      if (!mm)
-+              return NULL;
-+
-+      priv->tail_vma = tail_vma = get_gate_vma(priv->task);
-+      down_read(&mm->mmap_sem);
-+
-+      /* Start with last addr hint */
-+      if (last_addr && (vma = find_vma(mm, last_addr))) {
-+              vma = vma->vm_next;
-+              goto out;
-+      }
-+
-+      /*
-+       * Check the vma index is within the range and do
-+       * sequential scan until m_index.
-+       */
-+      vma = NULL;
-+      if ((unsigned long)l < mm->map_count) {
-+              vma = mm->mmap;
-+              while (l-- && vma)
-+                      vma = vma->vm_next;
-+              goto out;
-+      }
-+
-+      if (l != mm->map_count)
-+              tail_vma = NULL; /* After gate vma */
-+
-+out:
-+      if (vma)
-+              return vma;
+-      host->active_tc->flags |= TCF_SYNC_DONE;
++      pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_SYNC_DONE;
+-      if (host->msg[3]) {
+-              host->active_tc->js_period |= host->msg[3];
++      if (pCurHcb->HCS_Msg[3]) {
++              pCurHcb->HCS_ActTcs->TCS_JS_Period |= pCurHcb->HCS_Msg[3];
+               for (i = 0; i < 8; i++) {
+-                      if (initio_rate_tbl[i] >= host->msg[2]) /* pick the big one */
++                      if (tul_rate_tbl[i] >= pCurHcb->HCS_Msg[2])     /* pick the big one */
+                               break;
+               }
+-              host->active_tc->js_period |= (i << 4);
+-              host->active_tc->sconfig0 |= TSC_ALT_PERIOD;
++              pCurHcb->HCS_ActTcs->TCS_JS_Period |= (i << 4);
++              pCurHcb->HCS_ActTcs->TCS_SConfig0 |= TSC_ALT_PERIOD;
+       }
+-      outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);
+-      outb(host->active_tc->js_period, host->addr + TUL_SPeriod);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
+-      return -1;
++      return (-1);
+ }
+-static int initio_post_scsi_rst(struct initio_host * host)
++int tul_post_scsi_rst(HCS * pCurHcb)
+ {
+-      struct scsi_ctrl_blk *scb;
+-      struct target_control *active_tc;
++      SCB *pCurScb;
++      TCS *pCurTcb;
+       int i;
+-      host->active = NULL;
+-      host->active_tc = NULL;
+-      host->flags = 0;
+-
+-      while ((scb = initio_pop_busy_scb(host)) != NULL) {
+-              scb->hastat = HOST_BAD_PHAS;
+-              initio_append_done_scb(host, scb);
++      pCurHcb->HCS_ActScb = NULL;
++      pCurHcb->HCS_ActTcs = NULL;
++      pCurHcb->HCS_Flags = 0;
 +
-+      /* End of vmas has been reached */
-+      m->version = (tail_vma != NULL)? 0: -1UL;
-+      up_read(&mm->mmap_sem);
-+      mmput(mm);
-+      return tail_vma;
++      while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
++              pCurScb->SCB_HaStat = HOST_BAD_PHAS;
++              tul_append_done_scb(pCurHcb, pCurScb);
+       }
+       /* clear sync done flag         */
+-      active_tc = &host->targets[0];
+-      for (i = 0; i < host->max_tar; active_tc++, i++) {
+-              active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
++      pCurTcb = &pCurHcb->HCS_Tcs[0];
++      for (i = 0; i < pCurHcb->HCS_MaxTar; pCurTcb++, i++) {
++              pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+               /* Initialize the sync. xfer register values to an asyn xfer */
+-              active_tc->js_period = 0;
+-              active_tc->sconfig0 = host->sconf1;
+-              host->act_tags[0] = 0;  /* 07/22/98 */
+-              host->targets[i].flags &= ~TCF_BUSY;    /* 07/22/98 */
++              pCurTcb->TCS_JS_Period = 0;
++              pCurTcb->TCS_SConfig0 = pCurHcb->HCS_SConf1;
++              pCurHcb->HCS_ActTags[0] = 0;    /* 07/22/98 */
++              pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;     /* 07/22/98 */
+       }                       /* for */
+-      return -1;
++      return (-1);
+ }
+-static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb)
++/***************************************************************************/
++void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb)
+ {
+-      scb->status |= SCB_SELECT;
+-      scb->next_state = 0x1;
+-      host->active = scb;
+-      host->active_tc = &host->targets[scb->target];
+-      outb(TSC_SELATNSTOP, host->addr + TUL_SCmd);
++      pCurScb->SCB_Status |= SCB_SELECT;
++      pCurScb->SCB_NxtStat = 0x1;
++      pCurHcb->HCS_ActScb = pCurScb;
++      pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SELATNSTOP);
++      return;
+ }
+-static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb)
++/***************************************************************************/
++void tul_select_atn(HCS * pCurHcb, SCB * pCurScb)
+ {
+       int i;
+-      scb->status |= SCB_SELECT;
+-      scb->next_state = 0x2;
++      pCurScb->SCB_Status |= SCB_SELECT;
++      pCurScb->SCB_NxtStat = 0x2;
+-      outb(scb->ident, host->addr + TUL_SFifo);
+-      for (i = 0; i < (int) scb->cdblen; i++)
+-              outb(scb->cdb[i], host->addr + TUL_SFifo);
+-      host->active_tc = &host->targets[scb->target];
+-      host->active = scb;
+-      outb(TSC_SEL_ATN, host->addr + TUL_SCmd);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
++      for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
++              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
++      pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
++      pCurHcb->HCS_ActScb = pCurScb;
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN);
++      return;
+ }
+-static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb)
++/***************************************************************************/
++void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb)
+ {
+       int i;
+-      scb->status |= SCB_SELECT;
+-      scb->next_state = 0x2;
++      pCurScb->SCB_Status |= SCB_SELECT;
++      pCurScb->SCB_NxtStat = 0x2;
+-      outb(scb->ident, host->addr + TUL_SFifo);
+-      outb(scb->tagmsg, host->addr + TUL_SFifo);
+-      outb(scb->tagid, host->addr + TUL_SFifo);
+-      for (i = 0; i < scb->cdblen; i++)
+-              outb(scb->cdb[i], host->addr + TUL_SFifo);
+-      host->active_tc = &host->targets[scb->target];
+-      host->active = scb;
+-      outb(TSC_SEL_ATN3, host->addr + TUL_SCmd);
+-}
+-
+-/**
+- *    initio_bus_device_reset -        SCSI Bus Device Reset
+- *    @host: InitIO host to reset
+- *
+- *    Perform a device reset and abort all pending SCBs for the
+- *    victim device
+- */
+-int initio_bus_device_reset(struct initio_host * host)
+-{
+-      struct scsi_ctrl_blk *scb = host->active;
+-      struct target_control *active_tc = host->active_tc;
+-      struct scsi_ctrl_blk *tmp, *prev;
+-      u8 tar;
++      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
++      for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
++              TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
++      pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
++      pCurHcb->HCS_ActScb = pCurScb;
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN3);
++      return;
 +}
-+
-+static void *m_next(struct seq_file *m, void *v, loff_t *pos)
+-      if (host->phase != MSG_OUT)
+-              return int_initio_bad_seq(host);        /* Unexpected phase */
++/***************************************************************************/
++/* SCSI Bus Device Reset */
++int tul_bus_device_reset(HCS * pCurHcb)
 +{
-+      struct proc_maps_private *priv = m->private;
-+      struct vm_area_struct *vma = v;
-+      struct vm_area_struct *tail_vma = priv->tail_vma;
-+
-+      (*pos)++;
-+      if (vma && (vma != tail_vma) && vma->vm_next)
-+              return vma->vm_next;
-+      vma_stop(priv, vma);
-+      return (vma != tail_vma)? tail_vma: NULL;
-+}
++      SCB *pCurScb = pCurHcb->HCS_ActScb;
++      TCS *pCurTcb = pCurHcb->HCS_ActTcs;
++      SCB *pTmpScb, *pPrevScb;
++      BYTE tar;
+-      initio_unlink_pend_scb(host, scb);
+-      initio_release_scb(host, scb);
++      if (pCurHcb->HCS_Phase != MSG_OUT) {
++              return (int_tul_bad_seq(pCurHcb));      /* Unexpected phase             */
++      }
++      tul_unlink_pend_scb(pCurHcb, pCurScb);
++      tul_release_scb(pCurHcb, pCurScb);
+-      tar = scb->target;      /* target                       */
+-      active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
++      tar = pCurScb->SCB_Target;      /* target                       */
++      pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
+       /* clr sync. nego & WDTR flags  07/22/98 */
+       /* abort all SCB with same target */
+-      prev = tmp = host->first_busy;  /* Check Busy queue */
+-      while (tmp != NULL) {
+-              if (tmp->target == tar) {
++      pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;    /* Check Busy queue */
++      while (pTmpScb != NULL) {
 +
-+static void m_stop(struct seq_file *m, void *v)
-+{
-+      struct proc_maps_private *priv = m->private;
-+      struct vm_area_struct *vma = v;
++              if (pTmpScb->SCB_Target == tar) {
+                       /* unlink it */
+-                      if (tmp == host->first_busy) {
+-                              if ((host->first_busy = tmp->next) == NULL)
+-                                      host->last_busy = NULL;
+-                      } else {
+-                              prev->next = tmp->next;
+-                              if (tmp == host->last_busy)
+-                                      host->last_busy = prev;
++                      if (pTmpScb == pCurHcb->HCS_FirstBusy) {
++                              if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
++                                      pCurHcb->HCS_LastBusy = NULL;
++                      } else {
++                              pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
++                              if (pTmpScb == pCurHcb->HCS_LastBusy)
++                                      pCurHcb->HCS_LastBusy = pPrevScb;
+                       }
+-                      tmp->hastat = HOST_ABORTED;
+-                      initio_append_done_scb(host, tmp);
++                      pTmpScb->SCB_HaStat = HOST_ABORTED;
++                      tul_append_done_scb(pCurHcb, pTmpScb);
+               }
+               /* Previous haven't change      */
+               else {
+-                      prev = tmp;
++                      pPrevScb = pTmpScb;
+               }
+-              tmp = tmp->next;
++              pTmpScb = pTmpScb->SCB_NxtScb;
+       }
+-      outb(MSG_DEVRST, host->addr + TUL_SFifo);
+-      outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);
+-      return initio_wait_disc(host);
++
++      TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_DEVRST);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
++
++      return tul_wait_disc(pCurHcb);
+ }
+-static int initio_msgin_accept(struct initio_host * host)
++/***************************************************************************/
++int tul_msgin_accept(HCS * pCurHcb)
+ {
+-      outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);
+-      return wait_tulip(host);
++      TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
++      return (wait_tulip(pCurHcb));
+ }
+-static int wait_tulip(struct initio_host * host)
++/***************************************************************************/
++int wait_tulip(HCS * pCurHcb)
+ {
+-      while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))
+-               & TSS_INT_PENDING))
+-                      cpu_relax();
+-
+-      host->jsint = inb(host->addr + TUL_SInt);
+-      host->phase = host->jsstatus0 & TSS_PH_MASK;
+-      host->jsstatus1 = inb(host->addr + TUL_SStatus1);
++      while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
++               & TSS_INT_PENDING));
+-      if (host->jsint & TSS_RESEL_INT)        /* if SCSI bus reset detected */
+-              return int_initio_resel(host);
+-      if (host->jsint & TSS_SEL_TIMEOUT)      /* if selected/reselected timeout interrupt */
+-              return int_initio_busfree(host);
+-      if (host->jsint & TSS_SCSIRST_INT)      /* if SCSI bus reset detected   */
+-              return int_initio_scsi_rst(host);
+-
+-      if (host->jsint & TSS_DISC_INT) {       /* BUS disconnection            */
+-              if (host->flags & HCF_EXPECT_DONE_DISC) {
+-                      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */
+-                      initio_unlink_busy_scb(host, host->active);
+-                      host->active->hastat = 0;
+-                      initio_append_done_scb(host, host->active);
+-                      host->active = NULL;
+-                      host->active_tc = NULL;
+-                      host->flags &= ~HCF_EXPECT_DONE_DISC;
+-                      outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+-                      outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */
+-                      return -1;
++      pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
++      pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
++      pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
++
++      if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {       /* if SCSI bus reset detected   */
++              return (int_tul_resel(pCurHcb));
++      }
++      if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {     /* if selected/reselected timeout interrupt */
++              return (int_tul_busfree(pCurHcb));
++      }
++      if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {     /* if SCSI bus reset detected   */
++              return (int_tul_scsi_rst(pCurHcb));
++      }
++      if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {        /* BUS disconnection            */
++              if (pCurHcb->HCS_Flags & HCF_EXPECT_DONE_DISC) {
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);         /* Flush SCSI FIFO  */
++                      tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
++                      pCurHcb->HCS_ActScb->SCB_HaStat = 0;
++                      tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
++                      pCurHcb->HCS_ActScb = NULL;
++                      pCurHcb->HCS_ActTcs = NULL;
++                      pCurHcb->HCS_Flags &= ~HCF_EXPECT_DONE_DISC;
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);        /* Enable HW reselect       */
++                      return (-1);
++              }
++              if (pCurHcb->HCS_Flags & HCF_EXPECT_DISC) {
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);         /* Flush SCSI FIFO  */
++                      pCurHcb->HCS_ActScb = NULL;
++                      pCurHcb->HCS_ActTcs = NULL;
++                      pCurHcb->HCS_Flags &= ~HCF_EXPECT_DISC;
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
++                      TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);        /* Enable HW reselect       */
++                      return (-1);
+               }
+-              if (host->flags & HCF_EXPECT_DISC) {
+-                      outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */
+-                      host->active = NULL;
+-                      host->active_tc = NULL;
+-                      host->flags &= ~HCF_EXPECT_DISC;
+-                      outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+-                      outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */
+-                      return -1;
++              return (int_tul_busfree(pCurHcb));
+       }
+-              return int_initio_busfree(host);
++      if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {
++              return (pCurHcb->HCS_Phase);
+       }
+-      /* The old code really does the below. Can probably be removed */
+-      if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV))
+-              return host->phase;
+-      return host->phase;
++      return (pCurHcb->HCS_Phase);
+ }
+-
+-static int initio_wait_disc(struct initio_host * host)
++/***************************************************************************/
++int tul_wait_disc(HCS * pCurHcb)
+ {
+-      while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING))
+-              cpu_relax();
+-      host->jsint = inb(host->addr + TUL_SInt);
++      while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
++               & TSS_INT_PENDING));
+-      if (host->jsint & TSS_SCSIRST_INT)      /* if SCSI bus reset detected */
+-              return int_initio_scsi_rst(host);
+-      if (host->jsint & TSS_DISC_INT) {       /* BUS disconnection */
+-              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */
+-              outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+-              outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */
+-              host->active = NULL;
+-              return -1;
 +
-+      vma_stop(priv, vma);
-+      if (priv->task)
-+              put_task_struct(priv->task);
-+}
++      pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
 +
-+static int do_maps_open(struct inode *inode, struct file *file,
-+                      struct seq_operations *ops)
-+{
-+      struct proc_maps_private *priv;
-+      int ret = -ENOMEM;
-+      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-+      if (priv) {
-+              priv->pid = proc_pid(inode);
-+              ret = seq_open(file, ops);
-+              if (!ret) {
-+                      struct seq_file *m = file->private_data;
-+                      m->private = priv;
-+              } else {
-+                      kfree(priv);
-+              }
++      if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {     /* if SCSI bus reset detected   */
++              return (int_tul_scsi_rst(pCurHcb));
 +      }
-+      return ret;
-+}
++      if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {        /* BUS disconnection            */
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);         /* Flush SCSI FIFO  */
++              TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);        /* Enable HW reselect       */
++              pCurHcb->HCS_ActScb = NULL;
++              return (-1);
+       }
+-      return initio_bad_seq(host);
++      return (tul_bad_seq(pCurHcb));
+ }
  
--static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
-+static int show_map(struct seq_file *m, void *v)
+-static int initio_wait_done_disc(struct initio_host * host)
++/***************************************************************************/
++int tul_wait_done_disc(HCS * pCurHcb)
  {
-       struct proc_maps_private *priv = m->private;
-       struct task_struct *task = priv->task;
-@@ -191,38 +291,47 @@
-       }
-       seq_putc(m, '\n');
+-      while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))
+-               & TSS_INT_PENDING))
+-               cpu_relax();
  
--      if (mss)
--              seq_printf(m,
--                         "Size:           %8lu kB\n"
--                         "Rss:            %8lu kB\n"
--                         "Shared_Clean:   %8lu kB\n"
--                         "Shared_Dirty:   %8lu kB\n"
--                         "Private_Clean:  %8lu kB\n"
--                         "Private_Dirty:  %8lu kB\n"
--                         "Referenced:     %8lu kB\n",
--                         (vma->vm_end - vma->vm_start) >> 10,
--                         mss->resident >> 10,
--                         mss->shared_clean  >> 10,
--                         mss->shared_dirty  >> 10,
--                         mss->private_clean >> 10,
--                         mss->private_dirty >> 10,
--                         mss->referenced >> 10);
--
-       if (m->count < m->size)  /* vma is copied successfully */
-               m->version = (vma != get_gate_vma(task))? vma->vm_start: 0;
-       return 0;
- }
+-      host->jsint = inb(host->addr + TUL_SInt);
  
--static int show_map(struct seq_file *m, void *v)
-+static struct seq_operations proc_pid_maps_op = {
-+      .start  = m_start,
-+      .next   = m_next,
-+      .stop   = m_stop,
-+      .show   = show_map
-+};
+-      if (host->jsint & TSS_SCSIRST_INT)      /* if SCSI bus reset detected */
+-              return int_initio_scsi_rst(host);
+-      if (host->jsint & TSS_DISC_INT) {       /* BUS disconnection */
+-              outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);          /* Flush SCSI FIFO */
+-              outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);
+-              outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);         /* Enable HW reselect */
+-              initio_unlink_busy_scb(host, host->active);
++      while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
++               & TSS_INT_PENDING));
+-              initio_append_done_scb(host, host->active);
+-              host->active = NULL;
+-              return -1;
++      pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
 +
-+static int maps_open(struct inode *inode, struct file *file)
++
++      if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {     /* if SCSI bus reset detected   */
++              return (int_tul_scsi_rst(pCurHcb));
+       }
+-      return initio_bad_seq(host);
+-}
++      if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {        /* BUS disconnection            */
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);         /* Flush SCSI FIFO  */
++              TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
++              TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);        /* Enable HW reselect       */
++              tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
+-/**
+- *    i91u_intr               -       IRQ handler
+- *    @irqno: IRQ number
+- *    @dev_id: IRQ identifier
+- *
+- *    Take the relevant locks and then invoke the actual isr processing
+- *    code under the lock.
+- */
++              tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
++              pCurHcb->HCS_ActScb = NULL;
++              return (-1);
++      }
++      return (tul_bad_seq(pCurHcb));
++}
+ static irqreturn_t i91u_intr(int irqno, void *dev_id)
  {
--      return show_map_internal(m, v, NULL);
-+      return do_maps_open(inode, file, &proc_pid_maps_op);
+       struct Scsi_Host *dev = dev_id;
+       unsigned long flags;
+-      int r;
+       
+       spin_lock_irqsave(dev->host_lock, flags);
+-      r = initio_isr((struct initio_host *)dev->hostdata);
++      tul_isr((HCS *)dev->base);
+       spin_unlock_irqrestore(dev->host_lock, flags);
+-      if (r)
+       return IRQ_HANDLED;
+-      else
+-              return IRQ_NONE;
  }
  
--static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
--                          unsigned long addr, unsigned long end,
-+const struct file_operations proc_maps_operations = {
-+      .open           = maps_open,
-+      .read           = seq_read,
-+      .llseek         = seq_lseek,
-+      .release        = seq_release_private,
-+};
-+
-+#ifdef CONFIG_PROC_SMAPS
-+struct mem_size_stats
++static int tul_NewReturnNumberOfAdapters(void)
 +{
-+      struct vm_area_struct *vma;
-+      unsigned long resident;
-+      unsigned long shared_clean;
-+      unsigned long shared_dirty;
-+      unsigned long private_clean;
-+      unsigned long private_dirty;
-+      unsigned long referenced;
-+};
++      struct pci_dev *pDev = NULL;    /* Start from none              */
++      int iAdapters = 0;
++      long dRegValue;
++      WORD wBIOS;
++      int i = 0;
 +
-+static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
-                           void *private)
- {
-       struct mem_size_stats *mss = private;
-+      struct vm_area_struct *vma = mss->vma;
-       pte_t *pte, ptent;
-       spinlock_t *ptl;
-       struct page *page;
-@@ -256,12 +365,71 @@
++      init_i91uAdapter_table();
++
++      for (i = 0; i < ARRAY_SIZE(i91u_pci_devices); i++)
++      {
++              while ((pDev = pci_find_device(i91u_pci_devices[i].vendor, i91u_pci_devices[i].device, pDev)) != NULL) {
++                      if (pci_enable_device(pDev))
++                              continue;
++                      pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
++                      wBIOS = (UWORD) (dRegValue & 0xFF);
++                      if (((dRegValue & 0xFF00) >> 8) == 0xFF)
++                              dRegValue = 0;
++                      wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
++                      if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) {
++                              printk(KERN_WARNING 
++                                     "i91u: Could not set 32 bit DMA mask\n");
++                              continue;
++                      }
+-/**
+- *    initio_build_scb                -       Build the mappings and SCB
+- *    @host: InitIO host taking the command
+- *    @cblk: Firmware command block
+- *    @cmnd: SCSI midlayer command block
+- *
+- *    Translate the abstract SCSI command into a firmware command block
+- *    suitable for feeding to the InitIO host controller. This also requires
+- *    we build the scatter gather lists and ensure they are mapped properly.
+- */
++                      if (Addi91u_into_Adapter_table(wBIOS,
++                                                      (pDev->resource[0].start),
++                                                      pDev->irq,
++                                                      pDev->bus->number,
++                                                      (pDev->devfn >> 3)
++                              ) == 0)
++                              iAdapters++;
++              }
++      }
+-static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * cblk, struct scsi_cmnd * cmnd)
+-{                             /* Create corresponding SCB     */
+-      struct scatterlist *sglist;
+-      struct sg_entry *sg;            /* Pointer to SG list           */
+-      int i, nseg;
+-      long total_len;
+-      dma_addr_t dma_addr;
++      return (iAdapters);
++}
+-      /* Fill in the command headers */
+-      cblk->post = i91uSCBPost;       /* i91u's callback routine      */
+-      cblk->srb = cmnd;
+-      cblk->opcode = ExecSCSI;
+-      cblk->flags = SCF_POST; /* After SCSI done, call post routine */
+-      cblk->target = cmnd->device->id;
+-      cblk->lun = cmnd->device->lun;
+-      cblk->ident = cmnd->device->lun | DISC_ALLOW;
++static int i91u_detect(struct scsi_host_template * tpnt)
++{
++      HCS *pHCB;
++      struct Scsi_Host *hreg;
++      unsigned long i;        /* 01/14/98                     */
++      int ok = 0, iAdapters;
++      ULONG dBiosAdr;
++      BYTE *pbBiosAdr;
+-      cblk->flags |= SCF_SENSE;       /* Turn on auto request sense   */
++      /* Get total number of adapters in the motherboard */
++      iAdapters = tul_NewReturnNumberOfAdapters();
++      if (iAdapters == 0)     /* If no tulip founded, return */
++              return (0);
+-      /* Map the sense buffer into bus memory */
+-      dma_addr = dma_map_single(&host->pci_dev->dev, cmnd->sense_buffer,
+-                                SENSE_SIZE, DMA_FROM_DEVICE);
+-      cblk->senseptr = cpu_to_le32((u32)dma_addr);
+-      cblk->senselen = cpu_to_le32(SENSE_SIZE);
+-      cmnd->SCp.ptr = (char *)(unsigned long)dma_addr;
+-      cblk->cdblen = cmnd->cmd_len;
+-
+-      /* Clear the returned status */
+-      cblk->hastat = 0;
+-      cblk->tastat = 0;
+-      /* Command the command */
+-      memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len);
+-
+-      /* Set up tags */
+-      if (cmnd->device->tagged_supported) {   /* Tag Support                  */
+-              cblk->tagmsg = SIMPLE_QUEUE_TAG;        /* Do simple tag only   */
++      tul_num_ch = (iAdapters > tul_num_ch) ? tul_num_ch : iAdapters;
++      /* Update actually channel number */
++      if (tul_tag_enable) {   /* 1.01i                  */
++              tul_num_scb = MAX_TARGETS * i91u_MAXQUEUE;
+       } else {
+-              cblk->tagmsg = 0;       /* No tag support               */
++              tul_num_scb = MAX_TARGETS + 3;  /* 1-tape, 1-CD_ROM, 1- extra */
++      }                       /* Update actually SCBs per adapter */
++
++      /* Get total memory needed for HCS */
++      i = tul_num_ch * sizeof(HCS);
++      memset((unsigned char *) &tul_hcs[0], 0, i);    /* Initialize tul_hcs 0 */
++      /* Get total memory needed for SCB */
++
++      for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) {
++              i = tul_num_ch * tul_num_scb * sizeof(SCB);
++              if ((tul_scb = kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
++                      break;
++      }
++      if (tul_scb == NULL) {
++              printk("i91u: SCB memory allocation error\n");
++              return (0);
+       }
++      memset((unsigned char *) tul_scb, 0, i);
+-      /* todo handle map_sg error */
+-      nseg = scsi_dma_map(cmnd);
+-      BUG_ON(nseg < 0);
+-      if (nseg) {
+-              dma_addr = dma_map_single(&host->pci_dev->dev, &cblk->sglist[0],
+-                                        sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
+-                                        DMA_BIDIRECTIONAL);
+-              cblk->bufptr = cpu_to_le32((u32)dma_addr);
+-              cmnd->SCp.dma_handle = dma_addr;
++      for (i = 0, pHCB = &tul_hcs[0];         /* Get pointer for control block */
++           i < tul_num_ch;
++           i++, pHCB++) {
++              get_tulipPCIConfig(pHCB, i);
++              dBiosAdr = pHCB->HCS_BIOS;
++              dBiosAdr = (dBiosAdr << 4);
+-              cblk->flags |= SCF_SG;  /* Turn on SG list flag       */
+-              total_len = 0;
+-              sg = &cblk->sglist[0];
+-              scsi_for_each_sg(cmnd, sglist, cblk->sglen, i) {
+-                      sg->data = cpu_to_le32((u32)sg_dma_address(sglist));
+-                      total_len += sg->len = cpu_to_le32((u32)sg_dma_len(sglist));
+-              }
++              pbBiosAdr = phys_to_virt(dBiosAdr);
++
++              init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10);
++              request_region(pHCB->HCS_Base, 256, "i91u"); /* Register */ 
+-              cblk->buflen = (scsi_bufflen(cmnd) > total_len) ?
+-                      total_len : scsi_bufflen(cmnd);
+-      } else {        /* No data transfer required */
+-              cblk->buflen = 0;
+-              cblk->sglen = 0;
++              pHCB->HCS_Index = i;    /* 7/29/98 */
++              hreg = scsi_register(tpnt, sizeof(HCS));
++              if(hreg == NULL) {
++                      release_region(pHCB->HCS_Base, 256);
++                      return 0;
++              }
++              hreg->io_port = pHCB->HCS_Base;
++              hreg->n_io_port = 0xff;
++              hreg->can_queue = tul_num_scb;  /* 03/05/98                      */
++              hreg->unique_id = pHCB->HCS_Base;
++              hreg->max_id = pHCB->HCS_MaxTar;
++              hreg->max_lun = 32;     /* 10/21/97                     */
++              hreg->irq = pHCB->HCS_Intr;
++              hreg->this_id = pHCB->HCS_SCSI_ID;      /* Assign HCS index           */
++              hreg->base = (unsigned long)pHCB;
++              hreg->sg_tablesize = TOTAL_SG_ENTRY;    /* Maximun support is 32 */
++
++              /* Initial tulip chip           */
++              ok = request_irq(pHCB->HCS_Intr, i91u_intr, IRQF_DISABLED | IRQF_SHARED, "i91u", hreg);
++              if (ok < 0) {
++                      printk(KERN_WARNING "i91u: unable to request IRQ %d\n\n", pHCB->HCS_Intr);
++                      return 0;
        }
-       pte_unmap_unlock(pte - 1, ptl);
-       cond_resched();
-+      return 0;
++      }
++
++      tpnt->this_id = -1;
++      tpnt->can_queue = 1;
++
++      return 1;
  }
  
--static void clear_refs_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
--                               unsigned long addr, unsigned long end,
--                               void *private)
-+static struct mm_walk smaps_walk = { .pmd_entry = smaps_pte_range };
+-/**
+- *    i91u_queuecommand       -       Queue a new command if possible
+- *    @cmd: SCSI command block from the mid layer
+- *    @done: Completion handler
+- *
+- *    Attempts to queue a new command with the host adapter. Will return
+- *    zero if successful or indicate a host busy condition if not (which
+- *    will cause the mid layer to call us again later with the command)
+- */
++static void i91uBuildSCB(HCS * pHCB, SCB * pSCB, struct scsi_cmnd * SCpnt)
++{                             /* Create corresponding SCB     */
++      struct scatterlist *pSrbSG;
++      SG *pSG;                /* Pointer to SG list           */
++      int i;
++      long TotalLen;
++      dma_addr_t dma_addr;
 +
-+static int show_smap(struct seq_file *m, void *v)
- {
-+      struct vm_area_struct *vma = v;
-+      struct mem_size_stats mss;
-+      int ret;
++      pSCB->SCB_Post = i91uSCBPost;   /* i91u's callback routine      */
++      pSCB->SCB_Srb = SCpnt;
++      pSCB->SCB_Opcode = ExecSCSI;
++      pSCB->SCB_Flags = SCF_POST;     /* After SCSI done, call post routine */
++      pSCB->SCB_Target = SCpnt->device->id;
++      pSCB->SCB_Lun = SCpnt->device->lun;
++      pSCB->SCB_Ident = SCpnt->device->lun | DISC_ALLOW;
 +
-+      memset(&mss, 0, sizeof mss);
-+      mss.vma = vma;
-+      if (vma->vm_mm && !is_vm_hugetlb_page(vma))
-+              walk_page_range(vma->vm_mm, vma->vm_start, vma->vm_end,
-+                              &smaps_walk, &mss);
++      pSCB->SCB_Flags |= SCF_SENSE;   /* Turn on auto request sense   */
++      dma_addr = dma_map_single(&pHCB->pci_dev->dev, SCpnt->sense_buffer,
++                                SENSE_SIZE, DMA_FROM_DEVICE);
++      pSCB->SCB_SensePtr = cpu_to_le32((u32)dma_addr);
++      pSCB->SCB_SenseLen = cpu_to_le32(SENSE_SIZE);
++      SCpnt->SCp.ptr = (char *)(unsigned long)dma_addr;
 +
-+      ret = show_map(m, v);
-+      if (ret)
-+              return ret;
++      pSCB->SCB_CDBLen = SCpnt->cmd_len;
++      pSCB->SCB_HaStat = 0;
++      pSCB->SCB_TaStat = 0;
++      memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, SCpnt->cmd_len);
 +
-+      seq_printf(m,
-+                 "Size:           %8lu kB\n"
-+                 "Rss:            %8lu kB\n"
-+                 "Shared_Clean:   %8lu kB\n"
-+                 "Shared_Dirty:   %8lu kB\n"
-+                 "Private_Clean:  %8lu kB\n"
-+                 "Private_Dirty:  %8lu kB\n"
-+                 "Referenced:     %8lu kB\n",
-+                 (vma->vm_end - vma->vm_start) >> 10,
-+                 mss.resident >> 10,
-+                 mss.shared_clean  >> 10,
-+                 mss.shared_dirty  >> 10,
-+                 mss.private_clean >> 10,
-+                 mss.private_dirty >> 10,
-+                 mss.referenced >> 10);
++      if (SCpnt->device->tagged_supported) {  /* Tag Support                  */
++              pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG;    /* Do simple tag only   */
++      } else {
++              pSCB->SCB_TagMsg = 0;   /* No tag support               */
++      }
++      /* todo handle map_sg error */
++      if (SCpnt->use_sg) {
++              dma_addr = dma_map_single(&pHCB->pci_dev->dev, &pSCB->SCB_SGList[0],
++                                        sizeof(struct SG_Struc) * TOTAL_SG_ENTRY,
++                                        DMA_BIDIRECTIONAL);
++              pSCB->SCB_BufPtr = cpu_to_le32((u32)dma_addr);
++              SCpnt->SCp.dma_handle = dma_addr;
++
++              pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
++              pSCB->SCB_SGLen = dma_map_sg(&pHCB->pci_dev->dev, pSrbSG,
++                                           SCpnt->use_sg, SCpnt->sc_data_direction);
++
++              pSCB->SCB_Flags |= SCF_SG;      /* Turn on SG list flag       */
++              for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0];   /* 1.01g */
++                   i < pSCB->SCB_SGLen; i++, pSG++, pSrbSG++) {
++                      pSG->SG_Ptr = cpu_to_le32((u32)sg_dma_address(pSrbSG));
++                      TotalLen += pSG->SG_Len = cpu_to_le32((u32)sg_dma_len(pSrbSG));
++              }
++
++              pSCB->SCB_BufLen = (SCpnt->request_bufflen > TotalLen) ?
++                  TotalLen : SCpnt->request_bufflen;
++      } else if (SCpnt->request_bufflen) {            /* Non SG */
++              dma_addr = dma_map_single(&pHCB->pci_dev->dev, SCpnt->request_buffer,
++                                        SCpnt->request_bufflen,
++                                        SCpnt->sc_data_direction);
++              SCpnt->SCp.dma_handle = dma_addr;
++              pSCB->SCB_BufPtr = cpu_to_le32((u32)dma_addr);
++              pSCB->SCB_BufLen = cpu_to_le32((u32)SCpnt->request_bufflen);
++              pSCB->SCB_SGLen = 0;
++      } else {
++              pSCB->SCB_BufLen = 0;
++              pSCB->SCB_SGLen = 0;
++      }
++}
+ static int i91u_queuecommand(struct scsi_cmnd *cmd,
+               void (*done)(struct scsi_cmnd *))
+ {
+-      struct initio_host *host = (struct initio_host *) cmd->device->host->hostdata;
+-      struct scsi_ctrl_blk *cmnd;
++      HCS *pHCB = (HCS *) cmd->device->host->base;
++      register SCB *pSCB;
+       cmd->scsi_done = done;
+-      cmnd = initio_alloc_scb(host);
+-      if (!cmnd)
++      pSCB = tul_alloc_scb(pHCB);
++      if (!pSCB)
+               return SCSI_MLQUEUE_HOST_BUSY;
+-      initio_build_scb(host, cmnd, cmd);
+-      initio_exec_scb(host, cmnd);
++      i91uBuildSCB(pHCB, pSCB, cmd);
++      tul_exec_scb(pHCB, pSCB);
+       return 0;
+ }
+-/**
+- *    i91u_bus_reset          -       reset the SCSI bus
+- *    @cmnd: Command block we want to trigger the reset for
+- *
+- *    Initiate a SCSI bus reset sequence
++#if 0 /* no new EH yet */
++/*
++ *  Abort a queued command
++ *  (commands that are on the bus can't be aborted easily)
+  */
++static int i91u_abort(struct scsi_cmnd * SCpnt)
++{
++      HCS *pHCB;
 +
-+      return ret;
++      pHCB = (HCS *) SCpnt->device->host->base;
++      return tul_abort_srb(pHCB, SCpnt);
 +}
 +
-+static struct seq_operations proc_pid_smaps_op = {
-+      .start  = m_start,
-+      .next   = m_next,
-+      .stop   = m_stop,
-+      .show   = show_smap
-+};
++/*
++ *  Reset registers, reset a hanging bus and
++ *  kill active and disconnected commands for target w/o soft reset
++ */
++static int i91u_reset(struct scsi_cmnd * SCpnt, unsigned int reset_flags)
++{                             /* I need Host Control Block Information */
++      HCS *pHCB;
 +
-+static int smaps_open(struct inode *inode, struct file *file)
-+{
-+      return do_maps_open(inode, file, &proc_pid_smaps_op);
-+}
++      pHCB = (HCS *) SCpnt->device->host->base;
 +
-+const struct file_operations proc_smaps_operations = {
-+      .open           = smaps_open,
-+      .read           = seq_read,
-+      .llseek         = seq_lseek,
-+      .release        = seq_release_private,
-+};
++      if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET))
++              return tul_reset_scsi_bus(pHCB);
++      else
++              return tul_device_reset(pHCB, SCpnt, SCpnt->device->id, reset_flags);
++}
 +#endif
-+
-+#ifdef CONFIG_PROC_CLEAR_REFS
-+static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
-+                              unsigned long end, void *private)
-+{
-+      struct vm_area_struct *vma = private;
-       pte_t *pte, ptent;
-       spinlock_t *ptl;
-       struct page *page;
-@@ -282,236 +450,52 @@
-       }
-       pte_unmap_unlock(pte - 1, ptl);
-       cond_resched();
-+      return 0;
+-static int i91u_bus_reset(struct scsi_cmnd * cmnd)
++static int i91u_bus_reset(struct scsi_cmnd * SCpnt)
+ {
+-      struct initio_host *host;
++      HCS *pHCB;
+-      host = (struct initio_host *) cmnd->device->host->hostdata;
++      pHCB = (HCS *) SCpnt->device->host->base;
+-      spin_lock_irq(cmnd->device->host->host_lock);
+-      initio_reset_scsi(host, 0);
+-      spin_unlock_irq(cmnd->device->host->host_lock);
++      spin_lock_irq(SCpnt->device->host->host_lock);
++      tul_reset_scsi(pHCB, 0);
++      spin_unlock_irq(SCpnt->device->host->host_lock);
+       return SUCCESS;
  }
  
--static inline void walk_pmd_range(struct pmd_walker *walker, pud_t *pud,
--                                unsigned long addr, unsigned long end)
--{
--      pmd_t *pmd;
--      unsigned long next;
--
--      for (pmd = pmd_offset(pud, addr); addr != end;
--           pmd++, addr = next) {
--              next = pmd_addr_end(addr, end);
--              if (pmd_none_or_clear_bad(pmd))
--                      continue;
--              walker->action(walker->vma, pmd, addr, next, walker->private);
--      }
--}
--
--static inline void walk_pud_range(struct pmd_walker *walker, pgd_t *pgd,
--                                unsigned long addr, unsigned long end)
--{
--      pud_t *pud;
--      unsigned long next;
--
--      for (pud = pud_offset(pgd, addr); addr != end;
--           pud++, addr = next) {
--              next = pud_addr_end(addr, end);
--              if (pud_none_or_clear_bad(pud))
--                      continue;
--              walk_pmd_range(walker, pud, addr, next);
--      }
--}
--
--/*
-- * walk_page_range - walk the page tables of a VMA with a callback
-- * @vma - VMA to walk
-- * @action - callback invoked for every bottom-level (PTE) page table
-- * @private - private data passed to the callback function
+-/**
+- *    i91u_biospararm                 -       return the "logical geometry
+- *    @sdev: SCSI device
+- *    @dev; Matching block device
+- *    @capacity: Sector size of drive
+- *    @info_array: Return space for BIOS geometry
 - *
-- * Recursively walk the page table for the memory area in a VMA, calling
-- * a callback for every bottom-level (PTE) page table.
-- */
--static inline void walk_page_range(struct vm_area_struct *vma,
--                                 void (*action)(struct vm_area_struct *,
--                                                pmd_t *, unsigned long,
--                                                unsigned long, void *),
--                                 void *private)
--{
--      unsigned long addr = vma->vm_start;
--      unsigned long end = vma->vm_end;
--      struct pmd_walker walker = {
--              .vma            = vma,
--              .private        = private,
--              .action         = action,
--      };
--      pgd_t *pgd;
--      unsigned long next;
--
--      for (pgd = pgd_offset(vma->vm_mm, addr); addr != end;
--           pgd++, addr = next) {
--              next = pgd_addr_end(addr, end);
--              if (pgd_none_or_clear_bad(pgd))
--                      continue;
--              walk_pud_range(&walker, pgd, addr, next);
--      }
--}
+- *    Map the device geometry in a manner compatible with the host
+- *    controller BIOS behaviour.
+- *
+- *    FIXME: limited to 2^32 sector devices.
++/*
++ * Return the "logical geometry"
+  */
 -
--static int show_smap(struct seq_file *m, void *v)
--{
--      struct vm_area_struct *vma = v;
--      struct mem_size_stats mss;
-+static struct mm_walk clear_refs_walk = { .pmd_entry = clear_refs_pte_range };
+ static int i91u_biosparam(struct scsi_device *sdev, struct block_device *dev,
+               sector_t capacity, int *info_array)
+ {
+-      struct initio_host *host;               /* Point to Host adapter control block */
+-      struct target_control *tc;
++      HCS *pHcb;              /* Point to Host adapter control block */
++      TCS *pTcb;
+-      host = (struct initio_host *) sdev->host->hostdata;
+-      tc = &host->targets[sdev->id];
++      pHcb = (HCS *) sdev->host->base;
++      pTcb = &pHcb->HCS_Tcs[sdev->id];
+-      if (tc->heads) {
+-              info_array[0] = tc->heads;
+-              info_array[1] = tc->sectors;
+-              info_array[2] = (unsigned long)capacity / tc->heads / tc->sectors;
++      if (pTcb->TCS_DrvHead) {
++              info_array[0] = pTcb->TCS_DrvHead;
++              info_array[1] = pTcb->TCS_DrvSector;
++              info_array[2] = (unsigned long)capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector;
+       } else {
+-              if (tc->drv_flags & TCF_DRV_255_63) {
++              if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) {
+                       info_array[0] = 255;
+                       info_array[1] = 63;
+                       info_array[2] = (unsigned long)capacity / 255 / 63;
+@@ -2722,16 +3047,7 @@
+       return 0;
+ }
  
--      memset(&mss, 0, sizeof mss);
--      if (vma->vm_mm && !is_vm_hugetlb_page(vma))
--              walk_page_range(vma, smaps_pte_range, &mss);
--      return show_map_internal(m, v, &mss);
--}
+-/**
+- *    i91u_unmap_scb          -       Unmap a command
+- *    @pci_dev: PCI device the command is for
+- *    @cmnd: The command itself
+- *
+- *    Unmap any PCI mapping/IOMMU resources allocated when the command
+- *    was mapped originally as part of initio_build_scb
+- */
 -
--void clear_refs_smap(struct mm_struct *mm)
-+static ssize_t clear_refs_write(struct file *file, const char __user *buf,
-+                              size_t count, loff_t *ppos)
+-static void i91u_unmap_scb(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd)
++static void i91u_unmap_cmnd(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd)
  {
-+      struct task_struct *task;
-+      char buffer[13], *end;
-+      struct mm_struct *mm;
-       struct vm_area_struct *vma;
+       /* auto sense buffer */
+       if (cmnd->SCp.ptr) {
+@@ -2742,63 +3058,65 @@
+       }
  
-+      memset(buffer, 0, sizeof(buffer));
-+      if (count > sizeof(buffer) - 1)
-+              count = sizeof(buffer) - 1;
-+      if (copy_from_user(buffer, buf, count))
-+              return -EFAULT;
-+      if (!simple_strtol(buffer, &end, 0))
-+              return -EINVAL;
-+      if (*end == '\n')
-+              end++;
-+      task = get_proc_task(file->f_path.dentry->d_inode);
-+      if (!task)
-+              return -ESRCH;
-+      mm = get_task_mm(task);
-+      if (mm) {
-       down_read(&mm->mmap_sem);
-       for (vma = mm->mmap; vma; vma = vma->vm_next)
--              if (vma->vm_mm && !is_vm_hugetlb_page(vma))
--                      walk_page_range(vma, clear_refs_pte_range, NULL);
-+                      if (!is_vm_hugetlb_page(vma))
-+                              walk_page_range(mm, vma->vm_start, vma->vm_end,
-+                                              &clear_refs_walk, vma);
-       flush_tlb_mm(mm);
-       up_read(&mm->mmap_sem);
--}
--
--static void *m_start(struct seq_file *m, loff_t *pos)
--{
--      struct proc_maps_private *priv = m->private;
--      unsigned long last_addr = m->version;
--      struct mm_struct *mm;
--      struct vm_area_struct *vma, *tail_vma = NULL;
--      loff_t l = *pos;
+       /* request buffer */
+-      if (scsi_sg_count(cmnd)) {
++      if (cmnd->use_sg) {
+               dma_unmap_single(&pci_dev->dev, cmnd->SCp.dma_handle,
+-                               sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
++                               sizeof(struct SG_Struc) * TOTAL_SG_ENTRY,
+                                DMA_BIDIRECTIONAL);
+-              scsi_dma_unmap(cmnd);
++              dma_unmap_sg(&pci_dev->dev, cmnd->request_buffer,
++                           cmnd->use_sg,
++                           cmnd->sc_data_direction);
++      } else if (cmnd->request_bufflen) {
++              dma_unmap_single(&pci_dev->dev, cmnd->SCp.dma_handle,
++                               cmnd->request_bufflen,
++                               cmnd->sc_data_direction);
+       }
+ }
+-/**
+- *    i91uSCBPost             -       SCSI callback
+- *    @host: Pointer to host adapter control block.
+- *    @cmnd: Pointer to SCSI control block.
+- *
+- *    This is callback routine be called when tulip finish one
+- *    SCSI command.
+- */
 -
--      /* Clear the per syscall fields in priv */
--      priv->task = NULL;
--      priv->tail_vma = NULL;
+-static void i91uSCBPost(u8 * host_mem, u8 * cblk_mem)
+-{
+-      struct scsi_cmnd *cmnd; /* Pointer to SCSI request block */
+-      struct initio_host *host;
+-      struct scsi_ctrl_blk *cblk;
++/*****************************************************************************
++ Function name  : i91uSCBPost
++ Description    : This is callback routine be called when tulip finish one
++                      SCSI command.
++ Input          : pHCB  -       Pointer to host adapter control block.
++                pSCB  -       Pointer to SCSI control block.
++ Output         : None.
++ Return         : None.
++*****************************************************************************/
++static void i91uSCBPost(BYTE * pHcb, BYTE * pScb)
++{
++      struct scsi_cmnd *pSRB; /* Pointer to SCSI request block */
++      HCS *pHCB;
++      SCB *pSCB;
++
++      pHCB = (HCS *) pHcb;
++      pSCB = (SCB *) pScb;
++      if ((pSRB = pSCB->SCB_Srb) == 0) {
++              printk("i91uSCBPost: SRB pointer is empty\n");
+-      host = (struct initio_host *) host_mem;
+-      cblk = (struct scsi_ctrl_blk *) cblk_mem;
+-      if ((cmnd = cblk->srb) == NULL) {
+-              printk(KERN_ERR "i91uSCBPost: SRB pointer is empty\n");
+-              WARN_ON(1);
+-              initio_release_scb(host, cblk); /* Release SCB for current channel */
++              tul_release_scb(pHCB, pSCB);    /* Release SCB for current channel */
+               return;
+       }
 -
 -      /*
--       * We remember last_addr rather than next_addr to hit with
--       * mmap_cache most of the time. We have zero last_addr at
--       * the beginning and also after lseek. We will have -1 last_addr
--       * after the end of the vmas.
+-       *      Remap the firmware error status into a mid layer one
 -       */
+-      switch (cblk->hastat) {
++      switch (pSCB->SCB_HaStat) {
+       case 0x0:
+       case 0xa:               /* Linked command complete without error and linked normally */
+       case 0xb:               /* Linked command complete without error interrupt generated */
+-              cblk->hastat = 0;
++              pSCB->SCB_HaStat = 0;
+               break;
+       case 0x11:              /* Selection time out-The initiator selection or target
+                                  reselection was not complete within the SCSI Time out period */
+-              cblk->hastat = DID_TIME_OUT;
++              pSCB->SCB_HaStat = DID_TIME_OUT;
+               break;
+       case 0x14:              /* Target bus phase sequence failure-An invalid bus phase or bus
+                                  phase sequence was requested by the target. The host adapter
+                                  will generate a SCSI Reset Condition, notifying the host with
+                                  a SCRD interrupt */
+-              cblk->hastat = DID_RESET;
++              pSCB->SCB_HaStat = DID_RESET;
+               break;
+       case 0x1a:              /* SCB Aborted. 07/21/98 */
+-              cblk->hastat = DID_ABORT;
++              pSCB->SCB_HaStat = DID_ABORT;
+               break;
+       case 0x12:              /* Data overrun/underrun-The target attempted to transfer more data
+@@ -2808,196 +3126,49 @@
+       case 0x16:              /* Invalid SCB Operation Code. */
+       default:
+-              printk("ini9100u: %x %x\n", cblk->hastat, cblk->tastat);
+-              cblk->hastat = DID_ERROR;       /* Couldn't find any better */
++              printk("ini9100u: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat);
++              pSCB->SCB_HaStat = DID_ERROR;   /* Couldn't find any better */
+               break;
+       }
+-      cmnd->result = cblk->tastat | (cblk->hastat << 16);
+-      WARN_ON(cmnd == NULL);
+-      i91u_unmap_scb(host->pci_dev, cmnd);
+-      cmnd->scsi_done(cmnd);  /* Notify system DONE           */
+-      initio_release_scb(host, cblk); /* Release SCB for current channel */
++      pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);
++
++      if (pSRB == NULL) {
++              printk("pSRB is NULL\n");
++      }
++
++      i91u_unmap_cmnd(pHCB->pci_dev, pSRB);
++      pSRB->scsi_done(pSRB);  /* Notify system DONE           */
++
++      tul_release_scb(pHCB, pSCB);    /* Release SCB for current channel */
+ }
+-static struct scsi_host_template initio_template = {
++/*
++ * Release ressources
++ */
++static int i91u_release(struct Scsi_Host *hreg)
++{
++      free_irq(hreg->irq, hreg);
++      release_region(hreg->io_port, 256);
++      return 0;
++}
++MODULE_LICENSE("Dual BSD/GPL");
++
++static struct scsi_host_template driver_template = {
+       .proc_name      = "INI9100U",
+-      .name                   = "Initio INI-9X00U/UW SCSI device driver",
++      .name           = i91u_REVID,
++      .detect         = i91u_detect,
++      .release        = i91u_release,
+       .queuecommand   = i91u_queuecommand,
++//    .abort          = i91u_abort,
++//    .reset          = i91u_reset,
+       .eh_bus_reset_handler = i91u_bus_reset,
+       .bios_param     = i91u_biosparam,
+-      .can_queue              = MAX_TARGETS * i91u_MAXQUEUE,
++      .can_queue      = 1,
+       .this_id        = 1,
+       .sg_tablesize   = SG_ALL,
+       .cmd_per_lun    = 1,
+       .use_clustering = ENABLE_CLUSTERING,
+ };
++#include "scsi_module.c"
+-static int initio_probe_one(struct pci_dev *pdev,
+-      const struct pci_device_id *id)
+-{
+-      struct Scsi_Host *shost;
+-      struct initio_host *host;
+-      u32 reg;
+-      u16 bios_seg;
+-      struct scsi_ctrl_blk *scb, *tmp, *prev = NULL /* silence gcc */;
+-      int num_scb, i, error;
 -
--      if (last_addr == -1UL)
--              return NULL;
+-      error = pci_enable_device(pdev);
+-      if (error)
+-              return error;
 -
--      priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
--      if (!priv->task)
--              return NULL;
+-      pci_read_config_dword(pdev, 0x44, (u32 *) & reg);
+-      bios_seg = (u16) (reg & 0xFF);
+-      if (((reg & 0xFF00) >> 8) == 0xFF)
+-              reg = 0;
+-      bios_seg = (bios_seg << 8) + ((u16) ((reg & 0xFF00) >> 8));
 -
--      mm = get_task_mm(priv->task);
--      if (!mm)
--              return NULL;
+-      if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+-              printk(KERN_WARNING  "i91u: Could not set 32 bit DMA mask\n");
+-              error = -ENODEV;
+-              goto out_disable_device;
+-      }
+-      shost = scsi_host_alloc(&initio_template, sizeof(struct initio_host));
+-      if (!shost) {
+-              printk(KERN_WARNING "initio: Could not allocate host structure.\n");
+-              error = -ENOMEM;
+-              goto out_disable_device;
+-      }
+-      host = (struct initio_host *)shost->hostdata;
+-      memset(host, 0, sizeof(struct initio_host));
 -
--      priv->tail_vma = tail_vma = get_gate_vma(priv->task);
--      down_read(&mm->mmap_sem);
+-      if (!request_region(host->addr, 256, "i91u")) {
+-              printk(KERN_WARNING "initio: I/O port range 0x%x is busy.\n", host->addr);
+-              error = -ENODEV;
+-              goto out_host_put;
+-      }
 -
--      /* Start with last addr hint */
--      if (last_addr && (vma = find_vma(mm, last_addr))) {
--              vma = vma->vm_next;
--              goto out;
+-      if (initio_tag_enable)  /* 1.01i */
+-              num_scb = MAX_TARGETS * i91u_MAXQUEUE;
+-      else
+-              num_scb = MAX_TARGETS + 3;      /* 1-tape, 1-CD_ROM, 1- extra */
+-
+-      for (; num_scb >= MAX_TARGETS + 3; num_scb--) {
+-              i = num_scb * sizeof(struct scsi_ctrl_blk);
+-              if ((scb = kzalloc(i, GFP_DMA)) != NULL)
+-                      break;
 -      }
 -
--      /*
--       * Check the vma index is within the range and do
--       * sequential scan until m_index.
--       */
--      vma = NULL;
--      if ((unsigned long)l < mm->map_count) {
--              vma = mm->mmap;
--              while (l-- && vma)
--                      vma = vma->vm_next;
--              goto out;
+-      if (!scb) {
+-              printk(KERN_WARNING "initio: Cannot allocate SCB array.\n");
+-              error = -ENOMEM;
+-              goto out_release_region;
 -      }
 -
--      if (l != mm->map_count)
--              tail_vma = NULL; /* After gate vma */
+-      host->num_scbs = num_scb;
+-      host->scb = scb;
+-      host->next_pending = scb;
+-      host->next_avail = scb;
+-      for (i = 0, tmp = scb; i < num_scb; i++, tmp++) {
+-              tmp->tagid = i;
+-              if (i != 0)
+-                      prev->next = tmp;
+-              prev = tmp;
+-      }
+-      prev->next = NULL;
+-      host->scb_end = tmp;
+-      host->first_avail = scb;
+-      host->last_avail = prev;
+-
+-      initio_init(host, phys_to_virt(bios_seg << 4));
+-
+-      host->jsstatus0 = 0;
+-
+-      shost->io_port = host->addr;
+-      shost->n_io_port = 0xff;
+-      shost->can_queue = num_scb;             /* 03/05/98                      */
+-      shost->unique_id = host->addr;
+-      shost->max_id = host->max_tar;
+-      shost->max_lun = 32;    /* 10/21/97                     */
+-      shost->irq = pdev->irq;
+-      shost->this_id = host->scsi_id; /* Assign HCS index           */
+-      shost->base = host->addr;
+-      shost->sg_tablesize = TOTAL_SG_ENTRY;
+-
+-      error = request_irq(pdev->irq, i91u_intr, IRQF_DISABLED|IRQF_SHARED, "i91u", shost);
+-      if (error < 0) {
+-              printk(KERN_WARNING "initio: Unable to request IRQ %d\n", pdev->irq);
+-              goto out_free_scbs;
+-      }
 -
--out:
--      if (vma)
--              return vma;
+-      pci_set_drvdata(pdev, shost);
+-      host->pci_dev = pdev;
 -
--      /* End of vmas has been reached */
--      m->version = (tail_vma != NULL)? 0: -1UL;
--      up_read(&mm->mmap_sem);
--      mmput(mm);
--      return tail_vma;
+-      error = scsi_add_host(shost, &pdev->dev);
+-      if (error)
+-              goto out_free_irq;
+-      scsi_scan_host(shost);
+-      return 0;
+-out_free_irq:
+-      free_irq(pdev->irq, shost);
+-out_free_scbs:
+-      kfree(host->scb);
+-out_release_region:
+-      release_region(host->addr, 256);
+-out_host_put:
+-      scsi_host_put(shost);
+-out_disable_device:
+-      pci_disable_device(pdev);
+-      return error;
 -}
 -
--static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)
--{
--      if (vma && vma != priv->tail_vma) {
--              struct mm_struct *mm = vma->vm_mm;
--              up_read(&mm->mmap_sem);
-               mmput(mm);
-       }
-+      put_task_struct(task);
-+      if (end - buffer == 0)
-+              return -EIO;
-+      return end - buffer;
- }
--static void *m_next(struct seq_file *m, void *v, loff_t *pos)
--{
--      struct proc_maps_private *priv = m->private;
--      struct vm_area_struct *vma = v;
--      struct vm_area_struct *tail_vma = priv->tail_vma;
--
--      (*pos)++;
--      if (vma && (vma != tail_vma) && vma->vm_next)
--              return vma->vm_next;
--      vma_stop(priv, vma);
--      return (vma != tail_vma)? tail_vma: NULL;
--}
+-/**
+- *    initio_remove_one       -       control shutdown
+- *    @pdev:  PCI device being released
+- *
+- *    Release the resources assigned to this adapter after it has
+- *    finished being used.
+- */
 -
--static void m_stop(struct seq_file *m, void *v)
+-static void initio_remove_one(struct pci_dev *pdev)
 -{
--      struct proc_maps_private *priv = m->private;
--      struct vm_area_struct *vma = v;
--
--      vma_stop(priv, vma);
--      if (priv->task)
--              put_task_struct(priv->task);
+-      struct Scsi_Host *host = pci_get_drvdata(pdev);
+-      struct initio_host *s = (struct initio_host *)host->hostdata;
+-      scsi_remove_host(host);
+-      free_irq(pdev->irq, host);
+-      release_region(s->addr, 256);
+-      scsi_host_put(host);
+-      pci_disable_device(pdev);
 -}
 -
--static struct seq_operations proc_pid_maps_op = {
--      .start  = m_start,
--      .next   = m_next,
--      .stop   = m_stop,
--      .show   = show_map
+-MODULE_LICENSE("GPL");
+-
+-static struct pci_device_id initio_pci_tbl[] = {
+-      {PCI_VENDOR_ID_INIT, 0x9500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+-      {PCI_VENDOR_ID_INIT, 0x9400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+-      {PCI_VENDOR_ID_INIT, 0x9401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+-      {PCI_VENDOR_ID_INIT, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+-      {PCI_VENDOR_ID_DOMEX, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+-      {0,}
 -};
+-MODULE_DEVICE_TABLE(pci, initio_pci_tbl);
 -
--static struct seq_operations proc_pid_smaps_op = {
--      .start  = m_start,
--      .next   = m_next,
--      .stop   = m_stop,
--      .show   = show_smap
+-static struct pci_driver initio_pci_driver = {
+-      .name           = "initio",
+-      .id_table       = initio_pci_tbl,
+-      .probe          = initio_probe_one,
+-      .remove         = __devexit_p(initio_remove_one),
 -};
 -
--static int do_maps_open(struct inode *inode, struct file *file,
--                      struct seq_operations *ops)
+-static int __init initio_init_driver(void)
 -{
--      struct proc_maps_private *priv;
--      int ret = -ENOMEM;
--      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
--      if (priv) {
--              priv->pid = proc_pid(inode);
--              ret = seq_open(file, ops);
--              if (!ret) {
--                      struct seq_file *m = file->private_data;
--                      m->private = priv;
--              } else {
--                      kfree(priv);
--              }
--      }
--      return ret;
+-      return pci_register_driver(&initio_pci_driver);
 -}
 -
--static int maps_open(struct inode *inode, struct file *file)
+-static void __exit initio_exit_driver(void)
 -{
--      return do_maps_open(inode, file, &proc_pid_maps_op);
+-      pci_unregister_driver(&initio_pci_driver);
 -}
 -
--const struct file_operations proc_maps_operations = {
--      .open           = maps_open,
--      .read           = seq_read,
--      .llseek         = seq_lseek,
--      .release        = seq_release_private,
-+const struct file_operations proc_clear_refs_operations = {
-+      .write          = clear_refs_write,
- };
-+#endif
- #ifdef CONFIG_NUMA
- extern int show_numa_map(struct seq_file *m, void *v);
-@@ -547,14 +531,211 @@
- };
- #endif
+-MODULE_DESCRIPTION("Initio INI-9X00U/UW SCSI device driver");
+-MODULE_AUTHOR("Initio Corporation");
+-MODULE_LICENSE("GPL");
+-
+-module_init(initio_init_driver);
+-module_exit(initio_exit_driver);
+diff -Nurb linux-2.6.22-590/drivers/scsi/initio.h linux-2.6.22-570/drivers/scsi/initio.h
+--- linux-2.6.22-590/drivers/scsi/initio.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/initio.h     2007-07-08 19:32:17.000000000 -0400
+@@ -4,8 +4,6 @@
+  * Copyright (c) 1994-1998 Initio Corporation
+  * All rights reserved.
+  *
+- * Cleanups (c) Copyright 2007 Red Hat <alan@redhat.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, or (at your option)
+@@ -20,6 +18,27 @@
+  * along with this program; see the file COPYING.  If not, write to
+  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+  *
++ * --------------------------------------------------------------------------
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions, and the following disclaimer,
++ *    without modification, immediately at the beginning of the file.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote products
++ *    derived from this software without specific prior written permission.
++ *
++ * Where this Software is combined with software released under the terms of 
++ * the GNU General Public License ("GPL") and the terms of the GPL would require the 
++ * combined work to also be released under the terms of the GPL, the terms
++ * and conditions of this License will apply in addition to those of the
++ * GPL with the exception of any terms or conditions of this License that
++ * conflict with, or are expressly prohibited by, the GPL.
++ *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+@@ -37,6 +56,17 @@
  
--static int smaps_open(struct inode *inode, struct file *file)
-+#ifdef CONFIG_PROC_PAGEMAP
-+struct pagemapread {
-+      struct mm_struct *mm;
-+      unsigned long next;
-+      unsigned long *buf;
-+      pte_t *ptebuf;
-+      unsigned long pos;
-+      size_t count;
-+      int index;
-+      char __user *out;
-+};
-+
-+static int flush_pagemap(struct pagemapread *pm)
- {
--      return do_maps_open(inode, file, &proc_pid_smaps_op);
-+      int n = min(pm->count, pm->index * sizeof(unsigned long));
-+      if (copy_to_user(pm->out, pm->buf, n))
-+              return -EFAULT;
-+      pm->out += n;
-+      pm->pos += n;
-+      pm->count -= n;
-+      pm->index = 0;
-+      cond_resched();
-+      return 0;
- }
+ #include <linux/types.h>
  
--const struct file_operations proc_smaps_operations = {
--      .open           = smaps_open,
--      .read           = seq_read,
--      .llseek         = seq_lseek,
--      .release        = seq_release_private,
-+static int add_to_pagemap(unsigned long addr, unsigned long pfn,
-+                        struct pagemapread *pm)
-+{
-+      pm->buf[pm->index++] = pfn;
-+      pm->next = addr + PAGE_SIZE;
-+      if (pm->index * sizeof(unsigned long) >= PAGE_SIZE ||
-+          pm->index * sizeof(unsigned long) >= pm->count)
-+              return flush_pagemap(pm);
-+      return 0;
-+}
-+
-+static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
-+                           void *private)
-+{
-+      struct pagemapread *pm = private;
-+      pte_t *pte;
-+      int err;
-+
-+      pte = pte_offset_map(pmd, addr);
-+
-+#ifdef CONFIG_HIGHPTE
-+      /* copy PTE directory to temporary buffer and unmap it */
-+      memcpy(pm->ptebuf, pte, PAGE_ALIGN((unsigned long)pte) - (unsigned long)pte);
-+      pte_unmap(pte);
-+      pte = pm->ptebuf;
-+#endif
-+
-+      for (; addr != end; pte++, addr += PAGE_SIZE) {
-+              if (addr < pm->next)
-+                      continue;
-+              if (!pte_present(*pte))
-+                      err = add_to_pagemap(addr, -1, pm);
-+              else
-+                      err = add_to_pagemap(addr, pte_pfn(*pte), pm);
-+              if (err)
-+                      return err;
-+      }
-+
-+#ifndef CONFIG_HIGHPTE
-+      pte_unmap(pte - 1);
-+#endif
-+
-+      return 0;
-+}
-+
-+static int pagemap_fill(struct pagemapread *pm, unsigned long end)
-+{
-+      int ret;
-+
-+      while (pm->next != end) {
-+              ret = add_to_pagemap(pm->next, -1UL, pm);
-+              if (ret)
-+                      return ret;
-+      }
-+      return 0;
-+}
-+
-+static struct mm_walk pagemap_walk = { .pmd_entry = pagemap_pte_range };
-+
-+/*
-+ * /proc/pid/pagemap - an array mapping virtual pages to pfns
-+ *
-+ * For each page in the address space, this file contains one long
-+ * representing the corresponding physical page frame number (PFN) or
-+ * -1 if the page isn't present. This allows determining precisely
-+ * which pages are mapped and comparing mapped pages between
-+ * processes.
-+ *
-+ * Efficient users of this interface will use /proc/pid/maps to
-+ * determine which areas of memory are actually mapped and llseek to
-+ * skip over unmapped regions.
-+ *
-+ * The first 4 bytes of this file form a simple header:
-+ *
-+ * first byte:   0 for big endian, 1 for little
-+ * second byte:  page shift (eg 12 for 4096 byte pages)
-+ * third byte:   entry size in bytes (currently either 4 or 8)
-+ * fourth byte:  header size
-+ */
-+static ssize_t pagemap_read(struct file *file, char __user *buf,
-+                          size_t count, loff_t *ppos)
-+{
-+      struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
-+      unsigned long src = *ppos;
-+      unsigned long *page;
-+      unsigned long addr, end, vend, svpfn, evpfn;
-+      struct mm_struct *mm;
-+      struct vm_area_struct *vma;
-+      struct pagemapread pm;
-+      int ret = -ESRCH;
-+
-+      if (!task)
-+              goto out_no_task;
-+
-+      ret = -EACCES;
-+      if (!ptrace_may_attach(task))
-+              goto out;
-+
-+      ret = -EIO;
-+      svpfn = src / sizeof(unsigned long) - 1;
-+      addr = PAGE_SIZE * svpfn;
-+      if ((svpfn + 1) * sizeof(unsigned long) != src)
-+              goto out;
-+      evpfn = min((src + count) / sizeof(unsigned long),
-+                  ((~0UL) >> PAGE_SHIFT) + 1);
-+      count = (evpfn - svpfn) * sizeof(unsigned long);
-+      end = PAGE_SIZE * evpfn;
-+
-+      ret = -ENOMEM;
-+      page = kzalloc(PAGE_SIZE, GFP_USER);
-+      if (!page)
-+              goto out;
-+
-+#ifdef CONFIG_HIGHPTE
-+      pm.ptebuf = kzalloc(PAGE_SIZE, GFP_USER);
-+      if (!pm.ptebuf)
-+              goto out_free;
-+#endif
-+
-+      ret = 0;
-+      mm = get_task_mm(task);
-+      if (!mm)
-+              goto out_freepte;
-+
-+      pm.mm = mm;
-+      pm.next = addr;
-+      pm.buf = page;
-+      pm.pos = src;
-+      pm.count = count;
-+      pm.index = 0;
-+      pm.out = buf;
-+
-+      if (svpfn == -1) {
-+              add_to_pagemap(pm.next, 0, &pm);
-+              ((char *)page)[0] = (ntohl(1) != 1);
-+              ((char *)page)[1] = PAGE_SHIFT;
-+              ((char *)page)[2] = sizeof(unsigned long);
-+              ((char *)page)[3] = sizeof(unsigned long);
-+      }
-+
-+      down_read(&mm->mmap_sem);
-+      vma = find_vma(mm, pm.next);
-+      while (pm.count > 0 && vma) {
-+              if (!ptrace_may_attach(task)) {
-+                      ret = -EIO;
-+                      goto out_mm;
-+              }
-+              vend = min(vma->vm_start - 1, end - 1) + 1;
-+              ret = pagemap_fill(&pm, vend);
-+              if (ret || !pm.count)
-+                      break;
-+              vend = min(vma->vm_end - 1, end - 1) + 1;
-+              ret = walk_page_range(mm, vma->vm_start, vend,
-+                                    &pagemap_walk, &pm);
-+              vma = vma->vm_next;
-+      }
-+      up_read(&mm->mmap_sem);
-+
-+      ret = pagemap_fill(&pm, end);
-+
-+      *ppos = pm.pos;
-+      if (!ret)
-+              ret = pm.pos - src;
-+
-+out_mm:
-+      mmput(mm);
-+out_freepte:
-+#ifdef CONFIG_HIGHPTE
-+      kfree(pm.ptebuf);
-+out_free:
-+#endif
-+      kfree(page);
-+out:
-+      put_task_struct(task);
-+out_no_task:
-+      return ret;
-+}
-+
-+const struct file_operations proc_pagemap_operations = {
-+      .llseek         = mem_lseek, /* borrow this */
-+      .read           = pagemap_read,
- };
-+#endif
-diff -Nurb linux-2.6.22-570/fs/ramfs/inode.c linux-2.6.22-590/fs/ramfs/inode.c
---- linux-2.6.22-570/fs/ramfs/inode.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/ramfs/inode.c  2008-01-02 13:56:37.000000000 -0500
-@@ -60,6 +60,7 @@
-               inode->i_blocks = 0;
-               inode->i_mapping->a_ops = &ramfs_aops;
-               inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
-+              mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
-               inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-               switch (mode & S_IFMT) {
-               default:
-diff -Nurb linux-2.6.22-570/fs/revoke.c linux-2.6.22-590/fs/revoke.c
---- linux-2.6.22-570/fs/revoke.c       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/revoke.c       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,777 @@
-+/*
-+ * fs/revoke.c - Invalidate all current open file descriptors of an inode.
-+ *
-+ * Copyright (C) 2006-2007  Pekka Enberg
-+ *
-+ * This file is released under the GPLv2.
-+ */
-+
-+#include <linux/file.h>
-+#include <linux/fs.h>
-+#include <linux/namei.h>
-+#include <linux/magic.h>
-+#include <linux/mm.h>
-+#include <linux/mman.h>
-+#include <linux/module.h>
-+#include <linux/mount.h>
-+#include <linux/sched.h>
-+#include <linux/revoked_fs_i.h>
-+#include <linux/syscalls.h>
-+
-+/**
-+ * fileset - an array of file pointers.
-+ * @files:    the array of file pointers
-+ * @nr:               number of elements in the array
-+ * @end:      index to next unused file pointer
-+ */
-+struct fileset {
-+      struct file     **files;
-+      unsigned long   nr;
-+      unsigned long   end;
-+};
++#define ULONG   unsigned long
++#define USHORT  unsigned short
++#define UCHAR   unsigned char
++#define BYTE    unsigned char
++#define WORD    unsigned short
++#define DWORD   unsigned long
++#define UBYTE   unsigned char
++#define UWORD   unsigned short
++#define UDWORD  unsigned long
++#define U32     u32
 +
-+/**
-+ * revoke_details - details of the revoke operation
-+ * @inode:            invalidate open file descriptors of this inode
-+ * @fset:             set of files that point to a revoked inode
-+ * @restore_start:    index to the first file pointer that is currently in
-+ *                    use by a file descriptor but the real file has not
-+ *                    been revoked
-+ */
-+struct revoke_details {
-+      struct fileset  *fset;
-+      unsigned long   restore_start;
-+};
+ #define TOTAL_SG_ENTRY                32
+ #define MAX_SUPPORTED_ADAPTERS  8
+ #define MAX_OFFSET            15
+@@ -338,55 +368,55 @@
+ /************************************************************************/
+ /*              Scatter-Gather Element Structure                        */
+ /************************************************************************/
+-struct sg_entry {
+-      u32 data;               /* Data Pointer */
+-      u32 len;                /* Data Length */
+-};
++typedef struct SG_Struc {
++      U32 SG_Ptr;             /* Data Pointer */
++      U32 SG_Len;             /* Data Length */
++} SG;
+ /***********************************************************************
+               SCSI Control Block
+ ************************************************************************/
+-struct scsi_ctrl_blk {
+-      struct scsi_ctrl_blk *next;
+-      u8 status;      /*4 */
+-      u8 next_state;  /*5 */
+-      u8 mode;                /*6 */
+-      u8 msgin;       /*7 SCB_Res0 */
+-      u16 sgidx;      /*8 */
+-      u16 sgmax;      /*A */
++typedef struct Scsi_Ctrl_Blk {
++      struct Scsi_Ctrl_Blk *SCB_NxtScb;
++      UBYTE SCB_Status;       /*4 */
++      UBYTE SCB_NxtStat;      /*5 */
++      UBYTE SCB_Mode;         /*6 */
++      UBYTE SCB_Msgin;        /*7 SCB_Res0 */
++      UWORD SCB_SGIdx;        /*8 */
++      UWORD SCB_SGMax;        /*A */
+ #ifdef ALPHA
+-      u32 reserved[2];        /*C */
++      U32 SCB_Reserved[2];    /*C */
+ #else
+-      u32 reserved[3];        /*C */
++      U32 SCB_Reserved[3];    /*C */
+ #endif
+-      u32 xferlen;    /*18 Current xfer len           */
+-      u32 totxlen;    /*1C Total xfer len             */
+-      u32 paddr;              /*20 SCB phy. Addr. */
+-
+-      u8 opcode;      /*24 SCB command code */
+-      u8 flags;       /*25 SCB Flags */
+-      u8 target;      /*26 Target Id */
+-      u8 lun;         /*27 Lun */
+-      u32 bufptr;             /*28 Data Buffer Pointer */
+-      u32 buflen;             /*2C Data Allocation Length */
+-      u8 sglen;       /*30 SG list # */
+-      u8 senselen;    /*31 Sense Allocation Length */
+-      u8 hastat;      /*32 */
+-      u8 tastat;      /*33 */
+-      u8 cdblen;      /*34 CDB Length */
+-      u8 ident;       /*35 Identify */
+-      u8 tagmsg;      /*36 Tag Message */
+-      u8 tagid;       /*37 Queue Tag */
+-      u8 cdb[12];     /*38 */
+-      u32 sgpaddr;    /*44 SG List/Sense Buf phy. Addr. */
+-      u32 senseptr;   /*48 Sense data pointer */
+-      void (*post) (u8 *, u8 *);      /*4C POST routine */
+-      struct scsi_cmnd *srb;  /*50 SRB Pointer */
+-      struct sg_entry sglist[TOTAL_SG_ENTRY]; /*54 Start of SG list */
+-};
++      U32 SCB_XferLen;        /*18 Current xfer len           */
++      U32 SCB_TotXLen;        /*1C Total xfer len             */
++      U32 SCB_PAddr;          /*20 SCB phy. Addr. */
++
++      UBYTE SCB_Opcode;       /*24 SCB command code */
++      UBYTE SCB_Flags;        /*25 SCB Flags */
++      UBYTE SCB_Target;       /*26 Target Id */
++      UBYTE SCB_Lun;          /*27 Lun */
++      U32 SCB_BufPtr;         /*28 Data Buffer Pointer */
++      U32 SCB_BufLen;         /*2C Data Allocation Length */
++      UBYTE SCB_SGLen;        /*30 SG list # */
++      UBYTE SCB_SenseLen;     /*31 Sense Allocation Length */
++      UBYTE SCB_HaStat;       /*32 */
++      UBYTE SCB_TaStat;       /*33 */
++      UBYTE SCB_CDBLen;       /*34 CDB Length */
++      UBYTE SCB_Ident;        /*35 Identify */
++      UBYTE SCB_TagMsg;       /*36 Tag Message */
++      UBYTE SCB_TagId;        /*37 Queue Tag */
++      UBYTE SCB_CDB[12];      /*38 */
++      U32 SCB_SGPAddr;        /*44 SG List/Sense Buf phy. Addr. */
++      U32 SCB_SensePtr;       /*48 Sense data pointer */
++      void (*SCB_Post) (BYTE *, BYTE *);      /*4C POST routine */
++      struct scsi_cmnd *SCB_Srb;      /*50 SRB Pointer */
++      SG SCB_SGList[TOTAL_SG_ENTRY];  /*54 Start of SG list */
++} SCB;
+-/* Bit Definition for status */
++/* Bit Definition for SCB_Status */
+ #define SCB_RENT        0x01
+ #define SCB_PEND        0x02
+ #define SCB_CONTIG      0x04  /* Contigent Allegiance */
+@@ -395,17 +425,17 @@
+ #define SCB_DONE        0x20
+-/* Opcodes for opcode */
++/* Opcodes of SCB_Opcode */
+ #define ExecSCSI        0x1
+ #define BusDevRst       0x2
+ #define AbortCmd        0x3
+-/* Bit Definition for mode */
++/* Bit Definition for SCB_Mode */
+ #define SCM_RSENS       0x01  /* request sense mode */
+-/* Bit Definition for flags */
++/* Bit Definition for SCB_Flags */
+ #define SCF_DONE        0x01
+ #define SCF_POST        0x02
+ #define SCF_SENSE       0x04
+@@ -462,14 +492,15 @@
+               Target Device Control Structure
+ **********************************************************************/
+-struct target_control {
+-      u16 flags;
+-      u8 js_period;
+-      u8 sconfig0;
+-      u16 drv_flags;
+-      u8 heads;
+-      u8 sectors;
+-};
++typedef struct Tar_Ctrl_Struc {
++      UWORD TCS_Flags;        /* 0 */
++      UBYTE TCS_JS_Period;    /* 2 */
++      UBYTE TCS_SConfig0;     /* 3 */
 +
-+static struct kmem_cache *revokefs_inode_cache;
++      UWORD TCS_DrvFlags;     /* 4 */
++      UBYTE TCS_DrvHead;      /* 6 */
++      UBYTE TCS_DrvSector;    /* 7 */
++} TCS;
+ /***********************************************************************
+               Target Device Control Structure
+@@ -492,53 +523,62 @@
+ #define TCF_DRV_EN_TAG          0x0800
+ #define TCF_DRV_255_63          0x0400
++typedef struct I91u_Adpt_Struc {
++      UWORD ADPT_BIOS;        /* 0 */
++      UWORD ADPT_BASE;        /* 1 */
++      UBYTE ADPT_Bus;         /* 2 */
++      UBYTE ADPT_Device;      /* 3 */
++      UBYTE ADPT_INTR;        /* 4 */
++} INI_ADPT_STRUCT;
 +
-+static inline bool fset_is_full(struct fileset *set)
-+{
-+      return set->nr == set->end;
-+}
 +
-+static inline struct file *fset_get_filp(struct fileset *set)
-+{
-+      return set->files[set->end++];
-+}
+ /***********************************************************************
+             Host Adapter Control Structure
+ ************************************************************************/
+-struct initio_host {
+-      u16 addr;               /* 00 */
+-      u16 bios_addr;          /* 02 */
+-      u8 irq;                 /* 04 */
+-      u8 scsi_id;             /* 05 */
+-      u8 max_tar;             /* 06 */
+-      u8 num_scbs;            /* 07 */
+-
+-      u8 flags;               /* 08 */
+-      u8 index;               /* 09 */
+-      u8 ha_id;               /* 0A */
+-      u8 config;              /* 0B */
+-      u16 idmask;             /* 0C */
+-      u8 semaph;              /* 0E */
+-      u8 phase;               /* 0F */
+-      u8 jsstatus0;           /* 10 */
+-      u8 jsint;               /* 11 */
+-      u8 jsstatus1;           /* 12 */
+-      u8 sconf1;              /* 13 */
+-
+-      u8 msg[8];              /* 14 */
+-      struct scsi_ctrl_blk *next_avail;       /* 1C */
+-      struct scsi_ctrl_blk *scb;              /* 20 */
+-      struct scsi_ctrl_blk *scb_end;          /* 24 */ /*UNUSED*/
+-      struct scsi_ctrl_blk *next_pending;     /* 28 */
+-      struct scsi_ctrl_blk *next_contig;      /* 2C */ /*UNUSED*/
+-      struct scsi_ctrl_blk *active;           /* 30 */
+-      struct target_control *active_tc;       /* 34 */
+-
+-      struct scsi_ctrl_blk *first_avail;      /* 38 */
+-      struct scsi_ctrl_blk *last_avail;       /* 3C */
+-      struct scsi_ctrl_blk *first_pending;    /* 40 */
+-      struct scsi_ctrl_blk *last_pending;     /* 44 */
+-      struct scsi_ctrl_blk *first_busy;       /* 48 */
+-      struct scsi_ctrl_blk *last_busy;        /* 4C */
+-      struct scsi_ctrl_blk *first_done;       /* 50 */
+-      struct scsi_ctrl_blk *last_done;        /* 54 */
+-      u8 max_tags[16];        /* 58 */
+-      u8 act_tags[16];        /* 68 */
+-      struct target_control targets[MAX_TARGETS];     /* 78 */
+-      spinlock_t avail_lock;
+-      spinlock_t semaph_lock;
++typedef struct Ha_Ctrl_Struc {
++      UWORD HCS_Base;         /* 00 */
++      UWORD HCS_BIOS;         /* 02 */
++      UBYTE HCS_Intr;         /* 04 */
++      UBYTE HCS_SCSI_ID;      /* 05 */
++      UBYTE HCS_MaxTar;       /* 06 */
++      UBYTE HCS_NumScbs;      /* 07 */
++
++      UBYTE HCS_Flags;        /* 08 */
++      UBYTE HCS_Index;        /* 09 */
++      UBYTE HCS_HaId;         /* 0A */
++      UBYTE HCS_Config;       /* 0B */
++      UWORD HCS_IdMask;       /* 0C */
++      UBYTE HCS_Semaph;       /* 0E */
++      UBYTE HCS_Phase;        /* 0F */
++      UBYTE HCS_JSStatus0;    /* 10 */
++      UBYTE HCS_JSInt;        /* 11 */
++      UBYTE HCS_JSStatus1;    /* 12 */
++      UBYTE HCS_SConf1;       /* 13 */
++
++      UBYTE HCS_Msg[8];       /* 14 */
++      SCB *HCS_NxtAvail;      /* 1C */
++      SCB *HCS_Scb;           /* 20 */
++      SCB *HCS_ScbEnd;        /* 24 */
++      SCB *HCS_NxtPend;       /* 28 */
++      SCB *HCS_NxtContig;     /* 2C */
++      SCB *HCS_ActScb;        /* 30 */
++      TCS *HCS_ActTcs;        /* 34 */
++
++      SCB *HCS_FirstAvail;    /* 38 */
++      SCB *HCS_LastAvail;     /* 3C */
++      SCB *HCS_FirstPend;     /* 40 */
++      SCB *HCS_LastPend;      /* 44 */
++      SCB *HCS_FirstBusy;     /* 48 */
++      SCB *HCS_LastBusy;      /* 4C */
++      SCB *HCS_FirstDone;     /* 50 */
++      SCB *HCS_LastDone;      /* 54 */
++      UBYTE HCS_MaxTags[16];  /* 58 */
++      UBYTE HCS_ActTags[16];  /* 68 */
++      TCS HCS_Tcs[MAX_TARGETS];       /* 78 */
++      spinlock_t HCS_AvailLock;
++      spinlock_t HCS_SemaphLock;
+       struct pci_dev *pci_dev;
+-};
++} HCS;
+ /* Bit Definition for HCB_Config */
+ #define HCC_SCSI_RESET          0x01
+@@ -559,47 +599,47 @@
+ *******************************************************************/
+ typedef struct _NVRAM_SCSI {  /* SCSI channel configuration   */
+-      u8 NVM_ChSCSIID;        /* 0Ch -> Channel SCSI ID       */
+-      u8 NVM_ChConfig1;       /* 0Dh -> Channel config 1      */
+-      u8 NVM_ChConfig2;       /* 0Eh -> Channel config 2      */
+-      u8 NVM_NumOfTarg;       /* 0Fh -> Number of SCSI target */
++      UCHAR NVM_ChSCSIID;     /* 0Ch -> Channel SCSI ID       */
++      UCHAR NVM_ChConfig1;    /* 0Dh -> Channel config 1      */
++      UCHAR NVM_ChConfig2;    /* 0Eh -> Channel config 2      */
++      UCHAR NVM_NumOfTarg;    /* 0Fh -> Number of SCSI target */
+       /* SCSI target configuration    */
+-      u8 NVM_Targ0Config;     /* 10h -> Target 0 configuration */
+-      u8 NVM_Targ1Config;     /* 11h -> Target 1 configuration */
+-      u8 NVM_Targ2Config;     /* 12h -> Target 2 configuration */
+-      u8 NVM_Targ3Config;     /* 13h -> Target 3 configuration */
+-      u8 NVM_Targ4Config;     /* 14h -> Target 4 configuration */
+-      u8 NVM_Targ5Config;     /* 15h -> Target 5 configuration */
+-      u8 NVM_Targ6Config;     /* 16h -> Target 6 configuration */
+-      u8 NVM_Targ7Config;     /* 17h -> Target 7 configuration */
+-      u8 NVM_Targ8Config;     /* 18h -> Target 8 configuration */
+-      u8 NVM_Targ9Config;     /* 19h -> Target 9 configuration */
+-      u8 NVM_TargAConfig;     /* 1Ah -> Target A configuration */
+-      u8 NVM_TargBConfig;     /* 1Bh -> Target B configuration */
+-      u8 NVM_TargCConfig;     /* 1Ch -> Target C configuration */
+-      u8 NVM_TargDConfig;     /* 1Dh -> Target D configuration */
+-      u8 NVM_TargEConfig;     /* 1Eh -> Target E configuration */
+-      u8 NVM_TargFConfig;     /* 1Fh -> Target F configuration */
++      UCHAR NVM_Targ0Config;  /* 10h -> Target 0 configuration */
++      UCHAR NVM_Targ1Config;  /* 11h -> Target 1 configuration */
++      UCHAR NVM_Targ2Config;  /* 12h -> Target 2 configuration */
++      UCHAR NVM_Targ3Config;  /* 13h -> Target 3 configuration */
++      UCHAR NVM_Targ4Config;  /* 14h -> Target 4 configuration */
++      UCHAR NVM_Targ5Config;  /* 15h -> Target 5 configuration */
++      UCHAR NVM_Targ6Config;  /* 16h -> Target 6 configuration */
++      UCHAR NVM_Targ7Config;  /* 17h -> Target 7 configuration */
++      UCHAR NVM_Targ8Config;  /* 18h -> Target 8 configuration */
++      UCHAR NVM_Targ9Config;  /* 19h -> Target 9 configuration */
++      UCHAR NVM_TargAConfig;  /* 1Ah -> Target A configuration */
++      UCHAR NVM_TargBConfig;  /* 1Bh -> Target B configuration */
++      UCHAR NVM_TargCConfig;  /* 1Ch -> Target C configuration */
++      UCHAR NVM_TargDConfig;  /* 1Dh -> Target D configuration */
++      UCHAR NVM_TargEConfig;  /* 1Eh -> Target E configuration */
++      UCHAR NVM_TargFConfig;  /* 1Fh -> Target F configuration */
+ } NVRAM_SCSI;
+ typedef struct _NVRAM {
+ /*----------header ---------------*/
+-      u16 NVM_Signature;      /* 0,1: Signature */
+-      u8 NVM_Size;            /* 2:   Size of data structure */
+-      u8 NVM_Revision;        /* 3:   Revision of data structure */
++      USHORT NVM_Signature;   /* 0,1: Signature */
++      UCHAR NVM_Size;         /* 2:   Size of data structure */
++      UCHAR NVM_Revision;     /* 3:   Revision of data structure */
+       /* ----Host Adapter Structure ---- */
+-      u8 NVM_ModelByte0;      /* 4:   Model number (byte 0) */
+-      u8 NVM_ModelByte1;      /* 5:   Model number (byte 1) */
+-      u8 NVM_ModelInfo;       /* 6:   Model information         */
+-      u8 NVM_NumOfCh; /* 7:   Number of SCSI channel */
+-      u8 NVM_BIOSConfig1;     /* 8:   BIOS configuration 1  */
+-      u8 NVM_BIOSConfig2;     /* 9:   BIOS configuration 2  */
+-      u8 NVM_HAConfig1;       /* A:   Hoat adapter configuration 1 */
+-      u8 NVM_HAConfig2;       /* B:   Hoat adapter configuration 2 */
++      UCHAR NVM_ModelByte0;   /* 4:   Model number (byte 0) */
++      UCHAR NVM_ModelByte1;   /* 5:   Model number (byte 1) */
++      UCHAR NVM_ModelInfo;    /* 6:   Model information         */
++      UCHAR NVM_NumOfCh;      /* 7:   Number of SCSI channel */
++      UCHAR NVM_BIOSConfig1;  /* 8:   BIOS configuration 1  */
++      UCHAR NVM_BIOSConfig2;  /* 9:   BIOS configuration 2  */
++      UCHAR NVM_HAConfig1;    /* A:   Hoat adapter configuration 1 */
++      UCHAR NVM_HAConfig2;    /* B:   Hoat adapter configuration 2 */
+       NVRAM_SCSI NVM_SCSIInfo[2];
+-      u8 NVM_reserved[10];
++      UCHAR NVM_reserved[10];
+       /* ---------- CheckSum ----------       */
+-      u16 NVM_CheckSum;       /* 0x3E, 0x3F: Checksum of NVRam        */
++      USHORT NVM_CheckSum;    /* 0x3E, 0x3F: Checksum of NVRam        */
+ } NVRAM, *PNVRAM;
+ /* Bios Configuration for nvram->BIOSConfig1                            */
+@@ -641,6 +681,19 @@
+ #define DISC_ALLOW              0xC0  /* Disconnect is allowed        */
+ #define SCSICMD_RequestSense    0x03
++typedef struct _HCSinfo {
++      ULONG base;
++      UCHAR vec;
++      UCHAR bios;             /* High byte of BIOS address */
++      USHORT BaseAndBios;     /* high byte: pHcsInfo->bios,low byte:pHcsInfo->base */
++} HCSINFO;
 +
-+static struct fileset *alloc_fset(unsigned long size)
-+{
-+      struct fileset *fset;
++#define TUL_RD(x,y)             (UCHAR)(inb(  (int)((ULONG)(x+y)) ))
++#define TUL_RDLONG(x,y)         (ULONG)(inl((int)((ULONG)(x+y)) ))
++#define TUL_WR(     adr,data)   outb( (UCHAR)(data), (int)(adr))
++#define TUL_WRSHORT(adr,data)   outw( (UWORD)(data), (int)(adr))
++#define TUL_WRLONG( adr,data)   outl( (ULONG)(data), (int)(adr))
 +
-+      fset = kzalloc(sizeof *fset, GFP_KERNEL);
-+      if (!fset)
-+              return NULL;
+ #define SCSI_ABORT_SNOOZE 0
+ #define SCSI_ABORT_SUCCESS 1
+ #define SCSI_ABORT_PENDING 2
+diff -Nurb linux-2.6.22-590/drivers/scsi/ipr.c linux-2.6.22-570/drivers/scsi/ipr.c
+--- linux-2.6.22-590/drivers/scsi/ipr.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/ipr.c        2007-07-08 19:32:17.000000000 -0400
+@@ -540,6 +540,32 @@
+ }
+ /**
++ * ipr_unmap_sglist - Unmap scatterlist if mapped
++ * @ioa_cfg:  ioa config struct
++ * @ipr_cmd:  ipr command struct
++ *
++ * Return value:
++ *    nothing
++ **/
++static void ipr_unmap_sglist(struct ipr_ioa_cfg *ioa_cfg,
++                           struct ipr_cmnd *ipr_cmd)
++{
++      struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
 +
-+      fset->files = kcalloc(size, sizeof(struct file *), GFP_KERNEL);
-+      if (!fset->files) {
-+              kfree(fset);
-+              return NULL;
++      if (ipr_cmd->dma_use_sg) {
++              if (scsi_cmd->use_sg > 0) {
++                      pci_unmap_sg(ioa_cfg->pdev, scsi_cmd->request_buffer,
++                                   scsi_cmd->use_sg,
++                                   scsi_cmd->sc_data_direction);
++              } else {
++                      pci_unmap_single(ioa_cfg->pdev, ipr_cmd->dma_handle,
++                                       scsi_cmd->request_bufflen,
++                                       scsi_cmd->sc_data_direction);
++              }
 +      }
-+      fset->nr = size;
-+      return fset;
 +}
 +
-+static void free_fset(struct fileset *fset)
-+{
-+      int i;
-+
-+      for (i = fset->end; i < fset->nr; i++)
-+              fput(fset->files[i]);
++/**
+  * ipr_mask_and_clear_interrupts - Mask all and clear specified interrupts
+  * @ioa_cfg:  ioa config struct
+  * @clr_ints:     interrupts to clear
+@@ -651,7 +677,7 @@
+       scsi_cmd->result |= (DID_ERROR << 16);
+-      scsi_dma_unmap(ipr_cmd->scsi_cmd);
++      ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+       scsi_cmd->scsi_done(scsi_cmd);
+       list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+ }
+@@ -2439,7 +2465,6 @@
+ /**
+  * ipr_read_trace - Dump the adapter trace
+  * @kobj:             kobject struct
+- * @bin_attr:         bin_attribute struct
+  * @buf:              buffer
+  * @off:              offset
+  * @count:            buffer size
+@@ -2447,9 +2472,8 @@
+  * Return value:
+  *    number of bytes printed to buffer
+  **/
+-static ssize_t ipr_read_trace(struct kobject *kobj,
+-                            struct bin_attribute *bin_attr,
+-                            char *buf, loff_t off, size_t count)
++static ssize_t ipr_read_trace(struct kobject *kobj, char *buf,
++                            loff_t off, size_t count)
+ {
+       struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+       struct Scsi_Host *shost = class_to_shost(cdev);
+@@ -3142,7 +3166,6 @@
+ /**
+  * ipr_read_dump - Dump the adapter
+  * @kobj:             kobject struct
+- * @bin_attr:         bin_attribute struct
+  * @buf:              buffer
+  * @off:              offset
+  * @count:            buffer size
+@@ -3150,9 +3173,8 @@
+  * Return value:
+  *    number of bytes printed to buffer
+  **/
+-static ssize_t ipr_read_dump(struct kobject *kobj,
+-                           struct bin_attribute *bin_attr,
+-                           char *buf, loff_t off, size_t count)
++static ssize_t ipr_read_dump(struct kobject *kobj, char *buf,
++                            loff_t off, size_t count)
+ {
+       struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+       struct Scsi_Host *shost = class_to_shost(cdev);
+@@ -3305,7 +3327,6 @@
+ /**
+  * ipr_write_dump - Setup dump state of adapter
+  * @kobj:             kobject struct
+- * @bin_attr:         bin_attribute struct
+  * @buf:              buffer
+  * @off:              offset
+  * @count:            buffer size
+@@ -3313,9 +3334,8 @@
+  * Return value:
+  *    number of bytes printed to buffer
+  **/
+-static ssize_t ipr_write_dump(struct kobject *kobj,
+-                            struct bin_attribute *bin_attr,
+-                            char *buf, loff_t off, size_t count)
++static ssize_t ipr_write_dump(struct kobject *kobj, char *buf,
++                            loff_t off, size_t count)
+ {
+       struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+       struct Scsi_Host *shost = class_to_shost(cdev);
+@@ -4272,25 +4292,24 @@
+ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
+                          struct ipr_cmnd *ipr_cmd)
+ {
+-      int i, nseg;
+-      struct scatterlist *sg;
++      int i;
++      struct scatterlist *sglist;
+       u32 length;
+       u32 ioadl_flags = 0;
+       struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
+       struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
+       struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl;
+-      length = scsi_bufflen(scsi_cmd);
+-      if (!length)
+-              return 0;
++      length = scsi_cmd->request_bufflen;
+-      nseg = scsi_dma_map(scsi_cmd);
+-      if (nseg < 0) {
+-              dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
+-              return -1;
+-      }
++      if (length == 0)
++              return 0;
+-      ipr_cmd->dma_use_sg = nseg;
++      if (scsi_cmd->use_sg) {
++              ipr_cmd->dma_use_sg = pci_map_sg(ioa_cfg->pdev,
++                                               scsi_cmd->request_buffer,
++                                               scsi_cmd->use_sg,
++                                               scsi_cmd->sc_data_direction);
+               if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
+                       ioadl_flags = IPR_IOADL_FLAGS_WRITE;
+@@ -4305,6 +4324,8 @@
+                               cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
+               }
++              sglist = scsi_cmd->request_buffer;
 +
-+      kfree(fset->files);
-+      kfree(fset);
-+}
+               if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) {
+                       ioadl = ioarcb->add_data.u.ioadl;
+                       ioarcb->write_ioadl_addr =
+@@ -4313,14 +4334,51 @@
+                       ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
+               }
+-      scsi_for_each_sg(scsi_cmd, sg, ipr_cmd->dma_use_sg, i) {
++              for (i = 0; i < ipr_cmd->dma_use_sg; i++) {
+                       ioadl[i].flags_and_data_len =
+-                      cpu_to_be32(ioadl_flags | sg_dma_len(sg));
+-              ioadl[i].address = cpu_to_be32(sg_dma_address(sg));
++                              cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i]));
++                      ioadl[i].address =
++                              cpu_to_be32(sg_dma_address(&sglist[i]));
+               }
+-      ioadl[i-1].flags_and_data_len |= cpu_to_be32(IPR_IOADL_FLAGS_LAST);
++              if (likely(ipr_cmd->dma_use_sg)) {
++                      ioadl[i-1].flags_and_data_len |=
++                              cpu_to_be32(IPR_IOADL_FLAGS_LAST);
++                      return 0;
++              } else
++                      dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
++      } else {
++              if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
++                      ioadl_flags = IPR_IOADL_FLAGS_WRITE;
++                      ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
++                      ioarcb->write_data_transfer_length = cpu_to_be32(length);
++                      ioarcb->write_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc));
++              } else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) {
++                      ioadl_flags = IPR_IOADL_FLAGS_READ;
++                      ioarcb->read_data_transfer_length = cpu_to_be32(length);
++                      ioarcb->read_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc));
++              }
++
++              ipr_cmd->dma_handle = pci_map_single(ioa_cfg->pdev,
++                                                   scsi_cmd->request_buffer, length,
++                                                   scsi_cmd->sc_data_direction);
++
++              if (likely(!pci_dma_mapping_error(ipr_cmd->dma_handle))) {
++                      ioadl = ioarcb->add_data.u.ioadl;
++                      ioarcb->write_ioadl_addr =
++                              cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
++                                          offsetof(struct ipr_ioarcb, add_data));
++                      ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
++                      ipr_cmd->dma_use_sg = 1;
++                      ioadl[0].flags_and_data_len =
++                              cpu_to_be32(ioadl_flags | length | IPR_IOADL_FLAGS_LAST);
++                      ioadl[0].address = cpu_to_be32(ipr_cmd->dma_handle);
+                       return 0;
++              } else
++                      dev_err(&ioa_cfg->pdev->dev, "pci_map_single failed!\n");
++      }
 +
-+/*
-+ * Revoked file descriptors point to inodes in the revokefs filesystem.
-+ */
-+static struct vfsmount *revokefs_mnt;
++      return -1;
+ }
+ /**
+@@ -4383,7 +4441,7 @@
+                       res->needs_sync_complete = 1;
+               res->in_erp = 0;
+       }
+-      scsi_dma_unmap(ipr_cmd->scsi_cmd);
++      ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+       list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+       scsi_cmd->scsi_done(scsi_cmd);
+ }
+@@ -4761,7 +4819,7 @@
+               break;
+       }
+-      scsi_dma_unmap(ipr_cmd->scsi_cmd);
++      ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+       list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+       scsi_cmd->scsi_done(scsi_cmd);
+ }
+@@ -4782,10 +4840,10 @@
+       struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
+       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+-      scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->ioasa.residual_data_len));
++      scsi_cmd->resid = be32_to_cpu(ipr_cmd->ioasa.residual_data_len);
+       if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) {
+-              scsi_dma_unmap(ipr_cmd->scsi_cmd);
++              ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+               list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+               scsi_cmd->scsi_done(scsi_cmd);
+       } else
+diff -Nurb linux-2.6.22-590/drivers/scsi/ips.c linux-2.6.22-570/drivers/scsi/ips.c
+--- linux-2.6.22-590/drivers/scsi/ips.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/ips.c        2007-07-08 19:32:17.000000000 -0400
+@@ -211,6 +211,19 @@
+ #warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
+ #endif
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
++#include <linux/blk.h>
++#include "sd.h"
++#define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
++#define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
++#ifndef __devexit_p
++#define __devexit_p(x) x
++#endif
++#else
++#define IPS_LOCK_SAVE(lock,flags) do{spin_lock(lock);(void)flags;}while(0)
++#define IPS_UNLOCK_RESTORE(lock,flags) do{spin_unlock(lock);(void)flags;}while(0)
++#endif
 +
-+static struct file *get_revoked_file(void)
+ #define IPS_DMA_DIR(scb) ((!scb->scsi_cmd || ips_is_passthru(scb->scsi_cmd) || \
+                          DMA_NONE == scb->scsi_cmd->sc_data_direction) ? \
+                          PCI_DMA_BIDIRECTIONAL : \
+@@ -368,13 +381,24 @@
+       .eh_abort_handler       = ips_eh_abort,
+       .eh_host_reset_handler  = ips_eh_reset,
+       .proc_name              = "ips",
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+       .proc_info              = ips_proc_info,
+       .slave_configure        = ips_slave_configure,
++#else
++      .proc_info              = ips_proc24_info,
++      .select_queue_depths    = ips_select_queue_depth,
++#endif
+       .bios_param             = ips_biosparam,
+       .this_id                = -1,
+       .sg_tablesize           = IPS_MAX_SG,
+       .cmd_per_lun            = 3,
+       .use_clustering         = ENABLE_CLUSTERING,
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++      .use_new_eh_code        = 1,
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)  &&  LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++    .highmem_io          = 1,   
++#endif
+ };
+@@ -707,7 +731,7 @@
+       /* free IRQ */
+       free_irq(ha->irq, ha);
+-      scsi_remove_host(sh);
++      IPS_REMOVE_HOST(sh);
+       scsi_host_put(sh);
+       ips_released_controllers++;
+@@ -789,6 +813,7 @@
+       ips_ha_t *ha;
+       ips_copp_wait_item_t *item;
+       int ret;
++      unsigned long cpu_flags;
+       struct Scsi_Host *host;
+       METHOD_TRACE("ips_eh_abort", 1);
+@@ -805,7 +830,7 @@
+       if (!ha->active)
+               return (FAILED);
+-      spin_lock(host->host_lock);
++      IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+       /* See if the command is on the copp queue */
+       item = ha->copp_waitlist.head;
+@@ -826,7 +851,7 @@
+               ret = (FAILED);
+       }
+-      spin_unlock(host->host_lock);
++      IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+       return ret;
+ }
+@@ -1104,7 +1129,7 @@
+               /* A Reset IOCTL is only sent by the boot CD in extreme cases.           */
+               /* There can never be any system activity ( network or disk ), but check */
+               /* anyway just as a good practice.                                       */
+-              pt = (ips_passthru_t *) scsi_sglist(SC);
++              pt = (ips_passthru_t *) SC->request_buffer;
+               if ((pt->CoppCP.cmd.reset.op_code == IPS_CMD_RESET_CHANNEL) &&
+                   (pt->CoppCP.cmd.reset.adapter_flag == 1)) {
+                       if (ha->scb_activelist.count != 0) {
+@@ -1151,10 +1176,18 @@
+ /*   Set bios geometry for the controller                                   */
+ /*                                                                          */
+ /****************************************************************************/
+-static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
++static int
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++ips_biosparam(Disk * disk, kdev_t dev, int geom[])
 +{
-+      struct dentry *dentry;
-+      struct inode *inode;
-+      struct file *filp;
-+      struct qstr name;
-+
-+      filp = get_empty_filp();
-+      if (!filp)
-+              goto err;
-+
-+      inode = new_inode(revokefs_mnt->mnt_sb);
-+      if (!inode)
-+              goto err_inode;
-+
-+      name.name = "revoked_file";
-+      name.len = strlen(name.name);
-+      dentry = d_alloc(revokefs_mnt->mnt_sb->s_root, &name);
-+      if (!dentry)
-+              goto err_dentry;
-+
-+      d_instantiate(dentry, inode);
-+
-+      filp->f_mapping = inode->i_mapping;
-+      filp->f_dentry = dget(dentry);
-+      filp->f_vfsmnt = mntget(revokefs_mnt);
-+      filp->f_op = fops_get(inode->i_fop);
-+      filp->f_pos = 0;
-+
-+      return filp;
-+
-+  err_dentry:
-+      iput(inode);
-+  err_inode:
-+      fput(filp);
-+  err:
-+      return NULL;
-+}
++      ips_ha_t *ha = (ips_ha_t *) disk->device->host->hostdata;
++      unsigned long capacity = disk->capacity;
++#else
++ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+             sector_t capacity, int geom[])
+ {
+       ips_ha_t *ha = (ips_ha_t *) sdev->host->hostdata;
++#endif
+       int heads;
+       int sectors;
+       int cylinders;
+@@ -1192,6 +1225,70 @@
+       return (0);
+ }
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 +
-+static inline bool can_revoke_file(struct file *file, struct inode *inode,
-+                                 struct file *to_exclude)
++/* ips_proc24_info is a wrapper around ips_proc_info *
++ * for compatibility with the 2.4 scsi parameters    */
++static int
++ips_proc24_info(char *buffer, char **start, off_t offset, int length,
++                            int hostno, int func)
 +{
-+      if (!file || file == to_exclude)
-+              return false;
++      int i;
 +
-+      return file->f_dentry->d_inode == inode;
++      for (i = 0; i < ips_next_controller; i++) {
++              if (ips_sh[i] && ips_sh[i]->host_no == hostno) {
++                      return ips_proc_info(ips_sh[i], buffer, start,
++                                           offset, length, func);
++              }
++      }
++      return -EINVAL; 
 +}
 +
-+/*
-+ *    LOCKING: task_lock(owner)
-+ */
-+static int revoke_fds(struct task_struct *owner,
-+                    struct inode *inode,
-+                    struct file *to_exclude, struct fileset *fset)
++/****************************************************************************/
++/*                                                                          */
++/* Routine Name: ips_select_queue_depth                                     */
++/*                                                                          */
++/* Routine Description:                                                     */
++/*                                                                          */
++/*   Select queue depths for the devices on the contoller                   */
++/*                                                                          */
++/****************************************************************************/
++static void
++ips_select_queue_depth(struct Scsi_Host *host, struct scsi_device * scsi_devs)
 +{
-+      struct files_struct *files;
-+      struct fdtable *fdt;
-+      unsigned int fd;
-+      int err = 0;
-+
-+      files = get_files_struct(owner);
-+      if (!files)
-+              goto out;
++      struct scsi_device *device;
++      ips_ha_t *ha;
++      int count = 0;
++      int min;
 +
-+      spin_lock(&files->file_lock);
-+      fdt = files_fdtable(files);
++      ha = IPS_HA(host);
++      min = ha->max_cmds / 4;
 +
-+      for (fd = 0; fd < fdt->max_fds; fd++) {
-+              struct revokefs_inode_info *info;
-+              struct file *filp, *new_filp;
-+              struct inode *new_inode;
++      for (device = scsi_devs; device; device = device->next) {
++              if (device->host == host) {
++                      if ((device->channel == 0) && (device->type == 0))
++                              count++;
++              }
++      }
 +
-+              filp = fcheck_files(files, fd);
-+              if (!can_revoke_file(filp, inode, to_exclude))
-+                      continue;
++      for (device = scsi_devs; device; device = device->next) {
++              if (device->host == host) {
++                      if ((device->channel == 0) && (device->type == 0)) {
++                              device->queue_depth =
++                                  (ha->max_cmds - 1) / count;
++                              if (device->queue_depth < min)
++                                      device->queue_depth = min;
++                      } else {
++                              device->queue_depth = 2;
++                      }
 +
-+              if (!filp->f_op->revoke) {
-+                      err = -EOPNOTSUPP;
-+                      goto failed;
++                      if (device->queue_depth < 2)
++                              device->queue_depth = 2;
 +              }
++      }
++}
 +
-+              if (fset_is_full(fset)) {
-+                      err = -ENOMEM;
-+                      goto failed;
++#else
+ /****************************************************************************/
+ /*                                                                          */
+ /* Routine Name: ips_slave_configure                                        */
+@@ -1219,6 +1316,7 @@
+       SDptr->skip_ms_page_3f = 1;
+       return 0;
+ }
++#endif
+ /****************************************************************************/
+ /*                                                                          */
+@@ -1233,6 +1331,7 @@
+ do_ipsintr(int irq, void *dev_id)
+ {
+       ips_ha_t *ha;
++      unsigned long cpu_flags;
+       struct Scsi_Host *host;
+       int irqstatus;
+@@ -1248,16 +1347,16 @@
+               return IRQ_HANDLED;
+       }
+-      spin_lock(host->host_lock);
++      IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+       if (!ha->active) {
+-              spin_unlock(host->host_lock);
++              IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+               return IRQ_HANDLED;
+       }
+       irqstatus = (*ha->func.intr) (ha);
+-      spin_unlock(host->host_lock);
++      IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+       /* start the next command */
+       ips_next(ha, IPS_INTR_ON);
+@@ -1507,8 +1606,15 @@
+       if ((SC->cmnd[0] == IPS_IOCTL_COMMAND) &&
+           (SC->device->channel == 0) &&
+           (SC->device->id == IPS_ADAPTER_ID) &&
+-          (SC->device->lun == 0) && scsi_sglist(SC)) {
+-                struct scatterlist *sg = scsi_sglist(SC);
++          (SC->device->lun == 0) && SC->request_buffer) {
++              if ((!SC->use_sg) && SC->request_bufflen &&
++                  (((char *) SC->request_buffer)[0] == 'C') &&
++                  (((char *) SC->request_buffer)[1] == 'O') &&
++                  (((char *) SC->request_buffer)[2] == 'P') &&
++                  (((char *) SC->request_buffer)[3] == 'P'))
++                      return 1;
++              else if (SC->use_sg) {
++                      struct scatterlist *sg = SC->request_buffer;
+                       char  *buffer; 
+                       /* kmap_atomic() ensures addressability of the user buffer.*/
+@@ -1524,6 +1630,7 @@
+                       kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+                       local_irq_restore(flags);
+               }
++      }
+       return 0;
+ }
+@@ -1573,14 +1680,18 @@
+ {
+       ips_passthru_t *pt;
+       int length = 0;
+-      int i, ret;
+-        struct scatterlist *sg = scsi_sglist(SC);
++      int ret;
+       METHOD_TRACE("ips_make_passthru", 1);
+-        scsi_for_each_sg(SC, sg, scsi_sg_count(SC), i)
++      if (!SC->use_sg) {
++              length = SC->request_bufflen;
++      } else {
++              struct scatterlist *sg = SC->request_buffer;
++              int i;
++              for (i = 0; i < SC->use_sg; i++)
+                       length += sg[i].length;
+-
++      }
+       if (length < sizeof (ips_passthru_t)) {
+               /* wrong size */
+               DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
+@@ -2004,7 +2115,7 @@
+       METHOD_TRACE("ips_cleanup_passthru", 1);
+-      if ((!scb) || (!scb->scsi_cmd) || (!scsi_sglist(scb->scsi_cmd))) {
++      if ((!scb) || (!scb->scsi_cmd) || (!scb->scsi_cmd->request_buffer)) {
+               DEBUG_VAR(1, "(%s%d) couldn't cleanup after passthru",
+                         ips_name, ha->host_num);
+@@ -2619,6 +2730,7 @@
+       struct scsi_cmnd *q;
+       ips_copp_wait_item_t *item;
+       int ret;
++      unsigned long cpu_flags = 0;
+       struct Scsi_Host *host;
+       METHOD_TRACE("ips_next", 1);
+@@ -2630,7 +2742,7 @@
+        * this command won't time out
+        */
+       if (intr == IPS_INTR_ON)
+-              spin_lock(host->host_lock);
++              IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+       if ((ha->subsys->param[3] & 0x300000)
+           && (ha->scb_activelist.count == 0)) {
+@@ -2657,14 +2769,14 @@
+               item = ips_removeq_copp_head(&ha->copp_waitlist);
+               ha->num_ioctl++;
+               if (intr == IPS_INTR_ON)
+-                      spin_unlock(host->host_lock);
++                      IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+               scb->scsi_cmd = item->scsi_cmd;
+               kfree(item);
+               ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr);
+               if (intr == IPS_INTR_ON)
+-                      spin_lock(host->host_lock);
++                      IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+               switch (ret) {
+               case IPS_FAILURE:
+                       if (scb->scsi_cmd) {
+@@ -2734,7 +2846,7 @@
+               SC = ips_removeq_wait(&ha->scb_waitlist, q);
+               if (intr == IPS_INTR_ON)
+-                      spin_unlock(host->host_lock);   /* Unlock HA after command is taken off queue */
++                      IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); /* Unlock HA after command is taken off queue */
+               SC->result = DID_OK;
+               SC->host_scribble = NULL;
+@@ -2754,28 +2866,43 @@
+               /* copy in the CDB */
+               memcpy(scb->cdb, SC->cmnd, SC->cmd_len);
+-                scb->sg_count = scsi_dma_map(SC);
+-                BUG_ON(scb->sg_count < 0);
+-              if (scb->sg_count) {
++              /* Now handle the data buffer */
++              if (SC->use_sg) {
+                       struct scatterlist *sg;
+                       int i;
++                      sg = SC->request_buffer;
++                      scb->sg_count = pci_map_sg(ha->pcidev, sg, SC->use_sg,
++                                                 SC->sc_data_direction);
+                       scb->flags |= IPS_SCB_MAP_SG;
+-
+-                        scsi_for_each_sg(SC, sg, scb->sg_count, i) {
++                      for (i = 0; i < scb->sg_count; i++) {
+                               if (ips_fill_scb_sg_single
+-                                  (ha, sg_dma_address(sg), scb, i,
+-                                   sg_dma_len(sg)) < 0)
++                                  (ha, sg_dma_address(&sg[i]), scb, i,
++                                   sg_dma_len(&sg[i])) < 0)
+                                       break;
+                       }
+                       scb->dcdb.transfer_length = scb->data_len;
+               } else {
++                      if (SC->request_bufflen) {
++                              scb->data_busaddr =
++                                  pci_map_single(ha->pcidev,
++                                                 SC->request_buffer,
++                                                 SC->request_bufflen,
++                                                 SC->sc_data_direction);
++                              scb->flags |= IPS_SCB_MAP_SINGLE;
++                              ips_fill_scb_sg_single(ha, scb->data_busaddr,
++                                                     scb, 0,
++                                                     SC->request_bufflen);
++                              scb->dcdb.transfer_length = scb->data_len;
++                      } else {
+                               scb->data_busaddr = 0L;
+                               scb->sg_len = 0;
+                               scb->data_len = 0;
+                               scb->dcdb.transfer_length = 0;
+                       }
 +              }
 +
-+              new_filp = fset_get_filp(fset);
+               scb->dcdb.cmd_attribute =
+                   ips_command_direction[scb->scsi_cmd->cmnd[0]];
+@@ -2792,7 +2919,7 @@
+                       scb->dcdb.transfer_length = 0;
+               }
+               if (intr == IPS_INTR_ON)
+-                      spin_lock(host->host_lock);
++                      IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+               ret = ips_send_cmd(ha, scb);
+@@ -2831,7 +2958,7 @@
+       }                       /* end while */
+       if (intr == IPS_INTR_ON)
+-              spin_unlock(host->host_lock);
++              IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+ }
+ /****************************************************************************/
+@@ -3250,24 +3377,29 @@
+                * the rest of the data and continue.
+                */
+               if ((scb->breakup) || (scb->sg_break)) {
+-                        struct scatterlist *sg;
+-                        int sg_dma_index, ips_sg_index = 0;
+-
+                       /* we had a data breakup */
+                       scb->data_len = 0;
+-                        sg = scsi_sglist(scb->scsi_cmd);
++                      if (scb->sg_count) {
++                              /* S/G request */
++                              struct scatterlist *sg;
++                              int ips_sg_index = 0;
++                              int sg_dma_index;
 +
-+              /*
-+               * Replace original struct file pointer with a pointer to
-+               * a 'revoked file.'  After this point, we don't need to worry
-+               * about racing with sys_close or sys_dup.
-+               */
-+              rcu_assign_pointer(fdt->fd[fd], new_filp);
++                              sg = scb->scsi_cmd->request_buffer;
+                               /* Spin forward to last dma chunk */
+                               sg_dma_index = scb->breakup;
+                               /* Take care of possible partial on last chunk */
+                               ips_fill_scb_sg_single(ha,
+-                                               sg_dma_address(&sg[sg_dma_index]),
++                                                     sg_dma_address(&sg
++                                                                    [sg_dma_index]),
+                                                      scb, ips_sg_index++,
+-                                               sg_dma_len(&sg[sg_dma_index]));
++                                                     sg_dma_len(&sg
++                                                                [sg_dma_index]));
+-                        for (; sg_dma_index < scsi_sg_count(scb->scsi_cmd);
++                              for (; sg_dma_index < scb->sg_count;
+                                    sg_dma_index++) {
+                                       if (ips_fill_scb_sg_single
+                                           (ha,
+@@ -3275,6 +3407,21 @@
+                                            scb, ips_sg_index++,
+                                            sg_dma_len(&sg[sg_dma_index])) < 0)
+                                               break;
 +
-+              /*
-+               * Hold on to task until we can take down the file and its
-+               * mmap.
-+               */
-+              get_task_struct(owner);
++                              }
 +
-+              new_inode = new_filp->f_dentry->d_inode;
-+              make_revoked_inode(new_inode, inode->i_mode & S_IFMT);
++                      } else {
++                              /* Non S/G Request */
++                              (void) ips_fill_scb_sg_single(ha,
++                                                            scb->
++                                                            data_busaddr +
++                                                            (scb->sg_break *
++                                                             ha->max_xfer),
++                                                            scb, 0,
++                                                            scb->scsi_cmd->
++                                                            request_bufflen -
++                                                            (scb->sg_break *
++                                                             ha->max_xfer));
+                       }
+                       scb->dcdb.transfer_length = scb->data_len;
+@@ -3506,15 +3653,15 @@
+ static void
+ ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
+ {
++      if (scmd->use_sg) {
+               int i;
+               unsigned int min_cnt, xfer_cnt;
+               char *cdata = (char *) data;
+               unsigned char *buffer;
+               unsigned long flags;
+-        struct scatterlist *sg = scsi_sglist(scmd);
+-
++              struct scatterlist *sg = scmd->request_buffer;
+               for (i = 0, xfer_cnt = 0;
+-             (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
++                   (i < scmd->use_sg) && (xfer_cnt < count); i++) {
+                       min_cnt = min(count - xfer_cnt, sg[i].length);
+                       /* kmap_atomic() ensures addressability of the data buffer.*/
+@@ -3527,6 +3674,11 @@
+                       xfer_cnt += min_cnt;
+               }
 +
-+              info = revokefs_i(new_inode);
-+              info->fd = fd;
-+              info->file = filp;
-+              info->owner = owner;
++      } else {
++              unsigned int min_cnt = min(count, scmd->request_bufflen);
++              memcpy(scmd->request_buffer, data, min_cnt);
 +      }
-+  failed:
-+      spin_unlock(&files->file_lock);
-+      put_files_struct(files);
-+  out:
-+      return err;
-+}
-+
-+static inline bool can_revoke_vma(struct vm_area_struct *vma,
-+                                struct inode *inode, struct file *to_exclude)
-+{
-+      struct file *file = vma->vm_file;
-+
-+      if (vma->vm_flags & VM_REVOKED)
-+              return false;
-+
-+      if (!file || file == to_exclude)
-+              return false;
+ }
+ /****************************************************************************/
+@@ -3539,15 +3691,15 @@
+ static void
+ ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
+ {
++      if (scmd->use_sg) {
+               int i;
+               unsigned int min_cnt, xfer_cnt;
+               char *cdata = (char *) data;
+               unsigned char *buffer;
+               unsigned long flags;
+-        struct scatterlist *sg = scsi_sglist(scmd);
+-
++              struct scatterlist *sg = scmd->request_buffer;
+               for (i = 0, xfer_cnt = 0;
+-             (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
++                   (i < scmd->use_sg) && (xfer_cnt < count); i++) {
+                       min_cnt = min(count - xfer_cnt, sg[i].length);
+                       /* kmap_atomic() ensures addressability of the data buffer.*/
+@@ -3560,6 +3712,11 @@
+                       xfer_cnt += min_cnt;
+               }
 +
-+      return file->f_path.dentry->d_inode == inode;
-+}
++      } else {
++              unsigned int min_cnt = min(count, scmd->request_bufflen);
++              memcpy(data, scmd->request_buffer, min_cnt);
++      }
+ }
+ /****************************************************************************/
+@@ -4193,7 +4350,7 @@
+       METHOD_TRACE("ips_rdcap", 1);
+-      if (scsi_bufflen(scb->scsi_cmd) < 8)
++      if (scb->scsi_cmd->request_bufflen < 8)
+               return (0);
+       cap.lba =
+@@ -4578,7 +4735,8 @@
+       METHOD_TRACE("ips_freescb", 1);
+       if (scb->flags & IPS_SCB_MAP_SG)
+-                scsi_dma_unmap(scb->scsi_cmd);
++              pci_unmap_sg(ha->pcidev, scb->scsi_cmd->request_buffer,
++                           scb->scsi_cmd->use_sg, IPS_DMA_DIR(scb));
+       else if (scb->flags & IPS_SCB_MAP_SINGLE)
+               pci_unmap_single(ha->pcidev, scb->data_busaddr, scb->data_len,
+                                IPS_DMA_DIR(scb));
+@@ -6846,6 +7004,7 @@
+       kfree(oldha);
+       ips_sh[index] = sh;
+       ips_ha[index] = ha;
++      IPS_SCSI_SET_DEVICE(sh, ha);
+       /* Store away needed values for later use */
+       sh->io_port = ha->io_addr;
+@@ -6857,16 +7016,17 @@
+       sh->cmd_per_lun = sh->hostt->cmd_per_lun;
+       sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
+       sh->use_clustering = sh->hostt->use_clustering;
 +
-+static int __revoke_break_cow(struct task_struct *tsk, struct inode *inode,
-+                            struct file *to_exclude)
-+{
-+      struct mm_struct *mm = tsk->mm;
-+      struct vm_area_struct *vma;
-+      int err = 0;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
+       sh->max_sectors = 128;
++#endif
+       sh->max_id = ha->ntargets;
+       sh->max_lun = ha->nlun;
+       sh->max_channel = ha->nbus - 1;
+       sh->can_queue = ha->max_cmds - 1;
+-      scsi_add_host(sh, NULL);
+-      scsi_scan_host(sh);
+-
++      IPS_ADD_HOST(sh, NULL);
+       return 0;
+ }
+@@ -6909,7 +7069,7 @@
+               return -ENODEV;
+       ips_driver_template.module = THIS_MODULE;
+       ips_order_controllers();
+-      if (!ips_detect(&ips_driver_template)) {
++      if (IPS_REGISTER_HOSTS(&ips_driver_template)) {
+               pci_unregister_driver(&ips_pci_driver);
+               return -ENODEV;
+       }
+@@ -6927,6 +7087,7 @@
+ static void __exit
+ ips_module_exit(void)
+ {
++      IPS_UNREGISTER_HOSTS(&ips_driver_template);
+       pci_unregister_driver(&ips_pci_driver);
+       unregister_reboot_notifier(&ips_notifier);
+ }
+@@ -7282,9 +7443,15 @@
+       return SUCCESS;
+ }
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
+ MODULE_LICENSE("GPL");
++#endif
 +
-+      down_read(&mm->mmap_sem);
-+      for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
-+              int ret;
+ MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING);
 +
-+              if (vma->vm_flags & VM_SHARED)
-+                      continue;
++#ifdef MODULE_VERSION
+ MODULE_VERSION(IPS_VER_STRING);
++#endif
+ /*
+diff -Nurb linux-2.6.22-590/drivers/scsi/ips.h linux-2.6.22-570/drivers/scsi/ips.h
+--- linux-2.6.22-590/drivers/scsi/ips.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/ips.h        2007-07-08 19:32:17.000000000 -0400
+@@ -58,6 +58,10 @@
+    /*
+     * Some handy macros
+     */
++   #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) || defined CONFIG_HIGHIO
++      #define IPS_HIGHIO
++   #endif
 +
-+              if (!can_revoke_vma(vma, inode, to_exclude))
-+                      continue;
+    #define IPS_HA(x)                   ((ips_ha_t *) x->hostdata)
+    #define IPS_COMMAND_ID(ha, scb)     (int) (scb - ha->scbs)
+    #define IPS_IS_TROMBONE(ha)         (((ha->device_id == IPS_DEVICEID_COPPERHEAD) && \
+@@ -80,8 +84,38 @@
+     #define IPS_SGLIST_SIZE(ha)       (IPS_USE_ENH_SGLIST(ha) ? \
+                                          sizeof(IPS_ENH_SG_LIST) : sizeof(IPS_STD_SG_LIST))
++   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
++      #define pci_set_dma_mask(dev,mask) ( mask > 0xffffffff ? 1:0 )
++      #define scsi_set_pci_device(sh,dev) (0)
++   #endif
++
++   #ifndef IRQ_NONE
++      typedef void irqreturn_t;
++      #define IRQ_NONE
++      #define IRQ_HANDLED
++      #define IRQ_RETVAL(x)
++   #endif
++   
++   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++      #define IPS_REGISTER_HOSTS(SHT)      scsi_register_module(MODULE_SCSI_HA,SHT)
++      #define IPS_UNREGISTER_HOSTS(SHT)    scsi_unregister_module(MODULE_SCSI_HA,SHT)
++      #define IPS_ADD_HOST(shost,device)
++      #define IPS_REMOVE_HOST(shost)
++      #define IPS_SCSI_SET_DEVICE(sh,ha)   scsi_set_pci_device(sh, (ha)->pcidev)
++      #define IPS_PRINTK(level, pcidev, format, arg...)                 \
++            printk(level "%s %s:" format , "ips" ,     \
++            (pcidev)->slot_name , ## arg)
++      #define scsi_host_alloc(sh,size)         scsi_register(sh,size)
++      #define scsi_host_put(sh)             scsi_unregister(sh)
++   #else
++      #define IPS_REGISTER_HOSTS(SHT)      (!ips_detect(SHT))
++      #define IPS_UNREGISTER_HOSTS(SHT)
++      #define IPS_ADD_HOST(shost,device)   do { scsi_add_host(shost,device); scsi_scan_host(shost); } while (0)
++      #define IPS_REMOVE_HOST(shost)       scsi_remove_host(shost)
++      #define IPS_SCSI_SET_DEVICE(sh,ha)   do { } while (0)
+       #define IPS_PRINTK(level, pcidev, format, arg...)                 \
+             dev_printk(level , &((pcidev)->dev) , format , ## arg)
++   #endif
+    #define MDELAY(n)                  \
+       do {                            \
+@@ -100,7 +134,7 @@
+    #define pci_dma_hi32(a)         ((a >> 16) >> 16)
+    #define pci_dma_lo32(a)         (a & 0xffffffff)
+-   #if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
++   #if (BITS_PER_LONG > 32) || (defined CONFIG_HIGHMEM64G && defined IPS_HIGHIO)
+       #define IPS_ENABLE_DMA64        (1)
+    #else
+       #define IPS_ENABLE_DMA64        (0)
+@@ -417,10 +451,16 @@
+    /*
+     * Scsi_Host Template
+     */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++   static int ips_proc24_info(char *, char **, off_t, int, int, int);
++   static void ips_select_queue_depth(struct Scsi_Host *, struct scsi_device *);
++   static int ips_biosparam(Disk *disk, kdev_t dev, int geom[]);
++#else
+    static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
+    static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+               sector_t capacity, int geom[]);
+    static int ips_slave_configure(struct scsi_device *SDptr);
++#endif
+ /*
+  * Raid Command Formats
+diff -Nurb linux-2.6.22-590/drivers/scsi/iscsi_tcp.c linux-2.6.22-570/drivers/scsi/iscsi_tcp.c
+--- linux-2.6.22-590/drivers/scsi/iscsi_tcp.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/iscsi_tcp.c  2007-07-08 19:32:17.000000000 -0400
+@@ -29,15 +29,14 @@
+ #include <linux/types.h>
+ #include <linux/list.h>
+ #include <linux/inet.h>
+-#include <linux/file.h>
+ #include <linux/blkdev.h>
+ #include <linux/crypto.h>
+ #include <linux/delay.h>
+ #include <linux/kfifo.h>
+ #include <linux/scatterlist.h>
++#include <linux/mutex.h>
+ #include <net/tcp.h>
+ #include <scsi/scsi_cmnd.h>
+-#include <scsi/scsi_device.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_transport_iscsi.h>
+@@ -110,7 +109,7 @@
+       struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+       crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc);
+-      buf->sg.length += sizeof(u32);
++      buf->sg.length = tcp_conn->hdr_size;
+ }
+ static inline int
+@@ -212,14 +211,16 @@
+ static int
+ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
++      int rc;
+       struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+       struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+       struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
+       struct iscsi_session *session = conn->session;
+-      struct scsi_cmnd *sc = ctask->sc;
+       int datasn = be32_to_cpu(rhdr->datasn);
+-      iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
++      rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
++      if (rc)
++              return rc;
+       /*
+        * setup Data-In byte counter (gets decremented..)
+        */
+@@ -228,36 +229,31 @@
+       if (tcp_conn->in.datalen == 0)
+               return 0;
+-      if (tcp_ctask->exp_datasn != datasn) {
+-              debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->datasn(%d)\n",
+-                        __FUNCTION__, tcp_ctask->exp_datasn, datasn);
++      if (ctask->datasn != datasn)
+               return ISCSI_ERR_DATASN;
+-      }
+-      tcp_ctask->exp_datasn++;
++      ctask->datasn++;
+       tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+-      if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {
+-              debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+-                        __FUNCTION__, tcp_ctask->data_offset,
+-                        tcp_conn->in.datalen, scsi_bufflen(sc));
++      if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length)
+               return ISCSI_ERR_DATA_OFFSET;
+-      }
+       if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) {
++              struct scsi_cmnd *sc = ctask->sc;
 +
-+              ret = get_user_pages(tsk, tsk->mm, vma->vm_start,
-+                                   vma_pages(vma), 1, 1, NULL, NULL);
-+              if (ret < 0) {
-+                      err = ret;
-+                      break;
-+              }
+               conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
+               if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
+                       int res_count = be32_to_cpu(rhdr->residual_count);
+                       if (res_count > 0 &&
+-                          res_count <= scsi_bufflen(sc)) {
+-                              scsi_set_resid(sc, res_count);
++                          res_count <= sc->request_bufflen) {
++                              sc->resid = res_count;
+                               sc->result = (DID_OK << 16) | rhdr->cmd_status;
+                       } else
+                               sc->result = (DID_BAD_TARGET << 16) |
+                                       rhdr->cmd_status;
+               } else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) {
+-                      scsi_set_resid(sc, be32_to_cpu(rhdr->residual_count));
++                      sc->resid = be32_to_cpu(rhdr->residual_count);
+                       sc->result = (DID_OK << 16) | rhdr->cmd_status;
+               } else
+                       sc->result = (DID_OK << 16) | rhdr->cmd_status;
+@@ -285,8 +281,6 @@
+ {
+       struct iscsi_data *hdr;
+       struct scsi_cmnd *sc = ctask->sc;
+-      int i, sg_count = 0;
+-      struct scatterlist *sg;
+       hdr = &r2t->dtask.hdr;
+       memset(hdr, 0, sizeof(struct iscsi_data));
+@@ -314,9 +308,12 @@
+       iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr,
+                          sizeof(struct iscsi_hdr));
+-      sg = scsi_sglist(sc);
++      if (sc->use_sg) {
++              int i, sg_count = 0;
++              struct scatterlist *sg = sc->request_buffer;
 +
-+              unlink_file_vma(vma);
-+              fput(vma->vm_file);
-+              vma->vm_file = NULL;
+               r2t->sg = NULL;
+-      for (i = 0; i < scsi_sg_count(sc); i++, sg += 1) {
++              for (i = 0; i < sc->use_sg; i++, sg += 1) {
+                       /* FIXME: prefetch ? */
+                       if (sg_count + sg->length > r2t->data_offset) {
+                               int page_offset;
+@@ -338,6 +335,12 @@
+                       sg_count += sg->length;
+               }
+               BUG_ON(r2t->sg == NULL);
++      } else {
++              iscsi_buf_init_iov(&r2t->sendbuf,
++                          (char*)sc->request_buffer + r2t->data_offset,
++                          r2t->data_count);
++              r2t->sg = NULL;
 +      }
-+      up_read(&mm->mmap_sem);
-+      return err;
-+}
-+
-+static int revoke_break_cow(struct fileset *fset, struct inode *inode,
-+                          struct file *to_exclude)
-+{
-+      unsigned long i;
-+      int err = 0;
-+
-+      for (i = 0; i < fset->end; i++) {
-+              struct revokefs_inode_info *info;
-+              struct file *this;
+ }
+ /**
+@@ -362,16 +365,17 @@
+               return ISCSI_ERR_DATALEN;
+       }
+-      if (tcp_ctask->exp_datasn != r2tsn){
+-              debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
+-                        __FUNCTION__, tcp_ctask->exp_datasn, r2tsn);
++      if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn)
+               return ISCSI_ERR_R2TSN;
+-      }
 +
-+              this = fset->files[i];
-+              info = revokefs_i(this->f_dentry->d_inode);
++      rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
++      if (rc)
++              return rc;
 +
-+              err = __revoke_break_cow(info->owner, inode, to_exclude);
-+              if (err)
-+                      break;
++      /* FIXME: use R2TSN to detect missing R2T */
+       /* fill-in new R2T associated with the task */
+       spin_lock(&session->lock);
+-      iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+-
+       if (!ctask->sc || ctask->mtask ||
+            session->state != ISCSI_STATE_LOGGED_IN) {
+               printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "
+@@ -397,11 +401,11 @@
+                           r2t->data_length, session->max_burst);
+       r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+-      if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) {
++      if (r2t->data_offset + r2t->data_length > ctask->total_length) {
+               spin_unlock(&session->lock);
+               printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at "
+                      "offset %u and total length %d\n", r2t->data_length,
+-                     r2t->data_offset, scsi_bufflen(ctask->sc));
++                     r2t->data_offset, ctask->total_length);
+               return ISCSI_ERR_DATALEN;
+       }
+@@ -410,9 +414,9 @@
+       iscsi_solicit_data_init(conn, ctask, r2t);
+-      tcp_ctask->exp_datasn = r2tsn + 1;
++      tcp_ctask->exp_r2tsn = r2tsn + 1;
+       __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
+-      tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT;
++      tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+       list_move_tail(&ctask->running, &conn->xmitqueue);
+       scsi_queue_work(session->host, &conn->xmitwork);
+@@ -596,7 +600,7 @@
+ {
+       struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+       int buf_left = buf_size - (tcp_conn->data_copied + offset);
+-      unsigned size = min(tcp_conn->in.copy, buf_left);
++      int size = min(tcp_conn->in.copy, buf_left);
+       int rc;
+       size = min(size, ctask->data_count);
+@@ -605,7 +609,7 @@
+              size, tcp_conn->in.offset, tcp_conn->in.copied);
+       BUG_ON(size <= 0);
+-      BUG_ON(tcp_ctask->sent + size > scsi_bufflen(ctask->sc));
++      BUG_ON(tcp_ctask->sent + size > ctask->total_length);
+       rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
+                          (char*)buf + (offset + tcp_conn->data_copied), size);
+@@ -703,8 +707,25 @@
+       BUG_ON((void*)ctask != sc->SCp.ptr);
++      /*
++       * copying Data-In into the Scsi_Cmnd
++       */
++      if (!sc->use_sg) {
++              i = ctask->data_count;
++              rc = iscsi_ctask_copy(tcp_conn, ctask, sc->request_buffer,
++                                    sc->request_bufflen,
++                                    tcp_ctask->data_offset);
++              if (rc == -EAGAIN)
++                      return rc;
++              if (conn->datadgst_en)
++                      iscsi_recv_digest_update(tcp_conn, sc->request_buffer,
++                                               i);
++              rc = 0;
++              goto done;
 +      }
-+      return err;
-+}
 +
-+/*
-+ *     LOCKING: down_write(&mm->mmap_sem)
-+ *                -> spin_lock(&mapping->i_mmap_lock)
-+ */
-+static int revoke_vma(struct vm_area_struct *vma, struct zap_details *details)
-+{
-+      unsigned long restart_addr, start_addr, end_addr;
-+      int need_break;
-+
-+      start_addr = vma->vm_start;
-+      end_addr = vma->vm_end;
-+
-+  again:
-+      restart_addr = zap_page_range(vma, start_addr, end_addr - start_addr,
-+                                    details);
-+
-+      need_break = need_resched() || need_lockbreak(details->i_mmap_lock);
-+      if (need_break)
-+              goto out_need_break;
+       offset = tcp_ctask->data_offset;
+-      sg = scsi_sglist(sc);
++      sg = sc->request_buffer;
+       if (tcp_ctask->data_offset)
+               for (i = 0; i < tcp_ctask->sg_count; i++)
+@@ -713,7 +734,7 @@
+       if (offset < 0)
+               offset = 0;
+-      for (i = tcp_ctask->sg_count; i < scsi_sg_count(sc); i++) {
++      for (i = tcp_ctask->sg_count; i < sc->use_sg; i++) {
+               char *dest;
+               dest = kmap_atomic(sg[i].page, KM_SOFTIRQ0);
+@@ -758,6 +779,7 @@
+       }
+       BUG_ON(ctask->data_count);
++done:
+       /* check for non-exceptional status */
+       if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) {
+               debug_scsi("done [sc %lx res %d itt 0x%x flags 0x%x]\n",
+@@ -873,27 +895,11 @@
+               }
+       }
+-      if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV &&
+-          tcp_conn->in.copy) {
++      if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
+               uint32_t recv_digest;
+               debug_tcp("extra data_recv offset %d copy %d\n",
+                         tcp_conn->in.offset, tcp_conn->in.copy);
+-
+-              if (!tcp_conn->data_copied) {
+-                      if (tcp_conn->in.padding) {
+-                              debug_tcp("padding -> %d\n",
+-                                        tcp_conn->in.padding);
+-                              memset(pad, 0, tcp_conn->in.padding);
+-                              sg_init_one(&sg, pad, tcp_conn->in.padding);
+-                              crypto_hash_update(&tcp_conn->rx_hash,
+-                                                 &sg, sg.length);
+-                      }
+-                      crypto_hash_final(&tcp_conn->rx_hash,
+-                                        (u8 *) &tcp_conn->in.datadgst);
+-                      debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
+-              }
+-
+               rc = iscsi_tcp_copy(conn, sizeof(uint32_t));
+               if (rc) {
+                       if (rc == -EAGAIN)
+@@ -919,6 +925,7 @@
+       if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV &&
+          tcp_conn->in.copy) {
 +
-+      if (restart_addr < end_addr) {
-+              start_addr = restart_addr;
-+              goto again;
+               debug_tcp("data_recv offset %d copy %d\n",
+                      tcp_conn->in.offset, tcp_conn->in.copy);
+@@ -929,32 +936,24 @@
+                       iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+                       return 0;
+               }
+-
+-              if (tcp_conn->in.padding)
+-                      tcp_conn->in_progress = IN_PROGRESS_PAD_RECV;
+-              else if (conn->datadgst_en)
+-                      tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
+-              else
+-                      tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+-                      tcp_conn->data_copied = 0;
++              tcp_conn->in.copy -= tcp_conn->in.padding;
++              tcp_conn->in.offset += tcp_conn->in.padding;
++              if (conn->datadgst_en) {
++                      if (tcp_conn->in.padding) {
++                              debug_tcp("padding -> %d\n",
++                                        tcp_conn->in.padding);
++                              memset(pad, 0, tcp_conn->in.padding);
++                              sg_init_one(&sg, pad, tcp_conn->in.padding);
++                              crypto_hash_update(&tcp_conn->rx_hash,
++                                                 &sg, sg.length);
+       }
+-
+-      if (tcp_conn->in_progress == IN_PROGRESS_PAD_RECV &&
+-          tcp_conn->in.copy) {
+-              int copylen = min(tcp_conn->in.padding - tcp_conn->data_copied,
+-                                tcp_conn->in.copy);
+-
+-              tcp_conn->in.copy -= copylen;
+-              tcp_conn->in.offset += copylen;
+-              tcp_conn->data_copied += copylen;
+-
+-              if (tcp_conn->data_copied != tcp_conn->in.padding)
+-                      tcp_conn->in_progress = IN_PROGRESS_PAD_RECV;
+-              else if (conn->datadgst_en)
++                      crypto_hash_final(&tcp_conn->rx_hash,
++                                        (u8 *) &tcp_conn->in.datadgst);
++                      debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
+                       tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
+-              else
+-                      tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+               tcp_conn->data_copied = 0;
++              } else
++                      tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+       }
+       debug_tcp("f, processed %d from out of %d padding %d\n",
+@@ -1216,6 +1215,7 @@
+                       struct iscsi_r2t_info *r2t, int left)
+ {
+       struct iscsi_data *hdr;
++      struct scsi_cmnd *sc = ctask->sc;
+       int new_offset;
+       hdr = &r2t->dtask.hdr;
+@@ -1245,8 +1245,15 @@
+       if (iscsi_buf_left(&r2t->sendbuf))
+               return;
++      if (sc->use_sg) {
+               iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
+               r2t->sg += 1;
++      } else {
++              iscsi_buf_init_iov(&r2t->sendbuf,
++                          (char*)sc->request_buffer + new_offset,
++                          r2t->data_count);
++              r2t->sg = NULL;
 +      }
-+      vma->vm_flags |= VM_REVOKED;
-+      return 0;
-+
-+  out_need_break:
-+      spin_unlock(details->i_mmap_lock);
-+      cond_resched();
-+      spin_lock(details->i_mmap_lock);
-+      return -EINTR;
-+}
-+
-+/*
-+ *    LOCKING: spin_lock(&mapping->i_mmap_lock)
-+ */
-+static int revoke_mm(struct mm_struct *mm, struct address_space *mapping,
-+                   struct file *to_exclude)
-+{
-+      struct vm_area_struct *vma;
-+      struct zap_details details;
-+      int err = 0;
+ }
+ static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask,
+@@ -1270,10 +1277,41 @@
+ static void
+ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
+ {
++      struct scsi_cmnd *sc = ctask->sc;
+       struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+       BUG_ON(__kfifo_len(tcp_ctask->r2tqueue));
+-      tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT;
 +
-+      details.i_mmap_lock = &mapping->i_mmap_lock;
++      tcp_ctask->sent = 0;
++      tcp_ctask->sg_count = 0;
 +
-+      /*
-+       * If ->mmap_sem is under contention, we continue scanning other
-+       * mms and try again later.
-+       */
-+      if (!down_write_trylock(&mm->mmap_sem)) {
-+              err = -EAGAIN;
-+              goto out;
-+      }
-+      for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
-+              if (!(vma->vm_flags & VM_SHARED))
-+                      continue;
++      if (sc->sc_data_direction == DMA_TO_DEVICE) {
++              tcp_ctask->xmstate = XMSTATE_W_HDR;
++              tcp_ctask->exp_r2tsn = 0;
++              BUG_ON(ctask->total_length == 0);
 +
-+              if (!can_revoke_vma(vma, mapping->host, to_exclude))
-+                      continue;
++              if (sc->use_sg) {
++                      struct scatterlist *sg = sc->request_buffer;
 +
-+              err = revoke_vma(vma, &details);
-+              if (err)
-+                      break;
++                      iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
++                      tcp_ctask->sg = sg + 1;
++                      tcp_ctask->bad_sg = sg + sc->use_sg;
++              } else {
++                      iscsi_buf_init_iov(&tcp_ctask->sendbuf,
++                                         sc->request_buffer,
++                                         sc->request_bufflen);
++                      tcp_ctask->sg = NULL;
++                      tcp_ctask->bad_sg = NULL;
++              }
++              debug_scsi("cmd [itt 0x%x total %d imm_data %d "
++                         "unsol count %d, unsol offset %d]\n",
++                         ctask->itt, ctask->total_length, ctask->imm_count,
++                         ctask->unsol_count, ctask->unsol_offset);
++      } else
++              tcp_ctask->xmstate = XMSTATE_R_HDR;
 +
-+              __unlink_file_vma(vma);
-+              fput(vma->vm_file);
-+              vma->vm_file = NULL;
-+      }
-+      up_write(&mm->mmap_sem);
-+  out:
-+      return err;
++      iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
++                          sizeof(struct iscsi_hdr));
+ }
+ /**
+@@ -1286,11 +1324,9 @@
+  *    call it again later, or recover. '0' return code means successful
+  *    xmit.
+  *
+- *    Management xmit state machine consists of these states:
+- *            XMSTATE_IMM_HDR_INIT    - calculate digest of PDU Header
+- *            XMSTATE_IMM_HDR         - PDU Header xmit in progress
+- *            XMSTATE_IMM_DATA        - PDU Data xmit in progress
+- *            XMSTATE_IDLE            - management PDU is done
++ *    Management xmit state machine consists of two states:
++ *            IN_PROGRESS_IMM_HEAD - PDU Header xmit in progress
++ *            IN_PROGRESS_IMM_DATA - PDU Data xmit in progress
+  **/
+ static int
+ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+@@ -1301,34 +1337,23 @@
+       debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n",
+               conn->id, tcp_mtask->xmstate, mtask->itt);
+-      if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) {
+-              iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
+-                                 sizeof(struct iscsi_hdr));
+-
+-              if (mtask->data_count) {
++      if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
++              tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
++              if (mtask->data_count)
+                       tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
+-                      iscsi_buf_init_iov(&tcp_mtask->sendbuf,
+-                                         (char*)mtask->data,
+-                                         mtask->data_count);
+-              }
+-
+               if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
+                   conn->stop_stage != STOP_CONN_RECOVER &&
+                   conn->hdrdgst_en)
+                       iscsi_hdr_digest(conn, &tcp_mtask->headbuf,
+                                       (u8*)tcp_mtask->hdrext);
+-
+-              tcp_mtask->sent = 0;
+-              tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR_INIT;
+-              tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
+-      }
+-
+-      if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
+               rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf,
+                                  mtask->data_count);
+-              if (rc)
++              if (rc) {
++                      tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
++                      if (mtask->data_count)
++                              tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
+                       return rc;
+-              tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
++              }
+       }
+       if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) {
+@@ -1362,67 +1387,55 @@
+       return 0;
+ }
+-static int
+-iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
++static inline int
++iscsi_send_read_hdr(struct iscsi_conn *conn,
++                  struct iscsi_tcp_cmd_task *tcp_ctask)
+ {
+-      struct scsi_cmnd *sc = ctask->sc;
+-      struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+-      int rc = 0;
+-
+-      if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) {
+-              tcp_ctask->sent = 0;
+-              tcp_ctask->sg_count = 0;
+-              tcp_ctask->exp_datasn = 0;
+-
+-              if (sc->sc_data_direction == DMA_TO_DEVICE) {
+-                      struct scatterlist *sg = scsi_sglist(sc);
+-
+-                      iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
+-                      tcp_ctask->sg = sg + 1;
+-                      tcp_ctask->bad_sg = sg + scsi_sg_count(sc);
++      int rc;
+-                      debug_scsi("cmd [itt 0x%x total %d imm_data %d "
+-                                 "unsol count %d, unsol offset %d]\n",
+-                                 ctask->itt, scsi_bufflen(sc),
+-                                 ctask->imm_count, ctask->unsol_count,
+-                                 ctask->unsol_offset);
++      tcp_ctask->xmstate &= ~XMSTATE_R_HDR;
++      if (conn->hdrdgst_en)
++              iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
++                               (u8*)tcp_ctask->hdrext);
++      rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0);
++      if (!rc) {
++              BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE);
++              return 0; /* wait for Data-In */
+       }
++      tcp_ctask->xmstate |= XMSTATE_R_HDR;
++      return rc;
 +}
-+
-+/*
-+ *    LOCKING: spin_lock(&mapping->i_mmap_lock)
-+ */
-+static void revoke_mapping_tree(struct address_space *mapping,
-+                              struct file *to_exclude)
+-              iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
+-                                sizeof(struct iscsi_hdr));
++static inline int
++iscsi_send_write_hdr(struct iscsi_conn *conn,
++                   struct iscsi_cmd_task *ctask)
 +{
-+      struct vm_area_struct *vma;
-+      struct prio_tree_iter iter;
-+      int try_again = 0;
-+
-+  restart:
-+      vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, 0, ULONG_MAX) {
-+              int err;
-+
-+              if (!(vma->vm_flags & VM_SHARED))
-+                      continue;
-+
-+              if (likely(!can_revoke_vma(vma, mapping->host, to_exclude)))
-+                      continue;
++      struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
++      int rc;
++      tcp_ctask->xmstate &= ~XMSTATE_W_HDR;
+       if (conn->hdrdgst_en)
+               iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+                                (u8*)tcp_ctask->hdrext);
+-              tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT;
+-              tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT;
+-      }
+-
+-      if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) {
+       rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
+-              if (rc)
++      if (rc) {
++              tcp_ctask->xmstate |= XMSTATE_W_HDR;
+               return rc;
+-              tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT;
+-
+-              if (sc->sc_data_direction != DMA_TO_DEVICE)
+-                      return 0;
++      }
+       if (ctask->imm_count) {
+               tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
+               iscsi_set_padding(tcp_ctask, ctask->imm_count);
+               if (ctask->conn->datadgst_en) {
+-                              iscsi_data_digest_init(ctask->conn->dd_data,
+-                                                     tcp_ctask);
++                      iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask);
+                       tcp_ctask->immdigest = 0;
+               }
+       }
+       if (ctask->unsol_count)
+-                      tcp_ctask->xmstate |=
+-                                      XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
+-      }
+-      return rc;
++              tcp_ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
++      return 0;
+ }
+ static int
+@@ -1611,7 +1624,9 @@
+       struct iscsi_data_task *dtask;
+       int left, rc;
+-      if (tcp_ctask->xmstate & XMSTATE_SOL_HDR_INIT) {
++      if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
++              tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
++              tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+               if (!tcp_ctask->r2t) {
+                       spin_lock_bh(&session->lock);
+                       __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
+@@ -1625,19 +1640,12 @@
+               if (conn->hdrdgst_en)
+                       iscsi_hdr_digest(conn, &r2t->headbuf,
+                                       (u8*)dtask->hdrext);
+-              tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR_INIT;
+-                      tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+-              }
+-
+-      if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
+-              r2t = tcp_ctask->r2t;
+-              dtask = &r2t->dtask;
+-
+               rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
+-              if (rc)
++              if (rc) {
++                      tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
++                      tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+                       return rc;
+-              tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+-              tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
++              }
+               if (conn->datadgst_en) {
+                       iscsi_data_digest_init(conn->dd_data, tcp_ctask);
+@@ -1669,6 +1677,8 @@
+               left = r2t->data_length - r2t->sent;
+               if (left) {
+                       iscsi_solicit_data_cont(conn, ctask, r2t, left);
++                      tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
++                      tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+                       goto send_hdr;
+               }
+@@ -1683,6 +1693,8 @@
+               if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t,
+                               sizeof(void*))) {
+                       tcp_ctask->r2t = r2t;
++                      tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
++                      tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+                       spin_unlock_bh(&session->lock);
+                       goto send_hdr;
+               }
+@@ -1691,46 +1703,6 @@
+       return 0;
+ }
+-/**
+- * iscsi_tcp_ctask_xmit - xmit normal PDU task
+- * @conn: iscsi connection
+- * @ctask: iscsi command task
+- *
+- * Notes:
+- *    The function can return -EAGAIN in which case caller must
+- *    call it again later, or recover. '0' return code means successful
+- *    xmit.
+- *    The function is devided to logical helpers (above) for the different
+- *    xmit stages.
+- *
+- *iscsi_send_cmd_hdr()
+- *    XMSTATE_CMD_HDR_INIT - prepare Header and Data buffers Calculate
+- *                           Header Digest
+- *    XMSTATE_CMD_HDR_XMIT - Transmit header in progress
+- *
+- *iscsi_send_padding
+- *    XMSTATE_W_PAD        - Prepare and send pading
+- *    XMSTATE_W_RESEND_PAD - retry send pading
+- *
+- *iscsi_send_digest
+- *    XMSTATE_W_RESEND_DATA_DIGEST - Finalize and send Data Digest
+- *    XMSTATE_W_RESEND_DATA_DIGEST - retry sending digest
+- *
+- *iscsi_send_unsol_hdr
+- *    XMSTATE_UNS_INIT     - prepare un-solicit data header and digest
+- *    XMSTATE_UNS_HDR      - send un-solicit header
+- *
+- *iscsi_send_unsol_pdu
+- *    XMSTATE_UNS_DATA     - send un-solicit data in progress
+- *
+- *iscsi_send_sol_pdu
+- *    XMSTATE_SOL_HDR_INIT - solicit data header and digest initialize
+- *    XMSTATE_SOL_HDR      - send solicit header
+- *    XMSTATE_SOL_DATA     - send solicit data
+- *
+- *iscsi_tcp_ctask_xmit
+- *    XMSTATE_IMM_DATA     - xmit managment data (??)
+- **/
+ static int
+ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+@@ -1740,11 +1712,20 @@
+       debug_scsi("ctask deq [cid %d xmstate %x itt 0x%x]\n",
+               conn->id, tcp_ctask->xmstate, ctask->itt);
+-      rc = iscsi_send_cmd_hdr(conn, ctask);
++      /*
++       * serialize with TMF AbortTask
++       */
++      if (ctask->mtask)
++              return rc;
 +
-+              err = revoke_mm(vma->vm_mm, mapping, to_exclude);
-+              if (err == -EAGAIN)
-+                      try_again = 1;
++      if (tcp_ctask->xmstate & XMSTATE_R_HDR)
++              return iscsi_send_read_hdr(conn, tcp_ctask);
 +
-+              goto restart;
-+      }
-+      if (try_again) {
-+              cond_resched();
-+              goto restart;
++      if (tcp_ctask->xmstate & XMSTATE_W_HDR) {
++              rc = iscsi_send_write_hdr(conn, ctask);
+               if (rc)
+                       return rc;
+-      if (ctask->sc->sc_data_direction != DMA_TO_DEVICE)
+-              return 0;
 +      }
-+}
-+
-+/*
-+ *    LOCKING: spin_lock(&mapping->i_mmap_lock)
-+ */
-+static void revoke_mapping_list(struct address_space *mapping,
-+                              struct file *to_exclude)
-+{
-+      struct vm_area_struct *vma;
-+      int try_again = 0;
-+
-+  restart:
-+      list_for_each_entry(vma, &mapping->i_mmap_nonlinear, shared.vm_set.list) {
-+              int err;
+       if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) {
+               rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg,
+@@ -1829,22 +1810,18 @@
+ static void
+ iscsi_tcp_release_conn(struct iscsi_conn *conn)
+ {
+-      struct iscsi_session *session = conn->session;
+       struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-      struct socket *sock = tcp_conn->sock;
+-      if (!sock)
++      if (!tcp_conn->sock)
+               return;
+-      sock_hold(sock->sk);
++      sock_hold(tcp_conn->sock->sk);
+       iscsi_conn_restore_callbacks(tcp_conn);
+-      sock_put(sock->sk);
++      sock_put(tcp_conn->sock->sk);
+-      spin_lock_bh(&session->lock);
++      sock_release(tcp_conn->sock);
+       tcp_conn->sock = NULL;
+       conn->recv_lock = NULL;
+-      spin_unlock_bh(&session->lock);
+-      sockfd_put(sock);
+ }
+ static void
+@@ -1875,46 +1852,6 @@
+       tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+ }
+-static int iscsi_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
+-                            char *buf, int *port,
+-                            int (*getname)(struct socket *, struct sockaddr *,
+-                                      int *addrlen))
+-{
+-      struct sockaddr_storage *addr;
+-      struct sockaddr_in6 *sin6;
+-      struct sockaddr_in *sin;
+-      int rc = 0, len;
+-
+-      addr = kmalloc(GFP_KERNEL, sizeof(*addr));
+-      if (!addr)
+-              return -ENOMEM;
+-
+-      if (getname(sock, (struct sockaddr *) addr, &len)) {
+-              rc = -ENODEV;
+-              goto free_addr;
+-      }
+-
+-      switch (addr->ss_family) {
+-      case AF_INET:
+-              sin = (struct sockaddr_in *)addr;
+-              spin_lock_bh(&conn->session->lock);
+-              sprintf(buf, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
+-              *port = be16_to_cpu(sin->sin_port);
+-              spin_unlock_bh(&conn->session->lock);
+-              break;
+-      case AF_INET6:
+-              sin6 = (struct sockaddr_in6 *)addr;
+-              spin_lock_bh(&conn->session->lock);
+-              sprintf(buf, NIP6_FMT, NIP6(sin6->sin6_addr));
+-              *port = be16_to_cpu(sin6->sin6_port);
+-              spin_unlock_bh(&conn->session->lock);
+-              break;
+-      }
+-free_addr:
+-      kfree(addr);
+-      return rc;
+-}
+-
+ static int
+ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+                   struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
+@@ -1932,24 +1869,10 @@
+               printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err);
+               return -EEXIST;
+       }
+-      /*
+-       * copy these values now because if we drop the session
+-       * userspace may still want to query the values since we will
+-       * be using them for the reconnect
+-       */
+-      err = iscsi_tcp_get_addr(conn, sock, conn->portal_address,
+-                               &conn->portal_port, kernel_getpeername);
+-      if (err)
+-              goto free_socket;
+-
+-      err = iscsi_tcp_get_addr(conn, sock, conn->local_address,
+-                              &conn->local_port, kernel_getsockname);
+-      if (err)
+-              goto free_socket;
+       err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+       if (err)
+-              goto free_socket;
++              return err;
+       /* bind iSCSI connection and socket */
+       tcp_conn->sock = sock;
+@@ -1973,19 +1896,25 @@
+        * set receive state machine into initial state
+        */
+       tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+-      return 0;
+-free_socket:
+-      sockfd_put(sock);
+-      return err;
++      return 0;
+ }
+ /* called with host lock */
+ static void
+-iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
++iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
++                  char *data, uint32_t data_size)
+ {
+       struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
+-      tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT;
 +
-+              if (likely(!can_revoke_vma(vma, mapping->host, to_exclude)))
-+                      continue;
++      iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
++                         sizeof(struct iscsi_hdr));
++      tcp_mtask->xmstate = XMSTATE_IMM_HDR;
++      tcp_mtask->sent = 0;
 +
-+              err = revoke_mm(vma->vm_mm, mapping, to_exclude);
-+              if (err == -EAGAIN) {
-+                      try_again = 1;
-+                      continue;
++      if (mtask->data_count)
++              iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data,
++                                  mtask->data_count);
+ }
+ static int
+@@ -2097,46 +2026,46 @@
+                        enum iscsi_param param, char *buf)
+ {
+       struct iscsi_conn *conn = cls_conn->dd_data;
++      struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++      struct inet_sock *inet;
++      struct ipv6_pinfo *np;
++      struct sock *sk;
+       int len;
+       switch(param) {
+       case ISCSI_PARAM_CONN_PORT:
+-              spin_lock_bh(&conn->session->lock);
+-              len = sprintf(buf, "%hu\n", conn->portal_port);
+-              spin_unlock_bh(&conn->session->lock);
++              mutex_lock(&conn->xmitmutex);
++              if (!tcp_conn->sock) {
++                      mutex_unlock(&conn->xmitmutex);
++                      return -EINVAL;
 +              }
-+              if (err == -EINTR)
-+                      goto restart;
-+      }
-+      if (try_again) {
-+              cond_resched();
-+              goto restart;
-+      }
-+}
-+
-+static void revoke_mapping(struct address_space *mapping, struct file *to_exclude)
-+{
-+      spin_lock(&mapping->i_mmap_lock);
-+      if (unlikely(!prio_tree_empty(&mapping->i_mmap)))
-+              revoke_mapping_tree(mapping, to_exclude);
-+      if (unlikely(!list_empty(&mapping->i_mmap_nonlinear)))
-+              revoke_mapping_list(mapping, to_exclude);
-+      spin_unlock(&mapping->i_mmap_lock);
-+}
-+
-+static void restore_file(struct revokefs_inode_info *info)
-+{
-+      struct files_struct *files;
-+
-+      files = get_files_struct(info->owner);
-+      if (files) {
-+              struct fdtable *fdt;
-+              struct file *filp;
-+
-+              spin_lock(&files->file_lock);
-+              fdt = files_fdtable(files);
-+
-+              filp = fdt->fd[info->fd];
-+              if (filp)
-+                      fput(filp);
-+
-+              rcu_assign_pointer(fdt->fd[info->fd], info->file);
-+              FD_SET(info->fd, fdt->close_on_exec);
-+              spin_unlock(&files->file_lock);
-+              put_files_struct(files);
-+      }
-+      put_task_struct(info->owner);
-+      info->owner = NULL;     /* To avoid double-restore. */
-+}
 +
-+static void restore_files(struct revoke_details *details)
-+{
-+      unsigned long i;
-+
-+      for (i = details->restore_start; i < details->fset->end; i++) {
-+              struct revokefs_inode_info *info;
-+              struct file *filp;
-+
-+              filp = details->fset->files[i];
-+              info = revokefs_i(filp->f_dentry->d_inode);
-+
-+              restore_file(info);
-+      }
-+}
-+
-+static int revoke_files(struct revoke_details *details)
-+{
-+      unsigned long i;
-+      int err = 0;
-+
-+      for (i = 0; i < details->fset->end; i++) {
-+              struct revokefs_inode_info *info;
-+              struct file *this, *filp;
-+              struct inode *inode;
-+
-+              this = details->fset->files[i];
-+              inode = this->f_dentry->d_inode;
-+              info = revokefs_i(inode);
-+
-+              /*
-+               * Increase count before attempting to close file as
-+               * an partially closed file can no longer be restored.
-+               */
-+              details->restore_start++;
-+              filp = info->file;
-+              err = filp->f_op->revoke(filp, inode->i_mapping);
-+              put_task_struct(info->owner);
-+              info->owner = NULL;     /* To avoid restoring closed file. */
-+              if (err)
-+                      goto out;
-+      }
-+  out:
-+      return err;
-+}
-+
-+/*
-+ *    Returns the maximum number of file descriptors pointing to an inode.
-+ *
-+ *    LOCKING: read_lock(&tasklist_lock)
-+ */
-+static unsigned long inode_fds(struct inode *inode, struct file *to_exclude)
-+{
-+      struct task_struct *g, *p;
-+      unsigned long nr_fds = 0;
-+
-+      do_each_thread(g, p) {
-+              struct files_struct *files;
-+              struct fdtable *fdt;
-+              unsigned int fd;
-+
-+              files = get_files_struct(p);
-+              if (!files)
-+                      continue;
-+
-+              spin_lock(&files->file_lock);
-+              fdt = files_fdtable(files);
-+              for (fd = 0; fd < fdt->max_fds; fd++) {
-+                      struct file *file;
-+
-+                      file = fcheck_files(files, fd);
-+                      if (can_revoke_file(file, inode, to_exclude)) {
-+                              nr_fds += fdt->max_fds;
-+                              break;
-+                      }
++              inet = inet_sk(tcp_conn->sock->sk);
++              len = sprintf(buf, "%hu\n", be16_to_cpu(inet->dport));
++              mutex_unlock(&conn->xmitmutex);
+               break;
+       case ISCSI_PARAM_CONN_ADDRESS:
+-              spin_lock_bh(&conn->session->lock);
+-              len = sprintf(buf, "%s\n", conn->portal_address);
+-              spin_unlock_bh(&conn->session->lock);
+-              break;
+-      default:
+-              return iscsi_conn_get_param(cls_conn, param, buf);
++              mutex_lock(&conn->xmitmutex);
++              if (!tcp_conn->sock) {
++                      mutex_unlock(&conn->xmitmutex);
++                      return -EINVAL;
+       }
+-      return len;
+-}
+-
+-static int
+-iscsi_tcp_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+-                       char *buf)
+-{
+-        struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+-      int len;
+-
+-      switch (param) {
+-      case ISCSI_HOST_PARAM_IPADDRESS:
+-              spin_lock_bh(&session->lock);
+-              if (!session->leadconn)
+-                      len = -ENODEV;
+-              else
+-                      len = sprintf(buf, "%s\n",
+-                                   session->leadconn->local_address);
+-              spin_unlock_bh(&session->lock);
++              sk = tcp_conn->sock->sk;
++              if (sk->sk_family == PF_INET) {
++                      inet = inet_sk(sk);
++                      len = sprintf(buf, NIPQUAD_FMT "\n",
++                                    NIPQUAD(inet->daddr));
++              } else {
++                      np = inet6_sk(sk);
++                      len = sprintf(buf, NIP6_FMT "\n", NIP6(np->daddr));
 +              }
-+              spin_unlock(&files->file_lock);
-+              put_files_struct(files);
-+      }
-+      while_each_thread(g, p);
-+      return nr_fds;
-+}
++              mutex_unlock(&conn->xmitmutex);
+               break;
+       default:
+-              return iscsi_host_get_param(shost, param, buf);
++              return iscsi_conn_get_param(cls_conn, param, buf);
+       }
 +
-+static struct fileset *__alloc_revoke_fset(unsigned long size)
+       return len;
+ }
+@@ -2167,7 +2096,6 @@
+ static struct iscsi_cls_session *
+ iscsi_tcp_session_create(struct iscsi_transport *iscsit,
+                        struct scsi_transport_template *scsit,
+-                       uint16_t cmds_max, uint16_t qdepth,
+                        uint32_t initial_cmdsn, uint32_t *hostno)
+ {
+       struct iscsi_cls_session *cls_session;
+@@ -2175,7 +2103,7 @@
+       uint32_t hn;
+       int cmd_i;
+-      cls_session = iscsi_session_setup(iscsit, scsit, cmds_max, qdepth,
++      cls_session = iscsi_session_setup(iscsit, scsit,
+                                        sizeof(struct iscsi_tcp_cmd_task),
+                                        sizeof(struct iscsi_tcp_mgmt_task),
+                                        initial_cmdsn, &hn);
+@@ -2214,24 +2142,17 @@
+       iscsi_session_teardown(cls_session);
+ }
+-static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
+-{
+-      blk_queue_dma_alignment(sdev->request_queue, 0);
+-      return 0;
+-}
+-
+ static struct scsi_host_template iscsi_sht = {
+       .name                   = "iSCSI Initiator over TCP/IP",
+       .queuecommand           = iscsi_queuecommand,
+       .change_queue_depth     = iscsi_change_queue_depth,
+-      .can_queue              = ISCSI_DEF_XMIT_CMDS_MAX - 1,
++      .can_queue              = ISCSI_XMIT_CMDS_MAX - 1,
+       .sg_tablesize           = ISCSI_SG_TABLESIZE,
+       .max_sectors            = 0xFFFF,
+       .cmd_per_lun            = ISCSI_DEF_CMD_PER_LUN,
+       .eh_abort_handler       = iscsi_eh_abort,
+       .eh_host_reset_handler  = iscsi_eh_host_reset,
+       .use_clustering         = DISABLE_CLUSTERING,
+-      .slave_configure        = iscsi_tcp_slave_configure,
+       .proc_name              = "iscsi_tcp",
+       .this_id                = -1,
+ };
+@@ -2258,12 +2179,8 @@
+                                 ISCSI_EXP_STATSN |
+                                 ISCSI_PERSISTENT_PORT |
+                                 ISCSI_PERSISTENT_ADDRESS |
+-                                ISCSI_TARGET_NAME | ISCSI_TPGT |
+-                                ISCSI_USERNAME | ISCSI_PASSWORD |
+-                                ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
+-      .host_param_mask        = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+-                                ISCSI_HOST_INITIATOR_NAME |
+-                                ISCSI_HOST_NETDEV_NAME,
++                                ISCSI_TARGET_NAME |
++                                ISCSI_TPGT,
+       .host_template          = &iscsi_sht,
+       .conndata_size          = sizeof(struct iscsi_conn),
+       .max_conn               = 1,
+@@ -2280,9 +2197,6 @@
+       .get_session_param      = iscsi_session_get_param,
+       .start_conn             = iscsi_conn_start,
+       .stop_conn              = iscsi_tcp_conn_stop,
+-      /* iscsi host params */
+-      .get_host_param         = iscsi_tcp_host_get_param,
+-      .set_host_param         = iscsi_host_set_param,
+       /* IO */
+       .send_pdu               = iscsi_conn_send_pdu,
+       .get_stats              = iscsi_conn_get_stats,
+diff -Nurb linux-2.6.22-590/drivers/scsi/iscsi_tcp.h linux-2.6.22-570/drivers/scsi/iscsi_tcp.h
+--- linux-2.6.22-590/drivers/scsi/iscsi_tcp.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/iscsi_tcp.h  2007-07-08 19:32:17.000000000 -0400
+@@ -29,12 +29,11 @@
+ #define IN_PROGRESS_HEADER_GATHER     0x1
+ #define IN_PROGRESS_DATA_RECV         0x2
+ #define IN_PROGRESS_DDIGEST_RECV      0x3
+-#define IN_PROGRESS_PAD_RECV          0x4
+ /* xmit state machine */
+ #define XMSTATE_IDLE                  0x0
+-#define XMSTATE_CMD_HDR_INIT          0x1
+-#define XMSTATE_CMD_HDR_XMIT          0x2
++#define XMSTATE_R_HDR                 0x1
++#define XMSTATE_W_HDR                 0x2
+ #define XMSTATE_IMM_HDR                       0x4
+ #define XMSTATE_IMM_DATA              0x8
+ #define XMSTATE_UNS_INIT              0x10
+@@ -45,8 +44,6 @@
+ #define XMSTATE_W_PAD                 0x200
+ #define XMSTATE_W_RESEND_PAD          0x400
+ #define XMSTATE_W_RESEND_DATA_DIGEST  0x800
+-#define XMSTATE_IMM_HDR_INIT          0x1000
+-#define XMSTATE_SOL_HDR_INIT          0x2000
+ #define ISCSI_PAD_LEN                 4
+ #define ISCSI_SG_TABLESIZE            SG_ALL
+@@ -155,7 +152,7 @@
+       struct scatterlist      *sg;                    /* per-cmd SG list  */
+       struct scatterlist      *bad_sg;                /* assert statement */
+       int                     sg_count;               /* SG's to process  */
+-      uint32_t                exp_datasn;             /* expected target's R2TSN/DataSN */
++      uint32_t                exp_r2tsn;
+       int                     data_offset;
+       struct iscsi_r2t_info   *r2t;                   /* in progress R2T    */
+       struct iscsi_queue      r2tpool;
+diff -Nurb linux-2.6.22-590/drivers/scsi/jazz_esp.c linux-2.6.22-570/drivers/scsi/jazz_esp.c
+--- linux-2.6.22-590/drivers/scsi/jazz_esp.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/jazz_esp.c   2007-07-08 19:32:17.000000000 -0400
+@@ -1,6 +1,6 @@
+ /* jazz_esp.c: ESP front-end for MIPS JAZZ systems.
+  *
+- * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
++ * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
+  */
+ #include <linux/kernel.h>
+@@ -143,7 +143,7 @@
+               goto fail;
+       host->max_id = 8;
+-      esp = shost_priv(host);
++      esp = host_to_esp(host);
+       esp->host = host;
+       esp->dev = dev;
+diff -Nurb linux-2.6.22-590/drivers/scsi/libiscsi.c linux-2.6.22-570/drivers/scsi/libiscsi.c
+--- linux-2.6.22-590/drivers/scsi/libiscsi.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/libiscsi.c   2007-07-08 19:32:17.000000000 -0400
+@@ -22,6 +22,7 @@
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  */
+ #include <linux/types.h>
++#include <linux/mutex.h>
+ #include <linux/kfifo.h>
+ #include <linux/delay.h>
+ #include <asm/unaligned.h>
+@@ -45,53 +46,27 @@
+ }
+ EXPORT_SYMBOL_GPL(class_to_transport_session);
+-/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
+-#define SNA32_CHECK 2147483648UL
++#define INVALID_SN_DELTA      0xffff
+-static int iscsi_sna_lt(u32 n1, u32 n2)
+-{
+-      return n1 != n2 && ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) ||
+-                          (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
+-}
+-
+-/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
+-static int iscsi_sna_lte(u32 n1, u32 n2)
+-{
+-      return n1 == n2 || ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) ||
+-                          (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
+-}
+-
+-void
+-iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
++int
++iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+ {
+       uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn);
+       uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn);
+-      /*
+-       * standard specifies this check for when to update expected and
+-       * max sequence numbers
+-       */
+-      if (iscsi_sna_lt(max_cmdsn, exp_cmdsn - 1))
+-              return;
+-
+-      if (exp_cmdsn != session->exp_cmdsn &&
+-          !iscsi_sna_lt(exp_cmdsn, session->exp_cmdsn))
++      if (max_cmdsn < exp_cmdsn -1 &&
++          max_cmdsn > exp_cmdsn - INVALID_SN_DELTA)
++              return ISCSI_ERR_MAX_CMDSN;
++      if (max_cmdsn > session->max_cmdsn ||
++          max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA)
++              session->max_cmdsn = max_cmdsn;
++      if (exp_cmdsn > session->exp_cmdsn ||
++          exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA)
+               session->exp_cmdsn = exp_cmdsn;
+-      if (max_cmdsn != session->max_cmdsn &&
+-          !iscsi_sna_lt(max_cmdsn, session->max_cmdsn)) {
+-              session->max_cmdsn = max_cmdsn;
+-              /*
+-               * if the window closed with IO queued, then kick the
+-               * xmit thread
+-               */
+-              if (!list_empty(&session->leadconn->xmitqueue) ||
+-                  __kfifo_len(session->leadconn->mgmtqueue))
+-                      scsi_queue_work(session->host,
+-                                      &session->leadconn->xmitwork);
+-      }
++      return 0;
+ }
+-EXPORT_SYMBOL_GPL(iscsi_update_cmdsn);
++EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn);
+ void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
+                                  struct iscsi_data *hdr)
+@@ -140,17 +115,14 @@
+         hdr->flags = ISCSI_ATTR_SIMPLE;
+         int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+         hdr->itt = build_itt(ctask->itt, conn->id, session->age);
+-        hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
++        hdr->data_length = cpu_to_be32(sc->request_bufflen);
+         hdr->cmdsn = cpu_to_be32(session->cmdsn);
+         session->cmdsn++;
+         hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+         memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
+-      if (sc->cmd_len < MAX_COMMAND_SIZE)
+-              memset(&hdr->cdb[sc->cmd_len], 0,
+-                      MAX_COMMAND_SIZE - sc->cmd_len);
++        memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len);
+       ctask->data_count = 0;
+-      ctask->imm_count = 0;
+       if (sc->sc_data_direction == DMA_TO_DEVICE) {
+               hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+               /*
+@@ -167,24 +139,25 @@
+                *
+                *      pad_count       bytes to be sent as zero-padding
+                */
++              ctask->imm_count = 0;
+               ctask->unsol_count = 0;
+               ctask->unsol_offset = 0;
+               ctask->unsol_datasn = 0;
+               if (session->imm_data_en) {
+-                      if (scsi_bufflen(sc) >= session->first_burst)
++                      if (ctask->total_length >= session->first_burst)
+                               ctask->imm_count = min(session->first_burst,
+                                                       conn->max_xmit_dlength);
+                       else
+-                              ctask->imm_count = min(scsi_bufflen(sc),
++                              ctask->imm_count = min(ctask->total_length,
+                                                       conn->max_xmit_dlength);
+                       hton24(ctask->hdr->dlength, ctask->imm_count);
+               } else
+                       zero_data(ctask->hdr->dlength);
+               if (!session->initial_r2t_en) {
+-                      ctask->unsol_count = min((session->first_burst),
+-                              (scsi_bufflen(sc))) - ctask->imm_count;
++                      ctask->unsol_count = min(session->first_burst,
++                              ctask->total_length) - ctask->imm_count;
+                       ctask->unsol_offset = ctask->imm_count;
+               }
+@@ -192,6 +165,7 @@
+                       /* No unsolicit Data-Out's */
+                       ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+       } else {
++              ctask->datasn = 0;
+               hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+               zero_data(hdr->dlength);
+@@ -200,13 +174,8 @@
+       }
+       conn->scsicmd_pdus_cnt++;
+-
+-        debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
+-              "cmdsn %d win %d]\n",
+-                sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+-              conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
+-                session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ }
++EXPORT_SYMBOL_GPL(iscsi_prep_scsi_cmd_pdu);
+ /**
+  * iscsi_complete_command - return command back to scsi-ml
+@@ -235,12 +204,26 @@
+       atomic_inc(&ctask->refcount);
+ }
++static void iscsi_get_ctask(struct iscsi_cmd_task *ctask)
 +{
-+      struct fileset *fset;
-+      int i;
-+
-+      fset = alloc_fset(size);
-+      if (!fset)
-+              return NULL;
-+
-+      for (i = 0; i < fset->nr; i++) {
-+              struct file *filp;
-+
-+              filp = get_revoked_file();
-+              if (!filp)
-+                      goto err;
-+
-+              fset->files[i] = filp;
-+      }
-+      return fset;
-+  err:
-+      free_fset(fset);
-+      return NULL;
++      spin_lock_bh(&ctask->conn->session->lock);
++      __iscsi_get_ctask(ctask);
++      spin_unlock_bh(&ctask->conn->session->lock);
 +}
 +
-+static struct fileset *alloc_revoke_fset(struct inode *inode, struct file *to_exclude)
+ static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask)
+ {
+       if (atomic_dec_and_test(&ctask->refcount))
+               iscsi_complete_command(ctask);
+ }
++static void iscsi_put_ctask(struct iscsi_cmd_task *ctask)
 +{
-+      unsigned long nr_fds;
-+
-+      read_lock(&tasklist_lock);
-+      nr_fds = inode_fds(inode, to_exclude);
-+      read_unlock(&tasklist_lock);
-+
-+      return __alloc_revoke_fset(nr_fds);
++      spin_lock_bh(&ctask->conn->session->lock);
++      __iscsi_put_ctask(ctask);
++      spin_unlock_bh(&ctask->conn->session->lock);
 +}
 +
-+static int do_revoke(struct inode *inode, struct file *to_exclude)
-+{
-+      struct revoke_details details;
-+      struct fileset *fset = NULL;
-+      struct task_struct *g, *p;
-+      int err = 0;
-+
-+      if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER)) {
-+              err = -EPERM;
+ /**
+  * iscsi_cmd_rsp - SCSI Command Response processing
+  * @conn: iscsi connection
+@@ -252,15 +235,21 @@
+  * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and
+  * then completes the command and task.
+  **/
+-static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+                             struct iscsi_cmd_task *ctask, char *data,
+                             int datalen)
+ {
++      int rc;
+       struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr;
+       struct iscsi_session *session = conn->session;
+       struct scsi_cmnd *sc = ctask->sc;
+-      iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
++      rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
++      if (rc) {
++              sc->result = DID_ERROR << 16;
 +              goto out;
 +      }
 +
-+  retry:
-+      if (signal_pending(current)) {
-+              err = -ERESTARTSYS;
-+              goto out;
-+      }
+       conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
+       sc->result = (DID_OK << 16) | rhdr->cmd_status;
+@@ -297,14 +286,14 @@
+       if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
+               int res_count = be32_to_cpu(rhdr->residual_count);
+-              if (res_count > 0 && res_count <= scsi_bufflen(sc))
+-                      scsi_set_resid(sc, res_count);
++              if (res_count > 0 && res_count <= sc->request_bufflen)
++                      sc->resid = res_count;
+               else
+                       sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+       } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW)
+               sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+       else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW)
+-              scsi_set_resid(sc, be32_to_cpu(rhdr->residual_count));
++              sc->resid = be32_to_cpu(rhdr->residual_count);
+ out:
+       debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+@@ -312,6 +301,7 @@
+       conn->scsirsp_pdus_cnt++;
+       __iscsi_put_ctask(ctask);
++      return rc;
+ }
+ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+@@ -391,7 +381,7 @@
+               switch(opcode) {
+               case ISCSI_OP_SCSI_CMD_RSP:
+                       BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+-                      iscsi_scsi_cmd_rsp(conn, hdr, ctask, data,
++                      rc = iscsi_scsi_cmd_rsp(conn, hdr, ctask, data,
+                                               datalen);
+                       break;
+               case ISCSI_OP_SCSI_DATA_IN:
+@@ -415,7 +405,11 @@
+               debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n",
+                          opcode, conn->id, mtask->itt, datalen);
+-              iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
++              rc = iscsi_check_assign_cmdsn(session,
++                                            (struct iscsi_nopin*)hdr);
++              if (rc)
++                      goto done;
++
+               switch(opcode) {
+               case ISCSI_OP_LOGOUT_RSP:
+                       if (datalen) {
+@@ -464,7 +458,10 @@
+                       break;
+               }
+       } else if (itt == ~0U) {
+-              iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
++              rc = iscsi_check_assign_cmdsn(session,
++                                           (struct iscsi_nopin*)hdr);
++              if (rc)
++                      goto done;
+               switch(opcode) {
+               case ISCSI_OP_NOOP_IN:
+@@ -494,6 +491,7 @@
+       } else
+               rc = ISCSI_ERR_BAD_ITT;
++done:
+       return rc;
+ }
+ EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
+@@ -580,47 +578,17 @@
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_failure);
+-static void iscsi_prep_mtask(struct iscsi_conn *conn,
+-                           struct iscsi_mgmt_task *mtask)
+-{
+-      struct iscsi_session *session = conn->session;
+-      struct iscsi_hdr *hdr = mtask->hdr;
+-      struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
+-
+-      if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) &&
+-          hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
+-              nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
+-      /*
+-       * pre-format CmdSN for outgoing PDU.
+-       */
+-      nop->cmdsn = cpu_to_be32(session->cmdsn);
+-      if (hdr->itt != RESERVED_ITT) {
+-              hdr->itt = build_itt(mtask->itt, conn->id, session->age);
+-              if (conn->c_stage == ISCSI_CONN_STARTED &&
+-                  !(hdr->opcode & ISCSI_OP_IMMEDIATE))
+-                      session->cmdsn++;
+-      }
+-
+-      if (session->tt->init_mgmt_task)
+-              session->tt->init_mgmt_task(conn, mtask);
+-
+-      debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
+-                 hdr->opcode, hdr->itt, mtask->data_count);
+-}
+-
+ static int iscsi_xmit_mtask(struct iscsi_conn *conn)
+ {
+       struct iscsi_hdr *hdr = conn->mtask->hdr;
+       int rc, was_logout = 0;
+-      spin_unlock_bh(&conn->session->lock);
+       if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) {
+               conn->session->state = ISCSI_STATE_IN_RECOVERY;
+               iscsi_block_session(session_to_cls(conn->session));
+               was_logout = 1;
+       }
+       rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask);
+-      spin_lock_bh(&conn->session->lock);
+       if (rc)
+               return rc;
+@@ -634,45 +602,6 @@
+       return 0;
+ }
+-static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
+-{
+-      struct iscsi_session *session = conn->session;
+-
+-      /*
+-       * Check for iSCSI window and take care of CmdSN wrap-around
+-       */
+-      if (!iscsi_sna_lte(session->cmdsn, session->max_cmdsn)) {
+-              debug_scsi("iSCSI CmdSN closed. MaxCmdSN %u CmdSN %u\n",
+-                         session->max_cmdsn, session->cmdsn);
+-              return -ENOSPC;
+-      }
+-      return 0;
+-}
+-
+-static int iscsi_xmit_ctask(struct iscsi_conn *conn)
+-{
+-      struct iscsi_cmd_task *ctask = conn->ctask;
+-      int rc = 0;
+-
+-      /*
+-       * serialize with TMF AbortTask
+-       */
+-      if (ctask->state == ISCSI_TASK_ABORTING)
+-              goto done;
+-
+-      __iscsi_get_ctask(ctask);
+-      spin_unlock_bh(&conn->session->lock);
+-      rc = conn->session->tt->xmit_cmd_task(conn, ctask);
+-      spin_lock_bh(&conn->session->lock);
+-      __iscsi_put_ctask(ctask);
+-
+-done:
+-      if (!rc)
+-              /* done with this ctask */
+-              conn->ctask = NULL;
+-      return rc;
+-}
+-
+ /**
+  * iscsi_data_xmit - xmit any command into the scheduled connection
+  * @conn: iscsi connection
+@@ -684,79 +613,106 @@
+  **/
+ static int iscsi_data_xmit(struct iscsi_conn *conn)
+ {
++      struct iscsi_transport *tt;
+       int rc = 0;
+-      spin_lock_bh(&conn->session->lock);
+       if (unlikely(conn->suspend_tx)) {
+               debug_scsi("conn %d Tx suspended!\n", conn->id);
+-              spin_unlock_bh(&conn->session->lock);
+               return -ENODATA;
+       }
++      tt = conn->session->tt;
 +
 +      /*
-+       * Pre-allocate memory because the first pass is done under
-+       * tasklist_lock.
++       * Transmit in the following order:
++       *
++       * 1) un-finished xmit (ctask or mtask)
++       * 2) immediate control PDUs
++       * 3) write data
++       * 4) SCSI commands
++       * 5) non-immediate control PDUs
++       *
++       * No need to lock around __kfifo_get as long as
++       * there's one producer and one consumer.
 +       */
-+      fset = alloc_revoke_fset(inode, to_exclude);
-+      if (!fset) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      read_lock(&tasklist_lock);
 +
-+      /*
-+       * If someone forked while we were allocating memory, try again.
-+       */
-+      if (inode_fds(inode, to_exclude) > fset->nr) {
-+              read_unlock(&tasklist_lock);
-+              free_fset(fset);
-+              goto retry;
++      BUG_ON(conn->ctask && conn->mtask);
+       if (conn->ctask) {
+-              rc = iscsi_xmit_ctask(conn);
++              iscsi_get_ctask(conn->ctask);
++              rc = tt->xmit_cmd_task(conn, conn->ctask);
++              iscsi_put_ctask(conn->ctask);
+               if (rc)
+                       goto again;
++              /* done with this in-progress ctask */
++              conn->ctask = NULL;
+       }
+-
+       if (conn->mtask) {
+               rc = iscsi_xmit_mtask(conn);
+               if (rc)
+                       goto again;
+       }
+-      /*
+-       * process mgmt pdus like nops before commands since we should
+-       * only have one nop-out as a ping from us and targets should not
+-       * overflow us with nop-ins
+-       */
+-check_mgmt:
+-      while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
++      /* process immediate first */
++        if (unlikely(__kfifo_len(conn->immqueue))) {
++              while (__kfifo_get(conn->immqueue, (void*)&conn->mtask,
+                                  sizeof(void*))) {
+-              iscsi_prep_mtask(conn, conn->mtask);
+-              list_add_tail(&conn->mtask->running, &conn->mgmt_run_list);
++                      spin_lock_bh(&conn->session->lock);
++                      list_add_tail(&conn->mtask->running,
++                                    &conn->mgmt_run_list);
++                      spin_unlock_bh(&conn->session->lock);
+                       rc = iscsi_xmit_mtask(conn);
+                       if (rc)
+                               goto again;
+               }
 +      }
+       /* process command queue */
++      spin_lock_bh(&conn->session->lock);
+       while (!list_empty(&conn->xmitqueue)) {
+-              rc = iscsi_check_cmdsn_window_closed(conn);
+-              if (rc) {
+-                      spin_unlock_bh(&conn->session->lock);
+-                      return rc;
+-              }
+               /*
+                * iscsi tcp may readd the task to the xmitqueue to send
+                * write data
+                */
+               conn->ctask = list_entry(conn->xmitqueue.next,
+                                        struct iscsi_cmd_task, running);
+-              if (conn->ctask->state == ISCSI_TASK_PENDING) {
+-                      iscsi_prep_scsi_cmd_pdu(conn->ctask);
+-                      conn->session->tt->init_cmd_task(conn->ctask);
+-              }
+               conn->ctask->state = ISCSI_TASK_RUNNING;
+               list_move_tail(conn->xmitqueue.next, &conn->run_list);
+-              rc = iscsi_xmit_ctask(conn);
+-                      if (rc)
++              __iscsi_get_ctask(conn->ctask);
++              spin_unlock_bh(&conn->session->lock);
 +
-+      details.fset = fset;
-+      details.restore_start = 0;
++              rc = tt->xmit_cmd_task(conn, conn->ctask);
 +
-+      /*
-+       * First revoke the descriptors. After we are done, no one can start
-+       * new operations on them.
-+       */
-+      do_each_thread(g, p) {
-+              err = revoke_fds(p, inode, to_exclude, fset);
-+              if (err)
-+                      goto exit_loop;
++              spin_lock_bh(&conn->session->lock);
++              __iscsi_put_ctask(conn->ctask);
++              if (rc) {
++                      spin_unlock_bh(&conn->session->lock);
+                               goto again;
+-              /*
+-               * we could continuously get new ctask requests so
+-               * we need to check the mgmt queue for nops that need to
+-               * be sent to aviod starvation
+-               */
+-              if (__kfifo_len(conn->mgmtqueue))
+-                      goto check_mgmt;
++              }
+               }
+       spin_unlock_bh(&conn->session->lock);
++      /* done with this ctask */
++      conn->ctask = NULL;
++
++      /* process the rest control plane PDUs, if any */
++        if (unlikely(__kfifo_len(conn->mgmtqueue))) {
++              while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
++                                 sizeof(void*))) {
++                      spin_lock_bh(&conn->session->lock);
++                      list_add_tail(&conn->mtask->running,
++                                    &conn->mgmt_run_list);
++                      spin_unlock_bh(&conn->session->lock);
++                      rc = iscsi_xmit_mtask(conn);
++                      if (rc)
++                              goto again;
++              }
 +      }
-+      while_each_thread(g, p);
-+  exit_loop:
-+      read_unlock(&tasklist_lock);
-+
-+      if (err)
-+              goto out_restore;
-+
-+      /*
-+       * Take down shared memory mappings.
-+       */
-+      revoke_mapping(inode->i_mapping, to_exclude);
-+
-+      /*
-+       * Break COW for private mappings.
-+       */
-+      err = revoke_break_cow(fset, inode, to_exclude);
-+      if (err)
-+              goto out_restore;
-+
-+      /*
-+       * Now, revoke the files for good.
-+       */
-+      err = revoke_files(&details);
-+      if (err)
-+              goto out_restore;
-+
-+  out_free_table:
-+      free_fset(fset);
-+  out:
-+      return err;
-+
-+  out_restore:
-+      restore_files(&details);
-+      goto out_free_table;
-+}
 +
-+asmlinkage long sys_revokeat(int dfd, const char __user * filename)
-+{
-+      struct nameidata nd;
-+      int err;
+       return -ENODATA;
+ again:
+       if (unlikely(conn->suspend_tx))
+-              rc = -ENODATA;
+-      spin_unlock_bh(&conn->session->lock);
++              return -ENODATA;
 +
-+      err = __user_walk_fd(dfd, filename, 0, &nd);
-+      if (!err) {
-+              err = do_revoke(nd.dentry->d_inode, NULL);
-+              path_release(&nd);
+       return rc;
+ }
+@@ -768,9 +724,11 @@
+       /*
+        * serialize Xmit worker on a per-connection basis.
+        */
++      mutex_lock(&conn->xmitmutex);
+       do {
+               rc = iscsi_data_xmit(conn);
+       } while (rc >= 0 || rc == -EAGAIN);
++      mutex_unlock(&conn->xmitmutex);
+ }
+ enum {
+@@ -828,23 +786,20 @@
+               goto fault;
+       }
+-      conn = session->leadconn;
+-      if (!conn) {
+-              reason = FAILURE_SESSION_FREED;
+-              goto fault;
+-      }
+-
+       /*
+-       * We check this here and in data xmit, because if we get to the point
+-       * that this check is hitting the window then we have enough IO in
+-       * flight and enough IO waiting to be transmitted it is better
+-       * to let the scsi/block layer queue up.
++       * Check for iSCSI window and take care of CmdSN wrap-around
+        */
+-      if (iscsi_check_cmdsn_window_closed(conn)) {
++      if ((int)(session->max_cmdsn - session->cmdsn) < 0) {
+               reason = FAILURE_WINDOW_CLOSED;
+               goto reject;
+       }
++      conn = session->leadconn;
++      if (!conn) {
++              reason = FAILURE_SESSION_FREED;
++              goto fault;
 +      }
-+      return err;
-+}
 +
-+asmlinkage long sys_frevoke(unsigned int fd)
-+{
-+      struct file *file = fget(fd);
-+      int err = -EBADF;
+       if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask,
+                        sizeof(void*))) {
+               reason = FAILURE_OOM;
+@@ -859,8 +814,18 @@
+       ctask->conn = conn;
+       ctask->sc = sc;
+       INIT_LIST_HEAD(&ctask->running);
++      ctask->total_length = sc->request_bufflen;
++      iscsi_prep_scsi_cmd_pdu(ctask);
 +
-+      if (file) {
-+              err = do_revoke(file->f_dentry->d_inode, file);
-+              fput(file);
++      session->tt->init_cmd_task(ctask);
+       list_add_tail(&ctask->running, &conn->xmitqueue);
++      debug_scsi(
++             "ctask enq [%s cid %d sc %p cdb 0x%x itt 0x%x len %d cmdsn %d "
++              "win %d]\n",
++              sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
++              conn->id, sc, sc->cmnd[0], ctask->itt, sc->request_bufflen,
++              session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+       spin_unlock(&session->lock);
+       scsi_queue_work(host, &conn->xmitwork);
+@@ -876,7 +841,7 @@
+       printk(KERN_ERR "iscsi: cmd 0x%x is not queued (%d)\n",
+              sc->cmnd[0], reason);
+       sc->result = (DID_NO_CONNECT << 16);
+-      scsi_set_resid(sc, scsi_bufflen(sc));
++      sc->resid = sc->request_bufflen;
+       sc->scsi_done(sc);
+       return 0;
+ }
+@@ -891,16 +856,19 @@
+ }
+ EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
+-static struct iscsi_mgmt_task *
+-__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
++static int
++iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+                       char *data, uint32_t data_size)
+ {
+       struct iscsi_session *session = conn->session;
++      struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
+       struct iscsi_mgmt_task *mtask;
+-      if (session->state == ISCSI_STATE_TERMINATE)
+-              return NULL;
+-
++      spin_lock_bh(&session->lock);
++      if (session->state == ISCSI_STATE_TERMINATE) {
++              spin_unlock_bh(&session->lock);
++              return -EPERM;
 +      }
-+      return err;
-+}
-+
-+int generic_file_revoke(struct file *file, struct address_space *new_mapping)
-+{
-+      struct address_space *mapping = file->f_mapping;
-+      int err;
-+
+       if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
+           hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
+               /*
+@@ -914,11 +882,27 @@
+               BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+               BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
++              nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
+               if (!__kfifo_get(session->mgmtpool.queue,
+-                               (void*)&mtask, sizeof(void*)))
+-                      return NULL;
++                               (void*)&mtask, sizeof(void*))) {
++                      spin_unlock_bh(&session->lock);
++                      return -ENOSPC;
++              }
+       }
 +      /*
-+       * Flush pending writes.
++       * pre-format CmdSN for outgoing PDU.
 +       */
-+      err = do_fsync(file, 1);
-+      if (err)
-+              goto out;
++      if (hdr->itt != RESERVED_ITT) {
++              hdr->itt = build_itt(mtask->itt, conn->id, session->age);
++              nop->cmdsn = cpu_to_be32(session->cmdsn);
++              if (conn->c_stage == ISCSI_CONN_STARTED &&
++                  !(hdr->opcode & ISCSI_OP_IMMEDIATE))
++                      session->cmdsn++;
++      } else
++              /* do not advance CmdSN */
++              nop->cmdsn = cpu_to_be32(session->cmdsn);
++
+       if (data_size) {
+               memcpy(mtask->data, data, data_size);
+               mtask->data_count = data_size;
+@@ -927,23 +911,38 @@
+       INIT_LIST_HEAD(&mtask->running);
+       memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
++      if (session->tt->init_mgmt_task)
++              session->tt->init_mgmt_task(conn, mtask, data, data_size);
++      spin_unlock_bh(&session->lock);
 +
-+      file->f_mapping = new_mapping;
++      debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
++                 hdr->opcode, hdr->itt, data_size);
 +
 +      /*
-+       * Make pending reads fail.
++       * since send_pdu() could be called at least from two contexts,
++       * we need to serialize __kfifo_put, so we don't have to take
++       * additional lock on fast data-path
 +       */
-+      err = invalidate_inode_pages2(mapping);
-+
-+  out:
-+      return err;
-+}
-+EXPORT_SYMBOL(generic_file_revoke);
-+
-+/*
-+ *    Filesystem for revoked files.
-+ */
-+
-+static struct inode *revokefs_alloc_inode(struct super_block *sb)
-+{
-+      struct revokefs_inode_info *info;
-+
-+      info = kmem_cache_alloc(revokefs_inode_cache, GFP_KERNEL);
-+      if (!info)
-+              return NULL;
-+
-+      return &info->vfs_inode;
-+}
-+
-+static void revokefs_destroy_inode(struct inode *inode)
-+{
-+      kmem_cache_free(revokefs_inode_cache, revokefs_i(inode));
-+}
-+
-+static struct super_operations revokefs_super_ops = {
-+      .alloc_inode = revokefs_alloc_inode,
-+      .destroy_inode = revokefs_destroy_inode,
-+      .drop_inode = generic_delete_inode,
-+};
-+
-+static int revokefs_get_sb(struct file_system_type *fs_type,
-+                         int flags, const char *dev_name, void *data,
-+                         struct vfsmount *mnt)
-+{
-+      return get_sb_pseudo(fs_type, "revoke:", &revokefs_super_ops,
-+                           REVOKEFS_MAGIC, mnt);
-+}
-+
-+static struct file_system_type revokefs_fs_type = {
-+      .name = "revokefs",
-+      .get_sb = revokefs_get_sb,
-+      .kill_sb = kill_anon_super
-+};
-+
-+static void revokefs_init_inode(void *obj, struct kmem_cache *cache,
-+                              unsigned long flags)
-+{
-+      struct revokefs_inode_info *info = obj;
-+
-+      info->owner = NULL;
-+      inode_init_once(&info->vfs_inode);
-+}
-+
-+static int __init revokefs_init(void)
-+{
-+      int err = -ENOMEM;
-+
-+      revokefs_inode_cache =
-+          kmem_cache_create("revokefs_inode_cache",
-+                            sizeof(struct revokefs_inode_info),
-+                            0,
-+                            (SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT |
-+                             SLAB_MEM_SPREAD), revokefs_init_inode, NULL);
-+      if (!revokefs_inode_cache)
-+              goto out;
-+
-+      err = register_filesystem(&revokefs_fs_type);
-+      if (err)
-+              goto err_register;
-+
-+      revokefs_mnt = kern_mount(&revokefs_fs_type);
-+      if (IS_ERR(revokefs_mnt)) {
-+              err = PTR_ERR(revokefs_mnt);
-+              goto err_mnt;
-+      }
-+  out:
-+      return err;
-+  err_mnt:
-+      unregister_filesystem(&revokefs_fs_type);
-+  err_register:
-+      kmem_cache_destroy(revokefs_inode_cache);
-+      return err;
-+}
-+
-+late_initcall(revokefs_init);
-diff -Nurb linux-2.6.22-570/fs/revoked_inode.c linux-2.6.22-590/fs/revoked_inode.c
---- linux-2.6.22-570/fs/revoked_inode.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/revoked_inode.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,417 @@
-+/*
-+ * fs/revoked_inode.c
-+ *
-+ * Copyright (C) 2007  Pekka Enberg
-+ *
-+ * Provide stub functions for revoked inodes. Based on fs/bad_inode.c which is
-+ *
-+ * Copyright (C) 1997  Stephen Tweedie
-+ *
-+ * This file is released under the GPLv2.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/module.h>
-+#include <linux/stat.h>
-+#include <linux/time.h>
-+#include <linux/smp_lock.h>
-+#include <linux/namei.h>
-+#include <linux/poll.h>
-+#include <linux/revoked_fs_i.h>
-+
-+static loff_t revoked_file_llseek(struct file *file, loff_t offset, int origin)
-+{
-+      return -EBADF;
-+}
-+
-+static ssize_t revoked_file_read(struct file *filp, char __user * buf,
-+                               size_t size, loff_t * ppos)
-+{
-+      return -EBADF;
-+}
++        if (hdr->opcode & ISCSI_OP_IMMEDIATE)
++              __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*));
++      else
+               __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
+-      return mtask;
 +
-+static ssize_t revoked_special_file_read(struct file *filp, char __user * buf,
-+                                       size_t size, loff_t * ppos)
-+{
++      scsi_queue_work(session->host, &conn->xmitwork);
 +      return 0;
-+}
-+
-+static ssize_t revoked_file_write(struct file *filp, const char __user * buf,
-+                                size_t siz, loff_t * ppos)
-+{
-+      return -EBADF;
-+}
-+
-+static ssize_t revoked_file_aio_read(struct kiocb *iocb,
-+                                   const struct iovec *iov,
-+                                   unsigned long nr_segs, loff_t pos)
-+{
-+      return -EBADF;
-+}
-+
-+static ssize_t revoked_file_aio_write(struct kiocb *iocb,
-+                                    const struct iovec *iov,
-+                                    unsigned long nr_segs, loff_t pos)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_file_readdir(struct file *filp, void *dirent,
-+                              filldir_t filldir)
-+{
-+      return -EBADF;
-+}
-+
-+static unsigned int revoked_file_poll(struct file *filp, poll_table * wait)
-+{
-+      return POLLERR;
-+}
-+
-+static int revoked_file_ioctl(struct inode *inode, struct file *filp,
-+                            unsigned int cmd, unsigned long arg)
-+{
-+      return -EBADF;
-+}
-+
-+static long revoked_file_unlocked_ioctl(struct file *file, unsigned cmd,
-+                                      unsigned long arg)
-+{
-+      return -EBADF;
-+}
-+
-+static long revoked_file_compat_ioctl(struct file *file, unsigned int cmd,
-+                                    unsigned long arg)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_file_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_file_open(struct inode *inode, struct file *filp)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_file_flush(struct file *file, fl_owner_t id)
-+{
-+      return filp_close(file, id);
-+}
-+
-+static int revoked_file_release(struct inode *inode, struct file *filp)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_file_fsync(struct file *file, struct dentry *dentry,
-+                            int datasync)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_file_aio_fsync(struct kiocb *iocb, int datasync)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_file_fasync(int fd, struct file *filp, int on)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_file_lock(struct file *file, int cmd, struct file_lock *fl)
-+{
-+      return -EBADF;
-+}
-+
-+static ssize_t revoked_file_sendfile(struct file *in_file, loff_t * ppos,
-+                                   size_t count, read_actor_t actor,
-+                                   void *target)
-+{
-+      return -EBADF;
-+}
-+
-+static ssize_t revoked_file_sendpage(struct file *file, struct page *page,
-+                                   int off, size_t len, loff_t * pos,
-+                                   int more)
-+{
-+      return -EBADF;
-+}
-+
-+static unsigned long revoked_file_get_unmapped_area(struct file *file,
-+                                                  unsigned long addr,
-+                                                  unsigned long len,
-+                                                  unsigned long pgoff,
-+                                                  unsigned long flags)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_file_check_flags(int flags)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_file_dir_notify(struct file *file, unsigned long arg)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_file_flock(struct file *filp, int cmd, struct file_lock *fl)
-+{
-+      return -EBADF;
-+}
-+
-+static ssize_t revoked_file_splice_write(struct pipe_inode_info *pipe,
-+                                       struct file *out, loff_t * ppos,
-+                                       size_t len, unsigned int flags)
-+{
-+      return -EBADF;
-+}
-+
-+static ssize_t revoked_file_splice_read(struct file *in, loff_t * ppos,
-+                                      struct pipe_inode_info *pipe,
-+                                      size_t len, unsigned int flags)
-+{
-+      return -EBADF;
-+}
-+
-+static const struct file_operations revoked_file_ops = {
-+      .llseek = revoked_file_llseek,
-+      .read = revoked_file_read,
-+      .write = revoked_file_write,
-+      .aio_read = revoked_file_aio_read,
-+      .aio_write = revoked_file_aio_write,
-+      .readdir = revoked_file_readdir,
-+      .poll = revoked_file_poll,
-+      .ioctl = revoked_file_ioctl,
-+      .unlocked_ioctl = revoked_file_unlocked_ioctl,
-+      .compat_ioctl = revoked_file_compat_ioctl,
-+      .mmap = revoked_file_mmap,
-+      .open = revoked_file_open,
-+      .flush = revoked_file_flush,
-+      .release = revoked_file_release,
-+      .fsync = revoked_file_fsync,
-+      .aio_fsync = revoked_file_aio_fsync,
-+      .fasync = revoked_file_fasync,
-+      .lock = revoked_file_lock,
-+      .sendfile = revoked_file_sendfile,
-+      .sendpage = revoked_file_sendpage,
-+      .get_unmapped_area = revoked_file_get_unmapped_area,
-+      .check_flags = revoked_file_check_flags,
-+      .dir_notify = revoked_file_dir_notify,
-+      .flock = revoked_file_flock,
-+      .splice_write = revoked_file_splice_write,
-+      .splice_read = revoked_file_splice_read,
-+};
-+
-+static const struct file_operations revoked_special_file_ops = {
-+      .llseek = revoked_file_llseek,
-+      .read = revoked_special_file_read,
-+      .write = revoked_file_write,
-+      .aio_read = revoked_file_aio_read,
-+      .aio_write = revoked_file_aio_write,
-+      .readdir = revoked_file_readdir,
-+      .poll = revoked_file_poll,
-+      .ioctl = revoked_file_ioctl,
-+      .unlocked_ioctl = revoked_file_unlocked_ioctl,
-+      .compat_ioctl = revoked_file_compat_ioctl,
-+      .mmap = revoked_file_mmap,
-+      .open = revoked_file_open,
-+      .flush = revoked_file_flush,
-+      .release = revoked_file_release,
-+      .fsync = revoked_file_fsync,
-+      .aio_fsync = revoked_file_aio_fsync,
-+      .fasync = revoked_file_fasync,
-+      .lock = revoked_file_lock,
-+      .sendfile = revoked_file_sendfile,
-+      .sendpage = revoked_file_sendpage,
-+      .get_unmapped_area = revoked_file_get_unmapped_area,
-+      .check_flags = revoked_file_check_flags,
-+      .dir_notify = revoked_file_dir_notify,
-+      .flock = revoked_file_flock,
-+      .splice_write = revoked_file_splice_write,
-+      .splice_read = revoked_file_splice_read,
-+};
-+
-+static int revoked_inode_create(struct inode *dir, struct dentry *dentry,
-+                              int mode, struct nameidata *nd)
-+{
-+      return -EBADF;
-+}
-+
-+static struct dentry *revoked_inode_lookup(struct inode *dir,
-+                                         struct dentry *dentry,
-+                                         struct nameidata *nd)
-+{
-+      return ERR_PTR(-EBADF);
-+}
-+
-+static int revoked_inode_link(struct dentry *old_dentry, struct inode *dir,
-+                            struct dentry *dentry)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_inode_unlink(struct inode *dir, struct dentry *dentry)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_inode_symlink(struct inode *dir, struct dentry *dentry,
-+                               const char *symname)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_inode_mkdir(struct inode *dir, struct dentry *dentry,
-+                             int mode)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_inode_rmdir(struct inode *dir, struct dentry *dentry)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_inode_mknod(struct inode *dir, struct dentry *dentry,
-+                             int mode, dev_t rdev)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_inode_rename(struct inode *old_dir,
-+                              struct dentry *old_dentry,
-+                              struct inode *new_dir,
-+                              struct dentry *new_dentry)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_inode_readlink(struct dentry *dentry, char __user * buffer,
-+                                int buflen)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_inode_permission(struct inode *inode, int mask,
-+                                  struct nameidata *nd)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
-+                               struct kstat *stat)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_inode_setattr(struct dentry *direntry, struct iattr *attrs)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_inode_setxattr(struct dentry *dentry, const char *name,
-+                                const void *value, size_t size, int flags)
-+{
-+      return -EBADF;
-+}
-+
-+static ssize_t revoked_inode_getxattr(struct dentry *dentry, const char *name,
-+                                    void *buffer, size_t size)
-+{
-+      return -EBADF;
-+}
-+
-+static ssize_t revoked_inode_listxattr(struct dentry *dentry, char *buffer,
-+                                     size_t buffer_size)
-+{
-+      return -EBADF;
-+}
-+
-+static int revoked_inode_removexattr(struct dentry *dentry, const char *name)
-+{
-+      return -EBADF;
-+}
-+
-+static struct inode_operations revoked_inode_ops = {
-+      .create = revoked_inode_create,
-+      .lookup = revoked_inode_lookup,
-+      .link = revoked_inode_link,
-+      .unlink = revoked_inode_unlink,
-+      .symlink = revoked_inode_symlink,
-+      .mkdir = revoked_inode_mkdir,
-+      .rmdir = revoked_inode_rmdir,
-+      .mknod = revoked_inode_mknod,
-+      .rename = revoked_inode_rename,
-+      .readlink = revoked_inode_readlink,
-+      /* follow_link must be no-op, otherwise unmounting this inode
-+         won't work */
-+      /* put_link returns void */
-+      /* truncate returns void */
-+      .permission = revoked_inode_permission,
-+      .getattr = revoked_inode_getattr,
-+      .setattr = revoked_inode_setattr,
-+      .setxattr = revoked_inode_setxattr,
-+      .getxattr = revoked_inode_getxattr,
-+      .listxattr = revoked_inode_listxattr,
-+      .removexattr = revoked_inode_removexattr,
-+      /* truncate_range returns void */
-+};
+ }
+ int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+                       char *data, uint32_t data_size)
+ {
+       struct iscsi_conn *conn = cls_conn->dd_data;
+-      struct iscsi_session *session = conn->session;
+-      int err = 0;
++      int rc;
+-      spin_lock_bh(&session->lock);
+-      if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
+-              err = -EPERM;
+-      spin_unlock_bh(&session->lock);
+-      scsi_queue_work(session->host, &conn->xmitwork);
+-      return err;
++      mutex_lock(&conn->xmitmutex);
++      rc = iscsi_conn_send_generic(conn, hdr, data, data_size);
++      mutex_unlock(&conn->xmitmutex);
 +
-+static int revoked_readpage(struct file *file, struct page *page)
-+{
-+      return -EIO;
-+}
++      return rc;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
+@@ -1028,12 +1027,14 @@
+       spin_unlock(&session->lock);
+ }
++/* must be called with the mutex lock */
+ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+                                struct iscsi_cmd_task *ctask)
+ {
+       struct iscsi_conn *conn = ctask->conn;
+       struct iscsi_session *session = conn->session;
+       struct iscsi_tm *hdr = &conn->tmhdr;
++      int rc;
+       /*
+        * ctask timed out but session is OK requests must be serialized.
+@@ -1046,27 +1047,32 @@
+       hdr->rtt = ctask->hdr->itt;
+       hdr->refcmdsn = ctask->hdr->cmdsn;
+-      ctask->mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
++      rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr,
+                                    NULL, 0);
+-      if (!ctask->mtask) {
++      if (rc) {
+               iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-              debug_scsi("abort sent failure [itt 0x%x]\n", ctask->itt);
+-              return -EPERM;
++              debug_scsi("abort sent failure [itt 0x%x] %d\n", ctask->itt,
++                         rc);
++              return rc;
+       }
+-      ctask->state = ISCSI_TASK_ABORTING;
+       debug_scsi("abort sent [itt 0x%x]\n", ctask->itt);
++      spin_lock_bh(&session->lock);
++      ctask->mtask = (struct iscsi_mgmt_task *)
++                      session->mgmt_cmds[get_itt(hdr->itt) -
++                                      ISCSI_MGMT_ITT_OFFSET];
 +
-+static int revoked_writepage(struct page *page, struct writeback_control *wbc)
-+{
-+      return -EIO;
-+}
+       if (conn->tmabort_state == TMABORT_INITIAL) {
+               conn->tmfcmd_pdus_cnt++;
+-              conn->tmabort_timer.expires = 20*HZ + jiffies;
++              conn->tmabort_timer.expires = 10*HZ + jiffies;
+               conn->tmabort_timer.function = iscsi_tmabort_timedout;
+               conn->tmabort_timer.data = (unsigned long)ctask;
+               add_timer(&conn->tmabort_timer);
+               debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt);
+       }
+       spin_unlock_bh(&session->lock);
+-      scsi_queue_work(session->host, &conn->xmitwork);
++      mutex_unlock(&conn->xmitmutex);
+       /*
+        * block eh thread until:
+@@ -1083,12 +1089,13 @@
+       if (signal_pending(current))
+               flush_signals(current);
+       del_timer_sync(&conn->tmabort_timer);
+-      spin_lock_bh(&session->lock);
 +
-+static int revoked_prepare_write(struct file *file, struct page *page,
-+                               unsigned from, unsigned to)
-+{
-+      return -EIO;
-+}
++      mutex_lock(&conn->xmitmutex);
+       return 0;
+ }
+ /*
+- * session lock must be held
++ * xmit mutex and session lock must be held
+  */
+ static struct iscsi_mgmt_task *
+ iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt)
+@@ -1120,7 +1127,7 @@
+       if (!ctask->mtask)
+               return -EINVAL;
+-      if (!iscsi_remove_mgmt_task(conn->mgmtqueue, ctask->mtask->itt))
++      if (!iscsi_remove_mgmt_task(conn->immqueue, ctask->mtask->itt))
+               list_del(&ctask->mtask->running);
+       __kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask,
+                   sizeof(void*));
+@@ -1129,7 +1136,7 @@
+ }
+ /*
+- * session lock must be held
++ * session lock and xmitmutex must be held
+  */
+ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+                        int err)
+@@ -1140,14 +1147,11 @@
+       if (!sc)
+               return;
+-      if (ctask->state != ISCSI_TASK_PENDING)
+       conn->session->tt->cleanup_cmd_task(conn, ctask);
+       iscsi_ctask_mtask_cleanup(ctask);
+       sc->result = err;
+-      scsi_set_resid(sc, scsi_bufflen(sc));
+-      if (conn->ctask == ctask)
+-              conn->ctask = NULL;
++      sc->resid = sc->request_bufflen;
+       /* release ref from queuecommand */
+       __iscsi_put_ctask(ctask);
+ }
+@@ -1175,6 +1179,7 @@
+       conn->eh_abort_cnt++;
+       debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
++      mutex_lock(&conn->xmitmutex);
+       spin_lock_bh(&session->lock);
+       /*
+@@ -1187,8 +1192,9 @@
+       /* ctask completed before time out */
+       if (!ctask->sc) {
++              spin_unlock_bh(&session->lock);
+               debug_scsi("sc completed while abort in progress\n");
+-              goto success;
++              goto success_rel_mutex;
+       }
+       /* what should we do here ? */
+@@ -1198,13 +1204,15 @@
+               goto failed;
+       }
+-      if (ctask->state == ISCSI_TASK_PENDING) {
+-              fail_command(conn, ctask, DID_ABORT << 16);
+-              goto success;
+-      }
++      if (ctask->state == ISCSI_TASK_PENDING)
++              goto success_cleanup;
+       conn->tmabort_state = TMABORT_INITIAL;
 +
-+static int revoked_commit_write(struct file *file, struct page *page,
-+                              unsigned from, unsigned to)
-+{
-+      return -EIO;
-+}
++      spin_unlock_bh(&session->lock);
+       rc = iscsi_exec_abort_task(sc, ctask);
++      spin_lock_bh(&session->lock);
 +
-+static ssize_t revoked_direct_IO(int rw, struct kiocb *iocb,
-+                               const struct iovec *iov, loff_t offset,
-+                               unsigned long nr_segs)
-+{
-+      return -EIO;
-+}
+       if (rc || sc->SCp.phase != session->age ||
+           session->state != ISCSI_STATE_LOGGED_IN)
+               goto failed;
+@@ -1212,44 +1220,45 @@
+       switch (conn->tmabort_state) {
+       case TMABORT_SUCCESS:
+-              spin_unlock_bh(&session->lock);
+-              /*
+-               * clean up task if aborted. grab the recv lock as a writer
+-               */
+-              write_lock_bh(conn->recv_lock);
+-              spin_lock(&session->lock);
+-              fail_command(conn, ctask, DID_ABORT << 16);
+-              spin_unlock(&session->lock);
+-              write_unlock_bh(conn->recv_lock);
+-              /*
+-               * make sure xmit thread is not still touching the
+-               * ctask/scsi_cmnd
+-               */
+-              scsi_flush_work(session->host);
+-              goto success_unlocked;
++              goto success_cleanup;
+       case TMABORT_NOT_FOUND:
+               if (!ctask->sc) {
+                       /* ctask completed before tmf abort response */
++                      spin_unlock_bh(&session->lock);
+                       debug_scsi("sc completed while abort in progress\n");
+-                      goto success;
++                      goto success_rel_mutex;
+               }
+               /* fall through */
+       default:
+               /* timedout or failed */
+               spin_unlock_bh(&session->lock);
+               iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+-              goto failed_unlocked;
++              spin_lock_bh(&session->lock);
++              goto failed;
+       }
+-success:
+-      spin_unlock_bh(&session->lock);
+-success_unlocked:
++success_cleanup:
+       debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
++      spin_unlock_bh(&session->lock);
 +
-+static const struct address_space_operations revoked_aops = {
-+        .readpage       = revoked_readpage,
-+        .writepage      = revoked_writepage,
-+        .prepare_write  = revoked_prepare_write,
-+        .commit_write   = revoked_commit_write,
-+        .direct_IO      = revoked_direct_IO,
-+};
++      /*
++       * clean up task if aborted. we have the xmitmutex so grab
++       * the recv lock as a writer
++       */
++      write_lock_bh(conn->recv_lock);
++      spin_lock(&session->lock);
++      fail_command(conn, ctask, DID_ABORT << 16);
++      spin_unlock(&session->lock);
++      write_unlock_bh(conn->recv_lock);
++
++success_rel_mutex:
++      mutex_unlock(&conn->xmitmutex);
+       return SUCCESS;
+ failed:
+       spin_unlock_bh(&session->lock);
+-failed_unlocked:
++      mutex_unlock(&conn->xmitmutex);
 +
-+void make_revoked_inode(struct inode *inode, int mode)
-+{
-+      remove_inode_hash(inode);
+       debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
+       return FAILED;
+ }
+@@ -1330,10 +1339,6 @@
+  * iscsi_session_setup - create iscsi cls session and host and session
+  * @scsit: scsi transport template
+  * @iscsit: iscsi transport template
+- * @cmds_max: scsi host can queue
+- * @qdepth: scsi host cmds per lun
+- * @cmd_task_size: LLD ctask private data size
+- * @mgmt_task_size: LLD mtask private data size
+  * @initial_cmdsn: initial CmdSN
+  * @hostno: host no allocated
+  *
+@@ -1343,7 +1348,6 @@
+ struct iscsi_cls_session *
+ iscsi_session_setup(struct iscsi_transport *iscsit,
+                   struct scsi_transport_template *scsit,
+-                  uint16_t cmds_max, uint16_t qdepth,
+                   int cmd_task_size, int mgmt_task_size,
+                   uint32_t initial_cmdsn, uint32_t *hostno)
+ {
+@@ -1352,32 +1356,11 @@
+       struct iscsi_cls_session *cls_session;
+       int cmd_i;
+-      if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
+-              if (qdepth != 0)
+-                      printk(KERN_ERR "iscsi: invalid queue depth of %d. "
+-                            "Queue depth must be between 1 and %d.\n",
+-                            qdepth, ISCSI_MAX_CMD_PER_LUN);
+-              qdepth = ISCSI_DEF_CMD_PER_LUN;
+-      }
+-
+-      if (cmds_max < 2 || (cmds_max & (cmds_max - 1)) ||
+-          cmds_max >= ISCSI_MGMT_ITT_OFFSET) {
+-              if (cmds_max != 0)
+-                      printk(KERN_ERR "iscsi: invalid can_queue of %d. "
+-                             "can_queue must be a power of 2 and between "
+-                             "2 and %d - setting to %d.\n", cmds_max,
+-                             ISCSI_MGMT_ITT_OFFSET, ISCSI_DEF_XMIT_CMDS_MAX);
+-              cmds_max = ISCSI_DEF_XMIT_CMDS_MAX;
+-      }
+-
+       shost = scsi_host_alloc(iscsit->host_template,
+                               hostdata_privsize(sizeof(*session)));
+       if (!shost)
+               return NULL;
+-      /* the iscsi layer takes one task for reserve */
+-      shost->can_queue = cmds_max - 1;
+-      shost->cmd_per_lun = qdepth;
+       shost->max_id = 1;
+       shost->max_channel = 0;
+       shost->max_lun = iscsit->max_lun;
+@@ -1391,7 +1374,7 @@
+       session->host = shost;
+       session->state = ISCSI_STATE_FREE;
+       session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
+-      session->cmds_max = cmds_max;
++      session->cmds_max = ISCSI_XMIT_CMDS_MAX;
+       session->cmdsn = initial_cmdsn;
+       session->exp_cmdsn = initial_cmdsn + 1;
+       session->max_cmdsn = initial_cmdsn + 1;
+@@ -1478,14 +1461,7 @@
+       iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
+       iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+-      kfree(session->password);
+-      kfree(session->password_in);
+-      kfree(session->username);
+-      kfree(session->username_in);
+       kfree(session->targetname);
+-      kfree(session->netdev);
+-      kfree(session->hwaddress);
+-      kfree(session->initiatorname);
+       iscsi_destroy_session(cls_session);
+       scsi_host_put(shost);
+@@ -1523,6 +1499,11 @@
+       INIT_LIST_HEAD(&conn->xmitqueue);
+       /* initialize general immediate & non-immediate PDU commands queue */
++      conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
++                                      GFP_KERNEL, NULL);
++      if (conn->immqueue == ERR_PTR(-ENOMEM))
++              goto immqueue_alloc_fail;
 +
-+      inode->i_mode = mode;
-+      inode->i_atime = inode->i_mtime = inode->i_ctime =
-+          current_fs_time(inode->i_sb);
-+      inode->i_op = &revoked_inode_ops;
+       conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
+                                       GFP_KERNEL, NULL);
+       if (conn->mgmtqueue == ERR_PTR(-ENOMEM))
+@@ -1546,6 +1527,7 @@
+       conn->login_mtask->data = conn->data = data;
+       init_timer(&conn->tmabort_timer);
++      mutex_init(&conn->xmitmutex);
+       init_waitqueue_head(&conn->ehwait);
+       return cls_conn;
+@@ -1556,6 +1538,8 @@
+ login_mtask_alloc_fail:
+       kfifo_free(conn->mgmtqueue);
+ mgmtqueue_alloc_fail:
++      kfifo_free(conn->immqueue);
++immqueue_alloc_fail:
+       iscsi_destroy_conn(cls_conn);
+       return NULL;
+ }
+@@ -1574,8 +1558,10 @@
+       struct iscsi_session *session = conn->session;
+       unsigned long flags;
+-      spin_lock_bh(&session->lock);
+       set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
++      mutex_lock(&conn->xmitmutex);
 +
-+      if (special_file(mode))
-+              inode->i_fop = &revoked_special_file_ops;
-+      else
-+              inode->i_fop = &revoked_file_ops;
++      spin_lock_bh(&session->lock);
+       conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
+       if (session->leadconn == conn) {
+               /*
+@@ -1586,6 +1572,8 @@
+       }
+       spin_unlock_bh(&session->lock);
++      mutex_unlock(&conn->xmitmutex);
 +
-+      inode->i_mapping->a_ops = &revoked_aops;
-+}
-diff -Nurb linux-2.6.22-570/fs/splice.c linux-2.6.22-590/fs/splice.c
---- linux-2.6.22-570/fs/splice.c       2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/fs/splice.c       2008-01-02 13:56:37.000000000 -0500
-@@ -28,6 +28,7 @@
- #include <linux/module.h>
- #include <linux/syscalls.h>
- #include <linux/uio.h>
-+#include <linux/security.h>
+       /*
+        * Block until all in-progress commands for this connection
+        * time out or fail.
+@@ -1622,6 +1610,7 @@
+       }
+       spin_unlock_bh(&session->lock);
  
- struct partial_page {
-       unsigned int offset;
-@@ -932,6 +933,10 @@
-       if (unlikely(ret < 0))
-               return ret;
++      kfifo_free(conn->immqueue);
+       kfifo_free(conn->mgmtqueue);
  
-+      ret = security_file_permission(out, MAY_WRITE);
-+      if (unlikely(ret < 0))
-+              return ret;
-+
-       return out->f_op->splice_write(pipe, out, ppos, len, flags);
- }
+       iscsi_destroy_conn(cls_conn);
+@@ -1682,7 +1671,8 @@
+       struct iscsi_mgmt_task *mtask, *tmp;
  
-@@ -954,6 +959,10 @@
-       if (unlikely(ret < 0))
-               return ret;
+       /* handle pending */
+-      while (__kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
++      while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) ||
++             __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
+               if (mtask == conn->login_mtask)
+                       continue;
+               debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt);
+@@ -1752,12 +1742,12 @@
+       conn->c_stage = ISCSI_CONN_STOPPED;
+       set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+       spin_unlock_bh(&session->lock);
+-      scsi_flush_work(session->host);
  
-+      ret = security_file_permission(in, MAY_READ);
-+      if (unlikely(ret < 0))
-+              return ret;
+       write_lock_bh(conn->recv_lock);
+       set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+       write_unlock_bh(conn->recv_lock);
++      mutex_lock(&conn->xmitmutex);
+       /*
+        * for connection level recovery we should not calculate
+        * header digest. conn->hdr_size used for optimization
+@@ -1781,6 +1771,8 @@
+       fail_all_commands(conn);
+       flush_control_queues(session, conn);
+       spin_unlock_bh(&session->lock);
 +
-       return in->f_op->splice_read(in, ppos, pipe, len, flags);
++      mutex_unlock(&conn->xmitmutex);
  }
  
-@@ -1272,6 +1281,7 @@
- static long do_vmsplice(struct file *file, const struct iovec __user *iov,
-                       unsigned long nr_segs, unsigned int flags)
- {
-+      long err;
-       struct pipe_inode_info *pipe;
-       struct page *pages[PIPE_BUFFERS];
-       struct partial_page partial[PIPE_BUFFERS];
-@@ -1290,6 +1300,10 @@
-       else if (unlikely(!nr_segs))
-               return 0;
+ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+@@ -1875,30 +1867,6 @@
+       case ISCSI_PARAM_EXP_STATSN:
+               sscanf(buf, "%u", &conn->exp_statsn);
+               break;
+-      case ISCSI_PARAM_USERNAME:
+-              kfree(session->username);
+-              session->username = kstrdup(buf, GFP_KERNEL);
+-              if (!session->username)
+-                      return -ENOMEM;
+-              break;
+-      case ISCSI_PARAM_USERNAME_IN:
+-              kfree(session->username_in);
+-              session->username_in = kstrdup(buf, GFP_KERNEL);
+-              if (!session->username_in)
+-                      return -ENOMEM;
+-              break;
+-      case ISCSI_PARAM_PASSWORD:
+-              kfree(session->password);
+-              session->password = kstrdup(buf, GFP_KERNEL);
+-              if (!session->password)
+-                      return -ENOMEM;
+-              break;
+-      case ISCSI_PARAM_PASSWORD_IN:
+-              kfree(session->password_in);
+-              session->password_in = kstrdup(buf, GFP_KERNEL);
+-              if (!session->password_in)
+-                      return -ENOMEM;
+-              break;
+       case ISCSI_PARAM_TARGET_NAME:
+               /* this should not change between logins */
+               if (session->targetname)
+@@ -1972,18 +1940,6 @@
+       case ISCSI_PARAM_TPGT:
+               len = sprintf(buf, "%d\n", session->tpgt);
+               break;
+-      case ISCSI_PARAM_USERNAME:
+-              len = sprintf(buf, "%s\n", session->username);
+-              break;
+-      case ISCSI_PARAM_USERNAME_IN:
+-              len = sprintf(buf, "%s\n", session->username_in);
+-              break;
+-      case ISCSI_PARAM_PASSWORD:
+-              len = sprintf(buf, "%s\n", session->password);
+-              break;
+-      case ISCSI_PARAM_PASSWORD_IN:
+-              len = sprintf(buf, "%s\n", session->password_in);
+-              break;
+       default:
+               return -ENOSYS;
+       }
+@@ -2034,66 +1990,6 @@
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_get_param);
  
-+      err = security_file_permission(file, MAY_WRITE);
-+      if (unlikely(err < 0))
-+              return err;
-+
-       spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial,
-                                           flags & SPLICE_F_GIFT);
-       if (spd.nr_pages <= 0)
-diff -Nurb linux-2.6.22-570/fs/stack.c linux-2.6.22-590/fs/stack.c
---- linux-2.6.22-570/fs/stack.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/stack.c        2008-01-02 13:56:37.000000000 -0500
-@@ -1,8 +1,20 @@
-+/*
-+ * Copyright (c) 2006-2007 Erez Zadok
-+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2006-2007 Stony Brook University
-+ * Copyright (c) 2006-2007 The Research Foundation of SUNY
-+ *
-+ * 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/fs.h>
- #include <linux/fs_stack.h>
+-int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+-                       char *buf)
+-{
+-      struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+-      int len;
+-
+-      switch (param) {
+-      case ISCSI_HOST_PARAM_NETDEV_NAME:
+-              if (!session->netdev)
+-                      len = sprintf(buf, "%s\n", "default");
+-              else
+-                      len = sprintf(buf, "%s\n", session->netdev);
+-              break;
+-      case ISCSI_HOST_PARAM_HWADDRESS:
+-              if (!session->hwaddress)
+-                      len = sprintf(buf, "%s\n", "default");
+-              else
+-                      len = sprintf(buf, "%s\n", session->hwaddress);
+-              break;
+-      case ISCSI_HOST_PARAM_INITIATOR_NAME:
+-              if (!session->initiatorname)
+-                      len = sprintf(buf, "%s\n", "unknown");
+-              else
+-                      len = sprintf(buf, "%s\n", session->initiatorname);
+-              break;
+-
+-      default:
+-              return -ENOSYS;
+-      }
+-
+-      return len;
+-}
+-EXPORT_SYMBOL_GPL(iscsi_host_get_param);
+-
+-int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+-                       char *buf, int buflen)
+-{
+-      struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+-
+-      switch (param) {
+-      case ISCSI_HOST_PARAM_NETDEV_NAME:
+-              if (!session->netdev)
+-                      session->netdev = kstrdup(buf, GFP_KERNEL);
+-              break;
+-      case ISCSI_HOST_PARAM_HWADDRESS:
+-              if (!session->hwaddress)
+-                      session->hwaddress = kstrdup(buf, GFP_KERNEL);
+-              break;
+-      case ISCSI_HOST_PARAM_INITIATOR_NAME:
+-              if (!session->initiatorname)
+-                      session->initiatorname = kstrdup(buf, GFP_KERNEL);
+-              break;
+-      default:
+-              return -ENOSYS;
+-      }
+-
+-      return 0;
+-}
+-EXPORT_SYMBOL_GPL(iscsi_host_set_param);
+-
+ MODULE_AUTHOR("Mike Christie");
+ MODULE_DESCRIPTION("iSCSI library functions");
+ MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/drivers/scsi/libsas/sas_expander.c linux-2.6.22-570/drivers/scsi/libsas/sas_expander.c
+--- linux-2.6.22-590/drivers/scsi/libsas/sas_expander.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/libsas/sas_expander.c        2007-07-08 19:32:17.000000000 -0400
+@@ -38,10 +38,8 @@
  
--/* does _NOT_ require i_mutex to be held.
-+/*
-+ * does _NOT_ require i_mutex to be held.
-  *
-  * This function cannot be inlined since i_size_{read,write} is rather
-  * heavy-weight on 32-bit systems
-@@ -14,7 +26,8 @@
+ #if 0
+ /* FIXME: smp needs to migrate into the sas class */
+-static ssize_t smp_portal_read(struct kobject *, struct bin_attribute *,
+-                             char *, loff_t, size_t);
+-static ssize_t smp_portal_write(struct kobject *, struct bin_attribute *,
+-                              char *, loff_t, size_t);
++static ssize_t smp_portal_read(struct kobject *, char *, loff_t, size_t);
++static ssize_t smp_portal_write(struct kobject *, char *, loff_t, size_t);
+ #endif
+ /* ---------- SMP task management ---------- */
+@@ -1370,6 +1368,7 @@
+       memset(bin_attr, 0, sizeof(*bin_attr));
+       bin_attr->attr.name = SMP_BIN_ATTR_NAME;
++      bin_attr->attr.owner = THIS_MODULE;
+       bin_attr->attr.mode = 0600;
+       bin_attr->size = 0;
+@@ -1847,9 +1846,8 @@
+ #if 0
+ /* ---------- SMP portal ---------- */
+-static ssize_t smp_portal_write(struct kobject *kobj,
+-                              struct bin_attribute *bin_attr,
+-                              char *buf, loff_t offs, size_t size)
++static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs,
++                              size_t size)
+ {
+       struct domain_device *dev = to_dom_device(kobj);
+       struct expander_device *ex = &dev->ex_dev;
+@@ -1875,9 +1873,8 @@
+       return size;
  }
- EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
  
--/* copy all attributes; get_nlinks is optional way to override the i_nlink
-+/*
-+ * copy all attributes; get_nlinks is optional way to override the i_nlink
-  * copying
-  */
- void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
-diff -Nurb linux-2.6.22-570/fs/sync.c linux-2.6.22-590/fs/sync.c
---- linux-2.6.22-570/fs/sync.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/sync.c 2008-01-02 13:56:37.000000000 -0500
-@@ -174,6 +174,9 @@
-  * already-instantiated disk blocks, there are no guarantees here that the data
-  * will be available after a crash.
-  */
-+/* It would be nice if people remember that not all the world's an i386
-+   when they introduce new system calls */
-+
- asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
-                                       unsigned int flags)
+-static ssize_t smp_portal_read(struct kobject *kobj,
+-                             struct bin_attribute *bin_attr,
+-                             char *buf, loff_t offs, size_t size)
++static ssize_t smp_portal_read(struct kobject *kobj, char *buf, loff_t offs,
++                             size_t size)
  {
-diff -Nurb linux-2.6.22-570/fs/sysfs/bin.c linux-2.6.22-590/fs/sysfs/bin.c
---- linux-2.6.22-570/fs/sysfs/bin.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/sysfs/bin.c    2008-01-02 13:56:37.000000000 -0500
-@@ -20,29 +20,41 @@
+       struct domain_device *dev = to_dom_device(kobj);
+       struct expander_device *ex = &dev->ex_dev;
+diff -Nurb linux-2.6.22-590/drivers/scsi/libsas/sas_scsi_host.c linux-2.6.22-570/drivers/scsi/libsas/sas_scsi_host.c
+--- linux-2.6.22-590/drivers/scsi/libsas/sas_scsi_host.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/libsas/sas_scsi_host.c       2007-07-08 19:32:17.000000000 -0400
+@@ -40,7 +40,6 @@
  
- #include "sysfs.h"
+ #include <linux/err.h>
+ #include <linux/blkdev.h>
+-#include <linux/freezer.h>
+ #include <linux/scatterlist.h>
  
-+struct bin_buffer {
-+      struct mutex    mutex;
-+      void            *buffer;
-+      int             mmapped;
-+};
-+
- static int
- fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
+ /* ---------- SCSI Host glue ---------- */
+@@ -77,8 +76,8 @@
+                       hs = DID_NO_CONNECT;
+                       break;
+               case SAS_DATA_UNDERRUN:
+-                      scsi_set_resid(sc, ts->residual);
+-                      if (scsi_bufflen(sc) - scsi_get_resid(sc) < sc->underflow)
++                      sc->resid = ts->residual;
++                      if (sc->request_bufflen - sc->resid < sc->underflow)
+                               hs = DID_ERROR;
+                       break;
+               case SAS_DATA_OVERRUN:
+@@ -162,9 +161,9 @@
+       task->ssp_task.task_attr = sas_scsi_get_task_attr(cmd);
+       memcpy(task->ssp_task.cdb, cmd->cmnd, 16);
+-      task->scatter = scsi_sglist(cmd);
+-      task->num_scatter = scsi_sg_count(cmd);
+-      task->total_xfer_len = scsi_bufflen(cmd);
++      task->scatter = cmd->request_buffer;
++      task->num_scatter = cmd->use_sg;
++      task->total_xfer_len = cmd->request_bufflen;
+       task->data_dir = cmd->sc_data_direction;
+       task->task_done = sas_scsi_task_done;
+@@ -869,6 +868,8 @@
  {
--      struct bin_attribute * attr = to_bin_attr(dentry);
--      struct kobject * kobj = to_kobj(dentry->d_parent);
-+      struct sysfs_dirent *attr_sd = dentry->d_fsdata;
-+      struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
-+      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
-+      int rc;
-+
-+      /* need attr_sd for attr, its parent for kobj */
-+      if (!sysfs_get_active_two(attr_sd))
-+              return -ENODEV;
+       struct sas_ha_struct *sas_ha = _sas_ha;
++      current->flags |= PF_NOFREEZE;
 +
-+      rc = -EIO;
-+      if (attr->read)
-+              rc = attr->read(kobj, attr, buffer, off, count);
+       while (1) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule();
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/Makefile linux-2.6.22-570/drivers/scsi/lpfc/Makefile
+--- linux-2.6.22-590/drivers/scsi/lpfc/Makefile        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/Makefile        2007-07-08 19:32:17.000000000 -0400
+@@ -1,7 +1,7 @@
+ #/*******************************************************************
+ # * This file is part of the Emulex Linux Device Driver for         *
+ # * Fibre Channel Host Bus Adapters.                                *
+-# * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
++# * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
+ # * EMULEX and SLI are trademarks of Emulex.                        *
+ # * www.emulex.com                                                  *
+ # *                                                                 *
+@@ -27,5 +27,4 @@
+ obj-$(CONFIG_SCSI_LPFC) := lpfc.o
  
--      if (!attr->read)
--              return -EIO;
-+      sysfs_put_active_two(attr_sd);
+ lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o lpfc_hbadisc.o        \
+-      lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o \
+-      lpfc_vport.o lpfc_debugfs.o
++      lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc.h linux-2.6.22-570/drivers/scsi/lpfc/lpfc.h
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc.h  2007-07-08 19:32:17.000000000 -0400
+@@ -19,10 +19,9 @@
+  * included with this package.                                     *
+  *******************************************************************/
  
--      return attr->read(kobj, buffer, off, count);
-+      return rc;
- }
+-#include <scsi/scsi_host.h>
+-
+ struct lpfc_sli2_slim;
  
- static ssize_t
--read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
-+read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
- {
--      char *buffer = file->private_data;
-+      struct bin_buffer *bb = file->private_data;
-       struct dentry *dentry = file->f_path.dentry;
-       int size = dentry->d_inode->i_size;
-       loff_t offs = *off;
--      int ret;
++
+ #define LPFC_MAX_TARGET               256     /* max number of targets supported */
+ #define LPFC_MAX_DISC_THREADS 64      /* max outstanding discovery els
+                                          requests */
+@@ -33,20 +32,6 @@
+ #define LPFC_IOCB_LIST_CNT    2250    /* list of IOCBs for fast-path usage. */
+ #define LPFC_Q_RAMP_UP_INTERVAL 120     /* lun q_depth ramp up interval */
+-/*
+- * Following time intervals are used of adjusting SCSI device
+- * queue depths when there are driver resource error or Firmware
+- * resource error.
+- */
+-#define QUEUE_RAMP_DOWN_INTERVAL      (1 * HZ)   /* 1 Second */
+-#define QUEUE_RAMP_UP_INTERVAL                (300 * HZ) /* 5 minutes */
+-
+-/* Number of exchanges reserved for discovery to complete */
+-#define LPFC_DISC_IOCB_BUFF_COUNT 20
 -
--      if (count > PAGE_SIZE)
--              count = PAGE_SIZE;
-+      int count = min_t(size_t, bytes, PAGE_SIZE);
+-#define LPFC_HB_MBOX_INTERVAL   5     /* Heart beat interval in seconds. */
+-#define LPFC_HB_MBOX_TIMEOUT    30    /* Heart beat timeout  in seconds. */
+-
+ /* Define macros for 64 bit support */
+ #define putPaddrLow(addr)    ((uint32_t) (0xffffffff & (u64)(addr)))
+ #define putPaddrHigh(addr)   ((uint32_t) (0xffffffff & (((u64)(addr))>>32)))
+@@ -76,11 +61,6 @@
+       uint32_t    current_count;
+ };
  
-       if (size) {
-               if (offs > size)
-@@ -51,43 +63,56 @@
-                       count = size - offs;
-       }
+-struct hbq_dmabuf {
+-      struct lpfc_dmabuf dbuf;
+-      uint32_t tag;
+-};
+-
+ /* Priority bit.  Set value to exceed low water mark in lpfc_mem. */
+ #define MEM_PRI               0x100
  
--      ret = fill_read(dentry, buffer, offs, count);
--      if (ret < 0) 
--              return ret;
--      count = ret;
-+      mutex_lock(&bb->mutex);
+@@ -110,29 +90,6 @@
+               uint32_t sli2FwRev;
+               uint8_t sli2FwName[16];
+       } rev;
+-      struct {
+-#ifdef __BIG_ENDIAN_BITFIELD
+-              uint32_t rsvd2  :24;  /* Reserved                             */
+-              uint32_t cmv    : 1;  /* Configure Max VPIs                   */
+-              uint32_t ccrp   : 1;  /* Config Command Ring Polling          */
+-              uint32_t csah   : 1;  /* Configure Synchronous Abort Handling */
+-              uint32_t chbs   : 1;  /* Cofigure Host Backing store          */
+-              uint32_t cinb   : 1;  /* Enable Interrupt Notification Block  */
+-              uint32_t cerbm  : 1;  /* Configure Enhanced Receive Buf Mgmt  */
+-              uint32_t cmx    : 1;  /* Configure Max XRIs                   */
+-              uint32_t cmr    : 1;  /* Configure Max RPIs                   */
+-#else /*  __LITTLE_ENDIAN */
+-              uint32_t cmr    : 1;  /* Configure Max RPIs                   */
+-              uint32_t cmx    : 1;  /* Configure Max XRIs                   */
+-              uint32_t cerbm  : 1;  /* Configure Enhanced Receive Buf Mgmt  */
+-              uint32_t cinb   : 1;  /* Enable Interrupt Notification Block  */
+-              uint32_t chbs   : 1;  /* Cofigure Host Backing store          */
+-              uint32_t csah   : 1;  /* Configure Synchronous Abort Handling */
+-              uint32_t ccrp   : 1;  /* Config Command Ring Polling          */
+-              uint32_t cmv    : 1;  /* Configure Max VPIs                   */
+-              uint32_t rsvd2  :24;  /* Reserved                             */
+-#endif
+-      } sli3Feat;
+ } lpfc_vpd_t;
  
--      if (copy_to_user(userbuf, buffer, count))
--              return -EFAULT;
-+      count = fill_read(dentry, bb->buffer, offs, count);
-+      if (count < 0)
-+              goto out_unlock;
+ struct lpfc_scsi_buf;
+@@ -165,7 +122,6 @@
+       uint32_t elsRcvRPS;
+       uint32_t elsRcvRPL;
+       uint32_t elsXmitFLOGI;
+-      uint32_t elsXmitFDISC;
+       uint32_t elsXmitPLOGI;
+       uint32_t elsXmitPRLI;
+       uint32_t elsXmitADISC;
+@@ -209,53 +165,70 @@
+       struct lpfcMboxq *    mbox;
+ };
+-struct lpfc_hba;
++struct lpfc_hba {
++      struct lpfc_sli sli;
++      struct lpfc_sli2_slim *slim2p;
++      dma_addr_t slim2p_mapping;
++      uint16_t pci_cfg_value;
++      int32_t hba_state;
+-enum discovery_state {
+-      LPFC_VPORT_UNKNOWN     =  0,    /* vport state is unknown */
+-      LPFC_VPORT_FAILED      =  1,    /* vport has failed */
+-      LPFC_LOCAL_CFG_LINK    =  6,    /* local NPORT Id configured */
+-      LPFC_FLOGI             =  7,    /* FLOGI sent to Fabric */
+-      LPFC_FDISC             =  8,    /* FDISC sent for vport */
+-      LPFC_FABRIC_CFG_LINK   =  9,    /* Fabric assigned NPORT Id
+-                                       * configured */
+-      LPFC_NS_REG            =  10,   /* Register with NameServer */
+-      LPFC_NS_QRY            =  11,   /* Query NameServer for NPort ID list */
+-      LPFC_BUILD_DISC_LIST   =  12,   /* Build ADISC and PLOGI lists for
++#define LPFC_STATE_UNKNOWN        0    /* HBA state is unknown */
++#define LPFC_WARM_START           1    /* HBA state after selective reset */
++#define LPFC_INIT_START           2    /* Initial state after board reset */
++#define LPFC_INIT_MBX_CMDS        3    /* Initialize HBA with mbox commands */
++#define LPFC_LINK_DOWN            4    /* HBA initialized, link is down */
++#define LPFC_LINK_UP              5    /* Link is up  - issue READ_LA */
++#define LPFC_LOCAL_CFG_LINK       6    /* local NPORT Id configured */
++#define LPFC_FLOGI                7    /* FLOGI sent to Fabric */
++#define LPFC_FABRIC_CFG_LINK      8    /* Fabric assigned NPORT Id
++                                         configured */
++#define LPFC_NS_REG               9   /* Register with NameServer */
++#define LPFC_NS_QRY               10  /* Query NameServer for NPort ID list */
++#define LPFC_BUILD_DISC_LIST      11  /* Build ADISC and PLOGI lists for
+                                        * device authentication / discovery */
+-      LPFC_DISC_AUTH         =  13,   /* Processing ADISC list */
+-      LPFC_VPORT_READY       =  32,
+-};
++#define LPFC_DISC_AUTH            12  /* Processing ADISC list */
++#define LPFC_CLEAR_LA             13  /* authentication cmplt - issue
++                                         CLEAR_LA */
++#define LPFC_HBA_READY            32
++#define LPFC_HBA_ERROR            -1
+-enum hba_state {
+-      LPFC_LINK_UNKNOWN    =   0,   /* HBA state is unknown */
+-      LPFC_WARM_START      =   1,   /* HBA state after selective reset */
+-      LPFC_INIT_START      =   2,   /* Initial state after board reset */
+-      LPFC_INIT_MBX_CMDS   =   3,   /* Initialize HBA with mbox commands */
+-      LPFC_LINK_DOWN       =   4,   /* HBA initialized, link is down */
+-      LPFC_LINK_UP         =   5,   /* Link is up  - issue READ_LA */
+-      LPFC_CLEAR_LA        =   6,   /* authentication cmplt - issue
+-                                     * CLEAR_LA */
+-      LPFC_HBA_READY       =  32,
+-      LPFC_HBA_ERROR       =  -1
+-};
++      int32_t stopped;   /* HBA has not been restarted since last ERATT */
++      uint8_t fc_linkspeed;   /* Link speed after last READ_LA */
+-struct lpfc_vport {
+-      struct list_head listentry;
+-      struct lpfc_hba *phba;
+-      uint8_t port_type;
+-#define LPFC_PHYSICAL_PORT 1
+-#define LPFC_NPIV_PORT  2
+-#define LPFC_FABRIC_PORT 3
+-      enum discovery_state port_state;
++      uint32_t fc_eventTag;   /* event tag for link attention */
++      uint32_t fc_prli_sent;  /* cntr for outstanding PRLIs */
+-      uint16_t vpi;
++      uint32_t num_disc_nodes;        /*in addition to hba_state */
++      struct timer_list fc_estabtmo;  /* link establishment timer */
++      struct timer_list fc_disctmo;   /* Discovery rescue timer */
++      struct timer_list fc_fdmitmo;   /* fdmi timer */
++      /* These fields used to be binfo */
++      struct lpfc_name fc_nodename;   /* fc nodename */
++      struct lpfc_name fc_portname;   /* fc portname */
++      uint32_t fc_pref_DID;   /* preferred D_ID */
++      uint8_t fc_pref_ALPA;   /* preferred AL_PA */
++      uint32_t fc_edtov;      /* E_D_TOV timer value */
++      uint32_t fc_arbtov;     /* ARB_TOV timer value */
++      uint32_t fc_ratov;      /* R_A_TOV timer value */
++      uint32_t fc_rttov;      /* R_T_TOV timer value */
++      uint32_t fc_altov;      /* AL_TOV timer value */
++      uint32_t fc_crtov;      /* C_R_TOV timer value */
++      uint32_t fc_citov;      /* C_I_TOV timer value */
++      uint32_t fc_myDID;      /* fibre channel S_ID */
++      uint32_t fc_prevDID;    /* previous fibre channel S_ID */
 +
-+      if (copy_to_user(userbuf, bb->buffer, count)) {
-+              count = -EFAULT;
-+              goto out_unlock;
-+      }
++      struct serv_parm fc_sparam;     /* buffer for our service parameters */
++      struct serv_parm fc_fabparam;   /* fabric service parameters buffer */
++      uint8_t alpa_map[128];  /* AL_PA map from READ_LA */
++
++      uint8_t fc_ns_retry;    /* retries for fabric nameserver */
++      uint32_t fc_nlp_cnt;    /* outstanding NODELIST requests */
++      uint32_t fc_rscn_id_cnt;        /* count of RSCNs payloads in list */
++      struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN];
++      uint32_t lmt;
+       uint32_t fc_flag;       /* FC flags */
+-/* Several of these flags are HBA centric and should be moved to
+- * phba->link_flag (e.g. FC_PTP, FC_PUBLIC_LOOP)
+- */
+ #define FC_PT2PT                0x1   /* pt2pt with no fabric */
+ #define FC_PT2PT_PLOGI          0x2   /* pt2pt initiate PLOGI */
+ #define FC_DISC_TMO             0x4   /* Discovery timer running */
+@@ -266,14 +239,22 @@
+ #define FC_OFFLINE_MODE         0x80  /* Interface is offline for diag */
+ #define FC_FABRIC               0x100 /* We are fabric attached */
+ #define FC_ESTABLISH_LINK       0x200 /* Reestablish Link */
+-#define FC_RSCN_DISCOVERY       0x400  /* Auth all devices after RSCN */
++#define FC_RSCN_DISCOVERY       0x400 /* Authenticate all devices after RSCN*/
++#define FC_BLOCK_MGMT_IO        0x800   /* Don't allow mgmt mbx or iocb cmds */
++#define FC_LOADING            0x1000  /* HBA in process of loading drvr */
++#define FC_UNLOADING          0x2000  /* HBA in process of unloading drvr */
+ #define FC_SCSI_SCAN_TMO        0x4000        /* scsi scan timer running */
+ #define FC_ABORT_DISCOVERY      0x8000        /* we want to abort discovery */
+ #define FC_NDISC_ACTIVE         0x10000       /* NPort discovery active */
+ #define FC_BYPASSED_MODE        0x20000       /* NPort is in bypassed mode */
+-#define FC_RFF_NOT_SUPPORTED    0x40000        /* RFF_ID was rejected by switch */
+-#define FC_VPORT_NEEDS_REG_VPI        0x80000  /* Needs to have its vpi registered */
+-#define FC_RSCN_DEFERRED      0x100000 /* A deferred RSCN being processed */
++#define FC_LOOPBACK_MODE        0x40000       /* NPort is in Loopback mode */
++                                      /* This flag is set while issuing */
++                                      /* INIT_LINK mailbox command */
++#define FC_IGNORE_ERATT         0x80000       /* intr handler should ignore ERATT */
++
++      uint32_t fc_topology;   /* link topology, from LINK INIT */
++
++      struct lpfc_stats fc_stat;
  
--      pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count);
-+      pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
+       struct list_head fc_nodes;
  
-       *off = offs + count;
+@@ -286,131 +267,10 @@
+       uint16_t fc_map_cnt;
+       uint16_t fc_npr_cnt;
+       uint16_t fc_unused_cnt;
+-      struct serv_parm fc_sparam;     /* buffer for our service parameters */
+-
+-      uint32_t fc_myDID;      /* fibre channel S_ID */
+-      uint32_t fc_prevDID;    /* previous fibre channel S_ID */
+-
+-      int32_t stopped;   /* HBA has not been restarted since last ERATT */
+-      uint8_t fc_linkspeed;   /* Link speed after last READ_LA */
+-
+-      uint32_t num_disc_nodes;        /*in addition to hba_state */
+-
+-      uint32_t fc_nlp_cnt;    /* outstanding NODELIST requests */
+-      uint32_t fc_rscn_id_cnt;        /* count of RSCNs payloads in list */
+-      struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN];
+-      struct lpfc_name fc_nodename;   /* fc nodename */
+-      struct lpfc_name fc_portname;   /* fc portname */
+-
+-      struct lpfc_work_evt disc_timeout_evt;
+-
+-      struct timer_list fc_disctmo;   /* Discovery rescue timer */
+-      uint8_t fc_ns_retry;    /* retries for fabric nameserver */
+-      uint32_t fc_prli_sent;  /* cntr for outstanding PRLIs */
+-
+-      spinlock_t work_port_lock;
+-      uint32_t work_port_events; /* Timeout to be handled  */
+-#define WORKER_DISC_TMO                0x1    /* vport: Discovery timeout */
+-#define WORKER_ELS_TMO                 0x2    /* vport: ELS timeout */
+-#define WORKER_FDMI_TMO                0x4    /* vport: FDMI timeout */
+-
+-#define WORKER_MBOX_TMO                0x100  /* hba: MBOX timeout */
+-#define WORKER_HB_TMO                  0x200  /* hba: Heart beat timeout */
+-#define WORKER_FABRIC_BLOCK_TMO        0x400  /* hba: fabric block timout */
+-#define WORKER_RAMP_DOWN_QUEUE         0x800  /* hba: Decrease Q depth */
+-#define WORKER_RAMP_UP_QUEUE           0x1000 /* hba: Increase Q depth */
+-
+-      struct timer_list fc_fdmitmo;
+-      struct timer_list els_tmofunc;
+-
+-      int unreg_vpi_cmpl;
+-
+-      uint8_t load_flag;
+-#define FC_LOADING            0x1     /* HBA in process of loading drvr */
+-#define FC_UNLOADING          0x2     /* HBA in process of unloading drvr */
+-      char  *vname;                   /* Application assigned name */
+-      struct fc_vport *fc_vport;
+-
+-#ifdef CONFIG_LPFC_DEBUG_FS
+-      struct dentry *debug_disc_trc;
+-      struct dentry *debug_nodelist;
+-      struct dentry *vport_debugfs_root;
+-      struct lpfc_disc_trc *disc_trc;
+-      atomic_t disc_trc_cnt;
+-#endif
+-};
+-
+-struct hbq_s {
+-      uint16_t entry_count;     /* Current number of HBQ slots */
+-      uint32_t next_hbqPutIdx;  /* Index to next HBQ slot to use */
+-      uint32_t hbqPutIdx;       /* HBQ slot to use */
+-      uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */
+-};
+-
+-#define LPFC_MAX_HBQS  16
+-/* this matches the possition in the lpfc_hbq_defs array */
+-#define LPFC_ELS_HBQ  0
+-
+-struct lpfc_hba {
+-      struct lpfc_sli sli;
+-      uint32_t sli_rev;               /* SLI2 or SLI3 */
+-      uint32_t sli3_options;          /* Mask of enabled SLI3 options */
+-#define LPFC_SLI3_ENABLED      0x01
+-#define LPFC_SLI3_HBQ_ENABLED  0x02
+-#define LPFC_SLI3_NPIV_ENABLED         0x04
+-#define LPFC_SLI3_VPORT_TEARDOWN 0x08
+-      uint32_t iocb_cmd_size;
+-      uint32_t iocb_rsp_size;
+-
+-      enum hba_state link_state;
+-      uint32_t link_flag;     /* link state flags */
+-#define LS_LOOPBACK_MODE      0x1     /* NPort is in Loopback mode */
+-                                      /* This flag is set while issuing */
+-                                      /* INIT_LINK mailbox command */
+-#define LS_NPIV_FAB_SUPPORTED 0x2     /* Fabric supports NPIV */
+-#define LS_IGNORE_ERATT       0x3     /* intr handler should ignore ERATT */
+-
+-      struct lpfc_sli2_slim *slim2p;
+-      struct lpfc_dmabuf hbqslimp;
+-
+-      dma_addr_t slim2p_mapping;
+-
+-      uint16_t pci_cfg_value;
+-
+-      uint8_t work_found;
+-#define LPFC_MAX_WORKER_ITERATION  4
+-
+-      uint8_t fc_linkspeed;   /* Link speed after last READ_LA */
+-
+-      uint32_t fc_eventTag;   /* event tag for link attention */
+-
+-
+-      struct timer_list fc_estabtmo;  /* link establishment timer */
+-      /* These fields used to be binfo */
+-      uint32_t fc_pref_DID;   /* preferred D_ID */
+-      uint8_t  fc_pref_ALPA;  /* preferred AL_PA */
+-      uint32_t fc_edtov;      /* E_D_TOV timer value */
+-      uint32_t fc_arbtov;     /* ARB_TOV timer value */
+-      uint32_t fc_ratov;      /* R_A_TOV timer value */
+-      uint32_t fc_rttov;      /* R_T_TOV timer value */
+-      uint32_t fc_altov;      /* AL_TOV timer value */
+-      uint32_t fc_crtov;      /* C_R_TOV timer value */
+-      uint32_t fc_citov;      /* C_I_TOV timer value */
+-
+-      struct serv_parm fc_fabparam;   /* fabric service parameters buffer */
+-      uint8_t alpa_map[128];  /* AL_PA map from READ_LA */
+-
+-      uint32_t lmt;
+-
+-      uint32_t fc_topology;   /* link topology, from LINK INIT */
+-
+-      struct lpfc_stats fc_stat;
+-
+       struct lpfc_nodelist fc_fcpnodev; /* nodelist entry for no device */
+       uint32_t nport_event_cnt;       /* timestamp for nlplist entry */
+-      uint8_t  wwnn[8];
+-      uint8_t  wwpn[8];
++      uint32_t wwnn[2];
+       uint32_t RandomData[7];
  
-+ out_unlock:
-+      mutex_unlock(&bb->mutex);
-       return count;
- }
+       uint32_t cfg_log_verbose;
+@@ -418,9 +278,6 @@
+       uint32_t cfg_nodev_tmo;
+       uint32_t cfg_devloss_tmo;
+       uint32_t cfg_hba_queue_depth;
+-      uint32_t cfg_peer_port_login;
+-      uint32_t cfg_vport_restrict_login;
+-      uint32_t cfg_npiv_enable;
+       uint32_t cfg_fcp_class;
+       uint32_t cfg_use_adisc;
+       uint32_t cfg_ack0;
+@@ -447,20 +304,22 @@
  
- static int
- flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
- {
--      struct bin_attribute *attr = to_bin_attr(dentry);
--      struct kobject *kobj = to_kobj(dentry->d_parent);
-+      struct sysfs_dirent *attr_sd = dentry->d_fsdata;
-+      struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
-+      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
-+      int rc;
+       lpfc_vpd_t vpd;         /* vital product data */
  
--      if (!attr->write)
--              return -EIO;
-+      /* need attr_sd for attr, its parent for kobj */
-+      if (!sysfs_get_active_two(attr_sd))
-+              return -ENODEV;
++      struct Scsi_Host *host;
+       struct pci_dev *pcidev;
+       struct list_head      work_list;
+       uint32_t              work_ha;      /* Host Attention Bits for WT */
+       uint32_t              work_ha_mask; /* HA Bits owned by WT        */
+       uint32_t              work_hs;      /* HS stored in case of ERRAT */
+       uint32_t              work_status[2]; /* Extra status from SLIM */
++      uint32_t              work_hba_events; /* Timeout to be handled  */
++#define WORKER_DISC_TMO                0x1    /* Discovery timeout */
++#define WORKER_ELS_TMO                 0x2    /* ELS timeout */
++#define WORKER_MBOX_TMO                0x4    /* MBOX timeout */
++#define WORKER_FDMI_TMO                0x8    /* FDMI timeout */
  
--      return attr->write(kobj, buffer, offset, count);
-+      rc = -EIO;
-+      if (attr->write)
-+              rc = attr->write(kobj, attr, buffer, offset, count);
-+
-+      sysfs_put_active_two(attr_sd);
-+
-+      return rc;
- }
+       wait_queue_head_t    *work_wait;
+       struct task_struct   *worker_thread;
  
--static ssize_t write(struct file * file, const char __user * userbuf,
--                   size_t count, loff_t * off)
-+static ssize_t write(struct file *file, const char __user *userbuf,
-+                   size_t bytes, loff_t *off)
- {
--      char *buffer = file->private_data;
-+      struct bin_buffer *bb = file->private_data;
-       struct dentry *dentry = file->f_path.dentry;
-       int size = dentry->d_inode->i_size;
-       loff_t offs = *off;
-+      int count = min_t(size_t, bytes, PAGE_SIZE);
+-      struct list_head hbq_buffer_list;
+-      uint32_t hbq_count;             /* Count of configured HBQs */
+-      struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies  */
+-
+       unsigned long pci_bar0_map;     /* Physical address for PCI BAR0 */
+       unsigned long pci_bar2_map;     /* Physical address for PCI BAR2 */
+       void __iomem *slim_memmap_p;    /* Kernel memory mapped address for
+@@ -475,10 +334,6 @@
+                                          reg */
+       void __iomem *HCregaddr;        /* virtual address for host ctl reg */
  
--      if (count > PAGE_SIZE)
--              count = PAGE_SIZE;
-       if (size) {
-               if (offs > size)
-                       return 0;
-@@ -95,72 +120,100 @@
-                       count = size - offs;
-       }
+-      struct lpfc_hgp __iomem *host_gp; /* Host side get/put pointers */
+-      uint32_t __iomem  *hbq_put;     /* Address in SLIM to HBQ put ptrs */
+-      uint32_t          *hbq_get;     /* Host mem address of HBQ get ptrs */
+-
+       int brd_no;                     /* FC board number */
  
--      if (copy_from_user(buffer, userbuf, count))
--              return -EFAULT;
-+      mutex_lock(&bb->mutex);
+       char SerialNumber[32];          /* adapter Serial Number */
+@@ -498,6 +353,7 @@
+       uint8_t soft_wwn_enable;
  
--      count = flush_write(dentry, buffer, offs, count);
-+      if (copy_from_user(bb->buffer, userbuf, count)) {
-+              count = -EFAULT;
-+              goto out_unlock;
-+      }
-+
-+      count = flush_write(dentry, bb->buffer, offs, count);
-       if (count > 0)
-               *off = offs + count;
-+
-+ out_unlock:
-+      mutex_unlock(&bb->mutex);
-       return count;
- }
+       struct timer_list fcp_poll_timer;
++      struct timer_list els_tmofunc;
  
- static int mmap(struct file *file, struct vm_area_struct *vma)
- {
--      struct dentry *dentry = file->f_path.dentry;
--      struct bin_attribute *attr = to_bin_attr(dentry);
--      struct kobject *kobj = to_kobj(dentry->d_parent);
-+      struct bin_buffer *bb = file->private_data;
-+      struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-+      struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
-+      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
-+      int rc;
-+
-+      mutex_lock(&bb->mutex);
-+
-+      /* need attr_sd for attr, its parent for kobj */
-+      if (!sysfs_get_active_two(attr_sd))
-+              return -ENODEV;
-+
-+      rc = -EINVAL;
-+      if (attr->mmap)
-+              rc = attr->mmap(kobj, attr, vma);
-+
-+      if (rc == 0 && !bb->mmapped)
-+              bb->mmapped = 1;
-+      else
-+              sysfs_put_active_two(attr_sd);
+       /*
+        * stat  counters
+@@ -514,69 +370,31 @@
+       uint32_t total_scsi_bufs;
+       struct list_head lpfc_iocb_list;
+       uint32_t total_iocbq_bufs;
+-      spinlock_t hbalock;
  
--      if (!attr->mmap)
--              return -EINVAL;
-+      mutex_unlock(&bb->mutex);
+       /* pci_mem_pools */
+       struct pci_pool *lpfc_scsi_dma_buf_pool;
+       struct pci_pool *lpfc_mbuf_pool;
+-      struct pci_pool *lpfc_hbq_pool;
+       struct lpfc_dma_pool lpfc_mbuf_safety_pool;
  
--      return attr->mmap(kobj, attr, vma);
-+      return rc;
- }
+       mempool_t *mbox_mem_pool;
+       mempool_t *nlp_mem_pool;
  
- static int open(struct inode * inode, struct file * file)
- {
--      struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
--      struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
--      int error = -EINVAL;
+       struct fc_host_statistics link_stats;
 -
--      if (!kobj || !attr)
--              goto Done;
+-      struct list_head port_list;
+-      struct lpfc_vport *pport; /* physical lpfc_vport pointer */
+-      uint16_t max_vpi;       /* Maximum virtual nports */
+-#define LPFC_MAX_VPI 100  /* Max number of VPorts supported */
+-      unsigned long *vpi_bmask; /* vpi allocation table */
+-
+-      /* Data structure used by fabric iocb scheduler */
+-      struct list_head fabric_iocb_list;
+-      atomic_t fabric_iocb_count;
+-      struct timer_list fabric_block_timer;
+-      unsigned long bit_flags;
+-#define       FABRIC_COMANDS_BLOCKED  0
+-      atomic_t num_rsrc_err;
+-      atomic_t num_cmd_success;
+-      unsigned long last_rsrc_error_time;
+-      unsigned long last_ramp_down_time;
+-      unsigned long last_ramp_up_time;
+-#ifdef CONFIG_LPFC_DEBUG_FS
+-      struct dentry *hba_debugfs_root;
+-      atomic_t debugfs_vport_count;
+-#endif
+-
+-      /* Fields used for heart beat. */
+-      unsigned long last_completion_time;
+-      struct timer_list hb_tmofunc;
+-      uint8_t hb_outstanding;
+ };
+-static inline struct Scsi_Host *
+-lpfc_shost_from_vport(struct lpfc_vport *vport)
+-{
+-      return container_of((void *) vport, struct Scsi_Host, hostdata[0]);
+-}
 -
--      /* Grab the module reference for this attribute if we have one */
--      error = -ENODEV;
--      if (!try_module_get(attr->attr.owner)) 
--              goto Done;
-+      struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-+      struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
-+      struct bin_buffer *bb = NULL;
-+      int error;
-+
-+      /* need attr_sd for attr */
-+      if (!sysfs_get_active(attr_sd))
-+              return -ENODEV;
+ static inline void
+-lpfc_set_loopback_flag(struct lpfc_hba *phba)
+-{
++lpfc_set_loopback_flag(struct lpfc_hba *phba) {
+       if (phba->cfg_topology == FLAGS_LOCAL_LB)
+-              phba->link_flag |= LS_LOOPBACK_MODE;
++              phba->fc_flag |= FC_LOOPBACK_MODE;
+       else
+-              phba->link_flag &= ~LS_LOOPBACK_MODE;
++              phba->fc_flag &= ~FC_LOOPBACK_MODE;
+ }
  
-       error = -EACCES;
-       if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap))
--              goto Error;
-+              goto err_out;
-       if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap))
--              goto Error;
-+              goto err_out;
+-static inline int
+-lpfc_is_link_up(struct lpfc_hba *phba)
+-{
+-      return  phba->link_state == LPFC_LINK_UP ||
+-              phba->link_state == LPFC_CLEAR_LA ||
+-              phba->link_state == LPFC_HBA_READY;
+-}
++struct rnidrsp {
++      void *buf;
++      uint32_t uniqueid;
++      struct list_head list;
++      uint32_t data;
++};
  
-       error = -ENOMEM;
--      file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
--      if (!file->private_data)
--              goto Error;
+ #define FC_REG_DUMP_EVENT     0x10    /* Register for Dump events */
 -
--      error = 0;
--    goto Done;
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_attr.c linux-2.6.22-570/drivers/scsi/lpfc/lpfc_attr.c
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_attr.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_attr.c     2007-07-08 19:32:17.000000000 -0400
+@@ -39,7 +39,6 @@
+ #include "lpfc_version.h"
+ #include "lpfc_compat.h"
+ #include "lpfc_crtn.h"
+-#include "lpfc_vport.h"
+ #define LPFC_DEF_DEVLOSS_TMO 30
+ #define LPFC_MIN_DEVLOSS_TMO 1
+@@ -77,156 +76,116 @@
+ lpfc_info_show(struct class_device *cdev, char *buf)
+ {
+       struct Scsi_Host *host = class_to_shost(cdev);
 -
-- Error:
--      module_put(attr->attr.owner);
-- Done:
--      if (error)
--              kobject_put(kobj);
-+      bb = kzalloc(sizeof(*bb), GFP_KERNEL);
-+      if (!bb)
-+              goto err_out;
-+
-+      bb->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
-+      if (!bb->buffer)
-+              goto err_out;
-+
-+      mutex_init(&bb->mutex);
-+      file->private_data = bb;
-+
-+      /* open succeeded, put active reference and pin attr_sd */
-+      sysfs_put_active(attr_sd);
-+      sysfs_get(attr_sd);
-+      return 0;
-+
-+ err_out:
-+      sysfs_put_active(attr_sd);
-+      kfree(bb);
-       return error;
+       return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host));
  }
  
- static int release(struct inode * inode, struct file * file)
+ static ssize_t
+ lpfc_serialnum_show(struct class_device *cdev, char *buf)
  {
--      struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent);
--      struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
--      u8 * buffer = file->private_data;
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
 -
--      kobject_put(kobj);
--      module_put(attr->attr.owner);
--      kfree(buffer);
-+      struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-+      struct bin_buffer *bb = file->private_data;
-+
-+      if (bb->mmapped)
-+              sysfs_put_active_two(attr_sd);
-+      sysfs_put(attr_sd);
-+      kfree(bb->buffer);
-+      kfree(bb);
-       return 0;
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber);
  }
  
-@@ -181,9 +234,9 @@
- int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
+ static ssize_t
+ lpfc_modeldesc_show(struct class_device *cdev, char *buf)
  {
--      BUG_ON(!kobj || !kobj->dentry || !attr);
-+      BUG_ON(!kobj || !kobj->sd || !attr);
--      return sysfs_add_file(kobj->dentry, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
-+      return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc);
  }
  
-@@ -195,7 +248,7 @@
- void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
+ static ssize_t
+ lpfc_modelname_show(struct class_device *cdev, char *buf)
  {
--      if (sysfs_hash_and_remove(kobj->dentry, attr->attr.name) < 0) {
-+      if (sysfs_hash_and_remove(kobj, kobj->sd, attr->attr.name) < 0) {
-               printk(KERN_ERR "%s: "
-                       "bad dentry or inode or no such file: \"%s\"\n",
-                       __FUNCTION__, attr->attr.name);
-diff -Nurb linux-2.6.22-570/fs/sysfs/dir.c linux-2.6.22-590/fs/sysfs/dir.c
---- linux-2.6.22-570/fs/sysfs/dir.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/sysfs/dir.c    2008-01-02 13:56:37.000000000 -0500
-@@ -9,21 +9,442 @@
- #include <linux/module.h>
- #include <linux/kobject.h>
- #include <linux/namei.h>
-+#include <linux/idr.h>
-+#include <linux/completion.h>
- #include <asm/semaphore.h>
- #include "sysfs.h"
--DECLARE_RWSEM(sysfs_rename_sem);
--spinlock_t sysfs_lock = SPIN_LOCK_UNLOCKED;
-+static void sysfs_prune_shadow_sd(struct sysfs_dirent *sd);
-+
-+DEFINE_MUTEX(sysfs_mutex);
-+spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED;
-+
-+static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED;
-+static DEFINE_IDA(sysfs_ino_ida);
-+
-+static struct sysfs_dirent *find_shadow_sd(struct sysfs_dirent *parent_sd, const void *target)
-+{
-+      /* Find the shadow directory for the specified tag */
-+      struct sysfs_dirent *sd;
-+
-+      for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) {
-+              if (sd->s_name != target)
-+                      continue;
-+              break;
-+      }
-+      return sd;
-+}
-+
-+static const void *find_shadow_tag(struct kobject *kobj)
-+{
-+      /* Find the tag the current kobj is cached with */
-+      return kobj->sd->s_parent->s_name;
-+}
-+
-+/**
-+ *    sysfs_link_sibling - link sysfs_dirent into sibling list
-+ *    @sd: sysfs_dirent of interest
-+ *
-+ *    Link @sd into its sibling list which starts from
-+ *    sd->s_parent->s_children.
-+ *
-+ *    Locking:
-+ *    mutex_lock(sysfs_mutex)
-+ */
-+
-+/**
-+ *    sysfs_unlink_sibling - unlink sysfs_dirent from sibling list
-+ *    @sd: sysfs_dirent of interest
-+ *
-+ *    Unlink @sd from its sibling list which starts from
-+ *    sd->s_parent->s_children.
-+ *
-+ *    Locking:
-+ *    mutex_lock(sysfs_mutex)
-+ */
-+
-+void sysfs_link_sibling(struct sysfs_dirent *sd)
-+{
-+      struct sysfs_dirent *parent_sd = sd->s_parent;
-+
-+      BUG_ON(sd->s_sibling);
-+      sd->s_sibling = parent_sd->s_children;
-+      parent_sd->s_children = sd;
-+}
-+/**
-+ *    sysfs_get_dentry - get dentry for the given sysfs_dirent
-+ *    @sd: sysfs_dirent of interest
-+ *
-+ *    Get dentry for @sd.  Dentry is looked up if currently not
-+ *    present.  This function climbs sysfs_dirent tree till it
-+ *    reaches a sysfs_dirent with valid dentry attached and descends
-+ *    down from there looking up dentry for each step.
-+ *
-+ *    LOCKING:
-+ *    Kernel thread context (may sleep)
-+ *
-+ *    RETURNS:
-+ *    Pointer to found dentry on success, ERR_PTR() value on error.
-+ */
-+struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd)
-+{
-+      struct sysfs_dirent *cur;
-+      struct dentry *parent_dentry, *dentry;
-+      int i, depth;
-+
-+      /* Find the first parent which has valid s_dentry and get the
-+       * dentry.
-+       */
-+      mutex_lock(&sysfs_mutex);
-+ restart0:
-+      spin_lock(&sysfs_assoc_lock);
-+ restart1:
-+      spin_lock(&dcache_lock);
-+
-+      dentry = NULL;
-+      depth = 0;
-+      cur = sd;
-+      while (!cur->s_dentry || !cur->s_dentry->d_inode) {
-+              if (cur->s_flags & SYSFS_FLAG_REMOVED) {
-+                      dentry = ERR_PTR(-ENOENT);
-+                      depth = 0;
-+                      break;
-+              }
-+              cur = cur->s_parent;
-+              depth++;
-+      }
-+      if (!IS_ERR(dentry))
-+              dentry = dget_locked(cur->s_dentry);
-+
-+      spin_unlock(&dcache_lock);
-+      spin_unlock(&sysfs_assoc_lock);
-+
-+      /* from the found dentry, look up depth times */
-+      while (depth--) {
-+              /* find and get depth'th ancestor */
-+              for (cur = sd, i = 0; cur && i < depth; i++)
-+                      cur = cur->s_parent;
-+
-+              /* This can happen if tree structure was modified due
-+               * to move/rename.  Restart.
-+               */
-+              if (i != depth) {
-+                      dput(dentry);
-+                      goto restart0;
-+              }
-+
-+              sysfs_get(cur);
-+
-+              mutex_unlock(&sysfs_mutex);
-+
-+              /* look it up */
-+              parent_dentry = dentry;
-+              dentry = lookup_one_len_kern(cur->s_name, parent_dentry,
-+                                           strlen(cur->s_name));
-+              dput(parent_dentry);
-+
-+              if (IS_ERR(dentry)) {
-+                      sysfs_put(cur);
-+                      return dentry;
-+              }
-+
-+              mutex_lock(&sysfs_mutex);
-+              spin_lock(&sysfs_assoc_lock);
-+
-+              /* This, again, can happen if tree structure has
-+               * changed and we looked up the wrong thing.  Restart.
-+               */
-+              if (cur->s_dentry != dentry) {
-+                      dput(dentry);
-+                      sysfs_put(cur);
-+                      goto restart1;
-+              }
-+
-+              spin_unlock(&sysfs_assoc_lock);
-+
-+              sysfs_put(cur);
-+      }
-+
-+      mutex_unlock(&sysfs_mutex);
-+      return dentry;
-+}
-+
-+/**
-+ *    sysfs_link_sibling - link sysfs_dirent into sibling list
-+ *    @sd: sysfs_dirent of interest
-+ *
-+ *    Link @sd into its sibling list which starts from
-+ *    sd->s_parent->s_children.
-+ *
-+ *    Locking:
-+ *    mutex_lock(sd->s_parent->dentry->d_inode->i_mutex)
-+ */
-+
-+/**
-+ *    sysfs_unlink_sibling - unlink sysfs_dirent from sibling list
-+ *    @sd: sysfs_dirent of interest
-+ *
-+ *    Unlink @sd from its sibling list which starts from
-+ *    sd->s_parent->s_children.
-+ *
-+ *    Locking:
-+ *    mutex_lock(sd->s_parent->dentry->d_inode->i_mutex)
-+ */
-+void sysfs_unlink_sibling(struct sysfs_dirent *sd)
-+{
-+      struct sysfs_dirent **pos;
-+
-+      for (pos = &sd->s_parent->s_children; *pos; pos = &(*pos)->s_sibling) {
-+              if (*pos == sd) {
-+                      *pos = sd->s_sibling;
-+                      sd->s_sibling = NULL;
-+                      break;
-+              }
-+      }
-+}
-+
-+/**
-+ *    sysfs_get_dentry - get dentry for the given sysfs_dirent
-+ *    @sd: sysfs_dirent of interest
-+ *
-+ *    Get dentry for @sd.  Dentry is looked up if currently not
-+ *    present.  This function climbs sysfs_dirent tree till it
-+ *    reaches a sysfs_dirent with valid dentry attached and descends
-+ *    down from there looking up dentry for each step.
-+ *
-+ *    LOCKING:
-+ *    Kernel thread context (may sleep)
-+ *
-+ *    RETURNS:
-+ *    Pointer to found dentry on success, ERR_PTR() value on error.
-+ */
-+
-+/**
-+ *    sysfs_get_active - get an active reference to sysfs_dirent
-+ *    @sd: sysfs_dirent to get an active reference to
-+ *
-+ *    Get an active reference of @sd.  This function is noop if @sd
-+ *    is NULL.
-+ *
-+ *    RETURNS:
-+ *    Pointer to @sd on success, NULL on failure.
-+ */
-+/**
-+ *    sysfs_put_active - put an active reference to sysfs_dirent
-+ *    @sd: sysfs_dirent to put an active reference to
-+ *
-+ *    Put an active reference to @sd.  This function is noop if @sd
-+ *    is NULL.
-+ */
-+void sysfs_put_active(struct sysfs_dirent *sd)
-+{
-+      struct completion *cmpl;
-+      int v;
-+
-+      if (unlikely(!sd))
-+              return;
-+
-+      v = atomic_dec_return(&sd->s_active);
-+      if (likely(v != SD_DEACTIVATED_BIAS))
-+              return;
-+
-+      /* atomic_dec_return() is a mb(), we'll always see the updated
-+       * sd->s_sibling.
-+       */
-+      cmpl = (void *)sd->s_sibling;
-+      complete(cmpl);
-+}
-+
-+/**
-+ *    sysfs_get_active_two - get active references to sysfs_dirent and parent
-+ *    @sd: sysfs_dirent of interest
-+ *
-+ *    Get active reference to @sd and its parent.  Parent's active
-+ *    reference is grabbed first.  This function is noop if @sd is
-+ *    NULL.
-+ *
-+ *    RETURNS:
-+ *    Pointer to @sd on success, NULL on failure.
-+ */
-+struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd)
-+{
-+      if (sd) {
-+              if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent)))
-+                      return NULL;
-+              if (unlikely(!sysfs_get_active(sd))) {
-+                      sysfs_put_active(sd->s_parent);
-+                      return NULL;
-+              }
-+      }
-+      return sd;
-+}
-+
-+/**
-+ *    sysfs_put_active_two - put active references to sysfs_dirent and parent
-+ *    @sd: sysfs_dirent of interest
-+ *
-+ *    Put active references to @sd and its parent.  This function is
-+ *    noop if @sd is NULL.
-+ */
-+void sysfs_put_active_two(struct sysfs_dirent *sd)
-+{
-+      if (sd) {
-+              sysfs_put_active(sd);
-+              sysfs_put_active(sd->s_parent);
-+      }
-+}
-+
-+/**
-+ *    sysfs_deactivate - deactivate sysfs_dirent
-+ *    @sd: sysfs_dirent to deactivate
-+ *
-+ *    Deny new active references and drain existing ones.
-+ */
-+static void sysfs_deactivate(struct sysfs_dirent *sd)
-+{
-+      DECLARE_COMPLETION_ONSTACK(wait);
-+      int v;
-+
-+      BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
-+      sd->s_sibling = (void *)&wait;
-+
-+      /* atomic_add_return() is a mb(), put_active() will always see
-+       * the updated sd->s_sibling.
-+       */
-+      v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active);
-+
-+      if (v != SD_DEACTIVATED_BIAS)
-+              wait_for_completion(&wait);
-+
-+      sd->s_sibling = NULL;
-+}
-+
-+/**
-+ *    sysfs_get_active - get an active reference to sysfs_dirent
-+ *    @sd: sysfs_dirent to get an active reference to
-+ *
-+ *    Get an active reference of @sd.  This function is noop if @sd
-+ *    is NULL.
-+ *
-+ *    RETURNS:
-+ *    Pointer to @sd on success, NULL on failure.
-+ */
-+struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
-+{
-+      if (unlikely(!sd))
-+              return NULL;
-+
-+      while (1) {
-+              int v, t;
-+
-+              v = atomic_read(&sd->s_active);
-+              if (unlikely(v < 0))
-+                      return NULL;
-+
-+              t = atomic_cmpxchg(&sd->s_active, v, v + 1);
-+              if (likely(t == v))
-+                      return sd;
-+              if (t < 0)
-+                      return NULL;
-+
-+              cpu_relax();
-+      }
-+}
-+/**
-+ *    sysfs_put_active - put an active reference to sysfs_dirent
-+ *    @sd: sysfs_dirent to put an active reference to
-+ *
-+ *    Put an active reference to @sd.  This function is noop if @sd
-+ *    is NULL.
-+ */
-+
-+/**
-+ *    sysfs_get_active_two - get active references to sysfs_dirent and parent
-+ *    @sd: sysfs_dirent of interest
-+ *
-+ *    Get active reference to @sd and its parent.  Parent's active
-+ *    reference is grabbed first.  This function is noop if @sd is
-+ *    NULL.
-+ *
-+ *    RETURNS:
-+ *    Pointer to @sd on success, NULL on failure.
-+ */
-+
-+/**
-+ *    sysfs_put_active_two - put active references to sysfs_dirent and parent
-+ *    @sd: sysfs_dirent of interest
-+ *
-+ *    Put active references to @sd and its parent.  This function is
-+ *    noop if @sd is NULL.
-+ */
-+
-+/**
-+ *    sysfs_deactivate - deactivate sysfs_dirent
-+ *    @sd: sysfs_dirent to deactivate
-+ *
-+ *    Deny new active references and drain existing ones.  s_active
-+ *    will be unlocked when the sysfs_dirent is released.
-+ */
-+
-+static int sysfs_alloc_ino(ino_t *pino)
-+{
-+      int ino, rc;
-+
-+ retry:
-+      spin_lock(&sysfs_ino_lock);
-+      rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino);
-+      spin_unlock(&sysfs_ino_lock);
-+
-+      if (rc == -EAGAIN) {
-+              if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL))
-+                      goto retry;
-+              rc = -ENOMEM;
-+      }
-+
-+      *pino = ino;
-+      return rc;
-+}
-+
-+static void sysfs_free_ino(ino_t ino)
-+{
-+      spin_lock(&sysfs_ino_lock);
-+      ida_remove(&sysfs_ino_ida, ino);
-+      spin_unlock(&sysfs_ino_lock);
-+}
-+
-+void release_sysfs_dirent(struct sysfs_dirent * sd)
-+{
-+      struct sysfs_dirent *parent_sd;
-+
-+ repeat:
-+      /* Moving/renaming is always done while holding reference.
-+       * sd->s_parent won't change beneath us.
-+       */
-+      parent_sd = sd->s_parent;
-+
-+      if (sysfs_type(sd) == SYSFS_KOBJ_LINK)
-+              sysfs_put(sd->s_elem.symlink.target_sd);
-+      if (sysfs_type(sd) & SYSFS_COPY_NAME)
-+              kfree(sd->s_name);
-+      kfree(sd->s_iattr);
-+      if (sysfs_type(sd) != SYSFS_SHADOW_DIR)
-+              sysfs_free_ino(sd->s_ino);
-+      kmem_cache_free(sysfs_dir_cachep, sd);
-+
-+      sd = parent_sd;
-+      if (sd && atomic_dec_and_test(&sd->s_count))
-+              goto repeat;
-+}
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName);
+ }
  
- static void sysfs_d_iput(struct dentry * dentry, struct inode * inode)
+ static ssize_t
+ lpfc_programtype_show(struct class_device *cdev, char *buf)
  {
-       struct sysfs_dirent * sd = dentry->d_fsdata;
-       if (sd) {
--              /* sd->s_dentry is protected with sysfs_lock.  This
--               * allows sysfs_drop_dentry() to dereference it.
-+              /* sd->s_dentry is protected with sysfs_assoc_lock.
-+               * This allows sysfs_drop_dentry() to dereference it.
-                */
--              spin_lock(&sysfs_lock);
-+              spin_lock(&sysfs_assoc_lock);
-               /* The dentry might have been deleted or another
-                * lookup could have happened updating sd->s_dentry to
-@@ -32,7 +453,7 @@
-                */
-               if (sd->s_dentry == dentry)
-                       sd->s_dentry = NULL;
--              spin_unlock(&sysfs_lock);
-+              spin_unlock(&sysfs_assoc_lock);
-               sysfs_put(sd);
-       }
-       iput(inode);
-@@ -42,344 +463,594 @@
-       .d_iput         = sysfs_d_iput,
- };
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType);
+ }
  
--static unsigned int sysfs_inode_counter;
--ino_t sysfs_get_inum(void)
-+struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
+ static ssize_t
+-lpfc_vportnum_show(struct class_device *cdev, char *buf)
++lpfc_portnum_show(struct class_device *cdev, char *buf)
  {
--      if (unlikely(sysfs_inode_counter < 3))
--              sysfs_inode_counter = 3;
--      return sysfs_inode_counter++;
--}
-+      char *dup_name = NULL;
-+      struct sysfs_dirent *sd = NULL;
--/*
-- * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent
-- */
--static struct sysfs_dirent * __sysfs_new_dirent(void * element)
--{
--      struct sysfs_dirent * sd;
-+      if (type & SYSFS_COPY_NAME) {
-+              name = dup_name = kstrdup(name, GFP_KERNEL);
-+              if (!name)
-+                      goto err_out;
-+      }
-       sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
-       if (!sd)
--              return NULL;
-+              goto err_out;
-+
-+      if (sysfs_alloc_ino(&sd->s_ino))
-+              goto err_out;
--      sd->s_ino = sysfs_get_inum();
-       atomic_set(&sd->s_count, 1);
-+      atomic_set(&sd->s_active, 0);
-       atomic_set(&sd->s_event, 1);
--      INIT_LIST_HEAD(&sd->s_children);
--      INIT_LIST_HEAD(&sd->s_sibling);
--      sd->s_element = element;
-+
-+      sd->s_name = name;
-+      sd->s_mode = mode;
-+      sd->s_flags = type;
-       return sd;
-+
-+ err_out:
-+      kfree(dup_name);
-+      kmem_cache_free(sysfs_dir_cachep, sd);
-+      return NULL;
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port);
  }
  
--static void __sysfs_list_dirent(struct sysfs_dirent *parent_sd,
--                            struct sysfs_dirent *sd)
-+/**
-+ *    sysfs_attach_dentry - associate sysfs_dirent with dentry
-+ *    @sd: target sysfs_dirent
-+ *    @dentry: dentry to associate
-+ *
-+ *    Associate @sd with @dentry.  This is protected by
-+ *    sysfs_assoc_lock to avoid race with sysfs_d_iput().
-+ *
-+ *    LOCKING:
-+ *    mutex_lock(sysfs_mutex)
-+ */
-+static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry)
+ static ssize_t
+ lpfc_fwrev_show(struct class_device *cdev, char *buf)
  {
--      if (sd)
--              list_add(&sd->s_sibling, &parent_sd->s_children);
-+      dentry->d_op = &sysfs_dentry_ops;
-+      dentry->d_fsdata = sysfs_get(sd);
-+
-+      /* protect sd->s_dentry against sysfs_d_iput */
-+      spin_lock(&sysfs_assoc_lock);
-+      sd->s_dentry = dentry;
-+      spin_unlock(&sysfs_assoc_lock);
-+
-+      if (dentry->d_flags & DCACHE_UNHASHED)
-+      d_rehash(dentry);
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       char fwrev[32];
+-
+       lpfc_decode_firmware_rev(phba, fwrev, 1);
+-      return snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", fwrev, phba->sli_rev);
++      return snprintf(buf, PAGE_SIZE, "%s\n",fwrev);
  }
  
--static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent *parent_sd,
--                                              void * element)
-+static int sysfs_ilookup_test(struct inode *inode, void *arg)
+ static ssize_t
+ lpfc_hdw_show(struct class_device *cdev, char *buf)
  {
--      struct sysfs_dirent *sd;
--      sd = __sysfs_new_dirent(element);
--      __sysfs_list_dirent(parent_sd, sd);
--      return sd;
-+      struct sysfs_dirent *sd = arg;
-+      return inode->i_ino == sd->s_ino;
+       char hdw[9];
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       lpfc_vpd_t *vp = &phba->vpd;
+-
+       lpfc_jedec_to_ascii(vp->rev.biuRev, hdw);
+       return snprintf(buf, PAGE_SIZE, "%s\n", hdw);
  }
--/*
-+/**
-+ *    sysfs_addrm_start - prepare for sysfs_dirent add/remove
-+ *    @acxt: pointer to sysfs_addrm_cxt to be used
-+ *    @parent_sd: parent sysfs_dirent
-  *
-- * Return -EEXIST if there is already a sysfs element with the same name for
-- * the same parent.
-+ *    This function is called when the caller is about to add or
-+ *    remove sysfs_dirent under @parent_sd.  This function acquires
-+ *    sysfs_mutex, grabs inode for @parent_sd if available and lock
-+ *    i_mutex of it.  @acxt is used to keep and pass context to
-+ *    other addrm functions.
-  *
-- * called with parent inode's i_mutex held
-+ *    LOCKING:
-+ *    Kernel thread context (may sleep).  sysfs_mutex is locked on
-+ *    return.  i_mutex of parent inode is locked on return if
-+ *    available.
-  */
--int sysfs_dirent_exist(struct sysfs_dirent *parent_sd,
--                        const unsigned char *new)
-+void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
-+                     struct sysfs_dirent *parent_sd)
+ static ssize_t
+ lpfc_option_rom_version_show(struct class_device *cdev, char *buf)
  {
--      struct sysfs_dirent * sd;
-+      struct inode *inode;
--      list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
--              if (sd->s_element) {
--                      const unsigned char *existing = sysfs_get_name(sd);
--                      if (strcmp(existing, new))
--                              continue;
--                      else
--                              return -EEXIST;
--              }
-+      memset(acxt, 0, sizeof(*acxt));
-+      acxt->parent_sd = parent_sd;
-+
-+      /* Lookup parent inode.  inode initialization and I_NEW
-+       * clearing are protected by sysfs_mutex.  By grabbing it and
-+       * looking up with _nowait variant, inode state can be
-+       * determined reliably.
-+       */
-+      mutex_lock(&sysfs_mutex);
-+
-+      inode = ilookup5_nowait(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
-+                              parent_sd);
-+
-+      if (inode && !(inode->i_state & I_NEW)) {
-+              /* parent inode available */
-+              acxt->parent_inode = inode;
-+
-+              /* sysfs_mutex is below i_mutex in lock hierarchy.
-+               * First, trylock i_mutex.  If fails, unlock
-+               * sysfs_mutex and lock them in order.
-+               */
-+              if (!mutex_trylock(&inode->i_mutex)) {
-+                      mutex_unlock(&sysfs_mutex);
-+                      mutex_lock(&inode->i_mutex);
-+                      mutex_lock(&sysfs_mutex);
-       }
-+      } else
-+              iput(inode);
-+}
--      return 0;
-+/**
-+ *    sysfs_add_one - add sysfs_dirent to parent
-+ *    @acxt: addrm context to use
-+ *    @sd: sysfs_dirent to be added
-+ *
-+ *    Get @acxt->parent_sd and set sd->s_parent to it and increment
-+ *    nlink of parent inode if @sd is a directory.  @sd is NOT
-+ *    linked into the children list of the parent.  The caller
-+ *    should invoke sysfs_link_sibling() after this function
-+ *    completes if @sd needs to be on the children list.
-+ *
-+ *    This function should be called between calls to
-+ *    sysfs_addrm_start() and sysfs_addrm_finish() and should be
-+ *    passed the same @acxt as passed to sysfs_addrm_start().
-+ *
-+ *    LOCKING:
-+ *    Determined by sysfs_addrm_start().
-+ */
-+void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
-+{
-+      sd->s_parent = sysfs_get(acxt->parent_sd);
-+
-+      if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
-+              inc_nlink(acxt->parent_inode);
-+
-+      acxt->cnt++;
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
  }
-+/**
-+ *    sysfs_remove_one - remove sysfs_dirent from parent
-+ *    @acxt: addrm context to use
-+ *    @sd: sysfs_dirent to be added
-+ *
-+ *    Mark @sd removed and drop nlink of parent inode if @sd is a
-+ *    directory.  @sd is NOT unlinked from the children list of the
-+ *    parent.  The caller is repsonsible for removing @sd from the
-+ *    children list before calling this function.
-+ *
-+ *    This function should be called between calls to
-+ *    sysfs_addrm_start() and sysfs_addrm_finish() and should be
-+ *    passed the same @acxt as passed to sysfs_addrm_start().
-+ *
-+ *    LOCKING:
-+ *    Determined by sysfs_addrm_start().
-+ */
-+void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
-+{
-+      BUG_ON(sd->s_sibling || (sd->s_flags & SYSFS_FLAG_REMOVED));
-+
-+      sd->s_flags |= SYSFS_FLAG_REMOVED;
-+      sd->s_sibling = acxt->removed;
-+      acxt->removed = sd;
-+
-+      if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
-+              drop_nlink(acxt->parent_inode);
-+
-+      acxt->cnt++;
-+}
--static struct sysfs_dirent *
--__sysfs_make_dirent(struct dentry *dentry, void *element, mode_t mode, int type)
-+/**
-+ *    sysfs_drop_dentry - drop dentry for the specified sysfs_dirent
-+ *    @sd: target sysfs_dirent
-+ *
-+ *    Drop dentry for @sd.  @sd must have been unlinked from its
-+ *    parent on entry to this function such that it can't be looked
-+ *    up anymore.
-+ *
-+ *    @sd->s_dentry which is protected with sysfs_assoc_lock points
-+ *    to the currently associated dentry but we're not holding a
-+ *    reference to it and racing with dput().  Grab dcache_lock and
-+ *    verify dentry before dropping it.  If @sd->s_dentry is NULL or
-+ *    dput() beats us, no need to bother.
-+ */
-+static void sysfs_drop_dentry(struct sysfs_dirent *sd)
+ static ssize_t
+ lpfc_state_show(struct class_device *cdev, char *buf)
  {
--      struct sysfs_dirent * sd;
-+      struct dentry *dentry = NULL;
-+      struct inode *inode;
--      sd = __sysfs_new_dirent(element);
--      if (!sd)
--              goto out;
-+      /* We're not holding a reference to ->s_dentry dentry but the
-+       * field will stay valid as long as sysfs_assoc_lock is held.
-+       */
-+      spin_lock(&sysfs_assoc_lock);
-+      spin_lock(&dcache_lock);
--      sd->s_mode = mode;
--      sd->s_type = type;
--      sd->s_dentry = dentry;
--      if (dentry) {
--              dentry->d_fsdata = sysfs_get(sd);
--              dentry->d_op = &sysfs_dentry_ops;
--      }
-+      /* drop dentry if it's there and dput() didn't kill it yet */
-+      if (sd->s_dentry && sd->s_dentry->d_inode) {
-+              dentry = dget_locked(sd->s_dentry);
-+              spin_lock(&dentry->d_lock);
-+              __d_drop(dentry);
-+              spin_unlock(&dentry->d_lock);
-+      }
-+
-+      spin_unlock(&dcache_lock);
-+      spin_unlock(&sysfs_assoc_lock);
-+
-+      /* dentries for shadowed directories are pinned, unpin */
-+      if ((sysfs_type(sd) == SYSFS_SHADOW_DIR) ||
-+          (sd->s_flags & SYSFS_FLAG_SHADOWED))
-+              dput(dentry);
-+      dput(dentry);
--out:
--      return sd;
-+      /* adjust nlink and update timestamp */
-+      inode = ilookup(sysfs_sb, sd->s_ino);
-+      if (inode) {
-+              mutex_lock(&inode->i_mutex);
-+
-+              inode->i_ctime = CURRENT_TIME;
-+              drop_nlink(inode);
-+              if (sysfs_type(sd) == SYSFS_DIR)
-+                      drop_nlink(inode);
-+
-+              mutex_unlock(&inode->i_mutex);
-+              iput(inode);
-+      }
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       int len = 0;
+-
+-      switch (phba->link_state) {
+-      case LPFC_LINK_UNKNOWN:
++      switch (phba->hba_state) {
++      case LPFC_STATE_UNKNOWN:
+       case LPFC_WARM_START:
+       case LPFC_INIT_START:
+       case LPFC_INIT_MBX_CMDS:
+       case LPFC_LINK_DOWN:
+-      case LPFC_HBA_ERROR:
+               len += snprintf(buf + len, PAGE_SIZE-len, "Link Down\n");
+               break;
+       case LPFC_LINK_UP:
+-      case LPFC_CLEAR_LA:
+-      case LPFC_HBA_READY:
+-              len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - \n");
+-
+-              switch (vport->port_state) {
+-                      len += snprintf(buf + len, PAGE_SIZE-len,
+-                                      "initializing\n");
+-                      break;
+       case LPFC_LOCAL_CFG_LINK:
+-                      len += snprintf(buf + len, PAGE_SIZE-len,
+-                                      "Configuring Link\n");
++              len += snprintf(buf + len, PAGE_SIZE-len, "Link Up\n");
+               break;
+-              case LPFC_FDISC:
+       case LPFC_FLOGI:
+       case LPFC_FABRIC_CFG_LINK:
+       case LPFC_NS_REG:
+       case LPFC_NS_QRY:
+       case LPFC_BUILD_DISC_LIST:
+       case LPFC_DISC_AUTH:
+-                      len += snprintf(buf + len, PAGE_SIZE - len,
+-                                      "Discovery\n");
+-              break;
+-              case LPFC_VPORT_READY:
+-                      len += snprintf(buf + len, PAGE_SIZE - len, "Ready\n");
+-                      break;
+-
+-              case LPFC_VPORT_FAILED:
+-                      len += snprintf(buf + len, PAGE_SIZE - len, "Failed\n");
+-                      break;
+-
+-              case LPFC_VPORT_UNKNOWN:
+-                      len += snprintf(buf + len, PAGE_SIZE - len,
+-                                      "Unknown\n");
++      case LPFC_CLEAR_LA:
++              len += snprintf(buf + len, PAGE_SIZE-len,
++                              "Link Up - Discovery\n");
+                       break;
+-              }
+-
++      case LPFC_HBA_READY:
++              len += snprintf(buf + len, PAGE_SIZE-len,
++                              "Link Up - Ready:\n");
+               if (phba->fc_topology == TOPOLOGY_LOOP) {
+-                      if (vport->fc_flag & FC_PUBLIC_LOOP)
++                      if (phba->fc_flag & FC_PUBLIC_LOOP)
+                               len += snprintf(buf + len, PAGE_SIZE-len,
+                                               "   Public Loop\n");
+                       else
+                               len += snprintf(buf + len, PAGE_SIZE-len,
+                                               "   Private Loop\n");
+               } else {
+-                      if (vport->fc_flag & FC_FABRIC)
++                      if (phba->fc_flag & FC_FABRIC)
+                               len += snprintf(buf + len, PAGE_SIZE-len,
+                                               "   Fabric\n");
+                       else
+@@ -234,32 +193,29 @@
+                                               "   Point-2-Point\n");
+               }
+       }
+-
+       return len;
  }
  
--int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
--                      void * element, umode_t mode, int type)
-+/**
-+ *    sysfs_drop_dentry - drop dentry for the specified sysfs_dirent
-+ *    @sd: target sysfs_dirent
-+ *
-+ *    Drop dentry for @sd.  @sd must have been unlinked from its
-+ *    parent on entry to this function such that it can't be looked
-+ *    up anymore.
-+ *
-+ *    @sd->s_dentry which is protected with sysfs_assoc_lock points
-+ *    to the currently associated dentry but we're not holding a
-+ *    reference to it and racing with dput().  Grab dcache_lock and
-+ *    verify dentry before dropping it.  If @sd->s_dentry is NULL or
-+ *    dput() beats us, no need to bother.
-+ */
-+
-+
-+/**
-+ *    sysfs_addrm_finish - finish up sysfs_dirent add/remove
-+ *    @acxt: addrm context to finish up
-+ *
-+ *    Finish up sysfs_dirent add/remove.  Resources acquired by
-+ *    sysfs_addrm_start() are released and removed sysfs_dirents are
-+ *    cleaned up.  Timestamps on the parent inode are updated.
-+ *
-+ *    LOCKING:
-+ *    All mutexes acquired by sysfs_addrm_start() are released.
-+ *
-+ *    RETURNS:
-+ *    Number of added/removed sysfs_dirents since sysfs_addrm_start().
-+ */
-+int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
+ static ssize_t
+ lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
  {
--      struct sysfs_dirent *sd;
-+      /* release resources acquired by sysfs_addrm_start() */
-+      mutex_unlock(&sysfs_mutex);
-+      if (acxt->parent_inode) {
-+              struct inode *inode = acxt->parent_inode;
-+
-+              /* if added/removed, update timestamps on the parent */
-+              if (acxt->cnt)
-+                      inode->i_ctime = inode->i_mtime = CURRENT_TIME;
--      sd = __sysfs_make_dirent(dentry, element, mode, type);
--      __sysfs_list_dirent(parent_sd, sd);
-+              mutex_unlock(&inode->i_mutex);
-+              iput(inode);
-+      }
--      return sd ? 0 : -ENOMEM;
-+      /* kill removed sysfs_dirents */
-+      while (acxt->removed) {
-+              struct sysfs_dirent *sd = acxt->removed;
-+
-+              acxt->removed = sd->s_sibling;
-+              sd->s_sibling = NULL;
-+
-+              sysfs_prune_shadow_sd(sd->s_parent);
-+              sysfs_drop_dentry(sd);
-+              sysfs_deactivate(sd);
-+              sysfs_put(sd);
-+      }
-+
-+      return acxt->cnt;
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-
+-      return snprintf(buf, PAGE_SIZE, "%d\n",
+-                      vport->fc_map_cnt + vport->fc_unmap_cnt);
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
++      return snprintf(buf, PAGE_SIZE, "%d\n", phba->fc_map_cnt +
++                                                      phba->fc_unmap_cnt);
  }
  
--static int init_dir(struct inode * inode)
-+/**
-+ *    sysfs_find_dirent - find sysfs_dirent with the given name
-+ *    @parent_sd: sysfs_dirent to search under
-+ *    @name: name to look for
-+ *
-+ *    Look for sysfs_dirent with name @name under @parent_sd.
-+ *
-+ *    LOCKING:
-+ *    mutex_lock(sysfs_mutex)
-+ *
-+ *    RETURNS:
-+ *    Pointer to sysfs_dirent if found, NULL if not.
-+ */
-+struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
-+                                     const unsigned char *name)
- {
--      inode->i_op = &sysfs_dir_inode_operations;
--      inode->i_fop = &sysfs_dir_operations;
-+      struct sysfs_dirent *sd;
--      /* directory inodes start off with i_nlink == 2 (for "." entry) */
--      inc_nlink(inode);
--      return 0;
-+      for (sd = parent_sd->s_children; sd; sd = sd->s_sibling)
-+              if (sysfs_type(sd) && !strcmp(sd->s_name, name))
-+                      return sd;
-+      return NULL;
- }
  
--static int init_file(struct inode * inode)
-+/**
-+ *    sysfs_get_dirent - find and get sysfs_dirent with the given name
-+ *    @parent_sd: sysfs_dirent to search under
-+ *    @name: name to look for
-+ *
-+ *    Look for sysfs_dirent with name @name under @parent_sd and get
-+ *    it if found.
-+ *
-+ *    LOCKING:
-+ *    Kernel thread context (may sleep).  Grabs sysfs_mutex.
-+ *
-+ *    RETURNS:
-+ *    Pointer to sysfs_dirent if found, NULL if not.
-+ */
-+struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
-+                                    const unsigned char *name)
+ static int
+-lpfc_issue_lip(struct Scsi_Host *shost)
++lpfc_issue_lip(struct Scsi_Host *host)
  {
--      inode->i_size = PAGE_SIZE;
--      inode->i_fop = &sysfs_file_operations;
--      return 0;
--}
-+      struct sysfs_dirent *sd;
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata;
+       LPFC_MBOXQ_t *pmboxq;
+       int mbxstatus = MBXERR_ERROR;
  
--static int init_symlink(struct inode * inode)
--{
--      inode->i_op = &sysfs_symlink_inode_operations;
--      return 0;
-+      mutex_lock(&sysfs_mutex);
-+      sd = sysfs_find_dirent(parent_sd, name);
-+      sysfs_get(sd);
-+      mutex_unlock(&sysfs_mutex);
-+
-+      return sd;
- }
+-      if ((vport->fc_flag & FC_OFFLINE_MODE) ||
+-          (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) ||
+-          (vport->port_state != LPFC_VPORT_READY))
++      if ((phba->fc_flag & FC_OFFLINE_MODE) ||
++          (phba->fc_flag & FC_BLOCK_MGMT_IO) ||
++          (phba->hba_state != LPFC_HBA_READY))
+               return -EPERM;
  
--static int create_dir(struct kobject * k, struct dentry * p,
--                    const char * n, struct dentry ** d)
-+static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
-+                    const char *name, struct sysfs_dirent **p_sd)
- {
--      int error;
-       umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
-+      struct sysfs_addrm_cxt acxt;
-+      struct sysfs_dirent *sd;
-+      int err;
+       pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
+@@ -282,7 +238,9 @@
+       }
  
--      mutex_lock(&p->d_inode->i_mutex);
--      *d = lookup_one_len(n, p, strlen(n));
--      if (!IS_ERR(*d)) {
--              if (sysfs_dirent_exist(p->d_fsdata, n))
--                      error = -EEXIST;
--              else
--                      error = sysfs_make_dirent(p->d_fsdata, *d, k, mode,
--                                                              SYSFS_DIR);
--              if (!error) {
--                      error = sysfs_create(*d, mode, init_dir);
--                      if (!error) {
--                              inc_nlink(p->d_inode);
--                              (*d)->d_op = &sysfs_dentry_ops;
--                              d_rehash(*d);
--                      }
-+      /* allocate */
-+      sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
-+      if (!sd)
-+              return -ENOMEM;
-+      sd->s_elem.dir.kobj = kobj;
-+
-+      /* link in */
-+      sysfs_addrm_start(&acxt, parent_sd);
-+      err = -ENOENT;
-+      if (!sysfs_resolve_for_create(kobj, &acxt.parent_sd))
-+              goto addrm_finish;
-+
-+      err = -EEXIST;
-+      if (!sysfs_find_dirent(acxt.parent_sd, name)) {
-+              sysfs_add_one(&acxt, sd);
-+              sysfs_link_sibling(sd);
-+              err = 0;
-+                      }
-+addrm_finish:
-+      if (sysfs_addrm_finish(&acxt)) {
-+              *p_sd = sd;
-+              return 0;
-               }
--              if (error && (error != -EEXIST)) {
--                      struct sysfs_dirent *sd = (*d)->d_fsdata;
--                      if (sd) {
--                              list_del_init(&sd->s_sibling);
-+
-                               sysfs_put(sd);
--                      }
--                      d_drop(*d);
--              }
--              dput(*d);
--      } else
--              error = PTR_ERR(*d);
--      mutex_unlock(&p->d_inode->i_mutex);
--      return error;
-+      return err;
- }
+       lpfc_set_loopback_flag(phba);
+-      if (mbxstatus != MBX_TIMEOUT)
++      if (mbxstatus == MBX_TIMEOUT)
++              pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
++      else
+               mempool_free(pmboxq, phba->mbox_mem_pool);
  
+       if (mbxstatus == MBXERR_ERROR)
+@@ -362,10 +320,8 @@
+ static ssize_t
+ lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
+ {
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
 -
--int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d)
-+int sysfs_create_subdir(struct kobject *kobj, const char *name,
-+                      struct sysfs_dirent **p_sd)
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       int status = -EINVAL;
+       if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
+@@ -380,26 +336,23 @@
+ static ssize_t
+ lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
  {
--      return create_dir(k,k->dentry,n,d);
-+      return create_dir(kobj, kobj->sd, name, p_sd);
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
  }
  
- /**
-  *    sysfs_create_dir - create a directory for an object.
-  *    @kobj:          object we're creating directory for. 
-- *    @shadow_parent: parent parent object.
-  */
--
--int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent)
-+int sysfs_create_dir(struct kobject * kobj)
+ static ssize_t
+ lpfc_board_mode_show(struct class_device *cdev, char *buf)
  {
--      struct dentry * dentry = NULL;
--      struct dentry * parent;
-+      struct sysfs_dirent *parent_sd, *sd;
-       int error = 0;
-       BUG_ON(!kobj);
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       char  * state;
  
--      if (shadow_parent)
--              parent = shadow_parent;
--      else if (kobj->parent)
--              parent = kobj->parent->dentry;
-+      if (kobj->parent)
-+              parent_sd = kobj->parent->sd;
-       else if (sysfs_mount && sysfs_mount->mnt_sb)
--              parent = sysfs_mount->mnt_sb->s_root;
-+              parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
+-      if (phba->link_state == LPFC_HBA_ERROR)
++      if (phba->hba_state == LPFC_HBA_ERROR)
+               state = "error";
+-      else if (phba->link_state == LPFC_WARM_START)
++      else if (phba->hba_state == LPFC_WARM_START)
+               state = "warm start";
+-      else if (phba->link_state == LPFC_INIT_START)
++      else if (phba->hba_state == LPFC_INIT_START)
+               state = "offline";
        else
-               return -EFAULT;
+               state = "online";
+@@ -410,9 +363,8 @@
+ static ssize_t
+ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
+ {
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct completion online_compl;
+       int status=0;
  
--      error = create_dir(kobj,parent,kobject_name(kobj),&dentry);
-+      error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd);
-       if (!error)
--              kobj->dentry = dentry;
-+              kobj->sd = sd;
-       return error;
+@@ -437,166 +389,11 @@
+               return -EIO;
  }
  
--/* attaches attribute's sysfs_dirent to the dentry corresponding to the
-- * attribute file
-- */
--static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
-+static int sysfs_count_nlink(struct sysfs_dirent *sd)
- {
--      struct attribute * attr = NULL;
--      struct bin_attribute * bin_attr = NULL;
--      int (* init) (struct inode *) = NULL;
--      int error = 0;
-+      struct sysfs_dirent *child;
-+      int nr = 0;
--        if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) {
--                bin_attr = sd->s_element;
--                attr = &bin_attr->attr;
--        } else {
--                attr = sd->s_element;
--                init = init_file;
--        }
-+      for (child = sd->s_children; child; child = child->s_sibling)
-+              if (sysfs_type(child) == SYSFS_DIR)
-+                      nr++;
-+      return nr + 2;
-+}
--      dentry->d_fsdata = sysfs_get(sd);
--      /* protect sd->s_dentry against sysfs_d_iput */
--      spin_lock(&sysfs_lock);
--      sd->s_dentry = dentry;
--      spin_unlock(&sysfs_lock);
--      error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init);
--      if (error) {
--              sysfs_put(sd);
--              return error;
+-int
+-lpfc_get_hba_info(struct lpfc_hba *phba,
+-                uint32_t *mxri, uint32_t *axri,
+-                uint32_t *mrpi, uint32_t *arpi,
+-                uint32_t *mvpi, uint32_t *avpi)
+-{
+-      struct lpfc_sli   *psli = &phba->sli;
+-      LPFC_MBOXQ_t *pmboxq;
+-      MAILBOX_t *pmb;
+-      int rc = 0;
+-
+-      /*
+-       * prevent udev from issuing mailbox commands until the port is
+-       * configured.
+-       */
+-      if (phba->link_state < LPFC_LINK_DOWN ||
+-          !phba->mbox_mem_pool ||
+-          (phba->sli.sli_flag & LPFC_SLI2_ACTIVE) == 0)
+-              return 0;
+-
+-      if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
+-              return 0;
+-
+-      pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (!pmboxq)
+-              return 0;
+-      memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
+-
+-      pmb = &pmboxq->mb;
+-      pmb->mbxCommand = MBX_READ_CONFIG;
+-      pmb->mbxOwner = OWN_HOST;
+-      pmboxq->context1 = NULL;
+-
+-      if ((phba->pport->fc_flag & FC_OFFLINE_MODE) ||
+-              (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
+-              rc = MBX_NOT_FINISHED;
+-      else
+-              rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+-
+-      if (rc != MBX_SUCCESS) {
+-              if (rc != MBX_TIMEOUT)
+-                      mempool_free(pmboxq, phba->mbox_mem_pool);
+-              return 0;
 -      }
-+static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
-+                              struct nameidata *nd)
-+{
-+      struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
-+      struct sysfs_dirent * sd;
-+      struct bin_attribute *bin_attr;
-+      struct inode *inode;
-+      int found = 0;
--        if (bin_attr) {
--              dentry->d_inode->i_size = bin_attr->size;
--              dentry->d_inode->i_fop = &bin_fops;
-+      for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) {
-+              if (sysfs_type(sd) &&
-+                  !strcmp(sd->s_name, dentry->d_name.name)) {
-+                      found = 1;
-+                      break;
-+              }
-       }
--      dentry->d_op = &sysfs_dentry_ops;
--      d_rehash(dentry);
--      return 0;
+-
+-      if (mrpi)
+-              *mrpi = pmb->un.varRdConfig.max_rpi;
+-      if (arpi)
+-              *arpi = pmb->un.varRdConfig.avail_rpi;
+-      if (mxri)
+-              *mxri = pmb->un.varRdConfig.max_xri;
+-      if (axri)
+-              *axri = pmb->un.varRdConfig.avail_xri;
+-      if (mvpi)
+-              *mvpi = pmb->un.varRdConfig.max_vpi;
+-      if (avpi)
+-              *avpi = pmb->un.varRdConfig.avail_vpi;
+-
+-      mempool_free(pmboxq, phba->mbox_mem_pool);
+-      return 1;
 -}
-+      /* no such entry */
-+      if (!found)
-+              return NULL;
--static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
+-
+-static ssize_t
+-lpfc_max_rpi_show(struct class_device *cdev, char *buf)
 -{
--      int err = 0;
-+      /* attach dentry and inode */
-+      inode = sysfs_get_inode(sd);
-+      if (!inode)
-+              return ERR_PTR(-ENOMEM);
-+
-+      mutex_lock(&sysfs_mutex);
-+
-+      if (inode->i_state & I_NEW) {
-+              /* initialize inode according to type */
-+              switch (sysfs_type(sd)) {
-+              case SYSFS_DIR:
-+                      inode->i_op = &sysfs_dir_inode_operations;
-+                      inode->i_fop = &sysfs_dir_operations;
-+                      inode->i_nlink = sysfs_count_nlink(sd);
-+                      break;
-+              case SYSFS_KOBJ_ATTR:
-+                      inode->i_size = PAGE_SIZE;
-+                      inode->i_fop = &sysfs_file_operations;
-+                      break;
-+              case SYSFS_KOBJ_BIN_ATTR:
-+                      bin_attr = sd->s_elem.bin_attr.bin_attr;
-+                      inode->i_size = bin_attr->size;
-+                      inode->i_fop = &bin_fops;
-+                      break;
-+              case SYSFS_KOBJ_LINK:
-+                      inode->i_op = &sysfs_symlink_inode_operations;
-+                      break;
-+              default:
-+                      BUG();
-+              }
-+      }
--      dentry->d_fsdata = sysfs_get(sd);
--      /* protect sd->s_dentry against sysfs_d_iput */
--      spin_lock(&sysfs_lock);
--      sd->s_dentry = dentry;
--      spin_unlock(&sysfs_lock);
--      err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
--      if (!err) {
--              dentry->d_op = &sysfs_dentry_ops;
--              d_rehash(dentry);
--      } else
--              sysfs_put(sd);
-+      sysfs_instantiate(dentry, inode);
-+      sysfs_attach_dentry(sd, dentry);
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-      uint32_t cnt;
+-
+-      if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL, NULL, NULL))
+-              return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
+-      return snprintf(buf, PAGE_SIZE, "Unknown\n");
+-}
+-
+-static ssize_t
+-lpfc_used_rpi_show(struct class_device *cdev, char *buf)
+-{
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-      uint32_t cnt, acnt;
+-
+-      if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt, NULL, NULL))
+-              return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
+-      return snprintf(buf, PAGE_SIZE, "Unknown\n");
+-}
+-
+-static ssize_t
+-lpfc_max_xri_show(struct class_device *cdev, char *buf)
+-{
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-      uint32_t cnt;
+-
+-      if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL, NULL, NULL))
+-              return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
+-      return snprintf(buf, PAGE_SIZE, "Unknown\n");
+-}
+-
+-static ssize_t
+-lpfc_used_xri_show(struct class_device *cdev, char *buf)
+-{
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-      uint32_t cnt, acnt;
+-
+-      if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL, NULL, NULL))
+-              return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
+-      return snprintf(buf, PAGE_SIZE, "Unknown\n");
+-}
+-
+-static ssize_t
+-lpfc_max_vpi_show(struct class_device *cdev, char *buf)
+-{
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-      uint32_t cnt;
+-
+-      if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, NULL))
+-              return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
+-      return snprintf(buf, PAGE_SIZE, "Unknown\n");
+-}
+-
+-static ssize_t
+-lpfc_used_vpi_show(struct class_device *cdev, char *buf)
+-{
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-      uint32_t cnt, acnt;
+-
+-      if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, &acnt))
+-              return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
+-      return snprintf(buf, PAGE_SIZE, "Unknown\n");
+-}
+-
+-static ssize_t
+-lpfc_npiv_info_show(struct class_device *cdev, char *buf)
+-{
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-
+-      if (!(phba->max_vpi))
+-              return snprintf(buf, PAGE_SIZE, "NPIV Not Supported\n");
+-      if (vport->port_type == LPFC_PHYSICAL_PORT)
+-              return snprintf(buf, PAGE_SIZE, "NPIV Physical\n");
+-      return snprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi);
+-}
+-
+ static ssize_t
+ lpfc_poll_show(struct class_device *cdev, char *buf)
+ {
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
  
--      return err;
-+      mutex_unlock(&sysfs_mutex);
-+
-+      return NULL;
+       return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
  }
--static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
--                              struct nameidata *nd)
-+static void *sysfs_shadow_follow_link(struct dentry *dentry, struct nameidata *nd)
+@@ -605,9 +402,8 @@
+ lpfc_poll_store(struct class_device *cdev, const char *buf,
+               size_t count)
  {
--      struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
--      struct sysfs_dirent * sd;
--      int err = 0;
-+      struct sysfs_dirent *sd;
-+      struct dentry *dest;
--      list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
--              if (sd->s_type & SYSFS_NOT_PINNED) {
--                      const unsigned char * name = sysfs_get_name(sd);
-+      sd = dentry->d_fsdata;
-+      dest = NULL;
-+      if (sd->s_flags & SYSFS_FLAG_SHADOWED) {
-+              const struct shadow_dir_operations *shadow_ops;
-+              const void *tag;
--                      if (strcmp(name, dentry->d_name.name))
--                              continue;
-+              mutex_lock(&sysfs_mutex);
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       uint32_t creg_val;
+       uint32_t old_val;
+       int val=0;
+@@ -621,7 +417,7 @@
+       if ((val & 0x3) != val)
+               return -EINVAL;
  
--                      if (sd->s_type & SYSFS_KOBJ_LINK)
--                              err = sysfs_attach_link(sd, dentry);
--                      else
--                              err = sysfs_attach_attr(sd, dentry);
--                      break;
--              }
-+              shadow_ops = dentry->d_inode->i_private;
-+              tag = shadow_ops->current_tag();
-+
-+              sd = find_shadow_sd(sd, tag);
-+              if (sd)
-+                      dest = sd->s_dentry;
-+              dget(dest);
-+
-+              mutex_unlock(&sysfs_mutex);
-       }
-+      if (!dest)
-+              dest = dget(dentry);
-+      dput(nd->dentry);
-+      nd->dentry = dest;
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
  
--      return ERR_PTR(err);
-+      return NULL;
- }
+       old_val = phba->cfg_poll;
  
-+
- const struct inode_operations sysfs_dir_inode_operations = {
-       .lookup         = sysfs_lookup,
-       .setattr        = sysfs_setattr,
-+      .follow_link    = sysfs_shadow_follow_link,
- };
+@@ -636,16 +432,16 @@
+                       lpfc_poll_start_timer(phba);
+               }
+       } else if (val != 0x0) {
+-              spin_unlock_irq(&phba->hbalock);
++              spin_unlock_irq(phba->host->host_lock);
+               return -EINVAL;
+       }
  
--static void remove_dir(struct dentry * d)
-+static void __remove_dir(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
- {
--      struct dentry * parent = dget(d->d_parent);
--      struct sysfs_dirent * sd;
-+      sysfs_unlink_sibling(sd);
-+      sysfs_remove_one(acxt, sd);
-+}
+       if (!(val & DISABLE_FCP_RING_INT) &&
+           (old_val & DISABLE_FCP_RING_INT))
+       {
+-              spin_unlock_irq(&phba->hbalock);
++              spin_unlock_irq(phba->host->host_lock);
+               del_timer(&phba->fcp_poll_timer);
+-              spin_lock_irq(&phba->hbalock);
++              spin_lock_irq(phba->host->host_lock);
+               creg_val = readl(phba->HCregaddr);
+               creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
+               writel(creg_val, phba->HCregaddr);
+@@ -654,7 +450,7 @@
  
--      mutex_lock(&parent->d_inode->i_mutex);
--      d_delete(d);
--      sd = d->d_fsdata;
--      list_del_init(&sd->s_sibling);
--      sysfs_put(sd);
--      if (d->d_inode)
--              simple_rmdir(parent->d_inode,d);
-+static void remove_dir(struct sysfs_dirent *sd)
-+{
-+      struct sysfs_addrm_cxt acxt;
+       phba->cfg_poll = val;
  
--      pr_debug(" o %s removing done (%d)\n",d->d_name.name,
--               atomic_read(&d->d_count));
-+      sysfs_addrm_start(&acxt, sd->s_parent);
-+      __remove_dir(&acxt, sd);
-+      sysfs_addrm_finish(&acxt);
-+}
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
  
--      mutex_unlock(&parent->d_inode->i_mutex);
--      dput(parent);
-+void sysfs_remove_subdir(struct sysfs_dirent *sd)
-+{
-+      remove_dir(sd);
+       return strlen(buf);
  }
+@@ -663,9 +459,8 @@
+ static ssize_t \
+ lpfc_##attr##_show(struct class_device *cdev, char *buf) \
+ { \
+-      struct Scsi_Host  *shost = class_to_shost(cdev);\
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+-      struct lpfc_hba   *phba = vport->phba;\
++      struct Scsi_Host *host = class_to_shost(cdev);\
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
+       int val = 0;\
+       val = phba->cfg_##attr;\
+       return snprintf(buf, PAGE_SIZE, "%d\n",\
+@@ -676,9 +471,8 @@
+ static ssize_t \
+ lpfc_##attr##_show(struct class_device *cdev, char *buf) \
+ { \
+-      struct Scsi_Host  *shost = class_to_shost(cdev);\
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+-      struct lpfc_hba   *phba = vport->phba;\
++      struct Scsi_Host *host = class_to_shost(cdev);\
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
+       int val = 0;\
+       val = phba->cfg_##attr;\
+       return snprintf(buf, PAGE_SIZE, "%#x\n",\
+@@ -720,9 +514,8 @@
+ static ssize_t \
+ lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
+ { \
+-      struct Scsi_Host  *shost = class_to_shost(cdev);\
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+-      struct lpfc_hba   *phba = vport->phba;\
++      struct Scsi_Host *host = class_to_shost(cdev);\
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
+       int val=0;\
+       if (!isdigit(buf[0]))\
+               return -EINVAL;\
+@@ -783,7 +576,7 @@
+ static CLASS_DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL);
+ static CLASS_DEVICE_ATTR(modelname, S_IRUGO, lpfc_modelname_show, NULL);
+ static CLASS_DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
+-static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
++static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_portnum_show, NULL);
+ static CLASS_DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
+ static CLASS_DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
+ static CLASS_DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);
+@@ -799,13 +592,6 @@
+ static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
+                        lpfc_board_mode_show, lpfc_board_mode_store);
+ static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
+-static CLASS_DEVICE_ATTR(max_vpi, S_IRUGO, lpfc_max_vpi_show, NULL);
+-static CLASS_DEVICE_ATTR(used_vpi, S_IRUGO, lpfc_used_vpi_show, NULL);
+-static CLASS_DEVICE_ATTR(max_rpi, S_IRUGO, lpfc_max_rpi_show, NULL);
+-static CLASS_DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL);
+-static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
+-static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
+-static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
  
--void sysfs_remove_subdir(struct dentry * d)
-+static void sysfs_empty_dir(struct sysfs_addrm_cxt *acxt,
-+                          struct sysfs_dirent *dir_sd)
+ static char *lpfc_soft_wwn_key = "C99G71SL8032A";
+@@ -814,9 +600,8 @@
+ lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf,
+                               size_t count)
  {
--      remove_dir(d);
-+      struct sysfs_dirent **pos;
-+
-+      pos = &dir_sd->s_children;
-+      while (*pos) {
-+              struct sysfs_dirent *sd = *pos;
-+
-+              if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) {
-+                      *pos = sd->s_sibling;
-+                      sd->s_sibling = NULL;
-+                      sysfs_remove_one(acxt, sd);
-+              } else
-+                      pos = &(*pos)->s_sibling;
-+      }
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       unsigned int cnt = count;
+       /*
+@@ -849,10 +634,8 @@
+ static ssize_t
+ lpfc_soft_wwpn_show(struct class_device *cdev, char *buf)
+ {
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       return snprintf(buf, PAGE_SIZE, "0x%llx\n",
+                       (unsigned long long)phba->cfg_soft_wwpn);
  }
+@@ -861,9 +644,8 @@
+ static ssize_t
+ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
+ {
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct completion online_compl;
+       int stat1=0, stat2=0;
+       unsigned int i, j, cnt=count;
+@@ -898,9 +680,9 @@
+               }
+       }
+       phba->cfg_soft_wwpn = wwn_to_u64(wwpn);
+-      fc_host_port_name(shost) = phba->cfg_soft_wwpn;
++      fc_host_port_name(host) = phba->cfg_soft_wwpn;
+       if (phba->cfg_soft_wwnn)
+-              fc_host_node_name(shost) = phba->cfg_soft_wwnn;
++              fc_host_node_name(host) = phba->cfg_soft_wwnn;
  
-+static void sysfs_remove_shadows(struct sysfs_addrm_cxt * acxt,
-+                                      struct sysfs_dirent *dir_sd)
-+{
-+      struct sysfs_dirent **pos;
-+
-+      pos = &dir_sd->s_children;
-+      while (*pos) {
-+              struct sysfs_dirent *sd = *pos;
-+
-+              sysfs_empty_dir(acxt, sd);
-+              __remove_dir(acxt, sd);
-+      }
-+}
+       dev_printk(KERN_NOTICE, &phba->pcidev->dev,
+                  "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no);
+@@ -995,15 +777,6 @@
+ static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
+                        lpfc_poll_show, lpfc_poll_store);
  
--static void __sysfs_remove_dir(struct dentry *dentry)
-+static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
+-int  lpfc_sli_mode = 0;
+-module_param(lpfc_sli_mode, int, 0);
+-MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:"
+-               " 0 - auto (SLI-3 if supported),"
+-               " 2 - select SLI-2 even on SLI-3 capable HBAs,"
+-               " 3 - select SLI-3");
+-
+-LPFC_ATTR_R(npiv_enable, 0, 0, 1, "Enable NPIV functionality");
+-
+ /*
+ # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
+ # until the timer expires. Value range is [0,255]. Default value is 30.
+@@ -1017,9 +790,8 @@
+ static ssize_t
+ lpfc_nodev_tmo_show(struct class_device *cdev, char *buf)
  {
--      struct sysfs_dirent * parent_sd;
--      struct sysfs_dirent * sd, * tmp;
-+      struct sysfs_addrm_cxt acxt;
--      dget(dentry);
--      if (!dentry)
-+      if (!dir_sd)
-               return;
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host = class_to_shost(cdev);
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       int val = 0;
+       val = phba->cfg_devloss_tmo;
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+@@ -1060,19 +832,13 @@
+ static void
+ lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba)
+ {
+-      struct lpfc_vport *vport;
+-      struct Scsi_Host  *shost;
+       struct lpfc_nodelist  *ndlp;
  
--      pr_debug("sysfs %s: removing dir\n",dentry->d_name.name);
--      mutex_lock(&dentry->d_inode->i_mutex);
--      parent_sd = dentry->d_fsdata;
--      list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) {
--              if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED))
--                      continue;
--              list_del_init(&sd->s_sibling);
--              sysfs_drop_dentry(sd, dentry);
--              sysfs_put(sd);
+-      list_for_each_entry(vport, &phba->port_list, listentry) {
+-              shost = lpfc_shost_from_vport(vport);
+-              spin_lock_irq(shost->host_lock);
+-              list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp)
++      spin_lock_irq(phba->host->host_lock);
++      list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp)
+               if (ndlp->rport)
+-                              ndlp->rport->dev_loss_tmo =
+-                                      phba->cfg_devloss_tmo;
+-              spin_unlock_irq(shost->host_lock);
 -      }
--      mutex_unlock(&dentry->d_inode->i_mutex);
-+      pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
-+      sysfs_addrm_start(&acxt, dir_sd);
-+      if (sysfs_type(dir_sd) == SYSFS_DIR)
-+              sysfs_empty_dir(&acxt, dir_sd);
-+      else
-+              sysfs_remove_shadows(&acxt, dir_sd);
-+      sysfs_addrm_finish(&acxt);
--      remove_dir(dentry);
--      /**
--       * Drop reference from dget() on entrance.
--       */
--      dput(dentry);
-+      remove_dir(dir_sd);
++                      ndlp->rport->dev_loss_tmo = phba->cfg_devloss_tmo;
++      spin_unlock_irq(phba->host->host_lock);
  }
  
- /**
-@@ -393,102 +1064,154 @@
+ static int
+@@ -1180,33 +946,6 @@
+           "Max number of FCP commands we can queue to a lpfc HBA");
  
- void sysfs_remove_dir(struct kobject * kobj)
- {
--      __sysfs_remove_dir(kobj->dentry);
--      kobj->dentry = NULL;
-+      struct sysfs_dirent *sd = kobj->sd;
-+
-+      spin_lock(&sysfs_assoc_lock);
-+      kobj->sd = NULL;
-+      spin_unlock(&sysfs_assoc_lock);
-+
-+      __sysfs_remove_dir(sd);
- }
+ /*
+-# peer_port_login:  This parameter allows/prevents logins
+-# between peer ports hosted on the same physical port.
+-# When this parameter is set 0 peer ports of same physical port
+-# are not allowed to login to each other.
+-# When this parameter is set 1 peer ports of same physical port
+-# are allowed to login to each other.
+-# Default value of this parameter is 0.
+-*/
+-LPFC_ATTR_R(peer_port_login, 0, 0, 1,
+-          "Allow peer ports on the same physical port to login to each "
+-          "other.");
+-
+-/*
+-# vport_restrict_login:  This parameter allows/prevents logins
+-# between Virtual Ports and remote initiators.
+-# When this parameter is not set (0) Virtual Ports will accept PLOGIs from
+-# other initiators and will attempt to PLOGI all remote ports.
+-# When this parameter is set (1) Virtual Ports will reject PLOGIs from
+-# remote ports and will not attempt to PLOGI to other initiators.
+-# This parameter does not restrict to the physical port.
+-# This parameter does not restrict logins to Fabric resident remote ports.
+-# Default value of this parameter is 1.
+-*/
+-LPFC_ATTR_RW(vport_restrict_login, 1, 0, 1,
+-          "Restrict virtual ports login to remote initiators.");
+-
+-/*
+ # Some disk devices have a "select ID" or "select Target" capability.
+ # From a protocol standpoint "select ID" usually means select the
+ # Fibre channel "ALPA".  In the FC-AL Profile there is an "informative
+@@ -1349,8 +1088,7 @@
+ LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible");
  
--int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
--                   const char *new_name)
-+int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
+-
+-struct class_device_attribute *lpfc_hba_attrs[] = {
++struct class_device_attribute *lpfc_host_attrs[] = {
+       &class_device_attr_info,
+       &class_device_attr_serialnum,
+       &class_device_attr_modeldesc,
+@@ -1366,8 +1104,6 @@
+       &class_device_attr_lpfc_log_verbose,
+       &class_device_attr_lpfc_lun_queue_depth,
+       &class_device_attr_lpfc_hba_queue_depth,
+-      &class_device_attr_lpfc_peer_port_login,
+-      &class_device_attr_lpfc_vport_restrict_login,
+       &class_device_attr_lpfc_nodev_tmo,
+       &class_device_attr_lpfc_devloss_tmo,
+       &class_device_attr_lpfc_fcp_class,
+@@ -1383,17 +1119,9 @@
+       &class_device_attr_lpfc_multi_ring_type,
+       &class_device_attr_lpfc_fdmi_on,
+       &class_device_attr_lpfc_max_luns,
+-      &class_device_attr_lpfc_npiv_enable,
+       &class_device_attr_nport_evt_cnt,
+       &class_device_attr_management_version,
+       &class_device_attr_board_mode,
+-      &class_device_attr_max_vpi,
+-      &class_device_attr_used_vpi,
+-      &class_device_attr_max_rpi,
+-      &class_device_attr_used_rpi,
+-      &class_device_attr_max_xri,
+-      &class_device_attr_used_xri,
+-      &class_device_attr_npiv_info,
+       &class_device_attr_issue_reset,
+       &class_device_attr_lpfc_poll,
+       &class_device_attr_lpfc_poll_tmo,
+@@ -1408,11 +1136,9 @@
+ sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
  {
--      int error = 0;
--      struct dentry * new_dentry;
-+      struct dentry *old_dentry, *new_dentry, *parent;
-+      struct sysfs_addrm_cxt acxt;
-+      struct sysfs_dirent *sd;
-+      const char *dup_name;
-+      int error;
+       size_t buf_off;
+-      struct class_device *cdev = container_of(kobj, struct class_device,
+-                                               kobj);
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host = class_to_shost(container_of(kobj,
++                                           struct class_device, kobj));
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
  
--      if (!new_parent)
--              return -EFAULT;
-+      dup_name = NULL;
-+      new_dentry = NULL;
--      down_write(&sysfs_rename_sem);
--      mutex_lock(&new_parent->d_inode->i_mutex);
-+      sd = kobj->sd;
-+      sysfs_addrm_start(&acxt, sd->s_parent);
-+      error = -ENOENT;
-+      if (!sysfs_resolve_for_create(kobj, &acxt.parent_sd))
-+              goto addrm_finish;
-+
-+      error = -EEXIST;
-+      if (sysfs_find_dirent(acxt.parent_sd, new_name))
-+              goto addrm_finish;
--      new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name));
--      if (!IS_ERR(new_dentry)) {
--              /* By allowing two different directories with the
--               * same d_parent we allow this routine to move
--               * between different shadows of the same directory
--               */
--              if (kobj->dentry->d_parent->d_inode != new_parent->d_inode)
--                      return -EINVAL;
--              else if (new_dentry->d_parent->d_inode != new_parent->d_inode)
-                       error = -EINVAL;
--              else if (new_dentry == kobj->dentry)
-+      if ((sd->s_parent == acxt.parent_sd) &&
-+          (strcmp(new_name, sd->s_name) == 0))
-+              goto addrm_finish;
-+
-+      old_dentry = sd->s_dentry;
-+      parent = acxt.parent_sd->s_dentry;
-+      if (old_dentry) {
-+              old_dentry = sd->s_dentry;
-+              parent = acxt.parent_sd->s_dentry;
-+              new_dentry = lookup_one_len(new_name, parent, strlen(new_name));
-+      if (IS_ERR(new_dentry)) {
-+              error = PTR_ERR(new_dentry);
-+                      goto addrm_finish;
-+      }
-+
-                       error = -EINVAL;
--              else if (!new_dentry->d_inode) {
-+              if (old_dentry == new_dentry)
-+                      goto addrm_finish;
-+      }
-+
-+      /* rename kobject and sysfs_dirent */
-+      error = -ENOMEM;
-+      new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
-+      if (!new_name)
-+              goto addrm_finish;
+       if ((off + count) > FF_REG_AREA_SIZE)
+               return -ERANGE;
+@@ -1422,16 +1148,18 @@
+       if (off % 4 || count % 4 || (unsigned long)buf % 4)
+               return -EINVAL;
+-      if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
++      spin_lock_irq(phba->host->host_lock);
 +
-                       error = kobject_set_name(kobj, "%s", new_name);
--                      if (!error) {
--                              struct sysfs_dirent *sd, *parent_sd;
-+      if (error)
-+              goto addrm_finish;
--                              d_add(new_dentry, NULL);
--                              d_move(kobj->dentry, new_dentry);
-+      dup_name = sd->s_name;
-+      sd->s_name = new_name;
--                              sd = kobj->dentry->d_fsdata;
--                              parent_sd = new_parent->d_fsdata;
-+      /* move under the new parent */
-+      sysfs_unlink_sibling(sd);
-+      sysfs_get(acxt.parent_sd);
-+      sysfs_put(sd->s_parent);
-+      sd->s_parent = acxt.parent_sd;
-+      sysfs_link_sibling(sd);
--                              list_del_init(&sd->s_sibling);
--                              list_add(&sd->s_sibling, &parent_sd->s_children);
--                      }
--                      else
--                              d_drop(new_dentry);
--              } else
--                      error = -EEXIST;
--              dput(new_dentry);
-+      if (new_dentry) {
-+              d_add(new_dentry, NULL);
-+              d_move(old_dentry, new_dentry);
++      if (!(phba->fc_flag & FC_OFFLINE_MODE)) {
++              spin_unlock_irq(phba->host->host_lock);
+               return -EPERM;
        }
--      mutex_unlock(&new_parent->d_inode->i_mutex);
--      up_write(&sysfs_rename_sem);
-+      error = 0;
-+addrm_finish:
-+      sysfs_addrm_finish(&acxt);
  
-+      kfree(dup_name);
-+      dput(new_dentry);
-       return error;
- }
+-      spin_lock_irq(&phba->hbalock);
+       for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t))
+               writel(*((uint32_t *)(buf + buf_off)),
+                      phba->ctrl_regs_memmap_p + off + buf_off);
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
  
--int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
-+int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
+       return count;
+ }
+@@ -1441,11 +1169,9 @@
  {
--      struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry;
--      struct sysfs_dirent *new_parent_sd, *sd;
-+      struct sysfs_dirent *sd = kobj->sd;
-+      struct sysfs_dirent *new_parent_sd;
-+      struct dentry *old_parent, *new_parent = NULL;
-+      struct dentry *old_dentry = NULL, *new_dentry = NULL;
-       int error;
+       size_t buf_off;
+       uint32_t * tmp_ptr;
+-      struct class_device *cdev = container_of(kobj, struct class_device,
+-                                               kobj);
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host = class_to_shost(container_of(kobj,
++                                           struct class_device, kobj));
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
  
--      old_parent_dentry = kobj->parent ?
--              kobj->parent->dentry : sysfs_mount->mnt_sb->s_root;
--      new_parent_dentry = new_parent ?
--              new_parent->dentry : sysfs_mount->mnt_sb->s_root;
-+      BUG_ON(!sd->s_parent);
-+      new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root;
-+
-+      /* get dentries */
-+      old_dentry = sysfs_get_dentry(sd);
-+      if (IS_ERR(old_dentry)) {
-+              error = PTR_ERR(old_dentry);
-+              goto out_dput;
-+      }
-+      old_parent = sd->s_parent->s_dentry;
-+
-+      new_parent = sysfs_get_dentry(new_parent_sd);
-+      if (IS_ERR(new_parent)) {
-+              error = PTR_ERR(new_parent);
-+              goto out_dput;
-+      }
+       if (off > FF_REG_AREA_SIZE)
+               return -ERANGE;
+@@ -1458,14 +1184,14 @@
+       if (off % 4 || count % 4 || (unsigned long)buf % 4)
+               return -EINVAL;
  
--      if (old_parent_dentry->d_inode == new_parent_dentry->d_inode)
--              return 0;       /* nothing to move */
-+      if (old_parent->d_inode == new_parent->d_inode) {
-+              error = 0;
-+              goto out_dput;  /* nothing to move */
-+      }
- again:
--      mutex_lock(&old_parent_dentry->d_inode->i_mutex);
--      if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) {
--              mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
-+      mutex_lock(&old_parent->d_inode->i_mutex);
-+      if (!mutex_trylock(&new_parent->d_inode->i_mutex)) {
-+              mutex_unlock(&old_parent->d_inode->i_mutex);
-               goto again;
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) {
+               tmp_ptr = (uint32_t *)(buf + buf_off);
+               *tmp_ptr = readl(phba->ctrl_regs_memmap_p + off + buf_off);
        }
  
--      new_parent_sd = new_parent_dentry->d_fsdata;
--      sd = kobj->dentry->d_fsdata;
--
--      new_dentry = lookup_one_len(kobj->name, new_parent_dentry,
--                                  strlen(kobj->name));
-+      new_dentry = lookup_one_len(kobj->name, new_parent, strlen(kobj->name));
-       if (IS_ERR(new_dentry)) {
-               error = PTR_ERR(new_dentry);
--              goto out;
-+              goto out_unlock;
-       } else
-               error = 0;
-       d_add(new_dentry, NULL);
--      d_move(kobj->dentry, new_dentry);
-+      d_move(sd->s_dentry, new_dentry);
-       dput(new_dentry);
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       return count;
+ }
+@@ -1474,6 +1200,7 @@
+       .attr = {
+               .name = "ctlreg",
+               .mode = S_IRUSR | S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = 256,
+       .read = sysfs_ctlreg_read,
+@@ -1482,7 +1209,7 @@
+ static void
+-sysfs_mbox_idle(struct lpfc_hba *phba)
++sysfs_mbox_idle (struct lpfc_hba * phba)
+ {
+       phba->sysfs_mbox.state = SMBOX_IDLE;
+       phba->sysfs_mbox.offset = 0;
+@@ -1497,12 +1224,10 @@
+ static ssize_t
+ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+-      struct class_device *cdev = container_of(kobj, struct class_device,
+-                                               kobj);
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-      struct lpfcMboxq  *mbox = NULL;
++      struct Scsi_Host * host =
++              class_to_shost(container_of(kobj, struct class_device, kobj));
++      struct lpfc_hba * phba = (struct lpfc_hba*)host->hostdata;
++      struct lpfcMboxq * mbox = NULL;
  
-       /* Remove from old parent's list and insert into new parent's list. */
--      list_del_init(&sd->s_sibling);
--      list_add(&sd->s_sibling, &new_parent_sd->s_children);
-+      mutex_lock(&sysfs_mutex);
+       if ((count + off) > MAILBOX_CMD_SIZE)
+               return -ERANGE;
+@@ -1520,7 +1245,7 @@
+               memset(mbox, 0, sizeof (LPFC_MBOXQ_t));
+       }
  
--out:
--      mutex_unlock(&new_parent_dentry->d_inode->i_mutex);
--      mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
-+      sysfs_unlink_sibling(sd);
-+      sysfs_get(new_parent_sd);
-+      sysfs_put(sd->s_parent);
-+      sd->s_parent = new_parent_sd;
-+      sysfs_link_sibling(sd);
-+
-+      mutex_unlock(&sysfs_mutex);
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(host->host_lock);
  
-+ out_unlock:
-+      mutex_unlock(&new_parent->d_inode->i_mutex);
-+      mutex_unlock(&old_parent->d_inode->i_mutex);
-+ out_dput:
-+      dput(new_parent);
-+      dput(old_dentry);
-+      dput(new_dentry);
-       return error;
- }
+       if (off == 0) {
+               if (phba->sysfs_mbox.mbox)
+@@ -1531,9 +1256,9 @@
+       } else {
+               if (phba->sysfs_mbox.state  != SMBOX_WRITING ||
+                   phba->sysfs_mbox.offset != off           ||
+-                  phba->sysfs_mbox.mbox   == NULL) {
++                  phba->sysfs_mbox.mbox   == NULL ) {
+                       sysfs_mbox_idle(phba);
+-                      spin_unlock_irq(&phba->hbalock);
++                      spin_unlock_irq(host->host_lock);
+                       return -EAGAIN;
+               }
+       }
+@@ -1543,7 +1268,7 @@
  
-@@ -496,23 +1219,27 @@
- {
-       struct dentry * dentry = file->f_path.dentry;
-       struct sysfs_dirent * parent_sd = dentry->d_fsdata;
-+      struct sysfs_dirent * sd;
+       phba->sysfs_mbox.offset = off + count;
  
--      mutex_lock(&dentry->d_inode->i_mutex);
--      file->private_data = sysfs_new_dirent(parent_sd, NULL);
--      mutex_unlock(&dentry->d_inode->i_mutex);
--
--      return file->private_data ? 0 : -ENOMEM;
-+      sd = sysfs_new_dirent("_DIR_", 0, 0);
-+      if (sd) {
-+              mutex_lock(&sysfs_mutex);
-+              sd->s_parent = sysfs_get(parent_sd);
-+              sysfs_link_sibling(sd);
-+              mutex_unlock(&sysfs_mutex);
-+      }
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(host->host_lock);
  
-+      file->private_data = sd;
-+      return sd ? 0 : -ENOMEM;
+       return count;
  }
- static int sysfs_dir_close(struct inode *inode, struct file *file)
+@@ -1551,11 +1276,10 @@
+ static ssize_t
+ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
  {
--      struct dentry * dentry = file->f_path.dentry;
-       struct sysfs_dirent * cursor = file->private_data;
--      mutex_lock(&dentry->d_inode->i_mutex);
--      list_del_init(&cursor->s_sibling);
--      mutex_unlock(&dentry->d_inode->i_mutex);
-+      mutex_lock(&sysfs_mutex);
-+      sysfs_unlink_sibling(cursor);
-+      mutex_unlock(&sysfs_mutex);
+-      struct class_device *cdev = container_of(kobj, struct class_device,
+-                                               kobj);
+-      struct Scsi_Host  *shost = class_to_shost(cdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct Scsi_Host *host =
++              class_to_shost(container_of(kobj, struct class_device,
++                                          kobj));
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       int rc;
  
-       release_sysfs_dirent(cursor);
+       if (off > MAILBOX_CMD_SIZE)
+@@ -1570,7 +1294,7 @@
+       if (off && count == 0)
+               return 0;
  
-@@ -530,7 +1257,7 @@
-       struct dentry *dentry = filp->f_path.dentry;
-       struct sysfs_dirent * parent_sd = dentry->d_fsdata;
-       struct sysfs_dirent *cursor = filp->private_data;
--      struct list_head *p, *q = &cursor->s_sibling;
-+      struct sysfs_dirent **pos;
-       ino_t ino;
-       int i = filp->f_pos;
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
  
-@@ -543,38 +1270,55 @@
-                       i++;
-                       /* fallthrough */
-               case 1:
--                      ino = parent_ino(dentry);
-+                      if (parent_sd->s_parent)
-+                              ino = parent_sd->s_parent->s_ino;
-+                      else
-+                              ino = parent_sd->s_ino;
-                       if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
-                               break;
-                       filp->f_pos++;
-                       i++;
-                       /* fallthrough */
+       if (off == 0 &&
+           phba->sysfs_mbox.state  == SMBOX_WRITING &&
+@@ -1593,12 +1317,12 @@
+               case MBX_SET_MASK:
+               case MBX_SET_SLIM:
+               case MBX_SET_DEBUG:
+-                      if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
++                      if (!(phba->fc_flag & FC_OFFLINE_MODE)) {
+                               printk(KERN_WARNING "mbox_read:Command 0x%x "
+                                      "is illegal in on-line state\n",
+                                      phba->sysfs_mbox.mbox->mb.mbxCommand);
+                               sysfs_mbox_idle(phba);
+-                              spin_unlock_irq(&phba->hbalock);
++                              spin_unlock_irq(phba->host->host_lock);
+                               return -EPERM;
+                       }
+               case MBX_LOAD_SM:
+@@ -1628,48 +1352,48 @@
+                       printk(KERN_WARNING "mbox_read: Illegal Command 0x%x\n",
+                              phba->sysfs_mbox.mbox->mb.mbxCommand);
+                       sysfs_mbox_idle(phba);
+-                      spin_unlock_irq(&phba->hbalock);
++                      spin_unlock_irq(phba->host->host_lock);
+                       return -EPERM;
                default:
-+                      /* If I am the shadow master return nothing. */
-+                      if (parent_sd->s_flags & SYSFS_FLAG_SHADOWED)
-+                              return 0;
-+
-+                      mutex_lock(&sysfs_mutex);
-+                      pos = &parent_sd->s_children;
-+                      while (*pos != cursor)
-+                              pos = &(*pos)->s_sibling;
-+
-+                      /* unlink cursor */
-+                      *pos = cursor->s_sibling;
-+
-                       if (filp->f_pos == 2)
--                              list_move(q, &parent_sd->s_children);
-+                              pos = &parent_sd->s_children;
+                       printk(KERN_WARNING "mbox_read: Unknown Command 0x%x\n",
+                              phba->sysfs_mbox.mbox->mb.mbxCommand);
+                       sysfs_mbox_idle(phba);
+-                      spin_unlock_irq(&phba->hbalock);
++                      spin_unlock_irq(phba->host->host_lock);
+                       return -EPERM;
+               }
  
--                      for (p=q->next; p!= &parent_sd->s_children; p=p->next) {
--                              struct sysfs_dirent *next;
-+                      for ( ; *pos; pos = &(*pos)->s_sibling) {
-+                              struct sysfs_dirent *next = *pos;
-                               const char * name;
-                               int len;
+-              phba->sysfs_mbox.mbox->vport = vport;
+-
+-              if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
++              if (phba->fc_flag & FC_BLOCK_MGMT_IO) {
+                       sysfs_mbox_idle(phba);
+-                      spin_unlock_irq(&phba->hbalock);
++                      spin_unlock_irq(host->host_lock);
+                       return  -EAGAIN;
+               }
  
--                              next = list_entry(p, struct sysfs_dirent,
--                                                 s_sibling);
--                              if (!next->s_element)
-+                              if (!sysfs_type(next))
-                                       continue;
+-              if ((vport->fc_flag & FC_OFFLINE_MODE) ||
++              if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+                   (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){
  
--                              name = sysfs_get_name(next);
-+                              name = next->s_name;
-                               len = strlen(name);
-                               ino = next->s_ino;
+-                      spin_unlock_irq(&phba->hbalock);
++                      spin_unlock_irq(phba->host->host_lock);
+                       rc = lpfc_sli_issue_mbox (phba,
+                                                 phba->sysfs_mbox.mbox,
+                                                 MBX_POLL);
+-                      spin_lock_irq(&phba->hbalock);
++                      spin_lock_irq(phba->host->host_lock);
  
-                               if (filldir(dirent, name, len, filp->f_pos, ino,
-                                                dt_type(next)) < 0)
--                                      return 0;
-+                                      break;
+               } else {
+-                      spin_unlock_irq(&phba->hbalock);
++                      spin_unlock_irq(phba->host->host_lock);
+                       rc = lpfc_sli_issue_mbox_wait (phba,
+                                                      phba->sysfs_mbox.mbox,
+                               lpfc_mbox_tmo_val(phba,
+                                   phba->sysfs_mbox.mbox->mb.mbxCommand) * HZ);
+-                      spin_lock_irq(&phba->hbalock);
++                      spin_lock_irq(phba->host->host_lock);
+               }
  
--                              list_move(q, p);
--                              p = q;
-                               filp->f_pos++;
+               if (rc != MBX_SUCCESS) {
+                       if (rc == MBX_TIMEOUT) {
++                              phba->sysfs_mbox.mbox->mbox_cmpl =
++                                      lpfc_sli_def_mbox_cmpl;
+                               phba->sysfs_mbox.mbox = NULL;
                        }
-+
-+                      /* put cursor back in */
-+                      cursor->s_sibling = *pos;
-+                      *pos = cursor;
-+
-+                      mutex_unlock(&sysfs_mutex);
+                       sysfs_mbox_idle(phba);
+-                      spin_unlock_irq(&phba->hbalock);
++                      spin_unlock_irq(host->host_lock);
+                       return  (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
+               }
+               phba->sysfs_mbox.state = SMBOX_READING;
+@@ -1678,7 +1402,7 @@
+                phba->sysfs_mbox.state  != SMBOX_READING) {
+               printk(KERN_WARNING  "mbox_read: Bad State\n");
+               sysfs_mbox_idle(phba);
+-              spin_unlock_irq(&phba->hbalock);
++              spin_unlock_irq(host->host_lock);
+               return -EAGAIN;
        }
-       return 0;
+@@ -1689,7 +1413,7 @@
+       if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE)
+               sysfs_mbox_idle(phba);
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       return count;
  }
-@@ -583,7 +1327,6 @@
+@@ -1698,6 +1422,7 @@
+       .attr = {
+               .name = "mbox",
+               .mode = S_IRUSR | S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = MAILBOX_CMD_SIZE,
+       .read = sysfs_mbox_read,
+@@ -1705,35 +1430,35 @@
+ };
+ int
+-lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
++lpfc_alloc_sysfs_attr(struct lpfc_hba *phba)
  {
-       struct dentry * dentry = file->f_path.dentry;
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
++      struct Scsi_Host *host = phba->host;
+       int error;
  
--      mutex_lock(&dentry->d_inode->i_mutex);
-       switch (origin) {
-               case 1:
-                       offset += file->f_pos;
-@@ -591,127 +1334,224 @@
-                       if (offset >= 0)
-                               break;
-               default:
--                      mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
-                       return -EINVAL;
-       }
-       if (offset != file->f_pos) {
-+              mutex_lock(&sysfs_mutex);
-+
-               file->f_pos = offset;
-               if (file->f_pos >= 2) {
-                       struct sysfs_dirent *sd = dentry->d_fsdata;
-                       struct sysfs_dirent *cursor = file->private_data;
--                      struct list_head *p;
-+                      struct sysfs_dirent **pos;
-                       loff_t n = file->f_pos - 2;
+-      error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
++      error = sysfs_create_bin_file(&host->shost_classdev.kobj,
+                                                       &sysfs_ctlreg_attr);
+       if (error)
+               goto out;
  
--                      list_del(&cursor->s_sibling);
--                      p = sd->s_children.next;
--                      while (n && p != &sd->s_children) {
--                              struct sysfs_dirent *next;
--                              next = list_entry(p, struct sysfs_dirent,
--                                                 s_sibling);
--                              if (next->s_element)
-+                      sysfs_unlink_sibling(cursor);
-+
-+                      pos = &sd->s_children;
-+                      while (n && *pos) {
-+                              struct sysfs_dirent *next = *pos;
-+                              if (sysfs_type(next))
-                                       n--;
--                              p = p->next;
-+                              pos = &(*pos)->s_sibling;
-                       }
--                      list_add_tail(&cursor->s_sibling, p);
-+
-+                      cursor->s_sibling = *pos;
-+                      *pos = cursor;
-               }
-+
-+              mutex_unlock(&sysfs_mutex);
-       }
--      mutex_unlock(&dentry->d_inode->i_mutex);
-+
-       return offset;
+-      error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
++      error = sysfs_create_bin_file(&host->shost_classdev.kobj,
+                                                       &sysfs_mbox_attr);
+       if (error)
+               goto out_remove_ctlreg_attr;
+       return 0;
+ out_remove_ctlreg_attr:
+-      sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
++      sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
+ out:
+       return error;
  }
  
-+const struct file_operations sysfs_dir_operations = {
-+      .open           = sysfs_dir_open,
-+      .release        = sysfs_dir_close,
-+      .llseek         = sysfs_dir_lseek,
-+      .read           = generic_read_dir,
-+      .readdir        = sysfs_readdir,
-+};
+ void
+-lpfc_free_sysfs_attr(struct lpfc_vport *vport)
++lpfc_free_sysfs_attr(struct lpfc_hba *phba)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
++      struct Scsi_Host *host = phba->host;
  
--/**
-- *    sysfs_make_shadowed_dir - Setup so a directory can be shadowed
-- *    @kobj:  object we're creating shadow of.
-- */
+-      sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_mbox_attr);
+-      sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
++      sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_mbox_attr);
++      sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
+ }
  
--int sysfs_make_shadowed_dir(struct kobject *kobj,
--      void * (*follow_link)(struct dentry *, struct nameidata *))
-+static void sysfs_prune_shadow_sd(struct sysfs_dirent *sd)
- {
--      struct inode *inode;
--      struct inode_operations *i_op;
-+      struct sysfs_addrm_cxt acxt;
  
--      inode = kobj->dentry->d_inode;
--      if (inode->i_op != &sysfs_dir_inode_operations)
--              return -EINVAL;
-+      /* If a shadow directory goes empty remove it. */
-+      if (sysfs_type(sd) != SYSFS_SHADOW_DIR)
-+              return;
+@@ -1744,30 +1469,26 @@
+ static void
+ lpfc_get_host_port_id(struct Scsi_Host *shost)
+ {
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-
++      struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+       /* note: fc_myDID already in cpu endianness */
+-      fc_host_port_id(shost) = vport->fc_myDID;
++      fc_host_port_id(shost) = phba->fc_myDID;
+ }
  
--      i_op = kmalloc(sizeof(*i_op), GFP_KERNEL);
--      if (!i_op)
--              return -ENOMEM;
-+      if (sd->s_children)
-+              return;
+ static void
+ lpfc_get_host_port_type(struct Scsi_Host *shost)
+ {
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
  
--      memcpy(i_op, &sysfs_dir_inode_operations, sizeof(*i_op));
--      i_op->follow_link = follow_link;
-+      sysfs_addrm_start(&acxt, sd->s_parent);
+       spin_lock_irq(shost->host_lock);
  
--      /* Locking of inode->i_op?
--       * Since setting i_op is a single word write and they
--       * are atomic we should be ok here.
--       */
--      inode->i_op = i_op;
--      return 0;
--}
-+      if (sd->s_flags & SYSFS_FLAG_REMOVED)
-+              goto addrm_finish;
+-      if (vport->port_type == LPFC_NPIV_PORT) {
+-              fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
+-      } else if (lpfc_is_link_up(phba)) {
++      if (phba->hba_state == LPFC_HBA_READY) {
+               if (phba->fc_topology == TOPOLOGY_LOOP) {
+-                      if (vport->fc_flag & FC_PUBLIC_LOOP)
++                      if (phba->fc_flag & FC_PUBLIC_LOOP)
+                               fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
+                       else
+                               fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
+               } else {
+-                      if (vport->fc_flag & FC_FABRIC)
++                      if (phba->fc_flag & FC_FABRIC)
+                               fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
+                       else
+                               fc_host_port_type(shost) = FC_PORTTYPE_PTP;
+@@ -1781,20 +1502,29 @@
+ static void
+ lpfc_get_host_port_state(struct Scsi_Host *shost)
+ {
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
  
--/**
-- *    sysfs_create_shadow_dir - create a shadow directory for an object.
-- *    @kobj:  object we're creating directory for.
-- *
-- *    sysfs_make_shadowed_dir must already have been called on this
-- *    directory.
-- */
-+      if (sd->s_children)
-+              goto addrm_finish;
+       spin_lock_irq(shost->host_lock);
  
--struct dentry *sysfs_create_shadow_dir(struct kobject *kobj)
-+      __remove_dir(&acxt, sd);
-+addrm_finish:
-+      sysfs_addrm_finish(&acxt);
-+}
-+
-+static struct sysfs_dirent *add_shadow_sd(struct sysfs_dirent *parent_sd, const void *tag)
+-      if (vport->fc_flag & FC_OFFLINE_MODE)
++      if (phba->fc_flag & FC_OFFLINE_MODE)
+               fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
+       else {
+-              switch (phba->link_state) {
+-              case LPFC_LINK_UNKNOWN:
++              switch (phba->hba_state) {
++              case LPFC_STATE_UNKNOWN:
++              case LPFC_WARM_START:
++              case LPFC_INIT_START:
++              case LPFC_INIT_MBX_CMDS:
+               case LPFC_LINK_DOWN:
+                       fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
+                       break;
+               case LPFC_LINK_UP:
++              case LPFC_LOCAL_CFG_LINK:
++              case LPFC_FLOGI:
++              case LPFC_FABRIC_CFG_LINK:
++              case LPFC_NS_REG:
++              case LPFC_NS_QRY:
++              case LPFC_BUILD_DISC_LIST:
++              case LPFC_DISC_AUTH:
+               case LPFC_CLEAR_LA:
+               case LPFC_HBA_READY:
+                       /* Links up, beyond this port_type reports state */
+@@ -1815,12 +1545,11 @@
+ static void
+ lpfc_get_host_speed(struct Scsi_Host *shost)
  {
--      struct sysfs_dirent *sd;
--      struct dentry *parent, *dir, *shadow;
-+      struct sysfs_dirent *sd = NULL;
-+      struct dentry *dir, *shadow;
-       struct inode *inode;
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
  
--      dir = kobj->dentry;
-+      dir = parent_sd->s_dentry;
-       inode = dir->d_inode;
--      parent = dir->d_parent;
--      shadow = ERR_PTR(-EINVAL);
--      if (!sysfs_is_shadowed_inode(inode))
--              goto out;
+       spin_lock_irq(shost->host_lock);
  
--      shadow = d_alloc(parent, &dir->d_name);
-+      shadow = d_alloc(dir->d_parent, &dir->d_name);
-       if (!shadow)
--              goto nomem;
-+              goto out;
-+
-+      /* Since the shadow directory is reachable make it look
-+       * like it is actually hashed.
-+       */
-+      shadow->d_hash.pprev = &shadow->d_hash.next;
-+      shadow->d_hash.next = NULL;
-+      shadow->d_flags &= ~DCACHE_UNHASHED;
+-      if (lpfc_is_link_up(phba)) {
++      if (phba->hba_state == LPFC_HBA_READY) {
+               switch(phba->fc_linkspeed) {
+                       case LA_1GHZ_LINK:
+                               fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
+@@ -1846,30 +1575,38 @@
+ static void
+ lpfc_get_host_fabric_name (struct Scsi_Host *shost)
+ {
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+       u64 node_name;
  
--      sd = __sysfs_make_dirent(shadow, kobj, inode->i_mode, SYSFS_DIR);
-+      sd = sysfs_new_dirent(tag, parent_sd->s_mode, SYSFS_SHADOW_DIR);
-       if (!sd)
--              goto nomem;
-+              goto error;
+       spin_lock_irq(shost->host_lock);
  
--      d_instantiate(shadow, igrab(inode));
--      inc_nlink(inode);
--      inc_nlink(parent->d_inode);
--      shadow->d_op = &sysfs_dentry_ops;
-+      sd->s_elem.dir.kobj = parent_sd->s_elem.dir.kobj;
-+      sd->s_parent = sysfs_get(parent_sd);
+-      if ((vport->fc_flag & FC_FABRIC) ||
++      if ((phba->fc_flag & FC_FABRIC) ||
+           ((phba->fc_topology == TOPOLOGY_LOOP) &&
+-           (vport->fc_flag & FC_PUBLIC_LOOP)))
++           (phba->fc_flag & FC_PUBLIC_LOOP)))
+               node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
+       else
+               /* fabric is local port if there is no F/FL_Port */
+-              node_name = wwn_to_u64(vport->fc_nodename.u.wwn);
++              node_name = wwn_to_u64(phba->fc_nodename.u.wwn);
  
--      dget(shadow);           /* Extra count - pin the dentry in core */
-+      /* Use the inode number of the parent we are shadowing */
-+      sysfs_free_ino(sd->s_ino);
-+      sd->s_ino = parent_sd->s_ino;
+       spin_unlock_irq(shost->host_lock);
  
-+      inc_nlink(inode);
-+      inc_nlink(dir->d_parent->d_inode);
-+
-+      sysfs_link_sibling(sd);
-+      __iget(inode);
-+      sysfs_instantiate(shadow, inode);
-+      sysfs_attach_dentry(sd, shadow);
- out:
--      return shadow;
--nomem:
-+      return sd;
-+error:
-       dput(shadow);
--      shadow = ERR_PTR(-ENOMEM);
-       goto out;
+       fc_host_fabric_name(shost) = node_name;
  }
  
-+int sysfs_resolve_for_create(struct kobject *kobj,
-+                              struct sysfs_dirent **parent_sd)
-+{
-+      const struct shadow_dir_operations *shadow_ops;
-+      struct sysfs_dirent *sd, *shadow_sd;
-+
-+      sd = *parent_sd;
-+      if (sysfs_type(sd) == SYSFS_SHADOW_DIR)
-+              sd = sd->s_parent;
-+
-+      if (sd->s_flags & SYSFS_FLAG_SHADOWED) {
-+              const void *tag;
-+
-+              shadow_ops = sd->s_dentry->d_inode->i_private;
-+              tag = shadow_ops->kobject_tag(kobj);
-+
-+              shadow_sd = find_shadow_sd(sd, tag);
-+              if (!shadow_sd)
-+                      shadow_sd = add_shadow_sd(sd, tag);
-+              sd = shadow_sd;
-+      }
-+      if (sd) {
-+              *parent_sd = sd;
-+              return 1;
-+      }
-+      return 0;
-+}
-+
-+int sysfs_resolve_for_remove(struct kobject *kobj,
-+                              struct sysfs_dirent **parent_sd)
++static void
++lpfc_get_host_symbolic_name (struct Scsi_Host *shost)
 +{
-+      struct sysfs_dirent *sd;
-+      /* If dentry is a shadow directory find the shadow that is
-+       * stored under the same tag as kobj.  This allows removal
-+       * of dirents to function properly even if the value of
-+       * kobject_tag() has changed since we initially created
-+       * the dirents assoctated with kobj.
-+       */
++      struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
 +
-+      sd = *parent_sd;
-+      if (sysfs_type(sd) == SYSFS_SHADOW_DIR)
-+              sd = sd->s_parent;
-+      if (sd->s_flags & SYSFS_FLAG_SHADOWED) {
-+              const void *tag;
-+
-+              tag = find_shadow_tag(kobj);
-+              sd = find_shadow_sd(sd, tag);
-+      }
-+      if (sd) {
-+              *parent_sd = sd;
-+              return 1;
-+      }
-+      return 0;
++      spin_lock_irq(shost->host_lock);
++      lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost));
++      spin_unlock_irq(shost->host_lock);
 +}
 +
- /**
-- *    sysfs_remove_shadow_dir - remove an object's directory.
-- *    @shadow: dentry of shadow directory
-+ *    sysfs_enable_shadowing - Automatically create shadows of a directory
-+ *    @kobj:  object to automatically shadow
-  *
-- *    The only thing special about this is that we remove any files in
-- *    the directory before we remove the directory, and we've inlined
-- *    what used to be sysfs_rmdir() below, instead of calling separately.
-+ *    Once shadowing has been enabled on a directory the contents
-+ *    of the directory become dependent upon context.
-+ *
-+ *    shadow_ops->current_tag() returns the context for the current
-+ *    process.
-+ *
-+ *    shadow_ops->kobject_tag() returns the context that a given kobj
-+ *    resides in.
-+ *
-+ *    Using those methods the sysfs code on shadowed directories
-+ *    carefully stores the files so that when we lookup files
-+ *    we get the proper answer for our context.
-+ *
-+ *    If the context of a kobject is changed it is expected that
-+ *    the kobject will be renamed so the appopriate sysfs data structures
-+ *    can be updated.
-  */
--
--void sysfs_remove_shadow_dir(struct dentry *shadow)
-+int sysfs_enable_shadowing(struct kobject *kobj,
-+      const struct shadow_dir_operations *shadow_ops)
+ static struct fc_host_statistics *
+ lpfc_get_stats(struct Scsi_Host *shost)
  {
--      __sysfs_remove_dir(shadow);
-+      struct sysfs_dirent *sd;
-+      struct dentry *dentry;
-+      int err;
-+
-+      /* Find the dentry for the shadowed directory and
-+       * increase it's count.
-+       */
-+      err = -ENOENT;
-+      sd = kobj->sd;
-+      dentry = sysfs_get_dentry(sd);
-+      if (!dentry)
-+              goto out;
-+
-+      mutex_lock(&sysfs_mutex);
-+      err = -EINVAL;
-+      /* We can only enable shadowing on empty directories
-+       * where shadowing is not already enabled.
-+       */
-+      if (!sd->s_children && (sysfs_type(sd) == SYSFS_DIR) &&
-+          !(sd->s_flags & SYSFS_FLAG_REMOVED) &&
-+          !(sd->s_flags & SYSFS_FLAG_SHADOWED)) {
-+              sd->s_flags |= SYSFS_FLAG_SHADOWED;
-+              dentry->d_inode->i_private = (void *)shadow_ops;
-+              err = 0;
-+      }
-+      mutex_unlock(&sysfs_mutex);
-+out:
-+      if (err)
-+              dput(dentry);
-+      return err;
- }
--const struct file_operations sysfs_dir_operations = {
--      .open           = sysfs_dir_open,
--      .release        = sysfs_dir_close,
--      .llseek         = sysfs_dir_lseek,
--      .read           = generic_read_dir,
--      .readdir        = sysfs_readdir,
--};
-diff -Nurb linux-2.6.22-570/fs/sysfs/file.c linux-2.6.22-590/fs/sysfs/file.c
---- linux-2.6.22-570/fs/sysfs/file.c   2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/fs/sysfs/file.c   2008-01-02 13:56:37.000000000 -0500
-@@ -50,29 +50,15 @@
-       .store  = subsys_attr_store,
- };
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+       struct lpfc_sli *psli = &phba->sli;
+       struct fc_host_statistics *hs = &phba->link_stats;
+       struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
+@@ -1878,16 +1615,7 @@
+       unsigned long seconds;
+       int rc = 0;
  
--/**
-- *    add_to_collection - add buffer to a collection
-- *    @buffer:        buffer to be added
-- *    @node:          inode of set to add to
-- */
--
--static inline void
--add_to_collection(struct sysfs_buffer *buffer, struct inode *node)
--{
--      struct sysfs_buffer_collection *set = node->i_private;
--
--      mutex_lock(&node->i_mutex);
--      list_add(&buffer->associates, &set->associates);
--      mutex_unlock(&node->i_mutex);
--}
+-      /*
+-       * prevent udev from issuing mailbox commands until the port is
+-       * configured.
+-       */
+-      if (phba->link_state < LPFC_LINK_DOWN ||
+-          !phba->mbox_mem_pool ||
+-          (phba->sli.sli_flag & LPFC_SLI2_ACTIVE) == 0)
+-              return NULL;
 -
--static inline void
--remove_from_collection(struct sysfs_buffer *buffer, struct inode *node)
--{
--      mutex_lock(&node->i_mutex);
--      list_del(&buffer->associates);
--      mutex_unlock(&node->i_mutex);
--}
-+struct sysfs_buffer {
-+      size_t                  count;
-+      loff_t                  pos;
-+      char                    * page;
-+      struct sysfs_ops        * ops;
-+      struct semaphore        sem;
-+      int                     needs_read_fill;
-+      int                     event;
-+};
+-      if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
++      if (phba->fc_flag & FC_BLOCK_MGMT_IO)
+               return NULL;
  
- /**
-  *    fill_read_buffer - allocate and fill buffer from object.
-@@ -87,9 +73,8 @@
-  */
- static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
- {
--      struct sysfs_dirent * sd = dentry->d_fsdata;
--      struct attribute * attr = to_attr(dentry);
--      struct kobject * kobj = to_kobj(dentry->d_parent);
-+      struct sysfs_dirent *attr_sd = dentry->d_fsdata;
-+      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
-       struct sysfs_ops * ops = buffer->ops;
-       int ret = 0;
-       ssize_t count;
-@@ -99,8 +84,15 @@
-       if (!buffer->page)
-               return -ENOMEM;
+       pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+@@ -1899,16 +1627,17 @@
+       pmb->mbxCommand = MBX_READ_STATUS;
+       pmb->mbxOwner = OWN_HOST;
+       pmboxq->context1 = NULL;
+-      pmboxq->vport = vport;
  
--      buffer->event = atomic_read(&sd->s_event);
--      count = ops->show(kobj,attr,buffer->page);
-+      /* need attr_sd for attr and ops, its parent for kobj */
-+      if (!sysfs_get_active_two(attr_sd))
-+              return -ENODEV;
-+
-+      buffer->event = atomic_read(&attr_sd->s_event);
-+      count = ops->show(kobj, attr_sd->s_elem.attr.attr, buffer->page);
-+
-+      sysfs_put_active_two(attr_sd);
-+
-       BUG_ON(count > (ssize_t)PAGE_SIZE);
-       if (count >= 0) {
-               buffer->needs_read_fill = 0;
-@@ -138,9 +130,6 @@
+-      if ((vport->fc_flag & FC_OFFLINE_MODE) ||
++      if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+               (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
+               rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
+       else
+               rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
  
-       down(&buffer->sem);
-       if (buffer->needs_read_fill) {
--              if (buffer->orphaned)
--                      retval = -ENODEV;
--              else
-                       retval = fill_read_buffer(file->f_path.dentry,buffer);
-               if (retval)
-                       goto out;
-@@ -199,11 +188,20 @@
- static int 
- flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
+       if (rc != MBX_SUCCESS) {
+-              if (rc != MBX_TIMEOUT)
++              if (rc == MBX_TIMEOUT)
++                      pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
++              else
+                       mempool_free(pmboxq, phba->mbox_mem_pool);
+               return NULL;
+       }
+@@ -1924,17 +1653,18 @@
+       pmb->mbxCommand = MBX_READ_LNK_STAT;
+       pmb->mbxOwner = OWN_HOST;
+       pmboxq->context1 = NULL;
+-      pmboxq->vport = vport;
+-      if ((vport->fc_flag & FC_OFFLINE_MODE) ||
++      if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+           (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
+               rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
+       else
+               rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+       if (rc != MBX_SUCCESS) {
+-              if (rc != MBX_TIMEOUT)
+-                      mempool_free(pmboxq, phba->mbox_mem_pool);
++              if (rc == MBX_TIMEOUT)
++                      pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
++              else
++                      mempool_free( pmboxq, phba->mbox_mem_pool);
+               return NULL;
+       }
+@@ -1981,15 +1711,14 @@
+ static void
+ lpfc_reset_stats(struct Scsi_Host *shost)
  {
--      struct attribute * attr = to_attr(dentry);
--      struct kobject * kobj = to_kobj(dentry->d_parent);
-+      struct sysfs_dirent *attr_sd = dentry->d_fsdata;
-+      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
-       struct sysfs_ops * ops = buffer->ops;
-+      int rc;
-+
-+      /* need attr_sd for attr and ops, its parent for kobj */
-+      if (!sysfs_get_active_two(attr_sd))
-+              return -ENODEV;
-+
-+      rc = ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count);
-+
-+      sysfs_put_active_two(attr_sd);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+       struct lpfc_sli *psli = &phba->sli;
+-      struct lpfc_lnk_stat *lso = &psli->lnk_stat_offsets;
++      struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
+       LPFC_MBOXQ_t *pmboxq;
+       MAILBOX_t *pmb;
+       int rc = 0;
  
--      return ops->store(kobj,attr,buffer->page,count);
-+      return rc;
- }
+-      if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
++      if (phba->fc_flag & FC_BLOCK_MGMT_IO)
+               return;
  
+       pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+@@ -2002,16 +1731,17 @@
+       pmb->mbxOwner = OWN_HOST;
+       pmb->un.varWords[0] = 0x1; /* reset request */
+       pmboxq->context1 = NULL;
+-      pmboxq->vport = vport;
  
-@@ -231,37 +229,29 @@
-       ssize_t len;
+-      if ((vport->fc_flag & FC_OFFLINE_MODE) ||
++      if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+               (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
+               rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
+       else
+               rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
  
-       down(&buffer->sem);
--      if (buffer->orphaned) {
--              len = -ENODEV;
--              goto out;
--      }
-       len = fill_write_buffer(buffer, buf, count);
-       if (len > 0)
-               len = flush_write_buffer(file->f_path.dentry, buffer, len);
-       if (len > 0)
-               *ppos += len;
--out:
-       up(&buffer->sem);
-       return len;
- }
+       if (rc != MBX_SUCCESS) {
+-              if (rc != MBX_TIMEOUT)
++              if (rc == MBX_TIMEOUT)
++                      pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
++              else
+                       mempool_free(pmboxq, phba->mbox_mem_pool);
+               return;
+       }
+@@ -2020,16 +1750,17 @@
+       pmb->mbxCommand = MBX_READ_LNK_STAT;
+       pmb->mbxOwner = OWN_HOST;
+       pmboxq->context1 = NULL;
+-      pmboxq->vport = vport;
  
- static int sysfs_open_file(struct inode *inode, struct file *file)
+-      if ((vport->fc_flag & FC_OFFLINE_MODE) ||
++      if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+           (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
+               rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
+       else
+               rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+       if (rc != MBX_SUCCESS) {
+-              if (rc != MBX_TIMEOUT)
++              if (rc == MBX_TIMEOUT)
++                      pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
++              else
+                       mempool_free( pmboxq, phba->mbox_mem_pool);
+               return;
+       }
+@@ -2059,12 +1790,12 @@
+ lpfc_get_node_by_target(struct scsi_target *starget)
  {
--      struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
--      struct attribute * attr = to_attr(file->f_path.dentry);
--      struct sysfs_buffer_collection *set;
-+      struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-+      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
-       struct sysfs_buffer * buffer;
-+
-       struct sysfs_ops * ops = NULL;
--      int error = 0;
-+      int error;
+       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
++      struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
+       struct lpfc_nodelist *ndlp;
+       spin_lock_irq(shost->host_lock);
+       /* Search for this, mapped, target ID */
+-      list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
++      list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+               if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
+                   starget->id == ndlp->nlp_sid) {
+                       spin_unlock_irq(shost->host_lock);
+@@ -2154,66 +1885,8 @@
+       .get_host_fabric_name = lpfc_get_host_fabric_name,
+       .show_host_fabric_name = 1,
+-      /*
+-       * The LPFC driver treats linkdown handling as target loss events
+-       * so there are no sysfs handlers for link_down_tmo.
+-       */
+-
+-      .get_fc_host_stats = lpfc_get_stats,
+-      .reset_fc_host_stats = lpfc_reset_stats,
+-
+-      .dd_fcrport_size = sizeof(struct lpfc_rport_data),
+-      .show_rport_maxframe_size = 1,
+-      .show_rport_supported_classes = 1,
+-
+-      .set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo,
+-      .show_rport_dev_loss_tmo = 1,
+-
+-      .get_starget_port_id  = lpfc_get_starget_port_id,
+-      .show_starget_port_id = 1,
+-
+-      .get_starget_node_name = lpfc_get_starget_node_name,
+-      .show_starget_node_name = 1,
+-
+-      .get_starget_port_name = lpfc_get_starget_port_name,
+-      .show_starget_port_name = 1,
+-
+-      .issue_fc_host_lip = lpfc_issue_lip,
+-      .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk,
+-      .terminate_rport_io = lpfc_terminate_rport_io,
+-
+-      .vport_create = lpfc_vport_create,
+-      .vport_delete = lpfc_vport_delete,
+-      .dd_fcvport_size = sizeof(struct lpfc_vport *),
+-};
+-
+-struct fc_function_template lpfc_vport_transport_functions = {
+-      /* fixed attributes the driver supports */
+-      .show_host_node_name = 1,
+-      .show_host_port_name = 1,
+-      .show_host_supported_classes = 1,
+-      .show_host_supported_fc4s = 1,
+-      .show_host_supported_speeds = 1,
+-      .show_host_maxframe_size = 1,
+-
+-      /* dynamic attributes the driver supports */
+-      .get_host_port_id = lpfc_get_host_port_id,
+-      .show_host_port_id = 1,
+-
+-      .get_host_port_type = lpfc_get_host_port_type,
+-      .show_host_port_type = 1,
+-
+-      .get_host_port_state = lpfc_get_host_port_state,
+-      .show_host_port_state = 1,
+-
+-      /* active_fc4s is shown but doesn't change (thus no get function) */
+-      .show_host_active_fc4s = 1,
+-
+-      .get_host_speed = lpfc_get_host_speed,
+-      .show_host_speed = 1,
+-
+-      .get_host_fabric_name = lpfc_get_host_fabric_name,
+-      .show_host_fabric_name = 1,
++      .get_host_symbolic_name = lpfc_get_host_symbolic_name,
++      .show_host_symbolic_name = 1,
+       /*
+        * The LPFC driver treats linkdown handling as target loss events
+@@ -2242,8 +1915,6 @@
+       .issue_fc_host_lip = lpfc_issue_lip,
+       .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk,
+       .terminate_rport_io = lpfc_terminate_rport_io,
+-
+-      .vport_disable = lpfc_vport_disable,
+ };
  
--      if (!kobj || !attr)
--              goto Einval;
+ void
+@@ -2266,9 +1937,6 @@
+       lpfc_discovery_threads_init(phba, lpfc_discovery_threads);
+       lpfc_max_luns_init(phba, lpfc_max_luns);
+       lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
+-      lpfc_peer_port_login_init(phba, lpfc_peer_port_login);
+-      lpfc_npiv_enable_init(phba, lpfc_npiv_enable);
+-      lpfc_vport_restrict_login_init(phba, lpfc_vport_restrict_login);
+       lpfc_use_msi_init(phba, lpfc_use_msi);
+       lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo);
+       lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo);
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_crtn.h linux-2.6.22-570/drivers/scsi/lpfc/lpfc_crtn.h
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_crtn.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_crtn.h     2007-07-08 19:32:17.000000000 -0400
+@@ -23,114 +23,92 @@
+ struct fc_rport;
+ void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
+ void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
+-void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *);
+ int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
+                struct lpfc_dmabuf *mp);
+ void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
+-void lpfc_issue_clear_la(struct lpfc_hba *phba, struct lpfc_vport *vport);
+ void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
+-int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *, int);
++int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *);
+ void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
+ void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
+-int lpfc_reg_login(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *,
+-                 LPFC_MBOXQ_t *, uint32_t);
+-void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
+-void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
+-void lpfc_reg_vpi(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
+-void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *);
++int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_t *,
++                 uint32_t);
++void lpfc_unreg_login(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
++void lpfc_unreg_did(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
+ void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
  
--      /* Grab the module reference for this attribute if we have one */
--      if (!try_module_get(attr->owner)) {
--              error = -ENODEV;
--              goto Done;
--      }
-+      /* need attr_sr for attr and ops, its parent for kobj */
+-void lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove);
 +
-+      if (!sysfs_get_active_two(attr_sd))
-+              return -ENODEV;
-       /* if the kobject has no ktype, then we assume that it is a subsystem
-        * itself, and use ops for it.
-@@ -277,20 +267,7 @@
-        * or the subsystem have no operations.
-        */
-       if (!ops)
--              goto Eaccess;
--
--      /* make sure we have a collection to add our buffers to */
--      mutex_lock(&inode->i_mutex);
--      if (!(set = inode->i_private)) {
--              if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL))) {
--                      mutex_unlock(&inode->i_mutex);
--                      error = -ENOMEM;
--                      goto Done;
--              } else {
--                      INIT_LIST_HEAD(&set->associates);
--              }
--      }
--      mutex_unlock(&inode->i_mutex);
-+              goto err_out;
-       /* File needs write support.
-        * The inode's perms must say it's ok, 
-@@ -299,7 +276,7 @@
-       if (file->f_mode & FMODE_WRITE) {
+ int lpfc_linkdown(struct lpfc_hba *);
+ void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
  
-               if (!(inode->i_mode & S_IWUGO) || !ops->store)
--                      goto Eaccess;
-+                      goto err_out;
+ void lpfc_mbx_cmpl_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
+ void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
+-void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *);
+ void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
+ void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
+ void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
+-void lpfc_dequeue_node(struct lpfc_vport *, struct lpfc_nodelist *);
+-void lpfc_nlp_set_state(struct lpfc_vport *, struct lpfc_nodelist *, int);
+-void lpfc_drop_node(struct lpfc_vport *, struct lpfc_nodelist *);
+-void lpfc_set_disctmo(struct lpfc_vport *);
+-int  lpfc_can_disctmo(struct lpfc_vport *);
+-int  lpfc_unreg_rpi(struct lpfc_vport *, struct lpfc_nodelist *);
+-void lpfc_unreg_all_rpis(struct lpfc_vport *);
+-void lpfc_unreg_default_rpis(struct lpfc_vport *);
+-void lpfc_issue_reg_vpi(struct lpfc_hba *, struct lpfc_vport *);
+-
++void lpfc_dequeue_node(struct lpfc_hba *, struct lpfc_nodelist *);
++void lpfc_nlp_set_state(struct lpfc_hba *, struct lpfc_nodelist *, int);
++void lpfc_drop_node(struct lpfc_hba *, struct lpfc_nodelist *);
++void lpfc_set_disctmo(struct lpfc_hba *);
++int lpfc_can_disctmo(struct lpfc_hba *);
++int lpfc_unreg_rpi(struct lpfc_hba *, struct lpfc_nodelist *);
+ int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *,
+                   struct lpfc_iocbq *, struct lpfc_nodelist *);
+-void lpfc_nlp_init(struct lpfc_vport *, struct lpfc_nodelist *, uint32_t);
++void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t);
+ struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *);
+ int  lpfc_nlp_put(struct lpfc_nodelist *);
+-struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_vport *, uint32_t);
+-void lpfc_disc_list_loopmap(struct lpfc_vport *);
+-void lpfc_disc_start(struct lpfc_vport *);
+-void lpfc_disc_flush_list(struct lpfc_vport *);
+-void lpfc_cleanup_discovery_resources(struct lpfc_vport *);
++struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t);
++void lpfc_disc_list_loopmap(struct lpfc_hba *);
++void lpfc_disc_start(struct lpfc_hba *);
++void lpfc_disc_flush_list(struct lpfc_hba *);
+ void lpfc_disc_timeout(unsigned long);
  
-       }
+-struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
+-struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
++struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
++struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
  
-@@ -309,48 +286,38 @@
-        */
-       if (file->f_mode & FMODE_READ) {
-               if (!(inode->i_mode & S_IRUGO) || !ops->show)
--                      goto Eaccess;
-+                      goto err_out;
-       }
+-void lpfc_worker_wake_up(struct lpfc_hba *);
+ int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t);
+ int lpfc_do_work(void *);
+-int lpfc_disc_state_machine(struct lpfc_vport *, struct lpfc_nodelist *, void *,
++int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *,
+                           uint32_t);
  
-       /* No error? Great, allocate a buffer for the file, and store it
-        * it in file->private_data for easy access.
-        */
-+      error = -ENOMEM;
-       buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);
--      if (buffer) {
--              INIT_LIST_HEAD(&buffer->associates);
-+      if (!buffer)
-+              goto err_out;
-+
-               init_MUTEX(&buffer->sem);
-               buffer->needs_read_fill = 1;
-               buffer->ops = ops;
--              add_to_collection(buffer, inode);
-               file->private_data = buffer;
--      } else
--              error = -ENOMEM;
--      goto Done;
-- Einval:
--      error = -EINVAL;
--      goto Done;
-- Eaccess:
--      error = -EACCES;
--      module_put(attr->owner);
-- Done:
--      if (error)
--              kobject_put(kobj);
-+      /* open succeeded, put active references and pin attr_sd */
-+      sysfs_put_active_two(attr_sd);
-+      sysfs_get(attr_sd);
-+      return 0;
-+
-+ err_out:
-+      sysfs_put_active_two(attr_sd);
-       return error;
- }
+-void lpfc_register_new_vport(struct lpfc_hba *, struct lpfc_vport *,
+-                      struct lpfc_nodelist *);
+-void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *);
+-int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *,
++int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *,
+                    struct serv_parm *, uint32_t);
+-int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
+-int lpfc_els_chk_latt(struct lpfc_vport *);
++int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp);
+ int lpfc_els_abort_flogi(struct lpfc_hba *);
+-int lpfc_initial_flogi(struct lpfc_vport *);
+-int lpfc_initial_fdisc(struct lpfc_vport *);
+-int lpfc_issue_els_fdisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
+-int lpfc_issue_els_plogi(struct lpfc_vport *, uint32_t, uint8_t);
+-int lpfc_issue_els_prli(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
+-int lpfc_issue_els_adisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
+-int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
+-int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *);
+-int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t);
++int lpfc_initial_flogi(struct lpfc_hba *);
++int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t);
++int lpfc_issue_els_prli(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
++int lpfc_issue_els_adisc(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
++int lpfc_issue_els_logo(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
++int lpfc_issue_els_scr(struct lpfc_hba *, uint32_t, uint8_t);
+ int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
+-int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
+-int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
++int lpfc_els_rsp_acc(struct lpfc_hba *, uint32_t, struct lpfc_iocbq *,
+                    struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t);
+-int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
+-                      struct lpfc_nodelist *, LPFC_MBOXQ_t *);
+-int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *,
++int lpfc_els_rsp_reject(struct lpfc_hba *, uint32_t, struct lpfc_iocbq *,
+                       struct lpfc_nodelist *);
+-int lpfc_els_rsp_prli_acc(struct lpfc_vport *, struct lpfc_iocbq *,
++int lpfc_els_rsp_adisc_acc(struct lpfc_hba *, struct lpfc_iocbq *,
+                          struct lpfc_nodelist *);
+-void lpfc_cancel_retry_delay_tmo(struct lpfc_vport *, struct lpfc_nodelist *);
++int lpfc_els_rsp_prli_acc(struct lpfc_hba *, struct lpfc_iocbq *,
++                        struct lpfc_nodelist *);
++void lpfc_cancel_retry_delay_tmo(struct lpfc_hba *, struct lpfc_nodelist *);
+ void lpfc_els_retry_delay(unsigned long);
+ void lpfc_els_retry_delay_handler(struct lpfc_nodelist *);
+-void lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *);
+ void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
+                         struct lpfc_iocbq *);
+-int lpfc_els_handle_rscn(struct lpfc_vport *);
+-void lpfc_els_flush_rscn(struct lpfc_vport *);
+-int lpfc_rscn_payload_check(struct lpfc_vport *, uint32_t);
+-void lpfc_els_flush_cmd(struct lpfc_vport *);
+-int lpfc_els_disc_adisc(struct lpfc_vport *);
+-int lpfc_els_disc_plogi(struct lpfc_vport *);
++int lpfc_els_handle_rscn(struct lpfc_hba *);
++int lpfc_els_flush_rscn(struct lpfc_hba *);
++int lpfc_rscn_payload_check(struct lpfc_hba *, uint32_t);
++void lpfc_els_flush_cmd(struct lpfc_hba *);
++int lpfc_els_disc_adisc(struct lpfc_hba *);
++int lpfc_els_disc_plogi(struct lpfc_hba *);
+ void lpfc_els_timeout(unsigned long);
+-void lpfc_els_timeout_handler(struct lpfc_vport *);
+-void lpfc_hb_timeout(unsigned long);
+-void lpfc_hb_timeout_handler(struct lpfc_hba *);
++void lpfc_els_timeout_handler(struct lpfc_hba *);
  
- static int sysfs_release(struct inode * inode, struct file * filp)
- {
--      struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
--      struct attribute * attr = to_attr(filp->f_path.dentry);
--      struct module * owner = attr->owner;
--      struct sysfs_buffer * buffer = filp->private_data;
-+      struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
-+      struct sysfs_buffer *buffer = filp->private_data;
+ void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
+                        struct lpfc_iocbq *);
+-int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
+-int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
++int lpfc_ns_cmd(struct lpfc_hba *, struct lpfc_nodelist *, int);
++int lpfc_fdmi_cmd(struct lpfc_hba *, struct lpfc_nodelist *, int);
+ void lpfc_fdmi_tmo(unsigned long);
+-void lpfc_fdmi_timeout_handler(struct lpfc_vport *vport);
++void lpfc_fdmi_tmo_handler(struct lpfc_hba *);
  
--      if (buffer)
--              remove_from_collection(buffer, inode);
--      kobject_put(kobj);
--      /* After this point, attr should not be accessed. */
--      module_put(owner);
-+      sysfs_put(attr_sd);
+ int lpfc_config_port_prep(struct lpfc_hba *);
+ int lpfc_config_port_post(struct lpfc_hba *);
+@@ -158,23 +136,16 @@
+ void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *);
+ void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
+ LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
+-void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
+ int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
  
-       if (buffer) {
-               if (buffer->page)
-@@ -377,57 +344,43 @@
- static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
- {
-       struct sysfs_buffer * buffer = filp->private_data;
--      struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
--      struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata;
--      int res = 0;
+-void lpfc_config_hbq(struct lpfc_hba *, struct lpfc_hbq_init *, uint32_t ,
+-                   LPFC_MBOXQ_t *);
+-struct lpfc_hbq_entry * lpfc_sli_next_hbq_slot(struct lpfc_hba *, uint32_t);
 -
--      poll_wait(filp, &kobj->poll, wait);
-+      struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
-+      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+ int lpfc_mem_alloc(struct lpfc_hba *);
+ void lpfc_mem_free(struct lpfc_hba *);
+-void lpfc_stop_vport_timers(struct lpfc_vport *);
  
--      if (buffer->event != atomic_read(&sd->s_event)) {
--              res = POLLERR|POLLPRI;
--              buffer->needs_read_fill = 1;
--      }
-+      /* need parent for the kobj, grab both */
-+      if (!sysfs_get_active_two(attr_sd))
-+              goto trigger;
+ void lpfc_poll_timeout(unsigned long ptr);
+ void lpfc_poll_start_timer(struct lpfc_hba * phba);
+ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba);
+ struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
+ void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
+-void __lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
+ uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
  
--      return res;
--}
-+      poll_wait(filp, &kobj->poll, wait);
+ void lpfc_reset_barrier(struct lpfc_hba * phba);
+@@ -183,7 +154,6 @@
+ int lpfc_sli_brdreset(struct lpfc_hba *);
+ int lpfc_sli_brdrestart(struct lpfc_hba *);
+ int lpfc_sli_hba_setup(struct lpfc_hba *);
+-int lpfc_sli_host_down(struct lpfc_vport *);
+ int lpfc_sli_hba_down(struct lpfc_hba *);
+ int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
+ int lpfc_sli_handle_mb_event(struct lpfc_hba *);
+@@ -194,17 +164,12 @@
+ int lpfc_sli_issue_iocb(struct lpfc_hba *, struct lpfc_sli_ring *,
+                       struct lpfc_iocbq *, uint32_t);
+ void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
+-void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
++int lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
+ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
+                            struct lpfc_dmabuf *);
+ struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
+                                            struct lpfc_sli_ring *,
+                                            dma_addr_t);
+-int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t);
+-int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t);
+-void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *);
+-struct hbq_dmabuf *lpfc_sli_hbqbuf_find(struct lpfc_hba *, uint32_t);
+-int lpfc_sli_hbq_size(void);
+ int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *,
+                              struct lpfc_iocbq *);
+ int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
+@@ -215,12 +180,8 @@
+ void lpfc_mbox_timeout(unsigned long);
+ void lpfc_mbox_timeout_handler(struct lpfc_hba *);
  
-+      sysfs_put_active_two(attr_sd);
+-struct lpfc_nodelist *__lpfc_find_node(struct lpfc_vport *, node_filter,
+-                                     void *);
+-struct lpfc_nodelist *lpfc_find_node(struct lpfc_vport *, node_filter, void *);
+-struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_vport *, uint32_t);
+-struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_vport *,
+-                                       struct lpfc_name *);
++struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t);
++struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, struct lpfc_name *);
  
--static struct dentry *step_down(struct dentry *dir, const char * name)
--{
--      struct dentry * de;
-+      if (buffer->event != atomic_read(&attr_sd->s_event))
-+              goto trigger;
+ int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
+                        uint32_t timeout);
+@@ -234,56 +195,25 @@
+                            struct lpfc_iocbq * cmdiocb,
+                            struct lpfc_iocbq * rspiocb);
  
--      if (dir == NULL || dir->d_inode == NULL)
--              return NULL;
-+      return 0;
+-void *lpfc_hbq_alloc(struct lpfc_hba *, int, dma_addr_t *);
+-void lpfc_hbq_free(struct lpfc_hba *, void *, dma_addr_t);
+-void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *);
+-
+ void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
+-void __lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
+ void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
  
--      mutex_lock(&dir->d_inode->i_mutex);
--      de = lookup_one_len(name, dir, strlen(name));
--      mutex_unlock(&dir->d_inode->i_mutex);
--      dput(dir);
--      if (IS_ERR(de))
--              return NULL;
--      if (de->d_inode == NULL) {
--              dput(de);
--              return NULL;
--      }
--      return de;
-+ trigger:
-+      buffer->needs_read_fill = 1;
-+      return POLLERR|POLLPRI;
- }
+-void lpfc_in_buf_free(struct lpfc_hba *, struct lpfc_dmabuf *);
+ /* Function prototypes. */
+ const char* lpfc_info(struct Scsi_Host *);
++void lpfc_scan_start(struct Scsi_Host *);
+ int lpfc_scan_finished(struct Scsi_Host *, unsigned long);
  
--void sysfs_notify(struct kobject * k, char *dir, char *attr)
-+void sysfs_notify(struct kobject *k, char *dir, char *attr)
- {
--      struct dentry *de = k->dentry;
--      if (de)
--              dget(de);
--      if (de && dir)
--              de = step_down(de, dir);
--      if (de && attr)
--              de = step_down(de, attr);
--      if (de) {
--              struct sysfs_dirent * sd = de->d_fsdata;
--              if (sd)
-+      struct sysfs_dirent *sd = k->sd;
-+
-+      mutex_lock(&sysfs_mutex);
-+
-+      if (sd && dir)
-+              sd = sysfs_find_dirent(sd, dir);
-+      if (sd && attr)
-+              sd = sysfs_find_dirent(sd, attr);
-+      if (sd) {
-                       atomic_inc(&sd->s_event);
-               wake_up_interruptible(&k->poll);
--              dput(de);
-       }
-+
-+      mutex_unlock(&sysfs_mutex);
- }
- EXPORT_SYMBOL_GPL(sysfs_notify);
+ void lpfc_get_cfgparam(struct lpfc_hba *);
+-int lpfc_alloc_sysfs_attr(struct lpfc_vport *);
+-void lpfc_free_sysfs_attr(struct lpfc_vport *);
+-extern struct class_device_attribute *lpfc_hba_attrs[];
++int lpfc_alloc_sysfs_attr(struct lpfc_hba *);
++void lpfc_free_sysfs_attr(struct lpfc_hba *);
++extern struct class_device_attribute *lpfc_host_attrs[];
+ extern struct scsi_host_template lpfc_template;
+ extern struct fc_function_template lpfc_transport_functions;
+-extern struct fc_function_template lpfc_vport_transport_functions;
+-extern int lpfc_sli_mode;
  
-@@ -441,19 +394,30 @@
- };
+-int  lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t);
++void lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp);
+ void lpfc_terminate_rport_io(struct fc_rport *);
+ void lpfc_dev_loss_tmo_callbk(struct fc_rport *rport);
  
+-struct lpfc_vport *lpfc_create_port(struct lpfc_hba *, int, struct fc_vport *);
+-int  lpfc_vport_disable(struct fc_vport *fc_vport, bool disable);
+-void lpfc_mbx_unreg_vpi(struct lpfc_vport *);
+-void destroy_port(struct lpfc_vport *);
+-int lpfc_get_instance(void);
+-void lpfc_host_attrib_init(struct Scsi_Host *);
+-
+-extern void lpfc_debugfs_initialize(struct lpfc_vport *);
+-extern void lpfc_debugfs_terminate(struct lpfc_vport *);
+-extern void lpfc_debugfs_disc_trc(struct lpfc_vport *, int, char *, uint32_t,
+-      uint32_t, uint32_t);
+-
+-/* Interface exported by fabric iocb scheduler */
+-int lpfc_issue_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
+-void lpfc_fabric_abort_vport(struct lpfc_vport *);
+-void lpfc_fabric_abort_nport(struct lpfc_nodelist *);
+-void lpfc_fabric_abort_hba(struct lpfc_hba *);
+-void lpfc_fabric_abort_flogi(struct lpfc_hba *);
+-void lpfc_fabric_block_timeout(unsigned long);
+-void lpfc_unblock_fabric_iocbs(struct lpfc_hba *);
+-void lpfc_adjust_queue_depth(struct lpfc_hba *);
+-void lpfc_ramp_down_queue_handler(struct lpfc_hba *);
+-void lpfc_ramp_up_queue_handler(struct lpfc_hba *);
+-
+ #define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
+ #define HBA_EVENT_RSCN                   5
+ #define HBA_EVENT_LINK_UP                2
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_ct.c linux-2.6.22-570/drivers/scsi/lpfc/lpfc_ct.c
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_ct.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_ct.c       2007-07-08 19:32:17.000000000 -0400
+@@ -40,8 +40,6 @@
+ #include "lpfc_logmsg.h"
+ #include "lpfc_crtn.h"
+ #include "lpfc_version.h"
+-#include "lpfc_vport.h"
+-#include "lpfc_debugfs.h"
  
--int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
-+int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
-+                 int type)
+ #define HBA_PORTSPEED_UNKNOWN               0 /* Unknown - transceiver
+                                                * incapable of reporting */
+@@ -60,68 +58,24 @@
+ /*
+  * lpfc_ct_unsol_event
+  */
+-static void
+-lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
+-                   struct lpfc_dmabuf *mp, uint32_t size)
+-{
+-      if (!mp) {
+-              printk(KERN_ERR "%s (%d): Unsolited CT, no buffer, "
+-                     "piocbq = %p, status = x%x, mp = %p, size = %d\n",
+-                     __FUNCTION__, __LINE__,
+-                     piocbq, piocbq->iocb.ulpStatus, mp, size);
+-      }
+-
+-      printk(KERN_ERR "%s (%d): Ignoring unsolicted CT piocbq = %p, "
+-             "buffer = %p, size = %d, status = x%x\n",
+-             __FUNCTION__, __LINE__,
+-             piocbq, mp, size,
+-             piocbq->iocb.ulpStatus);
+-
+-}
+-
+-static void
+-lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
+-                        struct lpfc_dmabuf *mp, uint32_t size)
+-{
+-      if (!mp) {
+-              printk(KERN_ERR "%s (%d): Unsolited CT, no "
+-                     "HBQ buffer, piocbq = %p, status = x%x\n",
+-                     __FUNCTION__, __LINE__,
+-                     piocbq, piocbq->iocb.ulpStatus);
+-      } else {
+-              lpfc_ct_unsol_buffer(phba, piocbq, mp, size);
+-              printk(KERN_ERR "%s (%d): Ignoring unsolicted CT "
+-                     "piocbq = %p, buffer = %p, size = %d, "
+-                     "status = x%x\n",
+-                     __FUNCTION__, __LINE__,
+-                     piocbq, mp, size, piocbq->iocb.ulpStatus);
+-      }
+-}
+-
+ void
+-lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+-                  struct lpfc_iocbq *piocbq)
++lpfc_ct_unsol_event(struct lpfc_hba * phba,
++                  struct lpfc_sli_ring * pring, struct lpfc_iocbq * piocbq)
  {
--      struct sysfs_dirent * parent_sd = dir->d_fsdata;
-       umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
--      int error = -EEXIST;
-+      struct sysfs_addrm_cxt acxt;
-+      struct sysfs_dirent *sd;
  
--      mutex_lock(&dir->d_inode->i_mutex);
--      if (!sysfs_dirent_exist(parent_sd, attr->name))
--              error = sysfs_make_dirent(parent_sd, NULL, (void *)attr,
--                                        mode, type);
--      mutex_unlock(&dir->d_inode->i_mutex);
-+      sd = sysfs_new_dirent(attr->name, mode, type);
-+      if (!sd)
-+              return -ENOMEM;
-+      sd->s_elem.attr.attr = (void *)attr;
+-      struct lpfc_dmabuf *mp = NULL;
++      struct lpfc_iocbq *next_piocbq;
++      struct lpfc_dmabuf *pmbuf = NULL;
++      struct lpfc_dmabuf *matp, *next_matp;
++      uint32_t ctx = 0, size = 0, cnt = 0;
+       IOCB_t *icmd = &piocbq->iocb;
+-      int i;
+-      struct lpfc_iocbq *iocbq;
+-      dma_addr_t paddr;
+-      uint32_t size;
+-      struct lpfc_dmabuf *bdeBuf1 = piocbq->context2;
+-      struct lpfc_dmabuf *bdeBuf2 = piocbq->context3;
+-
+-      piocbq->context2 = NULL;
+-      piocbq->context3 = NULL;
++      IOCB_t *save_icmd = icmd;
++      int i, go_exit = 0;
++      struct list_head head;
+-      if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) {
+-              lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
+-      } else if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
++      if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
+               ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) {
+               /* Not enough posted buffers; Try posting more buffers */
+               phba->fc_stat.NoRcvBuf++;
+-              if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
+               lpfc_post_buffer(phba, pring, 0, 1);
+               return;
+       }
+@@ -132,56 +86,66 @@
+       if (icmd->ulpBdeCount == 0)
+               return;
  
--      return error;
-+      sysfs_addrm_start(&acxt, dir_sd);
-+
-+      if (!sysfs_find_dirent(dir_sd, attr->name)) {
-+              sysfs_add_one(&acxt, sd);
-+              sysfs_link_sibling(sd);
-+      }
+-      if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
+-              list_for_each_entry(iocbq, &piocbq->list, list) {
+-                      icmd = &iocbq->iocb;
+-                      if (icmd->ulpBdeCount == 0) {
+-                              printk(KERN_ERR "%s (%d): Unsolited CT, no "
+-                                     "BDE, iocbq = %p, status = x%x\n",
+-                                     __FUNCTION__, __LINE__,
+-                                     iocbq, iocbq->iocb.ulpStatus);
++      INIT_LIST_HEAD(&head);
++      list_add_tail(&head, &piocbq->list);
++
++      list_for_each_entry_safe(piocbq, next_piocbq, &head, list) {
++              icmd = &piocbq->iocb;
++              if (ctx == 0)
++                      ctx = (uint32_t) (icmd->ulpContext);
++              if (icmd->ulpBdeCount == 0)
+                       continue;
+-              }
+-                      size  = icmd->un.cont64[0].tus.f.bdeSize;
+-                      lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf1, size);
+-                      lpfc_in_buf_free(phba, bdeBuf1);
+-                      if (icmd->ulpBdeCount == 2) {
+-                              lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf2,
+-                                                        size);
+-                              lpfc_in_buf_free(phba, bdeBuf2);
+-                      }
++              for (i = 0; i < icmd->ulpBdeCount; i++) {
++                      matp = lpfc_sli_ringpostbuf_get(phba, pring,
++                                                      getPaddr(icmd->un.
++                                                               cont64[i].
++                                                               addrHigh,
++                                                               icmd->un.
++                                                               cont64[i].
++                                                               addrLow));
++                      if (!matp) {
++                              /* Insert lpfc log message here */
++                              lpfc_post_buffer(phba, pring, cnt, 1);
++                              go_exit = 1;
++                              goto ct_unsol_event_exit_piocbq;
++                      }
 +
-+      if (sysfs_addrm_finish(&acxt))
-+              return 0;
++                      /* Typically for Unsolicited CT requests */
++                      if (!pmbuf) {
++                              pmbuf = matp;
++                              INIT_LIST_HEAD(&pmbuf->list);
++                      } else
++                              list_add_tail(&matp->list, &pmbuf->list);
 +
-+      sysfs_put(sd);
-+      return -EEXIST;
++                      size += icmd->un.cont64[i].tus.f.bdeSize;
++                      cnt++;
+       }
+-      } else {
+-              struct lpfc_iocbq  *next;
+-              list_for_each_entry_safe(iocbq, next, &piocbq->list, list) {
+-                      icmd = &iocbq->iocb;
+-                      if (icmd->ulpBdeCount == 0) {
+-                              printk(KERN_ERR "%s (%d): Unsolited CT, no "
+-                                     "BDE, iocbq = %p, status = x%x\n",
+-                                     __FUNCTION__, __LINE__,
+-                                     iocbq, iocbq->iocb.ulpStatus);
+-                              continue;
++              icmd->ulpBdeCount = 0;
+       }
+-                      for (i = 0; i < icmd->ulpBdeCount; i++) {
+-                              paddr = getPaddr(icmd->un.cont64[i].addrHigh,
+-                                               icmd->un.cont64[i].addrLow);
+-                              mp = lpfc_sli_ringpostbuf_get(phba, pring,
+-                                                            paddr);
+-                              size = icmd->un.cont64[i].tus.f.bdeSize;
+-                              lpfc_ct_unsol_buffer(phba, piocbq, mp, size);
+-                              lpfc_in_buf_free(phba, mp);
++      lpfc_post_buffer(phba, pring, cnt, 1);
++      if (save_icmd->ulpStatus) {
++              go_exit = 1;
+                       }
+-                      list_del(&iocbq->list);
+-                      lpfc_sli_release_iocbq(phba, iocbq);
++
++ct_unsol_event_exit_piocbq:
++      list_del(&head);
++      if (pmbuf) {
++              list_for_each_entry_safe(matp, next_matp, &pmbuf->list, list) {
++                      lpfc_mbuf_free(phba, matp->virt, matp->phys);
++                      list_del(&matp->list);
++                      kfree(matp);
+               }
++              lpfc_mbuf_free(phba, pmbuf->virt, pmbuf->phys);
++              kfree(pmbuf);
+       }
++      return;
  }
  
-@@ -465,9 +429,9 @@
- int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
+ static void
+-lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
++lpfc_free_ct_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mlist)
  {
--      BUG_ON(!kobj || !kobj->dentry || !attr);
-+      BUG_ON(!kobj || !kobj->sd || !attr);
--      return sysfs_add_file(kobj->dentry, attr, SYSFS_KOBJ_ATTR);
-+      return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
+       struct lpfc_dmabuf *mlast, *next_mlast;
  
+@@ -196,7 +160,7 @@
  }
  
-@@ -481,16 +445,16 @@
- int sysfs_add_file_to_group(struct kobject *kobj,
-               const struct attribute *attr, const char *group)
- {
--      struct dentry *dir;
-+      struct sysfs_dirent *dir_sd;
-       int error;
--      dir = lookup_one_len(group, kobj->dentry, strlen(group));
--      if (IS_ERR(dir))
--              error = PTR_ERR(dir);
--      else {
--              error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR);
--              dput(dir);
--      }
-+      dir_sd = sysfs_get_dirent(kobj->sd, group);
-+      if (!dir_sd)
-+              return -ENOENT;
-+
-+      error = sysfs_add_file(dir_sd, attr, SYSFS_KOBJ_ATTR);
-+      sysfs_put(dir_sd);
-+
-       return error;
- }
- EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
-@@ -503,30 +467,31 @@
-  */
- int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
+ static struct lpfc_dmabuf *
+-lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
++lpfc_alloc_ct_rsp(struct lpfc_hba * phba, int cmdcode, struct ulp_bde64 * bpl,
+                 uint32_t size, int *entries)
  {
--      struct dentry * dir = kobj->dentry;
--      struct dentry * victim;
--      int res = -ENOENT;
--
--      mutex_lock(&dir->d_inode->i_mutex);
--      victim = lookup_one_len(attr->name, dir, strlen(attr->name));
--      if (!IS_ERR(victim)) {
--              /* make sure dentry is really there */
--              if (victim->d_inode && 
--                  (victim->d_parent->d_inode == dir->d_inode)) {
--                      victim->d_inode->i_mtime = CURRENT_TIME;
--                      fsnotify_modify(victim);
--                      res = 0;
--              } else
--                      d_drop(victim);
-+      struct sysfs_dirent *victim_sd = NULL;
-+      struct dentry *victim = NULL;
-+      int rc;
-+
-+      rc = -ENOENT;
-+      victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
-+      if (!victim_sd)
-+              goto out;
-               
--              /**
--               * Drop the reference acquired from lookup_one_len() above.
--               */
--              dput(victim);
-+      victim = sysfs_get_dentry(victim_sd);
-+      if (IS_ERR(victim)) {
-+              rc = PTR_ERR(victim);
-+              victim = NULL;
-+              goto out;
-       }
--      mutex_unlock(&dir->d_inode->i_mutex);
+       struct lpfc_dmabuf *mlist = NULL;
+@@ -217,8 +181,7 @@
  
--      return res;
-+      mutex_lock(&victim->d_inode->i_mutex);
-+      victim->d_inode->i_mtime = CURRENT_TIME;
-+      fsnotify_modify(victim);
-+      mutex_unlock(&victim->d_inode->i_mutex);
-+      rc = 0;
-+ out:
-+      dput(victim);
-+      sysfs_put(victim_sd);
-+      return rc;
- }
+               INIT_LIST_HEAD(&mp->list);
  
+-              if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT) ||
+-                  cmdcode == be16_to_cpu(SLI_CTNS_GFF_ID))
++              if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT))
+                       mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
+               else
+                       mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys));
+@@ -238,8 +201,8 @@
  
-@@ -539,30 +504,34 @@
-  */
- int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
- {
--      struct dentry *dir = kobj->dentry;
--      struct dentry *victim;
-+      struct sysfs_dirent *victim_sd = NULL;
-+      struct dentry *victim = NULL;
-       struct inode * inode;
-       struct iattr newattrs;
--      int res = -ENOENT;
-+      int rc;
-+
-+      rc = -ENOENT;
-+      victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
-+      if (!victim_sd)
-+              goto out;
-+
-+      victim = sysfs_get_dentry(victim_sd);
-+      if (IS_ERR(victim)) {
-+              rc = PTR_ERR(victim);
-+              victim = NULL;
-+              goto out;
-+      }
+               bpl->tus.f.bdeFlags = BUFF_USE_RCV;
+               /* build buffer ptr list for IOCB */
+-              bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
+-              bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
++              bpl->addrLow = le32_to_cpu( putPaddrLow(mp->phys) );
++              bpl->addrHigh = le32_to_cpu( putPaddrHigh(mp->phys) );
+               bpl->tus.f.bdeSize = (uint16_t) cnt;
+               bpl->tus.w = le32_to_cpu(bpl->tus.w);
+               bpl++;
+@@ -252,49 +215,24 @@
+       return mlist;
+ }
  
--      mutex_lock(&dir->d_inode->i_mutex);
--      victim = lookup_one_len(attr->name, dir, strlen(attr->name));
--      if (!IS_ERR(victim)) {
--              if (victim->d_inode &&
--                  (victim->d_parent->d_inode == dir->d_inode)) {
-                       inode = victim->d_inode;
-                       mutex_lock(&inode->i_mutex);
--                      newattrs.ia_mode = (mode & S_IALLUGO) |
--                                              (inode->i_mode & ~S_IALLUGO);
-+      newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
-                       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
--                      res = notify_change(victim, &newattrs);
-+      rc = notify_change(victim, &newattrs);
-                       mutex_unlock(&inode->i_mutex);
--              }
-+ out:
-               dput(victim);
+-int
+-lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb)
+-{
+-      struct lpfc_dmabuf *buf_ptr;
+-
+-      if (ctiocb->context1) {
+-              buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1;
+-              lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
+-              kfree(buf_ptr);
+-              ctiocb->context1 = NULL;
+-      }
+-      if (ctiocb->context2) {
+-              lpfc_free_ct_rsp(phba, (struct lpfc_dmabuf *) ctiocb->context2);
+-              ctiocb->context2 = NULL;
 -      }
--      mutex_unlock(&dir->d_inode->i_mutex);
 -
--      return res;
-+      sysfs_put(victim_sd);
-+      return rc;
- }
- EXPORT_SYMBOL_GPL(sysfs_chmod_file);
-@@ -577,7 +546,7 @@
- void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
+-      if (ctiocb->context3) {
+-              buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3;
+-              lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
+-              kfree(buf_ptr);
+-              ctiocb->context1 = NULL;
+-      }
+-      lpfc_sli_release_iocbq(phba, ctiocb);
+-      return 0;
+-}
+-
+ static int
+-lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
++lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp,
+            struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp,
+            void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
+                    struct lpfc_iocbq *),
+            struct lpfc_nodelist *ndlp, uint32_t usr_flg, uint32_t num_entry,
+-           uint32_t tmo, uint8_t retry)
++           uint32_t tmo)
  {
--      sysfs_hash_and_remove(kobj->dentry, attr->name);
-+      sysfs_hash_and_remove(kobj, kobj->sd, attr->name);
- }
+-      struct lpfc_hba  *phba = vport->phba;
++
+       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
+       IOCB_t *icmd;
+       struct lpfc_iocbq *geniocb;
+-      int rc;
  
+       /* Allocate buffer for  command iocb */
++      spin_lock_irq(phba->host->host_lock);
+       geniocb = lpfc_sli_get_iocbq(phba);
++      spin_unlock_irq(phba->host->host_lock);
  
-@@ -590,12 +559,12 @@
- void sysfs_remove_file_from_group(struct kobject *kobj,
-               const struct attribute *attr, const char *group)
- {
--      struct dentry *dir;
-+      struct sysfs_dirent *dir_sd;
+       if (geniocb == NULL)
+               return 1;
+@@ -334,40 +272,31 @@
+       icmd->ulpClass = CLASS3;
+       icmd->ulpContext = ndlp->nlp_rpi;
  
--      dir = lookup_one_len(group, kobj->dentry, strlen(group));
--      if (!IS_ERR(dir)) {
--              sysfs_hash_and_remove(dir, attr->name);
--              dput(dir);
-+      dir_sd = sysfs_get_dirent(kobj->sd, group);
-+      if (dir_sd) {
-+              sysfs_hash_and_remove(kobj, dir_sd, attr->name);
-+              sysfs_put(dir_sd);
+-      if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+-              /* For GEN_REQUEST64_CR, use the RPI */
+-              icmd->ulpCt_h = 0;
+-              icmd->ulpCt_l = 0;
+-      }
+-
+       /* Issue GEN REQ IOCB for NPORT <did> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0119 Issue GEN REQ IOCB to NPORT x%x "
+-                      "Data: x%x x%x\n", phba->brd_no, vport->vpi,
+-                      ndlp->nlp_DID, icmd->ulpIoTag,
+-                      vport->port_state);
++                      "%d:0119 Issue GEN REQ IOCB for NPORT x%x "
++                      "Data: x%x x%x\n", phba->brd_no, icmd->un.ulpWord[5],
++                      icmd->ulpIoTag, phba->hba_state);
+       geniocb->iocb_cmpl = cmpl;
+       geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT;
+-      geniocb->vport = vport;
+-      geniocb->retry = retry;
+-      rc = lpfc_sli_issue_iocb(phba, pring, geniocb, 0);
+-
+-      if (rc == IOCB_ERROR) {
++      spin_lock_irq(phba->host->host_lock);
++      if (lpfc_sli_issue_iocb(phba, pring, geniocb, 0) == IOCB_ERROR) {
+               lpfc_sli_release_iocbq(phba, geniocb);
++              spin_unlock_irq(phba->host->host_lock);
+               return 1;
        }
- }
- EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
-diff -Nurb linux-2.6.22-570/fs/sysfs/group.c linux-2.6.22-590/fs/sysfs/group.c
---- linux-2.6.22-570/fs/sysfs/group.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/sysfs/group.c  2008-01-02 13:56:37.000000000 -0500
-@@ -13,31 +13,29 @@
- #include <linux/dcache.h>
- #include <linux/namei.h>
- #include <linux/err.h>
--#include <linux/fs.h>
- #include <asm/semaphore.h>
- #include "sysfs.h"
++      spin_unlock_irq(phba->host->host_lock);
  
+       return 0;
+ }
  
--static void remove_files(struct dentry * dir, 
--                       const struct attribute_group * grp)
-+static void remove_files(struct kobject *kobj, struct sysfs_dirent *dir_sd,
-+                       const struct attribute_group *grp)
+ static int
+-lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp,
++lpfc_ct_cmd(struct lpfc_hba *phba, struct lpfc_dmabuf *inmp,
+           struct lpfc_dmabuf *bmp, struct lpfc_nodelist *ndlp,
+           void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
+                         struct lpfc_iocbq *),
+-          uint32_t rsp_size, uint8_t retry)
++          uint32_t rsp_size)
  {
-       struct attribute *const* attr;
+-      struct lpfc_hba  *phba = vport->phba;
+       struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt;
+       struct lpfc_dmabuf *outmp;
+       int cnt = 0, status;
+@@ -381,8 +310,8 @@
+       if (!outmp)
+               return -ENOMEM;
  
-       for (attr = grp->attrs; *attr; attr++)
--              sysfs_hash_and_remove(dir,(*attr)->name);
-+              sysfs_hash_and_remove(kobj, dir_sd, (*attr)->name);
+-      status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp, 0,
+-                            cnt+1, 0, retry);
++      status = lpfc_gen_req(phba, bmp, inmp, outmp, cmpl, ndlp, 0,
++                            cnt+1, 0);
+       if (status) {
+               lpfc_free_ct_rsp(phba, outmp);
+               return -ENOMEM;
+@@ -390,35 +319,20 @@
+       return 0;
  }
  
--static int create_files(struct dentry * dir,
--                      const struct attribute_group * grp)
-+static int create_files(struct kobject *kobj, struct sysfs_dirent *dir_sd,
-+                      const struct attribute_group *grp)
+-static struct lpfc_vport *
+-lpfc_find_vport_by_did(struct lpfc_hba *phba, uint32_t did) {
+-
+-      struct lpfc_vport *vport_curr;
+-
+-      list_for_each_entry(vport_curr, &phba->port_list, listentry) {
+-              if ((vport_curr->fc_myDID) &&
+-                      (vport_curr->fc_myDID == did))
+-                      return vport_curr;
+-      }
+-
+-      return NULL;
+-}
+-
+ static int
+-lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
++lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
  {
-       struct attribute *const* attr;
-       int error = 0;
+-      struct lpfc_hba  *phba = vport->phba;
+       struct lpfc_sli_ct_request *Response =
+               (struct lpfc_sli_ct_request *) mp->virt;
+       struct lpfc_nodelist *ndlp = NULL;
+       struct lpfc_dmabuf *mlast, *next_mp;
+       uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType;
+-      uint32_t Did, CTentry;
++      uint32_t Did;
++      uint32_t CTentry;
+       int Cnt;
+       struct list_head head;
  
--      for (attr = grp->attrs; *attr && !error; attr++) {
--              error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
--      }
-+      for (attr = grp->attrs; *attr && !error; attr++)
-+              error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
-       if (error)
--              remove_files(dir,grp);
-+              remove_files(kobj, dir_sd, grp);
-       return error;
- }
+-      lpfc_set_disctmo(vport);
+-      vport->num_disc_nodes = 0;
++      lpfc_set_disctmo(phba);
  
-@@ -45,44 +43,44 @@
- int sysfs_create_group(struct kobject * kobj, 
-                      const struct attribute_group * grp)
- {
--      struct dentry * dir;
-+      struct sysfs_dirent *sd;
-       int error;
  
--      BUG_ON(!kobj || !kobj->dentry);
-+      BUG_ON(!kobj || !kobj->sd);
+       list_add_tail(&head, &mp->list);
+@@ -436,96 +350,39 @@
  
-       if (grp->name) {
--              error = sysfs_create_subdir(kobj,grp->name,&dir);
-+              error = sysfs_create_subdir(kobj, grp->name, &sd);
-               if (error)
-                       return error;
-       } else
--              dir = kobj->dentry;
--      dir = dget(dir);
--      if ((error = create_files(dir,grp))) {
-+              sd = kobj->sd;
-+      sysfs_get(sd);
-+      error = create_files(kobj, sd, grp);
-+      if (error) {
-               if (grp->name)
--                      sysfs_remove_subdir(dir);
-+                      sysfs_remove_subdir(sd);
-       }
--      dput(dir);
-+      sysfs_put(sd);
-       return error;
- }
+               /* Loop through entire NameServer list of DIDs */
+               while (Cnt >= sizeof (uint32_t)) {
++
+                       /* Get next DID from NameServer List */
+                       CTentry = *ctptr++;
+                       Did = ((be32_to_cpu(CTentry)) & Mask_DID);
  
- void sysfs_remove_group(struct kobject * kobj, 
-                       const struct attribute_group * grp)
- {
--      struct dentry * dir;
-+      struct sysfs_dirent *dir_sd = kobj->sd;
-+      struct sysfs_dirent *sd;
+                       ndlp = NULL;
+-
+-                      /*
+-                       * Check for rscn processing or not
+-                       * To conserve rpi's, filter out addresses for other
+-                       * vports on the same physical HBAs.
+-                       */
+-                      if ((Did != vport->fc_myDID) &&
+-                          ((lpfc_find_vport_by_did(phba, Did) == NULL) ||
+-                           phba->cfg_peer_port_login)) {
+-                              if ((vport->port_type != LPFC_NPIV_PORT) ||
+-                                  (vport->fc_flag & FC_RFF_NOT_SUPPORTED) ||
+-                                  (!phba->cfg_vport_restrict_login)) {
+-                                      ndlp = lpfc_setup_disc_node(vport, Did);
++                      if (Did != phba->fc_myDID) {
++                              /* Check for rscn processing or not */
++                              ndlp = lpfc_setup_disc_node(phba, Did);
++                      }
++                      /* Mark all node table entries that are in the
++                         Nameserver */
+                       if (ndlp) {
+-                                              lpfc_debugfs_disc_trc(vport,
+-                                              LPFC_DISC_TRC_CT,
+-                                              "Parse GID_FTrsp: "
+-                                              "did:x%x flg:x%x x%x",
+-                                              Did, ndlp->nlp_flag,
+-                                              vport->fc_flag);
+-
+-                                              lpfc_printf_log(phba, KERN_INFO,
+-                                                      LOG_DISCOVERY,
+-                                                      "%d (%d):0238 Process "
+-                                                      "x%x NameServer Rsp"
+-                                                      "Data: x%x x%x x%x\n",
++                              /* NameServer Rsp */
++                              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
++                                              "%d:0238 Process x%x NameServer"
++                                              " Rsp Data: x%x x%x x%x\n",
+                                                       phba->brd_no,
+-                                                      vport->vpi, Did,
+-                                                      ndlp->nlp_flag,
+-                                                      vport->fc_flag,
+-                                                      vport->fc_rscn_id_cnt);
++                                              Did, ndlp->nlp_flag,
++                                              phba->fc_flag,
++                                              phba->fc_rscn_id_cnt);
+                       } else {
+-                                              lpfc_debugfs_disc_trc(vport,
+-                                              LPFC_DISC_TRC_CT,
+-                                              "Skip1 GID_FTrsp: "
+-                                              "did:x%x flg:x%x cnt:%d",
+-                                              Did, vport->fc_flag,
+-                                              vport->fc_rscn_id_cnt);
+-
+-                                              lpfc_printf_log(phba, KERN_INFO,
++                              /* NameServer Rsp */
++                              lpfc_printf_log(phba,
++                                              KERN_INFO,
+                                               LOG_DISCOVERY,
+-                                                      "%d (%d):0239 Skip x%x "
+-                                                      "NameServer Rsp Data: "
+-                                                      "x%x x%x\n",
++                                              "%d:0239 Skip x%x NameServer "
++                                              "Rsp Data: x%x x%x x%x\n",
+                                               phba->brd_no,
+-                                                      vport->vpi, Did,
+-                                                      vport->fc_flag,
+-                                                      vport->fc_rscn_id_cnt);
++                                              Did, Size, phba->fc_flag,
++                                              phba->fc_rscn_id_cnt);
+                       }
  
-       if (grp->name) {
--              dir = lookup_one_len_kern(grp->name, kobj->dentry,
--                              strlen(grp->name));
--              BUG_ON(IS_ERR(dir));
--      }
--      else
--              dir = dget(kobj->dentry);
-+              sd = sysfs_get_dirent(dir_sd, grp->name);
-+              BUG_ON(!sd);
-+      } else
-+              sd = sysfs_get(dir_sd);
+-                              } else {
+-                                      if (!(vport->fc_flag & FC_RSCN_MODE) ||
+-                                      (lpfc_rscn_payload_check(vport, Did))) {
+-                                              lpfc_debugfs_disc_trc(vport,
+-                                              LPFC_DISC_TRC_CT,
+-                                              "Query GID_FTrsp: "
+-                                              "did:x%x flg:x%x cnt:%d",
+-                                              Did, vport->fc_flag,
+-                                              vport->fc_rscn_id_cnt);
+-
+-                                              if (lpfc_ns_cmd(vport,
+-                                                      SLI_CTNS_GFF_ID,
+-                                                      0, Did) == 0)
+-                                                      vport->num_disc_nodes++;
+-                                      }
+-                                      else {
+-                                              lpfc_debugfs_disc_trc(vport,
+-                                              LPFC_DISC_TRC_CT,
+-                                              "Skip2 GID_FTrsp: "
+-                                              "did:x%x flg:x%x cnt:%d",
+-                                              Did, vport->fc_flag,
+-                                              vport->fc_rscn_id_cnt);
+-
+-                                              lpfc_printf_log(phba, KERN_INFO,
+-                                                      LOG_DISCOVERY,
+-                                                      "%d (%d):0245 Skip x%x "
+-                                                      "NameServer Rsp Data: "
+-                                                      "x%x x%x\n",
+-                                                      phba->brd_no,
+-                                                      vport->vpi, Did,
+-                                                      vport->fc_flag,
+-                                                      vport->fc_rscn_id_cnt);
+-                                      }
+-                              }
+-                      }
+                       if (CTentry & (be32_to_cpu(SLI_CT_LAST_ENTRY)))
+                               goto nsout1;
+                       Cnt -= sizeof (uint32_t);
+@@ -536,367 +393,188 @@
  
--      remove_files(dir,grp);
-+      remove_files(kobj, sd, grp);
-       if (grp->name)
--              sysfs_remove_subdir(dir);
--      /* release the ref. taken in this routine */
--      dput(dir);
-+              sysfs_remove_subdir(sd);
+ nsout1:
+       list_del(&head);
 +
-+      sysfs_put(sd);
++      /*
++       * The driver has cycled through all Nports in the RSCN payload.
++       * Complete the handling by cleaning up and marking the
++       * current driver state.
++       */
++      if (phba->hba_state == LPFC_HBA_READY) {
++              lpfc_els_flush_rscn(phba);
++              spin_lock_irq(phba->host->host_lock);
++              phba->fc_flag |= FC_RSCN_MODE; /* we are still in RSCN mode */
++              spin_unlock_irq(phba->host->host_lock);
++      }
+       return 0;
  }
  
++
++
++
+ static void
+-lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                      struct lpfc_iocbq *rspiocb)
++lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                      struct lpfc_iocbq * rspiocb)
+ {
+-      struct lpfc_vport *vport = cmdiocb->vport;
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+       IOCB_t *irsp;
++      struct lpfc_sli *psli;
+       struct lpfc_dmabuf *bmp;
++      struct lpfc_dmabuf *inp;
+       struct lpfc_dmabuf *outp;
++      struct lpfc_nodelist *ndlp;
+       struct lpfc_sli_ct_request *CTrsp;
+-      int rc;
  
-diff -Nurb linux-2.6.22-570/fs/sysfs/inode.c linux-2.6.22-590/fs/sysfs/inode.c
---- linux-2.6.22-570/fs/sysfs/inode.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/sysfs/inode.c  2008-01-02 13:56:37.000000000 -0500
-@@ -34,16 +34,6 @@
-       .setattr        = sysfs_setattr,
- };
++      psli = &phba->sli;
+       /* we pass cmdiocb to state machine which needs rspiocb as well */
+       cmdiocb->context_un.rsp_iocb = rspiocb;
  
--void sysfs_delete_inode(struct inode *inode)
--{
--      /* Free the shadowed directory inode operations */
--      if (sysfs_is_shadowed_inode(inode)) {
--              kfree(inode->i_op);
--              inode->i_op = NULL;
--      }
--      return generic_delete_inode(inode);
--}
++      inp = (struct lpfc_dmabuf *) cmdiocb->context1;
+       outp = (struct lpfc_dmabuf *) cmdiocb->context2;
+       bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
+-      irsp = &rspiocb->iocb;
 -
- int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
- {
-       struct inode * inode = dentry->d_inode;
-@@ -133,10 +123,8 @@
-  */
- static struct lock_class_key sysfs_inode_imutex_key;
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+-               "GID_FT cmpl:     status:x%x/x%x rtry:%d",
+-              irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry);
  
--struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
-+void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
- {
--      struct inode * inode = new_inode(sysfs_sb);
--      if (inode) {
-               inode->i_blocks = 0;
-               inode->i_mapping->a_ops = &sysfs_aops;
-               inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
-@@ -151,169 +139,81 @@
-                        */
-                       set_inode_attr(inode, sd->s_iattr);
-               } else
--                      set_default_inode_attr(inode, mode);
+-      /* Don't bother processing response if vport is being torn down. */
+-      if (vport->load_flag & FC_UNLOADING)
+-              goto out;
+-
+-
+-      if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) {
+-              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                              "%d (%d):0216 Link event during NS query\n",
+-                              phba->brd_no, vport->vpi);
+-              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
++      irsp = &rspiocb->iocb;
++      if (irsp->ulpStatus) {
++              if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
++                      ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) ||
++                       (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) {
+                       goto out;
+               }
+-      if (irsp->ulpStatus) {
+               /* Check for retry */
+-              if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
+-                      if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
+-                              (irsp->un.ulpWord[4] != IOERR_NO_RESOURCES))
+-                              vport->fc_ns_retry++;
++              if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
++                      phba->fc_ns_retry++;
+                       /* CT command is being retried */
+-                      rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
+-                                       vport->fc_ns_retry, 0);
+-                      if (rc == 0)
++                      ndlp = lpfc_findnode_did(phba, NameServer_DID);
++                      if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
++                              if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) ==
++                                  0) {
+                                       goto out;
+                               }
+-              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                      "%d (%d):0257 GID_FT Query error: 0x%x 0x%x\n",
+-                      phba->brd_no, vport->vpi, irsp->ulpStatus,
+-                      vport->fc_ns_retry);
++                      }
++              }
+       } else {
+               /* Good status, continue checking */
+               CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
+               if (CTrsp->CommandResponse.bits.CmdRsp ==
+                   be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
+                       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                                      "%d (%d):0208 NameServer Rsp "
++                                      "%d:0208 NameServer Rsp "
+                                       "Data: x%x\n",
+-                                      phba->brd_no, vport->vpi,
+-                                      vport->fc_flag);
+-                      lpfc_ns_rsp(vport, outp,
++                                      phba->brd_no,
++                                      phba->fc_flag);
++                      lpfc_ns_rsp(phba, outp,
+                                   (uint32_t) (irsp->un.genreq64.bdl.bdeSize));
+               } else if (CTrsp->CommandResponse.bits.CmdRsp ==
+                          be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
+                       /* NameServer Rsp Error */
+                       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                                      "%d (%d):0240 NameServer Rsp Error "
++                                      "%d:0240 NameServer Rsp Error "
+                                       "Data: x%x x%x x%x x%x\n",
+-                                      phba->brd_no, vport->vpi,
++                                      phba->brd_no,
+                                       CTrsp->CommandResponse.bits.CmdRsp,
+                                       (uint32_t) CTrsp->ReasonCode,
+                                       (uint32_t) CTrsp->Explanation,
+-                                      vport->fc_flag);
+-
+-                      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+-                              "GID_FT rsp err1  cmd:x%x rsn:x%x exp:x%x",
+-                              (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
+-                              (uint32_t) CTrsp->ReasonCode,
+-                              (uint32_t) CTrsp->Explanation);
+-
++                                      phba->fc_flag);
+               } else {
+                       /* NameServer Rsp Error */
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                                      "%d (%d):0241 NameServer Rsp Error "
++                      lpfc_printf_log(phba,
++                                      KERN_INFO,
++                                      LOG_DISCOVERY,
++                                      "%d:0241 NameServer Rsp Error "
+                                       "Data: x%x x%x x%x x%x\n",
+-                                      phba->brd_no, vport->vpi,
++                                      phba->brd_no,
+                                       CTrsp->CommandResponse.bits.CmdRsp,
+                                       (uint32_t) CTrsp->ReasonCode,
+                                       (uint32_t) CTrsp->Explanation,
+-                                      vport->fc_flag);
+-
+-                      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+-                              "GID_FT rsp err2  cmd:x%x rsn:x%x exp:x%x",
+-                              (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
+-                              (uint32_t) CTrsp->ReasonCode,
+-                              (uint32_t) CTrsp->Explanation);
++                                      phba->fc_flag);
+               }
+       }
+       /* Link up / RSCN discovery */
+-      if (vport->num_disc_nodes == 0) {
+-              /*
+-               * The driver has cycled through all Nports in the RSCN payload.
+-               * Complete the handling by cleaning up and marking the
+-               * current driver state.
+-               */
+-              if (vport->port_state >= LPFC_DISC_AUTH) {
+-                      if (vport->fc_flag & FC_RSCN_MODE) {
+-                              lpfc_els_flush_rscn(vport);
+-                              spin_lock_irq(shost->host_lock);
+-                              vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
+-                              spin_unlock_irq(shost->host_lock);
+-                      }
+-                      else
+-                              lpfc_els_flush_rscn(vport);
+-              }
+-
+-              lpfc_disc_start(vport);
 -      }
--      return inode;
+-out:
+-      lpfc_ct_free_iocb(phba, cmdiocb);
+-      return;
 -}
 -
--int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
--{
--      int error = 0;
--      struct inode * inode = NULL;
--      if (dentry) {
--              if (!dentry->d_inode) {
--                      struct sysfs_dirent * sd = dentry->d_fsdata;
--                      if ((inode = sysfs_new_inode(mode, sd))) {
--                              if (dentry->d_parent && dentry->d_parent->d_inode) {
--                                      struct inode *p_inode = dentry->d_parent->d_inode;
--                                      p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
--                              }
--                              goto Proceed;
--                      }
--                      else 
--                              error = -ENOMEM;
--              } else
--                      error = -EEXIST;
--      } else 
--              error = -ENOENT;
--      goto Done;
--
-- Proceed:
--      if (init)
--              error = init(inode);
--      if (!error) {
--              d_instantiate(dentry, inode);
--              if (S_ISDIR(mode))
--                      dget(dentry);  /* pin only directory dentry in core */
--      } else
--              iput(inode);
-- Done:
--      return error;
-+              set_default_inode_attr(inode, sd->s_mode);
- }
--/*
-- * Get the name for corresponding element represented by the given sysfs_dirent
-+/**
-+ *    sysfs_get_inode - get inode for sysfs_dirent
-+ *    @sd: sysfs_dirent to allocate inode for
-+ *
-+ *    Get inode for @sd.  If such inode doesn't exist, a new inode
-+ *    is allocated and basics are initialized.  New inode is
-+ *    returned locked.
-+ *
-+ *    LOCKING:
-+ *    Kernel thread context (may sleep).
-+ *
-+ *    RETURNS:
-+ *    Pointer to allocated inode on success, NULL on failure.
-  */
--const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
-+struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
- {
--      struct attribute * attr;
--      struct bin_attribute * bin_attr;
--      struct sysfs_symlink  * sl;
--
--      BUG_ON(!sd || !sd->s_element);
+-void
+-lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                      struct lpfc_iocbq *rspiocb)
+-{
+-      struct lpfc_vport *vport = cmdiocb->vport;
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      IOCB_t *irsp = &rspiocb->iocb;
+-      struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1;
+-      struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2;
+-      struct lpfc_sli_ct_request *CTrsp;
+-      int did;
+-      uint8_t fbits;
+-      struct lpfc_nodelist *ndlp;
 -
--      switch (sd->s_type) {
--              case SYSFS_DIR:
--                      /* Always have a dentry so use that */
--                      return sd->s_dentry->d_name.name;
+-      did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId;
+-      did = be32_to_cpu(did);
 -
--              case SYSFS_KOBJ_ATTR:
--                      attr = sd->s_element;
--                      return attr->name;
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+-              "GFF_ID cmpl:     status:x%x/x%x did:x%x",
+-              irsp->ulpStatus, irsp->un.ulpWord[4], did);
 -
--              case SYSFS_KOBJ_BIN_ATTR:
--                      bin_attr = sd->s_element;
--                      return bin_attr->attr.name;
+-      if (irsp->ulpStatus == IOSTAT_SUCCESS) {
+-              /* Good status, continue checking */
+-              CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
+-              fbits = CTrsp->un.gff_acc.fbits[FCP_TYPE_FEATURE_OFFSET];
 -
--              case SYSFS_KOBJ_LINK:
--                      sl = sd->s_element;
--                      return sl->link_name;
--      }
--      return NULL;
--}
-+      struct inode *inode;
--static inline void orphan_all_buffers(struct inode *node)
--{
--      struct sysfs_buffer_collection *set;
--      struct sysfs_buffer *buf;
-+      inode = iget_locked(sysfs_sb, sd->s_ino);
-+      if (inode && (inode->i_state & I_NEW))
-+              sysfs_init_inode(sd, inode);
--      mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD);
--      set = node->i_private;
--      if (set) {
--              list_for_each_entry(buf, &set->associates, associates) {
--                      down(&buf->sem);
--                      buf->orphaned = 1;
--                      up(&buf->sem);
+-              if (CTrsp->CommandResponse.bits.CmdRsp ==
+-                  be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
+-                      if ((fbits & FC4_FEATURE_INIT) &&
+-                          !(fbits & FC4_FEATURE_TARGET)) {
+-                              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                                              "%d (%d):0245 Skip x%x GFF "
+-                                              "NameServer Rsp Data: (init) "
+-                                              "x%x x%x\n", phba->brd_no,
+-                                              vport->vpi, did, fbits,
+-                                              vport->fc_rscn_id_cnt);
+-                              goto out;
+-                      }
 -              }
 -      }
--      mutex_unlock(&node->i_mutex);
-+      return inode;
+-      else {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                              "%d (%d):0267 NameServer GFF Rsp"
+-                              " x%x Error (%d %d) Data: x%x x%x\n",
+-                              phba->brd_no, vport->vpi, did,
+-                              irsp->ulpStatus, irsp->un.ulpWord[4],
+-                              vport->fc_flag, vport->fc_rscn_id_cnt)
+-      }
+-
+-      /* This is a target port, unregistered port, or the GFF_ID failed */
+-      ndlp = lpfc_setup_disc_node(vport, did);
+-      if (ndlp) {
+-              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                              "%d (%d):0242 Process x%x GFF "
+-                              "NameServer Rsp Data: x%x x%x x%x\n",
+-                              phba->brd_no, vport->vpi,
+-                              did, ndlp->nlp_flag, vport->fc_flag,
+-                              vport->fc_rscn_id_cnt);
+-      } else {
+-              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                              "%d (%d):0243 Skip x%x GFF "
+-                              "NameServer Rsp Data: x%x x%x\n",
+-                              phba->brd_no, vport->vpi, did,
+-                              vport->fc_flag, vport->fc_rscn_id_cnt);
+-      }
++      lpfc_disc_start(phba);
+ out:
+-      /* Link up / RSCN discovery */
+-      if (vport->num_disc_nodes)
+-              vport->num_disc_nodes--;
+-      if (vport->num_disc_nodes == 0) {
+-              /*
+-               * The driver has cycled through all Nports in the RSCN payload.
+-               * Complete the handling by cleaning up and marking the
+-               * current driver state.
+-               */
+-              if (vport->port_state >= LPFC_DISC_AUTH) {
+-                      if (vport->fc_flag & FC_RSCN_MODE) {
+-                              lpfc_els_flush_rscn(vport);
+-                              spin_lock_irq(shost->host_lock);
+-                              vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
+-                              spin_unlock_irq(shost->host_lock);
+-                      }
+-                      else
+-                              lpfc_els_flush_rscn(vport);
+-              }
+-              lpfc_disc_start(vport);
+-      }
+-      lpfc_ct_free_iocb(phba, cmdiocb);
++      lpfc_free_ct_rsp(phba, outp);
++      lpfc_mbuf_free(phba, inp->virt, inp->phys);
++      lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
++      kfree(inp);
++      kfree(bmp);
++      spin_lock_irq(phba->host->host_lock);
++      lpfc_sli_release_iocbq(phba, cmdiocb);
++      spin_unlock_irq(phba->host->host_lock);
+       return;
  }
  
 -
--/*
-- * Unhashes the dentry corresponding to given sysfs_dirent
-- * Called with parent inode's i_mutex held.
-+/**
-+ *    sysfs_instantiate - instantiate dentry
-+ *    @dentry: dentry to be instantiated
-+ *    @inode: inode associated with @sd
-+ *
-+ *    Unlock @inode if locked and instantiate @dentry with @inode.
-+ *
-+ *    LOCKING:
-+ *    None.
-  */
--void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
-+void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
- {
--      struct dentry *dentry = NULL;
--      struct inode *inode;
-+      BUG_ON(!dentry || dentry->d_inode);
+ static void
+-lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                      struct lpfc_iocbq *rspiocb)
++lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                      struct lpfc_iocbq * rspiocb)
+ {
+-      struct lpfc_vport *vport = cmdiocb->vport;
++      struct lpfc_sli *psli;
++      struct lpfc_dmabuf *bmp;
+       struct lpfc_dmabuf *inp;
+       struct lpfc_dmabuf *outp;
+       IOCB_t *irsp;
+       struct lpfc_sli_ct_request *CTrsp;
+-      int cmdcode, rc;
+-      uint8_t retry;
+-      uint32_t latt;
  
--      /* We're not holding a reference to ->s_dentry dentry but the
--       * field will stay valid as long as sysfs_lock is held.
--       */
--      spin_lock(&sysfs_lock);
--      spin_lock(&dcache_lock);
-+      if (inode->i_state & I_NEW)
-+              unlock_new_inode(inode);
++      psli = &phba->sli;
+       /* we pass cmdiocb to state machine which needs rspiocb as well */
+       cmdiocb->context_un.rsp_iocb = rspiocb;
  
--      /* dget dentry if it's still alive */
--      if (sd->s_dentry && sd->s_dentry->d_inode)
--              dentry = dget_locked(sd->s_dentry);
+       inp = (struct lpfc_dmabuf *) cmdiocb->context1;
+       outp = (struct lpfc_dmabuf *) cmdiocb->context2;
++      bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
+       irsp = &rspiocb->iocb;
+-      cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)->
+-                                      CommandResponse.bits.CmdRsp);
+       CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
+-      latt = lpfc_els_chk_latt(vport);
 -
--      spin_unlock(&dcache_lock);
--      spin_unlock(&sysfs_lock);
+       /* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0209 RFT request completes, latt %d, "
+-                      "ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n",
+-                      phba->brd_no, vport->vpi, latt, irsp->ulpStatus,
+-                      CTrsp->CommandResponse.bits.CmdRsp,
+-                      cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag);
 -
--      /* drop dentry */
--      if (dentry) {
--              spin_lock(&dcache_lock);
--              spin_lock(&dentry->d_lock);
--              if (!d_unhashed(dentry) && dentry->d_inode) {
--                      inode = dentry->d_inode;
--                      spin_lock(&inode->i_lock);
--                      __iget(inode);
--                      spin_unlock(&inode->i_lock);
--                      dget_locked(dentry);
--                      __d_drop(dentry);
--                      spin_unlock(&dentry->d_lock);
--                      spin_unlock(&dcache_lock);
--                      simple_unlink(parent->d_inode, dentry);
--                      orphan_all_buffers(inode);
--                      iput(inode);
--              } else {
--                      spin_unlock(&dentry->d_lock);
--                      spin_unlock(&dcache_lock);
--              }
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+-              "CT cmd cmpl:     status:x%x/x%x cmd:x%x",
+-              irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode);
 -
--              dput(dentry);
--      }
-+      d_instantiate(dentry, inode);
- }
--int sysfs_hash_and_remove(struct dentry * dir, const char * name)
-+int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent *dir_sd, const char *name)
- {
--      struct sysfs_dirent * sd;
--      struct sysfs_dirent * parent_sd;
--      int found = 0;
-+      struct sysfs_addrm_cxt acxt;
-+      struct sysfs_dirent **pos, *sd;
--      if (!dir)
-+      if (!dir_sd)
-               return -ENOENT;
--      if (dir->d_inode == NULL)
--              /* no inode means this hasn't been made visible yet */
--              return -ENOENT;
--      parent_sd = dir->d_fsdata;
--      mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
--      list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
--              if (!sd->s_element)
-+      sysfs_addrm_start(&acxt, dir_sd);
-+      if (!sysfs_resolve_for_remove(kobj, &acxt.parent_sd))
-+              goto addrm_finish;
-+
-+      for (pos = &acxt.parent_sd->s_children; *pos; pos = &(*pos)->s_sibling) {
-+              sd = *pos;
-+
-+              if (!sysfs_type(sd))
-                       continue;
--              if (!strcmp(sysfs_get_name(sd), name)) {
--                      list_del_init(&sd->s_sibling);
--                      sysfs_drop_dentry(sd, dir);
--                      sysfs_put(sd);
--                      found = 1;
-+              if (!strcmp(sd->s_name, name)) {
-+                      *pos = sd->s_sibling;
-+                      sd->s_sibling = NULL;
-+                      sysfs_remove_one(&acxt, sd);
-                       break;
-               }
-       }
--      mutex_unlock(&dir->d_inode->i_mutex);
+-      if (irsp->ulpStatus) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                      "%d (%d):0268 NS cmd %x Error (%d %d)\n",
+-                      phba->brd_no, vport->vpi, cmdcode,
+-                      irsp->ulpStatus, irsp->un.ulpWord[4]);
 -
--      return found ? 0 : -ENOENT;
-+addrm_finish:
-+      if (sysfs_addrm_finish(&acxt))
-+              return 0;
-+      return -ENOENT;
- }
-diff -Nurb linux-2.6.22-570/fs/sysfs/mount.c linux-2.6.22-590/fs/sysfs/mount.c
---- linux-2.6.22-570/fs/sysfs/mount.c  2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/sysfs/mount.c  2008-01-02 13:56:37.000000000 -0500
-@@ -17,28 +17,18 @@
- struct super_block * sysfs_sb = NULL;
- struct kmem_cache *sysfs_dir_cachep;
--static void sysfs_clear_inode(struct inode *inode);
+-              if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
+-                      ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) ||
+-                       (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED)))
+-                      goto out;
 -
- static const struct super_operations sysfs_ops = {
-       .statfs         = simple_statfs,
--      .drop_inode     = sysfs_delete_inode,
--      .clear_inode    = sysfs_clear_inode,
-+      .drop_inode     = generic_delete_inode,
- };
--static struct sysfs_dirent sysfs_root = {
--      .s_sibling      = LIST_HEAD_INIT(sysfs_root.s_sibling),
--      .s_children     = LIST_HEAD_INIT(sysfs_root.s_children),
--      .s_element      = NULL,
--      .s_type         = SYSFS_ROOT,
--      .s_iattr        = NULL,
-+struct sysfs_dirent sysfs_root = {
-+      .s_count        = ATOMIC_INIT(1),
-+      .s_flags        = SYSFS_ROOT,
-+      .s_mode         = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
-       .s_ino          = 1,
- };
--static void sysfs_clear_inode(struct inode *inode)
--{
--      kfree(inode->i_private);
--}
+-              retry = cmdiocb->retry;
+-              if (retry >= LPFC_MAX_NS_RETRY)
+-                      goto out;
 -
- static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
- {
-       struct inode *inode;
-@@ -51,17 +41,18 @@
-       sb->s_time_gran = 1;
-       sysfs_sb = sb;
--      inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
--                               &sysfs_root);
--      if (inode) {
-+      inode = new_inode(sysfs_sb);
-+      if (!inode) {
-+              pr_debug("sysfs: could not get root inode\n");
-+              return -ENOMEM;
-+      }
-+
-+      sysfs_init_inode(&sysfs_root, inode);
-+
-               inode->i_op = &sysfs_dir_inode_operations;
-               inode->i_fop = &sysfs_dir_operations;
-               /* directory inodes start off with i_nlink == 2 (for "." entry) */
-               inc_nlink(inode);
--      } else {
--              pr_debug("sysfs: could not get root inode\n");
--              return -ENOMEM;
+-              retry++;
+-              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                              "%d (%d):0216 Retrying NS cmd %x\n",
+-                              phba->brd_no, vport->vpi, cmdcode);
+-              rc = lpfc_ns_cmd(vport, cmdcode, retry, 0);
+-              if (rc == 0)
+-                      goto out;
 -      }
+-
+-out:
+-      lpfc_ct_free_iocb(phba, cmdiocb);
+-      return;
+-}
++                      "%d:0209 RFT request completes ulpStatus x%x "
++                      "CmdRsp x%x\n", phba->brd_no, irsp->ulpStatus,
++                      CTrsp->CommandResponse.bits.CmdRsp);
  
-       root = d_alloc_root(inode);
-       if (!root) {
-@@ -69,6 +60,7 @@
-               iput(inode);
-               return -ENOMEM;
-       }
-+      sysfs_root.s_dentry = root;
-       root->d_fsdata = &sysfs_root;
-       sb->s_root = root;
-       return 0;
-diff -Nurb linux-2.6.22-570/fs/sysfs/symlink.c linux-2.6.22-590/fs/sysfs/symlink.c
---- linux-2.6.22-570/fs/sysfs/symlink.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/sysfs/symlink.c        2008-01-02 13:56:37.000000000 -0500
-@@ -11,71 +11,49 @@
- #include "sysfs.h"
+-static void
+-lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                      struct lpfc_iocbq *rspiocb)
+-{
+-      lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
++      lpfc_free_ct_rsp(phba, outp);
++      lpfc_mbuf_free(phba, inp->virt, inp->phys);
++      lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
++      kfree(inp);
++      kfree(bmp);
++      spin_lock_irq(phba->host->host_lock);
++      lpfc_sli_release_iocbq(phba, cmdiocb);
++      spin_unlock_irq(phba->host->host_lock);
+       return;
+ }
  
--static int object_depth(struct kobject * kobj)
-+static int object_depth(struct sysfs_dirent *sd)
+ static void
+-lpfc_cmpl_ct_cmd_rspn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                       struct lpfc_iocbq *rspiocb)
++lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                      struct lpfc_iocbq * rspiocb)
  {
--      struct kobject * p = kobj;
-       int depth = 0;
--      do { depth++; } while ((p = p->parent));
-+
-+      for (; sd->s_parent; sd = sd->s_parent) {
-+              if (sysfs_type(sd) == SYSFS_SHADOW_DIR)
-+                      continue;
-+              depth++;
-+      }
-+
-       return depth;
+       lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
+       return;
  }
  
--static int object_path_length(struct kobject * kobj)
-+static int object_path_length(struct sysfs_dirent * sd)
+ static void
+-lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                       struct lpfc_iocbq *rspiocb)
++lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                       struct lpfc_iocbq * rspiocb)
  {
--      struct kobject * p = kobj;
-       int length = 1;
--      do {
--              length += strlen(kobject_name(p)) + 1;
--              p = p->parent;
--      } while (p);
-+
-+      for (; sd->s_parent; sd = sd->s_parent) {
-+              if (sysfs_type(sd) == SYSFS_SHADOW_DIR)
-+                      continue;
-+              length += strlen(sd->s_name) + 1;
-+      }
-+
-       return length;
+       lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
+       return;
  }
  
--static void fill_object_path(struct kobject * kobj, char * buffer, int length)
-+static void fill_object_path(struct sysfs_dirent *sd, char *buffer, int length)
+ static void
+-lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                      struct lpfc_iocbq *rspiocb)
++lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                       struct lpfc_iocbq * rspiocb)
  {
--      struct kobject * p;
+-      IOCB_t *irsp = &rspiocb->iocb;
+-      struct lpfc_vport *vport = cmdiocb->vport;
 -
-+      int cur;
-       --length;
--      for (p = kobj; p; p = p->parent) {
--              int cur = strlen(kobject_name(p));
-+      for (; sd->s_parent; sd = sd->s_parent) {
-+              if (sysfs_type(sd) == SYSFS_SHADOW_DIR)
-+                      continue;
-+
-+              cur = strlen(sd->s_name);
-               /* back up enough to print this bus id with '/' */
-               length -= cur;
--              strncpy(buffer + length,kobject_name(p),cur);
-+              strncpy(buffer + length, sd->s_name, cur);
-               *(buffer + --length) = '/';
-       }
+-      if (irsp->ulpStatus != IOSTAT_SUCCESS)
+-          vport->fc_flag |= FC_RFF_NOT_SUPPORTED;
+-
+       lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
+       return;
  }
  
--static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target)
+-int
+-lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol,
+-      size_t size)
 -{
--      struct sysfs_dirent * parent_sd = parent->d_fsdata;
--      struct sysfs_symlink * sl;
--      int error = 0;
--
--      error = -ENOMEM;
--      sl = kmalloc(sizeof(*sl), GFP_KERNEL);
--      if (!sl)
--              goto exit1;
+-      int n;
+-      uint8_t *wwn = vport->phba->wwpn;
 -
--      sl->link_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
--      if (!sl->link_name)
--              goto exit2;
+-      n = snprintf(symbol, size,
+-                   "Emulex PPN-%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+-                   wwn[0], wwn[1], wwn[2], wwn[3],
+-                   wwn[4], wwn[5], wwn[6], wwn[7]);
 -
--      strcpy(sl->link_name, name);
--      sl->target_kobj = kobject_get(target);
+-      if (vport->port_type == LPFC_PHYSICAL_PORT)
+-              return n;
 -
--      error = sysfs_make_dirent(parent_sd, NULL, sl, S_IFLNK|S_IRWXUGO,
--                              SYSFS_KOBJ_LINK);
--      if (!error)
--              return 0;
+-      if (n < size)
+-              n += snprintf(symbol + n, size - n, " VPort-%d", vport->vpi);
 -
--      kobject_put(target);
--      kfree(sl->link_name);
--exit2:
--      kfree(sl);
--exit1:
--      return error;
+-      if (n < size && vport->vname)
+-              n += snprintf(symbol + n, size - n, " VName-%s", vport->vname);
+-      return n;
 -}
 -
- /**
-  *    sysfs_create_link - create symlink between two objects.
-  *    @kobj:  object whose directory we're creating the link in.
-@@ -84,29 +62,80 @@
+-int
+-lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
+-      size_t size)
++void
++lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp)
+ {
+       char fwrev[16];
+-      int n;
+-      lpfc_decode_firmware_rev(vport->phba, fwrev, 0);
++      lpfc_decode_firmware_rev(phba, fwrev, 0);
+-      n = snprintf(symbol, size, "Emulex %s FV%s DV%s",
+-              vport->phba->ModelName, fwrev, lpfc_release_version);
+-      return n;
++      sprintf(symbp, "Emulex %s FV%s DV%s", phba->ModelName,
++              fwrev, lpfc_release_version);
++      return;
+ }
+ /*
+@@ -907,76 +585,55 @@
+  *       LI_CTNS_RFT_ID
   */
- int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
+ int
+-lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
+-          uint8_t retry, uint32_t context)
++lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
  {
--      struct dentry *dentry = NULL;
--      int error = -EEXIST;
-+      struct sysfs_dirent *parent_sd = NULL;
-+      struct sysfs_dirent *target_sd = NULL;
-+      struct sysfs_dirent *sd = NULL;
-+      struct sysfs_addrm_cxt acxt;
-+      int error;
+-      struct lpfc_nodelist * ndlp;
+-      struct lpfc_hba *phba = vport->phba;
+       struct lpfc_dmabuf *mp, *bmp;
+       struct lpfc_sli_ct_request *CtReq;
+       struct ulp_bde64 *bpl;
+       void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
+                     struct lpfc_iocbq *) = NULL;
+       uint32_t rsp_size = 1024;
+-      size_t   size;
+-      int rc = 0;
+-
+-      ndlp = lpfc_findnode_did(vport, NameServer_DID);
+-      if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) {
+-              rc=1;
+-              goto ns_cmd_exit;
+-      }
  
-       BUG_ON(!name);
+       /* fill in BDEs for command */
+       /* Allocate buffer for command payload */
+       mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
+-      if (!mp) {
+-              rc=2;
++      if (!mp)
+               goto ns_cmd_exit;
+-      }
  
-       if (!kobj) {
-               if (sysfs_mount && sysfs_mount->mnt_sb)
--                      dentry = sysfs_mount->mnt_sb->s_root;
-+                      parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
-       } else
--              dentry = kobj->dentry;
-+              parent_sd = kobj->sd;
-+
-+      error = -EFAULT;
-+      if (!parent_sd)
-+              goto out_put;
-+
-+      /* target->sd can go away beneath us but is protected with
-+       * sysfs_assoc_lock.  Fetch target_sd from it.
-+       */
-+      spin_lock(&sysfs_assoc_lock);
-+      if (target->sd)
-+              target_sd = sysfs_get(target->sd);
-+      spin_unlock(&sysfs_assoc_lock);
-+
-+      error = -ENOENT;
-+      if (!target_sd)
-+              goto out_put;
-+
-+      error = -ENOMEM;
-+      sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
-+      if (!sd)
-+              goto out_put;
-+      sd->s_elem.symlink.target_sd = target_sd;
-+
-+      sysfs_addrm_start(&acxt, parent_sd);
-+      if (!sysfs_resolve_for_create(target, &acxt.parent_sd))
-+              goto addrm_finish;
-+
-+      if (!sysfs_find_dirent(acxt.parent_sd, name)) {
-+              sysfs_add_one(&acxt, sd);
-+              sysfs_link_sibling(sd);
-+      }
+       INIT_LIST_HEAD(&mp->list);
+       mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
+-      if (!mp->virt) {
+-              rc=3;
++      if (!mp->virt)
+               goto ns_cmd_free_mp;
+-      }
  
--      if (!dentry)
--              return -EFAULT;
-+addrm_finish:
-+      if (sysfs_addrm_finish(&acxt))
-+              return 0;
+       /* Allocate buffer for Buffer ptr list */
+       bmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
+-      if (!bmp) {
+-              rc=4;
++      if (!bmp)
+               goto ns_cmd_free_mpvirt;
+-      }
  
--      mutex_lock(&dentry->d_inode->i_mutex);
--      if (!sysfs_dirent_exist(dentry->d_fsdata, name))
--              error = sysfs_add_link(dentry, name, target);
--      mutex_unlock(&dentry->d_inode->i_mutex);
-+      error = -EEXIST;
-+      /* fall through */
-+ out_put:
-+      sysfs_put(target_sd);
-+      sysfs_put(sd);
-       return error;
- }
+       INIT_LIST_HEAD(&bmp->list);
+       bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys));
+-      if (!bmp->virt) {
+-              rc=5;
++      if (!bmp->virt)
+               goto ns_cmd_free_bmp;
+-      }
  
+       /* NameServer Req */
+-      lpfc_printf_log(phba, KERN_INFO ,LOG_DISCOVERY,
+-                      "%d (%d):0236 NameServer Req Data: x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, cmdcode, vport->fc_flag,
+-                      vport->fc_rscn_id_cnt);
++      lpfc_printf_log(phba,
++                      KERN_INFO,
++                      LOG_DISCOVERY,
++                      "%d:0236 NameServer Req Data: x%x x%x x%x\n",
++                      phba->brd_no, cmdcode, phba->fc_flag,
++                      phba->fc_rscn_id_cnt);
  
- /**
-+ *    sysfs_delete_link - remove symlink in object's directory.
-+ *    @kobj:  object we're acting for.
-+ *    @targ:  object we're pointing to.
-+ *    @name:  name of the symlink to remove.
-+ *
-+ *    Unlike sysfs_remove_link sysfs_delete_link has enough information
-+ *    to successfully delete symlinks in shadow directories.
-+ */
-+void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
-+                      const char *name)
-+{
-+      sysfs_hash_and_remove(targ, kobj->sd, name);
-+}
+       bpl = (struct ulp_bde64 *) bmp->virt;
+       memset(bpl, 0, sizeof(struct ulp_bde64));
+-      bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
+-      bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
++      bpl->addrHigh = le32_to_cpu( putPaddrHigh(mp->phys) );
++      bpl->addrLow = le32_to_cpu( putPaddrLow(mp->phys) );
+       bpl->tus.f.bdeFlags = 0;
+       if (cmdcode == SLI_CTNS_GID_FT)
+               bpl->tus.f.bdeSize = GID_REQUEST_SZ;
+-      else if (cmdcode == SLI_CTNS_GFF_ID)
+-              bpl->tus.f.bdeSize = GFF_REQUEST_SZ;
+       else if (cmdcode == SLI_CTNS_RFT_ID)
+               bpl->tus.f.bdeSize = RFT_REQUEST_SZ;
+       else if (cmdcode == SLI_CTNS_RNN_ID)
+               bpl->tus.f.bdeSize = RNN_REQUEST_SZ;
+-      else if (cmdcode == SLI_CTNS_RSPN_ID)
+-              bpl->tus.f.bdeSize = RSPN_REQUEST_SZ;
+       else if (cmdcode == SLI_CTNS_RSNN_NN)
+               bpl->tus.f.bdeSize = RSNN_REQUEST_SZ;
+       else if (cmdcode == SLI_CTNS_RFF_ID)
+@@ -997,78 +654,56 @@
+               CtReq->CommandResponse.bits.CmdRsp =
+                   be16_to_cpu(SLI_CTNS_GID_FT);
+               CtReq->un.gid.Fc4Type = SLI_CTPT_FCP;
+-              if (vport->port_state < LPFC_NS_QRY)
+-                      vport->port_state = LPFC_NS_QRY;
+-              lpfc_set_disctmo(vport);
++              if (phba->hba_state < LPFC_HBA_READY)
++                      phba->hba_state = LPFC_NS_QRY;
++              lpfc_set_disctmo(phba);
+               cmpl = lpfc_cmpl_ct_cmd_gid_ft;
+               rsp_size = FC_MAX_NS_RSP;
+               break;
+-      case SLI_CTNS_GFF_ID:
+-              CtReq->CommandResponse.bits.CmdRsp =
+-                      be16_to_cpu(SLI_CTNS_GFF_ID);
+-              CtReq->un.gff.PortId = be32_to_cpu(context);
+-              cmpl = lpfc_cmpl_ct_cmd_gff_id;
+-              break;
+-
+       case SLI_CTNS_RFT_ID:
+               CtReq->CommandResponse.bits.CmdRsp =
+                   be16_to_cpu(SLI_CTNS_RFT_ID);
+-              CtReq->un.rft.PortId = be32_to_cpu(vport->fc_myDID);
++              CtReq->un.rft.PortId = be32_to_cpu(phba->fc_myDID);
+               CtReq->un.rft.fcpReg = 1;
+               cmpl = lpfc_cmpl_ct_cmd_rft_id;
+               break;
++      case SLI_CTNS_RFF_ID:
++              CtReq->CommandResponse.bits.CmdRsp =
++                      be16_to_cpu(SLI_CTNS_RFF_ID);
++              CtReq->un.rff.PortId = be32_to_cpu(phba->fc_myDID);
++              CtReq->un.rff.feature_res = 0;
++              CtReq->un.rff.feature_tgt = 0;
++              CtReq->un.rff.type_code = FC_FCP_DATA;
++              CtReq->un.rff.feature_init = 1;
++              cmpl = lpfc_cmpl_ct_cmd_rff_id;
++              break;
 +
-+/**
-  *    sysfs_remove_link - remove symlink in object's directory.
-  *    @kobj:  object we're acting for.
-  *    @name:  name of the symlink to remove.
-@@ -114,17 +143,33 @@
+       case SLI_CTNS_RNN_ID:
+               CtReq->CommandResponse.bits.CmdRsp =
+                   be16_to_cpu(SLI_CTNS_RNN_ID);
+-              CtReq->un.rnn.PortId = be32_to_cpu(vport->fc_myDID);
+-              memcpy(CtReq->un.rnn.wwnn,  &vport->fc_nodename,
++              CtReq->un.rnn.PortId = be32_to_cpu(phba->fc_myDID);
++              memcpy(CtReq->un.rnn.wwnn,  &phba->fc_nodename,
+                      sizeof (struct lpfc_name));
+               cmpl = lpfc_cmpl_ct_cmd_rnn_id;
+               break;
  
- void sysfs_remove_link(struct kobject * kobj, const char * name)
- {
--      sysfs_hash_and_remove(kobj->dentry,name);
-+      sysfs_hash_and_remove(kobj, kobj->sd, name);
+-      case SLI_CTNS_RSPN_ID:
+-              CtReq->CommandResponse.bits.CmdRsp =
+-                  be16_to_cpu(SLI_CTNS_RSPN_ID);
+-              CtReq->un.rspn.PortId = be32_to_cpu(vport->fc_myDID);
+-              size = sizeof(CtReq->un.rspn.symbname);
+-              CtReq->un.rspn.len =
+-                      lpfc_vport_symbolic_port_name(vport,
+-                      CtReq->un.rspn.symbname, size);
+-              cmpl = lpfc_cmpl_ct_cmd_rspn_id;
+-              break;
+       case SLI_CTNS_RSNN_NN:
+               CtReq->CommandResponse.bits.CmdRsp =
+                   be16_to_cpu(SLI_CTNS_RSNN_NN);
+-              memcpy(CtReq->un.rsnn.wwnn, &vport->fc_nodename,
++              memcpy(CtReq->un.rsnn.wwnn, &phba->fc_nodename,
+                      sizeof (struct lpfc_name));
+-              size = sizeof(CtReq->un.rsnn.symbname);
+-              CtReq->un.rsnn.len =
+-                      lpfc_vport_symbolic_node_name(vport,
+-                      CtReq->un.rsnn.symbname, size);
++              lpfc_get_hba_sym_node_name(phba, CtReq->un.rsnn.symbname);
++              CtReq->un.rsnn.len = strlen(CtReq->un.rsnn.symbname);
+               cmpl = lpfc_cmpl_ct_cmd_rsnn_nn;
+               break;
+-      case SLI_CTNS_RFF_ID:
+-              vport->fc_flag &= ~FC_RFF_NOT_SUPPORTED;
+-              CtReq->CommandResponse.bits.CmdRsp =
+-                  be16_to_cpu(SLI_CTNS_RFF_ID);
+-              CtReq->un.rff.PortId = be32_to_cpu(vport->fc_myDID);;
+-              CtReq->un.rff.fbits = FC4_FEATURE_INIT;
+-              CtReq->un.rff.type_code = FC_FCP_DATA;
+-              cmpl = lpfc_cmpl_ct_cmd_rff_id;
+-              break;
+       }
+-      if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) {
++      if (!lpfc_ct_cmd(phba, mp, bmp, ndlp, cmpl, rsp_size))
+               /* On success, The cmpl function will free the buffers */
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+-                      "Issue CT cmd:    cmd:x%x did:x%x",
+-                      cmdcode, ndlp->nlp_DID, 0);
+               return 0;
+-      }
+-      rc=6;
+       lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
+ ns_cmd_free_bmp:
+       kfree(bmp);
+@@ -1077,17 +712,14 @@
+ ns_cmd_free_mp:
+       kfree(mp);
+ ns_cmd_exit:
+-      lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-              "%d (%d):0266 Issue NameServer Req x%x err %d Data: x%x x%x\n",
+-                      phba->brd_no, vport->vpi, cmdcode, rc, vport->fc_flag,
+-                      vport->fc_rscn_id_cnt);
+       return 1;
  }
  
--static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
--                               char *path)
-+/**
-+ *    sysfs_rename_link - rename symlink in object's directory.
-+ *    @kobj:  object we're acting for.
-+ *    @targ:  object we're pointing to.
-+ *    @old:   previous name of the symlink.
-+ *    @new:   new name of the symlink.
-+ *
-+ *    A helper function for the common rename symlink idiom.
-+ */
-+int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
-+                      const char *old, const char *new)
-+{
-+      sysfs_delete_link(kobj, targ, old);
-+      return sysfs_create_link(kobj, targ, new);
-+}
+ static void
+-lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                    struct lpfc_iocbq * rspiocb)
++lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba,
++                    struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb)
+ {
++      struct lpfc_dmabuf *bmp = cmdiocb->context3;
+       struct lpfc_dmabuf *inp = cmdiocb->context1;
+       struct lpfc_dmabuf *outp = cmdiocb->context2;
+       struct lpfc_sli_ct_request *CTrsp = outp->virt;
+@@ -1095,60 +727,48 @@
+       struct lpfc_nodelist *ndlp;
+       uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
+       uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
+-      struct lpfc_vport *vport = cmdiocb->vport;
+-      IOCB_t *irsp = &rspiocb->iocb;
+-      uint32_t latt;
+-
+-      latt = lpfc_els_chk_latt(vport);
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+-              "FDMI cmpl:       status:x%x/x%x latt:%d",
+-              irsp->ulpStatus, irsp->un.ulpWord[4], latt);
+-      if (latt || irsp->ulpStatus) {
+-              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                              "%d (%d):0229 FDMI cmd %04x failed, latt = %d "
+-                              "ulpStatus: x%x, rid x%x\n",
+-                              phba->brd_no, vport->vpi,
+-                              be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus,
+-                              irsp->un.ulpWord[4]);
+-              lpfc_ct_free_iocb(phba, cmdiocb);
+-              return;
+-      }
+-
+-      ndlp = lpfc_findnode_did(vport, FDMI_DID);
++      ndlp = lpfc_findnode_did(phba, FDMI_DID);
+       if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
+               /* FDMI rsp failed */
+-              lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                              "%d (%d):0220 FDMI rsp failed Data: x%x\n",
+-                              phba->brd_no, vport->vpi,
++              lpfc_printf_log(phba,
++                              KERN_INFO,
++                              LOG_DISCOVERY,
++                              "%d:0220 FDMI rsp failed Data: x%x\n",
++                              phba->brd_no,
+                              be16_to_cpu(fdmi_cmd));
+       }
+       switch (be16_to_cpu(fdmi_cmd)) {
+       case SLI_MGMT_RHBA:
+-              lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA);
++              lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_RPA);
+               break;
+       case SLI_MGMT_RPA:
+               break;
+       case SLI_MGMT_DHBA:
+-              lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT);
++              lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DPRT);
+               break;
+       case SLI_MGMT_DPRT:
+-              lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA);
++              lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_RHBA);
+               break;
+       }
+-      lpfc_ct_free_iocb(phba, cmdiocb);
 +
-+static int sysfs_get_target_path(struct sysfs_dirent * parent_sd,
-+                               struct sysfs_dirent * target_sd, char *path)
++      lpfc_free_ct_rsp(phba, outp);
++      lpfc_mbuf_free(phba, inp->virt, inp->phys);
++      lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
++      kfree(inp);
++      kfree(bmp);
++      spin_lock_irq(phba->host->host_lock);
++      lpfc_sli_release_iocbq(phba, cmdiocb);
++      spin_unlock_irq(phba->host->host_lock);
+       return;
+ }
+-
+ int
+-lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode)
++lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
  {
-       char * s;
-       int depth, size;
+-      struct lpfc_hba *phba = vport->phba;
+       struct lpfc_dmabuf *mp, *bmp;
+       struct lpfc_sli_ct_request *CtReq;
+       struct ulp_bde64 *bpl;
+@@ -1185,10 +805,12 @@
+       INIT_LIST_HEAD(&bmp->list);
  
--      depth = object_depth(kobj);
--      size = object_path_length(target) + depth * 3 - 1;
-+      depth = object_depth(parent_sd);
-+      size = object_path_length(target_sd) + depth * 3 - 1;
-       if (size > PATH_MAX)
-               return -ENAMETOOLONG;
+       /* FDMI request */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0218 FDMI Request Data: x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, vport->fc_flag,
+-                      vport->port_state, cmdcode);
++      lpfc_printf_log(phba,
++                      KERN_INFO,
++                      LOG_DISCOVERY,
++                      "%d:0218 FDMI Request Data: x%x x%x x%x\n",
++                      phba->brd_no,
++                     phba->fc_flag, phba->hba_state, cmdcode);
  
-@@ -133,7 +178,7 @@
-       for (s = path; depth--; s += 3)
-               strcpy(s,"../");
+       CtReq = (struct lpfc_sli_ct_request *) mp->virt;
  
--      fill_object_path(target, path, size);
-+      fill_object_path(target_sd, path, size);
-       pr_debug("%s: path = '%s'\n", __FUNCTION__, path);
+@@ -1211,11 +833,11 @@
+                           be16_to_cpu(SLI_MGMT_RHBA);
+                       CtReq->CommandResponse.bits.Size = 0;
+                       rh = (REG_HBA *) & CtReq->un.PortID;
+-                      memcpy(&rh->hi.PortName, &vport->fc_sparam.portName,
++                      memcpy(&rh->hi.PortName, &phba->fc_sparam.portName,
+                              sizeof (struct lpfc_name));
+                       /* One entry (port) per adapter */
+                       rh->rpl.EntryCnt = be32_to_cpu(1);
+-                      memcpy(&rh->rpl.pe, &vport->fc_sparam.portName,
++                      memcpy(&rh->rpl.pe, &phba->fc_sparam.portName,
+                              sizeof (struct lpfc_name));
  
-       return 0;
-@@ -141,27 +186,16 @@
+                       /* point to the HBA attribute block */
+@@ -1231,7 +853,7 @@
+                       ae->ad.bits.AttrType = be16_to_cpu(NODE_NAME);
+                       ae->ad.bits.AttrLen =  be16_to_cpu(FOURBYTES
+                                               + sizeof (struct lpfc_name));
+-                      memcpy(&ae->un.NodeName, &vport->fc_sparam.nodeName,
++                      memcpy(&ae->un.NodeName, &phba->fc_sparam.nodeName,
+                              sizeof (struct lpfc_name));
+                       ab->EntryCnt++;
+                       size += FOURBYTES + sizeof (struct lpfc_name);
+@@ -1369,7 +991,7 @@
+                       pab = (REG_PORT_ATTRIBUTE *) & CtReq->un.PortID;
+                       size = sizeof (struct lpfc_name) + FOURBYTES;
+                       memcpy((uint8_t *) & pab->PortName,
+-                             (uint8_t *) & vport->fc_sparam.portName,
++                             (uint8_t *) & phba->fc_sparam.portName,
+                              sizeof (struct lpfc_name));
+                       pab->ab.EntryCnt = 0;
  
- static int sysfs_getlink(struct dentry *dentry, char * path)
- {
--      struct kobject *kobj, *target_kobj;
--      int error = 0;
--
--      kobj = sysfs_get_kobject(dentry->d_parent);
--      if (!kobj)
--              return -EINVAL;
--
--      target_kobj = sysfs_get_kobject(dentry);
--      if (!target_kobj) {
--              kobject_put(kobj);
--              return -EINVAL;
--      }
-+      struct sysfs_dirent *sd = dentry->d_fsdata;
-+      struct sysfs_dirent *parent_sd = sd->s_parent;
-+      struct sysfs_dirent *target_sd = sd->s_elem.symlink.target_sd;
-+      int error;
-+
-+      mutex_lock(&sysfs_mutex);
-+      error = sysfs_get_target_path(parent_sd, target_sd, path);
-+      mutex_unlock(&sysfs_mutex);
+@@ -1431,7 +1053,7 @@
+                       ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size);
+                       ae->ad.bits.AttrType = be16_to_cpu(MAX_FRAME_SIZE);
+                       ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4);
+-                      hsp = (struct serv_parm *) & vport->fc_sparam;
++                      hsp = (struct serv_parm *) & phba->fc_sparam;
+                       ae->un.MaxFrameSize =
+                           (((uint32_t) hsp->cmn.
+                             bbRcvSizeMsb) << 8) | (uint32_t) hsp->cmn.
+@@ -1475,7 +1097,7 @@
+               CtReq->CommandResponse.bits.Size = 0;
+               pe = (PORT_ENTRY *) & CtReq->un.PortID;
+               memcpy((uint8_t *) & pe->PortName,
+-                     (uint8_t *) & vport->fc_sparam.portName,
++                     (uint8_t *) & phba->fc_sparam.portName,
+                      sizeof (struct lpfc_name));
+               size = GID_REQUEST_SZ - 4 + sizeof (struct lpfc_name);
+               break;
+@@ -1485,22 +1107,22 @@
+               CtReq->CommandResponse.bits.Size = 0;
+               pe = (PORT_ENTRY *) & CtReq->un.PortID;
+               memcpy((uint8_t *) & pe->PortName,
+-                     (uint8_t *) & vport->fc_sparam.portName,
++                     (uint8_t *) & phba->fc_sparam.portName,
+                      sizeof (struct lpfc_name));
+               size = GID_REQUEST_SZ - 4 + sizeof (struct lpfc_name);
+               break;
+       }
  
--      down_read(&sysfs_rename_sem);
--      error = sysfs_get_target_path(kobj, target_kobj, path);
--      up_read(&sysfs_rename_sem);
--      
--      kobject_put(kobj);
--      kobject_put(target_kobj);
-       return error;
--
- }
+       bpl = (struct ulp_bde64 *) bmp->virt;
+-      bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
+-      bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
++      bpl->addrHigh = le32_to_cpu( putPaddrHigh(mp->phys) );
++      bpl->addrLow = le32_to_cpu( putPaddrLow(mp->phys) );
+       bpl->tus.f.bdeFlags = 0;
+       bpl->tus.f.bdeSize = size;
+       bpl->tus.w = le32_to_cpu(bpl->tus.w);
  
- static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
-diff -Nurb linux-2.6.22-570/fs/sysfs/sysfs.h linux-2.6.22-590/fs/sysfs/sysfs.h
---- linux-2.6.22-570/fs/sysfs/sysfs.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/sysfs/sysfs.h  2008-01-02 13:56:37.000000000 -0500
-@@ -1,9 +1,40 @@
-+struct sysfs_elem_dir {
-+      struct kobject          * kobj;
-+};
-+
-+struct sysfs_elem_symlink {
-+      struct sysfs_dirent     * target_sd;
-+};
-+
-+struct sysfs_elem_attr {
-+      struct attribute        * attr;
-+};
-+
-+struct sysfs_elem_bin_attr {
-+      struct bin_attribute    * bin_attr;
-+};
-+
-+/*
-+ * As long as s_count reference is held, the sysfs_dirent itself is
-+ * accessible.  Dereferencing s_elem or any other outer entity
-+ * requires s_active reference.
-+ */
- struct sysfs_dirent {
-       atomic_t                s_count;
--      struct list_head        s_sibling;
--      struct list_head        s_children;
--      void                    * s_element;
--      int                     s_type;
-+      atomic_t                s_active;
-+      struct sysfs_dirent     * s_parent;
-+      struct sysfs_dirent     * s_sibling;
-+      struct sysfs_dirent     * s_children;
-+      const char              * s_name;
-+
-+      union {
-+              struct sysfs_elem_dir           dir;
-+              struct sysfs_elem_symlink       symlink;
-+              struct sysfs_elem_attr          attr;
-+              struct sysfs_elem_bin_attr      bin_attr;
-+      }                       s_elem;
-+
-+      unsigned int            s_flags;
-       umode_t                 s_mode;
-       ino_t                   s_ino;
-       struct dentry           * s_dentry;
-@@ -11,30 +42,77 @@
-       atomic_t                s_event;
- };
+       cmpl = lpfc_cmpl_ct_cmd_fdmi;
  
-+#define SD_DEACTIVATED_BIAS   INT_MIN
-+
-+struct sysfs_addrm_cxt {
-+      struct sysfs_dirent     *parent_sd;
-+      struct inode            *parent_inode;
-+      struct sysfs_dirent     *removed;
-+      int                     cnt;
-+};
-+
-+/*
-+ * A sysfs file which deletes another file when written to need to
-+ * write lock the s_active of the victim while its s_active is read
-+ * locked for the write operation.  Tell lockdep that this is okay.
-+ */
-+enum sysfs_s_active_class
-+{
-+      SYSFS_S_ACTIVE_NORMAL,          /* file r/w access, etc - default */
-+      SYSFS_S_ACTIVE_DEACTIVATE,      /* file deactivation */
-+};
-+
- extern struct vfsmount * sysfs_mount;
-+extern struct sysfs_dirent sysfs_root;
- extern struct kmem_cache *sysfs_dir_cachep;
+-      if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0))
++      if (!lpfc_ct_cmd(phba, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP))
+               return 0;
  
--extern void sysfs_delete_inode(struct inode *inode);
--extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
--extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
--
--extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
--extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
--                              umode_t, int);
--
--extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
--extern int sysfs_hash_and_remove(struct dentry * dir, const char * name);
-+extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
-+extern void sysfs_link_sibling(struct sysfs_dirent *sd);
-+extern void sysfs_unlink_sibling(struct sysfs_dirent *sd);
-+
-+extern int sysfs_resolve_for_create(struct kobject *kobj,
-+                                  struct sysfs_dirent **parent_sd);
-+extern int sysfs_resolve_for_remove(struct kobject *kobj,
-+                                  struct sysfs_dirent **parent_sd);
-+
-+extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
-+extern void sysfs_put_active(struct sysfs_dirent *sd);
-+extern struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
-+extern void sysfs_put_active_two(struct sysfs_dirent *sd);
-+extern void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
-+                            struct sysfs_dirent *parent_sd);
-+extern void sysfs_add_one(struct sysfs_addrm_cxt *acxt,
-+                        struct sysfs_dirent *sd);
-+extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt,
-+                           struct sysfs_dirent *sd);
-+extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
-+
-+extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode);
-+extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd);
-+extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode);
-+
-+extern void release_sysfs_dirent(struct sysfs_dirent * sd);
-+extern struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
-+                                            const unsigned char *name);
-+extern struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
-+                                           const unsigned char *name);
-+extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode,
-+                                           int type);
-+
-+extern int sysfs_add_file(struct sysfs_dirent *dir_sd,
-+                        const struct attribute *attr, int type);
-+extern int sysfs_hash_and_remove(struct kobject *kobj,
-+                               struct sysfs_dirent *dir_sd, const char *name);
- extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
+       lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
+@@ -1512,50 +1134,49 @@
+       kfree(mp);
+ fdmi_cmd_exit:
+       /* Issue FDMI request failed */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0244 Issue FDMI request failed Data: x%x\n",
+-                      phba->brd_no, vport->vpi, cmdcode);
++      lpfc_printf_log(phba,
++                      KERN_INFO,
++                      LOG_DISCOVERY,
++                      "%d:0244 Issue FDMI request failed Data: x%x\n",
++                      phba->brd_no,
++                      cmdcode);
+       return 1;
+ }
+ void
+ lpfc_fdmi_tmo(unsigned long ptr)
+ {
+-      struct lpfc_vport *vport = (struct lpfc_vport *)ptr;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
+       unsigned long iflag;
  
--extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
--extern void sysfs_remove_subdir(struct dentry *);
-+extern int sysfs_create_subdir(struct kobject *kobj, const char *name,
-+                             struct sysfs_dirent **p_sd);
-+extern void sysfs_remove_subdir(struct sysfs_dirent *sd);
+-      spin_lock_irqsave(&vport->work_port_lock, iflag);
+-      if (!(vport->work_port_events & WORKER_FDMI_TMO)) {
+-              vport->work_port_events |= WORKER_FDMI_TMO;
+-              spin_unlock_irqrestore(&vport->work_port_lock, iflag);
+-
+-              spin_lock_irqsave(&phba->hbalock, iflag);
++      spin_lock_irqsave(phba->host->host_lock, iflag);
++      if (!(phba->work_hba_events & WORKER_FDMI_TMO)) {
++              phba->work_hba_events |= WORKER_FDMI_TMO;
+               if (phba->work_wait)
+-                      lpfc_worker_wake_up(phba);
+-              spin_unlock_irqrestore(&phba->hbalock, iflag);
++                      wake_up(phba->work_wait);
+       }
+-      else
+-              spin_unlock_irqrestore(&vport->work_port_lock, iflag);
++      spin_unlock_irqrestore(phba->host->host_lock,iflag);
+ }
  
--extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
--extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
- extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
+ void
+-lpfc_fdmi_timeout_handler(struct lpfc_vport *vport)
++lpfc_fdmi_tmo_handler(struct lpfc_hba *phba)
+ {
+       struct lpfc_nodelist *ndlp;
  
--extern spinlock_t sysfs_lock;
--extern struct rw_semaphore sysfs_rename_sem;
-+extern spinlock_t sysfs_assoc_lock;
-+extern struct mutex sysfs_mutex;
- extern struct super_block * sysfs_sb;
- extern const struct file_operations sysfs_dir_operations;
- extern const struct file_operations sysfs_file_operations;
-@@ -42,73 +120,9 @@
- extern const struct inode_operations sysfs_dir_inode_operations;
- extern const struct inode_operations sysfs_symlink_inode_operations;
+-      ndlp = lpfc_findnode_did(vport, FDMI_DID);
++      ndlp = lpfc_findnode_did(phba, FDMI_DID);
+       if (ndlp) {
+-              if (init_utsname()->nodename[0] != '\0')
+-                      lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
+-              else
+-                      mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60);
++              if (init_utsname()->nodename[0] != '\0') {
++                      lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA);
++              } else {
++                      mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60);
++              }
+       }
+       return;
+ }
  
--struct sysfs_symlink {
--      char * link_name;
--      struct kobject * target_kobj;
--};
++
+ void
+-lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
++lpfc_decode_firmware_rev(struct lpfc_hba * phba, char *fwrevision, int flag)
+ {
+       struct lpfc_sli *psli = &phba->sli;
+       lpfc_vpd_t *vp = &phba->vpd;
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_debugfs.c linux-2.6.22-570/drivers/scsi/lpfc/lpfc_debugfs.c
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_debugfs.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_debugfs.c  1969-12-31 19:00:00.000000000 -0500
+@@ -1,508 +0,0 @@
+-/*******************************************************************
+- * This file is part of the Emulex Linux Device Driver for         *
+- * Fibre Channel Host Bus Adapters.                                *
+- * Copyright (C) 2007 Emulex.  All rights reserved.                *
+- * EMULEX and SLI are trademarks of Emulex.                        *
+- * www.emulex.com                                                  *
+- *                                                                 *
+- * This program is free software; you can redistribute it and/or   *
+- * modify it under the terms of version 2 of the GNU General       *
+- * Public License as published by the Free Software Foundation.    *
+- * This program is distributed in the hope that it will be useful. *
+- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
+- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
+- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
+- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+- * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
+- * more details, a copy of which can be found in the file COPYING  *
+- * included with this package.                                     *
+- *******************************************************************/
 -
--struct sysfs_buffer {
--      struct list_head                associates;
--      size_t                          count;
--      loff_t                          pos;
--      char                            * page;
--      struct sysfs_ops                * ops;
--      struct semaphore                sem;
--      int                             orphaned;
--      int                             needs_read_fill;
--      int                             event;
--};
+-#include <linux/blkdev.h>
+-#include <linux/delay.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/idr.h>
+-#include <linux/interrupt.h>
+-#include <linux/kthread.h>
+-#include <linux/pci.h>
+-#include <linux/spinlock.h>
+-#include <linux/ctype.h>
+-#include <linux/version.h>
+-
+-#include <scsi/scsi.h>
+-#include <scsi/scsi_device.h>
+-#include <scsi/scsi_host.h>
+-#include <scsi/scsi_transport_fc.h>
+-
+-#include "lpfc_hw.h"
+-#include "lpfc_sli.h"
+-#include "lpfc_disc.h"
+-#include "lpfc_scsi.h"
+-#include "lpfc.h"
+-#include "lpfc_logmsg.h"
+-#include "lpfc_crtn.h"
+-#include "lpfc_vport.h"
+-#include "lpfc_version.h"
+-#include "lpfc_vport.h"
+-#include "lpfc_debugfs.h"
+-
+-#ifdef CONFIG_LPFC_DEBUG_FS
+-/* debugfs interface
+- *
+- * To access this interface the user should:
+- * # mkdir /debug
+- * # mount -t debugfs none /debug
+- *
+- * The lpfc debugfs directory hierachy is:
+- * lpfc/lpfcX/vportY
+- * where X is the lpfc hba unique_id
+- * where Y is the vport VPI on that hba
+- *
+- * Debugging services available per vport:
+- * discovery_trace
+- * This is an ACSII readable file that contains a trace of the last
+- * lpfc_debugfs_max_disc_trc events that happened on a specific vport.
+- * See lpfc_debugfs.h for different categories of
+- * discovery events. To enable the discovery trace, the following
+- * module parameters must be set:
+- * lpfc_debugfs_enable=1         Turns on lpfc debugfs filesystem support
+- * lpfc_debugfs_max_disc_trc=X   Where X is the event trace depth for
+- *                               EACH vport. X MUST also be a power of 2.
+- * lpfc_debugfs_mask_disc_trc=Y  Where Y is an event mask as defined in
+- *                               lpfc_debugfs.h .
+- */
+-static int lpfc_debugfs_enable = 0;
+-module_param(lpfc_debugfs_enable, int, 0);
+-MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services");
+-
+-static int lpfc_debugfs_max_disc_trc = 0;  /* This MUST be a power of 2 */
+-module_param(lpfc_debugfs_max_disc_trc, int, 0);
+-MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc,
+-      "Set debugfs discovery trace depth");
+-
+-static int lpfc_debugfs_mask_disc_trc = 0;
+-module_param(lpfc_debugfs_mask_disc_trc, int, 0);
+-MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
+-      "Set debugfs discovery trace mask");
 -
--struct sysfs_buffer_collection {
--      struct list_head        associates;
+-#include <linux/debugfs.h>
+-
+-/* size of discovery_trace output line */
+-#define LPFC_DISC_TRC_ENTRY_SIZE 80
+-
+-/* nodelist output buffer size */
+-#define LPFC_NODELIST_SIZE 8192
+-#define LPFC_NODELIST_ENTRY_SIZE 120
+-
+-struct lpfc_debug {
+-      char *buffer;
+-      int  len;
 -};
 -
--static inline struct kobject * to_kobj(struct dentry * dentry)
+-atomic_t lpfc_debugfs_disc_trc_cnt = ATOMIC_INIT(0);
+-unsigned long lpfc_debugfs_start_time = 0L;
+-
+-static int
+-lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
 -{
--      struct sysfs_dirent * sd = dentry->d_fsdata;
--      return ((struct kobject *) sd->s_element);
+-      int i, index, len, enable;
+-      uint32_t ms;
+-      struct lpfc_disc_trc *dtp;
+-      char buffer[80];
+-
+-
+-      enable = lpfc_debugfs_enable;
+-      lpfc_debugfs_enable = 0;
+-
+-      len = 0;
+-      index = (atomic_read(&vport->disc_trc_cnt) + 1) &
+-              (lpfc_debugfs_max_disc_trc - 1);
+-      for (i = index; i < lpfc_debugfs_max_disc_trc; i++) {
+-              dtp = vport->disc_trc + i;
+-              if (!dtp->fmt)
+-                      continue;
+-              ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
+-              snprintf(buffer, 80, "%010d:%010d ms:%s\n",
+-                      dtp->seq_cnt, ms, dtp->fmt);
+-              len +=  snprintf(buf+len, size-len, buffer,
+-                      dtp->data1, dtp->data2, dtp->data3);
+-      }
+-      for (i = 0; i < index; i++) {
+-              dtp = vport->disc_trc + i;
+-              if (!dtp->fmt)
+-                      continue;
+-              ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
+-              snprintf(buffer, 80, "%010d:%010d ms:%s\n",
+-                      dtp->seq_cnt, ms, dtp->fmt);
+-              len +=  snprintf(buf+len, size-len, buffer,
+-                      dtp->data1, dtp->data2, dtp->data3);
+-      }
+-
+-      lpfc_debugfs_enable = enable;
+-      return len;
 -}
 -
--static inline struct attribute * to_attr(struct dentry * dentry)
+-static int
+-lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
 -{
--      struct sysfs_dirent * sd = dentry->d_fsdata;
--      return ((struct attribute *) sd->s_element);
+-      int len = 0;
+-      int cnt;
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_nodelist *ndlp;
+-      unsigned char *statep, *name;
+-
+-      cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
+-
+-      spin_lock_irq(shost->host_lock);
+-      list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
+-              if (!cnt) {
+-                      len +=  snprintf(buf+len, size-len,
+-                              "Missing Nodelist Entries\n");
+-                      break;
+-              }
+-              cnt--;
+-              switch (ndlp->nlp_state) {
+-              case NLP_STE_UNUSED_NODE:
+-                      statep = "UNUSED";
+-                      break;
+-              case NLP_STE_PLOGI_ISSUE:
+-                      statep = "PLOGI ";
+-                      break;
+-              case NLP_STE_ADISC_ISSUE:
+-                      statep = "ADISC ";
+-                      break;
+-              case NLP_STE_REG_LOGIN_ISSUE:
+-                      statep = "REGLOG";
+-                      break;
+-              case NLP_STE_PRLI_ISSUE:
+-                      statep = "PRLI  ";
+-                      break;
+-              case NLP_STE_UNMAPPED_NODE:
+-                      statep = "UNMAP ";
+-                      break;
+-              case NLP_STE_MAPPED_NODE:
+-                      statep = "MAPPED";
+-                      break;
+-              case NLP_STE_NPR_NODE:
+-                      statep = "NPR   ";
+-                      break;
+-              default:
+-                      statep = "UNKNOWN";
+-              }
+-              len +=  snprintf(buf+len, size-len, "%s DID:x%06x ",
+-                      statep, ndlp->nlp_DID);
+-              name = (unsigned char *)&ndlp->nlp_portname;
+-              len +=  snprintf(buf+len, size-len,
+-                      "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
+-                      *name, *(name+1), *(name+2), *(name+3),
+-                      *(name+4), *(name+5), *(name+6), *(name+7));
+-              name = (unsigned char *)&ndlp->nlp_nodename;
+-              len +=  snprintf(buf+len, size-len,
+-                      "WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
+-                      *name, *(name+1), *(name+2), *(name+3),
+-                      *(name+4), *(name+5), *(name+6), *(name+7));
+-              len +=  snprintf(buf+len, size-len, "RPI:%03d flag:x%08x ",
+-                      ndlp->nlp_rpi, ndlp->nlp_flag);
+-              if (!ndlp->nlp_type)
+-                      len +=  snprintf(buf+len, size-len, "UNKNOWN_TYPE");
+-              if (ndlp->nlp_type & NLP_FC_NODE)
+-                      len +=  snprintf(buf+len, size-len, "FC_NODE ");
+-              if (ndlp->nlp_type & NLP_FABRIC)
+-                      len +=  snprintf(buf+len, size-len, "FABRIC ");
+-              if (ndlp->nlp_type & NLP_FCP_TARGET)
+-                      len +=  snprintf(buf+len, size-len, "FCP_TGT sid:%d ",
+-                              ndlp->nlp_sid);
+-              if (ndlp->nlp_type & NLP_FCP_INITIATOR)
+-                      len +=  snprintf(buf+len, size-len, "FCP_INITIATOR");
+-              len +=  snprintf(buf+len, size-len, "\n");
+-      }
+-      spin_unlock_irq(shost->host_lock);
+-      return len;
 -}
+-#endif
 -
--static inline struct bin_attribute * to_bin_attr(struct dentry * dentry)
+-
+-inline void
+-lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
+-      uint32_t data1, uint32_t data2, uint32_t data3)
 -{
--      struct sysfs_dirent * sd = dentry->d_fsdata;
--      return ((struct bin_attribute *) sd->s_element);
+-#ifdef CONFIG_LPFC_DEBUG_FS
+-      struct lpfc_disc_trc *dtp;
+-      int index;
+-
+-      if (!(lpfc_debugfs_mask_disc_trc & mask))
+-              return;
+-
+-      if (!lpfc_debugfs_enable || !lpfc_debugfs_max_disc_trc ||
+-              !vport || !vport->disc_trc)
+-              return;
+-
+-      index = atomic_inc_return(&vport->disc_trc_cnt) &
+-              (lpfc_debugfs_max_disc_trc - 1);
+-      dtp = vport->disc_trc + index;
+-      dtp->fmt = fmt;
+-      dtp->data1 = data1;
+-      dtp->data2 = data2;
+-      dtp->data3 = data3;
+-      dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_disc_trc_cnt);
+-      dtp->jif = jiffies;
+-#endif
+-      return;
 -}
 -
--static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
-+static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
- {
--      struct kobject * kobj = NULL;
+-#ifdef CONFIG_LPFC_DEBUG_FS
+-static int
+-lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
+-{
+-      struct lpfc_vport *vport = inode->i_private;
+-      struct lpfc_debug *debug;
+-      int size;
+-      int rc = -ENOMEM;
 -
--      spin_lock(&dcache_lock);
--      if (!d_unhashed(dentry)) {
--              struct sysfs_dirent * sd = dentry->d_fsdata;
--              if (sd->s_type & SYSFS_KOBJ_LINK) {
--                      struct sysfs_symlink * sl = sd->s_element;
--                      kobj = kobject_get(sl->target_kobj);
--              } else
--                      kobj = kobject_get(sd->s_element);
+-      if (!lpfc_debugfs_max_disc_trc) {
+-               rc = -ENOSPC;
+-              goto out;
 -      }
--      spin_unlock(&dcache_lock);
 -
--      return kobj;
+-      debug = kmalloc(sizeof(*debug), GFP_KERNEL);
+-      if (!debug)
+-              goto out;
+-
+-      /* Round to page boundry */
+-      size =  (lpfc_debugfs_max_disc_trc * LPFC_DISC_TRC_ENTRY_SIZE);
+-      size = PAGE_ALIGN(size);
+-
+-      debug->buffer = kmalloc(size, GFP_KERNEL);
+-      if (!debug->buffer) {
+-              kfree(debug);
+-              goto out;
+-      }
+-
+-      debug->len = lpfc_debugfs_disc_trc_data(vport, debug->buffer, size);
+-      file->private_data = debug;
+-
+-      rc = 0;
+-out:
+-      return rc;
 -}
 -
--static inline void release_sysfs_dirent(struct sysfs_dirent * sd)
+-static int
+-lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
 -{
--      if (sd->s_type & SYSFS_KOBJ_LINK) {
--              struct sysfs_symlink * sl = sd->s_element;
--              kfree(sl->link_name);
--              kobject_put(sl->target_kobj);
--              kfree(sl);
+-      struct lpfc_vport *vport = inode->i_private;
+-      struct lpfc_debug *debug;
+-      int rc = -ENOMEM;
+-
+-      debug = kmalloc(sizeof(*debug), GFP_KERNEL);
+-      if (!debug)
+-              goto out;
+-
+-      /* Round to page boundry */
+-      debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL);
+-      if (!debug->buffer) {
+-              kfree(debug);
+-              goto out;
 -      }
--      kfree(sd->s_iattr);
--      kmem_cache_free(sysfs_dir_cachep, sd);
-+      return sd->s_flags & SYSFS_TYPE_MASK;
- }
- static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
-@@ -122,11 +136,6 @@
- static inline void sysfs_put(struct sysfs_dirent * sd)
- {
--      if (atomic_dec_and_test(&sd->s_count))
-+      if (sd && atomic_dec_and_test(&sd->s_count))
-               release_sysfs_dirent(sd);
- }
 -
--static inline int sysfs_is_shadowed_inode(struct inode *inode)
+-      debug->len = lpfc_debugfs_nodelist_data(vport, debug->buffer,
+-              LPFC_NODELIST_SIZE);
+-      file->private_data = debug;
+-
+-      rc = 0;
+-out:
+-      return rc;
+-}
+-
+-static loff_t
+-lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
 -{
--      return S_ISDIR(inode->i_mode) && inode->i_op->follow_link;
+-      struct lpfc_debug *debug;
+-      loff_t pos = -1;
+-
+-      debug = file->private_data;
+-
+-      switch (whence) {
+-      case 0:
+-              pos = off;
+-              break;
+-      case 1:
+-              pos = file->f_pos + off;
+-              break;
+-      case 2:
+-              pos = debug->len - off;
+-      }
+-      return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos);
 -}
-diff -Nurb linux-2.6.22-570/fs/unionfs/Makefile linux-2.6.22-590/fs/unionfs/Makefile
---- linux-2.6.22-570/fs/unionfs/Makefile       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/Makefile       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,7 @@
-+obj-$(CONFIG_UNION_FS) += unionfs.o
-+
-+unionfs-y := subr.o dentry.o file.o inode.o main.o super.o \
-+      rdstate.o copyup.o dirhelper.o rename.o unlink.o \
-+      lookup.o commonfops.o dirfops.o sioq.o mmap.o
-+
-+unionfs-$(CONFIG_UNION_FS_XATTR) += xattr.o
-diff -Nurb linux-2.6.22-570/fs/unionfs/commonfops.c linux-2.6.22-590/fs/unionfs/commonfops.c
---- linux-2.6.22-570/fs/unionfs/commonfops.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/commonfops.c   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,748 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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 "union.h"
-+
-+/*
-+ * 1) Copyup the file
-+ * 2) Rename the file to '.unionfs<original inode#><counter>' - obviously
-+ * stolen from NFS's silly rename
-+ */
-+static int copyup_deleted_file(struct file *file, struct dentry *dentry,
-+                             int bstart, int bindex)
-+{
-+      static unsigned int counter;
-+      const int i_inosize = sizeof(dentry->d_inode->i_ino) * 2;
-+      const int countersize = sizeof(counter) * 2;
-+      const int nlen = sizeof(".unionfs") + i_inosize + countersize - 1;
-+      char name[nlen + 1];
-+
-+      int err;
-+      struct dentry *tmp_dentry = NULL;
-+      struct dentry *hidden_dentry;
-+      struct dentry *hidden_dir_dentry = NULL;
-+
-+      hidden_dentry = unionfs_lower_dentry_idx(dentry, bstart);
-+
-+      sprintf(name, ".unionfs%*.*lx",
-+              i_inosize, i_inosize, hidden_dentry->d_inode->i_ino);
-+
-+retry:
-+      /*
-+       * Loop, looking for an unused temp name to copyup to.
-+       *
-+       * It's somewhat silly that we look for a free temp tmp name in the
-+       * source branch (bstart) instead of the dest branch (bindex), where
-+       * the final name will be created.  We _will_ catch it if somehow
-+       * the name exists in the dest branch, but it'd be nice to catch it
-+       * sooner than later.
-+       */
-+      tmp_dentry = NULL;
-+      do {
-+              char *suffix = name + nlen - countersize;
-+
-+              dput(tmp_dentry);
-+              counter++;
-+              sprintf(suffix, "%*.*x", countersize, countersize, counter);
-+
-+              printk(KERN_DEBUG "unionfs: trying to rename %s to %s\n",
-+                     dentry->d_name.name, name);
-+
-+              tmp_dentry = lookup_one_len(name, hidden_dentry->d_parent,
-+                                          nlen);
-+              if (IS_ERR(tmp_dentry)) {
-+                      err = PTR_ERR(tmp_dentry);
-+                      goto out;
-+              }
-+      } while (tmp_dentry->d_inode != NULL);  /* need negative dentry */
-+      dput(tmp_dentry);
-+
-+      err = copyup_named_file(dentry->d_parent->d_inode, file, name, bstart,
-+                              bindex, file->f_dentry->d_inode->i_size);
-+      if (err == -EEXIST)
-+              goto retry;
-+      else if (err)
-+              goto out;
-+
-+      /* bring it to the same state as an unlinked file */
-+      hidden_dentry = unionfs_lower_dentry_idx(dentry, dbstart(dentry));
-+      hidden_dir_dentry = lock_parent(hidden_dentry);
-+      err = vfs_unlink(hidden_dir_dentry->d_inode, hidden_dentry);
-+      unlock_dir(hidden_dir_dentry);
-+
-+out:
-+      return err;
-+}
-+
-+/*
-+ * put all references held by upper struct file and free lower file pointer
-+ * array
-+ */
-+static void cleanup_file(struct file *file)
-+{
-+      int bindex, bstart, bend;
-+      struct file **lf;
-+      struct super_block *sb = file->f_dentry->d_sb;
-+
-+      lf = UNIONFS_F(file)->lower_files;
-+      bstart = fbstart(file);
-+      bend = fbend(file);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              if (unionfs_lower_file_idx(file, bindex)) {
-+                      /*
-+                       * Find new index of matching branch with an open
-+                       * file, since branches could have been added or
-+                       * deleted causing the one with open files to shift.
-+                       */
-+                      int i;  /* holds (possibly) updated branch index */
-+                      int old_bid;
-+
-+                      old_bid = UNIONFS_F(file)->saved_branch_ids[bindex];
-+                      i = branch_id_to_idx(sb, old_bid);
-+                      if (i < 0)
-+                              printk(KERN_ERR "unionfs: no superblock for "
-+                                     "file %p\n", file);
-+                      else {
-+                              /* decrement count of open files */
-+                              branchput(sb, i);
-+                              /*
-+                               * fput will perform an mntput for us on the
-+                               * correct branch.  Although we're using the
-+                               * file's old branch configuration, bindex,
-+                               * which is the old index, correctly points
-+                               * to the right branch in the file's branch
-+                               * list.  In other words, we're going to
-+                               * mntput the correct branch even if
-+                               * branches have been added/removed.
-+                               */
-+                              fput(unionfs_lower_file_idx(file, bindex));
-+                      }
-+              }
-+      }
-+
-+      UNIONFS_F(file)->lower_files = NULL;
-+      kfree(lf);
-+      kfree(UNIONFS_F(file)->saved_branch_ids);
-+      /* set to NULL because caller needs to know if to kfree on error */
-+      UNIONFS_F(file)->saved_branch_ids = NULL;
-+}
-+
-+/* open all lower files for a given file */
-+static int open_all_files(struct file *file)
-+{
-+      int bindex, bstart, bend, err = 0;
-+      struct file *hidden_file;
-+      struct dentry *hidden_dentry;
-+      struct dentry *dentry = file->f_dentry;
-+      struct super_block *sb = dentry->d_sb;
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!hidden_dentry)
-+                      continue;
-+
-+              dget(hidden_dentry);
-+              unionfs_mntget(dentry, bindex);
-+              branchget(sb, bindex);
-+
-+              hidden_file =
-+                      dentry_open(hidden_dentry,
-+                                  unionfs_lower_mnt_idx(dentry, bindex),
-+                                  file->f_flags);
-+              if (IS_ERR(hidden_file)) {
-+                      err = PTR_ERR(hidden_file);
-+                      goto out;
-+              } else
-+                      unionfs_set_lower_file_idx(file, bindex, hidden_file);
-+      }
-+out:
-+      return err;
-+}
-+
-+/* open the highest priority file for a given upper file */
-+static int open_highest_file(struct file *file, int willwrite)
-+{
-+      int bindex, bstart, bend, err = 0;
-+      struct file *hidden_file;
-+      struct dentry *hidden_dentry;
-+
-+      struct dentry *dentry = file->f_dentry;
-+      struct inode *parent_inode = dentry->d_parent->d_inode;
-+      struct super_block *sb = dentry->d_sb;
-+      size_t inode_size = dentry->d_inode->i_size;
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+
-+      hidden_dentry = unionfs_lower_dentry(dentry);
-+      if (willwrite && IS_WRITE_FLAG(file->f_flags) && is_robranch(dentry)) {
-+              for (bindex = bstart - 1; bindex >= 0; bindex--) {
-+                      err = copyup_file(parent_inode, file, bstart, bindex,
-+                                        inode_size);
-+                      if (!err)
-+                              break;
-+              }
-+              atomic_set(&UNIONFS_F(file)->generation,
-+                         atomic_read(&UNIONFS_I(dentry->d_inode)->
-+                                     generation));
-+              goto out;
-+      }
-+
-+      dget(hidden_dentry);
-+      unionfs_mntget(dentry, bstart);
-+      branchget(sb, bstart);
-+      hidden_file = dentry_open(hidden_dentry,
-+                                unionfs_lower_mnt_idx(dentry, bstart),
-+                                file->f_flags);
-+      if (IS_ERR(hidden_file)) {
-+              err = PTR_ERR(hidden_file);
-+              goto out;
-+      }
-+      unionfs_set_lower_file(file, hidden_file);
-+      /* Fix up the position. */
-+      hidden_file->f_pos = file->f_pos;
-+
-+      memcpy(&hidden_file->f_ra, &file->f_ra, sizeof(struct file_ra_state));
-+out:
-+      return err;
-+}
-+
-+/* perform a delayed copyup of a read-write file on a read-only branch */
-+static int do_delayed_copyup(struct file *file, struct dentry *dentry)
-+{
-+      int bindex, bstart, bend, err = 0;
-+      struct inode *parent_inode = dentry->d_parent->d_inode;
-+      loff_t inode_size = file->f_dentry->d_inode->i_size;
-+
-+      bstart = fbstart(file);
-+      bend = fbend(file);
-+
-+      BUG_ON(!S_ISREG(file->f_dentry->d_inode->i_mode));
-+
-+      for (bindex = bstart - 1; bindex >= 0; bindex--) {
-+              if (!d_deleted(file->f_dentry))
-+                      err = copyup_file(parent_inode, file, bstart,
-+                                        bindex, inode_size);
-+              else
-+                      err = copyup_deleted_file(file, dentry, bstart,
-+                                                bindex);
-+
-+              if (!err)
-+                      break;
-+      }
-+      if (!err && (bstart > fbstart(file))) {
-+              bend = fbend(file);
-+              for (bindex = bstart; bindex <= bend; bindex++) {
-+                      if (unionfs_lower_file_idx(file, bindex)) {
-+                              branchput(dentry->d_sb, bindex);
-+                              fput(unionfs_lower_file_idx(file, bindex));
-+                              unionfs_set_lower_file_idx(file, bindex, NULL);
-+                      }
-+              }
-+              fbend(file) = bend;
-+      }
-+      return err;
-+}
-+
-+/*
-+ * Revalidate the struct file
-+ * @file: file to revalidate
-+ * @willwrite: 1 if caller may cause changes to the file; 0 otherwise.
-+ */
-+int unionfs_file_revalidate(struct file *file, int willwrite)
-+{
-+      struct super_block *sb;
-+      struct dentry *dentry;
-+      int sbgen, fgen, dgen;
-+      int bstart, bend;
-+      int size;
-+
-+      int err = 0;
-+
-+      dentry = file->f_dentry;
-+      unionfs_lock_dentry(dentry);
-+      sb = dentry->d_sb;
-+
-+      /*
-+       * First revalidate the dentry inside struct file,
-+       * but not unhashed dentries.
-+       */
-+      if (!d_deleted(dentry) &&
-+          !__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out_nofree;
-+      }
-+
-+      sbgen = atomic_read(&UNIONFS_SB(sb)->generation);
-+      dgen = atomic_read(&UNIONFS_D(dentry)->generation);
-+      fgen = atomic_read(&UNIONFS_F(file)->generation);
-+
-+      BUG_ON(sbgen > dgen);
-+
-+      /*
-+       * There are two cases we are interested in.  The first is if the
-+       * generation is lower than the super-block.  The second is if
-+       * someone has copied up this file from underneath us, we also need
-+       * to refresh things.
-+       */
-+      if (!d_deleted(dentry) &&
-+          (sbgen > fgen || dbstart(dentry) != fbstart(file))) {
-+              /* First we throw out the existing files. */
-+              cleanup_file(file);
-+
-+              /* Now we reopen the file(s) as in unionfs_open. */
-+              bstart = fbstart(file) = dbstart(dentry);
-+              bend = fbend(file) = dbend(dentry);
-+
-+              size = sizeof(struct file *) * sbmax(sb);
-+              UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
-+              if (!UNIONFS_F(file)->lower_files) {
-+                      err = -ENOMEM;
-+                      goto out;
-+              }
-+              size = sizeof(int) * sbmax(sb);
-+              UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
-+              if (!UNIONFS_F(file)->saved_branch_ids) {
-+                      err = -ENOMEM;
-+                      goto out;
-+              }
-+
-+              if (S_ISDIR(dentry->d_inode->i_mode)) {
-+                      /* We need to open all the files. */
-+                      err = open_all_files(file);
-+                      if (err)
-+                              goto out;
-+              } else {
-+                      /* We only open the highest priority branch. */
-+                      err = open_highest_file(file, willwrite);
-+                      if (err)
-+                              goto out;
-+              }
-+              atomic_set(&UNIONFS_F(file)->generation,
-+                         atomic_read(&UNIONFS_I(dentry->d_inode)->
-+                                     generation));
-+      }
-+
-+      /* Copyup on the first write to a file on a readonly branch. */
-+      if (willwrite && IS_WRITE_FLAG(file->f_flags) &&
-+          !IS_WRITE_FLAG(unionfs_lower_file(file)->f_flags) &&
-+          is_robranch(dentry)) {
-+              printk(KERN_DEBUG "unionfs: Doing delayed copyup of a "
-+                     "read-write file on a read-only branch.\n");
-+              err = do_delayed_copyup(file, dentry);
-+      }
-+
-+out:
-+      if (err) {
-+              kfree(UNIONFS_F(file)->lower_files);
-+              kfree(UNIONFS_F(file)->saved_branch_ids);
-+      }
-+out_nofree:
-+      unionfs_unlock_dentry(dentry);
-+      return err;
-+}
-+
-+/* unionfs_open helper function: open a directory */
-+static int __open_dir(struct inode *inode, struct file *file)
-+{
-+      struct dentry *hidden_dentry;
-+      struct file *hidden_file;
-+      int bindex, bstart, bend;
-+
-+      bstart = fbstart(file) = dbstart(file->f_dentry);
-+      bend = fbend(file) = dbend(file->f_dentry);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_dentry =
-+                      unionfs_lower_dentry_idx(file->f_dentry, bindex);
-+              if (!hidden_dentry)
-+                      continue;
-+
-+              dget(hidden_dentry);
-+              unionfs_mntget(file->f_dentry, bindex);
-+              hidden_file = dentry_open(hidden_dentry,
-+                                        unionfs_lower_mnt_idx(file->f_dentry,
-+                                                              bindex),
-+                                        file->f_flags);
-+              if (IS_ERR(hidden_file))
-+                      return PTR_ERR(hidden_file);
-+
-+              unionfs_set_lower_file_idx(file, bindex, hidden_file);
-+
-+              /*
-+               * The branchget goes after the open, because otherwise
-+               * we would miss the reference on release.
-+               */
-+              branchget(inode->i_sb, bindex);
-+      }
-+
-+      return 0;
-+}
-+
-+/* unionfs_open helper function: open a file */
-+static int __open_file(struct inode *inode, struct file *file)
-+{
-+      struct dentry *hidden_dentry;
-+      struct file *hidden_file;
-+      int hidden_flags;
-+      int bindex, bstart, bend;
-+
-+      hidden_dentry = unionfs_lower_dentry(file->f_dentry);
-+      hidden_flags = file->f_flags;
-+
-+      bstart = fbstart(file) = dbstart(file->f_dentry);
-+      bend = fbend(file) = dbend(file->f_dentry);
-+
-+      /*
-+       * check for the permission for hidden file.  If the error is
-+       * COPYUP_ERR, copyup the file.
-+       */
-+      if (hidden_dentry->d_inode && is_robranch(file->f_dentry)) {
-+              /*
-+               * if the open will change the file, copy it up otherwise
-+               * defer it.
-+               */
-+              if (hidden_flags & O_TRUNC) {
-+                      int size = 0;
-+                      int err = -EROFS;
-+
-+                      /* copyup the file */
-+                      for (bindex = bstart - 1; bindex >= 0; bindex--) {
-+                              err = copyup_file(
-+                                      file->f_dentry->d_parent->d_inode,
-+                                      file, bstart, bindex, size);
-+                              if (!err)
-+                                      break;
-+                      }
-+                      return err;
-+              } else
-+                      hidden_flags &= ~(OPEN_WRITE_FLAGS);
-+      }
-+
-+      dget(hidden_dentry);
-+
-+      /*
-+       * dentry_open will decrement mnt refcnt if err.
-+       * otherwise fput() will do an mntput() for us upon file close.
-+       */
-+      unionfs_mntget(file->f_dentry, bstart);
-+      hidden_file =
-+              dentry_open(hidden_dentry,
-+                          unionfs_lower_mnt_idx(file->f_dentry, bstart),
-+                          hidden_flags);
-+      if (IS_ERR(hidden_file))
-+              return PTR_ERR(hidden_file);
-+
-+      unionfs_set_lower_file(file, hidden_file);
-+      branchget(inode->i_sb, bstart);
-+
-+      return 0;
-+}
-+
-+int unionfs_open(struct inode *inode, struct file *file)
-+{
-+      int err = 0;
-+      struct file *hidden_file = NULL;
-+      struct dentry *dentry = NULL;
-+      int bindex = 0, bstart = 0, bend = 0;
-+      int size;
-+
-+      unionfs_read_lock(inode->i_sb);
-+
-+      file->private_data =
-+              kzalloc(sizeof(struct unionfs_file_info), GFP_KERNEL);
-+      if (!UNIONFS_F(file)) {
-+              err = -ENOMEM;
-+              goto out_nofree;
-+      }
-+      fbstart(file) = -1;
-+      fbend(file) = -1;
-+      atomic_set(&UNIONFS_F(file)->generation,
-+                 atomic_read(&UNIONFS_I(inode)->generation));
-+
-+      size = sizeof(struct file *) * sbmax(inode->i_sb);
-+      UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
-+      if (!UNIONFS_F(file)->lower_files) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+      size = sizeof(int) * sbmax(inode->i_sb);
-+      UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
-+      if (!UNIONFS_F(file)->saved_branch_ids) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      dentry = file->f_dentry;
-+      unionfs_lock_dentry(dentry);
-+
-+      bstart = fbstart(file) = dbstart(dentry);
-+      bend = fbend(file) = dbend(dentry);
-+
-+      /* increment, so that we can flush appropriately */
-+      atomic_inc(&UNIONFS_I(dentry->d_inode)->totalopens);
-+
-+      /*
-+       * open all directories and make the unionfs file struct point to
-+       * these hidden file structs
-+       */
-+      if (S_ISDIR(inode->i_mode))
-+              err = __open_dir(inode, file);  /* open a dir */
-+      else
-+              err = __open_file(inode, file); /* open a file */
-+
-+      /* freeing the allocated resources, and fput the opened files */
-+      if (err) {
-+              atomic_dec(&UNIONFS_I(dentry->d_inode)->totalopens);
-+              for (bindex = bstart; bindex <= bend; bindex++) {
-+                      hidden_file = unionfs_lower_file_idx(file, bindex);
-+                      if (!hidden_file)
-+                              continue;
-+
-+                      branchput(file->f_dentry->d_sb, bindex);
-+                      /* fput calls dput for hidden_dentry */
-+                      fput(hidden_file);
-+              }
-+      }
-+
-+      unionfs_unlock_dentry(dentry);
-+
-+out:
-+      if (err) {
-+              kfree(UNIONFS_F(file)->lower_files);
-+              kfree(UNIONFS_F(file)->saved_branch_ids);
-+              kfree(UNIONFS_F(file));
-+      }
-+out_nofree:
-+      unionfs_read_unlock(inode->i_sb);
-+      return err;
-+}
-+
-+/*
-+ * release all lower object references & free the file info structure
-+ *
-+ * No need to grab sb info's rwsem.
-+ */
-+int unionfs_file_release(struct inode *inode, struct file *file)
-+{
-+      struct file *hidden_file = NULL;
-+      struct unionfs_file_info *fileinfo;
-+      struct unionfs_inode_info *inodeinfo;
-+      struct super_block *sb = inode->i_sb;
-+      int bindex, bstart, bend;
-+      int fgen;
-+      int err;
-+
-+      unionfs_read_lock(sb);
-+      /*
-+       * Yes, we have to revalidate this file even if it's being released.
-+       * This is important for open-but-unlinked files, as well as mmap
-+       * support.
-+       */
-+      if ((err = unionfs_file_revalidate(file, 1)))
-+              return err;
-+      fileinfo = UNIONFS_F(file);
-+      BUG_ON(file->f_dentry->d_inode != inode);
-+      inodeinfo = UNIONFS_I(inode);
-+
-+      /* fput all the hidden files */
-+      fgen = atomic_read(&fileinfo->generation);
-+      bstart = fbstart(file);
-+      bend = fbend(file);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_file = unionfs_lower_file_idx(file, bindex);
-+
-+              if (hidden_file) {
-+                      fput(hidden_file);
-+                      branchput(inode->i_sb, bindex);
-+              }
-+      }
-+      kfree(fileinfo->lower_files);
-+      kfree(fileinfo->saved_branch_ids);
-+
-+      if (fileinfo->rdstate) {
-+              fileinfo->rdstate->access = jiffies;
-+              printk(KERN_DEBUG "unionfs: saving rdstate with cookie "
-+                     "%u [%d.%lld]\n",
-+                     fileinfo->rdstate->cookie,
-+                     fileinfo->rdstate->bindex,
-+                     (long long)fileinfo->rdstate->dirpos);
-+              spin_lock(&inodeinfo->rdlock);
-+              inodeinfo->rdcount++;
-+              list_add_tail(&fileinfo->rdstate->cache,
-+                            &inodeinfo->readdircache);
-+              mark_inode_dirty(inode);
-+              spin_unlock(&inodeinfo->rdlock);
-+              fileinfo->rdstate = NULL;
-+      }
-+      kfree(fileinfo);
-+      return 0;
-+}
-+
-+/* pass the ioctl to the lower fs */
-+static long do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+      struct file *hidden_file;
-+      int err;
-+
-+      hidden_file = unionfs_lower_file(file);
-+
-+      err = security_file_ioctl(hidden_file, cmd, arg);
-+      if (err)
-+              goto out;
-+
-+      err = -ENOTTY;
-+      if (!hidden_file || !hidden_file->f_op)
-+              goto out;
-+      if (hidden_file->f_op->unlocked_ioctl) {
-+              err = hidden_file->f_op->unlocked_ioctl(hidden_file, cmd, arg);
-+      } else if (hidden_file->f_op->ioctl) {
-+              lock_kernel();
-+              err = hidden_file->f_op->ioctl(hidden_file->f_dentry->d_inode,
-+                                             hidden_file, cmd, arg);
-+              unlock_kernel();
-+      }
-+
-+out:
-+      return err;
-+}
-+
-+/*
-+ * return to user-space the branch indices containing the file in question
-+ *
-+ * We use fd_set and therefore we are limited to the number of the branches
-+ * to FD_SETSIZE, which is currently 1024 - plenty for most people
-+ */
-+static int unionfs_ioctl_queryfile(struct file *file, unsigned int cmd,
-+                                 unsigned long arg)
-+{
-+      int err = 0;
-+      fd_set branchlist;
-+
-+      int bstart = 0, bend = 0, bindex = 0;
-+      struct dentry *dentry, *hidden_dentry;
-+
-+      dentry = file->f_dentry;
-+      unionfs_lock_dentry(dentry);
-+      if ((err = unionfs_partial_lookup(dentry)))
-+              goto out;
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+
-+      FD_ZERO(&branchlist);
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!hidden_dentry)
-+                      continue;
-+              if (hidden_dentry->d_inode)
-+                      FD_SET(bindex, &branchlist);
-+      }
-+
-+      err = copy_to_user((void __user *)arg, &branchlist, sizeof(fd_set));
-+      if (err)
-+              err = -EFAULT;
-+
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      return err < 0 ? err : bend;
-+}
-+
-+long unionfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+      long err;
-+
-+      unionfs_read_lock(file->f_path.dentry->d_sb);
-+
-+      if ((err = unionfs_file_revalidate(file, 1)))
-+              goto out;
-+
-+      /* check if asked for local commands */
-+      switch (cmd) {
-+      case UNIONFS_IOCTL_INCGEN:
-+              /* Increment the superblock generation count */
-+              printk("unionfs: incgen ioctl deprecated; "
-+                     "use \"-o remount,incgen\"\n");
-+              err = -ENOSYS;
-+              break;
-+
-+      case UNIONFS_IOCTL_QUERYFILE:
-+              /* Return list of branches containing the given file */
-+              err = unionfs_ioctl_queryfile(file, cmd, arg);
-+              break;
-+
-+      default:
-+              /* pass the ioctl down */
-+              err = do_ioctl(file, cmd, arg);
-+              break;
-+      }
-+
-+out:
-+      unionfs_read_unlock(file->f_path.dentry->d_sb);
-+      return err;
-+}
-+
-+int unionfs_flush(struct file *file, fl_owner_t id)
-+{
-+      int err = 0;
-+      struct file *hidden_file = NULL;
-+      struct dentry *dentry = file->f_dentry;
-+      int bindex, bstart, bend;
-+
-+      unionfs_read_lock(file->f_path.dentry->d_sb);
-+
-+      if ((err = unionfs_file_revalidate(file, 1)))
-+              goto out;
-+
-+      if (!atomic_dec_and_test(&UNIONFS_I(dentry->d_inode)->totalopens))
-+              goto out;
-+
-+      unionfs_lock_dentry(dentry);
-+
-+      bstart = fbstart(file);
-+      bend = fbend(file);
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_file = unionfs_lower_file_idx(file, bindex);
-+
-+              if (hidden_file && hidden_file->f_op &&
-+                  hidden_file->f_op->flush) {
-+                      err = hidden_file->f_op->flush(hidden_file, id);
-+                      if (err)
-+                              goto out_lock;
+-
+-static ssize_t
+-lpfc_debugfs_read(struct file *file, char __user *buf,
+-                size_t nbytes, loff_t *ppos)
+-{
+-      struct lpfc_debug *debug = file->private_data;
+-      return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer,
+-                                     debug->len);
+-}
+-
+-static int
+-lpfc_debugfs_release(struct inode *inode, struct file *file)
+-{
+-      struct lpfc_debug *debug = file->private_data;
+-
+-      kfree(debug->buffer);
+-      kfree(debug);
+-
+-      return 0;
+-}
+-
+-#undef lpfc_debugfs_op_disc_trc
+-static struct file_operations lpfc_debugfs_op_disc_trc = {
+-      .owner =        THIS_MODULE,
+-      .open =         lpfc_debugfs_disc_trc_open,
+-      .llseek =       lpfc_debugfs_lseek,
+-      .read =         lpfc_debugfs_read,
+-      .release =      lpfc_debugfs_release,
+-};
+-
+-#undef lpfc_debugfs_op_nodelist
+-static struct file_operations lpfc_debugfs_op_nodelist = {
+-      .owner =        THIS_MODULE,
+-      .open =         lpfc_debugfs_nodelist_open,
+-      .llseek =       lpfc_debugfs_lseek,
+-      .read =         lpfc_debugfs_read,
+-      .release =      lpfc_debugfs_release,
+-};
+-
+-static struct dentry *lpfc_debugfs_root = NULL;
+-static atomic_t lpfc_debugfs_hba_count;
+-#endif
+-
+-inline void
+-lpfc_debugfs_initialize(struct lpfc_vport *vport)
+-{
+-#ifdef CONFIG_LPFC_DEBUG_FS
+-      struct lpfc_hba   *phba = vport->phba;
+-      char name[64];
+-      uint32_t num, i;
+-
+-      if (!lpfc_debugfs_enable)
+-              return;
+-
+-      if (lpfc_debugfs_max_disc_trc) {
+-              num = lpfc_debugfs_max_disc_trc - 1;
+-              if (num & lpfc_debugfs_max_disc_trc) {
+-                      /* Change to be a power of 2 */
+-                      num = lpfc_debugfs_max_disc_trc;
+-                      i = 0;
+-                      while (num > 1) {
+-                              num = num >> 1;
+-                              i++;
+-                      }
+-                      lpfc_debugfs_max_disc_trc = (1 << i);
+-                      printk(KERN_ERR
+-                              "lpfc_debugfs_max_disc_trc changed to %d\n",
+-                              lpfc_debugfs_max_disc_trc);
+-              }
+-      }
+-
+-      if (!lpfc_debugfs_root) {
+-              lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL);
+-              atomic_set(&lpfc_debugfs_hba_count, 0);
+-              if (!lpfc_debugfs_root)
+-                      goto debug_failed;
+-      }
+-
+-      snprintf(name, sizeof(name), "lpfc%d", phba->brd_no);
+-      if (!phba->hba_debugfs_root) {
+-              phba->hba_debugfs_root =
+-                      debugfs_create_dir(name, lpfc_debugfs_root);
+-              if (!phba->hba_debugfs_root)
+-                      goto debug_failed;
+-              atomic_inc(&lpfc_debugfs_hba_count);
+-              atomic_set(&phba->debugfs_vport_count, 0);
+-      }
+-
+-      snprintf(name, sizeof(name), "vport%d", vport->vpi);
+-      if (!vport->vport_debugfs_root) {
+-              vport->vport_debugfs_root =
+-                      debugfs_create_dir(name, phba->hba_debugfs_root);
+-              if (!vport->vport_debugfs_root)
+-                      goto debug_failed;
+-              atomic_inc(&phba->debugfs_vport_count);
+-      }
+-
+-      if (!lpfc_debugfs_start_time)
+-              lpfc_debugfs_start_time = jiffies;
+-
+-      vport->disc_trc = kmalloc(
+-              (sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc),
+-              GFP_KERNEL);
+-
+-      if (!vport->disc_trc)
+-              goto debug_failed;
+-      memset(vport->disc_trc, 0,
+-              (sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc));
+-
+-      snprintf(name, sizeof(name), "discovery_trace");
+-      vport->debug_disc_trc =
+-              debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+-                               vport->vport_debugfs_root,
+-                               vport, &lpfc_debugfs_op_disc_trc);
+-      if (!vport->debug_disc_trc) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+-                              "%d:0409 Cannot create debugfs",
+-                              phba->brd_no);
+-              goto debug_failed;
+-      }
+-      snprintf(name, sizeof(name), "nodelist");
+-      vport->debug_nodelist =
+-              debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+-                               vport->vport_debugfs_root,
+-                               vport, &lpfc_debugfs_op_nodelist);
+-      if (!vport->debug_nodelist) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+-                              "%d:0409 Cannot create debugfs",
+-                              phba->brd_no);
+-              goto debug_failed;
+-      }
+-debug_failed:
+-      return;
+-#endif
+-}
+-
+-
+-inline void
+-lpfc_debugfs_terminate(struct lpfc_vport *vport)
+-{
+-#ifdef CONFIG_LPFC_DEBUG_FS
+-      struct lpfc_hba   *phba = vport->phba;
+-
+-      if (vport->disc_trc) {
+-              kfree(vport->disc_trc);
+-              vport->disc_trc = NULL;
+-      }
+-      if (vport->debug_disc_trc) {
+-              debugfs_remove(vport->debug_disc_trc); /* discovery_trace */
+-              vport->debug_disc_trc = NULL;
+-      }
+-      if (vport->debug_nodelist) {
+-              debugfs_remove(vport->debug_nodelist); /* nodelist */
+-              vport->debug_nodelist = NULL;
+-      }
+-      if (vport->vport_debugfs_root) {
+-              debugfs_remove(vport->vport_debugfs_root); /* vportX */
+-              vport->vport_debugfs_root = NULL;
+-              atomic_dec(&phba->debugfs_vport_count);
+-      }
+-      if (atomic_read(&phba->debugfs_vport_count) == 0) {
+-              debugfs_remove(vport->phba->hba_debugfs_root); /* lpfcX */
+-              vport->phba->hba_debugfs_root = NULL;
+-              atomic_dec(&lpfc_debugfs_hba_count);
+-              if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
+-                      debugfs_remove(lpfc_debugfs_root); /* lpfc */
+-                      lpfc_debugfs_root = NULL;
+-              }
+-      }
+-#endif
+-}
+-
+-
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_debugfs.h linux-2.6.22-570/drivers/scsi/lpfc/lpfc_debugfs.h
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_debugfs.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_debugfs.h  1969-12-31 19:00:00.000000000 -0500
+@@ -1,50 +0,0 @@
+-/*******************************************************************
+- * This file is part of the Emulex Linux Device Driver for         *
+- * Fibre Channel Host Bus Adapters.                                *
+- * Copyright (C) 2007 Emulex.  All rights reserved.                *
+- * EMULEX and SLI are trademarks of Emulex.                        *
+- * www.emulex.com                                                  *
+- *                                                                 *
+- * This program is free software; you can redistribute it and/or   *
+- * modify it under the terms of version 2 of the GNU General       *
+- * Public License as published by the Free Software Foundation.    *
+- * This program is distributed in the hope that it will be useful. *
+- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
+- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
+- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
+- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+- * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
+- * more details, a copy of which can be found in the file COPYING  *
+- * included with this package.                                     *
+- *******************************************************************/
+-
+-#ifndef _H_LPFC_DEBUG_FS
+-#define _H_LPFC_DEBUG_FS
+-
+-#ifdef CONFIG_LPFC_DEBUG_FS
+-struct lpfc_disc_trc {
+-      char *fmt;
+-      uint32_t data1;
+-      uint32_t data2;
+-      uint32_t data3;
+-      uint32_t seq_cnt;
+-      unsigned long jif;
+-};
+-#endif
+-
+-/* Mask for discovery_trace */
+-#define LPFC_DISC_TRC_ELS_CMD         0x1     /* Trace ELS commands */
+-#define LPFC_DISC_TRC_ELS_RSP         0x2     /* Trace ELS response */
+-#define LPFC_DISC_TRC_ELS_UNSOL               0x4     /* Trace ELS rcv'ed   */
+-#define LPFC_DISC_TRC_ELS_ALL         0x7     /* Trace ELS */
+-#define LPFC_DISC_TRC_MBOX_VPORT      0x8     /* Trace vport MBOXs */
+-#define LPFC_DISC_TRC_MBOX            0x10    /* Trace other MBOXs */
+-#define LPFC_DISC_TRC_MBOX_ALL                0x18    /* Trace all MBOXs */
+-#define LPFC_DISC_TRC_CT              0x20    /* Trace disc CT requests */
+-#define LPFC_DISC_TRC_DSM             0x40    /* Trace DSM events */
+-#define LPFC_DISC_TRC_RPORT           0x80    /* Trace rport events */
+-#define LPFC_DISC_TRC_NODE            0x100   /* Trace ndlp state changes */
+-
+-#define LPFC_DISC_TRC_DISCOVERY               0xef    /* common mask for general
+-                                               * discovery */
+-#endif /* H_LPFC_DEBUG_FS */
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_disc.h linux-2.6.22-570/drivers/scsi/lpfc/lpfc_disc.h
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_disc.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_disc.h     2007-07-08 19:32:17.000000000 -0400
+@@ -36,23 +36,21 @@
+       LPFC_EVT_WARM_START,
+       LPFC_EVT_KILL,
+       LPFC_EVT_ELS_RETRY,
+-      LPFC_EVT_DEV_LOSS_DELAY,
+-      LPFC_EVT_DEV_LOSS,
+ };
+ /* structure used to queue event to the discovery tasklet */
+ struct lpfc_work_evt {
+       struct list_head      evt_listp;
+-      void                 *evt_arg1;
+-      void                 *evt_arg2;
++      void                * evt_arg1;
++      void                * evt_arg2;
+       enum lpfc_work_type   evt;
+ };
+ struct lpfc_nodelist {
+       struct list_head nlp_listp;
+-      struct lpfc_name nlp_portname;
+-      struct lpfc_name nlp_nodename;
++      struct lpfc_name nlp_portname;          /* port name */
++      struct lpfc_name nlp_nodename;          /* node name */
+       uint32_t         nlp_flag;              /* entry  flags */
+       uint32_t         nlp_DID;               /* FC D_ID of entry */
+       uint32_t         nlp_last_elscmd;       /* Last ELS cmd sent */
+@@ -77,9 +75,8 @@
+       struct timer_list   nlp_delayfunc;      /* Used for delayed ELS cmds */
+       struct fc_rport *rport;                 /* Corresponding FC transport
+                                                  port structure */
+-      struct lpfc_vport *vport;
++      struct lpfc_hba      *nlp_phba;
+       struct lpfc_work_evt els_retry_evt;
+-      struct lpfc_work_evt dev_loss_evt;
+       unsigned long last_ramp_up_time;        /* jiffy of last ramp up */
+       unsigned long last_q_full_time;         /* jiffy of last queue full */
+       struct kref     kref;
+@@ -101,9 +98,7 @@
+                                          ACC */
+ #define NLP_NPR_ADISC      0x2000000  /* Issue ADISC when dq'ed from
+                                          NPR list */
+-#define NLP_RM_DFLT_RPI    0x4000000  /* need to remove leftover dflt RPI */
+ #define NLP_NODEV_REMOVE   0x8000000  /* Defer removal till discovery ends */
+-#define NLP_TARGET_REMOVE  0x10000000   /* Target remove in process */
+ /* There are 4 different double linked lists nodelist entries can reside on.
+  * The Port Login (PLOGI) list and Address Discovery (ADISC) list are used
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_els.c linux-2.6.22-570/drivers/scsi/lpfc/lpfc_els.c
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_els.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_els.c      2007-07-08 19:32:17.000000000 -0400
+@@ -35,38 +35,38 @@
+ #include "lpfc.h"
+ #include "lpfc_logmsg.h"
+ #include "lpfc_crtn.h"
+-#include "lpfc_vport.h"
+-#include "lpfc_debugfs.h"
+ static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *,
+                         struct lpfc_iocbq *);
+-static void lpfc_cmpl_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *,
+-                      struct lpfc_iocbq *);
+-
+ static int lpfc_max_els_tries = 3;
+-int
+-lpfc_els_chk_latt(struct lpfc_vport *vport)
++static int
++lpfc_els_chk_latt(struct lpfc_hba * phba)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
++      struct lpfc_sli *psli;
++      LPFC_MBOXQ_t *mbox;
+       uint32_t ha_copy;
++      int rc;
 +
-+                      /* if there are no more refs to the dentry, dput it */
-+                      if (d_deleted(dentry)) {
-+                              dput(unionfs_lower_dentry_idx(dentry, bindex));
-+                              unionfs_set_lower_dentry_idx(dentry, bindex,
-+                                                           NULL);
++      psli = &phba->sli;
+-      if (vport->port_state >= LPFC_VPORT_READY ||
+-          phba->link_state == LPFC_LINK_DOWN)
++      if ((phba->hba_state >= LPFC_HBA_READY) ||
++          (phba->hba_state == LPFC_LINK_DOWN))
+               return 0;
+       /* Read the HBA Host Attention Register */
++      spin_lock_irq(phba->host->host_lock);
+       ha_copy = readl(phba->HAregaddr);
++      spin_unlock_irq(phba->host->host_lock);
+       if (!(ha_copy & HA_LATT))
+               return 0;
+       /* Pending Link Event during Discovery */
+-      lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                      "%d (%d):0237 Pending Link Event during "
++      lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY,
++                      "%d:0237 Pending Link Event during "
+                       "Discovery: State x%x\n",
+-                      phba->brd_no, vport->vpi,  phba->pport->port_state);
++                      phba->brd_no, phba->hba_state);
+       /* CLEAR_LA should re-enable link attention events and
+        * we should then imediately take a LATT event. The
+@@ -74,34 +74,48 @@
+        * will cleanup any left over in-progress discovery
+        * events.
+        */
+-      spin_lock_irq(shost->host_lock);
+-      vport->fc_flag |= FC_ABORT_DISCOVERY;
+-      spin_unlock_irq(shost->host_lock);
+-
+-      if (phba->link_state != LPFC_CLEAR_LA)
+-              lpfc_issue_clear_la(phba, vport);
++      spin_lock_irq(phba->host->host_lock);
++      phba->fc_flag |= FC_ABORT_DISCOVERY;
++      spin_unlock_irq(phba->host->host_lock);
++
++      if (phba->hba_state != LPFC_CLEAR_LA) {
++              if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
++                      phba->hba_state = LPFC_CLEAR_LA;
++                      lpfc_clear_la(phba, mbox);
++                      mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
++                      rc = lpfc_sli_issue_mbox (phba, mbox,
++                                                (MBX_NOWAIT | MBX_STOP_IOCB));
++                      if (rc == MBX_NOT_FINISHED) {
++                              mempool_free(mbox, phba->mbox_mem_pool);
++                              phba->hba_state = LPFC_HBA_ERROR;
 +                      }
 +              }
-+
-+      }
-+
-+out_lock:
-+      unionfs_unlock_dentry(dentry);
-+out:
-+      unionfs_read_unlock(file->f_path.dentry->d_sb);
-+      return err;
-+}
-diff -Nurb linux-2.6.22-570/fs/unionfs/copyup.c linux-2.6.22-590/fs/unionfs/copyup.c
---- linux-2.6.22-570/fs/unionfs/copyup.c       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/copyup.c       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,806 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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 "union.h"
-+
-+/*
-+ * For detailed explanation of copyup see:
-+ * Documentation/filesystems/unionfs/concepts.txt
-+ */
-+
-+/* forward definitions */
-+static int copyup_named_dentry(struct inode *dir, struct dentry *dentry,
-+                             int bstart, int new_bindex, const char *name,
-+                             int namelen, struct file **copyup_file,
-+                             loff_t len);
-+static struct dentry *create_parents_named(struct inode *dir,
-+                                         struct dentry *dentry,
-+                                         const char *name, int bindex);
-+
-+#ifdef CONFIG_UNION_FS_XATTR
-+/* copyup all extended attrs for a given dentry */
-+static int copyup_xattrs(struct dentry *old_hidden_dentry,
-+                       struct dentry *new_hidden_dentry)
-+{
-+      int err = 0;
-+      ssize_t list_size = -1;
-+      char *name_list = NULL;
-+      char *attr_value = NULL;
-+      char *name_list_orig = NULL;
-+
-+      list_size = vfs_listxattr(old_hidden_dentry, NULL, 0);
-+
-+      if (list_size <= 0) {
-+              err = list_size;
-+              goto out;
-+      }
-+
-+      name_list = unionfs_xattr_alloc(list_size + 1, XATTR_LIST_MAX);
-+      if (!name_list || IS_ERR(name_list)) {
-+              err = PTR_ERR(name_list);
-+              goto out;
-+      }
-+      list_size = vfs_listxattr(old_hidden_dentry, name_list, list_size);
-+      attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX);
-+      if (!attr_value || IS_ERR(attr_value)) {
-+              err = PTR_ERR(name_list);
-+              goto out;
-+      }
-+      name_list_orig = name_list;
-+      while (*name_list) {
-+              ssize_t size;
-+
-+              /* Lock here since vfs_getxattr doesn't lock for us */
-+              mutex_lock(&old_hidden_dentry->d_inode->i_mutex);
-+              size = vfs_getxattr(old_hidden_dentry, name_list,
-+                                  attr_value, XATTR_SIZE_MAX);
-+              mutex_unlock(&old_hidden_dentry->d_inode->i_mutex);
-+              if (size < 0) {
-+                      err = size;
-+                      goto out;
-+              }
-+
-+              if (size > XATTR_SIZE_MAX) {
-+                      err = -E2BIG;
-+                      goto out;
-+              }
-+              /* Don't lock here since vfs_setxattr does it for us. */
-+              err = vfs_setxattr(new_hidden_dentry, name_list, attr_value,
-+                                 size, 0);
-+
-+              if (err < 0)
-+                      goto out;
-+              name_list += strlen(name_list) + 1;
-+      }
-+out:
-+      name_list = name_list_orig;
-+
-+      if (name_list)
-+              unionfs_xattr_free(name_list, list_size + 1);
-+      if (attr_value)
-+              unionfs_xattr_free(attr_value, XATTR_SIZE_MAX);
-+      /* It is no big deal if this fails, we just roll with the punches. */
-+      if (err == -ENOTSUPP || err == -EOPNOTSUPP)
-+              err = 0;
-+      return err;
-+}
-+#endif /* CONFIG_UNION_FS_XATTR */
-+
-+/* Determine the mode based on the copyup flags, and the existing dentry. */
-+static int copyup_permissions(struct super_block *sb,
-+                            struct dentry *old_hidden_dentry,
-+                            struct dentry *new_hidden_dentry)
-+{
-+      struct inode *i = old_hidden_dentry->d_inode;
-+      struct iattr newattrs;
-+      int err;
-+
-+      newattrs.ia_atime = i->i_atime;
-+      newattrs.ia_mtime = i->i_mtime;
-+      newattrs.ia_ctime = i->i_ctime;
-+
-+      newattrs.ia_gid = i->i_gid;
-+      newattrs.ia_uid = i->i_uid;
-+
-+      newattrs.ia_mode = i->i_mode;
-+
-+      newattrs.ia_valid = ATTR_CTIME | ATTR_ATIME | ATTR_MTIME |
-+              ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_FORCE |
-+              ATTR_GID | ATTR_UID | ATTR_MODE;
-+
-+      err = notify_change(new_hidden_dentry, &newattrs);
-+
-+      return err;
-+}
-+
-+int copyup_dentry(struct inode *dir, struct dentry *dentry,
-+                int bstart, int new_bindex,
-+                struct file **copyup_file, loff_t len)
-+{
-+      return copyup_named_dentry(dir, dentry, bstart, new_bindex,
-+                                 dentry->d_name.name,
-+                                 dentry->d_name.len, copyup_file, len);
-+}
-+
-+/*
-+ * create the new device/file/directory - use copyup_permission to copyup
-+ * times, and mode
-+ *
-+ * if the object being copied up is a regular file, the file is only created,
-+ * the contents have to be copied up separately
-+ */
-+static int __copyup_ndentry(struct dentry *old_hidden_dentry,
-+                          struct dentry *new_hidden_dentry,
-+                          struct dentry *new_hidden_parent_dentry,
-+                          char *symbuf)
-+{
-+      int err = 0;
-+      umode_t old_mode = old_hidden_dentry->d_inode->i_mode;
-+      struct sioq_args args;
-+
-+      if (S_ISDIR(old_mode)) {
-+              args.mkdir.parent = new_hidden_parent_dentry->d_inode;
-+              args.mkdir.dentry = new_hidden_dentry;
-+              args.mkdir.mode = old_mode;
-+
-+              run_sioq(__unionfs_mkdir, &args);
-+              err = args.err;
-+      } else if (S_ISLNK(old_mode)) {
-+              args.symlink.parent = new_hidden_parent_dentry->d_inode;
-+              args.symlink.dentry = new_hidden_dentry;
-+              args.symlink.symbuf = symbuf;
-+              args.symlink.mode = old_mode;
-+
-+              run_sioq(__unionfs_symlink, &args);
-+              err = args.err;
-+      } else if (S_ISBLK(old_mode) || S_ISCHR(old_mode) ||
-+                 S_ISFIFO(old_mode) || S_ISSOCK(old_mode)) {
-+              args.mknod.parent = new_hidden_parent_dentry->d_inode;
-+              args.mknod.dentry = new_hidden_dentry;
-+              args.mknod.mode = old_mode;
-+              args.mknod.dev = old_hidden_dentry->d_inode->i_rdev;
-+
-+              run_sioq(__unionfs_mknod, &args);
-+              err = args.err;
-+      } else if (S_ISREG(old_mode)) {
-+              args.create.parent = new_hidden_parent_dentry->d_inode;
-+              args.create.dentry = new_hidden_dentry;
-+              args.create.mode = old_mode;
-+              args.create.nd = NULL;
-+
-+              run_sioq(__unionfs_create, &args);
-+              err = args.err;
-+      } else {
-+              printk(KERN_ERR "unionfs: unknown inode type %d\n",
-+                     old_mode);
-+              BUG();
-+      }
-+
-+      return err;
-+}
-+
-+static int __copyup_reg_data(struct dentry *dentry,
-+                           struct dentry *new_hidden_dentry, int new_bindex,
-+                           struct dentry *old_hidden_dentry, int old_bindex,
-+                           struct file **copyup_file, loff_t len)
-+{
-+      struct super_block *sb = dentry->d_sb;
-+      struct file *input_file;
-+      struct file *output_file;
-+      mm_segment_t old_fs;
-+      char *buf = NULL;
-+      ssize_t read_bytes, write_bytes;
-+      loff_t size;
-+      int err = 0;
-+
-+      /* open old file */
-+      unionfs_mntget(dentry, old_bindex);
-+      branchget(sb, old_bindex);
-+      input_file = dentry_open(old_hidden_dentry,
-+                               unionfs_lower_mnt_idx(dentry, old_bindex),
-+                               O_RDONLY | O_LARGEFILE);
-+      if (IS_ERR(input_file)) {
-+              dput(old_hidden_dentry);
-+              err = PTR_ERR(input_file);
-+              goto out;
-+      }
-+      if (!input_file->f_op || !input_file->f_op->read) {
-+              err = -EINVAL;
-+              goto out_close_in;
-+      }
-+
-+      /* open new file */
-+      dget(new_hidden_dentry);
-+      unionfs_mntget(dentry, new_bindex);
-+      branchget(sb, new_bindex);
-+      output_file = dentry_open(new_hidden_dentry,
-+                                unionfs_lower_mnt_idx(dentry, new_bindex),
-+                                O_WRONLY | O_LARGEFILE);
-+      if (IS_ERR(output_file)) {
-+              err = PTR_ERR(output_file);
-+              goto out_close_in2;
-+      }
-+      if (!output_file->f_op || !output_file->f_op->write) {
-+              err = -EINVAL;
-+              goto out_close_out;
-+      }
-+
-+      /* allocating a buffer */
-+      buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-+      if (!buf) {
-+              err = -ENOMEM;
-+              goto out_close_out;
-+      }
-+
-+      input_file->f_pos = 0;
-+      output_file->f_pos = 0;
-+
-+      old_fs = get_fs();
-+      set_fs(KERNEL_DS);
-+
-+      size = len;
-+      err = 0;
-+      do {
-+              if (len >= PAGE_SIZE)
-+                      size = PAGE_SIZE;
-+              else if ((len < PAGE_SIZE) && (len > 0))
-+                      size = len;
-+
-+              len -= PAGE_SIZE;
-+
-+              read_bytes =
-+                      input_file->f_op->read(input_file,
-+                                             (char __user *)buf, size,
-+                                             &input_file->f_pos);
-+              if (read_bytes <= 0) {
-+                      err = read_bytes;
-+                      break;
-+              }
-+
-+              write_bytes =
-+                      output_file->f_op->write(output_file,
-+                                               (char __user *)buf,
-+                                               read_bytes,
-+                                               &output_file->f_pos);
-+              if ((write_bytes < 0) || (write_bytes < read_bytes)) {
-+                      err = write_bytes;
-+                      break;
-+              }
-+      } while ((read_bytes > 0) && (len > 0));
-+
-+      set_fs(old_fs);
-+
-+      kfree(buf);
-+
-+      if (!err)
-+              err = output_file->f_op->fsync(output_file,
-+                                             new_hidden_dentry, 0);
-+
-+      if (err)
-+              goto out_close_out;
-+
-+      if (copyup_file) {
-+              *copyup_file = output_file;
-+              goto out_close_in;
 +      }
+       return 1;
 +
-+out_close_out:
-+      fput(output_file);
-+
-+out_close_in2:
-+      branchput(sb, new_bindex);
-+
-+out_close_in:
-+      fput(input_file);
-+
-+out:
-+      branchput(sb, old_bindex);
-+
-+      return err;
-+}
-+
-+/*
-+ * dput the lower references for old and new dentry & clear a lower dentry
-+ * pointer
-+ */
-+static void __clear(struct dentry *dentry, struct dentry *old_hidden_dentry,
-+                  int old_bstart, int old_bend,
-+                  struct dentry *new_hidden_dentry, int new_bindex)
-+{
-+      /* get rid of the hidden dentry and all its traces */
-+      unionfs_set_lower_dentry_idx(dentry, new_bindex, NULL);
-+      set_dbstart(dentry, old_bstart);
-+      set_dbend(dentry, old_bend);
-+
-+      dput(new_hidden_dentry);
-+      dput(old_hidden_dentry);
-+}
-+
-+/* copy up a dentry to a file of specified name */
-+static int copyup_named_dentry(struct inode *dir, struct dentry *dentry,
-+                             int bstart, int new_bindex, const char *name,
-+                             int namelen, struct file **copyup_file,
-+                             loff_t len)
-+{
-+      struct dentry *new_hidden_dentry;
-+      struct dentry *old_hidden_dentry = NULL;
-+      struct super_block *sb;
-+      int err = 0;
-+      int old_bindex;
-+      int old_bstart;
-+      int old_bend;
-+      struct dentry *new_hidden_parent_dentry = NULL;
-+      mm_segment_t oldfs;
-+      char *symbuf = NULL;
-+
-+      verify_locked(dentry);
-+
-+      old_bindex = bstart;
-+      old_bstart = dbstart(dentry);
-+      old_bend = dbend(dentry);
-+
-+      BUG_ON(new_bindex < 0);
-+      BUG_ON(new_bindex >= old_bindex);
-+
-+      sb = dir->i_sb;
-+
-+      if ((err = is_robranch_super(sb, new_bindex)))
-+              goto out;
-+
-+      /* Create the directory structure above this dentry. */
-+      new_hidden_dentry =
-+              create_parents_named(dir, dentry, name, new_bindex);
-+      if (IS_ERR(new_hidden_dentry)) {
-+              err = PTR_ERR(new_hidden_dentry);
-+              goto out;
-+      }
+ }
+ static struct lpfc_iocbq *
+-lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
+-                 uint16_t cmdSize, uint8_t retry,
+-                 struct lpfc_nodelist *ndlp, uint32_t did,
+-                 uint32_t elscmd)
++lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp,
++                 uint16_t cmdSize, uint8_t retry, struct lpfc_nodelist * ndlp,
++                 uint32_t did, uint32_t elscmd)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
++      struct lpfc_sli_ring *pring;
+       struct lpfc_iocbq *elsiocb;
+       struct lpfc_dmabuf *pcmd, *prsp, *pbuflist;
+       struct ulp_bde64 *bpl;
+       IOCB_t *icmd;
++      pring = &phba->sli.ring[LPFC_ELS_RING];
+-      if (!lpfc_is_link_up(phba))
++      if (phba->hba_state < LPFC_LINK_UP)
+               return  NULL;
+       /* Allocate buffer for  command iocb */
++      spin_lock_irq(phba->host->host_lock);
+       elsiocb = lpfc_sli_get_iocbq(phba);
++      spin_unlock_irq(phba->host->host_lock);
+       if (elsiocb == NULL)
+               return NULL;
+@@ -109,12 +123,14 @@
+       /* fill in BDEs for command */
+       /* Allocate buffer for command payload */
+-      if (((pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
++      if (((pcmd = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
+           ((pcmd->virt = lpfc_mbuf_alloc(phba,
+                                          MEM_PRI, &(pcmd->phys))) == 0)) {
+               kfree(pcmd);
++              spin_lock_irq(phba->host->host_lock);
+               lpfc_sli_release_iocbq(phba, elsiocb);
++              spin_unlock_irq(phba->host->host_lock);
+               return NULL;
+       }
+@@ -122,7 +138,7 @@
+       /* Allocate buffer for response payload */
+       if (expectRsp) {
+-              prsp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
++              prsp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
+               if (prsp)
+                       prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
+                                                    &prsp->phys);
+@@ -130,7 +146,9 @@
+                       kfree(prsp);
+                       lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
+                       kfree(pcmd);
++                      spin_lock_irq(phba->host->host_lock);
+                       lpfc_sli_release_iocbq(phba, elsiocb);
++                      spin_unlock_irq(phba->host->host_lock);
+                       return NULL;
+               }
+               INIT_LIST_HEAD(&prsp->list);
+@@ -139,12 +157,14 @@
+       }
+       /* Allocate buffer for Buffer ptr list */
+-      pbuflist = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
++      pbuflist = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
+       if (pbuflist)
+           pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
+                                            &pbuflist->phys);
+       if (pbuflist == 0 || pbuflist->virt == 0) {
++              spin_lock_irq(phba->host->host_lock);
+               lpfc_sli_release_iocbq(phba, elsiocb);
++              spin_unlock_irq(phba->host->host_lock);
+               lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
+               lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
+               kfree(pcmd);
+@@ -158,28 +178,20 @@
+       icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
+       icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
+       icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL;
+-              icmd->un.elsreq64.remoteID = did;       /* DID */
+       if (expectRsp) {
+-              icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64));
++              icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64));
++              icmd->un.elsreq64.remoteID = did;       /* DID */
+               icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
+               icmd->ulpTimeout = phba->fc_ratov * 2;
+       } else {
+-              icmd->un.elsreq64.bdl.bdeSize = sizeof(struct ulp_bde64);
++              icmd->un.elsreq64.bdl.bdeSize = sizeof (struct ulp_bde64);
+               icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
+       }
 +
-+      old_hidden_dentry = unionfs_lower_dentry_idx(dentry, old_bindex);
-+      /* we conditionally dput this old_hidden_dentry at end of function */
-+      dget(old_hidden_dentry);
+       icmd->ulpBdeCount = 1;
+       icmd->ulpLe = 1;
+       icmd->ulpClass = CLASS3;
+-      if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+-              icmd->un.elsreq64.myID = vport->fc_myDID;
+-
+-              /* For ELS_REQUEST64_CR, use the VPI by default */
+-              icmd->ulpContext = vport->vpi;
+-              icmd->ulpCt_h = 0;
+-              icmd->ulpCt_l = 1;
+-      }
+-
+       bpl = (struct ulp_bde64 *) pbuflist->virt;
+       bpl->addrLow = le32_to_cpu(putPaddrLow(pcmd->phys));
+       bpl->addrHigh = le32_to_cpu(putPaddrHigh(pcmd->phys));
+@@ -197,12 +209,10 @@
+       }
+       /* Save for completion so we can release these resources */
+-      if (elscmd != ELS_CMD_LS_RJT)
+       elsiocb->context1 = lpfc_nlp_get(ndlp);
+       elsiocb->context2 = pcmd;
+       elsiocb->context3 = pbuflist;
+       elsiocb->retry = retry;
+-      elsiocb->vport = vport;
+       elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT;
+       if (prsp) {
+@@ -212,16 +222,16 @@
+       if (expectRsp) {
+               /* Xmit ELS command <elsCmd> to remote NPORT <did> */
+               lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                              "%d (%d):0116 Xmit ELS command x%x to remote "
+-                              "NPORT x%x I/O tag: x%x, port state: x%x\n",
+-                              phba->brd_no, vport->vpi,  elscmd, did,
+-                              elsiocb->iotag, vport->port_state);
++                              "%d:0116 Xmit ELS command x%x to remote "
++                              "NPORT x%x I/O tag: x%x, HBA state: x%x\n",
++                              phba->brd_no, elscmd,
++                              did, elsiocb->iotag, phba->hba_state);
+       } else {
+               /* Xmit ELS response <elsCmd> to remote NPORT <did> */
+               lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                              "%d (%d):0117 Xmit ELS response x%x to remote "
++                              "%d:0117 Xmit ELS response x%x to remote "
+                               "NPORT x%x I/O tag: x%x, size: x%x\n",
+-                              phba->brd_no, vport->vpi, elscmd,
++                              phba->brd_no, elscmd,
+                               ndlp->nlp_DID, elsiocb->iotag, cmdSize);
+       }
+@@ -230,79 +240,16 @@
+ static int
+-lpfc_issue_fabric_reglogin(struct lpfc_vport *vport)
++lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
++              struct serv_parm *sp, IOCB_t *irsp)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+       LPFC_MBOXQ_t *mbox;
+       struct lpfc_dmabuf *mp;
+-      struct lpfc_nodelist *ndlp;
+-      struct serv_parm *sp;
+       int rc;
+-      sp = &phba->fc_fabparam;
+-      ndlp = lpfc_findnode_did(vport, Fabric_DID);
+-      if (!ndlp)
+-              goto fail;
+-
+-      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (!mbox)
+-              goto fail;
+-
+-      vport->port_state = LPFC_FABRIC_CFG_LINK;
+-      lpfc_config_link(phba, mbox);
+-      mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-      mbox->vport = vport;
+-
+-      rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
+-      if (rc == MBX_NOT_FINISHED)
+-              goto fail_free_mbox;
+-
+-      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (!mbox)
+-              goto fail;
+-      rc = lpfc_reg_login(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox,
+-                          0);
+-      if (rc)
+-              goto fail_free_mbox;
+-
+-      mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
+-      mbox->vport = vport;
+-      mbox->context2 = lpfc_nlp_get(ndlp);
+-
+-      rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
+-      if (rc == MBX_NOT_FINISHED)
+-              goto fail_issue_reg_login;
+-
+-      return 0;
+-
+-fail_issue_reg_login:
+-      lpfc_nlp_put(ndlp);
+-      mp = (struct lpfc_dmabuf *) mbox->context1;
+-      lpfc_mbuf_free(phba, mp->virt, mp->phys);
+-      kfree(mp);
+-fail_free_mbox:
+-      mempool_free(mbox, phba->mbox_mem_pool);
+-
+-fail:
+-      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-      lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-              "%d (%d):0249 Cannot issue Register Fabric login\n",
+-              phba->brd_no, vport->vpi);
+-      return -ENXIO;
+-}
+-
+-static int
+-lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                         struct serv_parm *sp, IOCB_t *irsp)
+-{
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+-      struct lpfc_nodelist *np;
+-      struct lpfc_nodelist *next_np;
+-
+-      spin_lock_irq(shost->host_lock);
+-      vport->fc_flag |= FC_FABRIC;
+-      spin_unlock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
++      phba->fc_flag |= FC_FABRIC;
++      spin_unlock_irq(phba->host->host_lock);
+       phba->fc_edtov = be32_to_cpu(sp->cmn.e_d_tov);
+       if (sp->cmn.edtovResolution)    /* E_D_TOV ticks are in nanoseconds */
+@@ -311,20 +258,20 @@
+       phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000;
+       if (phba->fc_topology == TOPOLOGY_LOOP) {
+-              spin_lock_irq(shost->host_lock);
+-              vport->fc_flag |= FC_PUBLIC_LOOP;
+-              spin_unlock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
++              phba->fc_flag |= FC_PUBLIC_LOOP;
++              spin_unlock_irq(phba->host->host_lock);
+       } else {
+               /*
+                * If we are a N-port connected to a Fabric, fixup sparam's so
+                * logins to devices on remote loops work.
+                */
+-              vport->fc_sparam.cmn.altBbCredit = 1;
++              phba->fc_sparam.cmn.altBbCredit = 1;
+       }
+-      vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
++      phba->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
+       memcpy(&ndlp->nlp_portname, &sp->portName, sizeof(struct lpfc_name));
+-      memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof(struct lpfc_name));
++      memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
+       ndlp->nlp_class_sup = 0;
+       if (sp->cls1.classValid)
+               ndlp->nlp_class_sup |= FC_COS_CLASS1;
+@@ -338,85 +285,68 @@
+                               sp->cmn.bbRcvSizeLsb;
+       memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
+-      if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+-              if (sp->cmn.response_multiple_NPort) {
+-                      lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT,
+-                                      "%d:1816 FLOGI NPIV supported, "
+-                                      "response data 0x%x\n",
+-                                      phba->brd_no,
+-                                      sp->cmn.response_multiple_NPort);
+-                      phba->link_flag |= LS_NPIV_FAB_SUPPORTED;
++      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
++      if (!mbox)
++              goto fail;
+-              } else {
+-                      /* Because we asked f/w for NPIV it still expects us
+-                         to call reg_vnpid atleast for the physcial host */
+-                      lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT,
+-                                      "%d:1817 Fabric does not support NPIV "
+-                                      "- configuring single port mode.\n",
+-                                      phba->brd_no);
+-                      phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
+-              }
+-      }
++      phba->hba_state = LPFC_FABRIC_CFG_LINK;
++      lpfc_config_link(phba, mbox);
++      mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-      if ((vport->fc_prevDID != vport->fc_myDID) &&
+-              !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
++      rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
++      if (rc == MBX_NOT_FINISHED)
++              goto fail_free_mbox;
+-              /* If our NportID changed, we need to ensure all
+-               * remaining NPORTs get unreg_login'ed.
+-               */
+-              list_for_each_entry_safe(np, next_np,
+-                                      &vport->fc_nodes, nlp_listp) {
+-                      if ((np->nlp_state != NLP_STE_NPR_NODE) ||
+-                                 !(np->nlp_flag & NLP_NPR_ADISC))
+-                              continue;
+-                      spin_lock_irq(shost->host_lock);
+-                      np->nlp_flag &= ~NLP_NPR_ADISC;
+-                      spin_unlock_irq(shost->host_lock);
+-                      lpfc_unreg_rpi(vport, np);
+-              }
+-              if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+-                      lpfc_mbx_unreg_vpi(vport);
+-                      vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+-              }
+-      }
++      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
++      if (!mbox)
++              goto fail;
+-      ndlp->nlp_sid = irsp->un.ulpWord[4] & Mask_DID;
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE);
++      if (lpfc_reg_login(phba, Fabric_DID, (uint8_t *) sp, mbox, 0))
++              goto fail_free_mbox;
 +
-+      /* For symlinks, we must read the link before we lock the directory. */
-+      if (S_ISLNK(old_hidden_dentry->d_inode->i_mode)) {
++      mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
++      mbox->context2 = lpfc_nlp_get(ndlp);
 +
-+              symbuf = kmalloc(PATH_MAX, GFP_KERNEL);
-+              if (!symbuf) {
-+                      __clear(dentry, old_hidden_dentry,
-+                              old_bstart, old_bend,
-+                              new_hidden_dentry, new_bindex);
-+                      err = -ENOMEM;
-+                      goto out_free;
-+              }
++      rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
++      if (rc == MBX_NOT_FINISHED)
++              goto fail_issue_reg_login;
+-      if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED &&
+-          vport->fc_flag & FC_VPORT_NEEDS_REG_VPI) {
+-              lpfc_register_new_vport(phba, vport, ndlp);
+-              return 0;
+-      }
+-      lpfc_issue_fabric_reglogin(vport);
+       return 0;
 +
-+              oldfs = get_fs();
-+              set_fs(KERNEL_DS);
-+              err = old_hidden_dentry->d_inode->i_op->readlink(
-+                      old_hidden_dentry,
-+                      (char __user *)symbuf,
-+                      PATH_MAX);
-+              set_fs(oldfs);
-+              if (err) {
-+                      __clear(dentry, old_hidden_dentry,
-+                              old_bstart, old_bend,
-+                              new_hidden_dentry, new_bindex);
-+                      goto out_free;
++ fail_issue_reg_login:
++      lpfc_nlp_put(ndlp);
++      mp = (struct lpfc_dmabuf *) mbox->context1;
++      lpfc_mbuf_free(phba, mp->virt, mp->phys);
++      kfree(mp);
++ fail_free_mbox:
++      mempool_free(mbox, phba->mbox_mem_pool);
++ fail:
++      return -ENXIO;
+ }
+ /*
+  * We FLOGIed into an NPort, initiate pt2pt protocol
+  */
+ static int
+-lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
++lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+               struct serv_parm *sp)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+       LPFC_MBOXQ_t *mbox;
+       int rc;
+-      spin_lock_irq(shost->host_lock);
+-      vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+-      spin_unlock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
++      phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
++      spin_unlock_irq(phba->host->host_lock);
+       phba->fc_edtov = FF_DEF_EDTOV;
+       phba->fc_ratov = FF_DEF_RATOV;
+-      rc = memcmp(&vport->fc_portname, &sp->portName,
+-                  sizeof(vport->fc_portname));
++      rc = memcmp(&phba->fc_portname, &sp->portName,
++                      sizeof(struct lpfc_name));
+       if (rc >= 0) {
+               /* This side will initiate the PLOGI */
+-              spin_lock_irq(shost->host_lock);
+-              vport->fc_flag |= FC_PT2PT_PLOGI;
+-              spin_unlock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
++              phba->fc_flag |= FC_PT2PT_PLOGI;
++              spin_unlock_irq(phba->host->host_lock);
+               /*
+                * N_Port ID cannot be 0, set our to LocalID the other
+@@ -425,7 +355,7 @@
+               /* not equal */
+               if (rc)
+-                      vport->fc_myDID = PT2PT_LocalID;
++                      phba->fc_myDID = PT2PT_LocalID;
+               mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+               if (!mbox)
+@@ -434,7 +364,6 @@
+               lpfc_config_link(phba, mbox);
+               mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-              mbox->vport = vport;
+               rc = lpfc_sli_issue_mbox(phba, mbox,
+                               MBX_NOWAIT | MBX_STOP_IOCB);
+               if (rc == MBX_NOT_FINISHED) {
+@@ -443,7 +372,7 @@
+               }
+               lpfc_nlp_put(ndlp);
+-              ndlp = lpfc_findnode_did(vport, PT2PT_RemoteID);
++              ndlp = lpfc_findnode_did(phba, PT2PT_RemoteID);
+               if (!ndlp) {
+                       /*
+                        * Cannot find existing Fabric ndlp, so allocate a
+@@ -453,30 +382,28 @@
+                       if (!ndlp)
+                               goto fail;
+-                      lpfc_nlp_init(vport, ndlp, PT2PT_RemoteID);
++                      lpfc_nlp_init(phba, ndlp, PT2PT_RemoteID);
+               }
+               memcpy(&ndlp->nlp_portname, &sp->portName,
+                               sizeof(struct lpfc_name));
+               memcpy(&ndlp->nlp_nodename, &sp->nodeName,
+                               sizeof(struct lpfc_name));
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+-              spin_lock_irq(shost->host_lock);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+-              spin_unlock_irq(shost->host_lock);
+       } else {
+               /* This side will wait for the PLOGI */
+               lpfc_nlp_put(ndlp);
+       }
+-      spin_lock_irq(shost->host_lock);
+-      vport->fc_flag |= FC_PT2PT;
+-      spin_unlock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
++      phba->fc_flag |= FC_PT2PT;
++      spin_unlock_irq(phba->host->host_lock);
+       /* Start discovery - this should just do CLEAR_LA */
+-      lpfc_disc_start(vport);
++      lpfc_disc_start(phba);
+       return 0;
+-fail:
++ fail:
+       return -ENXIO;
+ }
+@@ -484,8 +411,6 @@
+ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+                   struct lpfc_iocbq *rspiocb)
+ {
+-      struct lpfc_vport *vport = cmdiocb->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+       IOCB_t *irsp = &rspiocb->iocb;
+       struct lpfc_nodelist *ndlp = cmdiocb->context1;
+       struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp;
+@@ -493,25 +418,21 @@
+       int rc;
+       /* Check to see if link went down during discovery */
+-      if (lpfc_els_chk_latt(vport)) {
++      if (lpfc_els_chk_latt(phba)) {
+               lpfc_nlp_put(ndlp);
+               goto out;
+       }
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "FLOGI cmpl:      status:x%x/x%x state:x%x",
+-              irsp->ulpStatus, irsp->un.ulpWord[4],
+-              vport->port_state);
+-
+       if (irsp->ulpStatus) {
+               /* Check for retry */
+-              if (lpfc_els_retry(phba, cmdiocb, rspiocb))
++              if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
++                      /* ELS command is being retried */
+                       goto out;
+-
 +              }
-+              symbuf[err] = '\0';
-+      }
-+
-+      /* Now we lock the parent, and create the object in the new branch. */
-+      new_hidden_parent_dentry = lock_parent(new_hidden_dentry);
-+
-+      /* create the new inode */
-+      err = __copyup_ndentry(old_hidden_dentry, new_hidden_dentry,
-+                             new_hidden_parent_dentry, symbuf);
-+
-+      if (err) {
-+              __clear(dentry, old_hidden_dentry,
-+                      old_bstart, old_bend,
-+                      new_hidden_dentry, new_bindex);
-+              goto out_unlock;
-+      }
-+
-+      /* We actually copyup the file here. */
-+      if (S_ISREG(old_hidden_dentry->d_inode->i_mode))
-+              err = __copyup_reg_data(dentry, new_hidden_dentry, new_bindex,
-+                                      old_hidden_dentry, old_bindex,
-+                                      copyup_file, len);
-+      if (err)
-+              goto out_unlink;
-+
-+      /* Set permissions. */
-+      if ((err = copyup_permissions(sb, old_hidden_dentry,
-+                                    new_hidden_dentry)))
-+              goto out_unlink;
-+
-+#ifdef CONFIG_UNION_FS_XATTR
-+      /* Selinux uses extended attributes for permissions. */
-+      if ((err = copyup_xattrs(old_hidden_dentry, new_hidden_dentry)))
-+              goto out_unlink;
-+#endif
-+
-+      /* do not allow files getting deleted to be re-interposed */
-+      if (!d_deleted(dentry))
-+              unionfs_reinterpose(dentry);
-+
-+      goto out_unlock;
-+
-+out_unlink:
-+      /*
-+       * copyup failed, because we possibly ran out of space or
-+       * quota, or something else happened so let's unlink; we don't
-+       * really care about the return value of vfs_unlink
-+       */
-+      vfs_unlink(new_hidden_parent_dentry->d_inode, new_hidden_dentry);
-+
-+      if (copyup_file) {
-+              /* need to close the file */
-+
-+              fput(*copyup_file);
-+              branchput(sb, new_bindex);
-+      }
-+
-+      /*
-+       * TODO: should we reset the error to something like -EIO?
-+       *
-+       * If we don't reset, the user may get some nonsensical errors, but
-+       * on the other hand, if we reset to EIO, we guarantee that the user
-+       * will get a "confusing" error message.
-+       */
-+
-+out_unlock:
-+      unlock_dir(new_hidden_parent_dentry);
-+
-+out_free:
-+      /*
-+       * If old_hidden_dentry was a directory, we need to dput it.  If it
-+       * was a file, then it was already dput indirectly by other
-+       * functions we call above which operate on regular files.
-+       */
-+      if (old_hidden_dentry && old_hidden_dentry->d_inode &&
-+          S_ISDIR(old_hidden_dentry->d_inode->i_mode))
-+              dput(old_hidden_dentry);
-+      kfree(symbuf);
-+
-+out:
-+      return err;
-+}
-+
-+/*
-+ * This function creates a copy of a file represented by 'file' which
-+ * currently resides in branch 'bstart' to branch 'new_bindex.'  The copy
-+ * will be named "name".
-+ */
-+int copyup_named_file(struct inode *dir, struct file *file, char *name,
-+                    int bstart, int new_bindex, loff_t len)
-+{
-+      int err = 0;
-+      struct file *output_file = NULL;
-+
-+      err = copyup_named_dentry(dir, file->f_dentry, bstart,
-+                                new_bindex, name, strlen(name), &output_file,
-+                                len);
-+      if (!err) {
-+              fbstart(file) = new_bindex;
-+              unionfs_set_lower_file_idx(file, new_bindex, output_file);
+               /* FLOGI failed, so there is no fabric */
+-              spin_lock_irq(shost->host_lock);
+-              vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+-              spin_unlock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
++              phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
++              spin_unlock_irq(phba->host->host_lock);
+               /* If private loop, then allow max outstanding els to be
+                * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no
+@@ -522,10 +443,11 @@
+               }
+               /* FLOGI failure */
+-              lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                              "%d (%d):0100 FLOGI failure Data: x%x x%x "
+-                              "x%x\n",
+-                              phba->brd_no, vport->vpi,
++              lpfc_printf_log(phba,
++                              KERN_INFO,
++                              LOG_ELS,
++                              "%d:0100 FLOGI failure Data: x%x x%x x%x\n",
++                              phba->brd_no,
+                               irsp->ulpStatus, irsp->un.ulpWord[4],
+                               irsp->ulpTimeout);
+               goto flogifail;
+@@ -541,21 +463,21 @@
+       /* FLOGI completes successfully */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0101 FLOGI completes sucessfully "
++                      "%d:0101 FLOGI completes sucessfully "
+                       "Data: x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi,
++                      phba->brd_no,
+                       irsp->un.ulpWord[4], sp->cmn.e_d_tov,
+                       sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution);
+-      if (vport->port_state == LPFC_FLOGI) {
++      if (phba->hba_state == LPFC_FLOGI) {
+               /*
+                * If Common Service Parameters indicate Nport
+                * we are point to point, if Fport we are Fabric.
+                */
+               if (sp->cmn.fPort)
+-                      rc = lpfc_cmpl_els_flogi_fabric(vport, ndlp, sp, irsp);
++                      rc = lpfc_cmpl_els_flogi_fabric(phba, ndlp, sp, irsp);
+               else
+-                      rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp);
++                      rc = lpfc_cmpl_els_flogi_nport(phba, ndlp, sp);
+               if (!rc)
+                       goto out;
+@@ -564,12 +486,14 @@
+ flogifail:
+       lpfc_nlp_put(ndlp);
+-      if (!lpfc_error_lost_link(irsp)) {
++      if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
++          (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED &&
++           irsp->un.ulpWord[4] != IOERR_SLI_DOWN)) {
+               /* FLOGI failed, so just use loop map to make discovery list */
+-              lpfc_disc_list_loopmap(vport);
++              lpfc_disc_list_loopmap(phba);
+               /* Start discovery */
+-              lpfc_disc_start(vport);
++              lpfc_disc_start(phba);
+       }
+ out:
+@@ -577,10 +501,9 @@
+ }
+ static int
+-lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
++lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
+                    uint8_t retry)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+       struct serv_parm *sp;
+       IOCB_t *icmd;
+       struct lpfc_iocbq *elsiocb;
+@@ -592,10 +515,9 @@
+       pring = &phba->sli.ring[LPFC_ELS_RING];
+-      cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
+-      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
++      cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
++      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
+                                                ndlp->nlp_DID, ELS_CMD_FLOGI);
+-
+       if (!elsiocb)
+               return 1;
+@@ -604,8 +526,8 @@
+       /* For FLOGI request, remainder of payload is service parameters */
+       *((uint32_t *) (pcmd)) = ELS_CMD_FLOGI;
+-      pcmd += sizeof(uint32_t);
+-      memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
++      pcmd += sizeof (uint32_t);
++      memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
+       sp = (struct serv_parm *) pcmd;
+       /* Setup CSPs accordingly for Fabric */
+@@ -619,32 +541,16 @@
+       if (sp->cmn.fcphHigh < FC_PH3)
+               sp->cmn.fcphHigh = FC_PH3;
+-      if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+-              sp->cmn.request_multiple_Nport = 1;
+-
+-              /* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */
+-              icmd->ulpCt_h = 1;
+-              icmd->ulpCt_l = 0;
+-      }
+-
+-      if (phba->fc_topology != TOPOLOGY_LOOP) {
+-              icmd->un.elsreq64.myID = 0;
+-              icmd->un.elsreq64.fl = 1;
+-      }
+-
+       tmo = phba->fc_ratov;
+       phba->fc_ratov = LPFC_DISC_FLOGI_TMO;
+-      lpfc_set_disctmo(vport);
++      lpfc_set_disctmo(phba);
+       phba->fc_ratov = tmo;
+       phba->fc_stat.elsXmitFLOGI++;
+       elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "Issue FLOGI:     opt:x%x",
+-              phba->sli3_options, 0, 0);
+-
+-      rc = lpfc_issue_fabric_iocb(phba, elsiocb);
++      spin_lock_irq(phba->host->host_lock);
++      rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
++      spin_unlock_irq(phba->host->host_lock);
+       if (rc == IOCB_ERROR) {
+               lpfc_els_free_iocb(phba, elsiocb);
+               return 1;
+@@ -653,7 +559,7 @@
+ }
+ int
+-lpfc_els_abort_flogi(struct lpfc_hba *phba)
++lpfc_els_abort_flogi(struct lpfc_hba * phba)
+ {
+       struct lpfc_sli_ring *pring;
+       struct lpfc_iocbq *iocb, *next_iocb;
+@@ -671,99 +577,73 @@
+        * Check the txcmplq for an iocb that matches the nport the driver is
+        * searching for.
+        */
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
+               icmd = &iocb->iocb;
+-              if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
+-                  icmd->un.elsreq64.bdl.ulpIoTag32) {
++              if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
+                       ndlp = (struct lpfc_nodelist *)(iocb->context1);
+-                      if (ndlp && (ndlp->nlp_DID == Fabric_DID)) {
++                      if (ndlp && (ndlp->nlp_DID == Fabric_DID))
+                               lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+               }
+       }
+-      }
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       return 0;
+ }
+ int
+-lpfc_initial_flogi(struct lpfc_vport *vport)
++lpfc_initial_flogi(struct lpfc_hba *phba)
+ {
+-      struct lpfc_hba *phba = vport->phba;
+       struct lpfc_nodelist *ndlp;
+       /* First look for the Fabric ndlp */
+-      ndlp = lpfc_findnode_did(vport, Fabric_DID);
++      ndlp = lpfc_findnode_did(phba, Fabric_DID);
+       if (!ndlp) {
+               /* Cannot find existing Fabric ndlp, so allocate a new one */
+               ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+               if (!ndlp)
+                       return 0;
+-              lpfc_nlp_init(vport, ndlp, Fabric_DID);
++              lpfc_nlp_init(phba, ndlp, Fabric_DID);
+       } else {
+-              lpfc_dequeue_node(vport, ndlp);
++              lpfc_dequeue_node(phba, ndlp);
+       }
+-      if (lpfc_issue_els_flogi(vport, ndlp, 0)) {
++      if (lpfc_issue_els_flogi(phba, ndlp, 0)) {
+               lpfc_nlp_put(ndlp);
+       }
+       return 1;
+ }
+-int
+-lpfc_initial_fdisc(struct lpfc_vport *vport)
+-{
+-      struct lpfc_hba *phba = vport->phba;
+-      struct lpfc_nodelist *ndlp;
+-
+-      /* First look for the Fabric ndlp */
+-      ndlp = lpfc_findnode_did(vport, Fabric_DID);
+-      if (!ndlp) {
+-              /* Cannot find existing Fabric ndlp, so allocate a new one */
+-              ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+-              if (!ndlp)
+-                      return 0;
+-              lpfc_nlp_init(vport, ndlp, Fabric_DID);
+-      } else {
+-              lpfc_dequeue_node(vport, ndlp);
+-      }
+-      if (lpfc_issue_els_fdisc(vport, ndlp, 0)) {
+-              lpfc_nlp_put(ndlp);
+-      }
+-      return 1;
+-}
+ static void
+-lpfc_more_plogi(struct lpfc_vport *vport)
++lpfc_more_plogi(struct lpfc_hba * phba)
+ {
+       int sentplogi;
+-      struct lpfc_hba *phba = vport->phba;
+-      if (vport->num_disc_nodes)
+-              vport->num_disc_nodes--;
++      if (phba->num_disc_nodes)
++              phba->num_disc_nodes--;
+       /* Continue discovery with <num_disc_nodes> PLOGIs to go */
+       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0232 Continue discovery with %d PLOGIs to go "
++                      "%d:0232 Continue discovery with %d PLOGIs to go "
+                       "Data: x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, vport->num_disc_nodes,
+-                      vport->fc_plogi_cnt, vport->fc_flag, vport->port_state);
++                      phba->brd_no, phba->num_disc_nodes, phba->fc_plogi_cnt,
++                      phba->fc_flag, phba->hba_state);
+       /* Check to see if there are more PLOGIs to be sent */
+-      if (vport->fc_flag & FC_NLP_MORE)
+-              /* go thru NPR nodes and issue any remaining ELS PLOGIs */
+-              sentplogi = lpfc_els_disc_plogi(vport);
+-
++      if (phba->fc_flag & FC_NLP_MORE) {
++              /* go thru NPR list and issue any remaining ELS PLOGIs */
++              sentplogi = lpfc_els_disc_plogi(phba);
 +      }
+       return;
+ }
+ static struct lpfc_nodelist *
+-lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
++lpfc_plogi_confirm_nport(struct lpfc_hba *phba, struct lpfc_dmabuf *prsp,
+                        struct lpfc_nodelist *ndlp)
+ {
+-      struct lpfc_vport    *vport = ndlp->vport;
+       struct lpfc_nodelist *new_ndlp;
++      uint32_t *lp;
+       struct serv_parm *sp;
+-      uint8_t  name[sizeof(struct lpfc_name)];
++      uint8_t name[sizeof (struct lpfc_name)];
+       uint32_t rc;
+       /* Fabric nodes can have the same WWPN so we don't bother searching
+@@ -772,51 +652,50 @@
+       if (ndlp->nlp_type & NLP_FABRIC)
+               return ndlp;
+-      sp = (struct serv_parm *) ((uint8_t *) prsp + sizeof(uint32_t));
++      lp = (uint32_t *) prsp->virt;
++      sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
+       memset(name, 0, sizeof(struct lpfc_name));
+       /* Now we find out if the NPort we are logging into, matches the WWPN
+        * we have for that ndlp. If not, we have some work to do.
+        */
+-      new_ndlp = lpfc_findnode_wwpn(vport, &sp->portName);
++      new_ndlp = lpfc_findnode_wwpn(phba, &sp->portName);
+       if (new_ndlp == ndlp)
+               return ndlp;
+       if (!new_ndlp) {
+-              rc = memcmp(&ndlp->nlp_portname, name,
+-                          sizeof(struct lpfc_name));
++              rc =
++                 memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name));
+               if (!rc)
+                       return ndlp;
+               new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
+               if (!new_ndlp)
+                       return ndlp;
+-              lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID);
++              lpfc_nlp_init(phba, new_ndlp, ndlp->nlp_DID);
+       }
+-      lpfc_unreg_rpi(vport, new_ndlp);
++      lpfc_unreg_rpi(phba, new_ndlp);
+       new_ndlp->nlp_DID = ndlp->nlp_DID;
+       new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
+-      lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state);
++      lpfc_nlp_set_state(phba, new_ndlp, ndlp->nlp_state);
+-      /* Move this back to NPR state */
++      /* Move this back to NPR list */
+       if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0)
+-              lpfc_drop_node(vport, ndlp);
++              lpfc_drop_node(phba, ndlp);
+       else {
+-              lpfc_unreg_rpi(vport, ndlp);
++              lpfc_unreg_rpi(phba, ndlp);
+               ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+       }
+       return new_ndlp;
+ }
+ static void
+-lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                  struct lpfc_iocbq *rspiocb)
++lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                  struct lpfc_iocbq * rspiocb)
+ {
+-      struct lpfc_vport *vport = cmdiocb->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+       IOCB_t *irsp;
+       struct lpfc_nodelist *ndlp;
+       struct lpfc_dmabuf *prsp;
+@@ -826,43 +705,32 @@
+       cmdiocb->context_un.rsp_iocb = rspiocb;
+       irsp = &rspiocb->iocb;
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "PLOGI cmpl:      status:x%x/x%x did:x%x",
+-              irsp->ulpStatus, irsp->un.ulpWord[4],
+-              irsp->un.elsreq64.remoteID);
+-
+-      ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
+-      if (!ndlp) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                      "%d (%d):0136 PLOGI completes to NPort x%x "
+-                      "with no ndlp. Data: x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, irsp->un.elsreq64.remoteID,
+-                      irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpIoTag);
++      ndlp = lpfc_findnode_did(phba, irsp->un.elsreq64.remoteID);
++      if (!ndlp)
+               goto out;
+-      }
+       /* Since ndlp can be freed in the disc state machine, note if this node
+        * is being used during discovery.
+        */
+-      spin_lock_irq(shost->host_lock);
+       disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+-      spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+       rc   = 0;
+       /* PLOGI completes to NPort <nlp_DID> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0102 PLOGI completes to NPort x%x "
++                      "%d:0102 PLOGI completes to NPort x%x "
+                       "Data: x%x x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, ndlp->nlp_DID,
+-                      irsp->ulpStatus, irsp->un.ulpWord[4],
+-                      irsp->ulpTimeout, disc, vport->num_disc_nodes);
++                      phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
++                      irsp->un.ulpWord[4], irsp->ulpTimeout, disc,
++                      phba->num_disc_nodes);
+       /* Check to see if link went down during discovery */
+-      if (lpfc_els_chk_latt(vport)) {
+-              spin_lock_irq(shost->host_lock);
++      if (lpfc_els_chk_latt(phba)) {
++              spin_lock_irq(phba->host->host_lock);
+               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+               goto out;
+       }
+@@ -875,28 +743,22 @@
+               if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
+                       /* ELS command is being retried */
+                       if (disc) {
+-                              spin_lock_irq(shost->host_lock);
++                              spin_lock_irq(phba->host->host_lock);
+                               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+-                              spin_unlock_irq(shost->host_lock);
++                              spin_unlock_irq(phba->host->host_lock);
+                       }
+                       goto out;
+               }
+               /* PLOGI failed */
+-              if (ndlp->nlp_DID == NameServer_DID) {
+-                      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                              "%d (%d):0250 Nameserver login error: "
+-                              "0x%x / 0x%x\n",
+-                              phba->brd_no, vport->vpi,
+-                              irsp->ulpStatus, irsp->un.ulpWord[4]);
+-              }
+-
+               /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
+-              if (lpfc_error_lost_link(irsp)) {
++              if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
++                 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
++                 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
++                 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
+                       rc = NLP_STE_FREED_NODE;
+               } else {
+-                      rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb,
++                      rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
+                                       NLP_EVT_CMPL_PLOGI);
+               }
+       } else {
+@@ -904,33 +766,33 @@
+               prsp = list_entry(((struct lpfc_dmabuf *)
+                       cmdiocb->context2)->list.next,
+                       struct lpfc_dmabuf, list);
+-              ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp);
+-              rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb,
++              ndlp = lpfc_plogi_confirm_nport(phba, prsp, ndlp);
++              rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
+                                       NLP_EVT_CMPL_PLOGI);
+       }
+-      if (disc && vport->num_disc_nodes) {
++      if (disc && phba->num_disc_nodes) {
+               /* Check to see if there are more PLOGIs to be sent */
+-              lpfc_more_plogi(vport);
++              lpfc_more_plogi(phba);
+-              if (vport->num_disc_nodes == 0) {
+-                      spin_lock_irq(shost->host_lock);
+-                      vport->fc_flag &= ~FC_NDISC_ACTIVE;
+-                      spin_unlock_irq(shost->host_lock);
++              if (phba->num_disc_nodes == 0) {
++                      spin_lock_irq(phba->host->host_lock);
++                      phba->fc_flag &= ~FC_NDISC_ACTIVE;
++                      spin_unlock_irq(phba->host->host_lock);
+-                      lpfc_can_disctmo(vport);
+-                      if (vport->fc_flag & FC_RSCN_MODE) {
++                      lpfc_can_disctmo(phba);
++                      if (phba->fc_flag & FC_RSCN_MODE) {
+                               /*
+                                * Check to see if more RSCNs came in while
+                                * we were processing this one.
+                                */
+-                              if ((vport->fc_rscn_id_cnt == 0) &&
+-                                  (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
+-                                      spin_lock_irq(shost->host_lock);
+-                                      vport->fc_flag &= ~FC_RSCN_MODE;
+-                                      spin_unlock_irq(shost->host_lock);
++                              if ((phba->fc_rscn_id_cnt == 0) &&
++                              (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
++                                      spin_lock_irq(phba->host->host_lock);
++                                      phba->fc_flag &= ~FC_RSCN_MODE;
++                                      spin_unlock_irq(phba->host->host_lock);
+                               } else {
+-                                      lpfc_els_handle_rscn(vport);
++                                      lpfc_els_handle_rscn(phba);
+                               }
+                       }
+               }
+@@ -942,9 +804,8 @@
+ }
+ int
+-lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
++lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+       struct serv_parm *sp;
+       IOCB_t *icmd;
+       struct lpfc_iocbq *elsiocb;
+@@ -952,13 +813,12 @@
+       struct lpfc_sli *psli;
+       uint8_t *pcmd;
+       uint16_t cmdsize;
+-      int ret;
+       psli = &phba->sli;
+       pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
+-      cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
+-      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, NULL, did,
++      cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
++      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, NULL, did,
+                                                               ELS_CMD_PLOGI);
+       if (!elsiocb)
+               return 1;
+@@ -968,8 +828,8 @@
+       /* For PLOGI request, remainder of payload is service parameters */
+       *((uint32_t *) (pcmd)) = ELS_CMD_PLOGI;
+-      pcmd += sizeof(uint32_t);
+-      memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
++      pcmd += sizeof (uint32_t);
++      memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
+       sp = (struct serv_parm *) pcmd;
+       if (sp->cmn.fcphLow < FC_PH_4_3)
+@@ -978,27 +838,22 @@
+       if (sp->cmn.fcphHigh < FC_PH3)
+               sp->cmn.fcphHigh = FC_PH3;
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "Issue PLOGI:     did:x%x",
+-              did, 0, 0);
+-
+       phba->fc_stat.elsXmitPLOGI++;
+       elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
+-      ret = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
+-
+-      if (ret == IOCB_ERROR) {
++      spin_lock_irq(phba->host->host_lock);
++      if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
++              spin_unlock_irq(phba->host->host_lock);
+               lpfc_els_free_iocb(phba, elsiocb);
+               return 1;
+       }
++      spin_unlock_irq(phba->host->host_lock);
+       return 0;
+ }
+ static void
+-lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                 struct lpfc_iocbq *rspiocb)
++lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                 struct lpfc_iocbq * rspiocb)
+ {
+-      struct lpfc_vport *vport = cmdiocb->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+       IOCB_t *irsp;
+       struct lpfc_sli *psli;
+       struct lpfc_nodelist *ndlp;
+@@ -1009,26 +864,21 @@
+       irsp = &(rspiocb->iocb);
+       ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+-      spin_lock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag &= ~NLP_PRLI_SND;
+-      spin_unlock_irq(shost->host_lock);
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "PRLI cmpl:       status:x%x/x%x did:x%x",
+-              irsp->ulpStatus, irsp->un.ulpWord[4],
+-              ndlp->nlp_DID);
++      spin_unlock_irq(phba->host->host_lock);
+       /* PRLI completes to NPort <nlp_DID> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0103 PRLI completes to NPort x%x "
++                      "%d:0103 PRLI completes to NPort x%x "
+                       "Data: x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, ndlp->nlp_DID,
+-                      irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
+-                      vport->num_disc_nodes);
++                      phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
++                      irsp->un.ulpWord[4], irsp->ulpTimeout,
++                      phba->num_disc_nodes);
+-      vport->fc_prli_sent--;
++      phba->fc_prli_sent--;
+       /* Check to see if link went down during discovery */
+-      if (lpfc_els_chk_latt(vport))
++      if (lpfc_els_chk_latt(phba))
+               goto out;
+       if (irsp->ulpStatus) {
+@@ -1039,16 +889,18 @@
+               }
+               /* PRLI failed */
+               /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
+-              if (lpfc_error_lost_link(irsp)) {
++              if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
++                 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
++                 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
++                 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
+                       goto out;
+               } else {
+-                      lpfc_disc_state_machine(vport, ndlp, cmdiocb,
++                      lpfc_disc_state_machine(phba, ndlp, cmdiocb,
+                                       NLP_EVT_CMPL_PRLI);
+               }
+       } else {
+               /* Good status, call state machine */
+-              lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+-                                      NLP_EVT_CMPL_PRLI);
++              lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_PRLI);
+       }
+ out:
+@@ -1057,11 +909,9 @@
+ }
+ int
+-lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
++lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
+                   uint8_t retry)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba *phba = vport->phba;
+       PRLI *npr;
+       IOCB_t *icmd;
+       struct lpfc_iocbq *elsiocb;
+@@ -1073,8 +923,8 @@
+       psli = &phba->sli;
+       pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
+-      cmdsize = (sizeof(uint32_t) + sizeof(PRLI));
+-      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
++      cmdsize = (sizeof (uint32_t) + sizeof (PRLI));
++      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
+                                       ndlp->nlp_DID, ELS_CMD_PRLI);
+       if (!elsiocb)
+               return 1;
+@@ -1083,9 +933,9 @@
+       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+       /* For PRLI request, remainder of payload is service parameters */
+-      memset(pcmd, 0, (sizeof(PRLI) + sizeof(uint32_t)));
++      memset(pcmd, 0, (sizeof (PRLI) + sizeof (uint32_t)));
+       *((uint32_t *) (pcmd)) = ELS_CMD_PRLI;
+-      pcmd += sizeof(uint32_t);
++      pcmd += sizeof (uint32_t);
+       /* For PRLI, remainder of payload is PRLI parameter page */
+       npr = (PRLI *) pcmd;
+@@ -1105,88 +955,81 @@
+       npr->prliType = PRLI_FCP_TYPE;
+       npr->initiatorFunc = 1;
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "Issue PRLI:      did:x%x",
+-              ndlp->nlp_DID, 0, 0);
+-
+       phba->fc_stat.elsXmitPRLI++;
+       elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;
+-      spin_lock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag |= NLP_PRLI_SND;
+-      spin_unlock_irq(shost->host_lock);
+       if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+-              spin_lock_irq(shost->host_lock);
+               ndlp->nlp_flag &= ~NLP_PRLI_SND;
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+               lpfc_els_free_iocb(phba, elsiocb);
+               return 1;
+       }
+-      vport->fc_prli_sent++;
++      spin_unlock_irq(phba->host->host_lock);
++      phba->fc_prli_sent++;
+       return 0;
+ }
+ static void
+-lpfc_more_adisc(struct lpfc_vport *vport)
++lpfc_more_adisc(struct lpfc_hba * phba)
+ {
+       int sentadisc;
+-      struct lpfc_hba *phba = vport->phba;
+-      if (vport->num_disc_nodes)
+-              vport->num_disc_nodes--;
++      if (phba->num_disc_nodes)
++              phba->num_disc_nodes--;
+       /* Continue discovery with <num_disc_nodes> ADISCs to go */
+       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0210 Continue discovery with %d ADISCs to go "
++                      "%d:0210 Continue discovery with %d ADISCs to go "
+                       "Data: x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, vport->num_disc_nodes,
+-                      vport->fc_adisc_cnt, vport->fc_flag, vport->port_state);
++                      phba->brd_no, phba->num_disc_nodes, phba->fc_adisc_cnt,
++                      phba->fc_flag, phba->hba_state);
+       /* Check to see if there are more ADISCs to be sent */
+-      if (vport->fc_flag & FC_NLP_MORE) {
+-              lpfc_set_disctmo(vport);
+-              /* go thru NPR nodes and issue any remaining ELS ADISCs */
+-              sentadisc = lpfc_els_disc_adisc(vport);
++      if (phba->fc_flag & FC_NLP_MORE) {
++              lpfc_set_disctmo(phba);
 +
-+      return err;
-+}
-+
-+/*
-+ * This function creates a copy of a file represented by 'file' which
-+ * currently resides in branch 'bstart' to branch 'new_bindex'.
-+ */
-+int copyup_file(struct inode *dir, struct file *file, int bstart,
-+              int new_bindex, loff_t len)
-+{
-+      int err = 0;
-+      struct file *output_file = NULL;
-+
-+      err = copyup_dentry(dir, file->f_dentry, bstart, new_bindex,
-+                          &output_file, len);
-+      if (!err) {
-+              fbstart(file) = new_bindex;
-+              unionfs_set_lower_file_idx(file, new_bindex, output_file);
++              /* go thru NPR list and issue any remaining ELS ADISCs */
++              sentadisc = lpfc_els_disc_adisc(phba);
+       }
+       return;
+ }
+ static void
+-lpfc_rscn_disc(struct lpfc_vport *vport)
++lpfc_rscn_disc(struct lpfc_hba * phba)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+-      lpfc_can_disctmo(vport);
+-
+       /* RSCN discovery */
+-      /* go thru NPR nodes and issue ELS PLOGIs */
+-      if (vport->fc_npr_cnt)
+-              if (lpfc_els_disc_plogi(vport))
++      /* go thru NPR list and issue ELS PLOGIs */
++      if (phba->fc_npr_cnt) {
++              if (lpfc_els_disc_plogi(phba))
+                       return;
+-
+-      if (vport->fc_flag & FC_RSCN_MODE) {
 +      }
++      if (phba->fc_flag & FC_RSCN_MODE) {
+               /* Check to see if more RSCNs came in while we were
+                * processing this one.
+                */
+-              if ((vport->fc_rscn_id_cnt == 0) &&
+-                  (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
+-                      spin_lock_irq(shost->host_lock);
+-                      vport->fc_flag &= ~FC_RSCN_MODE;
+-                      spin_unlock_irq(shost->host_lock);
++              if ((phba->fc_rscn_id_cnt == 0) &&
++                  (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
++                      spin_lock_irq(phba->host->host_lock);
++                      phba->fc_flag &= ~FC_RSCN_MODE;
++                      spin_unlock_irq(phba->host->host_lock);
+               } else {
+-                      lpfc_els_handle_rscn(vport);
++                      lpfc_els_handle_rscn(phba);
+               }
+       }
+ }
+ static void
+-lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                  struct lpfc_iocbq *rspiocb)
++lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                  struct lpfc_iocbq * rspiocb)
+ {
+-      struct lpfc_vport *vport = cmdiocb->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+       IOCB_t *irsp;
++      struct lpfc_sli *psli;
+       struct lpfc_nodelist *ndlp;
+-      int  disc;
++      LPFC_MBOXQ_t *mbox;
++      int disc, rc;
 +
-+      return err;
-+}
-+
-+/*
-+ * This function replicates the directory structure up-to given dentry in the
-+ * bindex branch. Can create directory structure recursively to the right
-+ * also.
-+ */
-+struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
-+                            int bindex)
-+{
-+      return create_parents_named(dir, dentry, dentry->d_name.name, bindex);
-+}
-+
-+/* purge a dentry's lower-branch states (dput/mntput, etc.) */
-+static void __cleanup_dentry(struct dentry *dentry, int bindex,
-+                           int old_bstart, int old_bend)
-+{
-+      int loop_start;
-+      int loop_end;
-+      int new_bstart = -1;
-+      int new_bend = -1;
-+      int i;
-+
-+      loop_start = min(old_bstart, bindex);
-+      loop_end = max(old_bend, bindex);
-+
-+      /*
-+       * This loop sets the bstart and bend for the new dentry by
-+       * traversing from left to right.  It also dputs all negative
-+       * dentries except bindex
-+       */
-+      for (i = loop_start; i <= loop_end; i++) {
-+              if (!unionfs_lower_dentry_idx(dentry, i))
-+                      continue;
++      psli = &phba->sli;
+       /* we pass cmdiocb to state machine which needs rspiocb as well */
+       cmdiocb->context_un.rsp_iocb = rspiocb;
+@@ -1194,32 +1037,27 @@
+       irsp = &(rspiocb->iocb);
+       ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "ADISC cmpl:      status:x%x/x%x did:x%x",
+-              irsp->ulpStatus, irsp->un.ulpWord[4],
+-              ndlp->nlp_DID);
+-
+       /* Since ndlp can be freed in the disc state machine, note if this node
+        * is being used during discovery.
+        */
+-      spin_lock_irq(shost->host_lock);
+       disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC);
+-      spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+       /* ADISC completes to NPort <nlp_DID> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0104 ADISC completes to NPort x%x "
++                      "%d:0104 ADISC completes to NPort x%x "
+                       "Data: x%x x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, ndlp->nlp_DID,
+-                      irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
+-                      disc, vport->num_disc_nodes);
++                      phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
++                      irsp->un.ulpWord[4], irsp->ulpTimeout, disc,
++                      phba->num_disc_nodes);
+       /* Check to see if link went down during discovery */
+-      if (lpfc_els_chk_latt(vport)) {
+-              spin_lock_irq(shost->host_lock);
++      if (lpfc_els_chk_latt(phba)) {
++              spin_lock_irq(phba->host->host_lock);
+               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+               goto out;
+       }
+@@ -1228,68 +1066,67 @@
+               if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
+                       /* ELS command is being retried */
+                       if (disc) {
+-                              spin_lock_irq(shost->host_lock);
++                              spin_lock_irq(phba->host->host_lock);
+                               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+-                              spin_unlock_irq(shost->host_lock);
+-                              lpfc_set_disctmo(vport);
++                              spin_unlock_irq(phba->host->host_lock);
++                              lpfc_set_disctmo(phba);
+                       }
+                       goto out;
+               }
+               /* ADISC failed */
+               /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
+-              if (!lpfc_error_lost_link(irsp)) {
+-                      lpfc_disc_state_machine(vport, ndlp, cmdiocb,
++              if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
++                 ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) &&
++                 (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) &&
++                 (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) {
++                      lpfc_disc_state_machine(phba, ndlp, cmdiocb,
+                                       NLP_EVT_CMPL_ADISC);
+               }
+       } else {
+               /* Good status, call state machine */
+-              lpfc_disc_state_machine(vport, ndlp, cmdiocb,
++              lpfc_disc_state_machine(phba, ndlp, cmdiocb,
+                                       NLP_EVT_CMPL_ADISC);
+       }
+-      if (disc && vport->num_disc_nodes) {
++      if (disc && phba->num_disc_nodes) {
+               /* Check to see if there are more ADISCs to be sent */
+-              lpfc_more_adisc(vport);
++              lpfc_more_adisc(phba);
+               /* Check to see if we are done with ADISC authentication */
+-              if (vport->num_disc_nodes == 0) {
+-                      /* If we get here, there is nothing left to ADISC */
+-                      /*
+-                       * For NPIV, cmpl_reg_vpi will set port_state to READY,
+-                       * and continue discovery.
+-                       */
+-                      if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+-                         !(vport->fc_flag & FC_RSCN_MODE)) {
+-                              lpfc_issue_reg_vpi(phba, vport);
+-                              goto out;
+-                      }
+-                      /*
+-                       * For SLI2, we need to set port_state to READY
+-                       * and continue discovery.
+-                       */
+-                      if (vport->port_state < LPFC_VPORT_READY) {
+-                              /* If we get here, there is nothing to ADISC */
+-                              if (vport->port_type == LPFC_PHYSICAL_PORT)
+-                                      lpfc_issue_clear_la(phba, vport);
+-
+-                              if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) {
+-                                      vport->num_disc_nodes = 0;
+-                                      /* go thru NPR list, issue ELS PLOGIs */
+-                                      if (vport->fc_npr_cnt)
+-                                              lpfc_els_disc_plogi(vport);
+-
+-                                      if (!vport->num_disc_nodes) {
+-                                              spin_lock_irq(shost->host_lock);
+-                                              vport->fc_flag &=
+-                                                      ~FC_NDISC_ACTIVE;
+-                                              spin_unlock_irq(
+-                                                      shost->host_lock);
+-                                              lpfc_can_disctmo(vport);
++              if (phba->num_disc_nodes == 0) {
++                      lpfc_can_disctmo(phba);
++                      /* If we get here, there is nothing left to wait for */
++                      if ((phba->hba_state < LPFC_HBA_READY) &&
++                          (phba->hba_state != LPFC_CLEAR_LA)) {
++                              /* Link up discovery */
++                              if ((mbox = mempool_alloc(phba->mbox_mem_pool,
++                                                        GFP_KERNEL))) {
++                                      phba->hba_state = LPFC_CLEAR_LA;
++                                      lpfc_clear_la(phba, mbox);
++                                      mbox->mbox_cmpl =
++                                          lpfc_mbx_cmpl_clear_la;
++                                      rc = lpfc_sli_issue_mbox
++                                              (phba, mbox,
++                                               (MBX_NOWAIT | MBX_STOP_IOCB));
++                                      if (rc == MBX_NOT_FINISHED) {
++                                              mempool_free(mbox,
++                                                   phba->mbox_mem_pool);
++                                              lpfc_disc_flush_list(phba);
++                                              psli->ring[(psli->extra_ring)].
++                                                  flag &=
++                                                  ~LPFC_STOP_IOCB_EVENT;
++                                              psli->ring[(psli->fcp_ring)].
++                                                  flag &=
++                                                  ~LPFC_STOP_IOCB_EVENT;
++                                              psli->ring[(psli->next_ring)].
++                                                  flag &=
++                                                  ~LPFC_STOP_IOCB_EVENT;
++                                              phba->hba_state =
++                                                  LPFC_HBA_READY;
+                                       }
+                               }
+-                              vport->port_state = LPFC_VPORT_READY;
+                       } else {
+-                              lpfc_rscn_disc(vport);
++                              lpfc_rscn_disc(phba);
+                       }
+               }
+       }
+@@ -1299,21 +1136,22 @@
+ }
+ int
+-lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
++lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
+                    uint8_t retry)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+       ADISC *ap;
+       IOCB_t *icmd;
+       struct lpfc_iocbq *elsiocb;
+-      struct lpfc_sli *psli = &phba->sli;
+-      struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
++      struct lpfc_sli_ring *pring;
++      struct lpfc_sli *psli;
+       uint8_t *pcmd;
+       uint16_t cmdsize;
+-      cmdsize = (sizeof(uint32_t) + sizeof(ADISC));
+-      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
++      psli = &phba->sli;
++      pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
 +
-+              if (i == bindex) {
-+                      new_bend = i;
-+                      if (new_bstart < 0)
-+                              new_bstart = i;
-+                      continue;
++      cmdsize = (sizeof (uint32_t) + sizeof (ADISC));
++      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
+                                               ndlp->nlp_DID, ELS_CMD_ADISC);
+       if (!elsiocb)
+               return 1;
+@@ -1323,97 +1161,81 @@
+       /* For ADISC request, remainder of payload is service parameters */
+       *((uint32_t *) (pcmd)) = ELS_CMD_ADISC;
+-      pcmd += sizeof(uint32_t);
++      pcmd += sizeof (uint32_t);
+       /* Fill in ADISC payload */
+       ap = (ADISC *) pcmd;
+       ap->hardAL_PA = phba->fc_pref_ALPA;
+-      memcpy(&ap->portName, &vport->fc_portname, sizeof(struct lpfc_name));
+-      memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
+-      ap->DID = be32_to_cpu(vport->fc_myDID);
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "Issue ADISC:     did:x%x",
+-              ndlp->nlp_DID, 0, 0);
++      memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));
++      memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
++      ap->DID = be32_to_cpu(phba->fc_myDID);
+       phba->fc_stat.elsXmitADISC++;
+       elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;
+-      spin_lock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag |= NLP_ADISC_SND;
+-      spin_unlock_irq(shost->host_lock);
+       if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+-              spin_lock_irq(shost->host_lock);
+               ndlp->nlp_flag &= ~NLP_ADISC_SND;
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+               lpfc_els_free_iocb(phba, elsiocb);
+               return 1;
+       }
++      spin_unlock_irq(phba->host->host_lock);
+       return 0;
+ }
+ static void
+-lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                 struct lpfc_iocbq *rspiocb)
++lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                 struct lpfc_iocbq * rspiocb)
+ {
+-      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+-      struct lpfc_vport *vport = ndlp->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+       IOCB_t *irsp;
+       struct lpfc_sli *psli;
++      struct lpfc_nodelist *ndlp;
+       psli = &phba->sli;
+       /* we pass cmdiocb to state machine which needs rspiocb as well */
+       cmdiocb->context_un.rsp_iocb = rspiocb;
+       irsp = &(rspiocb->iocb);
+-      spin_lock_irq(shost->host_lock);
++      ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag &= ~NLP_LOGO_SND;
+-      spin_unlock_irq(shost->host_lock);
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "LOGO cmpl:       status:x%x/x%x did:x%x",
+-              irsp->ulpStatus, irsp->un.ulpWord[4],
+-              ndlp->nlp_DID);
++      spin_unlock_irq(phba->host->host_lock);
+       /* LOGO completes to NPort <nlp_DID> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0105 LOGO completes to NPort x%x "
++                      "%d:0105 LOGO completes to NPort x%x "
+                       "Data: x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, ndlp->nlp_DID,
+-                      irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
+-                      vport->num_disc_nodes);
++                      phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
++                      irsp->un.ulpWord[4], irsp->ulpTimeout,
++                      phba->num_disc_nodes);
+       /* Check to see if link went down during discovery */
+-      if (lpfc_els_chk_latt(vport))
+-              goto out;
+-
+-      if (ndlp->nlp_flag & NLP_TARGET_REMOVE) {
+-              /* NLP_EVT_DEVICE_RM should unregister the RPI
+-               * which should abort all outstanding IOs.
+-               */
+-              lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+-                                      NLP_EVT_DEVICE_RM);
++      if (lpfc_els_chk_latt(phba))
+               goto out;
+-      }
+       if (irsp->ulpStatus) {
+               /* Check for retry */
+-              if (lpfc_els_retry(phba, cmdiocb, rspiocb))
++              if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
+                       /* ELS command is being retried */
+                       goto out;
 +              }
-+
-+              if (!unionfs_lower_dentry_idx(dentry, i)->d_inode) {
-+                      dput(unionfs_lower_dentry_idx(dentry, i));
-+                      unionfs_set_lower_dentry_idx(dentry, i, NULL);
-+
-+                      unionfs_mntput(dentry, i);
-+                      unionfs_set_lower_mnt_idx(dentry, i, NULL);
+               /* LOGO failed */
+               /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
+-              if (lpfc_error_lost_link(irsp))
++              if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
++                 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
++                 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
++                 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
+                       goto out;
+-              else
+-                      lpfc_disc_state_machine(vport, ndlp, cmdiocb,
 +              } else {
-+                      if (new_bstart < 0)
-+                              new_bstart = i;
-+                      new_bend = i;
++                      lpfc_disc_state_machine(phba, ndlp, cmdiocb,
+                                       NLP_EVT_CMPL_LOGO);
 +              }
-+      }
-+
-+      if (new_bstart < 0)
-+              new_bstart = bindex;
-+      if (new_bend < 0)
-+              new_bend = bindex;
-+      set_dbstart(dentry, new_bstart);
-+      set_dbend(dentry, new_bend);
-+
-+}
-+
-+/* set lower inode ptr and update bstart & bend if necessary */
-+static void __set_inode(struct dentry *upper, struct dentry *lower,
-+                      int bindex)
-+{
-+      unionfs_set_lower_inode_idx(upper->d_inode, bindex,
-+                                  igrab(lower->d_inode));
-+      if (likely(ibstart(upper->d_inode) > bindex))
-+              ibstart(upper->d_inode) = bindex;
-+      if (likely(ibend(upper->d_inode) < bindex))
-+              ibend(upper->d_inode) = bindex;
-+
-+}
-+
-+/* set lower dentry ptr and update bstart & bend if necessary */
-+static void __set_dentry(struct dentry *upper, struct dentry *lower,
-+                       int bindex)
-+{
-+      unionfs_set_lower_dentry_idx(upper, bindex, lower);
-+      if (likely(dbstart(upper) > bindex))
-+              set_dbstart(upper, bindex);
-+      if (likely(dbend(upper) < bindex))
-+              set_dbend(upper, bindex);
-+}
-+
-+/*
-+ * This function replicates the directory structure up-to given dentry
-+ * in the bindex branch.
-+ */
-+static struct dentry *create_parents_named(struct inode *dir,
-+                                         struct dentry *dentry,
-+                                         const char *name, int bindex)
-+{
-+      int err;
-+      struct dentry *child_dentry;
-+      struct dentry *parent_dentry;
-+      struct dentry *hidden_parent_dentry = NULL;
-+      struct dentry *hidden_dentry = NULL;
-+      const char *childname;
-+      unsigned int childnamelen;
-+
-+      int nr_dentry;
-+      int count = 0;
-+
-+      int old_bstart;
-+      int old_bend;
-+      struct dentry **path = NULL;
-+      struct super_block *sb;
-+
-+      verify_locked(dentry);
-+
-+      if ((err = is_robranch_super(dir->i_sb, bindex))) {
-+              hidden_dentry = ERR_PTR(err);
-+              goto out;
-+      }
-+
-+      old_bstart = dbstart(dentry);
-+      old_bend = dbend(dentry);
-+
-+      hidden_dentry = ERR_PTR(-ENOMEM);
-+
-+      /* There is no sense allocating any less than the minimum. */
-+      nr_dentry = 1;
-+      path = kmalloc(nr_dentry * sizeof(struct dentry *), GFP_KERNEL);
-+      if (!path)
-+              goto out;
-+
-+      /* assume the negative dentry of unionfs as the parent dentry */
-+      parent_dentry = dentry;
-+
-+      /*
-+       * This loop finds the first parent that exists in the given branch.
-+       * We start building the directory structure from there.  At the end
-+       * of the loop, the following should hold:
-+       *  - child_dentry is the first nonexistent child
-+       *  - parent_dentry is the first existent parent
-+       *  - path[0] is the = deepest child
-+       *  - path[count] is the first child to create
-+       */
-+      do {
-+              child_dentry = parent_dentry;
-+
-+              /* find the parent directory dentry in unionfs */
-+              parent_dentry = child_dentry->d_parent;
-+              unionfs_lock_dentry(parent_dentry);
-+
-+              /* find out the hidden_parent_dentry in the given branch */
-+              hidden_parent_dentry =
-+                      unionfs_lower_dentry_idx(parent_dentry, bindex);
-+
-+              /* grow path table */
-+              if (count == nr_dentry) {
-+                      void *p;
+       } else {
+               /* Good status, call state machine.
+                * This will unregister the rpi if needed.
+                */
+-              lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+-                                      NLP_EVT_CMPL_LOGO);
++              lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO);
+       }
+ out:
+@@ -1422,24 +1244,21 @@
+ }
+ int
+-lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
++lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
+                   uint8_t retry)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+       IOCB_t *icmd;
+       struct lpfc_iocbq *elsiocb;
+       struct lpfc_sli_ring *pring;
+       struct lpfc_sli *psli;
+       uint8_t *pcmd;
+       uint16_t cmdsize;
+-      int rc;
+       psli = &phba->sli;
+       pring = &psli->ring[LPFC_ELS_RING];
+-      cmdsize = (2 * sizeof(uint32_t)) + sizeof(struct lpfc_name);
+-      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
++      cmdsize = (2 * sizeof (uint32_t)) + sizeof (struct lpfc_name);
++      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
+                                               ndlp->nlp_DID, ELS_CMD_LOGO);
+       if (!elsiocb)
+               return 1;
+@@ -1447,66 +1266,53 @@
+       icmd = &elsiocb->iocb;
+       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+       *((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
+-      pcmd += sizeof(uint32_t);
++      pcmd += sizeof (uint32_t);
+       /* Fill in LOGO payload */
+-      *((uint32_t *) (pcmd)) = be32_to_cpu(vport->fc_myDID);
+-      pcmd += sizeof(uint32_t);
+-      memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "Issue LOGO:      did:x%x",
+-              ndlp->nlp_DID, 0, 0);
++      *((uint32_t *) (pcmd)) = be32_to_cpu(phba->fc_myDID);
++      pcmd += sizeof (uint32_t);
++      memcpy(pcmd, &phba->fc_portname, sizeof (struct lpfc_name));
+       phba->fc_stat.elsXmitLOGO++;
+       elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
+-      spin_lock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag |= NLP_LOGO_SND;
+-      spin_unlock_irq(shost->host_lock);
+-      rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
+-
+-      if (rc == IOCB_ERROR) {
+-              spin_lock_irq(shost->host_lock);
++      if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+               ndlp->nlp_flag &= ~NLP_LOGO_SND;
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+               lpfc_els_free_iocb(phba, elsiocb);
+               return 1;
+       }
++      spin_unlock_irq(phba->host->host_lock);
+       return 0;
+ }
+ static void
+-lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                struct lpfc_iocbq *rspiocb)
++lpfc_cmpl_els_cmd(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                struct lpfc_iocbq * rspiocb)
+ {
+-      struct lpfc_vport *vport = cmdiocb->vport;
+       IOCB_t *irsp;
+       irsp = &rspiocb->iocb;
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "ELS cmd cmpl:    status:x%x/x%x did:x%x",
+-              irsp->ulpStatus, irsp->un.ulpWord[4],
+-              irsp->un.elsreq64.remoteID);
+-
+       /* ELS cmd tag <ulpIoTag> completes */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0106 ELS cmd tag x%x completes Data: x%x x%x "
+-                      "x%x\n",
+-                      phba->brd_no, vport->vpi,
++      lpfc_printf_log(phba,
++                      KERN_INFO,
++                      LOG_ELS,
++                      "%d:0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n",
++                      phba->brd_no,
+                       irsp->ulpIoTag, irsp->ulpStatus,
+                       irsp->un.ulpWord[4], irsp->ulpTimeout);
+       /* Check to see if link went down during discovery */
+-      lpfc_els_chk_latt(vport);
++      lpfc_els_chk_latt(phba);
+       lpfc_els_free_iocb(phba, cmdiocb);
+       return;
+ }
+ int
+-lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
++lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+       IOCB_t *icmd;
+       struct lpfc_iocbq *elsiocb;
+       struct lpfc_sli_ring *pring;
+@@ -1517,16 +1323,15 @@
+       psli = &phba->sli;
+       pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
+-      cmdsize = (sizeof(uint32_t) + sizeof(SCR));
++      cmdsize = (sizeof (uint32_t) + sizeof (SCR));
+       ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+       if (!ndlp)
+               return 1;
+-      lpfc_nlp_init(vport, ndlp, nportid);
++      lpfc_nlp_init(phba, ndlp, nportid);
+-      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
++      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
+                                               ndlp->nlp_DID, ELS_CMD_SCR);
+-
+       if (!elsiocb) {
+               lpfc_nlp_put(ndlp);
+               return 1;
+@@ -1536,31 +1341,29 @@
+       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+       *((uint32_t *) (pcmd)) = ELS_CMD_SCR;
+-      pcmd += sizeof(uint32_t);
++      pcmd += sizeof (uint32_t);
+       /* For SCR, remainder of payload is SCR parameter page */
+-      memset(pcmd, 0, sizeof(SCR));
++      memset(pcmd, 0, sizeof (SCR));
+       ((SCR *) pcmd)->Function = SCR_FUNC_FULL;
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "Issue SCR:       did:x%x",
+-              ndlp->nlp_DID, 0, 0);
+-
+       phba->fc_stat.elsXmitSCR++;
+       elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
++      spin_lock_irq(phba->host->host_lock);
+       if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
++              spin_unlock_irq(phba->host->host_lock);
+               lpfc_nlp_put(ndlp);
+               lpfc_els_free_iocb(phba, elsiocb);
+               return 1;
+       }
++      spin_unlock_irq(phba->host->host_lock);
+       lpfc_nlp_put(ndlp);
+       return 0;
+ }
+ static int
+-lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
++lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+       IOCB_t *icmd;
+       struct lpfc_iocbq *elsiocb;
+       struct lpfc_sli_ring *pring;
+@@ -1574,14 +1377,13 @@
+       psli = &phba->sli;
+       pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
+-      cmdsize = (sizeof(uint32_t) + sizeof(FARP));
++      cmdsize = (sizeof (uint32_t) + sizeof (FARP));
+       ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+       if (!ndlp)
+               return 1;
++      lpfc_nlp_init(phba, ndlp, nportid);
+-      lpfc_nlp_init(vport, ndlp, nportid);
+-
+-      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
++      elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
+                                               ndlp->nlp_DID, ELS_CMD_RNID);
+       if (!elsiocb) {
+               lpfc_nlp_put(ndlp);
+@@ -1592,71 +1394,44 @@
+       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+       *((uint32_t *) (pcmd)) = ELS_CMD_FARPR;
+-      pcmd += sizeof(uint32_t);
++      pcmd += sizeof (uint32_t);
+       /* Fill in FARPR payload */
+       fp = (FARP *) (pcmd);
+-      memset(fp, 0, sizeof(FARP));
++      memset(fp, 0, sizeof (FARP));
+       lp = (uint32_t *) pcmd;
+       *lp++ = be32_to_cpu(nportid);
+-      *lp++ = be32_to_cpu(vport->fc_myDID);
++      *lp++ = be32_to_cpu(phba->fc_myDID);
+       fp->Rflags = 0;
+       fp->Mflags = (FARP_MATCH_PORT | FARP_MATCH_NODE);
+-      memcpy(&fp->RportName, &vport->fc_portname, sizeof(struct lpfc_name));
+-      memcpy(&fp->RnodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
+-      ondlp = lpfc_findnode_did(vport, nportid);
+-      if (ondlp) {
++      memcpy(&fp->RportName, &phba->fc_portname, sizeof (struct lpfc_name));
++      memcpy(&fp->RnodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
++      if ((ondlp = lpfc_findnode_did(phba, nportid))) {
+               memcpy(&fp->OportName, &ondlp->nlp_portname,
+-                     sizeof(struct lpfc_name));
++                     sizeof (struct lpfc_name));
+               memcpy(&fp->OnodeName, &ondlp->nlp_nodename,
+-                     sizeof(struct lpfc_name));
++                     sizeof (struct lpfc_name));
+       }
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "Issue FARPR:     did:x%x",
+-              ndlp->nlp_DID, 0, 0);
+-
+       phba->fc_stat.elsXmitFARPR++;
+       elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
++      spin_lock_irq(phba->host->host_lock);
+       if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
++              spin_unlock_irq(phba->host->host_lock);
+               lpfc_nlp_put(ndlp);
+               lpfc_els_free_iocb(phba, elsiocb);
+               return 1;
+       }
++      spin_unlock_irq(phba->host->host_lock);
+       lpfc_nlp_put(ndlp);
+       return 0;
+ }
+-static void
+-lpfc_end_rscn(struct lpfc_vport *vport)
+-{
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+-      if (vport->fc_flag & FC_RSCN_MODE) {
+-              /*
+-               * Check to see if more RSCNs came in while we were
+-               * processing this one.
+-               */
+-              if (vport->fc_rscn_id_cnt ||
+-                  (vport->fc_flag & FC_RSCN_DISCOVERY) != 0)
+-                      lpfc_els_handle_rscn(vport);
+-              else {
+-                      spin_lock_irq(shost->host_lock);
+-                      vport->fc_flag &= ~FC_RSCN_MODE;
+-                      spin_unlock_irq(shost->host_lock);
+-              }
+-      }
+-}
+-
+ void
+-lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
++lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+-      spin_lock_irq(shost->host_lock);
+       nlp->nlp_flag &= ~NLP_DELAY_TMO;
+-      spin_unlock_irq(shost->host_lock);
+       del_timer_sync(&nlp->nlp_delayfunc);
+       nlp->nlp_last_elscmd = 0;
+@@ -1664,21 +1439,30 @@
+               list_del_init(&nlp->els_retry_evt.evt_listp);
+       if (nlp->nlp_flag & NLP_NPR_2B_DISC) {
+-              spin_lock_irq(shost->host_lock);
+               nlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+-              spin_unlock_irq(shost->host_lock);
+-              if (vport->num_disc_nodes) {
++              if (phba->num_disc_nodes) {
+                       /* Check to see if there are more
+                        * PLOGIs to be sent
+                        */
+-                      lpfc_more_plogi(vport);
++                      lpfc_more_plogi(phba);
+-                      if (vport->num_disc_nodes == 0) {
+-                              spin_lock_irq(shost->host_lock);
+-                              vport->fc_flag &= ~FC_NDISC_ACTIVE;
+-                              spin_unlock_irq(shost->host_lock);
+-                              lpfc_can_disctmo(vport);
+-                              lpfc_end_rscn(vport);
++                      if (phba->num_disc_nodes == 0) {
++                              phba->fc_flag &= ~FC_NDISC_ACTIVE;
++                              lpfc_can_disctmo(phba);
++                              if (phba->fc_flag & FC_RSCN_MODE) {
++                                      /*
++                                       * Check to see if more RSCNs
++                                       * came in while we were
++                                       * processing this one.
++                                       */
++                                      if((phba->fc_rscn_id_cnt==0) &&
++                                       !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
++                                              phba->fc_flag &= ~FC_RSCN_MODE;
++                                      }
++                                      else {
++                                              lpfc_els_handle_rscn(phba);
++                                      }
++                              }
+                       }
+               }
+       }
+@@ -1688,19 +1472,18 @@
+ void
+ lpfc_els_retry_delay(unsigned long ptr)
+ {
+-      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) ptr;
+-      struct lpfc_vport *vport = ndlp->vport;
+-      struct lpfc_hba   *phba = vport->phba;
+-      unsigned long flags;
+-      struct lpfc_work_evt  *evtp = &ndlp->els_retry_evt;
++      struct lpfc_nodelist *ndlp;
++      struct lpfc_hba *phba;
++      unsigned long iflag;
++      struct lpfc_work_evt  *evtp;
+-      ndlp = (struct lpfc_nodelist *) ptr;
+-      phba = ndlp->vport->phba;
++      ndlp = (struct lpfc_nodelist *)ptr;
++      phba = ndlp->nlp_phba;
+       evtp = &ndlp->els_retry_evt;
+-      spin_lock_irqsave(&phba->hbalock, flags);
++      spin_lock_irqsave(phba->host->host_lock, iflag);
+       if (!list_empty(&evtp->evt_listp)) {
+-              spin_unlock_irqrestore(&phba->hbalock, flags);
++              spin_unlock_irqrestore(phba->host->host_lock, iflag);
+               return;
+       }
+@@ -1708,31 +1491,33 @@
+       evtp->evt       = LPFC_EVT_ELS_RETRY;
+       list_add_tail(&evtp->evt_listp, &phba->work_list);
+       if (phba->work_wait)
+-              lpfc_worker_wake_up(phba);
++              wake_up(phba->work_wait);
+-      spin_unlock_irqrestore(&phba->hbalock, flags);
++      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+       return;
+ }
+ void
+ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
+ {
+-      struct lpfc_vport *vport = ndlp->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      uint32_t cmd, did, retry;
++      struct lpfc_hba *phba;
++      uint32_t cmd;
++      uint32_t did;
++      uint8_t retry;
+-      spin_lock_irq(shost->host_lock);
++      phba = ndlp->nlp_phba;
++      spin_lock_irq(phba->host->host_lock);
+       did = ndlp->nlp_DID;
+       cmd = ndlp->nlp_last_elscmd;
+       ndlp->nlp_last_elscmd = 0;
+       if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+               return;
+       }
+       ndlp->nlp_flag &= ~NLP_DELAY_TMO;
+-      spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+       /*
+        * If a discovery event readded nlp_delayfunc after timer
+        * firing and before processing the timer, cancel the
+@@ -1743,57 +1528,60 @@
+       switch (cmd) {
+       case ELS_CMD_FLOGI:
+-              lpfc_issue_els_flogi(vport, ndlp, retry);
++              lpfc_issue_els_flogi(phba, ndlp, retry);
+               break;
+       case ELS_CMD_PLOGI:
+-              if (!lpfc_issue_els_plogi(vport, ndlp->nlp_DID, retry)) {
++              if(!lpfc_issue_els_plogi(phba, ndlp->nlp_DID, retry)) {
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
+               }
+               break;
+       case ELS_CMD_ADISC:
+-              if (!lpfc_issue_els_adisc(vport, ndlp, retry)) {
++              if (!lpfc_issue_els_adisc(phba, ndlp, retry)) {
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
+               }
+               break;
+       case ELS_CMD_PRLI:
+-              if (!lpfc_issue_els_prli(vport, ndlp, retry)) {
++              if (!lpfc_issue_els_prli(phba, ndlp, retry)) {
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
+               }
+               break;
+       case ELS_CMD_LOGO:
+-              if (!lpfc_issue_els_logo(vport, ndlp, retry)) {
++              if (!lpfc_issue_els_logo(phba, ndlp, retry)) {
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+               }
+               break;
+-      case ELS_CMD_FDISC:
+-              lpfc_issue_els_fdisc(vport, ndlp, retry);
+-              break;
+       }
+       return;
+ }
+ static int
+-lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-             struct lpfc_iocbq *rspiocb)
++lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++             struct lpfc_iocbq * rspiocb)
+ {
+-      struct lpfc_vport *vport = cmdiocb->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      IOCB_t *irsp = &rspiocb->iocb;
+-      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+-      struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
++      IOCB_t *irsp;
++      struct lpfc_dmabuf *pcmd;
++      struct lpfc_nodelist *ndlp;
+       uint32_t *elscmd;
+       struct ls_rjt stat;
+-      int retry = 0, maxretry = lpfc_max_els_tries, delay = 0;
+-      uint32_t cmd = 0;
++      int retry, maxretry;
++      int delay;
++      uint32_t cmd;
+       uint32_t did;
+-
+-      /* Note: context2 may be 0 for internal driver abort
+-       * of delays ELS command.
++      retry = 0;
++      delay = 0;
++      maxretry = lpfc_max_els_tries;
++      irsp = &rspiocb->iocb;
++      ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
++      pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
++      cmd = 0;
 +
-+                      nr_dentry *= 2;
-+                      p = krealloc(path, nr_dentry * sizeof(struct dentry *), GFP_KERNEL);
-+                      if (!p) {
-+                              hidden_dentry = ERR_PTR(-ENOMEM);
-+                              goto out;
++      /* Note: context2 may be 0 for internal driver abort
++       * of delays ELS command.
+        */
+       if (pcmd && pcmd->virt) {
+@@ -1806,15 +1594,11 @@
+       else {
+               /* We should only hit this case for retrying PLOGI */
+               did = irsp->un.elsreq64.remoteID;
+-              ndlp = lpfc_findnode_did(vport, did);
++              ndlp = lpfc_findnode_did(phba, did);
+               if (!ndlp && (cmd != ELS_CMD_PLOGI))
+                       return 1;
+       }
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "Retry ELS:       wd7:x%x wd4:x%x did:x%x",
+-              *(((uint32_t *) irsp) + 7), irsp->un.ulpWord[4], ndlp->nlp_DID);
+-
+       switch (irsp->ulpStatus) {
+       case IOSTAT_FCP_RSP_ERROR:
+       case IOSTAT_REMOTE_STOP:
+@@ -1823,37 +1607,25 @@
+       case IOSTAT_LOCAL_REJECT:
+               switch ((irsp->un.ulpWord[4] & 0xff)) {
+               case IOERR_LOOP_OPEN_FAILURE:
+-                      if (cmd == ELS_CMD_PLOGI && cmdiocb->retry == 0)
+-                              delay = 1000;
++                      if (cmd == ELS_CMD_PLOGI) {
++                              if (cmdiocb->retry == 0) {
++                                      delay = 1;
++                              }
 +                      }
-+                      path = p;
-+              }
-+
-+              /* store the child dentry */
-+              path[count++] = child_dentry;
-+      } while (!hidden_parent_dentry);
-+      count--;
-+
-+      sb = dentry->d_sb;
-+
-+      /*
-+       * This is basically while(child_dentry != dentry).  This loop is
-+       * horrible to follow and should be replaced with cleaner code.
-+       */
-+      while (1) {
-+              /* get hidden parent dir in the current branch */
-+              hidden_parent_dentry =
-+                      unionfs_lower_dentry_idx(parent_dentry, bindex);
-+              unionfs_unlock_dentry(parent_dentry);
-+
-+              /* init the values to lookup */
-+              childname = child_dentry->d_name.name;
-+              childnamelen = child_dentry->d_name.len;
-+
-+              if (child_dentry != dentry) {
-+                      /* lookup child in the underlying file system */
-+                      hidden_dentry =
-+                              lookup_one_len(childname, hidden_parent_dentry,
-+                                             childnamelen);
-+                      if (IS_ERR(hidden_dentry))
-+                              goto out;
-+              } else {
-+
-+                      /*
-+                       * is the name a whiteout of the child name ?
-+                       * lookup the whiteout child in the underlying file
-+                       * system
-+                       */
-+                      hidden_dentry =
-+                              lookup_one_len(name, hidden_parent_dentry,
-+                                             strlen(name));
-+                      if (IS_ERR(hidden_dentry))
-+                              goto out;
-+
-+                      /*
-+                       * Replace the current dentry (if any) with the new
-+                       * one.
-+                       */
-+                      dput(unionfs_lower_dentry_idx(dentry, bindex));
-+                      unionfs_set_lower_dentry_idx(dentry, bindex,
-+                                                   hidden_dentry);
-+
-+                      __cleanup_dentry(dentry, bindex, old_bstart, old_bend);
-+                      break;
-+              }
-+
-+              if (hidden_dentry->d_inode) {
-+                      /*
-+                       * since this already exists we dput to avoid
-+                       * multiple references on the same dentry
-+                       */
-+                      dput(hidden_dentry);
-+              } else {
-+                      struct sioq_args args;
-+
-+                      /* its a negative dentry, create a new dir */
-+                      hidden_parent_dentry = lock_parent(hidden_dentry);
-+
-+                      args.mkdir.parent = hidden_parent_dentry->d_inode;
-+                      args.mkdir.dentry = hidden_dentry;
-+                      args.mkdir.mode = child_dentry->d_inode->i_mode;
-+
-+                      run_sioq(__unionfs_mkdir, &args);
-+                      err = args.err;
-+
-+                      if (!err)
-+                              err = copyup_permissions(dir->i_sb,
-+                                                       child_dentry,
-+                                                       hidden_dentry);
-+                      unlock_dir(hidden_parent_dentry);
-+                      if (err) {
-+                              struct inode *inode = hidden_dentry->d_inode;
-+                              /*
-+                               * If we get here, it means that we created a new
-+                               * dentry+inode, but copying permissions failed.
-+                               * Therefore, we should delete this inode and dput
-+                               * the dentry so as not to leave cruft behind.
-+                               *
-+                               * XXX: call dentry_iput() instead, but then we have
-+                               * to export that symbol.
-+                               */
-+                              if (hidden_dentry->d_op && hidden_dentry->d_op->d_iput)
-+                                      hidden_dentry->d_op->d_iput(hidden_dentry,
-+                                                                  inode);
-+                              else
-+                                      iput(inode);
-+                              hidden_dentry->d_inode = NULL;
-+
-+                              dput(hidden_dentry);
-+                              hidden_dentry = ERR_PTR(err);
-+                              goto out;
+                       retry = 1;
+                       break;
+-              case IOERR_ILLEGAL_COMMAND:
+-                      if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) &&
+-                          (cmd == ELS_CMD_FDISC)) {
+-                              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                              "%d (%d):0124 FDISC failed (3/6) retrying...\n",
+-                                      phba->brd_no, vport->vpi);
+-                              lpfc_mbx_unreg_vpi(vport);
++              case IOERR_SEQUENCE_TIMEOUT:
+                       retry = 1;
+-                              /* Always retry for this case */
+-                              cmdiocb->retry = 0;
+-                      }
+                       break;
+               case IOERR_NO_RESOURCES:
+-                      retry = 1;
+-                      if (cmdiocb->retry > 100)
+-                              delay = 100;
+-                      maxretry = 250;
+-                      break;
+-
+-              case IOERR_ILLEGAL_FRAME:
+-                      delay = 100;
++                      if (cmd == ELS_CMD_PLOGI) {
++                              delay = 1;
++                      }
+                       retry = 1;
+                       break;
+-              case IOERR_SEQUENCE_TIMEOUT:
+               case IOERR_INVALID_RPI:
+                       retry = 1;
+                       break;
+@@ -1883,57 +1655,27 @@
+                       if (stat.un.b.lsRjtRsnCodeExp ==
+                           LSEXP_CMD_IN_PROGRESS) {
+                               if (cmd == ELS_CMD_PLOGI) {
+-                                      delay = 1000;
++                                      delay = 1;
+                                       maxretry = 48;
+                               }
+                               retry = 1;
+                               break;
+                       }
+                       if (cmd == ELS_CMD_PLOGI) {
+-                              delay = 1000;
++                              delay = 1;
+                               maxretry = lpfc_max_els_tries + 1;
+                               retry = 1;
+                               break;
+                       }
+-                      if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+-                        (cmd == ELS_CMD_FDISC) &&
+-                        (stat.un.b.lsRjtRsnCodeExp == LSEXP_OUT_OF_RESOURCE)){
+-                              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                              "%d (%d):0125 FDISC Failed (x%x)."
+-                              " Fabric out of resources\n",
+-                              phba->brd_no, vport->vpi, stat.un.lsRjtError);
+-                              lpfc_vport_set_state(vport,
+-                                                   FC_VPORT_NO_FABRIC_RSCS);
+-                      }
+                       break;
+               case LSRJT_LOGICAL_BSY:
+-                      if ((cmd == ELS_CMD_PLOGI) ||
+-                          (cmd == ELS_CMD_PRLI)) {
+-                              delay = 1000;
++                      if (cmd == ELS_CMD_PLOGI) {
++                              delay = 1;
+                               maxretry = 48;
+-                      } else if (cmd == ELS_CMD_FDISC) {
+-                              /* Always retry for this case */
+-                              cmdiocb->retry = 0;
+                       }
+                       retry = 1;
+                       break;
+-
+-              case LSRJT_LOGICAL_ERR:
+-              case LSRJT_PROTOCOL_ERR:
+-                      if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+-                        (cmd == ELS_CMD_FDISC) &&
+-                        ((stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_PNAME) ||
+-                        (stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_NPORT_ID))
+-                        ) {
+-                              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                              "%d (%d):0123 FDISC Failed (x%x)."
+-                              " Fabric Detected Bad WWN\n",
+-                              phba->brd_no, vport->vpi, stat.un.lsRjtError);
+-                              lpfc_vport_set_state(vport,
+-                                                   FC_VPORT_FABRIC_REJ_WWN);
+-                      }
+-                      break;
+               }
+               break;
+@@ -1953,27 +1695,21 @@
+               retry = 0;
+       }
+-      if ((vport->load_flag & FC_UNLOADING) != 0)
+-              retry = 0;
+-
+       if (retry) {
+               /* Retry ELS command <elsCmd> to remote NPORT <did> */
+               lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                              "%d (%d):0107 Retry ELS command x%x to remote "
++                              "%d:0107 Retry ELS command x%x to remote "
+                               "NPORT x%x Data: x%x x%x\n",
+-                              phba->brd_no, vport->vpi,
++                              phba->brd_no,
+                               cmd, did, cmdiocb->retry, delay);
+-              if (((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) &&
+-                      ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
+-                      ((irsp->un.ulpWord[4] & 0xff) != IOERR_NO_RESOURCES))) {
+-                      /* Don't reset timer for no resources */
+-
++              if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) {
+                       /* If discovery / RSCN timer is running, reset it */
+-                      if (timer_pending(&vport->fc_disctmo) ||
+-                          (vport->fc_flag & FC_RSCN_MODE))
+-                              lpfc_set_disctmo(vport);
++                      if (timer_pending(&phba->fc_disctmo) ||
++                            (phba->fc_flag & FC_RSCN_MODE)) {
++                              lpfc_set_disctmo(phba);
 +                      }
+               }
+               phba->fc_stat.elsXmitRetry++;
+@@ -1981,62 +1717,50 @@
+                       phba->fc_stat.elsDelayRetry++;
+                       ndlp->nlp_retry = cmdiocb->retry;
+-                      /* delay is specified in milliseconds */
+-                      mod_timer(&ndlp->nlp_delayfunc,
+-                              jiffies + msecs_to_jiffies(delay));
+-                      spin_lock_irq(shost->host_lock);
++                      mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+                       ndlp->nlp_flag |= NLP_DELAY_TMO;
+-                      spin_unlock_irq(shost->host_lock);
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+-                      if (cmd == ELS_CMD_PRLI)
+-                              lpfc_nlp_set_state(vport, ndlp,
+-                                      NLP_STE_REG_LOGIN_ISSUE);
+-                      else
+-                              lpfc_nlp_set_state(vport, ndlp,
+-                                      NLP_STE_NPR_NODE);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+                       ndlp->nlp_last_elscmd = cmd;
+                       return 1;
+               }
+               switch (cmd) {
+               case ELS_CMD_FLOGI:
+-                      lpfc_issue_els_flogi(vport, ndlp, cmdiocb->retry);
+-                      return 1;
+-              case ELS_CMD_FDISC:
+-                      lpfc_issue_els_fdisc(vport, ndlp, cmdiocb->retry);
++                      lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry);
+                       return 1;
+               case ELS_CMD_PLOGI:
+                       if (ndlp) {
+                               ndlp->nlp_prev_state = ndlp->nlp_state;
+-                              lpfc_nlp_set_state(vport, ndlp,
++                              lpfc_nlp_set_state(phba, ndlp,
+                                                  NLP_STE_PLOGI_ISSUE);
+                       }
+-                      lpfc_issue_els_plogi(vport, did, cmdiocb->retry);
++                      lpfc_issue_els_plogi(phba, did, cmdiocb->retry);
+                       return 1;
+               case ELS_CMD_ADISC:
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
+-                      lpfc_issue_els_adisc(vport, ndlp, cmdiocb->retry);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
++                      lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry);
+                       return 1;
+               case ELS_CMD_PRLI:
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
+-                      lpfc_issue_els_prli(vport, ndlp, cmdiocb->retry);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
++                      lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry);
+                       return 1;
+               case ELS_CMD_LOGO:
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+-                      lpfc_issue_els_logo(vport, ndlp, cmdiocb->retry);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
++                      lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry);
+                       return 1;
+               }
+       }
+       /* No retry ELS command <elsCmd> to remote NPORT <did> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0108 No retry ELS command x%x to remote "
+-                      "NPORT x%x Data: x%x\n",
+-                      phba->brd_no, vport->vpi,
++                      "%d:0108 No retry ELS command x%x to remote NPORT x%x "
++                      "Data: x%x\n",
++                      phba->brd_no,
+                       cmd, did, cmdiocb->retry);
+       return 0;
+@@ -2071,36 +1795,33 @@
+               lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
+               kfree(buf_ptr);
+       }
++      spin_lock_irq(phba->host->host_lock);
+       lpfc_sli_release_iocbq(phba, elsiocb);
++      spin_unlock_irq(phba->host->host_lock);
+       return 0;
+ }
+ static void
+-lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                     struct lpfc_iocbq *rspiocb)
++lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                     struct lpfc_iocbq * rspiocb)
+ {
+-      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+-      struct lpfc_vport *vport = cmdiocb->vport;
+-      IOCB_t *irsp;
++      struct lpfc_nodelist *ndlp;
+-      irsp = &rspiocb->iocb;
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+-              "ACC LOGO cmpl:   status:x%x/x%x did:x%x",
+-              irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID);
++      ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+       /* ACC to LOGO completes to NPort <nlp_DID> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0109 ACC to LOGO completes to NPort x%x "
++                      "%d:0109 ACC to LOGO completes to NPort x%x "
+                       "Data: x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, ndlp->nlp_DID,
+-                      ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
++                      phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
++                      ndlp->nlp_state, ndlp->nlp_rpi);
+       switch (ndlp->nlp_state) {
+       case NLP_STE_UNUSED_NODE:       /* node is just allocated */
+-              lpfc_drop_node(vport, ndlp);
++              lpfc_drop_node(phba, ndlp);
+               break;
+       case NLP_STE_NPR_NODE:          /* NPort Recovery mode */
+-              lpfc_unreg_rpi(vport, ndlp);
++              lpfc_unreg_rpi(phba, ndlp);
+               break;
+       default:
+               break;
+@@ -2109,38 +1830,24 @@
+       return;
+ }
+-void
+-lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+-{
+-      struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
+-      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
+-
+-      pmb->context1 = NULL;
+-      lpfc_mbuf_free(phba, mp->virt, mp->phys);
+-      kfree(mp);
+-      mempool_free(pmb, phba->mbox_mem_pool);
+-      lpfc_nlp_put(ndlp);
+-      return;
+-}
+-
+ static void
+-lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
++lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+                 struct lpfc_iocbq *rspiocb)
+ {
+-      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+-      struct lpfc_vport *vport = ndlp ? ndlp->vport : NULL;
+-      struct Scsi_Host  *shost = vport ? lpfc_shost_from_vport(vport) : NULL;
+       IOCB_t *irsp;
++      struct lpfc_nodelist *ndlp;
+       LPFC_MBOXQ_t *mbox = NULL;
+-      struct lpfc_dmabuf *mp = NULL;
++      struct lpfc_dmabuf *mp;
+       irsp = &rspiocb->iocb;
++      ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+       if (cmdiocb->context_un.mbox)
+               mbox = cmdiocb->context_un.mbox;
 +
+       /* Check to see if link went down during discovery */
+-      if (!ndlp || lpfc_els_chk_latt(vport)) {
++      if (lpfc_els_chk_latt(phba) || !ndlp) {
+               if (mbox) {
+                       mp = (struct lpfc_dmabuf *) mbox->context1;
+                       if (mp) {
+@@ -2152,16 +1859,11 @@
+               goto out;
+       }
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+-              "ACC cmpl:        status:x%x/x%x did:x%x",
+-              irsp->ulpStatus, irsp->un.ulpWord[4],
+-              irsp->un.rcvels.remoteID);
+-
+       /* ELS response tag <ulpIoTag> completes */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0110 ELS response tag x%x completes "
++                      "%d:0110 ELS response tag x%x completes "
+                       "Data: x%x x%x x%x x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi,
++                      phba->brd_no,
+                       cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus,
+                       rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout,
+                       ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+@@ -2170,19 +1872,11 @@
+       if (mbox) {
+               if ((rspiocb->iocb.ulpStatus == 0)
+                   && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
+-                      lpfc_unreg_rpi(vport, ndlp);
+-                      mbox->context2 = lpfc_nlp_get(ndlp);
+-                      mbox->vport = vport;
+-                      if (ndlp->nlp_flag & NLP_RM_DFLT_RPI) {
+-                              mbox->mbox_flag |= LPFC_MBX_IMED_UNREG;
+-                              mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
+-                      }
+-                      else {
++                      lpfc_unreg_rpi(phba, ndlp);
+                               mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
++                      mbox->context2 = lpfc_nlp_get(ndlp);
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+-                              lpfc_nlp_set_state(vport, ndlp,
+-                                         NLP_STE_REG_LOGIN_ISSUE);
+-                      }
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
+                       if (lpfc_sli_issue_mbox(phba, mbox,
+                                               (MBX_NOWAIT | MBX_STOP_IOCB))
+                           != MBX_NOT_FINISHED) {
+@@ -2192,13 +1886,17 @@
+                       /* NOTE: we should have messages for unsuccessful
+                          reglogin */
+               } else {
+-                      /* Do not drop node for lpfc_els_abort'ed ELS cmds */
+-                      if (!lpfc_error_lost_link(irsp) &&
+-                          ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
+-                              lpfc_drop_node(vport, ndlp);
++                      /* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */
++                      if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
++                            ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
++                             (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
++                             (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) {
++                              if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
++                                      lpfc_drop_node(phba, ndlp);
+                                       ndlp = NULL;
+                               }
+                       }
 +              }
+               mp = (struct lpfc_dmabuf *) mbox->context1;
+               if (mp) {
+                       lpfc_mbuf_free(phba, mp->virt, mp->phys);
+@@ -2208,21 +1906,19 @@
+       }
+ out:
+       if (ndlp) {
+-              spin_lock_irq(shost->host_lock);
+-              ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI);
+-              spin_unlock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
++              ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;
++              spin_unlock_irq(phba->host->host_lock);
+       }
+       lpfc_els_free_iocb(phba, cmdiocb);
+       return;
+ }
+ int
+-lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
+-               struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
+-               LPFC_MBOXQ_t *mbox, uint8_t newnode)
++lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
++               struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp,
++               LPFC_MBOXQ_t * mbox, uint8_t newnode)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+       IOCB_t *icmd;
+       IOCB_t *oldcmd;
+       struct lpfc_iocbq *elsiocb;
+@@ -2239,29 +1935,22 @@
+       switch (flag) {
+       case ELS_CMD_ACC:
+-              cmdsize = sizeof(uint32_t);
+-              elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
++              cmdsize = sizeof (uint32_t);
++              elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
+                                       ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
+               if (!elsiocb) {
+-                      spin_lock_irq(shost->host_lock);
+                       ndlp->nlp_flag &= ~NLP_LOGO_ACC;
+-                      spin_unlock_irq(shost->host_lock);
+                       return 1;
+               }
+-
+               icmd = &elsiocb->iocb;
+               icmd->ulpContext = oldcmd->ulpContext;  /* Xri */
+               pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+               *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
+-              pcmd += sizeof(uint32_t);
+-
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+-                      "Issue ACC:       did:x%x flg:x%x",
+-                      ndlp->nlp_DID, ndlp->nlp_flag, 0);
++              pcmd += sizeof (uint32_t);
+               break;
+       case ELS_CMD_PLOGI:
+-              cmdsize = (sizeof(struct serv_parm) + sizeof(uint32_t));
+-              elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
++              cmdsize = (sizeof (struct serv_parm) + sizeof (uint32_t));
++              elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
+                                       ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
+               if (!elsiocb)
+                       return 1;
+@@ -2274,16 +1963,12 @@
+                       elsiocb->context_un.mbox = mbox;
+               *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
+-              pcmd += sizeof(uint32_t);
+-              memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
+-
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+-                      "Issue ACC PLOGI: did:x%x flg:x%x",
+-                      ndlp->nlp_DID, ndlp->nlp_flag, 0);
++              pcmd += sizeof (uint32_t);
++              memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
+               break;
+       case ELS_CMD_PRLO:
+-              cmdsize = sizeof(uint32_t) + sizeof(PRLO);
+-              elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
++              cmdsize = sizeof (uint32_t) + sizeof (PRLO);
++              elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
+                                            ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
+               if (!elsiocb)
+                       return 1;
+@@ -2293,14 +1978,10 @@
+               pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+               memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
+-                     sizeof(uint32_t) + sizeof(PRLO));
++                     sizeof (uint32_t) + sizeof (PRLO));
+               *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
+               els_pkt_ptr = (ELS_PKT *) pcmd;
+               els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
+-
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+-                      "Issue ACC PRLO:  did:x%x flg:x%x",
+-                      ndlp->nlp_DID, ndlp->nlp_flag, 0);
+               break;
+       default:
+               return 1;
+@@ -2313,23 +1994,25 @@
+       /* Xmit ELS ACC response tag <ulpIoTag> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
++                      "%d:0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
+                       "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
+-                      phba->brd_no, vport->vpi, elsiocb->iotag,
++                      phba->brd_no, elsiocb->iotag,
+                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
+                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+       if (ndlp->nlp_flag & NLP_LOGO_ACC) {
+-              spin_lock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
+               ndlp->nlp_flag &= ~NLP_LOGO_ACC;
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+               elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
+       } else {
+-              elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++              elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+       }
+       phba->fc_stat.elsXmitACC++;
++      spin_lock_irq(phba->host->host_lock);
+       rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
++      spin_unlock_irq(phba->host->host_lock);
+       if (rc == IOCB_ERROR) {
+               lpfc_els_free_iocb(phba, elsiocb);
+               return 1;
+@@ -2338,11 +2021,9 @@
+ }
+ int
+-lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
+-                  struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
+-                  LPFC_MBOXQ_t *mbox)
++lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError,
++                  struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+       IOCB_t *icmd;
+       IOCB_t *oldcmd;
+       struct lpfc_iocbq *elsiocb;
+@@ -2355,9 +2036,9 @@
+       psli = &phba->sli;
+       pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
+-      cmdsize = 2 * sizeof(uint32_t);
+-      elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
+-                                   ndlp->nlp_DID, ELS_CMD_LS_RJT);
++      cmdsize = 2 * sizeof (uint32_t);
++      elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
++                                      ndlp, ndlp->nlp_DID, ELS_CMD_LS_RJT);
+       if (!elsiocb)
+               return 1;
+@@ -2367,30 +2048,22 @@
+       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+       *((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT;
+-      pcmd += sizeof(uint32_t);
++      pcmd += sizeof (uint32_t);
+       *((uint32_t *) (pcmd)) = rejectError;
+-      if (mbox) {
+-              elsiocb->context_un.mbox = mbox;
+-              elsiocb->context1 = lpfc_nlp_get(ndlp);
+-      }
+-
+       /* Xmit ELS RJT <err> response tag <ulpIoTag> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0129 Xmit ELS RJT x%x response tag x%x "
+-                      "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
+-                      "rpi x%x\n",
+-                      phba->brd_no, vport->vpi, rejectError, elsiocb->iotag,
++                      "%d:0129 Xmit ELS RJT x%x response tag x%x xri x%x, "
++                      "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
++                      phba->brd_no, rejectError, elsiocb->iotag,
+                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
+                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+-              "Issue LS_RJT:    did:x%x flg:x%x err:x%x",
+-              ndlp->nlp_DID, ndlp->nlp_flag, rejectError);
+-
+       phba->fc_stat.elsXmitLSRJT++;
+-      elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++      elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
++      spin_lock_irq(phba->host->host_lock);
+       rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
++      spin_unlock_irq(phba->host->host_lock);
+       if (rc == IOCB_ERROR) {
+               lpfc_els_free_iocb(phba, elsiocb);
+               return 1;
+@@ -2399,22 +2072,25 @@
+ }
+ int
+-lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
+-                     struct lpfc_nodelist *ndlp)
++lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba,
++                     struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+-      struct lpfc_sli  *psli = &phba->sli;
+-      struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
+       ADISC *ap;
+-      IOCB_t *icmd, *oldcmd;
++      IOCB_t *icmd;
++      IOCB_t *oldcmd;
+       struct lpfc_iocbq *elsiocb;
++      struct lpfc_sli_ring *pring;
++      struct lpfc_sli *psli;
+       uint8_t *pcmd;
+       uint16_t cmdsize;
+       int rc;
+-      cmdsize = sizeof(uint32_t) + sizeof(ADISC);
+-      elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
+-                                   ndlp->nlp_DID, ELS_CMD_ACC);
++      psli = &phba->sli;
++      pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
 +
-+              __set_inode(child_dentry, hidden_dentry, bindex);
-+              __set_dentry(child_dentry, hidden_dentry, bindex);
-+
-+              parent_dentry = child_dentry;
-+              child_dentry = path[--count];
++      cmdsize = sizeof (uint32_t) + sizeof (ADISC);
++      elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
++                                      ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
+       if (!elsiocb)
+               return 1;
+@@ -2424,30 +2100,28 @@
+       /* Xmit ADISC ACC response tag <ulpIoTag> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0130 Xmit ADISC ACC response iotag x%x xri: "
++                      "%d:0130 Xmit ADISC ACC response iotag x%x xri: "
+                       "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n",
+-                      phba->brd_no, vport->vpi, elsiocb->iotag,
++                      phba->brd_no, elsiocb->iotag,
+                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
+                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+       *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
+-      pcmd += sizeof(uint32_t);
++      pcmd += sizeof (uint32_t);
+       ap = (ADISC *) (pcmd);
+       ap->hardAL_PA = phba->fc_pref_ALPA;
+-      memcpy(&ap->portName, &vport->fc_portname, sizeof(struct lpfc_name));
+-      memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
+-      ap->DID = be32_to_cpu(vport->fc_myDID);
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+-              "Issue ACC ADISC: did:x%x flg:x%x",
+-              ndlp->nlp_DID, ndlp->nlp_flag, 0);
++      memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));
++      memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
++      ap->DID = be32_to_cpu(phba->fc_myDID);
+       phba->fc_stat.elsXmitACC++;
+-      elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++      elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
++      spin_lock_irq(phba->host->host_lock);
+       rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
++      spin_unlock_irq(phba->host->host_lock);
+       if (rc == IOCB_ERROR) {
+               lpfc_els_free_iocb(phba, elsiocb);
+               return 1;
+@@ -2456,10 +2130,9 @@
+ }
+ int
+-lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
++lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb,
+                     struct lpfc_nodelist *ndlp)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+       PRLI *npr;
+       lpfc_vpd_t *vpd;
+       IOCB_t *icmd;
+@@ -2474,8 +2147,8 @@
+       psli = &phba->sli;
+       pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
+-      cmdsize = sizeof(uint32_t) + sizeof(PRLI);
+-      elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
++      cmdsize = sizeof (uint32_t) + sizeof (PRLI);
++      elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp,
+               ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
+       if (!elsiocb)
+               return 1;
+@@ -2486,19 +2159,19 @@
+       /* Xmit PRLI ACC response tag <ulpIoTag> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0131 Xmit PRLI ACC response tag x%x xri x%x, "
++                      "%d:0131 Xmit PRLI ACC response tag x%x xri x%x, "
+                       "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
+-                      phba->brd_no, vport->vpi, elsiocb->iotag,
++                      phba->brd_no, elsiocb->iotag,
+                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
+                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+       *((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK));
+-      pcmd += sizeof(uint32_t);
++      pcmd += sizeof (uint32_t);
+       /* For PRLI, remainder of payload is PRLI parameter page */
+-      memset(pcmd, 0, sizeof(PRLI));
++      memset(pcmd, 0, sizeof (PRLI));
+       npr = (PRLI *) pcmd;
+       vpd = &phba->vpd;
+@@ -2520,14 +2193,12 @@
+       npr->prliType = PRLI_FCP_TYPE;
+       npr->initiatorFunc = 1;
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+-              "Issue ACC PRLI:  did:x%x flg:x%x",
+-              ndlp->nlp_DID, ndlp->nlp_flag, 0);
+-
+       phba->fc_stat.elsXmitACC++;
+-      elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++      elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
++      spin_lock_irq(phba->host->host_lock);
+       rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
++      spin_unlock_irq(phba->host->host_lock);
+       if (rc == IOCB_ERROR) {
+               lpfc_els_free_iocb(phba, elsiocb);
+               return 1;
+@@ -2536,12 +2207,12 @@
+ }
+ static int
+-lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
++lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format,
+                     struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+       RNID *rn;
+-      IOCB_t *icmd, *oldcmd;
++      IOCB_t *icmd;
++      IOCB_t *oldcmd;
+       struct lpfc_iocbq *elsiocb;
+       struct lpfc_sli_ring *pring;
+       struct lpfc_sli *psli;
+@@ -2552,13 +2223,13 @@
+       psli = &phba->sli;
+       pring = &psli->ring[LPFC_ELS_RING];
+-      cmdsize = sizeof(uint32_t) + sizeof(uint32_t)
+-                                      + (2 * sizeof(struct lpfc_name));
++      cmdsize = sizeof (uint32_t) + sizeof (uint32_t)
++              + (2 * sizeof (struct lpfc_name));
+       if (format)
+-              cmdsize += sizeof(RNID_TOP_DISC);
++              cmdsize += sizeof (RNID_TOP_DISC);
+-      elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
+-                                   ndlp->nlp_DID, ELS_CMD_ACC);
++      elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
++                                      ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
+       if (!elsiocb)
+               return 1;
+@@ -2568,30 +2239,30 @@
+       /* Xmit RNID ACC response tag <ulpIoTag> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0132 Xmit RNID ACC response tag x%x "
++                      "%d:0132 Xmit RNID ACC response tag x%x "
+                       "xri x%x\n",
+-                      phba->brd_no, vport->vpi, elsiocb->iotag,
++                      phba->brd_no, elsiocb->iotag,
+                       elsiocb->iocb.ulpContext);
+       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+       *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
+-      pcmd += sizeof(uint32_t);
++      pcmd += sizeof (uint32_t);
+-      memset(pcmd, 0, sizeof(RNID));
++      memset(pcmd, 0, sizeof (RNID));
+       rn = (RNID *) (pcmd);
+       rn->Format = format;
+-      rn->CommonLen = (2 * sizeof(struct lpfc_name));
+-      memcpy(&rn->portName, &vport->fc_portname, sizeof(struct lpfc_name));
+-      memcpy(&rn->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
++      rn->CommonLen = (2 * sizeof (struct lpfc_name));
++      memcpy(&rn->portName, &phba->fc_portname, sizeof (struct lpfc_name));
++      memcpy(&rn->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
+       switch (format) {
+       case 0:
+               rn->SpecificLen = 0;
+               break;
+       case RNID_TOPOLOGY_DISC:
+-              rn->SpecificLen = sizeof(RNID_TOP_DISC);
++              rn->SpecificLen = sizeof (RNID_TOP_DISC);
+               memcpy(&rn->un.topologyDisc.portName,
+-                     &vport->fc_portname, sizeof(struct lpfc_name));
++                     &phba->fc_portname, sizeof (struct lpfc_name));
+               rn->un.topologyDisc.unitType = RNID_HBA;
+               rn->un.topologyDisc.physPort = 0;
+               rn->un.topologyDisc.attachedNodes = 0;
+@@ -2602,17 +2273,15 @@
+               break;
+       }
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+-              "Issue ACC RNID:  did:x%x flg:x%x",
+-              ndlp->nlp_DID, ndlp->nlp_flag, 0);
+-
+       phba->fc_stat.elsXmitACC++;
+-      elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++      elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+       lpfc_nlp_put(ndlp);
+       elsiocb->context1 = NULL;  /* Don't need ndlp for cmpl,
+                                   * it could be freed */
++      spin_lock_irq(phba->host->host_lock);
+       rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
++      spin_unlock_irq(phba->host->host_lock);
+       if (rc == IOCB_ERROR) {
+               lpfc_els_free_iocb(phba, elsiocb);
+               return 1;
+@@ -2621,153 +2290,168 @@
+ }
+ int
+-lpfc_els_disc_adisc(struct lpfc_vport *vport)
++lpfc_els_disc_adisc(struct lpfc_hba *phba)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
++      int sentadisc;
+       struct lpfc_nodelist *ndlp, *next_ndlp;
+-      int sentadisc = 0;
++      sentadisc = 0;
+       /* go thru NPR nodes and issue any remaining ELS ADISCs */
+-      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
++      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
+               if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
+                   (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
+                   (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) {
+-                      spin_lock_irq(shost->host_lock);
++                      spin_lock_irq(phba->host->host_lock);
+                       ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+-                      spin_unlock_irq(shost->host_lock);
++                      spin_unlock_irq(phba->host->host_lock);
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
+-                      lpfc_issue_els_adisc(vport, ndlp, 0);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
++                      lpfc_issue_els_adisc(phba, ndlp, 0);
+                       sentadisc++;
+-                      vport->num_disc_nodes++;
+-                      if (vport->num_disc_nodes >=
+-                          vport->phba->cfg_discovery_threads) {
+-                              spin_lock_irq(shost->host_lock);
+-                              vport->fc_flag |= FC_NLP_MORE;
+-                              spin_unlock_irq(shost->host_lock);
++                      phba->num_disc_nodes++;
++                      if (phba->num_disc_nodes >=
++                          phba->cfg_discovery_threads) {
++                              spin_lock_irq(phba->host->host_lock);
++                              phba->fc_flag |= FC_NLP_MORE;
++                              spin_unlock_irq(phba->host->host_lock);
+                               break;
+                       }
+               }
+       }
+       if (sentadisc == 0) {
+-              spin_lock_irq(shost->host_lock);
+-              vport->fc_flag &= ~FC_NLP_MORE;
+-              spin_unlock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
++              phba->fc_flag &= ~FC_NLP_MORE;
++              spin_unlock_irq(phba->host->host_lock);
+       }
+       return sentadisc;
+ }
+ int
+-lpfc_els_disc_plogi(struct lpfc_vport *vport)
++lpfc_els_disc_plogi(struct lpfc_hba * phba)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
++      int sentplogi;
+       struct lpfc_nodelist *ndlp, *next_ndlp;
+-      int sentplogi = 0;
+-      /* go thru NPR nodes and issue any remaining ELS PLOGIs */
+-      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
++      sentplogi = 0;
++      /* go thru NPR list and issue any remaining ELS PLOGIs */
++      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
+               if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
+                   (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
+                   (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 &&
+                   (ndlp->nlp_flag & NLP_NPR_ADISC) == 0) {
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+-                      lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
++                      lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+                       sentplogi++;
+-                      vport->num_disc_nodes++;
+-                      if (vport->num_disc_nodes >=
+-                          vport->phba->cfg_discovery_threads) {
+-                              spin_lock_irq(shost->host_lock);
+-                              vport->fc_flag |= FC_NLP_MORE;
+-                              spin_unlock_irq(shost->host_lock);
++                      phba->num_disc_nodes++;
++                      if (phba->num_disc_nodes >=
++                          phba->cfg_discovery_threads) {
++                              spin_lock_irq(phba->host->host_lock);
++                              phba->fc_flag |= FC_NLP_MORE;
++                              spin_unlock_irq(phba->host->host_lock);
+                               break;
+                       }
+               }
+       }
+       if (sentplogi == 0) {
+-              spin_lock_irq(shost->host_lock);
+-              vport->fc_flag &= ~FC_NLP_MORE;
+-              spin_unlock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
++              phba->fc_flag &= ~FC_NLP_MORE;
++              spin_unlock_irq(phba->host->host_lock);
+       }
+       return sentplogi;
+ }
+-void
+-lpfc_els_flush_rscn(struct lpfc_vport *vport)
++int
++lpfc_els_flush_rscn(struct lpfc_hba * phba)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
++      struct lpfc_dmabuf *mp;
+       int i;
+-      for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
+-              lpfc_in_buf_free(phba, vport->fc_rscn_id_list[i]);
+-              vport->fc_rscn_id_list[i] = NULL;
+-      }
+-      spin_lock_irq(shost->host_lock);
+-      vport->fc_rscn_id_cnt = 0;
+-      vport->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);
+-      spin_unlock_irq(shost->host_lock);
+-      lpfc_can_disctmo(vport);
++      for (i = 0; i < phba->fc_rscn_id_cnt; i++) {
++              mp = phba->fc_rscn_id_list[i];
++              lpfc_mbuf_free(phba, mp->virt, mp->phys);
++              kfree(mp);
++              phba->fc_rscn_id_list[i] = NULL;
 +      }
-+out:
-+      /* cleanup any leftover locks from the do/while loop above */
-+      if (IS_ERR(hidden_dentry))
-+              while (count)
-+                      unionfs_unlock_dentry(path[count--]);
-+      kfree(path);
-+      return hidden_dentry;
-+}
-diff -Nurb linux-2.6.22-570/fs/unionfs/dentry.c linux-2.6.22-590/fs/unionfs/dentry.c
---- linux-2.6.22-570/fs/unionfs/dentry.c       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/dentry.c       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,353 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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 "union.h"
-+
-+/*
-+ * Revalidate a single dentry.
-+ * Assume that dentry's info node is locked.
-+ * Assume that parent(s) are all valid already, but
-+ * the child may not yet be valid.
-+ * Returns 1 if valid, 0 otherwise.
-+ */
-+static int __unionfs_d_revalidate_one(struct dentry *dentry,
-+                                    struct nameidata *nd)
-+{
-+      int valid = 1;          /* default is valid (1); invalid is 0. */
-+      struct dentry *hidden_dentry;
-+      int bindex, bstart, bend;
-+      int sbgen, dgen;
-+      int positive = 0;
-+      int locked = 0;
-+      int interpose_flag;
-+
-+      struct nameidata lowernd; /* TODO: be gentler to the stack */
-+
-+      if (nd)
-+              memcpy(&lowernd, nd, sizeof(struct nameidata));
-+      else
-+              memset(&lowernd, 0, sizeof(struct nameidata));
-+
-+      verify_locked(dentry);
-+
-+      /* if the dentry is unhashed, do NOT revalidate */
-+      if (d_deleted(dentry)) {
-+              printk(KERN_DEBUG "unionfs: unhashed dentry being "
-+                     "revalidated: %*s\n",
-+                     dentry->d_name.len, dentry->d_name.name);
-+              goto out;
++      phba->fc_rscn_id_cnt = 0;
++      spin_lock_irq(phba->host->host_lock);
++      phba->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);
++      spin_unlock_irq(phba->host->host_lock);
++      lpfc_can_disctmo(phba);
++      return 0;
+ }
+ int
+-lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did)
++lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did)
+ {
+       D_ID ns_did;
+       D_ID rscn_did;
++      struct lpfc_dmabuf *mp;
+       uint32_t *lp;
+-      uint32_t payload_len, i;
+-      struct lpfc_hba *phba = vport->phba;
++      uint32_t payload_len, cmd, i, match;
+       ns_did.un.word = did;
++      match = 0;
+       /* Never match fabric nodes for RSCNs */
+       if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
+-              return 0;
++              return(0);
+       /* If we are doing a FULL RSCN rediscovery, match everything */
+-      if (vport->fc_flag & FC_RSCN_DISCOVERY)
++      if (phba->fc_flag & FC_RSCN_DISCOVERY) {
+               return did;
 +      }
-+
-+      BUG_ON(dbstart(dentry) == -1);
-+      if (dentry->d_inode)
-+              positive = 1;
-+      dgen = atomic_read(&UNIONFS_D(dentry)->generation);
-+      sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
-+      /*
-+       * If we are working on an unconnected dentry, then there is no
-+       * revalidation to be done, because this file does not exist within
-+       * the namespace, and Unionfs operates on the namespace, not data.
-+       */
-+      if (sbgen != dgen) {
-+              struct dentry *result;
-+              int pdgen;
-+
-+              /* The root entry should always be valid */
-+              BUG_ON(IS_ROOT(dentry));
-+
-+              /* We can't work correctly if our parent isn't valid. */
-+              pdgen = atomic_read(&UNIONFS_D(dentry->d_parent)->generation);
-+              BUG_ON(pdgen != sbgen); /* should never happen here */
-+
-+              /* Free the pointers for our inodes and this dentry. */
-+              bstart = dbstart(dentry);
-+              bend = dbend(dentry);
-+              if (bstart >= 0) {
-+                      struct dentry *hidden_dentry;
-+                      for (bindex = bstart; bindex <= bend; bindex++) {
-+                              hidden_dentry =
-+                                      unionfs_lower_dentry_idx(dentry,
-+                                                               bindex);
-+                              dput(hidden_dentry);
-+                      }
-+              }
-+              set_dbstart(dentry, -1);
-+              set_dbend(dentry, -1);
-+
-+              interpose_flag = INTERPOSE_REVAL_NEG;
-+              if (positive) {
-+                      interpose_flag = INTERPOSE_REVAL;
-+                      /*
-+                       * During BRM, the VFS could already hold a lock on
-+                       * a file being read, so don't lock it again
-+                       * (deadlock), but if you lock it in this function,
-+                       * then release it here too.
-+                       */
-+                      if (!mutex_is_locked(&dentry->d_inode->i_mutex)) {
-+                              mutex_lock(&dentry->d_inode->i_mutex);
-+                              locked = 1;
-+                      }
-+
-+                      bstart = ibstart(dentry->d_inode);
-+                      bend = ibend(dentry->d_inode);
-+                      if (bstart >= 0) {
-+                              struct inode *hidden_inode;
-+                              for (bindex = bstart; bindex <= bend;
-+                                   bindex++) {
-+                                      hidden_inode =
-+                                              unionfs_lower_inode_idx(
-+                                                      dentry->d_inode,
-+                                                      bindex);
-+                                      iput(hidden_inode);
+-      for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
+-              lp = vport->fc_rscn_id_list[i]->virt;
+-              payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
+-              payload_len -= sizeof(uint32_t);        /* take off word 0 */
++      for (i = 0; i < phba->fc_rscn_id_cnt; i++) {
++              mp = phba->fc_rscn_id_list[i];
++              lp = (uint32_t *) mp->virt;
++              cmd = *lp++;
++              payload_len = be32_to_cpu(cmd) & 0xffff; /* payload length */
++              payload_len -= sizeof (uint32_t);       /* take off word 0 */
+               while (payload_len) {
+-                      rscn_did.un.word = be32_to_cpu(*lp++);
+-                      payload_len -= sizeof(uint32_t);
++                      rscn_did.un.word = *lp++;
++                      rscn_did.un.word = be32_to_cpu(rscn_did.un.word);
++                      payload_len -= sizeof (uint32_t);
+                       switch (rscn_did.un.b.resv) {
+                       case 0: /* Single N_Port ID effected */
+-                              if (ns_did.un.word == rscn_did.un.word)
+-                                      return did;
++                              if (ns_did.un.word == rscn_did.un.word) {
++                                      match = did;
 +                              }
-+                      }
-+                      kfree(UNIONFS_I(dentry->d_inode)->lower_inodes);
-+                      UNIONFS_I(dentry->d_inode)->lower_inodes = NULL;
-+                      ibstart(dentry->d_inode) = -1;
-+                      ibend(dentry->d_inode) = -1;
-+                      if (locked)
-+                              mutex_unlock(&dentry->d_inode->i_mutex);
-+              }
-+
-+              result = unionfs_lookup_backend(dentry, &lowernd,
-+                                              interpose_flag);
-+              if (result) {
-+                      if (IS_ERR(result)) {
-+                              valid = 0;
-+                              goto out;
-+                      }
-+                      /*
-+                       * current unionfs_lookup_backend() doesn't return
-+                       * a valid dentry
-+                       */
-+                      dput(dentry);
-+                      dentry = result;
-+              }
-+
-+              if (positive && UNIONFS_I(dentry->d_inode)->stale) {
-+                      make_bad_inode(dentry->d_inode);
-+                      d_drop(dentry);
-+                      valid = 0;
-+                      goto out;
-+              }
-+              goto out;
-+      }
-+
-+      /* The revalidation must occur across all branches */
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+      BUG_ON(bstart == -1);
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!hidden_dentry || !hidden_dentry->d_op
-+                  || !hidden_dentry->d_op->d_revalidate)
-+                      continue;
-+              if (!hidden_dentry->d_op->d_revalidate(hidden_dentry,
-+                                                     &lowernd))
-+                      valid = 0;
-+      }
-+
-+      if (!dentry->d_inode)
-+              valid = 0;
-+
-+      if (valid) {
-+              fsstack_copy_attr_all(dentry->d_inode,
-+                                    unionfs_lower_inode(dentry->d_inode),
-+                                    unionfs_get_nlinks);
-+              fsstack_copy_inode_size(dentry->d_inode,
-+                                      unionfs_lower_inode(dentry->d_inode));
-+      }
-+
-+out:
-+      return valid;
-+}
-+
-+/*
-+ * Revalidate a parent chain of dentries, then the actual node.
-+ * Assumes that dentry is locked, but will lock all parents if/when needed.
-+ */
-+int __unionfs_d_revalidate_chain(struct dentry *dentry, struct nameidata *nd)
-+{
-+      int valid = 0;          /* default is invalid (0); valid is 1. */
-+      struct dentry **chain = NULL; /* chain of dentries to reval */
-+      int chain_len = 0;
-+      struct dentry *dtmp;
-+      int sbgen, dgen, i;
-+      int saved_bstart, saved_bend, bindex;
-+
-+      /* find length of chain needed to revalidate */
-+      /* XXX: should I grab some global (dcache?) lock? */
-+      chain_len = 0;
-+      sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
-+      dtmp = dentry->d_parent;
-+      dgen = atomic_read(&UNIONFS_D(dtmp)->generation);
-+      while (sbgen != dgen) {
-+              /* The root entry should always be valid */
-+              BUG_ON(IS_ROOT(dtmp));
-+              chain_len++;
-+              dtmp = dtmp->d_parent;
-+              dgen = atomic_read(&UNIONFS_D(dtmp)->generation);
-+      }
-+      if (chain_len == 0)
-+              goto out_this;  /* shortcut if parents are OK */
-+
-+      /*
-+       * Allocate array of dentries to reval.  We could use linked lists,
-+       * but the number of entries we need to alloc here is often small,
-+       * and short lived, so locality will be better.
-+       */
-+      chain = kzalloc(chain_len * sizeof(struct dentry *), GFP_KERNEL);
-+      if (!chain) {
-+              printk("unionfs: no more memory in %s\n", __FUNCTION__);
-+              goto out;
-+      }
-+
-+      /*
-+       * lock all dentries in chain, in child to parent order.
-+       * if failed, then sleep for a little, then retry.
-+       */
-+      dtmp = dentry->d_parent;
-+      for (i=chain_len-1; i>=0; i--) {
-+              chain[i] = dget(dtmp);
-+              dtmp = dtmp->d_parent;
-+      }
-+
-+      /*
-+       * call __unionfs_d_revalidate() on each dentry, but in parent to
-+       * child order.
-+       */
-+      for (i=0; i<chain_len; i++) {
-+              unionfs_lock_dentry(chain[i]);
-+              saved_bstart = dbstart(chain[i]);
-+              saved_bend = dbend(chain[i]);
-+              sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
-+              dgen = atomic_read(&UNIONFS_D(chain[i])->generation);
-+
-+              valid = __unionfs_d_revalidate_one(chain[i], nd);
-+              /* XXX: is this the correct mntput condition?! */
-+              if (valid && chain_len > 0 &&
-+                  sbgen != dgen && chain[i]->d_inode &&
-+                  S_ISDIR(chain[i]->d_inode->i_mode)) {
-+                      for (bindex = saved_bstart; bindex <= saved_bend;
-+                           bindex++)
-+                              unionfs_mntput(chain[i], bindex);
-+              }
-+              unionfs_unlock_dentry(chain[i]);
-+
-+              if (!valid)
-+                      goto out_free;
-+      }
-+
-+
-+out_this:
-+      /* finally, lock this dentry and revalidate it */
-+      verify_locked(dentry);
-+      dgen = atomic_read(&UNIONFS_D(dentry)->generation);
-+      valid = __unionfs_d_revalidate_one(dentry, nd);
-+
-+      /*
-+       * If __unionfs_d_revalidate_one() succeeded above, then it will
-+       * have incremented the refcnt of the mnt's, but also the branch
-+       * indices of the dentry will have been updated (to take into
-+       * account any branch insertions/deletion.  So the current
-+       * dbstart/dbend match the current, and new, indices of the mnts
-+       * which __unionfs_d_revalidate_one has incremented.  Note: the "if"
-+       * test below does not depend on whether chain_len was 0 or greater.
-+       */
-+      if (valid && sbgen != dgen)
-+              for (bindex = dbstart(dentry);
-+                   bindex <= dbend(dentry);
-+                   bindex++)
-+                      unionfs_mntput(dentry, bindex);
-+
-+out_free:
-+      /* unlock/dput all dentries in chain and return status */
-+      if (chain_len > 0) {
-+              for (i=0; i<chain_len; i++)
-+                      dput(chain[i]);
-+              kfree(chain);
-+      }
-+out:
-+      return valid;
-+}
-+
-+static int unionfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
-+{
-+      int err;
-+
-+      unionfs_read_lock(dentry->d_sb);
-+
-+      unionfs_lock_dentry(dentry);
-+      err = __unionfs_d_revalidate_chain(dentry, nd);
-+      unionfs_unlock_dentry(dentry);
-+
-+      unionfs_read_unlock(dentry->d_sb);
-+
-+      return err;
-+}
-+
-+/*
-+ * At this point no one can reference this dentry, so we don't have to be
-+ * careful about concurrent access.
-+ */
-+static void unionfs_d_release(struct dentry *dentry)
-+{
-+      int bindex, bstart, bend;
-+
-+      unionfs_read_lock(dentry->d_sb);
-+
-+      /* this could be a negative dentry, so check first */
-+      if (!UNIONFS_D(dentry)) {
-+              printk(KERN_DEBUG "unionfs: dentry without private data: %.*s",
-+                     dentry->d_name.len, dentry->d_name.name);
-+              goto out;
-+      } else if (dbstart(dentry) < 0) {
-+              /* this is due to a failed lookup */
-+              printk(KERN_DEBUG "unionfs: dentry without hidden "
-+                     "dentries: %.*s",
-+                     dentry->d_name.len, dentry->d_name.name);
-+              goto out_free;
-+      }
-+
-+      /* Release all the hidden dentries */
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              dput(unionfs_lower_dentry_idx(dentry, bindex));
-+              unionfs_mntput(dentry, bindex);
-+
-+              unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
-+              unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
-+      }
-+      /* free private data (unionfs_dentry_info) here */
-+      kfree(UNIONFS_D(dentry)->lower_paths);
-+      UNIONFS_D(dentry)->lower_paths = NULL;
-+
-+out_free:
-+      /* No need to unlock it, because it is disappeared. */
-+      free_dentry_private_data(dentry);
-+
-+out:
-+      unionfs_read_unlock(dentry->d_sb);
-+      return;
-+}
-+
-+struct dentry_operations unionfs_dops = {
-+      .d_revalidate   = unionfs_d_revalidate,
-+      .d_release      = unionfs_d_release,
-+};
-diff -Nurb linux-2.6.22-570/fs/unionfs/dirfops.c linux-2.6.22-590/fs/unionfs/dirfops.c
---- linux-2.6.22-570/fs/unionfs/dirfops.c      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/dirfops.c      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,276 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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 "union.h"
-+
-+/* Make sure our rdstate is playing by the rules. */
-+static void verify_rdstate_offset(struct unionfs_dir_state *rdstate)
-+{
-+      BUG_ON(rdstate->offset >= DIREOF);
-+      BUG_ON(rdstate->cookie >= MAXRDCOOKIE);
-+}
-+
-+struct unionfs_getdents_callback {
-+      struct unionfs_dir_state *rdstate;
-+      void *dirent;
-+      int entries_written;
-+      int filldir_called;
-+      int filldir_error;
-+      filldir_t filldir;
-+      struct super_block *sb;
-+};
-+
-+/* based on generic filldir in fs/readir.c */
-+static int unionfs_filldir(void *dirent, const char *name, int namelen,
-+                         loff_t offset, u64 ino, unsigned int d_type)
-+{
-+      struct unionfs_getdents_callback *buf = dirent;
-+      struct filldir_node *found = NULL;
-+      int err = 0;
-+      int is_wh_entry = 0;
-+
-+      buf->filldir_called++;
-+
-+      if ((namelen > UNIONFS_WHLEN) &&
-+          !strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN)) {
-+              name += UNIONFS_WHLEN;
-+              namelen -= UNIONFS_WHLEN;
-+              is_wh_entry = 1;
-+      }
-+
-+      found = find_filldir_node(buf->rdstate, name, namelen);
-+
-+      if (found)
-+              goto out;
-+
-+      /* if 'name' isn't a whiteout, filldir it. */
-+      if (!is_wh_entry) {
-+              off_t pos = rdstate2offset(buf->rdstate);
-+              u64 unionfs_ino = ino;
-+
-+              if (!err) {
-+                      err = buf->filldir(buf->dirent, name, namelen, pos,
-+                                         unionfs_ino, d_type);
-+                      buf->rdstate->offset++;
-+                      verify_rdstate_offset(buf->rdstate);
-+              }
-+      }
-+      /*
-+       * If we did fill it, stuff it in our hash, otherwise return an
-+       * error.
-+       */
-+      if (err) {
-+              buf->filldir_error = err;
-+              goto out;
-+      }
-+      buf->entries_written++;
-+      if ((err = add_filldir_node(buf->rdstate, name, namelen,
-+                                  buf->rdstate->bindex, is_wh_entry)))
-+              buf->filldir_error = err;
-+
-+out:
-+      return err;
-+}
-+
-+static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
-+{
-+      int err = 0;
-+      struct file *hidden_file = NULL;
-+      struct inode *inode = NULL;
-+      struct unionfs_getdents_callback buf;
-+      struct unionfs_dir_state *uds;
-+      int bend;
-+      loff_t offset;
-+
-+      unionfs_read_lock(file->f_path.dentry->d_sb);
-+
-+      if ((err = unionfs_file_revalidate(file, 0)))
-+              goto out;
-+
-+      inode = file->f_dentry->d_inode;
-+
-+      uds = UNIONFS_F(file)->rdstate;
-+      if (!uds) {
-+              if (file->f_pos == DIREOF) {
-+                      goto out;
-+              } else if (file->f_pos > 0) {
-+                      uds = find_rdstate(inode, file->f_pos);
-+                      if (!uds) {
-+                              err = -ESTALE;
-+                              goto out;
-+                      }
-+                      UNIONFS_F(file)->rdstate = uds;
-+              } else {
-+                      init_rdstate(file);
-+                      uds = UNIONFS_F(file)->rdstate;
-+              }
+                               break;
+                       case 1: /* Whole N_Port Area effected */
+                               if ((ns_did.un.b.domain == rscn_did.un.b.domain)
+                                   && (ns_did.un.b.area == rscn_did.un.b.area))
+-                                      return did;
++                                      {
++                                              match = did;
++                                      }
+                               break;
+                       case 2: /* Whole N_Port Domain effected */
+                               if (ns_did.un.b.domain == rscn_did.un.b.domain)
+-                                      return did;
++                                      {
++                                              match = did;
++                                      }
++                              break;
++                      case 3: /* Whole Fabric effected */
++                              match = did;
+                               break;
+                       default:
+-                              /* Unknown Identifier in RSCN node */
++                              /* Unknown Identifier in RSCN list */
+                               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                                              "%d (%d):0217 Unknown "
+-                                              "Identifier in RSCN payload "
+-                                              "Data: x%x\n",
+-                                              phba->brd_no, vport->vpi,
+-                                              rscn_did.un.word);
+-                      case 3: /* Whole Fabric effected */
+-                              return did;
++                                              "%d:0217 Unknown Identifier in "
++                                              "RSCN payload Data: x%x\n",
++                                              phba->brd_no, rscn_did.un.word);
++                              break;
+                       }
++                      if (match) {
++                              break;
+               }
+       }
+-      return 0;
 +      }
-+      bend = fbend(file);
-+
-+      while (uds->bindex <= bend) {
-+              hidden_file = unionfs_lower_file_idx(file, uds->bindex);
-+              if (!hidden_file) {
-+                      uds->bindex++;
-+                      uds->dirpos = 0;
-+                      continue;
-+              }
++      return match;
+ }
+ static int
+-lpfc_rscn_recovery_check(struct lpfc_vport *vport)
++lpfc_rscn_recovery_check(struct lpfc_hba *phba)
+ {
+       struct lpfc_nodelist *ndlp = NULL;
+@@ -2775,12 +2459,12 @@
+        * them to NPR state.
+        */
+-      list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
++      list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+               if (ndlp->nlp_state == NLP_STE_UNUSED_NODE ||
+-                  lpfc_rscn_payload_check(vport, ndlp->nlp_DID) == 0)
++                  lpfc_rscn_payload_check(phba, ndlp->nlp_DID) == 0)
+                       continue;
+-              lpfc_disc_state_machine(vport, ndlp, NULL,
++              lpfc_disc_state_machine(phba, ndlp, NULL,
+                                       NLP_EVT_DEVICE_RECOVERY);
+               /*
+@@ -2788,248 +2472,175 @@
+                * recovery event.
+                */
+               if (ndlp->nlp_flag & NLP_DELAY_TMO)
+-                      lpfc_cancel_retry_delay_tmo(vport, ndlp);
++                      lpfc_cancel_retry_delay_tmo(phba, ndlp);
+       }
+       return 0;
+ }
+ static int
+-lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+-                struct lpfc_nodelist *ndlp, uint8_t newnode)
++lpfc_els_rcv_rscn(struct lpfc_hba * phba,
++                struct lpfc_iocbq * cmdiocb,
++                struct lpfc_nodelist * ndlp, uint8_t newnode)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+       struct lpfc_dmabuf *pcmd;
+-      struct lpfc_vport *next_vport;
+-      uint32_t *lp, *datap;
++      uint32_t *lp;
+       IOCB_t *icmd;
+-      uint32_t payload_len, length, nportid, *cmd;
+-      int rscn_cnt = vport->fc_rscn_id_cnt;
+-      int rscn_id = 0, hba_id = 0;
++      uint32_t payload_len, cmd;
+       int i;
+       icmd = &cmdiocb->iocb;
+       pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
+       lp = (uint32_t *) pcmd->virt;
+-      payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
+-      payload_len -= sizeof(uint32_t);        /* take off word 0 */
++      cmd = *lp++;
++      payload_len = be32_to_cpu(cmd) & 0xffff;        /* payload length */
++      payload_len -= sizeof (uint32_t);       /* take off word 0 */
++      cmd &= ELS_CMD_MASK;
+       /* RSCN received */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0214 RSCN received Data: x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
+-                      *lp, rscn_cnt);
++      lpfc_printf_log(phba,
++                      KERN_INFO,
++                      LOG_DISCOVERY,
++                      "%d:0214 RSCN received Data: x%x x%x x%x x%x\n",
++                      phba->brd_no,
++                      phba->fc_flag, payload_len, *lp, phba->fc_rscn_id_cnt);
+       for (i = 0; i < payload_len/sizeof(uint32_t); i++)
+-              fc_host_post_event(shost, fc_get_event_number(),
++              fc_host_post_event(phba->host, fc_get_event_number(),
+                       FCH_EVT_RSCN, lp[i]);
+       /* If we are about to begin discovery, just ACC the RSCN.
+        * Discovery processing will satisfy it.
+        */
+-      if (vport->port_state <= LPFC_NS_QRY) {
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV RSCN ignore: did:x%x/ste:x%x flg:x%x",
+-                      ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
+-
+-              lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
++      if (phba->hba_state <= LPFC_NS_QRY) {
++              lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
+                                                               newnode);
+               return 0;
+       }
+-      /* If this RSCN just contains NPortIDs for other vports on this HBA,
+-       * just ACC and ignore it.
+-       */
+-      if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+-              !(phba->cfg_peer_port_login)) {
+-              i = payload_len;
+-              datap = lp;
+-              while (i > 0) {
+-                      nportid = *datap++;
+-                      nportid = ((be32_to_cpu(nportid)) & Mask_DID);
+-                      i -= sizeof(uint32_t);
+-                      rscn_id++;
+-                      list_for_each_entry(next_vport, &phba->port_list,
+-                              listentry) {
+-                              if (nportid == next_vport->fc_myDID) {
+-                                      hba_id++;
+-                                      break;
+-                              }
+-                      }
+-              }
+-              if (rscn_id == hba_id) {
+-                      /* ALL NPortIDs in RSCN are on HBA */
+-                      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                        "%d (%d):0214 Ignore RSCN Data: x%x x%x x%x x%x\n",
+-                        phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
+-                        *lp, rscn_cnt);
+-
+-                      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                              "RCV RSCN vport:  did:x%x/ste:x%x flg:x%x",
+-                              ndlp->nlp_DID, vport->port_state,
+-                              ndlp->nlp_flag);
+-
+-                      lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb,
+-                              ndlp, NULL, newnode);
+-                      return 0;
+-              }
+-      }
+-
+       /* If we are already processing an RSCN, save the received
+        * RSCN payload buffer, cmdiocb->context2 to process later.
+        */
+-      if (vport->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV RSCN defer:  did:x%x/ste:x%x flg:x%x",
+-                      ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
+-
+-              vport->fc_flag |= FC_RSCN_DEFERRED;
+-              if ((rscn_cnt < FC_MAX_HOLD_RSCN) &&
+-                  !(vport->fc_flag & FC_RSCN_DISCOVERY)) {
+-                      spin_lock_irq(shost->host_lock);
+-                      vport->fc_flag |= FC_RSCN_MODE;
+-                      spin_unlock_irq(shost->host_lock);
+-                      if (rscn_cnt) {
+-                              cmd = vport->fc_rscn_id_list[rscn_cnt-1]->virt;
+-                              length = be32_to_cpu(*cmd & ~ELS_CMD_MASK);
+-                      }
+-                      if ((rscn_cnt) &&
+-                          (payload_len + length <= LPFC_BPL_SIZE)) {
+-                              *cmd &= ELS_CMD_MASK;
+-                              *cmd |= be32_to_cpu(payload_len + length);
+-                              memcpy(((uint8_t *)cmd) + length, lp,
+-                                     payload_len);
+-                      } else {
+-                              vport->fc_rscn_id_list[rscn_cnt] = pcmd;
+-                              vport->fc_rscn_id_cnt++;
++      if (phba->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
++              if ((phba->fc_rscn_id_cnt < FC_MAX_HOLD_RSCN) &&
++                  !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
++                      spin_lock_irq(phba->host->host_lock);
++                      phba->fc_flag |= FC_RSCN_MODE;
++                      spin_unlock_irq(phba->host->host_lock);
++                      phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;
 +
-+              /* prepare callback buffer */
-+              buf.filldir_called = 0;
-+              buf.filldir_error = 0;
-+              buf.entries_written = 0;
-+              buf.dirent = dirent;
-+              buf.filldir = filldir;
-+              buf.rdstate = uds;
-+              buf.sb = inode->i_sb;
-+
-+              /* Read starting from where we last left off. */
-+              offset = vfs_llseek(hidden_file, uds->dirpos, SEEK_SET);
-+              if (offset < 0) {
-+                      err = offset;
-+                      goto out;
+                       /* If we zero, cmdiocb->context2, the calling
+                        * routine will not try to free it.
+                        */
+                       cmdiocb->context2 = NULL;
+-                      }
+                       /* Deferred RSCN */
+                       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                                      "%d (%d):0235 Deferred RSCN "
++                                      "%d:0235 Deferred RSCN "
+                                       "Data: x%x x%x x%x\n",
+-                                      phba->brd_no, vport->vpi,
+-                                      vport->fc_rscn_id_cnt, vport->fc_flag,
+-                                      vport->port_state);
++                                      phba->brd_no, phba->fc_rscn_id_cnt,
++                                      phba->fc_flag, phba->hba_state);
+               } else {
+-                      spin_lock_irq(shost->host_lock);
+-                      vport->fc_flag |= FC_RSCN_DISCOVERY;
+-                      spin_unlock_irq(shost->host_lock);
++                      spin_lock_irq(phba->host->host_lock);
++                      phba->fc_flag |= FC_RSCN_DISCOVERY;
++                      spin_unlock_irq(phba->host->host_lock);
+                       /* ReDiscovery RSCN */
+                       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                                      "%d (%d):0234 ReDiscovery RSCN "
++                                      "%d:0234 ReDiscovery RSCN "
+                                       "Data: x%x x%x x%x\n",
+-                                      phba->brd_no, vport->vpi,
+-                                      vport->fc_rscn_id_cnt, vport->fc_flag,
+-                                      vport->port_state);
++                                      phba->brd_no, phba->fc_rscn_id_cnt,
++                                      phba->fc_flag, phba->hba_state);
+               }
+               /* Send back ACC */
+-              lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
++              lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
+                                                               newnode);
+               /* send RECOVERY event for ALL nodes that match RSCN payload */
+-              lpfc_rscn_recovery_check(vport);
+-              vport->fc_flag &= ~FC_RSCN_DEFERRED;
++              lpfc_rscn_recovery_check(phba);
+               return 0;
+       }
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-              "RCV RSCN:        did:x%x/ste:x%x flg:x%x",
+-              ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
+-
+-      spin_lock_irq(shost->host_lock);
+-      vport->fc_flag |= FC_RSCN_MODE;
+-      spin_unlock_irq(shost->host_lock);
+-      vport->fc_rscn_id_list[vport->fc_rscn_id_cnt++] = pcmd;
++      phba->fc_flag |= FC_RSCN_MODE;
++      phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;
+       /*
+        * If we zero, cmdiocb->context2, the calling routine will
+        * not try to free it.
+        */
+       cmdiocb->context2 = NULL;
+-      lpfc_set_disctmo(vport);
++      lpfc_set_disctmo(phba);
+       /* Send back ACC */
+-      lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode);
++      lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode);
+       /* send RECOVERY event for ALL nodes that match RSCN payload */
+-      lpfc_rscn_recovery_check(vport);
++      lpfc_rscn_recovery_check(phba);
+-      return lpfc_els_handle_rscn(vport);
++      return lpfc_els_handle_rscn(phba);
+ }
+ int
+-lpfc_els_handle_rscn(struct lpfc_vport *vport)
++lpfc_els_handle_rscn(struct lpfc_hba * phba)
+ {
+       struct lpfc_nodelist *ndlp;
+-      struct lpfc_hba *phba = vport->phba;
+-
+-      /* Ignore RSCN if the port is being torn down. */
+-      if (vport->load_flag & FC_UNLOADING) {
+-              lpfc_els_flush_rscn(vport);
+-              return 0;
+-      }
+       /* Start timer for RSCN processing */
+-      lpfc_set_disctmo(vport);
++      lpfc_set_disctmo(phba);
+       /* RSCN processed */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0215 RSCN processed Data: x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi,
+-                      vport->fc_flag, 0, vport->fc_rscn_id_cnt,
+-                      vport->port_state);
++      lpfc_printf_log(phba,
++                      KERN_INFO,
++                      LOG_DISCOVERY,
++                      "%d:0215 RSCN processed Data: x%x x%x x%x x%x\n",
++                      phba->brd_no,
++                      phba->fc_flag, 0, phba->fc_rscn_id_cnt,
++                      phba->hba_state);
+       /* To process RSCN, first compare RSCN data with NameServer */
+-      vport->fc_ns_retry = 0;
+-      ndlp = lpfc_findnode_did(vport, NameServer_DID);
++      phba->fc_ns_retry = 0;
++      ndlp = lpfc_findnode_did(phba, NameServer_DID);
+       if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
+               /* Good ndlp, issue CT Request to NameServer */
+-              if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0) == 0)
++              if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) {
+                       /* Wait for NameServer query cmpl before we can
+                          continue */
+                       return 1;
 +              }
-+              err = vfs_readdir(hidden_file, unionfs_filldir, &buf);
-+
-+              /* Save the position for when we continue. */
-+              offset = vfs_llseek(hidden_file, 0, SEEK_CUR);
-+              if (offset < 0) {
-+                      err = offset;
-+                      goto out;
+       } else {
+               /* If login to NameServer does not exist, issue one */
+               /* Good status, issue PLOGI to NameServer */
+-              ndlp = lpfc_findnode_did(vport, NameServer_DID);
+-              if (ndlp)
++              ndlp = lpfc_findnode_did(phba, NameServer_DID);
++              if (ndlp) {
+                       /* Wait for NameServer login cmpl before we can
+                          continue */
+                       return 1;
+-
 +              }
-+              uds->dirpos = offset;
-+
-+              /* Copy the atime. */
-+              fsstack_copy_attr_atime(inode, hidden_file->f_dentry->d_inode);
-+
-+              if (err < 0)
-+                      goto out;
-+
-+              if (buf.filldir_error)
-+                      break;
+               ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+               if (!ndlp) {
+-                      lpfc_els_flush_rscn(vport);
++                      lpfc_els_flush_rscn(phba);
+                       return 0;
+               } else {
+-                      lpfc_nlp_init(vport, ndlp, NameServer_DID);
++                      lpfc_nlp_init(phba, ndlp, NameServer_DID);
+                       ndlp->nlp_type |= NLP_FABRIC;
+                       ndlp->nlp_prev_state = ndlp->nlp_state;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+-                      lpfc_issue_els_plogi(vport, NameServer_DID, 0);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
++                      lpfc_issue_els_plogi(phba, NameServer_DID, 0);
+                       /* Wait for NameServer login cmpl before we can
+                          continue */
+                       return 1;
+               }
+       }
+-      lpfc_els_flush_rscn(vport);
++      lpfc_els_flush_rscn(phba);
+       return 0;
+ }
+ static int
+-lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+-                 struct lpfc_nodelist *ndlp, uint8_t newnode)
++lpfc_els_rcv_flogi(struct lpfc_hba * phba,
++                 struct lpfc_iocbq * cmdiocb,
++                 struct lpfc_nodelist * ndlp, uint8_t newnode)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+       struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
+       uint32_t *lp = (uint32_t *) pcmd->virt;
+       IOCB_t *icmd = &cmdiocb->iocb;
+@@ -3044,7 +2655,7 @@
+       /* FLOGI received */
+-      lpfc_set_disctmo(vport);
++      lpfc_set_disctmo(phba);
+       if (phba->fc_topology == TOPOLOGY_LOOP) {
+               /* We should never receive a FLOGI in loop mode, ignore it */
+@@ -3053,34 +2664,33 @@
+               /* An FLOGI ELS command <elsCmd> was received from DID <did> in
+                  Loop Mode */
+               lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                              "%d (%d):0113 An FLOGI ELS command x%x was "
+-                              "received from DID x%x in Loop Mode\n",
+-                              phba->brd_no, vport->vpi, cmd, did);
++                              "%d:0113 An FLOGI ELS command x%x was received "
++                              "from DID x%x in Loop Mode\n",
++                              phba->brd_no, cmd, did);
+               return 1;
+       }
+       did = Fabric_DID;
+-      if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3))) {
++      if ((lpfc_check_sparm(phba, ndlp, sp, CLASS3))) {
+               /* For a FLOGI we accept, then if our portname is greater
+                * then the remote portname we initiate Nport login.
+                */
+-              rc = memcmp(&vport->fc_portname, &sp->portName,
+-                          sizeof(struct lpfc_name));
++              rc = memcmp(&phba->fc_portname, &sp->portName,
++                          sizeof (struct lpfc_name));
+               if (!rc) {
+-                      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-                      if (!mbox)
++                      if ((mbox = mempool_alloc(phba->mbox_mem_pool,
++                                                GFP_KERNEL)) == 0) {
+                               return 1;
+-
++                      }
+                       lpfc_linkdown(phba);
+                       lpfc_init_link(phba, mbox,
+                                      phba->cfg_topology,
+                                      phba->cfg_link_speed);
+                       mbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
+                       mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-                      mbox->vport = vport;
+                       rc = lpfc_sli_issue_mbox
+                               (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
+                       lpfc_set_loopback_flag(phba);
+@@ -3089,34 +2699,31 @@
+                       }
+                       return 1;
+               } else if (rc > 0) {    /* greater than */
+-                      spin_lock_irq(shost->host_lock);
+-                      vport->fc_flag |= FC_PT2PT_PLOGI;
+-                      spin_unlock_irq(shost->host_lock);
+-              }
+-              spin_lock_irq(shost->host_lock);
+-              vport->fc_flag |= FC_PT2PT;
+-              vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+-              spin_unlock_irq(shost->host_lock);
++                      spin_lock_irq(phba->host->host_lock);
++                      phba->fc_flag |= FC_PT2PT_PLOGI;
++                      spin_unlock_irq(phba->host->host_lock);
++              }
++              phba->fc_flag |= FC_PT2PT;
++              phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+       } else {
+               /* Reject this request because invalid parameters */
+               stat.un.b.lsRjtRsvd0 = 0;
+               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+               stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
+               stat.un.b.vendorUnique = 0;
+-              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+-                      NULL);
++              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+               return 1;
+       }
+       /* Send back ACC */
+-      lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode);
++      lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode);
+       return 0;
+ }
+ static int
+-lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+-                struct lpfc_nodelist *ndlp)
++lpfc_els_rcv_rnid(struct lpfc_hba * phba,
++                struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
+ {
+       struct lpfc_dmabuf *pcmd;
+       uint32_t *lp;
+@@ -3139,7 +2746,7 @@
+       case 0:
+       case RNID_TOPOLOGY_DISC:
+               /* Send back ACC */
+-              lpfc_els_rsp_rnid_acc(vport, rn->Format, cmdiocb, ndlp);
++              lpfc_els_rsp_rnid_acc(phba, rn->Format, cmdiocb, ndlp);
+               break;
+       default:
+               /* Reject this request because format not supported */
+@@ -3147,14 +2754,13 @@
+               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+               stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
+               stat.un.b.vendorUnique = 0;
+-              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+-                      NULL);
++              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+       }
+       return 0;
+ }
+ static int
+-lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
++lpfc_els_rcv_lirr(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+                struct lpfc_nodelist *ndlp)
+ {
+       struct ls_rjt stat;
+@@ -3164,15 +2770,15 @@
+       stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+       stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
+       stat.un.b.vendorUnique = 0;
+-      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
++      lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+       return 0;
+ }
+ static void
+ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ {
+-      struct lpfc_sli *psli = &phba->sli;
+-      struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
++      struct lpfc_sli *psli;
++      struct lpfc_sli_ring *pring;
+       MAILBOX_t *mb;
+       IOCB_t *icmd;
+       RPS_RSP *rps_rsp;
+@@ -3182,6 +2788,8 @@
+       uint16_t xri, status;
+       uint32_t cmdsize;
++      psli = &phba->sli;
++      pring = &psli->ring[LPFC_ELS_RING];
+       mb = &pmb->mb;
+       ndlp = (struct lpfc_nodelist *) pmb->context2;
+@@ -3196,8 +2804,7 @@
+       cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t);
+       mempool_free(pmb, phba->mbox_mem_pool);
+-      elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize,
+-                                   lpfc_max_els_tries, ndlp,
++      elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp,
+                                               ndlp->nlp_DID, ELS_CMD_ACC);
+       lpfc_nlp_put(ndlp);
+       if (!elsiocb)
+@@ -3208,14 +2815,14 @@
+       pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+       *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
+-      pcmd += sizeof(uint32_t); /* Skip past command */
++      pcmd += sizeof (uint32_t); /* Skip past command */
+       rps_rsp = (RPS_RSP *)pcmd;
+       if (phba->fc_topology != TOPOLOGY_LOOP)
+               status = 0x10;
+       else
+               status = 0x8;
+-      if (phba->pport->fc_flag & FC_FABRIC)
++      if (phba->fc_flag & FC_FABRIC)
+               status |= 0x4;
+       rps_rsp->rsvd1 = 0;
+@@ -3229,25 +2836,25 @@
+       /* Xmit ELS RPS ACC response tag <ulpIoTag> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0118 Xmit ELS RPS ACC response tag x%x "
+-                      "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
+-                      "rpi x%x\n",
+-                      phba->brd_no, ndlp->vport->vpi, elsiocb->iotag,
++                      "%d:0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
++                      "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
++                      phba->brd_no, elsiocb->iotag,
+                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
+                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+-      elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++      elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+       phba->fc_stat.elsXmitACC++;
+-      if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR)
 +
-+              if (!buf.entries_written) {
-+                      uds->bindex++;
-+                      uds->dirpos = 0;
-+              }
++      if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+               lpfc_els_free_iocb(phba, elsiocb);
 +      }
-+
-+      if (!buf.filldir_error && uds->bindex >= bend) {
-+              /* Save the number of hash entries for next time. */
-+              UNIONFS_I(inode)->hashsize = uds->hashentries;
-+              free_rdstate(uds);
-+              UNIONFS_F(file)->rdstate = NULL;
-+              file->f_pos = DIREOF;
-+      } else
-+              file->f_pos = rdstate2offset(uds);
-+
-+out:
-+      unionfs_read_unlock(file->f_path.dentry->d_sb);
-+      return err;
-+}
-+
-+/*
-+ * This is not meant to be a generic repositioning function.  If you do
-+ * things that aren't supported, then we return EINVAL.
-+ *
-+ * What is allowed:
-+ *  (1) seeking to the same position that you are currently at
-+ *    This really has no effect, but returns where you are.
-+ *  (2) seeking to the beginning of the file
-+ *    This throws out all state, and lets you begin again.
-+ */
-+static loff_t unionfs_dir_llseek(struct file *file, loff_t offset, int origin)
-+{
-+      struct unionfs_dir_state *rdstate;
-+      loff_t err;
-+
-+      unionfs_read_lock(file->f_path.dentry->d_sb);
-+
-+      if ((err = unionfs_file_revalidate(file, 0)))
-+              goto out;
-+
-+      rdstate = UNIONFS_F(file)->rdstate;
-+
-+      /*
-+       * we let users seek to their current position, but not anywhere
-+       * else.
-+       */
-+      if (!offset) {
-+              switch (origin) {
-+              case SEEK_SET:
-+                      if (rdstate) {
-+                              free_rdstate(rdstate);
-+                              UNIONFS_F(file)->rdstate = NULL;
+       return;
+ }
+ static int
+-lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+-               struct lpfc_nodelist *ndlp)
++lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++               struct lpfc_nodelist * ndlp)
+ {
+-      struct lpfc_hba *phba = vport->phba;
+       uint32_t *lp;
+       uint8_t flag;
+       LPFC_MBOXQ_t *mbox;
+@@ -3261,8 +2868,7 @@
+               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+               stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
+               stat.un.b.vendorUnique = 0;
+-              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+-                      NULL);
++              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+       }
+       pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
+@@ -3272,24 +2878,19 @@
+       if ((flag == 0) ||
+           ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) ||
+-          ((flag == 2) && (memcmp(&rps->un.portName, &vport->fc_portname,
+-                                  sizeof(struct lpfc_name)) == 0))) {
+-
+-              printk("Fix me....\n");
+-              dump_stack();
+-              mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC);
+-              if (mbox) {
++          ((flag == 2) && (memcmp(&rps->un.portName, &phba->fc_portname,
++                         sizeof (struct lpfc_name)) == 0))) {
++              if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC))) {
+                       lpfc_read_lnk_stat(phba, mbox);
+                       mbox->context1 =
+-                          (void *)((unsigned long) cmdiocb->iocb.ulpContext);
++                          (void *)((unsigned long)cmdiocb->iocb.ulpContext);
+                       mbox->context2 = lpfc_nlp_get(ndlp);
+-                      mbox->vport = vport;
+                       mbox->mbox_cmpl = lpfc_els_rsp_rps_acc;
+                       if (lpfc_sli_issue_mbox (phba, mbox,
+-                          (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED)
++                          (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) {
+                               /* Mbox completion will send ELS Response */
+                               return 0;
+-
 +                      }
-+                      init_rdstate(file);
-+                      err = 0;
-+                      break;
-+              case SEEK_CUR:
-+                      err = file->f_pos;
-+                      break;
-+              case SEEK_END:
-+                      /* Unsupported, because we would break everything.  */
-+                      err = -EINVAL;
-+                      break;
+                       lpfc_nlp_put(ndlp);
+                       mempool_free(mbox, phba->mbox_mem_pool);
+               }
+@@ -3298,25 +2899,27 @@
+       stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+       stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
+       stat.un.b.vendorUnique = 0;
+-      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
++      lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+       return 0;
+ }
+ static int
+-lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
+-                   struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
++lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize,
++               struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
+ {
+-      struct lpfc_hba *phba = vport->phba;
+-      IOCB_t *icmd, *oldcmd;
++      IOCB_t *icmd;
++      IOCB_t *oldcmd;
+       RPL_RSP rpl_rsp;
+       struct lpfc_iocbq *elsiocb;
+-      struct lpfc_sli *psli = &phba->sli;
+-      struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
++      struct lpfc_sli_ring *pring;
++      struct lpfc_sli *psli;
+       uint8_t *pcmd;
+-      elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
+-                                   ndlp->nlp_DID, ELS_CMD_ACC);
++      psli = &phba->sli;
++      pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
++      elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
++                                      ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
+       if (!elsiocb)
+               return 1;
+@@ -3326,7 +2929,7 @@
+       pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+       *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
+-      pcmd += sizeof(uint16_t);
++      pcmd += sizeof (uint16_t);
+       *((uint16_t *)(pcmd)) = be16_to_cpu(cmdsize);
+       pcmd += sizeof(uint16_t);
+@@ -3334,8 +2937,8 @@
+       rpl_rsp.listLen = be32_to_cpu(1);
+       rpl_rsp.index = 0;
+       rpl_rsp.port_num_blk.portNum = 0;
+-      rpl_rsp.port_num_blk.portID = be32_to_cpu(vport->fc_myDID);
+-      memcpy(&rpl_rsp.port_num_blk.portName, &vport->fc_portname,
++      rpl_rsp.port_num_blk.portID = be32_to_cpu(phba->fc_myDID);
++      memcpy(&rpl_rsp.port_num_blk.portName, &phba->fc_portname,
+           sizeof(struct lpfc_name));
+       memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t));
+@@ -3343,14 +2946,13 @@
+       /* Xmit ELS RPL ACC response tag <ulpIoTag> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0120 Xmit ELS RPL ACC response tag x%x "
+-                      "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
+-                      "rpi x%x\n",
+-                      phba->brd_no, vport->vpi, elsiocb->iotag,
++                      "%d:0120 Xmit ELS RPL ACC response tag x%x xri x%x, "
++                      "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
++                      phba->brd_no, elsiocb->iotag,
+                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
+                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
+-      elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++      elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+       phba->fc_stat.elsXmitACC++;
+       if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+@@ -3361,8 +2963,8 @@
+ }
+ static int
+-lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+-               struct lpfc_nodelist *ndlp)
++lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++               struct lpfc_nodelist * ndlp)
+ {
+       struct lpfc_dmabuf *pcmd;
+       uint32_t *lp;
+@@ -3377,8 +2979,7 @@
+               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+               stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
+               stat.un.b.vendorUnique = 0;
+-              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+-                      NULL);
++              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+       }
+       pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
+@@ -3395,16 +2996,15 @@
+       } else {
+               cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t);
+       }
+-      lpfc_els_rsp_rpl_acc(vport, cmdsize, cmdiocb, ndlp);
++      lpfc_els_rsp_rpl_acc(phba, cmdsize, cmdiocb, ndlp);
+       return 0;
+ }
+ static int
+-lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+-                struct lpfc_nodelist *ndlp)
++lpfc_els_rcv_farp(struct lpfc_hba * phba,
++                struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
+ {
+-      struct lpfc_hba *phba = vport->phba;
+       struct lpfc_dmabuf *pcmd;
+       uint32_t *lp;
+       IOCB_t *icmd;
+@@ -3420,9 +3020,11 @@
+       fp = (FARP *) lp;
+       /* FARP-REQ received from DID <did> */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0601 FARP-REQ received from DID x%x\n",
+-                      phba->brd_no, vport->vpi, did);
++      lpfc_printf_log(phba,
++                       KERN_INFO,
++                       LOG_ELS,
++                       "%d:0601 FARP-REQ received from DID x%x\n",
++                       phba->brd_no, did);
+       /* We will only support match on WWPN or WWNN */
+       if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) {
+@@ -3432,15 +3034,15 @@
+       cnt = 0;
+       /* If this FARP command is searching for my portname */
+       if (fp->Mflags & FARP_MATCH_PORT) {
+-              if (memcmp(&fp->RportName, &vport->fc_portname,
+-                         sizeof(struct lpfc_name)) == 0)
++              if (memcmp(&fp->RportName, &phba->fc_portname,
++                         sizeof (struct lpfc_name)) == 0)
+                       cnt = 1;
+       }
+       /* If this FARP command is searching for my nodename */
+       if (fp->Mflags & FARP_MATCH_NODE) {
+-              if (memcmp(&fp->RnodeName, &vport->fc_nodename,
+-                         sizeof(struct lpfc_name)) == 0)
++              if (memcmp(&fp->RnodeName, &phba->fc_nodename,
++                         sizeof (struct lpfc_name)) == 0)
+                       cnt = 1;
+       }
+@@ -3450,28 +3052,28 @@
+                       /* Log back into the node before sending the FARP. */
+                       if (fp->Rflags & FARP_REQUEST_PLOGI) {
+                               ndlp->nlp_prev_state = ndlp->nlp_state;
+-                              lpfc_nlp_set_state(vport, ndlp,
++                              lpfc_nlp_set_state(phba, ndlp,
+                                                  NLP_STE_PLOGI_ISSUE);
+-                              lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
++                              lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+                       }
+                       /* Send a FARP response to that node */
+-                      if (fp->Rflags & FARP_REQUEST_FARPR)
+-                              lpfc_issue_els_farpr(vport, did, 0);
++                      if (fp->Rflags & FARP_REQUEST_FARPR) {
++                              lpfc_issue_els_farpr(phba, did, 0);
++                      }
+               }
+       }
+       return 0;
+ }
+ static int
+-lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+-                 struct lpfc_nodelist  *ndlp)
++lpfc_els_rcv_farpr(struct lpfc_hba * phba,
++                 struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
+ {
+       struct lpfc_dmabuf *pcmd;
+       uint32_t *lp;
+       IOCB_t *icmd;
+       uint32_t cmd, did;
+-      struct lpfc_hba *phba = vport->phba;
+       icmd = &cmdiocb->iocb;
+       did = icmd->un.elsreq64.remoteID;
+@@ -3480,18 +3082,21 @@
+       cmd = *lp++;
+       /* FARP-RSP received from DID <did> */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0600 FARP-RSP received from DID x%x\n",
+-                      phba->brd_no, vport->vpi, did);
++      lpfc_printf_log(phba,
++                       KERN_INFO,
++                       LOG_ELS,
++                       "%d:0600 FARP-RSP received from DID x%x\n",
++                       phba->brd_no, did);
++
+       /* ACCEPT the Farp resp request */
+-      lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
++      lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+       return 0;
+ }
+ static int
+-lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+-               struct lpfc_nodelist *fan_ndlp)
++lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++               struct lpfc_nodelist * fan_ndlp)
+ {
+       struct lpfc_dmabuf *pcmd;
+       uint32_t *lp;
+@@ -3499,12 +3104,10 @@
+       uint32_t cmd, did;
+       FAN *fp;
+       struct lpfc_nodelist *ndlp, *next_ndlp;
+-      struct lpfc_hba *phba = vport->phba;
+       /* FAN received */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0265 FAN received\n",
+-                      phba->brd_no, vport->vpi);
++      lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n",
++                                                              phba->brd_no);
+       icmd = &cmdiocb->iocb;
+       did = icmd->un.elsreq64.remoteID;
+@@ -3512,11 +3115,11 @@
+       lp = (uint32_t *)pcmd->virt;
+       cmd = *lp++;
+-      fp = (FAN *) lp;
++      fp = (FAN *)lp;
+       /* FAN received; Fan does not have a reply sequence */
+-      if (phba->pport->port_state == LPFC_LOCAL_CFG_LINK) {
++      if (phba->hba_state == LPFC_LOCAL_CFG_LINK) {
+               if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName,
+                       sizeof(struct lpfc_name)) != 0) ||
+                   (memcmp(&phba->fc_fabparam.portName, &fp->FportName,
+@@ -3527,7 +3130,7 @@
+                        */
+                       list_for_each_entry_safe(ndlp, next_ndlp,
+-                                               &vport->fc_nodes, nlp_listp) {
++                                               &phba->fc_nodes, nlp_listp) {
+                               if (ndlp->nlp_state != NLP_STE_NPR_NODE)
+                                       continue;
+                               if (ndlp->nlp_type & NLP_FABRIC) {
+@@ -3535,24 +3138,24 @@
+                                        * Clean up old Fabric, Nameserver and
+                                        * other NLP_FABRIC logins
+                                        */
+-                                      lpfc_drop_node(vport, ndlp);
++                                      lpfc_drop_node(phba, ndlp);
+                               } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
+                                       /* Fail outstanding I/O now since this
+                                        * device is marked for PLOGI
+                                        */
+-                                      lpfc_unreg_rpi(vport, ndlp);
++                                      lpfc_unreg_rpi(phba, ndlp);
+                               }
+                       }
+-                      vport->port_state = LPFC_FLOGI;
+-                      lpfc_set_disctmo(vport);
+-                      lpfc_initial_flogi(vport);
++                      phba->hba_state = LPFC_FLOGI;
++                      lpfc_set_disctmo(phba);
++                      lpfc_initial_flogi(phba);
+                       return 0;
+               }
+               /* Discovery not needed,
+                * move the nodes to their original state.
+                */
+-              list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
++              list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+                                        nlp_listp) {
+                       if (ndlp->nlp_state != NLP_STE_NPR_NODE)
+                               continue;
+@@ -3560,13 +3163,13 @@
+                       switch (ndlp->nlp_prev_state) {
+                       case NLP_STE_UNMAPPED_NODE:
+                               ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
+-                              lpfc_nlp_set_state(vport, ndlp,
++                              lpfc_nlp_set_state(phba, ndlp,
+                                                  NLP_STE_UNMAPPED_NODE);
+                               break;
+                       case NLP_STE_MAPPED_NODE:
+                               ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
+-                              lpfc_nlp_set_state(vport, ndlp,
++                              lpfc_nlp_set_state(phba, ndlp,
+                                                  NLP_STE_MAPPED_NODE);
+                               break;
+@@ -3576,7 +3179,7 @@
+               }
+               /* Start discovery - this should just do CLEAR_LA */
+-              lpfc_disc_start(vport);
++              lpfc_disc_start(phba);
+       }
+       return 0;
+ }
+@@ -3584,42 +3187,42 @@
+ void
+ lpfc_els_timeout(unsigned long ptr)
+ {
+-      struct lpfc_vport *vport = (struct lpfc_vport *) ptr;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba;
+       unsigned long iflag;
+-      spin_lock_irqsave(&vport->work_port_lock, iflag);
+-      if ((vport->work_port_events & WORKER_ELS_TMO) == 0) {
+-              vport->work_port_events |= WORKER_ELS_TMO;
+-              spin_unlock_irqrestore(&vport->work_port_lock, iflag);
+-
+-              spin_lock_irqsave(&phba->hbalock, iflag);
++      phba = (struct lpfc_hba *)ptr;
++      if (phba == 0)
++              return;
++      spin_lock_irqsave(phba->host->host_lock, iflag);
++      if (!(phba->work_hba_events & WORKER_ELS_TMO)) {
++              phba->work_hba_events |= WORKER_ELS_TMO;
+               if (phba->work_wait)
+-                      lpfc_worker_wake_up(phba);
+-              spin_unlock_irqrestore(&phba->hbalock, iflag);
++                      wake_up(phba->work_wait);
+       }
+-      else
+-              spin_unlock_irqrestore(&vport->work_port_lock, iflag);
++      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+       return;
+ }
+ void
+-lpfc_els_timeout_handler(struct lpfc_vport *vport)
++lpfc_els_timeout_handler(struct lpfc_hba *phba)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+       struct lpfc_sli_ring *pring;
+       struct lpfc_iocbq *tmp_iocb, *piocb;
+       IOCB_t *cmd = NULL;
+       struct lpfc_dmabuf *pcmd;
+-      uint32_t els_command = 0;
++      uint32_t *elscmd;
++      uint32_t els_command=0;
+       uint32_t timeout;
+-      uint32_t remote_ID = 0xffffffff;
++      uint32_t remote_ID;
++      if (phba == 0)
++              return;
++      spin_lock_irq(phba->host->host_lock);
+       /* If the timer is already canceled do nothing */
+-      if ((vport->work_port_events & WORKER_ELS_TMO) == 0) {
++      if (!(phba->work_hba_events & WORKER_ELS_TMO)) {
++              spin_unlock_irq(phba->host->host_lock);
+               return;
+       }
+-      spin_lock_irq(&phba->hbalock);
+       timeout = (uint32_t)(phba->fc_ratov << 1);
+       pring = &phba->sli.ring[LPFC_ELS_RING];
+@@ -3627,70 +3230,63 @@
+       list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
+               cmd = &piocb->iocb;
+-              if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 ||
+-                  piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
+-                  piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
++              if ((piocb->iocb_flag & LPFC_IO_LIBDFC) ||
++                      (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN) ||
++                      (piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)) {
+                       continue;
+-
+-              if (piocb->vport != vport)
+-                      continue;
+-
 +              }
-+      } else {
-+              switch (origin) {
-+              case SEEK_SET:
-+                      if (rdstate) {
-+                              if (offset == rdstate2offset(rdstate))
-+                                      err = offset;
-+                              else if (file->f_pos == DIREOF)
-+                                      err = DIREOF;
-+                              else
-+                                      err = -EINVAL;
-+                      } else {
-+                              rdstate = find_rdstate(file->f_dentry->d_inode,
-+                                                     offset);
-+                              if (rdstate) {
-+                                      UNIONFS_F(file)->rdstate = rdstate;
-+                                      err = rdstate->offset;
-+                              } else
-+                                      err = -EINVAL;
-+                      }
-+                      break;
-+              case SEEK_CUR:
-+              case SEEK_END:
-+                      /* Unsupported, because we would break everything.  */
-+                      err = -EINVAL;
-+                      break;
+               pcmd = (struct lpfc_dmabuf *) piocb->context2;
+-              if (pcmd)
+-                      els_command = *(uint32_t *) (pcmd->virt);
+-
+-              if (els_command == ELS_CMD_FARP ||
+-                  els_command == ELS_CMD_FARPR ||
+-                  els_command == ELS_CMD_FDISC)
+-                      continue;
++              if (pcmd) {
++                      elscmd = (uint32_t *) (pcmd->virt);
++                      els_command = *elscmd;
 +              }
-+      }
-+
-+out:
-+      unionfs_read_unlock(file->f_path.dentry->d_sb);
-+      return err;
-+}
-+
-+/*
-+ * Trimmed directory options, we shouldn't pass everything down since
-+ * we don't want to operate on partial directories.
-+ */
-+struct file_operations unionfs_dir_fops = {
-+      .llseek         = unionfs_dir_llseek,
-+      .read           = generic_read_dir,
-+      .readdir        = unionfs_readdir,
-+      .unlocked_ioctl = unionfs_ioctl,
-+      .open           = unionfs_open,
-+      .release        = unionfs_file_release,
-+      .flush          = unionfs_flush,
-+};
-diff -Nurb linux-2.6.22-570/fs/unionfs/dirhelper.c linux-2.6.22-590/fs/unionfs/dirhelper.c
---- linux-2.6.22-570/fs/unionfs/dirhelper.c    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/dirhelper.c    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,273 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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 "union.h"
-+
-+/*
-+ * Delete all of the whiteouts in a given directory for rmdir.
-+ *
-+ * hidden directory inode should be locked
-+ */
-+int do_delete_whiteouts(struct dentry *dentry, int bindex,
-+                      struct unionfs_dir_state *namelist)
-+{
-+      int err = 0;
-+      struct dentry *hidden_dir_dentry = NULL;
-+      struct dentry *hidden_dentry;
-+      char *name = NULL, *p;
-+      struct inode *hidden_dir;
-+
-+      int i;
-+      struct list_head *pos;
-+      struct filldir_node *cursor;
-+
-+      /* Find out hidden parent dentry */
-+      hidden_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+      BUG_ON(!S_ISDIR(hidden_dir_dentry->d_inode->i_mode));
-+      hidden_dir = hidden_dir_dentry->d_inode;
-+      BUG_ON(!S_ISDIR(hidden_dir->i_mode));
-+
-+      err = -ENOMEM;
-+      name = __getname();
-+      if (!name)
-+              goto out;
-+      strcpy(name, UNIONFS_WHPFX);
-+      p = name + UNIONFS_WHLEN;
-+
-+      err = 0;
-+      for (i = 0; !err && i < namelist->size; i++) {
-+              list_for_each(pos, &namelist->list[i]) {
-+                      cursor =
-+                              list_entry(pos, struct filldir_node,
-+                                         file_list);
-+                      /* Only operate on whiteouts in this branch. */
-+                      if (cursor->bindex != bindex)
-+                              continue;
-+                      if (!cursor->whiteout)
-+                              continue;
-+
-+                      strcpy(p, cursor->name);
-+                      hidden_dentry =
-+                              lookup_one_len(name, hidden_dir_dentry,
-+                                             cursor->namelen +
-+                                             UNIONFS_WHLEN);
-+                      if (IS_ERR(hidden_dentry)) {
-+                              err = PTR_ERR(hidden_dentry);
-+                              break;
-+                      }
-+                      if (hidden_dentry->d_inode)
-+                              err = vfs_unlink(hidden_dir, hidden_dentry);
-+                      dput(hidden_dentry);
-+                      if (err)
-+                              break;
+-              if (vport != piocb->vport)
++              if ((els_command == ELS_CMD_FARP)
++                  || (els_command == ELS_CMD_FARPR)) {
+                       continue;
 +              }
-+      }
-+
-+      __putname(name);
-+
-+      /* After all of the removals, we should copy the attributes once. */
-+      fsstack_copy_attr_times(dentry->d_inode, hidden_dir_dentry->d_inode);
-+
-+out:
-+      return err;
-+}
-+
-+/* delete whiteouts in a dir (for rmdir operation) using sioq if necessary */
-+int delete_whiteouts(struct dentry *dentry, int bindex,
-+                   struct unionfs_dir_state *namelist)
-+{
-+      int err;
-+      struct super_block *sb;
-+      struct dentry *hidden_dir_dentry;
-+      struct inode *hidden_dir;
-+
-+      struct sioq_args args;
-+
-+      sb = dentry->d_sb;
-+
-+      BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
-+      BUG_ON(bindex < dbstart(dentry));
-+      BUG_ON(bindex > dbend(dentry));
-+      err = is_robranch_super(sb, bindex);
-+      if (err)
-+              goto out;
-+
-+      hidden_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+      BUG_ON(!S_ISDIR(hidden_dir_dentry->d_inode->i_mode));
-+      hidden_dir = hidden_dir_dentry->d_inode;
-+      BUG_ON(!S_ISDIR(hidden_dir->i_mode));
-+
-+      mutex_lock(&hidden_dir->i_mutex);
-+      if (!permission(hidden_dir, MAY_WRITE | MAY_EXEC, NULL))
-+              err = do_delete_whiteouts(dentry, bindex, namelist);
-+      else {
-+              args.deletewh.namelist = namelist;
-+              args.deletewh.dentry = dentry;
-+              args.deletewh.bindex = bindex;
-+              run_sioq(__delete_whiteouts, &args);
-+              err = args.err;
-+      }
-+      mutex_unlock(&hidden_dir->i_mutex);
-+
-+out:
-+      return err;
-+}
+               if (piocb->drvrTimeout > 0) {
+-                      if (piocb->drvrTimeout >= timeout)
++                      if (piocb->drvrTimeout >= timeout) {
+                               piocb->drvrTimeout -= timeout;
+-                      else
++                      } else {
+                               piocb->drvrTimeout = 0;
++                      }
+                       continue;
+               }
+-              remote_ID = 0xffffffff;
+-              if (cmd->ulpCommand != CMD_GEN_REQUEST64_CR)
+-                      remote_ID = cmd->un.elsreq64.remoteID;
+-              else {
++              if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) {
+                       struct lpfc_nodelist *ndlp;
+-                      ndlp = __lpfc_findnode_rpi(vport, cmd->ulpContext);
+-                      if (ndlp)
++                      ndlp = __lpfc_findnode_rpi(phba, cmd->ulpContext);
+                       remote_ID = ndlp->nlp_DID;
++              } else {
++                      remote_ID = cmd->un.elsreq64.remoteID;
+               }
+-              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                              "%d (%d):0127 ELS timeout Data: x%x x%x x%x "
+-                              "x%x\n",
+-                              phba->brd_no, vport->vpi, els_command,
++              lpfc_printf_log(phba,
++                              KERN_ERR,
++                              LOG_ELS,
++                              "%d:0127 ELS timeout Data: x%x x%x x%x x%x\n",
++                              phba->brd_no, els_command,
+                               remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
+               lpfc_sli_issue_abort_iotag(phba, pring, piocb);
+       }
+-      spin_unlock_irq(&phba->hbalock);
+-
+       if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
+-              mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
++              mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
 +
-+#define RD_NONE 0
-+#define RD_CHECK_EMPTY 1
-+/* The callback structure for check_empty. */
-+struct unionfs_rdutil_callback {
-+      int err;
-+      int filldir_called;
-+      struct unionfs_dir_state *rdstate;
-+      int mode;
-+};
++      spin_unlock_irq(phba->host->host_lock);
+ }
+ void
+-lpfc_els_flush_cmd(struct lpfc_vport *vport)
++lpfc_els_flush_cmd(struct lpfc_hba *phba)
+ {
+       LIST_HEAD(completions);
+-      struct lpfc_hba  *phba = vport->phba;
+       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+       struct lpfc_iocbq *tmp_iocb, *piocb;
+       IOCB_t *cmd = NULL;
+-      lpfc_fabric_abort_vport(vport);
+-
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
+               cmd = &piocb->iocb;
+@@ -3705,1042 +3301,271 @@
+                   cmd->ulpCommand == CMD_ABORT_XRI_CN)
+                       continue;
+-              if (piocb->vport != vport)
+-                      continue;
+-
+               list_move_tail(&piocb->list, &completions);
+               pring->txq_cnt--;
 +
-+/* This filldir function makes sure only whiteouts exist within a directory. */
-+static int readdir_util_callback(void *dirent, const char *name, int namelen,
-+                               loff_t offset, u64 ino, unsigned int d_type)
-+{
-+      int err = 0;
-+      struct unionfs_rdutil_callback *buf = dirent;
-+      int whiteout = 0;
-+      struct filldir_node *found;
+       }
+       list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
++              cmd = &piocb->iocb;
 +
-+      buf->filldir_called = 1;
+               if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
+                       continue;
+               }
+-              if (piocb->vport != vport)
+-                      continue;
+-
+               lpfc_sli_issue_abort_iotag(phba, pring, piocb);
+       }
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+-      while (!list_empty(&completions)) {
++      while(!list_empty(&completions)) {
+               piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+               cmd = &piocb->iocb;
+-              list_del_init(&piocb->list);
++              list_del(&piocb->list);
+-              if (!piocb->iocb_cmpl)
+-                      lpfc_sli_release_iocbq(phba, piocb);
+-              else {
++              if (piocb->iocb_cmpl) {
+                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                       cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+                       (piocb->iocb_cmpl) (phba, piocb, piocb);
+-              }
++              } else
++                      lpfc_sli_release_iocbq(phba, piocb);
+       }
+       return;
+ }
+-static void
+-lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+-                    struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb)
++void
++lpfc_els_unsol_event(struct lpfc_hba * phba,
++                   struct lpfc_sli_ring * pring, struct lpfc_iocbq * elsiocb)
+ {
++      struct lpfc_sli *psli;
+       struct lpfc_nodelist *ndlp;
++      struct lpfc_dmabuf *mp;
++      uint32_t *lp;
++      IOCB_t *icmd;
+       struct ls_rjt stat;
+-      uint32_t *payload;
+-      uint32_t cmd, did, newnode, rjt_err = 0;
+-      IOCB_t *icmd = &elsiocb->iocb;
++      uint32_t cmd;
++      uint32_t did;
++      uint32_t newnode;
++      uint32_t drop_cmd = 0;  /* by default do NOT drop received cmd */
++      uint32_t rjt_err = 0;
 +
-+      if (name[0] == '.' && (namelen == 1 ||
-+                             (name[1] == '.' && namelen == 2)))
-+              goto out;
++      psli = &phba->sli;
++      icmd = &elsiocb->iocb;
 +
-+      if (namelen > UNIONFS_WHLEN &&
-+          !strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN)) {
-+              namelen -= UNIONFS_WHLEN;
-+              name += UNIONFS_WHLEN;
-+              whiteout = 1;
++      if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
++              ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) {
++              /* Not enough posted buffers; Try posting more buffers */
++              phba->fc_stat.NoRcvBuf++;
++              lpfc_post_buffer(phba, pring, 0, 1);
++              return;
 +      }
 +
-+      found = find_filldir_node(buf->rdstate, name, namelen);
-+      /* If it was found in the table there was a previous whiteout. */
-+      if (found)
-+              goto out;
-+
-+      /*
-+       * if it wasn't found and isn't a whiteout, the directory isn't
-+       * empty.
++      /* If there are no BDEs associated with this IOCB,
++       * there is nothing to do.
 +       */
-+      err = -ENOTEMPTY;
-+      if ((buf->mode == RD_CHECK_EMPTY) && !whiteout)
-+              goto out;
-+
-+      err = add_filldir_node(buf->rdstate, name, namelen,
-+                             buf->rdstate->bindex, whiteout);
-+
-+out:
-+      buf->err = err;
-+      return err;
-+}
-+
-+/* Is a directory logically empty? */
-+int check_empty(struct dentry *dentry, struct unionfs_dir_state **namelist)
-+{
-+      int err = 0;
-+      struct dentry *hidden_dentry = NULL;
-+      struct super_block *sb;
-+      struct file *hidden_file;
-+      struct unionfs_rdutil_callback *buf = NULL;
-+      int bindex, bstart, bend, bopaque;
-+
-+      sb = dentry->d_sb;
-+
-+
-+      BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
-+
-+      if ((err = unionfs_partial_lookup(dentry)))
-+              goto out;
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+      bopaque = dbopaque(dentry);
-+      if (0 <= bopaque && bopaque < bend)
-+              bend = bopaque;
-+
-+      buf = kmalloc(sizeof(struct unionfs_rdutil_callback), GFP_KERNEL);
-+      if (!buf) {
-+              err = -ENOMEM;
-+              goto out;
++      if (icmd->ulpBdeCount == 0)
++              return;
+-      if (vport == NULL || elsiocb->context2 == NULL)
++      /* type of ELS cmd is first 32bit word in packet */
++      mp = lpfc_sli_ringpostbuf_get(phba, pring, getPaddr(icmd->un.
++                                                          cont64[0].
++                                                          addrHigh,
++                                                          icmd->un.
++                                                          cont64[0].addrLow));
++      if (mp == 0) {
++              drop_cmd = 1;
+               goto dropit;
 +      }
-+      buf->err = 0;
-+      buf->mode = RD_CHECK_EMPTY;
-+      buf->rdstate = alloc_rdstate(dentry->d_inode, bstart);
-+      if (!buf->rdstate) {
-+              err = -ENOMEM;
-+              goto out;
+       newnode = 0;
+-      payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt;
+-      cmd = *payload;
+-      if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0)
+-              lpfc_post_buffer(phba, pring, 1, 1);
++      lp = (uint32_t *) mp->virt;
++      cmd = *lp++;
++      lpfc_post_buffer(phba, &psli->ring[LPFC_ELS_RING], 1, 1);
+-      did = icmd->un.rcvels.remoteID;
+       if (icmd->ulpStatus) {
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV Unsol ELS:  status:x%x/x%x did:x%x",
+-                      icmd->ulpStatus, icmd->un.ulpWord[4], did);
++              lpfc_mbuf_free(phba, mp->virt, mp->phys);
++              kfree(mp);
++              drop_cmd = 1;
+               goto dropit;
+       }
+       /* Check to see if link went down during discovery */
+-      if (lpfc_els_chk_latt(vport))
++      if (lpfc_els_chk_latt(phba)) {
++              lpfc_mbuf_free(phba, mp->virt, mp->phys);
++              kfree(mp);
++              drop_cmd = 1;
+               goto dropit;
 +      }
-+
-+      /* Process the hidden directories with rdutil_callback as a filldir. */
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!hidden_dentry)
-+                      continue;
-+              if (!hidden_dentry->d_inode)
-+                      continue;
-+              if (!S_ISDIR(hidden_dentry->d_inode->i_mode))
-+                      continue;
-+
-+              dget(hidden_dentry);
-+              unionfs_mntget(dentry, bindex);
-+              branchget(sb, bindex);
-+              hidden_file =
-+                      dentry_open(hidden_dentry,
-+                                  unionfs_lower_mnt_idx(dentry, bindex),
-+                                  O_RDONLY);
-+              if (IS_ERR(hidden_file)) {
-+                      err = PTR_ERR(hidden_file);
-+                      dput(hidden_dentry);
-+                      branchput(sb, bindex);
-+                      goto out;
+-      /* Ignore traffic recevied during vport shutdown. */
+-      if (vport->load_flag & FC_UNLOADING)
+-              goto dropit;
+-
+-      ndlp = lpfc_findnode_did(vport, did);
++      did = icmd->un.rcvels.remoteID;
++      ndlp = lpfc_findnode_did(phba, did);
+       if (!ndlp) {
+               /* Cannot find existing Fabric ndlp, so allocate a new one */
+               ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+-              if (!ndlp)
++              if (!ndlp) {
++                      lpfc_mbuf_free(phba, mp->virt, mp->phys);
++                      kfree(mp);
++                      drop_cmd = 1;
+                       goto dropit;
 +              }
+-              lpfc_nlp_init(vport, ndlp, did);
++              lpfc_nlp_init(phba, ndlp, did);
+               newnode = 1;
+               if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
+                       ndlp->nlp_type |= NLP_FABRIC;
+               }
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
+       }
+       phba->fc_stat.elsRcvFrame++;
+       if (elsiocb->context1)
+               lpfc_nlp_put(elsiocb->context1);
+       elsiocb->context1 = lpfc_nlp_get(ndlp);
+-      elsiocb->vport = vport;
++      elsiocb->context2 = mp;
+       if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) {
+               cmd &= ELS_CMD_MASK;
+       }
+       /* ELS command <elsCmd> received from NPORT <did> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0112 ELS command x%x received from NPORT x%x "
+-                      "Data: x%x\n", phba->brd_no, vport->vpi, cmd, did,
+-                      vport->port_state);
++                      "%d:0112 ELS command x%x received from NPORT x%x "
++                      "Data: x%x\n", phba->brd_no, cmd, did, phba->hba_state);
+       switch (cmd) {
+       case ELS_CMD_PLOGI:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV PLOGI:       did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvPLOGI++;
+-              ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
+-
+-              if (vport->port_state < LPFC_DISC_AUTH) {
+-                      rjt_err = LSRJT_UNABLE_TPC;
++              if (phba->hba_state < LPFC_DISC_AUTH) {
++                      rjt_err = 1;
+                       break;
+               }
+-              lpfc_disc_state_machine(vport, ndlp, elsiocb,
+-                                      NLP_EVT_RCV_PLOGI);
+-
++              ndlp = lpfc_plogi_confirm_nport(phba, mp, ndlp);
++              lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI);
+               break;
+       case ELS_CMD_FLOGI:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV FLOGI:       did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvFLOGI++;
+-              lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode);
++              lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode);
+               if (newnode)
+-                      lpfc_drop_node(vport, ndlp);
++                      lpfc_drop_node(phba, ndlp);
+               break;
+       case ELS_CMD_LOGO:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV LOGO:        did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvLOGO++;
+-              if (vport->port_state < LPFC_DISC_AUTH) {
+-                      rjt_err = LSRJT_UNABLE_TPC;
++              if (phba->hba_state < LPFC_DISC_AUTH) {
++                      rjt_err = 1;
+                       break;
+               }
+-              lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
++              lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
+               break;
+       case ELS_CMD_PRLO:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV PRLO:        did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvPRLO++;
+-              if (vport->port_state < LPFC_DISC_AUTH) {
+-                      rjt_err = LSRJT_UNABLE_TPC;
++              if (phba->hba_state < LPFC_DISC_AUTH) {
++                      rjt_err = 1;
+                       break;
+               }
+-              lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
++              lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
+               break;
+       case ELS_CMD_RSCN:
+               phba->fc_stat.elsRcvRSCN++;
+-              lpfc_els_rcv_rscn(vport, elsiocb, ndlp, newnode);
++              lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode);
+               if (newnode)
+-                      lpfc_drop_node(vport, ndlp);
++                      lpfc_drop_node(phba, ndlp);
+               break;
+       case ELS_CMD_ADISC:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV ADISC:       did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvADISC++;
+-              if (vport->port_state < LPFC_DISC_AUTH) {
+-                      rjt_err = LSRJT_UNABLE_TPC;
++              if (phba->hba_state < LPFC_DISC_AUTH) {
++                      rjt_err = 1;
+                       break;
+               }
+-              lpfc_disc_state_machine(vport, ndlp, elsiocb,
+-                                      NLP_EVT_RCV_ADISC);
++              lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_ADISC);
+               break;
+       case ELS_CMD_PDISC:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV PDISC:       did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvPDISC++;
+-              if (vport->port_state < LPFC_DISC_AUTH) {
+-                      rjt_err = LSRJT_UNABLE_TPC;
++              if (phba->hba_state < LPFC_DISC_AUTH) {
++                      rjt_err = 1;
+                       break;
+               }
+-              lpfc_disc_state_machine(vport, ndlp, elsiocb,
+-                                      NLP_EVT_RCV_PDISC);
++              lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PDISC);
+               break;
+       case ELS_CMD_FARPR:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV FARPR:       did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvFARPR++;
+-              lpfc_els_rcv_farpr(vport, elsiocb, ndlp);
++              lpfc_els_rcv_farpr(phba, elsiocb, ndlp);
+               break;
+       case ELS_CMD_FARP:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV FARP:        did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvFARP++;
+-              lpfc_els_rcv_farp(vport, elsiocb, ndlp);
++              lpfc_els_rcv_farp(phba, elsiocb, ndlp);
+               break;
+       case ELS_CMD_FAN:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV FAN:         did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvFAN++;
+-              lpfc_els_rcv_fan(vport, elsiocb, ndlp);
++              lpfc_els_rcv_fan(phba, elsiocb, ndlp);
+               break;
+       case ELS_CMD_PRLI:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV PRLI:        did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvPRLI++;
+-              if (vport->port_state < LPFC_DISC_AUTH) {
+-                      rjt_err = LSRJT_UNABLE_TPC;
++              if (phba->hba_state < LPFC_DISC_AUTH) {
++                      rjt_err = 1;
+                       break;
+               }
+-              lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
++              lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
+               break;
+       case ELS_CMD_LIRR:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV LIRR:        did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvLIRR++;
+-              lpfc_els_rcv_lirr(vport, elsiocb, ndlp);
++              lpfc_els_rcv_lirr(phba, elsiocb, ndlp);
+               if (newnode)
+-                      lpfc_drop_node(vport, ndlp);
++                      lpfc_drop_node(phba, ndlp);
+               break;
+       case ELS_CMD_RPS:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV RPS:         did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvRPS++;
+-              lpfc_els_rcv_rps(vport, elsiocb, ndlp);
++              lpfc_els_rcv_rps(phba, elsiocb, ndlp);
+               if (newnode)
+-                      lpfc_drop_node(vport, ndlp);
++                      lpfc_drop_node(phba, ndlp);
+               break;
+       case ELS_CMD_RPL:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV RPL:         did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvRPL++;
+-              lpfc_els_rcv_rpl(vport, elsiocb, ndlp);
++              lpfc_els_rcv_rpl(phba, elsiocb, ndlp);
+               if (newnode)
+-                      lpfc_drop_node(vport, ndlp);
++                      lpfc_drop_node(phba, ndlp);
+               break;
+       case ELS_CMD_RNID:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV RNID:        did:x%x/ste:x%x flg:x%x",
+-                      did, vport->port_state, ndlp->nlp_flag);
+-
+               phba->fc_stat.elsRcvRNID++;
+-              lpfc_els_rcv_rnid(vport, elsiocb, ndlp);
++              lpfc_els_rcv_rnid(phba, elsiocb, ndlp);
+               if (newnode)
+-                      lpfc_drop_node(vport, ndlp);
++                      lpfc_drop_node(phba, ndlp);
+               break;
+       default:
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+-                      "RCV ELS cmd:     cmd:x%x did:x%x/ste:x%x",
+-                      cmd, did, vport->port_state);
+-
+               /* Unsupported ELS command, reject */
+-              rjt_err = LSRJT_INVALID_CMD;
++              rjt_err = 1;
+               /* Unknown ELS command <elsCmd> received from NPORT <did> */
+               lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                              "%d (%d):0115 Unknown ELS command x%x "
+-                              "received from NPORT x%x\n",
+-                              phba->brd_no, vport->vpi, cmd, did);
++                              "%d:0115 Unknown ELS command x%x received from "
++                              "NPORT x%x\n", phba->brd_no, cmd, did);
+               if (newnode)
+-                      lpfc_drop_node(vport, ndlp);
++                      lpfc_drop_node(phba, ndlp);
+               break;
+       }
+       /* check if need to LS_RJT received ELS cmd */
+       if (rjt_err) {
+-              memset(&stat, 0, sizeof(stat));
+-              stat.un.b.lsRjtRsnCode = rjt_err;
++              stat.un.b.lsRjtRsvd0 = 0;
++              stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+               stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
+-              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp,
+-                      NULL);
+-              if (newnode)
+-                      lpfc_drop_node(vport, ndlp);
+-      }
+-
+-      return;
+-
+-dropit:
+-              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                      "%d (%d):0111 Dropping received ELS cmd "
+-                      "Data: x%x x%x x%x\n",
+-                      phba->brd_no, vport ? vport->vpi : 0xffff,
+-                              icmd->ulpStatus, icmd->un.ulpWord[4],
+-                              icmd->ulpTimeout);
+-              phba->fc_stat.elsRcvDrop++;
+-}
+-
+-static struct lpfc_vport *
+-lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
+-{
+-      struct lpfc_vport *vport;
+-
+-      list_for_each_entry(vport, &phba->port_list, listentry) {
+-              if (vport->vpi == vpi)
+-                      return vport;
+-      }
+-      return NULL;
+-}
+-
+-void
+-lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+-                   struct lpfc_iocbq *elsiocb)
+-{
+-      struct lpfc_vport *vport = phba->pport;
+-      IOCB_t *icmd = &elsiocb->iocb;
+-      dma_addr_t paddr;
+-      struct lpfc_dmabuf *bdeBuf1 = elsiocb->context2;
+-      struct lpfc_dmabuf *bdeBuf2 = elsiocb->context3;
+-
+-      elsiocb->context2 = NULL;
+-      elsiocb->context3 = NULL;
+-
+-      if (icmd->ulpStatus == IOSTAT_NEED_BUFFER) {
+-              lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
+-      } else if (icmd->ulpStatus == IOSTAT_LOCAL_REJECT &&
+-          (icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING) {
+-              phba->fc_stat.NoRcvBuf++;
+-              /* Not enough posted buffers; Try posting more buffers */
+-              if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
+-                      lpfc_post_buffer(phba, pring, 0, 1);
+-              return;
+-      }
+-
+-      if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+-          (icmd->ulpCommand == CMD_IOCB_RCV_ELS64_CX ||
+-           icmd->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
+-              if (icmd->unsli3.rcvsli3.vpi == 0xffff)
+-                      vport = phba->pport;
+-              else {
+-                      uint16_t vpi = icmd->unsli3.rcvsli3.vpi;
+-                      vport = lpfc_find_vport_by_vpid(phba, vpi);
+-              }
+-      }
+-                              /* If there are no BDEs associated
+-                               * with this IOCB, there is nothing to do.
+-                               */
+-      if (icmd->ulpBdeCount == 0)
+-              return;
+-
+-                              /* type of ELS cmd is first 32bit word
+-                               * in packet
+-                               */
+-      if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
+-              elsiocb->context2 = bdeBuf1;
+-      } else {
+-              paddr = getPaddr(icmd->un.cont64[0].addrHigh,
+-                               icmd->un.cont64[0].addrLow);
+-              elsiocb->context2 = lpfc_sli_ringpostbuf_get(phba, pring,
+-                                                           paddr);
++              stat.un.b.vendorUnique = 0;
++              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, elsiocb, ndlp);
+       }
+-      lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
+-      /*
+-       * The different unsolicited event handlers would tell us
+-       * if they are done with "mp" by setting context2 to NULL.
+-       */
+       lpfc_nlp_put(elsiocb->context1);
+       elsiocb->context1 = NULL;
+       if (elsiocb->context2) {
+-              lpfc_in_buf_free(phba, (struct lpfc_dmabuf *)elsiocb->context2);
+-              elsiocb->context2 = NULL;
+-      }
+-
+-      /* RCV_ELS64_CX provide for 2 BDEs - process 2nd if included */
+-      if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) &&
+-          icmd->ulpBdeCount == 2) {
+-              elsiocb->context2 = bdeBuf2;
+-              lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
+-              /* free mp if we are done with it */
+-              if (elsiocb->context2) {
+-                      lpfc_in_buf_free(phba, elsiocb->context2);
+-                      elsiocb->context2 = NULL;
+-              }
+-      }
+-}
+-
+-void
+-lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
+-{
+-      struct lpfc_nodelist *ndlp, *ndlp_fdmi;
+-
+-      ndlp = lpfc_findnode_did(vport, NameServer_DID);
+-      if (!ndlp) {
+-              ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+-              if (!ndlp) {
+-                      if (phba->fc_topology == TOPOLOGY_LOOP) {
+-                              lpfc_disc_start(vport);
+-                              return;
+-                      }
+-                      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                              "%d (%d):0251 NameServer login: no memory\n",
+-                              phba->brd_no, vport->vpi);
+-                      return;
+-              }
+-              lpfc_nlp_init(vport, ndlp, NameServer_DID);
+-              ndlp->nlp_type |= NLP_FABRIC;
+-      }
+-
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+-
+-      if (lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0)) {
+-              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                      "%d (%d):0252 Cannot issue NameServer login\n",
+-                      phba->brd_no, vport->vpi);
+-              return;
+-      }
+-
+-      if (phba->cfg_fdmi_on) {
+-              ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
+-                                        GFP_KERNEL);
+-              if (ndlp_fdmi) {
+-                      lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
+-                      ndlp_fdmi->nlp_type |= NLP_FABRIC;
+-                      ndlp_fdmi->nlp_state =
+-                              NLP_STE_PLOGI_ISSUE;
+-                      lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID,
+-                                           0);
+-              }
+-      }
+-      return;
+-}
+-
+-static void
+-lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+-{
+-      struct lpfc_vport *vport = pmb->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
+-      MAILBOX_t *mb = &pmb->mb;
+-
+-      vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+-      lpfc_nlp_put(ndlp);
+-
+-      if (mb->mbxStatus) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+-                              "%d (%d):0915 Register VPI failed: 0x%x\n",
+-                              phba->brd_no, vport->vpi, mb->mbxStatus);
+-
+-              switch (mb->mbxStatus) {
+-              case 0x11:      /* unsupported feature */
+-              case 0x9603:    /* max_vpi exceeded */
+-                      /* giving up on vport registration */
+-                      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-                      spin_lock_irq(shost->host_lock);
+-                      vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+-                      spin_unlock_irq(shost->host_lock);
+-                      lpfc_can_disctmo(vport);
+-                      break;
+-              default:
+-                      /* Try to recover from this error */
+-                      lpfc_mbx_unreg_vpi(vport);
+-                      vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+-                      lpfc_initial_fdisc(vport);
+-                      break;
+-              }
+-
+-      } else {
+-              if (vport == phba->pport)
+-                      lpfc_issue_fabric_reglogin(vport);
+-              else
+-                      lpfc_do_scr_ns_plogi(phba, vport);
+-      }
+-      mempool_free(pmb, phba->mbox_mem_pool);
+-      return;
+-}
+-
+-void
+-lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
+-                      struct lpfc_nodelist *ndlp)
+-{
+-      LPFC_MBOXQ_t *mbox;
+-
+-      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (mbox) {
+-              lpfc_reg_vpi(phba, vport->vpi, vport->fc_myDID, mbox);
+-              mbox->vport = vport;
+-              mbox->context2 = lpfc_nlp_get(ndlp);
+-              mbox->mbox_cmpl = lpfc_cmpl_reg_new_vport;
+-              if (lpfc_sli_issue_mbox(phba, mbox,
+-                                      MBX_NOWAIT | MBX_STOP_IOCB)
+-                  == MBX_NOT_FINISHED) {
+-                      mempool_free(mbox, phba->mbox_mem_pool);
+-                      vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+-
+-                      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+-                              "%d (%d):0253 Register VPI: Cannot send mbox\n",
+-                              phba->brd_no, vport->vpi);
+-              }
+-      } else {
+-              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-
+-              lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+-                      "%d (%d):0254 Register VPI: no memory\n",
+-                      phba->brd_no, vport->vpi);
+-
+-              vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+-              lpfc_nlp_put(ndlp);
+-      }
+-}
+-
+-static void
+-lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                  struct lpfc_iocbq *rspiocb)
+-{
+-      struct lpfc_vport *vport = cmdiocb->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+-      struct lpfc_nodelist *np;
+-      struct lpfc_nodelist *next_np;
+-      IOCB_t *irsp = &rspiocb->iocb;
+-      struct lpfc_iocbq *piocb;
+-
+-      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-              "%d (%d):0123 FDISC completes. x%x/x%x prevDID: x%x\n",
+-              phba->brd_no, vport->vpi,
+-              irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID);
+-
+-      /* Since all FDISCs are being single threaded, we
+-       * must reset the discovery timer for ALL vports
+-       * waiting to send FDISC when one completes.
+-       */
+-      list_for_each_entry(piocb, &phba->fabric_iocb_list, list) {
+-              lpfc_set_disctmo(piocb->vport);
+-      }
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "FDISC cmpl:      status:x%x/x%x prevdid:x%x",
+-              irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID);
+-
+-      if (irsp->ulpStatus) {
+-              /* Check for retry */
+-              if (lpfc_els_retry(phba, cmdiocb, rspiocb))
+-                      goto out;
+-
+-              /* FDISC failed */
+-              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                      "%d (%d):0124 FDISC failed. (%d/%d)\n",
+-                      phba->brd_no, vport->vpi,
+-                      irsp->ulpStatus, irsp->un.ulpWord[4]);
+-
+-              if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING)
+-                      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-
+-              lpfc_nlp_put(ndlp);
+-              /* giving up on FDISC. Cancel discovery timer */
+-              lpfc_can_disctmo(vport);
+-      } else {
+-              spin_lock_irq(shost->host_lock);
+-              vport->fc_flag |= FC_FABRIC;
+-              if (vport->phba->fc_topology == TOPOLOGY_LOOP)
+-                      vport->fc_flag |=  FC_PUBLIC_LOOP;
+-              spin_unlock_irq(shost->host_lock);
+-
+-              vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
+-              lpfc_vport_set_state(vport, FC_VPORT_ACTIVE);
+-              if ((vport->fc_prevDID != vport->fc_myDID) &&
+-                      !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
+-                      /* If our NportID changed, we need to ensure all
+-                       * remaining NPORTs get unreg_login'ed so we can
+-                       * issue unreg_vpi.
+-                       */
+-                      list_for_each_entry_safe(np, next_np,
+-                              &vport->fc_nodes, nlp_listp) {
+-                              if (np->nlp_state != NLP_STE_NPR_NODE
+-                                 || !(np->nlp_flag & NLP_NPR_ADISC))
+-                                      continue;
+-                              spin_lock_irq(shost->host_lock);
+-                              np->nlp_flag &= ~NLP_NPR_ADISC;
+-                              spin_unlock_irq(shost->host_lock);
+-                              lpfc_unreg_rpi(vport, np);
+-                      }
+-                      lpfc_mbx_unreg_vpi(vport);
+-                      vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+-              }
+-
+-              if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)
+-                      lpfc_register_new_vport(phba, vport, ndlp);
+-              else
+-                      lpfc_do_scr_ns_plogi(phba, vport);
+-
+-              lpfc_nlp_put(ndlp); /* Free Fabric ndlp for vports */
+-      }
+-
+-out:
+-      lpfc_els_free_iocb(phba, cmdiocb);
+-}
+-
+-int
+-lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                   uint8_t retry)
+-{
+-      struct lpfc_hba *phba = vport->phba;
+-      IOCB_t *icmd;
+-      struct lpfc_iocbq *elsiocb;
+-      struct serv_parm *sp;
+-      uint8_t *pcmd;
+-      uint16_t cmdsize;
+-      int did = ndlp->nlp_DID;
+-      int rc;
+-
+-      cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
+-      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
+-                                   ELS_CMD_FDISC);
+-      if (!elsiocb) {
+-              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-
+-              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                      "%d (%d):0255 Issue FDISC: no IOCB\n",
+-                      phba->brd_no, vport->vpi);
+-              return 1;
++              lpfc_mbuf_free(phba, mp->virt, mp->phys);
++              kfree(mp);
+       }
+-
+-      icmd = &elsiocb->iocb;
+-      icmd->un.elsreq64.myID = 0;
+-      icmd->un.elsreq64.fl = 1;
+-
+-      /* For FDISC, Let FDISC rsp set the NPortID for this VPI */
+-      icmd->ulpCt_h = 1;
+-      icmd->ulpCt_l = 0;
+-
+-      pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+-      *((uint32_t *) (pcmd)) = ELS_CMD_FDISC;
+-      pcmd += sizeof(uint32_t); /* CSP Word 1 */
+-      memcpy(pcmd, &vport->phba->pport->fc_sparam, sizeof(struct serv_parm));
+-      sp = (struct serv_parm *) pcmd;
+-      /* Setup CSPs accordingly for Fabric */
+-      sp->cmn.e_d_tov = 0;
+-      sp->cmn.w2.r_a_tov = 0;
+-      sp->cls1.classValid = 0;
+-      sp->cls2.seqDelivery = 1;
+-      sp->cls3.seqDelivery = 1;
+-
+-      pcmd += sizeof(uint32_t); /* CSP Word 2 */
+-      pcmd += sizeof(uint32_t); /* CSP Word 3 */
+-      pcmd += sizeof(uint32_t); /* CSP Word 4 */
+-      pcmd += sizeof(uint32_t); /* Port Name */
+-      memcpy(pcmd, &vport->fc_portname, 8);
+-      pcmd += sizeof(uint32_t); /* Node Name */
+-      pcmd += sizeof(uint32_t); /* Node Name */
+-      memcpy(pcmd, &vport->fc_nodename, 8);
+-
+-      lpfc_set_disctmo(vport);
+-
+-      phba->fc_stat.elsXmitFDISC++;
+-      elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc;
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "Issue FDISC:     did:x%x",
+-              did, 0, 0);
+-
+-      rc = lpfc_issue_fabric_iocb(phba, elsiocb);
+-      if (rc == IOCB_ERROR) {
+-              lpfc_els_free_iocb(phba, elsiocb);
+-              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-
++dropit:
++      /* check if need to drop received ELS cmd */
++      if (drop_cmd == 1) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                      "%d (%d):0256 Issue FDISC: Cannot send IOCB\n",
+-                      phba->brd_no, vport->vpi);
+-
+-              return 1;
+-      }
+-      lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING);
+-      vport->port_state = LPFC_FDISC;
+-      return 0;
+-}
+-
+-static void
+-lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                      struct lpfc_iocbq *rspiocb)
+-{
+-      struct lpfc_vport *vport = cmdiocb->vport;
+-      IOCB_t *irsp;
+-
+-      irsp = &rspiocb->iocb;
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "LOGO npiv cmpl:  status:x%x/x%x did:x%x",
+-              irsp->ulpStatus, irsp->un.ulpWord[4], irsp->un.rcvels.remoteID);
+-
+-      lpfc_els_free_iocb(phba, cmdiocb);
+-      vport->unreg_vpi_cmpl = VPORT_ERROR;
+-}
+-
+-int
+-lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
+-{
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+-      struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+-      IOCB_t *icmd;
+-      struct lpfc_iocbq *elsiocb;
+-      uint8_t *pcmd;
+-      uint16_t cmdsize;
+-
+-      cmdsize = 2 * sizeof(uint32_t) + sizeof(struct lpfc_name);
+-      elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp, ndlp->nlp_DID,
+-                                   ELS_CMD_LOGO);
+-      if (!elsiocb)
+-              return 1;
+-
+-      icmd = &elsiocb->iocb;
+-      pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+-      *((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
+-      pcmd += sizeof(uint32_t);
+-
+-      /* Fill in LOGO payload */
+-      *((uint32_t *) (pcmd)) = be32_to_cpu(vport->fc_myDID);
+-      pcmd += sizeof(uint32_t);
+-      memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "Issue LOGO npiv  did:x%x flg:x%x",
+-              ndlp->nlp_DID, ndlp->nlp_flag, 0);
+-
+-      elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo;
+-      spin_lock_irq(shost->host_lock);
+-      ndlp->nlp_flag |= NLP_LOGO_SND;
+-      spin_unlock_irq(shost->host_lock);
+-      if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+-              spin_lock_irq(shost->host_lock);
+-              ndlp->nlp_flag &= ~NLP_LOGO_SND;
+-              spin_unlock_irq(shost->host_lock);
+-              lpfc_els_free_iocb(phba, elsiocb);
+-              return 1;
+-      }
+-      return 0;
+-}
+-
+-void
+-lpfc_fabric_block_timeout(unsigned long ptr)
+-{
+-      struct lpfc_hba  *phba = (struct lpfc_hba *) ptr;
+-      unsigned long iflags;
+-      uint32_t tmo_posted;
+-      spin_lock_irqsave(&phba->pport->work_port_lock, iflags);
+-      tmo_posted = phba->pport->work_port_events & WORKER_FABRIC_BLOCK_TMO;
+-      if (!tmo_posted)
+-              phba->pport->work_port_events |= WORKER_FABRIC_BLOCK_TMO;
+-      spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags);
+-
+-      if (!tmo_posted) {
+-              spin_lock_irqsave(&phba->hbalock, iflags);
+-              if (phba->work_wait)
+-                      lpfc_worker_wake_up(phba);
+-              spin_unlock_irqrestore(&phba->hbalock, iflags);
+-      }
+-}
+-
+-static void
+-lpfc_resume_fabric_iocbs(struct lpfc_hba *phba)
+-{
+-      struct lpfc_iocbq *iocb;
+-      unsigned long iflags;
+-      int ret;
+-      struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+-      IOCB_t *cmd;
+-
+-repeat:
+-      iocb = NULL;
+-      spin_lock_irqsave(&phba->hbalock, iflags);
+-                              /* Post any pending iocb to the SLI layer */
+-      if (atomic_read(&phba->fabric_iocb_count) == 0) {
+-              list_remove_head(&phba->fabric_iocb_list, iocb, typeof(*iocb),
+-                               list);
+-              if (iocb)
+-                      atomic_inc(&phba->fabric_iocb_count);
+-      }
+-      spin_unlock_irqrestore(&phba->hbalock, iflags);
+-      if (iocb) {
+-              iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
+-              iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
+-              iocb->iocb_flag |= LPFC_IO_FABRIC;
+-
+-              lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
+-                      "Fabric sched1:   ste:x%x",
+-                      iocb->vport->port_state, 0, 0);
+-
+-              ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
+-
+-              if (ret == IOCB_ERROR) {
+-                      iocb->iocb_cmpl = iocb->fabric_iocb_cmpl;
+-                      iocb->fabric_iocb_cmpl = NULL;
+-                      iocb->iocb_flag &= ~LPFC_IO_FABRIC;
+-                      cmd = &iocb->iocb;
+-                      cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+-                      cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+-                      iocb->iocb_cmpl(phba, iocb, iocb);
+-
+-                      atomic_dec(&phba->fabric_iocb_count);
+-                      goto repeat;
+-              }
++                              "%d:0111 Dropping received ELS cmd "
++                              "Data: x%x x%x x%x\n", phba->brd_no,
++                              icmd->ulpStatus, icmd->un.ulpWord[4],
++                              icmd->ulpTimeout);
++              phba->fc_stat.elsRcvDrop++;
+       }
+-
+       return;
+ }
+-
+-void
+-lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba)
+-{
+-      clear_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
+-
+-      lpfc_resume_fabric_iocbs(phba);
+-      return;
+-}
+-
+-static void
+-lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
+-{
+-      int blocked;
+-
+-      blocked = test_and_set_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
+-                              /* Start a timer to unblock fabric
+-                               * iocbs after 100ms
+-                               */
+-      if (!blocked)
+-              mod_timer(&phba->fabric_block_timer, jiffies + HZ/10 );
+-
+-      return;
+-}
+-
+-static void
+-lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-      struct lpfc_iocbq *rspiocb)
+-{
+-      struct ls_rjt stat;
+-
+-      if ((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC)
+-              BUG();
+-
+-      switch (rspiocb->iocb.ulpStatus) {
+-              case IOSTAT_NPORT_RJT:
+-              case IOSTAT_FABRIC_RJT:
+-                      if (rspiocb->iocb.un.ulpWord[4] & RJT_UNAVAIL_TEMP) {
+-                              lpfc_block_fabric_iocbs(phba);
+-                      }
+-                      break;
+-
+-              case IOSTAT_NPORT_BSY:
+-              case IOSTAT_FABRIC_BSY:
+-                      lpfc_block_fabric_iocbs(phba);
+-                      break;
+-
+-              case IOSTAT_LS_RJT:
+-                      stat.un.lsRjtError =
+-                              be32_to_cpu(rspiocb->iocb.un.ulpWord[4]);
+-                      if ((stat.un.b.lsRjtRsnCode == LSRJT_UNABLE_TPC) ||
+-                              (stat.un.b.lsRjtRsnCode == LSRJT_LOGICAL_BSY))
+-                              lpfc_block_fabric_iocbs(phba);
+-                      break;
+-      }
+-
+-      if (atomic_read(&phba->fabric_iocb_count) == 0)
+-              BUG();
+-
+-      cmdiocb->iocb_cmpl = cmdiocb->fabric_iocb_cmpl;
+-      cmdiocb->fabric_iocb_cmpl = NULL;
+-      cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC;
+-      cmdiocb->iocb_cmpl(phba, cmdiocb, rspiocb);
+-
+-      atomic_dec(&phba->fabric_iocb_count);
+-      if (!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags)) {
+-                              /* Post any pending iocbs to HBA */
+-                  lpfc_resume_fabric_iocbs(phba);
+-      }
+-}
+-
+-int
+-lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
+-{
+-      unsigned long iflags;
+-      struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+-      int ready;
+-      int ret;
+-
+-      if (atomic_read(&phba->fabric_iocb_count) > 1)
+-              BUG();
+-
+-      spin_lock_irqsave(&phba->hbalock, iflags);
+-      ready = atomic_read(&phba->fabric_iocb_count) == 0 &&
+-              !test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
+-
+-      spin_unlock_irqrestore(&phba->hbalock, iflags);
+-      if (ready) {
+-              iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
+-              iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
+-              iocb->iocb_flag |= LPFC_IO_FABRIC;
+-
+-              lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
+-                      "Fabric sched2:   ste:x%x",
+-                      iocb->vport->port_state, 0, 0);
+-
+-              atomic_inc(&phba->fabric_iocb_count);
+-              ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
+-
+-              if (ret == IOCB_ERROR) {
+-                      iocb->iocb_cmpl = iocb->fabric_iocb_cmpl;
+-                      iocb->fabric_iocb_cmpl = NULL;
+-                      iocb->iocb_flag &= ~LPFC_IO_FABRIC;
+-                      atomic_dec(&phba->fabric_iocb_count);
+-              }
+-      } else {
+-              spin_lock_irqsave(&phba->hbalock, iflags);
+-              list_add_tail(&iocb->list, &phba->fabric_iocb_list);
+-              spin_unlock_irqrestore(&phba->hbalock, iflags);
+-              ret = IOCB_SUCCESS;
+-      }
+-      return ret;
+-}
+-
+-
+-void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
+-{
+-      LIST_HEAD(completions);
+-      struct lpfc_hba  *phba = vport->phba;
+-      struct lpfc_iocbq *tmp_iocb, *piocb;
+-      IOCB_t *cmd;
+-
+-      spin_lock_irq(&phba->hbalock);
+-      list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
+-                               list) {
+-
+-              if (piocb->vport != vport)
+-                      continue;
+-
+-              list_move_tail(&piocb->list, &completions);
+-      }
+-      spin_unlock_irq(&phba->hbalock);
+-
+-      while (!list_empty(&completions)) {
+-              piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+-              list_del_init(&piocb->list);
+-
+-              cmd = &piocb->iocb;
+-              cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+-              cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+-              (piocb->iocb_cmpl) (phba, piocb, piocb);
+-      }
+-}
+-
+-void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
+-{
+-      LIST_HEAD(completions);
+-      struct lpfc_hba  *phba = ndlp->vport->phba;
+-      struct lpfc_iocbq *tmp_iocb, *piocb;
+-      struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+-      IOCB_t *cmd;
+-
+-      spin_lock_irq(&phba->hbalock);
+-      list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
+-                               list) {
+-              if ((lpfc_check_sli_ndlp(phba, pring, piocb, ndlp))) {
+-
+-                      list_move_tail(&piocb->list, &completions);
+-              }
+-      }
+-      spin_unlock_irq(&phba->hbalock);
+-
+-      while (!list_empty(&completions)) {
+-              piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+-              list_del_init(&piocb->list);
+-
+-              cmd = &piocb->iocb;
+-              cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+-              cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+-              (piocb->iocb_cmpl) (phba, piocb, piocb);
+-      }
+-}
+-
+-void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
+-{
+-      LIST_HEAD(completions);
+-      struct lpfc_iocbq *piocb;
+-      IOCB_t *cmd;
+-
+-      spin_lock_irq(&phba->hbalock);
+-      list_splice_init(&phba->fabric_iocb_list, &completions);
+-      spin_unlock_irq(&phba->hbalock);
+-
+-      while (!list_empty(&completions)) {
+-              piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+-              list_del_init(&piocb->list);
+-
+-              cmd = &piocb->iocb;
+-              cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+-              cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+-              (piocb->iocb_cmpl) (phba, piocb, piocb);
+-      }
+-}
+-
+-
+-void lpfc_fabric_abort_flogi(struct lpfc_hba *phba)
+-{
+-      LIST_HEAD(completions);
+-      struct lpfc_iocbq *tmp_iocb, *piocb;
+-      IOCB_t *cmd;
+-      struct lpfc_nodelist *ndlp;
+-
+-      spin_lock_irq(&phba->hbalock);
+-      list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
+-                               list) {
+-
+-              cmd = &piocb->iocb;
+-              ndlp = (struct lpfc_nodelist *) piocb->context1;
+-              if (cmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
+-                  ndlp != NULL &&
+-                  ndlp->nlp_DID == Fabric_DID)
+-                      list_move_tail(&piocb->list, &completions);
+-      }
+-      spin_unlock_irq(&phba->hbalock);
+-
+-      while (!list_empty(&completions)) {
+-              piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+-              list_del_init(&piocb->list);
+-
+-              cmd = &piocb->iocb;
+-              cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+-              cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+-              (piocb->iocb_cmpl) (phba, piocb, piocb);
+-      }
+-}
+-
+-
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_hbadisc.c linux-2.6.22-570/drivers/scsi/lpfc/lpfc_hbadisc.c
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_hbadisc.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_hbadisc.c  2007-07-08 19:32:17.000000000 -0400
+@@ -36,8 +36,6 @@
+ #include "lpfc.h"
+ #include "lpfc_logmsg.h"
+ #include "lpfc_crtn.h"
+-#include "lpfc_vport.h"
+-#include "lpfc_debugfs.h"
+ /* AlpaArray for assignment of scsid for scan-down and bind_method */
+ static uint8_t lpfcAlpaArray[] = {
+@@ -56,7 +54,7 @@
+       0x10, 0x0F, 0x08, 0x04, 0x02, 0x01
+ };
+-static void lpfc_disc_timeout_handler(struct lpfc_vport *);
++static void lpfc_disc_timeout_handler(struct lpfc_hba *);
+ void
+ lpfc_terminate_rport_io(struct fc_rport *rport)
+@@ -76,16 +74,14 @@
+               return;
+       }
+-      phba  = ndlp->vport->phba;
+-
+-      lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT,
+-              "rport terminate: sid:x%x did:x%x flg:x%x",
+-              ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag);
++      phba = ndlp->nlp_phba;
++      spin_lock_irq(phba->host->host_lock);
+       if (ndlp->nlp_sid != NLP_NO_SID) {
+               lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
+                       ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
+       }
++      spin_unlock_irq(phba->host->host_lock);
+       return;
+ }
+@@ -98,98 +94,28 @@
+ {
+       struct lpfc_rport_data *rdata;
+       struct lpfc_nodelist * ndlp;
+-      struct lpfc_vport *vport;
++      uint8_t *name;
++      int warn_on = 0;
+       struct lpfc_hba *phba;
+-      struct completion devloss_compl;
+-      struct lpfc_work_evt *evtp;
+       rdata = rport->dd_data;
+       ndlp = rdata->pnode;
+       if (!ndlp) {
+-              if (rport->scsi_target_id != -1) {
++              if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+                       printk(KERN_ERR "Cannot find remote node"
+                       " for rport in dev_loss_tmo_callbk x%x\n",
+                       rport->port_id);
+-              }
+               return;
+       }
+-      vport = ndlp->vport;
+-      phba  = vport->phba;
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
+-              "rport devlosscb: sid:x%x did:x%x flg:x%x",
+-              ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag);
+-
+-      init_completion(&devloss_compl);
+-      evtp = &ndlp->dev_loss_evt;
+-
+-      if (!list_empty(&evtp->evt_listp))
+-              return;
+-
+-      spin_lock_irq(&phba->hbalock);
+-      evtp->evt_arg1  = ndlp;
+-      evtp->evt_arg2  = &devloss_compl;
+-      evtp->evt       = LPFC_EVT_DEV_LOSS;
+-      list_add_tail(&evtp->evt_listp, &phba->work_list);
+-      if (phba->work_wait)
+-              wake_up(phba->work_wait);
+-
+-      spin_unlock_irq(&phba->hbalock);
+-
+-      wait_for_completion(&devloss_compl);
+-
+-      return;
+-}
+-
+-/*
+- * This function is called from the worker thread when dev_loss_tmo
+- * expire.
+- */
+-void
+-lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
+-{
+-      struct lpfc_rport_data *rdata;
+-      struct fc_rport   *rport;
+-      struct lpfc_vport *vport;
+-      struct lpfc_hba   *phba;
+-      uint8_t *name;
+-      int warn_on = 0;
+-
+-      rport = ndlp->rport;
+-
+-      if (!rport)
++      if (ndlp->nlp_state == NLP_STE_MAPPED_NODE)
+               return;
+-      rdata = rport->dd_data;
+-      name = (uint8_t *) &ndlp->nlp_portname;
+-      vport = ndlp->vport;
+-      phba  = vport->phba;
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
+-              "rport devlosstmo:did:x%x type:x%x id:x%x",
+-              ndlp->nlp_DID, ndlp->nlp_type, rport->scsi_target_id);
++      name = (uint8_t *)&ndlp->nlp_portname;
++      phba = ndlp->nlp_phba;
+-      if (!(vport->load_flag & FC_UNLOADING) &&
+-          ndlp->nlp_state == NLP_STE_MAPPED_NODE)
+-              return;
+-
+-      if (ndlp->nlp_type & NLP_FABRIC) {
+-              int  put_node;
+-              int  put_rport;
+-
+-              /* We will clean up these Nodes in linkup */
+-              put_node = rdata->pnode != NULL;
+-              put_rport = ndlp->rport != NULL;
+-              rdata->pnode = NULL;
+-              ndlp->rport = NULL;
+-              if (put_node)
+-                      lpfc_nlp_put(ndlp);
+-              if (put_rport)
+-                      put_device(&rport->dev);
+-              return;
+-      }
++      spin_lock_irq(phba->host->host_lock);
+       if (ndlp->nlp_sid != NLP_NO_SID) {
+               warn_on = 1;
+@@ -197,114 +123,76 @@
+               lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
+                       ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
+       }
+-      if (vport->load_flag & FC_UNLOADING)
++      if (phba->fc_flag & FC_UNLOADING)
+               warn_on = 0;
++      spin_unlock_irq(phba->host->host_lock);
 +
-+              do {
-+                      buf->filldir_called = 0;
-+                      buf->rdstate->bindex = bindex;
-+                      err = vfs_readdir(hidden_file,
-+                                        readdir_util_callback, buf);
-+                      if (buf->err)
-+                              err = buf->err;
-+              } while ((err >= 0) && buf->filldir_called);
-+
-+              /* fput calls dput for hidden_dentry */
-+              fput(hidden_file);
-+              branchput(sb, bindex);
-+
-+              if (err < 0)
-+                      goto out;
-+      }
-+
-+out:
-+      if (buf) {
-+              if (namelist && !err)
-+                      *namelist = buf->rdstate;
-+              else if (buf->rdstate)
-+                      free_rdstate(buf->rdstate);
-+              kfree(buf);
-+      }
-+
-+
-+      return err;
-+}
-diff -Nurb linux-2.6.22-570/fs/unionfs/fanout.h linux-2.6.22-590/fs/unionfs/fanout.h
---- linux-2.6.22-570/fs/unionfs/fanout.h       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/fanout.h       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,308 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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.
-+ */
-+
-+#ifndef _FANOUT_H_
-+#define _FANOUT_H_
-+
-+/*
-+ * Inode to private data
-+ *
-+ * Since we use containers and the struct inode is _inside_ the
-+ * unionfs_inode_info structure, UNIONFS_I will always (given a non-NULL
-+ * inode pointer), return a valid non-NULL pointer.
-+ */
-+static inline struct unionfs_inode_info *UNIONFS_I(const struct inode *inode)
-+{
-+      return container_of(inode, struct unionfs_inode_info, vfs_inode);
-+}
-+
-+#define ibstart(ino) (UNIONFS_I(ino)->bstart)
-+#define ibend(ino) (UNIONFS_I(ino)->bend)
-+
-+/* Superblock to private data */
-+#define UNIONFS_SB(super) ((struct unionfs_sb_info *)(super)->s_fs_info)
-+#define sbstart(sb) 0
-+#define sbend(sb) (UNIONFS_SB(sb)->bend)
-+#define sbmax(sb) (UNIONFS_SB(sb)->bend + 1)
-+#define sbhbid(sb) (UNIONFS_SB(sb)->high_branch_id)
-+
-+/* File to private Data */
-+#define UNIONFS_F(file) ((struct unionfs_file_info *)((file)->private_data))
-+#define fbstart(file) (UNIONFS_F(file)->bstart)
-+#define fbend(file) (UNIONFS_F(file)->bend)
-+
-+/* macros to manipulate branch IDs in stored in our superblock */
-+static inline int branch_id(struct super_block *sb, int index)
-+{
-+      BUG_ON(!sb || index < 0);
-+      return UNIONFS_SB(sb)->data[index].branch_id;
-+}
-+
-+static inline void set_branch_id(struct super_block *sb, int index, int val)
-+{
-+      BUG_ON(!sb || index < 0);
-+      UNIONFS_SB(sb)->data[index].branch_id = val;
-+}
-+
-+static inline void new_branch_id(struct super_block *sb, int index)
-+{
-+      BUG_ON(!sb || index < 0);
-+      set_branch_id(sb, index, ++UNIONFS_SB(sb)->high_branch_id);
-+}
-+
-+/*
-+ * Find new index of matching branch with an existing superblock a a known
-+ * (possibly old) id.  This is needed because branches could have been
-+ * added/deleted causing the branchs of any open files to shift.
-+ *
-+ * @sb: the new superblock which may have new/different branch IDs
-+ * @id: the old/existing id we're looking for
-+ * Returns index of newly found branch (0 or greater), -1 otherwise.
-+ */
-+static inline int branch_id_to_idx(struct super_block *sb, int id)
-+{
+       if (warn_on) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                              "%d (%d):0203 Devloss timeout on "
++                              "%d:0203 Devloss timeout on "
+                               "WWPN %x:%x:%x:%x:%x:%x:%x:%x "
+                               "NPort x%x Data: x%x x%x x%x\n",
+-                              phba->brd_no, vport->vpi,
++                              phba->brd_no,
+                               *name, *(name+1), *(name+2), *(name+3),
+                               *(name+4), *(name+5), *(name+6), *(name+7),
+                               ndlp->nlp_DID, ndlp->nlp_flag,
+                               ndlp->nlp_state, ndlp->nlp_rpi);
+       } else {
+               lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                              "%d (%d):0204 Devloss timeout on "
++                              "%d:0204 Devloss timeout on "
+                               "WWPN %x:%x:%x:%x:%x:%x:%x:%x "
+                               "NPort x%x Data: x%x x%x x%x\n",
+-                              phba->brd_no, vport->vpi,
++                              phba->brd_no,
+                               *name, *(name+1), *(name+2), *(name+3),
+                               *(name+4), *(name+5), *(name+6), *(name+7),
+                               ndlp->nlp_DID, ndlp->nlp_flag,
+                               ndlp->nlp_state, ndlp->nlp_rpi);
+       }
+-      if (!(vport->load_flag & FC_UNLOADING) &&
++      if (!(phba->fc_flag & FC_UNLOADING) &&
+           !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
+           !(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
+           (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE))
+-              lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
++              lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM);
+       else {
+-              int  put_node;
+-              int  put_rport;
+-
+-              put_node = rdata->pnode != NULL;
+-              put_rport = ndlp->rport != NULL;
+               rdata->pnode = NULL;
+               ndlp->rport = NULL;
+-              if (put_node)
+               lpfc_nlp_put(ndlp);
+-              if (put_rport)
+               put_device(&rport->dev);
+       }
+-}
+-
+-void
+-lpfc_worker_wake_up(struct lpfc_hba *phba)
+-{
+-      wake_up(phba->work_wait);
+       return;
+ }
+ static void
+-lpfc_work_list_done(struct lpfc_hba *phba)
++lpfc_work_list_done(struct lpfc_hba * phba)
+ {
+       struct lpfc_work_evt  *evtp = NULL;
+       struct lpfc_nodelist  *ndlp;
+-      struct lpfc_vport     *vport;
+       int free_evt;
+-      spin_lock_irq(&phba->hbalock);
+-      while (!list_empty(&phba->work_list)) {
++      spin_lock_irq(phba->host->host_lock);
++      while(!list_empty(&phba->work_list)) {
+               list_remove_head((&phba->work_list), evtp, typeof(*evtp),
+                                evt_listp);
+-              spin_unlock_irq(&phba->hbalock);
++              spin_unlock_irq(phba->host->host_lock);
+               free_evt = 1;
+               switch (evtp->evt) {
+-              case LPFC_EVT_DEV_LOSS_DELAY:
+-                      free_evt = 0; /* evt is part of ndlp */
+-                      ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1);
+-                      vport = ndlp->vport;
+-                      if (!vport)
+-                              break;
+-
+-                      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
+-                              "rport devlossdly:did:x%x flg:x%x",
+-                              ndlp->nlp_DID, ndlp->nlp_flag, 0);
+-
+-                      if (!(vport->load_flag & FC_UNLOADING) &&
+-                          !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
+-                          !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
+-                              lpfc_disc_state_machine(vport, ndlp, NULL,
+-                                      NLP_EVT_DEVICE_RM);
+-                      }
+-                      break;
+               case LPFC_EVT_ELS_RETRY:
+-                      ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1);
+-                      lpfc_els_retry_delay_handler(ndlp);
+-                      free_evt = 0; /* evt is part of ndlp */
+-                      break;
+-              case LPFC_EVT_DEV_LOSS:
+                       ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1);
+-                      lpfc_nlp_get(ndlp);
+-                      lpfc_dev_loss_tmo_handler(ndlp);
++                      lpfc_els_retry_delay_handler(ndlp);
+                       free_evt = 0;
+-                      complete((struct completion *)(evtp->evt_arg2));
+-                      lpfc_nlp_put(ndlp);
+                       break;
+               case LPFC_EVT_ONLINE:
+-                      if (phba->link_state < LPFC_LINK_DOWN)
+-                              *(int *) (evtp->evt_arg1) = lpfc_online(phba);
++                      if (phba->hba_state < LPFC_LINK_DOWN)
++                              *(int *)(evtp->evt_arg1)  = lpfc_online(phba);
+                       else
+-                              *(int *) (evtp->evt_arg1) = 0;
++                              *(int *)(evtp->evt_arg1)  = 0;
+                       complete((struct completion *)(evtp->evt_arg2));
+                       break;
+               case LPFC_EVT_OFFLINE_PREP:
+-                      if (phba->link_state >= LPFC_LINK_DOWN)
++                      if (phba->hba_state >= LPFC_LINK_DOWN)
+                               lpfc_offline_prep(phba);
+                       *(int *)(evtp->evt_arg1) = 0;
+                       complete((struct completion *)(evtp->evt_arg2));
+@@ -330,31 +218,33 @@
+               case LPFC_EVT_KILL:
+                       lpfc_offline(phba);
+                       *(int *)(evtp->evt_arg1)
+-                              = (phba->pport->stopped)
+-                                      ? 0 : lpfc_sli_brdkill(phba);
++                              = (phba->stopped) ? 0 : lpfc_sli_brdkill(phba);
+                       lpfc_unblock_mgmt_io(phba);
+                       complete((struct completion *)(evtp->evt_arg2));
+                       break;
+               }
+               if (free_evt)
+                       kfree(evtp);
+-              spin_lock_irq(&phba->hbalock);
++              spin_lock_irq(phba->host->host_lock);
+       }
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+ }
+-void
+-lpfc_work_done(struct lpfc_hba *phba)
++static void
++lpfc_work_done(struct lpfc_hba * phba)
+ {
+       struct lpfc_sli_ring *pring;
+-      uint32_t ha_copy, status, control, work_port_events;
+-      struct lpfc_vport *vport;
 +      int i;
-+      for (i = 0; i < sbmax(sb); i++) {
-+              if (branch_id(sb, i) == id)
-+                      return i;
-+      }
-+      /*
-+       * XXX: maybe we should BUG_ON if not found new branch index?
-+       * (really that should never happen).
-+       */
-+      printk(KERN_WARNING "unionfs: cannot find branch with id %d\n", id);
-+      return -1;
-+}
-+
-+/* File to lower file. */
-+static inline struct file *unionfs_lower_file(const struct file *f)
-+{
-+      BUG_ON(!f);
-+      return UNIONFS_F(f)->lower_files[fbstart(f)];
-+}
-+
-+static inline struct file *unionfs_lower_file_idx(const struct file *f,
-+                                                int index)
-+{
-+      BUG_ON(!f || index < 0);
-+      return UNIONFS_F(f)->lower_files[index];
-+}
-+
-+static inline void unionfs_set_lower_file_idx(struct file *f, int index,
-+                                            struct file *val)
-+{
-+      BUG_ON(!f || index < 0);
-+      UNIONFS_F(f)->lower_files[index] = val;
-+      /* save branch ID (may be redundant?) */
-+      UNIONFS_F(f)->saved_branch_ids[index] =
-+              branch_id((f)->f_dentry->d_sb, index);
-+}
-+
-+static inline void unionfs_set_lower_file(struct file *f, struct file *val)
-+{
-+      BUG_ON(!f);
-+      unionfs_set_lower_file_idx((f), fbstart(f), (val));
-+}
-+
-+/* Inode to lower inode. */
-+static inline struct inode *unionfs_lower_inode(const struct inode *i)
-+{
-+      BUG_ON(!i);
-+      return UNIONFS_I(i)->lower_inodes[ibstart(i)];
-+}
-+
-+static inline struct inode *unionfs_lower_inode_idx(const struct inode *i,
-+                                                  int index)
-+{
-+      BUG_ON(!i || index < 0);
-+      return UNIONFS_I(i)->lower_inodes[index];
-+}
-+
-+static inline void unionfs_set_lower_inode_idx(struct inode *i, int index,
-+                                             struct inode *val)
-+{
-+      BUG_ON(!i || index < 0);
-+      UNIONFS_I(i)->lower_inodes[index] = val;
-+}
-+
-+static inline void unionfs_set_lower_inode(struct inode *i, struct inode *val)
-+{
-+      BUG_ON(!i);
-+      UNIONFS_I(i)->lower_inodes[ibstart(i)] = val;
-+}
-+
-+/* Superblock to lower superblock. */
-+static inline struct super_block *unionfs_lower_super(
-+                                      const struct super_block *sb)
-+{
-+      BUG_ON(!sb);
-+      return UNIONFS_SB(sb)->data[sbstart(sb)].sb;
-+}
-+
-+static inline struct super_block *unionfs_lower_super_idx(
-+                                      const struct super_block *sb,
-+                                      int index)
-+{
-+      BUG_ON(!sb || index < 0);
-+      return UNIONFS_SB(sb)->data[index].sb;
-+}
-+
-+static inline void unionfs_set_lower_super_idx(struct super_block *sb,
-+                                             int index,
-+                                             struct super_block *val)
-+{
-+      BUG_ON(!sb || index < 0);
-+      UNIONFS_SB(sb)->data[index].sb = val;
-+}
-+
-+static inline void unionfs_set_lower_super(struct super_block *sb,
-+                                         struct super_block *val)
-+{
-+      BUG_ON(!sb);
-+      UNIONFS_SB(sb)->data[sbstart(sb)].sb = val;
-+}
-+
-+/* Branch count macros. */
-+static inline int branch_count(const struct super_block *sb, int index)
-+{
-+      BUG_ON(!sb || index < 0);
-+      return atomic_read(&UNIONFS_SB(sb)->data[index].open_files);
-+}
-+
-+static inline void set_branch_count(struct super_block *sb, int index, int val)
-+{
-+      BUG_ON(!sb || index < 0);
-+      atomic_set(&UNIONFS_SB(sb)->data[index].open_files, val);
-+}
-+
-+static inline void branchget(struct super_block *sb, int index)
-+{
-+      BUG_ON(!sb || index < 0);
-+      atomic_inc(&UNIONFS_SB(sb)->data[index].open_files);
-+}
-+
-+static inline void branchput(struct super_block *sb, int index)
-+{
-+      BUG_ON(!sb || index < 0);
-+      atomic_dec(&UNIONFS_SB(sb)->data[index].open_files);
-+}
-+
-+/* Dentry macros */
-+static inline struct unionfs_dentry_info *UNIONFS_D(const struct dentry *dent)
-+{
-+      BUG_ON(!dent);
-+      return dent->d_fsdata;
-+}
-+
-+static inline int dbstart(const struct dentry *dent)
-+{
-+      BUG_ON(!dent);
-+      return UNIONFS_D(dent)->bstart;
-+}
-+
-+static inline void set_dbstart(struct dentry *dent, int val)
-+{
-+      BUG_ON(!dent);
-+      UNIONFS_D(dent)->bstart = val;
-+}
-+
-+static inline int dbend(const struct dentry *dent)
-+{
-+      BUG_ON(!dent);
-+      return UNIONFS_D(dent)->bend;
-+}
-+
-+static inline void set_dbend(struct dentry *dent, int val)
-+{
-+      BUG_ON(!dent);
-+      UNIONFS_D(dent)->bend = val;
-+}
-+
-+static inline int dbopaque(const struct dentry *dent)
-+{
-+      BUG_ON(!dent);
-+      return UNIONFS_D(dent)->bopaque;
-+}
-+
-+static inline void set_dbopaque(struct dentry *dent, int val)
-+{
-+      BUG_ON(!dent);
-+      UNIONFS_D(dent)->bopaque = val;
-+}
-+
-+static inline void unionfs_set_lower_dentry_idx(struct dentry *dent, int index,
-+                                              struct dentry *val)
-+{
-+      BUG_ON(!dent || index < 0);
-+      UNIONFS_D(dent)->lower_paths[index].dentry = val;
-+}
-+
-+static inline struct dentry *unionfs_lower_dentry_idx(
-+                              const struct dentry *dent,
-+                              int index)
-+{
-+      BUG_ON(!dent || index < 0);
-+      return UNIONFS_D(dent)->lower_paths[index].dentry;
-+}
-+
-+static inline struct dentry *unionfs_lower_dentry(const struct dentry *dent)
-+{
-+      BUG_ON(!dent);
-+      return unionfs_lower_dentry_idx(dent, dbstart(dent));
-+}
-+
-+static inline void unionfs_set_lower_mnt_idx(struct dentry *dent, int index,
-+                                           struct vfsmount *mnt)
-+{
-+      BUG_ON(!dent || index < 0);
-+      UNIONFS_D(dent)->lower_paths[index].mnt = mnt;
-+}
-+
-+static inline struct vfsmount *unionfs_lower_mnt_idx(
-+                                      const struct dentry *dent,
-+                                      int index)
-+{
-+      BUG_ON(!dent || index < 0);
-+      return UNIONFS_D(dent)->lower_paths[index].mnt;
-+}
-+
-+static inline struct vfsmount *unionfs_lower_mnt(const struct dentry *dent)
-+{
-+      BUG_ON(!dent);
-+      return unionfs_lower_mnt_idx(dent, dbstart(dent));
-+}
-+
-+/* Macros for locking a dentry. */
-+static inline void unionfs_lock_dentry(struct dentry *d)
-+{
-+      BUG_ON(!d);
-+      mutex_lock(&UNIONFS_D(d)->lock);
-+}
-+
-+static inline void unionfs_unlock_dentry(struct dentry *d)
-+{
-+      BUG_ON(!d);
-+      mutex_unlock(&UNIONFS_D(d)->lock);
-+}
-+
-+static inline void verify_locked(struct dentry *d)
-+{
-+      BUG_ON(!d);
-+      BUG_ON(!mutex_is_locked(&UNIONFS_D(d)->lock));
-+}
-+
-+#endif        /* _FANOUT_H */
-diff -Nurb linux-2.6.22-570/fs/unionfs/file.c linux-2.6.22-590/fs/unionfs/file.c
---- linux-2.6.22-570/fs/unionfs/file.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/file.c 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,149 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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 "union.h"
-+
-+/*******************
-+ * File Operations *
-+ *******************/
-+
-+static ssize_t unionfs_read(struct file *file, char __user *buf,
-+                          size_t count, loff_t *ppos)
-+{
-+      int err;
-+
-+      unionfs_read_lock(file->f_path.dentry->d_sb);
-+
-+      if ((err = unionfs_file_revalidate(file, 0)))
-+              goto out;
-+
-+      err = do_sync_read(file, buf, count, ppos);
-+
-+      if (err >= 0)
-+              touch_atime(unionfs_lower_mnt(file->f_path.dentry),
-+                          unionfs_lower_dentry(file->f_path.dentry));
-+
-+out:
-+      unionfs_read_unlock(file->f_path.dentry->d_sb);
-+      return err;
-+}
-+
-+static ssize_t unionfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
-+                              unsigned long nr_segs, loff_t pos)
-+{
-+      int err = 0;
-+      struct file *file = iocb->ki_filp;
-+
-+      unionfs_read_lock(file->f_path.dentry->d_sb);
-+
-+      if ((err = unionfs_file_revalidate(file, 0)))
-+              goto out;
-+
-+      err = generic_file_aio_read(iocb, iov, nr_segs, pos);
-+
-+      if (err == -EIOCBQUEUED)
-+              err = wait_on_sync_kiocb(iocb);
-+
-+      if (err >= 0)
-+              touch_atime(unionfs_lower_mnt(file->f_path.dentry),
-+                          unionfs_lower_dentry(file->f_path.dentry));
-+
-+out:
-+      unionfs_read_unlock(file->f_path.dentry->d_sb);
-+      return err;
-+}
-+static ssize_t unionfs_write(struct file * file, const char __user * buf,
-+                           size_t count, loff_t *ppos)
-+{
-+      int err = 0;
-+
-+      unionfs_read_lock(file->f_path.dentry->d_sb);
-+
-+      if ((err = unionfs_file_revalidate(file, 1)))
-+              goto out;
-+
-+      err = do_sync_write(file, buf, count, ppos);
-+
-+out:
-+      unionfs_read_unlock(file->f_path.dentry->d_sb);
-+      return err;
-+}
-+
-+static int unionfs_file_readdir(struct file *file, void *dirent,
-+                              filldir_t filldir)
-+{
-+      return -ENOTDIR;
-+}
-+
-+static int unionfs_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+      int err = 0;
-+      int willwrite;
-+      struct file *lower_file;
-+
-+      unionfs_read_lock(file->f_path.dentry->d_sb);
-+
-+      if ((err = unionfs_file_revalidate(file, 1)))
-+              goto out;
-+
-+      /* This might be deferred to mmap's writepage */
-+      willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
-+      if ((err = unionfs_file_revalidate(file, willwrite)))
-+              goto out;
-+
-+      /*
-+       * File systems which do not implement ->writepage may use
-+       * generic_file_readonly_mmap as their ->mmap op.  If you call
-+       * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL.
-+       * But we cannot call the lower ->mmap op, so we can't tell that
-+       * writeable mappings won't work.  Therefore, our only choice is to
-+       * check if the lower file system supports the ->writepage, and if
-+       * not, return EINVAL (the same error that
-+       * generic_file_readonly_mmap returns in that case).
-+       */
-+      lower_file = unionfs_lower_file(file);
-+      if (willwrite && !lower_file->f_mapping->a_ops->writepage) {
-+              err = -EINVAL;
-+              printk("unionfs: branch %d file system does not support "
-+                     "writeable mmap\n", fbstart(file));
-+      } else {
-+              err = generic_file_mmap(file, vma);
-+              if (err)
-+                      printk("unionfs: generic_file_mmap failed %d\n", err);
-+      }
-+
-+out:
-+      unionfs_read_unlock(file->f_path.dentry->d_sb);
-+      return err;
-+}
-+
-+struct file_operations unionfs_main_fops = {
-+      .llseek         = generic_file_llseek,
-+      .read           = unionfs_read,
-+      .aio_read       = unionfs_aio_read,
-+      .write          = unionfs_write,
-+      .aio_write      = generic_file_aio_write,
-+      .readdir        = unionfs_file_readdir,
-+      .unlocked_ioctl = unionfs_ioctl,
-+      .mmap           = unionfs_mmap,
-+      .open           = unionfs_open,
-+      .flush          = unionfs_flush,
-+      .release        = unionfs_file_release,
-+      .fsync          = file_fsync,
-+      .sendfile       = generic_file_sendfile,
-+};
-diff -Nurb linux-2.6.22-570/fs/unionfs/inode.c linux-2.6.22-590/fs/unionfs/inode.c
---- linux-2.6.22-570/fs/unionfs/inode.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/inode.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,1138 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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.
-+ */
++      uint32_t ha_copy;
++      uint32_t control;
++      uint32_t work_hba_events;
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       ha_copy = phba->work_ha;
+       phba->work_ha = 0;
+-      spin_unlock_irq(&phba->hbalock);
++      work_hba_events=phba->work_hba_events;
++      spin_unlock_irq(phba->host->host_lock);
+       if (ha_copy & HA_ERATT)
+               lpfc_handle_eratt(phba);
+@@ -365,111 +255,66 @@
+       if (ha_copy & HA_LATT)
+               lpfc_handle_latt(phba);
+-      spin_lock_irq(&phba->hbalock);
+-      list_for_each_entry(vport, &phba->port_list, listentry) {
+-              struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-
+-              if (!scsi_host_get(shost)) {
+-                      continue;
+-              }
+-              spin_unlock_irq(&phba->hbalock);
+-              work_port_events = vport->work_port_events;
+-
+-              if (work_port_events & WORKER_DISC_TMO)
+-                      lpfc_disc_timeout_handler(vport);
++      if (work_hba_events & WORKER_DISC_TMO)
++              lpfc_disc_timeout_handler(phba);
+-              if (work_port_events & WORKER_ELS_TMO)
+-                      lpfc_els_timeout_handler(vport);
++      if (work_hba_events & WORKER_ELS_TMO)
++              lpfc_els_timeout_handler(phba);
+-              if (work_port_events & WORKER_HB_TMO)
+-                      lpfc_hb_timeout_handler(phba);
+-
+-              if (work_port_events & WORKER_MBOX_TMO)
++      if (work_hba_events & WORKER_MBOX_TMO)
+               lpfc_mbox_timeout_handler(phba);
+-              if (work_port_events & WORKER_FABRIC_BLOCK_TMO)
+-                      lpfc_unblock_fabric_iocbs(phba);
+-
+-              if (work_port_events & WORKER_FDMI_TMO)
+-                      lpfc_fdmi_timeout_handler(vport);
++      if (work_hba_events & WORKER_FDMI_TMO)
++              lpfc_fdmi_tmo_handler(phba);
+-              if (work_port_events & WORKER_RAMP_DOWN_QUEUE)
+-                      lpfc_ramp_down_queue_handler(phba);
+-
+-              if (work_port_events & WORKER_RAMP_UP_QUEUE)
+-                      lpfc_ramp_up_queue_handler(phba);
+-
+-              spin_lock_irq(&vport->work_port_lock);
+-              vport->work_port_events &= ~work_port_events;
+-              spin_unlock_irq(&vport->work_port_lock);
+-              scsi_host_put(shost);
+-              spin_lock_irq(&phba->hbalock);
+-      }
+-      spin_unlock_irq(&phba->hbalock);
+-
+-      pring = &phba->sli.ring[LPFC_ELS_RING];
+-      status = (ha_copy & (HA_RXMASK  << (4*LPFC_ELS_RING)));
+-      status >>= (4*LPFC_ELS_RING);
+-      if ((status & HA_RXMASK)
++      spin_lock_irq(phba->host->host_lock);
++      phba->work_hba_events &= ~work_hba_events;
++      spin_unlock_irq(phba->host->host_lock);
++
++      for (i = 0; i < phba->sli.num_rings; i++, ha_copy >>= 4) {
++              pring = &phba->sli.ring[i];
++              if ((ha_copy & HA_RXATT)
+                   || (pring->flag & LPFC_DEFERRED_RING_EVENT)) {
+                       if (pring->flag & LPFC_STOP_IOCB_MASK) {
+                               pring->flag |= LPFC_DEFERRED_RING_EVENT;
+                       } else {
+                               lpfc_sli_handle_slow_ring_event(phba, pring,
+-                                                      (status &
++                                                              (ha_copy &
+                                                                HA_RXMASK));
+                               pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
+                       }
+                       /*
+                        * Turn on Ring interrupts
+                        */
+-              spin_lock_irq(&phba->hbalock);
++                      spin_lock_irq(phba->host->host_lock);
+                       control = readl(phba->HCregaddr);
+-              if (!(control & (HC_R0INT_ENA << LPFC_ELS_RING))) {
+-                      control |= (HC_R0INT_ENA << LPFC_ELS_RING);
++                      control |= (HC_R0INT_ENA << i);
+                       writel(control, phba->HCregaddr);
+                       readl(phba->HCregaddr); /* flush */
++                      spin_unlock_irq(phba->host->host_lock);
+               }
+-              spin_unlock_irq(&phba->hbalock);
+       }
+-      lpfc_work_list_done(phba);
 +
-+#include "union.h"
++      lpfc_work_list_done (phba);
 +
-+static int unionfs_create(struct inode *parent, struct dentry *dentry,
-+                        int mode, struct nameidata *nd)
-+{
-+      int err = 0;
-+      struct dentry *hidden_dentry = NULL;
-+      struct dentry *wh_dentry = NULL;
-+      struct dentry *new_hidden_dentry;
-+      struct dentry *hidden_parent_dentry = NULL;
-+      int bindex = 0, bstart;
-+      char *name = NULL;
-+      int valid = 0;
-+
-+      unionfs_read_lock(dentry->d_sb);
-+      unionfs_lock_dentry(dentry);
-+
-+      unionfs_lock_dentry(dentry->d_parent);
-+      valid = __unionfs_d_revalidate_chain(dentry->d_parent, nd);
-+      unionfs_unlock_dentry(dentry->d_parent);
-+      if (!valid) {
-+              err = -ESTALE;  /* same as what real_lookup does */
-+              goto out;
+ }
+ static int
+-check_work_wait_done(struct lpfc_hba *phba)
+-{
+-      struct lpfc_vport *vport;
+-      struct lpfc_sli_ring *pring;
+-      int rc = 0;
++check_work_wait_done(struct lpfc_hba *phba) {
+-      spin_lock_irq(&phba->hbalock);
+-      list_for_each_entry(vport, &phba->port_list, listentry) {
+-              if (vport->work_port_events) {
+-                      rc = 1;
+-                      goto exit;
+-              }
+-      }
+-
+-      if (phba->work_ha || (!list_empty(&phba->work_list)) ||
++      spin_lock_irq(phba->host->host_lock);
++      if (phba->work_ha ||
++          phba->work_hba_events ||
++          (!list_empty(&phba->work_list)) ||
+           kthread_should_stop()) {
+-              rc = 1;
+-              goto exit;
++              spin_unlock_irq(phba->host->host_lock);
++              return 1;
++      } else {
++              spin_unlock_irq(phba->host->host_lock);
++              return 0;
+       }
+-
+-      pring = &phba->sli.ring[LPFC_ELS_RING];
+-      if (pring->flag & LPFC_DEFERRED_RING_EVENT)
+-              rc = 1;
+-exit:
+-      if (rc)
+-              phba->work_found++;
+-      else
+-              phba->work_found = 0;
+-
+-      spin_unlock_irq(&phba->hbalock);
+-      return rc;
+ }
+-
+ int
+ lpfc_do_work(void *p)
+ {
+@@ -479,13 +324,11 @@
+       set_user_nice(current, -20);
+       phba->work_wait = &work_waitq;
+-      phba->work_found = 0;
+       while (1) {
+               rc = wait_event_interruptible(work_waitq,
+                                               check_work_wait_done(phba));
+-
+               BUG_ON(rc);
+               if (kthread_should_stop())
+@@ -493,17 +336,6 @@
+               lpfc_work_done(phba);
+-              /* If there is alot of slow ring work, like during link up
+-               * check_work_wait_done() may cause this thread to not give
+-               * up the CPU for very long periods of time. This may cause
+-               * soft lockups or other problems. To avoid these situations
+-               * give up the CPU here after LPFC_MAX_WORKER_ITERATION
+-               * consecutive iterations.
+-               */
+-              if (phba->work_found >= LPFC_MAX_WORKER_ITERATION) {
+-                      phba->work_found = 0;
+-                      schedule();
+-              }
+       }
+       phba->work_wait = NULL;
+       return 0;
+@@ -515,17 +347,16 @@
+  * embedding it in the IOCB.
+  */
+ int
+-lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2,
++lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
+                     uint32_t evt)
+ {
+       struct lpfc_work_evt  *evtp;
+-      unsigned long flags;
+       /*
+        * All Mailbox completions and LPFC_ELS_RING rcv ring IOCB events will
+        * be queued to worker thread for processing
+        */
+-      evtp = kmalloc(sizeof(struct lpfc_work_evt), GFP_ATOMIC);
++      evtp = kmalloc(sizeof(struct lpfc_work_evt), GFP_KERNEL);
+       if (!evtp)
+               return 0;
+@@ -533,210 +364,136 @@
+       evtp->evt_arg2  = arg2;
+       evtp->evt       = evt;
+-      spin_lock_irqsave(&phba->hbalock, flags);
++      spin_lock_irq(phba->host->host_lock);
+       list_add_tail(&evtp->evt_listp, &phba->work_list);
+       if (phba->work_wait)
+-              lpfc_worker_wake_up(phba);
+-      spin_unlock_irqrestore(&phba->hbalock, flags);
++              wake_up(phba->work_wait);
++      spin_unlock_irq(phba->host->host_lock);
+       return 1;
+ }
+-void
+-lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
++int
++lpfc_linkdown(struct lpfc_hba *phba)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
++      struct lpfc_sli       *psli;
+       struct lpfc_nodelist  *ndlp, *next_ndlp;
++      LPFC_MBOXQ_t          *mb;
+       int                   rc;
+-      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+-              if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+-                      continue;
+-
+-              if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN)
+-                      lpfc_unreg_rpi(vport, ndlp);
++      psli = &phba->sli;
++      /* sysfs or selective reset may call this routine to clean up */
++      if (phba->hba_state >= LPFC_LINK_DOWN) {
++              if (phba->hba_state == LPFC_LINK_DOWN)
++                      return 0;
+-              /* Leave Fabric nodes alone on link down */
+-              if (!remove && ndlp->nlp_type & NLP_FABRIC)
+-                      continue;
+-              rc = lpfc_disc_state_machine(vport, ndlp, NULL,
+-                                           remove
+-                                           ? NLP_EVT_DEVICE_RM
+-                                           : NLP_EVT_DEVICE_RECOVERY);
+-      }
+-      if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) {
+-              lpfc_mbx_unreg_vpi(vport);
+-              vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
++              spin_lock_irq(phba->host->host_lock);
++              phba->hba_state = LPFC_LINK_DOWN;
++              spin_unlock_irq(phba->host->host_lock);
+       }
+-}
+-
+-static void
+-lpfc_linkdown_port(struct lpfc_vport *vport)
+-{
+-      struct lpfc_nodelist *ndlp, *next_ndlp;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0);
++      fc_host_post_event(phba->host, fc_get_event_number(),
++                      FCH_EVT_LINKDOWN, 0);
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "Link Down:       state:x%x rtry:x%x flg:x%x",
+-              vport->port_state, vport->fc_ns_retry, vport->fc_flag);
++      /* Clean up any firmware default rpi's */
++      if ((mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
++              lpfc_unreg_did(phba, 0xffffffff, mb);
++              mb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
++              if (lpfc_sli_issue_mbox(phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB))
++                  == MBX_NOT_FINISHED) {
++                      mempool_free( mb, phba->mbox_mem_pool);
++              }
 +      }
-+      valid = __unionfs_d_revalidate_chain(dentry, nd);
+       /* Cleanup any outstanding RSCN activity */
+-      lpfc_els_flush_rscn(vport);
++      lpfc_els_flush_rscn(phba);
+       /* Cleanup any outstanding ELS commands */
+-      lpfc_els_flush_cmd(vport);
+-
+-      lpfc_cleanup_rpis(vport, 0);
++      lpfc_els_flush_cmd(phba);
 +      /*
-+       * It's only a bug if this dentry was not negative and couldn't be
-+       * revalidated (shouldn't happen).
++       * Issue a LINK DOWN event to all nodes.
 +       */
-+      BUG_ON(!valid && dentry->d_inode);
++      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
+                               /* free any ndlp's on unused list */
+-      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
+-                              /* free any ndlp's in unused state */
+               if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+-                      lpfc_drop_node(vport, ndlp);
+-
+-      /* Turn off discovery timer if its running */
+-      lpfc_can_disctmo(vport);
+-}
+-
+-int
+-lpfc_linkdown(struct lpfc_hba *phba)
+-{
+-      struct lpfc_vport *vport = phba->pport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_vport *port_iterator;
+-      LPFC_MBOXQ_t          *mb;
+-
+-      if (phba->link_state == LPFC_LINK_DOWN) {
+-              return 0;
+-      }
+-      spin_lock_irq(&phba->hbalock);
+-      if (phba->link_state > LPFC_LINK_DOWN) {
+-              phba->link_state = LPFC_LINK_DOWN;
+-              phba->pport->fc_flag &= ~FC_LBIT;
+-      }
+-      spin_unlock_irq(&phba->hbalock);
+-
+-      list_for_each_entry(port_iterator, &phba->port_list, listentry) {
+-
+-                              /* Issue a LINK DOWN event to all nodes */
+-              lpfc_linkdown_port(port_iterator);
+-      }
+-
+-      /* Clean up any firmware default rpi's */
+-      mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (mb) {
+-              lpfc_unreg_did(phba, 0xffff, 0xffffffff, mb);
+-              mb->vport = vport;
+-              mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-              if (lpfc_sli_issue_mbox(phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB))
+-                  == MBX_NOT_FINISHED) {
+-                      mempool_free(mb, phba->mbox_mem_pool);
+-              }
++                      lpfc_drop_node(phba, ndlp);
++              else            /* otherwise, force node recovery. */
++                      rc = lpfc_disc_state_machine(phba, ndlp, NULL,
++                                                   NLP_EVT_DEVICE_RECOVERY);
+       }
+       /* Setup myDID for link up if we are in pt2pt mode */
+-      if (phba->pport->fc_flag & FC_PT2PT) {
+-              phba->pport->fc_myDID = 0;
+-              mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-              if (mb) {
++      if (phba->fc_flag & FC_PT2PT) {
++              phba->fc_myDID = 0;
++              if ((mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
+                       lpfc_config_link(phba, mb);
+-                      mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-                      mb->vport = vport;
+-                      if (lpfc_sli_issue_mbox(phba, mb,
+-                                              (MBX_NOWAIT | MBX_STOP_IOCB))
++                      mb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
++                      if (lpfc_sli_issue_mbox
++                          (phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB))
+                           == MBX_NOT_FINISHED) {
+-                              mempool_free(mb, phba->mbox_mem_pool);
++                              mempool_free( mb, phba->mbox_mem_pool);
+                       }
+               }
+-              spin_lock_irq(shost->host_lock);
+-              phba->pport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI);
+-              spin_unlock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
++              phba->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI);
++              spin_unlock_irq(phba->host->host_lock);
+       }
++      spin_lock_irq(phba->host->host_lock);
++      phba->fc_flag &= ~FC_LBIT;
++      spin_unlock_irq(phba->host->host_lock);
 +
-+      /* We start out in the leftmost branch. */
-+      bstart = dbstart(dentry);
-+      hidden_dentry = unionfs_lower_dentry(dentry);
++      /* Turn off discovery timer if its running */
++      lpfc_can_disctmo(phba);
++      /* Must process IOCBs on all rings to handle ABORTed I/Os */
+       return 0;
+ }
+-static void
+-lpfc_linkup_cleanup_nodes(struct lpfc_vport *vport)
++static int
++lpfc_linkup(struct lpfc_hba *phba)
+ {
+-      struct lpfc_nodelist *ndlp;
++      struct lpfc_nodelist *ndlp, *next_ndlp;
 +
-+      /*
-+       * check if whiteout exists in this branch, i.e. lookup .wh.foo
-+       * first.
-+       */
-+      name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
-+      if (IS_ERR(name)) {
-+              err = PTR_ERR(name);
-+              goto out;
-+      }
++      fc_host_post_event(phba->host, fc_get_event_number(),
++                      FCH_EVT_LINKUP, 0);
 +
-+      wh_dentry = lookup_one_len(name, hidden_dentry->d_parent,
-+                                 dentry->d_name.len + UNIONFS_WHLEN);
-+      if (IS_ERR(wh_dentry)) {
-+              err = PTR_ERR(wh_dentry);
-+              wh_dentry = NULL;
++      spin_lock_irq(phba->host->host_lock);
++      phba->hba_state = LPFC_LINK_UP;
++      phba->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY |
++                         FC_RSCN_MODE | FC_NLP_MORE | FC_RSCN_DISCOVERY);
++      phba->fc_flag |= FC_NDISC_ACTIVE;
++      phba->fc_ns_retry = 0;
++      spin_unlock_irq(phba->host->host_lock);
+-      list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
+-              if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+-                      continue;
++      if (phba->fc_flag & FC_LBIT) {
++              list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
++                      if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) {
+                               if (ndlp->nlp_type & NLP_FABRIC) {
+-                              /* On Linkup its safe to clean up the ndlp
+-                               * from Fabric connections.
++                                      /*
++                                       * On Linkup its safe to clean up the
++                                       * ndlp from Fabric connections.
+                                        */
+-                      if (ndlp->nlp_DID != Fabric_DID)
+-                              lpfc_unreg_rpi(vport, ndlp);
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
++                                      lpfc_nlp_set_state(phba, ndlp,
++                                                         NLP_STE_UNUSED_NODE);
+                               } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
+-                              /* Fail outstanding IO now since device is
+-                               * marked for PLOGI.
++                                      /*
++                                       * Fail outstanding IO now since
++                                       * device is marked for PLOGI.
+                                        */
+-                      lpfc_unreg_rpi(vport, ndlp);
++                                      lpfc_unreg_rpi(phba, ndlp);
++                              }
++                      }
+               }
+       }
+-}
+-
+-static void
+-lpfc_linkup_port(struct lpfc_vport *vport)
+-{
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_nodelist *ndlp, *next_ndlp;
+-      struct lpfc_hba  *phba = vport->phba;
+-
+-      if ((vport->load_flag & FC_UNLOADING) != 0)
+-              return;
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "Link Up:         top:x%x speed:x%x flg:x%x",
+-              phba->fc_topology, phba->fc_linkspeed, phba->link_flag);
+-
+-      /* If NPIV is not enabled, only bring the physical port up */
+-      if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+-              (vport != phba->pport))
+-              return;
+-
+-      fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKUP, 0);
+-      spin_lock_irq(shost->host_lock);
+-      vport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY |
+-                          FC_RSCN_MODE | FC_NLP_MORE | FC_RSCN_DISCOVERY);
+-      vport->fc_flag |= FC_NDISC_ACTIVE;
+-      vport->fc_ns_retry = 0;
+-      spin_unlock_irq(shost->host_lock);
+-
+-      if (vport->fc_flag & FC_LBIT)
+-              lpfc_linkup_cleanup_nodes(vport);
+-
+-                              /* free any ndlp's in unused state */
+-      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
+-                               nlp_listp)
++      /* free any ndlp's on unused list */
++      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
++                               nlp_listp) {
+               if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+-                      lpfc_drop_node(vport, ndlp);
+-}
+-
+-static int
+-lpfc_linkup(struct lpfc_hba *phba)
+-{
+-      struct lpfc_vport *vport;
+-
+-      phba->link_state = LPFC_LINK_UP;
+-
+-      /* Unblock fabric iocbs if they are blocked */
+-      clear_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
+-      del_timer_sync(&phba->fabric_block_timer);
+-
+-      list_for_each_entry(vport, &phba->port_list, listentry) {
+-              lpfc_linkup_port(vport);
++                      lpfc_drop_node(phba, ndlp);
+       }
+-      if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
+-              lpfc_issue_clear_la(phba, phba->pport);
+       return 0;
+ }
+@@ -748,14 +505,14 @@
+  * handed off to the SLI layer.
+  */
+ void
+-lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
++lpfc_mbx_cmpl_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+ {
+-      struct lpfc_vport *vport = pmb->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_sli   *psli = &phba->sli;
+-      MAILBOX_t *mb = &pmb->mb;
++      struct lpfc_sli *psli;
++      MAILBOX_t *mb;
+       uint32_t control;
++      psli = &phba->sli;
++      mb = &pmb->mb;
+       /* Since we don't do discovery right now, turn these off here */
+       psli->ring[psli->extra_ring].flag &= ~LPFC_STOP_IOCB_EVENT;
+       psli->ring[psli->fcp_ring].flag &= ~LPFC_STOP_IOCB_EVENT;
+@@ -765,74 +522,69 @@
+       if ((mb->mbxStatus) && (mb->mbxStatus != 0x1601)) {
+               /* CLEAR_LA mbox error <mbxStatus> state <hba_state> */
+               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+-                              "%d (%d):0320 CLEAR_LA mbxStatus error x%x hba "
++                              "%d:0320 CLEAR_LA mbxStatus error x%x hba "
+                               "state x%x\n",
+-                              phba->brd_no, vport->vpi, mb->mbxStatus,
+-                              vport->port_state);
++                              phba->brd_no, mb->mbxStatus, phba->hba_state);
+-              phba->link_state = LPFC_HBA_ERROR;
++              phba->hba_state = LPFC_HBA_ERROR;
+               goto out;
+       }
+-      if (vport->port_type == LPFC_PHYSICAL_PORT)
+-              phba->link_state = LPFC_HBA_READY;
+-
+-      spin_lock_irq(&phba->hbalock);
+-      psli->sli_flag |= LPFC_PROCESS_LA;
+-      control = readl(phba->HCregaddr);
+-      control |= HC_LAINT_ENA;
+-      writel(control, phba->HCregaddr);
+-      readl(phba->HCregaddr); /* flush */
+-      spin_unlock_irq(&phba->hbalock);
+-      return;
++      if (phba->fc_flag & FC_ABORT_DISCOVERY)
 +              goto out;
+-      vport->num_disc_nodes = 0;
+-      /* go thru NPR nodes and issue ELS PLOGIs */
+-      if (vport->fc_npr_cnt)
+-              lpfc_els_disc_plogi(vport);
++      phba->num_disc_nodes = 0;
++      /* go thru NPR list and issue ELS PLOGIs */
++      if (phba->fc_npr_cnt) {
++              lpfc_els_disc_plogi(phba);
 +      }
+-      if (!vport->num_disc_nodes) {
+-              spin_lock_irq(shost->host_lock);
+-              vport->fc_flag &= ~FC_NDISC_ACTIVE;
+-              spin_unlock_irq(shost->host_lock);
++      if (!phba->num_disc_nodes) {
++              spin_lock_irq(phba->host->host_lock);
++              phba->fc_flag &= ~FC_NDISC_ACTIVE;
++              spin_unlock_irq(phba->host->host_lock);
+       }
+-      vport->port_state = LPFC_VPORT_READY;
++      phba->hba_state = LPFC_HBA_READY;
+ out:
+       /* Device Discovery completes */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0225 Device Discovery completes\n",
+-                      phba->brd_no, vport->vpi);
+-
+-      mempool_free(pmb, phba->mbox_mem_pool);
+-
+-      spin_lock_irq(shost->host_lock);
+-      vport->fc_flag &= ~(FC_ABORT_DISCOVERY | FC_ESTABLISH_LINK);
+-      spin_unlock_irq(shost->host_lock);
++      lpfc_printf_log(phba,
++                       KERN_INFO,
++                       LOG_DISCOVERY,
++                       "%d:0225 Device Discovery completes\n",
++                       phba->brd_no);
 +
-+      if (wh_dentry->d_inode) {
-+              /*
-+               * .wh.foo has been found.
-+               * First truncate it and then rename it to foo (hence having
-+               * the same overall effect as a normal create.
-+               */
-+              struct dentry *hidden_dir_dentry;
-+              struct iattr newattrs;
-+
-+              mutex_lock(&wh_dentry->d_inode->i_mutex);
-+              newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_ATIME
-+                      | ATTR_MTIME | ATTR_UID | ATTR_GID | ATTR_FORCE
-+                      | ATTR_KILL_SUID | ATTR_KILL_SGID;
-+
-+              newattrs.ia_mode = mode & ~current->fs->umask;
-+              newattrs.ia_uid = current->fsuid;
-+              newattrs.ia_gid = current->fsgid;
-+
-+              if (wh_dentry->d_inode->i_size != 0) {
-+                      newattrs.ia_valid |= ATTR_SIZE;
-+                      newattrs.ia_size = 0;
-+              }
-+
-+              err = notify_change(wh_dentry, &newattrs);
-+
-+              mutex_unlock(&wh_dentry->d_inode->i_mutex);
-+
-+              if (err)
-+                      printk(KERN_WARNING "unionfs: %s:%d: notify_change "
-+                             "failed: %d, ignoring..\n",
-+                             __FILE__, __LINE__, err);
-+
-+              new_hidden_dentry = unionfs_lower_dentry(dentry);
-+              dget(new_hidden_dentry);
-+
-+              hidden_dir_dentry = dget_parent(wh_dentry);
-+              lock_rename(hidden_dir_dentry, hidden_dir_dentry);
-+
-+              if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
-+                      err = vfs_rename(hidden_dir_dentry->d_inode,
-+                                       wh_dentry,
-+                                       hidden_dir_dentry->d_inode,
-+                                       new_hidden_dentry);
-+              }
-+              if (!err) {
-+                      fsstack_copy_attr_times(parent,
-+                                              new_hidden_dentry->d_parent->
-+                                              d_inode);
-+                      fsstack_copy_inode_size(parent,
-+                                              new_hidden_dentry->d_parent->
-+                                              d_inode);
-+                      parent->i_nlink = unionfs_get_nlinks(parent);
-+              }
-+
-+              unlock_rename(hidden_dir_dentry, hidden_dir_dentry);
-+              dput(hidden_dir_dentry);
-+
-+              dput(new_hidden_dentry);
-+
-+              if (err) {
-+                      /* exit if the error returned was NOT -EROFS */
-+                      if (!IS_COPYUP_ERR(err))
-+                              goto out;
-+                      /*
-+                       * We were not able to create the file in this
-+                       * branch, so, we try to create it in one branch to
-+                       * left
-+                       */
-+                      bstart--;
-+              } else {
-+                      /*
-+                       * reset the unionfs dentry to point to the .wh.foo
-+                       * entry.
-+                       */
-+
-+                      /* Discard any old reference. */
-+                      dput(unionfs_lower_dentry(dentry));
-+
-+                      /* Trade one reference to another. */
-+                      unionfs_set_lower_dentry_idx(dentry, bstart,
-+                                                   wh_dentry);
-+                      wh_dentry = NULL;
-+
-+                      err = unionfs_interpose(dentry, parent->i_sb, 0);
-+                      goto out;
-+              }
-+      }
-+
-+      for (bindex = bstart; bindex >= 0; bindex--) {
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!hidden_dentry) {
-+                      /*
-+                       * if hidden_dentry is NULL, create the entire
-+                       * dentry directory structure in branch 'bindex'.
-+                       * hidden_dentry will NOT be null when bindex == bstart
-+                       * because lookup passed as a negative unionfs dentry
-+                       * pointing to a lone negative underlying dentry.
-+                       */
-+                      hidden_dentry = create_parents(parent, dentry, bindex);
-+                      if (!hidden_dentry || IS_ERR(hidden_dentry)) {
-+                              if (IS_ERR(hidden_dentry))
-+                                      err = PTR_ERR(hidden_dentry);
-+                              continue;
-+                      }
-+              }
-+
-+              hidden_parent_dentry = lock_parent(hidden_dentry);
-+              if (IS_ERR(hidden_parent_dentry)) {
-+                      err = PTR_ERR(hidden_parent_dentry);
-+                      goto out;
-+              }
-+              /* We shouldn't create things in a read-only branch. */
-+              if (!(err = is_robranch_super(dentry->d_sb, bindex)))
-+                      err = vfs_create(hidden_parent_dentry->d_inode,
-+                                       hidden_dentry, mode, nd);
-+
-+              if (err || !hidden_dentry->d_inode) {
-+                      unlock_dir(hidden_parent_dentry);
++      mempool_free( pmb, phba->mbox_mem_pool);
 +
-+                      /* break out of for loop if the error wasn't  -EROFS */
-+                      if (!IS_COPYUP_ERR(err))
-+                              break;
-+              } else {
-+                      err = unionfs_interpose(dentry, parent->i_sb, 0);
-+                      if (!err) {
-+                              fsstack_copy_attr_times(parent,
-+                                                      hidden_parent_dentry->
-+                                                      d_inode);
-+                              fsstack_copy_inode_size(parent,
-+                                                      hidden_parent_dentry->
-+                                                      d_inode);
-+                              /* update no. of links on parent directory */
-+                              parent->i_nlink = unionfs_get_nlinks(parent);
-+                      }
-+                      unlock_dir(hidden_parent_dentry);
-+                      break;
-+              }
++      spin_lock_irq(phba->host->host_lock);
++      phba->fc_flag &= ~FC_ABORT_DISCOVERY;
++      if (phba->fc_flag & FC_ESTABLISH_LINK) {
++              phba->fc_flag &= ~FC_ESTABLISH_LINK;
 +      }
++      spin_unlock_irq(phba->host->host_lock);
+       del_timer_sync(&phba->fc_estabtmo);
+-      lpfc_can_disctmo(vport);
++      lpfc_can_disctmo(phba);
+       /* turn on Link Attention interrupts */
+-
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       psli->sli_flag |= LPFC_PROCESS_LA;
+       control = readl(phba->HCregaddr);
+       control |= HC_LAINT_ENA;
+       writel(control, phba->HCregaddr);
+       readl(phba->HCregaddr); /* flush */
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       return;
+ }
+-
+ static void
+ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ {
+-      struct lpfc_vport *vport = pmb->vport;
++      struct lpfc_sli *psli = &phba->sli;
++      int rc;
+       if (pmb->mb.mbxStatus)
+               goto out;
+@@ -840,110 +592,127 @@
+       mempool_free(pmb, phba->mbox_mem_pool);
+       if (phba->fc_topology == TOPOLOGY_LOOP &&
+-          vport->fc_flag & FC_PUBLIC_LOOP &&
+-          !(vport->fc_flag & FC_LBIT)) {
++              phba->fc_flag & FC_PUBLIC_LOOP &&
++               !(phba->fc_flag & FC_LBIT)) {
+                       /* Need to wait for FAN - use discovery timer
+-                       * for timeout.  port_state is identically
++                       * for timeout.  hba_state is identically
+                        * LPFC_LOCAL_CFG_LINK while waiting for FAN
+                        */
+-                      lpfc_set_disctmo(vport);
++                      lpfc_set_disctmo(phba);
+                       return;
+               }
+-      /* Start discovery by sending a FLOGI. port_state is identically
++      /* Start discovery by sending a FLOGI. hba_state is identically
+        * LPFC_FLOGI while waiting for FLOGI cmpl
+        */
+-      if (vport->port_state != LPFC_FLOGI) {
+-              vport->port_state = LPFC_FLOGI;
+-              lpfc_set_disctmo(vport);
+-              lpfc_initial_flogi(vport);
+-      }
++      phba->hba_state = LPFC_FLOGI;
++      lpfc_set_disctmo(phba);
++      lpfc_initial_flogi(phba);
+       return;
+ out:
+       lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+-                      "%d (%d):0306 CONFIG_LINK mbxStatus error x%x "
++                      "%d:0306 CONFIG_LINK mbxStatus error x%x "
+                       "HBA state x%x\n",
+-                      phba->brd_no, vport->vpi, pmb->mb.mbxStatus,
+-                      vport->port_state);
+-
+-      mempool_free(pmb, phba->mbox_mem_pool);
++                      phba->brd_no, pmb->mb.mbxStatus, phba->hba_state);
+       lpfc_linkdown(phba);
++      phba->hba_state = LPFC_HBA_ERROR;
 +
-+out:
-+      dput(wh_dentry);
-+      kfree(name);
-+
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+static struct dentry *unionfs_lookup(struct inode *parent,
-+                                   struct dentry *dentry,
-+                                   struct nameidata *nd)
-+{
-+      struct path path_save;
-+      struct dentry *ret;
-+
-+      unionfs_read_lock(dentry->d_sb);
-+
-+      /* save the dentry & vfsmnt from namei */
-+      if (nd) {
-+              path_save.dentry = nd->dentry;
-+              path_save.mnt = nd->mnt;
+       lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                      "%d (%d):0200 CONFIG_LINK bad hba state x%x\n",
+-                      phba->brd_no, vport->vpi, vport->port_state);
++                      "%d:0200 CONFIG_LINK bad hba state x%x\n",
++                      phba->brd_no, phba->hba_state);
+-      lpfc_issue_clear_la(phba, vport);
++      lpfc_clear_la(phba, pmb);
++      pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
++      rc = lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB));
++      if (rc == MBX_NOT_FINISHED) {
++              mempool_free(pmb, phba->mbox_mem_pool);
++              lpfc_disc_flush_list(phba);
++              psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
++              psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
++              psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
++              phba->hba_state = LPFC_HBA_READY;
 +      }
-+
-+      /* The locking is done by unionfs_lookup_backend. */
-+      ret = unionfs_lookup_backend(dentry, nd, INTERPOSE_LOOKUP);
-+
-+      /* restore the dentry & vfsmnt in namei */
-+      if (nd) {
-+              nd->dentry = path_save.dentry;
-+              nd->mnt = path_save.mnt;
+       return;
+ }
+ static void
+-lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
++lpfc_mbx_cmpl_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+ {
++      struct lpfc_sli *psli = &phba->sli;
+       MAILBOX_t *mb = &pmb->mb;
+       struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) pmb->context1;
+-      struct lpfc_vport  *vport = pmb->vport;
+       /* Check for error */
+       if (mb->mbxStatus) {
+               /* READ_SPARAM mbox error <mbxStatus> state <hba_state> */
+               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+-                              "%d (%d):0319 READ_SPARAM mbxStatus error x%x "
++                              "%d:0319 READ_SPARAM mbxStatus error x%x "
+                               "hba state x%x>\n",
+-                              phba->brd_no, vport->vpi, mb->mbxStatus,
+-                              vport->port_state);
++                              phba->brd_no, mb->mbxStatus, phba->hba_state);
+               lpfc_linkdown(phba);
++              phba->hba_state = LPFC_HBA_ERROR;
+               goto out;
+       }
+-      memcpy((uint8_t *) &vport->fc_sparam, (uint8_t *) mp->virt,
++      memcpy((uint8_t *) & phba->fc_sparam, (uint8_t *) mp->virt,
+              sizeof (struct serv_parm));
+       if (phba->cfg_soft_wwnn)
+-              u64_to_wwn(phba->cfg_soft_wwnn,
+-                         vport->fc_sparam.nodeName.u.wwn);
++              u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
+       if (phba->cfg_soft_wwpn)
+-              u64_to_wwn(phba->cfg_soft_wwpn,
+-                         vport->fc_sparam.portName.u.wwn);
+-      memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
+-             sizeof(vport->fc_nodename));
+-      memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
+-             sizeof(vport->fc_portname));
+-      if (vport->port_type == LPFC_PHYSICAL_PORT) {
+-              memcpy(&phba->wwnn, &vport->fc_nodename, sizeof(phba->wwnn));
+-              memcpy(&phba->wwpn, &vport->fc_portname, sizeof(phba->wwnn));
+-      }
+-
++              u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
++      memcpy((uint8_t *) & phba->fc_nodename,
++             (uint8_t *) & phba->fc_sparam.nodeName,
++             sizeof (struct lpfc_name));
++      memcpy((uint8_t *) & phba->fc_portname,
++             (uint8_t *) & phba->fc_sparam.portName,
++             sizeof (struct lpfc_name));
+       lpfc_mbuf_free(phba, mp->virt, mp->phys);
+       kfree(mp);
+-      mempool_free(pmb, phba->mbox_mem_pool);
++      mempool_free( pmb, phba->mbox_mem_pool);
+       return;
+ out:
+       pmb->context1 = NULL;
+       lpfc_mbuf_free(phba, mp->virt, mp->phys);
+       kfree(mp);
+-      lpfc_issue_clear_la(phba, vport);
+-      mempool_free(pmb, phba->mbox_mem_pool);
++      if (phba->hba_state != LPFC_CLEAR_LA) {
++              lpfc_clear_la(phba, pmb);
++              pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
++              if (lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB))
++                  == MBX_NOT_FINISHED) {
++                      mempool_free( pmb, phba->mbox_mem_pool);
++                      lpfc_disc_flush_list(phba);
++                      psli->ring[(psli->extra_ring)].flag &=
++                          ~LPFC_STOP_IOCB_EVENT;
++                      psli->ring[(psli->fcp_ring)].flag &=
++                          ~LPFC_STOP_IOCB_EVENT;
++                      psli->ring[(psli->next_ring)].flag &=
++                          ~LPFC_STOP_IOCB_EVENT;
++                      phba->hba_state = LPFC_HBA_READY;
++              }
++      } else {
++              mempool_free( pmb, phba->mbox_mem_pool);
 +      }
+       return;
+ }
+ static void
+ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
+ {
+-      struct lpfc_vport *vport = phba->pport;
+-      LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox;
+       int i;
++      LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox;
+       struct lpfc_dmabuf *mp;
+       int rc;
+       sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       switch (la->UlnkSpeed) {
+               case LA_1GHZ_LINK:
+                       phba->fc_linkspeed = LA_1GHZ_LINK;
+@@ -963,16 +732,14 @@
+       }
+       phba->fc_topology = la->topology;
+-      phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
+       if (phba->fc_topology == TOPOLOGY_LOOP) {
+-              phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED;
+-
+                               /* Get Loop Map information */
 +
-+      unionfs_read_unlock(dentry->d_sb);
-+
-+      return ret;
-+}
-+
-+static int unionfs_link(struct dentry *old_dentry, struct inode *dir,
-+                      struct dentry *new_dentry)
-+{
-+      int err = 0;
-+      struct dentry *hidden_old_dentry = NULL;
-+      struct dentry *hidden_new_dentry = NULL;
-+      struct dentry *hidden_dir_dentry = NULL;
-+      struct dentry *whiteout_dentry;
-+      char *name = NULL;
-+
-+      unionfs_read_lock(old_dentry->d_sb);
-+      unionfs_double_lock_dentry(new_dentry, old_dentry);
-+
-+      if (!__unionfs_d_revalidate_chain(old_dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+      if (new_dentry->d_inode &&
-+          !__unionfs_d_revalidate_chain(new_dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
+               if (la->il)
+-                      vport->fc_flag |= FC_LBIT;
++                      phba->fc_flag |= FC_LBIT;
+-              vport->fc_myDID = la->granted_AL_PA;
++              phba->fc_myDID = la->granted_AL_PA;
+               i = la->un.lilpBde64.tus.f.bdeSize;
+               if (i == 0) {
+@@ -1014,20 +781,14 @@
+                       }
+               }
+       } else {
+-              if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) {
+-                      if (phba->max_vpi && phba->cfg_npiv_enable &&
+-                         (phba->sli_rev == 3))
+-                              phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
+-              }
+-              vport->fc_myDID = phba->fc_pref_DID;
+-              vport->fc_flag |= FC_LBIT;
++              phba->fc_myDID = phba->fc_pref_DID;
++              phba->fc_flag |= FC_LBIT;
+       }
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       lpfc_linkup(phba);
+       if (sparam_mbox) {
+-              lpfc_read_sparam(phba, sparam_mbox, 0);
+-              sparam_mbox->vport = vport;
++              lpfc_read_sparam(phba, sparam_mbox);
+               sparam_mbox->mbox_cmpl = lpfc_mbx_cmpl_read_sparam;
+               rc = lpfc_sli_issue_mbox(phba, sparam_mbox,
+                                               (MBX_NOWAIT | MBX_STOP_IOCB));
+@@ -1038,48 +799,36 @@
+                       mempool_free(sparam_mbox, phba->mbox_mem_pool);
+                       if (cfglink_mbox)
+                               mempool_free(cfglink_mbox, phba->mbox_mem_pool);
+-                      goto out;
++                      return;
+               }
+       }
+       if (cfglink_mbox) {
+-              vport->port_state = LPFC_LOCAL_CFG_LINK;
++              phba->hba_state = LPFC_LOCAL_CFG_LINK;
+               lpfc_config_link(phba, cfglink_mbox);
+-              cfglink_mbox->vport = vport;
+               cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link;
+               rc = lpfc_sli_issue_mbox(phba, cfglink_mbox,
+                                               (MBX_NOWAIT | MBX_STOP_IOCB));
+-              if (rc != MBX_NOT_FINISHED)
+-                      return;
++              if (rc == MBX_NOT_FINISHED)
+                       mempool_free(cfglink_mbox, phba->mbox_mem_pool);
+       }
+-out:
+-      lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-      lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+-              "%d (%d):0263 Discovery Mailbox error: state: 0x%x : %p %p\n",
+-              phba->brd_no, vport->vpi,
+-              vport->port_state, sparam_mbox, cfglink_mbox);
+-
+-      lpfc_issue_clear_la(phba, vport);
+-      return;
+ }
+ static void
+-lpfc_mbx_issue_link_down(struct lpfc_hba *phba)
+-{
++lpfc_mbx_issue_link_down(struct lpfc_hba *phba) {
+       uint32_t control;
+       struct lpfc_sli *psli = &phba->sli;
+       lpfc_linkdown(phba);
+       /* turn on Link Attention interrupts - no CLEAR_LA needed */
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       psli->sli_flag |= LPFC_PROCESS_LA;
+       control = readl(phba->HCregaddr);
+       control |= HC_LAINT_ENA;
+       writel(control, phba->HCregaddr);
+       readl(phba->HCregaddr); /* flush */
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+ }
+ /*
+@@ -1089,21 +838,22 @@
+  * handed off to the SLI layer.
+  */
+ void
+-lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
++lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+ {
+-      struct lpfc_vport *vport = pmb->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+       READ_LA_VAR *la;
+       MAILBOX_t *mb = &pmb->mb;
+       struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
+       /* Check for error */
+       if (mb->mbxStatus) {
+-              lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
++              lpfc_printf_log(phba,
++                              KERN_INFO,
++                              LOG_LINK_EVENT,
+                               "%d:1307 READ_LA mbox error x%x state x%x\n",
+-                              phba->brd_no, mb->mbxStatus, vport->port_state);
++                              phba->brd_no,
++                              mb->mbxStatus, phba->hba_state);
+               lpfc_mbx_issue_link_down(phba);
+-              phba->link_state = LPFC_HBA_ERROR;
++              phba->hba_state = LPFC_HBA_ERROR;
+               goto lpfc_mbx_cmpl_read_la_free_mbuf;
+       }
+@@ -1111,26 +861,27 @@
+       memcpy(&phba->alpa_map[0], mp->virt, 128);
+-      spin_lock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
+       if (la->pb)
+-              vport->fc_flag |= FC_BYPASSED_MODE;
++              phba->fc_flag |= FC_BYPASSED_MODE;
+       else
+-              vport->fc_flag &= ~FC_BYPASSED_MODE;
+-      spin_unlock_irq(shost->host_lock);
++              phba->fc_flag &= ~FC_BYPASSED_MODE;
++      spin_unlock_irq(phba->host->host_lock);
+       if (((phba->fc_eventTag + 1) < la->eventTag) ||
+            (phba->fc_eventTag == la->eventTag)) {
+               phba->fc_stat.LinkMultiEvent++;
+-              if (la->attType == AT_LINK_UP)
++              if (la->attType == AT_LINK_UP) {
+                       if (phba->fc_eventTag != 0)
+                               lpfc_linkdown(phba);
+               }
 +      }
+       phba->fc_eventTag = la->eventTag;
+       if (la->attType == AT_LINK_UP) {
+               phba->fc_stat.LinkUp++;
+-              if (phba->link_flag & LS_LOOPBACK_MODE) {
++              if (phba->fc_flag & FC_LOOPBACK_MODE) {
+                       lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
+                               "%d:1306 Link Up Event in loop back mode "
+                               "x%x received Data: x%x x%x x%x x%x\n",
+@@ -1152,7 +903,7 @@
+                               "%d:1305 Link Down Event x%x received "
+                               "Data: x%x x%x x%x\n",
+                               phba->brd_no, la->eventTag, phba->fc_eventTag,
+-                              phba->pport->port_state, vport->fc_flag);
++                              phba->hba_state, phba->fc_flag);
+               lpfc_mbx_issue_link_down(phba);
+       }
+@@ -1170,115 +921,31 @@
+  * handed off to the SLI layer.
+  */
+ void
+-lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
++lpfc_mbx_cmpl_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+ {
+-      struct lpfc_vport  *vport = pmb->vport;
+-      struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
+-      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
++      struct lpfc_sli *psli;
++      MAILBOX_t *mb;
++      struct lpfc_dmabuf *mp;
++      struct lpfc_nodelist *ndlp;
 +
-+      hidden_new_dentry = unionfs_lower_dentry(new_dentry);
++      psli = &phba->sli;
++      mb = &pmb->mb;
 +
-+      /*
-+       * check if whiteout exists in the branch of new dentry, i.e. lookup
-+       * .wh.foo first. If present, delete it
-+       */
-+      name = alloc_whname(new_dentry->d_name.name, new_dentry->d_name.len);
-+      if (IS_ERR(name)) {
-+              err = PTR_ERR(name);
-+              goto out;
-+      }
++      ndlp = (struct lpfc_nodelist *) pmb->context2;
++      mp = (struct lpfc_dmabuf *) (pmb->context1);
+       pmb->context1 = NULL;
+       /* Good status, call state machine */
+-      lpfc_disc_state_machine(vport, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN);
++      lpfc_disc_state_machine(phba, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN);
+       lpfc_mbuf_free(phba, mp->virt, mp->phys);
+       kfree(mp);
+-      mempool_free(pmb, phba->mbox_mem_pool);
++      mempool_free( pmb, phba->mbox_mem_pool);
+       lpfc_nlp_put(ndlp);
+       return;
+ }
+-static void
+-lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+-{
+-      MAILBOX_t *mb = &pmb->mb;
+-      struct lpfc_vport *vport = pmb->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-
+-      switch (mb->mbxStatus) {
+-      case 0x0011:
+-      case 0x0020:
+-      case 0x9700:
+-              lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
+-                              "%d (%d):0911 cmpl_unreg_vpi, "
+-                              "mb status = 0x%x\n",
+-                              phba->brd_no, vport->vpi, mb->mbxStatus);
+-              break;
+-      }
+-      vport->unreg_vpi_cmpl = VPORT_OK;
+-      mempool_free(pmb, phba->mbox_mem_pool);
+-      /*
+-       * This shost reference might have been taken at the beginning of
+-       * lpfc_vport_delete()
+-       */
+-      if (vport->load_flag & FC_UNLOADING)
+-              scsi_host_put(shost);
+-}
+-
+-void
+-lpfc_mbx_unreg_vpi(struct lpfc_vport *vport)
+-{
+-      struct lpfc_hba  *phba = vport->phba;
+-      LPFC_MBOXQ_t *mbox;
+-      int rc;
+-
+-      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (!mbox)
+-              return;
+-
+-      lpfc_unreg_vpi(phba, vport->vpi, mbox);
+-      mbox->vport = vport;
+-      mbox->mbox_cmpl = lpfc_mbx_cmpl_unreg_vpi;
+-      rc = lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
+-      if (rc == MBX_NOT_FINISHED) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_VPORT,
+-                              "%d (%d):1800 Could not issue unreg_vpi\n",
+-                              phba->brd_no, vport->vpi);
+-              mempool_free(mbox, phba->mbox_mem_pool);
+-              vport->unreg_vpi_cmpl = VPORT_ERROR;
+-      }
+-}
+-
+-static void
+-lpfc_mbx_cmpl_reg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+-{
+-      struct lpfc_vport *vport = pmb->vport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      MAILBOX_t *mb = &pmb->mb;
+-
+-      switch (mb->mbxStatus) {
+-      case 0x0011:
+-      case 0x9601:
+-      case 0x9602:
+-              lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
+-                              "%d (%d):0912 cmpl_reg_vpi, mb status = 0x%x\n",
+-                              phba->brd_no, vport->vpi, mb->mbxStatus);
+-              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-              spin_lock_irq(shost->host_lock);
+-              vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+-              spin_unlock_irq(shost->host_lock);
+-              vport->fc_myDID = 0;
+-              goto out;
+-      }
+-
+-      vport->num_disc_nodes = 0;
+-      /* go thru NPR list and issue ELS PLOGIs */
+-      if (vport->fc_npr_cnt)
+-              lpfc_els_disc_plogi(vport);
+-
+-      if (!vport->num_disc_nodes) {
+-              spin_lock_irq(shost->host_lock);
+-              vport->fc_flag &= ~FC_NDISC_ACTIVE;
+-              spin_unlock_irq(shost->host_lock);
+-              lpfc_can_disctmo(vport);
+-      }
+-      vport->port_state = LPFC_VPORT_READY;
+-
+-out:
+-      mempool_free(pmb, phba->mbox_mem_pool);
+-      return;
+-}
+-
+ /*
+  * This routine handles processing a Fabric REG_LOGIN mailbox
+  * command upon completion. It is setup in the LPFC_MBOXQ
+@@ -1286,14 +953,20 @@
+  * handed off to the SLI layer.
+  */
+ void
+-lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
++lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+ {
+-      struct lpfc_vport *vport = pmb->vport;
+-      struct lpfc_vport *next_vport;
+-      MAILBOX_t *mb = &pmb->mb;
+-      struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
++      struct lpfc_sli *psli;
++      MAILBOX_t *mb;
++      struct lpfc_dmabuf *mp;
+       struct lpfc_nodelist *ndlp;
++      struct lpfc_nodelist *ndlp_fdmi;
 +
-+      whiteout_dentry = lookup_one_len(name, hidden_new_dentry->d_parent,
-+                                       new_dentry->d_name.len +
-+                                       UNIONFS_WHLEN);
-+      if (IS_ERR(whiteout_dentry)) {
-+              err = PTR_ERR(whiteout_dentry);
-+              goto out;
-+      }
 +
-+      if (!whiteout_dentry->d_inode) {
-+              dput(whiteout_dentry);
-+              whiteout_dentry = NULL;
-+      } else {
-+              /* found a .wh.foo entry, unlink it and then call vfs_link() */
-+              hidden_dir_dentry = lock_parent(whiteout_dentry);
-+              err = is_robranch_super(new_dentry->d_sb, dbstart(new_dentry));
-+              if (!err)
-+                      err = vfs_unlink(hidden_dir_dentry->d_inode,
-+                                       whiteout_dentry);
-+
-+              fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
-+              dir->i_nlink = unionfs_get_nlinks(dir);
-+              unlock_dir(hidden_dir_dentry);
-+              hidden_dir_dentry = NULL;
-+              dput(whiteout_dentry);
-+              if (err)
-+                      goto out;
-+      }
++      psli = &phba->sli;
++      mb = &pmb->mb;
 +
-+      if (dbstart(old_dentry) != dbstart(new_dentry)) {
-+              hidden_new_dentry =
-+                      create_parents(dir, new_dentry, dbstart(old_dentry));
-+              err = PTR_ERR(hidden_new_dentry);
-+              if (IS_COPYUP_ERR(err))
-+                      goto docopyup;
-+              if (!hidden_new_dentry || IS_ERR(hidden_new_dentry))
-+                      goto out;
-+      }
-+      hidden_new_dentry = unionfs_lower_dentry(new_dentry);
-+      hidden_old_dentry = unionfs_lower_dentry(old_dentry);
-+
-+      BUG_ON(dbstart(old_dentry) != dbstart(new_dentry));
-+      hidden_dir_dentry = lock_parent(hidden_new_dentry);
-+      if (!(err = is_robranch(old_dentry)))
-+              err = vfs_link(hidden_old_dentry, hidden_dir_dentry->d_inode,
-+                             hidden_new_dentry);
-+      unlock_dir(hidden_dir_dentry);
-+
-+docopyup:
-+      if (IS_COPYUP_ERR(err)) {
-+              int old_bstart = dbstart(old_dentry);
-+              int bindex;
-+
-+              for (bindex = old_bstart - 1; bindex >= 0; bindex--) {
-+                      err = copyup_dentry(old_dentry->d_parent->d_inode,
-+                                          old_dentry, old_bstart,
-+                                          bindex, NULL,
-+                                          old_dentry->d_inode->i_size);
-+                      if (!err) {
-+                              hidden_new_dentry =
-+                                      create_parents(dir, new_dentry,
-+                                                     bindex);
-+                              hidden_old_dentry =
-+                                      unionfs_lower_dentry(old_dentry);
-+                              hidden_dir_dentry =
-+                                      lock_parent(hidden_new_dentry);
-+                              /* do vfs_link */
-+                              err = vfs_link(hidden_old_dentry,
-+                                             hidden_dir_dentry->d_inode,
-+                                             hidden_new_dentry);
-+                              unlock_dir(hidden_dir_dentry);
-+                              goto check_link;
+       ndlp = (struct lpfc_nodelist *) pmb->context2;
++      mp = (struct lpfc_dmabuf *) (pmb->context1);
+       pmb->context1 = NULL;
+       pmb->context2 = NULL;
+@@ -1304,46 +977,60 @@
+               mempool_free(pmb, phba->mbox_mem_pool);
+               lpfc_nlp_put(ndlp);
+-              if (phba->fc_topology == TOPOLOGY_LOOP) {
+-                      /* FLOGI failed, use loop map to make discovery list */
+-                      lpfc_disc_list_loopmap(vport);
++              /* FLOGI failed, so just use loop map to make discovery list */
++              lpfc_disc_list_loopmap(phba);
+               /* Start discovery */
+-                      lpfc_disc_start(vport);
+-                      return;
+-              }
+-
+-              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-              lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+-                      "%d (%d):0258 Register Fabric login error: 0x%x\n",
+-                      phba->brd_no, vport->vpi, mb->mbxStatus);
+-
++              lpfc_disc_start(phba);
+               return;
+       }
+       ndlp->nlp_rpi = mb->un.varWords[0];
+       ndlp->nlp_type |= NLP_FABRIC;
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+       lpfc_nlp_put(ndlp);     /* Drop the reference from the mbox */
+-      if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
+-              list_for_each_entry(next_vport, &phba->port_list, listentry) {
+-                      if (next_vport->port_type == LPFC_PHYSICAL_PORT)
+-                              continue;
++      if (phba->hba_state == LPFC_FABRIC_CFG_LINK) {
++              /* This NPort has been assigned an NPort_ID by the fabric as a
++               * result of the completed fabric login.  Issue a State Change
++               * Registration (SCR) ELS request to the fabric controller
++               * (SCR_DID) so that this NPort gets RSCN events from the
++               * fabric.
++               */
++              lpfc_issue_els_scr(phba, SCR_DID, 0);
+-                      if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
+-                              lpfc_initial_fdisc(next_vport);
+-                      else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
+-                              lpfc_vport_set_state(vport,
+-                                                   FC_VPORT_NO_FABRIC_SUPP);
+-                              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                                              "%d (%d):0259 No NPIV Fabric "
+-                                              "support\n",
+-                                              phba->brd_no, vport->vpi);
++              ndlp = lpfc_findnode_did(phba, NameServer_DID);
++              if (!ndlp) {
++                      /* Allocate a new node instance. If the pool is empty,
++                       * start the discovery process and skip the Nameserver
++                       * login process.  This is attempted again later on.
++                       * Otherwise, issue a Port Login (PLOGI) to NameServer.
++                       */
++                      ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
++                      if (!ndlp) {
++                              lpfc_disc_start(phba);
++                              lpfc_mbuf_free(phba, mp->virt, mp->phys);
++                              kfree(mp);
++                              mempool_free(pmb, phba->mbox_mem_pool);
++                              return;
++                      } else {
++                              lpfc_nlp_init(phba, ndlp, NameServer_DID);
++                              ndlp->nlp_type |= NLP_FABRIC;
 +                      }
 +              }
-+              goto out;
-+      }
-+
-+check_link:
-+      if (err || !hidden_new_dentry->d_inode)
-+              goto out;
-+
-+      /* Its a hard link, so use the same inode */
-+      new_dentry->d_inode = igrab(old_dentry->d_inode);
-+      d_instantiate(new_dentry, new_dentry->d_inode);
-+      fsstack_copy_attr_all(dir, hidden_new_dentry->d_parent->d_inode,
-+                            unionfs_get_nlinks);
-+      fsstack_copy_inode_size(dir, hidden_new_dentry->d_parent->d_inode);
-+
-+      /* propagate number of hard-links */
-+      old_dentry->d_inode->i_nlink = unionfs_get_nlinks(old_dentry->d_inode);
-+
-+out:
-+      if (!new_dentry->d_inode)
-+              d_drop(new_dentry);
-+
-+      kfree(name);
-+
-+      unionfs_unlock_dentry(new_dentry);
-+      unionfs_unlock_dentry(old_dentry);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
++              lpfc_issue_els_plogi(phba, NameServer_DID, 0);
++              if (phba->cfg_fdmi_on) {
++                      ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
++                                                              GFP_KERNEL);
++                      if (ndlp_fdmi) {
++                              lpfc_nlp_init(phba, ndlp_fdmi, FDMI_DID);
++                              ndlp_fdmi->nlp_type |= NLP_FABRIC;
++                              ndlp_fdmi->nlp_state = NLP_STE_PLOGI_ISSUE;
++                              lpfc_issue_els_plogi(phba, FDMI_DID, 0);
+                       }
+               }
+-              lpfc_do_scr_ns_plogi(phba, vport);
+       }
+       lpfc_mbuf_free(phba, mp->virt, mp->phys);
+@@ -1359,36 +1046,32 @@
+  * handed off to the SLI layer.
+  */
+ void
+-lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
++lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+ {
+-      MAILBOX_t *mb = &pmb->mb;
+-      struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
+-      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
+-      struct lpfc_vport *vport = pmb->vport;
++      struct lpfc_sli *psli;
++      MAILBOX_t *mb;
++      struct lpfc_dmabuf *mp;
++      struct lpfc_nodelist *ndlp;
 +
-+      unionfs_read_unlock(old_dentry->d_sb);
++      psli = &phba->sli;
++      mb = &pmb->mb;
 +
-+      return err;
-+}
++      ndlp = (struct lpfc_nodelist *) pmb->context2;
++      mp = (struct lpfc_dmabuf *) (pmb->context1);
+       if (mb->mbxStatus) {
+-out:
+               lpfc_nlp_put(ndlp);
+               lpfc_mbuf_free(phba, mp->virt, mp->phys);
+               kfree(mp);
+               mempool_free(pmb, phba->mbox_mem_pool);
+-              lpfc_drop_node(vport, ndlp);
++              lpfc_drop_node(phba, ndlp);
+-              if (phba->fc_topology == TOPOLOGY_LOOP) {
+-                      /*
+-                       * RegLogin failed, use loop map to make discovery
+-                       * list
+-                       */
+-                      lpfc_disc_list_loopmap(vport);
++              /* RegLogin failed, so just use loop map to make discovery
++                 list */
++              lpfc_disc_list_loopmap(phba);
+               /* Start discovery */
+-                      lpfc_disc_start(vport);
+-                      return;
+-              }
+-              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                      "%d (%d):0260 Register NameServer error: 0x%x\n",
+-                      phba->brd_no, vport->vpi, mb->mbxStatus);
++              lpfc_disc_start(phba);
+               return;
+       }
+@@ -1396,43 +1079,37 @@
+       ndlp->nlp_rpi = mb->un.varWords[0];
+       ndlp->nlp_type |= NLP_FABRIC;
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+-      if (vport->port_state < LPFC_VPORT_READY) {
+-              /* Link up discovery requires Fabric registration. */
+-              lpfc_ns_cmd(vport, SLI_CTNS_RFF_ID, 0, 0); /* Do this first! */
+-              lpfc_ns_cmd(vport, SLI_CTNS_RNN_ID, 0, 0);
+-              lpfc_ns_cmd(vport, SLI_CTNS_RSNN_NN, 0, 0);
+-              lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0);
+-              lpfc_ns_cmd(vport, SLI_CTNS_RFT_ID, 0, 0);
+-
+-              /* Issue SCR just before NameServer GID_FT Query */
+-              lpfc_issue_els_scr(vport, SCR_DID, 0);
++      if (phba->hba_state < LPFC_HBA_READY) {
++              /* Link up discovery requires Fabrib registration. */
++              lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RNN_ID);
++              lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RSNN_NN);
++              lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFT_ID);
++              lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFF_ID);
+       }
+-      vport->fc_ns_retry = 0;
++      phba->fc_ns_retry = 0;
+       /* Good status, issue CT Request to NameServer */
+-      if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0)) {
++      if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT)) {
+               /* Cannot issue NameServer Query, so finish up discovery */
+-              goto out;
++              lpfc_disc_start(phba);
+       }
+       lpfc_nlp_put(ndlp);
+       lpfc_mbuf_free(phba, mp->virt, mp->phys);
+       kfree(mp);
+-      mempool_free(pmb, phba->mbox_mem_pool);
++      mempool_free( pmb, phba->mbox_mem_pool);
+       return;
+ }
+ static void
+-lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
++lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+       struct fc_rport *rport;
+       struct lpfc_rport_data *rdata;
+       struct fc_rport_identifiers rport_ids;
+-      struct lpfc_hba  *phba = vport->phba;
+       /* Remote port has reappeared. Re-register w/ FC transport */
+       rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
+@@ -1448,15 +1125,10 @@
+        * registered the port.
+        */
+       if (ndlp->rport && ndlp->rport->dd_data &&
+-          ((struct lpfc_rport_data *) ndlp->rport->dd_data)->pnode == ndlp) {
++          *(struct lpfc_rport_data **) ndlp->rport->dd_data) {
+               lpfc_nlp_put(ndlp);
+       }
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
+-              "rport add:       did:x%x flg:x%x type x%x",
+-              ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
+-
+-      ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids);
++      ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
+       if (!rport || !get_device(&rport->dev)) {
+               dev_printk(KERN_WARNING, &phba->pcidev->dev,
+                          "Warning: fc_remote_port_add failed\n");
+@@ -1482,17 +1154,22 @@
+               (rport->scsi_target_id < LPFC_MAX_TARGET)) {
+               ndlp->nlp_sid = rport->scsi_target_id;
+       }
 +
-+static int unionfs_symlink(struct inode *dir, struct dentry *dentry,
-+                         const char *symname)
-+{
-+      int err = 0;
-+      struct dentry *hidden_dentry = NULL;
-+      struct dentry *whiteout_dentry = NULL;
-+      struct dentry *hidden_dir_dentry = NULL;
-+      umode_t mode;
-+      int bindex = 0, bstart;
-+      char *name = NULL;
-+
-+      unionfs_read_lock(dentry->d_sb);
-+      unionfs_lock_dentry(dentry);
-+
-+      if (dentry->d_inode &&
-+          !__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
+       return;
+ }
+ static void
+-lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp)
++lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+ {
+       struct fc_rport *rport = ndlp->rport;
++      struct lpfc_rport_data *rdata = rport->dd_data;
+-      lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT,
+-              "rport delete:    did:x%x flg:x%x type x%x",
+-              ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
++      if (rport->scsi_target_id == -1) {
++              ndlp->rport = NULL;
++              rdata->pnode = NULL;
++              lpfc_nlp_put(ndlp);
++              put_device(&rport->dev);
 +      }
+       fc_remote_port_delete(rport);
+@@ -1500,46 +1177,42 @@
+ }
+ static void
+-lpfc_nlp_counters(struct lpfc_vport *vport, int state, int count)
++lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+-      spin_lock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
+       switch (state) {
+       case NLP_STE_UNUSED_NODE:
+-              vport->fc_unused_cnt += count;
++              phba->fc_unused_cnt += count;
+               break;
+       case NLP_STE_PLOGI_ISSUE:
+-              vport->fc_plogi_cnt += count;
++              phba->fc_plogi_cnt += count;
+               break;
+       case NLP_STE_ADISC_ISSUE:
+-              vport->fc_adisc_cnt += count;
++              phba->fc_adisc_cnt += count;
+               break;
+       case NLP_STE_REG_LOGIN_ISSUE:
+-              vport->fc_reglogin_cnt += count;
++              phba->fc_reglogin_cnt += count;
+               break;
+       case NLP_STE_PRLI_ISSUE:
+-              vport->fc_prli_cnt += count;
++              phba->fc_prli_cnt += count;
+               break;
+       case NLP_STE_UNMAPPED_NODE:
+-              vport->fc_unmap_cnt += count;
++              phba->fc_unmap_cnt += count;
+               break;
+       case NLP_STE_MAPPED_NODE:
+-              vport->fc_map_cnt += count;
++              phba->fc_map_cnt += count;
+               break;
+       case NLP_STE_NPR_NODE:
+-              vport->fc_npr_cnt += count;
++              phba->fc_npr_cnt += count;
+               break;
+       }
+-      spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+ }
+ static void
+-lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
++lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+                      int old_state, int new_state)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+       if (new_state == NLP_STE_UNMAPPED_NODE) {
+               ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
+               ndlp->nlp_flag &= ~NLP_NODEV_REMOVE;
+@@ -1553,20 +1226,21 @@
+       /* Transport interface */
+       if (ndlp->rport && (old_state == NLP_STE_MAPPED_NODE ||
+                           old_state == NLP_STE_UNMAPPED_NODE)) {
+-              vport->phba->nport_event_cnt++;
+-              lpfc_unregister_remote_port(ndlp);
++              phba->nport_event_cnt++;
++              lpfc_unregister_remote_port(phba, ndlp);
+       }
+       if (new_state ==  NLP_STE_MAPPED_NODE ||
+           new_state == NLP_STE_UNMAPPED_NODE) {
+-              vport->phba->nport_event_cnt++;
++              phba->nport_event_cnt++;
+                       /*
+                        * Tell the fc transport about the port, if we haven't
+                        * already. If we have, and it's a scsi entity, be
+                        * sure to unblock any attached scsi devices
+                        */
+-              lpfc_register_remote_port(vport, ndlp);
++                      lpfc_register_remote_port(phba, ndlp);
+       }
 +
-+      /* We start out in the leftmost branch. */
-+      bstart = dbstart(dentry);
-+
-+      hidden_dentry = unionfs_lower_dentry(dentry);
-+
-+      /*
-+       * check if whiteout exists in this branch, i.e. lookup .wh.foo
-+       * first. If present, delete it
-+       */
-+      name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
-+      if (IS_ERR(name)) {
-+              err = PTR_ERR(name);
-+              goto out;
-+      }
+                       /*
+                        * if we added to Mapped list, but the remote port
+                        * registration failed or assigned a target id outside
+@@ -1577,10 +1251,10 @@
+           (!ndlp->rport ||
+            ndlp->rport->scsi_target_id == -1 ||
+            ndlp->rport->scsi_target_id >= LPFC_MAX_TARGET)) {
+-              spin_lock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
+               ndlp->nlp_flag |= NLP_TGT_NO_SCSIID;
+-              spin_unlock_irq(shost->host_lock);
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
++              spin_unlock_irq(phba->host->host_lock);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+       }
+ }
+@@ -1606,74 +1280,61 @@
+ }
+ void
+-lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                 int state)
++lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+       int  old_state = ndlp->nlp_state;
+       char name1[16], name2[16];
+-      lpfc_printf_log(vport->phba, KERN_INFO, LOG_NODE,
+-                      "%d (%d):0904 NPort state transition x%06x, %s -> %s\n",
+-                      vport->phba->brd_no, vport->vpi,
++      lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
++                      "%d:0904 NPort state transition x%06x, %s -> %s\n",
++                      phba->brd_no,
+                       ndlp->nlp_DID,
+                       lpfc_nlp_state_name(name1, sizeof(name1), old_state),
+                       lpfc_nlp_state_name(name2, sizeof(name2), state));
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE,
+-              "node statechg    did:x%x old:%d ste:%d",
+-              ndlp->nlp_DID, old_state, state);
+-
+       if (old_state == NLP_STE_NPR_NODE &&
+           (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 &&
+           state != NLP_STE_NPR_NODE)
+-              lpfc_cancel_retry_delay_tmo(vport, ndlp);
++              lpfc_cancel_retry_delay_tmo(phba, ndlp);
+       if (old_state == NLP_STE_UNMAPPED_NODE) {
+               ndlp->nlp_flag &= ~NLP_TGT_NO_SCSIID;
+               ndlp->nlp_type &= ~NLP_FC_NODE;
+       }
+       if (list_empty(&ndlp->nlp_listp)) {
+-              spin_lock_irq(shost->host_lock);
+-              list_add_tail(&ndlp->nlp_listp, &vport->fc_nodes);
+-              spin_unlock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
++              list_add_tail(&ndlp->nlp_listp, &phba->fc_nodes);
++              spin_unlock_irq(phba->host->host_lock);
+       } else if (old_state)
+-              lpfc_nlp_counters(vport, old_state, -1);
++              lpfc_nlp_counters(phba, old_state, -1);
+       ndlp->nlp_state = state;
+-      lpfc_nlp_counters(vport, state, 1);
+-      lpfc_nlp_state_cleanup(vport, ndlp, old_state, state);
++      lpfc_nlp_counters(phba, state, 1);
++      lpfc_nlp_state_cleanup(phba, ndlp, old_state, state);
+ }
+ void
+-lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
++lpfc_dequeue_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+       if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
+-              lpfc_cancel_retry_delay_tmo(vport, ndlp);
++              lpfc_cancel_retry_delay_tmo(phba, ndlp);
+       if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
+-              lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
+-      spin_lock_irq(shost->host_lock);
++              lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
++      spin_lock_irq(phba->host->host_lock);
+       list_del_init(&ndlp->nlp_listp);
+-      spin_unlock_irq(shost->host_lock);
+-      lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state,
+-                             NLP_STE_UNUSED_NODE);
++      spin_unlock_irq(phba->host->host_lock);
++      lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0);
+ }
+ void
+-lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
++lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+       if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
+-              lpfc_cancel_retry_delay_tmo(vport, ndlp);
++              lpfc_cancel_retry_delay_tmo(phba, ndlp);
+       if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
+-              lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
+-      spin_lock_irq(shost->host_lock);
++              lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
++      spin_lock_irq(phba->host->host_lock);
+       list_del_init(&ndlp->nlp_listp);
+-      ndlp->nlp_flag &= ~NLP_TARGET_REMOVE;
+-      spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+       lpfc_nlp_put(ndlp);
+ }
+@@ -1681,13 +1342,11 @@
+  * Start / ReStart rescue timer for Discovery / RSCN handling
+  */
+ void
+-lpfc_set_disctmo(struct lpfc_vport *vport)
++lpfc_set_disctmo(struct lpfc_hba * phba)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+       uint32_t tmo;
+-      if (vport->port_state == LPFC_LOCAL_CFG_LINK) {
++      if (phba->hba_state == LPFC_LOCAL_CFG_LINK) {
+               /* For FAN, timeout should be greater then edtov */
+               tmo = (((phba->fc_edtov + 999) / 1000) + 1);
+       } else {
+@@ -1697,25 +1356,18 @@
+               tmo = ((phba->fc_ratov * 3) + 3);
+       }
+-
+-      if (!timer_pending(&vport->fc_disctmo)) {
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-                      "set disc timer:  tmo:x%x state:x%x flg:x%x",
+-                      tmo, vport->port_state, vport->fc_flag);
+-      }
+-
+-      mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo);
+-      spin_lock_irq(shost->host_lock);
+-      vport->fc_flag |= FC_DISC_TMO;
+-      spin_unlock_irq(shost->host_lock);
++      mod_timer(&phba->fc_disctmo, jiffies + HZ * tmo);
++      spin_lock_irq(phba->host->host_lock);
++      phba->fc_flag |= FC_DISC_TMO;
++      spin_unlock_irq(phba->host->host_lock);
+       /* Start Discovery Timer state <hba_state> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0247 Start Discovery Timer state x%x "
++                      "%d:0247 Start Discovery Timer state x%x "
+                       "Data: x%x x%lx x%x x%x\n",
+-                      phba->brd_no, vport->vpi, vport->port_state, tmo,
+-                      (unsigned long)&vport->fc_disctmo, vport->fc_plogi_cnt,
+-                      vport->fc_adisc_cnt);
++                      phba->brd_no,
++                      phba->hba_state, tmo, (unsigned long)&phba->fc_disctmo,
++                      phba->fc_plogi_cnt, phba->fc_adisc_cnt);
+       return;
+ }
+@@ -1724,34 +1376,23 @@
+  * Cancel rescue timer for Discovery / RSCN handling
+  */
+ int
+-lpfc_can_disctmo(struct lpfc_vport *vport)
++lpfc_can_disctmo(struct lpfc_hba * phba)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+-      unsigned long iflags;
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "can disc timer:  state:x%x rtry:x%x flg:x%x",
+-              vport->port_state, vport->fc_ns_retry, vport->fc_flag);
+-
+       /* Turn off discovery timer if its running */
+-      if (vport->fc_flag & FC_DISC_TMO) {
+-              spin_lock_irqsave(shost->host_lock, iflags);
+-              vport->fc_flag &= ~FC_DISC_TMO;
+-              spin_unlock_irqrestore(shost->host_lock, iflags);
+-              del_timer_sync(&vport->fc_disctmo);
+-              spin_lock_irqsave(&vport->work_port_lock, iflags);
+-              vport->work_port_events &= ~WORKER_DISC_TMO;
+-              spin_unlock_irqrestore(&vport->work_port_lock, iflags);
++      if (phba->fc_flag & FC_DISC_TMO) {
++              spin_lock_irq(phba->host->host_lock);
++              phba->fc_flag &= ~FC_DISC_TMO;
++              spin_unlock_irq(phba->host->host_lock);
++              del_timer_sync(&phba->fc_disctmo);
++              phba->work_hba_events &= ~WORKER_DISC_TMO;
+       }
+       /* Cancel Discovery Timer state <hba_state> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0248 Cancel Discovery Timer state x%x "
++                      "%d:0248 Cancel Discovery Timer state x%x "
+                       "Data: x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, vport->port_state,
+-                      vport->fc_flag, vport->fc_plogi_cnt,
+-                      vport->fc_adisc_cnt);
++                      phba->brd_no, phba->hba_state, phba->fc_flag,
++                      phba->fc_plogi_cnt, phba->fc_adisc_cnt);
+       return 0;
+ }
+@@ -1761,18 +1402,15 @@
+  * Return true if iocb matches the specified nport
+  */
+ int
+-lpfc_check_sli_ndlp(struct lpfc_hba *phba,
+-                  struct lpfc_sli_ring *pring,
+-                  struct lpfc_iocbq *iocb,
+-                  struct lpfc_nodelist *ndlp)
++lpfc_check_sli_ndlp(struct lpfc_hba * phba,
++                  struct lpfc_sli_ring * pring,
++                  struct lpfc_iocbq * iocb, struct lpfc_nodelist * ndlp)
+ {
+-      struct lpfc_sli *psli = &phba->sli;
+-      IOCB_t *icmd = &iocb->iocb;
+-      struct lpfc_vport    *vport = ndlp->vport;
+-
+-      if (iocb->vport != vport)
+-              return 0;
++      struct lpfc_sli *psli;
++      IOCB_t *icmd;
++      psli = &phba->sli;
++      icmd = &iocb->iocb;
+       if (pring->ringno == LPFC_ELS_RING) {
+               switch (icmd->ulpCommand) {
+               case CMD_GEN_REQUEST64_CR:
+@@ -1807,7 +1445,7 @@
+  * associated with nlp_rpi in the LPFC_NODELIST entry.
+  */
+ static int
+-lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
++lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+ {
+       LIST_HEAD(completions);
+       struct lpfc_sli *psli;
+@@ -1816,8 +1454,6 @@
+       IOCB_t *icmd;
+       uint32_t rpi, i;
+-      lpfc_fabric_abort_nport(ndlp);
+-
+       /*
+        * Everything that matches on txcmplq will be returned
+        * by firmware with a no rpi error.
+@@ -1829,15 +1465,15 @@
+               for (i = 0; i < psli->num_rings; i++) {
+                       pring = &psli->ring[i];
+-                      spin_lock_irq(&phba->hbalock);
++                      spin_lock_irq(phba->host->host_lock);
+                       list_for_each_entry_safe(iocb, next_iocb, &pring->txq,
+                                               list) {
+                               /*
+                                * Check to see if iocb matches the nport we are
+                                * looking for
+                                */
+-                              if ((lpfc_check_sli_ndlp(phba, pring, iocb,
+-                                                       ndlp))) {
++                              if ((lpfc_check_sli_ndlp
++                                   (phba, pring, iocb, ndlp))) {
+                                       /* It matches, so deque and call compl
+                                          with an error */
+                                       list_move_tail(&iocb->list,
+@@ -1845,22 +1481,22 @@
+                                       pring->txq_cnt--;
+                               }
+                       }
+-                      spin_unlock_irq(&phba->hbalock);
++                      spin_unlock_irq(phba->host->host_lock);
 +
-+      whiteout_dentry =
-+              lookup_one_len(name, hidden_dentry->d_parent,
-+                             dentry->d_name.len + UNIONFS_WHLEN);
-+      if (IS_ERR(whiteout_dentry)) {
-+              err = PTR_ERR(whiteout_dentry);
-+              goto out;
+               }
+       }
+       while (!list_empty(&completions)) {
+               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
+-              list_del_init(&iocb->list);
++              list_del(&iocb->list);
+-              if (!iocb->iocb_cmpl)
+-                      lpfc_sli_release_iocbq(phba, iocb);
+-              else {
++              if (iocb->iocb_cmpl) {
+                       icmd = &iocb->iocb;
+                       icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                       icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+-                      (iocb->iocb_cmpl)(phba, iocb, iocb);
+-              }
++                      (iocb->iocb_cmpl) (phba, iocb, iocb);
++              } else
++                      lpfc_sli_release_iocbq(phba, iocb);
+       }
+       return 0;
+@@ -1876,22 +1512,19 @@
+  * we are waiting to PLOGI back to the remote NPort.
+  */
+ int
+-lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
++lpfc_unreg_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+ {
+-      struct lpfc_hba *phba = vport->phba;
+       LPFC_MBOXQ_t *mbox;
+       int rc;
+       if (ndlp->nlp_rpi) {
+-              mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-              if (mbox) {
+-                      lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox);
+-                      mbox->vport = vport;
+-                      mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-                      rc = lpfc_sli_issue_mbox(phba, mbox,
+-                                               (MBX_NOWAIT | MBX_STOP_IOCB));
++              if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
++                      lpfc_unreg_login(phba, ndlp->nlp_rpi, mbox);
++                      mbox->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
++                      rc = lpfc_sli_issue_mbox
++                                  (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
+                       if (rc == MBX_NOT_FINISHED)
+-                              mempool_free(mbox, phba->mbox_mem_pool);
++                              mempool_free( mbox, phba->mbox_mem_pool);
+               }
+               lpfc_no_rpi(phba, ndlp);
+               ndlp->nlp_rpi = 0;
+@@ -1900,70 +1533,25 @@
+       return 0;
+ }
+-void
+-lpfc_unreg_all_rpis(struct lpfc_vport *vport)
+-{
+-      struct lpfc_hba  *phba  = vport->phba;
+-      LPFC_MBOXQ_t     *mbox;
+-      int rc;
+-
+-      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (mbox) {
+-              lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox);
+-              mbox->vport = vport;
+-              mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-              rc = lpfc_sli_issue_mbox(phba, mbox,
+-                                       (MBX_NOWAIT | MBX_STOP_IOCB));
+-              if (rc == MBX_NOT_FINISHED) {
+-                      mempool_free(mbox, phba->mbox_mem_pool);
+-              }
+-      }
+-}
+-
+-void
+-lpfc_unreg_default_rpis(struct lpfc_vport *vport)
+-{
+-      struct lpfc_hba  *phba  = vport->phba;
+-      LPFC_MBOXQ_t     *mbox;
+-      int rc;
+-
+-      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (mbox) {
+-              lpfc_unreg_did(phba, vport->vpi, 0xffffffff, mbox);
+-              mbox->vport = vport;
+-              mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-              rc = lpfc_sli_issue_mbox(phba, mbox,
+-                                       (MBX_NOWAIT | MBX_STOP_IOCB));
+-              if (rc == MBX_NOT_FINISHED) {
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_VPORT,
+-                                      "%d (%d):1815 Could not issue "
+-                                      "unreg_did (default rpis)\n",
+-                                      phba->brd_no, vport->vpi);
+-                      mempool_free(mbox, phba->mbox_mem_pool);
+-              }
+-      }
+-}
+-
+ /*
+  * Free resources associated with LPFC_NODELIST entry
+  * so it can be freed.
+  */
+ static int
+-lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
++lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+-      LPFC_MBOXQ_t *mb, *nextmb;
++      LPFC_MBOXQ_t       *mb;
++      LPFC_MBOXQ_t       *nextmb;
+       struct lpfc_dmabuf *mp;
+       /* Cleanup node for NPort <nlp_DID> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
+-                      "%d (%d):0900 Cleanup node for NPort x%x "
++                      "%d:0900 Cleanup node for NPort x%x "
+                       "Data: x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, ndlp->nlp_DID, ndlp->nlp_flag,
++                      phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
+                       ndlp->nlp_state, ndlp->nlp_rpi);
+-      lpfc_dequeue_node(vport, ndlp);
++      lpfc_dequeue_node(phba, ndlp);
+       /* cleanup any ndlp on mbox q waiting for reglogin cmpl */
+       if ((mb = phba->sli.mbox_active)) {
+@@ -1974,13 +1562,13 @@
+               }
+       }
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
+               if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
+                  (ndlp == (struct lpfc_nodelist *) mb->context2)) {
+                       mp = (struct lpfc_dmabuf *) (mb->context1);
+                       if (mp) {
+-                              __lpfc_mbuf_free(phba, mp->virt, mp->phys);
++                              lpfc_mbuf_free(phba, mp->virt, mp->phys);
+                               kfree(mp);
+                       }
+                       list_del(&mb->list);
+@@ -1988,27 +1576,20 @@
+                       lpfc_nlp_put(ndlp);
+               }
+       }
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       lpfc_els_abort(phba,ndlp);
+-      spin_lock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag &= ~NLP_DELAY_TMO;
+-      spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+       ndlp->nlp_last_elscmd = 0;
+       del_timer_sync(&ndlp->nlp_delayfunc);
+       if (!list_empty(&ndlp->els_retry_evt.evt_listp))
+               list_del_init(&ndlp->els_retry_evt.evt_listp);
+-      if (!list_empty(&ndlp->dev_loss_evt.evt_listp))
+-              list_del_init(&ndlp->dev_loss_evt.evt_listp);
+-
+-      if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) {
+-              list_del_init(&ndlp->dev_loss_evt.evt_listp);
+-              complete((struct completion *)(ndlp->dev_loss_evt.evt_arg2));
+-      }
+-      lpfc_unreg_rpi(vport, ndlp);
++      lpfc_unreg_rpi(phba, ndlp);
+       return 0;
+ }
+@@ -2019,22 +1600,18 @@
+  * machine, defer the free till we reach the end of the state machine.
+  */
+ static void
+-lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
++lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+ {
+       struct lpfc_rport_data *rdata;
+       if (ndlp->nlp_flag & NLP_DELAY_TMO) {
+-              lpfc_cancel_retry_delay_tmo(vport, ndlp);
++              lpfc_cancel_retry_delay_tmo(phba, ndlp);
+       }
+-      lpfc_cleanup_node(vport, ndlp);
++      lpfc_cleanup_node(phba, ndlp);
+-      /*
+-       * We can get here with a non-NULL ndlp->rport because when we
+-       * unregister a rport we don't break the rport/node linkage.  So if we
+-       * do, make sure we don't leaving any dangling pointers behind.
+-       */
+-      if (ndlp->rport) {
++      if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
++              put_device(&ndlp->rport->dev);
+               rdata = ndlp->rport->dd_data;
+               rdata->pnode = NULL;
+               ndlp->rport = NULL;
+@@ -2042,10 +1619,11 @@
+ }
+ static int
+-lpfc_matchdid(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-            uint32_t did)
++lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
+ {
+-      D_ID mydid, ndlpdid, matchdid;
++      D_ID mydid;
++      D_ID ndlpdid;
++      D_ID matchdid;
+       if (did == Bcast_DID)
+               return 0;
+@@ -2059,7 +1637,7 @@
+               return 1;
+       /* Next check for area/domain identically equals 0 match */
+-      mydid.un.word = vport->fc_myDID;
++      mydid.un.word = phba->fc_myDID;
+       if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) {
+               return 0;
+       }
+@@ -2091,116 +1669,101 @@
+ }
+ /* Search for a nodelist entry */
+-static struct lpfc_nodelist *
+-__lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
++struct lpfc_nodelist *
++lpfc_findnode_did(struct lpfc_hba *phba, uint32_t did)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+       struct lpfc_nodelist *ndlp;
+       uint32_t data1;
+-      list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
+-              if (lpfc_matchdid(vport, ndlp, did)) {
++      spin_lock_irq(phba->host->host_lock);
++      list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
++              if (lpfc_matchdid(phba, ndlp, did)) {
+                       data1 = (((uint32_t) ndlp->nlp_state << 24) |
+                                ((uint32_t) ndlp->nlp_xri << 16) |
+                                ((uint32_t) ndlp->nlp_type << 8) |
+                                ((uint32_t) ndlp->nlp_rpi & 0xff));
+                       lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
+-                                      "%d (%d):0929 FIND node DID "
++                                      "%d:0929 FIND node DID "
+                                       " Data: x%p x%x x%x x%x\n",
+-                                      phba->brd_no, vport->vpi,
++                                      phba->brd_no,
+                                       ndlp, ndlp->nlp_DID,
+                                       ndlp->nlp_flag, data1);
++                      spin_unlock_irq(phba->host->host_lock);
+                       return ndlp;
+               }
+       }
++      spin_unlock_irq(phba->host->host_lock);
+       /* FIND node did <did> NOT FOUND */
+       lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
+-                      "%d (%d):0932 FIND node did x%x NOT FOUND.\n",
+-                      phba->brd_no, vport->vpi, did);
++                      "%d:0932 FIND node did x%x NOT FOUND.\n",
++                      phba->brd_no, did);
+       return NULL;
+ }
+ struct lpfc_nodelist *
+-lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
+-{
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_nodelist *ndlp;
+-
+-      spin_lock_irq(shost->host_lock);
+-      ndlp = __lpfc_findnode_did(vport, did);
+-      spin_unlock_irq(shost->host_lock);
+-      return ndlp;
+-}
+-
+-struct lpfc_nodelist *
+-lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
++lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+       struct lpfc_nodelist *ndlp;
+-      ndlp = lpfc_findnode_did(vport, did);
++      ndlp = lpfc_findnode_did(phba, did);
+       if (!ndlp) {
+-              if ((vport->fc_flag & FC_RSCN_MODE) != 0 &&
+-                  lpfc_rscn_payload_check(vport, did) == 0)
++              if ((phba->fc_flag & FC_RSCN_MODE) &&
++                 ((lpfc_rscn_payload_check(phba, did) == 0)))
+                       return NULL;
+               ndlp = (struct lpfc_nodelist *)
+-                   mempool_alloc(vport->phba->nlp_mem_pool, GFP_KERNEL);
++                   mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+               if (!ndlp)
+                       return NULL;
+-              lpfc_nlp_init(vport, ndlp, did);
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+-              spin_lock_irq(shost->host_lock);
++              lpfc_nlp_init(phba, ndlp, did);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+-              spin_unlock_irq(shost->host_lock);
+               return ndlp;
+       }
+-      if (vport->fc_flag & FC_RSCN_MODE) {
+-              if (lpfc_rscn_payload_check(vport, did)) {
+-                      spin_lock_irq(shost->host_lock);
++      if (phba->fc_flag & FC_RSCN_MODE) {
++              if (lpfc_rscn_payload_check(phba, did)) {
+                       ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+-                      spin_unlock_irq(shost->host_lock);
+                       /* Since this node is marked for discovery,
+                        * delay timeout is not needed.
+                        */
+                       if (ndlp->nlp_flag & NLP_DELAY_TMO)
+-                              lpfc_cancel_retry_delay_tmo(vport, ndlp);
++                              lpfc_cancel_retry_delay_tmo(phba, ndlp);
+               } else
+                       ndlp = NULL;
+       } else {
+               if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE ||
+                   ndlp->nlp_state == NLP_STE_PLOGI_ISSUE)
+                       return NULL;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+-              spin_lock_irq(shost->host_lock);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+               ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+-              spin_unlock_irq(shost->host_lock);
+       }
+       return ndlp;
+ }
+ /* Build a list of nodes to discover based on the loopmap */
+ void
+-lpfc_disc_list_loopmap(struct lpfc_vport *vport)
++lpfc_disc_list_loopmap(struct lpfc_hba * phba)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+       int j;
+       uint32_t alpa, index;
+-      if (!lpfc_is_link_up(phba))
++      if (phba->hba_state <= LPFC_LINK_DOWN) {
+               return;
+-
+-      if (phba->fc_topology != TOPOLOGY_LOOP)
 +      }
-+
-+      if (!whiteout_dentry->d_inode) {
-+              dput(whiteout_dentry);
-+              whiteout_dentry = NULL;
-+      } else {
-+              /*
-+               * found a .wh.foo entry, unlink it and then call
-+               * vfs_symlink().
-+               */
-+              hidden_dir_dentry = lock_parent(whiteout_dentry);
-+
-+              if (!(err = is_robranch_super(dentry->d_sb, bstart)))
-+                      err = vfs_unlink(hidden_dir_dentry->d_inode,
-+                                       whiteout_dentry);
-+              dput(whiteout_dentry);
-+
-+              fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
-+              /* propagate number of hard-links */
-+              dir->i_nlink = unionfs_get_nlinks(dir);
-+
-+              unlock_dir(hidden_dir_dentry);
-+
-+              if (err) {
-+                      /* exit if the error returned was NOT -EROFS */
-+                      if (!IS_COPYUP_ERR(err))
-+                              goto out;
-+                      /*
-+                       * should now try to create symlink in the another
-+                       * branch.
-+                       */
-+                      bstart--;
-+              }
++      if (phba->fc_topology != TOPOLOGY_LOOP) {
+               return;
 +      }
+       /* Check for loop map present or not */
+       if (phba->alpa_map[0]) {
+               for (j = 1; j <= phba->alpa_map[0]; j++) {
+                       alpa = phba->alpa_map[j];
+-                      if (((vport->fc_myDID & 0xff) == alpa) || (alpa == 0))
 +
-+      /*
-+       * deleted whiteout if it was present, now do a normal vfs_symlink()
-+       * with possible recursive directory creation
-+       */
-+      for (bindex = bstart; bindex >= 0; bindex--) {
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!hidden_dentry) {
-+                      /*
-+                       * if hidden_dentry is NULL, create the entire
-+                       * dentry directory structure in branch 'bindex'.
-+                       * hidden_dentry will NOT be null when bindex ==
-+                       * bstart because lookup passed as a negative
-+                       * unionfs dentry pointing to a lone negative
-+                       * underlying dentry
-+                       */
-+                      hidden_dentry = create_parents(dir, dentry, bindex);
-+                      if (!hidden_dentry || IS_ERR(hidden_dentry)) {
-+                              if (IS_ERR(hidden_dentry))
-+                                      err = PTR_ERR(hidden_dentry);
-+
-+                              printk(KERN_DEBUG "unionfs: hidden dentry "
-+                                     "NULL (or error) for bindex = %d\n",
-+                                     bindex);
-+                              continue;
-+                      }
-+              }
-+
-+              hidden_dir_dentry = lock_parent(hidden_dentry);
-+
-+              if (!(err = is_robranch_super(dentry->d_sb, bindex))) {
-+                      mode = S_IALLUGO;
-+                      err =
-+                              vfs_symlink(hidden_dir_dentry->d_inode,
-+                                          hidden_dentry, symname, mode);
-+              }
-+              unlock_dir(hidden_dir_dentry);
-+
-+              if (err || !hidden_dentry->d_inode) {
-+                      /*
-+                       * break out of for loop if error returned was NOT
-+                       * -EROFS.
-+                       */
-+                      if (!IS_COPYUP_ERR(err))
-+                              break;
-+              } else {
-+                      err = unionfs_interpose(dentry, dir->i_sb, 0);
-+                      if (!err) {
-+                              fsstack_copy_attr_times(dir,
-+                                                      hidden_dir_dentry->
-+                                                      d_inode);
-+                              fsstack_copy_inode_size(dir,
-+                                                      hidden_dir_dentry->
-+                                                      d_inode);
-+                              /*
-+                               * update number of links on parent
-+                               * directory.
-+                               */
-+                              dir->i_nlink = unionfs_get_nlinks(dir);
++                      if (((phba->fc_myDID & 0xff) == alpa) || (alpa == 0)) {
+                               continue;
+-                      lpfc_setup_disc_node(vport, alpa);
 +                      }
-+                      break;
-+              }
-+      }
-+
-+out:
-+      if (!dentry->d_inode)
-+              d_drop(dentry);
-+
-+      kfree(name);
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+static int unionfs_mkdir(struct inode *parent, struct dentry *dentry, int mode)
-+{
-+      int err = 0;
-+      struct dentry *hidden_dentry = NULL, *whiteout_dentry = NULL;
-+      struct dentry *hidden_parent_dentry = NULL;
-+      int bindex = 0, bstart;
-+      char *name = NULL;
-+      int whiteout_unlinked = 0;
-+      struct sioq_args args;
-+
-+      unionfs_read_lock(dentry->d_sb);
-+      unionfs_lock_dentry(dentry);
-+
-+      if (dentry->d_inode &&
-+          !__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      bstart = dbstart(dentry);
-+
-+      hidden_dentry = unionfs_lower_dentry(dentry);
-+
-+      /*
-+       * check if whiteout exists in this branch, i.e. lookup .wh.foo
-+       * first.
-+       */
-+      name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
-+      if (IS_ERR(name)) {
-+              err = PTR_ERR(name);
-+              goto out;
++                      lpfc_setup_disc_node(phba, alpa);
+               }
+       } else {
+               /* No alpamap, so try all alpa's */
+@@ -2213,167 +1776,113 @@
+                       else
+                               index = FC_MAXLOOP - j - 1;
+                       alpa = lpfcAlpaArray[index];
+-                      if ((vport->fc_myDID & 0xff) == alpa)
++                      if ((phba->fc_myDID & 0xff) == alpa) {
+                               continue;
+-                      lpfc_setup_disc_node(vport, alpa);
+-              }
+-      }
+-      return;
+-}
+-
+-void
+-lpfc_issue_clear_la(struct lpfc_hba *phba, struct lpfc_vport *vport)
+-{
+-      LPFC_MBOXQ_t *mbox;
+-      struct lpfc_sli *psli = &phba->sli;
+-      struct lpfc_sli_ring *extra_ring = &psli->ring[psli->extra_ring];
+-      struct lpfc_sli_ring *fcp_ring   = &psli->ring[psli->fcp_ring];
+-      struct lpfc_sli_ring *next_ring  = &psli->ring[psli->next_ring];
+-      int  rc;
+-
+-      /*
+-       * if it's not a physical port or if we already send
+-       * clear_la then don't send it.
+-       */
+-      if ((phba->link_state >= LPFC_CLEAR_LA) ||
+-          (vport->port_type != LPFC_PHYSICAL_PORT))
+-              return;
+-
+-                      /* Link up discovery */
+-      if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) != NULL) {
+-              phba->link_state = LPFC_CLEAR_LA;
+-              lpfc_clear_la(phba, mbox);
+-              mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
+-              mbox->vport = vport;
+-              rc = lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT |
+-                                                    MBX_STOP_IOCB));
+-              if (rc == MBX_NOT_FINISHED) {
+-                      mempool_free(mbox, phba->mbox_mem_pool);
+-                      lpfc_disc_flush_list(vport);
+-                      extra_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
+-                      fcp_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
+-                      next_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
+-                      phba->link_state = LPFC_HBA_ERROR;
+-              }
+       }
+-}
+-
+-/* Reg_vpi to tell firmware to resume normal operations */
+-void
+-lpfc_issue_reg_vpi(struct lpfc_hba *phba, struct lpfc_vport *vport)
+-{
+-      LPFC_MBOXQ_t *regvpimbox;
+-      regvpimbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (regvpimbox) {
+-              lpfc_reg_vpi(phba, vport->vpi, vport->fc_myDID, regvpimbox);
+-              regvpimbox->mbox_cmpl = lpfc_mbx_cmpl_reg_vpi;
+-              regvpimbox->vport = vport;
+-              if (lpfc_sli_issue_mbox(phba, regvpimbox,
+-                                      (MBX_NOWAIT | MBX_STOP_IOCB))
+-                                      == MBX_NOT_FINISHED) {
+-                      mempool_free(regvpimbox, phba->mbox_mem_pool);
++                      lpfc_setup_disc_node(phba, alpa);
+               }
+       }
++      return;
+ }
+-/* Start Link up / RSCN discovery on NPR nodes */
++/* Start Link up / RSCN discovery on NPR list */
+ void
+-lpfc_disc_start(struct lpfc_vport *vport)
++lpfc_disc_start(struct lpfc_hba * phba)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
++      struct lpfc_sli *psli;
++      LPFC_MBOXQ_t *mbox;
++      struct lpfc_nodelist *ndlp, *next_ndlp;
+       uint32_t num_sent;
+       uint32_t clear_la_pending;
+       int did_changed;
++      int rc;
+-      if (!lpfc_is_link_up(phba))
+-              return;
++      psli = &phba->sli;
+-      if (phba->link_state == LPFC_CLEAR_LA)
++      if (phba->hba_state <= LPFC_LINK_DOWN) {
++              return;
 +      }
-+
-+      whiteout_dentry = lookup_one_len(name, hidden_dentry->d_parent,
-+                                       dentry->d_name.len + UNIONFS_WHLEN);
-+      if (IS_ERR(whiteout_dentry)) {
-+              err = PTR_ERR(whiteout_dentry);
-+              goto out;
++      if (phba->hba_state == LPFC_CLEAR_LA)
+               clear_la_pending = 1;
+       else
+               clear_la_pending = 0;
+-      if (vport->port_state < LPFC_VPORT_READY)
+-              vport->port_state = LPFC_DISC_AUTH;
+-
+-      lpfc_set_disctmo(vport);
++      if (phba->hba_state < LPFC_HBA_READY) {
++              phba->hba_state = LPFC_DISC_AUTH;
 +      }
-+
-+      if (!whiteout_dentry->d_inode) {
-+              dput(whiteout_dentry);
-+              whiteout_dentry = NULL;
++      lpfc_set_disctmo(phba);
+-      if (vport->fc_prevDID == vport->fc_myDID)
++      if (phba->fc_prevDID == phba->fc_myDID) {
+               did_changed = 0;
+-      else
 +      } else {
-+              hidden_parent_dentry = lock_parent(whiteout_dentry);
-+
-+              /* found a.wh.foo entry, remove it then do vfs_mkdir */
-+              if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
-+                      args.unlink.parent = hidden_parent_dentry->d_inode;
-+                      args.unlink.dentry = whiteout_dentry;
-+                      run_sioq(__unionfs_unlink, &args);
-+                      err = args.err;
-+              }
-+              dput(whiteout_dentry);
-+
-+              unlock_dir(hidden_parent_dentry);
-+
-+              if (err) {
-+                      /* exit if the error returned was NOT -EROFS */
-+                      if (!IS_COPYUP_ERR(err))
-+                              goto out;
-+                      bstart--;
-+              } else
-+                      whiteout_unlinked = 1;
+               did_changed = 1;
+-
+-      vport->fc_prevDID = vport->fc_myDID;
+-      vport->num_disc_nodes = 0;
 +      }
-+
-+      for (bindex = bstart; bindex >= 0; bindex--) {
-+              int i;
-+              int bend = dbend(dentry);
-+
-+              if (is_robranch_super(dentry->d_sb, bindex))
-+                      continue;
-+
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!hidden_dentry) {
-+                      hidden_dentry = create_parents(parent, dentry, bindex);
-+                      if (!hidden_dentry || IS_ERR(hidden_dentry)) {
-+                              printk(KERN_DEBUG "unionfs: hidden dentry "
-+                                     " NULL for bindex = %d\n", bindex);
-+                              continue;
-+                      }
-+              }
-+
-+              hidden_parent_dentry = lock_parent(hidden_dentry);
-+
-+              if (IS_ERR(hidden_parent_dentry)) {
-+                      err = PTR_ERR(hidden_parent_dentry);
-+                      goto out;
-+              }
-+
-+              err = vfs_mkdir(hidden_parent_dentry->d_inode, hidden_dentry,
-+                              mode);
-+
-+              unlock_dir(hidden_parent_dentry);
-+
-+              /* did the mkdir succeed? */
-+              if (err)
-+                      break;
-+
-+              for (i = bindex + 1; i < bend; i++) {
-+                      if (unionfs_lower_dentry_idx(dentry, i)) {
-+                              dput(unionfs_lower_dentry_idx(dentry, i));
-+                              unionfs_set_lower_dentry_idx(dentry, i, NULL);
-+                      }
-+              }
-+              set_dbend(dentry, bindex);
-+
-+              err = unionfs_interpose(dentry, parent->i_sb, 0);
-+              if (!err) {
-+                      fsstack_copy_attr_times(parent,
-+                                              hidden_parent_dentry->d_inode);
-+                      fsstack_copy_inode_size(parent,
-+                                              hidden_parent_dentry->d_inode);
-+
-+                      /* update number of links on parent directory */
-+                      parent->i_nlink = unionfs_get_nlinks(parent);
-+              }
-+
-+              err = make_dir_opaque(dentry, dbstart(dentry));
-+              if (err) {
-+                      printk(KERN_ERR "unionfs: mkdir: error creating "
-+                             ".wh.__dir_opaque: %d\n", err);
-+                      goto out;
++      phba->fc_prevDID = phba->fc_myDID;
++      phba->num_disc_nodes = 0;
+       /* Start Discovery state <hba_state> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0202 Start Discovery hba state x%x "
++                      "%d:0202 Start Discovery hba state x%x "
+                       "Data: x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi, vport->port_state,
+-                      vport->fc_flag, vport->fc_plogi_cnt,
+-                      vport->fc_adisc_cnt);
++                      phba->brd_no, phba->hba_state, phba->fc_flag,
++                      phba->fc_plogi_cnt, phba->fc_adisc_cnt);
++
++      /* If our did changed, we MUST do PLOGI */
++      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) {
++              if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
++                  (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
++                  did_changed) {
++                      spin_lock_irq(phba->host->host_lock);
++                      ndlp->nlp_flag &= ~NLP_NPR_ADISC;
++                      spin_unlock_irq(phba->host->host_lock);
 +              }
-+
-+              /* we are done! */
-+              break;
-+      }
-+
-+out:
-+      if (!dentry->d_inode)
-+              d_drop(dentry);
-+
-+      kfree(name);
-+
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
-+                       dev_t dev)
-+{
-+      int err = 0;
-+      struct dentry *hidden_dentry = NULL, *whiteout_dentry = NULL;
-+      struct dentry *hidden_parent_dentry = NULL;
-+      int bindex = 0, bstart;
-+      char *name = NULL;
-+      int whiteout_unlinked = 0;
-+
-+      unionfs_read_lock(dentry->d_sb);
-+      unionfs_lock_dentry(dentry);
-+
-+      if (dentry->d_inode &&
-+          !__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      bstart = dbstart(dentry);
-+
-+      hidden_dentry = unionfs_lower_dentry(dentry);
-+
-+      /*
-+       * check if whiteout exists in this branch, i.e. lookup .wh.foo
-+       * first.
-+       */
-+      name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
-+      if (IS_ERR(name)) {
-+              err = PTR_ERR(name);
-+              goto out;
 +      }
-+
-+      whiteout_dentry = lookup_one_len(name, hidden_dentry->d_parent,
-+                                       dentry->d_name.len + UNIONFS_WHLEN);
-+      if (IS_ERR(whiteout_dentry)) {
-+              err = PTR_ERR(whiteout_dentry);
-+              goto out;
-+      }
-+
-+      if (!whiteout_dentry->d_inode) {
-+              dput(whiteout_dentry);
-+              whiteout_dentry = NULL;
-+      } else {
-+              /* found .wh.foo, unlink it */
-+              hidden_parent_dentry = lock_parent(whiteout_dentry);
-+
-+              /* found a.wh.foo entry, remove it then do vfs_mkdir */
-+              if (!(err = is_robranch_super(dentry->d_sb, bstart)))
-+                      err = vfs_unlink(hidden_parent_dentry->d_inode,
-+                                       whiteout_dentry);
-+              dput(whiteout_dentry);
-+
-+              unlock_dir(hidden_parent_dentry);
-+
-+              if (err) {
-+                      if (!IS_COPYUP_ERR(err))
-+                              goto out;
-+
-+                      bstart--;
+       /* First do ADISCs - if any */
+-      num_sent = lpfc_els_disc_adisc(vport);
++      num_sent = lpfc_els_disc_adisc(phba);
+       if (num_sent)
+               return;
+-      /*
+-       * For SLI3, cmpl_reg_vpi will set port_state to READY, and
+-       * continue discovery.
+-       */
+-      if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
+-          !(vport->fc_flag & FC_RSCN_MODE)) {
+-              lpfc_issue_reg_vpi(phba, vport);
+-              return;
+-      }
+-
+-      /*
+-       * For SLI2, we need to set port_state to READY and continue
+-       * discovery.
+-       */
+-      if (vport->port_state < LPFC_VPORT_READY && !clear_la_pending) {
++      if ((phba->hba_state < LPFC_HBA_READY) && (!clear_la_pending)) {
+               /* If we get here, there is nothing to ADISC */
+-              if (vport->port_type == LPFC_PHYSICAL_PORT)
+-                      lpfc_issue_clear_la(phba, vport);
+-
+-              if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) {
+-                      vport->num_disc_nodes = 0;
+-                      /* go thru NPR nodes and issue ELS PLOGIs */
+-                      if (vport->fc_npr_cnt)
+-                              lpfc_els_disc_plogi(vport);
+-
+-                      if (!vport->num_disc_nodes) {
+-                              spin_lock_irq(shost->host_lock);
+-                              vport->fc_flag &= ~FC_NDISC_ACTIVE;
+-                              spin_unlock_irq(shost->host_lock);
+-                              lpfc_can_disctmo(vport);
++              if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
++                      phba->hba_state = LPFC_CLEAR_LA;
++                      lpfc_clear_la(phba, mbox);
++                      mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
++                      rc = lpfc_sli_issue_mbox(phba, mbox,
++                                               (MBX_NOWAIT | MBX_STOP_IOCB));
++                      if (rc == MBX_NOT_FINISHED) {
++                              mempool_free( mbox, phba->mbox_mem_pool);
++                              lpfc_disc_flush_list(phba);
++                              psli->ring[(psli->extra_ring)].flag &=
++                                      ~LPFC_STOP_IOCB_EVENT;
++                              psli->ring[(psli->fcp_ring)].flag &=
++                                      ~LPFC_STOP_IOCB_EVENT;
++                              psli->ring[(psli->next_ring)].flag &=
++                                      ~LPFC_STOP_IOCB_EVENT;
++                              phba->hba_state = LPFC_HBA_READY;
+                       }
+               }
+-              vport->port_state = LPFC_VPORT_READY;
+       } else {
+               /* Next do PLOGIs - if any */
+-              num_sent = lpfc_els_disc_plogi(vport);
++              num_sent = lpfc_els_disc_plogi(phba);
+               if (num_sent)
+                       return;
+-              if (vport->fc_flag & FC_RSCN_MODE) {
++              if (phba->fc_flag & FC_RSCN_MODE) {
+                       /* Check to see if more RSCNs came in while we
+                        * were processing this one.
+                        */
+-                      if ((vport->fc_rscn_id_cnt == 0) &&
+-                          (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
+-                              spin_lock_irq(shost->host_lock);
+-                              vport->fc_flag &= ~FC_RSCN_MODE;
+-                              spin_unlock_irq(shost->host_lock);
+-                              lpfc_can_disctmo(vport);
++                      if ((phba->fc_rscn_id_cnt == 0) &&
++                          (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
++                              spin_lock_irq(phba->host->host_lock);
++                              phba->fc_flag &= ~FC_RSCN_MODE;
++                              spin_unlock_irq(phba->host->host_lock);
+                       } else
+-                              lpfc_els_handle_rscn(vport);
++                              lpfc_els_handle_rscn(phba);
+               }
+       }
+       return;
+@@ -2384,7 +1893,7 @@
+  *  ring the match the sppecified nodelist.
+  */
+ static void
+-lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
++lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+ {
+       LIST_HEAD(completions);
+       struct lpfc_sli *psli;
+@@ -2398,7 +1907,7 @@
+       /* Error matching iocb on txq or txcmplq
+        * First check the txq.
+        */
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
+               if (iocb->context1 != ndlp) {
+                       continue;
+@@ -2418,36 +1927,36 @@
+                       continue;
+               }
+               icmd = &iocb->iocb;
+-              if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR ||
+-                  icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX) {
++              if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) ||
++                  (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) {
+                       lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+               }
+       }
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       while (!list_empty(&completions)) {
+               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
+-              list_del_init(&iocb->list);
++              list_del(&iocb->list);
+-              if (!iocb->iocb_cmpl)
+-                      lpfc_sli_release_iocbq(phba, iocb);
+-              else {
++              if (iocb->iocb_cmpl) {
+                       icmd = &iocb->iocb;
+                       icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                       icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+                       (iocb->iocb_cmpl) (phba, iocb, iocb);
 +              } else
-+                      whiteout_unlinked = 1;
-+      }
-+
-+      for (bindex = bstart; bindex >= 0; bindex--) {
-+              if (is_robranch_super(dentry->d_sb, bindex))
-+                      continue;
-+
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!hidden_dentry) {
-+                      hidden_dentry = create_parents(dir, dentry, bindex);
-+                      if (IS_ERR(hidden_dentry)) {
-+                              printk(KERN_DEBUG "unionfs: failed to create "
-+                                     "parents on %d, err = %ld\n",
-+                                     bindex, PTR_ERR(hidden_dentry));
-+                              continue;
-+                      }
-+              }
-+
-+              hidden_parent_dentry = lock_parent(hidden_dentry);
-+              if (IS_ERR(hidden_parent_dentry)) {
-+                      err = PTR_ERR(hidden_parent_dentry);
-+                      goto out;
-+              }
-+
-+              err = vfs_mknod(hidden_parent_dentry->d_inode,
-+                              hidden_dentry, mode, dev);
-+
-+              if (err) {
-+                      unlock_dir(hidden_parent_dentry);
-+                      break;
-+              }
-+
-+              err = unionfs_interpose(dentry, dir->i_sb, 0);
-+              if (!err) {
-+                      fsstack_copy_attr_times(dir,
-+                                              hidden_parent_dentry->d_inode);
-+                      fsstack_copy_inode_size(dir,
-+                                              hidden_parent_dentry->d_inode);
-+                      /* update number of links on parent directory */
-+                      dir->i_nlink = unionfs_get_nlinks(dir);
-+              }
-+              unlock_dir(hidden_parent_dentry);
-+
-+              break;
-+      }
-+
-+out:
-+      if (!dentry->d_inode)
-+              d_drop(dentry);
-+
-+      kfree(name);
-+
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+static int unionfs_readlink(struct dentry *dentry, char __user *buf,
-+                          int bufsiz)
-+{
-+      int err;
-+      struct dentry *hidden_dentry;
-+
-+      unionfs_read_lock(dentry->d_sb);
-+      unionfs_lock_dentry(dentry);
-+
-+      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      hidden_dentry = unionfs_lower_dentry(dentry);
-+
-+      if (!hidden_dentry->d_inode->i_op ||
-+          !hidden_dentry->d_inode->i_op->readlink) {
-+              err = -EINVAL;
-+              goto out;
-+      }
-+
-+      err = hidden_dentry->d_inode->i_op->readlink(hidden_dentry,
-+                                                   buf, bufsiz);
-+      if (err > 0)
-+              fsstack_copy_attr_atime(dentry->d_inode,
-+                                      hidden_dentry->d_inode);
-+
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-+
-+/*
-+ * Check if dentry is valid or not, as per our generation numbers.
-+ * @dentry: dentry to check.
-+ * Returns 1 (valid) or 0 (invalid/stale).
-+ */
-+static inline int is_valid_dentry(struct dentry *dentry)
-+{
-+      BUG_ON(!UNIONFS_D(dentry));
-+      BUG_ON(!UNIONFS_SB(dentry->d_sb));
-+      return (atomic_read(&UNIONFS_D(dentry)->generation) ==
-+                      atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
-+}
-+
-+/* We don't lock the dentry here, because readlink does the heavy lifting. */
-+static void *unionfs_follow_link(struct dentry *dentry, struct nameidata *nd)
-+{
-+      char *buf;
-+      int len = PAGE_SIZE, err;
-+      mm_segment_t old_fs;
-+
-+      /*
-+       * FIXME: Really nasty...we can get called from two distinct places:
-+       * 1) read_link - locks the dentry
-+       * 2) VFS lookup code - does NOT lock the dentry
-+       *
-+       * The proper thing would be to call dentry revalidate. It however
-+       * expects a locked dentry, and we can't cleanly guarantee that.
-+       */
-+      BUG_ON(!is_valid_dentry(dentry));
-+
-+      unionfs_read_lock(dentry->d_sb);
-+
-+      /* This is freed by the put_link method assuming a successful call. */
-+      buf = kmalloc(len, GFP_KERNEL);
-+      if (!buf) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      /* read the symlink, and then we will follow it */
-+      old_fs = get_fs();
-+      set_fs(KERNEL_DS);
-+      err = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len);
-+      set_fs(old_fs);
-+      if (err < 0) {
-+              kfree(buf);
-+              buf = NULL;
-+              goto out;
-+      }
-+      buf[err] = 0;
-+      nd_set_link(nd, buf);
-+      err = 0;
-+
-+out:
-+      unionfs_read_unlock(dentry->d_sb);
-+      return ERR_PTR(err);
-+}
-+
-+/* FIXME: We may not have to lock here */
-+static void unionfs_put_link(struct dentry *dentry, struct nameidata *nd,
-+                           void *cookie)
-+{
-+      unionfs_read_lock(dentry->d_sb);
-+      kfree(nd_get_link(nd));
-+      unionfs_read_unlock(dentry->d_sb);
-+}
++                      lpfc_sli_release_iocbq(phba, iocb);
+       }
+-      }
 +
-+/*
-+ * Basically copied from the kernel vfs permission(), but we've changed
-+ * the following:
-+ *   (1) the IS_RDONLY check is skipped, and
-+ *   (2) if you set the mount option `mode=nfsro', we assume that -EACCES
-+ *   means that the export is read-only and we should check standard Unix
-+ *   permissions.  This means that NFS ACL checks (or other advanced
-+ *   permission features) are bypassed. Note however, that we do call
-+ *   security_inode_permission, and therefore security inside SELinux, etc.
-+ *   are performed.
-+ */
-+static int inode_permission(struct inode *inode, int mask,
-+                          struct nameidata *nd, int bindex)
-+{
-+      int retval, submask;
-+
-+      if (mask & MAY_WRITE) {
-+              /* The first branch is allowed to be really readonly. */
-+              if (bindex == 0) {
-+                      umode_t mode = inode->i_mode;
-+                      if (IS_RDONLY(inode) &&
-+                          (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
-+                              return -EROFS;
-+              }
-+              /*
-+               * Nobody gets write access to an immutable file.
-+               */
-+              if (IS_IMMUTABLE(inode))
-+                      return -EACCES;
-+      }
++      return;
+ }
+ void
+-lpfc_disc_flush_list(struct lpfc_vport *vport)
++lpfc_disc_flush_list(struct lpfc_hba * phba)
+ {
+       struct lpfc_nodelist *ndlp, *next_ndlp;
+-      struct lpfc_hba *phba = vport->phba;
+-      if (vport->fc_plogi_cnt || vport->fc_adisc_cnt) {
+-              list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
++      if (phba->fc_plogi_cnt || phba->fc_adisc_cnt) {
++              list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+                                        nlp_listp) {
+                       if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE ||
+                           ndlp->nlp_state == NLP_STE_ADISC_ISSUE) {
+@@ -2458,14 +1967,6 @@
+       }
+ }
+-void
+-lpfc_cleanup_discovery_resources(struct lpfc_vport *vport)
+-{
+-      lpfc_els_flush_rscn(vport);
+-      lpfc_els_flush_cmd(vport);
+-      lpfc_disc_flush_list(vport);
+-}
+-
+ /*****************************************************************************/
+ /*
+  * NAME:     lpfc_disc_timeout
+@@ -2484,154 +1985,158 @@
+ void
+ lpfc_disc_timeout(unsigned long ptr)
+ {
+-      struct lpfc_vport *vport = (struct lpfc_vport *) ptr;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
+       unsigned long flags = 0;
+       if (unlikely(!phba))
+               return;
+-      if ((vport->work_port_events & WORKER_DISC_TMO) == 0) {
+-              spin_lock_irqsave(&vport->work_port_lock, flags);
+-              vport->work_port_events |= WORKER_DISC_TMO;
+-              spin_unlock_irqrestore(&vport->work_port_lock, flags);
+-
+-              spin_lock_irqsave(&phba->hbalock, flags);
++      spin_lock_irqsave(phba->host->host_lock, flags);
++      if (!(phba->work_hba_events & WORKER_DISC_TMO)) {
++              phba->work_hba_events |= WORKER_DISC_TMO;
+               if (phba->work_wait)
+-                      lpfc_worker_wake_up(phba);
+-              spin_unlock_irqrestore(&phba->hbalock, flags);
++                      wake_up(phba->work_wait);
+       }
++      spin_unlock_irqrestore(phba->host->host_lock, flags);
+       return;
+ }
+ static void
+-lpfc_disc_timeout_handler(struct lpfc_vport *vport)
++lpfc_disc_timeout_handler(struct lpfc_hba *phba)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+-      struct lpfc_sli  *psli = &phba->sli;
++      struct lpfc_sli *psli;
+       struct lpfc_nodelist *ndlp, *next_ndlp;
+-      LPFC_MBOXQ_t *initlinkmbox;
++      LPFC_MBOXQ_t *clearlambox, *initlinkmbox;
+       int rc, clrlaerr = 0;
+-      if (!(vport->fc_flag & FC_DISC_TMO))
++      if (unlikely(!phba))
++              return;
 +
-+      /* Ordinary permission routines do not understand MAY_APPEND. */
-+      submask = mask & ~MAY_APPEND;
-+      if (inode->i_op && inode->i_op->permission) {
-+              retval = inode->i_op->permission(inode, submask, nd);
-+              if ((retval == -EACCES) && (submask & MAY_WRITE) &&
-+                  (!strcmp("nfs", (inode)->i_sb->s_type->name)) &&
-+                  (nd) && (nd->mnt) && (nd->mnt->mnt_sb)) {
-+                      int perms;
-+                      perms = branchperms(nd->mnt->mnt_sb, bindex);
-+                      if (perms & MAY_NFSRO)
-+                              retval = generic_permission(inode, submask,
-+                                                          NULL);
++      if (!(phba->fc_flag & FC_DISC_TMO))
+               return;
+-      spin_lock_irq(shost->host_lock);
+-      vport->fc_flag &= ~FC_DISC_TMO;
+-      spin_unlock_irq(shost->host_lock);
++      psli = &phba->sli;
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+-              "disc timeout:    state:x%x rtry:x%x flg:x%x",
+-              vport->port_state, vport->fc_ns_retry, vport->fc_flag);
++      spin_lock_irq(phba->host->host_lock);
++      phba->fc_flag &= ~FC_DISC_TMO;
++      spin_unlock_irq(phba->host->host_lock);
+-      switch (vport->port_state) {
++      switch (phba->hba_state) {
+       case LPFC_LOCAL_CFG_LINK:
+-      /* port_state is identically  LPFC_LOCAL_CFG_LINK while waiting for
+-       * FAN
+-       */
++      /* hba_state is identically LPFC_LOCAL_CFG_LINK while waiting for FAN */
+               /* FAN timeout */
+-              lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY,
+-                              "%d (%d):0221 FAN timeout\n",
+-                              phba->brd_no, vport->vpi);
++              lpfc_printf_log(phba,
++                               KERN_WARNING,
++                               LOG_DISCOVERY,
++                               "%d:0221 FAN timeout\n",
++                               phba->brd_no);
+               /* Start discovery by sending FLOGI, clean up old rpis */
+-              list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
++              list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes,
+                                        nlp_listp) {
+                       if (ndlp->nlp_state != NLP_STE_NPR_NODE)
+                               continue;
+                       if (ndlp->nlp_type & NLP_FABRIC) {
+                               /* Clean up the ndlp on Fabric connections */
+-                              lpfc_drop_node(vport, ndlp);
++                              lpfc_drop_node(phba, ndlp);
+                       } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
+                               /* Fail outstanding IO now since device
+                                * is marked for PLOGI.
+                                */
+-                              lpfc_unreg_rpi(vport, ndlp);
++                              lpfc_unreg_rpi(phba, ndlp);
+                       }
+               }
+-              if (vport->port_state != LPFC_FLOGI) {
+-                      vport->port_state = LPFC_FLOGI;
+-                      lpfc_set_disctmo(vport);
+-                      lpfc_initial_flogi(vport);
+-              }
++              phba->hba_state = LPFC_FLOGI;
++              lpfc_set_disctmo(phba);
++              lpfc_initial_flogi(phba);
+               break;
+-      case LPFC_FDISC:
+       case LPFC_FLOGI:
+-      /* port_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */
++      /* hba_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */
+               /* Initial FLOGI timeout */
+-              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                              "%d (%d):0222 Initial %s timeout\n",
+-                              phba->brd_no, vport->vpi,
+-                              vport->vpi ? "FLOGI" : "FDISC");
++              lpfc_printf_log(phba,
++                               KERN_ERR,
++                               LOG_DISCOVERY,
++                               "%d:0222 Initial FLOGI timeout\n",
++                               phba->brd_no);
+               /* Assume no Fabric and go on with discovery.
+                * Check for outstanding ELS FLOGI to abort.
+                */
+               /* FLOGI failed, so just use loop map to make discovery list */
+-              lpfc_disc_list_loopmap(vport);
++              lpfc_disc_list_loopmap(phba);
+               /* Start discovery */
+-              lpfc_disc_start(vport);
++              lpfc_disc_start(phba);
+               break;
+       case LPFC_FABRIC_CFG_LINK:
+       /* hba_state is identically LPFC_FABRIC_CFG_LINK while waiting for
+          NameServer login */
+               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                              "%d (%d):0223 Timeout while waiting for "
+-                              "NameServer login\n",
+-                              phba->brd_no, vport->vpi);
++                              "%d:0223 Timeout while waiting for NameServer "
++                              "login\n", phba->brd_no);
+               /* Next look for NameServer ndlp */
+-              ndlp = lpfc_findnode_did(vport, NameServer_DID);
++              ndlp = lpfc_findnode_did(phba, NameServer_DID);
+               if (ndlp)
+                       lpfc_nlp_put(ndlp);
+               /* Start discovery */
+-              lpfc_disc_start(vport);
++              lpfc_disc_start(phba);
+               break;
+       case LPFC_NS_QRY:
+       /* Check for wait for NameServer Rsp timeout */
+               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                              "%d (%d):0224 NameServer Query timeout "
++                              "%d:0224 NameServer Query timeout "
+                               "Data: x%x x%x\n",
+-                              phba->brd_no, vport->vpi,
+-                              vport->fc_ns_retry, LPFC_MAX_NS_RETRY);
++                              phba->brd_no,
++                              phba->fc_ns_retry, LPFC_MAX_NS_RETRY);
+-              if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
++              ndlp = lpfc_findnode_did(phba, NameServer_DID);
++              if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
++                      if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
+                               /* Try it one more time */
+-                      vport->fc_ns_retry++;
+-                      rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
+-                                       vport->fc_ns_retry, 0);
++                              rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT);
+                               if (rc == 0)
+                                       break;
+                       }
+-              vport->fc_ns_retry = 0;
++                      phba->fc_ns_retry = 0;
 +              }
-+      } else
-+              retval = generic_permission(inode, submask, NULL);
-+
-+      if (retval && retval != -EROFS) /* ignore EROFS */
-+              return retval;
-+
-+      retval = security_inode_permission(inode, mask, nd);
-+      return ((retval == -EROFS) ? 0 : retval);       /* ignore EROFS */
-+}
-+
-+static int unionfs_permission(struct inode *inode, int mask,
-+                            struct nameidata *nd)
-+{
-+      struct inode *hidden_inode = NULL;
-+      int err = 0;
-+      int bindex, bstart, bend;
-+      const int is_file = !S_ISDIR(inode->i_mode);
-+      const int write_mask = (mask & MAY_WRITE) && !(mask & MAY_READ);
-+
-+      unionfs_read_lock(inode->i_sb);
-+
-+      bstart = ibstart(inode);
-+      bend = ibend(inode);
-+      if (bstart < 0 || bend < 0) {
-+              /*
-+               * With branch-management, we can get a stale inode here.
-+               * If so, we return ESTALE back to link_path_walk, which
-+               * would discard the dcache entry and re-lookup the
-+               * dentry+inode.  This should be equivalent to issuing
-+               * __unionfs_d_revalidate_chain on nd.dentry here.
-+               */
-+              err = -ESTALE;  /* force revalidate */
-+              goto out;
-+      }
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_inode = unionfs_lower_inode_idx(inode, bindex);
-+              if (!hidden_inode)
-+                      continue;
-+
-+              /*
-+               * check the condition for D-F-D underlying files/directories,
-+               * we don't have to check for files, if we are checking for
-+               * directories.
-+               */
-+              if (!is_file && !S_ISDIR(hidden_inode->i_mode))
-+                      continue;
-+
-+              /*
-+               * We use our own special version of permission, such that
-+               * only the first branch returns -EROFS.
-+               */
-+              err = inode_permission(hidden_inode, mask, nd, bindex);
-+
-+              /*
-+               * The permissions are an intersection of the overall directory
-+               * permissions, so we fail if one fails.
-+               */
-+              if (err)
-+                      goto out;
-+
-+              /* only the leftmost file matters. */
-+              if (is_file || write_mask) {
-+                      if (is_file && write_mask) {
-+                              err = get_write_access(hidden_inode);
-+                              if (!err)
-+                                      put_write_access(hidden_inode);
-+                      }
+-              /*
+-               * Discovery is over.
+-               * set port_state to PORT_READY if SLI2.
+-               * cmpl_reg_vpi will set port_state to READY for SLI3.
+-               */
+-              if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
+-                      lpfc_issue_reg_vpi(phba, vport);
+-              else  { /* NPIV Not enabled */
+-                      lpfc_issue_clear_la(phba, vport);
+-                      vport->port_state = LPFC_VPORT_READY;
++              /* Nothing to authenticate, so CLEAR_LA right now */
++              clearlambox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
++              if (!clearlambox) {
++                      clrlaerr = 1;
++                      lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
++                                      "%d:0226 Device Discovery "
++                                      "completion error\n",
++                                      phba->brd_no);
++                      phba->hba_state = LPFC_HBA_ERROR;
 +                      break;
 +              }
-+      }
-+
-+out:
-+      unionfs_read_unlock(inode->i_sb);
-+      return err;
-+}
-+
-+static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
-+{
-+      int err = 0;
-+      struct dentry *hidden_dentry;
-+      struct inode *inode = NULL;
-+      struct inode *hidden_inode = NULL;
-+      int bstart, bend, bindex;
-+      int i;
-+      int copyup = 0;
-+
-+      unionfs_read_lock(dentry->d_sb);
-+      unionfs_lock_dentry(dentry);
-+
-+      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+      inode = dentry->d_inode;
-+
-+      for (bindex = bstart; (bindex <= bend) || (bindex == bstart);
-+           bindex++) {
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!hidden_dentry)
-+                      continue;
-+              BUG_ON(hidden_dentry->d_inode == NULL);
-+
-+              /* If the file is on a read only branch */
-+              if (is_robranch_super(dentry->d_sb, bindex)
-+                  || IS_RDONLY(hidden_dentry->d_inode)) {
-+                      if (copyup || (bindex != bstart))
-+                              continue;
-+                      /* Only if its the leftmost file, copyup the file */
-+                      for (i = bstart - 1; i >= 0; i--) {
-+                              loff_t size = dentry->d_inode->i_size;
-+                              if (ia->ia_valid & ATTR_SIZE)
-+                                      size = ia->ia_size;
-+                              err = copyup_dentry(dentry->d_parent->d_inode,
-+                                                  dentry, bstart, i, NULL,
-+                                                  size);
-+
-+                              if (!err) {
-+                                      copyup = 1;
-+                                      hidden_dentry =
-+                                              unionfs_lower_dentry(dentry);
-+                                      break;
-+                              }
-+                              /*
-+                               * if error is in the leftmost branch, pass
-+                               * it up.
-+                               */
-+                              if (i == 0)
-+                                      goto out;
-+                      }
 +
-+              }
-+              err = notify_change(hidden_dentry, ia);
-+              if (err)
-+                      goto out;
++              phba->hba_state = LPFC_CLEAR_LA;
++              lpfc_clear_la(phba, clearlambox);
++              clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
++              rc = lpfc_sli_issue_mbox(phba, clearlambox,
++                                       (MBX_NOWAIT | MBX_STOP_IOCB));
++              if (rc == MBX_NOT_FINISHED) {
++                      mempool_free(clearlambox, phba->mbox_mem_pool);
++                      clrlaerr = 1;
++                      break;
+               }
+               /* Setup and issue mailbox INITIALIZE LINK command */
+               initlinkmbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+               if (!initlinkmbox) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                                      "%d (%d):0206 Device Discovery "
++                                      "%d:0206 Device Discovery "
+                                       "completion error\n",
+-                                      phba->brd_no, vport->vpi);
+-                      phba->link_state = LPFC_HBA_ERROR;
++                                      phba->brd_no);
++                      phba->hba_state = LPFC_HBA_ERROR;
+                       break;
+               }
+@@ -2639,8 +2144,6 @@
+               lpfc_init_link(phba, initlinkmbox, phba->cfg_topology,
+                              phba->cfg_link_speed);
+               initlinkmbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
+-              initlinkmbox->vport = vport;
+-              initlinkmbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+               rc = lpfc_sli_issue_mbox(phba, initlinkmbox,
+                                        (MBX_NOWAIT | MBX_STOP_IOCB));
+               lpfc_set_loopback_flag(phba);
+@@ -2651,81 +2154,67 @@
+       case LPFC_DISC_AUTH:
+       /* Node Authentication timeout */
++              lpfc_printf_log(phba,
++                               KERN_ERR,
++                               LOG_DISCOVERY,
++                               "%d:0227 Node Authentication timeout\n",
++                               phba->brd_no);
++              lpfc_disc_flush_list(phba);
++              clearlambox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
++              if (!clearlambox) {
++                      clrlaerr = 1;
+                       lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                              "%d (%d):0227 Node Authentication timeout\n",
+-                              phba->brd_no, vport->vpi);
+-              lpfc_disc_flush_list(vport);
+-
+-              /*
+-               * set port_state to PORT_READY if SLI2.
+-               * cmpl_reg_vpi will set port_state to READY for SLI3.
+-               */
+-              if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
+-                      lpfc_issue_reg_vpi(phba, vport);
+-              else {  /* NPIV Not enabled */
+-                      lpfc_issue_clear_la(phba, vport);
+-                      vport->port_state = LPFC_VPORT_READY;
+-              }
++                                      "%d:0207 Device Discovery "
++                                      "completion error\n",
++                                      phba->brd_no);
++                      phba->hba_state = LPFC_HBA_ERROR;
+               break;
+-
+-      case LPFC_VPORT_READY:
+-              if (vport->fc_flag & FC_RSCN_MODE) {
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                                      "%d (%d):0231 RSCN timeout Data: x%x "
+-                                      "x%x\n",
+-                                      phba->brd_no, vport->vpi,
+-                                      vport->fc_ns_retry, LPFC_MAX_NS_RETRY);
+-
+-                      /* Cleanup any outstanding ELS commands */
+-                      lpfc_els_flush_cmd(vport);
+-
+-                      lpfc_els_flush_rscn(vport);
+-                      lpfc_disc_flush_list(vport);
+               }
+-              break;
+-
+-      default:
+-              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                              "%d (%d):0229 Unexpected discovery timeout, "
+-                              "vport State x%x\n",
+-                              phba->brd_no, vport->vpi, vport->port_state);
+-
+-              break;
++              phba->hba_state = LPFC_CLEAR_LA;
++              lpfc_clear_la(phba, clearlambox);
++              clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
++              rc = lpfc_sli_issue_mbox(phba, clearlambox,
++                                       (MBX_NOWAIT | MBX_STOP_IOCB));
++              if (rc == MBX_NOT_FINISHED) {
++                      mempool_free(clearlambox, phba->mbox_mem_pool);
++                      clrlaerr = 1;
+       }
 +              break;
-+      }
-+
-+      /* for mmap */
-+      if (ia->ia_valid & ATTR_SIZE) {
-+              if (ia->ia_size != i_size_read(inode)) {
-+                      err = vmtruncate(inode, ia->ia_size);
-+                      if (err)
-+                              printk("unionfs_setattr: vmtruncate failed\n");
-+              }
-+      }
-+
-+      /* get the size from the first hidden inode */
-+      hidden_inode = unionfs_lower_inode(dentry->d_inode);
-+      fsstack_copy_attr_all(inode, hidden_inode, unionfs_get_nlinks);
-+      fsstack_copy_inode_size(inode, hidden_inode);
+-      switch (phba->link_state) {
+       case LPFC_CLEAR_LA:
+       /* CLEAR LA timeout */
+-              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                              "%d (%d):0228 CLEAR LA timeout\n",
+-                              phba->brd_no, vport->vpi);
+-              clrlaerr = 1;
+-              break;
+-
+-      case LPFC_LINK_UNKNOWN:
+-      case LPFC_WARM_START:
+-      case LPFC_INIT_START:
+-      case LPFC_INIT_MBX_CMDS:
+-      case LPFC_LINK_DOWN:
+-      case LPFC_LINK_UP:
+-      case LPFC_HBA_ERROR:
+-              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                              "%d (%d):0230 Unexpected timeout, hba link "
+-                              "state x%x\n",
+-                              phba->brd_no, vport->vpi, phba->link_state);
++              lpfc_printf_log(phba,
++                               KERN_ERR,
++                               LOG_DISCOVERY,
++                               "%d:0228 CLEAR LA timeout\n",
++                               phba->brd_no);
+               clrlaerr = 1;
+               break;
+       case LPFC_HBA_READY:
++              if (phba->fc_flag & FC_RSCN_MODE) {
++                      lpfc_printf_log(phba,
++                                      KERN_ERR,
++                                      LOG_DISCOVERY,
++                                      "%d:0231 RSCN timeout Data: x%x x%x\n",
++                                      phba->brd_no,
++                                      phba->fc_ns_retry, LPFC_MAX_NS_RETRY);
 +
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
++                      /* Cleanup any outstanding ELS commands */
++                      lpfc_els_flush_cmd(phba);
 +
-+struct inode_operations unionfs_symlink_iops = {
-+      .readlink       = unionfs_readlink,
-+      .permission     = unionfs_permission,
-+      .follow_link    = unionfs_follow_link,
-+      .setattr        = unionfs_setattr,
-+      .put_link       = unionfs_put_link,
-+};
++                      lpfc_els_flush_rscn(phba);
++                      lpfc_disc_flush_list(phba);
++              }
+               break;
+       }
+       if (clrlaerr) {
+-              lpfc_disc_flush_list(vport);
++              lpfc_disc_flush_list(phba);
+               psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
+               psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
+               psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
+-              vport->port_state = LPFC_VPORT_READY;
++              phba->hba_state = LPFC_HBA_READY;
+       }
+       return;
+@@ -2738,29 +2227,37 @@
+  * handed off to the SLI layer.
+  */
+ void
+-lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
++lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+ {
+-      MAILBOX_t *mb = &pmb->mb;
+-      struct lpfc_dmabuf   *mp = (struct lpfc_dmabuf *) (pmb->context1);
+-      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
+-      struct lpfc_vport    *vport = pmb->vport;
++      struct lpfc_sli *psli;
++      MAILBOX_t *mb;
++      struct lpfc_dmabuf *mp;
++      struct lpfc_nodelist *ndlp;
 +
-+struct inode_operations unionfs_dir_iops = {
-+      .create         = unionfs_create,
-+      .lookup         = unionfs_lookup,
-+      .link           = unionfs_link,
-+      .unlink         = unionfs_unlink,
-+      .symlink        = unionfs_symlink,
-+      .mkdir          = unionfs_mkdir,
-+      .rmdir          = unionfs_rmdir,
-+      .mknod          = unionfs_mknod,
-+      .rename         = unionfs_rename,
-+      .permission     = unionfs_permission,
-+      .setattr        = unionfs_setattr,
-+#ifdef CONFIG_UNION_FS_XATTR
-+      .setxattr       = unionfs_setxattr,
-+      .getxattr       = unionfs_getxattr,
-+      .removexattr    = unionfs_removexattr,
-+      .listxattr      = unionfs_listxattr,
-+#endif
-+};
++      psli = &phba->sli;
++      mb = &pmb->mb;
 +
-+struct inode_operations unionfs_main_iops = {
-+      .permission     = unionfs_permission,
-+      .setattr        = unionfs_setattr,
-+#ifdef CONFIG_UNION_FS_XATTR
-+      .setxattr       = unionfs_setxattr,
-+      .getxattr       = unionfs_getxattr,
-+      .removexattr    = unionfs_removexattr,
-+      .listxattr      = unionfs_listxattr,
-+#endif
-+};
-diff -Nurb linux-2.6.22-570/fs/unionfs/lookup.c linux-2.6.22-590/fs/unionfs/lookup.c
---- linux-2.6.22-570/fs/unionfs/lookup.c       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/lookup.c       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,549 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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.
++      ndlp = (struct lpfc_nodelist *) pmb->context2;
++      mp = (struct lpfc_dmabuf *) (pmb->context1);
+       pmb->context1 = NULL;
+       ndlp->nlp_rpi = mb->un.varWords[0];
+       ndlp->nlp_type |= NLP_FABRIC;
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
++      /* Start issuing Fabric-Device Management Interface (FDMI)
++       * command to 0xfffffa (FDMI well known port)
++       */
++      if (phba->cfg_fdmi_on == 1) {
++              lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA);
++      } else {
+               /*
+-       * Start issuing Fabric-Device Management Interface (FDMI) command to
+-       * 0xfffffa (FDMI well known port) or Delay issuing FDMI command if
+-       * fdmi-on=2 (supporting RPA/hostnmae)
++               * Delay issuing FDMI command if fdmi-on=2
++               * (supporting RPA/hostnmae)
+                */
+-
+-      if (phba->cfg_fdmi_on == 1)
+-              lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
+-      else
+-              mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60);
++              mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60);
++      }
+                               /* Mailbox took a reference to the node */
+       lpfc_nlp_put(ndlp);
+@@ -2786,12 +2283,16 @@
+                     sizeof(ndlp->nlp_portname)) == 0;
+ }
++/*
++ * Search node lists for a remote port matching filter criteria
++ * Caller needs to hold host_lock before calling this routine.
 + */
+ struct lpfc_nodelist *
+-__lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
++__lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
+ {
+       struct lpfc_nodelist *ndlp;
+-      list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
++      list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+               if (ndlp->nlp_state != NLP_STE_UNUSED_NODE &&
+                   filter(ndlp, param))
+                       return ndlp;
+@@ -2801,104 +2302,68 @@
+ /*
+  * Search node lists for a remote port matching filter criteria
+- * Caller needs to hold host_lock before calling this routine.
++ * This routine is used when the caller does NOT have host_lock.
+  */
+ struct lpfc_nodelist *
+-lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
++lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param)
+ {
+-      struct Scsi_Host     *shost = lpfc_shost_from_vport(vport);
+       struct lpfc_nodelist *ndlp;
+-      spin_lock_irq(shost->host_lock);
+-      ndlp = __lpfc_find_node(vport, filter, param);
+-      spin_unlock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
++      ndlp = __lpfc_find_node(phba, filter, param);
++      spin_unlock_irq(phba->host->host_lock);
+       return ndlp;
+ }
+ /*
+  * This routine looks up the ndlp lists for the given RPI. If rpi found it
+- * returns the node list element pointer else return NULL.
++ * returns the node list pointer else return NULL.
+  */
+ struct lpfc_nodelist *
+-__lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
++__lpfc_findnode_rpi(struct lpfc_hba *phba, uint16_t rpi)
+ {
+-      return __lpfc_find_node(vport, lpfc_filter_by_rpi, &rpi);
++      return __lpfc_find_node(phba, lpfc_filter_by_rpi, &rpi);
+ }
+ struct lpfc_nodelist *
+-lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
++lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+       struct lpfc_nodelist *ndlp;
+-      spin_lock_irq(shost->host_lock);
+-      ndlp = __lpfc_findnode_rpi(vport, rpi);
+-      spin_unlock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
++      ndlp = __lpfc_findnode_rpi(phba, rpi);
++      spin_unlock_irq(phba->host->host_lock);
+       return ndlp;
+ }
+ /*
+  * This routine looks up the ndlp lists for the given WWPN. If WWPN found it
+- * returns the node element list pointer else return NULL.
++ * returns the node list pointer else return NULL.
+  */
+ struct lpfc_nodelist *
+-lpfc_findnode_wwpn(struct lpfc_vport *vport, struct lpfc_name *wwpn)
++lpfc_findnode_wwpn(struct lpfc_hba *phba, struct lpfc_name *wwpn)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+       struct lpfc_nodelist *ndlp;
+-      spin_lock_irq(shost->host_lock);
+-      ndlp = __lpfc_find_node(vport, lpfc_filter_by_wwpn, wwpn);
+-      spin_unlock_irq(shost->host_lock);
+-      return ndlp;
+-}
+-
+-void
+-lpfc_dev_loss_delay(unsigned long ptr)
+-{
+-      struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) ptr;
+-      struct lpfc_vport *vport = ndlp->vport;
+-      struct lpfc_hba   *phba = vport->phba;
+-      struct lpfc_work_evt  *evtp = &ndlp->dev_loss_evt;
+-      unsigned long flags;
+-
+-      evtp = &ndlp->dev_loss_evt;
+-
+-      spin_lock_irqsave(&phba->hbalock, flags);
+-      if (!list_empty(&evtp->evt_listp)) {
+-              spin_unlock_irqrestore(&phba->hbalock, flags);
+-              return;
+-      }
+-
+-      evtp->evt_arg1  = ndlp;
+-      evtp->evt       = LPFC_EVT_DEV_LOSS_DELAY;
+-      list_add_tail(&evtp->evt_listp, &phba->work_list);
+-      if (phba->work_wait)
+-              lpfc_worker_wake_up(phba);
+-      spin_unlock_irqrestore(&phba->hbalock, flags);
+-      return;
++      spin_lock_irq(phba->host->host_lock);
++      ndlp = __lpfc_find_node(phba, lpfc_filter_by_wwpn, wwpn);
++      spin_unlock_irq(phba->host->host_lock);
++      return NULL;
+ }
+ void
+-lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-            uint32_t did)
++lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did)
+ {
+       memset(ndlp, 0, sizeof (struct lpfc_nodelist));
+       INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
+-      INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp);
+       init_timer(&ndlp->nlp_delayfunc);
+       ndlp->nlp_delayfunc.function = lpfc_els_retry_delay;
+       ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
+       ndlp->nlp_DID = did;
+-      ndlp->vport = vport;
++      ndlp->nlp_phba = phba;
+       ndlp->nlp_sid = NLP_NO_SID;
+       INIT_LIST_HEAD(&ndlp->nlp_listp);
+       kref_init(&ndlp->kref);
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE,
+-              "node init:       did:x%x",
+-              ndlp->nlp_DID, 0, 0);
+-
+       return;
+ }
+@@ -2907,13 +2372,8 @@
+ {
+       struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist,
+                                                 kref);
+-
+-      lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE,
+-              "node release:    did:x%x flg:x%x type:x%x",
+-              ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
+-
+-      lpfc_nlp_remove(ndlp->vport, ndlp);
+-      mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool);
++      lpfc_nlp_remove(ndlp->nlp_phba, ndlp);
++      mempool_free(ndlp, ndlp->nlp_phba->nlp_mem_pool);
+ }
+ struct lpfc_nodelist *
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_hw.h linux-2.6.22-570/drivers/scsi/lpfc/lpfc_hw.h
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_hw.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_hw.h       2007-07-08 19:32:17.000000000 -0400
+@@ -59,12 +59,6 @@
+ #define SLI2_IOCB_CMD_R3XTRA_ENTRIES 24
+ #define SLI2_IOCB_RSP_R3XTRA_ENTRIES 32
+-#define SLI2_IOCB_CMD_SIZE    32
+-#define SLI2_IOCB_RSP_SIZE    32
+-#define SLI3_IOCB_CMD_SIZE    128
+-#define SLI3_IOCB_RSP_SIZE    64
+-
+-
+ /* Common Transport structures and definitions */
+ union CtRevisionId {
+@@ -85,9 +79,6 @@
+       uint32_t word;
+ };
+-#define FC4_FEATURE_INIT 0x2
+-#define FC4_FEATURE_TARGET 0x1
+-
+ struct lpfc_sli_ct_request {
+       /* Structure is in Big Endian format */
+       union CtRevisionId RevisionId;
+@@ -130,6 +121,20 @@
+                       uint32_t rsvd[7];
+               } rft;
++              struct rff {
++                      uint32_t PortId;
++                      uint8_t reserved[2];
++#ifdef __BIG_ENDIAN_BITFIELD
++                      uint8_t feature_res:6;
++                      uint8_t feature_init:1;
++                      uint8_t feature_tgt:1;
++#else  /*  __LITTLE_ENDIAN_BITFIELD */
++                      uint8_t feature_tgt:1;
++                      uint8_t feature_init:1;
++                      uint8_t feature_res:6;
++#endif
++                      uint8_t type_code;     /* type=8 for FCP */
++              } rff;
+               struct rnn {
+                       uint32_t PortId;        /* For RNN_ID requests */
+                       uint8_t wwnn[8];
+@@ -139,42 +144,15 @@
+                       uint8_t len;
+                       uint8_t symbname[255];
+               } rsnn;
+-              struct rspn {   /* For RSPN_ID requests */
+-                      uint32_t PortId;
+-                      uint8_t len;
+-                      uint8_t symbname[255];
+-              } rspn;
+-              struct gff {
+-                      uint32_t PortId;
+-              } gff;
+-              struct gff_acc {
+-                      uint8_t fbits[128];
+-              } gff_acc;
+-#define FCP_TYPE_FEATURE_OFFSET 4
+-              struct rff {
+-                      uint32_t PortId;
+-                      uint8_t reserved[2];
+-                      uint8_t fbits;
+-                      uint8_t type_code;     /* type=8 for FCP */
+-              } rff;
+       } un;
+ };
+ #define  SLI_CT_REVISION        1
+-#define  GID_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
+-                         sizeof(struct gid))
+-#define  GFF_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
+-                         sizeof(struct gff))
+-#define  RFT_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
+-                         sizeof(struct rft))
+-#define  RFF_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
+-                         sizeof(struct rff))
+-#define  RNN_REQUEST_SZ   (offsetof(struct lpfc_sli_ct_request, un) + \
+-                         sizeof(struct rnn))
+-#define  RSNN_REQUEST_SZ  (offsetof(struct lpfc_sli_ct_request, un) + \
+-                         sizeof(struct rsnn))
+-#define  RSPN_REQUEST_SZ  (offsetof(struct lpfc_sli_ct_request, un) + \
+-                         sizeof(struct rspn))
++#define  GID_REQUEST_SZ         (sizeof(struct lpfc_sli_ct_request) - 260)
++#define  RFT_REQUEST_SZ         (sizeof(struct lpfc_sli_ct_request) - 228)
++#define  RFF_REQUEST_SZ         (sizeof(struct lpfc_sli_ct_request) - 235)
++#define  RNN_REQUEST_SZ         (sizeof(struct lpfc_sli_ct_request) - 252)
++#define  RSNN_REQUEST_SZ        (sizeof(struct lpfc_sli_ct_request))
+ /*
+  * FsType Definitions
+@@ -249,7 +227,6 @@
+ #define  SLI_CTNS_GFT_ID      0x0117
+ #define  SLI_CTNS_GSPN_ID     0x0118
+ #define  SLI_CTNS_GPT_ID      0x011A
+-#define  SLI_CTNS_GFF_ID      0x011F
+ #define  SLI_CTNS_GID_PN      0x0121
+ #define  SLI_CTNS_GID_NN      0x0131
+ #define  SLI_CTNS_GIP_NN      0x0135
+@@ -263,9 +240,9 @@
+ #define  SLI_CTNS_RNN_ID      0x0213
+ #define  SLI_CTNS_RCS_ID      0x0214
+ #define  SLI_CTNS_RFT_ID      0x0217
++#define  SLI_CTNS_RFF_ID      0x021F
+ #define  SLI_CTNS_RSPN_ID     0x0218
+ #define  SLI_CTNS_RPT_ID      0x021A
+-#define  SLI_CTNS_RFF_ID      0x021F
+ #define  SLI_CTNS_RIP_NN      0x0235
+ #define  SLI_CTNS_RIPA_NN     0x0236
+ #define  SLI_CTNS_RSNN_NN     0x0239
+@@ -334,9 +311,9 @@
+       uint8_t bbCreditlsb;    /* FC Word 0, byte 3 */
+ #ifdef __BIG_ENDIAN_BITFIELD
+-      uint16_t request_multiple_Nport:1;      /* FC Word 1, bit 31 */
++      uint16_t increasingOffset:1;    /* FC Word 1, bit 31 */
+       uint16_t randomOffset:1;        /* FC Word 1, bit 30 */
+-      uint16_t response_multiple_NPort:1;     /* FC Word 1, bit 29 */
++      uint16_t word1Reserved2:1;      /* FC Word 1, bit 29 */
+       uint16_t fPort:1;       /* FC Word 1, bit 28 */
+       uint16_t altBbCredit:1; /* FC Word 1, bit 27 */
+       uint16_t edtovResolution:1;     /* FC Word 1, bit 26 */
+@@ -355,9 +332,9 @@
+       uint16_t edtovResolution:1;     /* FC Word 1, bit 26 */
+       uint16_t altBbCredit:1; /* FC Word 1, bit 27 */
+       uint16_t fPort:1;       /* FC Word 1, bit 28 */
+-      uint16_t response_multiple_NPort:1;     /* FC Word 1, bit 29 */
++      uint16_t word1Reserved2:1;      /* FC Word 1, bit 29 */
+       uint16_t randomOffset:1;        /* FC Word 1, bit 30 */
+-      uint16_t request_multiple_Nport:1;      /* FC Word 1, bit 31 */
++      uint16_t increasingOffset:1;    /* FC Word 1, bit 31 */
+       uint16_t payloadlength:1;       /* FC Word 1, bit 16 */
+       uint16_t contIncSeqCnt:1;       /* FC Word 1, bit 17 */
+@@ -1278,9 +1255,7 @@
+ #define MBX_KILL_BOARD      0x24
+ #define MBX_CONFIG_FARP     0x25
+ #define MBX_BEACON          0x2A
+-#define MBX_HEARTBEAT       0x31
+-#define MBX_CONFIG_HBQ            0x7C
+ #define MBX_LOAD_AREA       0x81
+ #define MBX_RUN_BIU_DIAG64  0x84
+ #define MBX_CONFIG_PORT     0x88
+@@ -1288,10 +1263,6 @@
+ #define MBX_READ_RPI64      0x8F
+ #define MBX_REG_LOGIN64     0x93
+ #define MBX_READ_LA64       0x95
+-#define MBX_REG_VPI       0x96
+-#define MBX_UNREG_VPI     0x97
+-#define MBX_REG_VNPID     0x96
+-#define MBX_UNREG_VNPID           0x97
+ #define MBX_FLASH_WR_ULA    0x98
+ #define MBX_SET_DEBUG       0x99
+@@ -1364,10 +1335,6 @@
+ #define CMD_FCP_TRECEIVE64_CX   0xA1
+ #define CMD_FCP_TRSP64_CX       0xA3
+-#define CMD_IOCB_RCV_SEQ64_CX 0xB5
+-#define CMD_IOCB_RCV_ELS64_CX 0xB7
+-#define CMD_IOCB_RCV_CONT64_CX        0xBB
+-
+ #define CMD_GEN_REQUEST64_CR    0xC2
+ #define CMD_GEN_REQUEST64_CX    0xC3
+@@ -1594,7 +1561,6 @@
+ #define FLAGS_TOPOLOGY_MODE_PT_PT    0x02 /* Attempt pt-pt only */
+ #define FLAGS_TOPOLOGY_MODE_LOOP     0x04 /* Attempt loop only */
+ #define FLAGS_TOPOLOGY_MODE_PT_LOOP  0x06 /* Attempt pt-pt then loop */
+-#define       FLAGS_UNREG_LOGIN_ALL        0x08 /* UNREG_LOGIN all on link down */
+ #define FLAGS_LIRP_LILP              0x80 /* LIRP / LILP is disabled */
+ #define FLAGS_TOPOLOGY_FAILOVER      0x0400   /* Bit 10 */
+@@ -1778,6 +1744,8 @@
+ #define LMT_4Gb       0x040
+ #define LMT_8Gb       0x080
+ #define LMT_10Gb      0x100
 +
-+#include "union.h"
-+
-+/* is the filename valid == !(whiteout for a file or opaque dir marker) */
-+static int is_validname(const char *name)
-+{
-+      if (!strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN))
-+              return 0;
-+      if (!strncmp(name, UNIONFS_DIR_OPAQUE_NAME,
-+                   sizeof(UNIONFS_DIR_OPAQUE_NAME) - 1))
-+              return 0;
-+      return 1;
-+}
-+
-+/* The rest of these are utility functions for lookup. */
-+static noinline int is_opaque_dir(struct dentry *dentry, int bindex)
-+{
-+      int err = 0;
-+      struct dentry *hidden_dentry;
-+      struct dentry *wh_hidden_dentry;
-+      struct inode *hidden_inode;
-+      struct sioq_args args;
-+
-+      hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+      hidden_inode = hidden_dentry->d_inode;
 +
-+      BUG_ON(!S_ISDIR(hidden_inode->i_mode));
+       uint32_t rsvd2;
+       uint32_t rsvd3;
+       uint32_t max_xri;
+@@ -1786,10 +1754,7 @@
+       uint32_t avail_xri;
+       uint32_t avail_iocb;
+       uint32_t avail_rpi;
+-      uint32_t max_vpi;
+-      uint32_t rsvd4;
+-      uint32_t rsvd5;
+-      uint32_t avail_vpi;
++      uint32_t default_rpi;
+ } READ_CONFIG_VAR;
+ /* Structure for MB Command READ_RCONFIG (12) */
+@@ -1853,13 +1818,6 @@
+                                     structure */
+               struct ulp_bde64 sp64;
+       } un;
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint16_t rsvd3;
+-      uint16_t vpi;
+-#else /*  __LITTLE_ENDIAN_BITFIELD */
+-      uint16_t vpi;
+-      uint16_t rsvd3;
+-#endif
+ } READ_SPARM_VAR;
+ /* Structure for MB Command READ_STATUS (14) */
+@@ -1960,17 +1918,11 @@
+ #ifdef __BIG_ENDIAN_BITFIELD
+       uint32_t cv:1;
+       uint32_t rr:1;
+-      uint32_t rsvd2:2;
+-      uint32_t v3req:1;
+-      uint32_t v3rsp:1;
+-      uint32_t rsvd1:25;
++      uint32_t rsvd1:29;
+       uint32_t rv:1;
+ #else /*  __LITTLE_ENDIAN_BITFIELD */
+       uint32_t rv:1;
+-      uint32_t rsvd1:25;
+-      uint32_t v3rsp:1;
+-      uint32_t v3req:1;
+-      uint32_t rsvd2:2;
++      uint32_t rsvd1:29;
+       uint32_t rr:1;
+       uint32_t cv:1;
+ #endif
+@@ -2020,8 +1972,8 @@
+       uint8_t sli1FwName[16];
+       uint32_t sli2FwRev;
+       uint8_t sli2FwName[16];
+-      uint32_t sli3Feat;
+-      uint32_t RandomData[6];
++      uint32_t rsvd2;
++      uint32_t RandomData[7];
+ } READ_REV_VAR;
+ /* Structure for MB Command READ_LINK_STAT (18) */
+@@ -2061,14 +2013,6 @@
+               struct ulp_bde64 sp64;
+       } un;
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint16_t rsvd6;
+-      uint16_t vpi;
+-#else /* __LITTLE_ENDIAN_BITFIELD */
+-      uint16_t vpi;
+-      uint16_t rsvd6;
+-#endif
+-
+ } REG_LOGIN_VAR;
+ /* Word 30 contents for REG_LOGIN */
+@@ -2093,78 +2037,16 @@
+ #ifdef __BIG_ENDIAN_BITFIELD
+       uint16_t rsvd1;
+       uint16_t rpi;
+-      uint32_t rsvd2;
+-      uint32_t rsvd3;
+-      uint32_t rsvd4;
+-      uint32_t rsvd5;
+-      uint16_t rsvd6;
+-      uint16_t vpi;
+ #else /*  __LITTLE_ENDIAN_BITFIELD */
+       uint16_t rpi;
+       uint16_t rsvd1;
+-      uint32_t rsvd2;
+-      uint32_t rsvd3;
+-      uint32_t rsvd4;
+-      uint32_t rsvd5;
+-      uint16_t vpi;
+-      uint16_t rsvd6;
+ #endif
+ } UNREG_LOGIN_VAR;
+-/* Structure for MB Command REG_VPI (0x96) */
+-typedef struct {
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint32_t rsvd1;
+-      uint32_t rsvd2:8;
+-      uint32_t sid:24;
+-      uint32_t rsvd3;
+-      uint32_t rsvd4;
+-      uint32_t rsvd5;
+-      uint16_t rsvd6;
+-      uint16_t vpi;
+-#else /*  __LITTLE_ENDIAN */
+-      uint32_t rsvd1;
+-      uint32_t sid:24;
+-      uint32_t rsvd2:8;
+-      uint32_t rsvd3;
+-      uint32_t rsvd4;
+-      uint32_t rsvd5;
+-      uint16_t vpi;
+-      uint16_t rsvd6;
+-#endif
+-} REG_VPI_VAR;
+-
+-/* Structure for MB Command UNREG_VPI (0x97) */
+-typedef struct {
+-      uint32_t rsvd1;
+-      uint32_t rsvd2;
+-      uint32_t rsvd3;
+-      uint32_t rsvd4;
+-      uint32_t rsvd5;
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint16_t rsvd6;
+-      uint16_t vpi;
+-#else /*  __LITTLE_ENDIAN */
+-      uint16_t vpi;
+-      uint16_t rsvd6;
+-#endif
+-} UNREG_VPI_VAR;
+-
+ /* Structure for MB Command UNREG_D_ID (0x23) */
+ typedef struct {
+       uint32_t did;
+-      uint32_t rsvd2;
+-      uint32_t rsvd3;
+-      uint32_t rsvd4;
+-      uint32_t rsvd5;
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint16_t rsvd6;
+-      uint16_t vpi;
+-#else
+-      uint16_t vpi;
+-      uint16_t rsvd6;
+-#endif
+ } UNREG_D_ID_VAR;
+ /* Structure for MB Command READ_LA (21) */
+@@ -2296,240 +2178,13 @@
+ #define  DMP_RSP_OFFSET          0x14   /* word 5 contains first word of rsp */
+ #define  DMP_RSP_SIZE            0x6C   /* maximum of 27 words of rsp data */
+-struct hbq_mask {
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint8_t tmatch;
+-      uint8_t tmask;
+-      uint8_t rctlmatch;
+-      uint8_t rctlmask;
+-#else /*  __LITTLE_ENDIAN */
+-      uint8_t rctlmask;
+-      uint8_t rctlmatch;
+-      uint8_t tmask;
+-      uint8_t tmatch;
+-#endif
+-};
+-
+-
+-/* Structure for MB Command CONFIG_HBQ (7c) */
+-
+-struct config_hbq_var {
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint32_t rsvd1      :7;
+-      uint32_t recvNotify :1;     /* Receive Notification */
+-      uint32_t numMask    :8;     /* # Mask Entries       */
+-      uint32_t profile    :8;     /* Selection Profile    */
+-      uint32_t rsvd2      :8;
+-#else /*  __LITTLE_ENDIAN */
+-      uint32_t rsvd2      :8;
+-      uint32_t profile    :8;     /* Selection Profile    */
+-      uint32_t numMask    :8;     /* # Mask Entries       */
+-      uint32_t recvNotify :1;     /* Receive Notification */
+-      uint32_t rsvd1      :7;
+-#endif
+-
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint32_t hbqId      :16;
+-      uint32_t rsvd3      :12;
+-      uint32_t ringMask   :4;
+-#else /*  __LITTLE_ENDIAN */
+-      uint32_t ringMask   :4;
+-      uint32_t rsvd3      :12;
+-      uint32_t hbqId      :16;
+-#endif
+-
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint32_t entry_count :16;
+-      uint32_t rsvd4        :8;
+-      uint32_t headerLen    :8;
+-#else /*  __LITTLE_ENDIAN */
+-      uint32_t headerLen    :8;
+-      uint32_t rsvd4        :8;
+-      uint32_t entry_count :16;
+-#endif
+-
+-      uint32_t hbqaddrLow;
+-      uint32_t hbqaddrHigh;
+-
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint32_t rsvd5      :31;
+-      uint32_t logEntry   :1;
+-#else /*  __LITTLE_ENDIAN */
+-      uint32_t logEntry   :1;
+-      uint32_t rsvd5      :31;
+-#endif
+-
+-      uint32_t rsvd6;    /* w7 */
+-      uint32_t rsvd7;    /* w8 */
+-      uint32_t rsvd8;    /* w9 */
+-
+-      struct hbq_mask hbqMasks[6];
+-
+-
+-      union {
+-              uint32_t allprofiles[12];
+-
+-              struct {
+-                      #ifdef __BIG_ENDIAN_BITFIELD
+-                              uint32_t        seqlenoff       :16;
+-                              uint32_t        maxlen          :16;
+-                      #else   /*  __LITTLE_ENDIAN */
+-                              uint32_t        maxlen          :16;
+-                              uint32_t        seqlenoff       :16;
+-                      #endif
+-                      #ifdef __BIG_ENDIAN_BITFIELD
+-                              uint32_t        rsvd1           :28;
+-                              uint32_t        seqlenbcnt      :4;
+-                      #else   /*  __LITTLE_ENDIAN */
+-                              uint32_t        seqlenbcnt      :4;
+-                              uint32_t        rsvd1           :28;
+-                      #endif
+-                      uint32_t rsvd[10];
+-              } profile2;
+-
+-              struct {
+-                      #ifdef __BIG_ENDIAN_BITFIELD
+-                              uint32_t        seqlenoff       :16;
+-                              uint32_t        maxlen          :16;
+-                      #else   /*  __LITTLE_ENDIAN */
+-                              uint32_t        maxlen          :16;
+-                              uint32_t        seqlenoff       :16;
+-                      #endif
+-                      #ifdef __BIG_ENDIAN_BITFIELD
+-                              uint32_t        cmdcodeoff      :28;
+-                              uint32_t        rsvd1           :12;
+-                              uint32_t        seqlenbcnt      :4;
+-                      #else   /*  __LITTLE_ENDIAN */
+-                              uint32_t        seqlenbcnt      :4;
+-                              uint32_t        rsvd1           :12;
+-                              uint32_t        cmdcodeoff      :28;
+-                      #endif
+-                      uint32_t cmdmatch[8];
+-
+-                      uint32_t rsvd[2];
+-              } profile3;
+-
+-              struct {
+-                      #ifdef __BIG_ENDIAN_BITFIELD
+-                              uint32_t        seqlenoff       :16;
+-                              uint32_t        maxlen          :16;
+-                      #else   /*  __LITTLE_ENDIAN */
+-                              uint32_t        maxlen          :16;
+-                              uint32_t        seqlenoff       :16;
+-                      #endif
+-                      #ifdef __BIG_ENDIAN_BITFIELD
+-                              uint32_t        cmdcodeoff      :28;
+-                              uint32_t        rsvd1           :12;
+-                              uint32_t        seqlenbcnt      :4;
+-                      #else   /*  __LITTLE_ENDIAN */
+-                              uint32_t        seqlenbcnt      :4;
+-                              uint32_t        rsvd1           :12;
+-                              uint32_t        cmdcodeoff      :28;
+-                      #endif
+-                      uint32_t cmdmatch[8];
+-
+-                      uint32_t rsvd[2];
+-              } profile5;
+-
+-      } profiles;
+-
+-};
+-
+-
+-
+ /* Structure for MB Command CONFIG_PORT (0x88) */
+-typedef struct {
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint32_t cBE       :  1;
+-      uint32_t cET       :  1;
+-      uint32_t cHpcb     :  1;
+-      uint32_t cMA       :  1;
+-      uint32_t sli_mode  :  4;
+-      uint32_t pcbLen    : 24;       /* bit 23:0  of memory based port
+-                                      * config block */
+-#else /*  __LITTLE_ENDIAN */
+-      uint32_t pcbLen    : 24;       /* bit 23:0  of memory based port
+-                                      * config block */
+-      uint32_t sli_mode  :  4;
+-      uint32_t cMA       :  1;
+-      uint32_t cHpcb     :  1;
+-      uint32_t cET       :  1;
+-      uint32_t cBE       :  1;
+-#endif
++typedef struct {
++      uint32_t pcbLen;
+       uint32_t pcbLow;       /* bit 31:0  of memory based port config block */
+       uint32_t pcbHigh;      /* bit 63:32 of memory based port config block */
+-      uint32_t hbainit[6];
+-
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint32_t rsvd      : 24;  /* Reserved                             */
+-      uint32_t cmv       :  1;  /* Configure Max VPIs                   */
+-      uint32_t ccrp      :  1;  /* Config Command Ring Polling          */
+-      uint32_t csah      :  1;  /* Configure Synchronous Abort Handling */
+-      uint32_t chbs      :  1;  /* Cofigure Host Backing store          */
+-      uint32_t cinb      :  1;  /* Enable Interrupt Notification Block  */
+-      uint32_t cerbm     :  1;  /* Configure Enhanced Receive Buf Mgmt  */
+-      uint32_t cmx       :  1;  /* Configure Max XRIs                   */
+-      uint32_t cmr       :  1;  /* Configure Max RPIs                   */
+-#else /*  __LITTLE_ENDIAN */
+-      uint32_t cmr       :  1;  /* Configure Max RPIs                   */
+-      uint32_t cmx       :  1;  /* Configure Max XRIs                   */
+-      uint32_t cerbm     :  1;  /* Configure Enhanced Receive Buf Mgmt  */
+-      uint32_t cinb      :  1;  /* Enable Interrupt Notification Block  */
+-      uint32_t chbs      :  1;  /* Cofigure Host Backing store          */
+-      uint32_t csah      :  1;  /* Configure Synchronous Abort Handling */
+-      uint32_t ccrp      :  1;  /* Config Command Ring Polling          */
+-      uint32_t cmv       :  1;  /* Configure Max VPIs                   */
+-      uint32_t rsvd      : 24;  /* Reserved                             */
+-#endif
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint32_t rsvd2     : 24;  /* Reserved                             */
+-      uint32_t gmv       :  1;  /* Grant Max VPIs                       */
+-      uint32_t gcrp      :  1;  /* Grant Command Ring Polling           */
+-      uint32_t gsah      :  1;  /* Grant Synchronous Abort Handling     */
+-      uint32_t ghbs      :  1;  /* Grant Host Backing Store             */
+-      uint32_t ginb      :  1;  /* Grant Interrupt Notification Block   */
+-      uint32_t gerbm     :  1;  /* Grant ERBM Request                   */
+-      uint32_t gmx       :  1;  /* Grant Max XRIs                       */
+-      uint32_t gmr       :  1;  /* Grant Max RPIs                       */
+-#else /*  __LITTLE_ENDIAN */
+-      uint32_t gmr       :  1;  /* Grant Max RPIs                       */
+-      uint32_t gmx       :  1;  /* Grant Max XRIs                       */
+-      uint32_t gerbm     :  1;  /* Grant ERBM Request                   */
+-      uint32_t ginb      :  1;  /* Grant Interrupt Notification Block   */
+-      uint32_t ghbs      :  1;  /* Grant Host Backing Store             */
+-      uint32_t gsah      :  1;  /* Grant Synchronous Abort Handling     */
+-      uint32_t gcrp      :  1;  /* Grant Command Ring Polling           */
+-      uint32_t gmv       :  1;  /* Grant Max VPIs                       */
+-      uint32_t rsvd2     : 24;  /* Reserved                             */
+-#endif
+-
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint32_t max_rpi   : 16;  /* Max RPIs Port should configure       */
+-      uint32_t max_xri   : 16;  /* Max XRIs Port should configure       */
+-#else /*  __LITTLE_ENDIAN */
+-      uint32_t max_xri   : 16;  /* Max XRIs Port should configure       */
+-      uint32_t max_rpi   : 16;  /* Max RPIs Port should configure       */
+-#endif
+-
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint32_t max_hbq   : 16;  /* Max HBQs Host expect to configure    */
+-      uint32_t rsvd3     : 16;  /* Max HBQs Host expect to configure    */
+-#else /*  __LITTLE_ENDIAN */
+-      uint32_t rsvd3     : 16;  /* Max HBQs Host expect to configure    */
+-      uint32_t max_hbq   : 16;  /* Max HBQs Host expect to configure    */
+-#endif
+-
+-      uint32_t rsvd4;           /* Reserved                             */
+-
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint32_t rsvd5      : 16;  /* Reserved                             */
+-      uint32_t max_vpi    : 16;  /* Max number of virt N-Ports           */
+-#else /*  __LITTLE_ENDIAN */
+-      uint32_t max_vpi    : 16;  /* Max number of virt N-Ports           */
+-      uint32_t rsvd5      : 16;  /* Reserved                             */
+-#endif
+-
++      uint32_t hbainit[5];
+ } CONFIG_PORT_VAR;
+ /* SLI-2 Port Control Block */
+@@ -2607,9 +2262,7 @@
+ #define MAILBOX_CMD_SIZE      (MAILBOX_CMD_WSIZE * sizeof(uint32_t))
+ typedef union {
+-      uint32_t varWords[MAILBOX_CMD_WSIZE - 1]; /* first word is type/
+-                                                  * feature/max ring number
+-                                                  */
++      uint32_t varWords[MAILBOX_CMD_WSIZE - 1];
+       LOAD_SM_VAR varLdSM;    /* cmd =  1 (LOAD_SM)        */
+       READ_NV_VAR varRDnvp;   /* cmd =  2 (READ_NVPARMS)   */
+       WRITE_NV_VAR varWTnvp;  /* cmd =  3 (WRITE_NVPARMS)  */
+@@ -2634,13 +2287,8 @@
+       CLEAR_LA_VAR varClearLA;        /* cmd = 22 (CLEAR_LA)       */
+       DUMP_VAR varDmp;        /* Warm Start DUMP mbx cmd   */
+       UNREG_D_ID_VAR varUnregDID; /* cmd = 0x23 (UNREG_D_ID)   */
+-      CONFIG_FARP_VAR varCfgFarp;     /* cmd = 0x25 (CONFIG_FARP)
+-                                       * NEW_FEATURE
+-                                       */
+-      struct config_hbq_var varCfgHbq;/* cmd = 0x7c (CONFIG_HBQ)  */
++      CONFIG_FARP_VAR varCfgFarp; /* cmd = 0x25 (CONFIG_FARP)  NEW_FEATURE */
+       CONFIG_PORT_VAR varCfgPort; /* cmd = 0x88 (CONFIG_PORT)  */
+-      REG_VPI_VAR varRegVpi;          /* cmd = 0x96 (REG_VPI) */
+-      UNREG_VPI_VAR varUnregVpi;      /* cmd = 0x97 (UNREG_VPI) */
+ } MAILVARIANTS;
+ /*
+@@ -2657,27 +2305,14 @@
+       __le32 rspPutInx;
+ };
+-struct sli2_desc {
+-      uint32_t unused1[16];
+-      struct lpfc_hgp host[MAX_RINGS];
+-      struct lpfc_pgp port[MAX_RINGS];
+-};
+-
+-struct sli3_desc {
++typedef struct _SLI2_DESC {
+       struct lpfc_hgp host[MAX_RINGS];
+-      uint32_t reserved[8];
+-      uint32_t hbq_put[16];
+-};
+-
+-struct sli3_pgp {
++      uint32_t unused1[16];
+       struct lpfc_pgp port[MAX_RINGS];
+-      uint32_t hbq_get[16];
+-};
++} SLI2_DESC;
+ typedef union {
+-      struct sli2_desc s2;
+-      struct sli3_desc s3;
+-      struct sli3_pgp  s3_pgp;
++      SLI2_DESC s2;
+ } SLI_VAR;
+ typedef struct {
+@@ -2983,25 +2618,6 @@
+       uint32_t fcpt_Length;   /* transfer ready for IWRITE */
+ } FCPT_FIELDS64;
+-/* IOCB Command template for CMD_IOCB_RCV_ELS64_CX (0xB7)
+-   or CMD_IOCB_RCV_SEQ64_CX (0xB5) */
+-
+-struct rcv_sli3 {
+-      uint32_t word8Rsvd;
+-#ifdef __BIG_ENDIAN_BITFIELD
+-      uint16_t vpi;
+-      uint16_t word9Rsvd;
+-#else  /*  __LITTLE_ENDIAN */
+-      uint16_t word9Rsvd;
+-      uint16_t vpi;
+-#endif
+-      uint32_t word10Rsvd;
+-      uint32_t acc_len;      /* accumulated length */
+-      struct ulp_bde64 bde2;
+-};
+-
+-
+-
+ typedef struct _IOCB {        /* IOCB structure */
+       union {
+               GENERIC_RSP grsp;       /* Generic response */
+@@ -3017,7 +2633,7 @@
+               /* SLI-2 structures */
+               struct ulp_bde64 cont64[2];     /* up to 2 64 bit continuation
+-                                            * bde_64s */
++                                         bde_64s */
+               ELS_REQUEST64 elsreq64; /* ELS_REQUEST template */
+               GEN_REQUEST64 genreq64; /* GEN_REQUEST template */
+               RCV_ELS_REQ64 rcvels64; /* RCV_ELS_REQ template */
+@@ -3079,20 +2695,9 @@
+       uint32_t ulpTimeout:8;
+ #endif
+-      union {
+-              struct rcv_sli3 rcvsli3; /* words 8 - 15 */
+-              uint32_t sli3Words[24]; /* 96 extra bytes for SLI-3 */
+-      } unsli3;
+-
+-#define ulpCt_h ulpXS
+-#define ulpCt_l ulpFCP2Rcvy
+-
+-#define IOCB_FCP         1    /* IOCB is used for FCP ELS cmds-ulpRsvByte */
+-#define IOCB_IP                  2    /* IOCB is used for IP ELS cmds */
+ #define PARM_UNUSED        0  /* PU field (Word 4) not used */
+ #define PARM_REL_OFF       1  /* PU field (Word 4) = R. O. */
+ #define PARM_READ_CHECK    2  /* PU field (Word 4) = Data Transfer Length */
+-#define PARM_NPIV_DID    3
+ #define CLASS1             0  /* Class 1 */
+ #define CLASS2             1  /* Class 2 */
+ #define CLASS3             2  /* Class 3 */
+@@ -3113,51 +2718,39 @@
+ #define IOSTAT_RSVD2           0xC
+ #define IOSTAT_RSVD3           0xD
+ #define IOSTAT_RSVD4           0xE
+-#define IOSTAT_NEED_BUFFER     0xF
++#define IOSTAT_RSVD5           0xF
+ #define IOSTAT_DRIVER_REJECT   0x10   /* ulpStatus  - Driver defined */
+ #define IOSTAT_DEFAULT         0xF    /* Same as rsvd5 for now */
+ #define IOSTAT_CNT             0x11
+ } IOCB_t;
+-/* Structure used for a single HBQ entry */
+-struct lpfc_hbq_entry {
+-      struct ulp_bde64 bde;
+-      uint32_t buffer_tag;
+-};
+-
+ #define SLI1_SLIM_SIZE   (4 * 1024)
+ /* Up to 498 IOCBs will fit into 16k
+  * 256 (MAILBOX_t) + 140 (PCB_t) + ( 32 (IOCB_t) * 498 ) = < 16384
+  */
+-#define SLI2_SLIM_SIZE   (64 * 1024)
++#define SLI2_SLIM_SIZE   (16 * 1024)
+ /* Maximum IOCBs that will fit in SLI2 slim */
+ #define MAX_SLI2_IOCB    498
+-#define MAX_SLIM_IOCB_SIZE (SLI2_SLIM_SIZE - \
+-                          (sizeof(MAILBOX_t) + sizeof(PCB_t)))
+-
+-/* HBQ entries are 4 words each = 4k */
+-#define LPFC_TOTAL_HBQ_SIZE (sizeof(struct lpfc_hbq_entry) *  \
+-                           lpfc_sli_hbq_count())
+ struct lpfc_sli2_slim {
+       MAILBOX_t mbx;
+       PCB_t pcb;
+-      IOCB_t IOCBs[MAX_SLIM_IOCB_SIZE];
++      IOCB_t IOCBs[MAX_SLI2_IOCB];
+ };
+-/*
+- * This function checks PCI device to allow special handling for LC HBAs.
+- *
+- * Parameters:
+- * device : struct pci_dev 's device field
+- *
+- * return 1 => TRUE
+- *        0 => FALSE
+- */
++/*******************************************************************
++This macro check PCI device to allow special handling for LC HBAs.
 +
-+      mutex_lock(&hidden_inode->i_mutex);
++Parameters:
++device : struct pci_dev 's device field
 +
-+      if (!permission(hidden_inode, MAY_EXEC, NULL))
-+              wh_hidden_dentry =
-+                      lookup_one_len(UNIONFS_DIR_OPAQUE, hidden_dentry,
-+                                     sizeof(UNIONFS_DIR_OPAQUE) - 1);
-+      else {
-+              args.is_opaque.dentry = hidden_dentry;
-+              run_sioq(__is_opaque_dir, &args);
-+              wh_hidden_dentry = args.ret;
++return 1 => TRUE
++       0 => FALSE
++ *******************************************************************/
+ static inline int
+ lpfc_is_LC_HBA(unsigned short device)
+ {
+@@ -3173,16 +2766,3 @@
+       else
+               return 0;
+ }
+-
+-/*
+- * Determine if an IOCB failed because of a link event or firmware reset.
+- */
+-
+-static inline int
+-lpfc_error_lost_link(IOCB_t *iocbp)
+-{
+-      return (iocbp->ulpStatus == IOSTAT_LOCAL_REJECT &&
+-              (iocbp->un.ulpWord[4] == IOERR_SLI_ABORTED ||
+-               iocbp->un.ulpWord[4] == IOERR_LINK_DOWN ||
+-               iocbp->un.ulpWord[4] == IOERR_SLI_DOWN));
+-}
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_init.c linux-2.6.22-570/drivers/scsi/lpfc/lpfc_init.c
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_init.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_init.c     2007-07-08 19:32:17.000000000 -0400
+@@ -27,7 +27,6 @@
+ #include <linux/kthread.h>
+ #include <linux/pci.h>
+ #include <linux/spinlock.h>
+-#include <linux/ctype.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_device.h>
+@@ -41,20 +40,15 @@
+ #include "lpfc.h"
+ #include "lpfc_logmsg.h"
+ #include "lpfc_crtn.h"
+-#include "lpfc_vport.h"
+ #include "lpfc_version.h"
+-#include "lpfc_vport.h"
+ static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int);
+ static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
+ static int lpfc_post_rcv_buf(struct lpfc_hba *);
+ static struct scsi_transport_template *lpfc_transport_template = NULL;
+-static struct scsi_transport_template *lpfc_vport_transport_template = NULL;
+ static DEFINE_IDR(lpfc_hba_index);
+-
+-
+ /************************************************************************/
+ /*                                                                      */
+ /*    lpfc_config_port_prep                                             */
+@@ -67,7 +61,7 @@
+ /*                                                                      */
+ /************************************************************************/
+ int
+-lpfc_config_port_prep(struct lpfc_hba *phba)
++lpfc_config_port_prep(struct lpfc_hba * phba)
+ {
+       lpfc_vpd_t *vp = &phba->vpd;
+       int i = 0, rc;
+@@ -81,12 +75,12 @@
+       pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!pmb) {
+-              phba->link_state = LPFC_HBA_ERROR;
++              phba->hba_state = LPFC_HBA_ERROR;
+               return -ENOMEM;
+       }
+       mb = &pmb->mb;
+-      phba->link_state = LPFC_INIT_MBX_CMDS;
++      phba->hba_state = LPFC_INIT_MBX_CMDS;
+       if (lpfc_is_LC_HBA(phba->pcidev->device)) {
+               if (init_key) {
+@@ -106,7 +100,9 @@
+               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
+               if (rc != MBX_SUCCESS) {
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
++                      lpfc_printf_log(phba,
++                                      KERN_ERR,
++                                      LOG_MBOX,
+                                       "%d:0324 Config Port initialization "
+                                       "error, mbxCmd x%x READ_NVPARM, "
+                                       "mbxStatus x%x\n",
+@@ -116,18 +112,16 @@
+                       return -ERESTART;
+               }
+               memcpy(phba->wwnn, (char *)mb->un.varRDnvp.nodename,
+-                     sizeof(phba->wwnn));
+-              memcpy(phba->wwpn, (char *)mb->un.varRDnvp.portname,
+-                     sizeof(phba->wwpn));
++                     sizeof (mb->un.varRDnvp.nodename));
+       }
+-      phba->sli3_options = 0x0;
+-
+       /* Setup and issue mailbox READ REV command */
+       lpfc_read_rev(phba, pmb);
+       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
+       if (rc != MBX_SUCCESS) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
++              lpfc_printf_log(phba,
++                              KERN_ERR,
++                              LOG_INIT,
+                               "%d:0439 Adapter failed to init, mbxCmd x%x "
+                               "READ_REV, mbxStatus x%x\n",
+                               phba->brd_no,
+@@ -136,7 +130,6 @@
+               return -ERESTART;
+       }
+-
+       /*
+        * The value of rr must be 1 since the driver set the cv field to 1.
+        * This setting requires the FW to set all revision fields.
+@@ -151,12 +144,8 @@
+               return -ERESTART;
+       }
+-      if (phba->sli_rev == 3 && !mb->un.varRdRev.v3rsp)
+-              return -EINVAL;
+-
+       /* Save information as VPD data */
+       vp->rev.rBit = 1;
+-      memcpy(&vp->sli3Feat, &mb->un.varRdRev.sli3Feat, sizeof(uint32_t));
+       vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev;
+       memcpy(vp->rev.sli1FwName, (char*) mb->un.varRdRev.sli1FwName, 16);
+       vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev;
+@@ -172,13 +161,6 @@
+       vp->rev.postKernRev = mb->un.varRdRev.postKernRev;
+       vp->rev.opFwRev = mb->un.varRdRev.opFwRev;
+-      /* If the sli feature level is less then 9, we must
+-       * tear down all RPIs and VPIs on link down if NPIV
+-       * is enabled.
+-       */
+-      if (vp->rev.feaLevelHigh < 9)
+-              phba->sli3_options |= LPFC_SLI3_VPORT_TEARDOWN;
+-
+       if (lpfc_is_LC_HBA(phba->pcidev->device))
+               memcpy(phba->RandomData, (char *)&mb->un.varWords[24],
+                                               sizeof (phba->RandomData));
+@@ -230,34 +212,48 @@
+ /*                                                                      */
+ /************************************************************************/
+ int
+-lpfc_config_port_post(struct lpfc_hba *phba)
++lpfc_config_port_post(struct lpfc_hba * phba)
+ {
+-      struct lpfc_vport *vport = phba->pport;
+       LPFC_MBOXQ_t *pmb;
+       MAILBOX_t *mb;
+       struct lpfc_dmabuf *mp;
+       struct lpfc_sli *psli = &phba->sli;
+       uint32_t status, timeout;
+-      int i, j;
+-      int rc;
++      int i, j, rc;
+       pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!pmb) {
+-              phba->link_state = LPFC_HBA_ERROR;
++              phba->hba_state = LPFC_HBA_ERROR;
+               return -ENOMEM;
+       }
+       mb = &pmb->mb;
++      lpfc_config_link(phba, pmb);
++      rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
++      if (rc != MBX_SUCCESS) {
++              lpfc_printf_log(phba,
++                              KERN_ERR,
++                              LOG_INIT,
++                              "%d:0447 Adapter failed init, mbxCmd x%x "
++                              "CONFIG_LINK mbxStatus x%x\n",
++                              phba->brd_no,
++                              mb->mbxCommand, mb->mbxStatus);
++              phba->hba_state = LPFC_HBA_ERROR;
++              mempool_free( pmb, phba->mbox_mem_pool);
++              return -EIO;
 +      }
 +
-+      mutex_unlock(&hidden_inode->i_mutex);
-+
-+      if (IS_ERR(wh_hidden_dentry)) {
-+              err = PTR_ERR(wh_hidden_dentry);
-+              goto out;
+       /* Get login parameters for NID.  */
+-      lpfc_read_sparam(phba, pmb, 0);
+-      pmb->vport = vport;
++      lpfc_read_sparam(phba, pmb);
+       if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
++              lpfc_printf_log(phba,
++                              KERN_ERR,
++                              LOG_INIT,
+                               "%d:0448 Adapter failed init, mbxCmd x%x "
+                               "READ_SPARM mbxStatus x%x\n",
+                               phba->brd_no,
+                               mb->mbxCommand, mb->mbxStatus);
+-              phba->link_state = LPFC_HBA_ERROR;
++              phba->hba_state = LPFC_HBA_ERROR;
+               mp = (struct lpfc_dmabuf *) pmb->context1;
+               mempool_free( pmb, phba->mbox_mem_pool);
+               lpfc_mbuf_free(phba, mp->virt, mp->phys);
+@@ -267,27 +263,25 @@
+       mp = (struct lpfc_dmabuf *) pmb->context1;
+-      memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
++      memcpy(&phba->fc_sparam, mp->virt, sizeof (struct serv_parm));
+       lpfc_mbuf_free(phba, mp->virt, mp->phys);
+       kfree(mp);
+       pmb->context1 = NULL;
+       if (phba->cfg_soft_wwnn)
+-              u64_to_wwn(phba->cfg_soft_wwnn,
+-                         vport->fc_sparam.nodeName.u.wwn);
++              u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
+       if (phba->cfg_soft_wwpn)
+-              u64_to_wwn(phba->cfg_soft_wwpn,
+-                         vport->fc_sparam.portName.u.wwn);
+-      memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
++              u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
++      memcpy(&phba->fc_nodename, &phba->fc_sparam.nodeName,
+              sizeof (struct lpfc_name));
+-      memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
++      memcpy(&phba->fc_portname, &phba->fc_sparam.portName,
+              sizeof (struct lpfc_name));
+       /* If no serial number in VPD data, use low 6 bytes of WWNN */
+       /* This should be consolidated into parse_vpd ? - mr */
+       if (phba->SerialNumber[0] == 0) {
+               uint8_t *outptr;
+-              outptr = &vport->fc_nodename.u.s.IEEE[0];
++              outptr = &phba->fc_nodename.u.s.IEEE[0];
+               for (i = 0; i < 12; i++) {
+                       status = *outptr++;
+                       j = ((status & 0xf0) >> 4);
+@@ -309,14 +303,15 @@
+       }
+       lpfc_read_config(phba, pmb);
+-      pmb->vport = vport;
+       if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
++              lpfc_printf_log(phba,
++                              KERN_ERR,
++                              LOG_INIT,
+                               "%d:0453 Adapter failed to init, mbxCmd x%x "
+                               "READ_CONFIG, mbxStatus x%x\n",
+                               phba->brd_no,
+                               mb->mbxCommand, mb->mbxStatus);
+-              phba->link_state = LPFC_HBA_ERROR;
++              phba->hba_state = LPFC_HBA_ERROR;
+               mempool_free( pmb, phba->mbox_mem_pool);
+               return -EIO;
+       }
+@@ -343,7 +338,9 @@
+           || ((phba->cfg_link_speed == LINK_SPEED_10G)
+               && !(phba->lmt & LMT_10Gb))) {
+               /* Reset link speed to auto */
+-              lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT,
++              lpfc_printf_log(phba,
++                      KERN_WARNING,
++                      LOG_LINK_EVENT,
+                       "%d:1302 Invalid speed for this board: "
+                       "Reset link speed to auto: x%x\n",
+                       phba->brd_no,
+@@ -351,7 +348,7 @@
+                       phba->cfg_link_speed = LINK_SPEED_AUTO;
+       }
+-      phba->link_state = LPFC_LINK_DOWN;
++      phba->hba_state = LPFC_LINK_DOWN;
+       /* Only process IOCBs on ring 0 till hba_state is READY */
+       if (psli->ring[psli->extra_ring].cmdringaddr)
+@@ -362,11 +359,10 @@
+               psli->ring[psli->next_ring].flag |= LPFC_STOP_IOCB_EVENT;
+       /* Post receive buffers for desired rings */
+-      if (phba->sli_rev != 3)
+       lpfc_post_rcv_buf(phba);
+       /* Enable appropriate host interrupts */
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       status = readl(phba->HCregaddr);
+       status |= HC_MBINT_ENA | HC_ERINT_ENA | HC_LAINT_ENA;
+       if (psli->num_rings > 0)
+@@ -384,24 +380,22 @@
+       writel(status, phba->HCregaddr);
+       readl(phba->HCregaddr); /* flush */
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       /*
+        * Setup the ring 0 (els)  timeout handler
+        */
+       timeout = phba->fc_ratov << 1;
+-      mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
+-      mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+-      phba->hb_outstanding = 0;
+-      phba->last_completion_time = jiffies;
++      mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
+       lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
+       pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-      pmb->vport = vport;
+       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+       lpfc_set_loopback_flag(phba);
+       if (rc != MBX_SUCCESS) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
++              lpfc_printf_log(phba,
++                              KERN_ERR,
++                              LOG_INIT,
+                               "%d:0454 Adapter failed to init, mbxCmd x%x "
+                               "INIT_LINK, mbxStatus x%x\n",
+                               phba->brd_no,
+@@ -414,7 +408,7 @@
+               writel(0xffffffff, phba->HAregaddr);
+               readl(phba->HAregaddr); /* flush */
+-              phba->link_state = LPFC_HBA_ERROR;
++              phba->hba_state = LPFC_HBA_ERROR;
+               if (rc != MBX_BUSY)
+                       mempool_free(pmb, phba->mbox_mem_pool);
+               return -EIO;
+@@ -435,19 +429,18 @@
+ /*                                                                      */
+ /************************************************************************/
+ int
+-lpfc_hba_down_prep(struct lpfc_hba *phba)
++lpfc_hba_down_prep(struct lpfc_hba * phba)
+ {
+-      struct lpfc_vport *vport = phba->pport;
+-
+       /* Disable interrupts */
+       writel(0, phba->HCregaddr);
+       readl(phba->HCregaddr); /* flush */
+-      list_for_each_entry(vport, &phba->port_list, listentry) {
+-              lpfc_cleanup_discovery_resources(vport);
+-      }
++      /* Cleanup potential discovery resources */
++      lpfc_els_flush_rscn(phba);
++      lpfc_els_flush_cmd(phba);
++      lpfc_disc_flush_list(phba);
+-      return 0;
++      return (0);
+ }
+ /************************************************************************/
+@@ -460,16 +453,13 @@
+ /*                                                                      */
+ /************************************************************************/
+ int
+-lpfc_hba_down_post(struct lpfc_hba *phba)
++lpfc_hba_down_post(struct lpfc_hba * phba)
+ {
+       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_sli_ring *pring;
+       struct lpfc_dmabuf *mp, *next_mp;
+       int i;
+-      if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
+-              lpfc_sli_hbqbuf_free_all(phba);
+-      else {
+       /* Cleanup preposted buffers on the ELS ring */
+       pring = &psli->ring[LPFC_ELS_RING];
+       list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
+@@ -478,7 +468,6 @@
+               lpfc_mbuf_free(phba, mp->virt, mp->phys);
+               kfree(mp);
+       }
+-      }
+       for (i = 0; i < psli->num_rings; i++) {
+               pring = &psli->ring[i];
+@@ -488,119 +477,6 @@
+       return 0;
+ }
+-/* HBA heart beat timeout handler */
+-void
+-lpfc_hb_timeout(unsigned long ptr)
+-{
+-      struct lpfc_hba *phba;
+-      unsigned long iflag;
+-
+-      phba = (struct lpfc_hba *)ptr;
+-      spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
+-      if (!(phba->pport->work_port_events & WORKER_HB_TMO))
+-              phba->pport->work_port_events |= WORKER_HB_TMO;
+-      spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
+-
+-      if (phba->work_wait)
+-              wake_up(phba->work_wait);
+-      return;
+-}
+-
+-static void
+-lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
+-{
+-      unsigned long drvr_flag;
+-
+-      spin_lock_irqsave(&phba->hbalock, drvr_flag);
+-      phba->hb_outstanding = 0;
+-      spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+-
+-      mempool_free(pmboxq, phba->mbox_mem_pool);
+-      if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) &&
+-              !(phba->link_state == LPFC_HBA_ERROR) &&
+-              !(phba->pport->fc_flag & FC_UNLOADING))
+-              mod_timer(&phba->hb_tmofunc,
+-                      jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+-      return;
+-}
+-
+-void
+-lpfc_hb_timeout_handler(struct lpfc_hba *phba)
+-{
+-      LPFC_MBOXQ_t *pmboxq;
+-      int retval;
+-      struct lpfc_sli *psli = &phba->sli;
+-
+-      if ((phba->link_state == LPFC_HBA_ERROR) ||
+-              (phba->pport->fc_flag & FC_UNLOADING) ||
+-              (phba->pport->fc_flag & FC_OFFLINE_MODE))
+-              return;
+-
+-      spin_lock_irq(&phba->pport->work_port_lock);
+-      /* If the timer is already canceled do nothing */
+-      if (!(phba->pport->work_port_events & WORKER_HB_TMO)) {
+-              spin_unlock_irq(&phba->pport->work_port_lock);
+-              return;
+-      }
+-
+-      if (time_after(phba->last_completion_time + LPFC_HB_MBOX_INTERVAL * HZ,
+-              jiffies)) {
+-              spin_unlock_irq(&phba->pport->work_port_lock);
+-              if (!phba->hb_outstanding)
+-                      mod_timer(&phba->hb_tmofunc,
+-                              jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+-              else
+-                      mod_timer(&phba->hb_tmofunc,
+-                              jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
+-              return;
+-      }
+-      spin_unlock_irq(&phba->pport->work_port_lock);
+-
+-      /* If there is no heart beat outstanding, issue a heartbeat command */
+-      if (!phba->hb_outstanding) {
+-              pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
+-              if (!pmboxq) {
+-                      mod_timer(&phba->hb_tmofunc,
+-                              jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+-                      return;
+-              }
+-
+-              lpfc_heart_beat(phba, pmboxq);
+-              pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl;
+-              pmboxq->vport = phba->pport;
+-              retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
+-
+-              if (retval != MBX_BUSY && retval != MBX_SUCCESS) {
+-                      mempool_free(pmboxq, phba->mbox_mem_pool);
+-                      mod_timer(&phba->hb_tmofunc,
+-                              jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+-                      return;
+-              }
+-              mod_timer(&phba->hb_tmofunc,
+-                      jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
+-              phba->hb_outstanding = 1;
+-              return;
+-      } else {
+-              /*
+-               * If heart beat timeout called with hb_outstanding set we
+-               * need to take the HBA offline.
+-               */
+-              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+-                      "%d:0459 Adapter heartbeat failure, taking "
+-                      "this port offline.\n", phba->brd_no);
+-
+-              spin_lock_irq(&phba->hbalock);
+-              psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+-              spin_unlock_irq(&phba->hbalock);
+-
+-              lpfc_offline_prep(phba);
+-              lpfc_offline(phba);
+-              lpfc_unblock_mgmt_io(phba);
+-              phba->link_state = LPFC_HBA_ERROR;
+-              lpfc_hba_down_post(phba);
+-      }
+-}
+-
+ /************************************************************************/
+ /*                                                                      */
+ /*    lpfc_handle_eratt                                                 */
+@@ -610,15 +486,11 @@
+ /*                                                                      */
+ /************************************************************************/
+ void
+-lpfc_handle_eratt(struct lpfc_hba *phba)
++lpfc_handle_eratt(struct lpfc_hba * phba)
+ {
+-      struct lpfc_vport *vport = phba->pport;
+       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_sli_ring  *pring;
+-      struct lpfc_vport *port_iterator;
+       uint32_t event_data;
+-      struct Scsi_Host  *shost;
+-
+       /* If the pci channel is offline, ignore possible errors,
+        * since we cannot communicate with the pci card anyway. */
+       if (pci_channel_offline(phba->pcidev))
+@@ -632,17 +504,10 @@
+                               "Data: x%x x%x x%x\n",
+                               phba->brd_no, phba->work_hs,
+                               phba->work_status[0], phba->work_status[1]);
+-              list_for_each_entry(port_iterator, &phba->port_list,
+-                                  listentry) {
+-                      shost = lpfc_shost_from_vport(port_iterator);
+-
+-                      spin_lock_irq(shost->host_lock);
+-                      port_iterator->fc_flag |= FC_ESTABLISH_LINK;
+-                      spin_unlock_irq(shost->host_lock);
+-              }
+-              spin_lock_irq(&phba->hbalock);
++              spin_lock_irq(phba->host->host_lock);
++              phba->fc_flag |= FC_ESTABLISH_LINK;
+               psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+-              spin_unlock_irq(&phba->hbalock);
++              spin_unlock_irq(phba->host->host_lock);
+               /*
+               * Firmware stops when it triggled erratt with HS_FFER6.
+@@ -679,18 +544,15 @@
+                               phba->work_status[0], phba->work_status[1]);
+               event_data = FC_REG_DUMP_EVENT;
+-              shost = lpfc_shost_from_vport(vport);
+-              fc_host_post_vendor_event(shost, fc_get_event_number(),
++              fc_host_post_vendor_event(phba->host, fc_get_event_number(),
+                               sizeof(event_data), (char *) &event_data,
+                               SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
+-              spin_lock_irq(&phba->hbalock);
+               psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+-              spin_unlock_irq(&phba->hbalock);
+               lpfc_offline_prep(phba);
+               lpfc_offline(phba);
+               lpfc_unblock_mgmt_io(phba);
+-              phba->link_state = LPFC_HBA_ERROR;
++              phba->hba_state = LPFC_HBA_ERROR;
+               lpfc_hba_down_post(phba);
+       }
+ }
+@@ -704,11 +566,9 @@
+ /*                                                                      */
+ /************************************************************************/
+ void
+-lpfc_handle_latt(struct lpfc_hba *phba)
++lpfc_handle_latt(struct lpfc_hba * phba)
+ {
+-      struct lpfc_vport *vport = phba->pport;
+       struct lpfc_sli *psli = &phba->sli;
+-      struct lpfc_vport *port_iterator;
+       LPFC_MBOXQ_t *pmb;
+       volatile uint32_t control;
+       struct lpfc_dmabuf *mp;
+@@ -729,22 +589,20 @@
+       rc = -EIO;
+       /* Cleanup any outstanding ELS commands */
+-      list_for_each_entry(port_iterator, &phba->port_list, listentry)
+-              lpfc_els_flush_cmd(port_iterator);
++      lpfc_els_flush_cmd(phba);
+       psli->slistat.link_event++;
+       lpfc_read_la(phba, pmb, mp);
+       pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la;
+-      pmb->vport = vport;
+       rc = lpfc_sli_issue_mbox (phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB));
+       if (rc == MBX_NOT_FINISHED)
+               goto lpfc_handle_latt_free_mbuf;
+       /* Clear Link Attention in HA REG */
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       writel(HA_LATT, phba->HAregaddr);
+       readl(phba->HAregaddr); /* flush */
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       return;
+@@ -756,7 +614,7 @@
+       mempool_free(pmb, phba->mbox_mem_pool);
+ lpfc_handle_latt_err_exit:
+       /* Enable Link attention interrupts */
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       psli->sli_flag |= LPFC_PROCESS_LA;
+       control = readl(phba->HCregaddr);
+       control |= HC_LAINT_ENA;
+@@ -766,13 +624,15 @@
+       /* Clear Link Attention in HA REG */
+       writel(HA_LATT, phba->HAregaddr);
+       readl(phba->HAregaddr); /* flush */
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       lpfc_linkdown(phba);
+-      phba->link_state = LPFC_HBA_ERROR;
++      phba->hba_state = LPFC_HBA_ERROR;
+       /* The other case is an error from issue_mbox */
+       if (rc == -ENOMEM)
+-              lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
++              lpfc_printf_log(phba,
++                              KERN_WARNING,
++                              LOG_MBOX,
+                               "%d:0300 READ_LA: no buffers\n",
+                               phba->brd_no);
+@@ -786,7 +646,7 @@
+ /*                                                                      */
+ /************************************************************************/
+ static int
+-lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
++lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len)
+ {
+       uint8_t lenlo, lenhi;
+       int Length;
+@@ -798,7 +658,9 @@
+               return 0;
+       /* Vital Product */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
++      lpfc_printf_log(phba,
++                      KERN_INFO,
++                      LOG_INIT,
+                       "%d:0455 Vital Product Data: x%x x%x x%x x%x\n",
+                       phba->brd_no,
+                       (uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2],
+@@ -923,7 +785,7 @@
+ }
+ static void
+-lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
++lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
+ {
+       lpfc_vpd_t *vp;
+       uint16_t dev_id = phba->pcidev->device;
+@@ -1081,7 +943,7 @@
+ /*   Returns the number of buffers NOT posted.    */
+ /**************************************************/
+ int
+-lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt,
++lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
+                int type)
+ {
+       IOCB_t *icmd;
+@@ -1093,7 +955,9 @@
+       /* While there are buffers to post */
+       while (cnt > 0) {
+               /* Allocate buffer for  command iocb */
++              spin_lock_irq(phba->host->host_lock);
+               iocb = lpfc_sli_get_iocbq(phba);
++              spin_unlock_irq(phba->host->host_lock);
+               if (iocb == NULL) {
+                       pring->missbufcnt = cnt;
+                       return cnt;
+@@ -1108,7 +972,9 @@
+                                               &mp1->phys);
+               if (mp1 == 0 || mp1->virt == 0) {
+                       kfree(mp1);
++                      spin_lock_irq(phba->host->host_lock);
+                       lpfc_sli_release_iocbq(phba, iocb);
++                      spin_unlock_irq(phba->host->host_lock);
+                       pring->missbufcnt = cnt;
+                       return cnt;
+               }
+@@ -1124,7 +990,9 @@
+                               kfree(mp2);
+                               lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
+                               kfree(mp1);
++                              spin_lock_irq(phba->host->host_lock);
+                               lpfc_sli_release_iocbq(phba, iocb);
++                              spin_unlock_irq(phba->host->host_lock);
+                               pring->missbufcnt = cnt;
+                               return cnt;
+                       }
+@@ -1150,6 +1018,7 @@
+               icmd->ulpCommand = CMD_QUE_RING_BUF64_CN;
+               icmd->ulpLe = 1;
++              spin_lock_irq(phba->host->host_lock);
+               if (lpfc_sli_issue_iocb(phba, pring, iocb, 0) == IOCB_ERROR) {
+                       lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
+                       kfree(mp1);
+@@ -1161,12 +1030,15 @@
+                       }
+                       lpfc_sli_release_iocbq(phba, iocb);
+                       pring->missbufcnt = cnt;
++                      spin_unlock_irq(phba->host->host_lock);
+                       return cnt;
+               }
++              spin_unlock_irq(phba->host->host_lock);
+               lpfc_sli_ringpostbuf_put(phba, pring, mp1);
+-              if (mp2)
++              if (mp2) {
+                       lpfc_sli_ringpostbuf_put(phba, pring, mp2);
+               }
 +      }
+       pring->missbufcnt = 0;
+       return 0;
+ }
+@@ -1178,7 +1050,7 @@
+ /*                                                                      */
+ /************************************************************************/
+ static int
+-lpfc_post_rcv_buf(struct lpfc_hba *phba)
++lpfc_post_rcv_buf(struct lpfc_hba * phba)
+ {
+       struct lpfc_sli *psli = &phba->sli;
+@@ -1279,7 +1151,7 @@
+ {
+       int t;
+       uint32_t *HashWorking;
+-      uint32_t *pwwnn = (uint32_t *) phba->wwnn;
++      uint32_t *pwwnn = phba->wwnn;
+       HashWorking = kmalloc(80 * sizeof(uint32_t), GFP_KERNEL);
+       if (!HashWorking)
+@@ -1298,76 +1170,64 @@
+ }
+ static void
+-lpfc_cleanup(struct lpfc_vport *vport)
++lpfc_cleanup(struct lpfc_hba * phba)
+ {
+       struct lpfc_nodelist *ndlp, *next_ndlp;
+       /* clean up phba - lpfc specific */
+-      lpfc_can_disctmo(vport);
+-      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
++      lpfc_can_disctmo(phba);
++      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
+               lpfc_nlp_put(ndlp);
 +
-+      /* This is an opaque dir iff wh_hidden_dentry is positive */
-+      err = !!wh_hidden_dentry->d_inode;
++      INIT_LIST_HEAD(&phba->fc_nodes);
 +
-+      dput(wh_hidden_dentry);
-+out:
-+      return err;
-+}
+       return;
+ }
+ static void
+ lpfc_establish_link_tmo(unsigned long ptr)
+ {
+-      struct lpfc_hba   *phba = (struct lpfc_hba *) ptr;
+-      struct lpfc_vport *vport = phba->pport;
++      struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
+       unsigned long iflag;
 +
-+/* main (and complex) driver function for Unionfs's lookup */
-+struct dentry *unionfs_lookup_backend(struct dentry *dentry,
-+                                    struct nameidata *nd, int lookupmode)
-+{
-+      int err = 0;
-+      struct dentry *hidden_dentry = NULL;
-+      struct dentry *wh_hidden_dentry = NULL;
-+      struct dentry *hidden_dir_dentry = NULL;
-+      struct dentry *parent_dentry = NULL;
-+      int bindex, bstart, bend, bopaque;
-+      int dentry_count = 0;   /* Number of positive dentries. */
-+      int first_dentry_offset = -1; /* -1 is uninitialized */
-+      struct dentry *first_dentry = NULL;
-+      struct dentry *first_hidden_dentry = NULL;
-+      struct vfsmount *first_hidden_mnt = NULL;
-+      int locked_parent = 0;
-+      int locked_child = 0;
-+      int allocated_new_info = 0;
-+
-+      int opaque;
-+      char *whname = NULL;
-+      const char *name;
-+      int namelen;
+       /* Re-establishing Link, timer expired */
+       lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
+                       "%d:1300 Re-establishing Link, timer expired "
+                       "Data: x%x x%x\n",
+-                      phba->brd_no, vport->fc_flag,
+-                      vport->port_state);
+-      list_for_each_entry(vport, &phba->port_list, listentry) {
+-              struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+-              spin_lock_irqsave(shost->host_lock, iflag);
+-              vport->fc_flag &= ~FC_ESTABLISH_LINK;
+-              spin_unlock_irqrestore(shost->host_lock, iflag);
+-      }
++                      phba->brd_no, phba->fc_flag, phba->hba_state);
++      spin_lock_irqsave(phba->host->host_lock, iflag);
++      phba->fc_flag &= ~FC_ESTABLISH_LINK;
++      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+ }
+-void
+-lpfc_stop_vport_timers(struct lpfc_vport *vport)
+-{
+-      del_timer_sync(&vport->els_tmofunc);
+-      del_timer_sync(&vport->fc_fdmitmo);
+-      lpfc_can_disctmo(vport);
+-      return;
+-}
+-
+-static void
+-lpfc_stop_phba_timers(struct lpfc_hba *phba)
++static int
++lpfc_stop_timer(struct lpfc_hba * phba)
+ {
+-      struct lpfc_vport *vport;
++      struct lpfc_sli *psli = &phba->sli;
+       del_timer_sync(&phba->fcp_poll_timer);
+       del_timer_sync(&phba->fc_estabtmo);
+-      list_for_each_entry(vport, &phba->port_list, listentry)
+-              lpfc_stop_vport_timers(vport);
+-      del_timer_sync(&phba->sli.mbox_tmo);
+-      del_timer_sync(&phba->fabric_block_timer);
+-      phba->hb_outstanding = 0;
+-      del_timer_sync(&phba->hb_tmofunc);
+-      return;
++      del_timer_sync(&phba->fc_disctmo);
++      del_timer_sync(&phba->fc_fdmitmo);
++      del_timer_sync(&phba->els_tmofunc);
++      psli = &phba->sli;
++      del_timer_sync(&psli->mbox_tmo);
++      return(1);
+ }
+ int
+-lpfc_online(struct lpfc_hba *phba)
++lpfc_online(struct lpfc_hba * phba)
+ {
+-      struct lpfc_vport *vport = phba->pport;
+-
+       if (!phba)
+               return 0;
+-      if (!(vport->fc_flag & FC_OFFLINE_MODE))
++      if (!(phba->fc_flag & FC_OFFLINE_MODE))
+               return 0;
+-      lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
++      lpfc_printf_log(phba,
++                     KERN_WARNING,
++                     LOG_INIT,
+                      "%d:0458 Bring Adapter online\n",
+                      phba->brd_no);
+@@ -1383,14 +1243,9 @@
+               return 1;
+       }
+-      list_for_each_entry(vport, &phba->port_list, listentry) {
+-              struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-              spin_lock_irq(shost->host_lock);
+-              vport->fc_flag &= ~FC_OFFLINE_MODE;
+-              if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
+-                      vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+-              spin_unlock_irq(shost->host_lock);
+-      }
++      spin_lock_irq(phba->host->host_lock);
++      phba->fc_flag &= ~FC_OFFLINE_MODE;
++      spin_unlock_irq(phba->host->host_lock);
+       lpfc_unblock_mgmt_io(phba);
+       return 0;
+@@ -1401,9 +1256,9 @@
+ {
+       unsigned long iflag;
+-      spin_lock_irqsave(&phba->hbalock, iflag);
+-      phba->sli.sli_flag |= LPFC_BLOCK_MGMT_IO;
+-      spin_unlock_irqrestore(&phba->hbalock, iflag);
++      spin_lock_irqsave(phba->host->host_lock, iflag);
++      phba->fc_flag |= FC_BLOCK_MGMT_IO;
++      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+ }
+ void
+@@ -1411,18 +1266,17 @@
+ {
+       unsigned long iflag;
+-      spin_lock_irqsave(&phba->hbalock, iflag);
+-      phba->sli.sli_flag &= ~LPFC_BLOCK_MGMT_IO;
+-      spin_unlock_irqrestore(&phba->hbalock, iflag);
++      spin_lock_irqsave(phba->host->host_lock, iflag);
++      phba->fc_flag &= ~FC_BLOCK_MGMT_IO;
++      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+ }
+ void
+ lpfc_offline_prep(struct lpfc_hba * phba)
+ {
+-      struct lpfc_vport *vport = phba->pport;
+       struct lpfc_nodelist  *ndlp, *next_ndlp;
+-      if (vport->fc_flag & FC_OFFLINE_MODE)
++      if (phba->fc_flag & FC_OFFLINE_MODE)
+               return;
+       lpfc_block_mgmt_io(phba);
+@@ -1430,49 +1284,39 @@
+       lpfc_linkdown(phba);
+       /* Issue an unreg_login to all nodes */
+-      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
++      list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
+               if (ndlp->nlp_state != NLP_STE_UNUSED_NODE)
+-                      lpfc_unreg_rpi(vport, ndlp);
++                      lpfc_unreg_rpi(phba, ndlp);
+       lpfc_sli_flush_mbox_queue(phba);
+ }
+ void
+-lpfc_offline(struct lpfc_hba *phba)
++lpfc_offline(struct lpfc_hba * phba)
+ {
+-      struct lpfc_vport *vport = phba->pport;
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_vport *port_iterator;
++      unsigned long iflag;
+-      if (vport->fc_flag & FC_OFFLINE_MODE)
++      if (phba->fc_flag & FC_OFFLINE_MODE)
+               return;
+       /* stop all timers associated with this hba */
+-      lpfc_stop_phba_timers(phba);
+-      list_for_each_entry(port_iterator, &phba->port_list, listentry) {
+-              port_iterator->work_port_events = 0;
+-      }
++      lpfc_stop_timer(phba);
+-      lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
++      lpfc_printf_log(phba,
++                     KERN_WARNING,
++                     LOG_INIT,
+                      "%d:0460 Bring Adapter offline\n",
+                      phba->brd_no);
+       /* Bring down the SLI Layer and cleanup.  The HBA is offline
+          now.  */
+       lpfc_sli_hba_down(phba);
+-      spin_lock_irq(&phba->hbalock);
++      lpfc_cleanup(phba);
++      spin_lock_irqsave(phba->host->host_lock, iflag);
++      phba->work_hba_events = 0;
+       phba->work_ha = 0;
+-      vport->fc_flag |= FC_OFFLINE_MODE;
+-      spin_unlock_irq(&phba->hbalock);
+-      list_for_each_entry(port_iterator, &phba->port_list, listentry) {
+-              shost = lpfc_shost_from_vport(port_iterator);
+-
+-              lpfc_cleanup(port_iterator);
+-              spin_lock_irq(shost->host_lock);
+-              vport->work_port_events = 0;
+-              vport->fc_flag |= FC_OFFLINE_MODE;
+-              spin_unlock_irq(shost->host_lock);
+-      }
++      phba->fc_flag |= FC_OFFLINE_MODE;
++      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+ }
+ /******************************************************************************
+@@ -1482,12 +1326,12 @@
+ *
+ ******************************************************************************/
+ static int
+-lpfc_scsi_free(struct lpfc_hba *phba)
++lpfc_scsi_free(struct lpfc_hba * phba)
+ {
+       struct lpfc_scsi_buf *sb, *sb_next;
+       struct lpfc_iocbq *io, *io_next;
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       /* Release all the lpfc_scsi_bufs maintained by this host. */
+       list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) {
+               list_del(&sb->list);
+@@ -1504,174 +1348,126 @@
+               phba->total_iocbq_bufs--;
+       }
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       return 0;
+ }
+-
+-struct lpfc_vport *
+-lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport)
++void lpfc_remove_device(struct lpfc_hba *phba)
+ {
+-      struct lpfc_vport *vport;
+-      struct Scsi_Host  *shost;
+-      int error = 0;
++      unsigned long iflag;
+-      shost = scsi_host_alloc(&lpfc_template, sizeof(struct lpfc_vport));
+-      if (!shost)
+-              goto out;
++      lpfc_free_sysfs_attr(phba);
++
++      spin_lock_irqsave(phba->host->host_lock, iflag);
++      phba->fc_flag |= FC_UNLOADING;
+-      vport = (struct lpfc_vport *) shost->hostdata;
+-      vport->phba = phba;
++      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+-      vport->load_flag |= FC_LOADING;
+-      vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
++      fc_remove_host(phba->host);
++      scsi_remove_host(phba->host);
 +
++      kthread_stop(phba->worker_thread);
+-      shost->unique_id = instance;
+-      shost->max_id = LPFC_MAX_TARGET;
+-      shost->max_lun = phba->cfg_max_luns;
+-      shost->this_id = -1;
+-      shost->max_cmd_len = 16;
+       /*
+-       * Set initial can_queue value since 0 is no longer supported and
+-       * scsi_add_host will fail. This will be adjusted later based on the
+-       * max xri value determined in hba setup.
++       * Bring down the SLI Layer. This step disable all interrupts,
++       * clears the rings, discards all mailbox commands, and resets
++       * the HBA.
+        */
+-      shost->can_queue = phba->cfg_hba_queue_depth - 10;
+-      if (fc_vport != NULL) {
+-              shost->transportt = lpfc_vport_transport_template;
+-              vport->port_type = LPFC_NPIV_PORT;
+-      } else {
+-              shost->transportt = lpfc_transport_template;
+-              vport->port_type = LPFC_PHYSICAL_PORT;
+-      }
++      lpfc_sli_hba_down(phba);
++      lpfc_sli_brdrestart(phba);
+-      /* Initialize all internally managed lists. */
+-      INIT_LIST_HEAD(&vport->fc_nodes);
+-      spin_lock_init(&vport->work_port_lock);
++      /* Release the irq reservation */
++      free_irq(phba->pcidev->irq, phba);
++      pci_disable_msi(phba->pcidev);
+-      init_timer(&vport->fc_disctmo);
+-      vport->fc_disctmo.function = lpfc_disc_timeout;
+-      vport->fc_disctmo.data = (unsigned long)vport;
++      lpfc_cleanup(phba);
++      lpfc_stop_timer(phba);
++      phba->work_hba_events = 0;
+-      init_timer(&vport->fc_fdmitmo);
+-      vport->fc_fdmitmo.function = lpfc_fdmi_tmo;
+-      vport->fc_fdmitmo.data = (unsigned long)vport;
 +      /*
-+       * We should already have a lock on this dentry in the case of a
-+       * partial lookup, or a revalidation. Otherwise it is returned from
-+       * new_dentry_private_data already locked.
++       * Call scsi_free before mem_free since scsi bufs are released to their
++       * corresponding pools here.
 +       */
-+      if (lookupmode == INTERPOSE_PARTIAL || lookupmode == INTERPOSE_REVAL ||
-+          lookupmode == INTERPOSE_REVAL_NEG)
-+              verify_locked(dentry);
-+      else {
-+              BUG_ON(UNIONFS_D(dentry) != NULL);
-+              locked_child = 1;
-+      }
-+
-+      switch(lookupmode) {
-+              case INTERPOSE_PARTIAL:
-+                      break;
-+              case INTERPOSE_LOOKUP:
-+                      if ((err = new_dentry_private_data(dentry)))
-+                              goto out;
-+                      allocated_new_info = 1;
-+                      break;
-+              default:
-+                      if ((err = realloc_dentry_private_data(dentry)))
-+                              goto out;
-+                      allocated_new_info = 1;
-+                      break;
-+      }
-+
-+      /* must initialize dentry operations */
-+      dentry->d_op = &unionfs_dops;
-+
-+      parent_dentry = dget_parent(dentry);
-+      /* We never partial lookup the root directory. */
-+      if (parent_dentry != dentry) {
-+              unionfs_lock_dentry(parent_dentry);
-+              locked_parent = 1;
-+      } else {
-+              dput(parent_dentry);
-+              parent_dentry = NULL;
-+              goto out;
-+      }
-+
-+      name = dentry->d_name.name;
-+      namelen = dentry->d_name.len;
-+
-+      /* No dentries should get created for possible whiteout names. */
-+      if (!is_validname(name)) {
-+              err = -EPERM;
-+              goto out_free;
-+      }
-+
-+      /* Now start the actual lookup procedure. */
-+      bstart = dbstart(parent_dentry);
-+      bend = dbend(parent_dentry);
-+      bopaque = dbopaque(parent_dentry);
-+      BUG_ON(bstart < 0);
-+
++      lpfc_scsi_free(phba);
++      lpfc_mem_free(phba);
+-      init_timer(&vport->els_tmofunc);
+-      vport->els_tmofunc.function = lpfc_els_timeout;
+-      vport->els_tmofunc.data = (unsigned long)vport;
++      /* Free resources associated with SLI2 interface */
++      dma_free_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE,
++                        phba->slim2p, phba->slim2p_mapping);
+-      if (fc_vport != NULL) {
+-              error = scsi_add_host(shost, &fc_vport->dev);
+-      } else {
+-              error = scsi_add_host(shost, &phba->pcidev->dev);
+-      }
+-      if (error)
+-              goto out_put_shost;
++      /* unmap adapter SLIM and Control Registers */
++      iounmap(phba->ctrl_regs_memmap_p);
++      iounmap(phba->slim_memmap_p);
+-      list_add_tail(&vport->listentry, &phba->port_list);
+-      return vport;
++      pci_release_regions(phba->pcidev);
++      pci_disable_device(phba->pcidev);
+-out_put_shost:
+-      scsi_host_put(shost);
+-out:
+-      return NULL;
++      idr_remove(&lpfc_hba_index, phba->brd_no);
++      scsi_host_put(phba->host);
+ }
+-void
+-destroy_port(struct lpfc_vport *vport)
++void lpfc_scan_start(struct Scsi_Host *host)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+-      kfree(vport->vname);
++      if (lpfc_alloc_sysfs_attr(phba))
++              goto error;
+-      lpfc_debugfs_terminate(vport);
+-      fc_remove_host(shost);
+-      scsi_remove_host(shost);
++      phba->MBslimaddr = phba->slim_memmap_p;
++      phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
++      phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
++      phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
++      phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
+-      spin_lock_irq(&phba->hbalock);
+-      list_del_init(&vport->listentry);
+-      spin_unlock_irq(&phba->hbalock);
++      if (lpfc_sli_hba_setup(phba))
++              goto error;
+-      lpfc_cleanup(vport);
 +      /*
-+       * It would be ideal if we could convert partial lookups to only have
-+       * to do this work when they really need to.  It could probably improve
-+       * performance quite a bit, and maybe simplify the rest of the code.
++       * hba setup may have changed the hba_queue_depth so we need to adjust
++       * the value of can_queue.
 +       */
-+      if (lookupmode == INTERPOSE_PARTIAL) {
-+              bstart++;
-+              if ((bopaque != -1) && (bopaque < bend))
-+                      bend = bopaque;
-+      }
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (lookupmode == INTERPOSE_PARTIAL && hidden_dentry)
-+                      continue;
-+              BUG_ON(hidden_dentry != NULL);
-+
-+              hidden_dir_dentry =
-+                      unionfs_lower_dentry_idx(parent_dentry, bindex);
-+
-+              /* if the parent hidden dentry does not exist skip this */
-+              if (!(hidden_dir_dentry && hidden_dir_dentry->d_inode))
-+                      continue;
-+
-+              /* also skip it if the parent isn't a directory. */
-+              if (!S_ISDIR(hidden_dir_dentry->d_inode->i_mode))
-+                      continue;
-+
-+              /* Reuse the whiteout name because its value doesn't change. */
-+              if (!whname) {
-+                      whname = alloc_whname(name, namelen);
-+                      if (IS_ERR(whname)) {
-+                              err = PTR_ERR(whname);
-+                              goto out_free;
-+                      }
-+              }
-+
-+              /* check if whiteout exists in this branch: lookup .wh.foo */
-+              wh_hidden_dentry = lookup_one_len(whname, hidden_dir_dentry,
-+                                                namelen + UNIONFS_WHLEN);
-+              if (IS_ERR(wh_hidden_dentry)) {
-+                      dput(first_hidden_dentry);
-+                      unionfs_mntput(first_dentry, first_dentry_offset);
-+                      err = PTR_ERR(wh_hidden_dentry);
-+                      goto out_free;
-+              }
-+
-+              if (wh_hidden_dentry->d_inode) {
-+                      /* We found a whiteout so lets give up. */
-+                      if (S_ISREG(wh_hidden_dentry->d_inode->i_mode)) {
-+                              set_dbend(dentry, bindex);
-+                              set_dbopaque(dentry, bindex);
-+                              dput(wh_hidden_dentry);
-+                              break;
-+                      }
-+                      err = -EIO;
-+                      printk(KERN_NOTICE "unionfs: EIO: invalid whiteout "
-+                             "entry type %d.\n",
-+                             wh_hidden_dentry->d_inode->i_mode);
-+                      dput(wh_hidden_dentry);
-+                      dput(first_hidden_dentry);
-+                      unionfs_mntput(first_dentry, first_dentry_offset);
-+                      goto out_free;
-+              }
-+
-+              dput(wh_hidden_dentry);
-+              wh_hidden_dentry = NULL;
-+
-+              /* Now do regular lookup; lookup foo */
-+              nd->dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              /* FIXME: fix following line for mount point crossing */
-+              nd->mnt = unionfs_lower_mnt_idx(parent_dentry, bindex);
-+
-+              hidden_dentry = lookup_one_len_nd(name, hidden_dir_dentry,
-+                                                namelen, nd);
-+              if (IS_ERR(hidden_dentry)) {
-+                      dput(first_hidden_dentry);
-+                      unionfs_mntput(first_dentry, first_dentry_offset);
-+                      err = PTR_ERR(hidden_dentry);
-+                      goto out_free;
-+              }
-+
-+              /*
-+               * Store the first negative dentry specially, because if they
-+               * are all negative we need this for future creates.
-+               */
-+              if (!hidden_dentry->d_inode) {
-+                      if (!first_hidden_dentry && (dbstart(dentry) == -1)) {
-+                              first_hidden_dentry = hidden_dentry;
-+                              /*
-+                               * FIXME: following line needs to be changed
-+                               * to allow mount-point crossing
-+                               */
-+                              first_dentry = parent_dentry;
-+                              first_hidden_mnt =
-+                                      unionfs_mntget(parent_dentry, bindex);
-+                              first_dentry_offset = bindex;
-+                      } else
-+                              dput(hidden_dentry);
-+
-+                      continue;
-+              }
-+
-+              /* number of positive dentries */
-+              dentry_count++;
-+
-+              /* store underlying dentry */
-+              if (dbstart(dentry) == -1)
-+                      set_dbstart(dentry, bindex);
-+              unionfs_set_lower_dentry_idx(dentry, bindex, hidden_dentry);
-+              /*
-+               * FIXME: the following line needs to get fixed to allow
-+               * mount-point crossing
-+               */
-+              unionfs_set_lower_mnt_idx(dentry, bindex,
-+                                        unionfs_mntget(parent_dentry,
-+                                                       bindex));
-+              set_dbend(dentry, bindex);
-+
-+              /* update parent directory's atime with the bindex */
-+              fsstack_copy_attr_atime(parent_dentry->d_inode,
-+                                      hidden_dir_dentry->d_inode);
-+
-+              /* We terminate file lookups here. */
-+              if (!S_ISDIR(hidden_dentry->d_inode->i_mode)) {
-+                      if (lookupmode == INTERPOSE_PARTIAL)
-+                              continue;
-+                      if (dentry_count == 1)
-+                              goto out_positive;
-+                      /* This can only happen with mixed D-*-F-* */
-+                      BUG_ON(!S_ISDIR(unionfs_lower_dentry(dentry)->
-+                                      d_inode->i_mode));
-+                      continue;
-+              }
-+
-+              opaque = is_opaque_dir(dentry, bindex);
-+              if (opaque < 0) {
-+                      dput(first_hidden_dentry);
-+                      unionfs_mntput(first_dentry, first_dentry_offset);
-+                      err = opaque;
-+                      goto out_free;
-+              } else if (opaque) {
-+                      set_dbend(dentry, bindex);
-+                      set_dbopaque(dentry, bindex);
-+                      break;
-+              }
++      host->can_queue = phba->cfg_hba_queue_depth - 10;
+       return;
+-}
+-int
+-lpfc_get_instance(void)
+-{
+-      int instance = 0;
+-
+-      /* Assign an unused number */
+-      if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))
+-              return -1;
+-      if (idr_get_new(&lpfc_hba_index, NULL, &instance))
+-              return -1;
+-      return instance;
++error:
++      lpfc_remove_device(phba);
+ }
+-/*
+- * Note: there is no scan_start function as adapter initialization
+- * will have asynchronously kicked off the link initialization.
+- */
+-
+ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
+ {
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-      int stat = 0;
++      struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+-      spin_lock_irq(shost->host_lock);
+-
+-      if (vport->fc_flag & FC_UNLOADING) {
+-              stat = 1;
+-              goto finished;
+-      }
+-      if (time >= 30 * HZ) {
+-              lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+-                              "%d:0461 Scanning longer than 30 "
+-                              "seconds.  Continuing initialization\n",
+-                              phba->brd_no);
+-              stat = 1;
+-              goto finished;
+-      }
+-      if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) {
+-              lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+-                              "%d:0465 Link down longer than 15 "
+-                              "seconds.  Continuing initialization\n",
+-                              phba->brd_no);
+-              stat = 1;
+-              goto finished;
+-      }
+-
+-      if (vport->port_state != LPFC_VPORT_READY)
+-              goto finished;
+-      if (vport->num_disc_nodes || vport->fc_prli_sent)
+-              goto finished;
+-      if (vport->fc_map_cnt == 0 && time < 2 * HZ)
+-              goto finished;
+-      if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0)
++      if (!phba->host)
++              return 1;
++      if (time >= 30 * HZ)
+               goto finished;
+-      stat = 1;
++      if (phba->hba_state != LPFC_HBA_READY)
++              return 0;
++      if (phba->num_disc_nodes || phba->fc_prli_sent)
++              return 0;
++      if ((phba->fc_map_cnt == 0) && (time < 2 * HZ))
++              return 0;
++      if (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)
++              return 0;
++      if ((phba->hba_state > LPFC_LINK_DOWN) || (time < 15 * HZ))
++              return 0;
+ finished:
++      if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
++              spin_lock_irq(shost->host_lock);
++              lpfc_poll_start_timer(phba);
+               spin_unlock_irq(shost->host_lock);
+-      return stat;
+-}
 +      }
+-void lpfc_host_attrib_init(struct Scsi_Host *shost)
+-{
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+       /*
+-       * Set fixed host attributes.  Must done after lpfc_sli_hba_setup().
++       * set fixed host attributes
++       * Must done after lpfc_sli_hba_setup()
+        */
+-      fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn);
+-      fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn);
++      fc_host_node_name(shost) = wwn_to_u64(phba->fc_nodename.u.wwn);
++      fc_host_port_name(shost) = wwn_to_u64(phba->fc_portname.u.wwn);
+       fc_host_supported_classes(shost) = FC_COS_CLASS3;
+       memset(fc_host_supported_fc4s(shost), 0,
+@@ -1679,8 +1475,7 @@
+       fc_host_supported_fc4s(shost)[2] = 1;
+       fc_host_supported_fc4s(shost)[7] = 1;
+-      lpfc_vport_symbolic_node_name(vport, fc_host_symbolic_name(shost),
+-                               sizeof fc_host_symbolic_name(shost));
++      lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost));
+       fc_host_supported_speeds(shost) = 0;
+       if (phba->lmt & LMT_10Gb)
+@@ -1693,8 +1488,8 @@
+               fc_host_supported_speeds(shost) |= FC_PORTSPEED_1GBIT;
+       fc_host_maxframe_size(shost) =
+-              (((uint32_t) vport->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
+-              (uint32_t) vport->fc_sparam.cmn.bbRcvSizeLsb;
++              ((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
++               (uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb);
+       /* This value is also unchanging */
+       memset(fc_host_active_fc4s(shost), 0,
+@@ -1702,20 +1497,20 @@
+       fc_host_active_fc4s(shost)[2] = 1;
+       fc_host_active_fc4s(shost)[7] = 1;
+-      fc_host_max_npiv_vports(shost) = phba->max_vpi;
+       spin_lock_irq(shost->host_lock);
+-      vport->fc_flag &= ~FC_LOADING;
++      phba->fc_flag &= ~FC_LOADING;
+       spin_unlock_irq(shost->host_lock);
 +
-+      if (dentry_count)
-+              goto out_positive;
-+      else
-+              goto out_negative;
-+
-+out_negative:
-+      if (lookupmode == INTERPOSE_PARTIAL)
-+              goto out;
-+
-+      /* If we've only got negative dentries, then use the leftmost one. */
-+      if (lookupmode == INTERPOSE_REVAL) {
-+              if (dentry->d_inode)
-+                      UNIONFS_I(dentry->d_inode)->stale = 1;
++      return 1;
+ }
+ static int __devinit
+ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
+ {
+-      struct lpfc_vport *vport = NULL;
++      struct Scsi_Host *host;
+       struct lpfc_hba  *phba;
+       struct lpfc_sli  *psli;
+       struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL;
+-      struct Scsi_Host  *shost = NULL;
+       unsigned long bar0map_len, bar2map_len;
+       int error = -ENODEV, retval;
+       int i;
+@@ -1726,46 +1521,61 @@
+       if (pci_request_regions(pdev, LPFC_DRIVER_NAME))
+               goto out_disable_device;
+-      phba = kzalloc(sizeof (struct lpfc_hba), GFP_KERNEL);
+-      if (!phba)
++      host = scsi_host_alloc(&lpfc_template, sizeof (struct lpfc_hba));
++      if (!host)
+               goto out_release_regions;
+-      spin_lock_init(&phba->hbalock);
++      phba = (struct lpfc_hba*)host->hostdata;
++      memset(phba, 0, sizeof (struct lpfc_hba));
++      phba->host = host;
++      phba->fc_flag |= FC_LOADING;
+       phba->pcidev = pdev;
+       /* Assign an unused board number */
+-      if ((phba->brd_no = lpfc_get_instance()) < 0)
+-              goto out_free_phba;
++      if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))
++              goto out_put_host;
+-      INIT_LIST_HEAD(&phba->port_list);
+-      INIT_LIST_HEAD(&phba->hbq_buffer_list);
+-      /*
+-       * Get all the module params for configuring this host and then
+-       * establish the host.
+-       */
+-      lpfc_get_cfgparam(phba);
+-      phba->max_vpi = LPFC_MAX_VPI;
++      error = idr_get_new(&lpfc_hba_index, NULL, &phba->brd_no);
++      if (error)
++              goto out_put_host;
 +
-+              goto out;
-+      }
-+      /* This should only happen if we found a whiteout. */
-+      if (first_dentry_offset == -1) {
-+              nd->dentry = dentry;
-+              /* FIXME: fix following line for mount point crossing */
-+              nd->mnt = unionfs_lower_mnt_idx(parent_dentry, bindex);
-+
-+              first_hidden_dentry =
-+                      lookup_one_len_nd(name, hidden_dir_dentry,
-+                                        namelen, nd);
-+              first_dentry_offset = bindex;
-+              if (IS_ERR(first_hidden_dentry)) {
-+                      err = PTR_ERR(first_hidden_dentry);
-+                      goto out;
-+              }
++      host->unique_id = phba->brd_no;
+       /* Initialize timers used by driver */
+       init_timer(&phba->fc_estabtmo);
+       phba->fc_estabtmo.function = lpfc_establish_link_tmo;
+       phba->fc_estabtmo.data = (unsigned long)phba;
+-
+-      init_timer(&phba->hb_tmofunc);
+-      phba->hb_tmofunc.function = lpfc_hb_timeout;
+-      phba->hb_tmofunc.data = (unsigned long)phba;
+-
++      init_timer(&phba->fc_disctmo);
++      phba->fc_disctmo.function = lpfc_disc_timeout;
++      phba->fc_disctmo.data = (unsigned long)phba;
 +
-+              /*
-+               * FIXME: the following line needs to be changed to allow
-+               * mount-point crossing
-+               */
-+              first_dentry = dentry;
-+              first_hidden_mnt = unionfs_mntget(dentry, bindex);
-+      }
-+      unionfs_set_lower_dentry_idx(dentry, first_dentry_offset,
-+                                   first_hidden_dentry);
-+      unionfs_set_lower_mnt_idx(dentry, first_dentry_offset,
-+                                first_hidden_mnt);
-+      set_dbstart(dentry, first_dentry_offset);
-+      set_dbend(dentry, first_dentry_offset);
-+
-+      if (lookupmode == INTERPOSE_REVAL_NEG)
-+              BUG_ON(dentry->d_inode != NULL);
-+      else
-+              d_add(dentry, NULL);
-+      goto out;
++      init_timer(&phba->fc_fdmitmo);
++      phba->fc_fdmitmo.function = lpfc_fdmi_tmo;
++      phba->fc_fdmitmo.data = (unsigned long)phba;
++      init_timer(&phba->els_tmofunc);
++      phba->els_tmofunc.function = lpfc_els_timeout;
++      phba->els_tmofunc.data = (unsigned long)phba;
+       psli = &phba->sli;
+       init_timer(&psli->mbox_tmo);
+       psli->mbox_tmo.function = lpfc_mbox_timeout;
+-      psli->mbox_tmo.data = (unsigned long) phba;
++      psli->mbox_tmo.data = (unsigned long)phba;
 +
-+/* This part of the code is for positive dentries. */
-+out_positive:
-+      BUG_ON(dentry_count <= 0);
+       init_timer(&phba->fcp_poll_timer);
+       phba->fcp_poll_timer.function = lpfc_poll_timeout;
+-      phba->fcp_poll_timer.data = (unsigned long) phba;
+-      init_timer(&phba->fabric_block_timer);
+-      phba->fabric_block_timer.function = lpfc_fabric_block_timeout;
+-      phba->fabric_block_timer.data = (unsigned long) phba;
++      phba->fcp_poll_timer.data = (unsigned long)phba;
 +
 +      /*
-+       * If we're holding onto the first negative dentry & corresponding
-+       * vfsmount - throw it out.
++       * Get all the module params for configuring this host and then
++       * establish the host parameters.
 +       */
-+      dput(first_hidden_dentry);
-+      unionfs_mntput(first_dentry, first_dentry_offset);
++      lpfc_get_cfgparam(phba);
 +
-+      /* Partial lookups need to re-interpose, or throw away older negs. */
-+      if (lookupmode == INTERPOSE_PARTIAL) {
-+              if (dentry->d_inode) {
-+                      unionfs_reinterpose(dentry);
-+                      goto out;
-+              }
++      host->max_id = LPFC_MAX_TARGET;
++      host->max_lun = phba->cfg_max_luns;
++      host->this_id = -1;
 +
-+              /*
-+               * This somehow turned positive, so it is as if we had a
-+               * negative revalidation.
-+               */
-+              lookupmode = INTERPOSE_REVAL_NEG;
++      INIT_LIST_HEAD(&phba->fc_nodes);
+       pci_set_master(pdev);
+       retval = pci_set_mwi(pdev);
+@@ -1813,22 +1623,13 @@
+       memset(phba->slim2p, 0, SLI2_SLIM_SIZE);
+-      phba->hbqslimp.virt = dma_alloc_coherent(&phba->pcidev->dev,
+-                                               lpfc_sli_hbq_size(),
+-                                               &phba->hbqslimp.phys,
+-                                               GFP_KERNEL);
+-      if (!phba->hbqslimp.virt)
+-              goto out_free_slim;
+-
+-      memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size());
+-
+       /* Initialize the SLI Layer to run with lpfc HBAs. */
+       lpfc_sli_setup(phba);
+       lpfc_sli_queue_setup(phba);
+       error = lpfc_mem_alloc(phba);
+       if (error)
+-              goto out_free_hbqslimp;
++              goto out_free_slim;
+       /* Initialize and populate the iocb list per host.  */
+       INIT_LIST_HEAD(&phba->lpfc_iocb_list);
+@@ -1852,11 +1653,10 @@
+                       error = -ENOMEM;
+                       goto out_free_iocbq;
+               }
+-
+-              spin_lock_irq(&phba->hbalock);
++              spin_lock_irq(phba->host->host_lock);
+               list_add(&iocbq_entry->list, &phba->lpfc_iocb_list);
+               phba->total_iocbq_bufs++;
+-              spin_unlock_irq(&phba->hbalock);
++              spin_unlock_irq(phba->host->host_lock);
+       }
+       /* Initialize HBA structure */
+@@ -1877,22 +1677,22 @@
+               goto out_free_iocbq;
+       }
++      /*
++       * Set initial can_queue value since 0 is no longer supported and
++       * scsi_add_host will fail. This will be adjusted later based on the
++       * max xri value determined in hba setup.
++       */
++      host->can_queue = phba->cfg_hba_queue_depth - 10;
 +
-+              update_bstart(dentry);
-+              bstart = dbstart(dentry);
-+              bend = dbend(dentry);
-+      }
++      /* Tell the midlayer we support 16 byte commands */
++      host->max_cmd_len = 16;
 +
-+      err = unionfs_interpose(dentry, dentry->d_sb, lookupmode);
-+      if (err)
-+              goto out_drop;
+       /* Initialize the list of scsi buffers used by driver for scsi IO. */
+       spin_lock_init(&phba->scsi_buf_list_lock);
+       INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list);
+-      /* Initialize list of fabric iocbs */
+-      INIT_LIST_HEAD(&phba->fabric_iocb_list);
+-
+-      vport = lpfc_create_port(phba, phba->brd_no, NULL);
+-      if (!vport)
+-              goto out_kthread_stop;
+-
+-      shost = lpfc_shost_from_vport(vport);
+-      phba->pport = vport;
+-      lpfc_debugfs_initialize(vport);
+-
+-      pci_set_drvdata(pdev, shost);
++      host->transportt = lpfc_transport_template;
++      pci_set_drvdata(pdev, host);
+       if (phba->cfg_use_msi) {
+               error = pci_enable_msi(phba->pcidev);
+@@ -1908,63 +1708,33 @@
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "%d:0451 Enable interrupt handler failed\n",
+                       phba->brd_no);
+-              goto out_disable_msi;
++              goto out_kthread_stop;
+       }
+-      phba->MBslimaddr = phba->slim_memmap_p;
+-      phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
+-      phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
+-      phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
+-      phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
+-
+-      if (lpfc_alloc_sysfs_attr(vport))
++      error = scsi_add_host(host, &pdev->dev);
++      if (error)
+               goto out_free_irq;
+-      if (lpfc_sli_hba_setup(phba))
+-              goto out_remove_device;
+-
+-      /*
+-       * hba setup may have changed the hba_queue_depth so we need to adjust
+-       * the value of can_queue.
+-       */
+-      shost->can_queue = phba->cfg_hba_queue_depth - 10;
+-
+-      lpfc_host_attrib_init(shost);
+-
+-      if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
+-              spin_lock_irq(shost->host_lock);
+-              lpfc_poll_start_timer(phba);
+-              spin_unlock_irq(shost->host_lock);
+-      }
+-
+-      scsi_scan_host(shost);
++      scsi_scan_host(host);
+       return 0;
+-out_remove_device:
+-      lpfc_free_sysfs_attr(vport);
+-      spin_lock_irq(shost->host_lock);
+-      vport->fc_flag |= FC_UNLOADING;
+-      spin_unlock_irq(shost->host_lock);
+ out_free_irq:
+-      lpfc_stop_phba_timers(phba);
+-      phba->pport->work_port_events = 0;
++      lpfc_stop_timer(phba);
++      phba->work_hba_events = 0;
+       free_irq(phba->pcidev->irq, phba);
+-out_disable_msi:
+       pci_disable_msi(phba->pcidev);
+-      destroy_port(vport);
+ out_kthread_stop:
+       kthread_stop(phba->worker_thread);
+ out_free_iocbq:
+       list_for_each_entry_safe(iocbq_entry, iocbq_next,
+                                               &phba->lpfc_iocb_list, list) {
++              spin_lock_irq(phba->host->host_lock);
+               kfree(iocbq_entry);
+               phba->total_iocbq_bufs--;
++              spin_unlock_irq(phba->host->host_lock);
+       }
+       lpfc_mem_free(phba);
+-out_free_hbqslimp:
+-      dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(), phba->hbqslimp.virt,
+-                        phba->hbqslimp.phys);
+ out_free_slim:
+       dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE, phba->slim2p,
+                                                       phba->slim2p_mapping);
+@@ -1974,85 +1744,27 @@
+       iounmap(phba->slim_memmap_p);
+ out_idr_remove:
+       idr_remove(&lpfc_hba_index, phba->brd_no);
+-out_free_phba:
+-      kfree(phba);
++out_put_host:
++      phba->host = NULL;
++      scsi_host_put(host);
+ out_release_regions:
+       pci_release_regions(pdev);
+ out_disable_device:
+       pci_disable_device(pdev);
+ out:
+       pci_set_drvdata(pdev, NULL);
+-      if (shost)
+-              scsi_host_put(shost);
+       return error;
+ }
+ static void __devexit
+ lpfc_pci_remove_one(struct pci_dev *pdev)
+ {
+-      struct Scsi_Host  *shost = pci_get_drvdata(pdev);
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
+-      struct lpfc_vport *port_iterator;
+-      list_for_each_entry(port_iterator, &phba->port_list, listentry)
+-              port_iterator->load_flag |= FC_UNLOADING;
+-
+-      kfree(vport->vname);
+-      lpfc_free_sysfs_attr(vport);
+-
+-      fc_remove_host(shost);
+-      scsi_remove_host(shost);
+-
+-      /*
+-       * Bring down the SLI Layer. This step disable all interrupts,
+-       * clears the rings, discards all mailbox commands, and resets
+-       * the HBA.
+-       */
+-      lpfc_sli_hba_down(phba);
+-      lpfc_sli_brdrestart(phba);
+-
+-      lpfc_stop_phba_timers(phba);
+-      spin_lock_irq(&phba->hbalock);
+-      list_del_init(&vport->listentry);
+-      spin_unlock_irq(&phba->hbalock);
+-
+-
+-      lpfc_debugfs_terminate(vport);
+-      lpfc_cleanup(vport);
+-
+-      kthread_stop(phba->worker_thread);
++      struct Scsi_Host   *host = pci_get_drvdata(pdev);
++      struct lpfc_hba    *phba = (struct lpfc_hba *)host->hostdata;
+-      /* Release the irq reservation */
+-      free_irq(phba->pcidev->irq, phba);
+-      pci_disable_msi(phba->pcidev);
++      lpfc_remove_device(phba);
+       pci_set_drvdata(pdev, NULL);
+-      scsi_host_put(shost);
+-
+-      /*
+-       * Call scsi_free before mem_free since scsi bufs are released to their
+-       * corresponding pools here.
+-       */
+-      lpfc_scsi_free(phba);
+-      lpfc_mem_free(phba);
+-
+-      dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(), phba->hbqslimp.virt,
+-                        phba->hbqslimp.phys);
+-
+-      /* Free resources associated with SLI2 interface */
+-      dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE,
+-                        phba->slim2p, phba->slim2p_mapping);
+-
+-      /* unmap adapter SLIM and Control Registers */
+-      iounmap(phba->ctrl_regs_memmap_p);
+-      iounmap(phba->slim_memmap_p);
+-
+-      idr_remove(&lpfc_hba_index, phba->brd_no);
+-
+-      kfree(phba);
+-
+-      pci_release_regions(pdev);
+-      pci_disable_device(pdev);
+ }
+ /**
+@@ -2110,13 +1822,10 @@
+       pci_set_master(pdev);
+       /* Re-establishing Link */
+-      spin_lock_irq(host->host_lock);
+-      phba->pport->fc_flag |= FC_ESTABLISH_LINK;
+-      spin_unlock_irq(host->host_lock);
+-
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
++      phba->fc_flag |= FC_ESTABLISH_LINK;
+       psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       /* Take device offline; this will perform cleanup */
+@@ -2239,15 +1948,11 @@
+       lpfc_transport_template =
+                               fc_attach_transport(&lpfc_transport_functions);
+-      lpfc_vport_transport_template =
+-                      fc_attach_transport(&lpfc_vport_transport_functions);
+-      if (!lpfc_transport_template || !lpfc_vport_transport_template)
++      if (!lpfc_transport_template)
+               return -ENOMEM;
+       error = pci_register_driver(&lpfc_driver);
+-      if (error) {
++      if (error)
+               fc_release_transport(lpfc_transport_template);
+-              fc_release_transport(lpfc_vport_transport_template);
+-      }
+       return error;
+ }
+@@ -2257,7 +1962,6 @@
+ {
+       pci_unregister_driver(&lpfc_driver);
+       fc_release_transport(lpfc_transport_template);
+-      fc_release_transport(lpfc_vport_transport_template);
+ }
+ module_init(lpfc_init);
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_logmsg.h linux-2.6.22-570/drivers/scsi/lpfc/lpfc_logmsg.h
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_logmsg.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_logmsg.h   2007-07-08 19:32:17.000000000 -0400
+@@ -30,7 +30,6 @@
+ #define LOG_SLI                       0x800   /* SLI events */
+ #define LOG_FCP_ERROR                 0x1000  /* log errors, not underruns */
+ #define LOG_LIBDFC                    0x2000  /* Libdfc events */
+-#define LOG_VPORT                     0x4000  /* NPIV events */
+ #define LOG_ALL_MSG                   0xffff  /* LOG all messages */
+ #define lpfc_printf_log(phba, level, mask, fmt, arg...) \
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_mbox.c linux-2.6.22-570/drivers/scsi/lpfc/lpfc_mbox.c
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_mbox.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_mbox.c     2007-07-08 19:32:17.000000000 -0400
+@@ -82,22 +82,6 @@
+ }
+ /**********************************************/
+-/*  lpfc_heart_beat  Issue a HEART_BEAT       */
+-/*                mailbox command             */
+-/**********************************************/
+-void
+-lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+-{
+-      MAILBOX_t *mb;
+-
+-      mb = &pmb->mb;
+-      memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+-      mb->mbxCommand = MBX_HEARTBEAT;
+-      mb->mbxOwner = OWN_HOST;
+-      return;
+-}
+-
+-/**********************************************/
+ /*  lpfc_read_la  Issue a READ LA             */
+ /*                mailbox command             */
+ /**********************************************/
+@@ -150,7 +134,6 @@
+ void
+ lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+ {
+-      struct lpfc_vport  *vport = phba->pport;
+       MAILBOX_t *mb = &pmb->mb;
+       memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+@@ -164,7 +147,7 @@
+               mb->un.varCfgLnk.cr_count = phba->cfg_cr_count;
+       }
+-      mb->un.varCfgLnk.myId = vport->fc_myDID;
++      mb->un.varCfgLnk.myId = phba->fc_myDID;
+       mb->un.varCfgLnk.edtov = phba->fc_edtov;
+       mb->un.varCfgLnk.arbtov = phba->fc_arbtov;
+       mb->un.varCfgLnk.ratov = phba->fc_ratov;
+@@ -256,7 +239,7 @@
+ /*                    mailbox command         */
+ /**********************************************/
+ int
+-lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi)
++lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+ {
+       struct lpfc_dmabuf *mp;
+       MAILBOX_t *mb;
+@@ -287,7 +270,6 @@
+       mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
+       mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys);
+       mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys);
+-      mb->un.varRdSparm.vpi = vpi;
+       /* save address for completion */
+       pmb->context1 = mp;
+@@ -300,8 +282,7 @@
+ /*                  mailbox command         */
+ /********************************************/
+ void
+-lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did,
+-             LPFC_MBOXQ_t * pmb)
++lpfc_unreg_did(struct lpfc_hba * phba, uint32_t did, LPFC_MBOXQ_t * pmb)
+ {
+       MAILBOX_t *mb;
+@@ -309,7 +290,6 @@
+       memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+       mb->un.varUnregDID.did = did;
+-      mb->un.varUnregDID.vpi = vpi;
+       mb->mbxCommand = MBX_UNREG_D_ID;
+       mb->mbxOwner = OWN_HOST;
+@@ -355,17 +335,19 @@
+ /*                  mailbox command         */
+ /********************************************/
+ int
+-lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
+-             uint8_t *param, LPFC_MBOXQ_t *pmb, uint32_t flag)
++lpfc_reg_login(struct lpfc_hba * phba,
++             uint32_t did, uint8_t * param, LPFC_MBOXQ_t * pmb, uint32_t flag)
+ {
+-      MAILBOX_t *mb = &pmb->mb;
+       uint8_t *sparam;
+       struct lpfc_dmabuf *mp;
++      MAILBOX_t *mb;
++      struct lpfc_sli *psli;
++      psli = &phba->sli;
++      mb = &pmb->mb;
+       memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+       mb->un.varRegLogin.rpi = 0;
+-      mb->un.varRegLogin.vpi = vpi;
+       mb->un.varRegLogin.did = did;
+       mb->un.varWords[30] = flag;     /* Set flag to issue action on cmpl */
+@@ -377,10 +359,12 @@
+               kfree(mp);
+               mb->mbxCommand = MBX_REG_LOGIN64;
+               /* REG_LOGIN: no buffers */
+-              lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
+-                              "%d (%d):0302 REG_LOGIN: no buffers, DID x%x, "
+-                              "flag x%x\n",
+-                              phba->brd_no, vpi, did, flag);
++              lpfc_printf_log(phba,
++                             KERN_WARNING,
++                             LOG_MBOX,
++                             "%d:0302 REG_LOGIN: no buffers Data x%x x%x\n",
++                             phba->brd_no,
++                             (uint32_t) did, (uint32_t) flag);
+               return (1);
+       }
+       INIT_LIST_HEAD(&mp->list);
+@@ -405,8 +389,7 @@
+ /*                    mailbox command         */
+ /**********************************************/
+ void
+-lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi,
+-               LPFC_MBOXQ_t * pmb)
++lpfc_unreg_login(struct lpfc_hba * phba, uint32_t rpi, LPFC_MBOXQ_t * pmb)
+ {
+       MAILBOX_t *mb;
+@@ -415,52 +398,12 @@
+       mb->un.varUnregLogin.rpi = (uint16_t) rpi;
+       mb->un.varUnregLogin.rsvd1 = 0;
+-      mb->un.varUnregLogin.vpi = vpi;
+       mb->mbxCommand = MBX_UNREG_LOGIN;
+       mb->mbxOwner = OWN_HOST;
+       return;
+ }
+-/**************************************************/
+-/*  lpfc_reg_vpi   Issue a REG_VPI                */
+-/*                    mailbox command             */
+-/**************************************************/
+-void
+-lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid,
+-           LPFC_MBOXQ_t *pmb)
+-{
+-      MAILBOX_t *mb = &pmb->mb;
+-
+-      memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+-
+-      mb->un.varRegVpi.vpi = vpi;
+-      mb->un.varRegVpi.sid = sid;
+-
+-      mb->mbxCommand = MBX_REG_VPI;
+-      mb->mbxOwner = OWN_HOST;
+-      return;
+-
+-}
+-
+-/**************************************************/
+-/*  lpfc_unreg_vpi   Issue a UNREG_VNPI           */
+-/*                    mailbox command             */
+-/**************************************************/
+-void
+-lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb)
+-{
+-      MAILBOX_t *mb = &pmb->mb;
+-      memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+-
+-      mb->un.varUnregVpi.vpi = vpi;
+-
+-      mb->mbxCommand = MBX_UNREG_VPI;
+-      mb->mbxOwner = OWN_HOST;
+-      return;
+-
+-}
+-
+ static void
+ lpfc_config_pcb_setup(struct lpfc_hba * phba)
+ {
+@@ -469,18 +412,14 @@
+       PCB_t *pcbp = &phba->slim2p->pcb;
+       dma_addr_t pdma_addr;
+       uint32_t offset;
+-      uint32_t iocbCnt = 0;
++      uint32_t iocbCnt;
+       int i;
+       pcbp->maxRing = (psli->num_rings - 1);
++      iocbCnt = 0;
+       for (i = 0; i < psli->num_rings; i++) {
+               pring = &psli->ring[i];
+-
+-              pring->sizeCiocb = phba->sli_rev == 3 ? SLI3_IOCB_CMD_SIZE:
+-                                                      SLI2_IOCB_CMD_SIZE;
+-              pring->sizeRiocb = phba->sli_rev == 3 ? SLI3_IOCB_RSP_SIZE:
+-                                                      SLI2_IOCB_RSP_SIZE;
+               /* A ring MUST have both cmd and rsp entries defined to be
+                  valid */
+               if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) {
+@@ -495,18 +434,20 @@
+                       continue;
+               }
+               /* Command ring setup for ring */
+-              pring->cmdringaddr = (void *) &phba->slim2p->IOCBs[iocbCnt];
++              pring->cmdringaddr =
++                  (void *)&phba->slim2p->IOCBs[iocbCnt];
+               pcbp->rdsc[i].cmdEntries = pring->numCiocb;
+-              offset = (uint8_t *) &phba->slim2p->IOCBs[iocbCnt] -
+-                       (uint8_t *) phba->slim2p;
++              offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
++                       (uint8_t *)phba->slim2p;
+               pdma_addr = phba->slim2p_mapping + offset;
+               pcbp->rdsc[i].cmdAddrHigh = putPaddrHigh(pdma_addr);
+               pcbp->rdsc[i].cmdAddrLow = putPaddrLow(pdma_addr);
+               iocbCnt += pring->numCiocb;
+               /* Response ring setup for ring */
+-              pring->rspringaddr = (void *) &phba->slim2p->IOCBs[iocbCnt];
++              pring->rspringaddr =
++                  (void *)&phba->slim2p->IOCBs[iocbCnt];
+               pcbp->rdsc[i].rspEntries = pring->numRiocb;
+               offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
+@@ -521,108 +462,16 @@
+ void
+ lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+ {
+-      MAILBOX_t *mb = &pmb->mb;
++      MAILBOX_t *mb;
 +
-+      goto out;
++      mb = &pmb->mb;
+       memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+       mb->un.varRdRev.cv = 1;
+-      mb->un.varRdRev.v3req = 1; /* Request SLI3 info */
+       mb->mbxCommand = MBX_READ_REV;
+       mb->mbxOwner = OWN_HOST;
+       return;
+ }
+-static void
+-lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb,
+-                      struct lpfc_hbq_init  *hbq_desc)
+-{
+-      hbqmb->profiles.profile2.seqlenbcnt = hbq_desc->seqlenbcnt;
+-      hbqmb->profiles.profile2.maxlen     = hbq_desc->maxlen;
+-      hbqmb->profiles.profile2.seqlenoff  = hbq_desc->seqlenoff;
+-}
+-
+-static void
+-lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb,
+-                      struct lpfc_hbq_init  *hbq_desc)
+-{
+-      hbqmb->profiles.profile3.seqlenbcnt = hbq_desc->seqlenbcnt;
+-      hbqmb->profiles.profile3.maxlen     = hbq_desc->maxlen;
+-      hbqmb->profiles.profile3.cmdcodeoff = hbq_desc->cmdcodeoff;
+-      hbqmb->profiles.profile3.seqlenoff  = hbq_desc->seqlenoff;
+-      memcpy(&hbqmb->profiles.profile3.cmdmatch, hbq_desc->cmdmatch,
+-             sizeof(hbqmb->profiles.profile3.cmdmatch));
+-}
+-
+-static void
+-lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb,
+-                      struct lpfc_hbq_init  *hbq_desc)
+-{
+-      hbqmb->profiles.profile5.seqlenbcnt = hbq_desc->seqlenbcnt;
+-      hbqmb->profiles.profile5.maxlen     = hbq_desc->maxlen;
+-      hbqmb->profiles.profile5.cmdcodeoff = hbq_desc->cmdcodeoff;
+-      hbqmb->profiles.profile5.seqlenoff  = hbq_desc->seqlenoff;
+-      memcpy(&hbqmb->profiles.profile5.cmdmatch, hbq_desc->cmdmatch,
+-             sizeof(hbqmb->profiles.profile5.cmdmatch));
+-}
+-
+-void
+-lpfc_config_hbq(struct lpfc_hba *phba, struct lpfc_hbq_init *hbq_desc,
+-              uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb)
+-{
+-      int i;
+-      MAILBOX_t *mb = &pmb->mb;
+-      struct config_hbq_var *hbqmb = &mb->un.varCfgHbq;
+-
+-      memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
+-      hbqmb->entry_count = hbq_desc->entry_count;   /* # entries in HBQ */
+-      hbqmb->recvNotify = hbq_desc->rn;             /* Receive
+-                                                     * Notification */
+-      hbqmb->numMask    = hbq_desc->mask_count;     /* # R_CTL/TYPE masks
+-                                                     * # in words 0-19 */
+-      hbqmb->profile    = hbq_desc->profile;        /* Selection profile:
+-                                                     * 0 = all,
+-                                                     * 7 = logentry */
+-      hbqmb->ringMask   = hbq_desc->ring_mask;      /* Binds HBQ to a ring
+-                                                     * e.g. Ring0=b0001,
+-                                                     * ring2=b0100 */
+-      hbqmb->headerLen  = hbq_desc->headerLen;      /* 0 if not profile 4
+-                                                     * or 5 */
+-      hbqmb->logEntry   = hbq_desc->logEntry;       /* Set to 1 if this
+-                                                     * HBQ will be used
+-                                                     * for LogEntry
+-                                                     * buffers */
+-      hbqmb->hbqaddrLow = putPaddrLow(phba->hbqslimp.phys) +
+-              hbq_entry_index * sizeof(struct lpfc_hbq_entry);
+-      hbqmb->hbqaddrHigh = putPaddrHigh(phba->hbqslimp.phys);
+-
+-      mb->mbxCommand = MBX_CONFIG_HBQ;
+-      mb->mbxOwner = OWN_HOST;
+-
+-                              /* Copy info for profiles 2,3,5. Other
+-                               * profiles this area is reserved
+-                               */
+-      if (hbq_desc->profile == 2)
+-              lpfc_build_hbq_profile2(hbqmb, hbq_desc);
+-      else if (hbq_desc->profile == 3)
+-              lpfc_build_hbq_profile3(hbqmb, hbq_desc);
+-      else if (hbq_desc->profile == 5)
+-              lpfc_build_hbq_profile5(hbqmb, hbq_desc);
+-
+-      /* Return if no rctl / type masks for this HBQ */
+-      if (!hbq_desc->mask_count)
+-              return;
+-
+-      /* Otherwise we setup specific rctl / type masks for this HBQ */
+-      for (i = 0; i < hbq_desc->mask_count; i++) {
+-              hbqmb->hbqMasks[i].tmatch = hbq_desc->hbqMasks[i].tmatch;
+-              hbqmb->hbqMasks[i].tmask  = hbq_desc->hbqMasks[i].tmask;
+-              hbqmb->hbqMasks[i].rctlmatch = hbq_desc->hbqMasks[i].rctlmatch;
+-              hbqmb->hbqMasks[i].rctlmask  = hbq_desc->hbqMasks[i].rctlmask;
+-      }
+-
+-      return;
+-}
+-
+-
+-
+ void
+ lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
+ {
+@@ -665,16 +514,15 @@
+ }
+ void
+-lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
++lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+ {
+-      MAILBOX_t __iomem *mb_slim = (MAILBOX_t __iomem *) phba->MBslimaddr;
+       MAILBOX_t *mb = &pmb->mb;
+       dma_addr_t pdma_addr;
+       uint32_t bar_low, bar_high;
+       size_t offset;
+       struct lpfc_hgp hgp;
++      void __iomem *to_slim;
+       int i;
+-      uint32_t pgp_offset;
+       memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
+       mb->mbxCommand = MBX_CONFIG_PORT;
+@@ -687,29 +535,12 @@
+       mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr);
+       mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr);
+-      /* If HBA supports SLI=3 ask for it */
+-
+-      if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) {
+-              mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
+-              mb->un.varCfgPort.max_hbq = 1; /* Requesting 2 HBQs */
+-              if (phba->max_vpi && phba->cfg_npiv_enable &&
+-                  phba->vpd.sli3Feat.cmv) {
+-                      mb->un.varCfgPort.max_vpi = phba->max_vpi;
+-                      mb->un.varCfgPort.cmv = 1;
+-                      phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
+-              } else
+-                      mb->un.varCfgPort.max_vpi = phba->max_vpi = 0;
+-      } else
+-              phba->sli_rev = 2;
+-      mb->un.varCfgPort.sli_mode = phba->sli_rev;
+-
+       /* Now setup pcb */
+       phba->slim2p->pcb.type = TYPE_NATIVE_SLI2;
+       phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2;
+       /* Setup Mailbox pointers */
+-      phba->slim2p->pcb.mailBoxSize = offsetof(MAILBOX_t, us) +
+-              sizeof(struct sli2_desc);
++      phba->slim2p->pcb.mailBoxSize = sizeof(MAILBOX_t);
+       offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p;
+       pdma_addr = phba->slim2p_mapping + offset;
+       phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr);
+@@ -737,70 +568,29 @@
+       pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low);
+       pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high);
+-      /*
+-       * Set up HGP - Port Memory
+-       *
+-       * The port expects the host get/put pointers to reside in memory
+-       * following the "non-diagnostic" mode mailbox (32 words, 0x80 bytes)
+-       * area of SLIM.  In SLI-2 mode, there's an additional 16 reserved
+-       * words (0x40 bytes).  This area is not reserved if HBQs are
+-       * configured in SLI-3.
+-       *
+-       * CR0Put    - SLI2(no HBQs) = 0xc0, With HBQs = 0x80
+-       * RR0Get                      0xc4              0x84
+-       * CR1Put                      0xc8              0x88
+-       * RR1Get                      0xcc              0x8c
+-       * CR2Put                      0xd0              0x90
+-       * RR2Get                      0xd4              0x94
+-       * CR3Put                      0xd8              0x98
+-       * RR3Get                      0xdc              0x9c
+-       *
+-       * Reserved                    0xa0-0xbf
+-       *    If HBQs configured:
+-       *                         HBQ 0 Put ptr  0xc0
+-       *                         HBQ 1 Put ptr  0xc4
+-       *                         HBQ 2 Put ptr  0xc8
+-       *                         ......
+-       *                         HBQ(M-1)Put Pointer 0xc0+(M-1)*4
+-       *
+-       */
+-
+-      if (phba->sli_rev == 3) {
+-              phba->host_gp = &mb_slim->us.s3.host[0];
+-              phba->hbq_put = &mb_slim->us.s3.hbq_put[0];
+-      } else {
+-              phba->host_gp = &mb_slim->us.s2.host[0];
+-              phba->hbq_put = NULL;
+-      }
+       /* mask off BAR0's flag bits 0 - 3 */
+       phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) +
+-              (void __iomem *) phba->host_gp -
+-              (void __iomem *)phba->MBslimaddr;
++                                      (SLIMOFF*sizeof(uint32_t));
+       if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64)
+               phba->slim2p->pcb.hgpAddrHigh = bar_high;
+       else
+               phba->slim2p->pcb.hgpAddrHigh = 0;
+       /* write HGP data to SLIM at the required longword offset */
+       memset(&hgp, 0, sizeof(struct lpfc_hgp));
++      to_slim = phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t));
+       for (i=0; i < phba->sli.num_rings; i++) {
+-              lpfc_memcpy_to_slim(phba->host_gp + i, &hgp,
+-                                  sizeof(*phba->host_gp));
++              lpfc_memcpy_to_slim(to_slim, &hgp, sizeof(struct lpfc_hgp));
++              to_slim += sizeof (struct lpfc_hgp);
+       }
+       /* Setup Port Group ring pointer */
+-      if (phba->sli_rev == 3)
+-              pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s3_pgp.port -
+-               (uint8_t *)phba->slim2p;
+-      else
+-              pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
++      offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
+                       (uint8_t *)phba->slim2p;
+-
+-      pdma_addr = phba->slim2p_mapping + pgp_offset;
++      pdma_addr = phba->slim2p_mapping + offset;
+       phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr);
+       phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr);
+-      phba->hbq_get = &phba->slim2p->mbx.us.s3_pgp.hbq_get[0];
+       /* Use callback routine to setp rings in the pcb */
+       lpfc_config_pcb_setup(phba);
+@@ -816,7 +606,11 @@
+       /* Swap PCB if needed */
+       lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb,
+-                            sizeof(PCB_t));
++                                                              sizeof (PCB_t));
 +
-+out_drop:
-+      d_drop(dentry);
-+
-+out_free:
-+      /* should dput all the underlying dentries on error condition */
-+      bstart = dbstart(dentry);
-+      if (bstart >= 0) {
-+              bend = dbend(dentry);
-+              for (bindex = bstart; bindex <= bend; bindex++) {
-+                      dput(unionfs_lower_dentry_idx(dentry, bindex));
-+                      unionfs_mntput(dentry, bindex);
-+              }
++      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
++                      "%d:0405 Service Level Interface (SLI) 2 selected\n",
++                      phba->brd_no);
+ }
+ void
+@@ -850,23 +644,15 @@
+       LPFC_MBOXQ_t *mbq = NULL;
+       struct lpfc_sli *psli = &phba->sli;
+-      list_remove_head((&psli->mboxq), mbq, LPFC_MBOXQ_t, list);
+-      if (mbq)
++      list_remove_head((&psli->mboxq), mbq, LPFC_MBOXQ_t,
++                       list);
++      if (mbq) {
+               psli->mboxq_cnt--;
 +      }
-+      kfree(UNIONFS_D(dentry)->lower_paths);
-+      UNIONFS_D(dentry)->lower_paths = NULL;
-+      set_dbstart(dentry, -1);
-+      set_dbend(dentry, -1);
-+
-+out:
-+      if (!err && UNIONFS_D(dentry)) {
-+              BUG_ON(dbend(dentry) > UNIONFS_D(dentry)->bcount);
-+              BUG_ON(dbend(dentry) > sbmax(dentry->d_sb));
-+              BUG_ON(dbstart(dentry) < 0);
-+      }
-+      kfree(whname);
-+      if (locked_parent)
-+              unionfs_unlock_dentry(parent_dentry);
-+      dput(parent_dentry);
-+      if (locked_child || (err && allocated_new_info))
-+              unionfs_unlock_dentry(dentry);
-+      return ERR_PTR(err);
-+}
-+
-+/* This is a utility function that fills in a unionfs dentry */
-+int unionfs_partial_lookup(struct dentry *dentry)
-+{
-+      struct dentry *tmp;
-+      struct nameidata nd = { .flags = 0 };
-+
-+      tmp = unionfs_lookup_backend(dentry, &nd, INTERPOSE_PARTIAL);
-+      if (!tmp)
-+              return 0;
-+      if (IS_ERR(tmp))
-+              return PTR_ERR(tmp);
-+      /* need to change the interface */
-+      BUG_ON(tmp != dentry);
-+      return -ENOSYS;
-+}
-+
-+/* The dentry cache is just so we have properly sized dentries. */
-+static struct kmem_cache *unionfs_dentry_cachep;
-+int unionfs_init_dentry_cache(void)
-+{
-+      unionfs_dentry_cachep =
-+              kmem_cache_create("unionfs_dentry",
-+                                sizeof(struct unionfs_dentry_info),
-+                                0, SLAB_RECLAIM_ACCOUNT, NULL, NULL);
-+
-+      return (unionfs_dentry_cachep ? 0 : -ENOMEM);
-+}
-+
-+void unionfs_destroy_dentry_cache(void)
-+{
-+      if (unionfs_dentry_cachep)
-+              kmem_cache_destroy(unionfs_dentry_cachep);
-+}
-+
-+void free_dentry_private_data(struct dentry *dentry)
-+{
-+      if (!dentry || !dentry->d_fsdata)
-+              return;
-+      kmem_cache_free(unionfs_dentry_cachep, dentry->d_fsdata);
-+      dentry->d_fsdata = NULL;
-+}
-+
-+static inline int __realloc_dentry_private_data(struct dentry *dentry)
-+{
-+      struct unionfs_dentry_info *info = UNIONFS_D(dentry);
-+      void *p;
-+      int size;
-+
-+      BUG_ON(!info);
-+
-+      size = sizeof(struct path) * sbmax(dentry->d_sb);
-+      p = krealloc(info->lower_paths, size, GFP_ATOMIC);
-+      if (!p)
-+              return -ENOMEM;
-+
-+      info->lower_paths = p;
-+
-+      info->bstart = -1;
-+      info->bend = -1;
-+      info->bopaque = -1;
-+      info->bcount = sbmax(dentry->d_sb);
-+      atomic_set(&info->generation,
-+                      atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
-+
-+      memset(info->lower_paths, 0, size);
-+
-+      return 0;
-+}
-+
-+/* UNIONFS_D(dentry)->lock must be locked */
-+int realloc_dentry_private_data(struct dentry *dentry)
-+{
-+      if (!__realloc_dentry_private_data(dentry))
+       return mbq;
+ }
+-void
+-lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
+-{
+-      /* This function expects to be called from interupt context */
+-      spin_lock(&phba->hbalock);
+-      list_add_tail(&mbq->list, &phba->sli.mboxq_cmpl);
+-      spin_unlock(&phba->hbalock);
+-      return;
+-}
+-
+ int
+ lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
+ {
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_mem.c linux-2.6.22-570/drivers/scsi/lpfc/lpfc_mem.c
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_mem.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_mem.c      2007-07-08 19:32:17.000000000 -0400
+@@ -1,7 +1,7 @@
+ /*******************************************************************
+  * This file is part of the Emulex Linux Device Driver for         *
+  * Fibre Channel Host Bus Adapters.                                *
+- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
++ * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
+  * EMULEX and SLI are trademarks of Emulex.                        *
+  * www.emulex.com                                                  *
+  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
+@@ -38,13 +38,10 @@
+ #define LPFC_MBUF_POOL_SIZE     64      /* max elements in MBUF safety pool */
+ #define LPFC_MEM_POOL_SIZE      64      /* max elem in non-DMA safety pool */
+-
+-
+ int
+ lpfc_mem_alloc(struct lpfc_hba * phba)
+ {
+       struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
+-      int longs;
+       int i;
+       phba->lpfc_scsi_dma_buf_pool = pci_pool_create("lpfc_scsi_dma_buf_pool",
+@@ -83,27 +80,10 @@
+       if (!phba->nlp_mem_pool)
+               goto fail_free_mbox_pool;
+-      phba->lpfc_hbq_pool = pci_pool_create("lpfc_hbq_pool",phba->pcidev,
+-                                            LPFC_BPL_SIZE, 8, 0);
+-      if (!phba->lpfc_hbq_pool)
+-              goto fail_free_nlp_mem_pool;
+-
+-      /* vpi zero is reserved for the physical port so add 1 to max */
+-      longs = ((phba->max_vpi + 1) + BITS_PER_LONG - 1) / BITS_PER_LONG;
+-      phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), GFP_KERNEL);
+-      if (!phba->vpi_bmask)
+-              goto fail_free_hbq_pool;
+-
+       return 0;
+- fail_free_hbq_pool:
+-      lpfc_sli_hbqbuf_free_all(phba);
+- fail_free_nlp_mem_pool:
+-      mempool_destroy(phba->nlp_mem_pool);
+-      phba->nlp_mem_pool = NULL;
+  fail_free_mbox_pool:
+       mempool_destroy(phba->mbox_mem_pool);
+-      phba->mbox_mem_pool = NULL;
+  fail_free_mbuf_pool:
+       while (i--)
+               pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
+@@ -111,10 +91,8 @@
+       kfree(pool->elements);
+  fail_free_lpfc_mbuf_pool:
+       pci_pool_destroy(phba->lpfc_mbuf_pool);
+-      phba->lpfc_mbuf_pool = NULL;
+  fail_free_dma_buf_pool:
+       pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
+-      phba->lpfc_scsi_dma_buf_pool = NULL;
+  fail:
+       return -ENOMEM;
+ }
+@@ -128,9 +106,6 @@
+       struct lpfc_dmabuf   *mp;
+       int i;
+-      kfree(phba->vpi_bmask);
+-      lpfc_sli_hbqbuf_free_all(phba);
+-
+       list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) {
+               mp = (struct lpfc_dmabuf *) (mbox->context1);
+               if (mp) {
+@@ -140,15 +115,6 @@
+               list_del(&mbox->list);
+               mempool_free(mbox, phba->mbox_mem_pool);
+       }
+-      list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq_cmpl, list) {
+-              mp = (struct lpfc_dmabuf *) (mbox->context1);
+-              if (mp) {
+-                      lpfc_mbuf_free(phba, mp->virt, mp->phys);
+-                      kfree(mp);
+-              }
+-              list_del(&mbox->list);
+-              mempool_free(mbox, phba->mbox_mem_pool);
+-      }
+       psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+       if (psli->mbox_active) {
+@@ -166,20 +132,12 @@
+               pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
+                                                pool->elements[i].phys);
+       kfree(pool->elements);
+-
+-      pci_pool_destroy(phba->lpfc_hbq_pool);
+       mempool_destroy(phba->nlp_mem_pool);
+       mempool_destroy(phba->mbox_mem_pool);
+       pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
+       pci_pool_destroy(phba->lpfc_mbuf_pool);
+-      phba->lpfc_hbq_pool = NULL;
+-      phba->nlp_mem_pool = NULL;
+-      phba->mbox_mem_pool = NULL;
+-      phba->lpfc_scsi_dma_buf_pool = NULL;
+-      phba->lpfc_mbuf_pool = NULL;
+-
+       /* Free the iocb lookup array */
+       kfree(psli->iocbq_lookup);
+       psli->iocbq_lookup = NULL;
+@@ -190,23 +148,20 @@
+ lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
+ {
+       struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
+-      unsigned long iflags;
+       void *ret;
+       ret = pci_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle);
+-      spin_lock_irqsave(&phba->hbalock, iflags);
+-      if (!ret && (mem_flags & MEM_PRI) && pool->current_count) {
++      if (!ret && ( mem_flags & MEM_PRI) && pool->current_count) {
+               pool->current_count--;
+               ret = pool->elements[pool->current_count].virt;
+               *handle = pool->elements[pool->current_count].phys;
+       }
+-      spin_unlock_irqrestore(&phba->hbalock, iflags);
+       return ret;
+ }
+ void
+-__lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
++lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
+ {
+       struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
+@@ -219,51 +174,3 @@
+       }
+       return;
+ }
+-
+-void
+-lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
+-{
+-      unsigned long iflags;
+-
+-      spin_lock_irqsave(&phba->hbalock, iflags);
+-      __lpfc_mbuf_free(phba, virt, dma);
+-      spin_unlock_irqrestore(&phba->hbalock, iflags);
+-      return;
+-}
+-
+-void *
+-lpfc_hbq_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
+-{
+-      void *ret;
+-      ret = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_ATOMIC, handle);
+-      return ret;
+-}
+-
+-void
+-lpfc_hbq_free(struct lpfc_hba *phba, void *virt, dma_addr_t dma)
+-{
+-      pci_pool_free(phba->lpfc_hbq_pool, virt, dma);
+-      return;
+-}
+-
+-void
+-lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
+-{
+-      struct hbq_dmabuf *hbq_entry;
+-
+-      if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
+-              hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf);
+-              if (hbq_entry->tag == -1) {
+-                      lpfc_hbq_free(phba, hbq_entry->dbuf.virt,
+-                                    hbq_entry->dbuf.phys);
+-                      kfree(hbq_entry);
+-              } else {
+-                      lpfc_sli_free_hbq(phba, hbq_entry);
+-              }
+-      } else {
+-              lpfc_mbuf_free(phba, mp->virt, mp->phys);
+-              kfree(mp);
+-      }
+-      return;
+-}
+-
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_nportdisc.c linux-2.6.22-570/drivers/scsi/lpfc/lpfc_nportdisc.c
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_nportdisc.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_nportdisc.c        2007-07-08 19:32:17.000000000 -0400
+@@ -1,4 +1,4 @@
+- /*******************************************************************
++/*******************************************************************
+  * This file is part of the Emulex Linux Device Driver for         *
+  * Fibre Channel Host Bus Adapters.                                *
+  * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
+@@ -35,22 +35,20 @@
+ #include "lpfc.h"
+ #include "lpfc_logmsg.h"
+ #include "lpfc_crtn.h"
+-#include "lpfc_vport.h"
+-#include "lpfc_debugfs.h"
+ /* Called to verify a rcv'ed ADISC was intended for us. */
+ static int
+-lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-               struct lpfc_name *nn, struct lpfc_name *pn)
++lpfc_check_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
++               struct lpfc_name * nn, struct lpfc_name * pn)
+ {
+       /* Compare the ADISC rsp WWNN / WWPN matches our internal node
+        * table entry for that node.
+        */
+-      if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)))
++      if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)) != 0)
+               return 0;
+-      if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)))
++      if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)) != 0)
+               return 0;
+       /* we match, return success */
+@@ -58,10 +56,11 @@
+ }
+ int
+-lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-               struct serv_parm * sp, uint32_t class)
++lpfc_check_sparm(struct lpfc_hba * phba,
++               struct lpfc_nodelist * ndlp, struct serv_parm * sp,
++               uint32_t class)
+ {
+-      volatile struct serv_parm *hsp = &vport->fc_sparam;
++      volatile struct serv_parm *hsp = &phba->fc_sparam;
+       uint16_t hsp_value, ssp_value = 0;
+       /*
+@@ -76,14 +75,12 @@
+                               hsp->cls1.rcvDataSizeLsb;
+               ssp_value = (sp->cls1.rcvDataSizeMsb << 8) |
+                               sp->cls1.rcvDataSizeLsb;
+-              if (!ssp_value)
+-                      goto bad_service_param;
+               if (ssp_value > hsp_value) {
+                       sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb;
+                       sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
+               }
+       } else if (class == CLASS1) {
+-              goto bad_service_param;
 +              return 0;
-+
-+      kfree(UNIONFS_D(dentry)->lower_paths);
-+      free_dentry_private_data(dentry);
-+      return -ENOMEM;
-+}
-+
-+/* allocate new dentry private data */
-+int new_dentry_private_data(struct dentry *dentry)
-+{
-+      struct unionfs_dentry_info *info = UNIONFS_D(dentry);
-+
-+      BUG_ON(info);
-+
-+      info = kmem_cache_alloc(unionfs_dentry_cachep, GFP_ATOMIC);
-+      if (!info)
-+              return -ENOMEM;
-+
-+      mutex_init(&info->lock);
-+      mutex_lock(&info->lock);
-+
-+      info->lower_paths = NULL;
-+
-+      dentry->d_fsdata = info;
-+
-+      if (!__realloc_dentry_private_data(dentry))
+       }
+       if (sp->cls2.classValid) {
+@@ -91,14 +88,12 @@
+                               hsp->cls2.rcvDataSizeLsb;
+               ssp_value = (sp->cls2.rcvDataSizeMsb << 8) |
+                               sp->cls2.rcvDataSizeLsb;
+-              if (!ssp_value)
+-                      goto bad_service_param;
+               if (ssp_value > hsp_value) {
+                       sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb;
+                       sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
+               }
+       } else if (class == CLASS2) {
+-              goto bad_service_param;
 +              return 0;
-+
-+      mutex_unlock(&info->lock);
-+      free_dentry_private_data(dentry);
-+      return -ENOMEM;
-+}
-+
-+/*
-+ * scan through the lower dentry objects, and set bstart to reflect the
-+ * starting branch
-+ */
-+void update_bstart(struct dentry *dentry)
-+{
-+      int bindex;
-+      int bstart = dbstart(dentry);
-+      int bend = dbend(dentry);
-+      struct dentry *hidden_dentry;
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!hidden_dentry)
-+                      continue;
-+              if (hidden_dentry->d_inode) {
-+                      set_dbstart(dentry, bindex);
-+                      break;
-+              }
-+              dput(hidden_dentry);
-+              unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
-+      }
-+}
-diff -Nurb linux-2.6.22-570/fs/unionfs/main.c linux-2.6.22-590/fs/unionfs/main.c
---- linux-2.6.22-570/fs/unionfs/main.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/main.c 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,729 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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 "union.h"
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+
-+/*
-+ * Connect a unionfs inode dentry/inode with several lower ones.  This is
-+ * the classic stackable file system "vnode interposition" action.
-+ *
-+ * @sb: unionfs's super_block
-+ */
-+int unionfs_interpose(struct dentry *dentry, struct super_block *sb, int flag)
-+{
-+      struct inode *hidden_inode;
-+      struct dentry *hidden_dentry;
-+      int err = 0;
-+      struct inode *inode;
-+      int is_negative_dentry = 1;
-+      int bindex, bstart, bend;
-+
-+      verify_locked(dentry);
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+
-+      /* Make sure that we didn't get a negative dentry. */
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              if (unionfs_lower_dentry_idx(dentry, bindex) &&
-+                  unionfs_lower_dentry_idx(dentry, bindex)->d_inode) {
-+                      is_negative_dentry = 0;
-+                      break;
-+              }
-+      }
-+      BUG_ON(is_negative_dentry);
-+
-+      /*
-+       * We allocate our new inode below, by calling iget.
-+       * iget will call our read_inode which will initialize some
-+       * of the new inode's fields
-+       */
-+
-+      /*
-+       * On revalidate we've already got our own inode and just need
-+       * to fix it up.
-+       */
-+      if (flag == INTERPOSE_REVAL) {
-+              inode = dentry->d_inode;
-+              UNIONFS_I(inode)->bstart = -1;
-+              UNIONFS_I(inode)->bend = -1;
-+              atomic_set(&UNIONFS_I(inode)->generation,
-+                         atomic_read(&UNIONFS_SB(sb)->generation));
-+
-+              UNIONFS_I(inode)->lower_inodes =
-+                      kcalloc(sbmax(sb), sizeof(struct inode *), GFP_KERNEL);
-+              if (!UNIONFS_I(inode)->lower_inodes) {
-+                      err = -ENOMEM;
-+                      goto out;
-+              }
-+      } else {
-+              /* get unique inode number for unionfs */
-+              inode = iget(sb, iunique(sb, UNIONFS_ROOT_INO));
-+              if (!inode) {
-+                      err = -EACCES;
-+                      goto out;
-+              }
-+
-+              if (atomic_read(&inode->i_count) > 1)
-+                      goto skip;
-+      }
-+
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!hidden_dentry) {
-+                      unionfs_set_lower_inode_idx(inode, bindex, NULL);
-+                      continue;
-+              }
-+
-+              /* Initialize the hidden inode to the new hidden inode. */
-+              if (!hidden_dentry->d_inode)
-+                      continue;
-+
-+              unionfs_set_lower_inode_idx(inode, bindex,
-+                                          igrab(hidden_dentry->d_inode));
-+      }
-+
-+      ibstart(inode) = dbstart(dentry);
-+      ibend(inode) = dbend(dentry);
-+
-+      /* Use attributes from the first branch. */
-+      hidden_inode = unionfs_lower_inode(inode);
-+
-+      /* Use different set of inode ops for symlinks & directories */
-+      if (S_ISLNK(hidden_inode->i_mode))
-+              inode->i_op = &unionfs_symlink_iops;
-+      else if (S_ISDIR(hidden_inode->i_mode))
-+              inode->i_op = &unionfs_dir_iops;
-+
-+      /* Use different set of file ops for directories */
-+      if (S_ISDIR(hidden_inode->i_mode))
-+              inode->i_fop = &unionfs_dir_fops;
-+
-+      /* properly initialize special inodes */
-+      if (S_ISBLK(hidden_inode->i_mode) || S_ISCHR(hidden_inode->i_mode) ||
-+          S_ISFIFO(hidden_inode->i_mode) || S_ISSOCK(hidden_inode->i_mode))
-+              init_special_inode(inode, hidden_inode->i_mode,
-+                                 hidden_inode->i_rdev);
-+
-+      /* all well, copy inode attributes */
-+      fsstack_copy_attr_all(inode, hidden_inode, unionfs_get_nlinks);
-+      fsstack_copy_inode_size(inode, hidden_inode);
-+
-+skip:
-+      /* only (our) lookup wants to do a d_add */
-+      switch (flag) {
-+      case INTERPOSE_DEFAULT:
-+      case INTERPOSE_REVAL_NEG:
-+              d_instantiate(dentry, inode);
-+              break;
-+      case INTERPOSE_LOOKUP:
-+              err = PTR_ERR(d_splice_alias(inode, dentry));
-+              break;
-+      case INTERPOSE_REVAL:
-+              /* Do nothing. */
-+              break;
-+      default:
-+              printk(KERN_ERR "unionfs: invalid interpose flag passed!");
-+              BUG();
-+      }
-+
-+out:
-+      return err;
-+}
-+
-+/* like interpose above, but for an already existing dentry */
-+void unionfs_reinterpose(struct dentry *dentry)
-+{
-+      struct dentry *hidden_dentry;
-+      struct inode *inode;
-+      int bindex, bstart, bend;
-+
-+      verify_locked(dentry);
-+
-+      /* This is pre-allocated inode */
-+      inode = dentry->d_inode;
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+              if (!hidden_dentry)
-+                      continue;
-+
-+              if (!hidden_dentry->d_inode)
-+                      continue;
-+              if (unionfs_lower_inode_idx(inode, bindex))
-+                      continue;
-+              unionfs_set_lower_inode_idx(inode, bindex,
-+                                          igrab(hidden_dentry->d_inode));
-+      }
-+      ibstart(inode) = dbstart(dentry);
-+      ibend(inode) = dbend(dentry);
-+}
-+
-+/*
-+ * make sure the branch we just looked up (nd) makes sense:
-+ *
-+ * 1) we're not trying to stack unionfs on top of unionfs
-+ * 2) it exists
-+ * 3) is a directory
-+ */
-+int check_branch(struct nameidata *nd)
-+{
-+      if (!strcmp(nd->dentry->d_sb->s_type->name, "unionfs"))
-+              return -EINVAL;
-+      if (!nd->dentry->d_inode)
-+              return -ENOENT;
-+      if (!S_ISDIR(nd->dentry->d_inode->i_mode))
-+              return -ENOTDIR;
-+      return 0;
-+}
-+
-+/* checks if two hidden_dentries have overlapping branches */
-+static int is_branch_overlap(struct dentry *dent1, struct dentry *dent2)
-+{
-+      struct dentry *dent = NULL;
-+
-+      dent = dent1;
-+      while ((dent != dent2) && (dent->d_parent != dent))
-+              dent = dent->d_parent;
-+
-+      if (dent == dent2)
-+              return 1;
-+
-+      dent = dent2;
-+      while ((dent != dent1) && (dent->d_parent != dent))
-+              dent = dent->d_parent;
-+
-+      return (dent == dent1);
-+}
-+
-+/*
-+ * Parse branch mode helper function
-+ */
-+int __parse_branch_mode(const char *name)
-+{
-+      if (!name)
+       }
+       if (sp->cls3.classValid) {
+@@ -106,14 +101,12 @@
+                               hsp->cls3.rcvDataSizeLsb;
+               ssp_value = (sp->cls3.rcvDataSizeMsb << 8) |
+                               sp->cls3.rcvDataSizeLsb;
+-              if (!ssp_value)
+-                      goto bad_service_param;
+               if (ssp_value > hsp_value) {
+                       sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb;
+                       sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
+               }
+       } else if (class == CLASS3) {
+-              goto bad_service_param;
 +              return 0;
-+      if (!strcmp(name, "ro"))
-+              return MAY_READ;
-+      if (!strcmp(name, "rw"))
-+              return (MAY_READ | MAY_WRITE);
-+      return 0;
-+}
-+
-+/*
-+ * Parse "ro" or "rw" options, but default to "rw" of no mode options
-+ * was specified.
-+ */
-+int parse_branch_mode(const char *name)
-+{
-+      int perms =  __parse_branch_mode(name);
-+
-+      if (perms == 0)
-+              perms = MAY_READ | MAY_WRITE;
-+      return perms;
-+}
-+
-+/* 
-+ * parse the dirs= mount argument
-+ *
-+ * We don't need to lock the superblock private data's rwsem, as we get
-+ * called only by unionfs_read_super - it is still a long time before anyone
-+ * can even get a reference to us.
-+ */
-+static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info
-+                           *hidden_root_info, char *options)
-+{
-+      struct nameidata nd;
-+      char *name;
-+      int err = 0;
-+      int branches = 1;
-+      int bindex = 0;
-+      int i = 0;
-+      int j = 0;
-+
-+      struct dentry *dent1;
-+      struct dentry *dent2;
-+
-+      if (options[0] == '\0') {
-+              printk(KERN_WARNING "unionfs: no branches specified\n");
-+              err = -EINVAL;
-+              goto out;
-+      }
-+
-+      /*
-+       * Each colon means we have a separator, this is really just a rough
-+       * guess, since strsep will handle empty fields for us.
-+       */
-+      for (i = 0; options[i]; i++)
-+              if (options[i] == ':')
-+                      branches++;
-+
-+      /* allocate space for underlying pointers to hidden dentry */
-+      UNIONFS_SB(sb)->data =
-+              kcalloc(branches, sizeof(struct unionfs_data), GFP_KERNEL);
-+      if (!UNIONFS_SB(sb)->data) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      hidden_root_info->lower_paths =
-+              kcalloc(branches, sizeof(struct path), GFP_KERNEL);
-+      if (!hidden_root_info->lower_paths) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      /* now parsing a string such as "b1:b2=rw:b3=ro:b4" */
-+      branches = 0;
-+      while ((name = strsep(&options, ":")) != NULL) {
-+              int perms;
-+              char *mode = strchr(name, '=');
-+
-+              if (!name || !*name)
-+                      continue;
-+
-+              branches++;
-+
-+              /* strip off '=' if any */
-+              if (mode)
-+                      *mode++ = '\0';
-+
-+              perms = parse_branch_mode(mode);
-+              if (!bindex && !(perms & MAY_WRITE)) {
-+                      err = -EINVAL;
-+                      goto out;
-+              }
-+
-+              err = path_lookup(name, LOOKUP_FOLLOW, &nd);
-+              if (err) {
-+                      printk(KERN_WARNING "unionfs: error accessing "
-+                             "hidden directory '%s' (error %d)\n",
-+                             name, err);
-+                      goto out;
-+              }
-+
-+              if ((err = check_branch(&nd))) {
-+                      printk(KERN_WARNING "unionfs: hidden directory "
-+                             "'%s' is not a valid branch\n", name);
-+                      path_release(&nd);
-+                      goto out;
-+              }
-+
-+              hidden_root_info->lower_paths[bindex].dentry = nd.dentry;
-+              hidden_root_info->lower_paths[bindex].mnt = nd.mnt;
-+
-+              set_branchperms(sb, bindex, perms);
-+              set_branch_count(sb, bindex, 0);
-+              new_branch_id(sb, bindex);
-+
-+              if (hidden_root_info->bstart < 0)
-+                      hidden_root_info->bstart = bindex;
-+              hidden_root_info->bend = bindex;
-+              bindex++;
-+      }
-+
-+      if (branches == 0) {
-+              printk(KERN_WARNING "unionfs: no branches specified\n");
-+              err = -EINVAL;
-+              goto out;
-+      }
-+
-+      BUG_ON(branches != (hidden_root_info->bend + 1));
-+
-+      /*
-+       * Ensure that no overlaps exist in the branches.
-+       *
-+       * This test is required because the Linux kernel has no support
-+       * currently for ensuring coherency between stackable layers and
-+       * branches.  If we were to allow overlapping branches, it would be
-+       * possible, for example, to delete a file via one branch, which
-+       * would not be reflected in another branch.  Such incoherency could
-+       * lead to inconsistencies and even kernel oopses.  Rather than
-+       * implement hacks to work around some of these cache-coherency
-+       * problems, we prevent branch overlapping, for now.  A complete
-+       * solution will involve proper kernel/VFS support for cache
-+       * coherency, at which time we could safely remove this
-+       * branch-overlapping test.
-+       */
-+      for (i = 0; i < branches; i++) {
-+              for (j = i + 1; j < branches; j++) {
-+                      dent1 = hidden_root_info->lower_paths[i].dentry;
-+                      dent2 = hidden_root_info->lower_paths[j].dentry;
-+
-+                      if (is_branch_overlap(dent1, dent2)) {
-+                              printk(KERN_WARNING "unionfs: branches %d and "
-+                                     "%d overlap\n", i, j);
-+                              err = -EINVAL;
-+                              goto out;
+       }
+       /*
+@@ -132,21 +125,11 @@
+       memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
+       memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name));
+       return 1;
+-bad_service_param:
+-      lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY,
+-                      "%d (%d):0207 Device %x "
+-                      "(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent "
+-                      "invalid service parameters.  Ignoring device.\n",
+-                      vport->phba->brd_no, ndlp->vport->vpi, ndlp->nlp_DID,
+-                      sp->nodeName.u.wwn[0], sp->nodeName.u.wwn[1],
+-                      sp->nodeName.u.wwn[2], sp->nodeName.u.wwn[3],
+-                      sp->nodeName.u.wwn[4], sp->nodeName.u.wwn[5],
+-                      sp->nodeName.u.wwn[6], sp->nodeName.u.wwn[7]);
+-      return 0;
+ }
+ static void *
+-lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
++lpfc_check_elscmpl_iocb(struct lpfc_hba * phba,
++                    struct lpfc_iocbq *cmdiocb,
+                     struct lpfc_iocbq *rspiocb)
+ {
+       struct lpfc_dmabuf *pcmd, *prsp;
+@@ -185,29 +168,32 @@
+  * routine effectively results in a "software abort".
+  */
+ int
+-lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
++lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
+ {
+       LIST_HEAD(completions);
+-      struct lpfc_sli  *psli = &phba->sli;
+-      struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
++      struct lpfc_sli *psli;
++      struct lpfc_sli_ring *pring;
+       struct lpfc_iocbq *iocb, *next_iocb;
+       IOCB_t *cmd;
+       /* Abort outstanding I/O on NPort <nlp_DID> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0205 Abort outstanding I/O on NPort x%x "
++                      "%d:0205 Abort outstanding I/O on NPort x%x "
+                       "Data: x%x x%x x%x\n",
+-                      phba->brd_no, ndlp->vport->vpi, ndlp->nlp_DID,
+-                      ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
++                      phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
++                      ndlp->nlp_state, ndlp->nlp_rpi);
+-      lpfc_fabric_abort_nport(ndlp);
++      psli = &phba->sli;
++      pring = &psli->ring[LPFC_ELS_RING];
+       /* First check the txq */
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
+-              /* Check to see if iocb matches the nport we are looking for */
++              /* Check to see if iocb matches the nport we are looking
++                 for */
+               if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
+-                      /* It matches, so deque and call compl with anp error */
++                      /* It matches, so deque and call compl with an
++                         error */
+                       list_move_tail(&iocb->list, &completions);
+                       pring->txq_cnt--;
+               }
+@@ -215,39 +201,37 @@
+       /* Next check the txcmplq */
+       list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
+-              /* Check to see if iocb matches the nport we are looking for */
+-              if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
++              /* Check to see if iocb matches the nport we are looking
++                 for */
++              if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))
+                       lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+       }
+-      }
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       while (!list_empty(&completions)) {
+               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
+               cmd = &iocb->iocb;
+-              list_del_init(&iocb->list);
++              list_del(&iocb->list);
+-              if (!iocb->iocb_cmpl)
+-                      lpfc_sli_release_iocbq(phba, iocb);
+-              else {
++              if (iocb->iocb_cmpl) {
+                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                       cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+                       (iocb->iocb_cmpl) (phba, iocb, iocb);
+-              }
++              } else
++                      lpfc_sli_release_iocbq(phba, iocb);
+       }
+       /* If we are delaying issuing an ELS command, cancel it */
+       if (ndlp->nlp_flag & NLP_DELAY_TMO)
+-              lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
++              lpfc_cancel_retry_delay_tmo(phba, ndlp);
+       return 0;
+ }
+ static int
+-lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
++lpfc_rcv_plogi(struct lpfc_hba * phba,
++                    struct lpfc_nodelist * ndlp,
+                     struct lpfc_iocbq *cmdiocb)
+ {
+-      struct Scsi_Host   *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba    *phba = vport->phba;
+       struct lpfc_dmabuf *pcmd;
+       uint32_t *lp;
+       IOCB_t *icmd;
+@@ -257,14 +241,14 @@
+       int rc;
+       memset(&stat, 0, sizeof (struct ls_rjt));
+-      if (vport->port_state <= LPFC_FLOGI) {
++      if (phba->hba_state <= LPFC_FLOGI) {
+               /* Before responding to PLOGI, check for pt2pt mode.
+                * If we are pt2pt, with an outstanding FLOGI, abort
+                * the FLOGI and resend it first.
+                */
+-              if (vport->fc_flag & FC_PT2PT) {
++              if (phba->fc_flag & FC_PT2PT) {
+                       lpfc_els_abort_flogi(phba);
+-                      if (!(vport->fc_flag & FC_PT2PT_PLOGI)) {
++                      if (!(phba->fc_flag & FC_PT2PT_PLOGI)) {
+                               /* If the other side is supposed to initiate
+                                * the PLOGI anyway, just ACC it now and
+                                * move on with discovery.
+@@ -273,42 +257,45 @@
+                               phba->fc_ratov = FF_DEF_RATOV;
+                               /* Start discovery - this should just do
+                                  CLEAR_LA */
+-                              lpfc_disc_start(vport);
+-                      } else
+-                              lpfc_initial_flogi(vport);
++                              lpfc_disc_start(phba);
++                      } else {
++                              lpfc_initial_flogi(phba);
 +                      }
-+              }
+               } else {
+                       stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
+                       stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
+-                      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
+-                                          ndlp, NULL);
++                      lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb,
++                                          ndlp);
+                       return 0;
+               }
+       }
+       pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
+       lp = (uint32_t *) pcmd->virt;
+       sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
+-      if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) {
++      if ((lpfc_check_sparm(phba, ndlp, sp, CLASS3) == 0)) {
+               /* Reject this request because invalid parameters */
+               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+               stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
+-              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+-                      NULL);
++              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+               return 0;
+       }
+       icmd = &cmdiocb->iocb;
+       /* PLOGI chkparm OK */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi,
++      lpfc_printf_log(phba,
++                      KERN_INFO,
++                      LOG_ELS,
++                      "%d:0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
++                      phba->brd_no,
+                       ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag,
+                       ndlp->nlp_rpi);
+-      if (phba->cfg_fcp_class == 2 && sp->cls2.classValid)
++      if ((phba->cfg_fcp_class == 2) &&
++          (sp->cls2.classValid)) {
+               ndlp->nlp_fcp_info |= CLASS2;
+-      else
++      } else {
+               ndlp->nlp_fcp_info |= CLASS3;
+-
 +      }
-+
-+out:
-+      if (err) {
-+              for (i = 0; i < branches; i++)
-+                      if (hidden_root_info->lower_paths[i].dentry) {
-+                              dput(hidden_root_info->lower_paths[i].dentry);
-+                              /* initialize: can't use unionfs_mntput here */
-+                              mntput(hidden_root_info->lower_paths[i].mnt);
-+                      }
-+
-+              kfree(hidden_root_info->lower_paths);
-+              kfree(UNIONFS_SB(sb)->data);
-+
-+              /*
-+               * MUST clear the pointers to prevent potential double free if
-+               * the caller dies later on
-+               */
-+              hidden_root_info->lower_paths = NULL;
-+              UNIONFS_SB(sb)->data = NULL;
+       ndlp->nlp_class_sup = 0;
+       if (sp->cls1.classValid)
+               ndlp->nlp_class_sup |= FC_COS_CLASS1;
+@@ -330,37 +317,35 @@
+       case  NLP_STE_PRLI_ISSUE:
+       case  NLP_STE_UNMAPPED_NODE:
+       case  NLP_STE_MAPPED_NODE:
+-              lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0);
++              lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0);
+               return 1;
+       }
+-      if ((vport->fc_flag & FC_PT2PT) &&
+-          !(vport->fc_flag & FC_PT2PT_PLOGI)) {
++      if ((phba->fc_flag & FC_PT2PT)
++          && !(phba->fc_flag & FC_PT2PT_PLOGI)) {
+               /* rcv'ed PLOGI decides what our NPortId will be */
+-              vport->fc_myDID = icmd->un.rcvels.parmRo;
++              phba->fc_myDID = icmd->un.rcvels.parmRo;
+               mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+               if (mbox == NULL)
+                       goto out;
+               lpfc_config_link(phba, mbox);
+               mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-              mbox->vport = vport;
+               rc = lpfc_sli_issue_mbox
+                       (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
+               if (rc == MBX_NOT_FINISHED) {
+-                      mempool_free(mbox, phba->mbox_mem_pool);
++                      mempool_free( mbox, phba->mbox_mem_pool);
+                       goto out;
+               }
+-              lpfc_can_disctmo(vport);
++              lpfc_can_disctmo(phba);
+       }
+       mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (!mbox)
++      if (mbox == NULL)
+               goto out;
+-      rc = lpfc_reg_login(phba, vport->vpi, icmd->un.rcvels.remoteID,
+-                          (uint8_t *) sp, mbox, 0);
+-      if (rc) {
+-              mempool_free(mbox, phba->mbox_mem_pool);
++      if (lpfc_reg_login(phba, icmd->un.rcvels.remoteID,
++                         (uint8_t *) sp, mbox, 0)) {
++              mempool_free( mbox, phba->mbox_mem_pool);
+               goto out;
+       }
+@@ -372,10 +357,7 @@
+        * mbox->context2 = lpfc_nlp_get(ndlp) deferred until mailbox
+        * command issued in lpfc_cmpl_els_acc().
+        */
+-      mbox->vport = vport;
+-      spin_lock_irq(shost->host_lock);
+       ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
+-      spin_unlock_irq(shost->host_lock);
+       /*
+        * If there is an outstanding PLOGI issued, abort it before
+@@ -391,38 +373,21 @@
+               lpfc_els_abort(phba, ndlp);
+       }
+-      if ((vport->port_type == LPFC_NPIV_PORT &&
+-            phba->cfg_vport_restrict_login)) {
+-
+-              /* In order to preserve RPIs, we want to cleanup
+-               * the default RPI the firmware created to rcv
+-               * this ELS request. The only way to do this is
+-               * to register, then unregister the RPI.
+-               */
+-              spin_lock_irq(shost->host_lock);
+-              ndlp->nlp_flag |= NLP_RM_DFLT_RPI;
+-              spin_unlock_irq(shost->host_lock);
+-              stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
+-              stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
+-              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
+-                      ndlp, mbox);
+-              return 1;
+-      }
+-      lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
++      lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
+       return 1;
+ out:
+       stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+       stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;
+-      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
++      lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+       return 0;
+ }
+ static int
+-lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
++lpfc_rcv_padisc(struct lpfc_hba * phba,
++              struct lpfc_nodelist * ndlp,
+               struct lpfc_iocbq *cmdiocb)
+ {
+-      struct Scsi_Host   *shost = lpfc_shost_from_vport(vport);
+       struct lpfc_dmabuf *pcmd;
+       struct serv_parm *sp;
+       struct lpfc_name *pnn, *ppn;
+@@ -447,11 +412,12 @@
+       }
+       icmd = &cmdiocb->iocb;
+-      if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) {
++      if ((icmd->ulpStatus == 0) &&
++          (lpfc_check_adisc(phba, ndlp, pnn, ppn))) {
+               if (cmd == ELS_CMD_ADISC) {
+-                      lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp);
++                      lpfc_els_rsp_adisc_acc(phba, cmdiocb, ndlp);
+               } else {
+-                      lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp,
++                      lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp,
+                               NULL, 0);
+               }
+               return 1;
+@@ -461,57 +427,55 @@
+       stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+       stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
+       stat.un.b.vendorUnique = 0;
+-      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
++      lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+       /* 1 sec timeout */
+       mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+-      spin_lock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag |= NLP_DELAY_TMO;
+-      spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+       ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
+       ndlp->nlp_prev_state = ndlp->nlp_state;
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+       return 0;
+ }
+ static int
+-lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-            struct lpfc_iocbq *cmdiocb, uint32_t els_cmd)
++lpfc_rcv_logo(struct lpfc_hba * phba,
++                    struct lpfc_nodelist * ndlp,
++                    struct lpfc_iocbq *cmdiocb,
++                    uint32_t els_cmd)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+-      /* Put ndlp in NPR state with 1 sec timeout for plogi, ACC logo */
++      /* Put ndlp on NPR list with 1 sec timeout for plogi, ACC logo */
+       /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
+        * PLOGIs during LOGO storms from a device.
+        */
+-      spin_lock_irq(shost->host_lock);
+       ndlp->nlp_flag |= NLP_LOGO_ACC;
+-      spin_unlock_irq(shost->host_lock);
+       if (els_cmd == ELS_CMD_PRLO)
+-              lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
++              lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
+       else
+-              lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
++              lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+       if (!(ndlp->nlp_type & NLP_FABRIC) ||
+               (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
+               /* Only try to re-login if this is NOT a Fabric Node */
+               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
+-              spin_lock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
+               ndlp->nlp_flag |= NLP_DELAY_TMO;
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+               ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
+               ndlp->nlp_prev_state = ndlp->nlp_state;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+       } else {
+               ndlp->nlp_prev_state = ndlp->nlp_state;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
+       }
+-      spin_lock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+-      spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+       /* The driver has to wait until the ACC completes before it continues
+        * processing the LOGO.  The action will resume in
+        * lpfc_cmpl_els_logo_acc routine. Since part of processing includes an
+@@ -521,7 +485,8 @@
+ }
+ static void
+-lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
++lpfc_rcv_prli(struct lpfc_hba * phba,
++                    struct lpfc_nodelist * ndlp,
+                     struct lpfc_iocbq *cmdiocb)
+ {
+       struct lpfc_dmabuf *pcmd;
+@@ -536,7 +501,8 @@
+       ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
+       ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
+-      if (npr->prliType == PRLI_FCP_TYPE) {
++      if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) &&
++          (npr->prliType == PRLI_FCP_TYPE)) {
+               if (npr->initiatorFunc)
+                       ndlp->nlp_type |= NLP_FCP_INITIATOR;
+               if (npr->targetFunc)
+@@ -551,42 +517,36 @@
+                       roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+               if (ndlp->nlp_type & NLP_FCP_TARGET)
+                       roles |= FC_RPORT_ROLE_FCP_TARGET;
+-
+-              lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
+-                      "rport rolechg:   role:x%x did:x%x flg:x%x",
+-                      roles, ndlp->nlp_DID, ndlp->nlp_flag);
+-
+               fc_remote_port_rolechg(rport, roles);
+       }
+ }
+ static uint32_t
+-lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
++lpfc_disc_set_adisc(struct lpfc_hba * phba,
++                    struct lpfc_nodelist * ndlp)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+-
+       /* Check config parameter use-adisc or FCP-2 */
+-      if ((phba->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
+-          ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
+-              spin_lock_irq(shost->host_lock);
++      if ((phba->cfg_use_adisc == 0) &&
++              !(phba->fc_flag & FC_RSCN_MODE)) {
++              if (!(ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE))
++                      return 0;
 +      }
-+      return err;
-+}
-+
-+/*
-+ * Parse mount options.  See the manual page for usage instructions.
-+ *
-+ * Returns the dentry object of the lower-level (hidden) directory;
-+ * We want to mount our stackable file system on top of that hidden directory.
-+ */
-+static struct unionfs_dentry_info *unionfs_parse_options(
-+                                      struct super_block *sb,
-+                                      char *options)
-+{
-+      struct unionfs_dentry_info *hidden_root_info;
-+      char *optname;
-+      int err = 0;
-+      int bindex;
-+      int dirsfound = 0;
-+
-+      /* allocate private data area */
-+      err = -ENOMEM;
-+      hidden_root_info =
-+              kzalloc(sizeof(struct unionfs_dentry_info), GFP_KERNEL);
-+      if (!hidden_root_info)
-+              goto out_error;
-+      hidden_root_info->bstart = -1;
-+      hidden_root_info->bend = -1;
-+      hidden_root_info->bopaque = -1;
-+
-+      while ((optname = strsep(&options, ",")) != NULL) {
-+              char *optarg;
-+              char *endptr;
-+              int intval;
-+
-+              if (!optname || !*optname)
-+                      continue;
-+
-+              optarg = strchr(optname, '=');
-+              if (optarg)
-+                      *optarg++ = '\0';
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag |= NLP_NPR_ADISC;
+-              spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+       return 1;
+-      }
+-      ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+-      lpfc_unreg_rpi(vport, ndlp);
+-      return 0;
+ }
+ static uint32_t
+-lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                void *arg, uint32_t evt)
++lpfc_disc_illegal(struct lpfc_hba * phba,
++                 struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY,
+-                      "%d (%d):0253 Illegal State Transition: node x%x "
+-                      "event x%x, state x%x Data: x%x x%x\n",
+-                      vport->phba->brd_no, vport->vpi,
++      lpfc_printf_log(phba,
++                      KERN_ERR,
++                      LOG_DISCOVERY,
++                      "%d:0253 Illegal State Transition: node x%x event x%x, "
++                      "state x%x Data: x%x x%x\n",
++                      phba->brd_no,
+                       ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
+                       ndlp->nlp_flag);
+       return ndlp->nlp_state;
+@@ -595,161 +555,150 @@
+ /* Start of Discovery State Machine routines */
+ static uint32_t
+-lpfc_rcv_plogi_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                         void *arg, uint32_t evt)
++lpfc_rcv_plogi_unused_node(struct lpfc_hba * phba,
++                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+       struct lpfc_iocbq *cmdiocb;
+       cmdiocb = (struct lpfc_iocbq *) arg;
+-      if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
++      if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
+               ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
+               return ndlp->nlp_state;
+       }
+-      lpfc_drop_node(vport, ndlp);
++      lpfc_drop_node(phba, ndlp);
+       return NLP_STE_FREED_NODE;
+ }
+ static uint32_t
+-lpfc_rcv_els_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                       void *arg, uint32_t evt)
++lpfc_rcv_els_unused_node(struct lpfc_hba * phba,
++                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      lpfc_issue_els_logo(vport, ndlp, 0);
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
++      lpfc_issue_els_logo(phba, ndlp, 0);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
++lpfc_rcv_logo_unused_node(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq     *cmdiocb;
 +
-+              /*
-+               * All of our options take an argument now. Insert ones that
-+               * don't, above this check.
-+               */
-+              if (!optarg) {
-+                      printk("unionfs: %s requires an argument.\n", optname);
-+                      err = -EINVAL;
-+                      goto out_error;
-+              }
++      cmdiocb = (struct lpfc_iocbq *) arg;
+-      spin_lock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag |= NLP_LOGO_ACC;
+-      spin_unlock_irq(shost->host_lock);
+-      lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
++      spin_unlock_irq(phba->host->host_lock);
++      lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                         void *arg, uint32_t evt)
++lpfc_cmpl_logo_unused_node(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      lpfc_drop_node(vport, ndlp);
++      lpfc_drop_node(phba, ndlp);
+       return NLP_STE_FREED_NODE;
+ }
+ static uint32_t
+-lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                         void *arg, uint32_t evt)
++lpfc_device_rm_unused_node(struct lpfc_hba * phba,
++                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      lpfc_drop_node(vport, ndlp);
++      lpfc_drop_node(phba, ndlp);
+       return NLP_STE_FREED_NODE;
+ }
+ static uint32_t
+-lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
++lpfc_rcv_plogi_plogi_issue(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
+                          void *arg, uint32_t evt)
+ {
+-      struct lpfc_hba   *phba = vport->phba;
+       struct lpfc_iocbq *cmdiocb = arg;
+-      struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
+-      uint32_t *lp = (uint32_t *) pcmd->virt;
+-      struct serv_parm *sp = (struct serv_parm *) (lp + 1);
++      struct lpfc_dmabuf *pcmd;
++      struct serv_parm *sp;
++      uint32_t *lp;
+       struct ls_rjt stat;
+       int port_cmp;
++      pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
++      lp = (uint32_t *) pcmd->virt;
++      sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
 +
-+              if (!strcmp("dirs", optname)) {
-+                      if (++dirsfound > 1) {
-+                              printk(KERN_WARNING
-+                                     "unionfs: multiple dirs specified\n");
-+                              err = -EINVAL;
-+                              goto out_error;
-+                      }
-+                      err = parse_dirs_option(sb, hidden_root_info, optarg);
-+                      if (err)
-+                              goto out_error;
-+                      continue;
-+              }
+       memset(&stat, 0, sizeof (struct ls_rjt));
+       /* For a PLOGI, we only accept if our portname is less
+        * than the remote portname.
+        */
+       phba->fc_stat.elsLogiCol++;
+-      port_cmp = memcmp(&vport->fc_portname, &sp->portName,
+-                        sizeof(struct lpfc_name));
++      port_cmp = memcmp(&phba->fc_portname, &sp->portName,
++                        sizeof (struct lpfc_name));
+       if (port_cmp >= 0) {
+               /* Reject this request because the remote node will accept
+                  ours */
+               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+               stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
+-              lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+-                      NULL);
++              lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+       } else {
+-              lpfc_rcv_plogi(vport, ndlp, cmdiocb);
+-      } /* If our portname was less */
++              lpfc_rcv_plogi(phba, ndlp, cmdiocb);
++      } /* if our portname was less */
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_prli_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
++lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
+-      struct ls_rjt     stat;
+-
+-      memset(&stat, 0, sizeof (struct ls_rjt));
+-      stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
+-      stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
+-      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
+-      return ndlp->nlp_state;
+-}
++      struct lpfc_iocbq     *cmdiocb;
+-static uint32_t
+-lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
+-{
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      cmdiocb = (struct lpfc_iocbq *) arg;
+       /* software abort outstanding PLOGI */
+-      lpfc_els_abort(vport->phba, ndlp);
++      lpfc_els_abort(phba, ndlp);
+-      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
++      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                       void *arg, uint32_t evt)
++lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba   *phba = vport->phba;
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq     *cmdiocb;
 +
-+              /* All of these options require an integer argument. */
-+              intval = simple_strtoul(optarg, &endptr, 0);
-+              if (*endptr) {
-+                      printk(KERN_WARNING
-+                             "unionfs: invalid %s option '%s'\n",
-+                             optname, optarg);
-+                      err = -EINVAL;
-+                      goto out_error;
-+              }
++      cmdiocb = (struct lpfc_iocbq *) arg;
+       /* software abort outstanding PLOGI */
+       lpfc_els_abort(phba, ndlp);
+       if (evt == NLP_EVT_RCV_LOGO) {
+-              lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
++              lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+       } else {
+-              lpfc_issue_els_logo(vport, ndlp, 0);
++              lpfc_issue_els_logo(phba, ndlp, 0);
+       }
+-      /* Put ndlp in npr state set plogi timer for 1 sec */
++      /* Put ndlp in npr list set plogi timer for 1 sec */
+       mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
+-      spin_lock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag |= NLP_DELAY_TMO;
+-      spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+       ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
+       ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
+-                          struct lpfc_nodelist *ndlp,
+-                          void *arg,
++lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
+                           uint32_t evt)
+ {
+-      struct lpfc_hba    *phba = vport->phba;
+       struct lpfc_iocbq *cmdiocb, *rspiocb;
+       struct lpfc_dmabuf *pcmd, *prsp, *mp;
+       uint32_t *lp;
+@@ -772,26 +721,31 @@
+       pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
+-      prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
+-
++      prsp = list_get_first(&pcmd->list,
++                            struct lpfc_dmabuf,
++                            list);
+       lp = (uint32_t *) prsp->virt;
 +
-+              err = -EINVAL;
-+              printk(KERN_WARNING
-+                     "unionfs: unrecognized option '%s'\n", optname);
-+              goto out_error;
+       sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
+-      if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3))
++      if (!lpfc_check_sparm(phba, ndlp, sp, CLASS3))
+               goto out;
+       /* PLOGI chkparm OK */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (%d):0121 PLOGI chkparm OK "
++      lpfc_printf_log(phba,
++                      KERN_INFO,
++                      LOG_ELS,
++                      "%d:0121 PLOGI chkparm OK "
+                       "Data: x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi,
++                      phba->brd_no,
+                       ndlp->nlp_DID, ndlp->nlp_state,
+                       ndlp->nlp_flag, ndlp->nlp_rpi);
+-      if (phba->cfg_fcp_class == 2 && (sp->cls2.classValid))
++      if ((phba->cfg_fcp_class == 2) &&
++          (sp->cls2.classValid)) {
+               ndlp->nlp_fcp_info |= CLASS2;
+-      else
++      } else {
+               ndlp->nlp_fcp_info |= CLASS3;
+-
 +      }
-+      if (dirsfound != 1) {
-+              printk(KERN_WARNING "unionfs: dirs option required\n");
-+              err = -EINVAL;
-+              goto out_error;
+       ndlp->nlp_class_sup = 0;
+       if (sp->cls1.classValid)
+               ndlp->nlp_class_sup |= FC_COS_CLASS1;
+@@ -802,23 +756,16 @@
+       if (sp->cls4.classValid)
+               ndlp->nlp_class_sup |= FC_COS_CLASS4;
+       ndlp->nlp_maxframe =
+-              ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
++              ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
++              sp->cmn.bbRcvSizeLsb;
+-      mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (!mbox) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                      "%d (%d):0133 PLOGI: no memory for reg_login "
+-                      "Data: x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi,
+-                      ndlp->nlp_DID, ndlp->nlp_state,
+-                      ndlp->nlp_flag, ndlp->nlp_rpi);
++      if (!(mbox = mempool_alloc(phba->mbox_mem_pool,
++                                 GFP_KERNEL)))
+               goto out;
+-      }
+-
+-      lpfc_unreg_rpi(vport, ndlp);
+-      if (lpfc_reg_login(phba, vport->vpi, irsp->un.elsreq64.remoteID,
+-                         (uint8_t *) sp, mbox, 0) == 0) {
++      lpfc_unreg_rpi(phba, ndlp);
++      if (lpfc_reg_login(phba, irsp->un.elsreq64.remoteID, (uint8_t *) sp,
++                         mbox, 0) == 0) {
+               switch (ndlp->nlp_DID) {
+               case NameServer_DID:
+                       mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login;
+@@ -830,104 +777,68 @@
+                       mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
+               }
+               mbox->context2 = lpfc_nlp_get(ndlp);
+-              mbox->vport = vport;
+               if (lpfc_sli_issue_mbox(phba, mbox,
+                                       (MBX_NOWAIT | MBX_STOP_IOCB))
+                   != MBX_NOT_FINISHED) {
+-                      lpfc_nlp_set_state(vport, ndlp,
+-                                         NLP_STE_REG_LOGIN_ISSUE);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
+                       return ndlp->nlp_state;
+               }
+               lpfc_nlp_put(ndlp);
+-              mp = (struct lpfc_dmabuf *) mbox->context1;
++              mp = (struct lpfc_dmabuf *)mbox->context1;
+               lpfc_mbuf_free(phba, mp->virt, mp->phys);
+               kfree(mp);
+               mempool_free(mbox, phba->mbox_mem_pool);
+-
+-              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                      "%d (%d):0134 PLOGI: cannot issue reg_login "
+-                      "Data: x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi,
+-                      ndlp->nlp_DID, ndlp->nlp_state,
+-                      ndlp->nlp_flag, ndlp->nlp_rpi);
+       } else {
+               mempool_free(mbox, phba->mbox_mem_pool);
+-
+-              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                      "%d (%d):0135 PLOGI: cannot format reg_login "
+-                      "Data: x%x x%x x%x x%x\n",
+-                      phba->brd_no, vport->vpi,
+-                      ndlp->nlp_DID, ndlp->nlp_state,
+-                      ndlp->nlp_flag, ndlp->nlp_rpi);
+       }
+-out:
+-      if (ndlp->nlp_DID == NameServer_DID) {
+-              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-              lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                      "%d (%d):0261 Cannot Register NameServer login\n",
+-                      phba->brd_no, vport->vpi);
+-      }
+-
++ out:
+       /* Free this node since the driver cannot login or has the wrong
+          sparm */
+-      lpfc_drop_node(vport, ndlp);
++      lpfc_drop_node(phba, ndlp);
+       return NLP_STE_FREED_NODE;
+ }
+ static uint32_t
+-lpfc_device_rm_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                         void *arg, uint32_t evt)
++lpfc_device_rm_plogi_issue(struct lpfc_hba * phba,
++                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+-      if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+-              spin_lock_irq(shost->host_lock);
++      if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+-              spin_unlock_irq(shost->host_lock);
+               return ndlp->nlp_state;
+-      } else {
 +      }
-+      goto out;
-+
-+out_error:
-+      if (hidden_root_info && hidden_root_info->lower_paths) {
-+              for (bindex = hidden_root_info->bstart;
-+                   bindex >= 0 && bindex <= hidden_root_info->bend;
-+                   bindex++) {
-+                      struct dentry *d;
-+                      struct vfsmount *m;
-+
-+                      d = hidden_root_info->lower_paths[bindex].dentry;
-+                      m = hidden_root_info->lower_paths[bindex].mnt;
-+
-+                      dput(d);
-+                      /* initializing: can't use unionfs_mntput here */
-+                      mntput(m);
-+              }
++      else {
+               /* software abort outstanding PLOGI */
+-              lpfc_els_abort(vport->phba, ndlp);
++              lpfc_els_abort(phba, ndlp);
+-              lpfc_drop_node(vport, ndlp);
++              lpfc_drop_node(phba, ndlp);
+               return NLP_STE_FREED_NODE;
+       }
+ }
+ static uint32_t
+-lpfc_device_recov_plogi_issue(struct lpfc_vport *vport,
+-                            struct lpfc_nodelist *ndlp,
+-                            void *arg,
++lpfc_device_recov_plogi_issue(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
+                           uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+-
+-      /* Don't do anything that will mess up processing of the
+-       * previous RSCN.
+-       */
+-      if (vport->fc_flag & FC_RSCN_DEFERRED)
+-              return ndlp->nlp_state;
+-
+       /* software abort outstanding PLOGI */
+       lpfc_els_abort(phba, ndlp);
+       ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+-      spin_lock_irq(shost->host_lock);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
+-      spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                         void *arg, uint32_t evt)
++lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct lpfc_hba   *phba = vport->phba;
+       struct lpfc_iocbq *cmdiocb;
+       /* software abort outstanding ADISC */
+@@ -935,31 +846,34 @@
+       cmdiocb = (struct lpfc_iocbq *) arg;
+-      if (lpfc_rcv_plogi(vport, ndlp, cmdiocb))
++      if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
+               return ndlp->nlp_state;
+-
 +      }
+       ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
+-      lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
++      lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_prli_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
++lpfc_rcv_prli_adisc_issue(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
+-      lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
++      cmdiocb = (struct lpfc_iocbq *) arg;
 +
-+      kfree(hidden_root_info->lower_paths);
-+      kfree(hidden_root_info);
-+
-+      kfree(UNIONFS_SB(sb)->data);
-+      UNIONFS_SB(sb)->data = NULL;
++      lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_logo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
++lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct lpfc_hba *phba = vport->phba;
+       struct lpfc_iocbq *cmdiocb;
+       cmdiocb = (struct lpfc_iocbq *) arg;
+@@ -967,43 +881,42 @@
+       /* software abort outstanding ADISC */
+       lpfc_els_abort(phba, ndlp);
+-      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
++      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_padisc_adisc_issue(struct lpfc_vport *vport,
+-                          struct lpfc_nodelist *ndlp,
+-                          void *arg, uint32_t evt)
++lpfc_rcv_padisc_adisc_issue(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+       struct lpfc_iocbq *cmdiocb;
+       cmdiocb = (struct lpfc_iocbq *) arg;
+-      lpfc_rcv_padisc(vport, ndlp, cmdiocb);
++      lpfc_rcv_padisc(phba, ndlp, cmdiocb);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_prlo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
++lpfc_rcv_prlo_adisc_issue(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+       struct lpfc_iocbq *cmdiocb;
+       cmdiocb = (struct lpfc_iocbq *) arg;
+       /* Treat like rcv logo */
+-      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
++      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
+-                          struct lpfc_nodelist *ndlp,
+-                          void *arg, uint32_t evt)
++lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba   *phba = vport->phba;
+       struct lpfc_iocbq *cmdiocb, *rspiocb;
+       IOCB_t *irsp;
+       ADISC *ap;
+@@ -1015,112 +928,101 @@
+       irsp = &rspiocb->iocb;
+       if ((irsp->ulpStatus) ||
+-          (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) {
++              (!lpfc_check_adisc(phba, ndlp, &ap->nodeName, &ap->portName))) {
+               /* 1 sec timeout */
+               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+-              spin_lock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
+               ndlp->nlp_flag |= NLP_DELAY_TMO;
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+               ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
+-              memset(&ndlp->nlp_nodename, 0, sizeof(struct lpfc_name));
+-              memset(&ndlp->nlp_portname, 0, sizeof(struct lpfc_name));
++              memset(&ndlp->nlp_nodename, 0, sizeof (struct lpfc_name));
++              memset(&ndlp->nlp_portname, 0, sizeof (struct lpfc_name));
+               ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+-              lpfc_unreg_rpi(vport, ndlp);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
++              lpfc_unreg_rpi(phba, ndlp);
+               return ndlp->nlp_state;
+       }
+       if (ndlp->nlp_type & NLP_FCP_TARGET) {
+               ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE);
+       } else {
+               ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+       }
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_device_rm_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                         void *arg, uint32_t evt)
++lpfc_device_rm_adisc_issue(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+-      if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+-              spin_lock_irq(shost->host_lock);
++      if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+-              spin_unlock_irq(shost->host_lock);
+               return ndlp->nlp_state;
+-      } else {
++      }
++      else {
+               /* software abort outstanding ADISC */
+-              lpfc_els_abort(vport->phba, ndlp);
++              lpfc_els_abort(phba, ndlp);
+-              lpfc_drop_node(vport, ndlp);
++              lpfc_drop_node(phba, ndlp);
+               return NLP_STE_FREED_NODE;
+       }
+ }
+ static uint32_t
+-lpfc_device_recov_adisc_issue(struct lpfc_vport *vport,
+-                            struct lpfc_nodelist *ndlp,
+-                            void *arg,
++lpfc_device_recov_adisc_issue(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
+                           uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+-
+-      /* Don't do anything that will mess up processing of the
+-       * previous RSCN.
+-       */
+-      if (vport->fc_flag & FC_RSCN_DEFERRED)
+-              return ndlp->nlp_state;
+-
+       /* software abort outstanding ADISC */
+       lpfc_els_abort(phba, ndlp);
+       ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+-      spin_lock_irq(shost->host_lock);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
+-      spin_unlock_irq(shost->host_lock);
+-      lpfc_disc_set_adisc(vport, ndlp);
++      ndlp->nlp_flag |= NLP_NPR_ADISC;
++      spin_unlock_irq(phba->host->host_lock);
 +
-+      hidden_root_info = ERR_PTR(err);
-+out:
-+      return hidden_root_info;
-+}
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_plogi_reglogin_issue(struct lpfc_vport *vport,
+-                            struct lpfc_nodelist *ndlp,
+-                            void *arg,
++lpfc_rcv_plogi_reglogin_issue(struct lpfc_hba * phba,
++                            struct lpfc_nodelist * ndlp, void *arg,
+                             uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
 +
-+/*
-+ * our custom d_alloc_root work-alike
-+ *
-+ * we can't use d_alloc_root if we want to use our own interpose function
-+ * unchanged, so we simply call our own "fake" d_alloc_root
-+ */
-+static struct dentry *unionfs_d_alloc_root(struct super_block *sb)
-+{
-+      struct dentry *ret = NULL;
++      cmdiocb = (struct lpfc_iocbq *) arg;
+-      lpfc_rcv_plogi(vport, ndlp, cmdiocb);
++      lpfc_rcv_plogi(phba, ndlp, cmdiocb);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_prli_reglogin_issue(struct lpfc_vport *vport,
+-                           struct lpfc_nodelist *ndlp,
+-                           void *arg,
++lpfc_rcv_prli_reglogin_issue(struct lpfc_hba * phba,
++                           struct lpfc_nodelist * ndlp, void *arg,
+                            uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
+-      lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
++      cmdiocb = (struct lpfc_iocbq *) arg;
 +
-+      if (sb) {
-+              static const struct qstr name = {.name = "/",.len = 1 };
++      lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,
+-                           struct lpfc_nodelist *ndlp,
+-                           void *arg,
++lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
++                           struct lpfc_nodelist * ndlp, void *arg,
+                            uint32_t evt)
+ {
+-      struct lpfc_hba   *phba = vport->phba;
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
+       LPFC_MBOXQ_t      *mb;
+       LPFC_MBOXQ_t      *nextmb;
+       struct lpfc_dmabuf *mp;
+@@ -1131,13 +1033,12 @@
+       if ((mb = phba->sli.mbox_active)) {
+               if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
+                  (ndlp == (struct lpfc_nodelist *) mb->context2)) {
+-                      lpfc_nlp_put(ndlp);
+                       mb->context2 = NULL;
+                       mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+               }
+       }
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
+               if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
+                  (ndlp == (struct lpfc_nodelist *) mb->context2)) {
+@@ -1146,61 +1047,61 @@
+                               lpfc_mbuf_free(phba, mp->virt, mp->phys);
+                               kfree(mp);
+                       }
+-                      lpfc_nlp_put(ndlp);
+                       list_del(&mb->list);
+                       mempool_free(mb, phba->mbox_mem_pool);
+               }
+       }
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+-      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
++      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_padisc_reglogin_issue(struct lpfc_vport *vport,
+-                             struct lpfc_nodelist *ndlp,
+-                             void *arg,
++lpfc_rcv_padisc_reglogin_issue(struct lpfc_hba * phba,
++                             struct lpfc_nodelist * ndlp, void *arg,
+                              uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
 +
-+              ret = d_alloc(NULL, &name);
-+              if (ret) {
-+                      ret->d_op = &unionfs_dops;
-+                      ret->d_sb = sb;
-+                      ret->d_parent = ret;
-+              }
++      cmdiocb = (struct lpfc_iocbq *) arg;
+-      lpfc_rcv_padisc(vport, ndlp, cmdiocb);
++      lpfc_rcv_padisc(phba, ndlp, cmdiocb);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport,
+-                           struct lpfc_nodelist *ndlp,
+-                           void *arg,
++lpfc_rcv_prlo_reglogin_issue(struct lpfc_hba * phba,
++                           struct lpfc_nodelist * ndlp, void *arg,
+                            uint32_t evt)
+ {
+       struct lpfc_iocbq *cmdiocb;
+       cmdiocb = (struct lpfc_iocbq *) arg;
+-      lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
++      lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,
+-                                struct lpfc_nodelist *ndlp,
+-                                void *arg,
+-                                uint32_t evt)
++lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
++                                struct lpfc_nodelist * ndlp,
++                                void *arg, uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+-      LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
+-      MAILBOX_t *mb = &pmb->mb;
+-      uint32_t did  = mb->un.varWords[1];
++      LPFC_MBOXQ_t *pmb;
++      MAILBOX_t *mb;
++      uint32_t did;
++      pmb = (LPFC_MBOXQ_t *) arg;
++      mb = &pmb->mb;
++      did = mb->un.varWords[1];
+       if (mb->mbxStatus) {
+               /* RegLogin failed */
+-              lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+-                              "%d (%d):0246 RegLogin failed Data: x%x x%x "
+-                              "x%x\n",
+-                              phba->brd_no, vport->vpi,
+-                              did, mb->mbxStatus, vport->port_state);
++              lpfc_printf_log(phba,
++                              KERN_ERR,
++                              LOG_DISCOVERY,
++                              "%d:0246 RegLogin failed Data: x%x x%x x%x\n",
++                              phba->brd_no,
++                              did, mb->mbxStatus, phba->hba_state);
+               /*
+                * If RegLogin failed due to lack of HBA resources do not
+@@ -1208,20 +1109,20 @@
+                */
+               if (mb->mbxStatus == MBXERR_RPI_FULL) {
+                       ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
+                       return ndlp->nlp_state;
+               }
+-              /* Put ndlp in npr state set plogi timer for 1 sec */
++              /* Put ndlp in npr list set plogi timer for 1 sec */
+               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
+-              spin_lock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
+               ndlp->nlp_flag |= NLP_DELAY_TMO;
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+               ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
+-              lpfc_issue_els_logo(vport, ndlp, 0);
++              lpfc_issue_els_logo(phba, ndlp, 0);
+               ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+               return ndlp->nlp_state;
+       }
+@@ -1230,99 +1131,91 @@
+       /* Only if we are not a fabric nport do we issue PRLI */
+       if (!(ndlp->nlp_type & NLP_FABRIC)) {
+               ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
+-              lpfc_issue_els_prli(vport, ndlp, 0);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
++              lpfc_issue_els_prli(phba, ndlp, 0);
+       } else {
+               ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+       }
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_device_rm_reglogin_issue(struct lpfc_vport *vport,
+-                            struct lpfc_nodelist *ndlp,
+-                            void *arg,
++lpfc_device_rm_reglogin_issue(struct lpfc_hba * phba,
++                            struct lpfc_nodelist * ndlp, void *arg,
+                             uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+-      if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+-              spin_lock_irq(shost->host_lock);
++      if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+-              spin_unlock_irq(shost->host_lock);
+               return ndlp->nlp_state;
+-      } else {
+-              lpfc_drop_node(vport, ndlp);
 +      }
-+      return ret;
-+}
-+
-+/*
-+ * There is no need to lock the unionfs_super_info's rwsem as there is no
-+ * way anyone can have a reference to the superblock at this point in time.
-+ */
-+static int unionfs_read_super(struct super_block *sb, void *raw_data,
-+                            int silent)
-+{
-+      int err = 0;
++      else {
++              lpfc_drop_node(phba, ndlp);
+               return NLP_STE_FREED_NODE;
+       }
+ }
+ static uint32_t
+-lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport,
+-                               struct lpfc_nodelist *ndlp,
+-                               void *arg,
++lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba,
++                             struct lpfc_nodelist * ndlp, void *arg,
+                              uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+-      /* Don't do anything that will mess up processing of the
+-       * previous RSCN.
+-       */
+-      if (vport->fc_flag & FC_RSCN_DEFERRED)
+-              return ndlp->nlp_state;
+-
+       ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+-      spin_lock_irq(shost->host_lock);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
+-      spin_unlock_irq(shost->host_lock);
+-      lpfc_disc_set_adisc(vport, ndlp);
++      spin_unlock_irq(phba->host->host_lock);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_plogi_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
++lpfc_rcv_plogi_prli_issue(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+       struct lpfc_iocbq *cmdiocb;
+       cmdiocb = (struct lpfc_iocbq *) arg;
+-      lpfc_rcv_plogi(vport, ndlp, cmdiocb);
++      lpfc_rcv_plogi(phba, ndlp, cmdiocb);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                       void *arg, uint32_t evt)
++lpfc_rcv_prli_prli_issue(struct lpfc_hba * phba,
++                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
+-      lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
++      cmdiocb = (struct lpfc_iocbq *) arg;
 +
-+      struct unionfs_dentry_info *hidden_root_info = NULL;
-+      int bindex, bstart, bend;
++      lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_logo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                       void *arg, uint32_t evt)
++lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba,
++                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
 +
-+      if (!raw_data) {
-+              printk(KERN_WARNING
-+                     "unionfs: read_super: missing data argument\n");
-+              err = -EINVAL;
-+              goto out;
-+      }
++      cmdiocb = (struct lpfc_iocbq *) arg;
+       /* Software abort outstanding PRLI before sending acc */
+-      lpfc_els_abort(vport->phba, ndlp);
++      lpfc_els_abort(phba, ndlp);
+-      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
++      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_padisc_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                         void *arg, uint32_t evt)
++lpfc_rcv_padisc_prli_issue(struct lpfc_hba * phba,
++                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
+-      lpfc_rcv_padisc(vport, ndlp, cmdiocb);
++      cmdiocb = (struct lpfc_iocbq *) arg;
 +
-+      /* Allocate superblock private data */
-+      sb->s_fs_info = kzalloc(sizeof(struct unionfs_sb_info), GFP_KERNEL);
-+      if (!UNIONFS_SB(sb)) {
-+              printk(KERN_WARNING "unionfs: read_super: out of memory\n");
-+              err = -ENOMEM;
-+              goto out;
++      lpfc_rcv_padisc(phba, ndlp, cmdiocb);
+       return ndlp->nlp_state;
+ }
+@@ -1332,22 +1225,21 @@
+  * NEXT STATE = PRLI_ISSUE
+  */
+ static uint32_t
+-lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                       void *arg, uint32_t evt)
++lpfc_rcv_prlo_prli_issue(struct lpfc_hba * phba,
++                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
+-      lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
++      cmdiocb = (struct lpfc_iocbq *) arg;
++      lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
++lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+       struct lpfc_iocbq *cmdiocb, *rspiocb;
+-      struct lpfc_hba   *phba = vport->phba;
+       IOCB_t *irsp;
+       PRLI *npr;
+@@ -1357,12 +1249,8 @@
+       irsp = &rspiocb->iocb;
+       if (irsp->ulpStatus) {
+-              if ((vport->port_type == LPFC_NPIV_PORT) &&
+-                      phba->cfg_vport_restrict_login) {
+-                      goto out;
+-              }
+               ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
+               return ndlp->nlp_state;
+       }
+@@ -1378,25 +1266,9 @@
+               if (npr->Retry)
+                       ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
+       }
+-      if (!(ndlp->nlp_type & NLP_FCP_TARGET) &&
+-          (vport->port_type == LPFC_NPIV_PORT) &&
+-           phba->cfg_vport_restrict_login) {
+-out:
+-              spin_lock_irq(shost->host_lock);
+-              ndlp->nlp_flag |= NLP_TARGET_REMOVE;
+-              spin_unlock_irq(shost->host_lock);
+-              lpfc_issue_els_logo(vport, ndlp, 0);
+-
+-              ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
+-              return ndlp->nlp_state;
+-      }
+       ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
+-      if (ndlp->nlp_type & NLP_FCP_TARGET)
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
+-      else
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE);
+       return ndlp->nlp_state;
+ }
+@@ -1417,23 +1289,19 @@
+   *    on plogi list so it can be freed when LOGO completes.
+   *
+   */
+-
+ static uint32_t
+-lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
++lpfc_device_rm_prli_issue(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+-      if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+-              spin_lock_irq(shost->host_lock);
++      if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+-              spin_unlock_irq(shost->host_lock);
+               return ndlp->nlp_state;
+-      } else {
 +      }
++      else {
+               /* software abort outstanding PLOGI */
+-              lpfc_els_abort(vport->phba, ndlp);
++              lpfc_els_abort(phba, ndlp);
+-              lpfc_drop_node(vport, ndlp);
++              lpfc_drop_node(phba, ndlp);
+               return NLP_STE_FREED_NODE;
+       }
+ }
+@@ -1456,251 +1324,261 @@
+   *    outstanding PRLI command, then free the node entry.
+   */
+ static uint32_t
+-lpfc_device_recov_prli_issue(struct lpfc_vport *vport,
+-                           struct lpfc_nodelist *ndlp,
+-                           void *arg,
+-                           uint32_t evt)
++lpfc_device_recov_prli_issue(struct lpfc_hba * phba,
++                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_hba  *phba = vport->phba;
+-
+-      /* Don't do anything that will mess up processing of the
+-       * previous RSCN.
+-       */
+-      if (vport->fc_flag & FC_RSCN_DEFERRED)
+-              return ndlp->nlp_state;
+-
+       /* software abort outstanding PRLI */
+       lpfc_els_abort(phba, ndlp);
+       ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+-      spin_lock_irq(shost->host_lock);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
+-      spin_unlock_irq(shost->host_lock);
+-      lpfc_disc_set_adisc(vport, ndlp);
++      spin_unlock_irq(phba->host->host_lock);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_plogi_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
++lpfc_rcv_plogi_unmap_node(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
 +
-+      UNIONFS_SB(sb)->bend = -1;
-+      atomic_set(&UNIONFS_SB(sb)->generation, 1);
-+      init_rwsem(&UNIONFS_SB(sb)->rwsem);
-+      UNIONFS_SB(sb)->high_branch_id = -1; /* -1 == invalid branch ID */
++      cmdiocb = (struct lpfc_iocbq *) arg;
+-      lpfc_rcv_plogi(vport, ndlp, cmdiocb);
++      lpfc_rcv_plogi(phba, ndlp, cmdiocb);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_prli_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                       void *arg, uint32_t evt)
++lpfc_rcv_prli_unmap_node(struct lpfc_hba * phba,
++                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
+-      lpfc_rcv_prli(vport, ndlp, cmdiocb);
+-      lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
++      cmdiocb = (struct lpfc_iocbq *) arg;
 +
-+      hidden_root_info = unionfs_parse_options(sb, raw_data);
-+      if (IS_ERR(hidden_root_info)) {
-+              printk(KERN_WARNING
-+                     "unionfs: read_super: error while parsing options "
-+                     "(err = %ld)\n", PTR_ERR(hidden_root_info));
-+              err = PTR_ERR(hidden_root_info);
-+              hidden_root_info = NULL;
-+              goto out_free;
-+      }
-+      if (hidden_root_info->bstart == -1) {
-+              err = -ENOENT;
-+              goto out_free;
-+      }
++      lpfc_rcv_prli(phba, ndlp, cmdiocb);
++      lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_logo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                       void *arg, uint32_t evt)
++lpfc_rcv_logo_unmap_node(struct lpfc_hba * phba,
++                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
 +
-+      /* set the hidden superblock field of upper superblock */
-+      bstart = hidden_root_info->bstart;
-+      BUG_ON(bstart != 0);
-+      sbend(sb) = bend = hidden_root_info->bend;
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              struct dentry *d = hidden_root_info->lower_paths[bindex].dentry;
-+              unionfs_set_lower_super_idx(sb, bindex, d->d_sb);
-+      }
++      cmdiocb = (struct lpfc_iocbq *) arg;
+-      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
++      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_padisc_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                         void *arg, uint32_t evt)
++lpfc_rcv_padisc_unmap_node(struct lpfc_hba * phba,
++                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
 +
-+      /* max Bytes is the maximum bytes from highest priority branch */
-+      sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
++      cmdiocb = (struct lpfc_iocbq *) arg;
+-      lpfc_rcv_padisc(vport, ndlp, cmdiocb);
++      lpfc_rcv_padisc(phba, ndlp, cmdiocb);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                       void *arg, uint32_t evt)
++lpfc_rcv_prlo_unmap_node(struct lpfc_hba * phba,
++                       struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
+-      lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
++      cmdiocb = (struct lpfc_iocbq *) arg;
 +
-+      sb->s_op = &unionfs_sops;
++      lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_device_recov_unmap_node(struct lpfc_vport *vport,
+-                           struct lpfc_nodelist *ndlp,
+-                           void *arg,
+-                           uint32_t evt)
++lpfc_device_recov_unmap_node(struct lpfc_hba * phba,
++                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+       ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+-      spin_lock_irq(shost->host_lock);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
+-      spin_unlock_irq(shost->host_lock);
+-      lpfc_disc_set_adisc(vport, ndlp);
++      lpfc_disc_set_adisc(phba, ndlp);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_plogi_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                         void *arg, uint32_t evt)
++lpfc_rcv_plogi_mapped_node(struct lpfc_hba * phba,
++                         struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
+-      lpfc_rcv_plogi(vport, ndlp, cmdiocb);
++      cmdiocb = (struct lpfc_iocbq *) arg;
 +
-+      /* See comment next to the definition of unionfs_d_alloc_root */
-+      sb->s_root = unionfs_d_alloc_root(sb);
-+      if (!sb->s_root) {
-+              err = -ENOMEM;
-+              goto out_dput;
-+      }
++      lpfc_rcv_plogi(phba, ndlp, cmdiocb);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_prli_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
++lpfc_rcv_prli_mapped_node(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
 +
-+      /* link the upper and lower dentries */
-+      sb->s_root->d_fsdata = NULL;
-+      if ((err = new_dentry_private_data(sb->s_root)))
-+              goto out_freedpd;
++      cmdiocb = (struct lpfc_iocbq *) arg;
+-      lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
++      lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_logo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
++lpfc_rcv_logo_mapped_node(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
+-      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
++      cmdiocb = (struct lpfc_iocbq *) arg;
 +
-+      /* Set the hidden dentries for s_root */
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              struct dentry *d;
-+              struct vfsmount *m;
++      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_padisc_mapped_node(struct lpfc_vport *vport,
+-                          struct lpfc_nodelist *ndlp,
+-                          void *arg, uint32_t evt)
++lpfc_rcv_padisc_mapped_node(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
+-      lpfc_rcv_padisc(vport, ndlp, cmdiocb);
++      cmdiocb = (struct lpfc_iocbq *) arg;
 +
-+              d = hidden_root_info->lower_paths[bindex].dentry;
-+              m = hidden_root_info->lower_paths[bindex].mnt;
++      lpfc_rcv_padisc(phba, ndlp, cmdiocb);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                        void *arg, uint32_t evt)
++lpfc_rcv_prlo_mapped_node(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
 +
-+              unionfs_set_lower_dentry_idx(sb->s_root, bindex, d);
-+              unionfs_set_lower_mnt_idx(sb->s_root, bindex, m);
-+      }
-+      set_dbstart(sb->s_root, bstart);
-+      set_dbend(sb->s_root, bend);
++      cmdiocb = (struct lpfc_iocbq *) arg;
+       /* flush the target */
++      spin_lock_irq(phba->host->host_lock);
+       lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
+                              ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
++      spin_unlock_irq(phba->host->host_lock);
+       /* Treat like rcv logo */
+-      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
++      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_device_recov_mapped_node(struct lpfc_vport *vport,
+-                            struct lpfc_nodelist *ndlp,
+-                            void *arg,
++lpfc_device_recov_mapped_node(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
+                           uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+       ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE;
+-      lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+-      spin_lock_irq(shost->host_lock);
++      lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
+-      spin_unlock_irq(shost->host_lock);
+-      lpfc_disc_set_adisc(vport, ndlp);
++      spin_unlock_irq(phba->host->host_lock);
++      lpfc_disc_set_adisc(phba, ndlp);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                      void *arg, uint32_t evt)
++lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_iocbq *cmdiocb  = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq *cmdiocb;
 +
-+      /* Set the generation number to one, since this is for the mount. */
-+      atomic_set(&UNIONFS_D(sb->s_root)->generation, 1);
++      cmdiocb = (struct lpfc_iocbq *) arg;
+       /* Ignore PLOGI if we have an outstanding LOGO */
+-      if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC)) {
++      if (ndlp->nlp_flag & NLP_LOGO_SND) {
+               return ndlp->nlp_state;
+       }
+-      if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
+-              spin_lock_irq(shost->host_lock);
++      if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
++              spin_lock_irq(phba->host->host_lock);
+               ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+               return ndlp->nlp_state;
+       }
+       /* send PLOGI immediately, move to PLOGI issue state */
+       if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
+               ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
+-              lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+-              lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
++              lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
++              lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+       }
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                     void *arg, uint32_t evt)
++lpfc_rcv_prli_npr_node(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq     *cmdiocb;
+       struct ls_rjt          stat;
++      cmdiocb = (struct lpfc_iocbq *) arg;
 +
-+      /* call interpose to create the upper level inode */
-+      err = unionfs_interpose(sb->s_root, sb, 0);
-+      unionfs_unlock_dentry(sb->s_root);
-+      if (!err)
-+              goto out;
-+      /* else fall through */
+       memset(&stat, 0, sizeof (struct ls_rjt));
+       stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+       stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
+-      lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
++      lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
+       if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
+               if (ndlp->nlp_flag & NLP_NPR_ADISC) {
+-                      spin_lock_irq(shost->host_lock);
++                      spin_lock_irq(phba->host->host_lock);
+                       ndlp->nlp_flag &= ~NLP_NPR_ADISC;
++                      spin_unlock_irq(phba->host->host_lock);
+                       ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
+-                      spin_unlock_irq(shost->host_lock);
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
+-                      lpfc_issue_els_adisc(vport, ndlp, 0);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
++                      lpfc_issue_els_adisc(phba, ndlp, 0);
+               } else {
+                       ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+-                      lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
++                      lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+               }
+       }
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_logo_npr_node(struct lpfc_vport *vport,  struct lpfc_nodelist *ndlp,
+-                     void *arg, uint32_t evt)
++lpfc_rcv_logo_npr_node(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq     *cmdiocb;
 +
-+out_freedpd:
-+      if (UNIONFS_D(sb->s_root)) {
-+              kfree(UNIONFS_D(sb->s_root)->lower_paths);
-+              free_dentry_private_data(sb->s_root);
-+      }
-+      dput(sb->s_root);
++      cmdiocb = (struct lpfc_iocbq *) arg;
+-      lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
++      lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                       void *arg, uint32_t evt)
++lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq     *cmdiocb;
 +
-+out_dput:
-+      if (hidden_root_info && !IS_ERR(hidden_root_info)) {
-+              for (bindex = hidden_root_info->bstart;
-+                   bindex <= hidden_root_info->bend; bindex++) {
-+                      struct dentry *d;
-+                      struct vfsmount *m;
++      cmdiocb = (struct lpfc_iocbq *) arg;
+-      lpfc_rcv_padisc(vport, ndlp, cmdiocb);
++      lpfc_rcv_padisc(phba, ndlp, cmdiocb);
+       /*
+        * Do not start discovery if discovery is about to start
+@@ -1708,52 +1586,53 @@
+        * here will affect the counting of discovery threads.
+        */
+       if (!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
+-          !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
++              !(ndlp->nlp_flag & NLP_NPR_2B_DISC)){
+               if (ndlp->nlp_flag & NLP_NPR_ADISC) {
+-                      ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+                       ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
+-                      lpfc_issue_els_adisc(vport, ndlp, 0);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
++                      lpfc_issue_els_adisc(phba, ndlp, 0);
+               } else {
+                       ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
+-                      lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+-                      lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
++                      lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
++                      lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
+               }
+       }
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                     void *arg, uint32_t evt)
++lpfc_rcv_prlo_npr_node(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-      struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
++      struct lpfc_iocbq     *cmdiocb;
+-      spin_lock_irq(shost->host_lock);
++      cmdiocb = (struct lpfc_iocbq *) arg;
 +
-+                      d = hidden_root_info->lower_paths[bindex].dentry;
-+                      m = hidden_root_info->lower_paths[bindex].mnt;
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag |= NLP_LOGO_ACC;
+-      spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+-      lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
++      lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+-      if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) {
++      if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
+               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
+-              spin_lock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
+               ndlp->nlp_flag |= NLP_DELAY_TMO;
+               ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+               ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
+       } else {
+-              spin_lock_irq(shost->host_lock);
++              spin_lock_irq(phba->host->host_lock);
+               ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+-              spin_unlock_irq(shost->host_lock);
++              spin_unlock_irq(phba->host->host_lock);
+       }
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                       void *arg, uint32_t evt)
++lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+       struct lpfc_iocbq *cmdiocb, *rspiocb;
+       IOCB_t *irsp;
+@@ -1763,15 +1642,15 @@
+       irsp = &rspiocb->iocb;
+       if (irsp->ulpStatus) {
+-              lpfc_drop_node(vport, ndlp);
++              lpfc_drop_node(phba, ndlp);
+               return NLP_STE_FREED_NODE;
+       }
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_cmpl_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                      void *arg, uint32_t evt)
++lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba,
++                        struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+       struct lpfc_iocbq *cmdiocb, *rspiocb;
+       IOCB_t *irsp;
+@@ -1781,24 +1660,25 @@
+       irsp = &rspiocb->iocb;
+       if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
+-              lpfc_drop_node(vport, ndlp);
++              lpfc_drop_node(phba, ndlp);
+               return NLP_STE_FREED_NODE;
+       }
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_cmpl_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                      void *arg, uint32_t evt)
++lpfc_cmpl_logo_npr_node(struct lpfc_hba * phba,
++              struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      lpfc_unreg_rpi(vport, ndlp);
++      lpfc_unreg_rpi(phba, ndlp);
+       /* This routine does nothing, just return the current state */
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_cmpl_adisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                       void *arg, uint32_t evt)
++lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+       struct lpfc_iocbq *cmdiocb, *rspiocb;
+       IOCB_t *irsp;
+@@ -1808,25 +1688,28 @@
+       irsp = &rspiocb->iocb;
+       if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
+-              lpfc_drop_node(vport, ndlp);
++              lpfc_drop_node(phba, ndlp);
+               return NLP_STE_FREED_NODE;
+       }
+       return ndlp->nlp_state;
+ }
+ static uint32_t
+-lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport,
+-                          struct lpfc_nodelist *ndlp,
+-                          void *arg, uint32_t evt)
++lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
+-      MAILBOX_t    *mb = &pmb->mb;
++      LPFC_MBOXQ_t *pmb;
++      MAILBOX_t *mb;
 +
-+                      dput(d);
-+                      /* initializing: can't use unionfs_mntput here */
-+                      mntput(m);
++      pmb = (LPFC_MBOXQ_t *) arg;
++      mb = &pmb->mb;
+       if (!mb->mbxStatus)
+               ndlp->nlp_rpi = mb->un.varWords[0];
+       else {
+               if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
+-                      lpfc_drop_node(vport, ndlp);
++                      lpfc_drop_node(phba, ndlp);
+                       return NLP_STE_FREED_NODE;
+               }
+       }
+@@ -1834,38 +1717,28 @@
+ }
+ static uint32_t
+-lpfc_device_rm_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                      void *arg, uint32_t evt)
++lpfc_device_rm_npr_node(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+       if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+-              spin_lock_irq(shost->host_lock);
+               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+-              spin_unlock_irq(shost->host_lock);
+               return ndlp->nlp_state;
+       }
+-      lpfc_drop_node(vport, ndlp);
++      lpfc_drop_node(phba, ndlp);
+       return NLP_STE_FREED_NODE;
+ }
+ static uint32_t
+-lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                         void *arg, uint32_t evt)
++lpfc_device_recov_npr_node(struct lpfc_hba * phba,
++                          struct lpfc_nodelist * ndlp, void *arg,
++                          uint32_t evt)
+ {
+-      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-
+-      /* Don't do anything that will mess up processing of the
+-       * previous RSCN.
+-       */
+-      if (vport->fc_flag & FC_RSCN_DEFERRED)
+-              return ndlp->nlp_state;
+-
+-      spin_lock_irq(shost->host_lock);
++      spin_lock_irq(phba->host->host_lock);
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
+-      spin_unlock_irq(shost->host_lock);
++      spin_unlock_irq(phba->host->host_lock);
+       if (ndlp->nlp_flag & NLP_DELAY_TMO) {
+-              lpfc_cancel_retry_delay_tmo(vport, ndlp);
++              lpfc_cancel_retry_delay_tmo(phba, ndlp);
+       }
+       return ndlp->nlp_state;
+ }
+@@ -1928,7 +1801,7 @@
+  */
+ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT])
+-     (struct lpfc_vport *, struct lpfc_nodelist *, void *, uint32_t) = {
++     (struct lpfc_hba *, struct lpfc_nodelist *, void *, uint32_t) = {
+       /* Action routine                  Event       Current State  */
+       lpfc_rcv_plogi_unused_node,     /* RCV_PLOGI   UNUSED_NODE    */
+       lpfc_rcv_els_unused_node,       /* RCV_PRLI        */
+@@ -1945,7 +1818,7 @@
+       lpfc_disc_illegal,              /* DEVICE_RECOVERY */
+       lpfc_rcv_plogi_plogi_issue,     /* RCV_PLOGI   PLOGI_ISSUE    */
+-      lpfc_rcv_prli_plogi_issue,      /* RCV_PRLI        */
++      lpfc_rcv_els_plogi_issue,       /* RCV_PRLI        */
+       lpfc_rcv_logo_plogi_issue,      /* RCV_LOGO        */
+       lpfc_rcv_els_plogi_issue,       /* RCV_ADISC       */
+       lpfc_rcv_els_plogi_issue,       /* RCV_PDISC       */
+@@ -2044,40 +1917,34 @@
+ };
+ int
+-lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+-                      void *arg, uint32_t evt)
++lpfc_disc_state_machine(struct lpfc_hba * phba,
++                      struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
+ {
+-      struct lpfc_hba  *phba = vport->phba;
+       uint32_t cur_state, rc;
+-      uint32_t(*func) (struct lpfc_vport *, struct lpfc_nodelist *, void *,
++      uint32_t(*func) (struct lpfc_hba *, struct lpfc_nodelist *, void *,
+                        uint32_t);
+       lpfc_nlp_get(ndlp);
+       cur_state = ndlp->nlp_state;
+       /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0211 DSM in event x%x on NPort x%x in "
+-                      "state %d Data: x%x\n",
+-                      phba->brd_no, vport->vpi,
++      lpfc_printf_log(phba,
++                      KERN_INFO,
++                      LOG_DISCOVERY,
++                      "%d:0211 DSM in event x%x on NPort x%x in state %d "
++                      "Data: x%x\n",
++                      phba->brd_no,
+                       evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag);
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
+-               "DSM in:          evt:%d ste:%d did:x%x",
+-              evt, cur_state, ndlp->nlp_DID);
+-
+       func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt];
+-      rc = (func) (vport, ndlp, arg, evt);
++      rc = (func) (phba, ndlp, arg, evt);
+       /* DSM out state <rc> on NPort <nlp_DID> */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+-                      "%d (%d):0212 DSM out state %d on NPort x%x "
+-                      "Data: x%x\n",
+-                      phba->brd_no, vport->vpi,
+-                      rc, ndlp->nlp_DID, ndlp->nlp_flag);
+-
+-      lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
+-               "DSM out:         ste:%d did:x%x flg:x%x",
++      lpfc_printf_log(phba,
++                     KERN_INFO,
++                     LOG_DISCOVERY,
++                     "%d:0212 DSM out state %d on NPort x%x Data: x%x\n",
++                     phba->brd_no,
+                      rc, ndlp->nlp_DID, ndlp->nlp_flag);
+       lpfc_nlp_put(ndlp);
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_scsi.c linux-2.6.22-570/drivers/scsi/lpfc/lpfc_scsi.c
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_scsi.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_scsi.c     2007-07-08 19:32:17.000000000 -0400
+@@ -37,158 +37,10 @@
+ #include "lpfc.h"
+ #include "lpfc_logmsg.h"
+ #include "lpfc_crtn.h"
+-#include "lpfc_vport.h"
+ #define LPFC_RESET_WAIT  2
+ #define LPFC_ABORT_WAIT  2
+-/*
+- * This function is called with no lock held when there is a resource
+- * error in driver or in firmware.
+- */
+-void
+-lpfc_adjust_queue_depth(struct lpfc_hba *phba)
+-{
+-      unsigned long flags;
+-
+-      spin_lock_irqsave(&phba->hbalock, flags);
+-      atomic_inc(&phba->num_rsrc_err);
+-      phba->last_rsrc_error_time = jiffies;
+-
+-      if ((phba->last_ramp_down_time + QUEUE_RAMP_DOWN_INTERVAL) > jiffies) {
+-              spin_unlock_irqrestore(&phba->hbalock, flags);
+-              return;
+-      }
+-
+-      phba->last_ramp_down_time = jiffies;
+-
+-      spin_unlock_irqrestore(&phba->hbalock, flags);
+-
+-      spin_lock_irqsave(&phba->pport->work_port_lock, flags);
+-      if ((phba->pport->work_port_events &
+-              WORKER_RAMP_DOWN_QUEUE) == 0) {
+-              phba->pport->work_port_events |= WORKER_RAMP_DOWN_QUEUE;
+-      }
+-      spin_unlock_irqrestore(&phba->pport->work_port_lock, flags);
+-
+-      spin_lock_irqsave(&phba->hbalock, flags);
+-      if (phba->work_wait)
+-              wake_up(phba->work_wait);
+-      spin_unlock_irqrestore(&phba->hbalock, flags);
+-
+-      return;
+-}
+-
+-/*
+- * This function is called with no lock held when there is a successful
+- * SCSI command completion.
+- */
+-static inline void
+-lpfc_rampup_queue_depth(struct lpfc_hba *phba,
+-                      struct scsi_device *sdev)
+-{
+-      unsigned long flags;
+-      atomic_inc(&phba->num_cmd_success);
+-
+-      if (phba->cfg_lun_queue_depth <= sdev->queue_depth)
+-              return;
+-
+-      spin_lock_irqsave(&phba->hbalock, flags);
+-      if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) ||
+-       ((phba->last_rsrc_error_time + QUEUE_RAMP_UP_INTERVAL ) > jiffies)) {
+-              spin_unlock_irqrestore(&phba->hbalock, flags);
+-              return;
+-      }
+-
+-      phba->last_ramp_up_time = jiffies;
+-      spin_unlock_irqrestore(&phba->hbalock, flags);
+-
+-      spin_lock_irqsave(&phba->pport->work_port_lock, flags);
+-      if ((phba->pport->work_port_events &
+-              WORKER_RAMP_UP_QUEUE) == 0) {
+-              phba->pport->work_port_events |= WORKER_RAMP_UP_QUEUE;
+-      }
+-      spin_unlock_irqrestore(&phba->pport->work_port_lock, flags);
+-
+-      spin_lock_irqsave(&phba->hbalock, flags);
+-      if (phba->work_wait)
+-              wake_up(phba->work_wait);
+-      spin_unlock_irqrestore(&phba->hbalock, flags);
+-}
+-
+-void
+-lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
+-{
+-      struct lpfc_vport *vport;
+-      struct Scsi_Host  *host;
+-      struct scsi_device *sdev;
+-      unsigned long new_queue_depth;
+-      unsigned long num_rsrc_err, num_cmd_success;
+-
+-      num_rsrc_err = atomic_read(&phba->num_rsrc_err);
+-      num_cmd_success = atomic_read(&phba->num_cmd_success);
+-
+-      spin_lock_irq(&phba->hbalock);
+-      list_for_each_entry(vport, &phba->port_list, listentry) {
+-              host = lpfc_shost_from_vport(vport);
+-              if (!scsi_host_get(host))
+-                      continue;
+-
+-              spin_unlock_irq(&phba->hbalock);
+-
+-              shost_for_each_device(sdev, host) {
+-                      new_queue_depth = sdev->queue_depth * num_rsrc_err /
+-                      (num_rsrc_err + num_cmd_success);
+-                      if (!new_queue_depth)
+-                              new_queue_depth = sdev->queue_depth - 1;
+-                      else
+-                              new_queue_depth =
+-                                      sdev->queue_depth - new_queue_depth;
+-
+-                      if (sdev->ordered_tags)
+-                              scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
+-                                      new_queue_depth);
+-                      else
+-                              scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG,
+-                                      new_queue_depth);
+-              }
+-              spin_lock_irq(&phba->hbalock);
+-              scsi_host_put(host);
+-      }
+-      spin_unlock_irq(&phba->hbalock);
+-      atomic_set(&phba->num_rsrc_err, 0);
+-      atomic_set(&phba->num_cmd_success, 0);
+-}
+-
+-void
+-lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
+-{
+-      struct lpfc_vport *vport;
+-      struct Scsi_Host  *host;
+-      struct scsi_device *sdev;
+-
+-      spin_lock_irq(&phba->hbalock);
+-      list_for_each_entry(vport, &phba->port_list, listentry) {
+-              host = lpfc_shost_from_vport(vport);
+-              if (!scsi_host_get(host))
+-                      continue;
+-
+-              spin_unlock_irq(&phba->hbalock);
+-              shost_for_each_device(sdev, host) {
+-                      if (sdev->ordered_tags)
+-                              scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
+-                                      sdev->queue_depth+1);
+-                      else
+-                              scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG,
+-                                      sdev->queue_depth+1);
+-              }
+-              spin_lock_irq(&phba->hbalock);
+-              scsi_host_put(host);
+-      }
+-      spin_unlock_irq(&phba->hbalock);
+-      atomic_set(&phba->num_rsrc_err, 0);
+-      atomic_set(&phba->num_cmd_success, 0);
+-}
+ /*
+  * This routine allocates a scsi buffer, which contains all the necessary
+@@ -199,9 +51,8 @@
+  * and the BPL BDE is setup in the IOCB.
+  */
+ static struct lpfc_scsi_buf *
+-lpfc_new_scsi_buf(struct lpfc_vport *vport)
++lpfc_new_scsi_buf(struct lpfc_hba * phba)
+ {
+-      struct lpfc_hba *phba = vport->phba;
+       struct lpfc_scsi_buf *psb;
+       struct ulp_bde64 *bpl;
+       IOCB_t *iocb;
+@@ -212,6 +63,7 @@
+       if (!psb)
+               return NULL;
+       memset(psb, 0, sizeof (struct lpfc_scsi_buf));
++      psb->scsi_hba = phba;
+       /*
+        * Get memory from the pci pool to map the virt space to pci bus space
+@@ -303,7 +155,7 @@
+ }
+ static void
+-lpfc_release_scsi_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
++lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
+ {
+       unsigned long iflag = 0;
+@@ -314,7 +166,7 @@
+ }
+ static int
+-lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
++lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
+ {
+       struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
+       struct scatterlist *sgel = NULL;
+@@ -323,7 +175,8 @@
+       IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
+       dma_addr_t physaddr;
+       uint32_t i, num_bde = 0;
+-      int nseg, datadir = scsi_cmnd->sc_data_direction;
++      int datadir = scsi_cmnd->sc_data_direction;
++      int dma_error;
+       /*
+        * There are three possibilities here - use scatter-gather segment, use
+@@ -332,22 +185,26 @@
+        * data bde entry.
+        */
+       bpl += 2;
+-      nseg = scsi_dma_map(scsi_cmnd);
+-      if (nseg > 0) {
++      if (scsi_cmnd->use_sg) {
+               /*
+                * The driver stores the segment count returned from pci_map_sg
+                * because this a count of dma-mappings used to map the use_sg
+                * pages.  They are not guaranteed to be the same for those
+                * architectures that implement an IOMMU.
+                */
++              sgel = (struct scatterlist *)scsi_cmnd->request_buffer;
++              lpfc_cmd->seg_cnt = dma_map_sg(&phba->pcidev->dev, sgel,
++                                              scsi_cmnd->use_sg, datadir);
++              if (lpfc_cmd->seg_cnt == 0)
++                      return 1;
+-              lpfc_cmd->seg_cnt = nseg;
+               if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
+                       printk(KERN_ERR "%s: Too many sg segments from "
+                              "dma_map_sg.  Config %d, seg_cnt %d",
+                              __FUNCTION__, phba->cfg_sg_seg_cnt,
+                              lpfc_cmd->seg_cnt);
+-                      scsi_dma_unmap(scsi_cmnd);
++                      dma_unmap_sg(&phba->pcidev->dev, sgel,
++                                   lpfc_cmd->seg_cnt, datadir);
+                       return 1;
+               }
+@@ -357,7 +214,7 @@
+                * single scsi command.  Just run through the seg_cnt and format
+                * the bde's.
+                */
+-              scsi_for_each_sg(scsi_cmnd, sgel, nseg, i) {
++              for (i = 0; i < lpfc_cmd->seg_cnt; i++) {
+                       physaddr = sg_dma_address(sgel);
+                       bpl->addrLow = le32_to_cpu(putPaddrLow(physaddr));
+                       bpl->addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
+@@ -368,10 +225,35 @@
+                               bpl->tus.f.bdeFlags = BUFF_USE_RCV;
+                       bpl->tus.w = le32_to_cpu(bpl->tus.w);
+                       bpl++;
++                      sgel++;
+                       num_bde++;
+               }
+-      } else if (nseg < 0)
++      } else if (scsi_cmnd->request_buffer && scsi_cmnd->request_bufflen) {
++              physaddr = dma_map_single(&phba->pcidev->dev,
++                                        scsi_cmnd->request_buffer,
++                                        scsi_cmnd->request_bufflen,
++                                        datadir);
++              dma_error = dma_mapping_error(physaddr);
++              if (dma_error) {
++                      lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
++                              "%d:0718 Unable to dma_map_single "
++                              "request_buffer: x%x\n",
++                              phba->brd_no, dma_error);
+                       return 1;
 +              }
-+              kfree(hidden_root_info->lower_paths);
-+              kfree(hidden_root_info);
-+              hidden_root_info = NULL;
-+      }
 +
-+out_free:
-+      kfree(UNIONFS_SB(sb)->data);
-+      kfree(UNIONFS_SB(sb));
-+      sb->s_fs_info = NULL;
-+
-+out:
-+      if (hidden_root_info && !IS_ERR(hidden_root_info)) {
-+              kfree(hidden_root_info->lower_paths);
-+              kfree(hidden_root_info);
++              lpfc_cmd->nonsg_phys = physaddr;
++              bpl->addrLow = le32_to_cpu(putPaddrLow(physaddr));
++              bpl->addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
++              bpl->tus.f.bdeSize = scsi_cmnd->request_bufflen;
++              if (datadir == DMA_TO_DEVICE)
++                      bpl->tus.f.bdeFlags = 0;
++              else
++                      bpl->tus.f.bdeFlags = BUFF_USE_RCV;
++              bpl->tus.w = le32_to_cpu(bpl->tus.w);
++              num_bde = 1;
++              bpl++;
 +      }
-+      return err;
-+}
+       /*
+        * Finish initializing those IOCB fields that are dependent on the
+@@ -384,7 +266,7 @@
+               (num_bde * sizeof (struct ulp_bde64));
+       iocb_cmd->ulpBdeCount = 1;
+       iocb_cmd->ulpLe = 1;
+-      fcp_cmnd->fcpDl = be32_to_cpu(scsi_bufflen(scsi_cmnd));
++      fcp_cmnd->fcpDl = be32_to_cpu(scsi_cmnd->request_bufflen);
+       return 0;
+ }
+@@ -397,20 +279,26 @@
+        * a request buffer, but did not request use_sg.  There is a third
+        * case, but it does not require resource deallocation.
+        */
+-      if (psb->seg_cnt > 0)
+-              scsi_dma_unmap(psb->pCmd);
++      if ((psb->seg_cnt > 0) && (psb->pCmd->use_sg)) {
++              dma_unmap_sg(&phba->pcidev->dev, psb->pCmd->request_buffer,
++                              psb->seg_cnt, psb->pCmd->sc_data_direction);
++      } else {
++               if ((psb->nonsg_phys) && (psb->pCmd->request_bufflen)) {
++                      dma_unmap_single(&phba->pcidev->dev, psb->nonsg_phys,
++                                              psb->pCmd->request_bufflen,
++                                              psb->pCmd->sc_data_direction);
++               }
++      }
+ }
+ static void
+-lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
+-                  struct lpfc_iocbq *rsp_iocb)
++lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb)
+ {
+       struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
+       struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd;
+       struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
+-      struct lpfc_hba *phba = vport->phba;
++      struct lpfc_hba *phba = lpfc_cmd->scsi_hba;
+       uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm;
+-      uint32_t vpi = vport->vpi;
+       uint32_t resp_info = fcprsp->rspStatus2;
+       uint32_t scsi_status = fcprsp->rspStatus3;
+       uint32_t *lp;
+@@ -443,9 +331,9 @@
+               logit = LOG_FCP;
+       lpfc_printf_log(phba, KERN_WARNING, logit,
+-                      "%d (%d):0730 FCP command x%x failed: x%x SNS x%x x%x "
++                      "%d:0730 FCP command x%x failed: x%x SNS x%x x%x "
+                       "Data: x%x x%x x%x x%x x%x\n",
+-                      phba->brd_no, vpi, cmnd->cmnd[0], scsi_status,
++                      phba->brd_no, cmnd->cmnd[0], scsi_status,
+                       be32_to_cpu(*lp), be32_to_cpu(*(lp + 3)), resp_info,
+                       be32_to_cpu(fcprsp->rspResId),
+                       be32_to_cpu(fcprsp->rspSnsLen),
+@@ -461,16 +349,15 @@
+               }
+       }
+-      scsi_set_resid(cmnd, 0);
++      cmnd->resid = 0;
+       if (resp_info & RESID_UNDER) {
+-              scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId));
++              cmnd->resid = be32_to_cpu(fcprsp->rspResId);
+               lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+-                              "%d (%d):0716 FCP Read Underrun, expected %d, "
+-                              "residual %d Data: x%x x%x x%x\n",
+-                              phba->brd_no, vpi, be32_to_cpu(fcpcmd->fcpDl),
+-                              scsi_get_resid(cmnd), fcpi_parm, cmnd->cmnd[0],
+-                              cmnd->underflow);
++                              "%d:0716 FCP Read Underrun, expected %d, "
++                              "residual %d Data: x%x x%x x%x\n", phba->brd_no,
++                              be32_to_cpu(fcpcmd->fcpDl), cmnd->resid,
++                              fcpi_parm, cmnd->cmnd[0], cmnd->underflow);
+               /*
+                * If there is an under run check if under run reported by
+@@ -479,16 +366,15 @@
+                */
+               if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) &&
+                       fcpi_parm &&
+-                      (scsi_get_resid(cmnd) != fcpi_parm)) {
++                      (cmnd->resid != fcpi_parm)) {
+                       lpfc_printf_log(phba, KERN_WARNING,
+                               LOG_FCP | LOG_FCP_ERROR,
+-                                      "%d (%d):0735 FCP Read Check Error "
+-                                      "and Underrun Data: x%x x%x x%x x%x\n",
+-                                      phba->brd_no, vpi,
++                              "%d:0735 FCP Read Check Error and Underrun "
++                              "Data: x%x x%x x%x x%x\n", phba->brd_no,
+                               be32_to_cpu(fcpcmd->fcpDl),
+-                                      scsi_get_resid(cmnd), fcpi_parm,
+-                                      cmnd->cmnd[0]);
+-                      scsi_set_resid(cmnd, scsi_bufflen(cmnd));
++                              cmnd->resid,
++                              fcpi_parm, cmnd->cmnd[0]);
++                      cmnd->resid = cmnd->request_bufflen;
+                       host_status = DID_ERROR;
+               }
+               /*
+@@ -499,23 +385,22 @@
+                */
+               if (!(resp_info & SNS_LEN_VALID) &&
+                   (scsi_status == SAM_STAT_GOOD) &&
+-                  (scsi_bufflen(cmnd) - scsi_get_resid(cmnd)
+-                   < cmnd->underflow)) {
++                  (cmnd->request_bufflen - cmnd->resid) < cmnd->underflow) {
+                       lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+-                                      "%d (%d):0717 FCP command x%x residual "
++                                      "%d:0717 FCP command x%x residual "
+                                       "underrun converted to error "
+-                                      "Data: x%x x%x x%x\n",
+-                                      phba->brd_no, vpi, cmnd->cmnd[0],
+-                                      cmnd->request_bufflen,
+-                                      scsi_get_resid(cmnd), cmnd->underflow);
++                                      "Data: x%x x%x x%x\n", phba->brd_no,
++                                      cmnd->cmnd[0], cmnd->request_bufflen,
++                                      cmnd->resid, cmnd->underflow);
 +
-+static int unionfs_get_sb(struct file_system_type *fs_type,
-+                        int flags, const char *dev_name,
-+                        void *raw_data, struct vfsmount *mnt)
-+{
-+      return get_sb_nodev(fs_type, flags, raw_data, unionfs_read_super, mnt);
-+}
+                       host_status = DID_ERROR;
+               }
+       } else if (resp_info & RESID_OVER) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
+-                              "%d (%d):0720 FCP command x%x residual "
++                              "%d:0720 FCP command x%x residual "
+                               "overrun error. Data: x%x x%x \n",
+-                              phba->brd_no, vpi, cmnd->cmnd[0],
+-                              scsi_bufflen(cmnd), scsi_get_resid(cmnd));
++                              phba->brd_no, cmnd->cmnd[0],
++                              cmnd->request_bufflen, cmnd->resid);
+               host_status = DID_ERROR;
+       /*
+@@ -525,14 +410,13 @@
+       } else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm &&
+                       (cmnd->sc_data_direction == DMA_FROM_DEVICE)) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR,
+-                              "%d (%d):0734 FCP Read Check Error Data: "
+-                              "x%x x%x x%x x%x\n",
+-                              phba->brd_no, vpi,
++                      "%d:0734 FCP Read Check Error Data: "
++                      "x%x x%x x%x x%x\n", phba->brd_no,
+                       be32_to_cpu(fcpcmd->fcpDl),
+                       be32_to_cpu(fcprsp->rspResId),
+                       fcpi_parm, cmnd->cmnd[0]);
+               host_status = DID_ERROR;
+-              scsi_set_resid(cmnd, scsi_bufflen(cmnd));
++              cmnd->resid = cmnd->request_bufflen;
+       }
+  out:
+@@ -545,13 +429,9 @@
+ {
+       struct lpfc_scsi_buf *lpfc_cmd =
+               (struct lpfc_scsi_buf *) pIocbIn->context1;
+-      struct lpfc_vport      *vport = pIocbIn->vport;
+       struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
+       struct lpfc_nodelist *pnode = rdata->pnode;
+       struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
+-      uint32_t vpi = (lpfc_cmd->cur_iocbq.vport
+-                      ? lpfc_cmd->cur_iocbq.vport->vpi
+-                      : 0);
+       int result;
+       struct scsi_device *sdev, *tmp_sdev;
+       int depth = 0;
+@@ -567,31 +447,22 @@
+                       lpfc_cmd->status = IOSTAT_DEFAULT;
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
+-                              "%d (%d):0729 FCP cmd x%x failed <%d/%d> "
+-                              "status: x%x result: x%x Data: x%x x%x\n",
+-                              phba->brd_no, vpi, cmd->cmnd[0],
+-                              cmd->device ? cmd->device->id : 0xffff,
+-                              cmd->device ? cmd->device->lun : 0xffff,
+-                              lpfc_cmd->status, lpfc_cmd->result,
+-                              pIocbOut->iocb.ulpContext,
++                              "%d:0729 FCP cmd x%x failed <%d/%d> status: "
++                              "x%x result: x%x Data: x%x x%x\n",
++                              phba->brd_no, cmd->cmnd[0], cmd->device->id,
++                              cmd->device->lun, lpfc_cmd->status,
++                              lpfc_cmd->result, pIocbOut->iocb.ulpContext,
+                               lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
+               switch (lpfc_cmd->status) {
+               case IOSTAT_FCP_RSP_ERROR:
+                       /* Call FCP RSP handler to determine result */
+-                      lpfc_handle_fcp_err(vport, lpfc_cmd, pIocbOut);
++                      lpfc_handle_fcp_err(lpfc_cmd,pIocbOut);
+                       break;
+               case IOSTAT_NPORT_BSY:
+               case IOSTAT_FABRIC_BSY:
+                       cmd->result = ScsiResult(DID_BUS_BUSY, 0);
+                       break;
+-              case IOSTAT_LOCAL_REJECT:
+-                      if (lpfc_cmd->result == RJT_UNAVAIL_PERM ||
+-                          lpfc_cmd->result == IOERR_NO_RESOURCES ||
+-                          lpfc_cmd->result == RJT_LOGIN_REQUIRED) {
+-                              cmd->result = ScsiResult(DID_REQUEUE, 0);
+-                      break;
+-              } /* else: fall through */
+               default:
+                       cmd->result = ScsiResult(DID_ERROR, 0);
+                       break;
+@@ -608,12 +479,11 @@
+               uint32_t *lp = (uint32_t *)cmd->sense_buffer;
+               lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+-                              "%d (%d):0710 Iodone <%d/%d> cmd %p, error "
+-                              "x%x SNS x%x x%x Data: x%x x%x\n",
+-                              phba->brd_no, vpi, cmd->device->id,
++                              "%d:0710 Iodone <%d/%d> cmd %p, error x%x "
++                              "SNS x%x x%x Data: x%x x%x\n",
++                              phba->brd_no, cmd->device->id,
+                               cmd->device->lun, cmd, cmd->result,
+-                              *lp, *(lp + 3), cmd->retries,
+-                              scsi_get_resid(cmd));
++                              *lp, *(lp + 3), cmd->retries, cmd->resid);
+       }
+       result = cmd->result;
+@@ -626,10 +496,6 @@
+               return;
+       }
+-
+-      if (!result)
+-              lpfc_rampup_queue_depth(phba, sdev);
+-
+       if (!result && pnode != NULL &&
+          ((jiffies - pnode->last_ramp_up_time) >
+               LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
+@@ -678,9 +544,8 @@
+               if (depth) {
+                       lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
+-                                      "%d (%d):0711 detected queue full - "
+-                                      "lun queue depth  adjusted to %d.\n",
+-                                      phba->brd_no, vpi, depth);
++                              "%d:0711 detected queue full - lun queue depth "
++                              " adjusted to %d.\n", phba->brd_no, depth);
+               }
+       }
+@@ -688,10 +553,9 @@
+ }
+ static void
+-lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
++lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd,
+                       struct lpfc_nodelist *pnode)
+ {
+-      struct lpfc_hba *phba = vport->phba;
+       struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
+       struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
+       IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
+@@ -728,7 +592,22 @@
+        * bumping the bpl beyond the fcp_cmnd and fcp_rsp regions to the first
+        * data bde entry.
+        */
+-      if (scsi_sg_count(scsi_cmnd)) {
++      if (scsi_cmnd->use_sg) {
++              if (datadir == DMA_TO_DEVICE) {
++                      iocb_cmd->ulpCommand = CMD_FCP_IWRITE64_CR;
++                      iocb_cmd->un.fcpi.fcpi_parm = 0;
++                      iocb_cmd->ulpPU = 0;
++                      fcp_cmnd->fcpCntl3 = WRITE_DATA;
++                      phba->fc4OutputRequests++;
++              } else {
++                      iocb_cmd->ulpCommand = CMD_FCP_IREAD64_CR;
++                      iocb_cmd->ulpPU = PARM_READ_CHECK;
++                      iocb_cmd->un.fcpi.fcpi_parm =
++                              scsi_cmnd->request_bufflen;
++                      fcp_cmnd->fcpCntl3 = READ_DATA;
++                      phba->fc4InputRequests++;
++              }
++      } else if (scsi_cmnd->request_buffer && scsi_cmnd->request_bufflen) {
+               if (datadir == DMA_TO_DEVICE) {
+                       iocb_cmd->ulpCommand = CMD_FCP_IWRITE64_CR;
+                       iocb_cmd->un.fcpi.fcpi_parm = 0;
+@@ -738,7 +617,8 @@
+               } else {
+                       iocb_cmd->ulpCommand = CMD_FCP_IREAD64_CR;
+                       iocb_cmd->ulpPU = PARM_READ_CHECK;
+-                      iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd);
++                      iocb_cmd->un.fcpi.fcpi_parm =
++                              scsi_cmnd->request_bufflen;
+                       fcp_cmnd->fcpCntl3 = READ_DATA;
+                       phba->fc4InputRequests++;
+               }
+@@ -762,15 +642,15 @@
+       piocbq->context1  = lpfc_cmd;
+       piocbq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl;
+       piocbq->iocb.ulpTimeout = lpfc_cmd->timeout;
+-      piocbq->vport = vport;
+ }
+ static int
+-lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
++lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
+                            struct lpfc_scsi_buf *lpfc_cmd,
+                            unsigned int lun,
+                            uint8_t task_mgmt_cmd)
+ {
++      struct lpfc_sli *psli;
+       struct lpfc_iocbq *piocbq;
+       IOCB_t *piocb;
+       struct fcp_cmnd *fcp_cmnd;
+@@ -781,9 +661,8 @@
+               return 0;
+       }
++      psli = &phba->sli;
+       piocbq = &(lpfc_cmd->cur_iocbq);
+-      piocbq->vport = vport;
+-
+       piocb = &piocbq->iocb;
+       fcp_cmnd = lpfc_cmd->fcp_cmnd;
+@@ -809,7 +688,7 @@
+               piocb->ulpTimeout = lpfc_cmd->timeout;
+       }
+-      return 1;
++      return (1);
+ }
+ static void
+@@ -825,11 +704,10 @@
+ }
+ static int
+-lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport,
++lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
+                   unsigned  tgt_id, unsigned int lun,
+                   struct lpfc_rport_data *rdata)
+ {
+-      struct lpfc_hba   *phba = vport->phba;
+       struct lpfc_iocbq *iocbq;
+       struct lpfc_iocbq *iocbqrsp;
+       int ret;
+@@ -838,11 +716,12 @@
+               return FAILED;
+       lpfc_cmd->rdata = rdata;
+-      ret = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun,
++      ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, lun,
+                                          FCP_TARGET_RESET);
+       if (!ret)
+               return FAILED;
++      lpfc_cmd->scsi_hba = phba;
+       iocbq = &lpfc_cmd->cur_iocbq;
+       iocbqrsp = lpfc_sli_get_iocbq(phba);
+@@ -851,10 +730,10 @@
+       /* Issue Target Reset to TGT <num> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+-                      "%d (%d):0702 Issue Target Reset to TGT %d "
++                      "%d:0702 Issue Target Reset to TGT %d "
+                       "Data: x%x x%x\n",
+-                      phba->brd_no, vport->vpi, tgt_id,
+-                      rdata->pnode->nlp_rpi, rdata->pnode->nlp_flag);
++                      phba->brd_no, tgt_id, rdata->pnode->nlp_rpi,
++                      rdata->pnode->nlp_flag);
+       ret = lpfc_sli_issue_iocb_wait(phba,
+                                      &phba->sli.ring[phba->sli.fcp_ring],
+@@ -879,8 +758,7 @@
+ const char *
+ lpfc_info(struct Scsi_Host *host)
+ {
+-      struct lpfc_vport *vport = (struct lpfc_vport *) host->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba    *phba = (struct lpfc_hba *) host->hostdata;
+       int len;
+       static char  lpfcinfobuf[384];
+@@ -922,21 +800,25 @@
+ void lpfc_poll_timeout(unsigned long ptr)
+ {
+-      struct lpfc_hba *phba = (struct lpfc_hba *) ptr;
++      struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
++      unsigned long iflag;
 +
-+static struct file_system_type unionfs_fs_type = {
-+      .owner          = THIS_MODULE,
-+      .name           = "unionfs",
-+      .get_sb         = unionfs_get_sb,
-+      .kill_sb        = generic_shutdown_super,
-+      .fs_flags       = FS_REVAL_DOT,
-+};
++      spin_lock_irqsave(phba->host->host_lock, iflag);
+       if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+               lpfc_sli_poll_fcp_ring (phba);
+               if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+                       lpfc_poll_rearm_timer(phba);
+       }
 +
-+static int __init init_unionfs_fs(void)
-+{
-+      int err;
++      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+ }
+ static int
+ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
+ {
+-      struct Scsi_Host  *shost = cmnd->device->host;
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba =
++              (struct lpfc_hba *) cmnd->device->host->hostdata;
+       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_rport_data *rdata = cmnd->device->hostdata;
+       struct lpfc_nodelist *ndlp = rdata->pnode;
+@@ -958,14 +840,11 @@
+               cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
+               goto out_fail_command;
+       }
+-      lpfc_cmd = lpfc_get_scsi_buf(phba);
++      lpfc_cmd = lpfc_get_scsi_buf (phba);
+       if (lpfc_cmd == NULL) {
+-              lpfc_adjust_queue_depth(phba);
+-
+               lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+-                              "%d (%d):0707 driver's buffer pool is empty, "
+-                              "IO busied\n",
+-                              phba->brd_no, vport->vpi);
++                              "%d:0707 driver's buffer pool is empty, "
++                              "IO busied\n", phba->brd_no);
+               goto out_host_busy;
+       }
+@@ -983,7 +862,7 @@
+       if (err)
+               goto out_host_busy_free_buf;
+-      lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp);
++      lpfc_scsi_prep_cmnd(phba, lpfc_cmd, ndlp);
+       err = lpfc_sli_issue_iocb(phba, &phba->sli.ring[psli->fcp_ring],
+                               &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
+@@ -1029,8 +908,7 @@
+ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+ {
+       struct Scsi_Host *shost = cmnd->device->host;
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+       struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring];
+       struct lpfc_iocbq *iocb;
+       struct lpfc_iocbq *abtsiocb;
+@@ -1040,6 +918,8 @@
+       int ret = SUCCESS;
+       lpfc_block_error_handler(cmnd);
++      spin_lock_irq(shost->host_lock);
 +
-+      printk("Registering unionfs " UNIONFS_VERSION "\n");
+       lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
+       BUG_ON(!lpfc_cmd);
+@@ -1076,13 +956,12 @@
+       icmd->ulpLe = 1;
+       icmd->ulpClass = cmd->ulpClass;
+-      if (lpfc_is_link_up(phba))
++      if (phba->hba_state >= LPFC_LINK_UP)
+               icmd->ulpCommand = CMD_ABORT_XRI_CN;
+       else
+               icmd->ulpCommand = CMD_CLOSE_XRI_CN;
+       abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
+-      abtsiocb->vport = vport;
+       if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) == IOCB_ERROR) {
+               lpfc_sli_release_iocbq(phba, abtsiocb);
+               ret = FAILED;
+@@ -1098,7 +977,9 @@
+               if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+                       lpfc_sli_poll_fcp_ring (phba);
+-              schedule_timeout_uninterruptible(LPFC_ABORT_WAIT * HZ);
++              spin_unlock_irq(phba->host->host_lock);
++                      schedule_timeout_uninterruptible(LPFC_ABORT_WAIT*HZ);
++              spin_lock_irq(phba->host->host_lock);
+               if (++loop_count
+                   > (2 * phba->cfg_devloss_tmo)/LPFC_ABORT_WAIT)
+                       break;
+@@ -1107,21 +988,22 @@
+       if (lpfc_cmd->pCmd == cmnd) {
+               ret = FAILED;
+               lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+-                              "%d (%d):0748 abort handler timed out waiting "
+-                              "for abort to complete: ret %#x, ID %d, "
+-                              "LUN %d, snum %#lx\n",
+-                              phba->brd_no, vport->vpi, ret,
+-                              cmnd->device->id, cmnd->device->lun,
+-                              cmnd->serial_number);
++                              "%d:0748 abort handler timed out waiting for "
++                              "abort to complete: ret %#x, ID %d, LUN %d, "
++                              "snum %#lx\n",
++                              phba->brd_no,  ret, cmnd->device->id,
++                              cmnd->device->lun, cmnd->serial_number);
+       }
+  out:
+       lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
+-                      "%d (%d):0749 SCSI Layer I/O Abort Request "
++                      "%d:0749 SCSI Layer I/O Abort Request "
+                       "Status x%x ID %d LUN %d snum %#lx\n",
+-                      phba->brd_no, vport->vpi, ret, cmnd->device->id,
++                      phba->brd_no, ret, cmnd->device->id,
+                       cmnd->device->lun, cmnd->serial_number);
++      spin_unlock_irq(shost->host_lock);
 +
-+      if ((err = unionfs_init_filldir_cache()))
-+              goto out;
-+      if ((err = unionfs_init_inode_cache()))
-+              goto out;
-+      if ((err = unionfs_init_dentry_cache()))
-+              goto out;
-+      if ((err = init_sioq()))
-+              goto out;
-+      err = register_filesystem(&unionfs_fs_type);
-+out:
-+      if (err) {
-+              stop_sioq();
-+              unionfs_destroy_filldir_cache();
-+              unionfs_destroy_inode_cache();
-+              unionfs_destroy_dentry_cache();
+       return ret;
+ }
+@@ -1129,8 +1011,7 @@
+ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
+ {
+       struct Scsi_Host *shost = cmnd->device->host;
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+       struct lpfc_scsi_buf *lpfc_cmd;
+       struct lpfc_iocbq *iocbq, *iocbqrsp;
+       struct lpfc_rport_data *rdata = cmnd->device->hostdata;
+@@ -1141,26 +1022,28 @@
+       int cnt, loopcnt;
+       lpfc_block_error_handler(cmnd);
++      spin_lock_irq(shost->host_lock);
+       loopcnt = 0;
+       /*
+        * If target is not in a MAPPED state, delay the reset until
+        * target is rediscovered or devloss timeout expires.
+        */
+-      while (1) {
++      while ( 1 ) {
+               if (!pnode)
+                       goto out;
+               if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
++                      spin_unlock_irq(phba->host->host_lock);
+                       schedule_timeout_uninterruptible(msecs_to_jiffies(500));
++                      spin_lock_irq(phba->host->host_lock);
+                       loopcnt++;
+                       rdata = cmnd->device->hostdata;
+                       if (!rdata ||
+                               (loopcnt > ((phba->cfg_devloss_tmo * 2) + 1))) {
+                               lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+-                                              "%d (%d):0721 LUN Reset rport "
+-                                              "failure: cnt x%x rdata x%p\n",
+-                                              phba->brd_no, vport->vpi,
+-                                              loopcnt, rdata);
++                                      "%d:0721 LUN Reset rport failure:"
++                                      " cnt x%x rdata x%p\n",
++                                      phba->brd_no, loopcnt, rdata);
+                               goto out;
+                       }
+                       pnode = rdata->pnode;
+@@ -1171,14 +1054,15 @@
+                       break;
+       }
+-      lpfc_cmd = lpfc_get_scsi_buf(phba);
++      lpfc_cmd = lpfc_get_scsi_buf (phba);
+       if (lpfc_cmd == NULL)
+               goto out;
+       lpfc_cmd->timeout = 60;
++      lpfc_cmd->scsi_hba = phba;
+       lpfc_cmd->rdata = rdata;
+-      ret = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, cmnd->device->lun,
++      ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun,
+                                          FCP_TARGET_RESET);
+       if (!ret)
+               goto out_free_scsi_buf;
+@@ -1191,9 +1075,8 @@
+               goto out_free_scsi_buf;
+       lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+-                      "%d (%d):0703 Issue target reset to TGT %d LUN %d "
+-                      "rpi x%x nlp_flag x%x\n",
+-                      phba->brd_no, vport->vpi, cmnd->device->id,
++                      "%d:0703 Issue target reset to TGT %d LUN %d rpi x%x "
++                      "nlp_flag x%x\n", phba->brd_no, cmnd->device->id,
+                       cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
+       iocb_status = lpfc_sli_issue_iocb_wait(phba,
+@@ -1228,7 +1111,9 @@
+                                   0, LPFC_CTX_LUN);
+       loopcnt = 0;
+       while(cnt) {
++              spin_unlock_irq(phba->host->host_lock);
+               schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
++              spin_lock_irq(phba->host->host_lock);
+               if (++loopcnt
+                   > (2 * phba->cfg_devloss_tmo)/LPFC_RESET_WAIT)
+@@ -1242,9 +1127,8 @@
+       if (cnt) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+-                              "%d (%d):0719 device reset I/O flush failure: "
+-                              "cnt x%x\n",
+-                              phba->brd_no, vport->vpi, cnt);
++                      "%d:0719 device reset I/O flush failure: cnt x%x\n",
++                      phba->brd_no, cnt);
+               ret = FAILED;
+       }
+@@ -1253,12 +1137,13 @@
+               lpfc_release_scsi_buf(phba, lpfc_cmd);
+       }
+       lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+-                      "%d (%d):0713 SCSI layer issued device reset (%d, %d) "
++                      "%d:0713 SCSI layer issued device reset (%d, %d) "
+                       "return x%x status x%x result x%x\n",
+-                      phba->brd_no, vport->vpi, cmnd->device->id,
+-                      cmnd->device->lun, ret, cmd_status, cmd_result);
++                      phba->brd_no, cmnd->device->id, cmnd->device->lun,
++                      ret, cmd_status, cmd_result);
+ out:
++      spin_unlock_irq(shost->host_lock);
+       return ret;
+ }
+@@ -1266,8 +1151,7 @@
+ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
+ {
+       struct Scsi_Host *shost = cmnd->device->host;
+-      struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+       struct lpfc_nodelist *ndlp = NULL;
+       int match;
+       int ret = FAILED, i, err_count = 0;
+@@ -1275,6 +1159,7 @@
+       struct lpfc_scsi_buf * lpfc_cmd;
+       lpfc_block_error_handler(cmnd);
++      spin_lock_irq(shost->host_lock);
+       lpfc_cmd = lpfc_get_scsi_buf(phba);
+       if (lpfc_cmd == NULL)
+@@ -1282,6 +1167,7 @@
+       /* The lpfc_cmd storage is reused.  Set all loop invariants. */
+       lpfc_cmd->timeout = 60;
++      lpfc_cmd->scsi_hba = phba;
+       /*
+        * Since the driver manages a single bus device, reset all
+@@ -1291,8 +1177,7 @@
+       for (i = 0; i < LPFC_MAX_TARGET; i++) {
+               /* Search for mapped node by target ID */
+               match = 0;
+-              spin_lock_irq(shost->host_lock);
+-              list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
++              list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+                       if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
+                           i == ndlp->nlp_sid &&
+                           ndlp->rport) {
+@@ -1300,18 +1185,15 @@
+                               break;
+                       }
+               }
+-              spin_unlock_irq(shost->host_lock);
+               if (!match)
+                       continue;
+-              ret = lpfc_scsi_tgt_reset(lpfc_cmd, vport, i,
+-                                        cmnd->device->lun,
++              ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba, i, cmnd->device->lun,
+                                         ndlp->rport->dd_data);
+               if (ret != SUCCESS) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+-                                      "%d (%d):0700 Bus Reset on target %d "
+-                                      "failed\n",
+-                                      phba->brd_no, vport->vpi, i);
++                              "%d:0700 Bus Reset on target %d failed\n",
++                              phba->brd_no, i);
+                       err_count++;
+                       break;
+               }
+@@ -1337,7 +1219,9 @@
+                                   0, 0, 0, LPFC_CTX_HOST);
+       loopcnt = 0;
+       while(cnt) {
++              spin_unlock_irq(phba->host->host_lock);
+               schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
++              spin_lock_irq(phba->host->host_lock);
+               if (++loopcnt
+                   > (2 * phba->cfg_devloss_tmo)/LPFC_RESET_WAIT)
+@@ -1350,24 +1234,25 @@
+       if (cnt) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+-                              "%d (%d):0715 Bus Reset I/O flush failure: "
+-                              "cnt x%x left x%x\n",
+-                              phba->brd_no, vport->vpi, cnt, i);
++                 "%d:0715 Bus Reset I/O flush failure: cnt x%x left x%x\n",
++                 phba->brd_no, cnt, i);
+               ret = FAILED;
+       }
+-      lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+-                      "%d (%d):0714 SCSI layer issued Bus Reset Data: x%x\n",
+-                      phba->brd_no, vport->vpi, ret);
++      lpfc_printf_log(phba,
++                      KERN_ERR,
++                      LOG_FCP,
++                      "%d:0714 SCSI layer issued Bus Reset Data: x%x\n",
++                      phba->brd_no, ret);
+ out:
++      spin_unlock_irq(shost->host_lock);
+       return ret;
+ }
+ static int
+ lpfc_slave_alloc(struct scsi_device *sdev)
+ {
+-      struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata;
+       struct lpfc_scsi_buf *scsi_buf = NULL;
+       struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+       uint32_t total = 0, i;
+@@ -1388,35 +1273,27 @@
+        */
+       total = phba->total_scsi_bufs;
+       num_to_alloc = phba->cfg_lun_queue_depth + 2;
+-
+-      /* Allow some exchanges to be available always to complete discovery */
+-      if (total >= phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) {
++      if (total >= phba->cfg_hba_queue_depth) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
+-                              "%d (%d):0704 At limitation of %d "
+-                              "preallocated command buffers\n",
+-                              phba->brd_no, vport->vpi, total);
++                              "%d:0704 At limitation of %d preallocated "
++                              "command buffers\n", phba->brd_no, total);
+               return 0;
+-
+-      /* Allow some exchanges to be available always to complete discovery */
+-      } else if (total + num_to_alloc >
+-              phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) {
++      } else if (total + num_to_alloc > phba->cfg_hba_queue_depth) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
+-                              "%d (%d):0705 Allocation request of %d "
+-                              "command buffers will exceed max of %d.  "
+-                              "Reducing allocation request to %d.\n",
+-                              phba->brd_no, vport->vpi, num_to_alloc,
+-                              phba->cfg_hba_queue_depth,
++                              "%d:0705 Allocation request of %d command "
++                              "buffers will exceed max of %d.  Reducing "
++                              "allocation request to %d.\n", phba->brd_no,
++                              num_to_alloc, phba->cfg_hba_queue_depth,
+                               (phba->cfg_hba_queue_depth - total));
+               num_to_alloc = phba->cfg_hba_queue_depth - total;
+       }
+       for (i = 0; i < num_to_alloc; i++) {
+-              scsi_buf = lpfc_new_scsi_buf(vport);
++              scsi_buf = lpfc_new_scsi_buf(phba);
+               if (!scsi_buf) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+-                                      "%d (%d):0706 Failed to allocate "
+-                                      "command buffer\n",
+-                                      phba->brd_no, vport->vpi);
++                                      "%d:0706 Failed to allocate command "
++                                      "buffer\n", phba->brd_no);
+                       break;
+               }
+@@ -1431,8 +1308,7 @@
+ static int
+ lpfc_slave_configure(struct scsi_device *sdev)
+ {
+-      struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
+-      struct lpfc_hba   *phba = vport->phba;
++      struct lpfc_hba *phba = (struct lpfc_hba *) sdev->host->hostdata;
+       struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
+       if (sdev->tagged_supported)
+@@ -1464,7 +1340,6 @@
+       return;
+ }
+-
+ struct scsi_host_template lpfc_template = {
+       .module                 = THIS_MODULE,
+       .name                   = LPFC_DRIVER_NAME,
+@@ -1477,10 +1352,11 @@
+       .slave_configure        = lpfc_slave_configure,
+       .slave_destroy          = lpfc_slave_destroy,
+       .scan_finished          = lpfc_scan_finished,
++      .scan_start             = lpfc_scan_start,
+       .this_id                = -1,
+       .sg_tablesize           = LPFC_SG_SEG_CNT,
+       .cmd_per_lun            = LPFC_CMD_PER_LUN,
+       .use_clustering         = ENABLE_CLUSTERING,
+-      .shost_attrs            = lpfc_hba_attrs,
++      .shost_attrs            = lpfc_host_attrs,
+       .max_sectors            = 0xFFFF,
+ };
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_scsi.h linux-2.6.22-570/drivers/scsi/lpfc/lpfc_scsi.h
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_scsi.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_scsi.h     2007-07-08 19:32:17.000000000 -0400
+@@ -1,7 +1,7 @@
+ /*******************************************************************
+  * This file is part of the Emulex Linux Device Driver for         *
+  * Fibre Channel Host Bus Adapters.                                *
+- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
++ * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
+  * EMULEX and SLI are trademarks of Emulex.                        *
+  * www.emulex.com                                                  *
+  *                                                                 *
+@@ -110,6 +110,7 @@
+ struct lpfc_scsi_buf {
+       struct list_head list;
+       struct scsi_cmnd *pCmd;
++      struct lpfc_hba *scsi_hba;
+       struct lpfc_rport_data *rdata;
+       uint32_t timeout;
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_sli.c linux-2.6.22-570/drivers/scsi/lpfc/lpfc_sli.c
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_sli.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_sli.c      2007-07-08 19:32:17.000000000 -0400
+@@ -38,25 +38,23 @@
+ #include "lpfc_crtn.h"
+ #include "lpfc_logmsg.h"
+ #include "lpfc_compat.h"
+-#include "lpfc_debugfs.h"
+ /*
+  * Define macro to log: Mailbox command x%x cannot issue Data
+  * This allows multiple uses of lpfc_msgBlk0311
+  * w/o perturbing log msg utility.
+  */
+-#define LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag) \
++#define LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag) \
+                       lpfc_printf_log(phba, \
+                               KERN_INFO, \
+                               LOG_MBOX | LOG_SLI, \
+-                              "%d (%d):0311 Mailbox command x%x cannot " \
+-                              "issue Data: x%x x%x x%x\n", \
++                              "%d:0311 Mailbox command x%x cannot issue " \
++                              "Data: x%x x%x x%x\n", \
+                               phba->brd_no, \
+-                              pmbox->vport ? pmbox->vport->vpi : 0, \
+-                              pmbox->mb.mbxCommand,           \
+-                              phba->pport->port_state,        \
++                              mb->mbxCommand,         \
++                              phba->hba_state,        \
+                               psli->sli_flag, \
+-                              flag)
++                              flag);
+ /* There are only four IOCB completion types. */
+@@ -67,26 +65,8 @@
+       LPFC_ABORT_IOCB
+ } lpfc_iocb_type;
+-              /* SLI-2/SLI-3 provide different sized iocbs.  Given a pointer
+-               * to the start of the ring, and the slot number of the
+-               * desired iocb entry, calc a pointer to that entry.
+-               */
+-static inline IOCB_t *
+-lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+-{
+-      return (IOCB_t *) (((char *) pring->cmdringaddr) +
+-                         pring->cmdidx * phba->iocb_cmd_size);
+-}
+-
+-static inline IOCB_t *
+-lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+-{
+-      return (IOCB_t *) (((char *) pring->rspringaddr) +
+-                         pring->rspidx * phba->iocb_rsp_size);
+-}
+-
+-static struct lpfc_iocbq *
+-__lpfc_sli_get_iocbq(struct lpfc_hba *phba)
++struct lpfc_iocbq *
++lpfc_sli_get_iocbq(struct lpfc_hba * phba)
+ {
+       struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
+       struct lpfc_iocbq * iocbq = NULL;
+@@ -95,22 +75,10 @@
+       return iocbq;
+ }
+-struct lpfc_iocbq *
+-lpfc_sli_get_iocbq(struct lpfc_hba *phba)
+-{
+-      struct lpfc_iocbq * iocbq = NULL;
+-      unsigned long iflags;
+-
+-      spin_lock_irqsave(&phba->hbalock, iflags);
+-      iocbq = __lpfc_sli_get_iocbq(phba);
+-      spin_unlock_irqrestore(&phba->hbalock, iflags);
+-      return iocbq;
+-}
+-
+ void
+-__lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
++lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
+ {
+-      size_t start_clean = offsetof(struct lpfc_iocbq, iocb);
++      size_t start_clean = (size_t)(&((struct lpfc_iocbq *)NULL)->iocb);
+       /*
+        * Clean all volatile data fields, preserve iotag and node struct.
+@@ -119,19 +87,6 @@
+       list_add_tail(&iocbq->list, &phba->lpfc_iocb_list);
+ }
+-void
+-lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
+-{
+-      unsigned long iflags;
+-
+-      /*
+-       * Clean all volatile data fields, preserve iotag and node struct.
+-       */
+-      spin_lock_irqsave(&phba->hbalock, iflags);
+-      __lpfc_sli_release_iocbq(phba, iocbq);
+-      spin_unlock_irqrestore(&phba->hbalock, iflags);
+-}
+-
+ /*
+  * Translate the iocb command to an iocb command type used to decide the final
+  * disposition of each completed IOCB.
+@@ -200,9 +155,6 @@
+       case CMD_RCV_ELS_REQ_CX:
+       case CMD_RCV_SEQUENCE64_CX:
+       case CMD_RCV_ELS_REQ64_CX:
+-      case CMD_IOCB_RCV_SEQ64_CX:
+-      case CMD_IOCB_RCV_ELS64_CX:
+-      case CMD_IOCB_RCV_CONT64_CX:
+               type = LPFC_UNSOL_IOCB;
+               break;
+       default:
+@@ -214,77 +166,73 @@
+ }
+ static int
+-lpfc_sli_ring_map(struct lpfc_hba *phba)
++lpfc_sli_ring_map(struct lpfc_hba * phba, LPFC_MBOXQ_t *pmb)
+ {
+       struct lpfc_sli *psli = &phba->sli;
+-      LPFC_MBOXQ_t *pmb;
+-      MAILBOX_t *pmbox;
+-      int i, rc, ret = 0;
++      MAILBOX_t *pmbox = &pmb->mb;
++      int i, rc;
+-      pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (!pmb)
+-              return -ENOMEM;
+-      pmbox = &pmb->mb;
+-      phba->link_state = LPFC_INIT_MBX_CMDS;
+       for (i = 0; i < psli->num_rings; i++) {
++              phba->hba_state = LPFC_INIT_MBX_CMDS;
+               lpfc_config_ring(phba, i, pmb);
+               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
+               if (rc != MBX_SUCCESS) {
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+-                                      "%d:0446 Adapter failed to init (%d), "
++                      lpfc_printf_log(phba,
++                                      KERN_ERR,
++                                      LOG_INIT,
++                                      "%d:0446 Adapter failed to init, "
+                                       "mbxCmd x%x CFG_RING, mbxStatus x%x, "
+                                       "ring %d\n",
+-                                      phba->brd_no, rc,
++                                      phba->brd_no,
+                                       pmbox->mbxCommand,
+                                       pmbox->mbxStatus,
+                                       i);
+-                      phba->link_state = LPFC_HBA_ERROR;
+-                      ret = -ENXIO;
+-                      break;
++                      phba->hba_state = LPFC_HBA_ERROR;
++                      return -ENXIO;
+               }
+       }
+-      mempool_free(pmb, phba->mbox_mem_pool);
+-      return ret;
++      return 0;
+ }
+ static int
+-lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+-                      struct lpfc_iocbq *piocb)
++lpfc_sli_ringtxcmpl_put(struct lpfc_hba * phba,
++                      struct lpfc_sli_ring * pring, struct lpfc_iocbq * piocb)
+ {
+       list_add_tail(&piocb->list, &pring->txcmplq);
+       pring->txcmplq_cnt++;
+-      if ((unlikely(pring->ringno == LPFC_ELS_RING)) &&
+-         (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
+-         (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) {
+-              if (!piocb->vport)
+-                      BUG();
+-              else
+-                      mod_timer(&piocb->vport->els_tmofunc,
++      if (unlikely(pring->ringno == LPFC_ELS_RING))
++              mod_timer(&phba->els_tmofunc,
+                                       jiffies + HZ * (phba->fc_ratov << 1));
+-      }
+-
+-      return 0;
++      return (0);
+ }
+ static struct lpfc_iocbq *
+-lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
++lpfc_sli_ringtx_get(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
+ {
++      struct list_head *dlp;
+       struct lpfc_iocbq *cmd_iocb;
+-      list_remove_head((&pring->txq), cmd_iocb, struct lpfc_iocbq, list);
+-      if (cmd_iocb != NULL)
++      dlp = &pring->txq;
++      cmd_iocb = NULL;
++      list_remove_head((&pring->txq), cmd_iocb,
++                       struct lpfc_iocbq,
++                       list);
++      if (cmd_iocb) {
++              /* If the first ptr is not equal to the list header,
++               * deque the IOCBQ_t and return it.
++               */
+               pring->txq_cnt--;
+-      return cmd_iocb;
 +      }
-+      return err;
-+}
-+
-+static void __exit exit_unionfs_fs(void)
-+{
-+      stop_sioq();
-+      unionfs_destroy_filldir_cache();
-+      unionfs_destroy_inode_cache();
-+      unionfs_destroy_dentry_cache();
-+      unregister_filesystem(&unionfs_fs_type);
-+      printk("Completed unionfs module unload.\n");
-+}
-+
-+MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
-+            " (http://www.fsl.cs.sunysb.edu)");
-+MODULE_DESCRIPTION("Unionfs " UNIONFS_VERSION
-+                 " (http://unionfs.filesystems.org)");
-+MODULE_LICENSE("GPL");
-+
-+module_init(init_unionfs_fs);
-+module_exit(exit_unionfs_fs);
-diff -Nurb linux-2.6.22-570/fs/unionfs/mmap.c linux-2.6.22-590/fs/unionfs/mmap.c
---- linux-2.6.22-570/fs/unionfs/mmap.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/mmap.c 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,348 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2006      Shaya Potter
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of State University of New York
-+ *
-+ * 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 "union.h"
-+
-+/*
-+ * Unionfs doesn't implement ->writepages, which is OK with the VFS and
-+ * nkeeps our code simpler and smaller.  Nevertheless, somehow, our own
-+ * ->writepage must be called so we can sync the upper pages with the lower
-+ * pages: otherwise data changed at the upper layer won't get written to the
-+ * lower layer.
-+ *
-+ * Some lower file systems (e.g., NFS) expect the VFS to call its writepages
-+ * only, which in turn will call generic_writepages and invoke each of the
-+ * lower file system's ->writepage.  NFS in particular uses the
-+ * wbc->fs_private field in its nfs_writepage, which is set in its
-+ * nfs_writepages.  So if we don't call the lower nfs_writepages first, then
-+ * NFS's nfs_writepage will dereference a NULL wbc->fs_private and cause an
-+ * OOPS.  If, however, we implement a unionfs_writepages and then we do call
-+ * the lower nfs_writepages, then we "lose control" over the pages we're
-+ * trying to write to the lower file system: we won't be writing our own
-+ * new/modified data from the upper pages to the lower pages, and any
-+ * mmap-based changes are lost.
-+ *
-+ * This is a fundamental cache-coherency problem in Linux.  The kernel isn't
-+ * able to support such stacking abstractions cleanly.  One possible clean
-+ * way would be that a lower file system's ->writepage method have some sort
-+ * of a callback to validate if any upper pages for the same file+offset
-+ * exist and have newer content in them.
-+ *
-+ * This whole NULL ptr dereference is triggered at the lower file system
-+ * (NFS) because the wbc->for_writepages is set to 1.  Therefore, to avoid
-+ * this NULL pointer dereference, we set this flag to 0 and restore it upon
-+ * exit.  This probably means that we're slightly less efficient in writing
-+ * pages out, doing them one at a time, but at least we avoid the oops until
-+ * such day as Linux can better support address_space_ops in a stackable
-+ * fashion.
-+ */
-+int unionfs_writepage(struct page *page, struct writeback_control *wbc)
-+{
-+      int err = -EIO;
-+      struct inode *inode;
-+      struct inode *lower_inode;
-+      struct page *lower_page;
-+      char *kaddr, *lower_kaddr;
-+      int saved_for_writepages = wbc->for_writepages;
-+
-+      inode = page->mapping->host;
-+      lower_inode = unionfs_lower_inode(inode);
-+
-+      /* find lower page (returns a locked page) */
-+      lower_page = grab_cache_page(lower_inode->i_mapping, page->index);
-+      if (!lower_page)
-+              goto out;
-+
-+      /* get page address, and encode it */
-+      kaddr = kmap(page);
-+      lower_kaddr = kmap(lower_page);
-+
-+      memcpy(lower_kaddr, kaddr, PAGE_CACHE_SIZE);
-+
-+      kunmap(page);
-+      kunmap(lower_page);
-+
-+      BUG_ON(!lower_inode->i_mapping->a_ops->writepage);
-+
-+      /* workaround for some lower file systems: see big comment on top */
-+      if (wbc->for_writepages && !wbc->fs_private)
-+              wbc->for_writepages = 0;
-+
-+      /* call lower writepage (expects locked page) */
-+      err = lower_inode->i_mapping->a_ops->writepage(lower_page, wbc);
-+      wbc->for_writepages = saved_for_writepages; /* restore value */
-+
-+      /*
-+       * update mtime and ctime of lower level file system
-+       * unionfs' mtime and ctime are updated by generic_file_write
-+       */
-+      lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
-+
-+      page_cache_release(lower_page); /* b/c grab_cache_page increased refcnt */
-+
-+      if (err)
-+              ClearPageUptodate(page);
-+      else
-+              SetPageUptodate(page);
-+
-+out:
-+      unlock_page(page);
-+      return err;
-+}
-+
-+/*
-+ * readpage is called from generic_page_read and the fault handler.
-+ * If your file system uses generic_page_read for the read op, it
-+ * must implement readpage.
-+ *
-+ * Readpage expects a locked page, and must unlock it.
-+ */
-+static int unionfs_do_readpage(struct file *file, struct page *page)
-+{
-+      int err = -EIO;
-+      struct dentry *dentry;
-+      struct file *lower_file = NULL;
-+      struct inode *inode, *lower_inode;
-+      char *page_data;
-+      struct page *lower_page;
-+      char *lower_page_data;
++      return (cmd_iocb);
+ }
+ static IOCB_t *
+ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+ {
+-      struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
+-              &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
+-              &phba->slim2p->mbx.us.s2.port[pring->ringno];
++      struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
+       uint32_t  max_cmd_idx = pring->numCiocb;
++      IOCB_t *iocb = NULL;
+       if ((pring->next_cmdidx == pring->cmdidx) &&
+          (++pring->next_cmdidx >= max_cmd_idx))
+@@ -301,17 +249,15 @@
+                                       phba->brd_no, pring->ringno,
+                                       pring->local_getidx, max_cmd_idx);
+-                      phba->link_state = LPFC_HBA_ERROR;
++                      phba->hba_state = LPFC_HBA_ERROR;
+                       /*
+                        * All error attention handlers are posted to
+                        * worker thread
+                        */
+                       phba->work_ha |= HA_ERATT;
+                       phba->work_hs = HS_FFER3;
+-
+-                      /* hbalock should already be held */
+                       if (phba->work_wait)
+-                              lpfc_worker_wake_up(phba);
++                              wake_up(phba->work_wait);
+                       return NULL;
+               }
+@@ -320,34 +266,39 @@
+                       return NULL;
+       }
+-      return lpfc_cmd_iocb(phba, pring);
++      iocb = IOCB_ENTRY(pring->cmdringaddr, pring->cmdidx);
 +
-+      dentry = file->f_dentry;
-+      if (UNIONFS_F(file) == NULL) {
-+              err = -ENOENT;
-+              goto out_err;
++      return iocb;
+ }
+ uint16_t
+-lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
++lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq)
+ {
+-      struct lpfc_iocbq **new_arr;
+-      struct lpfc_iocbq **old_arr;
++      struct lpfc_iocbq ** new_arr;
++      struct lpfc_iocbq ** old_arr;
+       size_t new_len;
+       struct lpfc_sli *psli = &phba->sli;
+       uint16_t iotag;
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       iotag = psli->last_iotag;
+       if(++iotag < psli->iocbq_lookup_len) {
+               psli->last_iotag = iotag;
+               psli->iocbq_lookup[iotag] = iocbq;
+-              spin_unlock_irq(&phba->hbalock);
++              spin_unlock_irq(phba->host->host_lock);
+               iocbq->iotag = iotag;
+               return iotag;
+-      } else if (psli->iocbq_lookup_len < (0xffff
 +      }
-+
-+      lower_file = unionfs_lower_file(file);
-+      inode = dentry->d_inode;
-+      lower_inode = unionfs_lower_inode(inode);
-+
-+      lower_page = NULL;
-+
-+      /* find lower page (returns a locked page) */
-+      lower_page = read_cache_page(lower_inode->i_mapping,
-+                                   page->index,
-+                                   (filler_t *) lower_inode->i_mapping->
-+                                   a_ops->readpage, (void *)lower_file);
-+
-+      if (IS_ERR(lower_page)) {
-+              err = PTR_ERR(lower_page);
-+              lower_page = NULL;
-+              goto out_release;
++      else if (psli->iocbq_lookup_len < (0xffff
+                                          - LPFC_IOCBQ_LOOKUP_INCREMENT)) {
+               new_len = psli->iocbq_lookup_len + LPFC_IOCBQ_LOOKUP_INCREMENT;
+-              spin_unlock_irq(&phba->hbalock);
+-              new_arr = kzalloc(new_len * sizeof (struct lpfc_iocbq *),
++              spin_unlock_irq(phba->host->host_lock);
++              new_arr = kmalloc(new_len * sizeof (struct lpfc_iocbq *),
+                                 GFP_KERNEL);
+               if (new_arr) {
+-                      spin_lock_irq(&phba->hbalock);
++                      memset((char *)new_arr, 0,
++                             new_len * sizeof (struct lpfc_iocbq *));
++                      spin_lock_irq(phba->host->host_lock);
+                       old_arr = psli->iocbq_lookup;
+                       if (new_len <= psli->iocbq_lookup_len) {
+                               /* highly unprobable case */
+@@ -356,11 +307,11 @@
+                               if(++iotag < psli->iocbq_lookup_len) {
+                                       psli->last_iotag = iotag;
+                                       psli->iocbq_lookup[iotag] = iocbq;
+-                                      spin_unlock_irq(&phba->hbalock);
++                                      spin_unlock_irq(phba->host->host_lock);
+                                       iocbq->iotag = iotag;
+                                       return iotag;
+                               }
+-                              spin_unlock_irq(&phba->hbalock);
++                              spin_unlock_irq(phba->host->host_lock);
+                               return 0;
+                       }
+                       if (psli->iocbq_lookup)
+@@ -371,13 +322,13 @@
+                       psli->iocbq_lookup_len = new_len;
+                       psli->last_iotag = iotag;
+                       psli->iocbq_lookup[iotag] = iocbq;
+-                      spin_unlock_irq(&phba->hbalock);
++                      spin_unlock_irq(phba->host->host_lock);
+                       iocbq->iotag = iotag;
+                       kfree(old_arr);
+                       return iotag;
+               }
+       } else
+-              spin_unlock_irq(&phba->hbalock);
++              spin_unlock_irq(phba->host->host_lock);
+       lpfc_printf_log(phba, KERN_ERR,LOG_SLI,
+                       "%d:0318 Failed to allocate IOTAG.last IOTAG is %d\n",
+@@ -398,7 +349,7 @@
+       /*
+        * Issue iocb command to adapter
+        */
+-      lpfc_sli_pcimem_bcopy(&nextiocb->iocb, iocb, phba->iocb_cmd_size);
++      lpfc_sli_pcimem_bcopy(&nextiocb->iocb, iocb, sizeof (IOCB_t));
+       wmb();
+       pring->stats.iocb_cmd++;
+@@ -410,18 +361,20 @@
+       if (nextiocb->iocb_cmpl)
+               lpfc_sli_ringtxcmpl_put(phba, pring, nextiocb);
+       else
+-              __lpfc_sli_release_iocbq(phba, nextiocb);
++              lpfc_sli_release_iocbq(phba, nextiocb);
+       /*
+        * Let the HBA know what IOCB slot will be the next one the
+        * driver will put a command into.
+        */
+       pring->cmdidx = pring->next_cmdidx;
+-      writel(pring->cmdidx, &phba->host_gp[pring->ringno].cmdPutInx);
++      writel(pring->cmdidx, phba->MBslimaddr
++             + (SLIMOFF + (pring->ringno * 2)) * 4);
+ }
+ static void
+-lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
++lpfc_sli_update_full_ring(struct lpfc_hba * phba,
++                        struct lpfc_sli_ring *pring)
+ {
+       int ringno = pring->ringno;
+@@ -440,7 +393,8 @@
+ }
+ static void
+-lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
++lpfc_sli_update_ring(struct lpfc_hba * phba,
++                   struct lpfc_sli_ring *pring)
+ {
+       int ringno = pring->ringno;
+@@ -453,7 +407,7 @@
+ }
+ static void
+-lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
++lpfc_sli_resume_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring)
+ {
+       IOCB_t *iocb;
+       struct lpfc_iocbq *nextiocb;
+@@ -466,7 +420,7 @@
+        *  (d) IOCB processing is not blocked by the outstanding mbox command.
+        */
+       if (pring->txq_cnt &&
+-          lpfc_is_link_up(phba) &&
++          (phba->hba_state > LPFC_LINK_DOWN) &&
+           (pring->ringno != phba->sli.fcp_ring ||
+            phba->sli.sli_flag & LPFC_PROCESS_LA) &&
+           !(pring->flag & LPFC_STOP_IOCB_MBX)) {
+@@ -486,15 +440,11 @@
+ /* lpfc_sli_turn_on_ring is only called by lpfc_sli_handle_mb_event below */
+ static void
+-lpfc_sli_turn_on_ring(struct lpfc_hba *phba, int ringno)
++lpfc_sli_turn_on_ring(struct lpfc_hba * phba, int ringno)
+ {
+-      struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
+-              &phba->slim2p->mbx.us.s3_pgp.port[ringno] :
+-              &phba->slim2p->mbx.us.s2.port[ringno];
+-      unsigned long iflags;
++      struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[ringno];
+       /* If the ring is active, flag it */
+-      spin_lock_irqsave(&phba->hbalock, iflags);
+       if (phba->sli.ring[ringno].cmdringaddr) {
+               if (phba->sli.ring[ringno].flag & LPFC_STOP_IOCB_MBX) {
+                       phba->sli.ring[ringno].flag &= ~LPFC_STOP_IOCB_MBX;
+@@ -503,176 +453,11 @@
+                        */
+                       phba->sli.ring[ringno].local_getidx
+                               = le32_to_cpu(pgp->cmdGetInx);
++                      spin_lock_irq(phba->host->host_lock);
+                       lpfc_sli_resume_iocb(phba, &phba->sli.ring[ringno]);
++                      spin_unlock_irq(phba->host->host_lock);
+               }
+       }
+-      spin_unlock_irqrestore(&phba->hbalock, iflags);
+-}
+-
+-struct lpfc_hbq_entry *
+-lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno)
+-{
+-      struct hbq_s *hbqp = &phba->hbqs[hbqno];
+-
+-      if (hbqp->next_hbqPutIdx == hbqp->hbqPutIdx &&
+-          ++hbqp->next_hbqPutIdx >= hbqp->entry_count)
+-              hbqp->next_hbqPutIdx = 0;
+-
+-      if (unlikely(hbqp->local_hbqGetIdx == hbqp->next_hbqPutIdx)) {
+-              uint32_t raw_index = phba->hbq_get[hbqno];
+-              uint32_t getidx = le32_to_cpu(raw_index);
+-
+-              hbqp->local_hbqGetIdx = getidx;
+-
+-              if (unlikely(hbqp->local_hbqGetIdx >= hbqp->entry_count)) {
+-                      lpfc_printf_log(phba, KERN_ERR,
+-                                      LOG_SLI | LOG_VPORT,
+-                                      "%d:1802 HBQ %d: local_hbqGetIdx "
+-                                      "%u is > than hbqp->entry_count %u\n",
+-                                      phba->brd_no, hbqno,
+-                                      hbqp->local_hbqGetIdx,
+-                                      hbqp->entry_count);
+-
+-                      phba->link_state = LPFC_HBA_ERROR;
+-                      return NULL;
+-              }
+-
+-              if (hbqp->local_hbqGetIdx == hbqp->next_hbqPutIdx)
+-                      return NULL;
+-      }
+-
+-      return (struct lpfc_hbq_entry *) phba->hbqslimp.virt + hbqp->hbqPutIdx;
+-}
+-
+-void
+-lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba)
+-{
+-      struct lpfc_dmabuf *dmabuf, *next_dmabuf;
+-      struct hbq_dmabuf *hbq_buf;
+-
+-      /* Return all memory used by all HBQs */
+-      list_for_each_entry_safe(dmabuf, next_dmabuf,
+-                               &phba->hbq_buffer_list, list) {
+-              hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf);
+-              list_del(&hbq_buf->dbuf.list);
+-              lpfc_hbq_free(phba, hbq_buf->dbuf.virt, hbq_buf->dbuf.phys);
+-              kfree(hbq_buf);
+-      }
+-}
+-
+-static void
+-lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
+-                       struct hbq_dmabuf *hbq_buf)
+-{
+-      struct lpfc_hbq_entry *hbqe;
+-      dma_addr_t physaddr = hbq_buf->dbuf.phys;
+-
+-      /* Get next HBQ entry slot to use */
+-      hbqe = lpfc_sli_next_hbq_slot(phba, hbqno);
+-      if (hbqe) {
+-              struct hbq_s *hbqp = &phba->hbqs[hbqno];
+-
+-              hbqe->bde.addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
+-              hbqe->bde.addrLow  = le32_to_cpu(putPaddrLow(physaddr));
+-              hbqe->bde.tus.f.bdeSize = FCELSSIZE;
+-              hbqe->bde.tus.f.bdeFlags = 0;
+-              hbqe->bde.tus.w = le32_to_cpu(hbqe->bde.tus.w);
+-              hbqe->buffer_tag = le32_to_cpu(hbq_buf->tag);
+-                              /* Sync SLIM */
+-              hbqp->hbqPutIdx = hbqp->next_hbqPutIdx;
+-              writel(hbqp->hbqPutIdx, phba->hbq_put + hbqno);
+-                              /* flush */
+-              readl(phba->hbq_put + hbqno);
+-              list_add_tail(&hbq_buf->dbuf.list, &phba->hbq_buffer_list);
+-      }
+-}
+-
+-static struct lpfc_hbq_init lpfc_els_hbq = {
+-      .rn = 1,
+-      .entry_count = 200,
+-      .mask_count = 0,
+-      .profile = 0,
+-      .ring_mask = 1 << LPFC_ELS_RING,
+-      .buffer_count = 0,
+-      .init_count = 20,
+-      .add_count = 5,
+-};
+-
+-static struct lpfc_hbq_init *lpfc_hbq_defs[] = {
+-      &lpfc_els_hbq,
+-};
+-
+-int
+-lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
+-{
+-      uint32_t i, start, end;
+-      struct hbq_dmabuf *hbq_buffer;
+-
+-      start = lpfc_hbq_defs[hbqno]->buffer_count;
+-      end = count + lpfc_hbq_defs[hbqno]->buffer_count;
+-      if (end > lpfc_hbq_defs[hbqno]->entry_count) {
+-              end = lpfc_hbq_defs[hbqno]->entry_count;
+-      }
+-
+-      /* Populate HBQ entries */
+-      for (i = start; i < end; i++) {
+-              hbq_buffer = kmalloc(sizeof(struct hbq_dmabuf),
+-                                   GFP_KERNEL);
+-              if (!hbq_buffer)
+-                      return 1;
+-              hbq_buffer->dbuf.virt = lpfc_hbq_alloc(phba, MEM_PRI,
+-                                                      &hbq_buffer->dbuf.phys);
+-              if (hbq_buffer->dbuf.virt == NULL)
+-                      return 1;
+-              hbq_buffer->tag = (i | (hbqno << 16));
+-              lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer);
+-              lpfc_hbq_defs[hbqno]->buffer_count++;
+-      }
+-      return 0;
+-}
+-
+-int
+-lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno)
+-{
+-      return(lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
+-                                       lpfc_hbq_defs[qno]->add_count));
+-}
+-
+-int
+-lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
+-{
+-      return(lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
+-                                       lpfc_hbq_defs[qno]->init_count));
+-}
+-
+-struct hbq_dmabuf *
+-lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
+-{
+-      struct lpfc_dmabuf *d_buf;
+-      struct hbq_dmabuf *hbq_buf;
+-
+-      list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) {
+-              hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
+-              if ((hbq_buf->tag & 0xffff) == tag) {
+-                      return hbq_buf;
+-              }
+-      }
+-      lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_VPORT,
+-                      "%d:1803 Bad hbq tag. Data: x%x x%x\n",
+-                      phba->brd_no, tag,
+-                      lpfc_hbq_defs[tag >> 16]->buffer_count);
+-      return NULL;
+-}
+-
+-void
+-lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *sp)
+-{
+-      uint32_t hbqno;
+-
+-      if (sp) {
+-              hbqno = sp->tag >> 16;
+-              lpfc_sli_hbq_to_firmware(phba, hbqno, sp);
+-      }
+ }
+ static int
+@@ -726,38 +511,32 @@
+       case MBX_FLASH_WR_ULA:
+       case MBX_SET_DEBUG:
+       case MBX_LOAD_EXP_ROM:
+-      case MBX_REG_VPI:
+-      case MBX_UNREG_VPI:
+-      case MBX_HEARTBEAT:
+               ret = mbxCommand;
+               break;
+       default:
+               ret = MBX_SHUTDOWN;
+               break;
+       }
+-      return ret;
++      return (ret);
+ }
+ static void
+-lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
++lpfc_sli_wake_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
+ {
+       wait_queue_head_t *pdone_q;
+-      unsigned long drvr_flag;
+       /*
+        * If pdone_q is empty, the driver thread gave up waiting and
+        * continued running.
+        */
+       pmboxq->mbox_flag |= LPFC_MBX_WAKE;
+-      spin_lock_irqsave(&phba->hbalock, drvr_flag);
+       pdone_q = (wait_queue_head_t *) pmboxq->context1;
+       if (pdone_q)
+               wake_up_interruptible(pdone_q);
+-      spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+       return;
+ }
+ void
+-lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
++lpfc_sli_def_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
+ {
+       struct lpfc_dmabuf *mp;
+       uint16_t rpi;
+@@ -774,64 +553,79 @@
+        * If a REG_LOGIN succeeded  after node is destroyed or node
+        * is in re-discovery driver need to cleanup the RPI.
+        */
+-      if (!(phba->pport->load_flag & FC_UNLOADING) &&
+-          pmb->mb.mbxCommand == MBX_REG_LOGIN64 &&
+-          !pmb->mb.mbxStatus) {
++      if (!(phba->fc_flag & FC_UNLOADING) &&
++              (pmb->mb.mbxCommand == MBX_REG_LOGIN64) &&
++              (!pmb->mb.mbxStatus)) {
+               rpi = pmb->mb.un.varWords[0];
+-              lpfc_unreg_login(phba, pmb->mb.un.varRegLogin.vpi, rpi, pmb);
+-              pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
++              lpfc_unreg_login(phba, rpi, pmb);
++              pmb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
+               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+               if (rc != MBX_NOT_FINISHED)
+                       return;
+       }
+-      mempool_free(pmb, phba->mbox_mem_pool);
++      mempool_free( pmb, phba->mbox_mem_pool);
+       return;
+ }
+ int
+-lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
++lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
+ {
++      MAILBOX_t *mbox;
+       MAILBOX_t *pmbox;
+       LPFC_MBOXQ_t *pmb;
+-      int rc;
+-      LIST_HEAD(cmplq);
++      struct lpfc_sli *psli;
++      int i, rc;
++      uint32_t process_next;
+-      phba->sli.slistat.mbox_event++;
++      psli = &phba->sli;
++      /* We should only get here if we are in SLI2 mode */
++      if (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE)) {
++              return (1);
 +      }
+-      /* Get all completed mailboxe buffers into the cmplq */
+-      spin_lock_irq(&phba->hbalock);
+-      list_splice_init(&phba->sli.mboxq_cmpl, &cmplq);
+-      spin_unlock_irq(&phba->hbalock);
++      phba->sli.slistat.mbox_event++;
+       /* Get a Mailbox buffer to setup mailbox commands for callback */
+-      do {
+-              list_remove_head(&cmplq, pmb, LPFC_MBOXQ_t, list);
+-              if (pmb == NULL)
+-                      break;
+-
++      if ((pmb = phba->sli.mbox_active)) {
+               pmbox = &pmb->mb;
++              mbox = &phba->slim2p->mbx;
+-              if (pmbox->mbxCommand != MBX_HEARTBEAT) {
+-                      if (pmb->vport) {
+-                              lpfc_debugfs_disc_trc(pmb->vport,
+-                                      LPFC_DISC_TRC_MBOX_VPORT,
+-                                      "MBOX cmpl vport: cmd:x%x mb:x%x x%x",
+-                                      (uint32_t)pmbox->mbxCommand,
+-                                      pmbox->un.varWords[0],
+-                                      pmbox->un.varWords[1]);
+-                      }
+-                      else {
+-                              lpfc_debugfs_disc_trc(phba->pport,
+-                                      LPFC_DISC_TRC_MBOX,
+-                                      "MBOX cmpl:       cmd:x%x mb:x%x x%x",
+-                                      (uint32_t)pmbox->mbxCommand,
+-                                      pmbox->un.varWords[0],
+-                                      pmbox->un.varWords[1]);
++              /* First check out the status word */
++              lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof (uint32_t));
++
++              /* Sanity check to ensure the host owns the mailbox */
++              if (pmbox->mbxOwner != OWN_HOST) {
++                      /* Lets try for a while */
++                      for (i = 0; i < 10240; i++) {
++                              /* First copy command data */
++                              lpfc_sli_pcimem_bcopy(mbox, pmbox,
++                                                      sizeof (uint32_t));
++                              if (pmbox->mbxOwner == OWN_HOST)
++                                      goto mbout;
+                       }
++                      /* Stray Mailbox Interrupt, mbxCommand <cmd> mbxStatus
++                         <status> */
++                      lpfc_printf_log(phba,
++                                      KERN_WARNING,
++                                      LOG_MBOX | LOG_SLI,
++                                      "%d:0304 Stray Mailbox Interrupt "
++                                      "mbxCommand x%x mbxStatus x%x\n",
++                                      phba->brd_no,
++                                      pmbox->mbxCommand,
++                                      pmbox->mbxStatus);
 +
-+      /*
-+       * wait for the page data to show up
-+       * (signaled by readpage as unlocking the page)
-+       */
-+      wait_on_page_locked(lower_page);
-+      if (!PageUptodate(lower_page)) {
-+              /*
-+               * call readpage() again if we returned from wait_on_page
-+               * with a page that's not up-to-date; that can happen when a
-+               * partial page has a few buffers which are ok, but not the
-+               * whole page.
-+               */
-+              lock_page(lower_page);
-+              err = lower_inode->i_mapping->a_ops->readpage(lower_file,
-+                                                            lower_page);
-+              if (err) {
-+                      lower_page = NULL;
-+                      goto out_release;
-+              }
++                      spin_lock_irq(phba->host->host_lock);
++                      phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE;
++                      spin_unlock_irq(phba->host->host_lock);
++                      return (1);
+               }
++            mbout:
++              del_timer_sync(&phba->sli.mbox_tmo);
++              phba->work_hba_events &= ~WORKER_MBOX_TMO;
 +
-+              wait_on_page_locked(lower_page);
-+              if (!PageUptodate(lower_page)) {
-+                      err = -EIO;
-+                      goto out_release;
+               /*
+                * It is a fatal error if unknown mbox command completion.
+                */
+@@ -839,50 +633,51 @@
+                   MBX_SHUTDOWN) {
+                       /* Unknow mailbox command compl */
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+-                                      "%d (%d):0323 Unknown Mailbox command "
+-                                      "%x Cmpl\n",
++                      lpfc_printf_log(phba,
++                              KERN_ERR,
++                              LOG_MBOX | LOG_SLI,
++                              "%d:0323 Unknown Mailbox command %x Cmpl\n",
+                               phba->brd_no,
+-                                      pmb->vport ? pmb->vport->vpi : 0,
+                               pmbox->mbxCommand);
+-                      phba->link_state = LPFC_HBA_ERROR;
++                      phba->hba_state = LPFC_HBA_ERROR;
+                       phba->work_hs = HS_FFER3;
+                       lpfc_handle_eratt(phba);
+-                      continue;
++                      return (0);
+               }
++              phba->sli.mbox_active = NULL;
+               if (pmbox->mbxStatus) {
+                       phba->sli.slistat.mbox_stat_err++;
+                       if (pmbox->mbxStatus == MBXERR_NO_RESOURCES) {
+                               /* Mbox cmd cmpl error - RETRYing */
+-                              lpfc_printf_log(phba, KERN_INFO,
++                              lpfc_printf_log(phba,
++                                      KERN_INFO,
+                                       LOG_MBOX | LOG_SLI,
+-                                              "%d (%d):0305 Mbox cmd cmpl "
+-                                              "error - RETRYing Data: x%x "
+-                                              "x%x x%x x%x\n",
++                                      "%d:0305 Mbox cmd cmpl error - "
++                                      "RETRYing Data: x%x x%x x%x x%x\n",
+                                       phba->brd_no,
+-                                              pmb->vport ? pmb->vport->vpi :0,
+                                       pmbox->mbxCommand,
+                                       pmbox->mbxStatus,
+                                       pmbox->un.varWords[0],
+-                                              pmb->vport->port_state);
++                                      phba->hba_state);
+                               pmbox->mbxStatus = 0;
+                               pmbox->mbxOwner = OWN_HOST;
+-                              spin_lock_irq(&phba->hbalock);
++                              spin_lock_irq(phba->host->host_lock);
+                               phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+-                              spin_unlock_irq(&phba->hbalock);
++                              spin_unlock_irq(phba->host->host_lock);
+                               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+                               if (rc == MBX_SUCCESS)
+-                                      continue;
++                                      return (0);
+                       }
+               }
+               /* Mailbox cmd <cmd> Cmpl <cmpl> */
+-              lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+-                              "%d (%d):0307 Mailbox cmd x%x Cmpl x%p "
++              lpfc_printf_log(phba,
++                              KERN_INFO,
++                              LOG_MBOX | LOG_SLI,
++                              "%d:0307 Mailbox cmd x%x Cmpl x%p "
+                               "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x\n",
+                               phba->brd_no,
+-                              pmb->vport ? pmb->vport->vpi : 0,
+                               pmbox->mbxCommand,
+                               pmb->mbox_cmpl,
+                               *((uint32_t *) pmbox),
+@@ -895,35 +690,39 @@
+                               pmbox->un.varWords[6],
+                               pmbox->un.varWords[7]);
+-              if (pmb->mbox_cmpl)
++              if (pmb->mbox_cmpl) {
++                      lpfc_sli_pcimem_bcopy(mbox, pmbox, MAILBOX_CMD_SIZE);
+                       pmb->mbox_cmpl(phba,pmb);
+-      } while (1);
+-      return 0;
+-}
 +              }
 +      }
+-static struct lpfc_dmabuf *
+-lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
+-{
+-      struct hbq_dmabuf *hbq_entry, *new_hbq_entry;
+-      hbq_entry = lpfc_sli_hbqbuf_find(phba, tag);
+-      if (hbq_entry == NULL)
+-              return NULL;
+-      list_del(&hbq_entry->dbuf.list);
+-      new_hbq_entry = kmalloc(sizeof(struct hbq_dmabuf), GFP_ATOMIC);
+-      if (new_hbq_entry == NULL)
+-              return &hbq_entry->dbuf;
+-      new_hbq_entry->dbuf = hbq_entry->dbuf;
+-      new_hbq_entry->tag = -1;
+-      hbq_entry->dbuf.virt = lpfc_hbq_alloc(phba, 0, &hbq_entry->dbuf.phys);
+-      if (hbq_entry->dbuf.virt == NULL) {
+-              kfree(new_hbq_entry);
+-              return &hbq_entry->dbuf;
++      do {
++              process_next = 0;       /* by default don't loop */
++              spin_lock_irq(phba->host->host_lock);
++              phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
++
++              /* Process next mailbox command if there is one */
++              if ((pmb = lpfc_mbox_get(phba))) {
++                      spin_unlock_irq(phba->host->host_lock);
++                      rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
++                      if (rc == MBX_NOT_FINISHED) {
++                              pmb->mb.mbxStatus = MBX_NOT_FINISHED;
++                              pmb->mbox_cmpl(phba,pmb);
++                              process_next = 1;
++                              continue;       /* loop back */
++                      }
++              } else {
++                      spin_unlock_irq(phba->host->host_lock);
++                      /* Turn on IOCB processing */
++                      for (i = 0; i < phba->sli.num_rings; i++)
++                              lpfc_sli_turn_on_ring(phba, i);
+               }
+-      lpfc_sli_free_hbq(phba, hbq_entry);
+-      return &new_hbq_entry->dbuf;
+-}
++      } while (process_next);
 +
-+      /* map pages, get their addresses */
-+      page_data = (char *)kmap(page);
-+      lower_page_data = (char *)kmap(lower_page);
-+
-+      memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE);
-+
-+      err = 0;
-+
-+      kunmap(lower_page);
-+      kunmap(page);
-+
-+out_release:
-+      if (lower_page)
-+              page_cache_release(lower_page); /* undo read_cache_page */
-+
-+      if (err == 0)
-+              SetPageUptodate(page);
-+      else
-+              ClearPageUptodate(page);
-+
-+out_err:
-+      return err;
-+}
-+
-+int unionfs_readpage(struct file *file, struct page *page)
-+{
-+      int err;
-+
-+      unionfs_read_lock(file->f_dentry->d_sb);
-+
-+      if ((err = unionfs_file_revalidate(file, 0)))
-+              goto out;
-+
-+      err = unionfs_do_readpage(file, page);
-+
-+      if (!err)
-+              touch_atime(unionfs_lower_mnt(file->f_path.dentry),
-+                          unionfs_lower_dentry(file->f_path.dentry));
-+
-+      /*
-+       * we have to unlock our page, b/c we _might_ have gotten a locked
-+       * page.  but we no longer have to wakeup on our page here, b/c
-+       * UnlockPage does it
-+       */
-+out:
-+      unlock_page(page);
-+      unionfs_read_unlock(file->f_dentry->d_sb);
-+
-+      return err;
-+}
-+
-+int unionfs_prepare_write(struct file *file, struct page *page, unsigned from,
-+                        unsigned to)
-+{
-+      int err;
-+
-+      unionfs_read_lock(file->f_dentry->d_sb);
-+
-+      err = unionfs_file_revalidate(file, 1);
-+
-+      unionfs_read_unlock(file->f_dentry->d_sb);
-+
-+      return err;
-+}
-+
-+int unionfs_commit_write(struct file *file, struct page *page, unsigned from,
-+                       unsigned to)
-+{
-+      int err = -ENOMEM;
-+      struct inode *inode, *lower_inode;
-+      struct file *lower_file = NULL;
-+      loff_t pos;
-+      unsigned bytes = to - from;
-+      char *page_data = NULL;
-+      mm_segment_t old_fs;
-+
-+      BUG_ON(file == NULL);
-+
-+      unionfs_read_lock(file->f_dentry->d_sb);
-+
-+      if ((err = unionfs_file_revalidate(file, 1)))
-+              goto out;
-+
-+      inode = page->mapping->host;
-+      lower_inode = unionfs_lower_inode(inode);
-+
-+      if (UNIONFS_F(file) != NULL)
-+              lower_file = unionfs_lower_file(file);
-+
-+      /* FIXME: is this assertion right here? */
-+      BUG_ON(lower_file == NULL);
-+
-+      page_data = (char *)kmap(page);
-+      lower_file->f_pos = (page->index << PAGE_CACHE_SHIFT) + from;
-+
-+      /* SP: I use vfs_write instead of copying page data and the
-+       * prepare_write/commit_write combo because file system's like
-+       * GFS/OCFS2 don't like things touching those directly,
-+       * calling the underlying write op, while a little bit slower, will
-+       * call all the FS specific code as well
-+       */
-+      old_fs = get_fs();
-+      set_fs(KERNEL_DS);
-+      err = vfs_write(lower_file, page_data + from, bytes,
-+                      &lower_file->f_pos);
-+      set_fs(old_fs);
-+
-+      kunmap(page);
-+
-+      if (err < 0)
-+              goto out;
-+
-+      inode->i_blocks = lower_inode->i_blocks;
-+      /* we may have to update i_size */
-+      pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + to;
-+      if (pos > i_size_read(inode))
-+              i_size_write(inode, pos);
-+
-+      /*
-+       * update mtime and ctime of lower level file system
-+       * unionfs' mtime and ctime are updated by generic_file_write
-+       */
-+      lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
-+
-+      mark_inode_dirty_sync(inode);
-+
-+out:
-+      if (err < 0)
-+              ClearPageUptodate(page);
-+
-+      unionfs_read_unlock(file->f_dentry->d_sb);
-+      return err;             /* assume all is ok */
-+}
-+
-+void unionfs_sync_page(struct page *page)
-+{
-+      struct inode *inode;
-+      struct inode *lower_inode;
-+      struct page *lower_page;
-+      struct address_space *mapping;
-+
-+      inode = page->mapping->host;
-+      lower_inode = unionfs_lower_inode(inode);
-+
-+      /* find lower page (returns a locked page) */
-+      lower_page = grab_cache_page(lower_inode->i_mapping, page->index);
-+      if (!lower_page)
-+              goto out;
-+
-+      /* do the actual sync */
-+      mapping = lower_page->mapping;
-+      /*
-+       * XXX: can we optimize ala RAIF and set the lower page to be
-+       * discarded after a successful sync_page?
-+       */
-+      if (mapping && mapping->a_ops && mapping->a_ops->sync_page)
-+              mapping->a_ops->sync_page(lower_page);
-+
-+      unlock_page(lower_page);        /* b/c grab_cache_page locked it */
-+      page_cache_release(lower_page); /* b/c grab_cache_page increased refcnt */
-+
-+out:
-+      return;
++      return (0);
 +}
+ static int
+ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+                           struct lpfc_iocbq *saveq)
+@@ -936,9 +735,7 @@
+       match = 0;
+       irsp = &(saveq->iocb);
+       if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX)
+-          || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX)
+-          || (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX)
+-          || (irsp->ulpCommand == CMD_IOCB_RCV_CONT64_CX)) {
++          || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX)) {
+               Rctl = FC_ELS_REQ;
+               Type = FC_ELS_DATA;
+       } else {
+@@ -950,24 +747,13 @@
+               /* Firmware Workaround */
+               if ((Rctl == 0) && (pring->ringno == LPFC_ELS_RING) &&
+-                      (irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX ||
+-                       irsp->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
++                      (irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX)) {
+                       Rctl = FC_ELS_REQ;
+                       Type = FC_ELS_DATA;
+                       w5p->hcsw.Rctl = Rctl;
+                       w5p->hcsw.Type = Type;
+               }
+       }
+-
+-      if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
+-              if (irsp->ulpBdeCount != 0)
+-                      saveq->context2 = lpfc_sli_replace_hbqbuff(phba,
+-                                              irsp->un.ulpWord[3]);
+-              if (irsp->ulpBdeCount == 2)
+-                      saveq->context3 = lpfc_sli_replace_hbqbuff(phba,
+-                                              irsp->un.ulpWord[15]);
+-      }
+-
+       /* unSolicited Responses */
+       if (pring->prt[0].profile) {
+               if (pring->prt[0].lpfc_sli_rcv_unsol_event)
+@@ -995,21 +781,23 @@
+               /* Unexpected Rctl / Type received */
+               /* Ring <ringno> handler: unexpected
+                  Rctl <Rctl> Type <Type> received */
+-              lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
++              lpfc_printf_log(phba,
++                              KERN_WARNING,
++                              LOG_SLI,
+                               "%d:0313 Ring %d handler: unexpected Rctl x%x "
+-                              "Type x%x received\n",
++                              "Type x%x received \n",
+                               phba->brd_no,
+                               pring->ringno,
+                               Rctl,
+                               Type);
+       }
+-      return 1;
++      return(1);
+ }
+ static struct lpfc_iocbq *
+-lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
+-                    struct lpfc_sli_ring *pring,
+-                    struct lpfc_iocbq *prspiocb)
++lpfc_sli_iocbq_lookup(struct lpfc_hba * phba,
++                    struct lpfc_sli_ring * pring,
++                    struct lpfc_iocbq * prspiocb)
+ {
+       struct lpfc_iocbq *cmd_iocb = NULL;
+       uint16_t iotag;
+@@ -1018,7 +806,7 @@
+       if (iotag != 0 && iotag <= phba->sli.last_iotag) {
+               cmd_iocb = phba->sli.iocbq_lookup[iotag];
+-              list_del_init(&cmd_iocb->list);
++              list_del(&cmd_iocb->list);
+               pring->txcmplq_cnt--;
+               return cmd_iocb;
+       }
+@@ -1033,18 +821,16 @@
+ }
+ static int
+-lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
++lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
+                         struct lpfc_iocbq *saveq)
+ {
+-      struct lpfc_iocbq *cmdiocbp;
++      struct lpfc_iocbq * cmdiocbp;
+       int rc = 1;
+       unsigned long iflag;
+       /* Based on the iotag field, get the cmd IOCB from the txcmplq */
+-      spin_lock_irqsave(&phba->hbalock, iflag);
++      spin_lock_irqsave(phba->host->host_lock, iflag);
+       cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
+-      spin_unlock_irqrestore(&phba->hbalock, iflag);
+-
+       if (cmdiocbp) {
+               if (cmdiocbp->iocb_cmpl) {
+                       /*
+@@ -1060,8 +846,17 @@
+                                       saveq->iocb.un.ulpWord[4] =
+                                               IOERR_SLI_ABORTED;
+                               }
++                              spin_unlock_irqrestore(phba->host->host_lock,
++                                                     iflag);
++                              (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
++                              spin_lock_irqsave(phba->host->host_lock, iflag);
+                       }
++                      else {
++                              spin_unlock_irqrestore(phba->host->host_lock,
++                                                     iflag);
+                               (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
++                              spin_lock_irqsave(phba->host->host_lock, iflag);
++                      }
+               } else
+                       lpfc_sli_release_iocbq(phba, cmdiocbp);
+       } else {
+@@ -1075,12 +870,12 @@
+                        * Ring <ringno> handler: unexpected completion IoTag
+                        * <IoTag>
+                        */
+-                      lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+-                                      "%d (%d):0322 Ring %d handler: "
+-                                      "unexpected completion IoTag x%x "
+-                                      "Data: x%x x%x x%x x%x\n",
++                      lpfc_printf_log(phba,
++                              KERN_WARNING,
++                              LOG_SLI,
++                              "%d:0322 Ring %d handler: unexpected "
++                              "completion IoTag x%x Data: x%x x%x x%x x%x\n",
+                               phba->brd_no,
+-                                      cmdiocbp->vport->vpi,
+                               pring->ringno,
+                               saveq->iocb.ulpIoTag,
+                               saveq->iocb.ulpStatus,
+@@ -1090,15 +885,14 @@
+               }
+       }
++      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+       return rc;
+ }
+-static void
+-lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
++static void lpfc_sli_rsp_pointers_error(struct lpfc_hba * phba,
++                                      struct lpfc_sli_ring * pring)
+ {
+-      struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
+-              &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
+-              &phba->slim2p->mbx.us.s2.port[pring->ringno];
++      struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
+       /*
+        * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
+        * rsp ring <portRspMax>
+@@ -1110,7 +904,7 @@
+                       le32_to_cpu(pgp->rspPutInx),
+                       pring->numRiocb);
+-      phba->link_state = LPFC_HBA_ERROR;
++      phba->hba_state = LPFC_HBA_ERROR;
+       /*
+        * All error attention handlers are posted to
+@@ -1118,18 +912,16 @@
+        */
+       phba->work_ha |= HA_ERATT;
+       phba->work_hs = HS_FFER3;
+-
+-      /* hbalock should already be held */
+       if (phba->work_wait)
+-              lpfc_worker_wake_up(phba);
++              wake_up(phba->work_wait);
+       return;
+ }
+-void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
++void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
+ {
+-      struct lpfc_sli      *psli  = &phba->sli;
+-      struct lpfc_sli_ring *pring = &psli->ring[LPFC_FCP_RING];
++      struct lpfc_sli      * psli   = &phba->sli;
++      struct lpfc_sli_ring * pring = &psli->ring[LPFC_FCP_RING];
+       IOCB_t *irsp = NULL;
+       IOCB_t *entry = NULL;
+       struct lpfc_iocbq *cmdiocbq = NULL;
+@@ -1139,15 +931,13 @@
+       uint32_t portRspPut, portRspMax;
+       int type;
+       uint32_t rsp_cmpl = 0;
++      void __iomem *to_slim;
+       uint32_t ha_copy;
+-      unsigned long iflags;
+       pring->stats.iocb_event++;
+-      pgp = (phba->sli_rev == 3) ?
+-              &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
+-              &phba->slim2p->mbx.us.s2.port[pring->ringno];
+-
++      /* The driver assumes SLI-2 mode */
++      pgp =  &phba->slim2p->mbx.us.s2.port[pring->ringno];
+       /*
+        * The next available response entry should never exceed the maximum
+@@ -1162,13 +952,15 @@
+       rmb();
+       while (pring->rspidx != portRspPut) {
+-              entry = lpfc_resp_iocb(phba, pring);
 +
-+struct address_space_operations unionfs_aops = {
-+      .writepage      = unionfs_writepage,
-+      .readpage       = unionfs_readpage,
-+      .prepare_write  = unionfs_prepare_write,
-+      .commit_write   = unionfs_commit_write,
-+      .sync_page      = unionfs_sync_page,
-+};
-diff -Nurb linux-2.6.22-570/fs/unionfs/rdstate.c linux-2.6.22-590/fs/unionfs/rdstate.c
---- linux-2.6.22-570/fs/unionfs/rdstate.c      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/rdstate.c      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,282 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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.
-+ */
++              entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
 +
-+#include "union.h"
+               if (++pring->rspidx >= portRspMax)
+                       pring->rspidx = 0;
+               lpfc_sli_pcimem_bcopy((uint32_t *) entry,
+                                     (uint32_t *) &rspiocbq.iocb,
+-                                    phba->iocb_rsp_size);
++                                    sizeof (IOCB_t));
+               irsp = &rspiocbq.iocb;
+               type = lpfc_sli_iocb_cmd_type(irsp->ulpCommand & CMD_IOCB_MASK);
+               pring->stats.iocb_rsp++;
+@@ -1206,10 +998,8 @@
+                               break;
+                       }
+-                      spin_lock_irqsave(&phba->hbalock, iflags);
+                       cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
+                                                        &rspiocbq);
+-                      spin_unlock_irqrestore(&phba->hbalock, iflags);
+                       if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) {
+                               (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
+                                                     &rspiocbq);
+@@ -1243,7 +1033,9 @@
+                * been updated, sync the pgp->rspPutInx and fetch the new port
+                * response put pointer.
+                */
+-              writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
++              to_slim = phba->MBslimaddr +
++                      (SLIMOFF + (pring->ringno * 2) + 1) * 4;
++              writeb(pring->rspidx, to_slim);
+               if (pring->rspidx == portRspPut)
+                       portRspPut = le32_to_cpu(pgp->rspPutInx);
+@@ -1253,16 +1045,13 @@
+       ha_copy >>= (LPFC_FCP_RING * 4);
+       if ((rsp_cmpl > 0) && (ha_copy & HA_R0RE_REQ)) {
+-              spin_lock_irqsave(&phba->hbalock, iflags);
+               pring->stats.iocb_rsp_full++;
+               status = ((CA_R0ATT | CA_R0RE_RSP) << (LPFC_FCP_RING * 4));
+               writel(status, phba->CAregaddr);
+               readl(phba->CAregaddr);
+-              spin_unlock_irqrestore(&phba->hbalock, iflags);
+       }
+       if ((ha_copy & HA_R0CE_RSP) &&
+           (pring->flag & LPFC_CALL_RING_AVAILABLE)) {
+-              spin_lock_irqsave(&phba->hbalock, iflags);
+               pring->flag &= ~LPFC_CALL_RING_AVAILABLE;
+               pring->stats.iocb_cmd_empty++;
+@@ -1273,7 +1062,6 @@
+               if ((pring->lpfc_sli_cmd_available))
+                       (pring->lpfc_sli_cmd_available) (phba, pring);
+-              spin_unlock_irqrestore(&phba->hbalock, iflags);
+       }
+       return;
+@@ -1284,12 +1072,10 @@
+  * to check it explicitly.
+  */
+ static int
+-lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
+-                              struct lpfc_sli_ring *pring, uint32_t mask)
++lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
++                              struct lpfc_sli_ring * pring, uint32_t mask)
+ {
+-      struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
+-              &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
+-              &phba->slim2p->mbx.us.s2.port[pring->ringno];
++      struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
+       IOCB_t *irsp = NULL;
+       IOCB_t *entry = NULL;
+       struct lpfc_iocbq *cmdiocbq = NULL;
+@@ -1300,8 +1086,9 @@
+       lpfc_iocb_type type;
+       unsigned long iflag;
+       uint32_t rsp_cmpl = 0;
++      void __iomem  *to_slim;
+-      spin_lock_irqsave(&phba->hbalock, iflag);
++      spin_lock_irqsave(phba->host->host_lock, iflag);
+       pring->stats.iocb_event++;
+       /*
+@@ -1312,7 +1099,7 @@
+       portRspPut = le32_to_cpu(pgp->rspPutInx);
+       if (unlikely(portRspPut >= portRspMax)) {
+               lpfc_sli_rsp_pointers_error(phba, pring);
+-              spin_unlock_irqrestore(&phba->hbalock, iflag);
++              spin_unlock_irqrestore(phba->host->host_lock, iflag);
+               return 1;
+       }
+@@ -1323,15 +1110,14 @@
+                * structure.  The copy involves a byte-swap since the
+                * network byte order and pci byte orders are different.
+                */
+-              entry = lpfc_resp_iocb(phba, pring);
+-              phba->last_completion_time = jiffies;
++              entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
+               if (++pring->rspidx >= portRspMax)
+                       pring->rspidx = 0;
+               lpfc_sli_pcimem_bcopy((uint32_t *) entry,
+                                     (uint32_t *) &rspiocbq.iocb,
+-                                    phba->iocb_rsp_size);
++                                    sizeof (IOCB_t));
+               INIT_LIST_HEAD(&(rspiocbq.list));
+               irsp = &rspiocbq.iocb;
+@@ -1340,28 +1126,14 @@
+               rsp_cmpl++;
+               if (unlikely(irsp->ulpStatus)) {
+-                      /*
+-                       * If resource errors reported from HBA, reduce
+-                       * queuedepths of the SCSI device.
+-                       */
+-                      if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
+-                              (irsp->un.ulpWord[4] == IOERR_NO_RESOURCES)) {
+-                              spin_unlock_irqrestore(&phba->hbalock, iflag);
+-                              lpfc_adjust_queue_depth(phba);
+-                              spin_lock_irqsave(&phba->hbalock, iflag);
+-                      }
+-
+                       /* Rsp ring <ringno> error: IOCB */
+                       lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+                               "%d:0336 Rsp Ring %d error: IOCB Data: "
+                               "x%x x%x x%x x%x x%x x%x x%x x%x\n",
+                               phba->brd_no, pring->ringno,
+-                                      irsp->un.ulpWord[0],
+-                                      irsp->un.ulpWord[1],
+-                                      irsp->un.ulpWord[2],
+-                                      irsp->un.ulpWord[3],
+-                                      irsp->un.ulpWord[4],
+-                                      irsp->un.ulpWord[5],
++                              irsp->un.ulpWord[0], irsp->un.ulpWord[1],
++                              irsp->un.ulpWord[2], irsp->un.ulpWord[3],
++                              irsp->un.ulpWord[4], irsp->un.ulpWord[5],
+                               *(((uint32_t *) irsp) + 6),
+                               *(((uint32_t *) irsp) + 7));
+               }
+@@ -1377,8 +1149,7 @@
+                               lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                                               "%d:0333 IOCB cmd 0x%x"
+                                               " processed. Skipping"
+-                                              " completion\n",
+-                                              phba->brd_no,
++                                              " completion\n", phba->brd_no,
+                                               irsp->ulpCommand);
+                               break;
+                       }
+@@ -1390,19 +1161,19 @@
+                                       (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
+                                                             &rspiocbq);
+                               } else {
+-                                      spin_unlock_irqrestore(&phba->hbalock,
+-                                                             iflag);
++                                      spin_unlock_irqrestore(
++                                              phba->host->host_lock, iflag);
+                                       (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
+                                                             &rspiocbq);
+-                                      spin_lock_irqsave(&phba->hbalock,
++                                      spin_lock_irqsave(phba->host->host_lock,
+                                                         iflag);
+                               }
+                       }
+                       break;
+               case LPFC_UNSOL_IOCB:
+-                      spin_unlock_irqrestore(&phba->hbalock, iflag);
++                      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+                       lpfc_sli_process_unsol_iocb(phba, pring, &rspiocbq);
+-                      spin_lock_irqsave(&phba->hbalock, iflag);
++                      spin_lock_irqsave(phba->host->host_lock, iflag);
+                       break;
+               default:
+                       if (irsp->ulpCommand == CMD_ADAPTER_MSG) {
+@@ -1417,10 +1188,8 @@
+                               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                                       "%d:0334 Unknown IOCB command "
+                                       "Data: x%x, x%x x%x x%x x%x\n",
+-                                              phba->brd_no, type,
+-                                              irsp->ulpCommand,
+-                                              irsp->ulpStatus,
+-                                              irsp->ulpIoTag,
++                                      phba->brd_no, type, irsp->ulpCommand,
++                                      irsp->ulpStatus, irsp->ulpIoTag,
+                                       irsp->ulpContext);
+                       }
+                       break;
+@@ -1432,7 +1201,9 @@
+                * been updated, sync the pgp->rspPutInx and fetch the new port
+                * response put pointer.
+                */
+-              writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
++              to_slim = phba->MBslimaddr +
++                      (SLIMOFF + (pring->ringno * 2) + 1) * 4;
++              writel(pring->rspidx, to_slim);
+               if (pring->rspidx == portRspPut)
+                       portRspPut = le32_to_cpu(pgp->rspPutInx);
+@@ -1457,31 +1228,31 @@
+       }
+-      spin_unlock_irqrestore(&phba->hbalock, iflag);
++      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+       return rc;
+ }
 +
-+/* This file contains the routines for maintaining readdir state. */
+ int
+-lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
+-                              struct lpfc_sli_ring *pring, uint32_t mask)
++lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
++                         struct lpfc_sli_ring * pring, uint32_t mask)
+ {
+-      struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
+-              &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
+-              &phba->slim2p->mbx.us.s2.port[pring->ringno];
+       IOCB_t *entry;
+       IOCB_t *irsp = NULL;
+       struct lpfc_iocbq *rspiocbp = NULL;
+       struct lpfc_iocbq *next_iocb;
+       struct lpfc_iocbq *cmdiocbp;
+       struct lpfc_iocbq *saveq;
++      struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
+       uint8_t iocb_cmd_type;
+       lpfc_iocb_type type;
+       uint32_t status, free_saveq;
+       uint32_t portRspPut, portRspMax;
+       int rc = 1;
+       unsigned long iflag;
++      void __iomem  *to_slim;
+-      spin_lock_irqsave(&phba->hbalock, iflag);
++      spin_lock_irqsave(phba->host->host_lock, iflag);
+       pring->stats.iocb_event++;
+       /*
+@@ -1495,14 +1266,16 @@
+                * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
+                * rsp ring <portRspMax>
+                */
+-              lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
++              lpfc_printf_log(phba,
++                              KERN_ERR,
++                              LOG_SLI,
+                               "%d:0303 Ring %d handler: portRspPut %d "
+                               "is bigger then rsp ring %d\n",
+-                              phba->brd_no, pring->ringno, portRspPut,
+-                              portRspMax);
++                              phba->brd_no,
++                              pring->ringno, portRspPut, portRspMax);
+-              phba->link_state = LPFC_HBA_ERROR;
+-              spin_unlock_irqrestore(&phba->hbalock, iflag);
++              phba->hba_state = LPFC_HBA_ERROR;
++              spin_unlock_irqrestore(phba->host->host_lock, iflag);
+               phba->work_hs = HS_FFER3;
+               lpfc_handle_eratt(phba);
+@@ -1525,24 +1298,23 @@
+                * the ulpLe field is set, the entire Command has been
+                * received.
+                */
+-              entry = lpfc_resp_iocb(phba, pring);
+-
+-              phba->last_completion_time = jiffies;
+-              rspiocbp = __lpfc_sli_get_iocbq(phba);
++              entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
++              rspiocbp = lpfc_sli_get_iocbq(phba);
+               if (rspiocbp == NULL) {
+                       printk(KERN_ERR "%s: out of buffers! Failing "
+                              "completion.\n", __FUNCTION__);
+                       break;
+               }
+-              lpfc_sli_pcimem_bcopy(entry, &rspiocbp->iocb,
+-                                    phba->iocb_rsp_size);
++              lpfc_sli_pcimem_bcopy(entry, &rspiocbp->iocb, sizeof (IOCB_t));
+               irsp = &rspiocbp->iocb;
+               if (++pring->rspidx >= portRspMax)
+                       pring->rspidx = 0;
+-              writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
++              to_slim = phba->MBslimaddr + (SLIMOFF + (pring->ringno * 2)
++                                            + 1) * 4;
++              writel(pring->rspidx, to_slim);
+               if (list_empty(&(pring->iocb_continueq))) {
+                       list_add(&rspiocbp->list, &(pring->iocb_continueq));
+@@ -1566,26 +1338,13 @@
+                       pring->stats.iocb_rsp++;
+-                      /*
+-                       * If resource errors reported from HBA, reduce
+-                       * queuedepths of the SCSI device.
+-                       */
+-                      if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
+-                           (irsp->un.ulpWord[4] == IOERR_NO_RESOURCES)) {
+-                              spin_unlock_irqrestore(&phba->hbalock, iflag);
+-                              lpfc_adjust_queue_depth(phba);
+-                              spin_lock_irqsave(&phba->hbalock, iflag);
+-                      }
+-
+                       if (irsp->ulpStatus) {
+                               /* Rsp ring <ringno> error: IOCB */
+-                              lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+-                                              "%d:0328 Rsp Ring %d error: "
+-                                              "IOCB Data: "
+-                                              "x%x x%x x%x x%x "
+-                                              "x%x x%x x%x x%x "
+-                                              "x%x x%x x%x x%x "
+-                                              "x%x x%x x%x x%x\n",
++                              lpfc_printf_log(phba,
++                                      KERN_WARNING,
++                                      LOG_SLI,
++                                      "%d:0328 Rsp Ring %d error: IOCB Data: "
++                                      "x%x x%x x%x x%x x%x x%x x%x x%x\n",
+                                       phba->brd_no,
+                                       pring->ringno,
+                                       irsp->un.ulpWord[0],
+@@ -1595,15 +1354,7 @@
+                                       irsp->un.ulpWord[4],
+                                       irsp->un.ulpWord[5],
+                                       *(((uint32_t *) irsp) + 6),
+-                                              *(((uint32_t *) irsp) + 7),
+-                                              *(((uint32_t *) irsp) + 8),
+-                                              *(((uint32_t *) irsp) + 9),
+-                                              *(((uint32_t *) irsp) + 10),
+-                                              *(((uint32_t *) irsp) + 11),
+-                                              *(((uint32_t *) irsp) + 12),
+-                                              *(((uint32_t *) irsp) + 13),
+-                                              *(((uint32_t *) irsp) + 14),
+-                                              *(((uint32_t *) irsp) + 15));
++                                      *(((uint32_t *) irsp) + 7));
+                       }
+                       /*
+@@ -1615,17 +1366,17 @@
+                       iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK;
+                       type = lpfc_sli_iocb_cmd_type(iocb_cmd_type);
+                       if (type == LPFC_SOL_IOCB) {
+-                              spin_unlock_irqrestore(&phba->hbalock,
++                              spin_unlock_irqrestore(phba->host->host_lock,
+                                                      iflag);
+                               rc = lpfc_sli_process_sol_iocb(phba, pring,
+                                       saveq);
+-                              spin_lock_irqsave(&phba->hbalock, iflag);
++                              spin_lock_irqsave(phba->host->host_lock, iflag);
+                       } else if (type == LPFC_UNSOL_IOCB) {
+-                              spin_unlock_irqrestore(&phba->hbalock,
++                              spin_unlock_irqrestore(phba->host->host_lock,
+                                                      iflag);
+                               rc = lpfc_sli_process_unsol_iocb(phba, pring,
+                                       saveq);
+-                              spin_lock_irqsave(&phba->hbalock, iflag);
++                              spin_lock_irqsave(phba->host->host_lock, iflag);
+                       } else if (type == LPFC_ABORT_IOCB) {
+                               if ((irsp->ulpCommand != CMD_XRI_ABORTED_CX) &&
+                                   ((cmdiocbp =
+@@ -1635,15 +1386,15 @@
+                                          routine */
+                                       if (cmdiocbp->iocb_cmpl) {
+                                               spin_unlock_irqrestore(
+-                                                     &phba->hbalock,
++                                                     phba->host->host_lock,
+                                                      iflag);
+                                               (cmdiocbp->iocb_cmpl) (phba,
+                                                            cmdiocbp, saveq);
+                                               spin_lock_irqsave(
+-                                                        &phba->hbalock,
++                                                        phba->host->host_lock,
+                                                         iflag);
+                                       } else
+-                                              __lpfc_sli_release_iocbq(phba,
++                                              lpfc_sli_release_iocbq(phba,
+                                                                     cmdiocbp);
+                               }
+                       } else if (type == LPFC_UNKNOWN_IOCB) {
+@@ -1660,10 +1411,11 @@
+                                                phba->brd_no, adaptermsg);
+                               } else {
+                                       /* Unknown IOCB command */
+-                                      lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+-                                                      "%d:0335 Unknown IOCB "
+-                                                      "command Data: x%x "
+-                                                      "x%x x%x x%x\n",
++                                      lpfc_printf_log(phba,
++                                              KERN_ERR,
++                                              LOG_SLI,
++                                              "%d:0335 Unknown IOCB command "
++                                              "Data: x%x x%x x%x x%x\n",
+                                               phba->brd_no,
+                                               irsp->ulpCommand,
+                                               irsp->ulpStatus,
+@@ -1673,15 +1425,18 @@
+                       }
+                       if (free_saveq) {
+-                              list_for_each_entry_safe(rspiocbp, next_iocb,
+-                                                       &saveq->list, list) {
++                              if (!list_empty(&saveq->list)) {
++                                      list_for_each_entry_safe(rspiocbp,
++                                                               next_iocb,
++                                                               &saveq->list,
++                                                               list) {
+                                               list_del(&rspiocbp->list);
+-                                      __lpfc_sli_release_iocbq(phba,
++                                              lpfc_sli_release_iocbq(phba,
+                                                                    rspiocbp);
+                                       }
+-                              __lpfc_sli_release_iocbq(phba, saveq);
+                               }
+-                      rspiocbp = NULL;
++                              lpfc_sli_release_iocbq(phba, saveq);
++                      }
+               }
+               /*
+@@ -1694,7 +1449,7 @@
+               }
+       } /* while (pring->rspidx != portRspPut) */
+-      if ((rspiocbp != NULL) && (mask & HA_R0RE_REQ)) {
++      if ((rspiocbp != 0) && (mask & HA_R0RE_REQ)) {
+               /* At least one response entry has been freed */
+               pring->stats.iocb_rsp_full++;
+               /* SET RxRE_RSP in Chip Att register */
+@@ -1715,25 +1470,24 @@
+       }
+-      spin_unlock_irqrestore(&phba->hbalock, iflag);
++      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+       return rc;
+ }
+-void
++int
+ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+ {
+       LIST_HEAD(completions);
+       struct lpfc_iocbq *iocb, *next_iocb;
+       IOCB_t *cmd = NULL;
++      int errcnt;
+-      if (pring->ringno == LPFC_ELS_RING) {
+-              lpfc_fabric_abort_hba(phba);
+-      }
++      errcnt = 0;
+       /* Error everything on txq and txcmplq
+        * First do the txq.
+        */
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       list_splice_init(&pring->txq, &completions);
+       pring->txq_cnt = 0;
+@@ -1741,25 +1495,26 @@
+       list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
+               lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       while (!list_empty(&completions)) {
+               iocb = list_get_first(&completions, struct lpfc_iocbq, list);
+               cmd = &iocb->iocb;
+-              list_del_init(&iocb->list);
++              list_del(&iocb->list);
+-              if (!iocb->iocb_cmpl)
+-                      lpfc_sli_release_iocbq(phba, iocb);
+-              else {
++              if (iocb->iocb_cmpl) {
+                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                       cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+                       (iocb->iocb_cmpl) (phba, iocb, iocb);
++              } else
++                      lpfc_sli_release_iocbq(phba, iocb);
+       }
+-      }
 +
-+/*
-+ * There are two structures here, rdstate which is a hash table
-+ * of the second structure which is a filldir_node.
-+ */
++      return errcnt;
+ }
+ int
+-lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask)
++lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
+ {
+       uint32_t status;
+       int i = 0;
+@@ -1786,8 +1541,7 @@
+                       msleep(2500);
+               if (i == 15) {
+-                              /* Do post */
+-                      phba->pport->port_state = LPFC_VPORT_UNKNOWN;
++                      phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
+                       lpfc_sli_brdrestart(phba);
+               }
+               /* Read the HBA Host Status Register */
+@@ -1796,7 +1550,7 @@
+       /* Check to see if any errors occurred during init */
+       if ((status & HS_FFERM) || (i >= 20)) {
+-              phba->link_state = LPFC_HBA_ERROR;
++              phba->hba_state = LPFC_HBA_ERROR;
+               retval = 1;
+       }
+@@ -1805,7 +1559,7 @@
+ #define BARRIER_TEST_PATTERN (0xdeadbeef)
+-void lpfc_reset_barrier(struct lpfc_hba *phba)
++void lpfc_reset_barrier(struct lpfc_hba * phba)
+ {
+       uint32_t __iomem *resp_buf;
+       uint32_t __iomem *mbox_buf;
+@@ -1830,12 +1584,12 @@
+       hc_copy = readl(phba->HCregaddr);
+       writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
+       readl(phba->HCregaddr); /* flush */
+-      phba->link_flag |= LS_IGNORE_ERATT;
++      phba->fc_flag |= FC_IGNORE_ERATT;
+       if (readl(phba->HAregaddr) & HA_ERATT) {
+               /* Clear Chip error bit */
+               writel(HA_ERATT, phba->HAregaddr);
+-              phba->pport->stopped = 1;
++              phba->stopped = 1;
+       }
+       mbox = 0;
+@@ -1852,7 +1606,7 @@
+       if (readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN)) {
+               if (phba->sli.sli_flag & LPFC_SLI2_ACTIVE ||
+-                  phba->pport->stopped)
++                  phba->stopped)
+                       goto restore_hc;
+               else
+                       goto clear_errat;
+@@ -1869,17 +1623,17 @@
+       if (readl(phba->HAregaddr) & HA_ERATT) {
+               writel(HA_ERATT, phba->HAregaddr);
+-              phba->pport->stopped = 1;
++              phba->stopped = 1;
+       }
+ restore_hc:
+-      phba->link_flag &= ~LS_IGNORE_ERATT;
++      phba->fc_flag &= ~FC_IGNORE_ERATT;
+       writel(hc_copy, phba->HCregaddr);
+       readl(phba->HCregaddr); /* flush */
+ }
+ int
+-lpfc_sli_brdkill(struct lpfc_hba *phba)
++lpfc_sli_brdkill(struct lpfc_hba * phba)
+ {
+       struct lpfc_sli *psli;
+       LPFC_MBOXQ_t *pmb;
+@@ -1891,22 +1645,26 @@
+       psli = &phba->sli;
+       /* Kill HBA */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
++      lpfc_printf_log(phba,
++              KERN_INFO,
++              LOG_SLI,
+               "%d:0329 Kill HBA Data: x%x x%x\n",
+-                      phba->brd_no, phba->pport->port_state, psli->sli_flag);
++              phba->brd_no,
++              phba->hba_state,
++              psli->sli_flag);
+       if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
+                                                 GFP_KERNEL)) == 0)
+               return 1;
+       /* Disable the error attention */
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       status = readl(phba->HCregaddr);
+       status &= ~HC_ERINT_ENA;
+       writel(status, phba->HCregaddr);
+       readl(phba->HCregaddr); /* flush */
+-      phba->link_flag |= LS_IGNORE_ERATT;
+-      spin_unlock_irq(&phba->hbalock);
++      phba->fc_flag |= FC_IGNORE_ERATT;
++      spin_unlock_irq(phba->host->host_lock);
+       lpfc_kill_board(phba, pmb);
+       pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+@@ -1915,9 +1673,9 @@
+       if (retval != MBX_SUCCESS) {
+               if (retval != MBX_BUSY)
+                       mempool_free(pmb, phba->mbox_mem_pool);
+-              spin_lock_irq(&phba->hbalock);
+-              phba->link_flag &= ~LS_IGNORE_ERATT;
+-              spin_unlock_irq(&phba->hbalock);
++              spin_lock_irq(phba->host->host_lock);
++              phba->fc_flag &= ~FC_IGNORE_ERATT;
++              spin_unlock_irq(phba->host->host_lock);
+               return 1;
+       }
+@@ -1940,22 +1698,22 @@
+       del_timer_sync(&psli->mbox_tmo);
+       if (ha_copy & HA_ERATT) {
+               writel(HA_ERATT, phba->HAregaddr);
+-              phba->pport->stopped = 1;
++              phba->stopped = 1;
+       }
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+-      phba->link_flag &= ~LS_IGNORE_ERATT;
+-      spin_unlock_irq(&phba->hbalock);
++      phba->fc_flag &= ~FC_IGNORE_ERATT;
++      spin_unlock_irq(phba->host->host_lock);
+       psli->mbox_active = NULL;
+       lpfc_hba_down_post(phba);
+-      phba->link_state = LPFC_HBA_ERROR;
++      phba->hba_state = LPFC_HBA_ERROR;
+-      return ha_copy & HA_ERATT ? 0 : 1;
++      return (ha_copy & HA_ERATT ? 0 : 1);
+ }
+ int
+-lpfc_sli_brdreset(struct lpfc_hba *phba)
++lpfc_sli_brdreset(struct lpfc_hba * phba)
+ {
+       struct lpfc_sli *psli;
+       struct lpfc_sli_ring *pring;
+@@ -1967,12 +1725,12 @@
+       /* Reset HBA */
+       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                       "%d:0325 Reset HBA Data: x%x x%x\n", phba->brd_no,
+-                      phba->pport->port_state, psli->sli_flag);
++                      phba->hba_state, psli->sli_flag);
+       /* perform board reset */
+       phba->fc_eventTag = 0;
+-      phba->pport->fc_myDID = 0;
+-      phba->pport->fc_prevDID = 0;
++      phba->fc_myDID = 0;
++      phba->fc_prevDID = 0;
+       /* Turn off parity checking and serr during the physical reset */
+       pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
+@@ -2002,12 +1760,12 @@
+               pring->missbufcnt = 0;
+       }
+-      phba->link_state = LPFC_WARM_START;
++      phba->hba_state = LPFC_WARM_START;
+       return 0;
+ }
+ int
+-lpfc_sli_brdrestart(struct lpfc_hba *phba)
++lpfc_sli_brdrestart(struct lpfc_hba * phba)
+ {
+       MAILBOX_t *mb;
+       struct lpfc_sli *psli;
+@@ -2015,14 +1773,14 @@
+       volatile uint32_t word0;
+       void __iomem *to_slim;
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       psli = &phba->sli;
+       /* Restart HBA */
+       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                       "%d:0337 Restart HBA Data: x%x x%x\n", phba->brd_no,
+-                      phba->pport->port_state, psli->sli_flag);
++                      phba->hba_state, psli->sli_flag);
+       word0 = 0;
+       mb = (MAILBOX_t *) &word0;
+@@ -2036,7 +1794,7 @@
+       readl(to_slim); /* flush */
+       /* Only skip post after fc_ffinit is completed */
+-      if (phba->pport->port_state) {
++      if (phba->hba_state) {
+               skip_post = 1;
+               word0 = 1;      /* This is really setting up word1 */
+       } else {
+@@ -2048,10 +1806,10 @@
+       readl(to_slim); /* flush */
+       lpfc_sli_brdreset(phba);
+-      phba->pport->stopped = 0;
+-      phba->link_state = LPFC_INIT_START;
++      phba->stopped = 0;
++      phba->hba_state = LPFC_INIT_START;
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets));
+       psli->stats_start = get_seconds();
+@@ -2085,11 +1843,14 @@
+               if (i++ >= 20) {
+                       /* Adapter failed to init, timeout, status reg
+                          <status> */
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
++                      lpfc_printf_log(phba,
++                                      KERN_ERR,
++                                      LOG_INIT,
+                                       "%d:0436 Adapter failed to init, "
+                                       "timeout, status reg x%x\n",
+-                                      phba->brd_no, status);
+-                      phba->link_state = LPFC_HBA_ERROR;
++                                      phba->brd_no,
++                                      status);
++                      phba->hba_state = LPFC_HBA_ERROR;
+                       return -ETIMEDOUT;
+               }
+@@ -2098,12 +1859,14 @@
+                       /* ERROR: During chipset initialization */
+                       /* Adapter failed to init, chipset, status reg
+                          <status> */
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
++                      lpfc_printf_log(phba,
++                                      KERN_ERR,
++                                      LOG_INIT,
+                                       "%d:0437 Adapter failed to init, "
+                                       "chipset, status reg x%x\n",
+                                       phba->brd_no,
+                                       status);
+-                      phba->link_state = LPFC_HBA_ERROR;
++                      phba->hba_state = LPFC_HBA_ERROR;
+                       return -EIO;
+               }
+@@ -2116,8 +1879,7 @@
+               }
+               if (i == 15) {
+-                              /* Do post */
+-                      phba->pport->port_state = LPFC_VPORT_UNKNOWN;
++                      phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
+                       lpfc_sli_brdrestart(phba);
+               }
+               /* Read the HBA Host Status Register */
+@@ -2128,12 +1890,14 @@
+       if (status & HS_FFERM) {
+               /* ERROR: During chipset initialization */
+               /* Adapter failed to init, chipset, status reg <status> */
+-              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
++              lpfc_printf_log(phba,
++                              KERN_ERR,
++                              LOG_INIT,
+                               "%d:0438 Adapter failed to init, chipset, "
+                               "status reg x%x\n",
+                               phba->brd_no,
+                               status);
+-              phba->link_state = LPFC_HBA_ERROR;
++              phba->hba_state = LPFC_HBA_ERROR;
+               return -EIO;
+       }
+@@ -2147,253 +1911,80 @@
+       return 0;
+ }
+-static int
+-lpfc_sli_hbq_count(void)
+-{
+-      return ARRAY_SIZE(lpfc_hbq_defs);
+-}
+-
+-static int
+-lpfc_sli_hbq_entry_count(void)
+-{
+-      int  hbq_count = lpfc_sli_hbq_count();
+-      int  count = 0;
+-      int  i;
+-
+-      for (i = 0; i < hbq_count; ++i)
+-              count += lpfc_hbq_defs[i]->entry_count;
+-      return count;
+-}
+-
+ int
+-lpfc_sli_hbq_size(void)
+-{
+-      return lpfc_sli_hbq_entry_count() * sizeof(struct lpfc_hbq_entry);
+-}
+-
+-static int
+-lpfc_sli_hbq_setup(struct lpfc_hba *phba)
+-{
+-      int  hbq_count = lpfc_sli_hbq_count();
+-      LPFC_MBOXQ_t *pmb;
+-      MAILBOX_t *pmbox;
+-      uint32_t hbqno;
+-      uint32_t hbq_entry_index;
+-
+-                              /* Get a Mailbox buffer to setup mailbox
+-                               * commands for HBA initialization
+-                               */
+-      pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-
+-      if (!pmb)
+-              return -ENOMEM;
+-
+-      pmbox = &pmb->mb;
+-
+-      /* Initialize the struct lpfc_sli_hbq structure for each hbq */
+-      phba->link_state = LPFC_INIT_MBX_CMDS;
+-
+-      hbq_entry_index = 0;
+-      for (hbqno = 0; hbqno < hbq_count; ++hbqno) {
+-              phba->hbqs[hbqno].next_hbqPutIdx = 0;
+-              phba->hbqs[hbqno].hbqPutIdx      = 0;
+-              phba->hbqs[hbqno].local_hbqGetIdx   = 0;
+-              phba->hbqs[hbqno].entry_count =
+-                      lpfc_hbq_defs[hbqno]->entry_count;
+-              lpfc_config_hbq(phba, lpfc_hbq_defs[hbqno], hbq_entry_index,
+-                              pmb);
+-              hbq_entry_index += phba->hbqs[hbqno].entry_count;
+-
+-              if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
+-                      /* Adapter failed to init, mbxCmd <cmd> CFG_RING,
+-                         mbxStatus <status>, ring <num> */
+-
+-                      lpfc_printf_log(phba, KERN_ERR,
+-                                      LOG_SLI | LOG_VPORT,
+-                                      "%d:1805 Adapter failed to init. "
+-                                      "Data: x%x x%x x%x\n",
+-                                      phba->brd_no, pmbox->mbxCommand,
+-                                      pmbox->mbxStatus, hbqno);
+-
+-                      phba->link_state = LPFC_HBA_ERROR;
+-                      mempool_free(pmb, phba->mbox_mem_pool);
+-                      return ENXIO;
+-              }
+-      }
+-      phba->hbq_count = hbq_count;
+-
+-      mempool_free(pmb, phba->mbox_mem_pool);
+-
+-      /* Initially populate or replenish the HBQs */
+-      for (hbqno = 0; hbqno < hbq_count; ++hbqno) {
+-              if (lpfc_sli_hbqbuf_init_hbqs(phba, hbqno))
+-                      return -ENOMEM;
+-      }
+-      return 0;
+-}
+-
+-static int
+-lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode)
++lpfc_sli_hba_setup(struct lpfc_hba * phba)
+ {
+       LPFC_MBOXQ_t *pmb;
+       uint32_t resetcount = 0, rc = 0, done = 0;
+       pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!pmb) {
+-              phba->link_state = LPFC_HBA_ERROR;
++              phba->hba_state = LPFC_HBA_ERROR;
+               return -ENOMEM;
+       }
+-      phba->sli_rev = sli_mode;
+       while (resetcount < 2 && !done) {
+-              spin_lock_irq(&phba->hbalock);
++              spin_lock_irq(phba->host->host_lock);
+               phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE;
+-              spin_unlock_irq(&phba->hbalock);
+-              phba->pport->port_state = LPFC_VPORT_UNKNOWN;
++              spin_unlock_irq(phba->host->host_lock);
++              phba->hba_state = LPFC_STATE_UNKNOWN;
+               lpfc_sli_brdrestart(phba);
+               msleep(2500);
+               rc = lpfc_sli_chipset_init(phba);
+               if (rc)
+                       break;
+-              spin_lock_irq(&phba->hbalock);
++              spin_lock_irq(phba->host->host_lock);
+               phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+-              spin_unlock_irq(&phba->hbalock);
++              spin_unlock_irq(phba->host->host_lock);
+               resetcount++;
+-              /* Call pre CONFIG_PORT mailbox command initialization.  A
+-               * value of 0 means the call was successful.  Any other
+-               * nonzero value is a failure, but if ERESTART is returned,
+-               * the driver may reset the HBA and try again.
++      /* Call pre CONFIG_PORT mailbox command initialization.  A value of 0
++       * means the call was successful.  Any other nonzero value is a failure,
++       * but if ERESTART is returned, the driver may reset the HBA and try
++       * again.
+        */
+               rc = lpfc_config_port_prep(phba);
+               if (rc == -ERESTART) {
+-                      phba->link_state = LPFC_LINK_UNKNOWN;
++                      phba->hba_state = 0;
+                       continue;
+               } else if (rc) {
+                       break;
+               }
+-              phba->link_state = LPFC_INIT_MBX_CMDS;
++              phba->hba_state = LPFC_INIT_MBX_CMDS;
+               lpfc_config_port(phba, pmb);
+               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
+-              if (rc != MBX_SUCCESS) {
++              if (rc == MBX_SUCCESS)
++                      done = 1;
++              else {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "%d:0442 Adapter failed to init, mbxCmd x%x "
+                               "CONFIG_PORT, mbxStatus x%x Data: x%x\n",
+                               phba->brd_no, pmb->mb.mbxCommand,
+                               pmb->mb.mbxStatus, 0);
+-                      spin_lock_irq(&phba->hbalock);
+                       phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE;
+-                      spin_unlock_irq(&phba->hbalock);
+-                      rc = -ENXIO;
+-              } else {
+-                      done = 1;
+-                      phba->max_vpi = (phba->max_vpi &&
+-                                       pmb->mb.un.varCfgPort.gmv) != 0
+-                              ? pmb->mb.un.varCfgPort.max_vpi
+-                              : 0;
+               }
+       }
+-
+-      if (!done) {
+-              rc = -EINVAL;
+-              goto do_prep_failed;
+-      }
+-
+-      if ((pmb->mb.un.varCfgPort.sli_mode == 3) &&
+-              (!pmb->mb.un.varCfgPort.cMA)) {
+-              rc = -ENXIO;
+-              goto do_prep_failed;
+-      }
+-      return rc;
+-
+-do_prep_failed:
+-      mempool_free(pmb, phba->mbox_mem_pool);
+-      return rc;
+-}
+-
+-int
+-lpfc_sli_hba_setup(struct lpfc_hba *phba)
+-{
+-      uint32_t rc;
+-      int  mode = 3;
+-
+-      switch (lpfc_sli_mode) {
+-      case 2:
+-              if (phba->cfg_npiv_enable) {
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
+-                              "%d:1824 NPIV enabled: Override lpfc_sli_mode "
+-                              "parameter (%d) to auto (0).\n",
+-                              phba->brd_no, lpfc_sli_mode);
+-                      break;
+-              }
+-              mode = 2;
+-              break;
+-      case 0:
+-      case 3:
+-              break;
+-      default:
+-              lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
+-                              "%d:1819 Unrecognized lpfc_sli_mode "
+-                              "parameter: %d.\n",
+-                              phba->brd_no, lpfc_sli_mode);
+-
+-              break;
+-      }
+-
+-      rc = lpfc_do_config_port(phba, mode);
+-      if (rc && lpfc_sli_mode == 3)
+-              lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
+-                              "%d:1820 Unable to select SLI-3.  "
+-                              "Not supported by adapter.\n",
+-                              phba->brd_no);
+-      if (rc && mode != 2)
+-              rc = lpfc_do_config_port(phba, 2);
+-      if (rc)
++      if (!done)
+               goto lpfc_sli_hba_setup_error;
+-      if (phba->sli_rev == 3) {
+-              phba->iocb_cmd_size = SLI3_IOCB_CMD_SIZE;
+-              phba->iocb_rsp_size = SLI3_IOCB_RSP_SIZE;
+-              phba->sli3_options |= LPFC_SLI3_ENABLED;
+-              phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED;
+-
+-      } else {
+-              phba->iocb_cmd_size = SLI2_IOCB_CMD_SIZE;
+-              phba->iocb_rsp_size = SLI2_IOCB_RSP_SIZE;
+-              phba->sli3_options = 0;
+-      }
+-
+-      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+-                      "%d:0444 Firmware in SLI %x mode. Max_vpi %d\n",
+-                      phba->brd_no, phba->sli_rev, phba->max_vpi);
+-      rc = lpfc_sli_ring_map(phba);
++      rc = lpfc_sli_ring_map(phba, pmb);
+       if (rc)
+               goto lpfc_sli_hba_setup_error;
+-                              /* Init HBQs */
+-
+-      if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
+-              rc = lpfc_sli_hbq_setup(phba);
+-      if (rc)
+-              goto lpfc_sli_hba_setup_error;
+-      }
+-
+       phba->sli.sli_flag |= LPFC_PROCESS_LA;
+       rc = lpfc_config_port_post(phba);
+       if (rc)
+               goto lpfc_sli_hba_setup_error;
+-      return rc;
+-
++      goto lpfc_sli_hba_setup_exit;
+ lpfc_sli_hba_setup_error:
+-      phba->link_state = LPFC_HBA_ERROR;
+-      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+-                      "%d:0445 Firmware initialization failed\n",
+-                      phba->brd_no);
++      phba->hba_state = LPFC_HBA_ERROR;
++lpfc_sli_hba_setup_exit:
++      mempool_free(pmb, phba->mbox_mem_pool);
+       return rc;
+ }
+@@ -2413,43 +2004,44 @@
+ void
+ lpfc_mbox_timeout(unsigned long ptr)
+ {
+-      struct lpfc_hba  *phba = (struct lpfc_hba *) ptr;
++      struct lpfc_hba *phba;
+       unsigned long iflag;
+-      uint32_t tmo_posted;
+-
+-      spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
+-      tmo_posted = phba->pport->work_port_events & WORKER_MBOX_TMO;
+-      if (!tmo_posted)
+-              phba->pport->work_port_events |= WORKER_MBOX_TMO;
+-      spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
+-      if (!tmo_posted) {
+-              spin_lock_irqsave(&phba->hbalock, iflag);
++      phba = (struct lpfc_hba *)ptr;
++      spin_lock_irqsave(phba->host->host_lock, iflag);
++      if (!(phba->work_hba_events & WORKER_MBOX_TMO)) {
++              phba->work_hba_events |= WORKER_MBOX_TMO;
+               if (phba->work_wait)
+-                      lpfc_worker_wake_up(phba);
+-              spin_unlock_irqrestore(&phba->hbalock, iflag);
++                      wake_up(phba->work_wait);
+       }
++      spin_unlock_irqrestore(phba->host->host_lock, iflag);
+ }
+ void
+ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
+ {
+-      LPFC_MBOXQ_t *pmbox = phba->sli.mbox_active;
+-      MAILBOX_t *mb = &pmbox->mb;
++      LPFC_MBOXQ_t *pmbox;
++      MAILBOX_t *mb;
+       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_sli_ring *pring;
+-      if (!(phba->pport->work_port_events & WORKER_MBOX_TMO)) {
++      spin_lock_irq(phba->host->host_lock);
++      if (!(phba->work_hba_events & WORKER_MBOX_TMO)) {
++              spin_unlock_irq(phba->host->host_lock);
+               return;
+       }
++      pmbox = phba->sli.mbox_active;
++      mb = &pmbox->mb;
 +
-+/*
-+ * This is a struct kmem_cache for filldir nodes, because we allocate a lot
-+ * of them and they shouldn't waste memory.  If the node has a small name
-+ * (as defined by the dentry structure), then we use an inline name to
-+ * preserve kmalloc space.
-+ */
-+static struct kmem_cache *unionfs_filldir_cachep;
+       /* Mbox cmd <mbxCommand> timeout */
+-      lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+-                      "%d:0310 Mailbox command x%x timeout Data: x%x x%x "
+-                      "x%p\n",
++      lpfc_printf_log(phba,
++              KERN_ERR,
++              LOG_MBOX | LOG_SLI,
++              "%d:0310 Mailbox command x%x timeout Data: x%x x%x x%p\n",
+               phba->brd_no,
+               mb->mbxCommand,
+-                      phba->pport->port_state,
++              phba->hba_state,
+               phba->sli.sli_flag,
+               phba->sli.mbox_active);
+@@ -2457,14 +2049,11 @@
+        * would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing
+        * it to fail all oustanding SCSI IO.
+        */
+-      spin_lock_irq(&phba->pport->work_port_lock);
+-      phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
+-      spin_unlock_irq(&phba->pport->work_port_lock);
+-      spin_lock_irq(&phba->hbalock);
+-      phba->link_state = LPFC_LINK_UNKNOWN;
+-      phba->pport->fc_flag |= FC_ESTABLISH_LINK;
++      phba->hba_state = LPFC_STATE_UNKNOWN;
++      phba->work_hba_events &= ~WORKER_MBOX_TMO;
++      phba->fc_flag |= FC_ESTABLISH_LINK;
+       psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+-      spin_unlock_irq(&phba->hbalock);
++      spin_unlock_irq(phba->host->host_lock);
+       pring = &psli->ring[psli->fcp_ring];
+       lpfc_sli_abort_iocb_ring(phba, pring);
+@@ -2486,10 +2075,10 @@
+ }
+ int
+-lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
++lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
+ {
+       MAILBOX_t *mb;
+-      struct lpfc_sli *psli = &phba->sli;
++      struct lpfc_sli *psli;
+       uint32_t status, evtctr;
+       uint32_t ha_copy;
+       int i;
+@@ -2497,44 +2086,31 @@
+       volatile uint32_t word0, ldata;
+       void __iomem *to_slim;
+-      if (pmbox->mbox_cmpl && pmbox->mbox_cmpl != lpfc_sli_def_mbox_cmpl &&
+-              pmbox->mbox_cmpl != lpfc_sli_wake_mbox_wait) {
+-              if(!pmbox->vport) {
+-                      lpfc_printf_log(phba, KERN_ERR,
+-                                      LOG_MBOX | LOG_VPORT,
+-                                      "%d:1806 Mbox x%x failed. No vport\n",
+-                                      phba->brd_no,
+-                                      pmbox->mb.mbxCommand);
+-                      dump_stack();
+-                      return MBXERR_ERROR;
+-              }
+-      }
+-
+-
+       /* If the PCI channel is in offline state, do not post mbox. */
+       if (unlikely(pci_channel_offline(phba->pcidev)))
+               return MBX_NOT_FINISHED;
+-      spin_lock_irqsave(&phba->hbalock, drvr_flag);
+       psli = &phba->sli;
++      spin_lock_irqsave(phba->host->host_lock, drvr_flag);
 +
-+int unionfs_init_filldir_cache(void)
-+{
-+      unionfs_filldir_cachep =
-+              kmem_cache_create("unionfs_filldir",
-+                                sizeof(struct filldir_node), 0,
-+                                SLAB_RECLAIM_ACCOUNT, NULL, NULL);
+       mb = &pmbox->mb;
+       status = MBX_SUCCESS;
+-      if (phba->link_state == LPFC_HBA_ERROR) {
+-              spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
++      if (phba->hba_state == LPFC_HBA_ERROR) {
++              spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
+               /* Mbox command <mbxCommand> cannot issue */
+-              LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag)
+-              return MBX_NOT_FINISHED;
++              LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
++              return (MBX_NOT_FINISHED);
+       }
+       if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
+           !(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
+-              spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+-              LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag)
+-              return MBX_NOT_FINISHED;
++              spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
++              LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
++              return (MBX_NOT_FINISHED);
+       }
+       if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
+@@ -2544,18 +2120,20 @@
+                */
+               if (flag & MBX_POLL) {
+-                      spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
++                      spin_unlock_irqrestore(phba->host->host_lock,
++                                             drvr_flag);
+                       /* Mbox command <mbxCommand> cannot issue */
+-                      LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+-                      return MBX_NOT_FINISHED;
++                      LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
++                      return (MBX_NOT_FINISHED);
+               }
+               if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) {
+-                      spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
++                      spin_unlock_irqrestore(phba->host->host_lock,
++                                             drvr_flag);
+                       /* Mbox command <mbxCommand> cannot issue */
+-                      LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+-                      return MBX_NOT_FINISHED;
++                      LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
++                      return (MBX_NOT_FINISHED);
+               }
+               /* Handle STOP IOCB processing flag. This is only meaningful
+@@ -2579,33 +2157,21 @@
+               lpfc_mbox_put(phba, pmbox);
+               /* Mbox cmd issue - BUSY */
+-              lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+-                              "%d (%d):0308 Mbox cmd issue - BUSY Data: "
+-                              "x%x x%x x%x x%x\n",
++              lpfc_printf_log(phba,
++                      KERN_INFO,
++                      LOG_MBOX | LOG_SLI,
++                      "%d:0308 Mbox cmd issue - BUSY Data: x%x x%x x%x x%x\n",
+                       phba->brd_no,
+-                              pmbox->vport ? pmbox->vport->vpi : 0xffffff,
+-                              mb->mbxCommand, phba->pport->port_state,
+-                              psli->sli_flag, flag);
++                      mb->mbxCommand,
++                      phba->hba_state,
++                      psli->sli_flag,
++                      flag);
+               psli->slistat.mbox_busy++;
+-              spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+-
+-              if (pmbox->vport) {
+-                      lpfc_debugfs_disc_trc(pmbox->vport,
+-                              LPFC_DISC_TRC_MBOX_VPORT,
+-                              "MBOX Bsy vport:  cmd:x%x mb:x%x x%x",
+-                              (uint32_t)mb->mbxCommand,
+-                              mb->un.varWords[0], mb->un.varWords[1]);
+-              }
+-              else {
+-                      lpfc_debugfs_disc_trc(phba->pport,
+-                              LPFC_DISC_TRC_MBOX,
+-                              "MBOX Bsy:        cmd:x%x mb:x%x x%x",
+-                              (uint32_t)mb->mbxCommand,
+-                              mb->un.varWords[0], mb->un.varWords[1]);
+-              }
++              spin_unlock_irqrestore(phba->host->host_lock,
++                                     drvr_flag);
+-              return MBX_BUSY;
++              return (MBX_BUSY);
+       }
+       /* Handle STOP IOCB processing flag. This is only meaningful
+@@ -2632,10 +2198,11 @@
+               if (!(psli->sli_flag & LPFC_SLI2_ACTIVE) &&
+                   (mb->mbxCommand != MBX_KILL_BOARD)) {
+                       psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+-                      spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
++                      spin_unlock_irqrestore(phba->host->host_lock,
++                                             drvr_flag);
+                       /* Mbox command <mbxCommand> cannot issue */
+-                      LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+-                      return MBX_NOT_FINISHED;
++                      LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag);
++                      return (MBX_NOT_FINISHED);
+               }
+               /* timeout active mbox command */
+               mod_timer(&psli->mbox_tmo, (jiffies +
+@@ -2643,29 +2210,15 @@
+       }
+       /* Mailbox cmd <cmd> issue */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+-                      "%d (%d):0309 Mailbox cmd x%x issue Data: x%x x%x "
+-                      "x%x\n",
+-                      phba->brd_no, pmbox->vport ? pmbox->vport->vpi : 0,
+-                      mb->mbxCommand, phba->pport->port_state,
+-                      psli->sli_flag, flag);
+-
+-      if (mb->mbxCommand != MBX_HEARTBEAT) {
+-              if (pmbox->vport) {
+-                      lpfc_debugfs_disc_trc(pmbox->vport,
+-                              LPFC_DISC_TRC_MBOX_VPORT,
+-                              "MBOX Send vport: cmd:x%x mb:x%x x%x",
+-                              (uint32_t)mb->mbxCommand,
+-                              mb->un.varWords[0], mb->un.varWords[1]);
+-              }
+-              else {
+-                      lpfc_debugfs_disc_trc(phba->pport,
+-                              LPFC_DISC_TRC_MBOX,
+-                              "MBOX Send:       cmd:x%x mb:x%x x%x",
+-                              (uint32_t)mb->mbxCommand,
+-                              mb->un.varWords[0], mb->un.varWords[1]);
+-              }
+-      }
++      lpfc_printf_log(phba,
++              KERN_INFO,
++              LOG_MBOX | LOG_SLI,
++              "%d:0309 Mailbox cmd x%x issue Data: x%x x%x x%x\n",
++              phba->brd_no,
++              mb->mbxCommand,
++              phba->hba_state,
++              psli->sli_flag,
++              flag);
+       psli->slistat.mbox_cmd++;
+       evtctr = psli->slistat.mbox_event;
+@@ -2732,12 +2285,12 @@
+               /* Wait for command to complete */
+               while (((word0 & OWN_CHIP) == OWN_CHIP) ||
+                      (!(ha_copy & HA_MBATT) &&
+-                      (phba->link_state > LPFC_WARM_START))) {
++                      (phba->hba_state > LPFC_WARM_START))) {
+                       if (i-- <= 0) {
+                               psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+-                              spin_unlock_irqrestore(&phba->hbalock,
++                              spin_unlock_irqrestore(phba->host->host_lock,
+                                                      drvr_flag);
+-                              return MBX_NOT_FINISHED;
++                              return (MBX_NOT_FINISHED);
+                       }
+                       /* Check if we took a mbox interrupt while we were
+@@ -2746,12 +2299,12 @@
+                           && (evtctr != psli->slistat.mbox_event))
+                               break;
+-                      spin_unlock_irqrestore(&phba->hbalock,
++                      spin_unlock_irqrestore(phba->host->host_lock,
+                                              drvr_flag);
+                       msleep(1);
+-                      spin_lock_irqsave(&phba->hbalock, drvr_flag);
++                      spin_lock_irqsave(phba->host->host_lock, drvr_flag);
+                       if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
+                               /* First copy command data */
+@@ -2802,25 +2355,23 @@
+               status = mb->mbxStatus;
+       }
+-      spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+-      return status;
++      spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
++      return (status);
+ }
+-/*
+- * Caller needs to hold lock.
+- */
+-static void
+-__lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+-                  struct lpfc_iocbq *piocb)
++static int
++lpfc_sli_ringtx_put(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
++                  struct lpfc_iocbq * piocb)
+ {
+       /* Insert the caller's iocb in the txq tail for later processing. */
+       list_add_tail(&piocb->list, &pring->txq);
+       pring->txq_cnt++;
++      return (0);
+ }
+ static struct lpfc_iocbq *
+ lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+-                 struct lpfc_iocbq **piocb)
++                 struct lpfc_iocbq ** piocb)
+ {
+       struct lpfc_iocbq * nextiocb;
+@@ -2833,29 +2384,13 @@
+       return nextiocb;
+ }
+-/*
+- * Lockless version of lpfc_sli_issue_iocb.
+- */
+ int
+-__lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
++lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+                   struct lpfc_iocbq *piocb, uint32_t flag)
+ {
+       struct lpfc_iocbq *nextiocb;
+       IOCB_t *iocb;
+-      if (piocb->iocb_cmpl && (!piocb->vport) &&
+-         (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
+-         (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) {
+-              lpfc_printf_log(phba, KERN_ERR,
+-                              LOG_SLI | LOG_VPORT,
+-                              "%d:1807 IOCB x%x failed. No vport\n",
+-                              phba->brd_no,
+-                              piocb->iocb.ulpCommand);
+-              dump_stack();
+-              return IOCB_ERROR;
+-      }
+-
+-
+       /* If the PCI channel is in offline state, do not post iocbs. */
+       if (unlikely(pci_channel_offline(phba->pcidev)))
+               return IOCB_ERROR;
+@@ -2863,7 +2398,7 @@
+       /*
+        * We should never get an IOCB if we are in a < LINK_DOWN state
+        */
+-      if (unlikely(phba->link_state < LPFC_LINK_DOWN))
++      if (unlikely(phba->hba_state < LPFC_LINK_DOWN))
+               return IOCB_ERROR;
+       /*
+@@ -2873,7 +2408,7 @@
+       if (unlikely(pring->flag & LPFC_STOP_IOCB_MBX))
+               goto iocb_busy;
+-      if (unlikely(phba->link_state == LPFC_LINK_DOWN)) {
++      if (unlikely(phba->hba_state == LPFC_LINK_DOWN)) {
+               /*
+                * Only CREATE_XRI, CLOSE_XRI, and QUE_RING_BUF
+                * can be issued if the link is not up.
+@@ -2901,9 +2436,8 @@
+        * attention events.
+        */
+       } else if (unlikely(pring->ringno == phba->sli.fcp_ring &&
+-                          !(phba->sli.sli_flag & LPFC_PROCESS_LA))) {
++                 !(phba->sli.sli_flag & LPFC_PROCESS_LA)))
+               goto iocb_busy;
+-      }
+       while ((iocb = lpfc_sli_next_iocb_slot(phba, pring)) &&
+              (nextiocb = lpfc_sli_next_iocb(phba, pring, &piocb)))
+@@ -2925,28 +2459,13 @@
+  out_busy:
+       if (!(flag & SLI_IOCB_RET_IOCB)) {
+-              __lpfc_sli_ringtx_put(phba, pring, piocb);
++              lpfc_sli_ringtx_put(phba, pring, piocb);
+               return IOCB_SUCCESS;
+       }
+       return IOCB_BUSY;
+ }
+-
+-int
+-lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+-                  struct lpfc_iocbq *piocb, uint32_t flag)
+-{
+-      unsigned long iflags;
+-      int rc;
+-
+-      spin_lock_irqsave(&phba->hbalock, iflags);
+-      rc = __lpfc_sli_issue_iocb(phba, pring, piocb, flag);
+-      spin_unlock_irqrestore(&phba->hbalock, iflags);
+-
+-      return rc;
+-}
+-
+ static int
+ lpfc_extra_ring_setup( struct lpfc_hba *phba)
+ {
+@@ -2985,7 +2504,7 @@
+ int
+ lpfc_sli_setup(struct lpfc_hba *phba)
+ {
+-      int i, totiocbsize = 0;
++      int i, totiocb = 0;
+       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_sli_ring *pring;
+@@ -3010,12 +2529,6 @@
+                       pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES;
+                       pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES;
+                       pring->numRiocb += SLI2_IOCB_RSP_R3XTRA_ENTRIES;
+-                      pring->sizeCiocb = (phba->sli_rev == 3) ?
+-                                                      SLI3_IOCB_CMD_SIZE :
+-                                                      SLI2_IOCB_CMD_SIZE;
+-                      pring->sizeRiocb = (phba->sli_rev == 3) ?
+-                                                      SLI3_IOCB_RSP_SIZE :
+-                                                      SLI2_IOCB_RSP_SIZE;
+                       pring->iotag_ctr = 0;
+                       pring->iotag_max =
+                           (phba->cfg_hba_queue_depth * 2);
+@@ -3026,25 +2539,12 @@
+                       /* numCiocb and numRiocb are used in config_port */
+                       pring->numCiocb = SLI2_IOCB_CMD_R1_ENTRIES;
+                       pring->numRiocb = SLI2_IOCB_RSP_R1_ENTRIES;
+-                      pring->sizeCiocb = (phba->sli_rev == 3) ?
+-                                                      SLI3_IOCB_CMD_SIZE :
+-                                                      SLI2_IOCB_CMD_SIZE;
+-                      pring->sizeRiocb = (phba->sli_rev == 3) ?
+-                                                      SLI3_IOCB_RSP_SIZE :
+-                                                      SLI2_IOCB_RSP_SIZE;
+-                      pring->iotag_max = phba->cfg_hba_queue_depth;
+                       pring->num_mask = 0;
+                       break;
+               case LPFC_ELS_RING:     /* ring 2 - ELS / CT */
+                       /* numCiocb and numRiocb are used in config_port */
+                       pring->numCiocb = SLI2_IOCB_CMD_R2_ENTRIES;
+                       pring->numRiocb = SLI2_IOCB_RSP_R2_ENTRIES;
+-                      pring->sizeCiocb = (phba->sli_rev == 3) ?
+-                                                      SLI3_IOCB_CMD_SIZE :
+-                                                      SLI2_IOCB_CMD_SIZE;
+-                      pring->sizeRiocb = (phba->sli_rev == 3) ?
+-                                                      SLI3_IOCB_RSP_SIZE :
+-                                                      SLI2_IOCB_RSP_SIZE;
+                       pring->fast_iotag = 0;
+                       pring->iotag_ctr = 0;
+                       pring->iotag_max = 4096;
+@@ -3075,16 +2575,14 @@
+                           lpfc_ct_unsol_event;
+                       break;
+               }
+-              totiocbsize += (pring->numCiocb * pring->sizeCiocb) +
+-                              (pring->numRiocb * pring->sizeRiocb);
++              totiocb += (pring->numCiocb + pring->numRiocb);
+       }
+-      if (totiocbsize > MAX_SLIM_IOCB_SIZE) {
++      if (totiocb > MAX_SLI2_IOCB) {
+               /* Too many cmd / rsp ring entries in SLI2 SLIM */
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "%d:0462 Too many cmd / rsp ring entries in "
+-                              "SLI2 SLIM Data: x%x x%lx\n",
+-                              phba->brd_no, totiocbsize,
+-                              (unsigned long) MAX_SLIM_IOCB_SIZE);
++                              "SLI2 SLIM Data: x%x x%x\n",
++                              phba->brd_no, totiocb, MAX_SLI2_IOCB);
+       }
+       if (phba->cfg_multi_ring_support == 2)
+               lpfc_extra_ring_setup(phba);
+@@ -3093,16 +2591,15 @@
+ }
+ int
+-lpfc_sli_queue_setup(struct lpfc_hba *phba)
++lpfc_sli_queue_setup(struct lpfc_hba * phba)
+ {
+       struct lpfc_sli *psli;
+       struct lpfc_sli_ring *pring;
+       int i;
+       psli = &phba->sli;
+-      spin_lock_irq(&phba->hbalock);
++      spin_lock_irq(phba->host->host_lock);
+       INIT_LIST_HEAD(&psli->mboxq);
+-      INIT_LIST_HEAD(&psli->mboxq_cmpl);
+       /* Initialize list headers for txq and txcmplq as double linked lists */
+       for (i = 0; i < psli->num_rings; i++) {
+               pring = &psli->ring[i];
+@@ -3115,73 +2612,15 @@
+               INIT_LIST_HEAD(&pring->iocb_continueq);
+               INIT_LIST_HEAD(&pring->postbufq);
+       }
+-      spin_unlock_irq(&phba->hbalock);
+-      return 1;
++      spin_unlock_irq(phba->host->host_lock);
++      return (1);
+ }
+ int
+-lpfc_sli_host_down(struct lpfc_vport *vport)
++lpfc_sli_hba_down(struct lpfc_hba * phba)
+ {
+       LIST_HEAD(completions);
+-      struct lpfc_hba *phba = vport->phba;
+-      struct lpfc_sli *psli = &phba->sli;
+-      struct lpfc_sli_ring *pring;
+-      struct lpfc_iocbq *iocb, *next_iocb;
+-      int i;
+-      unsigned long flags = 0;
+-      uint16_t prev_pring_flag;
+-
+-      lpfc_cleanup_discovery_resources(vport);
+-
+-      spin_lock_irqsave(&phba->hbalock, flags);
+-      for (i = 0; i < psli->num_rings; i++) {
+-              pring = &psli->ring[i];
+-              prev_pring_flag = pring->flag;
+-              if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */
+-                      pring->flag |= LPFC_DEFERRED_RING_EVENT;
+-              /*
+-               * Error everything on the txq since these iocbs have not been
+-               * given to the FW yet.
+-               */
+-              list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
+-                      if (iocb->vport != vport)
+-                              continue;
+-                      list_move_tail(&iocb->list, &completions);
+-                      pring->txq_cnt--;
+-              }
+-
+-              /* Next issue ABTS for everything on the txcmplq */
+-              list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq,
+-                                                                      list) {
+-                      if (iocb->vport != vport)
+-                              continue;
+-                      lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+-              }
+-
+-              pring->flag = prev_pring_flag;
+-      }
+-
+-      spin_unlock_irqrestore(&phba->hbalock, flags);
+-
+-      while (!list_empty(&completions)) {
+-              list_remove_head(&completions, iocb, struct lpfc_iocbq, list);
+-
+-              if (!iocb->iocb_cmpl)
+-                      lpfc_sli_release_iocbq(phba, iocb);
+-              else {
+-                      iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
+-                      iocb->iocb.un.ulpWord[4] = IOERR_SLI_DOWN;
+-                      (iocb->iocb_cmpl) (phba, iocb, iocb);
+-              }
+-      }
+-      return 1;
+-}
+-
+-int
+-lpfc_sli_hba_down(struct lpfc_hba *phba)
+-{
+-      LIST_HEAD(completions);
+-      struct lpfc_sli *psli = &phba->sli;
++      struct lpfc_sli *psli;
+       struct lpfc_sli_ring *pring;
+       LPFC_MBOXQ_t *pmb;
+       struct lpfc_iocbq *iocb;
+@@ -3189,14 +2628,12 @@
+       int i;
+       unsigned long flags = 0;
++      psli = &phba->sli;
+       lpfc_hba_down_prep(phba);
+-      lpfc_fabric_abort_hba(phba);
+-
+-      spin_lock_irqsave(&phba->hbalock, flags);
++      spin_lock_irqsave(phba->host->host_lock, flags);
+       for (i = 0; i < psli->num_rings; i++) {
+               pring = &psli->ring[i];
+-              if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */
+               pring->flag |= LPFC_DEFERRED_RING_EVENT;
+               /*
+@@ -3207,50 +2644,51 @@
+               pring->txq_cnt = 0;
+       }
+-      spin_unlock_irqrestore(&phba->hbalock, flags);
++      spin_unlock_irqrestore(phba->host->host_lock, flags);
+       while (!list_empty(&completions)) {
+-              list_remove_head(&completions, iocb, struct lpfc_iocbq, list);
++              iocb = list_get_first(&completions, struct lpfc_iocbq, list);
+               cmd = &iocb->iocb;
++              list_del(&iocb->list);
+-              if (!iocb->iocb_cmpl)
+-                      lpfc_sli_release_iocbq(phba, iocb);
+-              else {
++              if (iocb->iocb_cmpl) {
+                       cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                       cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
+                       (iocb->iocb_cmpl) (phba, iocb, iocb);
+-              }
++              } else
++                      lpfc_sli_release_iocbq(phba, iocb);
+       }
+       /* Return any active mbox cmds */
+       del_timer_sync(&psli->mbox_tmo);
+-      spin_lock_irqsave(&phba->hbalock, flags);
+-
+-      spin_lock(&phba->pport->work_port_lock);
+-      phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
+-      spin_unlock(&phba->pport->work_port_lock);
+-
++      spin_lock_irqsave(phba->host->host_lock, flags);
++      phba->work_hba_events &= ~WORKER_MBOX_TMO;
+       if (psli->mbox_active) {
+-              list_add_tail(&psli->mbox_active->list, &completions);
+-      psli->mbox_active = NULL;
+-              psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
++              pmb = psli->mbox_active;
++              pmb->mb.mbxStatus = MBX_NOT_FINISHED;
++              if (pmb->mbox_cmpl) {
++                      spin_unlock_irqrestore(phba->host->host_lock, flags);
++                      pmb->mbox_cmpl(phba,pmb);
++                      spin_lock_irqsave(phba->host->host_lock, flags);
+       }
++      }
++      psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
++      psli->mbox_active = NULL;
+-      /* Return any pending or completed mbox cmds */
+-      list_splice_init(&phba->sli.mboxq, &completions);
+-      list_splice_init(&phba->sli.mboxq_cmpl, &completions);
+-      INIT_LIST_HEAD(&psli->mboxq);
+-      INIT_LIST_HEAD(&psli->mboxq_cmpl);
+-
+-      spin_unlock_irqrestore(&phba->hbalock, flags);
+-
+-      while (!list_empty(&completions)) {
+-              list_remove_head(&completions, pmb, LPFC_MBOXQ_t, list);
++      /* Return any pending mbox cmds */
++      while ((pmb = lpfc_mbox_get(phba)) != NULL) {
+               pmb->mb.mbxStatus = MBX_NOT_FINISHED;
+               if (pmb->mbox_cmpl) {
++                      spin_unlock_irqrestore(phba->host->host_lock, flags);
+                       pmb->mbox_cmpl(phba,pmb);
++                      spin_lock_irqsave(phba->host->host_lock, flags);
+               }
+       }
 +
-+      return (unionfs_filldir_cachep ? 0 : -ENOMEM);
-+}
++      INIT_LIST_HEAD(&psli->mboxq);
 +
-+void unionfs_destroy_filldir_cache(void)
-+{
-+      if (unionfs_filldir_cachep)
-+              kmem_cache_destroy(unionfs_filldir_cachep);
-+}
++      spin_unlock_irqrestore(phba->host->host_lock, flags);
 +
-+/*
-+ * This is a tuning parameter that tells us roughly how big to make the
-+ * hash table in directory entries per page.  This isn't perfect, but
-+ * at least we get a hash table size that shouldn't be too overloaded.
-+ * The following averages are based on my home directory.
-+ * 14.44693   Overall
-+ * 12.29      Single Page Directories
-+ * 117.93     Multi-page directories
-+ */
-+#define DENTPAGE 4096
-+#define DENTPERONEPAGE 12
-+#define DENTPERPAGE 118
-+#define MINHASHSIZE 1
-+static int guesstimate_hash_size(struct inode *inode)
-+{
-+      struct inode *hidden_inode;
-+      int bindex;
-+      int hashsize = MINHASHSIZE;
+       return 1;
+ }
+@@ -3272,15 +2710,14 @@
+ }
+ int
+-lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+-                       struct lpfc_dmabuf *mp)
++lpfc_sli_ringpostbuf_put(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
++                       struct lpfc_dmabuf * mp)
+ {
+       /* Stick struct lpfc_dmabuf at end of postbufq so driver can look it up
+          later */
+-      spin_lock_irq(&phba->hbalock);
+       list_add_tail(&mp->list, &pring->postbufq);
 +
-+      if (UNIONFS_I(inode)->hashsize > 0)
-+              return UNIONFS_I(inode)->hashsize;
+       pring->postbufq_cnt++;
+-      spin_unlock_irq(&phba->hbalock);
+       return 0;
+ }
+@@ -3293,17 +2730,14 @@
+       struct list_head *slp = &pring->postbufq;
+       /* Search postbufq, from the begining, looking for a match on phys */
+-      spin_lock_irq(&phba->hbalock);
+       list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
+               if (mp->phys == phys) {
+                       list_del_init(&mp->list);
+                       pring->postbufq_cnt--;
+-                      spin_unlock_irq(&phba->hbalock);
+                       return mp;
+               }
+       }
+-      spin_unlock_irq(&phba->hbalock);
+       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "%d:0410 Cannot find virtual addr for mapped buf on "
+                       "ring %d Data x%llx x%p x%p x%x\n",
+@@ -3313,110 +2747,92 @@
+ }
+ static void
+-lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                      struct lpfc_iocbq *rspiocb)
++lpfc_sli_abort_els_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                      struct lpfc_iocbq * rspiocb)
+ {
+-      IOCB_t *irsp = &rspiocb->iocb;
++      IOCB_t *irsp;
+       uint16_t abort_iotag, abort_context;
+-      struct lpfc_iocbq *abort_iocb;
++      struct lpfc_iocbq *abort_iocb, *rsp_ab_iocb;
+       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+       abort_iocb = NULL;
++      irsp = &rspiocb->iocb;
 +
-+      for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
-+              if (!(hidden_inode = unionfs_lower_inode_idx(inode, bindex)))
-+                      continue;
++      spin_lock_irq(phba->host->host_lock);
+       if (irsp->ulpStatus) {
+               abort_context = cmdiocb->iocb.un.acxri.abortContextTag;
+               abort_iotag = cmdiocb->iocb.un.acxri.abortIoTag;
+-              spin_lock_irq(&phba->hbalock);
+               if (abort_iotag != 0 && abort_iotag <= phba->sli.last_iotag)
+                       abort_iocb = phba->sli.iocbq_lookup[abort_iotag];
+-              lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_SLI,
+-                              "%d:0327 Cannot abort els iocb %p "
+-                              "with tag %x context %x, abort status %x, "
+-                              "abort code %x\n",
+-                              phba->brd_no, abort_iocb, abort_iotag,
+-                              abort_context, irsp->ulpStatus,
+-                              irsp->un.ulpWord[4]);
++              lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
++                              "%d:0327 Cannot abort els iocb %p"
++                              " with tag %x context %x\n",
++                              phba->brd_no, abort_iocb,
++                              abort_iotag, abort_context);
+               /*
+                * make sure we have the right iocbq before taking it
+                * off the txcmplq and try to call completion routine.
+                */
+-              if (!abort_iocb ||
+-                  abort_iocb->iocb.ulpContext != abort_context ||
+-                  (abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) == 0)
+-                      spin_unlock_irq(&phba->hbalock);
+-              else {
+-                      list_del_init(&abort_iocb->list);
++              if (abort_iocb &&
++                  abort_iocb->iocb.ulpContext == abort_context &&
++                  abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) {
++                      list_del(&abort_iocb->list);
+                       pring->txcmplq_cnt--;
+-                      spin_unlock_irq(&phba->hbalock);
+-                      abort_iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED;
+-                      abort_iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
+-                      abort_iocb->iocb.un.ulpWord[4] = IOERR_SLI_ABORTED;
+-                      (abort_iocb->iocb_cmpl)(phba, abort_iocb, abort_iocb);
++                      rsp_ab_iocb = lpfc_sli_get_iocbq(phba);
++                      if (rsp_ab_iocb == NULL)
++                              lpfc_sli_release_iocbq(phba, abort_iocb);
++                      else {
++                              abort_iocb->iocb_flag &=
++                                      ~LPFC_DRIVER_ABORTED;
++                              rsp_ab_iocb->iocb.ulpStatus =
++                                      IOSTAT_LOCAL_REJECT;
++                              rsp_ab_iocb->iocb.un.ulpWord[4] =
++                                      IOERR_SLI_ABORTED;
++                              spin_unlock_irq(phba->host->host_lock);
++                              (abort_iocb->iocb_cmpl)
++                                      (phba, abort_iocb, rsp_ab_iocb);
++                              spin_lock_irq(phba->host->host_lock);
++                              lpfc_sli_release_iocbq(phba, rsp_ab_iocb);
++                      }
+               }
+       }
+       lpfc_sli_release_iocbq(phba, cmdiocb);
+-      return;
+-}
+-
+-static void
+-lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                   struct lpfc_iocbq *rspiocb)
+-{
+-      IOCB_t *irsp = &rspiocb->iocb;
+-
+-      /* ELS cmd tag <ulpIoTag> completes */
+-      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-                      "%d (X):0133 Ignoring ELS cmd tag x%x completion Data: "
+-                      "x%x x%x x%x\n",
+-                      phba->brd_no, irsp->ulpIoTag, irsp->ulpStatus,
+-                      irsp->un.ulpWord[4], irsp->ulpTimeout);
+-      if (cmdiocb->iocb.ulpCommand == CMD_GEN_REQUEST64_CR)
+-              lpfc_ct_free_iocb(phba, cmdiocb);
+-      else
+-              lpfc_els_free_iocb(phba, cmdiocb);
++      spin_unlock_irq(phba->host->host_lock);
+       return;
+ }
+ int
+-lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+-                         struct lpfc_iocbq *cmdiocb)
++lpfc_sli_issue_abort_iotag(struct lpfc_hba * phba,
++                         struct lpfc_sli_ring * pring,
++                         struct lpfc_iocbq * cmdiocb)
+ {
+-      struct lpfc_vport *vport = cmdiocb->vport;
+       struct lpfc_iocbq *abtsiocbp;
+       IOCB_t *icmd = NULL;
+       IOCB_t *iabt = NULL;
+       int retval = IOCB_ERROR;
+-      /*
+-       * There are certain command types we don't want to abort.  And we
+-       * don't want to abort commands that are already in the process of
+-       * being aborted.
++      /* There are certain command types we don't want
++       * to abort.
+        */
+       icmd = &cmdiocb->iocb;
+-      if (icmd->ulpCommand == CMD_ABORT_XRI_CN ||
+-          icmd->ulpCommand == CMD_CLOSE_XRI_CN ||
+-          (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0)
++      if ((icmd->ulpCommand == CMD_ABORT_XRI_CN) ||
++          (icmd->ulpCommand == CMD_CLOSE_XRI_CN))
+               return 0;
+-      /* If we're unloading, don't abort iocb on the ELS ring, but change the
+-       * callback so that nothing happens when it finishes.
++      /* If we're unloading, interrupts are disabled so we
++       * need to cleanup the iocb here.
+        */
+-      if ((vport->load_flag & FC_UNLOADING) &&
+-          (pring->ringno == LPFC_ELS_RING)) {
+-              if (cmdiocb->iocb_flag & LPFC_IO_FABRIC)
+-                      cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl;
+-              else
+-                      cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl;
++      if (phba->fc_flag & FC_UNLOADING)
+               goto abort_iotag_exit;
+-      }
+       /* issue ABTS for this IOCB based on iotag */
+-      abtsiocbp = __lpfc_sli_get_iocbq(phba);
++      abtsiocbp = lpfc_sli_get_iocbq(phba);
+       if (abtsiocbp == NULL)
+               return 0;
+@@ -3432,7 +2848,7 @@
+       iabt->ulpLe = 1;
+       iabt->ulpClass = icmd->ulpClass;
+-      if (phba->link_state >= LPFC_LINK_UP)
++      if (phba->hba_state >= LPFC_LINK_UP)
+               iabt->ulpCommand = CMD_ABORT_XRI_CN;
+       else
+               iabt->ulpCommand = CMD_CLOSE_XRI_CN;
+@@ -3440,20 +2856,32 @@
+       abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl;
+       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+-                      "%d (%d):0339 Abort xri x%x, original iotag x%x, "
+-                      "abort cmd iotag x%x\n",
+-                      phba->brd_no, vport->vpi,
+-                      iabt->un.acxri.abortContextTag,
++                      "%d:0339 Abort xri x%x, original iotag x%x, abort "
++                      "cmd iotag x%x\n",
++                      phba->brd_no, iabt->un.acxri.abortContextTag,
+                       iabt->un.acxri.abortIoTag, abtsiocbp->iotag);
+-      retval = __lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
++      retval = lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
+ abort_iotag_exit:
+-      /*
+-       * Caller to this routine should check for IOCB_ERROR
+-       * and handle it properly.  This routine no longer removes
+-       * iocb off txcmplq and call compl in case of IOCB_ERROR.
 +
-+              if (hidden_inode->i_size == DENTPAGE)
-+                      hashsize += DENTPERONEPAGE;
-+              else
-+                      hashsize += (hidden_inode->i_size / DENTPAGE) *
-+                              DENTPERPAGE;
++      /* If we could not issue an abort dequeue the iocb and handle
++       * the completion here.
+        */
+-      return retval;
++      if (retval == IOCB_ERROR) {
++              list_del(&cmdiocb->list);
++              pring->txcmplq_cnt--;
++
++              if (cmdiocb->iocb_cmpl) {
++                      icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
++                      icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
++                      spin_unlock_irq(phba->host->host_lock);
++                      (cmdiocb->iocb_cmpl) (phba, cmdiocb, cmdiocb);
++                      spin_lock_irq(phba->host->host_lock);
++              } else
++                      lpfc_sli_release_iocbq(phba, cmdiocb);
 +      }
 +
-+      return hashsize;
-+}
-+
-+int init_rdstate(struct file *file)
-+{
-+      BUG_ON(sizeof(loff_t) !=
-+             (sizeof(unsigned int) + sizeof(unsigned int)));
-+      BUG_ON(UNIONFS_F(file)->rdstate != NULL);
-+
-+      UNIONFS_F(file)->rdstate = alloc_rdstate(file->f_dentry->d_inode,
-+                                               fbstart(file));
-+
-+      return (UNIONFS_F(file)->rdstate ? 0 : -ENOMEM);
-+}
++      return 1;
+ }
+ static int
+@@ -3519,10 +2947,14 @@
+ }
+ void
+-lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+-                      struct lpfc_iocbq *rspiocb)
++lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
++                         struct lpfc_iocbq * rspiocb)
+ {
++      unsigned long iflags;
 +
-+struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos)
-+{
-+      struct unionfs_dir_state *rdstate = NULL;
-+      struct list_head *pos;
++      spin_lock_irqsave(phba->host->host_lock, iflags);
+       lpfc_sli_release_iocbq(phba, cmdiocb);
++      spin_unlock_irqrestore(phba->host->host_lock, iflags);
+       return;
+ }
+@@ -3540,8 +2972,8 @@
+       for (i = 1; i <= phba->sli.last_iotag; i++) {
+               iocbq = phba->sli.iocbq_lookup[i];
+-              if (lpfc_sli_validate_fcp_iocb(iocbq, tgt_id, lun_id, 0,
+-                                             abort_cmd) != 0)
++              if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id,
++                                              0, abort_cmd) != 0)
+                       continue;
+               /* issue ABTS for this IOCB based on iotag */
+@@ -3557,9 +2989,8 @@
+               abtsiocb->iocb.un.acxri.abortIoTag = cmd->ulpIoTag;
+               abtsiocb->iocb.ulpLe = 1;
+               abtsiocb->iocb.ulpClass = cmd->ulpClass;
+-              abtsiocb->vport = phba->pport;
+-              if (lpfc_is_link_up(phba))
++              if (phba->hba_state >= LPFC_LINK_UP)
+                       abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN;
+               else
+                       abtsiocb->iocb.ulpCommand = CMD_CLOSE_XRI_CN;
+@@ -3585,16 +3016,16 @@
+       wait_queue_head_t *pdone_q;
+       unsigned long iflags;
+-      spin_lock_irqsave(&phba->hbalock, iflags);
++      spin_lock_irqsave(phba->host->host_lock, iflags);
+       cmdiocbq->iocb_flag |= LPFC_IO_WAKE;
+       if (cmdiocbq->context2 && rspiocbq)
+               memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb,
+                      &rspiocbq->iocb, sizeof(IOCB_t));
+       pdone_q = cmdiocbq->context_un.wait_queue;
++      spin_unlock_irqrestore(phba->host->host_lock, iflags);
+       if (pdone_q)
+               wake_up(pdone_q);
+-      spin_unlock_irqrestore(&phba->hbalock, iflags);
+       return;
+ }
+@@ -3604,12 +3035,11 @@
+  * lpfc_sli_issue_call since the wake routine sets a unique value and by
+  * definition this is a wait function.
+  */
+-
+ int
+-lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
+-                       struct lpfc_sli_ring *pring,
+-                       struct lpfc_iocbq *piocb,
+-                       struct lpfc_iocbq *prspiocbq,
++lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
++                       struct lpfc_sli_ring * pring,
++                       struct lpfc_iocbq * piocb,
++                       struct lpfc_iocbq * prspiocbq,
+                        uint32_t timeout)
+ {
+       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
+@@ -3641,9 +3071,11 @@
+       retval = lpfc_sli_issue_iocb(phba, pring, piocb, 0);
+       if (retval == IOCB_SUCCESS) {
+               timeout_req = timeout * HZ;
++              spin_unlock_irq(phba->host->host_lock);
+               timeleft = wait_event_timeout(done_q,
+                               piocb->iocb_flag & LPFC_IO_WAKE,
+                               timeout_req);
++              spin_lock_irq(phba->host->host_lock);
+               if (piocb->iocb_flag & LPFC_IO_WAKE) {
+                       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+@@ -3685,16 +3117,16 @@
+ }
+ int
+-lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
++lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
+                        uint32_t timeout)
+ {
+       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
+       int retval;
+-      unsigned long flag;
+       /* The caller must leave context1 empty. */
+-      if (pmboxq->context1 != 0)
+-              return MBX_NOT_FINISHED;
++      if (pmboxq->context1 != 0) {
++              return (MBX_NOT_FINISHED);
++      }
+       /* setup wake call as IOCB callback */
+       pmboxq->mbox_cmpl = lpfc_sli_wake_mbox_wait;
+@@ -3709,7 +3141,6 @@
+                               pmboxq->mbox_flag & LPFC_MBX_WAKE,
+                               timeout * HZ);
+-              spin_lock_irqsave(&phba->hbalock, flag);
+               pmboxq->context1 = NULL;
+               /*
+                * if LPFC_MBX_WAKE flag is set the mailbox is completed
+@@ -3717,11 +3148,8 @@
+                */
+               if (pmboxq->mbox_flag & LPFC_MBX_WAKE)
+                       retval = MBX_SUCCESS;
+-              else {
++              else
+                       retval = MBX_TIMEOUT;
+-                      pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+-              }
+-              spin_unlock_irqrestore(&phba->hbalock, flag);
+       }
+       return retval;
+@@ -3730,25 +3158,12 @@
+ int
+ lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
+ {
+-      struct lpfc_vport *vport = phba->pport;
+       int i = 0;
+-      uint32_t ha_copy;
+-      while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !vport->stopped) {
++      while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !phba->stopped) {
+               if (i++ > LPFC_MBOX_TMO * 1000)
+                       return 1;
+-              /*
+-               * Call lpfc_sli_handle_mb_event only if a mailbox cmd
+-               * did finish. This way we won't get the misleading
+-               * "Stray Mailbox Interrupt" message.
+-               */
+-              spin_lock_irq(&phba->hbalock);
+-              ha_copy = phba->work_ha;
+-              phba->work_ha &= ~HA_MBATT;
+-              spin_unlock_irq(&phba->hbalock);
+-
+-              if (ha_copy & HA_MBATT)
+               if (lpfc_sli_handle_mb_event(phba) == 0)
+                       i = 0;
+@@ -3768,13 +3183,6 @@
+       int i;
+       uint32_t control;
+-      MAILBOX_t *mbox, *pmbox;
+-      struct lpfc_vport *vport;
+-      struct lpfc_nodelist *ndlp;
+-      struct lpfc_dmabuf *mp;
+-      LPFC_MBOXQ_t *pmb;
+-      int rc;
+-
+       /*
+        * Get the driver's phba structure from the dev_id and
+        * assume the HBA is not interrupting.
+@@ -3796,7 +3204,7 @@
+        */
+       /* Ignore all interrupts during initialization. */
+-      if (unlikely(phba->link_state < LPFC_LINK_DOWN))
++      if (unlikely(phba->hba_state < LPFC_LINK_DOWN))
+               return IRQ_NONE;
+       /*
+@@ -3804,16 +3212,16 @@
+        * Clear Attention Sources, except Error Attention (to
+        * preserve status) and Link Attention
+        */
+-      spin_lock(&phba->hbalock);
++      spin_lock(phba->host->host_lock);
+       ha_copy = readl(phba->HAregaddr);
+       /* If somebody is waiting to handle an eratt don't process it
+        * here.  The brdkill function will do this.
+        */
+-      if (phba->link_flag & LS_IGNORE_ERATT)
++      if (phba->fc_flag & FC_IGNORE_ERATT)
+               ha_copy &= ~HA_ERATT;
+       writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
+       readl(phba->HAregaddr); /* flush */
+-      spin_unlock(&phba->hbalock);
++      spin_unlock(phba->host->host_lock);
+       if (unlikely(!ha_copy))
+               return IRQ_NONE;
+@@ -3827,41 +3235,36 @@
+                                * Turn off Link Attention interrupts
+                                * until CLEAR_LA done
+                                */
+-                              spin_lock(&phba->hbalock);
++                              spin_lock(phba->host->host_lock);
+                               phba->sli.sli_flag &= ~LPFC_PROCESS_LA;
+                               control = readl(phba->HCregaddr);
+                               control &= ~HC_LAINT_ENA;
+                               writel(control, phba->HCregaddr);
+                               readl(phba->HCregaddr); /* flush */
+-                              spin_unlock(&phba->hbalock);
++                              spin_unlock(phba->host->host_lock);
+                       }
+                       else
+                               work_ha_copy &= ~HA_LATT;
+               }
+               if (work_ha_copy & ~(HA_ERATT|HA_MBATT|HA_LATT)) {
++                      for (i = 0; i < phba->sli.num_rings; i++) {
++                              if (work_ha_copy & (HA_RXATT << (4*i))) {
+                                       /*
+-                       * Turn off Slow Rings interrupts, LPFC_ELS_RING is
+-                       * the only slow ring.
++                                       * Turn off Slow Rings interrupts
+                                        */
+-                      status = (work_ha_copy &
+-                              (HA_RXMASK  << (4*LPFC_ELS_RING)));
+-                      status >>= (4*LPFC_ELS_RING);
+-                      if (status & HA_RXMASK) {
+-                              spin_lock(&phba->hbalock);
++                                      spin_lock(phba->host->host_lock);
+                                       control = readl(phba->HCregaddr);
+-                              if (control & (HC_R0INT_ENA << LPFC_ELS_RING)) {
+-                                      control &=
+-                                          ~(HC_R0INT_ENA << LPFC_ELS_RING);
++                                      control &= ~(HC_R0INT_ENA << i);
+                                       writel(control, phba->HCregaddr);
+                                       readl(phba->HCregaddr); /* flush */
++                                      spin_unlock(phba->host->host_lock);
+                               }
+-                              spin_unlock(&phba->hbalock);
+                       }
+               }
+               if (work_ha_copy & HA_ERATT) {
+-                      phba->link_state = LPFC_HBA_ERROR;
++                      phba->hba_state = LPFC_HBA_ERROR;
+                       /*
+                        * There was a link/board error.  Read the
+                        * status register to retrieve the error event
+@@ -3876,108 +3279,14 @@
+                       /* Clear Chip error bit */
+                       writel(HA_ERATT, phba->HAregaddr);
+                       readl(phba->HAregaddr); /* flush */
+-                      phba->pport->stopped = 1;
+-              }
+-
+-              if ((work_ha_copy & HA_MBATT) &&
+-                  (phba->sli.mbox_active)) {
+-                      pmb = phba->sli.mbox_active;
+-                      pmbox = &pmb->mb;
+-                      mbox = &phba->slim2p->mbx;
+-                      vport = pmb->vport;
+-
+-                      /* First check out the status word */
+-                      lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
+-                      if (pmbox->mbxOwner != OWN_HOST) {
+-                              /*
+-                               * Stray Mailbox Interrupt, mbxCommand <cmd>
+-                               * mbxStatus <status>
+-                               */
+-                              lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX |
+-                                              LOG_SLI,
+-                                              "%d (%d):0304 Stray Mailbox "
+-                                              "Interrupt mbxCommand x%x "
+-                                              "mbxStatus x%x\n",
+-                                              phba->brd_no,
+-                                              (vport
+-                                               ? vport->vpi : 0),
+-                                              pmbox->mbxCommand,
+-                                              pmbox->mbxStatus);
+-                      }
+-                      phba->last_completion_time = jiffies;
+-                      del_timer_sync(&phba->sli.mbox_tmo);
+-
+-                      phba->sli.mbox_active = NULL;
+-                      if (pmb->mbox_cmpl) {
+-                              lpfc_sli_pcimem_bcopy(mbox, pmbox,
+-                                                    MAILBOX_CMD_SIZE);
+-                      }
+-                      if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) {
+-                              pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG;
+-
+-                              lpfc_debugfs_disc_trc(vport,
+-                                      LPFC_DISC_TRC_MBOX_VPORT,
+-                                      "MBOX dflt rpi: : status:x%x rpi:x%x",
+-                                      (uint32_t)pmbox->mbxStatus,
+-                                      pmbox->un.varWords[0], 0);
+-
+-                              if ( !pmbox->mbxStatus) {
+-                                      mp = (struct lpfc_dmabuf *)
+-                                              (pmb->context1);
+-                                      ndlp = (struct lpfc_nodelist *)
+-                                              pmb->context2;
+-
+-                                      /* Reg_LOGIN of dflt RPI was successful.
+-                                       * new lets get rid of the RPI using the
+-                                       * same mbox buffer.
+-                                       */
+-                                      lpfc_unreg_login(phba, vport->vpi,
+-                                              pmbox->un.varWords[0], pmb);
+-                                      pmb->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
+-                                      pmb->context1 = mp;
+-                                      pmb->context2 = ndlp;
+-                                      pmb->vport = vport;
+-                                      spin_lock(&phba->hbalock);
+-                                      phba->sli.sli_flag &=
+-                                              ~LPFC_SLI_MBOX_ACTIVE;
+-                                      spin_unlock(&phba->hbalock);
+-                                      goto send_current_mbox;
+-                              }
+-                      }
+-                      spin_lock(&phba->pport->work_port_lock);
+-                      phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
+-                      spin_unlock(&phba->pport->work_port_lock);
+-                      lpfc_mbox_cmpl_put(phba, pmb);
+-              }
+-              if ((work_ha_copy & HA_MBATT) &&
+-                  (phba->sli.mbox_active == NULL)) {
+-send_next_mbox:
+-                      spin_lock(&phba->hbalock);
+-                      phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+-                      pmb = lpfc_mbox_get(phba);
+-                      spin_unlock(&phba->hbalock);
+-send_current_mbox:
+-                      /* Process next mailbox command if there is one */
+-                      if (pmb != NULL) {
+-                              rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+-                              if (rc == MBX_NOT_FINISHED) {
+-                                      pmb->mb.mbxStatus = MBX_NOT_FINISHED;
+-                                      lpfc_mbox_cmpl_put(phba, pmb);
+-                                      goto send_next_mbox;
+-                              }
+-                      } else {
+-                              /* Turn on IOCB processing */
+-                              for (i = 0; i < phba->sli.num_rings; i++)
+-                                      lpfc_sli_turn_on_ring(phba, i);
+-                      }
+-
++                      phba->stopped = 1;
+               }
+-              spin_lock(&phba->hbalock);
++              spin_lock(phba->host->host_lock);
+               phba->work_ha |= work_ha_copy;
+               if (phba->work_wait)
+-                      lpfc_worker_wake_up(phba);
+-              spin_unlock(&phba->hbalock);
++                      wake_up(phba->work_wait);
++              spin_unlock(phba->host->host_lock);
+       }
+       ha_copy &= ~(phba->work_ha_mask);
+@@ -3989,7 +3298,7 @@
+        */
+       status = (ha_copy & (HA_RXMASK  << (4*LPFC_FCP_RING)));
+       status >>= (4*LPFC_FCP_RING);
+-      if (status & HA_RXMASK)
++      if (status & HA_RXATT)
+               lpfc_sli_handle_fast_ring_event(phba,
+                                               &phba->sli.ring[LPFC_FCP_RING],
+                                               status);
+@@ -4002,7 +3311,7 @@
+                */
+               status = (ha_copy & (HA_RXMASK  << (4*LPFC_EXTRA_RING)));
+               status >>= (4*LPFC_EXTRA_RING);
+-              if (status & HA_RXMASK) {
++              if (status & HA_RXATT) {
+                       lpfc_sli_handle_fast_ring_event(phba,
+                                       &phba->sli.ring[LPFC_EXTRA_RING],
+                                       status);
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_sli.h linux-2.6.22-570/drivers/scsi/lpfc/lpfc_sli.h
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_sli.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_sli.h      2007-07-08 19:32:17.000000000 -0400
+@@ -20,7 +20,6 @@
+ /* forward declaration for LPFC_IOCB_t's use */
+ struct lpfc_hba;
+-struct lpfc_vport;
+ /* Define the context types that SLI handles for abort and sums. */
+ typedef enum _lpfc_ctx_cmd {
+@@ -44,12 +43,10 @@
+ #define LPFC_IO_WAKE          2       /* High Priority Queue signal flag */
+ #define LPFC_IO_FCP           4       /* FCP command -- iocbq in scsi_buf */
+ #define LPFC_DRIVER_ABORTED   8       /* driver aborted this request */
+-#define LPFC_IO_FABRIC                0x10    /* Iocb send using fabric scheduler */
+       uint8_t abort_count;
+       uint8_t rsvd2;
+       uint32_t drvrTimeout;   /* driver timeout in seconds */
+-      struct lpfc_vport *vport;/* virtual port pointer */
+       void *context1;         /* caller context information */
+       void *context2;         /* caller context information */
+       void *context3;         /* caller context information */
+@@ -59,8 +56,6 @@
+               struct lpfcMboxq   *mbox;
+       } context_un;
+-      void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
+-                         struct lpfc_iocbq *);
+       void (*iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
+                          struct lpfc_iocbq *);
+@@ -74,13 +69,11 @@
+ #define IOCB_TIMEDOUT       3
+ #define LPFC_MBX_WAKE 1
+-#define LPFC_MBX_IMED_UNREG   2
+ typedef struct lpfcMboxq {
+       /* MBOXQs are used in single linked lists */
+       struct list_head list;  /* ptr to next mailbox command */
+       MAILBOX_t mb;           /* Mailbox cmd */
+-      struct lpfc_vport *vport;/* virutal port pointer */
+       void *context1;         /* caller context information */
+       void *context2;         /* caller context information */
+@@ -142,8 +135,6 @@
+       uint8_t ringno;         /* ring number */
+       uint16_t numCiocb;      /* number of command iocb's per ring */
+       uint16_t numRiocb;      /* number of rsp iocb's per ring */
+-      uint16_t sizeCiocb;     /* Size of command iocb's in this ring */
+-      uint16_t sizeRiocb;     /* Size of response iocb's in this ring */
+       uint32_t fast_iotag;    /* max fastlookup based iotag           */
+       uint32_t iotag_ctr;     /* keeps track of the next iotag to use */
+@@ -174,34 +165,6 @@
+                                       struct lpfc_sli_ring *);
+ };
+-/* Structure used for configuring rings to a specific profile or rctl / type */
+-struct lpfc_hbq_init {
+-      uint32_t rn;            /* Receive buffer notification */
+-      uint32_t entry_count;   /* max # of entries in HBQ */
+-      uint32_t headerLen;     /* 0 if not profile 4 or 5 */
+-      uint32_t logEntry;      /* Set to 1 if this HBQ used for LogEntry */
+-      uint32_t profile;       /* Selection profile 0=all, 7=logentry */
+-      uint32_t ring_mask;     /* Binds HBQ to a ring e.g. Ring0=b0001,
+-                               * ring2=b0100 */
+-      uint32_t hbq_index;     /* index of this hbq in ring .HBQs[] */
+-
+-      uint32_t seqlenoff;
+-      uint32_t maxlen;
+-      uint32_t seqlenbcnt;
+-      uint32_t cmdcodeoff;
+-      uint32_t cmdmatch[8];
+-      uint32_t mask_count;    /* number of mask entries in prt array */
+-      struct hbq_mask hbqMasks[6];
+-
+-      /* Non-config rings fields to keep track of buffer allocations */
+-      uint32_t buffer_count;  /* number of buffers allocated */
+-      uint32_t init_count;    /* number to allocate when initialized */
+-      uint32_t add_count;     /* number to allocate when starved */
+-} ;
+-
+-#define LPFC_MAX_HBQ 16
+-
+-
+ /* Structure used to hold SLI statistical counters and info */
+ struct lpfc_sli_stat {
+       uint64_t mbox_stat_err;  /* Mbox cmds completed status error */
+@@ -234,7 +197,6 @@
+ #define LPFC_SLI_MBOX_ACTIVE      0x100       /* HBA mailbox is currently active */
+ #define LPFC_SLI2_ACTIVE          0x200       /* SLI2 overlay in firmware is active */
+ #define LPFC_PROCESS_LA           0x400       /* Able to process link attention */
+-#define LPFC_BLOCK_MGMT_IO        0x800       /* Don't allow mgmt mbx or iocb cmds */
+       struct lpfc_sli_ring ring[LPFC_MAX_RING];
+       int fcp_ring;           /* ring used for FCP initiator commands */
+@@ -247,7 +209,6 @@
+       uint16_t mboxq_cnt;     /* current length of queue */
+       uint16_t mboxq_max;     /* max length */
+       LPFC_MBOXQ_t *mbox_active;      /* active mboxq information */
+-      struct list_head mboxq_cmpl;
+       struct timer_list mbox_tmo;     /* Hold clk to timeout active mbox
+                                          cmd */
+@@ -260,6 +221,12 @@
+       struct lpfc_lnk_stat lnk_stat_offsets;
+ };
++/* Given a pointer to the start of the ring, and the slot number of
++ * the desired iocb entry, calc a pointer to that entry.
++ * (assume iocb entry size is 32 bytes, or 8 words)
++ */
++#define IOCB_ENTRY(ring,slot) ((IOCB_t *)(((char *)(ring)) + ((slot) * 32)))
 +
-+      spin_lock(&UNIONFS_I(inode)->rdlock);
-+      list_for_each(pos, &UNIONFS_I(inode)->readdircache) {
-+              struct unionfs_dir_state *r =
-+                      list_entry(pos, struct unionfs_dir_state, cache);
-+              if (fpos == rdstate2offset(r)) {
-+                      UNIONFS_I(inode)->rdcount--;
-+                      list_del(&r->cache);
-+                      rdstate = r;
-+                      break;
+ #define LPFC_MBOX_TMO           30    /* Sec tmo for outstanding mbox
+                                          command */
+ #define LPFC_MBOX_TMO_FLASH_CMD 300     /* Sec tmo for outstanding FLASH write
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_version.h linux-2.6.22-570/drivers/scsi/lpfc/lpfc_version.h
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_version.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_version.h  2007-07-08 19:32:17.000000000 -0400
+@@ -18,7 +18,7 @@
+  * included with this package.                                     *
+  *******************************************************************/
+-#define LPFC_DRIVER_VERSION "8.2.1"
++#define LPFC_DRIVER_VERSION "8.1.12"
+ #define LPFC_DRIVER_NAME "lpfc"
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_vport.c linux-2.6.22-570/drivers/scsi/lpfc/lpfc_vport.c
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_vport.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_vport.c    1969-12-31 19:00:00.000000000 -0500
+@@ -1,523 +0,0 @@
+-/*******************************************************************
+- * This file is part of the Emulex Linux Device Driver for         *
+- * Fibre Channel Host Bus Adapters.                                *
+- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+- * EMULEX and SLI are trademarks of Emulex.                        *
+- * www.emulex.com                                                  *
+- * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
+- *                                                                 *
+- * This program is free software; you can redistribute it and/or   *
+- * modify it under the terms of version 2 of the GNU General       *
+- * Public License as published by the Free Software Foundation.    *
+- * This program is distributed in the hope that it will be useful. *
+- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
+- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
+- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
+- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+- * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
+- * more details, a copy of which can be found in the file COPYING  *
+- * included with this package.                                     *
+- *******************************************************************/
+-
+-#include <linux/blkdev.h>
+-#include <linux/delay.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/idr.h>
+-#include <linux/interrupt.h>
+-#include <linux/kthread.h>
+-#include <linux/pci.h>
+-#include <linux/spinlock.h>
+-
+-#include <scsi/scsi.h>
+-#include <scsi/scsi_device.h>
+-#include <scsi/scsi_host.h>
+-#include <scsi/scsi_transport_fc.h>
+-#include "lpfc_hw.h"
+-#include "lpfc_sli.h"
+-#include "lpfc_disc.h"
+-#include "lpfc_scsi.h"
+-#include "lpfc.h"
+-#include "lpfc_logmsg.h"
+-#include "lpfc_crtn.h"
+-#include "lpfc_version.h"
+-#include "lpfc_vport.h"
+-
+-inline void lpfc_vport_set_state(struct lpfc_vport *vport,
+-                               enum fc_vport_state new_state)
+-{
+-      struct fc_vport *fc_vport = vport->fc_vport;
+-
+-      if (fc_vport) {
+-              /*
+-               * When the transport defines fc_vport_set state we will replace
+-               * this code with the following line
+-               */
+-              /* fc_vport_set_state(fc_vport, new_state); */
+-              if (new_state != FC_VPORT_INITIALIZING)
+-                      fc_vport->vport_last_state = fc_vport->vport_state;
+-              fc_vport->vport_state = new_state;
+-      }
+-
+-      /* for all the error states we will set the invternal state to FAILED */
+-      switch (new_state) {
+-      case FC_VPORT_NO_FABRIC_SUPP:
+-      case FC_VPORT_NO_FABRIC_RSCS:
+-      case FC_VPORT_FABRIC_LOGOUT:
+-      case FC_VPORT_FABRIC_REJ_WWN:
+-      case FC_VPORT_FAILED:
+-              vport->port_state = LPFC_VPORT_FAILED;
+-              break;
+-      case FC_VPORT_LINKDOWN:
+-              vport->port_state = LPFC_VPORT_UNKNOWN;
+-              break;
+-      default:
+-              /* do nothing */
+-              break;
+-      }
+-}
+-
+-static int
+-lpfc_alloc_vpi(struct lpfc_hba *phba)
+-{
+-      int  vpi;
+-
+-      spin_lock_irq(&phba->hbalock);
+-      /* Start at bit 1 because vpi zero is reserved for the physical port */
+-      vpi = find_next_zero_bit(phba->vpi_bmask, (phba->max_vpi + 1), 1);
+-      if (vpi > phba->max_vpi)
+-              vpi = 0;
+-      else
+-              set_bit(vpi, phba->vpi_bmask);
+-      spin_unlock_irq(&phba->hbalock);
+-      return vpi;
+-}
+-
+-static void
+-lpfc_free_vpi(struct lpfc_hba *phba, int vpi)
+-{
+-      spin_lock_irq(&phba->hbalock);
+-      clear_bit(vpi, phba->vpi_bmask);
+-      spin_unlock_irq(&phba->hbalock);
+-}
+-
+-static int
+-lpfc_vport_sparm(struct lpfc_hba *phba, struct lpfc_vport *vport)
+-{
+-      LPFC_MBOXQ_t *pmb;
+-      MAILBOX_t *mb;
+-      struct lpfc_dmabuf *mp;
+-      int  rc;
+-
+-      pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+-      if (!pmb) {
+-              return -ENOMEM;
+-      }
+-      mb = &pmb->mb;
+-
+-      lpfc_read_sparam(phba, pmb, vport->vpi);
+-      /*
+-       * Grab buffer pointer and clear context1 so we can use
+-       * lpfc_sli_issue_box_wait
+-       */
+-      mp = (struct lpfc_dmabuf *) pmb->context1;
+-      pmb->context1 = NULL;
+-
+-      pmb->vport = vport;
+-      rc = lpfc_sli_issue_mbox_wait(phba, pmb, phba->fc_ratov * 2);
+-      if (rc != MBX_SUCCESS) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
+-                              "%d (%d):1818 VPort failed init, mbxCmd x%x "
+-                              "READ_SPARM mbxStatus x%x, rc = x%x\n",
+-                              phba->brd_no, vport->vpi,
+-                              mb->mbxCommand, mb->mbxStatus, rc);
+-              lpfc_mbuf_free(phba, mp->virt, mp->phys);
+-              kfree(mp);
+-              if (rc != MBX_TIMEOUT)
+-                      mempool_free(pmb, phba->mbox_mem_pool);
+-              return -EIO;
+-      }
+-
+-      memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
+-      memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
+-             sizeof (struct lpfc_name));
+-      memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
+-             sizeof (struct lpfc_name));
+-
+-      lpfc_mbuf_free(phba, mp->virt, mp->phys);
+-      kfree(mp);
+-      mempool_free(pmb, phba->mbox_mem_pool);
+-
+-      return 0;
+-}
+-
+-static int
+-lpfc_valid_wwn_format(struct lpfc_hba *phba, struct lpfc_name *wwn,
+-                    const char *name_type)
+-{
+-                              /* ensure that IEEE format 1 addresses
+-                               * contain zeros in bits 59-48
+-                               */
+-      if (!((wwn->u.wwn[0] >> 4) == 1 &&
+-            ((wwn->u.wwn[0] & 0xf) != 0 || (wwn->u.wwn[1] & 0xf) != 0)))
+-              return 1;
+-
+-      lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+-                      "%d:1822 Invalid %s: %02x:%02x:%02x:%02x:"
+-                      "%02x:%02x:%02x:%02x\n",
+-                      phba->brd_no, name_type,
+-                      wwn->u.wwn[0], wwn->u.wwn[1],
+-                      wwn->u.wwn[2], wwn->u.wwn[3],
+-                      wwn->u.wwn[4], wwn->u.wwn[5],
+-                      wwn->u.wwn[6], wwn->u.wwn[7]);
+-      return 0;
+-}
+-
+-static int
+-lpfc_unique_wwpn(struct lpfc_hba *phba, struct lpfc_vport *new_vport)
+-{
+-      struct lpfc_vport *vport;
+-
+-      list_for_each_entry(vport, &phba->port_list, listentry) {
+-              if (vport == new_vport)
+-                      continue;
+-              /* If they match, return not unique */
+-              if (memcmp(&vport->fc_sparam.portName,
+-                      &new_vport->fc_sparam.portName,
+-                      sizeof(struct lpfc_name)) == 0)
+-                      return 0;
+-      }
+-      return 1;
+-}
+-
+-int
+-lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
+-{
+-      struct lpfc_nodelist *ndlp;
+-      struct lpfc_vport *pport =
+-              (struct lpfc_vport *) fc_vport->shost->hostdata;
+-      struct lpfc_hba   *phba = pport->phba;
+-      struct lpfc_vport *vport = NULL;
+-      int instance;
+-      int vpi;
+-      int rc = VPORT_ERROR;
+-
+-      if ((phba->sli_rev < 3) ||
+-              !(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+-                              "%d:1808 Create VPORT failed: "
+-                              "NPIV is not enabled: SLImode:%d\n",
+-                              phba->brd_no, phba->sli_rev);
+-              rc = VPORT_INVAL;
+-              goto error_out;
+-      }
+-
+-      vpi = lpfc_alloc_vpi(phba);
+-      if (vpi == 0) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+-                              "%d:1809 Create VPORT failed: "
+-                              "Max VPORTs (%d) exceeded\n",
+-                              phba->brd_no, phba->max_vpi);
+-              rc = VPORT_NORESOURCES;
+-              goto error_out;
+-      }
+-
+-
+-      /* Assign an unused board number */
+-      if ((instance = lpfc_get_instance()) < 0) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+-                              "%d:1810 Create VPORT failed: Cannot get "
+-                              "instance number\n", phba->brd_no);
+-              lpfc_free_vpi(phba, vpi);
+-              rc = VPORT_NORESOURCES;
+-              goto error_out;
+-      }
+-
+-      vport = lpfc_create_port(phba, instance, fc_vport);
+-      if (!vport) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+-                              "%d:1811 Create VPORT failed: vpi x%x\n",
+-                              phba->brd_no, vpi);
+-              lpfc_free_vpi(phba, vpi);
+-              rc = VPORT_NORESOURCES;
+-              goto error_out;
+-      }
+-
+-      vport->vpi = vpi;
+-      lpfc_debugfs_initialize(vport);
+-
+-      if (lpfc_vport_sparm(phba, vport)) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+-                              "%d:1813 Create VPORT failed: vpi:%d "
+-                              "Cannot get sparam\n",
+-                              phba->brd_no, vpi);
+-              lpfc_free_vpi(phba, vpi);
+-              destroy_port(vport);
+-              rc = VPORT_NORESOURCES;
+-              goto error_out;
+-      }
+-
+-      memcpy(vport->fc_portname.u.wwn, vport->fc_sparam.portName.u.wwn, 8);
+-      memcpy(vport->fc_nodename.u.wwn, vport->fc_sparam.nodeName.u.wwn, 8);
+-
+-      if (fc_vport->node_name != 0)
+-              u64_to_wwn(fc_vport->node_name, vport->fc_nodename.u.wwn);
+-      if (fc_vport->port_name != 0)
+-              u64_to_wwn(fc_vport->port_name, vport->fc_portname.u.wwn);
+-
+-      memcpy(&vport->fc_sparam.portName, vport->fc_portname.u.wwn, 8);
+-      memcpy(&vport->fc_sparam.nodeName, vport->fc_nodename.u.wwn, 8);
+-
+-      if (!lpfc_valid_wwn_format(phba, &vport->fc_sparam.nodeName, "WWNN") ||
+-          !lpfc_valid_wwn_format(phba, &vport->fc_sparam.portName, "WWPN")) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+-                              "%d:1821 Create VPORT failed: vpi:%d "
+-                              "Invalid WWN format\n",
+-                              phba->brd_no, vpi);
+-              lpfc_free_vpi(phba, vpi);
+-              destroy_port(vport);
+-              rc = VPORT_INVAL;
+-              goto error_out;
+-      }
+-
+-      if (!lpfc_unique_wwpn(phba, vport)) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+-                              "%d:1823 Create VPORT failed: vpi:%d "
+-                              "Duplicate WWN on HBA\n",
+-                              phba->brd_no, vpi);
+-              lpfc_free_vpi(phba, vpi);
+-              destroy_port(vport);
+-              rc = VPORT_INVAL;
+-              goto error_out;
+-      }
+-
+-      *(struct lpfc_vport **)fc_vport->dd_data = vport;
+-      vport->fc_vport = fc_vport;
+-
+-      if ((phba->link_state < LPFC_LINK_UP) ||
+-          (phba->fc_topology == TOPOLOGY_LOOP)) {
+-              lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
+-              rc = VPORT_OK;
+-              goto out;
+-      }
+-
+-      if (disable) {
+-              rc = VPORT_OK;
+-              goto out;
+-      }
+-
+-      /* Use the Physical nodes Fabric NDLP to determine if the link is
+-       * up and ready to FDISC.
+-       */
+-      ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
+-      if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
+-              if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
+-                      lpfc_set_disctmo(vport);
+-                      lpfc_initial_fdisc(vport);
+-              } else {
+-                      lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                                      "%d (%d):0262 No NPIV Fabric "
+-                                      "support\n",
+-                                      phba->brd_no, vport->vpi);
+-              }
+-      } else {
+-              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-      }
+-      rc = VPORT_OK;
+-
+-out:
+-      lpfc_host_attrib_init(lpfc_shost_from_vport(vport));
+-error_out:
+-      return rc;
+-}
+-
+-int
+-disable_vport(struct fc_vport *fc_vport)
+-{
+-      struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
+-      struct lpfc_hba   *phba = vport->phba;
+-      struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
+-      long timeout;
+-
+-      ndlp = lpfc_findnode_did(vport, Fabric_DID);
+-      if (ndlp && phba->link_state >= LPFC_LINK_UP) {
+-              vport->unreg_vpi_cmpl = VPORT_INVAL;
+-              timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
+-              if (!lpfc_issue_els_npiv_logo(vport, ndlp))
+-                      while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
+-                              timeout = schedule_timeout(timeout);
+-      }
+-
+-      lpfc_sli_host_down(vport);
+-
+-      /* Mark all nodes for discovery so we can remove them by
+-       * calling lpfc_cleanup_rpis(vport, 1)
+-       */
+-      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+-              if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
+-                      continue;
+-              lpfc_disc_state_machine(vport, ndlp, NULL,
+-                                      NLP_EVT_DEVICE_RECOVERY);
+-      }
+-      lpfc_cleanup_rpis(vport, 1);
+-
+-      lpfc_stop_vport_timers(vport);
+-      lpfc_unreg_all_rpis(vport);
+-      lpfc_unreg_default_rpis(vport);
+-      /*
+-       * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) does the
+-       * scsi_host_put() to release the vport.
+-       */
+-      lpfc_mbx_unreg_vpi(vport);
+-
+-      lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
+-      return VPORT_OK;
+-}
+-
+-int
+-enable_vport(struct fc_vport *fc_vport)
+-{
+-      struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
+-      struct lpfc_hba   *phba = vport->phba;
+-      struct lpfc_nodelist *ndlp = NULL;
+-
+-      if ((phba->link_state < LPFC_LINK_UP) ||
+-          (phba->fc_topology == TOPOLOGY_LOOP)) {
+-              lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
+-              return VPORT_OK;
+-      }
+-
+-      vport->load_flag |= FC_LOADING;
+-      vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+-
+-      /* Use the Physical nodes Fabric NDLP to determine if the link is
+-       * up and ready to FDISC.
+-       */
+-      ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
+-      if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
+-              if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
+-                      lpfc_set_disctmo(vport);
+-                      lpfc_initial_fdisc(vport);
+-              } else {
+-                      lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
+-                      lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+-                                      "%d (%d):0264 No NPIV Fabric "
+-                                      "support\n",
+-                                      phba->brd_no, vport->vpi);
+-              }
+-      } else {
+-              lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+-      }
+-
+-      return VPORT_OK;
+-}
+-
+-int
+-lpfc_vport_disable(struct fc_vport *fc_vport, bool disable)
+-{
+-      if (disable)
+-              return disable_vport(fc_vport);
+-      else
+-              return enable_vport(fc_vport);
+-}
+-
+-
+-int
+-lpfc_vport_delete(struct fc_vport *fc_vport)
+-{
+-      struct lpfc_nodelist *ndlp = NULL;
+-      struct lpfc_nodelist *next_ndlp;
+-      struct Scsi_Host *shost = (struct Scsi_Host *) fc_vport->shost;
+-      struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
+-      struct lpfc_hba   *phba = vport->phba;
+-      long timeout;
+-      int rc = VPORT_ERROR;
+-
+-      /*
+-       * This is a bit of a mess.  We want to ensure the shost doesn't get
+-       * torn down until we're done with the embedded lpfc_vport structure.
+-       *
+-       * Beyond holding a reference for this function, we also need a
+-       * reference for outstanding I/O requests we schedule during delete
+-       * processing.  But once we scsi_remove_host() we can no longer obtain
+-       * a reference through scsi_host_get().
+-       *
+-       * So we take two references here.  We release one reference at the
+-       * bottom of the function -- after delinking the vport.  And we
+-       * release the other at the completion of the unreg_vpi that get's
+-       * initiated after we've disposed of all other resources associated
+-       * with the port.
+-       */
+-      if (!scsi_host_get(shost) || !scsi_host_get(shost))
+-              return VPORT_INVAL;
+-
+-      if (vport->port_type == LPFC_PHYSICAL_PORT) {
+-              lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+-                              "%d:1812 vport_delete failed: Cannot delete "
+-                              "physical host\n", phba->brd_no);
+-              goto out;
+-      }
+-
+-      vport->load_flag |= FC_UNLOADING;
+-
+-      kfree(vport->vname);
+-      lpfc_debugfs_terminate(vport);
+-      fc_remove_host(lpfc_shost_from_vport(vport));
+-      scsi_remove_host(lpfc_shost_from_vport(vport));
+-
+-      ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
+-      if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
+-              phba->link_state >= LPFC_LINK_UP) {
+-
+-              /* First look for the Fabric ndlp */
+-              ndlp = lpfc_findnode_did(vport, Fabric_DID);
+-              if (!ndlp) {
+-                      /* Cannot find existing Fabric ndlp, allocate one */
+-                      ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+-                      if (!ndlp)
+-                              goto skip_logo;
+-                      lpfc_nlp_init(vport, ndlp, Fabric_DID);
+-              } else {
+-                      lpfc_dequeue_node(vport, ndlp);
+-              }
+-              vport->unreg_vpi_cmpl = VPORT_INVAL;
+-              timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
+-              if (!lpfc_issue_els_npiv_logo(vport, ndlp))
+-                      while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
+-                              timeout = schedule_timeout(timeout);
+-      }
+-
+-skip_logo:
+-      lpfc_sli_host_down(vport);
+-
+-      list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+-              lpfc_disc_state_machine(vport, ndlp, NULL,
+-                                           NLP_EVT_DEVICE_RECOVERY);
+-              lpfc_disc_state_machine(vport, ndlp, NULL,
+-                                           NLP_EVT_DEVICE_RM);
+-      }
+-
+-      lpfc_stop_vport_timers(vport);
+-      lpfc_unreg_all_rpis(vport);
+-      lpfc_unreg_default_rpis(vport);
+-      /*
+-       * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) does the
+-       * scsi_host_put() to release the vport.
+-       */
+-      lpfc_mbx_unreg_vpi(vport);
+-
+-      lpfc_free_vpi(phba, vport->vpi);
+-      vport->work_port_events = 0;
+-      spin_lock_irq(&phba->hbalock);
+-      list_del_init(&vport->listentry);
+-      spin_unlock_irq(&phba->hbalock);
+-
+-      rc = VPORT_OK;
+-out:
+-      scsi_host_put(shost);
+-      return rc;
+-}
+-
+-
+-EXPORT_SYMBOL(lpfc_vport_create);
+-EXPORT_SYMBOL(lpfc_vport_delete);
+diff -Nurb linux-2.6.22-590/drivers/scsi/lpfc/lpfc_vport.h linux-2.6.22-570/drivers/scsi/lpfc/lpfc_vport.h
+--- linux-2.6.22-590/drivers/scsi/lpfc/lpfc_vport.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/lpfc/lpfc_vport.h    1969-12-31 19:00:00.000000000 -0500
+@@ -1,113 +0,0 @@
+-/*******************************************************************
+- * This file is part of the Emulex Linux Device Driver for         *
+- * Fibre Channel Host Bus Adapters.                                *
+- * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+- * EMULEX and SLI are trademarks of Emulex.                        *
+- * www.emulex.com                                                  *
+- * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
+- *                                                                 *
+- * This program is free software; you can redistribute it and/or   *
+- * modify it under the terms of version 2 of the GNU General       *
+- * Public License as published by the Free Software Foundation.    *
+- * This program is distributed in the hope that it will be useful. *
+- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
+- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
+- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
+- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
+- * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
+- * more details, a copy of which can be found in the file COPYING  *
+- * included with this package.                                     *
+- *******************************************************************/
+-
+-#ifndef _H_LPFC_VPORT
+-#define _H_LPFC_VPORT
+-
+-/* API version values (each will be an individual bit) */
+-#define VPORT_API_VERSION_1   0x01
+-
+-/* Values returned via lpfc_vport_getinfo() */
+-struct vport_info {
+-
+-      uint32_t api_versions;
+-      uint8_t linktype;
+-#define  VPORT_TYPE_PHYSICAL  0
+-#define  VPORT_TYPE_VIRTUAL   1
+-
+-      uint8_t state;
+-#define  VPORT_STATE_OFFLINE  0
+-#define  VPORT_STATE_ACTIVE   1
+-#define  VPORT_STATE_FAILED   2
+-
+-      uint8_t fail_reason;
+-      uint8_t prev_fail_reason;
+-#define  VPORT_FAIL_UNKNOWN   0
+-#define  VPORT_FAIL_LINKDOWN  1
+-#define  VPORT_FAIL_FAB_UNSUPPORTED   2
+-#define  VPORT_FAIL_FAB_NORESOURCES   3
+-#define  VPORT_FAIL_FAB_LOGOUT        4
+-#define  VPORT_FAIL_ADAP_NORESOURCES  5
+-
+-      uint8_t node_name[8];   /* WWNN */
+-      uint8_t port_name[8];   /* WWPN */
+-
+-      struct Scsi_Host *shost;
+-
+-/* Following values are valid only on physical links */
+-      uint32_t vports_max;
+-      uint32_t vports_inuse;
+-      uint32_t rpi_max;
+-      uint32_t rpi_inuse;
+-#define  VPORT_CNT_INVALID    0xFFFFFFFF
+-};
+-
+-/* data used  in link creation */
+-struct vport_data {
+-      uint32_t api_version;
+-
+-      uint32_t options;
+-#define  VPORT_OPT_AUTORETRY  0x01
+-
+-      uint8_t node_name[8];   /* WWNN */
+-      uint8_t port_name[8];   /* WWPN */
+-
+-/*
+- *  Upon successful creation, vport_shost will point to the new Scsi_Host
+- *  structure for the new virtual link.
+- */
+-      struct Scsi_Host *vport_shost;
+-};
+-
+-/* API function return codes */
+-#define VPORT_OK      0
+-#define VPORT_ERROR   -1
+-#define VPORT_INVAL   -2
+-#define VPORT_NOMEM   -3
+-#define VPORT_NORESOURCES     -4
+-
+-int lpfc_vport_create(struct fc_vport *, bool);
+-int lpfc_vport_delete(struct fc_vport *);
+-int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *);
+-int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint);
+-
+-/*
+- *  queuecommand  VPORT-specific return codes. Specified in  the host byte code.
+- *  Returned when the virtual link has failed or is not active.
+- */
+-#define  DID_VPORT_ERROR      0x0f
+-
+-#define VPORT_INFO    0x1
+-#define VPORT_CREATE  0x2
+-#define VPORT_DELETE  0x4
+-
+-struct vport_cmd_tag {
+-      uint32_t cmd;
+-      struct vport_data cdata;
+-      struct vport_info cinfo;
+-      void *vport;
+-      int vport_num;
+-};
+-
+-void lpfc_vport_set_state(struct lpfc_vport *vport,
+-                        enum fc_vport_state new_state);
+-
+-#endif /* H_LPFC_VPORT */
+diff -Nurb linux-2.6.22-590/drivers/scsi/mac53c94.c linux-2.6.22-570/drivers/scsi/mac53c94.c
+--- linux-2.6.22-590/drivers/scsi/mac53c94.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/mac53c94.c   2007-07-08 19:32:17.000000000 -0400
+@@ -77,7 +77,7 @@
+               for (i = 0; i < cmd->cmd_len; ++i)
+                       printk(" %.2x", cmd->cmnd[i]);
+               printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n",
+-                     scsi_sg_count(cmd), scsi_bufflen(cmd), scsi_sglist(cmd));
++                     cmd->use_sg, cmd->request_bufflen, cmd->request_buffer);
+       }
+ #endif
+@@ -173,6 +173,7 @@
+       writeb(CMD_SELECT, &regs->command);
+       state->phase = selecting;
++      if (cmd->use_sg > 0 || cmd->request_bufflen != 0)
+               set_dma_cmds(state, cmd);
+ }
+@@ -261,7 +262,7 @@
+               writeb(CMD_NOP, &regs->command);
+               /* set DMA controller going if any data to transfer */
+               if ((stat & (STAT_MSG|STAT_CD)) == 0
+-                  && (scsi_sg_count(cmd) > 0 || scsi_bufflen(cmd))) {
++                  && (cmd->use_sg > 0 || cmd->request_bufflen != 0)) {
+                       nb = cmd->SCp.this_residual;
+                       if (nb > 0xfff0)
+                               nb = 0xfff0;
+@@ -309,7 +310,14 @@
+                       printk(KERN_DEBUG "intr %x before data xfer complete\n", intr);
+               }
+               writel(RUN << 16, &dma->control);       /* stop dma */
+-              scsi_dma_unmap(cmd);
++              if (cmd->use_sg != 0) {
++                      pci_unmap_sg(state->pdev,
++                              (struct scatterlist *)cmd->request_buffer,
++                              cmd->use_sg, cmd->sc_data_direction);
++              } else {
++                      pci_unmap_single(state->pdev, state->dma_addr,
++                              cmd->request_bufflen, cmd->sc_data_direction);
 +              }
-+      }
-+      spin_unlock(&UNIONFS_I(inode)->rdlock);
-+      return rdstate;
-+}
-+
-+struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex)
-+{
-+      int i = 0;
-+      int hashsize;
-+      unsigned long mallocsize = sizeof(struct unionfs_dir_state);
-+      struct unionfs_dir_state *rdstate;
-+
-+      hashsize = guesstimate_hash_size(inode);
-+      mallocsize += hashsize * sizeof(struct list_head);
-+      mallocsize = __roundup_pow_of_two(mallocsize);
-+
-+      /* This should give us about 500 entries anyway. */
-+      if (mallocsize > PAGE_SIZE)
-+              mallocsize = PAGE_SIZE;
-+
-+      hashsize = (mallocsize - sizeof(struct unionfs_dir_state)) /
-+              sizeof(struct list_head);
-+
-+      rdstate = kmalloc(mallocsize, GFP_KERNEL);
-+      if (!rdstate)
-+              return NULL;
-+
-+      spin_lock(&UNIONFS_I(inode)->rdlock);
-+      if (UNIONFS_I(inode)->cookie >= (MAXRDCOOKIE - 1))
-+              UNIONFS_I(inode)->cookie = 1;
-+      else
-+              UNIONFS_I(inode)->cookie++;
-+
-+      rdstate->cookie = UNIONFS_I(inode)->cookie;
-+      spin_unlock(&UNIONFS_I(inode)->rdlock);
-+      rdstate->offset = 1;
-+      rdstate->access = jiffies;
-+      rdstate->bindex = bindex;
-+      rdstate->dirpos = 0;
-+      rdstate->hashentries = 0;
-+      rdstate->size = hashsize;
-+      for (i = 0; i < rdstate->size; i++)
-+              INIT_LIST_HEAD(&rdstate->list[i]);
-+
-+      return rdstate;
-+}
-+
-+static void free_filldir_node(struct filldir_node *node)
-+{
-+      if (node->namelen >= DNAME_INLINE_LEN_MIN)
-+              kfree(node->name);
-+      kmem_cache_free(unionfs_filldir_cachep, node);
-+}
-+
-+void free_rdstate(struct unionfs_dir_state *state)
-+{
-+      struct filldir_node *tmp;
-+      int i;
-+
-+      for (i = 0; i < state->size; i++) {
-+              struct list_head *head = &(state->list[i]);
-+              struct list_head *pos, *n;
-+
-+              /* traverse the list and deallocate space */
-+              list_for_each_safe(pos, n, head) {
-+                      tmp = list_entry(pos, struct filldir_node, file_list);
-+                      list_del(&tmp->file_list);
-+                      free_filldir_node(tmp);
+               /* should check dma status */
+               writeb(CMD_I_COMPLETE, &regs->command);
+               state->phase = completing;
+@@ -357,23 +365,23 @@
+  */
+ static void set_dma_cmds(struct fsc_state *state, struct scsi_cmnd *cmd)
+ {
+-      int i, dma_cmd, total, nseg;
++      int i, dma_cmd, total;
+       struct scatterlist *scl;
+       struct dbdma_cmd *dcmds;
+       dma_addr_t dma_addr;
+       u32 dma_len;
+-      nseg = scsi_dma_map(cmd);
+-      BUG_ON(nseg < 0);
+-      if (!nseg)
+-              return;
+-
+       dma_cmd = cmd->sc_data_direction == DMA_TO_DEVICE ?
+                       OUTPUT_MORE : INPUT_MORE;
+       dcmds = state->dma_cmds;
+-              total = 0;
++      if (cmd->use_sg > 0) {
++              int nseg;
+-      scsi_for_each_sg(cmd, scl, nseg, i) {
++              total = 0;
++              scl = (struct scatterlist *) cmd->request_buffer;
++              nseg = pci_map_sg(state->pdev, scl, cmd->use_sg,
++                              cmd->sc_data_direction);
++              for (i = 0; i < nseg; ++i) {
+                       dma_addr = sg_dma_address(scl);
+                       dma_len = sg_dma_len(scl);
+                       if (dma_len > 0xffff)
+@@ -383,9 +391,21 @@
+                       st_le16(&dcmds->command, dma_cmd);
+                       st_le32(&dcmds->phy_addr, dma_addr);
+                       dcmds->xfer_status = 0;
++                      ++scl;
++                      ++dcmds;
 +              }
-+      }
-+
-+      kfree(state);
-+}
-+
-+struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
-+                                     const char *name, int namelen)
-+{
-+      int index;
-+      unsigned int hash;
-+      struct list_head *head;
-+      struct list_head *pos;
-+      struct filldir_node *cursor = NULL;
-+      int found = 0;
++      } else {
++              total = cmd->request_bufflen;
++              if (total > 0xffff)
++                      panic("mac53c94: transfer size >= 64k");
++              dma_addr = pci_map_single(state->pdev, cmd->request_buffer,
++                                        total, cmd->sc_data_direction);
++              state->dma_addr = dma_addr;
++              st_le16(&dcmds->req_count, total);
++              st_le32(&dcmds->phy_addr, dma_addr);
++              dcmds->xfer_status = 0;
+               ++dcmds;
+       }
+-
+       dma_cmd += OUTPUT_LAST - OUTPUT_MORE;
+       st_le16(&dcmds[-1].command, dma_cmd);
+       st_le16(&dcmds->command, DBDMA_STOP);
+diff -Nurb linux-2.6.22-590/drivers/scsi/megaraid/megaraid_mbox.c linux-2.6.22-570/drivers/scsi/megaraid/megaraid_mbox.c
+--- linux-2.6.22-590/drivers/scsi/megaraid/megaraid_mbox.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/megaraid/megaraid_mbox.c     2007-07-08 19:32:17.000000000 -0400
+@@ -1378,6 +1378,8 @@
+ {
+       struct scatterlist      *sgl;
+       mbox_ccb_t              *ccb;
++      struct page             *page;
++      unsigned long           offset;
+       struct scsi_cmnd        *scp;
+       int                     sgcnt;
+       int                     i;
+@@ -1386,16 +1388,48 @@
+       scp     = scb->scp;
+       ccb     = (mbox_ccb_t *)scb->ccb;
+-      sgcnt = scsi_dma_map(scp);
+-      BUG_ON(sgcnt < 0 || sgcnt > adapter->sglen);
+-
+       // no mapping required if no data to be transferred
+-      if (!sgcnt)
++      if (!scp->request_buffer || !scp->request_bufflen)
+               return 0;
++      if (!scp->use_sg) {     /* scatter-gather list not used */
 +
-+      BUG_ON(namelen <= 0);
++              page = virt_to_page(scp->request_buffer);
 +
-+      hash = full_name_hash(name, namelen);
-+      index = hash % rdstate->size;
++              offset = ((unsigned long)scp->request_buffer & ~PAGE_MASK);
 +
-+      head = &(rdstate->list[index]);
-+      list_for_each(pos, head) {
-+              cursor = list_entry(pos, struct filldir_node, file_list);
++              ccb->buf_dma_h = pci_map_page(adapter->pdev, page, offset,
++                                                scp->request_bufflen,
++                                                scb->dma_direction);
++              scb->dma_type = MRAID_DMA_WBUF;
 +
-+              if (cursor->namelen == namelen && cursor->hash == hash &&
-+                  !strncmp(cursor->name, name, namelen)) {
-+                      /*
-+                       * a duplicate exists, and hence no need to create
-+                       * entry to the list
-+                       */
-+                      found = 1;
++              /*
++               * We need to handle special 64-bit commands that need a
++               * minimum of 1 SG
++               */
++              sgcnt = 1;
++              ccb->sgl64[0].address   = ccb->buf_dma_h;
++              ccb->sgl64[0].length    = scp->request_bufflen;
 +
-+                      /*
-+                       * if the duplicate is in this branch, then the file
-+                       * system is corrupted.
-+                       */
-+                      if (cursor->bindex == rdstate->bindex) {
-+                              printk(KERN_DEBUG "unionfs: filldir: possible "
-+                                     "I/O error: a file is duplicated "
-+                                     "in the same branch %d: %s\n",
-+                                     rdstate->bindex, cursor->name);
-+                      }
-+                      break;
-+              }
++              return sgcnt;
 +      }
 +
-+      if (!found)
-+              cursor = NULL;
-+
-+      return cursor;
-+}
-+
-+int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name,
-+                   int namelen, int bindex, int whiteout)
-+{
-+      struct filldir_node *new;
-+      unsigned int hash;
-+      int index;
-+      int err = 0;
-+      struct list_head *head;
-+
-+      BUG_ON(namelen <= 0);
++      sgl = (struct scatterlist *)scp->request_buffer;
 +
-+      hash = full_name_hash(name, namelen);
-+      index = hash % rdstate->size;
-+      head = &(rdstate->list[index]);
++      // The number of sg elements returned must not exceed our limit
++      sgcnt = pci_map_sg(adapter->pdev, sgl, scp->use_sg,
++                      scb->dma_direction);
 +
-+      new = kmem_cache_alloc(unionfs_filldir_cachep, GFP_KERNEL);
-+      if (!new) {
-+              err = -ENOMEM;
-+              goto out;
++      if (sgcnt > adapter->sglen) {
++              con_log(CL_ANN, (KERN_CRIT
++                      "megaraid critical: too many sg elements:%d\n",
++                      sgcnt));
++              BUG();
 +      }
 +
-+      INIT_LIST_HEAD(&new->file_list);
-+      new->namelen = namelen;
-+      new->hash = hash;
-+      new->bindex = bindex;
-+      new->whiteout = whiteout;
-+
-+      if (namelen < DNAME_INLINE_LEN_MIN)
-+              new->name = new->iname;
-+      else {
-+              new->name = kmalloc(namelen + 1, GFP_KERNEL);
-+              if (!new->name) {
-+                      kmem_cache_free(unionfs_filldir_cachep, new);
-+                      new = NULL;
-+                      goto out;
+       scb->dma_type = MRAID_DMA_WSG;
+-      scsi_for_each_sg(scp, sgl, sgcnt, i) {
++      for (i = 0; i < sgcnt; i++, sgl++) {
+               ccb->sgl64[i].address   = sg_dma_address(sgl);
+               ccb->sgl64[i].length    = sg_dma_len(sgl);
+       }
+@@ -1455,11 +1489,19 @@
+       adapter->outstanding_cmds++;
+-      if (scb->dma_direction == PCI_DMA_TODEVICE)
+-                      pci_dma_sync_sg_for_device(adapter->pdev,
+-                                         scsi_sglist(scb->scp),
+-                                         scsi_sg_count(scb->scp),
++      if (scb->dma_direction == PCI_DMA_TODEVICE) {
++              if (!scb->scp->use_sg) {        // sg list not used
++                      pci_dma_sync_single_for_device(adapter->pdev,
++                                      ccb->buf_dma_h,
++                                      scb->scp->request_bufflen,
+                                          PCI_DMA_TODEVICE);
 +              }
-+      }
-+
-+      memcpy(new->name, name, namelen);
-+      new->name[namelen] = '\0';
-+
-+      rdstate->hashentries++;
-+
-+      list_add(&(new->file_list), head);
-+out:
-+      return err;
-+}
-diff -Nurb linux-2.6.22-570/fs/unionfs/rename.c linux-2.6.22-590/fs/unionfs/rename.c
---- linux-2.6.22-570/fs/unionfs/rename.c       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/rename.c       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,477 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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 "union.h"
-+
-+static int __unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+                          struct inode *new_dir, struct dentry *new_dentry,
-+                          int bindex, struct dentry **wh_old)
-+{
-+      int err = 0;
-+      struct dentry *hidden_old_dentry;
-+      struct dentry *hidden_new_dentry;
-+      struct dentry *hidden_old_dir_dentry;
-+      struct dentry *hidden_new_dir_dentry;
-+      struct dentry *hidden_wh_dentry;
-+      struct dentry *hidden_wh_dir_dentry;
-+      char *wh_name = NULL;
-+
-+      hidden_new_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
-+      hidden_old_dentry = unionfs_lower_dentry_idx(old_dentry, bindex);
-+
-+      if (!hidden_new_dentry) {
-+              hidden_new_dentry =
-+                      create_parents(new_dentry->d_parent->d_inode,
-+                                     new_dentry, bindex);
-+              if (IS_ERR(hidden_new_dentry)) {
-+                      printk(KERN_DEBUG "unionfs: error creating directory "
-+                             "tree for rename, bindex = %d, err = %ld\n",
-+                             bindex, PTR_ERR(hidden_new_dentry));
-+                      err = PTR_ERR(hidden_new_dentry);
-+                      goto out;
++              else {
++                      pci_dma_sync_sg_for_device(adapter->pdev,
++                              scb->scp->request_buffer,
++                              scb->scp->use_sg, PCI_DMA_TODEVICE);
 +              }
 +      }
-+
-+      wh_name = alloc_whname(new_dentry->d_name.name,
-+                             new_dentry->d_name.len);
-+      if (IS_ERR(wh_name)) {
-+              err = PTR_ERR(wh_name);
-+              goto out;
-+      }
-+
-+      hidden_wh_dentry = lookup_one_len(wh_name, hidden_new_dentry->d_parent,
-+                                        new_dentry->d_name.len +
-+                                        UNIONFS_WHLEN);
-+      if (IS_ERR(hidden_wh_dentry)) {
-+              err = PTR_ERR(hidden_wh_dentry);
-+              goto out;
-+      }
-+
-+      if (hidden_wh_dentry->d_inode) {
-+              /* get rid of the whiteout that is existing */
-+              if (hidden_new_dentry->d_inode) {
-+                      printk(KERN_WARNING "unionfs: both a whiteout and a "
-+                             "dentry exist when doing a rename!\n");
-+                      err = -EIO;
-+
-+                      dput(hidden_wh_dentry);
-+                      goto out;
+       mbox->busy      = 1;    // Set busy
+       mbox->poll      = 0;
+@@ -1582,11 +1624,11 @@
+                       return scb;
+               case MODE_SENSE:
+-              {
++                      if (scp->use_sg) {
+                               struct scatterlist      *sgl;
+                               caddr_t                 vaddr;
+-                      sgl = scsi_sglist(scp);
++                              sgl = (struct scatterlist *)scp->request_buffer;
+                               if (sgl->page) {
+                                       vaddr = (caddr_t)
+                                               (page_address((&sgl[0])->page)
+@@ -1600,6 +1642,9 @@
+                                       __LINE__));
+                               }
+                       }
++                      else {
++                              memset(scp->request_buffer, 0, scp->cmnd[4]);
++                      }
+                       scp->result = (DID_OK << 16);
+                       return NULL;
+@@ -1671,7 +1716,7 @@
+                       mbox->cmd               = MBOXCMD_PASSTHRU64;
+                       scb->dma_direction      = scp->sc_data_direction;
+-                      pthru->dataxferlen      = scsi_bufflen(scp);
++                      pthru->dataxferlen      = scp->request_bufflen;
+                       pthru->dataxferaddr     = ccb->sgl_dma_h;
+                       pthru->numsge           = megaraid_mbox_mksgl(adapter,
+                                                       scb);
+@@ -2005,8 +2050,8 @@
+       memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
+-      if (scsi_bufflen(scp)) {
+-              pthru->dataxferlen      = scsi_bufflen(scp);
++      if (scp->request_bufflen) {
++              pthru->dataxferlen      = scp->request_bufflen;
+               pthru->dataxferaddr     = ccb->sgl_dma_h;
+               pthru->numsge           = megaraid_mbox_mksgl(adapter, scb);
+       }
+@@ -2054,8 +2099,8 @@
+       memcpy(epthru->cdb, scp->cmnd, scp->cmd_len);
+-      if (scsi_bufflen(scp)) {
+-              epthru->dataxferlen     = scsi_bufflen(scp);
++      if (scp->request_bufflen) {
++              epthru->dataxferlen     = scp->request_bufflen;
+               epthru->dataxferaddr    = ccb->sgl_dma_h;
+               epthru->numsge          = megaraid_mbox_mksgl(adapter, scb);
+       }
+@@ -2221,13 +2266,37 @@
+       ccb     = (mbox_ccb_t *)scb->ccb;
+-      if (scb->dma_direction == PCI_DMA_FROMDEVICE)
+-                      pci_dma_sync_sg_for_cpu(adapter->pdev,
+-                                      scsi_sglist(scb->scp),
+-                                      scsi_sg_count(scb->scp),
++      switch (scb->dma_type) {
++
++      case MRAID_DMA_WBUF:
++              if (scb->dma_direction == PCI_DMA_FROMDEVICE) {
++                      pci_dma_sync_single_for_cpu(adapter->pdev,
++                                      ccb->buf_dma_h,
++                                      scb->scp->request_bufflen,
+                                       PCI_DMA_FROMDEVICE);
 +              }
 +
-+              hidden_wh_dir_dentry = lock_parent(hidden_wh_dentry);
-+              if (!(err = is_robranch_super(old_dentry->d_sb, bindex)))
-+                      err = vfs_unlink(hidden_wh_dir_dentry->d_inode,
-+                                       hidden_wh_dentry);
-+
-+              dput(hidden_wh_dentry);
-+              unlock_dir(hidden_wh_dir_dentry);
-+              if (err)
-+                      goto out;
-+      } else
-+              dput(hidden_wh_dentry);
-+
-+      dget(hidden_old_dentry);
-+      hidden_old_dir_dentry = dget_parent(hidden_old_dentry);
-+      hidden_new_dir_dentry = dget_parent(hidden_new_dentry);
-+
-+      lock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry);
++              pci_unmap_page(adapter->pdev, ccb->buf_dma_h,
++                      scb->scp->request_bufflen, scb->dma_direction);
 +
-+      err = is_robranch_super(old_dentry->d_sb, bindex);
-+      if (err)
-+              goto out_unlock;
++              break;
 +
-+      /*
-+       * ready to whiteout for old_dentry. caller will create the actual
-+       * whiteout, and must dput(*wh_old)
-+       */
-+      if (wh_old) {
-+              char *whname;
-+              whname = alloc_whname(old_dentry->d_name.name,
-+                                    old_dentry->d_name.len);
-+              err = PTR_ERR(whname);
-+              if (IS_ERR(whname))
-+                      goto out_unlock;
-+              *wh_old = lookup_one_len(whname, hidden_old_dir_dentry,
-+                                       old_dentry->d_name.len +
-+                                       UNIONFS_WHLEN);
-+              kfree(whname);
-+              err = PTR_ERR(*wh_old);
-+              if (IS_ERR(*wh_old)) {
-+                      *wh_old = NULL;
-+                      goto out_unlock;
++      case MRAID_DMA_WSG:
++              if (scb->dma_direction == PCI_DMA_FROMDEVICE) {
++                      pci_dma_sync_sg_for_cpu(adapter->pdev,
++                                      scb->scp->request_buffer,
++                                      scb->scp->use_sg, PCI_DMA_FROMDEVICE);
 +              }
-+      }
 +
-+      err = vfs_rename(hidden_old_dir_dentry->d_inode, hidden_old_dentry,
-+                       hidden_new_dir_dentry->d_inode, hidden_new_dentry);
-+
-+out_unlock:
-+      unlock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry);
++              pci_unmap_sg(adapter->pdev, scb->scp->request_buffer,
++                      scb->scp->use_sg, scb->dma_direction);
 +
-+      dput(hidden_old_dir_dentry);
-+      dput(hidden_new_dir_dentry);
-+      dput(hidden_old_dentry);
++              break;
 +
-+out:
-+      if (!err) {
-+              /* Fixup the new_dentry. */
-+              if (bindex < dbstart(new_dentry))
-+                      set_dbstart(new_dentry, bindex);
-+              else if (bindex > dbend(new_dentry))
-+                      set_dbend(new_dentry, bindex);
++      default:
++              break;
 +      }
+-      scsi_dma_unmap(scb->scp);
+       return;
+ }
+@@ -2330,17 +2399,25 @@
+               if (scp->cmnd[0] == INQUIRY && status == 0 && islogical == 0
+                               && IS_RAID_CH(raid_dev, scb->dev_channel)) {
+-                      sgl = scsi_sglist(scp);
++                      if (scp->use_sg) {
++                              sgl = (struct scatterlist *)
++                                      scp->request_buffer;
 +
-+      kfree(wh_name);
-+
-+      return err;
-+}
-+
-+/*
-+ * Main rename code.  This is sufficienly complex, that it's documented in
-+ * Docmentation/filesystems/unionfs/rename.txt.  This routine calls
-+ * __unionfs_rename() above to perform some of the work.
-+ */
-+static int do_unionfs_rename(struct inode *old_dir,
-+                           struct dentry *old_dentry,
-+                           struct inode *new_dir,
-+                           struct dentry *new_dentry)
-+{
-+      int err = 0;
-+      int bindex, bwh_old;
-+      int old_bstart, old_bend;
-+      int new_bstart, new_bend;
-+      int do_copyup = -1;
-+      struct dentry *parent_dentry;
-+      int local_err = 0;
-+      int eio = 0;
-+      int revert = 0;
-+      struct dentry *wh_old = NULL;
-+
-+      old_bstart = dbstart(old_dentry);
-+      bwh_old = old_bstart;
-+      old_bend = dbend(old_dentry);
-+      parent_dentry = old_dentry->d_parent;
-+
-+      new_bstart = dbstart(new_dentry);
-+      new_bend = dbend(new_dentry);
-+
-+      /* Rename source to destination. */
-+      err = __unionfs_rename(old_dir, old_dentry, new_dir, new_dentry,
-+                             old_bstart, &wh_old);
-+      if (err) {
-+              if (!IS_COPYUP_ERR(err))
-+                      goto out;
-+              do_copyup = old_bstart - 1;
-+      } else
-+              revert = 1;
-+
-+      /*
-+       * Unlink all instances of destination that exist to the left of
-+       * bstart of source. On error, revert back, goto out.
-+       */
-+      for (bindex = old_bstart - 1; bindex >= new_bstart; bindex--) {
-+              struct dentry *unlink_dentry;
-+              struct dentry *unlink_dir_dentry;
-+
-+              unlink_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
-+              if (!unlink_dentry)
-+                      continue;
-+
-+              unlink_dir_dentry = lock_parent(unlink_dentry);
-+              if (!(err = is_robranch_super(old_dir->i_sb, bindex)))
-+                      err = vfs_unlink(unlink_dir_dentry->d_inode,
-+                                       unlink_dentry);
-+
-+              fsstack_copy_attr_times(new_dentry->d_parent->d_inode,
-+                                      unlink_dir_dentry->d_inode);
-+              /* propagate number of hard-links */
-+              new_dentry->d_parent->d_inode->i_nlink =
-+                      unionfs_get_nlinks(new_dentry->d_parent->d_inode);
-+
-+              unlock_dir(unlink_dir_dentry);
-+              if (!err) {
-+                      if (bindex != new_bstart) {
-+                              dput(unlink_dentry);
-+                              unionfs_set_lower_dentry_idx(new_dentry,
-+                                                           bindex, NULL);
+                               if (sgl->page) {
+                                       c = *(unsigned char *)
+                                       (page_address((&sgl[0])->page) +
+                                               (&sgl[0])->offset);
+-                      } else {
++                              }
++                              else {
+                                       con_log(CL_ANN, (KERN_WARNING
+                                       "megaraid mailbox: invalid sg:%d\n",
+                                       __LINE__));
+                                       c = 0;
+                               }
 +                      }
-+              } else if (IS_COPYUP_ERR(err)) {
-+                      do_copyup = bindex - 1;
-+              } else if (revert) {
-+                      dput(wh_old);
-+                      goto revert;
-+              }
-+      }
-+
-+      if (do_copyup != -1) {
-+              for (bindex = do_copyup; bindex >= 0; bindex--) {
-+                      /*
-+                       * copyup the file into some left directory, so that
-+                       * you can rename it
-+                       */
-+                      err = copyup_dentry(old_dentry->d_parent->d_inode,
-+                                          old_dentry, old_bstart, bindex,
-+                                          NULL, old_dentry->d_inode->i_size);
-+                      if (!err) {
-+                              dput(wh_old);
-+                              bwh_old = bindex;
-+                              err = __unionfs_rename(old_dir, old_dentry,
-+                                                     new_dir, new_dentry,
-+                                                     bindex, &wh_old);
-+                              break;
++                      else {
++                              c = *(uint8_t *)scp->request_buffer;
 +                      }
-+              }
-+      }
-+
-+      /* make it opaque */
-+      if (S_ISDIR(old_dentry->d_inode->i_mode)) {
-+              err = make_dir_opaque(old_dentry, dbstart(old_dentry));
-+              if (err)
-+                      goto revert;
-+      }
-+
-+      /*
-+       * Create whiteout for source, only if:
-+       * (1) There is more than one underlying instance of source.
-+       * (2) We did a copy_up
-+       */
-+      if ((old_bstart != old_bend) || (do_copyup != -1)) {
-+              struct dentry *hidden_parent;
-+              BUG_ON(!wh_old || wh_old->d_inode || bwh_old < 0);
-+              hidden_parent = lock_parent(wh_old);
-+              local_err = vfs_create(hidden_parent->d_inode, wh_old, S_IRUGO,
-+                                     NULL);
-+              unlock_dir(hidden_parent);
-+              if (!local_err)
-+                      set_dbopaque(old_dentry, bwh_old);
-+              else {
-+                      /*
-+                       * we can't fix anything now, so we cop-out and use
-+                       * -EIO.
-+                       */
-+                      printk(KERN_ERR "unionfs: can't create a whiteout for "
-+                             "the source in rename!\n");
-+                      err = -EIO;
-+              }
-+      }
-+
-+out:
-+      dput(wh_old);
-+      return err;
-+
-+revert:
-+      /* Do revert here. */
-+      local_err = unionfs_refresh_hidden_dentry(new_dentry, old_bstart);
-+      if (local_err) {
-+              printk(KERN_WARNING "unionfs: revert failed in rename: "
-+                     "the new refresh failed.\n");
-+              eio = -EIO;
-+      }
-+
-+      local_err = unionfs_refresh_hidden_dentry(old_dentry, old_bstart);
-+      if (local_err) {
-+              printk(KERN_WARNING "unionfs: revert failed in rename: "
-+                     "the old refresh failed.\n");
-+              eio = -EIO;
-+              goto revert_out;
-+      }
-+
-+      if (!unionfs_lower_dentry_idx(new_dentry, bindex) ||
-+          !unionfs_lower_dentry_idx(new_dentry, bindex)->d_inode) {
-+              printk(KERN_WARNING "unionfs: revert failed in rename: "
-+                     "the object disappeared from under us!\n");
-+              eio = -EIO;
-+              goto revert_out;
-+      }
-+
-+      if (unionfs_lower_dentry_idx(old_dentry, bindex) &&
-+          unionfs_lower_dentry_idx(old_dentry, bindex)->d_inode) {
-+              printk(KERN_WARNING "unionfs: revert failed in rename: "
-+                     "the object was created underneath us!\n");
-+              eio = -EIO;
-+              goto revert_out;
-+      }
-+
-+      local_err = __unionfs_rename(new_dir, new_dentry,
-+                                   old_dir, old_dentry, old_bstart, NULL);
-+
-+      /* If we can't fix it, then we cop-out with -EIO. */
-+      if (local_err) {
-+              printk(KERN_WARNING "unionfs: revert failed in rename!\n");
-+              eio = -EIO;
-+      }
-+
-+      local_err = unionfs_refresh_hidden_dentry(new_dentry, bindex);
-+      if (local_err)
-+              eio = -EIO;
-+      local_err = unionfs_refresh_hidden_dentry(old_dentry, bindex);
-+      if (local_err)
-+              eio = -EIO;
-+
-+revert_out:
-+      if (eio)
-+              err = eio;
-+      return err;
-+}
-+
-+static struct dentry *lookup_whiteout(struct dentry *dentry)
-+{
-+      char *whname;
-+      int bindex = -1, bstart = -1, bend = -1;
-+      struct dentry *parent, *hidden_parent, *wh_dentry;
-+
-+      whname = alloc_whname(dentry->d_name.name, dentry->d_name.len);
-+      if (IS_ERR(whname))
-+              return (void *)whname;
-+
-+      parent = dget_parent(dentry);
-+      unionfs_lock_dentry(parent);
-+      bstart = dbstart(parent);
-+      bend = dbend(parent);
-+      wh_dentry = ERR_PTR(-ENOENT);
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_parent = unionfs_lower_dentry_idx(parent, bindex);
-+              if (!hidden_parent)
-+                      continue;
-+              wh_dentry = lookup_one_len(whname, hidden_parent,
-+                                         dentry->d_name.len + UNIONFS_WHLEN);
-+              if (IS_ERR(wh_dentry))
-+                      continue;
-+              if (wh_dentry->d_inode)
-+                      break;
-+              dput(wh_dentry);
-+              wh_dentry = ERR_PTR(-ENOENT);
-+      }
-+      unionfs_unlock_dentry(parent);
-+      dput(parent);
-+      kfree(whname);
-+      return wh_dentry;
-+}
-+
-+/*
-+ * We can't copyup a directory, because it may involve huge numbers of
-+ * children, etc.  Doing that in the kernel would be bad, so instead we
-+ * return EXDEV to the user-space utility that caused this, and let the
-+ * user-space recurse and ask us to copy up each file separately.
-+ */
-+static int may_rename_dir(struct dentry *dentry)
-+{
-+      int err, bstart;
-+
-+      err = check_empty(dentry, NULL);
-+      if (err == -ENOTEMPTY) {
-+              if (is_robranch(dentry))
-+                      return -EXDEV;
-+      } else if (err)
-+              return err;
-+
-+      bstart = dbstart(dentry);
-+      if (dbend(dentry) == bstart || dbopaque(dentry) == bstart)
-+              return 0;
-+
-+      set_dbstart(dentry, bstart + 1);
-+      err = check_empty(dentry, NULL);
-+      set_dbstart(dentry, bstart);
-+      if (err == -ENOTEMPTY)
-+              err = -EXDEV;
-+      return err;
-+}
-+
-+int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+                 struct inode *new_dir, struct dentry *new_dentry)
-+{
-+      int err = 0;
-+      struct dentry *wh_dentry;
-+
-+      unionfs_read_lock(old_dentry->d_sb);
-+      unionfs_double_lock_dentry(old_dentry, new_dentry);
-+
-+      if (!__unionfs_d_revalidate_chain(old_dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+      if (!d_deleted(new_dentry) && new_dentry->d_inode &&
-+          !__unionfs_d_revalidate_chain(new_dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      if (!S_ISDIR(old_dentry->d_inode->i_mode))
-+              err = unionfs_partial_lookup(old_dentry);
-+      else
-+              err = may_rename_dir(old_dentry);
-+
-+      if (err)
-+              goto out;
-+
-+      err = unionfs_partial_lookup(new_dentry);
-+      if (err)
-+              goto out;
-+
+                       if ((c & 0x1F ) == TYPE_DISK) {
+                               pdev_index = (scb->dev_channel * 16) +
+diff -Nurb linux-2.6.22-590/drivers/scsi/megaraid/megaraid_sas.c linux-2.6.22-570/drivers/scsi/megaraid/megaraid_sas.c
+--- linux-2.6.22-590/drivers/scsi/megaraid/megaraid_sas.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/megaraid/megaraid_sas.c      2007-07-08 19:32:17.000000000 -0400
+@@ -433,15 +433,34 @@
+       int sge_count;
+       struct scatterlist *os_sgl;
+-      sge_count = scsi_dma_map(scp);
+-      BUG_ON(sge_count < 0);
 +      /*
-+       * if new_dentry is already hidden because of whiteout,
-+       * simply override it even if the whited-out dir is not empty.
++       * Return 0 if there is no data transfer
 +       */
-+      wh_dentry = lookup_whiteout(new_dentry);
-+      if (!IS_ERR(wh_dentry))
-+              dput(wh_dentry);
-+      else if (new_dentry->d_inode) {
-+              if (S_ISDIR(old_dentry->d_inode->i_mode) !=
-+                  S_ISDIR(new_dentry->d_inode->i_mode)) {
-+                      err = S_ISDIR(old_dentry->d_inode->i_mode) ?
-+                              -ENOTDIR : -EISDIR;
-+                      goto out;
-+              }
-+
-+              if (S_ISDIR(new_dentry->d_inode->i_mode)) {
-+                      struct unionfs_dir_state *namelist;
-+                      /* check if this unionfs directory is empty or not */
-+                      err = check_empty(new_dentry, &namelist);
-+                      if (err)
-+                              goto out;
-+
-+                      if (!is_robranch(new_dentry))
-+                              err = delete_whiteouts(new_dentry,
-+                                                     dbstart(new_dentry),
-+                                                     namelist);
-+
-+                      free_rdstate(namelist);
-+
-+                      if (err)
-+                              goto out;
-+              }
-+      }
-+      err = do_unionfs_rename(old_dir, old_dentry, new_dir, new_dentry);
-+
-+out:
-+      if (err)
-+              /* clear the new_dentry stuff created */
-+              d_drop(new_dentry);
-+      else
-+              /*
-+               * force re-lookup since the dir on ro branch is not renamed,
-+               * and hidden dentries still indicate the un-renamed ones.
-+               */
-+              if (S_ISDIR(old_dentry->d_inode->i_mode))
-+                      atomic_dec(&UNIONFS_D(old_dentry)->generation);
-+
-+      unionfs_unlock_dentry(new_dentry);
-+      unionfs_unlock_dentry(old_dentry);
-+      unionfs_read_unlock(old_dentry->d_sb);
-+      return err;
-+}
-diff -Nurb linux-2.6.22-570/fs/unionfs/sioq.c linux-2.6.22-590/fs/unionfs/sioq.c
---- linux-2.6.22-570/fs/unionfs/sioq.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/sioq.c 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,118 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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 "union.h"
-+
-+/*
-+ * Super-user IO work Queue - sometimes we need to perform actions which
-+ * would fail due to the unix permissions on the parent directory (e.g.,
-+ * rmdir a directory which appears empty, but in reality contains
-+ * whiteouts).
-+ */
-+
-+static struct workqueue_struct *superio_workqueue;
-+
-+int __init init_sioq(void)
-+{
-+      int err;
-+
-+      superio_workqueue = create_workqueue("unionfs_siod");
-+      if (!IS_ERR(superio_workqueue))
++      if (!scp->request_buffer || !scp->request_bufflen)
 +              return 0;
+-      if (sge_count) {
+-              scsi_for_each_sg(scp, os_sgl, sge_count, i) {
++      if (!scp->use_sg) {
++              mfi_sgl->sge32[0].phys_addr = pci_map_single(instance->pdev,
++                                                           scp->
++                                                           request_buffer,
++                                                           scp->
++                                                           request_bufflen,
++                                                           scp->
++                                                           sc_data_direction);
++              mfi_sgl->sge32[0].length = scp->request_bufflen;
 +
-+      err = PTR_ERR(superio_workqueue);
-+      printk(KERN_ERR "unionfs: create_workqueue failed %d\n", err);
-+      superio_workqueue = NULL;
-+      return err;
-+}
-+
-+void stop_sioq(void)
-+{
-+      if (superio_workqueue)
-+              destroy_workqueue(superio_workqueue);
-+}
-+
-+void run_sioq(work_func_t func, struct sioq_args *args)
-+{
-+      INIT_WORK(&args->work, func);
-+
-+      init_completion(&args->comp);
-+      while (!queue_work(superio_workqueue, &args->work)) {
-+              /* TODO: do accounting if needed */
-+              schedule();
-+      }
-+      wait_for_completion(&args->comp);
-+}
-+
-+void __unionfs_create(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+      struct create_args *c = &args->create;
-+
-+      args->err = vfs_create(c->parent, c->dentry, c->mode, c->nd);
-+      complete(&args->comp);
-+}
-+
-+void __unionfs_mkdir(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+      struct mkdir_args *m = &args->mkdir;
-+
-+      args->err = vfs_mkdir(m->parent, m->dentry, m->mode);
-+      complete(&args->comp);
-+}
-+
-+void __unionfs_mknod(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+      struct mknod_args *m = &args->mknod;
-+
-+      args->err = vfs_mknod(m->parent, m->dentry, m->mode, m->dev);
-+      complete(&args->comp);
-+}
-+
-+void __unionfs_symlink(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+      struct symlink_args *s = &args->symlink;
-+
-+      args->err = vfs_symlink(s->parent, s->dentry, s->symbuf, s->mode);
-+      complete(&args->comp);
-+}
-+
-+void __unionfs_unlink(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+      struct unlink_args *u = &args->unlink;
-+
-+      args->err = vfs_unlink(u->parent, u->dentry);
-+      complete(&args->comp);
-+}
-+
-+void __delete_whiteouts(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+      struct deletewh_args *d = &args->deletewh;
-+
-+      args->err = do_delete_whiteouts(d->dentry, d->bindex, d->namelist);
-+      complete(&args->comp);
-+}
-+
-+void __is_opaque_dir(struct work_struct *work)
-+{
-+      struct sioq_args *args = container_of(work, struct sioq_args, work);
-+
-+      args->ret = lookup_one_len(UNIONFS_DIR_OPAQUE, args->is_opaque.dentry,
-+                                 sizeof(UNIONFS_DIR_OPAQUE) - 1);
-+      complete(&args->comp);
-+}
-diff -Nurb linux-2.6.22-570/fs/unionfs/sioq.h linux-2.6.22-590/fs/unionfs/sioq.h
---- linux-2.6.22-570/fs/unionfs/sioq.h 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/sioq.h 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,91 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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.
-+ */
-+
-+#ifndef _SIOQ_H
-+#define _SIOQ_H
-+
-+struct deletewh_args {
-+      struct unionfs_dir_state *namelist;
-+      struct dentry *dentry;
-+      int bindex;
-+};
-+
-+struct is_opaque_args {
-+      struct dentry *dentry;
-+};
-+
-+struct create_args {
-+      struct inode *parent;
-+      struct dentry *dentry;
-+      umode_t mode;
-+      struct nameidata *nd;
-+};
-+
-+struct mkdir_args {
-+      struct inode *parent;
-+      struct dentry *dentry;
-+      umode_t mode;
-+};
-+
-+struct mknod_args {
-+      struct inode *parent;
-+      struct dentry *dentry;
-+      umode_t mode;
-+      dev_t dev;
-+};
-+
-+struct symlink_args {
-+      struct inode *parent;
-+      struct dentry *dentry;
-+      char *symbuf;
-+      umode_t mode;
-+};
-+
-+struct unlink_args {
-+      struct inode *parent;
-+      struct dentry *dentry;
-+};
-+
-+
-+struct sioq_args {
-+      struct completion comp;
-+      struct work_struct work;
-+      int err;
-+      void *ret;
-+
-+      union {
-+              struct deletewh_args deletewh;
-+              struct is_opaque_args is_opaque;
-+              struct create_args create;
-+              struct mkdir_args mkdir;
-+              struct mknod_args mknod;
-+              struct symlink_args symlink;
-+              struct unlink_args unlink;
-+      };
-+};
-+
-+/* Extern definitions for SIOQ functions */
-+extern int __init init_sioq(void);
-+extern void stop_sioq(void);
-+extern void run_sioq(work_func_t func, struct sioq_args *args);
-+
-+/* Extern definitions for our privilege escalation helpers */
-+extern void __unionfs_create(struct work_struct *work);
-+extern void __unionfs_mkdir(struct work_struct *work);
-+extern void __unionfs_mknod(struct work_struct *work);
-+extern void __unionfs_symlink(struct work_struct *work);
-+extern void __unionfs_unlink(struct work_struct *work);
-+extern void __delete_whiteouts(struct work_struct *work);
-+extern void __is_opaque_dir(struct work_struct *work);
-+
-+#endif /* _SIOQ_H */
-diff -Nurb linux-2.6.22-570/fs/unionfs/subr.c linux-2.6.22-590/fs/unionfs/subr.c
---- linux-2.6.22-570/fs/unionfs/subr.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/subr.c 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,238 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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 "union.h"
-+
-+/*
-+ * Pass an unionfs dentry and an index.  It will try to create a whiteout
-+ * for the filename in dentry, and will try in branch 'index'.  On error,
-+ * it will proceed to a branch to the left.
-+ */
-+int create_whiteout(struct dentry *dentry, int start)
-+{
-+      int bstart, bend, bindex;
-+      struct dentry *hidden_dir_dentry;
-+      struct dentry *hidden_dentry;
-+      struct dentry *hidden_wh_dentry;
-+      char *name = NULL;
-+      int err = -EINVAL;
-+
-+      verify_locked(dentry);
-+
-+      bstart = dbstart(dentry);
-+      bend = dbend(dentry);
-+
-+      /* create dentry's whiteout equivalent */
-+      name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
-+      if (IS_ERR(name)) {
-+              err = PTR_ERR(name);
-+              goto out;
++              return 1;
 +      }
 +
-+      for (bindex = start; bindex >= 0; bindex--) {
-+              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+
-+              if (!hidden_dentry) {
-+                      /*
-+                       * if hidden dentry is not present, create the
-+                       * entire hidden dentry directory structure and go
-+                       * ahead.  Since we want to just create whiteout, we
-+                       * only want the parent dentry, and hence get rid of
-+                       * this dentry.
-+                       */
-+                      hidden_dentry = create_parents(dentry->d_inode,
-+                                                     dentry, bindex);
-+                      if (!hidden_dentry || IS_ERR(hidden_dentry)) {
-+                              printk(KERN_DEBUG "unionfs: create_parents "
-+                                     "failed for bindex = %d\n", bindex);
-+                              continue;
-+                      }
-+              }
++      os_sgl = (struct scatterlist *)scp->request_buffer;
++      sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg,
++                             scp->sc_data_direction);
 +
-+              hidden_wh_dentry =
-+                      lookup_one_len(name, hidden_dentry->d_parent,
-+                                     dentry->d_name.len + UNIONFS_WHLEN);
-+              if (IS_ERR(hidden_wh_dentry))
-+                      continue;
++      for (i = 0; i < sge_count; i++, os_sgl++) {
+               mfi_sgl->sge32[i].length = sg_dma_len(os_sgl);
+               mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl);
+       }
+-      }
 +
-+              /*
-+               * The whiteout already exists. This used to be impossible,
-+               * but now is possible because of opaqueness.
-+               */
-+              if (hidden_wh_dentry->d_inode) {
-+                      dput(hidden_wh_dentry);
-+                      err = 0;
-+                      goto out;
-+              }
+       return sge_count;
+ }
+@@ -462,15 +481,35 @@
+       int sge_count;
+       struct scatterlist *os_sgl;
+-      sge_count = scsi_dma_map(scp);
+-      BUG_ON(sge_count < 0);
++      /*
++       * Return 0 if there is no data transfer
++       */
++      if (!scp->request_buffer || !scp->request_bufflen)
++              return 0;
 +
-+              hidden_dir_dentry = lock_parent(hidden_wh_dentry);
-+              if (!(err = is_robranch_super(dentry->d_sb, bindex)))
-+                      err = vfs_create(hidden_dir_dentry->d_inode,
-+                                       hidden_wh_dentry,
-+                                       ~current->fs->umask & S_IRWXUGO,
-+                                       NULL);
-+              unlock_dir(hidden_dir_dentry);
-+              dput(hidden_wh_dentry);
++      if (!scp->use_sg) {
++              mfi_sgl->sge64[0].phys_addr = pci_map_single(instance->pdev,
++                                                           scp->
++                                                           request_buffer,
++                                                           scp->
++                                                           request_bufflen,
++                                                           scp->
++                                                           sc_data_direction);
+-      if (sge_count) {
+-              scsi_for_each_sg(scp, os_sgl, sge_count, i) {
++              mfi_sgl->sge64[0].length = scp->request_bufflen;
 +
-+              if (!err || !IS_COPYUP_ERR(err))
-+                      break;
++              return 1;
 +      }
 +
-+      /* set dbopaque so that lookup will not proceed after this branch */
-+      if (!err)
-+              set_dbopaque(dentry, bindex);
++      os_sgl = (struct scatterlist *)scp->request_buffer;
++      sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg,
++                             scp->sc_data_direction);
 +
-+out:
-+      kfree(name);
-+      return err;
-+}
++      for (i = 0; i < sge_count; i++, os_sgl++) {
+               mfi_sgl->sge64[i].length = sg_dma_len(os_sgl);
+               mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl);
+       }
+-      }
 +
-+/*
-+ * This is a helper function for rename, which ends up with hosed over
-+ * dentries when it needs to revert.
+       return sge_count;
+ }
+@@ -554,7 +593,7 @@
+       pthru->cdb_len = scp->cmd_len;
+       pthru->timeout = 0;
+       pthru->flags = flags;
+-      pthru->data_xfer_len = scsi_bufflen(scp);
++      pthru->data_xfer_len = scp->request_bufflen;
+       memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
+@@ -1156,6 +1195,45 @@
+ }
+ /**
++ * megasas_unmap_sgbuf -      Unmap SG buffers
++ * @instance:                 Adapter soft state
++ * @cmd:                      Completed command
 + */
-+int unionfs_refresh_hidden_dentry(struct dentry *dentry, int bindex)
++static void
++megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
 +{
-+      struct dentry *hidden_dentry;
-+      struct dentry *hidden_parent;
-+      int err = 0;
-+
-+      verify_locked(dentry);
++      dma_addr_t buf_h;
++      u8 opcode;
 +
-+      unionfs_lock_dentry(dentry->d_parent);
-+      hidden_parent = unionfs_lower_dentry_idx(dentry->d_parent, bindex);
-+      unionfs_unlock_dentry(dentry->d_parent);
-+
-+      BUG_ON(!S_ISDIR(hidden_parent->d_inode->i_mode));
-+
-+      hidden_dentry = lookup_one_len(dentry->d_name.name, hidden_parent,
-+                                     dentry->d_name.len);
-+      if (IS_ERR(hidden_dentry)) {
-+              err = PTR_ERR(hidden_dentry);
-+              goto out;
++      if (cmd->scmd->use_sg) {
++              pci_unmap_sg(instance->pdev, cmd->scmd->request_buffer,
++                           cmd->scmd->use_sg, cmd->scmd->sc_data_direction);
++              return;
 +      }
 +
-+      dput(unionfs_lower_dentry_idx(dentry, bindex));
-+      iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
-+      unionfs_set_lower_inode_idx(dentry->d_inode, bindex, NULL);
++      if (!cmd->scmd->request_bufflen)
++              return;
++
++      opcode = cmd->frame->hdr.cmd;
 +
-+      if (!hidden_dentry->d_inode) {
-+              dput(hidden_dentry);
-+              unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++      if ((opcode == MFI_CMD_LD_READ) || (opcode == MFI_CMD_LD_WRITE)) {
++              if (IS_DMA64)
++                      buf_h = cmd->frame->io.sgl.sge64[0].phys_addr;
++              else
++                      buf_h = cmd->frame->io.sgl.sge32[0].phys_addr;
 +      } else {
-+              unionfs_set_lower_dentry_idx(dentry, bindex, hidden_dentry);
-+              unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
-+                                          igrab(hidden_dentry->d_inode));
++              if (IS_DMA64)
++                      buf_h = cmd->frame->pthru.sgl.sge64[0].phys_addr;
++              else
++                      buf_h = cmd->frame->pthru.sgl.sge32[0].phys_addr;
 +      }
 +
-+out:
-+      return err;
++      pci_unmap_single(instance->pdev, buf_h, cmd->scmd->request_bufflen,
++                       cmd->scmd->sc_data_direction);
++      return;
 +}
 +
-+int make_dir_opaque(struct dentry *dentry, int bindex)
-+{
-+      int err = 0;
-+      struct dentry *hidden_dentry, *diropq;
-+      struct inode *hidden_dir;
-+
-+      hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+      hidden_dir = hidden_dentry->d_inode;
-+      BUG_ON(!S_ISDIR(dentry->d_inode->i_mode) ||
-+             !S_ISDIR(hidden_dir->i_mode));
-+
-+      mutex_lock(&hidden_dir->i_mutex);
-+      diropq = lookup_one_len(UNIONFS_DIR_OPAQUE, hidden_dentry,
-+                              sizeof(UNIONFS_DIR_OPAQUE) - 1);
-+      if (IS_ERR(diropq)) {
-+              err = PTR_ERR(diropq);
-+              goto out;
++/**
+  * megasas_complete_cmd -     Completes a command
+  * @instance:                 Adapter soft state
+  * @cmd:                      Command to be completed
+@@ -1203,7 +1281,7 @@
+                       atomic_dec(&instance->fw_outstanding);
+-                      scsi_dma_unmap(cmd->scmd);
++                      megasas_unmap_sgbuf(instance, cmd);
+                       cmd->scmd->scsi_done(cmd->scmd);
+                       megasas_return_cmd(instance, cmd);
+@@ -1251,7 +1329,7 @@
+               atomic_dec(&instance->fw_outstanding);
+-              scsi_dma_unmap(cmd->scmd);
++              megasas_unmap_sgbuf(instance, cmd);
+               cmd->scmd->scsi_done(cmd->scmd);
+               megasas_return_cmd(instance, cmd);
+diff -Nurb linux-2.6.22-590/drivers/scsi/megaraid.c linux-2.6.22-570/drivers/scsi/megaraid.c
+--- linux-2.6.22-590/drivers/scsi/megaraid.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/megaraid.c   2007-07-08 19:32:17.000000000 -0400
+@@ -523,8 +523,10 @@
+       /*
+        * filter the internal and ioctl commands
+        */
+-      if((cmd->cmnd[0] == MEGA_INTERNAL_CMD))
+-              return (scb_t *)cmd->host_scribble;
++      if((cmd->cmnd[0] == MEGA_INTERNAL_CMD)) {
++              return cmd->request_buffer;
 +      }
 +
-+      if (!diropq->d_inode)
-+              err = vfs_create(hidden_dir, diropq, S_IRUGO, NULL);
-+      if (!err)
-+              set_dbopaque(dentry, bindex);
-+
-+      dput(diropq);
-+
-+out:
-+      mutex_unlock(&hidden_dir->i_mutex);
-+      return err;
-+}
-+
-+/*
-+ * returns the sum of the n_link values of all the underlying inodes of the
-+ * passed inode
-+ */
-+int unionfs_get_nlinks(struct inode *inode)
-+{
-+      int sum_nlinks = 0;
-+      int dirs = 0;
-+      int bindex;
-+      struct inode *hidden_inode;
+       /*
+        * We know what channels our logical drives are on - mega_find_card()
+@@ -655,14 +657,22 @@
+               case MODE_SENSE: {
+                       char *buf;
+-                              struct scatterlist *sg;
+-                      sg = scsi_sglist(cmd);
+-                      buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
++                      if (cmd->use_sg) {
++                              struct scatterlist *sg;
++                              sg = (struct scatterlist *)cmd->request_buffer;
++                              buf = kmap_atomic(sg->page, KM_IRQ0) +
++                                      sg->offset;
++                      } else
++                              buf = cmd->request_buffer;
+                       memset(buf, 0, cmd->cmnd[4]);
+-                              kunmap_atomic(buf - sg->offset, KM_IRQ0);
++                      if (cmd->use_sg) {
++                              struct scatterlist *sg;
++                              sg = (struct scatterlist *)cmd->request_buffer;
++                              kunmap_atomic(buf - sg->offset, KM_IRQ0);
++                      }
+                       cmd->result = (DID_OK << 16);
+                       cmd->scsi_done(cmd);
+                       return NULL;
+@@ -1541,16 +1551,24 @@
+               islogical = adapter->logdrv_chan[cmd->device->channel];
+               if( cmd->cmnd[0] == INQUIRY && !islogical ) {
+-                      sgl = scsi_sglist(cmd);
++                      if( cmd->use_sg ) {
++                              sgl = (struct scatterlist *)
++                                      cmd->request_buffer;
 +
-+      /* don't bother to do all the work since we're unlinked */
-+      if (inode->i_nlink == 0)
-+              return 0;
+                               if( sgl->page ) {
+                                       c = *(unsigned char *)
+                                       page_address((&sgl[0])->page) +
+                                       (&sgl[0])->offset; 
+-                      } else {
++                              }
++                              else {
+                                       printk(KERN_WARNING
+                                               "megaraid: invalid sg.\n");
+                                       c = 0;
+                               }
++                      }
++                      else {
++                              c = *(u8 *)cmd->request_buffer;
++                      }
+                       if(IS_RAID_CH(adapter, cmd->device->channel) &&
+                                       ((c & 0x1F ) == TYPE_DISK)) {
+@@ -1686,14 +1704,30 @@
+ static void
+ mega_free_scb(adapter_t *adapter, scb_t *scb)
+ {
++      unsigned long length;
 +
-+      if (!S_ISDIR(inode->i_mode))
-+              return unionfs_lower_inode(inode)->i_nlink;
+       switch( scb->dma_type ) {
+       case MEGA_DMA_TYPE_NONE:
+               break;
++      case MEGA_BULK_DATA:
++              if (scb->cmd->use_sg == 0)
++                      length = scb->cmd->request_bufflen;
++              else {
++                      struct scatterlist *sgl =
++                              (struct scatterlist *)scb->cmd->request_buffer;
++                      length = sgl->length;
++              }
++              pci_unmap_page(adapter->dev, scb->dma_h_bulkdata,
++                             length, scb->dma_direction);
++              break;
 +
-+      for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
-+              hidden_inode = unionfs_lower_inode_idx(inode, bindex);
+       case MEGA_SGLIST:
+-              scsi_dma_unmap(scb->cmd);
++              pci_unmap_sg(adapter->dev, scb->cmd->request_buffer,
++                      scb->cmd->use_sg, scb->dma_direction);
+               break;
 +
-+              /* ignore files */
-+              if (!hidden_inode || !S_ISDIR(hidden_inode->i_mode))
-+                      continue;
+       default:
+               break;
+       }
+@@ -1733,33 +1767,80 @@
+ static int
+ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
+ {
+-      struct scatterlist *sg;
++      struct scatterlist      *sgl;
++      struct page     *page;
++      unsigned long   offset;
++      unsigned int    length;
+       Scsi_Cmnd       *cmd;
+       int     sgcnt;
+       int     idx;
+       cmd = scb->cmd;
++      /* Scatter-gather not used */
++      if( cmd->use_sg == 0 || (cmd->use_sg == 1 && 
++                               !adapter->has_64bit_addr)) {
 +
-+              BUG_ON(hidden_inode->i_nlink < 0);
++              if (cmd->use_sg == 0) {
++                      page = virt_to_page(cmd->request_buffer);
++                      offset = offset_in_page(cmd->request_buffer);
++                      length = cmd->request_bufflen;
++              } else {
++                      sgl = (struct scatterlist *)cmd->request_buffer;
++                      page = sgl->page;
++                      offset = sgl->offset;
++                      length = sgl->length;
++              }
 +
-+              /* A deleted directory. */
-+              if (hidden_inode->i_nlink == 0)
-+                      continue;
-+              dirs++;
++              scb->dma_h_bulkdata = pci_map_page(adapter->dev,
++                                                page, offset,
++                                                length,
++                                                scb->dma_direction);
++              scb->dma_type = MEGA_BULK_DATA;
 +
 +              /*
-+               * A broken directory...
-+               *
-+               * Some filesystems don't properly set the number of links
-+               * on empty directories
++               * We need to handle special 64-bit commands that need a
++               * minimum of 1 SG
 +               */
-+              if (hidden_inode->i_nlink == 1)
-+                      sum_nlinks += 2;
-+              else
-+                      sum_nlinks += (hidden_inode->i_nlink - 2);
++              if( adapter->has_64bit_addr ) {
++                      scb->sgl64[0].address = scb->dma_h_bulkdata;
++                      scb->sgl64[0].length = length;
++                      *buf = (u32)scb->sgl_dma_addr;
++                      *len = (u32)length;
++                      return 1;
++              }
++              else {
++                      *buf = (u32)scb->dma_h_bulkdata;
++                      *len = (u32)length;
++              }
++              return 0;
 +      }
 +
-+      return (!dirs ? 0 : sum_nlinks + 2);
-+}
-+
-+/* construct whiteout filename */
-+char *alloc_whname(const char *name, int len)
-+{
-+      char *buf;
-+
-+      buf = kmalloc(len + UNIONFS_WHLEN + 1, GFP_KERNEL);
-+      if (!buf)
-+              return ERR_PTR(-ENOMEM);
-+
-+      strcpy(buf, UNIONFS_WHPFX);
-+      strlcat(buf, name, len + UNIONFS_WHLEN + 1);
-+
-+      return buf;
-+}
-diff -Nurb linux-2.6.22-570/fs/unionfs/super.c linux-2.6.22-590/fs/unionfs/super.c
---- linux-2.6.22-570/fs/unionfs/super.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/super.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,1002 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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.
-+ */
++      sgl = (struct scatterlist *)cmd->request_buffer;
 +
-+#include "union.h"
-+
-+/*
-+ * The inode cache is used with alloc_inode for both our inode info and the
-+ * vfs inode.
-+ */
-+static struct kmem_cache *unionfs_inode_cachep;
+       /*
+        * Copy Scatter-Gather list info into controller structure.
+        *
+        * The number of sg elements returned must not exceed our limit
+        */
+-      sgcnt = scsi_dma_map(cmd);
++      sgcnt = pci_map_sg(adapter->dev, sgl, cmd->use_sg,
++                      scb->dma_direction);
+       scb->dma_type = MEGA_SGLIST;
+-      BUG_ON(sgcnt > adapter->sglen || sgcnt < 0);
++      BUG_ON(sgcnt > adapter->sglen);
+       *len = 0;
+-      scsi_for_each_sg(cmd, sg, sgcnt, idx) {
+-              if (adapter->has_64bit_addr) {
+-                      scb->sgl64[idx].address = sg_dma_address(sg);
+-                      *len += scb->sgl64[idx].length = sg_dma_len(sg);
+-              } else {
+-                      scb->sgl[idx].address = sg_dma_address(sg);
+-                      *len += scb->sgl[idx].length = sg_dma_len(sg);
++      for( idx = 0; idx < sgcnt; idx++, sgl++ ) {
 +
-+static void unionfs_read_inode(struct inode *inode)
-+{
-+      extern struct address_space_operations unionfs_aops;
-+      int size;
-+      struct unionfs_inode_info *info = UNIONFS_I(inode);
-+
-+      unionfs_read_lock(inode->i_sb);
-+
-+      memset(info, 0, offsetof(struct unionfs_inode_info, vfs_inode));
-+      info->bstart = -1;
-+      info->bend = -1;
-+      atomic_set(&info->generation,
-+                 atomic_read(&UNIONFS_SB(inode->i_sb)->generation));
-+      spin_lock_init(&info->rdlock);
-+      info->rdcount = 1;
-+      info->hashsize = -1;
-+      INIT_LIST_HEAD(&info->readdircache);
-+
-+      size = sbmax(inode->i_sb) * sizeof(struct inode *);
-+      info->lower_inodes = kzalloc(size, GFP_KERNEL);
-+      if (!info->lower_inodes) {
-+              printk(KERN_ERR "unionfs: no kernel memory when allocating "
-+                     "lower-pointer array!\n");
-+              BUG();
++              if( adapter->has_64bit_addr ) {
++                      scb->sgl64[idx].address = sg_dma_address(sgl);
++                      *len += scb->sgl64[idx].length = sg_dma_len(sgl);
++              }
++              else {
++                      scb->sgl[idx].address = sg_dma_address(sgl);
++                      *len += scb->sgl[idx].length = sg_dma_len(sgl);
+               }
+       }
+@@ -3490,7 +3571,7 @@
+                       /*
+                        * The user passthru structure
+                        */
+-                      upthru = (mega_passthru __user *)(unsigned long)MBOX(uioc)->xferaddr;
++                      upthru = (mega_passthru __user *)MBOX(uioc)->xferaddr;
+                       /*
+                        * Copy in the user passthru here.
+@@ -3542,7 +3623,7 @@
+                               /*
+                                * Get the user data
+                                */
+-                              if( copy_from_user(data, (char __user *)(unsigned long) uxferaddr,
++                              if( copy_from_user(data, (char __user *)uxferaddr,
+                                                       pthru->dataxferlen) ) {
+                                       rval = (-EFAULT);
+                                       goto freemem_and_return;
+@@ -3568,7 +3649,7 @@
+                        * Is data going up-stream
+                        */
+                       if( pthru->dataxferlen && (uioc.flags & UIOC_RD) ) {
+-                              if( copy_to_user((char __user *)(unsigned long) uxferaddr, data,
++                              if( copy_to_user((char __user *)uxferaddr, data,
+                                                       pthru->dataxferlen) ) {
+                                       rval = (-EFAULT);
+                               }
+@@ -3621,7 +3702,7 @@
+                               /*
+                                * Get the user data
+                                */
+-                              if( copy_from_user(data, (char __user *)(unsigned long) uxferaddr,
++                              if( copy_from_user(data, (char __user *)uxferaddr,
+                                                       uioc.xferlen) ) {
+                                       pci_free_consistent(pdev,
+@@ -3661,7 +3742,7 @@
+                        * Is data going up-stream
+                        */
+                       if( uioc.xferlen && (uioc.flags & UIOC_RD) ) {
+-                              if( copy_to_user((char __user *)(unsigned long) uxferaddr, data,
++                              if( copy_to_user((char __user *)uxferaddr, data,
+                                                       uioc.xferlen) ) {
+                                       rval = (-EFAULT);
+@@ -4413,7 +4494,7 @@
+       scmd->device = sdev;
+       scmd->device->host = adapter->host;
+-      scmd->host_scribble = (void *)scb;
++      scmd->request_buffer = (void *)scb;
+       scmd->cmnd[0] = MEGA_INTERNAL_CMD;
+       scb->state |= SCB_ACTIVE;
+diff -Nurb linux-2.6.22-590/drivers/scsi/mesh.c linux-2.6.22-570/drivers/scsi/mesh.c
+--- linux-2.6.22-590/drivers/scsi/mesh.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/mesh.c       2007-07-08 19:32:17.000000000 -0400
+@@ -421,7 +421,7 @@
+               for (i = 0; i < cmd->cmd_len; ++i)
+                       printk(" %x", cmd->cmnd[i]);
+               printk(" use_sg=%d buffer=%p bufflen=%u\n",
+-                     scsi_sg_count(cmd), scsi_sglist(cmd), scsi_bufflen(cmd));
++                     cmd->use_sg, cmd->request_buffer, cmd->request_bufflen);
+       }
+ #endif
+       if (ms->dma_started)
+@@ -602,16 +602,13 @@
+                       cmd->result += (cmd->SCp.Message << 8);
+               if (DEBUG_TARGET(cmd)) {
+                       printk(KERN_DEBUG "mesh_done: result = %x, data_ptr=%d, buflen=%d\n",
+-                             cmd->result, ms->data_ptr, scsi_bufflen(cmd));
+-#if 0
+-                      /* needs to use sg? */
++                             cmd->result, ms->data_ptr, cmd->request_bufflen);
+                       if ((cmd->cmnd[0] == 0 || cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 3)
+                           && cmd->request_buffer != 0) {
+                               unsigned char *b = cmd->request_buffer;
+                               printk(KERN_DEBUG "buffer = %x %x %x %x %x %x %x %x\n",
+                                      b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
+                       }
+-#endif
+               }
+               cmd->SCp.this_residual -= ms->data_ptr;
+               mesh_completed(ms, cmd);
+@@ -1268,18 +1265,15 @@
+       dcmds = ms->dma_cmds;
+       dtot = 0;
+       if (cmd) {
++              cmd->SCp.this_residual = cmd->request_bufflen;
++              if (cmd->use_sg > 0) {
+                       int nseg;
+-
+-              cmd->SCp.this_residual = scsi_bufflen(cmd);
+-
+-              nseg = scsi_dma_map(cmd);
+-              BUG_ON(nseg < 0);
+-
+-              if (nseg) {
+                       total = 0;
++                      scl = (struct scatterlist *) cmd->request_buffer;
+                       off = ms->data_ptr;
+-
+-                      scsi_for_each_sg(cmd, scl, nseg, i) {
++                      nseg = pci_map_sg(ms->pdev, scl, cmd->use_sg,
++                                        cmd->sc_data_direction);
++                      for (i = 0; i <nseg; ++i, ++scl) {
+                               u32 dma_addr = sg_dma_address(scl);
+                               u32 dma_len = sg_dma_len(scl);
+                               
+@@ -1298,6 +1292,16 @@
+                               dtot += dma_len - off;
+                               off = 0;
+                       }
++              } else if (ms->data_ptr < cmd->request_bufflen) {
++                      dtot = cmd->request_bufflen - ms->data_ptr;
++                      if (dtot > 0xffff)
++                              panic("mesh: transfer size >= 64k");
++                      st_le16(&dcmds->req_count, dtot);
++                      /* XXX Use pci DMA API here ... */
++                      st_le32(&dcmds->phy_addr,
++                              virt_to_phys(cmd->request_buffer) + ms->data_ptr);
++                      dcmds->xfer_status = 0;
++                      ++dcmds;
+               }
+       }
+       if (dtot == 0) {
+@@ -1352,14 +1356,18 @@
+               dumplog(ms, ms->conn_tgt);
+               dumpslog(ms);
+ #endif /* MESH_DBG */
+-      } else if (cmd && scsi_bufflen(cmd) &&
+-                 ms->data_ptr > scsi_bufflen(cmd)) {
++      } else if (cmd && cmd->request_bufflen != 0 &&
++                 ms->data_ptr > cmd->request_bufflen) {
+               printk(KERN_DEBUG "mesh: target %d overrun, "
+                      "data_ptr=%x total=%x goes_out=%d\n",
+-                     ms->conn_tgt, ms->data_ptr, scsi_bufflen(cmd),
++                     ms->conn_tgt, ms->data_ptr, cmd->request_bufflen,
+                      ms->tgts[ms->conn_tgt].data_goes_out);
+       }
+-      scsi_dma_unmap(cmd);
++      if (cmd->use_sg != 0) {
++              struct scatterlist *sg;
++              sg = (struct scatterlist *)cmd->request_buffer;
++              pci_unmap_sg(ms->pdev, sg, cmd->use_sg, cmd->sc_data_direction);
 +      }
-+
-+      inode->i_version++;
-+      inode->i_op = &unionfs_main_iops;
-+      inode->i_fop = &unionfs_main_fops;
-+
-+      inode->i_mapping->a_ops = &unionfs_aops;
-+
-+      unionfs_read_unlock(inode->i_sb);
-+}
-+
-+/*
-+ * we now define delete_inode, because there are two VFS paths that may
-+ * destroy an inode: one of them calls clear inode before doing everything
-+ * else that's needed, and the other is fine.  This way we truncate the inode
-+ * size (and its pages) and then clear our own inode, which will do an iput
-+ * on our and the lower inode.
-+ *
-+ * No need to lock sb info's rwsem.
-+ */
-+static void unionfs_delete_inode(struct inode *inode)
-+{
-+      inode->i_size = 0;      /* every f/s seems to do that */
-+
-+      if (inode->i_data.nrpages)
-+              truncate_inode_pages(&inode->i_data, 0);
-+
-+      clear_inode(inode);
-+}
-+
+       ms->dma_started = 0;
+ }
+diff -Nurb linux-2.6.22-590/drivers/scsi/mvme16x.c linux-2.6.22-570/drivers/scsi/mvme16x.c
+--- linux-2.6.22-590/drivers/scsi/mvme16x.c    1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/mvme16x.c    2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,78 @@
 +/*
-+ * final actions when unmounting a file system
++ * Detection routine for the NCR53c710 based MVME16x SCSI Controllers for Linux.
 + *
-+ * No need to lock rwsem.
++ * Based on work by Alan Hourihane
 + */
-+static void unionfs_put_super(struct super_block *sb)
-+{
-+      int bindex, bstart, bend;
-+      struct unionfs_sb_info *spd;
-+      int leaks = 0;
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/blkdev.h>
 +
-+      spd = UNIONFS_SB(sb);
-+      if (!spd)
-+              return;
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/mvme16xhw.h>
++#include <asm/irq.h>
 +
-+      bstart = sbstart(sb);
-+      bend = sbend(sb);
++#include "scsi.h"
++#include <scsi/scsi_host.h>
++#include "53c7xx.h"
++#include "mvme16x.h"
 +
-+      /* Make sure we have no leaks of branchget/branchput. */
-+      for (bindex = bstart; bindex <= bend; bindex++)
-+              if (branch_count(sb, bindex) != 0) {
-+                      printk("unionfs: branch %d has %d references left!\n",
-+                             bindex, branch_count(sb, bindex));
-+                      leaks = 1;
-+              }
-+      BUG_ON(leaks != 0);
++#include<linux/stat.h>
 +
-+      kfree(spd->data);
-+      kfree(spd);
-+      sb->s_fs_info = NULL;
-+}
 +
-+/*
-+ * Since people use this to answer the "How big of a file can I write?"
-+ * question, we report the size of the highest priority branch as the size of
-+ * the union.
-+ */
-+static int unionfs_statfs(struct dentry *dentry, struct kstatfs *buf)
++int mvme16x_scsi_detect(struct scsi_host_template *tpnt)
 +{
-+      int err = 0;
-+      struct super_block *sb;
-+      struct dentry *lower_dentry;
-+
-+      sb = dentry->d_sb;
-+
-+      unionfs_read_lock(sb);
-+      unionfs_lock_dentry(dentry);
-+
-+      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      lower_dentry = unionfs_lower_dentry(sb->s_root);
-+      err = vfs_statfs(lower_dentry, buf);
-+
-+      /* set return buf to our f/s to avoid confusing user-level utils */
-+      buf->f_type = UNIONFS_SUPER_MAGIC;
-+
-+      /*
-+       * Our maximum file name can is shorter by a few bytes because every
-+       * file name could potentially be whited-out.
-+       */
-+      buf->f_namelen -= UNIONFS_WHLEN;
++    static unsigned char called = 0;
++    int clock;
++    long long options;
 +
-+      memset(&buf->f_fsid, 0, sizeof(__kernel_fsid_t));
-+      memset(&buf->f_spare, 0, sizeof(buf->f_spare));
++    if (!MACH_IS_MVME16x)
++              return 0;
++    if (mvme16x_config & MVME16x_CONFIG_NO_SCSICHIP) {
++      printk ("SCSI detection disabled, SCSI chip not present\n");
++      return 0;
++    }
++    if (called)
++      return 0;
 +
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(sb);
-+      return err;
-+}
++    tpnt->proc_name = "MVME16x";
 +
-+/* handle mode changing during remount */
-+static noinline int do_remount_mode_option(char *optarg, int cur_branches,
-+                                         struct unionfs_data *new_data,
-+                                         struct path *new_lower_paths)
-+{
-+      int err = -EINVAL;
-+      int perms, idx;
-+      char *modename = strchr(optarg, '=');
-+      struct nameidata nd;
++    options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
 +
-+      /* by now, optarg contains the branch name */
-+      if (!*optarg) {
-+              printk("unionfs: no branch specified for mode change.\n");
-+              goto out;
-+      }
-+      if (!modename) {
-+              printk("unionfs: branch \"%s\" requires a mode.\n", optarg);
-+              goto out;
-+      }
-+      *modename++ = '\0';
-+      perms = __parse_branch_mode(modename);
-+      if (perms == 0) {
-+              printk("unionfs: invalid mode \"%s\" for \"%s\".\n",
-+                     modename, optarg);
-+              goto out;
-+      }
++    clock = 66000000; /* 66MHz SCSI Clock */
 +
-+      /*
-+       * Find matching branch index.  For now, this assumes that nothing
-+       * has been mounted on top of this Unionfs stack.  Once we have /odf
-+       * and cache-coherency resolved, we'll address the branch-path
-+       * uniqueness.
-+       */
-+      err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
-+      if (err) {
-+              printk(KERN_WARNING "unionfs: error accessing "
-+                     "hidden directory \"%s\" (error %d)\n",
-+                     optarg, err);
-+              goto out;
-+      }
-+      for (idx=0; idx<cur_branches; idx++)
-+              if (nd.mnt == new_lower_paths[idx].mnt &&
-+                  nd.dentry == new_lower_paths[idx].dentry)
-+                      break;
-+      path_release(&nd);      /* no longer needed */
-+      if (idx == cur_branches) {
-+              err = -ENOENT;  /* err may have been reset above */
-+              printk(KERN_WARNING "unionfs: branch \"%s\" "
-+                     "not found\n", optarg);
-+              goto out;
-+      }
-+      /* check/change mode for existing branch */
-+      /* we don't warn if perms==branchperms */
-+      new_data[idx].branchperms = perms;
-+      err = 0;
-+out:
-+      return err;
++    ncr53c7xx_init(tpnt, 0, 710, (unsigned long)0xfff47000,
++                      0, MVME16x_IRQ_SCSI, DMA_NONE,
++                      options, clock);
++    called = 1;
++    return 1;
 +}
 +
-+/* handle branch deletion during remount */
-+static noinline int do_remount_del_option(char *optarg, int cur_branches,
-+                                        struct unionfs_data *new_data,
-+                                        struct path *new_lower_paths)
++static int mvme16x_scsi_release(struct Scsi_Host *shost)
 +{
-+      int err = -EINVAL;
-+      int idx;
-+      struct nameidata nd;
-+
-+      /* optarg contains the branch name to delete */
-+
-+      /*
-+       * Find matching branch index.  For now, this assumes that nothing
-+       * has been mounted on top of this Unionfs stack.  Once we have /odf
-+       * and cache-coherency resolved, we'll address the branch-path
-+       * uniqueness.
-+       */
-+      err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
-+      if (err) {
-+              printk(KERN_WARNING "unionfs: error accessing "
-+                     "hidden directory \"%s\" (error %d)\n",
-+                     optarg, err);
-+              goto out;
-+      }
-+      for (idx=0; idx < cur_branches; idx++)
-+              if (nd.mnt == new_lower_paths[idx].mnt &&
-+                  nd.dentry == new_lower_paths[idx].dentry)
-+                      break;
-+      path_release(&nd);      /* no longer needed */
-+      if (idx == cur_branches) {
-+              printk(KERN_WARNING "unionfs: branch \"%s\" "
-+                     "not found\n", optarg);
-+              err = -ENOENT;
-+              goto out;
-+      }
-+      /* check if there are any open files on the branch to be deleted */
-+      if (atomic_read(&new_data[idx].open_files) > 0) {
-+              err = -EBUSY;
-+              goto out;
-+      }
-+
-+      /*
-+       * Now we have to delete the branch.  First, release any handles it
-+       * has.  Then, move the remaining array indexes past "idx" in
-+       * new_data and new_lower_paths one to the left.  Finally, adjust
-+       * cur_branches.
-+       */
-+      pathput(&new_lower_paths[idx]);
-+
-+      if (idx < cur_branches - 1) {
-+              /* if idx==cur_branches-1, we delete last branch: easy */
-+              memmove(&new_data[idx], &new_data[idx+1],
-+                      (cur_branches - 1 - idx) *
-+                      sizeof(struct unionfs_data));
-+              memmove(&new_lower_paths[idx], &new_lower_paths[idx+1],
-+                      (cur_branches - 1 - idx) * sizeof(struct path));
-+      }
-+
-+      err = 0;
-+out:
-+      return err;
++      if (shost->irq)
++              free_irq(shost->irq, NULL);
++      if (shost->dma_channel != 0xff)
++              free_dma(shost->dma_channel);
++      if (shost->io_port && shost->n_io_port)
++              release_region(shost->io_port, shost->n_io_port);
++      scsi_unregister(shost);
++      return 0;
 +}
 +
-+/* handle branch insertion during remount */
-+static noinline int do_remount_add_option(char *optarg, int cur_branches,
-+                                        struct unionfs_data *new_data,
-+                                        struct path *new_lower_paths,
-+                                        int *high_branch_id)
-+{
-+      int err = -EINVAL;
-+      int perms;
-+      int idx = 0;            /* default: insert at beginning */
-+      char *new_branch , *modename = NULL;
-+      struct nameidata nd;
-+
-+      /*
-+       * optarg can be of several forms:
-+       *
-+       * /bar:/foo            insert /foo before /bar
-+       * /bar:/foo=ro         insert /foo in ro mode before /bar
-+       * /foo                 insert /foo in the beginning (prepend)
-+       * :/foo                insert /foo at the end (append)
-+       */
-+      if (*optarg == ':') {   /* append? */
-+              new_branch = optarg + 1; /* skip ':' */
-+              idx = cur_branches;
-+              goto found_insertion_point;
-+      }
-+      new_branch = strchr(optarg, ':');
-+      if (!new_branch) {      /* prepend? */
-+              new_branch = optarg;
-+              goto found_insertion_point;
-+      }
-+      *new_branch++ = '\0';   /* holds path+mode of new branch */
-+
-+      /*
-+       * Find matching branch index.  For now, this assumes that nothing
-+       * has been mounted on top of this Unionfs stack.  Once we have /odf
-+       * and cache-coherency resolved, we'll address the branch-path
-+       * uniqueness.
-+       */
-+      err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
-+      if (err) {
-+              printk(KERN_WARNING "unionfs: error accessing "
-+                     "hidden directory \"%s\" (error %d)\n",
-+                     optarg, err);
-+              goto out;
-+      }
-+      for (idx=0; idx < cur_branches; idx++)
-+              if (nd.mnt == new_lower_paths[idx].mnt &&
-+                  nd.dentry == new_lower_paths[idx].dentry)
-+                      break;
-+      path_release(&nd);      /* no longer needed */
-+      if (idx == cur_branches) {
-+              printk(KERN_WARNING "unionfs: branch \"%s\" "
-+                     "not found\n", optarg);
-+              err = -ENOENT;
-+              goto out;
-+      }
-+
-+      /*
-+       * At this point idx will hold the index where the new branch should
-+       * be inserted before.
-+       */
-+found_insertion_point:
-+      /* find the mode for the new branch */
-+      if (new_branch)
-+              modename = strchr(new_branch, '=');
-+      if (modename)
-+              *modename++ = '\0';
-+      perms = parse_branch_mode(modename);
-+
-+      if (!new_branch || !*new_branch) {
-+              printk(KERN_WARNING "unionfs: null new branch\n");
-+              err = -EINVAL;
-+              goto out;
-+      }
-+      err = path_lookup(new_branch, LOOKUP_FOLLOW, &nd);
-+      if (err) {
-+              printk(KERN_WARNING "unionfs: error accessing "
-+                     "hidden directory \"%s\" (error %d)\n",
-+                     new_branch, err);
-+              goto out;
-+      }
-+      /*
-+       * It's probably safe to check_mode the new branch to insert.  Note:
-+       * we don't allow inserting branches which are unionfs's by
-+       * themselves (check_branch returns EINVAL in that case).  This is
-+       * because this code base doesn't support stacking unionfs: the ODF
-+       * code base supports that correctly.
-+       */
-+      if ((err = check_branch(&nd))) {
-+              printk(KERN_WARNING "unionfs: hidden directory "
-+                     "\"%s\" is not a valid branch\n", optarg);
-+              path_release(&nd);
-+              goto out;
-+      }
-+
-+      /*
-+       * Now we have to insert the new branch.  But first, move the bits
-+       * to make space for the new branch, if needed.  Finally, adjust
-+       * cur_branches.
-+       * We don't release nd here; it's kept until umount/remount.
-+       */
-+      if (idx < cur_branches) {
-+              /* if idx==cur_branches, we append: easy */
-+              memmove(&new_data[idx+1], &new_data[idx],
-+                      (cur_branches - idx) * sizeof(struct unionfs_data));
-+              memmove(&new_lower_paths[idx+1], &new_lower_paths[idx],
-+                      (cur_branches - idx) * sizeof(struct path));
-+      }
-+      new_lower_paths[idx].dentry = nd.dentry;
-+      new_lower_paths[idx].mnt = nd.mnt;
-+
-+      new_data[idx].sb = nd.dentry->d_sb;
-+      atomic_set(&new_data[idx].open_files, 0);
-+      new_data[idx].branchperms = perms;
-+      new_data[idx].branch_id = ++*high_branch_id; /* assign new branch ID */
++static struct scsi_host_template driver_template = {
++      .name                   = "MVME16x NCR53c710 SCSI",
++      .detect                 = mvme16x_scsi_detect,
++      .release                = mvme16x_scsi_release,
++      .queuecommand           = NCR53c7xx_queue_command,
++      .abort                  = NCR53c7xx_abort,
++      .reset                  = NCR53c7xx_reset,
++      .can_queue              = 24,
++      .this_id                = 7,
++      .sg_tablesize           = 63,
++      .cmd_per_lun            = 3,
++      .use_clustering         = DISABLE_CLUSTERING
++};
 +
-+      err = 0;
-+out:
-+      return err;
-+}
 +
++#include "scsi_module.c"
+diff -Nurb linux-2.6.22-590/drivers/scsi/mvme16x.h linux-2.6.22-570/drivers/scsi/mvme16x.h
+--- linux-2.6.22-590/drivers/scsi/mvme16x.h    1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/mvme16x.h    2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,24 @@
++#ifndef MVME16x_SCSI_H
++#define MVME16x_SCSI_H
 +
-+/*
-+ * Support branch management options on remount.
-+ *
-+ * See Documentation/filesystems/unionfs/ for details.
-+ *
-+ * @flags: numeric mount options
-+ * @options: mount options string
-+ *
-+ * This function can rearrange a mounted union dynamically, adding and
-+ * removing branches, including changing branch modes.  Clearly this has to
-+ * be done safely and atomically.  Luckily, the VFS already calls this
-+ * function with lock_super(sb) and lock_kernel() held, preventing
-+ * concurrent mixing of new mounts, remounts, and unmounts.  Moreover,
-+ * do_remount_sb(), our caller function, already called shrink_dcache_sb(sb)
-+ * to purge dentries/inodes from our superblock, and also called
-+ * fsync_super(sb) to purge any dirty pages.  So we're good.
-+ *
-+ * XXX: however, our remount code may also need to invalidate mapped pages
-+ * so as to force them to be re-gotten from the (newly reconfigured) lower
-+ * branches.  This has to wait for proper mmap and cache coherency support
-+ * in the VFS.
-+ *
-+ */
-+static int unionfs_remount_fs(struct super_block *sb, int *flags,
-+                            char *options)
-+{
-+      int err = 0;
-+      int i;
-+      char *optionstmp, *tmp_to_free; /* kstrdup'ed of "options" */
-+      char *optname;
-+      int cur_branches = 0;   /* no. of current branches */
-+      int new_branches = 0;   /* no. of branches actually left in the end */
-+      int add_branches;       /* est. no. of branches to add */
-+      int del_branches;       /* est. no. of branches to del */
-+      int max_branches;       /* max possible no. of branches */
-+      struct unionfs_data *new_data = NULL, *tmp_data = NULL;
-+      struct path *new_lower_paths = NULL, *tmp_lower_paths = NULL;
-+      struct inode **new_lower_inodes = NULL;
-+      int new_high_branch_id; /* new high branch ID */
-+      int size;               /* memory allocation size, temp var */
-+      int old_ibstart, old_ibend;
-+
-+      unionfs_write_lock(sb);
++#include <linux/types.h>
 +
-+      /*
-+       * The VFS will take care of "ro" and "rw" flags, and we can safely
-+       * ignore MS_SILENT, but anything else left over is an error.  So we
-+       * need to check if any other flags may have been passed (none are
-+       * allowed/supported as of now).
-+       */
-+      if ((*flags & ~(MS_RDONLY | MS_SILENT)) != 0) {
-+              printk(KERN_WARNING
-+                     "unionfs: remount flags 0x%x unsupported\n", *flags);
-+              err = -EINVAL;
-+              goto out_error;
-+      }
++int mvme16x_scsi_detect(struct scsi_host_template *);
++const char *NCR53c7x0_info(void);
++int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
++int NCR53c7xx_abort(Scsi_Cmnd *);
++int NCR53c7x0_release (struct Scsi_Host *);
++int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int);
++void NCR53c7x0_intr(int irq, void *dev_id);
 +
-+      /*
-+       * If 'options' is NULL, it's probably because the user just changed
-+       * the union to a "ro" or "rw" and the VFS took care of it.  So
-+       * nothing to do and we're done.
-+       */
-+      if (!options || options[0] == '\0')
-+              goto out_error;
++#ifndef CMD_PER_LUN
++#define CMD_PER_LUN 3
++#endif
 +
-+      /*
-+       * Find out how many branches we will have in the end, counting
-+       * "add" and "del" commands.  Copy the "options" string because
-+       * strsep modifies the string and we need it later.
-+       */
-+      optionstmp = tmp_to_free = kstrdup(options, GFP_KERNEL);
-+      if (!optionstmp) {
-+              err = -ENOMEM;
-+              goto out_free;
-+      }
-+      new_branches = cur_branches = sbmax(sb); /* current no. branches */
-+      add_branches = del_branches = 0;
-+      new_high_branch_id = sbhbid(sb); /* save current high_branch_id */
-+      while ((optname = strsep(&optionstmp, ",")) != NULL) {
-+              char *optarg;
++#ifndef CAN_QUEUE
++#define CAN_QUEUE 24
++#endif
 +
-+              if (!optname || !*optname)
-+                      continue;
++#include <scsi/scsicam.h>
 +
-+              optarg = strchr(optname, '=');
-+              if (optarg)
-+                      *optarg++ = '\0';
++#endif /* MVME16x_SCSI_H */
+diff -Nurb linux-2.6.22-590/drivers/scsi/mvme16x_scsi.c linux-2.6.22-570/drivers/scsi/mvme16x_scsi.c
+--- linux-2.6.22-590/drivers/scsi/mvme16x_scsi.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/mvme16x_scsi.c       1969-12-31 19:00:00.000000000 -0500
+@@ -1,158 +0,0 @@
+-/*
+- * Detection routine for the NCR53c710 based MVME16x SCSI Controllers for Linux.
+- *
+- * Based on work by Alan Hourihane
+- *
+- * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
+- */
+-
+-#include <linux/module.h>
+-#include <linux/blkdev.h>
+-#include <linux/device.h>
+-#include <linux/platform_device.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <asm/mvme16xhw.h>
+-#include <scsi/scsi_host.h>
+-#include <scsi/scsi_device.h>
+-#include <scsi/scsi_transport.h>
+-#include <scsi/scsi_transport_spi.h>
+-
+-#include "53c700.h"
+-
+-MODULE_AUTHOR("Kars de Jong <jongk@linux-m68k.org>");
+-MODULE_DESCRIPTION("MVME16x NCR53C710 driver");
+-MODULE_LICENSE("GPL");
+-
+-static struct scsi_host_template mvme16x_scsi_driver_template = {
+-      .name                   = "MVME16x NCR53c710 SCSI",
+-      .proc_name              = "MVME16x",
+-      .this_id                = 7,
+-      .module                 = THIS_MODULE,
+-};
+-
+-static struct platform_device *mvme16x_scsi_device;
+-
+-static __devinit int
+-mvme16x_probe(struct device *dev)
+-{
+-      struct Scsi_Host * host = NULL;
+-      struct NCR_700_Host_Parameters *hostdata;
+-
+-      if (!MACH_IS_MVME16x)
+-              goto out;
+-
+-      if (mvme16x_config & MVME16x_CONFIG_NO_SCSICHIP) {
+-              printk(KERN_INFO "mvme16x-scsi: detection disabled, "
+-                               "SCSI chip not present\n");
+-              goto out;
+-      }
+-
+-      hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+-      if (hostdata == NULL) {
+-              printk(KERN_ERR "mvme16x-scsi: "
+-                              "Failed to allocate host data\n");
+-              goto out;
+-      }
+-      memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
+-
+-      /* Fill in the required pieces of hostdata */
+-      hostdata->base = (void __iomem *)0xfff47000UL;
+-      hostdata->clock = 50;   /* XXX - depends on the CPU clock! */
+-      hostdata->chip710 = 1;
+-      hostdata->dmode_extra = DMODE_FC2;
+-      hostdata->dcntl_extra = EA_710;
+-      hostdata->ctest7_extra = CTEST7_TT1;
+-
+-      /* and register the chip */
+-      host = NCR_700_detect(&mvme16x_scsi_driver_template, hostdata, dev);
+-      if (!host) {
+-              printk(KERN_ERR "mvme16x-scsi: No host detected; "
+-                              "board configuration problem?\n");
+-              goto out_free;
+-      }
+-      host->this_id = 7;
+-      host->base = 0xfff47000UL;
+-      host->irq = MVME16x_IRQ_SCSI;
+-      if (request_irq(host->irq, NCR_700_intr, 0, "mvme16x-scsi", host)) {
+-              printk(KERN_ERR "mvme16x-scsi: request_irq failed\n");
+-              goto out_put_host;
+-      }
+-
+-      /* Enable scsi chip ints */
+-      {
+-              volatile unsigned long v;
+-
+-              /* Enable scsi interrupts at level 4 in PCCchip2 */
+-              v = in_be32(0xfff4202c);
+-              v = (v & ~0xff) | 0x10 | 4;
+-              out_be32(0xfff4202c, v);
+-      }
+-
+-      scsi_scan_host(host);
+-
+-      return 0;
+-
+- out_put_host:
+-      scsi_host_put(host);
+- out_free:
+-      kfree(hostdata);
+- out:
+-      return -ENODEV;
+-}
+-
+-static __devexit int
+-mvme16x_device_remove(struct device *dev)
+-{
+-      struct Scsi_Host *host = dev_to_shost(dev);
+-      struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
+-
+-      /* Disable scsi chip ints */
+-      {
+-              volatile unsigned long v;
+-
+-              v = in_be32(0xfff4202c);
+-              v &= ~0x10;
+-              out_be32(0xfff4202c, v);
+-      }
+-      scsi_remove_host(host);
+-      NCR_700_release(host);
+-      kfree(hostdata);
+-      free_irq(host->irq, host);
+-
+-      return 0;
+-}
+-
+-static struct device_driver mvme16x_scsi_driver = {
+-      .name   = "mvme16x-scsi",
+-      .bus    = &platform_bus_type,
+-      .probe  = mvme16x_probe,
+-      .remove = __devexit_p(mvme16x_device_remove),
+-};
+-
+-static int __init mvme16x_scsi_init(void)
+-{
+-      int err;
+-
+-      err = driver_register(&mvme16x_scsi_driver);
+-      if (err)
+-              return err;
+-
+-      mvme16x_scsi_device = platform_device_register_simple("mvme16x-scsi",
+-                                                            -1, NULL, 0);
+-      if (IS_ERR(mvme16x_scsi_device)) {
+-              driver_unregister(&mvme16x_scsi_driver);
+-              return PTR_ERR(mvme16x_scsi_device);
+-      }
+-
+-      return 0;
+-}
+-
+-static void __exit mvme16x_scsi_exit(void)
+-{
+-      platform_device_unregister(mvme16x_scsi_device);
+-      driver_unregister(&mvme16x_scsi_driver);
+-}
+-
+-module_init(mvme16x_scsi_init);
+-module_exit(mvme16x_scsi_exit);
+diff -Nurb linux-2.6.22-590/drivers/scsi/nsp32.c linux-2.6.22-570/drivers/scsi/nsp32.c
+--- linux-2.6.22-590/drivers/scsi/nsp32.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/nsp32.c      2007-07-08 19:32:17.000000000 -0400
+@@ -49,6 +49,10 @@
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi_ioctl.h>
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
++# include <linux/blk.h>
++#endif
 +
-+              if (!strcmp("add", optname))
-+                      add_branches++;
-+              else if (!strcmp("del", optname))
-+                      del_branches++;
-+      }
-+      kfree(tmp_to_free);
-+      /* after all changes, will we have at least one branch left? */
-+      if ((new_branches + add_branches - del_branches) < 1) {
-+              printk(KERN_WARNING
-+                     "unionfs: no branches left after remount\n");
-+              err = -EINVAL;
-+              goto out_free;
+ #include "nsp32.h"
+@@ -195,9 +199,17 @@
+ static void __exit    exit_nsp32  (void);
+ /* struct struct scsi_host_template */
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+ static int         nsp32_proc_info   (struct Scsi_Host *, char *, char **, off_t, int, int);
++#else
++static int         nsp32_proc_info   (char *, char **, off_t, int, int, int);
++#endif
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+ static int         nsp32_detect      (struct pci_dev *pdev);
++#else
++static int         nsp32_detect      (struct scsi_host_template *);
++#endif
+ static int         nsp32_queuecommand(struct scsi_cmnd *,
+               void (*done)(struct scsi_cmnd *));
+ static const char *nsp32_info        (struct Scsi_Host *);
+@@ -284,7 +296,15 @@
+       .eh_abort_handler               = nsp32_eh_abort,
+       .eh_bus_reset_handler           = nsp32_eh_bus_reset,
+       .eh_host_reset_handler          = nsp32_eh_host_reset,
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74))
++      .detect                         = nsp32_detect,
++      .release                        = nsp32_release,
++#endif
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2))
++      .use_new_eh_code                = 1,
++#else
+ /*    .highmem_io                     = 1, */
++#endif
+ };
+ #include "nsp32_io.h"
+@@ -719,7 +739,7 @@
+       command = 0;
+       command |= (TRANSFER_GO | ALL_COUNTER_CLR);
+       if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
+-              if (scsi_bufflen(SCpnt) > 0) {
++              if (SCpnt->request_bufflen > 0) {
+                       command |= BM_START;
+               }
+       } else if (data->trans_method & NSP32_TRANSFER_MMIO) {
+@@ -868,28 +888,31 @@
+ static int nsp32_setup_sg_table(struct scsi_cmnd *SCpnt)
+ {
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+-      struct scatterlist *sg;
++      struct scatterlist   *sgl;
+       nsp32_sgtable *sgt = data->cur_lunt->sglun->sgt;
+       int num, i;
+       u32_le l;
++      if (SCpnt->request_bufflen == 0) {
++              return TRUE;
 +      }
 +
-+      /*
-+       * Since we haven't actually parsed all the add/del options, nor
-+       * have we checked them for errors, we don't know for sure how many
-+       * branches we will have after all changes have taken place.  In
-+       * fact, the total number of branches left could be less than what
-+       * we have now.  So we need to allocate space for a temporary
-+       * placeholder that is at least as large as the maximum number of
-+       * branches we *could* have, which is the current number plus all
-+       * the additions.  Once we're done with these temp placeholders, we
-+       * may have to re-allocate the final size, copy over from the temp,
-+       * and then free the temps (done near the end of this function).
-+       */
-+      max_branches = cur_branches + add_branches;
-+      /* allocate space for new pointers to hidden dentry */
-+      tmp_data = kcalloc(max_branches,
-+                         sizeof(struct unionfs_data), GFP_KERNEL);
-+      if (!tmp_data) {
-+              err = -ENOMEM;
-+              goto out_free;
-+      }
-+      /* allocate space for new pointers to lower paths */
-+      tmp_lower_paths = kcalloc(max_branches,
-+                                sizeof(struct path), GFP_KERNEL);
-+      if (!tmp_lower_paths) {
-+              err = -ENOMEM;
-+              goto out_free;
-+      }
-+      /* copy current info into new placeholders, incrementing refcnts */
-+      memcpy(tmp_data, UNIONFS_SB(sb)->data,
-+             cur_branches * sizeof(struct unionfs_data));
-+      memcpy(tmp_lower_paths, UNIONFS_D(sb->s_root)->lower_paths,
-+             cur_branches * sizeof(struct path));
-+      for (i=0; i<cur_branches; i++)
-+              pathget(&tmp_lower_paths[i]); /* drop refs at end of fxn */
-+
-+      /*******************************************************************
-+       * For each branch command, do path_lookup on the requested branch,
-+       * and apply the change to a temp branch list.  To handle errors, we
-+       * already dup'ed the old arrays (above), and increased the refcnts
-+       * on various f/s objects.  So now we can do all the path_lookups
-+       * and branch-management commands on the new arrays.  If it fail mid
-+       * way, we free the tmp arrays and *put all objects.  If we succeed,
-+       * then we free old arrays and *put its objects, and then replace
-+       * the arrays with the new tmp list (we may have to re-allocate the
-+       * memory because the temp lists could have been larger than what we
-+       * actually needed).
-+       *******************************************************************/
-+
-+      while ((optname = strsep(&options, ",")) != NULL) {
-+              char *optarg;
-+
-+              if (!optname || !*optname)
-+                      continue;
-+              /*
-+               * At this stage optname holds a comma-delimited option, but
-+               * without the commas.  Next, we need to break the string on
-+               * the '=' symbol to separate CMD=ARG, where ARG itself can
-+               * be KEY=VAL.  For example, in mode=/foo=rw, CMD is "mode",
-+               * KEY is "/foo", and VAL is "rw".
-+               */
-+              optarg = strchr(optname, '=');
-+              if (optarg)
-+                      *optarg++ = '\0';
-+              /* incgen remount option (instead of old ioctl) */
-+              if (!strcmp("incgen", optname)) {
-+                      err = 0;
-+                      goto out_no_change;
-+              }
+       if (sgt == NULL) {
+               nsp32_dbg(NSP32_DEBUG_SGLIST, "SGT == null");
+               return FALSE;
+       }
+-      num = scsi_dma_map(SCpnt);
+-      if (!num)
+-              return TRUE;
+-      else if (num < 0)
+-              return FALSE;
+-      else {
+-              scsi_for_each_sg(SCpnt, sg, num, i) {
++      if (SCpnt->use_sg) {
++              sgl = (struct scatterlist *)SCpnt->request_buffer;
++              num = pci_map_sg(data->Pci, sgl, SCpnt->use_sg,
++                               SCpnt->sc_data_direction);
++              for (i = 0; i < num; i++) {
+                       /*
+                        * Build nsp32_sglist, substitute sg dma addresses.
+                        */
+-                      sgt[i].addr = cpu_to_le32(sg_dma_address(sg));
+-                      sgt[i].len  = cpu_to_le32(sg_dma_len(sg));
++                      sgt[i].addr = cpu_to_le32(sg_dma_address(sgl));
++                      sgt[i].len  = cpu_to_le32(sg_dma_len(sgl));
++                      sgl++;
+                       if (le32_to_cpu(sgt[i].len) > 0x10000) {
+                               nsp32_msg(KERN_ERR,
+@@ -906,6 +929,23 @@
+               /* set end mark */
+               l = le32_to_cpu(sgt[num-1].len);
+               sgt[num-1].len = cpu_to_le32(l | SGTEND);
 +
-+              /*
-+               * All of our options take an argument now.  (Insert ones
-+               * that don't above this check.)  So at this stage optname
-+               * contains the CMD part and optarg contains the ARG part.
-+               */
-+              if (!optarg || !*optarg) {
-+                      printk("unionfs: all remount options require "
-+                             "an argument (%s).\n", optname);
-+                      err = -EINVAL;
-+                      goto out_release;
-+              }
++      } else {
++              SCpnt->SCp.have_data_in = pci_map_single(data->Pci,
++                      SCpnt->request_buffer, SCpnt->request_bufflen,
++                      SCpnt->sc_data_direction);
 +
-+              if (!strcmp("add", optname)) {
-+                      err = do_remount_add_option(optarg, new_branches,
-+                                                  tmp_data,
-+                                                  tmp_lower_paths,
-+                                                  &new_high_branch_id);
-+                      if (err)
-+                              goto out_release;
-+                      new_branches++;
-+                      if (new_branches > UNIONFS_MAX_BRANCHES) {
-+                              printk("unionfs: command exceeds "
-+                                     "%d branches\n", UNIONFS_MAX_BRANCHES);
-+                              err = -E2BIG;
-+                              goto out_release;
-+                      }
-+                      continue;
-+              }
-+              if (!strcmp("del", optname)) {
-+                      err = do_remount_del_option(optarg, new_branches,
-+                                                  tmp_data,
-+                                                  tmp_lower_paths);
-+                      if (err)
-+                              goto out_release;
-+                      new_branches--;
-+                      continue;
-+              }
-+              if (!strcmp("mode", optname)) {
-+                      err = do_remount_mode_option(optarg, new_branches,
-+                                                   tmp_data,
-+                                                   tmp_lower_paths);
-+                      if (err)
-+                              goto out_release;
-+                      continue;
-+              }
++              sgt[0].addr = cpu_to_le32(SCpnt->SCp.have_data_in);
++              sgt[0].len  = cpu_to_le32(SCpnt->request_bufflen | SGTEND); /* set end mark */
 +
-+              /*
-+               * When you use "mount -o remount,ro", mount(8) will
-+               * reportedly pass the original dirs= string from
-+               * /proc/mounts.  So for now, we have to ignore dirs= and
-+               * not consider it an error, unless we want to allow users
-+               * to pass dirs= in remount.  Note that to allow the VFS to
-+               * actually process the ro/rw remount options, we have to
-+               * return 0 from this function.
-+               */
-+              if (!strcmp("dirs", optname)) {
-+                      printk(KERN_WARNING
-+                             "unionfs: remount ignoring option \"%s\".\n",
-+                             optname);
-+                      continue;
++              if (SCpnt->request_bufflen > 0x10000) {
++                      nsp32_msg(KERN_ERR,
++                                "can't transfer over 64KB at a time, size=0x%lx", SCpnt->request_bufflen);
++                      return FALSE;
 +              }
-+
-+              err = -EINVAL;
-+              printk(KERN_WARNING
-+                     "unionfs: unrecognized option \"%s\"\n", optname);
-+              goto out_release;
-+      }
-+
-+out_no_change:
-+
-+      /******************************************************************
-+       * WE'RE ALMOST DONE: check if leftmost branch might be read-only,
-+       * see if we need to allocate a small-sized new vector, copy the
-+       * vectors to their correct place, release the refcnt of the older
-+       * ones, and return.  Also handle invalidating any pages that will
-+       * have to be re-read.
-+       *******************************************************************/
-+
-+      if (!(tmp_data[0].branchperms & MAY_WRITE)) {
-+              printk("unionfs: leftmost branch cannot be read-only "
-+                     "(use \"remount,ro\" to create a read-only union)\n");
-+              err = -EINVAL;
-+              goto out_release;
-+      }
-+
-+      /* (re)allocate space for new pointers to hidden dentry */
-+      size = new_branches * sizeof(struct unionfs_data);
-+      new_data = krealloc(tmp_data, size, GFP_KERNEL);
-+      if (!new_data) {
-+              err = -ENOMEM;
-+              goto out_release;
-+      }
-+
-+      /* allocate space for new pointers to lower paths */
-+      size = new_branches * sizeof(struct path);
-+      new_lower_paths = krealloc(tmp_lower_paths, size, GFP_KERNEL);
-+      if (!new_lower_paths) {
-+              err = -ENOMEM;
-+              goto out_release;
-+      }
-+
-+      /* allocate space for new pointers to lower inodes */
-+      new_lower_inodes = kcalloc(new_branches,
-+                                 sizeof(struct inode *), GFP_KERNEL);
-+      if (!new_lower_inodes) {
-+              err = -ENOMEM;
-+              goto out_release;
++              nsp32_dbg(NSP32_DEBUG_SGLIST, "single : addr 0x%lx len=0x%lx",
++                        le32_to_cpu(sgt[0].addr),
++                        le32_to_cpu(sgt[0].len ));
+       }
+       return TRUE;
+@@ -922,7 +962,7 @@
+                 "enter. target: 0x%x LUN: 0x%x cmnd: 0x%x cmndlen: 0x%x "
+                 "use_sg: 0x%x reqbuf: 0x%lx reqlen: 0x%x",
+                 SCpnt->device->id, SCpnt->device->lun, SCpnt->cmnd[0], SCpnt->cmd_len,
+-                scsi_sg_count(SCpnt), scsi_sglist(SCpnt), scsi_bufflen(SCpnt));
++                SCpnt->use_sg, SCpnt->request_buffer, SCpnt->request_bufflen);
+       if (data->CurrentSC != NULL) {
+               nsp32_msg(KERN_ERR, "Currentsc != NULL. Cancel this command request");
+@@ -954,10 +994,10 @@
+       data->CurrentSC      = SCpnt;
+       SCpnt->SCp.Status    = CHECK_CONDITION;
+       SCpnt->SCp.Message   = 0;
+-      scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
++      SCpnt->resid         = SCpnt->request_bufflen;
+-      SCpnt->SCp.ptr              = (char *)scsi_sglist(SCpnt);
+-      SCpnt->SCp.this_residual    = scsi_bufflen(SCpnt);
++      SCpnt->SCp.ptr              = (char *) SCpnt->request_buffer;
++      SCpnt->SCp.this_residual    = SCpnt->request_bufflen;
+       SCpnt->SCp.buffer           = NULL;
+       SCpnt->SCp.buffers_residual = 0;
+@@ -1170,9 +1210,13 @@
+       unsigned long flags;
+       int ret;
+       int handled = 0;
+-      struct Scsi_Host *host = data->Host;
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
++      struct Scsi_Host *host = data->Host;
+       spin_lock_irqsave(host->host_lock, flags);
++#else
++      spin_lock_irqsave(&io_request_lock, flags);
++#endif
+       /*
+        * IRQ check, then enable IRQ mask
+@@ -1268,7 +1312,7 @@
+               }
+               if ((auto_stat & DATA_IN_PHASE) &&
+-                  (scsi_get_resid(SCpnt) > 0) &&
++                  (SCpnt->resid > 0) &&
+                   ((nsp32_read2(base, FIFO_REST_CNT) & FIFO_REST_MASK) != 0)) {
+                       printk( "auto+fifo\n");
+                       //nsp32_pio_read(SCpnt);
+@@ -1289,7 +1333,7 @@
+                       nsp32_dbg(NSP32_DEBUG_INTR, "SSACK=0x%lx", 
+                                   nsp32_read4(base, SAVED_SACK_CNT));
+-                      scsi_set_resid(SCpnt, 0); /* all data transfered! */
++                      SCpnt->resid = 0; /* all data transfered! */
+               }
+               /*
+@@ -1436,7 +1480,11 @@
+       nsp32_write2(base, IRQ_CONTROL, 0);
+  out2:
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+       spin_unlock_irqrestore(host->host_lock, flags);
++#else
++      spin_unlock_irqrestore(&io_request_lock, flags);
++#endif
+       nsp32_dbg(NSP32_DEBUG_INTR, "exit");
+@@ -1451,15 +1499,28 @@
+                       nsp32_dbg(NSP32_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length,  length - (pos - buffer));\
+               } \
+       } while(0)
+-
+-static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start,
+-                         off_t offset, int length, int inout)
++static int nsp32_proc_info(
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
++      struct Scsi_Host *host,
++#endif
++      char             *buffer,
++      char            **start,
++      off_t             offset,
++      int               length,
++#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
++      int               hostno,
++#endif
++      int               inout)
+ {
+       char             *pos = buffer;
+       int               thislength;
+       unsigned long     flags;
+       nsp32_hw_data    *data;
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
+       int               hostno;
++#else
++      struct Scsi_Host *host;
++#endif
+       unsigned int      base;
+       unsigned char     mode_reg;
+       int               id, speed;
+@@ -1470,7 +1531,15 @@
+               return -EINVAL;
+       }
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
+       hostno = host->host_no;
++#else
++      /* search this HBA host */
++      host = scsi_host_hn_get(hostno);
++      if (host == NULL) {
++              return -ESRCH;
 +      }
-+
-+      /*
-+       * OK, just before we actually put the new set of branches in place,
-+       * we need to ensure that our own f/s has no dirty objects left.
-+       * Luckily, do_remount_sb() already calls shrink_dcache_sb(sb) and
-+       * fsync_super(sb), taking care of dentries, inodes, and dirty
-+       * pages.  So all that's left is for us to invalidate any leftover
-+       * (non-dirty) pages to ensure that they will be re-read from the
-+       * new lower branches (and to support mmap).
-+       */
-+
-+      /*
-+       * No we call drop_pagecache_sb() to invalidate all pages in this
-+       * super.  This function calls invalidate_inode_pages(mapping),
-+       * which calls invalidate_mapping_pages(): the latter, however, will
-+       * not invalidate pages which are dirty, locked, under writeback, or
-+       * mapped into page tables.  We shouldn't have to worry about dirty
-+       * or under-writeback pages, because do_remount_sb() called
-+       * fsync_super() which would not have returned until all dirty pages
-+       * were flushed.
-+       *
-+       * But do we have to worry about locked pages?  Is there any chance
-+       * that in here we'll get locked pages?
-+       *
-+       * XXX: what about pages mapped into pagetables?  Are these pages
-+       * which user processes may have mmap(2)'ed?  If so, then we need to
-+       * invalidate those too, no?  Maybe we'll have to write our own
-+       * version of invalidate_mapping_pages() which also handled mapped
-+       * pages.
-+       *
-+       * XXX: Alternatively, maybe we should call truncate_inode_pages(),
-+       * which use two passes over the pages list, and will truncate all
-+       * pages.
-+       */
-+      drop_pagecache_sb(sb);
-+
-+      /* copy new vectors into their correct place */
-+      tmp_data = UNIONFS_SB(sb)->data;
-+      UNIONFS_SB(sb)->data = new_data;
-+      new_data = NULL;        /* so don't free good pointers below */
-+      tmp_lower_paths = UNIONFS_D(sb->s_root)->lower_paths;
-+      UNIONFS_D(sb->s_root)->lower_paths = new_lower_paths;
-+      new_lower_paths = NULL; /* so don't free good pointers below */
-+
-+      /* update our unionfs_sb_info and root dentry index of last branch */
-+      i = sbmax(sb);          /* save no. of branches to release at end */
-+      sbend(sb) = new_branches - 1;
-+      set_dbend(sb->s_root, new_branches - 1);
-+      old_ibstart = ibstart(sb->s_root->d_inode);
-+      old_ibend = ibend(sb->s_root->d_inode);
-+      ibend(sb->s_root->d_inode) = new_branches - 1;
-+      UNIONFS_D(sb->s_root)->bcount = new_branches;
-+      new_branches = i; /* no. of branches to release below */
-+
++#endif
+       data = (nsp32_hw_data *)host->hostdata;
+       base = host->io_port;
+@@ -1557,8 +1626,25 @@
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       unsigned int   base = SCpnt->device->host->io_port;
+-      scsi_dma_unmap(SCpnt);
 +      /*
-+       * Update lower inodes: 3 steps
-+       * 1. grab ref on all new lower inodes
++       * unmap pci
 +       */
-+      for (i=dbstart(sb->s_root); i<=dbend(sb->s_root); i++) {
-+              struct dentry *lower_dentry =
-+                      unionfs_lower_dentry_idx(sb->s_root, i);
-+              atomic_inc(&lower_dentry->d_inode->i_count);
-+              new_lower_inodes[i] = lower_dentry->d_inode;
-+      }
-+      /* 2. release reference on all older lower inodes */
-+      for (i=old_ibstart; i<=old_ibend; i++) {
-+              iput(unionfs_lower_inode_idx(sb->s_root->d_inode, i));
-+              unionfs_set_lower_inode_idx(sb->s_root->d_inode, i, NULL);
++      if (SCpnt->request_bufflen == 0) {
++              goto skip;
 +      }
-+      kfree(UNIONFS_I(sb->s_root->d_inode)->lower_inodes);
-+      /* 3. update root dentry's inode to new lower_inodes array */
-+      UNIONFS_I(sb->s_root->d_inode)->lower_inodes = new_lower_inodes;
-+      new_lower_inodes = NULL;
-+
-+      /* maxbytes may have changed */
-+      sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
-+      /* update high branch ID */
-+      sbhbid(sb) = new_high_branch_id;
-+
-+      /* update our sb->generation for revalidating objects */
-+      i = atomic_inc_return(&UNIONFS_SB(sb)->generation);
-+      atomic_set(&UNIONFS_D(sb->s_root)->generation, i);
-+      atomic_set(&UNIONFS_I(sb->s_root->d_inode)->generation, i);
 +
-+      err = 0;                /* reset to success */
-+
-+      if (!(*flags & MS_SILENT))
-+              printk("unionfs: new generation number %d\n", i);
++      if (SCpnt->use_sg) {
++              pci_unmap_sg(data->Pci,
++                           (struct scatterlist *)SCpnt->request_buffer,
++                           SCpnt->use_sg, SCpnt->sc_data_direction);
++      } else {
++              pci_unmap_single(data->Pci,
++                               (u32)SCpnt->SCp.have_data_in,
++                               SCpnt->request_bufflen,
++                               SCpnt->sc_data_direction);
++      }
++ skip:
+       /*
+        * clear TRANSFERCONTROL_BM_START
+        */
+@@ -1714,7 +1800,7 @@
+               SCpnt->SCp.Message = 0;
+               nsp32_dbg(NSP32_DEBUG_BUSFREE, 
+                         "normal end stat=0x%x resid=0x%x\n",
+-                        SCpnt->SCp.Status, scsi_get_resid(SCpnt));
++                        SCpnt->SCp.Status, SCpnt->resid);
+               SCpnt->result = (DID_OK             << 16) |
+                               (SCpnt->SCp.Message <<  8) |
+                               (SCpnt->SCp.Status  <<  0);
+@@ -1758,7 +1844,7 @@
+       unsigned int          restlen, sentlen;
+       u32_le                len, addr;
+-      nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", scsi_get_resid(SCpnt));
++      nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", SCpnt->resid);
+       /* adjust saved SACK count with 4 byte start address boundary */
+       s_sacklen -= le32_to_cpu(sgt[old_entry].addr) & 3;
+@@ -1802,12 +1888,12 @@
+       return;
+  last:
+-      if (scsi_get_resid(SCpnt) < sentlen) {
++      if (SCpnt->resid < sentlen) {
+               nsp32_msg(KERN_ERR, "resid underflow");
+       }
+-      scsi_set_resid(SCpnt, scsi_get_resid(SCpnt) - sentlen);
+-      nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", scsi_get_resid(SCpnt));
++      SCpnt->resid -= sentlen;
++      nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", SCpnt->resid);
+       /* update hostdata and lun */
+@@ -1936,7 +2022,7 @@
+       transfer = 0;
+       transfer |= (TRANSFER_GO | ALL_COUNTER_CLR);
+       if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
+-              if (scsi_bufflen(SCpnt) > 0) {
++              if (SCpnt->request_bufflen > 0) {
+                       transfer |= BM_START;
+               }
+       } else if (data->trans_method & NSP32_TRANSFER_MMIO) {
+@@ -2588,7 +2674,17 @@
+  *    0x900-0xbff: (map same 0x800-0x8ff I/O port image repeatedly)
+  *    0xc00-0xfff: CardBus status registers
+  */
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
++#define DETECT_OK 0
++#define DETECT_NG 1
++#define PCIDEV    pdev
+ static int nsp32_detect(struct pci_dev *pdev)
++#else
++#define DETECT_OK 1
++#define DETECT_NG 0
++#define PCIDEV    (data->Pci)
++static int nsp32_detect(struct scsi_host_template *sht)
++#endif
+ {
+       struct Scsi_Host *host; /* registered host structure */
+       struct resource  *res;
+@@ -2601,7 +2697,11 @@
+       /*
+        * register this HBA as SCSI device
+        */
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+       host = scsi_host_alloc(&nsp32_template, sizeof(nsp32_hw_data));
++#else
++      host = scsi_register(sht, sizeof(nsp32_hw_data));
++#endif
+       if (host == NULL) {
+               nsp32_msg (KERN_ERR, "failed to scsi register");
+               goto err;
+@@ -2619,6 +2719,9 @@
+       host->unique_id = data->BaseAddress;
+       host->n_io_port = data->NumAddress;
+       host->base      = (unsigned long)data->MmioAddress;
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,63))
++      scsi_set_pci_device(host, PCIDEV);
++#endif
+       data->Host      = host;
+       spin_lock_init(&(data->Lock));
+@@ -2673,7 +2776,7 @@
+       /*
+        * setup DMA 
+        */
+-      if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) {
++      if (pci_set_dma_mask(PCIDEV, DMA_32BIT_MASK) != 0) {
+               nsp32_msg (KERN_ERR, "failed to set PCI DMA mask");
+               goto scsi_unregister;
+       }
+@@ -2681,7 +2784,7 @@
+       /*
+        * allocate autoparam DMA resource.
+        */
+-      data->autoparam = pci_alloc_consistent(pdev, sizeof(nsp32_autoparam), &(data->auto_paddr));
++      data->autoparam = pci_alloc_consistent(PCIDEV, sizeof(nsp32_autoparam), &(data->auto_paddr));
+       if (data->autoparam == NULL) {
+               nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
+               goto scsi_unregister;
+@@ -2690,7 +2793,7 @@
+       /*
+        * allocate scatter-gather DMA resource.
+        */
+-      data->sg_list = pci_alloc_consistent(pdev, NSP32_SG_TABLE_SIZE,
++      data->sg_list = pci_alloc_consistent(PCIDEV, NSP32_SG_TABLE_SIZE,
+                                            &(data->sg_paddr));
+       if (data->sg_list == NULL) {
+               nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
+@@ -2780,14 +2883,16 @@
+               goto free_irq;
+         }
+-      ret = scsi_add_host(host, &pdev->dev);
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
++      ret = scsi_add_host(host, &PCIDEV->dev);
+       if (ret) {
+               nsp32_msg(KERN_ERR, "failed to add scsi host");
+               goto free_region;
+       }
+       scsi_scan_host(host);
+-      pci_set_drvdata(pdev, host);
+-      return 0;
++#endif
++      pci_set_drvdata(PCIDEV, host);
++      return DETECT_OK;
+  free_region:
+       release_region(host->io_port, host->n_io_port);
+@@ -2796,19 +2901,22 @@
+       free_irq(host->irq, data);
+  free_sg_list:
+-      pci_free_consistent(pdev, NSP32_SG_TABLE_SIZE,
++      pci_free_consistent(PCIDEV, NSP32_SG_TABLE_SIZE,
+                           data->sg_list, data->sg_paddr);
+  free_autoparam:
+-      pci_free_consistent(pdev, sizeof(nsp32_autoparam),
++      pci_free_consistent(PCIDEV, sizeof(nsp32_autoparam),
+                           data->autoparam, data->auto_paddr);
+       
+  scsi_unregister:
+       scsi_host_put(host);
+  err:
+-      return 1;
++      return DETECT_NG;
+ }
++#undef DETECT_OK
++#undef DETECT_NG
++#undef PCIDEV
+ static int nsp32_release(struct Scsi_Host *host)
+ {
+@@ -3417,7 +3525,11 @@
+       pci_set_master(pdev);
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+       ret = nsp32_detect(pdev);
++#else
++      ret = scsi_register_host(&nsp32_template);
++#endif
+       nsp32_msg(KERN_INFO, "irq: %i mmio: %p+0x%lx slot: %s model: %s",
+                 pdev->irq,
+@@ -3432,17 +3544,25 @@
+ static void __devexit nsp32_remove(struct pci_dev *pdev)
+ {
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
++#endif
+       nsp32_dbg(NSP32_DEBUG_REGISTER, "enter");
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+         scsi_remove_host(host);
+       nsp32_release(host);
+       scsi_host_put(host);
++#else
++      scsi_unregister_host(&nsp32_template);  
++#endif
+ }
 +
-+      /*
-+       * The code above falls through to the next label, and releases the
-+       * refcnts of the older ones (stored in tmp_*): if we fell through
-+       * here, it means success.  However, if we jump directly to this
-+       * label from any error above, then an error occurred after we
-+       * grabbed various refcnts, and so we have to release the
-+       * temporarily constructed structures.
-+       */
-+out_release:
-+      /* no need to cleanup/release anything in tmp_data */
-+      if (tmp_lower_paths)
-+              for (i=0; i<new_branches; i++)
-+                      pathput(&tmp_lower_paths[i]);
-+out_free:
-+      kfree(tmp_lower_paths);
-+      kfree(tmp_data);
-+      kfree(new_lower_paths);
-+      kfree(new_data);
-+      kfree(new_lower_inodes);
-+out_error:
-+      unionfs_write_unlock(sb);
-+      return err;
-+}
 +
-+/*
-+ * Called by iput() when the inode reference count reached zero
-+ * and the inode is not hashed anywhere.  Used to clear anything
-+ * that needs to be, before the inode is completely destroyed and put
-+ * on the inode free list.
-+ *
-+ * No need to lock sb info's rwsem.
-+ */
-+static void unionfs_clear_inode(struct inode *inode)
-+{
-+      int bindex, bstart, bend;
-+      struct inode *hidden_inode;
-+      struct list_head *pos, *n;
-+      struct unionfs_dir_state *rdstate;
+ static struct pci_driver nsp32_driver = {
+       .name           = "nsp32",
+       .id_table       = nsp32_pci_table,
+diff -Nurb linux-2.6.22-590/drivers/scsi/pcmcia/sym53c500_cs.c linux-2.6.22-570/drivers/scsi/pcmcia/sym53c500_cs.c
+--- linux-2.6.22-590/drivers/scsi/pcmcia/sym53c500_cs.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/pcmcia/sym53c500_cs.c        2007-07-08 19:32:17.000000000 -0400
+@@ -370,6 +370,8 @@
+       DEB(unsigned char seq_reg;)
+       unsigned char status, int_reg;
+       unsigned char pio_status;
++      struct scatterlist *sglist;
++      unsigned int sgcount;
+       int port_base = dev->io_port;
+       struct sym53c500_data *data =
+           (struct sym53c500_data *)dev->hostdata;
+@@ -432,19 +434,20 @@
+       switch (status & 0x07) {        /* scsi phase */
+       case 0x00:                      /* DATA-OUT */
+               if (int_reg & 0x10) {   /* Target requesting info transfer */
+-                      struct scatterlist *sg;
+-                      int i;
+-
+                       curSC->SCp.phase = data_out;
+                       VDEB(printk("SYM53C500: Data-Out phase\n"));
+                       outb(FLUSH_FIFO, port_base + CMD_REG);
+-                      LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC)); /* Max transfer size */
++                      LOAD_DMA_COUNT(port_base, curSC->request_bufflen);      /* Max transfer size */
+                       outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG);
+-
+-                      scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) {
+-                              SYM53C500_pio_write(fast_pio, port_base,
+-                                                  page_address(sg->page) + sg->offset,
+-                                                  sg->length);
++                      if (!curSC->use_sg)     /* Don't use scatter-gather */
++                              SYM53C500_pio_write(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen);
++                      else {  /* use scatter-gather */
++                              sgcount = curSC->use_sg;
++                              sglist = curSC->request_buffer;
++                              while (sgcount--) {
++                                      SYM53C500_pio_write(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length);
++                                      sglist++;
++                              }
+                       }
+                       REG0(port_base);
+               }
+@@ -452,19 +455,20 @@
+       case 0x01:              /* DATA-IN */
+               if (int_reg & 0x10) {   /* Target requesting info transfer */
+-                      struct scatterlist *sg;
+-                      int i;
+-
+                       curSC->SCp.phase = data_in;
+                       VDEB(printk("SYM53C500: Data-In phase\n"));
+                       outb(FLUSH_FIFO, port_base + CMD_REG);
+-                      LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC)); /* Max transfer size */
++                      LOAD_DMA_COUNT(port_base, curSC->request_bufflen);      /* Max transfer size */
+                       outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG);
+-
+-                      scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) {
+-                              SYM53C500_pio_read(fast_pio, port_base,
+-                                                 page_address(sg->page) + sg->offset,
+-                                                 sg->length);
++                      if (!curSC->use_sg)     /* Don't use scatter-gather */
++                              SYM53C500_pio_read(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen);
++                      else {  /* Use scatter-gather */
++                              sgcount = curSC->use_sg;
++                              sglist = curSC->request_buffer;
++                              while (sgcount--) {
++                                      SYM53C500_pio_read(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length);
++                                      sglist++;
++                              }
+                       }
+                       REG0(port_base);
+               }
+@@ -574,7 +578,7 @@
+       DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", 
+           SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->id, 
+-          SCpnt->device->lun,  scsi_bufflen(SCpnt)));
++          SCpnt->device->lun,  SCpnt->request_bufflen));
+       VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
+           printk("cmd[%d]=%02x  ", i, SCpnt->cmnd[i]));
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla2xxx/qla_attr.c linux-2.6.22-570/drivers/scsi/qla2xxx/qla_attr.c
+--- linux-2.6.22-590/drivers/scsi/qla2xxx/qla_attr.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla2xxx/qla_attr.c   2007-07-08 19:32:17.000000000 -0400
+@@ -11,9 +11,8 @@
+ /* SYSFS attributes --------------------------------------------------------- */
+ static ssize_t
+-qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
+-                         struct bin_attribute *bin_attr,
+-                         char *buf, loff_t off, size_t count)
++qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+           struct device, kobj)));
+@@ -32,9 +31,8 @@
+ }
+ static ssize_t
+-qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
+-                          struct bin_attribute *bin_attr,
+-                          char *buf, loff_t off, size_t count)
++qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+           struct device, kobj)));
+@@ -75,6 +73,7 @@
+       .attr = {
+               .name = "fw_dump",
+               .mode = S_IRUSR | S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = 0,
+       .read = qla2x00_sysfs_read_fw_dump,
+@@ -82,9 +81,8 @@
+ };
+ static ssize_t
+-qla2x00_sysfs_read_nvram(struct kobject *kobj,
+-                       struct bin_attribute *bin_attr,
+-                       char *buf, loff_t off, size_t count)
++qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+           struct device, kobj)));
+@@ -103,9 +101,8 @@
+ }
+ static ssize_t
+-qla2x00_sysfs_write_nvram(struct kobject *kobj,
+-                        struct bin_attribute *bin_attr,
+-                        char *buf, loff_t off, size_t count)
++qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+           struct device, kobj)));
+@@ -152,6 +149,7 @@
+       .attr = {
+               .name = "nvram",
+               .mode = S_IRUSR | S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = 512,
+       .read = qla2x00_sysfs_read_nvram,
+@@ -159,9 +157,8 @@
+ };
+ static ssize_t
+-qla2x00_sysfs_read_optrom(struct kobject *kobj,
+-                        struct bin_attribute *bin_attr,
+-                        char *buf, loff_t off, size_t count)
++qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+           struct device, kobj)));
+@@ -179,9 +176,8 @@
+ }
+ static ssize_t
+-qla2x00_sysfs_write_optrom(struct kobject *kobj,
+-                         struct bin_attribute *bin_attr,
+-                         char *buf, loff_t off, size_t count)
++qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+           struct device, kobj)));
+@@ -202,6 +198,7 @@
+       .attr = {
+               .name = "optrom",
+               .mode = S_IRUSR | S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = OPTROM_SIZE_24XX,
+       .read = qla2x00_sysfs_read_optrom,
+@@ -209,9 +206,8 @@
+ };
+ static ssize_t
+-qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
+-                             struct bin_attribute *bin_attr,
+-                             char *buf, loff_t off, size_t count)
++qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+           struct device, kobj)));
+@@ -283,15 +279,15 @@
+       .attr = {
+               .name = "optrom_ctl",
+               .mode = S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = 0,
+       .write = qla2x00_sysfs_write_optrom_ctl,
+ };
+ static ssize_t
+-qla2x00_sysfs_read_vpd(struct kobject *kobj,
+-                     struct bin_attribute *bin_attr,
+-                     char *buf, loff_t off, size_t count)
++qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+           struct device, kobj)));
+@@ -309,9 +305,8 @@
+ }
+ static ssize_t
+-qla2x00_sysfs_write_vpd(struct kobject *kobj,
+-                      struct bin_attribute *bin_attr,
+-                      char *buf, loff_t off, size_t count)
++qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+           struct device, kobj)));
+@@ -332,6 +327,7 @@
+       .attr = {
+               .name = "vpd",
+               .mode = S_IRUSR | S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = 0,
+       .read = qla2x00_sysfs_read_vpd,
+@@ -339,9 +335,8 @@
+ };
+ static ssize_t
+-qla2x00_sysfs_read_sfp(struct kobject *kobj,
+-                     struct bin_attribute *bin_attr,
+-                     char *buf, loff_t off, size_t count)
++qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off,
++    size_t count)
+ {
+       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+           struct device, kobj)));
+@@ -380,6 +375,7 @@
+       .attr = {
+               .name = "sfp",
+               .mode = S_IRUSR | S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = SFP_DEV_SIZE * 2,
+       .read = qla2x00_sysfs_read_sfp,
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla2xxx/qla_dbg.c linux-2.6.22-570/drivers/scsi/qla2xxx/qla_dbg.c
+--- linux-2.6.22-590/drivers/scsi/qla2xxx/qla_dbg.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla2xxx/qla_dbg.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1411,9 +1411,9 @@
+               printk("0x%02x ", cmd->cmnd[i]);
+       }
+       printk("\n  seg_cnt=%d, allowed=%d, retries=%d\n",
+-             scsi_sg_count(cmd), cmd->allowed, cmd->retries);
++          cmd->use_sg, cmd->allowed, cmd->retries);
+       printk("  request buffer=0x%p, request buffer len=0x%x\n",
+-             scsi_sglist(cmd), scsi_bufflen(cmd));
++          cmd->request_buffer, cmd->request_bufflen);
+       printk("  tag=%d, transfersize=0x%x\n",
+           cmd->tag, cmd->transfersize);
+       printk("  serial_number=%lx, SP=%p\n", cmd->serial_number, sp);
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla2xxx/qla_iocb.c linux-2.6.22-570/drivers/scsi/qla2xxx/qla_iocb.c
+--- linux-2.6.22-590/drivers/scsi/qla2xxx/qla_iocb.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla2xxx/qla_iocb.c   2007-07-08 19:32:17.000000000 -0400
+@@ -155,8 +155,6 @@
+       uint32_t        *cur_dsd;
+       scsi_qla_host_t *ha;
+       struct scsi_cmnd *cmd;
+-      struct scatterlist *sg;
+-      int i;
+       cmd = sp->cmd;
+@@ -165,7 +163,7 @@
+           __constant_cpu_to_le32(COMMAND_TYPE);
+       /* No data transfer */
+-      if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
++      if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
+               cmd_pkt->byte_count = __constant_cpu_to_le32(0);
+               return;
+       }
+@@ -179,8 +177,13 @@
+       cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
+       /* Load data segments */
+-
+-      scsi_for_each_sg(cmd, sg, tot_dsds, i) {
++      if (cmd->use_sg != 0) {
++              struct  scatterlist *cur_seg;
++              struct  scatterlist *end_seg;
 +
-+      list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
-+              rdstate = list_entry(pos, struct unionfs_dir_state, cache);
-+              list_del(&rdstate->cache);
-+              free_rdstate(rdstate);
-+      }
++              cur_seg = (struct scatterlist *)cmd->request_buffer;
++              end_seg = cur_seg + tot_dsds;
++              while (cur_seg < end_seg) {
+                       cont_entry_t    *cont_pkt;
+                       /* Allocate additional continuation packets? */
+@@ -194,9 +197,15 @@
+                               avail_dsds = 7;
+                       }
+-              *cur_dsd++ = cpu_to_le32(sg_dma_address(sg));
+-              *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
++                      *cur_dsd++ = cpu_to_le32(sg_dma_address(cur_seg));
++                      *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
+                       avail_dsds--;
 +
-+      /*
-+       * Decrement a reference to a hidden_inode, which was incremented
-+       * by our read_inode when it was created initially.
-+       */
-+      bstart = ibstart(inode);
-+      bend = ibend(inode);
-+      if (bstart >= 0) {
-+              for (bindex = bstart; bindex <= bend; bindex++) {
-+                      hidden_inode = unionfs_lower_inode_idx(inode, bindex);
-+                      if (!hidden_inode)
-+                              continue;
-+                      iput(hidden_inode);
++                      cur_seg++;
 +              }
-+      }
-+
-+      kfree(UNIONFS_I(inode)->lower_inodes);
-+      UNIONFS_I(inode)->lower_inodes = NULL;
-+}
-+
-+static struct inode *unionfs_alloc_inode(struct super_block *sb)
-+{
-+      struct unionfs_inode_info *i;
-+
-+      i = kmem_cache_alloc(unionfs_inode_cachep, GFP_KERNEL);
-+      if (!i)
-+              return NULL;
-+
-+      /* memset everything up to the inode to 0 */
-+      memset(i, 0, offsetof(struct unionfs_inode_info, vfs_inode));
-+
-+      i->vfs_inode.i_version = 1;
-+      return &i->vfs_inode;
-+}
-+
-+static void unionfs_destroy_inode(struct inode *inode)
-+{
-+      kmem_cache_free(unionfs_inode_cachep, UNIONFS_I(inode));
-+}
-+
-+/* unionfs inode cache constructor */
-+static void init_once(void *v, struct kmem_cache *cachep, unsigned long flags)
-+{
-+      struct unionfs_inode_info *i = v;
-+
-+      inode_init_once(&i->vfs_inode);
-+}
-+
-+int unionfs_init_inode_cache(void)
-+{
-+      int err = 0;
-+
-+      unionfs_inode_cachep =
-+              kmem_cache_create("unionfs_inode_cache",
-+                                sizeof(struct unionfs_inode_info), 0,
-+                                SLAB_RECLAIM_ACCOUNT, init_once, NULL);
-+      if (!unionfs_inode_cachep)
-+              err = -ENOMEM;
-+      return err;
-+}
-+
-+/* unionfs inode cache destructor */
-+void unionfs_destroy_inode_cache(void)
-+{
-+      if (unionfs_inode_cachep)
-+              kmem_cache_destroy(unionfs_inode_cachep);
-+}
-+
-+/*
-+ * Called when we have a dirty inode, right here we only throw out
-+ * parts of our readdir list that are too old.
-+ *
-+ * No need to grab sb info's rwsem.
-+ */
-+static int unionfs_write_inode(struct inode *inode, int sync)
-+{
-+      struct list_head *pos, *n;
-+      struct unionfs_dir_state *rdstate;
-+
-+      spin_lock(&UNIONFS_I(inode)->rdlock);
-+      list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
-+              rdstate = list_entry(pos, struct unionfs_dir_state, cache);
-+              /* We keep this list in LRU order. */
-+              if ((rdstate->access + RDCACHE_JIFFIES) > jiffies)
-+                      break;
-+              UNIONFS_I(inode)->rdcount--;
-+              list_del(&rdstate->cache);
-+              free_rdstate(rdstate);
-+      }
-+      spin_unlock(&UNIONFS_I(inode)->rdlock);
-+
-+      return 0;
-+}
-+
-+/*
-+ * Used only in nfs, to kill any pending RPC tasks, so that subsequent
-+ * code can actually succeed and won't leave tasks that need handling.
-+ */
-+static void unionfs_umount_begin(struct vfsmount *mnt, int flags)
-+{
-+      struct super_block *sb, *hidden_sb;
-+      struct vfsmount *hidden_mnt;
-+      int bindex, bstart, bend;
-+
-+      if (!(flags & MNT_FORCE))
-+              /*
-+               * we are not being MNT_FORCE'd, therefore we should emulate
-+               * old behavior
-+               */
-+              return;
-+
-+      sb = mnt->mnt_sb;
++      } else {
++              *cur_dsd++ = cpu_to_le32(sp->dma_handle);
++              *cur_dsd++ = cpu_to_le32(cmd->request_bufflen);
+       }
+ }
+@@ -215,8 +224,6 @@
+       uint32_t        *cur_dsd;
+       scsi_qla_host_t *ha;
+       struct scsi_cmnd *cmd;
+-      struct scatterlist *sg;
+-      int i;
+       cmd = sp->cmd;
+@@ -225,7 +232,7 @@
+           __constant_cpu_to_le32(COMMAND_A64_TYPE);
+       /* No data transfer */
+-      if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
++      if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
+               cmd_pkt->byte_count = __constant_cpu_to_le32(0);
+               return;
+       }
+@@ -239,7 +246,13 @@
+       cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
+       /* Load data segments */
+-      scsi_for_each_sg(cmd, sg, tot_dsds, i) {
++      if (cmd->use_sg != 0) {
++              struct  scatterlist *cur_seg;
++              struct  scatterlist *end_seg;
++
++              cur_seg = (struct scatterlist *)cmd->request_buffer;
++              end_seg = cur_seg + tot_dsds;
++              while (cur_seg < end_seg) {
+                       dma_addr_t      sle_dma;
+                       cont_a64_entry_t *cont_pkt;
+@@ -254,11 +267,18 @@
+                               avail_dsds = 5;
+                       }
+-              sle_dma = sg_dma_address(sg);
++                      sle_dma = sg_dma_address(cur_seg);
+                       *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+                       *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
+-              *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
++                      *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
+                       avail_dsds--;
 +
-+      unionfs_read_lock(sb);
++                      cur_seg++;
++              }
++      } else {
++              *cur_dsd++ = cpu_to_le32(LSD(sp->dma_handle));
++              *cur_dsd++ = cpu_to_le32(MSD(sp->dma_handle));
++              *cur_dsd++ = cpu_to_le32(cmd->request_bufflen);
+       }
+ }
+@@ -271,7 +291,7 @@
+ int
+ qla2x00_start_scsi(srb_t *sp)
+ {
+-      int             ret, nseg;
++      int             ret;
+       unsigned long   flags;
+       scsi_qla_host_t *ha;
+       struct scsi_cmnd *cmd;
+@@ -279,6 +299,7 @@
+       uint32_t        index;
+       uint32_t        handle;
+       cmd_entry_t     *cmd_pkt;
++      struct scatterlist *sg;
+       uint16_t        cnt;
+       uint16_t        req_cnt;
+       uint16_t        tot_dsds;
+@@ -316,10 +337,23 @@
+               goto queuing_error;
+       /* Map the sg table so we have an accurate count of sg entries needed */
+-      nseg = scsi_dma_map(cmd);
+-      if (nseg < 0)
++      if (cmd->use_sg) {
++              sg = (struct scatterlist *) cmd->request_buffer;
++              tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg,
++                  cmd->sc_data_direction);
++              if (tot_dsds == 0)
+                       goto queuing_error;
+-      tot_dsds = nseg;
++      } else if (cmd->request_bufflen) {
++              dma_addr_t      req_dma;
 +
-+      bstart = sbstart(sb);
-+      bend = sbend(sb);
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              hidden_mnt = unionfs_lower_mnt_idx(sb->s_root, bindex);
-+              hidden_sb = unionfs_lower_super_idx(sb, bindex);
++              req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
++                  cmd->request_bufflen, cmd->sc_data_direction);
++              if (dma_mapping_error(req_dma))
++                      goto queuing_error;
 +
-+              if (hidden_mnt && hidden_sb && hidden_sb->s_op &&
-+                  hidden_sb->s_op->umount_begin)
-+                      hidden_sb->s_op->umount_begin(hidden_mnt, flags);
++              sp->dma_handle = req_dma;
++              tot_dsds = 1;
 +      }
-+
-+      unionfs_read_unlock(sb);
-+}
-+
-+static int unionfs_show_options(struct seq_file *m, struct vfsmount *mnt)
-+{
-+      struct super_block *sb = mnt->mnt_sb;
-+      int ret = 0;
-+      char *tmp_page;
-+      char *path;
-+      int bindex, bstart, bend;
-+      int perms;
-+
-+      unionfs_read_lock(sb);
-+
-+      unionfs_lock_dentry(sb->s_root);
-+
-+      tmp_page = (char*) __get_free_page(GFP_KERNEL);
-+      if (!tmp_page) {
-+              ret = -ENOMEM;
-+              goto out;
+       /* Calculate the number of request entries needed. */
+       req_cnt = ha->isp_ops.calc_req_entries(tot_dsds);
+@@ -357,7 +391,7 @@
+       /* Load SCSI command packet. */
+       memcpy(cmd_pkt->scsi_cdb, cmd->cmnd, cmd->cmd_len);
+-      cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
++      cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen);
+       /* Build IOCB segments */
+       ha->isp_ops.build_iocbs(sp, cmd_pkt, tot_dsds);
+@@ -389,9 +423,14 @@
+       return (QLA_SUCCESS);
+ queuing_error:
+-      if (tot_dsds)
+-              scsi_dma_unmap(cmd);
+-
++      if (cmd->use_sg && tot_dsds) {
++              sg = (struct scatterlist *) cmd->request_buffer;
++              pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
++                  cmd->sc_data_direction);
++      } else if (tot_dsds) {
++              pci_unmap_single(ha->pdev, sp->dma_handle,
++                  cmd->request_bufflen, cmd->sc_data_direction);
 +      }
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       return (QLA_FUNCTION_FAILED);
+@@ -603,8 +642,6 @@
+       uint32_t        *cur_dsd;
+       scsi_qla_host_t *ha;
+       struct scsi_cmnd *cmd;
+-      struct scatterlist *sg;
+-      int i;
+       cmd = sp->cmd;
+@@ -613,7 +650,7 @@
+           __constant_cpu_to_le32(COMMAND_TYPE_7);
+       /* No data transfer */
+-      if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
++      if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
+               cmd_pkt->byte_count = __constant_cpu_to_le32(0);
+               return;
+       }
+@@ -633,8 +670,13 @@
+       cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
+       /* Load data segments */
+-
+-      scsi_for_each_sg(cmd, sg, tot_dsds, i) {
++      if (cmd->use_sg != 0) {
++              struct  scatterlist *cur_seg;
++              struct  scatterlist *end_seg;
 +
-+      bstart = sbstart(sb);
-+      bend = sbend(sb);
++              cur_seg = (struct scatterlist *)cmd->request_buffer;
++              end_seg = cur_seg + tot_dsds;
++              while (cur_seg < end_seg) {
+                       dma_addr_t      sle_dma;
+                       cont_a64_entry_t *cont_pkt;
+@@ -649,11 +691,18 @@
+                               avail_dsds = 5;
+                       }
+-              sle_dma = sg_dma_address(sg);
++                      sle_dma = sg_dma_address(cur_seg);
+                       *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+                       *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
+-              *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
++                      *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
+                       avail_dsds--;
 +
-+      seq_printf(m, ",dirs=");
-+      for (bindex = bstart; bindex <= bend; bindex++) {
-+              path = d_path(unionfs_lower_dentry_idx(sb->s_root, bindex),
-+                            unionfs_lower_mnt_idx(sb->s_root, bindex),
-+                            tmp_page, PAGE_SIZE);
-+              if (IS_ERR(path)) {
-+                      ret = PTR_ERR(path);
-+                      goto out;
++                      cur_seg++;
 +              }
++      } else {
++              *cur_dsd++ = cpu_to_le32(LSD(sp->dma_handle));
++              *cur_dsd++ = cpu_to_le32(MSD(sp->dma_handle));
++              *cur_dsd++ = cpu_to_le32(cmd->request_bufflen);
+       }
+ }
+@@ -667,7 +716,7 @@
+ int
+ qla24xx_start_scsi(srb_t *sp)
+ {
+-      int             ret, nseg;
++      int             ret;
+       unsigned long   flags;
+       scsi_qla_host_t *ha;
+       struct scsi_cmnd *cmd;
+@@ -675,6 +724,7 @@
+       uint32_t        index;
+       uint32_t        handle;
+       struct cmd_type_7 *cmd_pkt;
++      struct scatterlist *sg;
+       uint16_t        cnt;
+       uint16_t        req_cnt;
+       uint16_t        tot_dsds;
+@@ -712,10 +762,23 @@
+               goto queuing_error;
+       /* Map the sg table so we have an accurate count of sg entries needed */
+-      nseg = scsi_dma_map(cmd);
+-      if (nseg < 0)
++      if (cmd->use_sg) {
++              sg = (struct scatterlist *) cmd->request_buffer;
++              tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg,
++                  cmd->sc_data_direction);
++              if (tot_dsds == 0)
++                      goto queuing_error;
++      } else if (cmd->request_bufflen) {
++              dma_addr_t      req_dma;
++
++              req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
++                  cmd->request_bufflen, cmd->sc_data_direction);
++              if (dma_mapping_error(req_dma))
+                       goto queuing_error;
+-      tot_dsds = nseg;
 +
-+              perms = branchperms(sb, bindex);
-+
-+              seq_printf(m, "%s=%s", path,
-+                         perms & MAY_WRITE ? "rw" : "ro");
-+              if (bindex != bend)
-+                      seq_printf(m, ":");
++              sp->dma_handle = req_dma;
++              tot_dsds = 1;
 +      }
-+
-+out:
-+      free_page((unsigned long) tmp_page);
-+
-+      unionfs_unlock_dentry(sb->s_root);
-+
-+      unionfs_read_unlock(sb);
-+
-+      return ret;
-+}
-+
-+struct super_operations unionfs_sops = {
-+      .read_inode     = unionfs_read_inode,
-+      .delete_inode   = unionfs_delete_inode,
-+      .put_super      = unionfs_put_super,
-+      .statfs         = unionfs_statfs,
-+      .remount_fs     = unionfs_remount_fs,
-+      .clear_inode    = unionfs_clear_inode,
-+      .umount_begin   = unionfs_umount_begin,
-+      .show_options   = unionfs_show_options,
-+      .write_inode    = unionfs_write_inode,
-+      .alloc_inode    = unionfs_alloc_inode,
-+      .destroy_inode  = unionfs_destroy_inode,
-+};
-diff -Nurb linux-2.6.22-570/fs/unionfs/union.h linux-2.6.22-590/fs/unionfs/union.h
---- linux-2.6.22-570/fs/unionfs/union.h        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/union.h        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,467 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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.
-+ */
-+
-+#ifndef _UNION_H_
-+#define _UNION_H_
-+
-+#include <linux/dcache.h>
-+#include <linux/file.h>
-+#include <linux/list.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/module.h>
-+#include <linux/mount.h>
-+#include <linux/namei.h>
-+#include <linux/page-flags.h>
-+#include <linux/pagemap.h>
-+#include <linux/poll.h>
-+#include <linux/security.h>
-+#include <linux/seq_file.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/statfs.h>
-+#include <linux/string.h>
-+#include <linux/vmalloc.h>
-+#include <linux/writeback.h>
-+#include <linux/buffer_head.h>
-+#include <linux/xattr.h>
-+#include <linux/fs_stack.h>
-+#include <linux/magic.h>
-+#include <linux/log2.h>
-+
-+#include <asm/mman.h>
-+#include <asm/system.h>
-+
-+#include <linux/union_fs.h>
-+
-+/* the file system name */
-+#define UNIONFS_NAME "unionfs"
-+
-+/* unionfs root inode number */
-+#define UNIONFS_ROOT_INO     1
-+
-+/* number of times we try to get a unique temporary file name */
-+#define GET_TMPNAM_MAX_RETRY  5
-+
-+/* maximum number of branches we support, to avoid memory blowup */
-+#define UNIONFS_MAX_BRANCHES  128
-+
-+/* Operations vectors defined in specific files. */
-+extern struct file_operations unionfs_main_fops;
-+extern struct file_operations unionfs_dir_fops;
-+extern struct inode_operations unionfs_main_iops;
-+extern struct inode_operations unionfs_dir_iops;
-+extern struct inode_operations unionfs_symlink_iops;
-+extern struct super_operations unionfs_sops;
-+extern struct dentry_operations unionfs_dops;
-+
-+/* How long should an entry be allowed to persist */
-+#define RDCACHE_JIFFIES       (5*HZ)
-+
-+/* file private data. */
-+struct unionfs_file_info {
-+      int bstart;
-+      int bend;
-+      atomic_t generation;
-+
-+      struct unionfs_dir_state *rdstate;
-+      struct file **lower_files;
-+      int *saved_branch_ids; /* IDs of branches when file was opened */
-+};
-+
-+/* unionfs inode data in memory */
-+struct unionfs_inode_info {
-+      int bstart;
-+      int bend;
-+      atomic_t generation;
-+      int stale;
-+      /* Stuff for readdir over NFS. */
-+      spinlock_t rdlock;
-+      struct list_head readdircache;
-+      int rdcount;
-+      int hashsize;
-+      int cookie;
-+
-+      /* The hidden inodes */
-+      struct inode **lower_inodes;
-+      /* to keep track of reads/writes for unlinks before closes */
-+      atomic_t totalopens;
-+
-+      struct inode vfs_inode;
-+};
-+
-+/* unionfs dentry data in memory */
-+struct unionfs_dentry_info {
-+      /*
-+       * The semaphore is used to lock the dentry as soon as we get into a
-+       * unionfs function from the VFS.  Our lock ordering is that children
-+       * go before their parents.
-+       */
-+      struct mutex lock;
-+      int bstart;
-+      int bend;
-+      int bopaque;
-+      int bcount;
-+      atomic_t generation;
-+      struct path *lower_paths;
-+};
-+
-+/* These are the pointers to our various objects. */
-+struct unionfs_data {
-+      struct super_block *sb;
-+      atomic_t open_files;    /* number of open files on branch */
-+      int branchperms;
-+      int branch_id;          /* unique branch ID at re/mount time */
-+};
-+
-+/* unionfs super-block data in memory */
-+struct unionfs_sb_info {
-+      int bend;
-+
-+      atomic_t generation;
-+
-+      /*
-+       * This rwsem is used to make sure that a branch management
-+       * operation...
-+       *   1) will not begin before all currently in-flight operations
-+       *      complete
-+       *   2) any new operations do not execute until the currently
-+       *      running branch management operation completes
-+       */
-+      struct rw_semaphore rwsem;
-+      int high_branch_id;     /* last unique branch ID given */
-+      struct unionfs_data *data;
-+};
-+
-+/*
-+ * structure for making the linked list of entries by readdir on left branch
-+ * to compare with entries on right branch
-+ */
-+struct filldir_node {
-+      struct list_head file_list;     /* list for directory entries */
-+      char *name;             /* name entry */
-+      int hash;               /* name hash */
-+      int namelen;            /* name len since name is not 0 terminated */
-+
-+      /*
-+       * we can check for duplicate whiteouts and files in the same branch
-+       * in order to return -EIO.
-+       */
-+      int bindex;
-+
-+      /* is this a whiteout entry? */
-+      int whiteout;
-+
-+      /* Inline name, so we don't need to separately kmalloc small ones */
-+      char iname[DNAME_INLINE_LEN_MIN];
-+};
-+
-+/* Directory hash table. */
-+struct unionfs_dir_state {
-+      unsigned int cookie;    /* the cookie, based off of rdversion */
-+      unsigned int offset;    /* The entry we have returned. */
-+      int bindex;
-+      loff_t dirpos;          /* offset within the lower level directory */
-+      int size;               /* How big is the hash table? */
-+      int hashentries;        /* How many entries have been inserted? */
-+      unsigned long access;
-+
-+      /* This cache list is used when the inode keeps us around. */
-+      struct list_head cache;
-+      struct list_head list[0];
-+};
-+
-+/* include miscellaneous macros */
-+#include "fanout.h"
-+#include "sioq.h"
-+
-+/* externs for cache creation/deletion routines */
-+extern void unionfs_destroy_filldir_cache(void);
-+extern int unionfs_init_filldir_cache(void);
-+extern int unionfs_init_inode_cache(void);
-+extern void unionfs_destroy_inode_cache(void);
-+extern int unionfs_init_dentry_cache(void);
-+extern void unionfs_destroy_dentry_cache(void);
-+
-+/* Initialize and free readdir-specific  state. */
-+extern int init_rdstate(struct file *file);
-+extern struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex);
-+extern struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos);
-+extern void free_rdstate(struct unionfs_dir_state *state);
-+extern int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name,
-+                          int namelen, int bindex, int whiteout);
-+extern struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
-+                                            const char *name, int namelen);
-+
-+extern struct dentry **alloc_new_dentries(int objs);
-+extern struct unionfs_data *alloc_new_data(int objs);
-+
-+/* We can only use 32-bits of offset for rdstate --- blech! */
-+#define DIREOF (0xfffff)
-+#define RDOFFBITS 20          /* This is the number of bits in DIREOF. */
-+#define MAXRDCOOKIE (0xfff)
-+/* Turn an rdstate into an offset. */
-+static inline off_t rdstate2offset(struct unionfs_dir_state *buf)
-+{
-+      off_t tmp;
-+
-+      tmp = ((buf->cookie & MAXRDCOOKIE) << RDOFFBITS)
-+              | (buf->offset & DIREOF);
-+      return tmp;
-+}
-+
-+#define unionfs_read_lock(sb)  down_read(&UNIONFS_SB(sb)->rwsem)
-+#define unionfs_read_unlock(sb)        up_read(&UNIONFS_SB(sb)->rwsem)
-+#define unionfs_write_lock(sb)         down_write(&UNIONFS_SB(sb)->rwsem)
-+#define unionfs_write_unlock(sb) up_write(&UNIONFS_SB(sb)->rwsem)
-+
-+static inline void unionfs_double_lock_dentry(struct dentry *d1,
-+                                            struct dentry *d2)
-+{
-+      if (d2 < d1) {
-+              struct dentry *tmp = d1;
-+              d1 = d2;
-+              d2 = tmp;
+       req_cnt = qla24xx_calc_iocbs(tot_dsds);
+       if (ha->req_q_cnt < (req_cnt + 2)) {
+@@ -758,7 +821,7 @@
+       memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
+       host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb));
+-      cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
++      cmd_pkt->byte_count = cpu_to_le32((uint32_t)cmd->request_bufflen);
+       /* Build IOCB segments */
+       qla24xx_build_scsi_iocbs(sp, cmd_pkt, tot_dsds);
+@@ -790,9 +853,14 @@
+       return QLA_SUCCESS;
+ queuing_error:
+-      if (tot_dsds)
+-              scsi_dma_unmap(cmd);
+-
++      if (cmd->use_sg && tot_dsds) {
++              sg = (struct scatterlist *) cmd->request_buffer;
++              pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
++                  cmd->sc_data_direction);
++      } else if (tot_dsds) {
++              pci_unmap_single(ha->pdev, sp->dma_handle,
++                  cmd->request_bufflen, cmd->sc_data_direction);
 +      }
-+      unionfs_lock_dentry(d1);
-+      unionfs_lock_dentry(d2);
-+}
-+
-+extern int realloc_dentry_private_data(struct dentry *dentry);
-+extern int new_dentry_private_data(struct dentry *dentry);
-+extern void free_dentry_private_data(struct dentry *dentry);
-+extern void update_bstart(struct dentry *dentry);
-+
-+/*
-+ * EXTERNALS:
-+ */
-+
-+/* replicates the directory structure up to given dentry in given branch */
-+extern struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
-+                                   int bindex);
-+extern int make_dir_opaque(struct dentry *dir, int bindex);
-+
-+/* partial lookup */
-+extern int unionfs_partial_lookup(struct dentry *dentry);
-+
-+/*
-+ * Pass an unionfs dentry and an index and it will try to create a whiteout
-+ * in branch 'index'.
-+ *
-+ * On error, it will proceed to a branch to the left
-+ */
-+extern int create_whiteout(struct dentry *dentry, int start);
-+/* copies a file from dbstart to newbindex branch */
-+extern int copyup_file(struct inode *dir, struct file *file, int bstart,
-+                     int newbindex, loff_t size);
-+extern int copyup_named_file(struct inode *dir, struct file *file,
-+                           char *name, int bstart, int new_bindex,
-+                           loff_t len);
-+/* copies a dentry from dbstart to newbindex branch */
-+extern int copyup_dentry(struct inode *dir, struct dentry *dentry, int bstart,
-+                       int new_bindex, struct file **copyup_file,
-+                       loff_t len);
-+
-+extern int remove_whiteouts(struct dentry *dentry,
-+                          struct dentry *hidden_dentry, int bindex);
-+
-+extern int do_delete_whiteouts(struct dentry *dentry, int bindex,
-+                             struct unionfs_dir_state *namelist);
-+
-+extern int unionfs_get_nlinks(struct inode *inode);
-+
-+/* Is this directory empty: 0 if it is empty, -ENOTEMPTY if not. */
-+extern int check_empty(struct dentry *dentry,
-+                     struct unionfs_dir_state **namelist);
-+/* Delete whiteouts from this directory in branch bindex. */
-+extern int delete_whiteouts(struct dentry *dentry, int bindex,
-+                          struct unionfs_dir_state *namelist);
-+
-+/* Re-lookup a hidden dentry. */
-+extern int unionfs_refresh_hidden_dentry(struct dentry *dentry, int bindex);
-+
-+extern void unionfs_reinterpose(struct dentry *this_dentry);
-+extern struct super_block *unionfs_duplicate_super(struct super_block *sb);
-+
-+/* Locking functions. */
-+extern int unionfs_setlk(struct file *file, int cmd, struct file_lock *fl);
-+extern int unionfs_getlk(struct file *file, struct file_lock *fl);
-+
-+/* Common file operations. */
-+extern int unionfs_file_revalidate(struct file *file, int willwrite);
-+extern int unionfs_open(struct inode *inode, struct file *file);
-+extern int unionfs_file_release(struct inode *inode, struct file *file);
-+extern int unionfs_flush(struct file *file, fl_owner_t id);
-+extern long unionfs_ioctl(struct file *file, unsigned int cmd,
-+                        unsigned long arg);
-+
-+/* Inode operations */
-+extern int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+                        struct inode *new_dir, struct dentry *new_dentry);
-+extern int unionfs_unlink(struct inode *dir, struct dentry *dentry);
-+extern int unionfs_rmdir(struct inode *dir, struct dentry *dentry);
-+
-+extern int __unionfs_d_revalidate_chain(struct dentry *dentry,
-+                                      struct nameidata *nd);
-+
-+/* The values for unionfs_interpose's flag. */
-+#define INTERPOSE_DEFAULT     0
-+#define INTERPOSE_LOOKUP      1
-+#define INTERPOSE_REVAL               2
-+#define INTERPOSE_REVAL_NEG   3
-+#define INTERPOSE_PARTIAL     4
-+
-+extern int unionfs_interpose(struct dentry *this_dentry,
-+                           struct super_block *sb, int flag);
-+
-+#ifdef CONFIG_UNION_FS_XATTR
-+/* Extended attribute functions. */
-+extern void *unionfs_xattr_alloc(size_t size, size_t limit);
-+extern void unionfs_xattr_free(void *ptr, size_t size);
-+
-+extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name,
-+                              void *value, size_t size);
-+extern int unionfs_removexattr(struct dentry *dentry, const char *name);
-+extern ssize_t unionfs_listxattr(struct dentry *dentry, char *list,
-+                               size_t size);
-+extern int unionfs_setxattr(struct dentry *dentry, const char *name,
-+                          const void *value, size_t size, int flags);
-+#endif /* CONFIG_UNION_FS_XATTR */
-+
-+/* The root directory is unhashed, but isn't deleted. */
-+static inline int d_deleted(struct dentry *d)
-+{
-+      return d_unhashed(d) && (d != d->d_sb->s_root);
-+}
-+
-+struct dentry *unionfs_lookup_backend(struct dentry *dentry,
-+                                    struct nameidata *nd, int lookupmode);
-+
-+/* unionfs_permission, check if we should bypass error to facilitate copyup */
-+#define IS_COPYUP_ERR(err) ((err) == -EROFS)
-+
-+/* unionfs_open, check if we need to copyup the file */
-+#define OPEN_WRITE_FLAGS (O_WRONLY | O_RDWR | O_APPEND)
-+#define IS_WRITE_FLAG(flag) ((flag) & OPEN_WRITE_FLAGS)
-+
-+static inline int branchperms(const struct super_block *sb, int index)
-+{
-+      BUG_ON(index < 0);
-+
-+      return UNIONFS_SB(sb)->data[index].branchperms;
-+}
-+
-+static inline int set_branchperms(struct super_block *sb, int index, int perms)
-+{
-+      BUG_ON(index < 0);
-+
-+      UNIONFS_SB(sb)->data[index].branchperms = perms;
-+
-+      return perms;
-+}
-+
-+/* Is this file on a read-only branch? */
-+static inline int is_robranch_super(const struct super_block *sb, int index)
-+{
-+      int ret;
-+
-+      ret = (!(branchperms(sb, index) & MAY_WRITE)) ? -EROFS : 0;
-+      return ret;
-+}
-+
-+/* Is this file on a read-only branch? */
-+static inline int is_robranch_idx(const struct dentry *dentry, int index)
-+{
-+      int err = 0;
-+
-+      BUG_ON(index < 0);
-+
-+      if ((!(branchperms(dentry->d_sb, index) & MAY_WRITE)) ||
-+          IS_RDONLY(unionfs_lower_dentry_idx(dentry, index)->d_inode))
-+              err = -EROFS;
-+      return err;
-+}
-+
-+static inline int is_robranch(const struct dentry *dentry)
-+{
-+      int index;
-+
-+      index = UNIONFS_D(dentry)->bstart;
-+      BUG_ON(index < 0);
-+
-+      return is_robranch_idx(dentry, index);
-+}
-+
-+/* What do we use for whiteouts. */
-+#define UNIONFS_WHPFX ".wh."
-+#define UNIONFS_WHLEN 4
-+/*
-+ * If a directory contains this file, then it is opaque.  We start with the
-+ * .wh. flag so that it is blocked by lookup.
-+ */
-+#define UNIONFS_DIR_OPAQUE_NAME "__dir_opaque"
-+#define UNIONFS_DIR_OPAQUE UNIONFS_WHPFX UNIONFS_DIR_OPAQUE_NAME
-+
-+#ifndef DEFAULT_POLLMASK
-+#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
-+#endif
-+
-+/*
-+ * EXTERNALS:
-+ */
-+extern char *alloc_whname(const char *name, int len);
-+extern int check_branch(struct nameidata *nd);
-+extern int __parse_branch_mode(const char *name);
-+extern int parse_branch_mode(const char *name);
-+
-+/*
-+ * These two functions are here because it is kind of daft to copy and paste
-+ * the contents of the two functions to 32+ places in unionfs
-+ */
-+static inline struct dentry *lock_parent(struct dentry *dentry)
-+{
-+      struct dentry *dir = dget(dentry->d_parent);
-+
-+      mutex_lock(&dir->d_inode->i_mutex);
-+      return dir;
-+}
-+
-+static inline void unlock_dir(struct dentry *dir)
-+{
-+      mutex_unlock(&dir->d_inode->i_mutex);
-+      dput(dir);
-+}
-+
-+static inline struct vfsmount *unionfs_mntget(struct dentry *dentry,
-+                                            int bindex)
-+{
-+      BUG_ON(!dentry || bindex < 0);
-+
-+      return mntget(unionfs_lower_mnt_idx(dentry, bindex));
-+}
-+
-+static inline void unionfs_mntput(struct dentry *dentry, int bindex)
-+{
-+      if (!dentry)
-+              return;
-+
-+      BUG_ON(bindex < 0);
-+
-+      mntput(unionfs_lower_mnt_idx(dentry, bindex));
-+}
-+#endif        /* not _UNION_H_ */
-diff -Nurb linux-2.6.22-570/fs/unionfs/unlink.c linux-2.6.22-590/fs/unionfs/unlink.c
---- linux-2.6.22-570/fs/unionfs/unlink.c       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/unlink.c       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,176 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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.
-+ */
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       return QLA_FUNCTION_FAILED;
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla2xxx/qla_isr.c linux-2.6.22-570/drivers/scsi/qla2xxx/qla_isr.c
+--- linux-2.6.22-590/drivers/scsi/qla2xxx/qla_isr.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla2xxx/qla_isr.c    2007-07-08 19:32:17.000000000 -0400
+@@ -889,11 +889,11 @@
+               }
+               if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) {
+                       resid = resid_len;
+-                      scsi_set_resid(cp, resid);
++                      cp->resid = resid;
+                       CMD_RESID_LEN(cp) = resid;
+                       if (!lscsi_status &&
+-                          ((unsigned)(scsi_bufflen(cp) - resid) <
++                          ((unsigned)(cp->request_bufflen - resid) <
+                            cp->underflow)) {
+                               qla_printk(KERN_INFO, ha,
+                                   "scsi(%ld:%d:%d:%d): Mid-layer underflow "
+@@ -901,7 +901,7 @@
+                                   "error status.\n", ha->host_no,
+                                   cp->device->channel, cp->device->id,
+                                   cp->device->lun, resid,
+-                                         scsi_bufflen(cp));
++                                  cp->request_bufflen);
+                               cp->result = DID_ERROR << 16;
+                               break;
+@@ -963,7 +963,7 @@
+                       resid = fw_resid_len;
+               if (scsi_status & SS_RESIDUAL_UNDER) {
+-                      scsi_set_resid(cp, resid);
++                      cp->resid = resid;
+                       CMD_RESID_LEN(cp) = resid;
+               } else {
+                       DEBUG2(printk(KERN_INFO
+@@ -1046,14 +1046,14 @@
+                                   "retrying command.\n", ha->host_no,
+                                   cp->device->channel, cp->device->id,
+                                   cp->device->lun, resid,
+-                                            scsi_bufflen(cp)));
++                                  cp->request_bufflen));
+                               cp->result = DID_BUS_BUSY << 16;
+                               break;
+                       }
+                       /* Handle mid-layer underflow */
+-                      if ((unsigned)(scsi_bufflen(cp) - resid) <
++                      if ((unsigned)(cp->request_bufflen - resid) <
+                           cp->underflow) {
+                               qla_printk(KERN_INFO, ha,
+                                   "scsi(%ld:%d:%d:%d): Mid-layer underflow "
+@@ -1061,7 +1061,7 @@
+                                   "error status.\n", ha->host_no,
+                                   cp->device->channel, cp->device->id,
+                                   cp->device->lun, resid,
+-                                         scsi_bufflen(cp));
++                                  cp->request_bufflen);
+                               cp->result = DID_ERROR << 16;
+                               break;
+@@ -1084,7 +1084,7 @@
+               DEBUG2(printk(KERN_INFO
+                   "PID=0x%lx req=0x%x xtra=0x%x -- returning DID_ERROR "
+                   "status!\n",
+-                  cp->serial_number, scsi_bufflen(cp), resid_len));
++                  cp->serial_number, cp->request_bufflen, resid_len));
+               cp->result = DID_ERROR << 16;
+               break;
+@@ -1633,7 +1633,7 @@
+       uint16_t entry;
+       uint16_t index;
+       const char *name;
+-      irq_handler_t handler;
++      irqreturn_t (*handler)(int, void *);
+ };
+ static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = {
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla2xxx/qla_os.c linux-2.6.22-570/drivers/scsi/qla2xxx/qla_os.c
+--- linux-2.6.22-590/drivers/scsi/qla2xxx/qla_os.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla2xxx/qla_os.c     2007-07-08 19:32:17.000000000 -0400
+@@ -2426,7 +2426,13 @@
+       struct scsi_cmnd *cmd = sp->cmd;
+       if (sp->flags & SRB_DMA_VALID) {
+-              scsi_dma_unmap(cmd);
++              if (cmd->use_sg) {
++                      dma_unmap_sg(&ha->pdev->dev, cmd->request_buffer,
++                          cmd->use_sg, cmd->sc_data_direction);
++              } else if (cmd->request_bufflen) {
++                      dma_unmap_single(&ha->pdev->dev, sp->dma_handle,
++                          cmd->request_bufflen, cmd->sc_data_direction);
++              }
+               sp->flags &= ~SRB_DMA_VALID;
+       }
+       CMD_SP(cmd) = NULL;
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_dbg.c linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_dbg.c
+--- linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_dbg.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_dbg.c    2007-07-08 19:32:17.000000000 -0400
+@@ -6,9 +6,176 @@
+  */
+ #include "ql4_def.h"
+-#include "ql4_glbl.h"
+-#include "ql4_dbg.h"
+-#include "ql4_inline.h"
++#include <scsi/scsi_dbg.h>
 +
-+#include "union.h"
++#if 0
 +
-+/* unlink a file by creating a whiteout */
-+static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry)
++static void qla4xxx_print_srb_info(struct srb * srb)
++{
++      printk("%s: srb = 0x%p, flags=0x%02x\n", __func__, srb, srb->flags);
++      printk("%s: cmd = 0x%p, saved_dma_handle = 0x%lx\n",
++             __func__, srb->cmd, (unsigned long) srb->dma_handle);
++      printk("%s: fw_ddb_index = %d, lun = %d\n",
++             __func__, srb->fw_ddb_index, srb->cmd->device->lun);
++      printk("%s: iocb_tov = %d\n",
++             __func__, srb->iocb_tov);
++      printk("%s: cc_stat = 0x%x, r_start = 0x%lx, u_start = 0x%lx\n\n",
++             __func__, srb->cc_stat, srb->r_start, srb->u_start);
++}
++
++void qla4xxx_print_scsi_cmd(struct scsi_cmnd *cmd)
++{
++      printk("SCSI Command = 0x%p, Handle=0x%p\n", cmd, cmd->host_scribble);
++      printk("  b=%d, t=%02xh, l=%02xh, cmd_len = %02xh\n",
++             cmd->device->channel, cmd->device->id, cmd->device->lun,
++             cmd->cmd_len);
++      scsi_print_command(cmd);
++      printk("  seg_cnt = %d\n", cmd->use_sg);
++      printk("  request buffer = 0x%p, request buffer len = 0x%x\n",
++             cmd->request_buffer, cmd->request_bufflen);
++      if (cmd->use_sg) {
++              struct scatterlist *sg;
++              sg = (struct scatterlist *)cmd->request_buffer;
++              printk("  SG buffer: \n");
++              qla4xxx_dump_buffer((caddr_t) sg,
++                                  (cmd->use_sg * sizeof(*sg)));
++      }
++      printk("  tag = %d, transfersize = 0x%x \n", cmd->tag,
++             cmd->transfersize);
++      printk("  Pid = %d, SP = 0x%p\n", (int)cmd->pid, cmd->SCp.ptr);
++      printk("  underflow size = 0x%x, direction=0x%x\n", cmd->underflow,
++             cmd->sc_data_direction);
++      printk("  Current time (jiffies) = 0x%lx, "
++             "timeout expires = 0x%lx\n", jiffies, cmd->eh_timeout.expires);
++      qla4xxx_print_srb_info((struct srb *) cmd->SCp.ptr);
++}
++
++void __dump_registers(struct scsi_qla_host *ha)
++{
++      uint8_t i;
++      for (i = 0; i < MBOX_REG_COUNT; i++) {
++              printk(KERN_INFO "0x%02X mailbox[%d]      = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg, mailbox[i]), i,
++                     readw(&ha->reg->mailbox[i]));
++      }
++      printk(KERN_INFO "0x%02X flash_address   = 0x%08X\n",
++             (uint8_t) offsetof(struct isp_reg, flash_address),
++             readw(&ha->reg->flash_address));
++      printk(KERN_INFO "0x%02X flash_data      = 0x%08X\n",
++             (uint8_t) offsetof(struct isp_reg, flash_data),
++             readw(&ha->reg->flash_data));
++      printk(KERN_INFO "0x%02X ctrl_status     = 0x%08X\n",
++             (uint8_t) offsetof(struct isp_reg, ctrl_status),
++             readw(&ha->reg->ctrl_status));
++      if (is_qla4010(ha)) {
++              printk(KERN_INFO "0x%02X nvram           = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg, u1.isp4010.nvram),
++                     readw(&ha->reg->u1.isp4010.nvram));
++      }
++
++      else if (is_qla4022(ha) | is_qla4032(ha)) {
++              printk(KERN_INFO "0x%02X intr_mask       = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u1.isp4022.intr_mask),
++                     readw(&ha->reg->u1.isp4022.intr_mask));
++              printk(KERN_INFO "0x%02X nvram           = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg, u1.isp4022.nvram),
++                     readw(&ha->reg->u1.isp4022.nvram));
++              printk(KERN_INFO "0x%02X semaphore       = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u1.isp4022.semaphore),
++                     readw(&ha->reg->u1.isp4022.semaphore));
++      }
++      printk(KERN_INFO "0x%02X req_q_in        = 0x%08X\n",
++             (uint8_t) offsetof(struct isp_reg, req_q_in),
++             readw(&ha->reg->req_q_in));
++      printk(KERN_INFO "0x%02X rsp_q_out       = 0x%08X\n",
++             (uint8_t) offsetof(struct isp_reg, rsp_q_out),
++             readw(&ha->reg->rsp_q_out));
++      if (is_qla4010(ha)) {
++              printk(KERN_INFO "0x%02X ext_hw_conf     = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u2.isp4010.ext_hw_conf),
++                     readw(&ha->reg->u2.isp4010.ext_hw_conf));
++              printk(KERN_INFO "0x%02X port_ctrl       = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u2.isp4010.port_ctrl),
++                     readw(&ha->reg->u2.isp4010.port_ctrl));
++              printk(KERN_INFO "0x%02X port_status     = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u2.isp4010.port_status),
++                     readw(&ha->reg->u2.isp4010.port_status));
++              printk(KERN_INFO "0x%02X req_q_out       = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u2.isp4010.req_q_out),
++                     readw(&ha->reg->u2.isp4010.req_q_out));
++              printk(KERN_INFO "0x%02X gp_out          = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_out),
++                     readw(&ha->reg->u2.isp4010.gp_out));
++              printk(KERN_INFO "0x%02X gp_in           = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_in),
++                     readw(&ha->reg->u2.isp4010.gp_in));
++              printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u2.isp4010.port_err_status),
++                     readw(&ha->reg->u2.isp4010.port_err_status));
++      }
++
++      else if (is_qla4022(ha) | is_qla4032(ha)) {
++              printk(KERN_INFO "Page 0 Registers:\n");
++              printk(KERN_INFO "0x%02X ext_hw_conf     = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u2.isp4022.p0.ext_hw_conf),
++                     readw(&ha->reg->u2.isp4022.p0.ext_hw_conf));
++              printk(KERN_INFO "0x%02X port_ctrl       = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u2.isp4022.p0.port_ctrl),
++                     readw(&ha->reg->u2.isp4022.p0.port_ctrl));
++              printk(KERN_INFO "0x%02X port_status     = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u2.isp4022.p0.port_status),
++                     readw(&ha->reg->u2.isp4022.p0.port_status));
++              printk(KERN_INFO "0x%02X gp_out          = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u2.isp4022.p0.gp_out),
++                     readw(&ha->reg->u2.isp4022.p0.gp_out));
++              printk(KERN_INFO "0x%02X gp_in           = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg, u2.isp4022.p0.gp_in),
++                     readw(&ha->reg->u2.isp4022.p0.gp_in));
++              printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u2.isp4022.p0.port_err_status),
++                     readw(&ha->reg->u2.isp4022.p0.port_err_status));
++              printk(KERN_INFO "Page 1 Registers:\n");
++              writel(HOST_MEM_CFG_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT),
++                     &ha->reg->ctrl_status);
++              printk(KERN_INFO "0x%02X req_q_out       = 0x%08X\n",
++                     (uint8_t) offsetof(struct isp_reg,
++                                        u2.isp4022.p1.req_q_out),
++                     readw(&ha->reg->u2.isp4022.p1.req_q_out));
++              writel(PORT_CTRL_STAT_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT),
++                     &ha->reg->ctrl_status);
++      }
++}
++
++void qla4xxx_dump_mbox_registers(struct scsi_qla_host *ha)
 +{
-+      struct dentry *hidden_dentry;
-+      struct dentry *hidden_dir_dentry;
-+      int bindex;
-+      int err = 0;
-+
-+      if ((err = unionfs_partial_lookup(dentry)))
-+              goto out;
-+
-+      bindex = dbstart(dentry);
-+
-+      hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-+      if (!hidden_dentry)
-+              goto out;
-+
-+      hidden_dir_dentry = lock_parent(hidden_dentry);
-+
-+      /* avoid destroying the hidden inode if the file is in use */
-+      dget(hidden_dentry);
-+      if (!(err = is_robranch_super(dentry->d_sb, bindex)))
-+              err = vfs_unlink(hidden_dir_dentry->d_inode, hidden_dentry);
-+      dput(hidden_dentry);
-+      fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
-+      unlock_dir(hidden_dir_dentry);
-+
-+      if (err && !IS_COPYUP_ERR(err))
-+              goto out;
-+
-+      if (err) {
-+              if (dbstart(dentry) == 0)
-+                      goto out;
-+
-+              err = create_whiteout(dentry, dbstart(dentry) - 1);
-+      } else if (dbopaque(dentry) != -1)
-+              /* There is a hidden lower-priority file with the same name. */
-+              err = create_whiteout(dentry, dbopaque(dentry));
-+      else
-+              err = create_whiteout(dentry, dbstart(dentry));
-+
-+out:
-+      if (!err)
-+              dentry->d_inode->i_nlink--;
-+
-+      /* We don't want to leave negative leftover dentries for revalidate. */
-+      if (!err && (dbopaque(dentry) != -1))
-+              update_bstart(dentry);
-+
-+      return err;
++      unsigned long flags = 0;
++      int i = 0;
++      spin_lock_irqsave(&ha->hardware_lock, flags);
++      for (i = 1; i < MBOX_REG_COUNT; i++)
++              printk(KERN_INFO "  Mailbox[%d] = %08x\n", i,
++                     readw(&ha->reg->mailbox[i]));
++      spin_unlock_irqrestore(&ha->hardware_lock, flags);
 +}
 +
-+int unionfs_unlink(struct inode *dir, struct dentry *dentry)
++void qla4xxx_dump_registers(struct scsi_qla_host *ha)
 +{
-+      int err = 0;
-+
-+      unionfs_read_lock(dentry->d_sb);
-+      unionfs_lock_dentry(dentry);
-+
-+      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
-+
-+      err = unionfs_unlink_whiteout(dir, dentry);
-+      /* call d_drop so the system "forgets" about us */
-+      if (!err)
-+              d_drop(dentry);
-+
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
++      unsigned long flags = 0;
++      spin_lock_irqsave(&ha->hardware_lock, flags);
++      __dump_registers(ha);
++      spin_unlock_irqrestore(&ha->hardware_lock, flags);
 +}
+ void qla4xxx_dump_buffer(void *b, uint32_t size)
+ {
+@@ -31,3 +198,4 @@
+               printk(KERN_DEBUG "\n");
+ }
++#endif  /*  0  */
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_def.h linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_def.h
+--- linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_def.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_def.h    2007-07-08 19:32:17.000000000 -0400
+@@ -122,7 +122,8 @@
+ #define ISCSI_IPADDR_SIZE             4       /* IP address size */
+ #define ISCSI_ALIAS_SIZE              32      /* ISCSI Alais name size */
+-#define ISCSI_NAME_SIZE                       0xE0    /* ISCSI Name size */
++#define ISCSI_NAME_SIZE                       255     /* ISCSI Name size -
++                                               * usually a string */
+ #define LSDW(x) ((u32)((u64)(x)))
+ #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
+@@ -186,19 +187,7 @@
+       u_long u_start;         /* Time when we handed the cmd to F/W */
+ };
+-/*
+- * Asynchronous Event Queue structure
+- */
+-struct aen {
+-        uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
+-};
+-
+-struct ql4_aen_log {
+-        int count;
+-        struct aen entry[MAX_AEN_ENTRIES];
+-};
+-
+-/*
++      /*
+        * Device Database (DDB) structure
+        */
+ struct ddb_entry {
+@@ -265,6 +254,13 @@
+ #define DF_ISNS_DISCOVERED    2       /* Device was discovered via iSNS */
+ #define DF_FO_MASKED          3
++/*
++ * Asynchronous Event Queue structure
++ */
++struct aen {
++      uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
++};
 +
-+static int unionfs_rmdir_first(struct inode *dir, struct dentry *dentry,
-+                             struct unionfs_dir_state *namelist)
-+{
-+      int err;
-+      struct dentry *hidden_dentry;
-+      struct dentry *hidden_dir_dentry = NULL;
-+
-+      /* Here we need to remove whiteout entries. */
-+      err = delete_whiteouts(dentry, dbstart(dentry), namelist);
-+      if (err)
-+              goto out;
-+
-+      hidden_dentry = unionfs_lower_dentry(dentry);
-+
-+      hidden_dir_dentry = lock_parent(hidden_dentry);
-+
-+      /* avoid destroying the hidden inode if the file is in use */
-+      dget(hidden_dentry);
-+      if (!(err = is_robranch(dentry)))
-+              err = vfs_rmdir(hidden_dir_dentry->d_inode, hidden_dentry);
-+      dput(hidden_dentry);
+ #include "ql4_fw.h"
+ #include "ql4_nvram.h"
+@@ -274,17 +270,20 @@
+  */
+ struct scsi_qla_host {
+       /* Linux adapter configuration data */
++      struct Scsi_Host *host; /* pointer to host data */
++      uint32_t tot_ddbs;
+       unsigned long flags;
+ #define AF_ONLINE                   0 /* 0x00000001 */
+ #define AF_INIT_DONE                1 /* 0x00000002 */
+ #define AF_MBOX_COMMAND                     2 /* 0x00000004 */
+ #define AF_MBOX_COMMAND_DONE        3 /* 0x00000008 */
+-#define AF_INTERRUPTS_ON              6 /* 0x00000040 */
++#define AF_INTERRUPTS_ON            6 /* 0x00000040 Not Used */
+ #define AF_GET_CRASH_RECORD         7 /* 0x00000080 */
+ #define AF_LINK_UP                  8 /* 0x00000100 */
+ #define AF_IRQ_ATTACHED                    10 /* 0x00000400 */
+-#define AF_DISABLE_ACB_COMPLETE               11 /* 0x00000800 */
++#define AF_ISNS_CMD_IN_PROCESS             12 /* 0x00001000 */
++#define AF_ISNS_CMD_DONE           13 /* 0x00002000 */
+       unsigned long dpc_flags;
+@@ -297,9 +296,6 @@
+ #define DPC_AEN                             9 /* 0x00000200 */
+ #define DPC_GET_DHCP_IP_ADDR       15 /* 0x00008000 */
+-      struct Scsi_Host *host; /* pointer to host data */
+-      uint32_t tot_ddbs;
+-
+       uint16_t        iocb_cnt;
+       uint16_t        iocb_hiwat;
+@@ -348,7 +344,6 @@
+       uint32_t firmware_version[2];
+       uint32_t patch_number;
+       uint32_t build_number;
+-      uint32_t board_id;
+       /* --- From Init_FW --- */
+       /* init_cb_t *init_cb; */
+@@ -368,6 +363,7 @@
+       /* --- From GetFwState --- */
+       uint32_t firmware_state;
++      uint32_t board_id;
+       uint32_t addl_fw_state;
+       /* Linux kernel thread */
+@@ -418,8 +414,6 @@
+       uint16_t aen_out;
+       struct aen aen_q[MAX_AEN_ENTRIES];
+-      struct ql4_aen_log aen_log;/* tracks all aens */
+-
+       /* This mutex protects several threads to do mailbox commands
+        * concurrently.
+        */
+@@ -591,4 +585,10 @@
+ #define FLUSH_DDB_CHANGED_AENS         1
+ #define RELOGIN_DDB_CHANGED_AENS 2
++#include "ql4_version.h"
++#include "ql4_glbl.h"
++#include "ql4_dbg.h"
++#include "ql4_inline.h"
 +
-+      fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
-+      /* propagate number of hard-links */
-+      dentry->d_inode->i_nlink = unionfs_get_nlinks(dentry->d_inode);
 +
-+out:
-+      if (hidden_dir_dentry)
-+              unlock_dir(hidden_dir_dentry);
-+      return err;
-+}
+ #endif        /*_QLA4XXX_H */
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_fw.h linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_fw.h
+--- linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_fw.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_fw.h     2007-07-08 19:32:17.000000000 -0400
+@@ -20,23 +20,143 @@
+  *************************************************************************/
+ struct port_ctrl_stat_regs {
+-      __le32 ext_hw_conf;     /* 0x50  R/W */
+-      __le32 rsrvd0;          /* 0x54 */
+-      __le32 port_ctrl;       /* 0x58 */
+-      __le32 port_status;     /* 0x5c */
+-      __le32 rsrvd1[32];      /* 0x60-0xdf */
+-      __le32 gp_out;          /* 0xe0 */
+-      __le32 gp_in;           /* 0xe4 */
+-      __le32 rsrvd2[5];       /* 0xe8-0xfb */
+-      __le32 port_err_status; /* 0xfc */
++      __le32 ext_hw_conf;     /*  80 x50  R/W */
++      __le32 intChipConfiguration; /*  84 x54 */
++      __le32 port_ctrl;       /*  88 x58 */
++      __le32 port_status;     /*  92 x5c */
++      __le32 HostPrimMACHi;   /*  96 x60 */
++      __le32 HostPrimMACLow;  /* 100 x64 */
++      __le32 HostSecMACHi;    /* 104 x68 */
++      __le32 HostSecMACLow;   /* 108 x6c */
++      __le32 EPPrimMACHi;     /* 112 x70 */
++      __le32 EPPrimMACLow;    /* 116 x74 */
++      __le32 EPSecMACHi;      /* 120 x78 */
++      __le32 EPSecMACLow;     /* 124 x7c */
++      __le32 HostPrimIPHi;    /* 128 x80 */
++      __le32 HostPrimIPMidHi; /* 132 x84 */
++      __le32 HostPrimIPMidLow;        /* 136 x88 */
++      __le32 HostPrimIPLow;   /* 140 x8c */
++      __le32 HostSecIPHi;     /* 144 x90 */
++      __le32 HostSecIPMidHi;  /* 148 x94 */
++      __le32 HostSecIPMidLow; /* 152 x98 */
++      __le32 HostSecIPLow;    /* 156 x9c */
++      __le32 EPPrimIPHi;      /* 160 xa0 */
++      __le32 EPPrimIPMidHi;   /* 164 xa4 */
++      __le32 EPPrimIPMidLow;  /* 168 xa8 */
++      __le32 EPPrimIPLow;     /* 172 xac */
++      __le32 EPSecIPHi;       /* 176 xb0 */
++      __le32 EPSecIPMidHi;    /* 180 xb4 */
++      __le32 EPSecIPMidLow;   /* 184 xb8 */
++      __le32 EPSecIPLow;      /* 188 xbc */
++      __le32 IPReassemblyTimeout; /* 192 xc0 */
++      __le32 EthMaxFramePayload; /* 196 xc4 */
++      __le32 TCPMaxWindowSize; /* 200 xc8 */
++      __le32 TCPCurrentTimestampHi; /* 204 xcc */
++      __le32 TCPCurrentTimestampLow; /* 208 xd0 */
++      __le32 LocalRAMAddress; /* 212 xd4 */
++      __le32 LocalRAMData;    /* 216 xd8 */
++      __le32 PCSReserved1;    /* 220 xdc */
++      __le32 gp_out;          /* 224 xe0 */
++      __le32 gp_in;           /* 228 xe4 */
++      __le32 ProbeMuxAddr;    /* 232 xe8 */
++      __le32 ProbeMuxData;    /* 236 xec */
++      __le32 ERMQueueBaseAddr0; /* 240 xf0 */
++      __le32 ERMQueueBaseAddr1; /* 244 xf4 */
++      __le32 MACConfiguration; /* 248 xf8 */
++      __le32 port_err_status; /* 252 xfc  COR */
+ };
+ struct host_mem_cfg_regs {
+-      __le32 rsrvd0[12];      /* 0x50-0x79 */
+-      __le32 req_q_out;       /* 0x80 */
+-      __le32 rsrvd1[31];      /* 0x84-0xFF */
++      __le32 NetRequestQueueOut; /*  80 x50 */
++      __le32 NetRequestQueueOutAddrHi; /*  84 x54 */
++      __le32 NetRequestQueueOutAddrLow; /*  88 x58 */
++      __le32 NetRequestQueueBaseAddrHi; /*  92 x5c */
++      __le32 NetRequestQueueBaseAddrLow; /*  96 x60 */
++      __le32 NetRequestQueueLength; /* 100 x64 */
++      __le32 NetResponseQueueIn; /* 104 x68 */
++      __le32 NetResponseQueueInAddrHi; /* 108 x6c */
++      __le32 NetResponseQueueInAddrLow; /* 112 x70 */
++      __le32 NetResponseQueueBaseAddrHi; /* 116 x74 */
++      __le32 NetResponseQueueBaseAddrLow; /* 120 x78 */
++      __le32 NetResponseQueueLength; /* 124 x7c */
++      __le32 req_q_out;       /* 128 x80 */
++      __le32 RequestQueueOutAddrHi; /* 132 x84 */
++      __le32 RequestQueueOutAddrLow; /* 136 x88 */
++      __le32 RequestQueueBaseAddrHi; /* 140 x8c */
++      __le32 RequestQueueBaseAddrLow; /* 144 x90 */
++      __le32 RequestQueueLength; /* 148 x94 */
++      __le32 ResponseQueueIn; /* 152 x98 */
++      __le32 ResponseQueueInAddrHi; /* 156 x9c */
++      __le32 ResponseQueueInAddrLow; /* 160 xa0 */
++      __le32 ResponseQueueBaseAddrHi; /* 164 xa4 */
++      __le32 ResponseQueueBaseAddrLow; /* 168 xa8 */
++      __le32 ResponseQueueLength; /* 172 xac */
++      __le32 NetRxLargeBufferQueueOut; /* 176 xb0 */
++      __le32 NetRxLargeBufferQueueBaseAddrHi; /* 180 xb4 */
++      __le32 NetRxLargeBufferQueueBaseAddrLow; /* 184 xb8 */
++      __le32 NetRxLargeBufferQueueLength; /* 188 xbc */
++      __le32 NetRxLargeBufferLength; /* 192 xc0 */
++      __le32 NetRxSmallBufferQueueOut; /* 196 xc4 */
++      __le32 NetRxSmallBufferQueueBaseAddrHi; /* 200 xc8 */
++      __le32 NetRxSmallBufferQueueBaseAddrLow; /* 204 xcc */
++      __le32 NetRxSmallBufferQueueLength; /* 208 xd0 */
++      __le32 NetRxSmallBufferLength; /* 212 xd4 */
++      __le32 HMCReserved0[10]; /* 216 xd8 */
++};
 +
-+int unionfs_rmdir(struct inode *dir, struct dentry *dentry)
-+{
-+      int err = 0;
-+      struct unionfs_dir_state *namelist = NULL;
++struct local_ram_cfg_regs {
++      __le32 BufletSize;      /*  80 x50 */
++      __le32 BufletMaxCount;  /*  84 x54 */
++      __le32 BufletCurrCount; /*  88 x58 */
++      __le32 BufletPauseThresholdCount; /*  92 x5c */
++      __le32 BufletTCPWinThresholdHi; /*  96 x60 */
++      __le32 BufletTCPWinThresholdLow; /* 100 x64 */
++      __le32 IPHashTableBaseAddr; /* 104 x68 */
++      __le32 IPHashTableSize; /* 108 x6c */
++      __le32 TCPHashTableBaseAddr; /* 112 x70 */
++      __le32 TCPHashTableSize; /* 116 x74 */
++      __le32 NCBAreaBaseAddr; /* 120 x78 */
++      __le32 NCBMaxCount;     /* 124 x7c */
++      __le32 NCBCurrCount;    /* 128 x80 */
++      __le32 DRBAreaBaseAddr; /* 132 x84 */
++      __le32 DRBMaxCount;     /* 136 x88 */
++      __le32 DRBCurrCount;    /* 140 x8c */
++      __le32 LRCReserved[28]; /* 144 x90 */
++};
 +
-+      unionfs_read_lock(dentry->d_sb);
-+      unionfs_lock_dentry(dentry);
++struct prot_stat_regs {
++      __le32 MACTxFrameCount; /*  80 x50   R */
++      __le32 MACTxByteCount;  /*  84 x54   R */
++      __le32 MACRxFrameCount; /*  88 x58   R */
++      __le32 MACRxByteCount;  /*  92 x5c   R */
++      __le32 MACCRCErrCount;  /*  96 x60   R */
++      __le32 MACEncErrCount;  /* 100 x64   R */
++      __le32 MACRxLengthErrCount; /* 104 x68   R */
++      __le32 IPTxPacketCount; /* 108 x6c   R */
++      __le32 IPTxByteCount;   /* 112 x70   R */
++      __le32 IPTxFragmentCount; /* 116 x74   R */
++      __le32 IPRxPacketCount; /* 120 x78   R */
++      __le32 IPRxByteCount;   /* 124 x7c   R */
++      __le32 IPRxFragmentCount; /* 128 x80   R */
++      __le32 IPDatagramReassemblyCount; /* 132 x84   R */
++      __le32 IPV6RxPacketCount; /* 136 x88   R */
++      __le32 IPErrPacketCount; /* 140 x8c   R */
++      __le32 IPReassemblyErrCount; /* 144 x90   R */
++      __le32 TCPTxSegmentCount; /* 148 x94   R */
++      __le32 TCPTxByteCount;  /* 152 x98   R */
++      __le32 TCPRxSegmentCount; /* 156 x9c   R */
++      __le32 TCPRxByteCount;  /* 160 xa0   R */
++      __le32 TCPTimerExpCount; /* 164 xa4   R */
++      __le32 TCPRxAckCount;   /* 168 xa8   R */
++      __le32 TCPTxAckCount;   /* 172 xac   R */
++      __le32 TCPRxErrOOOCount; /* 176 xb0   R */
++      __le32 PSReserved0;     /* 180 xb4 */
++      __le32 TCPRxWindowProbeUpdateCount; /* 184 xb8   R */
++      __le32 ECCErrCorrectionCount; /* 188 xbc   R */
++      __le32 PSReserved1[16]; /* 192 xc0 */
+ };
 +
-+      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
+ /*  remote register set (access via PCI memory read/write) */
+ struct isp_reg {
+ #define MBOX_REG_COUNT 8
+@@ -87,7 +207,11 @@
+                       union {
+                               struct port_ctrl_stat_regs p0;
+                               struct host_mem_cfg_regs p1;
++                              struct local_ram_cfg_regs p2;
++                              struct prot_stat_regs p3;
++                              __le32 r_union[44];
+                       };
 +
-+      /* check if this unionfs directory is empty or not */
-+      err = check_empty(dentry, &namelist);
-+      if (err)
-+              goto out;
+               } __attribute__ ((packed)) isp4022;
+       } u2;
+ };                            /* 256 x100 */
+@@ -172,7 +296,6 @@
+ /*  ISP Semaphore definitions */
+ /*  ISP General Purpose Output definitions */
+-#define GPOR_TOPCAT_RESET                     0x00000004
+ /*  shadow registers (DMA'd from HA to system memory.  read only) */
+ struct shadow_regs {
+@@ -214,7 +337,6 @@
+ /*  Mailbox command definitions */
+ #define MBOX_CMD_ABOUT_FW                     0x0009
+-#define MBOX_CMD_PING                         0x000B
+ #define MBOX_CMD_LUN_RESET                    0x0016
+ #define MBOX_CMD_GET_MANAGEMENT_DATA          0x001E
+ #define MBOX_CMD_GET_FW_STATUS                        0x001F
+@@ -242,17 +364,6 @@
+ #define MBOX_CMD_GET_FW_STATE                 0x0069
+ #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A
+ #define MBOX_CMD_RESTORE_FACTORY_DEFAULTS     0x0087
+-#define MBOX_CMD_SET_ACB                      0x0088
+-#define MBOX_CMD_GET_ACB                      0x0089
+-#define MBOX_CMD_DISABLE_ACB                  0x008A
+-#define MBOX_CMD_GET_IPV6_NEIGHBOR_CACHE      0x008B
+-#define MBOX_CMD_GET_IPV6_DEST_CACHE          0x008C
+-#define MBOX_CMD_GET_IPV6_DEF_ROUTER_LIST     0x008D
+-#define MBOX_CMD_GET_IPV6_LCL_PREFIX_LIST     0x008E
+-#define MBOX_CMD_SET_IPV6_NEIGHBOR_CACHE      0x0090
+-#define MBOX_CMD_GET_IP_ADDR_STATE            0x0091
+-#define MBOX_CMD_SEND_IPV6_ROUTER_SOL         0x0092
+-#define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR 0x0093
+ /* Mailbox 1 */
+ #define FW_STATE_READY                                0x0000
+@@ -298,16 +409,6 @@
+ #define MBOX_ASTS_DHCP_LEASE_EXPIRED          0x801D
+ #define MBOX_ASTS_DHCP_LEASE_ACQUIRED         0x801F
+ #define MBOX_ASTS_ISNS_UNSOLICITED_PDU_RECEIVED 0x8021
+-#define MBOX_ASTS_DUPLICATE_IP                        0x8025
+-#define MBOX_ASTS_ARP_COMPLETE                        0x8026
+-#define MBOX_ASTS_SUBNET_STATE_CHANGE         0x8027
+-#define MBOX_ASTS_RESPONSE_QUEUE_FULL         0x8028
+-#define MBOX_ASTS_IP_ADDR_STATE_CHANGED               0x8029
+-#define MBOX_ASTS_IPV6_PREFIX_EXPIRED         0x802B
+-#define MBOX_ASTS_IPV6_ND_PREFIX_IGNORED      0x802C
+-#define MBOX_ASTS_IPV6_LCL_PREFIX_IGNORED     0x802D
+-#define MBOX_ASTS_ICMPV6_ERROR_MSG_RCVD               0x802E
+-
+ #define ISNS_EVENT_DATA_RECEIVED              0x0000
+ #define ISNS_EVENT_CONNECTION_OPENED          0x0001
+ #define ISNS_EVENT_CONNECTION_FAILED          0x0002
+@@ -317,166 +418,137 @@
+ /*************************************************************************/
+ /* Host Adapter Initialization Control Block (from host) */
+-struct addr_ctrl_blk {
+-      uint8_t version;        /* 00 */
+-      uint8_t control;        /* 01 */
++struct init_fw_ctrl_blk {
++      uint8_t Version;        /* 00 */
++      uint8_t Control;        /* 01 */
+-      uint16_t fw_options;    /* 02-03 */
++      uint16_t FwOptions;     /* 02-03 */
+ #define        FWOPT_HEARTBEAT_ENABLE           0x1000
+ #define        FWOPT_SESSION_MODE               0x0040
+ #define        FWOPT_INITIATOR_MODE             0x0020
+ #define        FWOPT_TARGET_MODE                0x0010
+-      uint16_t exec_throttle; /* 04-05 */
+-      uint8_t zio_count;      /* 06 */
+-      uint8_t res0;   /* 07 */
+-      uint16_t eth_mtu_size;  /* 08-09 */
+-      uint16_t add_fw_options;        /* 0A-0B */
+-
+-      uint8_t hb_interval;    /* 0C */
+-      uint8_t inst_num; /* 0D */
+-      uint16_t res1;          /* 0E-0F */
+-      uint16_t rqq_consumer_idx;      /* 10-11 */
+-      uint16_t compq_producer_idx;    /* 12-13 */
+-      uint16_t rqq_len;       /* 14-15 */
+-      uint16_t compq_len;     /* 16-17 */
+-      uint32_t rqq_addr_lo;   /* 18-1B */
+-      uint32_t rqq_addr_hi;   /* 1C-1F */
+-      uint32_t compq_addr_lo; /* 20-23 */
+-      uint32_t compq_addr_hi; /* 24-27 */
+-      uint32_t shdwreg_addr_lo;       /* 28-2B */
+-      uint32_t shdwreg_addr_hi;       /* 2C-2F */
+-
+-      uint16_t iscsi_opts;    /* 30-31 */
+-      uint16_t ipv4_tcp_opts; /* 32-33 */
+-      uint16_t ipv4_ip_opts;  /* 34-35 */
+-
+-      uint16_t iscsi_max_pdu_size;    /* 36-37 */
+-      uint8_t ipv4_tos;       /* 38 */
+-      uint8_t ipv4_ttl;       /* 39 */
+-      uint8_t acb_version;    /* 3A */
+-      uint8_t res2;   /* 3B */
+-      uint16_t def_timeout;   /* 3C-3D */
+-      uint16_t iscsi_fburst_len;      /* 3E-3F */
+-      uint16_t iscsi_def_time2wait;   /* 40-41 */
+-      uint16_t iscsi_def_time2retain; /* 42-43 */
+-      uint16_t iscsi_max_outstnd_r2t; /* 44-45 */
+-      uint16_t conn_ka_timeout;       /* 46-47 */
+-      uint16_t ipv4_port;     /* 48-49 */
+-      uint16_t iscsi_max_burst_len;   /* 4A-4B */
+-      uint32_t res5;          /* 4C-4F */
+-      uint8_t ipv4_addr[4];   /* 50-53 */
+-      uint16_t ipv4_vlan_tag; /* 54-55 */
+-      uint8_t ipv4_addr_state;        /* 56 */
+-      uint8_t ipv4_cacheid;   /* 57 */
+-      uint8_t res6[8];        /* 58-5F */
+-      uint8_t ipv4_subnet[4]; /* 60-63 */
+-      uint8_t res7[12];       /* 64-6F */
+-      uint8_t ipv4_gw_addr[4];        /* 70-73 */
+-      uint8_t res8[0xc];      /* 74-7F */
+-      uint8_t pri_dns_srvr_ip[4];/* 80-83 */
+-      uint8_t sec_dns_srvr_ip[4];/* 84-87 */
+-      uint16_t min_eph_port;  /* 88-89 */
+-      uint16_t max_eph_port;  /* 8A-8B */
+-      uint8_t res9[4];        /* 8C-8F */
+-      uint8_t iscsi_alias[32];/* 90-AF */
+-      uint8_t res9_1[0x16];   /* B0-C5 */
+-      uint16_t tgt_portal_grp;/* C6-C7 */
+-      uint8_t abort_timer;    /* C8    */
+-      uint8_t ipv4_tcp_wsf;   /* C9    */
+-      uint8_t res10[6];       /* CA-CF */
+-      uint8_t ipv4_sec_ip_addr[4];    /* D0-D3 */
+-      uint8_t ipv4_dhcp_vid_len;      /* D4 */
+-      uint8_t ipv4_dhcp_vid[11];      /* D5-DF */
+-      uint8_t res11[20];      /* E0-F3 */
+-      uint8_t ipv4_dhcp_alt_cid_len;  /* F4 */
+-      uint8_t ipv4_dhcp_alt_cid[11];  /* F5-FF */
+-      uint8_t iscsi_name[224];        /* 100-1DF */
+-      uint8_t res12[32];      /* 1E0-1FF */
+-      uint32_t cookie;        /* 200-203 */
+-      uint16_t ipv6_port;     /* 204-205 */
+-      uint16_t ipv6_opts;     /* 206-207 */
+-      uint16_t ipv6_addtl_opts;       /* 208-209 */
+-      uint16_t ipv6_tcp_opts; /* 20A-20B */
+-      uint8_t ipv6_tcp_wsf;   /* 20C */
+-      uint16_t ipv6_flow_lbl; /* 20D-20F */
+-      uint8_t ipv6_gw_addr[16];       /* 210-21F */
+-      uint16_t ipv6_vlan_tag; /* 220-221 */
+-      uint8_t ipv6_lnk_lcl_addr_state;/* 222 */
+-      uint8_t ipv6_addr0_state;       /* 223 */
+-      uint8_t ipv6_addr1_state;       /* 224 */
+-      uint8_t ipv6_gw_state;  /* 225 */
+-      uint8_t ipv6_traffic_class;     /* 226 */
+-      uint8_t ipv6_hop_limit; /* 227 */
+-      uint8_t ipv6_if_id[8];  /* 228-22F */
+-      uint8_t ipv6_addr0[16]; /* 230-23F */
+-      uint8_t ipv6_addr1[16]; /* 240-24F */
+-      uint32_t ipv6_nd_reach_time;    /* 250-253 */
+-      uint32_t ipv6_nd_rexmit_timer;  /* 254-257 */
+-      uint32_t ipv6_nd_stale_timeout; /* 258-25B */
+-      uint8_t ipv6_dup_addr_detect_count;     /* 25C */
+-      uint8_t ipv6_cache_id;  /* 25D */
+-      uint8_t res13[18];      /* 25E-26F */
+-      uint32_t ipv6_gw_advrt_mtu;     /* 270-273 */
+-      uint8_t res14[140];     /* 274-2FF */
+-};
+-
+-struct init_fw_ctrl_blk {
+-      struct addr_ctrl_blk pri;
+-      struct addr_ctrl_blk sec;
++      uint16_t ExecThrottle;  /* 04-05 */
++      uint8_t RetryCount;     /* 06 */
++      uint8_t RetryDelay;     /* 07 */
++      uint16_t MaxEthFrPayloadSize;   /* 08-09 */
++      uint16_t AddFwOptions;  /* 0A-0B */
++
++      uint8_t HeartbeatInterval;      /* 0C */
++      uint8_t InstanceNumber; /* 0D */
++      uint16_t RES2;          /* 0E-0F */
++      uint16_t ReqQConsumerIndex;     /* 10-11 */
++      uint16_t ComplQProducerIndex;   /* 12-13 */
++      uint16_t ReqQLen;       /* 14-15 */
++      uint16_t ComplQLen;     /* 16-17 */
++      uint32_t ReqQAddrLo;    /* 18-1B */
++      uint32_t ReqQAddrHi;    /* 1C-1F */
++      uint32_t ComplQAddrLo;  /* 20-23 */
++      uint32_t ComplQAddrHi;  /* 24-27 */
++      uint32_t ShadowRegBufAddrLo;    /* 28-2B */
++      uint32_t ShadowRegBufAddrHi;    /* 2C-2F */
++
++      uint16_t iSCSIOptions;  /* 30-31 */
++
++      uint16_t TCPOptions;    /* 32-33 */
++
++      uint16_t IPOptions;     /* 34-35 */
++
++      uint16_t MaxPDUSize;    /* 36-37 */
++      uint16_t RcvMarkerInt;  /* 38-39 */
++      uint16_t SndMarkerInt;  /* 3A-3B */
++      uint16_t InitMarkerlessInt;     /* 3C-3D */
++      uint16_t FirstBurstSize;        /* 3E-3F */
++      uint16_t DefaultTime2Wait;      /* 40-41 */
++      uint16_t DefaultTime2Retain;    /* 42-43 */
++      uint16_t MaxOutStndngR2T;       /* 44-45 */
++      uint16_t KeepAliveTimeout;      /* 46-47 */
++      uint16_t PortNumber;    /* 48-49 */
++      uint16_t MaxBurstSize;  /* 4A-4B */
++      uint32_t RES4;          /* 4C-4F */
++      uint8_t IPAddr[4];      /* 50-53 */
++      uint8_t RES5[12];       /* 54-5F */
++      uint8_t SubnetMask[4];  /* 60-63 */
++      uint8_t RES6[12];       /* 64-6F */
++      uint8_t GatewayIPAddr[4];       /* 70-73 */
++      uint8_t RES7[12];       /* 74-7F */
++      uint8_t PriDNSIPAddr[4];        /* 80-83 */
++      uint8_t SecDNSIPAddr[4];        /* 84-87 */
++      uint8_t RES8[8];        /* 88-8F */
++      uint8_t Alias[32];      /* 90-AF */
++      uint8_t TargAddr[8];    /* B0-B7 *//* /FIXME: Remove?? */
++      uint8_t CHAPNameSecretsTable[8];        /* B8-BF */
++      uint8_t EthernetMACAddr[6];     /* C0-C5 */
++      uint16_t TargetPortalGroup;     /* C6-C7 */
++      uint8_t SendScale;      /* C8    */
++      uint8_t RecvScale;      /* C9    */
++      uint8_t TypeOfService;  /* CA    */
++      uint8_t Time2Live;      /* CB    */
++      uint16_t VLANPriority;  /* CC-CD */
++      uint16_t Reserved8;     /* CE-CF */
++      uint8_t SecIPAddr[4];   /* D0-D3 */
++      uint8_t Reserved9[12];  /* D4-DF */
++      uint8_t iSNSIPAddr[4];  /* E0-E3 */
++      uint16_t iSNSServerPortNumber;  /* E4-E5 */
++      uint8_t Reserved10[10]; /* E6-EF */
++      uint8_t SLPDAIPAddr[4]; /* F0-F3 */
++      uint8_t Reserved11[12]; /* F4-FF */
++      uint8_t iSCSINameString[256];   /* 100-1FF */
+ };
+ /*************************************************************************/
+ struct dev_db_entry {
+-      uint16_t options;       /* 00-01 */
++      uint8_t options;        /* 00 */
+ #define DDB_OPT_DISC_SESSION  0x10
+ #define DDB_OPT_TARGET              0x02 /* device is a target */
+-      uint16_t exec_throttle; /* 02-03 */
+-      uint16_t exec_count;    /* 04-05 */
+-      uint16_t res0;  /* 06-07 */
+-      uint16_t iscsi_options; /* 08-09 */
+-      uint16_t tcp_options;   /* 0A-0B */
+-      uint16_t ip_options;    /* 0C-0D */
+-      uint16_t iscsi_max_rcv_data_seg_len;    /* 0E-0F */
+-      uint32_t res1;  /* 10-13 */
+-      uint16_t iscsi_max_snd_data_seg_len;    /* 14-15 */
+-      uint16_t iscsi_first_burst_len; /* 16-17 */
+-      uint16_t iscsi_def_time2wait;   /* 18-19 */
+-      uint16_t iscsi_def_time2retain; /* 1A-1B */
+-      uint16_t iscsi_max_outsnd_r2t;  /* 1C-1D */
+-      uint16_t ka_timeout;    /* 1E-1F */
+-      uint8_t isid[6];        /* 20-25 big-endian, must be converted
++      uint8_t control;        /* 01 */
 +
-+      err = unionfs_rmdir_first(dir, dentry, namelist);
-+      /* create whiteout */
-+      if (!err)
-+              err = create_whiteout(dentry, dbstart(dentry));
-+      else {
-+              int new_err;
++      uint16_t exeThrottle;   /* 02-03 */
++      uint16_t exeCount;      /* 04-05 */
++      uint8_t retryCount;     /* 06    */
++      uint8_t retryDelay;     /* 07    */
++      uint16_t iSCSIOptions;  /* 08-09 */
++
++      uint16_t TCPOptions;    /* 0A-0B */
++
++      uint16_t IPOptions;     /* 0C-0D */
++
++      uint16_t maxPDUSize;    /* 0E-0F */
++      uint16_t rcvMarkerInt;  /* 10-11 */
++      uint16_t sndMarkerInt;  /* 12-13 */
++      uint16_t iSCSIMaxSndDataSegLen; /* 14-15 */
++      uint16_t firstBurstSize;        /* 16-17 */
++      uint16_t minTime2Wait;  /* 18-19 : RA :default_time2wait */
++      uint16_t maxTime2Retain;        /* 1A-1B */
++      uint16_t maxOutstndngR2T;       /* 1C-1D */
++      uint16_t keepAliveTimeout;      /* 1E-1F */
++      uint8_t ISID[6];        /* 20-25 big-endian, must be converted
+                                * to little-endian */
+-      uint16_t tsid;          /* 26-27 */
+-      uint16_t port;  /* 28-29 */
+-      uint16_t iscsi_max_burst_len;   /* 2A-2B */
+-      uint16_t def_timeout;   /* 2C-2D */
+-      uint16_t res2;  /* 2E-2F */
+-      uint8_t ip_addr[0x10];  /* 30-3F */
+-      uint8_t iscsi_alias[0x20];      /* 40-5F */
+-      uint8_t tgt_addr[0x20]; /* 60-7F */
+-      uint16_t mss;   /* 80-81 */
+-      uint16_t res3;  /* 82-83 */
+-      uint16_t lcl_port;      /* 84-85 */
+-      uint8_t ipv4_tos;       /* 86 */
+-      uint16_t ipv6_flow_lbl; /* 87-89 */
+-      uint8_t res4[0x36];     /* 8A-BF */
+-      uint8_t iscsi_name[0xE0];       /* C0-19F : xxzzy Make this a
++      uint16_t TSID;          /* 26-27 */
++      uint16_t portNumber;    /* 28-29 */
++      uint16_t maxBurstSize;  /* 2A-2B */
++      uint16_t taskMngmntTimeout;     /* 2C-2D */
++      uint16_t reserved1;     /* 2E-2F */
++      uint8_t ipAddr[0x10];   /* 30-3F */
++      uint8_t iSCSIAlias[0x20];       /* 40-5F */
++      uint8_t targetAddr[0x20];       /* 60-7F */
++      uint8_t userID[0x20];   /* 80-9F */
++      uint8_t password[0x20]; /* A0-BF */
++      uint8_t iscsiName[0x100];       /* C0-1BF : xxzzy Make this a
+                                        * pointer to a string so we
+                                        * don't have to reserve soooo
+                                        * much RAM */
+-      uint8_t ipv6_addr[0x10];/* 1A0-1AF */
+-      uint8_t res5[0x10];     /* 1B0-1BF */
+-      uint16_t ddb_link;      /* 1C0-1C1 */
+-      uint16_t chap_tbl_idx;  /* 1C2-1C3 */
+-      uint16_t tgt_portal_grp; /* 1C4-1C5 */
+-      uint8_t tcp_xmt_wsf;    /* 1C6 */
+-      uint8_t tcp_rcv_wsf;    /* 1C7 */
+-      uint32_t stat_sn;       /* 1C8-1CB */
+-      uint32_t exp_stat_sn;   /* 1CC-1CF */
+-      uint8_t res6[0x30];     /* 1D0-1FF */
++      uint16_t ddbLink;       /* 1C0-1C1 */
++      uint16_t CHAPTableIndex; /* 1C2-1C3 */
++      uint16_t TargetPortalGroup; /* 1C4-1C5 */
++      uint16_t reserved2[2];  /* 1C6-1C7 */
++      uint32_t statSN;        /* 1C8-1CB */
++      uint32_t expStatSN;     /* 1CC-1CF */
++      uint16_t reserved3[0x2C]; /* 1D0-1FB */
++      uint16_t ddbValidCookie; /* 1FC-1FD */
++      uint16_t ddbValidSize;  /* 1FE-1FF */
+ };
+ /*************************************************************************/
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_glbl.h linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_glbl.h
+--- linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_glbl.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_glbl.h   2007-07-08 19:32:17.000000000 -0400
+@@ -8,9 +8,6 @@
+ #ifndef __QLA4x_GBL_H
+ #define       __QLA4x_GBL_H
+-struct iscsi_cls_conn;
+-
+-void qla4xxx_hw_reset(struct scsi_qla_host *ha);
+ int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a);
+ int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port);
+ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb);
+@@ -61,13 +58,11 @@
+ void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
+                                      uint32_t intr_status);
+ int qla4xxx_init_rings(struct scsi_qla_host * ha);
+-struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
+-                                      uint32_t index);
++struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index);
+ void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb);
+ int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
+ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
+                               uint32_t fw_ddb_index, uint32_t state);
+-void qla4xxx_dump_buffer(void *b, uint32_t size);
+ extern int ql4xextended_error_logging;
+ extern int ql4xdiscoverywait;
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_init.c linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_init.c
+--- linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_init.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_init.c   2007-07-08 19:32:17.000000000 -0400
+@@ -6,9 +6,6 @@
+  */
+ #include "ql4_def.h"
+-#include "ql4_glbl.h"
+-#include "ql4_dbg.h"
+-#include "ql4_inline.h"
+ static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
+                                           uint32_t fw_ddb_index);
+@@ -303,12 +300,12 @@
+       if (!qla4xxx_fw_ready(ha))
+               return status;
++      set_bit(AF_ONLINE, &ha->flags);
+       return qla4xxx_get_firmware_status(ha);
+ }
+ static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha,
+-                                              uint32_t fw_ddb_index,
+-                                              uint32_t *new_tgt)
++                                             uint32_t fw_ddb_index)
+ {
+       struct dev_db_entry *fw_ddb_entry = NULL;
+       dma_addr_t fw_ddb_entry_dma;
+@@ -316,7 +313,6 @@
+       int found = 0;
+       uint32_t device_state;
+-      *new_tgt = 0;
+       /* Make sure the dma buffer is valid */
+       fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
+                                         sizeof(*fw_ddb_entry),
+@@ -341,7 +337,7 @@
+       DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no,
+                     __func__, fw_ddb_index));
+       list_for_each_entry(ddb_entry, &ha->ddb_list, list) {
+-              if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name,
++              if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsiName,
+                          ISCSI_NAME_SIZE) == 0) {
+                       found++;
+                       break;
+@@ -352,7 +348,6 @@
+               DEBUG2(printk("scsi%ld: %s: ddb[%d] not found - allocating "
+                             "new ddb\n", ha->host_no, __func__,
+                             fw_ddb_index));
+-              *new_tgt = 1;
+               ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
+       }
+@@ -414,26 +409,26 @@
+       }
+       status = QLA_SUCCESS;
+-      ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid);
++      ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->TSID);
+       ddb_entry->task_mgmt_timeout =
+-              le16_to_cpu(fw_ddb_entry->def_timeout);
++              le16_to_cpu(fw_ddb_entry->taskMngmntTimeout);
+       ddb_entry->CmdSn = 0;
+-      ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exec_throttle);
++      ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exeThrottle);
+       ddb_entry->default_relogin_timeout =
+-              le16_to_cpu(fw_ddb_entry->def_timeout);
+-      ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
++              le16_to_cpu(fw_ddb_entry->taskMngmntTimeout);
++      ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->minTime2Wait);
+       /* Update index in case it changed */
+       ddb_entry->fw_ddb_index = fw_ddb_index;
+       ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
+-      ddb_entry->port = le16_to_cpu(fw_ddb_entry->port);
+-      ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
+-      memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],
++      ddb_entry->port = le16_to_cpu(fw_ddb_entry->portNumber);
++      ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->TargetPortalGroup);
++      memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsiName[0],
+              min(sizeof(ddb_entry->iscsi_name),
+-                 sizeof(fw_ddb_entry->iscsi_name)));
+-      memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0],
+-             min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr)));
++                 sizeof(fw_ddb_entry->iscsiName)));
++      memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ipAddr[0],
++             min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ipAddr)));
+       DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n",
+                     ha->host_no, __func__, fw_ddb_index,
+@@ -500,7 +495,6 @@
+       uint32_t ddb_state;
+       uint32_t conn_err, err_code;
+       struct ddb_entry *ddb_entry;
+-      uint32_t new_tgt;
+       dev_info(&ha->pdev->dev, "Initializing DDBs ...\n");
+       for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES;
+@@ -532,19 +526,8 @@
+                                             "completed "
+                                             "or access denied failure\n",
+                                             ha->host_no, __func__));
+-                      } else {
++                      } else
+                               qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0);
+-                              if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index,
+-                                      NULL, 0, NULL, &next_fw_ddb_index,
+-                                      &ddb_state, &conn_err, NULL, NULL)
+-                                      == QLA_ERROR) {
+-                                      DEBUG2(printk("scsi%ld: %s:"
+-                                              "get_ddb_entry %d failed\n",
+-                                              ha->host_no,
+-                                              __func__, fw_ddb_index));
+-                                      return QLA_ERROR;
+-                              }
+-                      }
+               }
+               if (ddb_state != DDB_DS_SESSION_ACTIVE)
+@@ -557,7 +540,7 @@
+                             ha->host_no, __func__, fw_ddb_index));
+               /* Add DDB to internal our ddb list. */
+-              ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
++              ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index);
+               if (ddb_entry == NULL) {
+                       DEBUG2(printk("scsi%ld: %s: Unable to allocate memory "
+                                     "for device at fw_ddb_index %d\n",
+@@ -882,20 +865,21 @@
+ static void qla4x00_pci_config(struct scsi_qla_host *ha)
+ {
+-      uint16_t w;
+-      int status;
++      uint16_t w, mwi;
+       dev_info(&ha->pdev->dev, "Configuring PCI space...\n");
+       pci_set_master(ha->pdev);
+-      status = pci_set_mwi(ha->pdev);
++      mwi = 0;
++      if (pci_set_mwi(ha->pdev))
++              mwi = PCI_COMMAND_INVALIDATE;
+       /*
+        * We want to respect framework's setting of PCI configuration space
+        * command register and also want to make sure that all bits of
+        * interest to us are properly set in command register.
+        */
+       pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
+-      w |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
++      w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+       w &= ~PCI_COMMAND_INTX_DISABLE;
+       pci_write_config_word(ha->pdev, PCI_COMMAND, w);
+ }
+@@ -927,9 +911,6 @@
+               writel(set_rmask(NVR_WRITE_ENABLE),
+                      &ha->reg->u1.isp4022.nvram);
+-        writel(2, &ha->reg->mailbox[6]);
+-        readl(&ha->reg->mailbox[6]);
+-
+       writel(set_rmask(CSR_BOOT_ENABLE), &ha->reg->ctrl_status);
+       readl(&ha->reg->ctrl_status);
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+@@ -977,25 +958,25 @@
+       return status;
+ }
+-int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
++int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha)
+ {
+-#define QL4_LOCK_DRVR_WAIT    60
++#define QL4_LOCK_DRVR_WAIT    30
+ #define QL4_LOCK_DRVR_SLEEP   1
+       int drvr_wait = QL4_LOCK_DRVR_WAIT;
+       while (drvr_wait) {
+-              if (ql4xxx_lock_drvr(a) == 0) {
++              if (ql4xxx_lock_drvr(ha) == 0) {
+                       ssleep(QL4_LOCK_DRVR_SLEEP);
+                       if (drvr_wait) {
+                               DEBUG2(printk("scsi%ld: %s: Waiting for "
+-                                            "Global Init Semaphore(%d)...\n",
+-                                            a->host_no,
++                                            "Global Init Semaphore(%d)...n",
++                                            ha->host_no,
+                                             __func__, drvr_wait));
+                       }
+                       drvr_wait -= QL4_LOCK_DRVR_SLEEP;
+               } else {
+                       DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
+-                                    "acquired\n", a->host_no, __func__));
++                                    "acquired.n", ha->host_no, __func__));
+                       return QLA_SUCCESS;
+               }
+       }
+@@ -1144,17 +1125,17 @@
+       /* Initialize the Host adapter request/response queues and firmware */
+       if (qla4xxx_start_firmware(ha) == QLA_ERROR)
+-              goto exit_init_hba;
++              return status;
+       if (qla4xxx_validate_mac_address(ha) == QLA_ERROR)
+-              goto exit_init_hba;
++              return status;
+       if (qla4xxx_init_local_data(ha) == QLA_ERROR)
+-              goto exit_init_hba;
++              return status;
+       status = qla4xxx_init_firmware(ha);
+       if (status == QLA_ERROR)
+-              goto exit_init_hba;
++              return status;
+       /*
+        * FW is waiting to get an IP address from DHCP server: Skip building
+@@ -1162,12 +1143,12 @@
+        * followed by 0x8014 aen" to trigger the tgt discovery process.
+        */
+       if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS)
+-              goto exit_init_online;
++              return status;
+       /* Skip device discovery if ip and subnet is zero */
+       if (memcmp(ha->ip_address, ip_address, IP_ADDR_LEN) == 0 ||
+           memcmp(ha->subnet_mask, ip_address, IP_ADDR_LEN) == 0)
+-              goto exit_init_online;
++              return status;
+       if (renew_ddb_list == PRESERVE_DDB_LIST) {
+               /*
+@@ -1196,10 +1177,9 @@
+                             ha->host_no));
+       }
+-exit_init_online:
+-      set_bit(AF_ONLINE, &ha->flags);
+-exit_init_hba:
++ exit_init_hba:
+       return status;
 +
-+              if (dbstart(dentry) == 0)
-+                      goto out;
+ }
+ /**
+@@ -1213,10 +1193,9 @@
+                                          uint32_t fw_ddb_index)
+ {
+       struct ddb_entry * ddb_entry;
+-      uint32_t new_tgt;
+       /* First allocate a device structure */
+-      ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
++      ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index);
+       if (ddb_entry == NULL) {
+               DEBUG2(printk(KERN_WARNING
+                             "scsi%ld: Unable to allocate memory to add "
+@@ -1224,18 +1203,6 @@
+               return;
+       }
+-      if (!new_tgt && (ddb_entry->fw_ddb_index != fw_ddb_index)) {
+-              /* Target has been bound to a new fw_ddb_index */
+-              qla4xxx_free_ddb(ha, ddb_entry);
+-              ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
+-              if (ddb_entry == NULL) {
+-                      DEBUG2(printk(KERN_WARNING
+-                              "scsi%ld: Unable to allocate memory"
+-                              " to add fw_ddb_index %d\n",
+-                              ha->host_no, fw_ddb_index));
+-                      return;
+-              }
+-      }
+       if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) ==
+                                   QLA_ERROR) {
+               ha->fw_ddb_index_map[fw_ddb_index] =
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_iocb.c linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_iocb.c
+--- linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_iocb.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_iocb.c   2007-07-08 19:32:17.000000000 -0400
+@@ -6,10 +6,6 @@
+  */
+ #include "ql4_def.h"
+-#include "ql4_glbl.h"
+-#include "ql4_dbg.h"
+-#include "ql4_inline.h"
+-
+ #include <scsi/scsi_tcq.h>
+@@ -145,13 +141,11 @@
+       uint16_t avail_dsds;
+       struct data_seg_a64 *cur_dsd;
+       struct scsi_cmnd *cmd;
+-      struct scatterlist *sg;
+-      int i;
+       cmd = srb->cmd;
+       ha = srb->ha;
+-      if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
++      if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) {
+               /* No data being transferred */
+               cmd_entry->ttlByteCnt = __constant_cpu_to_le32(0);
+               return;
+@@ -160,7 +154,14 @@
+       avail_dsds = COMMAND_SEG;
+       cur_dsd = (struct data_seg_a64 *) & (cmd_entry->dataseg[0]);
+-      scsi_for_each_sg(cmd, sg, tot_dsds, i) {
++      /* Load data segments */
++      if (cmd->use_sg) {
++              struct scatterlist *cur_seg;
++              struct scatterlist *end_seg;
 +
-+              /* exit if the error returned was NOT -EROFS */
-+              if (!IS_COPYUP_ERR(err))
-+                      goto out;
++              cur_seg = (struct scatterlist *)cmd->request_buffer;
++              end_seg = cur_seg + tot_dsds;
++              while (cur_seg < end_seg) {
+                       dma_addr_t sle_dma;
+                       /* Allocate additional continuation packets? */
+@@ -174,13 +175,19 @@
+                               avail_dsds = CONTINUE_SEG;
+                       }
+-              sle_dma = sg_dma_address(sg);
++                      sle_dma = sg_dma_address(cur_seg);
+                       cur_dsd->base.addrLow = cpu_to_le32(LSDW(sle_dma));
+                       cur_dsd->base.addrHigh = cpu_to_le32(MSDW(sle_dma));
+-              cur_dsd->count = cpu_to_le32(sg_dma_len(sg));
++                      cur_dsd->count = cpu_to_le32(sg_dma_len(cur_seg));
+                       avail_dsds--;
+                       cur_dsd++;
++                      cur_seg++;
++              }
++      } else {
++              cur_dsd->base.addrLow = cpu_to_le32(LSDW(srb->dma_handle));
++              cur_dsd->base.addrHigh = cpu_to_le32(MSDW(srb->dma_handle));
++              cur_dsd->count = cpu_to_le32(cmd->request_bufflen);
+       }
+ }
+@@ -197,8 +204,8 @@
+       struct scsi_cmnd *cmd = srb->cmd;
+       struct ddb_entry *ddb_entry;
+       struct command_t3_entry *cmd_entry;
++      struct scatterlist *sg = NULL;
+-      int nseg;
+       uint16_t tot_dsds;
+       uint16_t req_cnt;
+@@ -226,11 +233,24 @@
+       index = (uint32_t)cmd->request->tag;
+       /* Calculate the number of request entries needed. */
+-      nseg = scsi_dma_map(cmd);
+-      if (nseg < 0)
++      if (cmd->use_sg) {
++              sg = (struct scatterlist *)cmd->request_buffer;
++              tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg,
++                                    cmd->sc_data_direction);
++              if (tot_dsds == 0)
+                       goto queuing_error;
+-      tot_dsds = nseg;
++      } else if (cmd->request_bufflen) {
++              dma_addr_t      req_dma;
++              req_dma = pci_map_single(ha->pdev, cmd->request_buffer,
++                                       cmd->request_bufflen,
++                                       cmd->sc_data_direction);
++              if (dma_mapping_error(req_dma))
++                      goto queuing_error;
 +
-+              new_err = create_whiteout(dentry, dbstart(dentry) - 1);
-+              if (new_err != -EEXIST)
-+                      err = new_err;
++              srb->dma_handle = req_dma;
++              tot_dsds = 1;
 +      }
+       req_cnt = qla4xxx_calc_request_entries(tot_dsds);
+       if (ha->req_q_count < (req_cnt + 2)) {
+@@ -259,7 +279,7 @@
+       int_to_scsilun(cmd->device->lun, &cmd_entry->lun);
+       cmd_entry->cmdSeqNum = cpu_to_le32(ddb_entry->CmdSn);
+-      cmd_entry->ttlByteCnt = cpu_to_le32(scsi_bufflen(cmd));
++      cmd_entry->ttlByteCnt = cpu_to_le32(cmd->request_bufflen);
+       memcpy(cmd_entry->cdb, cmd->cmnd, cmd->cmd_len);
+       cmd_entry->dataSegCnt = cpu_to_le16(tot_dsds);
+       cmd_entry->hdr.entryCount = req_cnt;
+@@ -269,13 +289,13 @@
+        *       transferred, as the data direction bit is sometimed filled
+        *       in when there is no data to be transferred */
+       cmd_entry->control_flags = CF_NO_DATA;
+-      if (scsi_bufflen(cmd)) {
++      if (cmd->request_bufflen) {
+               if (cmd->sc_data_direction == DMA_TO_DEVICE)
+                       cmd_entry->control_flags = CF_WRITE;
+               else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+                       cmd_entry->control_flags = CF_READ;
+-              ha->bytes_xfered += scsi_bufflen(cmd);
++              ha->bytes_xfered += cmd->request_bufflen;
+               if (ha->bytes_xfered & ~0xFFFFF){
+                       ha->total_mbytes_xferred += ha->bytes_xfered >> 20;
+                       ha->bytes_xfered &= 0xFFFFF;
+@@ -339,9 +359,14 @@
+       return QLA_SUCCESS;
+ queuing_error:
+-      if (tot_dsds)
+-              scsi_dma_unmap(cmd);
++      if (cmd->use_sg && tot_dsds) {
++              sg = (struct scatterlist *) cmd->request_buffer;
++              pci_unmap_sg(ha->pdev, sg, cmd->use_sg,
++                           cmd->sc_data_direction);
++      } else if (tot_dsds)
++              pci_unmap_single(ha->pdev, srb->dma_handle,
++                               cmd->request_bufflen, cmd->sc_data_direction);
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       return QLA_ERROR;
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_isr.c linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_isr.c
+--- linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_isr.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_isr.c    2007-07-08 19:32:17.000000000 -0400
+@@ -6,9 +6,6 @@
+  */
+ #include "ql4_def.h"
+-#include "ql4_glbl.h"
+-#include "ql4_dbg.h"
+-#include "ql4_inline.h"
+ /**
+  * qla2x00_process_completed_request() - Process a Fast Post response.
+@@ -95,7 +92,7 @@
+               if (sts_entry->iscsiFlags &
+                   (ISCSI_FLAG_RESIDUAL_OVER|ISCSI_FLAG_RESIDUAL_UNDER))
+-                      scsi_set_resid(cmd, residual);
++                      cmd->resid = residual;
+               cmd->result = DID_OK << 16 | scsi_status;
+@@ -179,14 +176,14 @@
+                        * Firmware detected a SCSI transport underrun
+                        * condition
+                        */
+-                      scsi_set_resid(cmd, residual);
++                      cmd->resid = residual;
+                       DEBUG2(printk("scsi%ld:%d:%d:%d: %s: UNDERRUN status "
+                                     "detected, xferlen = 0x%x, residual = "
+                                     "0x%x\n",
+                                     ha->host_no, cmd->device->channel,
+                                     cmd->device->id,
+                                     cmd->device->lun, __func__,
+-                                    scsi_bufflen(cmd),
++                                    cmd->request_bufflen,
+                                     residual));
+               }
+@@ -230,7 +227,7 @@
+                       if ((sts_entry->iscsiFlags &
+                            ISCSI_FLAG_RESIDUAL_UNDER) == 0) {
+                               cmd->result = DID_BUS_BUSY << 16;
+-                      } else if ((scsi_bufflen(cmd) - residual) <
++                      } else if ((cmd->request_bufflen - residual) <
+                                  cmd->underflow) {
+                               /*
+                                * Handle mid-layer underflow???
+@@ -251,7 +248,7 @@
+                                             cmd->device->channel,
+                                             cmd->device->id,
+                                             cmd->device->lun, __func__,
+-                                            scsi_bufflen(cmd), residual));
++                                            cmd->request_bufflen, residual));
+                               cmd->result = DID_ERROR << 16;
+                       } else {
+@@ -420,7 +417,6 @@
+                                      uint32_t mbox_status)
+ {
+       int i;
+-      uint32_t mbox_stat2, mbox_stat3;
+       if ((mbox_status == MBOX_STS_BUSY) ||
+           (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) ||
+@@ -441,12 +437,6 @@
+       } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
+               /* Immediately process the AENs that don't require much work.
+                * Only queue the database_changed AENs */
+-              if (ha->aen_log.count < MAX_AEN_ENTRIES) {
+-                      for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
+-                              ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] =
+-                                      readl(&ha->reg->mailbox[i]);
+-                      ha->aen_log.count++;
+-              }
+               switch (mbox_status) {
+               case MBOX_ASTS_SYSTEM_ERROR:
+                       /* Log Mailbox registers */
+@@ -503,16 +493,6 @@
+                                     mbox_status));
+                       break;
+-              case MBOX_ASTS_IP_ADDR_STATE_CHANGED:
+-                      mbox_stat2 = readl(&ha->reg->mailbox[2]);
+-                      mbox_stat3 = readl(&ha->reg->mailbox[3]);
+-
+-                      if ((mbox_stat3 == 5) && (mbox_stat2 == 3))
+-                              set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
+-                      else if ((mbox_stat3 == 2) && (mbox_stat2 == 5))
+-                              set_bit(DPC_RESET_HA, &ha->dpc_flags);
+-                      break;
+-
+               case MBOX_ASTS_MAC_ADDRESS_CHANGED:
+               case MBOX_ASTS_DNS:
+                       /* No action */
+@@ -538,6 +518,11 @@
+                       /* Queue AEN information and process it in the DPC
+                        * routine */
+                       if (ha->aen_q_count > 0) {
++                              /* advance pointer */
++                              if (ha->aen_in == (MAX_AEN_ENTRIES - 1))
++                                      ha->aen_in = 0;
++                              else
++                                      ha->aen_in++;
+                               /* decrement available counter */
+                               ha->aen_q_count--;
+@@ -557,10 +542,6 @@
+                                             ha->aen_q[ha->aen_in].mbox_sts[2],
+                                             ha->aen_q[ha->aen_in].mbox_sts[3],
+                                             ha->aen_q[ha->aen_in].  mbox_sts[4]));
+-                              /* advance pointer */
+-                              ha->aen_in++;
+-                              if (ha->aen_in == MAX_AEN_ENTRIES)
+-                                      ha->aen_in = 0;
+                               /* The DPC routine will process the aen */
+                               set_bit(DPC_AEN, &ha->dpc_flags);
+@@ -743,24 +724,25 @@
+       spin_lock_irqsave(&ha->hardware_lock, flags);
+       while (ha->aen_out != ha->aen_in) {
++              /* Advance pointers for next entry */
++              if (ha->aen_out == (MAX_AEN_ENTRIES - 1))
++                      ha->aen_out = 0;
++              else
++                      ha->aen_out++;
 +
-+out:
-+      /* call d_drop so the system "forgets" about us */
-+      if (!err)
-+              d_drop(dentry);
++              ha->aen_q_count++;
+               aen = &ha->aen_q[ha->aen_out];
 +
-+      if (namelist)
-+              free_rdstate(namelist);
+               /* copy aen information to local structure */
+               for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
+                       mbox_sts[i] = aen->mbox_sts[i];
+-              ha->aen_q_count++;
+-              ha->aen_out++;
+-
+-              if (ha->aen_out == MAX_AEN_ENTRIES)
+-                      ha->aen_out = 0;
+-
+               spin_unlock_irqrestore(&ha->hardware_lock, flags);
+-              DEBUG2(printk("qla4xxx(%ld): AEN[%d]=0x%08x, mbx1=0x%08x mbx2=0x%08x"
+-                      " mbx3=0x%08x mbx4=0x%08x\n", ha->host_no,
+-                      (ha->aen_out ? (ha->aen_out-1): (MAX_AEN_ENTRIES-1)),
+-                      mbox_sts[0], mbox_sts[1], mbox_sts[2],
+-                      mbox_sts[3], mbox_sts[4]));
++              DEBUG(printk("scsi%ld: AEN[%d] %04x, index [%d] state=%04x "
++                           "mod=%x conerr=%08x \n", ha->host_no, ha->aen_out,
++                           mbox_sts[0], mbox_sts[2], mbox_sts[3],
++                           mbox_sts[1], mbox_sts[4]));
+               switch (mbox_sts[0]) {
+               case MBOX_ASTS_DATABASE_CHANGED:
+@@ -810,5 +792,6 @@
+               spin_lock_irqsave(&ha->hardware_lock, flags);
+       }
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
 +
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-diff -Nurb linux-2.6.22-570/fs/unionfs/xattr.c linux-2.6.22-590/fs/unionfs/xattr.c
---- linux-2.6.22-570/fs/unionfs/xattr.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/fs/unionfs/xattr.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,161 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2003-2006 Charles P. Wright
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2005-2006 Junjiro Okajima
-+ * Copyright (c) 2005      Arun M. Krishnakumar
-+ * Copyright (c) 2004-2006 David P. Quigley
-+ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
-+ * Copyright (c) 2003      Puja Gupta
-+ * Copyright (c) 2003      Harikesavan Krishnan
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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.
-+ */
+ }
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_mbx.c linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_mbx.c
+--- linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_mbx.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_mbx.c    2007-07-08 19:32:17.000000000 -0400
+@@ -6,9 +6,6 @@
+  */
+ #include "ql4_def.h"
+-#include "ql4_glbl.h"
+-#include "ql4_dbg.h"
+-#include "ql4_inline.h"
+ /**
+@@ -172,6 +169,84 @@
+       return status;
+ }
 +
-+#include "union.h"
++#if 0
 +
-+/* This is lifted from fs/xattr.c */
-+void *unionfs_xattr_alloc(size_t size, size_t limit)
++/**
++ * qla4xxx_issue_iocb - issue mailbox iocb command
++ * @ha: adapter state pointer.
++ * @buffer: buffer pointer.
++ * @phys_addr: physical address of buffer.
++ * @size: size of buffer.
++ *
++ * Issues iocbs via mailbox commands.
++ * TARGET_QUEUE_LOCK must be released.
++ * ADAPTER_STATE_LOCK must be released.
++ **/
++int
++qla4xxx_issue_iocb(struct scsi_qla_host * ha, void *buffer,
++                 dma_addr_t phys_addr, size_t size)
 +{
-+      void *ptr;
-+
-+      if (size > limit)
-+              return ERR_PTR(-E2BIG);
-+
-+      if (!size)              /* size request, no buffer is needed */
-+              return NULL;
-+      else if (size <= PAGE_SIZE)
-+              ptr = kmalloc(size, GFP_KERNEL);
-+      else
-+              ptr = vmalloc(size);
-+      if (!ptr)
-+              return ERR_PTR(-ENOMEM);
-+      return ptr;
-+}
++      uint32_t mbox_cmd[MBOX_REG_COUNT];
++      uint32_t mbox_sts[MBOX_REG_COUNT];
++      int status;
 +
-+void unionfs_xattr_free(void *ptr, size_t size)
-+{
-+      if (!size)              /* size request, no buffer was needed */
-+              return;
-+      else if (size <= PAGE_SIZE)
-+              kfree(ptr);
-+      else
-+              vfree(ptr);
++      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
++      memset(&mbox_sts, 0, sizeof(mbox_sts));
++      mbox_cmd[0] = MBOX_CMD_EXECUTE_IOCB_A64;
++      mbox_cmd[1] = 0;
++      mbox_cmd[2] = LSDW(phys_addr);
++      mbox_cmd[3] = MSDW(phys_addr);
++      status = qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
++      return status;
 +}
 +
-+/*
-+ * BKL held by caller.
-+ * dentry->d_inode->i_mutex locked
-+ */
-+ssize_t unionfs_getxattr(struct dentry *dentry, const char *name, void *value,
-+                       size_t size)
++int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
++                                 uint16_t fw_ddb_index,
++                                 uint16_t connection_id,
++                                 uint16_t option)
 +{
-+      struct dentry *hidden_dentry = NULL;
-+      int err = -EOPNOTSUPP;
++      uint32_t mbox_cmd[MBOX_REG_COUNT];
++      uint32_t mbox_sts[MBOX_REG_COUNT];
 +
-+      unionfs_read_lock(dentry->d_sb);
-+      unionfs_lock_dentry(dentry);
-+
-+      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
++      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
++      memset(&mbox_sts, 0, sizeof(mbox_sts));
++      mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
++      mbox_cmd[1] = fw_ddb_index;
++      mbox_cmd[2] = connection_id;
++      mbox_cmd[3] = LOGOUT_OPTION_RELOGIN;
++      if (qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]) !=
++          QLA_SUCCESS) {
++              DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
++                            "option %04x failed sts %04X %04X",
++                            ha->host_no, __func__,
++                            option, mbox_sts[0], mbox_sts[1]));
++              if (mbox_sts[0] == 0x4005)
++                      DEBUG2(printk("%s reason %04X\n", __func__,
++                                    mbox_sts[1]));
 +      }
-+
-+      hidden_dentry = unionfs_lower_dentry(dentry);
-+
-+      err = vfs_getxattr(hidden_dentry, (char*) name, value, size);
-+
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
++      return QLA_SUCCESS;
 +}
 +
-+/*
-+ * BKL held by caller.
-+ * dentry->d_inode->i_mutex locked
-+ */
-+int unionfs_setxattr(struct dentry *dentry, const char *name,
-+                   const void *value, size_t size, int flags)
++int qla4xxx_clear_database_entry(struct scsi_qla_host * ha,
++                               uint16_t fw_ddb_index)
 +{
-+      struct dentry *hidden_dentry = NULL;
-+      int err = -EOPNOTSUPP;
-+
-+      unionfs_read_lock(dentry->d_sb);
-+      unionfs_lock_dentry(dentry);
++      uint32_t mbox_cmd[MBOX_REG_COUNT];
++      uint32_t mbox_sts[MBOX_REG_COUNT];
 +
-+      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
-+      }
++      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
++      memset(&mbox_sts, 0, sizeof(mbox_sts));
++      mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;
++      mbox_cmd[1] = fw_ddb_index;
++      if (qla4xxx_mailbox_command(ha, 2, 5, &mbox_cmd[0], &mbox_sts[0]) !=
++          QLA_SUCCESS)
++              return QLA_ERROR;
 +
-+      hidden_dentry = unionfs_lower_dentry(dentry);
++      return QLA_SUCCESS;
++}
 +
-+      err = vfs_setxattr(hidden_dentry, (char*) name, (void*) value,
-+                         size, flags);
++#endif  /*  0  */
 +
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
+ /**
+  * qla4xxx_initialize_fw_cb - initializes firmware control block.
+  * @ha: Pointer to host adapter structure.
+@@ -197,13 +272,10 @@
+       /* Get Initialize Firmware Control Block. */
+       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+       memset(&mbox_sts, 0, sizeof(mbox_sts));
+-
+       mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
+       mbox_cmd[2] = LSDW(init_fw_cb_dma);
+       mbox_cmd[3] = MSDW(init_fw_cb_dma);
+-      mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk);
+-
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
++      if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
+           QLA_SUCCESS) {
+               dma_free_coherent(&ha->pdev->dev,
+                                 sizeof(struct init_fw_ctrl_blk),
+@@ -215,56 +287,51 @@
+       qla4xxx_init_rings(ha);
+       /* Fill in the request and response queue information. */
+-      init_fw_cb->pri.rqq_consumer_idx = cpu_to_le16(ha->request_out);
+-      init_fw_cb->pri.compq_producer_idx = cpu_to_le16(ha->response_in);
+-      init_fw_cb->pri.rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
+-      init_fw_cb->pri.compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
+-      init_fw_cb->pri.rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma));
+-      init_fw_cb->pri.rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma));
+-      init_fw_cb->pri.compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma));
+-      init_fw_cb->pri.compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma));
+-      init_fw_cb->pri.shdwreg_addr_lo =
++      init_fw_cb->ReqQConsumerIndex = cpu_to_le16(ha->request_out);
++      init_fw_cb->ComplQProducerIndex = cpu_to_le16(ha->response_in);
++      init_fw_cb->ReqQLen = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
++      init_fw_cb->ComplQLen = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
++      init_fw_cb->ReqQAddrLo = cpu_to_le32(LSDW(ha->request_dma));
++      init_fw_cb->ReqQAddrHi = cpu_to_le32(MSDW(ha->request_dma));
++      init_fw_cb->ComplQAddrLo = cpu_to_le32(LSDW(ha->response_dma));
++      init_fw_cb->ComplQAddrHi = cpu_to_le32(MSDW(ha->response_dma));
++      init_fw_cb->ShadowRegBufAddrLo =
+               cpu_to_le32(LSDW(ha->shadow_regs_dma));
+-      init_fw_cb->pri.shdwreg_addr_hi =
++      init_fw_cb->ShadowRegBufAddrHi =
+               cpu_to_le32(MSDW(ha->shadow_regs_dma));
+       /* Set up required options. */
+-      init_fw_cb->pri.fw_options |=
++      init_fw_cb->FwOptions |=
+               __constant_cpu_to_le16(FWOPT_SESSION_MODE |
+                                      FWOPT_INITIATOR_MODE);
+-      init_fw_cb->pri.fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
++      init_fw_cb->FwOptions &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
+       /* Save some info in adapter structure. */
+-      ha->firmware_options = le16_to_cpu(init_fw_cb->pri.fw_options);
+-      ha->tcp_options = le16_to_cpu(init_fw_cb->pri.ipv4_tcp_opts);
+-      ha->heartbeat_interval = init_fw_cb->pri.hb_interval;
+-      memcpy(ha->ip_address, init_fw_cb->pri.ipv4_addr,
+-             min(sizeof(ha->ip_address), sizeof(init_fw_cb->pri.ipv4_addr)));
+-      memcpy(ha->subnet_mask, init_fw_cb->pri.ipv4_subnet,
+-             min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->pri.ipv4_subnet)));
+-      memcpy(ha->gateway, init_fw_cb->pri.ipv4_gw_addr,
+-             min(sizeof(ha->gateway), sizeof(init_fw_cb->pri.ipv4_gw_addr)));
+-      memcpy(ha->name_string, init_fw_cb->pri.iscsi_name,
++      ha->firmware_options = le16_to_cpu(init_fw_cb->FwOptions);
++      ha->tcp_options = le16_to_cpu(init_fw_cb->TCPOptions);
++      ha->heartbeat_interval = init_fw_cb->HeartbeatInterval;
++      memcpy(ha->ip_address, init_fw_cb->IPAddr,
++             min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
++      memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
++             min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
++      memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
++             min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
++      memcpy(ha->name_string, init_fw_cb->iSCSINameString,
+              min(sizeof(ha->name_string),
+-                 sizeof(init_fw_cb->pri.iscsi_name)));
+-      /*memcpy(ha->alias, init_fw_cb->Alias,
+-             min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
++                 sizeof(init_fw_cb->iSCSINameString)));
++      memcpy(ha->alias, init_fw_cb->Alias,
++             min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));
+       /* Save Command Line Paramater info */
+-      ha->port_down_retry_count = le16_to_cpu(init_fw_cb->pri.conn_ka_timeout);
++      ha->port_down_retry_count = le16_to_cpu(init_fw_cb->KeepAliveTimeout);
+       ha->discovery_wait = ql4xdiscoverywait;
+       /* Send Initialize Firmware Control Block. */
+-      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+-      memset(&mbox_sts, 0, sizeof(mbox_sts));
+-
+       mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;
+       mbox_cmd[1] = 0;
+       mbox_cmd[2] = LSDW(init_fw_cb_dma);
+       mbox_cmd[3] = MSDW(init_fw_cb_dma);
+-      mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk);
+-
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) ==
++      if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) ==
+           QLA_SUCCESS)
+               status = QLA_SUCCESS;
+        else {
+@@ -301,14 +368,12 @@
+       /* Get Initialize Firmware Control Block. */
+       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+       memset(&mbox_sts, 0, sizeof(mbox_sts));
+-
+       memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk));
+       mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
+       mbox_cmd[2] = LSDW(init_fw_cb_dma);
+       mbox_cmd[3] = MSDW(init_fw_cb_dma);
+-      mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk);
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
++      if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
+           QLA_SUCCESS) {
+               DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
+                             ha->host_no, __func__));
+@@ -319,12 +384,12 @@
+       }
+       /* Save IP Address. */
+-      memcpy(ha->ip_address, init_fw_cb->pri.ipv4_addr,
+-             min(sizeof(ha->ip_address), sizeof(init_fw_cb->pri.ipv4_addr)));
+-      memcpy(ha->subnet_mask, init_fw_cb->pri.ipv4_subnet,
+-             min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->pri.ipv4_subnet)));
+-      memcpy(ha->gateway, init_fw_cb->pri.ipv4_gw_addr,
+-             min(sizeof(ha->gateway), sizeof(init_fw_cb->pri.ipv4_gw_addr)));
++      memcpy(ha->ip_address, init_fw_cb->IPAddr,
++             min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
++      memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
++             min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
++      memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
++             min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
+       dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk),
+                         init_fw_cb, init_fw_cb_dma);
+@@ -344,10 +409,8 @@
+       /* Get firmware version */
+       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+       memset(&mbox_sts, 0, sizeof(mbox_sts));
+-
+       mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;
+-
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) !=
++      if (qla4xxx_mailbox_command(ha, 1, 4, &mbox_cmd[0], &mbox_sts[0]) !=
+           QLA_SUCCESS) {
+               DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
+                             "status %04X\n", ha->host_no, __func__,
+@@ -375,10 +438,8 @@
+       /* Get firmware version */
+       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+       memset(&mbox_sts, 0, sizeof(mbox_sts));
+-
+       mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;
+-
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
++      if (qla4xxx_mailbox_command(ha, 1, 3, &mbox_cmd[0], &mbox_sts[0]) !=
+           QLA_SUCCESS) {
+               DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
+                             "status %04X\n", ha->host_no, __func__,
+@@ -430,14 +491,11 @@
+       }
+       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+       memset(&mbox_sts, 0, sizeof(mbox_sts));
+-
+       mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
+       mbox_cmd[1] = (uint32_t) fw_ddb_index;
+       mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
+       mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
+-      mbox_cmd[4] = sizeof(struct dev_db_entry);
+-
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) ==
++      if (qla4xxx_mailbox_command(ha, 4, 7, &mbox_cmd[0], &mbox_sts[0]) ==
+           QLA_ERROR) {
+               DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"
+                             " with status 0x%04X\n", ha->host_no, __func__,
+@@ -454,11 +512,11 @@
+               dev_info(&ha->pdev->dev, "DDB[%d] MB0 %04x Tot %d Next %d "
+                          "State %04x ConnErr %08x %d.%d.%d.%d:%04d \"%s\"\n",
+                          fw_ddb_index, mbox_sts[0], mbox_sts[2], mbox_sts[3],
+-                         mbox_sts[4], mbox_sts[5], fw_ddb_entry->ip_addr[0],
+-                         fw_ddb_entry->ip_addr[1], fw_ddb_entry->ip_addr[2],
+-                         fw_ddb_entry->ip_addr[3],
+-                         le16_to_cpu(fw_ddb_entry->port),
+-                         fw_ddb_entry->iscsi_name);
++                         mbox_sts[4], mbox_sts[5], fw_ddb_entry->ipAddr[0],
++                         fw_ddb_entry->ipAddr[1], fw_ddb_entry->ipAddr[2],
++                         fw_ddb_entry->ipAddr[3],
++                         le16_to_cpu(fw_ddb_entry->portNumber),
++                         fw_ddb_entry->iscsiName);
+       }
+       if (num_valid_ddb_entries)
+               *num_valid_ddb_entries = mbox_sts[2];
+@@ -513,10 +571,35 @@
+       mbox_cmd[1] = (uint32_t) fw_ddb_index;
+       mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
+       mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
+-      mbox_cmd[4] = sizeof(struct dev_db_entry);
++      return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
 +}
 +
-+/*
-+ * BKL held by caller.
-+ * dentry->d_inode->i_mutex locked
-+ */
-+int unionfs_removexattr(struct dentry *dentry, const char *name)
++#if 0
++int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha,
++                                  uint16_t fw_ddb_index)
 +{
-+      struct dentry *hidden_dentry = NULL;
-+      int err = -EOPNOTSUPP;
-+
-+      unionfs_read_lock(dentry->d_sb);
-+      unionfs_lock_dentry(dentry);
++      int status = QLA_ERROR;
++      uint32_t mbox_cmd[MBOX_REG_COUNT];
++      uint32_t mbox_sts[MBOX_REG_COUNT];
 +
-+      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
++      /* Do not wait for completion. The firmware will send us an
++       * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
++       */
++      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
++      memset(&mbox_sts, 0, sizeof(mbox_sts));
++      mbox_cmd[0] = MBOX_CMD_CONN_OPEN_SESS_LOGIN;
++      mbox_cmd[1] = (uint32_t) fw_ddb_index;
++      mbox_cmd[2] = 0;
++      mbox_cmd[3] = 0;
++      mbox_cmd[4] = 0;
++      status = qla4xxx_mailbox_command(ha, 4, 0, &mbox_cmd[0], &mbox_sts[0]);
++      DEBUG2(printk("%s fw_ddb_index=%d status=%d mbx0_1=0x%x :0x%x\n",
++                    __func__, fw_ddb_index, status, mbox_sts[0],
++                    mbox_sts[1]);)
+-      return qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
++              return status;
+ }
++#endif  /*  0  */
+ /**
+  * qla4xxx_get_crash_record - retrieves crash record.
+@@ -531,14 +614,12 @@
+       struct crash_record *crash_record = NULL;
+       dma_addr_t crash_record_dma = 0;
+       uint32_t crash_record_size = 0;
+-
+       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+       memset(&mbox_sts, 0, sizeof(mbox_cmd));
+       /* Get size of crash record. */
+       mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
+-
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
++      if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+           QLA_SUCCESS) {
+               DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",
+                             ha->host_no, __func__));
+@@ -558,15 +639,11 @@
+               goto exit_get_crash_record;
+       /* Get Crash Record. */
+-      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+-      memset(&mbox_sts, 0, sizeof(mbox_cmd));
+-
+       mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
+       mbox_cmd[2] = LSDW(crash_record_dma);
+       mbox_cmd[3] = MSDW(crash_record_dma);
+       mbox_cmd[4] = crash_record_size;
+-
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
++      if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+           QLA_SUCCESS)
+               goto exit_get_crash_record;
+@@ -578,6 +655,7 @@
+                                 crash_record, crash_record_dma);
+ }
++#if 0
+ /**
+  * qla4xxx_get_conn_event_log - retrieves connection event log
+  * @ha: Pointer to host adapter structure.
+@@ -600,8 +678,7 @@
+       /* Get size of crash record. */
+       mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
+-
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
++      if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+           QLA_SUCCESS)
+               goto exit_get_event_log;
+@@ -616,14 +693,10 @@
+               goto exit_get_event_log;
+       /* Get Crash Record. */
+-      memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+-      memset(&mbox_sts, 0, sizeof(mbox_cmd));
+-
+       mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
+       mbox_cmd[2] = LSDW(event_log_dma);
+       mbox_cmd[3] = MSDW(event_log_dma);
+-
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
++      if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+           QLA_SUCCESS) {
+               DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event "
+                             "log!\n", ha->host_no, __func__));
+@@ -672,6 +745,7 @@
+               dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
+                                 event_log_dma);
+ }
++#endif  /*  0  */
+ /**
+  * qla4xxx_reset_lun - issues LUN Reset
+@@ -699,13 +773,11 @@
+        */
+       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+       memset(&mbox_sts, 0, sizeof(mbox_sts));
+-
+       mbox_cmd[0] = MBOX_CMD_LUN_RESET;
+       mbox_cmd[1] = ddb_entry->fw_ddb_index;
+       mbox_cmd[2] = lun << 8;
+       mbox_cmd[5] = 0x01;     /* Immediate Command Enable */
+-
+-      qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
++      qla4xxx_mailbox_command(ha, 6, 1, &mbox_cmd[0], &mbox_sts[0]);
+       if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
+           mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
+               status = QLA_ERROR;
+@@ -722,14 +794,12 @@
+       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+       memset(&mbox_sts, 0, sizeof(mbox_sts));
+-
+       mbox_cmd[0] = MBOX_CMD_READ_FLASH;
+       mbox_cmd[1] = LSDW(dma_addr);
+       mbox_cmd[2] = MSDW(dma_addr);
+       mbox_cmd[3] = offset;
+       mbox_cmd[4] = len;
+-
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) !=
++      if (qla4xxx_mailbox_command(ha, 5, 2, &mbox_cmd[0], &mbox_sts[0]) !=
+           QLA_SUCCESS) {
+               DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
+                   "status %04X %04X, offset %08x, len %08x\n", ha->host_no,
+@@ -755,10 +825,8 @@
+       /* Get firmware version. */
+       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+       memset(&mbox_sts, 0, sizeof(mbox_sts));
+-
+       mbox_cmd[0] = MBOX_CMD_ABOUT_FW;
+-
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) !=
++      if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
+           QLA_SUCCESS) {
+               DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ "
+                   "status %04X\n", ha->host_no, __func__, mbox_sts[0]));
+@@ -787,7 +855,7 @@
+       mbox_cmd[2] = LSDW(dma_addr);
+       mbox_cmd[3] = MSDW(dma_addr);
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) !=
++      if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
+           QLA_SUCCESS) {
+               DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
+                    ha->host_no, __func__, mbox_sts[0]));
+@@ -807,7 +875,7 @@
+       mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
+       mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES;
+-      if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
++      if (qla4xxx_mailbox_command(ha, 2, 3, &mbox_cmd[0], &mbox_sts[0]) !=
+           QLA_SUCCESS) {
+               if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) {
+                       *ddb_index = mbox_sts[2];
+@@ -850,23 +918,23 @@
+       if (ret_val != QLA_SUCCESS)
+               goto qla4xxx_send_tgts_exit;
+-      memset(fw_ddb_entry->iscsi_alias, 0,
+-             sizeof(fw_ddb_entry->iscsi_alias));
++      memset((void *)fw_ddb_entry->iSCSIAlias, 0,
++             sizeof(fw_ddb_entry->iSCSIAlias));
+-      memset(fw_ddb_entry->iscsi_name, 0,
+-             sizeof(fw_ddb_entry->iscsi_name));
++      memset((void *)fw_ddb_entry->iscsiName, 0,
++             sizeof(fw_ddb_entry->iscsiName));
+-      memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr));
+-      memset(fw_ddb_entry->tgt_addr, 0,
+-             sizeof(fw_ddb_entry->tgt_addr));
++      memset((void *)fw_ddb_entry->ipAddr, 0, sizeof(fw_ddb_entry->ipAddr));
++      memset((void *)fw_ddb_entry->targetAddr, 0,
++             sizeof(fw_ddb_entry->targetAddr));
+       fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET);
+-      fw_ddb_entry->port = cpu_to_le16(ntohs(port));
++      fw_ddb_entry->portNumber = cpu_to_le16(ntohs(port));
+-      fw_ddb_entry->ip_addr[0] = *ip;
+-      fw_ddb_entry->ip_addr[1] = *(ip + 1);
+-      fw_ddb_entry->ip_addr[2] = *(ip + 2);
+-      fw_ddb_entry->ip_addr[3] = *(ip + 3);
++      fw_ddb_entry->ipAddr[0] = *ip;
++      fw_ddb_entry->ipAddr[1] = *(ip + 1);
++      fw_ddb_entry->ipAddr[2] = *(ip + 2);
++      fw_ddb_entry->ipAddr[3] = *(ip + 3);
+       ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma);
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_nvram.c linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_nvram.c
+--- linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_nvram.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_nvram.c  2007-07-08 19:32:17.000000000 -0400
+@@ -6,9 +6,6 @@
+  */
+ #include "ql4_def.h"
+-#include "ql4_glbl.h"
+-#include "ql4_dbg.h"
+-#include "ql4_inline.h"
+ static inline void eeprom_cmd(uint32_t cmd, struct scsi_qla_host *ha)
+ {
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_os.c linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_os.c
+--- linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_os.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_os.c     2007-07-08 19:32:17.000000000 -0400
+@@ -10,10 +10,6 @@
+ #include <scsi/scsicam.h>
+ #include "ql4_def.h"
+-#include "ql4_version.h"
+-#include "ql4_glbl.h"
+-#include "ql4_dbg.h"
+-#include "ql4_inline.h"
+ /*
+  * Driver version
+@@ -54,15 +50,12 @@
+ /*
+  * iSCSI template entry points
+  */
+-static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
+-                           enum iscsi_tgt_dscvr type, uint32_t enable,
+-                           struct sockaddr *dst_addr);
++static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no,
++                           uint32_t enable, struct sockaddr *dst_addr);
+ static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
+                                 enum iscsi_param param, char *buf);
+ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
+                                 enum iscsi_param param, char *buf);
+-static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+-                                enum iscsi_host_param param, char *buf);
+ static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag);
+ static int qla4xxx_conn_start(struct iscsi_cls_conn *conn);
+ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
+@@ -102,20 +95,16 @@
+ static struct iscsi_transport qla4xxx_iscsi_transport = {
+       .owner                  = THIS_MODULE,
+       .name                   = DRIVER_NAME,
+-      .caps                   = CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD |
+-                                CAP_DATA_PATH_OFFLOAD,
+-      .param_mask             = ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+-                                ISCSI_TARGET_NAME | ISCSI_TPGT,
+-      .host_param_mask        = ISCSI_HOST_HWADDRESS |
+-                                ISCSI_HOST_IPADDRESS |
+-                                ISCSI_HOST_INITIATOR_NAME,
++      .param_mask             = ISCSI_CONN_PORT |
++                                ISCSI_CONN_ADDRESS |
++                                ISCSI_TARGET_NAME |
++                                ISCSI_TPGT,
+       .sessiondata_size       = sizeof(struct ddb_entry),
+       .host_template          = &qla4xxx_driver_template,
+       .tgt_dscvr              = qla4xxx_tgt_dscvr,
+       .get_conn_param         = qla4xxx_conn_get_param,
+       .get_session_param      = qla4xxx_sess_get_param,
+-      .get_host_param         = qla4xxx_host_get_param,
+       .start_conn             = qla4xxx_conn_start,
+       .stop_conn              = qla4xxx_conn_stop,
+       .session_recovery_timedout = qla4xxx_recovery_timedout,
+@@ -172,43 +161,6 @@
+               printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
+ }
+-static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
+-{
+-      int i;
+-      char *cp = buf;
+-
+-      for (i = 0; i < len; i++)
+-              cp += sprintf(cp, "%02x%c", addr[i],
+-                            i == (len - 1) ? '\n' : ':');
+-      return cp - buf;
+-}
+-
+-
+-static int qla4xxx_host_get_param(struct Scsi_Host *shost,
+-                                enum iscsi_host_param param, char *buf)
+-{
+-      struct scsi_qla_host *ha = to_qla_host(shost);
+-      int len;
+-
+-      switch (param) {
+-      case ISCSI_HOST_PARAM_HWADDRESS:
+-              len = format_addr(buf, ha->my_mac, MAC_ADDR_LEN);
+-              break;
+-      case ISCSI_HOST_PARAM_IPADDRESS:
+-              len = sprintf(buf, "%d.%d.%d.%d\n", ha->ip_address[0],
+-                            ha->ip_address[1], ha->ip_address[2],
+-                            ha->ip_address[3]);
+-              break;
+-      case ISCSI_HOST_PARAM_INITIATOR_NAME:
+-              len = sprintf(buf, "%s\n", ha->name_string);
+-              break;
+-      default:
+-              return -ENOSYS;
+-      }
+-
+-      return len;
+-}
+-
+ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
+                                 enum iscsi_param param, char *buf)
+ {
+@@ -256,15 +208,21 @@
+       return len;
+ }
+-static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
+-                           enum iscsi_tgt_dscvr type, uint32_t enable,
+-                           struct sockaddr *dst_addr)
++static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no,
++                           uint32_t enable, struct sockaddr *dst_addr)
+ {
+       struct scsi_qla_host *ha;
++      struct Scsi_Host *shost;
+       struct sockaddr_in *addr;
+       struct sockaddr_in6 *addr6;
+       int ret = 0;
++      shost = scsi_host_lookup(host_no);
++      if (IS_ERR(shost)) {
++              printk(KERN_ERR "Could not find host no %u\n", host_no);
++              return -ENODEV;
 +      }
 +
-+      hidden_dentry = unionfs_lower_dentry(dentry);
+       ha = (struct scsi_qla_host *) shost->hostdata;
+       switch (type) {
+@@ -288,6 +246,8 @@
+       default:
+               ret = -ENOSYS;
+       }
 +
-+      err = vfs_removexattr(hidden_dentry, (char*) name);
++      scsi_host_put(shost);
+       return ret;
+ }
+@@ -409,7 +369,14 @@
+       struct scsi_cmnd *cmd = srb->cmd;
+       if (srb->flags & SRB_DMA_VALID) {
+-              scsi_dma_unmap(cmd);
++              if (cmd->use_sg) {
++                      pci_unmap_sg(ha->pdev, cmd->request_buffer,
++                                   cmd->use_sg, cmd->sc_data_direction);
++              } else if (cmd->request_bufflen) {
++                      pci_unmap_single(ha->pdev, srb->dma_handle,
++                                       cmd->request_bufflen,
++                                       cmd->sc_data_direction);
++              }
+               srb->flags &= ~SRB_DMA_VALID;
+       }
+       cmd->SCp.ptr = NULL;
+@@ -744,7 +711,7 @@
+       return stat;
+ }
+-void qla4xxx_hw_reset(struct scsi_qla_host *ha)
++static void qla4xxx_hw_reset(struct scsi_qla_host *ha)
+ {
+       uint32_t ctrl_status;
+       unsigned long flags = 0;
+@@ -1114,13 +1081,13 @@
+       if (ha->timer_active)
+               qla4xxx_stop_timer(ha);
++      /* free extra memory */
++      qla4xxx_mem_free(ha);
 +
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
+       /* Detach interrupts */
+       if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags))
+               free_irq(ha->pdev->irq, ha);
+-      /* free extra memory */
+-      qla4xxx_mem_free(ha);
+-
+       pci_disable_device(ha->pdev);
+ }
+@@ -1365,11 +1332,6 @@
+       ha = pci_get_drvdata(pdev);
+-      qla4xxx_disable_intrs(ha);
+-
+-      while (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags))
+-              ssleep(1);
+-
+       /* remove devs from iscsi_sessions to scsi_devices */
+       qla4xxx_free_ddb_list(ha);
+diff -Nurb linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_version.h linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_version.h
+--- linux-2.6.22-590/drivers/scsi/qla4xxx/ql4_version.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qla4xxx/ql4_version.h        2007-07-08 19:32:17.000000000 -0400
+@@ -5,5 +5,4 @@
+  * See LICENSE.qla4xxx for copyright and licensing details.
+  */
+-#define QLA4XXX_DRIVER_VERSION        "5.01.00-k7"
+-
++#define QLA4XXX_DRIVER_VERSION        "5.00.07-k1"
+diff -Nurb linux-2.6.22-590/drivers/scsi/qlogicfas408.c linux-2.6.22-570/drivers/scsi/qlogicfas408.c
+--- linux-2.6.22-590/drivers/scsi/qlogicfas408.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/qlogicfas408.c       2007-07-08 19:32:17.000000000 -0400
+@@ -265,6 +265,8 @@
+       unsigned int message;   /* scsi returned message */
+       unsigned int phase;     /* recorded scsi phase */
+       unsigned int reqlen;    /* total length of transfer */
++      struct scatterlist *sglist;     /* scatter-gather list pointer */
++      unsigned int sgcount;   /* sg counter */
+       char *buf;
+       struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
+       int qbase = priv->qbase;
+@@ -299,10 +301,9 @@
+       if (inb(qbase + 7) & 0x1f)      /* if some bytes in fifo */
+               outb(1, qbase + 3);     /* clear fifo */
+       /* note that request_bufflen is the total xfer size when sg is used */
+-      reqlen = scsi_bufflen(cmd);
++      reqlen = cmd->request_bufflen;
+       /* note that it won't work if transfers > 16M are requested */
+       if (reqlen && !((phase = inb(qbase + 4)) & 6)) {        /* data phase */
+-              struct scatterlist *sg;
+               rtrc(2)
+               outb(reqlen, qbase);    /* low-mid xfer cnt */
+               outb(reqlen >> 8, qbase + 1);   /* low-mid xfer cnt */
+@@ -310,16 +311,23 @@
+               outb(0x90, qbase + 3);  /* command do xfer */
+               /* PIO pseudo DMA to buffer or sglist */
+               REG1;
+-
+-              scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) {
++              if (!cmd->use_sg)
++                      ql_pdma(priv, phase, cmd->request_buffer,
++                              cmd->request_bufflen);
++              else {
++                      sgcount = cmd->use_sg;
++                      sglist = cmd->request_buffer;
++                      while (sgcount--) {
+                               if (priv->qabort) {
+                                       REG0;
+                                       return ((priv->qabort == 1 ?
+                                               DID_ABORT : DID_RESET) << 16);
+                               }
+-                      buf = page_address(sg->page) + sg->offset;
+-                      if (ql_pdma(priv, phase, buf, sg->length))
++                              buf = page_address(sglist->page) + sglist->offset;
++                              if (ql_pdma(priv, phase, buf, sglist->length))
+                                       break;
++                              sglist++;
++                      }
+               }
+               REG0;
+               rtrc(2)
+diff -Nurb linux-2.6.22-590/drivers/scsi/scsi_debug.c linux-2.6.22-570/drivers/scsi/scsi_debug.c
+--- linux-2.6.22-590/drivers/scsi/scsi_debug.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/scsi_debug.c 2007-07-08 19:32:17.000000000 -0400
+@@ -2405,7 +2405,7 @@
+ MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
+ MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)");
+ MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
+-MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
++MODULE_PARM_DESC(every_nth, "timeout every nth command(def=100)");
+ MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
+ MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
+ MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
+diff -Nurb linux-2.6.22-590/drivers/scsi/scsi_error.c linux-2.6.22-570/drivers/scsi/scsi_error.c
+--- linux-2.6.22-590/drivers/scsi/scsi_error.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/scsi_error.c 2007-07-08 19:32:17.000000000 -0400
+@@ -18,13 +18,12 @@
+ #include <linux/sched.h>
+ #include <linux/timer.h>
+ #include <linux/string.h>
++#include <linux/slab.h>
+ #include <linux/kernel.h>
+-#include <linux/freezer.h>
+ #include <linux/kthread.h>
+ #include <linux/interrupt.h>
+ #include <linux/blkdev.h>
+ #include <linux/delay.h>
+-#include <linux/scatterlist.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
+@@ -641,8 +640,16 @@
+       memcpy(scmd->cmnd, cmnd, cmnd_size);
+       if (copy_sense) {
+-              sg_init_one(&sgl, scmd->sense_buffer,
+-                          sizeof(scmd->sense_buffer));
++              gfp_t gfp_mask = GFP_ATOMIC;
++
++              if (shost->hostt->unchecked_isa_dma)
++                      gfp_mask |= __GFP_DMA;
++
++              sgl.page = alloc_page(gfp_mask);
++              if (!sgl.page)
++                      return FAILED;
++              sgl.offset = 0;
++              sgl.length = 252;
+               scmd->sc_data_direction = DMA_FROM_DEVICE;
+               scmd->request_bufflen = sgl.length;
+@@ -713,6 +720,18 @@
+       /*
++       * Last chance to have valid sense data.
++       */
++      if (copy_sense) {
++              if (!SCSI_SENSE_VALID(scmd)) {
++                      memcpy(scmd->sense_buffer, page_address(sgl.page),
++                             sizeof(scmd->sense_buffer));
++              }
++              __free_page(sgl.page);
++      }
 +
-+/*
-+ * BKL held by caller.
-+ * dentry->d_inode->i_mutex locked
-+ */
-+ssize_t unionfs_listxattr(struct dentry *dentry, char *list, size_t size)
-+{
-+      struct dentry *hidden_dentry = NULL;
-+      int err = -EOPNOTSUPP;
-+      char *encoded_list = NULL;
 +
-+      unionfs_read_lock(dentry->d_sb);
-+      unionfs_lock_dentry(dentry);
++      /*
+        * Restore original data
+        */
+       scmd->request_buffer = old_buffer;
+@@ -1517,6 +1536,8 @@
+ {
+       struct Scsi_Host *shost = data;
++      current->flags |= PF_NOFREEZE;
 +
-+      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
-+              err = -ESTALE;
-+              goto out;
+       /*
+        * We use TASK_INTERRUPTIBLE so that the thread is not
+        * counted against the load average as a running process.
+diff -Nurb linux-2.6.22-590/drivers/scsi/scsi_lib.c linux-2.6.22-570/drivers/scsi/scsi_lib.c
+--- linux-2.6.22-590/drivers/scsi/scsi_lib.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/scsi_lib.c   2007-07-08 19:32:17.000000000 -0400
+@@ -2290,41 +2290,3 @@
+       kunmap_atomic(virt, KM_BIO_SRC_IRQ);
+ }
+ EXPORT_SYMBOL(scsi_kunmap_atomic_sg);
+-
+-/**
+- * scsi_dma_map - perform DMA mapping against command's sg lists
+- * @cmd:      scsi command
+- *
+- * Returns the number of sg lists actually used, zero if the sg lists
+- * is NULL, or -ENOMEM if the mapping failed.
+- */
+-int scsi_dma_map(struct scsi_cmnd *cmd)
+-{
+-      int nseg = 0;
+-
+-      if (scsi_sg_count(cmd)) {
+-              struct device *dev = cmd->device->host->shost_gendev.parent;
+-
+-              nseg = dma_map_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
+-                                cmd->sc_data_direction);
+-              if (unlikely(!nseg))
+-                      return -ENOMEM;
+-      }
+-      return nseg;
+-}
+-EXPORT_SYMBOL(scsi_dma_map);
+-
+-/**
+- * scsi_dma_unmap - unmap command's sg lists mapped by scsi_dma_map
+- * @cmd:      scsi command
+- */
+-void scsi_dma_unmap(struct scsi_cmnd *cmd)
+-{
+-      if (scsi_sg_count(cmd)) {
+-              struct device *dev = cmd->device->host->shost_gendev.parent;
+-
+-              dma_unmap_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
+-                           cmd->sc_data_direction);
+-      }
+-}
+-EXPORT_SYMBOL(scsi_dma_unmap);
+diff -Nurb linux-2.6.22-590/drivers/scsi/scsi_netlink.c linux-2.6.22-570/drivers/scsi/scsi_netlink.c
+--- linux-2.6.22-590/drivers/scsi/scsi_netlink.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/scsi_netlink.c       2007-07-08 19:32:17.000000000 -0400
+@@ -167,7 +167,7 @@
+               return;
+       }
+-      scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT,
++      scsi_nl_sock = netlink_kernel_create(NETLINK_SCSITRANSPORT,
+                               SCSI_NL_GRP_CNT, scsi_nl_rcv, NULL,
+                               THIS_MODULE);
+       if (!scsi_nl_sock) {
+diff -Nurb linux-2.6.22-590/drivers/scsi/scsi_scan.c linux-2.6.22-570/drivers/scsi/scsi_scan.c
+--- linux-2.6.22-590/drivers/scsi/scsi_scan.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/scsi_scan.c  2007-07-08 19:32:17.000000000 -0400
+@@ -1213,7 +1213,7 @@
+  *     Given a struct scsi_lun of: 0a 04 0b 03 00 00 00 00, this function returns
+  *     the integer: 0x0b030a04
+  **/
+-int scsilun_to_int(struct scsi_lun *scsilun)
++static int scsilun_to_int(struct scsi_lun *scsilun)
+ {
+       int i;
+       unsigned int lun;
+@@ -1224,7 +1224,6 @@
+                             scsilun->scsi_lun[i + 1]) << (i * 8));
+       return lun;
+ }
+-EXPORT_SYMBOL(scsilun_to_int);
+ /**
+  * int_to_scsilun: reverts an int into a scsi_lun
+diff -Nurb linux-2.6.22-590/drivers/scsi/scsi_sysfs.c linux-2.6.22-570/drivers/scsi/scsi_sysfs.c
+--- linux-2.6.22-590/drivers/scsi/scsi_sysfs.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/scsi_sysfs.c 2007-07-08 19:32:17.000000000 -0400
+@@ -293,18 +293,30 @@
+ {
+       struct device_driver *drv = dev->driver;
+       struct scsi_device *sdev = to_scsi_device(dev);
++      struct scsi_host_template *sht = sdev->host->hostt;
+       int err;
+       err = scsi_device_quiesce(sdev);
+       if (err)
+               return err;
++      /* call HLD suspend first */
+       if (drv && drv->suspend) {
+               err = drv->suspend(dev, state);
+               if (err)
+                       return err;
+       }
++      /* then, call host suspend */
++      if (sht->suspend) {
++              err = sht->suspend(sdev, state);
++              if (err) {
++                      if (drv && drv->resume)
++                              drv->resume(dev);
++                      return err;
++              }
 +      }
 +
-+      hidden_dentry = unionfs_lower_dentry(dentry);
+       return 0;
+ }
+@@ -312,14 +324,21 @@
+ {
+       struct device_driver *drv = dev->driver;
+       struct scsi_device *sdev = to_scsi_device(dev);
+-      int err = 0;
++      struct scsi_host_template *sht = sdev->host->hostt;
++      int err = 0, err2 = 0;
++      /* call host resume first */
++      if (sht->resume)
++              err = sht->resume(sdev);
 +
-+      encoded_list = list;
-+      err = vfs_listxattr(hidden_dentry, encoded_list, size);
++      /* then, call HLD resume */
+       if (drv && drv->resume)
+-              err = drv->resume(dev);
++              err2 = drv->resume(dev);
+       scsi_device_resume(sdev);
+-      return err;
++      /* favor LLD failure */
++      return err ? err : err2;;
+ }
+ struct bus_type scsi_bus_type = {
+diff -Nurb linux-2.6.22-590/drivers/scsi/scsi_transport_fc.c linux-2.6.22-570/drivers/scsi/scsi_transport_fc.c
+--- linux-2.6.22-590/drivers/scsi/scsi_transport_fc.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/scsi_transport_fc.c  2007-07-08 19:32:17.000000000 -0400
+@@ -19,10 +19,9 @@
+  *
+  *  ========
+  *
+- *  Copyright (C) 2004-2007   James Smart, Emulex Corporation
++ *  Copyright (C) 2004-2005   James Smart, Emulex Corporation
+  *    Rewrite for host, target, device, and remote port attributes,
+  *    statistics, and service functions...
+- *    Add vports, etc
+  *
+  */
+ #include <linux/module.h>
+@@ -38,34 +37,6 @@
+ #include "scsi_priv.h"
+ static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
+-static void fc_vport_sched_delete(struct work_struct *work);
+-
+-/*
+- * This is a temporary carrier for creating a vport. It will eventually
+- * be replaced  by a real message definition for sgio or netlink.
+- *
+- * fc_vport_identifiers: This set of data contains all elements
+- * to uniquely identify and instantiate a FC virtual port.
+- *
+- * Notes:
+- *   symbolic_name: The driver is to append the symbolic_name string data
+- *      to the symbolic_node_name data that it generates by default.
+- *      the resulting combination should then be registered with the switch.
+- *      It is expected that things like Xen may stuff a VM title into
+- *      this field.
+- */
+-struct fc_vport_identifiers {
+-      u64 node_name;
+-      u64 port_name;
+-      u32 roles;
+-      bool disable;
+-      enum fc_port_type vport_type;   /* only FC_PORTTYPE_NPIV allowed */
+-      char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
+-};
+-
+-static int fc_vport_create(struct Scsi_Host *shost, int channel,
+-      struct device *pdev, struct fc_vport_identifiers  *ids,
+-      struct fc_vport **vport);
+ /*
+  * Redefine so that we can have same named attributes in the
+@@ -119,14 +90,10 @@
+       { FC_PORTTYPE_NLPORT,   "NLPort (fabric via loop)" },
+       { FC_PORTTYPE_LPORT,    "LPort (private loop)" },
+       { FC_PORTTYPE_PTP,      "Point-To-Point (direct nport connection" },
+-      { FC_PORTTYPE_NPIV,             "NPIV VPORT" },
+ };
+ fc_enum_name_search(port_type, fc_port_type, fc_port_type_names)
+ #define FC_PORTTYPE_MAX_NAMELEN               50
+-/* Reuse fc_port_type enum function for vport_type */
+-#define get_fc_vport_type_name get_fc_port_type_name
+-
+ /* Convert fc_host_event_code values to ascii string name */
+ static const struct {
+@@ -172,29 +139,6 @@
+ #define FC_PORTSTATE_MAX_NAMELEN      20
+-/* Convert fc_vport_state values to ascii string name */
+-static struct {
+-      enum fc_vport_state     value;
+-      char                    *name;
+-} fc_vport_state_names[] = {
+-      { FC_VPORT_UNKNOWN,             "Unknown" },
+-      { FC_VPORT_ACTIVE,              "Active" },
+-      { FC_VPORT_DISABLED,            "Disabled" },
+-      { FC_VPORT_LINKDOWN,            "Linkdown" },
+-      { FC_VPORT_INITIALIZING,        "Initializing" },
+-      { FC_VPORT_NO_FABRIC_SUPP,      "No Fabric Support" },
+-      { FC_VPORT_NO_FABRIC_RSCS,      "No Fabric Resources" },
+-      { FC_VPORT_FABRIC_LOGOUT,       "Fabric Logout" },
+-      { FC_VPORT_FABRIC_REJ_WWN,      "Fabric Rejected WWN" },
+-      { FC_VPORT_FAILED,              "VPort Failed" },
+-};
+-fc_enum_name_search(vport_state, fc_vport_state, fc_vport_state_names)
+-#define FC_VPORTSTATE_MAX_NAMELEN     24
+-
+-/* Reuse fc_vport_state enum function for vport_last_state */
+-#define get_fc_vport_last_state_name get_fc_vport_state_name
+-
+-
+ /* Convert fc_tgtid_binding_type values to ascii string name */
+ static const struct {
+       enum fc_tgtid_binding_type      value;
+@@ -275,16 +219,16 @@
+ }
+-/* Convert FC_PORT_ROLE bit values to ascii string name */
++/* Convert FC_RPORT_ROLE bit values to ascii string name */
+ static const struct {
+       u32                     value;
+       char                    *name;
+-} fc_port_role_names[] = {
+-      { FC_PORT_ROLE_FCP_TARGET,      "FCP Target" },
+-      { FC_PORT_ROLE_FCP_INITIATOR,   "FCP Initiator" },
+-      { FC_PORT_ROLE_IP_PORT,         "IP Port" },
++} fc_remote_port_role_names[] = {
++      { FC_RPORT_ROLE_FCP_TARGET,     "FCP Target" },
++      { FC_RPORT_ROLE_FCP_INITIATOR,  "FCP Initiator" },
++      { FC_RPORT_ROLE_IP_PORT,        "IP Port" },
+ };
+-fc_bitfield_name_search(port_roles, fc_port_role_names)
++fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
+ /*
+  * Define roles that are specific to port_id. Values are relative to ROLE_MASK.
+@@ -308,8 +252,7 @@
+  */
+ #define FC_STARGET_NUM_ATTRS  3
+ #define FC_RPORT_NUM_ATTRS    10
+-#define FC_VPORT_NUM_ATTRS    9
+-#define FC_HOST_NUM_ATTRS     21
++#define FC_HOST_NUM_ATTRS     17
+ struct fc_internal {
+       struct scsi_transport_template t;
+@@ -335,10 +278,6 @@
+       struct transport_container rport_attr_cont;
+       struct class_device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS];
+       struct class_device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1];
+-
+-      struct transport_container vport_attr_cont;
+-      struct class_device_attribute private_vport_attrs[FC_VPORT_NUM_ATTRS];
+-      struct class_device_attribute *vport_attrs[FC_VPORT_NUM_ATTRS + 1];
+ };
+ #define to_fc_internal(tmpl)  container_of(tmpl, struct fc_internal, t)
+@@ -392,7 +331,6 @@
+               sizeof(fc_host->supported_fc4s));
+       fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN;
+       fc_host->maxframe_size = -1;
+-      fc_host->max_npiv_vports = 0;
+       memset(fc_host->serial_number, 0,
+               sizeof(fc_host->serial_number));
+@@ -410,11 +348,8 @@
+       INIT_LIST_HEAD(&fc_host->rports);
+       INIT_LIST_HEAD(&fc_host->rport_bindings);
+-      INIT_LIST_HEAD(&fc_host->vports);
+       fc_host->next_rport_number = 0;
+       fc_host->next_target_id = 0;
+-      fc_host->next_vport_number = 0;
+-      fc_host->npiv_vports_inuse = 0;
+       snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d",
+               shost->host_no);
+@@ -453,16 +388,6 @@
+                              NULL);
+ /*
+- * Setup and Remove actions for virtual ports are handled
+- * in the service functions below.
+- */
+-static DECLARE_TRANSPORT_CLASS(fc_vport_class,
+-                             "fc_vports",
+-                             NULL,
+-                             NULL,
+-                             NULL);
+-
+-/*
+  * Module Parameters
+  */
+@@ -660,9 +585,6 @@
+       error = transport_class_register(&fc_host_class);
+       if (error)
+               return error;
+-      error = transport_class_register(&fc_vport_class);
+-      if (error)
+-              return error;
+       error = transport_class_register(&fc_rport_class);
+       if (error)
+               return error;
+@@ -674,7 +596,6 @@
+       transport_class_unregister(&fc_transport_class);
+       transport_class_unregister(&fc_rport_class);
+       transport_class_unregister(&fc_host_class);
+-      transport_class_unregister(&fc_vport_class);
+ }
+ /*
+@@ -879,9 +800,9 @@
+                       return snprintf(buf, 30, "Unknown Fabric Entity\n");
+               }
+       } else {
+-              if (rport->roles == FC_PORT_ROLE_UNKNOWN)
++              if (rport->roles == FC_RPORT_ROLE_UNKNOWN)
+                       return snprintf(buf, 20, "unknown\n");
+-              return get_fc_port_roles_names(rport->roles, buf);
++              return get_fc_remote_port_roles_names(rport->roles, buf);
+       }
+ }
+ static FC_CLASS_DEVICE_ATTR(rport, roles, S_IRUGO,
+@@ -936,7 +857,7 @@
+ /*
+  * Note: in the target show function we recognize when the remote
+- *  port is in the heirarchy and do not allow the driver to get
++ *  port is in the hierarchy and do not allow the driver to get
+  *  involved in sysfs functions. The driver only gets involved if
+  *  it's the "old" style that doesn't use rports.
+  */
+@@ -991,257 +912,6 @@
+ /*
+- * FC Virtual Port Attribute Management
+- */
+-
+-#define fc_vport_show_function(field, format_string, sz, cast)                \
+-static ssize_t                                                                \
+-show_fc_vport_##field (struct class_device *cdev, char *buf)          \
+-{                                                                     \
+-      struct fc_vport *vport = transport_class_to_vport(cdev);        \
+-      struct Scsi_Host *shost = vport_to_shost(vport);                \
+-      struct fc_internal *i = to_fc_internal(shost->transportt);      \
+-      if ((i->f->get_vport_##field) &&                                \
+-          !(vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)))       \
+-              i->f->get_vport_##field(vport);                         \
+-      return snprintf(buf, sz, format_string, cast vport->field);     \
+-}
+-
+-#define fc_vport_store_function(field)                                        \
+-static ssize_t                                                                \
+-store_fc_vport_##field(struct class_device *cdev, const char *buf,    \
+-                         size_t count)                                \
+-{                                                                     \
+-      int val;                                                        \
+-      struct fc_vport *vport = transport_class_to_vport(cdev);        \
+-      struct Scsi_Host *shost = vport_to_shost(vport);                \
+-      struct fc_internal *i = to_fc_internal(shost->transportt);      \
+-      char *cp;                                                       \
+-      if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))  \
+-              return -EBUSY;                                          \
+-      val = simple_strtoul(buf, &cp, 0);                              \
+-      if (*cp && (*cp != '\n'))                                       \
+-              return -EINVAL;                                         \
+-      i->f->set_vport_##field(vport, val);                            \
+-      return count;                                                   \
+-}
+-
+-#define fc_vport_store_str_function(field, slen)                      \
+-static ssize_t                                                                \
+-store_fc_vport_##field(struct class_device *cdev, const char *buf,    \
+-                         size_t count)                                \
+-{                                                                     \
+-      struct fc_vport *vport = transport_class_to_vport(cdev);        \
+-      struct Scsi_Host *shost = vport_to_shost(vport);                \
+-      struct fc_internal *i = to_fc_internal(shost->transportt);      \
+-      unsigned int cnt=count;                                         \
+-                                                                      \
+-      /* count may include a LF at end of string */                   \
+-      if (buf[cnt-1] == '\n')                                         \
+-              cnt--;                                                  \
+-      if (cnt > ((slen) - 1))                                         \
+-              return -EINVAL;                                         \
+-      memcpy(vport->field, buf, cnt);                                 \
+-      i->f->set_vport_##field(vport);                                 \
+-      return count;                                                   \
+-}
+-
+-#define fc_vport_rd_attr(field, format_string, sz)                    \
+-      fc_vport_show_function(field, format_string, sz, )              \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,                    \
+-                       show_fc_vport_##field, NULL)
+-
+-#define fc_vport_rd_attr_cast(field, format_string, sz, cast)         \
+-      fc_vport_show_function(field, format_string, sz, (cast))        \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,                    \
+-                        show_fc_vport_##field, NULL)
+-
+-#define fc_vport_rw_attr(field, format_string, sz)                    \
+-      fc_vport_show_function(field, format_string, sz, )              \
+-      fc_vport_store_function(field)                                  \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,          \
+-                      show_fc_vport_##field,                          \
+-                      store_fc_vport_##field)
+-
+-#define fc_private_vport_show_function(field, format_string, sz, cast)        \
+-static ssize_t                                                                \
+-show_fc_vport_##field (struct class_device *cdev, char *buf)          \
+-{                                                                     \
+-      struct fc_vport *vport = transport_class_to_vport(cdev);        \
+-      return snprintf(buf, sz, format_string, cast vport->field);     \
+-}
+-
+-#define fc_private_vport_store_u32_function(field)                    \
+-static ssize_t                                                                \
+-store_fc_vport_##field(struct class_device *cdev, const char *buf,    \
+-                         size_t count)                                \
+-{                                                                     \
+-      u32 val;                                                        \
+-      struct fc_vport *vport = transport_class_to_vport(cdev);        \
+-      char *cp;                                                       \
+-      if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))          \
+-              return -EBUSY;                                          \
+-      val = simple_strtoul(buf, &cp, 0);                              \
+-      if (*cp && (*cp != '\n'))                                       \
+-              return -EINVAL;                                         \
+-      vport->field = val;                                             \
+-      return count;                                                   \
+-}
+-
+-
+-#define fc_private_vport_rd_attr(field, format_string, sz)            \
+-      fc_private_vport_show_function(field, format_string, sz, )      \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,                    \
+-                       show_fc_vport_##field, NULL)
+-
+-#define fc_private_vport_rd_attr_cast(field, format_string, sz, cast) \
+-      fc_private_vport_show_function(field, format_string, sz, (cast)) \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,                    \
+-                        show_fc_vport_##field, NULL)
+-
+-#define fc_private_vport_rw_u32_attr(field, format_string, sz)                \
+-      fc_private_vport_show_function(field, format_string, sz, )      \
+-      fc_private_vport_store_u32_function(field)                      \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,          \
+-                      show_fc_vport_##field,                          \
+-                      store_fc_vport_##field)
+-
+-
+-#define fc_private_vport_rd_enum_attr(title, maxlen)                  \
+-static ssize_t                                                                \
+-show_fc_vport_##title (struct class_device *cdev, char *buf)          \
+-{                                                                     \
+-      struct fc_vport *vport = transport_class_to_vport(cdev);        \
+-      const char *name;                                               \
+-      name = get_fc_##title##_name(vport->title);                     \
+-      if (!name)                                                      \
+-              return -EINVAL;                                         \
+-      return snprintf(buf, maxlen, "%s\n", name);                     \
+-}                                                                     \
+-static FC_CLASS_DEVICE_ATTR(vport, title, S_IRUGO,                    \
+-                      show_fc_vport_##title, NULL)
+-
+-
+-#define SETUP_VPORT_ATTRIBUTE_RD(field)                                       \
+-      i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+-      i->private_vport_attrs[count].attr.mode = S_IRUGO;              \
+-      i->private_vport_attrs[count].store = NULL;                     \
+-      i->vport_attrs[count] = &i->private_vport_attrs[count];         \
+-      if (i->f->get_##field)                                          \
+-              count++
+-      /* NOTE: Above MACRO differs: checks function not show bit */
+-
+-#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(field)                               \
+-      i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+-      i->private_vport_attrs[count].attr.mode = S_IRUGO;              \
+-      i->private_vport_attrs[count].store = NULL;                     \
+-      i->vport_attrs[count] = &i->private_vport_attrs[count];         \
+-      count++
+-
+-#define SETUP_VPORT_ATTRIBUTE_WR(field)                                       \
+-      i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+-      i->vport_attrs[count] = &i->private_vport_attrs[count];         \
+-      if (i->f->field)                                                \
+-              count++
+-      /* NOTE: Above MACRO differs: checks function */
+-
+-#define SETUP_VPORT_ATTRIBUTE_RW(field)                                       \
+-      i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+-      if (!i->f->set_vport_##field) {                                 \
+-              i->private_vport_attrs[count].attr.mode = S_IRUGO;      \
+-              i->private_vport_attrs[count].store = NULL;             \
+-      }                                                               \
+-      i->vport_attrs[count] = &i->private_vport_attrs[count];         \
+-      count++
+-      /* NOTE: Above MACRO differs: does not check show bit */
+-
+-#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RW(field)                               \
+-{                                                                     \
+-      i->private_vport_attrs[count] = class_device_attr_vport_##field; \
+-      i->vport_attrs[count] = &i->private_vport_attrs[count];         \
+-      count++;                                                        \
+-}
+-
+-
+-/* The FC Transport Virtual Port Attributes: */
+-
+-/* Fixed Virtual Port Attributes */
+-
+-/* Dynamic Virtual Port Attributes */
+-
+-/* Private Virtual Port Attributes */
+-
+-fc_private_vport_rd_enum_attr(vport_state, FC_VPORTSTATE_MAX_NAMELEN);
+-fc_private_vport_rd_enum_attr(vport_last_state, FC_VPORTSTATE_MAX_NAMELEN);
+-fc_private_vport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
+-fc_private_vport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+-
+-static ssize_t
+-show_fc_vport_roles (struct class_device *cdev, char *buf)
+-{
+-      struct fc_vport *vport = transport_class_to_vport(cdev);
+-
+-      if (vport->roles == FC_PORT_ROLE_UNKNOWN)
+-              return snprintf(buf, 20, "unknown\n");
+-      return get_fc_port_roles_names(vport->roles, buf);
+-}
+-static FC_CLASS_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL);
+-
+-fc_private_vport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN);
+-
+-fc_private_vport_show_function(symbolic_name, "%s\n",
+-              FC_VPORT_SYMBOLIC_NAMELEN + 1, )
+-fc_vport_store_str_function(symbolic_name, FC_VPORT_SYMBOLIC_NAMELEN)
+-static FC_CLASS_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR,
+-              show_fc_vport_symbolic_name, store_fc_vport_symbolic_name);
+-
+-static ssize_t
+-store_fc_vport_delete(struct class_device *cdev, const char *buf,
+-                         size_t count)
+-{
+-      struct fc_vport *vport = transport_class_to_vport(cdev);
+-      struct Scsi_Host *shost = vport_to_shost(vport);
+-
+-      fc_queue_work(shost, &vport->vport_delete_work);
+-      return count;
+-}
+-static FC_CLASS_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
+-                      NULL, store_fc_vport_delete);
+-
+-
+-/*
+- * Enable/Disable vport
+- *  Write "1" to disable, write "0" to enable
+- */
+-static ssize_t
+-store_fc_vport_disable(struct class_device *cdev, const char *buf,
+-                         size_t count)
+-{
+-      struct fc_vport *vport = transport_class_to_vport(cdev);
+-      struct Scsi_Host *shost = vport_to_shost(vport);
+-      struct fc_internal *i = to_fc_internal(shost->transportt);
+-      int stat;
+-
+-      if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))
+-              return -EBUSY;
+-
+-      if (*buf == '0') {
+-              if (vport->vport_state != FC_VPORT_DISABLED)
+-                      return -EALREADY;
+-      } else if (*buf == '1') {
+-              if (vport->vport_state == FC_VPORT_DISABLED)
+-                      return -EALREADY;
+-      } else
+-              return -EINVAL;
+-
+-      stat = i->f->vport_disable(vport, ((*buf == '0') ? false : true));
+-      return stat ? stat : count;
+-}
+-static FC_CLASS_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
+-                      NULL, store_fc_vport_disable);
+-
+-
+-/*
+  * Host Attribute Management
+  */
+@@ -1333,13 +1003,6 @@
+       if (i->f->show_host_##field)                                    \
+               count++
+-#define SETUP_HOST_ATTRIBUTE_RD_NS(field)                             \
+-      i->private_host_attrs[count] = class_device_attr_host_##field;  \
+-      i->private_host_attrs[count].attr.mode = S_IRUGO;               \
+-      i->private_host_attrs[count].store = NULL;                      \
+-      i->host_attrs[count] = &i->private_host_attrs[count];           \
+-      count++
+-
+ #define SETUP_HOST_ATTRIBUTE_RW(field)                                        \
+       i->private_host_attrs[count] = class_device_attr_host_##field;  \
+       if (!i->f->set_host_##field) {                                  \
+@@ -1427,7 +1090,6 @@
+ fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20,
+                            unsigned long long);
+ fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
+-fc_private_host_rd_attr(max_npiv_vports, "%u\n", 20);
+ fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
+@@ -1548,9 +1210,6 @@
+ static FC_CLASS_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
+                       store_fc_private_host_issue_lip);
+-fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
+-
+-
+ /*
+  * Host Statistics Management
+  */
+@@ -1626,6 +1285,7 @@
+ static FC_CLASS_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL,
+                               fc_reset_statistics);
 +
-+out:
-+      unionfs_unlock_dentry(dentry);
-+      unionfs_read_unlock(dentry->d_sb);
-+      return err;
-+}
-diff -Nurb linux-2.6.22-570/fs/xfs/linux-2.6/xfs_file.c linux-2.6.22-590/fs/xfs/linux-2.6/xfs_file.c
---- linux-2.6.22-570/fs/xfs/linux-2.6/xfs_file.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/fs/xfs/linux-2.6/xfs_file.c       2008-01-02 13:56:37.000000000 -0500
-@@ -246,18 +246,19 @@
+ static struct attribute *fc_statistics_attrs[] = {
+       &class_device_attr_host_seconds_since_last_reset.attr,
+       &class_device_attr_host_tx_frames.attr,
+@@ -1656,142 +1316,6 @@
+       .attrs = fc_statistics_attrs,
+ };
  
- #ifdef CONFIG_XFS_DMAPI
- STATIC struct page *
--xfs_vm_nopage(
--      struct vm_area_struct   *area,
--      unsigned long           address,
--      int                     *type)
-+xfs_vm_fault(
-+      struct vm_area_struct   *vma,
-+      struct fault_data       *fdata)
- {
--      struct inode    *inode = area->vm_file->f_path.dentry->d_inode;
-+      struct inode    *inode = vma->vm_file->f_path.dentry->d_inode;
-       bhv_vnode_t     *vp = vn_from_inode(inode);
+-
+-/* Host Vport Attributes */
+-
+-static int
+-fc_parse_wwn(const char *ns, u64 *nm)
+-{
+-      unsigned int i, j;
+-      u8 wwn[8];
+-
+-      memset(wwn, 0, sizeof(wwn));
+-
+-      /* Validate and store the new name */
+-      for (i=0, j=0; i < 16; i++) {
+-              if ((*ns >= 'a') && (*ns <= 'f'))
+-                      j = ((j << 4) | ((*ns++ -'a') + 10));
+-              else if ((*ns >= 'A') && (*ns <= 'F'))
+-                      j = ((j << 4) | ((*ns++ -'A') + 10));
+-              else if ((*ns >= '0') && (*ns <= '9'))
+-                      j = ((j << 4) | (*ns++ -'0'));
+-              else
+-                      return -EINVAL;
+-              if (i % 2) {
+-                      wwn[i/2] = j & 0xff;
+-                      j = 0;
+-              }
+-      }
+-
+-      *nm = wwn_to_u64(wwn);
+-
+-      return 0;
+-}
+-
+-
+-/*
+- * "Short-cut" sysfs variable to create a new vport on a FC Host.
+- * Input is a string of the form "<WWPN>:<WWNN>". Other attributes
+- * will default to a NPIV-based FCP_Initiator; The WWNs are specified
+- * as hex characters, and may *not* contain any prefixes (e.g. 0x, x, etc)
+- */
+-static ssize_t
+-store_fc_host_vport_create(struct class_device *cdev, const char *buf,
+-                         size_t count)
+-{
+-      struct Scsi_Host *shost = transport_class_to_shost(cdev);
+-      struct fc_vport_identifiers vid;
+-      struct fc_vport *vport;
+-      unsigned int cnt=count;
+-      int stat;
+-
+-      memset(&vid, 0, sizeof(vid));
+-
+-      /* count may include a LF at end of string */
+-      if (buf[cnt-1] == '\n')
+-              cnt--;
+-
+-      /* validate we have enough characters for WWPN */
+-      if ((cnt != (16+1+16)) || (buf[16] != ':'))
+-              return -EINVAL;
+-
+-      stat = fc_parse_wwn(&buf[0], &vid.port_name);
+-      if (stat)
+-              return stat;
+-
+-      stat = fc_parse_wwn(&buf[17], &vid.node_name);
+-      if (stat)
+-              return stat;
+-
+-      vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
+-      vid.vport_type = FC_PORTTYPE_NPIV;
+-      /* vid.symbolic_name is already zero/NULL's */
+-      vid.disable = false;            /* always enabled */
+-
+-      /* we only allow support on Channel 0 !!! */
+-      stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport);
+-      return stat ? stat : count;
+-}
+-static FC_CLASS_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
+-                      store_fc_host_vport_create);
+-
+-
+-/*
+- * "Short-cut" sysfs variable to delete a vport on a FC Host.
+- * Vport is identified by a string containing "<WWPN>:<WWNN>".
+- * The WWNs are specified as hex characters, and may *not* contain
+- * any prefixes (e.g. 0x, x, etc)
+- */
+-static ssize_t
+-store_fc_host_vport_delete(struct class_device *cdev, const char *buf,
+-                         size_t count)
+-{
+-      struct Scsi_Host *shost = transport_class_to_shost(cdev);
+-      struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+-      struct fc_vport *vport;
+-      u64 wwpn, wwnn;
+-      unsigned long flags;
+-      unsigned int cnt=count;
+-      int stat, match;
+-
+-      /* count may include a LF at end of string */
+-      if (buf[cnt-1] == '\n')
+-              cnt--;
+-
+-      /* validate we have enough characters for WWPN */
+-      if ((cnt != (16+1+16)) || (buf[16] != ':'))
+-              return -EINVAL;
+-
+-      stat = fc_parse_wwn(&buf[0], &wwpn);
+-      if (stat)
+-              return stat;
+-
+-      stat = fc_parse_wwn(&buf[17], &wwnn);
+-      if (stat)
+-              return stat;
+-
+-      spin_lock_irqsave(shost->host_lock, flags);
+-      match = 0;
+-      /* we only allow support on Channel 0 !!! */
+-      list_for_each_entry(vport, &fc_host->vports, peers) {
+-              if ((vport->channel == 0) &&
+-                  (vport->port_name == wwpn) && (vport->node_name == wwnn)) {
+-                      match = 1;
+-                      break;
+-              }
+-      }
+-      spin_unlock_irqrestore(shost->host_lock, flags);
+-
+-      if (!match)
+-              return -ENODEV;
+-
+-      stat = fc_vport_terminate(vport);
+-      return stat ? stat : count;
+-}
+-static FC_CLASS_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL,
+-                      store_fc_host_vport_delete);
+-
+-
+ static int fc_host_match(struct attribute_container *cont,
+                         struct device *dev)
+ {
+@@ -1863,40 +1387,6 @@
+ }
+-static void fc_vport_dev_release(struct device *dev)
+-{
+-      struct fc_vport *vport = dev_to_vport(dev);
+-      put_device(dev->parent);                /* release kobj parent */
+-      kfree(vport);
+-}
+-
+-int scsi_is_fc_vport(const struct device *dev)
+-{
+-      return dev->release == fc_vport_dev_release;
+-}
+-EXPORT_SYMBOL(scsi_is_fc_vport);
+-
+-static int fc_vport_match(struct attribute_container *cont,
+-                          struct device *dev)
+-{
+-      struct fc_vport *vport;
+-      struct Scsi_Host *shost;
+-      struct fc_internal *i;
+-
+-      if (!scsi_is_fc_vport(dev))
+-              return 0;
+-      vport = dev_to_vport(dev);
+-
+-      shost = vport_to_shost(vport);
+-      if (!shost->transportt  || shost->transportt->host_attrs.ac.class
+-          != &fc_host_class.class)
+-              return 0;
+-
+-      i = to_fc_internal(shost->transportt);
+-      return &i->vport_attr_cont.ac == cont;
+-}
+-
+-
+ /**
+  * fc_timed_out - FC Transport I/O timeout intercept handler
+  *
+@@ -1943,9 +1433,6 @@
+               if (rport->scsi_target_id == -1)
+                       continue;
+-              if (rport->port_state != FC_PORTSTATE_ONLINE)
+-                      continue;
+-
+               if ((channel == SCAN_WILD_CARD || channel == rport->channel) &&
+                   (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) {
+                       scsi_scan_target(&rport->dev, rport->channel,
+@@ -1985,11 +1472,6 @@
+       i->rport_attr_cont.ac.match = fc_rport_match;
+       transport_container_register(&i->rport_attr_cont);
+-      i->vport_attr_cont.ac.attrs = &i->vport_attrs[0];
+-      i->vport_attr_cont.ac.class = &fc_vport_class.class;
+-      i->vport_attr_cont.ac.match = fc_vport_match;
+-      transport_container_register(&i->vport_attr_cont);
+-
+       i->f = ft;
+       /* Transport uses the shost workq for scsi scanning */
+@@ -2023,10 +1505,6 @@
+       SETUP_HOST_ATTRIBUTE_RD(supported_fc4s);
+       SETUP_HOST_ATTRIBUTE_RD(supported_speeds);
+       SETUP_HOST_ATTRIBUTE_RD(maxframe_size);
+-      if (ft->vport_create) {
+-              SETUP_HOST_ATTRIBUTE_RD_NS(max_npiv_vports);
+-              SETUP_HOST_ATTRIBUTE_RD_NS(npiv_vports_inuse);
+-      }
+       SETUP_HOST_ATTRIBUTE_RD(serial_number);
+       SETUP_HOST_ATTRIBUTE_RD(port_id);
+@@ -2042,10 +1520,6 @@
+       SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);
+       if (ft->issue_fc_host_lip)
+               SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip);
+-      if (ft->vport_create)
+-              SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_create);
+-      if (ft->vport_delete)
+-              SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_delete);
+       BUG_ON(count > FC_HOST_NUM_ATTRS);
+@@ -2071,24 +1545,6 @@
+       i->rport_attrs[count] = NULL;
+-      /*
+-       * Setup Virtual Port Attributes.
+-       */
+-      count=0;
+-      SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_state);
+-      SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_last_state);
+-      SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(node_name);
+-      SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(port_name);
+-      SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(roles);
+-      SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_type);
+-      SETUP_VPORT_ATTRIBUTE_RW(symbolic_name);
+-      SETUP_VPORT_ATTRIBUTE_WR(vport_delete);
+-      SETUP_VPORT_ATTRIBUTE_WR(vport_disable);
+-
+-      BUG_ON(count > FC_VPORT_NUM_ATTRS);
+-
+-      i->vport_attrs[count] = NULL;
+-
+       return &i->t;
+ }
+ EXPORT_SYMBOL(fc_attach_transport);
+@@ -2100,7 +1556,6 @@
+       transport_container_unregister(&i->t.target_attrs);
+       transport_container_unregister(&i->t.host_attrs);
+       transport_container_unregister(&i->rport_attr_cont);
+-      transport_container_unregister(&i->vport_attr_cont);
+       kfree(i);
+ }
+@@ -2212,17 +1667,9 @@
+ void
+ fc_remove_host(struct Scsi_Host *shost)
+ {
+-      struct fc_vport *vport = NULL, *next_vport = NULL;
+-      struct fc_rport *rport = NULL, *next_rport = NULL;
++      struct fc_rport *rport, *next_rport;
+       struct workqueue_struct *work_q;
+       struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+-      unsigned long flags;
+-
+-      spin_lock_irqsave(shost->host_lock, flags);
+-
+-      /* Remove any vports */
+-      list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers)
+-              fc_queue_work(shost, &vport->vport_delete_work);
+       /* Remove any remote ports */
+       list_for_each_entry_safe(rport, next_rport,
+@@ -2239,8 +1686,6 @@
+               fc_queue_work(shost, &rport->rport_delete_work);
+       }
+-      spin_unlock_irqrestore(shost->host_lock, flags);
+-
+       /* flush all scan work items */
+       scsi_flush_work(shost);
+@@ -2399,7 +1844,7 @@
+       spin_lock_irqsave(shost->host_lock, flags);
+       rport->number = fc_host->next_rport_number++;
+-      if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
++      if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+               rport->scsi_target_id = fc_host->next_target_id++;
+       else
+               rport->scsi_target_id = -1;
+@@ -2424,7 +1869,7 @@
+       transport_add_device(dev);
+       transport_configure_device(dev);
+-      if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
++      if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
+               /* initiate a scan of the target */
+               rport->flags |= FC_RPORT_SCAN_PENDING;
+               scsi_queue_work(shost, &rport->scan_work);
+@@ -2558,7 +2003,7 @@
+                               /* was a target, not in roles */
+                               if ((rport->scsi_target_id != -1) &&
+-                                  (!(ids->roles & FC_PORT_ROLE_FCP_TARGET)))
++                                  (!(ids->roles & FC_RPORT_ROLE_FCP_TARGET)))
+                                       return rport;
+                               /*
+@@ -2641,7 +2086,7 @@
+                               memset(rport->dd_data, 0,
+                                               fci->f->dd_fcrport_size);
+-                      if (rport->roles & FC_PORT_ROLE_FCP_TARGET) {
++                      if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
+                               /* initiate a scan of the target */
+                               rport->flags |= FC_RPORT_SCAN_PENDING;
+                               scsi_queue_work(shost, &rport->scan_work);
+@@ -2798,11 +2243,11 @@
+       int create = 0;
+       spin_lock_irqsave(shost->host_lock, flags);
+-      if (roles & FC_PORT_ROLE_FCP_TARGET) {
++      if (roles & FC_RPORT_ROLE_FCP_TARGET) {
+               if (rport->scsi_target_id == -1) {
+                       rport->scsi_target_id = fc_host->next_target_id++;
+                       create = 1;
+-              } else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET))
++              } else if (!(rport->roles & FC_RPORT_ROLE_FCP_TARGET))
+                       create = 1;
+       }
+@@ -2872,7 +2317,7 @@
+        */
+       if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
+           (rport->scsi_target_id != -1) &&
+-          !(rport->roles & FC_PORT_ROLE_FCP_TARGET)) {
++          !(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
+               dev_printk(KERN_ERR, &rport->dev,
+                       "blocked FC remote port time out: no longer"
+                       " a FCP target, removing starget\n");
+@@ -2922,7 +2367,7 @@
+        */
+       rport->maxframe_size = -1;
+       rport->supported_classes = FC_COS_UNSPECIFIED;
+-      rport->roles = FC_PORT_ROLE_UNKNOWN;
++      rport->roles = FC_RPORT_ROLE_UNKNOWN;
+       rport->port_state = FC_PORTSTATE_NOTPRESENT;
+       /* remove the identifiers that aren't used in the consisting binding */
+@@ -2991,7 +2436,7 @@
+       unsigned long flags;
+       if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
+-          (rport->roles & FC_PORT_ROLE_FCP_TARGET)) {
++          (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
+               scsi_scan_target(&rport->dev, rport->channel,
+                       rport->scsi_target_id, SCAN_WILD_CARD, 1);
+       }
+@@ -3002,227 +2447,7 @@
+ }
+-/**
+- * fc_vport_create - allocates and creates a FC virtual port.
+- * @shost:    scsi host the virtual port is connected to.
+- * @channel:  Channel on shost port connected to.
+- * @pdev:     parent device for vport
+- * @ids:      The world wide names, FC4 port roles, etc for
+- *              the virtual port.
+- * @ret_vport:        The pointer to the created vport.
+- *
+- * Allocates and creates the vport structure, calls the parent host
+- * to instantiate the vport, the completes w/ class and sysfs creation.
+- *
+- * Notes:
+- *    This routine assumes no locks are held on entry.
+- **/
+-static int
+-fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev,
+-      struct fc_vport_identifiers  *ids, struct fc_vport **ret_vport)
+-{
+-      struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+-      struct fc_internal *fci = to_fc_internal(shost->transportt);
+-      struct fc_vport *vport;
+-      struct device *dev;
+-      unsigned long flags;
+-      size_t size;
+-      int error;
+-
+-      *ret_vport = NULL;
+-
+-      if ( ! fci->f->vport_create)
+-              return -ENOENT;
+-
+-      size = (sizeof(struct fc_vport) + fci->f->dd_fcvport_size);
+-      vport = kzalloc(size, GFP_KERNEL);
+-      if (unlikely(!vport)) {
+-              printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
+-              return -ENOMEM;
+-      }
+-
+-      vport->vport_state = FC_VPORT_UNKNOWN;
+-      vport->vport_last_state = FC_VPORT_UNKNOWN;
+-      vport->node_name = ids->node_name;
+-      vport->port_name = ids->port_name;
+-      vport->roles = ids->roles;
+-      vport->vport_type = ids->vport_type;
+-      if (fci->f->dd_fcvport_size)
+-              vport->dd_data = &vport[1];
+-      vport->shost = shost;
+-      vport->channel = channel;
+-      vport->flags = FC_VPORT_CREATING;
+-      INIT_WORK(&vport->vport_delete_work, fc_vport_sched_delete);
+-
+-      spin_lock_irqsave(shost->host_lock, flags);
+-
+-      if (fc_host->npiv_vports_inuse >= fc_host->max_npiv_vports) {
+-              spin_unlock_irqrestore(shost->host_lock, flags);
+-              kfree(vport);
+-              return -ENOSPC;
+-      }
+-      fc_host->npiv_vports_inuse++;
+-      vport->number = fc_host->next_vport_number++;
+-      list_add_tail(&vport->peers, &fc_host->vports);
+-      get_device(&shost->shost_gendev);       /* for fc_host->vport list */
+-
+-      spin_unlock_irqrestore(shost->host_lock, flags);
+-
+-      dev = &vport->dev;
+-      device_initialize(dev);                 /* takes self reference */
+-      dev->parent = get_device(pdev);         /* takes parent reference */
+-      dev->release = fc_vport_dev_release;
+-      sprintf(dev->bus_id, "vport-%d:%d-%d",
+-              shost->host_no, channel, vport->number);
+-      transport_setup_device(dev);
+-
+-      error = device_add(dev);
+-      if (error) {
+-              printk(KERN_ERR "FC Virtual Port device_add failed\n");
+-              goto delete_vport;
+-      }
+-      transport_add_device(dev);
+-      transport_configure_device(dev);
+-
+-      error = fci->f->vport_create(vport, ids->disable);
+-      if (error) {
+-              printk(KERN_ERR "FC Virtual Port LLDD Create failed\n");
+-              goto delete_vport_all;
+-      }
+-
+-      /*
+-       * if the parent isn't the physical adapter's Scsi_Host, ensure
+-       * the Scsi_Host at least contains ia symlink to the vport.
+-       */
+-      if (pdev != &shost->shost_gendev) {
+-              error = sysfs_create_link(&shost->shost_gendev.kobj,
+-                               &dev->kobj, dev->bus_id);
+-              if (error)
+-                      printk(KERN_ERR
+-                              "%s: Cannot create vport symlinks for "
+-                              "%s, err=%d\n",
+-                              __FUNCTION__, dev->bus_id, error);
+-      }
+-      spin_lock_irqsave(shost->host_lock, flags);
+-      vport->flags &= ~FC_VPORT_CREATING;
+-      spin_unlock_irqrestore(shost->host_lock, flags);
+-
+-      dev_printk(KERN_NOTICE, pdev,
+-                      "%s created via shost%d channel %d\n", dev->bus_id,
+-                      shost->host_no, channel);
+-
+-      *ret_vport = vport;
+-
+-      return 0;
+-
+-delete_vport_all:
+-      transport_remove_device(dev);
+-      device_del(dev);
+-delete_vport:
+-      transport_destroy_device(dev);
+-      spin_lock_irqsave(shost->host_lock, flags);
+-      list_del(&vport->peers);
+-      put_device(&shost->shost_gendev);       /* for fc_host->vport list */
+-      fc_host->npiv_vports_inuse--;
+-      spin_unlock_irqrestore(shost->host_lock, flags);
+-      put_device(dev->parent);
+-      kfree(vport);
+-
+-      return error;
+-}
+-
+-
+-/**
+- * fc_vport_terminate - Admin App or LLDD requests termination of a vport
+- * @vport:    fc_vport to be terminated
+- *
+- * Calls the LLDD vport_delete() function, then deallocates and removes
+- * the vport from the shost and object tree.
+- *
+- * Notes:
+- *    This routine assumes no locks are held on entry.
+- **/
+-int
+-fc_vport_terminate(struct fc_vport *vport)
+-{
+-      struct Scsi_Host *shost = vport_to_shost(vport);
+-      struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+-      struct fc_internal *i = to_fc_internal(shost->transportt);
+-      struct device *dev = &vport->dev;
+-      unsigned long flags;
+-      int stat;
+-
+-      spin_lock_irqsave(shost->host_lock, flags);
+-      if (vport->flags & FC_VPORT_CREATING) {
+-              spin_unlock_irqrestore(shost->host_lock, flags);
+-              return -EBUSY;
+-      }
+-      if (vport->flags & (FC_VPORT_DEL)) {
+-              spin_unlock_irqrestore(shost->host_lock, flags);
+-              return -EALREADY;
+-      }
+-      vport->flags |= FC_VPORT_DELETING;
+-      spin_unlock_irqrestore(shost->host_lock, flags);
+-
+-      if (i->f->vport_delete)
+-              stat = i->f->vport_delete(vport);
+-      else
+-              stat = -ENOENT;
+-
+-      spin_lock_irqsave(shost->host_lock, flags);
+-      vport->flags &= ~FC_VPORT_DELETING;
+-      if (!stat) {
+-              vport->flags |= FC_VPORT_DELETED;
+-              list_del(&vport->peers);
+-              fc_host->npiv_vports_inuse--;
+-              put_device(&shost->shost_gendev);  /* for fc_host->vport list */
+-      }
+-      spin_unlock_irqrestore(shost->host_lock, flags);
+-
+-      if (stat)
+-              return stat;
+-
+-      if (dev->parent != &shost->shost_gendev)
+-              sysfs_remove_link(&shost->shost_gendev.kobj, dev->bus_id);
+-      transport_remove_device(dev);
+-      device_del(dev);
+-      transport_destroy_device(dev);
+-
+-      /*
+-       * Removing our self-reference should mean our
+-       * release function gets called, which will drop the remaining
+-       * parent reference and free the data structure.
+-       */
+-      put_device(dev);                        /* for self-reference */
+-
+-      return 0; /* SUCCESS */
+-}
+-EXPORT_SYMBOL(fc_vport_terminate);
+-
+-/**
+- * fc_vport_sched_delete - workq-based delete request for a vport
+- *
+- * @work:     vport to be deleted.
+- **/
+-static void
+-fc_vport_sched_delete(struct work_struct *work)
+-{
+-      struct fc_vport *vport =
+-              container_of(work, struct fc_vport, vport_delete_work);
+-      int stat;
+-
+-      stat = fc_vport_terminate(vport);
+-      if (stat)
+-              dev_printk(KERN_ERR, vport->dev.parent,
+-                      "%s: %s could not be deleted created via "
+-                      "shost%d channel %d - error %d\n", __FUNCTION__,
+-                      vport->dev.bus_id, vport->shost->host_no,
+-                      vport->channel, stat);
+-}
+-
+-
+-/* Original Author:  Martin Hicks */
+-MODULE_AUTHOR("James Smart");
++MODULE_AUTHOR("Martin Hicks");
+ MODULE_DESCRIPTION("FC Transport Attributes");
+ MODULE_LICENSE("GPL");
  
-       ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
--      if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), area, 0))
-+      if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), vma, 0)) {
-+              fdata->type = VM_FAULT_SIGBUS;
-               return NULL;
--      return filemap_nopage(area, address, type);
-+      }
-+      return filemap_fault(vma, fdata);
- }
- #endif /* CONFIG_XFS_DMAPI */
+diff -Nurb linux-2.6.22-590/drivers/scsi/scsi_transport_iscsi.c linux-2.6.22-570/drivers/scsi/scsi_transport_iscsi.c
+--- linux-2.6.22-590/drivers/scsi/scsi_transport_iscsi.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/scsi_transport_iscsi.c       2007-07-08 19:32:17.000000000 -0400
+@@ -30,9 +30,9 @@
+ #include <scsi/scsi_transport_iscsi.h>
+ #include <scsi/iscsi_if.h>
  
-@@ -343,6 +344,7 @@
-       struct vm_area_struct *vma)
- {
-       vma->vm_ops = &xfs_file_vm_ops;
-+      vma->vm_flags |= VM_CAN_INVALIDATE | VM_CAN_NONLINEAR;
+-#define ISCSI_SESSION_ATTRS 15
++#define ISCSI_SESSION_ATTRS 11
+ #define ISCSI_CONN_ATTRS 11
+-#define ISCSI_HOST_ATTRS 4
++#define ISCSI_HOST_ATTRS 0
+ #define ISCSI_TRANSPORT_VERSION "2.0-724"
  
- #ifdef CONFIG_XFS_DMAPI
-       if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
-@@ -501,14 +503,12 @@
- };
+ struct iscsi_internal {
+@@ -609,10 +609,12 @@
+       int t = done ? NLMSG_DONE : type;
  
- static struct vm_operations_struct xfs_file_vm_ops = {
--      .nopage         = filemap_nopage,
--      .populate       = filemap_populate,
-+      .fault          = filemap_fault,
- };
+       skb = alloc_skb(len, GFP_ATOMIC);
+-      if (!skb) {
+-              printk(KERN_ERR "Could not allocate skb to send reply.\n");
+-              return -ENOMEM;
+-      }
++      /*
++       * FIXME:
++       * user is supposed to react on iferror == -ENOMEM;
++       * see iscsi_if_rx().
++       */
++      BUG_ON(!skb);
  
- #ifdef CONFIG_XFS_DMAPI
- static struct vm_operations_struct xfs_dmapi_file_vm_ops = {
--      .nopage         = xfs_vm_nopage,
--      .populate       = filemap_populate,
-+      .fault          = xfs_vm_fault,
- #ifdef HAVE_VMOP_MPROTECT
-       .mprotect       = xfs_vm_mprotect,
- #endif
-diff -Nurb linux-2.6.22-570/fs/xfs/linux-2.6/xfs_super.c linux-2.6.22-590/fs/xfs/linux-2.6/xfs_super.c
---- linux-2.6.22-570/fs/xfs/linux-2.6/xfs_super.c      2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/fs/xfs/linux-2.6/xfs_super.c      2008-01-02 13:56:37.000000000 -0500
-@@ -570,6 +570,7 @@
-       bhv_vfs_sync_work_t     *work, *n;
-       LIST_HEAD               (tmp);
+       nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
+       nlh->nlmsg_flags = flags;
+@@ -814,8 +816,6 @@
+       uint32_t hostno;
  
-+      set_freezable();
-       timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
-       for (;;) {
-               timeleft = schedule_timeout_interruptible(timeleft);
-diff -Nurb linux-2.6.22-570/include/acpi/acmacros.h linux-2.6.22-590/include/acpi/acmacros.h
---- linux-2.6.22-570/include/acpi/acmacros.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/acpi/acmacros.h   2008-01-02 13:56:37.000000000 -0500
-@@ -486,6 +486,8 @@
- #define ACPI_FUNCTION_NAME(name)
- #endif
+       session = transport->create_session(transport, &priv->t,
+-                                          ev->u.c_session.cmds_max,
+-                                          ev->u.c_session.queue_depth,
+                                           ev->u.c_session.initial_cmdsn,
+                                           &hostno);
+       if (!session)
+@@ -947,50 +947,15 @@
+ iscsi_tgt_dscvr(struct iscsi_transport *transport,
+               struct iscsi_uevent *ev)
+ {
+-      struct Scsi_Host *shost;
+       struct sockaddr *dst_addr;
+-      int err;
  
-+#ifdef DEBUG_FUNC_TRACE
-+
- #define ACPI_FUNCTION_TRACE(a)          ACPI_FUNCTION_NAME(a) \
-                         acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
- #define ACPI_FUNCTION_TRACE_PTR(a,b)    ACPI_FUNCTION_NAME(a) \
-@@ -563,6 +565,27 @@
+       if (!transport->tgt_dscvr)
+               return -EINVAL;
  
- #endif                                /* ACPI_SIMPLE_RETURN_MACROS */
+-      shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
+-      if (IS_ERR(shost)) {
+-              printk(KERN_ERR "target discovery could not find host no %u\n",
+-                     ev->u.tgt_dscvr.host_no);
+-              return -ENODEV;
+-      }
+-
+-
+       dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
+-      err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type,
++      return transport->tgt_dscvr(ev->u.tgt_dscvr.type,
++                                  ev->u.tgt_dscvr.host_no,
+                                   ev->u.tgt_dscvr.enable, dst_addr);
+-      scsi_host_put(shost);
+-      return err;
+-}
+-
+-static int
+-iscsi_set_host_param(struct iscsi_transport *transport,
+-                   struct iscsi_uevent *ev)
+-{
+-      char *data = (char*)ev + sizeof(*ev);
+-      struct Scsi_Host *shost;
+-      int err;
+-
+-      if (!transport->set_host_param)
+-              return -ENOSYS;
+-
+-      shost = scsi_host_lookup(ev->u.set_host_param.host_no);
+-      if (IS_ERR(shost)) {
+-              printk(KERN_ERR "set_host_param could not find host no %u\n",
+-                     ev->u.set_host_param.host_no);
+-              return -ENODEV;
+-      }
+-
+-      err = transport->set_host_param(shost, ev->u.set_host_param.param,
+-                                      data, ev->u.set_host_param.len);
+-      scsi_host_put(shost);
+-      return err;
+ }
  
-+#else /* !DEBUG_FUNC_TRACE */
-+
-+#define ACPI_FUNCTION_TRACE(a)
-+#define ACPI_FUNCTION_TRACE_PTR(a,b)
-+#define ACPI_FUNCTION_TRACE_U32(a,b)
-+#define ACPI_FUNCTION_TRACE_STR(a,b)
-+#define ACPI_FUNCTION_EXIT
-+#define ACPI_FUNCTION_STATUS_EXIT(s)
-+#define ACPI_FUNCTION_VALUE_EXIT(s)
-+#define ACPI_FUNCTION_TRACE(a)
-+#define ACPI_FUNCTION_ENTRY()
-+
-+#define return_VOID                     return
-+#define return_ACPI_STATUS(s)           return(s)
-+#define return_VALUE(s)                 return(s)
-+#define return_UINT8(s)                 return(s)
-+#define return_UINT32(s)                return(s)
-+#define return_PTR(s)                   return(s)
-+
-+#endif /* DEBUG_FUNC_TRACE */
-+
- /* Conditional execution */
+ static int
+@@ -1084,11 +1049,8 @@
+       case ISCSI_UEVENT_TGT_DSCVR:
+               err = iscsi_tgt_dscvr(transport, ev);
+               break;
+-      case ISCSI_UEVENT_SET_HOST_PARAM:
+-              err = iscsi_set_host_param(transport, ev);
+-              break;
+       default:
+-              err = -ENOSYS;
++              err = -EINVAL;
+               break;
+       }
  
- #define ACPI_DEBUG_EXEC(a)              a
-diff -Nurb linux-2.6.22-570/include/acpi/acoutput.h linux-2.6.22-590/include/acpi/acoutput.h
---- linux-2.6.22-570/include/acpi/acoutput.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/acpi/acoutput.h   2008-01-02 13:56:37.000000000 -0500
-@@ -178,8 +178,8 @@
+@@ -1198,37 +1160,30 @@
+ /*
+  * iSCSI session attrs
+  */
+-#define iscsi_session_attr_show(param, perm)                          \
++#define iscsi_session_attr_show(param)                                        \
+ static ssize_t                                                                \
+ show_session_param_##param(struct class_device *cdev, char *buf)      \
+ {                                                                     \
+       struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+       struct iscsi_transport *t = session->transport;                 \
+-                                                                      \
+-      if (perm && !capable(CAP_SYS_ADMIN))                            \
+-              return -EACCES;                                         \
+       return t->get_session_param(session, param, buf);               \
+ }
  
- /* Defaults for debug_level, debug and normal */
+-#define iscsi_session_attr(field, param, perm)                                \
+-      iscsi_session_attr_show(param, perm)                            \
++#define iscsi_session_attr(field, param)                              \
++      iscsi_session_attr_show(param)                                  \
+ static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
+                       NULL);
  
--#define ACPI_DEBUG_DEFAULT          (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR | ACPI_LV_DEBUG_OBJECT)
--#define ACPI_NORMAL_DEFAULT         (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR | ACPI_LV_DEBUG_OBJECT)
-+#define ACPI_DEBUG_DEFAULT          (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR)
-+#define ACPI_NORMAL_DEFAULT         (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR)
- #define ACPI_DEBUG_ALL              (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL)
+-iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
+-iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
+-iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
+-iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0);
+-iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0);
+-iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0);
+-iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0);
+-iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0);
+-iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0);
+-iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0);
+-iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
+-iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
+-iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
+-iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
++iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME);
++iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN);
++iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T);
++iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN);
++iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST);
++iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST);
++iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN);
++iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN);
++iscsi_session_attr(erl, ISCSI_PARAM_ERL);
++iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT);
  
- #endif                                /* __ACOUTPUT_H__ */
-diff -Nurb linux-2.6.22-570/include/acpi/platform/acenv.h linux-2.6.22-590/include/acpi/platform/acenv.h
---- linux-2.6.22-570/include/acpi/platform/acenv.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/acpi/platform/acenv.h     2008-01-02 13:56:37.000000000 -0500
-@@ -136,7 +136,7 @@
+ #define iscsi_priv_session_attr_show(field, format)                   \
+ static ssize_t                                                                \
+@@ -1244,28 +1199,6 @@
+                       NULL)
+ iscsi_priv_session_attr(recovery_tmo, "%d");
  
- /*! [Begin] no source code translation */
+-/*
+- * iSCSI host attrs
+- */
+-#define iscsi_host_attr_show(param)                                   \
+-static ssize_t                                                                \
+-show_host_param_##param(struct class_device *cdev, char *buf)         \
+-{                                                                     \
+-      struct Scsi_Host *shost = transport_class_to_shost(cdev);       \
+-      struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
+-      return priv->iscsi_transport->get_host_param(shost, param, buf); \
+-}
+-
+-#define iscsi_host_attr(field, param)                                 \
+-      iscsi_host_attr_show(param)                                     \
+-static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param,        \
+-                      NULL);
+-
+-iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
+-iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
+-iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
+-iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
+-
+ #define SETUP_PRIV_SESSION_RD_ATTR(field)                             \
+ do {                                                                  \
+       priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
+@@ -1289,14 +1222,6 @@
+       }                                                               \
+ } while (0)
  
--#if defined(__linux__)
-+#if defined(_LINUX) || defined(__linux__)
- #include "aclinux.h"
+-#define SETUP_HOST_RD_ATTR(field, param_flag)                         \
+-do {                                                                  \
+-      if (tt->host_param_mask & param_flag) {                         \
+-              priv->host_attrs[count] = &class_device_attr_host_##field; \
+-              count++;                                                \
+-      }                                                               \
+-} while (0)
+-
+ static int iscsi_session_match(struct attribute_container *cont,
+                          struct device *dev)
+ {
+@@ -1398,16 +1323,9 @@
+       priv->t.host_attrs.ac.class = &iscsi_host_class.class;
+       priv->t.host_attrs.ac.match = iscsi_host_match;
+       priv->t.host_size = sizeof(struct iscsi_host);
++      priv->host_attrs[0] = NULL;
+       transport_container_register(&priv->t.host_attrs);
  
- #elif defined(_AED_EFI)
-diff -Nurb linux-2.6.22-570/include/acpi/platform/aclinux.h linux-2.6.22-590/include/acpi/platform/aclinux.h
---- linux-2.6.22-570/include/acpi/platform/aclinux.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/acpi/platform/aclinux.h   2008-01-02 13:56:37.000000000 -0500
-@@ -91,7 +91,10 @@
- #define ACPI_USE_NATIVE_DIVIDE
- #endif
+-      SETUP_HOST_RD_ATTR(netdev, ISCSI_HOST_NETDEV_NAME);
+-      SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS);
+-      SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
+-      SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME);
+-      BUG_ON(count > ISCSI_HOST_ATTRS);
+-      priv->host_attrs[count] = NULL;
+-      count = 0;
+-
+       /* connection parameters */
+       priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
+       priv->conn_cont.ac.class = &iscsi_connection_class.class;
+@@ -1446,10 +1364,6 @@
+       SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
+       SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
+       SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
+-      SETUP_SESSION_RD_ATTR(password, ISCSI_USERNAME);
+-      SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN);
+-      SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
+-      SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
+       SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
  
-+#ifndef __cdecl
- #define __cdecl
-+#endif
-+
- #define ACPI_FLUSH_CPU_CACHE()
- #endif                                /* __KERNEL__ */
+       BUG_ON(count > ISCSI_SESSION_ATTRS);
+@@ -1523,7 +1437,7 @@
+       if (err)
+               goto unregister_conn_class;
  
-diff -Nurb linux-2.6.22-570/include/acpi/processor.h linux-2.6.22-590/include/acpi/processor.h
---- linux-2.6.22-570/include/acpi/processor.h  2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/include/acpi/processor.h  2008-01-02 13:56:37.000000000 -0500
-@@ -21,6 +21,8 @@
- #define ACPI_PSD_REV0_REVISION                0       /* Support for _PSD as in ACPI 3.0 */
- #define ACPI_PSD_REV0_ENTRIES         5
+-      nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx, NULL,
++      nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, NULL,
+                       THIS_MODULE);
+       if (!nls) {
+               err = -ENOBUFS;
+diff -Nurb linux-2.6.22-590/drivers/scsi/sd.c linux-2.6.22-570/drivers/scsi/sd.c
+--- linux-2.6.22-590/drivers/scsi/sd.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/sd.c 2007-07-08 19:32:17.000000000 -0400
+@@ -1515,7 +1515,7 @@
+       if (!scsi_device_online(sdp))
+               goto out;
  
-+#define ACPI_TSD_REV0_REVISION                0       /* Support for _PSD as in ACPI 3.0 */
-+#define ACPI_TSD_REV0_ENTRIES         5
- /*
-  * Types of coordination defined in ACPI 3.0. Same macros can be used across
-  * P, C and T states
-@@ -125,17 +127,53 @@
+-      buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL);
++      buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL | __GFP_DMA);
+       if (!buffer) {
+               sd_printk(KERN_WARNING, sdkp, "sd_revalidate_disk: Memory "
+                         "allocation failure.\n");
+diff -Nurb linux-2.6.22-590/drivers/scsi/sg.c linux-2.6.22-570/drivers/scsi/sg.c
+--- linux-2.6.22-590/drivers/scsi/sg.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/sg.c 2007-07-08 19:32:17.000000000 -0400
+@@ -1842,7 +1842,7 @@
+       int blk_size = buff_size;
+       struct page *p = NULL;
  
- /* Throttling Control */
+-      if (blk_size < 0)
++      if ((blk_size < 0) || (!sfp))
+               return -EFAULT;
+       if (0 == blk_size)
+               ++blk_size;     /* don't know why */
+diff -Nurb linux-2.6.22-590/drivers/scsi/stex.c linux-2.6.22-570/drivers/scsi/stex.c
+--- linux-2.6.22-590/drivers/scsi/stex.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/stex.c       2007-07-08 19:32:17.000000000 -0400
+@@ -395,34 +395,53 @@
+ static int stex_map_sg(struct st_hba *hba,
+       struct req_msg *req, struct st_ccb *ccb)
+ {
++      struct pci_dev *pdev = hba->pdev;
+       struct scsi_cmnd *cmd;
+-      struct scatterlist *sg;
++      dma_addr_t dma_handle;
++      struct scatterlist *src;
+       struct st_sgtable *dst;
+-      int i, nseg;
++      int i;
  
-+struct acpi_tsd_package {
-+      acpi_integer num_entries;
-+      acpi_integer revision;
-+      acpi_integer domain;
-+      acpi_integer coord_type;
-+      acpi_integer num_processors;
-+} __attribute__ ((packed));
-+
-+struct acpi_ptc_register {
-+      u8 descriptor;
-+      u16 length;
-+      u8 space_id;
-+      u8 bit_width;
-+      u8 bit_offset;
-+      u8 reserved;
-+      u64 address;
-+} __attribute__ ((packed));
-+
-+struct acpi_processor_tx_tss {
-+      acpi_integer freqpercentage;    /* */
-+      acpi_integer power;     /* milliWatts */
-+      acpi_integer transition_latency;        /* microseconds */
-+      acpi_integer control;   /* control value */
-+      acpi_integer status;    /* success indicator */
-+};
- struct acpi_processor_tx {
-       u16 power;
-       u16 performance;
- };
+       cmd = ccb->cmd;
+       dst = (struct st_sgtable *)req->variable;
+       dst->max_sg_count = cpu_to_le16(ST_MAX_SG);
+-      dst->sz_in_byte = cpu_to_le32(scsi_bufflen(cmd));
++      dst->sz_in_byte = cpu_to_le32(cmd->request_bufflen);
++
++      if (cmd->use_sg) {
++              int n_elem;
+-      nseg = scsi_dma_map(cmd);
+-      if (nseg < 0)
++              src = (struct scatterlist *) cmd->request_buffer;
++              n_elem = pci_map_sg(pdev, src,
++                      cmd->use_sg, cmd->sc_data_direction);
++              if (n_elem <= 0)
+                       return -EIO;
+-      if (nseg) {
+-              ccb->sg_count = nseg;
+-              dst->sg_count = cpu_to_le16((u16)nseg);
  
-+struct acpi_processor;
- struct acpi_processor_throttling {
--      int state;
-+      unsigned int state;
-+      unsigned int platform_limit;
-+      struct acpi_pct_register control_register;
-+      struct acpi_pct_register status_register;
-+      unsigned int state_count;
-+      struct acpi_processor_tx_tss *states_tss;
-+      struct acpi_tsd_package domain_info;
-+      cpumask_t shared_cpu_map;
-+      int (*acpi_processor_get_throttling) (struct acpi_processor * pr);
-+      int (*acpi_processor_set_throttling) (struct acpi_processor * pr,
-+                                            int state);
+-              scsi_for_each_sg(cmd, sg, nseg, i) {
+-                      dst->table[i].count = cpu_to_le32((u32)sg_dma_len(sg));
++              ccb->sg_count = n_elem;
++              dst->sg_count = cpu_to_le16((u16)n_elem);
 +
-       u32 address;
-       u8 duty_offset;
-       u8 duty_width;
--      int state_count;
-       struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING];
- };
-@@ -161,6 +199,7 @@
-       u8 bm_check:1;
-       u8 has_cst:1;
-       u8 power_setup_done:1;
-+      u8 bm_rld_set:1;
- };
++              for (i = 0; i < n_elem; i++, src++) {
++                      dst->table[i].count = cpu_to_le32((u32)sg_dma_len(src));
+                       dst->table[i].addr =
+-                              cpu_to_le32(sg_dma_address(sg) & 0xffffffff);
++                              cpu_to_le32(sg_dma_address(src) & 0xffffffff);
+                       dst->table[i].addr_hi =
+-                              cpu_to_le32((sg_dma_address(sg) >> 16) >> 16);
++                              cpu_to_le32((sg_dma_address(src) >> 16) >> 16);
+                       dst->table[i].ctrl = SG_CF_64B | SG_CF_HOST;
+               }
+               dst->table[--i].ctrl |= SG_CF_EOT;
++              return 0;
+       }
  
- struct acpi_processor {
-@@ -169,6 +208,9 @@
-       u32 id;
-       u32 pblk;
-       int performance_platform_limit;
-+      int throttling_platform_limit;
-+      /* 0 - states 0..n-th state available */
++      dma_handle = pci_map_single(pdev, cmd->request_buffer,
++              cmd->request_bufflen, cmd->sc_data_direction);
++      cmd->SCp.dma_handle = dma_handle;
 +
-       struct acpi_processor_flags flags;
-       struct acpi_processor_power power;
-       struct acpi_processor_performance *performance;
-@@ -270,7 +312,7 @@
- /* in processor_throttling.c */
- int acpi_processor_get_throttling_info(struct acpi_processor *pr);
--int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
-+extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
- extern struct file_operations acpi_processor_throttling_fops;
- /* in processor_idle.c */
-@@ -279,6 +321,9 @@
- int acpi_processor_cst_has_changed(struct acpi_processor *pr);
- int acpi_processor_power_exit(struct acpi_processor *pr,
-                             struct acpi_device *device);
++      ccb->sg_count = 1;
++      dst->sg_count = cpu_to_le16(1);
++      dst->table[0].addr = cpu_to_le32(dma_handle & 0xffffffff);
++      dst->table[0].addr_hi = cpu_to_le32((dma_handle >> 16) >> 16);
++      dst->table[0].count = cpu_to_le32((u32)cmd->request_bufflen);
++      dst->table[0].ctrl = SG_CF_EOT | SG_CF_64B | SG_CF_HOST;
 +
-+extern struct cpuidle_driver acpi_idle_driver;
-+void acpi_max_cstate_changed(void);
- int acpi_processor_suspend(struct acpi_device * device, pm_message_t state);
- int acpi_processor_resume(struct acpi_device * device);
+       return 0;
+ }
  
-diff -Nurb linux-2.6.22-570/include/asm-alpha/page.h linux-2.6.22-590/include/asm-alpha/page.h
---- linux-2.6.22-570/include/asm-alpha/page.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-alpha/page.h  2008-01-02 13:56:37.000000000 -0500
-@@ -17,7 +17,8 @@
- extern void clear_page(void *page);
- #define clear_user_page(page, vaddr, pg)      clear_page(page)
+@@ -432,24 +451,24 @@
+       size_t lcount;
+       size_t len;
+       void *s, *d, *base = NULL;
+-      size_t offset;
+-
+-      if (*count > scsi_bufflen(cmd))
+-              *count = scsi_bufflen(cmd);
++      if (*count > cmd->request_bufflen)
++              *count = cmd->request_bufflen;
+       lcount = *count;
+       while (lcount) {
+               len = lcount;
+               s = (void *)src;
+-
+-              offset = *count - lcount;
++              if (cmd->use_sg) {
++                      size_t offset = *count - lcount;
+                       s += offset;
+-              base = scsi_kmap_atomic_sg(scsi_sglist(cmd),
++                      base = scsi_kmap_atomic_sg(cmd->request_buffer,
+                               sg_count, &offset, &len);
+-              if (!base) {
++                      if (base == NULL) {
+                               *count -= lcount;
+                               return;
+                       }
+                       d = base + offset;
++              } else
++                      d = cmd->request_buffer;
  
--#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vmaddr)
-+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
-+      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vmaddr)
- #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+               if (direction == ST_TO_CMD)
+                       memcpy(d, s, len);
+@@ -457,6 +476,7 @@
+                       memcpy(s, d, len);
  
- extern void copy_page(void * _to, void * _from);
-diff -Nurb linux-2.6.22-570/include/asm-arm/arch-iop13xx/adma.h linux-2.6.22-590/include/asm-arm/arch-iop13xx/adma.h
---- linux-2.6.22-570/include/asm-arm/arch-iop13xx/adma.h       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-arm/arch-iop13xx/adma.h       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,544 @@
-+/*
-+ * Copyright(c) 2006, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ */
-+#ifndef _ADMA_H
-+#define _ADMA_H
-+#include <linux/types.h>
-+#include <linux/io.h>
-+#include <asm/hardware.h>
-+#include <asm/hardware/iop_adma.h>
-+
-+#define ADMA_ACCR(chan)       (chan->mmr_base + 0x0)
-+#define ADMA_ACSR(chan)       (chan->mmr_base + 0x4)
-+#define ADMA_ADAR(chan)       (chan->mmr_base + 0x8)
-+#define ADMA_IIPCR(chan)      (chan->mmr_base + 0x18)
-+#define ADMA_IIPAR(chan)      (chan->mmr_base + 0x1c)
-+#define ADMA_IIPUAR(chan)     (chan->mmr_base + 0x20)
-+#define ADMA_ANDAR(chan)      (chan->mmr_base + 0x24)
-+#define ADMA_ADCR(chan)       (chan->mmr_base + 0x28)
-+#define ADMA_CARMD(chan)      (chan->mmr_base + 0x2c)
-+#define ADMA_ABCR(chan)       (chan->mmr_base + 0x30)
-+#define ADMA_DLADR(chan)      (chan->mmr_base + 0x34)
-+#define ADMA_DUADR(chan)      (chan->mmr_base + 0x38)
-+#define ADMA_SLAR(src, chan)  (chan->mmr_base + (0x3c + (src << 3)))
-+#define ADMA_SUAR(src, chan)  (chan->mmr_base + (0x40 + (src << 3)))
-+
-+struct iop13xx_adma_src {
-+      u32 src_addr;
-+      union {
-+              u32 upper_src_addr;
-+              struct {
-+                      unsigned int pq_upper_src_addr:24;
-+                      unsigned int pq_dmlt:8;
-+              };
-+      };
-+};
-+
-+struct iop13xx_adma_desc_ctrl {
-+      unsigned int int_en:1;
-+      unsigned int xfer_dir:2;
-+      unsigned int src_select:4;
-+      unsigned int zero_result:1;
-+      unsigned int block_fill_en:1;
-+      unsigned int crc_gen_en:1;
-+      unsigned int crc_xfer_dis:1;
-+      unsigned int crc_seed_fetch_dis:1;
-+      unsigned int status_write_back_en:1;
-+      unsigned int endian_swap_en:1;
-+      unsigned int reserved0:2;
-+      unsigned int pq_update_xfer_en:1;
-+      unsigned int dual_xor_en:1;
-+      unsigned int pq_xfer_en:1;
-+      unsigned int p_xfer_dis:1;
-+      unsigned int reserved1:10;
-+      unsigned int relax_order_en:1;
-+      unsigned int no_snoop_en:1;
-+};
-+
-+struct iop13xx_adma_byte_count {
-+      unsigned int byte_count:24;
-+      unsigned int host_if:3;
-+      unsigned int reserved:2;
-+      unsigned int zero_result_err_q:1;
-+      unsigned int zero_result_err:1;
-+      unsigned int tx_complete:1;
-+};
-+
-+struct iop13xx_adma_desc_hw {
-+      u32 next_desc;
-+      union {
-+              u32 desc_ctrl;
-+              struct iop13xx_adma_desc_ctrl desc_ctrl_field;
-+      };
-+      union {
-+              u32 crc_addr;
-+              u32 block_fill_data;
-+              u32 q_dest_addr;
-+      };
-+      union {
-+              u32 byte_count;
-+              struct iop13xx_adma_byte_count byte_count_field;
-+      };
-+      union {
-+              u32 dest_addr;
-+              u32 p_dest_addr;
-+      };
-+      union {
-+              u32 upper_dest_addr;
-+              u32 pq_upper_dest_addr;
-+      };
-+      struct iop13xx_adma_src src[1];
-+};
-+
-+struct iop13xx_adma_desc_dual_xor {
-+      u32 next_desc;
-+      u32 desc_ctrl;
-+      u32 reserved;
-+      u32 byte_count;
-+      u32 h_dest_addr;
-+      u32 h_upper_dest_addr;
-+      u32 src0_addr;
-+      u32 upper_src0_addr;
-+      u32 src1_addr;
-+      u32 upper_src1_addr;
-+      u32 h_src_addr;
-+      u32 h_upper_src_addr;
-+      u32 d_src_addr;
-+      u32 d_upper_src_addr;
-+      u32 d_dest_addr;
-+      u32 d_upper_dest_addr;
-+};
-+
-+struct iop13xx_adma_desc_pq_update {
-+      u32 next_desc;
-+      u32 desc_ctrl;
-+      u32 reserved;
-+      u32 byte_count;
-+      u32 p_dest_addr;
-+      u32 p_upper_dest_addr;
-+      u32 src0_addr;
-+      u32 upper_src0_addr;
-+      u32 src1_addr;
-+      u32 upper_src1_addr;
-+      u32 p_src_addr;
-+      u32 p_upper_src_addr;
-+      u32 q_src_addr;
-+      struct {
-+              unsigned int q_upper_src_addr:24;
-+              unsigned int q_dmlt:8;
-+      };
-+      u32 q_dest_addr;
-+      u32 q_upper_dest_addr;
-+};
-+
-+static inline int iop_adma_get_max_xor(void)
-+{
-+      return 16;
-+}
-+
-+static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
-+{
-+      return __raw_readl(ADMA_ADAR(chan));
-+}
-+
-+static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
-+                                              u32 next_desc_addr)
-+{
-+      __raw_writel(next_desc_addr, ADMA_ANDAR(chan));
-+}
-+
-+#define ADMA_STATUS_BUSY (1 << 13)
-+
-+static inline char iop_chan_is_busy(struct iop_adma_chan *chan)
-+{
-+      if (__raw_readl(ADMA_ACSR(chan)) &
-+              ADMA_STATUS_BUSY)
-+              return 1;
-+      else
-+              return 0;
-+}
-+
-+static inline int
-+iop_chan_get_desc_align(struct iop_adma_chan *chan, int num_slots)
-+{
-+      return 1;
-+}
-+#define iop_desc_is_aligned(x, y) 1
-+
-+static inline int
-+iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
-+{
-+      *slots_per_op = 1;
-+      return 1;
-+}
-+
-+#define iop_chan_interrupt_slot_count(s, c) iop_chan_memcpy_slot_count(0, s)
-+
-+static inline int
-+iop_chan_memset_slot_count(size_t len, int *slots_per_op)
-+{
-+      *slots_per_op = 1;
-+      return 1;
-+}
-+
-+static inline int
-+iop_chan_xor_slot_count(size_t len, int src_cnt, int *slots_per_op)
-+{
-+      int num_slots;
-+      /* slots_to_find = 1 for basic descriptor + 1 per 4 sources above 1
-+       * (1 source => 8 bytes) (1 slot => 32 bytes)
-+       */
-+      num_slots = 1 + (((src_cnt - 1) << 3) >> 5);
-+      if (((src_cnt - 1) << 3) & 0x1f)
-+              num_slots++;
-+
-+      *slots_per_op = num_slots;
-+
-+      return num_slots;
-+}
-+
-+#define ADMA_MAX_BYTE_COUNT   (16 * 1024 * 1024)
-+#define IOP_ADMA_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
-+#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
-+#define IOP_ADMA_XOR_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
-+#define iop_chan_zero_sum_slot_count(l, s, o) iop_chan_xor_slot_count(l, s, o)
-+
-+static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc,
-+                                      struct iop_adma_chan *chan)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      return hw_desc->dest_addr;
-+}
-+
-+static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
-+                                      struct iop_adma_chan *chan)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      return hw_desc->byte_count_field.byte_count;
-+}
-+
-+static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
-+                                      struct iop_adma_chan *chan,
-+                                      int src_idx)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      return hw_desc->src[src_idx].src_addr;
-+}
-+
-+static inline u32 iop_desc_get_src_count(struct iop_adma_desc_slot *desc,
-+                                      struct iop_adma_chan *chan)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      return hw_desc->desc_ctrl_field.src_select + 1;
-+}
-+
-+static inline void
-+iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      union {
-+              u32 value;
-+              struct iop13xx_adma_desc_ctrl field;
-+      } u_desc_ctrl;
-+
-+      u_desc_ctrl.value = 0;
-+      u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
-+      u_desc_ctrl.field.int_en = int_en;
-+      hw_desc->desc_ctrl = u_desc_ctrl.value;
-+      hw_desc->crc_addr = 0;
-+}
-+
-+static inline void
-+iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      union {
-+              u32 value;
-+              struct iop13xx_adma_desc_ctrl field;
-+      } u_desc_ctrl;
-+
-+      u_desc_ctrl.value = 0;
-+      u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
-+      u_desc_ctrl.field.block_fill_en = 1;
-+      u_desc_ctrl.field.int_en = int_en;
-+      hw_desc->desc_ctrl = u_desc_ctrl.value;
-+      hw_desc->crc_addr = 0;
-+}
-+
-+/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
-+static inline void
-+iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      union {
-+              u32 value;
-+              struct iop13xx_adma_desc_ctrl field;
-+      } u_desc_ctrl;
-+
-+      u_desc_ctrl.value = 0;
-+      u_desc_ctrl.field.src_select = src_cnt - 1;
-+      u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
-+      u_desc_ctrl.field.int_en = int_en;
-+      hw_desc->desc_ctrl = u_desc_ctrl.value;
-+      hw_desc->crc_addr = 0;
-+
-+}
-+#define iop_desc_init_null_xor(d, s, i) iop_desc_init_xor(d, s, i)
-+
-+/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
-+static inline int
-+iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      union {
-+              u32 value;
-+              struct iop13xx_adma_desc_ctrl field;
-+      } u_desc_ctrl;
-+
-+      u_desc_ctrl.value = 0;
-+      u_desc_ctrl.field.src_select = src_cnt - 1;
-+      u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
-+      u_desc_ctrl.field.zero_result = 1;
-+      u_desc_ctrl.field.status_write_back_en = 1;
-+      u_desc_ctrl.field.int_en = int_en;
-+      hw_desc->desc_ctrl = u_desc_ctrl.value;
-+      hw_desc->crc_addr = 0;
-+
-+      return 1;
-+}
-+
-+static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
-+                                      struct iop_adma_chan *chan,
-+                                      u32 byte_count)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      hw_desc->byte_count = byte_count;
-+}
-+
-+static inline void
-+iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
-+{
-+      int slots_per_op = desc->slots_per_op;
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
-+      int i = 0;
-+
-+      if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
-+              hw_desc->byte_count = len;
-+      } else {
-+              do {
-+                      iter = iop_hw_desc_slot_idx(hw_desc, i);
-+                      iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
-+                      len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
-+                      i += slots_per_op;
-+              } while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
-+
-+              if (len) {
-+                      iter = iop_hw_desc_slot_idx(hw_desc, i);
-+                      iter->byte_count = len;
-+              }
-+      }
-+}
-+
-+
-+static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
-+                                      struct iop_adma_chan *chan,
-+                                      dma_addr_t addr)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      hw_desc->dest_addr = addr;
-+      hw_desc->upper_dest_addr = 0;
-+}
-+
-+static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
-+                                      dma_addr_t addr)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      hw_desc->src[0].src_addr = addr;
-+      hw_desc->src[0].upper_src_addr = 0;
-+}
-+
-+static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
-+                                      int src_idx, dma_addr_t addr)
-+{
-+      int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
-+      int i = 0;
-+
-+      do {
-+              iter = iop_hw_desc_slot_idx(hw_desc, i);
-+              iter->src[src_idx].src_addr = addr;
-+              iter->src[src_idx].upper_src_addr = 0;
-+              slot_cnt -= slots_per_op;
-+              if (slot_cnt) {
-+                      i += slots_per_op;
-+                      addr += IOP_ADMA_XOR_MAX_BYTE_COUNT;
-+              }
-+      } while (slot_cnt);
-+}
-+
-+static inline void
-+iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
-+      struct iop_adma_chan *chan)
-+{
-+      iop_desc_init_memcpy(desc, 1);
-+      iop_desc_set_byte_count(desc, chan, 0);
-+      iop_desc_set_dest_addr(desc, chan, 0);
-+      iop_desc_set_memcpy_src_addr(desc, 0);
-+}
-+
-+#define iop_desc_set_zero_sum_src_addr iop_desc_set_xor_src_addr
-+
-+static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
-+                                      u32 next_desc_addr)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      BUG_ON(hw_desc->next_desc);
-+      hw_desc->next_desc = next_desc_addr;
-+}
-+
-+static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      return hw_desc->next_desc;
-+}
-+
-+static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      hw_desc->next_desc = 0;
-+}
-+
-+static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
-+                                              u32 val)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      hw_desc->block_fill_data = val;
-+}
-+
-+static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
-+{
-+      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
-+      struct iop13xx_adma_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
-+      struct iop13xx_adma_byte_count byte_count = hw_desc->byte_count_field;
-+
-+      BUG_ON(!(byte_count.tx_complete && desc_ctrl.zero_result));
-+
-+      if (desc_ctrl.pq_xfer_en)
-+              return byte_count.zero_result_err_q;
-+      else
-+              return byte_count.zero_result_err;
-+}
-+
-+static inline void iop_chan_append(struct iop_adma_chan *chan)
-+{
-+      u32 adma_accr;
-+
-+      adma_accr = __raw_readl(ADMA_ACCR(chan));
-+      adma_accr |= 0x2;
-+      __raw_writel(adma_accr, ADMA_ACCR(chan));
-+}
-+
-+static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
-+{
-+      do { } while (0);
-+}
-+
-+static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
-+{
-+      return __raw_readl(ADMA_ACSR(chan));
-+}
-+
-+static inline void iop_chan_disable(struct iop_adma_chan *chan)
-+{
-+      u32 adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));
-+      adma_chan_ctrl &= ~0x1;
-+      __raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));
-+}
-+
-+static inline void iop_chan_enable(struct iop_adma_chan *chan)
-+{
-+      u32 adma_chan_ctrl;
-+
-+      adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));
-+      adma_chan_ctrl |= 0x1;
-+      __raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));
-+}
-+
-+static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
-+{
-+      u32 status = __raw_readl(ADMA_ACSR(chan));
-+      status &= (1 << 12);
-+      __raw_writel(status, ADMA_ACSR(chan));
-+}
-+
-+static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
-+{
-+      u32 status = __raw_readl(ADMA_ACSR(chan));
-+      status &= (1 << 11);
-+      __raw_writel(status, ADMA_ACSR(chan));
-+}
-+
-+static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
+               lcount -= len;
++              if (cmd->use_sg)
+                       scsi_kunmap_atomic_sg(base);
+       }
+ }
+@@ -464,17 +484,22 @@
+ static int stex_direct_copy(struct scsi_cmnd *cmd,
+       const void *src, size_t count)
+ {
++      struct st_hba *hba = (struct st_hba *) &cmd->device->host->hostdata[0];
+       size_t cp_len = count;
+       int n_elem = 0;
+-      n_elem = scsi_dma_map(cmd);
+-      if (n_elem < 0)
++      if (cmd->use_sg) {
++              n_elem = pci_map_sg(hba->pdev, cmd->request_buffer,
++                      cmd->use_sg, cmd->sc_data_direction);
++              if (n_elem <= 0)
+                       return 0;
++      }
+       stex_internal_copy(cmd, src, &cp_len, n_elem, ST_TO_CMD);
+-      scsi_dma_unmap(cmd);
+-
++      if (cmd->use_sg)
++              pci_unmap_sg(hba->pdev, cmd->request_buffer,
++                      cmd->use_sg, cmd->sc_data_direction);
+       return cp_len == count;
+ }
+@@ -653,6 +678,18 @@
+       return 0;
+ }
++static void stex_unmap_sg(struct st_hba *hba, struct scsi_cmnd *cmd)
 +{
-+      u32 status = __raw_readl(ADMA_ACSR(chan));
-+      status &= (1 << 9) | (1 << 5) | (1 << 4) | (1 << 3);
-+      __raw_writel(status, ADMA_ACSR(chan));
++      if (cmd->sc_data_direction != DMA_NONE) {
++              if (cmd->use_sg)
++                      pci_unmap_sg(hba->pdev, cmd->request_buffer,
++                              cmd->use_sg, cmd->sc_data_direction);
++              else
++                      pci_unmap_single(hba->pdev, cmd->SCp.dma_handle,
++                              cmd->request_bufflen, cmd->sc_data_direction);
++      }
 +}
 +
-+static inline int
-+iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      return test_bit(9, &status);
-+}
+ static void stex_scsi_done(struct st_ccb *ccb)
+ {
+       struct scsi_cmnd *cmd = ccb->cmd;
+@@ -719,7 +756,7 @@
+       if (ccb->cmd->cmnd[0] == MGT_CMD &&
+               resp->scsi_status != SAM_STAT_CHECK_CONDITION) {
+-              scsi_bufflen(ccb->cmd) =
++              ccb->cmd->request_bufflen =
+                       le32_to_cpu(*(__le32 *)&resp->variable[0]);
+               return;
+       }
+@@ -818,7 +855,7 @@
+                               ccb->cmd->cmnd[1] == PASSTHRU_GET_ADAPTER))
+                               stex_controller_info(hba, ccb);
+-                      scsi_dma_unmap(ccb->cmd);
++                      stex_unmap_sg(hba, ccb->cmd);
+                       stex_scsi_done(ccb);
+                       hba->out_req_cnt--;
+               } else if (ccb->req_type & PASSTHRU_REQ_TYPE) {
+@@ -991,7 +1028,7 @@
+       }
+ fail_out:
+-      scsi_dma_unmap(cmd);
++      stex_unmap_sg(hba, cmd);
+       hba->wait_ccb->req = NULL; /* nullify the req's future return */
+       hba->wait_ccb = NULL;
+       result = FAILED;
+diff -Nurb linux-2.6.22-590/drivers/scsi/sun_esp.c linux-2.6.22-570/drivers/scsi/sun_esp.c
+--- linux-2.6.22-590/drivers/scsi/sun_esp.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/sun_esp.c    2007-07-08 19:32:17.000000000 -0400
+@@ -493,7 +493,7 @@
+               goto fail;
+       host->max_id = (hme ? 16 : 8);
+-      esp = shost_priv(host);
++      esp = host_to_esp(host);
+       esp->host = host;
+       esp->dev = esp_dev;
+diff -Nurb linux-2.6.22-590/drivers/scsi/sym53c416.c linux-2.6.22-570/drivers/scsi/sym53c416.c
+--- linux-2.6.22-590/drivers/scsi/sym53c416.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/sym53c416.c  2007-07-08 19:32:17.000000000 -0400
+@@ -332,7 +332,8 @@
+       int i;
+       unsigned long flags = 0;
+       unsigned char status_reg, pio_int_reg, int_reg;
+-      struct scatterlist *sg;
++      struct scatterlist *sglist;
++      unsigned int sgcount;
+       unsigned int tot_trans = 0;
+       /* We search the base address of the host adapter which caused the interrupt */
+@@ -428,15 +429,19 @@
+                       {
+                               current_command->SCp.phase = data_out;
+                               outb(FLUSH_FIFO, base + COMMAND_REG);
+-                              sym53c416_set_transfer_counter(base,
+-                                                             scsi_bufflen(current_command));
++                              sym53c416_set_transfer_counter(base, current_command->request_bufflen);
+                               outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
+-
+-                              scsi_for_each_sg(current_command,
+-                                               sg, scsi_sg_count(current_command), i) {
+-                                      tot_trans += sym53c416_write(base,
+-                                                                   SG_ADDRESS(sg),
+-                                                                   sg->length);
++                              if(!current_command->use_sg)
++                                      tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen);
++                              else
++                              {
++                                      sgcount = current_command->use_sg;
++                                      sglist = current_command->request_buffer;
++                                      while(sgcount--)
++                                      {
++                                              tot_trans += sym53c416_write(base, SG_ADDRESS(sglist), sglist->length);
++                                              sglist++;
++                                      }
+                               }
+                               if(tot_trans < current_command->underflow)
+                                       printk(KERN_WARNING "sym53c416: Underflow, wrote %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow);
+@@ -450,16 +455,19 @@
+                       {
+                               current_command->SCp.phase = data_in;
+                               outb(FLUSH_FIFO, base + COMMAND_REG);
+-                              sym53c416_set_transfer_counter(base,
+-                                                             scsi_bufflen(current_command));
+-
++                              sym53c416_set_transfer_counter(base, current_command->request_bufflen);
+                               outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
+-
+-                              scsi_for_each_sg(current_command,
+-                                               sg, scsi_sg_count(current_command), i) {
+-                                      tot_trans += sym53c416_read(base,
+-                                                                  SG_ADDRESS(sg),
+-                                                                  sg->length);
++                              if(!current_command->use_sg)
++                                      tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen);
++                              else
++                              {
++                                      sgcount = current_command->use_sg;
++                                      sglist = current_command->request_buffer;
++                                      while(sgcount--)
++                                      {
++                                              tot_trans += sym53c416_read(base, SG_ADDRESS(sglist), sglist->length);
++                                              sglist++;
++                                      }
+                               }
+                               if(tot_trans < current_command->underflow)
+                                       printk(KERN_WARNING "sym53c416: Underflow, read %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow);
+diff -Nurb linux-2.6.22-590/drivers/scsi/tmscsim.c linux-2.6.22-570/drivers/scsi/tmscsim.c
+--- linux-2.6.22-590/drivers/scsi/tmscsim.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/tmscsim.c    2007-07-08 19:32:17.000000000 -0400
+@@ -457,20 +457,27 @@
+                       error = 1;
+               DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __FUNCTION__, pcmd->sense_buffer, cmdp->saved_dma_handle));
+       /* Map SG list */
+-      } else if (scsi_sg_count(pcmd)) {
+-              int nseg;
+-
+-              nseg = scsi_dma_map(pcmd);
+-
+-              pSRB->pSegmentList      = scsi_sglist(pcmd);
+-              pSRB->SGcount           = nseg;
+-
++      } else if (pcmd->use_sg) {
++              pSRB->pSegmentList      = (struct scatterlist *) pcmd->request_buffer;
++              pSRB->SGcount           = pci_map_sg(pdev, pSRB->pSegmentList, pcmd->use_sg,
++                                                   pcmd->sc_data_direction);
+               /* TODO: error handling */
+-              if (nseg < 0)
++              if (!pSRB->SGcount)
+                       error = 1;
+               DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
+-                            __FUNCTION__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd)));
++                            __FUNCTION__, pcmd->request_buffer, pSRB->SGcount, pcmd->use_sg));
+       /* Map single segment */
++      } else if (pcmd->request_buffer && pcmd->request_bufflen) {
++              pSRB->pSegmentList      = dc390_sg_build_single(&pSRB->Segmentx, pcmd->request_buffer, pcmd->request_bufflen);
++              pSRB->SGcount           = pci_map_sg(pdev, pSRB->pSegmentList, 1,
++                                                   pcmd->sc_data_direction);
++              cmdp->saved_dma_handle  = sg_dma_address(pSRB->pSegmentList);
++
++              /* TODO: error handling */
++              if (pSRB->SGcount != 1)
++                      error = 1;
++              DEBUG1(printk("%s(): Mapped request buffer %p at %x\n", __FUNCTION__, pcmd->request_buffer, cmdp->saved_dma_handle));
++      /* No mapping !? */     
+       } else
+               pSRB->SGcount = 0;
+@@ -487,10 +494,12 @@
+       if (pSRB->SRBFlag) {
+               pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE);
+               DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle));
+-      } else {
+-              scsi_dma_unmap(pcmd);
+-              DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n",
+-                            __FUNCTION__, scsi_sglist(pcmd), scsi_sg_count(pcmd)));
++      } else if (pcmd->use_sg) {
++              pci_unmap_sg(pdev, pcmd->request_buffer, pcmd->use_sg, pcmd->sc_data_direction);
++              DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n", __FUNCTION__, pcmd->request_buffer, pcmd->use_sg));
++      } else if (pcmd->request_buffer && pcmd->request_bufflen) {
++              pci_unmap_sg(pdev, &pSRB->Segmentx, 1, pcmd->sc_data_direction);
++              DEBUG1(printk("%s(): Unmapped request buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle));
+       }
+ }
+@@ -1144,9 +1153,9 @@
+     struct scatterlist *psgl;
+     pSRB->TotalXferredLen = 0;
+     pSRB->SGIndex = 0;
+-    if (scsi_sg_count(pcmd)) {
++    if (pcmd->use_sg) {
+       size_t saved;
+-      pSRB->pSegmentList = scsi_sglist(pcmd);
++      pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer;
+       psgl = pSRB->pSegmentList;
+       //dc390_pci_sync(pSRB);
+@@ -1170,6 +1179,12 @@
+       printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
+               pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
++    } else if(pcmd->request_buffer) {
++      //dc390_pci_sync(pSRB);
 +
-+static inline int
-+iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      return test_bit(5, &status);
-+}
++      sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen - pSRB->Saved_Ptr;
++      pSRB->SGcount = 1;
++      pSRB->pSegmentList = (struct scatterlist *) &pSRB->Segmentx;
+     } else {
+        pSRB->SGcount = 0;
+        printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n");
+@@ -1564,8 +1579,7 @@
+       if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
+          !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
+       {       /* Selection time out */
+-              pSRB->AdaptStatus = H_SEL_TIMEOUT;
+-              pSRB->TargetStatus = 0;
++              pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT;
+               goto  disc1;
+       }
+       else if (!(pSRB->SRBState & SRB_DISCONNECT) && (pSRB->SRBState & SRB_COMPLETED))
+@@ -1598,7 +1612,7 @@
+       if( !( pACB->scan_devices ) )
+       {
+           struct scsi_cmnd *pcmd = pSRB->pcmd;
+-          scsi_set_resid(pcmd, scsi_bufflen(pcmd));
++          pcmd->resid = pcmd->request_bufflen;
+           SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
+           dc390_Going_remove(pDCB, pSRB);
+           dc390_Free_insert(pACB, pSRB);
+@@ -1681,7 +1695,7 @@
+                             pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
+       pSRB->SRBFlag |= AUTO_REQSENSE;
+-      pSRB->SavedSGCount = scsi_sg_count(pcmd);
++      pSRB->SavedSGCount = pcmd->use_sg;
+       pSRB->SavedTotXLen = pSRB->TotalXferredLen;
+       pSRB->AdaptStatus = 0;
+       pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
+@@ -1714,22 +1728,22 @@
+     { /* Last command was a Request Sense */
+       pSRB->SRBFlag &= ~AUTO_REQSENSE;
+       pSRB->AdaptStatus = 0;
+-      pSRB->TargetStatus = SAM_STAT_CHECK_CONDITION;
++      pSRB->TargetStatus = CHECK_CONDITION << 1;
+       //pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
+-      if (status == SAM_STAT_CHECK_CONDITION)
++      if (status == (CHECK_CONDITION << 1))
+           pcmd->result = MK_RES_LNX(0, DID_BAD_TARGET, 0, /*CHECK_CONDITION*/0);
+       else /* Retry */
+       {
+           if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */)
+           {
+               /* Don't retry on TEST_UNIT_READY */
+-              pcmd->result = MK_RES_LNX(DRIVER_SENSE, DID_OK, 0, SAM_STAT_CHECK_CONDITION);
++              pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION);
+               REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\
+                      (u32) pcmd->result, (u32) pSRB->TotalXferredLen));
+           } else {
+               SET_RES_DRV(pcmd->result, DRIVER_SENSE);
+-              scsi_sg_count(pcmd) = pSRB->SavedSGCount;
++              pcmd->use_sg = pSRB->SavedSGCount;
+               //pSRB->ScsiCmdLen       = (u8) (pSRB->Segment1[0] >> 8);
+               DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
+               pSRB->TotalXferredLen = 0;
+@@ -1740,7 +1754,7 @@
+     }
+     if( status )
+     {
+-      if (status == SAM_STAT_CHECK_CONDITION)
++      if( status_byte(status) == CHECK_CONDITION )
+       {
+           if (dc390_RequestSense(pACB, pDCB, pSRB)) {
+               SET_RES_DID(pcmd->result, DID_ERROR);
+@@ -1748,15 +1762,22 @@
+           }
+           return;
+       }
+-      else if (status == SAM_STAT_TASK_SET_FULL)
++      else if( status_byte(status) == QUEUE_FULL )
+       {
+           scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1);
+-          scsi_sg_count(pcmd) = pSRB->SavedSGCount;
++          pcmd->use_sg = pSRB->SavedSGCount;
+           DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
+           pSRB->TotalXferredLen = 0;
+           SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
+       }
+-      else if (status == SAM_STAT_BUSY &&
++      else if(status == SCSI_STAT_SEL_TIMEOUT)
++      {
++          pSRB->AdaptStatus = H_SEL_TIMEOUT;
++          pSRB->TargetStatus = 0;
++          pcmd->result = MK_RES(0,DID_NO_CONNECT,0,0);
++          /* Devices are removed below ... */
++      }
++      else if (status_byte(status) == BUSY && 
+                (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) &&
+                pACB->scan_devices)
+       {
+@@ -1774,17 +1795,12 @@
+     else
+     { /*  Target status == 0 */
+       status = pSRB->AdaptStatus;
+-      if (status == H_OVER_UNDER_RUN)
++      if(status & H_OVER_UNDER_RUN)
+       {
+           pSRB->TargetStatus = 0;
+           SET_RES_DID(pcmd->result,DID_OK);
+           SET_RES_MSG(pcmd->result,pSRB->EndMessage);
+       }
+-      else if (status == H_SEL_TIMEOUT)
+-      {
+-          pcmd->result = MK_RES(0, DID_NO_CONNECT, 0, 0);
+-          /* Devices are removed below ... */
+-      }
+       else if( pSRB->SRBStatus & PARITY_ERROR)
+       {
+           //pcmd->result = MK_RES(0,DID_PARITY,pSRB->EndMessage,0);
+@@ -1800,7 +1816,7 @@
+     }
+ cmd_done:
+-    scsi_set_resid(pcmd, scsi_bufflen(pcmd) - pSRB->TotalXferredLen);
++    pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen;
+     dc390_Going_remove (pDCB, pSRB);
+     /* Add to free list */
+diff -Nurb linux-2.6.22-590/drivers/scsi/tmscsim.h linux-2.6.22-570/drivers/scsi/tmscsim.h
+--- linux-2.6.22-590/drivers/scsi/tmscsim.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/tmscsim.h    2007-07-08 19:32:17.000000000 -0400
+@@ -258,6 +258,13 @@
+ #define H_BAD_CCB_OR_SG  0x1A
+ #define H_ABORT        0x0FF
++/*; SCSI Status byte codes*/ 
++/* The values defined in include/scsi/scsi.h, to be shifted << 1 */
 +
-+static inline int
-+iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      return test_bit(4, &status);
-+}
++#define SCSI_STAT_UNEXP_BUS_F 0xFD    /*;  Unexpect Bus Free */
++#define SCSI_STAT_BUS_RST_DETECT 0xFE /*;  Scsi Bus Reset detected */
++#define SCSI_STAT_SEL_TIMEOUT 0xFF    /*;  Selection Time out */
 +
-+static inline int
-+iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      return test_bit(3, &status);
-+}
+ /* cmd->result */
+ #define RES_TARGET            0x000000FF      /* Target State */
+ #define RES_TARGET_LNX                STATUS_MASK     /* Only official ... */
+@@ -266,7 +273,7 @@
+ #define RES_DRV                       0xFF000000      /* DRIVER_ codes */
+ #define MK_RES(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))
+-#define MK_RES_LNX(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))
++#define MK_RES_LNX(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt)<<1)
+ #define SET_RES_TARGET(who, tgt) do { who &= ~RES_TARGET; who |= (int)(tgt); } while (0)
+ #define SET_RES_TARGET_LNX(who, tgt) do { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; } while (0)
+diff -Nurb linux-2.6.22-590/drivers/scsi/u14-34f.c linux-2.6.22-570/drivers/scsi/u14-34f.c
+--- linux-2.6.22-590/drivers/scsi/u14-34f.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/u14-34f.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1111,7 +1111,7 @@
+ static void map_dma(unsigned int i, unsigned int j) {
+    unsigned int data_len = 0;
+    unsigned int k, count, pci_dir;
+-   struct scatterlist *sg;
++   struct scatterlist *sgpnt;
+    struct mscp *cpp;
+    struct scsi_cmnd *SCpnt;
+@@ -1124,28 +1124,33 @@
+    cpp->sense_len = sizeof SCpnt->sense_buffer;
+-   if (scsi_bufflen(SCpnt)) {
+-         count = scsi_dma_map(SCpnt);
+-         BUG_ON(count < 0);
+-
+-         scsi_for_each_sg(SCpnt, sg, count, k) {
+-                 cpp->sglist[k].address = H2DEV(sg_dma_address(sg));
+-                 cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(sg));
+-                 data_len += sg->length;
++   if (!SCpnt->use_sg) {
 +
-+static inline int
-+iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      return 0;
-+}
++      /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */
++      if (!SCpnt->request_bufflen) pci_dir = PCI_DMA_BIDIRECTIONAL;
 +
-+static inline int
-+iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      return 0;
-+}
++      if (SCpnt->request_buffer)
++         cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,
++                  SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));
 +
-+static inline int
-+iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      return 0;
-+}
++      cpp->data_len = H2DEV(SCpnt->request_bufflen);
++      return;
+       }
+-   cpp->sg = TRUE;
+-         cpp->use_sg = scsi_sg_count(SCpnt);
+-         cpp->data_address =
+-                 H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist,
+-                                      cpp->use_sg * sizeof(struct sg_list),
+-                                      pci_dir));
+-   cpp->data_len = H2DEV(data_len);
++   sgpnt = (struct scatterlist *) SCpnt->request_buffer;
++   count = pci_map_sg(HD(j)->pdev, sgpnt, SCpnt->use_sg, pci_dir);
+-   } else {
+-         pci_dir = PCI_DMA_BIDIRECTIONAL;
+-         cpp->data_len = H2DEV(scsi_bufflen(SCpnt));
++   for (k = 0; k < count; k++) {
++      cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
++      cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
++      data_len += sgpnt[k].length;
+    }
 +
-+#endif /* _ADMA_H */
-diff -Nurb linux-2.6.22-570/include/asm-arm/arch-iop13xx/iop13xx.h linux-2.6.22-590/include/asm-arm/arch-iop13xx/iop13xx.h
---- linux-2.6.22-570/include/asm-arm/arch-iop13xx/iop13xx.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-arm/arch-iop13xx/iop13xx.h    2008-01-02 13:56:37.000000000 -0500
-@@ -166,12 +166,22 @@
- #define IOP13XX_INIT_I2C_1          (1 << 1)
- #define IOP13XX_INIT_I2C_2          (1 << 2)
++   cpp->sg = TRUE;
++   cpp->use_sg = SCpnt->use_sg;
++   cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist,
++                             SCpnt->use_sg * sizeof(struct sg_list), pci_dir));
++   cpp->data_len = H2DEV(data_len);
+ }
+ static void unmap_dma(unsigned int i, unsigned int j) {
+@@ -1160,7 +1165,8 @@
+       pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
+                        DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+-   scsi_dma_unmap(SCpnt);
++   if (SCpnt->use_sg)
++      pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);
+    if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
+@@ -1181,9 +1187,9 @@
+       pci_dma_sync_single_for_cpu(HD(j)->pdev, DEV2H(cpp->sense_addr),
+                           DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+-   if (scsi_sg_count(SCpnt))
+-         pci_dma_sync_sg_for_cpu(HD(j)->pdev, scsi_sglist(SCpnt),
+-                                 scsi_sg_count(SCpnt), pci_dir);
++   if (SCpnt->use_sg)
++      pci_dma_sync_sg_for_cpu(HD(j)->pdev, SCpnt->request_buffer,
++                         SCpnt->use_sg, pci_dir);
+    if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
+diff -Nurb linux-2.6.22-590/drivers/scsi/ultrastor.c linux-2.6.22-570/drivers/scsi/ultrastor.c
+--- linux-2.6.22-590/drivers/scsi/ultrastor.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/ultrastor.c  2007-07-08 19:32:17.000000000 -0400
+@@ -675,15 +675,16 @@
+ static inline void build_sg_list(struct mscp *mscp, struct scsi_cmnd *SCpnt)
+ {
+-      struct scatterlist *sg;
++      struct scatterlist *sl;
+       long transfer_length = 0;
+       int i, max;
+-      max = scsi_sg_count(SCpnt);
+-      scsi_for_each_sg(SCpnt, sg, max, i) {
+-              mscp->sglist[i].address = isa_page_to_bus(sg->page) + sg->offset;
+-              mscp->sglist[i].num_bytes = sg->length;
+-              transfer_length += sg->length;
++      sl = (struct scatterlist *) SCpnt->request_buffer;
++      max = SCpnt->use_sg;
++      for (i = 0; i < max; i++) {
++              mscp->sglist[i].address = isa_page_to_bus(sl[i].page) + sl[i].offset;
++              mscp->sglist[i].num_bytes = sl[i].length;
++              transfer_length += sl[i].length;
+       }
+       mscp->number_of_sg_list = max;
+       mscp->transfer_data = isa_virt_to_bus(mscp->sglist);
+@@ -729,15 +730,15 @@
+     my_mscp->target_id = SCpnt->device->id;
+     my_mscp->ch_no = 0;
+     my_mscp->lun = SCpnt->device->lun;
+-    if (scsi_sg_count(SCpnt)) {
++    if (SCpnt->use_sg) {
+       /* Set scatter/gather flag in SCSI command packet */
+       my_mscp->sg = TRUE;
+       build_sg_list(my_mscp, SCpnt);
+     } else {
+       /* Unset scatter/gather flag in SCSI command packet */
+       my_mscp->sg = FALSE;
+-      my_mscp->transfer_data = isa_virt_to_bus(scsi_sglist(SCpnt));
+-      my_mscp->transfer_data_length = scsi_bufflen(SCpnt);
++      my_mscp->transfer_data = isa_virt_to_bus(SCpnt->request_buffer);
++      my_mscp->transfer_data_length = SCpnt->request_bufflen;
+     }
+     my_mscp->command_link = 0;                /*???*/
+     my_mscp->scsi_command_link_id = 0;        /*???*/
+diff -Nurb linux-2.6.22-590/drivers/scsi/wd7000.c linux-2.6.22-570/drivers/scsi/wd7000.c
+--- linux-2.6.22-590/drivers/scsi/wd7000.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/wd7000.c     2007-07-08 19:32:17.000000000 -0400
+@@ -1091,7 +1091,6 @@
+       unchar *cdb = (unchar *) SCpnt->cmnd;
+       unchar idlun;
+       short cdblen;
+-      int nseg;
+       Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
+       cdblen = SCpnt->cmd_len;
+@@ -1107,29 +1106,28 @@
+       SCpnt->host_scribble = (unchar *) scb;
+       scb->host = host;
+-      nseg = scsi_sg_count(SCpnt);
+-      if (nseg) {
+-              struct scatterlist *sg;
++      if (SCpnt->use_sg) {
++              struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
+               unsigned i;
+               if (SCpnt->device->host->sg_tablesize == SG_NONE) {
+                       panic("wd7000_queuecommand: scatter/gather not supported.\n");
+               }
+-              dprintk("Using scatter/gather with %d elements.\n", nseg);
++              dprintk("Using scatter/gather with %d elements.\n", SCpnt->use_sg);
+               sgb = scb->sgb;
+               scb->op = 1;
+               any2scsi(scb->dataptr, (int) sgb);
+-              any2scsi(scb->maxlen, nseg * sizeof(Sgb));
++              any2scsi(scb->maxlen, SCpnt->use_sg * sizeof(Sgb));
+-              scsi_for_each_sg(SCpnt, sg, nseg, i) {
+-                      any2scsi(sgb[i].ptr, isa_page_to_bus(sg->page) + sg->offset);
+-                      any2scsi(sgb[i].len, sg->length);
++              for (i = 0; i < SCpnt->use_sg; i++) {
++                      any2scsi(sgb[i].ptr, isa_page_to_bus(sg[i].page) + sg[i].offset);
++                      any2scsi(sgb[i].len, sg[i].length);
+               }
+       } else {
+               scb->op = 0;
+-              any2scsi(scb->dataptr, isa_virt_to_bus(scsi_sglist(SCpnt)));
+-              any2scsi(scb->maxlen, scsi_bufflen(SCpnt));
++              any2scsi(scb->dataptr, isa_virt_to_bus(SCpnt->request_buffer));
++              any2scsi(scb->maxlen, SCpnt->request_bufflen);
+       }
+       /* FIXME: drop lock and yield here ? */
+diff -Nurb linux-2.6.22-590/drivers/scsi/zorro7xx.c linux-2.6.22-570/drivers/scsi/zorro7xx.c
+--- linux-2.6.22-590/drivers/scsi/zorro7xx.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/scsi/zorro7xx.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,180 +0,0 @@
+-/*
+- * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
+- *            Amiga MacroSystemUS WarpEngine SCSI controller.
+- *            Amiga Technologies/DKB A4091 SCSI controller.
+- *
+- * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
+- * plus modifications of the 53c7xx.c driver to support the Amiga.
+- *
+- * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
+- */
+-
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/zorro.h>
+-#include <asm/amigaints.h>
+-#include <scsi/scsi_host.h>
+-#include <scsi/scsi_transport_spi.h>
+-
+-#include "53c700.h"
+-
+-MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>");
+-MODULE_DESCRIPTION("Amiga Zorro NCR53C710 driver");
+-MODULE_LICENSE("GPL");
+-
+-
+-static struct scsi_host_template zorro7xx_scsi_driver_template = {
+-      .proc_name      = "zorro7xx",
+-      .this_id        = 7,
+-      .module         = THIS_MODULE,
+-};
+-
+-static struct zorro_driver_data {
+-      const char *name;
+-      unsigned long offset;
+-      int absolute;   /* offset is absolute address */
+-} zorro7xx_driver_data[] __devinitdata = {
+-      { .name = "PowerUP 603e+", .offset = 0xf40000, .absolute = 1 },
+-      { .name = "WarpEngine 40xx", .offset = 0x40000 },
+-      { .name = "A4091", .offset = 0x800000 },
+-      { .name = "GForce 040/060", .offset = 0x40000 },
+-      { 0 }
+-};
+-
+-static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = {
+-      {
+-              .id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS,
+-              .driver_data = (unsigned long)&zorro7xx_driver_data[0],
+-      },
+-      {
+-              .id = ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx,
+-              .driver_data = (unsigned long)&zorro7xx_driver_data[1],
+-      },
+-      {
+-              .id = ZORRO_PROD_CBM_A4091_1,
+-              .driver_data = (unsigned long)&zorro7xx_driver_data[2],
+-      },
+-      {
+-              .id = ZORRO_PROD_CBM_A4091_2,
+-              .driver_data = (unsigned long)&zorro7xx_driver_data[2],
+-      },
+-      {
+-              .id = ZORRO_PROD_GVP_GFORCE_040_060,
+-              .driver_data = (unsigned long)&zorro7xx_driver_data[3],
+-      },
+-      { 0 }
+-};
+-
+-static int __devinit zorro7xx_init_one(struct zorro_dev *z,
+-                                     const struct zorro_device_id *ent)
+-{
+-      struct Scsi_Host * host = NULL;
+-      struct NCR_700_Host_Parameters *hostdata;
+-      struct zorro_driver_data *zdd;
+-      unsigned long board, ioaddr;
+-
+-      board = zorro_resource_start(z);
+-      zdd = (struct zorro_driver_data *)ent->driver_data;
+-
+-      if (zdd->absolute) {
+-              ioaddr = zdd->offset;
+-      } else {
+-              ioaddr = board + zdd->offset;
+-      }
+-
+-      if (!zorro_request_device(z, zdd->name)) {
+-              printk(KERN_ERR "zorro7xx: cannot reserve region 0x%lx, abort\n",
+-                     board);
+-              return -EBUSY;
+-      }
+-
+-      hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+-      if (hostdata == NULL) {
+-              printk(KERN_ERR "zorro7xx: Failed to allocate host data\n");
+-              goto out_release;
+-      }
+-
+-      memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
+-
+-      /* Fill in the required pieces of hostdata */
+-      if (ioaddr > 0x01000000)
+-              hostdata->base = ioremap(ioaddr, zorro_resource_len(z));
+-      else
+-              hostdata->base = (void __iomem *)ZTWO_VADDR(ioaddr);
+-
+-      hostdata->clock = 50;
+-      hostdata->chip710 = 1;
+-
+-      /* Settings for at least WarpEngine 40xx */
+-      hostdata->ctest7_extra = CTEST7_TT1;
+-
+-      zorro7xx_scsi_driver_template.name = zdd->name;
+-
+-      /* and register the chip */
+-      host = NCR_700_detect(&zorro7xx_scsi_driver_template, hostdata,
+-                            &z->dev);
+-      if (!host) {
+-              printk(KERN_ERR "zorro7xx: No host detected; "
+-                              "board configuration problem?\n");
+-              goto out_free;
+-      }
+-
+-      host->this_id = 7;
+-      host->base = ioaddr;
+-      host->irq = IRQ_AMIGA_PORTS;
+-
+-      if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "zorro7xx-scsi",
+-                      host)) {
+-              printk(KERN_ERR "zorro7xx: request_irq failed\n");
+-              goto out_put_host;
+-      }
+-
+-      scsi_scan_host(host);
+-
+-      return 0;
+-
+- out_put_host:
+-      scsi_host_put(host);
+- out_free:
+-      if (ioaddr > 0x01000000)
+-              iounmap(hostdata->base);
+-      kfree(hostdata);
+- out_release:
+-      zorro_release_device(z);
+-
+-      return -ENODEV;
+-}
+-
+-static __devexit void zorro7xx_remove_one(struct zorro_dev *z)
+-{
+-      struct Scsi_Host *host = dev_to_shost(&z->dev);
+-      struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
+-
+-      scsi_remove_host(host);
+-
+-      NCR_700_release(host);
+-      kfree(hostdata);
+-      free_irq(host->irq, host);
+-      zorro_release_device(z);
+-}
+-
+-static struct zorro_driver zorro7xx_driver = {
+-      .name     = "zorro7xx-scsi",
+-      .id_table = zorro7xx_zorro_tbl,
+-      .probe    = zorro7xx_init_one,
+-      .remove   = __devexit_p(zorro7xx_remove_one),
+-};
+-
+-static int __init zorro7xx_scsi_init(void)
+-{
+-      return zorro_register_driver(&zorro7xx_driver);
+-}
+-
+-static void __exit zorro7xx_scsi_exit(void)
+-{
+-      zorro_unregister_driver(&zorro7xx_driver);
+-}
+-
+-module_init(zorro7xx_scsi_init);
+-module_exit(zorro7xx_scsi_exit);
+diff -Nurb linux-2.6.22-590/drivers/serial/8250.c linux-2.6.22-570/drivers/serial/8250.c
+--- linux-2.6.22-590/drivers/serial/8250.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/8250.c     2007-07-08 19:32:17.000000000 -0400
+@@ -2845,25 +2845,6 @@
+ }
+ EXPORT_SYMBOL(serial8250_unregister_port);
+-/**
+- *    serial8250_unregister_by_port - remove a 16x50 serial port
+- *    at runtime.
+- *    @port: A &struct uart_port that describes the port to remove.
+- *
+- *    Remove one serial port.  This may not be called from interrupt
+- *    context.  We hand the port back to the our control.
+- */
+-void serial8250_unregister_by_port(struct uart_port *port)
+-{
+-      struct uart_8250_port *uart;
+-
+-      uart = serial8250_find_match_or_unused(port);
+-
+-      if (uart)
+-              serial8250_unregister_port(uart->port.line);
+-}
+-EXPORT_SYMBOL(serial8250_unregister_by_port);
+-
+ static int __init serial8250_init(void)
+ {
+       int ret, i;
+diff -Nurb linux-2.6.22-590/drivers/serial/8250_kgdb.c linux-2.6.22-570/drivers/serial/8250_kgdb.c
+--- linux-2.6.22-590/drivers/serial/8250_kgdb.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/8250_kgdb.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,515 +0,0 @@
+-/*
+- * 8250 interface for kgdb.
+- *
+- * This is a merging of many different drivers, and all of the people have
+- * had an impact in some form or another:
+- *
+- * 2004-2005 (c) MontaVista Software, Inc.
+- * 2005-2006 (c) Wind River Systems, Inc.
+- *
+- * Amit Kale <amitkale@emsyssoft.com>, David Grothe <dave@gcom.com>,
+- * Scott Foehner <sfoehner@engr.sgi.com>, George Anzinger <george@mvista.com>,
+- * Robert Walsh <rjwalsh@durables.org>, wangdi <wangdi@clusterfs.com>,
+- * San Mehat, Tom Rini <trini@mvista.com>,
+- * Jason Wessel <jason.wessel@windriver.com>
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/kgdb.h>
+-#include <linux/interrupt.h>
+-#include <linux/tty.h>
+-#include <linux/serial.h>
+-#include <linux/serial_reg.h>
+-#include <linux/serialP.h>
+-#include <linux/ioport.h>
+-
+-#include <asm/io.h>
+-#include <asm/serial.h>               /* For BASE_BAUD and SERIAL_PORT_DFNS */
+-
+-#include "8250.h"
+-
+-#define GDB_BUF_SIZE  512     /* power of 2, please */
+-
+-MODULE_DESCRIPTION("KGDB driver for the 8250");
+-MODULE_LICENSE("GPL");
+-/* These will conflict with early_param otherwise. */
+-#ifdef CONFIG_KGDB_8250_MODULE
+-static char config[256];
+-module_param_string(kgdb8250, config, 256, 0);
+-MODULE_PARM_DESC(kgdb8250,
+-               " kgdb8250=<io or mmio>,<address>,<baud rate>,<irq>\n");
+-static struct kgdb_io local_kgdb_io_ops;
+-#endif                                /* CONFIG_KGDB_8250_MODULE */
+-
+-/* Speed of the UART. */
+-static int kgdb8250_baud;
+-
+-/* Flag for if we need to call request_mem_region */
+-static int kgdb8250_needs_request_mem_region;
+-
+-static char kgdb8250_buf[GDB_BUF_SIZE];
+-static atomic_t kgdb8250_buf_in_cnt;
+-static int kgdb8250_buf_out_inx;
+-
+-/* Old-style serial definitions, if existant, and a counter. */
+-#ifdef CONFIG_KGDB_SIMPLE_SERIAL
+-static int __initdata should_copy_rs_table = 1;
+-static struct serial_state old_rs_table[] __initdata = {
+-#ifdef SERIAL_PORT_DFNS
+-      SERIAL_PORT_DFNS
+-#endif
+-};
+-#endif
+-
+-/* Our internal table of UARTS. */
+-#define UART_NR       CONFIG_SERIAL_8250_NR_UARTS
+-static struct uart_port kgdb8250_ports[UART_NR];
+-
+-static struct uart_port *current_port;
+-
+-/* Base of the UART. */
+-static void *kgdb8250_addr;
+-
+-/* Forward declarations. */
+-static int kgdb8250_uart_init(void);
+-static int __init kgdb_init_io(void);
+-static int __init kgdb8250_opt(char *str);
+-
+-/* These are much shorter calls to ioread8/iowrite8 that take into
+- * account our shifts, etc. */
+-static inline unsigned int kgdb_ioread(u8 mask)
+-{
+-      return ioread8(kgdb8250_addr + (mask << current_port->regshift));
+-}
+-
+-static inline void kgdb_iowrite(u8 val, u8 mask)
+-{
+-      iowrite8(val, kgdb8250_addr + (mask << current_port->regshift));
+-}
+-
+-/*
+- * Wait until the interface can accept a char, then write it.
+- */
+-static void kgdb_put_debug_char(u8 chr)
+-{
+-      while (!(kgdb_ioread(UART_LSR) & UART_LSR_THRE)) ;
+-
+-      kgdb_iowrite(chr, UART_TX);
+-}
+-
+-/*
+- * Get a byte from the hardware data buffer and return it
+- */
+-static int read_data_bfr(void)
+-{
+-      char it = kgdb_ioread(UART_LSR);
+-
+-      if (it & UART_LSR_DR)
+-              return kgdb_ioread(UART_RX);
+-
+-      /*
+-       * If we have a framing error assume somebody messed with
+-       * our uart.  Reprogram it and send '-' both ways...
+-       */
+-      if (it & 0xc) {
+-              kgdb8250_uart_init();
+-              kgdb_put_debug_char('-');
+-              return '-';
+-      }
+-
+-      return -1;
+-}
+-
+-/*
+- * Get a char if available, return -1 if nothing available.
+- * Empty the receive buffer first, then look at the interface hardware.
+- */
+-static int kgdb_get_debug_char(void)
+-{
+-      int retchr;
+-
+-      /* intr routine has q'd chars */
+-      if (atomic_read(&kgdb8250_buf_in_cnt) != 0) {
+-              retchr = kgdb8250_buf[kgdb8250_buf_out_inx++];
+-              kgdb8250_buf_out_inx &= (GDB_BUF_SIZE - 1);
+-              atomic_dec(&kgdb8250_buf_in_cnt);
+-              return retchr;
+-      }
+-
+-      do {
+-              retchr = read_data_bfr();
+-      } while (retchr < 0);
+-
+-      return retchr;
+-}
+-
+-/*
+- * This is the receiver interrupt routine for the GDB stub.
+- * All that we need to do is verify that the interrupt happened on the
+- * line we're in charge of.  If this is true, schedule a breakpoint and
+- * return.
+- */
+-static irqreturn_t
+-kgdb8250_interrupt(int irq, void *dev_id)
+-{
+-      if (kgdb_ioread(UART_IIR) & UART_IIR_RDI) {
+-              /* Throw away the data if another I/O routine is active. */
+-              if (kgdb_io_ops.read_char != kgdb_get_debug_char &&
+-                              (kgdb_ioread(UART_LSR) & UART_LSR_DR))
+-                      kgdb_ioread(UART_RX);
+-              else
+-                      breakpoint();
+-      }
+-
+-      return IRQ_HANDLED;
+-}
+-
+-/*
+- *  Initializes the UART.
+- *  Returns:
+- *    0 on success, 1 on failure.
+- */
+-static int
+-kgdb8250_uart_init (void)
+-{
+-      unsigned int ier, base_baud = current_port->uartclk ?
+-              current_port->uartclk / 16 : BASE_BAUD;
+-
+-      /* test uart existance */
+-      if(kgdb_ioread(UART_LSR) == 0xff)
+-              return -1;
+-
+-      /* disable interrupts */
+-      kgdb_iowrite(0, UART_IER);
+-
+-#if defined(CONFIG_ARCH_OMAP1510)
+-      /* Workaround to enable 115200 baud on OMAP1510 internal ports */
+-      if (cpu_is_omap1510() && is_omap_port((void *)kgdb8250_addr)) {
+-              if (kgdb8250_baud == 115200) {
+-                      base_baud = 1;
+-                      kgdb8250_baud = 1;
+-                      kgdb_iowrite(1, UART_OMAP_OSC_12M_SEL);
+-              } else
+-                      kgdb_iowrite(0, UART_OMAP_OSC_12M_SEL);
+-      }
+-#endif
+-      /* set DLAB */
+-      kgdb_iowrite(UART_LCR_DLAB, UART_LCR);
+-
+-      /* set baud */
+-      kgdb_iowrite((base_baud / kgdb8250_baud) & 0xff, UART_DLL);
+-      kgdb_iowrite((base_baud / kgdb8250_baud) >> 8, UART_DLM);
+-
+-      /* reset DLAB, set LCR */
+-      kgdb_iowrite(UART_LCR_WLEN8, UART_LCR);
+-
+-      /* set DTR and RTS */
+-      kgdb_iowrite(UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS, UART_MCR);
+-
+-      /* setup fifo */
+-      kgdb_iowrite(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR
+-              | UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_8,
+-              UART_FCR);
+-
+-      /* clear pending interrupts */
+-      kgdb_ioread(UART_IIR);
+-      kgdb_ioread(UART_RX);
+-      kgdb_ioread(UART_LSR);
+-      kgdb_ioread(UART_MSR);
+-
+-      /* turn on RX interrupt only */
+-      kgdb_iowrite(UART_IER_RDI, UART_IER);
+-
+-      /*
+-       * Borrowed from the main 8250 driver.
+-       * Try writing and reading the UART_IER_UUE bit (b6).
+-       * If it works, this is probably one of the Xscale platform's
+-       * internal UARTs.
+-       * We're going to explicitly set the UUE bit to 0 before
+-       * trying to write and read a 1 just to make sure it's not
+-       * already a 1 and maybe locked there before we even start start.
+-       */
+-      ier = kgdb_ioread(UART_IER);
+-      kgdb_iowrite(ier & ~UART_IER_UUE, UART_IER);
+-      if (!(kgdb_ioread(UART_IER) & UART_IER_UUE)) {
+-              /*
+-               * OK it's in a known zero state, try writing and reading
+-               * without disturbing the current state of the other bits.
+-               */
+-              kgdb_iowrite(ier | UART_IER_UUE, UART_IER);
+-              if (kgdb_ioread(UART_IER) & UART_IER_UUE)
+-                      /*
+-                       * It's an Xscale.
+-                       */
+-                      ier |= UART_IER_UUE | UART_IER_RTOIE;
+-      }
+-      kgdb_iowrite(ier, UART_IER);
+-      return 0;
+-}
+-
+-/*
+- * Copy the old serial_state table to our uart_port table if we haven't
+- * had values specifically configured in.  We need to make sure this only
+- * happens once.
+- */
+-static void __init kgdb8250_copy_rs_table(void)
+-{
+-#ifdef CONFIG_KGDB_SIMPLE_SERIAL
+-      int i;
+-
+-      if (!should_copy_rs_table)
+-              return;
+-
+-      for (i = 0; i < ARRAY_SIZE(old_rs_table); i++) {
+-              kgdb8250_ports[i].iobase = old_rs_table[i].port;
+-              kgdb8250_ports[i].irq = irq_canonicalize(old_rs_table[i].irq);
+-              kgdb8250_ports[i].uartclk = old_rs_table[i].baud_base * 16;
+-              kgdb8250_ports[i].membase = old_rs_table[i].iomem_base;
+-              kgdb8250_ports[i].iotype = old_rs_table[i].io_type;
+-              kgdb8250_ports[i].regshift = old_rs_table[i].iomem_reg_shift;
+-              kgdb8250_ports[i].line = i;
+-      }
+-
+-      should_copy_rs_table = 0;
+-#endif
+-}
+-
+-/*
+- * Hookup our IRQ line now that it is safe to do so, after we grab any
+- * memory regions we might need to.  If we haven't been initialized yet,
+- * go ahead and copy the old_rs_table in.
+- */
+-static void __init kgdb8250_late_init(void)
+-{
+-      /* Try and copy the old_rs_table. */
+-      kgdb8250_copy_rs_table();
+-
+-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+-      /* Take the port away from the main driver. */
+-      serial8250_unregister_by_port(current_port);
+-
+-      /* Now reinit the port as the above has disabled things. */
+-      kgdb8250_uart_init();
+-#endif
+-      /* We may need to call request_mem_region() first. */
+-      if (kgdb8250_needs_request_mem_region)
+-              request_mem_region(current_port->mapbase,
+-                                 8 << current_port->regshift, "kgdb");
+-      if (request_irq(current_port->irq, kgdb8250_interrupt, SA_SHIRQ,
+-                      "GDB-stub", current_port) < 0)
+-              printk(KERN_ERR "KGDB failed to request the serial IRQ (%d)\n",
+-                     current_port->irq);
+-}
+-
+-static __init int kgdb_init_io(void)
+-{
+-      /* Give us the basic table of uarts. */
+-      kgdb8250_copy_rs_table();
+-
+-      /* We're either a module and parse a config string, or we have a
+-       * semi-static config. */
+-#ifdef CONFIG_KGDB_8250_MODULE
+-      if (strlen(config)) {
+-              if (kgdb8250_opt(config))
+-                      return -EINVAL;
+-      } else {
+-              printk(KERN_ERR "kgdb8250: argument error, usage: "
+-                     "kgdb8250=<io or mmio>,<address>,<baud rate>,<irq>\n");
+-              return -EINVAL;
+-      }
+-#elif defined(CONFIG_KGDB_SIMPLE_SERIAL)
+-      kgdb8250_baud = CONFIG_KGDB_BAUDRATE;
+-
+-      /* Setup our pointer to the serial port now. */
+-      current_port = &kgdb8250_ports[CONFIG_KGDB_PORT_NUM];
+-#else
+-      if (kgdb8250_opt(CONFIG_KGDB_8250_CONF_STRING))
+-              return -EINVAL;
+-#endif
+-
+-
+-      /* Internal driver setup. */
+-      switch (current_port->iotype) {
+-      case UPIO_MEM:
+-              if (current_port->mapbase)
+-                      kgdb8250_needs_request_mem_region = 1;
+-              if (current_port->flags & UPF_IOREMAP) {
+-                      current_port->membase = ioremap(current_port->mapbase,
+-                                              8 << current_port->regshift);
+-                      if (!current_port->membase)
+-                              return -EIO;    /* Failed. */
+-              }
+-              kgdb8250_addr = current_port->membase;
+-              break;
+-      case UPIO_PORT:
+-      default:
+-              kgdb8250_addr = ioport_map(current_port->iobase,
+-                                         8 << current_port->regshift);
+-              if (!kgdb8250_addr)
+-                      return -EIO;    /* Failed. */
+-      }
+-
+-      if (kgdb8250_uart_init() == -1) {
+-              printk(KERN_ERR "kgdb8250: init failed\n");
+-              return -EIO;
+-      }
+-#ifdef CONFIG_KGDB_8250_MODULE
+-      /* Attach the kgdb irq. When this is built into the kernel, it
+-       * is called as a part of late_init sequence.
+-       */
+-      kgdb8250_late_init();
+-      if (kgdb_register_io_module(&local_kgdb_io_ops))
+-              return -EINVAL;
+-
+-      printk(KERN_INFO "kgdb8250: debugging enabled\n");
+-#endif                                /* CONFIG_KGD_8250_MODULE */
+-
+-      return 0;
+-}
+-
+-#ifdef CONFIG_KGDB_8250_MODULE
+-/* If it is a module the kgdb_io_ops should be a static which
+- * is passed to the KGDB I/O initialization
+- */
+-static struct kgdb_io local_kgdb_io_ops = {
+-#else                         /* ! CONFIG_KGDB_8250_MODULE */
+-struct kgdb_io kgdb_io_ops = {
+-#endif                                /* ! CONFIG_KGD_8250_MODULE */
+-      .read_char = kgdb_get_debug_char,
+-      .write_char = kgdb_put_debug_char,
+-      .init = kgdb_init_io,
+-      .late_init = kgdb8250_late_init,
+-};
+-
+-/**
+- *    kgdb8250_add_port - Define a serial port for use with KGDB
+- *    @i: The index of the port being added
+- *    @serial_req: The &struct uart_port describing the port
+- *
+- *    On platforms where we must register the serial device
+- *    dynamically, this is the best option if a platform also normally
+- *    calls early_serial_setup().
+- */
+-void __init kgdb8250_add_port(int i, struct uart_port *serial_req)
+-{
+-      /* Make sure we've got the built-in data before we override. */
+-      kgdb8250_copy_rs_table();
+-
+-      /* Copy the whole thing over. */
+-      if (current_port != &kgdb8250_ports[i])
+-                memcpy(&kgdb8250_ports[i], serial_req, sizeof(struct uart_port));
+-}
+-
+-/**
+- *    kgdb8250_add_platform_port - Define a serial port for use with KGDB
+- *    @i: The index of the port being added
+- *    @p: The &struct plat_serial8250_port describing the port
+- *
+- *    On platforms where we must register the serial device
+- *    dynamically, this is the best option if a platform normally
+- *    handles uart setup with an array of &struct plat_serial8250_port.
+- */
+-void __init kgdb8250_add_platform_port(int i, struct plat_serial8250_port *p)
+-{
+-      /* Make sure we've got the built-in data before we override. */
+-      kgdb8250_copy_rs_table();
+-
+-      kgdb8250_ports[i].iobase = p->iobase;
+-      kgdb8250_ports[i].membase = p->membase;
+-      kgdb8250_ports[i].irq = p->irq;
+-      kgdb8250_ports[i].uartclk = p->uartclk;
+-      kgdb8250_ports[i].regshift = p->regshift;
+-      kgdb8250_ports[i].iotype = p->iotype;
+-      kgdb8250_ports[i].flags = p->flags;
+-      kgdb8250_ports[i].mapbase = p->mapbase;
+-}
+-
+-/*
+- * Syntax for this cmdline option is:
+- * kgdb8250=<io or mmio>,<address>,<baud rate>,<irq>"
+- */
+-static int __init kgdb8250_opt(char *str)
+-{
+-      /* We'll fill out and use the first slot. */
+-      current_port = &kgdb8250_ports[0];
+-
+-      if (!strncmp(str, "io", 2)) {
+-              current_port->iotype = UPIO_PORT;
+-              str += 2;
+-      } else if (!strncmp(str, "mmap", 4)) {
+-              current_port->iotype = UPIO_MEM;
+-              current_port->flags |= UPF_IOREMAP;
+-              str += 4;
+-      } else if (!strncmp(str, "mmio", 4)) {
+-              current_port->iotype = UPIO_MEM;
+-              current_port->flags &= ~UPF_IOREMAP;
+-              str += 4;
+-      } else
+-              goto errout;
+-
+-      if (*str != ',')
+-              goto errout;
+-      str++;
+-
+-      if (current_port->iotype == UPIO_PORT)
+-              current_port->iobase = simple_strtoul(str, &str, 16);
+-      else {
+-              if (current_port->flags & UPF_IOREMAP)
+-                      current_port->mapbase =
+-                              (unsigned long) simple_strtoul(str, &str, 16);
+-              else
+-                      current_port->membase =
+-                              (void *) simple_strtoul(str, &str, 16);
+-      }
+-
+-      if (*str != ',')
+-              goto errout;
+-      str++;
+-
+-      kgdb8250_baud = simple_strtoul(str, &str, 10);
+-      if (!kgdb8250_baud)
+-              goto errout;
+-
+-      if (*str != ',')
+-              goto errout;
+-      str++;
+-
+-      current_port->irq = simple_strtoul(str, &str, 10);
+-
+-#ifdef CONFIG_KGDB_SIMPLE_SERIAL
+-      should_copy_rs_table = 0;
+-#endif
+-
+-      return 0;
+-
+-      errout:
+-      printk(KERN_ERR "Invalid syntax for option kgdb8250=\n");
+-      return 1;
+-}
+-
+-#ifdef CONFIG_KGDB_8250_MODULE
+-static void cleanup_kgdb8250(void)
+-{
+-      kgdb_unregister_io_module(&local_kgdb_io_ops);
+-
+-      /* Clean up the irq and memory */
+-      free_irq(current_port->irq, current_port);
+-
+-      if (kgdb8250_needs_request_mem_region)
+-              release_mem_region(current_port->mapbase,
+-                                 8 << current_port->regshift);
+-      /* Hook up the serial port back to what it was previously
+-       * hooked up to.
+-       */
+-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+-      /* Give the port back to the 8250 driver. */
+-      serial8250_register_port(current_port);
+-#endif
+-}
+-
+-module_init(kgdb_init_io);
+-module_exit(cleanup_kgdb8250);
+-#else                         /* ! CONFIG_KGDB_8250_MODULE */
+-early_param("kgdb8250", kgdb8250_opt);
+-#endif                                /* ! CONFIG_KGDB_8250_MODULE */
+diff -Nurb linux-2.6.22-590/drivers/serial/Kconfig linux-2.6.22-570/drivers/serial/Kconfig
+--- linux-2.6.22-590/drivers/serial/Kconfig    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/Kconfig    2008-01-23 19:15:55.000000000 -0500
+@@ -107,7 +107,7 @@
  
-+/* ADMA selection flags */
-+/* INIT_ADMA_DEFAULT = Rely on CONFIG_IOP13XX_ADMA* */
-+#define IOP13XX_INIT_ADMA_DEFAULT     (0)
-+#define IOP13XX_INIT_ADMA_0           (1 << 0)
-+#define IOP13XX_INIT_ADMA_1           (1 << 1)
-+#define IOP13XX_INIT_ADMA_2           (1 << 2)
-+
-+/* Platform devices */
- #define IQ81340_NUM_UART     2
- #define IQ81340_NUM_I2C      3
- #define IQ81340_NUM_PHYS_MAP_FLASH 1
--#define IQ81340_MAX_PLAT_DEVICES (IQ81340_NUM_UART +\
--                              IQ81340_NUM_I2C +\
--                              IQ81340_NUM_PHYS_MAP_FLASH)
-+#define IQ81340_NUM_ADMA              3
-+#define IQ81340_MAX_PLAT_DEVICES (IQ81340_NUM_UART + \
-+                              IQ81340_NUM_I2C + \
-+                              IQ81340_NUM_PHYS_MAP_FLASH + \
-+                              IQ81340_NUM_ADMA)
+ config SERIAL_8250_NR_UARTS
+       int "Maximum number of 8250/16550 serial ports"
+-      depends on SERIAL_8250 || KGDB_8250
++      depends on SERIAL_8250
+       default "4"
+       help
+         Set this to the number of serial ports you want the driver
+diff -Nurb linux-2.6.22-590/drivers/serial/Makefile linux-2.6.22-570/drivers/serial/Makefile
+--- linux-2.6.22-590/drivers/serial/Makefile   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/Makefile   2007-07-08 19:32:17.000000000 -0400
+@@ -23,7 +23,6 @@
+ obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o
+ obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
+ obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
+-obj-$(CONFIG_KGDB_AMBA_PL011) += pl011_kgdb.o
+ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
+ obj-$(CONFIG_SERIAL_PXA) += pxa.o
+ obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
+@@ -51,12 +50,10 @@
+ obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
+ obj-$(CONFIG_SERIAL_ICOM) += icom.o
+ obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
+-obj-$(CONFIG_KGDB_MPSC) += mpsc_kgdb.o
+ obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
+ obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
+ obj-$(CONFIG_SERIAL_JSM) += jsm/
+ obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
+-obj-$(CONFIG_KGDB_TXX9) += serial_txx9_kgdb.o
+ obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
+ obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
+ obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
+@@ -65,4 +62,3 @@
+ obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
+ obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
+ obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
+-obj-$(CONFIG_KGDB_8250) += 8250_kgdb.o
+diff -Nurb linux-2.6.22-590/drivers/serial/amba-pl011.c linux-2.6.22-570/drivers/serial/amba-pl011.c
+--- linux-2.6.22-590/drivers/serial/amba-pl011.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/amba-pl011.c       2007-07-08 19:32:17.000000000 -0400
+@@ -332,7 +332,7 @@
+       /*
+        * Allocate the IRQ
+        */
+-      retval = request_irq(uap->port.irq, pl011_int, SA_SHIRQ, "uart-pl011", uap);
++      retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
+       if (retval)
+               goto clk_dis;
  
- /*========================== PMMR offsets for key registers ============*/
- #define IOP13XX_ATU0_PMMR_OFFSET      0x00048000
-@@ -444,22 +454,6 @@
- /*==============================ADMA UNITS===============================*/
- #define IOP13XX_ADMA_PHYS_BASE(chan)  IOP13XX_REG_ADDR32_PHYS((chan << 9))
- #define IOP13XX_ADMA_UPPER_PA(chan)   (IOP13XX_ADMA_PHYS_BASE(chan) + 0xc0)
--#define IOP13XX_ADMA_OFFSET(chan, ofs)        IOP13XX_REG_ADDR32((chan << 9) + (ofs))
--
--#define IOP13XX_ADMA_ACCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x0)
--#define IOP13XX_ADMA_ACSR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x4)
--#define IOP13XX_ADMA_ADAR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x8)
--#define IOP13XX_ADMA_IIPCR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x18)
--#define IOP13XX_ADMA_IIPAR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x1c)
--#define IOP13XX_ADMA_IIPUAR(chan)    IOP13XX_ADMA_OFFSET(chan, 0x20)
--#define IOP13XX_ADMA_ANDAR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x24)
--#define IOP13XX_ADMA_ADCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x28)
--#define IOP13XX_ADMA_CARMD(chan)     IOP13XX_ADMA_OFFSET(chan, 0x2c)
--#define IOP13XX_ADMA_ABCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x30)
--#define IOP13XX_ADMA_DLADR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x34)
--#define IOP13XX_ADMA_DUADR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x38)
--#define IOP13XX_ADMA_SLAR(src, chan) IOP13XX_ADMA_OFFSET(chan, 0x3c + (src <<3))
--#define IOP13XX_ADMA_SUAR(src, chan) IOP13XX_ADMA_OFFSET(chan, 0x40 + (src <<3))
+diff -Nurb linux-2.6.22-590/drivers/serial/cpm_uart/Makefile linux-2.6.22-570/drivers/serial/cpm_uart/Makefile
+--- linux-2.6.22-590/drivers/serial/cpm_uart/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/cpm_uart/Makefile  2007-07-08 19:32:17.000000000 -0400
+@@ -7,6 +7,5 @@
+ # Select the correct platform objects.
+ cpm_uart-objs-$(CONFIG_CPM2)  += cpm_uart_cpm2.o
+ cpm_uart-objs-$(CONFIG_8xx)   += cpm_uart_cpm1.o
+-cpm_uart-objs-$(CONFIG_KGDB_CPM_UART) += cpm_uart_kgdb.o
+ cpm_uart-objs := cpm_uart_core.o $(cpm_uart-objs-y)
+diff -Nurb linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart.h linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart.h
+--- linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart.h        2007-07-08 19:32:17.000000000 -0400
+@@ -50,41 +50,6 @@
+ #define SCC_WAIT_CLOSING 100
+-#ifdef CONFIG_KGDB_CPM_UART
+-
+-/* Speed of the debug UART. */
+-#if CONFIG_KGDB_BAUDRATE == 9600
+-#define KGDB_BAUD B9600
+-#elif CONFIG_KGDB_BAUDRATE == 19200
+-#define KGDB_BAUD B19200
+-#elif CONFIG_KGDB_BAUDRATE == 38400
+-#define KGDB_BAUD B38400
+-#elif CONFIG_KGDB_BAUDRATE == 57600
+-#define KGDB_BAUD B57600
+-#elif CONFIG_KGDB_BAUDRATE == 115200
+-#define KGDB_BAUD B115200     /* Start with this if not given */
+-#else
+-#error Unsupported baud rate!
+-#endif
+-
+-#if defined(CONFIG_KGDB_CPM_UART_SCC1)
+-#define KGDB_PINFO_INDEX      UART_SCC1
+-#elif defined(CONFIG_KGDB_CPM_UART_SCC2)
+-#define KGDB_PINFO_INDEX      UART_SCC2
+-#elif defined(CONFIG_KGDB_CPM_UART_SCC3)
+-#define KGDB_PINFO_INDEX      UART_SCC3
+-#elif defined(CONFIG_KGDB_CPM_UART_SCC4)
+-#define KGDB_PINFO_INDEX      UART_SCC4
+-#elif defined(CONFIG_KGDB_CPM_UART_SMC1)
+-#define KGDB_PINFO_INDEX      UART_SMC1
+-#elif defined(CONFIG_KGDB_CPM_UART_SMC2)
+-#define KGDB_PINFO_INDEX      UART_SMC2
+-#else
+-#error The port for KGDB is undefined!
+-#endif
+-
+-#endif /* CONFIG_KGDB_CPM_UART */
+-
+ struct uart_cpm_port {
+       struct uart_port        port;
+       u16                     rx_nrfifos;
+@@ -121,9 +86,6 @@
+ extern int cpm_uart_nr;
+ extern struct uart_cpm_port cpm_uart_ports[UART_NR];
+-void cpm_uart_early_write(int index, const char *s, u_int count);
+-int cpm_uart_early_setup(int index,int early);
+-
+ /* these are located in their respective files */
+ void cpm_line_cr_cmd(int line, int cmd);
+ int cpm_uart_init_portdesc(void);
+@@ -170,4 +132,5 @@
+       return 0;
+ }
  
- /*==============================XSI BRIDGE===============================*/
- #define IOP13XX_XBG_BECSR             IOP13XX_REG_ADDR32(0x178c)
-diff -Nurb linux-2.6.22-570/include/asm-arm/arch-iop32x/adma.h linux-2.6.22-590/include/asm-arm/arch-iop32x/adma.h
---- linux-2.6.22-570/include/asm-arm/arch-iop32x/adma.h        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-arm/arch-iop32x/adma.h        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,5 @@
-+#ifndef IOP32X_ADMA_H
-+#define IOP32X_ADMA_H
-+#include <asm/hardware/iop3xx-adma.h>
-+#endif
-+
-diff -Nurb linux-2.6.22-570/include/asm-arm/arch-iop33x/adma.h linux-2.6.22-590/include/asm-arm/arch-iop33x/adma.h
---- linux-2.6.22-570/include/asm-arm/arch-iop33x/adma.h        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-arm/arch-iop33x/adma.h        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,5 @@
-+#ifndef IOP33X_ADMA_H
-+#define IOP33X_ADMA_H
-+#include <asm/hardware/iop3xx-adma.h>
-+#endif
 +
-diff -Nurb linux-2.6.22-570/include/asm-arm/hardware/iop3xx-adma.h linux-2.6.22-590/include/asm-arm/hardware/iop3xx-adma.h
---- linux-2.6.22-570/include/asm-arm/hardware/iop3xx-adma.h    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-arm/hardware/iop3xx-adma.h    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,891 @@
+ #endif /* CPM_UART_H */
+diff -Nurb linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_core.c linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_core.c
+--- linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_core.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_core.c   2007-07-08 19:32:17.000000000 -0400
+@@ -1073,17 +1073,22 @@
+       return 0;
+ }
+-void cpm_uart_early_write(int index, const char *s,
++#ifdef CONFIG_SERIAL_CPM_CONSOLE
 +/*
-+ * Copyright Â© 2006, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++ *    Print a string to the serial port trying not to disturb
++ *    any possible real use of the port...
 + *
++ *    Note that this is called with interrupts already disabled
 + */
-+#ifndef _ADMA_H
-+#define _ADMA_H
-+#include <linux/types.h>
-+#include <linux/io.h>
-+#include <asm/hardware.h>
-+#include <asm/hardware/iop_adma.h>
-+
-+/* Memory copy units */
-+#define DMA_CCR(chan)         (chan->mmr_base + 0x0)
-+#define DMA_CSR(chan)         (chan->mmr_base + 0x4)
-+#define DMA_DAR(chan)         (chan->mmr_base + 0xc)
-+#define DMA_NDAR(chan)                (chan->mmr_base + 0x10)
-+#define DMA_PADR(chan)                (chan->mmr_base + 0x14)
-+#define DMA_PUADR(chan)       (chan->mmr_base + 0x18)
-+#define DMA_LADR(chan)                (chan->mmr_base + 0x1c)
-+#define DMA_BCR(chan)         (chan->mmr_base + 0x20)
-+#define DMA_DCR(chan)         (chan->mmr_base + 0x24)
-+
-+/* Application accelerator unit  */
-+#define AAU_ACR(chan)         (chan->mmr_base + 0x0)
-+#define AAU_ASR(chan)         (chan->mmr_base + 0x4)
-+#define AAU_ADAR(chan)                (chan->mmr_base + 0x8)
-+#define AAU_ANDAR(chan)       (chan->mmr_base + 0xc)
-+#define AAU_SAR(src, chan)    (chan->mmr_base + (0x10 + ((src) << 2)))
-+#define AAU_DAR(chan)         (chan->mmr_base + 0x20)
-+#define AAU_ABCR(chan)                (chan->mmr_base + 0x24)
-+#define AAU_ADCR(chan)                (chan->mmr_base + 0x28)
-+#define AAU_SAR_EDCR(src_edc) (chan->mmr_base + (0x02c + ((src_edc-4) << 2)))
-+#define AAU_EDCR0_IDX 8
-+#define AAU_EDCR1_IDX 17
-+#define AAU_EDCR2_IDX 26
-+
-+#define DMA0_ID 0
-+#define DMA1_ID 1
-+#define AAU_ID 2
-+
-+struct iop3xx_aau_desc_ctrl {
-+      unsigned int int_en:1;
-+      unsigned int blk1_cmd_ctrl:3;
-+      unsigned int blk2_cmd_ctrl:3;
-+      unsigned int blk3_cmd_ctrl:3;
-+      unsigned int blk4_cmd_ctrl:3;
-+      unsigned int blk5_cmd_ctrl:3;
-+      unsigned int blk6_cmd_ctrl:3;
-+      unsigned int blk7_cmd_ctrl:3;
-+      unsigned int blk8_cmd_ctrl:3;
-+      unsigned int blk_ctrl:2;
-+      unsigned int dual_xor_en:1;
-+      unsigned int tx_complete:1;
-+      unsigned int zero_result_err:1;
-+      unsigned int zero_result_en:1;
-+      unsigned int dest_write_en:1;
-+};
-+
-+struct iop3xx_aau_e_desc_ctrl {
-+      unsigned int reserved:1;
-+      unsigned int blk1_cmd_ctrl:3;
-+      unsigned int blk2_cmd_ctrl:3;
-+      unsigned int blk3_cmd_ctrl:3;
-+      unsigned int blk4_cmd_ctrl:3;
-+      unsigned int blk5_cmd_ctrl:3;
-+      unsigned int blk6_cmd_ctrl:3;
-+      unsigned int blk7_cmd_ctrl:3;
-+      unsigned int blk8_cmd_ctrl:3;
-+      unsigned int reserved2:7;
-+};
-+
-+struct iop3xx_dma_desc_ctrl {
-+      unsigned int pci_transaction:4;
-+      unsigned int int_en:1;
-+      unsigned int dac_cycle_en:1;
-+      unsigned int mem_to_mem_en:1;
-+      unsigned int crc_data_tx_en:1;
-+      unsigned int crc_gen_en:1;
-+      unsigned int crc_seed_dis:1;
-+      unsigned int reserved:21;
-+      unsigned int crc_tx_complete:1;
-+};
-+
-+struct iop3xx_desc_dma {
-+      u32 next_desc;
-+      union {
-+              u32 pci_src_addr;
-+              u32 pci_dest_addr;
-+              u32 src_addr;
-+      };
-+      union {
-+              u32 upper_pci_src_addr;
-+              u32 upper_pci_dest_addr;
-+      };
-+      union {
-+              u32 local_pci_src_addr;
-+              u32 local_pci_dest_addr;
-+              u32 dest_addr;
-+      };
-+      u32 byte_count;
-+      union {
-+              u32 desc_ctrl;
-+              struct iop3xx_dma_desc_ctrl desc_ctrl_field;
-+      };
-+      u32 crc_addr;
-+};
-+
-+struct iop3xx_desc_aau {
-+      u32 next_desc;
-+      u32 src[4];
-+      u32 dest_addr;
-+      u32 byte_count;
-+      union {
-+              u32 desc_ctrl;
-+              struct iop3xx_aau_desc_ctrl desc_ctrl_field;
-+      };
-+      union {
-+              u32 src_addr;
-+              u32 e_desc_ctrl;
-+              struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
-+      } src_edc[31];
-+};
-+
-+struct iop3xx_aau_gfmr {
-+      unsigned int gfmr1:8;
-+      unsigned int gfmr2:8;
-+      unsigned int gfmr3:8;
-+      unsigned int gfmr4:8;
-+};
-+
-+struct iop3xx_desc_pq_xor {
-+      u32 next_desc;
-+      u32 src[3];
-+      union {
-+              u32 data_mult1;
-+              struct iop3xx_aau_gfmr data_mult1_field;
-+      };
-+      u32 dest_addr;
-+      u32 byte_count;
-+      union {
-+              u32 desc_ctrl;
-+              struct iop3xx_aau_desc_ctrl desc_ctrl_field;
-+      };
-+      union {
-+              u32 src_addr;
-+              u32 e_desc_ctrl;
-+              struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
-+              u32 data_multiplier;
-+              struct iop3xx_aau_gfmr data_mult_field;
-+              u32 reserved;
-+      } src_edc_gfmr[19];
-+};
-+
-+struct iop3xx_desc_dual_xor {
-+      u32 next_desc;
-+      u32 src0_addr;
-+      u32 src1_addr;
-+      u32 h_src_addr;
-+      u32 d_src_addr;
-+      u32 h_dest_addr;
-+      u32 byte_count;
-+      union {
-+              u32 desc_ctrl;
-+              struct iop3xx_aau_desc_ctrl desc_ctrl_field;
-+      };
-+      u32 d_dest_addr;
-+};
-+
-+union iop3xx_desc {
-+      struct iop3xx_desc_aau *aau;
-+      struct iop3xx_desc_dma *dma;
-+      struct iop3xx_desc_pq_xor *pq_xor;
-+      struct iop3xx_desc_dual_xor *dual_xor;
-+      void *ptr;
-+};
-+
-+static inline int iop_adma_get_max_xor(void)
-+{
-+      return 32;
-+}
-+
-+static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
-+{
-+      int id = chan->device->id;
-+
-+      switch (id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              return __raw_readl(DMA_DAR(chan));
-+      case AAU_ID:
-+              return __raw_readl(AAU_ADAR(chan));
-+      default:
-+              BUG();
-+      }
-+      return 0;
-+}
-+
-+static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
-+                                              u32 next_desc_addr)
-+{
-+      int id = chan->device->id;
-+
-+      switch (id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              __raw_writel(next_desc_addr, DMA_NDAR(chan));
-+              break;
-+      case AAU_ID:
-+              __raw_writel(next_desc_addr, AAU_ANDAR(chan));
-+              break;
-+      }
-+
-+}
-+
-+#define IOP_ADMA_STATUS_BUSY (1 << 10)
-+#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT (1024)
-+#define IOP_ADMA_XOR_MAX_BYTE_COUNT (16 * 1024 * 1024)
-+#define IOP_ADMA_MAX_BYTE_COUNT (16 * 1024 * 1024)
-+
-+static inline int iop_chan_is_busy(struct iop_adma_chan *chan)
-+{
-+      u32 status = __raw_readl(DMA_CSR(chan));
-+      return (status & IOP_ADMA_STATUS_BUSY) ? 1 : 0;
-+}
-+
-+static inline int iop_desc_is_aligned(struct iop_adma_desc_slot *desc,
-+                                      int num_slots)
-+{
-+      /* num_slots will only ever be 1, 2, 4, or 8 */
-+      return (desc->idx & (num_slots - 1)) ? 0 : 1;
-+}
-+
-+/* to do: support large (i.e. > hw max) buffer sizes */
-+static inline int iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
-+{
-+      *slots_per_op = 1;
-+      return 1;
-+}
-+
-+/* to do: support large (i.e. > hw max) buffer sizes */
-+static inline int iop_chan_memset_slot_count(size_t len, int *slots_per_op)
-+{
-+      *slots_per_op = 1;
-+      return 1;
-+}
-+
-+static inline int iop3xx_aau_xor_slot_count(size_t len, int src_cnt,
-+                                      int *slots_per_op)
-+{
-+      const static int slot_count_table[] = { 0,
-+                                              1, 1, 1, 1, /* 01 - 04 */
-+                                              2, 2, 2, 2, /* 05 - 08 */
-+                                              4, 4, 4, 4, /* 09 - 12 */
-+                                              4, 4, 4, 4, /* 13 - 16 */
-+                                              8, 8, 8, 8, /* 17 - 20 */
-+                                              8, 8, 8, 8, /* 21 - 24 */
-+                                              8, 8, 8, 8, /* 25 - 28 */
-+                                              8, 8, 8, 8, /* 29 - 32 */
-+                                            };
-+      *slots_per_op = slot_count_table[src_cnt];
-+      return *slots_per_op;
-+}
-+
-+static inline int
-+iop_chan_interrupt_slot_count(int *slots_per_op, struct iop_adma_chan *chan)
-+{
-+      switch (chan->device->id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              return iop_chan_memcpy_slot_count(0, slots_per_op);
-+      case AAU_ID:
-+              return iop3xx_aau_xor_slot_count(0, 2, slots_per_op);
-+      default:
-+              BUG();
-+      }
-+      return 0;
-+}
-+
-+static inline int iop_chan_xor_slot_count(size_t len, int src_cnt,
-+                                              int *slots_per_op)
-+{
-+      int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
-+
-+      if (len <= IOP_ADMA_XOR_MAX_BYTE_COUNT)
-+              return slot_cnt;
-+
-+      len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
-+      while (len > IOP_ADMA_XOR_MAX_BYTE_COUNT) {
-+              len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
-+              slot_cnt += *slots_per_op;
-+      }
-+
-+      if (len)
-+              slot_cnt += *slots_per_op;
-+
-+      return slot_cnt;
-+}
-+
-+/* zero sum on iop3xx is limited to 1k at a time so it requires multiple
-+ * descriptors
-+ */
-+static inline int iop_chan_zero_sum_slot_count(size_t len, int src_cnt,
-+                                              int *slots_per_op)
-+{
-+      int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
-+
-+      if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT)
-+              return slot_cnt;
-+
-+      len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
-+      while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
-+              len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
-+              slot_cnt += *slots_per_op;
-+      }
-+
-+      if (len)
-+              slot_cnt += *slots_per_op;
-+
-+      return slot_cnt;
-+}
-+
-+static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc,
-+                                      struct iop_adma_chan *chan)
-+{
-+      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-+
-+      switch (chan->device->id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              return hw_desc.dma->dest_addr;
-+      case AAU_ID:
-+              return hw_desc.aau->dest_addr;
-+      default:
-+              BUG();
-+      }
-+      return 0;
-+}
-+
-+static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
-+                                      struct iop_adma_chan *chan)
-+{
-+      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-+
-+      switch (chan->device->id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              return hw_desc.dma->byte_count;
-+      case AAU_ID:
-+              return hw_desc.aau->byte_count;
-+      default:
-+              BUG();
-+      }
-+      return 0;
-+}
-+
-+/* translate the src_idx to a descriptor word index */
-+static inline int __desc_idx(int src_idx)
-+{
-+      const static int desc_idx_table[] = { 0, 0, 0, 0,
-+                                            0, 1, 2, 3,
-+                                            5, 6, 7, 8,
-+                                            9, 10, 11, 12,
-+                                            14, 15, 16, 17,
-+                                            18, 19, 20, 21,
-+                                            23, 24, 25, 26,
-+                                            27, 28, 29, 30,
-+                                          };
-+
-+      return desc_idx_table[src_idx];
-+}
-+
-+static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
-+                                      struct iop_adma_chan *chan,
-+                                      int src_idx)
-+{
-+      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-+
-+      switch (chan->device->id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              return hw_desc.dma->src_addr;
-+      case AAU_ID:
-+              break;
-+      default:
-+              BUG();
-+      }
-+
-+      if (src_idx < 4)
-+              return hw_desc.aau->src[src_idx];
-+      else
-+              return hw_desc.aau->src_edc[__desc_idx(src_idx)].src_addr;
-+}
-+
-+static inline void iop3xx_aau_desc_set_src_addr(struct iop3xx_desc_aau *hw_desc,
-+                                      int src_idx, dma_addr_t addr)
-+{
-+      if (src_idx < 4)
-+              hw_desc->src[src_idx] = addr;
-+      else
-+              hw_desc->src_edc[__desc_idx(src_idx)].src_addr = addr;
-+}
-+
-+static inline void
-+iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en)
-+{
-+      struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
-+      union {
-+              u32 value;
-+              struct iop3xx_dma_desc_ctrl field;
-+      } u_desc_ctrl;
-+
-+      u_desc_ctrl.value = 0;
-+      u_desc_ctrl.field.mem_to_mem_en = 1;
-+      u_desc_ctrl.field.pci_transaction = 0xe; /* memory read block */
-+      u_desc_ctrl.field.int_en = int_en;
-+      hw_desc->desc_ctrl = u_desc_ctrl.value;
-+      hw_desc->upper_pci_src_addr = 0;
-+      hw_desc->crc_addr = 0;
-+}
-+
-+static inline void
-+iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en)
-+{
-+      struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
-+      union {
-+              u32 value;
-+              struct iop3xx_aau_desc_ctrl field;
-+      } u_desc_ctrl;
-+
-+      u_desc_ctrl.value = 0;
-+      u_desc_ctrl.field.blk1_cmd_ctrl = 0x2; /* memory block fill */
-+      u_desc_ctrl.field.dest_write_en = 1;
-+      u_desc_ctrl.field.int_en = int_en;
-+      hw_desc->desc_ctrl = u_desc_ctrl.value;
-+}
-+
-+static inline u32
-+iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt, int int_en)
-+{
-+      int i, shift;
-+      u32 edcr;
-+      union {
-+              u32 value;
-+              struct iop3xx_aau_desc_ctrl field;
-+      } u_desc_ctrl;
-+
-+      u_desc_ctrl.value = 0;
-+      switch (src_cnt) {
-+      case 25 ... 32:
-+              u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
-+              edcr = 0;
-+              shift = 1;
-+              for (i = 24; i < src_cnt; i++) {
-+                      edcr |= (1 << shift);
-+                      shift += 3;
-+              }
-+              hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = edcr;
-+              src_cnt = 24;
-+              /* fall through */
-+      case 17 ... 24:
-+              if (!u_desc_ctrl.field.blk_ctrl) {
-+                      hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
-+                      u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
-+              }
-+              edcr = 0;
-+              shift = 1;
-+              for (i = 16; i < src_cnt; i++) {
-+                      edcr |= (1 << shift);
-+                      shift += 3;
-+              }
-+              hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = edcr;
-+              src_cnt = 16;
-+              /* fall through */
-+      case 9 ... 16:
-+              if (!u_desc_ctrl.field.blk_ctrl)
-+                      u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
-+              edcr = 0;
-+              shift = 1;
-+              for (i = 8; i < src_cnt; i++) {
-+                      edcr |= (1 << shift);
-+                      shift += 3;
-+              }
-+              hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = edcr;
-+              src_cnt = 8;
-+              /* fall through */
-+      case 2 ... 8:
-+              shift = 1;
-+              for (i = 0; i < src_cnt; i++) {
-+                      u_desc_ctrl.value |= (1 << shift);
-+                      shift += 3;
-+              }
-+
-+              if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
-+                      u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
-+      }
-+
-+      u_desc_ctrl.field.dest_write_en = 1;
-+      u_desc_ctrl.field.blk1_cmd_ctrl = 0x7; /* direct fill */
-+      u_desc_ctrl.field.int_en = int_en;
-+      hw_desc->desc_ctrl = u_desc_ctrl.value;
-+
-+      return u_desc_ctrl.value;
-+}
-+
-+static inline void
-+iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
-+{
-+      iop3xx_desc_init_xor(desc->hw_desc, src_cnt, int_en);
-+}
-+
-+/* return the number of operations */
-+static inline int
-+iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
-+{
-+      int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
-+      struct iop3xx_desc_aau *hw_desc, *prev_hw_desc, *iter;
-+      union {
-+              u32 value;
-+              struct iop3xx_aau_desc_ctrl field;
-+      } u_desc_ctrl;
-+      int i, j;
-+
-+      hw_desc = desc->hw_desc;
-+
-+      for (i = 0, j = 0; (slot_cnt -= slots_per_op) >= 0;
-+              i += slots_per_op, j++) {
-+              iter = iop_hw_desc_slot_idx(hw_desc, i);
-+              u_desc_ctrl.value = iop3xx_desc_init_xor(iter, src_cnt, int_en);
-+              u_desc_ctrl.field.dest_write_en = 0;
-+              u_desc_ctrl.field.zero_result_en = 1;
-+              u_desc_ctrl.field.int_en = int_en;
-+              iter->desc_ctrl = u_desc_ctrl.value;
-+
-+              /* for the subsequent descriptors preserve the store queue
-+               * and chain them together
-+               */
-+              if (i) {
-+                      prev_hw_desc =
-+                              iop_hw_desc_slot_idx(hw_desc, i - slots_per_op);
-+                      prev_hw_desc->next_desc = (u32) (desc->phys + (i << 5));
-+              }
-+      }
-+
-+      return j;
-+}
-+
-+static inline void
-+iop_desc_init_null_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
-+{
-+      struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
-+      union {
-+              u32 value;
-+              struct iop3xx_aau_desc_ctrl field;
-+      } u_desc_ctrl;
-+
-+      u_desc_ctrl.value = 0;
-+      switch (src_cnt) {
-+      case 25 ... 32:
-+              u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
-+              hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
-+              /* fall through */
-+      case 17 ... 24:
-+              if (!u_desc_ctrl.field.blk_ctrl) {
-+                      hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
-+                      u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
-+              }
-+              hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = 0;
-+              /* fall through */
-+      case 9 ... 16:
-+              if (!u_desc_ctrl.field.blk_ctrl)
-+                      u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
-+              hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = 0;
-+              /* fall through */
-+      case 1 ... 8:
-+              if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
-+                      u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
-+      }
-+
-+      u_desc_ctrl.field.dest_write_en = 0;
-+      u_desc_ctrl.field.int_en = int_en;
-+      hw_desc->desc_ctrl = u_desc_ctrl.value;
-+}
-+
-+static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
-+                                      struct iop_adma_chan *chan,
-+                                      u32 byte_count)
-+{
-+      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-+
-+      switch (chan->device->id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              hw_desc.dma->byte_count = byte_count;
-+              break;
-+      case AAU_ID:
-+              hw_desc.aau->byte_count = byte_count;
-+              break;
-+      default:
-+              BUG();
-+      }
-+}
-+
-+static inline void
-+iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
-+                      struct iop_adma_chan *chan)
-+{
-+      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-+
-+      switch (chan->device->id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              iop_desc_init_memcpy(desc, 1);
-+              hw_desc.dma->byte_count = 0;
-+              hw_desc.dma->dest_addr = 0;
-+              hw_desc.dma->src_addr = 0;
-+              break;
-+      case AAU_ID:
-+              iop_desc_init_null_xor(desc, 2, 1);
-+              hw_desc.aau->byte_count = 0;
-+              hw_desc.aau->dest_addr = 0;
-+              hw_desc.aau->src[0] = 0;
-+              hw_desc.aau->src[1] = 0;
-+              break;
-+      default:
-+              BUG();
-+      }
-+}
-+
-+static inline void
-+iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
-+{
-+      int slots_per_op = desc->slots_per_op;
-+      struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
-+      int i = 0;
-+
-+      if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
-+              hw_desc->byte_count = len;
-+      } else {
-+              do {
-+                      iter = iop_hw_desc_slot_idx(hw_desc, i);
-+                      iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
-+                      len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
-+                      i += slots_per_op;
-+              } while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
-+
-+              if (len) {
-+                      iter = iop_hw_desc_slot_idx(hw_desc, i);
-+                      iter->byte_count = len;
-+              }
-+      }
-+}
-+
-+static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
-+                                      struct iop_adma_chan *chan,
-+                                      dma_addr_t addr)
-+{
-+      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-+
-+      switch (chan->device->id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              hw_desc.dma->dest_addr = addr;
-+              break;
-+      case AAU_ID:
-+              hw_desc.aau->dest_addr = addr;
-+              break;
-+      default:
-+              BUG();
-+      }
-+}
-+
-+static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
-+                                      dma_addr_t addr)
-+{
-+      struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
-+      hw_desc->src_addr = addr;
-+}
-+
-+static inline void
-+iop_desc_set_zero_sum_src_addr(struct iop_adma_desc_slot *desc, int src_idx,
-+                              dma_addr_t addr)
-+{
-+
-+      struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
-+      int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
-+      int i;
-+
-+      for (i = 0; (slot_cnt -= slots_per_op) >= 0;
-+              i += slots_per_op, addr += IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
-+              iter = iop_hw_desc_slot_idx(hw_desc, i);
-+              iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
-+      }
-+}
-+
-+static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
-+                                      int src_idx, dma_addr_t addr)
-+{
-+
-+      struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
-+      int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
-+      int i;
-+
-+      for (i = 0; (slot_cnt -= slots_per_op) >= 0;
-+              i += slots_per_op, addr += IOP_ADMA_XOR_MAX_BYTE_COUNT) {
-+              iter = iop_hw_desc_slot_idx(hw_desc, i);
-+              iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
-+      }
-+}
-+
-+static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
-+                                      u32 next_desc_addr)
-+{
-+      /* hw_desc->next_desc is the same location for all channels */
-+      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-+      BUG_ON(hw_desc.dma->next_desc);
-+      hw_desc.dma->next_desc = next_desc_addr;
-+}
-+
-+static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
-+{
-+      /* hw_desc->next_desc is the same location for all channels */
-+      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-+      return hw_desc.dma->next_desc;
-+}
-+
-+static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
-+{
-+      /* hw_desc->next_desc is the same location for all channels */
-+      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-+      hw_desc.dma->next_desc = 0;
-+}
-+
-+static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
-+                                              u32 val)
-+{
-+      struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
-+      hw_desc->src[0] = val;
-+}
-+
-+static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
-+{
-+      struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
-+      struct iop3xx_aau_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
-+
-+      BUG_ON(!(desc_ctrl.tx_complete && desc_ctrl.zero_result_en));
-+      return desc_ctrl.zero_result_err;
-+}
-+
-+static inline void iop_chan_append(struct iop_adma_chan *chan)
-+{
-+      u32 dma_chan_ctrl;
-+      /* workaround dropped interrupts on 3xx */
-+      mod_timer(&chan->cleanup_watchdog, jiffies + msecs_to_jiffies(3));
-+
-+      dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
-+      dma_chan_ctrl |= 0x2;
-+      __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
-+}
-+
-+static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
-+{
-+      if (!busy)
-+              del_timer(&chan->cleanup_watchdog);
-+}
-+
-+static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
-+{
-+      return __raw_readl(DMA_CSR(chan));
-+}
-+
-+static inline void iop_chan_disable(struct iop_adma_chan *chan)
-+{
-+      u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
-+      dma_chan_ctrl &= ~1;
-+      __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
-+}
-+
-+static inline void iop_chan_enable(struct iop_adma_chan *chan)
-+{
-+      u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
-+
-+      dma_chan_ctrl |= 1;
-+      __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
-+}
-+
-+static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
-+{
-+      u32 status = __raw_readl(DMA_CSR(chan));
-+      status &= (1 << 9);
-+      __raw_writel(status, DMA_CSR(chan));
-+}
-+
-+static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
-+{
-+      u32 status = __raw_readl(DMA_CSR(chan));
-+      status &= (1 << 8);
-+      __raw_writel(status, DMA_CSR(chan));
-+}
-+
-+static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
-+{
-+      u32 status = __raw_readl(DMA_CSR(chan));
-+
-+      switch (chan->device->id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              status &= (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1);
-+              break;
-+      case AAU_ID:
-+              status &= (1 << 5);
-+              break;
-+      default:
-+              BUG();
-+      }
-+
-+      __raw_writel(status, DMA_CSR(chan));
-+}
-+
-+static inline int
-+iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      return 0;
-+}
-+
-+static inline int
-+iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      return 0;
-+}
-+
-+static inline int
-+iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      return 0;
-+}
-+
-+static inline int
-+iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      return test_bit(5, &status);
-+}
++static void cpm_uart_console_write(struct console *co, const char *s,
+                                  u_int count)
+ {
+-      struct uart_cpm_port *pinfo;
++      struct uart_cpm_port *pinfo =
++          &cpm_uart_ports[cpm_uart_port_map[co->index]];
+       unsigned int i;
+       volatile cbd_t *bdp, *bdbase;
+       volatile unsigned char *cp;
+-      BUG_ON(index>UART_NR);
+-      pinfo = &cpm_uart_ports[index];
+-
+       /* Get the address of the host memory buffer.
+        */
+       bdp = pinfo->tx_cur;
+@@ -1147,14 +1152,19 @@
+       pinfo->tx_cur = (volatile cbd_t *) bdp;
+ }
+-int cpm_uart_early_setup(int index, int early)
 +
-+static inline int
-+iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      switch (chan->device->id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              return test_bit(2, &status);
-+      default:
-+              return 0;
-+      }
-+}
++static int __init cpm_uart_console_setup(struct console *co, char *options)
+ {
+-      int ret;
+       struct uart_port *port;
+       struct uart_cpm_port *pinfo;
++      int baud = 38400;
++      int bits = 8;
++      int parity = 'n';
++      int flow = 'n';
++      int ret;
+       struct fs_uart_platform_info *pdata;
+-      struct platform_device* pdev = early_uart_get_pdev(index);
++      struct platform_device* pdev = early_uart_get_pdev(co->index);
+       if (!pdev) {
+               pr_info("cpm_uart: console: compat mode\n");
+@@ -1162,9 +1172,8 @@
+               cpm_uart_init_portdesc();
+       }
+-      BUG_ON(index>UART_NR);
+       port =
+-              (struct uart_port *)&cpm_uart_ports[index];
++          (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
+       pinfo = (struct uart_cpm_port *)port;
+       if (!pdev) {
+               if (pinfo->set_lineif)
+@@ -1178,6 +1187,15 @@
+               cpm_uart_drv_get_platform_data(pdev, 1);
+       }
++      pinfo->flags |= FLAG_CONSOLE;
 +
-+static inline int
-+iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      switch (chan->device->id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              return test_bit(3, &status);
-+      default:
-+              return 0;
++      if (options) {
++              uart_parse_options(options, &baud, &parity, &bits, &flow);
++      } else {
++              if ((baud = uart_baudrate()) == -1)
++                      baud = 9600;
 +      }
-+}
 +
-+static inline int
-+iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
-+{
-+      switch (chan->device->id) {
-+      case DMA0_ID:
-+      case DMA1_ID:
-+              return test_bit(1, &status);
-+      default:
-+              return 0;
-+      }
-+}
-+#endif /* _ADMA_H */
-diff -Nurb linux-2.6.22-570/include/asm-arm/hardware/iop3xx.h linux-2.6.22-590/include/asm-arm/hardware/iop3xx.h
---- linux-2.6.22-570/include/asm-arm/hardware/iop3xx.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-arm/hardware/iop3xx.h 2008-01-02 13:56:37.000000000 -0500
-@@ -144,24 +144,9 @@
- #define IOP3XX_IAR            (volatile u32 *)IOP3XX_REG_ADDR(0x0380)
+       if (IS_SMC(pinfo)) {
+               pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
+               pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+@@ -1185,7 +1203,8 @@
+               pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+               pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+       }
+-      ret = cpm_uart_allocbuf(pinfo, early);
++
++      ret = cpm_uart_allocbuf(pinfo, 1);
  
- /* DMA Controller  */
--#define IOP3XX_DMA0_CCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0400)
--#define IOP3XX_DMA0_CSR               (volatile u32 *)IOP3XX_REG_ADDR(0x0404)
--#define IOP3XX_DMA0_DAR               (volatile u32 *)IOP3XX_REG_ADDR(0x040c)
--#define IOP3XX_DMA0_NDAR      (volatile u32 *)IOP3XX_REG_ADDR(0x0410)
--#define IOP3XX_DMA0_PADR      (volatile u32 *)IOP3XX_REG_ADDR(0x0414)
--#define IOP3XX_DMA0_PUADR     (volatile u32 *)IOP3XX_REG_ADDR(0x0418)
--#define IOP3XX_DMA0_LADR      (volatile u32 *)IOP3XX_REG_ADDR(0x041c)
--#define IOP3XX_DMA0_BCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0420)
--#define IOP3XX_DMA0_DCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0424)
--#define IOP3XX_DMA1_CCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0440)
--#define IOP3XX_DMA1_CSR               (volatile u32 *)IOP3XX_REG_ADDR(0x0444)
--#define IOP3XX_DMA1_DAR               (volatile u32 *)IOP3XX_REG_ADDR(0x044c)
--#define IOP3XX_DMA1_NDAR      (volatile u32 *)IOP3XX_REG_ADDR(0x0450)
--#define IOP3XX_DMA1_PADR      (volatile u32 *)IOP3XX_REG_ADDR(0x0454)
--#define IOP3XX_DMA1_PUADR     (volatile u32 *)IOP3XX_REG_ADDR(0x0458)
--#define IOP3XX_DMA1_LADR      (volatile u32 *)IOP3XX_REG_ADDR(0x045c)
--#define IOP3XX_DMA1_BCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0460)
--#define IOP3XX_DMA1_DCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0464)
-+#define IOP3XX_DMA_PHYS_BASE(chan) (IOP3XX_PERIPHERAL_PHYS_BASE + \
-+                                      (0x400 + (chan << 6)))
-+#define IOP3XX_DMA_UPPER_PA(chan)  (IOP3XX_DMA_PHYS_BASE(chan) + 0x27)
+       if (ret)
+               return ret;
+@@ -1197,62 +1216,6 @@
+       else
+               cpm_uart_init_scc(pinfo);
  
- /* Peripheral bus interface  */
- #define IOP3XX_PBCR           (volatile u32 *)IOP3XX_REG_ADDR(0x0680)
-@@ -210,48 +195,8 @@
- #define IOP_TMR_RATIO_1_1  0x00
+-      return 0;
+-}
+-
+-#ifdef CONFIG_SERIAL_CPM_CONSOLE
+-/*
+- *    Print a string to the serial port trying not to disturb
+- *    any possible real use of the port...
+- *
+- *    Note that this is called with interrupts already disabled
+- */
+-
+-static void cpm_uart_console_write(struct console *co, const char *s,
+-                                 u_int count)
+-{
+-      cpm_uart_early_write(cpm_uart_port_map[co->index],s,count);
+-}
+-
+-/*
+- * Setup console. Be careful is called early !
+- */
+-static int __init cpm_uart_console_setup(struct console *co, char *options)
+-{
+-      struct uart_port *port;
+-      struct uart_cpm_port *pinfo;
+-      int baud = 115200;
+-      int bits = 8;
+-      int parity = 'n';
+-      int flow = 'n';
+-      int ret;
+-
+-#ifdef CONFIG_KGDB_CPM_UART
+-      /* We are not interested in ports yet utilized by kgdb */
+-      if (co->index == KGDB_PINFO_INDEX)
+-              return 0;
+-#endif
+-
+-      port =
+-          (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
+-      pinfo = (struct uart_cpm_port *)port;
+-
+-      pinfo->flags |= FLAG_CONSOLE;
+-
+-      if (options) {
+-              uart_parse_options(options, &baud, &parity, &bits, &flow);
+-      } else {
+-              bd_t *bd = (bd_t *) __res;
+-
+-              if (bd->bi_baudrate)
+-                      baud = bd->bi_baudrate;
+-              else
+-                      baud = 9600;
+-      }
+-
+-      ret = cpm_uart_early_setup(cpm_uart_port_map[co->index], 1);
+-      if(ret)
+-              return ret;
+       uart_set_options(port, co, baud, parity, bits, flow);
  
- /* Application accelerator unit  */
--#define IOP3XX_AAU_ACR                (volatile u32 *)IOP3XX_REG_ADDR(0x0800)
--#define IOP3XX_AAU_ASR                (volatile u32 *)IOP3XX_REG_ADDR(0x0804)
--#define IOP3XX_AAU_ADAR               (volatile u32 *)IOP3XX_REG_ADDR(0x0808)
--#define IOP3XX_AAU_ANDAR      (volatile u32 *)IOP3XX_REG_ADDR(0x080c)
--#define IOP3XX_AAU_SAR1               (volatile u32 *)IOP3XX_REG_ADDR(0x0810)
--#define IOP3XX_AAU_SAR2               (volatile u32 *)IOP3XX_REG_ADDR(0x0814)
--#define IOP3XX_AAU_SAR3               (volatile u32 *)IOP3XX_REG_ADDR(0x0818)
--#define IOP3XX_AAU_SAR4               (volatile u32 *)IOP3XX_REG_ADDR(0x081c)
--#define IOP3XX_AAU_DAR                (volatile u32 *)IOP3XX_REG_ADDR(0x0820)
--#define IOP3XX_AAU_ABCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0824)
--#define IOP3XX_AAU_ADCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0828)
--#define IOP3XX_AAU_SAR5               (volatile u32 *)IOP3XX_REG_ADDR(0x082c)
--#define IOP3XX_AAU_SAR6               (volatile u32 *)IOP3XX_REG_ADDR(0x0830)
--#define IOP3XX_AAU_SAR7               (volatile u32 *)IOP3XX_REG_ADDR(0x0834)
--#define IOP3XX_AAU_SAR8               (volatile u32 *)IOP3XX_REG_ADDR(0x0838)
--#define IOP3XX_AAU_EDCR0      (volatile u32 *)IOP3XX_REG_ADDR(0x083c)
--#define IOP3XX_AAU_SAR9               (volatile u32 *)IOP3XX_REG_ADDR(0x0840)
--#define IOP3XX_AAU_SAR10      (volatile u32 *)IOP3XX_REG_ADDR(0x0844)
--#define IOP3XX_AAU_SAR11      (volatile u32 *)IOP3XX_REG_ADDR(0x0848)
--#define IOP3XX_AAU_SAR12      (volatile u32 *)IOP3XX_REG_ADDR(0x084c)
--#define IOP3XX_AAU_SAR13      (volatile u32 *)IOP3XX_REG_ADDR(0x0850)
--#define IOP3XX_AAU_SAR14      (volatile u32 *)IOP3XX_REG_ADDR(0x0854)
--#define IOP3XX_AAU_SAR15      (volatile u32 *)IOP3XX_REG_ADDR(0x0858)
--#define IOP3XX_AAU_SAR16      (volatile u32 *)IOP3XX_REG_ADDR(0x085c)
--#define IOP3XX_AAU_EDCR1      (volatile u32 *)IOP3XX_REG_ADDR(0x0860)
--#define IOP3XX_AAU_SAR17      (volatile u32 *)IOP3XX_REG_ADDR(0x0864)
--#define IOP3XX_AAU_SAR18      (volatile u32 *)IOP3XX_REG_ADDR(0x0868)
--#define IOP3XX_AAU_SAR19      (volatile u32 *)IOP3XX_REG_ADDR(0x086c)
--#define IOP3XX_AAU_SAR20      (volatile u32 *)IOP3XX_REG_ADDR(0x0870)
--#define IOP3XX_AAU_SAR21      (volatile u32 *)IOP3XX_REG_ADDR(0x0874)
--#define IOP3XX_AAU_SAR22      (volatile u32 *)IOP3XX_REG_ADDR(0x0878)
--#define IOP3XX_AAU_SAR23      (volatile u32 *)IOP3XX_REG_ADDR(0x087c)
--#define IOP3XX_AAU_SAR24      (volatile u32 *)IOP3XX_REG_ADDR(0x0880)
--#define IOP3XX_AAU_EDCR2      (volatile u32 *)IOP3XX_REG_ADDR(0x0884)
--#define IOP3XX_AAU_SAR25      (volatile u32 *)IOP3XX_REG_ADDR(0x0888)
--#define IOP3XX_AAU_SAR26      (volatile u32 *)IOP3XX_REG_ADDR(0x088c)
--#define IOP3XX_AAU_SAR27      (volatile u32 *)IOP3XX_REG_ADDR(0x0890)
--#define IOP3XX_AAU_SAR28      (volatile u32 *)IOP3XX_REG_ADDR(0x0894)
--#define IOP3XX_AAU_SAR29      (volatile u32 *)IOP3XX_REG_ADDR(0x0898)
--#define IOP3XX_AAU_SAR30      (volatile u32 *)IOP3XX_REG_ADDR(0x089c)
--#define IOP3XX_AAU_SAR31      (volatile u32 *)IOP3XX_REG_ADDR(0x08a0)
--#define IOP3XX_AAU_SAR32      (volatile u32 *)IOP3XX_REG_ADDR(0x08a4)
-+#define IOP3XX_AAU_PHYS_BASE (IOP3XX_PERIPHERAL_PHYS_BASE + 0x800)
-+#define IOP3XX_AAU_UPPER_PA (IOP3XX_AAU_PHYS_BASE + 0xa7)
+       return 0;
+@@ -1303,12 +1266,6 @@
  
- /* I2C bus interface unit  */
- #define IOP3XX_ICR0           (volatile u32 *)IOP3XX_REG_ADDR(0x1680)
-@@ -329,6 +274,9 @@
-       asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (val));
- }
+       pdata = pdev->dev.platform_data;
  
-+extern struct platform_device iop3xx_dma_0_channel;
-+extern struct platform_device iop3xx_dma_1_channel;
-+extern struct platform_device iop3xx_aau_channel;
- extern struct platform_device iop3xx_i2c0_device;
- extern struct platform_device iop3xx_i2c1_device;
+-#ifdef CONFIG_KGDB_CPM_UART
+-      /* We are not interested in ports yet utilized by kgdb */
+-      if (cpm_uart_id2nr(fs_uart_get_id(pdata)) == KGDB_PINFO_INDEX)
+-              return ret;
+-#endif
+-
+       if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))
+               return ret;
  
-diff -Nurb linux-2.6.22-570/include/asm-arm/hardware/iop_adma.h linux-2.6.22-590/include/asm-arm/hardware/iop_adma.h
---- linux-2.6.22-570/include/asm-arm/hardware/iop_adma.h       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-arm/hardware/iop_adma.h       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,120 @@
-+/*
-+ * Copyright Â© 2006, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ */
-+#ifndef IOP_ADMA_H
-+#define IOP_ADMA_H
-+#include <linux/types.h>
-+#include <linux/dmaengine.h>
-+#include <linux/interrupt.h>
-+
-+#define IOP_ADMA_SLOT_SIZE 32
-+#define IOP_ADMA_THRESHOLD 4
-+
-+/**
-+ * struct iop_adma_device - internal representation of an ADMA device
-+ * @pdev: Platform device
-+ * @id: HW ADMA Device selector
-+ * @dma_desc_pool: base of DMA descriptor region (DMA address)
-+ * @dma_desc_pool_virt: base of DMA descriptor region (CPU address)
-+ * @common: embedded struct dma_device
-+ */
-+struct iop_adma_device {
-+      struct platform_device *pdev;
-+      int id;
-+      dma_addr_t dma_desc_pool;
-+      void *dma_desc_pool_virt;
-+      struct dma_device common;
-+};
-+
-+/**
-+ * struct iop_adma_chan - internal representation of an ADMA device
-+ * @pending: allows batching of hardware operations
-+ * @completed_cookie: identifier for the most recently completed operation
-+ * @lock: serializes enqueue/dequeue operations to the slot pool
-+ * @mmr_base: memory mapped register base
-+ * @chain: device chain view of the descriptors
-+ * @device: parent device
-+ * @common: common dmaengine channel object members
-+ * @last_used: place holder for allocation to continue from where it left off
-+ * @all_slots: complete domain of slots usable by the channel
-+ * @cleanup_watchdog: workaround missed interrupts on iop3xx
-+ * @slots_allocated: records the actual size of the descriptor slot pool
-+ * @irq_tasklet: bottom half where iop_adma_slot_cleanup runs
-+ */
-+struct iop_adma_chan {
-+      int pending;
-+      dma_cookie_t completed_cookie;
-+      spinlock_t lock; /* protects the descriptor slot pool */
-+      void __iomem *mmr_base;
-+      struct list_head chain;
-+      struct iop_adma_device *device;
-+      struct dma_chan common;
-+      struct iop_adma_desc_slot *last_used;
-+      struct list_head all_slots;
-+      struct timer_list cleanup_watchdog;
-+      int slots_allocated;
-+      struct tasklet_struct irq_tasklet;
-+};
-+
-+/**
-+ * struct iop_adma_desc_slot - IOP-ADMA software descriptor
-+ * @slot_node: node on the iop_adma_chan.all_slots list
-+ * @chain_node: node on the op_adma_chan.chain list
-+ * @hw_desc: virtual address of the hardware descriptor chain
-+ * @phys: hardware address of the hardware descriptor chain
-+ * @group_head: first operation in a transaction
-+ * @slot_cnt: total slots used in an transaction (group of operations)
-+ * @slots_per_op: number of slots per operation
-+ * @idx: pool index
-+ * @unmap_src_cnt: number of xor sources
-+ * @unmap_len: transaction bytecount
-+ * @async_tx: support for the async_tx api
-+ * @group_list: list of slots that make up a multi-descriptor transaction
-+ *    for example transfer lengths larger than the supported hw max
-+ * @xor_check_result: result of zero sum
-+ * @crc32_result: result crc calculation
-+ */
-+struct iop_adma_desc_slot {
-+      struct list_head slot_node;
-+      struct list_head chain_node;
-+      void *hw_desc;
-+      dma_addr_t phys;
-+      struct iop_adma_desc_slot *group_head;
-+      u16 slot_cnt;
-+      u16 slots_per_op;
-+      u16 idx;
-+      u16 unmap_src_cnt;
-+      size_t unmap_len;
-+      struct dma_async_tx_descriptor async_tx;
-+      struct list_head group_list;
-+      union {
-+              u32 *xor_check_result;
-+              u32 *crc32_result;
-+      };
-+};
-+
-+struct iop_adma_platform_data {
-+      int hw_id;
-+      dma_cap_mask_t cap_mask;
-+      size_t pool_size;
-+};
-+
-+#define to_iop_sw_desc(addr_hw_desc) \
-+      container_of(addr_hw_desc, struct iop_adma_desc_slot, hw_desc)
-+#define iop_hw_desc_slot_idx(hw_desc, idx) \
-+      ( (void *) (((unsigned long) hw_desc) + ((idx) << 5)) )
-+#endif
-diff -Nurb linux-2.6.22-570/include/asm-arm/kgdb.h linux-2.6.22-590/include/asm-arm/kgdb.h
---- linux-2.6.22-570/include/asm-arm/kgdb.h    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-arm/kgdb.h    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,103 @@
-+/*
-+ * include/asm-arm/kgdb.h
-+ *
-+ * ARM KGDB support
-+ *
-+ * Author: Deepak Saxena <dsaxena@mvista.com>
-+ *
-+ * Copyright (C) 2002 MontaVista Software Inc.
-+ *
-+ */
-+
-+#ifndef __ASM_KGDB_H__
-+#define __ASM_KGDB_H__
-+
-+#include <asm/ptrace.h>
-+#include <asm-generic/kgdb.h>
-+
-+
-+/*
-+ * GDB assumes that we're a user process being debugged, so
-+ * it will send us an SWI command to write into memory as the
-+ * debug trap. When an SWI occurs, the next instruction addr is
-+ * placed into R14_svc before jumping to the vector trap.
-+ * This doesn't work for kernel debugging as we are already in SVC
-+ * we would loose the kernel's LR, which is a bad thing. This
-+ * is  bad thing.
-+ *
-+ * By doing this as an undefined instruction trap, we force a mode
-+ * switch from SVC to UND mode, allowing us to save full kernel state.
-+ *
-+ * We also define a KGDB_COMPILED_BREAK which can be used to compile
-+ * in breakpoints. This is important for things like sysrq-G and for
-+ * the initial breakpoint from trap_init().
-+ *
-+ * Note to ARM HW designers: Add real trap support like SH && PPC to
-+ * make our lives much much simpler. :)
-+ */
-+#define       BREAK_INSTR_SIZE                4
-+#define GDB_BREAKINST                   0xef9f0001
-+#define KGDB_BREAKINST                  0xe7ffdefe
-+#define KGDB_COMPILED_BREAK             0xe7ffdeff
-+#define CACHE_FLUSH_IS_SAFE           1
-+
-+#ifndef       __ASSEMBLY__
-+
-+#define       BREAKPOINT()                    asm(".word      0xe7ffdeff")
-+
-+
-+extern void kgdb_handle_bus_error(void);
-+extern int kgdb_fault_expected;
-+#endif /* !__ASSEMBLY__ */
-+
-+/*
-+ * From Kevin Hilman:
-+ *
-+ * gdb is expecting the following registers layout.
-+ *
-+ * r0-r15: 1 long word each
-+ * f0-f7:  unused, 3 long words each !!
-+ * fps:    unused, 1 long word
-+ * cpsr:   1 long word
-+ *
-+ * Even though f0-f7 and fps are not used, they need to be
-+ * present in the registers sent for correct processing in
-+ * the host-side gdb.
-+ *
-+ * In particular, it is crucial that CPSR is in the right place,
-+ * otherwise gdb will not be able to correctly interpret stepping over
-+ * conditional branches.
-+ */
-+#define _GP_REGS              16
-+#define _FP_REGS              8
-+#define _EXTRA_REGS           2
-+#define       GDB_MAX_REGS            (_GP_REGS + (_FP_REGS * 3) + _EXTRA_REGS)
-+
-+#define       KGDB_MAX_NO_CPUS        1
-+#define       BUFMAX                  400
-+#define       NUMREGBYTES             (GDB_MAX_REGS << 2)
-+#define       NUMCRITREGBYTES         (32 << 2)
-+
-+#define       _R0             0
-+#define       _R1             1
-+#define       _R2             2
-+#define       _R3             3
-+#define       _R4             4
-+#define       _R5             5
-+#define       _R6             6
-+#define       _R7             7
-+#define       _R8             8
-+#define       _R9             9
-+#define       _R10            10
-+#define       _FP             11
-+#define       _IP             12
-+#define       _SP             13
-+#define       _LR             14
-+#define       _PC             15
-+#define       _CPSR           (GDB_MAX_REGS - 1)
-+
-+/* So that we can denote the end of a frame for tracing, in the simple
-+ * case. */
-+#define CFI_END_FRAME(func)   __CFI_END_FRAME(_PC,_SP,func)
-+
-+#endif /* __ASM_KGDB_H__ */
-diff -Nurb linux-2.6.22-570/include/asm-arm/system.h linux-2.6.22-590/include/asm-arm/system.h
---- linux-2.6.22-570/include/asm-arm/system.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-arm/system.h  2008-01-02 13:56:37.000000000 -0500
-@@ -360,6 +360,41 @@
- extern void disable_hlt(void);
- extern void enable_hlt(void);
+@@ -1406,12 +1363,6 @@
  
-+#ifndef CONFIG_SMP
-+/*
-+ * Atomic compare and exchange.
-+ */
-+#define __HAVE_ARCH_CMPXCHG   1
-+
-+extern unsigned long wrong_size_cmpxchg(volatile void *ptr);
-+
-+static inline unsigned long __cmpxchg(volatile void *ptr,
-+                                  unsigned long old,
-+                                  unsigned long new, int size)
-+{
-+      unsigned long flags, prev;
-+      volatile unsigned long *p = ptr;
-+
-+      if (size == 4) {
-+              local_irq_save(flags);
-+              if ((prev = *p) == old)
-+                      *p = new;
-+              local_irq_restore(flags);
-+              return(prev);
-+      } else
-+              return wrong_size_cmpxchg(ptr);
-+}
-+
-+#define cmpxchg(ptr,o,n)                                              \
-+({                                                                    \
-+     __typeof__(*(ptr)) _o_ = (o);                                    \
-+     __typeof__(*(ptr)) _n_ = (n);                                    \
-+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,                \
-+                               (unsigned long)_n_, sizeof(*(ptr)));   \
-+})
-+
-+#endif
-+
- #endif /* __ASSEMBLY__ */
+               for (i = 0; i < cpm_uart_nr; i++) {
+                       int con = cpm_uart_port_map[i];
+-
+-#ifdef CONFIG_KGDB_CPM_UART
+-                      /* We are not interested in ports yet utilized by kgdb */
+-                      if (con == KGDB_PINFO_INDEX)
+-                              continue;
+-#endif
+                       cpm_uart_ports[con].port.line = i;
+                       cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF;
+                       if (cpm_uart_ports[con].set_lineif)
+diff -Nurb linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_cpm1.c linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+--- linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_cpm1.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_cpm1.c   2007-07-08 19:32:17.000000000 -0400
+@@ -53,7 +53,6 @@
+ {
+       ushort val;
+       volatile cpm8xx_t *cp = cpmp;
+-      unsigned *bcsr_io;
  
- #define arch_align_stack(x) (x)
-diff -Nurb linux-2.6.22-570/include/asm-cris/page.h linux-2.6.22-590/include/asm-cris/page.h
---- linux-2.6.22-570/include/asm-cris/page.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-cris/page.h   2008-01-02 13:56:37.000000000 -0500
-@@ -20,7 +20,8 @@
- #define clear_user_page(page, vaddr, pg)    clear_page(page)
- #define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
+       switch (line) {
+       case UART_SMC1:
+@@ -96,35 +95,12 @@
+ {
+       /* XXX SCC1: insert port configuration here */
+       pinfo->brg = 1;
+-
+-#if defined (CONFIG_MPC885ADS) || defined (CONFIG_MPC86XADS)
+-      bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+-
+-      if (bcsr_io == NULL) {
+-              printk(KERN_CRIT "Could not remap BCSR\n");
+-              return;
+-      }
+-      out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_RS232EN_1);
+-      iounmap(bcsr_io);
+-#endif
+ }
  
--#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
-+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
-+      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
- #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+ void scc2_lineif(struct uart_cpm_port *pinfo)
+ {
+       /* XXX SCC2: insert port configuration here */
+       pinfo->brg = 2;
+-      unsigned *bcsr_io;
+-
+-#if defined (CONFIG_MPC885ADS) || defined (CONFIG_MPC86XADS)
+-      bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+-
+-      if (bcsr_io == NULL) {
+-              printk(KERN_CRIT "Could not remap BCSR\n");
+-              return;
+-      }
+-        out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_RS232EN_2);
+-      iounmap(bcsr_io);
+-#endif
+ }
  
- /*
-diff -Nurb linux-2.6.22-570/include/asm-generic/kgdb.h linux-2.6.22-590/include/asm-generic/kgdb.h
---- linux-2.6.22-570/include/asm-generic/kgdb.h        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-generic/kgdb.h        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,100 @@
-+/*
-+ * include/asm-generic/kgdb.h
-+ *
-+ * This provides the assembly level information so that KGDB can provide
-+ * a GDB that has been patched with enough information to know to stop
-+ * trying to unwind the function.
-+ *
-+ * Author: Tom Rini <trini@kernel.crashing.org>
-+ *
-+ * 2005 (c) MontaVista Software, Inc.
-+ * 2006 (c) Embedded Alley Solutions, Inc.
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program is licensed "as is" without any warranty of any
-+ * kind, whether express or implied.
-+ */
-+
-+#ifndef __ASM_GENERIC_KGDB_H__
-+#define __ASM_GENERIC_KGDB_H__
-+
-+#ifdef CONFIG_X86
-+/**
-+ *    kgdb_skipexception - Bail of of KGDB when we've been triggered.
-+ *    @exception: Exception vector number
-+ *    @regs: Current &struct pt_regs.
-+ *
-+ *    On some architectures we need to skip a breakpoint exception when
-+ *    it occurs after a breakpoint has been removed.
-+ */
-+int kgdb_skipexception(int exception, struct pt_regs *regs);
-+#else
-+#define kgdb_skipexception(exception, regs)   0
-+#endif
-+
-+#if defined(CONFIG_X86)
-+/**
-+ *    kgdb_post_master_code - Save error vector/code numbers.
-+ *    @regs: Original pt_regs.
-+ *    @e_vector: Original error vector.
-+ *    @err_code: Original error code.
-+ *
-+ *    This is needed on architectures which support SMP and KGDB.
-+ *    This function is called after all the slave cpus have been put
-+ *    to a know spin state and the master CPU has control over KGDB.
-+ */
-+extern void kgdb_post_master_code(struct pt_regs *regs, int e_vector,
-+                                int err_code);
-+
-+/**
-+ *    kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb.
-+ *    @regs: Current &struct pt_regs.
-+ *
-+ *    This function will be called if the particular architecture must
-+ *    disable hardware debugging while it is processing gdb packets or
-+ *    handling exception.
-+ */
-+extern void kgdb_disable_hw_debug(struct pt_regs *regs);
-+#else
-+#define kgdb_disable_hw_debug(regs)           do { } while (0)
-+#define kgdb_post_master_code(regs, v, c)     do { } while (0)
-+#endif
-+
-+#ifdef CONFIG_KGDB_ARCH_HAS_SHADOW_INFO
-+/**
-+ *    kgdb_shadowinfo - Get shadowed information on @threadid.
-+ *    @regs: The &struct pt_regs of the current process.
-+ *    @buffer: A buffer of %BUFMAX size.
-+ *    @threadid: The thread id of the shadowed process to get information on.
-+ */
-+extern void kgdb_shadowinfo(struct pt_regs *regs, char *buffer,
-+                          unsigned threadid);
-+
-+/**
-+ *    kgdb_get_shadow_thread - Get the shadowed &task_struct of @threadid.
-+ *    @regs: The &struct pt_regs of the current thread.
-+ *    @threadid: The thread id of the shadowed process to get information on.
-+ *
-+ *    RETURN:
-+ *    This returns a pointer to the &struct task_struct of the shadowed
-+ *    thread, @threadid.
-+ */
-+extern struct task_struct *kgdb_get_shadow_thread(struct pt_regs *regs,
-+                                                int threadid);
-+
-+/**
-+ *    kgdb_shadow_regs - Return the shadowed registers of @threadid.
-+ *    @regs: The &struct pt_regs of the current thread.
-+ *    @threadid: The thread id we want the &struct pt_regs for.
-+ *
-+ *    RETURN:
-+ *    The a pointer to the &struct pt_regs of the shadowed thread @threadid.
-+ */
-+extern struct pt_regs *kgdb_shadow_regs(struct pt_regs *regs, int threadid);
-+#else
-+#define kgdb_shadowinfo(regs, buf, threadid)          do { } while (0)
-+#define kgdb_get_shadow_thread(regs, threadid)                NULL
-+#define kgdb_shadow_regs(regs, threadid)              NULL
-+#endif
-+
-+#endif                                /* __ASM_GENERIC_KGDB_H__ */
-diff -Nurb linux-2.6.22-570/include/asm-generic/vmlinux.lds.h linux-2.6.22-590/include/asm-generic/vmlinux.lds.h
---- linux-2.6.22-570/include/asm-generic/vmlinux.lds.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-generic/vmlinux.lds.h 2008-01-02 13:56:37.000000000 -0500
-@@ -127,6 +127,8 @@
-               *(__ksymtab_strings)                                    \
-       }                                                               \
-                                                                       \
-+      EH_FRAME                                                        \
-+                                                                      \
-       /* Built-in module parameters. */                               \
-       __param : AT(ADDR(__param) - LOAD_OFFSET) {                     \
-               VMLINUX_SYMBOL(__start___param) = .;                    \
-@@ -177,6 +179,26 @@
-               *(.kprobes.text)                                        \
-               VMLINUX_SYMBOL(__kprobes_text_end) = .;
+ void scc3_lineif(struct uart_cpm_port *pinfo)
+@@ -213,10 +189,6 @@
+ {
+       pr_debug("CPM uart[-]:init portdesc\n");
  
-+#ifdef CONFIG_STACK_UNWIND
-+#define EH_FRAME                                                      \
-+              /* Unwind data binary search table */                   \
-+              . = ALIGN(8);                                           \
-+              .eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - LOAD_OFFSET) { \
-+                      VMLINUX_SYMBOL(__start_unwind_hdr) = .;         \
-+                      *(.eh_frame_hdr)                                \
-+                      VMLINUX_SYMBOL(__end_unwind_hdr) = .;           \
-+              }                                                       \
-+              /* Unwind data */                                       \
-+              . = ALIGN(8);                                           \
-+              .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) {         \
-+                      VMLINUX_SYMBOL(__start_unwind) = .;             \
-+                      *(.eh_frame)                                    \
-+                      VMLINUX_SYMBOL(__end_unwind) = .;               \
-+              }
-+#else
-+#define EH_FRAME
-+#endif
-+
-               /* DWARF debug sections.
-               Symbols in the DWARF debugging sections are relative to
-               the beginning of the section so we begin them at 0.  */
-diff -Nurb linux-2.6.22-570/include/asm-h8300/page.h linux-2.6.22-590/include/asm-h8300/page.h
---- linux-2.6.22-570/include/asm-h8300/page.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-h8300/page.h  2008-01-02 13:56:37.000000000 -0500
-@@ -22,7 +22,8 @@
- #define clear_user_page(page, vaddr, pg)      clear_page(page)
- #define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
+-      /* Check if we have called this yet. This may happen if early kgdb
+-      breakpoint is on */
+-      if(cpm_uart_nr)
+-              return 0;
+       cpm_uart_nr = 0;
+ #ifdef CONFIG_SERIAL_CPM_SMC1
+       cpm_uart_ports[UART_SMC1].smcp = &cpmp->cp_smc[0];
+diff -Nurb linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_cpm2.c linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+--- linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_cpm2.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_cpm2.c   2007-07-08 19:32:17.000000000 -0400
+@@ -289,10 +289,6 @@
+ #endif
+       pr_debug("CPM uart[-]:init portdesc\n");
  
--#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
-+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
-+      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
- #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+-      /* Check if we have called this yet. This may happen if early kgdb
+-      breakpoint is on */
+-      if(cpm_uart_nr)
+-              return 0;
+       cpm_uart_nr = 0;
+ #ifdef CONFIG_SERIAL_CPM_SMC1
+       cpm_uart_ports[UART_SMC1].smcp = (smc_t *) cpm2_map(im_smc[0]);
+diff -Nurb linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_kgdb.c linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_kgdb.c
+--- linux-2.6.22-590/drivers/serial/cpm_uart/cpm_uart_kgdb.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/cpm_uart/cpm_uart_kgdb.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,185 +0,0 @@
+-/*
+- * drivers/serial/cpm_uart/cpm_uart_kgdb.c
+- *
+- * CPM UART interface for kgdb.
+- *
+- * Author: Vitaly Bordug <vbordug@ru.mvista.com>
+- *
+- * Used some bits from drivers/serial/kgdb_8250.c as a template
+- *
+- * 2005-2007 (c) MontaVista Software, Inc. This file is licensed under
+- * the terms of the GNU General Public License version 2. This program
+- * is licensed "as is" without any warranty of any kind, whether express
+- * or implied.
+- */
+-
+-#include <linux/kgdb.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/tty.h>
+-#include <linux/serial.h>
+-#include <linux/serial_core.h>
+-#include <linux/serial_reg.h>
+-
+-#include <asm/io.h>
+-#include <asm/serial.h>               /* For BASE_BAUD and SERIAL_PORT_DFNS */
+-
+-#include "cpm_uart.h"
+-
+-#define GDB_BUF_SIZE  512     /* power of 2, please */
+-
+-
+-static char kgdb_buf[GDB_BUF_SIZE], *kgdbp;
+-static int kgdb_chars;
+-
+-/* Forward declarations. */
+-
+-/*
+- * Receive character from the serial port.  This only works well
+- * before the port is initialize for real use.
+- */
+-static int kgdb_wait_key(char *obuf)
+-{
+-      struct uart_cpm_port *pinfo;
+-      u_char          c, *cp;
+-      volatile cbd_t  *bdp;
+-      int             i;
+-
+-      pinfo = &cpm_uart_ports[KGDB_PINFO_INDEX];
+-
+-      /* Get the address of the host memory buffer.
+-       */
+-      bdp = pinfo->rx_cur;
+-      while (bdp->cbd_sc & BD_SC_EMPTY);
+-
+-      /* If the buffer address is in the CPM DPRAM, don't
+-       * convert it.
+-       */
+-      cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
+-
+-      if (obuf) {
+-              i = c = bdp->cbd_datlen;
+-              while (i-- > 0)
+-                      *obuf++ = *cp++;
+-      } else
+-              c = *cp;
+-      bdp->cbd_sc |= BD_SC_EMPTY;
+-
+-      if (bdp->cbd_sc & BD_SC_WRAP)
+-              bdp = pinfo->rx_bd_base;
+-      else
+-              bdp++;
+-      pinfo->rx_cur = (cbd_t *)bdp;
+-
+-      return (int)c;
+-}
+-
+-
+-/*
+- * Wait until the interface can accept a char, then write it.
+- */
+-static void kgdb_put_debug_char(u8 chr)
+-{
+-      static char ch[2];
+-
+-      ch[0] = (char)chr;
+-      cpm_uart_early_write(KGDB_PINFO_INDEX, ch, 1);
+-}
+-
+-
+-/*
+- * Get a char if available, return -1 if nothing available.
+- * Empty the receive buffer first, then look at the interface hardware.
+- */
+-static int kgdb_get_debug_char(void)
+-{
+-      if (kgdb_chars <= 0) {
+-              kgdb_chars = kgdb_wait_key(kgdb_buf);
+-              kgdbp = kgdb_buf;
+-      }
+-      kgdb_chars--;
+-
+-      return (*kgdbp++);
+-}
+-
+-static void termios_set_options(int index,
+-               int baud, int parity, int bits, int flow)
+-{
+-      struct ktermios termios;
+-      struct uart_port *port;
+-      struct uart_cpm_port *pinfo;
+-
+-      BUG_ON(index>UART_NR);
+-
+-      port  = (struct uart_port *)&cpm_uart_ports[index];
+-      pinfo = (struct uart_cpm_port *)port;
+-
+-      /*
+-       * Ensure that the serial console lock is initialised
+-       * early.
+-       */
+-      spin_lock_init(&port->lock);
+-
+-      memset(&termios, 0, sizeof(struct termios));
+-
+-      termios.c_cflag = CREAD | HUPCL | CLOCAL;
+-
+-      termios.c_cflag |= baud;
+-
+-      if (bits == 7)
+-              termios.c_cflag |= CS7;
+-      else
+-              termios.c_cflag |= CS8;
+-
+-      switch (parity) {
+-      case 'o': case 'O':
+-              termios.c_cflag |= PARODD;
+-              /*fall through*/
+-      case 'e': case 'E':
+-              termios.c_cflag |= PARENB;
+-              break;
+-      }
+-
+-      if (flow == 'r')
+-              termios.c_cflag |= CRTSCTS;
+-
+-      port->ops->set_termios(port, &termios, NULL);
+-}
+-
+-/*
+- *  Returns:
+- *    0 on success, 1 on failure.
+- */
+-static int kgdb_init(void)
+-{
+-      struct uart_port *port;
+-      struct uart_cpm_port *pinfo;
+-      int use_bootmem = 0; /* use dma by default */
+-
+-      if (!cpm_uart_nr) {
+-              use_bootmem = 1;
+-              cpm_uart_init_portdesc();
+-      }
+-      port  = (struct uart_port *)&cpm_uart_ports[KGDB_PINFO_INDEX];
+-      pinfo = (struct uart_cpm_port *)port;
+-
+-      if (cpm_uart_early_setup(KGDB_PINFO_INDEX, use_bootmem))
+-              return 1;
+-
+-      termios_set_options(KGDB_PINFO_INDEX, KGDB_BAUD,'n',8,'n');
+-        if (IS_SMC(pinfo))
+-                pinfo->smcp->smc_smcm |= SMCM_TX;
+-        else
+-                pinfo->sccp->scc_sccm |= UART_SCCM_TX;
+-
+-      return 0;
+-}
+-
+-
+-struct kgdb_io kgdb_io_ops = {
+-      .read_char  = kgdb_get_debug_char,
+-      .write_char = kgdb_put_debug_char,
+-      .init = kgdb_init,
+-};
+-
+diff -Nurb linux-2.6.22-590/drivers/serial/mpsc_kgdb.c linux-2.6.22-570/drivers/serial/mpsc_kgdb.c
+--- linux-2.6.22-590/drivers/serial/mpsc_kgdb.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/mpsc_kgdb.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,345 +0,0 @@
+-/*
+- * drivers/serial/mpsc_kgdb.c
+- *
+- * KGDB driver for the Marvell MultiProtocol Serial Controller (MPCS)
+- *
+- * Based on the polled boot loader driver by Ajit Prem (ajit.prem@motorola.com)
+- *
+- * Author: Randy Vinson <rvinson@mvista.com>
+- *
+- * Copyright (C) 2005-2006 MontaVista Software, 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.
+- */
+-
+-#include <linux/kgdb.h>
+-#include <linux/mv643xx.h>
+-#include <linux/device.h>
+-#include <asm/mv64x60.h>
+-#include <asm/serial.h>
+-#include <asm/io.h>
+-#include <asm/delay.h>
+-
+-/* Main MPSC Configuration Register Offsets */
+-#define MPSC_MMCRL            0x0000
+-#define MPSC_MMCRH            0x0004
+-#define MPSC_MPCR             0x0008
+-#define MPSC_CHR_1            0x000c
+-#define MPSC_CHR_2            0x0010
+-#define MPSC_CHR_3            0x0014
+-#define MPSC_CHR_4            0x0018
+-#define MPSC_CHR_5            0x001c
+-#define MPSC_CHR_6            0x0020
+-#define MPSC_CHR_7            0x0024
+-#define MPSC_CHR_8            0x0028
+-#define MPSC_CHR_9            0x002c
+-#define MPSC_CHR_10           0x0030
+-#define MPSC_CHR_11           0x0034
+-
+-#define MPSC_MPCR_FRZ         (1 << 9)
+-#define MPSC_MPCR_CL_5                0
+-#define MPSC_MPCR_CL_6                1
+-#define MPSC_MPCR_CL_7                2
+-#define MPSC_MPCR_CL_8                3
+-#define MPSC_MPCR_SBL_1       0
+-#define MPSC_MPCR_SBL_2       1
+-
+-#define MPSC_CHR_2_TEV                (1<<1)
+-#define MPSC_CHR_2_TA         (1<<7)
+-#define MPSC_CHR_2_TTCS               (1<<9)
+-#define MPSC_CHR_2_REV                (1<<17)
+-#define MPSC_CHR_2_RA         (1<<23)
+-#define MPSC_CHR_2_CRD                (1<<25)
+-#define MPSC_CHR_2_EH         (1<<31)
+-#define MPSC_CHR_2_PAR_ODD    0
+-#define MPSC_CHR_2_PAR_SPACE  1
+-#define MPSC_CHR_2_PAR_EVEN   2
+-#define MPSC_CHR_2_PAR_MARK   3
+-
+-/* MPSC Signal Routing */
+-#define MPSC_MRR              0x0000
+-#define MPSC_RCRR             0x0004
+-#define MPSC_TCRR             0x0008
+-
+-/* MPSC Interrupt registers (offset from MV64x60_SDMA_INTR_OFFSET) */
+-#define MPSC_INTR_CAUSE       0x0004
+-#define MPSC_INTR_MASK                0x0084
+-#define MPSC_INTR_CAUSE_RCC   (1<<6)
+-
+-/* Baud Rate Generator Interface Registers */
+-#define BRG_BCR               0x0000
+-#define BRG_BTR               0x0004
+-
+-/* Speed of the UART. */
+-static int kgdbmpsc_baud = CONFIG_KGDB_BAUDRATE;
+-
+-/* Index of the UART, matches ttyMX naming. */
+-static int kgdbmpsc_ttyMM = CONFIG_KGDB_PORT_NUM;
+-
+-#define MPSC_INTR_REG_SELECT(x)       ((x) + (8 * kgdbmpsc_ttyMM))
+-
+-static int kgdbmpsc_init(void);
+-
+-static struct platform_device mpsc_dev, shared_dev;
+-
+-static void __iomem *mpsc_base;
+-static void __iomem *brg_base;
+-static void __iomem *routing_base;
+-static void __iomem *sdma_base;
+-
+-static unsigned int mpsc_irq;
+-
+-static void kgdb_write_debug_char(u8 c)
+-{
+-      u32 data;
+-
+-      data = readl(mpsc_base + MPSC_MPCR);
+-      writeb(c, mpsc_base + MPSC_CHR_1);
+-      mb();
+-      data = readl(mpsc_base + MPSC_CHR_2);
+-      data |= MPSC_CHR_2_TTCS;
+-      writel(data, mpsc_base + MPSC_CHR_2);
+-      mb();
+-
+-      while (readl(mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS) ;
+-}
+-
+-static int kgdb_get_debug_char(void)
+-{
+-      unsigned char c;
+-
+-      while (!(readl(sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE)) &
+-               MPSC_INTR_CAUSE_RCC)) ;
+-
+-      c = readb(mpsc_base + MPSC_CHR_10 + (1 << 1));
+-      mb();
+-      writeb(c, mpsc_base + MPSC_CHR_10 + (1 << 1));
+-      mb();
+-      writel(~MPSC_INTR_CAUSE_RCC, sdma_base +
+-             MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE));
+-      return (c);
+-}
+-
+-/*
+- * This is the receiver interrupt routine for the GDB stub.
+- * All that we need to do is verify that the interrupt happened on the
+- * line we're in charge of.  If this is true, schedule a breakpoint and
+- * return.
+- */
+-static irqreturn_t kgdbmpsc_interrupt(int irq, void *dev_id)
+-{
+-      if (irq != mpsc_irq)
+-              return IRQ_NONE;
+-      /*
+-       * If  there is some other CPU in KGDB then this is a
+-       * spurious interrupt. so return without even checking a byte
+-       */
+-      if (atomic_read(&debugger_active))
+-              return IRQ_NONE;
+-
+-      if (readl(sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE)) &
+-          MPSC_INTR_CAUSE_RCC)
+-              breakpoint();
+-
+-      return IRQ_HANDLED;
+-}
+-
+-static int __init kgdbmpsc_init(void)
+-{
+-      struct mpsc_pdata *pdata;
+-      u32 cdv;
+-
+-      if (!brg_base || !mpsc_base || !routing_base || !sdma_base)
+-              return -1;
+-
+-      /* Set MPSC Routing to enable both ports */
+-      writel(0x0, routing_base + MPSC_MRR);
+-
+-      /* MPSC 0/1 Rx & Tx get clocks BRG0/1 */
+-      writel(0x00000100, routing_base + MPSC_RCRR);
+-      writel(0x00000100, routing_base + MPSC_TCRR);
+-
+-      /* Disable all MPSC interrupts and clear any pending interrupts */
+-      writel(0, sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_MASK));
+-      writel(0, sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_CAUSE));
+-
+-      pdata = (struct mpsc_pdata *)mpsc_dev.dev.platform_data;
+-
+-      /* cdv = (clock/(2*16*baud rate)) for 16X mode. */
+-      cdv = ((pdata->brg_clk_freq / (32 * kgdbmpsc_baud)) - 1);
+-      writel((pdata->brg_clk_src << 18) | (1 << 16) | cdv,
+-             brg_base + BRG_BCR);
+-
+-      /* Put MPSC into UART mode, no null modem, 16x clock mode */
+-      writel(0x000004c4, mpsc_base + MPSC_MMCRL);
+-      writel(0x04400400, mpsc_base + MPSC_MMCRH);
+-
+-      writel(0, mpsc_base + MPSC_CHR_1);
+-      writel(0, mpsc_base + MPSC_CHR_9);
+-      writel(0, mpsc_base + MPSC_CHR_10);
+-      writel(4, mpsc_base + MPSC_CHR_3);
+-      writel(0x20000000, mpsc_base + MPSC_CHR_4);
+-      writel(0x9000, mpsc_base + MPSC_CHR_5);
+-      writel(0, mpsc_base + MPSC_CHR_6);
+-      writel(0, mpsc_base + MPSC_CHR_7);
+-      writel(0, mpsc_base + MPSC_CHR_8);
+-
+-      /* 8 data bits, 1 stop bit */
+-      writel((3 << 12), mpsc_base + MPSC_MPCR);
+-
+-      /* Enter "hunt" mode */
+-      writel((1 << 31), mpsc_base + MPSC_CHR_2);
+-
+-      udelay(100);
+-      return 0;
+-}
+-
+-static void __iomem *__init
+-kgdbmpsc_map_resource(struct platform_device *pd, int type, int num)
+-{
+-      void __iomem *base = NULL;
+-      struct resource *r;
+-
+-      if ((r = platform_get_resource(pd, IORESOURCE_MEM, num)))
+-              base = ioremap(r->start, r->end - r->start + 1);
+-      return base;
+-}
+-
+-static void __iomem *__init
+-kgdbmpsc_unmap_resource(struct platform_device *pd, int type, int num,
+-                      void __iomem * base)
+-{
+-      if (base)
+-              iounmap(base);
+-      return NULL;
+-}
+-
+-static void __init
+-kgdbmpsc_reserve_resource(struct platform_device *pd, int type, int num)
+-{
+-      struct resource *r;
+-
+-      if ((r = platform_get_resource(pd, IORESOURCE_MEM, num)))
+-              request_mem_region(r->start, r->end - r->start + 1, "kgdb");
+-}
+-
+-static int __init kgdbmpsc_local_init(void)
+-{
+-      if (!mpsc_dev.num_resources || !shared_dev.num_resources)
+-              return 1;       /* failure */
+-
+-      mpsc_base = kgdbmpsc_map_resource(&mpsc_dev, IORESOURCE_MEM,
+-                                        MPSC_BASE_ORDER);
+-      brg_base = kgdbmpsc_map_resource(&mpsc_dev, IORESOURCE_MEM,
+-                                       MPSC_BRG_BASE_ORDER);
+-
+-      /* get the platform data for the shared registers and get them mapped */
+-      routing_base = kgdbmpsc_map_resource(&shared_dev,
+-                                           IORESOURCE_MEM,
+-                                           MPSC_ROUTING_BASE_ORDER);
+-      sdma_base =
+-          kgdbmpsc_map_resource(&shared_dev, IORESOURCE_MEM,
+-                                MPSC_SDMA_INTR_BASE_ORDER);
+-
+-      mpsc_irq = platform_get_irq(&mpsc_dev, 1);
+-
+-      if (mpsc_base && brg_base && routing_base && sdma_base)
+-              return 0;       /* success */
+-
+-      return 1;               /* failure */
+-}
+-
+-static void __init kgdbmpsc_local_exit(void)
+-{
+-      if (sdma_base)
+-              sdma_base = kgdbmpsc_unmap_resource(&shared_dev, IORESOURCE_MEM,
+-                                                  MPSC_SDMA_INTR_BASE_ORDER,
+-                                                  sdma_base);
+-      if (routing_base)
+-              routing_base = kgdbmpsc_unmap_resource(&shared_dev,
+-                                                     IORESOURCE_MEM,
+-                                                     MPSC_ROUTING_BASE_ORDER,
+-                                                     routing_base);
+-      if (brg_base)
+-              brg_base = kgdbmpsc_unmap_resource(&mpsc_dev, IORESOURCE_MEM,
+-                                                 MPSC_BRG_BASE_ORDER,
+-                                                 brg_base);
+-      if (mpsc_base)
+-              mpsc_base = kgdbmpsc_unmap_resource(&mpsc_dev, IORESOURCE_MEM,
+-                                                  MPSC_BASE_ORDER, mpsc_base);
+-}
+-
+-static void __init kgdbmpsc_update_pdata(struct platform_device *pdev)
+-{
+-
+-      snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id);
+-}
+-
+-static int __init kgdbmpsc_pdev_init(void)
+-{
+-      struct platform_device *pdev;
+-
+-      /* get the platform data for the specified port. */
+-      pdev = mv64x60_early_get_pdev_data(MPSC_CTLR_NAME, kgdbmpsc_ttyMM, 1);
+-      if (pdev) {
+-              memcpy(&mpsc_dev, pdev, sizeof(struct platform_device));
+-              if (platform_notify) {
+-                      kgdbmpsc_update_pdata(&mpsc_dev);
+-                      platform_notify(&mpsc_dev.dev);
+-              }
+-
+-              /* get the platform data for the shared registers. */
+-              pdev = mv64x60_early_get_pdev_data(MPSC_SHARED_NAME, 0, 0);
+-              if (pdev) {
+-                      memcpy(&shared_dev, pdev,
+-                             sizeof(struct platform_device));
+-                      if (platform_notify) {
+-                              kgdbmpsc_update_pdata(&shared_dev);
+-                              platform_notify(&shared_dev.dev);
+-                      }
+-              }
+-      }
+-      return 0;
+-}
+-
+-postcore_initcall(kgdbmpsc_pdev_init);
+-
+-static int __init kgdbmpsc_init_io(void)
+-{
+-
+-      kgdbmpsc_pdev_init();
+-
+-      if (kgdbmpsc_local_init()) {
+-              kgdbmpsc_local_exit();
+-              return -1;
+-      }
+-
+-      if (kgdbmpsc_init() == -1)
+-              return -1;
+-      return 0;
+-}
+-
+-static void __init kgdbmpsc_hookup_irq(void)
+-{
+-      unsigned int msk;
+-      if (!request_irq(mpsc_irq, kgdbmpsc_interrupt, 0, "kgdb mpsc", NULL)) {
+-              /* Enable interrupt */
+-              msk = readl(sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_MASK));
+-              msk |= MPSC_INTR_CAUSE_RCC;
+-              writel(msk, sdma_base + MPSC_INTR_REG_SELECT(MPSC_INTR_MASK));
+-
+-              kgdbmpsc_reserve_resource(&mpsc_dev, IORESOURCE_MEM,
+-                                        MPSC_BASE_ORDER);
+-              kgdbmpsc_reserve_resource(&mpsc_dev, IORESOURCE_MEM,
+-                                        MPSC_BRG_BASE_ORDER);
+-      }
+-}
+-
+-struct kgdb_io kgdb_io_ops = {
+-      .read_char = kgdb_get_debug_char,
+-      .write_char = kgdb_write_debug_char,
+-      .init = kgdbmpsc_init_io,
+-      .late_init = kgdbmpsc_hookup_irq,
+-};
+diff -Nurb linux-2.6.22-590/drivers/serial/pl011_kgdb.c linux-2.6.22-570/drivers/serial/pl011_kgdb.c
+--- linux-2.6.22-590/drivers/serial/pl011_kgdb.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/pl011_kgdb.c       1969-12-31 19:00:00.000000000 -0500
+@@ -1,111 +0,0 @@
+-/*
+- * driver/serial/pl011_kgdb.c
+- *
+- * Support for KGDB on ARM AMBA PL011 UARTs
+- *
+- * Authors: Manish Lachwani <mlachwani@mvista.com>
+- *          Deepak Saxena <dsaxena@plexity.net>
+- *
+- * Copyright (c) 2005-2007 MontaVista Software, Inc.
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program is licensed "as is" without any warranty of any
+- * kind, whether expressor implied.
+- *
+- */
+-#include <linux/kgdb.h>
+-#include <linux/amba/bus.h>
+-#include <linux/amba/serial.h>
+-
+-#include <asm/io.h>
+-#include <asm/processor.h>
+-#include <asm/hardware.h>
+-
+-static int kgdb_irq = CONFIG_KGDB_AMBA_IRQ;
+-
+-#define UART_DIVISOR  (CONFIG_KGDB_AMBA_UARTCLK * 4 / CONFIG_KGDB_BAUDRATE)
+-/*
+- * Todo: IO_ADDRESS is not very generic across ARM...
+- */
+-static volatile unsigned char *kgdb_port =
+-      (unsigned char*)IO_ADDRESS(CONFIG_KGDB_AMBA_BASE);
+-
+-/*
+- * Init code taken from amba-pl011.c.
+- */
+-static int kgdb_serial_init(void)
+-{
+-      writew(0, kgdb_port + UART010_CR);
+-
+-      /* Set baud rate */
+-      writew(UART_DIVISOR & 0x3f, kgdb_port + UART011_FBRD);
+-      writew(UART_DIVISOR >> 6, kgdb_port + UART011_IBRD);
+-
+-      writew(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, kgdb_port + UART010_LCRH);
+-      writew(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE,
+-             kgdb_port + UART010_CR);
+-
+-      writew(UART011_RXIM, kgdb_port + UART011_IMSC);
+-
+-      return 0;
+-}
+-
+-static void kgdb_serial_putchar(u8 ch)
+-{
+-      unsigned int status;
+-
+-      do {
+-              status = readw(kgdb_port + UART01x_FR);
+-      } while (status & UART01x_FR_TXFF);
+-
+-      writew(ch, kgdb_port + UART01x_DR);
+-}
+-
+-static int kgdb_serial_getchar(void)
+-{
+-      unsigned int status;
+-      int ch;
+-
+-#ifdef CONFIG_DEBUG_LL
+-      printascii("Entering serial_getchar loop");
+-#endif
+-      do {
+-              status = readw(kgdb_port + UART01x_FR);
+-      } while (status & UART01x_FR_RXFE);
+-      ch = readw(kgdb_port + UART01x_DR);
+-#ifdef CONFIG_DEBUG_LL
+-      printascii("Exited serial_getchar loop");
+-      printascii("Read char: ");
+-      printch(ch);
+-      printascii("\n");
+-#endif
+-      return ch;
+-}
+-
+-static irqreturn_t kgdb_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+-{
+-      int status = readw(kgdb_port + UART011_MIS);
+-
+-#ifdef CONFIG_DEBUG_LL
+-      printascii("KGDB irq\n");
+-#endif
+-      if (irq != kgdb_irq)
+-              return IRQ_NONE;
+-
+-      if (status & 0x40)
+-              breakpoint();
+-
+-      return IRQ_HANDLED;
+-}
+-
+-static void __init kgdb_hookup_irq(void)
+-{
+-      request_irq(kgdb_irq, kgdb_interrupt, SA_SHIRQ, "KGDB-serial", kgdb_port);
+-}
+-
+-struct kgdb_io kgdb_io_ops = {
+-      .init = kgdb_serial_init,
+-      .write_char = kgdb_serial_putchar,
+-      .read_char  = kgdb_serial_getchar,
+-      .late_init  = kgdb_hookup_irq,
+-};
+diff -Nurb linux-2.6.22-590/drivers/serial/pxa.c linux-2.6.22-570/drivers/serial/pxa.c
+--- linux-2.6.22-590/drivers/serial/pxa.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/pxa.c      2007-07-08 19:32:17.000000000 -0400
+@@ -42,9 +42,6 @@
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
+ #include <linux/serial_core.h>
+-#ifdef CONFIG_KGDB_CONSOLE
+-#include <linux/kgdb.h>
+-#endif
  
- /*
-diff -Nurb linux-2.6.22-570/include/asm-i386/kdebug.h linux-2.6.22-590/include/asm-i386/kdebug.h
---- linux-2.6.22-570/include/asm-i386/kdebug.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-i386/kdebug.h 2008-01-02 13:56:37.000000000 -0500
-@@ -28,6 +28,7 @@
-       DIE_CALL,
-       DIE_NMI_IPI,
-       DIE_PAGE_FAULT,
-+      DIE_PAGE_FAULT_NO_CONTEXT,
- };
+ #include <asm/io.h>
+ #include <asm/hardware.h>
+@@ -693,8 +690,6 @@
+ console_initcall(serial_pxa_console_init);
  
+ #define PXA_CONSOLE   &serial_pxa_console
+-#elif defined(CONFIG_KGDB_CONSOLE)
+-#define PXA_CONSOLE   &kgdbcons
+ #else
+ #define PXA_CONSOLE   NULL
  #endif
-diff -Nurb linux-2.6.22-570/include/asm-i386/kgdb.h linux-2.6.22-590/include/asm-i386/kgdb.h
---- linux-2.6.22-570/include/asm-i386/kgdb.h   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-i386/kgdb.h   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,51 @@
-+#ifdef __KERNEL__
-+#ifndef _ASM_KGDB_H_
-+#define _ASM_KGDB_H_
-+
-+#include <asm-generic/kgdb.h>
-+
-+/*
-+ * Copyright (C) 2001-2004 Amit S. Kale
-+ */
-+
-+/************************************************************************/
-+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
-+/* at least NUMREGBYTES*2 are needed for register packets */
-+/* Longer buffer is needed to list all threads */
-+#define BUFMAX                        1024
-+
-+/* Number of bytes of registers.  */
-+#define NUMREGBYTES           64
-+/* Number of bytes of registers we need to save for a setjmp/longjmp. */
-+#define NUMCRITREGBYTES               24
-+
-+/*
-+ *  Note that this register image is in a different order than
-+ *  the register image that Linux produces at interrupt time.
-+ *
-+ *  Linux's register image is defined by struct pt_regs in ptrace.h.
-+ *  Just why GDB uses a different order is a historical mystery.
-+ */
-+enum regnames { _EAX,         /* 0 */
-+      _ECX,                   /* 1 */
-+      _EDX,                   /* 2 */
-+      _EBX,                   /* 3 */
-+      _ESP,                   /* 4 */
-+      _EBP,                   /* 5 */
-+      _ESI,                   /* 6 */
-+      _EDI,                   /* 7 */
-+      _PC,                    /* 8 also known as eip */
-+      _PS,                    /* 9 also known as eflags */
-+      _CS,                    /* 10 */
-+      _SS,                    /* 11 */
-+      _DS,                    /* 12 */
-+      _ES,                    /* 13 */
-+      _FS,                    /* 14 */
-+      _GS                     /* 15 */
-+};
-+
-+#define BREAKPOINT()          asm("   int $3");
-+#define BREAK_INSTR_SIZE      1
-+#define CACHE_FLUSH_IS_SAFE   1
-+#endif                                /* _ASM_KGDB_H_ */
-+#endif                                /* __KERNEL__ */
-diff -Nurb linux-2.6.22-570/include/asm-i386/page.h linux-2.6.22-590/include/asm-i386/page.h
---- linux-2.6.22-570/include/asm-i386/page.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-i386/page.h   2008-01-02 13:56:37.000000000 -0500
-@@ -34,7 +34,8 @@
- #define clear_user_page(page, vaddr, pg)      clear_page(page)
- #define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
--#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
-+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
-+      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
- #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
- /*
-diff -Nurb linux-2.6.22-570/include/asm-i386/unistd.h linux-2.6.22-590/include/asm-i386/unistd.h
---- linux-2.6.22-570/include/asm-i386/unistd.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-i386/unistd.h 2008-01-02 13:56:37.000000000 -0500
-@@ -329,10 +329,13 @@
- #define __NR_signalfd         321
- #define __NR_timerfd          322
- #define __NR_eventfd          323
-+#define __NR_revokeat         324
-+#define __NR_frevoke          325
-+#define __NR_fallocate                326
- #ifdef __KERNEL__
--#define NR_syscalls 324
-+#define NR_syscalls 327
- #define __ARCH_WANT_IPC_PARSE_VERSION
- #define __ARCH_WANT_OLD_READDIR
-diff -Nurb linux-2.6.22-570/include/asm-i386/unwind.h linux-2.6.22-590/include/asm-i386/unwind.h
---- linux-2.6.22-570/include/asm-i386/unwind.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-i386/unwind.h 2008-01-02 13:56:37.000000000 -0500
-@@ -1,6 +1,95 @@
- #ifndef _ASM_I386_UNWIND_H
- #define _ASM_I386_UNWIND_H
-+/*
-+ * Copyright (C) 2002-2006 Novell, Inc.
-+ *    Jan Beulich <jbeulich@novell.com>
-+ * This code is released under version 2 of the GNU GPL.
-+ */
-+
-+#ifdef CONFIG_STACK_UNWIND
-+
-+#include <linux/sched.h>
-+#include <asm/fixmap.h>
-+#include <asm/ptrace.h>
-+#include <asm/uaccess.h>
-+
-+struct unwind_frame_info
-+{
-+      struct pt_regs regs;
-+      struct task_struct *task;
-+      unsigned call_frame:1;
-+};
-+
-+#define UNW_PC(frame)        (frame)->regs.eip
-+#define UNW_SP(frame)        (frame)->regs.esp
-+#ifdef CONFIG_FRAME_POINTER
-+#define UNW_FP(frame)        (frame)->regs.ebp
-+#define FRAME_RETADDR_OFFSET 4
-+#define FRAME_LINK_OFFSET    0
-+#define STACK_BOTTOM(tsk)    STACK_LIMIT((tsk)->thread.esp0)
-+#define STACK_TOP(tsk)       ((tsk)->thread.esp0)
-+#else
-+#define UNW_FP(frame) ((void)(frame), 0)
-+#endif
-+#define STACK_LIMIT(ptr)     (((ptr) - 1) & ~(THREAD_SIZE - 1))
-+
-+#define UNW_REGISTER_INFO \
-+      PTREGS_INFO(eax), \
-+      PTREGS_INFO(ecx), \
-+      PTREGS_INFO(edx), \
-+      PTREGS_INFO(ebx), \
-+      PTREGS_INFO(esp), \
-+      PTREGS_INFO(ebp), \
-+      PTREGS_INFO(esi), \
-+      PTREGS_INFO(edi), \
-+      PTREGS_INFO(eip)
-+
-+#define UNW_DEFAULT_RA(raItem, dataAlign) \
-+      ((raItem).where == Memory && \
-+       !((raItem).value * (dataAlign) + 4))
-+
-+static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
-+                                            /*const*/ struct pt_regs *regs)
-+{
-+      if (user_mode_vm(regs))
-+              info->regs = *regs;
-+      else {
-+              memcpy(&info->regs, regs, offsetof(struct pt_regs, esp));
-+              info->regs.esp = (unsigned long)&regs->esp;
-+              info->regs.xss = __KERNEL_DS;
-+      }
-+}
-+
-+static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
-+{
-+      memset(&info->regs, 0, sizeof(info->regs));
-+      info->regs.eip = info->task->thread.eip;
-+      info->regs.xcs = __KERNEL_CS;
-+      __get_user(info->regs.ebp, (long *)info->task->thread.esp);
-+      info->regs.esp = info->task->thread.esp;
-+      info->regs.xss = __KERNEL_DS;
-+      info->regs.xds = __USER_DS;
-+      info->regs.xes = __USER_DS;
-+      info->regs.xfs = __KERNEL_PERCPU;
-+}
-+
-+extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
-+                                               asmlinkage int (*callback)(struct unwind_frame_info *,
-+                                                                          void *arg),
-+                                               void *arg);
-+
-+static inline int arch_unw_user_mode(/*const*/ struct unwind_frame_info *info)
-+{
-+      return user_mode_vm(&info->regs)
-+             || info->regs.eip < PAGE_OFFSET
-+             || (info->regs.eip >= __fix_to_virt(FIX_VDSO)
-+                 && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE)
-+             || info->regs.esp < PAGE_OFFSET;
-+}
-+
-+#else
-+
- #define UNW_PC(frame) ((void)(frame), 0)
- #define UNW_SP(frame) ((void)(frame), 0)
- #define UNW_FP(frame) ((void)(frame), 0)
-@@ -10,4 +99,6 @@
-       return 0;
- }
-+#endif
-+
- #endif /* _ASM_I386_UNWIND_H */
-diff -Nurb linux-2.6.22-570/include/asm-ia64/kdebug.h linux-2.6.22-590/include/asm-ia64/kdebug.h
---- linux-2.6.22-570/include/asm-ia64/kdebug.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-ia64/kdebug.h 2008-01-02 13:56:37.000000000 -0500
-@@ -69,6 +69,7 @@
-       DIE_KDEBUG_LEAVE,
-       DIE_KDUMP_ENTER,
-       DIE_KDUMP_LEAVE,
-+      DIE_PAGE_FAULT_NO_CONTEXT,
- };
+diff -Nurb linux-2.6.22-590/drivers/serial/serial_core.c linux-2.6.22-570/drivers/serial/serial_core.c
+--- linux-2.6.22-590/drivers/serial/serial_core.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/serial_core.c      2007-07-08 19:32:17.000000000 -0400
+@@ -33,7 +33,6 @@
+ #include <linux/serial.h> /* for serial_state and serial_icounter_struct */
+ #include <linux/delay.h>
+ #include <linux/mutex.h>
+-#include <linux/kgdb.h>
  
+ #include <asm/irq.h>
+ #include <asm/uaccess.h>
+@@ -59,12 +58,6 @@
+ #define uart_console(port)    (0)
  #endif
-diff -Nurb linux-2.6.22-570/include/asm-ia64/kgdb.h linux-2.6.22-590/include/asm-ia64/kgdb.h
---- linux-2.6.22-570/include/asm-ia64/kgdb.h   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-ia64/kgdb.h   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,37 @@
-+#ifdef __KERNEL__
-+#ifndef _ASM_KGDB_H_
-+#define _ASM_KGDB_H_
-+
-+/*
-+ * Copyright (C) 2001-2004 Amit S. Kale
-+ */
-+
-+#include <linux/threads.h>
-+#include <asm-generic/kgdb.h>
-+
-+/************************************************************************/
-+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
-+/* at least NUMREGBYTES*2 are needed for register packets */
-+/* Longer buffer is needed to list all threads */
-+#define BUFMAX                        1024
-+
-+/* Number of bytes of registers.  We set this to 0 so that certain GDB
-+ * packets will fail, forcing the use of others, which are more friendly
-+ * on ia64. */
-+#define NUMREGBYTES           0
-+
-+#define NUMCRITREGBYTES               (70*8)
-+#define JMP_REGS_ALIGNMENT    __attribute__ ((aligned (16)))
-+
-+#define BREAKNUM              0x00003333300LL
-+#define KGDBBREAKNUM          0x6665UL
-+#define BREAKPOINT()          asm volatile ("break.m 0x6665")
-+#define BREAK_INSTR_SIZE      16
-+#define CACHE_FLUSH_IS_SAFE   1
-+
-+struct pt_regs;
-+extern volatile int kgdb_hwbreak_sstep[NR_CPUS];
-+extern void smp_send_nmi_allbutself(void);
-+extern void kgdb_wait_ipi(struct pt_regs *);
-+#endif                                /* _ASM_KGDB_H_ */
-+#endif                                /* __KERNEL__ */
-diff -Nurb linux-2.6.22-570/include/asm-ia64/page.h linux-2.6.22-590/include/asm-ia64/page.h
---- linux-2.6.22-570/include/asm-ia64/page.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-ia64/page.h   2008-01-02 13:56:37.000000000 -0500
-@@ -87,9 +87,10 @@
- } while (0)
--#define alloc_zeroed_user_highpage(vma, vaddr) \
-+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr)                \
- ({                                            \
--      struct page *page = alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr); \
-+      struct page *page = alloc_page_vma(                             \
-+              GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr);  \
-       if (page)                               \
-               flush_dcache_page(page);        \
-       page;                                   \
-diff -Nurb linux-2.6.22-570/include/asm-ia64/processor.h linux-2.6.22-590/include/asm-ia64/processor.h
---- linux-2.6.22-570/include/asm-ia64/processor.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-ia64/processor.h      2008-01-02 13:56:37.000000000 -0500
-@@ -295,9 +295,9 @@
-       regs->ar_bspstore = current->thread.rbs_bot;                                            \
-       regs->ar_fpsr = FPSR_DEFAULT;                                                           \
-       regs->loadrs = 0;                                                                       \
--      regs->r8 = current->mm->dumpable;       /* set "don't zap registers" flag */            \
-+      regs->r8 = get_dumpable(current->mm);   /* set "don't zap registers" flag */            \
-       regs->r12 = new_sp - 16;        /* allocate 16 byte scratch area */                     \
--      if (unlikely(!current->mm->dumpable)) {                                                 \
-+      if (unlikely(!get_dumpable(current->mm))) {                                                     \
-               /*                                                                              \
-                * Zap scratch regs to avoid leaking bits between processes with different      \
-                * uid/privileges.                                                              \
-diff -Nurb linux-2.6.22-570/include/asm-m32r/page.h linux-2.6.22-590/include/asm-m32r/page.h
---- linux-2.6.22-570/include/asm-m32r/page.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-m32r/page.h   2008-01-02 13:56:37.000000000 -0500
-@@ -15,7 +15,8 @@
- #define clear_user_page(page, vaddr, pg)      clear_page(page)
- #define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
--#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
-+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
-+      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
- #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
  
- /*
-diff -Nurb linux-2.6.22-570/include/asm-m68knommu/page.h linux-2.6.22-590/include/asm-m68knommu/page.h
---- linux-2.6.22-570/include/asm-m68knommu/page.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-m68knommu/page.h      2008-01-02 13:56:37.000000000 -0500
-@@ -22,7 +22,8 @@
- #define clear_user_page(page, vaddr, pg)      clear_page(page)
- #define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
+-#ifdef CONFIG_KGDB_CONSOLE
+-#define uart_kgdb(port)               (port->cons && !strcmp(port->cons->name, "kgdb"))
+-#else
+-#define uart_kgdb(port)               (0)
+-#endif
+-
+ static void uart_change_speed(struct uart_state *state, struct ktermios *old_termios);
+ static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
+ static void uart_change_pm(struct uart_state *state, int pm_state);
+@@ -1678,9 +1671,6 @@
+                       mmio ? "mmio:0x" : "port:",
+                       mmio ? port->mapbase : (unsigned long) port->iobase,
+                       port->irq);
+-      if (port->iotype == UPIO_MEM)
+-              ret += sprintf(buf+ret, " membase 0x%08lX",
+-                                         (unsigned long) port->membase);
  
--#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
-+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
-+      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
- #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+       if (port->type == PORT_UNKNOWN) {
+               strcat(buf, "\n");
+@@ -2073,8 +2063,7 @@
+       case UPIO_TSI:
+       case UPIO_DWAPB:
+               snprintf(address, sizeof(address),
+-                      "MMIO map 0x%lx mem 0x%lx", port->mapbase,
+-                      (unsigned long) port->membase);
++                       "MMIO 0x%lx", port->mapbase);
+               break;
+       default:
+               strlcpy(address, "*unknown*", sizeof(address));
+@@ -2129,9 +2118,9 @@
  
- /*
-diff -Nurb linux-2.6.22-570/include/asm-mips/asmmacro-32.h linux-2.6.22-590/include/asm-mips/asmmacro-32.h
---- linux-2.6.22-570/include/asm-mips/asmmacro-32.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-mips/asmmacro-32.h    2008-01-02 13:56:37.000000000 -0500
-@@ -11,6 +11,28 @@
- #include <asm/regdef.h>
- #include <asm/fpregdef.h>
- #include <asm/mipsregs.h>
-+#include <asm/gdb-stub.h>
-+
-+      .macro  fpu_save_double_kgdb stack status tmp1=t0
-+      cfc1    \tmp1,  fcr31
-+      sdc1    $f0, GDB_FR_FPR0(\stack)
-+      sdc1    $f2, GDB_FR_FPR2(\stack)
-+      sdc1    $f4, GDB_FR_FPR4(\stack)
-+      sdc1    $f6, GDB_FR_FPR6(\stack)
-+      sdc1    $f8, GDB_FR_FPR8(\stack)
-+      sdc1    $f10, GDB_FR_FPR10(\stack)
-+      sdc1    $f12, GDB_FR_FPR12(\stack)
-+      sdc1    $f14, GDB_FR_FPR14(\stack)
-+      sdc1    $f16, GDB_FR_FPR16(\stack)
-+      sdc1    $f18, GDB_FR_FPR18(\stack)
-+      sdc1    $f20, GDB_FR_FPR20(\stack)
-+      sdc1    $f22, GDB_FR_FPR22(\stack)
-+      sdc1    $f24, GDB_FR_FPR24(\stack)
-+      sdc1    $f26, GDB_FR_FPR26(\stack)
-+      sdc1    $f28, GDB_FR_FPR28(\stack)
-+      sdc1    $f30, GDB_FR_FPR30(\stack)
-+      sw      \tmp1, GDB_FR_FSR(\stack)
-+      .endm
+               /*
+                * Power down all ports by default, except the
+-               * console (real or kgdb) if we have one.
++               * console if we have one.
+                */
+-              if (!uart_console(port) && !uart_kgdb(port))
++              if (!uart_console(port))
+                       uart_change_pm(state, 3);
+       }
+ }
+@@ -2322,12 +2311,6 @@
+        */
+       port->flags &= ~UPF_DEAD;
  
-       .macro  fpu_save_double thread status tmp1=t0
-       cfc1    \tmp1,  fcr31
-@@ -91,6 +113,27 @@
-       ctc1    \tmp, fcr31
-       .endm
+-#if defined(CONFIG_KGDB_8250)
+-      /* Add any 8250-like ports we find later. */
+-      if (port->type <= PORT_MAX_8250)
+-              kgdb8250_add_port(port->line, port);
+-#endif
+-
+  out:
+       mutex_unlock(&state->mutex);
+       mutex_unlock(&port_mutex);
+diff -Nurb linux-2.6.22-590/drivers/serial/serial_txx9.c linux-2.6.22-570/drivers/serial/serial_txx9.c
+--- linux-2.6.22-590/drivers/serial/serial_txx9.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/serial_txx9.c      2007-07-08 19:32:17.000000000 -0400
+@@ -40,10 +40,6 @@
+ static char *serial_version = "1.09";
+ static char *serial_name = "TX39/49 Serial driver";
  
-+      .macro  fpu_restore_double_kgdb stack status tmp=t0
-+      lw      \tmp, GDB_FR_FSR(\stack)
-+      ldc1    $f0,  GDB_FR_FPR0(\stack)
-+      ldc1    $f2,  GDB_FR_FPR2(\stack)
-+      ldc1    $f4,  GDB_FR_FPR4(\stack)
-+      ldc1    $f6,  GDB_FR_FPR6(\stack)
-+      ldc1    $f8,  GDB_FR_FPR8(\stack)
-+      ldc1    $f10, GDB_FR_FPR10(\stack)
-+      ldc1    $f12, GDB_FR_FPR12(\stack)
-+      ldc1    $f14, GDB_FR_FPR14(\stack)
-+      ldc1    $f16, GDB_FR_FPR16(\stack)
-+      ldc1    $f18, GDB_FR_FPR18(\stack)
-+      ldc1    $f20, GDB_FR_FPR20(\stack)
-+      ldc1    $f22, GDB_FR_FPR22(\stack)
-+      ldc1    $f24, GDB_FR_FPR24(\stack)
-+      ldc1    $f26, GDB_FR_FPR26(\stack)
-+      ldc1    $f28, GDB_FR_FPR28(\stack)
-+      ldc1    $f30, GDB_FR_FPR30(\stack)
-+      ctc1    \tmp, fcr31
-+      .endm
-+
-       .macro  fpu_restore_single thread tmp=t0
-       lw      \tmp, THREAD_FCR31(\thread)
-       lwc1    $f0,  THREAD_FPR0(\thread)
-diff -Nurb linux-2.6.22-570/include/asm-mips/asmmacro-64.h linux-2.6.22-590/include/asm-mips/asmmacro-64.h
---- linux-2.6.22-570/include/asm-mips/asmmacro-64.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-mips/asmmacro-64.h    2008-01-02 13:56:37.000000000 -0500
-@@ -12,6 +12,7 @@
- #include <asm/regdef.h>
- #include <asm/fpregdef.h>
- #include <asm/mipsregs.h>
-+#include <asm/gdb-stub.h>
+-#ifndef CONFIG_KGDB_TXX9
+-#define CONFIG_KGDB_PORT_NUM -1
+-#endif
+-
+ #define PASS_LIMIT    256
  
-       .macro  fpu_save_16even thread tmp=t0
-       cfc1    \tmp, fcr31
-@@ -53,6 +54,46 @@
-       sdc1    $f31, THREAD_FPR31(\thread)
-       .endm
+ #if !defined(CONFIG_SERIAL_TXX9_STDSERIAL)
+@@ -475,9 +471,6 @@
+       unsigned long flags;
+       int retval;
  
-+      .macro  fpu_save_16odd_kgdb stack
-+      sdc1    $f1, GDB_FR_FPR1(\stack)
-+      sdc1    $f3, GDB_FR_FPR3(\stack)
-+      sdc1    $f5, GDB_FR_FPR5(\stack)
-+      sdc1    $f7, GDB_FR_FPR7(\stack)
-+      sdc1    $f9, GDB_FR_FPR9(\stack)
-+      sdc1    $f11, GDB_FR_FPR11(\stack)
-+      sdc1    $f13, GDB_FR_FPR13(\stack)
-+      sdc1    $f15, GDB_FR_FPR15(\stack)
-+      sdc1    $f17, GDB_FR_FPR17(\stack)
-+      sdc1    $f19, GDB_FR_FPR19(\stack)
-+      sdc1    $f21, GDB_FR_FPR21(\stack)
-+      sdc1    $f23, GDB_FR_FPR23(\stack)
-+      sdc1    $f25, GDB_FR_FPR25(\stack)
-+      sdc1    $f27, GDB_FR_FPR27(\stack)
-+      sdc1    $f29, GDB_FR_FPR29(\stack)
-+      sdc1    $f31, GDB_FR_FPR31(\stack)
-+      .endm
-+
-+      .macro  fpu_save_16even_kgdb stack tmp=t0
-+      cfc1    \tmp,  fcr31
-+      sdc1    $f0, GDB_FR_FPR0(\stack)
-+      sdc1    $f2, GDB_FR_FPR2(\stack)
-+      sdc1    $f4, GDB_FR_FPR4(\stack)
-+      sdc1    $f6, GDB_FR_FPR6(\stack)
-+      sdc1    $f8, GDB_FR_FPR8(\stack)
-+      sdc1    $f10, GDB_FR_FPR10(\stack)
-+      sdc1    $f12, GDB_FR_FPR12(\stack)
-+      sdc1    $f14, GDB_FR_FPR14(\stack)
-+      sdc1    $f16, GDB_FR_FPR16(\stack)
-+      sdc1    $f18, GDB_FR_FPR18(\stack)
-+      sdc1    $f20, GDB_FR_FPR20(\stack)
-+      sdc1    $f22, GDB_FR_FPR22(\stack)
-+      sdc1    $f24, GDB_FR_FPR24(\stack)
-+      sdc1    $f26, GDB_FR_FPR26(\stack)
-+      sdc1    $f28, GDB_FR_FPR28(\stack)
-+      sdc1    $f30, GDB_FR_FPR30(\stack)
-+      sw      \tmp, GDB_FR_FSR(\stack)
-+      .endm
-+
-       .macro  fpu_save_double thread status tmp
-       sll     \tmp, \status, 5
-       bgez    \tmp, 2f
-@@ -61,6 +102,15 @@
-       fpu_save_16even \thread \tmp
-       .endm
+-      if (up->port.line == CONFIG_KGDB_PORT_NUM)
+-              return -EBUSY;
+-
+       /*
+        * Clear the FIFO buffers and disable them.
+        * (they will be reenabled in set_termios())
+@@ -806,9 +799,6 @@
+       for (i = 0; i < UART_NR; i++) {
+               struct uart_txx9_port *up = &serial_txx9_ports[i];
  
-+      .macro  fpu_save_double_kgdb stack status tmp
-+      sll     \tmp, \status, 5
-+      bgez    \tmp, 2f
-+      nop
-+      fpu_save_16odd_kgdb \stack
-+2:
-+      fpu_save_16even_kgdb \stack \tmp
-+      .endm
-+
-       .macro  fpu_restore_16even thread tmp=t0
-       lw      \tmp, THREAD_FCR31(\thread)
-       ldc1    $f0,  THREAD_FPR0(\thread)
-@@ -101,6 +151,46 @@
-       ldc1    $f31, THREAD_FPR31(\thread)
-       .endm
+-              if (up->port.line == CONFIG_KGDB_PORT_NUM)
+-                      continue;
+-
+               up->port.line = i;
+               up->port.ops = &serial_txx9_pops;
+               up->port.dev = dev;
+@@ -977,9 +967,6 @@
  
-+      .macro  fpu_restore_16even_kgdb stack tmp=t0
-+      lw      \tmp, GDB_FR_FSR(\stack)
-+      ldc1    $f0,  GDB_FR_FPR0(\stack)
-+      ldc1    $f2,  GDB_FR_FPR2(\stack)
-+      ldc1    $f4,  GDB_FR_FPR4(\stack)
-+      ldc1    $f6,  GDB_FR_FPR6(\stack)
-+      ldc1    $f8,  GDB_FR_FPR8(\stack)
-+      ldc1    $f10, GDB_FR_FPR10(\stack)
-+      ldc1    $f12, GDB_FR_FPR12(\stack)
-+      ldc1    $f14, GDB_FR_FPR14(\stack)
-+      ldc1    $f16, GDB_FR_FPR16(\stack)
-+      ldc1    $f18, GDB_FR_FPR18(\stack)
-+      ldc1    $f20, GDB_FR_FPR20(\stack)
-+      ldc1    $f22, GDB_FR_FPR22(\stack)
-+      ldc1    $f24, GDB_FR_FPR24(\stack)
-+      ldc1    $f26, GDB_FR_FPR26(\stack)
-+      ldc1    $f28, GDB_FR_FPR28(\stack)
-+      ldc1    $f30, GDB_FR_FPR30(\stack)
-+      ctc1    \tmp, fcr31
-+      .endm
-+
-+      .macro  fpu_restore_16odd_kgdb stack
-+      ldc1    $f1,  GDB_FR_FPR1(\stack)
-+      ldc1    $f3,  GDB_FR_FPR3(\stack)
-+      ldc1    $f5,  GDB_FR_FPR5(\stack)
-+      ldc1    $f7,  GDB_FR_FPR7(\stack)
-+      ldc1    $f9,  GDB_FR_FPR9(\stack)
-+      ldc1    $f11, GDB_FR_FPR11(\stack)
-+      ldc1    $f13, GDB_FR_FPR13(\stack)
-+      ldc1    $f15, GDB_FR_FPR15(\stack)
-+      ldc1    $f17, GDB_FR_FPR17(\stack)
-+      ldc1    $f19, GDB_FR_FPR19(\stack)
-+      ldc1    $f21, GDB_FR_FPR21(\stack)
-+      ldc1    $f23, GDB_FR_FPR23(\stack)
-+      ldc1    $f25, GDB_FR_FPR25(\stack)
-+      ldc1    $f27, GDB_FR_FPR27(\stack)
-+      ldc1    $f29, GDB_FR_FPR29(\stack)
-+      ldc1    $f31, GDB_FR_FPR31(\stack)
-+      .endm
-+
-       .macro  fpu_restore_double thread status tmp
-       sll     \tmp, \status, 5
-       bgez    \tmp, 1f                                # 16 register mode?
-@@ -109,6 +199,15 @@
- 1:    fpu_restore_16even \thread \tmp
-       .endm
+       mutex_lock(&serial_txx9_mutex);
+       for (i = 0; i < UART_NR; i++) {
+-              if (i == CONFIG_KGDB_PORT_NUM)
+-                      continue;
+-
+               uart = &serial_txx9_ports[i];
+               if (uart_match_port(&uart->port, port)) {
+                       uart_remove_one_port(&serial_txx9_reg, &uart->port);
+diff -Nurb linux-2.6.22-590/drivers/serial/serial_txx9_kgdb.c linux-2.6.22-570/drivers/serial/serial_txx9_kgdb.c
+--- linux-2.6.22-590/drivers/serial/serial_txx9_kgdb.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/serial_txx9_kgdb.c 1969-12-31 19:00:00.000000000 -0500
+@@ -1,150 +0,0 @@
+-/*
+- * drivers/serial/serial_txx9_kgdb.c
+- *
+- * kgdb interface for gdb
+- *
+- * Author: MontaVista Software, Inc.
+- *         source@mvista.com
+- *
+- * Copyright (C) 2005-2006 MontaVista Software 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.
+- */
+-
+-#include <linux/delay.h>
+-#include <linux/init.h>
+-#include <linux/kgdb.h>
+-#include <asm/io.h>
+-
+-/* Speed of the UART. */
+-static unsigned int kgdb_txx9_baud = CONFIG_KGDB_BAUDRATE;
+-
+-#define TXX9_NPORT 4          /* TX4939 has 4 UARTs, others only have 2 */
+-
+-static struct uart_port  kgdb_txx9_ports[TXX9_NPORT];
+-static struct uart_port *kgdb_port;
+-
+-/* TXX9 Serial Registers */
+-#define TXX9_SILCR    0x00
+-#define TXX9_SIDISR   0x08
+-#define TXX9_SISCISR  0x0c
+-#define TXX9_SIFCR    0x10
+-#define TXX9_SIFLCR   0x14
+-#define TXX9_SIBGR    0x18
+-#define TXX9_SITFIFO  0x1c
+-#define TXX9_SIRFIFO  0x20
+-
+-/* SILCR : Line Control */
+-#define TXX9_SILCR_SCS_IMCLK_BG       0x00000020
+-#define TXX9_SILCR_SCS_SCLK_BG        0x00000060
+-#define TXX9_SILCR_USBL_1BIT  0x00000000
+-#define TXX9_SILCR_UMODE_8BIT 0x00000000
+-
+-/* SIDISR : DMA/Int. Status */
+-#define TXX9_SIDISR_RFDN_MASK 0x0000001f
+-
+-/* SISCISR : Status Change Int. Status */
+-#define TXX9_SISCISR_TRDY     0x00000004
+-
+-/* SIFCR : FIFO Control */
+-#define TXX9_SIFCR_SWRST      0x00008000
+-
+-/* SIBGR : Baud Rate Control */
+-#define TXX9_SIBGR_BCLK_T0    0x00000000
+-#define TXX9_SIBGR_BCLK_T2    0x00000100
+-#define TXX9_SIBGR_BCLK_T4    0x00000200
+-#define TXX9_SIBGR_BCLK_T6    0x00000300
+-
+-static inline unsigned int sio_in(struct uart_port *port, int offset)
+-{
+-      return *(volatile u32 *)(port->membase + offset);
+-}
+-
+-static inline void sio_out(struct uart_port *port, int offset, unsigned int value)
+-{
+-      *(volatile u32 *)(port->membase + offset) = value;
+-}
+-
+-void __init txx9_kgdb_add_port(int n, struct uart_port *port)
+-{
+-      memcpy(&kgdb_txx9_ports[n], port, sizeof(struct uart_port));
+-}
+-
+-static int txx9_kgdb_init(void)
+-{
+-      unsigned int quot, sibgr;
+-
+-      kgdb_port = &kgdb_txx9_ports[CONFIG_KGDB_PORT_NUM];
+-
+-      if (kgdb_port->iotype != UPIO_MEM &&
+-          kgdb_port->iotype != UPIO_MEM32)
+-              return -1;
+-
+-      /* Reset the UART. */
+-      sio_out(kgdb_port, TXX9_SIFCR, TXX9_SIFCR_SWRST);
+-#ifdef CONFIG_CPU_TX49XX
+-      /*
+-       * TX4925 BUG WORKAROUND.  Accessing SIOC register
+-       * immediately after soft reset causes bus error.
+-       */
+-      iob();
+-      udelay(1);
+-#endif
+-      /* Wait until reset is complete. */
+-      while (sio_in(kgdb_port, TXX9_SIFCR) & TXX9_SIFCR_SWRST);
+-
+-      /* Select the frame format and input clock. */
+-      sio_out(kgdb_port, TXX9_SILCR,
+-              TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
+-              ((kgdb_port->flags & UPF_MAGIC_MULTIPLIER) ?
+-              TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
+-
+-      /* Select the input clock prescaler that fits the baud rate. */
+-      quot = (kgdb_port->uartclk + 8 * kgdb_txx9_baud) / (16 * kgdb_txx9_baud);
+-      if (quot < (256 << 1))
+-              sibgr = (quot >> 1) | TXX9_SIBGR_BCLK_T0;
+-      else if (quot < ( 256 << 3))
+-              sibgr = (quot >> 3) | TXX9_SIBGR_BCLK_T2;
+-      else if (quot < ( 256 << 5))
+-              sibgr = (quot >> 5) | TXX9_SIBGR_BCLK_T4;
+-      else if (quot < ( 256 << 7))
+-              sibgr = (quot >> 7) | TXX9_SIBGR_BCLK_T6;
+-      else
+-              sibgr = 0xff | TXX9_SIBGR_BCLK_T6;
+-
+-      sio_out(kgdb_port, TXX9_SIBGR, sibgr);
+-
+-      /* Enable receiver and transmitter. */
+-      sio_out(kgdb_port, TXX9_SIFLCR, 0);
+-
+-      return 0;
+-}
+-
+-static void txx9_kgdb_late_init(void)
+-{
+-      request_mem_region(kgdb_port->mapbase, 0x40, "serial_txx9(debug)");
+-}
+-
+-static int txx9_kgdb_read(void)
+-{
+-      while (!(sio_in(kgdb_port, TXX9_SIDISR) & TXX9_SIDISR_RFDN_MASK));
+-
+-      return sio_in(kgdb_port, TXX9_SIRFIFO);
+-}
+-
+-static void txx9_kgdb_write(u8 ch)
+-{
+-      while (!(sio_in(kgdb_port, TXX9_SISCISR) & TXX9_SISCISR_TRDY));
+-
+-      sio_out(kgdb_port, TXX9_SITFIFO, ch);
+-}
+-
+-struct kgdb_io kgdb_io_ops = {
+-      .read_char      = txx9_kgdb_read,
+-      .write_char     = txx9_kgdb_write,
+-      .init           = txx9_kgdb_init,
+-      .late_init      = txx9_kgdb_late_init
+-};
+diff -Nurb linux-2.6.22-590/drivers/serial/sh-sci.c linux-2.6.22-570/drivers/serial/sh-sci.c
+--- linux-2.6.22-590/drivers/serial/sh-sci.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/serial/sh-sci.c   2007-07-08 19:32:17.000000000 -0400
+@@ -118,8 +118,7 @@
+       do {
+               status = sci_in(port, SCxSR);
+               if (status & SCxSR_ERRORS(port)) {
+-                      /* Clear error flags. */
+-                      sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
++                      handle_error(port);
+                       continue;
+               }
+       } while (!(status & SCxSR_RDxF(port)));
+@@ -185,18 +184,18 @@
+                       int h, l;
  
-+      .macro  fpu_restore_double_kgdb stack status tmp
-+      sll     \tmp, \status, 5
-+      bgez    \tmp, 1f                                # 16 register mode?
-+      nop
-+
-+      fpu_restore_16odd_kgdb \stack
-+1:    fpu_restore_16even_kgdb \stack \tmp
-+      .endm
-+
-       .macro  cpu_save_nonscratch thread
-       LONG_S  s0, THREAD_REG16(\thread)
-       LONG_S  s1, THREAD_REG17(\thread)
-diff -Nurb linux-2.6.22-570/include/asm-mips/kdebug.h linux-2.6.22-590/include/asm-mips/kdebug.h
---- linux-2.6.22-570/include/asm-mips/kdebug.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-mips/kdebug.h 2008-01-02 13:56:37.000000000 -0500
-@@ -1 +1,30 @@
--#include <asm-generic/kdebug.h>
-+/*
-+ *
-+ * Copyright (C) 2004  MontaVista Software Inc.
-+ * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.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.
-+ *
-+ */
-+#ifndef _MIPS_KDEBUG_H
-+#define _MIPS_KDEBUG_H
-+
-+#include <linux/notifier.h>
-+
-+struct pt_regs;
-+
-+extern struct atomic_notifier_head mips_die_head;
-+
-+enum die_val {
-+      DIE_OOPS = 1,
-+      DIE_PANIC,
-+      DIE_DIE,
-+      DIE_KERNELDEBUG,
-+      DIE_TRAP,
-+      DIE_PAGE_FAULT,
-+};
-+
-+#endif /* _MIPS_KDEBUG_H */
-diff -Nurb linux-2.6.22-570/include/asm-mips/kgdb.h linux-2.6.22-590/include/asm-mips/kgdb.h
---- linux-2.6.22-570/include/asm-mips/kgdb.h   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-mips/kgdb.h   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,41 @@
-+#ifdef __KERNEL__
-+#ifndef _ASM_KGDB_H_
-+#define _ASM_KGDB_H_
-+
-+#include <asm/sgidefs.h>
-+#include <asm-generic/kgdb.h>
-+
-+#ifndef __ASSEMBLY__
-+#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS32)
-+
-+typedef u32 gdb_reg_t;
-+
-+#elif (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
-+
-+#ifdef CONFIG_32BIT
-+typedef u32 gdb_reg_t;
-+#else /* CONFIG_CPU_32BIT */
-+typedef u64 gdb_reg_t;
-+#endif
-+#else
-+#error "Need to set typedef for gdb_reg_t"
-+#endif /* _MIPS_ISA */
-+
-+#define BUFMAX                        2048
-+#define NUMREGBYTES           (90*sizeof(gdb_reg_t))
-+#define NUMCRITREGBYTES               (12*sizeof(gdb_reg_t))
-+#define BREAK_INSTR_SIZE      4
-+#define BREAKPOINT()          __asm__ __volatile__(           \
-+                                      ".globl breakinst\n\t"  \
-+                                      ".set\tnoreorder\n\t"   \
-+                                      "nop\n"                 \
-+                                      "breakinst:\tbreak\n\t" \
-+                                      "nop\n\t"               \
-+                                      ".set\treorder")
-+#define CACHE_FLUSH_IS_SAFE   0
-+
-+extern int kgdb_early_setup;
-+
-+#endif                                /* !__ASSEMBLY__ */
-+#endif                                /* _ASM_KGDB_H_ */
-+#endif                                /* __KERNEL__ */
-diff -Nurb linux-2.6.22-570/include/asm-mips/ptrace.h linux-2.6.22-590/include/asm-mips/ptrace.h
---- linux-2.6.22-570/include/asm-mips/ptrace.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-mips/ptrace.h 2008-01-02 13:56:37.000000000 -0500
-@@ -28,7 +28,7 @@
-  * system call/exception. As usual the registers k0/k1 aren't being saved.
-  */
- struct pt_regs {
--#ifdef CONFIG_32BIT
-+#if defined(CONFIG_32BIT) || defined(CONFIG_KGDB)
-       /* Pad bytes for argument save space on the stack. */
-       unsigned long pad0[6];
- #endif
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/cputable.h linux-2.6.22-590/include/asm-powerpc/cputable.h
---- linux-2.6.22-570/include/asm-powerpc/cputable.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/cputable.h    2008-01-02 13:56:37.000000000 -0500
-@@ -111,7 +111,7 @@
- /* CPU kernel features */
+                       c = *p++;
+-                      h = hexchars[c >> 4];
+-                      l = hexchars[c % 16];
++                      h = highhex(c);
++                      l = lowhex(c);
+                       put_char(port, h);
+                       put_char(port, l);
+                       checksum += h + l;
+               }
+               put_char(port, '#');
+-              put_char(port, hexchars[checksum >> 4]);
+-              put_char(port, hexchars[checksum & 16]);
++              put_char(port, highhex(checksum));
++              put_char(port, lowhex(checksum));
+           } while  (get_char(port) != '+');
+       } else
+-#endif /* CONFIG_SH_STANDARD_BIOS */
++#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
+       for (i=0; i<count; i++) {
+               if (*p == 10)
+                       put_char(port, '\r');
+@@ -548,16 +547,6 @@
+                                       continue;
+                               }
  
- /* Retain the 32b definitions all use bottom half of word */
--#define CPU_FTR_SPLIT_ID_CACHE                ASM_CONST(0x0000000000000001)
-+#define CPU_FTR_COHERENT_ICACHE               ASM_CONST(0x0000000000000001)
- #define CPU_FTR_L2CR                  ASM_CONST(0x0000000000000002)
- #define CPU_FTR_SPEC7450              ASM_CONST(0x0000000000000004)
- #define CPU_FTR_ALTIVEC                       ASM_CONST(0x0000000000000008)
-@@ -135,6 +135,7 @@
- #define CPU_FTR_PPC_LE                        ASM_CONST(0x0000000000200000)
- #define CPU_FTR_REAL_LE                       ASM_CONST(0x0000000000400000)
- #define CPU_FTR_FPU_UNAVAILABLE               ASM_CONST(0x0000000000800000)
-+#define CPU_FTR_UNIFIED_ID_CACHE      ASM_CONST(0x0000000001000000)
+-#ifdef CONFIG_KGDB_SH_SCI
+-                              /* We assume that a ^C on the port KGDB
+-                               * is using means that KGDB wants to
+-                               * interrupt the running system.
+-                               */
+-                              if (port->line == KGDBPORT.port.line &&
+-                                              c == 3)
+-                                      breakpoint();
+-#endif
+-
+                               /* Store data and status */
+                               if (status&SCxSR_FER(port)) {
+                                       flag = TTY_FRAME;
+@@ -1290,7 +1279,6 @@
+ console_initcall(sci_console_init);
+ #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
  
+-#if 0
+ #ifdef CONFIG_SH_KGDB
  /*
-  * Add the 64-bit processor unique features in the top half of the word;
-@@ -154,7 +155,6 @@
- #define CPU_FTR_MMCRA                 LONG_ASM_CONST(0x0000004000000000)
- #define CPU_FTR_CTRL                  LONG_ASM_CONST(0x0000008000000000)
- #define CPU_FTR_SMT                   LONG_ASM_CONST(0x0000010000000000)
--#define CPU_FTR_COHERENT_ICACHE               LONG_ASM_CONST(0x0000020000000000)
- #define CPU_FTR_LOCKLESS_TLBIE                LONG_ASM_CONST(0x0000040000000000)
- #define CPU_FTR_CI_LARGE_PAGE         LONG_ASM_CONST(0x0000100000000000)
- #define CPU_FTR_PAUSE_ZERO            LONG_ASM_CONST(0x0000200000000000)
-@@ -206,164 +206,163 @@
-                    !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
-                    !defined(CONFIG_BOOKE))
--#define CPU_FTRS_PPC601       (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE)
--#define CPU_FTRS_603  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_PPC601       (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE | \
-+      CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
-+#define CPU_FTRS_603  (CPU_FTR_COMMON | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
-           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
--#define CPU_FTRS_604  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_604  (CPU_FTR_COMMON | \
-           CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \
-           CPU_FTR_PPC_LE)
--#define CPU_FTRS_740_NOTAU    (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_740_NOTAU    (CPU_FTR_COMMON | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
--#define CPU_FTRS_740  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_740  (CPU_FTR_COMMON | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-           CPU_FTR_PPC_LE)
--#define CPU_FTRS_750  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_750  (CPU_FTR_COMMON | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-           CPU_FTR_PPC_LE)
--#define CPU_FTRS_750CL        (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_750CL        (CPU_FTR_COMMON | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-           CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
--#define CPU_FTRS_750FX1       (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_750FX1       (CPU_FTR_COMMON | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-           CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
--#define CPU_FTRS_750FX2       (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_750FX2       (CPU_FTR_COMMON | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-           CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
--#define CPU_FTRS_750FX        (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_750FX        (CPU_FTR_COMMON | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-           CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
--#define CPU_FTRS_750GX        (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_750GX        (CPU_FTR_COMMON | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-           CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
--#define CPU_FTRS_7400_NOTAU   (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_7400_NOTAU   (CPU_FTR_COMMON | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
-           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
--#define CPU_FTRS_7400 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_7400 (CPU_FTR_COMMON | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
-           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
--#define CPU_FTRS_7450_20      (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_7450_20      (CPU_FTR_COMMON | \
-           CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
-           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-           CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
--#define CPU_FTRS_7450_21      (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_7450_21      (CPU_FTR_COMMON | \
-           CPU_FTR_USE_TB | \
-           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
-           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
-           CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
--#define CPU_FTRS_7450_23      (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_7450_23      (CPU_FTR_COMMON | \
-           CPU_FTR_USE_TB | \
-           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
-           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
--#define CPU_FTRS_7455_1       (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_7455_1       (CPU_FTR_COMMON | \
-           CPU_FTR_USE_TB | \
-           CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \
-           CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
--#define CPU_FTRS_7455_20      (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_7455_20      (CPU_FTR_COMMON | \
-           CPU_FTR_USE_TB | \
-           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
-           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
-           CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
--#define CPU_FTRS_7455 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_7455 (CPU_FTR_COMMON | \
-           CPU_FTR_USE_TB | \
-           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
-           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-           CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
--#define CPU_FTRS_7447_10      (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_7447_10      (CPU_FTR_COMMON | \
-           CPU_FTR_USE_TB | \
-           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
-           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-           CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE)
--#define CPU_FTRS_7447 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_7447 (CPU_FTR_COMMON | \
-           CPU_FTR_USE_TB | \
-           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
-           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-           CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
--#define CPU_FTRS_7447A        (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_7447A        (CPU_FTR_COMMON | \
-           CPU_FTR_USE_TB | \
-           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-           CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
--#define CPU_FTRS_7448 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_7448 (CPU_FTR_COMMON | \
-           CPU_FTR_USE_TB | \
-           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-           CPU_FTR_PPC_LE)
--#define CPU_FTRS_82XX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_82XX (CPU_FTR_COMMON | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
--#define CPU_FTRS_G2_LE        (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
-+#define CPU_FTRS_G2_LE        (CPU_FTR_MAYBE_CAN_DOZE | \
-           CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS)
--#define CPU_FTRS_E300 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
-+#define CPU_FTRS_E300 (CPU_FTR_MAYBE_CAN_DOZE | \
-           CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
-           CPU_FTR_COMMON)
--#define CPU_FTRS_E300C2       (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
-+#define CPU_FTRS_E300C2       (CPU_FTR_MAYBE_CAN_DOZE | \
-           CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
-           CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE)
--#define CPU_FTRS_CLASSIC32    (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-+#define CPU_FTRS_CLASSIC32    (CPU_FTR_COMMON | \
-           CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
--#define CPU_FTRS_8XX  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
--#define CPU_FTRS_40X  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
--          CPU_FTR_NODSISRALIGN)
--#define CPU_FTRS_44X  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
--          CPU_FTR_NODSISRALIGN)
--#define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
--#define CPU_FTRS_E500 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
--          CPU_FTR_NODSISRALIGN)
--#define CPU_FTRS_E500_2       (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-+#define CPU_FTRS_8XX  (CPU_FTR_USE_TB)
-+#define CPU_FTRS_40X  (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
-+#define CPU_FTRS_44X  (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
-+#define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
-+          CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
-+#define CPU_FTRS_E500 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
-+#define CPU_FTRS_E500_2       (CPU_FTR_USE_TB | \
-           CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN)
- #define CPU_FTRS_GENERIC_32   (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
- /* 64-bit CPUs */
--#define CPU_FTRS_POWER3       (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-+#define CPU_FTRS_POWER3       (CPU_FTR_USE_TB | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE)
--#define CPU_FTRS_RS64 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-+#define CPU_FTRS_RS64 (CPU_FTR_USE_TB | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
-           CPU_FTR_MMCRA | CPU_FTR_CTRL)
--#define CPU_FTRS_POWER4       (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-+#define CPU_FTRS_POWER4       (CPU_FTR_USE_TB | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
-           CPU_FTR_MMCRA)
--#define CPU_FTRS_PPC970       (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-+#define CPU_FTRS_PPC970       (CPU_FTR_USE_TB | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
-           CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
--#define CPU_FTRS_POWER5       (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-+#define CPU_FTRS_POWER5       (CPU_FTR_USE_TB | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
-           CPU_FTR_MMCRA | CPU_FTR_SMT | \
-           CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
-           CPU_FTR_PURR)
--#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-+#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
-           CPU_FTR_MMCRA | CPU_FTR_SMT | \
-           CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
-           CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
-           CPU_FTR_DSCR)
--#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-+#define CPU_FTRS_CELL (CPU_FTR_USE_TB | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
-           CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
-           CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG)
--#define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-+#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
-           CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
-           CPU_FTR_PURR | CPU_FTR_REAL_LE)
--#define CPU_FTRS_COMPATIBLE   (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-+#define CPU_FTRS_COMPATIBLE   (CPU_FTR_USE_TB | \
-           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
- #ifdef __powerpc64__
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/floppy.h linux-2.6.22-590/include/asm-powerpc/floppy.h
---- linux-2.6.22-570/include/asm-powerpc/floppy.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/floppy.h      2008-01-02 13:56:37.000000000 -0500
-@@ -29,7 +29,7 @@
- #define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL);
- #include <linux/pci.h>
--#include <asm/ppc-pci.h>      /* for ppc64_isabridge_dev */
-+#include <asm/ppc-pci.h>      /* for isa_bridge_pcidev */
+  * FIXME: Most of this can go away.. at the moment, we rely on
+diff -Nurb linux-2.6.22-590/drivers/spi/at25.c linux-2.6.22-570/drivers/spi/at25.c
+--- linux-2.6.22-590/drivers/spi/at25.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/spi/at25.c        2007-07-08 19:32:17.000000000 -0400
+@@ -111,8 +111,7 @@
+ }
  
- #define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io)
+ static ssize_t
+-at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+-            char *buf, loff_t off, size_t count)
++at25_bin_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct device           *dev;
+       struct at25_data        *at25;
+@@ -237,8 +236,7 @@
+ }
  
-@@ -139,12 +139,12 @@
-       if (bus_addr 
-           && (addr != prev_addr || size != prev_size || dir != prev_dir)) {
-               /* different from last time -- unmap prev */
--              pci_unmap_single(ppc64_isabridge_dev, bus_addr, prev_size, prev_dir);
-+              pci_unmap_single(isa_bridge_pcidev, bus_addr, prev_size, prev_dir);
-               bus_addr = 0;
-       }
+ static ssize_t
+-at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+-             char *buf, loff_t off, size_t count)
++at25_bin_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct device           *dev;
+       struct at25_data        *at25;
+@@ -316,6 +314,7 @@
+        */
+       at25->bin.attr.name = "eeprom";
+       at25->bin.attr.mode = S_IRUSR;
++      at25->bin.attr.owner = THIS_MODULE;
+       at25->bin.read = at25_bin_read;
  
-       if (!bus_addr)  /* need to map it */
--              bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir);
-+              bus_addr = pci_map_single(isa_bridge_pcidev, addr, size, dir);
+       at25->bin.size = at25->chip.byte_len;
+diff -Nurb linux-2.6.22-590/drivers/usb/atm/cxacru.c linux-2.6.22-570/drivers/usb/atm/cxacru.c
+--- linux-2.6.22-590/drivers/usb/atm/cxacru.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/usb/atm/cxacru.c  2007-07-08 19:32:17.000000000 -0400
+@@ -171,7 +171,7 @@
+       struct delayed_work poll_work;
+       u32 card_info[CXINF_MAX];
+       struct mutex poll_state_serialize;
+-      enum cxacru_poll_state poll_state;
++      int poll_state;
  
-       /* remember this one as prev */
-       prev_addr = addr;
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/io.h linux-2.6.22-590/include/asm-powerpc/io.h
---- linux-2.6.22-570/include/asm-powerpc/io.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/io.h  2008-01-02 13:56:37.000000000 -0500
-@@ -607,9 +607,9 @@
-  *
-  * * iounmap undoes such a mapping and can be hooked
-  *
-- * * __ioremap_explicit (and the pending __iounmap_explicit) are low level
-- *   functions to create hand-made mappings for use only by the PCI code
-- *   and cannot currently be hooked.
-+ * * __ioremap_at (and the pending __iounmap_at) are low level functions to
-+ *   create hand-made mappings for use only by the PCI code and cannot
-+ *   currently be hooked. Must be page aligned.
-  *
-  * * __ioremap is the low level implementation used by ioremap and
-  *   ioremap_flags and cannot be hooked (but can be used by a hook on one
-@@ -629,19 +629,9 @@
-                              unsigned long flags);
- extern void __iounmap(volatile void __iomem *addr);
+       /* contol handles */
+       struct mutex cm_serialize;
+@@ -226,48 +226,58 @@
  
--extern int __ioremap_explicit(phys_addr_t p_addr, unsigned long v_addr,
-+extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea,
-                             unsigned long size, unsigned long flags);
--extern int __iounmap_explicit(volatile void __iomem *start,
--                            unsigned long size);
--
--extern void __iomem * reserve_phb_iospace(unsigned long size);
--
--/* Those are more 32 bits only functions */
--extern unsigned long iopa(unsigned long addr);
--extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
--extern void io_block_mapping(unsigned long virt, phys_addr_t phys,
--                           unsigned int size, int flags);
--
-+extern void __iounmap_at(void *ea, unsigned long size);
+ static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf)
+ {
++      if (unlikely(value < 0)) {
+               return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
+-                                      value / 100, abs(value) % 100);
++                                              value / 100, -value % 100);
++      } else {
++              return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
++                                              value / 100, value % 100);
++      }
+ }
  
- /*
-  * When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation
-@@ -651,8 +641,8 @@
-  */
- #define HAVE_ARCH_PIO_SIZE            1
- #define PIO_OFFSET                    0x00000000UL
--#define PIO_MASK                      0x3fffffffUL
--#define PIO_RESERVED                  0x40000000UL
-+#define PIO_MASK                      (FULL_IO_SIZE - 1)
-+#define PIO_RESERVED                  (FULL_IO_SIZE)
+ static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
+ {
+-      static char *str[] = { "no", "yes" };
+-      if (unlikely(value >= ARRAY_SIZE(str)))
+-              return snprintf(buf, PAGE_SIZE, "%u\n", value);
+-      return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
++      switch (value) {
++      case 0: return snprintf(buf, PAGE_SIZE, "no\n");
++      case 1: return snprintf(buf, PAGE_SIZE, "yes\n");
++      default: return 0;
++      }
+ }
  
- #define mmio_read16be(addr)           readw_be(addr)
- #define mmio_read32be(addr)           readl_be(addr)
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/kgdb.h linux-2.6.22-590/include/asm-powerpc/kgdb.h
---- linux-2.6.22-570/include/asm-powerpc/kgdb.h        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-powerpc/kgdb.h        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,75 @@
-+/*
-+ * include/asm-powerpc/kgdb.h
-+ *
-+ * The PowerPC (32/64) specific defines / externs for KGDB.  Based on
-+ * the previous 32bit and 64bit specific files, which had the following
-+ * copyrights:
-+ *
-+ * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
-+ * PPC Mods (C) 2004 Tom Rini (trini@mvista.com)
-+ * PPC Mods (C) 2003 John Whitney (john.whitney@timesys.com)
-+ * PPC Mods (C) 1998 Michael Tesch (tesch@cs.wisc.edu)
-+ *
-+ *
-+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
-+ * Author: Tom Rini <trini@kernel.crashing.org>
-+ *
-+ * 2006 (c) MontaVista Software, Inc. This file is licensed under
-+ * the terms of the GNU General Public License version 2. This program
-+ * is licensed "as is" without any warranty of any kind, whether express
-+ * or implied.
-+ */
-+#ifdef __KERNEL__
-+#ifndef __POWERPC_KGDB_H__
-+#define __POWERPC_KGDB_H__
-+
-+#include <asm-generic/kgdb.h>
-+
-+#ifndef __ASSEMBLY__
-+
-+#define BREAK_INSTR_SIZE      4
-+#define BUFMAX                        ((NUMREGBYTES * 2) + 512)
-+#define OUTBUFMAX             ((NUMREGBYTES * 2) + 512)
-+#define BREAKPOINT()          asm(".long 0x7d821008"); /* twge r2, r2 */
-+#define CACHE_FLUSH_IS_SAFE   1
-+
-+/* The number bytes of registers we have to save depends on a few
-+ * things.  For 64bit we default to not including vector registers and
-+ * vector state registers. */
-+#ifdef CONFIG_PPC64
-+/*
-+ * 64 bit (8 byte) registers:
-+ *   32 gpr, 32 fpr, nip, msr, link, ctr
-+ * 32 bit (4 byte) registers:
-+ *   ccr, xer, fpscr
-+ */
-+#define NUMREGBYTES           ((68 * 8) + (3 * 4))
-+#if 0
-+/* The following adds in vector registers and vector state registers. */
-+/* 128 bit (16 byte) registers:
-+ *   32 vr
-+ * 64 bit (8 byte) registers:
-+ *   32 gpr, 32 fpr, nip, msr, link, ctr
-+ * 32 bit (4 byte) registers:
-+ *   ccr, xer, fpscr, vscr, vrsave
-+ */
-+#define NUMREGBYTES           ((128 * 16) + (68 * 8) + (5 * 4))
-+#endif
-+#define NUMCRITREGBYTES               184
-+#else /* CONFIG_PPC32 */
-+/* On non-E500 family PPC32 we determine the size by picking the last
-+ * register we need, but on E500 we skip sections so we list what we
-+ * need to store, and add it up. */
-+#ifndef CONFIG_E500
-+#define MAXREG                        (PT_FPSCR+1)
-+#else
-+/* 32 GPRs (8 bytes), nip, msr, ccr, link, ctr, xer, acc (8 bytes), spefscr*/
-+#define MAXREG                 ((32*2)+6+2+1)
-+#endif
-+#define NUMREGBYTES           (MAXREG * sizeof(int))
-+/* CR/LR, R1, R2, R13-R31 inclusive. */
-+#define NUMCRITREGBYTES               (23 * sizeof(int))
-+#endif /* 32/64 */
-+#endif /* !(__ASSEMBLY__) */
-+#endif /* !__POWERPC_KGDB_H__ */
-+#endif /* __KERNEL__ */
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/lppaca.h linux-2.6.22-590/include/asm-powerpc/lppaca.h
---- linux-2.6.22-570/include/asm-powerpc/lppaca.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/lppaca.h      2008-01-02 13:56:37.000000000 -0500
-@@ -98,7 +98,7 @@
-       u64     saved_gpr5;             // Saved GPR5                   x30-x37
+ static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf)
+ {
+-      static char *str[] = { NULL, "not connected", "connected", "lost" };
+-      if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
+-              return snprintf(buf, PAGE_SIZE, "%u\n", value);
+-      return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
++      switch (value) {
++      case 1: return snprintf(buf, PAGE_SIZE, "not connected\n");
++      case 2: return snprintf(buf, PAGE_SIZE, "connected\n");
++      case 3: return snprintf(buf, PAGE_SIZE, "lost\n");
++      default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
++      }
+ }
  
-       u8      reserved4;              // Reserved                     x38-x38
--      u8      cpuctls_task_attrs;     // Task attributes for cpuctls  x39-x39
-+      u8      donate_dedicated_cpu;   // Donate dedicated CPU cycles  x39-x39
-       u8      fpregs_in_use;          // FP regs in use               x3A-x3A
-       u8      pmcregs_in_use;         // PMC regs in use              x3B-x3B
-       volatile u32 saved_decr;        // Saved Decr Value             x3C-x3F
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/mmu-hash32.h linux-2.6.22-590/include/asm-powerpc/mmu-hash32.h
---- linux-2.6.22-570/include/asm-powerpc/mmu-hash32.h  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-powerpc/mmu-hash32.h  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,91 @@
-+#ifndef _ASM_POWERPC_MMU_HASH32_H_
-+#define _ASM_POWERPC_MMU_HASH32_H_
-+/*
-+ * 32-bit hash table MMU support
-+ */
-+
-+/*
-+ * BATs
-+ */
-+
-+/* Block size masks */
-+#define BL_128K       0x000
-+#define BL_256K 0x001
-+#define BL_512K 0x003
-+#define BL_1M   0x007
-+#define BL_2M   0x00F
-+#define BL_4M   0x01F
-+#define BL_8M   0x03F
-+#define BL_16M  0x07F
-+#define BL_32M  0x0FF
-+#define BL_64M  0x1FF
-+#define BL_128M 0x3FF
-+#define BL_256M 0x7FF
-+
-+/* BAT Access Protection */
-+#define BPP_XX        0x00            /* No access */
-+#define BPP_RX        0x01            /* Read only */
-+#define BPP_RW        0x02            /* Read/write */
-+
-+#ifndef __ASSEMBLY__
-+struct ppc_bat {
-+      struct {
-+              unsigned long bepi:15;  /* Effective page index (virtual address) */
-+              unsigned long :4;       /* Unused */
-+              unsigned long bl:11;    /* Block size mask */
-+              unsigned long vs:1;     /* Supervisor valid */
-+              unsigned long vp:1;     /* User valid */
-+      } batu;                 /* Upper register */
-+      struct {
-+              unsigned long brpn:15;  /* Real page index (physical address) */
-+              unsigned long :10;      /* Unused */
-+              unsigned long w:1;      /* Write-thru cache */
-+              unsigned long i:1;      /* Cache inhibit */
-+              unsigned long m:1;      /* Memory coherence */
-+              unsigned long g:1;      /* Guarded (MBZ in IBAT) */
-+              unsigned long :1;       /* Unused */
-+              unsigned long pp:2;     /* Page access protections */
-+      } batl;                 /* Lower register */
-+};
-+#endif /* !__ASSEMBLY__ */
-+
-+/*
-+ * Hash table
-+ */
-+
-+/* Values for PP (assumes Ks=0, Kp=1) */
-+#define PP_RWXX       0       /* Supervisor read/write, User none */
-+#define PP_RWRX 1     /* Supervisor read/write, User read */
-+#define PP_RWRW 2     /* Supervisor read/write, User read/write */
-+#define PP_RXRX 3     /* Supervisor read,       User read */
-+
-+#ifndef __ASSEMBLY__
-+
-+/* Hardware Page Table Entry */
-+struct hash_pte {
-+      unsigned long v:1;      /* Entry is valid */
-+      unsigned long vsid:24;  /* Virtual segment identifier */
-+      unsigned long h:1;      /* Hash algorithm indicator */
-+      unsigned long api:6;    /* Abbreviated page index */
-+      unsigned long rpn:20;   /* Real (physical) page number */
-+      unsigned long    :3;    /* Unused */
-+      unsigned long r:1;      /* Referenced */
-+      unsigned long c:1;      /* Changed */
-+      unsigned long w:1;      /* Write-thru cache mode */
-+      unsigned long i:1;      /* Cache inhibited */
-+      unsigned long m:1;      /* Memory coherence */
-+      unsigned long g:1;      /* Guarded */
-+      unsigned long  :1;      /* Unused */
-+      unsigned long pp:2;     /* Page protection */
-+};
-+
-+typedef struct {
-+      unsigned long id;
-+      unsigned long vdso_base;
-+} mm_context_t;
-+
-+typedef unsigned long phys_addr_t;
-+
-+#endif /* !__ASSEMBLY__ */
-+
-+#endif /* _ASM_POWERPC_MMU_HASH32_H_ */
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/mmu-hash64.h linux-2.6.22-590/include/asm-powerpc/mmu-hash64.h
---- linux-2.6.22-570/include/asm-powerpc/mmu-hash64.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/mmu-hash64.h  2008-01-02 13:56:37.000000000 -0500
-@@ -103,12 +103,12 @@
+ static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf)
+ {
+-      static char *str[] = { "down", "attempting to activate",
+-              "training", "channel analysis", "exchange", "up",
+-              "waiting", "initialising"
+-      };
+-      if (unlikely(value >= ARRAY_SIZE(str)))
+-              return snprintf(buf, PAGE_SIZE, "%u\n", value);
+-      return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
++      switch (value) {
++      case 0: return snprintf(buf, PAGE_SIZE, "down\n");
++      case 1: return snprintf(buf, PAGE_SIZE, "attempting to activate\n");
++      case 2: return snprintf(buf, PAGE_SIZE, "training\n");
++      case 3: return snprintf(buf, PAGE_SIZE, "channel analysis\n");
++      case 4: return snprintf(buf, PAGE_SIZE, "exchange\n");
++      case 5: return snprintf(buf, PAGE_SIZE, "up\n");
++      case 6: return snprintf(buf, PAGE_SIZE, "waiting\n");
++      case 7: return snprintf(buf, PAGE_SIZE, "initialising\n");
++      default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
++      }
+ }
  
- #ifndef __ASSEMBLY__
+ static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf)
+ {
+-      static char *str[] = {
+-                      NULL,
+-                      "ANSI T1.413",
+-                      "ITU-T G.992.1 (G.DMT)",
+-                      "ITU-T G.992.2 (G.LITE)"
+-      };
+-      if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
+-              return snprintf(buf, PAGE_SIZE, "%u\n", value);
+-      return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
++      switch (value) {
++      case 0: return 0;
++      case 1: return snprintf(buf, PAGE_SIZE, "ANSI T1.413\n");
++      case 2: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.1 (G.DMT)\n");
++      case 3: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.2 (G.LITE)\n");
++      default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
++      }
+ }
  
--typedef struct {
-+struct hash_pte {
-       unsigned long v;
-       unsigned long r;
--} hpte_t;
-+};
+ /*
+@@ -298,10 +308,11 @@
+       struct cxacru_data *instance = usbatm_instance->driver_data;
+       u32 value = instance->card_info[CXINF_LINE_STARTABLE];
  
--extern hpte_t *htab_address;
-+extern struct hash_pte *htab_address;
- extern unsigned long htab_size_bytes;
- extern unsigned long htab_hash_mask;
+-      static char *str[] = { "running", "stopped" };
+-      if (unlikely(value >= ARRAY_SIZE(str)))
+-              return snprintf(buf, PAGE_SIZE, "%u\n", value);
+-      return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
++      switch (value) {
++      case 0: return snprintf(buf, PAGE_SIZE, "running\n");
++      case 1: return snprintf(buf, PAGE_SIZE, "stopped\n");
++      default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
++      }
+ }
  
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/mmu.h linux-2.6.22-590/include/asm-powerpc/mmu.h
---- linux-2.6.22-570/include/asm-powerpc/mmu.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/mmu.h 2008-01-02 13:56:37.000000000 -0500
-@@ -5,6 +5,9 @@
- #ifdef CONFIG_PPC64
- /* 64-bit classic hash table MMU */
- #  include <asm/mmu-hash64.h>
-+#elif defined(CONFIG_PPC_STD_MMU)
-+/* 32-bit classic hash table MMU */
-+#  include <asm/mmu-hash32.h>
- #elif defined(CONFIG_44x)
- /* 44x-style software loaded TLB */
- #  include <asm/mmu-44x.h>
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/pci-bridge.h linux-2.6.22-590/include/asm-powerpc/pci-bridge.h
---- linux-2.6.22-570/include/asm-powerpc/pci-bridge.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/pci-bridge.h  2008-01-02 13:56:37.000000000 -0500
-@@ -31,6 +31,7 @@
-       int last_busno;
+ static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
+diff -Nurb linux-2.6.22-590/drivers/usb/atm/ueagle-atm.c linux-2.6.22-570/drivers/usb/atm/ueagle-atm.c
+--- linux-2.6.22-590/drivers/usb/atm/ueagle-atm.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/usb/atm/ueagle-atm.c      2007-07-08 19:32:17.000000000 -0400
+@@ -1168,7 +1168,6 @@
+       struct uea_softc *sc = data;
+       int ret = -EAGAIN;
  
-       void __iomem *io_base_virt;
-+      void *io_base_alloc;
-       resource_size_t io_base_phys;
+-      set_freezable();
+       uea_enters(INS_TO_USBDEV(sc));
+       while (!kthread_should_stop()) {
+               if (ret < 0 || sc->reset)
+diff -Nurb linux-2.6.22-590/drivers/usb/core/config.c linux-2.6.22-570/drivers/usb/core/config.c
+--- linux-2.6.22-590/drivers/usb/core/config.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/usb/core/config.c 2007-07-08 19:32:17.000000000 -0400
+@@ -274,7 +274,6 @@
+       struct usb_descriptor_header *header;
+       int len, retval;
+       u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
+-      unsigned iad_num = 0;
  
-       /* Some machines have a non 1:1 mapping of
-@@ -70,19 +71,22 @@
-       int     devfn;                  /* pci device and function number */
-       int     class_code;             /* pci device class */
+       memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
+       if (config->desc.bDescriptorType != USB_DT_CONFIG ||
+@@ -352,20 +351,6 @@
+                               ++n;
+                       }
  
--#ifdef CONFIG_PPC_PSERIES
-+      struct  pci_controller *phb;    /* for pci devices */
-+      struct  iommu_table *iommu_table;       /* for phb's or bridges */
-+      struct  pci_dev *pcidev;        /* back-pointer to the pci device */
-+      struct  device_node *node;      /* back-pointer to the device_node */
-+
-+      int     pci_ext_config_space;   /* for pci devices */
-+
-+#ifdef CONFIG_EEH
-       int     eeh_mode;               /* See eeh.h for possible EEH_MODEs */
-       int     eeh_config_addr;
-       int     eeh_pe_config_addr; /* new-style partition endpoint address */
-       int     eeh_check_count;        /* # times driver ignored error */
-       int     eeh_freeze_count;       /* # times this device froze up. */
--#endif
--      int     pci_ext_config_space;   /* for pci devices */
--      struct  pci_controller *phb;    /* for pci devices */
--      struct  iommu_table *iommu_table;       /* for phb's or bridges */
--      struct  pci_dev *pcidev;        /* back-pointer to the pci device */
--      struct  device_node *node;      /* back-pointer to the device_node */
-+      int     eeh_false_positives;    /* # times this device reported #ff's */
-       u32     config_space[16];       /* saved PCI config space */
-+#endif
+-              } else if (header->bDescriptorType ==
+-                              USB_DT_INTERFACE_ASSOCIATION) {
+-                      if (iad_num == USB_MAXIADS) {
+-                              dev_warn(ddev, "found more Interface "
+-                                             "Association Descriptors "
+-                                             "than allocated for in "
+-                                             "configuration %d\n", cfgno);
+-                      } else {
+-                              config->intf_assoc[iad_num] =
+-                                      (struct usb_interface_assoc_descriptor
+-                                      *)header;
+-                              iad_num++;
+-                      }
+-
+               } else if (header->bDescriptorType == USB_DT_DEVICE ||
+                           header->bDescriptorType == USB_DT_CONFIG)
+                       dev_warn(ddev, "config %d contains an unexpected "
+diff -Nurb linux-2.6.22-590/drivers/usb/core/devices.c linux-2.6.22-570/drivers/usb/core/devices.c
+--- linux-2.6.22-590/drivers/usb/core/devices.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/usb/core/devices.c        2007-07-08 19:32:17.000000000 -0400
+@@ -102,10 +102,6 @@
+ /* C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
+   "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
+   
+-static const char *format_iad =
+-/* A:  FirstIf#=dd IfCount=dd Cls=xx(sssss) Sub=xx Prot=xx */
+-  "A:  FirstIf#=%2d IfCount=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n";
+-
+ static const char *format_iface =
+ /* I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
+   "I:%c If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
+@@ -150,7 +146,6 @@
+       {USB_CLASS_STILL_IMAGE,         "still"},
+       {USB_CLASS_CSCID,               "scard"},
+       {USB_CLASS_CONTENT_SEC,         "c-sec"},
+-      {USB_CLASS_VIDEO,               "video"},
+       {-1,                            "unk."}         /* leave as last */
  };
  
- /* Get the pointer to a device_node's pci_dn */
-@@ -164,6 +168,11 @@
- }
- #endif
-+extern void isa_bridge_find_early(struct pci_controller *hose);
-+
-+extern int pcibios_unmap_io_space(struct pci_bus *bus);
-+extern int pcibios_map_io_space(struct pci_bus *bus);
-+
- /* Return values for ppc_md.pci_probe_mode function */
- #define PCI_PROBE_NONE                -1      /* Don't look at this bus at all */
- #define PCI_PROBE_NORMAL      0       /* Do normal PCI probing */
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/pci.h linux-2.6.22-590/include/asm-powerpc/pci.h
---- linux-2.6.22-570/include/asm-powerpc/pci.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/pci.h 2008-01-02 13:56:37.000000000 -0500
-@@ -220,10 +220,6 @@
-       return root;
+@@ -291,21 +286,6 @@
+       return start;
  }
  
--extern int unmap_bus_range(struct pci_bus *bus);
--
--extern int remap_bus_range(struct pci_bus *bus);
+-static char *usb_dump_iad_descriptor(char *start, char *end,
+-      const struct usb_interface_assoc_descriptor *iad)
+-{
+-      if (start > end)
+-              return start;
+-      start += sprintf(start, format_iad,
+-                       iad->bFirstInterface,
+-                       iad->bInterfaceCount,
+-                       iad->bFunctionClass,
+-                       class_decode(iad->bFunctionClass),
+-                       iad->bFunctionSubClass,
+-                       iad->bFunctionProtocol);
+-      return start;
+-}
 -
- extern void pcibios_fixup_device_resources(struct pci_dev *dev,
-                       struct pci_bus *bus);
+ /* TBD:
+  * 0. TBDs
+  * 1. marking active interface altsettings (code lists all, but should mark
+@@ -342,12 +322,6 @@
+       if (!config)            /* getting these some in 2.3.7; none in 2.3.6 */
+               return start + sprintf(start, "(null Cfg. desc.)\n");
+       start = usb_dump_config_descriptor(start, end, &config->desc, active);
+-      for (i = 0; i < USB_MAXIADS; i++) {
+-              if (config->intf_assoc[i] == NULL)
+-                      break;
+-              start = usb_dump_iad_descriptor(start, end,
+-                                      config->intf_assoc[i]);
+-      }
+       for (i = 0; i < config->desc.bNumInterfaces; i++) {
+               intfc = config->intf_cache[i];
+               interface = config->interface[i];
+diff -Nurb linux-2.6.22-590/drivers/usb/core/hub.c linux-2.6.22-570/drivers/usb/core/hub.c
+--- linux-2.6.22-590/drivers/usb/core/hub.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/usb/core/hub.c    2008-01-23 19:15:55.000000000 -0500
+@@ -2831,7 +2831,6 @@
  
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/pgtable-ppc32.h linux-2.6.22-590/include/asm-powerpc/pgtable-ppc32.h
---- linux-2.6.22-570/include/asm-powerpc/pgtable-ppc32.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/pgtable-ppc32.h       2008-01-02 13:56:37.000000000 -0500
-@@ -6,11 +6,7 @@
- #ifndef __ASSEMBLY__
- #include <linux/sched.h>
- #include <linux/threads.h>
--#include <asm/processor.h>            /* For TASK_SIZE */
--#include <asm/mmu.h>
--#include <asm/page.h>
- #include <asm/io.h>                   /* For sub-arch specific PPC_PIN_SIZE */
--struct mm_struct;
+ static int hub_thread(void *__unused)
+ {
+-      set_freezable();
+       do {
+               hub_events();
+               wait_event_interruptible(khubd_wait,
+diff -Nurb linux-2.6.22-590/drivers/usb/core/message.c linux-2.6.22-570/drivers/usb/core/message.c
+--- linux-2.6.22-590/drivers/usb/core/message.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/usb/core/message.c        2008-01-23 19:15:55.000000000 -0500
+@@ -1409,36 +1409,6 @@
+       .uevent =       usb_if_uevent,
+ };
  
- extern unsigned long va_to_phys(unsigned long address);
- extern pte_t *va_to_pte(unsigned long address);
-@@ -488,14 +484,6 @@
- #define pfn_pte(pfn, prot)    __pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) |\
-                                       pgprot_val(prot))
- #define mk_pte(page, prot)    pfn_pte(page_to_pfn(page), prot)
+-static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
+-                                                     struct usb_host_config *config,
+-                                                     u8 inum)
+-{
+-      struct usb_interface_assoc_descriptor *retval = NULL;
+-      struct usb_interface_assoc_descriptor *intf_assoc;
+-      int first_intf;
+-      int last_intf;
+-      int i;
 -
--/*
-- * ZERO_PAGE is a global shared page that is always zero: used
-- * for zero-mapped memory areas etc..
-- */
--extern unsigned long empty_zero_page[1024];
--#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+-      for (i = 0; (i < USB_MAXIADS && config->intf_assoc[i]); i++) {
+-              intf_assoc = config->intf_assoc[i];
+-              if (intf_assoc->bInterfaceCount == 0)
+-                      continue;
 -
- #endif /* __ASSEMBLY__ */
- #define pte_none(pte)         ((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
-@@ -734,10 +722,6 @@
- #define pte_unmap(pte)                kunmap_atomic(pte, KM_PTE0)
- #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
--extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+-              first_intf = intf_assoc->bFirstInterface;
+-              last_intf = first_intf + (intf_assoc->bInterfaceCount - 1);
+-              if (inum >= first_intf && inum <= last_intf) {
+-                      if (!retval)
+-                              retval = intf_assoc;
+-                      else
+-                              dev_err(&dev->dev, "Interface #%d referenced"
+-                                      " by multiple IADs\n", inum);
+-              }
+-      }
+-
+-      return retval;
+-}
 -
--extern void paging_init(void);
 -
  /*
-  * Encode and decode a swap entry.
-  * Note that the bits we use in a PTE for representing a swap entry
-@@ -755,40 +739,6 @@
- #define pte_to_pgoff(pte)     (pte_val(pte) >> 3)
- #define pgoff_to_pte(off)     ((pte_t) { ((off) << 3) | _PAGE_FILE })
+  * usb_set_configuration - Makes a particular device setting be current
+  * @dev: the device whose configuration is being updated
+@@ -1585,7 +1555,6 @@
+               intfc = cp->intf_cache[i];
+               intf->altsetting = intfc->altsetting;
+               intf->num_altsetting = intfc->num_altsetting;
+-              intf->intf_assoc = find_iad(dev, cp, i);
+               kref_get(&intfc->ref);
+               alt = usb_altnum_to_altsetting(intf, 0);
+diff -Nurb linux-2.6.22-590/drivers/usb/core/sysfs.c linux-2.6.22-570/drivers/usb/core/sysfs.c
+--- linux-2.6.22-590/drivers/usb/core/sysfs.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/usb/core/sysfs.c  2007-07-08 19:32:17.000000000 -0400
+@@ -424,25 +424,6 @@
+       sysfs_remove_group(&dev->kobj, &dev_attr_grp);
+ }
  
--/* CONFIG_APUS */
--/* For virtual address to physical address conversion */
--extern void cache_clear(__u32 addr, int length);
--extern void cache_push(__u32 addr, int length);
--extern int mm_end_of_chunk (unsigned long addr, int len);
--extern unsigned long iopa(unsigned long addr);
--extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
--
--/* Values for nocacheflag and cmode */
--/* These are not used by the APUS kernel_map, but prevents
--   compilation errors. */
--#define       KERNELMAP_FULL_CACHING          0
--#define       KERNELMAP_NOCACHE_SER           1
--#define       KERNELMAP_NOCACHE_NONSER        2
--#define       KERNELMAP_NO_COPYBACK           3
+-/* Interface Accociation Descriptor fields */
+-#define usb_intf_assoc_attr(field, format_string)                     \
+-static ssize_t                                                                \
+-show_iad_##field (struct device *dev, struct device_attribute *attr,  \
+-              char *buf)                                              \
+-{                                                                     \
+-      struct usb_interface *intf = to_usb_interface (dev);            \
+-                                                                      \
+-      return sprintf (buf, format_string,                             \
+-                      intf->intf_assoc->field);               \
+-}                                                                     \
+-static DEVICE_ATTR(iad_##field, S_IRUGO, show_iad_##field, NULL);
 -
--/*
-- * Map some physical address range into the kernel address space.
-- */
--extern unsigned long kernel_map(unsigned long paddr, unsigned long size,
--                              int nocacheflag, unsigned long *memavailp );
+-usb_intf_assoc_attr (bFirstInterface, "%02x\n")
+-usb_intf_assoc_attr (bInterfaceCount, "%02d\n")
+-usb_intf_assoc_attr (bFunctionClass, "%02x\n")
+-usb_intf_assoc_attr (bFunctionSubClass, "%02x\n")
+-usb_intf_assoc_attr (bFunctionProtocol, "%02x\n")
 -
--/*
-- * Set cache mode of (kernel space) address range.
-- */
--extern void kernel_set_cachemode (unsigned long address, unsigned long size,
--                                 unsigned int cmode);
+ /* Interface fields */
+ #define usb_intf_attr(field, format_string)                           \
+ static ssize_t                                                                \
+@@ -506,18 +487,6 @@
+ }
+ static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
+-static struct attribute *intf_assoc_attrs[] = {
+-      &dev_attr_iad_bFirstInterface.attr,
+-      &dev_attr_iad_bInterfaceCount.attr,
+-      &dev_attr_iad_bFunctionClass.attr,
+-      &dev_attr_iad_bFunctionSubClass.attr,
+-      &dev_attr_iad_bFunctionProtocol.attr,
+-      NULL,
+-};
+-static struct attribute_group intf_assoc_attr_grp = {
+-      .attrs = intf_assoc_attrs,
+-};
 -
--/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
--#define kern_addr_valid(addr) (1)
+ static struct attribute *intf_attrs[] = {
+       &dev_attr_bInterfaceNumber.attr,
+       &dev_attr_bAlternateSetting.attr,
+@@ -569,8 +538,6 @@
+               alt->string = usb_cache_string(udev, alt->desc.iInterface);
+       if (alt->string)
+               retval = device_create_file(dev, &dev_attr_interface);
+-      if (intf->intf_assoc)
+-              retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp);
+       usb_create_intf_ep_files(intf, udev);
+       return 0;
+ }
+@@ -582,5 +549,4 @@
+       usb_remove_intf_ep_files(intf);
+       device_remove_file(dev, &dev_attr_interface);
+       sysfs_remove_group(&dev->kobj, &intf_attr_grp);
+-      sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp);
+ }
+diff -Nurb linux-2.6.22-590/drivers/usb/gadget/file_storage.c linux-2.6.22-570/drivers/usb/gadget/file_storage.c
+--- linux-2.6.22-590/drivers/usb/gadget/file_storage.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/usb/gadget/file_storage.c 2007-07-08 19:32:17.000000000 -0400
+@@ -3434,9 +3434,6 @@
+       allow_signal(SIGKILL);
+       allow_signal(SIGUSR1);
+-      /* Allow the thread to be frozen */
+-      set_freezable();
 -
--#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)               \
--              remap_pfn_range(vma, vaddr, pfn, size, prot)
+       /* Arrange for userspace references to be interpreted as kernel
+        * pointers.  That way we can pass a kernel pointer to a routine
+        * that expects a __user pointer and it will work okay. */
+diff -Nurb linux-2.6.22-590/drivers/usb/storage/usb.c linux-2.6.22-570/drivers/usb/storage/usb.c
+--- linux-2.6.22-590/drivers/usb/storage/usb.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/usb/storage/usb.c 2007-07-08 19:32:17.000000000 -0400
+@@ -301,6 +301,8 @@
+       struct us_data *us = (struct us_data *)__us;
+       struct Scsi_Host *host = us_to_host(us);
++      current->flags |= PF_NOFREEZE;
++
+       for(;;) {
+               US_DEBUGP("*** thread sleeping.\n");
+               if(down_interruptible(&us->sema))
+@@ -907,7 +909,6 @@
+       printk(KERN_DEBUG
+               "usb-storage: device found at %d\n", us->pusb_dev->devnum);
+-      set_freezable();
+       /* Wait for the timeout to expire or for a disconnect */
+       if (delay_use > 0) {
+               printk(KERN_DEBUG "usb-storage: waiting for device "
+diff -Nurb linux-2.6.22-590/drivers/video/Kconfig linux-2.6.22-570/drivers/video/Kconfig
+--- linux-2.6.22-590/drivers/video/Kconfig     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/video/Kconfig     2007-07-08 19:32:17.000000000 -0400
+@@ -12,13 +12,6 @@
+        tristate
+        default n
+-config VIDEO_OUTPUT_CONTROL
+-      tristate "Lowlevel video output switch controls"
+-      default m
+-      help
+-        This framework adds support for low-level control of the video 
+-        output switch.
 -
- /*
-  * No page table caches to initialise
-  */
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/pgtable-ppc64.h linux-2.6.22-590/include/asm-powerpc/pgtable-ppc64.h
---- linux-2.6.22-570/include/asm-powerpc/pgtable-ppc64.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/pgtable-ppc64.h       2008-01-02 13:56:37.000000000 -0500
-@@ -7,11 +7,7 @@
+ config FB
+       tristate "Support for frame buffer devices"
+       ---help---
+diff -Nurb linux-2.6.22-590/drivers/video/Makefile linux-2.6.22-570/drivers/video/Makefile
+--- linux-2.6.22-590/drivers/video/Makefile    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/video/Makefile    2007-07-08 19:32:17.000000000 -0400
+@@ -122,6 +122,3 @@
  
- #ifndef __ASSEMBLY__
- #include <linux/stddef.h>
--#include <asm/processor.h>            /* For TASK_SIZE */
--#include <asm/mmu.h>
--#include <asm/page.h>
- #include <asm/tlbflush.h>
--struct mm_struct;
- #endif /* __ASSEMBLY__ */
+ # the test framebuffer is last
+ obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
+-
+-#video output switch sysfs driver
+-obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
+diff -Nurb linux-2.6.22-590/drivers/video/aty/radeon_base.c linux-2.6.22-570/drivers/video/aty/radeon_base.c
+--- linux-2.6.22-590/drivers/video/aty/radeon_base.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/video/aty/radeon_base.c   2007-07-08 19:32:17.000000000 -0400
+@@ -2102,9 +2102,7 @@
+ }
  
- #ifdef CONFIG_PPC_64K_PAGES
-@@ -27,7 +23,7 @@
-  */
- #define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
-                           PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
--#define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE)
-+#define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE)
  
- #if TASK_SIZE_USER64 > PGTABLE_RANGE
- #error TASK_SIZE_USER64 exceeds pagetable range
-@@ -37,19 +33,28 @@
- #error TASK_SIZE_USER64 exceeds user VSID range
- #endif
+-static ssize_t radeon_show_edid1(struct kobject *kobj,
+-                               struct bin_attribute *bin_attr,
+-                               char *buf, loff_t off, size_t count)
++static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct pci_dev *pdev = to_pci_dev(dev);
+@@ -2115,9 +2113,7 @@
+ }
  
-+
- /*
-  * Define the address range of the vmalloc VM area.
-  */
- #define VMALLOC_START ASM_CONST(0xD000000000000000)
--#define VMALLOC_SIZE  ASM_CONST(0x80000000000)
-+#define VMALLOC_SIZE  (PGTABLE_RANGE >> 1)
- #define VMALLOC_END   (VMALLOC_START + VMALLOC_SIZE)
  
- /*
-- * Define the address range of the imalloc VM area.
-- */
--#define PHBS_IO_BASE  VMALLOC_END
--#define IMALLOC_BASE  (PHBS_IO_BASE + 0x80000000ul)   /* Reserve 2 gigs for PHBs */
--#define IMALLOC_END   (VMALLOC_START + PGTABLE_RANGE)
-+ * Define the address ranges for MMIO and IO space :
-+ *
-+ *  ISA_IO_BASE = VMALLOC_END, 64K reserved area
-+ *  PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces
-+ * IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE
-+ */
-+#define FULL_IO_SIZE  0x80000000ul
-+#define  ISA_IO_BASE  (VMALLOC_END)
-+#define  ISA_IO_END   (VMALLOC_END + 0x10000ul)
-+#define  PHB_IO_BASE  (ISA_IO_END)
-+#define  PHB_IO_END   (VMALLOC_END + FULL_IO_SIZE)
-+#define IOREMAP_BASE  (PHB_IO_END)
-+#define IOREMAP_END   (VMALLOC_START + PGTABLE_RANGE)
+-static ssize_t radeon_show_edid2(struct kobject *kobj,
+-                               struct bin_attribute *bin_attr,
+-                               char *buf, loff_t off, size_t count)
++static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct pci_dev *pdev = to_pci_dev(dev);
+@@ -2130,6 +2126,7 @@
+ static struct bin_attribute edid1_attr = {
+       .attr   = {
+               .name   = "edid1",
++              .owner  = THIS_MODULE,
+               .mode   = 0444,
+       },
+       .size   = EDID_LENGTH,
+@@ -2139,6 +2136,7 @@
+ static struct bin_attribute edid2_attr = {
+       .attr   = {
+               .name   = "edid2",
++              .owner  = THIS_MODULE,
+               .mode   = 0444,
+       },
+       .size   = EDID_LENGTH,
+diff -Nurb linux-2.6.22-590/drivers/video/backlight/backlight.c linux-2.6.22-570/drivers/video/backlight/backlight.c
+--- linux-2.6.22-590/drivers/video/backlight/backlight.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/video/backlight/backlight.c       2007-07-08 19:32:17.000000000 -0400
+@@ -172,7 +172,7 @@
  
- /*
-  * Region IDs
-@@ -134,16 +139,6 @@
- #define __S110        PAGE_SHARED_X
- #define __S111        PAGE_SHARED_X
+ #define DECLARE_ATTR(_name,_mode,_show,_store)                        \
+ {                                                             \
+-      .attr   = { .name = __stringify(_name), .mode = _mode }, \
++      .attr   = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },  \
+       .show   = _show,                                        \
+       .store  = _store,                                       \
+ }
+diff -Nurb linux-2.6.22-590/drivers/video/backlight/lcd.c linux-2.6.22-570/drivers/video/backlight/lcd.c
+--- linux-2.6.22-590/drivers/video/backlight/lcd.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/video/backlight/lcd.c     2007-07-08 19:32:17.000000000 -0400
+@@ -157,7 +157,7 @@
  
--#ifndef __ASSEMBLY__
--
--/*
-- * ZERO_PAGE is a global shared page that is always zero: used
-- * for zero-mapped memory areas etc..
-- */
--extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
--#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
--#endif /* __ASSEMBLY__ */
--
- #ifdef CONFIG_HUGETLB_PAGE
+ #define DECLARE_ATTR(_name,_mode,_show,_store)                        \
+ {                                                             \
+-      .attr   = { .name = __stringify(_name), .mode = _mode }, \
++      .attr   = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },  \
+       .show   = _show,                                        \
+       .store  = _store,                                       \
+ }
+diff -Nurb linux-2.6.22-590/drivers/video/ps3fb.c linux-2.6.22-570/drivers/video/ps3fb.c
+--- linux-2.6.22-590/drivers/video/ps3fb.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/video/ps3fb.c     2007-07-08 19:32:17.000000000 -0400
+@@ -812,7 +812,6 @@
  
- #define HAVE_ARCH_UNMAPPED_AREA
-@@ -442,10 +437,6 @@
- #define pgd_ERROR(e) \
-       printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+ static int ps3fbd(void *arg)
+ {
+-      set_freezable();
+       while (!kthread_should_stop()) {
+               try_to_freeze();
+               set_current_state(TASK_INTERRUPTIBLE);
+diff -Nurb linux-2.6.22-590/drivers/w1/slaves/w1_ds2433.c linux-2.6.22-570/drivers/w1/slaves/w1_ds2433.c
+--- linux-2.6.22-590/drivers/w1/slaves/w1_ds2433.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/w1/slaves/w1_ds2433.c     2007-07-08 19:32:17.000000000 -0400
+@@ -91,9 +91,8 @@
+ }
+ #endif        /* CONFIG_W1_SLAVE_DS2433_CRC */
  
--extern pgd_t swapper_pg_dir[];
--
--extern void paging_init(void);
--
- /* Encode and de-code a swap entry */
- #define __swp_type(entry)     (((entry).val >> 1) & 0x3f)
- #define __swp_offset(entry)   ((entry).val >> 8)
-@@ -456,17 +447,6 @@
- #define pgoff_to_pte(off)     ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE})
- #define PTE_FILE_MAX_BITS     (BITS_PER_LONG - PTE_RPN_SHIFT)
+-static ssize_t w1_f23_read_bin(struct kobject *kobj,
+-                             struct bin_attribute *bin_attr,
+-                             char *buf, loff_t off, size_t count)
++static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
++                             size_t count)
+ {
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ #ifdef CONFIG_W1_SLAVE_DS2433_CRC
+@@ -200,9 +199,8 @@
+       return 0;
+ }
  
--/*
-- * kern_addr_valid is intended to indicate whether an address is a valid
-- * kernel address.  Most 32-bit archs define it as always true (like this)
-- * but most 64-bit archs actually perform a test.  What should we do here?
-- * The only use is in fs/ncpfs/dir.c
-- */
--#define kern_addr_valid(addr) (1)
--
--#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)               \
--              remap_pfn_range(vma, vaddr, pfn, size, prot)
--
- void pgtable_cache_init(void);
+-static ssize_t w1_f23_write_bin(struct kobject *kobj,
+-                              struct bin_attribute *bin_attr,
+-                              char *buf, loff_t off, size_t count)
++static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
++                              size_t count)
+ {
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+       int addr, len, idx;
+@@ -254,6 +252,7 @@
+       .attr = {
+               .name = "eeprom",
+               .mode = S_IRUGO | S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = W1_EEPROM_SIZE,
+       .read = w1_f23_read_bin,
+diff -Nurb linux-2.6.22-590/drivers/w1/slaves/w1_therm.c linux-2.6.22-570/drivers/w1/slaves/w1_therm.c
+--- linux-2.6.22-590/drivers/w1/slaves/w1_therm.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/w1/slaves/w1_therm.c      2007-07-08 19:32:17.000000000 -0400
+@@ -42,13 +42,13 @@
+                               {}
+                       };
  
- /*
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/pgtable.h linux-2.6.22-590/include/asm-powerpc/pgtable.h
---- linux-2.6.22-570/include/asm-powerpc/pgtable.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/pgtable.h     2008-01-02 13:56:37.000000000 -0500
-@@ -2,6 +2,13 @@
- #define _ASM_POWERPC_PGTABLE_H
- #ifdef __KERNEL__
+-static ssize_t w1_therm_read_bin(struct kobject *, struct bin_attribute *,
+-                               char *, loff_t, size_t);
++static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
  
-+#ifndef __ASSEMBLY__
-+#include <asm/processor.h>            /* For TASK_SIZE */
-+#include <asm/mmu.h>
-+#include <asm/page.h>
-+struct mm_struct;
-+#endif /* !__ASSEMBLY__ */
-+
- #if defined(CONFIG_PPC64)
- #  include <asm/pgtable-ppc64.h>
- #else
-@@ -9,6 +16,27 @@
- #endif
+ static struct bin_attribute w1_therm_bin_attr = {
+       .attr = {
+               .name = "w1_slave",
+               .mode = S_IRUGO,
++              .owner = THIS_MODULE,
+       },
+       .size = W1_SLAVE_DATA_SIZE,
+       .read = w1_therm_read_bin,
+@@ -159,9 +159,7 @@
+       return 0;
+ }
  
- #ifndef __ASSEMBLY__
-+/*
-+ * ZERO_PAGE is a global shared page that is always zero: used
-+ * for zero-mapped memory areas etc..
-+ */
-+extern unsigned long empty_zero_page[];
-+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-+
-+extern pgd_t swapper_pg_dir[];
-+
-+extern void paging_init(void);
-+
-+/*
-+ * kern_addr_valid is intended to indicate whether an address is a valid
-+ * kernel address.  Most 32-bit archs define it as always true (like this)
-+ * but most 64-bit archs actually perform a test.  What should we do here?
-+ */
-+#define kern_addr_valid(addr) (1)
-+
-+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)               \
-+              remap_pfn_range(vma, vaddr, pfn, size, prot)
-+
- #include <asm-generic/pgtable.h>
- #endif /* __ASSEMBLY__ */
+-static ssize_t w1_therm_read_bin(struct kobject *kobj,
+-                               struct bin_attribute *bin_attr,
+-                               char *buf, loff_t off, size_t count)
++static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+       struct w1_master *dev = sl->master;
+diff -Nurb linux-2.6.22-590/drivers/w1/w1.c linux-2.6.22-570/drivers/w1/w1.c
+--- linux-2.6.22-590/drivers/w1/w1.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/w1/w1.c   2007-07-08 19:32:17.000000000 -0400
+@@ -105,9 +105,7 @@
+       return sprintf(buf, "%s\n", sl->name);
+ }
+-static ssize_t w1_slave_read_id(struct kobject *kobj,
+-                              struct bin_attribute *bin_attr,
+-                              char *buf, loff_t off, size_t count)
++static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+@@ -130,6 +128,7 @@
+       .attr = {
+               .name = "id",
+               .mode = S_IRUGO,
++              .owner = THIS_MODULE,
+       },
+       .size = 8,
+       .read = w1_slave_read_id,
+@@ -137,9 +136,7 @@
  
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/ppc-pci.h linux-2.6.22-590/include/asm-powerpc/ppc-pci.h
---- linux-2.6.22-570/include/asm-powerpc/ppc-pci.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/ppc-pci.h     2008-01-02 13:56:37.000000000 -0500
-@@ -26,7 +26,7 @@
+ /* Default family */
  
- extern void find_and_init_phbs(void);
+-static ssize_t w1_default_write(struct kobject *kobj,
+-                              struct bin_attribute *bin_attr,
+-                              char *buf, loff_t off, size_t count)
++static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
  
--extern struct pci_dev *ppc64_isabridge_dev;   /* may be NULL if no ISA bus */
-+extern struct pci_dev *isa_bridge_pcidev;     /* may be NULL if no ISA bus */
+@@ -156,9 +153,7 @@
+       return count;
+ }
  
- /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */
- #define BUID_HI(buid) ((buid) >> 32)
-@@ -47,8 +47,8 @@
- extern unsigned long get_phb_buid (struct device_node *);
- extern int rtas_setup_phb(struct pci_controller *phb);
+-static ssize_t w1_default_read(struct kobject *kobj,
+-                             struct bin_attribute *bin_attr,
+-                             char *buf, loff_t off, size_t count)
++static ssize_t w1_default_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+ {
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
  
--/* From pSeries_pci.h */
--extern void pSeries_final_fixup(void);
-+/* From iSeries PCI */
-+extern void iSeries_pcibios_init(void);
+@@ -172,6 +167,7 @@
+       .attr = {
+               .name = "rw",
+               .mode = S_IRUGO | S_IWUSR,
++              .owner = THIS_MODULE,
+       },
+       .size = PAGE_SIZE,
+       .read = w1_default_read,
+@@ -805,7 +801,6 @@
+       struct w1_master *dev, *n;
+       int have_to_wait = 0;
  
- extern unsigned long pci_probe_only;
+-      set_freezable();
+       while (!kthread_should_stop() || have_to_wait) {
+               have_to_wait = 0;
  
-@@ -139,6 +139,9 @@
-  */
- struct device_node * find_device_pe(struct device_node *dn);
+diff -Nurb linux-2.6.22-590/drivers/zorro/zorro-sysfs.c linux-2.6.22-570/drivers/zorro/zorro-sysfs.c
+--- linux-2.6.22-590/drivers/zorro/zorro-sysfs.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/drivers/zorro/zorro-sysfs.c       2007-07-08 19:32:17.000000000 -0400
+@@ -49,9 +49,8 @@
  
-+void eeh_sysfs_add_device(struct pci_dev *pdev);
-+void eeh_sysfs_remove_device(struct pci_dev *pdev);
-+
- #endif /* CONFIG_EEH */
+ static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL);
  
- #else /* CONFIG_PCI */
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/ptrace.h linux-2.6.22-590/include/asm-powerpc/ptrace.h
---- linux-2.6.22-570/include/asm-powerpc/ptrace.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/ptrace.h      2008-01-02 13:56:37.000000000 -0500
-@@ -92,6 +92,11 @@
-               set_thread_flag(TIF_NOERROR); \
-       } while(0)
+-static ssize_t zorro_read_config(struct kobject *kobj,
+-                               struct bin_attribute *bin_attr,
+-                               char *buf, loff_t off, size_t count)
++static ssize_t zorro_read_config(struct kobject *kobj, char *buf, loff_t off,
++                               size_t count)
+ {
+       struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device,
+                                          kobj));
+@@ -79,6 +78,7 @@
+       .attr = {
+               .name = "config",
+               .mode = S_IRUGO | S_IWUSR,
++              .owner = THIS_MODULE
+       },
+       .size = sizeof(struct ConfigDev),
+       .read = zorro_read_config,
+diff -Nurb linux-2.6.22-590/ed linux-2.6.22-570/ed
+--- linux-2.6.22-590/ed        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/ed        1969-12-31 19:00:00.000000000 -0500
+@@ -1,6 +0,0 @@
+-vi -o ./fs/proc/proc_misc.c ./fs/proc/proc_misc.c.rej
+-vi -o ./fs/proc/array.c ./fs/proc/array.c.rej
+-vi -o ./include/linux/sched.h ./include/linux/sched.h.rej
+-vi -o ./kernel/time/timekeeping.c ./kernel/time/timekeeping.c.rej
+-vi -o ./kernel/timer.c ./kernel/timer.c.rej
+-vi -o ./kernel/fork.c ./kernel/fork.c.rej
+diff -Nurb linux-2.6.22-590/edit linux-2.6.22-570/edit
+--- linux-2.6.22-590/edit      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/edit      1969-12-31 19:00:00.000000000 -0500
+@@ -1,19 +0,0 @@
+-vi -o ./fs/proc/root.c ./fs/proc/root.c.rej
+-vi -o ./include/linux/nsproxy.h ./include/linux/nsproxy.h.rej
+-vi -o ./include/linux/sched.h ./include/linux/sched.h.rej
+-vi -o ./include/net/inet_timewait_sock.h ./include/net/inet_timewait_sock.h.rej
+-vi -o ./include/net/route.h ./include/net/route.h.rej
+-vi -o ./include/net/sock.h ./include/net/sock.h.rej
+-vi -o ./kernel/nsproxy.c ./kernel/nsproxy.c.rej
+-vi -o ./lib/Makefile ./lib/Makefile.rej
+-vi -o ./net/core/dev.c ./net/core/dev.c.rej
+-vi -o ./net/core/rtnetlink.c ./net/core/rtnetlink.c.rej
+-vi -o ./net/core/sock.c ./net/core/sock.c.rej
+-vi -o ./net/ipv4/af_inet.c ./net/ipv4/af_inet.c.rej
+-vi -o ./net/ipv4/inet_connection_sock.c ./net/ipv4/inet_connection_sock.c.rej
+-vi -o ./net/ipv4/inet_hashtables.c ./net/ipv4/inet_hashtables.c.rej
+-vi -o ./net/ipv4/raw.c ./net/ipv4/raw.c.rej
+-vi -o ./net/ipv4/tcp_ipv4.c ./net/ipv4/tcp_ipv4.c.rej
+-vi -o ./net/ipv4/udp.c ./net/ipv4/udp.c.rej
+-vi -o ./net/ipv6/addrconf.c ./net/ipv6/addrconf.c.rej
+-vi -o ./net/unix/af_unix.c ./net/unix/af_unix.c.rej
+diff -Nurb linux-2.6.22-590/fs/Kconfig linux-2.6.22-570/fs/Kconfig
+--- linux-2.6.22-590/fs/Kconfig        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/Kconfig        2007-07-08 19:32:17.000000000 -0400
+@@ -1030,41 +1030,6 @@
+ endmenu
+-menu "Layered filesystems"
+-
+-config ECRYPT_FS
+-      tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
+-      depends on EXPERIMENTAL && KEYS && CRYPTO && NET
+-      help
+-        Encrypted filesystem that operates on the VFS layer.  See
+-        <file:Documentation/ecryptfs.txt> to learn more about
+-        eCryptfs.  Userspace components are required and can be
+-        obtained from <http://ecryptfs.sf.net>.
+-
+-        To compile this file system support as a module, choose M here: the
+-        module will be called ecryptfs.
+-
+-config UNION_FS
+-      tristate "Union file system (EXPERIMENTAL)"
+-      depends on EXPERIMENTAL
+-      help
+-        Unionfs is a stackable unification file system, which appears to
+-        merge the contents of several directories (branches), while keeping
+-        their physical content separate.
+-
+-        See <http://unionfs.filesystems.org> for details
+-
+-config UNION_FS_XATTR
+-      bool "Unionfs extended attributes"
+-      depends on UNION_FS
+-      help
+-        Extended attributes are name:value pairs associated with inodes by
+-        the kernel or by users (see the attr(5) manual page).
+-
+-        If unsure, say N.
+-
+-endmenu
+-
+ menu "Miscellaneous filesystems"
+ config ADFS_FS
+@@ -1117,6 +1082,18 @@
+         To compile this file system support as a module, choose M here: the
+         module will be called affs.  If unsure, say N.
  
-+struct task_struct;
-+extern unsigned long ptrace_get_reg(struct task_struct *task, int regno);
-+extern int ptrace_put_reg(struct task_struct *task, int regno,
-+                        unsigned long data);
++config ECRYPT_FS
++      tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
++      depends on EXPERIMENTAL && KEYS && CRYPTO && NET
++      help
++        Encrypted filesystem that operates on the VFS layer.  See
++        <file:Documentation/ecryptfs.txt> to learn more about
++        eCryptfs.  Userspace components are required and can be
++        obtained from <http://ecryptfs.sf.net>.
 +
- /*
-  * We use the least-significant bit of the trap field to indicate
-  * whether we have saved the full set of registers, or only a
-@@ -158,9 +163,7 @@
++        To compile this file system support as a module, choose M here: the
++        module will be called ecryptfs.
++
+ config HFS_FS
+       tristate "Apple Macintosh file system support (EXPERIMENTAL)"
+       depends on BLOCK && EXPERIMENTAL
+diff -Nurb linux-2.6.22-590/fs/Makefile linux-2.6.22-570/fs/Makefile
+--- linux-2.6.22-590/fs/Makefile       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/Makefile       2007-07-08 19:32:17.000000000 -0400
+@@ -19,7 +19,6 @@
+ obj-y +=      no-block.o
+ endif
  
- #define PT_NIP        32
- #define PT_MSR        33
--#ifdef __KERNEL__
- #define PT_ORIG_R3 34
--#endif
- #define PT_CTR        35
- #define PT_LNK        36
- #define PT_XER        37
-@@ -169,11 +172,12 @@
- #define PT_MQ 39
- #else
- #define PT_SOFTE 39
-+#endif
- #define PT_TRAP       40
- #define PT_DAR        41
- #define PT_DSISR 42
- #define PT_RESULT 43
--#endif
-+#define PT_REGS_COUNT 44
+-obj-$(CONFIG_MMU)             += revoke.o revoked_inode.o
+ obj-$(CONFIG_INOTIFY)         += inotify.o
+ obj-$(CONFIG_INOTIFY_USER)    += inotify_user.o
+ obj-$(CONFIG_EPOLL)           += eventpoll.o
+@@ -119,4 +118,3 @@
+ obj-$(CONFIG_DEBUG_FS)                += debugfs/
+ obj-$(CONFIG_OCFS2_FS)                += ocfs2/
+ obj-$(CONFIG_GFS2_FS)           += gfs2/
+-obj-$(CONFIG_UNION_FS)                += unionfs/
+diff -Nurb linux-2.6.22-590/fs/afs/netdevices.c linux-2.6.22-570/fs/afs/netdevices.c
+--- linux-2.6.22-590/fs/afs/netdevices.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/afs/netdevices.c       2007-07-08 19:32:17.000000000 -0400
+@@ -8,7 +8,6 @@
+ #include <linux/inetdevice.h>
+ #include <linux/netdevice.h>
+ #include <linux/if_arp.h>
+-#include <net/net_namespace.h>
+ #include "internal.h"
  
- #define PT_FPR0       48      /* each FP reg occupies 2 slots in this space */
+ /*
+@@ -24,7 +23,7 @@
+               BUG();
  
-@@ -229,7 +233,17 @@
- #define PTRACE_GET_DEBUGREG   25
- #define PTRACE_SET_DEBUGREG   26
+       rtnl_lock();
+-      dev = __dev_getfirstbyhwtype(&init_net, ARPHRD_ETHER);
++      dev = __dev_getfirstbyhwtype(ARPHRD_ETHER);
+       if (dev) {
+               memcpy(mac, dev->dev_addr, maclen);
+               ret = 0;
+@@ -48,7 +47,7 @@
+       ASSERT(maxbufs > 0);
  
--/* Additional PTRACE requests implemented on PowerPC. */
-+/* (new) PTRACE requests using the same numbers as x86 and the same
-+ * argument ordering. Additionally, they support more registers too
-+ */
-+#define PTRACE_GETREGS            12
-+#define PTRACE_SETREGS            13
-+#define PTRACE_GETFPREGS          14
-+#define PTRACE_SETFPREGS          15
-+#define PTRACE_GETREGS64        22
-+#define PTRACE_SETREGS64        23
-+
-+/* (old) PTRACE requests with inverted arguments */
- #define PPC_PTRACE_GETREGS    0x99    /* Get GPRs 0 - 31 */
- #define PPC_PTRACE_SETREGS    0x98    /* Set GPRs 0 - 31 */
- #define PPC_PTRACE_GETFPREGS  0x97    /* Get FPRs 0 - 31 */
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/syscalls.h linux-2.6.22-590/include/asm-powerpc/syscalls.h
---- linux-2.6.22-570/include/asm-powerpc/syscalls.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/syscalls.h    2008-01-02 13:56:37.000000000 -0500
-@@ -43,16 +43,9 @@
+       rtnl_lock();
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if (dev->type == ARPHRD_LOOPBACK && !wantloopback)
+                       continue;
+               idev = __in_dev_get_rtnl(dev);
+diff -Nurb linux-2.6.22-590/fs/buffer.c linux-2.6.22-570/fs/buffer.c
+--- linux-2.6.22-590/fs/buffer.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/buffer.c       2007-07-08 19:32:17.000000000 -0400
+@@ -982,7 +982,7 @@
+       struct buffer_head *bh;
  
- asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset,
-               size_t sigsetsize);
--
--#ifndef __powerpc64__
--asmlinkage long sys_sigaltstack(const stack_t __user *uss,
--              stack_t __user *uoss, int r5, int r6, int r7, int r8,
--              struct pt_regs *regs);
--#else /* __powerpc64__ */
- asmlinkage long sys_sigaltstack(const stack_t __user *uss,
-               stack_t __user *uoss, unsigned long r5, unsigned long r6,
-               unsigned long r7, unsigned long r8, struct pt_regs *regs);
--#endif /* __powerpc64__ */
+       page = find_or_create_page(inode->i_mapping, index,
+-              (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);
++              mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
+       if (!page)
+               return NULL;
  
- #endif /* __KERNEL__ */
- #endif /* __ASM_POWERPC_SYSCALLS_H */
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/systbl.h linux-2.6.22-590/include/asm-powerpc/systbl.h
---- linux-2.6.22-570/include/asm-powerpc/systbl.h      2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/asm-powerpc/systbl.h      2008-01-02 13:56:37.000000000 -0500
-@@ -312,3 +312,4 @@
- COMPAT_SYS_SPU(timerfd)
- SYSCALL_SPU(eventfd)
- COMPAT_SYS_SPU(sync_file_range2)
-+COMPAT_SYS(fallocate)
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/thread_info.h linux-2.6.22-590/include/asm-powerpc/thread_info.h
---- linux-2.6.22-570/include/asm-powerpc/thread_info.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/thread_info.h 2008-01-02 13:56:37.000000000 -0500
-@@ -113,8 +113,8 @@
- #define TIF_POLLING_NRFLAG    4       /* true if poll_idle() is polling
-                                          TIF_NEED_RESCHED */
- #define TIF_32BIT             5       /* 32 bit binary */
--#define TIF_RUNLATCH          6       /* Is the runlatch enabled? */
--#define TIF_ABI_PENDING               7       /* 32/64 bit switch needed */
-+#define TIF_PERFMON_WORK      6       /* work for pfm_handle_work() */
-+#define TIF_PERFMON_CTXSW     7       /* perfmon needs ctxsw calls */
- #define TIF_SYSCALL_AUDIT     8       /* syscall auditing active */
- #define TIF_SINGLESTEP                9       /* singlestepping active */
- #define TIF_MEMDIE            10
-@@ -123,6 +123,8 @@
- #define TIF_NOERROR           14      /* Force successful syscall return */
- #define TIF_RESTORE_SIGMASK   15      /* Restore signal mask in do_signal */
- #define TIF_FREEZE            16      /* Freezing for suspend */
-+#define TIF_RUNLATCH          17      /* Is the runlatch enabled? */
-+#define TIF_ABI_PENDING               18      /* 32/64 bit switch needed */
+@@ -2899,8 +2899,7 @@
+       
+ struct buffer_head *alloc_buffer_head(gfp_t gfp_flags)
+ {
+-      struct buffer_head *ret = kmem_cache_zalloc(bh_cachep,
+-                              set_migrateflags(gfp_flags, __GFP_RECLAIMABLE));
++      struct buffer_head *ret = kmem_cache_zalloc(bh_cachep, gfp_flags);
+       if (ret) {
+               INIT_LIST_HEAD(&ret->b_assoc_buffers);
+               get_cpu_var(bh_accounting).nr++;
+diff -Nurb linux-2.6.22-590/fs/cifs/cifsfs.c linux-2.6.22-570/fs/cifs/cifsfs.c
+--- linux-2.6.22-590/fs/cifs/cifsfs.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/cifs/cifsfs.c  2007-07-08 19:32:17.000000000 -0400
+@@ -849,7 +849,6 @@
+       __u16  netfid;
+       int rc;
  
- /* as above, but as bit values */
- #define _TIF_SYSCALL_TRACE    (1<<TIF_SYSCALL_TRACE)
-@@ -131,8 +133,8 @@
- #define _TIF_NEED_RESCHED     (1<<TIF_NEED_RESCHED)
- #define _TIF_POLLING_NRFLAG   (1<<TIF_POLLING_NRFLAG)
- #define _TIF_32BIT            (1<<TIF_32BIT)
--#define _TIF_RUNLATCH         (1<<TIF_RUNLATCH)
--#define _TIF_ABI_PENDING      (1<<TIF_ABI_PENDING)
-+#define _TIF_PERFMON_WORK     (1<<TIF_PERFMON_WORK)
-+#define _TIF_PERFMON_CTXSW    (1<<TIF_PERFMON_CTXSW)
- #define _TIF_SYSCALL_AUDIT    (1<<TIF_SYSCALL_AUDIT)
- #define _TIF_SINGLESTEP               (1<<TIF_SINGLESTEP)
- #define _TIF_SECCOMP          (1<<TIF_SECCOMP)
-@@ -140,6 +142,8 @@
- #define _TIF_NOERROR          (1<<TIF_NOERROR)
- #define _TIF_RESTORE_SIGMASK  (1<<TIF_RESTORE_SIGMASK)
- #define _TIF_FREEZE           (1<<TIF_FREEZE)
-+#define _TIF_RUNLATCH         (1<<TIF_RUNLATCH)
-+#define _TIF_ABI_PENDING      (1<<TIF_ABI_PENDING)
- #define _TIF_SYSCALL_T_OR_A   (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
+-      set_freezable();
+       do {
+               if (try_to_freeze()) 
+                       continue;
+diff -Nurb linux-2.6.22-590/fs/cifs/connect.c linux-2.6.22-570/fs/cifs/connect.c
+--- linux-2.6.22-590/fs/cifs/connect.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/cifs/connect.c 2007-07-08 19:32:17.000000000 -0400
+@@ -363,7 +363,6 @@
+                       GFP_KERNEL);
+       }
  
- #define _TIF_USER_WORK_MASK   (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/tlbflush.h linux-2.6.22-590/include/asm-powerpc/tlbflush.h
---- linux-2.6.22-570/include/asm-powerpc/tlbflush.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-powerpc/tlbflush.h    2008-01-02 13:56:37.000000000 -0500
-@@ -155,6 +155,11 @@
+-      set_freezable();
+       while (!kthread_should_stop()) {
+               if (try_to_freeze())
+                       continue;
+diff -Nurb linux-2.6.22-590/fs/compat_ioctl.c linux-2.6.22-570/fs/compat_ioctl.c
+--- linux-2.6.22-590/fs/compat_ioctl.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/compat_ioctl.c 2007-07-08 19:32:17.000000000 -0400
+@@ -319,21 +319,22 @@
+ static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
  {
+-      struct ifreq __user *uifr;
++      struct net_device *dev;
++      struct ifreq32 ifr32;
+       int err;
+-      uifr = compat_alloc_user_space(sizeof(struct ifreq));
+-      if (copy_in_user(uifr, compat_ptr(arg), sizeof(struct ifreq32)));
++      if (copy_from_user(&ifr32, compat_ptr(arg), sizeof(ifr32)))
+               return -EFAULT;
+-      err = sys_ioctl(fd, SIOCGIFNAME, (unsigned long)uifr);
+-      if (err)
+-              return err;
++      dev = dev_get_by_index(ifr32.ifr_ifindex);
++      if (!dev)
++              return -ENODEV;
+-      if (copy_in_user(compat_ptr(arg), uifr, sizeof(struct ifreq32)))
+-              return -EFAULT;
++      strlcpy(ifr32.ifr_name, dev->name, sizeof(ifr32.ifr_name));
++      dev_put(dev);
+       
+-      return 0;
++      err = copy_to_user(compat_ptr(arg), &ifr32, sizeof(ifr32));
++      return (err ? -EFAULT : 0);
  }
  
-+/* Private function for use by PCI IO mapping code */
-+extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
-+                                   unsigned long end);
-+
-+
- #endif
+ static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
+diff -Nurb linux-2.6.22-590/fs/configfs/configfs_internal.h linux-2.6.22-570/fs/configfs/configfs_internal.h
+--- linux-2.6.22-590/fs/configfs/configfs_internal.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/configfs/configfs_internal.h   2007-07-08 19:32:17.000000000 -0400
+@@ -29,7 +29,6 @@
  
- /*
-diff -Nurb linux-2.6.22-570/include/asm-powerpc/unistd.h linux-2.6.22-590/include/asm-powerpc/unistd.h
---- linux-2.6.22-570/include/asm-powerpc/unistd.h      2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/asm-powerpc/unistd.h      2008-01-02 13:56:37.000000000 -0500
-@@ -331,10 +331,11 @@
- #define __NR_timerfd          306
- #define __NR_eventfd          307
- #define __NR_sync_file_range2 308
-+#define __NR_fallocate                309
+ struct configfs_dirent {
+       atomic_t                s_count;
+-      int                     s_dependent_count;
+       struct list_head        s_sibling;
+       struct list_head        s_children;
+       struct list_head        s_links;
+diff -Nurb linux-2.6.22-590/fs/configfs/dir.c linux-2.6.22-570/fs/configfs/dir.c
+--- linux-2.6.22-590/fs/configfs/dir.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/configfs/dir.c 2007-07-08 19:32:17.000000000 -0400
+@@ -355,10 +355,6 @@
+                       /* Mark that we've taken i_mutex */
+                       sd->s_type |= CONFIGFS_USET_DROPPING;
  
- #ifdef __KERNEL__
+-                      /*
+-                       * Yup, recursive.  If there's a problem, blame
+-                       * deep nesting of default_groups
+-                       */
+                       ret = configfs_detach_prep(sd->s_dentry);
+                       if (!ret)
+                               continue;
+@@ -718,28 +714,6 @@
+ }
  
--#define __NR_syscalls         309
-+#define __NR_syscalls         310
+ /*
+- * After the item has been detached from the filesystem view, we are
+- * ready to tear it out of the hierarchy.  Notify the client before
+- * we do that so they can perform any cleanup that requires
+- * navigating the hierarchy.  A client does not need to provide this
+- * callback.  The subsystem semaphore MUST be held by the caller, and
+- * references must be valid for both items.  It also assumes the
+- * caller has validated ci_type.
+- */
+-static void client_disconnect_notify(struct config_item *parent_item,
+-                                   struct config_item *item)
+-{
+-      struct config_item_type *type;
+-
+-      type = parent_item->ci_type;
+-      BUG_ON(!type);
+-
+-      if (type->ct_group_ops && type->ct_group_ops->disconnect_notify)
+-              type->ct_group_ops->disconnect_notify(to_config_group(parent_item),
+-                                                    item);
+-}
+-
+-/*
+  * Drop the initial reference from make_item()/make_group()
+  * This function assumes that reference is held on item
+  * and that item holds a valid reference to the parent.  Also, it
+@@ -764,239 +738,6 @@
+               config_item_put(item);
+ }
  
- #define __NR__exit __NR_exit
- #define NR_syscalls   __NR_syscalls
-diff -Nurb linux-2.6.22-570/include/asm-ppc/kgdb.h linux-2.6.22-590/include/asm-ppc/kgdb.h
---- linux-2.6.22-570/include/asm-ppc/kgdb.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-ppc/kgdb.h    2008-01-02 13:56:37.000000000 -0500
-@@ -1,57 +1,18 @@
+-#ifdef DEBUG
+-static void configfs_dump_one(struct configfs_dirent *sd, int level)
+-{
+-      printk(KERN_INFO "%*s\"%s\":\n", level, " ", configfs_get_name(sd));
+-
+-#define type_print(_type) if (sd->s_type & _type) printk(KERN_INFO "%*s %s\n", level, " ", #_type);
+-      type_print(CONFIGFS_ROOT);
+-      type_print(CONFIGFS_DIR);
+-      type_print(CONFIGFS_ITEM_ATTR);
+-      type_print(CONFIGFS_ITEM_LINK);
+-      type_print(CONFIGFS_USET_DIR);
+-      type_print(CONFIGFS_USET_DEFAULT);
+-      type_print(CONFIGFS_USET_DROPPING);
+-#undef type_print
+-}
+-
+-static int configfs_dump(struct configfs_dirent *sd, int level)
+-{
+-      struct configfs_dirent *child_sd;
+-      int ret = 0;
+-
+-      configfs_dump_one(sd, level);
+-
+-      if (!(sd->s_type & (CONFIGFS_DIR|CONFIGFS_ROOT)))
+-              return 0;
+-
+-      list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
+-              ret = configfs_dump(child_sd, level + 2);
+-              if (ret)
+-                      break;
+-      }
+-
+-      return ret;
+-}
+-#endif
+-
+-
 -/*
-- * kgdb.h: Defines and declarations for serial line source level
-- *         remote debugging of the Linux kernel using gdb.
+- * configfs_depend_item() and configfs_undepend_item()
 - *
-- * PPC Mods (C) 1998 Michael Tesch (tesch@cs.wisc.edu)
+- * WARNING: Do not call these from a configfs callback!
 - *
-- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+- * This describes these functions and their helpers.
+- *
+- * Allow another kernel system to depend on a config_item.  If this
+- * happens, the item cannot go away until the dependant can live without
+- * it.  The idea is to give client modules as simple an interface as
+- * possible.  When a system asks them to depend on an item, they just
+- * call configfs_depend_item().  If the item is live and the client
+- * driver is in good shape, we'll happily do the work for them.
+- *
+- * Why is the locking complex?  Because configfs uses the VFS to handle
+- * all locking, but this function is called outside the normal
+- * VFS->configfs path.  So it must take VFS locks to prevent the
+- * VFS->configfs stuff (configfs_mkdir(), configfs_rmdir(), etc).  This is
+- * why you can't call these functions underneath configfs callbacks.
+- *
+- * Note, btw, that this can be called at *any* time, even when a configfs
+- * subsystem isn't registered, or when configfs is loading or unloading.
+- * Just like configfs_register_subsystem().  So we take the same
+- * precautions.  We pin the filesystem.  We lock each i_mutex _in_order_
+- * on our way down the tree.  If we can find the target item in the
+- * configfs tree, it must be part of the subsystem tree as well, so we
+- * do not need the subsystem semaphore.  Holding the i_mutex chain locks
+- * out mkdir() and rmdir(), who might be racing us.
 - */
- #ifdef __KERNEL__
--#ifndef _PPC_KGDB_H
--#define _PPC_KGDB_H
 -
-+#ifndef __PPC_KGDB_H__
-+#define __PPC_KGDB_H__
-+#include <asm-powerpc/kgdb.h>
- #ifndef __ASSEMBLY__
+-/*
+- * configfs_depend_prep()
+- *
+- * Only subdirectories count here.  Files (CONFIGFS_NOT_PINNED) are
+- * attributes.  This is similar but not the same to configfs_detach_prep().
+- * Note that configfs_detach_prep() expects the parent to be locked when it
+- * is called, but we lock the parent *inside* configfs_depend_prep().  We
+- * do that so we can unlock it if we find nothing.
+- *
+- * Here we do a depth-first search of the dentry hierarchy looking for
+- * our object.  We take i_mutex on each step of the way down.  IT IS
+- * ESSENTIAL THAT i_mutex LOCKING IS ORDERED.  If we come back up a branch,
+- * we'll drop the i_mutex.
+- *
+- * If the target is not found, -ENOENT is bubbled up and we have released
+- * all locks.  If the target was found, the locks will be cleared by
+- * configfs_depend_rollback().
+- *
+- * This adds a requirement that all config_items be unique!
+- *
+- * This is recursive because the locking traversal is tricky.  There isn't
+- * much on the stack, though, so folks that need this function - be careful
+- * about your stack!  Patches will be accepted to make it iterative.
+- */
+-static int configfs_depend_prep(struct dentry *origin,
+-                              struct config_item *target)
+-{
+-      struct configfs_dirent *child_sd, *sd = origin->d_fsdata;
+-      int ret = 0;
 -
--/* Things specific to the gen550 backend. */
--struct uart_port;
+-      BUG_ON(!origin || !sd);
+-
+-      /* Lock this guy on the way down */
+-      mutex_lock(&sd->s_dentry->d_inode->i_mutex);
+-      if (sd->s_element == target)  /* Boo-yah */
+-              goto out;
 -
--extern void gen550_progress(char *, unsigned short);
--extern void gen550_kgdb_map_scc(void);
--extern void gen550_init(int, struct uart_port *);
+-      list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
+-              if (child_sd->s_type & CONFIGFS_DIR) {
+-                      ret = configfs_depend_prep(child_sd->s_dentry,
+-                                                 target);
+-                      if (!ret)
+-                              goto out;  /* Child path boo-yah */
+-              }
+-      }
 -
--/* Things specific to the pmac backend. */
--extern void zs_kgdb_hook(int tty_num);
+-      /* We looped all our children and didn't find target */
+-      mutex_unlock(&sd->s_dentry->d_inode->i_mutex);
+-      ret = -ENOENT;
 -
--/* To init the kgdb engine. (called by serial hook)*/
--extern void set_debug_traps(void);
+-out:
+-      return ret;
+-}
 -
--/* To enter the debugger explicitly. */
--extern void breakpoint(void);
+-/*
+- * This is ONLY called if configfs_depend_prep() did its job.  So we can
+- * trust the entire path from item back up to origin.
+- *
+- * We walk backwards from item, unlocking each i_mutex.  We finish by
+- * unlocking origin.
+- */
+-static void configfs_depend_rollback(struct dentry *origin,
+-                                   struct config_item *item)
+-{
+-      struct dentry *dentry = item->ci_dentry;
 -
--/* For taking exceptions
-+ /* For taking exceptions
-  * these are defined in traps.c
-  */
--extern int (*debugger)(struct pt_regs *regs);
-+struct pt_regs;
-+extern void (*debugger)(struct pt_regs *regs);
- extern int (*debugger_bpt)(struct pt_regs *regs);
- extern int (*debugger_sstep)(struct pt_regs *regs);
- extern int (*debugger_iabr_match)(struct pt_regs *regs);
- extern int (*debugger_dabr_match)(struct pt_regs *regs);
- extern void (*debugger_fault_handler)(struct pt_regs *regs);
+-      while (dentry != origin) {
+-              mutex_unlock(&dentry->d_inode->i_mutex);
+-              dentry = dentry->d_parent;
+-      }
+-
+-      mutex_unlock(&origin->d_inode->i_mutex);
+-}
+-
+-int configfs_depend_item(struct configfs_subsystem *subsys,
+-                       struct config_item *target)
+-{
+-      int ret;
+-      struct configfs_dirent *p, *root_sd, *subsys_sd = NULL;
+-      struct config_item *s_item = &subsys->su_group.cg_item;
+-
+-      /*
+-       * Pin the configfs filesystem.  This means we can safely access
+-       * the root of the configfs filesystem.
+-       */
+-      ret = configfs_pin_fs();
+-      if (ret)
+-              return ret;
+-
+-      /*
+-       * Next, lock the root directory.  We're going to check that the
+-       * subsystem is really registered, and so we need to lock out
+-       * configfs_[un]register_subsystem().
+-       */
+-      mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);
 -
--/* What we bring to the party */
--int kgdb_bpt(struct pt_regs *regs);
--int kgdb_sstep(struct pt_regs *regs);
--void kgdb(struct pt_regs *regs);
--int kgdb_iabr_match(struct pt_regs *regs);
--int kgdb_dabr_match(struct pt_regs *regs);
+-      root_sd = configfs_sb->s_root->d_fsdata;
+-
+-      list_for_each_entry(p, &root_sd->s_children, s_sibling) {
+-              if (p->s_type & CONFIGFS_DIR) {
+-                      if (p->s_element == s_item) {
+-                              subsys_sd = p;
+-                              break;
+-                      }
+-              }
+-      }
+-
+-      if (!subsys_sd) {
+-              ret = -ENOENT;
+-              goto out_unlock_fs;
+-      }
+-
+-      /* Ok, now we can trust subsys/s_item */
+-
+-      /* Scan the tree, locking i_mutex recursively, return 0 if found */
+-      ret = configfs_depend_prep(subsys_sd->s_dentry, target);
+-      if (ret)
+-              goto out_unlock_fs;
+-
+-      /* We hold all i_mutexes from the subsystem down to the target */
+-      p = target->ci_dentry->d_fsdata;
+-      p->s_dependent_count += 1;
+-
+-      configfs_depend_rollback(subsys_sd->s_dentry, target);
+-
+-out_unlock_fs:
+-      mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);
+-
+-      /*
+-       * If we succeeded, the fs is pinned via other methods.  If not,
+-       * we're done with it anyway.  So release_fs() is always right.
+-       */
+-      configfs_release_fs();
+-
+-      return ret;
+-}
+-EXPORT_SYMBOL(configfs_depend_item);
 -
 -/*
-- * external low-level support routines (ie macserial.c)
+- * Release the dependent linkage.  This is much simpler than
+- * configfs_depend_item() because we know that that the client driver is
+- * pinned, thus the subsystem is pinned, and therefore configfs is pinned.
 - */
--extern void kgdb_interruptible(int); /* control interrupts from serial */
--extern void putDebugChar(char);   /* write a single character      */
--extern char getDebugChar(void);   /* read and return a single char */
+-void configfs_undepend_item(struct configfs_subsystem *subsys,
+-                          struct config_item *target)
+-{
+-      struct configfs_dirent *sd;
 -
--#endif /* !(__ASSEMBLY__) */
--#endif /* !(_PPC_KGDB_H) */
-+#endif /* !__ASSEMBLY__ */
-+#endif /* __PPC_KGDB_H__ */
- #endif /* __KERNEL__ */
-diff -Nurb linux-2.6.22-570/include/asm-ppc/machdep.h linux-2.6.22-590/include/asm-ppc/machdep.h
---- linux-2.6.22-570/include/asm-ppc/machdep.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-ppc/machdep.h 2008-01-02 13:56:37.000000000 -0500
-@@ -72,9 +72,7 @@
-       unsigned long   (*find_end_of_memory)(void);
-       void            (*setup_io_mappings)(void);
--      void            (*early_serial_map)(void);
-       void            (*progress)(char *, unsigned short);
--      void            (*kgdb_map_scc)(void);
+-      /*
+-       * Since we can trust everything is pinned, we just need i_mutex
+-       * on the item.
+-       */
+-      mutex_lock(&target->ci_dentry->d_inode->i_mutex);
+-
+-      sd = target->ci_dentry->d_fsdata;
+-      BUG_ON(sd->s_dependent_count < 1);
+-
+-      sd->s_dependent_count -= 1;
+-
+-      /*
+-       * After this unlock, we cannot trust the item to stay alive!
+-       * DO NOT REFERENCE item after this unlock.
+-       */
+-      mutex_unlock(&target->ci_dentry->d_inode->i_mutex);
+-}
+-EXPORT_SYMBOL(configfs_undepend_item);
  
-       unsigned char   (*nvram_read_val)(int addr);
-       void            (*nvram_write_val)(int addr, unsigned char val);
-diff -Nurb linux-2.6.22-570/include/asm-ppc/mv64x60.h linux-2.6.22-590/include/asm-ppc/mv64x60.h
---- linux-2.6.22-570/include/asm-ppc/mv64x60.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-ppc/mv64x60.h 2008-01-02 13:56:37.000000000 -0500
-@@ -348,6 +348,8 @@
+ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+ {
+@@ -1101,14 +842,11 @@
+       if (ret) {
+               /* Tear down everything we built up */
+               down(&subsys->su_sem);
+-
+-              client_disconnect_notify(parent_item, item);
+               if (group)
+                       unlink_group(group);
+               else
+                       unlink_obj(item);
+               client_drop_item(parent_item, item);
+-
+               up(&subsys->su_sem);
  
- void mv64x60_progress_init(u32 base);
- void mv64x60_mpsc_progress(char *s, unsigned short hex);
-+struct platform_device * mv64x60_early_get_pdev_data(const char *name,
-+              int id, int remove);
+               if (module_got)
+@@ -1143,13 +881,6 @@
+       if (sd->s_type & CONFIGFS_USET_DEFAULT)
+               return -EPERM;
  
- extern struct mv64x60_32bit_window
-       gt64260_32bit_windows[MV64x60_32BIT_WIN_COUNT];
-diff -Nurb linux-2.6.22-570/include/asm-ppc/mv64x60_defs.h linux-2.6.22-590/include/asm-ppc/mv64x60_defs.h
---- linux-2.6.22-570/include/asm-ppc/mv64x60_defs.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-ppc/mv64x60_defs.h    2008-01-02 13:56:37.000000000 -0500
-@@ -57,7 +57,8 @@
- #define       MV64x60_IRQ_I2C                         37
- #define       MV64x60_IRQ_BRG                         39
- #define       MV64x60_IRQ_MPSC_0                      40
--#define       MV64x60_IRQ_MPSC_1                      42
-+#define       MV64360_IRQ_MPSC_1                      41
-+#define       GT64260_IRQ_MPSC_1                      42
- #define       MV64x60_IRQ_COMM                        43
- #define       MV64x60_IRQ_P0_GPP_0_7                  56
- #define       MV64x60_IRQ_P0_GPP_8_15                 57
-diff -Nurb linux-2.6.22-570/include/asm-s390/page.h linux-2.6.22-590/include/asm-s390/page.h
---- linux-2.6.22-570/include/asm-s390/page.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-s390/page.h   2008-01-02 13:56:37.000000000 -0500
-@@ -64,7 +64,8 @@
- #define clear_user_page(page, vaddr, pg)      clear_page(page)
- #define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
+-      /*
+-       * Here's where we check for dependents.  We're protected by
+-       * i_mutex.
+-       */
+-      if (sd->s_dependent_count)
+-              return -EBUSY;
+-
+       /* Get a working ref until we have the child */
+       parent_item = configfs_get_config_item(dentry->d_parent);
+       subsys = to_config_group(parent_item)->cg_subsys;
+@@ -1180,13 +911,11 @@
+               configfs_detach_group(item);
  
--#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
-+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
-+      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
- #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+               down(&subsys->su_sem);
+-              client_disconnect_notify(parent_item, item);
+               unlink_group(to_config_group(item));
+       } else {
+               configfs_detach_item(item);
  
- /*
-diff -Nurb linux-2.6.22-570/include/asm-sh/kgdb.h linux-2.6.22-590/include/asm-sh/kgdb.h
---- linux-2.6.22-570/include/asm-sh/kgdb.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-sh/kgdb.h     2008-01-02 13:56:37.000000000 -0500
-@@ -2,78 +2,41 @@
-  * May be copied or modified under the terms of the GNU General Public
-  * License.  See linux/COPYING for more information.
-  *
-- * Based on original code by Glenn Engel, Jim Kingdon,
-- * David Grothe <dave@gcom.com>, Tigran Aivazian, <tigran@sco.com> and
-- * Amit S. Kale <akale@veritas.com>
-+ * Based on a file that was modified or based on files by: Glenn Engel,
-+ * Jim Kingdon, David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
-+ * Amit S. Kale <akale@veritas.com>, sh-stub.c from Ben Lee and
-+ * Steve Chamberlain, Henry Bell <henry.bell@st.com>
-  * 
-- * Super-H port based on sh-stub.c (Ben Lee and Steve Chamberlain) by
-- * Henry Bell <henry.bell@st.com>
-- * 
-- * Header file for low-level support for remote debug using GDB. 
-+ * Maintainer: Tom Rini <trini@kernel.crashing.org>
-  *
-  */
+               down(&subsys->su_sem);
+-              client_disconnect_notify(parent_item, item);
+               unlink_obj(item);
+       }
  
- #ifndef __KGDB_H
- #define __KGDB_H
+diff -Nurb linux-2.6.22-590/fs/configfs/file.c linux-2.6.22-570/fs/configfs/file.c
+--- linux-2.6.22-590/fs/configfs/file.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/configfs/file.c        2007-07-08 19:32:17.000000000 -0400
+@@ -27,26 +27,19 @@
+ #include <linux/fs.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+-#include <linux/mutex.h>
+ #include <asm/uaccess.h>
++#include <asm/semaphore.h>
  
--#include <asm/ptrace.h>
--#include <asm/cacheflush.h>
-+#include <asm-generic/kgdb.h>
+ #include <linux/configfs.h>
+ #include "configfs_internal.h"
  
--struct console;
-+/* Based on sh-gdb.c from gdb-6.1, Glenn
-+     Engel at HP  Ben Lee and Steve Chamberlain */
-+#define NUMREGBYTES   112     /* 92 */
-+#define NUMCRITREGBYTES       (9 << 2)
-+#define BUFMAX                400
+-/*
+- * A simple attribute can only be 4096 characters.  Why 4k?  Because the
+- * original code limited it to PAGE_SIZE.  That's a bad idea, though,
+- * because an attribute of 16k on ia64 won't work on x86.  So we limit to
+- * 4k, our minimum common page size.
+- */
+-#define SIMPLE_ATTR_SIZE 4096
  
--/* Same as pt_regs but has vbr in place of syscall_nr */
-+#ifndef __ASSEMBLY__
- struct kgdb_regs {
-         unsigned long regs[16];
-         unsigned long pc;
-         unsigned long pr;
--        unsigned long sr;
-         unsigned long gbr;
-+        unsigned long vbr;
-         unsigned long mach;
-         unsigned long macl;
--        unsigned long vbr;
-+        unsigned long sr;
+ struct configfs_buffer {
+       size_t                  count;
+       loff_t                  pos;
+       char                    * page;
+       struct configfs_item_operations * ops;
+-      struct mutex            mutex;
++      struct semaphore        sem;
+       int                     needs_read_fill;
  };
  
--/* State info */
--extern char kgdb_in_gdb_mode;
--extern int kgdb_done_init;
--extern int kgdb_enabled;
--extern int kgdb_nofault;      /* Ignore bus errors (in gdb mem access) */
--extern int kgdb_halt;         /* Execute initial breakpoint at startup */
--extern char in_nmi;           /* Debounce flag to prevent NMI reentry*/
--
--/* SCI */
--extern int kgdb_portnum;
--extern int kgdb_baud;
--extern char kgdb_parity;
--extern char kgdb_bits;
--
--/* Init and interface stuff */
--extern int kgdb_init(void);
--extern int (*kgdb_getchar)(void);
--extern void (*kgdb_putchar)(int);
--
--/* Trap functions */
--typedef void (kgdb_debug_hook_t)(struct pt_regs *regs);
--typedef void (kgdb_bus_error_hook_t)(void);
--extern kgdb_debug_hook_t  *kgdb_debug_hook;
--extern kgdb_bus_error_hook_t *kgdb_bus_err_hook;
--
--/* Console */
--void kgdb_console_write(struct console *co, const char *s, unsigned count);
--extern int kgdb_console_setup(struct console *, char *);
--
--/* Prototypes for jmp fns */
--#define _JBLEN 9
--typedef        int jmp_buf[_JBLEN];
--extern void    longjmp(jmp_buf __jmpb, int __retval);
--extern int     setjmp(jmp_buf __jmpb);
--
--/* Forced breakpoint */
--#define breakpoint()                                  \
--do {                                                  \
--      if (kgdb_enabled)                               \
--              __asm__ __volatile__("trapa   #0x3c");  \
--} while (0)
-+#define BREAKPOINT()          asm("trapa #0xff");
-+#define BREAK_INSTR_SIZE      2
-+#define CACHE_FLUSH_IS_SAFE   1
+@@ -76,7 +69,7 @@
  
- /* KGDB should be able to flush all kernel text space */
- #if defined(CONFIG_CPU_SH4)
-@@ -100,4 +63,5 @@
- {
-       return hexchars[x & 0xf];
+       count = ops->show_attribute(item,attr,buffer->page);
+       buffer->needs_read_fill = 0;
+-      BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE);
++      BUG_ON(count > (ssize_t)PAGE_SIZE);
+       if (count >= 0)
+               buffer->count = count;
+       else
+@@ -109,7 +102,7 @@
+       struct configfs_buffer * buffer = file->private_data;
+       ssize_t retval = 0;
+-      mutex_lock(&buffer->mutex);
++      down(&buffer->sem);
+       if (buffer->needs_read_fill) {
+               if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
+                       goto out;
+@@ -119,7 +112,7 @@
+       retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
+                                        buffer->count);
+ out:
+-      mutex_unlock(&buffer->mutex);
++      up(&buffer->sem);
+       return retval;
  }
-+#endif                                /* !__ASSEMBLY__ */
- #endif
-diff -Nurb linux-2.6.22-570/include/asm-sh/system.h linux-2.6.22-590/include/asm-sh/system.h
---- linux-2.6.22-570/include/asm-sh/system.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-sh/system.h   2008-01-02 13:56:37.000000000 -0500
-@@ -264,6 +264,45 @@
- #define instruction_size(insn)        (2)
- #endif
  
-+static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
-+      unsigned long new)
-+{
-+      __u32 retval;
-+      unsigned long flags;
-+
-+      local_irq_save(flags);
-+      retval = *m;
-+      if (retval == old)
-+              *m = new;
-+      local_irq_restore(flags);       /* implies memory barrier  */
-+      return retval;
-+}
-+
-+/* This function doesn't exist, so you'll get a linker error
-+ * if something tries to do an invalid cmpxchg(). */
-+extern void __cmpxchg_called_with_bad_pointer(void);
-+
-+#define __HAVE_ARCH_CMPXCHG   1
-+
-+static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
-+              unsigned long new, int size)
-+{
-+      switch (size) {
-+      case 4:
-+              return __cmpxchg_u32(ptr, old, new);
-+      }
-+      __cmpxchg_called_with_bad_pointer();
-+      return old;
-+}
+@@ -144,8 +137,8 @@
+       if (!buffer->page)
+               return -ENOMEM;
+-      if (count >= SIMPLE_ATTR_SIZE)
+-              count = SIMPLE_ATTR_SIZE - 1;
++      if (count >= PAGE_SIZE)
++              count = PAGE_SIZE - 1;
+       error = copy_from_user(buffer->page,buf,count);
+       buffer->needs_read_fill = 1;
+       /* if buf is assumed to contain a string, terminate it by \0,
+@@ -200,13 +193,13 @@
+       struct configfs_buffer * buffer = file->private_data;
+       ssize_t len;
+-      mutex_lock(&buffer->mutex);
++      down(&buffer->sem);
+       len = fill_write_buffer(buffer, buf, count);
+       if (len > 0)
+               len = flush_write_buffer(file->f_path.dentry, buffer, count);
+       if (len > 0)
+               *ppos += len;
+-      mutex_unlock(&buffer->mutex);
++      up(&buffer->sem);
+       return len;
+ }
+@@ -260,7 +253,7 @@
+               error = -ENOMEM;
+               goto Enomem;
+       }
+-      mutex_init(&buffer->mutex);
++      init_MUTEX(&buffer->sem);
+       buffer->needs_read_fill = 1;
+       buffer->ops = ops;
+       file->private_data = buffer;
+@@ -299,7 +292,6 @@
+       if (buffer) {
+               if (buffer->page)
+                       free_page((unsigned long)buffer->page);
+-              mutex_destroy(&buffer->mutex);
+               kfree(buffer);
+       }
+       return 0;
+diff -Nurb linux-2.6.22-590/fs/configfs/item.c linux-2.6.22-570/fs/configfs/item.c
+--- linux-2.6.22-590/fs/configfs/item.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/configfs/item.c        2007-07-08 19:32:17.000000000 -0400
+@@ -62,6 +62,7 @@
+  *    dynamically allocated string that @item->ci_name points to.
+  *    Otherwise, use the static @item->ci_namebuf array.
+  */
 +
-+#define cmpxchg(ptr,o,n)                                               \
-+  ({                                                                   \
-+     __typeof__(*(ptr)) _o_ = (o);                                     \
-+     __typeof__(*(ptr)) _n_ = (n);                                     \
-+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,                 \
-+                                  (unsigned long)_n_, sizeof(*(ptr))); \
-+  })
+ int config_item_set_name(struct config_item * item, const char * fmt, ...)
+ {
+       int error = 0;
+@@ -138,7 +139,12 @@
+       return item;
+ }
+-static void config_item_cleanup(struct config_item * item)
++/**
++ *    config_item_cleanup - free config_item resources.
++ *    @item:  item.
++ */
 +
- /* XXX
-  * disable hlt during certain critical i/o operations
-  */
-diff -Nurb linux-2.6.22-570/include/asm-um/thread_info.h linux-2.6.22-590/include/asm-um/thread_info.h
---- linux-2.6.22-570/include/asm-um/thread_info.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-um/thread_info.h      2008-01-02 13:56:37.000000000 -0500
-@@ -52,10 +52,21 @@
-       return ti;
++void config_item_cleanup(struct config_item * item)
+ {
+       struct config_item_type * t = item->ci_type;
+       struct config_group * s = item->ci_group;
+@@ -173,10 +179,12 @@
+               kref_put(&item->ci_kref, config_item_release);
  }
  
-+#ifdef CONFIG_DEBUG_STACK_USAGE
 +
-+#define alloc_thread_info(tsk) \
-+      ((struct thread_info *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, \
-+                                               CONFIG_KERNEL_STACK_ORDER))
-+#else
+ /**
+  *    config_group_init - initialize a group for use
+  *    @k:     group
+  */
 +
- /* thread information allocation */
- #define alloc_thread_info(tsk) \
--      ((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
--#define free_thread_info(ti) kfree(ti)
-+      ((struct thread_info *) __get_free_pages(GFP_KERNEL, \
-+                                               CONFIG_KERNEL_STACK_ORDER))
-+#endif
+ void config_group_init(struct config_group *group)
+ {
+       config_item_init(&group->cg_item);
+@@ -193,8 +201,8 @@
+  *    looking for a matching config_item. If matching item is found
+  *    take a reference and return the item.
+  */
+-struct config_item *config_group_find_obj(struct config_group *group,
+-                                        const char * name)
 +
-+#define free_thread_info(ti) \
-+      free_pages((unsigned long)(ti),CONFIG_KERNEL_STACK_ORDER)
++struct config_item * config_group_find_obj(struct config_group * group, const char * name)
+ {
+       struct list_head * entry;
+       struct config_item * ret = NULL;
+@@ -211,6 +219,7 @@
+       return ret;
+ }
  
- #endif
++
+ EXPORT_SYMBOL(config_item_init);
+ EXPORT_SYMBOL(config_group_init);
+ EXPORT_SYMBOL(config_item_get);
+diff -Nurb linux-2.6.22-590/fs/drop_caches.c linux-2.6.22-570/fs/drop_caches.c
+--- linux-2.6.22-590/fs/drop_caches.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/drop_caches.c  2007-07-08 19:32:17.000000000 -0400
+@@ -3,7 +3,6 @@
+  */
  
-diff -Nurb linux-2.6.22-570/include/asm-x86_64/kdebug.h linux-2.6.22-590/include/asm-x86_64/kdebug.h
---- linux-2.6.22-570/include/asm-x86_64/kdebug.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-x86_64/kdebug.h       2008-01-02 13:56:37.000000000 -0500
-@@ -23,6 +23,7 @@
-       DIE_CALL,
-       DIE_NMI_IPI,
-       DIE_PAGE_FAULT,
-+      DIE_PAGE_FAULT_NO_CONTEXT,
- };
+ #include <linux/kernel.h>
+-#include <linux/module.h>
+ #include <linux/mm.h>
+ #include <linux/fs.h>
+ #include <linux/writeback.h>
+@@ -13,7 +12,7 @@
+ /* A global variable is a bit ugly, but it keeps the code simple */
+ int sysctl_drop_caches;
  
- extern void printk_address(unsigned long address);
-diff -Nurb linux-2.6.22-570/include/asm-x86_64/kgdb.h linux-2.6.22-590/include/asm-x86_64/kgdb.h
---- linux-2.6.22-570/include/asm-x86_64/kgdb.h 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/asm-x86_64/kgdb.h 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,52 @@
-+#ifdef __KERNEL__
-+#ifndef _ASM_KGDB_H_
-+#define _ASM_KGDB_H_
-+
-+/*
-+ * Copyright (C) 2001-2004 Amit S. Kale
-+ */
-+
-+#include <asm-generic/kgdb.h>
-+
-+/*
-+ *  Note that this register image is in a different order than
-+ *  the register image that Linux produces at interrupt time.
-+ *
-+ *  Linux's register image is defined by struct pt_regs in ptrace.h.
-+ *  Just why GDB uses a different order is a historical mystery.
-+ */
-+#define _RAX  0
-+#define _RDX  1
-+#define _RCX  2
-+#define _RBX  3
-+#define _RSI  4
-+#define _RDI  5
-+#define _RBP  6
-+#define _RSP  7
-+#define _R8   8
-+#define _R9   9
-+#define _R10  10
-+#define _R11  11
-+#define _R12  12
-+#define _R13  13
-+#define _R14  14
-+#define _R15  15
-+#define _PC   16
-+#define _PS   17
-+
-+/* Number of bytes of registers.  */
-+#define NUMREGBYTES           ((_PS+1)*8)
-+#define NUMCRITREGBYTES               (8 * 8)         /* 8 registers. */
-+
-+#ifndef __ASSEMBLY__
-+/* BUFMAX defines the maximum number of characters in inbound/outbound
-+ * buffers at least NUMREGBYTES*2 are needed for register packets, and
-+ * a longer buffer is needed to list all threads. */
-+#define BUFMAX                        1024
-+#define BREAKPOINT()          asm("   int $3");
-+#define CHECK_EXCEPTION_STACK() ((&__get_cpu_var(init_tss))[0].ist[0])
-+#define BREAK_INSTR_SIZE      1
-+#define CACHE_FLUSH_IS_SAFE   1
-+#endif                                /* !__ASSEMBLY__ */
-+#endif                                /* _ASM_KGDB_H_ */
-+#endif                                /* __KERNEL__ */
-diff -Nurb linux-2.6.22-570/include/asm-x86_64/page.h linux-2.6.22-590/include/asm-x86_64/page.h
---- linux-2.6.22-570/include/asm-x86_64/page.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-x86_64/page.h 2008-01-02 13:56:37.000000000 -0500
-@@ -48,7 +48,8 @@
- #define clear_user_page(page, vaddr, pg)      clear_page(page)
- #define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
+-void drop_pagecache_sb(struct super_block *sb)
++static void drop_pagecache_sb(struct super_block *sb)
+ {
+       struct inode *inode;
  
--#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
-+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
-+      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
- #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
- /*
-  * These are used to make use of C type-checking..
-diff -Nurb linux-2.6.22-570/include/asm-x86_64/proto.h linux-2.6.22-590/include/asm-x86_64/proto.h
---- linux-2.6.22-570/include/asm-x86_64/proto.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-x86_64/proto.h        2008-01-02 13:56:37.000000000 -0500
-@@ -75,8 +75,6 @@
- extern void early_quirks(void);
- extern void check_efer(void);
+@@ -25,7 +24,6 @@
+       }
+       spin_unlock(&inode_lock);
+ }
+-EXPORT_SYMBOL(drop_pagecache_sb);
  
--extern int unhandled_signal(struct task_struct *tsk, int sig);
--
- extern void select_idle_routine(const struct cpuinfo_x86 *c);
+ void drop_pagecache(void)
+ {
+diff -Nurb linux-2.6.22-590/fs/ecryptfs/inode.c linux-2.6.22-570/fs/ecryptfs/inode.c
+--- linux-2.6.22-590/fs/ecryptfs/inode.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ecryptfs/inode.c       2008-01-23 19:16:04.000000000 -0500
+@@ -280,9 +280,7 @@
+       int rc = 0;
+       struct dentry *lower_dir_dentry;
+       struct dentry *lower_dentry;
+-      struct dentry *dentry_save;
+       struct vfsmount *lower_mnt;
+-      struct vfsmount *mnt_save;
+       char *encoded_name;
+       unsigned int encoded_namelen;
+       struct ecryptfs_crypt_stat *crypt_stat = NULL;
+@@ -310,13 +308,9 @@
+       }
+       ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen "
+                       "= [%d]\n", encoded_name, encoded_namelen);
+-      dentry_save = nd->dentry;
+-      mnt_save = nd->mnt;
+-      lower_dentry = lookup_one_len_nd(encoded_name, lower_dir_dentry,
+-                                       (encoded_namelen - 1), nd);
++      lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry,
++                                    encoded_namelen - 1);
+       kfree(encoded_name);
+-      nd->mnt = mnt_save;
+-      nd->dentry = dentry_save;
+       if (IS_ERR(lower_dentry)) {
+               ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n");
+               rc = PTR_ERR(lower_dentry);
+diff -Nurb linux-2.6.22-590/fs/ecryptfs/main.c linux-2.6.22-570/fs/ecryptfs/main.c
+--- linux-2.6.22-590/fs/ecryptfs/main.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ecryptfs/main.c        2007-07-08 19:32:17.000000000 -0400
+@@ -840,6 +840,8 @@
+               goto out;
+       }
+       kobj_set_kset_s(&ecryptfs_subsys, fs_subsys);
++      sysfs_attr_version.attr.owner = THIS_MODULE;
++      sysfs_attr_version_str.attr.owner = THIS_MODULE;
+       rc = do_sysfs_registration();
+       if (rc) {
+               printk(KERN_ERR "sysfs registration failed\n");
+diff -Nurb linux-2.6.22-590/fs/exec.c linux-2.6.22-570/fs/exec.c
+--- linux-2.6.22-590/fs/exec.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/exec.c 2008-01-23 19:16:04.000000000 -0500
+@@ -861,9 +861,9 @@
+       current->sas_ss_sp = current->sas_ss_size = 0;
  
- extern unsigned long table_start, table_end;
-diff -Nurb linux-2.6.22-570/include/asm-x86_64/system.h linux-2.6.22-590/include/asm-x86_64/system.h
---- linux-2.6.22-570/include/asm-x86_64/system.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-x86_64/system.h       2008-01-02 13:56:37.000000000 -0500
-@@ -22,7 +22,9 @@
+       if (current->euid == current->uid && current->egid == current->gid)
+-              set_dumpable(current->mm, 1);
++              current->mm->dumpable = 1;
+       else
+-              set_dumpable(current->mm, suid_dumpable);
++              current->mm->dumpable = suid_dumpable;
  
- /* Save restore flags to clear handle leaking NT */
- #define switch_to(prev,next,last) \
--      asm volatile(SAVE_CONTEXT                                                   \
-+       asm volatile(".globl __switch_to_begin\n\t"                                \
-+                   "__switch_to_begin:\n\t"                                     \
-+                   SAVE_CONTEXT                                                 \
-                    "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */       \
-                    "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */    \
-                    "call __switch_to\n\t"                                       \
-@@ -34,6 +36,8 @@
-                    "movq %%rax,%%rdi\n\t"                                       \
-                    "jc   ret_from_fork\n\t"                                     \
-                    RESTORE_CONTEXT                                                \
-+                   "\n.globl __switch_to_end\n\t"                               \
-+                   "__switch_to_end:\n\t"                                       \
-                    : "=a" (last)                                                \
-                    : [next] "S" (next), [prev] "D" (prev),                      \
-                      [threadrsp] "i" (offsetof(struct task_struct, thread.rsp)), \
-diff -Nurb linux-2.6.22-570/include/asm-x86_64/unistd.h linux-2.6.22-590/include/asm-x86_64/unistd.h
---- linux-2.6.22-570/include/asm-x86_64/unistd.h       2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/asm-x86_64/unistd.h       2008-01-02 13:56:37.000000000 -0500
-@@ -630,6 +630,8 @@
- __SYSCALL(__NR_timerfd, sys_timerfd)
- #define __NR_eventfd          284
- __SYSCALL(__NR_eventfd, sys_eventfd)
-+#define __NR_fallocate                284
-+__SYSCALL(__NR_fallocate, sys_fallocate)
+       name = bprm->filename;
  
- #ifndef __NO_STUBS
- #define __ARCH_WANT_OLD_READDIR
-diff -Nurb linux-2.6.22-570/include/asm-x86_64/unwind.h linux-2.6.22-590/include/asm-x86_64/unwind.h
---- linux-2.6.22-570/include/asm-x86_64/unwind.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/asm-x86_64/unwind.h       2008-01-02 13:56:37.000000000 -0500
-@@ -1,6 +1,100 @@
- #ifndef _ASM_X86_64_UNWIND_H
- #define _ASM_X86_64_UNWIND_H
+@@ -889,12 +889,12 @@
  
-+/*
-+ * Copyright (C) 2002-2006 Novell, Inc.
-+ *    Jan Beulich <jbeulich@novell.com>
-+ * This code is released under version 2 of the GNU GPL.
-+ */
-+
-+#ifdef CONFIG_STACK_UNWIND
-+
-+#include <linux/sched.h>
-+#include <asm/ptrace.h>
-+#include <asm/uaccess.h>
-+#include <asm/vsyscall.h>
-+
-+struct unwind_frame_info
-+{
-+      struct pt_regs regs;
-+      struct task_struct *task;
-+      unsigned call_frame:1;
-+};
-+
-+#define UNW_PC(frame)        (frame)->regs.rip
-+#define UNW_SP(frame)        (frame)->regs.rsp
-+#ifdef CONFIG_FRAME_POINTER
-+#define UNW_FP(frame)        (frame)->regs.rbp
-+#define FRAME_RETADDR_OFFSET 8
-+#define FRAME_LINK_OFFSET    0
-+#define STACK_BOTTOM(tsk)    (((tsk)->thread.rsp0 - 1) & ~(THREAD_SIZE - 1))
-+#define STACK_TOP(tsk)       ((tsk)->thread.rsp0)
-+#endif
-+/* Might need to account for the special exception and interrupt handling
-+   stacks here, since normally
-+      EXCEPTION_STACK_ORDER < THREAD_ORDER < IRQSTACK_ORDER,
-+   but the construct is needed only for getting across the stack switch to
-+   the interrupt stack - thus considering the IRQ stack itself is unnecessary,
-+   and the overhead of comparing against all exception handling stacks seems
-+   not desirable. */
-+#define STACK_LIMIT(ptr)     (((ptr) - 1) & ~(THREAD_SIZE - 1))
-+
-+#define UNW_REGISTER_INFO \
-+      PTREGS_INFO(rax), \
-+      PTREGS_INFO(rdx), \
-+      PTREGS_INFO(rcx), \
-+      PTREGS_INFO(rbx), \
-+      PTREGS_INFO(rsi), \
-+      PTREGS_INFO(rdi), \
-+      PTREGS_INFO(rbp), \
-+      PTREGS_INFO(rsp), \
-+      PTREGS_INFO(r8), \
-+      PTREGS_INFO(r9), \
-+      PTREGS_INFO(r10), \
-+      PTREGS_INFO(r11), \
-+      PTREGS_INFO(r12), \
-+      PTREGS_INFO(r13), \
-+      PTREGS_INFO(r14), \
-+      PTREGS_INFO(r15), \
-+      PTREGS_INFO(rip)
-+
-+#define UNW_DEFAULT_RA(raItem, dataAlign) \
-+      ((raItem).where == Memory && \
-+       !((raItem).value * (dataAlign) + 8))
-+
-+static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
-+                                            /*const*/ struct pt_regs *regs)
-+{
-+      info->regs = *regs;
-+}
-+
-+static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
-+{
-+      extern const char thread_return[];
-+
-+      memset(&info->regs, 0, sizeof(info->regs));
-+      info->regs.rip = (unsigned long)thread_return;
-+      info->regs.cs = __KERNEL_CS;
-+      __get_user(info->regs.rbp, (unsigned long *)info->task->thread.rsp);
-+      info->regs.rsp = info->task->thread.rsp;
-+      info->regs.ss = __KERNEL_DS;
-+}
-+
-+extern int arch_unwind_init_running(struct unwind_frame_info *,
-+                                    int (*callback)(struct unwind_frame_info *,
-+                                                    void *arg),
-+                                    void *arg);
-+
-+static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
-+{
-+      return user_mode(&info->regs)
-+             || (long)info->regs.rip >= 0
-+             || (info->regs.rip >= VSYSCALL_START && info->regs.rip < VSYSCALL_END)
-+             || (long)info->regs.rsp >= 0;
-+}
-+
-+#else
-+
- #define UNW_PC(frame) ((void)(frame), 0UL)
- #define UNW_SP(frame) ((void)(frame), 0UL)
+       if (bprm->e_uid != current->euid || bprm->e_gid != current->egid) {
+               suid_keys(current);
+-              set_dumpable(current->mm, suid_dumpable);
++              current->mm->dumpable = suid_dumpable;
+               current->pdeath_signal = 0;
+       } else if (file_permission(bprm->file, MAY_READ) ||
+                       (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
+               suid_keys(current);
+-              set_dumpable(current->mm, suid_dumpable);
++              current->mm->dumpable = suid_dumpable;
+       }
  
-@@ -9,4 +103,6 @@
-       return 0;
+       /* An exec changes our domain. We are no longer part of the thread
+@@ -1486,55 +1486,6 @@
+       return core_waiters;
  }
  
-+#endif
-+
- #endif /* _ASM_X86_64_UNWIND_H */
-diff -Nurb linux-2.6.22-570/include/linux/Kbuild linux-2.6.22-590/include/linux/Kbuild
---- linux-2.6.22-570/include/linux/Kbuild      2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/Kbuild      2008-01-02 13:56:37.000000000 -0500
-@@ -91,7 +91,6 @@
- header-y += in_route.h
- header-y += ioctl.h
- header-y += ipmi_msgdefs.h
--header-y += ip_mp_alg.h
- header-y += ipsec.h
- header-y += ipx.h
- header-y += irda.h
-diff -Nurb linux-2.6.22-570/include/linux/acpi.h linux-2.6.22-590/include/linux/acpi.h
---- linux-2.6.22-570/include/linux/acpi.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/acpi.h      2008-01-02 13:56:37.000000000 -0500
-@@ -206,11 +206,8 @@
- {
-       return max_cstate;
- }
--static inline void acpi_set_cstate_limit(unsigned int new_limit)
+-/*
+- * set_dumpable converts traditional three-value dumpable to two flags and
+- * stores them into mm->flags.  It modifies lower two bits of mm->flags, but
+- * these bits are not changed atomically.  So get_dumpable can observe the
+- * intermediate state.  To avoid doing unexpected behavior, get get_dumpable
+- * return either old dumpable or new one by paying attention to the order of
+- * modifying the bits.
+- *
+- * dumpable |   mm->flags (binary)
+- * old  new | initial interim  final
+- * ---------+-----------------------
+- *  0    1  |   00      01      01
+- *  0    2  |   00      10(*)   11
+- *  1    0  |   01      00      00
+- *  1    2  |   01      11      11
+- *  2    0  |   11      10(*)   00
+- *  2    1  |   11      11      01
+- *
+- * (*) get_dumpable regards interim value of 10 as 11.
+- */
+-void set_dumpable(struct mm_struct *mm, int value)
 -{
--      max_cstate = new_limit;
--      return;
+-      switch (value) {
+-      case 0:
+-              clear_bit(MMF_DUMPABLE, &mm->flags);
+-              smp_wmb();
+-              clear_bit(MMF_DUMP_SECURELY, &mm->flags);
+-              break;
+-      case 1:
+-              set_bit(MMF_DUMPABLE, &mm->flags);
+-              smp_wmb();
+-              clear_bit(MMF_DUMP_SECURELY, &mm->flags);
+-              break;
+-      case 2:
+-              set_bit(MMF_DUMP_SECURELY, &mm->flags);
+-              smp_wmb();
+-              set_bit(MMF_DUMPABLE, &mm->flags);
+-              break;
+-      }
 -}
-+extern void (*acpi_do_set_cstate_limit)(void);
-+extern void acpi_set_cstate_limit(unsigned int new_limit);
- #else
- static inline unsigned int acpi_get_cstate_limit(void) { return 0; }
- static inline void acpi_set_cstate_limit(unsigned int new_limit) { return; }
-diff -Nurb linux-2.6.22-570/include/linux/async_tx.h linux-2.6.22-590/include/linux/async_tx.h
---- linux-2.6.22-570/include/linux/async_tx.h  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/linux/async_tx.h  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,156 @@
-+/*
-+ * Copyright Â© 2006, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ */
-+#ifndef _ASYNC_TX_H_
-+#define _ASYNC_TX_H_
-+#include <linux/dmaengine.h>
-+#include <linux/spinlock.h>
-+#include <linux/interrupt.h>
-+
-+/**
-+ * dma_chan_ref - object used to manage dma channels received from the
-+ *   dmaengine core.
-+ * @chan - the channel being tracked
-+ * @node - node for the channel to be placed on async_tx_master_list
-+ * @rcu - for list_del_rcu
-+ * @count - number of times this channel is listed in the pool
-+ *    (for channels with multiple capabiities)
-+ */
-+struct dma_chan_ref {
-+      struct dma_chan *chan;
-+      struct list_head node;
-+      struct rcu_head rcu;
-+      atomic_t count;
-+};
-+
-+/**
-+ * async_tx_flags - modifiers for the async_* calls
-+ * @ASYNC_TX_XOR_ZERO_DST: this flag must be used for xor operations where the
-+ * the destination address is not a source.  The asynchronous case handles this
-+ * implicitly, the synchronous case needs to zero the destination block.
-+ * @ASYNC_TX_XOR_DROP_DST: this flag must be used if the destination address is
-+ * also one of the source addresses.  In the synchronous case the destination
-+ * address is an implied source, whereas the asynchronous case it must be listed
-+ * as a source.  The destination address must be the first address in the source
-+ * array.
-+ * @ASYNC_TX_ASSUME_COHERENT: skip cache maintenance operations
-+ * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a
-+ * dependency chain
-+ * @ASYNC_TX_DEP_ACK: ack the dependency descriptor.  Useful for chaining.
-+ * @ASYNC_TX_KMAP_SRC: if the transaction is to be performed synchronously
-+ * take an atomic mapping (KM_USER0) on the source page(s)
-+ * @ASYNC_TX_KMAP_DST: if the transaction is to be performed synchronously
-+ * take an atomic mapping (KM_USER0) on the dest page(s)
-+ */
-+enum async_tx_flags {
-+      ASYNC_TX_XOR_ZERO_DST    = (1 << 0),
-+      ASYNC_TX_XOR_DROP_DST    = (1 << 1),
-+      ASYNC_TX_ASSUME_COHERENT = (1 << 2),
-+      ASYNC_TX_ACK             = (1 << 3),
-+      ASYNC_TX_DEP_ACK         = (1 << 4),
-+      ASYNC_TX_KMAP_SRC        = (1 << 5),
-+      ASYNC_TX_KMAP_DST        = (1 << 6),
-+};
-+
-+#ifdef CONFIG_DMA_ENGINE
-+void async_tx_issue_pending_all(void);
-+enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
-+void async_tx_run_dependencies(struct dma_async_tx_descriptor *tx);
-+struct dma_chan *
-+async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
-+      enum dma_transaction_type tx_type);
-+#else
-+static inline void async_tx_issue_pending_all(void)
-+{
-+      do { } while (0);
-+}
-+
-+static inline enum dma_status
-+dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
-+{
-+      return DMA_SUCCESS;
-+}
-+
-+static inline void
-+async_tx_run_dependencies(struct dma_async_tx_descriptor *tx,
-+      struct dma_chan *host_chan)
-+{
-+      do { } while (0);
-+}
-+
-+static inline struct dma_chan *
-+async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
-+      enum dma_transaction_type tx_type)
-+{
-+      return NULL;
-+}
-+#endif
-+
-+/**
-+ * async_tx_sync_epilog - actions to take if an operation is run synchronously
-+ * @flags: async_tx flags
-+ * @depend_tx: transaction depends on depend_tx
-+ * @cb_fn: function to call when the transaction completes
-+ * @cb_fn_param: parameter to pass to the callback routine
-+ */
-+static inline void
-+async_tx_sync_epilog(unsigned long flags,
-+      struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_fn_param)
-+{
-+      if (cb_fn)
-+              cb_fn(cb_fn_param);
-+
-+      if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
-+              async_tx_ack(depend_tx);
-+}
-+
-+void
-+async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
-+      enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_fn_param);
-+
-+struct dma_async_tx_descriptor *
-+async_xor(struct page *dest, struct page **src_list, unsigned int offset,
-+      int src_cnt, size_t len, enum async_tx_flags flags,
-+      struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_fn_param);
-+
-+struct dma_async_tx_descriptor *
-+async_xor_zero_sum(struct page *dest, struct page **src_list,
-+      unsigned int offset, int src_cnt, size_t len,
-+      u32 *result, enum async_tx_flags flags,
-+      struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_fn_param);
-+
-+struct dma_async_tx_descriptor *
-+async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
-+      unsigned int src_offset, size_t len, enum async_tx_flags flags,
-+      struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_fn_param);
-+
-+struct dma_async_tx_descriptor *
-+async_memset(struct page *dest, int val, unsigned int offset,
-+      size_t len, enum async_tx_flags flags,
-+      struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_fn_param);
-+
-+struct dma_async_tx_descriptor *
-+async_trigger_callback(enum async_tx_flags flags,
-+      struct dma_async_tx_descriptor *depend_tx,
-+      dma_async_tx_callback cb_fn, void *cb_fn_param);
-+#endif /* _ASYNC_TX_H_ */
-diff -Nurb linux-2.6.22-570/include/linux/configfs.h linux-2.6.22-590/include/linux/configfs.h
---- linux-2.6.22-570/include/linux/configfs.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/configfs.h  2008-01-02 13:56:37.000000000 -0500
-@@ -75,7 +75,6 @@
- extern void config_item_init_type_name(struct config_item *item,
-                                      const char *name,
-                                      struct config_item_type *type);
--extern void config_item_cleanup(struct config_item *);
+-
+-int get_dumpable(struct mm_struct *mm)
+-{
+-      int ret;
+-
+-      ret = mm->flags & 0x3;
+-      return (ret >= 2) ? 2 : ret;
+-}
+-
+ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
+ {
+       char corename[CORENAME_MAX_SIZE + 1];
+@@ -1553,7 +1504,7 @@
+       if (!binfmt || !binfmt->core_dump)
+               goto fail;
+       down_write(&mm->mmap_sem);
+-      if (!get_dumpable(mm)) {
++      if (!mm->dumpable) {
+               up_write(&mm->mmap_sem);
+               goto fail;
+       }
+@@ -1563,11 +1514,11 @@
+        *      process nor do we know its entire history. We only know it
+        *      was tainted so we dump it as root in mode 2.
+        */
+-      if (get_dumpable(mm) == 2) {    /* Setuid core dump mode */
++      if (mm->dumpable == 2) {        /* Setuid core dump mode */
+               flag = O_EXCL;          /* Stop rewrite attacks */
+               current->fsuid = 0;     /* Dump root private */
+       }
+-      set_dumpable(mm, 0);
++      mm->dumpable = 0;
  
- extern struct config_item * config_item_get(struct config_item *);
- extern void config_item_put(struct config_item *);
-@@ -157,6 +156,7 @@
-       struct config_item *(*make_item)(struct config_group *group, const char *name);
-       struct config_group *(*make_group)(struct config_group *group, const char *name);
-       int (*commit_item)(struct config_item *item);
-+      void (*disconnect_notify)(struct config_group *group, struct config_item *item);
-       void (*drop_item)(struct config_group *group, struct config_item *item);
- };
+       retval = coredump_wait(exit_code);
+       if (retval < 0)
+diff -Nurb linux-2.6.22-590/fs/gfs2/ops_address.c linux-2.6.22-570/fs/gfs2/ops_address.c
+--- linux-2.6.22-590/fs/gfs2/ops_address.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/gfs2/ops_address.c     2007-07-08 19:32:17.000000000 -0400
+@@ -250,7 +250,7 @@
+               if (file) {
+                       gf = file->private_data;
+                       if (test_bit(GFF_EXLOCK, &gf->f_flags))
+-                              /* gfs2_sharewrite_fault has grabbed the ip->i_gl already */
++                              /* gfs2_sharewrite_nopage has grabbed the ip->i_gl already */
+                               goto skip_lock;
+               }
+               gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh);
+diff -Nurb linux-2.6.22-590/fs/gfs2/ops_file.c linux-2.6.22-570/fs/gfs2/ops_file.c
+--- linux-2.6.22-590/fs/gfs2/ops_file.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/gfs2/ops_file.c        2007-07-08 19:32:17.000000000 -0400
+@@ -364,8 +364,6 @@
+       else
+               vma->vm_ops = &gfs2_vm_ops_private;
  
-@@ -175,6 +175,11 @@
- int configfs_register_subsystem(struct configfs_subsystem *subsys);
void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
+-      vma->vm_flags |= VM_CAN_INVALIDATE|VM_CAN_NONLINEAR;
+-
      gfs2_glock_dq_uninit(&i_gh);
  
-+/* These functions can sleep and can alloc with GFP_KERNEL */
-+/* WARNING: These cannot be called underneath configfs callbacks!! */
-+int configfs_depend_item(struct configfs_subsystem *subsys, struct config_item *target);
-+void configfs_undepend_item(struct configfs_subsystem *subsys, struct config_item *target);
-+
- #endif  /* __KERNEL__ */
+       return error;
+diff -Nurb linux-2.6.22-590/fs/gfs2/ops_vm.c linux-2.6.22-570/fs/gfs2/ops_vm.c
+--- linux-2.6.22-590/fs/gfs2/ops_vm.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/gfs2/ops_vm.c  2007-07-08 19:32:17.000000000 -0400
+@@ -27,13 +27,13 @@
+ #include "trans.h"
+ #include "util.h"
  
- #endif /* _CONFIGFS_H_ */
-diff -Nurb linux-2.6.22-570/include/linux/container.h linux-2.6.22-590/include/linux/container.h
---- linux-2.6.22-570/include/linux/container.h 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/linux/container.h 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,295 @@
-+#ifndef _LINUX_CONTAINER_H
-+#define _LINUX_CONTAINER_H
-+/*
-+ *  container interface
-+ *
-+ *  Copyright (C) 2003 BULL SA
-+ *  Copyright (C) 2004-2006 Silicon Graphics, Inc.
-+ *
-+ */
-+
-+#include <linux/sched.h>
-+#include <linux/kref.h>
-+#include <linux/cpumask.h>
-+#include <linux/nodemask.h>
-+#include <linux/rcupdate.h>
-+
-+#ifdef CONFIG_CONTAINERS
-+
-+struct containerfs_root;
-+struct inode;
-+
-+extern int container_init_early(void);
-+extern int container_init(void);
-+extern void container_init_smp(void);
-+extern void container_lock(void);
-+extern void container_unlock(void);
-+extern void container_fork(struct task_struct *p);
-+extern void container_fork_callbacks(struct task_struct *p);
-+extern void container_exit(struct task_struct *p, int run_callbacks);
-+
-+extern struct file_operations proc_container_operations;
-+
-+/* Define the enumeration of all container subsystems */
-+#define SUBSYS(_x) _x ## _subsys_id,
-+enum container_subsys_id {
-+#include <linux/container_subsys.h>
-+      CONTAINER_SUBSYS_COUNT
-+};
-+#undef SUBSYS
-+
-+/* Per-subsystem/per-container state maintained by the system. */
-+struct container_subsys_state {
-+      /* The container that this subsystem is attached to. Useful
-+       * for subsystems that want to know about the container
-+       * hierarchy structure */
-+      struct container *container;
-+
-+      /* State maintained by the container system to allow
-+       * subsystems to be "busy". Should be accessed via css_get()
-+       * and css_put() */
-+
-+      atomic_t refcnt;
-+};
-+
-+/*
-+ * Call css_get() to hold a reference on the container;
-+ *
-+ */
-+
-+static inline void css_get(struct container_subsys_state *css)
-+{
-+      atomic_inc(&css->refcnt);
-+}
-+/*
-+ * css_put() should be called to release a reference taken by
-+ * css_get()
-+ */
-+void css_put(struct container_subsys_state *css);
-+
-+struct container {
-+      unsigned long flags;            /* "unsigned long" so bitops work */
-+
-+      /* count users of this container. >0 means busy, but doesn't
-+       * necessarily indicate the number of tasks in the
-+       * container */
-+      atomic_t count;
-+
-+      /*
-+       * We link our 'sibling' struct into our parent's 'children'.
-+       * Our children link their 'sibling' into our 'children'.
-+       */
-+      struct list_head sibling;       /* my parent's children */
-+      struct list_head children;      /* my children */
-+
-+      struct container *parent;       /* my parent */
-+      struct dentry *dentry;          /* container fs entry */
-+
-+      /* Private pointers for each registered subsystem */
-+      struct container_subsys_state *subsys[CONTAINER_SUBSYS_COUNT];
-+
-+      struct containerfs_root *root;
-+      struct container *top_container;
-+
-+      /*
-+       * List of cg_container_links pointing at css_groups with
-+       * tasks in this container. Protected by css_group_lock
-+       */
-+      struct list_head css_groups;
-+
-+      /*
-+       * Linked list running through all containers that can
-+       * potentially be reaped by the release agent. Protected by
-+       * container_mutex
-+       */
-+      struct list_head release_list;
-+};
-+
-+/* A css_group is a structure holding pointers to a set of
-+ * container_subsys_state objects. This saves space in the task struct
-+ * object and speeds up fork()/exit(), since a single inc/dec and a
-+ * list_add()/del() can bump the reference count on the entire
-+ * container set for a task.
-+ */
-+
-+struct css_group {
-+
-+      /* Reference count */
-+      struct kref ref;
-+
-+      /*
-+       * List running through all container groups. Protected by
-+       * css_group_lock
-+       */
-+      struct list_head list;
-+
-+      /*
-+       * List running through all tasks using this container
-+       * group. Protected by css_group_lock
-+       */
-+      struct list_head tasks;
-+
-+      /*
-+       * List of cg_container_link objects on link chains from
-+       * containers referenced from this css_group. Protected by
-+       * css_group_lock
-+       */
-+      struct list_head cg_links;
-+
-+      /* Set of subsystem states, one for each subsystem. NULL for
-+       * subsystems that aren't part of this hierarchy. These
-+       * pointers reduce the number of dereferences required to get
-+       * from a task to its state for a given container, but result
-+       * in increased space usage if tasks are in wildly different
-+       * groupings across different hierarchies. This array is
-+       * immutable after creation */
-+      struct container_subsys_state *subsys[CONTAINER_SUBSYS_COUNT];
-+
-+};
-+
-+/* struct cftype:
-+ *
-+ * The files in the container filesystem mostly have a very simple read/write
-+ * handling, some common function will take care of it. Nevertheless some cases
-+ * (read tasks) are special and therefore I define this structure for every
-+ * kind of file.
-+ *
-+ *
-+ * When reading/writing to a file:
-+ *    - the container to use in file->f_dentry->d_parent->d_fsdata
-+ *    - the 'cftype' of the file is file->f_dentry->d_fsdata
-+ */
-+
-+#define MAX_CFTYPE_NAME 64
-+struct cftype {
-+      /* By convention, the name should begin with the name of the
-+       * subsystem, followed by a period */
-+      char name[MAX_CFTYPE_NAME];
-+      int private;
-+      int (*open) (struct inode *inode, struct file *file);
-+      ssize_t (*read) (struct container *cont, struct cftype *cft,
-+                       struct file *file,
-+                       char __user *buf, size_t nbytes, loff_t *ppos);
-+      /*
-+       * read_uint() is a shortcut for the common case of returning a
-+       * single integer. Use it in place of read()
-+       */
-+      u64 (*read_uint) (struct container *cont, struct cftype *cft);
-+      ssize_t (*write) (struct container *cont, struct cftype *cft,
-+                        struct file *file,
-+                        const char __user *buf, size_t nbytes, loff_t *ppos);
-+      int (*release) (struct inode *inode, struct file *file);
-+};
-+
-+/* Add a new file to the given container directory. Should only be
-+ * called by subsystems from within a populate() method */
-+int container_add_file(struct container *cont, const struct cftype *cft);
-+
-+/* Add a set of new files to the given container directory. Should
-+ * only be called by subsystems from within a populate() method */
-+int container_add_files(struct container *cont, const struct cftype cft[],
-+                      int count);
-+
-+int container_is_removed(const struct container *cont);
-+
-+int container_path(const struct container *cont, char *buf, int buflen);
-+
-+int container_task_count(const struct container *cont);
-+
-+/* Return true if the container is a descendant of the current container */
-+int container_is_descendant(const struct container *cont);
-+
-+/* Container subsystem type. See Documentation/containers.txt for details */
-+
-+struct container_subsys {
-+      int (*create)(struct container_subsys *ss,
-+                    struct container *cont);
-+      void (*destroy)(struct container_subsys *ss, struct container *cont);
-+      int (*can_attach)(struct container_subsys *ss,
-+                        struct container *cont, struct task_struct *tsk);
-+      void (*attach)(struct container_subsys *ss, struct container *cont,
-+                      struct container *old_cont, struct task_struct *tsk);
-+      void (*fork)(struct container_subsys *ss, struct task_struct *task);
-+      void (*exit)(struct container_subsys *ss, struct task_struct *task);
-+      int (*populate)(struct container_subsys *ss,
-+                      struct container *cont);
-+      void (*post_clone)(struct container_subsys *ss, struct container *cont);
-+      void (*bind)(struct container_subsys *ss, struct container *root);
-+      int subsys_id;
-+      int active;
-+      int early_init;
-+#define MAX_CONTAINER_TYPE_NAMELEN 32
-+      const char *name;
-+
-+      /* Protected by RCU */
-+      struct containerfs_root *root;
-+
-+      struct list_head sibling;
-+
-+      void *private;
-+};
-+
-+#define SUBSYS(_x) extern struct container_subsys _x ## _subsys;
-+#include <linux/container_subsys.h>
-+#undef SUBSYS
-+
-+static inline struct container_subsys_state *container_subsys_state(
-+      struct container *cont, int subsys_id)
-+{
-+      return cont->subsys[subsys_id];
-+}
-+
-+static inline struct container_subsys_state *task_subsys_state(
-+      struct task_struct *task, int subsys_id)
-+{
-+      return rcu_dereference(task->containers->subsys[subsys_id]);
-+}
-+
-+static inline struct container* task_container(struct task_struct *task,
-+                                             int subsys_id)
-+{
-+      return task_subsys_state(task, subsys_id)->container;
-+}
-+
-+int container_path(const struct container *cont, char *buf, int buflen);
-+
-+int container_clone(struct task_struct *tsk, struct container_subsys *ss);
-+
-+/* A container_iter should be treated as an opaque object */
-+struct container_iter {
-+      struct list_head *cg_link;
-+      struct list_head *task;
-+};
-+
-+/* To iterate across the tasks in a container:
-+ *
-+ * 1) call container_iter_start to intialize an iterator
-+ *
-+ * 2) call container_iter_next() to retrieve member tasks until it
-+ *    returns NULL or until you want to end the iteration
-+ *
-+ * 3) call container_iter_end() to destroy the iterator.
-+ */
-+void container_iter_start(struct container *cont, struct container_iter *it);
-+struct task_struct *container_iter_next(struct container *cont,
-+                                      struct container_iter *it);
-+void container_iter_end(struct container *cont, struct container_iter *it);
-+
-+void container_set_release_agent_path(struct container_subsys *ss,
-+                                    const char *path);
-+
-+#else /* !CONFIG_CONTAINERS */
-+
-+static inline int container_init_early(void) { return 0; }
-+static inline int container_init(void) { return 0; }
-+static inline void container_init_smp(void) {}
-+static inline void container_fork(struct task_struct *p) {}
-+static inline void container_fork_callbacks(struct task_struct *p) {}
-+static inline void container_exit(struct task_struct *p, int callbacks) {}
-+
-+static inline void container_lock(void) {}
-+static inline void container_unlock(void) {}
-+
-+#endif /* !CONFIG_CONTAINERS */
-+
-+#endif /* _LINUX_CONTAINER_H */
-diff -Nurb linux-2.6.22-570/include/linux/container_subsys.h linux-2.6.22-590/include/linux/container_subsys.h
---- linux-2.6.22-570/include/linux/container_subsys.h  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/linux/container_subsys.h  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,32 @@
-+/* Add subsystem definitions of the form SUBSYS(<name>) in this
-+ * file. Surround each one by a line of comment markers so that
-+ * patches don't collide
-+ */
-+
-+/* */
-+
-+/* */
-+
-+#ifdef CONFIG_CONTAINER_CPUACCT
-+SUBSYS(cpuacct)
-+#endif
-+
-+/* */
-+
-+#ifdef CONFIG_CPUSETS
-+SUBSYS(cpuset)
-+#endif
-+
-+/* */
-+
-+#ifdef CONFIG_CONTAINER_DEBUG
-+SUBSYS(debug)
-+#endif
-+
-+/* */
-+
-+#ifdef CONFIG_CONTAINER_NS
-+SUBSYS(ns)
-+#endif
-+
-+/* */
-diff -Nurb linux-2.6.22-570/include/linux/cpu_acct.h linux-2.6.22-590/include/linux/cpu_acct.h
---- linux-2.6.22-570/include/linux/cpu_acct.h  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/linux/cpu_acct.h  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,14 @@
-+
-+#ifndef _LINUX_CPU_ACCT_H
-+#define _LINUX_CPU_ACCT_H
-+
-+#include <linux/container.h>
-+#include <asm/cputime.h>
-+
-+#ifdef CONFIG_CONTAINER_CPUACCT
-+extern void cpuacct_charge(struct task_struct *, cputime_t cputime);
-+#else
-+static void inline cpuacct_charge(struct task_struct *p, cputime_t cputime) {}
-+#endif
-+
-+#endif
-diff -Nurb linux-2.6.22-570/include/linux/cpuidle.h linux-2.6.22-590/include/linux/cpuidle.h
---- linux-2.6.22-570/include/linux/cpuidle.h   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/linux/cpuidle.h   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,189 @@
-+/*
-+ * cpuidle.h - a generic framework for CPU idle power management
-+ *
-+ * (C) 2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
-+ *          Shaohua Li <shaohua.li@intel.com>
-+ *          Adam Belay <abelay@novell.com>
-+ *
-+ * This code is licenced under the GPL.
-+ */
-+
-+#ifndef _LINUX_CPUIDLE_H
-+#define _LINUX_CPUIDLE_H
-+
-+#include <linux/percpu.h>
-+#include <linux/list.h>
-+#include <linux/module.h>
-+#include <linux/kobject.h>
-+#include <linux/completion.h>
-+
-+#define CPUIDLE_STATE_MAX     8
-+#define CPUIDLE_NAME_LEN      16
-+
-+struct cpuidle_device;
-+
-+
-+/****************************
-+ * CPUIDLE DEVICE INTERFACE *
-+ ****************************/
-+
-+struct cpuidle_state {
-+      char            name[CPUIDLE_NAME_LEN];
-+      void            *driver_data;
-+
-+      unsigned int    flags;
-+      unsigned int    exit_latency; /* in US */
-+      unsigned int    power_usage; /* in mW */
-+      unsigned int    target_residency; /* in US */
-+
-+      unsigned int    usage;
-+      unsigned int    time; /* in US */
-+
-+      int (*enter)    (struct cpuidle_device *dev,
-+                       struct cpuidle_state *state);
-+};
-+
-+/* Idle State Flags */
-+#define CPUIDLE_FLAG_TIME_VALID       (0x01) /* is residency time measurable? */
-+#define CPUIDLE_FLAG_CHECK_BM (0x02) /* BM activity will exit state */
-+#define CPUIDLE_FLAG_SHALLOW  (0x10) /* low latency, minimal savings */
-+#define CPUIDLE_FLAG_BALANCED (0x20) /* medium latency, moderate savings */
-+#define CPUIDLE_FLAG_DEEP     (0x40) /* high latency, large savings */
-+
-+#define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
-+
-+/**
-+ * cpuidle_get_statedata - retrieves private driver state data
-+ * @state: the state
-+ */
-+static inline void * cpuidle_get_statedata(struct cpuidle_state *state)
-+{
-+      return state->driver_data;
-+}
-+
-+/**
-+ * cpuidle_set_statedata - stores private driver state data
-+ * @state: the state
-+ * @data: the private data
-+ */
-+static inline void
-+cpuidle_set_statedata(struct cpuidle_state *state, void *data)
-+{
-+      state->driver_data = data;
-+}
-+
-+struct cpuidle_state_kobj {
-+      struct cpuidle_state *state;
-+      struct completion kobj_unregister;
-+      struct kobject kobj;
-+};
-+
-+struct cpuidle_device {
-+      unsigned int            status;
-+      int                     cpu;
-+
-+      int                     last_residency;
-+      int                     state_count;
-+      struct cpuidle_state    states[CPUIDLE_STATE_MAX];
-+      struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
-+      struct cpuidle_state    *last_state;
-+
-+      struct list_head        device_list;
-+      struct kobject          kobj;
-+      struct completion       kobj_unregister;
-+      void                    *governor_data;
-+};
-+
-+DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
-+
-+/* Device Status Flags */
-+#define CPUIDLE_STATUS_DETECTED                (0x1)
-+#define CPUIDLE_STATUS_DRIVER_ATTACHED         (0x2)
-+#define CPUIDLE_STATUS_GOVERNOR_ATTACHED (0x4)
-+#define CPUIDLE_STATUS_DOIDLE          (CPUIDLE_STATUS_DETECTED | \
-+                                        CPUIDLE_STATUS_DRIVER_ATTACHED | \
-+                                        CPUIDLE_STATUS_GOVERNOR_ATTACHED)
-+
-+/**
-+ * cpuidle_get_last_residency - retrieves the last state's residency time
-+ * @dev: the target CPU
-+ *
-+ * NOTE: this value is invalid if CPUIDLE_FLAG_TIME_VALID isn't set
-+ */
-+static inline int cpuidle_get_last_residency(struct cpuidle_device *dev)
-+{
-+      return dev->last_residency;
-+}
-+
-+
-+/****************************
-+ * CPUIDLE DRIVER INTERFACE *
-+ ****************************/
-+
-+struct cpuidle_driver {
-+      char                    name[CPUIDLE_NAME_LEN];
-+      struct list_head        driver_list;
-+
-+      int  (*init)            (struct cpuidle_device *dev);
-+      void (*exit)            (struct cpuidle_device *dev);
-+      int  (*redetect)        (struct cpuidle_device *dev);
-+
-+      int  (*bm_check)        (void);
-+
-+      struct module           *owner;
-+};
-+
-+#ifdef CONFIG_CPU_IDLE
-+
-+extern int cpuidle_register_driver(struct cpuidle_driver *drv);
-+extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
-+extern int cpuidle_force_redetect(struct cpuidle_device *dev, struct cpuidle_driver *drv);
-+extern int cpuidle_force_redetect_devices(struct cpuidle_driver *drv);
-+
-+#else
-+
-+static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
-+{return 0;}
-+static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }
-+static inline int cpuidle_force_redetect(struct cpuidle_device *dev, struct cpuidle_driver *drv)
-+{return 0;}
-+static inline int cpuidle_force_redetect_devices(struct cpuidle_driver *drv)
-+{return 0;}
-+
-+#endif
-+
-+/******************************
-+ * CPUIDLE GOVERNOR INTERFACE *
-+ ******************************/
-+
-+struct cpuidle_governor {
-+      char                    name[CPUIDLE_NAME_LEN];
-+      struct list_head        governor_list;
-+
-+      int  (*init)            (struct cpuidle_device *dev);
-+      void (*exit)            (struct cpuidle_device *dev);
-+      void (*scan)            (struct cpuidle_device *dev);
-+
-+      int  (*select)          (struct cpuidle_device *dev);
-+      void (*reflect)         (struct cpuidle_device *dev);
-+
-+      struct module           *owner;
-+};
-+
-+#ifdef CONFIG_CPU_IDLE
-+
-+extern int cpuidle_register_governor(struct cpuidle_governor *gov);
-+extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
-+extern int cpuidle_get_bm_activity(void);
-+
-+#else
-+
-+static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
-+{return 0;}
-+static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { }
-+static inline int cpuidle_get_bm_activity(void)
-+{return 0;}
-+
-+#endif
-+
-+#endif /* _LINUX_CPUIDLE_H */
-diff -Nurb linux-2.6.22-570/include/linux/cpuset.h linux-2.6.22-590/include/linux/cpuset.h
---- linux-2.6.22-570/include/linux/cpuset.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/cpuset.h    2008-01-02 13:56:37.000000000 -0500
-@@ -11,6 +11,7 @@
- #include <linux/sched.h>
- #include <linux/cpumask.h>
- #include <linux/nodemask.h>
-+#include <linux/container.h>
+-static struct page *gfs2_private_fault(struct vm_area_struct *vma,
+-                                      struct fault_data *fdata)
++static struct page *gfs2_private_nopage(struct vm_area_struct *area,
++                                      unsigned long address, int *type)
+ {
+-      struct gfs2_inode *ip = GFS2_I(vma->vm_file->f_mapping->host);
++      struct gfs2_inode *ip = GFS2_I(area->vm_file->f_mapping->host);
+       set_bit(GIF_PAGED, &ip->i_flags);
+-      return filemap_fault(vma, fdata);
++      return filemap_nopage(area, address, type);
+ }
+ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
+@@ -104,14 +104,16 @@
+       return error;
+ }
+-static struct page *gfs2_sharewrite_fault(struct vm_area_struct *vma,
+-                                              struct fault_data *fdata)
++static struct page *gfs2_sharewrite_nopage(struct vm_area_struct *area,
++                                         unsigned long address, int *type)
+ {
+-      struct file *file = vma->vm_file;
++      struct file *file = area->vm_file;
+       struct gfs2_file *gf = file->private_data;
+       struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
+       struct gfs2_holder i_gh;
+       struct page *result = NULL;
++      unsigned long index = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) +
++                            area->vm_pgoff;
+       int alloc_required;
+       int error;
+@@ -122,27 +124,21 @@
+       set_bit(GIF_PAGED, &ip->i_flags);
+       set_bit(GIF_SW_PAGED, &ip->i_flags);
+-      error = gfs2_write_alloc_required(ip,
+-                                      (u64)fdata->pgoff << PAGE_CACHE_SHIFT,
++      error = gfs2_write_alloc_required(ip, (u64)index << PAGE_CACHE_SHIFT,
+                                         PAGE_CACHE_SIZE, &alloc_required);
+-      if (error) {
+-              fdata->type = VM_FAULT_OOM; /* XXX: are these right? */
++      if (error)
+               goto out;
+-      }
  
- #ifdef CONFIG_CPUSETS
+       set_bit(GFF_EXLOCK, &gf->f_flags);
+-      result = filemap_fault(vma, fdata);
++      result = filemap_nopage(area, address, type);
+       clear_bit(GFF_EXLOCK, &gf->f_flags);
+-      if (!result)
++      if (!result || result == NOPAGE_OOM)
+               goto out;
  
-@@ -19,8 +20,6 @@
- extern int cpuset_init_early(void);
- extern int cpuset_init(void);
- extern void cpuset_init_smp(void);
--extern void cpuset_fork(struct task_struct *p);
--extern void cpuset_exit(struct task_struct *p);
- extern cpumask_t cpuset_cpus_allowed(struct task_struct *p);
- extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
- #define cpuset_current_mems_allowed (current->mems_allowed)
-@@ -75,13 +74,13 @@
+       if (alloc_required) {
+               error = alloc_page_backing(ip, result);
+               if (error) {
+-                      if (vma->vm_flags & VM_CAN_INVALIDATE)
+-                              unlock_page(result);
+                       page_cache_release(result);
+-                      fdata->type = VM_FAULT_OOM;
+                       result = NULL;
+                       goto out;
+               }
+@@ -156,10 +152,10 @@
+ }
  
- extern void cpuset_track_online_nodes(void);
+ struct vm_operations_struct gfs2_vm_ops_private = {
+-      .fault = gfs2_private_fault,
++      .nopage = gfs2_private_nopage,
+ };
  
-+extern int current_cpuset_is_being_rebound(void);
-+
- #else /* !CONFIG_CPUSETS */
+ struct vm_operations_struct gfs2_vm_ops_sharewrite = {
+-      .fault = gfs2_sharewrite_fault,
++      .nopage = gfs2_sharewrite_nopage,
+ };
  
- static inline int cpuset_init_early(void) { return 0; }
- static inline int cpuset_init(void) { return 0; }
- static inline void cpuset_init_smp(void) {}
--static inline void cpuset_fork(struct task_struct *p) {}
--static inline void cpuset_exit(struct task_struct *p) {}
+diff -Nurb linux-2.6.22-590/fs/inode.c linux-2.6.22-570/fs/inode.c
+--- linux-2.6.22-590/fs/inode.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/inode.c        2008-01-23 19:16:04.000000000 -0500
+@@ -149,7 +149,7 @@
+               mapping->a_ops = &empty_aops;
+               mapping->host = inode;
+               mapping->flags = 0;
+-              mapping_set_gfp_mask(mapping, GFP_HIGHUSER_PAGECACHE);
++              mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
+               mapping->assoc_mapping = NULL;
+               mapping->backing_dev_info = &default_backing_dev_info;
  
- static inline cpumask_t cpuset_cpus_allowed(struct task_struct *p)
+@@ -525,13 +525,7 @@
+  *    new_inode       - obtain an inode
+  *    @sb: superblock
+  *
+- *    Allocates a new inode for given superblock. The default gfp_mask
+- *    for allocations related to inode->i_mapping is GFP_HIGHUSER_PAGECACHE.
+- *    If HIGHMEM pages are unsuitable or it is known that pages allocated
+- *    for the page cache are not reclaimable or migratable,
+- *    mapping_set_gfp_mask() must be called with suitable flags on the
+- *    newly created inode's mapping
+- *
++ *    Allocates a new inode for given superblock.
+  */
+ struct inode *new_inode(struct super_block *sb)
+ {
+diff -Nurb linux-2.6.22-590/fs/jbd/journal.c linux-2.6.22-570/fs/jbd/journal.c
+--- linux-2.6.22-590/fs/jbd/journal.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/jbd/journal.c  2007-07-08 19:32:17.000000000 -0400
+@@ -1710,7 +1710,7 @@
+       journal_head_cache = kmem_cache_create("journal_head",
+                               sizeof(struct journal_head),
+                               0,              /* offset */
+-                              SLAB_TEMPORARY, /* flags */
++                              0,              /* flags */
+                               NULL,           /* ctor */
+                               NULL);          /* dtor */
+       retval = 0;
+@@ -2007,7 +2007,7 @@
+       jbd_handle_cache = kmem_cache_create("journal_handle",
+                               sizeof(handle_t),
+                               0,              /* offset */
+-                              SLAB_TEMPORARY, /* flags */
++                              0,              /* flags */
+                               NULL,           /* ctor */
+                               NULL);          /* dtor */
+       if (jbd_handle_cache == NULL) {
+diff -Nurb linux-2.6.22-590/fs/jbd/revoke.c linux-2.6.22-570/fs/jbd/revoke.c
+--- linux-2.6.22-590/fs/jbd/revoke.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/jbd/revoke.c   2007-07-08 19:32:17.000000000 -0400
+@@ -169,17 +169,13 @@
  {
-@@ -146,6 +145,11 @@
+       revoke_record_cache = kmem_cache_create("revoke_record",
+                                          sizeof(struct jbd_revoke_record_s),
+-                                         0,
+-                                         SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY,
+-                                         NULL, NULL);
++                                         0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+       if (revoke_record_cache == 0)
+               return -ENOMEM;
  
- static inline void cpuset_track_online_nodes(void) {}
+       revoke_table_cache = kmem_cache_create("revoke_table",
+                                          sizeof(struct jbd_revoke_table_s),
+-                                         0,
+-                                         SLAB_TEMPORARY,
+-                                         NULL, NULL);
++                                         0, 0, NULL, NULL);
+       if (revoke_table_cache == 0) {
+               kmem_cache_destroy(revoke_record_cache);
+               revoke_record_cache = NULL;
+diff -Nurb linux-2.6.22-590/fs/jffs2/background.c linux-2.6.22-570/fs/jffs2/background.c
+--- linux-2.6.22-590/fs/jffs2/background.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/jffs2/background.c     2007-07-08 19:32:17.000000000 -0400
+@@ -81,7 +81,6 @@
  
-+static inline int current_cpuset_is_being_rebound(void)
-+{
-+      return 0;
-+}
+       set_user_nice(current, 10);
+-      set_freezable();
+       for (;;) {
+               allow_signal(SIGHUP);
+diff -Nurb linux-2.6.22-590/fs/lockd/host.c linux-2.6.22-570/fs/lockd/host.c
+--- linux-2.6.22-590/fs/lockd/host.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/lockd/host.c   2007-07-08 19:32:17.000000000 -0400
+@@ -161,9 +161,15 @@
+        */
+       nsm_unmonitor(host);
+-      clnt = host->h_rpcclnt;
+-      if (clnt != NULL)
+-              rpc_shutdown_client(clnt);
++      if ((clnt = host->h_rpcclnt) != NULL) {
++              if (atomic_read(&clnt->cl_users)) {
++                      printk(KERN_WARNING
++                              "lockd: active RPC handle\n");
++                      clnt->cl_dead = 1;
++              } else {
++                      rpc_destroy_client(host->h_rpcclnt);
++              }
++      }
+       kfree(host);
+ }
+diff -Nurb linux-2.6.22-590/fs/lockd/mon.c linux-2.6.22-570/fs/lockd/mon.c
+--- linux-2.6.22-590/fs/lockd/mon.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/lockd/mon.c    2007-07-08 19:32:17.000000000 -0400
+@@ -61,7 +61,6 @@
+                       status);
+       else
+               status = 0;
+-      rpc_shutdown_client(clnt);
+  out:
+       return status;
+ }
+@@ -139,6 +138,7 @@
+               .program        = &nsm_program,
+               .version        = SM_VERSION,
+               .authflavor     = RPC_AUTH_NULL,
++              .flags          = (RPC_CLNT_CREATE_ONESHOT),
+       };
+       return rpc_create(&args);
+diff -Nurb linux-2.6.22-590/fs/lockd/svc.c linux-2.6.22-570/fs/lockd/svc.c
+--- linux-2.6.22-590/fs/lockd/svc.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/lockd/svc.c    2007-07-08 19:32:17.000000000 -0400
+@@ -25,7 +25,6 @@
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
+ #include <linux/mutex.h>
+-#include <linux/freezer.h>
+ #include <linux/sunrpc/types.h>
+ #include <linux/sunrpc/stats.h>
+@@ -120,11 +119,13 @@
+       complete(&lockd_start_done);
+       daemonize("lockd");
+-      set_freezable();
+       /* Process request with signals blocked, but allow SIGKILL.  */
+       allow_signal(SIGKILL);
++      /* kick rpciod */
++      rpciod_up();
 +
- #endif /* !CONFIG_CPUSETS */
+       dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
  
- #endif /* _LINUX_CPUSET_H */
-diff -Nurb linux-2.6.22-570/include/linux/device.h linux-2.6.22-590/include/linux/device.h
---- linux-2.6.22-570/include/linux/device.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/device.h    2008-01-02 13:56:37.000000000 -0500
-@@ -200,6 +200,8 @@
+       if (!nlm_timeout)
+@@ -201,6 +202,9 @@
+       /* Exit the RPC thread */
+       svc_exit_thread(rqstp);
  
-       int     (*suspend)(struct device *, pm_message_t state);
-       int     (*resume)(struct device *);
++      /* release rpciod */
++      rpciod_down();
 +
-+      const struct shadow_dir_operations *shadow_ops;
- };
+       /* Release module */
+       unlock_kernel();
+       module_put_and_exit(0);
+diff -Nurb linux-2.6.22-590/fs/namei.c linux-2.6.22-570/fs/namei.c
+--- linux-2.6.22-590/fs/namei.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/namei.c        2008-01-23 19:16:04.000000000 -0500
+@@ -1386,8 +1386,7 @@
+       return 0;
+ }
  
- extern int __must_check class_register(struct class *);
-@@ -238,7 +240,6 @@
-  * @devt: for internal use by the driver core only.
-  * @node: for internal use by the driver core only.
-  * @kobj: for internal use by the driver core only.
-- * @devt_attr: for internal use by the driver core only.
-  * @groups: optional additional groups to be created
-  * @dev: if set, a symlink to the struct device is created in the sysfs
-  * directory for this struct class device.
-@@ -263,8 +264,6 @@
-       struct kobject          kobj;
-       struct class            * class;        /* required */
-       dev_t                   devt;           /* dev_t, creates the sysfs "dev" */
--      struct class_device_attribute *devt_attr;
--      struct class_device_attribute uevent_attr;
-       struct device           * dev;          /* not necessary, but nice to have */
-       void                    * class_data;   /* class-specific data */
-       struct class_device     *parent;        /* parent of this child device, if there is one */
-@@ -419,8 +418,6 @@
-       struct device_type      *type;
-       unsigned                is_registered:1;
-       unsigned                uevent_suppress:1;
--      struct device_attribute uevent_attr;
--      struct device_attribute *devt_attr;
+-struct dentry *lookup_one_len_nd(const char *name, struct dentry *base, 
+-                               int len, struct nameidata *nd)
++struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
+ {
+       int err;
+       struct qstr this;
+@@ -1395,7 +1394,7 @@
+       err = __lookup_one_len(name, &this, base, len);
+       if (err)
+               return ERR_PTR(err);
+-      return __lookup_hash(&this, base, nd);
++      return __lookup_hash(&this, base, NULL);
+ }
  
-       struct semaphore        sem;    /* semaphore to synchronize calls to
-                                        * its driver.
-diff -Nurb linux-2.6.22-570/include/linux/dmaengine.h linux-2.6.22-590/include/linux/dmaengine.h
---- linux-2.6.22-570/include/linux/dmaengine.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/dmaengine.h 2008-01-02 13:56:37.000000000 -0500
-@@ -21,29 +21,40 @@
- #ifndef DMAENGINE_H
- #define DMAENGINE_H
+ struct dentry *lookup_one_len_kern(const char *name, struct dentry *base, int len)
+@@ -3087,7 +3086,7 @@
+ EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
+ EXPORT_SYMBOL(getname);
+ EXPORT_SYMBOL(lock_rename);
+-EXPORT_SYMBOL(lookup_one_len_nd);
++EXPORT_SYMBOL(lookup_one_len);
+ EXPORT_SYMBOL(page_follow_link_light);
+ EXPORT_SYMBOL(page_put_link);
+ EXPORT_SYMBOL(page_readlink);
+diff -Nurb linux-2.6.22-590/fs/namespace.c linux-2.6.22-570/fs/namespace.c
+--- linux-2.6.22-590/fs/namespace.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/namespace.c    2008-01-23 19:16:04.000000000 -0500
+@@ -1538,7 +1538,7 @@
  
--#ifdef CONFIG_DMA_ENGINE
--
- #include <linux/device.h>
- #include <linux/uio.h>
- #include <linux/kref.h>
- #include <linux/completion.h>
- #include <linux/rcupdate.h>
-+#include <linux/dma-mapping.h>
+       new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
+       if (!new_ns)
+-              return ERR_PTR(-ENOMEM);
++              return NULL;
  
- /**
-- * enum dma_event - resource PNP/power managment events
-+ * enum dma_state - resource PNP/power managment state
-  * @DMA_RESOURCE_SUSPEND: DMA device going into low power state
-  * @DMA_RESOURCE_RESUME: DMA device returning to full power
-- * @DMA_RESOURCE_ADDED: DMA device added to the system
-+ * @DMA_RESOURCE_AVAILABLE: DMA device available to the system
-  * @DMA_RESOURCE_REMOVED: DMA device removed from the system
+       atomic_set(&new_ns->count, 1);
+       INIT_LIST_HEAD(&new_ns->list);
+@@ -1552,7 +1552,7 @@
+       if (!new_ns->root) {
+               up_write(&namespace_sem);
+               kfree(new_ns);
+-              return ERR_PTR(-ENOMEM);;
++              return NULL;
+       }
+       spin_lock(&vfsmount_lock);
+       list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
+@@ -1597,7 +1597,7 @@
+       return new_ns;
+ }
+-struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
++struct mnt_namespace *copy_mnt_ns(int flags, struct mnt_namespace *ns,
+               struct fs_struct *new_fs)
+ {
+       struct mnt_namespace *new_ns;
+diff -Nurb linux-2.6.22-590/fs/ncpfs/mmap.c linux-2.6.22-570/fs/ncpfs/mmap.c
+--- linux-2.6.22-590/fs/ncpfs/mmap.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ncpfs/mmap.c   2007-07-08 19:32:17.000000000 -0400
+@@ -25,8 +25,8 @@
+ /*
+  * Fill in the supplied page for mmap
   */
--enum dma_event {
-+enum dma_state {
-       DMA_RESOURCE_SUSPEND,
-       DMA_RESOURCE_RESUME,
--      DMA_RESOURCE_ADDED,
-+      DMA_RESOURCE_AVAILABLE,
-       DMA_RESOURCE_REMOVED,
- };
+-static struct page* ncp_file_mmap_fault(struct vm_area_struct *area,
+-                                              struct fault_data *fdata)
++static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
++                                   unsigned long address, int *type)
+ {
+       struct file *file = area->vm_file;
+       struct dentry *dentry = file->f_path.dentry;
+@@ -40,17 +40,15 @@
  
- /**
-+ * enum dma_state_client - state of the channel in the client
-+ * @DMA_ACK: client would like to use, or was using this channel
-+ * @DMA_DUP: client has already seen this channel, or is not using this channel
-+ * @DMA_NAK: client does not want to see any more channels
-+ */
-+enum dma_state_client {
-+      DMA_ACK,
-+      DMA_DUP,
-+      DMA_NAK,
-+};
-+
-+/**
-  * typedef dma_cookie_t - an opaque DMA cookie
-  *
-  * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code
-@@ -65,6 +76,31 @@
+       page = alloc_page(GFP_HIGHUSER); /* ncpfs has nothing against high pages
+                  as long as recvmsg and memset works on it */
+-      if (!page) {
+-              fdata->type = VM_FAULT_OOM;
+-              return NULL;
+-      }
++      if (!page)
++              return page;
+       pg_addr = kmap(page);
+-      pos = fdata->pgoff << PAGE_SHIFT;
++      address &= PAGE_MASK;
++      pos = address - area->vm_start + (area->vm_pgoff << PAGE_SHIFT);
+       count = PAGE_SIZE;
+-      if (fdata->address + PAGE_SIZE > area->vm_end) {
+-              WARN_ON(1); /* shouldn't happen? */
+-              count = area->vm_end - fdata->address;
++      if (address + PAGE_SIZE > area->vm_end) {
++              count = area->vm_end - address;
+       }
+       /* what we can read in one go */
+       bufsize = NCP_SERVER(inode)->buffer_size;
+@@ -93,14 +91,15 @@
+        * fetches from the network, here the analogue of disk.
+        * -- wli
+        */
+-      fdata->type = VM_FAULT_MAJOR;
++      if (type)
++              *type = VM_FAULT_MAJOR;
+       count_vm_event(PGMAJFAULT);
+       return page;
+ }
+ static struct vm_operations_struct ncp_file_mmap =
+ {
+-      .fault = ncp_file_mmap_fault,
++      .nopage = ncp_file_mmap_nopage,
  };
  
- /**
-+ * enum dma_transaction_type - DMA transaction types/indexes
-+ */
-+enum dma_transaction_type {
-+      DMA_MEMCPY,
-+      DMA_XOR,
-+      DMA_PQ_XOR,
-+      DMA_DUAL_XOR,
-+      DMA_PQ_UPDATE,
-+      DMA_ZERO_SUM,
-+      DMA_PQ_ZERO_SUM,
-+      DMA_MEMSET,
-+      DMA_MEMCPY_CRC32C,
-+      DMA_INTERRUPT,
-+};
-+
-+/* last transaction type for creation of the capabilities mask */
-+#define DMA_TX_TYPE_END (DMA_INTERRUPT + 1)
+@@ -124,7 +123,6 @@
+               return -EFBIG;
+       vma->vm_ops = &ncp_file_mmap;
+-      vma->vm_flags |= VM_CAN_INVALIDATE;
+       file_accessed(file);
+       return 0;
+ }
+diff -Nurb linux-2.6.22-590/fs/nfs/callback.c linux-2.6.22-570/fs/nfs/callback.c
+--- linux-2.6.22-590/fs/nfs/callback.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/callback.c 2007-07-08 19:32:17.000000000 -0400
+@@ -14,7 +14,6 @@
+ #include <linux/sunrpc/svcsock.h>
+ #include <linux/nfs_fs.h>
+ #include <linux/mutex.h>
+-#include <linux/freezer.h>
+ #include <net/inet_sock.h>
+@@ -68,7 +67,6 @@
+       daemonize("nfsv4-svc");
+       /* Process request with signals blocked, but allow SIGKILL.  */
+       allow_signal(SIGKILL);
+-      set_freezable();
+       complete(&nfs_callback_info.started);
+diff -Nurb linux-2.6.22-590/fs/nfs/client.c linux-2.6.22-570/fs/nfs/client.c
+--- linux-2.6.22-590/fs/nfs/client.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/client.c   2008-01-23 19:16:04.000000000 -0500
+@@ -102,10 +102,19 @@
+                                          int nfsversion)
+ {
+       struct nfs_client *clp;
++      int error;
+       if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
+               goto error_0;
++      error = rpciod_up();
++      if (error < 0) {
++              dprintk("%s: couldn't start rpciod! Error = %d\n",
++                              __FUNCTION__, error);
++              goto error_1;
++      }
++      __set_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
 +
-+/**
-+ * dma_cap_mask_t - capabilities bitmap modeled after cpumask_t.
-+ * See linux/cpumask.h
-+ */
-+typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t;
+       if (nfsversion == 4) {
+               if (nfs_callback_up() < 0)
+                       goto error_2;
+@@ -145,6 +154,9 @@
+       if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+               nfs_callback_down();
+ error_2:
++      rpciod_down();
++      __clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
++error_1:
+       kfree(clp);
+ error_0:
+       return NULL;
+@@ -186,6 +198,9 @@
+       if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+               nfs_callback_down();
++      if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state))
++              rpciod_down();
 +
-+/**
-  * struct dma_chan_percpu - the per-CPU part of struct dma_chan
-  * @refcount: local_t used for open-coded "bigref" counting
-  * @memcpy_count: transaction counter
-@@ -80,7 +116,6 @@
+       kfree(clp->cl_hostname);
+       kfree(clp);
  
- /**
-  * struct dma_chan - devices supply DMA channels, clients use them
-- * @client: ptr to the client user of this chan, will be %NULL when unused
-  * @device: ptr to the dma device who supplies this channel, always !%NULL
-  * @cookie: last cookie value returned to client
-  * @chan_id: channel ID for sysfs
-@@ -88,12 +123,10 @@
-  * @refcount: kref, used in "bigref" slow-mode
-  * @slow_ref: indicates that the DMA channel is free
-  * @rcu: the DMA channel's RCU head
-- * @client_node: used to add this to the client chan list
-  * @device_node: used to add this to the device chan list
-  * @local: per-cpu pointer to a struct dma_chan_percpu
-  */
- struct dma_chan {
--      struct dma_client *client;
-       struct dma_device *device;
-       dma_cookie_t cookie;
+diff -Nurb linux-2.6.22-590/fs/nfs/delegation.c linux-2.6.22-570/fs/nfs/delegation.c
+--- linux-2.6.22-590/fs/nfs/delegation.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/delegation.c       2007-07-08 19:32:17.000000000 -0400
+@@ -74,7 +74,7 @@
+                       continue;
+               get_nfs_open_context(ctx);
+               spin_unlock(&inode->i_lock);
+-              err = nfs4_open_delegation_recall(ctx, state);
++              err = nfs4_open_delegation_recall(ctx->dentry, state);
+               if (err >= 0)
+                       err = nfs_delegation_claim_locks(ctx, state);
+               put_nfs_open_context(ctx);
+diff -Nurb linux-2.6.22-590/fs/nfs/delegation.h linux-2.6.22-570/fs/nfs/delegation.h
+--- linux-2.6.22-590/fs/nfs/delegation.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/delegation.h       2007-07-08 19:32:17.000000000 -0400
+@@ -39,7 +39,7 @@
  
-@@ -105,11 +138,11 @@
-       int slow_ref;
-       struct rcu_head rcu;
+ /* NFSv4 delegation-related procedures */
+ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
+-int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state);
++int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
+ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
+ int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
  
--      struct list_head client_node;
-       struct list_head device_node;
-       struct dma_chan_percpu *local;
- };
+diff -Nurb linux-2.6.22-590/fs/nfs/dir.c linux-2.6.22-570/fs/nfs/dir.c
+--- linux-2.6.22-590/fs/nfs/dir.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/dir.c      2008-01-23 19:16:04.000000000 -0500
+@@ -898,13 +898,14 @@
+       return (nd->intent.open.flags & O_EXCL) != 0;
+ }
  
-+
- void dma_chan_cleanup(struct kref *kref);
+-static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr)
++static inline int nfs_reval_fsid(struct vfsmount *mnt, struct inode *dir,
++                               struct nfs_fh *fh, struct nfs_fattr *fattr)
+ {
+       struct nfs_server *server = NFS_SERVER(dir);
  
- static inline void dma_chan_get(struct dma_chan *chan)
-@@ -134,27 +167,68 @@
+       if (!nfs_fsid_equal(&server->fsid, &fattr->fsid))
+-              /* Revalidate fsid using the parent directory */
+-              return __nfs_revalidate_inode(server, dir);
++              /* Revalidate fsid on root dir */
++              return __nfs_revalidate_inode(server, mnt->mnt_root->d_inode);
+       return 0;
+ }
+@@ -946,7 +947,7 @@
+               res = ERR_PTR(error);
+               goto out_unlock;
+       }
+-      error = nfs_reval_fsid(dir, &fattr);
++      error = nfs_reval_fsid(nd->mnt, dir, &fhandle, &fattr);
+       if (error < 0) {
+               res = ERR_PTR(error);
+               goto out_unlock;
+@@ -1246,7 +1247,7 @@
+       attr.ia_mode = mode;
+       attr.ia_valid = ATTR_MODE;
+-      if ((nd->flags & LOOKUP_CREATE) != 0)
++      if (nd && (nd->flags & LOOKUP_CREATE))
+               open_flags = nd->intent.open.flags;
+       lock_kernel();
+@@ -1746,8 +1747,8 @@
+       struct nfs_inode *nfsi;
+       struct nfs_access_entry *cache;
+-restart:
+       spin_lock(&nfs_access_lru_lock);
++restart:
+       list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) {
+               struct inode *inode;
+@@ -1772,7 +1773,6 @@
+                       clear_bit(NFS_INO_ACL_LRU_SET, &nfsi->flags);
+               }
+               spin_unlock(&inode->i_lock);
+-              spin_unlock(&nfs_access_lru_lock);
+               iput(inode);
+               goto restart;
+       }
+diff -Nurb linux-2.6.22-590/fs/nfs/direct.c linux-2.6.22-570/fs/nfs/direct.c
+--- linux-2.6.22-590/fs/nfs/direct.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/direct.c   2007-07-08 19:32:17.000000000 -0400
+@@ -266,7 +266,7 @@
+ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos)
+ {
+       struct nfs_open_context *ctx = dreq->ctx;
+-      struct inode *inode = ctx->path.dentry->d_inode;
++      struct inode *inode = ctx->dentry->d_inode;
+       size_t rsize = NFS_SERVER(inode)->rsize;
+       unsigned int pgbase;
+       int result;
+@@ -295,15 +295,10 @@
+                       break;
+               }
+               if ((unsigned)result < data->npages) {
+-                      bytes = result * PAGE_SIZE;
+-                      if (bytes <= pgbase) {
+                       nfs_direct_release_pages(data->pagevec, result);
+                       nfs_readdata_release(data);
+                       break;
+               }
+-                      bytes -= pgbase;
+-                      data->npages = result;
+-              }
+               get_dreq(dreq);
+@@ -606,7 +601,7 @@
+ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync)
+ {
+       struct nfs_open_context *ctx = dreq->ctx;
+-      struct inode *inode = ctx->path.dentry->d_inode;
++      struct inode *inode = ctx->dentry->d_inode;
+       size_t wsize = NFS_SERVER(inode)->wsize;
+       unsigned int pgbase;
+       int result;
+@@ -635,15 +630,10 @@
+                       break;
+               }
+               if ((unsigned)result < data->npages) {
+-                      bytes = result * PAGE_SIZE;
+-                      if (bytes <= pgbase) {
+                       nfs_direct_release_pages(data->pagevec, result);
+                       nfs_writedata_release(data);
+                       break;
+               }
+-                      bytes -= pgbase;
+-                      data->npages = result;
+-              }
+               get_dreq(dreq);
+@@ -773,8 +763,10 @@
+               (unsigned long) count, (long long) pos);
+       if (nr_segs != 1)
+-              goto out;
++              return -EINVAL;
++      if (count < 0)
++              goto out;
+       retval = -EFAULT;
+       if (!access_ok(VERIFY_WRITE, buf, count))
+               goto out;
+@@ -822,7 +814,7 @@
+ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
+                               unsigned long nr_segs, loff_t pos)
+ {
+-      ssize_t retval = -EINVAL;
++      ssize_t retval;
+       struct file *file = iocb->ki_filp;
+       struct address_space *mapping = file->f_mapping;
+       /* XXX: temporary */
+@@ -835,7 +827,7 @@
+               (unsigned long) count, (long long) pos);
+       if (nr_segs != 1)
+-              goto out;
++              return -EINVAL;
+       retval = generic_write_checks(file, &pos, &count, 0);
+       if (retval)
+diff -Nurb linux-2.6.22-590/fs/nfs/inode.c linux-2.6.22-570/fs/nfs/inode.c
+--- linux-2.6.22-590/fs/nfs/inode.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/inode.c    2008-01-23 19:16:04.000000000 -0500
+@@ -466,14 +466,14 @@
+       ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+       if (ctx != NULL) {
+-              ctx->path.dentry = dget(dentry);
+-              ctx->path.mnt = mntget(mnt);
++              atomic_set(&ctx->count, 1);
++              ctx->dentry = dget(dentry);
++              ctx->vfsmnt = mntget(mnt);
+               ctx->cred = get_rpccred(cred);
+               ctx->state = NULL;
+               ctx->lockowner = current->files;
+               ctx->error = 0;
+               ctx->dir_cookie = 0;
+-              kref_init(&ctx->kref);
+       }
+       return ctx;
+ }
+@@ -481,33 +481,27 @@
+ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
+ {
+       if (ctx != NULL)
+-              kref_get(&ctx->kref);
++              atomic_inc(&ctx->count);
+       return ctx;
+ }
+-static void nfs_free_open_context(struct kref *kref)
++void put_nfs_open_context(struct nfs_open_context *ctx)
+ {
+-      struct nfs_open_context *ctx = container_of(kref,
+-                      struct nfs_open_context, kref);
+-
++      if (atomic_dec_and_test(&ctx->count)) {
+               if (!list_empty(&ctx->list)) {
+-              struct inode *inode = ctx->path.dentry->d_inode;
++                      struct inode *inode = ctx->dentry->d_inode;
+                       spin_lock(&inode->i_lock);
+                       list_del(&ctx->list);
+                       spin_unlock(&inode->i_lock);
+               }
+               if (ctx->state != NULL)
+-              nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
++                      nfs4_close_state(ctx->state, ctx->mode);
+               if (ctx->cred != NULL)
+                       put_rpccred(ctx->cred);
+-      dput(ctx->path.dentry);
+-      mntput(ctx->path.mnt);
++              dput(ctx->dentry);
++              mntput(ctx->vfsmnt);
+               kfree(ctx);
+-}
+-
+-void put_nfs_open_context(struct nfs_open_context *ctx)
+-{
+-      kref_put(&ctx->kref, nfs_free_open_context);
++      }
+ }
  
  /*
-  * typedef dma_event_callback - function pointer to a DMA event callback
-- */
--typedef void (*dma_event_callback) (struct dma_client *client,
--              struct dma_chan *chan, enum dma_event event);
-+ * For each channel added to the system this routine is called for each client.
-+ * If the client would like to use the channel it returns '1' to signal (ack)
-+ * the dmaengine core to take out a reference on the channel and its
-+ * corresponding device.  A client must not 'ack' an available channel more
-+ * than once.  When a channel is removed all clients are notified.  If a client
-+ * is using the channel it must 'ack' the removal.  A client must not 'ack' a
-+ * removed channel more than once.
-+ * @client - 'this' pointer for the client context
-+ * @chan - channel to be acted upon
-+ * @state - available or removed
-+ */
-+struct dma_client;
-+typedef enum dma_state_client (*dma_event_callback) (struct dma_client *client,
-+              struct dma_chan *chan, enum dma_state state);
+@@ -983,8 +977,8 @@
+               goto out_changed;
  
- /**
-  * struct dma_client - info on the entity making use of DMA services
-  * @event_callback: func ptr to call when something happens
-- * @chan_count: number of chans allocated
-- * @chans_desired: number of chans requested. Can be +/- chan_count
-- * @lock: protects access to the channels list
-- * @channels: the list of DMA channels allocated
-+ * @cap_mask: only return channels that satisfy the requested capabilities
-+ *  a value of zero corresponds to any capability
-  * @global_node: list_head for global dma_client_list
+       server = NFS_SERVER(inode);
+-      /* Update the fsid? */
+-      if (S_ISDIR(inode->i_mode)
++      /* Update the fsid if and only if this is the root directory */
++      if (inode == inode->i_sb->s_root->d_inode
+                       && !nfs_fsid_equal(&server->fsid, &fattr->fsid))
+               server->fsid = fattr->fsid;
+@@ -1131,10 +1125,27 @@
   */
- struct dma_client {
-       dma_event_callback      event_callback;
--      unsigned int            chan_count;
--      unsigned int            chans_desired;
-+      dma_cap_mask_t          cap_mask;
-+      struct list_head        global_node;
-+};
+ void nfs4_clear_inode(struct inode *inode)
+ {
++      struct nfs_inode *nfsi = NFS_I(inode);
++
+       /* If we are holding a delegation, return it! */
+       nfs_inode_return_delegation(inode);
+       /* First call standard NFS clear_inode() code */
+       nfs_clear_inode(inode);
++      /* Now clear out any remaining state */
++      while (!list_empty(&nfsi->open_states)) {
++              struct nfs4_state *state;
++              
++              state = list_entry(nfsi->open_states.next,
++                              struct nfs4_state,
++                              inode_states);
++              dprintk("%s(%s/%Ld): found unclaimed NFSv4 state %p\n",
++                              __FUNCTION__,
++                              inode->i_sb->s_id,
++                              (long long)NFS_FILEID(inode),
++                              state);
++              BUG_ON(atomic_read(&state->count) != 1);
++              nfs4_close_state(state, state->state);
++      }
+ }
+ #endif
  
-+typedef void (*dma_async_tx_callback)(void *dma_async_param);
-+/**
-+ * struct dma_async_tx_descriptor - async transaction descriptor
-+ * @cookie: tracking cookie for this transaction, set to -EBUSY if
-+ *    this tx is sitting on a dependency list
-+ * @ack: the descriptor can not be reused until the client acknowledges
-+ *    receipt, i.e. has has a chance to establish any dependency chains
-+ * @callback: routine to call after this operation is complete
-+ * @callback_param: general parameter to pass to the callback routine
-+ * @chan: target channel for this operation
-+ * @tx_submit: execute an operation
-+ * @tx_set_dest: set a destination address in a hardware descriptor
-+ * @tx_set_src: set a source address in a hardware descriptor
-+ * @depend_list: at completion this list of transactions are submitted
-+ * @depend_node: allow this transaction to be executed after another
-+ *    transaction has completed
-+ * @parent: pointer to the next level up in the dependency chain
-+ * @lock: protect the dependency list
-+ */
-+struct dma_async_tx_descriptor {
-+      dma_cookie_t cookie;
-+      int ack;
-+      dma_async_tx_callback callback;
-+      void *callback_param;
-+      struct dma_chan *chan;
-+      dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);
-+      void (*tx_set_dest)(dma_addr_t addr,
-+              struct dma_async_tx_descriptor *tx, int index);
-+      void (*tx_set_src)(dma_addr_t addr,
-+              struct dma_async_tx_descriptor *tx, int index);
-+      struct list_head depend_list;
-+      struct list_head depend_node;
-+      struct dma_async_tx_descriptor *parent;
-       spinlock_t              lock;
--      struct list_head        channels;
--      struct list_head        global_node;
- };
+@@ -1177,11 +1188,14 @@
  
- /**
-@@ -162,141 +236,130 @@
-  * @chancnt: how many DMA channels are supported
-  * @channels: the list of struct dma_chan
-  * @global_node: list_head for global dma_device_list
-+ * @cap_mask: one or more dma_capability flags
-+ * @max_xor: maximum number of xor sources, 0 if no capability
-  * @refcount: reference count
-  * @done: IO completion struct
-  * @dev_id: unique device ID
-+ * @dev: struct device reference for dma mapping api
-  * @device_alloc_chan_resources: allocate resources and return the
-  *    number of allocated descriptors
-  * @device_free_chan_resources: release DMA channel's resources
-- * @device_memcpy_buf_to_buf: memcpy buf pointer to buf pointer
-- * @device_memcpy_buf_to_pg: memcpy buf pointer to struct page
-- * @device_memcpy_pg_to_pg: memcpy struct page/offset to struct page/offset
-- * @device_memcpy_complete: poll the status of an IOAT DMA transaction
-- * @device_memcpy_issue_pending: push appended descriptors to hardware
-+ * @device_prep_dma_memcpy: prepares a memcpy operation
-+ * @device_prep_dma_xor: prepares a xor operation
-+ * @device_prep_dma_zero_sum: prepares a zero_sum operation
-+ * @device_prep_dma_memset: prepares a memset operation
-+ * @device_prep_dma_interrupt: prepares an end of chain interrupt operation
-+ * @device_dependency_added: async_tx notifies the channel about new deps
-+ * @device_issue_pending: push pending transactions to hardware
-  */
- struct dma_device {
+       inode_init_once(&nfsi->vfs_inode);
+       spin_lock_init(&nfsi->req_lock);
++      INIT_LIST_HEAD(&nfsi->dirty);
++      INIT_LIST_HEAD(&nfsi->commit);
+       INIT_LIST_HEAD(&nfsi->open_files);
+       INIT_LIST_HEAD(&nfsi->access_cache_entry_lru);
+       INIT_LIST_HEAD(&nfsi->access_cache_inode_lru);
+       INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
+       atomic_set(&nfsi->data_updates, 0);
++      nfsi->ndirty = 0;
+       nfsi->ncommit = 0;
+       nfsi->npages = 0;
+       nfs4_init_once(nfsi);
+diff -Nurb linux-2.6.22-590/fs/nfs/mount_clnt.c linux-2.6.22-570/fs/nfs/mount_clnt.c
+--- linux-2.6.22-590/fs/nfs/mount_clnt.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/mount_clnt.c       2007-07-08 19:32:17.000000000 -0400
+@@ -69,7 +69,6 @@
+               msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT];
+       status = rpc_call_sync(mnt_clnt, &msg, 0);
+-      rpc_shutdown_client(mnt_clnt);
+       return status < 0? status : (result.status? -EACCES : 0);
+ }
  
-       unsigned int chancnt;
-       struct list_head channels;
-       struct list_head global_node;
-+      dma_cap_mask_t  cap_mask;
-+      int max_xor;
+@@ -85,7 +84,8 @@
+               .program        = &mnt_program,
+               .version        = version,
+               .authflavor     = RPC_AUTH_UNIX,
+-              .flags          = RPC_CLNT_CREATE_INTR,
++              .flags          = (RPC_CLNT_CREATE_ONESHOT |
++                                 RPC_CLNT_CREATE_INTR),
+       };
  
-       struct kref refcount;
-       struct completion done;
+       return rpc_create(&args);
+diff -Nurb linux-2.6.22-590/fs/nfs/nfs3proc.c linux-2.6.22-570/fs/nfs/nfs3proc.c
+--- linux-2.6.22-590/fs/nfs/nfs3proc.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/nfs3proc.c 2007-07-08 19:32:17.000000000 -0400
+@@ -335,7 +335,9 @@
+                * not sure this buys us anything (and I'd have
+                * to revamp the NFSv3 XDR code) */
+               status = nfs3_proc_setattr(dentry, &fattr, sattr);
+-              nfs_post_op_update_inode(dentry->d_inode, &fattr);
++              if (status == 0)
++                      nfs_setattr_update_inode(dentry->d_inode, sattr);
++              nfs_refresh_inode(dentry->d_inode, &fattr);
+               dprintk("NFS reply setattr (post-create): %d\n", status);
+       }
+       if (status != 0)
+diff -Nurb linux-2.6.22-590/fs/nfs/nfs4_fs.h linux-2.6.22-570/fs/nfs/nfs4_fs.h
+--- linux-2.6.22-590/fs/nfs/nfs4_fs.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/nfs4_fs.h  2007-07-08 19:32:17.000000000 -0400
+@@ -165,7 +165,7 @@
+ extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *);
+ extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
+ extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
+-extern int nfs4_do_close(struct path *path, struct nfs4_state *state);
++extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state);
+ extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
+ extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
+ extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
+@@ -196,7 +196,7 @@
+ extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
+ extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
+ extern void nfs4_put_open_state(struct nfs4_state *);
+-extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t);
++extern void nfs4_close_state(struct nfs4_state *, mode_t);
+ extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t);
+ extern void nfs4_schedule_state_recovery(struct nfs_client *);
+ extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
+@@ -222,7 +222,7 @@
  
-       int dev_id;
-+      struct device *dev;
+ #else
  
-       int (*device_alloc_chan_resources)(struct dma_chan *chan);
-       void (*device_free_chan_resources)(struct dma_chan *chan);
--      dma_cookie_t (*device_memcpy_buf_to_buf)(struct dma_chan *chan,
--                      void *dest, void *src, size_t len);
--      dma_cookie_t (*device_memcpy_buf_to_pg)(struct dma_chan *chan,
--                      struct page *page, unsigned int offset, void *kdata,
--                      size_t len);
--      dma_cookie_t (*device_memcpy_pg_to_pg)(struct dma_chan *chan,
--                      struct page *dest_pg, unsigned int dest_off,
--                      struct page *src_pg, unsigned int src_off, size_t len);
--      enum dma_status (*device_memcpy_complete)(struct dma_chan *chan,
-+
-+      struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(
-+              struct dma_chan *chan, size_t len, int int_en);
-+      struct dma_async_tx_descriptor *(*device_prep_dma_xor)(
-+              struct dma_chan *chan, unsigned int src_cnt, size_t len,
-+              int int_en);
-+      struct dma_async_tx_descriptor *(*device_prep_dma_zero_sum)(
-+              struct dma_chan *chan, unsigned int src_cnt, size_t len,
-+              u32 *result, int int_en);
-+      struct dma_async_tx_descriptor *(*device_prep_dma_memset)(
-+              struct dma_chan *chan, int value, size_t len, int int_en);
-+      struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
-+              struct dma_chan *chan);
-+
-+      void (*device_dependency_added)(struct dma_chan *chan);
-+      enum dma_status (*device_is_tx_complete)(struct dma_chan *chan,
-                       dma_cookie_t cookie, dma_cookie_t *last,
-                       dma_cookie_t *used);
--      void (*device_memcpy_issue_pending)(struct dma_chan *chan);
-+      void (*device_issue_pending)(struct dma_chan *chan);
- };
+-#define nfs4_close_state(a, b, c) do { } while (0)
++#define nfs4_close_state(a, b) do { } while (0)
  
- /* --- public DMA engine API --- */
+ #endif /* CONFIG_NFS_V4 */
+ #endif /* __LINUX_FS_NFS_NFS4_FS.H */
+diff -Nurb linux-2.6.22-590/fs/nfs/nfs4proc.c linux-2.6.22-570/fs/nfs/nfs4proc.c
+--- linux-2.6.22-590/fs/nfs/nfs4proc.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/nfs4proc.c 2007-07-08 19:32:17.000000000 -0400
+@@ -214,14 +214,14 @@
+ }
  
--struct dma_client *dma_async_client_register(dma_event_callback event_callback);
-+void dma_async_client_register(struct dma_client *client);
- void dma_async_client_unregister(struct dma_client *client);
--void dma_async_client_chan_request(struct dma_client *client,
--              unsigned int number);
-+void dma_async_client_chan_request(struct dma_client *client);
-+dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
-+      void *dest, void *src, size_t len);
-+dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
-+      struct page *page, unsigned int offset, void *kdata, size_t len);
-+dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
-+      struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
-+      unsigned int src_off, size_t len);
-+void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
-+      struct dma_chan *chan);
+ struct nfs4_opendata {
+-      struct kref kref;
++      atomic_t count;
+       struct nfs_openargs o_arg;
+       struct nfs_openres o_res;
+       struct nfs_open_confirmargs c_arg;
+       struct nfs_open_confirmres c_res;
+       struct nfs_fattr f_attr;
+       struct nfs_fattr dir_attr;
+-      struct path path;
++      struct dentry *dentry;
+       struct dentry *dir;
+       struct nfs4_state_owner *owner;
+       struct iattr attrs;
+@@ -230,11 +230,11 @@
+       int cancelled;
+ };
  
--/**
-- * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
-- * @chan: DMA channel to offload copy to
-- * @dest: destination address (virtual)
-- * @src: source address (virtual)
-- * @len: length
-- *
-- * Both @dest and @src must be mappable to a bus address according to the
-- * DMA mapping API rules for streaming mappings.
-- * Both @dest and @src must stay memory resident (kernel memory or locked
-- * user space pages).
-- */
--static inline dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
--      void *dest, void *src, size_t len)
-+static inline void
-+async_tx_ack(struct dma_async_tx_descriptor *tx)
+-static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
++static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
+               struct nfs4_state_owner *sp, int flags,
+               const struct iattr *attrs)
  {
--      int cpu = get_cpu();
--      per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
--      per_cpu_ptr(chan->local, cpu)->memcpy_count++;
--      put_cpu();
--
--      return chan->device->device_memcpy_buf_to_buf(chan, dest, src, len);
-+      tx->ack = 1;
+-      struct dentry *parent = dget_parent(path->dentry);
++      struct dentry *parent = dget_parent(dentry);
+       struct inode *dir = parent->d_inode;
+       struct nfs_server *server = NFS_SERVER(dir);
+       struct nfs4_opendata *p;
+@@ -245,8 +245,8 @@
+       p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
+       if (p->o_arg.seqid == NULL)
+               goto err_free;
+-      p->path.mnt = mntget(path->mnt);
+-      p->path.dentry = dget(path->dentry);
++      atomic_set(&p->count, 1);
++      p->dentry = dget(dentry);
+       p->dir = parent;
+       p->owner = sp;
+       atomic_inc(&sp->so_count);
+@@ -254,7 +254,7 @@
+       p->o_arg.open_flags = flags,
+       p->o_arg.clientid = server->nfs_client->cl_clientid;
+       p->o_arg.id = sp->so_id;
+-      p->o_arg.name = &p->path.dentry->d_name;
++      p->o_arg.name = &dentry->d_name;
+       p->o_arg.server = server;
+       p->o_arg.bitmask = server->attr_bitmask;
+       p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
+@@ -274,7 +274,6 @@
+       p->c_arg.fh = &p->o_res.fh;
+       p->c_arg.stateid = &p->o_res.stateid;
+       p->c_arg.seqid = p->o_arg.seqid;
+-      kref_init(&p->kref);
+       return p;
+ err_free:
+       kfree(p);
+@@ -283,23 +282,27 @@
+       return NULL;
  }
  
--/**
-- * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
-- * @chan: DMA channel to offload copy to
-- * @page: destination page
-- * @offset: offset in page to copy to
-- * @kdata: source address (virtual)
-- * @len: length
-- *
-- * Both @page/@offset and @kdata must be mappable to a bus address according
-- * to the DMA mapping API rules for streaming mappings.
-- * Both @page/@offset and @kdata must stay memory resident (kernel memory or
-- * locked user space pages)
-- */
--static inline dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
--      struct page *page, unsigned int offset, void *kdata, size_t len)
-+#define first_dma_cap(mask) __first_dma_cap(&(mask))
-+static inline int __first_dma_cap(const dma_cap_mask_t *srcp)
+-static void nfs4_opendata_free(struct kref *kref)
++static void nfs4_opendata_free(struct nfs4_opendata *p)
  {
--      int cpu = get_cpu();
--      per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
--      per_cpu_ptr(chan->local, cpu)->memcpy_count++;
--      put_cpu();
-+      return min_t(int, DMA_TX_TYPE_END,
-+              find_first_bit(srcp->bits, DMA_TX_TYPE_END));
-+}
+-      struct nfs4_opendata *p = container_of(kref,
+-                      struct nfs4_opendata, kref);
+-
++      if (p != NULL && atomic_dec_and_test(&p->count)) {
+               nfs_free_seqid(p->o_arg.seqid);
+               nfs4_put_state_owner(p->owner);
+               dput(p->dir);
+-      dput(p->path.dentry);
+-      mntput(p->path.mnt);
++              dput(p->dentry);
+               kfree(p);
++      }
+ }
  
--      return chan->device->device_memcpy_buf_to_pg(chan, page, offset,
--                                                   kdata, len);
-+#define next_dma_cap(n, mask) __next_dma_cap((n), &(mask))
-+static inline int __next_dma_cap(int n, const dma_cap_mask_t *srcp)
-+{
-+      return min_t(int, DMA_TX_TYPE_END,
-+              find_next_bit(srcp->bits, DMA_TX_TYPE_END, n+1));
+-static void nfs4_opendata_put(struct nfs4_opendata *p)
++/* Helper for asynchronous RPC calls */
++static int nfs4_call_async(struct rpc_clnt *clnt,
++              const struct rpc_call_ops *tk_ops, void *calldata)
+ {
+-      if (p != NULL)
+-              kref_put(&p->kref, nfs4_opendata_free);
++      struct rpc_task *task;
++
++      if (!(task = rpc_new_task(clnt, RPC_TASK_ASYNC, tk_ops, calldata)))
++              return -ENOMEM;
++      rpc_execute(task);
++      return 0;
  }
  
--/**
-- * dma_async_memcpy_pg_to_pg - offloaded copy from page to page
-- * @chan: DMA channel to offload copy to
-- * @dest_pg: destination page
-- * @dest_off: offset in page to copy to
-- * @src_pg: source page
-- * @src_off: offset in page to copy from
-- * @len: length
-- *
-- * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
-- * address according to the DMA mapping API rules for streaming mappings.
-- * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
-- * (kernel memory or locked user space pages).
-- */
--static inline dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
--      struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
--      unsigned int src_off, size_t len)
-+#define dma_cap_set(tx, mask) __dma_cap_set((tx), &(mask))
-+static inline void
-+__dma_cap_set(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp)
+ static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
+@@ -448,7 +451,7 @@
+                                               opendata->owner->so_cred,
+                                               &opendata->o_res);
+               }
+-              nfs4_close_state(&opendata->path, newstate, opendata->o_arg.open_flags);
++              nfs4_close_state(newstate, opendata->o_arg.open_flags);
+       }
+       if (newstate != state)
+               return -ESTALE;
+@@ -459,7 +462,7 @@
+  * OPEN_RECLAIM:
+  *    reclaim state on the server after a reboot.
+  */
+-static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
++static int _nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
  {
--      int cpu = get_cpu();
--      per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
--      per_cpu_ptr(chan->local, cpu)->memcpy_count++;
--      put_cpu();
-+      set_bit(tx_type, dstp->bits);
-+}
+       struct nfs_delegation *delegation = NFS_I(state->inode)->delegation;
+       struct nfs4_opendata *opendata;
+@@ -475,7 +478,7 @@
+               }
+               delegation_type = delegation->type;
+       }
+-      opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
++      opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL);
+       if (opendata == NULL)
+               return -ENOMEM;
+       opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS;
+@@ -483,17 +486,17 @@
+       nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh);
+       opendata->o_arg.u.delegation_type = delegation_type;
+       status = nfs4_open_recover(opendata, state);
+-      nfs4_opendata_put(opendata);
++      nfs4_opendata_free(opendata);
+       return status;
+ }
  
--      return chan->device->device_memcpy_pg_to_pg(chan, dest_pg, dest_off,
--                                                  src_pg, src_off, len);
-+#define dma_has_cap(tx, mask) __dma_has_cap((tx), &(mask))
-+static inline int
-+__dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp)
-+{
-+      return test_bit(tx_type, srcp->bits);
+-static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
++static int nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+ {
+       struct nfs_server *server = NFS_SERVER(state->inode);
+       struct nfs4_exception exception = { };
+       int err;
+       do {
+-              err = _nfs4_do_open_reclaim(ctx, state);
++              err = _nfs4_do_open_reclaim(sp, state, dentry);
+               if (err != -NFS4ERR_DELAY)
+                       break;
+               nfs4_handle_exception(server, err, &exception);
+@@ -509,12 +512,12 @@
+       ctx = nfs4_state_find_open_context(state);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
+-      ret = nfs4_do_open_reclaim(ctx, state);
++      ret = nfs4_do_open_reclaim(sp, state, ctx->dentry);
+       put_nfs_open_context(ctx);
+       return ret;
  }
  
-+#define for_each_dma_cap_mask(cap, mask) \
-+      for ((cap) = first_dma_cap(mask);       \
-+              (cap) < DMA_TX_TYPE_END;        \
-+              (cap) = next_dma_cap((cap), (mask)))
-+
- /**
-- * dma_async_memcpy_issue_pending - flush pending copies to HW
-+ * dma_async_issue_pending - flush pending transactions to HW
-  * @chan: target DMA channel
-  *
-  * This allows drivers to push copies to HW in batches,
-  * reducing MMIO writes where possible.
-  */
--static inline void dma_async_memcpy_issue_pending(struct dma_chan *chan)
-+static inline void dma_async_issue_pending(struct dma_chan *chan)
+-static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state)
++static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
  {
--      return chan->device->device_memcpy_issue_pending(chan);
-+      return chan->device->device_issue_pending(chan);
+       struct nfs4_state_owner  *sp  = state->owner;
+       struct nfs4_opendata *opendata;
+@@ -522,24 +525,24 @@
+       if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
+               return 0;
+-      opendata = nfs4_opendata_alloc(&ctx->path, sp, 0, NULL);
++      opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL);
+       if (opendata == NULL)
+               return -ENOMEM;
+       opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR;
+       memcpy(opendata->o_arg.u.delegation.data, state->stateid.data,
+                       sizeof(opendata->o_arg.u.delegation.data));
+       ret = nfs4_open_recover(opendata, state);
+-      nfs4_opendata_put(opendata);
++      nfs4_opendata_free(opendata);
+       return ret;
  }
  
-+#define dma_async_memcpy_issue_pending(chan) dma_async_issue_pending(chan)
-+
- /**
-- * dma_async_memcpy_complete - poll for transaction completion
-+ * dma_async_is_tx_complete - poll for transaction completion
-  * @chan: DMA channel
-  * @cookie: transaction identifier to check status of
-  * @last: returns last completed cookie, can be NULL
-@@ -306,12 +369,15 @@
-  * internal state and can be used with dma_async_is_complete() to check
-  * the status of multiple cookies without re-checking hardware state.
-  */
--static inline enum dma_status dma_async_memcpy_complete(struct dma_chan *chan,
-+static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
-       dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
+-int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state)
++int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
  {
--      return chan->device->device_memcpy_complete(chan, cookie, last, used);
-+      return chan->device->device_is_tx_complete(chan, cookie, last, used);
+       struct nfs4_exception exception = { };
+-      struct nfs_server *server = NFS_SERVER(state->inode);
++      struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+       int err;
+       do {
+-              err = _nfs4_open_delegation_recall(ctx, state);
++              err = _nfs4_open_delegation_recall(dentry, state);
+               switch (err) {
+                       case 0:
+                               return err;
+@@ -598,9 +601,9 @@
+       nfs_confirm_seqid(&data->owner->so_seqid, 0);
+       state = nfs4_opendata_to_nfs4_state(data);
+       if (state != NULL)
+-              nfs4_close_state(&data->path, state, data->o_arg.open_flags);
++              nfs4_close_state(state, data->o_arg.open_flags);
+ out_free:
+-      nfs4_opendata_put(data);
++      nfs4_opendata_free(data);
  }
  
-+#define dma_async_memcpy_complete(chan, cookie, last, used)\
-+      dma_async_is_tx_complete(chan, cookie, last, used)
-+
- /**
-  * dma_async_is_complete - test a cookie against chan state
-  * @cookie: transaction identifier to test status of
-@@ -334,6 +400,7 @@
-       return DMA_IN_PROGRESS;
+ static const struct rpc_call_ops nfs4_open_confirm_ops = {
+@@ -618,7 +621,7 @@
+       struct rpc_task *task;
+       int status;
+-      kref_get(&data->kref);
++      atomic_inc(&data->count);
+       /*
+        * If rpc_run_task() ends up calling ->rpc_release(), we
+        * want to ensure that it takes the 'error' code path.
+@@ -701,9 +704,9 @@
+       nfs_confirm_seqid(&data->owner->so_seqid, 0);
+       state = nfs4_opendata_to_nfs4_state(data);
+       if (state != NULL)
+-              nfs4_close_state(&data->path, state, data->o_arg.open_flags);
++              nfs4_close_state(state, data->o_arg.open_flags);
+ out_free:
+-      nfs4_opendata_put(data);
++      nfs4_opendata_free(data);
  }
  
-+enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
+ static const struct rpc_call_ops nfs4_open_ops = {
+@@ -724,7 +727,7 @@
+       struct rpc_task *task;
+       int status;
  
- /* --- DMA device --- */
+-      kref_get(&data->kref);
++      atomic_inc(&data->count);
+       /*
+        * If rpc_run_task() ends up calling ->rpc_release(), we
+        * want to ensure that it takes the 'error' code path.
+@@ -808,7 +811,7 @@
+  *    reclaim state on the server after a network partition.
+  *    Assumes caller holds the appropriate lock
+  */
+-static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
++static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+ {
+       struct inode *inode = state->inode;
+       struct nfs_delegation *delegation = NFS_I(inode)->delegation;
+@@ -817,34 +820,34 @@
+       int ret;
  
-@@ -362,5 +429,4 @@
-       struct dma_pinned_list *pinned_list, struct page *page,
-       unsigned int offset, size_t len);
+       if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
+-              ret = _nfs4_do_access(inode, ctx->cred, openflags);
++              ret = _nfs4_do_access(inode, sp->so_cred, openflags);
+               if (ret < 0)
+                       return ret;
+               memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid));
+               set_bit(NFS_DELEGATED_STATE, &state->flags);
+               return 0;
+       }
+-      opendata = nfs4_opendata_alloc(&ctx->path, state->owner, openflags, NULL);
++      opendata = nfs4_opendata_alloc(dentry, sp, openflags, NULL);
+       if (opendata == NULL)
+               return -ENOMEM;
+       ret = nfs4_open_recover(opendata, state);
+       if (ret == -ESTALE) {
+               /* Invalidate the state owner so we don't ever use it again */
+-              nfs4_drop_state_owner(state->owner);
+-              d_drop(ctx->path.dentry);
++              nfs4_drop_state_owner(sp);
++              d_drop(dentry);
+       }
+-      nfs4_opendata_put(opendata);
++      nfs4_opendata_free(opendata);
+       return ret;
+ }
  
--#endif /* CONFIG_DMA_ENGINE */
- #endif /* DMAENGINE_H */
-diff -Nurb linux-2.6.22-570/include/linux/etherdevice.h linux-2.6.22-590/include/linux/etherdevice.h
---- linux-2.6.22-570/include/linux/etherdevice.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/etherdevice.h       2008-01-02 13:56:37.000000000 -0500
-@@ -40,12 +40,6 @@
-                                        struct hh_cache *hh);
+-static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
++static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+ {
+-      struct nfs_server *server = NFS_SERVER(state->inode);
++      struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+       struct nfs4_exception exception = { };
+       int err;
  
- extern struct net_device *alloc_etherdev(int sizeof_priv);
--static inline void eth_copy_and_sum (struct sk_buff *dest, 
--                                   const unsigned char *src, 
--                                   int len, int base)
+       do {
+-              err = _nfs4_open_expired(ctx, state);
++              err = _nfs4_open_expired(sp, state, dentry);
+               if (err == -NFS4ERR_DELAY)
+                       nfs4_handle_exception(server, err, &exception);
+       } while (exception.retry);
+@@ -859,7 +862,7 @@
+       ctx = nfs4_state_find_open_context(state);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
+-      ret = nfs4_do_open_expired(ctx, state);
++      ret = nfs4_do_open_expired(sp, state, ctx->dentry);
+       put_nfs_open_context(ctx);
+       return ret;
+ }
+@@ -950,25 +953,9 @@
+ }
+ /*
+- * on an EXCLUSIVE create, the server should send back a bitmask with FATTR4-*
+- * fields corresponding to attributes that were used to store the verifier.
+- * Make sure we clobber those fields in the later setattr call
+- */
+-static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct iattr *sattr)
 -{
--      memcpy (dest->data, src, len);
+-      if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_ACCESS) &&
+-          !(sattr->ia_valid & ATTR_ATIME_SET))
+-              sattr->ia_valid |= ATTR_ATIME;
+-
+-      if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_MODIFY) &&
+-          !(sattr->ia_valid & ATTR_MTIME_SET))
+-              sattr->ia_valid |= ATTR_MTIME;
 -}
+-
+-/*
+  * Returns a referenced nfs4_state
+  */
+-static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
++static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
+ {
+       struct nfs4_state_owner  *sp;
+       struct nfs4_state     *state = NULL;
+@@ -988,30 +975,27 @@
+               goto err_put_state_owner;
+       down_read(&clp->cl_sem);
+       status = -ENOMEM;
+-      opendata = nfs4_opendata_alloc(path, sp, flags, sattr);
++      opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr);
+       if (opendata == NULL)
+               goto err_release_rwsem;
  
- /**
-  * is_zero_ether_addr - Determine if give Ethernet address is all zeros.
-diff -Nurb linux-2.6.22-570/include/linux/freezer.h linux-2.6.22-590/include/linux/freezer.h
---- linux-2.6.22-570/include/linux/freezer.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/freezer.h   2008-01-02 13:56:37.000000000 -0500
-@@ -115,6 +115,14 @@
-       return !!(p->flags & PF_FREEZER_SKIP);
+       status = _nfs4_proc_open(opendata);
+       if (status != 0)
+-              goto err_opendata_put;
+-
+-      if (opendata->o_arg.open_flags & O_EXCL)
+-              nfs4_exclusive_attrset(opendata, sattr);
++              goto err_opendata_free;
+       status = -ENOMEM;
+       state = nfs4_opendata_to_nfs4_state(opendata);
+       if (state == NULL)
+-              goto err_opendata_put;
++              goto err_opendata_free;
+       if (opendata->o_res.delegation_type != 0)
+               nfs_inode_set_delegation(state->inode, cred, &opendata->o_res);
+-      nfs4_opendata_put(opendata);
++      nfs4_opendata_free(opendata);
+       nfs4_put_state_owner(sp);
+       up_read(&clp->cl_sem);
+       *res = state;
+       return 0;
+-err_opendata_put:
+-      nfs4_opendata_put(opendata);
++err_opendata_free:
++      nfs4_opendata_free(opendata);
+ err_release_rwsem:
+       up_read(&clp->cl_sem);
+ err_put_state_owner:
+@@ -1022,14 +1006,14 @@
  }
  
-+/*
-+ * Tell the freezer that the current task should be frozen by it
-+ */
-+static inline void set_freezable(void)
-+{
-+      current->flags &= ~PF_NOFREEZE;
-+}
-+
- #else
- static inline int frozen(struct task_struct *p) { return 0; }
- static inline int freezing(struct task_struct *p) { return 0; }
-@@ -130,4 +138,5 @@
- static inline void freezer_do_not_count(void) {}
- static inline void freezer_count(void) {}
- static inline int freezer_should_skip(struct task_struct *p) { return 0; }
-+static inline void set_freezable(void) {}
- #endif
-diff -Nurb linux-2.6.22-570/include/linux/fs.h linux-2.6.22-590/include/linux/fs.h
---- linux-2.6.22-570/include/linux/fs.h        2008-01-02 13:56:29.000000000 -0500
-+++ linux-2.6.22-590/include/linux/fs.h        2008-01-02 13:56:37.000000000 -0500
-@@ -283,6 +283,17 @@
- #define SYNC_FILE_RANGE_WRITE         2
- #define SYNC_FILE_RANGE_WAIT_AFTER    4
  
-+/*
-+ * sys_fallocate modes
-+ * Currently sys_fallocate supports two modes:
-+ * FA_ALLOCATE  : This is the preallocate mode, using which an application/user
-+ *              may request (pre)allocation of blocks.
-+ * FA_DEALLOCATE: This is the deallocate mode, which can be used to free
-+ *              the preallocated blocks.
-+ */
-+#define FA_ALLOCATE   0x1
-+#define FA_DEALLOCATE 0x2
-+
- #ifdef __KERNEL__
+-static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred)
++static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
+ {
+       struct nfs4_exception exception = { };
+       struct nfs4_state *res;
+       int status;
  
- #include <linux/linkage.h>
-@@ -300,6 +311,7 @@
- #include <linux/init.h>
- #include <linux/pid.h>
- #include <linux/mutex.h>
-+#include <linux/sysctl.h>
+       do {
+-              status = _nfs4_do_open(dir, path, flags, sattr, cred, &res);
++              status = _nfs4_do_open(dir, dentry, flags, sattr, cred, &res);
+               if (status == 0)
+                       break;
+               /* NOTE: BAD_SEQID means the server and client disagree about the
+@@ -1117,7 +1101,6 @@
+ }
  
- #include <asm/atomic.h>
- #include <asm/semaphore.h>
-@@ -1139,6 +1151,7 @@
-       int (*flock) (struct file *, int, struct file_lock *);
-       ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
-       ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
-+      int (*revoke)(struct file *, struct address_space *);
- };
+ struct nfs4_closedata {
+-      struct path path;
+       struct inode *inode;
+       struct nfs4_state *state;
+       struct nfs_closeargs arg;
+@@ -1134,8 +1117,6 @@
+       nfs4_put_open_state(calldata->state);
+       nfs_free_seqid(calldata->arg.seqid);
+       nfs4_put_state_owner(sp);
+-      dput(calldata->path.dentry);
+-      mntput(calldata->path.mnt);
+       kfree(calldata);
+ }
  
- struct inode_operations {
-@@ -1164,6 +1177,8 @@
-       ssize_t (*listxattr) (struct dentry *, char *, size_t);
-       int (*removexattr) (struct dentry *, const char *);
-       void (*truncate_range)(struct inode *, loff_t, loff_t);
-+      long (*fallocate)(struct inode *inode, int mode, loff_t offset,
-+                        loff_t len);
-       int (*sync_flags) (struct inode *);
- };
+@@ -1228,20 +1209,18 @@
+  *
+  * NOTE: Caller must be holding the sp->so_owner semaphore!
+  */
+-int nfs4_do_close(struct path *path, struct nfs4_state *state) 
++int nfs4_do_close(struct inode *inode, struct nfs4_state *state) 
+ {
+-      struct nfs_server *server = NFS_SERVER(state->inode);
++      struct nfs_server *server = NFS_SERVER(inode);
+       struct nfs4_closedata *calldata;
+-      struct nfs4_state_owner *sp = state->owner;
+-      struct rpc_task *task;
+       int status = -ENOMEM;
  
-@@ -1809,6 +1824,13 @@
- extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
-               size_t len, unsigned int flags);
+       calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
+       if (calldata == NULL)
+               goto out;
+-      calldata->inode = state->inode;
++      calldata->inode = inode;
+       calldata->state = state;
+-      calldata->arg.fh = NFS_FH(state->inode);
++      calldata->arg.fh = NFS_FH(inode);
+       calldata->arg.stateid = &state->stateid;
+       /* Serialization for the sequence id */
+       calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
+@@ -1250,44 +1229,36 @@
+       calldata->arg.bitmask = server->attr_bitmask;
+       calldata->res.fattr = &calldata->fattr;
+       calldata->res.server = server;
+-      calldata->path.mnt = mntget(path->mnt);
+-      calldata->path.dentry = dget(path->dentry);
  
-+/* fs/revoke.c */
-+#ifdef CONFIG_MMU
-+extern int generic_file_revoke(struct file *, struct address_space *);
-+#else
-+#define generic_file_revoke NULL
-+#endif
+-      task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata);
+-      if (IS_ERR(task))
+-              return PTR_ERR(task);
+-      rpc_put_task(task);
+-      return 0;
++      status = nfs4_call_async(server->client, &nfs4_close_ops, calldata);
++      if (status == 0)
++              goto out;
 +
- extern void
- file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
- extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
-@@ -2077,5 +2099,9 @@
- { }
- #endif        /* CONFIG_SECURITY */
++      nfs_free_seqid(calldata->arg.seqid);
+ out_free_calldata:
+       kfree(calldata);
+ out:
+-      nfs4_put_open_state(state);
+-      nfs4_put_state_owner(sp);
+       return status;
+ }
  
-+int proc_nr_files(ctl_table *table, int write, struct file *filp,
-+                void __user *buffer, size_t *lenp, loff_t *ppos);
-+
-+
- #endif /* __KERNEL__ */
- #endif /* _LINUX_FS_H */
-diff -Nurb linux-2.6.22-570/include/linux/fs_stack.h linux-2.6.22-590/include/linux/fs_stack.h
---- linux-2.6.22-570/include/linux/fs_stack.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/fs_stack.h  2008-01-02 13:56:37.000000000 -0500
-@@ -1,7 +1,19 @@
-+/*
-+ * Copyright (c) 2006-2007 Erez Zadok
-+ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2006-2007 Stony Brook University
-+ * Copyright (c) 2006-2007 The Research Foundation of SUNY
-+ *
-+ * 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.
-+ */
-+
- #ifndef _LINUX_FS_STACK_H
- #define _LINUX_FS_STACK_H
+-static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state)
++static int nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
+ {
+       struct file *filp;
  
--/* This file defines generic functions used primarily by stackable
-+/*
-+ * This file defines generic functions used primarily by stackable
-  * filesystems; none of these functions require i_mutex to be held.
+-      filp = lookup_instantiate_filp(nd, path->dentry, NULL);
++      filp = lookup_instantiate_filp(nd, dentry, NULL);
+       if (!IS_ERR(filp)) {
+               struct nfs_open_context *ctx;
+               ctx = (struct nfs_open_context *)filp->private_data;
+               ctx->state = state;
+               return 0;
+       }
+-      nfs4_close_state(path, state, nd->intent.open.flags);
++      nfs4_close_state(state, nd->intent.open.flags);
+       return PTR_ERR(filp);
+ }
+ struct dentry *
+ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+ {
+-      struct path path = {
+-              .mnt = nd->mnt,
+-              .dentry = dentry,
+-      };
+       struct iattr attr;
+       struct rpc_cred *cred;
+       struct nfs4_state *state;
+@@ -1306,7 +1277,7 @@
+       cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
+       if (IS_ERR(cred))
+               return (struct dentry *)cred;
+-      state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred);
++      state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
+       put_rpccred(cred);
+       if (IS_ERR(state)) {
+               if (PTR_ERR(state) == -ENOENT)
+@@ -1316,17 +1287,13 @@
+       res = d_add_unique(dentry, igrab(state->inode));
+       if (res != NULL)
+               dentry = res;
+-      nfs4_intent_set_file(nd, &path, state);
++      nfs4_intent_set_file(nd, dentry, state);
+       return res;
+ }
+ int
+ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
+ {
+-      struct path path = {
+-              .mnt = nd->mnt,
+-              .dentry = dentry,
+-      };
+       struct rpc_cred *cred;
+       struct nfs4_state *state;
+@@ -1335,7 +1302,7 @@
+               return PTR_ERR(cred);
+       state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
+       if (IS_ERR(state))
+-              state = nfs4_do_open(dir, &path, openflags, NULL, cred);
++              state = nfs4_do_open(dir, dentry, openflags, NULL, cred);
+       put_rpccred(cred);
+       if (IS_ERR(state)) {
+               switch (PTR_ERR(state)) {
+@@ -1351,10 +1318,10 @@
+               }
+       }
+       if (state->inode == dentry->d_inode) {
+-              nfs4_intent_set_file(nd, &path, state);
++              nfs4_intent_set_file(nd, dentry, state);
+               return 1;
+       }
+-      nfs4_close_state(&path, state, openflags);
++      nfs4_close_state(state, openflags);
+ out_drop:
+       d_drop(dentry);
+       return 0;
+@@ -1785,10 +1752,6 @@
+ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+                  int flags, struct nameidata *nd)
+ {
+-      struct path path = {
+-              .mnt = nd->mnt,
+-              .dentry = dentry,
+-      };
+       struct nfs4_state *state;
+       struct rpc_cred *cred;
+       int status = 0;
+@@ -1798,7 +1761,7 @@
+               status = PTR_ERR(cred);
+               goto out;
+       }
+-      state = nfs4_do_open(dir, &path, flags, sattr, cred);
++      state = nfs4_do_open(dir, dentry, flags, sattr, cred);
+       put_rpccred(cred);
+       if (IS_ERR(state)) {
+               status = PTR_ERR(state);
+@@ -1810,12 +1773,11 @@
+               status = nfs4_do_setattr(state->inode, &fattr, sattr, state);
+               if (status == 0)
+                       nfs_setattr_update_inode(state->inode, sattr);
+-              nfs_post_op_update_inode(state->inode, &fattr);
+       }
+-      if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
+-              status = nfs4_intent_set_file(nd, &path, state);
++      if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN))
++              status = nfs4_intent_set_file(nd, dentry, state);
+       else
+-              nfs4_close_state(&path, state, flags);
++              nfs4_close_state(state, flags);
+ out:
+       return status;
+ }
+@@ -3323,7 +3285,7 @@
+               memcpy(data->lsp->ls_stateid.data, data->res.stateid.data,
+                                       sizeof(data->lsp->ls_stateid.data));
+               data->lsp->ls_flags |= NFS_LOCK_INITIALIZED;
+-              renew_lease(NFS_SERVER(data->ctx->path.dentry->d_inode), data->timestamp);
++              renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp);
+       }
+       nfs_increment_lock_seqid(data->rpc_status, data->arg.lock_seqid);
+ out:
+diff -Nurb linux-2.6.22-590/fs/nfs/nfs4state.c linux-2.6.22-570/fs/nfs/nfs4state.c
+--- linux-2.6.22-590/fs/nfs/nfs4state.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/nfs4state.c        2007-07-08 19:32:17.000000000 -0400
+@@ -341,7 +341,7 @@
+ /*
+  * Close the current file.
   */
+-void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
++void nfs4_close_state(struct nfs4_state *state, mode_t mode)
+ {
+       struct inode *inode = state->inode;
+       struct nfs4_state_owner *owner = state->owner;
+@@ -375,11 +375,10 @@
+       spin_unlock(&inode->i_lock);
+       spin_unlock(&owner->so_lock);
  
-@@ -11,7 +23,8 @@
- extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
-                               int (*get_nlinks)(struct inode *));
--extern void fsstack_copy_inode_size(struct inode *dst, const struct inode *src);
-+extern void fsstack_copy_inode_size(struct inode *dst,
-+                                  const struct inode *src);
+-      if (oldstate == newstate) {
++      if (oldstate != newstate && nfs4_do_close(inode, state) == 0)
++              return;
+       nfs4_put_open_state(state);
+       nfs4_put_state_owner(owner);
+-      } else
+-              nfs4_do_close(path, state);
+ }
  
- /* inlines */
- static inline void fsstack_copy_attr_atime(struct inode *dest,
-diff -Nurb linux-2.6.22-570/include/linux/gfp.h linux-2.6.22-590/include/linux/gfp.h
---- linux-2.6.22-570/include/linux/gfp.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/gfp.h       2008-01-02 13:56:37.000000000 -0500
-@@ -30,6 +30,9 @@
-  * cannot handle allocation failures.
-  *
-  * __GFP_NORETRY: The VM implementation must not retry indefinitely.
-+ *
-+ * __GFP_MOVABLE: Flag that this page will be movable by the page migration
-+ * mechanism or reclaimed
-  */
- #define __GFP_WAIT    ((__force gfp_t)0x10u)  /* Can wait and reschedule? */
- #define __GFP_HIGH    ((__force gfp_t)0x20u)  /* Should access emergency pools? */
-@@ -45,15 +48,21 @@
- #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
- #define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
- #define __GFP_THISNODE        ((__force gfp_t)0x40000u)/* No fallback, no policies */
-+#define __GFP_RECLAIMABLE ((__force gfp_t)0x80000u) /* Page is reclaimable */
-+#define __GFP_MOVABLE ((__force gfp_t)0x100000u)  /* Page is movable */
+ /*
+diff -Nurb linux-2.6.22-590/fs/nfs/nfs4xdr.c linux-2.6.22-570/fs/nfs/nfs4xdr.c
+--- linux-2.6.22-590/fs/nfs/nfs4xdr.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/nfs4xdr.c  2007-07-08 19:32:17.000000000 -0400
+@@ -3269,7 +3269,7 @@
+ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
+ {
+         __be32 *p;
+-        uint32_t savewords, bmlen, i;
++        uint32_t bmlen;
+         int status;
  
--#define __GFP_BITS_SHIFT 20   /* Room for 20 __GFP_FOO bits */
-+#define __GFP_BITS_SHIFT 21   /* Room for 21 __GFP_FOO bits */
- #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
+         status = decode_op_hdr(xdr, OP_OPEN);
+@@ -3287,12 +3287,7 @@
+                 goto xdr_error;
  
- /* if you forget to add the bitmask here kernel will crash, period */
- #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
-                       __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
-                       __GFP_NOFAIL|__GFP_NORETRY|__GFP_COMP| \
--                      __GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE)
-+                      __GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE| \
-+                      __GFP_RECLAIMABLE|__GFP_MOVABLE)
+         READ_BUF(bmlen << 2);
+-      savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
+-      for (i = 0; i < savewords; ++i)
+-              READ32(res->attrset[i]);
+-
+-      p += (bmlen - savewords);
+-
++        p += bmlen;
+       return decode_delegation(xdr, res);
+ xdr_error:
+       dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen);
+diff -Nurb linux-2.6.22-590/fs/nfs/pagelist.c linux-2.6.22-570/fs/nfs/pagelist.c
+--- linux-2.6.22-590/fs/nfs/pagelist.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/pagelist.c 2007-07-08 19:32:17.000000000 -0400
+@@ -85,8 +85,9 @@
+       req->wb_offset  = offset;
+       req->wb_pgbase  = offset;
+       req->wb_bytes   = count;
++      atomic_set(&req->wb_count, 1);
+       req->wb_context = get_nfs_open_context(ctx);
+-      kref_init(&req->wb_kref);
 +
-+/* This mask makes up all the page movable related flags */
-+#define GFP_MOVABLE_MASK (__GFP_RECLAIMABLE|__GFP_MOVABLE)
- /* This equals 0, but use constants in case they ever change */
- #define GFP_NOWAIT    (GFP_ATOMIC & ~__GFP_HIGH)
-@@ -62,9 +71,20 @@
- #define GFP_NOIO      (__GFP_WAIT)
- #define GFP_NOFS      (__GFP_WAIT | __GFP_IO)
- #define GFP_KERNEL    (__GFP_WAIT | __GFP_IO | __GFP_FS)
-+#define GFP_TEMPORARY (__GFP_WAIT | __GFP_IO | __GFP_FS | \
-+                       __GFP_RECLAIMABLE)
- #define GFP_USER      (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
- #define GFP_HIGHUSER  (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \
-                        __GFP_HIGHMEM)
-+#define GFP_HIGHUSER_MOVABLE  (__GFP_WAIT | __GFP_IO | __GFP_FS | \
-+                               __GFP_HARDWALL | __GFP_HIGHMEM | \
-+                               __GFP_MOVABLE)
-+#define GFP_NOFS_PAGECACHE    (__GFP_WAIT | __GFP_IO | __GFP_MOVABLE)
-+#define GFP_USER_PAGECACHE    (__GFP_WAIT | __GFP_IO | __GFP_FS | \
-+                               __GFP_HARDWALL | __GFP_MOVABLE)
-+#define GFP_HIGHUSER_PAGECACHE        (__GFP_WAIT | __GFP_IO | __GFP_FS | \
-+                               __GFP_HARDWALL | __GFP_HIGHMEM | \
-+                               __GFP_MOVABLE)
- #ifdef CONFIG_NUMA
- #define GFP_THISNODE  (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
-@@ -99,6 +119,12 @@
-       return ZONE_NORMAL;
+       return req;
  }
  
-+static inline gfp_t set_migrateflags(gfp_t gfp, gfp_t migrate_flags)
-+{
-+      BUG_ON((gfp & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK);
-+      return (gfp & ~(GFP_MOVABLE_MASK)) | migrate_flags;
-+}
-+
- /*
-  * There is only one page-allocator function, and two main namespaces to
-  * it. The alloc_page*() variants return 'struct page *' and as such
-diff -Nurb linux-2.6.22-570/include/linux/highmem.h linux-2.6.22-590/include/linux/highmem.h
---- linux-2.6.22-570/include/linux/highmem.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/highmem.h   2008-01-02 13:56:37.000000000 -0500
-@@ -73,10 +73,27 @@
+@@ -108,29 +109,29 @@
  }
  
- #ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
-+/**
-+ * __alloc_zeroed_user_highpage - Allocate a zeroed HIGHMEM page for a VMA with caller-specified movable GFP flags
-+ * @movableflags: The GFP flags related to the pages future ability to move like __GFP_MOVABLE
-+ * @vma: The VMA the page is to be allocated for
-+ * @vaddr: The virtual address the page will be inserted into
-+ *
-+ * This function will allocate a page for a VMA but the caller is expected
-+ * to specify via movableflags whether the page will be movable in the
-+ * future or not
-+ *
-+ * An architecture may override this function by defining
-+ * __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE and providing their own
-+ * implementation.
-+ */
- static inline struct page *
--alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr)
-+__alloc_zeroed_user_highpage(gfp_t movableflags,
-+                      struct vm_area_struct *vma,
-+                      unsigned long vaddr)
+ /**
+- * nfs_set_page_tag_locked - Tag a request as locked
++ * nfs_set_page_writeback_locked - Lock a request for writeback
+  * @req:
+  */
+-static int nfs_set_page_tag_locked(struct nfs_page *req)
++int nfs_set_page_writeback_locked(struct nfs_page *req)
  {
--      struct page *page = alloc_page_vma(GFP_HIGHUSER, vma, vaddr);
-+      struct page *page = alloc_page_vma(GFP_HIGHUSER | movableflags,
-+                      vma, vaddr);
+-      struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode);
++      struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
  
-       if (page)
-               clear_user_highpage(page, vaddr);
-@@ -85,6 +102,36 @@
+       if (!nfs_lock_request(req))
+               return 0;
+-      radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
++      radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
+       return 1;
  }
- #endif
  
-+/**
-+ * alloc_zeroed_user_highpage - Allocate a zeroed HIGHMEM page for a VMA
-+ * @vma: The VMA the page is to be allocated for
-+ * @vaddr: The virtual address the page will be inserted into
-+ *
-+ * This function will allocate a page for a VMA that the caller knows will
-+ * not be able to move in the future using move_pages() or reclaim. If it
-+ * is known that the page can move, use alloc_zeroed_user_highpage_movable
-+ */
-+static inline struct page *
-+alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr)
-+{
-+      return __alloc_zeroed_user_highpage(0, vma, vaddr);
-+}
-+
-+/**
-+ * alloc_zeroed_user_highpage_movable - Allocate a zeroed HIGHMEM page for a VMA that the caller knows can move
-+ * @vma: The VMA the page is to be allocated for
-+ * @vaddr: The virtual address the page will be inserted into
-+ *
-+ * This function will allocate a page for a VMA that the caller knows will
-+ * be able to migrate in the future using move_pages() or reclaimed
-+ */
-+static inline struct page *
-+alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma,
-+                                      unsigned long vaddr)
-+{
-+      return __alloc_zeroed_user_highpage(__GFP_MOVABLE, vma, vaddr);
-+}
-+
- static inline void clear_highpage(struct page *page)
+ /**
+- * nfs_clear_page_tag_locked - Clear request tag and wake up sleepers
++ * nfs_clear_page_writeback - Unlock request and wake up sleepers
+  */
+-void nfs_clear_page_tag_locked(struct nfs_page *req)
++void nfs_clear_page_writeback(struct nfs_page *req)
  {
-       void *kaddr = kmap_atomic(page, KM_USER0);
-diff -Nurb linux-2.6.22-570/include/linux/hugetlb.h linux-2.6.22-590/include/linux/hugetlb.h
---- linux-2.6.22-570/include/linux/hugetlb.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/hugetlb.h   2008-01-02 13:56:37.000000000 -0500
-@@ -15,6 +15,7 @@
- }
- int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
-+int hugetlb_treat_movable_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
- int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
- int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int);
- void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
-@@ -29,6 +30,8 @@
- void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
- extern unsigned long max_huge_pages;
-+extern unsigned long hugepages_treat_as_movable;
-+extern gfp_t htlb_alloc_mask;
- extern const unsigned long hugetlb_zero, hugetlb_infinity;
- extern int sysctl_hugetlb_shm_group;
-diff -Nurb linux-2.6.22-570/include/linux/idr.h linux-2.6.22-590/include/linux/idr.h
---- linux-2.6.22-570/include/linux/idr.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/idr.h       2008-01-02 13:56:37.000000000 -0500
-@@ -83,4 +83,33 @@
- void idr_destroy(struct idr *idp);
- void idr_init(struct idr *idp);
+-      struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode);
++      struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
  
-+
-+/*
-+ * IDA - IDR based id allocator, use when translation from id to
-+ * pointer isn't necessary.
-+ */
-+#define IDA_CHUNK_SIZE                128     /* 128 bytes per chunk */
-+#define IDA_BITMAP_LONGS      (128 / sizeof(long) - 1)
-+#define IDA_BITMAP_BITS               (IDA_BITMAP_LONGS * sizeof(long) * 8)
-+
-+struct ida_bitmap {
-+      long                    nr_busy;
-+      unsigned long           bitmap[IDA_BITMAP_LONGS];
-+};
-+
-+struct ida {
-+      struct idr              idr;
-+      struct ida_bitmap       *free_bitmap;
-+};
-+
-+#define IDA_INIT(name)                { .idr = IDR_INIT(name), .free_bitmap = NULL, }
-+#define DEFINE_IDA(name)      struct ida name = IDA_INIT(name)
-+
-+int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
-+int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
-+int ida_get_new(struct ida *ida, int *p_id);
-+void ida_remove(struct ida *ida, int id);
-+void ida_destroy(struct ida *ida);
-+void ida_init(struct ida *ida);
-+
- #endif /* __IDR_H__ */
-diff -Nurb linux-2.6.22-570/include/linux/if_bridge.h linux-2.6.22-590/include/linux/if_bridge.h
---- linux-2.6.22-570/include/linux/if_bridge.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/if_bridge.h 2008-01-02 13:56:37.000000000 -0500
-@@ -104,7 +104,7 @@
+       if (req->wb_page != NULL) {
+               spin_lock(&nfsi->req_lock);
+-              radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
++              radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
+               spin_unlock(&nfsi->req_lock);
+       }
+       nfs_unlock_request(req);
+@@ -159,9 +160,11 @@
+  *
+  * Note: Should never be called with the spinlock held!
+  */
+-static void nfs_free_request(struct kref *kref)
++void
++nfs_release_request(struct nfs_page *req)
+ {
+-      struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref);
++      if (!atomic_dec_and_test(&req->wb_count))
++              return;
  
- #include <linux/netdevice.h>
+       /* Release struct file or cached credential */
+       nfs_clear_request(req);
+@@ -169,11 +172,6 @@
+       nfs_page_free(req);
+ }
  
--extern void brioctl_set(int (*ioctl_hook)(unsigned int, void __user *));
-+extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
- extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
-                                              struct sk_buff *skb);
- extern int (*br_should_route_hook)(struct sk_buff **pskb);
-diff -Nurb linux-2.6.22-570/include/linux/if_link.h linux-2.6.22-590/include/linux/if_link.h
---- linux-2.6.22-570/include/linux/if_link.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/if_link.h   2008-01-02 13:56:37.000000000 -0500
-@@ -76,6 +76,8 @@
- #define IFLA_WEIGHT IFLA_WEIGHT
-       IFLA_OPERSTATE,
-       IFLA_LINKMODE,
-+      IFLA_LINKINFO,
-+#define IFLA_LINKINFO IFLA_LINKINFO
-       __IFLA_MAX
};
+-void nfs_release_request(struct nfs_page *req)
+-{
+-      kref_put(&req->wb_kref, nfs_free_request);
+-}
+-
+ static int nfs_wait_bit_interruptible(void *word)
+ {
+       int ret = 0;
+@@ -195,7 +193,7 @@
+ int
+ nfs_wait_on_request(struct nfs_page *req)
+ {
+-        struct rpc_clnt       *clnt = NFS_CLIENT(req->wb_context->path.dentry->d_inode);
++        struct rpc_clnt       *clnt = NFS_CLIENT(req->wb_context->dentry->d_inode);
+       sigset_t oldmask;
      int ret = 0;
  
-@@ -140,4 +142,49 @@
-       __u32   retrans_time;
- };
+@@ -381,10 +379,10 @@
+ /**
+  * nfs_scan_list - Scan a list for matching requests
+  * @nfsi: NFS inode
++ * @head: One of the NFS inode request lists
+  * @dst: Destination list
+  * @idx_start: lower bound of page->index to scan
+  * @npages: idx_start + npages sets the upper bound to scan.
+- * @tag: tag to scan for
+  *
+  * Moves elements from one of the inode request lists.
+  * If the number of requests is set to 0, the entire address_space
+@@ -392,9 +390,9 @@
+  * The requests are *not* checked to ensure that they form a contiguous set.
+  * You must be holding the inode's req_lock when calling this function
+  */
+-int nfs_scan_list(struct nfs_inode *nfsi,
++int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,
+               struct list_head *dst, pgoff_t idx_start,
+-              unsigned int npages, int tag)
++              unsigned int npages)
+ {
+       struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
+       struct nfs_page *req;
+@@ -409,9 +407,9 @@
+               idx_end = idx_start + npages - 1;
  
-+enum
-+{
-+      IFLA_INFO_UNSPEC,
-+      IFLA_INFO_KIND,
-+      IFLA_INFO_DATA,
-+      IFLA_INFO_XSTATS,
-+      __IFLA_INFO_MAX,
-+};
-+
-+#define IFLA_INFO_MAX (__IFLA_INFO_MAX - 1)
-+
-+/* VLAN section */
-+
-+enum
-+{
-+      IFLA_VLAN_UNSPEC,
-+      IFLA_VLAN_ID,
-+      IFLA_VLAN_FLAGS,
-+      IFLA_VLAN_EGRESS_QOS,
-+      IFLA_VLAN_INGRESS_QOS,
-+      __IFLA_VLAN_MAX,
-+};
-+
-+#define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1)
-+
-+struct ifla_vlan_flags {
-+      __u32   flags;
-+      __u32   mask;
-+};
-+
-+enum
-+{
-+      IFLA_VLAN_QOS_UNSPEC,
-+      IFLA_VLAN_QOS_MAPPING,
-+      __IFLA_VLAN_QOS_MAX
-+};
-+
-+#define IFLA_VLAN_QOS_MAX     (__IFLA_VLAN_QOS_MAX - 1)
-+
-+struct ifla_vlan_qos_mapping
-+{
-+      __u32 from;
-+      __u32 to;
-+};
+       for (;;) {
+-              found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
++              found = radix_tree_gang_lookup(&nfsi->nfs_page_tree,
+                               (void **)&pgvec[0], idx_start,
+-                              NFS_SCAN_MAXENTRIES, tag);
++                              NFS_SCAN_MAXENTRIES);
+               if (found <= 0)
+                       break;
+               for (i = 0; i < found; i++) {
+@@ -419,18 +417,15 @@
+                       if (req->wb_index > idx_end)
+                               goto out;
+                       idx_start = req->wb_index + 1;
+-                      if (nfs_set_page_tag_locked(req)) {
++                      if (req->wb_list_head != head)
++                              continue;
++                      if (nfs_set_page_writeback_locked(req)) {
+                               nfs_list_remove_request(req);
+-                              radix_tree_tag_clear(&nfsi->nfs_page_tree,
+-                                              req->wb_index, tag);
+                               nfs_list_add_request(req, dst);
+                               res++;
+-                              if (res == INT_MAX)
+-                                      goto out;
+                       }
+               }
+-              /* for latency reduction */
+-              cond_resched_lock(&nfsi->req_lock);
 +
- #endif /* _LINUX_IF_LINK_H */
-diff -Nurb linux-2.6.22-570/include/linux/if_pppox.h linux-2.6.22-590/include/linux/if_pppox.h
---- linux-2.6.22-570/include/linux/if_pppox.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/if_pppox.h  2008-01-02 13:56:37.000000000 -0500
-@@ -160,7 +160,7 @@
- struct module;
- struct pppox_proto {
--      int             (*create)(struct socket *sock);
-+      int             (*create)(struct net *net, struct socket *sock);
-       int             (*ioctl)(struct socket *sock, unsigned int cmd,
-                                unsigned long arg);
-       struct module   *owner;
-diff -Nurb linux-2.6.22-570/include/linux/if_tun.h linux-2.6.22-590/include/linux/if_tun.h
---- linux-2.6.22-570/include/linux/if_tun.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/if_tun.h    2008-01-02 13:56:37.000000000 -0500
-@@ -36,6 +36,7 @@
-       unsigned long           flags;
-       int                     attached;
-       uid_t                   owner;
-+      gid_t                   group;
+       }
+ out:
+       return res;
+diff -Nurb linux-2.6.22-590/fs/nfs/read.c linux-2.6.22-570/fs/nfs/read.c
+--- linux-2.6.22-590/fs/nfs/read.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/read.c     2007-07-08 19:32:17.000000000 -0400
+@@ -145,8 +145,8 @@
+       unlock_page(req->wb_page);
  
-       wait_queue_head_t       read_wait;
-       struct sk_buff_head     readq;
-@@ -78,6 +79,7 @@
- #define TUNSETPERSIST _IOW('T', 203, int) 
- #define TUNSETOWNER   _IOW('T', 204, int)
- #define TUNSETLINK    _IOW('T', 205, int)
-+#define TUNSETGROUP   _IOW('T', 206, int)
+       dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
+-                      req->wb_context->path.dentry->d_inode->i_sb->s_id,
+-                      (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
++                      req->wb_context->dentry->d_inode->i_sb->s_id,
++                      (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+                       req->wb_bytes,
+                       (long long)req_offset(req));
+       nfs_clear_request(req);
+@@ -164,7 +164,7 @@
+       int flags;
  
- /* TUNSETIFF ifr flags */
- #define IFF_TUN               0x0001
-diff -Nurb linux-2.6.22-570/include/linux/if_vlan.h linux-2.6.22-590/include/linux/if_vlan.h
---- linux-2.6.22-570/include/linux/if_vlan.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/if_vlan.h   2008-01-02 13:56:37.000000000 -0500
-@@ -62,7 +62,7 @@
- #define VLAN_VID_MASK 0xfff
+       data->req         = req;
+-      data->inode       = inode = req->wb_context->path.dentry->d_inode;
++      data->inode       = inode = req->wb_context->dentry->d_inode;
+       data->cred        = req->wb_context->cred;
  
- /* found in socket.c */
--extern void vlan_ioctl_set(int (*hook)(void __user *));
-+extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
+       data->args.fh     = NFS_FH(inode);
+@@ -483,19 +483,17 @@
+        */
+       error = nfs_wb_page(inode, page);
+       if (error)
+-              goto out_unlock;
+-      if (PageUptodate(page))
+-              goto out_unlock;
++              goto out_error;
  
- #define VLAN_NAME "vlan"
+       error = -ESTALE;
+       if (NFS_STALE(inode))
+-              goto out_unlock;
++              goto out_error;
  
-@@ -99,7 +99,7 @@
- }
+       if (file == NULL) {
+               error = -EBADF;
+               ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
+               if (ctx == NULL)
+-                      goto out_unlock;
++                      goto out_error;
+       } else
+               ctx = get_nfs_open_context((struct nfs_open_context *)
+                               file->private_data);
+@@ -504,7 +502,8 @@
  
- struct vlan_priority_tci_mapping {
--      unsigned long priority;
-+      u32 priority;
-       unsigned short vlan_qos; /* This should be shifted when first set, so we only do it
-                                 * at provisioning time.
-                                 * ((skb->priority << 13) & 0xE000)
-@@ -112,7 +112,10 @@
-       /** This will be the mapping that correlates skb->priority to
-        * 3 bits of VLAN QOS tags...
-        */
--      unsigned long ingress_priority_map[8];
-+      unsigned int nr_ingress_mappings;
-+      u32 ingress_priority_map[8];
+       put_nfs_open_context(ctx);
+       return error;
+-out_unlock:
 +
-+      unsigned int nr_egress_mappings;
-       struct vlan_priority_tci_mapping *egress_priority_map[16]; /* hash table */
-       unsigned short vlan_id;        /*  The VLAN Identifier for this interface. */
-@@ -395,6 +398,10 @@
-       GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
- };
++out_error:
+       unlock_page(page);
+       return error;
+ }
+@@ -521,32 +520,21 @@
+       struct inode *inode = page->mapping->host;
+       struct nfs_page *new;
+       unsigned int len;
+-      int error;
+-
+-      error = nfs_wb_page(inode, page);
+-      if (error)
+-              goto out_unlock;
+-      if (PageUptodate(page))
+-              goto out_unlock;
  
-+enum vlan_flags {
-+      VLAN_FLAG_REORDER_HDR   = 0x1,
-+};
-+
- enum vlan_name_types {
-       VLAN_NAME_TYPE_PLUS_VID, /* Name will look like:  vlan0005 */
-       VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like:  eth1.0005 */
-diff -Nurb linux-2.6.22-570/include/linux/inetdevice.h linux-2.6.22-590/include/linux/inetdevice.h
---- linux-2.6.22-570/include/linux/inetdevice.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/inetdevice.h        2008-01-02 13:56:37.000000000 -0500
-@@ -17,8 +17,6 @@
-       DECLARE_BITMAP(state, __NET_IPV4_CONF_MAX - 1);
- };
++      nfs_wb_page(inode, page);
+       len = nfs_page_length(page);
+       if (len == 0)
+               return nfs_return_empty_page(page);
+-
+       new = nfs_create_request(desc->ctx, inode, page, 0, len);
+-      if (IS_ERR(new))
+-              goto out_error;
+-
++      if (IS_ERR(new)) {
++                      SetPageError(page);
++                      unlock_page(page);
++                      return PTR_ERR(new);
++      }
+       if (len < PAGE_CACHE_SIZE)
+               zero_user_page(page, len, PAGE_CACHE_SIZE - len, KM_USER0);
+       nfs_pageio_add_request(desc->pgio, new);
+       return 0;
+-out_error:
+-      error = PTR_ERR(new);
+-      SetPageError(page);
+-out_unlock:
+-      unlock_page(page);
+-      return error;
+ }
  
--extern struct ipv4_devconf ipv4_devconf;
+ int nfs_readpages(struct file *filp, struct address_space *mapping,
+diff -Nurb linux-2.6.22-590/fs/nfs/super.c linux-2.6.22-570/fs/nfs/super.c
+--- linux-2.6.22-590/fs/nfs/super.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/super.c    2008-01-23 19:16:04.000000000 -0500
+@@ -292,7 +292,6 @@
+               { NFS_MOUNT_NONLM, ",nolock", "" },
+               { NFS_MOUNT_NOACL, ",noacl", "" },
+               { NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
+-              { NFS_MOUNT_UNSHARED, ",nosharecache", ""},
+               { NFS_MOUNT_TAGGED, ",tag", "" },
+               { 0, NULL, NULL }
+       };
+@@ -433,20 +432,7 @@
+  */
+ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
+ {
+-      struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb);
+-      struct rpc_clnt *rpc;
 -
- struct in_device
+       shrink_submounts(vfsmnt, &nfs_automount_list);
+-      
+-      if (!(flags & MNT_FORCE))
+-              return;
+-      /* -EIO all pending I/O */
+-      rpc = server->client_acl;
+-      if (!IS_ERR(rpc))
+-              rpc_killall_tasks(rpc);
+-      rpc = server->client;
+-      if (!IS_ERR(rpc))
+-              rpc_killall_tasks(rpc);
+ }
+ /*
+@@ -616,51 +602,13 @@
  {
-       struct net_device       *dev;
-@@ -44,7 +42,7 @@
- };
+       struct nfs_server *server = data, *old = NFS_SB(sb);
  
- #define IPV4_DEVCONF(cnf, attr) ((cnf).data[NET_IPV4_CONF_ ## attr - 1])
--#define IPV4_DEVCONF_ALL(attr) IPV4_DEVCONF(ipv4_devconf, attr)
-+#define IPV4_DEVCONF_ALL(net, attr) IPV4_DEVCONF(*((net)->ipv4_devconf), attr)
+-      if (memcmp(&old->nfs_client->cl_addr,
+-                              &server->nfs_client->cl_addr,
+-                              sizeof(old->nfs_client->cl_addr)) != 0)
+-              return 0;
+-      /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
+-      if (old->flags & NFS_MOUNT_UNSHARED)
++      if (old->nfs_client != server->nfs_client)
+               return 0;
+       if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
+               return 0;
+       return 1;
+ }
  
- static inline int ipv4_devconf_get(struct in_device *in_dev, int index)
+-#define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS)
+-
+-static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, int flags)
+-{
+-      const struct nfs_server *a = s->s_fs_info;
+-      const struct rpc_clnt *clnt_a = a->client;
+-      const struct rpc_clnt *clnt_b = b->client;
+-
+-      if ((s->s_flags & NFS_MS_MASK) != (flags & NFS_MS_MASK))
+-              goto Ebusy;
+-      if (a->nfs_client != b->nfs_client)
+-              goto Ebusy;
+-      if (a->flags != b->flags)
+-              goto Ebusy;
+-      if (a->wsize != b->wsize)
+-              goto Ebusy;
+-      if (a->rsize != b->rsize)
+-              goto Ebusy;
+-      if (a->acregmin != b->acregmin)
+-              goto Ebusy;
+-      if (a->acregmax != b->acregmax)
+-              goto Ebusy;
+-      if (a->acdirmin != b->acdirmin)
+-              goto Ebusy;
+-      if (a->acdirmax != b->acdirmax)
+-              goto Ebusy;
+-      if (clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor)
+-              goto Ebusy;
+-      return 0;
+-Ebusy:
+-      return -EBUSY;
+-}
+-
+ static int nfs_get_sb(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
  {
-@@ -71,14 +69,14 @@
-       ipv4_devconf_set((in_dev), NET_IPV4_CONF_ ## attr, (val))
+@@ -669,7 +617,6 @@
+       struct nfs_fh mntfh;
+       struct nfs_mount_data *data = raw_data;
+       struct dentry *mntroot;
+-      int (*compare_super)(struct super_block *,void *) = nfs_compare_super;
+       int error;
  
- #define IN_DEV_ANDCONF(in_dev, attr) \
--      (IPV4_DEVCONF_ALL(attr) && IN_DEV_CONF_GET((in_dev), attr))
-+      (IPV4_DEVCONF_ALL((in_dev)->dev->nd_net, attr) && IN_DEV_CONF_GET((in_dev), attr))
- #define IN_DEV_ORCONF(in_dev, attr) \
--      (IPV4_DEVCONF_ALL(attr) || IN_DEV_CONF_GET((in_dev), attr))
-+      (IPV4_DEVCONF_ALL((in_dev)->dev->nd_net, attr) || IN_DEV_CONF_GET((in_dev), attr))
- #define IN_DEV_MAXCONF(in_dev, attr) \
--      (max(IPV4_DEVCONF_ALL(attr), IN_DEV_CONF_GET((in_dev), attr)))
-+      (max(IPV4_DEVCONF_ALL((in_dev)->dev->nd_net, attr), IN_DEV_CONF_GET((in_dev), attr)))
+       /* Validate the mount data */
+@@ -684,22 +631,16 @@
+               goto out_err_noserver;
+       }
  
- #define IN_DEV_FORWARD(in_dev)                IN_DEV_CONF_GET((in_dev), FORWARDING)
--#define IN_DEV_MFORWARD(in_dev)               (IPV4_DEVCONF_ALL(MC_FORWARDING) && \
-+#define IN_DEV_MFORWARD(in_dev)               (IPV4_DEVCONF_ALL((in_dev)->dev->nd_net, MC_FORWARDING) && \
-                                        IPV4_DEVCONF((in_dev)->cnf, \
-                                                     MC_FORWARDING))
- #define IN_DEV_RPFILTER(in_dev)               IN_DEV_ANDCONF((in_dev), RP_FILTER)
-@@ -127,15 +125,15 @@
- extern int register_inetaddr_notifier(struct notifier_block *nb);
- extern int unregister_inetaddr_notifier(struct notifier_block *nb);
+-      if (server->flags & NFS_MOUNT_UNSHARED)
+-              compare_super = NULL;
+-
+       /* Get a superblock - note that we may end up sharing one that already exists */
+-      s = sget(fs_type, compare_super, nfs_set_super, server);
++      s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+       if (IS_ERR(s)) {
+               error = PTR_ERR(s);
+               goto out_err_nosb;
+       }
  
--extern struct net_device      *ip_dev_find(__be32 addr);
-+extern struct net_device      *ip_dev_find(struct net *net, __be32 addr);
- extern int            inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
--extern int            devinet_ioctl(unsigned int cmd, void __user *);
-+extern int            devinet_ioctl(struct net *net, unsigned int cmd, void __user *);
- extern void           devinet_init(void);
--extern struct in_device       *inetdev_by_index(int);
-+extern struct in_device       *inetdev_by_index(struct net *, int);
- extern __be32         inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
--extern __be32         inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope);
-+extern __be32         inet_confirm_addr(struct net *net, const struct net_device *dev, __be32 dst, __be32 local, int scope);
- extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix, __be32 mask);
--extern void           inet_forward_change(void);
-+extern void           inet_forward_change(struct net *net);
+       if (s->s_fs_info != server) {
+-              error = nfs_compare_mount_options(s, server, flags);
+               nfs_free_server(server);
+               server = NULL;
+-              if (error < 0)
+-                      goto error_splat_super;
+       }
  
- static __inline__ int inet_ifa_match(__be32 addr, struct in_ifaddr *ifa)
- {
-diff -Nurb linux-2.6.22-570/include/linux/init_task.h linux-2.6.22-590/include/linux/init_task.h
---- linux-2.6.22-570/include/linux/init_task.h 2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/init_task.h 2008-01-02 13:56:37.000000000 -0500
-@@ -8,6 +8,8 @@
- #include <linux/lockdep.h>
- #include <linux/ipc.h>
- #include <linux/pid_namespace.h>
-+#include <linux/user_namespace.h>
-+#include <net/net_namespace.h>
+       if (!s->s_root) {
+@@ -752,7 +693,6 @@
+       struct super_block *s;
+       struct nfs_server *server;
+       struct dentry *mntroot;
+-      int (*compare_super)(struct super_block *,void *) = nfs_compare_super;
+       int error;
  
- #define INIT_FDTABLE \
- {                                                     \
-@@ -77,7 +79,9 @@
-       .nslock         = __SPIN_LOCK_UNLOCKED(nsproxy.nslock),         \
-       .uts_ns         = &init_uts_ns,                                 \
-       .mnt_ns         = NULL,                                         \
-+      .net_ns         = &init_net,                                    \
-       INIT_IPC_NS(ipc_ns)                                             \
-+      .user_ns        = &init_user_ns,                                \
- }
+       dprintk("--> nfs_xdev_get_sb()\n");
+@@ -764,11 +704,8 @@
+               goto out_err_noserver;
+       }
  
- #define INIT_SIGHAND(sighand) {                                               \
-diff -Nurb linux-2.6.22-570/include/linux/io.h linux-2.6.22-590/include/linux/io.h
---- linux-2.6.22-570/include/linux/io.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/io.h        2008-01-02 13:56:37.000000000 -0500
-@@ -63,32 +63,7 @@
- void __iomem * devm_ioremap_nocache(struct device *dev, unsigned long offset,
-                                   unsigned long size);
- void devm_iounmap(struct device *dev, void __iomem *addr);
--
--/**
-- *    check_signature         -       find BIOS signatures
-- *    @io_addr: mmio address to check
-- *    @signature:  signature block
-- *    @length: length of signature
-- *
-- *    Perform a signature comparison with the mmio address io_addr. This
-- *    address should have been obtained by ioremap.
-- *    Returns 1 on a match.
-- */
+-      if (server->flags & NFS_MOUNT_UNSHARED)
+-              compare_super = NULL;
 -
--static inline int check_signature(const volatile void __iomem *io_addr,
--      const unsigned char *signature, int length)
--{
--      int retval = 0;
--      do {
--              if (readb(io_addr) != *signature)
--                      goto out;
--              io_addr++;
--              signature++;
--              length--;
--      } while (length);
--      retval = 1;
--out:
--      return retval;
--}
-+int check_signature(const volatile void __iomem *io_addr,
-+                      const unsigned char *signature, int length);
+       /* Get a superblock - note that we may end up sharing one that already exists */
+-      s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
++      s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+       if (IS_ERR(s)) {
+               error = PTR_ERR(s);
+               goto out_err_nosb;
+@@ -873,7 +810,6 @@
+       struct dentry *mntroot;
+       char *mntpath = NULL, *hostname = NULL, ip_addr[16];
+       void *p;
+-      int (*compare_super)(struct super_block *,void *) = nfs_compare_super;
+       int error;
  
- #endif /* _LINUX_IO_H */
-diff -Nurb linux-2.6.22-570/include/linux/ip_mp_alg.h linux-2.6.22-590/include/linux/ip_mp_alg.h
---- linux-2.6.22-570/include/linux/ip_mp_alg.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/ip_mp_alg.h 1969-12-31 19:00:00.000000000 -0500
-@@ -1,22 +0,0 @@
--/* ip_mp_alg.h: IPV4 multipath algorithm support, user-visible values.
-- *
-- * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
-- * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
-- */
--
--#ifndef _LINUX_IP_MP_ALG_H
--#define _LINUX_IP_MP_ALG_H
--
--enum ip_mp_alg {
--      IP_MP_ALG_NONE,
--      IP_MP_ALG_RR,
--      IP_MP_ALG_DRR,
--      IP_MP_ALG_RANDOM,
--      IP_MP_ALG_WRANDOM,
--      __IP_MP_ALG_MAX
--};
--
--#define IP_MP_ALG_MAX (__IP_MP_ALG_MAX - 1)
+       if (data == NULL) {
+@@ -945,22 +881,16 @@
+               goto out_err_noserver;
+       }
+-      if (server->flags & NFS4_MOUNT_UNSHARED)
+-              compare_super = NULL;
 -
--#endif /* _LINUX_IP_MP_ALG_H */
+       /* Get a superblock - note that we may end up sharing one that already exists */
+-      s = sget(fs_type, compare_super, nfs_set_super, server);
++      s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+       if (IS_ERR(s)) {
+               error = PTR_ERR(s);
+               goto out_free;
+       }
+       if (s->s_fs_info != server) {
+-              error = nfs_compare_mount_options(s, server, flags);
+               nfs_free_server(server);
+               server = NULL;
+-              if (error < 0)
+-                      goto error_splat_super;
+       }
+       if (!s->s_root) {
+@@ -1021,7 +951,6 @@
+       struct super_block *s;
+       struct nfs_server *server;
+       struct dentry *mntroot;
+-      int (*compare_super)(struct super_block *,void *) = nfs_compare_super;
+       int error;
+       dprintk("--> nfs4_xdev_get_sb()\n");
+@@ -1033,11 +962,8 @@
+               goto out_err_noserver;
+       }
+-      if (server->flags & NFS4_MOUNT_UNSHARED)
+-              compare_super = NULL;
 -
-diff -Nurb linux-2.6.22-570/include/linux/ipc.h linux-2.6.22-590/include/linux/ipc.h
---- linux-2.6.22-570/include/linux/ipc.h       2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/ipc.h       2008-01-02 13:56:37.000000000 -0500
-@@ -93,6 +93,7 @@
+       /* Get a superblock - note that we may end up sharing one that already exists */
+-      s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
++      s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+       if (IS_ERR(s)) {
+               error = PTR_ERR(s);
+               goto out_err_nosb;
+@@ -1092,7 +1018,6 @@
+       struct nfs_server *server;
+       struct dentry *mntroot;
+       struct nfs_fh mntfh;
+-      int (*compare_super)(struct super_block *,void *) = nfs_compare_super;
+       int error;
  
- #ifdef CONFIG_SYSVIPC
- #define INIT_IPC_NS(ns)               .ns             = &init_ipc_ns,
-+extern void free_ipc_ns(struct kref *kref);
- extern struct ipc_namespace *copy_ipcs(unsigned long flags,
-                                               struct ipc_namespace *ns);
- #else
-@@ -104,13 +105,9 @@
+       dprintk("--> nfs4_referral_get_sb()\n");
+@@ -1104,11 +1029,8 @@
+               goto out_err_noserver;
+       }
+-      if (server->flags & NFS4_MOUNT_UNSHARED)
+-              compare_super = NULL;
+-
+       /* Get a superblock - note that we may end up sharing one that already exists */
+-      s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
++      s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+       if (IS_ERR(s)) {
+               error = PTR_ERR(s);
+               goto out_err_nosb;
+diff -Nurb linux-2.6.22-590/fs/nfs/write.c linux-2.6.22-570/fs/nfs/write.c
+--- linux-2.6.22-590/fs/nfs/write.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfs/write.c    2007-07-08 19:32:17.000000000 -0400
+@@ -117,7 +117,7 @@
+       if (PagePrivate(page)) {
+               req = (struct nfs_page *)page_private(page);
+               if (req != NULL)
+-                      kref_get(&req->wb_kref);
++                      atomic_inc(&req->wb_count);
+       }
+       return req;
+ }
+@@ -191,6 +191,8 @@
+       }
+       /* Update file length */
+       nfs_grow_file(page, offset, count);
++      /* Set the PG_uptodate flag? */
++      nfs_mark_uptodate(page, offset, count);
+       nfs_unlock_request(req);
+       return 0;
+ }
+@@ -289,7 +291,7 @@
+               BUG();
+       }
+       radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index,
+-                      NFS_PAGE_TAG_LOCKED);
++                      NFS_PAGE_TAG_WRITEBACK);
+       ret = test_bit(PG_NEED_FLUSH, &req->wb_flags);
+       spin_unlock(req_lock);
+       nfs_pageio_add_request(pgio, req);
+@@ -398,7 +400,7 @@
+       if (PageDirty(req->wb_page))
+               set_bit(PG_NEED_FLUSH, &req->wb_flags);
+       nfsi->npages++;
+-      kref_get(&req->wb_kref);
++      atomic_inc(&req->wb_count);
+       return 0;
  }
- #endif
  
--#ifdef CONFIG_IPC_NS
--extern void free_ipc_ns(struct kref *kref);
--#endif
--
- static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
+@@ -407,7 +409,7 @@
+  */
+ static void nfs_inode_remove_request(struct nfs_page *req)
  {
--#ifdef CONFIG_IPC_NS
-+#ifdef CONFIG_SYSVIPC
-       if (ns)
-               kref_get(&ns->kref);
- #endif
-@@ -119,7 +116,7 @@
+-      struct inode *inode = req->wb_context->path.dentry->d_inode;
++      struct inode *inode = req->wb_context->dentry->d_inode;
+       struct nfs_inode *nfsi = NFS_I(inode);
  
- static inline void put_ipc_ns(struct ipc_namespace *ns)
+       BUG_ON (!NFS_WBACK_BUSY(req));
+@@ -455,15 +457,13 @@
+ static void
+ nfs_mark_request_commit(struct nfs_page *req)
  {
--#ifdef CONFIG_IPC_NS
-+#ifdef CONFIG_SYSVIPC
-       kref_put(&ns->kref, free_ipc_ns);
- #endif
- }
-@@ -127,5 +124,3 @@
- #endif /* __KERNEL__ */
+-      struct inode *inode = req->wb_context->path.dentry->d_inode;
++      struct inode *inode = req->wb_context->dentry->d_inode;
+       struct nfs_inode *nfsi = NFS_I(inode);
  
- #endif /* _LINUX_IPC_H */
--
--
-diff -Nurb linux-2.6.22-570/include/linux/ipv6.h linux-2.6.22-590/include/linux/ipv6.h
---- linux-2.6.22-570/include/linux/ipv6.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/ipv6.h      2008-01-02 13:56:37.000000000 -0500
-@@ -247,7 +247,7 @@
-       __u16                   lastopt;
-       __u32                   nhoff;
-       __u16                   flags;
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-       __u16                   dsthao;
- #endif
+       spin_lock(&nfsi->req_lock);
++      nfs_list_add_request(req, &nfsi->commit);
+       nfsi->ncommit++;
+       set_bit(PG_NEED_COMMIT, &(req)->wb_flags);
+-      radix_tree_tag_set(&nfsi->nfs_page_tree,
+-                      req->wb_index,
+-                      NFS_PAGE_TAG_COMMIT);
+       spin_unlock(&nfsi->req_lock);
+       inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
+       __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
+@@ -526,14 +526,14 @@
+               idx_end = idx_start + npages - 1;
  
-diff -Nurb linux-2.6.22-570/include/linux/kgdb.h linux-2.6.22-590/include/linux/kgdb.h
---- linux-2.6.22-570/include/linux/kgdb.h      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/linux/kgdb.h      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,291 @@
-+/*
-+ * include/linux/kgdb.h
-+ *
-+ * This provides the hooks and functions that KGDB needs to share between
-+ * the core, I/O and arch-specific portions.
-+ *
-+ * Author: Amit Kale <amitkale@linsyssoft.com> and
-+ *         Tom Rini <trini@kernel.crashing.org>
-+ *
-+ * 2001-2004 (c) Amit S. Kale and 2003-2005 (c) MontaVista Software, Inc.
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program is licensed "as is" without any warranty of any
-+ * kind, whether express or implied.
-+ */
-+#ifdef __KERNEL__
-+#ifndef _KGDB_H_
-+#define _KGDB_H_
-+
-+#include <asm/atomic.h>
-+
-+#ifdef CONFIG_KGDB
-+#include <asm/kgdb.h>
-+#include <linux/serial_8250.h>
-+#include <linux/linkage.h>
-+#include <linux/init.h>
-+
-+#ifndef CHECK_EXCEPTION_STACK
-+#define CHECK_EXCEPTION_STACK()       1
-+#endif
-+
-+struct tasklet_struct;
-+struct pt_regs;
-+struct task_struct;
-+struct uart_port;
-+
-+#ifdef CONFIG_KGDB_CONSOLE
-+extern struct console kgdbcons;
-+#endif
-+
-+/* To enter the debugger explicitly. */
-+extern void breakpoint(void);
-+extern int kgdb_connected;
-+extern int kgdb_may_fault;
-+extern struct tasklet_struct kgdb_tasklet_breakpoint;
-+
-+extern atomic_t kgdb_setting_breakpoint;
-+extern atomic_t cpu_doing_single_step;
-+extern atomic_t kgdb_sync_softlockup[NR_CPUS];
-+
-+extern struct task_struct *kgdb_usethread, *kgdb_contthread;
-+
-+enum kgdb_bptype {
-+      bp_breakpoint = '0',
-+      bp_hardware_breakpoint,
-+      bp_write_watchpoint,
-+      bp_read_watchpoint,
-+      bp_access_watchpoint
-+};
-+
-+enum kgdb_bpstate {
-+      bp_none = 0,
-+      bp_removed,
-+      bp_set,
-+      bp_active
-+};
-+
-+struct kgdb_bkpt {
-+      unsigned long bpt_addr;
-+      unsigned char saved_instr[BREAK_INSTR_SIZE];
-+      enum kgdb_bptype type;
-+      enum kgdb_bpstate state;
-+};
-+
-+/* The maximum number of KGDB I/O modules that can be loaded */
-+#define MAX_KGDB_IO_HANDLERS 3
-+
-+#ifndef MAX_BREAKPOINTS
-+#define MAX_BREAKPOINTS               1000
-+#endif
-+
-+#define KGDB_HW_BREAKPOINT    1
-+
-+/* Required functions. */
-+/**
-+ *    kgdb_arch_init - Perform any architecture specific initalization.
-+ *
-+ *    This function will handle the initalization of any architecture
-+ *    specific hooks.
-+ */
-+extern int kgdb_arch_init(void);
-+
-+/**
-+ *    regs_to_gdb_regs - Convert ptrace regs to GDB regs
-+ *    @gdb_regs: A pointer to hold the registers in the order GDB wants.
-+ *    @regs: The &struct pt_regs of the current process.
-+ *
-+ *    Convert the pt_regs in @regs into the format for registers that
-+ *    GDB expects, stored in @gdb_regs.
-+ */
-+extern void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs);
-+
-+/**
-+ *    sleeping_regs_to_gdb_regs - Convert ptrace regs to GDB regs
-+ *    @gdb_regs: A pointer to hold the registers in the order GDB wants.
-+ *    @p: The &struct task_struct of the desired process.
-+ *
-+ *    Convert the register values of the sleeping process in @p to
-+ *    the format that GDB expects.
-+ *    This function is called when kgdb does not have access to the
-+ *    &struct pt_regs and therefore it should fill the gdb registers
-+ *    @gdb_regs with what has been saved in &struct thread_struct
-+ *    thread field during switch_to.
-+ */
-+extern void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
-+                                      struct task_struct *p);
-+
-+/**
-+ *    gdb_regs_to_regs - Convert GDB regs to ptrace regs.
-+ *    @gdb_regs: A pointer to hold the registers we've recieved from GDB.
-+ *    @regs: A pointer to a &struct pt_regs to hold these values in.
-+ *
-+ *    Convert the GDB regs in @gdb_regs into the pt_regs, and store them
-+ *    in @regs.
-+ */
-+extern void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs);
-+
-+/**
-+ *    kgdb_arch_handle_exception - Handle architecture specific GDB packets.
-+ *    @vector: The error vector of the exception that happened.
-+ *    @signo: The signal number of the exception that happened.
-+ *    @err_code: The error code of the exception that happened.
-+ *    @remcom_in_buffer: The buffer of the packet we have read.
-+ *    @remcom_out_buffer: The buffer, of %BUFMAX to write a packet into.
-+ *    @regs: The &struct pt_regs of the current process.
-+ *
-+ *    This function MUST handle the 'c' and 's' command packets,
-+ *    as well packets to set / remove a hardware breakpoint, if used.
-+ *    If there are additional packets which the hardware needs to handle,
-+ *    they are handled here.  The code should return -1 if it wants to
-+ *    process more packets, and a %0 or %1 if it wants to exit from the
-+ *    kgdb hook.
-+ */
-+extern int kgdb_arch_handle_exception(int vector, int signo, int err_code,
-+                                    char *remcom_in_buffer,
-+                                    char *remcom_out_buffer,
-+                                    struct pt_regs *regs);
-+
-+/**
-+ *    kgdb_roundup_cpus - Get other CPUs into a holding pattern
-+ *    @flags: Current IRQ state
-+ *
-+ *    On SMP systems, we need to get the attention of the other CPUs
-+ *    and get them be in a known state.  This should do what is needed
-+ *    to get the other CPUs to call kgdb_wait(). Note that on some arches,
-+ *    the NMI approach is not used for rounding up all the CPUs. For example,
-+ *    in case of MIPS, smp_call_function() is used to roundup CPUs. In
-+ *    this case, we have to make sure that interrupts are enabled before
-+ *    calling smp_call_function(). The argument to this function is
-+ *    the flags that will be used when restoring the interrupts. There is
-+ *    local_irq_save() call before kgdb_roundup_cpus().
-+ *
-+ *    On non-SMP systems, this is not called.
-+ */
-+extern void kgdb_roundup_cpus(unsigned long flags);
-+
-+#ifndef JMP_REGS_ALIGNMENT
-+#define JMP_REGS_ALIGNMENT
-+#endif
-+
-+extern unsigned long kgdb_fault_jmp_regs[];
-+
-+/**
-+ *    kgdb_fault_setjmp - Store state in case we fault.
-+ *    @curr_context: An array to store state into.
-+ *
-+ *    Certain functions may try and access memory, and in doing so may
-+ *    cause a fault.  When this happens, we trap it, restore state to
-+ *    this call, and let ourself know that something bad has happened.
-+ */
-+extern asmlinkage int kgdb_fault_setjmp(unsigned long *curr_context);
-+
-+/**
-+ *    kgdb_fault_longjmp - Restore state when we have faulted.
-+ *    @curr_context: The previously stored state.
-+ *
-+ *    When something bad does happen, this function is called to
-+ *    restore the known good state, and set the return value to 1, so
-+ *    we know something bad happened.
-+ */
-+extern asmlinkage void kgdb_fault_longjmp(unsigned long *curr_context);
-+
-+/* Optional functions. */
-+extern int kgdb_validate_break_address(unsigned long addr);
-+extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr);
-+extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle);
-+
-+/**
-+ * struct kgdb_arch - Desribe architecture specific values.
-+ * @gdb_bpt_instr: The instruction to trigger a breakpoint.
-+ * @flags: Flags for the breakpoint, currently just %KGDB_HW_BREAKPOINT.
-+ * @shadowth: A value of %1 indicates we shadow information on processes.
-+ * @set_breakpoint: Allow an architecture to specify how to set a software
-+ * breakpoint.
-+ * @remove_breakpoint: Allow an architecture to specify how to remove a
-+ * software breakpoint.
-+ * @set_hw_breakpoint: Allow an architecture to specify how to set a hardware
-+ * breakpoint.
-+ * @remove_hw_breakpoint: Allow an architecture to specify how to remove a
-+ * hardware breakpoint.
-+ *
-+ * The @shadowth flag is an option to shadow information not retrievable by
-+ * gdb otherwise.  This is deprecated in favor of a binutils which supports
-+ * CFI macros.
-+ */
-+struct kgdb_arch {
-+      unsigned char gdb_bpt_instr[BREAK_INSTR_SIZE];
-+      unsigned long flags;
-+      unsigned shadowth;
-+      int (*set_breakpoint) (unsigned long, char *);
-+      int (*remove_breakpoint)(unsigned long, char *);
-+      int (*set_hw_breakpoint)(unsigned long, int, enum kgdb_bptype);
-+      int (*remove_hw_breakpoint)(unsigned long, int, enum kgdb_bptype);
-+      void (*remove_all_hw_break)(void);
-+      void (*correct_hw_break)(void);
-+};
-+
-+/* Thread reference */
-+typedef unsigned char threadref[8];
-+
-+/**
-+ * struct kgdb_io - Desribe the interface for an I/O driver to talk with KGDB.
-+ * @read_char: Pointer to a function that will return one char.
-+ * @write_char: Pointer to a function that will write one char.
-+ * @flush: Pointer to a function that will flush any pending writes.
-+ * @init: Pointer to a function that will initialize the device.
-+ * @late_init: Pointer to a function that will do any setup that has
-+ * other dependencies.
-+ * @pre_exception: Pointer to a function that will do any prep work for
-+ * the I/O driver.
-+ * @post_exception: Pointer to a function that will do any cleanup work
-+ * for the I/O driver.
-+ *
-+ * The @init and @late_init function pointers allow for an I/O driver
-+ * such as a serial driver to fully initialize the port with @init and
-+ * be called very early, yet safely call request_irq() later in the boot
-+ * sequence.
-+ *
-+ * @init is allowed to return a non-0 return value to indicate failure.
-+ * If this is called early on, then KGDB will try again when it would call
-+ * @late_init.  If it has failed later in boot as well, the user will be
-+ * notified.
-+ */
-+struct kgdb_io {
-+      int (*read_char) (void);
-+      void (*write_char) (u8);
-+      void (*flush) (void);
-+      int (*init) (void);
-+      void (*late_init) (void);
-+      void (*pre_exception) (void);
-+      void (*post_exception) (void);
-+};
-+
-+extern struct kgdb_io kgdb_io_ops;
-+extern struct kgdb_arch arch_kgdb_ops;
-+extern int kgdb_initialized;
-+
-+extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops);
-+extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops);
-+
-+extern void __init kgdb8250_add_port(int i, struct uart_port *serial_req);
-+extern void __init kgdb8250_add_platform_port(int i, struct plat_serial8250_port *serial_req);
-+
-+extern int kgdb_hex2long(char **ptr, long *long_val);
-+extern char *kgdb_mem2hex(char *mem, char *buf, int count);
-+extern char *kgdb_hex2mem(char *buf, char *mem, int count);
-+extern int kgdb_get_mem(char *addr, unsigned char *buf, int count);
-+extern int kgdb_set_mem(char *addr, unsigned char *buf, int count);
-+
-+int kgdb_isremovedbreak(unsigned long addr);
-+
-+extern int kgdb_handle_exception(int ex_vector, int signo, int err_code,
-+                              struct pt_regs *regs);
-+extern void kgdb_nmihook(int cpu, void *regs);
-+extern int debugger_step;
-+extern atomic_t debugger_active;
-+#else
-+/* Stubs for when KGDB is not set. */
-+static const atomic_t debugger_active = ATOMIC_INIT(0);
-+#endif                                /* CONFIG_KGDB */
-+#endif                                /* _KGDB_H_ */
-+#endif                                /* __KERNEL__ */
-diff -Nurb linux-2.6.22-570/include/linux/kmod.h linux-2.6.22-590/include/linux/kmod.h
---- linux-2.6.22-570/include/linux/kmod.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/kmod.h      2008-01-02 13:56:37.000000000 -0500
-@@ -36,13 +36,57 @@
- #define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
+       next = idx_start;
+-      while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_LOCKED)) {
++      while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) {
+               if (req->wb_index > idx_end)
+                       break;
  
- struct key;
--extern int call_usermodehelper_keys(char *path, char *argv[], char *envp[],
--                                  struct key *session_keyring, int wait);
-+struct file;
-+struct subprocess_info;
-+
-+/* Allocate a subprocess_info structure */
-+struct subprocess_info *call_usermodehelper_setup(char *path,
-+                                                char **argv, char **envp);
-+
-+/* Set various pieces of state into the subprocess_info structure */
-+void call_usermodehelper_setkeys(struct subprocess_info *info,
-+                               struct key *session_keyring);
-+int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info,
-+                                struct file **filp);
-+void call_usermodehelper_setcleanup(struct subprocess_info *info,
-+                                  void (*cleanup)(char **argv, char **envp));
-+
-+enum umh_wait {
-+      UMH_NO_WAIT = -1,       /* don't wait at all */
-+      UMH_WAIT_EXEC = 0,      /* wait for the exec, but not the process */
-+      UMH_WAIT_PROC = 1,      /* wait for the process to complete */
-+};
-+
-+/* Actually execute the sub-process */
-+int call_usermodehelper_exec(struct subprocess_info *info, enum umh_wait wait);
-+
-+/* Free the subprocess_info. This is only needed if you're not going
-+   to call call_usermodehelper_exec */
-+void call_usermodehelper_freeinfo(struct subprocess_info *info);
+               next = req->wb_index + 1;
+               BUG_ON(!NFS_WBACK_BUSY(req));
  
- static inline int
--call_usermodehelper(char *path, char **argv, char **envp, int wait)
-+call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)
- {
--      return call_usermodehelper_keys(path, argv, envp, NULL, wait);
-+      struct subprocess_info *info;
-+
-+      info = call_usermodehelper_setup(path, argv, envp);
-+      if (info == NULL)
-+              return -ENOMEM;
-+      return call_usermodehelper_exec(info, wait);
-+}
-+
-+static inline int
-+call_usermodehelper_keys(char *path, char **argv, char **envp,
-+                       struct key *session_keyring, enum umh_wait wait)
-+{
-+      struct subprocess_info *info;
-+
-+      info = call_usermodehelper_setup(path, argv, envp);
-+      if (info == NULL)
-+              return -ENOMEM;
-+
-+      call_usermodehelper_setkeys(info, session_keyring);
-+      return call_usermodehelper_exec(info, wait);
+-              kref_get(&req->wb_kref);
++              atomic_inc(&req->wb_count);
+               spin_unlock(&nfsi->req_lock);
+               error = nfs_wait_on_request(req);
+               nfs_release_request(req);
+@@ -577,9 +577,10 @@
+       int res = 0;
+       if (nfsi->ncommit != 0) {
+-              res = nfs_scan_list(nfsi, dst, idx_start, npages,
+-                              NFS_PAGE_TAG_COMMIT);
++              res = nfs_scan_list(nfsi, &nfsi->commit, dst, idx_start, npages);
+               nfsi->ncommit -= res;
++              if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
++                      printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
+       }
+       return res;
  }
+@@ -750,17 +751,12 @@
+ static void nfs_writepage_release(struct nfs_page *req)
+ {
  
- extern void usermodehelper_init(void);
-diff -Nurb linux-2.6.22-570/include/linux/kobject.h linux-2.6.22-590/include/linux/kobject.h
---- linux-2.6.22-570/include/linux/kobject.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/kobject.h   2008-01-02 13:56:37.000000000 -0500
-@@ -55,7 +55,7 @@
-       struct kobject          * parent;
-       struct kset             * kset;
-       struct kobj_type        * ktype;
--      struct dentry           * dentry;
-+      struct sysfs_dirent     * sd;
-       wait_queue_head_t       poll;
- };
+-      if (PageError(req->wb_page)) {
+-              nfs_end_page_writeback(req->wb_page);
+-              nfs_inode_remove_request(req);
+-      } else if (!nfs_reschedule_unstable_write(req)) {
+-              /* Set the PG_uptodate flag */
+-              nfs_mark_uptodate(req->wb_page, req->wb_pgbase, req->wb_bytes);
++      if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) {
+               nfs_end_page_writeback(req->wb_page);
+               nfs_inode_remove_request(req);
+       } else
+               nfs_end_page_writeback(req->wb_page);
+-      nfs_clear_page_tag_locked(req);
++      nfs_clear_page_writeback(req);
+ }
  
-@@ -71,13 +71,9 @@
- extern void kobject_cleanup(struct kobject *);
+ static inline int flush_task_priority(int how)
+@@ -790,7 +786,7 @@
+        * NB: take care not to mess about with data->commit et al. */
  
- extern int __must_check kobject_add(struct kobject *);
--extern int __must_check kobject_shadow_add(struct kobject *, struct dentry *);
- extern void kobject_del(struct kobject *);
+       data->req = req;
+-      data->inode = inode = req->wb_context->path.dentry->d_inode;
++      data->inode = inode = req->wb_context->dentry->d_inode;
+       data->cred = req->wb_context->cred;
  
- extern int __must_check kobject_rename(struct kobject *, const char *new_name);
--extern int __must_check kobject_shadow_rename(struct kobject *kobj,
--                                              struct dentry *new_parent,
--                                              const char *new_name);
- extern int __must_check kobject_move(struct kobject *, struct kobject *);
+       data->args.fh     = NFS_FH(inode);
+@@ -889,7 +885,7 @@
+       }
+       nfs_redirty_request(req);
+       nfs_end_page_writeback(req->wb_page);
+-      nfs_clear_page_tag_locked(req);
++      nfs_clear_page_writeback(req);
+       return -ENOMEM;
+ }
  
- extern int __must_check kobject_register(struct kobject *);
-diff -Nurb linux-2.6.22-570/include/linux/ktime.h linux-2.6.22-590/include/linux/ktime.h
---- linux-2.6.22-570/include/linux/ktime.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/ktime.h     2008-01-02 13:56:37.000000000 -0500
-@@ -279,6 +279,16 @@
-       return (s64) tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
+@@ -932,7 +928,7 @@
+               nfs_list_remove_request(req);
+               nfs_redirty_request(req);
+               nfs_end_page_writeback(req->wb_page);
+-              nfs_clear_page_tag_locked(req);
++              nfs_clear_page_writeback(req);
+       }
+       return -ENOMEM;
  }
+@@ -958,8 +954,8 @@
+       struct page             *page = req->wb_page;
  
-+static inline s64 ktime_us_delta(const ktime_t later, const ktime_t earlier)
-+{
-+       return ktime_to_us(ktime_sub(later, earlier));
-+}
-+
-+static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec)
-+{
-+      return ktime_add_ns(kt, usec * 1000);
-+}
-+
- /*
-  * The resolution of the clocks. The resolution value is returned in
-  * the clock_getres() system call to give application programmers an
-diff -Nurb linux-2.6.22-570/include/linux/magic.h linux-2.6.22-590/include/linux/magic.h
---- linux-2.6.22-570/include/linux/magic.h     2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/magic.h     2008-01-02 13:56:37.000000000 -0500
-@@ -36,8 +36,12 @@
- #define REISERFS_SUPER_MAGIC_STRING   "ReIsErFs"
- #define REISER2FS_SUPER_MAGIC_STRING  "ReIsEr2Fs"
- #define REISER2FS_JR_SUPER_MAGIC_STRING       "ReIsEr3Fs"
-+#define REVOKEFS_MAGIC                0x5245564B      /* REVK */
-+
-+#define UNIONFS_SUPER_MAGIC 0xf15f083d
+       dprintk("NFS: write (%s/%Ld %d@%Ld)",
+-              req->wb_context->path.dentry->d_inode->i_sb->s_id,
+-              (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
++              req->wb_context->dentry->d_inode->i_sb->s_id,
++              (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+               req->wb_bytes,
+               (long long)req_offset(req));
  
- #define SMB_SUPER_MAGIC               0x517B
- #define USBDEVICE_SUPER_MAGIC 0x9fa2
-+#define CONTAINER_SUPER_MAGIC 0x27e0eb
+@@ -1024,8 +1020,8 @@
+               page = req->wb_page;
  
- #endif /* __LINUX_MAGIC_H__ */
-diff -Nurb linux-2.6.22-570/include/linux/mempolicy.h linux-2.6.22-590/include/linux/mempolicy.h
---- linux-2.6.22-570/include/linux/mempolicy.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/mempolicy.h 2008-01-02 13:56:37.000000000 -0500
-@@ -148,18 +148,10 @@
-                                       const nodemask_t *new);
- extern void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new);
- extern void mpol_fix_fork_child_flag(struct task_struct *p);
--#define set_cpuset_being_rebound(x) (cpuset_being_rebound = (x))
--
--#ifdef CONFIG_CPUSETS
--#define current_cpuset_is_being_rebound() \
--                              (cpuset_being_rebound == current->cpuset)
--#else
--#define current_cpuset_is_being_rebound() 0
--#endif
+               dprintk("NFS: write (%s/%Ld %d@%Ld)",
+-                      req->wb_context->path.dentry->d_inode->i_sb->s_id,
+-                      (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
++                      req->wb_context->dentry->d_inode->i_sb->s_id,
++                      (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+                       req->wb_bytes,
+                       (long long)req_offset(req));
  
- extern struct mempolicy default_policy;
- extern struct zonelist *huge_zonelist(struct vm_area_struct *vma,
--              unsigned long addr);
-+              unsigned long addr, gfp_t gfp_flags);
- extern unsigned slab_node(struct mempolicy *policy);
+@@ -1043,14 +1039,12 @@
+                       dprintk(" marked for commit\n");
+                       goto next;
+               }
+-              /* Set the PG_uptodate flag? */
+-              nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes);
+               dprintk(" OK\n");
+ remove_request:
+               nfs_end_page_writeback(page);
+               nfs_inode_remove_request(req);
+       next:
+-              nfs_clear_page_tag_locked(req);
++              nfs_clear_page_writeback(req);
+       }
+ }
  
- extern enum zone_type policy_zone;
-@@ -173,8 +165,6 @@
- int do_migrate_pages(struct mm_struct *mm,
-       const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags);
+@@ -1163,7 +1157,7 @@
  
--extern void *cpuset_being_rebound;    /* Trigger mpol_copy vma rebind */
--
- #else
+       list_splice_init(head, &data->pages);
+       first = nfs_list_entry(data->pages.next);
+-      inode = first->wb_context->path.dentry->d_inode;
++      inode = first->wb_context->dentry->d_inode;
  
- struct mempolicy {};
-@@ -253,12 +243,10 @@
- {
+       data->inode       = inode;
+       data->cred        = first->wb_context->cred;
+@@ -1213,7 +1207,7 @@
+               nfs_list_remove_request(req);
+               nfs_mark_request_commit(req);
+               dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
+-              nfs_clear_page_tag_locked(req);
++              nfs_clear_page_writeback(req);
+       }
+       return -ENOMEM;
  }
+@@ -1240,8 +1234,8 @@
+               dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
  
--#define set_cpuset_being_rebound(x) do {} while (0)
--
- static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma,
--              unsigned long addr)
-+              unsigned long addr, gfp_t gfp_flags)
- {
--      return NODE_DATA(0)->node_zonelists + gfp_zone(GFP_HIGHUSER);
-+      return NODE_DATA(0)->node_zonelists + gfp_zone(gfp_flags);
+               dprintk("NFS: commit (%s/%Ld %d@%Ld)",
+-                      req->wb_context->path.dentry->d_inode->i_sb->s_id,
+-                      (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
++                      req->wb_context->dentry->d_inode->i_sb->s_id,
++                      (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+                       req->wb_bytes,
+                       (long long)req_offset(req));
+               if (task->tk_status < 0) {
+@@ -1255,9 +1249,6 @@
+                * returned by the server against all stored verfs. */
+               if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) {
+                       /* We have a match */
+-                      /* Set the PG_uptodate flag */
+-                      nfs_mark_uptodate(req->wb_page, req->wb_pgbase,
+-                                      req->wb_bytes);
+                       nfs_inode_remove_request(req);
+                       dprintk(" OK\n");
+                       goto next;
+@@ -1266,7 +1257,7 @@
+               dprintk(" mismatch\n");
+               nfs_redirty_request(req);
+       next:
+-              nfs_clear_page_tag_locked(req);
++              nfs_clear_page_writeback(req);
+       }
  }
  
- static inline int do_migrate_pages(struct mm_struct *mm,
-diff -Nurb linux-2.6.22-570/include/linux/mm.h linux-2.6.22-590/include/linux/mm.h
---- linux-2.6.22-570/include/linux/mm.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/mm.h        2008-01-02 13:56:37.000000000 -0500
-@@ -42,6 +42,8 @@
- #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
-+#define VM_REVOKED     0x20000000      /* Mapping has been revoked */
-+
- /*
-  * Linux kernel virtual memory manager primitives.
-  * The idea being to have a "virtual" mm in the same way
-@@ -170,6 +172,13 @@
- #define VM_INSERTPAGE 0x02000000      /* The vma has had "vm_insert_page()" done on it */
- #define VM_ALWAYSDUMP 0x04000000      /* Always include in core dumps */
+diff -Nurb linux-2.6.22-590/fs/nfsd/nfs4callback.c linux-2.6.22-570/fs/nfsd/nfs4callback.c
+--- linux-2.6.22-590/fs/nfsd/nfs4callback.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfsd/nfs4callback.c    2007-07-08 19:32:17.000000000 -0400
+@@ -429,23 +429,29 @@
+               goto out_err;
+       }
  
-+#define VM_CAN_INVALIDATE 0x08000000  /* The mapping may be invalidated,
-+                                       * eg. truncate or invalidate_inode_*.
-+                                       * In this case, do_no_page must
-+                                       * return with the page locked.
-+                                       */
-+#define VM_CAN_NONLINEAR 0x10000000   /* Has ->fault & does nonlinear pages */
++      /* Kick rpciod, put the call on the wire. */
++      if (rpciod_up() != 0)
++              goto out_clnt;
 +
- #ifndef VM_STACK_DEFAULT_FLAGS                /* arch can override this */
- #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
- #endif
-@@ -192,6 +201,25 @@
-  */
- extern pgprot_t protection_map[16];
+       /* the task holds a reference to the nfs4_client struct */
+       atomic_inc(&clp->cl_count);
  
-+#define FAULT_FLAG_WRITE      0x01
-+#define FAULT_FLAG_NONLINEAR  0x02
-+
-+/*
-+ * fault_data is filled in the the pagefault handler and passed to the
-+ * vma's ->fault function. That function is responsible for filling in
-+ * 'type', which is the type of fault if a page is returned, or the type
-+ * of error if NULL is returned.
-+ *
-+ * pgoff should be used in favour of address, if possible. If pgoff is
-+ * used, one may set VM_CAN_NONLINEAR in the vma->vm_flags to get
-+ * nonlinear mapping support.
-+ */
-+struct fault_data {
-+      unsigned long address;
-+      pgoff_t pgoff;
-+      unsigned int flags;
-+      int type;
-+};
+       msg.rpc_cred = nfsd4_lookupcred(clp,0);
+       if (IS_ERR(msg.rpc_cred))
+-              goto out_release_clp;
++              goto out_rpciod;
+       status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL);
+       put_rpccred(msg.rpc_cred);
  
- /*
-  * These are the virtual MM functions - opening of an area, closing and
-@@ -201,9 +229,15 @@
- struct vm_operations_struct {
-       void (*open)(struct vm_area_struct * area);
-       void (*close)(struct vm_area_struct * area);
--      struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int *type);
--      unsigned long (*nopfn)(struct vm_area_struct * area, unsigned long address);
--      int (*populate)(struct vm_area_struct * area, unsigned long address, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock);
-+      struct page *(*fault)(struct vm_area_struct *vma,
-+                      struct fault_data *fdata);
-+      struct page *(*nopage)(struct vm_area_struct *area,
-+                      unsigned long address, int *type);
-+      unsigned long (*nopfn)(struct vm_area_struct *area,
-+                      unsigned long address);
-+      int (*populate)(struct vm_area_struct *area, unsigned long address,
-+                      unsigned long len, pgprot_t prot, unsigned long pgoff,
-+                      int nonblock);
+       if (status != 0) {
+               dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n");
+-              goto out_release_clp;
++              goto out_rpciod;
+       }
+       return;
  
-       /* notification that a previously read-only page is about to become
-        * writable, if an error is returned it will cause a SIGBUS */
-@@ -656,7 +690,6 @@
-  */
- #define NOPAGE_SIGBUS (NULL)
- #define NOPAGE_OOM    ((struct page *) (-1))
--#define NOPAGE_REFAULT        ((struct page *) (-2))  /* Return to userspace, rerun */
+-out_release_clp:
++out_rpciod:
+       atomic_dec(&clp->cl_count);
++      rpciod_down();
++out_clnt:
+       rpc_shutdown_client(cb->cb_client);
+ out_err:
+       cb->cb_client = NULL;
+diff -Nurb linux-2.6.22-590/fs/nfsd/nfs4state.c linux-2.6.22-570/fs/nfsd/nfs4state.c
+--- linux-2.6.22-590/fs/nfsd/nfs4state.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfsd/nfs4state.c       2007-07-08 19:32:17.000000000 -0400
+@@ -378,6 +378,7 @@
+       if (clnt) {
+               clp->cl_callback.cb_client = NULL;
+               rpc_shutdown_client(clnt);
++              rpciod_down();
+       }
+ }
  
- /*
-  * Error return values for the *_nopfn functions
-@@ -744,6 +777,16 @@
-               struct vm_area_struct *start_vma, unsigned long start_addr,
-               unsigned long end_addr, unsigned long *nr_accounted,
-               struct zap_details *);
-+
-+struct mm_walk {
-+      int (*pgd_entry)(pgd_t *, unsigned long, unsigned long, void *);
-+      int (*pud_entry)(pud_t *, unsigned long, unsigned long, void *);
-+      int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, void *);
-+      int (*pte_entry)(pte_t *, unsigned long, unsigned long, void *);
-+};
-+
-+int walk_page_range(struct mm_struct *, unsigned long addr, unsigned long end,
-+                  struct mm_walk *walk, void *private);
- void free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
-               unsigned long end, unsigned long floor, unsigned long ceiling);
- void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *start_vma,
-@@ -1058,6 +1101,7 @@
- extern int insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
- extern void __vma_link_rb(struct mm_struct *, struct vm_area_struct *,
-       struct rb_node **, struct rb_node *);
-+extern void __unlink_file_vma(struct vm_area_struct *);
- extern void unlink_file_vma(struct vm_area_struct *);
- extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
-       unsigned long addr, unsigned long len, pgoff_t pgoff);
-@@ -1097,9 +1141,11 @@
-                                      loff_t lstart, loff_t lend);
+diff -Nurb linux-2.6.22-590/fs/nfsd/nfssvc.c linux-2.6.22-570/fs/nfsd/nfssvc.c
+--- linux-2.6.22-590/fs/nfsd/nfssvc.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/nfsd/nfssvc.c  2007-07-08 19:32:17.000000000 -0400
+@@ -19,7 +19,6 @@
+ #include <linux/slab.h>
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
+-#include <linux/freezer.h>
+ #include <linux/fs_struct.h>
  
- /* generic vm_area_ops exported for stackable file systems */
--extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int *);
--extern int filemap_populate(struct vm_area_struct *, unsigned long,
--              unsigned long, pgprot_t, unsigned long, int);
-+extern struct page *filemap_fault(struct vm_area_struct *, struct fault_data *);
-+extern struct page * __deprecated_for_modules
-+filemap_nopage(struct vm_area_struct *, unsigned long, int *);
-+extern int __deprecated_for_modules filemap_populate(struct vm_area_struct *,
-+              unsigned long, unsigned long, pgprot_t, unsigned long, int);
+ #include <linux/sunrpc/types.h>
+@@ -433,7 +432,6 @@
+        * dirty pages.
+        */
+       current->flags |= PF_LESS_THROTTLE;
+-      set_freezable();
  
- /* mm/page-writeback.c */
- int write_one_page(struct page *page, int wait);
-@@ -1199,6 +1245,7 @@
-                                       void __user *, size_t *, loff_t *);
- unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
-                       unsigned long lru_pages);
-+extern void drop_pagecache_sb(struct super_block *);
- void drop_pagecache(void);
- void drop_slab(void);
+       /*
+        * The main request loop
+diff -Nurb linux-2.6.22-590/fs/ocfs2/alloc.c linux-2.6.22-570/fs/ocfs2/alloc.c
+--- linux-2.6.22-590/fs/ocfs2/alloc.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/alloc.c  2007-07-08 19:32:17.000000000 -0400
+@@ -50,8 +50,6 @@
+ #include "buffer_head_io.h"
  
-diff -Nurb linux-2.6.22-570/include/linux/mmc/card.h linux-2.6.22-590/include/linux/mmc/card.h
---- linux-2.6.22-570/include/linux/mmc/card.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/mmc/card.h  2008-01-02 13:56:37.000000000 -0500
-@@ -72,6 +72,7 @@
- #define MMC_STATE_READONLY    (1<<1)          /* card is read-only */
- #define MMC_STATE_HIGHSPEED   (1<<2)          /* card is in high speed mode */
- #define MMC_STATE_BLOCKADDR   (1<<3)          /* card uses block-addressing */
-+#define MMC_STATE_LOCKED      (1<<4)          /* card is currently locked */
-       u32                     raw_cid[4];     /* raw card CID */
-       u32                     raw_csd[4];     /* raw card CSD */
-       u32                     raw_scr[2];     /* raw card SCR */
-@@ -89,11 +90,16 @@
- #define mmc_card_readonly(c)  ((c)->state & MMC_STATE_READONLY)
- #define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
- #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
-+#define mmc_card_locked(c)    ((c)->state & MMC_STATE_LOCKED)
-+
-+#define mmc_card_lockable(c)  (((c)->csd.cmdclass & CCC_LOCK_CARD) && \
-+                              ((c)->host->caps & MMC_CAP_BYTEBLOCK))
+ static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc);
+-static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
+-                                       struct ocfs2_extent_block *eb);
  
- #define mmc_card_set_present(c)       ((c)->state |= MMC_STATE_PRESENT)
- #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
- #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
- #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
-+#define mmc_card_set_locked(c)        ((c)->state |= MMC_STATE_LOCKED)
+ /*
+  * Structures which describe a path through a btree, and functions to
+@@ -119,31 +117,6 @@
+ }
  
- #define mmc_card_name(c)      ((c)->cid.prod_name)
- #define mmc_card_id(c)                ((c)->dev.bus_id)
-diff -Nurb linux-2.6.22-570/include/linux/mmc/mmc.h linux-2.6.22-590/include/linux/mmc/mmc.h
---- linux-2.6.22-570/include/linux/mmc/mmc.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/mmc/mmc.h   2008-01-02 13:56:37.000000000 -0500
-@@ -253,5 +253,13 @@
- #define MMC_SWITCH_MODE_CLEAR_BITS    0x02    /* Clear bits which are 1 in value */
- #define MMC_SWITCH_MODE_WRITE_BYTE    0x03    /* Set target to value */
+ /*
+- * All the elements of src into dest. After this call, src could be freed
+- * without affecting dest.
+- *
+- * Both paths should have the same root. Any non-root elements of dest
+- * will be freed.
+- */
+-static void ocfs2_cp_path(struct ocfs2_path *dest, struct ocfs2_path *src)
+-{
+-      int i;
+-
+-      BUG_ON(path_root_bh(dest) != path_root_bh(src));
+-      BUG_ON(path_root_el(dest) != path_root_el(src));
+-
+-      ocfs2_reinit_path(dest, 1);
+-
+-      for(i = 1; i < OCFS2_MAX_PATH_DEPTH; i++) {
+-              dest->p_node[i].bh = src->p_node[i].bh;
+-              dest->p_node[i].el = src->p_node[i].el;
+-
+-              if (dest->p_node[i].bh)
+-                      get_bh(dest->p_node[i].bh);
+-      }
+-}
+-
+-/*
+  * Make the *dest path the same as src and re-initialize src path to
+  * have a root only.
+  */
+@@ -239,41 +212,10 @@
+       return ret;
+ }
  
-+/*
-+ * MMC_LOCK_UNLOCK modes
-+ */
-+#define MMC_LOCK_MODE_ERASE   (1<<3)
-+#define MMC_LOCK_MODE_UNLOCK  (1<<2)
-+#define MMC_LOCK_MODE_CLR_PWD (1<<1)
-+#define MMC_LOCK_MODE_SET_PWD (1<<0)
-+
- #endif  /* MMC_MMC_PROTOCOL_H */
+-/*
+- * Return the index of the extent record which contains cluster #v_cluster.
+- * -1 is returned if it was not found.
+- *
+- * Should work fine on interior and exterior nodes.
+- */
+-int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster)
+-{
+-      int ret = -1;
+-      int i;
+-      struct ocfs2_extent_rec *rec;
+-      u32 rec_end, rec_start, clusters;
+-
+-      for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
+-              rec = &el->l_recs[i];
+-
+-              rec_start = le32_to_cpu(rec->e_cpos);
+-              clusters = ocfs2_rec_clusters(el, rec);
+-
+-              rec_end = rec_start + clusters;
+-
+-              if (v_cluster >= rec_start && v_cluster < rec_end) {
+-                      ret = i;
+-                      break;
+-              }
+-      }
+-
+-      return ret;
+-}
+-
+ enum ocfs2_contig_type {
+       CONTIG_NONE = 0,
+       CONTIG_LEFT,
+-      CONTIG_RIGHT,
+-      CONTIG_LEFTRIGHT,
++      CONTIG_RIGHT
+ };
  
-diff -Nurb linux-2.6.22-570/include/linux/mmzone.h linux-2.6.22-590/include/linux/mmzone.h
---- linux-2.6.22-570/include/linux/mmzone.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/mmzone.h    2008-01-02 13:56:37.000000000 -0500
-@@ -13,6 +13,7 @@
- #include <linux/init.h>
- #include <linux/seqlock.h>
- #include <linux/nodemask.h>
-+#include <linux/pageblock-flags.h>
- #include <asm/atomic.h>
- #include <asm/page.h>
  
-@@ -24,8 +25,24 @@
- #endif
- #define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1))
+@@ -311,14 +253,6 @@
+ {
+       u64 blkno = le64_to_cpu(insert_rec->e_blkno);
  
-+#ifdef CONFIG_PAGE_GROUP_BY_MOBILITY
-+#define MIGRATE_UNMOVABLE     0
-+#define MIGRATE_RECLAIMABLE   1
-+#define MIGRATE_MOVABLE       2
-+#define MIGRATE_TYPES         3
-+#else
-+#define MIGRATE_UNMOVABLE     0
-+#define MIGRATE_UNRECLAIMABLE 0
-+#define MIGRATE_MOVABLE       0
-+#define MIGRATE_TYPES         1
-+#endif
-+
-+#define for_each_migratetype_order(order, type) \
-+      for (order = 0; order < MAX_ORDER; order++) \
-+              for (type = 0; type < MIGRATE_TYPES; type++)
-+
- struct free_area {
--      struct list_head        free_list;
-+      struct list_head        free_list[MIGRATE_TYPES];
-       unsigned long           nr_free;
+-      /*
+-       * Refuse to coalesce extent records with different flag
+-       * fields - we don't want to mix unwritten extents with user
+-       * data.
+-       */
+-      if (ext->e_flags != insert_rec->e_flags)
+-              return CONTIG_NONE;
+-
+       if (ocfs2_extents_adjacent(ext, insert_rec) &&
+           ocfs2_block_extent_contig(inode->i_sb, ext, blkno))
+                       return CONTIG_RIGHT;
+@@ -343,14 +277,7 @@
+       APPEND_TAIL,
  };
  
-@@ -213,6 +230,14 @@
- #endif
-       struct free_area        free_area[MAX_ORDER];
+-enum ocfs2_split_type {
+-      SPLIT_NONE = 0,
+-      SPLIT_LEFT,
+-      SPLIT_RIGHT,
+-};
+-
+ struct ocfs2_insert_type {
+-      enum ocfs2_split_type   ins_split;
+       enum ocfs2_append_type  ins_appending;
+       enum ocfs2_contig_type  ins_contig;
+       int                     ins_contig_index;
+@@ -358,13 +285,6 @@
+       int                     ins_tree_depth;
+ };
  
-+#ifndef CONFIG_SPARSEMEM
-+      /*
-+       * Flags for a MAX_ORDER_NR_PAGES block. See pageblock-flags.h.
-+       * In SPARSEMEM, this map is stored in struct mem_section
-+       */
-+      unsigned long           *pageblock_flags;
-+#endif /* CONFIG_SPARSEMEM */
+-struct ocfs2_merge_ctxt {
+-      enum ocfs2_contig_type  c_contig_type;
+-      int                     c_has_empty_extent;
+-      int                     c_split_covers_rec;
+-      int                     c_used_tail_recs;
+-};
+-
+ /*
+  * How many free extents have we got before we need more meta data?
+  */
+@@ -464,7 +384,13 @@
+                       strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE);
+                       eb->h_blkno = cpu_to_le64(first_blkno);
+                       eb->h_fs_generation = cpu_to_le32(osb->fs_generation);
 +
++#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
++                      /* we always use slot zero's suballocator */
++                      eb->h_suballoc_slot = 0;
++#else
+                       eb->h_suballoc_slot = cpu_to_le16(osb->slot_num);
++#endif
+                       eb->h_suballoc_bit = cpu_to_le16(suballoc_bit_start);
+                       eb->h_list.l_count =
+                               cpu_to_le16(ocfs2_extent_recs_per_eb(osb->sb));
+@@ -535,7 +461,7 @@
+                           struct inode *inode,
+                           struct buffer_head *fe_bh,
+                           struct buffer_head *eb_bh,
+-                          struct buffer_head **last_eb_bh,
++                          struct buffer_head *last_eb_bh,
+                           struct ocfs2_alloc_context *meta_ac)
+ {
+       int status, new_blocks, i;
+@@ -550,7 +476,7 @@
  
-       ZONE_PADDING(_pad1_)
+       mlog_entry_void();
  
-@@ -468,6 +493,7 @@
- void get_zone_counts(unsigned long *active, unsigned long *inactive,
-                       unsigned long *free);
- void build_all_zonelists(void);
-+void raise_kswapd_order(unsigned int order);
- void wakeup_kswapd(struct zone *zone, int order);
- int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
-               int classzone_idx, int alloc_flags);
-@@ -662,6 +688,9 @@
- #define PAGES_PER_SECTION       (1UL << PFN_SECTION_SHIFT)
- #define PAGE_SECTION_MASK     (~(PAGES_PER_SECTION-1))
+-      BUG_ON(!last_eb_bh || !*last_eb_bh);
++      BUG_ON(!last_eb_bh);
  
-+#define SECTION_BLOCKFLAGS_BITS \
-+              ((SECTION_SIZE_BITS - (MAX_ORDER-1)) * NR_PAGEBLOCK_BITS)
-+
- #if (MAX_ORDER - 1 + PAGE_SHIFT) > SECTION_SIZE_BITS
- #error Allocator MAX_ORDER exceeds SECTION_SIZE
- #endif
-@@ -681,6 +710,7 @@
-        * before using it wrong.
-        */
-       unsigned long section_mem_map;
-+      DECLARE_BITMAP(pageblock_flags, SECTION_BLOCKFLAGS_BITS);
- };
+       fe = (struct ocfs2_dinode *) fe_bh->b_data;
  
- #ifdef CONFIG_SPARSEMEM_EXTREME
-diff -Nurb linux-2.6.22-570/include/linux/mnt_namespace.h linux-2.6.22-590/include/linux/mnt_namespace.h
---- linux-2.6.22-570/include/linux/mnt_namespace.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/mnt_namespace.h     2008-01-02 13:56:37.000000000 -0500
-@@ -14,7 +14,7 @@
-       int event;
- };
+@@ -581,7 +507,7 @@
+               goto bail;
+       }
  
--extern struct mnt_namespace *copy_mnt_ns(int, struct mnt_namespace *,
-+extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
-               struct fs_struct *);
- extern void __put_mnt_ns(struct mnt_namespace *ns);
+-      eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
++      eb = (struct ocfs2_extent_block *)last_eb_bh->b_data;
+       new_cpos = ocfs2_sum_rightmost_rec(&eb->h_list);
  
-diff -Nurb linux-2.6.22-570/include/linux/module.h linux-2.6.22-590/include/linux/module.h
---- linux-2.6.22-570/include/linux/module.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/module.h    2008-01-02 13:56:37.000000000 -0500
-@@ -227,8 +227,17 @@
-       MODULE_STATE_LIVE,
-       MODULE_STATE_COMING,
-       MODULE_STATE_GOING,
-+      MODULE_STATE_GONE,
- };
+       /* Note: new_eb_bhs[new_blocks - 1] is the guy which will be
+@@ -642,7 +568,7 @@
+        * journal_dirty erroring as it won't unless we've aborted the
+        * handle (in which case we would never be here) so reserving
+        * the write with journal_access is all we need to do. */
+-      status = ocfs2_journal_access(handle, inode, *last_eb_bh,
++      status = ocfs2_journal_access(handle, inode, last_eb_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       if (status < 0) {
+               mlog_errno(status);
+@@ -675,10 +601,10 @@
+        * next_leaf on the previously last-extent-block. */
+       fe->i_last_eb_blk = cpu_to_le64(new_last_eb_blk);
  
-+#ifdef CONFIG_KGDB
-+#define MAX_SECTNAME 31
-+struct mod_section {
-+       void *address;
-+       char name[MAX_SECTNAME + 1];
-+};
-+#endif
-+
- /* Similar stuff for section attributes. */
- struct module_sect_attr
- {
-@@ -256,6 +265,13 @@
-       /* Unique handle for this module */
-       char name[MODULE_NAME_LEN];
+-      eb = (struct ocfs2_extent_block *) (*last_eb_bh)->b_data;
++      eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+       eb->h_next_leaf_blk = cpu_to_le64(new_last_eb_blk);
  
-+#ifdef CONFIG_KGDB
-+      /* keep kgdb info at the begining so that gdb doesn't have a chance to
-+       * miss out any fields */
-+      unsigned long num_sections;
-+      struct mod_section *mod_sections;
-+#endif
-+
-       /* Sysfs stuff. */
-       struct module_kobject mkobj;
-       struct module_param_attrs *param_attrs;
-diff -Nurb linux-2.6.22-570/include/linux/namei.h linux-2.6.22-590/include/linux/namei.h
---- linux-2.6.22-570/include/linux/namei.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/namei.h     2008-01-02 13:56:37.000000000 -0500
-@@ -3,6 +3,7 @@
+-      status = ocfs2_journal_dirty(handle, *last_eb_bh);
++      status = ocfs2_journal_dirty(handle, last_eb_bh);
+       if (status < 0)
+               mlog_errno(status);
+       status = ocfs2_journal_dirty(handle, fe_bh);
+@@ -690,14 +616,6 @@
+                       mlog_errno(status);
+       }
  
- #include <linux/dcache.h>
- #include <linux/linkage.h>
-+#include <linux/mount.h>
+-      /*
+-       * Some callers want to track the rightmost leaf so pass it
+-       * back here.
+-       */
+-      brelse(*last_eb_bh);
+-      get_bh(new_eb_bhs[0]);
+-      *last_eb_bh = new_eb_bhs[0];
+-
+       status = 0;
+ bail:
+       if (new_eb_bhs) {
+@@ -911,87 +829,6 @@
+ }
  
- struct vfsmount;
+ /*
+- * Grow a b-tree so that it has more records.
+- *
+- * We might shift the tree depth in which case existing paths should
+- * be considered invalid.
+- *
+- * Tree depth after the grow is returned via *final_depth.
+- *
+- * *last_eb_bh will be updated by ocfs2_add_branch().
+- */
+-static int ocfs2_grow_tree(struct inode *inode, handle_t *handle,
+-                         struct buffer_head *di_bh, int *final_depth,
+-                         struct buffer_head **last_eb_bh,
+-                         struct ocfs2_alloc_context *meta_ac)
+-{
+-      int ret, shift;
+-      struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+-      int depth = le16_to_cpu(di->id2.i_list.l_tree_depth);
+-      struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+-      struct buffer_head *bh = NULL;
+-
+-      BUG_ON(meta_ac == NULL);
+-
+-      shift = ocfs2_find_branch_target(osb, inode, di_bh, &bh);
+-      if (shift < 0) {
+-              ret = shift;
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      /* We traveled all the way to the bottom of the allocation tree
+-       * and didn't find room for any more extents - we need to add
+-       * another tree level */
+-      if (shift) {
+-              BUG_ON(bh);
+-              mlog(0, "need to shift tree depth (current = %d)\n", depth);
+-
+-              /* ocfs2_shift_tree_depth will return us a buffer with
+-               * the new extent block (so we can pass that to
+-               * ocfs2_add_branch). */
+-              ret = ocfs2_shift_tree_depth(osb, handle, inode, di_bh,
+-                                           meta_ac, &bh);
+-              if (ret < 0) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
+-              depth++;
+-              if (depth == 1) {
+-                      /*
+-                       * Special case: we have room now if we shifted from
+-                       * tree_depth 0, so no more work needs to be done.
+-                       *
+-                       * We won't be calling add_branch, so pass
+-                       * back *last_eb_bh as the new leaf. At depth
+-                       * zero, it should always be null so there's
+-                       * no reason to brelse.
+-                       */
+-                      BUG_ON(*last_eb_bh);
+-                      get_bh(bh);
+-                      *last_eb_bh = bh;
+-                      goto out;
+-              }
+-      }
+-
+-      /* call ocfs2_add_branch to add the final part of the tree with
+-       * the new data. */
+-      mlog(0, "add branch. bh = %p\n", bh);
+-      ret = ocfs2_add_branch(osb, handle, inode, di_bh, bh, last_eb_bh,
+-                             meta_ac);
+-      if (ret < 0) {
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-out:
+-      if (final_depth)
+-              *final_depth = depth;
+-      brelse(bh);
+-      return ret;
+-}
+-
+-/*
+  * This is only valid for leaf nodes, which are the only ones that can
+  * have empty extents anyway.
+  */
+@@ -1097,22 +934,6 @@
  
-@@ -81,9 +82,16 @@
- extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
- extern void release_open_intent(struct nameidata *);
+ }
  
--extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
-+extern struct dentry * lookup_one_len_nd(const char *, struct dentry *,
-+                                       int, struct nameidata *);
- extern struct dentry *lookup_one_len_kern(const char *, struct dentry *, int);
+-static void ocfs2_remove_empty_extent(struct ocfs2_extent_list *el)
+-{
+-      int size, num_recs = le16_to_cpu(el->l_next_free_rec);
+-
+-      BUG_ON(num_recs == 0);
+-
+-      if (ocfs2_is_empty_extent(&el->l_recs[0])) {
+-              num_recs--;
+-              size = num_recs * sizeof(struct ocfs2_extent_rec);
+-              memmove(&el->l_recs[0], &el->l_recs[1], size);
+-              memset(&el->l_recs[num_recs], 0,
+-                     sizeof(struct ocfs2_extent_rec));
+-              el->l_next_free_rec = cpu_to_le16(num_recs);
+-      }
+-}
+-
+ /*
+  * Create an empty extent record .
+  *
+@@ -1390,10 +1211,6 @@
+        * immediately to their right.
+        */
+       left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);
+-      if (ocfs2_is_empty_extent(&right_child_el->l_recs[0])) {
+-              BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1);
+-              left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);
+-      }
+       left_clusters -= le32_to_cpu(left_rec->e_cpos);
+       left_rec->e_int_clusters = cpu_to_le32(left_clusters);
  
-+static inline struct dentry *lookup_one_len(const char *name,
-+                      struct dentry *dir, int len)
-+{
-+      return lookup_one_len_nd(name, dir, len, NULL);
-+}
-+
- extern int follow_down(struct vfsmount **, struct dentry **);
- extern int follow_up(struct vfsmount **, struct dentry **);
+@@ -1714,16 +1531,10 @@
+       return ret;
+ }
  
-@@ -100,4 +108,16 @@
-       return nd->saved_names[nd->depth];
+-/*
+- * Extend the transaction by enough credits to complete the rotation,
+- * and still leave at least the original number of credits allocated
+- * to this transaction.
+- */
+ static int ocfs2_extend_rotate_transaction(handle_t *handle, int subtree_depth,
+-                                         int op_credits,
+                                          struct ocfs2_path *path)
+ {
+-      int credits = (path->p_tree_depth - subtree_depth) * 2 + 1 + op_credits;
++      int credits = (path->p_tree_depth - subtree_depth) * 2 + 1;
+       if (handle->h_buffer_credits < credits)
+               return ocfs2_extend_trans(handle, credits);
+@@ -1757,29 +1568,6 @@
+       return 0;
  }
  
-+static inline void pathget(struct path *path)
-+{
-+      mntget(path->mnt);
-+      dget(path->dentry);
-+}
-+
-+static inline void pathput(struct path *path)
-+{
-+      dput(path->dentry);
-+      mntput(path->mnt);
-+}
-+
- #endif /* _LINUX_NAMEI_H */
-diff -Nurb linux-2.6.22-570/include/linux/net.h linux-2.6.22-590/include/linux/net.h
---- linux-2.6.22-570/include/linux/net.h       2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/net.h       2008-01-02 13:56:37.000000000 -0500
-@@ -23,6 +23,7 @@
+-static int ocfs2_leftmost_rec_contains(struct ocfs2_extent_list *el, u32 cpos)
+-{
+-      int next_free = le16_to_cpu(el->l_next_free_rec);
+-      unsigned int range;
+-      struct ocfs2_extent_rec *rec;
+-
+-      if (next_free == 0)
+-              return 0;
+-
+-      rec = &el->l_recs[0];
+-      if (ocfs2_is_empty_extent(rec)) {
+-              /* Empty list. */
+-              if (next_free == 1)
+-                      return 0;
+-              rec = &el->l_recs[1];
+-      }
+-
+-      range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+-      if (cpos >= le32_to_cpu(rec->e_cpos) && cpos < range)
+-              return 1;
+-      return 0;
+-}
+-
+ /*
+  * Rotate all the records in a btree right one record, starting at insert_cpos.
+  *
+@@ -1798,12 +1586,11 @@
+  */
+ static int ocfs2_rotate_tree_right(struct inode *inode,
+                                  handle_t *handle,
+-                                 enum ocfs2_split_type split,
+                                  u32 insert_cpos,
+                                  struct ocfs2_path *right_path,
+                                  struct ocfs2_path **ret_left_path)
+ {
+-      int ret, start, orig_credits = handle->h_buffer_credits;
++      int ret, start;
+       u32 cpos;
+       struct ocfs2_path *left_path = NULL;
  
- struct poll_table_struct;
- struct inode;
-+struct net;
+@@ -1870,9 +1657,9 @@
+                               (unsigned long long)
+                               path_leaf_bh(left_path)->b_blocknr);
  
- #define NPROTO                34              /* should be enough for now..   */
+-              if (split == SPLIT_NONE &&
+-                  ocfs2_rotate_requires_path_adjustment(left_path,
++              if (ocfs2_rotate_requires_path_adjustment(left_path,
+                                                         insert_cpos)) {
++                      mlog(0, "Path adjustment required\n");
  
-@@ -170,7 +171,7 @@
+                       /*
+                        * We've rotated the tree as much as we
+@@ -1900,7 +1687,7 @@
+                    right_path->p_tree_depth);
  
- struct net_proto_family {
-       int             family;
--      int             (*create)(struct socket *sock, int protocol);
-+      int             (*create)(struct net *net, struct socket *sock, int protocol);
-       struct module   *owner;
- };
+               ret = ocfs2_extend_rotate_transaction(handle, start,
+-                                                    orig_credits, right_path);
++                                                    right_path);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+@@ -1913,24 +1700,6 @@
+                       goto out;
+               }
  
-diff -Nurb linux-2.6.22-570/include/linux/netdevice.h linux-2.6.22-590/include/linux/netdevice.h
---- linux-2.6.22-570/include/linux/netdevice.h 2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/include/linux/netdevice.h 2008-01-02 13:56:37.000000000 -0500
-@@ -39,6 +39,7 @@
- #include <linux/percpu.h>
- #include <linux/dmaengine.h>
+-              if (split != SPLIT_NONE &&
+-                  ocfs2_leftmost_rec_contains(path_leaf_el(right_path),
+-                                              insert_cpos)) {
+-                      /*
+-                       * A rotate moves the rightmost left leaf
+-                       * record over to the leftmost right leaf
+-                       * slot. If we're doing an extent split
+-                       * instead of a real insert, then we have to
+-                       * check that the extent to be split wasn't
+-                       * just moved over. If it was, then we can
+-                       * exit here, passing left_path back -
+-                       * ocfs2_split_extent() is smart enough to
+-                       * search both leaves.
+-                       */
+-                      *ret_left_path = left_path;
+-                      goto out_ret_path;
+-              }
+-
+               /*
+                * There is no need to re-read the next right path
+                * as we know that it'll be our current left
+@@ -1953,921 +1722,110 @@
+       return ret;
+ }
  
-+struct net;
- struct vlan_group;
- struct ethtool_ops;
- struct netpoll_info;
-@@ -314,9 +315,10 @@
-       /* Net device features */
-       unsigned long           features;
- #define NETIF_F_SG            1       /* Scatter/gather IO. */
--#define NETIF_F_IP_CSUM               2       /* Can checksum only TCP/UDP over IPv4. */
-+#define NETIF_F_IP_CSUM               2       /* Can checksum TCP/UDP over IPv4. */
- #define NETIF_F_NO_CSUM               4       /* Does not require checksum. F.e. loopack. */
- #define NETIF_F_HW_CSUM               8       /* Can checksum all the packets. */
-+#define NETIF_F_IPV6_CSUM     16      /* Can checksum TCP/UDP over IPV6 */
- #define NETIF_F_HIGHDMA               32      /* Can DMA to high memory. */
- #define NETIF_F_FRAGLIST      64      /* Scatter/gather IO. */
- #define NETIF_F_HW_VLAN_TX    128     /* Transmit VLAN hw acceleration */
-@@ -325,6 +327,7 @@
- #define NETIF_F_VLAN_CHALLENGED       1024    /* Device cannot handle VLAN packets */
- #define NETIF_F_GSO           2048    /* Enable software GSO. */
- #define NETIF_F_LLTX          4096    /* LockLess TX */
-+#define NETIF_F_NETNS_LOCAL   8192    /* Does not change network namespaces */
+-static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
+-                                    struct ocfs2_path *path)
++/*
++ * Do the final bits of extent record insertion at the target leaf
++ * list. If this leaf is part of an allocation tree, it is assumed
++ * that the tree above has been prepared.
++ */
++static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
++                               struct ocfs2_extent_list *el,
++                               struct ocfs2_insert_type *insert,
++                               struct inode *inode)
+ {
+-      int i, idx;
++      int i = insert->ins_contig_index;
++      unsigned int range;
+       struct ocfs2_extent_rec *rec;
+-      struct ocfs2_extent_list *el;
+-      struct ocfs2_extent_block *eb;
+-      u32 range;
  
-       /* Segmentation offload features */
- #define NETIF_F_GSO_SHIFT     16
-@@ -338,8 +341,11 @@
-       /* List of features with software fallbacks. */
- #define NETIF_F_GSO_SOFTWARE  (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
+-      /* Path should always be rightmost. */
+-      eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
+-      BUG_ON(eb->h_next_leaf_blk != 0ULL);
++      BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
  
-+
- #define NETIF_F_GEN_CSUM      (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
--#define NETIF_F_ALL_CSUM      (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
-+#define NETIF_F_V4_CSUM               (NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM)
-+#define NETIF_F_V6_CSUM               (NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
-+#define NETIF_F_ALL_CSUM      (NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)
+-      el = &eb->h_list;
+-      BUG_ON(le16_to_cpu(el->l_next_free_rec) == 0);
+-      idx = le16_to_cpu(el->l_next_free_rec) - 1;
+-      rec = &el->l_recs[idx];
+-      range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
++      /*
++       * Contiguous insert - either left or right.
++       */
++      if (insert->ins_contig != CONTIG_NONE) {
++              rec = &el->l_recs[i];
++              if (insert->ins_contig == CONTIG_LEFT) {
++                      rec->e_blkno = insert_rec->e_blkno;
++                      rec->e_cpos = insert_rec->e_cpos;
++              }
++              le16_add_cpu(&rec->e_leaf_clusters,
++                           le16_to_cpu(insert_rec->e_leaf_clusters));
++              return;
++      }
  
-       struct net_device       *next_sched;
+-      for (i = 0; i < path->p_tree_depth; i++) {
+-              el = path->p_node[i].el;
+-              idx = le16_to_cpu(el->l_next_free_rec) - 1;
+-              rec = &el->l_recs[idx];
++      /*
++       * Handle insert into an empty leaf.
++       */
++      if (le16_to_cpu(el->l_next_free_rec) == 0 ||
++          ((le16_to_cpu(el->l_next_free_rec) == 1) &&
++           ocfs2_is_empty_extent(&el->l_recs[0]))) {
++              el->l_recs[0] = *insert_rec;
++              el->l_next_free_rec = cpu_to_le16(1);
++              return;
++      }
  
-@@ -533,6 +539,9 @@
-       void                    (*poll_controller)(struct net_device *dev);
- #endif
+-              rec->e_int_clusters = cpu_to_le32(range);
+-              le32_add_cpu(&rec->e_int_clusters, -le32_to_cpu(rec->e_cpos));
++      /*
++       * Appending insert.
++       */
++      if (insert->ins_appending == APPEND_TAIL) {
++              i = le16_to_cpu(el->l_next_free_rec) - 1;
++              rec = &el->l_recs[i];
++              range = le32_to_cpu(rec->e_cpos)
++                      + le16_to_cpu(rec->e_leaf_clusters);
++              BUG_ON(le32_to_cpu(insert_rec->e_cpos) < range);
  
-+      /* Network namespace this network device is inside */
-+      struct net              *nd_net;
+-              ocfs2_journal_dirty(handle, path->p_node[i].bh);
++              mlog_bug_on_msg(le16_to_cpu(el->l_next_free_rec) >=
++                              le16_to_cpu(el->l_count),
++                              "inode %lu, depth %u, count %u, next free %u, "
++                              "rec.cpos %u, rec.clusters %u, "
++                              "insert.cpos %u, insert.clusters %u\n",
++                              inode->i_ino,
++                              le16_to_cpu(el->l_tree_depth),
++                              le16_to_cpu(el->l_count),
++                              le16_to_cpu(el->l_next_free_rec),
++                              le32_to_cpu(el->l_recs[i].e_cpos),
++                              le16_to_cpu(el->l_recs[i].e_leaf_clusters),
++                              le32_to_cpu(insert_rec->e_cpos),
++                              le16_to_cpu(insert_rec->e_leaf_clusters));
++              i++;
++              el->l_recs[i] = *insert_rec;
++              le16_add_cpu(&el->l_next_free_rec, 1);
++              return;
+       }
 +
-       /* bridge stuff */
-       struct net_bridge_port  *br_port;
++      /*
++       * Ok, we have to rotate.
++       *
++       * At this point, it is safe to assume that inserting into an
++       * empty leaf and appending to a leaf have both been handled
++       * above.
++       *
++       * This leaf needs to have space, either by the empty 1st
++       * extent record, or by virtue of an l_next_rec < l_count.
++       */
++      ocfs2_rotate_leaf(el, insert_rec);
+ }
  
-@@ -540,13 +549,16 @@
-       struct device           dev;
-       /* space for optional statistics and wireless sysfs groups */
-       struct attribute_group  *sysfs_groups[3];
+-static void ocfs2_unlink_subtree(struct inode *inode, handle_t *handle,
+-                               struct ocfs2_path *left_path,
++static inline void ocfs2_update_dinode_clusters(struct inode *inode,
++                                              struct ocfs2_dinode *di,
++                                              u32 clusters)
++{
++      le32_add_cpu(&di->i_clusters, clusters);
++      spin_lock(&OCFS2_I(inode)->ip_lock);
++      OCFS2_I(inode)->ip_clusters = le32_to_cpu(di->i_clusters);
++      spin_unlock(&OCFS2_I(inode)->ip_lock);
++}
 +
-+      /* rtnetlink link ops */
-+      const struct rtnl_link_ops *rtnl_link_ops;
- };
- #define to_net_dev(d) container_of(d, struct net_device, dev)
- #define       NETDEV_ALIGN            32
- #define       NETDEV_ALIGN_CONST      (NETDEV_ALIGN - 1)
--static inline void *netdev_priv(struct net_device *dev)
-+static inline void *netdev_priv(const struct net_device *dev)
++static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
++                                  struct ocfs2_extent_rec *insert_rec,
+                                   struct ocfs2_path *right_path,
+-                               int subtree_index,
+-                               struct ocfs2_cached_dealloc_ctxt *dealloc)
++                                  struct ocfs2_path **ret_left_path)
  {
-       return (char *)dev + ((sizeof(struct net_device)
-                                       + NETDEV_ALIGN_CONST)
-@@ -576,45 +588,48 @@
- #include <linux/interrupt.h>
- #include <linux/notifier.h>
--extern struct net_device              loopback_dev;           /* The loopback */
--extern struct list_head                       dev_base_head;          /* All devices */
- extern rwlock_t                               dev_base_lock;          /* Device list lock */
+-      int ret, i;
+-      struct buffer_head *root_bh = left_path->p_node[subtree_index].bh;
+-      struct ocfs2_extent_list *root_el = left_path->p_node[subtree_index].el;
+-      struct ocfs2_extent_list *el;
+-      struct ocfs2_extent_block *eb;
++      int ret, i, next_free;
+       struct buffer_head *bh;
++      struct ocfs2_extent_list *el;
++      struct ocfs2_path *left_path = NULL;
  
--#define for_each_netdev(d)            \
--              list_for_each_entry(d, &dev_base_head, dev_list)
--#define for_each_netdev_safe(d, n)    \
--              list_for_each_entry_safe(d, n, &dev_base_head, dev_list)
--#define for_each_netdev_continue(d)           \
--              list_for_each_entry_continue(d, &dev_base_head, dev_list)
--#define net_device_entry(lh)  list_entry(lh, struct net_device, dev_list)
+-      el = path_leaf_el(left_path);
+-
+-      eb = (struct ocfs2_extent_block *)right_path->p_node[subtree_index + 1].bh->b_data;
+-
+-      for(i = 1; i < le16_to_cpu(root_el->l_next_free_rec); i++)
+-              if (root_el->l_recs[i].e_blkno == eb->h_blkno)
+-                      break;
+-
+-      BUG_ON(i >= le16_to_cpu(root_el->l_next_free_rec));
+-
+-      memset(&root_el->l_recs[i], 0, sizeof(struct ocfs2_extent_rec));
+-      le16_add_cpu(&root_el->l_next_free_rec, -1);
+-
+-      eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
+-      eb->h_next_leaf_blk = 0;
+-
+-      ocfs2_journal_dirty(handle, root_bh);
+-      ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
+-
+-      for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
+-              bh = right_path->p_node[i].bh;
+-
+-              eb = (struct ocfs2_extent_block *)bh->b_data;
+-              /*
+-               * Not all nodes might have had their final count
+-               * decremented by the caller - handle this here.
+-               */
+-              el = &eb->h_list;
+-              if (le16_to_cpu(el->l_next_free_rec) > 1) {
+-                      mlog(ML_ERROR,
+-                           "Inode %llu, attempted to remove extent block "
+-                           "%llu with %u records\n",
+-                           (unsigned long long)OCFS2_I(inode)->ip_blkno,
+-                           (unsigned long long)le64_to_cpu(eb->h_blkno),
+-                           le16_to_cpu(el->l_next_free_rec));
+-
+-                      ocfs2_journal_dirty(handle, bh);
+-                      ocfs2_remove_from_cache(inode, bh);
+-                      continue;
+-              }
+-
+-              el->l_next_free_rec = 0;
+-              memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
+-
+-              ocfs2_journal_dirty(handle, bh);
+-
+-              ret = ocfs2_cache_extent_block_free(dealloc, eb);
+-              if (ret)
+-                      mlog_errno(ret);
+-
+-              ocfs2_remove_from_cache(inode, bh);
+-      }
+-}
+-
+-static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
+-                                   struct ocfs2_path *left_path,
+-                                   struct ocfs2_path *right_path,
+-                                   int subtree_index,
+-                                   struct ocfs2_cached_dealloc_ctxt *dealloc,
+-                                   int *deleted)
+-{
+-      int ret, i, del_right_subtree = 0;
+-      struct buffer_head *root_bh, *di_bh = path_root_bh(right_path);
+-      struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+-      struct ocfs2_extent_list *right_leaf_el, *left_leaf_el;
+-      struct ocfs2_extent_block *eb;
+-
+-      *deleted = 0;
+-
+-      right_leaf_el = path_leaf_el(right_path);
+-      left_leaf_el = path_leaf_el(left_path);
+-      root_bh = left_path->p_node[subtree_index].bh;
+-      BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
+-
+-      if (!ocfs2_is_empty_extent(&left_leaf_el->l_recs[0]))
+-              return 0;
+-
+-      if (ocfs2_is_empty_extent(&right_leaf_el->l_recs[0]))
+-              return -EAGAIN;
+-
+-      eb = (struct ocfs2_extent_block *)path_leaf_bh(right_path)->b_data;
+-      if (eb->h_next_leaf_blk == 0ULL &&
+-          le16_to_cpu(right_leaf_el->l_next_free_rec) == 1) {
+-              /*
+-               * We have to update i_last_eb_blk during the meta
+-               * data delete.
+-               */
+-              ret = ocfs2_journal_access(handle, inode, di_bh,
+-                                         OCFS2_JOURNAL_ACCESS_WRITE);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
+-
+-              del_right_subtree = 1;
+-      }
+-
+-      ret = ocfs2_journal_access(handle, inode, root_bh,
+-                                 OCFS2_JOURNAL_ACCESS_WRITE);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
+-              ret = ocfs2_journal_access(handle, inode,
+-                                         right_path->p_node[i].bh,
+-                                         OCFS2_JOURNAL_ACCESS_WRITE);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
+-
+-              ret = ocfs2_journal_access(handle, inode,
+-                                         left_path->p_node[i].bh,
+-                                         OCFS2_JOURNAL_ACCESS_WRITE);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
+-      }
+-
+-      ocfs2_rotate_leaf(left_leaf_el, &right_leaf_el->l_recs[0]);
+-      memset(&right_leaf_el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
+-      if (eb->h_next_leaf_blk == 0ULL) {
+-              /*
+-               * XXX: move recs over to get rid of empty extent,
+-               * decrease next_free. how does this play with the
+-               * delete code below?
+-               */
+-              ocfs2_remove_empty_extent(right_leaf_el);
+-      }
+-
+-      ret = ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
+-      if (ret)
+-              mlog_errno(ret);
+-      ret = ocfs2_journal_dirty(handle, path_leaf_bh(right_path));
+-      if (ret)
+-              mlog_errno(ret);
+-
+-      if (del_right_subtree) {
+-              ocfs2_unlink_subtree(inode, handle, left_path, right_path,
+-                                   subtree_index, dealloc);
+-              ocfs2_update_edge_lengths(inode, handle, left_path);
+-
+-              eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
+-              di->i_last_eb_blk = eb->h_blkno;
+-              ret = ocfs2_journal_dirty(handle, di_bh);
+-              if (ret)
+-                      mlog_errno(ret);
+-
+-              *deleted = 1;
+-      } else
+-              ocfs2_complete_edge_insert(inode, handle, left_path, right_path,
+-                                         subtree_index);
+-
+-out:
+-      return ret;
+-}
+-
+-/*
+- * Given a full path, determine what cpos value would return us a path
+- * containing the leaf immediately to the right of the current one.
+- *
+- * Will return zero if the path passed in is already the rightmost path.
+- *
+- * This looks similar, but is subtly different to
+- * ocfs2_find_cpos_for_left_leaf().
+- */
+-static int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
+-                                        struct ocfs2_path *path, u32 *cpos)
+-{
+-      int i, j, ret = 0;
+-      u64 blkno;
+-      struct ocfs2_extent_list *el;
+-
+-      *cpos = 0;
+-
+-      if (path->p_tree_depth == 0)
+-              return 0;
+-
+-      blkno = path_leaf_bh(path)->b_blocknr;
+-
+-      /* Start at the tree node just above the leaf and work our way up. */
+-      i = path->p_tree_depth - 1;
+-      while (i >= 0) {
+-              int next_free;
+-
+-              el = path->p_node[i].el;
+-
+-              /*
+-               * Find the extent record just after the one in our
+-               * path.
+-               */
+-              next_free = le16_to_cpu(el->l_next_free_rec);
+-              for(j = 0; j < le16_to_cpu(el->l_next_free_rec); j++) {
+-                      if (le64_to_cpu(el->l_recs[j].e_blkno) == blkno) {
+-                              if (j == (next_free - 1)) {
+-                                      if (i == 0) {
+-                                              /*
+-                                               * We've determined that the
+-                                               * path specified is already
+-                                               * the rightmost one - return a
+-                                               * cpos of zero.
+-                                               */
+-                                              goto out;
+-                                      }
+-                                      /*
+-                                       * The rightmost record points to our
+-                                       * leaf - we need to travel up the
+-                                       * tree one level.
+-                                       */
+-                                      goto next_node;
+-                              }
+-
+-                              *cpos = le32_to_cpu(el->l_recs[j + 1].e_cpos);
+-                              goto out;
+-                      }
+-              }
+-
+-              /*
+-               * If we got here, we never found a valid node where
+-               * the tree indicated one should be.
+-               */
+-              ocfs2_error(sb,
+-                          "Invalid extent tree at extent block %llu\n",
+-                          (unsigned long long)blkno);
+-              ret = -EROFS;
+-              goto out;
+-
+-next_node:
+-              blkno = path->p_node[i].bh->b_blocknr;
+-              i--;
+-      }
+-
+-out:
+-      return ret;
+-}
+-
+-static int ocfs2_rotate_rightmost_leaf_left(struct inode *inode,
+-                                          handle_t *handle,
+-                                          struct buffer_head *bh,
+-                                          struct ocfs2_extent_list *el,
+-                                          int *rotated_any)
+-{
+-      int ret;
+-
+-      if (rotated_any)
+-              *rotated_any = 0;
+-
+-      if (!ocfs2_is_empty_extent(&el->l_recs[0]))
+-              return 0;
+-
+-      if (le16_to_cpu(el->l_next_free_rec) == 1)
+-              return -EAGAIN;
+-
+-      ret = ocfs2_journal_access(handle, inode, bh,
+-                                 OCFS2_JOURNAL_ACCESS_WRITE);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      ocfs2_remove_empty_extent(el);
+-
+-      ret = ocfs2_journal_dirty(handle, bh);
+-      if (ret)
+-              mlog_errno(ret);
+-
+-      if (rotated_any)
+-              *rotated_any = 1;
+-out:
+-      return ret;
+-}
+-
+-/*
+- * Left rotation of btree records.
+- *
+- * In many ways, this is (unsurprisingly) the opposite of right
+- * rotation. We start at some non-rightmost path containing an empty
+- * extent in the leaf block. The code works its way to the rightmost
+- * path by rotating records to the left in every subtree.
+- *
+- * There are a few places where we might want to do this:
+- *   - merging extent records
+- *     - rightleft contiguousness during insert
+- *     - merging two previously unwritten extents
+- *   - truncate
+- *     - via ocfs2_truncate, if we ever fix it up to use this code
+- *     - via ioctl at the request of user (reverse fallocate)
+- *   - "compressing" a tree with empty extents
+- *     - as a result of a user defrag request
+- *     - perhaps as a preventative measure if we notice a tree needs
+- *       this during any of the above operations.
+- *
+- * The major difference between those states above are the ability to
+- * lock one of the meta data allocators so that we can remove unused
+- * extent blocks. It might be unrealistic for us to assume that any
+- * merging cases will want to lock the meta data allocator. Luckily,
+- * the merges are an optimization.
+- *
+- * So, merging won't happen if it would result in an empty rightmost
+- * path (this is illegal).
+- *
+- * This function will move extents left until it runs out of leaves to
+- * rotate, or it hits a right leaf that already contains an empty
+- * extent, in which case it will exit early. This means that we might
+- * never rotate anything if the 1st right leaf contains an empty
+- * extent.
+- *
+- * Truncate cases will have to happen as a second step. I'm not
+- * completely sure how we want to handle those yet.
+- */
+-static int ocfs2_rotate_tree_left(struct inode *inode,
+-                                handle_t *handle,
+-                                struct ocfs2_path *path,
+-                                struct ocfs2_cached_dealloc_ctxt *dealloc,
+-                                int *rotated_any)
+-{
+-      int ret, subtree_root, deleted, orig_credits = handle->h_buffer_credits;
+-      u32 right_cpos;
+-      struct ocfs2_path *left_path = NULL;
+-      struct ocfs2_path *right_path = NULL;
+-
+-      BUG_ON(!ocfs2_is_empty_extent(&(path_leaf_el(path)->l_recs[0])));
+-
+-      if (rotated_any)
+-              *rotated_any = 0;
+-
+-      ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, path,
+-                                           &right_cpos);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      if (path->p_tree_depth == 0 || right_cpos == 0) {
+-              /*
+-               * Two cases where rotation of adjacent leaves isn't
+-               * necessary:
+-               *  - in-inode extents (no btree)
+-               *  - path passed is already rightmost
+-               */
+-              ret = ocfs2_rotate_rightmost_leaf_left(inode, handle,
+-                                                     path_leaf_bh(path),
+-                                                     path_leaf_el(path),
+-                                                     rotated_any);
+-              if (ret)
+-                      mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      left_path = ocfs2_new_path(path_root_bh(path),
+-                                 path_root_el(path));
+-      if (!left_path) {
+-              ret = -ENOMEM;
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      ocfs2_cp_path(left_path, path);
+-
+-      right_path = ocfs2_new_path(path_root_bh(path),
+-                                  path_root_el(path));
+-      if (!right_path) {
+-              ret = -ENOMEM;
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      while (right_cpos) {
+-              ret = ocfs2_find_path(inode, right_path, right_cpos);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
+-
+-              subtree_root = ocfs2_find_subtree_root(inode, left_path,
+-                                                     right_path);
+-
+-              mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n",
+-                   subtree_root,
+-                   (unsigned long long)
+-                   right_path->p_node[subtree_root].bh->b_blocknr,
+-                   right_path->p_tree_depth);
+-
+-              ret = ocfs2_extend_rotate_transaction(handle, subtree_root,
+-                                                    orig_credits, left_path);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
 -
--static inline struct net_device *next_net_device(struct net_device *dev)
+-              ret = ocfs2_rotate_subtree_left(inode, handle, left_path,
+-                                              right_path, subtree_root,
+-                                              dealloc, &deleted);
+-              if (ret) {
+-                      if (ret != -EAGAIN)
+-                              mlog_errno(ret);
+-                      goto out;
+-              }
+-
+-              if (rotated_any)
+-                      *rotated_any = 1;
+-
+-              /*
+-               * The subtree rotate might have removed records on
+-               * the rightmost edge. If so, then rotation is
+-               * complete.
+-               */
+-              if (deleted)
+-                      break;
+-
+-              ocfs2_mv_path(left_path, right_path);
+-
+-              ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, left_path,
+-                                                   &right_cpos);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
+-      }
+-
+-out:
+-      ocfs2_free_path(right_path);
+-      ocfs2_free_path(left_path);
+-
+-      return ret;
+-}
+-
+-static void ocfs2_cleanup_merge(struct ocfs2_extent_list *el,
+-                              int index)
 -{
--      struct list_head *lh;
--      lh = dev->dev_list.next;
--      return lh == &dev_base_head ? NULL : net_device_entry(lh);
+-      struct ocfs2_extent_rec *rec = &el->l_recs[index];
+-      unsigned int size;
+-
+-      if (rec->e_leaf_clusters == 0) {
+-              /*
+-               * We consumed all of the merged-from record. An empty
+-               * extent cannot exist anywhere but the 1st array
+-               * position, so move things over if the merged-from
+-               * record doesn't occupy that position.
+-               *
+-               * This creates a new empty extent so the caller
+-               * should be smart enough to have removed any existing
+-               * ones.
+-               */
+-              if (index > 0) {
+-                      BUG_ON(ocfs2_is_empty_extent(&el->l_recs[0]));
+-                      size = index * sizeof(struct ocfs2_extent_rec);
+-                      memmove(&el->l_recs[1], &el->l_recs[0], size);
+-              }
+-
+-              /*
+-               * Always memset - the caller doesn't check whether it
+-               * created an empty extent, so there could be junk in
+-               * the other fields.
+-               */
+-              memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
+-      }
 -}
-+#define for_each_netdev(net, d)               \
-+              list_for_each_entry(d, &(net)->dev_base_head, dev_list)
-+#define for_each_netdev_safe(net, d, n)       \
-+              list_for_each_entry_safe(d, n, &(net)->dev_base_head, dev_list)
-+#define for_each_netdev_continue(net, d)              \
-+              list_for_each_entry_continue(d, &(net)->dev_base_head, dev_list)
-+#define net_device_entry(lh)  list_entry(lh, struct net_device, dev_list)
--static inline struct net_device *first_net_device(void)
+-
+-/*
+- * Remove split_rec clusters from the record at index and merge them
+- * onto the beginning of the record at index + 1.
+- */
+-static int ocfs2_merge_rec_right(struct inode *inode, struct buffer_head *bh,
+-                              handle_t *handle,
+-                              struct ocfs2_extent_rec *split_rec,
+-                              struct ocfs2_extent_list *el, int index)
 -{
--      return list_empty(&dev_base_head) ? NULL :
--              net_device_entry(dev_base_head.next);
+-      int ret;
+-      unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
+-      struct ocfs2_extent_rec *left_rec;
+-      struct ocfs2_extent_rec *right_rec;
+-
+-      BUG_ON(index >= le16_to_cpu(el->l_next_free_rec));
+-
+-      left_rec = &el->l_recs[index];
+-      right_rec = &el->l_recs[index + 1];
+-
+-      ret = ocfs2_journal_access(handle, inode, bh,
+-                                 OCFS2_JOURNAL_ACCESS_WRITE);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      le16_add_cpu(&left_rec->e_leaf_clusters, -split_clusters);
+-
+-      le32_add_cpu(&right_rec->e_cpos, -split_clusters);
+-      le64_add_cpu(&right_rec->e_blkno,
+-                   -ocfs2_clusters_to_blocks(inode->i_sb, split_clusters));
+-      le16_add_cpu(&right_rec->e_leaf_clusters, split_clusters);
+-
+-      ocfs2_cleanup_merge(el, index);
+-
+-      ret = ocfs2_journal_dirty(handle, bh);
+-      if (ret)
+-              mlog_errno(ret);
+-
+-out:
+-      return ret;
 -}
-+#define next_net_device(d)                                            \
-+({                                                                    \
-+      struct net_device *dev = d;                                     \
-+      struct list_head *lh;                                           \
-+      struct net *net;                                                \
-+                                                                      \
-+      net = dev->nd_net;                                              \
-+      lh = dev->dev_list.next;                                        \
-+      lh == &net->dev_base_head ? NULL : net_device_entry(lh);        \
-+})
-+
-+#define first_net_device(N)                                   \
-+({                                                            \
-+      struct net *NET = (N);                                  \
-+      list_empty(&NET->dev_base_head) ? NULL :                \
-+              net_device_entry(NET->dev_base_head.next);      \
-+})
- extern int                    netdev_boot_setup_check(struct net_device *dev);
- extern unsigned long          netdev_boot_base(const char *prefix, int unit);
--extern struct net_device    *dev_getbyhwaddr(unsigned short type, char *hwaddr);
--extern struct net_device *dev_getfirstbyhwtype(unsigned short type);
--extern struct net_device *__dev_getfirstbyhwtype(unsigned short type);
-+extern struct net_device    *dev_getbyhwaddr(struct net *net, unsigned short type, char *hwaddr);
-+extern struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type);
-+extern struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short type);
- extern void           dev_add_pack(struct packet_type *pt);
- extern void           dev_remove_pack(struct packet_type *pt);
- extern void           __dev_remove_pack(struct packet_type *pt);
--extern struct net_device      *dev_get_by_flags(unsigned short flags,
-+extern struct net_device      *dev_get_by_flags(struct net *net, unsigned short flags,
-                                                 unsigned short mask);
--extern struct net_device      *dev_get_by_name(const char *name);
--extern struct net_device      *__dev_get_by_name(const char *name);
-+extern struct net_device      *dev_get_by_name(struct net *net, const char *name);
-+extern struct net_device      *__dev_get_by_name(struct net *net, const char *name);
- extern int            dev_alloc_name(struct net_device *dev, const char *name);
- extern int            dev_open(struct net_device *dev);
- extern int            dev_close(struct net_device *dev);
-@@ -625,9 +640,9 @@
- extern void           synchronize_net(void);
- extern int            register_netdevice_notifier(struct notifier_block *nb);
- extern int            unregister_netdevice_notifier(struct notifier_block *nb);
--extern int            call_netdevice_notifiers(unsigned long val, void *v);
--extern struct net_device      *dev_get_by_index(int ifindex);
--extern struct net_device      *__dev_get_by_index(int ifindex);
-+extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
-+extern struct net_device      *dev_get_by_index(struct net *net, int ifindex);
-+extern struct net_device      *__dev_get_by_index(struct net *net, int ifindex);
- extern int            dev_restart(struct net_device *dev);
- #ifdef CONFIG_NETPOLL_TRAP
- extern int            netpoll_trap(void);
-@@ -732,11 +747,13 @@
- #define HAVE_NETIF_RECEIVE_SKB 1
- extern int            netif_receive_skb(struct sk_buff *skb);
- extern int            dev_valid_name(const char *name);
--extern int            dev_ioctl(unsigned int cmd, void __user *);
--extern int            dev_ethtool(struct ifreq *);
-+extern int            dev_ioctl(struct net *net, unsigned int cmd, void __user *);
-+extern int            dev_ethtool(struct net *net, struct ifreq *);
- extern unsigned               dev_get_flags(const struct net_device *);
- extern int            dev_change_flags(struct net_device *, unsigned);
- extern int            dev_change_name(struct net_device *, char *);
-+extern int            dev_change_net_namespace(struct net_device *,
-+                                               struct net *, const char *);
- extern int            dev_set_mtu(struct net_device *, int);
- extern int            dev_set_mac_address(struct net_device *,
-                                           struct sockaddr *);
-@@ -1006,7 +1023,7 @@
- extern void           netdev_state_change(struct net_device *dev);
- extern void           netdev_features_change(struct net_device *dev);
- /* Load a device via the kmod */
--extern void           dev_load(const char *name);
-+extern void           dev_load(struct net *net, const char *name);
- extern void           dev_mcast_init(void);
- extern int            netdev_max_backlog;
- extern int            weight_p;
-diff -Nurb linux-2.6.22-570/include/linux/netfilter/x_tables.h linux-2.6.22-590/include/linux/netfilter/x_tables.h
---- linux-2.6.22-570/include/linux/netfilter/x_tables.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/netfilter/x_tables.h        2008-01-02 13:56:37.000000000 -0500
-@@ -289,7 +289,7 @@
-                          unsigned int size, const char *table, unsigned int hook,
-                          unsigned short proto, int inv_proto);
--extern int xt_register_table(struct xt_table *table,
-+extern int xt_register_table(struct net *net, struct xt_table *table,
-                            struct xt_table_info *bootstrap,
-                            struct xt_table_info *newinfo);
- extern void *xt_unregister_table(struct xt_table *table);
-@@ -306,7 +306,7 @@
- extern int xt_find_revision(int af, const char *name, u8 revision, int target,
-                           int *err);
--extern struct xt_table *xt_find_table_lock(int af, const char *name);
-+extern struct xt_table *xt_find_table_lock(struct net *net, int af, const char *name);
- extern void xt_table_unlock(struct xt_table *t);
+-
+-/*
+- * Remove split_rec clusters from the record at index and merge them
+- * onto the tail of the record at index - 1.
+- */
+-static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh,
+-                              handle_t *handle,
+-                              struct ocfs2_extent_rec *split_rec,
+-                              struct ocfs2_extent_list *el, int index)
+-{
+-      int ret, has_empty_extent = 0;
+-      unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
+-      struct ocfs2_extent_rec *left_rec;
+-      struct ocfs2_extent_rec *right_rec;
+-
+-      BUG_ON(index <= 0);
+-
+-      left_rec = &el->l_recs[index - 1];
+-      right_rec = &el->l_recs[index];
+-      if (ocfs2_is_empty_extent(&el->l_recs[0]))
+-              has_empty_extent = 1;
+-
+-      ret = ocfs2_journal_access(handle, inode, bh,
+-                                 OCFS2_JOURNAL_ACCESS_WRITE);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      if (has_empty_extent && index == 1) {
+-              /*
+-               * The easy case - we can just plop the record right in.
+-               */
+-              *left_rec = *split_rec;
+-
+-              has_empty_extent = 0;
+-      } else {
+-              le16_add_cpu(&left_rec->e_leaf_clusters, split_clusters);
+-      }
+-
+-      le32_add_cpu(&right_rec->e_cpos, split_clusters);
+-      le64_add_cpu(&right_rec->e_blkno,
+-                   ocfs2_clusters_to_blocks(inode->i_sb, split_clusters));
+-      le16_add_cpu(&right_rec->e_leaf_clusters, -split_clusters);
+-
+-      ocfs2_cleanup_merge(el, index);
+-
+-      ret = ocfs2_journal_dirty(handle, bh);
+-      if (ret)
+-              mlog_errno(ret);
+-
+-out:
+-      return ret;
+-}
+-
+-static int ocfs2_try_to_merge_extent(struct inode *inode,
+-                                   handle_t *handle,
+-                                   struct ocfs2_path *left_path,
+-                                   int split_index,
+-                                   struct ocfs2_extent_rec *split_rec,
+-                                   struct ocfs2_cached_dealloc_ctxt *dealloc,
+-                                   struct ocfs2_merge_ctxt *ctxt)
+-
+-{
+-      int ret = 0, rotated, delete_tail_recs = 0;
+-      struct ocfs2_extent_list *el = path_leaf_el(left_path);
+-      struct ocfs2_extent_rec *rec = &el->l_recs[split_index];
+-
+-      BUG_ON(ctxt->c_contig_type == CONTIG_NONE);
+-
+-      if (ctxt->c_split_covers_rec) {
+-              delete_tail_recs++;
+-
+-              if (ctxt->c_contig_type == CONTIG_LEFTRIGHT ||
+-                  ctxt->c_has_empty_extent)
+-                      delete_tail_recs++;
+-
+-              if (ctxt->c_has_empty_extent) {
+-                      /*
+-                       * The merge code will need to create an empty
+-                       * extent to take the place of the newly
+-                       * emptied slot. Remove any pre-existing empty
+-                       * extents - having more than one in a leaf is
+-                       * illegal.
+-                       */
+-                      ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+-                                                   dealloc, &rotated);
+-                      if (rotated) {
+-                              split_index--;
+-                              rec = &el->l_recs[split_index];
+-                      }
+-                      if (ret) {
+-                              if (ret == -EAGAIN) {
+-                                      ret = 0;
+-                                      goto straight_insert;
+-                              }
+-
+-                              mlog_errno(ret);
+-                              goto out;
+-                      }
+-              }
+-      }
+-
+-      if (ctxt->c_contig_type == CONTIG_LEFTRIGHT) {
+-              /*
+-               * Left-right contig implies this.
+-               */
+-              BUG_ON(!ctxt->c_split_covers_rec);
+-              BUG_ON(split_index == 0);
+-
+-              /*
+-               * Since the leftright insert always covers the entire
+-               * extent, this call will delete the insert record
+-               * entirely, resulting in an empty extent record added to
+-               * the extent block.
+-               *
+-               * Since the adding of an empty extent shifts
+-               * everything back to the right, there's no need to
+-               * update split_index here.
+-               */
+-              ret = ocfs2_merge_rec_left(inode, path_leaf_bh(left_path),
+-                                         handle, split_rec, el, split_index);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
+-
+-              /*
+-               * We can only get this from logic error above.
+-               */
+-              BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
+-
+-              /*
+-               * The left merge left us with an empty extent, remove
+-               * it.
+-               */
+-              ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+-                                           dealloc, &rotated);
+-              if (rotated) {
+-                      split_index--;
+-                      rec = &el->l_recs[split_index];
+-              }
+-              if (ret) {
+-                      if (ret == -EAGAIN) {
+-                              ret = 0;
+-                              goto straight_insert;
+-                      }
+-
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
+-
+-              /*
+-               * Note that we don't pass split_rec here on purpose -
+-               * we've merged it into the left side.
+-               */
+-              ret = ocfs2_merge_rec_right(inode, path_leaf_bh(left_path),
+-                                          handle, rec, el, split_index);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
+-
+-              BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
+-
+-              ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+-                                           dealloc, NULL);
+-              /*
+-               * Error from this last rotate is not critical, so
+-               * print but don't bubble it up.
+-               */
+-              if (ret && ret != -EAGAIN)
+-                      mlog_errno(ret);
+-              ret = 0;
+-      } else {
+-              /*
+-               * Merge a record to the left or right.
+-               *
+-               * 'contig_type' is relative to the existing record,
+-               * so for example, if we're "right contig", it's to
+-               * the record on the left (hence the left merge).
+-               */
+-              if (ctxt->c_contig_type == CONTIG_RIGHT) {
+-                      ret = ocfs2_merge_rec_left(inode,
+-                                                 path_leaf_bh(left_path),
+-                                                 handle, split_rec, el,
+-                                                 split_index);
+-                      if (ret) {
+-                              mlog_errno(ret);
+-                              goto out;
+-                      }
+-              } else {
+-                      ret = ocfs2_merge_rec_right(inode,
+-                                                  path_leaf_bh(left_path),
+-                                                  handle, split_rec, el,
+-                                                  split_index);
+-                      if (ret) {
+-                              mlog_errno(ret);
+-                              goto out;
+-                      }
+-              }
+-
+-              if (ctxt->c_split_covers_rec) {
+-                      /*
+-                       * The merge may have left an empty extent in
+-                       * our leaf. Try to rotate it away.
+-                       */
+-                      ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+-                                                   dealloc, &rotated);
+-                      if (ret)
+-                              mlog_errno(ret);
+-                      ret = 0;
+-              }
+-      }
+-
+-out:
+-      return ret;
+-
+-straight_insert:
+-      el->l_recs[split_index] = *split_rec;
+-      goto out;
+-}
+-
+-static void ocfs2_subtract_from_rec(struct super_block *sb,
+-                                  enum ocfs2_split_type split,
+-                                  struct ocfs2_extent_rec *rec,
+-                                  struct ocfs2_extent_rec *split_rec)
+-{
+-      u64 len_blocks;
+-
+-      len_blocks = ocfs2_clusters_to_blocks(sb,
+-                              le16_to_cpu(split_rec->e_leaf_clusters));
+-
+-      if (split == SPLIT_LEFT) {
+-              /*
+-               * Region is on the left edge of the existing
+-               * record.
+-               */
+-              le32_add_cpu(&rec->e_cpos,
+-                           le16_to_cpu(split_rec->e_leaf_clusters));
+-              le64_add_cpu(&rec->e_blkno, len_blocks);
+-              le16_add_cpu(&rec->e_leaf_clusters,
+-                           -le16_to_cpu(split_rec->e_leaf_clusters));
+-      } else {
+-              /*
+-               * Region is on the right edge of the existing
+-               * record.
+-               */
+-              le16_add_cpu(&rec->e_leaf_clusters,
+-                           -le16_to_cpu(split_rec->e_leaf_clusters));
+-      }
+-}
+-
+-/*
+- * Do the final bits of extent record insertion at the target leaf
+- * list. If this leaf is part of an allocation tree, it is assumed
+- * that the tree above has been prepared.
+- */
+-static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
+-                               struct ocfs2_extent_list *el,
+-                               struct ocfs2_insert_type *insert,
+-                               struct inode *inode)
+-{
+-      int i = insert->ins_contig_index;
+-      unsigned int range;
+-      struct ocfs2_extent_rec *rec;
+-
+-      BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
+-
+-      if (insert->ins_split != SPLIT_NONE) {
+-              i = ocfs2_search_extent_list(el, le32_to_cpu(insert_rec->e_cpos));
+-              BUG_ON(i == -1);
+-              rec = &el->l_recs[i];
+-              ocfs2_subtract_from_rec(inode->i_sb, insert->ins_split, rec,
+-                                      insert_rec);
+-              goto rotate;
+-      }
+-
+-      /*
+-       * Contiguous insert - either left or right.
+-       */
+-      if (insert->ins_contig != CONTIG_NONE) {
+-              rec = &el->l_recs[i];
+-              if (insert->ins_contig == CONTIG_LEFT) {
+-                      rec->e_blkno = insert_rec->e_blkno;
+-                      rec->e_cpos = insert_rec->e_cpos;
+-              }
+-              le16_add_cpu(&rec->e_leaf_clusters,
+-                           le16_to_cpu(insert_rec->e_leaf_clusters));
+-              return;
+-      }
+-
+-      /*
+-       * Handle insert into an empty leaf.
+-       */
+-      if (le16_to_cpu(el->l_next_free_rec) == 0 ||
+-          ((le16_to_cpu(el->l_next_free_rec) == 1) &&
+-           ocfs2_is_empty_extent(&el->l_recs[0]))) {
+-              el->l_recs[0] = *insert_rec;
+-              el->l_next_free_rec = cpu_to_le16(1);
+-              return;
+-      }
+-
+-      /*
+-       * Appending insert.
+-       */
+-      if (insert->ins_appending == APPEND_TAIL) {
+-              i = le16_to_cpu(el->l_next_free_rec) - 1;
+-              rec = &el->l_recs[i];
+-              range = le32_to_cpu(rec->e_cpos)
+-                      + le16_to_cpu(rec->e_leaf_clusters);
+-              BUG_ON(le32_to_cpu(insert_rec->e_cpos) < range);
+-
+-              mlog_bug_on_msg(le16_to_cpu(el->l_next_free_rec) >=
+-                              le16_to_cpu(el->l_count),
+-                              "inode %lu, depth %u, count %u, next free %u, "
+-                              "rec.cpos %u, rec.clusters %u, "
+-                              "insert.cpos %u, insert.clusters %u\n",
+-                              inode->i_ino,
+-                              le16_to_cpu(el->l_tree_depth),
+-                              le16_to_cpu(el->l_count),
+-                              le16_to_cpu(el->l_next_free_rec),
+-                              le32_to_cpu(el->l_recs[i].e_cpos),
+-                              le16_to_cpu(el->l_recs[i].e_leaf_clusters),
+-                              le32_to_cpu(insert_rec->e_cpos),
+-                              le16_to_cpu(insert_rec->e_leaf_clusters));
+-              i++;
+-              el->l_recs[i] = *insert_rec;
+-              le16_add_cpu(&el->l_next_free_rec, 1);
+-              return;
+-      }
+-
+-rotate:
+-      /*
+-       * Ok, we have to rotate.
+-       *
+-       * At this point, it is safe to assume that inserting into an
+-       * empty leaf and appending to a leaf have both been handled
+-       * above.
+-       *
+-       * This leaf needs to have space, either by the empty 1st
+-       * extent record, or by virtue of an l_next_rec < l_count.
+-       */
+-      ocfs2_rotate_leaf(el, insert_rec);
+-}
+-
+-static inline void ocfs2_update_dinode_clusters(struct inode *inode,
+-                                              struct ocfs2_dinode *di,
+-                                              u32 clusters)
+-{
+-      le32_add_cpu(&di->i_clusters, clusters);
+-      spin_lock(&OCFS2_I(inode)->ip_lock);
+-      OCFS2_I(inode)->ip_clusters = le32_to_cpu(di->i_clusters);
+-      spin_unlock(&OCFS2_I(inode)->ip_lock);
+-}
+-
+-static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
+-                                  struct ocfs2_extent_rec *insert_rec,
+-                                  struct ocfs2_path *right_path,
+-                                  struct ocfs2_path **ret_left_path)
+-{
+-      int ret, i, next_free;
+-      struct buffer_head *bh;
+-      struct ocfs2_extent_list *el;
+-      struct ocfs2_path *left_path = NULL;
+-
+-      *ret_left_path = NULL;
++      *ret_left_path = NULL;
  
- extern int xt_proto_init(int af);
-diff -Nurb linux-2.6.22-570/include/linux/netfilter.h linux-2.6.22-590/include/linux/netfilter.h
---- linux-2.6.22-570/include/linux/netfilter.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/netfilter.h 2008-01-02 13:56:37.000000000 -0500
-@@ -362,11 +362,6 @@
- #endif
+       /*
+        * This shouldn't happen for non-trees. The extent rec cluster
+@@ -2973,83 +1931,6 @@
+       return ret;
  }
  
--#ifdef CONFIG_PROC_FS
--#include <linux/proc_fs.h>
--extern struct proc_dir_entry *proc_net_netfilter;
--#endif
+-static void ocfs2_split_record(struct inode *inode,
+-                             struct ocfs2_path *left_path,
+-                             struct ocfs2_path *right_path,
+-                             struct ocfs2_extent_rec *split_rec,
+-                             enum ocfs2_split_type split)
+-{
+-      int index;
+-      u32 cpos = le32_to_cpu(split_rec->e_cpos);
+-      struct ocfs2_extent_list *left_el = NULL, *right_el, *insert_el, *el;
+-      struct ocfs2_extent_rec *rec, *tmprec;
 -
- #else /* !CONFIG_NETFILTER */
- #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
- #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
-diff -Nurb linux-2.6.22-570/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.22-590/include/linux/netfilter_ipv4/ip_tables.h
---- linux-2.6.22-570/include/linux/netfilter_ipv4/ip_tables.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/netfilter_ipv4/ip_tables.h  2008-01-02 13:56:37.000000000 -0500
-@@ -292,7 +292,7 @@
- #include <linux/init.h>
- extern void ipt_init(void) __init;
--extern int ipt_register_table(struct xt_table *table,
-+extern int ipt_register_table(struct net *net, struct xt_table *table,
-                             const struct ipt_replace *repl);
- extern void ipt_unregister_table(struct xt_table *table);
-diff -Nurb linux-2.6.22-570/include/linux/netfilter_ipv4.h linux-2.6.22-590/include/linux/netfilter_ipv4.h
---- linux-2.6.22-570/include/linux/netfilter_ipv4.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/netfilter_ipv4.h    2008-01-02 13:56:37.000000000 -0500
-@@ -75,7 +75,7 @@
- #define SO_ORIGINAL_DST 80
- #ifdef __KERNEL__
--extern int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type);
-+extern int ip_route_me_harder(struct net *net, struct sk_buff **pskb, unsigned addr_type);
- extern int ip_xfrm_me_harder(struct sk_buff **pskb);
- extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
-                                  unsigned int dataoff, u_int8_t protocol);
-diff -Nurb linux-2.6.22-570/include/linux/netlink.h linux-2.6.22-590/include/linux/netlink.h
---- linux-2.6.22-570/include/linux/netlink.h   2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/include/linux/netlink.h   2008-01-02 13:56:37.000000000 -0500
-@@ -21,12 +21,14 @@
- #define NETLINK_DNRTMSG               14      /* DECnet routing messages */
- #define NETLINK_KOBJECT_UEVENT        15      /* Kernel messages to userspace */
- #define NETLINK_GENERIC               16
--/* leave room for NETLINK_DM (DM Events) */
-+#define NETLINK_DM            17      /* Device Mapper */
- #define NETLINK_SCSITRANSPORT 18      /* SCSI Transports */
- #define NETLINK_ECRYPTFS      19
- #define MAX_LINKS 32          
-+struct net;
-+
- struct sockaddr_nl
- {
-       sa_family_t     nl_family;      /* AF_NETLINK   */
-@@ -157,7 +159,8 @@
- #define NETLINK_CREDS(skb)    (&NETLINK_CB((skb)).creds)
--extern struct sock *netlink_kernel_create(int unit, unsigned int groups,
-+extern struct sock *netlink_kernel_create(struct net *net,
-+                                        int unit,unsigned int groups,
-                                         void (*input)(struct sock *sk, int len),
-                                         struct mutex *cb_mutex,
-                                         struct module *module);
-@@ -204,6 +207,7 @@
- struct netlink_notify
+-      right_el = path_leaf_el(right_path);;
+-      if (left_path)
+-              left_el = path_leaf_el(left_path);
+-
+-      el = right_el;
+-      insert_el = right_el;
+-      index = ocfs2_search_extent_list(el, cpos);
+-      if (index != -1) {
+-              if (index == 0 && left_path) {
+-                      BUG_ON(ocfs2_is_empty_extent(&el->l_recs[0]));
+-
+-                      /*
+-                       * This typically means that the record
+-                       * started in the left path but moved to the
+-                       * right as a result of rotation. We either
+-                       * move the existing record to the left, or we
+-                       * do the later insert there.
+-                       *
+-                       * In this case, the left path should always
+-                       * exist as the rotate code will have passed
+-                       * it back for a post-insert update.
+-                       */
+-
+-                      if (split == SPLIT_LEFT) {
+-                              /*
+-                               * It's a left split. Since we know
+-                               * that the rotate code gave us an
+-                               * empty extent in the left path, we
+-                               * can just do the insert there.
+-                               */
+-                              insert_el = left_el;
+-                      } else {
+-                              /*
+-                               * Right split - we have to move the
+-                               * existing record over to the left
+-                               * leaf. The insert will be into the
+-                               * newly created empty extent in the
+-                               * right leaf.
+-                               */
+-                              tmprec = &right_el->l_recs[index];
+-                              ocfs2_rotate_leaf(left_el, tmprec);
+-                              el = left_el;
+-
+-                              memset(tmprec, 0, sizeof(*tmprec));
+-                              index = ocfs2_search_extent_list(left_el, cpos);
+-                              BUG_ON(index == -1);
+-                      }
+-              }
+-      } else {
+-              BUG_ON(!left_path);
+-              BUG_ON(!ocfs2_is_empty_extent(&left_el->l_recs[0]));
+-              /*
+-               * Left path is easy - we can just allow the insert to
+-               * happen.
+-               */
+-              el = left_el;
+-              insert_el = left_el;
+-              index = ocfs2_search_extent_list(el, cpos);
+-              BUG_ON(index == -1);
+-      }
+-
+-      rec = &el->l_recs[index];
+-      ocfs2_subtract_from_rec(inode->i_sb, split, rec, split_rec);
+-      ocfs2_rotate_leaf(insert_el, split_rec);
+-}
+-
+ /*
+  * This function only does inserts on an allocation b-tree. For dinode
+  * lists, ocfs2_insert_at_leaf() is called directly.
+@@ -3067,6 +1948,7 @@
  {
-+      struct net *net;
-       int pid;
-       int protocol;
- };
-diff -Nurb linux-2.6.22-570/include/linux/netpoll.h linux-2.6.22-590/include/linux/netpoll.h
---- linux-2.6.22-570/include/linux/netpoll.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/netpoll.h   2008-01-02 13:56:37.000000000 -0500
-@@ -16,7 +16,7 @@
-       struct net_device *dev;
-       char dev_name[IFNAMSIZ];
-       const char *name;
--      void (*rx_hook)(struct netpoll *, int, char *, int);
-+      void (*rx_hook)(struct netpoll *, int, char *, int, struct sk_buff *);
-       u32 local_ip, remote_ip;
-       u16 local_port, remote_port;
-diff -Nurb linux-2.6.22-570/include/linux/nfs4.h linux-2.6.22-590/include/linux/nfs4.h
---- linux-2.6.22-570/include/linux/nfs4.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/nfs4.h      2008-01-02 13:56:37.000000000 -0500
-@@ -15,6 +15,7 @@
- #include <linux/types.h>
-+#define NFS4_BITMAP_SIZE      2
- #define NFS4_VERIFIER_SIZE    8
- #define NFS4_STATEID_SIZE     16
- #define NFS4_FHSIZE           128
-diff -Nurb linux-2.6.22-570/include/linux/nfs4_mount.h linux-2.6.22-590/include/linux/nfs4_mount.h
---- linux-2.6.22-570/include/linux/nfs4_mount.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/nfs4_mount.h        2008-01-02 13:56:37.000000000 -0500
-@@ -65,6 +65,7 @@
- #define NFS4_MOUNT_NOCTO      0x0010  /* 1 */
- #define NFS4_MOUNT_NOAC               0x0020  /* 1 */
- #define NFS4_MOUNT_STRICTLOCK 0x1000  /* 1 */
-+#define NFS4_MOUNT_UNSHARED   0x8000  /* 1 */
- #define NFS4_MOUNT_FLAGMASK   0xFFFF
+       int ret, subtree_index;
+       struct buffer_head *leaf_bh = path_leaf_bh(right_path);
++      struct ocfs2_extent_list *el;
  
- #endif
-diff -Nurb linux-2.6.22-570/include/linux/nfs_fs.h linux-2.6.22-590/include/linux/nfs_fs.h
---- linux-2.6.22-570/include/linux/nfs_fs.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/nfs_fs.h    2008-01-02 13:56:37.000000000 -0500
-@@ -30,7 +30,9 @@
- #ifdef __KERNEL__
+       /*
+        * Pass both paths to the journal. The majority of inserts
+@@ -3102,18 +1984,9 @@
+               }
+       }
  
- #include <linux/in.h>
-+#include <linux/kref.h>
- #include <linux/mm.h>
-+#include <linux/namei.h>
- #include <linux/pagemap.h>
- #include <linux/rbtree.h>
- #include <linux/rwsem.h>
-@@ -69,9 +71,8 @@
+-      if (insert->ins_split != SPLIT_NONE) {
+-              /*
+-               * We could call ocfs2_insert_at_leaf() for some types
+-               * of splits, but it's easier to just let one seperate
+-               * function sort it all out.
+-               */
+-              ocfs2_split_record(inode, left_path, right_path,
+-                                 insert_rec, insert->ins_split);
+-      } else
+-              ocfs2_insert_at_leaf(insert_rec, path_leaf_el(right_path),
+-                                   insert, inode);
++      el = path_leaf_el(right_path);
  
- struct nfs4_state;
- struct nfs_open_context {
--      atomic_t count;
--      struct vfsmount *vfsmnt;
--      struct dentry *dentry;
-+      struct kref kref;
-+      struct path path;
-       struct rpc_cred *cred;
-       struct nfs4_state *state;
-       fl_owner_t lockowner;
-@@ -156,12 +157,9 @@
-        * This is the list of dirty unwritten pages.
++      ocfs2_insert_at_leaf(insert_rec, el, insert, inode);
+       ret = ocfs2_journal_dirty(handle, leaf_bh);
+       if (ret)
+               mlog_errno(ret);
+@@ -3202,7 +2075,7 @@
+        * can wind up skipping both of these two special cases...
         */
-       spinlock_t              req_lock;
--      struct list_head        dirty;
--      struct list_head        commit;
-       struct radix_tree_root  nfs_page_tree;
--      unsigned int            ndirty,
--                              ncommit,
-+      unsigned long           ncommit,
-                               npages;
-       /* Open contexts for shared mmap writes */
-diff -Nurb linux-2.6.22-570/include/linux/nfs_fs_sb.h linux-2.6.22-590/include/linux/nfs_fs_sb.h
---- linux-2.6.22-570/include/linux/nfs_fs_sb.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/nfs_fs_sb.h 2008-01-02 13:56:37.000000000 -0500
-@@ -16,7 +16,6 @@
- #define NFS_CS_INITING                1               /* busy initialising */
-       int                     cl_nfsversion;  /* NFS protocol version */
-       unsigned long           cl_res_state;   /* NFS resources state */
--#define NFS_CS_RPCIOD         0               /* - rpciod started */
- #define NFS_CS_CALLBACK               1               /* - callback started */
- #define NFS_CS_IDMAP          2               /* - idmap started */
- #define NFS_CS_RENEWD         3               /* - renewd started */
-diff -Nurb linux-2.6.22-570/include/linux/nfs_mount.h linux-2.6.22-590/include/linux/nfs_mount.h
---- linux-2.6.22-570/include/linux/nfs_mount.h 2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/nfs_mount.h 2008-01-02 13:56:37.000000000 -0500
-@@ -62,6 +62,7 @@
- #define NFS_MOUNT_STRICTLOCK  0x1000  /* reserved for NFSv4 */
- #define NFS_MOUNT_SECFLAVOUR  0x2000  /* 5 */
- #define NFS_MOUNT_NORDIRPLUS  0x4000  /* 5 */
-+#define NFS_MOUNT_UNSHARED    0x8000  /* 5 */
- #define NFS_MOUNT_TAGGED      0x8000  /* context tagging */
- #define NFS_MOUNT_FLAGMASK    0xFFFF
-diff -Nurb linux-2.6.22-570/include/linux/nfs_page.h linux-2.6.22-590/include/linux/nfs_page.h
---- linux-2.6.22-570/include/linux/nfs_page.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/nfs_page.h  2008-01-02 13:56:37.000000000 -0500
-@@ -16,12 +16,13 @@
- #include <linux/sunrpc/auth.h>
- #include <linux/nfs_xdr.h>
--#include <asm/atomic.h>
-+#include <linux/kref.h>
+       if (rotate) {
+-              ret = ocfs2_rotate_tree_right(inode, handle, type->ins_split,
++              ret = ocfs2_rotate_tree_right(inode, handle,
+                                             le32_to_cpu(insert_rec->e_cpos),
+                                             right_path, &left_path);
+               if (ret) {
+@@ -3227,7 +2100,6 @@
+       }
  
- /*
-  * Valid flags for the radix tree
-  */
--#define NFS_PAGE_TAG_WRITEBACK        0
-+#define NFS_PAGE_TAG_LOCKED   0
-+#define NFS_PAGE_TAG_COMMIT   1
+ out_update_clusters:
+-      if (type->ins_split == SPLIT_NONE)
+       ocfs2_update_dinode_clusters(inode, di,
+                                    le16_to_cpu(insert_rec->e_leaf_clusters));
  
- /*
-  * Valid flags for a dirty buffer
-@@ -33,8 +34,7 @@
+@@ -3242,44 +2114,6 @@
+       return ret;
+ }
  
- struct nfs_inode;
- struct nfs_page {
--      struct list_head        wb_list,        /* Defines state of page: */
--                              *wb_list_head;  /*      read/write/commit */
-+      struct list_head        wb_list;        /* Defines state of page: */
-       struct page             *wb_page;       /* page to read in/write out */
-       struct nfs_open_context *wb_context;    /* File state context info */
-       atomic_t                wb_complete;    /* i/os we're waiting for */
-@@ -42,7 +42,7 @@
-       unsigned int            wb_offset,      /* Offset & ~PAGE_CACHE_MASK */
-                               wb_pgbase,      /* Start of page data */
-                               wb_bytes;       /* Length of request */
--      atomic_t                wb_count;       /* reference count */
-+      struct kref             wb_kref;        /* reference count */
-       unsigned long           wb_flags;
-       struct nfs_writeverf    wb_verf;        /* Commit cookie */
- };
-@@ -71,8 +71,8 @@
- extern        void nfs_release_request(struct nfs_page *req);
+-static enum ocfs2_contig_type
+-ocfs2_figure_merge_contig_type(struct inode *inode,
+-                             struct ocfs2_extent_list *el, int index,
+-                             struct ocfs2_extent_rec *split_rec)
+-{
+-      struct ocfs2_extent_rec *rec;
+-      enum ocfs2_contig_type ret = CONTIG_NONE;
+-
+-      /*
+-       * We're careful to check for an empty extent record here -
+-       * the merge code will know what to do if it sees one.
+-       */
+-
+-      if (index > 0) {
+-              rec = &el->l_recs[index - 1];
+-              if (index == 1 && ocfs2_is_empty_extent(rec)) {
+-                      if (split_rec->e_cpos == el->l_recs[index].e_cpos)
+-                              ret = CONTIG_RIGHT;
+-              } else {
+-                      ret = ocfs2_extent_contig(inode, rec, split_rec);
+-              }
+-      }
+-
+-      if (index < (le16_to_cpu(el->l_next_free_rec) - 1)) {
+-              enum ocfs2_contig_type contig_type;
+-
+-              rec = &el->l_recs[index + 1];
+-              contig_type = ocfs2_extent_contig(inode, rec, split_rec);
+-
+-              if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT)
+-                      ret = CONTIG_LEFTRIGHT;
+-              else if (ret == CONTIG_NONE)
+-                      ret = contig_type;
+-      }
+-
+-      return ret;
+-}
+-
+ static void ocfs2_figure_contig_type(struct inode *inode,
+                                    struct ocfs2_insert_type *insert,
+                                    struct ocfs2_extent_list *el,
+@@ -3371,8 +2205,6 @@
+       struct ocfs2_path *path = NULL;
+       struct buffer_head *bh = NULL;
  
+-      insert->ins_split = SPLIT_NONE;
+-
+       el = &di->id2.i_list;
+       insert->ins_tree_depth = le16_to_cpu(el->l_tree_depth);
  
--extern        int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, struct list_head *dst,
--                        pgoff_t idx_start, unsigned int npages);
-+extern        int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *dst,
-+                        pgoff_t idx_start, unsigned int npages, int tag);
- extern        void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
-                            struct inode *inode,
-                            int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
-@@ -84,12 +84,11 @@
- extern        void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t);
- extern  int nfs_wait_on_request(struct nfs_page *);
- extern        void nfs_unlock_request(struct nfs_page *req);
--extern  int nfs_set_page_writeback_locked(struct nfs_page *req);
--extern  void nfs_clear_page_writeback(struct nfs_page *req);
-+extern  void nfs_clear_page_tag_locked(struct nfs_page *req);
+@@ -3464,434 +2296,139 @@
+       if (le64_to_cpu(di->i_last_eb_blk) == path_leaf_bh(path)->b_blocknr) {
+               /*
+                * Ok, ocfs2_find_path() returned us the rightmost
+-               * tree path. This might be an appending insert. There are
+-               * two cases:
+-               *    1) We're doing a true append at the tail:
+-               *      -This might even be off the end of the leaf
+-               *    2) We're "appending" by rotating in the tail
+-               */
+-              ocfs2_figure_appending_type(insert, el, insert_rec);
+-      }
+-
+-out:
+-      ocfs2_free_path(path);
+-
+-      if (ret == 0)
+-              *last_eb_bh = bh;
+-      else
+-              brelse(bh);
+-      return ret;
+-}
+-
+-/*
+- * Insert an extent into an inode btree.
+- *
+- * The caller needs to update fe->i_clusters
+- */
+-int ocfs2_insert_extent(struct ocfs2_super *osb,
+-                      handle_t *handle,
+-                      struct inode *inode,
+-                      struct buffer_head *fe_bh,
+-                      u32 cpos,
+-                      u64 start_blk,
+-                      u32 new_clusters,
+-                      u8 flags,
+-                      struct ocfs2_alloc_context *meta_ac)
+-{
+-      int status;
+-      struct buffer_head *last_eb_bh = NULL;
+-      struct buffer_head *bh = NULL;
+-      struct ocfs2_insert_type insert = {0, };
+-      struct ocfs2_extent_rec rec;
+-
+-      mlog(0, "add %u clusters at position %u to inode %llu\n",
+-           new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno);
+-
+-      mlog_bug_on_msg(!ocfs2_sparse_alloc(osb) &&
+-                      (OCFS2_I(inode)->ip_clusters != cpos),
+-                      "Device %s, asking for sparse allocation: inode %llu, "
+-                      "cpos %u, clusters %u\n",
+-                      osb->dev_str,
+-                      (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos,
+-                      OCFS2_I(inode)->ip_clusters);
+-
+-      memset(&rec, 0, sizeof(rec));
+-      rec.e_cpos = cpu_to_le32(cpos);
+-      rec.e_blkno = cpu_to_le64(start_blk);
+-      rec.e_leaf_clusters = cpu_to_le16(new_clusters);
+-      rec.e_flags = flags;
+-
+-      status = ocfs2_figure_insert_type(inode, fe_bh, &last_eb_bh, &rec,
+-                                        &insert);
+-      if (status < 0) {
+-              mlog_errno(status);
+-              goto bail;
+-      }
+-
+-      mlog(0, "Insert.appending: %u, Insert.Contig: %u, "
+-           "Insert.contig_index: %d, Insert.free_records: %d, "
+-           "Insert.tree_depth: %d\n",
+-           insert.ins_appending, insert.ins_contig, insert.ins_contig_index,
+-           insert.ins_free_records, insert.ins_tree_depth);
+-
+-      if (insert.ins_contig == CONTIG_NONE && insert.ins_free_records == 0) {
+-              status = ocfs2_grow_tree(inode, handle, fe_bh,
+-                                       &insert.ins_tree_depth, &last_eb_bh,
+-                                       meta_ac);
+-              if (status) {
+-                      mlog_errno(status);
+-                      goto bail;
+-              }
+-      }
+-
+-      /* Finally, we can add clusters. This might rotate the tree for us. */
+-      status = ocfs2_do_insert_extent(inode, handle, fe_bh, &rec, &insert);
+-      if (status < 0)
+-              mlog_errno(status);
+-      else
+-              ocfs2_extent_map_insert_rec(inode, &rec);
+-
+-bail:
+-      if (bh)
+-              brelse(bh);
+-
+-      if (last_eb_bh)
+-              brelse(last_eb_bh);
+-
+-      mlog_exit(status);
+-      return status;
+-}
+-
+-static int ocfs2_split_and_insert(struct inode *inode,
+-                                handle_t *handle,
+-                                struct ocfs2_path *path,
+-                                struct buffer_head *di_bh,
+-                                struct buffer_head **last_eb_bh,
+-                                int split_index,
+-                                struct ocfs2_extent_rec *orig_split_rec,
+-                                struct ocfs2_alloc_context *meta_ac)
+-{
+-      int ret = 0, depth;
+-      unsigned int insert_range, rec_range, do_leftright = 0;
+-      struct ocfs2_extent_rec tmprec;
+-      struct ocfs2_extent_list *rightmost_el;
+-      struct ocfs2_extent_rec rec;
+-      struct ocfs2_extent_rec split_rec = *orig_split_rec;
+-      struct ocfs2_insert_type insert;
+-      struct ocfs2_extent_block *eb;
+-      struct ocfs2_dinode *di;
+-
+-leftright:
+-      /*
+-       * Store a copy of the record on the stack - it might move
+-       * around as the tree is manipulated below.
+-       */
+-      rec = path_leaf_el(path)->l_recs[split_index];
+-
+-      di = (struct ocfs2_dinode *)di_bh->b_data;
+-      rightmost_el = &di->id2.i_list;
+-
+-      depth = le16_to_cpu(rightmost_el->l_tree_depth);
+-      if (depth) {
+-              BUG_ON(!(*last_eb_bh));
+-              eb = (struct ocfs2_extent_block *) (*last_eb_bh)->b_data;
+-              rightmost_el = &eb->h_list;
+-      }
+-
+-      if (le16_to_cpu(rightmost_el->l_next_free_rec) ==
+-          le16_to_cpu(rightmost_el->l_count)) {
+-              int old_depth = depth;
+-
+-              ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, last_eb_bh,
+-                                    meta_ac);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
+-
+-              if (old_depth != depth) {
+-                      eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
+-                      rightmost_el = &eb->h_list;
+-              }
+-      }
+-
+-      memset(&insert, 0, sizeof(struct ocfs2_insert_type));
+-      insert.ins_appending = APPEND_NONE;
+-      insert.ins_contig = CONTIG_NONE;
+-      insert.ins_free_records = le16_to_cpu(rightmost_el->l_count)
+-              - le16_to_cpu(rightmost_el->l_next_free_rec);
+-      insert.ins_tree_depth = depth;
+-
+-      insert_range = le32_to_cpu(split_rec.e_cpos) +
+-              le16_to_cpu(split_rec.e_leaf_clusters);
+-      rec_range = le32_to_cpu(rec.e_cpos) +
+-              le16_to_cpu(rec.e_leaf_clusters);
+-
+-      if (split_rec.e_cpos == rec.e_cpos) {
+-              insert.ins_split = SPLIT_LEFT;
+-      } else if (insert_range == rec_range) {
+-              insert.ins_split = SPLIT_RIGHT;
+-      } else {
+-              /*
+-               * Left/right split. We fake this as a right split
+-               * first and then make a second pass as a left split.
+-               */
+-              insert.ins_split = SPLIT_RIGHT;
+-
+-              memset(&tmprec, 0, sizeof(tmprec));
+-
+-              tmprec.e_cpos = cpu_to_le32(insert_range);
+-              tmprec.e_leaf_clusters = cpu_to_le16(rec_range - insert_range);
+-              tmprec.e_flags = rec.e_flags;
+-              tmprec.e_blkno = split_rec.e_blkno;
+-              le64_add_cpu(&tmprec.e_blkno,
+-                           ocfs2_clusters_to_blocks(inode->i_sb,
+-                                   le16_to_cpu(split_rec.e_leaf_clusters)));
+-              split_rec = tmprec;
+-
+-              BUG_ON(do_leftright);
+-              do_leftright = 1;
+-      }
+-
+-      ret = ocfs2_do_insert_extent(inode, handle, di_bh, &split_rec,
+-                                   &insert);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      if (do_leftright == 1) {
+-              u32 cpos;
+-              struct ocfs2_extent_list *el;
+-
+-              do_leftright++;
+-              split_rec = *orig_split_rec;
+-
+-              ocfs2_reinit_path(path, 1);
+-
+-              cpos = le32_to_cpu(split_rec.e_cpos);
+-              ret = ocfs2_find_path(inode, path, cpos);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
+-
+-              el = path_leaf_el(path);
+-              split_index = ocfs2_search_extent_list(el, cpos);
+-              goto leftright;
+-      }
+-out:
+-
+-      return ret;
+-}
+-
+-/*
+- * Mark part or all of the extent record at split_index in the leaf
+- * pointed to by path as written. This removes the unwritten
+- * extent flag.
+- *
+- * Care is taken to handle contiguousness so as to not grow the tree.
+- *
+- * meta_ac is not strictly necessary - we only truly need it if growth
+- * of the tree is required. All other cases will degrade into a less
+- * optimal tree layout.
+- *
+- * last_eb_bh should be the rightmost leaf block for any inode with a
+- * btree. Since a split may grow the tree or a merge might shrink it, the caller cannot trust the contents of that buffer after this call.
+- *
+- * This code is optimized for readability - several passes might be
+- * made over certain portions of the tree. All of those blocks will
+- * have been brought into cache (and pinned via the journal), so the
+- * extra overhead is not expressed in terms of disk reads.
+- */
+-static int __ocfs2_mark_extent_written(struct inode *inode,
+-                                     struct buffer_head *di_bh,
+-                                     handle_t *handle,
+-                                     struct ocfs2_path *path,
+-                                     int split_index,
+-                                     struct ocfs2_extent_rec *split_rec,
+-                                     struct ocfs2_alloc_context *meta_ac,
+-                                     struct ocfs2_cached_dealloc_ctxt *dealloc)
+-{
+-      int ret = 0;
+-      struct ocfs2_extent_list *el = path_leaf_el(path);
+-      struct buffer_head *eb_bh, *last_eb_bh = NULL;
+-      struct ocfs2_extent_rec *rec = &el->l_recs[split_index];
+-      struct ocfs2_merge_ctxt ctxt;
+-      struct ocfs2_extent_list *rightmost_el;
+-
+-      if (!rec->e_flags & OCFS2_EXT_UNWRITTEN) {
+-              ret = -EIO;
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      if (le32_to_cpu(rec->e_cpos) > le32_to_cpu(split_rec->e_cpos) ||
+-          ((le32_to_cpu(rec->e_cpos) + le16_to_cpu(rec->e_leaf_clusters)) <
+-           (le32_to_cpu(split_rec->e_cpos) + le16_to_cpu(split_rec->e_leaf_clusters)))) {
+-              ret = -EIO;
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      eb_bh = path_leaf_bh(path);
+-      ret = ocfs2_journal_access(handle, inode, eb_bh,
+-                                 OCFS2_JOURNAL_ACCESS_WRITE);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, el,
+-                                                          split_index,
+-                                                          split_rec);
+-
+-      /*
+-       * The core merge / split code wants to know how much room is
+-       * left in this inodes allocation tree, so we pass the
+-       * rightmost extent list.
+-       */
+-      if (path->p_tree_depth) {
+-              struct ocfs2_extent_block *eb;
+-              struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+-
+-              ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+-                                     le64_to_cpu(di->i_last_eb_blk),
+-                                     &last_eb_bh, OCFS2_BH_CACHED, inode);
+-              if (ret) {
+-                      mlog_exit(ret);
+-                      goto out;
+-              }
+-
+-              eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+-              if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+-                      OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+-                      ret = -EROFS;
+-                      goto out;
++               * tree path. This might be an appending insert. There are
++               * two cases:
++               *    1) We're doing a true append at the tail:
++               *      -This might even be off the end of the leaf
++               *    2) We're "appending" by rotating in the tail
++               */
++              ocfs2_figure_appending_type(insert, el, insert_rec);
+               }
  
+-              rightmost_el = &eb->h_list;
+-      } else
+-              rightmost_el = path_root_el(path);
+-
+-      ctxt.c_used_tail_recs = le16_to_cpu(rightmost_el->l_next_free_rec);
+-      if (ctxt.c_used_tail_recs > 0 &&
+-          ocfs2_is_empty_extent(&rightmost_el->l_recs[0]))
+-              ctxt.c_used_tail_recs--;
+-
+-      if (rec->e_cpos == split_rec->e_cpos &&
+-          rec->e_leaf_clusters == split_rec->e_leaf_clusters)
+-              ctxt.c_split_covers_rec = 1;
+-      else
+-              ctxt.c_split_covers_rec = 0;
+-
+-      ctxt.c_has_empty_extent = ocfs2_is_empty_extent(&el->l_recs[0]);
++out:
++      ocfs2_free_path(path);
  
- /*
-- * Lock the page of an asynchronous request without incrementing the wb_count
-+ * Lock the page of an asynchronous request without getting a new reference
-  */
- static inline int
- nfs_lock_request_dontget(struct nfs_page *req)
-@@ -98,14 +97,14 @@
+-      mlog(0, "index: %d, contig: %u, used_tail_recs: %u, "
+-           "has_empty: %u, split_covers: %u\n", split_index,
+-           ctxt.c_contig_type, ctxt.c_used_tail_recs,
+-           ctxt.c_has_empty_extent, ctxt.c_split_covers_rec);
+-
+-      if (ctxt.c_contig_type == CONTIG_NONE) {
+-              if (ctxt.c_split_covers_rec)
+-                      el->l_recs[split_index] = *split_rec;
++      if (ret == 0)
++              *last_eb_bh = bh;
+               else
+-                      ret = ocfs2_split_and_insert(inode, handle, path, di_bh,
+-                                                   &last_eb_bh, split_index,
+-                                                   split_rec, meta_ac);
+-              if (ret)
+-                      mlog_errno(ret);
+-      } else {
+-              ret = ocfs2_try_to_merge_extent(inode, handle, path,
+-                                              split_index, split_rec,
+-                                              dealloc, &ctxt);
+-              if (ret)
+-                      mlog_errno(ret);
+-      }
+-
+-      ocfs2_journal_dirty(handle, eb_bh);
+-
+-out:
+-      brelse(last_eb_bh);
++              brelse(bh);
+       return ret;
  }
  
  /*
-- * Lock the page of an asynchronous request
-+ * Lock the page of an asynchronous request and take a reference
+- * Mark the already-existing extent at cpos as written for len clusters.
+- *
+- * If the existing extent is larger than the request, initiate a
+- * split. An attempt will be made at merging with adjacent extents.
++ * Insert an extent into an inode btree.
+  *
+- * The caller is responsible for passing down meta_ac if we'll need it.
++ * The caller needs to update fe->i_clusters
   */
- static inline int
- nfs_lock_request(struct nfs_page *req)
- {
-       if (test_and_set_bit(PG_BUSY, &req->wb_flags))
-               return 0;
--      atomic_inc(&req->wb_count);
-+      kref_get(&req->wb_kref);
-       return 1;
- }
-@@ -118,7 +117,6 @@
- nfs_list_add_request(struct nfs_page *req, struct list_head *head)
+-int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
+-                            handle_t *handle, u32 cpos, u32 len, u32 phys,
+-                            struct ocfs2_alloc_context *meta_ac,
+-                            struct ocfs2_cached_dealloc_ctxt *dealloc)
++int ocfs2_insert_extent(struct ocfs2_super *osb,
++                      handle_t *handle,
++                      struct inode *inode,
++                      struct buffer_head *fe_bh,
++                      u32 cpos,
++                      u64 start_blk,
++                      u32 new_clusters,
++                      struct ocfs2_alloc_context *meta_ac)
  {
-       list_add_tail(&req->wb_list, head);
--      req->wb_list_head = head;
- }
-@@ -132,7 +130,6 @@
-       if (list_empty(&req->wb_list))
-               return;
-       list_del_init(&req->wb_list);
--      req->wb_list_head = NULL;
- }
- static inline struct nfs_page *
-diff -Nurb linux-2.6.22-570/include/linux/nfs_xdr.h linux-2.6.22-590/include/linux/nfs_xdr.h
---- linux-2.6.22-570/include/linux/nfs_xdr.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/nfs_xdr.h   2008-01-02 13:56:37.000000000 -0500
-@@ -144,6 +144,7 @@
-       nfs4_stateid            delegation;
-       __u32                   do_recall;
-       __u64                   maxsize;
-+      __u32                   attrset[NFS4_BITMAP_SIZE];
- };
- /*
-diff -Nurb linux-2.6.22-570/include/linux/nsproxy.h linux-2.6.22-590/include/linux/nsproxy.h
---- linux-2.6.22-570/include/linux/nsproxy.h   2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/nsproxy.h   2008-01-02 13:56:37.000000000 -0500
-@@ -10,6 +10,12 @@
- struct ipc_namespace;
- struct pid_namespace;
+-      int ret, index;
+-      u64 start_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys);
+-      struct ocfs2_extent_rec split_rec;
+-      struct ocfs2_path *left_path = NULL;
+-      struct ocfs2_extent_list *el;
++      int status, shift;
++      struct buffer_head *last_eb_bh = NULL;
++      struct buffer_head *bh = NULL;
++      struct ocfs2_insert_type insert = {0, };
++      struct ocfs2_extent_rec rec;
  
-+#ifdef CONFIG_CONTAINER_NS
-+int ns_container_clone(struct task_struct *tsk);
-+#else
-+static inline int ns_container_clone(struct task_struct *tsk) { return 0; }
-+#endif
-+
- /*
-  * A structure to contain pointers to all per-process
-  * namespaces - fs (mount), uts, network, sysvipc, etc.
-@@ -29,10 +35,12 @@
-       struct ipc_namespace *ipc_ns;
-       struct mnt_namespace *mnt_ns;
-       struct pid_namespace *pid_ns;
-+      struct user_namespace *user_ns;
-+      struct net           *net_ns;
- };
- extern struct nsproxy init_nsproxy;
+-      mlog(0, "Inode %lu cpos %u, len %u, phys %u (%llu)\n",
+-           inode->i_ino, cpos, len, phys, (unsigned long long)start_blkno);
++      mlog(0, "add %u clusters at position %u to inode %llu\n",
++           new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno);
  
--int copy_namespaces(int flags, struct task_struct *tsk);
-+int copy_namespaces(unsigned long flags, struct task_struct *tsk);
- struct nsproxy *copy_nsproxy(struct nsproxy *orig);
- void get_task_namespaces(struct task_struct *tsk);
- void free_nsproxy(struct nsproxy *ns);
-diff -Nurb linux-2.6.22-570/include/linux/pageblock-flags.h linux-2.6.22-590/include/linux/pageblock-flags.h
---- linux-2.6.22-570/include/linux/pageblock-flags.h   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/linux/pageblock-flags.h   2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,52 @@
-+/*
-+ * Macros for manipulating and testing flags related to a
-+ * MAX_ORDER_NR_PAGES block of pages.
-+ *
-+ * 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 version 2 of the License
-+ *
-+ * 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.
-+ *
-+ * Copyright (C) IBM Corporation, 2006
-+ *
-+ * Original author, Mel Gorman
-+ * Major cleanups and reduction of bit operations, Andy Whitcroft
-+ */
-+#ifndef PAGEBLOCK_FLAGS_H
-+#define PAGEBLOCK_FLAGS_H
-+
-+#include <linux/types.h>
-+
-+/* Macro to aid the definition of ranges of bits */
-+#define PB_range(name, required_bits) \
-+      name, name ## _end = (name + required_bits) - 1
-+
-+/* Bit indices that affect a whole block of pages */
-+enum pageblock_bits {
-+      PB_range(PB_migrate, 2), /* 2 bits required for migrate types */
-+      NR_PAGEBLOCK_BITS
-+};
-+
-+/* Forward declaration */
-+struct page;
-+
-+/* Declarations for getting and setting flags. See mm/page_alloc.c */
-+unsigned long get_pageblock_flags_group(struct page *page,
-+                                      int start_bitidx, int end_bitidx);
-+void set_pageblock_flags_group(struct page *page, unsigned long flags,
-+                                      int start_bitidx, int end_bitidx);
+-      if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {
+-              ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents "
+-                          "that are being written to, but the feature bit "
+-                          "is not set in the super block.",
+-                          (unsigned long long)OCFS2_I(inode)->ip_blkno);
+-              ret = -EROFS;
+-              goto out;
++      mlog_bug_on_msg(!ocfs2_sparse_alloc(osb) &&
++                      (OCFS2_I(inode)->ip_clusters != cpos),
++                      "Device %s, asking for sparse allocation: inode %llu, "
++                      "cpos %u, clusters %u\n",
++                      osb->dev_str,
++                      (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos,
++                      OCFS2_I(inode)->ip_clusters);
 +
-+#define get_pageblock_flags(page) \
-+                      get_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
-+#define set_pageblock_flags(page) \
-+                      set_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
++      memset(&rec, 0, sizeof(rec));
++      rec.e_cpos = cpu_to_le32(cpos);
++      rec.e_blkno = cpu_to_le64(start_blk);
++      rec.e_leaf_clusters = cpu_to_le16(new_clusters);
 +
-+#endif        /* PAGEBLOCK_FLAGS_H */
-diff -Nurb linux-2.6.22-570/include/linux/pci_ids.h linux-2.6.22-590/include/linux/pci_ids.h
---- linux-2.6.22-570/include/linux/pci_ids.h   2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/include/linux/pci_ids.h   2008-01-02 13:56:37.000000000 -0500
-@@ -2003,6 +2003,7 @@
- #define PCI_VENDOR_ID_ENE             0x1524
- #define PCI_DEVICE_ID_ENE_CB712_SD    0x0550
-+#define PCI_DEVICE_ID_ENE_CB712_SD_2  0x0551
- #define PCI_DEVICE_ID_ENE_1211                0x1211
- #define PCI_DEVICE_ID_ENE_1225                0x1225
- #define PCI_DEVICE_ID_ENE_1410                0x1410
-diff -Nurb linux-2.6.22-570/include/linux/pid_namespace.h linux-2.6.22-590/include/linux/pid_namespace.h
---- linux-2.6.22-570/include/linux/pid_namespace.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/pid_namespace.h     2008-01-02 13:56:37.000000000 -0500
-@@ -29,7 +29,7 @@
-       kref_get(&ns->kref);
- }
++      status = ocfs2_figure_insert_type(inode, fe_bh, &last_eb_bh, &rec,
++                                        &insert);
++      if (status < 0) {
++              mlog_errno(status);
++              goto bail;
+       }
  
--extern struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *ns);
-+extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns);
- extern void free_pid_ns(struct kref *kref);
++      mlog(0, "Insert.appending: %u, Insert.Contig: %u, "
++           "Insert.contig_index: %d, Insert.free_records: %d, "
++           "Insert.tree_depth: %d\n",
++           insert.ins_appending, insert.ins_contig, insert.ins_contig_index,
++           insert.ins_free_records, insert.ins_tree_depth);
++
+       /*
+-       * XXX: This should be fixed up so that we just re-insert the
+-       * next extent records.
++       * Avoid growing the tree unless we're out of records and the
++       * insert type requres one.
+        */
+-      ocfs2_extent_map_trunc(inode, 0);
++      if (insert.ins_contig != CONTIG_NONE || insert.ins_free_records)
++              goto out_add;
  
- static inline void put_pid_ns(struct pid_namespace *ns)
-diff -Nurb linux-2.6.22-570/include/linux/pnp.h linux-2.6.22-590/include/linux/pnp.h
---- linux-2.6.22-570/include/linux/pnp.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/pnp.h       2008-01-02 13:56:37.000000000 -0500
-@@ -335,6 +335,10 @@
-       int (*set)(struct pnp_dev *dev, struct pnp_resource_table *res);
-       int (*disable)(struct pnp_dev *dev);
+-      left_path = ocfs2_new_inode_path(di_bh);
+-      if (!left_path) {
+-              ret = -ENOMEM;
+-              mlog_errno(ret);
+-              goto out;
++      shift = ocfs2_find_branch_target(osb, inode, fe_bh, &bh);
++      if (shift < 0) {
++              status = shift;
++              mlog_errno(status);
++              goto bail;
+       }
  
-+      /* protocol specific suspend/resume */
-+      int (*suspend)(struct pnp_dev *dev, pm_message_t state);
-+      int (*resume)(struct pnp_dev *dev);
+-      ret = ocfs2_find_path(inode, left_path, cpos);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out;
++      /* We traveled all the way to the bottom of the allocation tree
++       * and didn't find room for any more extents - we need to add
++       * another tree level */
++      if (shift) {
++              BUG_ON(bh);
++              mlog(0, "need to shift tree depth "
++                   "(current = %d)\n", insert.ins_tree_depth);
 +
-       /* used by pnp layer only (look but don't touch) */
-       unsigned char           number;         /* protocol number*/
-       struct device           dev;            /* link to driver model */
-diff -Nurb linux-2.6.22-570/include/linux/prctl.h linux-2.6.22-590/include/linux/prctl.h
---- linux-2.6.22-570/include/linux/prctl.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/prctl.h     2008-01-02 13:56:37.000000000 -0500
-@@ -59,4 +59,8 @@
- # define PR_ENDIAN_LITTLE     1       /* True little endian mode */
- # define PR_ENDIAN_PPC_LITTLE 2       /* "PowerPC" pseudo little endian */
++              /* ocfs2_shift_tree_depth will return us a buffer with
++               * the new extent block (so we can pass that to
++               * ocfs2_add_branch). */
++              status = ocfs2_shift_tree_depth(osb, handle, inode, fe_bh,
++                                              meta_ac, &bh);
++              if (status < 0) {
++                      mlog_errno(status);
++                      goto bail;
++              }
++              insert.ins_tree_depth++;
++              /* Special case: we have room now if we shifted from
++               * tree_depth 0 */
++              if (insert.ins_tree_depth == 1)
++                      goto out_add;
+       }
+-      el = path_leaf_el(left_path);
+-      index = ocfs2_search_extent_list(el, cpos);
+-      if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
+-              ocfs2_error(inode->i_sb,
+-                          "Inode %llu has an extent at cpos %u which can no "
+-                          "longer be found.\n",
+-                          (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos);
+-              ret = -EROFS;
+-              goto out;
++      /* call ocfs2_add_branch to add the final part of the tree with
++       * the new data. */
++      mlog(0, "add branch. bh = %p\n", bh);
++      status = ocfs2_add_branch(osb, handle, inode, fe_bh, bh, last_eb_bh,
++                                meta_ac);
++      if (status < 0) {
++              mlog_errno(status);
++              goto bail;
+       }
  
-+/* Get/set process seccomp mode */
-+#define PR_GET_SECCOMP        21
-+#define PR_SET_SECCOMP        22
+-      memset(&split_rec, 0, sizeof(struct ocfs2_extent_rec));
+-      split_rec.e_cpos = cpu_to_le32(cpos);
+-      split_rec.e_leaf_clusters = cpu_to_le16(len);
+-      split_rec.e_blkno = cpu_to_le64(start_blkno);
+-      split_rec.e_flags = path_leaf_el(left_path)->l_recs[index].e_flags;
+-      split_rec.e_flags &= ~OCFS2_EXT_UNWRITTEN;
++out_add:
++      /* Finally, we can add clusters. This might rotate the tree for us. */
++      status = ocfs2_do_insert_extent(inode, handle, fe_bh, &rec, &insert);
++      if (status < 0)
++              mlog_errno(status);
++      else
++              ocfs2_extent_map_insert_rec(inode, &rec);
 +
- #endif /* _LINUX_PRCTL_H */
-diff -Nurb linux-2.6.22-570/include/linux/proc_fs.h linux-2.6.22-590/include/linux/proc_fs.h
---- linux-2.6.22-570/include/linux/proc_fs.h   2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/proc_fs.h   2008-01-02 13:56:37.000000000 -0500
-@@ -86,8 +86,6 @@
++bail:
++      if (bh)
++              brelse(bh);
  
- extern struct proc_dir_entry proc_root;
- extern struct proc_dir_entry *proc_root_fs;
--extern struct proc_dir_entry *proc_net;
--extern struct proc_dir_entry *proc_net_stat;
- extern struct proc_dir_entry *proc_bus;
- extern struct proc_dir_entry *proc_root_driver;
- extern struct proc_dir_entry *proc_root_kcore;
-@@ -105,7 +103,6 @@
- unsigned long task_vsize(struct mm_struct *);
- int task_statm(struct mm_struct *, int *, int *, int *, int *);
- char *task_mem(struct mm_struct *, char *);
--void clear_refs_smap(struct mm_struct *mm);
+-      ret = __ocfs2_mark_extent_written(inode, di_bh, handle, left_path,
+-                                        index, &split_rec, meta_ac, dealloc);
+-      if (ret)
+-              mlog_errno(ret);
++      if (last_eb_bh)
++              brelse(last_eb_bh);
  
- struct proc_dir_entry *de_get(struct proc_dir_entry *de);
- void de_put(struct proc_dir_entry *de);
-@@ -113,6 +110,10 @@
- extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
-                                               struct proc_dir_entry *parent);
- extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
-+static inline void remove_proc_pde(struct proc_dir_entry *pde)
-+{
-+      return remove_proc_entry(pde->name, pde->parent);
-+}
+-out:
+-      ocfs2_free_path(left_path);
+-      return ret;
++      mlog_exit(status);
++      return status;
+ }
  
- extern struct vfsmount *proc_mnt;
- extern int proc_fill_super(struct super_block *,void *,int);
-@@ -182,42 +183,18 @@
-       return res;
+ static inline int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb)
+@@ -4420,219 +2957,6 @@
+       return status;
  }
-  
--static inline struct proc_dir_entry *proc_net_create(const char *name,
--      mode_t mode, get_info_t *get_info)
+-/*
+- * Delayed de-allocation of suballocator blocks.
+- *
+- * Some sets of block de-allocations might involve multiple suballocator inodes.
+- *
+- * The locking for this can get extremely complicated, especially when
+- * the suballocator inodes to delete from aren't known until deep
+- * within an unrelated codepath.
+- *
+- * ocfs2_extent_block structures are a good example of this - an inode
+- * btree could have been grown by any number of nodes each allocating
+- * out of their own suballoc inode.
+- *
+- * These structures allow the delay of block de-allocation until a
+- * later time, when locking of multiple cluster inodes won't cause
+- * deadlock.
+- */
+-
+-/*
+- * Describes a single block free from a suballocator
+- */
+-struct ocfs2_cached_block_free {
+-      struct ocfs2_cached_block_free          *free_next;
+-      u64                                     free_blk;
+-      unsigned int                            free_bit;
+-};
+-
+-struct ocfs2_per_slot_free_list {
+-      struct ocfs2_per_slot_free_list         *f_next_suballocator;
+-      int                                     f_inode_type;
+-      int                                     f_slot;
+-      struct ocfs2_cached_block_free          *f_first;
+-};
+-
+-static int ocfs2_free_cached_items(struct ocfs2_super *osb,
+-                                 int sysfile_type,
+-                                 int slot,
+-                                 struct ocfs2_cached_block_free *head)
+-{
+-      int ret;
+-      u64 bg_blkno;
+-      handle_t *handle;
+-      struct inode *inode;
+-      struct buffer_head *di_bh = NULL;
+-      struct ocfs2_cached_block_free *tmp;
+-
+-      inode = ocfs2_get_system_file_inode(osb, sysfile_type, slot);
+-      if (!inode) {
+-              ret = -EINVAL;
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      mutex_lock(&inode->i_mutex);
+-
+-      ret = ocfs2_meta_lock(inode, &di_bh, 1);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out_mutex;
+-      }
+-
+-      handle = ocfs2_start_trans(osb, OCFS2_SUBALLOC_FREE);
+-      if (IS_ERR(handle)) {
+-              ret = PTR_ERR(handle);
+-              mlog_errno(ret);
+-              goto out_unlock;
+-      }
+-
+-      while (head) {
+-              bg_blkno = ocfs2_which_suballoc_group(head->free_blk,
+-                                                    head->free_bit);
+-              mlog(0, "Free bit: (bit %u, blkno %llu)\n",
+-                   head->free_bit, (unsigned long long)head->free_blk);
+-
+-              ret = ocfs2_free_suballoc_bits(handle, inode, di_bh,
+-                                             head->free_bit, bg_blkno, 1);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out_journal;
+-              }
+-
+-              ret = ocfs2_extend_trans(handle, OCFS2_SUBALLOC_FREE);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out_journal;
+-              }
+-
+-              tmp = head;
+-              head = head->free_next;
+-              kfree(tmp);
+-      }
+-
+-out_journal:
+-      ocfs2_commit_trans(osb, handle);
+-
+-out_unlock:
+-      ocfs2_meta_unlock(inode, 1);
+-      brelse(di_bh);
+-out_mutex:
+-      mutex_unlock(&inode->i_mutex);
+-      iput(inode);
+-out:
+-      while(head) {
+-              /* Premature exit may have left some dangling items. */
+-              tmp = head;
+-              head = head->free_next;
+-              kfree(tmp);
+-      }
+-
+-      return ret;
+-}
+-
+-int ocfs2_run_deallocs(struct ocfs2_super *osb,
+-                     struct ocfs2_cached_dealloc_ctxt *ctxt)
 -{
--      return create_proc_info_entry(name,mode,proc_net,get_info);
+-      int ret = 0, ret2;
+-      struct ocfs2_per_slot_free_list *fl;
+-
+-      if (!ctxt)
+-              return 0;
+-
+-      while (ctxt->c_first_suballocator) {
+-              fl = ctxt->c_first_suballocator;
+-
+-              if (fl->f_first) {
+-                      mlog(0, "Free items: (type %u, slot %d)\n",
+-                           fl->f_inode_type, fl->f_slot);
+-                      ret2 = ocfs2_free_cached_items(osb, fl->f_inode_type,
+-                                                     fl->f_slot, fl->f_first);
+-                      if (ret2)
+-                              mlog_errno(ret2);
+-                      if (!ret)
+-                              ret = ret2;
+-              }
+-
+-              ctxt->c_first_suballocator = fl->f_next_suballocator;
+-              kfree(fl);
+-      }
+-
+-      return ret;
 -}
 -
--static inline struct proc_dir_entry *proc_net_fops_create(const char *name,
--      mode_t mode, const struct file_operations *fops)
+-static struct ocfs2_per_slot_free_list *
+-ocfs2_find_per_slot_free_list(int type,
+-                            int slot,
+-                            struct ocfs2_cached_dealloc_ctxt *ctxt)
 -{
--      struct proc_dir_entry *res = create_proc_entry(name, mode, proc_net);
--      if (res)
--              res->proc_fops = fops;
--      return res;
+-      struct ocfs2_per_slot_free_list *fl = ctxt->c_first_suballocator;
+-
+-      while (fl) {
+-              if (fl->f_inode_type == type && fl->f_slot == slot)
+-                      return fl;
+-
+-              fl = fl->f_next_suballocator;
+-      }
+-
+-      fl = kmalloc(sizeof(*fl), GFP_NOFS);
+-      if (fl) {
+-              fl->f_inode_type = type;
+-              fl->f_slot = slot;
+-              fl->f_first = NULL;
+-              fl->f_next_suballocator = ctxt->c_first_suballocator;
+-
+-              ctxt->c_first_suballocator = fl;
+-      }
+-      return fl;
 -}
 -
--static inline void proc_net_remove(const char *name)
+-static int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
+-                                   int type, int slot, u64 blkno,
+-                                   unsigned int bit)
 -{
--      remove_proc_entry(name,proc_net);
+-      int ret;
+-      struct ocfs2_per_slot_free_list *fl;
+-      struct ocfs2_cached_block_free *item;
+-
+-      fl = ocfs2_find_per_slot_free_list(type, slot, ctxt);
+-      if (fl == NULL) {
+-              ret = -ENOMEM;
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      item = kmalloc(sizeof(*item), GFP_NOFS);
+-      if (item == NULL) {
+-              ret = -ENOMEM;
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      mlog(0, "Insert: (type %d, slot %u, bit %u, blk %llu)\n",
+-           type, slot, bit, (unsigned long long)blkno);
+-
+-      item->free_blk = blkno;
+-      item->free_bit = bit;
+-      item->free_next = fl->f_first;
+-
+-      fl->f_first = item;
+-
+-      ret = 0;
+-out:
+-      return ret;
 -}
 -
- #else
- #define proc_root_driver NULL
--#define proc_net NULL
- #define proc_bus NULL
--#define proc_net_fops_create(name, mode, fops)  ({ (void)(mode), NULL; })
--#define proc_net_create(name, mode, info)     ({ (void)(mode), NULL; })
--static inline void proc_net_remove(const char *name) {}
+-static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
+-                                       struct ocfs2_extent_block *eb)
+-{
+-      return ocfs2_cache_block_dealloc(ctxt, EXTENT_ALLOC_SYSTEM_INODE,
+-                                       le16_to_cpu(eb->h_suballoc_slot),
+-                                       le64_to_cpu(eb->h_blkno),
+-                                       le16_to_cpu(eb->h_suballoc_bit));
+-}
 -
- static inline void proc_flush_task(struct task_struct *task) { }
- static inline struct proc_dir_entry *create_proc_entry(const char *name,
-       mode_t mode, struct proc_dir_entry *parent) { return NULL; }
+ /* This function will figure out whether the currently last extent
+  * block will be deleted, and if it will, what the new last extent
+  * block will be so we can update his h_next_leaf_blk field, as well
+@@ -4914,10 +3238,27 @@
+                       BUG_ON(le32_to_cpu(el->l_recs[0].e_cpos));
+                       BUG_ON(le64_to_cpu(el->l_recs[0].e_blkno));
  
- #define remove_proc_entry(name, parent) do {} while (0)
-+#define remove_proc_pde(PDE) do {} while (0)
+-                      ret = ocfs2_cache_extent_block_free(&tc->tc_dealloc, eb);
++                      if (le16_to_cpu(eb->h_suballoc_slot) == 0) {
++                              /*
++                               * This code only understands how to
++                               * lock the suballocator in slot 0,
++                               * which is fine because allocation is
++                               * only ever done out of that
++                               * suballocator too. A future version
++                               * might change that however, so avoid
++                               * a free if we don't know how to
++                               * handle it. This way an fs incompat
++                               * bit will not be necessary.
++                               */
++                              ret = ocfs2_free_extent_block(handle,
++                                                            tc->tc_ext_alloc_inode,
++                                                            tc->tc_ext_alloc_bh,
++                                                            eb);
++
+                               /* An error here is not fatal. */
+                               if (ret < 0)
+                                       mlog_errno(ret);
++                      }
+               } else {
+                       deleted_eb = 0;
+               }
+@@ -5290,6 +3631,8 @@
  
- static inline struct proc_dir_entry *proc_symlink(const char *name,
-               struct proc_dir_entry *parent,const char *dest) {return NULL;}
-diff -Nurb linux-2.6.22-570/include/linux/raid/raid5.h linux-2.6.22-590/include/linux/raid/raid5.h
---- linux-2.6.22-570/include/linux/raid/raid5.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/raid/raid5.h        2008-01-02 13:56:37.000000000 -0500
-@@ -116,13 +116,46 @@
-  *  attach a request to an active stripe (add_stripe_bh())
-  *     lockdev attach-buffer unlockdev
-  *  handle a stripe (handle_stripe())
-- *     lockstripe clrSTRIPE_HANDLE ... (lockdev check-buffers unlockdev) .. change-state .. record io needed unlockstripe schedule io
-+ *     lockstripe clrSTRIPE_HANDLE ...
-+ *            (lockdev check-buffers unlockdev) ..
-+ *            change-state ..
-+ *            record io/ops needed unlockstripe schedule io/ops
-  *  release an active stripe (release_stripe())
-  *     lockdev if (!--cnt) { if  STRIPE_HANDLE, add to handle_list else add to inactive-list } unlockdev
-  *
-  * The refcount counts each thread that have activated the stripe,
-  * plus raid5d if it is handling it, plus one for each active request
-- * on a cached buffer.
-+ * on a cached buffer, and plus one if the stripe is undergoing stripe
-+ * operations.
-+ *
-+ * Stripe operations are performed outside the stripe lock,
-+ * the stripe operations are:
-+ * -copying data between the stripe cache and user application buffers
-+ * -computing blocks to save a disk access, or to recover a missing block
-+ * -updating the parity on a write operation (reconstruct write and
-+ *  read-modify-write)
-+ * -checking parity correctness
-+ * -running i/o to disk
-+ * These operations are carried out by raid5_run_ops which uses the async_tx
-+ * api to (optionally) offload operations to dedicated hardware engines.
-+ * When requesting an operation handle_stripe sets the pending bit for the
-+ * operation and increments the count.  raid5_run_ops is then run whenever
-+ * the count is non-zero.
-+ * There are some critical dependencies between the operations that prevent some
-+ * from being requested while another is in flight.
-+ * 1/ Parity check operations destroy the in cache version of the parity block,
-+ *    so we prevent parity dependent operations like writes and compute_blocks
-+ *    from starting while a check is in progress.  Some dma engines can perform
-+ *    the check without damaging the parity block, in these cases the parity
-+ *    block is re-marked up to date (assuming the check was successful) and is
-+ *    not re-read from disk.
-+ * 2/ When a write operation is requested we immediately lock the affected
-+ *    blocks, and mark them as not up to date.  This causes new read requests
-+ *    to be held off, as well as parity checks and compute block operations.
-+ * 3/ Once a compute block operation has been requested handle_stripe treats
-+ *    that block as if it is up to date.  raid5_run_ops guaruntees that any
-+ *    operation that is dependent on the compute block result is initiated after
-+ *    the compute block completes.
-  */
+       mlog_entry_void();
  
- struct stripe_head {
-@@ -136,15 +169,46 @@
-       spinlock_t              lock;
-       int                     bm_seq; /* sequence number for bitmap flushes */
-       int                     disks;                  /* disks in stripe */
-+      /* stripe_operations
-+       * @pending - pending ops flags (set for request->issue->complete)
-+       * @ack - submitted ops flags (set for issue->complete)
-+       * @complete - completed ops flags (set for complete)
-+       * @target - STRIPE_OP_COMPUTE_BLK target
-+       * @count - raid5_runs_ops is set to run when this is non-zero
-+       */
-+      struct stripe_operations {
-+              unsigned long      pending;
-+              unsigned long      ack;
-+              unsigned long      complete;
-+              int                target;
-+              int                count;
-+              u32                zero_sum_result;
-+      } ops;
-       struct r5dev {
-               struct bio      req;
-               struct bio_vec  vec;
-               struct page     *page;
--              struct bio      *toread, *towrite, *written;
-+              struct bio      *toread, *read, *towrite, *written;
-               sector_t        sector;                 /* sector of this page */
-               unsigned long   flags;
-       } dev[1]; /* allocated with extra space depending of RAID geometry */
- };
-+
-+/* stripe_head_state - collects and tracks the dynamic state of a stripe_head
-+ *     for handle_stripe.  It is only valid under spin_lock(sh->lock);
-+ */
-+struct stripe_head_state {
-+      int syncing, expanding, expanded;
-+      int locked, uptodate, to_read, to_write, failed, written;
-+      int to_fill, compute, req_compute, non_overwrite, dirty;
-+      int failed_num;
-+};
-+
-+/* r6_state - extra state data only relevant to r6 */
-+struct r6_state {
-+      int p_failed, q_failed, qd_idx, failed_num[2];
-+};
++      down_write(&OCFS2_I(inode)->ip_alloc_sem);
 +
- /* Flags */
- #define       R5_UPTODATE     0       /* page contains current data */
- #define       R5_LOCKED       1       /* IO has been submitted on "req" */
-@@ -158,6 +222,15 @@
- #define       R5_ReWrite      9       /* have tried to over-write the readerror */
+       new_highest_cpos = ocfs2_clusters_for_bytes(osb->sb,
+                                                    i_size_read(inode));
  
- #define       R5_Expanded     10      /* This block now has post-expand data */
-+#define       R5_Wantcompute  11 /* compute_block in progress treat as
-+                                  * uptodate
-+                                  */
-+#define       R5_Wantfill     12 /* dev->toread contains a bio that needs
-+                                  * filling
-+                                  */
-+#define       R5_Wantprexor   13 /* distinguish blocks ready for rmw from
-+                                  * other "towrites"
-+                                  */
- /*
-  * Write method
-  */
-@@ -180,6 +253,24 @@
- #define       STRIPE_EXPAND_SOURCE    10
- #define       STRIPE_EXPAND_READY     11
- /*
-+ * Operations flags (in issue order)
-+ */
-+#define STRIPE_OP_BIOFILL     0
-+#define STRIPE_OP_COMPUTE_BLK 1
-+#define STRIPE_OP_PREXOR      2
-+#define STRIPE_OP_BIODRAIN    3
-+#define STRIPE_OP_POSTXOR     4
-+#define STRIPE_OP_CHECK       5
-+#define STRIPE_OP_IO          6
-+
-+/* modifiers to the base operations
-+ * STRIPE_OP_MOD_REPAIR_PD - compute the parity block and write it back
-+ * STRIPE_OP_MOD_DMA_CHECK - parity is not corrupted by the check
-+ */
-+#define STRIPE_OP_MOD_REPAIR_PD 7
-+#define STRIPE_OP_MOD_DMA_CHECK 8
-+
-+/*
-  * Plugging:
-  *
-  * To improve write throughput, we need to delay the handling of some
-diff -Nurb linux-2.6.22-570/include/linux/raid/xor.h linux-2.6.22-590/include/linux/raid/xor.h
---- linux-2.6.22-570/include/linux/raid/xor.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/raid/xor.h  2008-01-02 13:56:37.000000000 -0500
-@@ -3,9 +3,10 @@
+@@ -5411,6 +3754,7 @@
+       goto start;
  
- #include <linux/raid/md.h>
+ bail:
++      up_write(&OCFS2_I(inode)->ip_alloc_sem);
  
--#define MAX_XOR_BLOCKS 5
-+#define MAX_XOR_BLOCKS 4
+       ocfs2_schedule_truncate_log_flush(osb, 1);
  
--extern void xor_block(unsigned int count, unsigned int bytes, void **ptr);
-+extern void xor_blocks(unsigned int count, unsigned int bytes,
-+      void *dest, void **srcs);
+@@ -5420,8 +3764,6 @@
+       if (handle)
+               ocfs2_commit_trans(osb, handle);
  
- struct xor_block_template {
-         struct xor_block_template *next;
-diff -Nurb linux-2.6.22-570/include/linux/reboot.h linux-2.6.22-590/include/linux/reboot.h
---- linux-2.6.22-570/include/linux/reboot.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/reboot.h    2008-01-02 13:56:37.000000000 -0500
-@@ -67,6 +67,11 @@
+-      ocfs2_run_deallocs(osb, &tc->tc_dealloc);
+-
+       ocfs2_free_path(path);
  
- void ctrl_alt_del(void);
+       /* This will drop the ext_alloc cluster lock for us */
+@@ -5432,18 +3774,23 @@
+ }
  
-+#define POWEROFF_CMD_PATH_LEN 256
-+extern char poweroff_cmd[POWEROFF_CMD_PATH_LEN];
-+
-+extern int orderly_poweroff(bool force);
-+
  /*
-  * Emergency restart, callable from an interrupt handler.
+- * Expects the inode to already be locked.
++ * Expects the inode to already be locked. This will figure out which
++ * inodes need to be locked and will put them on the returned truncate
++ * context.
   */
-diff -Nurb linux-2.6.22-570/include/linux/revoked_fs_i.h linux-2.6.22-590/include/linux/revoked_fs_i.h
---- linux-2.6.22-570/include/linux/revoked_fs_i.h      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/linux/revoked_fs_i.h      2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,18 @@
-+#ifndef _LINUX_REVOKED_FS_I_H
-+#define _LINUX_REVOKED_FS_I_H
-+
-+struct revokefs_inode_info {
-+      struct task_struct *owner;
-+      struct file *file;
-+      unsigned int fd;
-+      struct inode vfs_inode;
-+};
-+
-+static inline struct revokefs_inode_info *revokefs_i(struct inode *inode)
-+{
-+      return container_of(inode, struct revokefs_inode_info, vfs_inode);
-+}
-+
-+void make_revoked_inode(struct inode *, int);
-+
-+#endif
-diff -Nurb linux-2.6.22-570/include/linux/rtnetlink.h linux-2.6.22-590/include/linux/rtnetlink.h
---- linux-2.6.22-570/include/linux/rtnetlink.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/rtnetlink.h 2008-01-02 13:56:37.000000000 -0500
-@@ -261,7 +261,7 @@
-       RTA_FLOW,
-       RTA_CACHEINFO,
-       RTA_SESSION,
--      RTA_MP_ALGO,
-+      RTA_MP_ALGO, /* no longer used */
-       RTA_TABLE,
-       __RTA_MAX
- };
-@@ -570,15 +570,21 @@
- }
+ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
+                          struct inode *inode,
+                          struct buffer_head *fe_bh,
+                          struct ocfs2_truncate_context **tc)
+ {
+-      int status;
++      int status, metadata_delete, i;
+       unsigned int new_i_clusters;
+       struct ocfs2_dinode *fe;
+       struct ocfs2_extent_block *eb;
++      struct ocfs2_extent_list *el;
+       struct buffer_head *last_eb_bh = NULL;
++      struct inode *ext_alloc_inode = NULL;
++      struct buffer_head *ext_alloc_bh = NULL;
  
- extern int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len);
-+extern int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
-+                                      struct rtattr *rta, int len);
+       mlog_entry_void();
  
- #define rtattr_parse_nested(tb, max, rta) \
-       rtattr_parse((tb), (max), RTA_DATA((rta)), RTA_PAYLOAD((rta)))
+@@ -5463,9 +3810,12 @@
+               mlog_errno(status);
+               goto bail;
+       }
+-      ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc);
  
--extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo);
--extern int rtnl_unicast(struct sk_buff *skb, u32 pid);
--extern int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
-+#define rtattr_parse_nested_compat(tb, max, rta, data, len) \
-+({    data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \
-+      __rtattr_parse_nested_compat(tb, max, rta, len); })
++      metadata_delete = 0;
+       if (fe->id2.i_list.l_tree_depth) {
++              /* If we have a tree, then the truncate may result in
++               * metadata deletes. Figure this out from the
++               * rightmost leaf block.*/
+               status = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),
+                                         &last_eb_bh, OCFS2_BH_CACHED, inode);
+               if (status < 0) {
+@@ -5480,10 +3830,43 @@
+                       status = -EIO;
+                       goto bail;
+               }
++              el = &(eb->h_list);
 +
-+extern int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, u32 group, int echo);
-+extern int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid);
-+extern int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
-                      struct nlmsghdr *nlh, gfp_t flags);
--extern void rtnl_set_sk_err(u32 group, int error);
-+extern void rtnl_set_sk_err(struct net *net, u32 group, int error);
- extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics);
- extern int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst,
-                             u32 id, u32 ts, u32 tsage, long expires,
-@@ -638,6 +644,18 @@
- ({    (start)->rta_len = skb_tail_pointer(skb) - (unsigned char *)(start); \
-       (skb)->len; })
++              i = 0;
++              if (ocfs2_is_empty_extent(&el->l_recs[0]))
++                      i = 1;
++              /*
++               * XXX: Should we check that next_free_rec contains
++               * the extent?
++               */
++              if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_i_clusters)
++                      metadata_delete = 1;
+       }
+       (*tc)->tc_last_eb_bh = last_eb_bh;
  
-+#define RTA_NEST_COMPAT(skb, type, attrlen, data) \
-+({    struct rtattr *__start = (struct rtattr *)skb_tail_pointer(skb); \
-+      RTA_PUT(skb, type, attrlen, data); \
-+      RTA_NEST(skb, type); \
-+      __start; })
++      if (metadata_delete) {
++              mlog(0, "Will have to delete metadata for this trunc. "
++                   "locking allocator.\n");
++              ext_alloc_inode = ocfs2_get_system_file_inode(osb, EXTENT_ALLOC_SYSTEM_INODE, 0);
++              if (!ext_alloc_inode) {
++                      status = -ENOMEM;
++                      mlog_errno(status);
++                      goto bail;
++              }
 +
-+#define RTA_NEST_COMPAT_END(skb, start) \
-+({    struct rtattr *__nest = (void *)(start) + NLMSG_ALIGN((start)->rta_len); \
-+      (start)->rta_len = skb_tail_pointer(skb) - (unsigned char *)(start); \
-+      RTA_NEST_END(skb, __nest); \
-+      (skb)->len; })
++              mutex_lock(&ext_alloc_inode->i_mutex);
++              (*tc)->tc_ext_alloc_inode = ext_alloc_inode;
 +
- #define RTA_NEST_CANCEL(skb, start) \
- ({    if (start) \
-               skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
-diff -Nurb linux-2.6.22-570/include/linux/sched.h linux-2.6.22-590/include/linux/sched.h
---- linux-2.6.22-570/include/linux/sched.h     2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/sched.h     2008-01-02 13:56:37.000000000 -0500
-@@ -26,7 +26,9 @@
- #define CLONE_STOPPED         0x02000000      /* Start in stopped state */
- #define CLONE_NEWUTS          0x04000000      /* New utsname group? */
- #define CLONE_NEWIPC          0x08000000      /* New ipcs */
-+#define CLONE_NEWUSER         0x20000000      /* New user namespace */
- #define CLONE_KTHREAD         0x10000000      /* clone a kernel thread */
-+#define CLONE_NEWNET          0x40000000      /* New network namespace */
- /*
-  * Scheduling policies
-@@ -266,6 +268,7 @@
- asmlinkage void schedule(void);
- struct nsproxy;
-+struct user_namespace;
- /* Maximum number of active map areas.. This is a random (large) number */
- #define DEFAULT_MAX_MAP_COUNT 65536
-@@ -325,6 +328,27 @@
-               (mm)->hiwater_vm = (mm)->total_vm;      \
- } while (0)
-+extern void set_dumpable(struct mm_struct *mm, int value);
-+extern int get_dumpable(struct mm_struct *mm);
-+
-+/* mm flags */
-+/* dumpable bits */
-+#define MMF_DUMPABLE      0  /* core dump is permitted */
-+#define MMF_DUMP_SECURELY 1  /* core file is readable only by root */
-+#define MMF_DUMPABLE_BITS 2
-+
-+/* coredump filter bits */
-+#define MMF_DUMP_ANON_PRIVATE 2
-+#define MMF_DUMP_ANON_SHARED  3
-+#define MMF_DUMP_MAPPED_PRIVATE       4
-+#define MMF_DUMP_MAPPED_SHARED        5
-+#define MMF_DUMP_FILTER_SHIFT MMF_DUMPABLE_BITS
-+#define MMF_DUMP_FILTER_BITS  4
-+#define MMF_DUMP_FILTER_MASK \
-+      (((1 << MMF_DUMP_FILTER_BITS) - 1) << MMF_DUMP_FILTER_SHIFT)
-+#define MMF_DUMP_FILTER_DEFAULT \
-+      ((1 << MMF_DUMP_ANON_PRIVATE) | (1 << MMF_DUMP_ANON_SHARED))
++              status = ocfs2_meta_lock(ext_alloc_inode, &ext_alloc_bh, 1);
++              if (status < 0) {
++                      mlog_errno(status);
++                      goto bail;
++              }
++              (*tc)->tc_ext_alloc_bh = ext_alloc_bh;
++              (*tc)->tc_ext_alloc_locked = 1;
++      }
 +
- struct mm_struct {
-       struct vm_area_struct * mmap;           /* list of VMAs */
-       struct rb_root mm_rb;
-@@ -383,7 +407,7 @@
-       unsigned int token_priority;
-       unsigned int last_interval;
+       status = 0;
+ bail:
+       if (status < 0) {
+@@ -5497,13 +3880,16 @@
  
--      unsigned char dumpable:2;
-+      unsigned long flags; /* Must use atomic bitops to access the bits */
+ static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc)
+ {
+-      /*
+-       * The caller is responsible for completing deallocation
+-       * before freeing the context.
+-       */
+-      if (tc->tc_dealloc.c_first_suballocator != NULL)
+-              mlog(ML_NOTICE,
+-                   "Truncate completion has non-empty dealloc context\n");
++      if (tc->tc_ext_alloc_inode) {
++              if (tc->tc_ext_alloc_locked)
++                      ocfs2_meta_unlock(tc->tc_ext_alloc_inode, 1);
++
++              mutex_unlock(&tc->tc_ext_alloc_inode->i_mutex);
++              iput(tc->tc_ext_alloc_inode);
++      }
++
++      if (tc->tc_ext_alloc_bh)
++              brelse(tc->tc_ext_alloc_bh);
  
-       /* coredumping support */
-       int core_waiters;
-@@ -757,9 +781,6 @@
- #endif
- };
+       if (tc->tc_last_eb_bh)
+               brelse(tc->tc_last_eb_bh);
+diff -Nurb linux-2.6.22-590/fs/ocfs2/alloc.h linux-2.6.22-570/fs/ocfs2/alloc.h
+--- linux-2.6.22-590/fs/ocfs2/alloc.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/alloc.h  2007-07-08 19:32:17.000000000 -0400
+@@ -34,13 +34,7 @@
+                       u32 cpos,
+                       u64 start_blk,
+                       u32 new_clusters,
+-                      u8 flags,
+                       struct ocfs2_alloc_context *meta_ac);
+-struct ocfs2_cached_dealloc_ctxt;
+-int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
+-                            handle_t *handle, u32 cpos, u32 len, u32 phys,
+-                            struct ocfs2_alloc_context *meta_ac,
+-                            struct ocfs2_cached_dealloc_ctxt *dealloc);
+ int ocfs2_num_free_extents(struct ocfs2_super *osb,
+                          struct inode *inode,
+                          struct ocfs2_dinode *fe);
+@@ -69,27 +63,9 @@
+ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
+                                        struct ocfs2_dinode *tl_copy);
  
--extern int partition_sched_domains(cpumask_t *partition1,
--                                  cpumask_t *partition2);
+-/*
+- * Process local structure which describes the block unlinks done
+- * during an operation. This is populated via
+- * ocfs2_cache_block_dealloc().
+- *
+- * ocfs2_run_deallocs() should be called after the potentially
+- * de-allocating routines. No journal handles should be open, and most
+- * locks should have been dropped.
+- */
+-struct ocfs2_cached_dealloc_ctxt {
+-      struct ocfs2_per_slot_free_list         *c_first_suballocator;
+-};
+-static inline void ocfs2_init_dealloc_ctxt(struct ocfs2_cached_dealloc_ctxt *c)
+-{
+-      c->c_first_suballocator = NULL;
+-}
+-int ocfs2_run_deallocs(struct ocfs2_super *osb,
+-                     struct ocfs2_cached_dealloc_ctxt *ctxt);
 -
- /*
-  * Maximum cache size the migration-costs auto-tuning code will
-  * search from:
-@@ -770,8 +791,6 @@
+ struct ocfs2_truncate_context {
+-      struct ocfs2_cached_dealloc_ctxt tc_dealloc;
++      struct inode *tc_ext_alloc_inode;
++      struct buffer_head *tc_ext_alloc_bh;
+       int tc_ext_alloc_locked; /* is it cluster locked? */
+       /* these get destroyed once it's passed to ocfs2_commit_truncate. */
+       struct buffer_head *tc_last_eb_bh;
+@@ -108,7 +84,6 @@
  
- struct io_context;                    /* See blkdev.h */
--struct cpuset;
--
- #define NGROUPS_SMALL         32
- #define NGROUPS_PER_BLOCK     ((int)(PAGE_SIZE / sizeof(gid_t)))
- struct group_info {
-@@ -912,7 +931,7 @@
-       unsigned int rt_priority;
-       cputime_t utime, stime;
-       unsigned long nvcsw, nivcsw; /* context switch counts */
--      struct timespec start_time;
-+      struct timespec start_time, real_start_time;
- /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
-       unsigned long min_flt, maj_flt;
+ int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el,
+                   u32 cpos, struct buffer_head **leaf_bh);
+-int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster);
  
-@@ -1067,11 +1086,16 @@
-       short il_next;
- #endif
- #ifdef CONFIG_CPUSETS
--      struct cpuset *cpuset;
-       nodemask_t mems_allowed;
-       int cpuset_mems_generation;
-       int cpuset_mem_spread_rotor;
- #endif
-+#ifdef CONFIG_CONTAINERS
-+      /* Container info protected by css_group_lock */
-+      struct css_group *containers;
-+      /* cg_list protected by css_group_lock and tsk->alloc_lock */
-+      struct list_head cg_list;
-+#endif
-       struct robust_list_head __user *robust_list;
- #ifdef CONFIG_COMPAT
-       struct compat_robust_list_head __user *compat_robust_list;
-@@ -1514,7 +1538,8 @@
  /*
-  * Protects ->fs, ->files, ->mm, ->group_info, ->comm, keyring
-  * subscriptions and synchronises with wait4().  Also used in procfs.  Also
-- * pins the final release of task.io_context.  Also protects ->cpuset.
-+ * pins the final release of task.io_context.  Also protects ->cpuset and
-+ * ->container.subsys[].
-  *
-  * Nests both inside and outside of read_lock(&tasklist_lock).
-  * It must not be nested with write_lock_irq(&tasklist_lock),
-diff -Nurb linux-2.6.22-570/include/linux/seccomp.h linux-2.6.22-590/include/linux/seccomp.h
---- linux-2.6.22-570/include/linux/seccomp.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/seccomp.h   2008-01-02 13:56:37.000000000 -0500
-@@ -4,8 +4,6 @@
- #ifdef CONFIG_SECCOMP
+  * Helper function to look at the # of clusters in an extent record.
+diff -Nurb linux-2.6.22-590/fs/ocfs2/aops.c linux-2.6.22-570/fs/ocfs2/aops.c
+--- linux-2.6.22-590/fs/ocfs2/aops.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/aops.c   2008-01-23 19:15:56.000000000 -0500
+@@ -232,7 +232,7 @@
+        * might now be discovering a truncate that hit on another node.
+        * block_read_full_page->get_block freaks out if it is asked to read
+        * beyond the end of a file, so we check here.  Callers
+-       * (generic_file_read, vm_ops->fault) are clever enough to check i_size
++       * (generic_file_read, fault->nopage) are clever enough to check i_size
+        * and notice that the page they just read isn't needed.
+        *
+        * XXX sys_readahead() seems to get that wrong?
+@@ -705,8 +705,6 @@
+            bh = bh->b_this_page, block_start += bsize) {
+               block_end = block_start + bsize;
  
--#define NR_SECCOMP_MODES 1
+-              clear_buffer_new(bh);
 -
- #include <linux/thread_info.h>
- #include <asm/seccomp.h>
-@@ -23,6 +21,9 @@
-       return unlikely(test_ti_thread_flag(ti, TIF_SECCOMP));
- }
-+extern long prctl_get_seccomp(void);
-+extern long prctl_set_seccomp(unsigned long);
+               /*
+                * Ignore blocks outside of our i/o range -
+                * they may belong to unallocated clusters.
+@@ -721,8 +719,9 @@
+                * For an allocating write with cluster size >= page
+                * size, we always write the entire page.
+                */
+-              if (new)
+-                      set_buffer_new(bh);
 +
- #else /* CONFIG_SECCOMP */
- typedef struct { } seccomp_t;
-@@ -34,6 +35,16 @@
-       return 0;
- }
++              if (buffer_new(bh))
++                      clear_buffer_new(bh);
  
-+static inline long prctl_get_seccomp(void)
-+{
-+      return -EINVAL;
-+}
-+
-+static inline long prctl_set_seccomp(unsigned long arg2)
-+{
-+      return -EINVAL;
-+}
+               if (!buffer_mapped(bh)) {
+                       map_bh(bh, inode->i_sb, *p_blkno);
+@@ -761,13 +760,18 @@
+       bh = head;
+       block_start = 0;
+       do {
++              void *kaddr;
 +
- #endif /* CONFIG_SECCOMP */
- #endif /* _LINUX_SECCOMP_H */
-diff -Nurb linux-2.6.22-570/include/linux/security.h linux-2.6.22-590/include/linux/security.h
---- linux-2.6.22-570/include/linux/security.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/security.h  2008-01-02 13:56:37.000000000 -0500
-@@ -71,6 +71,7 @@
- extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
- extern int cap_netlink_recv(struct sk_buff *skb, int cap);
-+extern unsigned long mmap_min_addr;
- /*
-  * Values used in the task_security_ops calls
-  */
-@@ -1241,8 +1242,9 @@
-       int (*file_ioctl) (struct file * file, unsigned int cmd,
-                          unsigned long arg);
-       int (*file_mmap) (struct file * file,
--                        unsigned long reqprot,
--                        unsigned long prot, unsigned long flags);
-+                        unsigned long reqprot, unsigned long prot,
-+                        unsigned long flags, unsigned long addr,
-+                        unsigned long addr_only);
-       int (*file_mprotect) (struct vm_area_struct * vma,
-                             unsigned long reqprot,
-                             unsigned long prot);
-@@ -1814,9 +1816,12 @@
- static inline int security_file_mmap (struct file *file, unsigned long reqprot,
-                                     unsigned long prot,
--                                    unsigned long flags)
-+                                    unsigned long flags,
-+                                    unsigned long addr,
-+                                    unsigned long addr_only)
- {
--      return security_ops->file_mmap (file, reqprot, prot, flags);
-+      return security_ops->file_mmap (file, reqprot, prot, flags, addr,
-+                                      addr_only);
- }
+               block_end = block_start + bsize;
+               if (block_end <= from)
+                       goto next_bh;
+               if (block_start >= to)
+                       break;
  
- static inline int security_file_mprotect (struct vm_area_struct *vma,
-@@ -2489,7 +2494,9 @@
+-              zero_user_page(page, block_start, bh->b_size, KM_USER0);
++              kaddr = kmap_atomic(page, KM_USER0);
++              memset(kaddr+block_start, 0, bh->b_size);
++              flush_dcache_page(page);
++              kunmap_atomic(kaddr, KM_USER0);
+               set_buffer_uptodate(bh);
+               mark_buffer_dirty(bh);
  
- static inline int security_file_mmap (struct file *file, unsigned long reqprot,
-                                     unsigned long prot,
--                                    unsigned long flags)
-+                                    unsigned long flags,
-+                                    unsigned long addr,
-+                                    unsigned long addr_only)
- {
-       return 0;
+@@ -779,240 +783,217 @@
+       return ret;
  }
-diff -Nurb linux-2.6.22-570/include/linux/serial_8250.h linux-2.6.22-590/include/linux/serial_8250.h
---- linux-2.6.22-570/include/linux/serial_8250.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/serial_8250.h       2008-01-02 13:56:37.000000000 -0500
-@@ -57,6 +57,7 @@
- int serial8250_register_port(struct uart_port *);
- void serial8250_unregister_port(int line);
-+void serial8250_unregister_by_port(struct uart_port *port);
- void serial8250_suspend_port(int line);
- void serial8250_resume_port(int line);
  
-diff -Nurb linux-2.6.22-570/include/linux/signal.h linux-2.6.22-590/include/linux/signal.h
---- linux-2.6.22-570/include/linux/signal.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/signal.h    2008-01-02 13:56:37.000000000 -0500
-@@ -238,12 +238,15 @@
- extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
- extern long do_sigpending(void __user *, unsigned long);
- extern int sigprocmask(int, sigset_t *, sigset_t *);
-+extern int show_unhandled_signals;
+-#if (PAGE_CACHE_SIZE >= OCFS2_MAX_CLUSTERSIZE)
+-#define OCFS2_MAX_CTXT_PAGES  1
+-#else
+-#define OCFS2_MAX_CTXT_PAGES  (OCFS2_MAX_CLUSTERSIZE / PAGE_CACHE_SIZE)
+-#endif
+-
+-#define OCFS2_MAX_CLUSTERS_PER_PAGE   (PAGE_CACHE_SIZE / OCFS2_MIN_CLUSTERSIZE)
+-
+ /*
+- * Describe the state of a single cluster to be written to.
+- */
+-struct ocfs2_write_cluster_desc {
+-      u32             c_cpos;
+-      u32             c_phys;
+-      /*
+-       * Give this a unique field because c_phys eventually gets
+-       * filled.
+-       */
+-      unsigned        c_new;
+-      unsigned        c_unwritten;
+-};
+-
+-static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d)
+-{
+-      return d->c_new || d->c_unwritten;
+-}
+-
+-struct ocfs2_write_ctxt {
+-      /* Logical cluster position / len of write */
+-      u32                             w_cpos;
+-      u32                             w_clen;
+-
+-      struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE];
+-
+-              /*
+-       * This is true if page_size > cluster_size.
++ * This will copy user data from the buffer page in the splice
++ * context.
+        *
+-       * It triggers a set of special cases during write which might
+-       * have to deal with allocating writes to partial pages.
++ * For now, we ignore SPLICE_F_MOVE as that would require some extra
++ * communication out all the way to ocfs2_write().
+        */
+-      unsigned int                    w_large_pages;
++int ocfs2_map_and_write_splice_data(struct inode *inode,
++                                struct ocfs2_write_ctxt *wc, u64 *p_blkno,
++                                unsigned int *ret_from, unsigned int *ret_to)
++{
++      int ret;
++      unsigned int to, from, cluster_start, cluster_end;
++      char *src, *dst;
++      struct ocfs2_splice_write_priv *sp = wc->w_private;
++      struct pipe_buffer *buf = sp->s_buf;
++      unsigned long bytes, src_from;
++      struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
  
- struct pt_regs;
- extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
+-      /*
+-       * Pages involved in this write.
+-       *
+-       * w_target_page is the page being written to by the user.
+-       *
+-       * w_pages is an array of pages which always contains
+-       * w_target_page, and in the case of an allocating write with
+-       * page_size < cluster size, it will contain zero'd and mapped
+-       * pages adjacent to w_target_page which need to be written
+-       * out in so that future reads from that region will get
+-       * zero's.
+-       */
+-      struct page                     *w_pages[OCFS2_MAX_CTXT_PAGES];
+-      unsigned int                    w_num_pages;
+-      struct page                     *w_target_page;
++      ocfs2_figure_cluster_boundaries(osb, wc->w_cpos, &cluster_start,
++                                      &cluster_end);
  
- extern struct kmem_cache *sighand_cachep;
+-      /*
+-       * ocfs2_write_end() uses this to know what the real range to
+-       * write in the target should be.
+-       */
+-      unsigned int                    w_target_from;
+-      unsigned int                    w_target_to;
++      from = sp->s_offset;
++      src_from = sp->s_buf_offset;
++      bytes = wc->w_count;
  
-+int unhandled_signal(struct task_struct *tsk, int sig);
++      if (wc->w_large_pages) {
+       /*
+-       * We could use journal_current_handle() but this is cleaner,
+-       * IMHO -Mark
+-       */
+-      handle_t                        *w_handle;
+-
+-      struct buffer_head              *w_di_bh;
+-
+-      struct ocfs2_cached_dealloc_ctxt w_dealloc;
+-};
+-
+-static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
+-{
+-      int i;
+-
+-      for(i = 0; i < wc->w_num_pages; i++) {
+-              if (wc->w_pages[i] == NULL)
+-                      continue;
+-
+-              unlock_page(wc->w_pages[i]);
+-              mark_page_accessed(wc->w_pages[i]);
+-              page_cache_release(wc->w_pages[i]);
++               * For cluster size < page size, we have to
++               * calculate pos within the cluster and obey
++               * the rightmost boundary.
++               */
++              bytes = min(bytes, (unsigned long)(osb->s_clustersize
++                                 - (wc->w_pos & (osb->s_clustersize - 1))));
++      }
++      to = from + bytes;
 +
- /*
-  * In POSIX a signal is sent either to a specific thread (Linux task)
-  * or to the process as a whole (Linux thread group).  How the signal
-diff -Nurb linux-2.6.22-570/include/linux/skbuff.h linux-2.6.22-590/include/linux/skbuff.h
---- linux-2.6.22-570/include/linux/skbuff.h    2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/include/linux/skbuff.h    2008-01-02 13:56:37.000000000 -0500
-@@ -147,8 +147,8 @@
++      BUG_ON(from > PAGE_CACHE_SIZE);
++      BUG_ON(to > PAGE_CACHE_SIZE);
++      BUG_ON(from < cluster_start);
++      BUG_ON(to > cluster_end);
++
++      if (wc->w_this_page_new)
++              ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
++                                          cluster_start, cluster_end, 1);
++      else
++              ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
++                                          from, to, 0);
++      if (ret) {
++              mlog_errno(ret);
++              goto out;
+       }
  
- /* We divide dataref into two halves.  The higher 16 bits hold references
-  * to the payload part of skb->data.  The lower 16 bits hold references to
-- * the entire skb->data.  It is up to the users of the skb to agree on
-- * where the payload starts.
-+ * the entire skb->data.  A clone of a headerless skb holds the length of
-+ * the header in skb->hdr_len.
-  *
-  * All users must obey the rule that the skb->data reference count must be
-  * greater than or equal to the payload reference count.
-@@ -206,6 +206,7 @@
-  *    @len: Length of actual data
-  *    @data_len: Data length
-  *    @mac_len: Length of link layer header
-+ *    @hdr_len: writable header length of cloned skb
-  *    @csum: Checksum (must include start/offset pair)
-  *    @csum_start: Offset from skb->head where checksumming should start
-  *    @csum_offset: Offset from csum_start where checksum should be stored
-@@ -260,8 +261,9 @@
-       char                    cb[48];
+-      brelse(wc->w_di_bh);
+-      kfree(wc);
+-}
+-
+-static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
+-                                struct ocfs2_super *osb, loff_t pos,
+-                                unsigned len, struct buffer_head *di_bh)
+-{
+-      struct ocfs2_write_ctxt *wc;
+-
+-      wc = kzalloc(sizeof(struct ocfs2_write_ctxt), GFP_NOFS);
+-      if (!wc)
+-              return -ENOMEM;
+-
+-      wc->w_cpos = pos >> osb->s_clustersize_bits;
+-      wc->w_clen = ocfs2_clusters_for_bytes(osb->sb, len);
+-      get_bh(di_bh);
+-      wc->w_di_bh = di_bh;
+-
+-      if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
+-              wc->w_large_pages = 1;
+-      else
+-              wc->w_large_pages = 0;
++      src = buf->ops->map(sp->s_pipe, buf, 1);
++      dst = kmap_atomic(wc->w_this_page, KM_USER1);
++      memcpy(dst + from, src + src_from, bytes);
++      kunmap_atomic(wc->w_this_page, KM_USER1);
++      buf->ops->unmap(sp->s_pipe, buf, src);
+-      ocfs2_init_dealloc_ctxt(&wc->w_dealloc);
++      wc->w_finished_copy = 1;
+-      *wcp = wc;
++      *ret_from = from;
++      *ret_to = to;
++out:
  
-       unsigned int            len,
--                              data_len,
--                              mac_len;
-+                              data_len;
-+      __u16                   mac_len,
-+                              hdr_len;
-       union {
-               __wsum          csum;
-               struct {
-@@ -1323,6 +1325,20 @@
+-      return 0;
++      return bytes ? (unsigned int)bytes : ret;
  }
  
- /**
-+ *    skb_clone_writable - is the header of a clone writable
-+ *    @skb: buffer to check
-+ *    @len: length up to which to write
-+ *
-+ *    Returns true if modifying the header part of the cloned buffer
-+ *    does not requires the data to be copied.
-+ */
-+static inline int skb_clone_writable(struct sk_buff *skb, int len)
-+{
-+      return !skb_header_cloned(skb) &&
-+             skb_headroom(skb) + len <= skb->hdr_len;
-+}
-+
-+/**
-  *    skb_cow - copy header of skb when it is required
-  *    @skb: buffer to cow
-  *    @headroom: needed headroom
-diff -Nurb linux-2.6.22-570/include/linux/slab.h linux-2.6.22-590/include/linux/slab.h
---- linux-2.6.22-570/include/linux/slab.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/slab.h      2008-01-02 13:56:37.000000000 -0500
-@@ -26,12 +26,14 @@
- #define SLAB_HWCACHE_ALIGN    0x00002000UL    /* Align objs on cache lines */
- #define SLAB_CACHE_DMA                0x00004000UL    /* Use GFP_DMA memory */
- #define SLAB_STORE_USER               0x00010000UL    /* DEBUG: Store the last owner for bug hunting */
--#define SLAB_RECLAIM_ACCOUNT  0x00020000UL    /* Objects are reclaimable */
- #define SLAB_PANIC            0x00040000UL    /* Panic if kmem_cache_create() fails */
- #define SLAB_DESTROY_BY_RCU   0x00080000UL    /* Defer freeing slabs to RCU */
- #define SLAB_MEM_SPREAD               0x00100000UL    /* Spread some memory over cpuset */
- #define SLAB_TRACE            0x00200000UL    /* Trace allocations and frees */
-+/* The following flags affect the page allocator grouping pages by mobility */
-+#define SLAB_RECLAIM_ACCOUNT  0x00020000UL            /* Objects are reclaimable */
-+#define SLAB_TEMPORARY                SLAB_RECLAIM_ACCOUNT    /* Objects are short-lived */
  /*
-  * struct kmem_cache related prototypes
+- * If a page has any new buffers, zero them out here, and mark them uptodate
+- * and dirty so they'll be written out (in order to prevent uninitialised
+- * block data from leaking). And clear the new bit.
++ * This will copy user data from the iovec in the buffered write
++ * context.
   */
-diff -Nurb linux-2.6.22-570/include/linux/socket.h linux-2.6.22-590/include/linux/socket.h
---- linux-2.6.22-570/include/linux/socket.h    2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/include/linux/socket.h    2008-01-02 13:56:37.000000000 -0500
-@@ -24,7 +24,6 @@
- #include <linux/types.h>              /* pid_t                        */
- #include <linux/compiler.h>           /* __user                       */
+-static void ocfs2_zero_new_buffers(struct page *page, unsigned from, unsigned to)
++int ocfs2_map_and_write_user_data(struct inode *inode,
++                                struct ocfs2_write_ctxt *wc, u64 *p_blkno,
++                                unsigned int *ret_from, unsigned int *ret_to)
+ {
+-      unsigned int block_start, block_end;
+-      struct buffer_head *head, *bh;
+-
+-      BUG_ON(!PageLocked(page));
+-      if (!page_has_buffers(page))
+-              return;
+-
+-      bh = head = page_buffers(page);
+-      block_start = 0;
+-      do {
+-              block_end = block_start + bh->b_size;
+-
+-              if (buffer_new(bh)) {
+-                      if (block_end > from && block_start < to) {
+-                              if (!PageUptodate(page)) {
+-                                      unsigned start, end;
++      int ret;
++      unsigned int to, from, cluster_start, cluster_end;
++      unsigned long bytes, src_from;
++      char *dst;
++      struct ocfs2_buffered_write_priv *bp = wc->w_private;
++      const struct iovec *cur_iov = bp->b_cur_iov;
++      char __user *buf;
++      struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
  
--extern int sysctl_somaxconn;
- #ifdef CONFIG_PROC_FS
- struct seq_file;
- extern void socket_seq_show(struct seq_file *seq);
-diff -Nurb linux-2.6.22-570/include/linux/string.h linux-2.6.22-590/include/linux/string.h
---- linux-2.6.22-570/include/linux/string.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/string.h    2008-01-02 13:56:37.000000000 -0500
-@@ -105,8 +105,12 @@
- #endif
+-                                      start = max(from, block_start);
+-                                      end = min(to, block_end);
++      ocfs2_figure_cluster_boundaries(osb, wc->w_cpos, &cluster_start,
++                                      &cluster_end);
  
- extern char *kstrdup(const char *s, gfp_t gfp);
-+extern char *kstrndup(const char *s, size_t len, gfp_t gfp);
- extern void *kmemdup(const void *src, size_t len, gfp_t gfp);
+-                                      zero_user_page(page, start, end - start, KM_USER0);
+-                                      set_buffer_uptodate(bh);
+-                              }
++      buf = cur_iov->iov_base + bp->b_cur_off;
++      src_from = (unsigned long)buf & ~PAGE_CACHE_MASK;
+-                              clear_buffer_new(bh);
+-                              mark_buffer_dirty(bh);
+-                      }
+-      }
++      from = wc->w_pos & (PAGE_CACHE_SIZE - 1);
  
-+extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
-+extern void argv_free(char **argv);
+-              block_start = block_end;
+-              bh = bh->b_this_page;
+-      } while (bh != head);
+-}
+-
+-/*
+- * Only called when we have a failure during allocating write to write
+- * zero's to the newly allocated region.
++      /*
++       * This is a lot of comparisons, but it reads quite
++       * easily, which is important here.
++       */
++      /* Stay within the src page */
++      bytes = PAGE_SIZE - src_from;
++      /* Stay within the vector */
++      bytes = min(bytes,
++                  (unsigned long)(cur_iov->iov_len - bp->b_cur_off));
++      /* Stay within count */
++      bytes = min(bytes, (unsigned long)wc->w_count);
++      /*
++       * For clustersize > page size, just stay within
++       * target page, otherwise we have to calculate pos
++       * within the cluster and obey the rightmost
++       * boundary.
+        */
+-static void ocfs2_write_failure(struct inode *inode,
+-                              struct ocfs2_write_ctxt *wc,
+-                              loff_t user_pos, unsigned user_len)
+-{
+-      int i;
+-      unsigned from, to;
+-      struct page *tmppage;
+-
+-      ocfs2_zero_new_buffers(wc->w_target_page, user_pos, user_len);
+-
+       if (wc->w_large_pages) {
+-              from = wc->w_target_from;
+-              to = wc->w_target_to;
++              /*
++               * For cluster size < page size, we have to
++               * calculate pos within the cluster and obey
++               * the rightmost boundary.
++               */
++              bytes = min(bytes, (unsigned long)(osb->s_clustersize
++                                 - (wc->w_pos & (osb->s_clustersize - 1))));
+       } else {
+-              from = 0;
+-              to = PAGE_CACHE_SIZE;
++              /*
++               * cluster size > page size is the most common
++               * case - we just stay within the target page
++               * boundary.
++               */
++              bytes = min(bytes, PAGE_CACHE_SIZE - from);
+       }
+-      for(i = 0; i < wc->w_num_pages; i++) {
+-              tmppage = wc->w_pages[i];
++      to = from + bytes;
+-              if (ocfs2_should_order_data(inode))
+-                      walk_page_buffers(wc->w_handle, page_buffers(tmppage),
+-                                        from, to, NULL,
+-                                        ocfs2_journal_dirty_data);
++      BUG_ON(from > PAGE_CACHE_SIZE);
++      BUG_ON(to > PAGE_CACHE_SIZE);
++      BUG_ON(from < cluster_start);
++      BUG_ON(to > cluster_end);
+-              block_commit_write(tmppage, from, to);
++      if (wc->w_this_page_new)
++              ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
++                                          cluster_start, cluster_end, 1);
++      else
++              ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
++                                          from, to, 0);
++      if (ret) {
++              mlog_errno(ret);
++              goto out;
+       }
 +
- #ifdef __cplusplus
++      dst = kmap(wc->w_this_page);
++      memcpy(dst + from, bp->b_src_buf + src_from, bytes);
++      kunmap(wc->w_this_page);
++
++      /*
++       * XXX: This is slow, but simple. The caller of
++       * ocfs2_buffered_write_cluster() is responsible for
++       * passing through the iovecs, so it's difficult to
++       * predict what our next step is in here after our
++       * initial write. A future version should be pushing
++       * that iovec manipulation further down.
++       *
++       * By setting this, we indicate that a copy from user
++       * data was done, and subsequent calls for this
++       * cluster will skip copying more data.
++       */
++      wc->w_finished_copy = 1;
++
++      *ret_from = from;
++      *ret_to = to;
++out:
++
++      return bytes ? (unsigned int)bytes : ret;
  }
- #endif
-diff -Nurb linux-2.6.22-570/include/linux/sunrpc/auth.h linux-2.6.22-590/include/linux/sunrpc/auth.h
---- linux-2.6.22-570/include/linux/sunrpc/auth.h       2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/sunrpc/auth.h       2008-01-02 13:56:37.000000000 -0500
-@@ -16,6 +16,7 @@
- #include <linux/sunrpc/xdr.h>
  
- #include <asm/atomic.h>
-+#include <linux/rcupdate.h>
+-static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno,
+-                                      struct ocfs2_write_ctxt *wc,
+-                                      struct page *page, u32 cpos,
+-                                      loff_t user_pos, unsigned user_len,
+-                                      int new)
++/*
++ * Map, fill and write a page to disk.
++ *
++ * The work of copying data is done via callback.  Newly allocated
++ * pages which don't take user data will be zero'd (set 'new' to
++ * indicate an allocating write)
++ *
++ * Returns a negative error code or the number of bytes copied into
++ * the page.
++ */
++static int ocfs2_write_data_page(struct inode *inode, handle_t *handle,
++                               u64 *p_blkno, struct page *page,
++                               struct ocfs2_write_ctxt *wc, int new)
+ {
+-      int ret;
+-      unsigned int map_from = 0, map_to = 0;
++      int ret, copied = 0;
++      unsigned int from = 0, to = 0;
+       unsigned int cluster_start, cluster_end;
+-      unsigned int user_data_from = 0, user_data_to = 0;
++      unsigned int zero_from = 0, zero_to = 0;
  
- /* size of the nodename buffer */
- #define UNX_MAXNODENAME       32
-@@ -31,22 +32,28 @@
- /*
-  * Client user credentials
-  */
-+struct rpc_auth;
-+struct rpc_credops;
- struct rpc_cred {
-       struct hlist_node       cr_hash;        /* hash chain */
--      struct rpc_credops *    cr_ops;
--      unsigned long           cr_expire;      /* when to gc */
--      atomic_t                cr_count;       /* ref count */
--      unsigned short          cr_flags;       /* various flags */
-+      struct list_head        cr_lru;         /* lru garbage collection */
-+      struct rcu_head         cr_rcu;
-+      struct rpc_auth *       cr_auth;
-+      const struct rpc_credops *cr_ops;
- #ifdef RPC_DEBUG
-       unsigned long           cr_magic;       /* 0x0f4aa4f0 */
- #endif
-+      unsigned long           cr_expire;      /* when to gc */
-+      unsigned long           cr_flags;       /* various flags */
-+      atomic_t                cr_count;       /* ref count */
+-      ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos,
++      ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), wc->w_cpos,
+                                       &cluster_start, &cluster_end);
  
-       uid_t                   cr_uid;
+-      if (page == wc->w_target_page) {
+-              map_from = user_pos & (PAGE_CACHE_SIZE - 1);
+-              map_to = map_from + user_len;
++      if ((wc->w_pos >> PAGE_CACHE_SHIFT) == page->index
++          && !wc->w_finished_copy) {
  
-       /* per-flavor data */
- };
--#define RPCAUTH_CRED_NEW      0x0001
--#define RPCAUTH_CRED_UPTODATE 0x0002
-+#define RPCAUTH_CRED_NEW      0
-+#define RPCAUTH_CRED_UPTODATE 1
-+#define RPCAUTH_CRED_HASHED   2
+-              if (new)
+-                      ret = ocfs2_map_page_blocks(page, p_blkno, inode,
+-                                                  cluster_start, cluster_end,
+-                                                  new);
+-              else
+-                      ret = ocfs2_map_page_blocks(page, p_blkno, inode,
+-                                                  map_from, map_to, new);
+-              if (ret) {
++              wc->w_this_page = page;
++              wc->w_this_page_new = new;
++              ret = wc->w_write_data_page(inode, wc, p_blkno, &from, &to);
++              if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out;
+               }
  
- #define RPCAUTH_CRED_MAGIC    0x0f4aa4f0
+-              user_data_from = map_from;
+-              user_data_to = map_to;
++              copied = ret;
++
++              zero_from = from;
++              zero_to = to;
+               if (new) {
+-                      map_from = cluster_start;
+-                      map_to = cluster_end;
++                      from = cluster_start;
++                      to = cluster_end;
+               }
+-
+-              wc->w_target_from = map_from;
+-              wc->w_target_to = map_to;
+       } else {
+               /*
+                * If we haven't allocated the new page yet, we
+@@ -1021,11 +1002,11 @@
+                */
+               BUG_ON(!new);
  
-@@ -57,10 +64,10 @@
- #define RPC_CREDCACHE_MASK    (RPC_CREDCACHE_NR - 1)
- struct rpc_cred_cache {
-       struct hlist_head       hashtable[RPC_CREDCACHE_NR];
--      unsigned long           nextgc;         /* next garbage collection */
--      unsigned long           expire;         /* cache expiry interval */
-+      spinlock_t              lock;
- };
+-              map_from = cluster_start;
+-              map_to = cluster_end;
++              from = cluster_start;
++              to = cluster_end;
  
-+struct rpc_authops;
- struct rpc_auth {
-       unsigned int            au_cslack;      /* call cred size estimate */
-                               /* guess at number of u32's auth adds before
-@@ -70,7 +77,7 @@
-       unsigned int            au_verfsize;
+               ret = ocfs2_map_page_blocks(page, p_blkno, inode,
+-                                          cluster_start, cluster_end, new);
++                                          cluster_start, cluster_end, 1);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+@@ -1044,113 +1025,108 @@
+        */
+       if (new && !PageUptodate(page))
+               ocfs2_clear_page_regions(page, OCFS2_SB(inode->i_sb),
+-                                       cpos, user_data_from, user_data_to);
++                                       wc->w_cpos, zero_from, zero_to);
  
-       unsigned int            au_flags;       /* various flags */
--      struct rpc_authops *    au_ops;         /* operations */
-+      const struct rpc_authops *au_ops;               /* operations */
-       rpc_authflavor_t        au_flavor;      /* pseudoflavor (note may
-                                                * differ from the flavor in
-                                                * au_ops->au_flavor in gss
-@@ -116,17 +123,19 @@
-                                               void *, __be32 *, void *);
- };
+       flush_dcache_page(page);
  
--extern struct rpc_authops     authunix_ops;
--extern struct rpc_authops     authnull_ops;
--#ifdef CONFIG_SUNRPC_SECURE
--extern struct rpc_authops     authdes_ops;
--#endif
-+extern const struct rpc_authops       authunix_ops;
-+extern const struct rpc_authops       authnull_ops;
++      if (ocfs2_should_order_data(inode)) {
++              ret = walk_page_buffers(handle,
++                                      page_buffers(page),
++                                      from, to, NULL,
++                                      ocfs2_journal_dirty_data);
++              if (ret < 0)
++                      mlog_errno(ret);
++      }
++
++      /*
++       * We don't use generic_commit_write() because we need to
++       * handle our own i_size update.
++       */
++      ret = block_commit_write(page, from, to);
++      if (ret)
++              mlog_errno(ret);
+ out:
+-      return ret;
 +
-+void __init           rpc_init_authunix(void);
-+void __init           rpcauth_init_module(void);
-+void __exit           rpcauth_remove_module(void);
++      return copied ? copied : ret;
+ }
  
--int                   rpcauth_register(struct rpc_authops *);
--int                   rpcauth_unregister(struct rpc_authops *);
-+int                   rpcauth_register(const struct rpc_authops *);
-+int                   rpcauth_unregister(const struct rpc_authops *);
- struct rpc_auth *     rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
--void                  rpcauth_destroy(struct rpc_auth *);
-+void                  rpcauth_release(struct rpc_auth *);
- struct rpc_cred *     rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
-+void                  rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
- struct rpc_cred *     rpcauth_lookupcred(struct rpc_auth *, int);
- struct rpc_cred *     rpcauth_bindcred(struct rpc_task *);
- void                  rpcauth_holdcred(struct rpc_task *);
-@@ -139,8 +148,9 @@
- int                   rpcauth_refreshcred(struct rpc_task *);
- void                  rpcauth_invalcred(struct rpc_task *);
- int                   rpcauth_uptodatecred(struct rpc_task *);
--int                   rpcauth_init_credcache(struct rpc_auth *, unsigned long);
--void                  rpcauth_free_credcache(struct rpc_auth *);
-+int                   rpcauth_init_credcache(struct rpc_auth *);
-+void                  rpcauth_destroy_credcache(struct rpc_auth *);
-+void                  rpcauth_clear_credcache(struct rpc_cred_cache *);
+ /*
+- * This function will only grab one clusters worth of pages.
++ * Do the actual write of some data into an inode. Optionally allocate
++ * in order to fulfill the write.
++ *
++ * cpos is the logical cluster offset within the file to write at
++ *
++ * 'phys' is the physical mapping of that offset. a 'phys' value of
++ * zero indicates that allocation is required. In this case, data_ac
++ * and meta_ac should be valid (meta_ac can be null if metadata
++ * allocation isn't required).
+  */
+-static int ocfs2_grab_pages_for_write(struct address_space *mapping,
+-                                    struct ocfs2_write_ctxt *wc,
+-                                    u32 cpos, loff_t user_pos, int new,
+-                                    struct page *mmap_page)
++static ssize_t ocfs2_write(struct file *file, u32 phys, handle_t *handle,
++                         struct buffer_head *di_bh,
++                         struct ocfs2_alloc_context *data_ac,
++                         struct ocfs2_alloc_context *meta_ac,
++                         struct ocfs2_write_ctxt *wc)
+ {
+-      int ret = 0, i;
+-      unsigned long start, target_index, index;
++      int ret, i, numpages = 1, new;
++      unsigned int copied = 0;
++      u32 tmp_pos;
++      u64 v_blkno, p_blkno;
++      struct address_space *mapping = file->f_mapping;
+       struct inode *inode = mapping->host;
++      unsigned long index, start;
++      struct page **cpages;
  
- static inline
- struct rpc_cred *     get_rpccred(struct rpc_cred *cred)
-diff -Nurb linux-2.6.22-570/include/linux/sunrpc/auth_gss.h linux-2.6.22-590/include/linux/sunrpc/auth_gss.h
---- linux-2.6.22-570/include/linux/sunrpc/auth_gss.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/sunrpc/auth_gss.h   2008-01-02 13:56:37.000000000 -0500
-@@ -85,11 +85,6 @@
-       struct gss_upcall_msg   *gc_upcall;
- };
+-      target_index = user_pos >> PAGE_CACHE_SHIFT;
++      new = phys == 0 ? 1 : 0;
  
--#define gc_uid                        gc_base.cr_uid
--#define gc_count              gc_base.cr_count
--#define gc_flags              gc_base.cr_flags
--#define gc_expire             gc_base.cr_expire
+       /*
+        * Figure out how many pages we'll be manipulating here. For
+        * non allocating write, we just change the one
+        * page. Otherwise, we'll need a whole clusters worth.
+        */
+-      if (new) {
+-              wc->w_num_pages = ocfs2_pages_per_cluster(inode->i_sb);
+-              start = ocfs2_align_clusters_to_page_index(inode->i_sb, cpos);
+-      } else {
+-              wc->w_num_pages = 1;
+-              start = target_index;
+-      }
 -
- #endif /* __KERNEL__ */
- #endif /* _LINUX_SUNRPC_AUTH_GSS_H */
+-      for(i = 0; i < wc->w_num_pages; i++) {
+-              index = start + i;
++      if (new)
++              numpages = ocfs2_pages_per_cluster(inode->i_sb);
  
-diff -Nurb linux-2.6.22-570/include/linux/sunrpc/clnt.h linux-2.6.22-590/include/linux/sunrpc/clnt.h
---- linux-2.6.22-570/include/linux/sunrpc/clnt.h       2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/sunrpc/clnt.h       2008-01-02 13:56:37.000000000 -0500
-@@ -24,8 +24,10 @@
-  * The high-level client handle
-  */
- struct rpc_clnt {
--      atomic_t                cl_count;       /* Number of clones */
--      atomic_t                cl_users;       /* number of references */
-+      struct kref             cl_kref;        /* Number of references */
-+      struct list_head        cl_clients;     /* Global list of clients */
-+      struct list_head        cl_tasks;       /* List of tasks */
-+      spinlock_t              cl_lock;        /* spinlock */
-       struct rpc_xprt *       cl_xprt;        /* transport */
-       struct rpc_procinfo *   cl_procinfo;    /* procedure info */
-       u32                     cl_prog,        /* RPC program number */
-@@ -41,10 +43,7 @@
-       unsigned int            cl_softrtry : 1,/* soft timeouts */
-                               cl_intr     : 1,/* interruptible */
-                               cl_discrtry : 1,/* disconnect before retry */
--                              cl_autobind : 1,/* use getport() */
--                              cl_oneshot  : 1,/* dispose after use */
--                              cl_dead     : 1,/* abandoned */
--                              cl_tag      : 1;/* context tagging */
-+                              cl_autobind : 1;/* use getport() */
+-              if (index == target_index && mmap_page) {
+-                      /*
+-                       * ocfs2_pagemkwrite() is a little different
+-                       * and wants us to directly use the page
+-                       * passed in.
+-                       */
+-                      lock_page(mmap_page);
++      cpages = kzalloc(sizeof(*cpages) * numpages, GFP_NOFS);
++      if (!cpages) {
++              ret = -ENOMEM;
++              mlog_errno(ret);
++              return ret;
++      }
  
-       struct rpc_rtt *        cl_rtt;         /* RTO estimator data */
+-                      if (mmap_page->mapping != mapping) {
+-                              unlock_page(mmap_page);
+                               /*
+-                               * Sanity check - the locking in
+-                               * ocfs2_pagemkwrite() should ensure
+-                               * that this code doesn't trigger.
++       * Fill our page array first. That way we've grabbed enough so
++       * that we can zero and flush if we error after adding the
++       * extent.
+                                */
+-                              ret = -EINVAL;
+-                              mlog_errno(ret);
+-                              goto out;
++      if (new) {
++              start = ocfs2_align_clusters_to_page_index(inode->i_sb,
++                                                         wc->w_cpos);
++              v_blkno = ocfs2_clusters_to_blocks(inode->i_sb, wc->w_cpos);
++      } else {
++              start = wc->w_pos >> PAGE_CACHE_SHIFT;
++              v_blkno = wc->w_pos >> inode->i_sb->s_blocksize_bits;
+                       }
  
-@@ -111,17 +110,15 @@
- #define RPC_CLNT_CREATE_HARDRTRY      (1UL << 0)
- #define RPC_CLNT_CREATE_INTR          (1UL << 1)
- #define RPC_CLNT_CREATE_AUTOBIND      (1UL << 2)
--#define RPC_CLNT_CREATE_ONESHOT               (1UL << 3)
--#define RPC_CLNT_CREATE_NONPRIVPORT   (1UL << 4)
--#define RPC_CLNT_CREATE_NOPING                (1UL << 5)
--#define RPC_CLNT_CREATE_DISCRTRY      (1UL << 6)
-+#define RPC_CLNT_CREATE_NONPRIVPORT   (1UL << 3)
-+#define RPC_CLNT_CREATE_NOPING                (1UL << 4)
-+#define RPC_CLNT_CREATE_DISCRTRY      (1UL << 5)
+-                      page_cache_get(mmap_page);
+-                      wc->w_pages[i] = mmap_page;
+-              } else {
+-                      wc->w_pages[i] = find_or_create_page(mapping, index,
+-                                                           GFP_NOFS);
+-                      if (!wc->w_pages[i]) {
++      for(i = 0; i < numpages; i++) {
++              index = start + i;
++
++              cpages[i] = find_or_create_page(mapping, index, GFP_NOFS);
++              if (!cpages[i]) {
+                       ret = -ENOMEM;
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
  
- struct rpc_clnt *rpc_create(struct rpc_create_args *args);
- struct rpc_clnt       *rpc_bind_new_program(struct rpc_clnt *,
-                               struct rpc_program *, int);
- struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
--int           rpc_shutdown_client(struct rpc_clnt *);
--int           rpc_destroy_client(struct rpc_clnt *);
-+void          rpc_shutdown_client(struct rpc_clnt *);
- void          rpc_release_client(struct rpc_clnt *);
- int           rpcb_register(u32, u32, int, unsigned short, int *);
- void          rpcb_getport(struct rpc_task *);
-@@ -133,13 +130,14 @@
-                              void *calldata);
- int           rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
-                             int flags);
-+struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
-+                             int flags);
- void          rpc_restart_call(struct rpc_task *);
- void          rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
- void          rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
- void          rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
- size_t                rpc_max_payload(struct rpc_clnt *);
- void          rpc_force_rebind(struct rpc_clnt *);
--int           rpc_ping(struct rpc_clnt *clnt, int flags);
- size_t                rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);
- char *                rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t);
+-              if (index == target_index)
+-                      wc->w_target_page = wc->w_pages[i];
+-      }
+-out:
+-      return ret;
+-}
+-
+-/*
+- * Prepare a single cluster for write one cluster into the file.
+- */
+-static int ocfs2_write_cluster(struct address_space *mapping,
+-                             u32 phys, unsigned int unwritten,
+-                             struct ocfs2_alloc_context *data_ac,
+-                             struct ocfs2_alloc_context *meta_ac,
+-                             struct ocfs2_write_ctxt *wc, u32 cpos,
+-                             loff_t user_pos, unsigned user_len)
+-{
+-      int ret, i, new, should_zero = 0;
+-      u64 v_blkno, p_blkno;
+-      struct inode *inode = mapping->host;
+-
+-      new = phys == 0 ? 1 : 0;
+-      if (new || unwritten)
+-              should_zero = 1;
+-
+       if (new) {
+-              u32 tmp_pos;
+-
+               /*
+                * This is safe to call with the page locks - it won't take
+                * any additional semaphores or cluster locks.
+                */
+-              tmp_pos = cpos;
++              tmp_pos = wc->w_cpos;
+               ret = ocfs2_do_extend_allocation(OCFS2_SB(inode->i_sb), inode,
+-                                               &tmp_pos, 1, 0, wc->w_di_bh,
+-                                               wc->w_handle, data_ac,
+-                                               meta_ac, NULL);
++                                               &tmp_pos, 1, di_bh, handle,
++                                               data_ac, meta_ac, NULL);
+               /*
+                * This shouldn't happen because we must have already
+                * calculated the correct meta data allocation required. The
+@@ -1167,433 +1143,159 @@
+                       mlog_errno(ret);
+                       goto out;
+               }
+-      } else if (unwritten) {
+-              ret = ocfs2_mark_extent_written(inode, wc->w_di_bh,
+-                                              wc->w_handle, cpos, 1, phys,
+-                                              meta_ac, &wc->w_dealloc);
+-              if (ret < 0) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
+       }
  
-diff -Nurb linux-2.6.22-570/include/linux/sunrpc/gss_api.h linux-2.6.22-590/include/linux/sunrpc/gss_api.h
---- linux-2.6.22-570/include/linux/sunrpc/gss_api.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/sunrpc/gss_api.h    2008-01-02 13:56:37.000000000 -0500
-@@ -77,7 +77,7 @@
-       struct module           *gm_owner;
-       struct xdr_netobj       gm_oid;
-       char                    *gm_name;
--      struct gss_api_ops      *gm_ops;
-+      const struct gss_api_ops *gm_ops;
-       /* pseudoflavors supported by this mechanism: */
-       int                     gm_pf_num;
-       struct pf_desc *        gm_pfs;
-diff -Nurb linux-2.6.22-570/include/linux/sunrpc/rpc_pipe_fs.h linux-2.6.22-590/include/linux/sunrpc/rpc_pipe_fs.h
---- linux-2.6.22-570/include/linux/sunrpc/rpc_pipe_fs.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/sunrpc/rpc_pipe_fs.h        2008-01-02 13:56:37.000000000 -0500
-@@ -23,9 +23,11 @@
-       void *private;
-       struct list_head pipe;
-       struct list_head in_upcall;
-+      struct list_head in_downcall;
-       int pipelen;
-       int nreaders;
-       int nwriters;
-+      int nkern_readwriters;
-       wait_queue_head_t waitq;
- #define RPC_PIPE_WAIT_FOR_OPEN        1
-       int flags;
-diff -Nurb linux-2.6.22-570/include/linux/sunrpc/sched.h linux-2.6.22-590/include/linux/sunrpc/sched.h
---- linux-2.6.22-570/include/linux/sunrpc/sched.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/sunrpc/sched.h      2008-01-02 13:56:37.000000000 -0500
-@@ -110,11 +110,6 @@
-       if (!list_empty(head) &&  \
-           ((task=list_entry((head)->next, struct rpc_task, u.tk_wait.list)),1))
+-      if (should_zero)
+-              v_blkno = ocfs2_clusters_to_blocks(inode->i_sb, cpos);
+-      else
+-              v_blkno = user_pos >> inode->i_sb->s_blocksize_bits;
+-
+-      /*
+-       * The only reason this should fail is due to an inability to
+-       * find the extent added.
+-       */
+       ret = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, NULL,
+                                         NULL);
+       if (ret < 0) {
+-              ocfs2_error(inode->i_sb, "Corrupting extend for inode %llu, "
+-                          "at logical block %llu",
+-                          (unsigned long long)OCFS2_I(inode)->ip_blkno,
+-                          (unsigned long long)v_blkno);
+-              goto out;
+-      }
+-
+-      BUG_ON(p_blkno == 0);
+-
+-      for(i = 0; i < wc->w_num_pages; i++) {
+-              int tmpret;
+-
+-              tmpret = ocfs2_prepare_page_for_write(inode, &p_blkno, wc,
+-                                                    wc->w_pages[i], cpos,
+-                                                    user_pos, user_len,
+-                                                    should_zero);
+-              if (tmpret) {
+-                      mlog_errno(tmpret);
+-                      if (ret == 0)
+-                              tmpret = ret;
+-              }
+-      }
  
--/* .. and walking list of all tasks */
--#define       alltask_for_each(task, pos, head) \
--      list_for_each(pos, head) \
--              if ((task=list_entry(pos, struct rpc_task, tk_task)),1)
+               /*
+-       * We only have cleanup to do in case of allocating write.
++               * XXX: Should we go readonly here?
+                */
+-      if (ret && new)
+-              ocfs2_write_failure(inode, wc, user_pos, user_len);
 -
- typedef void                  (*rpc_action)(struct rpc_task *);
+-out:
+-
+-      return ret;
+-}
  
- struct rpc_call_ops {
-diff -Nurb linux-2.6.22-570/include/linux/syscalls.h linux-2.6.22-590/include/linux/syscalls.h
---- linux-2.6.22-570/include/linux/syscalls.h  2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/syscalls.h  2008-01-02 13:56:37.000000000 -0500
-@@ -110,6 +110,9 @@
- asmlinkage long sys_capset(cap_user_header_t header,
-                               const cap_user_data_t data);
- asmlinkage long sys_personality(u_long personality);
-+asmlinkage long sys_sync_file_range2(int fd, unsigned int flags,
-+                                   loff_t offset, loff_t nbytes);
-+
+-static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
+-                                     struct ocfs2_alloc_context *data_ac,
+-                                     struct ocfs2_alloc_context *meta_ac,
+-                                     struct ocfs2_write_ctxt *wc,
+-                                     loff_t pos, unsigned len)
+-{
+-      int ret, i;
+-      struct ocfs2_write_cluster_desc *desc;
++              mlog_errno(ret);
++              goto out;
++      }
  
- asmlinkage long sys_sigpending(old_sigset_t __user *set);
- asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set,
-@@ -612,7 +615,11 @@
- asmlinkage long sys_timerfd(int ufd, int clockid, int flags,
-                           const struct itimerspec __user *utmr);
- asmlinkage long sys_eventfd(unsigned int count);
-+asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len);
+-      for (i = 0; i < wc->w_clen; i++) {
+-              desc = &wc->w_desc[i];
++      BUG_ON(p_blkno == 0);
  
- int kernel_execve(const char *filename, char *const argv[], char *const envp[]);
+-              ret = ocfs2_write_cluster(mapping, desc->c_phys,
+-                                        desc->c_unwritten, data_ac, meta_ac,
+-                                        wc, desc->c_cpos, pos, len);
+-              if (ret) {
++      for(i = 0; i < numpages; i++) {
++              ret = ocfs2_write_data_page(inode, handle, &p_blkno, cpages[i],
++                                          wc, new);
++              if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out;
+               }
++
++              copied += ret;
+       }
  
-+asmlinkage long sys_revokeat(int dfd, const char __user *filename);
-+asmlinkage long sys_frevoke(unsigned int fd);
+-      ret = 0;
+ out:
+-      return ret;
++      for(i = 0; i < numpages; i++) {
++              unlock_page(cpages[i]);
++              mark_page_accessed(cpages[i]);
++              page_cache_release(cpages[i]);
++      }
++      kfree(cpages);
 +
- #endif
-diff -Nurb linux-2.6.22-570/include/linux/sysctl.h linux-2.6.22-590/include/linux/sysctl.h
---- linux-2.6.22-570/include/linux/sysctl.h    2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/include/linux/sysctl.h    2008-01-02 13:56:37.000000000 -0500
-@@ -31,6 +31,7 @@
++      return copied ? copied : ret;
+ }
  
- struct file;
- struct completion;
-+struct net;
+-/*
+- * ocfs2_write_end() wants to know which parts of the target page it
+- * should complete the write on. It's easiest to compute them ahead of
+- * time when a more complete view of the write is available.
+- */
+-static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
+-                                      struct ocfs2_write_ctxt *wc,
+-                                      loff_t pos, unsigned len, int alloc)
++static void ocfs2_write_ctxt_init(struct ocfs2_write_ctxt *wc,
++                                struct ocfs2_super *osb, loff_t pos,
++                                size_t count, ocfs2_page_writer *cb,
++                                void *cb_priv)
+ {
+-      struct ocfs2_write_cluster_desc *desc;
+-
+-      wc->w_target_from = pos & (PAGE_CACHE_SIZE - 1);
+-      wc->w_target_to = wc->w_target_from + len;
+-
+-      if (alloc == 0)
+-              return;
+-
+-      /*
+-       * Allocating write - we may have different boundaries based
+-       * on page size and cluster size.
+-       *
+-       * NOTE: We can no longer compute one value from the other as
+-       * the actual write length and user provided length may be
+-       * different.
+-       */
++      wc->w_count = count;
++      wc->w_pos = pos;
++      wc->w_cpos = wc->w_pos >> osb->s_clustersize_bits;
++      wc->w_finished_copy = 0;
  
- #define CTL_MAXNAME 10                /* how many path components do we allow in a
-                                  call to sysctl?   In other words, what is
-@@ -166,6 +167,7 @@
-       KERN_MAX_LOCK_DEPTH=74,
-       KERN_NMI_WATCHDOG=75, /* int: enable/disable nmi watchdog */
-       KERN_PANIC_ON_NMI=76, /* int: whether we will panic on an unrecovered */
-+      KERN_POWEROFF_CMD=77,   /* string: poweroff command line */
- };
+-      if (wc->w_large_pages) {
+-              /*
+-               * We only care about the 1st and last cluster within
+-               * our range and whether they should be zero'd or not. Either
+-               * value may be extended out to the start/end of a
+-               * newly allocated cluster.
+-               */
+-              desc = &wc->w_desc[0];
+-              if (ocfs2_should_zero_cluster(desc))
+-                      ocfs2_figure_cluster_boundaries(osb,
+-                                                      desc->c_cpos,
+-                                                      &wc->w_target_from,
+-                                                      NULL);
++      if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
++              wc->w_large_pages = 1;
++      else
++              wc->w_large_pages = 0;
  
+-              desc = &wc->w_desc[wc->w_clen - 1];
+-              if (ocfs2_should_zero_cluster(desc))
+-                      ocfs2_figure_cluster_boundaries(osb,
+-                                                      desc->c_cpos,
+-                                                      NULL,
+-                                                      &wc->w_target_to);
+-      } else {
+-              wc->w_target_from = 0;
+-              wc->w_target_to = PAGE_CACHE_SIZE;
+-      }
++      wc->w_write_data_page = cb;
++      wc->w_private = cb_priv;
+ }
  
-@@ -208,6 +210,7 @@
-       VM_PANIC_ON_OOM=33,     /* panic at out-of-memory */
-       VM_VDSO_ENABLED=34,     /* map VDSO into new processes? */
-       VM_MIN_SLAB=35,          /* Percent pages ignored by zone reclaim */
-+      VM_HUGETLB_TREAT_MOVABLE=36, /* Allocate hugepages from ZONE_MOVABLE */
+ /*
+- * Populate each single-cluster write descriptor in the write context
+- * with information about the i/o to be done.
++ * Write a cluster to an inode. The cluster may not be allocated yet,
++ * in which case it will be. This only exists for buffered writes -
++ * O_DIRECT takes a more "traditional" path through the kernel.
+  *
+- * Returns the number of clusters that will have to be allocated, as
+- * well as a worst case estimate of the number of extent records that
+- * would have to be created during a write to an unwritten region.
+- */
+-static int ocfs2_populate_write_desc(struct inode *inode,
+-                                   struct ocfs2_write_ctxt *wc,
+-                                   unsigned int *clusters_to_alloc,
+-                                   unsigned int *extents_to_split)
+-{
+-      int ret;
+-      struct ocfs2_write_cluster_desc *desc;
+-      unsigned int num_clusters = 0;
+-      unsigned int ext_flags = 0;
+-      u32 phys = 0;
+-      int i;
+-
+-      *clusters_to_alloc = 0;
+-      *extents_to_split = 0;
+-
+-      for (i = 0; i < wc->w_clen; i++) {
+-              desc = &wc->w_desc[i];
+-              desc->c_cpos = wc->w_cpos + i;
+-
+-              if (num_clusters == 0) {
+-                      /*
+-                       * Need to look up the next extent record.
+-                       */
+-                      ret = ocfs2_get_clusters(inode, desc->c_cpos, &phys,
+-                                               &num_clusters, &ext_flags);
+-                      if (ret) {
+-                              mlog_errno(ret);
+-                              goto out;
+-                      }
+-
+-                      /*
+-                       * Assume worst case - that we're writing in
+-                       * the middle of the extent.
++ * The caller is responsible for incrementing pos, written counts, etc
+  *
+-                       * We can assume that the write proceeds from
+-                       * left to right, in which case the extent
+-                       * insert code is smart enough to coalesce the
+-                       * next splits into the previous records created.
+- */
+-                      if (ext_flags & OCFS2_EXT_UNWRITTEN)
+-                              *extents_to_split = *extents_to_split + 2;
+-              } else if (phys) {
+-                      /*
+-                       * Only increment phys if it doesn't describe
+-                       * a hole.
++ * For file systems that don't support sparse files, pre-allocation
++ * and page zeroing up until cpos should be done prior to this
++ * function call.
++ *
++ * Callers should be holding i_sem, and the rw cluster lock.
++ *
++ * Returns the number of user bytes written, or less than zero for
++ * error.
+                        */
+-                      phys++;
+-              }
+-
+-              desc->c_phys = phys;
+-              if (phys == 0) {
+-                      desc->c_new = 1;
+-                      *clusters_to_alloc = *clusters_to_alloc + 1;
+-              }
+-              if (ext_flags & OCFS2_EXT_UNWRITTEN)
+-                      desc->c_unwritten = 1;
+-
+-              num_clusters--;
+-      }
+-
+-      ret = 0;
+-out:
+-      return ret;
+-}
+-
+-int ocfs2_write_begin_nolock(struct address_space *mapping,
+-                           loff_t pos, unsigned len, unsigned flags,
+-                           struct page **pagep, void **fsdata,
+-                           struct buffer_head *di_bh, struct page *mmap_page)
++ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
++                                   size_t count, ocfs2_page_writer *actor,
++                                   void *priv)
+ {
+       int ret, credits = OCFS2_INODE_UPDATE_CREDITS;
+-      unsigned int clusters_to_alloc, extents_to_split;
+-      struct ocfs2_write_ctxt *wc;
+-      struct inode *inode = mapping->host;
++      ssize_t written = 0;
++      u32 phys;
++      struct inode *inode = file->f_mapping->host;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
++      struct buffer_head *di_bh = NULL;
+       struct ocfs2_dinode *di;
+       struct ocfs2_alloc_context *data_ac = NULL;
+       struct ocfs2_alloc_context *meta_ac = NULL;
+       handle_t *handle;
++      struct ocfs2_write_ctxt wc;
  
-       /* s390 vm cmm sysctls */
-       VM_CMM_PAGES=1111,
-@@ -843,6 +846,9 @@
- };
+-      ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh);
+-      if (ret) {
+-              mlog_errno(ret);
+-              return ret;
+-      }
++      ocfs2_write_ctxt_init(&wc, osb, pos, count, actor, priv);
  
- /* CTL_DEBUG names: */
-+enum {
-+      DEBUG_UNHANDLED_SIGNALS = 1,
-+};
+-      ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc,
+-                                      &extents_to_split);
++      ret = ocfs2_meta_lock(inode, &di_bh, 1);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
++      di = (struct ocfs2_dinode *)di_bh->b_data;
  
- /* CTL_DEV names: */
- enum {
-@@ -980,6 +986,7 @@
-                              void __user *oldval, size_t __user *oldlenp,
-                              void __user *newval, size_t newlen);
+-      di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
+-
+-      /*
+-       * We set w_target_from, w_target_to here so that
+-       * ocfs2_write_end() knows which range in the target page to
+-       * write out. An allocation requires that we write the entire
+-       * cluster range.
+-       */
+-      if (clusters_to_alloc || extents_to_split) {
+               /*
+-               * XXX: We are stretching the limits of
+-               * ocfs2_lock_allocators(). It greatly over-estimates
+-               * the work to be done.
++       * Take alloc sem here to prevent concurrent lookups. That way
++       * the mapping, zeroing and tree manipulation within
++       * ocfs2_write() will be safe against ->readpage(). This
++       * should also serve to lock out allocation from a shared
++       * writeable region.
+                */
+-              ret = ocfs2_lock_allocators(inode, di, clusters_to_alloc,
+-                                          extents_to_split, &data_ac, &meta_ac);
+-      if (ret) {
+-              mlog_errno(ret);
+-                      goto out;
+-      }
+-
+-              credits = ocfs2_calc_extend_credits(inode->i_sb, di,
+-                                                  clusters_to_alloc);
+-
+-      }
+-
+-      ocfs2_set_target_boundaries(osb, wc, pos, len,
+-                                  clusters_to_alloc + extents_to_split);
++      down_write(&OCFS2_I(inode)->ip_alloc_sem);
  
-+extern ctl_handler sysctl_data;
- extern ctl_handler sysctl_string;
- extern ctl_handler sysctl_intvec;
- extern ctl_handler sysctl_jiffies;
-@@ -1056,6 +1063,12 @@
+-      handle = ocfs2_start_trans(osb, credits);
+-      if (IS_ERR(handle)) {
+-              ret = PTR_ERR(handle);
++      ret = ocfs2_get_clusters(inode, wc.w_cpos, &phys, NULL, NULL);
++      if (ret) {
+               mlog_errno(ret);
+-              goto out;
++              goto out_meta;
+       }
  
- void unregister_sysctl_table(struct ctl_table_header * table);
+-      wc->w_handle = handle;
+-
+-      /*
+-       * We don't want this to fail in ocfs2_write_end(), so do it
+-       * here.
+-       */
+-      ret = ocfs2_journal_access(handle, inode, wc->w_di_bh,
+-                                 OCFS2_JOURNAL_ACCESS_WRITE);
++      /* phys == 0 means that allocation is required. */
++      if (phys == 0) {
++              ret = ocfs2_lock_allocators(inode, di, 1, &data_ac, &meta_ac);
+               if (ret) {
+                       mlog_errno(ret);
+-              goto out_commit;
++                      goto out_meta;
+               }
  
-+#ifdef CONFIG_NET
-+extern struct ctl_table_header *register_net_sysctl_table(struct net *net, struct ctl_table *table);
-+extern void unregister_net_sysctl_table(struct ctl_table_header *header);
-+extern ctl_table net_root_table[];
-+#endif
-+
- #else /* __KERNEL__ */
+-      /*
+-       * Fill our page array first. That way we've grabbed enough so
+-       * that we can zero and flush if we error after adding the
+-       * extent.
+-       */
+-      ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos,
+-                                       clusters_to_alloc + extents_to_split,
+-                                       mmap_page);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out_commit;
++              credits = ocfs2_calc_extend_credits(inode->i_sb, di, 1);
+       }
  
- #endif /* __KERNEL__ */
-diff -Nurb linux-2.6.22-570/include/linux/sysdev.h linux-2.6.22-590/include/linux/sysdev.h
---- linux-2.6.22-570/include/linux/sysdev.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/sysdev.h    2008-01-02 13:56:37.000000000 -0500
-@@ -101,8 +101,7 @@
+-      ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos,
+-                                        len);
++      ret = ocfs2_data_lock(inode, 1);
+       if (ret) {
+               mlog_errno(ret);
+-              goto out_commit;
++              goto out_meta;
+       }
  
- #define _SYSDEV_ATTR(_name,_mode,_show,_store)                        \
- {                                                             \
--      .attr = { .name = __stringify(_name), .mode = _mode,    \
--               .owner = THIS_MODULE },                        \
-+      .attr = { .name = __stringify(_name), .mode = _mode },  \
-       .show   = _show,                                        \
-       .store  = _store,                                       \
- }
-diff -Nurb linux-2.6.22-570/include/linux/sysfs.h linux-2.6.22-590/include/linux/sysfs.h
---- linux-2.6.22-570/include/linux/sysfs.h     2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/sysfs.h     2008-01-02 13:56:37.000000000 -0500
-@@ -19,9 +19,11 @@
+-      if (data_ac)
+-              ocfs2_free_alloc_context(data_ac);
+-      if (meta_ac)
+-              ocfs2_free_alloc_context(meta_ac);
+-
+-      *pagep = wc->w_target_page;
+-      *fsdata = wc;
+-      return 0;
+-out_commit:
+-      ocfs2_commit_trans(osb, handle);
+-
+-out:
+-      ocfs2_free_write_ctxt(wc);
+-
+-      if (data_ac)
+-              ocfs2_free_alloc_context(data_ac);
+-      if (meta_ac)
+-              ocfs2_free_alloc_context(meta_ac);
+-      return ret;
+-}
+-
+-int ocfs2_write_begin(struct file *file, struct address_space *mapping,
+-                    loff_t pos, unsigned len, unsigned flags,
+-                    struct page **pagep, void **fsdata)
+-{
+-      int ret;
+-      struct buffer_head *di_bh = NULL;
+-      struct inode *inode = mapping->host;
+-
+-      ret = ocfs2_meta_lock(inode, &di_bh, 1);
+-      if (ret) {
++      handle = ocfs2_start_trans(osb, credits);
++      if (IS_ERR(handle)) {
++              ret = PTR_ERR(handle);
+               mlog_errno(ret);
+-              return ret;
++              goto out_data;
+       }
  
- struct kobject;
- struct module;
--struct nameidata;
--struct dentry;
+-      /*
+-       * Take alloc sem here to prevent concurrent lookups. That way
+-       * the mapping, zeroing and tree manipulation within
+-       * ocfs2_write() will be safe against ->readpage(). This
+-       * should also serve to lock out allocation from a shared
+-       * writeable region.
+-       */
+-      down_write(&OCFS2_I(inode)->ip_alloc_sem);
+-
+-      ret = ocfs2_data_lock(inode, 1);
+-      if (ret) {
++      written = ocfs2_write(file, phys, handle, di_bh, data_ac,
++                            meta_ac, &wc);
++      if (written < 0) {
++              ret = written;
+               mlog_errno(ret);
+-              goto out_fail;
++              goto out_commit;
+       }
  
-+/* FIXME
-+ * The *owner field is no longer used, but leave around
-+ * until the tree gets cleaned up fully.
-+ */
- struct attribute {
-       const char              * name;
-       struct module           * owner;
-@@ -41,13 +43,13 @@
-  */
+-      ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep,
+-                                     fsdata, di_bh, NULL);
++      ret = ocfs2_journal_access(handle, inode, di_bh,
++                                 OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+-              goto out_fail_data;
+-      }
+-
+-      brelse(di_bh);
+-
+-      return 0;
+-
+-out_fail_data:
+-      ocfs2_data_unlock(inode, 1);
+-out_fail:
+-      up_write(&OCFS2_I(inode)->ip_alloc_sem);
+-
+-      brelse(di_bh);
+-      ocfs2_meta_unlock(inode, 1);
+-
+-      return ret;
+-}
+-
+-int ocfs2_write_end_nolock(struct address_space *mapping,
+-                         loff_t pos, unsigned len, unsigned copied,
+-                         struct page *page, void *fsdata)
+-{
+-      int i;
+-      unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1);
+-      struct inode *inode = mapping->host;
+-      struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+-      struct ocfs2_write_ctxt *wc = fsdata;
+-      struct ocfs2_dinode *di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
+-      handle_t *handle = wc->w_handle;
+-      struct page *tmppage;
+-
+-      if (unlikely(copied < len)) {
+-              if (!PageUptodate(wc->w_target_page))
+-                      copied = 0;
+-
+-              ocfs2_zero_new_buffers(wc->w_target_page, start+copied,
+-                                     start+len);
+-      }
+-      flush_dcache_page(wc->w_target_page);
+-
+-      for(i = 0; i < wc->w_num_pages; i++) {
+-              tmppage = wc->w_pages[i];
+-
+-              if (tmppage == wc->w_target_page) {
+-                      from = wc->w_target_from;
+-                      to = wc->w_target_to;
+-
+-                      BUG_ON(from > PAGE_CACHE_SIZE ||
+-                             to > PAGE_CACHE_SIZE ||
+-                             to < from);
+-              } else {
+-                      /*
+-                       * Pages adjacent to the target (if any) imply
+-                       * a hole-filling write in which case we want
+-                       * to flush their entire range.
+-                       */
+-                      from = 0;
+-                      to = PAGE_CACHE_SIZE;
+-              }
+-
+-              if (ocfs2_should_order_data(inode))
+-                      walk_page_buffers(wc->w_handle, page_buffers(tmppage),
+-                                        from, to, NULL,
+-                                        ocfs2_journal_dirty_data);
+-
+-              block_commit_write(tmppage, from, to);
++              goto out_commit;
+       }
  
- #define __ATTR(_name,_mode,_show,_store) { \
--      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },     \
-+      .attr = {.name = __stringify(_name), .mode = _mode },   \
-       .show   = _show,                                        \
-       .store  = _store,                                       \
- }
+-      pos += copied;
++      pos += written;
+       if (pos > inode->i_size) {
+               i_size_write(inode, pos);
+               mark_inode_dirty(inode);
+@@ -1604,31 +1306,28 @@
+       di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
+       di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
  
- #define __ATTR_RO(_name) { \
--      .attr   = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE },   \
-+      .attr   = { .name = __stringify(_name), .mode = 0444 }, \
-       .show   = _name##_show, \
- }
+-      ocfs2_journal_dirty(handle, wc->w_di_bh);
++      ret = ocfs2_journal_dirty(handle, di_bh);
++      if (ret)
++              mlog_errno(ret);
  
-@@ -61,8 +63,10 @@
-       struct attribute        attr;
-       size_t                  size;
-       void                    *private;
--      ssize_t (*read)(struct kobject *, char *, loff_t, size_t);
--      ssize_t (*write)(struct kobject *, char *, loff_t, size_t);
-+      ssize_t (*read)(struct kobject *, struct bin_attribute *,
-+                      char *, loff_t, size_t);
-+      ssize_t (*write)(struct kobject *, struct bin_attribute *,
-+                       char *, loff_t, size_t);
-       int (*mmap)(struct kobject *, struct bin_attribute *attr,
-                   struct vm_area_struct *vma);
- };
-@@ -72,12 +76,23 @@
-       ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
- };
++out_commit:
+       ocfs2_commit_trans(osb, handle);
  
-+struct shadow_dir_operations {
-+      const void *(*current_tag)(void);
-+      const void *(*kobject_tag)(struct kobject *kobj);
-+};
-+
-+#define SYSFS_TYPE_MASK               0x00ff
- #define SYSFS_ROOT            0x0001
- #define SYSFS_DIR             0x0002
- #define SYSFS_KOBJ_ATTR       0x0004
- #define SYSFS_KOBJ_BIN_ATTR   0x0008
- #define SYSFS_KOBJ_LINK       0x0020
--#define SYSFS_NOT_PINNED      (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK)
-+#define SYSFS_SHADOW_DIR      0x0040
-+#define SYSFS_COPY_NAME               (SYSFS_DIR | SYSFS_KOBJ_LINK)
+-      ocfs2_run_deallocs(osb, &wc->w_dealloc);
+-
+-      ocfs2_free_write_ctxt(wc);
+-
+-      return copied;
+-}
+-
+-int ocfs2_write_end(struct file *file, struct address_space *mapping,
+-                  loff_t pos, unsigned len, unsigned copied,
+-                  struct page *page, void *fsdata)
+-{
+-      int ret;
+-      struct inode *inode = mapping->host;
+-
+-      ret = ocfs2_write_end_nolock(mapping, pos, len, copied, page, fsdata);
+-
++out_data:
+       ocfs2_data_unlock(inode, 1);
 +
-+#define SYSFS_FLAG_MASK               ~SYSFS_TYPE_MASK
-+#define SYSFS_FLAG_REMOVED    0x0100
-+#define SYSFS_FLAG_SHADOWED   0x0200
- #ifdef CONFIG_SYSFS
-@@ -85,13 +100,13 @@
-               void (*func)(void *), void *data, struct module *owner);
- extern int __must_check
--sysfs_create_dir(struct kobject *, struct dentry *);
-+sysfs_create_dir(struct kobject *);
- extern void
- sysfs_remove_dir(struct kobject *);
++out_meta:
+       up_write(&OCFS2_I(inode)->ip_alloc_sem);
+       ocfs2_meta_unlock(inode, 1);
  
- extern int __must_check
--sysfs_rename_dir(struct kobject *, struct dentry *, const char *new_name);
-+sysfs_rename_dir(struct kobject *kobj, const char *new_name);
+-      return ret;
++out:
++      brelse(di_bh);
++      if (data_ac)
++              ocfs2_free_alloc_context(data_ac);
++      if (meta_ac)
++              ocfs2_free_alloc_context(meta_ac);
++
++      return written ? written : ret;
+ }
  
- extern int __must_check
- sysfs_move_dir(struct kobject *, struct kobject *);
-@@ -114,6 +129,13 @@
- extern void
- sysfs_remove_link(struct kobject *, const char * name);
+ const struct address_space_operations ocfs2_aops = {
+diff -Nurb linux-2.6.22-590/fs/ocfs2/aops.h linux-2.6.22-570/fs/ocfs2/aops.h
+--- linux-2.6.22-590/fs/ocfs2/aops.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/aops.h   2007-07-08 19:32:17.000000000 -0400
+@@ -42,22 +42,57 @@
+                       int (*fn)(      handle_t *handle,
+                                       struct buffer_head *bh));
  
-+extern int
-+sysfs_rename_link(struct kobject *kobj, struct kobject *target,
-+                      const char *old_name, const char *new_name);
+-int ocfs2_write_begin(struct file *file, struct address_space *mapping,
+-                    loff_t pos, unsigned len, unsigned flags,
+-                    struct page **pagep, void **fsdata);
+-
+-int ocfs2_write_end(struct file *file, struct address_space *mapping,
+-                  loff_t pos, unsigned len, unsigned copied,
+-                  struct page *page, void *fsdata);
+-
+-int ocfs2_write_end_nolock(struct address_space *mapping,
+-                         loff_t pos, unsigned len, unsigned copied,
+-                         struct page *page, void *fsdata);
+-
+-int ocfs2_write_begin_nolock(struct address_space *mapping,
+-                           loff_t pos, unsigned len, unsigned flags,
+-                           struct page **pagep, void **fsdata,
+-                           struct buffer_head *di_bh, struct page *mmap_page);
++struct ocfs2_write_ctxt;
++typedef int (ocfs2_page_writer)(struct inode *, struct ocfs2_write_ctxt *,
++                              u64 *, unsigned int *, unsigned int *);
 +
-+extern void
-+sysfs_delete_link(struct kobject *dir, struct kobject *targ, const char *name);
++ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
++                                   size_t count, ocfs2_page_writer *actor,
++                                   void *priv);
 +
- int __must_check sysfs_create_bin_file(struct kobject *kobj,
-                                       struct bin_attribute *attr);
- void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr);
-@@ -128,11 +150,7 @@
++struct ocfs2_write_ctxt {
++      size_t                          w_count;
++      loff_t                          w_pos;
++      u32                             w_cpos;
++      unsigned int                    w_finished_copy;
++
++      /* This is true if page_size > cluster_size */
++      unsigned int                    w_large_pages;
++
++      /* Filler callback and private data */
++      ocfs2_page_writer               *w_write_data_page;
++      void                            *w_private;
++
++      /* Only valid for the filler callback */
++      struct page                     *w_this_page;
++      unsigned int                    w_this_page_new;
++};
++
++struct ocfs2_buffered_write_priv {
++      char                            *b_src_buf;
++      const struct iovec              *b_cur_iov; /* Current iovec */
++      size_t                          b_cur_off; /* Offset in the
++                                                  * current iovec */
++};
++int ocfs2_map_and_write_user_data(struct inode *inode,
++                                struct ocfs2_write_ctxt *wc,
++                                u64 *p_blkno,
++                                unsigned int *ret_from,
++                                unsigned int *ret_to);
++
++struct ocfs2_splice_write_priv {
++      struct splice_desc              *s_sd;
++      struct pipe_buffer              *s_buf;
++      struct pipe_inode_info          *s_pipe;
++      /* Neither offset value is ever larger than one page */
++      unsigned int                    s_offset;
++      unsigned int                    s_buf_offset;
++};
++int ocfs2_map_and_write_splice_data(struct inode *inode,
++                                  struct ocfs2_write_ctxt *wc,
++                                  u64 *p_blkno,
++                                  unsigned int *ret_from,
++                                  unsigned int *ret_to);
  
- void sysfs_notify(struct kobject * k, char *dir, char *attr);
+ /* all ocfs2_dio_end_io()'s fault */
+ #define ocfs2_iocb_is_rw_locked(iocb) \
+diff -Nurb linux-2.6.22-590/fs/ocfs2/cluster/heartbeat.c linux-2.6.22-570/fs/ocfs2/cluster/heartbeat.c
+--- linux-2.6.22-590/fs/ocfs2/cluster/heartbeat.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/cluster/heartbeat.c      2007-07-08 19:32:17.000000000 -0400
+@@ -1335,7 +1335,6 @@
+       ret = wait_event_interruptible(o2hb_steady_queue,
+                               atomic_read(&reg->hr_steady_iterations) == 0);
+       if (ret) {
+-              /* We got interrupted (hello ptrace!).  Clean up */
+               spin_lock(&o2hb_live_lock);
+               hb_task = reg->hr_task;
+               reg->hr_task = NULL;
+@@ -1346,16 +1345,7 @@
+               goto out;
+       }
  
+-      /* Ok, we were woken.  Make sure it wasn't by drop_item() */
+-      spin_lock(&o2hb_live_lock);
+-      hb_task = reg->hr_task;
+-      spin_unlock(&o2hb_live_lock);
 -
--extern int sysfs_make_shadowed_dir(struct kobject *kobj,
--      void * (*follow_link)(struct dentry *, struct nameidata *));
--extern struct dentry *sysfs_create_shadow_dir(struct kobject *kobj);
--extern void sysfs_remove_shadow_dir(struct dentry *dir);
-+int sysfs_enable_shadowing(struct kobject *, const struct shadow_dir_operations *);
- extern int __must_check sysfs_init(void);
+-      if (hb_task)
+       ret = count;
+-      else
+-              ret = -EIO;
+-
+ out:
+       if (filp)
+               fput(filp);
+@@ -1533,15 +1523,6 @@
+       if (hb_task)
+               kthread_stop(hb_task);
  
-@@ -144,7 +162,7 @@
-       return -ENOSYS;
+-      /*
+-       * If we're racing a dev_write(), we need to wake them.  They will
+-       * check reg->hr_task
+-       */
+-      if (atomic_read(&reg->hr_steady_iterations) != 0) {
+-              atomic_set(&reg->hr_steady_iterations, 0);
+-              wake_up(&o2hb_steady_queue);
+-      }
+-
+       config_item_put(item);
  }
  
--static inline int sysfs_create_dir(struct kobject * k, struct dentry *shadow)
-+static inline int sysfs_create_dir(struct kobject * kobj)
- {
-       return 0;
- }
-@@ -154,9 +172,7 @@
-       ;
+@@ -1684,67 +1665,7 @@
  }
+ EXPORT_SYMBOL_GPL(o2hb_setup_callback);
  
--static inline int sysfs_rename_dir(struct kobject * k,
--                                      struct dentry *new_parent,
--                                      const char *new_name)
-+static inline int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
+-static struct o2hb_region *o2hb_find_region(const char *region_uuid)
+-{
+-      struct o2hb_region *p, *reg = NULL;
+-
+-      assert_spin_locked(&o2hb_live_lock);
+-
+-      list_for_each_entry(p, &o2hb_all_regions, hr_all_item) {
+-              if (!strcmp(region_uuid, config_item_name(&p->hr_item))) {
+-                      reg = p;
+-                      break;
+-              }
+-      }
+-
+-      return reg;
+-}
+-
+-static int o2hb_region_get(const char *region_uuid)
+-{
+-      int ret = 0;
+-      struct o2hb_region *reg;
+-
+-      spin_lock(&o2hb_live_lock);
+-
+-      reg = o2hb_find_region(region_uuid);
+-      if (!reg)
+-              ret = -ENOENT;
+-      spin_unlock(&o2hb_live_lock);
+-
+-      if (ret)
+-              goto out;
+-
+-      ret = o2nm_depend_this_node();
+-      if (ret)
+-              goto out;
+-
+-      ret = o2nm_depend_item(&reg->hr_item);
+-      if (ret)
+-              o2nm_undepend_this_node();
+-
+-out:
+-      return ret;
+-}
+-
+-static void o2hb_region_put(const char *region_uuid)
+-{
+-      struct o2hb_region *reg;
+-
+-      spin_lock(&o2hb_live_lock);
+-
+-      reg = o2hb_find_region(region_uuid);
+-
+-      spin_unlock(&o2hb_live_lock);
+-
+-      if (reg) {
+-              o2nm_undepend_item(&reg->hr_item);
+-              o2nm_undepend_this_node();
+-      }
+-}
+-
+-int o2hb_register_callback(const char *region_uuid,
+-                         struct o2hb_callback_func *hc)
++int o2hb_register_callback(struct o2hb_callback_func *hc)
  {
-       return 0;
- }
-@@ -195,6 +211,17 @@
-       ;
- }
+       struct o2hb_callback_func *tmp;
+       struct list_head *iter;
+@@ -1760,12 +1681,6 @@
+               goto out;
      }
  
-+static inline int
-+sysfs_rename_link(struct kobject * k, struct kobject *t,
-+                      const char *old_name, const char * new_name)
-+{
-+      return 0;
-+}
-+
-+static inline void
-+sysfs_delete_link(struct kobject *k, struct kobject *t, const char *name)
-+{
-+}
+-      if (region_uuid) {
+-              ret = o2hb_region_get(region_uuid);
+-              if (ret)
+-                      goto out;
+-      }
+-
+       down_write(&o2hb_callback_sem);
  
- static inline int sysfs_create_bin_file(struct kobject * k, struct bin_attribute * a)
- {
-@@ -231,8 +258,8 @@
- {
+       list_for_each(iter, &hbcall->list) {
+@@ -1787,21 +1702,16 @@
  }
+ EXPORT_SYMBOL_GPL(o2hb_register_callback);
  
--static inline int sysfs_make_shadowed_dir(struct kobject *kobj,
--      void * (*follow_link)(struct dentry *, struct nameidata *))
-+static inline int sysfs_enable_shadowing(struct kobject *kobj,
-+                              const struct shadow_dir_operations *shadow_ops)
+-void o2hb_unregister_callback(const char *region_uuid,
+-                            struct o2hb_callback_func *hc)
++void o2hb_unregister_callback(struct o2hb_callback_func *hc)
  {
-       return 0;
- }
-diff -Nurb linux-2.6.22-570/include/linux/taskstats.h linux-2.6.22-590/include/linux/taskstats.h
---- linux-2.6.22-570/include/linux/taskstats.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/taskstats.h 2008-01-02 13:56:37.000000000 -0500
-@@ -31,7 +31,7 @@
-  */
+       BUG_ON(hc->hc_magic != O2HB_CB_MAGIC);
  
+       mlog(ML_HEARTBEAT, "on behalf of %p for funcs %p\n",
+            __builtin_return_address(0), hc);
  
--#define TASKSTATS_VERSION     4
-+#define TASKSTATS_VERSION     5
- #define TS_COMM_LEN           32      /* should be >= TASK_COMM_LEN
-                                        * in linux/sched.h */
+-      /* XXX Can this happen _with_ a region reference? */
+       if (list_empty(&hc->hc_item))
+               return;
  
-@@ -149,6 +149,9 @@
-       __u64   read_bytes;             /* bytes of read I/O */
-       __u64   write_bytes;            /* bytes of write I/O */
-       __u64   cancelled_write_bytes;  /* bytes of cancelled write I/O */
-+
-+      __u64  nvcsw;                   /* voluntary_ctxt_switches */
-+      __u64  nivcsw;                  /* nonvoluntary_ctxt_switches */
+-      if (region_uuid)
+-              o2hb_region_put(region_uuid);
+-
+       down_write(&o2hb_callback_sem);
+       list_del_init(&hc->hc_item);
+diff -Nurb linux-2.6.22-590/fs/ocfs2/cluster/heartbeat.h linux-2.6.22-570/fs/ocfs2/cluster/heartbeat.h
+--- linux-2.6.22-590/fs/ocfs2/cluster/heartbeat.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/cluster/heartbeat.h      2007-07-08 19:32:17.000000000 -0400
+@@ -69,10 +69,8 @@
+                        o2hb_cb_func *func,
+                        void *data,
+                        int priority);
+-int o2hb_register_callback(const char *region_uuid,
+-                         struct o2hb_callback_func *hc);
+-void o2hb_unregister_callback(const char *region_uuid,
+-                            struct o2hb_callback_func *hc);
++int o2hb_register_callback(struct o2hb_callback_func *hc);
++void o2hb_unregister_callback(struct o2hb_callback_func *hc);
+ void o2hb_fill_node_map(unsigned long *map,
+                       unsigned bytes);
+ void o2hb_init(void);
+diff -Nurb linux-2.6.22-590/fs/ocfs2/cluster/masklog.c linux-2.6.22-570/fs/ocfs2/cluster/masklog.c
+--- linux-2.6.22-590/fs/ocfs2/cluster/masklog.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/cluster/masklog.c        2007-07-08 19:32:17.000000000 -0400
+@@ -74,6 +74,7 @@
+ #define define_mask(_name) {                  \
+       .attr = {                               \
+               .name = #_name,                 \
++              .owner = THIS_MODULE,           \
+               .mode = S_IRUGO | S_IWUSR,      \
+       },                                      \
+       .mask = ML_##_name,                     \
+diff -Nurb linux-2.6.22-590/fs/ocfs2/cluster/nodemanager.c linux-2.6.22-570/fs/ocfs2/cluster/nodemanager.c
+--- linux-2.6.22-590/fs/ocfs2/cluster/nodemanager.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/cluster/nodemanager.c    2007-07-08 19:32:17.000000000 -0400
+@@ -900,46 +900,6 @@
+       },
  };
  
+-int o2nm_depend_item(struct config_item *item)
+-{
+-      return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item);
+-}
+-
+-void o2nm_undepend_item(struct config_item *item)
+-{
+-      configfs_undepend_item(&o2nm_cluster_group.cs_subsys, item);
+-}
+-
+-int o2nm_depend_this_node(void)
+-{
+-      int ret = 0;
+-      struct o2nm_node *local_node;
+-
+-      local_node = o2nm_get_node_by_num(o2nm_this_node());
+-      if (!local_node) {
+-              ret = -EINVAL;
+-              goto out;
+-      }
+-
+-      ret = o2nm_depend_item(&local_node->nd_item);
+-      o2nm_node_put(local_node);
+-
+-out:
+-      return ret;
+-}
+-
+-void o2nm_undepend_this_node(void)
+-{
+-      struct o2nm_node *local_node;
+-
+-      local_node = o2nm_get_node_by_num(o2nm_this_node());
+-      BUG_ON(!local_node);
+-
+-      o2nm_undepend_item(&local_node->nd_item);
+-      o2nm_node_put(local_node);
+-}
+-
+-
+ static void __exit exit_o2nm(void)
+ {
+       if (ocfs2_table_header)
+diff -Nurb linux-2.6.22-590/fs/ocfs2/cluster/nodemanager.h linux-2.6.22-570/fs/ocfs2/cluster/nodemanager.h
+--- linux-2.6.22-590/fs/ocfs2/cluster/nodemanager.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/cluster/nodemanager.h    2007-07-08 19:32:17.000000000 -0400
+@@ -77,9 +77,4 @@
+ void o2nm_node_get(struct o2nm_node *node);
+ void o2nm_node_put(struct o2nm_node *node);
  
-diff -Nurb linux-2.6.22-570/include/linux/tick.h linux-2.6.22-590/include/linux/tick.h
---- linux-2.6.22-570/include/linux/tick.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/tick.h      2008-01-02 13:56:37.000000000 -0500
-@@ -40,6 +40,7 @@
-  * @idle_sleeps:      Number of idle calls, where the sched tick was stopped
-  * @idle_entrytime:   Time when the idle call was entered
-  * @idle_sleeptime:   Sum of the time slept in idle with sched tick stopped
-+ * @sleep_length:     Duration of the current idle sleep
-  */
- struct tick_sched {
-       struct hrtimer                  sched_timer;
-@@ -52,6 +53,7 @@
-       unsigned long                   idle_sleeps;
-       ktime_t                         idle_entrytime;
-       ktime_t                         idle_sleeptime;
-+      ktime_t                         sleep_length;
-       unsigned long                   last_jiffies;
-       unsigned long                   next_jiffies;
-       ktime_t                         idle_expires;
-@@ -100,10 +102,18 @@
- extern void tick_nohz_stop_sched_tick(void);
- extern void tick_nohz_restart_sched_tick(void);
- extern void tick_nohz_update_jiffies(void);
-+extern ktime_t tick_nohz_get_sleep_length(void);
-+extern unsigned long tick_nohz_get_idle_jiffies(void);
- # else
- static inline void tick_nohz_stop_sched_tick(void) { }
- static inline void tick_nohz_restart_sched_tick(void) { }
- static inline void tick_nohz_update_jiffies(void) { }
-+static inline ktime_t tick_nohz_get_sleep_length(void)
-+{
-+      ktime_t len = { .tv64 = NSEC_PER_SEC/HZ };
-+
-+      return len;
-+}
- # endif /* !NO_HZ */
+-int o2nm_depend_item(struct config_item *item);
+-void o2nm_undepend_item(struct config_item *item);
+-int o2nm_depend_this_node(void);
+-void o2nm_undepend_this_node(void);
+-
+ #endif /* O2CLUSTER_NODEMANAGER_H */
+diff -Nurb linux-2.6.22-590/fs/ocfs2/cluster/tcp.c linux-2.6.22-570/fs/ocfs2/cluster/tcp.c
+--- linux-2.6.22-590/fs/ocfs2/cluster/tcp.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/cluster/tcp.c    2007-07-08 19:32:17.000000000 -0400
+@@ -261,12 +261,14 @@
  
- #endif
-diff -Nurb linux-2.6.22-570/include/linux/time.h linux-2.6.22-590/include/linux/time.h
---- linux-2.6.22-570/include/linux/time.h      2008-01-02 13:56:25.000000000 -0500
-+++ linux-2.6.22-590/include/linux/time.h      2008-01-02 13:56:37.000000000 -0500
-@@ -116,6 +116,8 @@
- extern unsigned int alarm_setitimer(unsigned int seconds);
- extern int do_getitimer(int which, struct itimerval *value);
- extern void getnstimeofday(struct timespec *tv);
-+extern void getboottime(struct timespec *ts);
-+extern void monotonic_to_bootbased(struct timespec *ts);
+ static void o2net_complete_nodes_nsw(struct o2net_node *nn)
+ {
+-      struct o2net_status_wait *nsw, *tmp;
++      struct list_head *iter, *tmp;
+       unsigned int num_kills = 0;
++      struct o2net_status_wait *nsw;
  
- extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
- extern int timekeeping_is_continuous(void);
-diff -Nurb linux-2.6.22-570/include/linux/union_fs.h linux-2.6.22-590/include/linux/union_fs.h
---- linux-2.6.22-570/include/linux/union_fs.h  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/linux/union_fs.h  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,29 @@
-+/*
-+ * Copyright (c) 2003-2007 Erez Zadok
-+ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
-+ * Copyright (c) 2003-2007 Stony Brook University
-+ * Copyright (c) 2003-2007 The Research Foundation of SUNY
-+ *
-+ * 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.
-+ */
-+
-+#ifndef _LINUX_UNION_FS_H
-+#define _LINUX_UNION_FS_H
-+
-+#define UNIONFS_VERSION  "2.0"
-+/*
-+ * DEFINITIONS FOR USER AND KERNEL CODE:
-+ */
-+# define UNIONFS_IOCTL_INCGEN         _IOR(0x15, 11, int)
-+# define UNIONFS_IOCTL_QUERYFILE      _IOR(0x15, 15, int)
-+
-+/* We don't support normal remount, but unionctl uses it. */
-+# define UNIONFS_REMOUNT_MAGIC                0x4a5a4380
-+
-+/* should be at least LAST_USED_UNIONFS_PERMISSION<<1 */
-+#define MAY_NFSRO                     16
-+
-+#endif /* _LINUX_UNIONFS_H */
-+
-diff -Nurb linux-2.6.22-570/include/linux/unwind.h linux-2.6.22-590/include/linux/unwind.h
---- linux-2.6.22-570/include/linux/unwind.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/unwind.h    2008-01-02 13:56:37.000000000 -0500
-@@ -14,6 +14,63 @@
+       assert_spin_locked(&nn->nn_lock);
  
- struct module;
+-      list_for_each_entry_safe(nsw, tmp, &nn->nn_status_list, ns_node_item) {
++      list_for_each_safe(iter, tmp, &nn->nn_status_list) {
++              nsw = list_entry(iter, struct o2net_status_wait, ns_node_item);
+               o2net_complete_nsw_locked(nn, nsw, O2NET_ERR_DIED, 0);
+               num_kills++;
+       }
+@@ -762,10 +764,13 @@
  
-+#ifdef CONFIG_STACK_UNWIND
-+
-+#include <asm/unwind.h>
-+
-+#ifndef ARCH_UNWIND_SECTION_NAME
-+#define ARCH_UNWIND_SECTION_NAME ".eh_frame"
-+#endif
-+
-+/*
-+ * Initialize unwind support.
-+ */
-+extern void unwind_init(void);
-+extern void unwind_setup(void);
-+
-+#ifdef CONFIG_MODULES
-+
-+extern void *unwind_add_table(struct module *,
-+                              const void *table_start,
-+                              unsigned long table_size);
-+
-+extern void unwind_remove_table(void *handle, int init_only);
-+
-+#endif
-+
-+extern int unwind_init_frame_info(struct unwind_frame_info *,
-+                                  struct task_struct *,
-+                                  /*const*/ struct pt_regs *);
-+
-+/*
-+ * Prepare to unwind a blocked task.
-+ */
-+extern int unwind_init_blocked(struct unwind_frame_info *,
-+                               struct task_struct *);
-+
-+/*
-+ * Prepare to unwind the currently running thread.
-+ */
-+extern int unwind_init_running(struct unwind_frame_info *,
-+                               asmlinkage int (*callback)(struct unwind_frame_info *,
-+                                                          void *arg),
-+                               void *arg);
-+
-+/*
-+ * Unwind to previous to frame.  Returns 0 if successful, negative
-+ * number in case of an error.
-+ */
-+extern int unwind(struct unwind_frame_info *);
-+
-+/*
-+ * Unwind until the return pointer is in user-land (or until an error
-+ * occurs).  Returns 0 if successful, negative number in case of
-+ * error.
-+ */
-+extern int unwind_to_user(struct unwind_frame_info *);
-+
-+#else
-+
- struct unwind_frame_info {};
+ void o2net_unregister_handler_list(struct list_head *list)
+ {
+-      struct o2net_msg_handler *nmh, *n;
++      struct list_head *pos, *n;
++      struct o2net_msg_handler *nmh;
  
- static inline void unwind_init(void) {}
-@@ -28,12 +85,12 @@
-       return NULL;
- }
+       write_lock(&o2net_handler_lock);
+-      list_for_each_entry_safe(nmh, n, list, nh_unregister_item) {
++      list_for_each_safe(pos, n, list) {
++              nmh = list_entry(pos, struct o2net_msg_handler,
++                               nh_unregister_item);
+               mlog(ML_TCP, "unregistering handler func %p type %u key %08x\n",
+                    nmh->nh_func, nmh->nh_msg_type, nmh->nh_key);
+               rb_erase(&nmh->nh_node, &o2net_handler_tree);
+@@ -1633,8 +1638,8 @@
  
-+#endif
-+
- static inline void unwind_remove_table(void *handle, int init_only)
+ void o2net_unregister_hb_callbacks(void)
  {
+-      o2hb_unregister_callback(NULL, &o2net_hb_up);
+-      o2hb_unregister_callback(NULL, &o2net_hb_down);
++      o2hb_unregister_callback(&o2net_hb_up);
++      o2hb_unregister_callback(&o2net_hb_down);
  }
  
--#endif
--
- static inline int unwind_init_frame_info(struct unwind_frame_info *info,
-                                          struct task_struct *tsk,
-                                          const struct pt_regs *regs)
-@@ -65,4 +122,6 @@
-       return -ENOSYS;
- }
-+#endif
-+
- #endif /* _LINUX_UNWIND_H */
-diff -Nurb linux-2.6.22-570/include/linux/usb.h linux-2.6.22-590/include/linux/usb.h
---- linux-2.6.22-570/include/linux/usb.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/usb.h       2008-01-02 13:56:37.000000000 -0500
-@@ -146,6 +146,10 @@
-                                        * active alternate setting */
-       unsigned num_altsetting;        /* number of alternate settings */
+ int o2net_register_hb_callbacks(void)
+@@ -1646,9 +1651,9 @@
+       o2hb_setup_callback(&o2net_hb_up, O2HB_NODE_UP_CB,
+                           o2net_hb_node_up_cb, NULL, O2NET_HB_PRI);
  
-+      /* If there is an interface association descriptor then it will list
-+       * the associated interfaces */
-+      struct usb_interface_assoc_descriptor *intf_assoc;
-+
-       int minor;                      /* minor number this interface is
-                                        * bound to */
-       enum usb_interface_condition condition;         /* state of binding */
-@@ -175,6 +179,7 @@
+-      ret = o2hb_register_callback(NULL, &o2net_hb_up);
++      ret = o2hb_register_callback(&o2net_hb_up);
+       if (ret == 0)
+-              ret = o2hb_register_callback(NULL, &o2net_hb_down);
++              ret = o2hb_register_callback(&o2net_hb_down);
  
- /* this maximum is arbitrary */
- #define USB_MAXINTERFACES     32
-+#define USB_MAXIADS           USB_MAXINTERFACES/2
+       if (ret)
+               o2net_unregister_hb_callbacks();
+diff -Nurb linux-2.6.22-590/fs/ocfs2/dir.c linux-2.6.22-570/fs/ocfs2/dir.c
+--- linux-2.6.22-590/fs/ocfs2/dir.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/dir.c    2007-07-08 19:32:17.000000000 -0400
+@@ -368,7 +368,7 @@
+               u32 offset = OCFS2_I(dir)->ip_clusters;
  
- /**
-  * struct usb_interface_cache - long-term representation of a device interface
-@@ -245,6 +250,11 @@
-       struct usb_config_descriptor    desc;
+               status = ocfs2_do_extend_allocation(OCFS2_SB(sb), dir, &offset,
+-                                                  1, 0, parent_fe_bh, handle,
++                                                  1, parent_fe_bh, handle,
+                                                   data_ac, meta_ac, NULL);
+               BUG_ON(status == -EAGAIN);
+               if (status < 0) {
+diff -Nurb linux-2.6.22-590/fs/ocfs2/dlm/dlmdomain.c linux-2.6.22-570/fs/ocfs2/dlm/dlmdomain.c
+--- linux-2.6.22-590/fs/ocfs2/dlm/dlmdomain.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/dlm/dlmdomain.c  2007-07-08 19:32:17.000000000 -0400
+@@ -1128,8 +1128,8 @@
  
-       char *string;           /* iConfiguration string, if present */
-+
-+      /* List of any Interface Association Descriptors in this
-+       * configuration. */
-+      struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];
-+
-       /* the interfaces associated with this configuration,
-        * stored in no particular order */
-       struct usb_interface *interface[USB_MAXINTERFACES];
-diff -Nurb linux-2.6.22-570/include/linux/user_namespace.h linux-2.6.22-590/include/linux/user_namespace.h
---- linux-2.6.22-570/include/linux/user_namespace.h    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/linux/user_namespace.h    2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,61 @@
-+#ifndef _LINUX_USER_NAMESPACE_H
-+#define _LINUX_USER_NAMESPACE_H
-+
-+#include <linux/kref.h>
-+#include <linux/nsproxy.h>
-+#include <linux/sched.h>
-+#include <linux/err.h>
-+
-+#define UIDHASH_BITS  (CONFIG_BASE_SMALL ? 3 : 8)
-+#define UIDHASH_SZ    (1 << UIDHASH_BITS)
-+
-+struct user_namespace {
-+      struct kref             kref;
-+      struct list_head        uidhash_table[UIDHASH_SZ];
-+      struct user_struct      *root_user;
-+};
-+
-+extern struct user_namespace init_user_ns;
-+
-+#ifdef CONFIG_USER_NS
-+
-+static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
-+{
-+      if (ns)
-+              kref_get(&ns->kref);
-+      return ns;
-+}
-+
-+extern struct user_namespace *copy_user_ns(int flags,
-+                                         struct user_namespace *old_ns);
-+extern void free_user_ns(struct kref *kref);
-+
-+static inline void put_user_ns(struct user_namespace *ns)
-+{
-+      if (ns)
-+              kref_put(&ns->kref, free_user_ns);
-+}
-+
-+#else
-+
-+static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
-+{
-+      return &init_user_ns;
-+}
-+
-+static inline struct user_namespace *copy_user_ns(int flags,
-+                                                struct user_namespace *old_ns)
-+{
-+      if (flags & CLONE_NEWUSER)
-+              return ERR_PTR(-EINVAL);
-+
-+      return NULL;
-+}
-+
-+static inline void put_user_ns(struct user_namespace *ns)
-+{
-+}
-+
-+#endif
-+
-+#endif /* _LINUX_USER_H */
-diff -Nurb linux-2.6.22-570/include/linux/utsname.h linux-2.6.22-590/include/linux/utsname.h
---- linux-2.6.22-570/include/linux/utsname.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/utsname.h   2008-01-02 13:56:37.000000000 -0500
-@@ -48,26 +48,14 @@
-       kref_get(&ns->kref);
+ static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm)
+ {
+-      o2hb_unregister_callback(NULL, &dlm->dlm_hb_up);
+-      o2hb_unregister_callback(NULL, &dlm->dlm_hb_down);
++      o2hb_unregister_callback(&dlm->dlm_hb_up);
++      o2hb_unregister_callback(&dlm->dlm_hb_down);
+       o2net_unregister_handler_list(&dlm->dlm_domain_handlers);
  }
  
--#ifdef CONFIG_UTS_NS
--extern struct uts_namespace *copy_utsname(int flags, struct uts_namespace *ns);
-+extern struct uts_namespace *copy_utsname(unsigned long flags,
-+                                      struct uts_namespace *ns);
- extern void free_uts_ns(struct kref *kref);
+@@ -1141,13 +1141,13 @@
  
- static inline void put_uts_ns(struct uts_namespace *ns)
+       o2hb_setup_callback(&dlm->dlm_hb_down, O2HB_NODE_DOWN_CB,
+                           dlm_hb_node_down_cb, dlm, DLM_HB_NODE_DOWN_PRI);
+-      status = o2hb_register_callback(NULL, &dlm->dlm_hb_down);
++      status = o2hb_register_callback(&dlm->dlm_hb_down);
+       if (status)
+               goto bail;
+       o2hb_setup_callback(&dlm->dlm_hb_up, O2HB_NODE_UP_CB,
+                           dlm_hb_node_up_cb, dlm, DLM_HB_NODE_UP_PRI);
+-      status = o2hb_register_callback(NULL, &dlm->dlm_hb_up);
++      status = o2hb_register_callback(&dlm->dlm_hb_up);
+       if (status)
+               goto bail;
+diff -Nurb linux-2.6.22-590/fs/ocfs2/dlm/dlmmaster.c linux-2.6.22-570/fs/ocfs2/dlm/dlmmaster.c
+--- linux-2.6.22-590/fs/ocfs2/dlm/dlmmaster.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/dlm/dlmmaster.c  2007-07-08 19:32:17.000000000 -0400
+@@ -192,20 +192,25 @@
+ static void dlm_dump_mles(struct dlm_ctxt *dlm)
  {
-       kref_put(&ns->kref, free_uts_ns);
+       struct dlm_master_list_entry *mle;
++      struct list_head *iter;
+       
+       mlog(ML_NOTICE, "dumping all mles for domain %s:\n", dlm->name);
+       spin_lock(&dlm->master_lock);
+-      list_for_each_entry(mle, &dlm->master_list, list)
++      list_for_each(iter, &dlm->master_list) {
++              mle = list_entry(iter, struct dlm_master_list_entry, list);
+               dlm_print_one_mle(mle);
++      }
+       spin_unlock(&dlm->master_lock);
  }
--#else
--static inline struct uts_namespace *copy_utsname(int flags,
--                                              struct uts_namespace *ns)
--{
--      return ns;
--}
--
--static inline void put_uts_ns(struct uts_namespace *ns)
--{
--}
--#endif
--
- static inline struct new_utsname *utsname(void)
+ int dlm_dump_all_mles(const char __user *data, unsigned int len)
  {
-       return &current->nsproxy->uts_ns->name;
-diff -Nurb linux-2.6.22-570/include/linux/vmalloc.h linux-2.6.22-590/include/linux/vmalloc.h
---- linux-2.6.22-570/include/linux/vmalloc.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/linux/vmalloc.h   2008-01-02 13:56:37.000000000 -0500
-@@ -65,9 +65,10 @@
-                                         unsigned long flags, int node,
-                                         gfp_t gfp_mask);
- extern struct vm_struct *remove_vm_area(void *addr);
-+
- extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
-                       struct page ***pages);
--extern void unmap_vm_area(struct vm_struct *area);
-+extern void unmap_kernel_range(unsigned long addr, unsigned long size);
++      struct list_head *iter;
+       struct dlm_ctxt *dlm;
  
- /*
-  *    Internals.  Dont't use..
-diff -Nurb linux-2.6.22-570/include/net/addrconf.h linux-2.6.22-590/include/net/addrconf.h
---- linux-2.6.22-570/include/net/addrconf.h    2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/include/net/addrconf.h    2008-01-02 13:56:37.000000000 -0500
-@@ -61,7 +61,7 @@
- extern int                    ipv6_chk_addr(struct in6_addr *addr,
-                                             struct net_device *dev,
-                                             int strict);
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- extern int                    ipv6_chk_home_addr(struct in6_addr *addr);
- #endif
- extern struct inet6_ifaddr *  ipv6_get_ifaddr(struct in6_addr *addr,
-diff -Nurb linux-2.6.22-570/include/net/af_unix.h linux-2.6.22-590/include/net/af_unix.h
---- linux-2.6.22-570/include/net/af_unix.h     2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/include/net/af_unix.h     2008-01-02 13:56:37.000000000 -0500
-@@ -91,12 +91,11 @@
- #define unix_sk(__sk) ((struct unix_sock *)__sk)
+       spin_lock(&dlm_domain_lock);
+-      list_for_each_entry(dlm, &dlm_domains, list) {
++      list_for_each(iter, &dlm_domains) {
++              dlm = list_entry (iter, struct dlm_ctxt, list);
+               mlog(ML_NOTICE, "found dlm: %p, name=%s\n", dlm, dlm->name);
+               dlm_dump_mles(dlm);
+       }
+@@ -449,10 +454,12 @@
+                       char *name, unsigned int namelen)
+ {
+       struct dlm_master_list_entry *tmpmle;
++      struct list_head *iter;
  
- #ifdef CONFIG_SYSCTL
--extern int sysctl_unix_max_dgram_qlen;
--extern void unix_sysctl_register(void);
--extern void unix_sysctl_unregister(void);
-+extern void unix_sysctl_register(struct net *net);
-+extern void unix_sysctl_unregister(struct net *net);
- #else
--static inline void unix_sysctl_register(void) {}
--static inline void unix_sysctl_unregister(void) {}
-+static inline void unix_sysctl_register(struct net *net) {}
-+static inline void unix_sysctl_unregister(struct net *net) {}
- #endif
- #endif
- #endif
-diff -Nurb linux-2.6.22-570/include/net/arp.h linux-2.6.22-590/include/net/arp.h
---- linux-2.6.22-570/include/net/arp.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/arp.h 2008-01-02 13:56:37.000000000 -0500
-@@ -11,7 +11,7 @@
+       assert_spin_locked(&dlm->master_lock);
  
- extern void   arp_init(void);
- extern int    arp_find(unsigned char *haddr, struct sk_buff *skb);
--extern int    arp_ioctl(unsigned int cmd, void __user *arg);
-+extern int    arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);
- extern void     arp_send(int type, int ptype, __be32 dest_ip,
-                        struct net_device *dev, __be32 src_ip,
-                        unsigned char *dest_hw, unsigned char *src_hw, unsigned char *th);
-diff -Nurb linux-2.6.22-570/include/net/dst.h linux-2.6.22-590/include/net/dst.h
---- linux-2.6.22-570/include/net/dst.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/dst.h 2008-01-02 13:56:37.000000000 -0500
-@@ -47,7 +47,6 @@
- #define DST_NOXFRM            2
- #define DST_NOPOLICY          4
- #define DST_NOHASH            8
--#define DST_BALANCED            0x10
-       unsigned long           expires;
+-      list_for_each_entry(tmpmle, &dlm->master_list, list) {
++      list_for_each(iter, &dlm->master_list) {
++              tmpmle = list_entry(iter, struct dlm_master_list_entry, list);
+               if (!dlm_mle_equal(dlm, tmpmle, name, namelen))
+                       continue;
+               dlm_get_mle(tmpmle);
+@@ -465,10 +472,13 @@
+ void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up)
+ {
+       struct dlm_master_list_entry *mle;
++      struct list_head *iter;
  
-       unsigned short          header_len;     /* more space at head required */
-diff -Nurb linux-2.6.22-570/include/net/fib_rules.h linux-2.6.22-590/include/net/fib_rules.h
---- linux-2.6.22-570/include/net/fib_rules.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/fib_rules.h   2008-01-02 13:56:37.000000000 -0500
-@@ -56,12 +56,12 @@
-       int                     (*fill)(struct fib_rule *, struct sk_buff *,
-                                       struct nlmsghdr *,
-                                       struct fib_rule_hdr *);
--      u32                     (*default_pref)(void);
-+      u32                     (*default_pref)(struct fib_rules_ops *ops);
-       size_t                  (*nlmsg_payload)(struct fib_rule *);
+       assert_spin_locked(&dlm->spinlock);
+       
+-      list_for_each_entry(mle, &dlm->mle_hb_events, hb_events) {
++      list_for_each(iter, &dlm->mle_hb_events) {
++              mle = list_entry(iter, struct dlm_master_list_entry, 
++                               hb_events);
+               if (node_up)
+                       dlm_mle_node_up(dlm, mle, NULL, idx);
+               else
+@@ -2424,7 +2434,7 @@
+       int ret;
+       int i;
+       int count = 0;
+-      struct list_head *queue;
++      struct list_head *queue, *iter;
+       struct dlm_lock *lock;
  
-       /* Called after modifications to the rules set, must flush
-        * the route cache if one exists. */
--      void                    (*flush_cache)(void);
-+      void                    (*flush_cache)(struct fib_rules_ops *ops);
+       assert_spin_locked(&res->spinlock);
+@@ -2443,7 +2453,8 @@
+       ret = 0;
+       queue = &res->granted;
+       for (i = 0; i < 3; i++) {
+-              list_for_each_entry(lock, queue, list) {
++              list_for_each(iter, queue) {
++                      lock = list_entry(iter, struct dlm_lock, list);
+                       ++count;
+                       if (lock->ml.node == dlm->node_num) {
+                               mlog(0, "found a lock owned by this node still "
+@@ -2912,16 +2923,18 @@
+ static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
+                                     struct dlm_lock_resource *res)
+ {
++      struct list_head *iter, *iter2;
+       struct list_head *queue = &res->granted;
+       int i, bit;
+-      struct dlm_lock *lock, *next;
++      struct dlm_lock *lock;
  
-       int                     nlgroup;
-       const struct nla_policy *policy;
-@@ -101,8 +101,8 @@
-       return frh->table;
- }
+       assert_spin_locked(&res->spinlock);
  
--extern int                    fib_rules_register(struct fib_rules_ops *);
--extern int                    fib_rules_unregister(struct fib_rules_ops *);
-+extern int                    fib_rules_register(struct net *net, struct fib_rules_ops *);
-+extern int                    fib_rules_unregister(struct net *net, struct fib_rules_ops *);
+       BUG_ON(res->owner == dlm->node_num);
  
- extern int                    fib_rules_lookup(struct fib_rules_ops *,
-                                                struct flowi *, int flags,
-diff -Nurb linux-2.6.22-570/include/net/flow.h linux-2.6.22-590/include/net/flow.h
---- linux-2.6.22-570/include/net/flow.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/flow.h        2008-01-02 13:56:37.000000000 -0500
-@@ -8,9 +8,11 @@
- #define _NET_FLOW_H
+       for (i=0; i<3; i++) {
+-              list_for_each_entry_safe(lock, next, queue, list) {
++              list_for_each_safe(iter, iter2, queue) {
++                      lock = list_entry (iter, struct dlm_lock, list);
+                       if (lock->ml.node != dlm->node_num) {
+                               mlog(0, "putting lock for node %u\n",
+                                    lock->ml.node);
+@@ -2963,6 +2976,7 @@
+ {
+       int i;
+       struct list_head *queue = &res->granted;
++      struct list_head *iter;
+       struct dlm_lock *lock;
+       int nodenum;
+@@ -2970,9 +2984,10 @@
+       spin_lock(&res->spinlock);
+       for (i=0; i<3; i++) {
+-              list_for_each_entry(lock, queue, list) {
++              list_for_each(iter, queue) {
+                       /* up to the caller to make sure this node
+                        * is alive */
++                      lock = list_entry (iter, struct dlm_lock, list);
+                       if (lock->ml.node != dlm->node_num) {
+                               spin_unlock(&res->spinlock);
+                               return lock->ml.node;
+@@ -3219,7 +3234,8 @@
+ void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node)
+ {
+-      struct dlm_master_list_entry *mle, *next;
++      struct list_head *iter, *iter2;
++      struct dlm_master_list_entry *mle;
+       struct dlm_lock_resource *res;
+       unsigned int hash;
+@@ -3229,7 +3245,9 @@
+       /* clean the master list */
+       spin_lock(&dlm->master_lock);
+-      list_for_each_entry_safe(mle, next, &dlm->master_list, list) {
++      list_for_each_safe(iter, iter2, &dlm->master_list) {
++              mle = list_entry(iter, struct dlm_master_list_entry, list);
++
+               BUG_ON(mle->type != DLM_MLE_BLOCK &&
+                      mle->type != DLM_MLE_MASTER &&
+                      mle->type != DLM_MLE_MIGRATION);
+diff -Nurb linux-2.6.22-590/fs/ocfs2/dlm/dlmrecovery.c linux-2.6.22-570/fs/ocfs2/dlm/dlmrecovery.c
+--- linux-2.6.22-590/fs/ocfs2/dlm/dlmrecovery.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/dlm/dlmrecovery.c        2007-07-08 19:32:17.000000000 -0400
+@@ -158,7 +158,8 @@
+       struct dlm_ctxt *dlm =
+               container_of(work, struct dlm_ctxt, dispatched_work);
+       LIST_HEAD(tmp_list);
+-      struct dlm_work_item *item, *next;
++      struct list_head *iter, *iter2;
++      struct dlm_work_item *item;
+       dlm_workfunc_t *workfunc;
+       int tot=0;
  
- #include <linux/in6.h>
-+#include <net/net_namespace.h>
- #include <asm/atomic.h>
+@@ -166,12 +167,13 @@
+       list_splice_init(&dlm->work_list, &tmp_list);
+       spin_unlock(&dlm->work_lock);
  
- struct flowi {
-+      struct net *fl_net;
-       int     oif;
-       int     iif;
-       __u32   mark;
-@@ -67,20 +69,16 @@
+-      list_for_each_entry(item, &tmp_list, list) {
++      list_for_each_safe(iter, iter2, &tmp_list) {
+               tot++;
+       }
+       mlog(0, "%s: work thread has %d work items\n", dlm->name, tot);
  
-               __be32          spi;
+-      list_for_each_entry_safe(item, next, &tmp_list, list) {
++      list_for_each_safe(iter, iter2, &tmp_list) {
++              item = list_entry(iter, struct dlm_work_item, list);
+               workfunc = item->func;
+               list_del_init(&item->list);
  
--#ifdef CONFIG_IPV6_MIP6
-               struct {
-                       __u8    type;
-               } mht;
--#endif
-       } uli_u;
- #define fl_ip_sport   uli_u.ports.sport
- #define fl_ip_dport   uli_u.ports.dport
- #define fl_icmp_type  uli_u.icmpt.type
- #define fl_icmp_code  uli_u.icmpt.code
- #define fl_ipsec_spi  uli_u.spi
--#ifdef CONFIG_IPV6_MIP6
- #define fl_mh_type    uli_u.mht.type
--#endif
-       __u32           secid;  /* used by xfrm; see secid.txt */
- } __attribute__((__aligned__(BITS_PER_LONG/8)));
+@@ -547,6 +549,7 @@
+ {
+       int status = 0;
+       struct dlm_reco_node_data *ndata;
++      struct list_head *iter;
+       int all_nodes_done;
+       int destroy = 0;
+       int pass = 0;
+@@ -564,7 +567,8 @@
  
-diff -Nurb linux-2.6.22-570/include/net/inet6_hashtables.h linux-2.6.22-590/include/net/inet6_hashtables.h
---- linux-2.6.22-570/include/net/inet6_hashtables.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/inet6_hashtables.h    2008-01-02 13:56:37.000000000 -0500
-@@ -62,31 +62,31 @@
-                                          const __be16 sport,
-                                          const struct in6_addr *daddr,
-                                          const u16 hnum,
--                                         const int dif);
-+                                         const int dif, struct net *net);
+       /* safe to access the node data list without a lock, since this
+        * process is the only one to change the list */
+-      list_for_each_entry(ndata, &dlm->reco.node_data, list) {
++      list_for_each(iter, &dlm->reco.node_data) {
++              ndata = list_entry (iter, struct dlm_reco_node_data, list);
+               BUG_ON(ndata->state != DLM_RECO_NODE_DATA_INIT);
+               ndata->state = DLM_RECO_NODE_DATA_REQUESTING;
  
- extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
-                                         const struct in6_addr *daddr,
-                                         const unsigned short hnum,
--                                        const int dif);
-+                                        const int dif, struct net *net);
+@@ -651,7 +655,9 @@
+                * done, or if anyone died */
+               all_nodes_done = 1;
+               spin_lock(&dlm_reco_state_lock);
+-              list_for_each_entry(ndata, &dlm->reco.node_data, list) {
++              list_for_each(iter, &dlm->reco.node_data) {
++                      ndata = list_entry (iter, struct dlm_reco_node_data, list);
++
+                       mlog(0, "checking recovery state of node %u\n",
+                            ndata->node_num);
+                       switch (ndata->state) {
+@@ -768,14 +774,16 @@
  
- static inline struct sock *__inet6_lookup(struct inet_hashinfo *hashinfo,
-                                         const struct in6_addr *saddr,
-                                         const __be16 sport,
-                                         const struct in6_addr *daddr,
-                                         const u16 hnum,
--                                        const int dif)
-+                                        const int dif, struct net *net)
+ static void dlm_destroy_recovery_area(struct dlm_ctxt *dlm, u8 dead_node)
  {
-       struct sock *sk = __inet6_lookup_established(hashinfo, saddr, sport,
--                                                   daddr, hnum, dif);
-+                                                   daddr, hnum, dif, net);
-       if (sk)
-               return sk;
+-      struct dlm_reco_node_data *ndata, *next;
++      struct list_head *iter, *iter2;
++      struct dlm_reco_node_data *ndata;
+       LIST_HEAD(tmplist);
  
--      return inet6_lookup_listener(hashinfo, daddr, hnum, dif);
-+      return inet6_lookup_listener(hashinfo, daddr, hnum, dif, net);
- }
+       spin_lock(&dlm_reco_state_lock);
+       list_splice_init(&dlm->reco.node_data, &tmplist);
+       spin_unlock(&dlm_reco_state_lock);
  
- extern struct sock *inet6_lookup(struct inet_hashinfo *hashinfo,
-                                const struct in6_addr *saddr, const __be16 sport,
-                                const struct in6_addr *daddr, const __be16 dport,
--                               const int dif);
-+                               const int dif, struct net *net);
- #endif /* defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) */
- #endif /* _INET6_HASHTABLES_H */
-diff -Nurb linux-2.6.22-570/include/net/inet_hashtables.h linux-2.6.22-590/include/net/inet_hashtables.h
---- linux-2.6.22-570/include/net/inet_hashtables.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/inet_hashtables.h     2008-01-02 13:56:37.000000000 -0500
-@@ -75,6 +75,7 @@
-  * ports are created in O(1) time?  I thought so. ;-) -DaveM
-  */
- struct inet_bind_bucket {
-+      struct net              *net;
-       unsigned short          port;
-       signed short            fastreuse;
-       struct hlist_node       node;
-@@ -138,34 +139,35 @@
- extern struct inet_bind_bucket *
-                   inet_bind_bucket_create(struct kmem_cache *cachep,
-                                           struct inet_bind_hashbucket *head,
-+                                          struct net *net,
-                                           const unsigned short snum);
- extern void inet_bind_bucket_destroy(struct kmem_cache *cachep,
-                                    struct inet_bind_bucket *tb);
+-      list_for_each_entry_safe(ndata, next, &tmplist, list) {
++      list_for_each_safe(iter, iter2, &tmplist) {
++              ndata = list_entry (iter, struct dlm_reco_node_data, list);
+               list_del_init(&ndata->list);
+               kfree(ndata);
+       }
+@@ -868,6 +876,7 @@
+       struct dlm_lock_resource *res;
+       struct dlm_ctxt *dlm;
+       LIST_HEAD(resources);
++      struct list_head *iter;
+       int ret;
+       u8 dead_node, reco_master;
+       int skip_all_done = 0;
+@@ -911,7 +920,8 @@
  
--static inline int inet_bhashfn(const __u16 lport, const int bhash_size)
-+static inline int inet_bhashfn(struct net *net, const __u16 lport, const int bhash_size)
+       /* any errors returned will be due to the new_master dying,
+        * the dlm_reco_thread should detect this */
+-      list_for_each_entry(res, &resources, recovering) {
++      list_for_each(iter, &resources) {
++              res = list_entry (iter, struct dlm_lock_resource, recovering);
+               ret = dlm_send_one_lockres(dlm, res, mres, reco_master,
+                                       DLM_MRES_RECOVERY);
+               if (ret < 0) {
+@@ -973,6 +983,7 @@
  {
--      return lport & (bhash_size - 1);
-+      return (((unsigned long)net) ^ lport) & (bhash_size - 1);
- }
+       struct dlm_ctxt *dlm = data;
+       struct dlm_reco_data_done *done = (struct dlm_reco_data_done *)msg->buf;
++      struct list_head *iter;
+       struct dlm_reco_node_data *ndata = NULL;
+       int ret = -EINVAL;
  
- extern void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
-                          const unsigned short snum);
+@@ -989,7 +1000,8 @@
+                       dlm->reco.dead_node, done->node_idx, dlm->node_num);
  
- /* These can have wildcards, don't try too hard. */
--static inline int inet_lhashfn(const unsigned short num)
-+static inline int inet_lhashfn(struct net *net, const unsigned short num)
+       spin_lock(&dlm_reco_state_lock);
+-      list_for_each_entry(ndata, &dlm->reco.node_data, list) {
++      list_for_each(iter, &dlm->reco.node_data) {
++              ndata = list_entry (iter, struct dlm_reco_node_data, list);
+               if (ndata->node_num != done->node_idx)
+                       continue;
+@@ -1037,11 +1049,13 @@
+                                       struct list_head *list,
+                                       u8 dead_node)
  {
--      return num & (INET_LHTABLE_SIZE - 1);
-+      return (((unsigned long)net) ^ num) & (INET_LHTABLE_SIZE - 1);
- }
+-      struct dlm_lock_resource *res, *next;
++      struct dlm_lock_resource *res;
++      struct list_head *iter, *iter2;
+       struct dlm_lock *lock;
  
- static inline int inet_sk_listen_hashfn(const struct sock *sk)
+       spin_lock(&dlm->spinlock);
+-      list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
++      list_for_each_safe(iter, iter2, &dlm->reco.resources) {
++              res = list_entry (iter, struct dlm_lock_resource, recovering);
+               /* always prune any $RECOVERY entries for dead nodes,
+                * otherwise hangs can occur during later recovery */
+               if (dlm_is_recovery_lock(res->lockname.name,
+@@ -1155,7 +1169,7 @@
+                                       u8 flags, u8 master)
  {
--      return inet_lhashfn(inet_sk(sk)->num);
-+      return inet_lhashfn(sk->sk_net, inet_sk(sk)->num);
- }
+       /* mres here is one full page */
+-      clear_page(mres);
++      memset(mres, 0, PAGE_SIZE);
+       mres->lockname_len = namelen;
+       memcpy(mres->lockname, lockname, namelen);
+       mres->num_locks = 0;
+@@ -1238,7 +1252,7 @@
+                        struct dlm_migratable_lockres *mres,
+                        u8 send_to, u8 flags)
+ {
+-      struct list_head *queue;
++      struct list_head *queue, *iter;
+       int total_locks, i;
+       u64 mig_cookie = 0;
+       struct dlm_lock *lock;
+@@ -1264,7 +1278,9 @@
+       total_locks = 0;
+       for (i=DLM_GRANTED_LIST; i<=DLM_BLOCKED_LIST; i++) {
+               queue = dlm_list_idx_to_ptr(res, i);
+-              list_for_each_entry(lock, queue, list) {
++              list_for_each(iter, queue) {
++                      lock = list_entry (iter, struct dlm_lock, list);
++
+                       /* add another lock. */
+                       total_locks++;
+                       if (!dlm_add_lock_to_array(lock, mres, i))
+@@ -1701,6 +1717,7 @@
+       struct dlm_lockstatus *lksb = NULL;
+       int ret = 0;
+       int i, j, bad;
++      struct list_head *iter;
+       struct dlm_lock *lock = NULL;
+       u8 from = O2NM_MAX_NODES;
+       unsigned int added = 0;
+@@ -1738,7 +1755,8 @@
+                       spin_lock(&res->spinlock);
+                       for (j = DLM_GRANTED_LIST; j <= DLM_BLOCKED_LIST; j++) {
+                               tmpq = dlm_list_idx_to_ptr(res, j);
+-                              list_for_each_entry(lock, tmpq, list) {
++                              list_for_each(iter, tmpq) {
++                                      lock = list_entry (iter, struct dlm_lock, list);
+                                       if (lock->ml.cookie != ml->cookie)
+                                               lock = NULL;
+                                       else
+@@ -1912,8 +1930,8 @@
+                                      struct dlm_lock_resource *res)
+ {
+       int i;
+-      struct list_head *queue;
+-      struct dlm_lock *lock, *next;
++      struct list_head *queue, *iter, *iter2;
++      struct dlm_lock *lock;
  
- /* Caller must disable local BH processing. */
- static inline void __inet_inherit_port(struct inet_hashinfo *table,
-                                      struct sock *sk, struct sock *child)
+       res->state |= DLM_LOCK_RES_RECOVERING;
+       if (!list_empty(&res->recovering)) {
+@@ -1929,7 +1947,8 @@
+       /* find any pending locks and put them back on proper list */
+       for (i=DLM_BLOCKED_LIST; i>=DLM_GRANTED_LIST; i--) {
+               queue = dlm_list_idx_to_ptr(res, i);
+-              list_for_each_entry_safe(lock, next, queue, list) {
++              list_for_each_safe(iter, iter2, queue) {
++                      lock = list_entry (iter, struct dlm_lock, list);
+                       dlm_lock_get(lock);
+                       if (lock->convert_pending) {
+                               /* move converting lock back to granted */
+@@ -1994,15 +2013,18 @@
+                                             u8 dead_node, u8 new_master)
  {
--      const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size);
-+      const int bhash = inet_bhashfn(sk->sk_net, inet_sk(child)->num, table->bhash_size);
-       struct inet_bind_hashbucket *head = &table->bhash[bhash];
-       struct inet_bind_bucket *tb;
+       int i;
++      struct list_head *iter, *iter2;
+       struct hlist_node *hash_iter;
+       struct hlist_head *bucket;
+-      struct dlm_lock_resource *res, *next;
++
++      struct dlm_lock_resource *res;
  
-@@ -274,12 +276,13 @@
- extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
-                                          const __be32 daddr,
-                                          const unsigned short hnum,
--                                         const int dif);
-+                                         const int dif, struct net *net);
+       mlog_entry_void();
  
- static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo,
--                                              __be32 daddr, __be16 dport, int dif)
-+                                              __be32 daddr, __be16 dport,
-+                                              int dif, struct net *net)
- {
--      return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif);
-+      return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif, net);
- }
+       assert_spin_locked(&dlm->spinlock);
  
- /* Socket demux engine toys. */
-@@ -313,30 +316,34 @@
-                                  (((__force __u64)(__be32)(__daddr)) << 32) | \
-                                  ((__force __u64)(__be32)(__saddr)));
- #endif /* __BIG_ENDIAN */
--#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
-+#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif, __net)\
-       (((__sk)->sk_hash == (__hash))                          &&      \
-        ((*((__addrpair *)&(inet_sk(__sk)->daddr))) == (__cookie))     &&      \
-        ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))      &&      \
--       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
--#define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
-+       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))) && \
-+       ((__sk)->sk_net == __net))
-+#define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif, __net)\
-       (((__sk)->sk_hash == (__hash))                          &&      \
-        ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&     \
-        ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&      \
--       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-+       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))) && \
-+       ((__sk)->sk_net == __net))
- #else /* 32-bit arch */
- #define INET_ADDR_COOKIE(__name, __saddr, __daddr)
--#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)  \
-+#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif, __net) \
-       (((__sk)->sk_hash == (__hash))                          &&      \
-        (inet_sk(__sk)->daddr          == (__saddr))           &&      \
-        (inet_sk(__sk)->rcv_saddr      == (__daddr))           &&      \
-        ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))      &&      \
--       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
--#define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif)        \
-+       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))) && \
-+       ((__sk)->sk_net == __net))
-+#define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif, __net) \
-       (((__sk)->sk_hash == (__hash))                          &&      \
-        (inet_twsk(__sk)->tw_daddr     == (__saddr))           &&      \
-        (inet_twsk(__sk)->tw_rcv_saddr == (__daddr))           &&      \
-        ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&      \
--       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-+       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))) && \
-+       ((__sk)->sk_net == __net))
- #endif /* 64-bit arch */
+-      list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
++      list_for_each_safe(iter, iter2, &dlm->reco.resources) {
++              res = list_entry (iter, struct dlm_lock_resource, recovering);
+               if (res->owner == dead_node) {
+                       list_del_init(&res->recovering);
+                       spin_lock(&res->spinlock);
+@@ -2077,7 +2099,7 @@
+ static void dlm_revalidate_lvb(struct dlm_ctxt *dlm,
+                              struct dlm_lock_resource *res, u8 dead_node)
+ {
+-      struct list_head *queue;
++      struct list_head *iter, *queue;
+       struct dlm_lock *lock;
+       int blank_lvb = 0, local = 0;
+       int i;
+@@ -2099,7 +2121,8 @@
  
- /*
-@@ -349,7 +356,7 @@
-       __inet_lookup_established(struct inet_hashinfo *hashinfo,
-                                 const __be32 saddr, const __be16 sport,
-                                 const __be32 daddr, const u16 hnum,
--                                const int dif)
-+                                const int dif, struct net *net)
+       for (i=DLM_GRANTED_LIST; i<=DLM_CONVERTING_LIST; i++) {
+               queue = dlm_list_idx_to_ptr(res, i);
+-              list_for_each_entry(lock, queue, list) {
++              list_for_each(iter, queue) {
++                      lock = list_entry (iter, struct dlm_lock, list);
+                       if (lock->ml.node == search_node) {
+                               if (dlm_lvb_needs_invalidation(lock, local)) {
+                                       /* zero the lksb lvb and lockres lvb */
+@@ -2120,7 +2143,8 @@
+ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
+                               struct dlm_lock_resource *res, u8 dead_node)
  {
-       INET_ADDR_COOKIE(acookie, saddr, daddr)
-       const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
-@@ -358,19 +365,19 @@
-       /* Optimize here for direct hit, only listening connections can
-        * have wildcards anyways.
-        */
--      unsigned int hash = inet_ehashfn(daddr, hnum, saddr, sport);
-+      unsigned int hash = inet_ehashfn(net, daddr, hnum, saddr, sport);
-       struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
+-      struct dlm_lock *lock, *next;
++      struct list_head *iter, *tmpiter;
++      struct dlm_lock *lock;
+       unsigned int freed = 0;
  
-       prefetch(head->chain.first);
-       read_lock(&head->lock);
-       sk_for_each(sk, node, &head->chain) {
--              if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
-+              if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif, net))
-                       goto hit; /* You sunk my battleship! */
-       }
+       /* this node is the lockres master:
+@@ -2131,21 +2155,24 @@
+       assert_spin_locked(&res->spinlock);
  
-       /* Must check for a TIME_WAIT'er before going to listener hash. */
-       sk_for_each(sk, node, &head->twchain) {
--              if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
-+              if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif, net))
-                       goto hit;
+       /* TODO: check pending_asts, pending_basts here */
+-      list_for_each_entry_safe(lock, next, &res->granted, list) {
++      list_for_each_safe(iter, tmpiter, &res->granted) {
++              lock = list_entry (iter, struct dlm_lock, list);
+               if (lock->ml.node == dead_node) {
+                       list_del_init(&lock->list);
+                       dlm_lock_put(lock);
+                       freed++;
+               }
        }
-       sk = NULL;
-@@ -386,32 +393,32 @@
-       inet_lookup_established(struct inet_hashinfo *hashinfo,
-                               const __be32 saddr, const __be16 sport,
-                               const __be32 daddr, const __be16 dport,
--                              const int dif)
-+                              const int dif, struct net *net)
+-      list_for_each_entry_safe(lock, next, &res->converting, list) {
++      list_for_each_safe(iter, tmpiter, &res->converting) {
++              lock = list_entry (iter, struct dlm_lock, list);
+               if (lock->ml.node == dead_node) {
+                       list_del_init(&lock->list);
+                       dlm_lock_put(lock);
+                       freed++;
+               }
+       }
+-      list_for_each_entry_safe(lock, next, &res->blocked, list) {
++      list_for_each_safe(iter, tmpiter, &res->blocked) {
++              lock = list_entry (iter, struct dlm_lock, list);
+               if (lock->ml.node == dead_node) {
+                       list_del_init(&lock->list);
+                       dlm_lock_put(lock);
+diff -Nurb linux-2.6.22-590/fs/ocfs2/dlmglue.c linux-2.6.22-570/fs/ocfs2/dlmglue.c
+--- linux-2.6.22-590/fs/ocfs2/dlmglue.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/dlmglue.c        2008-01-23 19:16:04.000000000 -0500
+@@ -600,13 +600,15 @@
+ static void lockres_set_flags(struct ocfs2_lock_res *lockres,
+                             unsigned long newflags)
  {
-       return __inet_lookup_established(hashinfo, saddr, sport, daddr,
--                                       ntohs(dport), dif);
-+                                       ntohs(dport), dif, net);
- }
+-      struct ocfs2_mask_waiter *mw, *tmp;
++      struct list_head *pos, *tmp;
++      struct ocfs2_mask_waiter *mw;
  
- static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo,
-                                        const __be32 saddr, const __be16 sport,
-                                        const __be32 daddr, const __be16 dport,
--                                       const int dif)
-+                                       const int dif, struct net *net)
- {
-       u16 hnum = ntohs(dport);
-       struct sock *sk = __inet_lookup_established(hashinfo, saddr, sport, daddr,
--                                                  hnum, dif);
--      return sk ? : __inet_lookup_listener(hashinfo, daddr, hnum, dif);
-+                                                  hnum, dif, net);
-+      return sk ? : __inet_lookup_listener(hashinfo, daddr, hnum, dif, net);
- }
+       assert_spin_locked(&lockres->l_lock);
  
- static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
-                                      const __be32 saddr, const __be16 sport,
-                                      const __be32 daddr, const __be16 dport,
--                                     const int dif)
-+                                     const int dif, struct net *net)
- {
-       struct sock *sk;
+       lockres->l_flags = newflags;
  
-       local_bh_disable();
--      sk = __inet_lookup(hashinfo, saddr, sport, daddr, dport, dif);
-+      sk = __inet_lookup(hashinfo, saddr, sport, daddr, dport, dif, net);
-       local_bh_enable();
+-      list_for_each_entry_safe(mw, tmp, &lockres->l_mask_waiters, mw_item) {
++      list_for_each_safe(pos, tmp, &lockres->l_mask_waiters) {
++              mw = list_entry(pos, struct ocfs2_mask_waiter, mw_item);
+               if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal)
+                       continue;
  
-       return sk;
-diff -Nurb linux-2.6.22-570/include/net/inet_sock.h linux-2.6.22-590/include/net/inet_sock.h
---- linux-2.6.22-570/include/net/inet_sock.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/inet_sock.h   2008-01-02 13:56:37.000000000 -0500
-@@ -171,10 +171,12 @@
- extern u32 inet_ehash_secret;
- extern void build_ehash_secret(void);
+diff -Nurb linux-2.6.22-590/fs/ocfs2/endian.h linux-2.6.22-570/fs/ocfs2/endian.h
+--- linux-2.6.22-590/fs/ocfs2/endian.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/endian.h 2007-07-08 19:32:17.000000000 -0400
+@@ -32,11 +32,6 @@
+       *var = cpu_to_le32(le32_to_cpu(*var) + val);
+ }
  
--static inline unsigned int inet_ehashfn(const __be32 laddr, const __u16 lport,
-+static inline unsigned int inet_ehashfn(struct net *net,
-+                                      const __be32 laddr, const __u16 lport,
-                                       const __be32 faddr, const __be16 fport)
+-static inline void le64_add_cpu(__le64 *var, u64 val)
+-{
+-      *var = cpu_to_le64(le64_to_cpu(*var) + val);
+-}
+-
+ static inline void le32_and_cpu(__le32 *var, u32 val)
  {
--      return jhash_2words((__force __u32) laddr ^ (__force __u32) faddr,
-+      return jhash_2words((__force __u32) laddr ^ (__force __u32) faddr ^
-+                          (__force __u32) ((unsigned long)net),
-                           ((__u32) lport) << 16 | (__force __u32)fport,
-                           inet_ehash_secret);
- }
-@@ -187,7 +189,7 @@
-       const __be32 faddr = inet->daddr;
-       const __be16 fport = inet->dport;
+       *var = cpu_to_le32(le32_to_cpu(*var) & val);
+diff -Nurb linux-2.6.22-590/fs/ocfs2/extent_map.c linux-2.6.22-570/fs/ocfs2/extent_map.c
+--- linux-2.6.22-590/fs/ocfs2/extent_map.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/extent_map.c     2007-07-08 19:32:17.000000000 -0400
+@@ -109,14 +109,17 @@
+  */
+ void ocfs2_extent_map_trunc(struct inode *inode, unsigned int cpos)
+ {
+-      struct ocfs2_extent_map_item *emi, *n;
++      struct list_head *p, *n;
++      struct ocfs2_extent_map_item *emi;
+       struct ocfs2_inode_info *oi = OCFS2_I(inode);
+       struct ocfs2_extent_map *em = &oi->ip_extent_map;
+       LIST_HEAD(tmp_list);
+       unsigned int range;
  
--      return inet_ehashfn(laddr, lport, faddr, fport);
-+      return inet_ehashfn(sk->sk_net, laddr, lport, faddr, fport);
- }
+       spin_lock(&oi->ip_lock);
+-      list_for_each_entry_safe(emi, n, &em->em_list, ei_list) {
++      list_for_each_safe(p, n, &em->em_list) {
++              emi = list_entry(p, struct ocfs2_extent_map_item, ei_list);
++
+               if (emi->ei_cpos >= cpos) {
+                       /* Full truncate of this record. */
+                       list_move(&emi->ei_list, &tmp_list);
+@@ -133,7 +136,8 @@
+       }
+       spin_unlock(&oi->ip_lock);
  
- #endif        /* _INET_SOCK_H */
-diff -Nurb linux-2.6.22-570/include/net/inet_timewait_sock.h linux-2.6.22-590/include/net/inet_timewait_sock.h
---- linux-2.6.22-570/include/net/inet_timewait_sock.h  2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/include/net/inet_timewait_sock.h  2008-01-02 13:56:37.000000000 -0500
-@@ -115,6 +115,7 @@
- #define tw_refcnt             __tw_common.skc_refcnt
- #define tw_hash                       __tw_common.skc_hash
- #define tw_prot                       __tw_common.skc_prot
-+#define tw_net                        __tw_common.skc_net
- #define tw_xid                __tw_common.skc_xid
- #define tw_vx_info            __tw_common.skc_vx_info
- #define tw_nid                __tw_common.skc_nid
-diff -Nurb linux-2.6.22-570/include/net/inetpeer.h linux-2.6.22-590/include/net/inetpeer.h
---- linux-2.6.22-570/include/net/inetpeer.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/inetpeer.h    2008-01-02 13:56:37.000000000 -0500
-@@ -15,6 +15,8 @@
- #include <linux/spinlock.h>
- #include <asm/atomic.h>
+-      list_for_each_entry_safe(emi, n, &tmp_list, ei_list) {
++      list_for_each_safe(p, n, &tmp_list) {
++              emi = list_entry(p, struct ocfs2_extent_map_item, ei_list);
+               list_del(&emi->ei_list);
+               kfree(emi);
+       }
+@@ -373,6 +377,37 @@
+       return ret;
+ }
  
-+struct net;
++/*
++ * Return the index of the extent record which contains cluster #v_cluster.
++ * -1 is returned if it was not found.
++ *
++ * Should work fine on interior and exterior nodes.
++ */
++static int ocfs2_search_extent_list(struct ocfs2_extent_list *el,
++                                  u32 v_cluster)
++{
++      int ret = -1;
++      int i;
++      struct ocfs2_extent_rec *rec;
++      u32 rec_end, rec_start, clusters;
 +
- struct inet_peer
- {
-       /* group together avl_left,avl_right,v4daddr to speedup lookups */
-@@ -22,7 +24,11 @@
-       __be32                  v4daddr;        /* peer's address */
-       __u16                   avl_height;
-       __u16                   ip_id_count;    /* IP ID for the next packet */
--      struct inet_peer        *unused_next, **unused_prevp;
-+      union {
-+              struct inet_peer        *unused_next;
-+              struct net              *net;
-+      } u;
-+      struct inet_peer        **unused_prevp;
-       __u32                   dtime;          /* the time of last use of not
-                                                * referenced entries */
-       atomic_t                refcnt;
-@@ -34,7 +40,7 @@
- void                  inet_initpeers(void) __init;
- /* can be called with or without local BH being disabled */
--struct inet_peer      *inet_getpeer(__be32 daddr, int create);
-+struct inet_peer      *inet_getpeer(struct net *net, __be32 daddr, int create);
++      for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
++              rec = &el->l_recs[i];
++
++              rec_start = le32_to_cpu(rec->e_cpos);
++              clusters = ocfs2_rec_clusters(el, rec);
++
++              rec_end = rec_start + clusters;
++
++              if (v_cluster >= rec_start && v_cluster < rec_end) {
++                      ret = i;
++                      break;
++              }
++      }
++
++      return ret;
++}
++
+ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
+                      u32 *p_cluster, u32 *num_clusters,
+                      unsigned int *extent_flags)
+diff -Nurb linux-2.6.22-590/fs/ocfs2/file.c linux-2.6.22-570/fs/ocfs2/file.c
+--- linux-2.6.22-590/fs/ocfs2/file.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/file.c   2008-01-23 19:16:04.000000000 -0500
+@@ -326,6 +326,9 @@
+                  (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                  (unsigned long long)new_i_size);
  
- /* can be called from BH context or outside */
- extern void inet_putpeer(struct inet_peer *p);
-diff -Nurb linux-2.6.22-570/include/net/ip.h linux-2.6.22-590/include/net/ip.h
---- linux-2.6.22-570/include/net/ip.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/ip.h  2008-01-02 13:56:37.000000000 -0500
-@@ -149,13 +149,6 @@
- void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
-                  unsigned int len); 
++      unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1);
++      truncate_inode_pages(inode->i_mapping, new_i_size);
++
+       fe = (struct ocfs2_dinode *) di_bh->b_data;
+       if (!OCFS2_IS_VALID_DINODE(fe)) {
+               OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
+@@ -360,23 +363,16 @@
+       if (new_i_size == le64_to_cpu(fe->i_size))
+               goto bail;
  
--struct ipv4_config
--{
--      int     log_martians;
--      int     no_pmtu_disc;
--};
+-      down_write(&OCFS2_I(inode)->ip_alloc_sem);
 -
--extern struct ipv4_config ipv4_config;
- DECLARE_SNMP_STAT(struct ipstats_mib, ip_statistics);
- #define IP_INC_STATS(field)           SNMP_INC_STATS(ip_statistics, field)
- #define IP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(ip_statistics, field)
-@@ -171,27 +164,6 @@
- extern int snmp_mib_init(void *ptr[2], size_t mibsize, size_t mibalign);
- extern void snmp_mib_free(void *ptr[2]);
--extern int sysctl_local_port_range[2];
--extern int sysctl_ip_default_ttl;
--extern int sysctl_ip_nonlocal_bind;
+       /* This forces other nodes to sync and drop their pages. Do
+        * this even if we have a truncate without allocation change -
+        * ocfs2 cluster sizes can be much greater than page size, so
+        * we have to truncate them anyway.  */
+       status = ocfs2_data_lock(inode, 1);
+       if (status < 0) {
+-              up_write(&OCFS2_I(inode)->ip_alloc_sem);
 -
--/* From ip_fragment.c */
--extern int sysctl_ipfrag_high_thresh; 
--extern int sysctl_ipfrag_low_thresh;
--extern int sysctl_ipfrag_time;
--extern int sysctl_ipfrag_secret_interval;
--extern int sysctl_ipfrag_max_dist;
+               mlog_errno(status);
+               goto bail;
+       }
+-      unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1);
+-      truncate_inode_pages(inode->i_mapping, new_i_size);
 -
--/* From inetpeer.c */
--extern int inet_peer_threshold;
--extern int inet_peer_minttl;
--extern int inet_peer_maxttl;
--extern int inet_peer_gc_mintime;
--extern int inet_peer_gc_maxtime;
+       /* alright, we're going to need to do a full blown alloc size
+        * change. Orphan the inode so that recovery can complete the
+        * truncate if necessary. This does the task of marking
+@@ -403,8 +399,6 @@
+ bail_unlock_data:
+       ocfs2_data_unlock(inode, 1);
+-      up_write(&OCFS2_I(inode)->ip_alloc_sem);
 -
--/* From ip_output.c */
--extern int sysctl_ip_dynaddr;
+ bail:
+       mlog_exit(status);
+@@ -425,7 +419,6 @@
+                              struct inode *inode,
+                              u32 *logical_offset,
+                              u32 clusters_to_add,
+-                             int mark_unwritten,
+                              struct buffer_head *fe_bh,
+                              handle_t *handle,
+                              struct ocfs2_alloc_context *data_ac,
+@@ -438,13 +431,9 @@
+       enum ocfs2_alloc_restarted reason = RESTART_NONE;
+       u32 bit_off, num_bits;
+       u64 block;
+-      u8 flags = 0;
+       BUG_ON(!clusters_to_add);
+-      if (mark_unwritten)
+-              flags = OCFS2_EXT_UNWRITTEN;
 -
- extern void ipfrag_init(void);
+       free_extents = ocfs2_num_free_extents(osb, inode, fe);
+       if (free_extents < 0) {
+               status = free_extents;
+@@ -494,7 +483,7 @@
+            num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
+       status = ocfs2_insert_extent(osb, handle, inode, fe_bh,
+                                    *logical_offset, block, num_bits,
+-                                   flags, meta_ac);
++                                   meta_ac);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+@@ -527,28 +516,25 @@
+  * For a given allocation, determine which allocators will need to be
+  * accessed, and lock them, reserving the appropriate number of bits.
+  *
+- * Sparse file systems call this from ocfs2_write_begin_nolock()
+- * and ocfs2_allocate_unwritten_extents().
+- *
+- * File systems which don't support holes call this from
+- * ocfs2_extend_allocation().
++ * Called from ocfs2_extend_allocation() for file systems which don't
++ * support holes, and from ocfs2_write() for file systems which
++ * understand sparse inodes.
+  */
+ int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
+-                        u32 clusters_to_add, u32 extents_to_split,
++                        u32 clusters_to_add,
+                         struct ocfs2_alloc_context **data_ac,
+                         struct ocfs2_alloc_context **meta_ac)
+ {
+       int ret, num_free_extents;
+-      unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
  
- #ifdef CONFIG_INET
-@@ -332,8 +304,6 @@
- };
+       *meta_ac = NULL;
+       *data_ac = NULL;
  
- struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user);
--extern int ip_frag_nqueues;
--extern atomic_t ip_frag_mem;
+       mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, "
+-           "clusters_to_add = %u, extents_to_split = %u\n",
++           "clusters_to_add = %u\n",
+            (unsigned long long)OCFS2_I(inode)->ip_blkno, i_size_read(inode),
+-           le32_to_cpu(di->i_clusters), clusters_to_add, extents_to_split);
++           le32_to_cpu(di->i_clusters), clusters_to_add);
  
- /*
-  *    Functions provided by ip_forward.c
-@@ -392,5 +362,6 @@
- #endif
+       num_free_extents = ocfs2_num_free_extents(osb, inode, di);
+       if (num_free_extents < 0) {
+@@ -566,12 +552,9 @@
+        *
+        * Most of the time we'll only be seeing this 1 cluster at a time
+        * anyway.
+-       *
+-       * Always lock for any unwritten extents - we might want to
+-       * remove blocks for a merge.
+        */
+       if (!num_free_extents ||
+-          (ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed)) {
++          (ocfs2_sparse_alloc(osb) && num_free_extents < clusters_to_add)) {
+               ret = ocfs2_reserve_new_metadata(osb, di, meta_ac);
+               if (ret < 0) {
+                       if (ret != -ENOSPC)
+@@ -602,13 +585,14 @@
+       return ret;
+ }
  
- extern struct ctl_table ipv4_table[];
-+extern struct ctl_table multi_ipv4_table[];
+-static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
+-                                   u32 clusters_to_add, int mark_unwritten)
++static int ocfs2_extend_allocation(struct inode *inode,
++                                 u32 clusters_to_add)
+ {
+       int status = 0;
+       int restart_func = 0;
++      int drop_alloc_sem = 0;
+       int credits;
+-      u32 prev_clusters;
++      u32 prev_clusters, logical_start;
+       struct buffer_head *bh = NULL;
+       struct ocfs2_dinode *fe = NULL;
+       handle_t *handle = NULL;
+@@ -623,7 +607,7 @@
+        * This function only exists for file systems which don't
+        * support holes.
+        */
+-      BUG_ON(mark_unwritten && !ocfs2_sparse_alloc(osb));
++      BUG_ON(ocfs2_sparse_alloc(osb));
  
- #endif        /* _IP_H */
-diff -Nurb linux-2.6.22-570/include/net/ip_fib.h linux-2.6.22-590/include/net/ip_fib.h
---- linux-2.6.22-570/include/net/ip_fib.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/ip_fib.h      2008-01-02 13:56:37.000000000 -0500
-@@ -39,7 +39,6 @@
-       int                     fc_mx_len;
-       int                     fc_mp_len;
-       u32                     fc_flow;
--      u32                     fc_mp_alg;
-       u32                     fc_nlflags;
-       struct nl_info          fc_nlinfo;
-  };
-@@ -89,6 +88,7 @@
- #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-       u32                     fib_mp_alg;
- #endif
-+      struct net *            fib_net;
-       struct fib_nh           fib_nh[0];
- #define fib_dev               fib_nh[0].nh_dev
- };
-@@ -103,10 +103,6 @@
-       unsigned char   nh_sel;
-       unsigned char   type;
-       unsigned char   scope;
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      __be32          network;
--      __be32          netmask;
--#endif
-       struct fib_info *fi;
- #ifdef CONFIG_IP_MULTIPLE_TABLES
-       struct fib_rule *r;
-@@ -145,14 +141,6 @@
- #define FIB_RES_DEV(res)              (FIB_RES_NH(res).nh_dev)
- #define FIB_RES_OIF(res)              (FIB_RES_NH(res).nh_oif)
+       status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &bh,
+                                 OCFS2_BH_CACHED, inode);
+@@ -639,10 +623,19 @@
+               goto leave;
+       }
++      logical_start = OCFS2_I(inode)->ip_clusters;
++
+ restart_all:
+       BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters);
  
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--#define FIB_RES_NETWORK(res)          ((res).network)
--#define FIB_RES_NETMASK(res)          ((res).netmask)
--#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
--#define FIB_RES_NETWORK(res)          (0)
--#define FIB_RES_NETMASK(res)          (0)
--#endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */
--
- struct fib_table {
-       struct hlist_node tb_hlist;
-       u32             tb_id;
-@@ -171,43 +159,43 @@
+-      status = ocfs2_lock_allocators(inode, fe, clusters_to_add, 0, &data_ac,
++      /* blocks peope in read/write from reading our allocation
++       * until we're done changing it. We depend on i_mutex to block
++       * other extend/truncate calls while we're here. Ordering wrt
++       * start_trans is important here -- always do it before! */
++      down_write(&OCFS2_I(inode)->ip_alloc_sem);
++      drop_alloc_sem = 1;
++
++      status = ocfs2_lock_allocators(inode, fe, clusters_to_add, &data_ac,
+                                      &meta_ac);
+       if (status) {
+               mlog_errno(status);
+@@ -675,7 +668,6 @@
+                                           inode,
+                                           &logical_start,
+                                           clusters_to_add,
+-                                          mark_unwritten,
+                                           bh,
+                                           handle,
+                                           data_ac,
+@@ -728,6 +720,10 @@
+            OCFS2_I(inode)->ip_clusters, i_size_read(inode));
  
- #ifndef CONFIG_IP_MULTIPLE_TABLES
+ leave:
++      if (drop_alloc_sem) {
++              up_write(&OCFS2_I(inode)->ip_alloc_sem);
++              drop_alloc_sem = 0;
++      }
+       if (handle) {
+               ocfs2_commit_trans(osb, handle);
+               handle = NULL;
+@@ -753,25 +749,6 @@
+       return status;
+ }
  
--extern struct fib_table *ip_fib_local_table;
--extern struct fib_table *ip_fib_main_table;
+-static int ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
+-                                 u32 clusters_to_add, int mark_unwritten)
+-{
+-      int ret;
 -
--static inline struct fib_table *fib_get_table(u32 id)
-+static inline struct fib_table *fib_get_table(struct net *net, u32 id)
- {
-       if (id != RT_TABLE_LOCAL)
--              return ip_fib_main_table;
--      return ip_fib_local_table;
-+              return net->ip_fib_main_table;
-+      return net->ip_fib_local_table;
- }
+-      /*
+-       * The alloc sem blocks peope in read/write from reading our
+-       * allocation until we're done changing it. We depend on
+-       * i_mutex to block other extend/truncate calls while we're
+-       * here.
+-       */
+-      down_write(&OCFS2_I(inode)->ip_alloc_sem);
+-      ret = __ocfs2_extend_allocation(inode, logical_start, clusters_to_add,
+-                                      mark_unwritten);
+-      up_write(&OCFS2_I(inode)->ip_alloc_sem);
+-
+-      return ret;
+-}
+-
+ /* Some parts of this taken from generic_cont_expand, which turned out
+  * to be too fragile to do exactly what we need without us having to
+  * worry about recursive locking in ->prepare_write() and
+@@ -913,9 +890,7 @@
+       }
  
--static inline struct fib_table *fib_new_table(u32 id)
-+static inline struct fib_table *fib_new_table(struct net *net, u32 id)
- {
--      return fib_get_table(id);
-+      return fib_get_table(net, id);
- }
+       if (clusters_to_add) {
+-              ret = ocfs2_extend_allocation(inode,
+-                                            OCFS2_I(inode)->ip_clusters,
+-                                            clusters_to_add, 0);
++              ret = ocfs2_extend_allocation(inode, clusters_to_add);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out_unlock;
+@@ -1022,13 +997,6 @@
+               goto bail_unlock;
+       }
  
- static inline int fib_lookup(const struct flowi *flp, struct fib_result *res)
- {
--      if (ip_fib_local_table->tb_lookup(ip_fib_local_table, flp, res) &&
--          ip_fib_main_table->tb_lookup(ip_fib_main_table, flp, res))
-+      struct net *net = flp->fl_net;
-+      struct fib_table *local_table = net->ip_fib_local_table;
-+      struct fib_table *main_table = net->ip_fib_main_table;
-+      if (local_table->tb_lookup(local_table, flp, res) &&
-+          main_table->tb_lookup(main_table, flp, res))
-               return -ENETUNREACH;
-       return 0;
+-      /*
+-       * This will intentionally not wind up calling vmtruncate(),
+-       * since all the work for a size change has been done above.
+-       * Otherwise, we could get into problems with truncate as
+-       * ip_alloc_sem is used there to protect against i_size
+-       * changes.
+-       */
+       status = inode_setattr(inode, attr);
+       if (status < 0) {
+               mlog_errno(status);
+@@ -1104,16 +1072,17 @@
+       return ret;
  }
  
- static inline void fib_select_default(const struct flowi *flp, struct fib_result *res)
+-static int __ocfs2_write_remove_suid(struct inode *inode,
+-                                   struct buffer_head *bh)
++static int ocfs2_write_remove_suid(struct inode *inode)
  {
-+      struct net *net = flp->fl_net;
-+      struct fib_table *main_table = net->ip_fib_main_table;
-       if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
--              ip_fib_main_table->tb_select_default(ip_fib_main_table, flp, res);
-+              main_table->tb_select_default(main_table, flp, res);
- }
- #else /* CONFIG_IP_MULTIPLE_TABLES */
--#define ip_fib_local_table fib_get_table(RT_TABLE_LOCAL)
--#define ip_fib_main_table fib_get_table(RT_TABLE_MAIN)
- extern int fib_lookup(struct flowi *flp, struct fib_result *res);
--extern struct fib_table *fib_new_table(u32 id);
--extern struct fib_table *fib_get_table(u32 id);
-+extern struct fib_table *fib_new_table(struct net *net, u32 id);
-+extern struct fib_table *fib_get_table(struct net *net, u32 id);
- extern void fib_select_default(const struct flowi *flp, struct fib_result *res);
- #endif /* CONFIG_IP_MULTIPLE_TABLES */
-@@ -223,15 +211,17 @@
+       int ret;
++      struct buffer_head *bh = NULL;
++      struct ocfs2_inode_info *oi = OCFS2_I(inode);
+       handle_t *handle;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_dinode *di;
  
- /* Exported by fib_semantics.c */
- extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
--extern int fib_sync_down(__be32 local, struct net_device *dev, int force);
-+extern int fib_sync_down(struct net *net, __be32 local, struct net_device *dev, int force);
- extern int fib_sync_up(struct net_device *dev);
- extern __be32  __fib_res_prefsrc(struct fib_result *res);
+       mlog_entry("(Inode %llu, mode 0%o)\n",
+-                 (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode);
++                 (unsigned long long)oi->ip_blkno, inode->i_mode);
  
- /* Exported by fib_hash.c */
- extern struct fib_table *fib_hash_init(u32 id);
-+extern void fib_hash_exit(struct fib_table *tb);
+       handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+       if (handle == NULL) {
+@@ -1122,11 +1091,17 @@
+               goto out;
+       }
  
- #ifdef CONFIG_IP_MULTIPLE_TABLES
--extern void __init fib4_rules_init(void);
-+extern void fib4_rules_init(struct net * net);
-+extern void fib4_rules_exit(struct net * net);
++      ret = ocfs2_read_block(osb, oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
++      if (ret < 0) {
++              mlog_errno(ret);
++              goto out_trans;
++      }
++
+       ret = ocfs2_journal_access(handle, inode, bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret < 0) {
+               mlog_errno(ret);
+-              goto out_trans;
++              goto out_bh;
+       }
  
- #ifdef CONFIG_NET_CLS_ROUTE
- extern u32 fib_rules_tclass(struct fib_result *res);
-@@ -274,8 +264,11 @@
+       inode->i_mode &= ~S_ISUID;
+@@ -1139,7 +1114,8 @@
+       ret = ocfs2_journal_dirty(handle, bh);
+       if (ret < 0)
+               mlog_errno(ret);
+-
++out_bh:
++      brelse(bh);
+ out_trans:
+       ocfs2_commit_trans(osb, handle);
+ out:
+@@ -1185,211 +1161,6 @@
+       return ret;
  }
  
- #ifdef CONFIG_PROC_FS
--extern int  fib_proc_init(void);
--extern void fib_proc_exit(void);
-+extern int  fib_proc_init(struct net * net);
-+extern void fib_proc_exit(struct net * net);
- #endif
-+extern int  fib_info_init(struct net *net);
-+extern void fib_info_exit(struct net *net);
-+
- #endif  /* _NET_FIB_H */
-diff -Nurb linux-2.6.22-570/include/net/ip_mp_alg.h linux-2.6.22-590/include/net/ip_mp_alg.h
---- linux-2.6.22-570/include/net/ip_mp_alg.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/ip_mp_alg.h   1969-12-31 19:00:00.000000000 -0500
-@@ -1,96 +0,0 @@
--/* ip_mp_alg.h: IPV4 multipath algorithm support.
-- *
-- * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
-- * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
-- */
+-static int ocfs2_write_remove_suid(struct inode *inode)
+-{
+-      int ret;
+-      struct buffer_head *bh = NULL;
+-      struct ocfs2_inode_info *oi = OCFS2_I(inode);
+-
+-      ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+-                             oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
+-      if (ret < 0) {
+-              mlog_errno(ret);
+-              goto out;
+-      }
 -
--#ifndef _NET_IP_MP_ALG_H
--#define _NET_IP_MP_ALG_H
+-      ret =  __ocfs2_write_remove_suid(inode, bh);
+-out:
+-      brelse(bh);
+-      return ret;
+-}
 -
--#include <linux/ip_mp_alg.h>
--#include <net/flow.h>
--#include <net/route.h>
+-/*
+- * Allocate enough extents to cover the region starting at byte offset
+- * start for len bytes. Existing extents are skipped, any extents
+- * added are marked as "unwritten".
+- */
+-static int ocfs2_allocate_unwritten_extents(struct inode *inode,
+-                                          u64 start, u64 len)
+-{
+-      int ret;
+-      u32 cpos, phys_cpos, clusters, alloc_size;
 -
--struct fib_nh;
+-      /*
+-       * We consider both start and len to be inclusive.
+-       */
+-      cpos = start >> OCFS2_SB(inode->i_sb)->s_clustersize_bits;
+-      clusters = ocfs2_clusters_for_bytes(inode->i_sb, start + len);
+-      clusters -= cpos;
 -
--struct ip_mp_alg_ops {
--      void    (*mp_alg_select_route)(const struct flowi *flp,
--                                     struct rtable *rth, struct rtable **rp);
--      void    (*mp_alg_flush)(void);
--      void    (*mp_alg_set_nhinfo)(__be32 network, __be32 netmask,
--                                   unsigned char prefixlen,
--                                   const struct fib_nh *nh);
--      void    (*mp_alg_remove)(struct rtable *rth);
--};
+-      while (clusters) {
+-              ret = ocfs2_get_clusters(inode, cpos, &phys_cpos,
+-                                       &alloc_size, NULL);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
 -
--extern int multipath_alg_register(struct ip_mp_alg_ops *, enum ip_mp_alg);
--extern void multipath_alg_unregister(struct ip_mp_alg_ops *, enum ip_mp_alg);
+-              /*
+-               * Hole or existing extent len can be arbitrary, so
+-               * cap it to our own allocation request.
+-               */
+-              if (alloc_size > clusters)
+-                      alloc_size = clusters;
 -
--extern struct ip_mp_alg_ops *ip_mp_alg_table[];
+-              if (phys_cpos) {
+-                      /*
+-                       * We already have an allocation at this
+-                       * region so we can safely skip it.
+-                       */
+-                      goto next;
+-              }
 -
--static inline int multipath_select_route(const struct flowi *flp,
--                                       struct rtable *rth,
--                                       struct rtable **rp)
--{
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
+-              ret = __ocfs2_extend_allocation(inode, cpos, alloc_size, 1);
+-              if (ret) {
+-                      if (ret != -ENOSPC)
+-                              mlog_errno(ret);
+-                      goto out;
+-              }
 -
--      /* mp_alg_select_route _MUST_ be implemented */
--      if (ops && (rth->u.dst.flags & DST_BALANCED)) {
--              ops->mp_alg_select_route(flp, rth, rp);
--              return 1;
+-next:
+-              cpos += alloc_size;
+-              clusters -= alloc_size;
 -      }
--#endif
--      return 0;
+-
+-      ret = 0;
+-out:
+-      return ret;
 -}
 -
--static inline void multipath_flush(void)
+-/*
+- * Parts of this function taken from xfs_change_file_space()
+- */
+-int ocfs2_change_file_space(struct file *file, unsigned int cmd,
+-                          struct ocfs2_space_resv *sr)
 -{
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      int i;
+-      int ret;
+-      s64 llen;
+-      struct inode *inode = file->f_path.dentry->d_inode;
+-      struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+-      struct buffer_head *di_bh = NULL;
+-      handle_t *handle;
+-      unsigned long long max_off = ocfs2_max_file_offset(inode->i_sb->s_blocksize_bits);
+-
+-      if (!ocfs2_writes_unwritten_extents(osb))
+-              return -ENOTTY;
+-
+-      if (!S_ISREG(inode->i_mode))
+-              return -EINVAL;
 -
--      for (i = IP_MP_ALG_NONE; i <= IP_MP_ALG_MAX; i++) {
--              struct ip_mp_alg_ops *ops = ip_mp_alg_table[i];
+-      if (!(file->f_mode & FMODE_WRITE))
+-              return -EBADF;
 -
--              if (ops && ops->mp_alg_flush)
--                      ops->mp_alg_flush();
+-      if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
+-              return -EROFS;
+-
+-      mutex_lock(&inode->i_mutex);
+-
+-      /*
+-       * This prevents concurrent writes on other nodes
+-       */
+-      ret = ocfs2_rw_lock(inode, 1);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out;
 -      }
--#endif
--}
 -
--static inline void multipath_set_nhinfo(struct rtable *rth,
--                                      __be32 network, __be32 netmask,
--                                      unsigned char prefixlen,
--                                      const struct fib_nh *nh)
--{
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
+-      ret = ocfs2_meta_lock(inode, &di_bh, 1);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out_rw_unlock;
+-      }
 -
--      if (ops && ops->mp_alg_set_nhinfo)
--              ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh);
--#endif
--}
+-      if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
+-              ret = -EPERM;
+-              goto out_meta_unlock;
+-      }
 -
--static inline void multipath_remove(struct rtable *rth)
--{
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
+-      switch (sr->l_whence) {
+-      case 0: /*SEEK_SET*/
+-              break;
+-      case 1: /*SEEK_CUR*/
+-              sr->l_start += file->f_pos;
+-              break;
+-      case 2: /*SEEK_END*/
+-              sr->l_start += i_size_read(inode);
+-              break;
+-      default:
+-              ret = -EINVAL;
+-              goto out_meta_unlock;
+-      }
+-      sr->l_whence = 0;
 -
--      if (ops && ops->mp_alg_remove &&
--          (rth->u.dst.flags & DST_BALANCED))
--              ops->mp_alg_remove(rth);
--#endif
--}
+-      llen = sr->l_len > 0 ? sr->l_len - 1 : sr->l_len;
 -
--static inline int multipath_comparekeys(const struct flowi *flp1,
--                                      const struct flowi *flp2)
--{
--      return flp1->fl4_dst == flp2->fl4_dst &&
--              flp1->fl4_src == flp2->fl4_src &&
--              flp1->oif == flp2->oif &&
--              flp1->mark == flp2->mark &&
--              !((flp1->fl4_tos ^ flp2->fl4_tos) &
--                (IPTOS_RT_MASK | RTO_ONLINK));
+-      if (sr->l_start < 0
+-          || sr->l_start > max_off
+-          || (sr->l_start + llen) < 0
+-          || (sr->l_start + llen) > max_off) {
+-              ret = -EINVAL;
+-              goto out_meta_unlock;
+-      }
+-
+-      if (cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) {
+-              if (sr->l_len <= 0) {
+-                      ret = -EINVAL;
+-                      goto out_meta_unlock;
+-              }
+-      }
+-
+-      if (should_remove_suid(file->f_path.dentry)) {
+-              ret = __ocfs2_write_remove_suid(inode, di_bh);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out_meta_unlock;
+-              }
+-      }
+-
+-      down_write(&OCFS2_I(inode)->ip_alloc_sem);
+-      /*
+-       * This takes unsigned offsets, but the signed ones we pass
+-       * have been checked against overflow above.
+-       */
+-      ret = ocfs2_allocate_unwritten_extents(inode, sr->l_start, sr->l_len);
+-      up_write(&OCFS2_I(inode)->ip_alloc_sem);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out_meta_unlock;
+-      }
+-
+-      /*
+-       * We update c/mtime for these changes
+-       */
+-      handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+-      if (IS_ERR(handle)) {
+-              ret = PTR_ERR(handle);
+-              mlog_errno(ret);
+-              goto out_meta_unlock;
+-      }
+-
+-      inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+-      ret = ocfs2_mark_inode_dirty(handle, inode, di_bh);
+-      if (ret < 0)
+-              mlog_errno(ret);
+-
+-      ocfs2_commit_trans(osb, handle);
+-
+-out_meta_unlock:
+-      brelse(di_bh);
+-      ocfs2_meta_unlock(inode, 1);
+-out_rw_unlock:
+-      ocfs2_rw_unlock(inode, 1);
+-
+-      mutex_unlock(&inode->i_mutex);
+-out:
+-      return ret;
 -}
 -
--#endif /* _NET_IP_MP_ALG_H */
-diff -Nurb linux-2.6.22-570/include/net/llc_conn.h linux-2.6.22-590/include/net/llc_conn.h
---- linux-2.6.22-570/include/net/llc_conn.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/llc_conn.h    2008-01-02 13:56:37.000000000 -0500
-@@ -93,7 +93,7 @@
-       return skb->cb[sizeof(skb->cb) - 1];
+ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
+                                        loff_t *ppos,
+                                        size_t count,
+@@ -1560,16 +1331,15 @@
+       *basep = base;
  }
  
--extern struct sock *llc_sk_alloc(int family, gfp_t priority,
-+extern struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority,
-                                struct proto *prot);
- extern void llc_sk_free(struct sock *sk);
-diff -Nurb linux-2.6.22-570/include/net/mip6.h linux-2.6.22-590/include/net/mip6.h
---- linux-2.6.22-570/include/net/mip6.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/mip6.h        2008-01-02 13:56:37.000000000 -0500
-@@ -54,8 +54,4 @@
- #define IP6_MH_TYPE_BERROR    7   /* Binding Error */
- #define IP6_MH_TYPE_MAX               IP6_MH_TYPE_BERROR
--extern int mip6_init(void);
--extern void mip6_fini(void);
--extern int mip6_mh_filter(struct sock *sk, struct sk_buff *skb);
--
- #endif
-diff -Nurb linux-2.6.22-570/include/net/neighbour.h linux-2.6.22-590/include/net/neighbour.h
---- linux-2.6.22-570/include/net/neighbour.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/neighbour.h   2008-01-02 13:56:37.000000000 -0500
-@@ -34,6 +34,7 @@
- struct neigh_parms
- {
-+      struct net *net;
-       struct net_device *dev;
-       struct neigh_parms *next;
-       int     (*neigh_setup)(struct neighbour *);
-@@ -126,6 +127,7 @@
- struct pneigh_entry
- {
-       struct pneigh_entry     *next;
-+      struct net              *net;
-       struct net_device               *dev;
-       u8                      flags;
-       u8                      key[0];
-@@ -187,6 +189,7 @@
-                                            const void *pkey,
-                                            struct net_device *dev);
- extern struct neighbour *     neigh_lookup_nodev(struct neigh_table *tbl,
-+                                                 struct net *net,
-                                                  const void *pkey);
- extern struct neighbour *     neigh_create(struct neigh_table *tbl,
-                                            const void *pkey,
-@@ -205,21 +208,24 @@
-                                               struct net_device *dev);
- extern struct neigh_parms     *neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl);
-+extern struct neigh_parms     *neigh_parms_alloc_default(struct neigh_table *tbl, struct net *net);
- extern void                   neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms);
- extern void                   neigh_parms_destroy(struct neigh_parms *parms);
- extern unsigned long          neigh_rand_reach_time(unsigned long base);
- extern void                   pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
-                                              struct sk_buff *skb);
--extern struct pneigh_entry    *pneigh_lookup(struct neigh_table *tbl, const void *key, struct net_device *dev, int creat);
--extern int                    pneigh_delete(struct neigh_table *tbl, const void *key, struct net_device *dev);
-+extern struct pneigh_entry    *pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev, int creat);
-+extern int                    pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev);
- extern void neigh_app_ns(struct neighbour *n);
- extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie);
- extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *));
- extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *));
--struct neigh_seq_state {
-+struct neigh_seq_state
-+{
-+      struct net *net;
-       struct neigh_table *tbl;
-       void *(*neigh_sub_iter)(struct neigh_seq_state *state,
-                               struct neighbour *n, loff_t *pos);
-diff -Nurb linux-2.6.22-570/include/net/net_namespace.h linux-2.6.22-590/include/net/net_namespace.h
---- linux-2.6.22-570/include/net/net_namespace.h       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/include/net/net_namespace.h       2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,236 @@
-+/*
-+ * Operations on the network namespace
-+ */
-+#ifndef __NET_NET_NAMESPACE_H
-+#define __NET_NET_NAMESPACE_H
-+
-+#include <asm/atomic.h>
-+#include <linux/workqueue.h>
-+#include <linux/list.h>
-+#include <linux/proc_fs.h>
-+#include <linux/sysctl.h>
-+#include <linux/netdevice.h>
-+#include <linux/timer.h>
-+
-+struct sock;
-+struct xt_af_pernet;
-+struct ipv4_devconf;
-+struct neigh_parms;
-+struct inet_peer;
-+struct xt_table;
-+struct net {
-+      atomic_t count;         /* To decided when the network namespace
-+                               * should go
-+                               */
-+      atomic_t use_count;     /* For references we destroy on demand */
-+      struct list_head list;  /* list of network namespace structures */
-+      struct work_struct work;        /* work struct for freeing */
-+
-+#ifdef CONFIG_PROC_FS
-+      struct proc_dir_entry *proc_net;
-+      struct proc_dir_entry *proc_net_stat;
-+      struct proc_dir_entry proc_net_root;
-+# ifdef CONFIG_NETFILTER
-+      struct proc_dir_entry *proc_net_netfilter;
-+# endif
-+#endif
-+#ifdef CONFIG_SYSCTL
-+      struct ctl_table_header net_table_header;
-+#endif
-+      struct net_device       loopback_dev;           /* The loopback */
-+      struct list_head        dev_base_head;          /* All devices */
-+
-+      struct hlist_head       *dev_name_head;
-+      struct hlist_head       *dev_index_head;
-+
-+      struct sock *           rtnl;   /* rtnetlink socket */
-+
-+
-+      /* core netfilter */
-+      struct xt_af_pernet *   xtn;
-+
-+      /* core fib_rules */
-+      struct list_head        rules_ops;
-+      spinlock_t              rules_mod_lock;
-+
-+#ifdef CONFIG_XFRM
-+      u32                     sysctl_xfrm_aevent_etime;
-+      u32                     sysctl_xfrm_aevent_rseqth;
-+      int                     sysctl_xfrm_larval_drop;
-+      u32                     sysctl_xfrm_acq_expires;
-+#endif /* CONFIG_XFRM */
-+
-+      int                     sysctl_somaxconn;
-+
-+#ifdef CONFIG_PACKET
-+      /* List of all packet sockets. */
-+      rwlock_t                packet_sklist_lock;
-+      struct hlist_head       packet_sklist;
-+#endif /* CONFIG_PACKET */
-+#ifdef CONFIG_UNIX
-+      int                     sysctl_unix_max_dgram_qlen;
-+      void *                  unix_sysctl;
-+#endif /* CONFIG_UNIX */
-+#ifdef CONFIG_IP_MULTIPLE_TABLES
-+      void *                  fib4_table;
-+#endif /* CONFIG_IP_MULTIPLE_TABLES */
-+#ifdef CONFIG_IP_FIB_HASH
-+      int                     fn_hash_last_dflt;
-+#endif
-+#ifdef CONFIG_IP_FIB_TRIE
-+      int                     trie_last_dflt;
-+#endif
-+#ifndef CONFIG_IP_MULTIPLE_TABLES
-+      struct fib_table        *ip_fib_local_table;
-+      struct fib_table        *ip_fib_main_table;
-+#endif
-+      struct hlist_head       *ip_fib_table_hash;
-+      struct sock             *nlfl;
-+
-+      /* fib_semantics */
-+      struct hlist_head       *fib_info_hash;
-+      struct hlist_head       *fib_info_laddrhash;
-+      unsigned int            fib_info_hash_size;
-+      unsigned int            fib_info_cnt;
-+      struct hlist_head       *fib_info_devhash;
-+
-+      /* af_inet.c */
-+      int                     sysctl_ip_nonlocal_bind; /* __read_mostly */
-+      int                     sysctl_ip_default_ttl;  /* __read_mostly */
-+      int                     sysctl_ipfrag_high_thresh;
-+      int                     sysctl_ipfrag_low_thresh;
-+      int                     sysctl_ipfrag_time;
-+      int                     sysctl_ipfrag_secret_interval;
-+      int                     sysctl_ipfrag_max_dist;
-+      int                     sysctl_ipv4_no_pmtu_disc;
-+      int                     sysctl_local_port_range[2];
-+      int                     sysctl_ip_dynaddr;
-+      int                     sysctl_tcp_timestamps;  /* __read_mostly */
-+      int                     sysctl_tcp_window_scaling; /* __read_mostly */
-+      /* inetpeer.c */
-+      int                     inet_peer_threshold;
-+      int                     inet_peer_minttl;
-+      int                     inet_peer_maxttl;
-+      int                     inet_peer_gc_mintime;
-+      int                     inet_peer_gc_maxtime;
-+
-+      /* devinet */
-+      struct ipv4_devconf     *ipv4_devconf;
-+      struct ipv4_devconf     *ipv4_devconf_dflt;
-+
-+      /* arp.c */
-+      struct neigh_parms      *arp_neigh_parms_default;
-+
-+      /* icmp.c */
-+      struct socket           **__icmp_socket;
-+
-+      /* inetpeer.c */
-+      struct inet_peer        *peer_root;
-+      int                     peer_total;
-+      struct inet_peer        *inet_peer_unused_head;
-+      struct inet_peer        **inet_peer_unused_tailp;
-+      struct timer_list       peer_periodic_timer;
-+
-+      /* ip_fragment.c */
-+      struct hlist_head       *ipq_hash;
-+      u32                     ipfrag_hash_rnd;
-+      struct list_head        ipq_lru_list;
-+      int                     ip_frag_nqueues;
-+      atomic_t                ip_frag_mem;
-+      struct timer_list       ipfrag_secret_timer;
-+
-+      /* udp.c */
-+      int                     udp_port_rover;
-+
-+      /* iptable_filter.c */
-+      struct xt_table         *ip_packet_filter;
-+};
-+
-+extern struct net init_net;
-+extern struct list_head net_namespace_list;
-+
-+extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns);
-+extern void __put_net(struct net *net);
-+
-+static inline struct net *get_net(struct net *net)
-+{
-+      atomic_inc(&net->count);
-+      return net;
-+}
-+
-+static inline void put_net(struct net *net)
-+{
-+      if (atomic_dec_and_test(&net->count))
-+              __put_net(net);
-+}
-+
-+static inline struct net *hold_net(struct net *net)
-+{
-+      atomic_inc(&net->use_count);
-+      return net;
-+}
-+
-+static inline void release_net(struct net *net)
-+{
-+      atomic_dec(&net->use_count);
-+}
-+
-+extern void net_lock(void);
-+extern void net_unlock(void);
-+
-+#define for_each_net(VAR)                             \
-+      list_for_each_entry(VAR, &net_namespace_list, list)
-+
-+
-+struct pernet_operations {
-+      struct list_head list;
-+      int (*init)(struct net *net);
-+      void (*exit)(struct net *net);
-+};
-+
-+extern int register_pernet_subsys(struct pernet_operations *);
-+extern void unregister_pernet_subsys(struct pernet_operations *);
-+extern int register_pernet_device(struct pernet_operations *);
-+extern void unregister_pernet_device(struct pernet_operations *);
-+
-+#ifdef CONFIG_PROC_FS
-+static inline struct net *PDE_NET(struct proc_dir_entry *pde)
-+{
-+      return pde->parent->data;
-+}
-+
-+static inline struct net *PROC_NET(const struct inode *inode)
-+{
-+      return PDE_NET(PDE(inode));
-+}
-+
-+static inline struct proc_dir_entry *proc_net_create(struct net *net,
-+      const char *name, mode_t mode, get_info_t *get_info)
-+{
-+      return create_proc_info_entry(name,mode, net->proc_net, get_info);
-+}
-+
-+static inline struct proc_dir_entry *proc_net_fops_create(struct net *net,
-+      const char *name, mode_t mode, const struct file_operations *fops)
-+{
-+      struct proc_dir_entry *res = 
-+              create_proc_entry(name, mode, net->proc_net);
-+      if (res)
-+              res->proc_fops = fops;
-+      return res;
-+}
-+
-+static inline void proc_net_remove(struct net *net, const char *name)
-+{
-+      remove_proc_entry(name, net->proc_net);
-+}
-+
-+#else
-+
-+#define proc_net_fops_create(net, name, mode, fops)  ({ (void)(mode), NULL; })
-+#define proc_net_create(net, name, mode, info)        ({ (void)(mode), NULL; })
-+static inline void proc_net_remove(struct net *net, const char *name) {}
-+
-+#endif /* CONFIG_PROC_FS */
-+
-+#endif /* __NET_NET_NAMESPACE_H */
-diff -Nurb linux-2.6.22-570/include/net/netlink.h linux-2.6.22-590/include/net/netlink.h
---- linux-2.6.22-570/include/net/netlink.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/netlink.h     2008-01-02 13:56:37.000000000 -0500
-@@ -118,6 +118,9 @@
-  * Nested Attributes Construction:
-  *   nla_nest_start(skb, type)                start a nested attribute
-  *   nla_nest_end(skb, nla)           finalize a nested attribute
-+ *   nla_nest_compat_start(skb, type, start a nested compat attribute
-+ *                       len, data)
-+ *   nla_nest_compat_end(skb, type)   finalize a nested compat attribute
-  *   nla_nest_cancel(skb, nla)                cancel nested attribute construction
-  *
-  * Attribute Length Calculations:
-@@ -152,6 +155,7 @@
-  *   nla_find_nested()                        find attribute in nested attributes
-  *   nla_parse()                      parse and validate stream of attrs
-  *   nla_parse_nested()                       parse nested attribuets
-+ *   nla_parse_nested_compat()                parse nested compat attributes
-  *   nla_for_each_attr()              loop over all attributes
-  *   nla_for_each_nested()            loop over the nested attributes
-  *=========================================================================
-@@ -170,6 +174,7 @@
-       NLA_FLAG,
-       NLA_MSECS,
-       NLA_NESTED,
-+      NLA_NESTED_COMPAT,
-       NLA_NUL_STRING,
-       NLA_BINARY,
-       __NLA_TYPE_MAX,
-@@ -190,6 +195,7 @@
-  *    NLA_NUL_STRING       Maximum length of string (excluding NUL)
-  *    NLA_FLAG             Unused
-  *    NLA_BINARY           Maximum length of attribute payload
-+ *    NLA_NESTED_COMPAT    Exact length of structure payload
-  *    All other            Exact length of attribute payload
-  *
-  * Example:
-@@ -212,6 +218,7 @@
- struct nl_info {
-       struct nlmsghdr         *nlh;
-       u32                     pid;
-+      struct net              *net;
- };
- extern void           netlink_run_queue(struct sock *sk, unsigned int *qlen,
-@@ -733,6 +740,39 @@
+-static struct page * ocfs2_get_write_source(char **ret_src_buf,
++static struct page * ocfs2_get_write_source(struct ocfs2_buffered_write_priv *bp,
+                                           const struct iovec *cur_iov,
+                                           size_t iov_offset)
  {
-       return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
- }
-+
-+/**
-+ * nla_parse_nested_compat - parse nested compat attributes
-+ * @tb: destination array with maxtype+1 elements
-+ * @maxtype: maximum attribute type to be expected
-+ * @nla: attribute containing the nested attributes
-+ * @data: pointer to point to contained structure
-+ * @len: length of contained structure
-+ * @policy: validation policy
-+ *
-+ * Parse a nested compat attribute. The compat attribute contains a structure
-+ * and optionally a set of nested attributes. On success the data pointer
-+ * points to the nested data and tb contains the parsed attributes
-+ * (see nla_parse).
-+ */
-+static inline int __nla_parse_nested_compat(struct nlattr *tb[], int maxtype,
-+                                          struct nlattr *nla,
-+                                          const struct nla_policy *policy,
-+                                          int len)
-+{
-+      if (nla_len(nla) < len)
-+              return -1;
-+      if (nla_len(nla) >= NLA_ALIGN(len) + sizeof(struct nlattr))
-+              return nla_parse_nested(tb, maxtype,
-+                                      nla_data(nla) + NLA_ALIGN(len),
-+                                      policy);
-+      memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
-+      return 0;
-+}
-+
-+#define nla_parse_nested_compat(tb, maxtype, nla, policy, data, len) \
-+({    data = nla_len(nla) >= len ? nla_data(nla) : NULL; \
-+      __nla_parse_nested_compat(tb, maxtype, nla, policy, len); })
- /**
-  * nla_put_u8 - Add a u16 netlink attribute to a socket buffer
-  * @skb: socket buffer to add attribute to
-@@ -965,6 +1005,51 @@
- }
- /**
-+ * nla_nest_compat_start - Start a new level of nested compat attributes
-+ * @skb: socket buffer to add attributes to
-+ * @attrtype: attribute type of container
-+ * @attrlen: length of structure
-+ * @data: pointer to structure
-+ *
-+ * Start a nested compat attribute that contains both a structure and
-+ * a set of nested attributes.
-+ *
-+ * Returns the container attribute
-+ */
-+static inline struct nlattr *nla_nest_compat_start(struct sk_buff *skb,
-+                                                 int attrtype, int attrlen,
-+                                                 const void *data)
-+{
-+      struct nlattr *start = (struct nlattr *)skb_tail_pointer(skb);
-+
-+      if (nla_put(skb, attrtype, attrlen, data) < 0)
-+              return NULL;
-+      if (nla_nest_start(skb, attrtype) == NULL) {
-+              nlmsg_trim(skb, start);
-+              return NULL;
-+      }
-+      return start;
-+}
-+
-+/**
-+ * nla_nest_compat_end - Finalize nesting of compat attributes
-+ * @skb: socket buffer the attribtues are stored in
-+ * @start: container attribute
-+ *
-+ * Corrects the container attribute header to include the all
-+ * appeneded attributes.
-+ *
-+ * Returns the total data length of the skb.
-+ */
-+static inline int nla_nest_compat_end(struct sk_buff *skb, struct nlattr *start)
-+{
-+      struct nlattr *nest = (void *)start + NLMSG_ALIGN(start->nla_len);
-+
-+      start->nla_len = skb_tail_pointer(skb) - (unsigned char *)start;
-+      return nla_nest_end(skb, nest);
-+}
-+
-+/**
-  * nla_nest_cancel - Cancel nesting of attributes
-  * @skb: socket buffer the message is stored in
-  * @start: container attribute
-diff -Nurb linux-2.6.22-570/include/net/pkt_cls.h linux-2.6.22-590/include/net/pkt_cls.h
---- linux-2.6.22-570/include/net/pkt_cls.h     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/pkt_cls.h     2008-01-02 13:56:37.000000000 -0500
-@@ -2,6 +2,7 @@
- #define __NET_PKT_CLS_H
- #include <linux/pkt_cls.h>
-+#include <net/net_namespace.h>
- #include <net/sch_generic.h>
- #include <net/act_api.h>
-@@ -357,7 +358,7 @@
-       if (indev[0]) {
-               if  (!skb->iif)
-                       return 0;
--              dev = __dev_get_by_index(skb->iif);
-+              dev = __dev_get_by_index(&init_net, skb->iif);
-               if (!dev || strcmp(indev, dev->name))
-                       return 0;
-       }
-diff -Nurb linux-2.6.22-570/include/net/protocol.h linux-2.6.22-590/include/net/protocol.h
---- linux-2.6.22-570/include/net/protocol.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/protocol.h    2008-01-02 13:56:37.000000000 -0500
-@@ -86,6 +86,7 @@
- #define INET_PROTOSW_REUSE 0x01            /* Are ports automatically reusable? */
- #define INET_PROTOSW_PERMANENT 0x02  /* Permanent protocols are unremovable. */
- #define INET_PROTOSW_ICSK      0x04  /* Is this an inet_connection_sock? */
-+#define INET_PROTOSW_NETNS     0x08  /* Multiple namespaces support? */
- extern struct net_protocol *inet_protocol_base;
- extern struct net_protocol *inet_protos[MAX_INET_PROTOS];
-diff -Nurb linux-2.6.22-570/include/net/raw.h linux-2.6.22-590/include/net/raw.h
---- linux-2.6.22-570/include/net/raw.h 2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/include/net/raw.h 2008-01-02 13:56:37.000000000 -0500
-@@ -34,7 +34,7 @@
- extern rwlock_t raw_v4_lock;
--extern struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
-+extern struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, unsigned short num,
-                                   __be32 raddr, __be32 laddr,
-                                   int dif, int tag);
-diff -Nurb linux-2.6.22-570/include/net/rawv6.h linux-2.6.22-590/include/net/rawv6.h
---- linux-2.6.22-570/include/net/rawv6.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/rawv6.h       2008-01-02 13:56:37.000000000 -0500
-@@ -3,6 +3,8 @@
- #ifdef __KERNEL__
-+#include <net/protocol.h>
-+
- #define RAWV6_HTABLE_SIZE     MAX_INET_PROTOS
- extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE];
- extern rwlock_t raw_v6_lock;
-@@ -23,6 +25,13 @@
-                                         int type, int code, 
-                                         int offset, __be32 info);
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-+int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
-+                                         struct sk_buff *skb));
-+int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
-+                                           struct sk_buff *skb));
-+#endif
-+
- #endif
- #endif
-diff -Nurb linux-2.6.22-570/include/net/route.h linux-2.6.22-590/include/net/route.h
---- linux-2.6.22-570/include/net/route.h       2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/include/net/route.h       2008-01-02 13:56:37.000000000 -0500
-@@ -27,6 +27,7 @@
- #include <net/dst.h>
- #include <net/inetpeer.h>
- #include <net/flow.h>
-+#include <net/sock.h>
- #include <net/inet_sock.h>
- #include <linux/in_route.h>
- #include <linux/rtnetlink.h>
-@@ -66,7 +67,6 @@
-       
-       unsigned                rt_flags;
-       __u16                   rt_type;
--      __u16                   rt_multipath_alg;
-       __be32                  rt_dst; /* Path destination     */
-       __be32                  rt_src; /* Path source          */
-@@ -123,9 +123,9 @@
- extern unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu);
- extern void           ip_rt_send_redirect(struct sk_buff *skb);
+       int ret;
+-      char *buf = cur_iov->iov_base + iov_offset;
++      char *buf;
+       struct page *src_page = NULL;
+-      unsigned long off;
  
--extern unsigned               inet_addr_type(__be32 addr);
-+extern unsigned               inet_addr_type(struct net *net, __be32 addr);
- extern void           ip_rt_multicast_event(struct in_device *);
--extern int            ip_rt_ioctl(unsigned int cmd, void __user *arg);
-+extern int            ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg);
- extern void           ip_rt_get_source(u8 *src, struct rtable *rt);
- extern int            ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb);
+-      off = (unsigned long)(buf) & ~PAGE_CACHE_MASK;
++      buf = cur_iov->iov_base + iov_offset;
  
-@@ -154,7 +154,8 @@
-                                  __be16 sport, __be16 dport, struct sock *sk,
-                                  int flags)
+       if (!segment_eq(get_fs(), KERNEL_DS)) {
+               /*
+@@ -1608,12 +1378,10 @@
  {
--      struct flowi fl = { .oif = oif,
-+      struct flowi fl = { .fl_net = sk->sk_net,
-+                          .oif = oif,
-                           .nl_u = { .ip4_u = { .daddr = dst,
-                                                .saddr = src,
-                                                .tos   = tos } },
-@@ -199,6 +200,7 @@
-               struct flowi fl;
-               memcpy(&fl, &(*rp)->fl, sizeof(fl));
-+              fl.fl_net = sk->sk_net;
-               fl.fl_ip_sport = sport;
-               fl.fl_ip_dport = dport;
-               fl.proto = protocol;
-diff -Nurb linux-2.6.22-570/include/net/rtnetlink.h linux-2.6.22-590/include/net/rtnetlink.h
---- linux-2.6.22-570/include/net/rtnetlink.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/rtnetlink.h   2008-01-02 13:56:37.000000000 -0500
-@@ -22,4 +22,62 @@
-               return AF_UNSPEC;
- }
+       int ret = 0;
+       ssize_t copied, total = 0;
+-      size_t iov_offset = 0, bytes;
+-      loff_t pos;
++      size_t iov_offset = 0;
+       const struct iovec *cur_iov = iov;
+-      struct page *user_page, *page;
+-      char *buf, *dst;
+-      void *fsdata;
++      struct ocfs2_buffered_write_priv bp;
++      struct page *page;
  
-+/**
-+ *    struct rtnl_link_ops - rtnetlink link operations
-+ *
-+ *    @list: Used internally
-+ *    @kind: Identifier
-+ *    @maxtype: Highest device specific netlink attribute number
-+ *    @policy: Netlink policy for device specific attribute validation
-+ *    @validate: Optional validation function for netlink/changelink parameters
-+ *    @priv_size: sizeof net_device private space
-+ *    @setup: net_device setup function
-+ *    @newlink: Function for configuring and registering a new device
-+ *    @changelink: Function for changing parameters of an existing device
-+ *    @dellink: Function to remove a device
-+ *    @get_size: Function to calculate required room for dumping device
-+ *               specific netlink attributes
-+ *    @fill_info: Function to dump device specific netlink attributes
-+ *    @get_xstats_size: Function to calculate required room for dumping devic
-+ *                      specific statistics
-+ *    @fill_xstats: Function to dump device specific statistics
-+ */
-+struct rtnl_link_ops {
-+      struct list_head        list;
-+
-+      const char              *kind;
-+
-+      size_t                  priv_size;
-+      void                    (*setup)(struct net_device *dev);
-+
-+      int                     maxtype;
-+      const struct nla_policy *policy;
-+      int                     (*validate)(struct nlattr *tb[],
-+                                          struct nlattr *data[]);
-+
-+      int                     (*newlink)(struct net_device *dev,
-+                                         struct nlattr *tb[],
-+                                         struct nlattr *data[]);
-+      int                     (*changelink)(struct net_device *dev,
-+                                            struct nlattr *tb[],
-+                                            struct nlattr *data[]);
-+      void                    (*dellink)(struct net_device *dev);
-+
-+      size_t                  (*get_size)(const struct net_device *dev);
-+      int                     (*fill_info)(struct sk_buff *skb,
-+                                           const struct net_device *dev);
-+
-+      size_t                  (*get_xstats_size)(const struct net_device *dev);
-+      int                     (*fill_xstats)(struct sk_buff *skb,
-+                                             const struct net_device *dev);
-+};
-+
-+extern int    __rtnl_link_register(struct rtnl_link_ops *ops);
-+extern void   __rtnl_link_unregister(struct rtnl_link_ops *ops);
-+
-+extern int    rtnl_link_register(struct rtnl_link_ops *ops);
-+extern void   rtnl_link_unregister(struct rtnl_link_ops *ops);
-+
-+#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
-+
- #endif
-diff -Nurb linux-2.6.22-570/include/net/sock.h linux-2.6.22-590/include/net/sock.h
---- linux-2.6.22-570/include/net/sock.h        2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/include/net/sock.h        2008-01-02 13:56:37.000000000 -0500
-@@ -55,6 +55,7 @@
- #include <asm/atomic.h>
- #include <net/dst.h>
- #include <net/checksum.h>
-+#include <net/net_namespace.h>
+       /*
+        * handle partial DIO write.  Adjust cur_iov if needed.
+@@ -1621,38 +1389,21 @@
+       ocfs2_set_next_iovec(&cur_iov, &iov_offset, o_direct_written);
  
- /*
-  * This structure really needs to be cleaned up.
-@@ -105,6 +106,7 @@
-  *    @skc_refcnt: reference count
-  *    @skc_hash: hash value used with various protocol lookup tables
-  *    @skc_prot: protocol handlers inside a network family
-+ *    @skc_net: reference to the network namespace of this socket
-  *
-  *    This is the minimal network layer representation of sockets, the header
-  *    for struct sock and struct inet_timewait_sock.
-@@ -119,6 +121,7 @@
-       atomic_t                skc_refcnt;
-       unsigned int            skc_hash;
-       struct proto            *skc_prot;
-+      struct net              *skc_net;
-       xid_t                   skc_xid;
-       struct vx_info          *skc_vx_info;
-       nid_t                   skc_nid;
-@@ -199,6 +202,7 @@
- #define sk_refcnt             __sk_common.skc_refcnt
- #define sk_hash                       __sk_common.skc_hash
- #define sk_prot                       __sk_common.skc_prot
-+#define sk_net                        __sk_common.skc_net
- #define sk_xid                        __sk_common.skc_xid
- #define sk_vx_info            __sk_common.skc_vx_info
- #define sk_nid                        __sk_common.skc_nid
-@@ -781,7 +785,7 @@
-                               SINGLE_DEPTH_NESTING)
- #define bh_unlock_sock(__sk)  spin_unlock(&((__sk)->sk_lock.slock))
+       do {
+-              pos = *ppos;
++              bp.b_cur_off = iov_offset;
++              bp.b_cur_iov = cur_iov;
+-              user_page = ocfs2_get_write_source(&buf, cur_iov, iov_offset);
+-              if (IS_ERR(user_page)) {
+-                      ret = PTR_ERR(user_page);
++              page = ocfs2_get_write_source(&bp, cur_iov, iov_offset);
++              if (IS_ERR(page)) {
++                      ret = PTR_ERR(page);
+                       goto out;
+               }
  
--extern struct sock            *sk_alloc(int family,
-+extern struct sock            *sk_alloc(struct net *net, int family,
-                                         gfp_t priority,
-                                         struct proto *prot, int zero_it);
- extern void                   sk_free(struct sock *sk);
-@@ -1010,6 +1014,7 @@
- #endif
+-              /* Stay within our page boundaries */
+-              bytes = min((PAGE_CACHE_SIZE - ((unsigned long)pos & ~PAGE_CACHE_MASK)),
+-                          (PAGE_CACHE_SIZE - ((unsigned long)buf & ~PAGE_CACHE_MASK)));
+-              /* Stay within the vector boundary */
+-              bytes = min_t(size_t, bytes, cur_iov->iov_len - iov_offset);
+-              /* Stay within count */
+-              bytes = min(bytes, count);
+-
+-              page = NULL;
+-              ret = ocfs2_write_begin(file, file->f_mapping, pos, bytes, 0,
+-                                      &page, &fsdata);
+-              if (ret) {
+-                      mlog_errno(ret);
+-                      goto out;
+-              }
++              copied = ocfs2_buffered_write_cluster(file, *ppos, count,
++                                                    ocfs2_map_and_write_user_data,
++                                                    &bp);
  
-       memcpy(nsk, osk, osk->sk_prot->obj_size);
-+      get_net(nsk->sk_net);
- #ifdef CONFIG_SECURITY_NETWORK
-       nsk->sk_security = sptr;
-       security_sk_clone(osk, nsk);
-@@ -1373,6 +1378,7 @@
+-              dst = kmap_atomic(page, KM_USER0);
+-              memcpy(dst + (pos & (PAGE_CACHE_SIZE - 1)), buf, bytes);
+-              kunmap_atomic(dst, KM_USER0);
+-              flush_dcache_page(page);
+-              ocfs2_put_write_source(user_page);
++              ocfs2_put_write_source(&bp, page);
  
- #ifdef CONFIG_SYSCTL
- extern struct ctl_table core_table[];
-+extern struct ctl_table multi_core_table[];
- #endif
+-              copied = ocfs2_write_end(file, file->f_mapping, pos, bytes,
+-                                       bytes, page, fsdata);
+               if (copied < 0) {
+                       mlog_errno(copied);
+                       ret = copied;
+@@ -1660,7 +1411,7 @@
+               }
  
- extern int sysctl_optmem_max;
-diff -Nurb linux-2.6.22-570/include/net/tcp.h linux-2.6.22-590/include/net/tcp.h
---- linux-2.6.22-570/include/net/tcp.h 2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/include/net/tcp.h 2008-01-02 13:56:37.000000000 -0500
-@@ -191,8 +191,6 @@
- extern struct inet_timewait_death_row tcp_death_row;
+               total += copied;
+-              *ppos = pos + copied;
++              *ppos = *ppos + copied;
+               count -= copied;
  
- /* sysctl variables for tcp */
--extern int sysctl_tcp_timestamps;
--extern int sysctl_tcp_window_scaling;
- extern int sysctl_tcp_sack;
- extern int sysctl_tcp_fin_timeout;
- extern int sysctl_tcp_keepalive_time;
-@@ -1293,6 +1291,7 @@
- };
+               ocfs2_set_next_iovec(&cur_iov, &iov_offset, copied);
+@@ -1830,46 +1581,52 @@
+                                   struct pipe_buffer *buf,
+                                   struct splice_desc *sd)
+ {
+-      int ret, count;
++      int ret, count, total = 0;
+       ssize_t copied = 0;
+-      struct file *file = sd->file;
+-      unsigned int offset;
+-      struct page *page = NULL;
+-      void *fsdata;
+-      char *src, *dst;
++      struct ocfs2_splice_write_priv sp;
  
- struct tcp_iter_state {
-+      struct net              *net;
-       sa_family_t             family;
-       enum tcp_seq_states     state;
-       struct sock             *syn_wait_sk;
-@@ -1300,8 +1299,8 @@
-       struct seq_operations   seq_ops;
- };
+       ret = buf->ops->pin(pipe, buf);
+       if (ret)
+               goto out;
  
--extern int tcp_proc_register(struct tcp_seq_afinfo *afinfo);
--extern void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo);
-+extern int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo);
-+extern void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo);
+-      offset = sd->pos & ~PAGE_CACHE_MASK;
+-      count = sd->len;
+-      if (count + offset > PAGE_CACHE_SIZE)
+-              count = PAGE_CACHE_SIZE - offset;
+-
+-      ret = ocfs2_write_begin(file, file->f_mapping, sd->pos, count, 0,
+-                              &page, &fsdata);
+-      if (ret) {
+-              mlog_errno(ret);
+-              goto out;
+-      }
++      sp.s_sd = sd;
++      sp.s_buf = buf;
++      sp.s_pipe = pipe;
++      sp.s_offset = sd->pos & ~PAGE_CACHE_MASK;
++      sp.s_buf_offset = buf->offset;
+-      src = buf->ops->map(pipe, buf, 1);
+-      dst = kmap_atomic(page, KM_USER1);
+-      memcpy(dst + offset, src + buf->offset, count);
+-      kunmap_atomic(page, KM_USER1);
+-      buf->ops->unmap(pipe, buf, src);
++      count = sd->len;
++      if (count + sp.s_offset > PAGE_CACHE_SIZE)
++              count = PAGE_CACHE_SIZE - sp.s_offset;
+-      copied = ocfs2_write_end(file, file->f_mapping, sd->pos, count, count,
+-                               page, fsdata);
++      do {
++              /*
++               * splice wants us to copy up to one page at a
++               * time. For pagesize > cluster size, this means we
++               * might enter ocfs2_buffered_write_cluster() more
++               * than once, so keep track of our progress here.
++               */
++              copied = ocfs2_buffered_write_cluster(sd->file,
++                                                    (loff_t)sd->pos + total,
++                                                    count,
++                                                    ocfs2_map_and_write_splice_data,
++                                                    &sp);
+               if (copied < 0) {
+                       mlog_errno(copied);
+                       ret = copied;
+                       goto out;
+               }
++
++              count -= copied;
++              sp.s_offset += copied;
++              sp.s_buf_offset += copied;
++              total += copied;
++      } while (count);
++
++      ret = 0;
+ out:
  
- extern struct request_sock_ops tcp_request_sock_ops;
+-      return copied ? copied : ret;
++      return total ? total : ret;
+ }
  
-diff -Nurb linux-2.6.22-570/include/net/tipc/tipc_port.h linux-2.6.22-590/include/net/tipc/tipc_port.h
---- linux-2.6.22-570/include/net/tipc/tipc_port.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/tipc/tipc_port.h      2008-01-02 13:56:37.000000000 -0500
-@@ -1,8 +1,8 @@
- /*
-  * include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports
-  * 
-- * Copyright (c) 1994-2006, Ericsson AB
-- * Copyright (c) 2005, Wind River Systems
-+ * Copyright (c) 1994-2007, Ericsson AB
-+ * Copyright (c) 2005-2007, Wind River Systems
-  * All rights reserved.
-  *
-  * Redistribution and use in source and binary forms, with or without
-@@ -55,6 +55,7 @@
-  * @conn_unacked: number of unacknowledged messages received from peer port
-  * @published: non-zero if port has one or more associated names
-  * @congested: non-zero if cannot send because of link or port congestion
-+ * @max_pkt: maximum packet size "hint" used when building messages sent by port
-  * @ref: unique reference to port in TIPC object registry
-  * @phdr: preformatted message header used when sending messages
-  */
-@@ -68,6 +69,7 @@
-       u32 conn_unacked;
-       int published;
-       u32 congested;
-+      u32 max_pkt;
-       u32 ref;
-       struct tipc_msg phdr;
- };
-diff -Nurb linux-2.6.22-570/include/net/udp.h linux-2.6.22-590/include/net/udp.h
---- linux-2.6.22-570/include/net/udp.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/udp.h 2008-01-02 13:56:37.000000000 -0500
-@@ -160,6 +160,7 @@
+ static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe,
+diff -Nurb linux-2.6.22-590/fs/ocfs2/file.h linux-2.6.22-570/fs/ocfs2/file.h
+--- linux-2.6.22-590/fs/ocfs2/file.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/file.h   2007-07-08 19:32:17.000000000 -0400
+@@ -39,16 +39,15 @@
  };
+ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
+                              struct inode *inode,
+-                             u32 *logical_offset,
++                             u32 *cluster_start,
+                              u32 clusters_to_add,
+-                             int mark_unwritten,
+                              struct buffer_head *fe_bh,
+                              handle_t *handle,
+                              struct ocfs2_alloc_context *data_ac,
+                              struct ocfs2_alloc_context *meta_ac,
+-                             enum ocfs2_alloc_restarted *reason_ret);
++                             enum ocfs2_alloc_restarted *reason);
+ int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
+-                        u32 clusters_to_add, u32 extents_to_split,
++                        u32 clusters_to_add,
+                         struct ocfs2_alloc_context **data_ac,
+                         struct ocfs2_alloc_context **meta_ac);
+ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
+@@ -62,7 +61,4 @@
+ int ocfs2_update_inode_atime(struct inode *inode,
+                            struct buffer_head *bh);
  
- struct udp_iter_state {
-+      struct net              *net;
-       sa_family_t             family;
-       struct hlist_head       *hashtable;
-       int                     bucket;
-@@ -167,8 +168,8 @@
- };
+-int ocfs2_change_file_space(struct file *file, unsigned int cmd,
+-                          struct ocfs2_space_resv *sr);
+-
+ #endif /* OCFS2_FILE_H */
+diff -Nurb linux-2.6.22-590/fs/ocfs2/heartbeat.c linux-2.6.22-570/fs/ocfs2/heartbeat.c
+--- linux-2.6.22-590/fs/ocfs2/heartbeat.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/heartbeat.c      2007-07-08 19:32:17.000000000 -0400
+@@ -157,16 +157,16 @@
+       if (ocfs2_mount_local(osb))
+               return 0;
  
- #ifdef CONFIG_PROC_FS
--extern int udp_proc_register(struct udp_seq_afinfo *afinfo);
--extern void udp_proc_unregister(struct udp_seq_afinfo *afinfo);
-+extern int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo);
-+extern void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo);
+-      status = o2hb_register_callback(osb->uuid_str, &osb->osb_hb_down);
++      status = o2hb_register_callback(&osb->osb_hb_down);
+       if (status < 0) {
+               mlog_errno(status);
+               goto bail;
+       }
  
- extern int  udp4_proc_init(void);
- extern void udp4_proc_exit(void);
-diff -Nurb linux-2.6.22-570/include/net/wext.h linux-2.6.22-590/include/net/wext.h
---- linux-2.6.22-570/include/net/wext.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/net/wext.h        2008-01-02 13:56:37.000000000 -0500
-@@ -5,16 +5,23 @@
-  * wireless extensions interface to the core code
-  */
+-      status = o2hb_register_callback(osb->uuid_str, &osb->osb_hb_up);
++      status = o2hb_register_callback(&osb->osb_hb_up);
+       if (status < 0) {
+               mlog_errno(status);
+-              o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_down);
++              o2hb_unregister_callback(&osb->osb_hb_down);
+       }
  
-+struct net;
-+
- #ifdef CONFIG_WIRELESS_EXT
--extern int wext_proc_init(void);
--extern int wext_handle_ioctl(struct ifreq *ifr, unsigned int cmd,
-+extern int wext_proc_init(struct net *net);
-+extern void wext_proc_exit(struct net *net);
-+extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
-                            void __user *arg);
- #else
--static inline int wext_proc_init(void)
-+static inline int wext_proc_init(struct net *net)
- {
-       return 0;
+ bail:
+@@ -178,8 +178,8 @@
+       if (ocfs2_mount_local(osb))
+               return;
+-      o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_down);
+-      o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_up);
++      o2hb_unregister_callback(&osb->osb_hb_down);
++      o2hb_unregister_callback(&osb->osb_hb_up);
  }
--static inline int wext_handle_ioctl(struct ifreq *ifr, unsigned int cmd,
-+static inline void wext_proc_exit(struct net *net)
-+{
-+      return;
-+}
-+static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
-                                   void __user *arg)
- {
-       return -EINVAL;
-diff -Nurb linux-2.6.22-570/include/net/xfrm.h linux-2.6.22-590/include/net/xfrm.h
---- linux-2.6.22-570/include/net/xfrm.h        2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/include/net/xfrm.h        2008-01-02 13:56:37.000000000 -0500
-@@ -19,13 +19,21 @@
- #include <net/ipv6.h>
- #include <net/ip6_fib.h>
  
-+#define XFRM_PROTO_ESP                50
-+#define XFRM_PROTO_AH         51
-+#define XFRM_PROTO_COMP               108
-+#define XFRM_PROTO_IPIP               4
-+#define XFRM_PROTO_IPV6               41
-+#define XFRM_PROTO_ROUTING    IPPROTO_ROUTING
-+#define XFRM_PROTO_DSTOPTS    IPPROTO_DSTOPTS
-+
- #define XFRM_ALIGN8(len)      (((len) + 7) & ~7)
- #define MODULE_ALIAS_XFRM_MODE(family, encap) \
-       MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
-+#define MODULE_ALIAS_XFRM_TYPE(family, proto) \
-+      MODULE_ALIAS("xfrm-type-" __stringify(family) "-" __stringify(proto))
+ void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
+@@ -209,7 +209,7 @@
+       envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+       envp[2] = NULL;
  
- extern struct sock *xfrm_nl;
--extern u32 sysctl_xfrm_aevent_etime;
--extern u32 sysctl_xfrm_aevent_rseqth;
+-      ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
++      ret = call_usermodehelper(argv[0], argv, envp, 1);
+       if (ret < 0)
+               mlog_errno(ret);
+ }
+diff -Nurb linux-2.6.22-590/fs/ocfs2/ioctl.c linux-2.6.22-570/fs/ocfs2/ioctl.c
+--- linux-2.6.22-590/fs/ocfs2/ioctl.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/ioctl.c  2008-01-23 19:16:04.000000000 -0500
+@@ -14,7 +14,6 @@
+ #include "ocfs2.h"
+ #include "alloc.h"
+ #include "dlmglue.h"
+-#include "file.h"
+ #include "inode.h"
+ #include "journal.h"
  
- extern struct mutex xfrm_cfg_mutex;
+@@ -116,7 +115,6 @@
+ {
+       unsigned int flags;
+       int status;
+-      struct ocfs2_space_resv sr;
  
-@@ -509,11 +517,9 @@
-       case IPPROTO_ICMPV6:
-               port = htons(fl->fl_icmp_type);
-               break;
--#ifdef CONFIG_IPV6_MIP6
-       case IPPROTO_MH:
-               port = htons(fl->fl_mh_type);
+       switch (cmd) {
+       case OCFS2_IOC_GETFLAGS:
+@@ -132,12 +130,6 @@
+               return ocfs2_set_inode_attr(inode, flags,
+                       OCFS2_FL_MODIFIABLE);
+-      case OCFS2_IOC_RESVSP:
+-      case OCFS2_IOC_RESVSP64:
+-              if (copy_from_user(&sr, (int __user *) arg, sizeof(sr)))
+-                      return -EFAULT;
+-
+-              return ocfs2_change_file_space(filp, cmd, &sr);
+       default:
+               return -ENOTTY;
+       }
+@@ -156,9 +148,6 @@
+       case OCFS2_IOC32_SETFLAGS:
+               cmd = OCFS2_IOC_SETFLAGS;
                break;
--#endif
+-      case OCFS2_IOC_RESVSP:
+-      case OCFS2_IOC_RESVSP64:
+-              break;
        default:
-               port = 0;       /*XXX*/
+               return -ENOIOCTLCMD;
        }
-diff -Nurb linux-2.6.22-570/include/scsi/iscsi_if.h linux-2.6.22-590/include/scsi/iscsi_if.h
---- linux-2.6.22-570/include/scsi/iscsi_if.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/scsi/iscsi_if.h   2008-01-02 13:56:37.000000000 -0500
-@@ -48,6 +48,7 @@
-       ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT    = UEVENT_BASE + 14,
-       ISCSI_UEVENT_TGT_DSCVR          = UEVENT_BASE + 15,
-+      ISCSI_UEVENT_SET_HOST_PARAM     = UEVENT_BASE + 16,
+diff -Nurb linux-2.6.22-590/fs/ocfs2/journal.c linux-2.6.22-570/fs/ocfs2/journal.c
+--- linux-2.6.22-590/fs/ocfs2/journal.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/journal.c        2007-07-08 19:32:17.000000000 -0400
+@@ -722,7 +722,8 @@
+               container_of(work, struct ocfs2_journal, j_recovery_work);
+       struct ocfs2_super *osb = journal->j_osb;
+       struct ocfs2_dinode *la_dinode, *tl_dinode;
+-      struct ocfs2_la_recovery_item *item, *n;
++      struct ocfs2_la_recovery_item *item;
++      struct list_head *p, *n;
+       LIST_HEAD(tmp_la_list);
  
-       /* up events */
-       ISCSI_KEVENT_RECV_PDU           = KEVENT_BASE + 1,
-@@ -71,6 +72,8 @@
-               /* messages u -> k */
-               struct msg_create_session {
-                       uint32_t        initial_cmdsn;
-+                      uint16_t        cmds_max;
-+                      uint16_t        queue_depth;
-               } c_session;
-               struct msg_destroy_session {
-                       uint32_t        sid;
-@@ -136,6 +139,11 @@
-                        */
-                       uint32_t        enable;
-               } tgt_dscvr;
-+              struct msg_set_host_param {
-+                      uint32_t        host_no;
-+                      uint32_t        param; /* enum iscsi_host_param */
-+                      uint32_t        len;
-+              } set_host_param;
-       } u;
-       union {
-               /* messages k -> u */
-@@ -223,6 +231,11 @@
-       ISCSI_PARAM_CONN_PORT,
-       ISCSI_PARAM_CONN_ADDRESS,
+       mlog_entry_void();
+@@ -733,7 +734,8 @@
+       list_splice_init(&journal->j_la_cleanups, &tmp_la_list);
+       spin_unlock(&journal->j_lock);
  
-+      ISCSI_PARAM_USERNAME,
-+      ISCSI_PARAM_USERNAME_IN,
-+      ISCSI_PARAM_PASSWORD,
-+      ISCSI_PARAM_PASSWORD_IN,
-+
-       /* must always be last */
-       ISCSI_PARAM_MAX,
- };
-@@ -249,6 +262,24 @@
- #define ISCSI_SESS_RECOVERY_TMO               (1 << ISCSI_PARAM_SESS_RECOVERY_TMO)
- #define ISCSI_CONN_PORT                       (1 << ISCSI_PARAM_CONN_PORT)
- #define ISCSI_CONN_ADDRESS            (1 << ISCSI_PARAM_CONN_ADDRESS)
-+#define ISCSI_USERNAME                        (1 << ISCSI_PARAM_USERNAME)
-+#define ISCSI_USERNAME_IN             (1 << ISCSI_PARAM_USERNAME_IN)
-+#define ISCSI_PASSWORD                        (1 << ISCSI_PARAM_PASSWORD)
-+#define ISCSI_PASSWORD_IN             (1 << ISCSI_PARAM_PASSWORD_IN)
-+
-+/* iSCSI HBA params */
-+enum iscsi_host_param {
-+      ISCSI_HOST_PARAM_HWADDRESS,
-+      ISCSI_HOST_PARAM_INITIATOR_NAME,
-+      ISCSI_HOST_PARAM_NETDEV_NAME,
-+      ISCSI_HOST_PARAM_IPADDRESS,
-+      ISCSI_HOST_PARAM_MAX,
-+};
-+
-+#define ISCSI_HOST_HWADDRESS          (1 << ISCSI_HOST_PARAM_HWADDRESS)
-+#define ISCSI_HOST_INITIATOR_NAME     (1 << ISCSI_HOST_PARAM_INITIATOR_NAME)
-+#define ISCSI_HOST_NETDEV_NAME                (1 << ISCSI_HOST_PARAM_NETDEV_NAME)
-+#define ISCSI_HOST_IPADDRESS          (1 << ISCSI_HOST_PARAM_IPADDRESS)
+-      list_for_each_entry_safe(item, n, &tmp_la_list, lri_list) {
++      list_for_each_safe(p, n, &tmp_la_list) {
++              item = list_entry(p, struct ocfs2_la_recovery_item, lri_list);
+               list_del_init(&item->lri_list);
  
- #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
- #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
-@@ -272,6 +303,9 @@
- #define CAP_MULTI_CONN                0x40
- #define CAP_TEXT_NEGO         0x80
- #define CAP_MARKERS           0x100
-+#define CAP_FW_DB             0x200
-+#define CAP_SENDTARGETS_OFFLOAD       0x400
-+#define CAP_DATA_PATH_OFFLOAD 0x800
+               mlog(0, "Complete recovery for slot %d\n", item->lri_slot);
+diff -Nurb linux-2.6.22-590/fs/ocfs2/mmap.c linux-2.6.22-570/fs/ocfs2/mmap.c
+--- linux-2.6.22-590/fs/ocfs2/mmap.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/mmap.c   2007-07-08 19:32:17.000000000 -0400
+@@ -37,48 +37,38 @@
  
- /*
-  * These flags describes reason of stop_conn() call
-diff -Nurb linux-2.6.22-570/include/scsi/libiscsi.h linux-2.6.22-590/include/scsi/libiscsi.h
---- linux-2.6.22-570/include/scsi/libiscsi.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/scsi/libiscsi.h   2008-01-02 13:56:37.000000000 -0500
-@@ -48,9 +48,8 @@
- #define debug_scsi(fmt...)
- #endif
+ #include "ocfs2.h"
  
--#define ISCSI_XMIT_CMDS_MAX   128     /* must be power of 2 */
--#define ISCSI_MGMT_CMDS_MAX   32      /* must be power of 2 */
--#define ISCSI_CONN_MAX                        1
-+#define ISCSI_DEF_XMIT_CMDS_MAX       128     /* must be power of 2 */
-+#define ISCSI_MGMT_CMDS_MAX   16      /* must be power of 2 */
+-#include "aops.h"
+ #include "dlmglue.h"
+ #include "file.h"
+ #include "inode.h"
+ #include "mmap.h"
  
- #define ISCSI_MGMT_ITT_OFFSET 0xa00
+-static inline int ocfs2_vm_op_block_sigs(sigset_t *blocked, sigset_t *oldset)
++static struct page *ocfs2_nopage(struct vm_area_struct * area,
++                               unsigned long address,
++                               int *type)
+ {
+-      /* The best way to deal with signals in the vm path is
+-       * to block them upfront, rather than allowing the
+-       * locking paths to return -ERESTARTSYS. */
+-      sigfillset(blocked);
+-
+-      /* We should technically never get a bad return value
+-       * from sigprocmask */
+-      return sigprocmask(SIG_BLOCK, blocked, oldset);
+-}
+-
+-static inline int ocfs2_vm_op_unblock_sigs(sigset_t *oldset)
+-{
+-      return sigprocmask(SIG_SETMASK, oldset, NULL);
+-}
+-
+-static struct page *ocfs2_fault(struct vm_area_struct *area,
+-                                              struct fault_data *fdata)
+-{
+-      struct page *page = NULL;
++      struct page *page = NOPAGE_SIGBUS;
+       sigset_t blocked, oldset;
+       int ret;
  
-@@ -73,6 +72,8 @@
- #define ISCSI_AGE_SHIFT                       28
- #define ISCSI_AGE_MASK                        (0xf << ISCSI_AGE_SHIFT)
+-      mlog_entry("(area=%p, page offset=%lu)\n", area, fdata->pgoff);
++      mlog_entry("(area=%p, address=%lu, type=%p)\n", area, address,
++                 type);
  
-+#define ISCSI_ADDRESS_BUF_LEN         64
+-      ret = ocfs2_vm_op_block_sigs(&blocked, &oldset);
++      /* The best way to deal with signals in this path is
++       * to block them upfront, rather than allowing the
++       * locking paths to return -ERESTARTSYS. */
++      sigfillset(&blocked);
 +
- struct iscsi_mgmt_task {
-       /*
-        * Becuae LLDs allocate their hdr differently, this is a pointer to
-@@ -80,7 +81,7 @@
-        */
-       struct iscsi_hdr        *hdr;
-       char                    *data;          /* mgmt payload */
--      int                     data_count;     /* counts data to be sent */
-+      unsigned                data_count;     /* counts data to be sent */
-       uint32_t                itt;            /* this ITT */
-       void                    *dd_data;       /* driver/transport data */
-       struct list_head        running;
-@@ -90,6 +91,7 @@
-       ISCSI_TASK_COMPLETED,
-       ISCSI_TASK_PENDING,
-       ISCSI_TASK_RUNNING,
-+      ISCSI_TASK_ABORTING,
++      /* We should technically never get a bad ret return
++       * from sigprocmask */
++      ret = sigprocmask(SIG_BLOCK, &blocked, &oldset);
+       if (ret < 0) {
+-              fdata->type = VM_FAULT_SIGBUS;
+               mlog_errno(ret);
+               goto out;
+       }
+-      page = filemap_fault(area, fdata);
++      page = filemap_nopage(area, address, type);
+-      ret = ocfs2_vm_op_unblock_sigs(&oldset);
++      ret = sigprocmask(SIG_SETMASK, &oldset, NULL);
+       if (ret < 0)
+               mlog_errno(ret);
+ out:
+@@ -86,135 +76,27 @@
+       return page;
+ }
+-static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
+-                              struct page *page)
+-{
+-      int ret;
+-      struct address_space *mapping = inode->i_mapping;
+-      loff_t pos = page->index << PAGE_CACHE_SHIFT;
+-      unsigned int len = PAGE_CACHE_SIZE;
+-      pgoff_t last_index;
+-      struct page *locked_page = NULL;
+-      void *fsdata;
+-      loff_t size = i_size_read(inode);
+-
+-      /*
+-       * Another node might have truncated while we were waiting on
+-       * cluster locks.
+-       */
+-      last_index = size >> PAGE_CACHE_SHIFT;
+-      if (page->index > last_index) {
+-              ret = -EINVAL;
+-              goto out;
+-      }
+-
+-      /*
+-       * The i_size check above doesn't catch the case where nodes
+-       * truncated and then re-extended the file. We'll re-check the
+-       * page mapping after taking the page lock inside of
+-       * ocfs2_write_begin_nolock().
+-       */
+-      if (!PageUptodate(page) || page->mapping != inode->i_mapping) {
+-              ret = -EINVAL;
+-              goto out;
+-      }
+-
+-      /*
+-       * Call ocfs2_write_begin() and ocfs2_write_end() to take
+-       * advantage of the allocation code there. We pass a write
+-       * length of the whole page (chopped to i_size) to make sure
+-       * the whole thing is allocated.
+-       *
+-       * Since we know the page is up to date, we don't have to
+-       * worry about ocfs2_write_begin() skipping some buffer reads
+-       * because the "write" would invalidate their data.
+-       */
+-      if (page->index == last_index)
+-              len = size & ~PAGE_CACHE_MASK;
+-
+-      ret = ocfs2_write_begin_nolock(mapping, pos, len, 0, &locked_page,
+-                                     &fsdata, di_bh, page);
+-      if (ret) {
+-              if (ret != -ENOSPC)
+-                      mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page,
+-                                   fsdata);
+-      if (ret < 0) {
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-      BUG_ON(ret != len);
+-      ret = 0;
+-out:
+-      return ret;
+-}
+-
+-static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+-{
+-      struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+-      struct buffer_head *di_bh = NULL;
+-      sigset_t blocked, oldset;
+-      int ret, ret2;
+-
+-      ret = ocfs2_vm_op_block_sigs(&blocked, &oldset);
+-      if (ret < 0) {
+-              mlog_errno(ret);
+-              return ret;
+-      }
+-
+-      /*
+-       * The cluster locks taken will block a truncate from another
+-       * node. Taking the data lock will also ensure that we don't
+-       * attempt page truncation as part of a downconvert.
+-       */
+-      ret = ocfs2_meta_lock(inode, &di_bh, 1);
+-      if (ret < 0) {
+-              mlog_errno(ret);
+-              goto out;
+-      }
+-
+-      /*
+-       * The alloc sem should be enough to serialize with
+-       * ocfs2_truncate_file() changing i_size as well as any thread
+-       * modifying the inode btree.
+-       */
+-      down_write(&OCFS2_I(inode)->ip_alloc_sem);
+-
+-      ret = ocfs2_data_lock(inode, 1);
+-      if (ret < 0) {
+-              mlog_errno(ret);
+-              goto out_meta_unlock;
+-      }
+-
+-      ret = __ocfs2_page_mkwrite(inode, di_bh, page);
+-
+-      ocfs2_data_unlock(inode, 1);
+-
+-out_meta_unlock:
+-      up_write(&OCFS2_I(inode)->ip_alloc_sem);
+-
+-      brelse(di_bh);
+-      ocfs2_meta_unlock(inode, 1);
+-
+-out:
+-      ret2 = ocfs2_vm_op_unblock_sigs(&oldset);
+-      if (ret2 < 0)
+-              mlog_errno(ret2);
+-
+-      return ret;
+-}
+-
+ static struct vm_operations_struct ocfs2_file_vm_ops = {
+-      .nopage         = ocfs2_fault,
+-      .page_mkwrite   = ocfs2_page_mkwrite,
++      .nopage = ocfs2_nopage,
  };
  
- struct iscsi_cmd_task {
-@@ -99,16 +101,14 @@
-        */
-       struct iscsi_cmd        *hdr;
-       int                     itt;            /* this ITT */
--      int                     datasn;         /* DataSN */
+ int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+       int ret = 0, lock_level = 0;
++      struct ocfs2_super *osb = OCFS2_SB(file->f_dentry->d_inode->i_sb);
++
++      /*
++       * Only support shared writeable mmap for local mounts which
++       * don't know about holes.
++       */
++      if ((!ocfs2_mount_local(osb) || ocfs2_sparse_alloc(osb)) &&
++          ((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE)) &&
++          ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
++              mlog(0, "disallow shared writable mmaps %lx\n", vma->vm_flags);
++              /* This is -EINVAL because generic_file_readonly_mmap
++               * returns it in a similar situation. */
++              return -EINVAL;
++      }
  
-       uint32_t                unsol_datasn;
--      int                     imm_count;      /* imm-data (bytes)   */
--      int                     unsol_count;    /* unsolicited (bytes)*/
-+      unsigned                imm_count;      /* imm-data (bytes)   */
-+      unsigned                unsol_count;    /* unsolicited (bytes)*/
-       /* offset in unsolicited stream (bytes); */
--      int                     unsol_offset;
--      int                     data_count;     /* remaining Data-Out */
-+      unsigned                unsol_offset;
-+      unsigned                data_count;     /* remaining Data-Out */
-       struct scsi_cmnd        *sc;            /* associated SCSI cmd*/
--      int                     total_length;
-       struct iscsi_conn       *conn;          /* used connection    */
-       struct iscsi_mgmt_task  *mtask;         /* tmf mtask in progr */
+       ret = ocfs2_meta_lock_atime(file->f_dentry->d_inode,
+                                   file->f_vfsmnt, &lock_level);
+@@ -225,7 +107,6 @@
+       ocfs2_meta_unlock(file->f_dentry->d_inode, lock_level);
+ out:
+       vma->vm_ops = &ocfs2_file_vm_ops;
+-      vma->vm_flags |= VM_CAN_INVALIDATE | VM_CAN_NONLINEAR;
+       return 0;
+ }
  
-@@ -152,18 +152,11 @@
-       struct iscsi_cmd_task   *ctask;         /* xmit ctask in progress */
+diff -Nurb linux-2.6.22-590/fs/ocfs2/namei.c linux-2.6.22-570/fs/ocfs2/namei.c
+--- linux-2.6.22-590/fs/ocfs2/namei.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/namei.c  2008-01-23 19:16:04.000000000 -0500
+@@ -1684,7 +1684,7 @@
+               u32 offset = 0;
  
-       /* xmit */
--      struct kfifo            *immqueue;      /* immediate xmit queue */
-       struct kfifo            *mgmtqueue;     /* mgmt (control) xmit queue */
-       struct list_head        mgmt_run_list;  /* list of control tasks */
-       struct list_head        xmitqueue;      /* data-path cmd queue */
-       struct list_head        run_list;       /* list of cmds in progress */
-       struct work_struct      xmitwork;       /* per-conn. xmit workqueue */
+               inode->i_op = &ocfs2_symlink_inode_operations;
+-              status = ocfs2_do_extend_allocation(osb, inode, &offset, 1, 0,
++              status = ocfs2_do_extend_allocation(osb, inode, &offset, 1,
+                                                   new_fe_bh,
+                                                   handle, data_ac, NULL,
+                                                   NULL);
+diff -Nurb linux-2.6.22-590/fs/ocfs2/ocfs2.h linux-2.6.22-570/fs/ocfs2/ocfs2.h
+--- linux-2.6.22-590/fs/ocfs2/ocfs2.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/ocfs2.h  2008-01-23 19:16:04.000000000 -0500
+@@ -220,7 +220,6 @@
+       u16 max_slots;
+       s16 node_num;
+       s16 slot_num;
+-      s16 preferred_slot;
+       int s_sectsize_bits;
+       int s_clustersize;
+       int s_clustersize_bits;
+@@ -307,19 +306,6 @@
+       return 0;
+ }
+-static inline int ocfs2_writes_unwritten_extents(struct ocfs2_super *osb)
+-{
 -      /*
--       * serializes connection xmit, access to kfifos:
--       * xmitqueue, immqueue, mgmtqueue
+-       * Support for sparse files is a pre-requisite
 -       */
--      struct mutex            xmitmutex;
+-      if (!ocfs2_sparse_alloc(osb))
+-              return 0;
 -
-       unsigned long           suspend_tx;     /* suspend Tx */
-       unsigned long           suspend_rx;     /* suspend Rx */
+-      if (osb->s_feature_ro_compat & OCFS2_FEATURE_RO_COMPAT_UNWRITTEN)
+-              return 1;
+-      return 0;
+-}
+-
+ /* set / clear functions because cluster events can make these happen
+  * in parallel so we want the transitions to be atomic. this also
+  * means that any future flags osb_flags must be protected by spinlock
+diff -Nurb linux-2.6.22-590/fs/ocfs2/ocfs2_fs.h linux-2.6.22-570/fs/ocfs2/ocfs2_fs.h
+--- linux-2.6.22-590/fs/ocfs2/ocfs2_fs.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/ocfs2_fs.h       2008-01-23 19:16:04.000000000 -0500
+@@ -88,7 +88,7 @@
+ #define OCFS2_FEATURE_COMPAT_SUPP     OCFS2_FEATURE_COMPAT_BACKUP_SB
+ #define OCFS2_FEATURE_INCOMPAT_SUPP   (OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \
+                                        | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC)
+-#define OCFS2_FEATURE_RO_COMPAT_SUPP  OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
++#define OCFS2_FEATURE_RO_COMPAT_SUPP  0
  
-@@ -174,8 +167,8 @@
-       int                     tmabort_state;  /* see TMABORT_INITIAL, etc.*/
+ /*
+  * Heartbeat-only devices are missing journals and other files.  The
+@@ -116,11 +116,6 @@
+  */
+ #define OCFS2_FEATURE_COMPAT_BACKUP_SB                0x0001
  
-       /* negotiated params */
--      int                     max_recv_dlength; /* initiator_max_recv_dsl*/
--      int                     max_xmit_dlength; /* target_max_recv_dsl */
-+      unsigned                max_recv_dlength; /* initiator_max_recv_dsl*/
-+      unsigned                max_xmit_dlength; /* target_max_recv_dsl */
-       int                     hdrdgst_en;
-       int                     datadgst_en;
-       int                     ifmarker_en;
-@@ -183,6 +176,12 @@
-       /* values userspace uses to id a conn */
-       int                     persistent_port;
-       char                    *persistent_address;
-+      /* remote portal currently connected to */
-+      int                     portal_port;
-+      char                    portal_address[ISCSI_ADDRESS_BUF_LEN];
-+      /* local address */
-+      int                     local_port;
-+      char                    local_address[ISCSI_ADDRESS_BUF_LEN];
+-/*
+- * Unwritten extents support.
+- */
+-#define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN     0x0001
+-
+ /* The byte offset of the first backup block will be 1G.
+  * The following will be 4G, 16G, 64G, 256G and 1T.
+  */
+@@ -179,32 +174,6 @@
+ #define OCFS2_IOC32_SETFLAGS  _IOW('f', 2, int)
  
-       /* MIB-statistics */
-       uint64_t                txdata_octets;
-@@ -213,18 +212,25 @@
+ /*
+- * Space reservation / allocation / free ioctls and argument structure
+- * are designed to be compatible with XFS.
+- *
+- * ALLOCSP* and FREESP* are not and will never be supported, but are
+- * included here for completeness.
+- */
+-struct ocfs2_space_resv {
+-      __s16           l_type;
+-      __s16           l_whence;
+-      __s64           l_start;
+-      __s64           l_len;          /* len == 0 means until end of file */
+-      __s32           l_sysid;
+-      __u32           l_pid;
+-      __s32           l_pad[4];       /* reserve area                     */
+-};
+-
+-#define OCFS2_IOC_ALLOCSP             _IOW ('X', 10, struct ocfs2_space_resv)
+-#define OCFS2_IOC_FREESP              _IOW ('X', 11, struct ocfs2_space_resv)
+-#define OCFS2_IOC_RESVSP              _IOW ('X', 40, struct ocfs2_space_resv)
+-#define OCFS2_IOC_UNRESVSP    _IOW ('X', 41, struct ocfs2_space_resv)
+-#define OCFS2_IOC_ALLOCSP64   _IOW ('X', 36, struct ocfs2_space_resv)
+-#define OCFS2_IOC_FREESP64    _IOW ('X', 37, struct ocfs2_space_resv)
+-#define OCFS2_IOC_RESVSP64    _IOW ('X', 42, struct ocfs2_space_resv)
+-#define OCFS2_IOC_UNRESVSP64  _IOW ('X', 43, struct ocfs2_space_resv)
+-
+-/*
+  * Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
+  */
+ #define OCFS2_JOURNAL_DIRTY_FL        (0x00000001)    /* Journal needs recovery */
+diff -Nurb linux-2.6.22-590/fs/ocfs2/slot_map.c linux-2.6.22-570/fs/ocfs2/slot_map.c
+--- linux-2.6.22-590/fs/ocfs2/slot_map.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/slot_map.c       2007-07-08 19:32:17.000000000 -0400
+@@ -121,25 +121,17 @@
+       return ret;
+ }
  
-       /* configuration */
-       int                     initial_r2t_en;
--      int                     max_r2t;
-+      unsigned                max_r2t;
-       int                     imm_data_en;
--      int                     first_burst;
--      int                     max_burst;
-+      unsigned                first_burst;
-+      unsigned                max_burst;
-       int                     time2wait;
-       int                     time2retain;
-       int                     pdu_inorder_en;
-       int                     dataseq_inorder_en;
-       int                     erl;
-       int                     tpgt;
-+      char                    *username;
-+      char                    *username_in;
-+      char                    *password;
-+      char                    *password_in;
-       char                    *targetname;
+-static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, s16 preferred)
++static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si)
+ {
+       int i;
+       s16 ret = OCFS2_INVALID_SLOT;
+-      if (preferred >= 0 && preferred < si->si_num_slots) {
+-              if (OCFS2_INVALID_SLOT == si->si_global_node_nums[preferred]) {
+-                      ret = preferred;
+-                      goto out;
+-              }
+-      }
 -
-+      char                    *initiatorname;
-+      /* hw address or netdev iscsi connection is bound to */
-+      char                    *hwaddress;
-+      char                    *netdev;
-       /* control data */
-       struct iscsi_transport  *tt;
-       struct Scsi_Host        *host;
-@@ -255,12 +261,22 @@
- extern int iscsi_queuecommand(struct scsi_cmnd *sc,
-                             void (*done)(struct scsi_cmnd *));
+       for(i = 0; i < si->si_num_slots; i++) {
+               if (OCFS2_INVALID_SLOT == si->si_global_node_nums[i]) {
+                       ret = (s16) i;
+                       break;
+               }
+       }
+-out:
+       return ret;
+ }
+@@ -256,7 +248,7 @@
+       if (slot == OCFS2_INVALID_SLOT) {
+               /* if no slot yet, then just take 1st available
+                * one. */
+-              slot = __ocfs2_find_empty_slot(si, osb->preferred_slot);
++              slot = __ocfs2_find_empty_slot(si);
+               if (slot == OCFS2_INVALID_SLOT) {
+                       spin_unlock(&si->si_lock);
+                       mlog(ML_ERROR, "no free slots available!\n");
+diff -Nurb linux-2.6.22-590/fs/ocfs2/suballoc.c linux-2.6.22-570/fs/ocfs2/suballoc.c
+--- linux-2.6.22-590/fs/ocfs2/suballoc.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/suballoc.c       2007-07-08 19:32:17.000000000 -0400
+@@ -98,6 +98,14 @@
+                                   u16 chain);
+ static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg,
+                                                    u32 wanted);
++static int ocfs2_free_suballoc_bits(handle_t *handle,
++                                  struct inode *alloc_inode,
++                                  struct buffer_head *alloc_bh,
++                                  unsigned int start_bit,
++                                  u64 bg_blkno,
++                                  unsigned int count);
++static inline u64 ocfs2_which_suballoc_group(u64 block,
++                                           unsigned int bit);
+ static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
+                                                  u64 bg_blkno,
+                                                  u16 bg_bit_off);
+@@ -488,7 +496,13 @@
  
+       (*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe);
+       (*ac)->ac_which = OCFS2_AC_USE_META;
 +
-+/*
-+ * iSCSI host helpers.
-+ */
-+extern int iscsi_host_set_param(struct Scsi_Host *shost,
-+                              enum iscsi_host_param param, char *buf,
-+                              int buflen);
-+extern int iscsi_host_get_param(struct Scsi_Host *shost,
-+                              enum iscsi_host_param param, char *buf);
++#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
++      slot = 0;
++#else
+       slot = osb->slot_num;
++#endif
 +
+       (*ac)->ac_group_search = ocfs2_block_group_search;
+       status = ocfs2_reserve_suballoc_bits(osb, (*ac),
+@@ -1612,7 +1626,7 @@
  /*
-  * session management
-  */
- extern struct iscsi_cls_session *
- iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *,
--                  int, int, uint32_t, uint32_t *);
-+                  uint16_t, uint16_t, int, int, uint32_t, uint32_t *);
- extern void iscsi_session_teardown(struct iscsi_cls_session *);
- extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *);
- extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
-@@ -289,8 +305,7 @@
- /*
-  * pdu and task processing
+  * expects the suballoc inode to already be locked.
   */
--extern int iscsi_check_assign_cmdsn(struct iscsi_session *,
--                                  struct iscsi_nopin *);
-+extern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *);
- extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *,
-                                       struct iscsi_data *hdr);
- extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
-diff -Nurb linux-2.6.22-570/include/scsi/scsi_cmnd.h linux-2.6.22-590/include/scsi/scsi_cmnd.h
---- linux-2.6.22-570/include/scsi/scsi_cmnd.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/scsi/scsi_cmnd.h  2008-01-02 13:56:37.000000000 -0500
-@@ -135,4 +135,24 @@
- extern struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *, gfp_t);
- extern void scsi_free_sgtable(struct scatterlist *, int);
+-int ocfs2_free_suballoc_bits(handle_t *handle,
++static int ocfs2_free_suballoc_bits(handle_t *handle,
+                                   struct inode *alloc_inode,
+                                   struct buffer_head *alloc_bh,
+                                   unsigned int start_bit,
+@@ -1689,6 +1703,13 @@
+       return status;
+ }
  
-+extern int scsi_dma_map(struct scsi_cmnd *cmd);
-+extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
-+
-+#define scsi_sg_count(cmd) ((cmd)->use_sg)
-+#define scsi_sglist(cmd) ((struct scatterlist *)(cmd)->request_buffer)
-+#define scsi_bufflen(cmd) ((cmd)->request_bufflen)
-+
-+static inline void scsi_set_resid(struct scsi_cmnd *cmd, int resid)
++static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
 +{
-+      cmd->resid = resid;
++      u64 group = block - (u64) bit;
++
++      return group;
 +}
 +
-+static inline int scsi_get_resid(struct scsi_cmnd *cmd)
+ int ocfs2_free_dinode(handle_t *handle,
+                     struct inode *inode_alloc_inode,
+                     struct buffer_head *inode_alloc_bh,
+@@ -1702,6 +1723,19 @@
+                                       inode_alloc_bh, bit, bg_blkno, 1);
+ }
++int ocfs2_free_extent_block(handle_t *handle,
++                          struct inode *eb_alloc_inode,
++                          struct buffer_head *eb_alloc_bh,
++                          struct ocfs2_extent_block *eb)
 +{
-+      return cmd->resid;
-+}
++      u64 blk = le64_to_cpu(eb->h_blkno);
++      u16 bit = le16_to_cpu(eb->h_suballoc_bit);
++      u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit);
 +
-+#define scsi_for_each_sg(cmd, sg, nseg, __i)                  \
-+      for (__i = 0, sg = scsi_sglist(cmd); __i < (nseg); __i++, (sg)++)
++      return ocfs2_free_suballoc_bits(handle, eb_alloc_inode, eb_alloc_bh,
++                                      bit, bg_blkno, 1);
++}
 +
- #endif /* _SCSI_SCSI_CMND_H */
-diff -Nurb linux-2.6.22-570/include/scsi/scsi_device.h linux-2.6.22-590/include/scsi/scsi_device.h
---- linux-2.6.22-570/include/scsi/scsi_device.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/scsi/scsi_device.h        2008-01-02 13:56:37.000000000 -0500
-@@ -287,6 +287,7 @@
- extern void scsi_target_unblock(struct device *);
- extern void scsi_remove_target(struct device *);
- extern void int_to_scsilun(unsigned int, struct scsi_lun *);
-+extern int scsilun_to_int(struct scsi_lun *);
- extern const char *scsi_device_state_name(enum scsi_device_state);
- extern int scsi_is_sdev_device(const struct device *);
- extern int scsi_is_target_device(const struct device *);
-diff -Nurb linux-2.6.22-570/include/scsi/scsi_host.h linux-2.6.22-590/include/scsi/scsi_host.h
---- linux-2.6.22-570/include/scsi/scsi_host.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/scsi/scsi_host.h  2008-01-02 13:56:37.000000000 -0500
-@@ -339,12 +339,6 @@
-       enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
+ int ocfs2_free_clusters(handle_t *handle,
+                      struct inode *bitmap_inode,
+                      struct buffer_head *bitmap_bh,
+diff -Nurb linux-2.6.22-590/fs/ocfs2/suballoc.h linux-2.6.22-570/fs/ocfs2/suballoc.h
+--- linux-2.6.22-590/fs/ocfs2/suballoc.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/suballoc.h       2007-07-08 19:32:17.000000000 -0400
+@@ -86,29 +86,20 @@
+                        u32 *cluster_start,
+                        u32 *num_clusters);
  
-       /*
--       * suspend support
--       */
--      int (*resume)(struct scsi_device *);
--      int (*suspend)(struct scsi_device *, pm_message_t state);
+-int ocfs2_free_suballoc_bits(handle_t *handle,
+-                           struct inode *alloc_inode,
+-                           struct buffer_head *alloc_bh,
+-                           unsigned int start_bit,
+-                           u64 bg_blkno,
+-                           unsigned int count);
+ int ocfs2_free_dinode(handle_t *handle,
+                     struct inode *inode_alloc_inode,
+                     struct buffer_head *inode_alloc_bh,
+                     struct ocfs2_dinode *di);
++int ocfs2_free_extent_block(handle_t *handle,
++                          struct inode *eb_alloc_inode,
++                          struct buffer_head *eb_alloc_bh,
++                          struct ocfs2_extent_block *eb);
+ int ocfs2_free_clusters(handle_t *handle,
+                       struct inode *bitmap_inode,
+                       struct buffer_head *bitmap_bh,
+                       u64 start_blk,
+                       unsigned int num_clusters);
+-static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
+-{
+-      u64 group = block - (u64) bit;
 -
--      /*
-        * Name of proc directory
-        */
-       char *proc_name;
-@@ -677,6 +671,10 @@
- #define shost_printk(prefix, shost, fmt, a...)        \
-       dev_printk(prefix, &(shost)->shost_gendev, fmt, ##a)
+-      return group;
+-}
+-
+ static inline u32 ocfs2_cluster_from_desc(struct ocfs2_super *osb,
+                                         u64 bg_blkno)
+ {
+diff -Nurb linux-2.6.22-590/fs/ocfs2/super.c linux-2.6.22-570/fs/ocfs2/super.c
+--- linux-2.6.22-590/fs/ocfs2/super.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/super.c  2008-01-23 19:16:15.000000000 -0500
+@@ -82,8 +82,7 @@
+ MODULE_LICENSE("GPL");
  
-+static inline void *shost_priv(struct Scsi_Host *shost)
-+{
-+      return (void *)shost->hostdata;
-+}
+ static int ocfs2_parse_options(struct super_block *sb, char *options,
+-                             unsigned long *mount_opt, s16 *slot,
+-                             int is_remount);
++                             unsigned long *mount_opt, int is_remount);
+ static void ocfs2_put_super(struct super_block *sb);
+ static int ocfs2_mount_volume(struct super_block *sb);
+ static int ocfs2_remount(struct super_block *sb, int *flags, char *data);
+@@ -115,6 +114,8 @@
+ static struct inode *ocfs2_alloc_inode(struct super_block *sb);
+ static void ocfs2_destroy_inode(struct inode *inode);
  
- int scsi_is_host_device(const struct device *);
++static unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
++
+ static const struct super_operations ocfs2_sops = {
+       .statfs         = ocfs2_statfs,
+       .alloc_inode    = ocfs2_alloc_inode,
+@@ -322,7 +323,7 @@
+ /* From xfs_super.c:xfs_max_file_offset
+  * Copyright (c) 2000-2004 Silicon Graphics, Inc.
+  */
+-unsigned long long ocfs2_max_file_offset(unsigned int blockshift)
++static unsigned long long ocfs2_max_file_offset(unsigned int blockshift)
+ {
+       unsigned int pagefactor = 1;
+       unsigned int bitshift = BITS_PER_LONG - 1;
+@@ -359,10 +360,9 @@
+       int incompat_features;
+       int ret = 0;
+       unsigned long parsed_options;
+-      s16 slot;
+       struct ocfs2_super *osb = OCFS2_SB(sb);
  
-diff -Nurb linux-2.6.22-570/include/scsi/scsi_transport_fc.h linux-2.6.22-590/include/scsi/scsi_transport_fc.h
---- linux-2.6.22-570/include/scsi/scsi_transport_fc.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/scsi/scsi_transport_fc.h  2008-01-02 13:56:37.000000000 -0500
-@@ -19,7 +19,7 @@
-  *
-  *  ========
-  *
-- *  Copyright (C) 2004-2005   James Smart, Emulex Corporation
-+ *  Copyright (C) 2004-2007   James Smart, Emulex Corporation
-  *    Rewrite for host, target, device, and remote port attributes,
-  *    statistics, and service functions...
-  *
-@@ -62,8 +62,10 @@
-       FC_PORTTYPE_NLPORT,             /* (Public) Loop w/ FLPort */
-       FC_PORTTYPE_LPORT,              /* (Private) Loop w/o FLPort */
-       FC_PORTTYPE_PTP,                /* Point to Point w/ another NPort */
-+      FC_PORTTYPE_NPIV,               /* VPORT based on NPIV */
- };
+-      if (!ocfs2_parse_options(sb, data, &parsed_options, &slot, 1)) {
++      if (!ocfs2_parse_options(sb, data, &parsed_options, 1)) {
+               ret = -EINVAL;
+               goto out;
+       }
+@@ -546,7 +546,6 @@
+       struct dentry *root;
+       int status, sector_size;
+       unsigned long parsed_opt;
+-      s16 slot;
+       struct inode *inode = NULL;
+       struct ocfs2_super *osb = NULL;
+       struct buffer_head *bh = NULL;
+@@ -554,7 +553,7 @@
  
-+
- /*
-  * fc_port_state: If you alter this, you also need to alter scsi_transport_fc.c
-  * (for the ascii descriptions).
-@@ -84,6 +86,25 @@
+       mlog_entry("%p, %p, %i", sb, data, silent);
  
+-      if (!ocfs2_parse_options(sb, data, &parsed_opt, &slot, 0)) {
++      if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
+               status = -EINVAL;
+               goto read_super_error;
+       }
+@@ -584,7 +583,6 @@
+       brelse(bh);
+       bh = NULL;
+       osb->s_mount_opt = parsed_opt;
+-      osb->preferred_slot = slot;
  
- /* 
-+ * fc_vport_state: If you alter this, you also need to alter
-+ * scsi_transport_fc.c (for the ascii descriptions).
-+ */
-+enum fc_vport_state {
-+      FC_VPORT_UNKNOWN,
-+      FC_VPORT_ACTIVE,
-+      FC_VPORT_DISABLED,
-+      FC_VPORT_LINKDOWN,
-+      FC_VPORT_INITIALIZING,
-+      FC_VPORT_NO_FABRIC_SUPP,
-+      FC_VPORT_NO_FABRIC_RSCS,
-+      FC_VPORT_FABRIC_LOGOUT,
-+      FC_VPORT_FABRIC_REJ_WWN,
-+      FC_VPORT_FAILED,
-+};
-+
-+
-+
-+/*
-  * FC Classes of Service
-  * Note: values are not enumerated, as they can be "or'd" together
-  * for reporting (e.g. report supported_classes). If you alter this list,
-@@ -124,18 +145,116 @@
- };
+       sb->s_magic = OCFS2_SUPER_MAGIC;
  
- /*
-- * FC Remote Port Roles
-+ * FC Port Roles
-  * Note: values are not enumerated, as they can be "or'd" together
-  * for reporting (e.g. report roles). If you alter this list,
-  * you also need to alter scsi_transport_fc.c (for the ascii descriptions).
-  */
--#define FC_RPORT_ROLE_UNKNOWN                 0x00
--#define FC_RPORT_ROLE_FCP_TARGET              0x01
--#define FC_RPORT_ROLE_FCP_INITIATOR           0x02
--#define FC_RPORT_ROLE_IP_PORT                 0x04
-+#define FC_PORT_ROLE_UNKNOWN                  0x00
-+#define FC_PORT_ROLE_FCP_TARGET                       0x01
-+#define FC_PORT_ROLE_FCP_INITIATOR            0x02
-+#define FC_PORT_ROLE_IP_PORT                  0x04
-+
-+/* The following are for compatibility */
-+#define FC_RPORT_ROLE_UNKNOWN                 FC_PORT_ROLE_UNKNOWN
-+#define FC_RPORT_ROLE_FCP_TARGET              FC_PORT_ROLE_FCP_TARGET
-+#define FC_RPORT_ROLE_FCP_INITIATOR           FC_PORT_ROLE_FCP_INITIATOR
-+#define FC_RPORT_ROLE_IP_PORT                 FC_PORT_ROLE_IP_PORT
-+
-+
-+/* Macro for use in defining Virtual Port attributes */
-+#define FC_VPORT_ATTR(_name,_mode,_show,_store)                               \
-+struct class_device_attribute class_device_attr_vport_##_name =       \
-+      __ATTR(_name,_mode,_show,_store)
+@@ -730,7 +728,6 @@
+ static int ocfs2_parse_options(struct super_block *sb,
+                              char *options,
+                              unsigned long *mount_opt,
+-                             s16 *slot,
+                              int is_remount)
+ {
+       int status;
+@@ -740,7 +737,6 @@
+                  options ? options : "(none)");
  
+       *mount_opt = 0;
+-      *slot = OCFS2_INVALID_SLOT;
  
- /*
-+ * FC Virtual Port Attributes
-+ *
-+ * This structure exists for each FC port is a virtual FC port. Virtual
-+ * ports share the physical link with the Physical port. Each virtual
-+ * ports has a unique presense on the SAN, and may be instantiated via
-+ * NPIV, Virtual Fabrics, or via additional ALPAs. As the vport is a
-+ * unique presense, each vport has it's own view of the fabric,
-+ * authentication priviledge, and priorities.
-+ *
-+ * A virtual port may support 1 or more FC4 roles. Typically it is a
-+ * FCP Initiator. It could be a FCP Target, or exist sole for an IP over FC
-+ * roles. FC port attributes for the vport will be reported on any
-+ * fc_host class object allocated for an FCP Initiator.
-+ *
-+ * --
-+ *
-+ * Fixed attributes are not expected to change. The driver is
-+ * expected to set these values after receiving the fc_vport structure
-+ * via the vport_create() call from the transport.
-+ * The transport fully manages all get functions w/o driver interaction.
-+ *
-+ * Dynamic attributes are expected to change. The driver participates
-+ * in all get/set operations via functions provided by the driver.
-+ *
-+ * Private attributes are transport-managed values. They are fully
-+ * managed by the transport w/o driver interaction.
-+ */
-+
-+#define FC_VPORT_SYMBOLIC_NAMELEN             64
-+struct fc_vport {
-+      /* Fixed Attributes */
-+
-+      /* Dynamic Attributes */
-+
-+      /* Private (Transport-managed) Attributes */
-+      enum fc_vport_state vport_state;
-+      enum fc_vport_state vport_last_state;
-+      u64 node_name;
-+      u64 port_name;
-+      u32 roles;
-+      u32 vport_id;           /* Admin Identifier for the vport */
-+      enum fc_port_type vport_type;
-+      char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
-+
-+      /* exported data */
-+      void *dd_data;                  /* Used for driver-specific storage */
-+
-+      /* internal data */
-+      struct Scsi_Host *shost;        /* Physical Port Parent */
-+      unsigned int channel;
-+      u32 number;
-+      u8 flags;
-+      struct list_head peers;
-+      struct device dev;
-+      struct work_struct vport_delete_work;
-+} __attribute__((aligned(sizeof(unsigned long))));
-+
-+/* bit field values for struct fc_vport "flags" field: */
-+#define FC_VPORT_CREATING             0x01
-+#define FC_VPORT_DELETING             0x02
-+#define FC_VPORT_DELETED              0x04
-+#define FC_VPORT_DEL                  0x06    /* Any DELETE state */
-+
-+#define       dev_to_vport(d)                         \
-+      container_of(d, struct fc_vport, dev)
-+#define transport_class_to_vport(classdev)    \
-+      dev_to_vport(classdev->dev)
-+#define vport_to_shost(v)                     \
-+      (v->shost)
-+#define vport_to_shost_channel(v)             \
-+      (v->channel)
-+#define vport_to_parent(v)                    \
-+      (v->dev.parent)
-+
-+
-+/* Error return codes for vport_create() callback */
-+#define VPCERR_UNSUPPORTED            -ENOSYS         /* no driver/adapter
-+                                                         support */
-+#define VPCERR_BAD_WWN                        -ENOTUNIQ       /* driver validation
-+                                                         of WWNs failed */
-+#define VPCERR_NO_FABRIC_SUPP         -EOPNOTSUPP     /* Fabric connection
-+                                                         is loop or the
-+                                                         Fabric Port does
-+                                                         not support NPIV */
-+
-+/*
-  * fc_rport_identifiers: This set of data contains all elements
-  * to uniquely identify a remote FC port. The driver uses this data
-  * to report the existence of a remote FC port in the topology. Internally,
-@@ -149,6 +268,7 @@
-       u32 roles;
- };
+       if (!options) {
+               status = 1;
+diff -Nurb linux-2.6.22-590/fs/ocfs2/super.h linux-2.6.22-570/fs/ocfs2/super.h
+--- linux-2.6.22-590/fs/ocfs2/super.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ocfs2/super.h  2007-07-08 19:32:17.000000000 -0400
+@@ -45,6 +45,4 @@
  
-+
- /* Macro for use in defining Remote Port attributes */
- #define FC_RPORT_ATTR(_name,_mode,_show,_store)                               \
- struct class_device_attribute class_device_attr_rport_##_name =       \
-@@ -343,6 +463,7 @@
-       u8  supported_fc4s[FC_FC4_LIST_SIZE];
-       u32 supported_speeds;
-       u32 maxframe_size;
-+      u16 max_npiv_vports;
-       char serial_number[FC_SERIAL_NUMBER_SIZE];
+ #define ocfs2_abort(sb, fmt, args...) __ocfs2_abort(sb, __PRETTY_FUNCTION__, fmt, ##args)
  
-       /* Dynamic Attributes */
-@@ -361,8 +482,11 @@
-       /* internal data */
-       struct list_head rports;
-       struct list_head rport_bindings;
-+      struct list_head vports;
-       u32 next_rport_number;
-       u32 next_target_id;
-+      u32 next_vport_number;
-+      u16 npiv_vports_inuse;
+-unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
+-
+ #endif /* OCFS2_SUPER_H */
+diff -Nurb linux-2.6.22-590/fs/open.c linux-2.6.22-570/fs/open.c
+--- linux-2.6.22-590/fs/open.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/open.c 2008-01-23 19:16:04.000000000 -0500
+@@ -362,92 +362,6 @@
+ #endif
  
-       /* work queues for rport state manipulation */
-       char work_q_name[KOBJ_NAME_LEN];
-@@ -388,6 +512,8 @@
-       (((struct fc_host_attrs *)(x)->shost_data)->supported_speeds)
- #define fc_host_maxframe_size(x)      \
-       (((struct fc_host_attrs *)(x)->shost_data)->maxframe_size)
-+#define fc_host_max_npiv_vports(x)    \
-+      (((struct fc_host_attrs *)(x)->shost_data)->max_npiv_vports)
- #define fc_host_serial_number(x)      \
-       (((struct fc_host_attrs *)(x)->shost_data)->serial_number)
- #define fc_host_port_id(x)    \
-@@ -412,10 +538,16 @@
-       (((struct fc_host_attrs *)(x)->shost_data)->rports)
- #define fc_host_rport_bindings(x) \
-       (((struct fc_host_attrs *)(x)->shost_data)->rport_bindings)
-+#define fc_host_vports(x) \
-+      (((struct fc_host_attrs *)(x)->shost_data)->vports)
- #define fc_host_next_rport_number(x) \
-       (((struct fc_host_attrs *)(x)->shost_data)->next_rport_number)
- #define fc_host_next_target_id(x) \
-       (((struct fc_host_attrs *)(x)->shost_data)->next_target_id)
-+#define fc_host_next_vport_number(x) \
-+      (((struct fc_host_attrs *)(x)->shost_data)->next_vport_number)
-+#define fc_host_npiv_vports_inuse(x)  \
-+      (((struct fc_host_attrs *)(x)->shost_data)->npiv_vports_inuse)
- #define fc_host_work_q_name(x) \
-       (((struct fc_host_attrs *)(x)->shost_data)->work_q_name)
- #define fc_host_work_q(x) \
-@@ -452,8 +584,14 @@
-       void    (*dev_loss_tmo_callbk)(struct fc_rport *);
-       void    (*terminate_rport_io)(struct fc_rport *);
+ /*
+- * sys_fallocate - preallocate blocks or free preallocated blocks
+- * @fd: the file descriptor
+- * @mode: mode specifies if fallocate should preallocate blocks OR free
+- *      (unallocate) preallocated blocks. Currently only FA_ALLOCATE and
+- *      FA_DEALLOCATE modes are supported.
+- * @offset: The offset within file, from where (un)allocation is being
+- *        requested. It should not have a negative value.
+- * @len: The amount (in bytes) of space to be (un)allocated, from the offset.
+- *
+- * This system call, depending on the mode, preallocates or unallocates blocks
+- * for a file. The range of blocks depends on the value of offset and len
+- * arguments provided by the user/application. For FA_ALLOCATE mode, if this
+- * system call succeeds, subsequent writes to the file in the given range
+- * (specified by offset & len) should not fail - even if the file system
+- * later becomes full. Hence the preallocation done is persistent (valid
+- * even after reopen of the file and remount/reboot).
+- *
+- * It is expected that the ->fallocate() inode operation implemented by the
+- * individual file systems will update the file size and/or ctime/mtime
+- * depending on the mode and also on the success of the operation.
+- *
+- * Note: Incase the file system does not support preallocation,
+- * posix_fallocate() should fall back to the library implementation (i.e.
+- * allocating zero-filled new blocks to the file).
+- *
+- * Return Values
+- *    0       : On SUCCESS a value of zero is returned.
+- *    error   : On Failure, an error code will be returned.
+- * An error code of -ENOSYS or -EOPNOTSUPP should make posix_fallocate()
+- * fall back on library implementation of fallocate.
+- *
+- * <TBD> Generic fallocate to be added for file systems that do not
+- *     support fallocate it.
+- */
+-asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len)
+-{
+-      struct file *file;
+-      struct inode *inode;
+-      long ret = -EINVAL;
+-
+-      if (offset < 0 || len <= 0)
+-              goto out;
+-
+-      /* Return error if mode is not supported */
+-      ret = -EOPNOTSUPP;
+-      if (mode != FA_ALLOCATE && mode !=FA_DEALLOCATE)
+-              goto out;
+-
+-      ret = -EBADF;
+-      file = fget(fd);
+-      if (!file)
+-              goto out;
+-      if (!(file->f_mode & FMODE_WRITE))
+-              goto out_fput;
+-
+-      inode = file->f_path.dentry->d_inode;
+-
+-      ret = -ESPIPE;
+-      if (S_ISFIFO(inode->i_mode))
+-              goto out_fput;
+-
+-      ret = -ENODEV;
+-      /*
+-       * Let individual file system decide if it supports preallocation
+-       * for directories or not.
+-       */
+-      if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
+-              goto out_fput;
+-
+-      ret = -EFBIG;
+-      /* Check for wrap through zero too */
+-      if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
+-              goto out_fput;
+-
+-      if (inode->i_op && inode->i_op->fallocate)
+-              ret = inode->i_op->fallocate(inode, mode, offset, len);
+-      else
+-              ret = -ENOSYS;
+-
+-out_fput:
+-      fput(file);
+-out:
+-      return ret;
+-}
+-
+-/*
+  * access() needs to use the real uid/gid, not the effective uid/gid.
+  * We do this by temporarily clearing all FS-related capabilities and
+  * switching the fsuid/fsgid around to the real ones.
+diff -Nurb linux-2.6.22-590/fs/partitions/check.c linux-2.6.22-570/fs/partitions/check.c
+--- linux-2.6.22-590/fs/partitions/check.c     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/partitions/check.c     2007-07-08 19:32:17.000000000 -0400
+@@ -397,6 +397,7 @@
+               static struct attribute addpartattr = {
+                       .name = "whole_disk",
+                       .mode = S_IRUSR | S_IRGRP | S_IROTH,
++                      .owner = THIS_MODULE,
+               };
  
-+      void    (*set_vport_symbolic_name)(struct fc_vport *);
-+      int     (*vport_create)(struct fc_vport *, bool);
-+      int     (*vport_disable)(struct fc_vport *, bool);
-+      int     (*vport_delete)(struct fc_vport *);
-+
-       /* allocation lengths for host-specific data */
-       u32                             dd_fcrport_size;
-+      u32                             dd_fcvport_size;
+               sysfs_create_file(&p->kobj, &addpartattr);
+diff -Nurb linux-2.6.22-590/fs/proc/Makefile linux-2.6.22-570/fs/proc/Makefile
+--- linux-2.6.22-590/fs/proc/Makefile  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/proc/Makefile  2007-07-08 19:32:17.000000000 -0400
+@@ -11,7 +11,6 @@
+               proc_tty.o proc_misc.o
  
-       /* 
-        * The driver sets these to tell the transport class it
-@@ -512,7 +650,7 @@
+ proc-$(CONFIG_PROC_SYSCTL)    += proc_sysctl.o
+-proc-$(CONFIG_NET)            += proc_net.o
+ proc-$(CONFIG_PROC_KCORE)     += kcore.o
+ proc-$(CONFIG_PROC_VMCORE)    += vmcore.o
+ proc-$(CONFIG_PROC_DEVICETREE)        += proc_devtree.o
+diff -Nurb linux-2.6.22-590/fs/proc/array.c linux-2.6.22-570/fs/proc/array.c
+--- linux-2.6.22-590/fs/proc/array.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/proc/array.c   2008-01-23 19:16:04.000000000 -0500
+@@ -291,15 +291,6 @@
+       return buffer;
+ }
  
-       switch (rport->port_state) {
-       case FC_PORTSTATE_ONLINE:
--              if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
-+              if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
-                       result = 0;
-               else if (rport->flags & FC_RPORT_DEVLOSS_PENDING)
-                       result = DID_IMM_RETRY << 16;
-@@ -549,6 +687,27 @@
-       wwn[7] = inm & 0xff;
+-static inline char *task_context_switch_counts(struct task_struct *p,
+-                                              char *buffer)
+-{
+-      return buffer + sprintf(buffer, "voluntary_ctxt_switches:\t%lu\n"
+-                          "nonvoluntary_ctxt_switches:\t%lu\n",
+-                          p->nvcsw,
+-                          p->nivcsw);
+-}
+-
+ static inline char *task_cap(struct task_struct *p, char *buffer)
+ {
+       struct vx_info *vxi = p->vx_info;
+@@ -337,7 +328,6 @@
+ #if defined(CONFIG_S390)
+       buffer = task_show_regs(task, buffer);
+ #endif
+-      buffer = task_context_switch_counts(task, buffer);
+       return buffer - orig;
  }
  
-+/**
-+ * fc_vport_set_state() - called to set a vport's state. Saves the old state,
-+ *   excepting the transitory states of initializing and sending the ELS
-+ *   traffic to instantiate the vport on the link.
-+ *
-+ * Assumes the driver has surrounded this with the proper locking to ensure
-+ * a coherent state change.
-+ *
-+ * @vport:    virtual port whose state is changing
-+ * @new_state:  new state
-+ **/
-+static inline void
-+fc_vport_set_state(struct fc_vport *vport, enum fc_vport_state new_state)
-+{
-+      if ((new_state != FC_VPORT_UNKNOWN) &&
-+          (new_state != FC_VPORT_INITIALIZING))
-+              vport->vport_last_state = vport->vport_state;
-+      vport->vport_state = new_state;
-+}
-+
-+
- struct scsi_transport_template *fc_attach_transport(
-                       struct fc_function_template *);
- void fc_release_transport(struct scsi_transport_template *);
-@@ -567,5 +726,6 @@
-        *   be sure to read the Vendor Type and ID formatting requirements
-        *   specified in scsi_netlink.h
-        */
-+int fc_vport_terminate(struct fc_vport *vport);
+@@ -436,9 +426,8 @@
  
- #endif /* SCSI_TRANSPORT_FC_H */
-diff -Nurb linux-2.6.22-570/include/scsi/scsi_transport_iscsi.h linux-2.6.22-590/include/scsi/scsi_transport_iscsi.h
---- linux-2.6.22-570/include/scsi/scsi_transport_iscsi.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/include/scsi/scsi_transport_iscsi.h       2008-01-02 13:56:37.000000000 -0500
-@@ -79,7 +79,8 @@
-       char *name;
-       unsigned int caps;
-       /* LLD sets this to indicate what values it can export to sysfs */
--      unsigned int param_mask;
-+      uint64_t param_mask;
-+      uint64_t host_param_mask;
-       struct scsi_host_template *host_template;
-       /* LLD connection data size */
-       int conndata_size;
-@@ -89,7 +90,8 @@
-       unsigned int max_conn;
-       unsigned int max_cmd_len;
-       struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it,
--              struct scsi_transport_template *t, uint32_t sn, uint32_t *hn);
-+              struct scsi_transport_template *t, uint16_t, uint16_t,
-+              uint32_t sn, uint32_t *hn);
-       void (*destroy_session) (struct iscsi_cls_session *session);
-       struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
-                               uint32_t cid);
-@@ -105,14 +107,18 @@
-                              enum iscsi_param param, char *buf);
-       int (*get_session_param) (struct iscsi_cls_session *session,
-                                 enum iscsi_param param, char *buf);
-+      int (*get_host_param) (struct Scsi_Host *shost,
-+                              enum iscsi_host_param param, char *buf);
-+      int (*set_host_param) (struct Scsi_Host *shost,
-+                             enum iscsi_host_param param, char *buf,
-+                             int buflen);
-       int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
-                        char *data, uint32_t data_size);
-       void (*get_stats) (struct iscsi_cls_conn *conn,
-                          struct iscsi_stats *stats);
-       void (*init_cmd_task) (struct iscsi_cmd_task *ctask);
-       void (*init_mgmt_task) (struct iscsi_conn *conn,
--                              struct iscsi_mgmt_task *mtask,
--                              char *data, uint32_t data_size);
-+                              struct iscsi_mgmt_task *mtask);
-       int (*xmit_cmd_task) (struct iscsi_conn *conn,
-                             struct iscsi_cmd_task *ctask);
-       void (*cleanup_cmd_task) (struct iscsi_conn *conn,
-@@ -124,7 +130,7 @@
-                          uint64_t *ep_handle);
-       int (*ep_poll) (uint64_t ep_handle, int timeout_ms);
-       void (*ep_disconnect) (uint64_t ep_handle);
--      int (*tgt_dscvr) (enum iscsi_tgt_dscvr type, uint32_t host_no,
-+      int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
-                         uint32_t enable, struct sockaddr *dst_addr);
- };
+       /* Temporary variable needed for gcc-2.96 */
+       /* convert timespec -> nsec*/
+-      start_time =
+-              (unsigned long long)task->real_start_time.tv_sec * NSEC_PER_SEC
+-                              + task->real_start_time.tv_nsec;
++      start_time = (unsigned long long)task->start_time.tv_sec * NSEC_PER_SEC
++                              + task->start_time.tv_nsec;
+       /* convert nsec -> ticks */
+       start_time = nsec_to_clock_t(start_time);
  
-diff -Nurb linux-2.6.22-570/init/Kconfig linux-2.6.22-590/init/Kconfig
---- linux-2.6.22-570/init/Kconfig      2008-01-02 13:56:29.000000000 -0500
-+++ linux-2.6.22-590/init/Kconfig      2008-01-02 13:56:37.000000000 -0500
-@@ -120,15 +120,6 @@
-         section 6.4 of the Linux Programmer's Guide, available from
-         <http://www.tldp.org/guides.html>.
+diff -Nurb linux-2.6.22-590/fs/proc/base.c linux-2.6.22-570/fs/proc/base.c
+--- linux-2.6.22-590/fs/proc/base.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/proc/base.c    2008-01-23 19:16:04.000000000 -0500
+@@ -67,7 +67,7 @@
+ #include <linux/mount.h>
+ #include <linux/security.h>
+ #include <linux/ptrace.h>
+-#include <linux/container.h>
++#include <linux/seccomp.h>
+ #include <linux/cpuset.h>
+ #include <linux/audit.h>
+ #include <linux/poll.h>
+@@ -490,7 +490,7 @@
+               count = PROC_BLOCK_SIZE;
  
--config IPC_NS
--      bool "IPC Namespaces"
--      depends on SYSVIPC
--      default n
--      help
--        Support ipc namespaces.  This allows containers, i.e. virtual
--        environments, to use ipc namespaces to provide different ipc
--        objects for different servers.  If unsure, say N.
--
- config SYSVIPC_SYSCTL
-       bool
-       depends on SYSVIPC
-@@ -218,13 +209,14 @@
+       length = -ENOMEM;
+-      if (!(page = __get_free_page(GFP_TEMPORARY)))
++      if (!(page = __get_free_page(GFP_KERNEL)))
+               goto out;
  
-         Say N if unsure.
+       length = PROC_I(inode)->op.proc_read(task, (char*)page);
+@@ -530,7 +530,7 @@
+               goto out;
  
--config UTS_NS
--      bool "UTS Namespaces"
-+config USER_NS
-+      bool "User Namespaces (EXPERIMENTAL)"
-       default n
-+      depends on EXPERIMENTAL
-       help
--        Support uts namespaces.  This allows containers, i.e.
--        vservers, to use uts namespaces to provide different
--        uts info for different servers.  If unsure, say N.
-+        Support user namespaces.  This allows containers, i.e.
-+        vservers, to use user namespaces to provide different
-+        user info for different servers.  If unsure, say N.
+       ret = -ENOMEM;
+-      page = (char *)__get_free_page(GFP_TEMPORARY);
++      page = (char *)__get_free_page(GFP_USER);
+       if (!page)
+               goto out;
  
- config AUDIT
-       bool "Auditing support"
-@@ -298,9 +290,23 @@
-       depends on !OOM_PANIC
-       default y
+@@ -600,7 +600,7 @@
+               goto out;
  
-+config CONTAINERS
-+      bool
+       copied = -ENOMEM;
+-      page = (char *)__get_free_page(GFP_TEMPORARY);
++      page = (char *)__get_free_page(GFP_USER);
+       if (!page)
+               goto out;
+@@ -633,7 +633,7 @@
+ }
+ #endif
+-loff_t mem_lseek(struct file * file, loff_t offset, int orig)
++static loff_t mem_lseek(struct file * file, loff_t offset, int orig)
+ {
+       switch (orig) {
+       case 0:
+@@ -711,6 +711,42 @@
+       .write          = oom_adjust_write,
+ };
++#ifdef CONFIG_MMU
++static ssize_t clear_refs_write(struct file *file, const char __user *buf,
++                              size_t count, loff_t *ppos)
++{
++      struct task_struct *task;
++      char buffer[PROC_NUMBUF], *end;
++      struct mm_struct *mm;
 +
-+config CONTAINER_DEBUG
-+      bool "Example debug container subsystem"
-+      select CONTAINERS
-+      help
-+        This option enables a simple container subsystem that
-+        exports useful debugging information about the containers
-+        framework
++      memset(buffer, 0, sizeof(buffer));
++      if (count > sizeof(buffer) - 1)
++              count = sizeof(buffer) - 1;
++      if (copy_from_user(buffer, buf, count))
++              return -EFAULT;
++      if (!simple_strtol(buffer, &end, 0))
++              return -EINVAL;
++      if (*end == '\n')
++              end++;
++      task = get_proc_task(file->f_path.dentry->d_inode);
++      if (!task)
++              return -ESRCH;
++      mm = get_task_mm(task);
++      if (mm) {
++              clear_refs_smap(mm);
++              mmput(mm);
++      }
++      put_task_struct(task);
++      if (end - buffer == 0)
++              return -EIO;
++      return end - buffer;
++}
 +
-+        Say N if unsure
++static struct file_operations proc_clear_refs_operations = {
++      .write          = clear_refs_write,
++};
++#endif
 +
- config CPUSETS
-       bool "Cpuset support"
-       depends on SMP
-+      select CONTAINERS
-       help
-         This option will let you create and manage CPUSETs which
-         allow dynamically partitioning a system into sets of CPUs and
-@@ -329,6 +335,27 @@
-         If you are using a distro that was released in 2006 or later,
-         it should be safe to say N here.
+ #ifdef CONFIG_AUDITSYSCALL
+ #define TMPBUFLEN 21
+ static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
+@@ -750,7 +786,7 @@
+               /* No partial writes. */
+               return -EINVAL;
+       }
+-      page = (char*)__get_free_page(GFP_TEMPORARY);
++      page = (char*)__get_free_page(GFP_USER);
+       if (!page)
+               return -ENOMEM;
+       length = -EFAULT;
+@@ -779,6 +815,71 @@
+ };
+ #endif
  
-+config CONTAINER_CPUACCT
-+      bool "Simple CPU accounting container subsystem"
-+      select CONTAINERS
-+      help
-+        Provides a simple Resource Controller for monitoring the
-+        total CPU consumed by the tasks in a container
-+
-+config CONTAINER_NS
-+        bool "Namespace container subsystem"
-+        select CONTAINERS
-+        help
-+          Provides a simple namespace container subsystem to
-+          provide hierarchical naming of sets of namespaces,
-+          for instance virtual servers and checkpoint/restart
-+          jobs.
-+
-+config PROC_PID_CPUSET
-+      bool "Include legacy /proc/<pid>/cpuset file"
-+      depends on CPUSETS
-+      default y
++#ifdef CONFIG_SECCOMP
++static ssize_t seccomp_read(struct file *file, char __user *buf,
++                          size_t count, loff_t *ppos)
++{
++      struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
++      char __buf[20];
++      size_t len;
 +
- config RELAY
-       bool "Kernel->user space relay support (formerly relayfs)"
-       help
-@@ -605,6 +632,33 @@
- endchoice
-+config PROC_SMAPS
-+      default y
-+      bool "Enable /proc/pid/smaps support" if EMBEDDED && PROC_FS && MMU
-+      help
-+        The /proc/pid/smaps interface reports a process's private and
-+          shared memory per mapping. Disabling this interface will reduce
-+          the size of the kernel for small machines.
++      if (!tsk)
++              return -ESRCH;
++      /* no need to print the trailing zero, so use only len */
++      len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
++      put_task_struct(tsk);
 +
-+config PROC_CLEAR_REFS
-+      default y
-+      bool "Enable /proc/pid/clear_refs support" if EMBEDDED && PROC_FS && MMU
-+      help
-+        The /proc/pid/clear_refs interface allows clearing the
-+          referenced bits on a process's memory maps to allow monitoring
-+          working set size. Disabling this interface will reduce
-+          the size of the kernel for small machines.
++      return simple_read_from_buffer(buf, count, ppos, __buf, len);
++}
 +
-+config PROC_PAGEMAP
-+      default y
-+      bool "Enable /proc/pid/pagemap support" if EMBEDDED && PROC_FS && MMU
-+      help
-+        The /proc/pid/pagemap interface allows reading the
-+          kernel's virtual memory to page frame mapping to determine which
-+          individual pages a process has mapped and which pages it shares
-+          with other processes. Disabling this interface will reduce the
-+          size of the kernel for small machines.
++static ssize_t seccomp_write(struct file *file, const char __user *buf,
++                           size_t count, loff_t *ppos)
++{
++      struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
++      char __buf[20], *end;
++      unsigned int seccomp_mode;
++      ssize_t result;
 +
- endmenu               # General setup
- config RT_MUTEXES
-@@ -620,6 +674,19 @@
-       default 0 if BASE_FULL
-       default 1 if !BASE_FULL
-+config PAGE_GROUP_BY_MOBILITY
-+      bool "Group pages based on their mobility in the page allocator"
-+      def_bool y
-+      help
-+        The standard allocator will fragment memory over time which means
-+        that high order allocations will fail even if kswapd is running. If
-+        this option is set, the allocator will try and group page types
-+        based on their ability to migrate or reclaim. This is a best effort
-+        attempt at lowering fragmentation which a few workloads care about.
-+        The loss is a more complex allocator that may perform slower. If
-+        you are interested in working with large pages, say Y and set
-+        /proc/sys/vm/min_free_bytes to 16374. Otherwise say N
++      result = -ESRCH;
++      if (!tsk)
++              goto out_no_task;
 +
- menu "Loadable module support"
++      /* can set it only once to be even more secure */
++      result = -EPERM;
++      if (unlikely(tsk->seccomp.mode))
++              goto out;
++
++      result = -EFAULT;
++      memset(__buf, 0, sizeof(__buf));
++      count = min(count, sizeof(__buf) - 1);
++      if (copy_from_user(__buf, buf, count))
++              goto out;
++
++      seccomp_mode = simple_strtoul(__buf, &end, 0);
++      if (*end == '\n')
++              end++;
++      result = -EINVAL;
++      if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
++              tsk->seccomp.mode = seccomp_mode;
++              set_tsk_thread_flag(tsk, TIF_SECCOMP);
++      } else
++              goto out;
++      result = -EIO;
++      if (unlikely(!(end - __buf)))
++              goto out;
++      result = end - __buf;
++out:
++      put_task_struct(tsk);
++out_no_task:
++      return result;
++}
++
++static const struct file_operations proc_seccomp_operations = {
++      .read           = seccomp_read,
++      .write          = seccomp_write,
++};
++#endif /* CONFIG_SECCOMP */
++
+ #ifdef CONFIG_FAULT_INJECTION
+ static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
+                                     size_t count, loff_t *ppos)
+@@ -853,8 +954,7 @@
+                           char __user *buffer, int buflen)
+ {
+       struct inode * inode;
+-      char *tmp = (char*)__get_free_page(GFP_TEMPORARY);
+-      char *path;
++      char *tmp = (char*)__get_free_page(GFP_KERNEL), *path;
+       int len;
  
- config MODULES
-diff -Nurb linux-2.6.22-570/init/do_mounts_initrd.c linux-2.6.22-590/init/do_mounts_initrd.c
---- linux-2.6.22-570/init/do_mounts_initrd.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/init/do_mounts_initrd.c   2008-01-02 13:56:37.000000000 -0500
-@@ -56,12 +56,9 @@
-       sys_chroot(".");
+       if (!tmp)
+@@ -915,7 +1015,7 @@
+       task_lock(task);
+       mm = task->mm;
+       if (mm)
+-              dumpable = get_dumpable(mm);
++              dumpable = mm->dumpable;
+       task_unlock(task);
+       if(dumpable == 1)
+               return 1;
+@@ -1644,7 +1744,7 @@
+               goto out;
  
-       pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
--      if (pid > 0) {
--              while (pid != sys_wait4(-1, NULL, 0, NULL)) {
--                      try_to_freeze();
-+      if (pid > 0)
-+              while (pid != sys_wait4(-1, NULL, 0, NULL))
-                       yield();
--              }
--      }
+       length = -ENOMEM;
+-      page = (char*)__get_free_page(GFP_TEMPORARY);
++      page = (char*)__get_free_page(GFP_USER);
+       if (!page)
+               goto out;
  
-       /* move initrd to rootfs' /old */
-       sys_fchdir(old_fd);
-diff -Nurb linux-2.6.22-570/init/main.c linux-2.6.22-590/init/main.c
---- linux-2.6.22-570/init/main.c       2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/init/main.c       2008-01-02 13:56:37.000000000 -0500
-@@ -39,6 +39,7 @@
- #include <linux/writeback.h>
- #include <linux/cpu.h>
- #include <linux/cpuset.h>
-+#include <linux/container.h>
- #include <linux/efi.h>
- #include <linux/tick.h>
- #include <linux/interrupt.h>
-@@ -502,6 +503,7 @@
-       char * command_line;
-       extern struct kernel_param __start___param[], __stop___param[];
+@@ -1704,91 +1804,6 @@
  
-+      container_init_early();
-       smp_setup_processor_id();
+ #endif
  
-       /*
-@@ -627,6 +629,7 @@
- #ifdef CONFIG_PROC_FS
-       proc_root_init();
+-#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
+-static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf,
+-                                       size_t count, loff_t *ppos)
+-{
+-      struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+-      struct mm_struct *mm;
+-      char buffer[PROC_NUMBUF];
+-      size_t len;
+-      int ret;
+-
+-      if (!task)
+-              return -ESRCH;
+-
+-      ret = 0;
+-      mm = get_task_mm(task);
+-      if (mm) {
+-              len = snprintf(buffer, sizeof(buffer), "%08lx\n",
+-                             ((mm->flags & MMF_DUMP_FILTER_MASK) >>
+-                              MMF_DUMP_FILTER_SHIFT));
+-              mmput(mm);
+-              ret = simple_read_from_buffer(buf, count, ppos, buffer, len);
+-      }
+-
+-      put_task_struct(task);
+-
+-      return ret;
+-}
+-
+-static ssize_t proc_coredump_filter_write(struct file *file,
+-                                        const char __user *buf,
+-                                        size_t count,
+-                                        loff_t *ppos)
+-{
+-      struct task_struct *task;
+-      struct mm_struct *mm;
+-      char buffer[PROC_NUMBUF], *end;
+-      unsigned int val;
+-      int ret;
+-      int i;
+-      unsigned long mask;
+-
+-      ret = -EFAULT;
+-      memset(buffer, 0, sizeof(buffer));
+-      if (count > sizeof(buffer) - 1)
+-              count = sizeof(buffer) - 1;
+-      if (copy_from_user(buffer, buf, count))
+-              goto out_no_task;
+-
+-      ret = -EINVAL;
+-      val = (unsigned int)simple_strtoul(buffer, &end, 0);
+-      if (*end == '\n')
+-              end++;
+-      if (end - buffer == 0)
+-              goto out_no_task;
+-
+-      ret = -ESRCH;
+-      task = get_proc_task(file->f_dentry->d_inode);
+-      if (!task)
+-              goto out_no_task;
+-
+-      ret = end - buffer;
+-      mm = get_task_mm(task);
+-      if (!mm)
+-              goto out_no_mm;
+-
+-      for (i = 0, mask = 1; i < MMF_DUMP_FILTER_BITS; i++, mask <<= 1) {
+-              if (val & mask)
+-                      set_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);
+-              else
+-                      clear_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);
+-      }
+-
+-      mmput(mm);
+- out_no_mm:
+-      put_task_struct(task);
+- out_no_task:
+-      return ret;
+-}
+-
+-static const struct file_operations proc_coredump_filter_operations = {
+-      .read           = proc_coredump_filter_read,
+-      .write          = proc_coredump_filter_write,
+-};
+-#endif
+-
+ /*
+  * /proc/self:
+  */
+@@ -1980,22 +1995,18 @@
+       REG("numa_maps",  S_IRUGO, numa_maps),
  #endif
-+      container_init();
-       cpuset_init();
-       taskstats_init_early();
-       delayacct_init();
-diff -Nurb linux-2.6.22-570/ipc/msg.c linux-2.6.22-590/ipc/msg.c
---- linux-2.6.22-570/ipc/msg.c 2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/ipc/msg.c 2008-01-02 13:56:37.000000000 -0500
-@@ -88,7 +88,7 @@
- static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
+       REG("mem",        S_IRUSR|S_IWUSR, mem),
++#ifdef CONFIG_SECCOMP
++      REG("seccomp",    S_IRUSR|S_IWUSR, seccomp),
++#endif
+       LNK("cwd",        cwd),
+       LNK("root",       root),
+       LNK("exe",        exe),
+       REG("mounts",     S_IRUGO, mounts),
+       REG("mountstats", S_IRUSR, mountstats),
+ #ifdef CONFIG_MMU
+-#ifdef CONFIG_PROC_CLEAR_REFS
+       REG("clear_refs", S_IWUSR, clear_refs),
+-#endif
+-#ifdef CONFIG_PROC_SMAPS
+       REG("smaps",      S_IRUGO, smaps),
+ #endif
+-#ifdef CONFIG_PROC_PAGEMAP
+-      REG("pagemap",    S_IRUSR, pagemap),
+-#endif
+-#endif
+ #ifdef CONFIG_SECURITY
+       DIR("attr",       S_IRUGO|S_IXUGO, attr_dir),
+ #endif
+@@ -2005,7 +2016,7 @@
+ #ifdef CONFIG_SCHEDSTATS
+       INF("schedstat",  S_IRUGO, pid_schedstat),
+ #endif
+-#ifdef CONFIG_PROC_PID_CPUSET
++#ifdef CONFIG_CPUSETS
+       REG("cpuset",     S_IRUGO, cpuset),
+ #endif
+       INF("vinfo",      S_IRUGO, pid_vx_info),
+@@ -2018,9 +2029,6 @@
+ #ifdef CONFIG_FAULT_INJECTION
+       REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
+ #endif
+-#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
+-      REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter),
+-#endif
+ #ifdef CONFIG_TASK_IO_ACCOUNTING
+       INF("io",       S_IRUGO, pid_io_accounting),
+ #endif
+@@ -2277,21 +2285,17 @@
+       REG("numa_maps", S_IRUGO, numa_maps),
+ #endif
+       REG("mem",       S_IRUSR|S_IWUSR, mem),
++#ifdef CONFIG_SECCOMP
++      REG("seccomp",   S_IRUSR|S_IWUSR, seccomp),
++#endif
+       LNK("cwd",       cwd),
+       LNK("root",      root),
+       LNK("exe",       exe),
+       REG("mounts",    S_IRUGO, mounts),
+ #ifdef CONFIG_MMU
+-#ifdef CONFIG_PROC_CLEAR_REFS
+       REG("clear_refs", S_IWUSR, clear_refs),
+-#endif
+-#ifdef CONFIG_PROC_SMAPS
+       REG("smaps",     S_IRUGO, smaps),
+ #endif
+-#ifdef CONFIG_PROC_PAGEMAP
+-      REG("pagemap",    S_IRUSR, pagemap),
+-#endif
+-#endif
+ #ifdef CONFIG_SECURITY
+       DIR("attr",      S_IRUGO|S_IXUGO, attr_dir),
+ #endif
+@@ -2301,12 +2305,9 @@
+ #ifdef CONFIG_SCHEDSTATS
+       INF("schedstat", S_IRUGO, pid_schedstat),
+ #endif
+-#ifdef CONFIG_PROC_PID_CPUSET
++#ifdef CONFIG_CPUSETS
+       REG("cpuset",    S_IRUGO, cpuset),
  #endif
+-#ifdef CONFIG_CONTAINERS
+-      REG("container",  S_IRUGO, container),
+-#endif
+       INF("oom_score", S_IRUGO, oom_score),
+       REG("oom_adj",   S_IRUGO|S_IWUSR, oom_adjust),
+ #ifdef CONFIG_AUDITSYSCALL
+diff -Nurb linux-2.6.22-590/fs/proc/generic.c linux-2.6.22-570/fs/proc/generic.c
+--- linux-2.6.22-590/fs/proc/generic.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/proc/generic.c 2008-01-23 19:16:04.000000000 -0500
+@@ -74,7 +74,7 @@
+               nbytes = MAX_NON_LFS - pos;
  
--static void __ipc_init __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
-+static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
- {
-       ns->ids[IPC_MSG_IDS] = ids;
-       ns->msg_ctlmax = MSGMAX;
-@@ -97,7 +97,6 @@
-       ipc_init_ids(ids, ns->msg_ctlmni);
- }
+       dp = PDE(inode);
+-      if (!(page = (char*) __get_free_page(GFP_TEMPORARY)))
++      if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+               return -ENOMEM;
  
--#ifdef CONFIG_IPC_NS
- int msg_init_ns(struct ipc_namespace *ns)
- {
-       struct ipc_ids *ids;
-@@ -129,7 +128,6 @@
-       kfree(ns->ids[IPC_MSG_IDS]);
-       ns->ids[IPC_MSG_IDS] = NULL;
- }
+       while ((nbytes > 0) && !eof) {
+diff -Nurb linux-2.6.22-590/fs/proc/internal.h linux-2.6.22-570/fs/proc/internal.h
+--- linux-2.6.22-590/fs/proc/internal.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/proc/internal.h        2008-01-23 19:16:04.000000000 -0500
+@@ -17,11 +17,6 @@
+ #else
+ static inline void proc_sys_init(void) { }
+ #endif
+-#ifdef CONFIG_NET
+-extern int proc_net_init(void);
+-#else
+-static inline int proc_net_init(void) { return 0; }
 -#endif
  
- void __init msg_init(void)
- {
-diff -Nurb linux-2.6.22-570/ipc/sem.c linux-2.6.22-590/ipc/sem.c
---- linux-2.6.22-570/ipc/sem.c 2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/ipc/sem.c 2008-01-02 13:56:37.000000000 -0500
-@@ -123,7 +123,7 @@
- #define sc_semopm     sem_ctls[2]
- #define sc_semmni     sem_ctls[3]
--static void __ipc_init __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
-+static void __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
- {
-       ns->ids[IPC_SEM_IDS] = ids;
-       ns->sc_semmsl = SEMMSL;
-@@ -134,7 +134,6 @@
-       ipc_init_ids(ids, ns->sc_semmni);
- }
+ struct vmalloc_info {
+       unsigned long   used;
+@@ -51,13 +46,15 @@
+ extern int proc_tgid_stat(struct task_struct *, char *);
+ extern int proc_pid_status(struct task_struct *, char *);
+ extern int proc_pid_statm(struct task_struct *, char *);
+-extern loff_t mem_lseek(struct file * file, loff_t offset, int orig);
  
--#ifdef CONFIG_IPC_NS
- int sem_init_ns(struct ipc_namespace *ns)
- {
-       struct ipc_ids *ids;
-@@ -166,7 +165,6 @@
-       kfree(ns->ids[IPC_SEM_IDS]);
-       ns->ids[IPC_SEM_IDS] = NULL;
- }
--#endif
+ extern const struct file_operations proc_maps_operations;
+ extern const struct file_operations proc_numa_maps_operations;
+ extern const struct file_operations proc_smaps_operations;
+-extern const struct file_operations proc_clear_refs_operations;
+-extern const struct file_operations proc_pagemap_operations;
++
++extern const struct file_operations proc_maps_operations;
++extern const struct file_operations proc_numa_maps_operations;
++extern const struct file_operations proc_smaps_operations;
++
  
- void __init sem_init (void)
- {
-diff -Nurb linux-2.6.22-570/ipc/shm.c linux-2.6.22-590/ipc/shm.c
---- linux-2.6.22-570/ipc/shm.c 2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/ipc/shm.c 2008-01-02 13:56:37.000000000 -0500
-@@ -79,7 +79,7 @@
- static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
- #endif
+ void free_proc_entry(struct proc_dir_entry *de);
  
--static void __ipc_init __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
-+static void __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
- {
-       ns->ids[IPC_SHM_IDS] = ids;
-       ns->shm_ctlmax = SHMMAX;
-@@ -100,7 +100,6 @@
-               shm_destroy(ns, shp);
- }
+diff -Nurb linux-2.6.22-590/fs/proc/proc_misc.c linux-2.6.22-570/fs/proc/proc_misc.c
+--- linux-2.6.22-590/fs/proc/proc_misc.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/proc/proc_misc.c       2008-01-23 19:16:04.000000000 -0500
+@@ -122,7 +122,6 @@
+       cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
  
--#ifdef CONFIG_IPC_NS
- int shm_init_ns(struct ipc_namespace *ns)
- {
-       struct ipc_ids *ids;
-@@ -132,7 +131,6 @@
-       kfree(ns->ids[IPC_SHM_IDS]);
-       ns->ids[IPC_SHM_IDS] = NULL;
- }
--#endif
+       do_posix_clock_monotonic_gettime(&uptime);
+-      monotonic_to_bootbased(&uptime);
+       cputime_to_timespec(idletime, &idle);
+       if (vx_flags(VXF_VIRT_UPTIME, 0))
+               vx_vsi_uptime(&uptime, &idle);
+@@ -464,14 +463,12 @@
+       unsigned long jif;
+       cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
+       u64 sum = 0;
+-      struct timespec boottime;
  
- void __init shm_init (void)
- {
-@@ -234,13 +232,13 @@
-       mutex_unlock(&shm_ids(ns).mutex);
- }
+       user = nice = system = idle = iowait =
+               irq = softirq = steal = cputime64_zero;
+-      getboottime(&boottime);
+-      jif = boottime.tv_sec;
+-      if (boottime.tv_nsec)
+-              ++jif;
++      jif = - wall_to_monotonic.tv_sec;
++      if (wall_to_monotonic.tv_nsec)
++              --jif;
  
--static struct page *shm_nopage(struct vm_area_struct *vma,
--                             unsigned long address, int *type)
-+static struct page *shm_fault(struct vm_area_struct *vma,
-+                                      struct fault_data *fdata)
- {
-       struct file *file = vma->vm_file;
-       struct shm_file_data *sfd = shm_file_data(file);
+       for_each_possible_cpu(i) {
+               int j;
+diff -Nurb linux-2.6.22-590/fs/proc/proc_net.c linux-2.6.22-570/fs/proc/proc_net.c
+--- linux-2.6.22-590/fs/proc/proc_net.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/proc/proc_net.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,154 +0,0 @@
+-/*
+- *  linux/fs/proc/net.c
+- *
+- *  Copyright (C) 2007
+- *
+- *  Author: Eric Biederman <ebiederm@xmission.com>
+- *
+- *  proc net directory handling functions
+- */
+-
+-#include <asm/uaccess.h>
+-
+-#include <linux/errno.h>
+-#include <linux/time.h>
+-#include <linux/proc_fs.h>
+-#include <linux/stat.h>
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/module.h>
+-#include <linux/bitops.h>
+-#include <linux/smp_lock.h>
+-#include <linux/mount.h>
+-#include <linux/nsproxy.h>
+-#include <net/net_namespace.h>
+-
+-#include "internal.h"
+-
+-static struct proc_dir_entry *proc_net_shadow;
+-
+-static struct dentry *proc_net_shadow_dentry(struct dentry *parent,
+-                                              struct proc_dir_entry *de)
+-{
+-      struct dentry *shadow = NULL;
+-      struct inode *inode;
+-      if (!de)
+-              goto out;
+-      de_get(de);
+-      inode = proc_get_inode(parent->d_inode->i_sb, de->low_ino, de);
+-      if (!inode)
+-              goto out_de_put;
+-      shadow = d_alloc_name(parent, de->name);
+-      if (!shadow)
+-              goto out_iput;
+-      shadow->d_op = parent->d_op; /* proc_dentry_operations */
+-      d_instantiate(shadow, inode);
+-out:
+-      return shadow;
+-out_iput:
+-      iput(inode);
+-out_de_put:
+-      de_put(de);
+-      goto out;
+-}
+-
+-static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd)
+-{
+-      struct net *net = current->nsproxy->net_ns;
+-      struct dentry *shadow;
+-      shadow = proc_net_shadow_dentry(parent, net->proc_net);
+-      if (!shadow)
+-              return ERR_PTR(-ENOENT);
+-
+-      dput(nd->dentry);
+-      /* My dentry count is 1 and that should be enough as the 
+-       * shadow dentry is thrown away immediately.
+-       */
+-      nd->dentry = shadow;
+-      return NULL;
+-}
+-
+-static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry,
+-                                    struct nameidata *nd)
+-{
+-      struct net *net = current->nsproxy->net_ns;
+-      struct dentry *shadow;
+-      
+-      shadow = proc_net_shadow_dentry(nd->dentry, net->proc_net);
+-      if (!shadow)
+-              return ERR_PTR(-ENOENT);
+-
+-      dput(nd->dentry);
+-      nd->dentry = shadow;
+-      
+-      return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd);
+-}
+-
+-static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr)
+-{
+-      struct net *net = current->nsproxy->net_ns;
+-      struct dentry *shadow;
+-      int ret;
+-
+-      shadow = proc_net_shadow_dentry(dentry->d_parent, net->proc_net);
+-      if (!shadow)
+-              return -ENOENT;
+-      ret = shadow->d_inode->i_op->setattr(shadow, iattr);
+-      dput(shadow);
+-      return ret;
+-}
+-
+-static const struct file_operations proc_net_dir_operations = {
+-      .read                   = generic_read_dir,
+-};
+-
+-static struct inode_operations proc_net_dir_inode_operations = {
+-      .follow_link    = proc_net_follow_link,
+-      .lookup         = proc_net_lookup,
+-      .setattr        = proc_net_setattr,
+-};
+-
+-
+-static int proc_net_ns_init(struct net *net)
+-{
+-      struct proc_dir_entry *netd, *net_statd;
+-
+-      netd = proc_mkdir("net", &net->proc_net_root);
+-      if (!netd)
+-              return -EEXIST;
+-
+-      net_statd = proc_mkdir("stat", netd);
+-      if (!net_statd) {
+-              remove_proc_entry("net", &net->proc_net_root);
+-              return -EEXIST;
+-      }
+-
+-      netd->data = net;
+-      net_statd->data = net;
+-      net->proc_net_root.data = net;
+-      net->proc_net = netd;
+-      net->proc_net_stat = net_statd;
+-
+-      return 0;
+-}
+-
+-static void proc_net_ns_exit(struct net *net)
+-{
+-      remove_proc_entry("stat", net->proc_net);
+-      remove_proc_entry("net", &net->proc_net_root);
+-
+-}
+-
+-struct pernet_operations proc_net_ns_ops = {
+-      .init = proc_net_ns_init,
+-      .exit = proc_net_ns_exit,
+-};
+-
+-int proc_net_init(void)
+-{
+-      proc_net_shadow = proc_mkdir("net", NULL);
+-      proc_net_shadow->proc_iops = &proc_net_dir_inode_operations;
+-      proc_net_shadow->proc_fops = &proc_net_dir_operations;
+-
+-      return register_pernet_subsys(&proc_net_ns_ops);
+-}
+diff -Nurb linux-2.6.22-590/fs/proc/root.c linux-2.6.22-570/fs/proc/root.c
+--- linux-2.6.22-590/fs/proc/root.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/proc/root.c    2008-01-23 19:16:04.000000000 -0500
+@@ -21,11 +21,11 @@
  
--      return sfd->vm_ops->nopage(vma, address, type);
-+      return sfd->vm_ops->fault(vma, fdata);
- }
+ #include "internal.h"
  
- #ifdef CONFIG_NUMA
-@@ -279,6 +277,7 @@
-       if (ret != 0)
-               return ret;
-       sfd->vm_ops = vma->vm_ops;
-+      BUG_ON(!sfd->vm_ops->fault);
-       vma->vm_ops = &shm_vm_ops;
-       shm_open(vma);
++struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
+ struct proc_dir_entry *proc_virtual;
  
-@@ -337,7 +336,7 @@
- static struct vm_operations_struct shm_vm_ops = {
-       .open   = shm_open,     /* callback for a new vm-area open */
-       .close  = shm_close,    /* callback for when the vm-area is released */
--      .nopage = shm_nopage,
-+      .fault  = shm_fault,
- #if defined(CONFIG_NUMA)
-       .set_policy = shm_set_policy,
-       .get_policy = shm_get_policy,
-diff -Nurb linux-2.6.22-570/ipc/util.c linux-2.6.22-590/ipc/util.c
---- linux-2.6.22-570/ipc/util.c        2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/ipc/util.c        2008-01-02 13:56:37.000000000 -0500
-@@ -52,7 +52,6 @@
-       },
- };
+ extern void proc_vx_init(void);
  
--#ifdef CONFIG_IPC_NS
- static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
+-struct proc_dir_entry *proc_bus, *proc_root_fs, *proc_root_driver;
+ static int proc_get_sb(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *data, struct vfsmount *mnt)
  {
-       int err;
-@@ -114,14 +113,6 @@
-       atomic_dec(&vs_global_ipc_ns);
-       kfree(ns);
+@@ -64,8 +64,8 @@
+               return;
+       }
+       proc_misc_init();
+-
+-      proc_net_init();
++      proc_net = proc_mkdir("net", NULL);
++      proc_net_stat = proc_mkdir("net/stat", NULL);
+ #ifdef CONFIG_SYSVIPC
+       proc_mkdir("sysvipc", NULL);
+@@ -163,5 +163,7 @@
+ EXPORT_SYMBOL(remove_proc_entry);
+ EXPORT_SYMBOL(proc_root);
+ EXPORT_SYMBOL(proc_root_fs);
++EXPORT_SYMBOL(proc_net);
++EXPORT_SYMBOL(proc_net_stat);
+ EXPORT_SYMBOL(proc_bus);
+ EXPORT_SYMBOL(proc_root_driver);
+diff -Nurb linux-2.6.22-590/fs/proc/task_mmu.c linux-2.6.22-570/fs/proc/task_mmu.c
+--- linux-2.6.22-590/fs/proc/task_mmu.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/proc/task_mmu.c        2007-07-08 19:32:17.000000000 -0400
+@@ -5,7 +5,6 @@
+ #include <linux/highmem.h>
+ #include <linux/ptrace.h>
+ #include <linux/pagemap.h>
+-#include <linux/ptrace.h>
+ #include <linux/mempolicy.h>
+ #include <asm/elf.h>
+@@ -115,123 +114,24 @@
+       seq_printf(m, "%*c", len, ' ');
  }
--#else
--struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
+-static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)
 -{
--      if (flags & CLONE_NEWIPC)
--              return ERR_PTR(-EINVAL);
--      return ns;
+-      if (vma && vma != priv->tail_vma) {
+-              struct mm_struct *mm = vma->vm_mm;
+-              up_read(&mm->mmap_sem);
+-              mmput(mm);
+-      }
 -}
--#endif
- /**
-  *    ipc_init        -       initialise IPC subsystem
-@@ -149,7 +140,7 @@
-  *    array itself. 
-  */
-  
--void __ipc_init ipc_init_ids(struct ipc_ids* ids, int size)
-+void ipc_init_ids(struct ipc_ids* ids, int size)
+-
+-static void *m_start(struct seq_file *m, loff_t *pos)
+-{
+-      struct proc_maps_private *priv = m->private;
+-      unsigned long last_addr = m->version;
+-      struct mm_struct *mm;
+-      struct vm_area_struct *vma, *tail_vma = NULL;
+-      loff_t l = *pos;
+-
+-      /* Clear the per syscall fields in priv */
+-      priv->task = NULL;
+-      priv->tail_vma = NULL;
+-
+-      /*
+-       * We remember last_addr rather than next_addr to hit with
+-       * mmap_cache most of the time. We have zero last_addr at
+-       * the beginning and also after lseek. We will have -1 last_addr
+-       * after the end of the vmas.
+-       */
+-
+-      if (last_addr == -1UL)
+-              return NULL;
+-
+-      priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
+-      if (!priv->task)
+-              return NULL;
+-
+-      mm = get_task_mm(priv->task);
+-      if (!mm)
+-              return NULL;
+-
+-      priv->tail_vma = tail_vma = get_gate_vma(priv->task);
+-      down_read(&mm->mmap_sem);
+-
+-      /* Start with last addr hint */
+-      if (last_addr && (vma = find_vma(mm, last_addr))) {
+-              vma = vma->vm_next;
+-              goto out;
+-      }
+-
+-      /*
+-       * Check the vma index is within the range and do
+-       * sequential scan until m_index.
+-       */
+-      vma = NULL;
+-      if ((unsigned long)l < mm->map_count) {
+-              vma = mm->mmap;
+-              while (l-- && vma)
+-                      vma = vma->vm_next;
+-              goto out;
+-      }
+-
+-      if (l != mm->map_count)
+-              tail_vma = NULL; /* After gate vma */
+-
+-out:
+-      if (vma)
+-              return vma;
+-
+-      /* End of vmas has been reached */
+-      m->version = (tail_vma != NULL)? 0: -1UL;
+-      up_read(&mm->mmap_sem);
+-      mmput(mm);
+-      return tail_vma;
+-}
+-
+-static void *m_next(struct seq_file *m, void *v, loff_t *pos)
+-{
+-      struct proc_maps_private *priv = m->private;
+-      struct vm_area_struct *vma = v;
+-      struct vm_area_struct *tail_vma = priv->tail_vma;
+-
+-      (*pos)++;
+-      if (vma && (vma != tail_vma) && vma->vm_next)
+-              return vma->vm_next;
+-      vma_stop(priv, vma);
+-      return (vma != tail_vma)? tail_vma: NULL;
+-}
+-
+-static void m_stop(struct seq_file *m, void *v)
++struct mem_size_stats
  {
-       int i;
-diff -Nurb linux-2.6.22-570/ipc/util.h linux-2.6.22-590/ipc/util.h
---- linux-2.6.22-570/ipc/util.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/ipc/util.h        2008-01-02 13:56:37.000000000 -0500
-@@ -41,12 +41,8 @@
- };
- struct seq_file;
--#ifdef CONFIG_IPC_NS
--#define __ipc_init
--#else
--#define __ipc_init    __init
--#endif
--void __ipc_init ipc_init_ids(struct ipc_ids *ids, int size);
-+
-+void ipc_init_ids(struct ipc_ids *ids, int size);
- #ifdef CONFIG_PROC_FS
- void __init ipc_init_proc_interface(const char *path, const char *header,
-               int ids, int (*show)(struct seq_file *, void *));
-diff -Nurb linux-2.6.22-570/kernel/Makefile linux-2.6.22-590/kernel/Makefile
---- linux-2.6.22-570/kernel/Makefile   2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/Makefile   2008-01-02 13:56:37.000000000 -0500
-@@ -4,11 +4,12 @@
+-      struct proc_maps_private *priv = m->private;
+-      struct vm_area_struct *vma = v;
+-
+-      vma_stop(priv, vma);
+-      if (priv->task)
+-              put_task_struct(priv->task);
+-}
++      unsigned long resident;
++      unsigned long shared_clean;
++      unsigned long shared_dirty;
++      unsigned long private_clean;
++      unsigned long private_dirty;
++      unsigned long referenced;
++};
  
- obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
-           exit.o itimer.o time.o softirq.o resource.o \
--          sysctl.o capability.o ptrace.o timer.o user.o \
-+          sysctl.o capability.o ptrace.o timer.o user.o user_namespace.o \
-           signal.o sys.o kmod.o workqueue.o pid.o \
-           rcupdate.o extable.o params.o posix-timers.o \
-           kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
--          hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o
-+          hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o \
-+          utsname.o
+-static int do_maps_open(struct inode *inode, struct file *file,
+-                      struct seq_operations *ops)
+-{
+-      struct proc_maps_private *priv;
+-      int ret = -ENOMEM;
+-      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+-      if (priv) {
+-              priv->pid = proc_pid(inode);
+-              ret = seq_open(file, ops);
+-              if (!ret) {
+-                      struct seq_file *m = file->private_data;
+-                      m->private = priv;
+-              } else {
+-                      kfree(priv);
+-              }
+-      }
+-      return ret;
+-}
++struct pmd_walker {
++      struct vm_area_struct *vma;
++      void *private;
++      void (*action)(struct vm_area_struct *, pmd_t *, unsigned long,
++                     unsigned long, void *);
++};
  
- obj-y   += vserver/
+-static int show_map(struct seq_file *m, void *v)
++static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
+ {
+       struct proc_maps_private *priv = m->private;
+       struct task_struct *task = priv->task;
+@@ -291,47 +191,38 @@
+       }
+       seq_putc(m, '\n');
  
-@@ -33,16 +34,22 @@
- obj-$(CONFIG_UID16) += uid16.o
- obj-$(CONFIG_MODULES) += module.o
- obj-$(CONFIG_KALLSYMS) += kallsyms.o
-+obj-$(CONFIG_STACK_UNWIND) += unwind.o
- obj-$(CONFIG_PM) += power/
- obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
- obj-$(CONFIG_KEXEC) += kexec.o
- obj-$(CONFIG_COMPAT) += compat.o
-+obj-$(CONFIG_CONTAINERS) += container.o
-+obj-$(CONFIG_CONTAINER_DEBUG) += container_debug.o
- obj-$(CONFIG_CPUSETS) += cpuset.o
-+obj-$(CONFIG_CONTAINER_CPUACCT) += cpu_acct.o
-+obj-$(CONFIG_CONTAINER_NS) += ns_container.o
- obj-$(CONFIG_IKCONFIG) += configs.o
- obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
- obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
- obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
- obj-$(CONFIG_KPROBES) += kprobes.o
-+obj-$(CONFIG_KGDB) += kgdb.o
- obj-$(CONFIG_SYSFS) += ksysfs.o
- obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
- obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
-@@ -50,7 +57,6 @@
- obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
- obj-$(CONFIG_RELAY) += relay.o
- obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
--obj-$(CONFIG_UTS_NS) += utsname.o
- obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
- obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
++      if (mss)
++              seq_printf(m,
++                         "Size:           %8lu kB\n"
++                         "Rss:            %8lu kB\n"
++                         "Shared_Clean:   %8lu kB\n"
++                         "Shared_Dirty:   %8lu kB\n"
++                         "Private_Clean:  %8lu kB\n"
++                         "Private_Dirty:  %8lu kB\n"
++                         "Referenced:     %8lu kB\n",
++                         (vma->vm_end - vma->vm_start) >> 10,
++                         mss->resident >> 10,
++                         mss->shared_clean  >> 10,
++                         mss->shared_dirty  >> 10,
++                         mss->private_clean >> 10,
++                         mss->private_dirty >> 10,
++                         mss->referenced >> 10);
++
+       if (m->count < m->size)  /* vma is copied successfully */
+               m->version = (vma != get_gate_vma(task))? vma->vm_start: 0;
+       return 0;
+ }
  
-diff -Nurb linux-2.6.22-570/kernel/audit.c linux-2.6.22-590/kernel/audit.c
---- linux-2.6.22-570/kernel/audit.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/kernel/audit.c    2008-01-02 13:56:37.000000000 -0500
-@@ -391,6 +391,7 @@
+-static struct seq_operations proc_pid_maps_op = {
+-      .start  = m_start,
+-      .next   = m_next,
+-      .stop   = m_stop,
+-      .show   = show_map
+-};
+-
+-static int maps_open(struct inode *inode, struct file *file)
++static int show_map(struct seq_file *m, void *v)
  {
-       struct sk_buff *skb;
-+      set_freezable();
-       while (!kthread_should_stop()) {
-               skb = skb_dequeue(&audit_skb_queue);
-               wake_up(&audit_backlog_wait);
-@@ -794,8 +795,8 @@
+-      return do_maps_open(inode, file, &proc_pid_maps_op);
++      return show_map_internal(m, v, NULL);
+ }
  
-       printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
-              audit_default ? "enabled" : "disabled");
--      audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive,
--                                         NULL, THIS_MODULE);
-+      audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, 0,
-+                                         audit_receive, NULL, THIS_MODULE);
-       if (!audit_sock)
-               audit_panic("cannot initialize netlink socket");
-       else
-diff -Nurb linux-2.6.22-570/kernel/auditsc.c linux-2.6.22-590/kernel/auditsc.c
---- linux-2.6.22-570/kernel/auditsc.c  2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/kernel/auditsc.c  2008-01-02 13:56:37.000000000 -0500
-@@ -1500,6 +1500,7 @@
-                       context->names[idx].ino = (unsigned long)-1;
+-const struct file_operations proc_maps_operations = {
+-      .open           = maps_open,
+-      .read           = seq_read,
+-      .llseek         = seq_lseek,
+-      .release        = seq_release_private,
+-};
+-
+-#ifdef CONFIG_PROC_SMAPS
+-struct mem_size_stats
+-{
+-      struct vm_area_struct *vma;
+-      unsigned long resident;
+-      unsigned long shared_clean;
+-      unsigned long shared_dirty;
+-      unsigned long private_clean;
+-      unsigned long private_dirty;
+-      unsigned long referenced;
+-};
+-
+-static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
++static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
++                          unsigned long addr, unsigned long end,
+                           void *private)
+ {
+       struct mem_size_stats *mss = private;
+-      struct vm_area_struct *vma = mss->vma;
+       pte_t *pte, ptent;
+       spinlock_t *ptl;
+       struct page *page;
+@@ -365,71 +256,12 @@
        }
+       pte_unmap_unlock(pte - 1, ptl);
+       cond_resched();
+-      return 0;
  }
-+EXPORT_SYMBOL(__audit_inode_child);
  
- /**
-  * auditsc_get_stamp - get local copies of audit_context values
-diff -Nurb linux-2.6.22-570/kernel/container.c linux-2.6.22-590/kernel/container.c
---- linux-2.6.22-570/kernel/container.c        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/kernel/container.c        2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,2545 @@
-+/*
-+ *  kernel/container.c
-+ *
-+ *  Generic process-grouping system.
-+ *
-+ *  Based originally on the cpuset system, extracted by Paul Menage
-+ *  Copyright (C) 2006 Google, Inc
-+ *
-+ *  Copyright notices from the original cpuset code:
-+ *  --------------------------------------------------
-+ *  Copyright (C) 2003 BULL SA.
-+ *  Copyright (C) 2004-2006 Silicon Graphics, Inc.
-+ *
-+ *  Portions derived from Patrick Mochel's sysfs code.
-+ *  sysfs is Copyright (c) 2001-3 Patrick Mochel
-+ *
-+ *  2003-10-10 Written by Simon Derr.
-+ *  2003-10-22 Updates by Stephen Hemminger.
-+ *  2004 May-July Rework by Paul Jackson.
-+ *  ---------------------------------------------------
-+ *
-+ *  This file is subject to the terms and conditions of the GNU General Public
-+ *  License.  See the file COPYING in the main directory of the Linux
-+ *  distribution for more details.
-+ */
-+
-+#include <linux/cpu.h>
-+#include <linux/cpumask.h>
-+#include <linux/container.h>
-+#include <linux/err.h>
-+#include <linux/errno.h>
-+#include <linux/file.h>
-+#include <linux/fs.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/kernel.h>
-+#include <linux/kmod.h>
-+#include <linux/list.h>
-+#include <linux/mempolicy.h>
-+#include <linux/mm.h>
-+#include <linux/mutex.h>
-+#include <linux/module.h>
-+#include <linux/mount.h>
-+#include <linux/namei.h>
-+#include <linux/pagemap.h>
-+#include <linux/proc_fs.h>
-+#include <linux/rcupdate.h>
-+#include <linux/uaccess.h>
-+#include <linux/sched.h>
-+#include <linux/seq_file.h>
-+#include <linux/security.h>
-+#include <linux/slab.h>
-+#include <linux/magic.h>
-+#include <linux/smp_lock.h>
-+#include <linux/spinlock.h>
-+#include <linux/stat.h>
-+#include <linux/string.h>
-+#include <linux/time.h>
-+#include <linux/backing-dev.h>
-+#include <linux/sort.h>
-+
-+#include <asm/atomic.h>
-+
-+static DEFINE_MUTEX(container_mutex);
-+
-+/* Generate an array of container subsystem pointers */
-+#define SUBSYS(_x) &_x ## _subsys,
-+
-+static struct container_subsys *subsys[] = {
-+#include <linux/container_subsys.h>
-+};
-+
-+/* A containerfs_root represents the root of a container hierarchy,
-+ * and may be associated with a superblock to form an active
-+ * hierarchy */
-+struct containerfs_root {
-+      struct super_block *sb;
-+
-+      /* The bitmask of subsystems attached to this hierarchy */
-+      unsigned long subsys_bits;
-+
-+      /* A list running through the attached subsystems */
-+      struct list_head subsys_list;
-+
-+      /* The root container for this hierarchy */
-+      struct container top_container;
-+
-+      /* Tracks how many containers are currently defined in hierarchy.*/
-+      int number_of_containers;
-+
-+      /* A list running through the mounted hierarchies */
-+      struct list_head root_list;
-+
-+      /* The path to use for release notifications. No locking
-+       * between setting and use - so if userspace updates this
-+       * while subcontainers exist, you could miss a
-+       * notification. We ensure that it's always a valid
-+       * NUL-terminated string */
-+      char release_agent_path[PATH_MAX];
-+};
-+
-+
-+/* The "rootnode" hierarchy is the "dummy hierarchy", reserved for the
-+ * subsystems that are otherwise unattached - it never has more than a
-+ * single container, and all tasks are part of that container. */
-+
-+static struct containerfs_root rootnode;
-+
-+/* The list of hierarchy roots */
-+
-+static LIST_HEAD(roots);
-+static int root_count;
-+
-+/* dummytop is a shorthand for the dummy hierarchy's top container */
-+#define dummytop (&rootnode.top_container)
-+
-+/* This flag indicates whether tasks in the fork and exit paths should
-+ * take callback_mutex and check for fork/exit handlers to call. This
-+ * avoids us having to do extra work in the fork/exit path if none of the
-+ * subsystems need to be called.
-+ */
-+static int need_forkexit_callback;
-+
-+/* bits in struct container flags field */
-+enum {
-+      /* Container is dead */
-+      CONT_REMOVED,
-+      /* Container has previously had a child container or a task,
-+       * but no longer (only if CONT_NOTIFY_ON_RELEASE is set) */
-+      CONT_RELEASABLE,
-+      /* Container requires release notifications to userspace */
-+      CONT_NOTIFY_ON_RELEASE,
-+};
-+
-+/* convenient tests for these bits */
-+inline int container_is_removed(const struct container *cont)
-+{
-+      return test_bit(CONT_REMOVED, &cont->flags);
-+}
-+
-+inline int container_is_releasable(const struct container *cont)
-+{
-+      const int bits =
-+              (1 << CONT_RELEASABLE) |
-+              (1 << CONT_NOTIFY_ON_RELEASE);
-+      return (cont->flags & bits) == bits;
-+}
-+
-+inline int notify_on_release(const struct container *cont)
-+{
-+      return test_bit(CONT_NOTIFY_ON_RELEASE, &cont->flags);
-+}
-+
-+/* for_each_subsys() allows you to iterate on each subsystem attached to
-+ * an active hierarchy */
-+#define for_each_subsys(_root, _ss) \
-+list_for_each_entry(_ss, &_root->subsys_list, sibling)
-+
-+/* for_each_root() allows you to iterate across the active hierarchies */
-+#define for_each_root(_root) \
-+list_for_each_entry(_root, &roots, root_list)
-+
-+/* the list of containers eligible for automatic release */
-+static LIST_HEAD(release_list);
-+static void container_release_agent(struct work_struct *work);
-+static DECLARE_WORK(release_agent_work, container_release_agent);
-+static void check_for_release(struct container *cont);
-+
-+/* Link structure for associating css_group objects with containers */
-+struct cg_container_link {
-+      /*
-+       * List running through cg_container_links associated with a
-+       * container, anchored on container->css_groups
-+       */
-+      struct list_head cont_link_list;
-+      /*
-+       * List running through cg_container_links pointing at a
-+       * single css_group object, anchored on css_group->cg_links
-+       */
-+      struct list_head cg_link_list;
-+      struct css_group *cg;
-+};
-+
-+/* The default css_group - used by init and its children prior to any
-+ * hierarchies being mounted. It contains a pointer to the root state
-+ * for each subsystem. Also used to anchor the list of css_groups. Not
-+ * reference-counted, to improve performance when child containers
-+ * haven't been created.
-+ */
-+
-+static struct css_group init_css_group;
-+static struct cg_container_link init_css_group_link;
-+
-+/* css_group_lock protects the list of css_group objects, and the
-+ * chain of tasks off each css_group. Nests inside task->alloc_lock */
-+static DEFINE_RWLOCK(css_group_lock);
-+static int css_group_count;
-+
-+
-+/* When we create or destroy a css_group, the operation simply
-+ * takes/releases a reference count on all the containers referenced
-+ * by subsystems in this css_group. This can end up multiple-counting
-+ * some containers, but that's OK - the ref-count is just a
-+ * busy/not-busy indicator; ensuring that we only count each container
-+ * once would require taking a global lock to ensure that no
-+ * subsystems moved between hierarchies while we were doing so.
-+ *
-+ * Possible TODO: decide at boot time based on the number of
-+ * registered subsystems and the number of CPUs or NUMA nodes whether
-+ * it's better for performance to ref-count every subsystem, or to
-+ * take a global lock and only add one ref count to each hierarchy.
-+ */
-+
-+/*
-+ * unlink a css_group from the list and free it
-+ */
-+static void unlink_css_group(struct css_group *cg)
-+{
-+      write_lock(&css_group_lock);
-+      list_del(&cg->list);
-+      css_group_count--;
-+      while (!list_empty(&cg->cg_links)) {
-+              struct cg_container_link *link;
-+              link = list_entry(cg->cg_links.next,
-+                                struct cg_container_link, cg_link_list);
-+              list_del(&link->cg_link_list);
-+              list_del(&link->cont_link_list);
-+              kfree(link);
-+      }
-+      write_unlock(&css_group_lock);
-+}
-+
-+static void release_css_group(struct kref *k)
-+{
-+      int i;
-+      struct css_group *cg = container_of(k, struct css_group, ref);
-+
-+      BUG_ON(!mutex_is_locked(&container_mutex));
-+      unlink_css_group(cg);
-+      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
-+              struct container *cont = cg->subsys[i]->container;
-+              if (atomic_dec_and_test(&cont->count) &&
-+                  container_is_releasable(cont)) {
-+                      check_for_release(cont);
-+              }
-+      }
-+      kfree(cg);
-+}
-+
-+/*
-+ * In the task exit path we want to avoid taking container_mutex
-+ * unless absolutely necessary, so the release process is slightly
-+ * different.
-+ */
-+static void release_css_group_taskexit(struct kref *k)
-+{
-+      int i;
-+      struct css_group *cg = container_of(k, struct css_group, ref);
-+
-+      unlink_css_group(cg);
-+      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
-+              struct container *cont = cg->subsys[i]->container;
-+              if (notify_on_release(cont)) {
-+                      mutex_lock(&container_mutex);
-+                      set_bit(CONT_RELEASABLE, &cont->flags);
-+                      if (atomic_dec_and_test(&cont->count))
-+                              check_for_release(cont);
-+                      mutex_unlock(&container_mutex);
-+              } else {
-+                      atomic_dec(&cont->count);
-+              }
-+      }
-+      kfree(cg);
-+}
-+
-+/*
-+ * refcounted get/put for css_group objects
-+ */
-+static inline void get_css_group(struct css_group *cg)
-+{
-+      kref_get(&cg->ref);
-+}
-+
-+static inline void put_css_group(struct css_group *cg)
-+{
-+      kref_put(&cg->ref, release_css_group);
-+}
-+
-+static inline void put_css_group_taskexit(struct css_group *cg)
-+{
-+      kref_put(&cg->ref, release_css_group_taskexit);
-+}
-+
-+/*
-+ * find_existing_css_group() is a helper for
-+ * find_css_group(), and checks to see whether an existing
-+ * css_group is suitable. This currently walks a linked-list for
-+ * simplicity; a later patch will use a hash table for better
-+ * performance
-+ *
-+ * oldcg: the container group that we're using before the container
-+ * transition
-+ *
-+ * cont: the container that we're moving into
-+ *
-+ * template: location in which to build the desired set of subsystem
-+ * state objects for the new container group
-+ */
-+
-+static struct css_group *find_existing_css_group(
-+      struct css_group *oldcg,
-+      struct container *cont,
-+      struct container_subsys_state *template[])
-+{
-+      int i;
-+      struct containerfs_root *root = cont->root;
-+      struct list_head *l = &init_css_group.list;
-+
-+      /* Built the set of subsystem state objects that we want to
-+       * see in the new css_group */
-+      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
-+              if (root->subsys_bits & (1ull << i)) {
-+                      /* Subsystem is in this hierarchy. So we want
-+                       * the subsystem state from the new
-+                       * container */
-+                      template[i] = cont->subsys[i];
-+              } else {
-+                      /* Subsystem is not in this hierarchy, so we
-+                       * don't want to change the subsystem state */
-+                      template[i] = oldcg->subsys[i];
-+              }
-+      }
-+
-+      /* Look through existing container groups to find one to reuse */
-+      do {
-+              struct css_group *cg =
-+                      list_entry(l, struct css_group, list);
-+
-+              if (!memcmp(template, cg->subsys, sizeof(cg->subsys))) {
-+                      /* All subsystems matched */
-+                      return cg;
-+              }
-+              /* Try the next container group */
-+              l = l->next;
-+      } while (l != &init_css_group.list);
-+
-+      /* No existing container group matched */
-+      return NULL;
-+}
-+
-+/*
-+ * allocate_cg_links() allocates "count" cg_container_link structures
-+ * and chains them on tmp through their cont_link_list fields. Returns 0 on
-+ * success or a negative error
-+ */
-+
-+static int allocate_cg_links(int count, struct list_head *tmp)
-+{
-+      struct cg_container_link *link;
-+      int i;
-+      INIT_LIST_HEAD(tmp);
-+      for (i = 0; i < count; i++) {
-+              link = kmalloc(sizeof(*link), GFP_KERNEL);
-+              if (!link) {
-+                      while (!list_empty(tmp)) {
-+                              link = list_entry(tmp->next,
-+                                                struct cg_container_link,
-+                                                cont_link_list);
-+                              list_del(&link->cont_link_list);
-+                              kfree(link);
-+                      }
-+                      return -ENOMEM;
-+              }
-+              list_add(&link->cont_link_list, tmp);
-+      }
-+      return 0;
-+}
-+
-+/*
-+ * find_css_group() takes an existing container group and a
-+ * container object, and returns a css_group object that's
-+ * equivalent to the old group, but with the given container
-+ * substituted into the appropriate hierarchy. Must be called with
-+ * container_mutex held
-+ */
-+
-+static struct css_group *find_css_group(
-+      struct css_group *oldcg, struct container *cont)
-+{
-+      struct css_group *res;
-+      struct container_subsys_state *template[CONTAINER_SUBSYS_COUNT];
-+      int i;
-+
-+      struct list_head tmp_cg_links;
-+      struct cg_container_link *link;
-+
-+      /* First see if we already have a container group that matches
-+       * the desired set */
-+      write_lock(&css_group_lock);
-+      res = find_existing_css_group(oldcg, cont, template);
-+      if (res)
-+              get_css_group(res);
-+      write_unlock(&css_group_lock);
-+
-+      if (res)
-+              return res;
-+
-+      res = kmalloc(sizeof(*res), GFP_KERNEL);
-+      if (!res)
-+              return NULL;
-+
-+      /* Allocate all the cg_container_link objects that we'll need */
-+      if (allocate_cg_links(root_count, &tmp_cg_links) < 0) {
-+              kfree(res);
-+              return NULL;
-+      }
-+
-+      kref_init(&res->ref);
-+      INIT_LIST_HEAD(&res->cg_links);
-+      INIT_LIST_HEAD(&res->tasks);
-+
-+      /* Copy the set of subsystem state objects generated in
-+       * find_existing_css_group() */
-+      memcpy(res->subsys, template, sizeof(res->subsys));
-+
-+      write_lock(&css_group_lock);
-+      /* Add reference counts and links from the new css_group. */
-+      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
-+              struct container *cont = res->subsys[i]->container;
-+              struct container_subsys *ss = subsys[i];
-+              atomic_inc(&cont->count);
-+              /*
-+               * We want to add a link once per container, so we
-+               * only do it for the first subsystem in each
-+               * hierarchy
-+               */
-+              if (ss->root->subsys_list.next == &ss->sibling) {
-+                      BUG_ON(list_empty(&tmp_cg_links));
-+                      link = list_entry(tmp_cg_links.next,
-+                                        struct cg_container_link,
-+                                        cont_link_list);
-+                      list_del(&link->cont_link_list);
-+                      list_add(&link->cont_link_list, &cont->css_groups);
-+                      link->cg = res;
-+                      list_add(&link->cg_link_list, &res->cg_links);
-+              }
-+      }
-+      if (list_empty(&rootnode.subsys_list)) {
-+              link = list_entry(tmp_cg_links.next,
-+                                struct cg_container_link,
-+                                cont_link_list);
-+              list_del(&link->cont_link_list);
-+              list_add(&link->cont_link_list, &dummytop->css_groups);
-+              link->cg = res;
-+              list_add(&link->cg_link_list, &res->cg_links);
-+      }
-+
-+      BUG_ON(!list_empty(&tmp_cg_links));
-+
-+      /* Link this container group into the list */
-+      list_add(&res->list, &init_css_group.list);
-+      css_group_count++;
-+      INIT_LIST_HEAD(&res->tasks);
-+      write_unlock(&css_group_lock);
-+
-+      return res;
-+}
-+
-+/*
-+ * There is one global container mutex. We also require taking
-+ * task_lock() when dereferencing a task's container subsys pointers.
-+ * See "The task_lock() exception", at the end of this comment.
-+ *
-+ * A task must hold container_mutex to modify containers.
-+ *
-+ * Any task can increment and decrement the count field without lock.
-+ * So in general, code holding container_mutex can't rely on the count
-+ * field not changing.  However, if the count goes to zero, then only
-+ * attach_task() can increment it again.  Because a count of zero
-+ * means that no tasks are currently attached, therefore there is no
-+ * way a task attached to that container can fork (the other way to
-+ * increment the count).  So code holding container_mutex can safely
-+ * assume that if the count is zero, it will stay zero. Similarly, if
-+ * a task holds container_mutex on a container with zero count, it
-+ * knows that the container won't be removed, as container_rmdir()
-+ * needs that mutex.
-+ *
-+ * The container_common_file_write handler for operations that modify
-+ * the container hierarchy holds container_mutex across the entire operation,
-+ * single threading all such container modifications across the system.
-+ *
-+ * The fork and exit callbacks container_fork() and container_exit(), don't
-+ * (usually) take container_mutex.  These are the two most performance
-+ * critical pieces of code here.  The exception occurs on container_exit(),
-+ * when a task in a notify_on_release container exits.  Then container_mutex
-+ * is taken, and if the container count is zero, a usermode call made
-+ * to /sbin/container_release_agent with the name of the container (path
-+ * relative to the root of container file system) as the argument.
-+ *
-+ * A container can only be deleted if both its 'count' of using tasks
-+ * is zero, and its list of 'children' containers is empty.  Since all
-+ * tasks in the system use _some_ container, and since there is always at
-+ * least one task in the system (init, pid == 1), therefore, top_container
-+ * always has either children containers and/or using tasks.  So we don't
-+ * need a special hack to ensure that top_container cannot be deleted.
-+ *
-+ *    The task_lock() exception
-+ *
-+ * The need for this exception arises from the action of
-+ * attach_task(), which overwrites one tasks container pointer with
-+ * another.  It does so using container_mutexe, however there are
-+ * several performance critical places that need to reference
-+ * task->container without the expense of grabbing a system global
-+ * mutex.  Therefore except as noted below, when dereferencing or, as
-+ * in attach_task(), modifying a task'ss container pointer we use
-+ * task_lock(), which acts on a spinlock (task->alloc_lock) already in
-+ * the task_struct routinely used for such matters.
-+ *
-+ * P.S.  One more locking exception.  RCU is used to guard the
-+ * update of a tasks container pointer by attach_task()
-+ */
-+
-+/**
-+ * container_lock - lock out any changes to container structures
-+ *
-+ */
-+
-+void container_lock(void)
-+{
-+      mutex_lock(&container_mutex);
-+}
-+
-+/**
-+ * container_unlock - release lock on container changes
-+ *
-+ * Undo the lock taken in a previous container_lock() call.
-+ */
-+
-+void container_unlock(void)
-+{
-+      mutex_unlock(&container_mutex);
-+}
-+
-+/*
-+ * A couple of forward declarations required, due to cyclic reference loop:
-+ * container_mkdir -> container_create -> container_populate_dir ->
-+ * container_add_file -> container_create_file -> container_dir_inode_operations
-+ * -> container_mkdir.
-+ */
-+
-+static int container_mkdir(struct inode *dir, struct dentry *dentry, int mode);
-+static int container_rmdir(struct inode *unused_dir, struct dentry *dentry);
-+static int container_populate_dir(struct container *cont);
-+static struct inode_operations container_dir_inode_operations;
-+static struct file_operations proc_containerstats_operations;
-+
-+static struct inode *container_new_inode(mode_t mode, struct super_block *sb)
-+{
-+      struct inode *inode = new_inode(sb);
-+      static struct backing_dev_info container_backing_dev_info = {
-+              .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
-+      };
-+
-+      if (inode) {
-+              inode->i_mode = mode;
-+              inode->i_uid = current->fsuid;
-+              inode->i_gid = current->fsgid;
-+              inode->i_blocks = 0;
-+              inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-+              inode->i_mapping->backing_dev_info = &container_backing_dev_info;
-+      }
-+      return inode;
-+}
-+
-+static void container_diput(struct dentry *dentry, struct inode *inode)
-+{
-+      /* is dentry a directory ? if so, kfree() associated container */
-+      if (S_ISDIR(inode->i_mode)) {
-+              struct container *cont = dentry->d_fsdata;
-+              BUG_ON(!(container_is_removed(cont)));
-+              kfree(cont);
-+      }
-+      iput(inode);
-+}
-+
-+static struct dentry *container_get_dentry(struct dentry *parent,
-+                                         const char *name)
-+{
-+      struct dentry *d = lookup_one_len(name, parent, strlen(name));
-+      static struct dentry_operations container_dops = {
-+              .d_iput = container_diput,
-+      };
-+
-+      if (!IS_ERR(d))
-+              d->d_op = &container_dops;
-+      return d;
-+}
-+
-+static void remove_dir(struct dentry *d)
-+{
-+      struct dentry *parent = dget(d->d_parent);
-+
-+      d_delete(d);
-+      simple_rmdir(parent->d_inode, d);
-+      dput(parent);
-+}
-+
-+static void container_clear_directory(struct dentry *dentry)
-+{
-+      struct list_head *node;
-+
-+      BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
-+      spin_lock(&dcache_lock);
-+      node = dentry->d_subdirs.next;
-+      while (node != &dentry->d_subdirs) {
-+              struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
-+              list_del_init(node);
-+              if (d->d_inode) {
-+                      /* This should never be called on a container
-+                       * directory with child containers */
-+                      BUG_ON(d->d_inode->i_mode & S_IFDIR);
-+                      d = dget_locked(d);
-+                      spin_unlock(&dcache_lock);
-+                      d_delete(d);
-+                      simple_unlink(dentry->d_inode, d);
-+                      dput(d);
-+                      spin_lock(&dcache_lock);
-+              }
-+              node = dentry->d_subdirs.next;
-+      }
-+      spin_unlock(&dcache_lock);
-+}
-+
-+/*
-+ * NOTE : the dentry must have been dget()'ed
-+ */
-+static void container_d_remove_dir(struct dentry *dentry)
-+{
-+      container_clear_directory(dentry);
-+
-+      spin_lock(&dcache_lock);
-+      list_del_init(&dentry->d_u.d_child);
-+      spin_unlock(&dcache_lock);
-+      remove_dir(dentry);
-+}
-+
-+static int rebind_subsystems(struct containerfs_root *root,
-+                            unsigned long final_bits)
-+{
-+      unsigned long added_bits, removed_bits;
-+      struct container *cont = &root->top_container;
-+      int i;
-+
-+      removed_bits = root->subsys_bits & ~final_bits;
-+      added_bits = final_bits & ~root->subsys_bits;
-+      /* Check that any added subsystems are currently free */
-+      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
-+              unsigned long long bit = 1ull << i;
-+              struct container_subsys *ss = subsys[i];
-+              if (!(bit & added_bits))
-+                      continue;
-+              if (ss->root != &rootnode) {
-+                      /* Subsystem isn't free */
-+                      return -EBUSY;
-+              }
-+      }
-+
-+      /* Currently we don't handle adding/removing subsystems when
-+       * any subcontainers exist. This is theoretically supportable
-+       * but involves complex error handling, so it's being left until
-+       * later */
-+      if (!list_empty(&cont->children))
-+              return -EBUSY;
-+
-+      /* Process each subsystem */
-+      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
-+              struct container_subsys *ss = subsys[i];
-+              unsigned long bit = 1UL << i;
-+              if (bit & added_bits) {
-+                      /* We're binding this subsystem to this hierarchy */
-+                      BUG_ON(cont->subsys[i]);
-+                      BUG_ON(!dummytop->subsys[i]);
-+                      BUG_ON(dummytop->subsys[i]->container != dummytop);
-+                      cont->subsys[i] = dummytop->subsys[i];
-+                      cont->subsys[i]->container = cont;
-+                      list_add(&ss->sibling, &root->subsys_list);
-+                      rcu_assign_pointer(ss->root, root);
-+                      if (ss->bind)
-+                              ss->bind(ss, cont);
-+
-+              } else if (bit & removed_bits) {
-+                      /* We're removing this subsystem */
-+                      BUG_ON(cont->subsys[i] != dummytop->subsys[i]);
-+                      BUG_ON(cont->subsys[i]->container != cont);
-+                      if (ss->bind)
-+                              ss->bind(ss, dummytop);
-+                      dummytop->subsys[i]->container = dummytop;
-+                      cont->subsys[i] = NULL;
-+                      rcu_assign_pointer(subsys[i]->root, &rootnode);
-+                      list_del(&ss->sibling);
-+              } else if (bit & final_bits) {
-+                      /* Subsystem state should already exist */
-+                      BUG_ON(!cont->subsys[i]);
-+              } else {
-+                      /* Subsystem state shouldn't exist */
-+                      BUG_ON(cont->subsys[i]);
-+              }
-+      }
-+      root->subsys_bits = final_bits;
-+      synchronize_rcu();
-+
-+      return 0;
-+}
-+
-+/*
-+ * Release the last use of a hierarchy.  Will never be called when
-+ * there are active subcontainers since each subcontainer bumps the
-+ * value of sb->s_active.
-+ */
-+static void container_put_super(struct super_block *sb)
-+{
-+      struct containerfs_root *root = sb->s_fs_info;
-+      struct container *cont = &root->top_container;
-+      int ret;
-+
-+      root->sb = NULL;
-+      sb->s_fs_info = NULL;
-+
-+      mutex_lock(&container_mutex);
-+
-+      BUG_ON(root->number_of_containers != 1);
-+      BUG_ON(!list_empty(&cont->children));
-+      BUG_ON(!list_empty(&cont->sibling));
-+      BUG_ON(!root->subsys_bits);
-+
-+      /* Rebind all subsystems back to the default hierarchy */
-+      ret = rebind_subsystems(root, 0);
-+      BUG_ON(ret);
-+
-+      write_lock(&css_group_lock);
-+      while (!list_empty(&cont->css_groups)) {
-+              struct cg_container_link *link;
-+              link = list_entry(cont->css_groups.next,
-+                                struct cg_container_link, cont_link_list);
-+              list_del(&link->cg_link_list);
-+              list_del(&link->cont_link_list);
-+              kfree(link);
-+      }
-+      write_unlock(&css_group_lock);
-+
-+      list_del(&root->root_list);
-+      root_count--;
-+      kfree(root);
-+      mutex_unlock(&container_mutex);
-+}
-+
-+static int container_show_options(struct seq_file *seq, struct vfsmount *vfs)
-+{
-+      struct containerfs_root *root = vfs->mnt_sb->s_fs_info;
-+      struct container_subsys *ss;
-+
-+      for_each_subsys(root, ss)
-+              seq_printf(seq, ",%s", ss->name);
-+      return 0;
-+}
-+
-+/* Convert a hierarchy specifier into a bitmask. LL=container_mutex */
-+static int parse_containerfs_options(char *opts, unsigned long *bits)
-+{
-+      char *token, *o = opts ?: "all";
-+
-+      *bits = 0;
-+
-+      while ((token = strsep(&o, ",")) != NULL) {
-+              if (!*token)
-+                      return -EINVAL;
-+              if (!strcmp(token, "all")) {
-+                      *bits = (1 << CONTAINER_SUBSYS_COUNT) - 1;
-+              } else {
-+                      struct container_subsys *ss;
-+                      int i;
-+                      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
-+                              ss = subsys[i];
-+                              if (!strcmp(token, ss->name)) {
-+                                      *bits |= 1 << i;
-+                                      break;
-+                              }
-+                      }
-+                      if (i == CONTAINER_SUBSYS_COUNT)
-+                              return -ENOENT;
-+              }
-+      }
-+
-+      /* We can't have an empty hierarchy */
-+      if (!*bits)
-+              return -EINVAL;
-+
-+      return 0;
-+}
-+
-+static int container_remount(struct super_block *sb, int *flags, char *data)
-+{
-+      int ret = 0;
-+      unsigned long subsys_bits;
-+      struct containerfs_root *root = sb->s_fs_info;
-+      struct container *cont = &root->top_container;
-+
-+      mutex_lock(&cont->dentry->d_inode->i_mutex);
-+      mutex_lock(&container_mutex);
-+
-+      /* See what subsystems are wanted */
-+      ret = parse_containerfs_options(data, &subsys_bits);
-+      if (ret)
-+              goto out_unlock;
-+
-+      ret = rebind_subsystems(root, subsys_bits);
-+
-+      /* (re)populate subsystem files */
-+      if (!ret)
-+              container_populate_dir(cont);
-+
-+ out_unlock:
-+      mutex_unlock(&container_mutex);
-+      mutex_unlock(&cont->dentry->d_inode->i_mutex);
-+      return ret;
-+}
-+
-+static struct super_operations container_ops = {
-+      .statfs = simple_statfs,
-+      .drop_inode = generic_delete_inode,
-+      .put_super = container_put_super,
-+      .show_options = container_show_options,
-+      .remount_fs = container_remount,
-+};
-+
-+static int container_fill_super(struct super_block *sb, void *options,
-+                              int unused_silent)
-+{
-+      struct inode *inode;
-+      struct dentry *root;
-+      struct containerfs_root *hroot = options;
-+
-+      sb->s_blocksize = PAGE_CACHE_SIZE;
-+      sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-+      sb->s_magic = CONTAINER_SUPER_MAGIC;
-+      sb->s_op = &container_ops;
-+
-+      inode = container_new_inode(S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR, sb);
-+      if (!inode)
-+              return -ENOMEM;
-+
-+      inode->i_op = &simple_dir_inode_operations;
-+      inode->i_fop = &simple_dir_operations;
-+      inode->i_op = &container_dir_inode_operations;
-+      /* directories start off with i_nlink == 2 (for "." entry) */
-+      inc_nlink(inode);
-+
-+      root = d_alloc_root(inode);
-+      if (!root) {
-+              iput(inode);
-+              return -ENOMEM;
-+      }
-+      sb->s_root = root;
-+      root->d_fsdata = &hroot->top_container;
-+      hroot->top_container.dentry = root;
-+
-+      strcpy(hroot->release_agent_path, "");
-+      sb->s_fs_info = hroot;
-+      hroot->sb = sb;
-+
-+      return 0;
-+}
-+
-+static void init_container_root(struct containerfs_root *root)
-+{
-+      struct container *cont = &root->top_container;
-+      INIT_LIST_HEAD(&root->subsys_list);
-+      root->number_of_containers = 1;
-+      cont->root = root;
-+      cont->top_container = cont;
-+      INIT_LIST_HEAD(&cont->sibling);
-+      INIT_LIST_HEAD(&cont->children);
-+      INIT_LIST_HEAD(&cont->css_groups);
-+      INIT_LIST_HEAD(&cont->release_list);
-+      list_add(&root->root_list, &roots);
-+      root_count++;
-+}
-+
-+static int container_get_sb(struct file_system_type *fs_type,
-+                       int flags, const char *unused_dev_name,
-+                       void *data, struct vfsmount *mnt)
-+{
-+      unsigned long subsys_bits = 0;
-+      int ret = 0;
-+      struct containerfs_root *root = NULL;
-+      int use_existing = 0;
-+
-+      mutex_lock(&container_mutex);
-+
-+      /* First find the desired set of resource controllers */
-+      ret = parse_containerfs_options(data, &subsys_bits);
-+      if (ret)
-+              goto out_unlock;
-+
-+      /* See if we already have a hierarchy containing this set */
-+
-+      for_each_root(root) {
-+              /* We match - use this hieracrchy */
-+              if (root->subsys_bits == subsys_bits) {
-+                      use_existing = 1;
-+                      break;
-+              }
-+              /* We clash - fail */
-+              if (root->subsys_bits & subsys_bits) {
-+                      ret = -EBUSY;
-+                      goto out_unlock;
-+              }
-+      }
-+
-+      if (!use_existing) {
-+              /* We need a new root */
-+              struct list_head tmp_cg_links, *l;
-+              root = kzalloc(sizeof(*root), GFP_KERNEL);
-+              if (!root) {
-+                      ret = -ENOMEM;
-+                      goto out_unlock;
-+              }
-+              /* We're accessing css_group_count without locking
-+               * here, but that's OK - it can only be increased by
-+               * someone holding container_lock, and that's us. The
-+               * worst that can happen is that we have some link
-+               * structures left over */
-+              ret = allocate_cg_links(css_group_count, &tmp_cg_links);
-+              if (ret < 0) {
-+                      kfree(root);
-+                      goto out_unlock;
-+              }
-+              init_container_root(root);
-+
-+              /* Link the top container in this hierarchy into all
-+               * the css_group objects */
-+              write_lock(&css_group_lock);
-+              l = &init_css_group.list;
-+              do {
-+                      struct css_group *cg;
-+                      struct cg_container_link *link;
-+                      cg = list_entry(l, struct css_group, list);
-+                      BUG_ON(list_empty(&tmp_cg_links));
-+                      link = list_entry(tmp_cg_links.next,
-+                                        struct cg_container_link,
-+                                        cont_link_list);
-+                      list_del(&link->cont_link_list);
-+                      link->cg = cg;
-+                      list_add(&link->cont_link_list,
-+                               &root->top_container.css_groups);
-+                      list_add(&link->cg_link_list, &cg->cg_links);
-+                      l = l->next;
-+              } while (l != &init_css_group.list);
-+              write_unlock(&css_group_lock);
-+
-+              while (!list_empty(&tmp_cg_links)) {
-+                      /* Probably shouldn't happen */
-+                      struct cg_container_link *link;
-+                      printk(KERN_INFO "Freeing unused cg_container_link\n");
-+                      link = list_entry(tmp_cg_links.next,
-+                                        struct cg_container_link,
-+                                        cont_link_list);
-+                      list_del(&link->cont_link_list);
-+                      kfree(link);
-+              }
-+      }
-+
-+      if (!root->sb) {
-+              /* We need a new superblock for this container combination */
-+              struct container *cont = &root->top_container;
-+
-+              BUG_ON(root->subsys_bits);
-+              ret = get_sb_nodev(fs_type, flags, root,
-+                                 container_fill_super, mnt);
-+              if (ret)
-+                      goto out_unlock;
-+
-+              BUG_ON(!list_empty(&cont->sibling));
-+              BUG_ON(!list_empty(&cont->children));
-+              BUG_ON(root->number_of_containers != 1);
-+
-+              ret = rebind_subsystems(root, subsys_bits);
-+
-+              /* It's safe to nest i_mutex inside container_mutex in
-+               * this case, since no-one else can be accessing this
-+               * directory yet */
-+              mutex_lock(&cont->dentry->d_inode->i_mutex);
-+              container_populate_dir(cont);
-+              mutex_unlock(&cont->dentry->d_inode->i_mutex);
-+              BUG_ON(ret);
-+      } else {
-+              /* Reuse the existing superblock */
-+              down_write(&(root->sb->s_umount));
-+              ret = simple_set_mnt(mnt, root->sb);
-+              if (!ret)
-+                      atomic_inc(&root->sb->s_active);
-+      }
-+
-+ out_unlock:
-+      mutex_unlock(&container_mutex);
-+      return ret;
-+}
-+
-+static struct file_system_type container_fs_type = {
-+      .name = "container",
-+      .get_sb = container_get_sb,
-+      .kill_sb = kill_litter_super,
-+};
-+
-+static inline struct container *__d_cont(struct dentry *dentry)
-+{
-+      return dentry->d_fsdata;
-+}
-+
-+static inline struct cftype *__d_cft(struct dentry *dentry)
-+{
-+      return dentry->d_fsdata;
-+}
-+
-+/*
-+ * Called with container_mutex held.  Writes path of container into buf.
-+ * Returns 0 on success, -errno on error.
-+ */
-+int container_path(const struct container *cont, char *buf, int buflen)
+-static struct mm_walk smaps_walk = { .pmd_entry = smaps_pte_range };
+-
+-static int show_smap(struct seq_file *m, void *v)
+-{
+-      struct vm_area_struct *vma = v;
+-      struct mem_size_stats mss;
+-      int ret;
+-
+-      memset(&mss, 0, sizeof mss);
+-      mss.vma = vma;
+-      if (vma->vm_mm && !is_vm_hugetlb_page(vma))
+-              walk_page_range(vma->vm_mm, vma->vm_start, vma->vm_end,
+-                              &smaps_walk, &mss);
+-
+-      ret = show_map(m, v);
+-      if (ret)
+-              return ret;
+-
+-      seq_printf(m,
+-                 "Size:           %8lu kB\n"
+-                 "Rss:            %8lu kB\n"
+-                 "Shared_Clean:   %8lu kB\n"
+-                 "Shared_Dirty:   %8lu kB\n"
+-                 "Private_Clean:  %8lu kB\n"
+-                 "Private_Dirty:  %8lu kB\n"
+-                 "Referenced:     %8lu kB\n",
+-                 (vma->vm_end - vma->vm_start) >> 10,
+-                 mss.resident >> 10,
+-                 mss.shared_clean  >> 10,
+-                 mss.shared_dirty  >> 10,
+-                 mss.private_clean >> 10,
+-                 mss.private_dirty >> 10,
+-                 mss.referenced >> 10);
+-
+-      return ret;
+-}
+-
+-static struct seq_operations proc_pid_smaps_op = {
+-      .start  = m_start,
+-      .next   = m_next,
+-      .stop   = m_stop,
+-      .show   = show_smap
+-};
+-
+-static int smaps_open(struct inode *inode, struct file *file)
+-{
+-      return do_maps_open(inode, file, &proc_pid_smaps_op);
+-}
+-
+-const struct file_operations proc_smaps_operations = {
+-      .open           = smaps_open,
+-      .read           = seq_read,
+-      .llseek         = seq_lseek,
+-      .release        = seq_release_private,
+-};
+-#endif
+-
+-#ifdef CONFIG_PROC_CLEAR_REFS
+-static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
+-                              unsigned long end, void *private)
++static void clear_refs_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
++                               unsigned long addr, unsigned long end,
++                               void *private)
+ {
+-      struct vm_area_struct *vma = private;
+       pte_t *pte, ptent;
+       spinlock_t *ptl;
+       struct page *page;
+@@ -450,52 +282,236 @@
+       }
+       pte_unmap_unlock(pte - 1, ptl);
+       cond_resched();
+-      return 0;
+ }
+-static struct mm_walk clear_refs_walk = { .pmd_entry = clear_refs_pte_range };
++static inline void walk_pmd_range(struct pmd_walker *walker, pud_t *pud,
++                                unsigned long addr, unsigned long end)
 +{
-+      char *start;
-+
-+      start = buf + buflen;
-+
-+      *--start = '\0';
-+      for (;;) {
-+              int len = cont->dentry->d_name.len;
-+              if ((start -= len) < buf)
-+                      return -ENAMETOOLONG;
-+              memcpy(start, cont->dentry->d_name.name, len);
-+              cont = cont->parent;
-+              if (!cont)
-+                      break;
-+              if (!cont->parent)
++      pmd_t *pmd;
++      unsigned long next;
+-static ssize_t clear_refs_write(struct file *file, const char __user *buf,
+-                              size_t count, loff_t *ppos)
++      for (pmd = pmd_offset(pud, addr); addr != end;
++           pmd++, addr = next) {
++              next = pmd_addr_end(addr, end);
++              if (pmd_none_or_clear_bad(pmd))
 +                      continue;
-+              if (--start < buf)
-+                      return -ENAMETOOLONG;
-+              *start = '/';
++              walker->action(walker->vma, pmd, addr, next, walker->private);
 +      }
-+      memmove(buf, start, buf + buflen - start);
-+      return 0;
 +}
 +
-+static void get_first_subsys(const struct container *cont,
-+                      struct container_subsys_state **css, int *subsys_id)
++static inline void walk_pud_range(struct pmd_walker *walker, pgd_t *pgd,
++                                unsigned long addr, unsigned long end)
 +{
-+      const struct containerfs_root *root = cont->root;
-+      const struct container_subsys *test_ss;
-+      BUG_ON(list_empty(&root->subsys_list));
-+      test_ss = list_entry(root->subsys_list.next,
-+                           struct container_subsys, sibling);
-+      if (css) {
-+              *css = cont->subsys[test_ss->subsys_id];
-+              BUG_ON(!*css);
++      pud_t *pud;
++      unsigned long next;
++
++      for (pud = pud_offset(pgd, addr); addr != end;
++           pud++, addr = next) {
++              next = pud_addr_end(addr, end);
++              if (pud_none_or_clear_bad(pud))
++                      continue;
++              walk_pmd_range(walker, pud, addr, next);
 +      }
-+      if (subsys_id)
-+              *subsys_id = test_ss->subsys_id;
 +}
 +
 +/*
-+ * Attach task 'tsk' to container 'cont'
++ * walk_page_range - walk the page tables of a VMA with a callback
++ * @vma - VMA to walk
++ * @action - callback invoked for every bottom-level (PTE) page table
++ * @private - private data passed to the callback function
 + *
-+ * Call holding container_mutex.  May take task_lock of
-+ * the task 'pid' during call.
++ * Recursively walk the page table for the memory area in a VMA, calling
++ * a callback for every bottom-level (PTE) page table.
 + */
-+static int attach_task(struct container *cont, struct task_struct *tsk)
-+{
-+      int retval = 0;
-+      struct container_subsys *ss;
-+      struct container *oldcont;
-+      struct css_group *cg = tsk->containers;
-+      struct css_group *newcg;
-+      struct containerfs_root *root = cont->root;
-+      int subsys_id;
-+
-+      get_first_subsys(cont, NULL, &subsys_id);
-+
-+      /* Nothing to do if the task is already in that container */
-+      oldcont = task_container(tsk, subsys_id);
-+      if (cont == oldcont)
-+              return 0;
-+
-+      for_each_subsys(root, ss) {
-+              if (ss->can_attach) {
-+                      retval = ss->can_attach(ss, cont, tsk);
-+                      if (retval) {
-+                              return retval;
-+                      }
-+              }
-+      }
-+
-+      /* Locate or allocate a new css_group for this task,
-+       * based on its final set of containers */
-+      newcg = find_css_group(cg, cont);
-+      if (!newcg) {
-+              return -ENOMEM;
-+      }
-+
-+      task_lock(tsk);
-+      if (tsk->flags & PF_EXITING) {
-+              task_unlock(tsk);
-+              put_css_group(newcg);
-+              return -ESRCH;
-+      }
-+      rcu_assign_pointer(tsk->containers, newcg);
-+      if (!list_empty(&tsk->cg_list)) {
-+              write_lock(&css_group_lock);
-+              list_del(&tsk->cg_list);
-+              list_add(&tsk->cg_list, &newcg->tasks);
-+              write_unlock(&css_group_lock);
-+      }
-+      task_unlock(tsk);
++static inline void walk_page_range(struct vm_area_struct *vma,
++                                 void (*action)(struct vm_area_struct *,
++                                                pmd_t *, unsigned long,
++                                                unsigned long, void *),
++                                 void *private)
++{
++      unsigned long addr = vma->vm_start;
++      unsigned long end = vma->vm_end;
++      struct pmd_walker walker = {
++              .vma            = vma,
++              .private        = private,
++              .action         = action,
++      };
++      pgd_t *pgd;
++      unsigned long next;
 +
-+      for_each_subsys(root, ss) {
-+              if (ss->attach) {
-+                      ss->attach(ss, cont, oldcont, tsk);
-+              }
++      for (pgd = pgd_offset(vma->vm_mm, addr); addr != end;
++           pgd++, addr = next) {
++              next = pgd_addr_end(addr, end);
++              if (pgd_none_or_clear_bad(pgd))
++                      continue;
++              walk_pud_range(&walker, pgd, addr, next);
 +      }
-+      set_bit(CONT_RELEASABLE, &oldcont->flags);
-+      synchronize_rcu();
-+      put_css_group(cg);
-+      return 0;
 +}
 +
-+/*
-+ * Attach task with pid 'pid' to container 'cont'. Call with
-+ * container_mutex, may take task_lock of task
-+ */
-+static int attach_task_by_pid(struct container *cont, char *pidbuf)
++static int show_smap(struct seq_file *m, void *v)
 +{
-+      pid_t pid;
-+      struct task_struct *tsk;
-+      int ret;
-+
-+      if (sscanf(pidbuf, "%d", &pid) != 1)
-+              return -EIO;
-+
-+      if (pid) {
-+              rcu_read_lock();
-+              tsk = find_task_by_pid(pid);
-+              if (!tsk || tsk->flags & PF_EXITING) {
-+                      rcu_read_unlock();
-+                      return -ESRCH;
-+              }
-+              get_task_struct(tsk);
-+              rcu_read_unlock();
++      struct vm_area_struct *vma = v;
++      struct mem_size_stats mss;
 +
-+              if ((current->euid) && (current->euid != tsk->uid)
-+                  && (current->euid != tsk->suid)) {
-+                      put_task_struct(tsk);
-+                      return -EACCES;
-+              }
-+      } else {
-+              tsk = current;
-+              get_task_struct(tsk);
-+      }
++      memset(&mss, 0, sizeof mss);
++      if (vma->vm_mm && !is_vm_hugetlb_page(vma))
++              walk_page_range(vma, smaps_pte_range, &mss);
++      return show_map_internal(m, v, &mss);
++}
 +
-+      ret = attach_task(cont, tsk);
-+      put_task_struct(tsk);
-+      return ret;
++void clear_refs_smap(struct mm_struct *mm)
+ {
+-      struct task_struct *task;
+-      char buffer[13], *end;
+-      struct mm_struct *mm;
+       struct vm_area_struct *vma;
+-      memset(buffer, 0, sizeof(buffer));
+-      if (count > sizeof(buffer) - 1)
+-              count = sizeof(buffer) - 1;
+-      if (copy_from_user(buffer, buf, count))
+-              return -EFAULT;
+-      if (!simple_strtol(buffer, &end, 0))
+-              return -EINVAL;
+-      if (*end == '\n')
+-              end++;
+-      task = get_proc_task(file->f_path.dentry->d_inode);
+-      if (!task)
+-              return -ESRCH;
+-      mm = get_task_mm(task);
+-      if (mm) {
+       down_read(&mm->mmap_sem);
+       for (vma = mm->mmap; vma; vma = vma->vm_next)
+-                      if (!is_vm_hugetlb_page(vma))
+-                              walk_page_range(mm, vma->vm_start, vma->vm_end,
+-                                              &clear_refs_walk, vma);
++              if (vma->vm_mm && !is_vm_hugetlb_page(vma))
++                      walk_page_range(vma, clear_refs_pte_range, NULL);
+       flush_tlb_mm(mm);
+       up_read(&mm->mmap_sem);
 +}
 +
-+/* The various types of files and directories in a container file system */
++static void *m_start(struct seq_file *m, loff_t *pos)
++{
++      struct proc_maps_private *priv = m->private;
++      unsigned long last_addr = m->version;
++      struct mm_struct *mm;
++      struct vm_area_struct *vma, *tail_vma = NULL;
++      loff_t l = *pos;
 +
-+enum container_filetype {
-+      FILE_ROOT,
-+      FILE_DIR,
-+      FILE_TASKLIST,
-+      FILE_NOTIFY_ON_RELEASE,
-+      FILE_RELEASABLE,
-+      FILE_RELEASE_AGENT,
-+};
++      /* Clear the per syscall fields in priv */
++      priv->task = NULL;
++      priv->tail_vma = NULL;
 +
-+static ssize_t container_common_file_write(struct container *cont,
-+                                         struct cftype *cft,
-+                                         struct file *file,
-+                                         const char __user *userbuf,
-+                                         size_t nbytes, loff_t *unused_ppos)
-+{
-+      enum container_filetype type = cft->private;
-+      char *buffer;
-+      int retval = 0;
++      /*
++       * We remember last_addr rather than next_addr to hit with
++       * mmap_cache most of the time. We have zero last_addr at
++       * the beginning and also after lseek. We will have -1 last_addr
++       * after the end of the vmas.
++       */
 +
-+      if (nbytes >= PATH_MAX)
-+              return -E2BIG;
++      if (last_addr == -1UL)
++              return NULL;
 +
-+      /* +1 for nul-terminator */
-+      buffer = kmalloc(nbytes + 1, GFP_KERNEL);
-+      if (buffer == NULL)
-+              return -ENOMEM;
++      priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
++      if (!priv->task)
++              return NULL;
 +
-+      if (copy_from_user(buffer, userbuf, nbytes)) {
-+              retval = -EFAULT;
-+              goto out1;
-+      }
-+      buffer[nbytes] = 0;     /* nul-terminate */
++      mm = get_task_mm(priv->task);
++      if (!mm)
++              return NULL;
 +
-+      mutex_lock(&container_mutex);
++      priv->tail_vma = tail_vma = get_gate_vma(priv->task);
++      down_read(&mm->mmap_sem);
 +
-+      if (container_is_removed(cont)) {
-+              retval = -ENODEV;
-+              goto out2;
++      /* Start with last addr hint */
++      if (last_addr && (vma = find_vma(mm, last_addr))) {
++              vma = vma->vm_next;
++              goto out;
 +      }
 +
-+      switch (type) {
-+      case FILE_TASKLIST:
-+              retval = attach_task_by_pid(cont, buffer);
-+              break;
-+      case FILE_NOTIFY_ON_RELEASE:
-+              clear_bit(CONT_RELEASABLE, &cont->flags);
-+              if (simple_strtoul(buffer, NULL, 10) != 0)
-+                      set_bit(CONT_NOTIFY_ON_RELEASE, &cont->flags);
-+              else
-+                      clear_bit(CONT_NOTIFY_ON_RELEASE, &cont->flags);
-+              break;
-+      case FILE_RELEASE_AGENT:
-+      {
-+              struct containerfs_root *root = cont->root;
-+              if (nbytes < sizeof(root->release_agent_path)) {
-+                      /* We never write anything other than '\0'
-+                       * into the last char of release_agent_path,
-+                       * so it always remains a NUL-terminated
-+                       * string */
-+                      strncpy(root->release_agent_path, buffer, nbytes);
-+                      root->release_agent_path[nbytes] = 0;
-+              } else {
-+                      retval = -ENOSPC;
-+              }
-+              break;
-+      }
-+      default:
-+              retval = -EINVAL;
-+              goto out2;
++      /*
++       * Check the vma index is within the range and do
++       * sequential scan until m_index.
++       */
++      vma = NULL;
++      if ((unsigned long)l < mm->map_count) {
++              vma = mm->mmap;
++              while (l-- && vma)
++                      vma = vma->vm_next;
++              goto out;
 +      }
 +
-+      if (retval == 0)
-+              retval = nbytes;
-+out2:
-+      mutex_unlock(&container_mutex);
-+out1:
-+      kfree(buffer);
-+      return retval;
-+}
-+
-+static ssize_t container_file_write(struct file *file, const char __user *buf,
-+                                              size_t nbytes, loff_t *ppos)
-+{
-+      struct cftype *cft = __d_cft(file->f_dentry);
-+      struct container *cont = __d_cont(file->f_dentry->d_parent);
++      if (l != mm->map_count)
++              tail_vma = NULL; /* After gate vma */
 +
-+      if (!cft)
-+              return -ENODEV;
-+      if (!cft->write)
-+              return -EINVAL;
++out:
++      if (vma)
++              return vma;
 +
-+      return cft->write(cont, cft, file, buf, nbytes, ppos);
++      /* End of vmas has been reached */
++      m->version = (tail_vma != NULL)? 0: -1UL;
++      up_read(&mm->mmap_sem);
++      mmput(mm);
++      return tail_vma;
 +}
 +
-+static ssize_t container_read_uint(struct container *cont, struct cftype *cft,
-+                                 struct file *file,
-+                                 char __user *buf, size_t nbytes,
-+                                 loff_t *ppos)
++static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)
 +{
-+      char tmp[64];
-+      u64 val = cft->read_uint(cont, cft);
-+      int len = sprintf(tmp, "%llu\n", (unsigned long long) val);
-+
-+      return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
-+}
-+
-+static ssize_t container_common_file_read(struct container *cont,
-+                                        struct cftype *cft,
-+                                        struct file *file,
-+                                        char __user *buf,
-+                                        size_t nbytes, loff_t *ppos)
++      if (vma && vma != priv->tail_vma) {
++              struct mm_struct *mm = vma->vm_mm;
++              up_read(&mm->mmap_sem);
+               mmput(mm);
+       }
+-      put_task_struct(task);
+-      if (end - buffer == 0)
+-              return -EIO;
+-      return end - buffer;
+ }
+-const struct file_operations proc_clear_refs_operations = {
+-      .write          = clear_refs_write,
++static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 +{
-+      enum container_filetype type = cft->private;
-+      char *page;
-+      ssize_t retval = 0;
-+      char *s;
-+
-+      if (!(page = (char *)__get_free_page(GFP_KERNEL)))
-+              return -ENOMEM;
-+
-+      s = page;
-+
-+      switch (type) {
-+      case FILE_RELEASE_AGENT:
-+      {
-+              struct containerfs_root *root;
-+              size_t n;
-+              mutex_lock(&container_mutex);
-+              root = cont->root;
-+              n = strnlen(root->release_agent_path,
-+                          sizeof(root->release_agent_path));
-+              n = min(n, (size_t) PAGE_SIZE);
-+              strncpy(s, root->release_agent_path, n);
-+              mutex_unlock(&container_mutex);
-+              s += n;
-+              break;
-+      }
-+      default:
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+      *s++ = '\n';
++      struct proc_maps_private *priv = m->private;
++      struct vm_area_struct *vma = v;
++      struct vm_area_struct *tail_vma = priv->tail_vma;
 +
-+      retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page);
-+out:
-+      free_page((unsigned long)page);
-+      return retval;
++      (*pos)++;
++      if (vma && (vma != tail_vma) && vma->vm_next)
++              return vma->vm_next;
++      vma_stop(priv, vma);
++      return (vma != tail_vma)? tail_vma: NULL;
 +}
 +
-+static ssize_t container_file_read(struct file *file, char __user *buf,
-+                                 size_t nbytes, loff_t *ppos)
++static void m_stop(struct seq_file *m, void *v)
 +{
-+      struct cftype *cft = __d_cft(file->f_dentry);
-+      struct container *cont = __d_cont(file->f_dentry->d_parent);
-+
-+      if (!cft)
-+              return -ENODEV;
++      struct proc_maps_private *priv = m->private;
++      struct vm_area_struct *vma = v;
 +
-+      if (cft->read)
-+              return cft->read(cont, cft, file, buf, nbytes, ppos);
-+      if (cft->read_uint)
-+              return container_read_uint(cont, cft, file, buf, nbytes, ppos);
-+      return -EINVAL;
++      vma_stop(priv, vma);
++      if (priv->task)
++              put_task_struct(priv->task);
 +}
 +
-+static int container_file_open(struct inode *inode, struct file *file)
-+{
-+      int err;
-+      struct cftype *cft;
-+
-+      err = generic_file_open(inode, file);
-+      if (err)
-+              return err;
++static struct seq_operations proc_pid_maps_op = {
++      .start  = m_start,
++      .next   = m_next,
++      .stop   = m_stop,
++      .show   = show_map
++};
 +
-+      cft = __d_cft(file->f_dentry);
-+      if (!cft)
-+              return -ENODEV;
-+      if (cft->open)
-+              err = cft->open(inode, file);
-+      else
-+              err = 0;
++static struct seq_operations proc_pid_smaps_op = {
++      .start  = m_start,
++      .next   = m_next,
++      .stop   = m_stop,
++      .show   = show_smap
++};
 +
-+      return err;
++static int do_maps_open(struct inode *inode, struct file *file,
++                      struct seq_operations *ops)
++{
++      struct proc_maps_private *priv;
++      int ret = -ENOMEM;
++      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++      if (priv) {
++              priv->pid = proc_pid(inode);
++              ret = seq_open(file, ops);
++              if (!ret) {
++                      struct seq_file *m = file->private_data;
++                      m->private = priv;
++              } else {
++                      kfree(priv);
++              }
++      }
++      return ret;
 +}
 +
-+static int container_file_release(struct inode *inode, struct file *file)
++static int maps_open(struct inode *inode, struct file *file)
 +{
-+      struct cftype *cft = __d_cft(file->f_dentry);
-+      if (cft->release)
-+              return cft->release(inode, file);
-+      return 0;
++      return do_maps_open(inode, file, &proc_pid_maps_op);
 +}
 +
-+/*
-+ * container_rename - Only allow simple rename of directories in place.
-+ */
-+static int container_rename(struct inode *old_dir, struct dentry *old_dentry,
-+                          struct inode *new_dir, struct dentry *new_dentry)
-+{
-+      if (!S_ISDIR(old_dentry->d_inode->i_mode))
-+              return -ENOTDIR;
-+      if (new_dentry->d_inode)
-+              return -EEXIST;
-+      if (old_dir != new_dir)
++const struct file_operations proc_maps_operations = {
++      .open           = maps_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = seq_release_private,
+ };
+-#endif
+ #ifdef CONFIG_NUMA
+ extern int show_numa_map(struct seq_file *m, void *v);
+@@ -531,211 +547,14 @@
+ };
+ #endif
+-#ifdef CONFIG_PROC_PAGEMAP
+-struct pagemapread {
+-      struct mm_struct *mm;
+-      unsigned long next;
+-      unsigned long *buf;
+-      pte_t *ptebuf;
+-      unsigned long pos;
+-      size_t count;
+-      int index;
+-      char __user *out;
+-};
+-
+-static int flush_pagemap(struct pagemapread *pm)
+-{
+-      int n = min(pm->count, pm->index * sizeof(unsigned long));
+-      if (copy_to_user(pm->out, pm->buf, n))
+-              return -EFAULT;
+-      pm->out += n;
+-      pm->pos += n;
+-      pm->count -= n;
+-      pm->index = 0;
+-      cond_resched();
+-      return 0;
+-}
+-
+-static int add_to_pagemap(unsigned long addr, unsigned long pfn,
+-                        struct pagemapread *pm)
+-{
+-      pm->buf[pm->index++] = pfn;
+-      pm->next = addr + PAGE_SIZE;
+-      if (pm->index * sizeof(unsigned long) >= PAGE_SIZE ||
+-          pm->index * sizeof(unsigned long) >= pm->count)
+-              return flush_pagemap(pm);
+-      return 0;
+-}
+-
+-static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+-                           void *private)
+-{
+-      struct pagemapread *pm = private;
+-      pte_t *pte;
+-      int err;
+-
+-      pte = pte_offset_map(pmd, addr);
+-
+-#ifdef CONFIG_HIGHPTE
+-      /* copy PTE directory to temporary buffer and unmap it */
+-      memcpy(pm->ptebuf, pte, PAGE_ALIGN((unsigned long)pte) - (unsigned long)pte);
+-      pte_unmap(pte);
+-      pte = pm->ptebuf;
+-#endif
+-
+-      for (; addr != end; pte++, addr += PAGE_SIZE) {
+-              if (addr < pm->next)
+-                      continue;
+-              if (!pte_present(*pte))
+-                      err = add_to_pagemap(addr, -1, pm);
+-              else
+-                      err = add_to_pagemap(addr, pte_pfn(*pte), pm);
+-              if (err)
+-                      return err;
+-      }
+-
+-#ifndef CONFIG_HIGHPTE
+-      pte_unmap(pte - 1);
+-#endif
+-
+-      return 0;
+-}
+-
+-static int pagemap_fill(struct pagemapread *pm, unsigned long end)
+-{
+-      int ret;
+-
+-      while (pm->next != end) {
+-              ret = add_to_pagemap(pm->next, -1UL, pm);
+-              if (ret)
+-                      return ret;
+-      }
+-      return 0;
+-}
+-
+-static struct mm_walk pagemap_walk = { .pmd_entry = pagemap_pte_range };
+-
+-/*
+- * /proc/pid/pagemap - an array mapping virtual pages to pfns
+- *
+- * For each page in the address space, this file contains one long
+- * representing the corresponding physical page frame number (PFN) or
+- * -1 if the page isn't present. This allows determining precisely
+- * which pages are mapped and comparing mapped pages between
+- * processes.
+- *
+- * Efficient users of this interface will use /proc/pid/maps to
+- * determine which areas of memory are actually mapped and llseek to
+- * skip over unmapped regions.
+- *
+- * The first 4 bytes of this file form a simple header:
+- *
+- * first byte:   0 for big endian, 1 for little
+- * second byte:  page shift (eg 12 for 4096 byte pages)
+- * third byte:   entry size in bytes (currently either 4 or 8)
+- * fourth byte:  header size
+- */
+-static ssize_t pagemap_read(struct file *file, char __user *buf,
+-                          size_t count, loff_t *ppos)
++static int smaps_open(struct inode *inode, struct file *file)
+ {
+-      struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+-      unsigned long src = *ppos;
+-      unsigned long *page;
+-      unsigned long addr, end, vend, svpfn, evpfn;
+-      struct mm_struct *mm;
+-      struct vm_area_struct *vma;
+-      struct pagemapread pm;
+-      int ret = -ESRCH;
+-
+-      if (!task)
+-              goto out_no_task;
+-
+-      ret = -EACCES;
+-      if (!ptrace_may_attach(task))
+-              goto out;
+-
+-      ret = -EIO;
+-      svpfn = src / sizeof(unsigned long) - 1;
+-      addr = PAGE_SIZE * svpfn;
+-      if ((svpfn + 1) * sizeof(unsigned long) != src)
+-              goto out;
+-      evpfn = min((src + count) / sizeof(unsigned long),
+-                  ((~0UL) >> PAGE_SHIFT) + 1);
+-      count = (evpfn - svpfn) * sizeof(unsigned long);
+-      end = PAGE_SIZE * evpfn;
+-
+-      ret = -ENOMEM;
+-      page = kzalloc(PAGE_SIZE, GFP_USER);
+-      if (!page)
+-              goto out;
+-
+-#ifdef CONFIG_HIGHPTE
+-      pm.ptebuf = kzalloc(PAGE_SIZE, GFP_USER);
+-      if (!pm.ptebuf)
+-              goto out_free;
+-#endif
+-
+-      ret = 0;
+-      mm = get_task_mm(task);
+-      if (!mm)
+-              goto out_freepte;
+-
+-      pm.mm = mm;
+-      pm.next = addr;
+-      pm.buf = page;
+-      pm.pos = src;
+-      pm.count = count;
+-      pm.index = 0;
+-      pm.out = buf;
+-
+-      if (svpfn == -1) {
+-              add_to_pagemap(pm.next, 0, &pm);
+-              ((char *)page)[0] = (ntohl(1) != 1);
+-              ((char *)page)[1] = PAGE_SHIFT;
+-              ((char *)page)[2] = sizeof(unsigned long);
+-              ((char *)page)[3] = sizeof(unsigned long);
+-      }
+-
+-      down_read(&mm->mmap_sem);
+-      vma = find_vma(mm, pm.next);
+-      while (pm.count > 0 && vma) {
+-              if (!ptrace_may_attach(task)) {
+-                      ret = -EIO;
+-                      goto out_mm;
+-              }
+-              vend = min(vma->vm_start - 1, end - 1) + 1;
+-              ret = pagemap_fill(&pm, vend);
+-              if (ret || !pm.count)
+-                      break;
+-              vend = min(vma->vm_end - 1, end - 1) + 1;
+-              ret = walk_page_range(mm, vma->vm_start, vend,
+-                                    &pagemap_walk, &pm);
+-              vma = vma->vm_next;
+-      }
+-      up_read(&mm->mmap_sem);
+-
+-      ret = pagemap_fill(&pm, end);
+-
+-      *ppos = pm.pos;
+-      if (!ret)
+-              ret = pm.pos - src;
+-
+-out_mm:
+-      mmput(mm);
+-out_freepte:
+-#ifdef CONFIG_HIGHPTE
+-      kfree(pm.ptebuf);
+-out_free:
+-#endif
+-      kfree(page);
+-out:
+-      put_task_struct(task);
+-out_no_task:
+-      return ret;
++      return do_maps_open(inode, file, &proc_pid_smaps_op);
+ }
+-const struct file_operations proc_pagemap_operations = {
+-      .llseek         = mem_lseek, /* borrow this */
+-      .read           = pagemap_read,
++const struct file_operations proc_smaps_operations = {
++      .open           = smaps_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = seq_release_private,
+ };
+-#endif
+diff -Nurb linux-2.6.22-590/fs/ramfs/inode.c linux-2.6.22-570/fs/ramfs/inode.c
+--- linux-2.6.22-590/fs/ramfs/inode.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/ramfs/inode.c  2007-07-08 19:32:17.000000000 -0400
+@@ -60,7 +60,6 @@
+               inode->i_blocks = 0;
+               inode->i_mapping->a_ops = &ramfs_aops;
+               inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
+-              mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
+               inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+               switch (mode & S_IFMT) {
+               default:
+diff -Nurb linux-2.6.22-590/fs/revoke.c linux-2.6.22-570/fs/revoke.c
+--- linux-2.6.22-590/fs/revoke.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/revoke.c       1969-12-31 19:00:00.000000000 -0500
+@@ -1,777 +0,0 @@
+-/*
+- * fs/revoke.c - Invalidate all current open file descriptors of an inode.
+- *
+- * Copyright (C) 2006-2007  Pekka Enberg
+- *
+- * This file is released under the GPLv2.
+- */
+-
+-#include <linux/file.h>
+-#include <linux/fs.h>
+-#include <linux/namei.h>
+-#include <linux/magic.h>
+-#include <linux/mm.h>
+-#include <linux/mman.h>
+-#include <linux/module.h>
+-#include <linux/mount.h>
+-#include <linux/sched.h>
+-#include <linux/revoked_fs_i.h>
+-#include <linux/syscalls.h>
+-
+-/**
+- * fileset - an array of file pointers.
+- * @files:    the array of file pointers
+- * @nr:               number of elements in the array
+- * @end:      index to next unused file pointer
+- */
+-struct fileset {
+-      struct file     **files;
+-      unsigned long   nr;
+-      unsigned long   end;
+-};
+-
+-/**
+- * revoke_details - details of the revoke operation
+- * @inode:            invalidate open file descriptors of this inode
+- * @fset:             set of files that point to a revoked inode
+- * @restore_start:    index to the first file pointer that is currently in
+- *                    use by a file descriptor but the real file has not
+- *                    been revoked
+- */
+-struct revoke_details {
+-      struct fileset  *fset;
+-      unsigned long   restore_start;
+-};
+-
+-static struct kmem_cache *revokefs_inode_cache;
+-
+-static inline bool fset_is_full(struct fileset *set)
+-{
+-      return set->nr == set->end;
+-}
+-
+-static inline struct file *fset_get_filp(struct fileset *set)
+-{
+-      return set->files[set->end++];
+-}
+-
+-static struct fileset *alloc_fset(unsigned long size)
+-{
+-      struct fileset *fset;
+-
+-      fset = kzalloc(sizeof *fset, GFP_KERNEL);
+-      if (!fset)
+-              return NULL;
+-
+-      fset->files = kcalloc(size, sizeof(struct file *), GFP_KERNEL);
+-      if (!fset->files) {
+-              kfree(fset);
+-              return NULL;
+-      }
+-      fset->nr = size;
+-      return fset;
+-}
+-
+-static void free_fset(struct fileset *fset)
+-{
+-      int i;
+-
+-      for (i = fset->end; i < fset->nr; i++)
+-              fput(fset->files[i]);
+-
+-      kfree(fset->files);
+-      kfree(fset);
+-}
+-
+-/*
+- * Revoked file descriptors point to inodes in the revokefs filesystem.
+- */
+-static struct vfsmount *revokefs_mnt;
+-
+-static struct file *get_revoked_file(void)
+-{
+-      struct dentry *dentry;
+-      struct inode *inode;
+-      struct file *filp;
+-      struct qstr name;
+-
+-      filp = get_empty_filp();
+-      if (!filp)
+-              goto err;
+-
+-      inode = new_inode(revokefs_mnt->mnt_sb);
+-      if (!inode)
+-              goto err_inode;
+-
+-      name.name = "revoked_file";
+-      name.len = strlen(name.name);
+-      dentry = d_alloc(revokefs_mnt->mnt_sb->s_root, &name);
+-      if (!dentry)
+-              goto err_dentry;
+-
+-      d_instantiate(dentry, inode);
+-
+-      filp->f_mapping = inode->i_mapping;
+-      filp->f_dentry = dget(dentry);
+-      filp->f_vfsmnt = mntget(revokefs_mnt);
+-      filp->f_op = fops_get(inode->i_fop);
+-      filp->f_pos = 0;
+-
+-      return filp;
+-
+-  err_dentry:
+-      iput(inode);
+-  err_inode:
+-      fput(filp);
+-  err:
+-      return NULL;
+-}
+-
+-static inline bool can_revoke_file(struct file *file, struct inode *inode,
+-                                 struct file *to_exclude)
+-{
+-      if (!file || file == to_exclude)
+-              return false;
+-
+-      return file->f_dentry->d_inode == inode;
+-}
+-
+-/*
+- *    LOCKING: task_lock(owner)
+- */
+-static int revoke_fds(struct task_struct *owner,
+-                    struct inode *inode,
+-                    struct file *to_exclude, struct fileset *fset)
+-{
+-      struct files_struct *files;
+-      struct fdtable *fdt;
+-      unsigned int fd;
+-      int err = 0;
+-
+-      files = get_files_struct(owner);
+-      if (!files)
+-              goto out;
+-
+-      spin_lock(&files->file_lock);
+-      fdt = files_fdtable(files);
+-
+-      for (fd = 0; fd < fdt->max_fds; fd++) {
+-              struct revokefs_inode_info *info;
+-              struct file *filp, *new_filp;
+-              struct inode *new_inode;
+-
+-              filp = fcheck_files(files, fd);
+-              if (!can_revoke_file(filp, inode, to_exclude))
+-                      continue;
+-
+-              if (!filp->f_op->revoke) {
+-                      err = -EOPNOTSUPP;
+-                      goto failed;
+-              }
+-
+-              if (fset_is_full(fset)) {
+-                      err = -ENOMEM;
+-                      goto failed;
+-              }
+-
+-              new_filp = fset_get_filp(fset);
+-
+-              /*
+-               * Replace original struct file pointer with a pointer to
+-               * a 'revoked file.'  After this point, we don't need to worry
+-               * about racing with sys_close or sys_dup.
+-               */
+-              rcu_assign_pointer(fdt->fd[fd], new_filp);
+-
+-              /*
+-               * Hold on to task until we can take down the file and its
+-               * mmap.
+-               */
+-              get_task_struct(owner);
+-
+-              new_inode = new_filp->f_dentry->d_inode;
+-              make_revoked_inode(new_inode, inode->i_mode & S_IFMT);
+-
+-              info = revokefs_i(new_inode);
+-              info->fd = fd;
+-              info->file = filp;
+-              info->owner = owner;
+-      }
+-  failed:
+-      spin_unlock(&files->file_lock);
+-      put_files_struct(files);
+-  out:
+-      return err;
+-}
+-
+-static inline bool can_revoke_vma(struct vm_area_struct *vma,
+-                                struct inode *inode, struct file *to_exclude)
+-{
+-      struct file *file = vma->vm_file;
+-
+-      if (vma->vm_flags & VM_REVOKED)
+-              return false;
+-
+-      if (!file || file == to_exclude)
+-              return false;
+-
+-      return file->f_path.dentry->d_inode == inode;
+-}
+-
+-static int __revoke_break_cow(struct task_struct *tsk, struct inode *inode,
+-                            struct file *to_exclude)
+-{
+-      struct mm_struct *mm = tsk->mm;
+-      struct vm_area_struct *vma;
+-      int err = 0;
+-
+-      down_read(&mm->mmap_sem);
+-      for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
+-              int ret;
+-
+-              if (vma->vm_flags & VM_SHARED)
+-                      continue;
+-
+-              if (!can_revoke_vma(vma, inode, to_exclude))
+-                      continue;
+-
+-              ret = get_user_pages(tsk, tsk->mm, vma->vm_start,
+-                                   vma_pages(vma), 1, 1, NULL, NULL);
+-              if (ret < 0) {
+-                      err = ret;
+-                      break;
+-              }
+-
+-              unlink_file_vma(vma);
+-              fput(vma->vm_file);
+-              vma->vm_file = NULL;
+-      }
+-      up_read(&mm->mmap_sem);
+-      return err;
+-}
+-
+-static int revoke_break_cow(struct fileset *fset, struct inode *inode,
+-                          struct file *to_exclude)
+-{
+-      unsigned long i;
+-      int err = 0;
+-
+-      for (i = 0; i < fset->end; i++) {
+-              struct revokefs_inode_info *info;
+-              struct file *this;
+-
+-              this = fset->files[i];
+-              info = revokefs_i(this->f_dentry->d_inode);
+-
+-              err = __revoke_break_cow(info->owner, inode, to_exclude);
+-              if (err)
+-                      break;
+-      }
+-      return err;
+-}
+-
+-/*
+- *     LOCKING: down_write(&mm->mmap_sem)
+- *                -> spin_lock(&mapping->i_mmap_lock)
+- */
+-static int revoke_vma(struct vm_area_struct *vma, struct zap_details *details)
+-{
+-      unsigned long restart_addr, start_addr, end_addr;
+-      int need_break;
+-
+-      start_addr = vma->vm_start;
+-      end_addr = vma->vm_end;
+-
+-  again:
+-      restart_addr = zap_page_range(vma, start_addr, end_addr - start_addr,
+-                                    details);
+-
+-      need_break = need_resched() || need_lockbreak(details->i_mmap_lock);
+-      if (need_break)
+-              goto out_need_break;
+-
+-      if (restart_addr < end_addr) {
+-              start_addr = restart_addr;
+-              goto again;
+-      }
+-      vma->vm_flags |= VM_REVOKED;
+-      return 0;
+-
+-  out_need_break:
+-      spin_unlock(details->i_mmap_lock);
+-      cond_resched();
+-      spin_lock(details->i_mmap_lock);
+-      return -EINTR;
+-}
+-
+-/*
+- *    LOCKING: spin_lock(&mapping->i_mmap_lock)
+- */
+-static int revoke_mm(struct mm_struct *mm, struct address_space *mapping,
+-                   struct file *to_exclude)
+-{
+-      struct vm_area_struct *vma;
+-      struct zap_details details;
+-      int err = 0;
+-
+-      details.i_mmap_lock = &mapping->i_mmap_lock;
+-
+-      /*
+-       * If ->mmap_sem is under contention, we continue scanning other
+-       * mms and try again later.
+-       */
+-      if (!down_write_trylock(&mm->mmap_sem)) {
+-              err = -EAGAIN;
+-              goto out;
+-      }
+-      for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
+-              if (!(vma->vm_flags & VM_SHARED))
+-                      continue;
+-
+-              if (!can_revoke_vma(vma, mapping->host, to_exclude))
+-                      continue;
+-
+-              err = revoke_vma(vma, &details);
+-              if (err)
+-                      break;
+-
+-              __unlink_file_vma(vma);
+-              fput(vma->vm_file);
+-              vma->vm_file = NULL;
+-      }
+-      up_write(&mm->mmap_sem);
+-  out:
+-      return err;
+-}
+-
+-/*
+- *    LOCKING: spin_lock(&mapping->i_mmap_lock)
+- */
+-static void revoke_mapping_tree(struct address_space *mapping,
+-                              struct file *to_exclude)
+-{
+-      struct vm_area_struct *vma;
+-      struct prio_tree_iter iter;
+-      int try_again = 0;
+-
+-  restart:
+-      vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, 0, ULONG_MAX) {
+-              int err;
+-
+-              if (!(vma->vm_flags & VM_SHARED))
+-                      continue;
+-
+-              if (likely(!can_revoke_vma(vma, mapping->host, to_exclude)))
+-                      continue;
+-
+-              err = revoke_mm(vma->vm_mm, mapping, to_exclude);
+-              if (err == -EAGAIN)
+-                      try_again = 1;
+-
+-              goto restart;
+-      }
+-      if (try_again) {
+-              cond_resched();
+-              goto restart;
+-      }
+-}
+-
+-/*
+- *    LOCKING: spin_lock(&mapping->i_mmap_lock)
+- */
+-static void revoke_mapping_list(struct address_space *mapping,
+-                              struct file *to_exclude)
+-{
+-      struct vm_area_struct *vma;
+-      int try_again = 0;
+-
+-  restart:
+-      list_for_each_entry(vma, &mapping->i_mmap_nonlinear, shared.vm_set.list) {
+-              int err;
+-
+-              if (likely(!can_revoke_vma(vma, mapping->host, to_exclude)))
+-                      continue;
+-
+-              err = revoke_mm(vma->vm_mm, mapping, to_exclude);
+-              if (err == -EAGAIN) {
+-                      try_again = 1;
+-                      continue;
+-              }
+-              if (err == -EINTR)
+-                      goto restart;
+-      }
+-      if (try_again) {
+-              cond_resched();
+-              goto restart;
+-      }
+-}
+-
+-static void revoke_mapping(struct address_space *mapping, struct file *to_exclude)
+-{
+-      spin_lock(&mapping->i_mmap_lock);
+-      if (unlikely(!prio_tree_empty(&mapping->i_mmap)))
+-              revoke_mapping_tree(mapping, to_exclude);
+-      if (unlikely(!list_empty(&mapping->i_mmap_nonlinear)))
+-              revoke_mapping_list(mapping, to_exclude);
+-      spin_unlock(&mapping->i_mmap_lock);
+-}
+-
+-static void restore_file(struct revokefs_inode_info *info)
+-{
+-      struct files_struct *files;
+-
+-      files = get_files_struct(info->owner);
+-      if (files) {
+-              struct fdtable *fdt;
+-              struct file *filp;
+-
+-              spin_lock(&files->file_lock);
+-              fdt = files_fdtable(files);
+-
+-              filp = fdt->fd[info->fd];
+-              if (filp)
+-                      fput(filp);
+-
+-              rcu_assign_pointer(fdt->fd[info->fd], info->file);
+-              FD_SET(info->fd, fdt->close_on_exec);
+-              spin_unlock(&files->file_lock);
+-              put_files_struct(files);
+-      }
+-      put_task_struct(info->owner);
+-      info->owner = NULL;     /* To avoid double-restore. */
+-}
+-
+-static void restore_files(struct revoke_details *details)
+-{
+-      unsigned long i;
+-
+-      for (i = details->restore_start; i < details->fset->end; i++) {
+-              struct revokefs_inode_info *info;
+-              struct file *filp;
+-
+-              filp = details->fset->files[i];
+-              info = revokefs_i(filp->f_dentry->d_inode);
+-
+-              restore_file(info);
+-      }
+-}
+-
+-static int revoke_files(struct revoke_details *details)
+-{
+-      unsigned long i;
+-      int err = 0;
+-
+-      for (i = 0; i < details->fset->end; i++) {
+-              struct revokefs_inode_info *info;
+-              struct file *this, *filp;
+-              struct inode *inode;
+-
+-              this = details->fset->files[i];
+-              inode = this->f_dentry->d_inode;
+-              info = revokefs_i(inode);
+-
+-              /*
+-               * Increase count before attempting to close file as
+-               * an partially closed file can no longer be restored.
+-               */
+-              details->restore_start++;
+-              filp = info->file;
+-              err = filp->f_op->revoke(filp, inode->i_mapping);
+-              put_task_struct(info->owner);
+-              info->owner = NULL;     /* To avoid restoring closed file. */
+-              if (err)
+-                      goto out;
+-      }
+-  out:
+-      return err;
+-}
+-
+-/*
+- *    Returns the maximum number of file descriptors pointing to an inode.
+- *
+- *    LOCKING: read_lock(&tasklist_lock)
+- */
+-static unsigned long inode_fds(struct inode *inode, struct file *to_exclude)
+-{
+-      struct task_struct *g, *p;
+-      unsigned long nr_fds = 0;
+-
+-      do_each_thread(g, p) {
+-              struct files_struct *files;
+-              struct fdtable *fdt;
+-              unsigned int fd;
+-
+-              files = get_files_struct(p);
+-              if (!files)
+-                      continue;
+-
+-              spin_lock(&files->file_lock);
+-              fdt = files_fdtable(files);
+-              for (fd = 0; fd < fdt->max_fds; fd++) {
+-                      struct file *file;
+-
+-                      file = fcheck_files(files, fd);
+-                      if (can_revoke_file(file, inode, to_exclude)) {
+-                              nr_fds += fdt->max_fds;
+-                              break;
+-                      }
+-              }
+-              spin_unlock(&files->file_lock);
+-              put_files_struct(files);
+-      }
+-      while_each_thread(g, p);
+-      return nr_fds;
+-}
+-
+-static struct fileset *__alloc_revoke_fset(unsigned long size)
+-{
+-      struct fileset *fset;
+-      int i;
+-
+-      fset = alloc_fset(size);
+-      if (!fset)
+-              return NULL;
+-
+-      for (i = 0; i < fset->nr; i++) {
+-              struct file *filp;
+-
+-              filp = get_revoked_file();
+-              if (!filp)
+-                      goto err;
+-
+-              fset->files[i] = filp;
+-      }
+-      return fset;
+-  err:
+-      free_fset(fset);
+-      return NULL;
+-}
+-
+-static struct fileset *alloc_revoke_fset(struct inode *inode, struct file *to_exclude)
+-{
+-      unsigned long nr_fds;
+-
+-      read_lock(&tasklist_lock);
+-      nr_fds = inode_fds(inode, to_exclude);
+-      read_unlock(&tasklist_lock);
+-
+-      return __alloc_revoke_fset(nr_fds);
+-}
+-
+-static int do_revoke(struct inode *inode, struct file *to_exclude)
+-{
+-      struct revoke_details details;
+-      struct fileset *fset = NULL;
+-      struct task_struct *g, *p;
+-      int err = 0;
+-
+-      if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER)) {
+-              err = -EPERM;
+-              goto out;
+-      }
+-
+-  retry:
+-      if (signal_pending(current)) {
+-              err = -ERESTARTSYS;
+-              goto out;
+-      }
+-
+-      /*
+-       * Pre-allocate memory because the first pass is done under
+-       * tasklist_lock.
+-       */
+-      fset = alloc_revoke_fset(inode, to_exclude);
+-      if (!fset) {
+-              err = -ENOMEM;
+-              goto out;
+-      }
+-
+-      read_lock(&tasklist_lock);
+-
+-      /*
+-       * If someone forked while we were allocating memory, try again.
+-       */
+-      if (inode_fds(inode, to_exclude) > fset->nr) {
+-              read_unlock(&tasklist_lock);
+-              free_fset(fset);
+-              goto retry;
+-      }
+-
+-      details.fset = fset;
+-      details.restore_start = 0;
+-
+-      /*
+-       * First revoke the descriptors. After we are done, no one can start
+-       * new operations on them.
+-       */
+-      do_each_thread(g, p) {
+-              err = revoke_fds(p, inode, to_exclude, fset);
+-              if (err)
+-                      goto exit_loop;
+-      }
+-      while_each_thread(g, p);
+-  exit_loop:
+-      read_unlock(&tasklist_lock);
+-
+-      if (err)
+-              goto out_restore;
+-
+-      /*
+-       * Take down shared memory mappings.
+-       */
+-      revoke_mapping(inode->i_mapping, to_exclude);
+-
+-      /*
+-       * Break COW for private mappings.
+-       */
+-      err = revoke_break_cow(fset, inode, to_exclude);
+-      if (err)
+-              goto out_restore;
+-
+-      /*
+-       * Now, revoke the files for good.
+-       */
+-      err = revoke_files(&details);
+-      if (err)
+-              goto out_restore;
+-
+-  out_free_table:
+-      free_fset(fset);
+-  out:
+-      return err;
+-
+-  out_restore:
+-      restore_files(&details);
+-      goto out_free_table;
+-}
+-
+-asmlinkage long sys_revokeat(int dfd, const char __user * filename)
+-{
+-      struct nameidata nd;
+-      int err;
+-
+-      err = __user_walk_fd(dfd, filename, 0, &nd);
+-      if (!err) {
+-              err = do_revoke(nd.dentry->d_inode, NULL);
+-              path_release(&nd);
+-      }
+-      return err;
+-}
+-
+-asmlinkage long sys_frevoke(unsigned int fd)
+-{
+-      struct file *file = fget(fd);
+-      int err = -EBADF;
+-
+-      if (file) {
+-              err = do_revoke(file->f_dentry->d_inode, file);
+-              fput(file);
+-      }
+-      return err;
+-}
+-
+-int generic_file_revoke(struct file *file, struct address_space *new_mapping)
+-{
+-      struct address_space *mapping = file->f_mapping;
+-      int err;
+-
+-      /*
+-       * Flush pending writes.
+-       */
+-      err = do_fsync(file, 1);
+-      if (err)
+-              goto out;
+-
+-      file->f_mapping = new_mapping;
+-
+-      /*
+-       * Make pending reads fail.
+-       */
+-      err = invalidate_inode_pages2(mapping);
+-
+-  out:
+-      return err;
+-}
+-EXPORT_SYMBOL(generic_file_revoke);
+-
+-/*
+- *    Filesystem for revoked files.
+- */
+-
+-static struct inode *revokefs_alloc_inode(struct super_block *sb)
+-{
+-      struct revokefs_inode_info *info;
+-
+-      info = kmem_cache_alloc(revokefs_inode_cache, GFP_KERNEL);
+-      if (!info)
+-              return NULL;
+-
+-      return &info->vfs_inode;
+-}
+-
+-static void revokefs_destroy_inode(struct inode *inode)
+-{
+-      kmem_cache_free(revokefs_inode_cache, revokefs_i(inode));
+-}
+-
+-static struct super_operations revokefs_super_ops = {
+-      .alloc_inode = revokefs_alloc_inode,
+-      .destroy_inode = revokefs_destroy_inode,
+-      .drop_inode = generic_delete_inode,
+-};
+-
+-static int revokefs_get_sb(struct file_system_type *fs_type,
+-                         int flags, const char *dev_name, void *data,
+-                         struct vfsmount *mnt)
+-{
+-      return get_sb_pseudo(fs_type, "revoke:", &revokefs_super_ops,
+-                           REVOKEFS_MAGIC, mnt);
+-}
+-
+-static struct file_system_type revokefs_fs_type = {
+-      .name = "revokefs",
+-      .get_sb = revokefs_get_sb,
+-      .kill_sb = kill_anon_super
+-};
+-
+-static void revokefs_init_inode(void *obj, struct kmem_cache *cache,
+-                              unsigned long flags)
+-{
+-      struct revokefs_inode_info *info = obj;
+-
+-      info->owner = NULL;
+-      inode_init_once(&info->vfs_inode);
+-}
+-
+-static int __init revokefs_init(void)
+-{
+-      int err = -ENOMEM;
+-
+-      revokefs_inode_cache =
+-          kmem_cache_create("revokefs_inode_cache",
+-                            sizeof(struct revokefs_inode_info),
+-                            0,
+-                            (SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT |
+-                             SLAB_MEM_SPREAD), revokefs_init_inode, NULL);
+-      if (!revokefs_inode_cache)
+-              goto out;
+-
+-      err = register_filesystem(&revokefs_fs_type);
+-      if (err)
+-              goto err_register;
+-
+-      revokefs_mnt = kern_mount(&revokefs_fs_type);
+-      if (IS_ERR(revokefs_mnt)) {
+-              err = PTR_ERR(revokefs_mnt);
+-              goto err_mnt;
+-      }
+-  out:
+-      return err;
+-  err_mnt:
+-      unregister_filesystem(&revokefs_fs_type);
+-  err_register:
+-      kmem_cache_destroy(revokefs_inode_cache);
+-      return err;
+-}
+-
+-late_initcall(revokefs_init);
+diff -Nurb linux-2.6.22-590/fs/revoked_inode.c linux-2.6.22-570/fs/revoked_inode.c
+--- linux-2.6.22-590/fs/revoked_inode.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/revoked_inode.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,417 +0,0 @@
+-/*
+- * fs/revoked_inode.c
+- *
+- * Copyright (C) 2007  Pekka Enberg
+- *
+- * Provide stub functions for revoked inodes. Based on fs/bad_inode.c which is
+- *
+- * Copyright (C) 1997  Stephen Tweedie
+- *
+- * This file is released under the GPLv2.
+- */
+-
+-#include <linux/fs.h>
+-#include <linux/module.h>
+-#include <linux/stat.h>
+-#include <linux/time.h>
+-#include <linux/smp_lock.h>
+-#include <linux/namei.h>
+-#include <linux/poll.h>
+-#include <linux/revoked_fs_i.h>
+-
+-static loff_t revoked_file_llseek(struct file *file, loff_t offset, int origin)
+-{
+-      return -EBADF;
+-}
+-
+-static ssize_t revoked_file_read(struct file *filp, char __user * buf,
+-                               size_t size, loff_t * ppos)
+-{
+-      return -EBADF;
+-}
+-
+-static ssize_t revoked_special_file_read(struct file *filp, char __user * buf,
+-                                       size_t size, loff_t * ppos)
+-{
+-      return 0;
+-}
+-
+-static ssize_t revoked_file_write(struct file *filp, const char __user * buf,
+-                                size_t siz, loff_t * ppos)
+-{
+-      return -EBADF;
+-}
+-
+-static ssize_t revoked_file_aio_read(struct kiocb *iocb,
+-                                   const struct iovec *iov,
+-                                   unsigned long nr_segs, loff_t pos)
+-{
+-      return -EBADF;
+-}
+-
+-static ssize_t revoked_file_aio_write(struct kiocb *iocb,
+-                                    const struct iovec *iov,
+-                                    unsigned long nr_segs, loff_t pos)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_file_readdir(struct file *filp, void *dirent,
+-                              filldir_t filldir)
+-{
+-      return -EBADF;
+-}
+-
+-static unsigned int revoked_file_poll(struct file *filp, poll_table * wait)
+-{
+-      return POLLERR;
+-}
+-
+-static int revoked_file_ioctl(struct inode *inode, struct file *filp,
+-                            unsigned int cmd, unsigned long arg)
+-{
+-      return -EBADF;
+-}
+-
+-static long revoked_file_unlocked_ioctl(struct file *file, unsigned cmd,
+-                                      unsigned long arg)
+-{
+-      return -EBADF;
+-}
+-
+-static long revoked_file_compat_ioctl(struct file *file, unsigned int cmd,
+-                                    unsigned long arg)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_file_mmap(struct file *file, struct vm_area_struct *vma)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_file_open(struct inode *inode, struct file *filp)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_file_flush(struct file *file, fl_owner_t id)
+-{
+-      return filp_close(file, id);
+-}
+-
+-static int revoked_file_release(struct inode *inode, struct file *filp)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_file_fsync(struct file *file, struct dentry *dentry,
+-                            int datasync)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_file_aio_fsync(struct kiocb *iocb, int datasync)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_file_fasync(int fd, struct file *filp, int on)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_file_lock(struct file *file, int cmd, struct file_lock *fl)
+-{
+-      return -EBADF;
+-}
+-
+-static ssize_t revoked_file_sendfile(struct file *in_file, loff_t * ppos,
+-                                   size_t count, read_actor_t actor,
+-                                   void *target)
+-{
+-      return -EBADF;
+-}
+-
+-static ssize_t revoked_file_sendpage(struct file *file, struct page *page,
+-                                   int off, size_t len, loff_t * pos,
+-                                   int more)
+-{
+-      return -EBADF;
+-}
+-
+-static unsigned long revoked_file_get_unmapped_area(struct file *file,
+-                                                  unsigned long addr,
+-                                                  unsigned long len,
+-                                                  unsigned long pgoff,
+-                                                  unsigned long flags)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_file_check_flags(int flags)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_file_dir_notify(struct file *file, unsigned long arg)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_file_flock(struct file *filp, int cmd, struct file_lock *fl)
+-{
+-      return -EBADF;
+-}
+-
+-static ssize_t revoked_file_splice_write(struct pipe_inode_info *pipe,
+-                                       struct file *out, loff_t * ppos,
+-                                       size_t len, unsigned int flags)
+-{
+-      return -EBADF;
+-}
+-
+-static ssize_t revoked_file_splice_read(struct file *in, loff_t * ppos,
+-                                      struct pipe_inode_info *pipe,
+-                                      size_t len, unsigned int flags)
+-{
+-      return -EBADF;
+-}
+-
+-static const struct file_operations revoked_file_ops = {
+-      .llseek = revoked_file_llseek,
+-      .read = revoked_file_read,
+-      .write = revoked_file_write,
+-      .aio_read = revoked_file_aio_read,
+-      .aio_write = revoked_file_aio_write,
+-      .readdir = revoked_file_readdir,
+-      .poll = revoked_file_poll,
+-      .ioctl = revoked_file_ioctl,
+-      .unlocked_ioctl = revoked_file_unlocked_ioctl,
+-      .compat_ioctl = revoked_file_compat_ioctl,
+-      .mmap = revoked_file_mmap,
+-      .open = revoked_file_open,
+-      .flush = revoked_file_flush,
+-      .release = revoked_file_release,
+-      .fsync = revoked_file_fsync,
+-      .aio_fsync = revoked_file_aio_fsync,
+-      .fasync = revoked_file_fasync,
+-      .lock = revoked_file_lock,
+-      .sendfile = revoked_file_sendfile,
+-      .sendpage = revoked_file_sendpage,
+-      .get_unmapped_area = revoked_file_get_unmapped_area,
+-      .check_flags = revoked_file_check_flags,
+-      .dir_notify = revoked_file_dir_notify,
+-      .flock = revoked_file_flock,
+-      .splice_write = revoked_file_splice_write,
+-      .splice_read = revoked_file_splice_read,
+-};
+-
+-static const struct file_operations revoked_special_file_ops = {
+-      .llseek = revoked_file_llseek,
+-      .read = revoked_special_file_read,
+-      .write = revoked_file_write,
+-      .aio_read = revoked_file_aio_read,
+-      .aio_write = revoked_file_aio_write,
+-      .readdir = revoked_file_readdir,
+-      .poll = revoked_file_poll,
+-      .ioctl = revoked_file_ioctl,
+-      .unlocked_ioctl = revoked_file_unlocked_ioctl,
+-      .compat_ioctl = revoked_file_compat_ioctl,
+-      .mmap = revoked_file_mmap,
+-      .open = revoked_file_open,
+-      .flush = revoked_file_flush,
+-      .release = revoked_file_release,
+-      .fsync = revoked_file_fsync,
+-      .aio_fsync = revoked_file_aio_fsync,
+-      .fasync = revoked_file_fasync,
+-      .lock = revoked_file_lock,
+-      .sendfile = revoked_file_sendfile,
+-      .sendpage = revoked_file_sendpage,
+-      .get_unmapped_area = revoked_file_get_unmapped_area,
+-      .check_flags = revoked_file_check_flags,
+-      .dir_notify = revoked_file_dir_notify,
+-      .flock = revoked_file_flock,
+-      .splice_write = revoked_file_splice_write,
+-      .splice_read = revoked_file_splice_read,
+-};
+-
+-static int revoked_inode_create(struct inode *dir, struct dentry *dentry,
+-                              int mode, struct nameidata *nd)
+-{
+-      return -EBADF;
+-}
+-
+-static struct dentry *revoked_inode_lookup(struct inode *dir,
+-                                         struct dentry *dentry,
+-                                         struct nameidata *nd)
+-{
+-      return ERR_PTR(-EBADF);
+-}
+-
+-static int revoked_inode_link(struct dentry *old_dentry, struct inode *dir,
+-                            struct dentry *dentry)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_inode_unlink(struct inode *dir, struct dentry *dentry)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_inode_symlink(struct inode *dir, struct dentry *dentry,
+-                               const char *symname)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_inode_mkdir(struct inode *dir, struct dentry *dentry,
+-                             int mode)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_inode_rmdir(struct inode *dir, struct dentry *dentry)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_inode_mknod(struct inode *dir, struct dentry *dentry,
+-                             int mode, dev_t rdev)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_inode_rename(struct inode *old_dir,
+-                              struct dentry *old_dentry,
+-                              struct inode *new_dir,
+-                              struct dentry *new_dentry)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_inode_readlink(struct dentry *dentry, char __user * buffer,
+-                                int buflen)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_inode_permission(struct inode *inode, int mask,
+-                                  struct nameidata *nd)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
+-                               struct kstat *stat)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_inode_setattr(struct dentry *direntry, struct iattr *attrs)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_inode_setxattr(struct dentry *dentry, const char *name,
+-                                const void *value, size_t size, int flags)
+-{
+-      return -EBADF;
+-}
+-
+-static ssize_t revoked_inode_getxattr(struct dentry *dentry, const char *name,
+-                                    void *buffer, size_t size)
+-{
+-      return -EBADF;
+-}
+-
+-static ssize_t revoked_inode_listxattr(struct dentry *dentry, char *buffer,
+-                                     size_t buffer_size)
+-{
+-      return -EBADF;
+-}
+-
+-static int revoked_inode_removexattr(struct dentry *dentry, const char *name)
+-{
+-      return -EBADF;
+-}
+-
+-static struct inode_operations revoked_inode_ops = {
+-      .create = revoked_inode_create,
+-      .lookup = revoked_inode_lookup,
+-      .link = revoked_inode_link,
+-      .unlink = revoked_inode_unlink,
+-      .symlink = revoked_inode_symlink,
+-      .mkdir = revoked_inode_mkdir,
+-      .rmdir = revoked_inode_rmdir,
+-      .mknod = revoked_inode_mknod,
+-      .rename = revoked_inode_rename,
+-      .readlink = revoked_inode_readlink,
+-      /* follow_link must be no-op, otherwise unmounting this inode
+-         won't work */
+-      /* put_link returns void */
+-      /* truncate returns void */
+-      .permission = revoked_inode_permission,
+-      .getattr = revoked_inode_getattr,
+-      .setattr = revoked_inode_setattr,
+-      .setxattr = revoked_inode_setxattr,
+-      .getxattr = revoked_inode_getxattr,
+-      .listxattr = revoked_inode_listxattr,
+-      .removexattr = revoked_inode_removexattr,
+-      /* truncate_range returns void */
+-};
+-
+-static int revoked_readpage(struct file *file, struct page *page)
+-{
+-      return -EIO;
+-}
+-
+-static int revoked_writepage(struct page *page, struct writeback_control *wbc)
+-{
+-      return -EIO;
+-}
+-
+-static int revoked_prepare_write(struct file *file, struct page *page,
+-                               unsigned from, unsigned to)
+-{
+-      return -EIO;
+-}
+-
+-static int revoked_commit_write(struct file *file, struct page *page,
+-                              unsigned from, unsigned to)
+-{
+-      return -EIO;
+-}
+-
+-static ssize_t revoked_direct_IO(int rw, struct kiocb *iocb,
+-                               const struct iovec *iov, loff_t offset,
+-                               unsigned long nr_segs)
+-{
+-      return -EIO;
+-}
+-
+-static const struct address_space_operations revoked_aops = {
+-        .readpage       = revoked_readpage,
+-        .writepage      = revoked_writepage,
+-        .prepare_write  = revoked_prepare_write,
+-        .commit_write   = revoked_commit_write,
+-        .direct_IO      = revoked_direct_IO,
+-};
+-
+-void make_revoked_inode(struct inode *inode, int mode)
+-{
+-      remove_inode_hash(inode);
+-
+-      inode->i_mode = mode;
+-      inode->i_atime = inode->i_mtime = inode->i_ctime =
+-          current_fs_time(inode->i_sb);
+-      inode->i_op = &revoked_inode_ops;
+-
+-      if (special_file(mode))
+-              inode->i_fop = &revoked_special_file_ops;
+-      else
+-              inode->i_fop = &revoked_file_ops;
+-
+-      inode->i_mapping->a_ops = &revoked_aops;
+-}
+diff -Nurb linux-2.6.22-590/fs/splice.c linux-2.6.22-570/fs/splice.c
+--- linux-2.6.22-590/fs/splice.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/splice.c       2008-01-23 19:15:56.000000000 -0500
+@@ -28,7 +28,6 @@
+ #include <linux/module.h>
+ #include <linux/syscalls.h>
+ #include <linux/uio.h>
+-#include <linux/security.h>
+ struct partial_page {
+       unsigned int offset;
+@@ -933,10 +932,6 @@
+       if (unlikely(ret < 0))
+               return ret;
+-      ret = security_file_permission(out, MAY_WRITE);
+-      if (unlikely(ret < 0))
+-              return ret;
+-
+       return out->f_op->splice_write(pipe, out, ppos, len, flags);
+ }
+@@ -959,10 +954,6 @@
+       if (unlikely(ret < 0))
+               return ret;
+-      ret = security_file_permission(in, MAY_READ);
+-      if (unlikely(ret < 0))
+-              return ret;
+-
+       return in->f_op->splice_read(in, ppos, pipe, len, flags);
+ }
+@@ -1281,7 +1272,6 @@
+ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
+                       unsigned long nr_segs, unsigned int flags)
+ {
+-      long err;
+       struct pipe_inode_info *pipe;
+       struct page *pages[PIPE_BUFFERS];
+       struct partial_page partial[PIPE_BUFFERS];
+@@ -1300,10 +1290,6 @@
+       else if (unlikely(!nr_segs))
+               return 0;
+-      err = security_file_permission(file, MAY_WRITE);
+-      if (unlikely(err < 0))
+-              return err;
+-
+       spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial,
+                                           flags & SPLICE_F_GIFT);
+       if (spd.nr_pages <= 0)
+diff -Nurb linux-2.6.22-590/fs/stack.c linux-2.6.22-570/fs/stack.c
+--- linux-2.6.22-590/fs/stack.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/stack.c        2007-07-08 19:32:17.000000000 -0400
+@@ -1,20 +1,8 @@
+-/*
+- * Copyright (c) 2006-2007 Erez Zadok
+- * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2006-2007 Stony Brook University
+- * Copyright (c) 2006-2007 The Research Foundation of SUNY
+- *
+- * 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/fs.h>
+ #include <linux/fs_stack.h>
+-/*
+- * does _NOT_ require i_mutex to be held.
++/* does _NOT_ require i_mutex to be held.
+  *
+  * This function cannot be inlined since i_size_{read,write} is rather
+  * heavy-weight on 32-bit systems
+@@ -26,8 +14,7 @@
+ }
+ EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
+-/*
+- * copy all attributes; get_nlinks is optional way to override the i_nlink
++/* copy all attributes; get_nlinks is optional way to override the i_nlink
+  * copying
+  */
+ void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
+diff -Nurb linux-2.6.22-590/fs/sync.c linux-2.6.22-570/fs/sync.c
+--- linux-2.6.22-590/fs/sync.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/sync.c 2007-07-08 19:32:17.000000000 -0400
+@@ -174,9 +174,6 @@
+  * already-instantiated disk blocks, there are no guarantees here that the data
+  * will be available after a crash.
+  */
+-/* It would be nice if people remember that not all the world's an i386
+-   when they introduce new system calls */
+-
+ asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
+                                       unsigned int flags)
+ {
+diff -Nurb linux-2.6.22-590/fs/sysfs/bin.c linux-2.6.22-570/fs/sysfs/bin.c
+--- linux-2.6.22-590/fs/sysfs/bin.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/sysfs/bin.c    2007-07-08 19:32:17.000000000 -0400
+@@ -20,41 +20,29 @@
+ #include "sysfs.h"
+-struct bin_buffer {
+-      struct mutex    mutex;
+-      void            *buffer;
+-      int             mmapped;
+-};
+-
+ static int
+ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
+ {
+-      struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+-      struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+-      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+-      int rc;
+-
+-      /* need attr_sd for attr, its parent for kobj */
+-      if (!sysfs_get_active_two(attr_sd))
+-              return -ENODEV;
+-
+-      rc = -EIO;
+-      if (attr->read)
+-              rc = attr->read(kobj, attr, buffer, off, count);
++      struct bin_attribute * attr = to_bin_attr(dentry);
++      struct kobject * kobj = to_kobj(dentry->d_parent);
+-      sysfs_put_active_two(attr_sd);
++      if (!attr->read)
 +              return -EIO;
-+      return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
-+}
-+
-+static struct file_operations container_file_operations = {
-+      .read = container_file_read,
-+      .write = container_file_write,
-+      .llseek = generic_file_llseek,
-+      .open = container_file_open,
-+      .release = container_file_release,
-+};
-+
-+static struct inode_operations container_dir_inode_operations = {
-+      .lookup = simple_lookup,
-+      .mkdir = container_mkdir,
-+      .rmdir = container_rmdir,
-+      .rename = container_rename,
-+};
-+
-+static int container_create_file(struct dentry *dentry, int mode,
-+                              struct super_block *sb)
-+{
-+      struct inode *inode;
-+
-+      if (!dentry)
-+              return -ENOENT;
-+      if (dentry->d_inode)
-+              return -EEXIST;
-+
-+      inode = container_new_inode(mode, sb);
-+      if (!inode)
-+              return -ENOMEM;
-+
-+      if (S_ISDIR(mode)) {
-+              inode->i_op = &container_dir_inode_operations;
-+              inode->i_fop = &simple_dir_operations;
-+
-+              /* start off with i_nlink == 2 (for "." entry) */
-+              inc_nlink(inode);
-+
-+              /* start with the directory inode held, so that we can
-+               * populate it without racing with another mkdir */
-+              mutex_lock(&inode->i_mutex);
-+      } else if (S_ISREG(mode)) {
-+              inode->i_size = 0;
-+              inode->i_fop = &container_file_operations;
-+      }
-+
-+      d_instantiate(dentry, inode);
-+      dget(dentry);   /* Extra count - pin the dentry in core */
-+      return 0;
-+}
-+
-+/*
-+ *    container_create_dir - create a directory for an object.
-+ *    cont:   the container we create the directory for.
-+ *            It must have a valid ->parent field
-+ *            And we are going to fill its ->dentry field.
-+ *    name:   The name to give to the container directory. Will be copied.
-+ *    mode:   mode to set on new directory.
-+ */
-+static int container_create_dir(struct container *cont, struct dentry *dentry,
-+                              int mode)
-+{
-+      struct dentry *parent;
-+      int error = 0;
-+
-+      parent = cont->parent->dentry;
-+      if (IS_ERR(dentry))
-+              return PTR_ERR(dentry);
-+      error = container_create_file(dentry, S_IFDIR | mode, cont->root->sb);
-+      if (!error) {
-+              dentry->d_fsdata = cont;
-+              inc_nlink(parent->d_inode);
-+              cont->dentry = dentry;
-+      }
-+      dput(dentry);
-+
-+      return error;
-+}
-+
-+int container_add_file(struct container *cont, const struct cftype *cft)
-+{
-+      struct dentry *dir = cont->dentry;
-+      struct dentry *dentry;
-+      int error;
-+
-+      BUG_ON(!mutex_is_locked(&dir->d_inode->i_mutex));
-+      dentry = container_get_dentry(dir, cft->name);
-+      if (!IS_ERR(dentry)) {
-+              error = container_create_file(dentry, 0644 | S_IFREG,
-+                                              cont->root->sb);
-+              if (!error)
-+                      dentry->d_fsdata = (void *)cft;
-+              dput(dentry);
-+      } else
-+              error = PTR_ERR(dentry);
-+      return error;
-+}
-+
-+int container_add_files(struct container *cont, const struct cftype cft[],
-+                      int count)
-+{
-+      int i, err;
-+      for (i = 0; i < count; i++) {
-+              err = container_add_file(cont, &cft[i]);
-+              if (err)
-+                      return err;
-+      }
-+      return 0;
-+}
-+
-+/* Count the number of tasks in a container. */
-+
-+int container_task_count(const struct container *cont)
-+{
-+      int count = 0;
-+      struct list_head *l;
-+
-+      read_lock(&css_group_lock);
-+      l = cont->css_groups.next;
-+      while (l != &cont->css_groups) {
-+              struct cg_container_link *link =
-+                      list_entry(l, struct cg_container_link, cont_link_list);
-+              count += atomic_read(&link->cg->ref.refcount);
-+              l = l->next;
-+      }
-+      read_unlock(&css_group_lock);
-+      return count;
-+}
-+
-+/* Advance a list_head iterator pointing at a cg_container_link's */
-+static void container_advance_iter(struct container *cont,
-+                                        struct container_iter *it)
-+{
-+      struct list_head *l = it->cg_link;
-+      struct cg_container_link *link;
-+      struct css_group *cg;
-+
-+      /* Advance to the next non-empty css_group */
-+      do {
-+              l = l->next;
-+              if (l == &cont->css_groups) {
-+                      it->cg_link = NULL;
-+                      return;
-+              }
-+              link = list_entry(l, struct cg_container_link, cont_link_list);
-+              cg = link->cg;
-+      } while (list_empty(&cg->tasks));
-+      it->cg_link = l;
-+      it->task = cg->tasks.next;
-+}
-+
-+void container_iter_start(struct container *cont, struct container_iter *it)
-+{
-+      read_lock(&css_group_lock);
-+      it->cg_link = &cont->css_groups;
-+      container_advance_iter(cont, it);
-+}
+-      return rc;
++      return attr->read(kobj, buffer, off, count);
+ }
+ static ssize_t
+-read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
++read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
+ {
+-      struct bin_buffer *bb = file->private_data;
++      char *buffer = file->private_data;
+       struct dentry *dentry = file->f_path.dentry;
+       int size = dentry->d_inode->i_size;
+       loff_t offs = *off;
+-      int count = min_t(size_t, bytes, PAGE_SIZE);
++      int ret;
 +
-+struct task_struct *container_iter_next(struct container *cont,
-+                                      struct container_iter *it)
-+{
-+      struct task_struct *res;
-+      struct list_head *l = it->task;
++      if (count > PAGE_SIZE)
++              count = PAGE_SIZE;
+       if (size) {
+               if (offs > size)
+@@ -63,56 +51,43 @@
+                       count = size - offs;
+       }
+-      mutex_lock(&bb->mutex);
++      ret = fill_read(dentry, buffer, offs, count);
++      if (ret < 0) 
++              return ret;
++      count = ret;
+-      count = fill_read(dentry, bb->buffer, offs, count);
+-      if (count < 0)
+-              goto out_unlock;
+-
+-      if (copy_to_user(userbuf, bb->buffer, count)) {
+-              count = -EFAULT;
+-              goto out_unlock;
+-      }
++      if (copy_to_user(userbuf, buffer, count))
++              return -EFAULT;
+-      pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
++      pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count);
+       *off = offs + count;
+- out_unlock:
+-      mutex_unlock(&bb->mutex);
+       return count;
+ }
+ static int
+ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
+ {
+-      struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+-      struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+-      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+-      int rc;
++      struct bin_attribute *attr = to_bin_attr(dentry);
++      struct kobject *kobj = to_kobj(dentry->d_parent);
+-      /* need attr_sd for attr, its parent for kobj */
+-      if (!sysfs_get_active_two(attr_sd))
+-              return -ENODEV;
++      if (!attr->write)
++              return -EIO;
+-      rc = -EIO;
+-      if (attr->write)
+-              rc = attr->write(kobj, attr, buffer, offset, count);
+-
+-      sysfs_put_active_two(attr_sd);
+-
+-      return rc;
++      return attr->write(kobj, buffer, offset, count);
+ }
+-static ssize_t write(struct file *file, const char __user *userbuf,
+-                   size_t bytes, loff_t *off)
++static ssize_t write(struct file * file, const char __user * userbuf,
++                   size_t count, loff_t * off)
+ {
+-      struct bin_buffer *bb = file->private_data;
++      char *buffer = file->private_data;
+       struct dentry *dentry = file->f_path.dentry;
+       int size = dentry->d_inode->i_size;
+       loff_t offs = *off;
+-      int count = min_t(size_t, bytes, PAGE_SIZE);
++      if (count > PAGE_SIZE)
++              count = PAGE_SIZE;
+       if (size) {
+               if (offs > size)
+                       return 0;
+@@ -120,100 +95,72 @@
+                       count = size - offs;
+       }
+-      mutex_lock(&bb->mutex);
++      if (copy_from_user(buffer, userbuf, count))
++              return -EFAULT;
+-      if (copy_from_user(bb->buffer, userbuf, count)) {
+-              count = -EFAULT;
+-              goto out_unlock;
+-      }
+-
+-      count = flush_write(dentry, bb->buffer, offs, count);
++      count = flush_write(dentry, buffer, offs, count);
+       if (count > 0)
+               *off = offs + count;
+-
+- out_unlock:
+-      mutex_unlock(&bb->mutex);
+       return count;
+ }
+ static int mmap(struct file *file, struct vm_area_struct *vma)
+ {
+-      struct bin_buffer *bb = file->private_data;
+-      struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+-      struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+-      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+-      int rc;
+-
+-      mutex_lock(&bb->mutex);
+-
+-      /* need attr_sd for attr, its parent for kobj */
+-      if (!sysfs_get_active_two(attr_sd))
+-              return -ENODEV;
+-
+-      rc = -EINVAL;
+-      if (attr->mmap)
+-              rc = attr->mmap(kobj, attr, vma);
+-
+-      if (rc == 0 && !bb->mmapped)
+-              bb->mmapped = 1;
+-      else
+-              sysfs_put_active_two(attr_sd);
++      struct dentry *dentry = file->f_path.dentry;
++      struct bin_attribute *attr = to_bin_attr(dentry);
++      struct kobject *kobj = to_kobj(dentry->d_parent);
+-      mutex_unlock(&bb->mutex);
++      if (!attr->mmap)
++              return -EINVAL;
+-      return rc;
++      return attr->mmap(kobj, attr, vma);
+ }
+ static int open(struct inode * inode, struct file * file)
+ {
+-      struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+-      struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+-      struct bin_buffer *bb = NULL;
+-      int error;
+-
+-      /* need attr_sd for attr */
+-      if (!sysfs_get_active(attr_sd))
+-              return -ENODEV;
++      struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
++      struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
++      int error = -EINVAL;
 +
-+      /* If the iterator cg is NULL, we have no tasks */
-+      if (!it->cg_link)
-+              return NULL;
-+      res = list_entry(l, struct task_struct, cg_list);
-+      /* Advance iterator to find next entry */
-+      l = l->next;
-+      if (l == &res->containers->tasks) {
-+              /* We reached the end of this task list - move on to
-+               * the next cg_container_link */
-+              container_advance_iter(cont, it);
-+      } else {
-+              it->task = l;
-+      }
-+      return res;
-+}
++      if (!kobj || !attr)
++              goto Done;
 +
-+void container_iter_end(struct container *cont, struct container_iter *it)
-+{
-+      read_unlock(&css_group_lock);
-+}
++      /* Grab the module reference for this attribute if we have one */
++      error = -ENODEV;
++      if (!try_module_get(attr->attr.owner)) 
++              goto Done;
+       error = -EACCES;
+       if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap))
+-              goto err_out;
++              goto Error;
+       if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap))
+-              goto err_out;
++              goto Error;
+       error = -ENOMEM;
+-      bb = kzalloc(sizeof(*bb), GFP_KERNEL);
+-      if (!bb)
+-              goto err_out;
+-
+-      bb->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+-      if (!bb->buffer)
+-              goto err_out;
+-
+-      mutex_init(&bb->mutex);
+-      file->private_data = bb;
+-
+-      /* open succeeded, put active reference and pin attr_sd */
+-      sysfs_put_active(attr_sd);
+-      sysfs_get(attr_sd);
+-      return 0;
+-
+- err_out:
+-      sysfs_put_active(attr_sd);
+-      kfree(bb);
++      file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
++      if (!file->private_data)
++              goto Error;
 +
-+/*
-+ * Stuff for reading the 'tasks' file.
-+ *
-+ * Reading this file can return large amounts of data if a container has
-+ * *lots* of attached tasks. So it may need several calls to read(),
-+ * but we cannot guarantee that the information we produce is correct
-+ * unless we produce it entirely atomically.
-+ *
-+ * Upon tasks file open(), a struct ctr_struct is allocated, that
-+ * will have a pointer to an array (also allocated here).  The struct
-+ * ctr_struct * is stored in file->private_data.  Its resources will
-+ * be freed by release() when the file is closed.  The array is used
-+ * to sprintf the PIDs and then used by read().
-+ */
-+struct ctr_struct {
-+      char *buf;
-+      int bufsz;
-+};
++      error = 0;
++    goto Done;
 +
-+/*
-+ * Load into 'pidarray' up to 'npids' of the tasks using container
-+ * 'cont'.  Return actual number of pids loaded.  No need to
-+ * task_lock(p) when reading out p->container, since we're in an RCU
-+ * read section, so the css_group can't go away, and is
-+ * immutable after creation.
-+ */
-+static int pid_array_load(pid_t *pidarray, int npids, struct container *cont)
-+{
-+      int n = 0;
-+      struct container_iter it;
-+      struct task_struct *tsk;
-+      container_iter_start(cont, &it);
-+      while ((tsk = container_iter_next(cont, &it))) {
-+              if (unlikely(n == npids))
-+                      break;
-+              pidarray[n++] = pid_nr(task_pid(tsk));
-+      }
-+      container_iter_end(cont, &it);
-+      return n;
-+}
++ Error:
++      module_put(attr->attr.owner);
++ Done:
++      if (error)
++              kobject_put(kobj);
+       return error;
+ }
+ static int release(struct inode * inode, struct file * file)
+ {
+-      struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+-      struct bin_buffer *bb = file->private_data;
+-
+-      if (bb->mmapped)
+-              sysfs_put_active_two(attr_sd);
+-      sysfs_put(attr_sd);
+-      kfree(bb->buffer);
+-      kfree(bb);
++      struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent);
++      struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
++      u8 * buffer = file->private_data;
 +
-+static int cmppid(const void *a, const void *b)
-+{
-+      return *(pid_t *)a - *(pid_t *)b;
++      kobject_put(kobj);
++      module_put(attr->attr.owner);
++      kfree(buffer);
+       return 0;
+ }
+@@ -234,9 +181,9 @@
+ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
+ {
+-      BUG_ON(!kobj || !kobj->sd || !attr);
++      BUG_ON(!kobj || !kobj->dentry || !attr);
+-      return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
++      return sysfs_add_file(kobj->dentry, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
+ }
+@@ -248,7 +195,7 @@
+ void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
+ {
+-      if (sysfs_hash_and_remove(kobj, kobj->sd, attr->attr.name) < 0) {
++      if (sysfs_hash_and_remove(kobj->dentry, attr->attr.name) < 0) {
+               printk(KERN_ERR "%s: "
+                       "bad dentry or inode or no such file: \"%s\"\n",
+                       __FUNCTION__, attr->attr.name);
+diff -Nurb linux-2.6.22-590/fs/sysfs/dir.c linux-2.6.22-570/fs/sysfs/dir.c
+--- linux-2.6.22-590/fs/sysfs/dir.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/sysfs/dir.c    2007-07-08 19:32:17.000000000 -0400
+@@ -9,442 +9,21 @@
+ #include <linux/module.h>
+ #include <linux/kobject.h>
+ #include <linux/namei.h>
+-#include <linux/idr.h>
+-#include <linux/completion.h>
+ #include <asm/semaphore.h>
+ #include "sysfs.h"
+-static void sysfs_prune_shadow_sd(struct sysfs_dirent *sd);
+-
+-DEFINE_MUTEX(sysfs_mutex);
+-spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED;
+-
+-static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED;
+-static DEFINE_IDA(sysfs_ino_ida);
+-
+-static struct sysfs_dirent *find_shadow_sd(struct sysfs_dirent *parent_sd, const void *target)
+-{
+-      /* Find the shadow directory for the specified tag */
+-      struct sysfs_dirent *sd;
+-
+-      for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) {
+-              if (sd->s_name != target)
+-                      continue;
+-              break;
+-      }
+-      return sd;
+-}
+-
+-static const void *find_shadow_tag(struct kobject *kobj)
+-{
+-      /* Find the tag the current kobj is cached with */
+-      return kobj->sd->s_parent->s_name;
+-}
+-
+-/**
+- *    sysfs_link_sibling - link sysfs_dirent into sibling list
+- *    @sd: sysfs_dirent of interest
+- *
+- *    Link @sd into its sibling list which starts from
+- *    sd->s_parent->s_children.
+- *
+- *    Locking:
+- *    mutex_lock(sysfs_mutex)
+- */
+-
+-/**
+- *    sysfs_unlink_sibling - unlink sysfs_dirent from sibling list
+- *    @sd: sysfs_dirent of interest
+- *
+- *    Unlink @sd from its sibling list which starts from
+- *    sd->s_parent->s_children.
+- *
+- *    Locking:
+- *    mutex_lock(sysfs_mutex)
+- */
+-
+-void sysfs_link_sibling(struct sysfs_dirent *sd)
+-{
+-      struct sysfs_dirent *parent_sd = sd->s_parent;
+-
+-      BUG_ON(sd->s_sibling);
+-      sd->s_sibling = parent_sd->s_children;
+-      parent_sd->s_children = sd;
+-}
+-/**
+- *    sysfs_get_dentry - get dentry for the given sysfs_dirent
+- *    @sd: sysfs_dirent of interest
+- *
+- *    Get dentry for @sd.  Dentry is looked up if currently not
+- *    present.  This function climbs sysfs_dirent tree till it
+- *    reaches a sysfs_dirent with valid dentry attached and descends
+- *    down from there looking up dentry for each step.
+- *
+- *    LOCKING:
+- *    Kernel thread context (may sleep)
+- *
+- *    RETURNS:
+- *    Pointer to found dentry on success, ERR_PTR() value on error.
+- */
+-struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd)
+-{
+-      struct sysfs_dirent *cur;
+-      struct dentry *parent_dentry, *dentry;
+-      int i, depth;
+-
+-      /* Find the first parent which has valid s_dentry and get the
+-       * dentry.
+-       */
+-      mutex_lock(&sysfs_mutex);
+- restart0:
+-      spin_lock(&sysfs_assoc_lock);
+- restart1:
+-      spin_lock(&dcache_lock);
+-
+-      dentry = NULL;
+-      depth = 0;
+-      cur = sd;
+-      while (!cur->s_dentry || !cur->s_dentry->d_inode) {
+-              if (cur->s_flags & SYSFS_FLAG_REMOVED) {
+-                      dentry = ERR_PTR(-ENOENT);
+-                      depth = 0;
+-                      break;
+-              }
+-              cur = cur->s_parent;
+-              depth++;
+-      }
+-      if (!IS_ERR(dentry))
+-              dentry = dget_locked(cur->s_dentry);
+-
+-      spin_unlock(&dcache_lock);
+-      spin_unlock(&sysfs_assoc_lock);
+-
+-      /* from the found dentry, look up depth times */
+-      while (depth--) {
+-              /* find and get depth'th ancestor */
+-              for (cur = sd, i = 0; cur && i < depth; i++)
+-                      cur = cur->s_parent;
+-
+-              /* This can happen if tree structure was modified due
+-               * to move/rename.  Restart.
+-               */
+-              if (i != depth) {
+-                      dput(dentry);
+-                      goto restart0;
+-              }
+-
+-              sysfs_get(cur);
+-
+-              mutex_unlock(&sysfs_mutex);
+-
+-              /* look it up */
+-              parent_dentry = dentry;
+-              dentry = lookup_one_len_kern(cur->s_name, parent_dentry,
+-                                           strlen(cur->s_name));
+-              dput(parent_dentry);
+-
+-              if (IS_ERR(dentry)) {
+-                      sysfs_put(cur);
+-                      return dentry;
+-              }
+-
+-              mutex_lock(&sysfs_mutex);
+-              spin_lock(&sysfs_assoc_lock);
+-
+-              /* This, again, can happen if tree structure has
+-               * changed and we looked up the wrong thing.  Restart.
+-               */
+-              if (cur->s_dentry != dentry) {
+-                      dput(dentry);
+-                      sysfs_put(cur);
+-                      goto restart1;
+-              }
+-
+-              spin_unlock(&sysfs_assoc_lock);
+-
+-              sysfs_put(cur);
+-      }
+-
+-      mutex_unlock(&sysfs_mutex);
+-      return dentry;
+-}
+-
+-/**
+- *    sysfs_link_sibling - link sysfs_dirent into sibling list
+- *    @sd: sysfs_dirent of interest
+- *
+- *    Link @sd into its sibling list which starts from
+- *    sd->s_parent->s_children.
+- *
+- *    Locking:
+- *    mutex_lock(sd->s_parent->dentry->d_inode->i_mutex)
+- */
+-
+-/**
+- *    sysfs_unlink_sibling - unlink sysfs_dirent from sibling list
+- *    @sd: sysfs_dirent of interest
+- *
+- *    Unlink @sd from its sibling list which starts from
+- *    sd->s_parent->s_children.
+- *
+- *    Locking:
+- *    mutex_lock(sd->s_parent->dentry->d_inode->i_mutex)
+- */
+-void sysfs_unlink_sibling(struct sysfs_dirent *sd)
+-{
+-      struct sysfs_dirent **pos;
+-
+-      for (pos = &sd->s_parent->s_children; *pos; pos = &(*pos)->s_sibling) {
+-              if (*pos == sd) {
+-                      *pos = sd->s_sibling;
+-                      sd->s_sibling = NULL;
+-                      break;
+-              }
+-      }
+-}
+-
+-/**
+- *    sysfs_get_dentry - get dentry for the given sysfs_dirent
+- *    @sd: sysfs_dirent of interest
+- *
+- *    Get dentry for @sd.  Dentry is looked up if currently not
+- *    present.  This function climbs sysfs_dirent tree till it
+- *    reaches a sysfs_dirent with valid dentry attached and descends
+- *    down from there looking up dentry for each step.
+- *
+- *    LOCKING:
+- *    Kernel thread context (may sleep)
+- *
+- *    RETURNS:
+- *    Pointer to found dentry on success, ERR_PTR() value on error.
+- */
+-
+-/**
+- *    sysfs_get_active - get an active reference to sysfs_dirent
+- *    @sd: sysfs_dirent to get an active reference to
+- *
+- *    Get an active reference of @sd.  This function is noop if @sd
+- *    is NULL.
+- *
+- *    RETURNS:
+- *    Pointer to @sd on success, NULL on failure.
+- */
+-/**
+- *    sysfs_put_active - put an active reference to sysfs_dirent
+- *    @sd: sysfs_dirent to put an active reference to
+- *
+- *    Put an active reference to @sd.  This function is noop if @sd
+- *    is NULL.
+- */
+-void sysfs_put_active(struct sysfs_dirent *sd)
+-{
+-      struct completion *cmpl;
+-      int v;
+-
+-      if (unlikely(!sd))
+-              return;
+-
+-      v = atomic_dec_return(&sd->s_active);
+-      if (likely(v != SD_DEACTIVATED_BIAS))
+-              return;
+-
+-      /* atomic_dec_return() is a mb(), we'll always see the updated
+-       * sd->s_sibling.
+-       */
+-      cmpl = (void *)sd->s_sibling;
+-      complete(cmpl);
+-}
+-
+-/**
+- *    sysfs_get_active_two - get active references to sysfs_dirent and parent
+- *    @sd: sysfs_dirent of interest
+- *
+- *    Get active reference to @sd and its parent.  Parent's active
+- *    reference is grabbed first.  This function is noop if @sd is
+- *    NULL.
+- *
+- *    RETURNS:
+- *    Pointer to @sd on success, NULL on failure.
+- */
+-struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd)
+-{
+-      if (sd) {
+-              if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent)))
+-                      return NULL;
+-              if (unlikely(!sysfs_get_active(sd))) {
+-                      sysfs_put_active(sd->s_parent);
+-                      return NULL;
+-              }
+-      }
+-      return sd;
+-}
+-
+-/**
+- *    sysfs_put_active_two - put active references to sysfs_dirent and parent
+- *    @sd: sysfs_dirent of interest
+- *
+- *    Put active references to @sd and its parent.  This function is
+- *    noop if @sd is NULL.
+- */
+-void sysfs_put_active_two(struct sysfs_dirent *sd)
+-{
+-      if (sd) {
+-              sysfs_put_active(sd);
+-              sysfs_put_active(sd->s_parent);
+-      }
+-}
+-
+-/**
+- *    sysfs_deactivate - deactivate sysfs_dirent
+- *    @sd: sysfs_dirent to deactivate
+- *
+- *    Deny new active references and drain existing ones.
+- */
+-static void sysfs_deactivate(struct sysfs_dirent *sd)
+-{
+-      DECLARE_COMPLETION_ONSTACK(wait);
+-      int v;
+-
+-      BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
+-      sd->s_sibling = (void *)&wait;
+-
+-      /* atomic_add_return() is a mb(), put_active() will always see
+-       * the updated sd->s_sibling.
+-       */
+-      v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active);
+-
+-      if (v != SD_DEACTIVATED_BIAS)
+-              wait_for_completion(&wait);
+-
+-      sd->s_sibling = NULL;
+-}
+-
+-/**
+- *    sysfs_get_active - get an active reference to sysfs_dirent
+- *    @sd: sysfs_dirent to get an active reference to
+- *
+- *    Get an active reference of @sd.  This function is noop if @sd
+- *    is NULL.
+- *
+- *    RETURNS:
+- *    Pointer to @sd on success, NULL on failure.
+- */
+-struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
+-{
+-      if (unlikely(!sd))
+-              return NULL;
+-
+-      while (1) {
+-              int v, t;
+-
+-              v = atomic_read(&sd->s_active);
+-              if (unlikely(v < 0))
+-                      return NULL;
+-
+-              t = atomic_cmpxchg(&sd->s_active, v, v + 1);
+-              if (likely(t == v))
+-                      return sd;
+-              if (t < 0)
+-                      return NULL;
+-
+-              cpu_relax();
+-      }
+-}
+-/**
+- *    sysfs_put_active - put an active reference to sysfs_dirent
+- *    @sd: sysfs_dirent to put an active reference to
+- *
+- *    Put an active reference to @sd.  This function is noop if @sd
+- *    is NULL.
+- */
+-
+-/**
+- *    sysfs_get_active_two - get active references to sysfs_dirent and parent
+- *    @sd: sysfs_dirent of interest
+- *
+- *    Get active reference to @sd and its parent.  Parent's active
+- *    reference is grabbed first.  This function is noop if @sd is
+- *    NULL.
+- *
+- *    RETURNS:
+- *    Pointer to @sd on success, NULL on failure.
+- */
+-
+-/**
+- *    sysfs_put_active_two - put active references to sysfs_dirent and parent
+- *    @sd: sysfs_dirent of interest
+- *
+- *    Put active references to @sd and its parent.  This function is
+- *    noop if @sd is NULL.
+- */
+-
+-/**
+- *    sysfs_deactivate - deactivate sysfs_dirent
+- *    @sd: sysfs_dirent to deactivate
+- *
+- *    Deny new active references and drain existing ones.  s_active
+- *    will be unlocked when the sysfs_dirent is released.
+- */
+-
+-static int sysfs_alloc_ino(ino_t *pino)
+-{
+-      int ino, rc;
+-
+- retry:
+-      spin_lock(&sysfs_ino_lock);
+-      rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino);
+-      spin_unlock(&sysfs_ino_lock);
+-
+-      if (rc == -EAGAIN) {
+-              if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL))
+-                      goto retry;
+-              rc = -ENOMEM;
+-      }
+-
+-      *pino = ino;
+-      return rc;
+-}
+-
+-static void sysfs_free_ino(ino_t ino)
+-{
+-      spin_lock(&sysfs_ino_lock);
+-      ida_remove(&sysfs_ino_ida, ino);
+-      spin_unlock(&sysfs_ino_lock);
+-}
+-
+-void release_sysfs_dirent(struct sysfs_dirent * sd)
+-{
+-      struct sysfs_dirent *parent_sd;
+-
+- repeat:
+-      /* Moving/renaming is always done while holding reference.
+-       * sd->s_parent won't change beneath us.
+-       */
+-      parent_sd = sd->s_parent;
+-
+-      if (sysfs_type(sd) == SYSFS_KOBJ_LINK)
+-              sysfs_put(sd->s_elem.symlink.target_sd);
+-      if (sysfs_type(sd) & SYSFS_COPY_NAME)
+-              kfree(sd->s_name);
+-      kfree(sd->s_iattr);
+-      if (sysfs_type(sd) != SYSFS_SHADOW_DIR)
+-              sysfs_free_ino(sd->s_ino);
+-      kmem_cache_free(sysfs_dir_cachep, sd);
+-
+-      sd = parent_sd;
+-      if (sd && atomic_dec_and_test(&sd->s_count))
+-              goto repeat;
+-}
++DECLARE_RWSEM(sysfs_rename_sem);
++spinlock_t sysfs_lock = SPIN_LOCK_UNLOCKED;
+ static void sysfs_d_iput(struct dentry * dentry, struct inode * inode)
+ {
+       struct sysfs_dirent * sd = dentry->d_fsdata;
+       if (sd) {
+-              /* sd->s_dentry is protected with sysfs_assoc_lock.
+-               * This allows sysfs_drop_dentry() to dereference it.
++              /* sd->s_dentry is protected with sysfs_lock.  This
++               * allows sysfs_drop_dentry() to dereference it.
+                */
+-              spin_lock(&sysfs_assoc_lock);
++              spin_lock(&sysfs_lock);
+               /* The dentry might have been deleted or another
+                * lookup could have happened updating sd->s_dentry to
+@@ -453,7 +32,7 @@
+                */
+               if (sd->s_dentry == dentry)
+                       sd->s_dentry = NULL;
+-              spin_unlock(&sysfs_assoc_lock);
++              spin_unlock(&sysfs_lock);
+               sysfs_put(sd);
+       }
+       iput(inode);
+@@ -463,594 +42,344 @@
+       .d_iput         = sysfs_d_iput,
+ };
+-struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
++static unsigned int sysfs_inode_counter;
++ino_t sysfs_get_inum(void)
+ {
+-      char *dup_name = NULL;
+-      struct sysfs_dirent *sd = NULL;
++      if (unlikely(sysfs_inode_counter < 3))
++              sysfs_inode_counter = 3;
++      return sysfs_inode_counter++;
 +}
-+
+-      if (type & SYSFS_COPY_NAME) {
+-              name = dup_name = kstrdup(name, GFP_KERNEL);
+-              if (!name)
+-                      goto err_out;
+-      }
 +/*
-+ * Convert array 'a' of 'npids' pid_t's to a string of newline separated
-+ * decimal pids in 'buf'.  Don't write more than 'sz' chars, but return
-+ * count 'cnt' of how many chars would be written if buf were large enough.
++ * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent
 + */
-+static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids)
++static struct sysfs_dirent * __sysfs_new_dirent(void * element)
 +{
-+      int cnt = 0;
-+      int i;
-+
-+      for (i = 0; i < npids; i++)
-+              cnt += snprintf(buf + cnt, max(sz - cnt, 0), "%d\n", a[i]);
-+      return cnt;
-+}
-+
++      struct sysfs_dirent * sd;
+       sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
+       if (!sd)
+-              goto err_out;
+-
+-      if (sysfs_alloc_ino(&sd->s_ino))
+-              goto err_out;
++              return NULL;
++      sd->s_ino = sysfs_get_inum();
+       atomic_set(&sd->s_count, 1);
+-      atomic_set(&sd->s_active, 0);
+       atomic_set(&sd->s_event, 1);
+-
+-      sd->s_name = name;
+-      sd->s_mode = mode;
+-      sd->s_flags = type;
++      INIT_LIST_HEAD(&sd->s_children);
++      INIT_LIST_HEAD(&sd->s_sibling);
++      sd->s_element = element;
+       return sd;
+-
+- err_out:
+-      kfree(dup_name);
+-      kmem_cache_free(sysfs_dir_cachep, sd);
+-      return NULL;
+ }
+-/**
+- *    sysfs_attach_dentry - associate sysfs_dirent with dentry
+- *    @sd: target sysfs_dirent
+- *    @dentry: dentry to associate
+- *
+- *    Associate @sd with @dentry.  This is protected by
+- *    sysfs_assoc_lock to avoid race with sysfs_d_iput().
+- *
+- *    LOCKING:
+- *    mutex_lock(sysfs_mutex)
+- */
+-static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry)
++static void __sysfs_list_dirent(struct sysfs_dirent *parent_sd,
++                            struct sysfs_dirent *sd)
+ {
+-      dentry->d_op = &sysfs_dentry_ops;
+-      dentry->d_fsdata = sysfs_get(sd);
+-
+-      /* protect sd->s_dentry against sysfs_d_iput */
+-      spin_lock(&sysfs_assoc_lock);
+-      sd->s_dentry = dentry;
+-      spin_unlock(&sysfs_assoc_lock);
+-
+-      if (dentry->d_flags & DCACHE_UNHASHED)
+-      d_rehash(dentry);
++      if (sd)
++              list_add(&sd->s_sibling, &parent_sd->s_children);
+ }
+-static int sysfs_ilookup_test(struct inode *inode, void *arg)
++static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent *parent_sd,
++                                              void * element)
+ {
+-      struct sysfs_dirent *sd = arg;
+-      return inode->i_ino == sd->s_ino;
++      struct sysfs_dirent *sd;
++      sd = __sysfs_new_dirent(element);
++      __sysfs_list_dirent(parent_sd, sd);
++      return sd;
+ }
+-/**
+- *    sysfs_addrm_start - prepare for sysfs_dirent add/remove
+- *    @acxt: pointer to sysfs_addrm_cxt to be used
+- *    @parent_sd: parent sysfs_dirent
 +/*
-+ * Handle an open on 'tasks' file.  Prepare a buffer listing the
-+ * process id's of tasks currently attached to the container being opened.
-+ *
-+ * Does not require any specific container mutexes, and does not take any.
-+ */
-+static int container_tasks_open(struct inode *unused, struct file *file)
-+{
-+      struct container *cont = __d_cont(file->f_dentry->d_parent);
-+      struct ctr_struct *ctr;
-+      pid_t *pidarray;
-+      int npids;
-+      char c;
-+
-+      if (!(file->f_mode & FMODE_READ))
-+              return 0;
-+
-+      ctr = kmalloc(sizeof(*ctr), GFP_KERNEL);
-+      if (!ctr)
-+              goto err0;
-+
-+      /*
-+       * If container gets more users after we read count, we won't have
-+       * enough space - tough.  This race is indistinguishable to the
-+       * caller from the case that the additional container users didn't
-+       * show up until sometime later on.
-+       */
-+      npids = container_task_count(cont);
-+      if (npids) {
-+              pidarray = kmalloc(npids * sizeof(pid_t), GFP_KERNEL);
-+              if (!pidarray)
-+                      goto err1;
-+
-+              npids = pid_array_load(pidarray, npids, cont);
-+              sort(pidarray, npids, sizeof(pid_t), cmppid, NULL);
-+
-+              /* Call pid_array_to_buf() twice, first just to get bufsz */
-+              ctr->bufsz = pid_array_to_buf(&c, sizeof(c), pidarray, npids) + 1;
-+              ctr->buf = kmalloc(ctr->bufsz, GFP_KERNEL);
-+              if (!ctr->buf)
-+                      goto err2;
-+              ctr->bufsz = pid_array_to_buf(ctr->buf, ctr->bufsz, pidarray, npids);
-+
-+              kfree(pidarray);
-+      } else {
-+              ctr->buf = 0;
-+              ctr->bufsz = 0;
-+      }
-+      file->private_data = ctr;
+  *
+- *    This function is called when the caller is about to add or
+- *    remove sysfs_dirent under @parent_sd.  This function acquires
+- *    sysfs_mutex, grabs inode for @parent_sd if available and lock
+- *    i_mutex of it.  @acxt is used to keep and pass context to
+- *    other addrm functions.
++ * Return -EEXIST if there is already a sysfs element with the same name for
++ * the same parent.
+  *
+- *    LOCKING:
+- *    Kernel thread context (may sleep).  sysfs_mutex is locked on
+- *    return.  i_mutex of parent inode is locked on return if
+- *    available.
++ * called with parent inode's i_mutex held
+  */
+-void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
+-                     struct sysfs_dirent *parent_sd)
++int sysfs_dirent_exist(struct sysfs_dirent *parent_sd,
++                        const unsigned char *new)
+ {
+-      struct inode *inode;
+-
+-      memset(acxt, 0, sizeof(*acxt));
+-      acxt->parent_sd = parent_sd;
+-
+-      /* Lookup parent inode.  inode initialization and I_NEW
+-       * clearing are protected by sysfs_mutex.  By grabbing it and
+-       * looking up with _nowait variant, inode state can be
+-       * determined reliably.
+-       */
+-      mutex_lock(&sysfs_mutex);
+-
+-      inode = ilookup5_nowait(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
+-                              parent_sd);
++      struct sysfs_dirent * sd;
+-      if (inode && !(inode->i_state & I_NEW)) {
+-              /* parent inode available */
+-              acxt->parent_inode = inode;
+-
+-              /* sysfs_mutex is below i_mutex in lock hierarchy.
+-               * First, trylock i_mutex.  If fails, unlock
+-               * sysfs_mutex and lock them in order.
+-               */
+-              if (!mutex_trylock(&inode->i_mutex)) {
+-                      mutex_unlock(&sysfs_mutex);
+-                      mutex_lock(&inode->i_mutex);
+-                      mutex_lock(&sysfs_mutex);
++      list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
++              if (sd->s_element) {
++                      const unsigned char *existing = sysfs_get_name(sd);
++                      if (strcmp(existing, new))
++                              continue;
++                      else
++                              return -EEXIST;
+       }
+-      } else
+-              iput(inode);
+-}
+-
+-/**
+- *    sysfs_add_one - add sysfs_dirent to parent
+- *    @acxt: addrm context to use
+- *    @sd: sysfs_dirent to be added
+- *
+- *    Get @acxt->parent_sd and set sd->s_parent to it and increment
+- *    nlink of parent inode if @sd is a directory.  @sd is NOT
+- *    linked into the children list of the parent.  The caller
+- *    should invoke sysfs_link_sibling() after this function
+- *    completes if @sd needs to be on the children list.
+- *
+- *    This function should be called between calls to
+- *    sysfs_addrm_start() and sysfs_addrm_finish() and should be
+- *    passed the same @acxt as passed to sysfs_addrm_start().
+- *
+- *    LOCKING:
+- *    Determined by sysfs_addrm_start().
+- */
+-void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
+-{
+-      sd->s_parent = sysfs_get(acxt->parent_sd);
+-
+-      if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
+-              inc_nlink(acxt->parent_inode);
+-
+-      acxt->cnt++;
+-}
+-
+-/**
+- *    sysfs_remove_one - remove sysfs_dirent from parent
+- *    @acxt: addrm context to use
+- *    @sd: sysfs_dirent to be added
+- *
+- *    Mark @sd removed and drop nlink of parent inode if @sd is a
+- *    directory.  @sd is NOT unlinked from the children list of the
+- *    parent.  The caller is repsonsible for removing @sd from the
+- *    children list before calling this function.
+- *
+- *    This function should be called between calls to
+- *    sysfs_addrm_start() and sysfs_addrm_finish() and should be
+- *    passed the same @acxt as passed to sysfs_addrm_start().
+- *
+- *    LOCKING:
+- *    Determined by sysfs_addrm_start().
+- */
+-void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
+-{
+-      BUG_ON(sd->s_sibling || (sd->s_flags & SYSFS_FLAG_REMOVED));
+-
+-      sd->s_flags |= SYSFS_FLAG_REMOVED;
+-      sd->s_sibling = acxt->removed;
+-      acxt->removed = sd;
+-
+-      if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
+-              drop_nlink(acxt->parent_inode);
+-
+-      acxt->cnt++;
+-}
+-
+-/**
+- *    sysfs_drop_dentry - drop dentry for the specified sysfs_dirent
+- *    @sd: target sysfs_dirent
+- *
+- *    Drop dentry for @sd.  @sd must have been unlinked from its
+- *    parent on entry to this function such that it can't be looked
+- *    up anymore.
+- *
+- *    @sd->s_dentry which is protected with sysfs_assoc_lock points
+- *    to the currently associated dentry but we're not holding a
+- *    reference to it and racing with dput().  Grab dcache_lock and
+- *    verify dentry before dropping it.  If @sd->s_dentry is NULL or
+- *    dput() beats us, no need to bother.
+- */
+-static void sysfs_drop_dentry(struct sysfs_dirent *sd)
+-{
+-      struct dentry *dentry = NULL;
+-      struct inode *inode;
+-
+-      /* We're not holding a reference to ->s_dentry dentry but the
+-       * field will stay valid as long as sysfs_assoc_lock is held.
+-       */
+-      spin_lock(&sysfs_assoc_lock);
+-      spin_lock(&dcache_lock);
+-
+-      /* drop dentry if it's there and dput() didn't kill it yet */
+-      if (sd->s_dentry && sd->s_dentry->d_inode) {
+-              dentry = dget_locked(sd->s_dentry);
+-              spin_lock(&dentry->d_lock);
+-              __d_drop(dentry);
+-              spin_unlock(&dentry->d_lock);
+-      }
+-
+-      spin_unlock(&dcache_lock);
+-      spin_unlock(&sysfs_assoc_lock);
+-
+-      /* dentries for shadowed directories are pinned, unpin */
+-      if ((sysfs_type(sd) == SYSFS_SHADOW_DIR) ||
+-          (sd->s_flags & SYSFS_FLAG_SHADOWED))
+-              dput(dentry);
+-      dput(dentry);
+-
+-      /* adjust nlink and update timestamp */
+-      inode = ilookup(sysfs_sb, sd->s_ino);
+-      if (inode) {
+-              mutex_lock(&inode->i_mutex);
+-
+-              inode->i_ctime = CURRENT_TIME;
+-              drop_nlink(inode);
+-              if (sysfs_type(sd) == SYSFS_DIR)
+-                      drop_nlink(inode);
+-
+-              mutex_unlock(&inode->i_mutex);
+-              iput(inode);
+       }
+-}
+-/**
+- *    sysfs_drop_dentry - drop dentry for the specified sysfs_dirent
+- *    @sd: target sysfs_dirent
+- *
+- *    Drop dentry for @sd.  @sd must have been unlinked from its
+- *    parent on entry to this function such that it can't be looked
+- *    up anymore.
+- *
+- *    @sd->s_dentry which is protected with sysfs_assoc_lock points
+- *    to the currently associated dentry but we're not holding a
+- *    reference to it and racing with dput().  Grab dcache_lock and
+- *    verify dentry before dropping it.  If @sd->s_dentry is NULL or
+- *    dput() beats us, no need to bother.
+- */
 +      return 0;
-+
-+err2:
-+      kfree(pidarray);
-+err1:
-+      kfree(ctr);
-+err0:
-+      return -ENOMEM;
-+}
-+
-+static ssize_t container_tasks_read(struct container *cont,
-+                                  struct cftype *cft,
-+                                  struct file *file, char __user *buf,
-+                                  size_t nbytes, loff_t *ppos)
-+{
-+      struct ctr_struct *ctr = file->private_data;
-+
-+      return simple_read_from_buffer(buf, nbytes, ppos, ctr->buf, ctr->bufsz);
 +}
-+
-+static int container_tasks_release(struct inode *unused_inode,
-+                                      struct file *file)
-+{
-+      struct ctr_struct *ctr;
-+
-+      if (file->f_mode & FMODE_READ) {
-+              ctr = file->private_data;
-+              kfree(ctr->buf);
-+              kfree(ctr);
-+      }
+-/**
+- *    sysfs_addrm_finish - finish up sysfs_dirent add/remove
+- *    @acxt: addrm context to finish up
+- *
+- *    Finish up sysfs_dirent add/remove.  Resources acquired by
+- *    sysfs_addrm_start() are released and removed sysfs_dirents are
+- *    cleaned up.  Timestamps on the parent inode are updated.
+- *
+- *    LOCKING:
+- *    All mutexes acquired by sysfs_addrm_start() are released.
+- *
+- *    RETURNS:
+- *    Number of added/removed sysfs_dirents since sysfs_addrm_start().
+- */
+-int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
++static struct sysfs_dirent *
++__sysfs_make_dirent(struct dentry *dentry, void *element, mode_t mode, int type)
+ {
+-      /* release resources acquired by sysfs_addrm_start() */
+-      mutex_unlock(&sysfs_mutex);
+-      if (acxt->parent_inode) {
+-              struct inode *inode = acxt->parent_inode;
+-
+-              /* if added/removed, update timestamps on the parent */
+-              if (acxt->cnt)
+-                      inode->i_ctime = inode->i_mtime = CURRENT_TIME;
++      struct sysfs_dirent * sd;
+-              mutex_unlock(&inode->i_mutex);
+-              iput(inode);
+-      }
++      sd = __sysfs_new_dirent(element);
++      if (!sd)
++              goto out;
+-      /* kill removed sysfs_dirents */
+-      while (acxt->removed) {
+-              struct sysfs_dirent *sd = acxt->removed;
+-
+-              acxt->removed = sd->s_sibling;
+-              sd->s_sibling = NULL;
+-
+-              sysfs_prune_shadow_sd(sd->s_parent);
+-              sysfs_drop_dentry(sd);
+-              sysfs_deactivate(sd);
+-              sysfs_put(sd);
++      sd->s_mode = mode;
++      sd->s_type = type;
++      sd->s_dentry = dentry;
++      if (dentry) {
++              dentry->d_fsdata = sysfs_get(sd);
++              dentry->d_op = &sysfs_dentry_ops;
+       }
+-      return acxt->cnt;
+-}
+-
+-/**
+- *    sysfs_find_dirent - find sysfs_dirent with the given name
+- *    @parent_sd: sysfs_dirent to search under
+- *    @name: name to look for
+- *
+- *    Look for sysfs_dirent with name @name under @parent_sd.
+- *
+- *    LOCKING:
+- *    mutex_lock(sysfs_mutex)
+- *
+- *    RETURNS:
+- *    Pointer to sysfs_dirent if found, NULL if not.
+- */
+-struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
+-                                     const unsigned char *name)
+-{
+-      struct sysfs_dirent *sd;
+-
+-      for (sd = parent_sd->s_children; sd; sd = sd->s_sibling)
+-              if (sysfs_type(sd) && !strcmp(sd->s_name, name))
++out:
+                       return sd;
+-      return NULL;
+ }
+-/**
+- *    sysfs_get_dirent - find and get sysfs_dirent with the given name
+- *    @parent_sd: sysfs_dirent to search under
+- *    @name: name to look for
+- *
+- *    Look for sysfs_dirent with name @name under @parent_sd and get
+- *    it if found.
+- *
+- *    LOCKING:
+- *    Kernel thread context (may sleep).  Grabs sysfs_mutex.
+- *
+- *    RETURNS:
+- *    Pointer to sysfs_dirent if found, NULL if not.
+- */
+-struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+-                                    const unsigned char *name)
++int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
++                      void * element, umode_t mode, int type)
+ {
+       struct sysfs_dirent *sd;
+-      mutex_lock(&sysfs_mutex);
+-      sd = sysfs_find_dirent(parent_sd, name);
+-      sysfs_get(sd);
+-      mutex_unlock(&sysfs_mutex);
++      sd = __sysfs_make_dirent(dentry, element, mode, type);
++      __sysfs_list_dirent(parent_sd, sd);
+-      return sd;
++      return sd ? 0 : -ENOMEM;
+ }
+-static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
+-                    const char *name, struct sysfs_dirent **p_sd)
++static int init_dir(struct inode * inode)
+ {
+-      umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
+-      struct sysfs_addrm_cxt acxt;
+-      struct sysfs_dirent *sd;
+-      int err;
++      inode->i_op = &sysfs_dir_inode_operations;
++      inode->i_fop = &sysfs_dir_operations;
+-      /* allocate */
+-      sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
+-      if (!sd)
+-              return -ENOMEM;
+-      sd->s_elem.dir.kobj = kobj;
++      /* directory inodes start off with i_nlink == 2 (for "." entry) */
++      inc_nlink(inode);
 +      return 0;
 +}
-+
-+static u64 container_read_notify_on_release(struct container *cont,
-+                                          struct cftype *cft)
-+{
-+      return notify_on_release(cont);
-+}
-+
-+static u64 container_read_releasable(struct container *cont, struct cftype *cft)
+-      /* link in */
+-      sysfs_addrm_start(&acxt, parent_sd);
+-      err = -ENOENT;
+-      if (!sysfs_resolve_for_create(kobj, &acxt.parent_sd))
+-              goto addrm_finish;
+-
+-      err = -EEXIST;
+-      if (!sysfs_find_dirent(acxt.parent_sd, name)) {
+-              sysfs_add_one(&acxt, sd);
+-              sysfs_link_sibling(sd);
+-              err = 0;
+-                      }
+-addrm_finish:
+-      if (sysfs_addrm_finish(&acxt)) {
+-              *p_sd = sd;
++static int init_file(struct inode * inode)
 +{
-+      return test_bit(CONT_RELEASABLE, &cont->flags);
++      inode->i_size = PAGE_SIZE;
++      inode->i_fop = &sysfs_file_operations;
+               return 0;
+-              }
 +}
-+
-+/*
-+ * for the common functions, 'private' gives the type of file
-+ */
-+static struct cftype files[] = {
-+      {
-+              .name = "tasks",
-+              .open = container_tasks_open,
-+              .read = container_tasks_read,
-+              .write = container_common_file_write,
-+              .release = container_tasks_release,
-+              .private = FILE_TASKLIST,
-+      },
-+
-+      {
-+              .name = "notify_on_release",
-+              .read_uint = container_read_notify_on_release,
-+              .write = container_common_file_write,
-+              .private = FILE_NOTIFY_ON_RELEASE,
-+      },
-+
-+      {
-+              .name = "releasable",
-+              .read_uint = container_read_releasable,
-+              .private = FILE_RELEASABLE,
-+      }
-+};
-+
-+static struct cftype cft_release_agent = {
-+      .name = "release_agent",
-+      .read = container_common_file_read,
-+      .write = container_common_file_write,
-+      .private = FILE_RELEASE_AGENT,
-+};
-+
-+static int container_populate_dir(struct container *cont)
++static int init_symlink(struct inode * inode)
 +{
-+      int err;
-+      struct container_subsys *ss;
-+
-+      /* First clear out any existing files */
-+      container_clear_directory(cont->dentry);
-+
-+      err = container_add_files(cont, files, ARRAY_SIZE(files));
-+      if (err < 0)
-+              return err;
-+
-+      if (cont == cont->top_container) {
-+              if ((err = container_add_file(cont, &cft_release_agent)) < 0)
-+                      return err;
-+      }
-+
-+      for_each_subsys(cont->root, ss) {
-+              if (ss->populate && (err = ss->populate(ss, cont)) < 0)
-+                      return err;
-+      }
-+
++      inode->i_op = &sysfs_symlink_inode_operations;
 +      return 0;
 +}
 +
-+static void init_container_css(struct container_subsys *ss,
-+                             struct container *cont)
-+{
-+      struct container_subsys_state *css = cont->subsys[ss->subsys_id];
-+      css->container = cont;
-+      atomic_set(&css->refcnt, 0);
-+}
-+
-+/*
-+ *    container_create - create a container
-+ *    parent: container that will be parent of the new container.
-+ *    name:           name of the new container. Will be strcpy'ed.
-+ *    mode:           mode to set on new inode
-+ *
-+ *    Must be called with the mutex on the parent inode held
-+ */
-+
-+static long container_create(struct container *parent, struct dentry *dentry,
-+                           int mode)
++static int create_dir(struct kobject * k, struct dentry * p,
++                    const char * n, struct dentry ** d)
 +{
-+      struct container *cont;
-+      struct containerfs_root *root = parent->root;
-+      int err = 0;
-+      struct container_subsys *ss;
-+      struct super_block *sb = root->sb;
-+
-+      cont = kzalloc(sizeof(*cont), GFP_KERNEL);
-+      if (!cont)
-+              return -ENOMEM;
-+
-+      /* Grab a reference on the superblock so the hierarchy doesn't
-+       * get deleted on unmount if there are child containers.  This
-+       * can be done outside container_mutex, since the sb can't
-+       * disappear while someone has an open control file on the
-+       * fs */
-+      atomic_inc(&sb->s_active);
-+
-+      mutex_lock(&container_mutex);
-+
-+      cont->flags = 0;
-+      INIT_LIST_HEAD(&cont->sibling);
-+      INIT_LIST_HEAD(&cont->children);
-+      INIT_LIST_HEAD(&cont->css_groups);
-+      INIT_LIST_HEAD(&cont->release_list);
++      int error;
++      umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
++
++      mutex_lock(&p->d_inode->i_mutex);
++      *d = lookup_one_len(n, p, strlen(n));
++      if (!IS_ERR(*d)) {
++              if (sysfs_dirent_exist(p->d_fsdata, n))
++                      error = -EEXIST;
++              else
++                      error = sysfs_make_dirent(p->d_fsdata, *d, k, mode,
++                                                              SYSFS_DIR);
++              if (!error) {
++                      error = sysfs_create(*d, mode, init_dir);
++                      if (!error) {
++                              inc_nlink(p->d_inode);
++                              (*d)->d_op = &sysfs_dentry_ops;
++                              d_rehash(*d);
++                      }
++              }
++              if (error && (error != -EEXIST)) {
++                      struct sysfs_dirent *sd = (*d)->d_fsdata;
++                      if (sd) {
++                              list_del_init(&sd->s_sibling);
+                               sysfs_put(sd);
+-      return err;
++                      }
++                      d_drop(*d);
++              }
++              dput(*d);
++      } else
++              error = PTR_ERR(*d);
++      mutex_unlock(&p->d_inode->i_mutex);
++      return error;
+ }
+-int sysfs_create_subdir(struct kobject *kobj, const char *name,
+-                      struct sysfs_dirent **p_sd)
 +
-+      cont->parent = parent;
-+      cont->root = parent->root;
-+      cont->top_container = parent->top_container;
++int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d)
+ {
+-      return create_dir(kobj, kobj->sd, name, p_sd);
++      return create_dir(k,k->dentry,n,d);
+ }
+ /**
+  *    sysfs_create_dir - create a directory for an object.
+  *    @kobj:          object we're creating directory for. 
++ *    @shadow_parent: parent parent object.
+  */
+-int sysfs_create_dir(struct kobject * kobj)
 +
-+      for_each_subsys(root, ss) {
-+              err = ss->create(ss, cont);
-+              if (err)
-+                      goto err_destroy;
-+              init_container_css(ss, cont);
++int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent)
+ {
+-      struct sysfs_dirent *parent_sd, *sd;
++      struct dentry * dentry = NULL;
++      struct dentry * parent;
+       int error = 0;
+       BUG_ON(!kobj);
+-      if (kobj->parent)
+-              parent_sd = kobj->parent->sd;
++      if (shadow_parent)
++              parent = shadow_parent;
++      else if (kobj->parent)
++              parent = kobj->parent->dentry;
+       else if (sysfs_mount && sysfs_mount->mnt_sb)
+-              parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
++              parent = sysfs_mount->mnt_sb->s_root;
+       else
+               return -EFAULT;
+-      error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd);
++      error = create_dir(kobj,parent,kobject_name(kobj),&dentry);
+       if (!error)
+-              kobj->sd = sd;
++              kobj->dentry = dentry;
+       return error;
+ }
+-static int sysfs_count_nlink(struct sysfs_dirent *sd)
+-{
+-      struct sysfs_dirent *child;
+-      int nr = 0;
+-
+-      for (child = sd->s_children; child; child = child->s_sibling)
+-              if (sysfs_type(child) == SYSFS_DIR)
+-                      nr++;
+-      return nr + 2;
+-}
+-
+-static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
+-                              struct nameidata *nd)
++/* attaches attribute's sysfs_dirent to the dentry corresponding to the
++ * attribute file
++ */
++static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
+ {
+-      struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
+-      struct sysfs_dirent * sd;
+-      struct bin_attribute *bin_attr;
+-      struct inode *inode;
+-      int found = 0;
++      struct attribute * attr = NULL;
++      struct bin_attribute * bin_attr = NULL;
++      int (* init) (struct inode *) = NULL;
++      int error = 0;
+-      for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) {
+-              if (sysfs_type(sd) &&
+-                  !strcmp(sd->s_name, dentry->d_name.name)) {
+-                      found = 1;
+-                      break;
+-              }
++        if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) {
++                bin_attr = sd->s_element;
++                attr = &bin_attr->attr;
++        } else {
++                attr = sd->s_element;
++                init = init_file;
+       }
+-      /* no such entry */
+-      if (!found)
+-              return NULL;
+-
+-      /* attach dentry and inode */
+-      inode = sysfs_get_inode(sd);
+-      if (!inode)
+-              return ERR_PTR(-ENOMEM);
+-
+-      mutex_lock(&sysfs_mutex);
+-
+-      if (inode->i_state & I_NEW) {
+-              /* initialize inode according to type */
+-              switch (sysfs_type(sd)) {
+-              case SYSFS_DIR:
+-                      inode->i_op = &sysfs_dir_inode_operations;
+-                      inode->i_fop = &sysfs_dir_operations;
+-                      inode->i_nlink = sysfs_count_nlink(sd);
+-                      break;
+-              case SYSFS_KOBJ_ATTR:
+-                      inode->i_size = PAGE_SIZE;
+-                      inode->i_fop = &sysfs_file_operations;
+-                      break;
+-              case SYSFS_KOBJ_BIN_ATTR:
+-                      bin_attr = sd->s_elem.bin_attr.bin_attr;
+-                      inode->i_size = bin_attr->size;
+-                      inode->i_fop = &bin_fops;
+-                      break;
+-              case SYSFS_KOBJ_LINK:
+-                      inode->i_op = &sysfs_symlink_inode_operations;
+-                      break;
+-              default:
+-                      BUG();
+-              }
++      dentry->d_fsdata = sysfs_get(sd);
++      /* protect sd->s_dentry against sysfs_d_iput */
++      spin_lock(&sysfs_lock);
++      sd->s_dentry = dentry;
++      spin_unlock(&sysfs_lock);
++      error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init);
++      if (error) {
++              sysfs_put(sd);
++              return error;
+       }
+-      sysfs_instantiate(dentry, inode);
+-      sysfs_attach_dentry(sd, dentry);
+-
+-      mutex_unlock(&sysfs_mutex);
++        if (bin_attr) {
++              dentry->d_inode->i_size = bin_attr->size;
++              dentry->d_inode->i_fop = &bin_fops;
 +      }
-+
-+      list_add(&cont->sibling, &cont->parent->children);
-+      root->number_of_containers++;
-+
-+      err = container_create_dir(cont, dentry, mode);
-+      if (err < 0)
-+              goto err_remove;
-+
-+      /* The container directory was pre-locked for us */
-+      BUG_ON(!mutex_is_locked(&cont->dentry->d_inode->i_mutex));
-+
-+      err = container_populate_dir(cont);
-+      /* If err < 0, we have a half-filled directory - oh well ;) */
-+
-+      mutex_unlock(&container_mutex);
-+      mutex_unlock(&cont->dentry->d_inode->i_mutex);
-+
++      dentry->d_op = &sysfs_dentry_ops;
++      d_rehash(dentry);
+-      return NULL;
 +      return 0;
+ }
+-static void *sysfs_shadow_follow_link(struct dentry *dentry, struct nameidata *nd)
++static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
+ {
+-      struct sysfs_dirent *sd;
+-      struct dentry *dest;
++      int err = 0;
 +
-+ err_remove:
-+
-+      list_del(&cont->sibling);
-+      root->number_of_containers--;
-+
-+ err_destroy:
-+
-+      for_each_subsys(root, ss) {
-+              if (cont->subsys[ss->subsys_id])
-+                      ss->destroy(ss, cont);
-+      }
-+
-+      mutex_unlock(&container_mutex);
-+
-+      /* Release the reference count that we took on the superblock */
-+      deactivate_super(sb);
-+
-+      kfree(cont);
++      dentry->d_fsdata = sysfs_get(sd);
++      /* protect sd->s_dentry against sysfs_d_iput */
++      spin_lock(&sysfs_lock);
++      sd->s_dentry = dentry;
++      spin_unlock(&sysfs_lock);
++      err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
++      if (!err) {
++              dentry->d_op = &sysfs_dentry_ops;
++              d_rehash(dentry);
++      } else
++              sysfs_put(sd);
+-      sd = dentry->d_fsdata;
+-      dest = NULL;
+-      if (sd->s_flags & SYSFS_FLAG_SHADOWED) {
+-              const struct shadow_dir_operations *shadow_ops;
+-              const void *tag;
 +      return err;
 +}
-+
-+static int container_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-+{
-+      struct container *c_parent = dentry->d_parent->d_fsdata;
-+
-+      /* the vfs holds inode->i_mutex already */
-+      return container_create(c_parent, dentry, mode | S_IFDIR);
-+}
-+
-+static inline int container_has_css_refs(struct container *cont)
+-              mutex_lock(&sysfs_mutex);
++static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
++                              struct nameidata *nd)
 +{
-+      /* Check the reference count on each subsystem. Since we
-+       * already established that there are no tasks in the
-+       * container, if the css refcount is also 0, then there should
-+       * be no outstanding references, so the subsystem is safe to
-+       * destroy */
-+      struct container_subsys *ss;
-+      for_each_subsys(cont->root, ss) {
-+              struct container_subsys_state *css;
-+              css = cont->subsys[ss->subsys_id];
-+              if (atomic_read(&css->refcnt)) {
-+                      return 1;
++      struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
++      struct sysfs_dirent * sd;
++      int err = 0;
+-              shadow_ops = dentry->d_inode->i_private;
+-              tag = shadow_ops->current_tag();
++      list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
++              if (sd->s_type & SYSFS_NOT_PINNED) {
++                      const unsigned char * name = sysfs_get_name(sd);
+-              sd = find_shadow_sd(sd, tag);
+-              if (sd)
+-                      dest = sd->s_dentry;
+-              dget(dest);
++                      if (strcmp(name, dentry->d_name.name))
++                              continue;
+-              mutex_unlock(&sysfs_mutex);
++                      if (sd->s_type & SYSFS_KOBJ_LINK)
++                              err = sysfs_attach_link(sd, dentry);
++                      else
++                              err = sysfs_attach_attr(sd, dentry);
++                      break;
 +              }
+       }
+-      if (!dest)
+-              dest = dget(dentry);
+-      dput(nd->dentry);
+-      nd->dentry = dest;
+-      return NULL;
++      return ERR_PTR(err);
+ }
+-
+ const struct inode_operations sysfs_dir_inode_operations = {
+       .lookup         = sysfs_lookup,
+       .setattr        = sysfs_setattr,
+-      .follow_link    = sysfs_shadow_follow_link,
+ };
+-static void __remove_dir(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
++static void remove_dir(struct dentry * d)
+ {
+-      sysfs_unlink_sibling(sd);
+-      sysfs_remove_one(acxt, sd);
+-}
++      struct dentry * parent = dget(d->d_parent);
++      struct sysfs_dirent * sd;
+-static void remove_dir(struct sysfs_dirent *sd)
+-{
+-      struct sysfs_addrm_cxt acxt;
++      mutex_lock(&parent->d_inode->i_mutex);
++      d_delete(d);
++      sd = d->d_fsdata;
++      list_del_init(&sd->s_sibling);
++      sysfs_put(sd);
++      if (d->d_inode)
++              simple_rmdir(parent->d_inode,d);
+-      sysfs_addrm_start(&acxt, sd->s_parent);
+-      __remove_dir(&acxt, sd);
+-      sysfs_addrm_finish(&acxt);
+-}
++      pr_debug(" o %s removing done (%d)\n",d->d_name.name,
++               atomic_read(&d->d_count));
+-void sysfs_remove_subdir(struct sysfs_dirent *sd)
+-{
+-      remove_dir(sd);
++      mutex_unlock(&parent->d_inode->i_mutex);
++      dput(parent);
+ }
+-static void sysfs_empty_dir(struct sysfs_addrm_cxt *acxt,
+-                          struct sysfs_dirent *dir_sd)
++void sysfs_remove_subdir(struct dentry * d)
+ {
+-      struct sysfs_dirent **pos;
+-
+-      pos = &dir_sd->s_children;
+-      while (*pos) {
+-              struct sysfs_dirent *sd = *pos;
+-
+-              if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) {
+-                      *pos = sd->s_sibling;
+-                      sd->s_sibling = NULL;
+-                      sysfs_remove_one(acxt, sd);
+-              } else
+-                      pos = &(*pos)->s_sibling;
+-      }
++      remove_dir(d);
+ }
+-static void sysfs_remove_shadows(struct sysfs_addrm_cxt * acxt,
+-                                      struct sysfs_dirent *dir_sd)
+-{
+-      struct sysfs_dirent **pos;
+-
+-      pos = &dir_sd->s_children;
+-      while (*pos) {
+-              struct sysfs_dirent *sd = *pos;
+-
+-              sysfs_empty_dir(acxt, sd);
+-              __remove_dir(acxt, sd);
+-      }
+-}
+-static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
++static void __sysfs_remove_dir(struct dentry *dentry)
+ {
+-      struct sysfs_addrm_cxt acxt;
++      struct sysfs_dirent * parent_sd;
++      struct sysfs_dirent * sd, * tmp;
+-      if (!dir_sd)
++      dget(dentry);
++      if (!dentry)
+               return;
+-      pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
+-      sysfs_addrm_start(&acxt, dir_sd);
+-      if (sysfs_type(dir_sd) == SYSFS_DIR)
+-              sysfs_empty_dir(&acxt, dir_sd);
+-      else
+-              sysfs_remove_shadows(&acxt, dir_sd);
+-      sysfs_addrm_finish(&acxt);
++      pr_debug("sysfs %s: removing dir\n",dentry->d_name.name);
++      mutex_lock(&dentry->d_inode->i_mutex);
++      parent_sd = dentry->d_fsdata;
++      list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) {
++              if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED))
++                      continue;
++              list_del_init(&sd->s_sibling);
++              sysfs_drop_dentry(sd, dentry);
++              sysfs_put(sd);
 +      }
-+      return 0;
-+}
-+
-+static int container_rmdir(struct inode *unused_dir, struct dentry *dentry)
-+{
-+      struct container *cont = dentry->d_fsdata;
-+      struct dentry *d;
-+      struct container *parent;
-+      struct container_subsys *ss;
-+      struct super_block *sb;
-+      struct containerfs_root *root;
-+
-+      /* the vfs holds both inode->i_mutex already */
-+
-+      mutex_lock(&container_mutex);
-+      if (atomic_read(&cont->count) != 0) {
-+              mutex_unlock(&container_mutex);
-+              return -EBUSY;
-+      }
-+      if (!list_empty(&cont->children)) {
-+              mutex_unlock(&container_mutex);
-+              return -EBUSY;
-+      }
-+
-+      parent = cont->parent;
-+      root = cont->root;
-+      sb = root->sb;
-+
-+      if (container_has_css_refs(cont)) {
-+              mutex_unlock(&container_mutex);
-+              return -EBUSY;
-+      }
-+
-+      for_each_subsys(root, ss) {
-+              if (cont->subsys[ss->subsys_id])
-+                      ss->destroy(ss, cont);
++      mutex_unlock(&dentry->d_inode->i_mutex);
+-      remove_dir(dir_sd);
++      remove_dir(dentry);
++      /**
++       * Drop reference from dget() on entrance.
++       */
++      dput(dentry);
+ }
+ /**
+@@ -1064,154 +393,102 @@
+ void sysfs_remove_dir(struct kobject * kobj)
+ {
+-      struct sysfs_dirent *sd = kobj->sd;
+-
+-      spin_lock(&sysfs_assoc_lock);
+-      kobj->sd = NULL;
+-      spin_unlock(&sysfs_assoc_lock);
+-
+-      __sysfs_remove_dir(sd);
++      __sysfs_remove_dir(kobj->dentry);
++      kobj->dentry = NULL;
+ }
+-int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
++int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
++                   const char *new_name)
+ {
+-      struct dentry *old_dentry, *new_dentry, *parent;
+-      struct sysfs_addrm_cxt acxt;
+-      struct sysfs_dirent *sd;
+-      const char *dup_name;
+-      int error;
+-
+-      dup_name = NULL;
+-      new_dentry = NULL;
++      int error = 0;
++      struct dentry * new_dentry;
+-      sd = kobj->sd;
+-      sysfs_addrm_start(&acxt, sd->s_parent);
+-      error = -ENOENT;
+-      if (!sysfs_resolve_for_create(kobj, &acxt.parent_sd))
+-              goto addrm_finish;
++      if (!new_parent)
++              return -EFAULT;
+-      error = -EEXIST;
+-      if (sysfs_find_dirent(acxt.parent_sd, new_name))
+-              goto addrm_finish;
++      down_write(&sysfs_rename_sem);
++      mutex_lock(&new_parent->d_inode->i_mutex);
++      new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name));
++      if (!IS_ERR(new_dentry)) {
++              /* By allowing two different directories with the
++               * same d_parent we allow this routine to move
++               * between different shadows of the same directory
++               */
++              if (kobj->dentry->d_parent->d_inode != new_parent->d_inode)
++                      return -EINVAL;
++              else if (new_dentry->d_parent->d_inode != new_parent->d_inode)
+                       error = -EINVAL;
+-      if ((sd->s_parent == acxt.parent_sd) &&
+-          (strcmp(new_name, sd->s_name) == 0))
+-              goto addrm_finish;
+-
+-      old_dentry = sd->s_dentry;
+-      parent = acxt.parent_sd->s_dentry;
+-      if (old_dentry) {
+-              old_dentry = sd->s_dentry;
+-              parent = acxt.parent_sd->s_dentry;
+-              new_dentry = lookup_one_len(new_name, parent, strlen(new_name));
+-      if (IS_ERR(new_dentry)) {
+-              error = PTR_ERR(new_dentry);
+-                      goto addrm_finish;
+-      }
+-
++              else if (new_dentry == kobj->dentry)
+                       error = -EINVAL;
+-              if (old_dentry == new_dentry)
+-                      goto addrm_finish;
+-      }
+-
+-      /* rename kobject and sysfs_dirent */
+-      error = -ENOMEM;
+-      new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
+-      if (!new_name)
+-              goto addrm_finish;
+-
++              else if (!new_dentry->d_inode) {
+                       error = kobject_set_name(kobj, "%s", new_name);
+-      if (error)
+-              goto addrm_finish;
++                      if (!error) {
++                              struct sysfs_dirent *sd, *parent_sd;
+-      dup_name = sd->s_name;
+-      sd->s_name = new_name;
++                              d_add(new_dentry, NULL);
++                              d_move(kobj->dentry, new_dentry);
+-      /* move under the new parent */
+-      sysfs_unlink_sibling(sd);
+-      sysfs_get(acxt.parent_sd);
+-      sysfs_put(sd->s_parent);
+-      sd->s_parent = acxt.parent_sd;
+-      sysfs_link_sibling(sd);
++                              sd = kobj->dentry->d_fsdata;
++                              parent_sd = new_parent->d_fsdata;
+-      if (new_dentry) {
+-              d_add(new_dentry, NULL);
+-              d_move(old_dentry, new_dentry);
++                              list_del_init(&sd->s_sibling);
++                              list_add(&sd->s_sibling, &parent_sd->s_children);
+       }
+-      error = 0;
+-addrm_finish:
+-      sysfs_addrm_finish(&acxt);
+-
+-      kfree(dup_name);
++                      else
++                              d_drop(new_dentry);
++              } else
++                      error = -EEXIST;
+       dput(new_dentry);
 +      }
++      mutex_unlock(&new_parent->d_inode->i_mutex);
++      up_write(&sysfs_rename_sem);
 +
-+      set_bit(CONT_REMOVED, &cont->flags);
-+      /* delete my sibling from parent->children */
-+      list_del(&cont->sibling);
-+      spin_lock(&cont->dentry->d_lock);
-+      d = dget(cont->dentry);
-+      cont->dentry = NULL;
-+      spin_unlock(&d->d_lock);
-+
-+      container_d_remove_dir(d);
-+      dput(d);
-+      root->number_of_containers--;
-+
-+      if (!list_empty(&cont->release_list))
-+              list_del(&cont->release_list);
-+      set_bit(CONT_RELEASABLE, &parent->flags);
-+      check_for_release(parent);
-+
-+      mutex_unlock(&container_mutex);
-+      /* Drop the active superblock reference that we took when we
-+       * created the container */
-+      deactivate_super(sb);
-+      return 0;
-+}
-+
-+static void container_init_subsys(struct container_subsys *ss)
-+{
-+      int retval;
-+      struct container_subsys_state *css;
-+      struct list_head *l;
-+      printk(KERN_ERR "Initializing container subsys %s\n", ss->name);
-+
-+      /* Create the top container state for this subsystem */
-+      ss->root = &rootnode;
-+      retval = ss->create(ss, dummytop);
-+      BUG_ON(retval);
-+      BUG_ON(!dummytop->subsys[ss->subsys_id]);
-+      init_container_css(ss, dummytop);
-+      css = dummytop->subsys[ss->subsys_id];
-+
-+      /* Update all container groups to contain a subsys
-+       * pointer to this state - since the subsystem is
-+       * newly registered, all tasks and hence all container
-+       * groups are in the subsystem's top container. */
-+      write_lock(&css_group_lock);
-+      l = &init_css_group.list;
-+      do {
-+              struct css_group *cg =
-+                      list_entry(l, struct css_group, list);
-+              cg->subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id];
-+              l = l->next;
-+      } while (l != &init_css_group.list);
-+      write_unlock(&css_group_lock);
-+
-+      /* If this subsystem requested that it be notified with fork
-+       * events, we should send it one now for every process in the
-+       * system */
-+      if (ss->fork) {
-+              struct task_struct *g, *p;
-+
-+              read_lock(&tasklist_lock);
-+              do_each_thread(g, p) {
-+                      ss->fork(ss, p);
-+              } while_each_thread(g, p);
-+              read_unlock(&tasklist_lock);
-+      }
-+
-+      need_forkexit_callback |= ss->fork || ss->exit;
+       return error;
+ }
+-int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
++int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
+ {
+-      struct sysfs_dirent *sd = kobj->sd;
+-      struct sysfs_dirent *new_parent_sd;
+-      struct dentry *old_parent, *new_parent = NULL;
+-      struct dentry *old_dentry = NULL, *new_dentry = NULL;
++      struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry;
++      struct sysfs_dirent *new_parent_sd, *sd;
+       int error;
+-      BUG_ON(!sd->s_parent);
+-      new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root;
+-
+-      /* get dentries */
+-      old_dentry = sysfs_get_dentry(sd);
+-      if (IS_ERR(old_dentry)) {
+-              error = PTR_ERR(old_dentry);
+-              goto out_dput;
+-      }
+-      old_parent = sd->s_parent->s_dentry;
+-
+-      new_parent = sysfs_get_dentry(new_parent_sd);
+-      if (IS_ERR(new_parent)) {
+-              error = PTR_ERR(new_parent);
+-              goto out_dput;
+-      }
++      old_parent_dentry = kobj->parent ?
++              kobj->parent->dentry : sysfs_mount->mnt_sb->s_root;
++      new_parent_dentry = new_parent ?
++              new_parent->dentry : sysfs_mount->mnt_sb->s_root;
+-      if (old_parent->d_inode == new_parent->d_inode) {
+-              error = 0;
+-              goto out_dput;  /* nothing to move */
+-      }
++      if (old_parent_dentry->d_inode == new_parent_dentry->d_inode)
++              return 0;       /* nothing to move */
+ again:
+-      mutex_lock(&old_parent->d_inode->i_mutex);
+-      if (!mutex_trylock(&new_parent->d_inode->i_mutex)) {
+-              mutex_unlock(&old_parent->d_inode->i_mutex);
++      mutex_lock(&old_parent_dentry->d_inode->i_mutex);
++      if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) {
++              mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
+               goto again;
+       }
+-      new_dentry = lookup_one_len(kobj->name, new_parent, strlen(kobj->name));
++      new_parent_sd = new_parent_dentry->d_fsdata;
++      sd = kobj->dentry->d_fsdata;
 +
-+      ss->active = 1;
-+}
++      new_dentry = lookup_one_len(kobj->name, new_parent_dentry,
++                                  strlen(kobj->name));
+       if (IS_ERR(new_dentry)) {
+               error = PTR_ERR(new_dentry);
+-              goto out_unlock;
++              goto out;
+       } else
+               error = 0;
+       d_add(new_dentry, NULL);
+-      d_move(sd->s_dentry, new_dentry);
++      d_move(kobj->dentry, new_dentry);
+       dput(new_dentry);
+       /* Remove from old parent's list and insert into new parent's list. */
+-      mutex_lock(&sysfs_mutex);
++      list_del_init(&sd->s_sibling);
++      list_add(&sd->s_sibling, &new_parent_sd->s_children);
+-      sysfs_unlink_sibling(sd);
+-      sysfs_get(new_parent_sd);
+-      sysfs_put(sd->s_parent);
+-      sd->s_parent = new_parent_sd;
+-      sysfs_link_sibling(sd);
+-
+-      mutex_unlock(&sysfs_mutex);
++out:
++      mutex_unlock(&new_parent_dentry->d_inode->i_mutex);
++      mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
+- out_unlock:
+-      mutex_unlock(&new_parent->d_inode->i_mutex);
+-      mutex_unlock(&old_parent->d_inode->i_mutex);
+- out_dput:
+-      dput(new_parent);
+-      dput(old_dentry);
+-      dput(new_dentry);
+       return error;
+ }
+@@ -1219,27 +496,23 @@
+ {
+       struct dentry * dentry = file->f_path.dentry;
+       struct sysfs_dirent * parent_sd = dentry->d_fsdata;
+-      struct sysfs_dirent * sd;
+-      sd = sysfs_new_dirent("_DIR_", 0, 0);
+-      if (sd) {
+-              mutex_lock(&sysfs_mutex);
+-              sd->s_parent = sysfs_get(parent_sd);
+-              sysfs_link_sibling(sd);
+-              mutex_unlock(&sysfs_mutex);
+-      }
++      mutex_lock(&dentry->d_inode->i_mutex);
++      file->private_data = sysfs_new_dirent(parent_sd, NULL);
++      mutex_unlock(&dentry->d_inode->i_mutex);
 +
++      return file->private_data ? 0 : -ENOMEM;
+-      file->private_data = sd;
+-      return sd ? 0 : -ENOMEM;
+ }
+ static int sysfs_dir_close(struct inode *inode, struct file *file)
+ {
++      struct dentry * dentry = file->f_path.dentry;
+       struct sysfs_dirent * cursor = file->private_data;
+-      mutex_lock(&sysfs_mutex);
+-      sysfs_unlink_sibling(cursor);
+-      mutex_unlock(&sysfs_mutex);
++      mutex_lock(&dentry->d_inode->i_mutex);
++      list_del_init(&cursor->s_sibling);
++      mutex_unlock(&dentry->d_inode->i_mutex);
+       release_sysfs_dirent(cursor);
+@@ -1257,7 +530,7 @@
+       struct dentry *dentry = filp->f_path.dentry;
+       struct sysfs_dirent * parent_sd = dentry->d_fsdata;
+       struct sysfs_dirent *cursor = filp->private_data;
+-      struct sysfs_dirent **pos;
++      struct list_head *p, *q = &cursor->s_sibling;
+       ino_t ino;
+       int i = filp->f_pos;
+@@ -1270,55 +543,38 @@
+                       i++;
+                       /* fallthrough */
+               case 1:
+-                      if (parent_sd->s_parent)
+-                              ino = parent_sd->s_parent->s_ino;
+-                      else
+-                              ino = parent_sd->s_ino;
++                      ino = parent_ino(dentry);
+                       if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
+                               break;
+                       filp->f_pos++;
+                       i++;
+                       /* fallthrough */
+               default:
+-                      /* If I am the shadow master return nothing. */
+-                      if (parent_sd->s_flags & SYSFS_FLAG_SHADOWED)
+-                              return 0;
+-
+-                      mutex_lock(&sysfs_mutex);
+-                      pos = &parent_sd->s_children;
+-                      while (*pos != cursor)
+-                              pos = &(*pos)->s_sibling;
+-
+-                      /* unlink cursor */
+-                      *pos = cursor->s_sibling;
+-
+                       if (filp->f_pos == 2)
+-                              pos = &parent_sd->s_children;
++                              list_move(q, &parent_sd->s_children);
+-                      for ( ; *pos; pos = &(*pos)->s_sibling) {
+-                              struct sysfs_dirent *next = *pos;
++                      for (p=q->next; p!= &parent_sd->s_children; p=p->next) {
++                              struct sysfs_dirent *next;
+                               const char * name;
+                               int len;
+-                              if (!sysfs_type(next))
++                              next = list_entry(p, struct sysfs_dirent,
++                                                 s_sibling);
++                              if (!next->s_element)
+                                       continue;
+-                              name = next->s_name;
++                              name = sysfs_get_name(next);
+                               len = strlen(name);
+                               ino = next->s_ino;
+                               if (filldir(dirent, name, len, filp->f_pos, ino,
+                                                dt_type(next)) < 0)
+-                                      break;
++                                      return 0;
++                              list_move(q, p);
++                              p = q;
+                               filp->f_pos++;
+                       }
+-
+-                      /* put cursor back in */
+-                      cursor->s_sibling = *pos;
+-                      *pos = cursor;
+-
+-                      mutex_unlock(&sysfs_mutex);
+       }
+       return 0;
+ }
+@@ -1327,6 +583,7 @@
+ {
+       struct dentry * dentry = file->f_path.dentry;
++      mutex_lock(&dentry->d_inode->i_mutex);
+       switch (origin) {
+               case 1:
+                       offset += file->f_pos;
+@@ -1334,224 +591,127 @@
+                       if (offset >= 0)
+                               break;
+               default:
++                      mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+                       return -EINVAL;
+       }
+       if (offset != file->f_pos) {
+-              mutex_lock(&sysfs_mutex);
+-
+               file->f_pos = offset;
+               if (file->f_pos >= 2) {
+                       struct sysfs_dirent *sd = dentry->d_fsdata;
+                       struct sysfs_dirent *cursor = file->private_data;
+-                      struct sysfs_dirent **pos;
++                      struct list_head *p;
+                       loff_t n = file->f_pos - 2;
+-                      sysfs_unlink_sibling(cursor);
+-
+-                      pos = &sd->s_children;
+-                      while (n && *pos) {
+-                              struct sysfs_dirent *next = *pos;
+-                              if (sysfs_type(next))
++                      list_del(&cursor->s_sibling);
++                      p = sd->s_children.next;
++                      while (n && p != &sd->s_children) {
++                              struct sysfs_dirent *next;
++                              next = list_entry(p, struct sysfs_dirent,
++                                                 s_sibling);
++                              if (next->s_element)
+                                       n--;
+-                              pos = &(*pos)->s_sibling;
++                              p = p->next;
+                       }
+-
+-                      cursor->s_sibling = *pos;
+-                      *pos = cursor;
++                      list_add_tail(&cursor->s_sibling, p);
+               }
+-
+-              mutex_unlock(&sysfs_mutex);
+       }
+-
++      mutex_unlock(&dentry->d_inode->i_mutex);
+       return offset;
+ }
+-const struct file_operations sysfs_dir_operations = {
+-      .open           = sysfs_dir_open,
+-      .release        = sysfs_dir_close,
+-      .llseek         = sysfs_dir_lseek,
+-      .read           = generic_read_dir,
+-      .readdir        = sysfs_readdir,
+-};
 +/**
-+ * container_init_early - initialize containers at system boot, and
-+ * initialize any subsystems that request early init.
++ *    sysfs_make_shadowed_dir - Setup so a directory can be shadowed
++ *    @kobj:  object we're creating shadow of.
 + */
-+int __init container_init_early(void)
-+{
-+      int i;
-+      kref_init(&init_css_group.ref);
-+      kref_get(&init_css_group.ref);
-+      INIT_LIST_HEAD(&init_css_group.list);
-+      INIT_LIST_HEAD(&init_css_group.cg_links);
-+      INIT_LIST_HEAD(&init_css_group.tasks);
-+      css_group_count = 1;
-+      init_container_root(&rootnode);
-+      init_task.containers = &init_css_group;
-+
-+      init_css_group_link.cg = &init_css_group;
-+      list_add(&init_css_group_link.cont_link_list,
-+               &rootnode.top_container.css_groups);
-+      list_add(&init_css_group_link.cg_link_list,
-+               &init_css_group.cg_links);
-+
-+      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
-+              struct container_subsys *ss = subsys[i];
-+
-+              BUG_ON(!ss->name);
-+              BUG_ON(strlen(ss->name) > MAX_CONTAINER_TYPE_NAMELEN);
-+              BUG_ON(!ss->create);
-+              BUG_ON(!ss->destroy);
-+              if (ss->subsys_id != i) {
-+                      printk(KERN_ERR "Subsys %s id == %d\n",
-+                             ss->name, ss->subsys_id);
-+                      BUG();
-+              }
-+
-+              if (ss->early_init)
-+                      container_init_subsys(ss);
-+      }
+-static void sysfs_prune_shadow_sd(struct sysfs_dirent *sd)
++int sysfs_make_shadowed_dir(struct kobject *kobj,
++      void * (*follow_link)(struct dentry *, struct nameidata *))
+ {
+-      struct sysfs_addrm_cxt acxt;
+-
+-      /* If a shadow directory goes empty remove it. */
+-      if (sysfs_type(sd) != SYSFS_SHADOW_DIR)
+-              return;
+-
+-      if (sd->s_children)
+-              return;
++      struct inode *inode;
++      struct inode_operations *i_op;
+-      sysfs_addrm_start(&acxt, sd->s_parent);
++      inode = kobj->dentry->d_inode;
++      if (inode->i_op != &sysfs_dir_inode_operations)
++              return -EINVAL;
+-      if (sd->s_flags & SYSFS_FLAG_REMOVED)
+-              goto addrm_finish;
++      i_op = kmalloc(sizeof(*i_op), GFP_KERNEL);
++      if (!i_op)
++              return -ENOMEM;
+-      if (sd->s_children)
+-              goto addrm_finish;
++      memcpy(i_op, &sysfs_dir_inode_operations, sizeof(*i_op));
++      i_op->follow_link = follow_link;
+-      __remove_dir(&acxt, sd);
+-addrm_finish:
+-      sysfs_addrm_finish(&acxt);
++      /* Locking of inode->i_op?
++       * Since setting i_op is a single word write and they
++       * are atomic we should be ok here.
++       */
++      inode->i_op = i_op;
 +      return 0;
-+}
-+
+ }
+-static struct sysfs_dirent *add_shadow_sd(struct sysfs_dirent *parent_sd, const void *tag)
 +/**
-+ * container_init - register container filesystem and /proc file, and
-+ * initialize any subsystems that didn't request early init.
++ *    sysfs_create_shadow_dir - create a shadow directory for an object.
++ *    @kobj:  object we're creating directory for.
++ *
++ *    sysfs_make_shadowed_dir must already have been called on this
++ *    directory.
 + */
-+int __init container_init(void)
-+{
-+      int err;
-+      int i;
-+      struct proc_dir_entry *entry;
-+
-+      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
-+              struct container_subsys *ss = subsys[i];
-+              if (!ss->early_init)
-+                      container_init_subsys(ss);
-+      }
-+
-+      err = register_filesystem(&container_fs_type);
-+      if (err < 0)
-+              goto out;
-+
-+      entry = create_proc_entry("containers", 0, NULL);
-+      if (entry)
-+              entry->proc_fops = &proc_containerstats_operations;
 +
-+out:
-+      return err;
-+}
++struct dentry *sysfs_create_shadow_dir(struct kobject *kobj)
+ {
+-      struct sysfs_dirent *sd = NULL;
+-      struct dentry *dir, *shadow;
++      struct sysfs_dirent *sd;
++      struct dentry *parent, *dir, *shadow;
+       struct inode *inode;
+-      dir = parent_sd->s_dentry;
++      dir = kobj->dentry;
+       inode = dir->d_inode;
+-
+-      shadow = d_alloc(dir->d_parent, &dir->d_name);
+-      if (!shadow)
++      parent = dir->d_parent;
++      shadow = ERR_PTR(-EINVAL);
++      if (!sysfs_is_shadowed_inode(inode))
+               goto out;
+-      /* Since the shadow directory is reachable make it look
+-       * like it is actually hashed.
+-       */
+-      shadow->d_hash.pprev = &shadow->d_hash.next;
+-      shadow->d_hash.next = NULL;
+-      shadow->d_flags &= ~DCACHE_UNHASHED;
++      shadow = d_alloc(parent, &dir->d_name);
++      if (!shadow)
++              goto nomem;
+-      sd = sysfs_new_dirent(tag, parent_sd->s_mode, SYSFS_SHADOW_DIR);
++      sd = __sysfs_make_dirent(shadow, kobj, inode->i_mode, SYSFS_DIR);
+       if (!sd)
+-              goto error;
+-
+-      sd->s_elem.dir.kobj = parent_sd->s_elem.dir.kobj;
+-      sd->s_parent = sysfs_get(parent_sd);
+-
+-      /* Use the inode number of the parent we are shadowing */
+-      sysfs_free_ino(sd->s_ino);
+-      sd->s_ino = parent_sd->s_ino;
++              goto nomem;
++      d_instantiate(shadow, igrab(inode));
+       inc_nlink(inode);
+-      inc_nlink(dir->d_parent->d_inode);
++      inc_nlink(parent->d_inode);
++      shadow->d_op = &sysfs_dentry_ops;
 +
-+/*
-+ * proc_container_show()
-+ *  - Print task's container paths into seq_file, one line for each hierarchy
-+ *  - Used for /proc/<pid>/container.
-+ *  - No need to task_lock(tsk) on this tsk->container reference, as it
-+ *    doesn't really matter if tsk->container changes after we read it,
-+ *    and we take container_mutex, keeping attach_task() from changing it
-+ *    anyway.  No need to check that tsk->container != NULL, thanks to
-+ *    the_top_container_hack in container_exit(), which sets an exiting tasks
-+ *    container to top_container.
++      dget(shadow);           /* Extra count - pin the dentry in core */
+-      sysfs_link_sibling(sd);
+-      __iget(inode);
+-      sysfs_instantiate(shadow, inode);
+-      sysfs_attach_dentry(sd, shadow);
+ out:
+-      return sd;
+-error:
++      return shadow;
++nomem:
+       dput(shadow);
++      shadow = ERR_PTR(-ENOMEM);
+       goto out;
+ }
+-int sysfs_resolve_for_create(struct kobject *kobj,
+-                              struct sysfs_dirent **parent_sd)
+-{
+-      const struct shadow_dir_operations *shadow_ops;
+-      struct sysfs_dirent *sd, *shadow_sd;
+-
+-      sd = *parent_sd;
+-      if (sysfs_type(sd) == SYSFS_SHADOW_DIR)
+-              sd = sd->s_parent;
+-
+-      if (sd->s_flags & SYSFS_FLAG_SHADOWED) {
+-              const void *tag;
+-
+-              shadow_ops = sd->s_dentry->d_inode->i_private;
+-              tag = shadow_ops->kobject_tag(kobj);
+-
+-              shadow_sd = find_shadow_sd(sd, tag);
+-              if (!shadow_sd)
+-                      shadow_sd = add_shadow_sd(sd, tag);
+-              sd = shadow_sd;
+-      }
+-      if (sd) {
+-              *parent_sd = sd;
+-              return 1;
+-      }
+-      return 0;
+-}
+-
+-int sysfs_resolve_for_remove(struct kobject *kobj,
+-                              struct sysfs_dirent **parent_sd)
+-{
+-      struct sysfs_dirent *sd;
+-      /* If dentry is a shadow directory find the shadow that is
+-       * stored under the same tag as kobj.  This allows removal
+-       * of dirents to function properly even if the value of
+-       * kobject_tag() has changed since we initially created
+-       * the dirents assoctated with kobj.
+-       */
+-
+-      sd = *parent_sd;
+-      if (sysfs_type(sd) == SYSFS_SHADOW_DIR)
+-              sd = sd->s_parent;
+-      if (sd->s_flags & SYSFS_FLAG_SHADOWED) {
+-              const void *tag;
+-
+-              tag = find_shadow_tag(kobj);
+-              sd = find_shadow_sd(sd, tag);
+-      }
+-      if (sd) {
+-              *parent_sd = sd;
+-              return 1;
+-      }
+-      return 0;
+-}
+-
+ /**
+- *    sysfs_enable_shadowing - Automatically create shadows of a directory
+- *    @kobj:  object to automatically shadow
+- *
+- *    Once shadowing has been enabled on a directory the contents
+- *    of the directory become dependent upon context.
+- *
+- *    shadow_ops->current_tag() returns the context for the current
+- *    process.
++ *    sysfs_remove_shadow_dir - remove an object's directory.
++ *    @shadow: dentry of shadow directory
+  *
+- *    shadow_ops->kobject_tag() returns the context that a given kobj
+- *    resides in.
+- *
+- *    Using those methods the sysfs code on shadowed directories
+- *    carefully stores the files so that when we lookup files
+- *    we get the proper answer for our context.
+- *
+- *    If the context of a kobject is changed it is expected that
+- *    the kobject will be renamed so the appopriate sysfs data structures
+- *    can be updated.
+- */
+-int sysfs_enable_shadowing(struct kobject *kobj,
+-      const struct shadow_dir_operations *shadow_ops)
+-{
+-      struct sysfs_dirent *sd;
+-      struct dentry *dentry;
+-      int err;
+-
+-      /* Find the dentry for the shadowed directory and
+-       * increase it's count.
++ *    The only thing special about this is that we remove any files in
++ *    the directory before we remove the directory, and we've inlined
++ *    what used to be sysfs_rmdir() below, instead of calling separately.
+        */
+-      err = -ENOENT;
+-      sd = kobj->sd;
+-      dentry = sysfs_get_dentry(sd);
+-      if (!dentry)
+-              goto out;
+-      mutex_lock(&sysfs_mutex);
+-      err = -EINVAL;
+-      /* We can only enable shadowing on empty directories
+-       * where shadowing is not already enabled.
+-       */
+-      if (!sd->s_children && (sysfs_type(sd) == SYSFS_DIR) &&
+-          !(sd->s_flags & SYSFS_FLAG_REMOVED) &&
+-          !(sd->s_flags & SYSFS_FLAG_SHADOWED)) {
+-              sd->s_flags |= SYSFS_FLAG_SHADOWED;
+-              dentry->d_inode->i_private = (void *)shadow_ops;
+-              err = 0;
+-      }
+-      mutex_unlock(&sysfs_mutex);
+-out:
+-      if (err)
+-              dput(dentry);
+-      return err;
++void sysfs_remove_shadow_dir(struct dentry *shadow)
++{
++      __sysfs_remove_dir(shadow);
+ }
++const struct file_operations sysfs_dir_operations = {
++      .open           = sysfs_dir_open,
++      .release        = sysfs_dir_close,
++      .llseek         = sysfs_dir_lseek,
++      .read           = generic_read_dir,
++      .readdir        = sysfs_readdir,
++};
+diff -Nurb linux-2.6.22-590/fs/sysfs/file.c linux-2.6.22-570/fs/sysfs/file.c
+--- linux-2.6.22-590/fs/sysfs/file.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/sysfs/file.c   2008-01-23 19:15:56.000000000 -0500
+@@ -50,15 +50,29 @@
+       .store  = subsys_attr_store,
+ };
+-struct sysfs_buffer {
+-      size_t                  count;
+-      loff_t                  pos;
+-      char                    * page;
+-      struct sysfs_ops        * ops;
+-      struct semaphore        sem;
+-      int                     needs_read_fill;
+-      int                     event;
+-};
++/**
++ *    add_to_collection - add buffer to a collection
++ *    @buffer:        buffer to be added
++ *    @node:          inode of set to add to
 + */
 +
-+/* TODO: Use a proper seq_file iterator */
-+static int proc_container_show(struct seq_file *m, void *v)
++static inline void
++add_to_collection(struct sysfs_buffer *buffer, struct inode *node)
 +{
-+      struct pid *pid;
-+      struct task_struct *tsk;
-+      char *buf;
-+      int retval;
-+      struct containerfs_root *root;
-+
-+      retval = -ENOMEM;
-+      buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-+      if (!buf)
-+              goto out;
-+
-+      retval = -ESRCH;
-+      pid = m->private;
-+      tsk = get_pid_task(pid, PIDTYPE_PID);
-+      if (!tsk)
-+              goto out_free;
-+
-+      retval = 0;
-+
-+      mutex_lock(&container_mutex);
++      struct sysfs_buffer_collection *set = node->i_private;
 +
-+      for_each_root(root) {
-+              struct container_subsys *ss;
-+              struct container *cont;
-+              int subsys_id;
-+              int count = 0;
-+
-+              /* Skip this hierarchy if it has no active subsystems */
-+              if (!root->subsys_bits)
-+                      continue;
-+              for_each_subsys(root, ss)
-+                      seq_printf(m, "%s%s", count++ ? "," : "", ss->name);
-+              seq_putc(m, ':');
-+              get_first_subsys(&root->top_container, NULL, &subsys_id);
-+              cont = task_container(tsk, subsys_id);
-+              retval = container_path(cont, buf, PAGE_SIZE);
-+              if (retval < 0)
-+                      goto out_unlock;
-+              seq_puts(m, buf);
-+              seq_putc(m, '\n');
-+      }
-+
-+out_unlock:
-+      mutex_unlock(&container_mutex);
-+      put_task_struct(tsk);
-+out_free:
-+      kfree(buf);
-+out:
-+      return retval;
++      mutex_lock(&node->i_mutex);
++      list_add(&buffer->associates, &set->associates);
++      mutex_unlock(&node->i_mutex);
 +}
 +
-+static int container_open(struct inode *inode, struct file *file)
++static inline void
++remove_from_collection(struct sysfs_buffer *buffer, struct inode *node)
 +{
-+      struct pid *pid = PROC_I(inode)->pid;
-+      return single_open(file, proc_container_show, pid);
++      mutex_lock(&node->i_mutex);
++      list_del(&buffer->associates);
++      mutex_unlock(&node->i_mutex);
 +}
+ /**
+  *    fill_read_buffer - allocate and fill buffer from object.
+@@ -73,8 +87,9 @@
+  */
+ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
+ {
+-      struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+-      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
++      struct sysfs_dirent * sd = dentry->d_fsdata;
++      struct attribute * attr = to_attr(dentry);
++      struct kobject * kobj = to_kobj(dentry->d_parent);
+       struct sysfs_ops * ops = buffer->ops;
+       int ret = 0;
+       ssize_t count;
+@@ -84,15 +99,8 @@
+       if (!buffer->page)
+               return -ENOMEM;
+-      /* need attr_sd for attr and ops, its parent for kobj */
+-      if (!sysfs_get_active_two(attr_sd))
+-              return -ENODEV;
+-
+-      buffer->event = atomic_read(&attr_sd->s_event);
+-      count = ops->show(kobj, attr_sd->s_elem.attr.attr, buffer->page);
+-
+-      sysfs_put_active_two(attr_sd);
+-
++      buffer->event = atomic_read(&sd->s_event);
++      count = ops->show(kobj,attr,buffer->page);
+       BUG_ON(count > (ssize_t)PAGE_SIZE);
+       if (count >= 0) {
+               buffer->needs_read_fill = 0;
+@@ -130,6 +138,9 @@
+       down(&buffer->sem);
+       if (buffer->needs_read_fill) {
++              if (buffer->orphaned)
++                      retval = -ENODEV;
++              else
+                       retval = fill_read_buffer(file->f_path.dentry,buffer);
+               if (retval)
+                       goto out;
+@@ -188,20 +199,11 @@
+ static int 
+ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
+ {
+-      struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+-      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
++      struct attribute * attr = to_attr(dentry);
++      struct kobject * kobj = to_kobj(dentry->d_parent);
+       struct sysfs_ops * ops = buffer->ops;
+-      int rc;
+-
+-      /* need attr_sd for attr and ops, its parent for kobj */
+-      if (!sysfs_get_active_two(attr_sd))
+-              return -ENODEV;
+-
+-      rc = ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count);
+-
+-      sysfs_put_active_two(attr_sd);
+-      return rc;
++      return ops->store(kobj,attr,buffer->page,count);
+ }
+@@ -229,29 +231,37 @@
+       ssize_t len;
+       down(&buffer->sem);
++      if (buffer->orphaned) {
++              len = -ENODEV;
++              goto out;
++      }
+       len = fill_write_buffer(buffer, buf, count);
+       if (len > 0)
+               len = flush_write_buffer(file->f_path.dentry, buffer, len);
+       if (len > 0)
+               *ppos += len;
++out:
+       up(&buffer->sem);
+       return len;
+ }
+ static int sysfs_open_file(struct inode *inode, struct file *file)
+ {
+-      struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+-      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
++      struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
++      struct attribute * attr = to_attr(file->f_path.dentry);
++      struct sysfs_buffer_collection *set;
+       struct sysfs_buffer * buffer;
+-
+       struct sysfs_ops * ops = NULL;
+-      int error;
++      int error = 0;
++      if (!kobj || !attr)
++              goto Einval;
+-      /* need attr_sr for attr and ops, its parent for kobj */
+-
+-      if (!sysfs_get_active_two(attr_sd))
+-              return -ENODEV;
++      /* Grab the module reference for this attribute if we have one */
++      if (!try_module_get(attr->owner)) {
++              error = -ENODEV;
++              goto Done;
++      }
+       /* if the kobject has no ktype, then we assume that it is a subsystem
+        * itself, and use ops for it.
+@@ -267,7 +277,20 @@
+        * or the subsystem have no operations.
+        */
+       if (!ops)
+-              goto err_out;
++              goto Eaccess;
 +
-+struct file_operations proc_container_operations = {
-+      .open           = container_open,
-+      .read           = seq_read,
-+      .llseek         = seq_lseek,
-+      .release        = single_release,
-+};
-+
-+/* Display information about each subsystem and each hierarchy */
-+static int proc_containerstats_show(struct seq_file *m, void *v)
-+{
-+      int i;
-+      struct containerfs_root *root;
-+
-+      mutex_lock(&container_mutex);
-+      seq_puts(m, "Hierarchies:\n");
-+      for_each_root(root) {
-+              struct container_subsys *ss;
-+              int first = 1;
-+              seq_printf(m, "%p: bits=%lx containers=%d (", root,
-+                         root->subsys_bits, root->number_of_containers);
-+              for_each_subsys(root, ss) {
-+                      seq_printf(m, "%s%s", first ? "" : ", ", ss->name);
-+                      first = false;
-+              }
-+              seq_putc(m, ')');
-+              if (root->sb) {
-+                      seq_printf(m, " s_active=%d",
-+                                 atomic_read(&root->sb->s_active));
++      /* make sure we have a collection to add our buffers to */
++      mutex_lock(&inode->i_mutex);
++      if (!(set = inode->i_private)) {
++              if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL))) {
++                      mutex_unlock(&inode->i_mutex);
++                      error = -ENOMEM;
++                      goto Done;
++              } else {
++                      INIT_LIST_HEAD(&set->associates);
 +              }
-+              seq_putc(m, '\n');
 +      }
-+      seq_puts(m, "Subsystems:\n");
-+      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
-+              struct container_subsys *ss = subsys[i];
-+              seq_printf(m, "%d: name=%s hierarchy=%p\n",
-+                         i, ss->name, ss->root);
++      mutex_unlock(&inode->i_mutex);
+       /* File needs write support.
+        * The inode's perms must say it's ok, 
+@@ -276,7 +299,7 @@
+       if (file->f_mode & FMODE_WRITE) {
+               if (!(inode->i_mode & S_IWUGO) || !ops->store)
+-                      goto err_out;
++                      goto Eaccess;
+       }
+@@ -286,38 +309,48 @@
+        */
+       if (file->f_mode & FMODE_READ) {
+               if (!(inode->i_mode & S_IRUGO) || !ops->show)
+-                      goto err_out;
++                      goto Eaccess;
+       }
+       /* No error? Great, allocate a buffer for the file, and store it
+        * it in file->private_data for easy access.
+        */
+-      error = -ENOMEM;
+       buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);
+-      if (!buffer)
+-              goto err_out;
+-
++      if (buffer) {
++              INIT_LIST_HEAD(&buffer->associates);
+               init_MUTEX(&buffer->sem);
+               buffer->needs_read_fill = 1;
+               buffer->ops = ops;
++              add_to_collection(buffer, inode);
+               file->private_data = buffer;
++      } else
++              error = -ENOMEM;
++      goto Done;
+-      /* open succeeded, put active references and pin attr_sd */
+-      sysfs_put_active_two(attr_sd);
+-      sysfs_get(attr_sd);
+-      return 0;
+-
+- err_out:
+-      sysfs_put_active_two(attr_sd);
++ Einval:
++      error = -EINVAL;
++      goto Done;
++ Eaccess:
++      error = -EACCES;
++      module_put(attr->owner);
++ Done:
++      if (error)
++              kobject_put(kobj);
+       return error;
+ }
+ static int sysfs_release(struct inode * inode, struct file * filp)
+ {
+-      struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
+-      struct sysfs_buffer *buffer = filp->private_data;
++      struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
++      struct attribute * attr = to_attr(filp->f_path.dentry);
++      struct module * owner = attr->owner;
++      struct sysfs_buffer * buffer = filp->private_data;
+-      sysfs_put(attr_sd);
++      if (buffer)
++              remove_from_collection(buffer, inode);
++      kobject_put(kobj);
++      /* After this point, attr should not be accessed. */
++      module_put(owner);
+       if (buffer) {
+               if (buffer->page)
+@@ -344,43 +377,57 @@
+ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
+ {
+       struct sysfs_buffer * buffer = filp->private_data;
+-      struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
+-      struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+-
+-      /* need parent for the kobj, grab both */
+-      if (!sysfs_get_active_two(attr_sd))
+-              goto trigger;
++      struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
++      struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata;
++      int res = 0;
+       poll_wait(filp, &kobj->poll, wait);
+-      sysfs_put_active_two(attr_sd);
+-
+-      if (buffer->event != atomic_read(&attr_sd->s_event))
+-              goto trigger;
+-
+-      return 0;
+-
+- trigger:
++      if (buffer->event != atomic_read(&sd->s_event)) {
++              res = POLLERR|POLLPRI;
+       buffer->needs_read_fill = 1;
+-      return POLLERR|POLLPRI;
 +      }
-+      seq_printf(m, "Container groups: %d\n", css_group_count);
-+      mutex_unlock(&container_mutex);
-+      return 0;
-+}
-+
-+static int containerstats_open(struct inode *inode, struct file *file)
-+{
-+      return single_open(file, proc_containerstats_show, 0);
-+}
-+
-+static struct file_operations proc_containerstats_operations = {
-+      .open = containerstats_open,
-+      .read = seq_read,
-+      .llseek = seq_lseek,
-+      .release = single_release,
-+};
 +
-+/**
-+ * container_fork - attach newly forked task to its parents container.
-+ * @tsk: pointer to task_struct of forking parent process.
-+ *
-+ * Description: A task inherits its parent's container at fork().
-+ *
-+ * A pointer to the shared css_group was automatically copied in
-+ * fork.c by dup_task_struct().  However, we ignore that copy, since
-+ * it was not made under the protection of RCU or container_mutex, so
-+ * might no longer be a valid container pointer.  attach_task() might
-+ * have already changed current->containers, allowing the previously
-+ * referenced container group to be removed and freed.
-+ *
-+ * At the point that container_fork() is called, 'current' is the parent
-+ * task, and the passed argument 'child' points to the child task.
-+ */
-+void container_fork(struct task_struct *child)
-+{
-+      write_lock(&css_group_lock);
-+      child->containers = current->containers;
-+      get_css_group(child->containers);
-+      list_add(&child->cg_list, &child->containers->tasks);
-+      write_unlock(&css_group_lock);
-+}
++      return res;
+ }
+-void sysfs_notify(struct kobject *k, char *dir, char *attr)
 +
-+/**
-+ * container_fork_callbacks - called on a new task very soon before
-+ * adding it to the tasklist. No need to take any locks since no-one
-+ * can be operating on this task
-+ */
-+void container_fork_callbacks(struct task_struct *child)
-+{
-+      if (need_forkexit_callback) {
-+              int i;
-+              for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
-+                      struct container_subsys *ss = subsys[i];
-+                      if (ss->fork)
-+                              ss->fork(ss, child);
-+              }
++static struct dentry *step_down(struct dentry *dir, const char * name)
+ {
+-      struct sysfs_dirent *sd = k->sd;
++      struct dentry * de;
+-      mutex_lock(&sysfs_mutex);
++      if (dir == NULL || dir->d_inode == NULL)
++              return NULL;
+-      if (sd && dir)
+-              sd = sysfs_find_dirent(sd, dir);
+-      if (sd && attr)
+-              sd = sysfs_find_dirent(sd, attr);
+-      if (sd) {
++      mutex_lock(&dir->d_inode->i_mutex);
++      de = lookup_one_len(name, dir, strlen(name));
++      mutex_unlock(&dir->d_inode->i_mutex);
++      dput(dir);
++      if (IS_ERR(de))
++              return NULL;
++      if (de->d_inode == NULL) {
++              dput(de);
++              return NULL;
 +      }
++      return de;
 +}
 +
-+/**
-+ * container_exit - detach container from exiting task
-+ * @tsk: pointer to task_struct of exiting process
-+ *
-+ * Description: Detach container from @tsk and release it.
-+ *
-+ * Note that containers marked notify_on_release force every task in
-+ * them to take the global container_mutex mutex when exiting.
-+ * This could impact scaling on very large systems.  Be reluctant to
-+ * use notify_on_release containers where very high task exit scaling
-+ * is required on large systems.
-+ *
-+ * the_top_container_hack:
-+ *
-+ *    Set the exiting tasks container to the root container (top_container).
-+ *
-+ *    We call container_exit() while the task is still competent to
-+ *    handle notify_on_release(), then leave the task attached to the
-+ *    root container in each hierarchy for the remainder of its exit.
-+ *
-+ *    To do this properly, we would increment the reference count on
-+ *    top_container, and near the very end of the kernel/exit.c do_exit()
-+ *    code we would add a second container function call, to drop that
-+ *    reference.  This would just create an unnecessary hot spot on
-+ *    the top_container reference count, to no avail.
-+ *
-+ *    Normally, holding a reference to a container without bumping its
-+ *    count is unsafe.   The container could go away, or someone could
-+ *    attach us to a different container, decrementing the count on
-+ *    the first container that we never incremented.  But in this case,
-+ *    top_container isn't going away, and either task has PF_EXITING set,
-+ *    which wards off any attach_task() attempts, or task is a failed
-+ *    fork, never visible to attach_task.
-+ *
-+ */
-+void container_exit(struct task_struct *tsk, int run_callbacks)
++void sysfs_notify(struct kobject * k, char *dir, char *attr)
 +{
-+      int i;
-+      struct css_group *cg = NULL;
-+
-+      if (run_callbacks && need_forkexit_callback) {
-+              for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
-+                      struct container_subsys *ss = subsys[i];
-+                      if (ss->exit)
-+                              ss->exit(ss, tsk);
-+              }
++      struct dentry *de = k->dentry;
++      if (de)
++              dget(de);
++      if (de && dir)
++              de = step_down(de, dir);
++      if (de && attr)
++              de = step_down(de, attr);
++      if (de) {
++              struct sysfs_dirent * sd = de->d_fsdata;
++              if (sd)
+                       atomic_inc(&sd->s_event);
+               wake_up_interruptible(&k->poll);
++              dput(de);
+       }
+-
+-      mutex_unlock(&sysfs_mutex);
+ }
+ EXPORT_SYMBOL_GPL(sysfs_notify);
+@@ -394,30 +441,19 @@
+ };
+-int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
+-                 int type)
++int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
+ {
++      struct sysfs_dirent * parent_sd = dir->d_fsdata;
+       umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
+-      struct sysfs_addrm_cxt acxt;
+-      struct sysfs_dirent *sd;
+-
+-      sd = sysfs_new_dirent(attr->name, mode, type);
+-      if (!sd)
+-              return -ENOMEM;
+-      sd->s_elem.attr.attr = (void *)attr;
++      int error = -EEXIST;
+-      sysfs_addrm_start(&acxt, dir_sd);
++      mutex_lock(&dir->d_inode->i_mutex);
++      if (!sysfs_dirent_exist(parent_sd, attr->name))
++              error = sysfs_make_dirent(parent_sd, NULL, (void *)attr,
++                                        mode, type);
++      mutex_unlock(&dir->d_inode->i_mutex);
+-      if (!sysfs_find_dirent(dir_sd, attr->name)) {
+-              sysfs_add_one(&acxt, sd);
+-              sysfs_link_sibling(sd);
+-      }
+-
+-      if (sysfs_addrm_finish(&acxt))
+-              return 0;
+-
+-      sysfs_put(sd);
+-      return -EEXIST;
++      return error;
+ }
+@@ -429,9 +465,9 @@
+ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
+ {
+-      BUG_ON(!kobj || !kobj->sd || !attr);
++      BUG_ON(!kobj || !kobj->dentry || !attr);
+-      return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
++      return sysfs_add_file(kobj->dentry, attr, SYSFS_KOBJ_ATTR);
+ }
+@@ -445,16 +481,16 @@
+ int sysfs_add_file_to_group(struct kobject *kobj,
+               const struct attribute *attr, const char *group)
+ {
+-      struct sysfs_dirent *dir_sd;
++      struct dentry *dir;
+       int error;
+-      dir_sd = sysfs_get_dirent(kobj->sd, group);
+-      if (!dir_sd)
+-              return -ENOENT;
+-
+-      error = sysfs_add_file(dir_sd, attr, SYSFS_KOBJ_ATTR);
+-      sysfs_put(dir_sd);
+-
++      dir = lookup_one_len(group, kobj->dentry, strlen(group));
++      if (IS_ERR(dir))
++              error = PTR_ERR(dir);
++      else {
++              error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR);
++              dput(dir);
 +      }
+       return error;
+ }
+ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
+@@ -467,31 +503,30 @@
+  */
+ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
+ {
+-      struct sysfs_dirent *victim_sd = NULL;
+-      struct dentry *victim = NULL;
+-      int rc;
+-
+-      rc = -ENOENT;
+-      victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
+-      if (!victim_sd)
+-              goto out;
+-              
+-      victim = sysfs_get_dentry(victim_sd);
+-      if (IS_ERR(victim)) {
+-              rc = PTR_ERR(victim);
+-              victim = NULL;
+-              goto out;
+-      }
+-
+-      mutex_lock(&victim->d_inode->i_mutex);
++      struct dentry * dir = kobj->dentry;
++      struct dentry * victim;
++      int res = -ENOENT;
 +
-+      /* Reassign the task to the init_css_group. */
-+      task_lock(tsk);
-+      write_lock(&css_group_lock);
-+      list_del(&tsk->cg_list);
-+      write_unlock(&css_group_lock);
-+
-+      cg = tsk->containers;
-+      tsk->containers = &init_css_group;
-+      task_unlock(tsk);
-+      if (cg)
-+              put_css_group_taskexit(cg);
-+}
-+
-+/**
-+ * container_clone - duplicate the current container in the hierarchy
-+ * that the given subsystem is attached to, and move this task into
-+ * the new child
-+ */
-+int container_clone(struct task_struct *tsk, struct container_subsys *subsys)
-+{
-+      struct dentry *dentry;
-+      int ret = 0;
-+      char nodename[MAX_CONTAINER_TYPE_NAMELEN];
-+      struct container *parent, *child;
-+      struct inode *inode;
-+      struct css_group *cg;
-+      struct containerfs_root *root;
-+      struct container_subsys *ss;
-+
-+      /* We shouldn't be called by an unregistered subsystem */
-+      BUG_ON(!subsys->active);
-+
-+      /* First figure out what hierarchy and container we're dealing
-+       * with, and pin them so we can drop container_mutex */
-+      mutex_lock(&container_mutex);
-+ again:
-+      root = subsys->root;
-+      if (root == &rootnode) {
-+              printk(KERN_INFO
-+                     "Not cloning container for unused subsystem %s\n",
-+                     subsys->name);
-+              mutex_unlock(&container_mutex);
-+              return 0;
++      mutex_lock(&dir->d_inode->i_mutex);
++      victim = lookup_one_len(attr->name, dir, strlen(attr->name));
++      if (!IS_ERR(victim)) {
++              /* make sure dentry is really there */
++              if (victim->d_inode && 
++                  (victim->d_parent->d_inode == dir->d_inode)) {
+       victim->d_inode->i_mtime = CURRENT_TIME;
+       fsnotify_modify(victim);
+-      mutex_unlock(&victim->d_inode->i_mutex);
+-      rc = 0;
+- out:
++                      res = 0;
++              } else
++                      d_drop(victim);
++              
++              /**
++               * Drop the reference acquired from lookup_one_len() above.
++               */
+       dput(victim);
+-      sysfs_put(victim_sd);
+-      return rc;
 +      }
-+      cg = tsk->containers;
-+      parent = task_container(tsk, subsys->subsys_id);
-+
-+      snprintf(nodename, MAX_CONTAINER_TYPE_NAMELEN, "node_%d", tsk->pid);
-+
-+      /* Pin the hierarchy */
-+      atomic_inc(&parent->root->sb->s_active);
-+
-+      /* Keep the container alive */
-+      get_css_group(cg);
-+      mutex_unlock(&container_mutex);
-+
-+      /* Now do the VFS work to create a container */
-+      inode = parent->dentry->d_inode;
++      mutex_unlock(&dir->d_inode->i_mutex);
 +
-+      /* Hold the parent directory mutex across this operation to
-+       * stop anyone else deleting the new container */
-+      mutex_lock(&inode->i_mutex);
-+      dentry = container_get_dentry(parent->dentry, nodename);
-+      if (IS_ERR(dentry)) {
-+              printk(KERN_INFO
-+                     "Couldn't allocate dentry for %s: %ld\n", nodename,
-+                     PTR_ERR(dentry));
-+              ret = PTR_ERR(dentry);
-+              goto out_release;
++      return res;
+ }
+@@ -504,34 +539,30 @@
+  */
+ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
+ {
+-      struct sysfs_dirent *victim_sd = NULL;
+-      struct dentry *victim = NULL;
++      struct dentry *dir = kobj->dentry;
++      struct dentry *victim;
+       struct inode * inode;
+       struct iattr newattrs;
+-      int rc;
+-
+-      rc = -ENOENT;
+-      victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
+-      if (!victim_sd)
+-              goto out;
+-
+-      victim = sysfs_get_dentry(victim_sd);
+-      if (IS_ERR(victim)) {
+-              rc = PTR_ERR(victim);
+-              victim = NULL;
+-              goto out;
+-      }
++      int res = -ENOENT;
++      mutex_lock(&dir->d_inode->i_mutex);
++      victim = lookup_one_len(attr->name, dir, strlen(attr->name));
++      if (!IS_ERR(victim)) {
++              if (victim->d_inode &&
++                  (victim->d_parent->d_inode == dir->d_inode)) {
+                       inode = victim->d_inode;
+                       mutex_lock(&inode->i_mutex);
+-      newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
++                      newattrs.ia_mode = (mode & S_IALLUGO) |
++                                              (inode->i_mode & ~S_IALLUGO);
+                       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+-      rc = notify_change(victim, &newattrs);
++                      res = notify_change(victim, &newattrs);
+                       mutex_unlock(&inode->i_mutex);
+- out:
++              }
+               dput(victim);
+-      sysfs_put(victim_sd);
+-      return rc;
 +      }
++      mutex_unlock(&dir->d_inode->i_mutex);
 +
-+      /* Create the container directory, which also creates the container */
-+      ret = vfs_mkdir(inode, dentry, S_IFDIR | 0755, NULL);
-+      child = __d_cont(dentry);
-+      dput(dentry);
-+      if (ret) {
-+              printk(KERN_INFO
-+                     "Failed to create container %s: %d\n", nodename,
-+                     ret);
-+              goto out_release;
++      return res;
+ }
+ EXPORT_SYMBOL_GPL(sysfs_chmod_file);
+@@ -546,7 +577,7 @@
+ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
+ {
+-      sysfs_hash_and_remove(kobj, kobj->sd, attr->name);
++      sysfs_hash_and_remove(kobj->dentry, attr->name);
+ }
+@@ -559,12 +590,12 @@
+ void sysfs_remove_file_from_group(struct kobject *kobj,
+               const struct attribute *attr, const char *group)
+ {
+-      struct sysfs_dirent *dir_sd;
++      struct dentry *dir;
+-      dir_sd = sysfs_get_dirent(kobj->sd, group);
+-      if (dir_sd) {
+-              sysfs_hash_and_remove(kobj, dir_sd, attr->name);
+-              sysfs_put(dir_sd);
++      dir = lookup_one_len(group, kobj->dentry, strlen(group));
++      if (!IS_ERR(dir)) {
++              sysfs_hash_and_remove(dir, attr->name);
++              dput(dir);
+       }
+ }
+ EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
+diff -Nurb linux-2.6.22-590/fs/sysfs/group.c linux-2.6.22-570/fs/sysfs/group.c
+--- linux-2.6.22-590/fs/sysfs/group.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/sysfs/group.c  2007-07-08 19:32:17.000000000 -0400
+@@ -13,29 +13,31 @@
+ #include <linux/dcache.h>
+ #include <linux/namei.h>
+ #include <linux/err.h>
++#include <linux/fs.h>
+ #include <asm/semaphore.h>
+ #include "sysfs.h"
+-static void remove_files(struct kobject *kobj, struct sysfs_dirent *dir_sd,
+-                       const struct attribute_group *grp)
++static void remove_files(struct dentry * dir, 
++                       const struct attribute_group * grp)
+ {
+       struct attribute *const* attr;
+       for (attr = grp->attrs; *attr; attr++)
+-              sysfs_hash_and_remove(kobj, dir_sd, (*attr)->name);
++              sysfs_hash_and_remove(dir,(*attr)->name);
+ }
+-static int create_files(struct kobject *kobj, struct sysfs_dirent *dir_sd,
+-                      const struct attribute_group *grp)
++static int create_files(struct dentry * dir,
++                      const struct attribute_group * grp)
+ {
+       struct attribute *const* attr;
+       int error = 0;
+-      for (attr = grp->attrs; *attr && !error; attr++)
+-              error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
++      for (attr = grp->attrs; *attr && !error; attr++) {
++              error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
 +      }
-+
-+      if (!child) {
-+              printk(KERN_INFO
-+                     "Couldn't find new container %s\n", nodename);
-+              ret = -ENOMEM;
-+              goto out_release;
+       if (error)
+-              remove_files(kobj, dir_sd, grp);
++              remove_files(dir,grp);
+       return error;
+ }
+@@ -43,44 +45,44 @@
+ int sysfs_create_group(struct kobject * kobj, 
+                      const struct attribute_group * grp)
+ {
+-      struct sysfs_dirent *sd;
++      struct dentry * dir;
+       int error;
+-      BUG_ON(!kobj || !kobj->sd);
++      BUG_ON(!kobj || !kobj->dentry);
+       if (grp->name) {
+-              error = sysfs_create_subdir(kobj, grp->name, &sd);
++              error = sysfs_create_subdir(kobj,grp->name,&dir);
+               if (error)
+                       return error;
+       } else
+-              sd = kobj->sd;
+-      sysfs_get(sd);
+-      error = create_files(kobj, sd, grp);
+-      if (error) {
++              dir = kobj->dentry;
++      dir = dget(dir);
++      if ((error = create_files(dir,grp))) {
+               if (grp->name)
+-                      sysfs_remove_subdir(sd);
++                      sysfs_remove_subdir(dir);
+       }
+-      sysfs_put(sd);
++      dput(dir);
+       return error;
+ }
+ void sysfs_remove_group(struct kobject * kobj, 
+                       const struct attribute_group * grp)
+ {
+-      struct sysfs_dirent *dir_sd = kobj->sd;
+-      struct sysfs_dirent *sd;
++      struct dentry * dir;
+       if (grp->name) {
+-              sd = sysfs_get_dirent(dir_sd, grp->name);
+-              BUG_ON(!sd);
+-      } else
+-              sd = sysfs_get(dir_sd);
++              dir = lookup_one_len_kern(grp->name, kobj->dentry,
++                              strlen(grp->name));
++              BUG_ON(IS_ERR(dir));
 +      }
-+
-+      /* The container now exists. Retake container_mutex and check
-+       * that we're still in the same state that we thought we
-+       * were. */
-+      mutex_lock(&container_mutex);
-+      if ((root != subsys->root) ||
-+          (parent != task_container(tsk, subsys->subsys_id))) {
-+              /* Aargh, we raced ... */
-+              mutex_unlock(&inode->i_mutex);
-+              put_css_group(cg);
-+
-+              deactivate_super(parent->root->sb);
-+              /* The container is still accessible in the VFS, but
-+               * we're not going to try to rmdir() it at this
-+               * point. */
-+              printk(KERN_INFO
-+                     "Race in container_clone() - leaking container %s\n",
-+                     nodename);
-+              goto again;
++      else
++              dir = dget(kobj->dentry);
+-      remove_files(kobj, sd, grp);
++      remove_files(dir,grp);
+       if (grp->name)
+-              sysfs_remove_subdir(sd);
+-
+-      sysfs_put(sd);
++              sysfs_remove_subdir(dir);
++      /* release the ref. taken in this routine */
++      dput(dir);
+ }
+diff -Nurb linux-2.6.22-590/fs/sysfs/inode.c linux-2.6.22-570/fs/sysfs/inode.c
+--- linux-2.6.22-590/fs/sysfs/inode.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/sysfs/inode.c  2007-07-08 19:32:17.000000000 -0400
+@@ -34,6 +34,16 @@
+       .setattr        = sysfs_setattr,
+ };
++void sysfs_delete_inode(struct inode *inode)
++{
++      /* Free the shadowed directory inode operations */
++      if (sysfs_is_shadowed_inode(inode)) {
++              kfree(inode->i_op);
++              inode->i_op = NULL;
 +      }
++      return generic_delete_inode(inode);
++}
 +
-+      /* do any required auto-setup */
-+      for_each_subsys(root, ss) {
-+              if (ss->post_clone)
-+                      ss->post_clone(ss, child);
+ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
+ {
+       struct inode * inode = dentry->d_inode;
+@@ -123,8 +133,10 @@
+  */
+ static struct lock_class_key sysfs_inode_imutex_key;
+-void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
++struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
+ {
++      struct inode * inode = new_inode(sysfs_sb);
++      if (inode) {
+               inode->i_blocks = 0;
+               inode->i_mapping->a_ops = &sysfs_aops;
+               inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
+@@ -139,81 +151,169 @@
+                        */
+                       set_inode_attr(inode, sd->s_iattr);
+               } else
+-              set_default_inode_attr(inode, sd->s_mode);
++                      set_default_inode_attr(inode, mode);
 +      }
++      return inode;
++}
 +
-+      /* All seems fine. Finish by moving the task into the new container */
-+      ret = attach_task(child, tsk);
-+      mutex_unlock(&container_mutex);
-+
-+ out_release:
-+      mutex_unlock(&inode->i_mutex);
++int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
++{
++      int error = 0;
++      struct inode * inode = NULL;
++      if (dentry) {
++              if (!dentry->d_inode) {
++                      struct sysfs_dirent * sd = dentry->d_fsdata;
++                      if ((inode = sysfs_new_inode(mode, sd))) {
++                              if (dentry->d_parent && dentry->d_parent->d_inode) {
++                                      struct inode *p_inode = dentry->d_parent->d_inode;
++                                      p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
++                              }
++                              goto Proceed;
++                      }
++                      else 
++                              error = -ENOMEM;
++              } else
++                      error = -EEXIST;
++      } else 
++              error = -ENOENT;
++      goto Done;
++
++ Proceed:
++      if (init)
++              error = init(inode);
++      if (!error) {
++              d_instantiate(dentry, inode);
++              if (S_ISDIR(mode))
++                      dget(dentry);  /* pin only directory dentry in core */
++      } else
++              iput(inode);
++ Done:
++      return error;
+ }
+-/**
+- *    sysfs_get_inode - get inode for sysfs_dirent
+- *    @sd: sysfs_dirent to allocate inode for
+- *
+- *    Get inode for @sd.  If such inode doesn't exist, a new inode
+- *    is allocated and basics are initialized.  New inode is
+- *    returned locked.
+- *
+- *    LOCKING:
+- *    Kernel thread context (may sleep).
+- *
+- *    RETURNS:
+- *    Pointer to allocated inode on success, NULL on failure.
++/*
++ * Get the name for corresponding element represented by the given sysfs_dirent
+  */
+-struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
++const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
+ {
+-      struct inode *inode;
++      struct attribute * attr;
++      struct bin_attribute * bin_attr;
++      struct sysfs_symlink  * sl;
 +
-+      mutex_lock(&container_mutex);
-+      put_css_group(cg);
-+      mutex_unlock(&container_mutex);
-+      deactivate_super(parent->root->sb);
-+      return ret;
-+}
++      BUG_ON(!sd || !sd->s_element);
 +
-+/* See if "cont" is a descendant of the current task's container in
-+ * the appropriate hierarchy */
++      switch (sd->s_type) {
++              case SYSFS_DIR:
++                      /* Always have a dentry so use that */
++                      return sd->s_dentry->d_name.name;
 +
-+int container_is_descendant(const struct container *cont)
-+{
-+      int ret;
-+      struct container *target;
-+      int subsys_id;
++              case SYSFS_KOBJ_ATTR:
++                      attr = sd->s_element;
++                      return attr->name;
 +
-+      if (cont == dummytop)
-+              return 1;
-+      get_first_subsys(cont, NULL, &subsys_id);
-+      target = task_container(current, subsys_id);
-+      while (cont != target && cont!= cont->top_container) {
-+              cont = cont->parent;
-+      }
-+      ret = (cont == target);
-+      return ret;
-+}
++              case SYSFS_KOBJ_BIN_ATTR:
++                      bin_attr = sd->s_element;
++                      return bin_attr->attr.name;
 +
-+static void check_for_release(struct container *cont)
-+{
-+      BUG_ON(!mutex_is_locked(&container_mutex));
-+      if (container_is_releasable(cont) && !atomic_read(&cont->count)
-+          && list_empty(&cont->children) && !container_has_css_refs(cont)) {
-+              /* Container is currently removeable. If it's not
-+               * already queued for a userspace notification, queue
-+               * it now */
-+              if (list_empty(&cont->release_list)) {
-+                      list_add(&cont->release_list, &release_list);
-+                      schedule_work(&release_agent_work);
-+              }
++              case SYSFS_KOBJ_LINK:
++                      sl = sd->s_element;
++                      return sl->link_name;
 +      }
++      return NULL;
 +}
-+
-+void css_put(struct container_subsys_state *css)
+-      inode = iget_locked(sysfs_sb, sd->s_ino);
+-      if (inode && (inode->i_state & I_NEW))
+-              sysfs_init_inode(sd, inode);
++static inline void orphan_all_buffers(struct inode *node)
 +{
-+      struct container *cont = css->container;
-+      if (notify_on_release(cont)) {
-+              mutex_lock(&container_mutex);
-+              set_bit(CONT_RELEASABLE, &cont->flags);
-+              if (atomic_dec_and_test(&css->refcnt)) {
-+                      check_for_release(cont);
++      struct sysfs_buffer_collection *set;
++      struct sysfs_buffer *buf;
+-      return inode;
++      mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD);
++      set = node->i_private;
++      if (set) {
++              list_for_each_entry(buf, &set->associates, associates) {
++                      down(&buf->sem);
++                      buf->orphaned = 1;
++                      up(&buf->sem);
 +              }
-+              mutex_unlock(&container_mutex);
-+      } else {
-+              atomic_dec(&css->refcnt);
 +      }
-+}
-+
-+void container_set_release_agent_path(struct container_subsys *ss,
-+                                    const char *path)
-+{
-+      mutex_lock(&container_mutex);
-+      strcpy(ss->root->release_agent_path, path);
-+      mutex_unlock(&container_mutex);
-+}
++      mutex_unlock(&node->i_mutex);
+ }
+-/**
+- *    sysfs_instantiate - instantiate dentry
+- *    @dentry: dentry to be instantiated
+- *    @inode: inode associated with @sd
+- *
+- *    Unlock @inode if locked and instantiate @dentry with @inode.
+- *
+- *    LOCKING:
+- *    None.
 +
 +/*
-+ * Notify userspace when a container is released, by running the
-+ * configured release agent with the name of the container (path
-+ * relative to the root of container file system) as the argument.
-+ *
-+ * Most likely, this user command will try to rmdir this container.
-+ *
-+ * This races with the possibility that some other task will be
-+ * attached to this container before it is removed, or that some other
-+ * user task will 'mkdir' a child container of this container.  That's ok.
-+ * The presumed 'rmdir' will fail quietly if this container is no longer
-+ * unused, and this container will be reprieved from its death sentence,
-+ * to continue to serve a useful existence.  Next time it's released,
-+ * we will get notified again, if it still has 'notify_on_release' set.
-+ *
-+ * The final arg to call_usermodehelper() is UMH_WAIT_EXEC, which
-+ * means only wait until the task is successfully execve()'d.  The
-+ * separate release agent task is forked by call_usermodehelper(),
-+ * then control in this thread returns here, without waiting for the
-+ * release agent task.  We don't bother to wait because the caller of
-+ * this routine has no use for the exit status of the release agent
-+ * task, so no sense holding our caller up for that.
-+ *
-+ */
++ * Unhashes the dentry corresponding to given sysfs_dirent
++ * Called with parent inode's i_mutex held.
+  */
+-void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
++void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
+ {
+-      BUG_ON(!dentry || dentry->d_inode);
++      struct dentry *dentry = NULL;
++      struct inode *inode;
+-      if (inode->i_state & I_NEW)
+-              unlock_new_inode(inode);
++      /* We're not holding a reference to ->s_dentry dentry but the
++       * field will stay valid as long as sysfs_lock is held.
++       */
++      spin_lock(&sysfs_lock);
++      spin_lock(&dcache_lock);
+-      d_instantiate(dentry, inode);
++      /* dget dentry if it's still alive */
++      if (sd->s_dentry && sd->s_dentry->d_inode)
++              dentry = dget_locked(sd->s_dentry);
 +
-+static void container_release_agent(struct work_struct *work)
-+{
-+      BUG_ON(work != &release_agent_work);
-+      mutex_lock(&container_mutex);
-+      while (!list_empty(&release_list)) {
-+              char *argv[3], *envp[3];
-+              int i;
-+              char *pathbuf;
-+              struct container *cont = list_entry(release_list.next,
-+                                                  struct container,
-+                                                  release_list);
-+              list_del_init(&cont->release_list);
-+
-+              pathbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-+              if (!pathbuf)
-+                      continue;
++      spin_unlock(&dcache_lock);
++      spin_unlock(&sysfs_lock);
 +
-+              if (container_path(cont, pathbuf, PAGE_SIZE) < 0) {
-+                      kfree(pathbuf);
-+                      continue;
++      /* drop dentry */
++      if (dentry) {
++              spin_lock(&dcache_lock);
++              spin_lock(&dentry->d_lock);
++              if (!d_unhashed(dentry) && dentry->d_inode) {
++                      inode = dentry->d_inode;
++                      spin_lock(&inode->i_lock);
++                      __iget(inode);
++                      spin_unlock(&inode->i_lock);
++                      dget_locked(dentry);
++                      __d_drop(dentry);
++                      spin_unlock(&dentry->d_lock);
++                      spin_unlock(&dcache_lock);
++                      simple_unlink(parent->d_inode, dentry);
++                      orphan_all_buffers(inode);
++                      iput(inode);
++              } else {
++                      spin_unlock(&dentry->d_lock);
++                      spin_unlock(&dcache_lock);
 +              }
 +
-+              i = 0;
-+              argv[i++] = cont->root->release_agent_path;
-+              argv[i++] = (char *)pathbuf;
-+              argv[i] = NULL;
-+
-+              i = 0;
-+              /* minimal command environment */
-+              envp[i++] = "HOME=/";
-+              envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-+              envp[i] = NULL;
-+
-+              /* Drop the lock while we invoke the usermode helper,
-+               * since the exec could involve hitting disk and hence
-+               * be a slow process */
-+              mutex_unlock(&container_mutex);
-+              call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
-+              kfree(pathbuf);
-+              mutex_lock(&container_mutex);
++              dput(dentry);
 +      }
-+      mutex_unlock(&container_mutex);
-+}
-diff -Nurb linux-2.6.22-570/kernel/container_debug.c linux-2.6.22-590/kernel/container_debug.c
---- linux-2.6.22-570/kernel/container_debug.c  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/kernel/container_debug.c  2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,89 @@
-+/*
-+ * kernel/ccontainer_debug.c - Example container subsystem that
-+ * exposes debug info
-+ *
-+ * Copyright (C) Google Inc, 2007
-+ *
-+ * Developed by Paul Menage (menage@google.com)
-+ *
-+ */
+ }
+-int sysfs_hash_and_remove(struct kobject *kobj, struct sysfs_dirent *dir_sd, const char *name)
++int sysfs_hash_and_remove(struct dentry * dir, const char * name)
+ {
+-      struct sysfs_addrm_cxt acxt;
+-      struct sysfs_dirent **pos, *sd;
++      struct sysfs_dirent * sd;
++      struct sysfs_dirent * parent_sd;
++      int found = 0;
+-      if (!dir_sd)
++      if (!dir)
+               return -ENOENT;
++      if (dir->d_inode == NULL)
++              /* no inode means this hasn't been made visible yet */
++              return -ENOENT;
+-      sysfs_addrm_start(&acxt, dir_sd);
+-      if (!sysfs_resolve_for_remove(kobj, &acxt.parent_sd))
+-              goto addrm_finish;
+-
+-      for (pos = &acxt.parent_sd->s_children; *pos; pos = &(*pos)->s_sibling) {
+-              sd = *pos;
+-
+-              if (!sysfs_type(sd))
++      parent_sd = dir->d_fsdata;
++      mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
++      list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
++              if (!sd->s_element)
+                       continue;
+-              if (!strcmp(sd->s_name, name)) {
+-                      *pos = sd->s_sibling;
+-                      sd->s_sibling = NULL;
+-                      sysfs_remove_one(&acxt, sd);
++              if (!strcmp(sysfs_get_name(sd), name)) {
++                      list_del_init(&sd->s_sibling);
++                      sysfs_drop_dentry(sd, dir);
++                      sysfs_put(sd);
++                      found = 1;
+                       break;
+               }
+       }
+-addrm_finish:
+-      if (sysfs_addrm_finish(&acxt))
+-              return 0;
+-      return -ENOENT;
++      mutex_unlock(&dir->d_inode->i_mutex);
 +
-+#include <linux/container.h>
-+#include <linux/fs.h>
++      return found ? 0 : -ENOENT;
+ }
+diff -Nurb linux-2.6.22-590/fs/sysfs/mount.c linux-2.6.22-570/fs/sysfs/mount.c
+--- linux-2.6.22-590/fs/sysfs/mount.c  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/sysfs/mount.c  2008-01-23 19:16:04.000000000 -0500
+@@ -17,18 +17,28 @@
+ struct super_block * sysfs_sb = NULL;
+ struct kmem_cache *sysfs_dir_cachep;
++static void sysfs_clear_inode(struct inode *inode);
 +
-+static int debug_create(struct container_subsys *ss, struct container *cont)
+ static const struct super_operations sysfs_ops = {
+       .statfs         = simple_statfs,
+-      .drop_inode     = generic_delete_inode,
++      .drop_inode     = sysfs_delete_inode,
++      .clear_inode    = sysfs_clear_inode,
+ };
+-struct sysfs_dirent sysfs_root = {
+-      .s_count        = ATOMIC_INIT(1),
+-      .s_flags        = SYSFS_ROOT,
+-      .s_mode         = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
++static struct sysfs_dirent sysfs_root = {
++      .s_sibling      = LIST_HEAD_INIT(sysfs_root.s_sibling),
++      .s_children     = LIST_HEAD_INIT(sysfs_root.s_children),
++      .s_element      = NULL,
++      .s_type         = SYSFS_ROOT,
++      .s_iattr        = NULL,
+       .s_ino          = 1,
+ };
++static void sysfs_clear_inode(struct inode *inode)
 +{
-+      struct container_subsys_state *css = kzalloc(sizeof(*css), GFP_KERNEL);
-+      if (!css)
-+              return -ENOMEM;
-+      cont->subsys[debug_subsys_id] = css;
-+      return 0;
++      kfree(inode->i_private);
 +}
 +
-+static void debug_destroy(struct container_subsys *ss, struct container *cont)
+ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
+ {
+       struct inode *inode;
+@@ -41,18 +51,17 @@
+       sb->s_time_gran = 1;
+       sysfs_sb = sb;
+-      inode = new_inode(sysfs_sb);
+-      if (!inode) {
+-              pr_debug("sysfs: could not get root inode\n");
+-              return -ENOMEM;
+-      }
+-
+-      sysfs_init_inode(&sysfs_root, inode);
+-
++      inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
++                               &sysfs_root);
++      if (inode) {
+               inode->i_op = &sysfs_dir_inode_operations;
+               inode->i_fop = &sysfs_dir_operations;
+               /* directory inodes start off with i_nlink == 2 (for "." entry) */
+               inc_nlink(inode);
++      } else {
++              pr_debug("sysfs: could not get root inode\n");
++              return -ENOMEM;
++      }
+       root = d_alloc_root(inode);
+       if (!root) {
+@@ -60,7 +69,6 @@
+               iput(inode);
+               return -ENOMEM;
+       }
+-      sysfs_root.s_dentry = root;
+       root->d_fsdata = &sysfs_root;
+       sb->s_root = root;
+       return 0;
+diff -Nurb linux-2.6.22-590/fs/sysfs/symlink.c linux-2.6.22-570/fs/sysfs/symlink.c
+--- linux-2.6.22-590/fs/sysfs/symlink.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/sysfs/symlink.c        2007-07-08 19:32:17.000000000 -0400
+@@ -11,49 +11,71 @@
+ #include "sysfs.h"
+-static int object_depth(struct sysfs_dirent *sd)
++static int object_depth(struct kobject * kobj)
+ {
++      struct kobject * p = kobj;
+       int depth = 0;
+-
+-      for (; sd->s_parent; sd = sd->s_parent) {
+-              if (sysfs_type(sd) == SYSFS_SHADOW_DIR)
+-                      continue;
+-              depth++;
+-      }
+-
++      do { depth++; } while ((p = p->parent));
+       return depth;
+ }
+-static int object_path_length(struct sysfs_dirent * sd)
++static int object_path_length(struct kobject * kobj)
+ {
++      struct kobject * p = kobj;
+       int length = 1;
+-
+-      for (; sd->s_parent; sd = sd->s_parent) {
+-              if (sysfs_type(sd) == SYSFS_SHADOW_DIR)
+-                      continue;
+-              length += strlen(sd->s_name) + 1;
+-      }
+-
++      do {
++              length += strlen(kobject_name(p)) + 1;
++              p = p->parent;
++      } while (p);
+       return length;
+ }
+-static void fill_object_path(struct sysfs_dirent *sd, char *buffer, int length)
++static void fill_object_path(struct kobject * kobj, char * buffer, int length)
+ {
+-      int cur;
+-      --length;
+-      for (; sd->s_parent; sd = sd->s_parent) {
+-              if (sysfs_type(sd) == SYSFS_SHADOW_DIR)
+-                      continue;
++      struct kobject * p;
+-              cur = strlen(sd->s_name);
++      --length;
++      for (p = kobj; p; p = p->parent) {
++              int cur = strlen(kobject_name(p));
+               /* back up enough to print this bus id with '/' */
+               length -= cur;
+-              strncpy(buffer + length, sd->s_name, cur);
++              strncpy(buffer + length,kobject_name(p),cur);
+               *(buffer + --length) = '/';
+       }
+ }
++static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target)
 +{
-+      kfree(cont->subsys[debug_subsys_id]);
-+}
++      struct sysfs_dirent * parent_sd = parent->d_fsdata;
++      struct sysfs_symlink * sl;
++      int error = 0;
 +
-+static u64 container_refcount_read(struct container *cont, struct cftype *cft)
-+{
-+      return atomic_read(&cont->count);
-+}
++      error = -ENOMEM;
++      sl = kmalloc(sizeof(*sl), GFP_KERNEL);
++      if (!sl)
++              goto exit1;
 +
-+static u64 taskcount_read(struct container *cont, struct cftype *cft)
-+{
-+      u64 count;
-+      container_lock();
-+      count = container_task_count(cont);
-+      container_unlock();
-+      return count;
-+}
++      sl->link_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
++      if (!sl->link_name)
++              goto exit2;
 +
-+static u64 current_css_group_read(struct container *cont, struct cftype *cft)
-+{
-+      return (u64) current->containers;
-+}
++      strcpy(sl->link_name, name);
++      sl->target_kobj = kobject_get(target);
 +
-+static u64 current_css_group_refcount_read(struct container *cont,
-+                                         struct cftype *cft)
-+{
-+      u64 count;
-+      rcu_read_lock();
-+      count = atomic_read(&current->containers->ref.refcount);
-+      rcu_read_unlock();
-+      return count;
++      error = sysfs_make_dirent(parent_sd, NULL, sl, S_IFLNK|S_IRWXUGO,
++                              SYSFS_KOBJ_LINK);
++      if (!error)
++              return 0;
++
++      kobject_put(target);
++      kfree(sl->link_name);
++exit2:
++      kfree(sl);
++exit1:
++      return error;
 +}
 +
-+static struct cftype files[] =  {
-+      {
-+              .name = "debug.container_refcount",
-+              .read_uint = container_refcount_read,
-+      },
-+      {
-+              .name = "debug.taskcount",
-+              .read_uint = taskcount_read,
-+      },
+ /**
+  *    sysfs_create_link - create symlink between two objects.
+  *    @kobj:  object whose directory we're creating the link in.
+@@ -62,80 +84,29 @@
+  */
+ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
+ {
+-      struct sysfs_dirent *parent_sd = NULL;
+-      struct sysfs_dirent *target_sd = NULL;
+-      struct sysfs_dirent *sd = NULL;
+-      struct sysfs_addrm_cxt acxt;
+-      int error;
++      struct dentry *dentry = NULL;
++      int error = -EEXIST;
+       BUG_ON(!name);
+       if (!kobj) {
+               if (sysfs_mount && sysfs_mount->mnt_sb)
+-                      parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
++                      dentry = sysfs_mount->mnt_sb->s_root;
+       } else
+-              parent_sd = kobj->sd;
+-
+-      error = -EFAULT;
+-      if (!parent_sd)
+-              goto out_put;
+-
+-      /* target->sd can go away beneath us but is protected with
+-       * sysfs_assoc_lock.  Fetch target_sd from it.
+-       */
+-      spin_lock(&sysfs_assoc_lock);
+-      if (target->sd)
+-              target_sd = sysfs_get(target->sd);
+-      spin_unlock(&sysfs_assoc_lock);
+-
+-      error = -ENOENT;
+-      if (!target_sd)
+-              goto out_put;
+-
+-      error = -ENOMEM;
+-      sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
+-      if (!sd)
+-              goto out_put;
+-      sd->s_elem.symlink.target_sd = target_sd;
+-
+-      sysfs_addrm_start(&acxt, parent_sd);
+-      if (!sysfs_resolve_for_create(target, &acxt.parent_sd))
+-              goto addrm_finish;
+-
+-      if (!sysfs_find_dirent(acxt.parent_sd, name)) {
+-              sysfs_add_one(&acxt, sd);
+-              sysfs_link_sibling(sd);
+-      }
++              dentry = kobj->dentry;
+-addrm_finish:
+-      if (sysfs_addrm_finish(&acxt))
+-              return 0;
++      if (!dentry)
++              return -EFAULT;
+-      error = -EEXIST;
+-      /* fall through */
+- out_put:
+-      sysfs_put(target_sd);
+-      sysfs_put(sd);
++      mutex_lock(&dentry->d_inode->i_mutex);
++      if (!sysfs_dirent_exist(dentry->d_fsdata, name))
++              error = sysfs_add_link(dentry, name, target);
++      mutex_unlock(&dentry->d_inode->i_mutex);
+       return error;
+ }
+ /**
+- *    sysfs_delete_link - remove symlink in object's directory.
+- *    @kobj:  object we're acting for.
+- *    @targ:  object we're pointing to.
+- *    @name:  name of the symlink to remove.
+- *
+- *    Unlike sysfs_remove_link sysfs_delete_link has enough information
+- *    to successfully delete symlinks in shadow directories.
+- */
+-void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
+-                      const char *name)
+-{
+-      sysfs_hash_and_remove(targ, kobj->sd, name);
+-}
+-
+-/**
+  *    sysfs_remove_link - remove symlink in object's directory.
+  *    @kobj:  object we're acting for.
+  *    @name:  name of the symlink to remove.
+@@ -143,33 +114,17 @@
+ void sysfs_remove_link(struct kobject * kobj, const char * name)
+ {
+-      sysfs_hash_and_remove(kobj, kobj->sd, name);
++      sysfs_hash_and_remove(kobj->dentry,name);
+ }
+-/**
+- *    sysfs_rename_link - rename symlink in object's directory.
+- *    @kobj:  object we're acting for.
+- *    @targ:  object we're pointing to.
+- *    @old:   previous name of the symlink.
+- *    @new:   new name of the symlink.
+- *
+- *    A helper function for the common rename symlink idiom.
+- */
+-int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
+-                      const char *old, const char *new)
+-{
+-      sysfs_delete_link(kobj, targ, old);
+-      return sysfs_create_link(kobj, targ, new);
+-}
+-
+-static int sysfs_get_target_path(struct sysfs_dirent * parent_sd,
+-                               struct sysfs_dirent * target_sd, char *path)
++static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
++                               char *path)
+ {
+       char * s;
+       int depth, size;
+-      depth = object_depth(parent_sd);
+-      size = object_path_length(target_sd) + depth * 3 - 1;
++      depth = object_depth(kobj);
++      size = object_path_length(target) + depth * 3 - 1;
+       if (size > PATH_MAX)
+               return -ENAMETOOLONG;
+@@ -178,7 +133,7 @@
+       for (s = path; depth--; s += 3)
+               strcpy(s,"../");
+-      fill_object_path(target_sd, path, size);
++      fill_object_path(target, path, size);
+       pr_debug("%s: path = '%s'\n", __FUNCTION__, path);
+       return 0;
+@@ -186,16 +141,27 @@
+ static int sysfs_getlink(struct dentry *dentry, char * path)
+ {
+-      struct sysfs_dirent *sd = dentry->d_fsdata;
+-      struct sysfs_dirent *parent_sd = sd->s_parent;
+-      struct sysfs_dirent *target_sd = sd->s_elem.symlink.target_sd;
+-      int error;
+-
+-      mutex_lock(&sysfs_mutex);
+-      error = sysfs_get_target_path(parent_sd, target_sd, path);
+-      mutex_unlock(&sysfs_mutex);
++      struct kobject *kobj, *target_kobj;
++      int error = 0;
 +
-+      {
-+              .name = "debug.current_css_group",
-+              .read_uint = current_css_group_read,
-+      },
++      kobj = sysfs_get_kobject(dentry->d_parent);
++      if (!kobj)
++              return -EINVAL;
 +
-+      {
-+              .name = "debug.current_css_group_refcount",
-+              .read_uint = current_css_group_refcount_read,
-+      },
++      target_kobj = sysfs_get_kobject(dentry);
++      if (!target_kobj) {
++              kobject_put(kobj);
++              return -EINVAL;
++      }
++      down_read(&sysfs_rename_sem);
++      error = sysfs_get_target_path(kobj, target_kobj, path);
++      up_read(&sysfs_rename_sem);
++      
++      kobject_put(kobj);
++      kobject_put(target_kobj);
+       return error;
++
+ }
+ static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+diff -Nurb linux-2.6.22-590/fs/sysfs/sysfs.h linux-2.6.22-570/fs/sysfs/sysfs.h
+--- linux-2.6.22-590/fs/sysfs/sysfs.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/sysfs/sysfs.h  2007-07-08 19:32:17.000000000 -0400
+@@ -1,40 +1,9 @@
+-struct sysfs_elem_dir {
+-      struct kobject          * kobj;
+-};
+-
+-struct sysfs_elem_symlink {
+-      struct sysfs_dirent     * target_sd;
+-};
+-
+-struct sysfs_elem_attr {
+-      struct attribute        * attr;
+-};
+-
+-struct sysfs_elem_bin_attr {
+-      struct bin_attribute    * bin_attr;
+-};
+-
+-/*
+- * As long as s_count reference is held, the sysfs_dirent itself is
+- * accessible.  Dereferencing s_elem or any other outer entity
+- * requires s_active reference.
+- */
+ struct sysfs_dirent {
+       atomic_t                s_count;
+-      atomic_t                s_active;
+-      struct sysfs_dirent     * s_parent;
+-      struct sysfs_dirent     * s_sibling;
+-      struct sysfs_dirent     * s_children;
+-      const char              * s_name;
+-
+-      union {
+-              struct sysfs_elem_dir           dir;
+-              struct sysfs_elem_symlink       symlink;
+-              struct sysfs_elem_attr          attr;
+-              struct sysfs_elem_bin_attr      bin_attr;
+-      }                       s_elem;
+-
+-      unsigned int            s_flags;
++      struct list_head        s_sibling;
++      struct list_head        s_children;
++      void                    * s_element;
++      int                     s_type;
+       umode_t                 s_mode;
+       ino_t                   s_ino;
+       struct dentry           * s_dentry;
+@@ -42,77 +11,30 @@
+       atomic_t                s_event;
+ };
+-#define SD_DEACTIVATED_BIAS   INT_MIN
+-
+-struct sysfs_addrm_cxt {
+-      struct sysfs_dirent     *parent_sd;
+-      struct inode            *parent_inode;
+-      struct sysfs_dirent     *removed;
+-      int                     cnt;
+-};
+-
+-/*
+- * A sysfs file which deletes another file when written to need to
+- * write lock the s_active of the victim while its s_active is read
+- * locked for the write operation.  Tell lockdep that this is okay.
+- */
+-enum sysfs_s_active_class
+-{
+-      SYSFS_S_ACTIVE_NORMAL,          /* file r/w access, etc - default */
+-      SYSFS_S_ACTIVE_DEACTIVATE,      /* file deactivation */
+-};
+-
+ extern struct vfsmount * sysfs_mount;
+-extern struct sysfs_dirent sysfs_root;
+ extern struct kmem_cache *sysfs_dir_cachep;
+-extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
+-extern void sysfs_link_sibling(struct sysfs_dirent *sd);
+-extern void sysfs_unlink_sibling(struct sysfs_dirent *sd);
+-
+-extern int sysfs_resolve_for_create(struct kobject *kobj,
+-                                  struct sysfs_dirent **parent_sd);
+-extern int sysfs_resolve_for_remove(struct kobject *kobj,
+-                                  struct sysfs_dirent **parent_sd);
+-
+-extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
+-extern void sysfs_put_active(struct sysfs_dirent *sd);
+-extern struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
+-extern void sysfs_put_active_two(struct sysfs_dirent *sd);
+-extern void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
+-                            struct sysfs_dirent *parent_sd);
+-extern void sysfs_add_one(struct sysfs_addrm_cxt *acxt,
+-                        struct sysfs_dirent *sd);
+-extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt,
+-                           struct sysfs_dirent *sd);
+-extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
+-
+-extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode);
+-extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd);
+-extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode);
+-
+-extern void release_sysfs_dirent(struct sysfs_dirent * sd);
+-extern struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
+-                                            const unsigned char *name);
+-extern struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+-                                           const unsigned char *name);
+-extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode,
+-                                           int type);
+-
+-extern int sysfs_add_file(struct sysfs_dirent *dir_sd,
+-                        const struct attribute *attr, int type);
+-extern int sysfs_hash_and_remove(struct kobject *kobj,
+-                               struct sysfs_dirent *dir_sd, const char *name);
++extern void sysfs_delete_inode(struct inode *inode);
++extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
++extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
++
++extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
++extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
++                              umode_t, int);
++
++extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
++extern int sysfs_hash_and_remove(struct dentry * dir, const char * name);
+ extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
+-extern int sysfs_create_subdir(struct kobject *kobj, const char *name,
+-                             struct sysfs_dirent **p_sd);
+-extern void sysfs_remove_subdir(struct sysfs_dirent *sd);
++extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
++extern void sysfs_remove_subdir(struct dentry *);
++extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
++extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
+ extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
+-extern spinlock_t sysfs_assoc_lock;
+-extern struct mutex sysfs_mutex;
++extern spinlock_t sysfs_lock;
++extern struct rw_semaphore sysfs_rename_sem;
+ extern struct super_block * sysfs_sb;
+ extern const struct file_operations sysfs_dir_operations;
+ extern const struct file_operations sysfs_file_operations;
+@@ -120,9 +42,73 @@
+ extern const struct inode_operations sysfs_dir_inode_operations;
+ extern const struct inode_operations sysfs_symlink_inode_operations;
+-static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
++struct sysfs_symlink {
++      char * link_name;
++      struct kobject * target_kobj;
 +};
 +
-+static int debug_populate(struct container_subsys *ss, struct container *cont)
-+{
-+      return container_add_files(cont, files, ARRAY_SIZE(files));
-+}
-+
-+struct container_subsys debug_subsys = {
-+      .name = "debug",
-+      .create = debug_create,
-+      .destroy = debug_destroy,
-+      .populate = debug_populate,
-+      .subsys_id = debug_subsys_id,
++struct sysfs_buffer {
++      struct list_head                associates;
++      size_t                          count;
++      loff_t                          pos;
++      char                            * page;
++      struct sysfs_ops                * ops;
++      struct semaphore                sem;
++      int                             orphaned;
++      int                             needs_read_fill;
++      int                             event;
 +};
-diff -Nurb linux-2.6.22-570/kernel/cpu_acct.c linux-2.6.22-590/kernel/cpu_acct.c
---- linux-2.6.22-570/kernel/cpu_acct.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/kernel/cpu_acct.c 2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,185 @@
-+/*
-+ * kernel/cpu_acct.c - CPU accounting container subsystem
-+ *
-+ * Copyright (C) Google Inc, 2006
-+ *
-+ * Developed by Paul Menage (menage@google.com) and Balbir Singh
-+ * (balbir@in.ibm.com)
-+ *
-+ */
-+
-+/*
-+ * Example container subsystem for reporting total CPU usage of tasks in a
-+ * container, along with percentage load over a time interval
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/container.h>
-+#include <linux/fs.h>
-+#include <asm/div64.h>
-+
-+struct cpuacct {
-+      struct container_subsys_state css;
-+      spinlock_t lock;
-+      /* total time used by this class */
-+      cputime64_t time;
-+
-+      /* time when next load calculation occurs */
-+      u64 next_interval_check;
 +
-+      /* time used in current period */
-+      cputime64_t current_interval_time;
-+
-+      /* time used in last period */
-+      cputime64_t last_interval_time;
++struct sysfs_buffer_collection {
++      struct list_head        associates;
 +};
 +
-+struct container_subsys cpuacct_subsys;
-+
-+static inline struct cpuacct *container_ca(struct container *cont)
-+{
-+      return container_of(container_subsys_state(cont, cpuacct_subsys_id),
-+                          struct cpuacct, css);
-+}
-+
-+static inline struct cpuacct *task_ca(struct task_struct *task)
++static inline struct kobject * to_kobj(struct dentry * dentry)
 +{
-+      return container_of(task_subsys_state(task, cpuacct_subsys_id),
-+                          struct cpuacct, css);
-+}
-+
-+#define INTERVAL (HZ * 10)
-+
-+static inline u64 next_interval_boundary(u64 now) {
-+      /* calculate the next interval boundary beyond the
-+       * current time */
-+      do_div(now, INTERVAL);
-+      return (now + 1) * INTERVAL;
++      struct sysfs_dirent * sd = dentry->d_fsdata;
++      return ((struct kobject *) sd->s_element);
 +}
 +
-+static int cpuacct_create(struct container_subsys *ss, struct container *cont)
++static inline struct attribute * to_attr(struct dentry * dentry)
 +{
-+      struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
-+      if (!ca)
-+              return -ENOMEM;
-+      spin_lock_init(&ca->lock);
-+      ca->next_interval_check = next_interval_boundary(get_jiffies_64());
-+      cont->subsys[cpuacct_subsys_id] = &ca->css;
-+      return 0;
++      struct sysfs_dirent * sd = dentry->d_fsdata;
++      return ((struct attribute *) sd->s_element);
 +}
 +
-+static void cpuacct_destroy(struct container_subsys *ss,
-+                          struct container *cont)
++static inline struct bin_attribute * to_bin_attr(struct dentry * dentry)
 +{
-+      kfree(container_ca(cont));
++      struct sysfs_dirent * sd = dentry->d_fsdata;
++      return ((struct bin_attribute *) sd->s_element);
 +}
 +
-+/* Lazily update the load calculation if necessary. Called with ca locked */
-+static void cpuusage_update(struct cpuacct *ca)
-+{
-+      u64 now = get_jiffies_64();
-+      /* If we're not due for an update, return */
-+      if (ca->next_interval_check > now)
-+              return;
++static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
+ {
+-      return sd->s_flags & SYSFS_TYPE_MASK;
++      struct kobject * kobj = NULL;
 +
-+      if (ca->next_interval_check <= (now - INTERVAL)) {
-+              /* If it's been more than an interval since the last
-+               * check, then catch up - the last interval must have
-+               * been zero load */
-+              ca->last_interval_time = 0;
-+              ca->next_interval_check = next_interval_boundary(now);
-+      } else {
-+              /* If a steal takes the last interval time negative,
-+               * then we just ignore it */
-+              if ((s64)ca->current_interval_time > 0) {
-+                      ca->last_interval_time = ca->current_interval_time;
-+              } else {
-+                      ca->last_interval_time = 0;
-+              }
-+              ca->next_interval_check += INTERVAL;
++      spin_lock(&dcache_lock);
++      if (!d_unhashed(dentry)) {
++              struct sysfs_dirent * sd = dentry->d_fsdata;
++              if (sd->s_type & SYSFS_KOBJ_LINK) {
++                      struct sysfs_symlink * sl = sd->s_element;
++                      kobj = kobject_get(sl->target_kobj);
++              } else
++                      kobj = kobject_get(sd->s_element);
 +      }
-+      ca->current_interval_time = 0;
-+}
-+
-+static u64 cpuusage_read(struct container *cont,
-+                       struct cftype *cft)
-+{
-+      struct cpuacct *ca = container_ca(cont);
-+      u64 time;
-+
-+      spin_lock_irq(&ca->lock);
-+      cpuusage_update(ca);
-+      time = cputime64_to_jiffies64(ca->time);
-+      spin_unlock_irq(&ca->lock);
++      spin_unlock(&dcache_lock);
 +
-+      /* Convert 64-bit jiffies to seconds */
-+      time *= 1000;
-+      do_div(time, HZ);
-+      return time;
++      return kobj;
 +}
 +
-+static u64 load_read(struct container *cont,
-+                   struct cftype *cft)
++static inline void release_sysfs_dirent(struct sysfs_dirent * sd)
 +{
-+      struct cpuacct *ca = container_ca(cont);
-+      u64 time;
-+
-+      /* Find the time used in the previous interval */
-+      spin_lock_irq(&ca->lock);
-+      cpuusage_update(ca);
-+      time = cputime64_to_jiffies64(ca->last_interval_time);
-+      spin_unlock_irq(&ca->lock);
-+
-+      /* Convert time to a percentage, to give the load in the
-+       * previous period */
-+      time *= 100;
-+      do_div(time, INTERVAL);
-+
-+      return time;
-+}
-+
-+static struct cftype files[] = {
-+      {
-+              .name = "cpuacct.usage",
-+              .read_uint = cpuusage_read,
-+      },
-+      {
-+              .name = "cpuacct.load",
-+              .read_uint = load_read,
++      if (sd->s_type & SYSFS_KOBJ_LINK) {
++              struct sysfs_symlink * sl = sd->s_element;
++              kfree(sl->link_name);
++              kobject_put(sl->target_kobj);
++              kfree(sl);
 +      }
-+};
-+
-+static int cpuacct_populate(struct container_subsys *ss,
-+                          struct container *cont)
-+{
-+      return container_add_files(cont, files, ARRAY_SIZE(files));
-+}
++      kfree(sd->s_iattr);
++      kmem_cache_free(sysfs_dir_cachep, sd);
+ }
+ static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
+@@ -136,6 +122,11 @@
+ static inline void sysfs_put(struct sysfs_dirent * sd)
+ {
+-      if (sd && atomic_dec_and_test(&sd->s_count))
++      if (atomic_dec_and_test(&sd->s_count))
+               release_sysfs_dirent(sd);
+ }
 +
-+void cpuacct_charge(struct task_struct *task, cputime_t cputime)
++static inline int sysfs_is_shadowed_inode(struct inode *inode)
 +{
-+
-+      struct cpuacct *ca;
-+      unsigned long flags;
-+
-+      if (!cpuacct_subsys.active)
-+              return;
-+      rcu_read_lock();
-+      ca = task_ca(task);
-+      if (ca) {
-+              spin_lock_irqsave(&ca->lock, flags);
-+              cpuusage_update(ca);
-+              ca->time = cputime64_add(ca->time, cputime);
-+              ca->current_interval_time =
-+                      cputime64_add(ca->current_interval_time, cputime);
-+              spin_unlock_irqrestore(&ca->lock, flags);
-+      }
-+      rcu_read_unlock();
++      return S_ISDIR(inode->i_mode) && inode->i_op->follow_link;
 +}
-+
-+struct container_subsys cpuacct_subsys = {
-+      .name = "cpuacct",
-+      .create = cpuacct_create,
-+      .destroy = cpuacct_destroy,
-+      .populate = cpuacct_populate,
-+      .subsys_id = cpuacct_subsys_id,
-+};
-diff -Nurb linux-2.6.22-570/kernel/cpuset.c linux-2.6.22-590/kernel/cpuset.c
---- linux-2.6.22-570/kernel/cpuset.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/kernel/cpuset.c   2008-01-02 13:56:37.000000000 -0500
-@@ -5,6 +5,7 @@
-  *
-  *  Copyright (C) 2003 BULL SA.
-  *  Copyright (C) 2004-2006 Silicon Graphics, Inc.
-+ *  Copyright (C) 2006 Google, Inc
-  *
-  *  Portions derived from Patrick Mochel's sysfs code.
-  *  sysfs is Copyright (c) 2001-3 Patrick Mochel
-@@ -12,6 +13,7 @@
-  *  2003-10-10 Written by Simon Derr.
-  *  2003-10-22 Updates by Stephen Hemminger.
-  *  2004 May-July Rework by Paul Jackson.
-+ *  2006 Rework by Paul Menage to use generic containers
-  *
-  *  This file is subject to the terms and conditions of the GNU General Public
-  *  License.  See the file COPYING in the main directory of the Linux
-@@ -53,8 +55,6 @@
- #include <asm/atomic.h>
- #include <linux/mutex.h>
--#define CPUSET_SUPER_MAGIC            0x27e0eb
+diff -Nurb linux-2.6.22-590/fs/unionfs/Makefile linux-2.6.22-570/fs/unionfs/Makefile
+--- linux-2.6.22-590/fs/unionfs/Makefile       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/Makefile       1969-12-31 19:00:00.000000000 -0500
+@@ -1,7 +0,0 @@
+-obj-$(CONFIG_UNION_FS) += unionfs.o
+-
+-unionfs-y := subr.o dentry.o file.o inode.o main.o super.o \
+-      rdstate.o copyup.o dirhelper.o rename.o unlink.o \
+-      lookup.o commonfops.o dirfops.o sioq.o mmap.o
+-
+-unionfs-$(CONFIG_UNION_FS_XATTR) += xattr.o
+diff -Nurb linux-2.6.22-590/fs/unionfs/commonfops.c linux-2.6.22-570/fs/unionfs/commonfops.c
+--- linux-2.6.22-590/fs/unionfs/commonfops.c   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/commonfops.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,748 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/*
+- * 1) Copyup the file
+- * 2) Rename the file to '.unionfs<original inode#><counter>' - obviously
+- * stolen from NFS's silly rename
+- */
+-static int copyup_deleted_file(struct file *file, struct dentry *dentry,
+-                             int bstart, int bindex)
+-{
+-      static unsigned int counter;
+-      const int i_inosize = sizeof(dentry->d_inode->i_ino) * 2;
+-      const int countersize = sizeof(counter) * 2;
+-      const int nlen = sizeof(".unionfs") + i_inosize + countersize - 1;
+-      char name[nlen + 1];
+-
+-      int err;
+-      struct dentry *tmp_dentry = NULL;
+-      struct dentry *hidden_dentry;
+-      struct dentry *hidden_dir_dentry = NULL;
+-
+-      hidden_dentry = unionfs_lower_dentry_idx(dentry, bstart);
+-
+-      sprintf(name, ".unionfs%*.*lx",
+-              i_inosize, i_inosize, hidden_dentry->d_inode->i_ino);
+-
+-retry:
+-      /*
+-       * Loop, looking for an unused temp name to copyup to.
+-       *
+-       * It's somewhat silly that we look for a free temp tmp name in the
+-       * source branch (bstart) instead of the dest branch (bindex), where
+-       * the final name will be created.  We _will_ catch it if somehow
+-       * the name exists in the dest branch, but it'd be nice to catch it
+-       * sooner than later.
+-       */
+-      tmp_dentry = NULL;
+-      do {
+-              char *suffix = name + nlen - countersize;
+-
+-              dput(tmp_dentry);
+-              counter++;
+-              sprintf(suffix, "%*.*x", countersize, countersize, counter);
+-
+-              printk(KERN_DEBUG "unionfs: trying to rename %s to %s\n",
+-                     dentry->d_name.name, name);
+-
+-              tmp_dentry = lookup_one_len(name, hidden_dentry->d_parent,
+-                                          nlen);
+-              if (IS_ERR(tmp_dentry)) {
+-                      err = PTR_ERR(tmp_dentry);
+-                      goto out;
+-              }
+-      } while (tmp_dentry->d_inode != NULL);  /* need negative dentry */
+-      dput(tmp_dentry);
+-
+-      err = copyup_named_file(dentry->d_parent->d_inode, file, name, bstart,
+-                              bindex, file->f_dentry->d_inode->i_size);
+-      if (err == -EEXIST)
+-              goto retry;
+-      else if (err)
+-              goto out;
+-
+-      /* bring it to the same state as an unlinked file */
+-      hidden_dentry = unionfs_lower_dentry_idx(dentry, dbstart(dentry));
+-      hidden_dir_dentry = lock_parent(hidden_dentry);
+-      err = vfs_unlink(hidden_dir_dentry->d_inode, hidden_dentry);
+-      unlock_dir(hidden_dir_dentry);
+-
+-out:
+-      return err;
+-}
+-
+-/*
+- * put all references held by upper struct file and free lower file pointer
+- * array
+- */
+-static void cleanup_file(struct file *file)
+-{
+-      int bindex, bstart, bend;
+-      struct file **lf;
+-      struct super_block *sb = file->f_dentry->d_sb;
+-
+-      lf = UNIONFS_F(file)->lower_files;
+-      bstart = fbstart(file);
+-      bend = fbend(file);
+-
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              if (unionfs_lower_file_idx(file, bindex)) {
+-                      /*
+-                       * Find new index of matching branch with an open
+-                       * file, since branches could have been added or
+-                       * deleted causing the one with open files to shift.
+-                       */
+-                      int i;  /* holds (possibly) updated branch index */
+-                      int old_bid;
+-
+-                      old_bid = UNIONFS_F(file)->saved_branch_ids[bindex];
+-                      i = branch_id_to_idx(sb, old_bid);
+-                      if (i < 0)
+-                              printk(KERN_ERR "unionfs: no superblock for "
+-                                     "file %p\n", file);
+-                      else {
+-                              /* decrement count of open files */
+-                              branchput(sb, i);
+-                              /*
+-                               * fput will perform an mntput for us on the
+-                               * correct branch.  Although we're using the
+-                               * file's old branch configuration, bindex,
+-                               * which is the old index, correctly points
+-                               * to the right branch in the file's branch
+-                               * list.  In other words, we're going to
+-                               * mntput the correct branch even if
+-                               * branches have been added/removed.
+-                               */
+-                              fput(unionfs_lower_file_idx(file, bindex));
+-                      }
+-              }
+-      }
+-
+-      UNIONFS_F(file)->lower_files = NULL;
+-      kfree(lf);
+-      kfree(UNIONFS_F(file)->saved_branch_ids);
+-      /* set to NULL because caller needs to know if to kfree on error */
+-      UNIONFS_F(file)->saved_branch_ids = NULL;
+-}
+-
+-/* open all lower files for a given file */
+-static int open_all_files(struct file *file)
+-{
+-      int bindex, bstart, bend, err = 0;
+-      struct file *hidden_file;
+-      struct dentry *hidden_dentry;
+-      struct dentry *dentry = file->f_dentry;
+-      struct super_block *sb = dentry->d_sb;
+-
+-      bstart = dbstart(dentry);
+-      bend = dbend(dentry);
+-
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (!hidden_dentry)
+-                      continue;
+-
+-              dget(hidden_dentry);
+-              unionfs_mntget(dentry, bindex);
+-              branchget(sb, bindex);
+-
+-              hidden_file =
+-                      dentry_open(hidden_dentry,
+-                                  unionfs_lower_mnt_idx(dentry, bindex),
+-                                  file->f_flags);
+-              if (IS_ERR(hidden_file)) {
+-                      err = PTR_ERR(hidden_file);
+-                      goto out;
+-              } else
+-                      unionfs_set_lower_file_idx(file, bindex, hidden_file);
+-      }
+-out:
+-      return err;
+-}
+-
+-/* open the highest priority file for a given upper file */
+-static int open_highest_file(struct file *file, int willwrite)
+-{
+-      int bindex, bstart, bend, err = 0;
+-      struct file *hidden_file;
+-      struct dentry *hidden_dentry;
+-
+-      struct dentry *dentry = file->f_dentry;
+-      struct inode *parent_inode = dentry->d_parent->d_inode;
+-      struct super_block *sb = dentry->d_sb;
+-      size_t inode_size = dentry->d_inode->i_size;
+-
+-      bstart = dbstart(dentry);
+-      bend = dbend(dentry);
+-
+-      hidden_dentry = unionfs_lower_dentry(dentry);
+-      if (willwrite && IS_WRITE_FLAG(file->f_flags) && is_robranch(dentry)) {
+-              for (bindex = bstart - 1; bindex >= 0; bindex--) {
+-                      err = copyup_file(parent_inode, file, bstart, bindex,
+-                                        inode_size);
+-                      if (!err)
+-                              break;
+-              }
+-              atomic_set(&UNIONFS_F(file)->generation,
+-                         atomic_read(&UNIONFS_I(dentry->d_inode)->
+-                                     generation));
+-              goto out;
+-      }
+-
+-      dget(hidden_dentry);
+-      unionfs_mntget(dentry, bstart);
+-      branchget(sb, bstart);
+-      hidden_file = dentry_open(hidden_dentry,
+-                                unionfs_lower_mnt_idx(dentry, bstart),
+-                                file->f_flags);
+-      if (IS_ERR(hidden_file)) {
+-              err = PTR_ERR(hidden_file);
+-              goto out;
+-      }
+-      unionfs_set_lower_file(file, hidden_file);
+-      /* Fix up the position. */
+-      hidden_file->f_pos = file->f_pos;
+-
+-      memcpy(&hidden_file->f_ra, &file->f_ra, sizeof(struct file_ra_state));
+-out:
+-      return err;
+-}
+-
+-/* perform a delayed copyup of a read-write file on a read-only branch */
+-static int do_delayed_copyup(struct file *file, struct dentry *dentry)
+-{
+-      int bindex, bstart, bend, err = 0;
+-      struct inode *parent_inode = dentry->d_parent->d_inode;
+-      loff_t inode_size = file->f_dentry->d_inode->i_size;
+-
+-      bstart = fbstart(file);
+-      bend = fbend(file);
+-
+-      BUG_ON(!S_ISREG(file->f_dentry->d_inode->i_mode));
+-
+-      for (bindex = bstart - 1; bindex >= 0; bindex--) {
+-              if (!d_deleted(file->f_dentry))
+-                      err = copyup_file(parent_inode, file, bstart,
+-                                        bindex, inode_size);
+-              else
+-                      err = copyup_deleted_file(file, dentry, bstart,
+-                                                bindex);
+-
+-              if (!err)
+-                      break;
+-      }
+-      if (!err && (bstart > fbstart(file))) {
+-              bend = fbend(file);
+-              for (bindex = bstart; bindex <= bend; bindex++) {
+-                      if (unionfs_lower_file_idx(file, bindex)) {
+-                              branchput(dentry->d_sb, bindex);
+-                              fput(unionfs_lower_file_idx(file, bindex));
+-                              unionfs_set_lower_file_idx(file, bindex, NULL);
+-                      }
+-              }
+-              fbend(file) = bend;
+-      }
+-      return err;
+-}
+-
+-/*
+- * Revalidate the struct file
+- * @file: file to revalidate
+- * @willwrite: 1 if caller may cause changes to the file; 0 otherwise.
+- */
+-int unionfs_file_revalidate(struct file *file, int willwrite)
+-{
+-      struct super_block *sb;
+-      struct dentry *dentry;
+-      int sbgen, fgen, dgen;
+-      int bstart, bend;
+-      int size;
+-
+-      int err = 0;
+-
+-      dentry = file->f_dentry;
+-      unionfs_lock_dentry(dentry);
+-      sb = dentry->d_sb;
+-
+-      /*
+-       * First revalidate the dentry inside struct file,
+-       * but not unhashed dentries.
+-       */
+-      if (!d_deleted(dentry) &&
+-          !__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out_nofree;
+-      }
+-
+-      sbgen = atomic_read(&UNIONFS_SB(sb)->generation);
+-      dgen = atomic_read(&UNIONFS_D(dentry)->generation);
+-      fgen = atomic_read(&UNIONFS_F(file)->generation);
+-
+-      BUG_ON(sbgen > dgen);
+-
+-      /*
+-       * There are two cases we are interested in.  The first is if the
+-       * generation is lower than the super-block.  The second is if
+-       * someone has copied up this file from underneath us, we also need
+-       * to refresh things.
+-       */
+-      if (!d_deleted(dentry) &&
+-          (sbgen > fgen || dbstart(dentry) != fbstart(file))) {
+-              /* First we throw out the existing files. */
+-              cleanup_file(file);
+-
+-              /* Now we reopen the file(s) as in unionfs_open. */
+-              bstart = fbstart(file) = dbstart(dentry);
+-              bend = fbend(file) = dbend(dentry);
+-
+-              size = sizeof(struct file *) * sbmax(sb);
+-              UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
+-              if (!UNIONFS_F(file)->lower_files) {
+-                      err = -ENOMEM;
+-                      goto out;
+-              }
+-              size = sizeof(int) * sbmax(sb);
+-              UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
+-              if (!UNIONFS_F(file)->saved_branch_ids) {
+-                      err = -ENOMEM;
+-                      goto out;
+-              }
+-
+-              if (S_ISDIR(dentry->d_inode->i_mode)) {
+-                      /* We need to open all the files. */
+-                      err = open_all_files(file);
+-                      if (err)
+-                              goto out;
+-              } else {
+-                      /* We only open the highest priority branch. */
+-                      err = open_highest_file(file, willwrite);
+-                      if (err)
+-                              goto out;
+-              }
+-              atomic_set(&UNIONFS_F(file)->generation,
+-                         atomic_read(&UNIONFS_I(dentry->d_inode)->
+-                                     generation));
+-      }
+-
+-      /* Copyup on the first write to a file on a readonly branch. */
+-      if (willwrite && IS_WRITE_FLAG(file->f_flags) &&
+-          !IS_WRITE_FLAG(unionfs_lower_file(file)->f_flags) &&
+-          is_robranch(dentry)) {
+-              printk(KERN_DEBUG "unionfs: Doing delayed copyup of a "
+-                     "read-write file on a read-only branch.\n");
+-              err = do_delayed_copyup(file, dentry);
+-      }
+-
+-out:
+-      if (err) {
+-              kfree(UNIONFS_F(file)->lower_files);
+-              kfree(UNIONFS_F(file)->saved_branch_ids);
+-      }
+-out_nofree:
+-      unionfs_unlock_dentry(dentry);
+-      return err;
+-}
+-
+-/* unionfs_open helper function: open a directory */
+-static int __open_dir(struct inode *inode, struct file *file)
+-{
+-      struct dentry *hidden_dentry;
+-      struct file *hidden_file;
+-      int bindex, bstart, bend;
+-
+-      bstart = fbstart(file) = dbstart(file->f_dentry);
+-      bend = fbend(file) = dbend(file->f_dentry);
+-
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_dentry =
+-                      unionfs_lower_dentry_idx(file->f_dentry, bindex);
+-              if (!hidden_dentry)
+-                      continue;
+-
+-              dget(hidden_dentry);
+-              unionfs_mntget(file->f_dentry, bindex);
+-              hidden_file = dentry_open(hidden_dentry,
+-                                        unionfs_lower_mnt_idx(file->f_dentry,
+-                                                              bindex),
+-                                        file->f_flags);
+-              if (IS_ERR(hidden_file))
+-                      return PTR_ERR(hidden_file);
+-
+-              unionfs_set_lower_file_idx(file, bindex, hidden_file);
+-
+-              /*
+-               * The branchget goes after the open, because otherwise
+-               * we would miss the reference on release.
+-               */
+-              branchget(inode->i_sb, bindex);
+-      }
+-
+-      return 0;
+-}
+-
+-/* unionfs_open helper function: open a file */
+-static int __open_file(struct inode *inode, struct file *file)
+-{
+-      struct dentry *hidden_dentry;
+-      struct file *hidden_file;
+-      int hidden_flags;
+-      int bindex, bstart, bend;
+-
+-      hidden_dentry = unionfs_lower_dentry(file->f_dentry);
+-      hidden_flags = file->f_flags;
+-
+-      bstart = fbstart(file) = dbstart(file->f_dentry);
+-      bend = fbend(file) = dbend(file->f_dentry);
+-
+-      /*
+-       * check for the permission for hidden file.  If the error is
+-       * COPYUP_ERR, copyup the file.
+-       */
+-      if (hidden_dentry->d_inode && is_robranch(file->f_dentry)) {
+-              /*
+-               * if the open will change the file, copy it up otherwise
+-               * defer it.
+-               */
+-              if (hidden_flags & O_TRUNC) {
+-                      int size = 0;
+-                      int err = -EROFS;
+-
+-                      /* copyup the file */
+-                      for (bindex = bstart - 1; bindex >= 0; bindex--) {
+-                              err = copyup_file(
+-                                      file->f_dentry->d_parent->d_inode,
+-                                      file, bstart, bindex, size);
+-                              if (!err)
+-                                      break;
+-                      }
+-                      return err;
+-              } else
+-                      hidden_flags &= ~(OPEN_WRITE_FLAGS);
+-      }
+-
+-      dget(hidden_dentry);
+-
+-      /*
+-       * dentry_open will decrement mnt refcnt if err.
+-       * otherwise fput() will do an mntput() for us upon file close.
+-       */
+-      unionfs_mntget(file->f_dentry, bstart);
+-      hidden_file =
+-              dentry_open(hidden_dentry,
+-                          unionfs_lower_mnt_idx(file->f_dentry, bstart),
+-                          hidden_flags);
+-      if (IS_ERR(hidden_file))
+-              return PTR_ERR(hidden_file);
+-
+-      unionfs_set_lower_file(file, hidden_file);
+-      branchget(inode->i_sb, bstart);
+-
+-      return 0;
+-}
+-
+-int unionfs_open(struct inode *inode, struct file *file)
+-{
+-      int err = 0;
+-      struct file *hidden_file = NULL;
+-      struct dentry *dentry = NULL;
+-      int bindex = 0, bstart = 0, bend = 0;
+-      int size;
+-
+-      unionfs_read_lock(inode->i_sb);
+-
+-      file->private_data =
+-              kzalloc(sizeof(struct unionfs_file_info), GFP_KERNEL);
+-      if (!UNIONFS_F(file)) {
+-              err = -ENOMEM;
+-              goto out_nofree;
+-      }
+-      fbstart(file) = -1;
+-      fbend(file) = -1;
+-      atomic_set(&UNIONFS_F(file)->generation,
+-                 atomic_read(&UNIONFS_I(inode)->generation));
+-
+-      size = sizeof(struct file *) * sbmax(inode->i_sb);
+-      UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
+-      if (!UNIONFS_F(file)->lower_files) {
+-              err = -ENOMEM;
+-              goto out;
+-      }
+-      size = sizeof(int) * sbmax(inode->i_sb);
+-      UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
+-      if (!UNIONFS_F(file)->saved_branch_ids) {
+-              err = -ENOMEM;
+-              goto out;
+-      }
+-
+-      dentry = file->f_dentry;
+-      unionfs_lock_dentry(dentry);
+-
+-      bstart = fbstart(file) = dbstart(dentry);
+-      bend = fbend(file) = dbend(dentry);
+-
+-      /* increment, so that we can flush appropriately */
+-      atomic_inc(&UNIONFS_I(dentry->d_inode)->totalopens);
+-
+-      /*
+-       * open all directories and make the unionfs file struct point to
+-       * these hidden file structs
+-       */
+-      if (S_ISDIR(inode->i_mode))
+-              err = __open_dir(inode, file);  /* open a dir */
+-      else
+-              err = __open_file(inode, file); /* open a file */
+-
+-      /* freeing the allocated resources, and fput the opened files */
+-      if (err) {
+-              atomic_dec(&UNIONFS_I(dentry->d_inode)->totalopens);
+-              for (bindex = bstart; bindex <= bend; bindex++) {
+-                      hidden_file = unionfs_lower_file_idx(file, bindex);
+-                      if (!hidden_file)
+-                              continue;
+-
+-                      branchput(file->f_dentry->d_sb, bindex);
+-                      /* fput calls dput for hidden_dentry */
+-                      fput(hidden_file);
+-              }
+-      }
+-
+-      unionfs_unlock_dentry(dentry);
+-
+-out:
+-      if (err) {
+-              kfree(UNIONFS_F(file)->lower_files);
+-              kfree(UNIONFS_F(file)->saved_branch_ids);
+-              kfree(UNIONFS_F(file));
+-      }
+-out_nofree:
+-      unionfs_read_unlock(inode->i_sb);
+-      return err;
+-}
+-
+-/*
+- * release all lower object references & free the file info structure
+- *
+- * No need to grab sb info's rwsem.
+- */
+-int unionfs_file_release(struct inode *inode, struct file *file)
+-{
+-      struct file *hidden_file = NULL;
+-      struct unionfs_file_info *fileinfo;
+-      struct unionfs_inode_info *inodeinfo;
+-      struct super_block *sb = inode->i_sb;
+-      int bindex, bstart, bend;
+-      int fgen;
+-      int err;
+-
+-      unionfs_read_lock(sb);
+-      /*
+-       * Yes, we have to revalidate this file even if it's being released.
+-       * This is important for open-but-unlinked files, as well as mmap
+-       * support.
+-       */
+-      if ((err = unionfs_file_revalidate(file, 1)))
+-              return err;
+-      fileinfo = UNIONFS_F(file);
+-      BUG_ON(file->f_dentry->d_inode != inode);
+-      inodeinfo = UNIONFS_I(inode);
+-
+-      /* fput all the hidden files */
+-      fgen = atomic_read(&fileinfo->generation);
+-      bstart = fbstart(file);
+-      bend = fbend(file);
+-
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_file = unionfs_lower_file_idx(file, bindex);
+-
+-              if (hidden_file) {
+-                      fput(hidden_file);
+-                      branchput(inode->i_sb, bindex);
+-              }
+-      }
+-      kfree(fileinfo->lower_files);
+-      kfree(fileinfo->saved_branch_ids);
+-
+-      if (fileinfo->rdstate) {
+-              fileinfo->rdstate->access = jiffies;
+-              printk(KERN_DEBUG "unionfs: saving rdstate with cookie "
+-                     "%u [%d.%lld]\n",
+-                     fileinfo->rdstate->cookie,
+-                     fileinfo->rdstate->bindex,
+-                     (long long)fileinfo->rdstate->dirpos);
+-              spin_lock(&inodeinfo->rdlock);
+-              inodeinfo->rdcount++;
+-              list_add_tail(&fileinfo->rdstate->cache,
+-                            &inodeinfo->readdircache);
+-              mark_inode_dirty(inode);
+-              spin_unlock(&inodeinfo->rdlock);
+-              fileinfo->rdstate = NULL;
+-      }
+-      kfree(fileinfo);
+-      return 0;
+-}
+-
+-/* pass the ioctl to the lower fs */
+-static long do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+-{
+-      struct file *hidden_file;
+-      int err;
+-
+-      hidden_file = unionfs_lower_file(file);
+-
+-      err = security_file_ioctl(hidden_file, cmd, arg);
+-      if (err)
+-              goto out;
+-
+-      err = -ENOTTY;
+-      if (!hidden_file || !hidden_file->f_op)
+-              goto out;
+-      if (hidden_file->f_op->unlocked_ioctl) {
+-              err = hidden_file->f_op->unlocked_ioctl(hidden_file, cmd, arg);
+-      } else if (hidden_file->f_op->ioctl) {
+-              lock_kernel();
+-              err = hidden_file->f_op->ioctl(hidden_file->f_dentry->d_inode,
+-                                             hidden_file, cmd, arg);
+-              unlock_kernel();
+-      }
+-
+-out:
+-      return err;
+-}
+-
+-/*
+- * return to user-space the branch indices containing the file in question
+- *
+- * We use fd_set and therefore we are limited to the number of the branches
+- * to FD_SETSIZE, which is currently 1024 - plenty for most people
+- */
+-static int unionfs_ioctl_queryfile(struct file *file, unsigned int cmd,
+-                                 unsigned long arg)
+-{
+-      int err = 0;
+-      fd_set branchlist;
+-
+-      int bstart = 0, bend = 0, bindex = 0;
+-      struct dentry *dentry, *hidden_dentry;
+-
+-      dentry = file->f_dentry;
+-      unionfs_lock_dentry(dentry);
+-      if ((err = unionfs_partial_lookup(dentry)))
+-              goto out;
+-      bstart = dbstart(dentry);
+-      bend = dbend(dentry);
+-
+-      FD_ZERO(&branchlist);
+-
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (!hidden_dentry)
+-                      continue;
+-              if (hidden_dentry->d_inode)
+-                      FD_SET(bindex, &branchlist);
+-      }
+-
+-      err = copy_to_user((void __user *)arg, &branchlist, sizeof(fd_set));
+-      if (err)
+-              err = -EFAULT;
+-
+-out:
+-      unionfs_unlock_dentry(dentry);
+-      return err < 0 ? err : bend;
+-}
+-
+-long unionfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+-{
+-      long err;
+-
+-      unionfs_read_lock(file->f_path.dentry->d_sb);
+-
+-      if ((err = unionfs_file_revalidate(file, 1)))
+-              goto out;
+-
+-      /* check if asked for local commands */
+-      switch (cmd) {
+-      case UNIONFS_IOCTL_INCGEN:
+-              /* Increment the superblock generation count */
+-              printk("unionfs: incgen ioctl deprecated; "
+-                     "use \"-o remount,incgen\"\n");
+-              err = -ENOSYS;
+-              break;
+-
+-      case UNIONFS_IOCTL_QUERYFILE:
+-              /* Return list of branches containing the given file */
+-              err = unionfs_ioctl_queryfile(file, cmd, arg);
+-              break;
+-
+-      default:
+-              /* pass the ioctl down */
+-              err = do_ioctl(file, cmd, arg);
+-              break;
+-      }
+-
+-out:
+-      unionfs_read_unlock(file->f_path.dentry->d_sb);
+-      return err;
+-}
+-
+-int unionfs_flush(struct file *file, fl_owner_t id)
+-{
+-      int err = 0;
+-      struct file *hidden_file = NULL;
+-      struct dentry *dentry = file->f_dentry;
+-      int bindex, bstart, bend;
+-
+-      unionfs_read_lock(file->f_path.dentry->d_sb);
+-
+-      if ((err = unionfs_file_revalidate(file, 1)))
+-              goto out;
+-
+-      if (!atomic_dec_and_test(&UNIONFS_I(dentry->d_inode)->totalopens))
+-              goto out;
+-
+-      unionfs_lock_dentry(dentry);
+-
+-      bstart = fbstart(file);
+-      bend = fbend(file);
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_file = unionfs_lower_file_idx(file, bindex);
+-
+-              if (hidden_file && hidden_file->f_op &&
+-                  hidden_file->f_op->flush) {
+-                      err = hidden_file->f_op->flush(hidden_file, id);
+-                      if (err)
+-                              goto out_lock;
+-
+-                      /* if there are no more refs to the dentry, dput it */
+-                      if (d_deleted(dentry)) {
+-                              dput(unionfs_lower_dentry_idx(dentry, bindex));
+-                              unionfs_set_lower_dentry_idx(dentry, bindex,
+-                                                           NULL);
+-                      }
+-              }
+-
+-      }
+-
+-out_lock:
+-      unionfs_unlock_dentry(dentry);
+-out:
+-      unionfs_read_unlock(file->f_path.dentry->d_sb);
+-      return err;
+-}
+diff -Nurb linux-2.6.22-590/fs/unionfs/copyup.c linux-2.6.22-570/fs/unionfs/copyup.c
+--- linux-2.6.22-590/fs/unionfs/copyup.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/copyup.c       1969-12-31 19:00:00.000000000 -0500
+@@ -1,806 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/*
+- * For detailed explanation of copyup see:
+- * Documentation/filesystems/unionfs/concepts.txt
+- */
+-
+-/* forward definitions */
+-static int copyup_named_dentry(struct inode *dir, struct dentry *dentry,
+-                             int bstart, int new_bindex, const char *name,
+-                             int namelen, struct file **copyup_file,
+-                             loff_t len);
+-static struct dentry *create_parents_named(struct inode *dir,
+-                                         struct dentry *dentry,
+-                                         const char *name, int bindex);
+-
+-#ifdef CONFIG_UNION_FS_XATTR
+-/* copyup all extended attrs for a given dentry */
+-static int copyup_xattrs(struct dentry *old_hidden_dentry,
+-                       struct dentry *new_hidden_dentry)
+-{
+-      int err = 0;
+-      ssize_t list_size = -1;
+-      char *name_list = NULL;
+-      char *attr_value = NULL;
+-      char *name_list_orig = NULL;
+-
+-      list_size = vfs_listxattr(old_hidden_dentry, NULL, 0);
+-
+-      if (list_size <= 0) {
+-              err = list_size;
+-              goto out;
+-      }
+-
+-      name_list = unionfs_xattr_alloc(list_size + 1, XATTR_LIST_MAX);
+-      if (!name_list || IS_ERR(name_list)) {
+-              err = PTR_ERR(name_list);
+-              goto out;
+-      }
+-      list_size = vfs_listxattr(old_hidden_dentry, name_list, list_size);
+-      attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX);
+-      if (!attr_value || IS_ERR(attr_value)) {
+-              err = PTR_ERR(name_list);
+-              goto out;
+-      }
+-      name_list_orig = name_list;
+-      while (*name_list) {
+-              ssize_t size;
+-
+-              /* Lock here since vfs_getxattr doesn't lock for us */
+-              mutex_lock(&old_hidden_dentry->d_inode->i_mutex);
+-              size = vfs_getxattr(old_hidden_dentry, name_list,
+-                                  attr_value, XATTR_SIZE_MAX);
+-              mutex_unlock(&old_hidden_dentry->d_inode->i_mutex);
+-              if (size < 0) {
+-                      err = size;
+-                      goto out;
+-              }
+-
+-              if (size > XATTR_SIZE_MAX) {
+-                      err = -E2BIG;
+-                      goto out;
+-              }
+-              /* Don't lock here since vfs_setxattr does it for us. */
+-              err = vfs_setxattr(new_hidden_dentry, name_list, attr_value,
+-                                 size, 0);
+-
+-              if (err < 0)
+-                      goto out;
+-              name_list += strlen(name_list) + 1;
+-      }
+-out:
+-      name_list = name_list_orig;
+-
+-      if (name_list)
+-              unionfs_xattr_free(name_list, list_size + 1);
+-      if (attr_value)
+-              unionfs_xattr_free(attr_value, XATTR_SIZE_MAX);
+-      /* It is no big deal if this fails, we just roll with the punches. */
+-      if (err == -ENOTSUPP || err == -EOPNOTSUPP)
+-              err = 0;
+-      return err;
+-}
+-#endif /* CONFIG_UNION_FS_XATTR */
+-
+-/* Determine the mode based on the copyup flags, and the existing dentry. */
+-static int copyup_permissions(struct super_block *sb,
+-                            struct dentry *old_hidden_dentry,
+-                            struct dentry *new_hidden_dentry)
+-{
+-      struct inode *i = old_hidden_dentry->d_inode;
+-      struct iattr newattrs;
+-      int err;
+-
+-      newattrs.ia_atime = i->i_atime;
+-      newattrs.ia_mtime = i->i_mtime;
+-      newattrs.ia_ctime = i->i_ctime;
+-
+-      newattrs.ia_gid = i->i_gid;
+-      newattrs.ia_uid = i->i_uid;
+-
+-      newattrs.ia_mode = i->i_mode;
+-
+-      newattrs.ia_valid = ATTR_CTIME | ATTR_ATIME | ATTR_MTIME |
+-              ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_FORCE |
+-              ATTR_GID | ATTR_UID | ATTR_MODE;
+-
+-      err = notify_change(new_hidden_dentry, &newattrs);
+-
+-      return err;
+-}
+-
+-int copyup_dentry(struct inode *dir, struct dentry *dentry,
+-                int bstart, int new_bindex,
+-                struct file **copyup_file, loff_t len)
+-{
+-      return copyup_named_dentry(dir, dentry, bstart, new_bindex,
+-                                 dentry->d_name.name,
+-                                 dentry->d_name.len, copyup_file, len);
+-}
+-
+-/*
+- * create the new device/file/directory - use copyup_permission to copyup
+- * times, and mode
+- *
+- * if the object being copied up is a regular file, the file is only created,
+- * the contents have to be copied up separately
+- */
+-static int __copyup_ndentry(struct dentry *old_hidden_dentry,
+-                          struct dentry *new_hidden_dentry,
+-                          struct dentry *new_hidden_parent_dentry,
+-                          char *symbuf)
+-{
+-      int err = 0;
+-      umode_t old_mode = old_hidden_dentry->d_inode->i_mode;
+-      struct sioq_args args;
+-
+-      if (S_ISDIR(old_mode)) {
+-              args.mkdir.parent = new_hidden_parent_dentry->d_inode;
+-              args.mkdir.dentry = new_hidden_dentry;
+-              args.mkdir.mode = old_mode;
+-
+-              run_sioq(__unionfs_mkdir, &args);
+-              err = args.err;
+-      } else if (S_ISLNK(old_mode)) {
+-              args.symlink.parent = new_hidden_parent_dentry->d_inode;
+-              args.symlink.dentry = new_hidden_dentry;
+-              args.symlink.symbuf = symbuf;
+-              args.symlink.mode = old_mode;
+-
+-              run_sioq(__unionfs_symlink, &args);
+-              err = args.err;
+-      } else if (S_ISBLK(old_mode) || S_ISCHR(old_mode) ||
+-                 S_ISFIFO(old_mode) || S_ISSOCK(old_mode)) {
+-              args.mknod.parent = new_hidden_parent_dentry->d_inode;
+-              args.mknod.dentry = new_hidden_dentry;
+-              args.mknod.mode = old_mode;
+-              args.mknod.dev = old_hidden_dentry->d_inode->i_rdev;
+-
+-              run_sioq(__unionfs_mknod, &args);
+-              err = args.err;
+-      } else if (S_ISREG(old_mode)) {
+-              args.create.parent = new_hidden_parent_dentry->d_inode;
+-              args.create.dentry = new_hidden_dentry;
+-              args.create.mode = old_mode;
+-              args.create.nd = NULL;
+-
+-              run_sioq(__unionfs_create, &args);
+-              err = args.err;
+-      } else {
+-              printk(KERN_ERR "unionfs: unknown inode type %d\n",
+-                     old_mode);
+-              BUG();
+-      }
+-
+-      return err;
+-}
+-
+-static int __copyup_reg_data(struct dentry *dentry,
+-                           struct dentry *new_hidden_dentry, int new_bindex,
+-                           struct dentry *old_hidden_dentry, int old_bindex,
+-                           struct file **copyup_file, loff_t len)
+-{
+-      struct super_block *sb = dentry->d_sb;
+-      struct file *input_file;
+-      struct file *output_file;
+-      mm_segment_t old_fs;
+-      char *buf = NULL;
+-      ssize_t read_bytes, write_bytes;
+-      loff_t size;
+-      int err = 0;
+-
+-      /* open old file */
+-      unionfs_mntget(dentry, old_bindex);
+-      branchget(sb, old_bindex);
+-      input_file = dentry_open(old_hidden_dentry,
+-                               unionfs_lower_mnt_idx(dentry, old_bindex),
+-                               O_RDONLY | O_LARGEFILE);
+-      if (IS_ERR(input_file)) {
+-              dput(old_hidden_dentry);
+-              err = PTR_ERR(input_file);
+-              goto out;
+-      }
+-      if (!input_file->f_op || !input_file->f_op->read) {
+-              err = -EINVAL;
+-              goto out_close_in;
+-      }
+-
+-      /* open new file */
+-      dget(new_hidden_dentry);
+-      unionfs_mntget(dentry, new_bindex);
+-      branchget(sb, new_bindex);
+-      output_file = dentry_open(new_hidden_dentry,
+-                                unionfs_lower_mnt_idx(dentry, new_bindex),
+-                                O_WRONLY | O_LARGEFILE);
+-      if (IS_ERR(output_file)) {
+-              err = PTR_ERR(output_file);
+-              goto out_close_in2;
+-      }
+-      if (!output_file->f_op || !output_file->f_op->write) {
+-              err = -EINVAL;
+-              goto out_close_out;
+-      }
+-
+-      /* allocating a buffer */
+-      buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+-      if (!buf) {
+-              err = -ENOMEM;
+-              goto out_close_out;
+-      }
+-
+-      input_file->f_pos = 0;
+-      output_file->f_pos = 0;
+-
+-      old_fs = get_fs();
+-      set_fs(KERNEL_DS);
+-
+-      size = len;
+-      err = 0;
+-      do {
+-              if (len >= PAGE_SIZE)
+-                      size = PAGE_SIZE;
+-              else if ((len < PAGE_SIZE) && (len > 0))
+-                      size = len;
+-
+-              len -= PAGE_SIZE;
+-
+-              read_bytes =
+-                      input_file->f_op->read(input_file,
+-                                             (char __user *)buf, size,
+-                                             &input_file->f_pos);
+-              if (read_bytes <= 0) {
+-                      err = read_bytes;
+-                      break;
+-              }
+-
+-              write_bytes =
+-                      output_file->f_op->write(output_file,
+-                                               (char __user *)buf,
+-                                               read_bytes,
+-                                               &output_file->f_pos);
+-              if ((write_bytes < 0) || (write_bytes < read_bytes)) {
+-                      err = write_bytes;
+-                      break;
+-              }
+-      } while ((read_bytes > 0) && (len > 0));
+-
+-      set_fs(old_fs);
+-
+-      kfree(buf);
+-
+-      if (!err)
+-              err = output_file->f_op->fsync(output_file,
+-                                             new_hidden_dentry, 0);
+-
+-      if (err)
+-              goto out_close_out;
+-
+-      if (copyup_file) {
+-              *copyup_file = output_file;
+-              goto out_close_in;
+-      }
+-
+-out_close_out:
+-      fput(output_file);
+-
+-out_close_in2:
+-      branchput(sb, new_bindex);
+-
+-out_close_in:
+-      fput(input_file);
+-
+-out:
+-      branchput(sb, old_bindex);
+-
+-      return err;
+-}
+-
+-/*
+- * dput the lower references for old and new dentry & clear a lower dentry
+- * pointer
+- */
+-static void __clear(struct dentry *dentry, struct dentry *old_hidden_dentry,
+-                  int old_bstart, int old_bend,
+-                  struct dentry *new_hidden_dentry, int new_bindex)
+-{
+-      /* get rid of the hidden dentry and all its traces */
+-      unionfs_set_lower_dentry_idx(dentry, new_bindex, NULL);
+-      set_dbstart(dentry, old_bstart);
+-      set_dbend(dentry, old_bend);
+-
+-      dput(new_hidden_dentry);
+-      dput(old_hidden_dentry);
+-}
+-
+-/* copy up a dentry to a file of specified name */
+-static int copyup_named_dentry(struct inode *dir, struct dentry *dentry,
+-                             int bstart, int new_bindex, const char *name,
+-                             int namelen, struct file **copyup_file,
+-                             loff_t len)
+-{
+-      struct dentry *new_hidden_dentry;
+-      struct dentry *old_hidden_dentry = NULL;
+-      struct super_block *sb;
+-      int err = 0;
+-      int old_bindex;
+-      int old_bstart;
+-      int old_bend;
+-      struct dentry *new_hidden_parent_dentry = NULL;
+-      mm_segment_t oldfs;
+-      char *symbuf = NULL;
+-
+-      verify_locked(dentry);
+-
+-      old_bindex = bstart;
+-      old_bstart = dbstart(dentry);
+-      old_bend = dbend(dentry);
+-
+-      BUG_ON(new_bindex < 0);
+-      BUG_ON(new_bindex >= old_bindex);
+-
+-      sb = dir->i_sb;
+-
+-      if ((err = is_robranch_super(sb, new_bindex)))
+-              goto out;
+-
+-      /* Create the directory structure above this dentry. */
+-      new_hidden_dentry =
+-              create_parents_named(dir, dentry, name, new_bindex);
+-      if (IS_ERR(new_hidden_dentry)) {
+-              err = PTR_ERR(new_hidden_dentry);
+-              goto out;
+-      }
+-
+-      old_hidden_dentry = unionfs_lower_dentry_idx(dentry, old_bindex);
+-      /* we conditionally dput this old_hidden_dentry at end of function */
+-      dget(old_hidden_dentry);
+-
+-      /* For symlinks, we must read the link before we lock the directory. */
+-      if (S_ISLNK(old_hidden_dentry->d_inode->i_mode)) {
+-
+-              symbuf = kmalloc(PATH_MAX, GFP_KERNEL);
+-              if (!symbuf) {
+-                      __clear(dentry, old_hidden_dentry,
+-                              old_bstart, old_bend,
+-                              new_hidden_dentry, new_bindex);
+-                      err = -ENOMEM;
+-                      goto out_free;
+-              }
+-
+-              oldfs = get_fs();
+-              set_fs(KERNEL_DS);
+-              err = old_hidden_dentry->d_inode->i_op->readlink(
+-                      old_hidden_dentry,
+-                      (char __user *)symbuf,
+-                      PATH_MAX);
+-              set_fs(oldfs);
+-              if (err) {
+-                      __clear(dentry, old_hidden_dentry,
+-                              old_bstart, old_bend,
+-                              new_hidden_dentry, new_bindex);
+-                      goto out_free;
+-              }
+-              symbuf[err] = '\0';
+-      }
+-
+-      /* Now we lock the parent, and create the object in the new branch. */
+-      new_hidden_parent_dentry = lock_parent(new_hidden_dentry);
+-
+-      /* create the new inode */
+-      err = __copyup_ndentry(old_hidden_dentry, new_hidden_dentry,
+-                             new_hidden_parent_dentry, symbuf);
+-
+-      if (err) {
+-              __clear(dentry, old_hidden_dentry,
+-                      old_bstart, old_bend,
+-                      new_hidden_dentry, new_bindex);
+-              goto out_unlock;
+-      }
+-
+-      /* We actually copyup the file here. */
+-      if (S_ISREG(old_hidden_dentry->d_inode->i_mode))
+-              err = __copyup_reg_data(dentry, new_hidden_dentry, new_bindex,
+-                                      old_hidden_dentry, old_bindex,
+-                                      copyup_file, len);
+-      if (err)
+-              goto out_unlink;
+-
+-      /* Set permissions. */
+-      if ((err = copyup_permissions(sb, old_hidden_dentry,
+-                                    new_hidden_dentry)))
+-              goto out_unlink;
+-
+-#ifdef CONFIG_UNION_FS_XATTR
+-      /* Selinux uses extended attributes for permissions. */
+-      if ((err = copyup_xattrs(old_hidden_dentry, new_hidden_dentry)))
+-              goto out_unlink;
+-#endif
+-
+-      /* do not allow files getting deleted to be re-interposed */
+-      if (!d_deleted(dentry))
+-              unionfs_reinterpose(dentry);
+-
+-      goto out_unlock;
+-
+-out_unlink:
+-      /*
+-       * copyup failed, because we possibly ran out of space or
+-       * quota, or something else happened so let's unlink; we don't
+-       * really care about the return value of vfs_unlink
+-       */
+-      vfs_unlink(new_hidden_parent_dentry->d_inode, new_hidden_dentry);
+-
+-      if (copyup_file) {
+-              /* need to close the file */
+-
+-              fput(*copyup_file);
+-              branchput(sb, new_bindex);
+-      }
+-
+-      /*
+-       * TODO: should we reset the error to something like -EIO?
+-       *
+-       * If we don't reset, the user may get some nonsensical errors, but
+-       * on the other hand, if we reset to EIO, we guarantee that the user
+-       * will get a "confusing" error message.
+-       */
+-
+-out_unlock:
+-      unlock_dir(new_hidden_parent_dentry);
+-
+-out_free:
+-      /*
+-       * If old_hidden_dentry was a directory, we need to dput it.  If it
+-       * was a file, then it was already dput indirectly by other
+-       * functions we call above which operate on regular files.
+-       */
+-      if (old_hidden_dentry && old_hidden_dentry->d_inode &&
+-          S_ISDIR(old_hidden_dentry->d_inode->i_mode))
+-              dput(old_hidden_dentry);
+-      kfree(symbuf);
+-
+-out:
+-      return err;
+-}
+-
+-/*
+- * This function creates a copy of a file represented by 'file' which
+- * currently resides in branch 'bstart' to branch 'new_bindex.'  The copy
+- * will be named "name".
+- */
+-int copyup_named_file(struct inode *dir, struct file *file, char *name,
+-                    int bstart, int new_bindex, loff_t len)
+-{
+-      int err = 0;
+-      struct file *output_file = NULL;
+-
+-      err = copyup_named_dentry(dir, file->f_dentry, bstart,
+-                                new_bindex, name, strlen(name), &output_file,
+-                                len);
+-      if (!err) {
+-              fbstart(file) = new_bindex;
+-              unionfs_set_lower_file_idx(file, new_bindex, output_file);
+-      }
+-
+-      return err;
+-}
+-
+-/*
+- * This function creates a copy of a file represented by 'file' which
+- * currently resides in branch 'bstart' to branch 'new_bindex'.
+- */
+-int copyup_file(struct inode *dir, struct file *file, int bstart,
+-              int new_bindex, loff_t len)
+-{
+-      int err = 0;
+-      struct file *output_file = NULL;
+-
+-      err = copyup_dentry(dir, file->f_dentry, bstart, new_bindex,
+-                          &output_file, len);
+-      if (!err) {
+-              fbstart(file) = new_bindex;
+-              unionfs_set_lower_file_idx(file, new_bindex, output_file);
+-      }
+-
+-      return err;
+-}
+-
+-/*
+- * This function replicates the directory structure up-to given dentry in the
+- * bindex branch. Can create directory structure recursively to the right
+- * also.
+- */
+-struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
+-                            int bindex)
+-{
+-      return create_parents_named(dir, dentry, dentry->d_name.name, bindex);
+-}
+-
+-/* purge a dentry's lower-branch states (dput/mntput, etc.) */
+-static void __cleanup_dentry(struct dentry *dentry, int bindex,
+-                           int old_bstart, int old_bend)
+-{
+-      int loop_start;
+-      int loop_end;
+-      int new_bstart = -1;
+-      int new_bend = -1;
+-      int i;
+-
+-      loop_start = min(old_bstart, bindex);
+-      loop_end = max(old_bend, bindex);
+-
+-      /*
+-       * This loop sets the bstart and bend for the new dentry by
+-       * traversing from left to right.  It also dputs all negative
+-       * dentries except bindex
+-       */
+-      for (i = loop_start; i <= loop_end; i++) {
+-              if (!unionfs_lower_dentry_idx(dentry, i))
+-                      continue;
+-
+-              if (i == bindex) {
+-                      new_bend = i;
+-                      if (new_bstart < 0)
+-                              new_bstart = i;
+-                      continue;
+-              }
+-
+-              if (!unionfs_lower_dentry_idx(dentry, i)->d_inode) {
+-                      dput(unionfs_lower_dentry_idx(dentry, i));
+-                      unionfs_set_lower_dentry_idx(dentry, i, NULL);
+-
+-                      unionfs_mntput(dentry, i);
+-                      unionfs_set_lower_mnt_idx(dentry, i, NULL);
+-              } else {
+-                      if (new_bstart < 0)
+-                              new_bstart = i;
+-                      new_bend = i;
+-              }
+-      }
+-
+-      if (new_bstart < 0)
+-              new_bstart = bindex;
+-      if (new_bend < 0)
+-              new_bend = bindex;
+-      set_dbstart(dentry, new_bstart);
+-      set_dbend(dentry, new_bend);
+-
+-}
+-
+-/* set lower inode ptr and update bstart & bend if necessary */
+-static void __set_inode(struct dentry *upper, struct dentry *lower,
+-                      int bindex)
+-{
+-      unionfs_set_lower_inode_idx(upper->d_inode, bindex,
+-                                  igrab(lower->d_inode));
+-      if (likely(ibstart(upper->d_inode) > bindex))
+-              ibstart(upper->d_inode) = bindex;
+-      if (likely(ibend(upper->d_inode) < bindex))
+-              ibend(upper->d_inode) = bindex;
+-
+-}
+-
+-/* set lower dentry ptr and update bstart & bend if necessary */
+-static void __set_dentry(struct dentry *upper, struct dentry *lower,
+-                       int bindex)
+-{
+-      unionfs_set_lower_dentry_idx(upper, bindex, lower);
+-      if (likely(dbstart(upper) > bindex))
+-              set_dbstart(upper, bindex);
+-      if (likely(dbend(upper) < bindex))
+-              set_dbend(upper, bindex);
+-}
+-
+-/*
+- * This function replicates the directory structure up-to given dentry
+- * in the bindex branch.
+- */
+-static struct dentry *create_parents_named(struct inode *dir,
+-                                         struct dentry *dentry,
+-                                         const char *name, int bindex)
+-{
+-      int err;
+-      struct dentry *child_dentry;
+-      struct dentry *parent_dentry;
+-      struct dentry *hidden_parent_dentry = NULL;
+-      struct dentry *hidden_dentry = NULL;
+-      const char *childname;
+-      unsigned int childnamelen;
+-
+-      int nr_dentry;
+-      int count = 0;
+-
+-      int old_bstart;
+-      int old_bend;
+-      struct dentry **path = NULL;
+-      struct super_block *sb;
+-
+-      verify_locked(dentry);
+-
+-      if ((err = is_robranch_super(dir->i_sb, bindex))) {
+-              hidden_dentry = ERR_PTR(err);
+-              goto out;
+-      }
+-
+-      old_bstart = dbstart(dentry);
+-      old_bend = dbend(dentry);
+-
+-      hidden_dentry = ERR_PTR(-ENOMEM);
+-
+-      /* There is no sense allocating any less than the minimum. */
+-      nr_dentry = 1;
+-      path = kmalloc(nr_dentry * sizeof(struct dentry *), GFP_KERNEL);
+-      if (!path)
+-              goto out;
+-
+-      /* assume the negative dentry of unionfs as the parent dentry */
+-      parent_dentry = dentry;
+-
+-      /*
+-       * This loop finds the first parent that exists in the given branch.
+-       * We start building the directory structure from there.  At the end
+-       * of the loop, the following should hold:
+-       *  - child_dentry is the first nonexistent child
+-       *  - parent_dentry is the first existent parent
+-       *  - path[0] is the = deepest child
+-       *  - path[count] is the first child to create
+-       */
+-      do {
+-              child_dentry = parent_dentry;
+-
+-              /* find the parent directory dentry in unionfs */
+-              parent_dentry = child_dentry->d_parent;
+-              unionfs_lock_dentry(parent_dentry);
+-
+-              /* find out the hidden_parent_dentry in the given branch */
+-              hidden_parent_dentry =
+-                      unionfs_lower_dentry_idx(parent_dentry, bindex);
+-
+-              /* grow path table */
+-              if (count == nr_dentry) {
+-                      void *p;
+-
+-                      nr_dentry *= 2;
+-                      p = krealloc(path, nr_dentry * sizeof(struct dentry *), GFP_KERNEL);
+-                      if (!p) {
+-                              hidden_dentry = ERR_PTR(-ENOMEM);
+-                              goto out;
+-                      }
+-                      path = p;
+-              }
+-
+-              /* store the child dentry */
+-              path[count++] = child_dentry;
+-      } while (!hidden_parent_dentry);
+-      count--;
+-
+-      sb = dentry->d_sb;
+-
+-      /*
+-       * This is basically while(child_dentry != dentry).  This loop is
+-       * horrible to follow and should be replaced with cleaner code.
+-       */
+-      while (1) {
+-              /* get hidden parent dir in the current branch */
+-              hidden_parent_dentry =
+-                      unionfs_lower_dentry_idx(parent_dentry, bindex);
+-              unionfs_unlock_dentry(parent_dentry);
+-
+-              /* init the values to lookup */
+-              childname = child_dentry->d_name.name;
+-              childnamelen = child_dentry->d_name.len;
+-
+-              if (child_dentry != dentry) {
+-                      /* lookup child in the underlying file system */
+-                      hidden_dentry =
+-                              lookup_one_len(childname, hidden_parent_dentry,
+-                                             childnamelen);
+-                      if (IS_ERR(hidden_dentry))
+-                              goto out;
+-              } else {
+-
+-                      /*
+-                       * is the name a whiteout of the child name ?
+-                       * lookup the whiteout child in the underlying file
+-                       * system
+-                       */
+-                      hidden_dentry =
+-                              lookup_one_len(name, hidden_parent_dentry,
+-                                             strlen(name));
+-                      if (IS_ERR(hidden_dentry))
+-                              goto out;
+-
+-                      /*
+-                       * Replace the current dentry (if any) with the new
+-                       * one.
+-                       */
+-                      dput(unionfs_lower_dentry_idx(dentry, bindex));
+-                      unionfs_set_lower_dentry_idx(dentry, bindex,
+-                                                   hidden_dentry);
+-
+-                      __cleanup_dentry(dentry, bindex, old_bstart, old_bend);
+-                      break;
+-              }
+-
+-              if (hidden_dentry->d_inode) {
+-                      /*
+-                       * since this already exists we dput to avoid
+-                       * multiple references on the same dentry
+-                       */
+-                      dput(hidden_dentry);
+-              } else {
+-                      struct sioq_args args;
+-
+-                      /* its a negative dentry, create a new dir */
+-                      hidden_parent_dentry = lock_parent(hidden_dentry);
+-
+-                      args.mkdir.parent = hidden_parent_dentry->d_inode;
+-                      args.mkdir.dentry = hidden_dentry;
+-                      args.mkdir.mode = child_dentry->d_inode->i_mode;
+-
+-                      run_sioq(__unionfs_mkdir, &args);
+-                      err = args.err;
+-
+-                      if (!err)
+-                              err = copyup_permissions(dir->i_sb,
+-                                                       child_dentry,
+-                                                       hidden_dentry);
+-                      unlock_dir(hidden_parent_dentry);
+-                      if (err) {
+-                              struct inode *inode = hidden_dentry->d_inode;
+-                              /*
+-                               * If we get here, it means that we created a new
+-                               * dentry+inode, but copying permissions failed.
+-                               * Therefore, we should delete this inode and dput
+-                               * the dentry so as not to leave cruft behind.
+-                               *
+-                               * XXX: call dentry_iput() instead, but then we have
+-                               * to export that symbol.
+-                               */
+-                              if (hidden_dentry->d_op && hidden_dentry->d_op->d_iput)
+-                                      hidden_dentry->d_op->d_iput(hidden_dentry,
+-                                                                  inode);
+-                              else
+-                                      iput(inode);
+-                              hidden_dentry->d_inode = NULL;
+-
+-                              dput(hidden_dentry);
+-                              hidden_dentry = ERR_PTR(err);
+-                              goto out;
+-                      }
+-
+-              }
+-
+-              __set_inode(child_dentry, hidden_dentry, bindex);
+-              __set_dentry(child_dentry, hidden_dentry, bindex);
+-
+-              parent_dentry = child_dentry;
+-              child_dentry = path[--count];
+-      }
+-out:
+-      /* cleanup any leftover locks from the do/while loop above */
+-      if (IS_ERR(hidden_dentry))
+-              while (count)
+-                      unionfs_unlock_dentry(path[count--]);
+-      kfree(path);
+-      return hidden_dentry;
+-}
+diff -Nurb linux-2.6.22-590/fs/unionfs/dentry.c linux-2.6.22-570/fs/unionfs/dentry.c
+--- linux-2.6.22-590/fs/unionfs/dentry.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/dentry.c       1969-12-31 19:00:00.000000000 -0500
+@@ -1,353 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/*
+- * Revalidate a single dentry.
+- * Assume that dentry's info node is locked.
+- * Assume that parent(s) are all valid already, but
+- * the child may not yet be valid.
+- * Returns 1 if valid, 0 otherwise.
+- */
+-static int __unionfs_d_revalidate_one(struct dentry *dentry,
+-                                    struct nameidata *nd)
+-{
+-      int valid = 1;          /* default is valid (1); invalid is 0. */
+-      struct dentry *hidden_dentry;
+-      int bindex, bstart, bend;
+-      int sbgen, dgen;
+-      int positive = 0;
+-      int locked = 0;
+-      int interpose_flag;
+-
+-      struct nameidata lowernd; /* TODO: be gentler to the stack */
+-
+-      if (nd)
+-              memcpy(&lowernd, nd, sizeof(struct nameidata));
+-      else
+-              memset(&lowernd, 0, sizeof(struct nameidata));
+-
+-      verify_locked(dentry);
+-
+-      /* if the dentry is unhashed, do NOT revalidate */
+-      if (d_deleted(dentry)) {
+-              printk(KERN_DEBUG "unionfs: unhashed dentry being "
+-                     "revalidated: %*s\n",
+-                     dentry->d_name.len, dentry->d_name.name);
+-              goto out;
+-      }
+-
+-      BUG_ON(dbstart(dentry) == -1);
+-      if (dentry->d_inode)
+-              positive = 1;
+-      dgen = atomic_read(&UNIONFS_D(dentry)->generation);
+-      sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
+-      /*
+-       * If we are working on an unconnected dentry, then there is no
+-       * revalidation to be done, because this file does not exist within
+-       * the namespace, and Unionfs operates on the namespace, not data.
+-       */
+-      if (sbgen != dgen) {
+-              struct dentry *result;
+-              int pdgen;
+-
+-              /* The root entry should always be valid */
+-              BUG_ON(IS_ROOT(dentry));
+-
+-              /* We can't work correctly if our parent isn't valid. */
+-              pdgen = atomic_read(&UNIONFS_D(dentry->d_parent)->generation);
+-              BUG_ON(pdgen != sbgen); /* should never happen here */
+-
+-              /* Free the pointers for our inodes and this dentry. */
+-              bstart = dbstart(dentry);
+-              bend = dbend(dentry);
+-              if (bstart >= 0) {
+-                      struct dentry *hidden_dentry;
+-                      for (bindex = bstart; bindex <= bend; bindex++) {
+-                              hidden_dentry =
+-                                      unionfs_lower_dentry_idx(dentry,
+-                                                               bindex);
+-                              dput(hidden_dentry);
+-                      }
+-              }
+-              set_dbstart(dentry, -1);
+-              set_dbend(dentry, -1);
+-
+-              interpose_flag = INTERPOSE_REVAL_NEG;
+-              if (positive) {
+-                      interpose_flag = INTERPOSE_REVAL;
+-                      /*
+-                       * During BRM, the VFS could already hold a lock on
+-                       * a file being read, so don't lock it again
+-                       * (deadlock), but if you lock it in this function,
+-                       * then release it here too.
+-                       */
+-                      if (!mutex_is_locked(&dentry->d_inode->i_mutex)) {
+-                              mutex_lock(&dentry->d_inode->i_mutex);
+-                              locked = 1;
+-                      }
+-
+-                      bstart = ibstart(dentry->d_inode);
+-                      bend = ibend(dentry->d_inode);
+-                      if (bstart >= 0) {
+-                              struct inode *hidden_inode;
+-                              for (bindex = bstart; bindex <= bend;
+-                                   bindex++) {
+-                                      hidden_inode =
+-                                              unionfs_lower_inode_idx(
+-                                                      dentry->d_inode,
+-                                                      bindex);
+-                                      iput(hidden_inode);
+-                              }
+-                      }
+-                      kfree(UNIONFS_I(dentry->d_inode)->lower_inodes);
+-                      UNIONFS_I(dentry->d_inode)->lower_inodes = NULL;
+-                      ibstart(dentry->d_inode) = -1;
+-                      ibend(dentry->d_inode) = -1;
+-                      if (locked)
+-                              mutex_unlock(&dentry->d_inode->i_mutex);
+-              }
+-
+-              result = unionfs_lookup_backend(dentry, &lowernd,
+-                                              interpose_flag);
+-              if (result) {
+-                      if (IS_ERR(result)) {
+-                              valid = 0;
+-                              goto out;
+-                      }
+-                      /*
+-                       * current unionfs_lookup_backend() doesn't return
+-                       * a valid dentry
+-                       */
+-                      dput(dentry);
+-                      dentry = result;
+-              }
+-
+-              if (positive && UNIONFS_I(dentry->d_inode)->stale) {
+-                      make_bad_inode(dentry->d_inode);
+-                      d_drop(dentry);
+-                      valid = 0;
+-                      goto out;
+-              }
+-              goto out;
+-      }
+-
+-      /* The revalidation must occur across all branches */
+-      bstart = dbstart(dentry);
+-      bend = dbend(dentry);
+-      BUG_ON(bstart == -1);
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (!hidden_dentry || !hidden_dentry->d_op
+-                  || !hidden_dentry->d_op->d_revalidate)
+-                      continue;
+-              if (!hidden_dentry->d_op->d_revalidate(hidden_dentry,
+-                                                     &lowernd))
+-                      valid = 0;
+-      }
+-
+-      if (!dentry->d_inode)
+-              valid = 0;
+-
+-      if (valid) {
+-              fsstack_copy_attr_all(dentry->d_inode,
+-                                    unionfs_lower_inode(dentry->d_inode),
+-                                    unionfs_get_nlinks);
+-              fsstack_copy_inode_size(dentry->d_inode,
+-                                      unionfs_lower_inode(dentry->d_inode));
+-      }
+-
+-out:
+-      return valid;
+-}
+-
+-/*
+- * Revalidate a parent chain of dentries, then the actual node.
+- * Assumes that dentry is locked, but will lock all parents if/when needed.
+- */
+-int __unionfs_d_revalidate_chain(struct dentry *dentry, struct nameidata *nd)
+-{
+-      int valid = 0;          /* default is invalid (0); valid is 1. */
+-      struct dentry **chain = NULL; /* chain of dentries to reval */
+-      int chain_len = 0;
+-      struct dentry *dtmp;
+-      int sbgen, dgen, i;
+-      int saved_bstart, saved_bend, bindex;
+-
+-      /* find length of chain needed to revalidate */
+-      /* XXX: should I grab some global (dcache?) lock? */
+-      chain_len = 0;
+-      sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
+-      dtmp = dentry->d_parent;
+-      dgen = atomic_read(&UNIONFS_D(dtmp)->generation);
+-      while (sbgen != dgen) {
+-              /* The root entry should always be valid */
+-              BUG_ON(IS_ROOT(dtmp));
+-              chain_len++;
+-              dtmp = dtmp->d_parent;
+-              dgen = atomic_read(&UNIONFS_D(dtmp)->generation);
+-      }
+-      if (chain_len == 0)
+-              goto out_this;  /* shortcut if parents are OK */
+-
+-      /*
+-       * Allocate array of dentries to reval.  We could use linked lists,
+-       * but the number of entries we need to alloc here is often small,
+-       * and short lived, so locality will be better.
+-       */
+-      chain = kzalloc(chain_len * sizeof(struct dentry *), GFP_KERNEL);
+-      if (!chain) {
+-              printk("unionfs: no more memory in %s\n", __FUNCTION__);
+-              goto out;
+-      }
+-
+-      /*
+-       * lock all dentries in chain, in child to parent order.
+-       * if failed, then sleep for a little, then retry.
+-       */
+-      dtmp = dentry->d_parent;
+-      for (i=chain_len-1; i>=0; i--) {
+-              chain[i] = dget(dtmp);
+-              dtmp = dtmp->d_parent;
+-      }
+-
+-      /*
+-       * call __unionfs_d_revalidate() on each dentry, but in parent to
+-       * child order.
+-       */
+-      for (i=0; i<chain_len; i++) {
+-              unionfs_lock_dentry(chain[i]);
+-              saved_bstart = dbstart(chain[i]);
+-              saved_bend = dbend(chain[i]);
+-              sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
+-              dgen = atomic_read(&UNIONFS_D(chain[i])->generation);
+-
+-              valid = __unionfs_d_revalidate_one(chain[i], nd);
+-              /* XXX: is this the correct mntput condition?! */
+-              if (valid && chain_len > 0 &&
+-                  sbgen != dgen && chain[i]->d_inode &&
+-                  S_ISDIR(chain[i]->d_inode->i_mode)) {
+-                      for (bindex = saved_bstart; bindex <= saved_bend;
+-                           bindex++)
+-                              unionfs_mntput(chain[i], bindex);
+-              }
+-              unionfs_unlock_dentry(chain[i]);
+-
+-              if (!valid)
+-                      goto out_free;
+-      }
+-
+-
+-out_this:
+-      /* finally, lock this dentry and revalidate it */
+-      verify_locked(dentry);
+-      dgen = atomic_read(&UNIONFS_D(dentry)->generation);
+-      valid = __unionfs_d_revalidate_one(dentry, nd);
+-
+-      /*
+-       * If __unionfs_d_revalidate_one() succeeded above, then it will
+-       * have incremented the refcnt of the mnt's, but also the branch
+-       * indices of the dentry will have been updated (to take into
+-       * account any branch insertions/deletion.  So the current
+-       * dbstart/dbend match the current, and new, indices of the mnts
+-       * which __unionfs_d_revalidate_one has incremented.  Note: the "if"
+-       * test below does not depend on whether chain_len was 0 or greater.
+-       */
+-      if (valid && sbgen != dgen)
+-              for (bindex = dbstart(dentry);
+-                   bindex <= dbend(dentry);
+-                   bindex++)
+-                      unionfs_mntput(dentry, bindex);
+-
+-out_free:
+-      /* unlock/dput all dentries in chain and return status */
+-      if (chain_len > 0) {
+-              for (i=0; i<chain_len; i++)
+-                      dput(chain[i]);
+-              kfree(chain);
+-      }
+-out:
+-      return valid;
+-}
+-
+-static int unionfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+-{
+-      int err;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-
+-      unionfs_lock_dentry(dentry);
+-      err = __unionfs_d_revalidate_chain(dentry, nd);
+-      unionfs_unlock_dentry(dentry);
+-
+-      unionfs_read_unlock(dentry->d_sb);
+-
+-      return err;
+-}
+-
+-/*
+- * At this point no one can reference this dentry, so we don't have to be
+- * careful about concurrent access.
+- */
+-static void unionfs_d_release(struct dentry *dentry)
+-{
+-      int bindex, bstart, bend;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-
+-      /* this could be a negative dentry, so check first */
+-      if (!UNIONFS_D(dentry)) {
+-              printk(KERN_DEBUG "unionfs: dentry without private data: %.*s",
+-                     dentry->d_name.len, dentry->d_name.name);
+-              goto out;
+-      } else if (dbstart(dentry) < 0) {
+-              /* this is due to a failed lookup */
+-              printk(KERN_DEBUG "unionfs: dentry without hidden "
+-                     "dentries: %.*s",
+-                     dentry->d_name.len, dentry->d_name.name);
+-              goto out_free;
+-      }
+-
+-      /* Release all the hidden dentries */
+-      bstart = dbstart(dentry);
+-      bend = dbend(dentry);
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              dput(unionfs_lower_dentry_idx(dentry, bindex));
+-              unionfs_mntput(dentry, bindex);
+-
+-              unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
+-              unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
+-      }
+-      /* free private data (unionfs_dentry_info) here */
+-      kfree(UNIONFS_D(dentry)->lower_paths);
+-      UNIONFS_D(dentry)->lower_paths = NULL;
+-
+-out_free:
+-      /* No need to unlock it, because it is disappeared. */
+-      free_dentry_private_data(dentry);
+-
+-out:
+-      unionfs_read_unlock(dentry->d_sb);
+-      return;
+-}
+-
+-struct dentry_operations unionfs_dops = {
+-      .d_revalidate   = unionfs_d_revalidate,
+-      .d_release      = unionfs_d_release,
+-};
+diff -Nurb linux-2.6.22-590/fs/unionfs/dirfops.c linux-2.6.22-570/fs/unionfs/dirfops.c
+--- linux-2.6.22-590/fs/unionfs/dirfops.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/dirfops.c      1969-12-31 19:00:00.000000000 -0500
+@@ -1,276 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/* Make sure our rdstate is playing by the rules. */
+-static void verify_rdstate_offset(struct unionfs_dir_state *rdstate)
+-{
+-      BUG_ON(rdstate->offset >= DIREOF);
+-      BUG_ON(rdstate->cookie >= MAXRDCOOKIE);
+-}
+-
+-struct unionfs_getdents_callback {
+-      struct unionfs_dir_state *rdstate;
+-      void *dirent;
+-      int entries_written;
+-      int filldir_called;
+-      int filldir_error;
+-      filldir_t filldir;
+-      struct super_block *sb;
+-};
+-
+-/* based on generic filldir in fs/readir.c */
+-static int unionfs_filldir(void *dirent, const char *name, int namelen,
+-                         loff_t offset, u64 ino, unsigned int d_type)
+-{
+-      struct unionfs_getdents_callback *buf = dirent;
+-      struct filldir_node *found = NULL;
+-      int err = 0;
+-      int is_wh_entry = 0;
+-
+-      buf->filldir_called++;
+-
+-      if ((namelen > UNIONFS_WHLEN) &&
+-          !strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN)) {
+-              name += UNIONFS_WHLEN;
+-              namelen -= UNIONFS_WHLEN;
+-              is_wh_entry = 1;
+-      }
+-
+-      found = find_filldir_node(buf->rdstate, name, namelen);
+-
+-      if (found)
+-              goto out;
+-
+-      /* if 'name' isn't a whiteout, filldir it. */
+-      if (!is_wh_entry) {
+-              off_t pos = rdstate2offset(buf->rdstate);
+-              u64 unionfs_ino = ino;
+-
+-              if (!err) {
+-                      err = buf->filldir(buf->dirent, name, namelen, pos,
+-                                         unionfs_ino, d_type);
+-                      buf->rdstate->offset++;
+-                      verify_rdstate_offset(buf->rdstate);
+-              }
+-      }
+-      /*
+-       * If we did fill it, stuff it in our hash, otherwise return an
+-       * error.
+-       */
+-      if (err) {
+-              buf->filldir_error = err;
+-              goto out;
+-      }
+-      buf->entries_written++;
+-      if ((err = add_filldir_node(buf->rdstate, name, namelen,
+-                                  buf->rdstate->bindex, is_wh_entry)))
+-              buf->filldir_error = err;
+-
+-out:
+-      return err;
+-}
+-
+-static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
+-{
+-      int err = 0;
+-      struct file *hidden_file = NULL;
+-      struct inode *inode = NULL;
+-      struct unionfs_getdents_callback buf;
+-      struct unionfs_dir_state *uds;
+-      int bend;
+-      loff_t offset;
+-
+-      unionfs_read_lock(file->f_path.dentry->d_sb);
+-
+-      if ((err = unionfs_file_revalidate(file, 0)))
+-              goto out;
+-
+-      inode = file->f_dentry->d_inode;
+-
+-      uds = UNIONFS_F(file)->rdstate;
+-      if (!uds) {
+-              if (file->f_pos == DIREOF) {
+-                      goto out;
+-              } else if (file->f_pos > 0) {
+-                      uds = find_rdstate(inode, file->f_pos);
+-                      if (!uds) {
+-                              err = -ESTALE;
+-                              goto out;
+-                      }
+-                      UNIONFS_F(file)->rdstate = uds;
+-              } else {
+-                      init_rdstate(file);
+-                      uds = UNIONFS_F(file)->rdstate;
+-              }
+-      }
+-      bend = fbend(file);
+-
+-      while (uds->bindex <= bend) {
+-              hidden_file = unionfs_lower_file_idx(file, uds->bindex);
+-              if (!hidden_file) {
+-                      uds->bindex++;
+-                      uds->dirpos = 0;
+-                      continue;
+-              }
+-
+-              /* prepare callback buffer */
+-              buf.filldir_called = 0;
+-              buf.filldir_error = 0;
+-              buf.entries_written = 0;
+-              buf.dirent = dirent;
+-              buf.filldir = filldir;
+-              buf.rdstate = uds;
+-              buf.sb = inode->i_sb;
+-
+-              /* Read starting from where we last left off. */
+-              offset = vfs_llseek(hidden_file, uds->dirpos, SEEK_SET);
+-              if (offset < 0) {
+-                      err = offset;
+-                      goto out;
+-              }
+-              err = vfs_readdir(hidden_file, unionfs_filldir, &buf);
+-
+-              /* Save the position for when we continue. */
+-              offset = vfs_llseek(hidden_file, 0, SEEK_CUR);
+-              if (offset < 0) {
+-                      err = offset;
+-                      goto out;
+-              }
+-              uds->dirpos = offset;
+-
+-              /* Copy the atime. */
+-              fsstack_copy_attr_atime(inode, hidden_file->f_dentry->d_inode);
+-
+-              if (err < 0)
+-                      goto out;
+-
+-              if (buf.filldir_error)
+-                      break;
+-
+-              if (!buf.entries_written) {
+-                      uds->bindex++;
+-                      uds->dirpos = 0;
+-              }
+-      }
+-
+-      if (!buf.filldir_error && uds->bindex >= bend) {
+-              /* Save the number of hash entries for next time. */
+-              UNIONFS_I(inode)->hashsize = uds->hashentries;
+-              free_rdstate(uds);
+-              UNIONFS_F(file)->rdstate = NULL;
+-              file->f_pos = DIREOF;
+-      } else
+-              file->f_pos = rdstate2offset(uds);
+-
+-out:
+-      unionfs_read_unlock(file->f_path.dentry->d_sb);
+-      return err;
+-}
+-
+-/*
+- * This is not meant to be a generic repositioning function.  If you do
+- * things that aren't supported, then we return EINVAL.
+- *
+- * What is allowed:
+- *  (1) seeking to the same position that you are currently at
+- *    This really has no effect, but returns where you are.
+- *  (2) seeking to the beginning of the file
+- *    This throws out all state, and lets you begin again.
+- */
+-static loff_t unionfs_dir_llseek(struct file *file, loff_t offset, int origin)
+-{
+-      struct unionfs_dir_state *rdstate;
+-      loff_t err;
+-
+-      unionfs_read_lock(file->f_path.dentry->d_sb);
+-
+-      if ((err = unionfs_file_revalidate(file, 0)))
+-              goto out;
+-
+-      rdstate = UNIONFS_F(file)->rdstate;
+-
+-      /*
+-       * we let users seek to their current position, but not anywhere
+-       * else.
+-       */
+-      if (!offset) {
+-              switch (origin) {
+-              case SEEK_SET:
+-                      if (rdstate) {
+-                              free_rdstate(rdstate);
+-                              UNIONFS_F(file)->rdstate = NULL;
+-                      }
+-                      init_rdstate(file);
+-                      err = 0;
+-                      break;
+-              case SEEK_CUR:
+-                      err = file->f_pos;
+-                      break;
+-              case SEEK_END:
+-                      /* Unsupported, because we would break everything.  */
+-                      err = -EINVAL;
+-                      break;
+-              }
+-      } else {
+-              switch (origin) {
+-              case SEEK_SET:
+-                      if (rdstate) {
+-                              if (offset == rdstate2offset(rdstate))
+-                                      err = offset;
+-                              else if (file->f_pos == DIREOF)
+-                                      err = DIREOF;
+-                              else
+-                                      err = -EINVAL;
+-                      } else {
+-                              rdstate = find_rdstate(file->f_dentry->d_inode,
+-                                                     offset);
+-                              if (rdstate) {
+-                                      UNIONFS_F(file)->rdstate = rdstate;
+-                                      err = rdstate->offset;
+-                              } else
+-                                      err = -EINVAL;
+-                      }
+-                      break;
+-              case SEEK_CUR:
+-              case SEEK_END:
+-                      /* Unsupported, because we would break everything.  */
+-                      err = -EINVAL;
+-                      break;
+-              }
+-      }
+-
+-out:
+-      unionfs_read_unlock(file->f_path.dentry->d_sb);
+-      return err;
+-}
+-
+-/*
+- * Trimmed directory options, we shouldn't pass everything down since
+- * we don't want to operate on partial directories.
+- */
+-struct file_operations unionfs_dir_fops = {
+-      .llseek         = unionfs_dir_llseek,
+-      .read           = generic_read_dir,
+-      .readdir        = unionfs_readdir,
+-      .unlocked_ioctl = unionfs_ioctl,
+-      .open           = unionfs_open,
+-      .release        = unionfs_file_release,
+-      .flush          = unionfs_flush,
+-};
+diff -Nurb linux-2.6.22-590/fs/unionfs/dirhelper.c linux-2.6.22-570/fs/unionfs/dirhelper.c
+--- linux-2.6.22-590/fs/unionfs/dirhelper.c    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/dirhelper.c    1969-12-31 19:00:00.000000000 -0500
+@@ -1,273 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/*
+- * Delete all of the whiteouts in a given directory for rmdir.
+- *
+- * hidden directory inode should be locked
+- */
+-int do_delete_whiteouts(struct dentry *dentry, int bindex,
+-                      struct unionfs_dir_state *namelist)
+-{
+-      int err = 0;
+-      struct dentry *hidden_dir_dentry = NULL;
+-      struct dentry *hidden_dentry;
+-      char *name = NULL, *p;
+-      struct inode *hidden_dir;
+-
+-      int i;
+-      struct list_head *pos;
+-      struct filldir_node *cursor;
+-
+-      /* Find out hidden parent dentry */
+-      hidden_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-      BUG_ON(!S_ISDIR(hidden_dir_dentry->d_inode->i_mode));
+-      hidden_dir = hidden_dir_dentry->d_inode;
+-      BUG_ON(!S_ISDIR(hidden_dir->i_mode));
+-
+-      err = -ENOMEM;
+-      name = __getname();
+-      if (!name)
+-              goto out;
+-      strcpy(name, UNIONFS_WHPFX);
+-      p = name + UNIONFS_WHLEN;
+-
+-      err = 0;
+-      for (i = 0; !err && i < namelist->size; i++) {
+-              list_for_each(pos, &namelist->list[i]) {
+-                      cursor =
+-                              list_entry(pos, struct filldir_node,
+-                                         file_list);
+-                      /* Only operate on whiteouts in this branch. */
+-                      if (cursor->bindex != bindex)
+-                              continue;
+-                      if (!cursor->whiteout)
+-                              continue;
+-
+-                      strcpy(p, cursor->name);
+-                      hidden_dentry =
+-                              lookup_one_len(name, hidden_dir_dentry,
+-                                             cursor->namelen +
+-                                             UNIONFS_WHLEN);
+-                      if (IS_ERR(hidden_dentry)) {
+-                              err = PTR_ERR(hidden_dentry);
+-                              break;
+-                      }
+-                      if (hidden_dentry->d_inode)
+-                              err = vfs_unlink(hidden_dir, hidden_dentry);
+-                      dput(hidden_dentry);
+-                      if (err)
+-                              break;
+-              }
+-      }
+-
+-      __putname(name);
+-
+-      /* After all of the removals, we should copy the attributes once. */
+-      fsstack_copy_attr_times(dentry->d_inode, hidden_dir_dentry->d_inode);
+-
+-out:
+-      return err;
+-}
+-
+-/* delete whiteouts in a dir (for rmdir operation) using sioq if necessary */
+-int delete_whiteouts(struct dentry *dentry, int bindex,
+-                   struct unionfs_dir_state *namelist)
+-{
+-      int err;
+-      struct super_block *sb;
+-      struct dentry *hidden_dir_dentry;
+-      struct inode *hidden_dir;
+-
+-      struct sioq_args args;
+-
+-      sb = dentry->d_sb;
+-
+-      BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
+-      BUG_ON(bindex < dbstart(dentry));
+-      BUG_ON(bindex > dbend(dentry));
+-      err = is_robranch_super(sb, bindex);
+-      if (err)
+-              goto out;
+-
+-      hidden_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-      BUG_ON(!S_ISDIR(hidden_dir_dentry->d_inode->i_mode));
+-      hidden_dir = hidden_dir_dentry->d_inode;
+-      BUG_ON(!S_ISDIR(hidden_dir->i_mode));
+-
+-      mutex_lock(&hidden_dir->i_mutex);
+-      if (!permission(hidden_dir, MAY_WRITE | MAY_EXEC, NULL))
+-              err = do_delete_whiteouts(dentry, bindex, namelist);
+-      else {
+-              args.deletewh.namelist = namelist;
+-              args.deletewh.dentry = dentry;
+-              args.deletewh.bindex = bindex;
+-              run_sioq(__delete_whiteouts, &args);
+-              err = args.err;
+-      }
+-      mutex_unlock(&hidden_dir->i_mutex);
+-
+-out:
+-      return err;
+-}
+-
+-#define RD_NONE 0
+-#define RD_CHECK_EMPTY 1
+-/* The callback structure for check_empty. */
+-struct unionfs_rdutil_callback {
+-      int err;
+-      int filldir_called;
+-      struct unionfs_dir_state *rdstate;
+-      int mode;
+-};
+-
+-/* This filldir function makes sure only whiteouts exist within a directory. */
+-static int readdir_util_callback(void *dirent, const char *name, int namelen,
+-                               loff_t offset, u64 ino, unsigned int d_type)
+-{
+-      int err = 0;
+-      struct unionfs_rdutil_callback *buf = dirent;
+-      int whiteout = 0;
+-      struct filldir_node *found;
+-
+-      buf->filldir_called = 1;
+-
+-      if (name[0] == '.' && (namelen == 1 ||
+-                             (name[1] == '.' && namelen == 2)))
+-              goto out;
+-
+-      if (namelen > UNIONFS_WHLEN &&
+-          !strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN)) {
+-              namelen -= UNIONFS_WHLEN;
+-              name += UNIONFS_WHLEN;
+-              whiteout = 1;
+-      }
+-
+-      found = find_filldir_node(buf->rdstate, name, namelen);
+-      /* If it was found in the table there was a previous whiteout. */
+-      if (found)
+-              goto out;
+-
+-      /*
+-       * if it wasn't found and isn't a whiteout, the directory isn't
+-       * empty.
+-       */
+-      err = -ENOTEMPTY;
+-      if ((buf->mode == RD_CHECK_EMPTY) && !whiteout)
+-              goto out;
+-
+-      err = add_filldir_node(buf->rdstate, name, namelen,
+-                             buf->rdstate->bindex, whiteout);
+-
+-out:
+-      buf->err = err;
+-      return err;
+-}
+-
+-/* Is a directory logically empty? */
+-int check_empty(struct dentry *dentry, struct unionfs_dir_state **namelist)
+-{
+-      int err = 0;
+-      struct dentry *hidden_dentry = NULL;
+-      struct super_block *sb;
+-      struct file *hidden_file;
+-      struct unionfs_rdutil_callback *buf = NULL;
+-      int bindex, bstart, bend, bopaque;
+-
+-      sb = dentry->d_sb;
+-
+-
+-      BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
+-
+-      if ((err = unionfs_partial_lookup(dentry)))
+-              goto out;
+-
+-      bstart = dbstart(dentry);
+-      bend = dbend(dentry);
+-      bopaque = dbopaque(dentry);
+-      if (0 <= bopaque && bopaque < bend)
+-              bend = bopaque;
+-
+-      buf = kmalloc(sizeof(struct unionfs_rdutil_callback), GFP_KERNEL);
+-      if (!buf) {
+-              err = -ENOMEM;
+-              goto out;
+-      }
+-      buf->err = 0;
+-      buf->mode = RD_CHECK_EMPTY;
+-      buf->rdstate = alloc_rdstate(dentry->d_inode, bstart);
+-      if (!buf->rdstate) {
+-              err = -ENOMEM;
+-              goto out;
+-      }
+-
+-      /* Process the hidden directories with rdutil_callback as a filldir. */
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (!hidden_dentry)
+-                      continue;
+-              if (!hidden_dentry->d_inode)
+-                      continue;
+-              if (!S_ISDIR(hidden_dentry->d_inode->i_mode))
+-                      continue;
+-
+-              dget(hidden_dentry);
+-              unionfs_mntget(dentry, bindex);
+-              branchget(sb, bindex);
+-              hidden_file =
+-                      dentry_open(hidden_dentry,
+-                                  unionfs_lower_mnt_idx(dentry, bindex),
+-                                  O_RDONLY);
+-              if (IS_ERR(hidden_file)) {
+-                      err = PTR_ERR(hidden_file);
+-                      dput(hidden_dentry);
+-                      branchput(sb, bindex);
+-                      goto out;
+-              }
+-
+-              do {
+-                      buf->filldir_called = 0;
+-                      buf->rdstate->bindex = bindex;
+-                      err = vfs_readdir(hidden_file,
+-                                        readdir_util_callback, buf);
+-                      if (buf->err)
+-                              err = buf->err;
+-              } while ((err >= 0) && buf->filldir_called);
+-
+-              /* fput calls dput for hidden_dentry */
+-              fput(hidden_file);
+-              branchput(sb, bindex);
+-
+-              if (err < 0)
+-                      goto out;
+-      }
+-
+-out:
+-      if (buf) {
+-              if (namelist && !err)
+-                      *namelist = buf->rdstate;
+-              else if (buf->rdstate)
+-                      free_rdstate(buf->rdstate);
+-              kfree(buf);
+-      }
+-
+-
+-      return err;
+-}
+diff -Nurb linux-2.6.22-590/fs/unionfs/fanout.h linux-2.6.22-570/fs/unionfs/fanout.h
+--- linux-2.6.22-590/fs/unionfs/fanout.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/fanout.h       1969-12-31 19:00:00.000000000 -0500
+@@ -1,308 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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.
+- */
+-
+-#ifndef _FANOUT_H_
+-#define _FANOUT_H_
+-
+-/*
+- * Inode to private data
+- *
+- * Since we use containers and the struct inode is _inside_ the
+- * unionfs_inode_info structure, UNIONFS_I will always (given a non-NULL
+- * inode pointer), return a valid non-NULL pointer.
+- */
+-static inline struct unionfs_inode_info *UNIONFS_I(const struct inode *inode)
+-{
+-      return container_of(inode, struct unionfs_inode_info, vfs_inode);
+-}
+-
+-#define ibstart(ino) (UNIONFS_I(ino)->bstart)
+-#define ibend(ino) (UNIONFS_I(ino)->bend)
+-
+-/* Superblock to private data */
+-#define UNIONFS_SB(super) ((struct unionfs_sb_info *)(super)->s_fs_info)
+-#define sbstart(sb) 0
+-#define sbend(sb) (UNIONFS_SB(sb)->bend)
+-#define sbmax(sb) (UNIONFS_SB(sb)->bend + 1)
+-#define sbhbid(sb) (UNIONFS_SB(sb)->high_branch_id)
+-
+-/* File to private Data */
+-#define UNIONFS_F(file) ((struct unionfs_file_info *)((file)->private_data))
+-#define fbstart(file) (UNIONFS_F(file)->bstart)
+-#define fbend(file) (UNIONFS_F(file)->bend)
+-
+-/* macros to manipulate branch IDs in stored in our superblock */
+-static inline int branch_id(struct super_block *sb, int index)
+-{
+-      BUG_ON(!sb || index < 0);
+-      return UNIONFS_SB(sb)->data[index].branch_id;
+-}
+-
+-static inline void set_branch_id(struct super_block *sb, int index, int val)
+-{
+-      BUG_ON(!sb || index < 0);
+-      UNIONFS_SB(sb)->data[index].branch_id = val;
+-}
+-
+-static inline void new_branch_id(struct super_block *sb, int index)
+-{
+-      BUG_ON(!sb || index < 0);
+-      set_branch_id(sb, index, ++UNIONFS_SB(sb)->high_branch_id);
+-}
+-
+-/*
+- * Find new index of matching branch with an existing superblock a a known
+- * (possibly old) id.  This is needed because branches could have been
+- * added/deleted causing the branchs of any open files to shift.
+- *
+- * @sb: the new superblock which may have new/different branch IDs
+- * @id: the old/existing id we're looking for
+- * Returns index of newly found branch (0 or greater), -1 otherwise.
+- */
+-static inline int branch_id_to_idx(struct super_block *sb, int id)
+-{
+-      int i;
+-      for (i = 0; i < sbmax(sb); i++) {
+-              if (branch_id(sb, i) == id)
+-                      return i;
+-      }
+-      /*
+-       * XXX: maybe we should BUG_ON if not found new branch index?
+-       * (really that should never happen).
+-       */
+-      printk(KERN_WARNING "unionfs: cannot find branch with id %d\n", id);
+-      return -1;
+-}
+-
+-/* File to lower file. */
+-static inline struct file *unionfs_lower_file(const struct file *f)
+-{
+-      BUG_ON(!f);
+-      return UNIONFS_F(f)->lower_files[fbstart(f)];
+-}
+-
+-static inline struct file *unionfs_lower_file_idx(const struct file *f,
+-                                                int index)
+-{
+-      BUG_ON(!f || index < 0);
+-      return UNIONFS_F(f)->lower_files[index];
+-}
+-
+-static inline void unionfs_set_lower_file_idx(struct file *f, int index,
+-                                            struct file *val)
+-{
+-      BUG_ON(!f || index < 0);
+-      UNIONFS_F(f)->lower_files[index] = val;
+-      /* save branch ID (may be redundant?) */
+-      UNIONFS_F(f)->saved_branch_ids[index] =
+-              branch_id((f)->f_dentry->d_sb, index);
+-}
+-
+-static inline void unionfs_set_lower_file(struct file *f, struct file *val)
+-{
+-      BUG_ON(!f);
+-      unionfs_set_lower_file_idx((f), fbstart(f), (val));
+-}
+-
+-/* Inode to lower inode. */
+-static inline struct inode *unionfs_lower_inode(const struct inode *i)
+-{
+-      BUG_ON(!i);
+-      return UNIONFS_I(i)->lower_inodes[ibstart(i)];
+-}
+-
+-static inline struct inode *unionfs_lower_inode_idx(const struct inode *i,
+-                                                  int index)
+-{
+-      BUG_ON(!i || index < 0);
+-      return UNIONFS_I(i)->lower_inodes[index];
+-}
+-
+-static inline void unionfs_set_lower_inode_idx(struct inode *i, int index,
+-                                             struct inode *val)
+-{
+-      BUG_ON(!i || index < 0);
+-      UNIONFS_I(i)->lower_inodes[index] = val;
+-}
+-
+-static inline void unionfs_set_lower_inode(struct inode *i, struct inode *val)
+-{
+-      BUG_ON(!i);
+-      UNIONFS_I(i)->lower_inodes[ibstart(i)] = val;
+-}
+-
+-/* Superblock to lower superblock. */
+-static inline struct super_block *unionfs_lower_super(
+-                                      const struct super_block *sb)
+-{
+-      BUG_ON(!sb);
+-      return UNIONFS_SB(sb)->data[sbstart(sb)].sb;
+-}
+-
+-static inline struct super_block *unionfs_lower_super_idx(
+-                                      const struct super_block *sb,
+-                                      int index)
+-{
+-      BUG_ON(!sb || index < 0);
+-      return UNIONFS_SB(sb)->data[index].sb;
+-}
+-
+-static inline void unionfs_set_lower_super_idx(struct super_block *sb,
+-                                             int index,
+-                                             struct super_block *val)
+-{
+-      BUG_ON(!sb || index < 0);
+-      UNIONFS_SB(sb)->data[index].sb = val;
+-}
+-
+-static inline void unionfs_set_lower_super(struct super_block *sb,
+-                                         struct super_block *val)
+-{
+-      BUG_ON(!sb);
+-      UNIONFS_SB(sb)->data[sbstart(sb)].sb = val;
+-}
+-
+-/* Branch count macros. */
+-static inline int branch_count(const struct super_block *sb, int index)
+-{
+-      BUG_ON(!sb || index < 0);
+-      return atomic_read(&UNIONFS_SB(sb)->data[index].open_files);
+-}
+-
+-static inline void set_branch_count(struct super_block *sb, int index, int val)
+-{
+-      BUG_ON(!sb || index < 0);
+-      atomic_set(&UNIONFS_SB(sb)->data[index].open_files, val);
+-}
+-
+-static inline void branchget(struct super_block *sb, int index)
+-{
+-      BUG_ON(!sb || index < 0);
+-      atomic_inc(&UNIONFS_SB(sb)->data[index].open_files);
+-}
+-
+-static inline void branchput(struct super_block *sb, int index)
+-{
+-      BUG_ON(!sb || index < 0);
+-      atomic_dec(&UNIONFS_SB(sb)->data[index].open_files);
+-}
+-
+-/* Dentry macros */
+-static inline struct unionfs_dentry_info *UNIONFS_D(const struct dentry *dent)
+-{
+-      BUG_ON(!dent);
+-      return dent->d_fsdata;
+-}
+-
+-static inline int dbstart(const struct dentry *dent)
+-{
+-      BUG_ON(!dent);
+-      return UNIONFS_D(dent)->bstart;
+-}
+-
+-static inline void set_dbstart(struct dentry *dent, int val)
+-{
+-      BUG_ON(!dent);
+-      UNIONFS_D(dent)->bstart = val;
+-}
+-
+-static inline int dbend(const struct dentry *dent)
+-{
+-      BUG_ON(!dent);
+-      return UNIONFS_D(dent)->bend;
+-}
+-
+-static inline void set_dbend(struct dentry *dent, int val)
+-{
+-      BUG_ON(!dent);
+-      UNIONFS_D(dent)->bend = val;
+-}
+-
+-static inline int dbopaque(const struct dentry *dent)
+-{
+-      BUG_ON(!dent);
+-      return UNIONFS_D(dent)->bopaque;
+-}
+-
+-static inline void set_dbopaque(struct dentry *dent, int val)
+-{
+-      BUG_ON(!dent);
+-      UNIONFS_D(dent)->bopaque = val;
+-}
+-
+-static inline void unionfs_set_lower_dentry_idx(struct dentry *dent, int index,
+-                                              struct dentry *val)
+-{
+-      BUG_ON(!dent || index < 0);
+-      UNIONFS_D(dent)->lower_paths[index].dentry = val;
+-}
+-
+-static inline struct dentry *unionfs_lower_dentry_idx(
+-                              const struct dentry *dent,
+-                              int index)
+-{
+-      BUG_ON(!dent || index < 0);
+-      return UNIONFS_D(dent)->lower_paths[index].dentry;
+-}
+-
+-static inline struct dentry *unionfs_lower_dentry(const struct dentry *dent)
+-{
+-      BUG_ON(!dent);
+-      return unionfs_lower_dentry_idx(dent, dbstart(dent));
+-}
+-
+-static inline void unionfs_set_lower_mnt_idx(struct dentry *dent, int index,
+-                                           struct vfsmount *mnt)
+-{
+-      BUG_ON(!dent || index < 0);
+-      UNIONFS_D(dent)->lower_paths[index].mnt = mnt;
+-}
+-
+-static inline struct vfsmount *unionfs_lower_mnt_idx(
+-                                      const struct dentry *dent,
+-                                      int index)
+-{
+-      BUG_ON(!dent || index < 0);
+-      return UNIONFS_D(dent)->lower_paths[index].mnt;
+-}
+-
+-static inline struct vfsmount *unionfs_lower_mnt(const struct dentry *dent)
+-{
+-      BUG_ON(!dent);
+-      return unionfs_lower_mnt_idx(dent, dbstart(dent));
+-}
+-
+-/* Macros for locking a dentry. */
+-static inline void unionfs_lock_dentry(struct dentry *d)
+-{
+-      BUG_ON(!d);
+-      mutex_lock(&UNIONFS_D(d)->lock);
+-}
+-
+-static inline void unionfs_unlock_dentry(struct dentry *d)
+-{
+-      BUG_ON(!d);
+-      mutex_unlock(&UNIONFS_D(d)->lock);
+-}
+-
+-static inline void verify_locked(struct dentry *d)
+-{
+-      BUG_ON(!d);
+-      BUG_ON(!mutex_is_locked(&UNIONFS_D(d)->lock));
+-}
+-
+-#endif        /* _FANOUT_H */
+diff -Nurb linux-2.6.22-590/fs/unionfs/file.c linux-2.6.22-570/fs/unionfs/file.c
+--- linux-2.6.22-590/fs/unionfs/file.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/file.c 1969-12-31 19:00:00.000000000 -0500
+@@ -1,149 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/*******************
+- * File Operations *
+- *******************/
+-
+-static ssize_t unionfs_read(struct file *file, char __user *buf,
+-                          size_t count, loff_t *ppos)
+-{
+-      int err;
+-
+-      unionfs_read_lock(file->f_path.dentry->d_sb);
+-
+-      if ((err = unionfs_file_revalidate(file, 0)))
+-              goto out;
+-
+-      err = do_sync_read(file, buf, count, ppos);
+-
+-      if (err >= 0)
+-              touch_atime(unionfs_lower_mnt(file->f_path.dentry),
+-                          unionfs_lower_dentry(file->f_path.dentry));
+-
+-out:
+-      unionfs_read_unlock(file->f_path.dentry->d_sb);
+-      return err;
+-}
+-
+-static ssize_t unionfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
+-                              unsigned long nr_segs, loff_t pos)
+-{
+-      int err = 0;
+-      struct file *file = iocb->ki_filp;
+-
+-      unionfs_read_lock(file->f_path.dentry->d_sb);
+-
+-      if ((err = unionfs_file_revalidate(file, 0)))
+-              goto out;
+-
+-      err = generic_file_aio_read(iocb, iov, nr_segs, pos);
+-
+-      if (err == -EIOCBQUEUED)
+-              err = wait_on_sync_kiocb(iocb);
+-
+-      if (err >= 0)
+-              touch_atime(unionfs_lower_mnt(file->f_path.dentry),
+-                          unionfs_lower_dentry(file->f_path.dentry));
+-
+-out:
+-      unionfs_read_unlock(file->f_path.dentry->d_sb);
+-      return err;
+-}
+-static ssize_t unionfs_write(struct file * file, const char __user * buf,
+-                           size_t count, loff_t *ppos)
+-{
+-      int err = 0;
+-
+-      unionfs_read_lock(file->f_path.dentry->d_sb);
+-
+-      if ((err = unionfs_file_revalidate(file, 1)))
+-              goto out;
+-
+-      err = do_sync_write(file, buf, count, ppos);
+-
+-out:
+-      unionfs_read_unlock(file->f_path.dentry->d_sb);
+-      return err;
+-}
+-
+-static int unionfs_file_readdir(struct file *file, void *dirent,
+-                              filldir_t filldir)
+-{
+-      return -ENOTDIR;
+-}
+-
+-static int unionfs_mmap(struct file *file, struct vm_area_struct *vma)
+-{
+-      int err = 0;
+-      int willwrite;
+-      struct file *lower_file;
+-
+-      unionfs_read_lock(file->f_path.dentry->d_sb);
+-
+-      if ((err = unionfs_file_revalidate(file, 1)))
+-              goto out;
+-
+-      /* This might be deferred to mmap's writepage */
+-      willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
+-      if ((err = unionfs_file_revalidate(file, willwrite)))
+-              goto out;
+-
+-      /*
+-       * File systems which do not implement ->writepage may use
+-       * generic_file_readonly_mmap as their ->mmap op.  If you call
+-       * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL.
+-       * But we cannot call the lower ->mmap op, so we can't tell that
+-       * writeable mappings won't work.  Therefore, our only choice is to
+-       * check if the lower file system supports the ->writepage, and if
+-       * not, return EINVAL (the same error that
+-       * generic_file_readonly_mmap returns in that case).
+-       */
+-      lower_file = unionfs_lower_file(file);
+-      if (willwrite && !lower_file->f_mapping->a_ops->writepage) {
+-              err = -EINVAL;
+-              printk("unionfs: branch %d file system does not support "
+-                     "writeable mmap\n", fbstart(file));
+-      } else {
+-              err = generic_file_mmap(file, vma);
+-              if (err)
+-                      printk("unionfs: generic_file_mmap failed %d\n", err);
+-      }
+-
+-out:
+-      unionfs_read_unlock(file->f_path.dentry->d_sb);
+-      return err;
+-}
+-
+-struct file_operations unionfs_main_fops = {
+-      .llseek         = generic_file_llseek,
+-      .read           = unionfs_read,
+-      .aio_read       = unionfs_aio_read,
+-      .write          = unionfs_write,
+-      .aio_write      = generic_file_aio_write,
+-      .readdir        = unionfs_file_readdir,
+-      .unlocked_ioctl = unionfs_ioctl,
+-      .mmap           = unionfs_mmap,
+-      .open           = unionfs_open,
+-      .flush          = unionfs_flush,
+-      .release        = unionfs_file_release,
+-      .fsync          = file_fsync,
+-      .sendfile       = generic_file_sendfile,
+-};
+diff -Nurb linux-2.6.22-590/fs/unionfs/inode.c linux-2.6.22-570/fs/unionfs/inode.c
+--- linux-2.6.22-590/fs/unionfs/inode.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/inode.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,1138 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-static int unionfs_create(struct inode *parent, struct dentry *dentry,
+-                        int mode, struct nameidata *nd)
+-{
+-      int err = 0;
+-      struct dentry *hidden_dentry = NULL;
+-      struct dentry *wh_dentry = NULL;
+-      struct dentry *new_hidden_dentry;
+-      struct dentry *hidden_parent_dentry = NULL;
+-      int bindex = 0, bstart;
+-      char *name = NULL;
+-      int valid = 0;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      unionfs_lock_dentry(dentry->d_parent);
+-      valid = __unionfs_d_revalidate_chain(dentry->d_parent, nd);
+-      unionfs_unlock_dentry(dentry->d_parent);
+-      if (!valid) {
+-              err = -ESTALE;  /* same as what real_lookup does */
+-              goto out;
+-      }
+-      valid = __unionfs_d_revalidate_chain(dentry, nd);
+-      /*
+-       * It's only a bug if this dentry was not negative and couldn't be
+-       * revalidated (shouldn't happen).
+-       */
+-      BUG_ON(!valid && dentry->d_inode);
+-
+-      /* We start out in the leftmost branch. */
+-      bstart = dbstart(dentry);
+-      hidden_dentry = unionfs_lower_dentry(dentry);
+-
+-      /*
+-       * check if whiteout exists in this branch, i.e. lookup .wh.foo
+-       * first.
+-       */
+-      name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
+-      if (IS_ERR(name)) {
+-              err = PTR_ERR(name);
+-              goto out;
+-      }
+-
+-      wh_dentry = lookup_one_len(name, hidden_dentry->d_parent,
+-                                 dentry->d_name.len + UNIONFS_WHLEN);
+-      if (IS_ERR(wh_dentry)) {
+-              err = PTR_ERR(wh_dentry);
+-              wh_dentry = NULL;
+-              goto out;
+-      }
+-
+-      if (wh_dentry->d_inode) {
+-              /*
+-               * .wh.foo has been found.
+-               * First truncate it and then rename it to foo (hence having
+-               * the same overall effect as a normal create.
+-               */
+-              struct dentry *hidden_dir_dentry;
+-              struct iattr newattrs;
+-
+-              mutex_lock(&wh_dentry->d_inode->i_mutex);
+-              newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_ATIME
+-                      | ATTR_MTIME | ATTR_UID | ATTR_GID | ATTR_FORCE
+-                      | ATTR_KILL_SUID | ATTR_KILL_SGID;
+-
+-              newattrs.ia_mode = mode & ~current->fs->umask;
+-              newattrs.ia_uid = current->fsuid;
+-              newattrs.ia_gid = current->fsgid;
+-
+-              if (wh_dentry->d_inode->i_size != 0) {
+-                      newattrs.ia_valid |= ATTR_SIZE;
+-                      newattrs.ia_size = 0;
+-              }
+-
+-              err = notify_change(wh_dentry, &newattrs);
+-
+-              mutex_unlock(&wh_dentry->d_inode->i_mutex);
+-
+-              if (err)
+-                      printk(KERN_WARNING "unionfs: %s:%d: notify_change "
+-                             "failed: %d, ignoring..\n",
+-                             __FILE__, __LINE__, err);
+-
+-              new_hidden_dentry = unionfs_lower_dentry(dentry);
+-              dget(new_hidden_dentry);
+-
+-              hidden_dir_dentry = dget_parent(wh_dentry);
+-              lock_rename(hidden_dir_dentry, hidden_dir_dentry);
+-
+-              if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
+-                      err = vfs_rename(hidden_dir_dentry->d_inode,
+-                                       wh_dentry,
+-                                       hidden_dir_dentry->d_inode,
+-                                       new_hidden_dentry);
+-              }
+-              if (!err) {
+-                      fsstack_copy_attr_times(parent,
+-                                              new_hidden_dentry->d_parent->
+-                                              d_inode);
+-                      fsstack_copy_inode_size(parent,
+-                                              new_hidden_dentry->d_parent->
+-                                              d_inode);
+-                      parent->i_nlink = unionfs_get_nlinks(parent);
+-              }
+-
+-              unlock_rename(hidden_dir_dentry, hidden_dir_dentry);
+-              dput(hidden_dir_dentry);
+-
+-              dput(new_hidden_dentry);
+-
+-              if (err) {
+-                      /* exit if the error returned was NOT -EROFS */
+-                      if (!IS_COPYUP_ERR(err))
+-                              goto out;
+-                      /*
+-                       * We were not able to create the file in this
+-                       * branch, so, we try to create it in one branch to
+-                       * left
+-                       */
+-                      bstart--;
+-              } else {
+-                      /*
+-                       * reset the unionfs dentry to point to the .wh.foo
+-                       * entry.
+-                       */
+-
+-                      /* Discard any old reference. */
+-                      dput(unionfs_lower_dentry(dentry));
+-
+-                      /* Trade one reference to another. */
+-                      unionfs_set_lower_dentry_idx(dentry, bstart,
+-                                                   wh_dentry);
+-                      wh_dentry = NULL;
+-
+-                      err = unionfs_interpose(dentry, parent->i_sb, 0);
+-                      goto out;
+-              }
+-      }
+-
+-      for (bindex = bstart; bindex >= 0; bindex--) {
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (!hidden_dentry) {
+-                      /*
+-                       * if hidden_dentry is NULL, create the entire
+-                       * dentry directory structure in branch 'bindex'.
+-                       * hidden_dentry will NOT be null when bindex == bstart
+-                       * because lookup passed as a negative unionfs dentry
+-                       * pointing to a lone negative underlying dentry.
+-                       */
+-                      hidden_dentry = create_parents(parent, dentry, bindex);
+-                      if (!hidden_dentry || IS_ERR(hidden_dentry)) {
+-                              if (IS_ERR(hidden_dentry))
+-                                      err = PTR_ERR(hidden_dentry);
+-                              continue;
+-                      }
+-              }
+-
+-              hidden_parent_dentry = lock_parent(hidden_dentry);
+-              if (IS_ERR(hidden_parent_dentry)) {
+-                      err = PTR_ERR(hidden_parent_dentry);
+-                      goto out;
+-              }
+-              /* We shouldn't create things in a read-only branch. */
+-              if (!(err = is_robranch_super(dentry->d_sb, bindex)))
+-                      err = vfs_create(hidden_parent_dentry->d_inode,
+-                                       hidden_dentry, mode, nd);
+-
+-              if (err || !hidden_dentry->d_inode) {
+-                      unlock_dir(hidden_parent_dentry);
+-
+-                      /* break out of for loop if the error wasn't  -EROFS */
+-                      if (!IS_COPYUP_ERR(err))
+-                              break;
+-              } else {
+-                      err = unionfs_interpose(dentry, parent->i_sb, 0);
+-                      if (!err) {
+-                              fsstack_copy_attr_times(parent,
+-                                                      hidden_parent_dentry->
+-                                                      d_inode);
+-                              fsstack_copy_inode_size(parent,
+-                                                      hidden_parent_dentry->
+-                                                      d_inode);
+-                              /* update no. of links on parent directory */
+-                              parent->i_nlink = unionfs_get_nlinks(parent);
+-                      }
+-                      unlock_dir(hidden_parent_dentry);
+-                      break;
+-              }
+-      }
+-
+-out:
+-      dput(wh_dentry);
+-      kfree(name);
+-
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(dentry->d_sb);
+-      return err;
+-}
+-
+-static struct dentry *unionfs_lookup(struct inode *parent,
+-                                   struct dentry *dentry,
+-                                   struct nameidata *nd)
+-{
+-      struct path path_save;
+-      struct dentry *ret;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-
+-      /* save the dentry & vfsmnt from namei */
+-      if (nd) {
+-              path_save.dentry = nd->dentry;
+-              path_save.mnt = nd->mnt;
+-      }
+-
+-      /* The locking is done by unionfs_lookup_backend. */
+-      ret = unionfs_lookup_backend(dentry, nd, INTERPOSE_LOOKUP);
+-
+-      /* restore the dentry & vfsmnt in namei */
+-      if (nd) {
+-              nd->dentry = path_save.dentry;
+-              nd->mnt = path_save.mnt;
+-      }
+-
+-      unionfs_read_unlock(dentry->d_sb);
+-
+-      return ret;
+-}
+-
+-static int unionfs_link(struct dentry *old_dentry, struct inode *dir,
+-                      struct dentry *new_dentry)
+-{
+-      int err = 0;
+-      struct dentry *hidden_old_dentry = NULL;
+-      struct dentry *hidden_new_dentry = NULL;
+-      struct dentry *hidden_dir_dentry = NULL;
+-      struct dentry *whiteout_dentry;
+-      char *name = NULL;
+-
+-      unionfs_read_lock(old_dentry->d_sb);
+-      unionfs_double_lock_dentry(new_dentry, old_dentry);
+-
+-      if (!__unionfs_d_revalidate_chain(old_dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-      if (new_dentry->d_inode &&
+-          !__unionfs_d_revalidate_chain(new_dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      hidden_new_dentry = unionfs_lower_dentry(new_dentry);
+-
+-      /*
+-       * check if whiteout exists in the branch of new dentry, i.e. lookup
+-       * .wh.foo first. If present, delete it
+-       */
+-      name = alloc_whname(new_dentry->d_name.name, new_dentry->d_name.len);
+-      if (IS_ERR(name)) {
+-              err = PTR_ERR(name);
+-              goto out;
+-      }
+-
+-      whiteout_dentry = lookup_one_len(name, hidden_new_dentry->d_parent,
+-                                       new_dentry->d_name.len +
+-                                       UNIONFS_WHLEN);
+-      if (IS_ERR(whiteout_dentry)) {
+-              err = PTR_ERR(whiteout_dentry);
+-              goto out;
+-      }
+-
+-      if (!whiteout_dentry->d_inode) {
+-              dput(whiteout_dentry);
+-              whiteout_dentry = NULL;
+-      } else {
+-              /* found a .wh.foo entry, unlink it and then call vfs_link() */
+-              hidden_dir_dentry = lock_parent(whiteout_dentry);
+-              err = is_robranch_super(new_dentry->d_sb, dbstart(new_dentry));
+-              if (!err)
+-                      err = vfs_unlink(hidden_dir_dentry->d_inode,
+-                                       whiteout_dentry);
+-
+-              fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
+-              dir->i_nlink = unionfs_get_nlinks(dir);
+-              unlock_dir(hidden_dir_dentry);
+-              hidden_dir_dentry = NULL;
+-              dput(whiteout_dentry);
+-              if (err)
+-                      goto out;
+-      }
+-
+-      if (dbstart(old_dentry) != dbstart(new_dentry)) {
+-              hidden_new_dentry =
+-                      create_parents(dir, new_dentry, dbstart(old_dentry));
+-              err = PTR_ERR(hidden_new_dentry);
+-              if (IS_COPYUP_ERR(err))
+-                      goto docopyup;
+-              if (!hidden_new_dentry || IS_ERR(hidden_new_dentry))
+-                      goto out;
+-      }
+-      hidden_new_dentry = unionfs_lower_dentry(new_dentry);
+-      hidden_old_dentry = unionfs_lower_dentry(old_dentry);
+-
+-      BUG_ON(dbstart(old_dentry) != dbstart(new_dentry));
+-      hidden_dir_dentry = lock_parent(hidden_new_dentry);
+-      if (!(err = is_robranch(old_dentry)))
+-              err = vfs_link(hidden_old_dentry, hidden_dir_dentry->d_inode,
+-                             hidden_new_dentry);
+-      unlock_dir(hidden_dir_dentry);
+-
+-docopyup:
+-      if (IS_COPYUP_ERR(err)) {
+-              int old_bstart = dbstart(old_dentry);
+-              int bindex;
+-
+-              for (bindex = old_bstart - 1; bindex >= 0; bindex--) {
+-                      err = copyup_dentry(old_dentry->d_parent->d_inode,
+-                                          old_dentry, old_bstart,
+-                                          bindex, NULL,
+-                                          old_dentry->d_inode->i_size);
+-                      if (!err) {
+-                              hidden_new_dentry =
+-                                      create_parents(dir, new_dentry,
+-                                                     bindex);
+-                              hidden_old_dentry =
+-                                      unionfs_lower_dentry(old_dentry);
+-                              hidden_dir_dentry =
+-                                      lock_parent(hidden_new_dentry);
+-                              /* do vfs_link */
+-                              err = vfs_link(hidden_old_dentry,
+-                                             hidden_dir_dentry->d_inode,
+-                                             hidden_new_dentry);
+-                              unlock_dir(hidden_dir_dentry);
+-                              goto check_link;
+-                      }
+-              }
+-              goto out;
+-      }
+-
+-check_link:
+-      if (err || !hidden_new_dentry->d_inode)
+-              goto out;
+-
+-      /* Its a hard link, so use the same inode */
+-      new_dentry->d_inode = igrab(old_dentry->d_inode);
+-      d_instantiate(new_dentry, new_dentry->d_inode);
+-      fsstack_copy_attr_all(dir, hidden_new_dentry->d_parent->d_inode,
+-                            unionfs_get_nlinks);
+-      fsstack_copy_inode_size(dir, hidden_new_dentry->d_parent->d_inode);
+-
+-      /* propagate number of hard-links */
+-      old_dentry->d_inode->i_nlink = unionfs_get_nlinks(old_dentry->d_inode);
+-
+-out:
+-      if (!new_dentry->d_inode)
+-              d_drop(new_dentry);
+-
+-      kfree(name);
+-
+-      unionfs_unlock_dentry(new_dentry);
+-      unionfs_unlock_dentry(old_dentry);
+-
+-      unionfs_read_unlock(old_dentry->d_sb);
+-
+-      return err;
+-}
+-
+-static int unionfs_symlink(struct inode *dir, struct dentry *dentry,
+-                         const char *symname)
+-{
+-      int err = 0;
+-      struct dentry *hidden_dentry = NULL;
+-      struct dentry *whiteout_dentry = NULL;
+-      struct dentry *hidden_dir_dentry = NULL;
+-      umode_t mode;
+-      int bindex = 0, bstart;
+-      char *name = NULL;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      if (dentry->d_inode &&
+-          !__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      /* We start out in the leftmost branch. */
+-      bstart = dbstart(dentry);
+-
+-      hidden_dentry = unionfs_lower_dentry(dentry);
+-
+-      /*
+-       * check if whiteout exists in this branch, i.e. lookup .wh.foo
+-       * first. If present, delete it
+-       */
+-      name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
+-      if (IS_ERR(name)) {
+-              err = PTR_ERR(name);
+-              goto out;
+-      }
+-
+-      whiteout_dentry =
+-              lookup_one_len(name, hidden_dentry->d_parent,
+-                             dentry->d_name.len + UNIONFS_WHLEN);
+-      if (IS_ERR(whiteout_dentry)) {
+-              err = PTR_ERR(whiteout_dentry);
+-              goto out;
+-      }
+-
+-      if (!whiteout_dentry->d_inode) {
+-              dput(whiteout_dentry);
+-              whiteout_dentry = NULL;
+-      } else {
+-              /*
+-               * found a .wh.foo entry, unlink it and then call
+-               * vfs_symlink().
+-               */
+-              hidden_dir_dentry = lock_parent(whiteout_dentry);
+-
+-              if (!(err = is_robranch_super(dentry->d_sb, bstart)))
+-                      err = vfs_unlink(hidden_dir_dentry->d_inode,
+-                                       whiteout_dentry);
+-              dput(whiteout_dentry);
+-
+-              fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
+-              /* propagate number of hard-links */
+-              dir->i_nlink = unionfs_get_nlinks(dir);
+-
+-              unlock_dir(hidden_dir_dentry);
+-
+-              if (err) {
+-                      /* exit if the error returned was NOT -EROFS */
+-                      if (!IS_COPYUP_ERR(err))
+-                              goto out;
+-                      /*
+-                       * should now try to create symlink in the another
+-                       * branch.
+-                       */
+-                      bstart--;
+-              }
+-      }
+-
+-      /*
+-       * deleted whiteout if it was present, now do a normal vfs_symlink()
+-       * with possible recursive directory creation
+-       */
+-      for (bindex = bstart; bindex >= 0; bindex--) {
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (!hidden_dentry) {
+-                      /*
+-                       * if hidden_dentry is NULL, create the entire
+-                       * dentry directory structure in branch 'bindex'.
+-                       * hidden_dentry will NOT be null when bindex ==
+-                       * bstart because lookup passed as a negative
+-                       * unionfs dentry pointing to a lone negative
+-                       * underlying dentry
+-                       */
+-                      hidden_dentry = create_parents(dir, dentry, bindex);
+-                      if (!hidden_dentry || IS_ERR(hidden_dentry)) {
+-                              if (IS_ERR(hidden_dentry))
+-                                      err = PTR_ERR(hidden_dentry);
+-
+-                              printk(KERN_DEBUG "unionfs: hidden dentry "
+-                                     "NULL (or error) for bindex = %d\n",
+-                                     bindex);
+-                              continue;
+-                      }
+-              }
+-
+-              hidden_dir_dentry = lock_parent(hidden_dentry);
+-
+-              if (!(err = is_robranch_super(dentry->d_sb, bindex))) {
+-                      mode = S_IALLUGO;
+-                      err =
+-                              vfs_symlink(hidden_dir_dentry->d_inode,
+-                                          hidden_dentry, symname, mode);
+-              }
+-              unlock_dir(hidden_dir_dentry);
+-
+-              if (err || !hidden_dentry->d_inode) {
+-                      /*
+-                       * break out of for loop if error returned was NOT
+-                       * -EROFS.
+-                       */
+-                      if (!IS_COPYUP_ERR(err))
+-                              break;
+-              } else {
+-                      err = unionfs_interpose(dentry, dir->i_sb, 0);
+-                      if (!err) {
+-                              fsstack_copy_attr_times(dir,
+-                                                      hidden_dir_dentry->
+-                                                      d_inode);
+-                              fsstack_copy_inode_size(dir,
+-                                                      hidden_dir_dentry->
+-                                                      d_inode);
+-                              /*
+-                               * update number of links on parent
+-                               * directory.
+-                               */
+-                              dir->i_nlink = unionfs_get_nlinks(dir);
+-                      }
+-                      break;
+-              }
+-      }
+-
+-out:
+-      if (!dentry->d_inode)
+-              d_drop(dentry);
+-
+-      kfree(name);
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(dentry->d_sb);
+-      return err;
+-}
+-
+-static int unionfs_mkdir(struct inode *parent, struct dentry *dentry, int mode)
+-{
+-      int err = 0;
+-      struct dentry *hidden_dentry = NULL, *whiteout_dentry = NULL;
+-      struct dentry *hidden_parent_dentry = NULL;
+-      int bindex = 0, bstart;
+-      char *name = NULL;
+-      int whiteout_unlinked = 0;
+-      struct sioq_args args;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      if (dentry->d_inode &&
+-          !__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      bstart = dbstart(dentry);
+-
+-      hidden_dentry = unionfs_lower_dentry(dentry);
+-
+-      /*
+-       * check if whiteout exists in this branch, i.e. lookup .wh.foo
+-       * first.
+-       */
+-      name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
+-      if (IS_ERR(name)) {
+-              err = PTR_ERR(name);
+-              goto out;
+-      }
+-
+-      whiteout_dentry = lookup_one_len(name, hidden_dentry->d_parent,
+-                                       dentry->d_name.len + UNIONFS_WHLEN);
+-      if (IS_ERR(whiteout_dentry)) {
+-              err = PTR_ERR(whiteout_dentry);
+-              goto out;
+-      }
+-
+-      if (!whiteout_dentry->d_inode) {
+-              dput(whiteout_dentry);
+-              whiteout_dentry = NULL;
+-      } else {
+-              hidden_parent_dentry = lock_parent(whiteout_dentry);
+-
+-              /* found a.wh.foo entry, remove it then do vfs_mkdir */
+-              if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
+-                      args.unlink.parent = hidden_parent_dentry->d_inode;
+-                      args.unlink.dentry = whiteout_dentry;
+-                      run_sioq(__unionfs_unlink, &args);
+-                      err = args.err;
+-              }
+-              dput(whiteout_dentry);
+-
+-              unlock_dir(hidden_parent_dentry);
+-
+-              if (err) {
+-                      /* exit if the error returned was NOT -EROFS */
+-                      if (!IS_COPYUP_ERR(err))
+-                              goto out;
+-                      bstart--;
+-              } else
+-                      whiteout_unlinked = 1;
+-      }
+-
+-      for (bindex = bstart; bindex >= 0; bindex--) {
+-              int i;
+-              int bend = dbend(dentry);
+-
+-              if (is_robranch_super(dentry->d_sb, bindex))
+-                      continue;
+-
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (!hidden_dentry) {
+-                      hidden_dentry = create_parents(parent, dentry, bindex);
+-                      if (!hidden_dentry || IS_ERR(hidden_dentry)) {
+-                              printk(KERN_DEBUG "unionfs: hidden dentry "
+-                                     " NULL for bindex = %d\n", bindex);
+-                              continue;
+-                      }
+-              }
+-
+-              hidden_parent_dentry = lock_parent(hidden_dentry);
+-
+-              if (IS_ERR(hidden_parent_dentry)) {
+-                      err = PTR_ERR(hidden_parent_dentry);
+-                      goto out;
+-              }
+-
+-              err = vfs_mkdir(hidden_parent_dentry->d_inode, hidden_dentry,
+-                              mode);
+-
+-              unlock_dir(hidden_parent_dentry);
+-
+-              /* did the mkdir succeed? */
+-              if (err)
+-                      break;
+-
+-              for (i = bindex + 1; i < bend; i++) {
+-                      if (unionfs_lower_dentry_idx(dentry, i)) {
+-                              dput(unionfs_lower_dentry_idx(dentry, i));
+-                              unionfs_set_lower_dentry_idx(dentry, i, NULL);
+-                      }
+-              }
+-              set_dbend(dentry, bindex);
+-
+-              err = unionfs_interpose(dentry, parent->i_sb, 0);
+-              if (!err) {
+-                      fsstack_copy_attr_times(parent,
+-                                              hidden_parent_dentry->d_inode);
+-                      fsstack_copy_inode_size(parent,
+-                                              hidden_parent_dentry->d_inode);
+-
+-                      /* update number of links on parent directory */
+-                      parent->i_nlink = unionfs_get_nlinks(parent);
+-              }
+-
+-              err = make_dir_opaque(dentry, dbstart(dentry));
+-              if (err) {
+-                      printk(KERN_ERR "unionfs: mkdir: error creating "
+-                             ".wh.__dir_opaque: %d\n", err);
+-                      goto out;
+-              }
+-
+-              /* we are done! */
+-              break;
+-      }
+-
+-out:
+-      if (!dentry->d_inode)
+-              d_drop(dentry);
+-
+-      kfree(name);
+-
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(dentry->d_sb);
+-      return err;
+-}
+-
+-static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+-                       dev_t dev)
+-{
+-      int err = 0;
+-      struct dentry *hidden_dentry = NULL, *whiteout_dentry = NULL;
+-      struct dentry *hidden_parent_dentry = NULL;
+-      int bindex = 0, bstart;
+-      char *name = NULL;
+-      int whiteout_unlinked = 0;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      if (dentry->d_inode &&
+-          !__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      bstart = dbstart(dentry);
+-
+-      hidden_dentry = unionfs_lower_dentry(dentry);
+-
+-      /*
+-       * check if whiteout exists in this branch, i.e. lookup .wh.foo
+-       * first.
+-       */
+-      name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
+-      if (IS_ERR(name)) {
+-              err = PTR_ERR(name);
+-              goto out;
+-      }
+-
+-      whiteout_dentry = lookup_one_len(name, hidden_dentry->d_parent,
+-                                       dentry->d_name.len + UNIONFS_WHLEN);
+-      if (IS_ERR(whiteout_dentry)) {
+-              err = PTR_ERR(whiteout_dentry);
+-              goto out;
+-      }
+-
+-      if (!whiteout_dentry->d_inode) {
+-              dput(whiteout_dentry);
+-              whiteout_dentry = NULL;
+-      } else {
+-              /* found .wh.foo, unlink it */
+-              hidden_parent_dentry = lock_parent(whiteout_dentry);
+-
+-              /* found a.wh.foo entry, remove it then do vfs_mkdir */
+-              if (!(err = is_robranch_super(dentry->d_sb, bstart)))
+-                      err = vfs_unlink(hidden_parent_dentry->d_inode,
+-                                       whiteout_dentry);
+-              dput(whiteout_dentry);
+-
+-              unlock_dir(hidden_parent_dentry);
+-
+-              if (err) {
+-                      if (!IS_COPYUP_ERR(err))
+-                              goto out;
+-
+-                      bstart--;
+-              } else
+-                      whiteout_unlinked = 1;
+-      }
+-
+-      for (bindex = bstart; bindex >= 0; bindex--) {
+-              if (is_robranch_super(dentry->d_sb, bindex))
+-                      continue;
+-
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (!hidden_dentry) {
+-                      hidden_dentry = create_parents(dir, dentry, bindex);
+-                      if (IS_ERR(hidden_dentry)) {
+-                              printk(KERN_DEBUG "unionfs: failed to create "
+-                                     "parents on %d, err = %ld\n",
+-                                     bindex, PTR_ERR(hidden_dentry));
+-                              continue;
+-                      }
+-              }
+-
+-              hidden_parent_dentry = lock_parent(hidden_dentry);
+-              if (IS_ERR(hidden_parent_dentry)) {
+-                      err = PTR_ERR(hidden_parent_dentry);
+-                      goto out;
+-              }
+-
+-              err = vfs_mknod(hidden_parent_dentry->d_inode,
+-                              hidden_dentry, mode, dev);
+-
+-              if (err) {
+-                      unlock_dir(hidden_parent_dentry);
+-                      break;
+-              }
+-
+-              err = unionfs_interpose(dentry, dir->i_sb, 0);
+-              if (!err) {
+-                      fsstack_copy_attr_times(dir,
+-                                              hidden_parent_dentry->d_inode);
+-                      fsstack_copy_inode_size(dir,
+-                                              hidden_parent_dentry->d_inode);
+-                      /* update number of links on parent directory */
+-                      dir->i_nlink = unionfs_get_nlinks(dir);
+-              }
+-              unlock_dir(hidden_parent_dentry);
+-
+-              break;
+-      }
+-
+-out:
+-      if (!dentry->d_inode)
+-              d_drop(dentry);
+-
+-      kfree(name);
+-
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(dentry->d_sb);
+-      return err;
+-}
+-
+-static int unionfs_readlink(struct dentry *dentry, char __user *buf,
+-                          int bufsiz)
+-{
+-      int err;
+-      struct dentry *hidden_dentry;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      hidden_dentry = unionfs_lower_dentry(dentry);
+-
+-      if (!hidden_dentry->d_inode->i_op ||
+-          !hidden_dentry->d_inode->i_op->readlink) {
+-              err = -EINVAL;
+-              goto out;
+-      }
+-
+-      err = hidden_dentry->d_inode->i_op->readlink(hidden_dentry,
+-                                                   buf, bufsiz);
+-      if (err > 0)
+-              fsstack_copy_attr_atime(dentry->d_inode,
+-                                      hidden_dentry->d_inode);
+-
+-out:
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(dentry->d_sb);
+-      return err;
+-}
+-
+-/*
+- * Check if dentry is valid or not, as per our generation numbers.
+- * @dentry: dentry to check.
+- * Returns 1 (valid) or 0 (invalid/stale).
+- */
+-static inline int is_valid_dentry(struct dentry *dentry)
+-{
+-      BUG_ON(!UNIONFS_D(dentry));
+-      BUG_ON(!UNIONFS_SB(dentry->d_sb));
+-      return (atomic_read(&UNIONFS_D(dentry)->generation) ==
+-                      atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
+-}
+-
+-/* We don't lock the dentry here, because readlink does the heavy lifting. */
+-static void *unionfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+-{
+-      char *buf;
+-      int len = PAGE_SIZE, err;
+-      mm_segment_t old_fs;
+-
+-      /*
+-       * FIXME: Really nasty...we can get called from two distinct places:
+-       * 1) read_link - locks the dentry
+-       * 2) VFS lookup code - does NOT lock the dentry
+-       *
+-       * The proper thing would be to call dentry revalidate. It however
+-       * expects a locked dentry, and we can't cleanly guarantee that.
+-       */
+-      BUG_ON(!is_valid_dentry(dentry));
+-
+-      unionfs_read_lock(dentry->d_sb);
+-
+-      /* This is freed by the put_link method assuming a successful call. */
+-      buf = kmalloc(len, GFP_KERNEL);
+-      if (!buf) {
+-              err = -ENOMEM;
+-              goto out;
+-      }
+-
+-      /* read the symlink, and then we will follow it */
+-      old_fs = get_fs();
+-      set_fs(KERNEL_DS);
+-      err = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len);
+-      set_fs(old_fs);
+-      if (err < 0) {
+-              kfree(buf);
+-              buf = NULL;
+-              goto out;
+-      }
+-      buf[err] = 0;
+-      nd_set_link(nd, buf);
+-      err = 0;
+-
+-out:
+-      unionfs_read_unlock(dentry->d_sb);
+-      return ERR_PTR(err);
+-}
+-
+-/* FIXME: We may not have to lock here */
+-static void unionfs_put_link(struct dentry *dentry, struct nameidata *nd,
+-                           void *cookie)
+-{
+-      unionfs_read_lock(dentry->d_sb);
+-      kfree(nd_get_link(nd));
+-      unionfs_read_unlock(dentry->d_sb);
+-}
+-
+-/*
+- * Basically copied from the kernel vfs permission(), but we've changed
+- * the following:
+- *   (1) the IS_RDONLY check is skipped, and
+- *   (2) if you set the mount option `mode=nfsro', we assume that -EACCES
+- *   means that the export is read-only and we should check standard Unix
+- *   permissions.  This means that NFS ACL checks (or other advanced
+- *   permission features) are bypassed. Note however, that we do call
+- *   security_inode_permission, and therefore security inside SELinux, etc.
+- *   are performed.
+- */
+-static int inode_permission(struct inode *inode, int mask,
+-                          struct nameidata *nd, int bindex)
+-{
+-      int retval, submask;
+-
+-      if (mask & MAY_WRITE) {
+-              /* The first branch is allowed to be really readonly. */
+-              if (bindex == 0) {
+-                      umode_t mode = inode->i_mode;
+-                      if (IS_RDONLY(inode) &&
+-                          (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+-                              return -EROFS;
+-              }
+-              /*
+-               * Nobody gets write access to an immutable file.
+-               */
+-              if (IS_IMMUTABLE(inode))
+-                      return -EACCES;
+-      }
+-
+-      /* Ordinary permission routines do not understand MAY_APPEND. */
+-      submask = mask & ~MAY_APPEND;
+-      if (inode->i_op && inode->i_op->permission) {
+-              retval = inode->i_op->permission(inode, submask, nd);
+-              if ((retval == -EACCES) && (submask & MAY_WRITE) &&
+-                  (!strcmp("nfs", (inode)->i_sb->s_type->name)) &&
+-                  (nd) && (nd->mnt) && (nd->mnt->mnt_sb)) {
+-                      int perms;
+-                      perms = branchperms(nd->mnt->mnt_sb, bindex);
+-                      if (perms & MAY_NFSRO)
+-                              retval = generic_permission(inode, submask,
+-                                                          NULL);
+-              }
+-      } else
+-              retval = generic_permission(inode, submask, NULL);
+-
+-      if (retval && retval != -EROFS) /* ignore EROFS */
+-              return retval;
+-
+-      retval = security_inode_permission(inode, mask, nd);
+-      return ((retval == -EROFS) ? 0 : retval);       /* ignore EROFS */
+-}
+-
+-static int unionfs_permission(struct inode *inode, int mask,
+-                            struct nameidata *nd)
+-{
+-      struct inode *hidden_inode = NULL;
+-      int err = 0;
+-      int bindex, bstart, bend;
+-      const int is_file = !S_ISDIR(inode->i_mode);
+-      const int write_mask = (mask & MAY_WRITE) && !(mask & MAY_READ);
+-
+-      unionfs_read_lock(inode->i_sb);
+-
+-      bstart = ibstart(inode);
+-      bend = ibend(inode);
+-      if (bstart < 0 || bend < 0) {
+-              /*
+-               * With branch-management, we can get a stale inode here.
+-               * If so, we return ESTALE back to link_path_walk, which
+-               * would discard the dcache entry and re-lookup the
+-               * dentry+inode.  This should be equivalent to issuing
+-               * __unionfs_d_revalidate_chain on nd.dentry here.
+-               */
+-              err = -ESTALE;  /* force revalidate */
+-              goto out;
+-      }
+-
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_inode = unionfs_lower_inode_idx(inode, bindex);
+-              if (!hidden_inode)
+-                      continue;
+-
+-              /*
+-               * check the condition for D-F-D underlying files/directories,
+-               * we don't have to check for files, if we are checking for
+-               * directories.
+-               */
+-              if (!is_file && !S_ISDIR(hidden_inode->i_mode))
+-                      continue;
+-
+-              /*
+-               * We use our own special version of permission, such that
+-               * only the first branch returns -EROFS.
+-               */
+-              err = inode_permission(hidden_inode, mask, nd, bindex);
+-
+-              /*
+-               * The permissions are an intersection of the overall directory
+-               * permissions, so we fail if one fails.
+-               */
+-              if (err)
+-                      goto out;
+-
+-              /* only the leftmost file matters. */
+-              if (is_file || write_mask) {
+-                      if (is_file && write_mask) {
+-                              err = get_write_access(hidden_inode);
+-                              if (!err)
+-                                      put_write_access(hidden_inode);
+-                      }
+-                      break;
+-              }
+-      }
+-
+-out:
+-      unionfs_read_unlock(inode->i_sb);
+-      return err;
+-}
+-
+-static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
+-{
+-      int err = 0;
+-      struct dentry *hidden_dentry;
+-      struct inode *inode = NULL;
+-      struct inode *hidden_inode = NULL;
+-      int bstart, bend, bindex;
+-      int i;
+-      int copyup = 0;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      bstart = dbstart(dentry);
+-      bend = dbend(dentry);
+-      inode = dentry->d_inode;
+-
+-      for (bindex = bstart; (bindex <= bend) || (bindex == bstart);
+-           bindex++) {
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (!hidden_dentry)
+-                      continue;
+-              BUG_ON(hidden_dentry->d_inode == NULL);
+-
+-              /* If the file is on a read only branch */
+-              if (is_robranch_super(dentry->d_sb, bindex)
+-                  || IS_RDONLY(hidden_dentry->d_inode)) {
+-                      if (copyup || (bindex != bstart))
+-                              continue;
+-                      /* Only if its the leftmost file, copyup the file */
+-                      for (i = bstart - 1; i >= 0; i--) {
+-                              loff_t size = dentry->d_inode->i_size;
+-                              if (ia->ia_valid & ATTR_SIZE)
+-                                      size = ia->ia_size;
+-                              err = copyup_dentry(dentry->d_parent->d_inode,
+-                                                  dentry, bstart, i, NULL,
+-                                                  size);
+-
+-                              if (!err) {
+-                                      copyup = 1;
+-                                      hidden_dentry =
+-                                              unionfs_lower_dentry(dentry);
+-                                      break;
+-                              }
+-                              /*
+-                               * if error is in the leftmost branch, pass
+-                               * it up.
+-                               */
+-                              if (i == 0)
+-                                      goto out;
+-                      }
+-
+-              }
+-              err = notify_change(hidden_dentry, ia);
+-              if (err)
+-                      goto out;
+-              break;
+-      }
+-
+-      /* for mmap */
+-      if (ia->ia_valid & ATTR_SIZE) {
+-              if (ia->ia_size != i_size_read(inode)) {
+-                      err = vmtruncate(inode, ia->ia_size);
+-                      if (err)
+-                              printk("unionfs_setattr: vmtruncate failed\n");
+-              }
+-      }
+-
+-      /* get the size from the first hidden inode */
+-      hidden_inode = unionfs_lower_inode(dentry->d_inode);
+-      fsstack_copy_attr_all(inode, hidden_inode, unionfs_get_nlinks);
+-      fsstack_copy_inode_size(inode, hidden_inode);
+-
+-out:
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(dentry->d_sb);
+-      return err;
+-}
+-
+-struct inode_operations unionfs_symlink_iops = {
+-      .readlink       = unionfs_readlink,
+-      .permission     = unionfs_permission,
+-      .follow_link    = unionfs_follow_link,
+-      .setattr        = unionfs_setattr,
+-      .put_link       = unionfs_put_link,
+-};
+-
+-struct inode_operations unionfs_dir_iops = {
+-      .create         = unionfs_create,
+-      .lookup         = unionfs_lookup,
+-      .link           = unionfs_link,
+-      .unlink         = unionfs_unlink,
+-      .symlink        = unionfs_symlink,
+-      .mkdir          = unionfs_mkdir,
+-      .rmdir          = unionfs_rmdir,
+-      .mknod          = unionfs_mknod,
+-      .rename         = unionfs_rename,
+-      .permission     = unionfs_permission,
+-      .setattr        = unionfs_setattr,
+-#ifdef CONFIG_UNION_FS_XATTR
+-      .setxattr       = unionfs_setxattr,
+-      .getxattr       = unionfs_getxattr,
+-      .removexattr    = unionfs_removexattr,
+-      .listxattr      = unionfs_listxattr,
+-#endif
+-};
+-
+-struct inode_operations unionfs_main_iops = {
+-      .permission     = unionfs_permission,
+-      .setattr        = unionfs_setattr,
+-#ifdef CONFIG_UNION_FS_XATTR
+-      .setxattr       = unionfs_setxattr,
+-      .getxattr       = unionfs_getxattr,
+-      .removexattr    = unionfs_removexattr,
+-      .listxattr      = unionfs_listxattr,
+-#endif
+-};
+diff -Nurb linux-2.6.22-590/fs/unionfs/lookup.c linux-2.6.22-570/fs/unionfs/lookup.c
+--- linux-2.6.22-590/fs/unionfs/lookup.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/lookup.c       1969-12-31 19:00:00.000000000 -0500
+@@ -1,549 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/* is the filename valid == !(whiteout for a file or opaque dir marker) */
+-static int is_validname(const char *name)
+-{
+-      if (!strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN))
+-              return 0;
+-      if (!strncmp(name, UNIONFS_DIR_OPAQUE_NAME,
+-                   sizeof(UNIONFS_DIR_OPAQUE_NAME) - 1))
+-              return 0;
+-      return 1;
+-}
+-
+-/* The rest of these are utility functions for lookup. */
+-static noinline int is_opaque_dir(struct dentry *dentry, int bindex)
+-{
+-      int err = 0;
+-      struct dentry *hidden_dentry;
+-      struct dentry *wh_hidden_dentry;
+-      struct inode *hidden_inode;
+-      struct sioq_args args;
+-
+-      hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-      hidden_inode = hidden_dentry->d_inode;
+-
+-      BUG_ON(!S_ISDIR(hidden_inode->i_mode));
+-
+-      mutex_lock(&hidden_inode->i_mutex);
+-
+-      if (!permission(hidden_inode, MAY_EXEC, NULL))
+-              wh_hidden_dentry =
+-                      lookup_one_len(UNIONFS_DIR_OPAQUE, hidden_dentry,
+-                                     sizeof(UNIONFS_DIR_OPAQUE) - 1);
+-      else {
+-              args.is_opaque.dentry = hidden_dentry;
+-              run_sioq(__is_opaque_dir, &args);
+-              wh_hidden_dentry = args.ret;
+-      }
+-
+-      mutex_unlock(&hidden_inode->i_mutex);
+-
+-      if (IS_ERR(wh_hidden_dentry)) {
+-              err = PTR_ERR(wh_hidden_dentry);
+-              goto out;
+-      }
+-
+-      /* This is an opaque dir iff wh_hidden_dentry is positive */
+-      err = !!wh_hidden_dentry->d_inode;
+-
+-      dput(wh_hidden_dentry);
+-out:
+-      return err;
+-}
+-
+-/* main (and complex) driver function for Unionfs's lookup */
+-struct dentry *unionfs_lookup_backend(struct dentry *dentry,
+-                                    struct nameidata *nd, int lookupmode)
+-{
+-      int err = 0;
+-      struct dentry *hidden_dentry = NULL;
+-      struct dentry *wh_hidden_dentry = NULL;
+-      struct dentry *hidden_dir_dentry = NULL;
+-      struct dentry *parent_dentry = NULL;
+-      int bindex, bstart, bend, bopaque;
+-      int dentry_count = 0;   /* Number of positive dentries. */
+-      int first_dentry_offset = -1; /* -1 is uninitialized */
+-      struct dentry *first_dentry = NULL;
+-      struct dentry *first_hidden_dentry = NULL;
+-      struct vfsmount *first_hidden_mnt = NULL;
+-      int locked_parent = 0;
+-      int locked_child = 0;
+-      int allocated_new_info = 0;
+-
+-      int opaque;
+-      char *whname = NULL;
+-      const char *name;
+-      int namelen;
+-
+-      /*
+-       * We should already have a lock on this dentry in the case of a
+-       * partial lookup, or a revalidation. Otherwise it is returned from
+-       * new_dentry_private_data already locked.
+-       */
+-      if (lookupmode == INTERPOSE_PARTIAL || lookupmode == INTERPOSE_REVAL ||
+-          lookupmode == INTERPOSE_REVAL_NEG)
+-              verify_locked(dentry);
+-      else {
+-              BUG_ON(UNIONFS_D(dentry) != NULL);
+-              locked_child = 1;
+-      }
+-
+-      switch(lookupmode) {
+-              case INTERPOSE_PARTIAL:
+-                      break;
+-              case INTERPOSE_LOOKUP:
+-                      if ((err = new_dentry_private_data(dentry)))
+-                              goto out;
+-                      allocated_new_info = 1;
+-                      break;
+-              default:
+-                      if ((err = realloc_dentry_private_data(dentry)))
+-                              goto out;
+-                      allocated_new_info = 1;
+-                      break;
+-      }
+-
+-      /* must initialize dentry operations */
+-      dentry->d_op = &unionfs_dops;
+-
+-      parent_dentry = dget_parent(dentry);
+-      /* We never partial lookup the root directory. */
+-      if (parent_dentry != dentry) {
+-              unionfs_lock_dentry(parent_dentry);
+-              locked_parent = 1;
+-      } else {
+-              dput(parent_dentry);
+-              parent_dentry = NULL;
+-              goto out;
+-      }
+-
+-      name = dentry->d_name.name;
+-      namelen = dentry->d_name.len;
+-
+-      /* No dentries should get created for possible whiteout names. */
+-      if (!is_validname(name)) {
+-              err = -EPERM;
+-              goto out_free;
+-      }
+-
+-      /* Now start the actual lookup procedure. */
+-      bstart = dbstart(parent_dentry);
+-      bend = dbend(parent_dentry);
+-      bopaque = dbopaque(parent_dentry);
+-      BUG_ON(bstart < 0);
+-
+-      /*
+-       * It would be ideal if we could convert partial lookups to only have
+-       * to do this work when they really need to.  It could probably improve
+-       * performance quite a bit, and maybe simplify the rest of the code.
+-       */
+-      if (lookupmode == INTERPOSE_PARTIAL) {
+-              bstart++;
+-              if ((bopaque != -1) && (bopaque < bend))
+-                      bend = bopaque;
+-      }
+-
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (lookupmode == INTERPOSE_PARTIAL && hidden_dentry)
+-                      continue;
+-              BUG_ON(hidden_dentry != NULL);
+-
+-              hidden_dir_dentry =
+-                      unionfs_lower_dentry_idx(parent_dentry, bindex);
+-
+-              /* if the parent hidden dentry does not exist skip this */
+-              if (!(hidden_dir_dentry && hidden_dir_dentry->d_inode))
+-                      continue;
+-
+-              /* also skip it if the parent isn't a directory. */
+-              if (!S_ISDIR(hidden_dir_dentry->d_inode->i_mode))
+-                      continue;
+-
+-              /* Reuse the whiteout name because its value doesn't change. */
+-              if (!whname) {
+-                      whname = alloc_whname(name, namelen);
+-                      if (IS_ERR(whname)) {
+-                              err = PTR_ERR(whname);
+-                              goto out_free;
+-                      }
+-              }
+-
+-              /* check if whiteout exists in this branch: lookup .wh.foo */
+-              wh_hidden_dentry = lookup_one_len(whname, hidden_dir_dentry,
+-                                                namelen + UNIONFS_WHLEN);
+-              if (IS_ERR(wh_hidden_dentry)) {
+-                      dput(first_hidden_dentry);
+-                      unionfs_mntput(first_dentry, first_dentry_offset);
+-                      err = PTR_ERR(wh_hidden_dentry);
+-                      goto out_free;
+-              }
+-
+-              if (wh_hidden_dentry->d_inode) {
+-                      /* We found a whiteout so lets give up. */
+-                      if (S_ISREG(wh_hidden_dentry->d_inode->i_mode)) {
+-                              set_dbend(dentry, bindex);
+-                              set_dbopaque(dentry, bindex);
+-                              dput(wh_hidden_dentry);
+-                              break;
+-                      }
+-                      err = -EIO;
+-                      printk(KERN_NOTICE "unionfs: EIO: invalid whiteout "
+-                             "entry type %d.\n",
+-                             wh_hidden_dentry->d_inode->i_mode);
+-                      dput(wh_hidden_dentry);
+-                      dput(first_hidden_dentry);
+-                      unionfs_mntput(first_dentry, first_dentry_offset);
+-                      goto out_free;
+-              }
+-
+-              dput(wh_hidden_dentry);
+-              wh_hidden_dentry = NULL;
+-
+-              /* Now do regular lookup; lookup foo */
+-              nd->dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              /* FIXME: fix following line for mount point crossing */
+-              nd->mnt = unionfs_lower_mnt_idx(parent_dentry, bindex);
+-
+-              hidden_dentry = lookup_one_len_nd(name, hidden_dir_dentry,
+-                                                namelen, nd);
+-              if (IS_ERR(hidden_dentry)) {
+-                      dput(first_hidden_dentry);
+-                      unionfs_mntput(first_dentry, first_dentry_offset);
+-                      err = PTR_ERR(hidden_dentry);
+-                      goto out_free;
+-              }
+-
+-              /*
+-               * Store the first negative dentry specially, because if they
+-               * are all negative we need this for future creates.
+-               */
+-              if (!hidden_dentry->d_inode) {
+-                      if (!first_hidden_dentry && (dbstart(dentry) == -1)) {
+-                              first_hidden_dentry = hidden_dentry;
+-                              /*
+-                               * FIXME: following line needs to be changed
+-                               * to allow mount-point crossing
+-                               */
+-                              first_dentry = parent_dentry;
+-                              first_hidden_mnt =
+-                                      unionfs_mntget(parent_dentry, bindex);
+-                              first_dentry_offset = bindex;
+-                      } else
+-                              dput(hidden_dentry);
+-
+-                      continue;
+-              }
+-
+-              /* number of positive dentries */
+-              dentry_count++;
+-
+-              /* store underlying dentry */
+-              if (dbstart(dentry) == -1)
+-                      set_dbstart(dentry, bindex);
+-              unionfs_set_lower_dentry_idx(dentry, bindex, hidden_dentry);
+-              /*
+-               * FIXME: the following line needs to get fixed to allow
+-               * mount-point crossing
+-               */
+-              unionfs_set_lower_mnt_idx(dentry, bindex,
+-                                        unionfs_mntget(parent_dentry,
+-                                                       bindex));
+-              set_dbend(dentry, bindex);
+-
+-              /* update parent directory's atime with the bindex */
+-              fsstack_copy_attr_atime(parent_dentry->d_inode,
+-                                      hidden_dir_dentry->d_inode);
+-
+-              /* We terminate file lookups here. */
+-              if (!S_ISDIR(hidden_dentry->d_inode->i_mode)) {
+-                      if (lookupmode == INTERPOSE_PARTIAL)
+-                              continue;
+-                      if (dentry_count == 1)
+-                              goto out_positive;
+-                      /* This can only happen with mixed D-*-F-* */
+-                      BUG_ON(!S_ISDIR(unionfs_lower_dentry(dentry)->
+-                                      d_inode->i_mode));
+-                      continue;
+-              }
+-
+-              opaque = is_opaque_dir(dentry, bindex);
+-              if (opaque < 0) {
+-                      dput(first_hidden_dentry);
+-                      unionfs_mntput(first_dentry, first_dentry_offset);
+-                      err = opaque;
+-                      goto out_free;
+-              } else if (opaque) {
+-                      set_dbend(dentry, bindex);
+-                      set_dbopaque(dentry, bindex);
+-                      break;
+-              }
+-      }
+-
+-      if (dentry_count)
+-              goto out_positive;
+-      else
+-              goto out_negative;
+-
+-out_negative:
+-      if (lookupmode == INTERPOSE_PARTIAL)
+-              goto out;
+-
+-      /* If we've only got negative dentries, then use the leftmost one. */
+-      if (lookupmode == INTERPOSE_REVAL) {
+-              if (dentry->d_inode)
+-                      UNIONFS_I(dentry->d_inode)->stale = 1;
+-
+-              goto out;
+-      }
+-      /* This should only happen if we found a whiteout. */
+-      if (first_dentry_offset == -1) {
+-              nd->dentry = dentry;
+-              /* FIXME: fix following line for mount point crossing */
+-              nd->mnt = unionfs_lower_mnt_idx(parent_dentry, bindex);
+-
+-              first_hidden_dentry =
+-                      lookup_one_len_nd(name, hidden_dir_dentry,
+-                                        namelen, nd);
+-              first_dentry_offset = bindex;
+-              if (IS_ERR(first_hidden_dentry)) {
+-                      err = PTR_ERR(first_hidden_dentry);
+-                      goto out;
+-              }
+-
+-              /*
+-               * FIXME: the following line needs to be changed to allow
+-               * mount-point crossing
+-               */
+-              first_dentry = dentry;
+-              first_hidden_mnt = unionfs_mntget(dentry, bindex);
+-      }
+-      unionfs_set_lower_dentry_idx(dentry, first_dentry_offset,
+-                                   first_hidden_dentry);
+-      unionfs_set_lower_mnt_idx(dentry, first_dentry_offset,
+-                                first_hidden_mnt);
+-      set_dbstart(dentry, first_dentry_offset);
+-      set_dbend(dentry, first_dentry_offset);
+-
+-      if (lookupmode == INTERPOSE_REVAL_NEG)
+-              BUG_ON(dentry->d_inode != NULL);
+-      else
+-              d_add(dentry, NULL);
+-      goto out;
+-
+-/* This part of the code is for positive dentries. */
+-out_positive:
+-      BUG_ON(dentry_count <= 0);
+-
+-      /*
+-       * If we're holding onto the first negative dentry & corresponding
+-       * vfsmount - throw it out.
+-       */
+-      dput(first_hidden_dentry);
+-      unionfs_mntput(first_dentry, first_dentry_offset);
+-
+-      /* Partial lookups need to re-interpose, or throw away older negs. */
+-      if (lookupmode == INTERPOSE_PARTIAL) {
+-              if (dentry->d_inode) {
+-                      unionfs_reinterpose(dentry);
+-                      goto out;
+-              }
+-
+-              /*
+-               * This somehow turned positive, so it is as if we had a
+-               * negative revalidation.
+-               */
+-              lookupmode = INTERPOSE_REVAL_NEG;
+-
+-              update_bstart(dentry);
+-              bstart = dbstart(dentry);
+-              bend = dbend(dentry);
+-      }
+-
+-      err = unionfs_interpose(dentry, dentry->d_sb, lookupmode);
+-      if (err)
+-              goto out_drop;
+-
+-      goto out;
+-
+-out_drop:
+-      d_drop(dentry);
+-
+-out_free:
+-      /* should dput all the underlying dentries on error condition */
+-      bstart = dbstart(dentry);
+-      if (bstart >= 0) {
+-              bend = dbend(dentry);
+-              for (bindex = bstart; bindex <= bend; bindex++) {
+-                      dput(unionfs_lower_dentry_idx(dentry, bindex));
+-                      unionfs_mntput(dentry, bindex);
+-              }
+-      }
+-      kfree(UNIONFS_D(dentry)->lower_paths);
+-      UNIONFS_D(dentry)->lower_paths = NULL;
+-      set_dbstart(dentry, -1);
+-      set_dbend(dentry, -1);
+-
+-out:
+-      if (!err && UNIONFS_D(dentry)) {
+-              BUG_ON(dbend(dentry) > UNIONFS_D(dentry)->bcount);
+-              BUG_ON(dbend(dentry) > sbmax(dentry->d_sb));
+-              BUG_ON(dbstart(dentry) < 0);
+-      }
+-      kfree(whname);
+-      if (locked_parent)
+-              unionfs_unlock_dentry(parent_dentry);
+-      dput(parent_dentry);
+-      if (locked_child || (err && allocated_new_info))
+-              unionfs_unlock_dentry(dentry);
+-      return ERR_PTR(err);
+-}
+-
+-/* This is a utility function that fills in a unionfs dentry */
+-int unionfs_partial_lookup(struct dentry *dentry)
+-{
+-      struct dentry *tmp;
+-      struct nameidata nd = { .flags = 0 };
+-
+-      tmp = unionfs_lookup_backend(dentry, &nd, INTERPOSE_PARTIAL);
+-      if (!tmp)
+-              return 0;
+-      if (IS_ERR(tmp))
+-              return PTR_ERR(tmp);
+-      /* need to change the interface */
+-      BUG_ON(tmp != dentry);
+-      return -ENOSYS;
+-}
+-
+-/* The dentry cache is just so we have properly sized dentries. */
+-static struct kmem_cache *unionfs_dentry_cachep;
+-int unionfs_init_dentry_cache(void)
+-{
+-      unionfs_dentry_cachep =
+-              kmem_cache_create("unionfs_dentry",
+-                                sizeof(struct unionfs_dentry_info),
+-                                0, SLAB_RECLAIM_ACCOUNT, NULL, NULL);
+-
+-      return (unionfs_dentry_cachep ? 0 : -ENOMEM);
+-}
+-
+-void unionfs_destroy_dentry_cache(void)
+-{
+-      if (unionfs_dentry_cachep)
+-              kmem_cache_destroy(unionfs_dentry_cachep);
+-}
+-
+-void free_dentry_private_data(struct dentry *dentry)
+-{
+-      if (!dentry || !dentry->d_fsdata)
+-              return;
+-      kmem_cache_free(unionfs_dentry_cachep, dentry->d_fsdata);
+-      dentry->d_fsdata = NULL;
+-}
+-
+-static inline int __realloc_dentry_private_data(struct dentry *dentry)
+-{
+-      struct unionfs_dentry_info *info = UNIONFS_D(dentry);
+-      void *p;
+-      int size;
+-
+-      BUG_ON(!info);
+-
+-      size = sizeof(struct path) * sbmax(dentry->d_sb);
+-      p = krealloc(info->lower_paths, size, GFP_ATOMIC);
+-      if (!p)
+-              return -ENOMEM;
+-
+-      info->lower_paths = p;
+-
+-      info->bstart = -1;
+-      info->bend = -1;
+-      info->bopaque = -1;
+-      info->bcount = sbmax(dentry->d_sb);
+-      atomic_set(&info->generation,
+-                      atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
+-
+-      memset(info->lower_paths, 0, size);
+-
+-      return 0;
+-}
+-
+-/* UNIONFS_D(dentry)->lock must be locked */
+-int realloc_dentry_private_data(struct dentry *dentry)
+-{
+-      if (!__realloc_dentry_private_data(dentry))
+-              return 0;
+-
+-      kfree(UNIONFS_D(dentry)->lower_paths);
+-      free_dentry_private_data(dentry);
+-      return -ENOMEM;
+-}
+-
+-/* allocate new dentry private data */
+-int new_dentry_private_data(struct dentry *dentry)
+-{
+-      struct unionfs_dentry_info *info = UNIONFS_D(dentry);
+-
+-      BUG_ON(info);
+-
+-      info = kmem_cache_alloc(unionfs_dentry_cachep, GFP_ATOMIC);
+-      if (!info)
+-              return -ENOMEM;
+-
+-      mutex_init(&info->lock);
+-      mutex_lock(&info->lock);
+-
+-      info->lower_paths = NULL;
+-
+-      dentry->d_fsdata = info;
+-
+-      if (!__realloc_dentry_private_data(dentry))
+-              return 0;
+-
+-      mutex_unlock(&info->lock);
+-      free_dentry_private_data(dentry);
+-      return -ENOMEM;
+-}
+-
+-/*
+- * scan through the lower dentry objects, and set bstart to reflect the
+- * starting branch
+- */
+-void update_bstart(struct dentry *dentry)
+-{
+-      int bindex;
+-      int bstart = dbstart(dentry);
+-      int bend = dbend(dentry);
+-      struct dentry *hidden_dentry;
+-
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (!hidden_dentry)
+-                      continue;
+-              if (hidden_dentry->d_inode) {
+-                      set_dbstart(dentry, bindex);
+-                      break;
+-              }
+-              dput(hidden_dentry);
+-              unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
+-      }
+-}
+diff -Nurb linux-2.6.22-590/fs/unionfs/main.c linux-2.6.22-570/fs/unionfs/main.c
+--- linux-2.6.22-590/fs/unionfs/main.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/main.c 1969-12-31 19:00:00.000000000 -0500
+@@ -1,729 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-
+-/*
+- * Connect a unionfs inode dentry/inode with several lower ones.  This is
+- * the classic stackable file system "vnode interposition" action.
+- *
+- * @sb: unionfs's super_block
+- */
+-int unionfs_interpose(struct dentry *dentry, struct super_block *sb, int flag)
+-{
+-      struct inode *hidden_inode;
+-      struct dentry *hidden_dentry;
+-      int err = 0;
+-      struct inode *inode;
+-      int is_negative_dentry = 1;
+-      int bindex, bstart, bend;
+-
+-      verify_locked(dentry);
+-
+-      bstart = dbstart(dentry);
+-      bend = dbend(dentry);
+-
+-      /* Make sure that we didn't get a negative dentry. */
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              if (unionfs_lower_dentry_idx(dentry, bindex) &&
+-                  unionfs_lower_dentry_idx(dentry, bindex)->d_inode) {
+-                      is_negative_dentry = 0;
+-                      break;
+-              }
+-      }
+-      BUG_ON(is_negative_dentry);
+-
+-      /*
+-       * We allocate our new inode below, by calling iget.
+-       * iget will call our read_inode which will initialize some
+-       * of the new inode's fields
+-       */
+-
+-      /*
+-       * On revalidate we've already got our own inode and just need
+-       * to fix it up.
+-       */
+-      if (flag == INTERPOSE_REVAL) {
+-              inode = dentry->d_inode;
+-              UNIONFS_I(inode)->bstart = -1;
+-              UNIONFS_I(inode)->bend = -1;
+-              atomic_set(&UNIONFS_I(inode)->generation,
+-                         atomic_read(&UNIONFS_SB(sb)->generation));
+-
+-              UNIONFS_I(inode)->lower_inodes =
+-                      kcalloc(sbmax(sb), sizeof(struct inode *), GFP_KERNEL);
+-              if (!UNIONFS_I(inode)->lower_inodes) {
+-                      err = -ENOMEM;
+-                      goto out;
+-              }
+-      } else {
+-              /* get unique inode number for unionfs */
+-              inode = iget(sb, iunique(sb, UNIONFS_ROOT_INO));
+-              if (!inode) {
+-                      err = -EACCES;
+-                      goto out;
+-              }
+-
+-              if (atomic_read(&inode->i_count) > 1)
+-                      goto skip;
+-      }
+-
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (!hidden_dentry) {
+-                      unionfs_set_lower_inode_idx(inode, bindex, NULL);
+-                      continue;
+-              }
+-
+-              /* Initialize the hidden inode to the new hidden inode. */
+-              if (!hidden_dentry->d_inode)
+-                      continue;
+-
+-              unionfs_set_lower_inode_idx(inode, bindex,
+-                                          igrab(hidden_dentry->d_inode));
+-      }
+-
+-      ibstart(inode) = dbstart(dentry);
+-      ibend(inode) = dbend(dentry);
+-
+-      /* Use attributes from the first branch. */
+-      hidden_inode = unionfs_lower_inode(inode);
+-
+-      /* Use different set of inode ops for symlinks & directories */
+-      if (S_ISLNK(hidden_inode->i_mode))
+-              inode->i_op = &unionfs_symlink_iops;
+-      else if (S_ISDIR(hidden_inode->i_mode))
+-              inode->i_op = &unionfs_dir_iops;
+-
+-      /* Use different set of file ops for directories */
+-      if (S_ISDIR(hidden_inode->i_mode))
+-              inode->i_fop = &unionfs_dir_fops;
+-
+-      /* properly initialize special inodes */
+-      if (S_ISBLK(hidden_inode->i_mode) || S_ISCHR(hidden_inode->i_mode) ||
+-          S_ISFIFO(hidden_inode->i_mode) || S_ISSOCK(hidden_inode->i_mode))
+-              init_special_inode(inode, hidden_inode->i_mode,
+-                                 hidden_inode->i_rdev);
+-
+-      /* all well, copy inode attributes */
+-      fsstack_copy_attr_all(inode, hidden_inode, unionfs_get_nlinks);
+-      fsstack_copy_inode_size(inode, hidden_inode);
+-
+-skip:
+-      /* only (our) lookup wants to do a d_add */
+-      switch (flag) {
+-      case INTERPOSE_DEFAULT:
+-      case INTERPOSE_REVAL_NEG:
+-              d_instantiate(dentry, inode);
+-              break;
+-      case INTERPOSE_LOOKUP:
+-              err = PTR_ERR(d_splice_alias(inode, dentry));
+-              break;
+-      case INTERPOSE_REVAL:
+-              /* Do nothing. */
+-              break;
+-      default:
+-              printk(KERN_ERR "unionfs: invalid interpose flag passed!");
+-              BUG();
+-      }
+-
+-out:
+-      return err;
+-}
+-
+-/* like interpose above, but for an already existing dentry */
+-void unionfs_reinterpose(struct dentry *dentry)
+-{
+-      struct dentry *hidden_dentry;
+-      struct inode *inode;
+-      int bindex, bstart, bend;
+-
+-      verify_locked(dentry);
+-
+-      /* This is pre-allocated inode */
+-      inode = dentry->d_inode;
+-
+-      bstart = dbstart(dentry);
+-      bend = dbend(dentry);
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-              if (!hidden_dentry)
+-                      continue;
+-
+-              if (!hidden_dentry->d_inode)
+-                      continue;
+-              if (unionfs_lower_inode_idx(inode, bindex))
+-                      continue;
+-              unionfs_set_lower_inode_idx(inode, bindex,
+-                                          igrab(hidden_dentry->d_inode));
+-      }
+-      ibstart(inode) = dbstart(dentry);
+-      ibend(inode) = dbend(dentry);
+-}
+-
+-/*
+- * make sure the branch we just looked up (nd) makes sense:
+- *
+- * 1) we're not trying to stack unionfs on top of unionfs
+- * 2) it exists
+- * 3) is a directory
+- */
+-int check_branch(struct nameidata *nd)
+-{
+-      if (!strcmp(nd->dentry->d_sb->s_type->name, "unionfs"))
+-              return -EINVAL;
+-      if (!nd->dentry->d_inode)
+-              return -ENOENT;
+-      if (!S_ISDIR(nd->dentry->d_inode->i_mode))
+-              return -ENOTDIR;
+-      return 0;
+-}
+-
+-/* checks if two hidden_dentries have overlapping branches */
+-static int is_branch_overlap(struct dentry *dent1, struct dentry *dent2)
+-{
+-      struct dentry *dent = NULL;
+-
+-      dent = dent1;
+-      while ((dent != dent2) && (dent->d_parent != dent))
+-              dent = dent->d_parent;
+-
+-      if (dent == dent2)
+-              return 1;
+-
+-      dent = dent2;
+-      while ((dent != dent1) && (dent->d_parent != dent))
+-              dent = dent->d_parent;
+-
+-      return (dent == dent1);
+-}
+-
+-/*
+- * Parse branch mode helper function
+- */
+-int __parse_branch_mode(const char *name)
+-{
+-      if (!name)
+-              return 0;
+-      if (!strcmp(name, "ro"))
+-              return MAY_READ;
+-      if (!strcmp(name, "rw"))
+-              return (MAY_READ | MAY_WRITE);
+-      return 0;
+-}
+-
+-/*
+- * Parse "ro" or "rw" options, but default to "rw" of no mode options
+- * was specified.
+- */
+-int parse_branch_mode(const char *name)
+-{
+-      int perms =  __parse_branch_mode(name);
+-
+-      if (perms == 0)
+-              perms = MAY_READ | MAY_WRITE;
+-      return perms;
+-}
+-
+-/* 
+- * parse the dirs= mount argument
+- *
+- * We don't need to lock the superblock private data's rwsem, as we get
+- * called only by unionfs_read_super - it is still a long time before anyone
+- * can even get a reference to us.
+- */
+-static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info
+-                           *hidden_root_info, char *options)
+-{
+-      struct nameidata nd;
+-      char *name;
+-      int err = 0;
+-      int branches = 1;
+-      int bindex = 0;
+-      int i = 0;
+-      int j = 0;
+-
+-      struct dentry *dent1;
+-      struct dentry *dent2;
+-
+-      if (options[0] == '\0') {
+-              printk(KERN_WARNING "unionfs: no branches specified\n");
+-              err = -EINVAL;
+-              goto out;
+-      }
+-
+-      /*
+-       * Each colon means we have a separator, this is really just a rough
+-       * guess, since strsep will handle empty fields for us.
+-       */
+-      for (i = 0; options[i]; i++)
+-              if (options[i] == ':')
+-                      branches++;
+-
+-      /* allocate space for underlying pointers to hidden dentry */
+-      UNIONFS_SB(sb)->data =
+-              kcalloc(branches, sizeof(struct unionfs_data), GFP_KERNEL);
+-      if (!UNIONFS_SB(sb)->data) {
+-              err = -ENOMEM;
+-              goto out;
+-      }
+-
+-      hidden_root_info->lower_paths =
+-              kcalloc(branches, sizeof(struct path), GFP_KERNEL);
+-      if (!hidden_root_info->lower_paths) {
+-              err = -ENOMEM;
+-              goto out;
+-      }
+-
+-      /* now parsing a string such as "b1:b2=rw:b3=ro:b4" */
+-      branches = 0;
+-      while ((name = strsep(&options, ":")) != NULL) {
+-              int perms;
+-              char *mode = strchr(name, '=');
+-
+-              if (!name || !*name)
+-                      continue;
+-
+-              branches++;
+-
+-              /* strip off '=' if any */
+-              if (mode)
+-                      *mode++ = '\0';
+-
+-              perms = parse_branch_mode(mode);
+-              if (!bindex && !(perms & MAY_WRITE)) {
+-                      err = -EINVAL;
+-                      goto out;
+-              }
+-
+-              err = path_lookup(name, LOOKUP_FOLLOW, &nd);
+-              if (err) {
+-                      printk(KERN_WARNING "unionfs: error accessing "
+-                             "hidden directory '%s' (error %d)\n",
+-                             name, err);
+-                      goto out;
+-              }
+-
+-              if ((err = check_branch(&nd))) {
+-                      printk(KERN_WARNING "unionfs: hidden directory "
+-                             "'%s' is not a valid branch\n", name);
+-                      path_release(&nd);
+-                      goto out;
+-              }
+-
+-              hidden_root_info->lower_paths[bindex].dentry = nd.dentry;
+-              hidden_root_info->lower_paths[bindex].mnt = nd.mnt;
+-
+-              set_branchperms(sb, bindex, perms);
+-              set_branch_count(sb, bindex, 0);
+-              new_branch_id(sb, bindex);
+-
+-              if (hidden_root_info->bstart < 0)
+-                      hidden_root_info->bstart = bindex;
+-              hidden_root_info->bend = bindex;
+-              bindex++;
+-      }
+-
+-      if (branches == 0) {
+-              printk(KERN_WARNING "unionfs: no branches specified\n");
+-              err = -EINVAL;
+-              goto out;
+-      }
+-
+-      BUG_ON(branches != (hidden_root_info->bend + 1));
+-
+-      /*
+-       * Ensure that no overlaps exist in the branches.
+-       *
+-       * This test is required because the Linux kernel has no support
+-       * currently for ensuring coherency between stackable layers and
+-       * branches.  If we were to allow overlapping branches, it would be
+-       * possible, for example, to delete a file via one branch, which
+-       * would not be reflected in another branch.  Such incoherency could
+-       * lead to inconsistencies and even kernel oopses.  Rather than
+-       * implement hacks to work around some of these cache-coherency
+-       * problems, we prevent branch overlapping, for now.  A complete
+-       * solution will involve proper kernel/VFS support for cache
+-       * coherency, at which time we could safely remove this
+-       * branch-overlapping test.
+-       */
+-      for (i = 0; i < branches; i++) {
+-              for (j = i + 1; j < branches; j++) {
+-                      dent1 = hidden_root_info->lower_paths[i].dentry;
+-                      dent2 = hidden_root_info->lower_paths[j].dentry;
+-
+-                      if (is_branch_overlap(dent1, dent2)) {
+-                              printk(KERN_WARNING "unionfs: branches %d and "
+-                                     "%d overlap\n", i, j);
+-                              err = -EINVAL;
+-                              goto out;
+-                      }
+-              }
+-      }
+-
+-out:
+-      if (err) {
+-              for (i = 0; i < branches; i++)
+-                      if (hidden_root_info->lower_paths[i].dentry) {
+-                              dput(hidden_root_info->lower_paths[i].dentry);
+-                              /* initialize: can't use unionfs_mntput here */
+-                              mntput(hidden_root_info->lower_paths[i].mnt);
+-                      }
+-
+-              kfree(hidden_root_info->lower_paths);
+-              kfree(UNIONFS_SB(sb)->data);
+-
+-              /*
+-               * MUST clear the pointers to prevent potential double free if
+-               * the caller dies later on
+-               */
+-              hidden_root_info->lower_paths = NULL;
+-              UNIONFS_SB(sb)->data = NULL;
+-      }
+-      return err;
+-}
+-
+-/*
+- * Parse mount options.  See the manual page for usage instructions.
+- *
+- * Returns the dentry object of the lower-level (hidden) directory;
+- * We want to mount our stackable file system on top of that hidden directory.
+- */
+-static struct unionfs_dentry_info *unionfs_parse_options(
+-                                      struct super_block *sb,
+-                                      char *options)
+-{
+-      struct unionfs_dentry_info *hidden_root_info;
+-      char *optname;
+-      int err = 0;
+-      int bindex;
+-      int dirsfound = 0;
+-
+-      /* allocate private data area */
+-      err = -ENOMEM;
+-      hidden_root_info =
+-              kzalloc(sizeof(struct unionfs_dentry_info), GFP_KERNEL);
+-      if (!hidden_root_info)
+-              goto out_error;
+-      hidden_root_info->bstart = -1;
+-      hidden_root_info->bend = -1;
+-      hidden_root_info->bopaque = -1;
+-
+-      while ((optname = strsep(&options, ",")) != NULL) {
+-              char *optarg;
+-              char *endptr;
+-              int intval;
+-
+-              if (!optname || !*optname)
+-                      continue;
+-
+-              optarg = strchr(optname, '=');
+-              if (optarg)
+-                      *optarg++ = '\0';
+-
+-              /*
+-               * All of our options take an argument now. Insert ones that
+-               * don't, above this check.
+-               */
+-              if (!optarg) {
+-                      printk("unionfs: %s requires an argument.\n", optname);
+-                      err = -EINVAL;
+-                      goto out_error;
+-              }
+-
+-              if (!strcmp("dirs", optname)) {
+-                      if (++dirsfound > 1) {
+-                              printk(KERN_WARNING
+-                                     "unionfs: multiple dirs specified\n");
+-                              err = -EINVAL;
+-                              goto out_error;
+-                      }
+-                      err = parse_dirs_option(sb, hidden_root_info, optarg);
+-                      if (err)
+-                              goto out_error;
+-                      continue;
+-              }
+-
+-              /* All of these options require an integer argument. */
+-              intval = simple_strtoul(optarg, &endptr, 0);
+-              if (*endptr) {
+-                      printk(KERN_WARNING
+-                             "unionfs: invalid %s option '%s'\n",
+-                             optname, optarg);
+-                      err = -EINVAL;
+-                      goto out_error;
+-              }
+-
+-              err = -EINVAL;
+-              printk(KERN_WARNING
+-                     "unionfs: unrecognized option '%s'\n", optname);
+-              goto out_error;
+-      }
+-      if (dirsfound != 1) {
+-              printk(KERN_WARNING "unionfs: dirs option required\n");
+-              err = -EINVAL;
+-              goto out_error;
+-      }
+-      goto out;
+-
+-out_error:
+-      if (hidden_root_info && hidden_root_info->lower_paths) {
+-              for (bindex = hidden_root_info->bstart;
+-                   bindex >= 0 && bindex <= hidden_root_info->bend;
+-                   bindex++) {
+-                      struct dentry *d;
+-                      struct vfsmount *m;
+-
+-                      d = hidden_root_info->lower_paths[bindex].dentry;
+-                      m = hidden_root_info->lower_paths[bindex].mnt;
+-
+-                      dput(d);
+-                      /* initializing: can't use unionfs_mntput here */
+-                      mntput(m);
+-              }
+-      }
+-
+-      kfree(hidden_root_info->lower_paths);
+-      kfree(hidden_root_info);
+-
+-      kfree(UNIONFS_SB(sb)->data);
+-      UNIONFS_SB(sb)->data = NULL;
+-
+-      hidden_root_info = ERR_PTR(err);
+-out:
+-      return hidden_root_info;
+-}
+-
+-/*
+- * our custom d_alloc_root work-alike
+- *
+- * we can't use d_alloc_root if we want to use our own interpose function
+- * unchanged, so we simply call our own "fake" d_alloc_root
+- */
+-static struct dentry *unionfs_d_alloc_root(struct super_block *sb)
+-{
+-      struct dentry *ret = NULL;
+-
+-      if (sb) {
+-              static const struct qstr name = {.name = "/",.len = 1 };
+-
+-              ret = d_alloc(NULL, &name);
+-              if (ret) {
+-                      ret->d_op = &unionfs_dops;
+-                      ret->d_sb = sb;
+-                      ret->d_parent = ret;
+-              }
+-      }
+-      return ret;
+-}
+-
+-/*
+- * There is no need to lock the unionfs_super_info's rwsem as there is no
+- * way anyone can have a reference to the superblock at this point in time.
+- */
+-static int unionfs_read_super(struct super_block *sb, void *raw_data,
+-                            int silent)
+-{
+-      int err = 0;
+-
+-      struct unionfs_dentry_info *hidden_root_info = NULL;
+-      int bindex, bstart, bend;
+-
+-      if (!raw_data) {
+-              printk(KERN_WARNING
+-                     "unionfs: read_super: missing data argument\n");
+-              err = -EINVAL;
+-              goto out;
+-      }
+-
+-      /* Allocate superblock private data */
+-      sb->s_fs_info = kzalloc(sizeof(struct unionfs_sb_info), GFP_KERNEL);
+-      if (!UNIONFS_SB(sb)) {
+-              printk(KERN_WARNING "unionfs: read_super: out of memory\n");
+-              err = -ENOMEM;
+-              goto out;
+-      }
+-
+-      UNIONFS_SB(sb)->bend = -1;
+-      atomic_set(&UNIONFS_SB(sb)->generation, 1);
+-      init_rwsem(&UNIONFS_SB(sb)->rwsem);
+-      UNIONFS_SB(sb)->high_branch_id = -1; /* -1 == invalid branch ID */
+-
+-      hidden_root_info = unionfs_parse_options(sb, raw_data);
+-      if (IS_ERR(hidden_root_info)) {
+-              printk(KERN_WARNING
+-                     "unionfs: read_super: error while parsing options "
+-                     "(err = %ld)\n", PTR_ERR(hidden_root_info));
+-              err = PTR_ERR(hidden_root_info);
+-              hidden_root_info = NULL;
+-              goto out_free;
+-      }
+-      if (hidden_root_info->bstart == -1) {
+-              err = -ENOENT;
+-              goto out_free;
+-      }
+-
+-      /* set the hidden superblock field of upper superblock */
+-      bstart = hidden_root_info->bstart;
+-      BUG_ON(bstart != 0);
+-      sbend(sb) = bend = hidden_root_info->bend;
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              struct dentry *d = hidden_root_info->lower_paths[bindex].dentry;
+-              unionfs_set_lower_super_idx(sb, bindex, d->d_sb);
+-      }
+-
+-      /* max Bytes is the maximum bytes from highest priority branch */
+-      sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
+-
+-      sb->s_op = &unionfs_sops;
+-
+-      /* See comment next to the definition of unionfs_d_alloc_root */
+-      sb->s_root = unionfs_d_alloc_root(sb);
+-      if (!sb->s_root) {
+-              err = -ENOMEM;
+-              goto out_dput;
+-      }
+-
+-      /* link the upper and lower dentries */
+-      sb->s_root->d_fsdata = NULL;
+-      if ((err = new_dentry_private_data(sb->s_root)))
+-              goto out_freedpd;
+-
+-      /* Set the hidden dentries for s_root */
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              struct dentry *d;
+-              struct vfsmount *m;
+-
+-              d = hidden_root_info->lower_paths[bindex].dentry;
+-              m = hidden_root_info->lower_paths[bindex].mnt;
+-
+-              unionfs_set_lower_dentry_idx(sb->s_root, bindex, d);
+-              unionfs_set_lower_mnt_idx(sb->s_root, bindex, m);
+-      }
+-      set_dbstart(sb->s_root, bstart);
+-      set_dbend(sb->s_root, bend);
+-
+-      /* Set the generation number to one, since this is for the mount. */
+-      atomic_set(&UNIONFS_D(sb->s_root)->generation, 1);
+-
+-      /* call interpose to create the upper level inode */
+-      err = unionfs_interpose(sb->s_root, sb, 0);
+-      unionfs_unlock_dentry(sb->s_root);
+-      if (!err)
+-              goto out;
+-      /* else fall through */
+-
+-out_freedpd:
+-      if (UNIONFS_D(sb->s_root)) {
+-              kfree(UNIONFS_D(sb->s_root)->lower_paths);
+-              free_dentry_private_data(sb->s_root);
+-      }
+-      dput(sb->s_root);
+-
+-out_dput:
+-      if (hidden_root_info && !IS_ERR(hidden_root_info)) {
+-              for (bindex = hidden_root_info->bstart;
+-                   bindex <= hidden_root_info->bend; bindex++) {
+-                      struct dentry *d;
+-                      struct vfsmount *m;
+-
+-                      d = hidden_root_info->lower_paths[bindex].dentry;
+-                      m = hidden_root_info->lower_paths[bindex].mnt;
+-
+-                      dput(d);
+-                      /* initializing: can't use unionfs_mntput here */
+-                      mntput(m);
+-              }
+-              kfree(hidden_root_info->lower_paths);
+-              kfree(hidden_root_info);
+-              hidden_root_info = NULL;
+-      }
+-
+-out_free:
+-      kfree(UNIONFS_SB(sb)->data);
+-      kfree(UNIONFS_SB(sb));
+-      sb->s_fs_info = NULL;
+-
+-out:
+-      if (hidden_root_info && !IS_ERR(hidden_root_info)) {
+-              kfree(hidden_root_info->lower_paths);
+-              kfree(hidden_root_info);
+-      }
+-      return err;
+-}
+-
+-static int unionfs_get_sb(struct file_system_type *fs_type,
+-                        int flags, const char *dev_name,
+-                        void *raw_data, struct vfsmount *mnt)
+-{
+-      return get_sb_nodev(fs_type, flags, raw_data, unionfs_read_super, mnt);
+-}
+-
+-static struct file_system_type unionfs_fs_type = {
+-      .owner          = THIS_MODULE,
+-      .name           = "unionfs",
+-      .get_sb         = unionfs_get_sb,
+-      .kill_sb        = generic_shutdown_super,
+-      .fs_flags       = FS_REVAL_DOT,
+-};
+-
+-static int __init init_unionfs_fs(void)
+-{
+-      int err;
+-
+-      printk("Registering unionfs " UNIONFS_VERSION "\n");
+-
+-      if ((err = unionfs_init_filldir_cache()))
+-              goto out;
+-      if ((err = unionfs_init_inode_cache()))
+-              goto out;
+-      if ((err = unionfs_init_dentry_cache()))
+-              goto out;
+-      if ((err = init_sioq()))
+-              goto out;
+-      err = register_filesystem(&unionfs_fs_type);
+-out:
+-      if (err) {
+-              stop_sioq();
+-              unionfs_destroy_filldir_cache();
+-              unionfs_destroy_inode_cache();
+-              unionfs_destroy_dentry_cache();
+-      }
+-      return err;
+-}
+-
+-static void __exit exit_unionfs_fs(void)
+-{
+-      stop_sioq();
+-      unionfs_destroy_filldir_cache();
+-      unionfs_destroy_inode_cache();
+-      unionfs_destroy_dentry_cache();
+-      unregister_filesystem(&unionfs_fs_type);
+-      printk("Completed unionfs module unload.\n");
+-}
+-
+-MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
+-            " (http://www.fsl.cs.sunysb.edu)");
+-MODULE_DESCRIPTION("Unionfs " UNIONFS_VERSION
+-                 " (http://unionfs.filesystems.org)");
+-MODULE_LICENSE("GPL");
+-
+-module_init(init_unionfs_fs);
+-module_exit(exit_unionfs_fs);
+diff -Nurb linux-2.6.22-590/fs/unionfs/mmap.c linux-2.6.22-570/fs/unionfs/mmap.c
+--- linux-2.6.22-590/fs/unionfs/mmap.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/mmap.c 1969-12-31 19:00:00.000000000 -0500
+@@ -1,348 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2006      Shaya Potter
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of State University of New York
+- *
+- * 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 "union.h"
+-
+-/*
+- * Unionfs doesn't implement ->writepages, which is OK with the VFS and
+- * nkeeps our code simpler and smaller.  Nevertheless, somehow, our own
+- * ->writepage must be called so we can sync the upper pages with the lower
+- * pages: otherwise data changed at the upper layer won't get written to the
+- * lower layer.
+- *
+- * Some lower file systems (e.g., NFS) expect the VFS to call its writepages
+- * only, which in turn will call generic_writepages and invoke each of the
+- * lower file system's ->writepage.  NFS in particular uses the
+- * wbc->fs_private field in its nfs_writepage, which is set in its
+- * nfs_writepages.  So if we don't call the lower nfs_writepages first, then
+- * NFS's nfs_writepage will dereference a NULL wbc->fs_private and cause an
+- * OOPS.  If, however, we implement a unionfs_writepages and then we do call
+- * the lower nfs_writepages, then we "lose control" over the pages we're
+- * trying to write to the lower file system: we won't be writing our own
+- * new/modified data from the upper pages to the lower pages, and any
+- * mmap-based changes are lost.
+- *
+- * This is a fundamental cache-coherency problem in Linux.  The kernel isn't
+- * able to support such stacking abstractions cleanly.  One possible clean
+- * way would be that a lower file system's ->writepage method have some sort
+- * of a callback to validate if any upper pages for the same file+offset
+- * exist and have newer content in them.
+- *
+- * This whole NULL ptr dereference is triggered at the lower file system
+- * (NFS) because the wbc->for_writepages is set to 1.  Therefore, to avoid
+- * this NULL pointer dereference, we set this flag to 0 and restore it upon
+- * exit.  This probably means that we're slightly less efficient in writing
+- * pages out, doing them one at a time, but at least we avoid the oops until
+- * such day as Linux can better support address_space_ops in a stackable
+- * fashion.
+- */
+-int unionfs_writepage(struct page *page, struct writeback_control *wbc)
+-{
+-      int err = -EIO;
+-      struct inode *inode;
+-      struct inode *lower_inode;
+-      struct page *lower_page;
+-      char *kaddr, *lower_kaddr;
+-      int saved_for_writepages = wbc->for_writepages;
+-
+-      inode = page->mapping->host;
+-      lower_inode = unionfs_lower_inode(inode);
+-
+-      /* find lower page (returns a locked page) */
+-      lower_page = grab_cache_page(lower_inode->i_mapping, page->index);
+-      if (!lower_page)
+-              goto out;
+-
+-      /* get page address, and encode it */
+-      kaddr = kmap(page);
+-      lower_kaddr = kmap(lower_page);
+-
+-      memcpy(lower_kaddr, kaddr, PAGE_CACHE_SIZE);
+-
+-      kunmap(page);
+-      kunmap(lower_page);
+-
+-      BUG_ON(!lower_inode->i_mapping->a_ops->writepage);
+-
+-      /* workaround for some lower file systems: see big comment on top */
+-      if (wbc->for_writepages && !wbc->fs_private)
+-              wbc->for_writepages = 0;
+-
+-      /* call lower writepage (expects locked page) */
+-      err = lower_inode->i_mapping->a_ops->writepage(lower_page, wbc);
+-      wbc->for_writepages = saved_for_writepages; /* restore value */
+-
+-      /*
+-       * update mtime and ctime of lower level file system
+-       * unionfs' mtime and ctime are updated by generic_file_write
+-       */
+-      lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
+-
+-      page_cache_release(lower_page); /* b/c grab_cache_page increased refcnt */
+-
+-      if (err)
+-              ClearPageUptodate(page);
+-      else
+-              SetPageUptodate(page);
+-
+-out:
+-      unlock_page(page);
+-      return err;
+-}
+-
+-/*
+- * readpage is called from generic_page_read and the fault handler.
+- * If your file system uses generic_page_read for the read op, it
+- * must implement readpage.
+- *
+- * Readpage expects a locked page, and must unlock it.
+- */
+-static int unionfs_do_readpage(struct file *file, struct page *page)
+-{
+-      int err = -EIO;
+-      struct dentry *dentry;
+-      struct file *lower_file = NULL;
+-      struct inode *inode, *lower_inode;
+-      char *page_data;
+-      struct page *lower_page;
+-      char *lower_page_data;
+-
+-      dentry = file->f_dentry;
+-      if (UNIONFS_F(file) == NULL) {
+-              err = -ENOENT;
+-              goto out_err;
+-      }
+-
+-      lower_file = unionfs_lower_file(file);
+-      inode = dentry->d_inode;
+-      lower_inode = unionfs_lower_inode(inode);
+-
+-      lower_page = NULL;
+-
+-      /* find lower page (returns a locked page) */
+-      lower_page = read_cache_page(lower_inode->i_mapping,
+-                                   page->index,
+-                                   (filler_t *) lower_inode->i_mapping->
+-                                   a_ops->readpage, (void *)lower_file);
+-
+-      if (IS_ERR(lower_page)) {
+-              err = PTR_ERR(lower_page);
+-              lower_page = NULL;
+-              goto out_release;
+-      }
+-
+-      /*
+-       * wait for the page data to show up
+-       * (signaled by readpage as unlocking the page)
+-       */
+-      wait_on_page_locked(lower_page);
+-      if (!PageUptodate(lower_page)) {
+-              /*
+-               * call readpage() again if we returned from wait_on_page
+-               * with a page that's not up-to-date; that can happen when a
+-               * partial page has a few buffers which are ok, but not the
+-               * whole page.
+-               */
+-              lock_page(lower_page);
+-              err = lower_inode->i_mapping->a_ops->readpage(lower_file,
+-                                                            lower_page);
+-              if (err) {
+-                      lower_page = NULL;
+-                      goto out_release;
+-              }
+-
+-              wait_on_page_locked(lower_page);
+-              if (!PageUptodate(lower_page)) {
+-                      err = -EIO;
+-                      goto out_release;
+-              }
+-      }
+-
+-      /* map pages, get their addresses */
+-      page_data = (char *)kmap(page);
+-      lower_page_data = (char *)kmap(lower_page);
+-
+-      memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE);
+-
+-      err = 0;
+-
+-      kunmap(lower_page);
+-      kunmap(page);
+-
+-out_release:
+-      if (lower_page)
+-              page_cache_release(lower_page); /* undo read_cache_page */
+-
+-      if (err == 0)
+-              SetPageUptodate(page);
+-      else
+-              ClearPageUptodate(page);
+-
+-out_err:
+-      return err;
+-}
+-
+-int unionfs_readpage(struct file *file, struct page *page)
+-{
+-      int err;
+-
+-      unionfs_read_lock(file->f_dentry->d_sb);
+-
+-      if ((err = unionfs_file_revalidate(file, 0)))
+-              goto out;
+-
+-      err = unionfs_do_readpage(file, page);
+-
+-      if (!err)
+-              touch_atime(unionfs_lower_mnt(file->f_path.dentry),
+-                          unionfs_lower_dentry(file->f_path.dentry));
+-
+-      /*
+-       * we have to unlock our page, b/c we _might_ have gotten a locked
+-       * page.  but we no longer have to wakeup on our page here, b/c
+-       * UnlockPage does it
+-       */
+-out:
+-      unlock_page(page);
+-      unionfs_read_unlock(file->f_dentry->d_sb);
+-
+-      return err;
+-}
+-
+-int unionfs_prepare_write(struct file *file, struct page *page, unsigned from,
+-                        unsigned to)
+-{
+-      int err;
+-
+-      unionfs_read_lock(file->f_dentry->d_sb);
+-
+-      err = unionfs_file_revalidate(file, 1);
+-
+-      unionfs_read_unlock(file->f_dentry->d_sb);
+-
+-      return err;
+-}
+-
+-int unionfs_commit_write(struct file *file, struct page *page, unsigned from,
+-                       unsigned to)
+-{
+-      int err = -ENOMEM;
+-      struct inode *inode, *lower_inode;
+-      struct file *lower_file = NULL;
+-      loff_t pos;
+-      unsigned bytes = to - from;
+-      char *page_data = NULL;
+-      mm_segment_t old_fs;
+-
+-      BUG_ON(file == NULL);
+-
+-      unionfs_read_lock(file->f_dentry->d_sb);
+-
+-      if ((err = unionfs_file_revalidate(file, 1)))
+-              goto out;
+-
+-      inode = page->mapping->host;
+-      lower_inode = unionfs_lower_inode(inode);
+-
+-      if (UNIONFS_F(file) != NULL)
+-              lower_file = unionfs_lower_file(file);
+-
+-      /* FIXME: is this assertion right here? */
+-      BUG_ON(lower_file == NULL);
+-
+-      page_data = (char *)kmap(page);
+-      lower_file->f_pos = (page->index << PAGE_CACHE_SHIFT) + from;
+-
+-      /* SP: I use vfs_write instead of copying page data and the
+-       * prepare_write/commit_write combo because file system's like
+-       * GFS/OCFS2 don't like things touching those directly,
+-       * calling the underlying write op, while a little bit slower, will
+-       * call all the FS specific code as well
+-       */
+-      old_fs = get_fs();
+-      set_fs(KERNEL_DS);
+-      err = vfs_write(lower_file, page_data + from, bytes,
+-                      &lower_file->f_pos);
+-      set_fs(old_fs);
+-
+-      kunmap(page);
+-
+-      if (err < 0)
+-              goto out;
+-
+-      inode->i_blocks = lower_inode->i_blocks;
+-      /* we may have to update i_size */
+-      pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + to;
+-      if (pos > i_size_read(inode))
+-              i_size_write(inode, pos);
+-
+-      /*
+-       * update mtime and ctime of lower level file system
+-       * unionfs' mtime and ctime are updated by generic_file_write
+-       */
+-      lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
+-
+-      mark_inode_dirty_sync(inode);
+-
+-out:
+-      if (err < 0)
+-              ClearPageUptodate(page);
+-
+-      unionfs_read_unlock(file->f_dentry->d_sb);
+-      return err;             /* assume all is ok */
+-}
+-
+-void unionfs_sync_page(struct page *page)
+-{
+-      struct inode *inode;
+-      struct inode *lower_inode;
+-      struct page *lower_page;
+-      struct address_space *mapping;
+-
+-      inode = page->mapping->host;
+-      lower_inode = unionfs_lower_inode(inode);
+-
+-      /* find lower page (returns a locked page) */
+-      lower_page = grab_cache_page(lower_inode->i_mapping, page->index);
+-      if (!lower_page)
+-              goto out;
+-
+-      /* do the actual sync */
+-      mapping = lower_page->mapping;
+-      /*
+-       * XXX: can we optimize ala RAIF and set the lower page to be
+-       * discarded after a successful sync_page?
+-       */
+-      if (mapping && mapping->a_ops && mapping->a_ops->sync_page)
+-              mapping->a_ops->sync_page(lower_page);
+-
+-      unlock_page(lower_page);        /* b/c grab_cache_page locked it */
+-      page_cache_release(lower_page); /* b/c grab_cache_page increased refcnt */
+-
+-out:
+-      return;
+-}
+-
+-struct address_space_operations unionfs_aops = {
+-      .writepage      = unionfs_writepage,
+-      .readpage       = unionfs_readpage,
+-      .prepare_write  = unionfs_prepare_write,
+-      .commit_write   = unionfs_commit_write,
+-      .sync_page      = unionfs_sync_page,
+-};
+diff -Nurb linux-2.6.22-590/fs/unionfs/rdstate.c linux-2.6.22-570/fs/unionfs/rdstate.c
+--- linux-2.6.22-590/fs/unionfs/rdstate.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/rdstate.c      1969-12-31 19:00:00.000000000 -0500
+@@ -1,282 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/* This file contains the routines for maintaining readdir state. */
+-
+-/*
+- * There are two structures here, rdstate which is a hash table
+- * of the second structure which is a filldir_node.
+- */
+-
+-/*
+- * This is a struct kmem_cache for filldir nodes, because we allocate a lot
+- * of them and they shouldn't waste memory.  If the node has a small name
+- * (as defined by the dentry structure), then we use an inline name to
+- * preserve kmalloc space.
+- */
+-static struct kmem_cache *unionfs_filldir_cachep;
+-
+-int unionfs_init_filldir_cache(void)
+-{
+-      unionfs_filldir_cachep =
+-              kmem_cache_create("unionfs_filldir",
+-                                sizeof(struct filldir_node), 0,
+-                                SLAB_RECLAIM_ACCOUNT, NULL, NULL);
+-
+-      return (unionfs_filldir_cachep ? 0 : -ENOMEM);
+-}
+-
+-void unionfs_destroy_filldir_cache(void)
+-{
+-      if (unionfs_filldir_cachep)
+-              kmem_cache_destroy(unionfs_filldir_cachep);
+-}
+-
+-/*
+- * This is a tuning parameter that tells us roughly how big to make the
+- * hash table in directory entries per page.  This isn't perfect, but
+- * at least we get a hash table size that shouldn't be too overloaded.
+- * The following averages are based on my home directory.
+- * 14.44693   Overall
+- * 12.29      Single Page Directories
+- * 117.93     Multi-page directories
+- */
+-#define DENTPAGE 4096
+-#define DENTPERONEPAGE 12
+-#define DENTPERPAGE 118
+-#define MINHASHSIZE 1
+-static int guesstimate_hash_size(struct inode *inode)
+-{
+-      struct inode *hidden_inode;
+-      int bindex;
+-      int hashsize = MINHASHSIZE;
+-
+-      if (UNIONFS_I(inode)->hashsize > 0)
+-              return UNIONFS_I(inode)->hashsize;
+-
+-      for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
+-              if (!(hidden_inode = unionfs_lower_inode_idx(inode, bindex)))
+-                      continue;
+-
+-              if (hidden_inode->i_size == DENTPAGE)
+-                      hashsize += DENTPERONEPAGE;
+-              else
+-                      hashsize += (hidden_inode->i_size / DENTPAGE) *
+-                              DENTPERPAGE;
+-      }
+-
+-      return hashsize;
+-}
+-
+-int init_rdstate(struct file *file)
+-{
+-      BUG_ON(sizeof(loff_t) !=
+-             (sizeof(unsigned int) + sizeof(unsigned int)));
+-      BUG_ON(UNIONFS_F(file)->rdstate != NULL);
+-
+-      UNIONFS_F(file)->rdstate = alloc_rdstate(file->f_dentry->d_inode,
+-                                               fbstart(file));
+-
+-      return (UNIONFS_F(file)->rdstate ? 0 : -ENOMEM);
+-}
+-
+-struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos)
+-{
+-      struct unionfs_dir_state *rdstate = NULL;
+-      struct list_head *pos;
+-
+-      spin_lock(&UNIONFS_I(inode)->rdlock);
+-      list_for_each(pos, &UNIONFS_I(inode)->readdircache) {
+-              struct unionfs_dir_state *r =
+-                      list_entry(pos, struct unionfs_dir_state, cache);
+-              if (fpos == rdstate2offset(r)) {
+-                      UNIONFS_I(inode)->rdcount--;
+-                      list_del(&r->cache);
+-                      rdstate = r;
+-                      break;
+-              }
+-      }
+-      spin_unlock(&UNIONFS_I(inode)->rdlock);
+-      return rdstate;
+-}
+-
+-struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex)
+-{
+-      int i = 0;
+-      int hashsize;
+-      unsigned long mallocsize = sizeof(struct unionfs_dir_state);
+-      struct unionfs_dir_state *rdstate;
+-
+-      hashsize = guesstimate_hash_size(inode);
+-      mallocsize += hashsize * sizeof(struct list_head);
+-      mallocsize = __roundup_pow_of_two(mallocsize);
+-
+-      /* This should give us about 500 entries anyway. */
+-      if (mallocsize > PAGE_SIZE)
+-              mallocsize = PAGE_SIZE;
+-
+-      hashsize = (mallocsize - sizeof(struct unionfs_dir_state)) /
+-              sizeof(struct list_head);
+-
+-      rdstate = kmalloc(mallocsize, GFP_KERNEL);
+-      if (!rdstate)
+-              return NULL;
+-
+-      spin_lock(&UNIONFS_I(inode)->rdlock);
+-      if (UNIONFS_I(inode)->cookie >= (MAXRDCOOKIE - 1))
+-              UNIONFS_I(inode)->cookie = 1;
+-      else
+-              UNIONFS_I(inode)->cookie++;
+-
+-      rdstate->cookie = UNIONFS_I(inode)->cookie;
+-      spin_unlock(&UNIONFS_I(inode)->rdlock);
+-      rdstate->offset = 1;
+-      rdstate->access = jiffies;
+-      rdstate->bindex = bindex;
+-      rdstate->dirpos = 0;
+-      rdstate->hashentries = 0;
+-      rdstate->size = hashsize;
+-      for (i = 0; i < rdstate->size; i++)
+-              INIT_LIST_HEAD(&rdstate->list[i]);
+-
+-      return rdstate;
+-}
+-
+-static void free_filldir_node(struct filldir_node *node)
+-{
+-      if (node->namelen >= DNAME_INLINE_LEN_MIN)
+-              kfree(node->name);
+-      kmem_cache_free(unionfs_filldir_cachep, node);
+-}
+-
+-void free_rdstate(struct unionfs_dir_state *state)
+-{
+-      struct filldir_node *tmp;
+-      int i;
+-
+-      for (i = 0; i < state->size; i++) {
+-              struct list_head *head = &(state->list[i]);
+-              struct list_head *pos, *n;
+-
+-              /* traverse the list and deallocate space */
+-              list_for_each_safe(pos, n, head) {
+-                      tmp = list_entry(pos, struct filldir_node, file_list);
+-                      list_del(&tmp->file_list);
+-                      free_filldir_node(tmp);
+-              }
+-      }
+-
+-      kfree(state);
+-}
+-
+-struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
+-                                     const char *name, int namelen)
+-{
+-      int index;
+-      unsigned int hash;
+-      struct list_head *head;
+-      struct list_head *pos;
+-      struct filldir_node *cursor = NULL;
+-      int found = 0;
+-
+-      BUG_ON(namelen <= 0);
+-
+-      hash = full_name_hash(name, namelen);
+-      index = hash % rdstate->size;
+-
+-      head = &(rdstate->list[index]);
+-      list_for_each(pos, head) {
+-              cursor = list_entry(pos, struct filldir_node, file_list);
+-
+-              if (cursor->namelen == namelen && cursor->hash == hash &&
+-                  !strncmp(cursor->name, name, namelen)) {
+-                      /*
+-                       * a duplicate exists, and hence no need to create
+-                       * entry to the list
+-                       */
+-                      found = 1;
+-
+-                      /*
+-                       * if the duplicate is in this branch, then the file
+-                       * system is corrupted.
+-                       */
+-                      if (cursor->bindex == rdstate->bindex) {
+-                              printk(KERN_DEBUG "unionfs: filldir: possible "
+-                                     "I/O error: a file is duplicated "
+-                                     "in the same branch %d: %s\n",
+-                                     rdstate->bindex, cursor->name);
+-                      }
+-                      break;
+-              }
+-      }
+-
+-      if (!found)
+-              cursor = NULL;
+-
+-      return cursor;
+-}
+-
+-int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name,
+-                   int namelen, int bindex, int whiteout)
+-{
+-      struct filldir_node *new;
+-      unsigned int hash;
+-      int index;
+-      int err = 0;
+-      struct list_head *head;
+-
+-      BUG_ON(namelen <= 0);
+-
+-      hash = full_name_hash(name, namelen);
+-      index = hash % rdstate->size;
+-      head = &(rdstate->list[index]);
+-
+-      new = kmem_cache_alloc(unionfs_filldir_cachep, GFP_KERNEL);
+-      if (!new) {
+-              err = -ENOMEM;
+-              goto out;
+-      }
+-
+-      INIT_LIST_HEAD(&new->file_list);
+-      new->namelen = namelen;
+-      new->hash = hash;
+-      new->bindex = bindex;
+-      new->whiteout = whiteout;
+-
+-      if (namelen < DNAME_INLINE_LEN_MIN)
+-              new->name = new->iname;
+-      else {
+-              new->name = kmalloc(namelen + 1, GFP_KERNEL);
+-              if (!new->name) {
+-                      kmem_cache_free(unionfs_filldir_cachep, new);
+-                      new = NULL;
+-                      goto out;
+-              }
+-      }
+-
+-      memcpy(new->name, name, namelen);
+-      new->name[namelen] = '\0';
+-
+-      rdstate->hashentries++;
+-
+-      list_add(&(new->file_list), head);
+-out:
+-      return err;
+-}
+diff -Nurb linux-2.6.22-590/fs/unionfs/rename.c linux-2.6.22-570/fs/unionfs/rename.c
+--- linux-2.6.22-590/fs/unionfs/rename.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/rename.c       1969-12-31 19:00:00.000000000 -0500
+@@ -1,477 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-static int __unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+-                          struct inode *new_dir, struct dentry *new_dentry,
+-                          int bindex, struct dentry **wh_old)
+-{
+-      int err = 0;
+-      struct dentry *hidden_old_dentry;
+-      struct dentry *hidden_new_dentry;
+-      struct dentry *hidden_old_dir_dentry;
+-      struct dentry *hidden_new_dir_dentry;
+-      struct dentry *hidden_wh_dentry;
+-      struct dentry *hidden_wh_dir_dentry;
+-      char *wh_name = NULL;
+-
+-      hidden_new_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
+-      hidden_old_dentry = unionfs_lower_dentry_idx(old_dentry, bindex);
+-
+-      if (!hidden_new_dentry) {
+-              hidden_new_dentry =
+-                      create_parents(new_dentry->d_parent->d_inode,
+-                                     new_dentry, bindex);
+-              if (IS_ERR(hidden_new_dentry)) {
+-                      printk(KERN_DEBUG "unionfs: error creating directory "
+-                             "tree for rename, bindex = %d, err = %ld\n",
+-                             bindex, PTR_ERR(hidden_new_dentry));
+-                      err = PTR_ERR(hidden_new_dentry);
+-                      goto out;
+-              }
+-      }
+-
+-      wh_name = alloc_whname(new_dentry->d_name.name,
+-                             new_dentry->d_name.len);
+-      if (IS_ERR(wh_name)) {
+-              err = PTR_ERR(wh_name);
+-              goto out;
+-      }
+-
+-      hidden_wh_dentry = lookup_one_len(wh_name, hidden_new_dentry->d_parent,
+-                                        new_dentry->d_name.len +
+-                                        UNIONFS_WHLEN);
+-      if (IS_ERR(hidden_wh_dentry)) {
+-              err = PTR_ERR(hidden_wh_dentry);
+-              goto out;
+-      }
+-
+-      if (hidden_wh_dentry->d_inode) {
+-              /* get rid of the whiteout that is existing */
+-              if (hidden_new_dentry->d_inode) {
+-                      printk(KERN_WARNING "unionfs: both a whiteout and a "
+-                             "dentry exist when doing a rename!\n");
+-                      err = -EIO;
+-
+-                      dput(hidden_wh_dentry);
+-                      goto out;
+-              }
+-
+-              hidden_wh_dir_dentry = lock_parent(hidden_wh_dentry);
+-              if (!(err = is_robranch_super(old_dentry->d_sb, bindex)))
+-                      err = vfs_unlink(hidden_wh_dir_dentry->d_inode,
+-                                       hidden_wh_dentry);
+-
+-              dput(hidden_wh_dentry);
+-              unlock_dir(hidden_wh_dir_dentry);
+-              if (err)
+-                      goto out;
+-      } else
+-              dput(hidden_wh_dentry);
+-
+-      dget(hidden_old_dentry);
+-      hidden_old_dir_dentry = dget_parent(hidden_old_dentry);
+-      hidden_new_dir_dentry = dget_parent(hidden_new_dentry);
+-
+-      lock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry);
+-
+-      err = is_robranch_super(old_dentry->d_sb, bindex);
+-      if (err)
+-              goto out_unlock;
+-
+-      /*
+-       * ready to whiteout for old_dentry. caller will create the actual
+-       * whiteout, and must dput(*wh_old)
+-       */
+-      if (wh_old) {
+-              char *whname;
+-              whname = alloc_whname(old_dentry->d_name.name,
+-                                    old_dentry->d_name.len);
+-              err = PTR_ERR(whname);
+-              if (IS_ERR(whname))
+-                      goto out_unlock;
+-              *wh_old = lookup_one_len(whname, hidden_old_dir_dentry,
+-                                       old_dentry->d_name.len +
+-                                       UNIONFS_WHLEN);
+-              kfree(whname);
+-              err = PTR_ERR(*wh_old);
+-              if (IS_ERR(*wh_old)) {
+-                      *wh_old = NULL;
+-                      goto out_unlock;
+-              }
+-      }
+-
+-      err = vfs_rename(hidden_old_dir_dentry->d_inode, hidden_old_dentry,
+-                       hidden_new_dir_dentry->d_inode, hidden_new_dentry);
+-
+-out_unlock:
+-      unlock_rename(hidden_old_dir_dentry, hidden_new_dir_dentry);
+-
+-      dput(hidden_old_dir_dentry);
+-      dput(hidden_new_dir_dentry);
+-      dput(hidden_old_dentry);
+-
+-out:
+-      if (!err) {
+-              /* Fixup the new_dentry. */
+-              if (bindex < dbstart(new_dentry))
+-                      set_dbstart(new_dentry, bindex);
+-              else if (bindex > dbend(new_dentry))
+-                      set_dbend(new_dentry, bindex);
+-      }
+-
+-      kfree(wh_name);
+-
+-      return err;
+-}
+-
+-/*
+- * Main rename code.  This is sufficienly complex, that it's documented in
+- * Docmentation/filesystems/unionfs/rename.txt.  This routine calls
+- * __unionfs_rename() above to perform some of the work.
+- */
+-static int do_unionfs_rename(struct inode *old_dir,
+-                           struct dentry *old_dentry,
+-                           struct inode *new_dir,
+-                           struct dentry *new_dentry)
+-{
+-      int err = 0;
+-      int bindex, bwh_old;
+-      int old_bstart, old_bend;
+-      int new_bstart, new_bend;
+-      int do_copyup = -1;
+-      struct dentry *parent_dentry;
+-      int local_err = 0;
+-      int eio = 0;
+-      int revert = 0;
+-      struct dentry *wh_old = NULL;
+-
+-      old_bstart = dbstart(old_dentry);
+-      bwh_old = old_bstart;
+-      old_bend = dbend(old_dentry);
+-      parent_dentry = old_dentry->d_parent;
+-
+-      new_bstart = dbstart(new_dentry);
+-      new_bend = dbend(new_dentry);
+-
+-      /* Rename source to destination. */
+-      err = __unionfs_rename(old_dir, old_dentry, new_dir, new_dentry,
+-                             old_bstart, &wh_old);
+-      if (err) {
+-              if (!IS_COPYUP_ERR(err))
+-                      goto out;
+-              do_copyup = old_bstart - 1;
+-      } else
+-              revert = 1;
+-
+-      /*
+-       * Unlink all instances of destination that exist to the left of
+-       * bstart of source. On error, revert back, goto out.
+-       */
+-      for (bindex = old_bstart - 1; bindex >= new_bstart; bindex--) {
+-              struct dentry *unlink_dentry;
+-              struct dentry *unlink_dir_dentry;
+-
+-              unlink_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
+-              if (!unlink_dentry)
+-                      continue;
+-
+-              unlink_dir_dentry = lock_parent(unlink_dentry);
+-              if (!(err = is_robranch_super(old_dir->i_sb, bindex)))
+-                      err = vfs_unlink(unlink_dir_dentry->d_inode,
+-                                       unlink_dentry);
+-
+-              fsstack_copy_attr_times(new_dentry->d_parent->d_inode,
+-                                      unlink_dir_dentry->d_inode);
+-              /* propagate number of hard-links */
+-              new_dentry->d_parent->d_inode->i_nlink =
+-                      unionfs_get_nlinks(new_dentry->d_parent->d_inode);
+-
+-              unlock_dir(unlink_dir_dentry);
+-              if (!err) {
+-                      if (bindex != new_bstart) {
+-                              dput(unlink_dentry);
+-                              unionfs_set_lower_dentry_idx(new_dentry,
+-                                                           bindex, NULL);
+-                      }
+-              } else if (IS_COPYUP_ERR(err)) {
+-                      do_copyup = bindex - 1;
+-              } else if (revert) {
+-                      dput(wh_old);
+-                      goto revert;
+-              }
+-      }
+-
+-      if (do_copyup != -1) {
+-              for (bindex = do_copyup; bindex >= 0; bindex--) {
+-                      /*
+-                       * copyup the file into some left directory, so that
+-                       * you can rename it
+-                       */
+-                      err = copyup_dentry(old_dentry->d_parent->d_inode,
+-                                          old_dentry, old_bstart, bindex,
+-                                          NULL, old_dentry->d_inode->i_size);
+-                      if (!err) {
+-                              dput(wh_old);
+-                              bwh_old = bindex;
+-                              err = __unionfs_rename(old_dir, old_dentry,
+-                                                     new_dir, new_dentry,
+-                                                     bindex, &wh_old);
+-                              break;
+-                      }
+-              }
+-      }
+-
+-      /* make it opaque */
+-      if (S_ISDIR(old_dentry->d_inode->i_mode)) {
+-              err = make_dir_opaque(old_dentry, dbstart(old_dentry));
+-              if (err)
+-                      goto revert;
+-      }
+-
+-      /*
+-       * Create whiteout for source, only if:
+-       * (1) There is more than one underlying instance of source.
+-       * (2) We did a copy_up
+-       */
+-      if ((old_bstart != old_bend) || (do_copyup != -1)) {
+-              struct dentry *hidden_parent;
+-              BUG_ON(!wh_old || wh_old->d_inode || bwh_old < 0);
+-              hidden_parent = lock_parent(wh_old);
+-              local_err = vfs_create(hidden_parent->d_inode, wh_old, S_IRUGO,
+-                                     NULL);
+-              unlock_dir(hidden_parent);
+-              if (!local_err)
+-                      set_dbopaque(old_dentry, bwh_old);
+-              else {
+-                      /*
+-                       * we can't fix anything now, so we cop-out and use
+-                       * -EIO.
+-                       */
+-                      printk(KERN_ERR "unionfs: can't create a whiteout for "
+-                             "the source in rename!\n");
+-                      err = -EIO;
+-              }
+-      }
+-
+-out:
+-      dput(wh_old);
+-      return err;
+-
+-revert:
+-      /* Do revert here. */
+-      local_err = unionfs_refresh_hidden_dentry(new_dentry, old_bstart);
+-      if (local_err) {
+-              printk(KERN_WARNING "unionfs: revert failed in rename: "
+-                     "the new refresh failed.\n");
+-              eio = -EIO;
+-      }
+-
+-      local_err = unionfs_refresh_hidden_dentry(old_dentry, old_bstart);
+-      if (local_err) {
+-              printk(KERN_WARNING "unionfs: revert failed in rename: "
+-                     "the old refresh failed.\n");
+-              eio = -EIO;
+-              goto revert_out;
+-      }
+-
+-      if (!unionfs_lower_dentry_idx(new_dentry, bindex) ||
+-          !unionfs_lower_dentry_idx(new_dentry, bindex)->d_inode) {
+-              printk(KERN_WARNING "unionfs: revert failed in rename: "
+-                     "the object disappeared from under us!\n");
+-              eio = -EIO;
+-              goto revert_out;
+-      }
+-
+-      if (unionfs_lower_dentry_idx(old_dentry, bindex) &&
+-          unionfs_lower_dentry_idx(old_dentry, bindex)->d_inode) {
+-              printk(KERN_WARNING "unionfs: revert failed in rename: "
+-                     "the object was created underneath us!\n");
+-              eio = -EIO;
+-              goto revert_out;
+-      }
+-
+-      local_err = __unionfs_rename(new_dir, new_dentry,
+-                                   old_dir, old_dentry, old_bstart, NULL);
+-
+-      /* If we can't fix it, then we cop-out with -EIO. */
+-      if (local_err) {
+-              printk(KERN_WARNING "unionfs: revert failed in rename!\n");
+-              eio = -EIO;
+-      }
+-
+-      local_err = unionfs_refresh_hidden_dentry(new_dentry, bindex);
+-      if (local_err)
+-              eio = -EIO;
+-      local_err = unionfs_refresh_hidden_dentry(old_dentry, bindex);
+-      if (local_err)
+-              eio = -EIO;
+-
+-revert_out:
+-      if (eio)
+-              err = eio;
+-      return err;
+-}
+-
+-static struct dentry *lookup_whiteout(struct dentry *dentry)
+-{
+-      char *whname;
+-      int bindex = -1, bstart = -1, bend = -1;
+-      struct dentry *parent, *hidden_parent, *wh_dentry;
+-
+-      whname = alloc_whname(dentry->d_name.name, dentry->d_name.len);
+-      if (IS_ERR(whname))
+-              return (void *)whname;
+-
+-      parent = dget_parent(dentry);
+-      unionfs_lock_dentry(parent);
+-      bstart = dbstart(parent);
+-      bend = dbend(parent);
+-      wh_dentry = ERR_PTR(-ENOENT);
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_parent = unionfs_lower_dentry_idx(parent, bindex);
+-              if (!hidden_parent)
+-                      continue;
+-              wh_dentry = lookup_one_len(whname, hidden_parent,
+-                                         dentry->d_name.len + UNIONFS_WHLEN);
+-              if (IS_ERR(wh_dentry))
+-                      continue;
+-              if (wh_dentry->d_inode)
+-                      break;
+-              dput(wh_dentry);
+-              wh_dentry = ERR_PTR(-ENOENT);
+-      }
+-      unionfs_unlock_dentry(parent);
+-      dput(parent);
+-      kfree(whname);
+-      return wh_dentry;
+-}
+-
+-/*
+- * We can't copyup a directory, because it may involve huge numbers of
+- * children, etc.  Doing that in the kernel would be bad, so instead we
+- * return EXDEV to the user-space utility that caused this, and let the
+- * user-space recurse and ask us to copy up each file separately.
+- */
+-static int may_rename_dir(struct dentry *dentry)
+-{
+-      int err, bstart;
+-
+-      err = check_empty(dentry, NULL);
+-      if (err == -ENOTEMPTY) {
+-              if (is_robranch(dentry))
+-                      return -EXDEV;
+-      } else if (err)
+-              return err;
+-
+-      bstart = dbstart(dentry);
+-      if (dbend(dentry) == bstart || dbopaque(dentry) == bstart)
+-              return 0;
+-
+-      set_dbstart(dentry, bstart + 1);
+-      err = check_empty(dentry, NULL);
+-      set_dbstart(dentry, bstart);
+-      if (err == -ENOTEMPTY)
+-              err = -EXDEV;
+-      return err;
+-}
+-
+-int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+-                 struct inode *new_dir, struct dentry *new_dentry)
+-{
+-      int err = 0;
+-      struct dentry *wh_dentry;
+-
+-      unionfs_read_lock(old_dentry->d_sb);
+-      unionfs_double_lock_dentry(old_dentry, new_dentry);
+-
+-      if (!__unionfs_d_revalidate_chain(old_dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-      if (!d_deleted(new_dentry) && new_dentry->d_inode &&
+-          !__unionfs_d_revalidate_chain(new_dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      if (!S_ISDIR(old_dentry->d_inode->i_mode))
+-              err = unionfs_partial_lookup(old_dentry);
+-      else
+-              err = may_rename_dir(old_dentry);
+-
+-      if (err)
+-              goto out;
+-
+-      err = unionfs_partial_lookup(new_dentry);
+-      if (err)
+-              goto out;
+-
+-      /*
+-       * if new_dentry is already hidden because of whiteout,
+-       * simply override it even if the whited-out dir is not empty.
+-       */
+-      wh_dentry = lookup_whiteout(new_dentry);
+-      if (!IS_ERR(wh_dentry))
+-              dput(wh_dentry);
+-      else if (new_dentry->d_inode) {
+-              if (S_ISDIR(old_dentry->d_inode->i_mode) !=
+-                  S_ISDIR(new_dentry->d_inode->i_mode)) {
+-                      err = S_ISDIR(old_dentry->d_inode->i_mode) ?
+-                              -ENOTDIR : -EISDIR;
+-                      goto out;
+-              }
+-
+-              if (S_ISDIR(new_dentry->d_inode->i_mode)) {
+-                      struct unionfs_dir_state *namelist;
+-                      /* check if this unionfs directory is empty or not */
+-                      err = check_empty(new_dentry, &namelist);
+-                      if (err)
+-                              goto out;
+-
+-                      if (!is_robranch(new_dentry))
+-                              err = delete_whiteouts(new_dentry,
+-                                                     dbstart(new_dentry),
+-                                                     namelist);
+-
+-                      free_rdstate(namelist);
+-
+-                      if (err)
+-                              goto out;
+-              }
+-      }
+-      err = do_unionfs_rename(old_dir, old_dentry, new_dir, new_dentry);
+-
+-out:
+-      if (err)
+-              /* clear the new_dentry stuff created */
+-              d_drop(new_dentry);
+-      else
+-              /*
+-               * force re-lookup since the dir on ro branch is not renamed,
+-               * and hidden dentries still indicate the un-renamed ones.
+-               */
+-              if (S_ISDIR(old_dentry->d_inode->i_mode))
+-                      atomic_dec(&UNIONFS_D(old_dentry)->generation);
+-
+-      unionfs_unlock_dentry(new_dentry);
+-      unionfs_unlock_dentry(old_dentry);
+-      unionfs_read_unlock(old_dentry->d_sb);
+-      return err;
+-}
+diff -Nurb linux-2.6.22-590/fs/unionfs/sioq.c linux-2.6.22-570/fs/unionfs/sioq.c
+--- linux-2.6.22-590/fs/unionfs/sioq.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/sioq.c 1969-12-31 19:00:00.000000000 -0500
+@@ -1,118 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/*
+- * Super-user IO work Queue - sometimes we need to perform actions which
+- * would fail due to the unix permissions on the parent directory (e.g.,
+- * rmdir a directory which appears empty, but in reality contains
+- * whiteouts).
+- */
+-
+-static struct workqueue_struct *superio_workqueue;
+-
+-int __init init_sioq(void)
+-{
+-      int err;
+-
+-      superio_workqueue = create_workqueue("unionfs_siod");
+-      if (!IS_ERR(superio_workqueue))
+-              return 0;
+-
+-      err = PTR_ERR(superio_workqueue);
+-      printk(KERN_ERR "unionfs: create_workqueue failed %d\n", err);
+-      superio_workqueue = NULL;
+-      return err;
+-}
+-
+-void stop_sioq(void)
+-{
+-      if (superio_workqueue)
+-              destroy_workqueue(superio_workqueue);
+-}
+-
+-void run_sioq(work_func_t func, struct sioq_args *args)
+-{
+-      INIT_WORK(&args->work, func);
+-
+-      init_completion(&args->comp);
+-      while (!queue_work(superio_workqueue, &args->work)) {
+-              /* TODO: do accounting if needed */
+-              schedule();
+-      }
+-      wait_for_completion(&args->comp);
+-}
+-
+-void __unionfs_create(struct work_struct *work)
+-{
+-      struct sioq_args *args = container_of(work, struct sioq_args, work);
+-      struct create_args *c = &args->create;
+-
+-      args->err = vfs_create(c->parent, c->dentry, c->mode, c->nd);
+-      complete(&args->comp);
+-}
+-
+-void __unionfs_mkdir(struct work_struct *work)
+-{
+-      struct sioq_args *args = container_of(work, struct sioq_args, work);
+-      struct mkdir_args *m = &args->mkdir;
+-
+-      args->err = vfs_mkdir(m->parent, m->dentry, m->mode);
+-      complete(&args->comp);
+-}
+-
+-void __unionfs_mknod(struct work_struct *work)
+-{
+-      struct sioq_args *args = container_of(work, struct sioq_args, work);
+-      struct mknod_args *m = &args->mknod;
+-
+-      args->err = vfs_mknod(m->parent, m->dentry, m->mode, m->dev);
+-      complete(&args->comp);
+-}
+-
+-void __unionfs_symlink(struct work_struct *work)
+-{
+-      struct sioq_args *args = container_of(work, struct sioq_args, work);
+-      struct symlink_args *s = &args->symlink;
+-
+-      args->err = vfs_symlink(s->parent, s->dentry, s->symbuf, s->mode);
+-      complete(&args->comp);
+-}
+-
+-void __unionfs_unlink(struct work_struct *work)
+-{
+-      struct sioq_args *args = container_of(work, struct sioq_args, work);
+-      struct unlink_args *u = &args->unlink;
+-
+-      args->err = vfs_unlink(u->parent, u->dentry);
+-      complete(&args->comp);
+-}
+-
+-void __delete_whiteouts(struct work_struct *work)
+-{
+-      struct sioq_args *args = container_of(work, struct sioq_args, work);
+-      struct deletewh_args *d = &args->deletewh;
+-
+-      args->err = do_delete_whiteouts(d->dentry, d->bindex, d->namelist);
+-      complete(&args->comp);
+-}
+-
+-void __is_opaque_dir(struct work_struct *work)
+-{
+-      struct sioq_args *args = container_of(work, struct sioq_args, work);
+-
+-      args->ret = lookup_one_len(UNIONFS_DIR_OPAQUE, args->is_opaque.dentry,
+-                                 sizeof(UNIONFS_DIR_OPAQUE) - 1);
+-      complete(&args->comp);
+-}
+diff -Nurb linux-2.6.22-590/fs/unionfs/sioq.h linux-2.6.22-570/fs/unionfs/sioq.h
+--- linux-2.6.22-590/fs/unionfs/sioq.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/sioq.h 1969-12-31 19:00:00.000000000 -0500
+@@ -1,91 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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.
+- */
+-
+-#ifndef _SIOQ_H
+-#define _SIOQ_H
+-
+-struct deletewh_args {
+-      struct unionfs_dir_state *namelist;
+-      struct dentry *dentry;
+-      int bindex;
+-};
+-
+-struct is_opaque_args {
+-      struct dentry *dentry;
+-};
+-
+-struct create_args {
+-      struct inode *parent;
+-      struct dentry *dentry;
+-      umode_t mode;
+-      struct nameidata *nd;
+-};
+-
+-struct mkdir_args {
+-      struct inode *parent;
+-      struct dentry *dentry;
+-      umode_t mode;
+-};
+-
+-struct mknod_args {
+-      struct inode *parent;
+-      struct dentry *dentry;
+-      umode_t mode;
+-      dev_t dev;
+-};
+-
+-struct symlink_args {
+-      struct inode *parent;
+-      struct dentry *dentry;
+-      char *symbuf;
+-      umode_t mode;
+-};
+-
+-struct unlink_args {
+-      struct inode *parent;
+-      struct dentry *dentry;
+-};
+-
+-
+-struct sioq_args {
+-      struct completion comp;
+-      struct work_struct work;
+-      int err;
+-      void *ret;
+-
+-      union {
+-              struct deletewh_args deletewh;
+-              struct is_opaque_args is_opaque;
+-              struct create_args create;
+-              struct mkdir_args mkdir;
+-              struct mknod_args mknod;
+-              struct symlink_args symlink;
+-              struct unlink_args unlink;
+-      };
+-};
+-
+-/* Extern definitions for SIOQ functions */
+-extern int __init init_sioq(void);
+-extern void stop_sioq(void);
+-extern void run_sioq(work_func_t func, struct sioq_args *args);
+-
+-/* Extern definitions for our privilege escalation helpers */
+-extern void __unionfs_create(struct work_struct *work);
+-extern void __unionfs_mkdir(struct work_struct *work);
+-extern void __unionfs_mknod(struct work_struct *work);
+-extern void __unionfs_symlink(struct work_struct *work);
+-extern void __unionfs_unlink(struct work_struct *work);
+-extern void __delete_whiteouts(struct work_struct *work);
+-extern void __is_opaque_dir(struct work_struct *work);
+-
+-#endif /* _SIOQ_H */
+diff -Nurb linux-2.6.22-590/fs/unionfs/subr.c linux-2.6.22-570/fs/unionfs/subr.c
+--- linux-2.6.22-590/fs/unionfs/subr.c 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/subr.c 1969-12-31 19:00:00.000000000 -0500
+@@ -1,238 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/*
+- * Pass an unionfs dentry and an index.  It will try to create a whiteout
+- * for the filename in dentry, and will try in branch 'index'.  On error,
+- * it will proceed to a branch to the left.
+- */
+-int create_whiteout(struct dentry *dentry, int start)
+-{
+-      int bstart, bend, bindex;
+-      struct dentry *hidden_dir_dentry;
+-      struct dentry *hidden_dentry;
+-      struct dentry *hidden_wh_dentry;
+-      char *name = NULL;
+-      int err = -EINVAL;
+-
+-      verify_locked(dentry);
+-
+-      bstart = dbstart(dentry);
+-      bend = dbend(dentry);
+-
+-      /* create dentry's whiteout equivalent */
+-      name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
+-      if (IS_ERR(name)) {
+-              err = PTR_ERR(name);
+-              goto out;
+-      }
+-
+-      for (bindex = start; bindex >= 0; bindex--) {
+-              hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-
+-              if (!hidden_dentry) {
+-                      /*
+-                       * if hidden dentry is not present, create the
+-                       * entire hidden dentry directory structure and go
+-                       * ahead.  Since we want to just create whiteout, we
+-                       * only want the parent dentry, and hence get rid of
+-                       * this dentry.
+-                       */
+-                      hidden_dentry = create_parents(dentry->d_inode,
+-                                                     dentry, bindex);
+-                      if (!hidden_dentry || IS_ERR(hidden_dentry)) {
+-                              printk(KERN_DEBUG "unionfs: create_parents "
+-                                     "failed for bindex = %d\n", bindex);
+-                              continue;
+-                      }
+-              }
+-
+-              hidden_wh_dentry =
+-                      lookup_one_len(name, hidden_dentry->d_parent,
+-                                     dentry->d_name.len + UNIONFS_WHLEN);
+-              if (IS_ERR(hidden_wh_dentry))
+-                      continue;
+-
+-              /*
+-               * The whiteout already exists. This used to be impossible,
+-               * but now is possible because of opaqueness.
+-               */
+-              if (hidden_wh_dentry->d_inode) {
+-                      dput(hidden_wh_dentry);
+-                      err = 0;
+-                      goto out;
+-              }
+-
+-              hidden_dir_dentry = lock_parent(hidden_wh_dentry);
+-              if (!(err = is_robranch_super(dentry->d_sb, bindex)))
+-                      err = vfs_create(hidden_dir_dentry->d_inode,
+-                                       hidden_wh_dentry,
+-                                       ~current->fs->umask & S_IRWXUGO,
+-                                       NULL);
+-              unlock_dir(hidden_dir_dentry);
+-              dput(hidden_wh_dentry);
+-
+-              if (!err || !IS_COPYUP_ERR(err))
+-                      break;
+-      }
+-
+-      /* set dbopaque so that lookup will not proceed after this branch */
+-      if (!err)
+-              set_dbopaque(dentry, bindex);
+-
+-out:
+-      kfree(name);
+-      return err;
+-}
+-
+-/*
+- * This is a helper function for rename, which ends up with hosed over
+- * dentries when it needs to revert.
+- */
+-int unionfs_refresh_hidden_dentry(struct dentry *dentry, int bindex)
+-{
+-      struct dentry *hidden_dentry;
+-      struct dentry *hidden_parent;
+-      int err = 0;
+-
+-      verify_locked(dentry);
+-
+-      unionfs_lock_dentry(dentry->d_parent);
+-      hidden_parent = unionfs_lower_dentry_idx(dentry->d_parent, bindex);
+-      unionfs_unlock_dentry(dentry->d_parent);
+-
+-      BUG_ON(!S_ISDIR(hidden_parent->d_inode->i_mode));
+-
+-      hidden_dentry = lookup_one_len(dentry->d_name.name, hidden_parent,
+-                                     dentry->d_name.len);
+-      if (IS_ERR(hidden_dentry)) {
+-              err = PTR_ERR(hidden_dentry);
+-              goto out;
+-      }
+-
+-      dput(unionfs_lower_dentry_idx(dentry, bindex));
+-      iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
+-      unionfs_set_lower_inode_idx(dentry->d_inode, bindex, NULL);
+-
+-      if (!hidden_dentry->d_inode) {
+-              dput(hidden_dentry);
+-              unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
+-      } else {
+-              unionfs_set_lower_dentry_idx(dentry, bindex, hidden_dentry);
+-              unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
+-                                          igrab(hidden_dentry->d_inode));
+-      }
+-
+-out:
+-      return err;
+-}
+-
+-int make_dir_opaque(struct dentry *dentry, int bindex)
+-{
+-      int err = 0;
+-      struct dentry *hidden_dentry, *diropq;
+-      struct inode *hidden_dir;
+-
+-      hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-      hidden_dir = hidden_dentry->d_inode;
+-      BUG_ON(!S_ISDIR(dentry->d_inode->i_mode) ||
+-             !S_ISDIR(hidden_dir->i_mode));
+-
+-      mutex_lock(&hidden_dir->i_mutex);
+-      diropq = lookup_one_len(UNIONFS_DIR_OPAQUE, hidden_dentry,
+-                              sizeof(UNIONFS_DIR_OPAQUE) - 1);
+-      if (IS_ERR(diropq)) {
+-              err = PTR_ERR(diropq);
+-              goto out;
+-      }
+-
+-      if (!diropq->d_inode)
+-              err = vfs_create(hidden_dir, diropq, S_IRUGO, NULL);
+-      if (!err)
+-              set_dbopaque(dentry, bindex);
+-
+-      dput(diropq);
+-
+-out:
+-      mutex_unlock(&hidden_dir->i_mutex);
+-      return err;
+-}
+-
+-/*
+- * returns the sum of the n_link values of all the underlying inodes of the
+- * passed inode
+- */
+-int unionfs_get_nlinks(struct inode *inode)
+-{
+-      int sum_nlinks = 0;
+-      int dirs = 0;
+-      int bindex;
+-      struct inode *hidden_inode;
+-
+-      /* don't bother to do all the work since we're unlinked */
+-      if (inode->i_nlink == 0)
+-              return 0;
+-
+-      if (!S_ISDIR(inode->i_mode))
+-              return unionfs_lower_inode(inode)->i_nlink;
+-
+-      for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
+-              hidden_inode = unionfs_lower_inode_idx(inode, bindex);
+-
+-              /* ignore files */
+-              if (!hidden_inode || !S_ISDIR(hidden_inode->i_mode))
+-                      continue;
+-
+-              BUG_ON(hidden_inode->i_nlink < 0);
+-
+-              /* A deleted directory. */
+-              if (hidden_inode->i_nlink == 0)
+-                      continue;
+-              dirs++;
+-
+-              /*
+-               * A broken directory...
+-               *
+-               * Some filesystems don't properly set the number of links
+-               * on empty directories
+-               */
+-              if (hidden_inode->i_nlink == 1)
+-                      sum_nlinks += 2;
+-              else
+-                      sum_nlinks += (hidden_inode->i_nlink - 2);
+-      }
+-
+-      return (!dirs ? 0 : sum_nlinks + 2);
+-}
+-
+-/* construct whiteout filename */
+-char *alloc_whname(const char *name, int len)
+-{
+-      char *buf;
+-
+-      buf = kmalloc(len + UNIONFS_WHLEN + 1, GFP_KERNEL);
+-      if (!buf)
+-              return ERR_PTR(-ENOMEM);
+-
+-      strcpy(buf, UNIONFS_WHPFX);
+-      strlcat(buf, name, len + UNIONFS_WHLEN + 1);
+-
+-      return buf;
+-}
+diff -Nurb linux-2.6.22-590/fs/unionfs/super.c linux-2.6.22-570/fs/unionfs/super.c
+--- linux-2.6.22-590/fs/unionfs/super.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/super.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,1002 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/*
+- * The inode cache is used with alloc_inode for both our inode info and the
+- * vfs inode.
+- */
+-static struct kmem_cache *unionfs_inode_cachep;
+-
+-static void unionfs_read_inode(struct inode *inode)
+-{
+-      extern struct address_space_operations unionfs_aops;
+-      int size;
+-      struct unionfs_inode_info *info = UNIONFS_I(inode);
+-
+-      unionfs_read_lock(inode->i_sb);
+-
+-      memset(info, 0, offsetof(struct unionfs_inode_info, vfs_inode));
+-      info->bstart = -1;
+-      info->bend = -1;
+-      atomic_set(&info->generation,
+-                 atomic_read(&UNIONFS_SB(inode->i_sb)->generation));
+-      spin_lock_init(&info->rdlock);
+-      info->rdcount = 1;
+-      info->hashsize = -1;
+-      INIT_LIST_HEAD(&info->readdircache);
+-
+-      size = sbmax(inode->i_sb) * sizeof(struct inode *);
+-      info->lower_inodes = kzalloc(size, GFP_KERNEL);
+-      if (!info->lower_inodes) {
+-              printk(KERN_ERR "unionfs: no kernel memory when allocating "
+-                     "lower-pointer array!\n");
+-              BUG();
+-      }
+-
+-      inode->i_version++;
+-      inode->i_op = &unionfs_main_iops;
+-      inode->i_fop = &unionfs_main_fops;
+-
+-      inode->i_mapping->a_ops = &unionfs_aops;
+-
+-      unionfs_read_unlock(inode->i_sb);
+-}
+-
+-/*
+- * we now define delete_inode, because there are two VFS paths that may
+- * destroy an inode: one of them calls clear inode before doing everything
+- * else that's needed, and the other is fine.  This way we truncate the inode
+- * size (and its pages) and then clear our own inode, which will do an iput
+- * on our and the lower inode.
+- *
+- * No need to lock sb info's rwsem.
+- */
+-static void unionfs_delete_inode(struct inode *inode)
+-{
+-      inode->i_size = 0;      /* every f/s seems to do that */
+-
+-      if (inode->i_data.nrpages)
+-              truncate_inode_pages(&inode->i_data, 0);
+-
+-      clear_inode(inode);
+-}
+-
+-/*
+- * final actions when unmounting a file system
+- *
+- * No need to lock rwsem.
+- */
+-static void unionfs_put_super(struct super_block *sb)
+-{
+-      int bindex, bstart, bend;
+-      struct unionfs_sb_info *spd;
+-      int leaks = 0;
+-
+-      spd = UNIONFS_SB(sb);
+-      if (!spd)
+-              return;
+-
+-      bstart = sbstart(sb);
+-      bend = sbend(sb);
+-
+-      /* Make sure we have no leaks of branchget/branchput. */
+-      for (bindex = bstart; bindex <= bend; bindex++)
+-              if (branch_count(sb, bindex) != 0) {
+-                      printk("unionfs: branch %d has %d references left!\n",
+-                             bindex, branch_count(sb, bindex));
+-                      leaks = 1;
+-              }
+-      BUG_ON(leaks != 0);
+-
+-      kfree(spd->data);
+-      kfree(spd);
+-      sb->s_fs_info = NULL;
+-}
+-
+-/*
+- * Since people use this to answer the "How big of a file can I write?"
+- * question, we report the size of the highest priority branch as the size of
+- * the union.
+- */
+-static int unionfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+-{
+-      int err = 0;
+-      struct super_block *sb;
+-      struct dentry *lower_dentry;
+-
+-      sb = dentry->d_sb;
+-
+-      unionfs_read_lock(sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      lower_dentry = unionfs_lower_dentry(sb->s_root);
+-      err = vfs_statfs(lower_dentry, buf);
+-
+-      /* set return buf to our f/s to avoid confusing user-level utils */
+-      buf->f_type = UNIONFS_SUPER_MAGIC;
+-
+-      /*
+-       * Our maximum file name can is shorter by a few bytes because every
+-       * file name could potentially be whited-out.
+-       */
+-      buf->f_namelen -= UNIONFS_WHLEN;
+-
+-      memset(&buf->f_fsid, 0, sizeof(__kernel_fsid_t));
+-      memset(&buf->f_spare, 0, sizeof(buf->f_spare));
+-
+-out:
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(sb);
+-      return err;
+-}
+-
+-/* handle mode changing during remount */
+-static noinline int do_remount_mode_option(char *optarg, int cur_branches,
+-                                         struct unionfs_data *new_data,
+-                                         struct path *new_lower_paths)
+-{
+-      int err = -EINVAL;
+-      int perms, idx;
+-      char *modename = strchr(optarg, '=');
+-      struct nameidata nd;
+-
+-      /* by now, optarg contains the branch name */
+-      if (!*optarg) {
+-              printk("unionfs: no branch specified for mode change.\n");
+-              goto out;
+-      }
+-      if (!modename) {
+-              printk("unionfs: branch \"%s\" requires a mode.\n", optarg);
+-              goto out;
+-      }
+-      *modename++ = '\0';
+-      perms = __parse_branch_mode(modename);
+-      if (perms == 0) {
+-              printk("unionfs: invalid mode \"%s\" for \"%s\".\n",
+-                     modename, optarg);
+-              goto out;
+-      }
+-
+-      /*
+-       * Find matching branch index.  For now, this assumes that nothing
+-       * has been mounted on top of this Unionfs stack.  Once we have /odf
+-       * and cache-coherency resolved, we'll address the branch-path
+-       * uniqueness.
+-       */
+-      err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
+-      if (err) {
+-              printk(KERN_WARNING "unionfs: error accessing "
+-                     "hidden directory \"%s\" (error %d)\n",
+-                     optarg, err);
+-              goto out;
+-      }
+-      for (idx=0; idx<cur_branches; idx++)
+-              if (nd.mnt == new_lower_paths[idx].mnt &&
+-                  nd.dentry == new_lower_paths[idx].dentry)
+-                      break;
+-      path_release(&nd);      /* no longer needed */
+-      if (idx == cur_branches) {
+-              err = -ENOENT;  /* err may have been reset above */
+-              printk(KERN_WARNING "unionfs: branch \"%s\" "
+-                     "not found\n", optarg);
+-              goto out;
+-      }
+-      /* check/change mode for existing branch */
+-      /* we don't warn if perms==branchperms */
+-      new_data[idx].branchperms = perms;
+-      err = 0;
+-out:
+-      return err;
+-}
+-
+-/* handle branch deletion during remount */
+-static noinline int do_remount_del_option(char *optarg, int cur_branches,
+-                                        struct unionfs_data *new_data,
+-                                        struct path *new_lower_paths)
+-{
+-      int err = -EINVAL;
+-      int idx;
+-      struct nameidata nd;
+-
+-      /* optarg contains the branch name to delete */
+-
+-      /*
+-       * Find matching branch index.  For now, this assumes that nothing
+-       * has been mounted on top of this Unionfs stack.  Once we have /odf
+-       * and cache-coherency resolved, we'll address the branch-path
+-       * uniqueness.
+-       */
+-      err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
+-      if (err) {
+-              printk(KERN_WARNING "unionfs: error accessing "
+-                     "hidden directory \"%s\" (error %d)\n",
+-                     optarg, err);
+-              goto out;
+-      }
+-      for (idx=0; idx < cur_branches; idx++)
+-              if (nd.mnt == new_lower_paths[idx].mnt &&
+-                  nd.dentry == new_lower_paths[idx].dentry)
+-                      break;
+-      path_release(&nd);      /* no longer needed */
+-      if (idx == cur_branches) {
+-              printk(KERN_WARNING "unionfs: branch \"%s\" "
+-                     "not found\n", optarg);
+-              err = -ENOENT;
+-              goto out;
+-      }
+-      /* check if there are any open files on the branch to be deleted */
+-      if (atomic_read(&new_data[idx].open_files) > 0) {
+-              err = -EBUSY;
+-              goto out;
+-      }
+-
+-      /*
+-       * Now we have to delete the branch.  First, release any handles it
+-       * has.  Then, move the remaining array indexes past "idx" in
+-       * new_data and new_lower_paths one to the left.  Finally, adjust
+-       * cur_branches.
+-       */
+-      pathput(&new_lower_paths[idx]);
+-
+-      if (idx < cur_branches - 1) {
+-              /* if idx==cur_branches-1, we delete last branch: easy */
+-              memmove(&new_data[idx], &new_data[idx+1],
+-                      (cur_branches - 1 - idx) *
+-                      sizeof(struct unionfs_data));
+-              memmove(&new_lower_paths[idx], &new_lower_paths[idx+1],
+-                      (cur_branches - 1 - idx) * sizeof(struct path));
+-      }
+-
+-      err = 0;
+-out:
+-      return err;
+-}
+-
+-/* handle branch insertion during remount */
+-static noinline int do_remount_add_option(char *optarg, int cur_branches,
+-                                        struct unionfs_data *new_data,
+-                                        struct path *new_lower_paths,
+-                                        int *high_branch_id)
+-{
+-      int err = -EINVAL;
+-      int perms;
+-      int idx = 0;            /* default: insert at beginning */
+-      char *new_branch , *modename = NULL;
+-      struct nameidata nd;
+-
+-      /*
+-       * optarg can be of several forms:
+-       *
+-       * /bar:/foo            insert /foo before /bar
+-       * /bar:/foo=ro         insert /foo in ro mode before /bar
+-       * /foo                 insert /foo in the beginning (prepend)
+-       * :/foo                insert /foo at the end (append)
+-       */
+-      if (*optarg == ':') {   /* append? */
+-              new_branch = optarg + 1; /* skip ':' */
+-              idx = cur_branches;
+-              goto found_insertion_point;
+-      }
+-      new_branch = strchr(optarg, ':');
+-      if (!new_branch) {      /* prepend? */
+-              new_branch = optarg;
+-              goto found_insertion_point;
+-      }
+-      *new_branch++ = '\0';   /* holds path+mode of new branch */
+-
+-      /*
+-       * Find matching branch index.  For now, this assumes that nothing
+-       * has been mounted on top of this Unionfs stack.  Once we have /odf
+-       * and cache-coherency resolved, we'll address the branch-path
+-       * uniqueness.
+-       */
+-      err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
+-      if (err) {
+-              printk(KERN_WARNING "unionfs: error accessing "
+-                     "hidden directory \"%s\" (error %d)\n",
+-                     optarg, err);
+-              goto out;
+-      }
+-      for (idx=0; idx < cur_branches; idx++)
+-              if (nd.mnt == new_lower_paths[idx].mnt &&
+-                  nd.dentry == new_lower_paths[idx].dentry)
+-                      break;
+-      path_release(&nd);      /* no longer needed */
+-      if (idx == cur_branches) {
+-              printk(KERN_WARNING "unionfs: branch \"%s\" "
+-                     "not found\n", optarg);
+-              err = -ENOENT;
+-              goto out;
+-      }
+-
+-      /*
+-       * At this point idx will hold the index where the new branch should
+-       * be inserted before.
+-       */
+-found_insertion_point:
+-      /* find the mode for the new branch */
+-      if (new_branch)
+-              modename = strchr(new_branch, '=');
+-      if (modename)
+-              *modename++ = '\0';
+-      perms = parse_branch_mode(modename);
+-
+-      if (!new_branch || !*new_branch) {
+-              printk(KERN_WARNING "unionfs: null new branch\n");
+-              err = -EINVAL;
+-              goto out;
+-      }
+-      err = path_lookup(new_branch, LOOKUP_FOLLOW, &nd);
+-      if (err) {
+-              printk(KERN_WARNING "unionfs: error accessing "
+-                     "hidden directory \"%s\" (error %d)\n",
+-                     new_branch, err);
+-              goto out;
+-      }
+-      /*
+-       * It's probably safe to check_mode the new branch to insert.  Note:
+-       * we don't allow inserting branches which are unionfs's by
+-       * themselves (check_branch returns EINVAL in that case).  This is
+-       * because this code base doesn't support stacking unionfs: the ODF
+-       * code base supports that correctly.
+-       */
+-      if ((err = check_branch(&nd))) {
+-              printk(KERN_WARNING "unionfs: hidden directory "
+-                     "\"%s\" is not a valid branch\n", optarg);
+-              path_release(&nd);
+-              goto out;
+-      }
+-
+-      /*
+-       * Now we have to insert the new branch.  But first, move the bits
+-       * to make space for the new branch, if needed.  Finally, adjust
+-       * cur_branches.
+-       * We don't release nd here; it's kept until umount/remount.
+-       */
+-      if (idx < cur_branches) {
+-              /* if idx==cur_branches, we append: easy */
+-              memmove(&new_data[idx+1], &new_data[idx],
+-                      (cur_branches - idx) * sizeof(struct unionfs_data));
+-              memmove(&new_lower_paths[idx+1], &new_lower_paths[idx],
+-                      (cur_branches - idx) * sizeof(struct path));
+-      }
+-      new_lower_paths[idx].dentry = nd.dentry;
+-      new_lower_paths[idx].mnt = nd.mnt;
+-
+-      new_data[idx].sb = nd.dentry->d_sb;
+-      atomic_set(&new_data[idx].open_files, 0);
+-      new_data[idx].branchperms = perms;
+-      new_data[idx].branch_id = ++*high_branch_id; /* assign new branch ID */
+-
+-      err = 0;
+-out:
+-      return err;
+-}
+-
+-
+-/*
+- * Support branch management options on remount.
+- *
+- * See Documentation/filesystems/unionfs/ for details.
+- *
+- * @flags: numeric mount options
+- * @options: mount options string
+- *
+- * This function can rearrange a mounted union dynamically, adding and
+- * removing branches, including changing branch modes.  Clearly this has to
+- * be done safely and atomically.  Luckily, the VFS already calls this
+- * function with lock_super(sb) and lock_kernel() held, preventing
+- * concurrent mixing of new mounts, remounts, and unmounts.  Moreover,
+- * do_remount_sb(), our caller function, already called shrink_dcache_sb(sb)
+- * to purge dentries/inodes from our superblock, and also called
+- * fsync_super(sb) to purge any dirty pages.  So we're good.
+- *
+- * XXX: however, our remount code may also need to invalidate mapped pages
+- * so as to force them to be re-gotten from the (newly reconfigured) lower
+- * branches.  This has to wait for proper mmap and cache coherency support
+- * in the VFS.
+- *
+- */
+-static int unionfs_remount_fs(struct super_block *sb, int *flags,
+-                            char *options)
+-{
+-      int err = 0;
+-      int i;
+-      char *optionstmp, *tmp_to_free; /* kstrdup'ed of "options" */
+-      char *optname;
+-      int cur_branches = 0;   /* no. of current branches */
+-      int new_branches = 0;   /* no. of branches actually left in the end */
+-      int add_branches;       /* est. no. of branches to add */
+-      int del_branches;       /* est. no. of branches to del */
+-      int max_branches;       /* max possible no. of branches */
+-      struct unionfs_data *new_data = NULL, *tmp_data = NULL;
+-      struct path *new_lower_paths = NULL, *tmp_lower_paths = NULL;
+-      struct inode **new_lower_inodes = NULL;
+-      int new_high_branch_id; /* new high branch ID */
+-      int size;               /* memory allocation size, temp var */
+-      int old_ibstart, old_ibend;
+-
+-      unionfs_write_lock(sb);
+-
+-      /*
+-       * The VFS will take care of "ro" and "rw" flags, and we can safely
+-       * ignore MS_SILENT, but anything else left over is an error.  So we
+-       * need to check if any other flags may have been passed (none are
+-       * allowed/supported as of now).
+-       */
+-      if ((*flags & ~(MS_RDONLY | MS_SILENT)) != 0) {
+-              printk(KERN_WARNING
+-                     "unionfs: remount flags 0x%x unsupported\n", *flags);
+-              err = -EINVAL;
+-              goto out_error;
+-      }
+-
+-      /*
+-       * If 'options' is NULL, it's probably because the user just changed
+-       * the union to a "ro" or "rw" and the VFS took care of it.  So
+-       * nothing to do and we're done.
+-       */
+-      if (!options || options[0] == '\0')
+-              goto out_error;
+-
+-      /*
+-       * Find out how many branches we will have in the end, counting
+-       * "add" and "del" commands.  Copy the "options" string because
+-       * strsep modifies the string and we need it later.
+-       */
+-      optionstmp = tmp_to_free = kstrdup(options, GFP_KERNEL);
+-      if (!optionstmp) {
+-              err = -ENOMEM;
+-              goto out_free;
+-      }
+-      new_branches = cur_branches = sbmax(sb); /* current no. branches */
+-      add_branches = del_branches = 0;
+-      new_high_branch_id = sbhbid(sb); /* save current high_branch_id */
+-      while ((optname = strsep(&optionstmp, ",")) != NULL) {
+-              char *optarg;
+-
+-              if (!optname || !*optname)
+-                      continue;
+-
+-              optarg = strchr(optname, '=');
+-              if (optarg)
+-                      *optarg++ = '\0';
+-
+-              if (!strcmp("add", optname))
+-                      add_branches++;
+-              else if (!strcmp("del", optname))
+-                      del_branches++;
+-      }
+-      kfree(tmp_to_free);
+-      /* after all changes, will we have at least one branch left? */
+-      if ((new_branches + add_branches - del_branches) < 1) {
+-              printk(KERN_WARNING
+-                     "unionfs: no branches left after remount\n");
+-              err = -EINVAL;
+-              goto out_free;
+-      }
+-
+-      /*
+-       * Since we haven't actually parsed all the add/del options, nor
+-       * have we checked them for errors, we don't know for sure how many
+-       * branches we will have after all changes have taken place.  In
+-       * fact, the total number of branches left could be less than what
+-       * we have now.  So we need to allocate space for a temporary
+-       * placeholder that is at least as large as the maximum number of
+-       * branches we *could* have, which is the current number plus all
+-       * the additions.  Once we're done with these temp placeholders, we
+-       * may have to re-allocate the final size, copy over from the temp,
+-       * and then free the temps (done near the end of this function).
+-       */
+-      max_branches = cur_branches + add_branches;
+-      /* allocate space for new pointers to hidden dentry */
+-      tmp_data = kcalloc(max_branches,
+-                         sizeof(struct unionfs_data), GFP_KERNEL);
+-      if (!tmp_data) {
+-              err = -ENOMEM;
+-              goto out_free;
+-      }
+-      /* allocate space for new pointers to lower paths */
+-      tmp_lower_paths = kcalloc(max_branches,
+-                                sizeof(struct path), GFP_KERNEL);
+-      if (!tmp_lower_paths) {
+-              err = -ENOMEM;
+-              goto out_free;
+-      }
+-      /* copy current info into new placeholders, incrementing refcnts */
+-      memcpy(tmp_data, UNIONFS_SB(sb)->data,
+-             cur_branches * sizeof(struct unionfs_data));
+-      memcpy(tmp_lower_paths, UNIONFS_D(sb->s_root)->lower_paths,
+-             cur_branches * sizeof(struct path));
+-      for (i=0; i<cur_branches; i++)
+-              pathget(&tmp_lower_paths[i]); /* drop refs at end of fxn */
+-
+-      /*******************************************************************
+-       * For each branch command, do path_lookup on the requested branch,
+-       * and apply the change to a temp branch list.  To handle errors, we
+-       * already dup'ed the old arrays (above), and increased the refcnts
+-       * on various f/s objects.  So now we can do all the path_lookups
+-       * and branch-management commands on the new arrays.  If it fail mid
+-       * way, we free the tmp arrays and *put all objects.  If we succeed,
+-       * then we free old arrays and *put its objects, and then replace
+-       * the arrays with the new tmp list (we may have to re-allocate the
+-       * memory because the temp lists could have been larger than what we
+-       * actually needed).
+-       *******************************************************************/
+-
+-      while ((optname = strsep(&options, ",")) != NULL) {
+-              char *optarg;
+-
+-              if (!optname || !*optname)
+-                      continue;
+-              /*
+-               * At this stage optname holds a comma-delimited option, but
+-               * without the commas.  Next, we need to break the string on
+-               * the '=' symbol to separate CMD=ARG, where ARG itself can
+-               * be KEY=VAL.  For example, in mode=/foo=rw, CMD is "mode",
+-               * KEY is "/foo", and VAL is "rw".
+-               */
+-              optarg = strchr(optname, '=');
+-              if (optarg)
+-                      *optarg++ = '\0';
+-              /* incgen remount option (instead of old ioctl) */
+-              if (!strcmp("incgen", optname)) {
+-                      err = 0;
+-                      goto out_no_change;
+-              }
+-
+-              /*
+-               * All of our options take an argument now.  (Insert ones
+-               * that don't above this check.)  So at this stage optname
+-               * contains the CMD part and optarg contains the ARG part.
+-               */
+-              if (!optarg || !*optarg) {
+-                      printk("unionfs: all remount options require "
+-                             "an argument (%s).\n", optname);
+-                      err = -EINVAL;
+-                      goto out_release;
+-              }
+-
+-              if (!strcmp("add", optname)) {
+-                      err = do_remount_add_option(optarg, new_branches,
+-                                                  tmp_data,
+-                                                  tmp_lower_paths,
+-                                                  &new_high_branch_id);
+-                      if (err)
+-                              goto out_release;
+-                      new_branches++;
+-                      if (new_branches > UNIONFS_MAX_BRANCHES) {
+-                              printk("unionfs: command exceeds "
+-                                     "%d branches\n", UNIONFS_MAX_BRANCHES);
+-                              err = -E2BIG;
+-                              goto out_release;
+-                      }
+-                      continue;
+-              }
+-              if (!strcmp("del", optname)) {
+-                      err = do_remount_del_option(optarg, new_branches,
+-                                                  tmp_data,
+-                                                  tmp_lower_paths);
+-                      if (err)
+-                              goto out_release;
+-                      new_branches--;
+-                      continue;
+-              }
+-              if (!strcmp("mode", optname)) {
+-                      err = do_remount_mode_option(optarg, new_branches,
+-                                                   tmp_data,
+-                                                   tmp_lower_paths);
+-                      if (err)
+-                              goto out_release;
+-                      continue;
+-              }
+-
+-              /*
+-               * When you use "mount -o remount,ro", mount(8) will
+-               * reportedly pass the original dirs= string from
+-               * /proc/mounts.  So for now, we have to ignore dirs= and
+-               * not consider it an error, unless we want to allow users
+-               * to pass dirs= in remount.  Note that to allow the VFS to
+-               * actually process the ro/rw remount options, we have to
+-               * return 0 from this function.
+-               */
+-              if (!strcmp("dirs", optname)) {
+-                      printk(KERN_WARNING
+-                             "unionfs: remount ignoring option \"%s\".\n",
+-                             optname);
+-                      continue;
+-              }
+-
+-              err = -EINVAL;
+-              printk(KERN_WARNING
+-                     "unionfs: unrecognized option \"%s\"\n", optname);
+-              goto out_release;
+-      }
+-
+-out_no_change:
+-
+-      /******************************************************************
+-       * WE'RE ALMOST DONE: check if leftmost branch might be read-only,
+-       * see if we need to allocate a small-sized new vector, copy the
+-       * vectors to their correct place, release the refcnt of the older
+-       * ones, and return.  Also handle invalidating any pages that will
+-       * have to be re-read.
+-       *******************************************************************/
+-
+-      if (!(tmp_data[0].branchperms & MAY_WRITE)) {
+-              printk("unionfs: leftmost branch cannot be read-only "
+-                     "(use \"remount,ro\" to create a read-only union)\n");
+-              err = -EINVAL;
+-              goto out_release;
+-      }
+-
+-      /* (re)allocate space for new pointers to hidden dentry */
+-      size = new_branches * sizeof(struct unionfs_data);
+-      new_data = krealloc(tmp_data, size, GFP_KERNEL);
+-      if (!new_data) {
+-              err = -ENOMEM;
+-              goto out_release;
+-      }
+-
+-      /* allocate space for new pointers to lower paths */
+-      size = new_branches * sizeof(struct path);
+-      new_lower_paths = krealloc(tmp_lower_paths, size, GFP_KERNEL);
+-      if (!new_lower_paths) {
+-              err = -ENOMEM;
+-              goto out_release;
+-      }
+-
+-      /* allocate space for new pointers to lower inodes */
+-      new_lower_inodes = kcalloc(new_branches,
+-                                 sizeof(struct inode *), GFP_KERNEL);
+-      if (!new_lower_inodes) {
+-              err = -ENOMEM;
+-              goto out_release;
+-      }
+-
+-      /*
+-       * OK, just before we actually put the new set of branches in place,
+-       * we need to ensure that our own f/s has no dirty objects left.
+-       * Luckily, do_remount_sb() already calls shrink_dcache_sb(sb) and
+-       * fsync_super(sb), taking care of dentries, inodes, and dirty
+-       * pages.  So all that's left is for us to invalidate any leftover
+-       * (non-dirty) pages to ensure that they will be re-read from the
+-       * new lower branches (and to support mmap).
+-       */
+-
+-      /*
+-       * No we call drop_pagecache_sb() to invalidate all pages in this
+-       * super.  This function calls invalidate_inode_pages(mapping),
+-       * which calls invalidate_mapping_pages(): the latter, however, will
+-       * not invalidate pages which are dirty, locked, under writeback, or
+-       * mapped into page tables.  We shouldn't have to worry about dirty
+-       * or under-writeback pages, because do_remount_sb() called
+-       * fsync_super() which would not have returned until all dirty pages
+-       * were flushed.
+-       *
+-       * But do we have to worry about locked pages?  Is there any chance
+-       * that in here we'll get locked pages?
+-       *
+-       * XXX: what about pages mapped into pagetables?  Are these pages
+-       * which user processes may have mmap(2)'ed?  If so, then we need to
+-       * invalidate those too, no?  Maybe we'll have to write our own
+-       * version of invalidate_mapping_pages() which also handled mapped
+-       * pages.
+-       *
+-       * XXX: Alternatively, maybe we should call truncate_inode_pages(),
+-       * which use two passes over the pages list, and will truncate all
+-       * pages.
+-       */
+-      drop_pagecache_sb(sb);
+-
+-      /* copy new vectors into their correct place */
+-      tmp_data = UNIONFS_SB(sb)->data;
+-      UNIONFS_SB(sb)->data = new_data;
+-      new_data = NULL;        /* so don't free good pointers below */
+-      tmp_lower_paths = UNIONFS_D(sb->s_root)->lower_paths;
+-      UNIONFS_D(sb->s_root)->lower_paths = new_lower_paths;
+-      new_lower_paths = NULL; /* so don't free good pointers below */
+-
+-      /* update our unionfs_sb_info and root dentry index of last branch */
+-      i = sbmax(sb);          /* save no. of branches to release at end */
+-      sbend(sb) = new_branches - 1;
+-      set_dbend(sb->s_root, new_branches - 1);
+-      old_ibstart = ibstart(sb->s_root->d_inode);
+-      old_ibend = ibend(sb->s_root->d_inode);
+-      ibend(sb->s_root->d_inode) = new_branches - 1;
+-      UNIONFS_D(sb->s_root)->bcount = new_branches;
+-      new_branches = i; /* no. of branches to release below */
+-
+-      /*
+-       * Update lower inodes: 3 steps
+-       * 1. grab ref on all new lower inodes
+-       */
+-      for (i=dbstart(sb->s_root); i<=dbend(sb->s_root); i++) {
+-              struct dentry *lower_dentry =
+-                      unionfs_lower_dentry_idx(sb->s_root, i);
+-              atomic_inc(&lower_dentry->d_inode->i_count);
+-              new_lower_inodes[i] = lower_dentry->d_inode;
+-      }
+-      /* 2. release reference on all older lower inodes */
+-      for (i=old_ibstart; i<=old_ibend; i++) {
+-              iput(unionfs_lower_inode_idx(sb->s_root->d_inode, i));
+-              unionfs_set_lower_inode_idx(sb->s_root->d_inode, i, NULL);
+-      }
+-      kfree(UNIONFS_I(sb->s_root->d_inode)->lower_inodes);
+-      /* 3. update root dentry's inode to new lower_inodes array */
+-      UNIONFS_I(sb->s_root->d_inode)->lower_inodes = new_lower_inodes;
+-      new_lower_inodes = NULL;
+-
+-      /* maxbytes may have changed */
+-      sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
+-      /* update high branch ID */
+-      sbhbid(sb) = new_high_branch_id;
+-
+-      /* update our sb->generation for revalidating objects */
+-      i = atomic_inc_return(&UNIONFS_SB(sb)->generation);
+-      atomic_set(&UNIONFS_D(sb->s_root)->generation, i);
+-      atomic_set(&UNIONFS_I(sb->s_root->d_inode)->generation, i);
+-
+-      err = 0;                /* reset to success */
+-
+-      if (!(*flags & MS_SILENT))
+-              printk("unionfs: new generation number %d\n", i);
+-
+-      /*
+-       * The code above falls through to the next label, and releases the
+-       * refcnts of the older ones (stored in tmp_*): if we fell through
+-       * here, it means success.  However, if we jump directly to this
+-       * label from any error above, then an error occurred after we
+-       * grabbed various refcnts, and so we have to release the
+-       * temporarily constructed structures.
+-       */
+-out_release:
+-      /* no need to cleanup/release anything in tmp_data */
+-      if (tmp_lower_paths)
+-              for (i=0; i<new_branches; i++)
+-                      pathput(&tmp_lower_paths[i]);
+-out_free:
+-      kfree(tmp_lower_paths);
+-      kfree(tmp_data);
+-      kfree(new_lower_paths);
+-      kfree(new_data);
+-      kfree(new_lower_inodes);
+-out_error:
+-      unionfs_write_unlock(sb);
+-      return err;
+-}
+-
+-/*
+- * Called by iput() when the inode reference count reached zero
+- * and the inode is not hashed anywhere.  Used to clear anything
+- * that needs to be, before the inode is completely destroyed and put
+- * on the inode free list.
+- *
+- * No need to lock sb info's rwsem.
+- */
+-static void unionfs_clear_inode(struct inode *inode)
+-{
+-      int bindex, bstart, bend;
+-      struct inode *hidden_inode;
+-      struct list_head *pos, *n;
+-      struct unionfs_dir_state *rdstate;
+-
+-      list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
+-              rdstate = list_entry(pos, struct unionfs_dir_state, cache);
+-              list_del(&rdstate->cache);
+-              free_rdstate(rdstate);
+-      }
+-
+-      /*
+-       * Decrement a reference to a hidden_inode, which was incremented
+-       * by our read_inode when it was created initially.
+-       */
+-      bstart = ibstart(inode);
+-      bend = ibend(inode);
+-      if (bstart >= 0) {
+-              for (bindex = bstart; bindex <= bend; bindex++) {
+-                      hidden_inode = unionfs_lower_inode_idx(inode, bindex);
+-                      if (!hidden_inode)
+-                              continue;
+-                      iput(hidden_inode);
+-              }
+-      }
+-
+-      kfree(UNIONFS_I(inode)->lower_inodes);
+-      UNIONFS_I(inode)->lower_inodes = NULL;
+-}
+-
+-static struct inode *unionfs_alloc_inode(struct super_block *sb)
+-{
+-      struct unionfs_inode_info *i;
+-
+-      i = kmem_cache_alloc(unionfs_inode_cachep, GFP_KERNEL);
+-      if (!i)
+-              return NULL;
+-
+-      /* memset everything up to the inode to 0 */
+-      memset(i, 0, offsetof(struct unionfs_inode_info, vfs_inode));
+-
+-      i->vfs_inode.i_version = 1;
+-      return &i->vfs_inode;
+-}
+-
+-static void unionfs_destroy_inode(struct inode *inode)
+-{
+-      kmem_cache_free(unionfs_inode_cachep, UNIONFS_I(inode));
+-}
+-
+-/* unionfs inode cache constructor */
+-static void init_once(void *v, struct kmem_cache *cachep, unsigned long flags)
+-{
+-      struct unionfs_inode_info *i = v;
+-
+-      inode_init_once(&i->vfs_inode);
+-}
+-
+-int unionfs_init_inode_cache(void)
+-{
+-      int err = 0;
+-
+-      unionfs_inode_cachep =
+-              kmem_cache_create("unionfs_inode_cache",
+-                                sizeof(struct unionfs_inode_info), 0,
+-                                SLAB_RECLAIM_ACCOUNT, init_once, NULL);
+-      if (!unionfs_inode_cachep)
+-              err = -ENOMEM;
+-      return err;
+-}
+-
+-/* unionfs inode cache destructor */
+-void unionfs_destroy_inode_cache(void)
+-{
+-      if (unionfs_inode_cachep)
+-              kmem_cache_destroy(unionfs_inode_cachep);
+-}
+-
+-/*
+- * Called when we have a dirty inode, right here we only throw out
+- * parts of our readdir list that are too old.
+- *
+- * No need to grab sb info's rwsem.
+- */
+-static int unionfs_write_inode(struct inode *inode, int sync)
+-{
+-      struct list_head *pos, *n;
+-      struct unionfs_dir_state *rdstate;
+-
+-      spin_lock(&UNIONFS_I(inode)->rdlock);
+-      list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
+-              rdstate = list_entry(pos, struct unionfs_dir_state, cache);
+-              /* We keep this list in LRU order. */
+-              if ((rdstate->access + RDCACHE_JIFFIES) > jiffies)
+-                      break;
+-              UNIONFS_I(inode)->rdcount--;
+-              list_del(&rdstate->cache);
+-              free_rdstate(rdstate);
+-      }
+-      spin_unlock(&UNIONFS_I(inode)->rdlock);
+-
+-      return 0;
+-}
+-
+-/*
+- * Used only in nfs, to kill any pending RPC tasks, so that subsequent
+- * code can actually succeed and won't leave tasks that need handling.
+- */
+-static void unionfs_umount_begin(struct vfsmount *mnt, int flags)
+-{
+-      struct super_block *sb, *hidden_sb;
+-      struct vfsmount *hidden_mnt;
+-      int bindex, bstart, bend;
+-
+-      if (!(flags & MNT_FORCE))
+-              /*
+-               * we are not being MNT_FORCE'd, therefore we should emulate
+-               * old behavior
+-               */
+-              return;
 -
- /*
-  * Tracks how many cpusets are currently defined in system.
-  * When there is only one cpuset (the root cpuset) we can
-@@ -62,6 +62,10 @@
-  */
- int number_of_cpusets __read_mostly;
-+/* Retrieve the cpuset from a container */
-+struct container_subsys cpuset_subsys;
-+struct cpuset;
-+
- /* See "Frequency meter" comments, below. */
- struct fmeter {
-@@ -72,24 +76,13 @@
- };
- struct cpuset {
-+      struct container_subsys_state css;
-+
-       unsigned long flags;            /* "unsigned long" so bitops work */
-       cpumask_t cpus_allowed;         /* CPUs allowed to tasks in cpuset */
-       nodemask_t mems_allowed;        /* Memory Nodes allowed to tasks */
+-      sb = mnt->mnt_sb;
+-
+-      unionfs_read_lock(sb);
+-
+-      bstart = sbstart(sb);
+-      bend = sbend(sb);
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              hidden_mnt = unionfs_lower_mnt_idx(sb->s_root, bindex);
+-              hidden_sb = unionfs_lower_super_idx(sb, bindex);
+-
+-              if (hidden_mnt && hidden_sb && hidden_sb->s_op &&
+-                  hidden_sb->s_op->umount_begin)
+-                      hidden_sb->s_op->umount_begin(hidden_mnt, flags);
+-      }
+-
+-      unionfs_read_unlock(sb);
+-}
+-
+-static int unionfs_show_options(struct seq_file *m, struct vfsmount *mnt)
+-{
+-      struct super_block *sb = mnt->mnt_sb;
+-      int ret = 0;
+-      char *tmp_page;
+-      char *path;
+-      int bindex, bstart, bend;
+-      int perms;
+-
+-      unionfs_read_lock(sb);
+-
+-      unionfs_lock_dentry(sb->s_root);
+-
+-      tmp_page = (char*) __get_free_page(GFP_KERNEL);
+-      if (!tmp_page) {
+-              ret = -ENOMEM;
+-              goto out;
+-      }
+-
+-      bstart = sbstart(sb);
+-      bend = sbend(sb);
+-
+-      seq_printf(m, ",dirs=");
+-      for (bindex = bstart; bindex <= bend; bindex++) {
+-              path = d_path(unionfs_lower_dentry_idx(sb->s_root, bindex),
+-                            unionfs_lower_mnt_idx(sb->s_root, bindex),
+-                            tmp_page, PAGE_SIZE);
+-              if (IS_ERR(path)) {
+-                      ret = PTR_ERR(path);
+-                      goto out;
+-              }
+-
+-              perms = branchperms(sb, bindex);
+-
+-              seq_printf(m, "%s=%s", path,
+-                         perms & MAY_WRITE ? "rw" : "ro");
+-              if (bindex != bend)
+-                      seq_printf(m, ":");
+-      }
+-
+-out:
+-      free_page((unsigned long) tmp_page);
+-
+-      unionfs_unlock_dentry(sb->s_root);
+-
+-      unionfs_read_unlock(sb);
+-
+-      return ret;
+-}
+-
+-struct super_operations unionfs_sops = {
+-      .read_inode     = unionfs_read_inode,
+-      .delete_inode   = unionfs_delete_inode,
+-      .put_super      = unionfs_put_super,
+-      .statfs         = unionfs_statfs,
+-      .remount_fs     = unionfs_remount_fs,
+-      .clear_inode    = unionfs_clear_inode,
+-      .umount_begin   = unionfs_umount_begin,
+-      .show_options   = unionfs_show_options,
+-      .write_inode    = unionfs_write_inode,
+-      .alloc_inode    = unionfs_alloc_inode,
+-      .destroy_inode  = unionfs_destroy_inode,
+-};
+diff -Nurb linux-2.6.22-590/fs/unionfs/union.h linux-2.6.22-570/fs/unionfs/union.h
+--- linux-2.6.22-590/fs/unionfs/union.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/union.h        1969-12-31 19:00:00.000000000 -0500
+@@ -1,467 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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.
+- */
+-
+-#ifndef _UNION_H_
+-#define _UNION_H_
+-
+-#include <linux/dcache.h>
+-#include <linux/file.h>
+-#include <linux/list.h>
+-#include <linux/fs.h>
+-#include <linux/mm.h>
+-#include <linux/module.h>
+-#include <linux/mount.h>
+-#include <linux/namei.h>
+-#include <linux/page-flags.h>
+-#include <linux/pagemap.h>
+-#include <linux/poll.h>
+-#include <linux/security.h>
+-#include <linux/seq_file.h>
+-#include <linux/slab.h>
+-#include <linux/spinlock.h>
+-#include <linux/smp_lock.h>
+-#include <linux/statfs.h>
+-#include <linux/string.h>
+-#include <linux/vmalloc.h>
+-#include <linux/writeback.h>
+-#include <linux/buffer_head.h>
+-#include <linux/xattr.h>
+-#include <linux/fs_stack.h>
+-#include <linux/magic.h>
+-#include <linux/log2.h>
+-
+-#include <asm/mman.h>
+-#include <asm/system.h>
+-
+-#include <linux/union_fs.h>
+-
+-/* the file system name */
+-#define UNIONFS_NAME "unionfs"
+-
+-/* unionfs root inode number */
+-#define UNIONFS_ROOT_INO     1
+-
+-/* number of times we try to get a unique temporary file name */
+-#define GET_TMPNAM_MAX_RETRY  5
+-
+-/* maximum number of branches we support, to avoid memory blowup */
+-#define UNIONFS_MAX_BRANCHES  128
+-
+-/* Operations vectors defined in specific files. */
+-extern struct file_operations unionfs_main_fops;
+-extern struct file_operations unionfs_dir_fops;
+-extern struct inode_operations unionfs_main_iops;
+-extern struct inode_operations unionfs_dir_iops;
+-extern struct inode_operations unionfs_symlink_iops;
+-extern struct super_operations unionfs_sops;
+-extern struct dentry_operations unionfs_dops;
+-
+-/* How long should an entry be allowed to persist */
+-#define RDCACHE_JIFFIES       (5*HZ)
+-
+-/* file private data. */
+-struct unionfs_file_info {
+-      int bstart;
+-      int bend;
+-      atomic_t generation;
+-
+-      struct unionfs_dir_state *rdstate;
+-      struct file **lower_files;
+-      int *saved_branch_ids; /* IDs of branches when file was opened */
+-};
+-
+-/* unionfs inode data in memory */
+-struct unionfs_inode_info {
+-      int bstart;
+-      int bend;
+-      atomic_t generation;
+-      int stale;
+-      /* Stuff for readdir over NFS. */
+-      spinlock_t rdlock;
+-      struct list_head readdircache;
+-      int rdcount;
+-      int hashsize;
+-      int cookie;
+-
+-      /* The hidden inodes */
+-      struct inode **lower_inodes;
+-      /* to keep track of reads/writes for unlinks before closes */
+-      atomic_t totalopens;
+-
+-      struct inode vfs_inode;
+-};
+-
+-/* unionfs dentry data in memory */
+-struct unionfs_dentry_info {
 -      /*
--       * Count is atomic so can incr (fork) or decr (exit) without a lock.
+-       * The semaphore is used to lock the dentry as soon as we get into a
+-       * unionfs function from the VFS.  Our lock ordering is that children
+-       * go before their parents.
 -       */
--      atomic_t count;                 /* count tasks using this cpuset */
+-      struct mutex lock;
+-      int bstart;
+-      int bend;
+-      int bopaque;
+-      int bcount;
+-      atomic_t generation;
+-      struct path *lower_paths;
+-};
+-
+-/* These are the pointers to our various objects. */
+-struct unionfs_data {
+-      struct super_block *sb;
+-      atomic_t open_files;    /* number of open files on branch */
+-      int branchperms;
+-      int branch_id;          /* unique branch ID at re/mount time */
+-};
+-
+-/* unionfs super-block data in memory */
+-struct unionfs_sb_info {
+-      int bend;
+-
+-      atomic_t generation;
 -
 -      /*
--       * We link our 'sibling' struct into our parents 'children'.
--       * Our children link their 'sibling' into our 'children'.
+-       * This rwsem is used to make sure that a branch management
+-       * operation...
+-       *   1) will not begin before all currently in-flight operations
+-       *      complete
+-       *   2) any new operations do not execute until the currently
+-       *      running branch management operation completes
 -       */
--      struct list_head sibling;       /* my parents children */
--      struct list_head children;      /* my children */
+-      struct rw_semaphore rwsem;
+-      int high_branch_id;     /* last unique branch ID given */
+-      struct unionfs_data *data;
+-};
 -
-       struct cpuset *parent;          /* my parent */
--      struct dentry *dentry;          /* cpuset fs entry */
-       /*
-        * Copy of global cpuset_mems_generation as of the most
-@@ -100,13 +93,32 @@
-       struct fmeter fmeter;           /* memory_pressure filter */
- };
-+/* Update the cpuset for a container */
-+static inline void set_container_cs(struct container *cont, struct cpuset *cs)
-+{
-+      cont->subsys[cpuset_subsys_id] = &cs->css;
-+}
-+
-+/* Retrieve the cpuset for a container */
-+static inline struct cpuset *container_cs(struct container *cont)
-+{
-+      return container_of(container_subsys_state(cont, cpuset_subsys_id),
-+                          struct cpuset, css);
-+}
-+
-+/* Retrieve the cpuset for a task */
-+static inline struct cpuset *task_cs(struct task_struct *task)
-+{
-+      return container_of(task_subsys_state(task, cpuset_subsys_id),
-+                          struct cpuset, css);
-+}
-+
-+
- /* bits in struct cpuset flags field */
- typedef enum {
-       CS_CPU_EXCLUSIVE,
-       CS_MEM_EXCLUSIVE,
-       CS_MEMORY_MIGRATE,
--      CS_REMOVED,
--      CS_NOTIFY_ON_RELEASE,
-       CS_SPREAD_PAGE,
-       CS_SPREAD_SLAB,
- } cpuset_flagbits_t;
-@@ -122,16 +134,6 @@
-       return test_bit(CS_MEM_EXCLUSIVE, &cs->flags);
- }
--static inline int is_removed(const struct cpuset *cs)
+-/*
+- * structure for making the linked list of entries by readdir on left branch
+- * to compare with entries on right branch
+- */
+-struct filldir_node {
+-      struct list_head file_list;     /* list for directory entries */
+-      char *name;             /* name entry */
+-      int hash;               /* name hash */
+-      int namelen;            /* name len since name is not 0 terminated */
+-
+-      /*
+-       * we can check for duplicate whiteouts and files in the same branch
+-       * in order to return -EIO.
+-       */
+-      int bindex;
+-
+-      /* is this a whiteout entry? */
+-      int whiteout;
+-
+-      /* Inline name, so we don't need to separately kmalloc small ones */
+-      char iname[DNAME_INLINE_LEN_MIN];
+-};
+-
+-/* Directory hash table. */
+-struct unionfs_dir_state {
+-      unsigned int cookie;    /* the cookie, based off of rdversion */
+-      unsigned int offset;    /* The entry we have returned. */
+-      int bindex;
+-      loff_t dirpos;          /* offset within the lower level directory */
+-      int size;               /* How big is the hash table? */
+-      int hashentries;        /* How many entries have been inserted? */
+-      unsigned long access;
+-
+-      /* This cache list is used when the inode keeps us around. */
+-      struct list_head cache;
+-      struct list_head list[0];
+-};
+-
+-/* include miscellaneous macros */
+-#include "fanout.h"
+-#include "sioq.h"
+-
+-/* externs for cache creation/deletion routines */
+-extern void unionfs_destroy_filldir_cache(void);
+-extern int unionfs_init_filldir_cache(void);
+-extern int unionfs_init_inode_cache(void);
+-extern void unionfs_destroy_inode_cache(void);
+-extern int unionfs_init_dentry_cache(void);
+-extern void unionfs_destroy_dentry_cache(void);
+-
+-/* Initialize and free readdir-specific  state. */
+-extern int init_rdstate(struct file *file);
+-extern struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex);
+-extern struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos);
+-extern void free_rdstate(struct unionfs_dir_state *state);
+-extern int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name,
+-                          int namelen, int bindex, int whiteout);
+-extern struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
+-                                            const char *name, int namelen);
+-
+-extern struct dentry **alloc_new_dentries(int objs);
+-extern struct unionfs_data *alloc_new_data(int objs);
+-
+-/* We can only use 32-bits of offset for rdstate --- blech! */
+-#define DIREOF (0xfffff)
+-#define RDOFFBITS 20          /* This is the number of bits in DIREOF. */
+-#define MAXRDCOOKIE (0xfff)
+-/* Turn an rdstate into an offset. */
+-static inline off_t rdstate2offset(struct unionfs_dir_state *buf)
+-{
+-      off_t tmp;
+-
+-      tmp = ((buf->cookie & MAXRDCOOKIE) << RDOFFBITS)
+-              | (buf->offset & DIREOF);
+-      return tmp;
+-}
+-
+-#define unionfs_read_lock(sb)  down_read(&UNIONFS_SB(sb)->rwsem)
+-#define unionfs_read_unlock(sb)        up_read(&UNIONFS_SB(sb)->rwsem)
+-#define unionfs_write_lock(sb)         down_write(&UNIONFS_SB(sb)->rwsem)
+-#define unionfs_write_unlock(sb) up_write(&UNIONFS_SB(sb)->rwsem)
+-
+-static inline void unionfs_double_lock_dentry(struct dentry *d1,
+-                                            struct dentry *d2)
+-{
+-      if (d2 < d1) {
+-              struct dentry *tmp = d1;
+-              d1 = d2;
+-              d2 = tmp;
+-      }
+-      unionfs_lock_dentry(d1);
+-      unionfs_lock_dentry(d2);
+-}
+-
+-extern int realloc_dentry_private_data(struct dentry *dentry);
+-extern int new_dentry_private_data(struct dentry *dentry);
+-extern void free_dentry_private_data(struct dentry *dentry);
+-extern void update_bstart(struct dentry *dentry);
+-
+-/*
+- * EXTERNALS:
+- */
+-
+-/* replicates the directory structure up to given dentry in given branch */
+-extern struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
+-                                   int bindex);
+-extern int make_dir_opaque(struct dentry *dir, int bindex);
+-
+-/* partial lookup */
+-extern int unionfs_partial_lookup(struct dentry *dentry);
+-
+-/*
+- * Pass an unionfs dentry and an index and it will try to create a whiteout
+- * in branch 'index'.
+- *
+- * On error, it will proceed to a branch to the left
+- */
+-extern int create_whiteout(struct dentry *dentry, int start);
+-/* copies a file from dbstart to newbindex branch */
+-extern int copyup_file(struct inode *dir, struct file *file, int bstart,
+-                     int newbindex, loff_t size);
+-extern int copyup_named_file(struct inode *dir, struct file *file,
+-                           char *name, int bstart, int new_bindex,
+-                           loff_t len);
+-/* copies a dentry from dbstart to newbindex branch */
+-extern int copyup_dentry(struct inode *dir, struct dentry *dentry, int bstart,
+-                       int new_bindex, struct file **copyup_file,
+-                       loff_t len);
+-
+-extern int remove_whiteouts(struct dentry *dentry,
+-                          struct dentry *hidden_dentry, int bindex);
+-
+-extern int do_delete_whiteouts(struct dentry *dentry, int bindex,
+-                             struct unionfs_dir_state *namelist);
+-
+-extern int unionfs_get_nlinks(struct inode *inode);
+-
+-/* Is this directory empty: 0 if it is empty, -ENOTEMPTY if not. */
+-extern int check_empty(struct dentry *dentry,
+-                     struct unionfs_dir_state **namelist);
+-/* Delete whiteouts from this directory in branch bindex. */
+-extern int delete_whiteouts(struct dentry *dentry, int bindex,
+-                          struct unionfs_dir_state *namelist);
+-
+-/* Re-lookup a hidden dentry. */
+-extern int unionfs_refresh_hidden_dentry(struct dentry *dentry, int bindex);
+-
+-extern void unionfs_reinterpose(struct dentry *this_dentry);
+-extern struct super_block *unionfs_duplicate_super(struct super_block *sb);
+-
+-/* Locking functions. */
+-extern int unionfs_setlk(struct file *file, int cmd, struct file_lock *fl);
+-extern int unionfs_getlk(struct file *file, struct file_lock *fl);
+-
+-/* Common file operations. */
+-extern int unionfs_file_revalidate(struct file *file, int willwrite);
+-extern int unionfs_open(struct inode *inode, struct file *file);
+-extern int unionfs_file_release(struct inode *inode, struct file *file);
+-extern int unionfs_flush(struct file *file, fl_owner_t id);
+-extern long unionfs_ioctl(struct file *file, unsigned int cmd,
+-                        unsigned long arg);
+-
+-/* Inode operations */
+-extern int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+-                        struct inode *new_dir, struct dentry *new_dentry);
+-extern int unionfs_unlink(struct inode *dir, struct dentry *dentry);
+-extern int unionfs_rmdir(struct inode *dir, struct dentry *dentry);
+-
+-extern int __unionfs_d_revalidate_chain(struct dentry *dentry,
+-                                      struct nameidata *nd);
+-
+-/* The values for unionfs_interpose's flag. */
+-#define INTERPOSE_DEFAULT     0
+-#define INTERPOSE_LOOKUP      1
+-#define INTERPOSE_REVAL               2
+-#define INTERPOSE_REVAL_NEG   3
+-#define INTERPOSE_PARTIAL     4
+-
+-extern int unionfs_interpose(struct dentry *this_dentry,
+-                           struct super_block *sb, int flag);
+-
+-#ifdef CONFIG_UNION_FS_XATTR
+-/* Extended attribute functions. */
+-extern void *unionfs_xattr_alloc(size_t size, size_t limit);
+-extern void unionfs_xattr_free(void *ptr, size_t size);
+-
+-extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name,
+-                              void *value, size_t size);
+-extern int unionfs_removexattr(struct dentry *dentry, const char *name);
+-extern ssize_t unionfs_listxattr(struct dentry *dentry, char *list,
+-                               size_t size);
+-extern int unionfs_setxattr(struct dentry *dentry, const char *name,
+-                          const void *value, size_t size, int flags);
+-#endif /* CONFIG_UNION_FS_XATTR */
+-
+-/* The root directory is unhashed, but isn't deleted. */
+-static inline int d_deleted(struct dentry *d)
 -{
--      return test_bit(CS_REMOVED, &cs->flags);
+-      return d_unhashed(d) && (d != d->d_sb->s_root);
 -}
 -
--static inline int notify_on_release(const struct cpuset *cs)
+-struct dentry *unionfs_lookup_backend(struct dentry *dentry,
+-                                    struct nameidata *nd, int lookupmode);
+-
+-/* unionfs_permission, check if we should bypass error to facilitate copyup */
+-#define IS_COPYUP_ERR(err) ((err) == -EROFS)
+-
+-/* unionfs_open, check if we need to copyup the file */
+-#define OPEN_WRITE_FLAGS (O_WRONLY | O_RDWR | O_APPEND)
+-#define IS_WRITE_FLAG(flag) ((flag) & OPEN_WRITE_FLAGS)
+-
+-static inline int branchperms(const struct super_block *sb, int index)
 -{
--      return test_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
+-      BUG_ON(index < 0);
+-
+-      return UNIONFS_SB(sb)->data[index].branchperms;
 -}
 -
- static inline int is_memory_migrate(const struct cpuset *cs)
+-static inline int set_branchperms(struct super_block *sb, int index, int perms)
+-{
+-      BUG_ON(index < 0);
+-
+-      UNIONFS_SB(sb)->data[index].branchperms = perms;
+-
+-      return perms;
+-}
+-
+-/* Is this file on a read-only branch? */
+-static inline int is_robranch_super(const struct super_block *sb, int index)
+-{
+-      int ret;
+-
+-      ret = (!(branchperms(sb, index) & MAY_WRITE)) ? -EROFS : 0;
+-      return ret;
+-}
+-
+-/* Is this file on a read-only branch? */
+-static inline int is_robranch_idx(const struct dentry *dentry, int index)
+-{
+-      int err = 0;
+-
+-      BUG_ON(index < 0);
+-
+-      if ((!(branchperms(dentry->d_sb, index) & MAY_WRITE)) ||
+-          IS_RDONLY(unionfs_lower_dentry_idx(dentry, index)->d_inode))
+-              err = -EROFS;
+-      return err;
+-}
+-
+-static inline int is_robranch(const struct dentry *dentry)
+-{
+-      int index;
+-
+-      index = UNIONFS_D(dentry)->bstart;
+-      BUG_ON(index < 0);
+-
+-      return is_robranch_idx(dentry, index);
+-}
+-
+-/* What do we use for whiteouts. */
+-#define UNIONFS_WHPFX ".wh."
+-#define UNIONFS_WHLEN 4
+-/*
+- * If a directory contains this file, then it is opaque.  We start with the
+- * .wh. flag so that it is blocked by lookup.
+- */
+-#define UNIONFS_DIR_OPAQUE_NAME "__dir_opaque"
+-#define UNIONFS_DIR_OPAQUE UNIONFS_WHPFX UNIONFS_DIR_OPAQUE_NAME
+-
+-#ifndef DEFAULT_POLLMASK
+-#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
+-#endif
+-
+-/*
+- * EXTERNALS:
+- */
+-extern char *alloc_whname(const char *name, int len);
+-extern int check_branch(struct nameidata *nd);
+-extern int __parse_branch_mode(const char *name);
+-extern int parse_branch_mode(const char *name);
+-
+-/*
+- * These two functions are here because it is kind of daft to copy and paste
+- * the contents of the two functions to 32+ places in unionfs
+- */
+-static inline struct dentry *lock_parent(struct dentry *dentry)
+-{
+-      struct dentry *dir = dget(dentry->d_parent);
+-
+-      mutex_lock(&dir->d_inode->i_mutex);
+-      return dir;
+-}
+-
+-static inline void unlock_dir(struct dentry *dir)
+-{
+-      mutex_unlock(&dir->d_inode->i_mutex);
+-      dput(dir);
+-}
+-
+-static inline struct vfsmount *unionfs_mntget(struct dentry *dentry,
+-                                            int bindex)
+-{
+-      BUG_ON(!dentry || bindex < 0);
+-
+-      return mntget(unionfs_lower_mnt_idx(dentry, bindex));
+-}
+-
+-static inline void unionfs_mntput(struct dentry *dentry, int bindex)
+-{
+-      if (!dentry)
+-              return;
+-
+-      BUG_ON(bindex < 0);
+-
+-      mntput(unionfs_lower_mnt_idx(dentry, bindex));
+-}
+-#endif        /* not _UNION_H_ */
+diff -Nurb linux-2.6.22-590/fs/unionfs/unlink.c linux-2.6.22-570/fs/unionfs/unlink.c
+--- linux-2.6.22-590/fs/unionfs/unlink.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/unlink.c       1969-12-31 19:00:00.000000000 -0500
+@@ -1,176 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/* unlink a file by creating a whiteout */
+-static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry)
+-{
+-      struct dentry *hidden_dentry;
+-      struct dentry *hidden_dir_dentry;
+-      int bindex;
+-      int err = 0;
+-
+-      if ((err = unionfs_partial_lookup(dentry)))
+-              goto out;
+-
+-      bindex = dbstart(dentry);
+-
+-      hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+-      if (!hidden_dentry)
+-              goto out;
+-
+-      hidden_dir_dentry = lock_parent(hidden_dentry);
+-
+-      /* avoid destroying the hidden inode if the file is in use */
+-      dget(hidden_dentry);
+-      if (!(err = is_robranch_super(dentry->d_sb, bindex)))
+-              err = vfs_unlink(hidden_dir_dentry->d_inode, hidden_dentry);
+-      dput(hidden_dentry);
+-      fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
+-      unlock_dir(hidden_dir_dentry);
+-
+-      if (err && !IS_COPYUP_ERR(err))
+-              goto out;
+-
+-      if (err) {
+-              if (dbstart(dentry) == 0)
+-                      goto out;
+-
+-              err = create_whiteout(dentry, dbstart(dentry) - 1);
+-      } else if (dbopaque(dentry) != -1)
+-              /* There is a hidden lower-priority file with the same name. */
+-              err = create_whiteout(dentry, dbopaque(dentry));
+-      else
+-              err = create_whiteout(dentry, dbstart(dentry));
+-
+-out:
+-      if (!err)
+-              dentry->d_inode->i_nlink--;
+-
+-      /* We don't want to leave negative leftover dentries for revalidate. */
+-      if (!err && (dbopaque(dentry) != -1))
+-              update_bstart(dentry);
+-
+-      return err;
+-}
+-
+-int unionfs_unlink(struct inode *dir, struct dentry *dentry)
+-{
+-      int err = 0;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      err = unionfs_unlink_whiteout(dir, dentry);
+-      /* call d_drop so the system "forgets" about us */
+-      if (!err)
+-              d_drop(dentry);
+-
+-out:
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(dentry->d_sb);
+-      return err;
+-}
+-
+-static int unionfs_rmdir_first(struct inode *dir, struct dentry *dentry,
+-                             struct unionfs_dir_state *namelist)
+-{
+-      int err;
+-      struct dentry *hidden_dentry;
+-      struct dentry *hidden_dir_dentry = NULL;
+-
+-      /* Here we need to remove whiteout entries. */
+-      err = delete_whiteouts(dentry, dbstart(dentry), namelist);
+-      if (err)
+-              goto out;
+-
+-      hidden_dentry = unionfs_lower_dentry(dentry);
+-
+-      hidden_dir_dentry = lock_parent(hidden_dentry);
+-
+-      /* avoid destroying the hidden inode if the file is in use */
+-      dget(hidden_dentry);
+-      if (!(err = is_robranch(dentry)))
+-              err = vfs_rmdir(hidden_dir_dentry->d_inode, hidden_dentry);
+-      dput(hidden_dentry);
+-
+-      fsstack_copy_attr_times(dir, hidden_dir_dentry->d_inode);
+-      /* propagate number of hard-links */
+-      dentry->d_inode->i_nlink = unionfs_get_nlinks(dentry->d_inode);
+-
+-out:
+-      if (hidden_dir_dentry)
+-              unlock_dir(hidden_dir_dentry);
+-      return err;
+-}
+-
+-int unionfs_rmdir(struct inode *dir, struct dentry *dentry)
+-{
+-      int err = 0;
+-      struct unionfs_dir_state *namelist = NULL;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      /* check if this unionfs directory is empty or not */
+-      err = check_empty(dentry, &namelist);
+-      if (err)
+-              goto out;
+-
+-      err = unionfs_rmdir_first(dir, dentry, namelist);
+-      /* create whiteout */
+-      if (!err)
+-              err = create_whiteout(dentry, dbstart(dentry));
+-      else {
+-              int new_err;
+-
+-              if (dbstart(dentry) == 0)
+-                      goto out;
+-
+-              /* exit if the error returned was NOT -EROFS */
+-              if (!IS_COPYUP_ERR(err))
+-                      goto out;
+-
+-              new_err = create_whiteout(dentry, dbstart(dentry) - 1);
+-              if (new_err != -EEXIST)
+-                      err = new_err;
+-      }
+-
+-out:
+-      /* call d_drop so the system "forgets" about us */
+-      if (!err)
+-              d_drop(dentry);
+-
+-      if (namelist)
+-              free_rdstate(namelist);
+-
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(dentry->d_sb);
+-      return err;
+-}
+diff -Nurb linux-2.6.22-590/fs/unionfs/xattr.c linux-2.6.22-570/fs/unionfs/xattr.c
+--- linux-2.6.22-590/fs/unionfs/xattr.c        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/unionfs/xattr.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,161 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2003-2006 Charles P. Wright
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2005-2006 Junjiro Okajima
+- * Copyright (c) 2005      Arun M. Krishnakumar
+- * Copyright (c) 2004-2006 David P. Quigley
+- * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
+- * Copyright (c) 2003      Puja Gupta
+- * Copyright (c) 2003      Harikesavan Krishnan
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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 "union.h"
+-
+-/* This is lifted from fs/xattr.c */
+-void *unionfs_xattr_alloc(size_t size, size_t limit)
+-{
+-      void *ptr;
+-
+-      if (size > limit)
+-              return ERR_PTR(-E2BIG);
+-
+-      if (!size)              /* size request, no buffer is needed */
+-              return NULL;
+-      else if (size <= PAGE_SIZE)
+-              ptr = kmalloc(size, GFP_KERNEL);
+-      else
+-              ptr = vmalloc(size);
+-      if (!ptr)
+-              return ERR_PTR(-ENOMEM);
+-      return ptr;
+-}
+-
+-void unionfs_xattr_free(void *ptr, size_t size)
+-{
+-      if (!size)              /* size request, no buffer was needed */
+-              return;
+-      else if (size <= PAGE_SIZE)
+-              kfree(ptr);
+-      else
+-              vfree(ptr);
+-}
+-
+-/*
+- * BKL held by caller.
+- * dentry->d_inode->i_mutex locked
+- */
+-ssize_t unionfs_getxattr(struct dentry *dentry, const char *name, void *value,
+-                       size_t size)
+-{
+-      struct dentry *hidden_dentry = NULL;
+-      int err = -EOPNOTSUPP;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      hidden_dentry = unionfs_lower_dentry(dentry);
+-
+-      err = vfs_getxattr(hidden_dentry, (char*) name, value, size);
+-
+-out:
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(dentry->d_sb);
+-      return err;
+-}
+-
+-/*
+- * BKL held by caller.
+- * dentry->d_inode->i_mutex locked
+- */
+-int unionfs_setxattr(struct dentry *dentry, const char *name,
+-                   const void *value, size_t size, int flags)
+-{
+-      struct dentry *hidden_dentry = NULL;
+-      int err = -EOPNOTSUPP;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      hidden_dentry = unionfs_lower_dentry(dentry);
+-
+-      err = vfs_setxattr(hidden_dentry, (char*) name, (void*) value,
+-                         size, flags);
+-
+-out:
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(dentry->d_sb);
+-      return err;
+-}
+-
+-/*
+- * BKL held by caller.
+- * dentry->d_inode->i_mutex locked
+- */
+-int unionfs_removexattr(struct dentry *dentry, const char *name)
+-{
+-      struct dentry *hidden_dentry = NULL;
+-      int err = -EOPNOTSUPP;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      hidden_dentry = unionfs_lower_dentry(dentry);
+-
+-      err = vfs_removexattr(hidden_dentry, (char*) name);
+-
+-out:
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(dentry->d_sb);
+-      return err;
+-}
+-
+-/*
+- * BKL held by caller.
+- * dentry->d_inode->i_mutex locked
+- */
+-ssize_t unionfs_listxattr(struct dentry *dentry, char *list, size_t size)
+-{
+-      struct dentry *hidden_dentry = NULL;
+-      int err = -EOPNOTSUPP;
+-      char *encoded_list = NULL;
+-
+-      unionfs_read_lock(dentry->d_sb);
+-      unionfs_lock_dentry(dentry);
+-
+-      if (!__unionfs_d_revalidate_chain(dentry, NULL)) {
+-              err = -ESTALE;
+-              goto out;
+-      }
+-
+-      hidden_dentry = unionfs_lower_dentry(dentry);
+-
+-      encoded_list = list;
+-      err = vfs_listxattr(hidden_dentry, encoded_list, size);
+-
+-out:
+-      unionfs_unlock_dentry(dentry);
+-      unionfs_read_unlock(dentry->d_sb);
+-      return err;
+-}
+diff -Nurb linux-2.6.22-590/fs/xfs/linux-2.6/xfs_file.c linux-2.6.22-570/fs/xfs/linux-2.6/xfs_file.c
+--- linux-2.6.22-590/fs/xfs/linux-2.6/xfs_file.c       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/xfs/linux-2.6/xfs_file.c       2007-07-08 19:32:17.000000000 -0400
+@@ -246,19 +246,18 @@
+ #ifdef CONFIG_XFS_DMAPI
+ STATIC struct page *
+-xfs_vm_fault(
+-      struct vm_area_struct   *vma,
+-      struct fault_data       *fdata)
++xfs_vm_nopage(
++      struct vm_area_struct   *area,
++      unsigned long           address,
++      int                     *type)
+ {
+-      struct inode    *inode = vma->vm_file->f_path.dentry->d_inode;
++      struct inode    *inode = area->vm_file->f_path.dentry->d_inode;
+       bhv_vnode_t     *vp = vn_from_inode(inode);
+       ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
+-      if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), vma, 0)) {
+-              fdata->type = VM_FAULT_SIGBUS;
++      if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), area, 0))
+               return NULL;
+-      }
+-      return filemap_fault(vma, fdata);
++      return filemap_nopage(area, address, type);
+ }
+ #endif /* CONFIG_XFS_DMAPI */
+@@ -344,7 +343,6 @@
+       struct vm_area_struct *vma)
  {
-       return test_bit(CS_MEMORY_MIGRATE, &cs->flags);
-@@ -172,14 +174,8 @@
-       .flags = ((1 << CS_CPU_EXCLUSIVE) | (1 << CS_MEM_EXCLUSIVE)),
-       .cpus_allowed = CPU_MASK_ALL,
-       .mems_allowed = NODE_MASK_ALL,
--      .count = ATOMIC_INIT(0),
--      .sibling = LIST_HEAD_INIT(top_cpuset.sibling),
--      .children = LIST_HEAD_INIT(top_cpuset.children),
+       vma->vm_ops = &xfs_file_vm_ops;
+-      vma->vm_flags |= VM_CAN_INVALIDATE | VM_CAN_NONLINEAR;
+ #ifdef CONFIG_XFS_DMAPI
+       if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
+@@ -503,12 +501,14 @@
+ };
+ static struct vm_operations_struct xfs_file_vm_ops = {
+-      .fault          = filemap_fault,
++      .nopage         = filemap_nopage,
++      .populate       = filemap_populate,
  };
  
--static struct vfsmount *cpuset_mount;
--static struct super_block *cpuset_sb;
+ #ifdef CONFIG_XFS_DMAPI
+ static struct vm_operations_struct xfs_dmapi_file_vm_ops = {
+-      .fault          = xfs_vm_fault,
++      .nopage         = xfs_vm_nopage,
++      .populate       = filemap_populate,
+ #ifdef HAVE_VMOP_MPROTECT
+       .mprotect       = xfs_vm_mprotect,
+ #endif
+diff -Nurb linux-2.6.22-590/fs/xfs/linux-2.6/xfs_super.c linux-2.6.22-570/fs/xfs/linux-2.6/xfs_super.c
+--- linux-2.6.22-590/fs/xfs/linux-2.6/xfs_super.c      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/fs/xfs/linux-2.6/xfs_super.c      2008-01-23 19:16:04.000000000 -0500
+@@ -570,7 +570,6 @@
+       bhv_vfs_sync_work_t     *work, *n;
+       LIST_HEAD               (tmp);
+-      set_freezable();
+       timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
+       for (;;) {
+               timeleft = schedule_timeout_interruptible(timeleft);
+diff -Nurb linux-2.6.22-590/include/acpi/acmacros.h linux-2.6.22-570/include/acpi/acmacros.h
+--- linux-2.6.22-590/include/acpi/acmacros.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/acpi/acmacros.h   2007-07-08 19:32:17.000000000 -0400
+@@ -486,8 +486,6 @@
+ #define ACPI_FUNCTION_NAME(name)
+ #endif
+-#ifdef DEBUG_FUNC_TRACE
+-
+ #define ACPI_FUNCTION_TRACE(a)          ACPI_FUNCTION_NAME(a) \
+                         acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
+ #define ACPI_FUNCTION_TRACE_PTR(a,b)    ACPI_FUNCTION_NAME(a) \
+@@ -565,27 +563,6 @@
+ #endif                                /* ACPI_SIMPLE_RETURN_MACROS */
+-#else /* !DEBUG_FUNC_TRACE */
+-
+-#define ACPI_FUNCTION_TRACE(a)
+-#define ACPI_FUNCTION_TRACE_PTR(a,b)
+-#define ACPI_FUNCTION_TRACE_U32(a,b)
+-#define ACPI_FUNCTION_TRACE_STR(a,b)
+-#define ACPI_FUNCTION_EXIT
+-#define ACPI_FUNCTION_STATUS_EXIT(s)
+-#define ACPI_FUNCTION_VALUE_EXIT(s)
+-#define ACPI_FUNCTION_TRACE(a)
+-#define ACPI_FUNCTION_ENTRY()
+-
+-#define return_VOID                     return
+-#define return_ACPI_STATUS(s)           return(s)
+-#define return_VALUE(s)                 return(s)
+-#define return_UINT8(s)                 return(s)
+-#define return_UINT32(s)                return(s)
+-#define return_PTR(s)                   return(s)
+-
+-#endif /* DEBUG_FUNC_TRACE */
+-
+ /* Conditional execution */
+ #define ACPI_DEBUG_EXEC(a)              a
+diff -Nurb linux-2.6.22-590/include/acpi/acoutput.h linux-2.6.22-570/include/acpi/acoutput.h
+--- linux-2.6.22-590/include/acpi/acoutput.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/acpi/acoutput.h   2007-07-08 19:32:17.000000000 -0400
+@@ -178,8 +178,8 @@
+ /* Defaults for debug_level, debug and normal */
+-#define ACPI_DEBUG_DEFAULT          (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR)
+-#define ACPI_NORMAL_DEFAULT         (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR)
++#define ACPI_DEBUG_DEFAULT          (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR | ACPI_LV_DEBUG_OBJECT)
++#define ACPI_NORMAL_DEFAULT         (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR | ACPI_LV_DEBUG_OBJECT)
+ #define ACPI_DEBUG_ALL              (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL)
+ #endif                                /* __ACOUTPUT_H__ */
+diff -Nurb linux-2.6.22-590/include/acpi/platform/acenv.h linux-2.6.22-570/include/acpi/platform/acenv.h
+--- linux-2.6.22-590/include/acpi/platform/acenv.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/acpi/platform/acenv.h     2007-07-08 19:32:17.000000000 -0400
+@@ -136,7 +136,7 @@
+ /*! [Begin] no source code translation */
+-#if defined(_LINUX) || defined(__linux__)
++#if defined(__linux__)
+ #include "aclinux.h"
+ #elif defined(_AED_EFI)
+diff -Nurb linux-2.6.22-590/include/acpi/platform/aclinux.h linux-2.6.22-570/include/acpi/platform/aclinux.h
+--- linux-2.6.22-590/include/acpi/platform/aclinux.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/acpi/platform/aclinux.h   2007-07-08 19:32:17.000000000 -0400
+@@ -91,10 +91,7 @@
+ #define ACPI_USE_NATIVE_DIVIDE
+ #endif
+-#ifndef __cdecl
+ #define __cdecl
+-#endif
 -
+ #define ACPI_FLUSH_CPU_CACHE()
+ #endif                                /* __KERNEL__ */
+diff -Nurb linux-2.6.22-590/include/acpi/processor.h linux-2.6.22-570/include/acpi/processor.h
+--- linux-2.6.22-590/include/acpi/processor.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/acpi/processor.h  2008-01-23 19:15:56.000000000 -0500
+@@ -21,8 +21,6 @@
+ #define ACPI_PSD_REV0_REVISION                0       /* Support for _PSD as in ACPI 3.0 */
+ #define ACPI_PSD_REV0_ENTRIES         5
+-#define ACPI_TSD_REV0_REVISION                0       /* Support for _PSD as in ACPI 3.0 */
+-#define ACPI_TSD_REV0_ENTRIES         5
  /*
-  * We have two global cpuset mutexes below.  They can nest.
-  * It is ok to first take manage_mutex, then nest callback_mutex.  We also
-@@ -263,297 +259,36 @@
-  * the routine cpuset_update_task_memory_state().
-  */
+  * Types of coordination defined in ACPI 3.0. Same macros can be used across
+  * P, C and T states
+@@ -127,53 +125,17 @@
+ /* Throttling Control */
+-struct acpi_tsd_package {
+-      acpi_integer num_entries;
+-      acpi_integer revision;
+-      acpi_integer domain;
+-      acpi_integer coord_type;
+-      acpi_integer num_processors;
+-} __attribute__ ((packed));
+-
+-struct acpi_ptc_register {
+-      u8 descriptor;
+-      u16 length;
+-      u8 space_id;
+-      u8 bit_width;
+-      u8 bit_offset;
+-      u8 reserved;
+-      u64 address;
+-} __attribute__ ((packed));
+-
+-struct acpi_processor_tx_tss {
+-      acpi_integer freqpercentage;    /* */
+-      acpi_integer power;     /* milliWatts */
+-      acpi_integer transition_latency;        /* microseconds */
+-      acpi_integer control;   /* control value */
+-      acpi_integer status;    /* success indicator */
+-};
+ struct acpi_processor_tx {
+       u16 power;
+       u16 performance;
+ };
+-struct acpi_processor;
+ struct acpi_processor_throttling {
+-      unsigned int state;
+-      unsigned int platform_limit;
+-      struct acpi_pct_register control_register;
+-      struct acpi_pct_register status_register;
+-      unsigned int state_count;
+-      struct acpi_processor_tx_tss *states_tss;
+-      struct acpi_tsd_package domain_info;
+-      cpumask_t shared_cpu_map;
+-      int (*acpi_processor_get_throttling) (struct acpi_processor * pr);
+-      int (*acpi_processor_set_throttling) (struct acpi_processor * pr,
+-                                            int state);
+-
++      int state;
+       u32 address;
+       u8 duty_offset;
+       u8 duty_width;
++      int state_count;
+       struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING];
+ };
+@@ -199,7 +161,6 @@
+       u8 bm_check:1;
+       u8 has_cst:1;
+       u8 power_setup_done:1;
+-      u8 bm_rld_set:1;
+ };
+ struct acpi_processor {
+@@ -208,9 +169,6 @@
+       u32 id;
+       u32 pblk;
+       int performance_platform_limit;
+-      int throttling_platform_limit;
+-      /* 0 - states 0..n-th state available */
+-
+       struct acpi_processor_flags flags;
+       struct acpi_processor_power power;
+       struct acpi_processor_performance *performance;
+@@ -312,7 +270,7 @@
+ /* in processor_throttling.c */
+ int acpi_processor_get_throttling_info(struct acpi_processor *pr);
+-extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
++int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
+ extern struct file_operations acpi_processor_throttling_fops;
+ /* in processor_idle.c */
+@@ -321,9 +279,6 @@
+ int acpi_processor_cst_has_changed(struct acpi_processor *pr);
+ int acpi_processor_power_exit(struct acpi_processor *pr,
+                             struct acpi_device *device);
+-
+-extern struct cpuidle_driver acpi_idle_driver;
+-void acpi_max_cstate_changed(void);
+ int acpi_processor_suspend(struct acpi_device * device, pm_message_t state);
+ int acpi_processor_resume(struct acpi_device * device);
+diff -Nurb linux-2.6.22-590/include/asm-alpha/page.h linux-2.6.22-570/include/asm-alpha/page.h
+--- linux-2.6.22-590/include/asm-alpha/page.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-alpha/page.h  2007-07-08 19:32:17.000000000 -0400
+@@ -17,8 +17,7 @@
+ extern void clear_page(void *page);
+ #define clear_user_page(page, vaddr, pg)      clear_page(page)
  
--static DEFINE_MUTEX(manage_mutex);
- static DEFINE_MUTEX(callback_mutex);
+-#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+-      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vmaddr)
++#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vmaddr)
+ #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
  
+ extern void copy_page(void * _to, void * _from);
+diff -Nurb linux-2.6.22-590/include/asm-arm/arch-iop13xx/adma.h linux-2.6.22-570/include/asm-arm/arch-iop13xx/adma.h
+--- linux-2.6.22-590/include/asm-arm/arch-iop13xx/adma.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-arm/arch-iop13xx/adma.h       1969-12-31 19:00:00.000000000 -0500
+@@ -1,544 +0,0 @@
 -/*
-- * A couple of forward declarations required, due to cyclic reference loop:
-- *  cpuset_mkdir -> cpuset_create -> cpuset_populate_dir -> cpuset_add_file
-- *  -> cpuset_create_file -> cpuset_dir_inode_operations -> cpuset_mkdir.
+- * Copyright(c) 2006, Intel Corporation.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- *
 - */
+-#ifndef _ADMA_H
+-#define _ADMA_H
+-#include <linux/types.h>
+-#include <linux/io.h>
+-#include <asm/hardware.h>
+-#include <asm/hardware/iop_adma.h>
+-
+-#define ADMA_ACCR(chan)       (chan->mmr_base + 0x0)
+-#define ADMA_ACSR(chan)       (chan->mmr_base + 0x4)
+-#define ADMA_ADAR(chan)       (chan->mmr_base + 0x8)
+-#define ADMA_IIPCR(chan)      (chan->mmr_base + 0x18)
+-#define ADMA_IIPAR(chan)      (chan->mmr_base + 0x1c)
+-#define ADMA_IIPUAR(chan)     (chan->mmr_base + 0x20)
+-#define ADMA_ANDAR(chan)      (chan->mmr_base + 0x24)
+-#define ADMA_ADCR(chan)       (chan->mmr_base + 0x28)
+-#define ADMA_CARMD(chan)      (chan->mmr_base + 0x2c)
+-#define ADMA_ABCR(chan)       (chan->mmr_base + 0x30)
+-#define ADMA_DLADR(chan)      (chan->mmr_base + 0x34)
+-#define ADMA_DUADR(chan)      (chan->mmr_base + 0x38)
+-#define ADMA_SLAR(src, chan)  (chan->mmr_base + (0x3c + (src << 3)))
+-#define ADMA_SUAR(src, chan)  (chan->mmr_base + (0x40 + (src << 3)))
+-
+-struct iop13xx_adma_src {
+-      u32 src_addr;
+-      union {
+-              u32 upper_src_addr;
+-              struct {
+-                      unsigned int pq_upper_src_addr:24;
+-                      unsigned int pq_dmlt:8;
+-              };
+-      };
+-};
+-
+-struct iop13xx_adma_desc_ctrl {
+-      unsigned int int_en:1;
+-      unsigned int xfer_dir:2;
+-      unsigned int src_select:4;
+-      unsigned int zero_result:1;
+-      unsigned int block_fill_en:1;
+-      unsigned int crc_gen_en:1;
+-      unsigned int crc_xfer_dis:1;
+-      unsigned int crc_seed_fetch_dis:1;
+-      unsigned int status_write_back_en:1;
+-      unsigned int endian_swap_en:1;
+-      unsigned int reserved0:2;
+-      unsigned int pq_update_xfer_en:1;
+-      unsigned int dual_xor_en:1;
+-      unsigned int pq_xfer_en:1;
+-      unsigned int p_xfer_dis:1;
+-      unsigned int reserved1:10;
+-      unsigned int relax_order_en:1;
+-      unsigned int no_snoop_en:1;
+-};
+-
+-struct iop13xx_adma_byte_count {
+-      unsigned int byte_count:24;
+-      unsigned int host_if:3;
+-      unsigned int reserved:2;
+-      unsigned int zero_result_err_q:1;
+-      unsigned int zero_result_err:1;
+-      unsigned int tx_complete:1;
+-};
+-
+-struct iop13xx_adma_desc_hw {
+-      u32 next_desc;
+-      union {
+-              u32 desc_ctrl;
+-              struct iop13xx_adma_desc_ctrl desc_ctrl_field;
+-      };
+-      union {
+-              u32 crc_addr;
+-              u32 block_fill_data;
+-              u32 q_dest_addr;
+-      };
+-      union {
+-              u32 byte_count;
+-              struct iop13xx_adma_byte_count byte_count_field;
+-      };
+-      union {
+-              u32 dest_addr;
+-              u32 p_dest_addr;
+-      };
+-      union {
+-              u32 upper_dest_addr;
+-              u32 pq_upper_dest_addr;
+-      };
+-      struct iop13xx_adma_src src[1];
+-};
 -
--static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode);
--static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry);
+-struct iop13xx_adma_desc_dual_xor {
+-      u32 next_desc;
+-      u32 desc_ctrl;
+-      u32 reserved;
+-      u32 byte_count;
+-      u32 h_dest_addr;
+-      u32 h_upper_dest_addr;
+-      u32 src0_addr;
+-      u32 upper_src0_addr;
+-      u32 src1_addr;
+-      u32 upper_src1_addr;
+-      u32 h_src_addr;
+-      u32 h_upper_src_addr;
+-      u32 d_src_addr;
+-      u32 d_upper_src_addr;
+-      u32 d_dest_addr;
+-      u32 d_upper_dest_addr;
+-};
 -
--static struct backing_dev_info cpuset_backing_dev_info = {
--      .ra_pages = 0,          /* No readahead */
--      .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+-struct iop13xx_adma_desc_pq_update {
+-      u32 next_desc;
+-      u32 desc_ctrl;
+-      u32 reserved;
+-      u32 byte_count;
+-      u32 p_dest_addr;
+-      u32 p_upper_dest_addr;
+-      u32 src0_addr;
+-      u32 upper_src0_addr;
+-      u32 src1_addr;
+-      u32 upper_src1_addr;
+-      u32 p_src_addr;
+-      u32 p_upper_src_addr;
+-      u32 q_src_addr;
+-      struct {
+-              unsigned int q_upper_src_addr:24;
+-              unsigned int q_dmlt:8;
+-      };
+-      u32 q_dest_addr;
+-      u32 q_upper_dest_addr;
 -};
 -
--static struct inode *cpuset_new_inode(mode_t mode)
+-static inline int iop_adma_get_max_xor(void)
 -{
--      struct inode *inode = new_inode(cpuset_sb);
+-      return 16;
+-}
 -
--      if (inode) {
--              inode->i_mode = mode;
--              inode->i_uid = current->fsuid;
--              inode->i_gid = current->fsgid;
--              inode->i_blocks = 0;
--              inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
--              inode->i_mapping->backing_dev_info = &cpuset_backing_dev_info;
--      }
--      return inode;
+-static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
+-{
+-      return __raw_readl(ADMA_ADAR(chan));
 -}
 -
--static void cpuset_diput(struct dentry *dentry, struct inode *inode)
+-static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
+-                                              u32 next_desc_addr)
 -{
--      /* is dentry a directory ? if so, kfree() associated cpuset */
--      if (S_ISDIR(inode->i_mode)) {
--              struct cpuset *cs = dentry->d_fsdata;
--              BUG_ON(!(is_removed(cs)));
--              kfree(cs);
--      }
--      iput(inode);
+-      __raw_writel(next_desc_addr, ADMA_ANDAR(chan));
 -}
 -
--static struct dentry_operations cpuset_dops = {
--      .d_iput = cpuset_diput,
--};
+-#define ADMA_STATUS_BUSY (1 << 13)
 -
--static struct dentry *cpuset_get_dentry(struct dentry *parent, const char *name)
+-static inline char iop_chan_is_busy(struct iop_adma_chan *chan)
 -{
--      struct dentry *d = lookup_one_len(name, parent, strlen(name));
--      if (!IS_ERR(d))
--              d->d_op = &cpuset_dops;
--      return d;
+-      if (__raw_readl(ADMA_ACSR(chan)) &
+-              ADMA_STATUS_BUSY)
+-              return 1;
+-      else
+-              return 0;
 -}
 -
--static void remove_dir(struct dentry *d)
+-static inline int
+-iop_chan_get_desc_align(struct iop_adma_chan *chan, int num_slots)
 -{
--      struct dentry *parent = dget(d->d_parent);
--
--      d_delete(d);
--      simple_rmdir(parent->d_inode, d);
--      dput(parent);
+-      return 1;
 -}
+-#define iop_desc_is_aligned(x, y) 1
 -
--/*
-- * NOTE : the dentry must have been dget()'ed
-- */
--static void cpuset_d_remove_dir(struct dentry *dentry)
+-static inline int
+-iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
 -{
--      struct list_head *node;
--
--      spin_lock(&dcache_lock);
--      node = dentry->d_subdirs.next;
--      while (node != &dentry->d_subdirs) {
--              struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
--              list_del_init(node);
--              if (d->d_inode) {
--                      d = dget_locked(d);
--                      spin_unlock(&dcache_lock);
--                      d_delete(d);
--                      simple_unlink(dentry->d_inode, d);
--                      dput(d);
--                      spin_lock(&dcache_lock);
--              }
--              node = dentry->d_subdirs.next;
--      }
--      list_del_init(&dentry->d_u.d_child);
--      spin_unlock(&dcache_lock);
--      remove_dir(dentry);
+-      *slots_per_op = 1;
+-      return 1;
 -}
 -
--static struct super_operations cpuset_ops = {
--      .statfs = simple_statfs,
--      .drop_inode = generic_delete_inode,
--};
+-#define iop_chan_interrupt_slot_count(s, c) iop_chan_memcpy_slot_count(0, s)
 -
--static int cpuset_fill_super(struct super_block *sb, void *unused_data,
--                                                      int unused_silent)
+-static inline int
+-iop_chan_memset_slot_count(size_t len, int *slots_per_op)
 -{
--      struct inode *inode;
--      struct dentry *root;
+-      *slots_per_op = 1;
+-      return 1;
+-}
 -
--      sb->s_blocksize = PAGE_CACHE_SIZE;
--      sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
--      sb->s_magic = CPUSET_SUPER_MAGIC;
--      sb->s_op = &cpuset_ops;
--      cpuset_sb = sb;
+-static inline int
+-iop_chan_xor_slot_count(size_t len, int src_cnt, int *slots_per_op)
+-{
+-      int num_slots;
+-      /* slots_to_find = 1 for basic descriptor + 1 per 4 sources above 1
+-       * (1 source => 8 bytes) (1 slot => 32 bytes)
+-       */
+-      num_slots = 1 + (((src_cnt - 1) << 3) >> 5);
+-      if (((src_cnt - 1) << 3) & 0x1f)
+-              num_slots++;
 -
--      inode = cpuset_new_inode(S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR);
--      if (inode) {
--              inode->i_op = &simple_dir_inode_operations;
--              inode->i_fop = &simple_dir_operations;
--              /* directories start off with i_nlink == 2 (for "." entry) */
--              inc_nlink(inode);
--      } else {
--              return -ENOMEM;
--      }
+-      *slots_per_op = num_slots;
 -
--      root = d_alloc_root(inode);
--      if (!root) {
--              iput(inode);
--              return -ENOMEM;
--      }
--      sb->s_root = root;
--      return 0;
+-      return num_slots;
 -}
 -
-+/* This is ugly, but preserves the userspace API for existing cpuset
-+ * users. If someone tries to mount the "cpuset" filesystem, we
-+ * silently switch it to mount "container" instead */
- static int cpuset_get_sb(struct file_system_type *fs_type,
-                        int flags, const char *unused_dev_name,
-                        void *data, struct vfsmount *mnt)
- {
--      return get_sb_single(fs_type, flags, data, cpuset_fill_super, mnt);
-+      struct file_system_type *container_fs = get_fs_type("container");
-+      int ret = -ENODEV;
-+      if (container_fs) {
-+              ret = container_fs->get_sb(container_fs, flags,
-+                                         unused_dev_name,
-+                                         "cpuset", mnt);
-+              put_filesystem(container_fs);
-+              if (!ret) {
-+                      container_set_release_agent_path(
-+                              &cpuset_subsys,
-+                              "/sbin/cpuset_release_agent");
-+              }
-+      }
-+      return ret;
- }
- static struct file_system_type cpuset_fs_type = {
-       .name = "cpuset",
-       .get_sb = cpuset_get_sb,
--      .kill_sb = kill_litter_super,
--};
--
--/* struct cftype:
-- *
-- * The files in the cpuset filesystem mostly have a very simple read/write
-- * handling, some common function will take care of it. Nevertheless some cases
-- * (read tasks) are special and therefore I define this structure for every
-- * kind of file.
-- *
-- *
-- * When reading/writing to a file:
-- *    - the cpuset to use in file->f_path.dentry->d_parent->d_fsdata
-- *    - the 'cftype' of the file is file->f_path.dentry->d_fsdata
-- */
+-#define ADMA_MAX_BYTE_COUNT   (16 * 1024 * 1024)
+-#define IOP_ADMA_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
+-#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
+-#define IOP_ADMA_XOR_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
+-#define iop_chan_zero_sum_slot_count(l, s, o) iop_chan_xor_slot_count(l, s, o)
 -
--struct cftype {
--      char *name;
--      int private;
--      int (*open) (struct inode *inode, struct file *file);
--      ssize_t (*read) (struct file *file, char __user *buf, size_t nbytes,
--                                                      loff_t *ppos);
--      int (*write) (struct file *file, const char __user *buf, size_t nbytes,
--                                                      loff_t *ppos);
--      int (*release) (struct inode *inode, struct file *file);
- };
--static inline struct cpuset *__d_cs(struct dentry *dentry)
+-static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc,
+-                                      struct iop_adma_chan *chan)
 -{
--      return dentry->d_fsdata;
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      return hw_desc->dest_addr;
 -}
 -
--static inline struct cftype *__d_cft(struct dentry *dentry)
+-static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
+-                                      struct iop_adma_chan *chan)
 -{
--      return dentry->d_fsdata;
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      return hw_desc->byte_count_field.byte_count;
 -}
 -
--/*
-- * Call with manage_mutex held.  Writes path of cpuset into buf.
-- * Returns 0 on success, -errno on error.
-- */
--
--static int cpuset_path(const struct cpuset *cs, char *buf, int buflen)
+-static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
+-                                      struct iop_adma_chan *chan,
+-                                      int src_idx)
 -{
--      char *start;
--
--      start = buf + buflen;
--
--      *--start = '\0';
--      for (;;) {
--              int len = cs->dentry->d_name.len;
--              if ((start -= len) < buf)
--                      return -ENAMETOOLONG;
--              memcpy(start, cs->dentry->d_name.name, len);
--              cs = cs->parent;
--              if (!cs)
--                      break;
--              if (!cs->parent)
--                      continue;
--              if (--start < buf)
--                      return -ENAMETOOLONG;
--              *start = '/';
--      }
--      memmove(buf, start, buf + buflen - start);
--      return 0;
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      return hw_desc->src[src_idx].src_addr;
 -}
 -
--/*
-- * Notify userspace when a cpuset is released, by running
-- * /sbin/cpuset_release_agent with the name of the cpuset (path
-- * relative to the root of cpuset file system) as the argument.
-- *
-- * Most likely, this user command will try to rmdir this cpuset.
-- *
-- * This races with the possibility that some other task will be
-- * attached to this cpuset before it is removed, or that some other
-- * user task will 'mkdir' a child cpuset of this cpuset.  That's ok.
-- * The presumed 'rmdir' will fail quietly if this cpuset is no longer
-- * unused, and this cpuset will be reprieved from its death sentence,
-- * to continue to serve a useful existence.  Next time it's released,
-- * we will get notified again, if it still has 'notify_on_release' set.
-- *
-- * The final arg to call_usermodehelper() is 0, which means don't
-- * wait.  The separate /sbin/cpuset_release_agent task is forked by
-- * call_usermodehelper(), then control in this thread returns here,
-- * without waiting for the release agent task.  We don't bother to
-- * wait because the caller of this routine has no use for the exit
-- * status of the /sbin/cpuset_release_agent task, so no sense holding
-- * our caller up for that.
-- *
-- * When we had only one cpuset mutex, we had to call this
-- * without holding it, to avoid deadlock when call_usermodehelper()
-- * allocated memory.  With two locks, we could now call this while
-- * holding manage_mutex, but we still don't, so as to minimize
-- * the time manage_mutex is held.
-- */
--
--static void cpuset_release_agent(const char *pathbuf)
+-static inline u32 iop_desc_get_src_count(struct iop_adma_desc_slot *desc,
+-                                      struct iop_adma_chan *chan)
 -{
--      char *argv[3], *envp[3];
--      int i;
--
--      if (!pathbuf)
--              return;
--
--      i = 0;
--      argv[i++] = "/sbin/cpuset_release_agent";
--      argv[i++] = (char *)pathbuf;
--      argv[i] = NULL;
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      return hw_desc->desc_ctrl_field.src_select + 1;
+-}
 -
--      i = 0;
--      /* minimal command environment */
--      envp[i++] = "HOME=/";
--      envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
--      envp[i] = NULL;
+-static inline void
+-iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en)
+-{
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      union {
+-              u32 value;
+-              struct iop13xx_adma_desc_ctrl field;
+-      } u_desc_ctrl;
 -
--      call_usermodehelper(argv[0], argv, envp, 0);
--      kfree(pathbuf);
+-      u_desc_ctrl.value = 0;
+-      u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+-      u_desc_ctrl.field.int_en = int_en;
+-      hw_desc->desc_ctrl = u_desc_ctrl.value;
+-      hw_desc->crc_addr = 0;
 -}
 -
--/*
-- * Either cs->count of using tasks transitioned to zero, or the
-- * cs->children list of child cpusets just became empty.  If this
-- * cs is notify_on_release() and now both the user count is zero and
-- * the list of children is empty, prepare cpuset path in a kmalloc'd
-- * buffer, to be returned via ppathbuf, so that the caller can invoke
-- * cpuset_release_agent() with it later on, once manage_mutex is dropped.
-- * Call here with manage_mutex held.
-- *
-- * This check_for_release() routine is responsible for kmalloc'ing
-- * pathbuf.  The above cpuset_release_agent() is responsible for
-- * kfree'ing pathbuf.  The caller of these routines is responsible
-- * for providing a pathbuf pointer, initialized to NULL, then
-- * calling check_for_release() with manage_mutex held and the address
-- * of the pathbuf pointer, then dropping manage_mutex, then calling
-- * cpuset_release_agent() with pathbuf, as set by check_for_release().
-- */
--
--static void check_for_release(struct cpuset *cs, char **ppathbuf)
--{
--      if (notify_on_release(cs) && atomic_read(&cs->count) == 0 &&
--          list_empty(&cs->children)) {
--              char *buf;
--
--              buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
--              if (!buf)
--                      return;
--              if (cpuset_path(cs, buf, PAGE_SIZE) < 0)
--                      kfree(buf);
--              else
--                      *ppathbuf = buf;
--      }
--}
+-static inline void
+-iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en)
+-{
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      union {
+-              u32 value;
+-              struct iop13xx_adma_desc_ctrl field;
+-      } u_desc_ctrl;
 -
- /*
-  * Return in *pmask the portion of a cpusets's cpus_allowed that
-  * are online.  If none are online, walk up the cpuset hierarchy
-@@ -651,20 +386,19 @@
-       struct task_struct *tsk = current;
-       struct cpuset *cs;
--      if (tsk->cpuset == &top_cpuset) {
-+      if (task_cs(tsk) == &top_cpuset) {
-               /* Don't need rcu for top_cpuset.  It's never freed. */
-               my_cpusets_mem_gen = top_cpuset.mems_generation;
-       } else {
-               rcu_read_lock();
--              cs = rcu_dereference(tsk->cpuset);
--              my_cpusets_mem_gen = cs->mems_generation;
-+              my_cpusets_mem_gen = task_cs(current)->mems_generation;
-               rcu_read_unlock();
-       }
-       if (my_cpusets_mem_gen != tsk->cpuset_mems_generation) {
-               mutex_lock(&callback_mutex);
-               task_lock(tsk);
--              cs = tsk->cpuset;       /* Maybe changed when task not locked */
-+              cs = task_cs(tsk); /* Maybe changed when task not locked */
-               guarantee_online_mems(cs, &tsk->mems_allowed);
-               tsk->cpuset_mems_generation = cs->mems_generation;
-               if (is_spread_page(cs))
-@@ -719,11 +453,12 @@
- static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
- {
-+      struct container *cont;
-       struct cpuset *c, *par;
-       /* Each of our child cpusets must be a subset of us */
--      list_for_each_entry(c, &cur->children, sibling) {
--              if (!is_cpuset_subset(c, trial))
-+      list_for_each_entry(cont, &cur->css.container->children, sibling) {
-+              if (!is_cpuset_subset(container_cs(cont), trial))
-                       return -EBUSY;
-       }
-@@ -738,7 +473,8 @@
-               return -EACCES;
-       /* If either I or some sibling (!= me) is exclusive, we can't overlap */
--      list_for_each_entry(c, &par->children, sibling) {
-+      list_for_each_entry(cont, &par->css.container->children, sibling) {
-+              c = container_cs(cont);
-               if ((is_cpu_exclusive(trial) || is_cpu_exclusive(c)) &&
-                   c != cur &&
-                   cpus_intersects(trial->cpus_allowed, c->cpus_allowed))
-@@ -753,68 +489,13 @@
- }
- /*
-- * For a given cpuset cur, partition the system as follows
-- * a. All cpus in the parent cpuset's cpus_allowed that are not part of any
-- *    exclusive child cpusets
-- * b. All cpus in the current cpuset's cpus_allowed that are not part of any
-- *    exclusive child cpusets
-- * Build these two partitions by calling partition_sched_domains
-- *
-- * Call with manage_mutex held.  May nest a call to the
-- * lock_cpu_hotplug()/unlock_cpu_hotplug() pair.
-- * Must not be called holding callback_mutex, because we must
-- * not call lock_cpu_hotplug() while holding callback_mutex.
-- */
+-      u_desc_ctrl.value = 0;
+-      u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+-      u_desc_ctrl.field.block_fill_en = 1;
+-      u_desc_ctrl.field.int_en = int_en;
+-      hw_desc->desc_ctrl = u_desc_ctrl.value;
+-      hw_desc->crc_addr = 0;
+-}
 -
--static void update_cpu_domains(struct cpuset *cur)
+-/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
+-static inline void
+-iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
 -{
--      struct cpuset *c, *par = cur->parent;
--      cpumask_t pspan, cspan;
--
--      if (par == NULL || cpus_empty(cur->cpus_allowed))
--              return;
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      union {
+-              u32 value;
+-              struct iop13xx_adma_desc_ctrl field;
+-      } u_desc_ctrl;
 -
--      /*
--       * Get all cpus from parent's cpus_allowed not part of exclusive
--       * children
--       */
--      pspan = par->cpus_allowed;
--      list_for_each_entry(c, &par->children, sibling) {
--              if (is_cpu_exclusive(c))
--                      cpus_andnot(pspan, pspan, c->cpus_allowed);
--      }
--      if (!is_cpu_exclusive(cur)) {
--              cpus_or(pspan, pspan, cur->cpus_allowed);
--              if (cpus_equal(pspan, cur->cpus_allowed))
--                      return;
--              cspan = CPU_MASK_NONE;
--      } else {
--              if (cpus_empty(pspan))
--                      return;
--              cspan = cur->cpus_allowed;
--              /*
--               * Get all cpus from current cpuset's cpus_allowed not part
--               * of exclusive children
--               */
--              list_for_each_entry(c, &cur->children, sibling) {
--                      if (is_cpu_exclusive(c))
--                              cpus_andnot(cspan, cspan, c->cpus_allowed);
--              }
--      }
+-      u_desc_ctrl.value = 0;
+-      u_desc_ctrl.field.src_select = src_cnt - 1;
+-      u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+-      u_desc_ctrl.field.int_en = int_en;
+-      hw_desc->desc_ctrl = u_desc_ctrl.value;
+-      hw_desc->crc_addr = 0;
 -
--      lock_cpu_hotplug();
--      partition_sched_domains(&pspan, &cspan);
--      unlock_cpu_hotplug();
 -}
+-#define iop_desc_init_null_xor(d, s, i) iop_desc_init_xor(d, s, i)
 -
--/*
-  * Call with manage_mutex held.  May take callback_mutex during call.
-  */
- static int update_cpumask(struct cpuset *cs, char *buf)
- {
-       struct cpuset trialcs;
--      int retval, cpus_unchanged;
-+      int retval;
-       /* top_cpuset.cpus_allowed tracks cpu_online_map; it's read-only */
-       if (cs == &top_cpuset)
-@@ -836,17 +517,15 @@
-       }
-       cpus_and(trialcs.cpus_allowed, trialcs.cpus_allowed, cpu_online_map);
-       /* cpus_allowed cannot be empty for a cpuset with attached tasks. */
--      if (atomic_read(&cs->count) && cpus_empty(trialcs.cpus_allowed))
-+      if (container_task_count(cs->css.container) &&
-+            cpus_empty(trialcs.cpus_allowed))
-               return -ENOSPC;
-       retval = validate_change(cs, &trialcs);
-       if (retval < 0)
-               return retval;
--      cpus_unchanged = cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed);
-       mutex_lock(&callback_mutex);
-       cs->cpus_allowed = trialcs.cpus_allowed;
-       mutex_unlock(&callback_mutex);
--      if (is_cpu_exclusive(cs) && !cpus_unchanged)
--              update_cpu_domains(cs);
-       return 0;
- }
-@@ -895,7 +574,7 @@
-       do_migrate_pages(mm, from, to, MPOL_MF_MOVE_ALL);
-       mutex_lock(&callback_mutex);
--      guarantee_online_mems(tsk->cpuset, &tsk->mems_allowed);
-+      guarantee_online_mems(task_cs(tsk),&tsk->mems_allowed);
-       mutex_unlock(&callback_mutex);
- }
-@@ -913,16 +592,19 @@
-  * their mempolicies to the cpusets new mems_allowed.
-  */
-+static void *cpuset_being_rebound;
-+
- static int update_nodemask(struct cpuset *cs, char *buf)
- {
-       struct cpuset trialcs;
-       nodemask_t oldmem;
--      struct task_struct *g, *p;
-+      struct task_struct *p;
-       struct mm_struct **mmarray;
-       int i, n, ntasks;
-       int migrate;
-       int fudge;
-       int retval;
-+      struct container_iter it;
-       /* top_cpuset.mems_allowed tracks node_online_map; it's read-only */
-       if (cs == &top_cpuset)
-@@ -949,7 +631,8 @@
-               goto done;
-       }
-       /* mems_allowed cannot be empty for a cpuset with attached tasks. */
--      if (atomic_read(&cs->count) && nodes_empty(trialcs.mems_allowed)) {
-+      if (container_task_count(cs->css.container) &&
-+          nodes_empty(trialcs.mems_allowed)) {
-               retval = -ENOSPC;
-               goto done;
-       }
-@@ -962,7 +645,7 @@
-       cs->mems_generation = cpuset_mems_generation++;
-       mutex_unlock(&callback_mutex);
--      set_cpuset_being_rebound(cs);           /* causes mpol_copy() rebind */
-+      cpuset_being_rebound = cs;              /* causes mpol_copy() rebind */
-       fudge = 10;                             /* spare mmarray[] slots */
-       fudge += cpus_weight(cs->cpus_allowed); /* imagine one fork-bomb/cpu */
-@@ -976,37 +659,37 @@
-        * enough mmarray[] w/o using GFP_ATOMIC.
-        */
-       while (1) {
--              ntasks = atomic_read(&cs->count);       /* guess */
-+              ntasks = container_task_count(cs->css.container);  /* guess */
-               ntasks += fudge;
-               mmarray = kmalloc(ntasks * sizeof(*mmarray), GFP_KERNEL);
-               if (!mmarray)
-                       goto done;
--              write_lock_irq(&tasklist_lock);         /* block fork */
--              if (atomic_read(&cs->count) <= ntasks)
-+              read_lock(&tasklist_lock);              /* block fork */
-+              if (container_task_count(cs->css.container) <= ntasks)
-                       break;                          /* got enough */
--              write_unlock_irq(&tasklist_lock);       /* try again */
-+              read_unlock(&tasklist_lock);            /* try again */
-               kfree(mmarray);
-       }
-       n = 0;
-       /* Load up mmarray[] with mm reference for each task in cpuset. */
--      do_each_thread(g, p) {
-+      container_iter_start(cs->css.container, &it);
-+      while ((p = container_iter_next(cs->css.container, &it))) {
-               struct mm_struct *mm;
-               if (n >= ntasks) {
-                       printk(KERN_WARNING
-                               "Cpuset mempolicy rebind incomplete.\n");
--                      continue;
-+                      break;
-               }
--              if (p->cpuset != cs)
--                      continue;
-               mm = get_task_mm(p);
-               if (!mm)
-                       continue;
-               mmarray[n++] = mm;
--      } while_each_thread(g, p);
--      write_unlock_irq(&tasklist_lock);
-+      }
-+      container_iter_end(cs->css.container, &it);
-+      read_unlock(&tasklist_lock);
-       /*
-        * Now that we've dropped the tasklist spinlock, we can
-@@ -1033,12 +716,17 @@
-       /* We're done rebinding vma's to this cpusets new mems_allowed. */
-       kfree(mmarray);
--      set_cpuset_being_rebound(NULL);
-+      cpuset_being_rebound = NULL;
-       retval = 0;
- done:
-       return retval;
- }
-+int current_cpuset_is_being_rebound(void)
-+{
-+      return task_cs(current) == cpuset_being_rebound;
-+}
-+
- /*
-  * Call with manage_mutex held.
-  */
-@@ -1067,7 +755,7 @@
- {
-       int turning_on;
-       struct cpuset trialcs;
--      int err, cpu_exclusive_changed;
-+      int err;
-       turning_on = (simple_strtoul(buf, NULL, 10) != 0);
-@@ -1080,14 +768,10 @@
-       err = validate_change(cs, &trialcs);
-       if (err < 0)
-               return err;
--      cpu_exclusive_changed =
--              (is_cpu_exclusive(cs) != is_cpu_exclusive(&trialcs));
-       mutex_lock(&callback_mutex);
-       cs->flags = trialcs.flags;
-       mutex_unlock(&callback_mutex);
--      if (cpu_exclusive_changed)
--                update_cpu_domains(cs);
-       return 0;
- }
-@@ -1189,85 +873,34 @@
-       return val;
- }
--/*
-- * Attack task specified by pid in 'pidbuf' to cpuset 'cs', possibly
-- * writing the path of the old cpuset in 'ppathbuf' if it needs to be
-- * notified on release.
-- *
-- * Call holding manage_mutex.  May take callback_mutex and task_lock of
-- * the task 'pid' during call.
-- */
+-/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
+-static inline int
+-iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+-{
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      union {
+-              u32 value;
+-              struct iop13xx_adma_desc_ctrl field;
+-      } u_desc_ctrl;
+-
+-      u_desc_ctrl.value = 0;
+-      u_desc_ctrl.field.src_select = src_cnt - 1;
+-      u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+-      u_desc_ctrl.field.zero_result = 1;
+-      u_desc_ctrl.field.status_write_back_en = 1;
+-      u_desc_ctrl.field.int_en = int_en;
+-      hw_desc->desc_ctrl = u_desc_ctrl.value;
+-      hw_desc->crc_addr = 0;
 -
--static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
-+int cpuset_can_attach(struct container_subsys *ss,
-+                    struct container *cont, struct task_struct *tsk)
- {
--      pid_t pid;
--      struct task_struct *tsk;
--      struct cpuset *oldcs;
--      cpumask_t cpus;
--      nodemask_t from, to;
--      struct mm_struct *mm;
--      int retval;
-+      struct cpuset *cs = container_cs(cont);
--      if (sscanf(pidbuf, "%d", &pid) != 1)
--              return -EIO;
-       if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed))
-               return -ENOSPC;
--      if (pid) {
--              read_lock(&tasklist_lock);
+-      return 1;
+-}
 -
--              tsk = find_task_by_pid(pid);
--              if (!tsk || tsk->flags & PF_EXITING) {
--                      read_unlock(&tasklist_lock);
--                      return -ESRCH;
--              }
+-static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
+-                                      struct iop_adma_chan *chan,
+-                                      u32 byte_count)
+-{
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      hw_desc->byte_count = byte_count;
+-}
 -
--              get_task_struct(tsk);
--              read_unlock(&tasklist_lock);
+-static inline void
+-iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
+-{
+-      int slots_per_op = desc->slots_per_op;
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
+-      int i = 0;
 -
--              if ((current->euid) && (current->euid != tsk->uid)
--                  && (current->euid != tsk->suid)) {
--                      put_task_struct(tsk);
--                      return -EACCES;
--              }
+-      if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+-              hw_desc->byte_count = len;
 -      } else {
--              tsk = current;
--              get_task_struct(tsk);
--      }
-+      return security_task_setscheduler(tsk, 0, NULL);
-+}
--      retval = security_task_setscheduler(tsk, 0, NULL);
--      if (retval) {
--              put_task_struct(tsk);
--              return retval;
--      }
-+void cpuset_attach(struct container_subsys *ss,
-+                 struct container *cont, struct container *oldcont,
-+                 struct task_struct *tsk)
-+{
-+      cpumask_t cpus;
-+      nodemask_t from, to;
-+      struct mm_struct *mm;
-+      struct cpuset *cs = container_cs(cont);
-+      struct cpuset *oldcs = container_cs(oldcont);
-       mutex_lock(&callback_mutex);
+-              do {
+-                      iter = iop_hw_desc_slot_idx(hw_desc, i);
+-                      iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+-                      len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+-                      i += slots_per_op;
+-              } while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
 -
--      task_lock(tsk);
--      oldcs = tsk->cpuset;
--      /*
--       * After getting 'oldcs' cpuset ptr, be sure still not exiting.
--       * If 'oldcs' might be the top_cpuset due to the_top_cpuset_hack
--       * then fail this attach_task(), to avoid breaking top_cpuset.count.
--       */
--      if (tsk->flags & PF_EXITING) {
--              task_unlock(tsk);
--              mutex_unlock(&callback_mutex);
--              put_task_struct(tsk);
--              return -ESRCH;
+-              if (len) {
+-                      iter = iop_hw_desc_slot_idx(hw_desc, i);
+-                      iter->byte_count = len;
+-              }
 -      }
--      atomic_inc(&cs->count);
--      rcu_assign_pointer(tsk->cpuset, cs);
--      task_unlock(tsk);
--
-       guarantee_online_cpus(cs, &cpus);
-       set_cpus_allowed(tsk, cpus);
-+      mutex_unlock(&callback_mutex);
-       from = oldcs->mems_allowed;
-       to = cs->mems_allowed;
--
--      mutex_unlock(&callback_mutex);
+-}
 -
-       mm = get_task_mm(tsk);
-       if (mm) {
-               mpol_rebind_mm(mm, &to);
-@@ -1276,40 +909,31 @@
-               mmput(mm);
-       }
--      put_task_struct(tsk);
--      synchronize_rcu();
--      if (atomic_dec_and_test(&oldcs->count))
--              check_for_release(oldcs, ppathbuf);
--      return 0;
- }
- /* The various types of files and directories in a cpuset file system */
- typedef enum {
--      FILE_ROOT,
--      FILE_DIR,
-       FILE_MEMORY_MIGRATE,
-       FILE_CPULIST,
-       FILE_MEMLIST,
-       FILE_CPU_EXCLUSIVE,
-       FILE_MEM_EXCLUSIVE,
--      FILE_NOTIFY_ON_RELEASE,
-       FILE_MEMORY_PRESSURE_ENABLED,
-       FILE_MEMORY_PRESSURE,
-       FILE_SPREAD_PAGE,
-       FILE_SPREAD_SLAB,
--      FILE_TASKLIST,
- } cpuset_filetype_t;
--static ssize_t cpuset_common_file_write(struct file *file,
-+static ssize_t cpuset_common_file_write(struct container *cont,
-+                                      struct cftype *cft,
-+                                      struct file *file,
-                                       const char __user *userbuf,
-                                       size_t nbytes, loff_t *unused_ppos)
- {
--      struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
--      struct cftype *cft = __d_cft(file->f_path.dentry);
-+      struct cpuset *cs = container_cs(cont);
-       cpuset_filetype_t type = cft->private;
-       char *buffer;
--      char *pathbuf = NULL;
-       int retval = 0;
-       /* Crude upper limit on largest legitimate cpulist user might write. */
-@@ -1326,9 +950,9 @@
-       }
-       buffer[nbytes] = 0;     /* nul-terminate */
--      mutex_lock(&manage_mutex);
-+      container_lock();
--      if (is_removed(cs)) {
-+      if (container_is_removed(cont)) {
-               retval = -ENODEV;
-               goto out2;
-       }
-@@ -1346,9 +970,6 @@
-       case FILE_MEM_EXCLUSIVE:
-               retval = update_flag(CS_MEM_EXCLUSIVE, cs, buffer);
-               break;
--      case FILE_NOTIFY_ON_RELEASE:
--              retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer);
--              break;
-       case FILE_MEMORY_MIGRATE:
-               retval = update_flag(CS_MEMORY_MIGRATE, cs, buffer);
-               break;
-@@ -1366,9 +987,6 @@
-               retval = update_flag(CS_SPREAD_SLAB, cs, buffer);
-               cs->mems_generation = cpuset_mems_generation++;
-               break;
--      case FILE_TASKLIST:
--              retval = attach_task(cs, buffer, &pathbuf);
--              break;
-       default:
-               retval = -EINVAL;
-               goto out2;
-@@ -1377,30 +995,12 @@
-       if (retval == 0)
-               retval = nbytes;
- out2:
--      mutex_unlock(&manage_mutex);
--      cpuset_release_agent(pathbuf);
-+      container_unlock();
- out1:
-       kfree(buffer);
-       return retval;
- }
--static ssize_t cpuset_file_write(struct file *file, const char __user *buf,
--                                              size_t nbytes, loff_t *ppos)
+-
+-static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
+-                                      struct iop_adma_chan *chan,
+-                                      dma_addr_t addr)
 -{
--      ssize_t retval = 0;
--      struct cftype *cft = __d_cft(file->f_path.dentry);
--      if (!cft)
--              return -ENODEV;
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      hw_desc->dest_addr = addr;
+-      hw_desc->upper_dest_addr = 0;
+-}
 -
--      /* special function ? */
--      if (cft->write)
--              retval = cft->write(file, buf, nbytes, ppos);
--      else
--              retval = cpuset_common_file_write(file, buf, nbytes, ppos);
+-static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
+-                                      dma_addr_t addr)
+-{
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      hw_desc->src[0].src_addr = addr;
+-      hw_desc->src[0].upper_src_addr = 0;
+-}
 -
--      return retval;
+-static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
+-                                      int src_idx, dma_addr_t addr)
+-{
+-      int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
+-      int i = 0;
+-
+-      do {
+-              iter = iop_hw_desc_slot_idx(hw_desc, i);
+-              iter->src[src_idx].src_addr = addr;
+-              iter->src[src_idx].upper_src_addr = 0;
+-              slot_cnt -= slots_per_op;
+-              if (slot_cnt) {
+-                      i += slots_per_op;
+-                      addr += IOP_ADMA_XOR_MAX_BYTE_COUNT;
+-              }
+-      } while (slot_cnt);
 -}
 -
- /*
-  * These ascii lists should be read in a single call, by using a user
-  * buffer large enough to hold the entire map.  If read in smaller
-@@ -1435,17 +1035,19 @@
-       return nodelist_scnprintf(page, PAGE_SIZE, mask);
- }
--static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
-+static ssize_t cpuset_common_file_read(struct container *cont,
-+                                     struct cftype *cft,
-+                                     struct file *file,
-+                                     char __user *buf,
-                               size_t nbytes, loff_t *ppos)
- {
--      struct cftype *cft = __d_cft(file->f_path.dentry);
--      struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
-+      struct cpuset *cs = container_cs(cont);
-       cpuset_filetype_t type = cft->private;
-       char *page;
-       ssize_t retval = 0;
-       char *s;
--      if (!(page = (char *)__get_free_page(GFP_KERNEL)))
-+      if (!(page = (char *)__get_free_page(GFP_TEMPORARY)))
-               return -ENOMEM;
-       s = page;
-@@ -1463,9 +1065,6 @@
-       case FILE_MEM_EXCLUSIVE:
-               *s++ = is_mem_exclusive(cs) ? '1' : '0';
-               break;
--      case FILE_NOTIFY_ON_RELEASE:
--              *s++ = notify_on_release(cs) ? '1' : '0';
--              break;
-       case FILE_MEMORY_MIGRATE:
-               *s++ = is_memory_migrate(cs) ? '1' : '0';
-               break;
-@@ -1493,390 +1092,140 @@
-       return retval;
- }
--static ssize_t cpuset_file_read(struct file *file, char __user *buf, size_t nbytes,
--                                                              loff_t *ppos)
+-static inline void
+-iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
+-      struct iop_adma_chan *chan)
 -{
--      ssize_t retval = 0;
--      struct cftype *cft = __d_cft(file->f_path.dentry);
--      if (!cft)
--              return -ENODEV;
+-      iop_desc_init_memcpy(desc, 1);
+-      iop_desc_set_byte_count(desc, chan, 0);
+-      iop_desc_set_dest_addr(desc, chan, 0);
+-      iop_desc_set_memcpy_src_addr(desc, 0);
+-}
 -
--      /* special function ? */
--      if (cft->read)
--              retval = cft->read(file, buf, nbytes, ppos);
--      else
--              retval = cpuset_common_file_read(file, buf, nbytes, ppos);
+-#define iop_desc_set_zero_sum_src_addr iop_desc_set_xor_src_addr
 -
--      return retval;
+-static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
+-                                      u32 next_desc_addr)
+-{
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      BUG_ON(hw_desc->next_desc);
+-      hw_desc->next_desc = next_desc_addr;
 -}
 -
--static int cpuset_file_open(struct inode *inode, struct file *file)
+-static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
 -{
--      int err;
--      struct cftype *cft;
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      return hw_desc->next_desc;
+-}
 -
--      err = generic_file_open(inode, file);
--      if (err)
--              return err;
+-static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
+-{
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      hw_desc->next_desc = 0;
+-}
 -
--      cft = __d_cft(file->f_path.dentry);
--      if (!cft)
--              return -ENODEV;
--      if (cft->open)
--              err = cft->open(inode, file);
--      else
--              err = 0;
+-static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
+-                                              u32 val)
+-{
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      hw_desc->block_fill_data = val;
+-}
 -
--      return err;
+-static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
+-{
+-      struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+-      struct iop13xx_adma_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
+-      struct iop13xx_adma_byte_count byte_count = hw_desc->byte_count_field;
+-
+-      BUG_ON(!(byte_count.tx_complete && desc_ctrl.zero_result));
+-
+-      if (desc_ctrl.pq_xfer_en)
+-              return byte_count.zero_result_err_q;
+-      else
+-              return byte_count.zero_result_err;
 -}
 -
--static int cpuset_file_release(struct inode *inode, struct file *file)
+-static inline void iop_chan_append(struct iop_adma_chan *chan)
 -{
--      struct cftype *cft = __d_cft(file->f_path.dentry);
--      if (cft->release)
--              return cft->release(inode, file);
--      return 0;
+-      u32 adma_accr;
+-
+-      adma_accr = __raw_readl(ADMA_ACCR(chan));
+-      adma_accr |= 0x2;
+-      __raw_writel(adma_accr, ADMA_ACCR(chan));
 -}
 -
--/*
-- * cpuset_rename - Only allow simple rename of directories in place.
-- */
--static int cpuset_rename(struct inode *old_dir, struct dentry *old_dentry,
--                  struct inode *new_dir, struct dentry *new_dentry)
+-static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
 -{
--      if (!S_ISDIR(old_dentry->d_inode->i_mode))
--              return -ENOTDIR;
--      if (new_dentry->d_inode)
--              return -EEXIST;
--      if (old_dir != new_dir)
--              return -EIO;
--      return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
+-      do { } while (0);
 -}
 -
--static const struct file_operations cpuset_file_operations = {
--      .read = cpuset_file_read,
--      .write = cpuset_file_write,
--      .llseek = generic_file_llseek,
--      .open = cpuset_file_open,
--      .release = cpuset_file_release,
--};
+-static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
+-{
+-      return __raw_readl(ADMA_ACSR(chan));
+-}
 -
--static const struct inode_operations cpuset_dir_inode_operations = {
--      .lookup = simple_lookup,
--      .mkdir = cpuset_mkdir,
--      .rmdir = cpuset_rmdir,
--      .rename = cpuset_rename,
--};
+-static inline void iop_chan_disable(struct iop_adma_chan *chan)
+-{
+-      u32 adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));
+-      adma_chan_ctrl &= ~0x1;
+-      __raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));
+-}
 -
--static int cpuset_create_file(struct dentry *dentry, int mode)
+-static inline void iop_chan_enable(struct iop_adma_chan *chan)
 -{
--      struct inode *inode;
+-      u32 adma_chan_ctrl;
 -
--      if (!dentry)
--              return -ENOENT;
--      if (dentry->d_inode)
--              return -EEXIST;
+-      adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));
+-      adma_chan_ctrl |= 0x1;
+-      __raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));
+-}
 -
--      inode = cpuset_new_inode(mode);
--      if (!inode)
--              return -ENOMEM;
+-static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
+-{
+-      u32 status = __raw_readl(ADMA_ACSR(chan));
+-      status &= (1 << 12);
+-      __raw_writel(status, ADMA_ACSR(chan));
+-}
 -
--      if (S_ISDIR(mode)) {
--              inode->i_op = &cpuset_dir_inode_operations;
--              inode->i_fop = &simple_dir_operations;
+-static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
+-{
+-      u32 status = __raw_readl(ADMA_ACSR(chan));
+-      status &= (1 << 11);
+-      __raw_writel(status, ADMA_ACSR(chan));
+-}
 -
--              /* start off with i_nlink == 2 (for "." entry) */
--              inc_nlink(inode);
--      } else if (S_ISREG(mode)) {
--              inode->i_size = 0;
--              inode->i_fop = &cpuset_file_operations;
--      }
+-static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
+-{
+-      u32 status = __raw_readl(ADMA_ACSR(chan));
+-      status &= (1 << 9) | (1 << 5) | (1 << 4) | (1 << 3);
+-      __raw_writel(status, ADMA_ACSR(chan));
+-}
 -
--      d_instantiate(dentry, inode);
--      dget(dentry);   /* Extra count - pin the dentry in core */
--      return 0;
+-static inline int
+-iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
+-{
+-      return test_bit(9, &status);
 -}
 -
--/*
-- *    cpuset_create_dir - create a directory for an object.
-- *    cs:     the cpuset we create the directory for.
-- *            It must have a valid ->parent field
-- *            And we are going to fill its ->dentry field.
-- *    name:   The name to give to the cpuset directory. Will be copied.
-- *    mode:   mode to set on new directory.
-- */
+-static inline int
+-iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
+-{
+-      return test_bit(5, &status);
+-}
 -
--static int cpuset_create_dir(struct cpuset *cs, const char *name, int mode)
+-static inline int
+-iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
 -{
--      struct dentry *dentry = NULL;
--      struct dentry *parent;
--      int error = 0;
+-      return test_bit(4, &status);
+-}
 -
--      parent = cs->parent->dentry;
--      dentry = cpuset_get_dentry(parent, name);
--      if (IS_ERR(dentry))
--              return PTR_ERR(dentry);
--      error = cpuset_create_file(dentry, S_IFDIR | mode);
--      if (!error) {
--              dentry->d_fsdata = cs;
--              inc_nlink(parent->d_inode);
--              cs->dentry = dentry;
--      }
--      dput(dentry);
+-static inline int
+-iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
+-{
+-      return test_bit(3, &status);
+-}
 -
--      return error;
+-static inline int
+-iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
+-{
+-      return 0;
 -}
 -
--static int cpuset_add_file(struct dentry *dir, const struct cftype *cft)
+-static inline int
+-iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
 -{
--      struct dentry *dentry;
--      int error;
+-      return 0;
+-}
 -
--      mutex_lock(&dir->d_inode->i_mutex);
--      dentry = cpuset_get_dentry(dir, cft->name);
--      if (!IS_ERR(dentry)) {
--              error = cpuset_create_file(dentry, 0644 | S_IFREG);
--              if (!error)
--                      dentry->d_fsdata = (void *)cft;
--              dput(dentry);
--      } else
--              error = PTR_ERR(dentry);
--      mutex_unlock(&dir->d_inode->i_mutex);
--      return error;
+-static inline int
+-iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
+-{
+-      return 0;
 -}
 -
+-#endif /* _ADMA_H */
+diff -Nurb linux-2.6.22-590/include/asm-arm/arch-iop13xx/iop13xx.h linux-2.6.22-570/include/asm-arm/arch-iop13xx/iop13xx.h
+--- linux-2.6.22-590/include/asm-arm/arch-iop13xx/iop13xx.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-arm/arch-iop13xx/iop13xx.h    2007-07-08 19:32:17.000000000 -0400
+@@ -166,22 +166,12 @@
+ #define IOP13XX_INIT_I2C_1          (1 << 1)
+ #define IOP13XX_INIT_I2C_2          (1 << 2)
+-/* ADMA selection flags */
+-/* INIT_ADMA_DEFAULT = Rely on CONFIG_IOP13XX_ADMA* */
+-#define IOP13XX_INIT_ADMA_DEFAULT     (0)
+-#define IOP13XX_INIT_ADMA_0           (1 << 0)
+-#define IOP13XX_INIT_ADMA_1           (1 << 1)
+-#define IOP13XX_INIT_ADMA_2           (1 << 2)
+-
+-/* Platform devices */
+ #define IQ81340_NUM_UART     2
+ #define IQ81340_NUM_I2C      3
+ #define IQ81340_NUM_PHYS_MAP_FLASH 1
+-#define IQ81340_NUM_ADMA              3
+-#define IQ81340_MAX_PLAT_DEVICES (IQ81340_NUM_UART + \
+-                              IQ81340_NUM_I2C + \
+-                              IQ81340_NUM_PHYS_MAP_FLASH + \
+-                              IQ81340_NUM_ADMA)
++#define IQ81340_MAX_PLAT_DEVICES (IQ81340_NUM_UART +\
++                              IQ81340_NUM_I2C +\
++                              IQ81340_NUM_PHYS_MAP_FLASH)
+ /*========================== PMMR offsets for key registers ============*/
+ #define IOP13XX_ATU0_PMMR_OFFSET      0x00048000
+@@ -454,6 +444,22 @@
+ /*==============================ADMA UNITS===============================*/
+ #define IOP13XX_ADMA_PHYS_BASE(chan)  IOP13XX_REG_ADDR32_PHYS((chan << 9))
+ #define IOP13XX_ADMA_UPPER_PA(chan)   (IOP13XX_ADMA_PHYS_BASE(chan) + 0xc0)
++#define IOP13XX_ADMA_OFFSET(chan, ofs)        IOP13XX_REG_ADDR32((chan << 9) + (ofs))
++
++#define IOP13XX_ADMA_ACCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x0)
++#define IOP13XX_ADMA_ACSR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x4)
++#define IOP13XX_ADMA_ADAR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x8)
++#define IOP13XX_ADMA_IIPCR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x18)
++#define IOP13XX_ADMA_IIPAR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x1c)
++#define IOP13XX_ADMA_IIPUAR(chan)    IOP13XX_ADMA_OFFSET(chan, 0x20)
++#define IOP13XX_ADMA_ANDAR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x24)
++#define IOP13XX_ADMA_ADCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x28)
++#define IOP13XX_ADMA_CARMD(chan)     IOP13XX_ADMA_OFFSET(chan, 0x2c)
++#define IOP13XX_ADMA_ABCR(chan)      IOP13XX_ADMA_OFFSET(chan, 0x30)
++#define IOP13XX_ADMA_DLADR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x34)
++#define IOP13XX_ADMA_DUADR(chan)     IOP13XX_ADMA_OFFSET(chan, 0x38)
++#define IOP13XX_ADMA_SLAR(src, chan) IOP13XX_ADMA_OFFSET(chan, 0x3c + (src <<3))
++#define IOP13XX_ADMA_SUAR(src, chan) IOP13XX_ADMA_OFFSET(chan, 0x40 + (src <<3))
+ /*==============================XSI BRIDGE===============================*/
+ #define IOP13XX_XBG_BECSR             IOP13XX_REG_ADDR32(0x178c)
+diff -Nurb linux-2.6.22-590/include/asm-arm/arch-iop32x/adma.h linux-2.6.22-570/include/asm-arm/arch-iop32x/adma.h
+--- linux-2.6.22-590/include/asm-arm/arch-iop32x/adma.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-arm/arch-iop32x/adma.h        1969-12-31 19:00:00.000000000 -0500
+@@ -1,5 +0,0 @@
+-#ifndef IOP32X_ADMA_H
+-#define IOP32X_ADMA_H
+-#include <asm/hardware/iop3xx-adma.h>
+-#endif
+-
+diff -Nurb linux-2.6.22-590/include/asm-arm/arch-iop33x/adma.h linux-2.6.22-570/include/asm-arm/arch-iop33x/adma.h
+--- linux-2.6.22-590/include/asm-arm/arch-iop33x/adma.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-arm/arch-iop33x/adma.h        1969-12-31 19:00:00.000000000 -0500
+@@ -1,5 +0,0 @@
+-#ifndef IOP33X_ADMA_H
+-#define IOP33X_ADMA_H
+-#include <asm/hardware/iop3xx-adma.h>
+-#endif
+-
+diff -Nurb linux-2.6.22-590/include/asm-arm/hardware/iop3xx-adma.h linux-2.6.22-570/include/asm-arm/hardware/iop3xx-adma.h
+--- linux-2.6.22-590/include/asm-arm/hardware/iop3xx-adma.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-arm/hardware/iop3xx-adma.h    1969-12-31 19:00:00.000000000 -0500
+@@ -1,891 +0,0 @@
 -/*
-- * Stuff for reading the 'tasks' file.
+- * Copyright Â© 2006, Intel Corporation.
 - *
-- * Reading this file can return large amounts of data if a cpuset has
-- * *lots* of attached tasks. So it may need several calls to read(),
-- * but we cannot guarantee that the information we produce is correct
-- * unless we produce it entirely atomically.
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 - *
-- * Upon tasks file open(), a struct ctr_struct is allocated, that
-- * will have a pointer to an array (also allocated here).  The struct
-- * ctr_struct * is stored in file->private_data.  Its resources will
-- * be freed by release() when the file is closed.  The array is used
-- * to sprintf the PIDs and then used by read().
 - */
+-#ifndef _ADMA_H
+-#define _ADMA_H
+-#include <linux/types.h>
+-#include <linux/io.h>
+-#include <asm/hardware.h>
+-#include <asm/hardware/iop_adma.h>
+-
+-/* Memory copy units */
+-#define DMA_CCR(chan)         (chan->mmr_base + 0x0)
+-#define DMA_CSR(chan)         (chan->mmr_base + 0x4)
+-#define DMA_DAR(chan)         (chan->mmr_base + 0xc)
+-#define DMA_NDAR(chan)                (chan->mmr_base + 0x10)
+-#define DMA_PADR(chan)                (chan->mmr_base + 0x14)
+-#define DMA_PUADR(chan)       (chan->mmr_base + 0x18)
+-#define DMA_LADR(chan)                (chan->mmr_base + 0x1c)
+-#define DMA_BCR(chan)         (chan->mmr_base + 0x20)
+-#define DMA_DCR(chan)         (chan->mmr_base + 0x24)
+-
+-/* Application accelerator unit  */
+-#define AAU_ACR(chan)         (chan->mmr_base + 0x0)
+-#define AAU_ASR(chan)         (chan->mmr_base + 0x4)
+-#define AAU_ADAR(chan)                (chan->mmr_base + 0x8)
+-#define AAU_ANDAR(chan)       (chan->mmr_base + 0xc)
+-#define AAU_SAR(src, chan)    (chan->mmr_base + (0x10 + ((src) << 2)))
+-#define AAU_DAR(chan)         (chan->mmr_base + 0x20)
+-#define AAU_ABCR(chan)                (chan->mmr_base + 0x24)
+-#define AAU_ADCR(chan)                (chan->mmr_base + 0x28)
+-#define AAU_SAR_EDCR(src_edc) (chan->mmr_base + (0x02c + ((src_edc-4) << 2)))
+-#define AAU_EDCR0_IDX 8
+-#define AAU_EDCR1_IDX 17
+-#define AAU_EDCR2_IDX 26
+-
+-#define DMA0_ID 0
+-#define DMA1_ID 1
+-#define AAU_ID 2
+-
+-struct iop3xx_aau_desc_ctrl {
+-      unsigned int int_en:1;
+-      unsigned int blk1_cmd_ctrl:3;
+-      unsigned int blk2_cmd_ctrl:3;
+-      unsigned int blk3_cmd_ctrl:3;
+-      unsigned int blk4_cmd_ctrl:3;
+-      unsigned int blk5_cmd_ctrl:3;
+-      unsigned int blk6_cmd_ctrl:3;
+-      unsigned int blk7_cmd_ctrl:3;
+-      unsigned int blk8_cmd_ctrl:3;
+-      unsigned int blk_ctrl:2;
+-      unsigned int dual_xor_en:1;
+-      unsigned int tx_complete:1;
+-      unsigned int zero_result_err:1;
+-      unsigned int zero_result_en:1;
+-      unsigned int dest_write_en:1;
+-};
 -
--/* cpusets_tasks_read array */
+-struct iop3xx_aau_e_desc_ctrl {
+-      unsigned int reserved:1;
+-      unsigned int blk1_cmd_ctrl:3;
+-      unsigned int blk2_cmd_ctrl:3;
+-      unsigned int blk3_cmd_ctrl:3;
+-      unsigned int blk4_cmd_ctrl:3;
+-      unsigned int blk5_cmd_ctrl:3;
+-      unsigned int blk6_cmd_ctrl:3;
+-      unsigned int blk7_cmd_ctrl:3;
+-      unsigned int blk8_cmd_ctrl:3;
+-      unsigned int reserved2:7;
+-};
 -
--struct ctr_struct {
--      char *buf;
--      int bufsz;
+-struct iop3xx_dma_desc_ctrl {
+-      unsigned int pci_transaction:4;
+-      unsigned int int_en:1;
+-      unsigned int dac_cycle_en:1;
+-      unsigned int mem_to_mem_en:1;
+-      unsigned int crc_data_tx_en:1;
+-      unsigned int crc_gen_en:1;
+-      unsigned int crc_seed_dis:1;
+-      unsigned int reserved:21;
+-      unsigned int crc_tx_complete:1;
 -};
 -
--/*
-- * Load into 'pidarray' up to 'npids' of the tasks using cpuset 'cs'.
-- * Return actual number of pids loaded.  No need to task_lock(p)
-- * when reading out p->cpuset, as we don't really care if it changes
-- * on the next cycle, and we are not going to try to dereference it.
-- */
--static int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs)
+-struct iop3xx_desc_dma {
+-      u32 next_desc;
+-      union {
+-              u32 pci_src_addr;
+-              u32 pci_dest_addr;
+-              u32 src_addr;
+-      };
+-      union {
+-              u32 upper_pci_src_addr;
+-              u32 upper_pci_dest_addr;
+-      };
+-      union {
+-              u32 local_pci_src_addr;
+-              u32 local_pci_dest_addr;
+-              u32 dest_addr;
+-      };
+-      u32 byte_count;
+-      union {
+-              u32 desc_ctrl;
+-              struct iop3xx_dma_desc_ctrl desc_ctrl_field;
+-      };
+-      u32 crc_addr;
+-};
+-
+-struct iop3xx_desc_aau {
+-      u32 next_desc;
+-      u32 src[4];
+-      u32 dest_addr;
+-      u32 byte_count;
+-      union {
+-              u32 desc_ctrl;
+-              struct iop3xx_aau_desc_ctrl desc_ctrl_field;
+-      };
+-      union {
+-              u32 src_addr;
+-              u32 e_desc_ctrl;
+-              struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
+-      } src_edc[31];
+-};
+-
+-struct iop3xx_aau_gfmr {
+-      unsigned int gfmr1:8;
+-      unsigned int gfmr2:8;
+-      unsigned int gfmr3:8;
+-      unsigned int gfmr4:8;
+-};
+-
+-struct iop3xx_desc_pq_xor {
+-      u32 next_desc;
+-      u32 src[3];
+-      union {
+-              u32 data_mult1;
+-              struct iop3xx_aau_gfmr data_mult1_field;
+-      };
+-      u32 dest_addr;
+-      u32 byte_count;
+-      union {
+-              u32 desc_ctrl;
+-              struct iop3xx_aau_desc_ctrl desc_ctrl_field;
+-      };
+-      union {
+-              u32 src_addr;
+-              u32 e_desc_ctrl;
+-              struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
+-              u32 data_multiplier;
+-              struct iop3xx_aau_gfmr data_mult_field;
+-              u32 reserved;
+-      } src_edc_gfmr[19];
+-};
+-
+-struct iop3xx_desc_dual_xor {
+-      u32 next_desc;
+-      u32 src0_addr;
+-      u32 src1_addr;
+-      u32 h_src_addr;
+-      u32 d_src_addr;
+-      u32 h_dest_addr;
+-      u32 byte_count;
+-      union {
+-              u32 desc_ctrl;
+-              struct iop3xx_aau_desc_ctrl desc_ctrl_field;
+-      };
+-      u32 d_dest_addr;
+-};
+-
+-union iop3xx_desc {
+-      struct iop3xx_desc_aau *aau;
+-      struct iop3xx_desc_dma *dma;
+-      struct iop3xx_desc_pq_xor *pq_xor;
+-      struct iop3xx_desc_dual_xor *dual_xor;
+-      void *ptr;
+-};
+-
+-static inline int iop_adma_get_max_xor(void)
 -{
--      int n = 0;
--      struct task_struct *g, *p;
+-      return 32;
+-}
 -
--      read_lock(&tasklist_lock);
+-static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
+-{
+-      int id = chan->device->id;
 -
--      do_each_thread(g, p) {
--              if (p->cpuset == cs) {
--                      if (unlikely(n == npids))
--                              goto array_full;
--                      pidarray[n++] = p->pid;
--              }
--      } while_each_thread(g, p);
+-      switch (id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              return __raw_readl(DMA_DAR(chan));
+-      case AAU_ID:
+-              return __raw_readl(AAU_ADAR(chan));
+-      default:
+-              BUG();
+-      }
+-      return 0;
+-}
+-
+-static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
+-                                              u32 next_desc_addr)
+-{
+-      int id = chan->device->id;
+-
+-      switch (id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              __raw_writel(next_desc_addr, DMA_NDAR(chan));
+-              break;
+-      case AAU_ID:
+-              __raw_writel(next_desc_addr, AAU_ANDAR(chan));
+-              break;
+-      }
 -
--array_full:
--      read_unlock(&tasklist_lock);
--      return n;
 -}
 -
--static int cmppid(const void *a, const void *b)
+-#define IOP_ADMA_STATUS_BUSY (1 << 10)
+-#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT (1024)
+-#define IOP_ADMA_XOR_MAX_BYTE_COUNT (16 * 1024 * 1024)
+-#define IOP_ADMA_MAX_BYTE_COUNT (16 * 1024 * 1024)
+-
+-static inline int iop_chan_is_busy(struct iop_adma_chan *chan)
 -{
--      return *(pid_t *)a - *(pid_t *)b;
+-      u32 status = __raw_readl(DMA_CSR(chan));
+-      return (status & IOP_ADMA_STATUS_BUSY) ? 1 : 0;
 -}
 -
--/*
-- * Convert array 'a' of 'npids' pid_t's to a string of newline separated
-- * decimal pids in 'buf'.  Don't write more than 'sz' chars, but return
-- * count 'cnt' of how many chars would be written if buf were large enough.
-- */
--static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids)
+-static inline int iop_desc_is_aligned(struct iop_adma_desc_slot *desc,
+-                                      int num_slots)
 -{
--      int cnt = 0;
--      int i;
+-      /* num_slots will only ever be 1, 2, 4, or 8 */
+-      return (desc->idx & (num_slots - 1)) ? 0 : 1;
+-}
 -
--      for (i = 0; i < npids; i++)
--              cnt += snprintf(buf + cnt, max(sz - cnt, 0), "%d\n", a[i]);
--      return cnt;
+-/* to do: support large (i.e. > hw max) buffer sizes */
+-static inline int iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
+-{
+-      *slots_per_op = 1;
+-      return 1;
 -}
 -
--/*
-- * Handle an open on 'tasks' file.  Prepare a buffer listing the
-- * process id's of tasks currently attached to the cpuset being opened.
-- *
-- * Does not require any specific cpuset mutexes, and does not take any.
+-/* to do: support large (i.e. > hw max) buffer sizes */
+-static inline int iop_chan_memset_slot_count(size_t len, int *slots_per_op)
+-{
+-      *slots_per_op = 1;
+-      return 1;
+-}
+-
+-static inline int iop3xx_aau_xor_slot_count(size_t len, int src_cnt,
+-                                      int *slots_per_op)
+-{
+-      const static int slot_count_table[] = { 0,
+-                                              1, 1, 1, 1, /* 01 - 04 */
+-                                              2, 2, 2, 2, /* 05 - 08 */
+-                                              4, 4, 4, 4, /* 09 - 12 */
+-                                              4, 4, 4, 4, /* 13 - 16 */
+-                                              8, 8, 8, 8, /* 17 - 20 */
+-                                              8, 8, 8, 8, /* 21 - 24 */
+-                                              8, 8, 8, 8, /* 25 - 28 */
+-                                              8, 8, 8, 8, /* 29 - 32 */
+-                                            };
+-      *slots_per_op = slot_count_table[src_cnt];
+-      return *slots_per_op;
+-}
+-
+-static inline int
+-iop_chan_interrupt_slot_count(int *slots_per_op, struct iop_adma_chan *chan)
+-{
+-      switch (chan->device->id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              return iop_chan_memcpy_slot_count(0, slots_per_op);
+-      case AAU_ID:
+-              return iop3xx_aau_xor_slot_count(0, 2, slots_per_op);
+-      default:
+-              BUG();
+-      }
+-      return 0;
+-}
+-
+-static inline int iop_chan_xor_slot_count(size_t len, int src_cnt,
+-                                              int *slots_per_op)
+-{
+-      int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
+-
+-      if (len <= IOP_ADMA_XOR_MAX_BYTE_COUNT)
+-              return slot_cnt;
+-
+-      len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
+-      while (len > IOP_ADMA_XOR_MAX_BYTE_COUNT) {
+-              len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
+-              slot_cnt += *slots_per_op;
+-      }
+-
+-      if (len)
+-              slot_cnt += *slots_per_op;
+-
+-      return slot_cnt;
+-}
+-
+-/* zero sum on iop3xx is limited to 1k at a time so it requires multiple
+- * descriptors
 - */
--static int cpuset_tasks_open(struct inode *unused, struct file *file)
+-static inline int iop_chan_zero_sum_slot_count(size_t len, int src_cnt,
+-                                              int *slots_per_op)
 -{
--      struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
--      struct ctr_struct *ctr;
--      pid_t *pidarray;
--      int npids;
--      char c;
+-      int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
 -
--      if (!(file->f_mode & FMODE_READ))
--              return 0;
+-      if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT)
+-              return slot_cnt;
 -
--      ctr = kmalloc(sizeof(*ctr), GFP_KERNEL);
--      if (!ctr)
--              goto err0;
+-      len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+-      while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+-              len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+-              slot_cnt += *slots_per_op;
+-      }
 -
--      /*
--       * If cpuset gets more users after we read count, we won't have
--       * enough space - tough.  This race is indistinguishable to the
--       * caller from the case that the additional cpuset users didn't
--       * show up until sometime later on.
--       */
--      npids = atomic_read(&cs->count);
--      pidarray = kmalloc(npids * sizeof(pid_t), GFP_KERNEL);
--      if (!pidarray)
--              goto err1;
+-      if (len)
+-              slot_cnt += *slots_per_op;
 -
--      npids = pid_array_load(pidarray, npids, cs);
--      sort(pidarray, npids, sizeof(pid_t), cmppid, NULL);
+-      return slot_cnt;
+-}
 -
--      /* Call pid_array_to_buf() twice, first just to get bufsz */
--      ctr->bufsz = pid_array_to_buf(&c, sizeof(c), pidarray, npids) + 1;
--      ctr->buf = kmalloc(ctr->bufsz, GFP_KERNEL);
--      if (!ctr->buf)
--              goto err2;
--      ctr->bufsz = pid_array_to_buf(ctr->buf, ctr->bufsz, pidarray, npids);
+-static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc,
+-                                      struct iop_adma_chan *chan)
+-{
+-      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
 -
--      kfree(pidarray);
--      file->private_data = ctr;
+-      switch (chan->device->id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              return hw_desc.dma->dest_addr;
+-      case AAU_ID:
+-              return hw_desc.aau->dest_addr;
+-      default:
+-              BUG();
+-      }
 -      return 0;
+-}
 -
--err2:
--      kfree(pidarray);
--err1:
--      kfree(ctr);
--err0:
--      return -ENOMEM;
+-static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
+-                                      struct iop_adma_chan *chan)
+-{
+-      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+-
+-      switch (chan->device->id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              return hw_desc.dma->byte_count;
+-      case AAU_ID:
+-              return hw_desc.aau->byte_count;
+-      default:
+-              BUG();
+-      }
+-      return 0;
 -}
 -
--static ssize_t cpuset_tasks_read(struct file *file, char __user *buf,
--                                              size_t nbytes, loff_t *ppos)
+-/* translate the src_idx to a descriptor word index */
+-static inline int __desc_idx(int src_idx)
 -{
--      struct ctr_struct *ctr = file->private_data;
--      return simple_read_from_buffer(buf, nbytes, ppos, ctr->buf, ctr->bufsz);
+-      const static int desc_idx_table[] = { 0, 0, 0, 0,
+-                                            0, 1, 2, 3,
+-                                            5, 6, 7, 8,
+-                                            9, 10, 11, 12,
+-                                            14, 15, 16, 17,
+-                                            18, 19, 20, 21,
+-                                            23, 24, 25, 26,
+-                                            27, 28, 29, 30,
+-                                          };
+-
+-      return desc_idx_table[src_idx];
 -}
--static int cpuset_tasks_release(struct inode *unused_inode, struct file *file)
+-
+-static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
+-                                      struct iop_adma_chan *chan,
+-                                      int src_idx)
 -{
--      struct ctr_struct *ctr;
--      if (file->f_mode & FMODE_READ) {
--              ctr = file->private_data;
--              kfree(ctr->buf);
--              kfree(ctr);
+-      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+-
+-      switch (chan->device->id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              return hw_desc.dma->src_addr;
+-      case AAU_ID:
+-              break;
+-      default:
+-              BUG();
 -      }
--      return 0;
+-
+-      if (src_idx < 4)
+-              return hw_desc.aau->src[src_idx];
+-      else
+-              return hw_desc.aau->src_edc[__desc_idx(src_idx)].src_addr;
 -}
- /*
-  * for the common functions, 'private' gives the type of file
-  */
--static struct cftype cft_tasks = {
--      .name = "tasks",
--      .open = cpuset_tasks_open,
--      .read = cpuset_tasks_read,
--      .release = cpuset_tasks_release,
--      .private = FILE_TASKLIST,
--};
 -
- static struct cftype cft_cpus = {
-       .name = "cpus",
-+      .read = cpuset_common_file_read,
-+      .write = cpuset_common_file_write,
-       .private = FILE_CPULIST,
- };
- static struct cftype cft_mems = {
-       .name = "mems",
-+      .read = cpuset_common_file_read,
-+      .write = cpuset_common_file_write,
-       .private = FILE_MEMLIST,
- };
- static struct cftype cft_cpu_exclusive = {
-       .name = "cpu_exclusive",
-+      .read = cpuset_common_file_read,
-+      .write = cpuset_common_file_write,
-       .private = FILE_CPU_EXCLUSIVE,
- };
- static struct cftype cft_mem_exclusive = {
-       .name = "mem_exclusive",
-+      .read = cpuset_common_file_read,
-+      .write = cpuset_common_file_write,
-       .private = FILE_MEM_EXCLUSIVE,
- };
--static struct cftype cft_notify_on_release = {
--      .name = "notify_on_release",
--      .private = FILE_NOTIFY_ON_RELEASE,
--};
+-static inline void iop3xx_aau_desc_set_src_addr(struct iop3xx_desc_aau *hw_desc,
+-                                      int src_idx, dma_addr_t addr)
+-{
+-      if (src_idx < 4)
+-              hw_desc->src[src_idx] = addr;
+-      else
+-              hw_desc->src_edc[__desc_idx(src_idx)].src_addr = addr;
+-}
 -
- static struct cftype cft_memory_migrate = {
-       .name = "memory_migrate",
-+      .read = cpuset_common_file_read,
-+      .write = cpuset_common_file_write,
-       .private = FILE_MEMORY_MIGRATE,
- };
- static struct cftype cft_memory_pressure_enabled = {
-       .name = "memory_pressure_enabled",
-+      .read = cpuset_common_file_read,
-+      .write = cpuset_common_file_write,
-       .private = FILE_MEMORY_PRESSURE_ENABLED,
- };
- static struct cftype cft_memory_pressure = {
-       .name = "memory_pressure",
-+      .read = cpuset_common_file_read,
-+      .write = cpuset_common_file_write,
-       .private = FILE_MEMORY_PRESSURE,
- };
- static struct cftype cft_spread_page = {
-       .name = "memory_spread_page",
-+      .read = cpuset_common_file_read,
-+      .write = cpuset_common_file_write,
-       .private = FILE_SPREAD_PAGE,
- };
- static struct cftype cft_spread_slab = {
-       .name = "memory_spread_slab",
-+      .read = cpuset_common_file_read,
-+      .write = cpuset_common_file_write,
-       .private = FILE_SPREAD_SLAB,
- };
--static int cpuset_populate_dir(struct dentry *cs_dentry)
-+int cpuset_populate(struct container_subsys *ss, struct container *cont)
- {
-       int err;
--      if ((err = cpuset_add_file(cs_dentry, &cft_cpus)) < 0)
-+      if ((err = container_add_file(cont, &cft_cpus)) < 0)
-               return err;
--      if ((err = cpuset_add_file(cs_dentry, &cft_mems)) < 0)
-+      if ((err = container_add_file(cont, &cft_mems)) < 0)
-               return err;
--      if ((err = cpuset_add_file(cs_dentry, &cft_cpu_exclusive)) < 0)
-+      if ((err = container_add_file(cont, &cft_cpu_exclusive)) < 0)
-               return err;
--      if ((err = cpuset_add_file(cs_dentry, &cft_mem_exclusive)) < 0)
-+      if ((err = container_add_file(cont, &cft_mem_exclusive)) < 0)
-               return err;
--      if ((err = cpuset_add_file(cs_dentry, &cft_notify_on_release)) < 0)
-+      if ((err = container_add_file(cont, &cft_memory_migrate)) < 0)
-               return err;
--      if ((err = cpuset_add_file(cs_dentry, &cft_memory_migrate)) < 0)
-+      if ((err = container_add_file(cont, &cft_memory_pressure)) < 0)
-               return err;
--      if ((err = cpuset_add_file(cs_dentry, &cft_memory_pressure)) < 0)
-+      if ((err = container_add_file(cont, &cft_spread_page)) < 0)
-               return err;
--      if ((err = cpuset_add_file(cs_dentry, &cft_spread_page)) < 0)
--              return err;
--      if ((err = cpuset_add_file(cs_dentry, &cft_spread_slab)) < 0)
--              return err;
--      if ((err = cpuset_add_file(cs_dentry, &cft_tasks)) < 0)
-+      if ((err = container_add_file(cont, &cft_spread_slab)) < 0)
-               return err;
-+      /* memory_pressure_enabled is in root cpuset only */
-+      if (err == 0 && !cont->parent)
-+              err = container_add_file(cont, &cft_memory_pressure_enabled);
-       return 0;
- }
- /*
-+ * post_clone() is called at the end of container_clone().
-+ * 'container' was just created automatically as a result of
-+ * a container_clone(), and the current task is about to
-+ * be moved into 'container'.
-+ *
-+ * Currently we refuse to set up the container - thereby
-+ * refusing the task to be entered, and as a result refusing
-+ * the sys_unshare() or clone() which initiated it - if any
-+ * sibling cpusets have exclusive cpus or mem.
-+ *
-+ * If this becomes a problem for some users who wish to
-+ * allow that scenario, then cpuset_post_clone() could be
-+ * changed to grant parent->cpus_allowed-sibling_cpus_exclusive
-+ * (and likewise for mems) to the new container.
-+ */
-+void cpuset_post_clone(struct container_subsys *ss,
-+              struct container *container)
-+{
-+      struct container *parent, *child;
-+      struct cpuset *cs, *parent_cs;
-+
-+      parent = container->parent;
-+      list_for_each_entry(child, &parent->children, sibling) {
-+              cs = container_cs(child);
-+              if (is_mem_exclusive(cs) || is_cpu_exclusive(cs))
-+                      return;
-+      }
-+      cs = container_cs(container);
-+      parent_cs = container_cs(parent);
-+
-+      cs->mems_allowed = parent_cs->mems_allowed;
-+      cs->cpus_allowed = parent_cs->cpus_allowed;
-+      return;
-+}
-+
-+/*
-  *    cpuset_create - create a cpuset
-  *    parent: cpuset that will be parent of the new cpuset.
-  *    name:           name of the new cpuset. Will be strcpy'ed.
-@@ -1885,124 +1234,62 @@
-  *    Must be called with the mutex on the parent inode held
-  */
--static long cpuset_create(struct cpuset *parent, const char *name, int mode)
-+int cpuset_create(struct container_subsys *ss, struct container *cont)
- {
-       struct cpuset *cs;
--      int err;
-+      struct cpuset *parent;
-+      if (!cont->parent) {
-+              /* This is early initialization for the top container */
-+              set_container_cs(cont, &top_cpuset);
-+              top_cpuset.css.container = cont;
-+              top_cpuset.mems_generation = cpuset_mems_generation++;
-+              return 0;
-+      }
-+      parent = container_cs(cont->parent);
-       cs = kmalloc(sizeof(*cs), GFP_KERNEL);
-       if (!cs)
-               return -ENOMEM;
--      mutex_lock(&manage_mutex);
-       cpuset_update_task_memory_state();
-       cs->flags = 0;
--      if (notify_on_release(parent))
--              set_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
-       if (is_spread_page(parent))
-               set_bit(CS_SPREAD_PAGE, &cs->flags);
-       if (is_spread_slab(parent))
-               set_bit(CS_SPREAD_SLAB, &cs->flags);
-       cs->cpus_allowed = CPU_MASK_NONE;
-       cs->mems_allowed = NODE_MASK_NONE;
--      atomic_set(&cs->count, 0);
--      INIT_LIST_HEAD(&cs->sibling);
--      INIT_LIST_HEAD(&cs->children);
-       cs->mems_generation = cpuset_mems_generation++;
-       fmeter_init(&cs->fmeter);
-       cs->parent = parent;
+-static inline void
+-iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en)
+-{
+-      struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
+-      union {
+-              u32 value;
+-              struct iop3xx_dma_desc_ctrl field;
+-      } u_desc_ctrl;
+-
+-      u_desc_ctrl.value = 0;
+-      u_desc_ctrl.field.mem_to_mem_en = 1;
+-      u_desc_ctrl.field.pci_transaction = 0xe; /* memory read block */
+-      u_desc_ctrl.field.int_en = int_en;
+-      hw_desc->desc_ctrl = u_desc_ctrl.value;
+-      hw_desc->upper_pci_src_addr = 0;
+-      hw_desc->crc_addr = 0;
+-}
+-
+-static inline void
+-iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en)
+-{
+-      struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+-      union {
+-              u32 value;
+-              struct iop3xx_aau_desc_ctrl field;
+-      } u_desc_ctrl;
+-
+-      u_desc_ctrl.value = 0;
+-      u_desc_ctrl.field.blk1_cmd_ctrl = 0x2; /* memory block fill */
+-      u_desc_ctrl.field.dest_write_en = 1;
+-      u_desc_ctrl.field.int_en = int_en;
+-      hw_desc->desc_ctrl = u_desc_ctrl.value;
+-}
+-
+-static inline u32
+-iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt, int int_en)
+-{
+-      int i, shift;
+-      u32 edcr;
+-      union {
+-              u32 value;
+-              struct iop3xx_aau_desc_ctrl field;
+-      } u_desc_ctrl;
+-
+-      u_desc_ctrl.value = 0;
+-      switch (src_cnt) {
+-      case 25 ... 32:
+-              u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+-              edcr = 0;
+-              shift = 1;
+-              for (i = 24; i < src_cnt; i++) {
+-                      edcr |= (1 << shift);
+-                      shift += 3;
+-              }
+-              hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = edcr;
+-              src_cnt = 24;
+-              /* fall through */
+-      case 17 ... 24:
+-              if (!u_desc_ctrl.field.blk_ctrl) {
+-                      hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
+-                      u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+-              }
+-              edcr = 0;
+-              shift = 1;
+-              for (i = 16; i < src_cnt; i++) {
+-                      edcr |= (1 << shift);
+-                      shift += 3;
+-              }
+-              hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = edcr;
+-              src_cnt = 16;
+-              /* fall through */
+-      case 9 ... 16:
+-              if (!u_desc_ctrl.field.blk_ctrl)
+-                      u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
+-              edcr = 0;
+-              shift = 1;
+-              for (i = 8; i < src_cnt; i++) {
+-                      edcr |= (1 << shift);
+-                      shift += 3;
+-              }
+-              hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = edcr;
+-              src_cnt = 8;
+-              /* fall through */
+-      case 2 ... 8:
+-              shift = 1;
+-              for (i = 0; i < src_cnt; i++) {
+-                      u_desc_ctrl.value |= (1 << shift);
+-                      shift += 3;
+-              }
+-
+-              if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
+-                      u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
+-      }
+-
+-      u_desc_ctrl.field.dest_write_en = 1;
+-      u_desc_ctrl.field.blk1_cmd_ctrl = 0x7; /* direct fill */
+-      u_desc_ctrl.field.int_en = int_en;
+-      hw_desc->desc_ctrl = u_desc_ctrl.value;
+-
+-      return u_desc_ctrl.value;
+-}
+-
+-static inline void
+-iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+-{
+-      iop3xx_desc_init_xor(desc->hw_desc, src_cnt, int_en);
+-}
+-
+-/* return the number of operations */
+-static inline int
+-iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+-{
+-      int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+-      struct iop3xx_desc_aau *hw_desc, *prev_hw_desc, *iter;
+-      union {
+-              u32 value;
+-              struct iop3xx_aau_desc_ctrl field;
+-      } u_desc_ctrl;
+-      int i, j;
+-
+-      hw_desc = desc->hw_desc;
+-
+-      for (i = 0, j = 0; (slot_cnt -= slots_per_op) >= 0;
+-              i += slots_per_op, j++) {
+-              iter = iop_hw_desc_slot_idx(hw_desc, i);
+-              u_desc_ctrl.value = iop3xx_desc_init_xor(iter, src_cnt, int_en);
+-              u_desc_ctrl.field.dest_write_en = 0;
+-              u_desc_ctrl.field.zero_result_en = 1;
+-              u_desc_ctrl.field.int_en = int_en;
+-              iter->desc_ctrl = u_desc_ctrl.value;
+-
+-              /* for the subsequent descriptors preserve the store queue
+-               * and chain them together
+-               */
+-              if (i) {
+-                      prev_hw_desc =
+-                              iop_hw_desc_slot_idx(hw_desc, i - slots_per_op);
+-                      prev_hw_desc->next_desc = (u32) (desc->phys + (i << 5));
+-              }
+-      }
+-
+-      return j;
+-}
+-
+-static inline void
+-iop_desc_init_null_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+-{
+-      struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+-      union {
+-              u32 value;
+-              struct iop3xx_aau_desc_ctrl field;
+-      } u_desc_ctrl;
+-
+-      u_desc_ctrl.value = 0;
+-      switch (src_cnt) {
+-      case 25 ... 32:
+-              u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+-              hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
+-              /* fall through */
+-      case 17 ... 24:
+-              if (!u_desc_ctrl.field.blk_ctrl) {
+-                      hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
+-                      u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+-              }
+-              hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = 0;
+-              /* fall through */
+-      case 9 ... 16:
+-              if (!u_desc_ctrl.field.blk_ctrl)
+-                      u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
+-              hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = 0;
+-              /* fall through */
+-      case 1 ... 8:
+-              if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
+-                      u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
+-      }
 -
--      mutex_lock(&callback_mutex);
--      list_add(&cs->sibling, &cs->parent->children);
-+      set_container_cs(cont, cs);
-+      cs->css.container = cont;
-       number_of_cpusets++;
--      mutex_unlock(&callback_mutex);
+-      u_desc_ctrl.field.dest_write_en = 0;
+-      u_desc_ctrl.field.int_en = int_en;
+-      hw_desc->desc_ctrl = u_desc_ctrl.value;
+-}
 -
--      err = cpuset_create_dir(cs, name, mode);
--      if (err < 0)
--              goto err;
+-static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
+-                                      struct iop_adma_chan *chan,
+-                                      u32 byte_count)
+-{
+-      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
 -
--      /*
--       * Release manage_mutex before cpuset_populate_dir() because it
--       * will down() this new directory's i_mutex and if we race with
--       * another mkdir, we might deadlock.
--       */
--      mutex_unlock(&manage_mutex);
+-      switch (chan->device->id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              hw_desc.dma->byte_count = byte_count;
+-              break;
+-      case AAU_ID:
+-              hw_desc.aau->byte_count = byte_count;
+-              break;
+-      default:
+-              BUG();
+-      }
+-}
 -
--      err = cpuset_populate_dir(cs->dentry);
--      /* If err < 0, we have a half-filled directory - oh well ;) */
-       return 0;
--err:
--      list_del(&cs->sibling);
--      mutex_unlock(&manage_mutex);
--      kfree(cs);
--      return err;
+-static inline void
+-iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
+-                      struct iop_adma_chan *chan)
+-{
+-      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+-
+-      switch (chan->device->id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              iop_desc_init_memcpy(desc, 1);
+-              hw_desc.dma->byte_count = 0;
+-              hw_desc.dma->dest_addr = 0;
+-              hw_desc.dma->src_addr = 0;
+-              break;
+-      case AAU_ID:
+-              iop_desc_init_null_xor(desc, 2, 1);
+-              hw_desc.aau->byte_count = 0;
+-              hw_desc.aau->dest_addr = 0;
+-              hw_desc.aau->src[0] = 0;
+-              hw_desc.aau->src[1] = 0;
+-              break;
+-      default:
+-              BUG();
+-      }
 -}
 -
--static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+-static inline void
+-iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
 -{
--      struct cpuset *c_parent = dentry->d_parent->d_fsdata;
+-      int slots_per_op = desc->slots_per_op;
+-      struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
+-      int i = 0;
 -
--      /* the vfs holds inode->i_mutex already */
--      return cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR);
- }
--/*
-- * Locking note on the strange update_flag() call below:
-- *
-- * If the cpuset being removed is marked cpu_exclusive, then simulate
-- * turning cpu_exclusive off, which will call update_cpu_domains().
-- * The lock_cpu_hotplug() call in update_cpu_domains() must not be
-- * made while holding callback_mutex.  Elsewhere the kernel nests
-- * callback_mutex inside lock_cpu_hotplug() calls.  So the reverse
-- * nesting would risk an ABBA deadlock.
-- */
+-      if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+-              hw_desc->byte_count = len;
+-      } else {
+-              do {
+-                      iter = iop_hw_desc_slot_idx(hw_desc, i);
+-                      iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+-                      len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+-                      i += slots_per_op;
+-              } while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
 -
--static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
-+void cpuset_destroy(struct container_subsys *ss, struct container *cont)
- {
--      struct cpuset *cs = dentry->d_fsdata;
--      struct dentry *d;
--      struct cpuset *parent;
--      char *pathbuf = NULL;
+-              if (len) {
+-                      iter = iop_hw_desc_slot_idx(hw_desc, i);
+-                      iter->byte_count = len;
+-              }
+-      }
+-}
 -
--      /* the vfs holds both inode->i_mutex already */
-+      struct cpuset *cs = container_cs(cont);
--      mutex_lock(&manage_mutex);
-       cpuset_update_task_memory_state();
--      if (atomic_read(&cs->count) > 0) {
--              mutex_unlock(&manage_mutex);
--              return -EBUSY;
+-static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
+-                                      struct iop_adma_chan *chan,
+-                                      dma_addr_t addr)
+-{
+-      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+-
+-      switch (chan->device->id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              hw_desc.dma->dest_addr = addr;
+-              break;
+-      case AAU_ID:
+-              hw_desc.aau->dest_addr = addr;
+-              break;
+-      default:
+-              BUG();
 -      }
--      if (!list_empty(&cs->children)) {
--              mutex_unlock(&manage_mutex);
--              return -EBUSY;
+-}
+-
+-static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
+-                                      dma_addr_t addr)
+-{
+-      struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
+-      hw_desc->src_addr = addr;
+-}
+-
+-static inline void
+-iop_desc_set_zero_sum_src_addr(struct iop_adma_desc_slot *desc, int src_idx,
+-                              dma_addr_t addr)
+-{
+-
+-      struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
+-      int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+-      int i;
+-
+-      for (i = 0; (slot_cnt -= slots_per_op) >= 0;
+-              i += slots_per_op, addr += IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+-              iter = iop_hw_desc_slot_idx(hw_desc, i);
+-              iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
 -      }
--      if (is_cpu_exclusive(cs)) {
--              int retval = update_flag(CS_CPU_EXCLUSIVE, cs, "0");
--              if (retval < 0) {
--                      mutex_unlock(&manage_mutex);
--                      return retval;
--              }
+-}
+-
+-static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
+-                                      int src_idx, dma_addr_t addr)
+-{
+-
+-      struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
+-      int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+-      int i;
+-
+-      for (i = 0; (slot_cnt -= slots_per_op) >= 0;
+-              i += slots_per_op, addr += IOP_ADMA_XOR_MAX_BYTE_COUNT) {
+-              iter = iop_hw_desc_slot_idx(hw_desc, i);
+-              iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
 -      }
--      parent = cs->parent;
--      mutex_lock(&callback_mutex);
--      set_bit(CS_REMOVED, &cs->flags);
--      list_del(&cs->sibling); /* delete my sibling from parent->children */
--      spin_lock(&cs->dentry->d_lock);
--      d = dget(cs->dentry);
--      cs->dentry = NULL;
--      spin_unlock(&d->d_lock);
--      cpuset_d_remove_dir(d);
--      dput(d);
-       number_of_cpusets--;
--      mutex_unlock(&callback_mutex);
--      if (list_empty(&parent->children))
--              check_for_release(parent, &pathbuf);
--      mutex_unlock(&manage_mutex);
--      cpuset_release_agent(pathbuf);
+-}
+-
+-static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
+-                                      u32 next_desc_addr)
+-{
+-      /* hw_desc->next_desc is the same location for all channels */
+-      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+-      BUG_ON(hw_desc.dma->next_desc);
+-      hw_desc.dma->next_desc = next_desc_addr;
+-}
+-
+-static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
+-{
+-      /* hw_desc->next_desc is the same location for all channels */
+-      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+-      return hw_desc.dma->next_desc;
+-}
+-
+-static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
+-{
+-      /* hw_desc->next_desc is the same location for all channels */
+-      union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+-      hw_desc.dma->next_desc = 0;
+-}
+-
+-static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
+-                                              u32 val)
+-{
+-      struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+-      hw_desc->src[0] = val;
+-}
+-
+-static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
+-{
+-      struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+-      struct iop3xx_aau_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
+-
+-      BUG_ON(!(desc_ctrl.tx_complete && desc_ctrl.zero_result_en));
+-      return desc_ctrl.zero_result_err;
+-}
+-
+-static inline void iop_chan_append(struct iop_adma_chan *chan)
+-{
+-      u32 dma_chan_ctrl;
+-      /* workaround dropped interrupts on 3xx */
+-      mod_timer(&chan->cleanup_watchdog, jiffies + msecs_to_jiffies(3));
+-
+-      dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+-      dma_chan_ctrl |= 0x2;
+-      __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+-}
+-
+-static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
+-{
+-      if (!busy)
+-              del_timer(&chan->cleanup_watchdog);
+-}
+-
+-static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
+-{
+-      return __raw_readl(DMA_CSR(chan));
+-}
+-
+-static inline void iop_chan_disable(struct iop_adma_chan *chan)
+-{
+-      u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+-      dma_chan_ctrl &= ~1;
+-      __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+-}
+-
+-static inline void iop_chan_enable(struct iop_adma_chan *chan)
+-{
+-      u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+-
+-      dma_chan_ctrl |= 1;
+-      __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+-}
+-
+-static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
+-{
+-      u32 status = __raw_readl(DMA_CSR(chan));
+-      status &= (1 << 9);
+-      __raw_writel(status, DMA_CSR(chan));
+-}
+-
+-static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
+-{
+-      u32 status = __raw_readl(DMA_CSR(chan));
+-      status &= (1 << 8);
+-      __raw_writel(status, DMA_CSR(chan));
+-}
+-
+-static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
+-{
+-      u32 status = __raw_readl(DMA_CSR(chan));
+-
+-      switch (chan->device->id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              status &= (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1);
+-              break;
+-      case AAU_ID:
+-              status &= (1 << 5);
+-              break;
+-      default:
+-              BUG();
+-      }
+-
+-      __raw_writel(status, DMA_CSR(chan));
+-}
+-
+-static inline int
+-iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
+-{
 -      return 0;
-+      kfree(cs);
- }
-+struct container_subsys cpuset_subsys = {
-+      .name = "cpuset",
-+      .create = cpuset_create,
-+      .destroy  = cpuset_destroy,
-+      .can_attach = cpuset_can_attach,
-+      .attach = cpuset_attach,
-+      .populate = cpuset_populate,
-+      .post_clone = cpuset_post_clone,
-+      .subsys_id = cpuset_subsys_id,
-+      .early_init = 1,
-+};
-+
- /*
-  * cpuset_init_early - just enough so that the calls to
-  * cpuset_update_task_memory_state() in early init code
-@@ -2011,13 +1298,11 @@
- int __init cpuset_init_early(void)
- {
--      struct task_struct *tsk = current;
+-}
 -
--      tsk->cpuset = &top_cpuset;
--      tsk->cpuset->mems_generation = cpuset_mems_generation++;
-+      top_cpuset.mems_generation = cpuset_mems_generation++;
-       return 0;
- }
-+
- /**
-  * cpuset_init - initialize cpusets at system boot
-  *
-@@ -2026,8 +1311,7 @@
- int __init cpuset_init(void)
- {
--      struct dentry *root;
--      int err;
-+      int err = 0;
-       top_cpuset.cpus_allowed = CPU_MASK_ALL;
-       top_cpuset.mems_allowed = NODE_MASK_ALL;
-@@ -2035,30 +1319,12 @@
-       fmeter_init(&top_cpuset.fmeter);
-       top_cpuset.mems_generation = cpuset_mems_generation++;
--      init_task.cpuset = &top_cpuset;
+-static inline int
+-iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
+-{
+-      return 0;
+-}
 -
-       err = register_filesystem(&cpuset_fs_type);
-       if (err < 0)
--              goto out;
--      cpuset_mount = kern_mount(&cpuset_fs_type);
--      if (IS_ERR(cpuset_mount)) {
--              printk(KERN_ERR "cpuset: could not mount!\n");
--              err = PTR_ERR(cpuset_mount);
--              cpuset_mount = NULL;
--              goto out;
+-static inline int
+-iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
+-{
+-      return 0;
+-}
+-
+-static inline int
+-iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
+-{
+-      return test_bit(5, &status);
+-}
+-
+-static inline int
+-iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
+-{
+-      switch (chan->device->id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              return test_bit(2, &status);
+-      default:
+-              return 0;
 -      }
--      root = cpuset_mount->mnt_sb->s_root;
--      root->d_fsdata = &top_cpuset;
--      inc_nlink(root->d_inode);
--      top_cpuset.dentry = root;
--      root->d_inode->i_op = &cpuset_dir_inode_operations;
--      number_of_cpusets = 1;
--      err = cpuset_populate_dir(root);
--      /* memory_pressure_enabled is in root cpuset only */
--      if (err == 0)
--              err = cpuset_add_file(root, &cft_memory_pressure_enabled);
--out:
-       return err;
-+
-+      number_of_cpusets = 1;
-+      return 0;
- }
- /*
-@@ -2084,10 +1350,12 @@
- static void guarantee_online_cpus_mems_in_subtree(const struct cpuset *cur)
- {
-+      struct container *cont;
-       struct cpuset *c;
+-}
+-
+-static inline int
+-iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
+-{
+-      switch (chan->device->id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              return test_bit(3, &status);
+-      default:
+-              return 0;
+-      }
+-}
+-
+-static inline int
+-iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
+-{
+-      switch (chan->device->id) {
+-      case DMA0_ID:
+-      case DMA1_ID:
+-              return test_bit(1, &status);
+-      default:
+-              return 0;
+-      }
+-}
+-#endif /* _ADMA_H */
+diff -Nurb linux-2.6.22-590/include/asm-arm/hardware/iop3xx.h linux-2.6.22-570/include/asm-arm/hardware/iop3xx.h
+--- linux-2.6.22-590/include/asm-arm/hardware/iop3xx.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-arm/hardware/iop3xx.h 2007-07-08 19:32:17.000000000 -0400
+@@ -144,9 +144,24 @@
+ #define IOP3XX_IAR            (volatile u32 *)IOP3XX_REG_ADDR(0x0380)
  
-       /* Each of our child cpusets mems must be online */
--      list_for_each_entry(c, &cur->children, sibling) {
-+      list_for_each_entry(cont, &cur->css.container->children, sibling) {
-+              c = container_cs(cont);
-               guarantee_online_cpus_mems_in_subtree(c);
-               if (!cpus_empty(c->cpus_allowed))
-                       guarantee_online_cpus(c, &c->cpus_allowed);
-@@ -2114,7 +1382,7 @@
+ /* DMA Controller  */
+-#define IOP3XX_DMA_PHYS_BASE(chan) (IOP3XX_PERIPHERAL_PHYS_BASE + \
+-                                      (0x400 + (chan << 6)))
+-#define IOP3XX_DMA_UPPER_PA(chan)  (IOP3XX_DMA_PHYS_BASE(chan) + 0x27)
++#define IOP3XX_DMA0_CCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0400)
++#define IOP3XX_DMA0_CSR               (volatile u32 *)IOP3XX_REG_ADDR(0x0404)
++#define IOP3XX_DMA0_DAR               (volatile u32 *)IOP3XX_REG_ADDR(0x040c)
++#define IOP3XX_DMA0_NDAR      (volatile u32 *)IOP3XX_REG_ADDR(0x0410)
++#define IOP3XX_DMA0_PADR      (volatile u32 *)IOP3XX_REG_ADDR(0x0414)
++#define IOP3XX_DMA0_PUADR     (volatile u32 *)IOP3XX_REG_ADDR(0x0418)
++#define IOP3XX_DMA0_LADR      (volatile u32 *)IOP3XX_REG_ADDR(0x041c)
++#define IOP3XX_DMA0_BCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0420)
++#define IOP3XX_DMA0_DCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0424)
++#define IOP3XX_DMA1_CCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0440)
++#define IOP3XX_DMA1_CSR               (volatile u32 *)IOP3XX_REG_ADDR(0x0444)
++#define IOP3XX_DMA1_DAR               (volatile u32 *)IOP3XX_REG_ADDR(0x044c)
++#define IOP3XX_DMA1_NDAR      (volatile u32 *)IOP3XX_REG_ADDR(0x0450)
++#define IOP3XX_DMA1_PADR      (volatile u32 *)IOP3XX_REG_ADDR(0x0454)
++#define IOP3XX_DMA1_PUADR     (volatile u32 *)IOP3XX_REG_ADDR(0x0458)
++#define IOP3XX_DMA1_LADR      (volatile u32 *)IOP3XX_REG_ADDR(0x045c)
++#define IOP3XX_DMA1_BCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0460)
++#define IOP3XX_DMA1_DCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0464)
  
- static void common_cpu_mem_hotplug_unplug(void)
- {
--      mutex_lock(&manage_mutex);
-+      container_lock();
-       mutex_lock(&callback_mutex);
+ /* Peripheral bus interface  */
+ #define IOP3XX_PBCR           (volatile u32 *)IOP3XX_REG_ADDR(0x0680)
+@@ -195,8 +210,48 @@
+ #define IOP_TMR_RATIO_1_1  0x00
  
-       guarantee_online_cpus_mems_in_subtree(&top_cpuset);
-@@ -2122,7 +1390,7 @@
-       top_cpuset.mems_allowed = node_online_map;
+ /* Application accelerator unit  */
+-#define IOP3XX_AAU_PHYS_BASE (IOP3XX_PERIPHERAL_PHYS_BASE + 0x800)
+-#define IOP3XX_AAU_UPPER_PA (IOP3XX_AAU_PHYS_BASE + 0xa7)
++#define IOP3XX_AAU_ACR                (volatile u32 *)IOP3XX_REG_ADDR(0x0800)
++#define IOP3XX_AAU_ASR                (volatile u32 *)IOP3XX_REG_ADDR(0x0804)
++#define IOP3XX_AAU_ADAR               (volatile u32 *)IOP3XX_REG_ADDR(0x0808)
++#define IOP3XX_AAU_ANDAR      (volatile u32 *)IOP3XX_REG_ADDR(0x080c)
++#define IOP3XX_AAU_SAR1               (volatile u32 *)IOP3XX_REG_ADDR(0x0810)
++#define IOP3XX_AAU_SAR2               (volatile u32 *)IOP3XX_REG_ADDR(0x0814)
++#define IOP3XX_AAU_SAR3               (volatile u32 *)IOP3XX_REG_ADDR(0x0818)
++#define IOP3XX_AAU_SAR4               (volatile u32 *)IOP3XX_REG_ADDR(0x081c)
++#define IOP3XX_AAU_DAR                (volatile u32 *)IOP3XX_REG_ADDR(0x0820)
++#define IOP3XX_AAU_ABCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0824)
++#define IOP3XX_AAU_ADCR               (volatile u32 *)IOP3XX_REG_ADDR(0x0828)
++#define IOP3XX_AAU_SAR5               (volatile u32 *)IOP3XX_REG_ADDR(0x082c)
++#define IOP3XX_AAU_SAR6               (volatile u32 *)IOP3XX_REG_ADDR(0x0830)
++#define IOP3XX_AAU_SAR7               (volatile u32 *)IOP3XX_REG_ADDR(0x0834)
++#define IOP3XX_AAU_SAR8               (volatile u32 *)IOP3XX_REG_ADDR(0x0838)
++#define IOP3XX_AAU_EDCR0      (volatile u32 *)IOP3XX_REG_ADDR(0x083c)
++#define IOP3XX_AAU_SAR9               (volatile u32 *)IOP3XX_REG_ADDR(0x0840)
++#define IOP3XX_AAU_SAR10      (volatile u32 *)IOP3XX_REG_ADDR(0x0844)
++#define IOP3XX_AAU_SAR11      (volatile u32 *)IOP3XX_REG_ADDR(0x0848)
++#define IOP3XX_AAU_SAR12      (volatile u32 *)IOP3XX_REG_ADDR(0x084c)
++#define IOP3XX_AAU_SAR13      (volatile u32 *)IOP3XX_REG_ADDR(0x0850)
++#define IOP3XX_AAU_SAR14      (volatile u32 *)IOP3XX_REG_ADDR(0x0854)
++#define IOP3XX_AAU_SAR15      (volatile u32 *)IOP3XX_REG_ADDR(0x0858)
++#define IOP3XX_AAU_SAR16      (volatile u32 *)IOP3XX_REG_ADDR(0x085c)
++#define IOP3XX_AAU_EDCR1      (volatile u32 *)IOP3XX_REG_ADDR(0x0860)
++#define IOP3XX_AAU_SAR17      (volatile u32 *)IOP3XX_REG_ADDR(0x0864)
++#define IOP3XX_AAU_SAR18      (volatile u32 *)IOP3XX_REG_ADDR(0x0868)
++#define IOP3XX_AAU_SAR19      (volatile u32 *)IOP3XX_REG_ADDR(0x086c)
++#define IOP3XX_AAU_SAR20      (volatile u32 *)IOP3XX_REG_ADDR(0x0870)
++#define IOP3XX_AAU_SAR21      (volatile u32 *)IOP3XX_REG_ADDR(0x0874)
++#define IOP3XX_AAU_SAR22      (volatile u32 *)IOP3XX_REG_ADDR(0x0878)
++#define IOP3XX_AAU_SAR23      (volatile u32 *)IOP3XX_REG_ADDR(0x087c)
++#define IOP3XX_AAU_SAR24      (volatile u32 *)IOP3XX_REG_ADDR(0x0880)
++#define IOP3XX_AAU_EDCR2      (volatile u32 *)IOP3XX_REG_ADDR(0x0884)
++#define IOP3XX_AAU_SAR25      (volatile u32 *)IOP3XX_REG_ADDR(0x0888)
++#define IOP3XX_AAU_SAR26      (volatile u32 *)IOP3XX_REG_ADDR(0x088c)
++#define IOP3XX_AAU_SAR27      (volatile u32 *)IOP3XX_REG_ADDR(0x0890)
++#define IOP3XX_AAU_SAR28      (volatile u32 *)IOP3XX_REG_ADDR(0x0894)
++#define IOP3XX_AAU_SAR29      (volatile u32 *)IOP3XX_REG_ADDR(0x0898)
++#define IOP3XX_AAU_SAR30      (volatile u32 *)IOP3XX_REG_ADDR(0x089c)
++#define IOP3XX_AAU_SAR31      (volatile u32 *)IOP3XX_REG_ADDR(0x08a0)
++#define IOP3XX_AAU_SAR32      (volatile u32 *)IOP3XX_REG_ADDR(0x08a4)
  
-       mutex_unlock(&callback_mutex);
--      mutex_unlock(&manage_mutex);
-+      container_unlock();
+ /* I2C bus interface unit  */
+ #define IOP3XX_ICR0           (volatile u32 *)IOP3XX_REG_ADDR(0x1680)
+@@ -274,9 +329,6 @@
+       asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (val));
  }
  
- /*
-@@ -2170,109 +1438,7 @@
- }
+-extern struct platform_device iop3xx_dma_0_channel;
+-extern struct platform_device iop3xx_dma_1_channel;
+-extern struct platform_device iop3xx_aau_channel;
+ extern struct platform_device iop3xx_i2c0_device;
+ extern struct platform_device iop3xx_i2c1_device;
  
- /**
-- * cpuset_fork - attach newly forked task to its parents cpuset.
-- * @tsk: pointer to task_struct of forking parent process.
+diff -Nurb linux-2.6.22-590/include/asm-arm/hardware/iop_adma.h linux-2.6.22-570/include/asm-arm/hardware/iop_adma.h
+--- linux-2.6.22-590/include/asm-arm/hardware/iop_adma.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-arm/hardware/iop_adma.h       1969-12-31 19:00:00.000000000 -0500
+@@ -1,120 +0,0 @@
+-/*
+- * Copyright Â© 2006, Intel Corporation.
 - *
-- * Description: A task inherits its parent's cpuset at fork().
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
 - *
-- * A pointer to the shared cpuset was automatically copied in fork.c
-- * by dup_task_struct().  However, we ignore that copy, since it was
-- * not made under the protection of task_lock(), so might no longer be
-- * a valid cpuset pointer.  attach_task() might have already changed
-- * current->cpuset, allowing the previously referenced cpuset to
-- * be removed and freed.  Instead, we task_lock(current) and copy
-- * its present value of current->cpuset for our freshly forked child.
+- * This program is distributed in the hope 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.
 - *
-- * At the point that cpuset_fork() is called, 'current' is the parent
-- * task, and the passed argument 'child' points to the child task.
-- **/
--void cpuset_fork(struct task_struct *child)
--{
--      task_lock(current);
--      child->cpuset = current->cpuset;
--      atomic_inc(&child->cpuset->count);
--      task_unlock(current);
--}
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- *
+- */
+-#ifndef IOP_ADMA_H
+-#define IOP_ADMA_H
+-#include <linux/types.h>
+-#include <linux/dmaengine.h>
+-#include <linux/interrupt.h>
+-
+-#define IOP_ADMA_SLOT_SIZE 32
+-#define IOP_ADMA_THRESHOLD 4
 -
 -/**
-- * cpuset_exit - detach cpuset from exiting task
-- * @tsk: pointer to task_struct of exiting process
+- * struct iop_adma_device - internal representation of an ADMA device
+- * @pdev: Platform device
+- * @id: HW ADMA Device selector
+- * @dma_desc_pool: base of DMA descriptor region (DMA address)
+- * @dma_desc_pool_virt: base of DMA descriptor region (CPU address)
+- * @common: embedded struct dma_device
+- */
+-struct iop_adma_device {
+-      struct platform_device *pdev;
+-      int id;
+-      dma_addr_t dma_desc_pool;
+-      void *dma_desc_pool_virt;
+-      struct dma_device common;
+-};
+-
+-/**
+- * struct iop_adma_chan - internal representation of an ADMA device
+- * @pending: allows batching of hardware operations
+- * @completed_cookie: identifier for the most recently completed operation
+- * @lock: serializes enqueue/dequeue operations to the slot pool
+- * @mmr_base: memory mapped register base
+- * @chain: device chain view of the descriptors
+- * @device: parent device
+- * @common: common dmaengine channel object members
+- * @last_used: place holder for allocation to continue from where it left off
+- * @all_slots: complete domain of slots usable by the channel
+- * @cleanup_watchdog: workaround missed interrupts on iop3xx
+- * @slots_allocated: records the actual size of the descriptor slot pool
+- * @irq_tasklet: bottom half where iop_adma_slot_cleanup runs
+- */
+-struct iop_adma_chan {
+-      int pending;
+-      dma_cookie_t completed_cookie;
+-      spinlock_t lock; /* protects the descriptor slot pool */
+-      void __iomem *mmr_base;
+-      struct list_head chain;
+-      struct iop_adma_device *device;
+-      struct dma_chan common;
+-      struct iop_adma_desc_slot *last_used;
+-      struct list_head all_slots;
+-      struct timer_list cleanup_watchdog;
+-      int slots_allocated;
+-      struct tasklet_struct irq_tasklet;
+-};
+-
+-/**
+- * struct iop_adma_desc_slot - IOP-ADMA software descriptor
+- * @slot_node: node on the iop_adma_chan.all_slots list
+- * @chain_node: node on the op_adma_chan.chain list
+- * @hw_desc: virtual address of the hardware descriptor chain
+- * @phys: hardware address of the hardware descriptor chain
+- * @group_head: first operation in a transaction
+- * @slot_cnt: total slots used in an transaction (group of operations)
+- * @slots_per_op: number of slots per operation
+- * @idx: pool index
+- * @unmap_src_cnt: number of xor sources
+- * @unmap_len: transaction bytecount
+- * @async_tx: support for the async_tx api
+- * @group_list: list of slots that make up a multi-descriptor transaction
+- *    for example transfer lengths larger than the supported hw max
+- * @xor_check_result: result of zero sum
+- * @crc32_result: result crc calculation
+- */
+-struct iop_adma_desc_slot {
+-      struct list_head slot_node;
+-      struct list_head chain_node;
+-      void *hw_desc;
+-      dma_addr_t phys;
+-      struct iop_adma_desc_slot *group_head;
+-      u16 slot_cnt;
+-      u16 slots_per_op;
+-      u16 idx;
+-      u16 unmap_src_cnt;
+-      size_t unmap_len;
+-      struct dma_async_tx_descriptor async_tx;
+-      struct list_head group_list;
+-      union {
+-              u32 *xor_check_result;
+-              u32 *crc32_result;
+-      };
+-};
+-
+-struct iop_adma_platform_data {
+-      int hw_id;
+-      dma_cap_mask_t cap_mask;
+-      size_t pool_size;
+-};
+-
+-#define to_iop_sw_desc(addr_hw_desc) \
+-      container_of(addr_hw_desc, struct iop_adma_desc_slot, hw_desc)
+-#define iop_hw_desc_slot_idx(hw_desc, idx) \
+-      ( (void *) (((unsigned long) hw_desc) + ((idx) << 5)) )
+-#endif
+diff -Nurb linux-2.6.22-590/include/asm-arm/kgdb.h linux-2.6.22-570/include/asm-arm/kgdb.h
+--- linux-2.6.22-590/include/asm-arm/kgdb.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-arm/kgdb.h    1969-12-31 19:00:00.000000000 -0500
+@@ -1,103 +0,0 @@
+-/*
+- * include/asm-arm/kgdb.h
 - *
-- * Description: Detach cpuset from @tsk and release it.
+- * ARM KGDB support
 - *
-- * Note that cpusets marked notify_on_release force every task in
-- * them to take the global manage_mutex mutex when exiting.
-- * This could impact scaling on very large systems.  Be reluctant to
-- * use notify_on_release cpusets where very high task exit scaling
-- * is required on large systems.
+- * Author: Deepak Saxena <dsaxena@mvista.com>
 - *
-- * Don't even think about derefencing 'cs' after the cpuset use count
-- * goes to zero, except inside a critical section guarded by manage_mutex
-- * or callback_mutex.   Otherwise a zero cpuset use count is a license to
-- * any other task to nuke the cpuset immediately, via cpuset_rmdir().
+- * Copyright (C) 2002 MontaVista Software Inc.
 - *
-- * This routine has to take manage_mutex, not callback_mutex, because
-- * it is holding that mutex while calling check_for_release(),
-- * which calls kmalloc(), so can't be called holding callback_mutex().
+- */
+-
+-#ifndef __ASM_KGDB_H__
+-#define __ASM_KGDB_H__
+-
+-#include <asm/ptrace.h>
+-#include <asm-generic/kgdb.h>
+-
+-
+-/*
+- * GDB assumes that we're a user process being debugged, so
+- * it will send us an SWI command to write into memory as the
+- * debug trap. When an SWI occurs, the next instruction addr is
+- * placed into R14_svc before jumping to the vector trap.
+- * This doesn't work for kernel debugging as we are already in SVC
+- * we would loose the kernel's LR, which is a bad thing. This
+- * is  bad thing.
 - *
-- * the_top_cpuset_hack:
+- * By doing this as an undefined instruction trap, we force a mode
+- * switch from SVC to UND mode, allowing us to save full kernel state.
 - *
-- *    Set the exiting tasks cpuset to the root cpuset (top_cpuset).
+- * We also define a KGDB_COMPILED_BREAK which can be used to compile
+- * in breakpoints. This is important for things like sysrq-G and for
+- * the initial breakpoint from trap_init().
 - *
-- *    Don't leave a task unable to allocate memory, as that is an
-- *    accident waiting to happen should someone add a callout in
-- *    do_exit() after the cpuset_exit() call that might allocate.
-- *    If a task tries to allocate memory with an invalid cpuset,
-- *    it will oops in cpuset_update_task_memory_state().
+- * Note to ARM HW designers: Add real trap support like SH && PPC to
+- * make our lives much much simpler. :)
+- */
+-#define       BREAK_INSTR_SIZE                4
+-#define GDB_BREAKINST                   0xef9f0001
+-#define KGDB_BREAKINST                  0xe7ffdefe
+-#define KGDB_COMPILED_BREAK             0xe7ffdeff
+-#define CACHE_FLUSH_IS_SAFE           1
+-
+-#ifndef       __ASSEMBLY__
+-
+-#define       BREAKPOINT()                    asm(".word      0xe7ffdeff")
+-
+-
+-extern void kgdb_handle_bus_error(void);
+-extern int kgdb_fault_expected;
+-#endif /* !__ASSEMBLY__ */
+-
+-/*
+- * From Kevin Hilman:
 - *
-- *    We call cpuset_exit() while the task is still competent to
-- *    handle notify_on_release(), then leave the task attached to
-- *    the root cpuset (top_cpuset) for the remainder of its exit.
+- * gdb is expecting the following registers layout.
 - *
-- *    To do this properly, we would increment the reference count on
-- *    top_cpuset, and near the very end of the kernel/exit.c do_exit()
-- *    code we would add a second cpuset function call, to drop that
-- *    reference.  This would just create an unnecessary hot spot on
-- *    the top_cpuset reference count, to no avail.
+- * r0-r15: 1 long word each
+- * f0-f7:  unused, 3 long words each !!
+- * fps:    unused, 1 long word
+- * cpsr:   1 long word
 - *
-- *    Normally, holding a reference to a cpuset without bumping its
-- *    count is unsafe.   The cpuset could go away, or someone could
-- *    attach us to a different cpuset, decrementing the count on
-- *    the first cpuset that we never incremented.  But in this case,
-- *    top_cpuset isn't going away, and either task has PF_EXITING set,
-- *    which wards off any attach_task() attempts, or task is a failed
-- *    fork, never visible to attach_task.
+- * Even though f0-f7 and fps are not used, they need to be
+- * present in the registers sent for correct processing in
+- * the host-side gdb.
 - *
-- *    Another way to do this would be to set the cpuset pointer
-- *    to NULL here, and check in cpuset_update_task_memory_state()
-- *    for a NULL pointer.  This hack avoids that NULL check, for no
-- *    cost (other than this way too long comment ;).
-- **/
+- * In particular, it is crucial that CPSR is in the right place,
+- * otherwise gdb will not be able to correctly interpret stepping over
+- * conditional branches.
+- */
+-#define _GP_REGS              16
+-#define _FP_REGS              8
+-#define _EXTRA_REGS           2
+-#define       GDB_MAX_REGS            (_GP_REGS + (_FP_REGS * 3) + _EXTRA_REGS)
+-
+-#define       KGDB_MAX_NO_CPUS        1
+-#define       BUFMAX                  400
+-#define       NUMREGBYTES             (GDB_MAX_REGS << 2)
+-#define       NUMCRITREGBYTES         (32 << 2)
+-
+-#define       _R0             0
+-#define       _R1             1
+-#define       _R2             2
+-#define       _R3             3
+-#define       _R4             4
+-#define       _R5             5
+-#define       _R6             6
+-#define       _R7             7
+-#define       _R8             8
+-#define       _R9             9
+-#define       _R10            10
+-#define       _FP             11
+-#define       _IP             12
+-#define       _SP             13
+-#define       _LR             14
+-#define       _PC             15
+-#define       _CPSR           (GDB_MAX_REGS - 1)
+-
+-/* So that we can denote the end of a frame for tracing, in the simple
+- * case. */
+-#define CFI_END_FRAME(func)   __CFI_END_FRAME(_PC,_SP,func)
+-
+-#endif /* __ASM_KGDB_H__ */
+diff -Nurb linux-2.6.22-590/include/asm-arm/system.h linux-2.6.22-570/include/asm-arm/system.h
+--- linux-2.6.22-590/include/asm-arm/system.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-arm/system.h  2007-07-08 19:32:17.000000000 -0400
+@@ -360,41 +360,6 @@
+ extern void disable_hlt(void);
+ extern void enable_hlt(void);
+-#ifndef CONFIG_SMP
+-/*
+- * Atomic compare and exchange.
+- */
+-#define __HAVE_ARCH_CMPXCHG   1
+-
+-extern unsigned long wrong_size_cmpxchg(volatile void *ptr);
 -
--void cpuset_exit(struct task_struct *tsk)
+-static inline unsigned long __cmpxchg(volatile void *ptr,
+-                                  unsigned long old,
+-                                  unsigned long new, int size)
 -{
--      struct cpuset *cs;
+-      unsigned long flags, prev;
+-      volatile unsigned long *p = ptr;
 -
--      task_lock(current);
--      cs = tsk->cpuset;
--      tsk->cpuset = &top_cpuset;      /* the_top_cpuset_hack - see above */
--      task_unlock(current);
+-      if (size == 4) {
+-              local_irq_save(flags);
+-              if ((prev = *p) == old)
+-                      *p = new;
+-              local_irq_restore(flags);
+-              return(prev);
+-      } else
+-              return wrong_size_cmpxchg(ptr);
+-}
 -
--      if (notify_on_release(cs)) {
--              char *pathbuf = NULL;
+-#define cmpxchg(ptr,o,n)                                              \
+-({                                                                    \
+-     __typeof__(*(ptr)) _o_ = (o);                                    \
+-     __typeof__(*(ptr)) _n_ = (n);                                    \
+-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,                \
+-                               (unsigned long)_n_, sizeof(*(ptr)));   \
+-})
 -
--              mutex_lock(&manage_mutex);
--              if (atomic_dec_and_test(&cs->count))
--                      check_for_release(cs, &pathbuf);
--              mutex_unlock(&manage_mutex);
--              cpuset_release_agent(pathbuf);
--      } else {
--              atomic_dec(&cs->count);
--      }
--}
+-#endif
 -
--/**
-  * cpuset_cpus_allowed - return cpus_allowed mask from a tasks cpuset.
-  * @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed.
-  *
-@@ -2288,7 +1454,7 @@
-       mutex_lock(&callback_mutex);
-       task_lock(tsk);
--      guarantee_online_cpus(tsk->cpuset, &mask);
-+      guarantee_online_cpus(task_cs(tsk), &mask);
-       task_unlock(tsk);
-       mutex_unlock(&callback_mutex);
-@@ -2316,7 +1482,7 @@
-       mutex_lock(&callback_mutex);
-       task_lock(tsk);
--      guarantee_online_mems(tsk->cpuset, &mask);
-+      guarantee_online_mems(task_cs(tsk), &mask);
-       task_unlock(tsk);
-       mutex_unlock(&callback_mutex);
-@@ -2447,7 +1613,7 @@
-       mutex_lock(&callback_mutex);
-       task_lock(current);
--      cs = nearest_exclusive_ancestor(current->cpuset);
-+      cs = nearest_exclusive_ancestor(task_cs(current));
-       task_unlock(current);
-       allowed = node_isset(node, cs->mems_allowed);
-@@ -2584,7 +1750,7 @@
-               task_unlock(current);
-               goto done;
-       }
--      cs1 = nearest_exclusive_ancestor(current->cpuset);
-+      cs1 = nearest_exclusive_ancestor(task_cs(current));
-       task_unlock(current);
-       task_lock((struct task_struct *)p);
-@@ -2592,7 +1758,7 @@
-               task_unlock((struct task_struct *)p);
-               goto done;
-       }
--      cs2 = nearest_exclusive_ancestor(p->cpuset);
-+      cs2 = nearest_exclusive_ancestor(task_cs((struct task_struct *)p));
-       task_unlock((struct task_struct *)p);
+ #endif /* __ASSEMBLY__ */
  
-       overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed);
-@@ -2628,14 +1794,12 @@
+ #define arch_align_stack(x) (x)
+diff -Nurb linux-2.6.22-590/include/asm-cris/page.h linux-2.6.22-570/include/asm-cris/page.h
+--- linux-2.6.22-590/include/asm-cris/page.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-cris/page.h   2007-07-08 19:32:17.000000000 -0400
+@@ -20,8 +20,7 @@
+ #define clear_user_page(page, vaddr, pg)    clear_page(page)
+ #define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
  
- void __cpuset_memory_pressure_bump(void)
- {
--      struct cpuset *cs;
--
-       task_lock(current);
--      cs = current->cpuset;
--      fmeter_markevent(&cs->fmeter);
-+      fmeter_markevent(&task_cs(current)->fmeter);
-       task_unlock(current);
- }
+-#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+-      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
++#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+ #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
  
-+#ifdef CONFIG_PROC_PID_CPUSET
  /*
-  * proc_cpuset_show()
-  *  - Print tasks cpuset path into seq_file.
-@@ -2652,6 +1816,7 @@
-       struct pid *pid;
-       struct task_struct *tsk;
-       char *buf;
-+      struct container_subsys_state *css;
-       int retval;
-       retval = -ENOMEM;
-@@ -2666,15 +1831,15 @@
-               goto out_free;
-       retval = -EINVAL;
--      mutex_lock(&manage_mutex);
+diff -Nurb linux-2.6.22-590/include/asm-generic/kgdb.h linux-2.6.22-570/include/asm-generic/kgdb.h
+--- linux-2.6.22-590/include/asm-generic/kgdb.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-generic/kgdb.h        1969-12-31 19:00:00.000000000 -0500
+@@ -1,100 +0,0 @@
+-/*
+- * include/asm-generic/kgdb.h
+- *
+- * This provides the assembly level information so that KGDB can provide
+- * a GDB that has been patched with enough information to know to stop
+- * trying to unwind the function.
+- *
+- * Author: Tom Rini <trini@kernel.crashing.org>
+- *
+- * 2005 (c) MontaVista Software, Inc.
+- * 2006 (c) Embedded Alley Solutions, Inc.
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program is licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
 -
--      retval = cpuset_path(tsk->cpuset, buf, PAGE_SIZE);
-+      container_lock();
-+      css = task_subsys_state(tsk, cpuset_subsys_id);
-+      retval = container_path(css->container, buf, PAGE_SIZE);
-       if (retval < 0)
-               goto out_unlock;
-       seq_puts(m, buf);
-       seq_putc(m, '\n');
- out_unlock:
--      mutex_unlock(&manage_mutex);
-+      container_unlock();
-       put_task_struct(tsk);
- out_free:
-       kfree(buf);
-@@ -2694,6 +1859,7 @@
-       .llseek         = seq_lseek,
-       .release        = single_release,
- };
-+#endif /* CONFIG_PROC_PID_CPUSET */
- /* Display task cpus_allowed, mems_allowed in /proc/<pid>/status file. */
- char *cpuset_task_status_allowed(struct task_struct *task, char *buffer)
-diff -Nurb linux-2.6.22-570/kernel/exit.c linux-2.6.22-590/kernel/exit.c
---- linux-2.6.22-570/kernel/exit.c     2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/exit.c     2008-01-02 13:56:37.000000000 -0500
-@@ -31,7 +31,8 @@
- #include <linux/mempolicy.h>
- #include <linux/taskstats_kern.h>
- #include <linux/delayacct.h>
--#include <linux/cpuset.h>
-+#include <linux/freezer.h>
-+#include <linux/container.h>
- #include <linux/syscalls.h>
- #include <linux/signal.h>
- #include <linux/posix-timers.h>
-@@ -393,6 +394,11 @@
-        * they would be locked into memory.
-        */
-       exit_mm(current);
-+      /*
-+       * We don't want to have TIF_FREEZE set if the system-wide hibernation
-+       * or suspend transition begins right now.
-+       */
-+      current->flags |= PF_NOFREEZE;
-       set_special_pids(1, 1);
-       proc_clear_tty(current);
-@@ -875,6 +881,34 @@
-               release_task(tsk);
- }
-+#ifdef CONFIG_DEBUG_STACK_USAGE
-+static void check_stack_usage(void)
-+{
-+      static DEFINE_SPINLOCK(low_water_lock);
-+      static int lowest_to_date = THREAD_SIZE;
-+      unsigned long *n = end_of_stack(current);
-+      unsigned long free;
-+
-+      while (*n == 0)
-+              n++;
-+      free = (unsigned long)n - (unsigned long)end_of_stack(current);
-+
-+      if (free >= lowest_to_date)
-+              return;
-+
-+      spin_lock(&low_water_lock);
-+      if (free < lowest_to_date) {
-+              printk(KERN_WARNING "%s used greatest stack depth: %lu bytes "
-+                              "left\n",
-+                              current->comm, free);
-+              lowest_to_date = free;
-+      }
-+      spin_unlock(&low_water_lock);
-+}
-+#else
-+static inline void check_stack_usage(void) {}
-+#endif
-+
- fastcall NORET_TYPE void do_exit(long code)
- {
-       struct task_struct *tsk = current;
-@@ -966,8 +1000,9 @@
-       exit_sem(tsk);
-       __exit_files(tsk);
-       __exit_fs(tsk);
-+      check_stack_usage();
-       exit_thread();
--      cpuset_exit(tsk);
-+      container_exit(tsk, 1);
-       exit_keys(tsk);
-       if (group_dead && tsk->signal->leader)
-diff -Nurb linux-2.6.22-570/kernel/fork.c linux-2.6.22-590/kernel/fork.c
---- linux-2.6.22-570/kernel/fork.c     2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/fork.c     2008-01-02 13:56:37.000000000 -0500
-@@ -29,7 +29,7 @@
- #include <linux/nsproxy.h>
- #include <linux/capability.h>
- #include <linux/cpu.h>
--#include <linux/cpuset.h>
-+#include <linux/container.h>
- #include <linux/security.h>
- #include <linux/swap.h>
- #include <linux/syscalls.h>
-@@ -342,6 +342,8 @@
-       atomic_set(&mm->mm_count, 1);
-       init_rwsem(&mm->mmap_sem);
-       INIT_LIST_HEAD(&mm->mmlist);
-+      mm->flags = (current->mm) ? current->mm->flags
-+                                : MMF_DUMP_FILTER_DEFAULT;
-       mm->core_waiters = 0;
-       mm->nr_ptes = 0;
-       __set_mm_counter(mm, file_rss, 0);
-@@ -936,7 +938,7 @@
- {
-       unsigned long new_flags = p->flags;
--      new_flags &= ~(PF_SUPERPRIV | PF_NOFREEZE);
-+      new_flags &= ~PF_SUPERPRIV;
-       new_flags |= PF_FORKNOEXEC;
-       if (!(clone_flags & CLONE_PTRACE))
-               p->ptrace = 0;
-@@ -977,6 +979,7 @@
- {
-       int retval;
-       struct task_struct *p = NULL;
-+      int container_callbacks_done = 0;
-       struct vx_info *vxi;
-       struct nx_info *nxi;
-@@ -1061,11 +1064,6 @@
-       delayacct_tsk_init(p);  /* Must remain after dup_task_struct() */
-       copy_flags(clone_flags, p);
-       p->pid = pid_nr(pid);
--      retval = -EFAULT;
--      if (clone_flags & CLONE_PARENT_SETTID)
--              if (put_user(p->pid, parent_tidptr))
--                      goto bad_fork_cleanup_delays_binfmt;
+-#ifndef __ASM_GENERIC_KGDB_H__
+-#define __ASM_GENERIC_KGDB_H__
 -
-       INIT_LIST_HEAD(&p->children);
-       INIT_LIST_HEAD(&p->sibling);
-       p->vfork_done = NULL;
-@@ -1095,17 +1093,19 @@
-       p->lock_depth = -1;             /* -1 = no lock */
-       do_posix_clock_monotonic_gettime(&p->start_time);
-+      p->real_start_time = p->start_time;
-+      monotonic_to_bootbased(&p->real_start_time);
-       p->security = NULL;
-       p->io_context = NULL;
-       p->io_wait = NULL;
-       p->audit_context = NULL;
--      cpuset_fork(p);
-+      container_fork(p);
- #ifdef CONFIG_NUMA
-       p->mempolicy = mpol_copy(p->mempolicy);
-       if (IS_ERR(p->mempolicy)) {
-               retval = PTR_ERR(p->mempolicy);
-               p->mempolicy = NULL;
--              goto bad_fork_cleanup_cpuset;
-+              goto bad_fork_cleanup_container;
-       }
-       mpol_fix_fork_child_flag(p);
- #endif
-@@ -1215,6 +1215,12 @@
-       /* Perform scheduler related setup. Assign this task to a CPU. */
-       sched_fork(p, clone_flags);
-+      /* Now that the task is set up, run container callbacks if
-+       * necessary. We need to run them before the task is visible
-+       * on the tasklist. */
-+      container_fork_callbacks(p);
-+      container_callbacks_done = 1;
-+
-       /* Need tasklist lock for parent etc handling! */
-       write_lock_irq(&tasklist_lock);
-@@ -1314,6 +1320,14 @@
-       if (nxi)
-               claim_nx_info(nxi, p);
-       write_unlock_irq(&tasklist_lock);
-+
-+      /*
-+       * Now that we know the fork has succeeded, record the new
-+       * TID.  It's too late to back out if this fails.
-+       */
-+      if (clone_flags & CLONE_PARENT_SETTID)
-+              put_user(p->pid, parent_tidptr);
-+
-       proc_fork_connector(p);
-       return p;
-@@ -1341,10 +1355,9 @@
- bad_fork_cleanup_policy:
- #ifdef CONFIG_NUMA
-       mpol_free(p->mempolicy);
--bad_fork_cleanup_cpuset:
-+bad_fork_cleanup_container:
- #endif
--      cpuset_exit(p);
--bad_fork_cleanup_delays_binfmt:
-+      container_exit(p, container_callbacks_done);
-       delayacct_tsk_free(p);
-       if (p->binfmt)
-               module_put(p->binfmt->module);
-@@ -1661,7 +1674,7 @@
-       err = -EINVAL;
-       if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
-                               CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
--                              CLONE_NEWUTS|CLONE_NEWIPC))
-+                              CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWUSER))
-               goto bad_unshare_out;
+-#ifdef CONFIG_X86
+-/**
+- *    kgdb_skipexception - Bail of of KGDB when we've been triggered.
+- *    @exception: Exception vector number
+- *    @regs: Current &struct pt_regs.
+- *
+- *    On some architectures we need to skip a breakpoint exception when
+- *    it occurs after a breakpoint has been removed.
+- */
+-int kgdb_skipexception(int exception, struct pt_regs *regs);
+-#else
+-#define kgdb_skipexception(exception, regs)   0
+-#endif
+-
+-#if defined(CONFIG_X86)
+-/**
+- *    kgdb_post_master_code - Save error vector/code numbers.
+- *    @regs: Original pt_regs.
+- *    @e_vector: Original error vector.
+- *    @err_code: Original error code.
+- *
+- *    This is needed on architectures which support SMP and KGDB.
+- *    This function is called after all the slave cpus have been put
+- *    to a know spin state and the master CPU has control over KGDB.
+- */
+-extern void kgdb_post_master_code(struct pt_regs *regs, int e_vector,
+-                                int err_code);
+-
+-/**
+- *    kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb.
+- *    @regs: Current &struct pt_regs.
+- *
+- *    This function will be called if the particular architecture must
+- *    disable hardware debugging while it is processing gdb packets or
+- *    handling exception.
+- */
+-extern void kgdb_disable_hw_debug(struct pt_regs *regs);
+-#else
+-#define kgdb_disable_hw_debug(regs)           do { } while (0)
+-#define kgdb_post_master_code(regs, v, c)     do { } while (0)
+-#endif
+-
+-#ifdef CONFIG_KGDB_ARCH_HAS_SHADOW_INFO
+-/**
+- *    kgdb_shadowinfo - Get shadowed information on @threadid.
+- *    @regs: The &struct pt_regs of the current process.
+- *    @buffer: A buffer of %BUFMAX size.
+- *    @threadid: The thread id of the shadowed process to get information on.
+- */
+-extern void kgdb_shadowinfo(struct pt_regs *regs, char *buffer,
+-                          unsigned threadid);
+-
+-/**
+- *    kgdb_get_shadow_thread - Get the shadowed &task_struct of @threadid.
+- *    @regs: The &struct pt_regs of the current thread.
+- *    @threadid: The thread id of the shadowed process to get information on.
+- *
+- *    RETURN:
+- *    This returns a pointer to the &struct task_struct of the shadowed
+- *    thread, @threadid.
+- */
+-extern struct task_struct *kgdb_get_shadow_thread(struct pt_regs *regs,
+-                                                int threadid);
+-
+-/**
+- *    kgdb_shadow_regs - Return the shadowed registers of @threadid.
+- *    @regs: The &struct pt_regs of the current thread.
+- *    @threadid: The thread id we want the &struct pt_regs for.
+- *
+- *    RETURN:
+- *    The a pointer to the &struct pt_regs of the shadowed thread @threadid.
+- */
+-extern struct pt_regs *kgdb_shadow_regs(struct pt_regs *regs, int threadid);
+-#else
+-#define kgdb_shadowinfo(regs, buf, threadid)          do { } while (0)
+-#define kgdb_get_shadow_thread(regs, threadid)                NULL
+-#define kgdb_shadow_regs(regs, threadid)              NULL
+-#endif
+-
+-#endif                                /* __ASM_GENERIC_KGDB_H__ */
+diff -Nurb linux-2.6.22-590/include/asm-generic/vmlinux.lds.h linux-2.6.22-570/include/asm-generic/vmlinux.lds.h
+--- linux-2.6.22-590/include/asm-generic/vmlinux.lds.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-generic/vmlinux.lds.h 2007-07-08 19:32:17.000000000 -0400
+@@ -127,8 +127,6 @@
+               *(__ksymtab_strings)                                    \
+       }                                                               \
+                                                                       \
+-      EH_FRAME                                                        \
+-                                                                      \
+       /* Built-in module parameters. */                               \
+       __param : AT(ADDR(__param) - LOAD_OFFSET) {                     \
+               VMLINUX_SYMBOL(__start___param) = .;                    \
+@@ -179,26 +177,6 @@
+               *(.kprobes.text)                                        \
+               VMLINUX_SYMBOL(__kprobes_text_end) = .;
  
-       if ((err = unshare_thread(unshare_flags)))
-diff -Nurb linux-2.6.22-570/kernel/kgdb.c linux-2.6.22-590/kernel/kgdb.c
---- linux-2.6.22-570/kernel/kgdb.c     1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/kernel/kgdb.c     2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,1866 @@
-+/*
-+ * kernel/kgdb.c
-+ *
-+ * Maintainer: Jason Wessel <jason.wessel@windriver.com>
-+ *
-+ * Copyright (C) 2000-2001 VERITAS Software Corporation.
-+ * Copyright (C) 2002-2004 Timesys Corporation
-+ * Copyright (C) 2003-2004 Amit S. Kale <amitkale@linsyssoft.com>
-+ * Copyright (C) 2004 Pavel Machek <pavel@suse.cz>
-+ * Copyright (C) 2004-2006 Tom Rini <trini@kernel.crashing.org>
-+ * Copyright (C) 2004-2006 LinSysSoft Technologies Pvt. Ltd.
-+ * Copyright (C) 2005-2007 Wind River Systems, Inc.
-+ *
-+ * Contributors at various stages not listed above:
-+ *  Jason Wessel ( jason.wessel@windriver.com )
-+ *  George Anzinger <george@mvista.com>
-+ *  Anurekh Saxena (anurekh.saxena@timesys.com)
-+ *  Lake Stevens Instrument Division (Glenn Engel)
-+ *  Jim Kingdon, Cygnus Support.
-+ *
-+ * Original KGDB stub: David Grothe <dave@gcom.com>,
-+ * Tigran Aivazian <tigran@sco.com>
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program is licensed "as is" without any warranty of any
-+ * kind, whether express or implied.
-+ */
-+
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+#include <linux/smp.h>
-+#include <linux/spinlock.h>
-+#include <linux/delay.h>
-+#include <linux/mm.h>
-+#include <linux/threads.h>
-+#include <linux/reboot.h>
-+#include <asm/system.h>
-+#include <asm/ptrace.h>
-+#include <asm/uaccess.h>
-+#include <linux/kgdb.h>
-+#include <asm/atomic.h>
-+#include <linux/notifier.h>
-+#include <linux/module.h>
-+#include <asm/cacheflush.h>
-+#include <linux/init.h>
-+#include <linux/sysrq.h>
-+#include <linux/console.h>
-+#include <linux/sched.h>
-+#include <linux/pid_namespace.h>
-+#include <asm/byteorder.h>
-+
-+extern int pid_max;
-+/* How many times to count all of the waiting CPUs */
-+#define ROUNDUP_WAIT          640000  /* Arbitrary, increase if needed. */
-+#define BUF_THREAD_ID_SIZE    16
-+
-+/*
-+ * kgdb_initialized with a value of 1 indicates that kgdb is setup and is
-+ * all ready to serve breakpoints and other kernel exceptions.  A value of
-+ * -1 indicates that we have tried to initialize early, and need to try
-+ * again later.
-+ */
-+int kgdb_initialized;
-+/* Is a host GDB connected to us? */
-+int kgdb_connected;
-+/* Could we be about to try and access a bad memory location? If so we
-+ * also need to flag this has happend. */
-+int kgdb_may_fault;
-+#ifdef CONFIG_PREEMPT
-+static int kgdb_fault_preempt_count;
-+#endif
-+
-+/* All the KGDB handlers are installed */
-+int kgdb_from_module_registered = 0;
-+/* Guard for recursive entry */
-+static int exception_level = 0;
-+
-+/* We provide a kgdb_io_ops structure that may be overriden. */
-+struct kgdb_io __attribute__ ((weak)) kgdb_io_ops;
-+
-+static struct kgdb_io kgdb_io_ops_prev[MAX_KGDB_IO_HANDLERS];
-+static int kgdb_io_handler_cnt = 0;
-+
-+/* Export the following symbols for use with kernel modules */
-+EXPORT_SYMBOL(kgdb_io_ops);
-+EXPORT_SYMBOL(kgdb_tasklet_breakpoint);
-+EXPORT_SYMBOL(kgdb_connected);
-+EXPORT_SYMBOL(kgdb_register_io_module);
-+EXPORT_SYMBOL(kgdb_unregister_io_module);
-+EXPORT_SYMBOL(debugger_active);
-+
-+/*
-+ * Holds information about breakpoints in a kernel. These breakpoints are
-+ * added and removed by gdb.
-+ */
-+struct kgdb_bkpt kgdb_break[MAX_BREAKPOINTS];
-+
-+struct kgdb_arch *kgdb_ops = &arch_kgdb_ops;
-+
-+static const char hexchars[] = "0123456789abcdef";
-+
-+static spinlock_t slavecpulocks[NR_CPUS];
-+static atomic_t procindebug[NR_CPUS];
-+atomic_t kgdb_setting_breakpoint;
-+EXPORT_SYMBOL(kgdb_setting_breakpoint);
-+struct task_struct *kgdb_usethread, *kgdb_contthread;
-+
-+int debugger_step;
-+atomic_t debugger_active;
-+
-+/* Our I/O buffers. */
-+static char remcom_in_buffer[BUFMAX];
-+static char remcom_out_buffer[BUFMAX];
-+/* Storage for the registers, in GDB format. */
-+static unsigned long gdb_regs[(NUMREGBYTES + sizeof(unsigned long) - 1) /
-+                            sizeof(unsigned long)];
-+/* Storage of registers for handling a fault. */
-+unsigned long kgdb_fault_jmp_regs[NUMCRITREGBYTES / sizeof(unsigned long)]
-+ JMP_REGS_ALIGNMENT;
-+static int kgdb_notify_reboot(struct notifier_block *this,
-+                              unsigned long code ,void *x);
-+struct debuggerinfo_struct {
-+      void *debuggerinfo;
-+      struct task_struct *task;
-+} kgdb_info[NR_CPUS];
-+
-+/* to keep track of the CPU which is doing the single stepping*/
-+atomic_t cpu_doing_single_step = ATOMIC_INIT(-1);
-+
-+atomic_t  kgdb_sync_softlockup[NR_CPUS] = {ATOMIC_INIT(0)};
-+
-+/* reboot notifier block */
-+static struct notifier_block kgdb_reboot_notifier = {
-+      .notifier_call  = kgdb_notify_reboot,
-+      .next           = NULL,
-+      .priority       = INT_MAX,
-+};
-+
-+int __attribute__ ((weak))
-+     kgdb_validate_break_address(unsigned long addr)
-+{
-+      int error = 0;
-+      char tmp_variable[BREAK_INSTR_SIZE];
-+      error = kgdb_get_mem((char *)addr, tmp_variable, BREAK_INSTR_SIZE);
-+      return error;
-+}
-+
-+int __attribute__ ((weak))
-+     kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
-+{
-+      int error = 0;
-+      if ((error = kgdb_get_mem((char *)addr,
-+              saved_instr, BREAK_INSTR_SIZE)) < 0)
-+                      return error;
-+
-+      if ((error = kgdb_set_mem((char *)addr, kgdb_ops->gdb_bpt_instr,
-+              BREAK_INSTR_SIZE)) < 0)
-+                      return error;
-+      return 0;
-+}
-+
-+int __attribute__ ((weak))
-+     kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
-+{
-+
-+      int error = 0;
-+      if ((error =kgdb_set_mem((char *)addr, (char *)bundle,
-+              BREAK_INSTR_SIZE)) < 0)
-+                      return error;
-+      return 0;
-+}
-+
-+unsigned long __attribute__ ((weak))
-+    kgdb_arch_pc(int exception, struct pt_regs *regs)
-+{
-+      return instruction_pointer(regs);
-+}
-+
-+static int hex(char ch)
-+{
-+      if ((ch >= 'a') && (ch <= 'f'))
-+              return (ch - 'a' + 10);
-+      if ((ch >= '0') && (ch <= '9'))
-+              return (ch - '0');
-+      if ((ch >= 'A') && (ch <= 'F'))
-+              return (ch - 'A' + 10);
-+      return (-1);
-+}
-+
-+/* scan for the sequence $<data>#<checksum>   */
-+static void get_packet(char *buffer)
-+{
-+      unsigned char checksum;
-+      unsigned char xmitcsum;
-+      int count;
-+      char ch;
-+      if (!kgdb_io_ops.read_char)
-+              return;
-+      do {
-+              /* Spin and wait around for the start character, ignore all
-+               * other characters */
-+              while ((ch = (kgdb_io_ops.read_char())) != '$') ;
-+              kgdb_connected = 1;
-+              checksum = 0;
-+              xmitcsum = -1;
-+
-+              count = 0;
-+
-+              /* now, read until a # or end of buffer is found */
-+              while (count < (BUFMAX - 1)) {
-+                      ch = kgdb_io_ops.read_char();
-+                      if (ch == '#')
-+                              break;
-+                      checksum = checksum + ch;
-+                      buffer[count] = ch;
-+                      count = count + 1;
-+              }
-+              buffer[count] = 0;
-+
-+              if (ch == '#') {
-+                      xmitcsum = hex(kgdb_io_ops.read_char()) << 4;
-+                      xmitcsum += hex(kgdb_io_ops.read_char());
-+
-+                      if (checksum != xmitcsum)
-+                              /* failed checksum */
-+                              kgdb_io_ops.write_char('-');
-+                      else
-+                              /* successful transfer */
-+                              kgdb_io_ops.write_char('+');
-+                      if (kgdb_io_ops.flush)
-+                              kgdb_io_ops.flush();
-+              }
-+      } while (checksum != xmitcsum);
-+}
-+
-+static void kgdb_set_may_fault(void) {
-+      kgdb_may_fault = 1;
-+#ifdef CONFIG_PREEMPT
-+      kgdb_fault_preempt_count = preempt_count();
-+#endif
-+}
-+
-+static void kgdb_unset_may_fault(void) {
-+      kgdb_may_fault = 0;
-+#ifdef CONFIG_PREEMPT
-+      preempt_count() = kgdb_fault_preempt_count;
-+#endif
-+}
-+
-+/*
-+ * Send the packet in buffer.
-+ * Check for gdb connection if asked for.
-+ */
-+static void put_packet(char *buffer)
-+{
-+      unsigned char checksum;
-+      int count;
-+      char ch;
-+
-+      if (!kgdb_io_ops.write_char)
-+              return;
-+      /* $<packet info>#<checksum>. */
-+      while (1) {
-+              kgdb_io_ops.write_char('$');
-+              checksum = 0;
-+              count = 0;
-+
-+              while ((ch = buffer[count])) {
-+                      kgdb_io_ops.write_char(ch);
-+                      checksum += ch;
-+                      count++;
-+              }
-+
-+              kgdb_io_ops.write_char('#');
-+              kgdb_io_ops.write_char(hexchars[checksum >> 4]);
-+              kgdb_io_ops.write_char(hexchars[checksum % 16]);
-+              if (kgdb_io_ops.flush)
-+                      kgdb_io_ops.flush();
-+
-+              /* Now see what we get in reply. */
-+              ch = kgdb_io_ops.read_char();
-+
-+              if (ch == 3)
-+                      ch = kgdb_io_ops.read_char();
-+
-+              /* If we get an ACK, we are done. */
-+              if (ch == '+')
-+                      return;
-+
-+              /* If we get the start of another packet, this means
-+               * that GDB is attempting to reconnect.  We will NAK
-+               * the packet being sent, and stop trying to send this
-+               * packet. */
-+              if (ch == '$') {
-+                      kgdb_io_ops.write_char('-');
-+                      if (kgdb_io_ops.flush)
-+                              kgdb_io_ops.flush();
-+                      return;
-+              }
-+      }
-+}
-+
-+/*
-+ * convert the memory pointed to by mem into hex, placing result in buf
-+ * return a pointer to the last char put in buf (null). May return an error.
-+ */
-+char *kgdb_mem2hex(char *mem, char *buf, int count)
-+{
-+      kgdb_set_may_fault();
-+      if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
-+              kgdb_unset_may_fault();
-+              return ERR_PTR(-EINVAL);
-+      }
-+      /* Accessing some registers in a single load instruction is
-+       * required to avoid bad side effects for some I/O registers.
-+       */
-+      if ((count == 2) && (((long)mem & 1) == 0)) {
-+              unsigned short tmp_s = *(unsigned short *)mem;
-+              mem += 2;
-+#ifdef __BIG_ENDIAN
-+              *buf++ = hexchars[(tmp_s >> 12) & 0xf];
-+              *buf++ = hexchars[(tmp_s >> 8) & 0xf];
-+              *buf++ = hexchars[(tmp_s >> 4) & 0xf];
-+              *buf++ = hexchars[tmp_s & 0xf];
-+#else
-+              *buf++ = hexchars[(tmp_s >> 4) & 0xf];
-+              *buf++ = hexchars[tmp_s & 0xf];
-+              *buf++ = hexchars[(tmp_s >> 12) & 0xf];
-+              *buf++ = hexchars[(tmp_s >> 8) & 0xf];
-+#endif
-+      } else if ((count == 4) && (((long)mem & 3) == 0)) {
-+              unsigned long tmp_l = *(unsigned int *)mem;
-+              mem += 4;
-+#ifdef __BIG_ENDIAN
-+              *buf++ = hexchars[(tmp_l >> 28) & 0xf];
-+              *buf++ = hexchars[(tmp_l >> 24) & 0xf];
-+              *buf++ = hexchars[(tmp_l >> 20) & 0xf];
-+              *buf++ = hexchars[(tmp_l >> 16) & 0xf];
-+              *buf++ = hexchars[(tmp_l >> 12) & 0xf];
-+              *buf++ = hexchars[(tmp_l >> 8) & 0xf];
-+              *buf++ = hexchars[(tmp_l >> 4) & 0xf];
-+              *buf++ = hexchars[tmp_l & 0xf];
-+#else
-+              *buf++ = hexchars[(tmp_l >> 4) & 0xf];
-+              *buf++ = hexchars[tmp_l & 0xf];
-+              *buf++ = hexchars[(tmp_l >> 12) & 0xf];
-+              *buf++ = hexchars[(tmp_l >> 8) & 0xf];
-+              *buf++ = hexchars[(tmp_l >> 20) & 0xf];
-+              *buf++ = hexchars[(tmp_l >> 16) & 0xf];
-+              *buf++ = hexchars[(tmp_l >> 28) & 0xf];
-+              *buf++ = hexchars[(tmp_l >> 24) & 0xf];
-+#endif
-+#ifdef CONFIG_64BIT
-+      } else if ((count == 8) && (((long)mem & 7) == 0)) {
-+              unsigned long long tmp_ll = *(unsigned long long *)mem;
-+              mem += 8;
-+#ifdef __BIG_ENDIAN
-+              *buf++ = hexchars[(tmp_ll >> 60) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 56) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 52) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 48) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 44) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 40) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 36) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 32) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 28) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 24) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 20) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 16) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 12) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 8) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 4) & 0xf];
-+              *buf++ = hexchars[tmp_ll & 0xf];
-+#else
-+              *buf++ = hexchars[(tmp_ll >> 4) & 0xf];
-+              *buf++ = hexchars[tmp_ll & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 12) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 8) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 20) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 16) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 28) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 24) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 36) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 32) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 44) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 40) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 52) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 48) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 60) & 0xf];
-+              *buf++ = hexchars[(tmp_ll >> 56) & 0xf];
-+#endif
-+#endif
-+      } else {
-+              while (count-- > 0) {
-+                      unsigned char ch = *mem++;
-+                      *buf++ = hexchars[ch >> 4];
-+                      *buf++ = hexchars[ch & 0xf];
-+              }
-+      }
-+      kgdb_unset_may_fault();
-+      *buf = 0;
-+      return (buf);
-+}
-+
-+/*
-+ * Copy the binary array pointed to by buf into mem.  Fix $, #, and
-+ * 0x7d escaped with 0x7d.  Return a pointer to the character after
-+ * the last byte written.
-+ */
-+static char *kgdb_ebin2mem(char *buf, char *mem, int count)
-+{
-+      kgdb_set_may_fault();
-+      if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
-+              kgdb_unset_may_fault();
-+              return ERR_PTR(-EINVAL);
-+      }
-+      for (; count > 0; count--, buf++) {
-+              if (*buf == 0x7d)
-+                      *mem++ = *(++buf) ^ 0x20;
-+              else
-+                      *mem++ = *buf;
-+      }
-+      kgdb_unset_may_fault();
-+      return mem;
-+}
-+
-+/*
-+ * convert the hex array pointed to by buf into binary to be placed in mem
-+ * return a pointer to the character AFTER the last byte written
-+ * May return an error.
-+ */
-+char *kgdb_hex2mem(char *buf, char *mem, int count)
-+{
-+      kgdb_set_may_fault();
-+      if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
-+              kgdb_unset_may_fault();
-+              return ERR_PTR(-EINVAL);
-+      }
-+      if ((count == 2) && (((long)mem & 1) == 0)) {
-+              unsigned short tmp_s = 0;
-+#ifdef __BIG_ENDIAN
-+              tmp_s |= hex(*buf++) << 12;
-+              tmp_s |= hex(*buf++) << 8;
-+              tmp_s |= hex(*buf++) << 4;
-+              tmp_s |= hex(*buf++);
-+#else
-+              tmp_s |= hex(*buf++) << 4;
-+              tmp_s |= hex(*buf++);
-+              tmp_s |= hex(*buf++) << 12;
-+              tmp_s |= hex(*buf++) << 8;
-+#endif
-+              *(unsigned short *)mem = tmp_s;
-+              mem += 2;
-+      } else if ((count == 4) && (((long)mem & 3) == 0)) {
-+              unsigned long tmp_l = 0;
-+#ifdef __BIG_ENDIAN
-+              tmp_l |= hex(*buf++) << 28;
-+              tmp_l |= hex(*buf++) << 24;
-+              tmp_l |= hex(*buf++) << 20;
-+              tmp_l |= hex(*buf++) << 16;
-+              tmp_l |= hex(*buf++) << 12;
-+              tmp_l |= hex(*buf++) << 8;
-+              tmp_l |= hex(*buf++) << 4;
-+              tmp_l |= hex(*buf++);
-+#else
-+              tmp_l |= hex(*buf++) << 4;
-+              tmp_l |= hex(*buf++);
-+              tmp_l |= hex(*buf++) << 12;
-+              tmp_l |= hex(*buf++) << 8;
-+              tmp_l |= hex(*buf++) << 20;
-+              tmp_l |= hex(*buf++) << 16;
-+              tmp_l |= hex(*buf++) << 28;
-+              tmp_l |= hex(*buf++) << 24;
-+#endif
-+              *(unsigned long *)mem = tmp_l;
-+              mem += 4;
-+      } else {
-+              int i;
-+              for (i = 0; i < count; i++) {
-+                      unsigned char ch = hex(*buf++) << 4;
-+                      ch |= hex(*buf++);
-+                      *mem++ = ch;
-+              }
-+      }
-+      kgdb_unset_may_fault();
-+      return (mem);
-+}
-+
-+/*
-+ * While we find nice hex chars, build a long_val.
-+ * Return number of chars processed.
-+ */
-+int kgdb_hex2long(char **ptr, long *long_val)
-+{
-+      int hex_val, num = 0;
-+
-+      *long_val = 0;
-+
-+      while (**ptr) {
-+              hex_val = hex(**ptr);
-+              if (hex_val >= 0) {
-+                      *long_val = (*long_val << 4) | hex_val;
-+                      num++;
-+              } else
-+                      break;
-+
-+              (*ptr)++;
-+      }
-+
-+      return (num);
-+}
-+
-+/* Write memory due to an 'M' or 'X' packet. */
-+static char *write_mem_msg(int binary)
-+{
-+      char *ptr = &remcom_in_buffer[1];
-+      unsigned long addr, length;
-+
-+      if (kgdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' &&
-+          kgdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') {
-+              if (binary)
-+                      ptr = kgdb_ebin2mem(ptr, (char *)addr, length);
-+              else
-+                      ptr = kgdb_hex2mem(ptr, (char *)addr, length);
-+              if (CACHE_FLUSH_IS_SAFE)
-+                      flush_icache_range(addr, addr + length + 1);
-+              if (IS_ERR(ptr))
-+                      return ptr;
-+              return NULL;
-+      }
-+
-+      return ERR_PTR(-EINVAL);
-+}
-+
-+static inline char *pack_hex_byte(char *pkt, int byte)
-+{
-+      *pkt++ = hexchars[(byte >> 4) & 0xf];
-+      *pkt++ = hexchars[(byte & 0xf)];
-+      return pkt;
-+}
-+
-+static inline void error_packet(char *pkt, int error)
-+{
-+      error = -error;
-+      pkt[0] = 'E';
-+      pkt[1] = hexchars[(error / 10)];
-+      pkt[2] = hexchars[(error % 10)];
-+      pkt[3] = '\0';
-+}
-+
-+static char *pack_threadid(char *pkt, threadref * id)
-+{
-+      char *limit;
-+      unsigned char *altid;
-+
-+      altid = (unsigned char *)id;
-+      limit = pkt + BUF_THREAD_ID_SIZE;
-+      while (pkt < limit)
-+              pkt = pack_hex_byte(pkt, *altid++);
-+
-+      return pkt;
-+}
-+
-+void int_to_threadref(threadref * id, int value)
-+{
-+      unsigned char *scan;
-+      int i = 4;
-+
-+      scan = (unsigned char *)id;
-+      while (i--)
-+              *scan++ = 0;
-+      *scan++ = (value >> 24) & 0xff;
-+      *scan++ = (value >> 16) & 0xff;
-+      *scan++ = (value >> 8) & 0xff;
-+      *scan++ = (value & 0xff);
-+}
-+
-+static struct task_struct *getthread(struct pt_regs *regs, int tid)
-+{
-+      if (init_pid_ns.last_pid == 0)
-+              return current;
-+
-+      if (num_online_cpus() &&
-+          (tid >= pid_max + num_online_cpus() + kgdb_ops->shadowth))
-+              return NULL;
-+
-+      if (kgdb_ops->shadowth && (tid >= pid_max + num_online_cpus()))
-+              return kgdb_get_shadow_thread(regs, tid - pid_max -
-+                                            num_online_cpus());
-+
-+      if (tid >= pid_max)
-+              return idle_task(tid - pid_max);
-+
-+      if (!tid)
-+              return NULL;
-+
-+      return find_task_by_pid(tid);
-+}
-+
-+#ifdef CONFIG_SMP
-+static void kgdb_wait(struct pt_regs *regs)
-+{
-+      unsigned long flags;
-+      int processor;
-+
-+      local_irq_save(flags);
-+      processor = raw_smp_processor_id();
-+      kgdb_info[processor].debuggerinfo = regs;
-+      kgdb_info[processor].task = current;
-+      atomic_set(&procindebug[processor], 1);
-+      atomic_set(&kgdb_sync_softlockup[raw_smp_processor_id()], 1);
-+
-+      /* Wait till master processor goes completely into the debugger.
-+       * FIXME: this looks racy */
-+      while (!atomic_read(&procindebug[atomic_read(&debugger_active) - 1])) {
-+              int i = 10;     /* an arbitrary number */
-+
-+              while (--i)
-+                      cpu_relax();
-+      }
-+
-+      /* Wait till master processor is done with debugging */
-+      spin_lock(&slavecpulocks[processor]);
-+
-+      kgdb_info[processor].debuggerinfo = NULL;
-+      kgdb_info[processor].task = NULL;
-+
-+      /* fix up hardware debug registers on local cpu */
-+      if (kgdb_ops->correct_hw_break)
-+              kgdb_ops->correct_hw_break();
-+      /* Signal the master processor that we are done */
-+      atomic_set(&procindebug[processor], 0);
-+      spin_unlock(&slavecpulocks[processor]);
-+      local_irq_restore(flags);
-+}
-+#endif
-+
-+int kgdb_get_mem(char *addr, unsigned char *buf, int count)
-+{
-+      kgdb_set_may_fault();
-+      if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
-+              kgdb_unset_may_fault();
-+              return -EINVAL;
-+      }
-+      while (count) {
-+              if ((unsigned long)addr < TASK_SIZE) {
-+                      kgdb_unset_may_fault();
-+                      return -EINVAL;
-+              }
-+              *buf++ = *addr++;
-+              count--;
-+      }
-+      kgdb_unset_may_fault();
-+      return 0;
-+}
-+
-+int kgdb_set_mem(char *addr, unsigned char *buf, int count)
-+{
-+      kgdb_set_may_fault();
-+      if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
-+              kgdb_unset_may_fault();
-+              return -EINVAL;
-+      }
-+      while (count) {
-+              if ((unsigned long)addr < TASK_SIZE) {
-+                      kgdb_unset_may_fault();
-+                      return -EINVAL;
-+              }
-+              *addr++ = *buf++;
-+              count--;
-+      }
-+      kgdb_unset_may_fault();
-+      return 0;
-+}
-+int kgdb_activate_sw_breakpoints(void)
-+{
-+      int i;
-+      int error = 0;
-+      unsigned long addr;
-+      for (i = 0; i < MAX_BREAKPOINTS; i++) {
-+              if (kgdb_break[i].state != bp_set)
-+                      continue;
-+              addr = kgdb_break[i].bpt_addr;
-+              if ((error = kgdb_arch_set_breakpoint(addr,
-+                                      kgdb_break[i].saved_instr)))
-+                      return error;
-+
-+              if (CACHE_FLUSH_IS_SAFE) {
-+                      if (current->mm && addr < TASK_SIZE)
-+                              flush_cache_range(current->mm->mmap_cache,
-+                                              addr, addr + BREAK_INSTR_SIZE);
-+                      else
-+                              flush_icache_range(addr, addr +
-+                                              BREAK_INSTR_SIZE);
-+              }
-+
-+              kgdb_break[i].state = bp_active;
-+        }
-+      return 0;
-+}
-+
-+static int kgdb_set_sw_break(unsigned long addr)
-+{
-+      int i, breakno = -1;
-+      int error = 0;
-+      if ((error = kgdb_validate_break_address(addr)) < 0)
-+              return error;
-+      for (i = 0; i < MAX_BREAKPOINTS; i++) {
-+              if ((kgdb_break[i].state == bp_set) &&
-+                      (kgdb_break[i].bpt_addr == addr))
-+                      return -EEXIST;
-+      }
-+      for (i = 0; i < MAX_BREAKPOINTS; i++) {
-+              if (kgdb_break[i].state == bp_removed &&
-+                              kgdb_break[i].bpt_addr == addr) {
-+                      breakno = i;
-+                      break;
-+              }
-+      }
-+
-+      if (breakno == -1) {
-+              for (i = 0; i < MAX_BREAKPOINTS; i++) {
-+                      if (kgdb_break[i].state == bp_none) {
-+                              breakno = i;
-+                              break;
-+                      }
-+              }
-+      }
-+      if (breakno == -1)
-+              return -E2BIG;
-+
-+      kgdb_break[breakno].state = bp_set;
-+      kgdb_break[breakno].type = bp_breakpoint;
-+      kgdb_break[breakno].bpt_addr = addr;
-+
-+      return 0;
-+}
-+
-+int kgdb_deactivate_sw_breakpoints(void)
-+{
-+      int i;
-+      int error = 0;
-+      unsigned long addr;
-+      for (i = 0; i < MAX_BREAKPOINTS; i++) {
-+              if (kgdb_break[i].state != bp_active)
-+                      continue;
-+              addr = kgdb_break[i].bpt_addr;
-+              if ((error = kgdb_arch_remove_breakpoint(addr,
-+                                      kgdb_break[i].saved_instr)))
-+                      return error;
-+
-+              if (CACHE_FLUSH_IS_SAFE && current->mm &&
-+                              addr < TASK_SIZE)
-+                      flush_cache_range(current->mm->mmap_cache,
-+                                      addr, addr + BREAK_INSTR_SIZE);
-+              else if (CACHE_FLUSH_IS_SAFE)
-+                      flush_icache_range(addr,
-+                                      addr + BREAK_INSTR_SIZE);
-+              kgdb_break[i].state = bp_set;
-+      }
-+      return 0;
-+}
-+
-+static int kgdb_remove_sw_break(unsigned long addr)
-+{
-+      int i;
-+
-+      for (i = 0; i < MAX_BREAKPOINTS; i++) {
-+              if ((kgdb_break[i].state == bp_set) &&
-+                      (kgdb_break[i].bpt_addr == addr)) {
-+                      kgdb_break[i].state = bp_removed;
-+                      return 0;
-+              }
-+      }
-+      return -ENOENT;
-+}
-+
-+int kgdb_isremovedbreak(unsigned long addr)
-+{
-+      int i;
-+      for (i = 0; i < MAX_BREAKPOINTS; i++) {
-+              if ((kgdb_break[i].state == bp_removed) &&
-+                      (kgdb_break[i].bpt_addr == addr)) {
-+                      return 1;
-+              }
-+      }
-+      return 0;
-+}
-+
-+int remove_all_break(void)
-+{
-+      int i;
-+      int error;
-+      unsigned long addr;
-+
-+      /* Clear memory breakpoints. */
-+      for (i = 0; i < MAX_BREAKPOINTS; i++) {
-+              if (kgdb_break[i].state != bp_set)
-+                      continue;
-+              addr = kgdb_break[i].bpt_addr;
-+              if ((error = kgdb_arch_remove_breakpoint(addr,
-+                                      kgdb_break[i].saved_instr)))
-+                      return error;
-+              kgdb_break[i].state = bp_removed;
-+      }
-+
-+      /* Clear hardware breakpoints. */
-+      if (kgdb_ops->remove_all_hw_break)
-+              kgdb_ops->remove_all_hw_break();
-+
-+      return 0;
-+}
-+
-+static inline int shadow_pid(int realpid)
-+{
-+      if (realpid) {
-+              return realpid;
-+      }
-+      return pid_max + raw_smp_processor_id();
-+}
-+
-+static char gdbmsgbuf[BUFMAX + 1];
-+static void kgdb_msg_write(const char *s, int len)
-+{
-+      int i;
-+      int wcount;
-+      char *bufptr;
-+
-+      /* 'O'utput */
-+      gdbmsgbuf[0] = 'O';
-+
-+      /* Fill and send buffers... */
-+      while (len > 0) {
-+              bufptr = gdbmsgbuf + 1;
-+
-+              /* Calculate how many this time */
-+              if ((len << 1) > (BUFMAX - 2))
-+                      wcount = (BUFMAX - 2) >> 1;
-+              else
-+                      wcount = len;
-+
-+              /* Pack in hex chars */
-+              for (i = 0; i < wcount; i++)
-+                      bufptr = pack_hex_byte(bufptr, s[i]);
-+              *bufptr = '\0';
-+
-+              /* Move up */
-+              s += wcount;
-+              len -= wcount;
-+
-+              /* Write packet */
-+              put_packet(gdbmsgbuf);
-+      }
-+}
-+
-+/*
-+ * This function does all command procesing for interfacing to gdb.
-+ *
-+ * Locking hierarchy:
-+ *    interface locks, if any (begin_session)
-+ *    kgdb lock (debugger_active)
-+ *
-+ * Note that since we can be in here prior to our cpumask being filled
-+ * out, we err on the side of caution and loop over NR_CPUS instead
-+ * of a for_each_online_cpu.
-+ *
-+ */
-+int kgdb_handle_exception(int ex_vector, int signo, int err_code,
-+                        struct pt_regs *linux_regs)
-+{
-+      unsigned long length, addr;
-+      char *ptr;
-+      unsigned long flags;
-+      unsigned i;
-+      long threadid;
-+      threadref thref;
-+      struct task_struct *thread = NULL;
-+      unsigned procid;
-+      int numshadowth = num_online_cpus() + kgdb_ops->shadowth;
-+      long kgdb_usethreadid = 0;
-+      int error = 0, all_cpus_synced = 0;
-+      struct pt_regs *shadowregs;
-+      int processor = raw_smp_processor_id();
-+      void *local_debuggerinfo;
-+
-+      /* Panic on recursive debugger calls. */
-+      if (atomic_read(&debugger_active) == raw_smp_processor_id() + 1) {
-+              exception_level++;
-+              addr = kgdb_arch_pc(ex_vector, linux_regs);
-+              kgdb_deactivate_sw_breakpoints();
-+              if (kgdb_remove_sw_break(addr) == 0) {
-+                      /* If the break point removed ok at the place exception
-+                       * occurred, try to recover and print a warning to the end
-+                       * user because the user planted a breakpoint in a place
-+                       * that KGDB needs in order to function.
-+                       */
-+                      exception_level = 0;
-+                      kgdb_skipexception(ex_vector, linux_regs);
-+                      kgdb_activate_sw_breakpoints();
-+                      printk(KERN_CRIT "KGDB: re-enter exception: breakpoint removed\n");
-+                      WARN_ON(1);
-+                      return 0;
-+              }
-+              remove_all_break();
-+              kgdb_skipexception(ex_vector, linux_regs);
-+              if (exception_level > 1)
-+                      panic("Recursive entry to debugger");
-+
-+              printk(KERN_CRIT "KGDB: re-enter exception: ALL breakpoints removed\n");
-+              panic("Recursive entry to debugger");
-+              return 0;
-+      }
-+
-+ acquirelock:
-+
-+      /*
-+       * Interrupts will be restored by the 'trap return' code, except when
-+       * single stepping.
-+       */
-+      local_irq_save(flags);
-+
-+      /* Hold debugger_active */
-+      procid = raw_smp_processor_id();
-+
-+      while (cmpxchg(&atomic_read(&debugger_active), 0, (procid + 1)) != 0) {
-+              int i = 25;     /* an arbitrary number */
-+
-+              while (--i)
-+                      cpu_relax();
-+
-+              if (atomic_read(&cpu_doing_single_step) != -1 &&
-+                              atomic_read(&cpu_doing_single_step) != procid)
-+                      udelay(1);
-+      }
-+
-+      atomic_set(&kgdb_sync_softlockup[raw_smp_processor_id()], 1);
-+
-+      /*
-+       * Don't enter if the last instance of the exception handler wanted to
-+       * come into the debugger again.
-+       */
-+      if (atomic_read(&cpu_doing_single_step) != -1 &&
-+          atomic_read(&cpu_doing_single_step) != procid) {
-+              atomic_set(&debugger_active, 0);
-+              local_irq_restore(flags);
-+              goto acquirelock;
-+      }
-+
-+      /*
-+      * Don't enter if we have hit a removed breakpoint.
-+      */
-+      if (kgdb_skipexception(ex_vector, linux_regs))
-+              goto kgdb_restore;
-+
-+      /*
-+       * Call the I/O drivers pre_exception routine
-+       * if the I/O driver defined one
-+       */
-+      if (kgdb_io_ops.pre_exception)
-+              kgdb_io_ops.pre_exception();
-+
-+      kgdb_info[processor].debuggerinfo = linux_regs;
-+      kgdb_info[processor].task = current;
-+
-+      kgdb_disable_hw_debug(linux_regs);
-+
-+      if (!debugger_step || !kgdb_contthread)
-+              for (i = 0; i < NR_CPUS; i++)
-+                      spin_lock(&slavecpulocks[i]);
-+
-+#ifdef CONFIG_SMP
-+      /* Make sure we get the other CPUs */
-+      if (!debugger_step || !kgdb_contthread)
-+              kgdb_roundup_cpus(flags);
-+#endif
-+
-+      /* spin_lock code is good enough as a barrier so we don't
-+       * need one here */
-+      atomic_set(&procindebug[processor], 1);
-+
-+      /* Wait a reasonable time for the other CPUs to be notified and
-+       * be waiting for us.  Very early on this could be imperfect
-+       * as num_online_cpus() could be 0.*/
-+      for (i = 0; i < ROUNDUP_WAIT; i++) {
-+              int cpu, num = 0;
-+              for (cpu = 0; cpu < NR_CPUS; cpu++) {
-+                      if (atomic_read(&procindebug[cpu]))
-+                              num++;
-+              }
-+              if (num >= num_online_cpus()) {
-+                      all_cpus_synced = 1;
-+                      break;
-+              }
-+      }
-+
-+      /* Clear the out buffer. */
-+      memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
-+
-+      /* Master processor is completely in the debugger */
-+      kgdb_post_master_code(linux_regs, ex_vector, err_code);
-+      kgdb_deactivate_sw_breakpoints();
-+      debugger_step = 0;
-+      kgdb_contthread = NULL;
-+      exception_level = 0;
-+
-+      if (kgdb_connected) {
-+              /* If we're still unable to roundup all of the CPUs,
-+               * send an 'O' packet informing the user again. */
-+              if (!all_cpus_synced)
-+                      kgdb_msg_write("Not all CPUs have been synced for "
-+                                     "KGDB\n", 39);
-+              /* Reply to host that an exception has occurred */
-+              ptr = remcom_out_buffer;
-+              *ptr++ = 'T';
-+              *ptr++ = hexchars[(signo >> 4) % 16];
-+              *ptr++ = hexchars[signo % 16];
-+              ptr += strlen(strcpy(ptr, "thread:"));
-+              int_to_threadref(&thref, shadow_pid(current->pid));
-+              ptr = pack_threadid(ptr, &thref);
-+              *ptr++ = ';';
-+
-+              put_packet(remcom_out_buffer);
-+      }
-+
-+      kgdb_usethread = kgdb_info[processor].task;
-+      kgdb_usethreadid = shadow_pid(kgdb_info[processor].task->pid);
-+
-+      while (kgdb_io_ops.read_char) {
-+              char *bpt_type;
-+              error = 0;
-+
-+              /* Clear the out buffer. */
-+              memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
-+
-+              get_packet(remcom_in_buffer);
-+
-+              switch (remcom_in_buffer[0]) {
-+              case '?':
-+                      /* We know that this packet is only sent
-+                       * during initial connect.  So to be safe,
-+                       * we clear out our breakpoints now incase
-+                       * GDB is reconnecting. */
-+                      remove_all_break();
-+                      /* Also, if we haven't been able to roundup all
-+                       * CPUs, send an 'O' packet informing the user
-+                       * as much.  Only need to do this once. */
-+                      if (!all_cpus_synced)
-+                              kgdb_msg_write("Not all CPUs have been "
-+                                             "synced for KGDB\n", 39);
-+                      remcom_out_buffer[0] = 'S';
-+                      remcom_out_buffer[1] = hexchars[signo >> 4];
-+                      remcom_out_buffer[2] = hexchars[signo % 16];
-+                      break;
-+
-+              case 'g':       /* return the value of the CPU registers */
-+                      thread = kgdb_usethread;
-+
-+                      if (!thread) {
-+                              thread = kgdb_info[processor].task;
-+                              local_debuggerinfo =
-+                                  kgdb_info[processor].debuggerinfo;
-+                      } else {
-+                              local_debuggerinfo = NULL;
-+                              for (i = 0; i < NR_CPUS; i++) {
-+                                      /* Try to find the task on some other
-+                                       * or possibly this node if we do not
-+                                       * find the matching task then we try
-+                                       * to approximate the results.
-+                                       */
-+                                      if (thread == kgdb_info[i].task)
-+                                              local_debuggerinfo =
-+                                                  kgdb_info[i].debuggerinfo;
-+                              }
-+                      }
-+
-+                      /* All threads that don't have debuggerinfo should be
-+                       * in __schedule() sleeping, since all other CPUs
-+                       * are in kgdb_wait, and thus have debuggerinfo. */
-+                      if (kgdb_ops->shadowth &&
-+                          kgdb_usethreadid >= pid_max + num_online_cpus()) {
-+                              shadowregs = kgdb_shadow_regs(linux_regs,
-+                                                            kgdb_usethreadid -
-+                                                            pid_max -
-+                                                            num_online_cpus
-+                                                            ());
-+                              if (!shadowregs) {
-+                                      error_packet(remcom_out_buffer,
-+                                                   -EINVAL);
-+                                      break;
-+                              }
-+                              regs_to_gdb_regs(gdb_regs, shadowregs);
-+                      } else if (local_debuggerinfo)
-+                              regs_to_gdb_regs(gdb_regs, local_debuggerinfo);
-+                      else {
-+                              /* Pull stuff saved during
-+                               * switch_to; nothing else is
-+                               * accessible (or even particularly relevant).
-+                               * This should be enough for a stack trace. */
-+                              sleeping_thread_to_gdb_regs(gdb_regs, thread);
-+                      }
-+                      kgdb_mem2hex((char *)gdb_regs, remcom_out_buffer,
-+                                   NUMREGBYTES);
-+                      break;
-+
-+                      /* set the value of the CPU registers - return OK */
-+              case 'G':
-+                      kgdb_hex2mem(&remcom_in_buffer[1], (char *)gdb_regs,
-+                                   NUMREGBYTES);
-+
-+                      if (kgdb_usethread && kgdb_usethread != current)
-+                              error_packet(remcom_out_buffer, -EINVAL);
-+                      else {
-+                              gdb_regs_to_regs(gdb_regs, linux_regs);
-+                              strcpy(remcom_out_buffer, "OK");
-+                      }
-+                      break;
-+
-+                      /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
-+              case 'm':
-+                      ptr = &remcom_in_buffer[1];
-+                      if (kgdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' &&
-+                          kgdb_hex2long(&ptr, &length) > 0) {
-+                              if (IS_ERR(ptr = kgdb_mem2hex((char *)addr,
-+                                                            remcom_out_buffer,
-+                                                            length)))
-+                                      error_packet(remcom_out_buffer,
-+                                                   PTR_ERR(ptr));
-+                      } else
-+                              error_packet(remcom_out_buffer, -EINVAL);
-+                      break;
-+
-+                      /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA */
-+              case 'M':
-+                      if (IS_ERR(ptr = write_mem_msg(0)))
-+                              error_packet(remcom_out_buffer, PTR_ERR(ptr));
-+                      else
-+                              strcpy(remcom_out_buffer, "OK");
-+                      break;
-+                      /* XAA..AA,LLLL: Write LLLL bytes at address AA..AA */
-+              case 'X':
-+                      if (IS_ERR(ptr = write_mem_msg(1)))
-+                              error_packet(remcom_out_buffer, PTR_ERR(ptr));
-+                      else
-+                              strcpy(remcom_out_buffer, "OK");
-+                      break;
-+
-+                      /* kill or detach. KGDB should treat this like a
-+                       * continue.
-+                       */
-+              case 'D':
-+                      if ((error = remove_all_break()) < 0) {
-+                              error_packet(remcom_out_buffer, error);
-+                      } else {
-+                              strcpy(remcom_out_buffer, "OK");
-+                              kgdb_connected = 0;
-+                      }
-+                      put_packet(remcom_out_buffer);
-+                      goto default_handle;
-+
-+              case 'k':
-+                      /* Don't care about error from remove_all_break */
-+                      remove_all_break();
-+                      kgdb_connected = 0;
-+                      goto default_handle;
-+
-+                      /* Reboot */
-+              case 'R':
-+                      /* For now, only honor R0 */
-+                      if (strcmp(remcom_in_buffer, "R0") == 0) {
-+                              printk(KERN_CRIT "Executing reboot\n");
-+                              strcpy(remcom_out_buffer, "OK");
-+                              put_packet(remcom_out_buffer);
-+                              emergency_sync();
-+                              /* Execution should not return from
-+                               * machine_restart()
-+                               */
-+                              machine_restart(NULL);
-+                              kgdb_connected = 0;
-+                              goto default_handle;
-+                      }
-+
-+                      /* query */
-+              case 'q':
-+                      switch (remcom_in_buffer[1]) {
-+                      case 's':
-+                      case 'f':
-+                              if (memcmp(remcom_in_buffer + 2, "ThreadInfo",
-+                                         10)) {
-+                                      error_packet(remcom_out_buffer,
-+                                                   -EINVAL);
-+                                      break;
-+                              }
-+
-+                              /*
-+                               * If we have not yet completed in
-+                               * pidhash_init() there isn't much we
-+                               * can give back.
-+                               */
-+                              if (init_pid_ns.last_pid == 0) {
-+                                      if (remcom_in_buffer[1] == 'f')
-+                                              strcpy(remcom_out_buffer,
-+                                                     "m0000000000000001");
-+                                      break;
-+                              }
-+
-+                              if (remcom_in_buffer[1] == 'f') {
-+                                      threadid = 1;
-+                              }
-+                              remcom_out_buffer[0] = 'm';
-+                              ptr = remcom_out_buffer + 1;
-+                              for (i = 0; i < 17 && threadid < pid_max +
-+                                   numshadowth; threadid++) {
-+                                      thread = getthread(linux_regs,
-+                                                         threadid);
-+                                      if (thread) {
-+                                              int_to_threadref(&thref,
-+                                                               threadid);
-+                                              pack_threadid(ptr, &thref);
-+                                              ptr += 16;
-+                                              *(ptr++) = ',';
-+                                              i++;
-+                                      }
-+                              }
-+                              *(--ptr) = '\0';
-+                              break;
-+
-+                      case 'C':
-+                              /* Current thread id */
-+                              strcpy(remcom_out_buffer, "QC");
-+
-+                              threadid = shadow_pid(current->pid);
-+
-+                              int_to_threadref(&thref, threadid);
-+                              pack_threadid(remcom_out_buffer + 2, &thref);
-+                              break;
-+                      case 'T':
-+                              if (memcmp(remcom_in_buffer + 1,
-+                                         "ThreadExtraInfo,", 16)) {
-+                                      error_packet(remcom_out_buffer,
-+                                                   -EINVAL);
-+                                      break;
-+                              }
-+                              threadid = 0;
-+                              ptr = remcom_in_buffer + 17;
-+                              kgdb_hex2long(&ptr, &threadid);
-+                              if (!getthread(linux_regs, threadid)) {
-+                                      error_packet(remcom_out_buffer,
-+                                                   -EINVAL);
-+                                      break;
-+                              }
-+                              if (threadid < pid_max) {
-+                                      kgdb_mem2hex(getthread(linux_regs,
-+                                                             threadid)->comm,
-+                                                   remcom_out_buffer, 16);
-+                              } else if (threadid >= pid_max +
-+                                         num_online_cpus()) {
-+                                      kgdb_shadowinfo(linux_regs,
-+                                                      remcom_out_buffer,
-+                                                      threadid - pid_max -
-+                                                      num_online_cpus());
-+                              } else {
-+                                      static char tmpstr[23 +
-+                                                         BUF_THREAD_ID_SIZE];
-+                                      sprintf(tmpstr, "Shadow task %d"
-+                                              " for pid 0",
-+                                              (int)(threadid - pid_max));
-+                                      kgdb_mem2hex(tmpstr, remcom_out_buffer,
-+                                                   strlen(tmpstr));
-+                              }
-+                              break;
-+                      }
-+                      break;
-+
-+                      /* task related */
-+              case 'H':
-+                      switch (remcom_in_buffer[1]) {
-+                      case 'g':
-+                              ptr = &remcom_in_buffer[2];
-+                              kgdb_hex2long(&ptr, &threadid);
-+                              thread = getthread(linux_regs, threadid);
-+                              if (!thread && threadid > 0) {
-+                                      error_packet(remcom_out_buffer,
-+                                                   -EINVAL);
-+                                      break;
-+                              }
-+                              kgdb_usethread = thread;
-+                              kgdb_usethreadid = threadid;
-+                              strcpy(remcom_out_buffer, "OK");
-+                              break;
-+
-+                      case 'c':
-+                              ptr = &remcom_in_buffer[2];
-+                              kgdb_hex2long(&ptr, &threadid);
-+                              if (!threadid) {
-+                                      kgdb_contthread = NULL;
-+                              } else {
-+                                      thread = getthread(linux_regs,
-+                                                         threadid);
-+                                      if (!thread && threadid > 0) {
-+                                              error_packet(remcom_out_buffer,
-+                                                           -EINVAL);
-+                                              break;
-+                                      }
-+                                      kgdb_contthread = thread;
-+                              }
-+                              strcpy(remcom_out_buffer, "OK");
-+                              break;
-+                      }
-+                      break;
+-#ifdef CONFIG_STACK_UNWIND
+-#define EH_FRAME                                                      \
+-              /* Unwind data binary search table */                   \
+-              . = ALIGN(8);                                           \
+-              .eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - LOAD_OFFSET) { \
+-                      VMLINUX_SYMBOL(__start_unwind_hdr) = .;         \
+-                      *(.eh_frame_hdr)                                \
+-                      VMLINUX_SYMBOL(__end_unwind_hdr) = .;           \
+-              }                                                       \
+-              /* Unwind data */                                       \
+-              . = ALIGN(8);                                           \
+-              .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) {         \
+-                      VMLINUX_SYMBOL(__start_unwind) = .;             \
+-                      *(.eh_frame)                                    \
+-                      VMLINUX_SYMBOL(__end_unwind) = .;               \
+-              }
+-#else
+-#define EH_FRAME
+-#endif
+-
+               /* DWARF debug sections.
+               Symbols in the DWARF debugging sections are relative to
+               the beginning of the section so we begin them at 0.  */
+diff -Nurb linux-2.6.22-590/include/asm-h8300/page.h linux-2.6.22-570/include/asm-h8300/page.h
+--- linux-2.6.22-590/include/asm-h8300/page.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-h8300/page.h  2007-07-08 19:32:17.000000000 -0400
+@@ -22,8 +22,7 @@
+ #define clear_user_page(page, vaddr, pg)      clear_page(page)
+ #define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
+-#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+-      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
++#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+ #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+ /*
+diff -Nurb linux-2.6.22-590/include/asm-i386/kdebug.h linux-2.6.22-570/include/asm-i386/kdebug.h
+--- linux-2.6.22-590/include/asm-i386/kdebug.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-i386/kdebug.h 2007-07-08 19:32:17.000000000 -0400
+@@ -28,7 +28,6 @@
+       DIE_CALL,
+       DIE_NMI_IPI,
+       DIE_PAGE_FAULT,
+-      DIE_PAGE_FAULT_NO_CONTEXT,
+ };
+ #endif
+diff -Nurb linux-2.6.22-590/include/asm-i386/kgdb.h linux-2.6.22-570/include/asm-i386/kgdb.h
+--- linux-2.6.22-590/include/asm-i386/kgdb.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-i386/kgdb.h   1969-12-31 19:00:00.000000000 -0500
+@@ -1,51 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef _ASM_KGDB_H_
+-#define _ASM_KGDB_H_
+-
+-#include <asm-generic/kgdb.h>
+-
+-/*
+- * Copyright (C) 2001-2004 Amit S. Kale
+- */
+-
+-/************************************************************************/
+-/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+-/* at least NUMREGBYTES*2 are needed for register packets */
+-/* Longer buffer is needed to list all threads */
+-#define BUFMAX                        1024
+-
+-/* Number of bytes of registers.  */
+-#define NUMREGBYTES           64
+-/* Number of bytes of registers we need to save for a setjmp/longjmp. */
+-#define NUMCRITREGBYTES               24
+-
+-/*
+- *  Note that this register image is in a different order than
+- *  the register image that Linux produces at interrupt time.
+- *
+- *  Linux's register image is defined by struct pt_regs in ptrace.h.
+- *  Just why GDB uses a different order is a historical mystery.
+- */
+-enum regnames { _EAX,         /* 0 */
+-      _ECX,                   /* 1 */
+-      _EDX,                   /* 2 */
+-      _EBX,                   /* 3 */
+-      _ESP,                   /* 4 */
+-      _EBP,                   /* 5 */
+-      _ESI,                   /* 6 */
+-      _EDI,                   /* 7 */
+-      _PC,                    /* 8 also known as eip */
+-      _PS,                    /* 9 also known as eflags */
+-      _CS,                    /* 10 */
+-      _SS,                    /* 11 */
+-      _DS,                    /* 12 */
+-      _ES,                    /* 13 */
+-      _FS,                    /* 14 */
+-      _GS                     /* 15 */
+-};
+-
+-#define BREAKPOINT()          asm("   int $3");
+-#define BREAK_INSTR_SIZE      1
+-#define CACHE_FLUSH_IS_SAFE   1
+-#endif                                /* _ASM_KGDB_H_ */
+-#endif                                /* __KERNEL__ */
+diff -Nurb linux-2.6.22-590/include/asm-i386/page.h linux-2.6.22-570/include/asm-i386/page.h
+--- linux-2.6.22-590/include/asm-i386/page.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-i386/page.h   2007-07-08 19:32:17.000000000 -0400
+@@ -34,8 +34,7 @@
+ #define clear_user_page(page, vaddr, pg)      clear_page(page)
+ #define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
+-#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+-      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
++#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+ #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+ /*
+diff -Nurb linux-2.6.22-590/include/asm-i386/unistd.h linux-2.6.22-570/include/asm-i386/unistd.h
+--- linux-2.6.22-590/include/asm-i386/unistd.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-i386/unistd.h 2007-07-08 19:32:17.000000000 -0400
+@@ -329,13 +329,10 @@
+ #define __NR_signalfd         321
+ #define __NR_timerfd          322
+ #define __NR_eventfd          323
+-#define __NR_revokeat         324
+-#define __NR_frevoke          325
+-#define __NR_fallocate                326
+ #ifdef __KERNEL__
+-#define NR_syscalls 327
++#define NR_syscalls 324
+ #define __ARCH_WANT_IPC_PARSE_VERSION
+ #define __ARCH_WANT_OLD_READDIR
+diff -Nurb linux-2.6.22-590/include/asm-i386/unwind.h linux-2.6.22-570/include/asm-i386/unwind.h
+--- linux-2.6.22-590/include/asm-i386/unwind.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-i386/unwind.h 2007-07-08 19:32:17.000000000 -0400
+@@ -1,95 +1,6 @@
+ #ifndef _ASM_I386_UNWIND_H
+ #define _ASM_I386_UNWIND_H
+-/*
+- * Copyright (C) 2002-2006 Novell, Inc.
+- *    Jan Beulich <jbeulich@novell.com>
+- * This code is released under version 2 of the GNU GPL.
+- */
+-
+-#ifdef CONFIG_STACK_UNWIND
+-
+-#include <linux/sched.h>
+-#include <asm/fixmap.h>
+-#include <asm/ptrace.h>
+-#include <asm/uaccess.h>
+-
+-struct unwind_frame_info
+-{
+-      struct pt_regs regs;
+-      struct task_struct *task;
+-      unsigned call_frame:1;
+-};
+-
+-#define UNW_PC(frame)        (frame)->regs.eip
+-#define UNW_SP(frame)        (frame)->regs.esp
+-#ifdef CONFIG_FRAME_POINTER
+-#define UNW_FP(frame)        (frame)->regs.ebp
+-#define FRAME_RETADDR_OFFSET 4
+-#define FRAME_LINK_OFFSET    0
+-#define STACK_BOTTOM(tsk)    STACK_LIMIT((tsk)->thread.esp0)
+-#define STACK_TOP(tsk)       ((tsk)->thread.esp0)
+-#else
+-#define UNW_FP(frame) ((void)(frame), 0)
+-#endif
+-#define STACK_LIMIT(ptr)     (((ptr) - 1) & ~(THREAD_SIZE - 1))
+-
+-#define UNW_REGISTER_INFO \
+-      PTREGS_INFO(eax), \
+-      PTREGS_INFO(ecx), \
+-      PTREGS_INFO(edx), \
+-      PTREGS_INFO(ebx), \
+-      PTREGS_INFO(esp), \
+-      PTREGS_INFO(ebp), \
+-      PTREGS_INFO(esi), \
+-      PTREGS_INFO(edi), \
+-      PTREGS_INFO(eip)
+-
+-#define UNW_DEFAULT_RA(raItem, dataAlign) \
+-      ((raItem).where == Memory && \
+-       !((raItem).value * (dataAlign) + 4))
+-
+-static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
+-                                            /*const*/ struct pt_regs *regs)
+-{
+-      if (user_mode_vm(regs))
+-              info->regs = *regs;
+-      else {
+-              memcpy(&info->regs, regs, offsetof(struct pt_regs, esp));
+-              info->regs.esp = (unsigned long)&regs->esp;
+-              info->regs.xss = __KERNEL_DS;
+-      }
+-}
+-
+-static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
+-{
+-      memset(&info->regs, 0, sizeof(info->regs));
+-      info->regs.eip = info->task->thread.eip;
+-      info->regs.xcs = __KERNEL_CS;
+-      __get_user(info->regs.ebp, (long *)info->task->thread.esp);
+-      info->regs.esp = info->task->thread.esp;
+-      info->regs.xss = __KERNEL_DS;
+-      info->regs.xds = __USER_DS;
+-      info->regs.xes = __USER_DS;
+-      info->regs.xfs = __KERNEL_PERCPU;
+-}
+-
+-extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
+-                                               asmlinkage int (*callback)(struct unwind_frame_info *,
+-                                                                          void *arg),
+-                                               void *arg);
+-
+-static inline int arch_unw_user_mode(/*const*/ struct unwind_frame_info *info)
+-{
+-      return user_mode_vm(&info->regs)
+-             || info->regs.eip < PAGE_OFFSET
+-             || (info->regs.eip >= __fix_to_virt(FIX_VDSO)
+-                 && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE)
+-             || info->regs.esp < PAGE_OFFSET;
+-}
+-
+-#else
+-
+ #define UNW_PC(frame) ((void)(frame), 0)
+ #define UNW_SP(frame) ((void)(frame), 0)
+ #define UNW_FP(frame) ((void)(frame), 0)
+@@ -99,6 +10,4 @@
+       return 0;
+ }
+-#endif
+-
+ #endif /* _ASM_I386_UNWIND_H */
+diff -Nurb linux-2.6.22-590/include/asm-ia64/kdebug.h linux-2.6.22-570/include/asm-ia64/kdebug.h
+--- linux-2.6.22-590/include/asm-ia64/kdebug.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-ia64/kdebug.h 2007-07-08 19:32:17.000000000 -0400
+@@ -69,7 +69,6 @@
+       DIE_KDEBUG_LEAVE,
+       DIE_KDUMP_ENTER,
+       DIE_KDUMP_LEAVE,
+-      DIE_PAGE_FAULT_NO_CONTEXT,
+ };
+ #endif
+diff -Nurb linux-2.6.22-590/include/asm-ia64/kgdb.h linux-2.6.22-570/include/asm-ia64/kgdb.h
+--- linux-2.6.22-590/include/asm-ia64/kgdb.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-ia64/kgdb.h   1969-12-31 19:00:00.000000000 -0500
+@@ -1,37 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef _ASM_KGDB_H_
+-#define _ASM_KGDB_H_
+-
+-/*
+- * Copyright (C) 2001-2004 Amit S. Kale
+- */
+-
+-#include <linux/threads.h>
+-#include <asm-generic/kgdb.h>
+-
+-/************************************************************************/
+-/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+-/* at least NUMREGBYTES*2 are needed for register packets */
+-/* Longer buffer is needed to list all threads */
+-#define BUFMAX                        1024
+-
+-/* Number of bytes of registers.  We set this to 0 so that certain GDB
+- * packets will fail, forcing the use of others, which are more friendly
+- * on ia64. */
+-#define NUMREGBYTES           0
+-
+-#define NUMCRITREGBYTES               (70*8)
+-#define JMP_REGS_ALIGNMENT    __attribute__ ((aligned (16)))
+-
+-#define BREAKNUM              0x00003333300LL
+-#define KGDBBREAKNUM          0x6665UL
+-#define BREAKPOINT()          asm volatile ("break.m 0x6665")
+-#define BREAK_INSTR_SIZE      16
+-#define CACHE_FLUSH_IS_SAFE   1
+-
+-struct pt_regs;
+-extern volatile int kgdb_hwbreak_sstep[NR_CPUS];
+-extern void smp_send_nmi_allbutself(void);
+-extern void kgdb_wait_ipi(struct pt_regs *);
+-#endif                                /* _ASM_KGDB_H_ */
+-#endif                                /* __KERNEL__ */
+diff -Nurb linux-2.6.22-590/include/asm-ia64/page.h linux-2.6.22-570/include/asm-ia64/page.h
+--- linux-2.6.22-590/include/asm-ia64/page.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-ia64/page.h   2007-07-08 19:32:17.000000000 -0400
+@@ -87,10 +87,9 @@
+ } while (0)
+-#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr)                \
++#define alloc_zeroed_user_highpage(vma, vaddr) \
+ ({                                            \
+-      struct page *page = alloc_page_vma(                             \
+-              GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr);  \
++      struct page *page = alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr); \
+       if (page)                               \
+               flush_dcache_page(page);        \
+       page;                                   \
+diff -Nurb linux-2.6.22-590/include/asm-ia64/processor.h linux-2.6.22-570/include/asm-ia64/processor.h
+--- linux-2.6.22-590/include/asm-ia64/processor.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-ia64/processor.h      2007-07-08 19:32:17.000000000 -0400
+@@ -295,9 +295,9 @@
+       regs->ar_bspstore = current->thread.rbs_bot;                                            \
+       regs->ar_fpsr = FPSR_DEFAULT;                                                           \
+       regs->loadrs = 0;                                                                       \
+-      regs->r8 = get_dumpable(current->mm);   /* set "don't zap registers" flag */            \
++      regs->r8 = current->mm->dumpable;       /* set "don't zap registers" flag */            \
+       regs->r12 = new_sp - 16;        /* allocate 16 byte scratch area */                     \
+-      if (unlikely(!get_dumpable(current->mm))) {                                                     \
++      if (unlikely(!current->mm->dumpable)) {                                                 \
+               /*                                                                              \
+                * Zap scratch regs to avoid leaking bits between processes with different      \
+                * uid/privileges.                                                              \
+diff -Nurb linux-2.6.22-590/include/asm-m32r/page.h linux-2.6.22-570/include/asm-m32r/page.h
+--- linux-2.6.22-590/include/asm-m32r/page.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-m32r/page.h   2007-07-08 19:32:17.000000000 -0400
+@@ -15,8 +15,7 @@
+ #define clear_user_page(page, vaddr, pg)      clear_page(page)
+ #define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
+-#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+-      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
++#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+ #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+ /*
+diff -Nurb linux-2.6.22-590/include/asm-m68knommu/page.h linux-2.6.22-570/include/asm-m68knommu/page.h
+--- linux-2.6.22-590/include/asm-m68knommu/page.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-m68knommu/page.h      2007-07-08 19:32:17.000000000 -0400
+@@ -22,8 +22,7 @@
+ #define clear_user_page(page, vaddr, pg)      clear_page(page)
+ #define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
+-#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+-      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
++#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+ #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+ /*
+diff -Nurb linux-2.6.22-590/include/asm-mips/asmmacro-32.h linux-2.6.22-570/include/asm-mips/asmmacro-32.h
+--- linux-2.6.22-590/include/asm-mips/asmmacro-32.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-mips/asmmacro-32.h    2007-07-08 19:32:17.000000000 -0400
+@@ -11,28 +11,6 @@
+ #include <asm/regdef.h>
+ #include <asm/fpregdef.h>
+ #include <asm/mipsregs.h>
+-#include <asm/gdb-stub.h>
+-
+-      .macro  fpu_save_double_kgdb stack status tmp1=t0
+-      cfc1    \tmp1,  fcr31
+-      sdc1    $f0, GDB_FR_FPR0(\stack)
+-      sdc1    $f2, GDB_FR_FPR2(\stack)
+-      sdc1    $f4, GDB_FR_FPR4(\stack)
+-      sdc1    $f6, GDB_FR_FPR6(\stack)
+-      sdc1    $f8, GDB_FR_FPR8(\stack)
+-      sdc1    $f10, GDB_FR_FPR10(\stack)
+-      sdc1    $f12, GDB_FR_FPR12(\stack)
+-      sdc1    $f14, GDB_FR_FPR14(\stack)
+-      sdc1    $f16, GDB_FR_FPR16(\stack)
+-      sdc1    $f18, GDB_FR_FPR18(\stack)
+-      sdc1    $f20, GDB_FR_FPR20(\stack)
+-      sdc1    $f22, GDB_FR_FPR22(\stack)
+-      sdc1    $f24, GDB_FR_FPR24(\stack)
+-      sdc1    $f26, GDB_FR_FPR26(\stack)
+-      sdc1    $f28, GDB_FR_FPR28(\stack)
+-      sdc1    $f30, GDB_FR_FPR30(\stack)
+-      sw      \tmp1, GDB_FR_FSR(\stack)
+-      .endm
+       .macro  fpu_save_double thread status tmp1=t0
+       cfc1    \tmp1,  fcr31
+@@ -113,27 +91,6 @@
+       ctc1    \tmp, fcr31
+       .endm
+-      .macro  fpu_restore_double_kgdb stack status tmp=t0
+-      lw      \tmp, GDB_FR_FSR(\stack)
+-      ldc1    $f0,  GDB_FR_FPR0(\stack)
+-      ldc1    $f2,  GDB_FR_FPR2(\stack)
+-      ldc1    $f4,  GDB_FR_FPR4(\stack)
+-      ldc1    $f6,  GDB_FR_FPR6(\stack)
+-      ldc1    $f8,  GDB_FR_FPR8(\stack)
+-      ldc1    $f10, GDB_FR_FPR10(\stack)
+-      ldc1    $f12, GDB_FR_FPR12(\stack)
+-      ldc1    $f14, GDB_FR_FPR14(\stack)
+-      ldc1    $f16, GDB_FR_FPR16(\stack)
+-      ldc1    $f18, GDB_FR_FPR18(\stack)
+-      ldc1    $f20, GDB_FR_FPR20(\stack)
+-      ldc1    $f22, GDB_FR_FPR22(\stack)
+-      ldc1    $f24, GDB_FR_FPR24(\stack)
+-      ldc1    $f26, GDB_FR_FPR26(\stack)
+-      ldc1    $f28, GDB_FR_FPR28(\stack)
+-      ldc1    $f30, GDB_FR_FPR30(\stack)
+-      ctc1    \tmp, fcr31
+-      .endm
+-
+       .macro  fpu_restore_single thread tmp=t0
+       lw      \tmp, THREAD_FCR31(\thread)
+       lwc1    $f0,  THREAD_FPR0(\thread)
+diff -Nurb linux-2.6.22-590/include/asm-mips/asmmacro-64.h linux-2.6.22-570/include/asm-mips/asmmacro-64.h
+--- linux-2.6.22-590/include/asm-mips/asmmacro-64.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-mips/asmmacro-64.h    2007-07-08 19:32:17.000000000 -0400
+@@ -12,7 +12,6 @@
+ #include <asm/regdef.h>
+ #include <asm/fpregdef.h>
+ #include <asm/mipsregs.h>
+-#include <asm/gdb-stub.h>
+       .macro  fpu_save_16even thread tmp=t0
+       cfc1    \tmp, fcr31
+@@ -54,46 +53,6 @@
+       sdc1    $f31, THREAD_FPR31(\thread)
+       .endm
+-      .macro  fpu_save_16odd_kgdb stack
+-      sdc1    $f1, GDB_FR_FPR1(\stack)
+-      sdc1    $f3, GDB_FR_FPR3(\stack)
+-      sdc1    $f5, GDB_FR_FPR5(\stack)
+-      sdc1    $f7, GDB_FR_FPR7(\stack)
+-      sdc1    $f9, GDB_FR_FPR9(\stack)
+-      sdc1    $f11, GDB_FR_FPR11(\stack)
+-      sdc1    $f13, GDB_FR_FPR13(\stack)
+-      sdc1    $f15, GDB_FR_FPR15(\stack)
+-      sdc1    $f17, GDB_FR_FPR17(\stack)
+-      sdc1    $f19, GDB_FR_FPR19(\stack)
+-      sdc1    $f21, GDB_FR_FPR21(\stack)
+-      sdc1    $f23, GDB_FR_FPR23(\stack)
+-      sdc1    $f25, GDB_FR_FPR25(\stack)
+-      sdc1    $f27, GDB_FR_FPR27(\stack)
+-      sdc1    $f29, GDB_FR_FPR29(\stack)
+-      sdc1    $f31, GDB_FR_FPR31(\stack)
+-      .endm
+-
+-      .macro  fpu_save_16even_kgdb stack tmp=t0
+-      cfc1    \tmp,  fcr31
+-      sdc1    $f0, GDB_FR_FPR0(\stack)
+-      sdc1    $f2, GDB_FR_FPR2(\stack)
+-      sdc1    $f4, GDB_FR_FPR4(\stack)
+-      sdc1    $f6, GDB_FR_FPR6(\stack)
+-      sdc1    $f8, GDB_FR_FPR8(\stack)
+-      sdc1    $f10, GDB_FR_FPR10(\stack)
+-      sdc1    $f12, GDB_FR_FPR12(\stack)
+-      sdc1    $f14, GDB_FR_FPR14(\stack)
+-      sdc1    $f16, GDB_FR_FPR16(\stack)
+-      sdc1    $f18, GDB_FR_FPR18(\stack)
+-      sdc1    $f20, GDB_FR_FPR20(\stack)
+-      sdc1    $f22, GDB_FR_FPR22(\stack)
+-      sdc1    $f24, GDB_FR_FPR24(\stack)
+-      sdc1    $f26, GDB_FR_FPR26(\stack)
+-      sdc1    $f28, GDB_FR_FPR28(\stack)
+-      sdc1    $f30, GDB_FR_FPR30(\stack)
+-      sw      \tmp, GDB_FR_FSR(\stack)
+-      .endm
+-
+       .macro  fpu_save_double thread status tmp
+       sll     \tmp, \status, 5
+       bgez    \tmp, 2f
+@@ -102,15 +61,6 @@
+       fpu_save_16even \thread \tmp
+       .endm
+-      .macro  fpu_save_double_kgdb stack status tmp
+-      sll     \tmp, \status, 5
+-      bgez    \tmp, 2f
+-      nop
+-      fpu_save_16odd_kgdb \stack
+-2:
+-      fpu_save_16even_kgdb \stack \tmp
+-      .endm
+-
+       .macro  fpu_restore_16even thread tmp=t0
+       lw      \tmp, THREAD_FCR31(\thread)
+       ldc1    $f0,  THREAD_FPR0(\thread)
+@@ -151,46 +101,6 @@
+       ldc1    $f31, THREAD_FPR31(\thread)
+       .endm
+-      .macro  fpu_restore_16even_kgdb stack tmp=t0
+-      lw      \tmp, GDB_FR_FSR(\stack)
+-      ldc1    $f0,  GDB_FR_FPR0(\stack)
+-      ldc1    $f2,  GDB_FR_FPR2(\stack)
+-      ldc1    $f4,  GDB_FR_FPR4(\stack)
+-      ldc1    $f6,  GDB_FR_FPR6(\stack)
+-      ldc1    $f8,  GDB_FR_FPR8(\stack)
+-      ldc1    $f10, GDB_FR_FPR10(\stack)
+-      ldc1    $f12, GDB_FR_FPR12(\stack)
+-      ldc1    $f14, GDB_FR_FPR14(\stack)
+-      ldc1    $f16, GDB_FR_FPR16(\stack)
+-      ldc1    $f18, GDB_FR_FPR18(\stack)
+-      ldc1    $f20, GDB_FR_FPR20(\stack)
+-      ldc1    $f22, GDB_FR_FPR22(\stack)
+-      ldc1    $f24, GDB_FR_FPR24(\stack)
+-      ldc1    $f26, GDB_FR_FPR26(\stack)
+-      ldc1    $f28, GDB_FR_FPR28(\stack)
+-      ldc1    $f30, GDB_FR_FPR30(\stack)
+-      ctc1    \tmp, fcr31
+-      .endm
+-
+-      .macro  fpu_restore_16odd_kgdb stack
+-      ldc1    $f1,  GDB_FR_FPR1(\stack)
+-      ldc1    $f3,  GDB_FR_FPR3(\stack)
+-      ldc1    $f5,  GDB_FR_FPR5(\stack)
+-      ldc1    $f7,  GDB_FR_FPR7(\stack)
+-      ldc1    $f9,  GDB_FR_FPR9(\stack)
+-      ldc1    $f11, GDB_FR_FPR11(\stack)
+-      ldc1    $f13, GDB_FR_FPR13(\stack)
+-      ldc1    $f15, GDB_FR_FPR15(\stack)
+-      ldc1    $f17, GDB_FR_FPR17(\stack)
+-      ldc1    $f19, GDB_FR_FPR19(\stack)
+-      ldc1    $f21, GDB_FR_FPR21(\stack)
+-      ldc1    $f23, GDB_FR_FPR23(\stack)
+-      ldc1    $f25, GDB_FR_FPR25(\stack)
+-      ldc1    $f27, GDB_FR_FPR27(\stack)
+-      ldc1    $f29, GDB_FR_FPR29(\stack)
+-      ldc1    $f31, GDB_FR_FPR31(\stack)
+-      .endm
+-
+       .macro  fpu_restore_double thread status tmp
+       sll     \tmp, \status, 5
+       bgez    \tmp, 1f                                # 16 register mode?
+@@ -199,15 +109,6 @@
+ 1:    fpu_restore_16even \thread \tmp
+       .endm
+-      .macro  fpu_restore_double_kgdb stack status tmp
+-      sll     \tmp, \status, 5
+-      bgez    \tmp, 1f                                # 16 register mode?
+-      nop
+-
+-      fpu_restore_16odd_kgdb \stack
+-1:    fpu_restore_16even_kgdb \stack \tmp
+-      .endm
+-
+       .macro  cpu_save_nonscratch thread
+       LONG_S  s0, THREAD_REG16(\thread)
+       LONG_S  s1, THREAD_REG17(\thread)
+diff -Nurb linux-2.6.22-590/include/asm-mips/kdebug.h linux-2.6.22-570/include/asm-mips/kdebug.h
+--- linux-2.6.22-590/include/asm-mips/kdebug.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-mips/kdebug.h 2007-07-08 19:32:17.000000000 -0400
+@@ -1,30 +1 @@
+-/*
+- *
+- * Copyright (C) 2004  MontaVista Software Inc.
+- * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.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.
+- *
+- */
+-#ifndef _MIPS_KDEBUG_H
+-#define _MIPS_KDEBUG_H
+-
+-#include <linux/notifier.h>
+-
+-struct pt_regs;
+-
+-extern struct atomic_notifier_head mips_die_head;
+-
+-enum die_val {
+-      DIE_OOPS = 1,
+-      DIE_PANIC,
+-      DIE_DIE,
+-      DIE_KERNELDEBUG,
+-      DIE_TRAP,
+-      DIE_PAGE_FAULT,
+-};
+-
+-#endif /* _MIPS_KDEBUG_H */
++#include <asm-generic/kdebug.h>
+diff -Nurb linux-2.6.22-590/include/asm-mips/kgdb.h linux-2.6.22-570/include/asm-mips/kgdb.h
+--- linux-2.6.22-590/include/asm-mips/kgdb.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-mips/kgdb.h   1969-12-31 19:00:00.000000000 -0500
+@@ -1,41 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef _ASM_KGDB_H_
+-#define _ASM_KGDB_H_
+-
+-#include <asm/sgidefs.h>
+-#include <asm-generic/kgdb.h>
+-
+-#ifndef __ASSEMBLY__
+-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS32)
+-
+-typedef u32 gdb_reg_t;
+-
+-#elif (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
+-
+-#ifdef CONFIG_32BIT
+-typedef u32 gdb_reg_t;
+-#else /* CONFIG_CPU_32BIT */
+-typedef u64 gdb_reg_t;
+-#endif
+-#else
+-#error "Need to set typedef for gdb_reg_t"
+-#endif /* _MIPS_ISA */
+-
+-#define BUFMAX                        2048
+-#define NUMREGBYTES           (90*sizeof(gdb_reg_t))
+-#define NUMCRITREGBYTES               (12*sizeof(gdb_reg_t))
+-#define BREAK_INSTR_SIZE      4
+-#define BREAKPOINT()          __asm__ __volatile__(           \
+-                                      ".globl breakinst\n\t"  \
+-                                      ".set\tnoreorder\n\t"   \
+-                                      "nop\n"                 \
+-                                      "breakinst:\tbreak\n\t" \
+-                                      "nop\n\t"               \
+-                                      ".set\treorder")
+-#define CACHE_FLUSH_IS_SAFE   0
+-
+-extern int kgdb_early_setup;
+-
+-#endif                                /* !__ASSEMBLY__ */
+-#endif                                /* _ASM_KGDB_H_ */
+-#endif                                /* __KERNEL__ */
+diff -Nurb linux-2.6.22-590/include/asm-mips/ptrace.h linux-2.6.22-570/include/asm-mips/ptrace.h
+--- linux-2.6.22-590/include/asm-mips/ptrace.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-mips/ptrace.h 2007-07-08 19:32:17.000000000 -0400
+@@ -28,7 +28,7 @@
+  * system call/exception. As usual the registers k0/k1 aren't being saved.
+  */
+ struct pt_regs {
+-#if defined(CONFIG_32BIT) || defined(CONFIG_KGDB)
++#ifdef CONFIG_32BIT
+       /* Pad bytes for argument save space on the stack. */
+       unsigned long pad0[6];
+ #endif
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/cputable.h linux-2.6.22-570/include/asm-powerpc/cputable.h
+--- linux-2.6.22-590/include/asm-powerpc/cputable.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/cputable.h    2007-07-08 19:32:17.000000000 -0400
+@@ -111,7 +111,7 @@
+ /* CPU kernel features */
+ /* Retain the 32b definitions all use bottom half of word */
+-#define CPU_FTR_COHERENT_ICACHE               ASM_CONST(0x0000000000000001)
++#define CPU_FTR_SPLIT_ID_CACHE                ASM_CONST(0x0000000000000001)
+ #define CPU_FTR_L2CR                  ASM_CONST(0x0000000000000002)
+ #define CPU_FTR_SPEC7450              ASM_CONST(0x0000000000000004)
+ #define CPU_FTR_ALTIVEC                       ASM_CONST(0x0000000000000008)
+@@ -135,7 +135,6 @@
+ #define CPU_FTR_PPC_LE                        ASM_CONST(0x0000000000200000)
+ #define CPU_FTR_REAL_LE                       ASM_CONST(0x0000000000400000)
+ #define CPU_FTR_FPU_UNAVAILABLE               ASM_CONST(0x0000000000800000)
+-#define CPU_FTR_UNIFIED_ID_CACHE      ASM_CONST(0x0000000001000000)
+ /*
+  * Add the 64-bit processor unique features in the top half of the word;
+@@ -155,6 +154,7 @@
+ #define CPU_FTR_MMCRA                 LONG_ASM_CONST(0x0000004000000000)
+ #define CPU_FTR_CTRL                  LONG_ASM_CONST(0x0000008000000000)
+ #define CPU_FTR_SMT                   LONG_ASM_CONST(0x0000010000000000)
++#define CPU_FTR_COHERENT_ICACHE               LONG_ASM_CONST(0x0000020000000000)
+ #define CPU_FTR_LOCKLESS_TLBIE                LONG_ASM_CONST(0x0000040000000000)
+ #define CPU_FTR_CI_LARGE_PAGE         LONG_ASM_CONST(0x0000100000000000)
+ #define CPU_FTR_PAUSE_ZERO            LONG_ASM_CONST(0x0000200000000000)
+@@ -206,163 +206,164 @@
+                    !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
+                    !defined(CONFIG_BOOKE))
+-#define CPU_FTRS_PPC601       (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE | \
+-      CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
+-#define CPU_FTRS_603  (CPU_FTR_COMMON | \
++#define CPU_FTRS_PPC601       (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE)
++#define CPU_FTRS_603  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
+           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_604  (CPU_FTR_COMMON | \
++#define CPU_FTRS_604  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \
+           CPU_FTR_PPC_LE)
+-#define CPU_FTRS_740_NOTAU    (CPU_FTR_COMMON | \
++#define CPU_FTRS_740_NOTAU    (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_740  (CPU_FTR_COMMON | \
++#define CPU_FTRS_740  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+           CPU_FTR_PPC_LE)
+-#define CPU_FTRS_750  (CPU_FTR_COMMON | \
++#define CPU_FTRS_750  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+           CPU_FTR_PPC_LE)
+-#define CPU_FTRS_750CL        (CPU_FTR_COMMON | \
++#define CPU_FTRS_750CL        (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+           CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_750FX1       (CPU_FTR_COMMON | \
++#define CPU_FTRS_750FX1       (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+           CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_750FX2       (CPU_FTR_COMMON | \
++#define CPU_FTRS_750FX2       (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+           CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_750FX        (CPU_FTR_COMMON | \
++#define CPU_FTRS_750FX        (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+           CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_750GX        (CPU_FTR_COMMON | \
++#define CPU_FTRS_750GX        (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+           CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_7400_NOTAU   (CPU_FTR_COMMON | \
++#define CPU_FTRS_7400_NOTAU   (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+           CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
+           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_7400 (CPU_FTR_COMMON | \
++#define CPU_FTRS_7400 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+           CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
+           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_7450_20      (CPU_FTR_COMMON | \
++#define CPU_FTRS_7450_20      (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+           CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_7450_21      (CPU_FTR_COMMON | \
++#define CPU_FTRS_7450_21      (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_USE_TB | \
+           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
+           CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_7450_23      (CPU_FTR_COMMON | \
++#define CPU_FTRS_7450_23      (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_USE_TB | \
+           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_7455_1       (CPU_FTR_COMMON | \
++#define CPU_FTRS_7455_1       (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_USE_TB | \
+           CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \
+           CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_7455_20      (CPU_FTR_COMMON | \
++#define CPU_FTRS_7455_20      (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_USE_TB | \
+           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
+           CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_7455 (CPU_FTR_COMMON | \
++#define CPU_FTRS_7455 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_USE_TB | \
+           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+           CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_7447_10      (CPU_FTR_COMMON | \
++#define CPU_FTRS_7447_10      (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_USE_TB | \
+           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+           CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_7447 (CPU_FTR_COMMON | \
++#define CPU_FTRS_7447 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_USE_TB | \
+           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+           CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+           CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_7447A        (CPU_FTR_COMMON | \
++#define CPU_FTRS_7447A        (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_USE_TB | \
+           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+           CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_7448 (CPU_FTR_COMMON | \
++#define CPU_FTRS_7448 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_USE_TB | \
+           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+           CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+           CPU_FTR_PPC_LE)
+-#define CPU_FTRS_82XX (CPU_FTR_COMMON | \
++#define CPU_FTRS_82XX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
+-#define CPU_FTRS_G2_LE        (CPU_FTR_MAYBE_CAN_DOZE | \
++#define CPU_FTRS_G2_LE        (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+           CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS)
+-#define CPU_FTRS_E300 (CPU_FTR_MAYBE_CAN_DOZE | \
++#define CPU_FTRS_E300 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+           CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
+           CPU_FTR_COMMON)
+-#define CPU_FTRS_E300C2       (CPU_FTR_MAYBE_CAN_DOZE | \
++#define CPU_FTRS_E300C2       (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+           CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
+           CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE)
+-#define CPU_FTRS_CLASSIC32    (CPU_FTR_COMMON | \
++#define CPU_FTRS_CLASSIC32    (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+           CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
+-#define CPU_FTRS_8XX  (CPU_FTR_USE_TB)
+-#define CPU_FTRS_40X  (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+-#define CPU_FTRS_44X  (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+-#define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
+-          CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
+-#define CPU_FTRS_E500 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+-#define CPU_FTRS_E500_2       (CPU_FTR_USE_TB | \
++#define CPU_FTRS_8XX  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
++#define CPU_FTRS_40X  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
++          CPU_FTR_NODSISRALIGN)
++#define CPU_FTRS_44X  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
++          CPU_FTR_NODSISRALIGN)
++#define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
++#define CPU_FTRS_E500 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
++          CPU_FTR_NODSISRALIGN)
++#define CPU_FTRS_E500_2       (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+           CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN)
+ #define CPU_FTRS_GENERIC_32   (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
+ /* 64-bit CPUs */
+-#define CPU_FTRS_POWER3       (CPU_FTR_USE_TB | \
++#define CPU_FTRS_POWER3       (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE)
+-#define CPU_FTRS_RS64 (CPU_FTR_USE_TB | \
++#define CPU_FTRS_RS64 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
+           CPU_FTR_MMCRA | CPU_FTR_CTRL)
+-#define CPU_FTRS_POWER4       (CPU_FTR_USE_TB | \
++#define CPU_FTRS_POWER4       (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
+           CPU_FTR_MMCRA)
+-#define CPU_FTRS_PPC970       (CPU_FTR_USE_TB | \
++#define CPU_FTRS_PPC970       (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
+           CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
+-#define CPU_FTRS_POWER5       (CPU_FTR_USE_TB | \
++#define CPU_FTRS_POWER5       (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
+           CPU_FTR_MMCRA | CPU_FTR_SMT | \
+           CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
+           CPU_FTR_PURR)
+-#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | \
++#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
+           CPU_FTR_MMCRA | CPU_FTR_SMT | \
+           CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
+           CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
+           CPU_FTR_DSCR)
+-#define CPU_FTRS_CELL (CPU_FTR_USE_TB | \
++#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
+           CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
+           CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG)
+-#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \
++#define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+           CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
+           CPU_FTR_PURR | CPU_FTR_REAL_LE)
+-#define CPU_FTRS_COMPATIBLE   (CPU_FTR_USE_TB | \
++#define CPU_FTRS_COMPATIBLE   (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+           CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
+ #ifdef __powerpc64__
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/floppy.h linux-2.6.22-570/include/asm-powerpc/floppy.h
+--- linux-2.6.22-590/include/asm-powerpc/floppy.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/floppy.h      2007-07-08 19:32:17.000000000 -0400
+@@ -29,7 +29,7 @@
+ #define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL);
+ #include <linux/pci.h>
+-#include <asm/ppc-pci.h>      /* for isa_bridge_pcidev */
++#include <asm/ppc-pci.h>      /* for ppc64_isabridge_dev */
+ #define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io)
+@@ -139,12 +139,12 @@
+       if (bus_addr 
+           && (addr != prev_addr || size != prev_size || dir != prev_dir)) {
+               /* different from last time -- unmap prev */
+-              pci_unmap_single(isa_bridge_pcidev, 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(isa_bridge_pcidev, addr, size, dir);
++              bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir);
+       /* remember this one as prev */
+       prev_addr = addr;
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/io.h linux-2.6.22-570/include/asm-powerpc/io.h
+--- linux-2.6.22-590/include/asm-powerpc/io.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/io.h  2007-07-08 19:32:17.000000000 -0400
+@@ -607,9 +607,9 @@
+  *
+  * * iounmap undoes such a mapping and can be hooked
+  *
+- * * __ioremap_at (and the pending __iounmap_at) are low level functions to
+- *   create hand-made mappings for use only by the PCI code and cannot
+- *   currently be hooked. Must be page aligned.
++ * * __ioremap_explicit (and the pending __iounmap_explicit) are low level
++ *   functions to create hand-made mappings for use only by the PCI code
++ *   and cannot currently be hooked.
+  *
+  * * __ioremap is the low level implementation used by ioremap and
+  *   ioremap_flags and cannot be hooked (but can be used by a hook on one
+@@ -629,9 +629,19 @@
+                              unsigned long flags);
+ extern void __iounmap(volatile void __iomem *addr);
+-extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea,
++extern int __ioremap_explicit(phys_addr_t p_addr, unsigned long v_addr,
+                             unsigned long size, unsigned long flags);
+-extern void __iounmap_at(void *ea, unsigned long size);
++extern int __iounmap_explicit(volatile void __iomem *start,
++                            unsigned long size);
 +
-+                      /* Query thread status */
-+              case 'T':
-+                      ptr = &remcom_in_buffer[1];
-+                      kgdb_hex2long(&ptr, &threadid);
-+                      thread = getthread(linux_regs, threadid);
-+                      if (thread)
-+                              strcpy(remcom_out_buffer, "OK");
-+                      else
-+                              error_packet(remcom_out_buffer, -EINVAL);
-+                      break;
-+              /* Since GDB-5.3, it's been drafted that '0' is a software
-+               * breakpoint, '1' is a hardware breakpoint, so let's do
-+               * that.
-+               */
-+              case 'z':
-+              case 'Z':
-+                      bpt_type = &remcom_in_buffer[1];
-+                      ptr = &remcom_in_buffer[2];
-+
-+                      if (kgdb_ops->set_hw_breakpoint && *bpt_type >= '1') {
-+                              /* Unsupported */
-+                              if (*bpt_type > '4')
-+                                      break;
-+                      } else if (*bpt_type != '0' && *bpt_type != '1')
-+                              /* Unsupported. */
-+                              break;
-+                      /* Test if this is a hardware breakpoint, and
-+                       * if we support it. */
-+                      if (*bpt_type == '1' &&
-+                          !(kgdb_ops->flags & KGDB_HW_BREAKPOINT))
-+                              /* Unsupported. */
-+                              break;
++extern void __iomem * reserve_phb_iospace(unsigned long size);
 +
-+                      if (*(ptr++) != ',') {
-+                              error_packet(remcom_out_buffer, -EINVAL);
-+                              break;
-+                      } else if (kgdb_hex2long(&ptr, &addr)) {
-+                              if (*(ptr++) != ',' ||
-+                                  !kgdb_hex2long(&ptr, &length)) {
-+                                      error_packet(remcom_out_buffer,
-+                                                   -EINVAL);
-+                                      break;
-+                              }
-+                      } else {
-+                              error_packet(remcom_out_buffer, -EINVAL);
-+                              break;
-+                      }
++/* Those are more 32 bits only functions */
++extern unsigned long iopa(unsigned long addr);
++extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
++extern void io_block_mapping(unsigned long virt, phys_addr_t phys,
++                           unsigned int size, int flags);
 +
-+                      if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0')
-+                              error = kgdb_set_sw_break(addr);
-+                      else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0')
-+                              error = kgdb_remove_sw_break(addr);
-+                      else if (remcom_in_buffer[0] == 'Z')
-+                              error = kgdb_ops->set_hw_breakpoint(addr,
-+                                                                  (int)length,
-+                                                                  *bpt_type);
-+                      else if (remcom_in_buffer[0] == 'z')
-+                              error = kgdb_ops->remove_hw_breakpoint(addr,
-+                                                                     (int)
-+                                                                     length,
-+                                                                     *bpt_type);
-+
-+                      if (error == 0)
-+                              strcpy(remcom_out_buffer, "OK");
-+                      else
-+                              error_packet(remcom_out_buffer, error);
+ /*
+  * When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation
+@@ -641,8 +651,8 @@
+  */
+ #define HAVE_ARCH_PIO_SIZE            1
+ #define PIO_OFFSET                    0x00000000UL
+-#define PIO_MASK                      (FULL_IO_SIZE - 1)
+-#define PIO_RESERVED                  (FULL_IO_SIZE)
++#define PIO_MASK                      0x3fffffffUL
++#define PIO_RESERVED                  0x40000000UL
+ #define mmio_read16be(addr)           readw_be(addr)
+ #define mmio_read32be(addr)           readl_be(addr)
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/kgdb.h linux-2.6.22-570/include/asm-powerpc/kgdb.h
+--- linux-2.6.22-590/include/asm-powerpc/kgdb.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/kgdb.h        1969-12-31 19:00:00.000000000 -0500
+@@ -1,75 +0,0 @@
+-/*
+- * include/asm-powerpc/kgdb.h
+- *
+- * The PowerPC (32/64) specific defines / externs for KGDB.  Based on
+- * the previous 32bit and 64bit specific files, which had the following
+- * copyrights:
+- *
+- * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
+- * PPC Mods (C) 2004 Tom Rini (trini@mvista.com)
+- * PPC Mods (C) 2003 John Whitney (john.whitney@timesys.com)
+- * PPC Mods (C) 1998 Michael Tesch (tesch@cs.wisc.edu)
+- *
+- *
+- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+- * Author: Tom Rini <trini@kernel.crashing.org>
+- *
+- * 2006 (c) MontaVista Software, Inc. This file is licensed under
+- * the terms of the GNU General Public License version 2. This program
+- * is licensed "as is" without any warranty of any kind, whether express
+- * or implied.
+- */
+-#ifdef __KERNEL__
+-#ifndef __POWERPC_KGDB_H__
+-#define __POWERPC_KGDB_H__
+-
+-#include <asm-generic/kgdb.h>
+-
+-#ifndef __ASSEMBLY__
+-
+-#define BREAK_INSTR_SIZE      4
+-#define BUFMAX                        ((NUMREGBYTES * 2) + 512)
+-#define OUTBUFMAX             ((NUMREGBYTES * 2) + 512)
+-#define BREAKPOINT()          asm(".long 0x7d821008"); /* twge r2, r2 */
+-#define CACHE_FLUSH_IS_SAFE   1
+-
+-/* The number bytes of registers we have to save depends on a few
+- * things.  For 64bit we default to not including vector registers and
+- * vector state registers. */
+-#ifdef CONFIG_PPC64
+-/*
+- * 64 bit (8 byte) registers:
+- *   32 gpr, 32 fpr, nip, msr, link, ctr
+- * 32 bit (4 byte) registers:
+- *   ccr, xer, fpscr
+- */
+-#define NUMREGBYTES           ((68 * 8) + (3 * 4))
+-#if 0
+-/* The following adds in vector registers and vector state registers. */
+-/* 128 bit (16 byte) registers:
+- *   32 vr
+- * 64 bit (8 byte) registers:
+- *   32 gpr, 32 fpr, nip, msr, link, ctr
+- * 32 bit (4 byte) registers:
+- *   ccr, xer, fpscr, vscr, vrsave
+- */
+-#define NUMREGBYTES           ((128 * 16) + (68 * 8) + (5 * 4))
+-#endif
+-#define NUMCRITREGBYTES               184
+-#else /* CONFIG_PPC32 */
+-/* On non-E500 family PPC32 we determine the size by picking the last
+- * register we need, but on E500 we skip sections so we list what we
+- * need to store, and add it up. */
+-#ifndef CONFIG_E500
+-#define MAXREG                        (PT_FPSCR+1)
+-#else
+-/* 32 GPRs (8 bytes), nip, msr, ccr, link, ctr, xer, acc (8 bytes), spefscr*/
+-#define MAXREG                 ((32*2)+6+2+1)
+-#endif
+-#define NUMREGBYTES           (MAXREG * sizeof(int))
+-/* CR/LR, R1, R2, R13-R31 inclusive. */
+-#define NUMCRITREGBYTES               (23 * sizeof(int))
+-#endif /* 32/64 */
+-#endif /* !(__ASSEMBLY__) */
+-#endif /* !__POWERPC_KGDB_H__ */
+-#endif /* __KERNEL__ */
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/lppaca.h linux-2.6.22-570/include/asm-powerpc/lppaca.h
+--- linux-2.6.22-590/include/asm-powerpc/lppaca.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/lppaca.h      2007-07-08 19:32:17.000000000 -0400
+@@ -98,7 +98,7 @@
+       u64     saved_gpr5;             // Saved GPR5                   x30-x37
+       u8      reserved4;              // Reserved                     x38-x38
+-      u8      donate_dedicated_cpu;   // Donate dedicated CPU cycles  x39-x39
++      u8      cpuctls_task_attrs;     // Task attributes for cpuctls  x39-x39
+       u8      fpregs_in_use;          // FP regs in use               x3A-x3A
+       u8      pmcregs_in_use;         // PMC regs in use              x3B-x3B
+       volatile u32 saved_decr;        // Saved Decr Value             x3C-x3F
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/mmu-hash32.h linux-2.6.22-570/include/asm-powerpc/mmu-hash32.h
+--- linux-2.6.22-590/include/asm-powerpc/mmu-hash32.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/mmu-hash32.h  1969-12-31 19:00:00.000000000 -0500
+@@ -1,91 +0,0 @@
+-#ifndef _ASM_POWERPC_MMU_HASH32_H_
+-#define _ASM_POWERPC_MMU_HASH32_H_
+-/*
+- * 32-bit hash table MMU support
+- */
+-
+-/*
+- * BATs
+- */
+-
+-/* Block size masks */
+-#define BL_128K       0x000
+-#define BL_256K 0x001
+-#define BL_512K 0x003
+-#define BL_1M   0x007
+-#define BL_2M   0x00F
+-#define BL_4M   0x01F
+-#define BL_8M   0x03F
+-#define BL_16M  0x07F
+-#define BL_32M  0x0FF
+-#define BL_64M  0x1FF
+-#define BL_128M 0x3FF
+-#define BL_256M 0x7FF
+-
+-/* BAT Access Protection */
+-#define BPP_XX        0x00            /* No access */
+-#define BPP_RX        0x01            /* Read only */
+-#define BPP_RW        0x02            /* Read/write */
+-
+-#ifndef __ASSEMBLY__
+-struct ppc_bat {
+-      struct {
+-              unsigned long bepi:15;  /* Effective page index (virtual address) */
+-              unsigned long :4;       /* Unused */
+-              unsigned long bl:11;    /* Block size mask */
+-              unsigned long vs:1;     /* Supervisor valid */
+-              unsigned long vp:1;     /* User valid */
+-      } batu;                 /* Upper register */
+-      struct {
+-              unsigned long brpn:15;  /* Real page index (physical address) */
+-              unsigned long :10;      /* Unused */
+-              unsigned long w:1;      /* Write-thru cache */
+-              unsigned long i:1;      /* Cache inhibit */
+-              unsigned long m:1;      /* Memory coherence */
+-              unsigned long g:1;      /* Guarded (MBZ in IBAT) */
+-              unsigned long :1;       /* Unused */
+-              unsigned long pp:2;     /* Page access protections */
+-      } batl;                 /* Lower register */
+-};
+-#endif /* !__ASSEMBLY__ */
+-
+-/*
+- * Hash table
+- */
+-
+-/* Values for PP (assumes Ks=0, Kp=1) */
+-#define PP_RWXX       0       /* Supervisor read/write, User none */
+-#define PP_RWRX 1     /* Supervisor read/write, User read */
+-#define PP_RWRW 2     /* Supervisor read/write, User read/write */
+-#define PP_RXRX 3     /* Supervisor read,       User read */
+-
+-#ifndef __ASSEMBLY__
+-
+-/* Hardware Page Table Entry */
+-struct hash_pte {
+-      unsigned long v:1;      /* Entry is valid */
+-      unsigned long vsid:24;  /* Virtual segment identifier */
+-      unsigned long h:1;      /* Hash algorithm indicator */
+-      unsigned long api:6;    /* Abbreviated page index */
+-      unsigned long rpn:20;   /* Real (physical) page number */
+-      unsigned long    :3;    /* Unused */
+-      unsigned long r:1;      /* Referenced */
+-      unsigned long c:1;      /* Changed */
+-      unsigned long w:1;      /* Write-thru cache mode */
+-      unsigned long i:1;      /* Cache inhibited */
+-      unsigned long m:1;      /* Memory coherence */
+-      unsigned long g:1;      /* Guarded */
+-      unsigned long  :1;      /* Unused */
+-      unsigned long pp:2;     /* Page protection */
+-};
+-
+-typedef struct {
+-      unsigned long id;
+-      unsigned long vdso_base;
+-} mm_context_t;
+-
+-typedef unsigned long phys_addr_t;
+-
+-#endif /* !__ASSEMBLY__ */
+-
+-#endif /* _ASM_POWERPC_MMU_HASH32_H_ */
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/mmu-hash64.h linux-2.6.22-570/include/asm-powerpc/mmu-hash64.h
+--- linux-2.6.22-590/include/asm-powerpc/mmu-hash64.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/mmu-hash64.h  2007-07-08 19:32:17.000000000 -0400
+@@ -103,12 +103,12 @@
+ #ifndef __ASSEMBLY__
+-struct hash_pte {
++typedef struct {
+       unsigned long v;
+       unsigned long r;
+-};
++} hpte_t;
+-extern struct hash_pte *htab_address;
++extern hpte_t *htab_address;
+ extern unsigned long htab_size_bytes;
+ extern unsigned long htab_hash_mask;
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/mmu.h linux-2.6.22-570/include/asm-powerpc/mmu.h
+--- linux-2.6.22-590/include/asm-powerpc/mmu.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/mmu.h 2007-07-08 19:32:17.000000000 -0400
+@@ -5,9 +5,6 @@
+ #ifdef CONFIG_PPC64
+ /* 64-bit classic hash table MMU */
+ #  include <asm/mmu-hash64.h>
+-#elif defined(CONFIG_PPC_STD_MMU)
+-/* 32-bit classic hash table MMU */
+-#  include <asm/mmu-hash32.h>
+ #elif defined(CONFIG_44x)
+ /* 44x-style software loaded TLB */
+ #  include <asm/mmu-44x.h>
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/pci-bridge.h linux-2.6.22-570/include/asm-powerpc/pci-bridge.h
+--- linux-2.6.22-590/include/asm-powerpc/pci-bridge.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/pci-bridge.h  2007-07-08 19:32:17.000000000 -0400
+@@ -31,7 +31,6 @@
+       int last_busno;
+       void __iomem *io_base_virt;
+-      void *io_base_alloc;
+       resource_size_t io_base_phys;
+       /* Some machines have a non 1:1 mapping of
+@@ -71,22 +70,19 @@
+       int     devfn;                  /* pci device and function number */
+       int     class_code;             /* pci device class */
+-      struct  pci_controller *phb;    /* for pci devices */
+-      struct  iommu_table *iommu_table;       /* for phb's or bridges */
+-      struct  pci_dev *pcidev;        /* back-pointer to the pci device */
+-      struct  device_node *node;      /* back-pointer to the device_node */
+-
+-      int     pci_ext_config_space;   /* for pci devices */
+-
+-#ifdef CONFIG_EEH
++#ifdef CONFIG_PPC_PSERIES
+       int     eeh_mode;               /* See eeh.h for possible EEH_MODEs */
+       int     eeh_config_addr;
+       int     eeh_pe_config_addr; /* new-style partition endpoint address */
+       int     eeh_check_count;        /* # times driver ignored error */
+       int     eeh_freeze_count;       /* # times this device froze up. */
+-      int     eeh_false_positives;    /* # times this device reported #ff's */
+-      u32     config_space[16];       /* saved PCI config space */
+ #endif
++      int     pci_ext_config_space;   /* for pci devices */
++      struct  pci_controller *phb;    /* for pci devices */
++      struct  iommu_table *iommu_table;       /* for phb's or bridges */
++      struct  pci_dev *pcidev;        /* back-pointer to the pci device */
++      struct  device_node *node;      /* back-pointer to the device_node */
++      u32     config_space[16];       /* saved PCI config space */
+ };
+ /* Get the pointer to a device_node's pci_dn */
+@@ -168,11 +164,6 @@
+ }
+ #endif
+-extern void isa_bridge_find_early(struct pci_controller *hose);
+-
+-extern int pcibios_unmap_io_space(struct pci_bus *bus);
+-extern int pcibios_map_io_space(struct pci_bus *bus);
+-
+ /* Return values for ppc_md.pci_probe_mode function */
+ #define PCI_PROBE_NONE                -1      /* Don't look at this bus at all */
+ #define PCI_PROBE_NORMAL      0       /* Do normal PCI probing */
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/pci.h linux-2.6.22-570/include/asm-powerpc/pci.h
+--- linux-2.6.22-590/include/asm-powerpc/pci.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/pci.h 2007-07-08 19:32:17.000000000 -0400
+@@ -220,6 +220,10 @@
+       return root;
+ }
++extern int unmap_bus_range(struct pci_bus *bus);
 +
-+                      break;
-+              case 'c':
-+              case 's':
-+                      if (kgdb_contthread && kgdb_contthread != current) {
-+                              /* Can't switch threads in kgdb */
-+                              error_packet(remcom_out_buffer, -EINVAL);
-+                              break;
-+                      }
-+                      kgdb_activate_sw_breakpoints();
-+                      /* Followthrough to default processing */
-+              default:
-+                    default_handle:
-+                      error = kgdb_arch_handle_exception(ex_vector, signo,
-+                                                         err_code,
-+                                                         remcom_in_buffer,
-+                                                         remcom_out_buffer,
-+                                                         linux_regs);
++extern int remap_bus_range(struct pci_bus *bus);
 +
-+                      if (error >= 0 || remcom_in_buffer[0] == 'D' ||
-+                          remcom_in_buffer[0] == 'k')
-+                              goto kgdb_exit;
+ extern void pcibios_fixup_device_resources(struct pci_dev *dev,
+                       struct pci_bus *bus);
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/pgtable-ppc32.h linux-2.6.22-570/include/asm-powerpc/pgtable-ppc32.h
+--- linux-2.6.22-590/include/asm-powerpc/pgtable-ppc32.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/pgtable-ppc32.h       2007-07-08 19:32:17.000000000 -0400
+@@ -6,7 +6,11 @@
+ #ifndef __ASSEMBLY__
+ #include <linux/sched.h>
+ #include <linux/threads.h>
++#include <asm/processor.h>            /* For TASK_SIZE */
++#include <asm/mmu.h>
++#include <asm/page.h>
+ #include <asm/io.h>                   /* For sub-arch specific PPC_PIN_SIZE */
++struct mm_struct;
+ extern unsigned long va_to_phys(unsigned long address);
+ extern pte_t *va_to_pte(unsigned long address);
+@@ -484,6 +488,14 @@
+ #define pfn_pte(pfn, prot)    __pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) |\
+                                       pgprot_val(prot))
+ #define mk_pte(page, prot)    pfn_pte(page_to_pfn(page), prot)
 +
-+              }               /* switch */
++/*
++ * ZERO_PAGE is a global shared page that is always zero: used
++ * for zero-mapped memory areas etc..
++ */
++extern unsigned long empty_zero_page[1024];
++#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 +
-+              /* reply to the request */
-+              put_packet(remcom_out_buffer);
-+      }
+ #endif /* __ASSEMBLY__ */
+ #define pte_none(pte)         ((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
+@@ -722,6 +734,10 @@
+ #define pte_unmap(pte)                kunmap_atomic(pte, KM_PTE0)
+ #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
++extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 +
-+ kgdb_exit:
-+      /*
-+       * Call the I/O driver's post_exception routine
-+       * if the I/O driver defined one.
-+       */
-+      if (kgdb_io_ops.post_exception)
-+              kgdb_io_ops.post_exception();
-+
-+      kgdb_info[processor].debuggerinfo = NULL;
-+      kgdb_info[processor].task = NULL;
-+      atomic_set(&procindebug[processor], 0);
-+
-+      if (!debugger_step || !kgdb_contthread) {
-+              for (i = 0; i < NR_CPUS; i++)
-+                      spin_unlock(&slavecpulocks[i]);
-+              /* Wait till all the processors have quit
-+               * from the debugger. */
-+              for (i = 0; i < NR_CPUS; i++) {
-+                      while (atomic_read(&procindebug[i])) {
-+                              int j = 10;     /* an arbitrary number */
-+
-+                              while (--j)
-+                                      cpu_relax();
-+                      }
-+              }
-+      }
++extern void paging_init(void);
 +
-+#ifdef CONFIG_SMP
-+      /* This delay has a real purpose.  The problem is that if you
-+       * are single-stepping, you are sending an NMI to all the
-+       * other processors to stop them.  Interrupts come in, but
-+       * don't get handled.  Then you let them go just long enough
-+       * to get into their interrupt routines and use up some stack.
-+       * You stop them again, and then do the same thing.  After a
-+       * while you blow the stack on the other processors.  This
-+       * delay gives some time for interrupts to be cleared out on
-+       * the other processors.
-+       */
-+      if (debugger_step)
-+              mdelay(2);
-+#endif
-+ kgdb_restore:
-+      /* Free debugger_active */
-+      atomic_set(&debugger_active, 0);
-+      local_irq_restore(flags);
+ /*
+  * Encode and decode a swap entry.
+  * Note that the bits we use in a PTE for representing a swap entry
+@@ -739,6 +755,40 @@
+ #define pte_to_pgoff(pte)     (pte_val(pte) >> 3)
+ #define pgoff_to_pte(off)     ((pte_t) { ((off) << 3) | _PAGE_FILE })
++/* CONFIG_APUS */
++/* For virtual address to physical address conversion */
++extern void cache_clear(__u32 addr, int length);
++extern void cache_push(__u32 addr, int length);
++extern int mm_end_of_chunk (unsigned long addr, int len);
++extern unsigned long iopa(unsigned long addr);
++extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
++
++/* Values for nocacheflag and cmode */
++/* These are not used by the APUS kernel_map, but prevents
++   compilation errors. */
++#define       KERNELMAP_FULL_CACHING          0
++#define       KERNELMAP_NOCACHE_SER           1
++#define       KERNELMAP_NOCACHE_NONSER        2
++#define       KERNELMAP_NO_COPYBACK           3
 +
-+      return error;
-+}
++/*
++ * Map some physical address range into the kernel address space.
++ */
++extern unsigned long kernel_map(unsigned long paddr, unsigned long size,
++                              int nocacheflag, unsigned long *memavailp );
 +
 +/*
-+ * GDB places a breakpoint at this function to know dynamically
-+ * loaded objects. It's not defined static so that only one instance with this
-+ * name exists in the kernel.
++ * Set cache mode of (kernel space) address range.
 + */
++extern void kernel_set_cachemode (unsigned long address, unsigned long size,
++                                 unsigned int cmode);
 +
-+int module_event(struct notifier_block *self, unsigned long val, void *data)
-+{
-+      return 0;
-+}
++/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
++#define kern_addr_valid(addr) (1)
 +
-+static struct notifier_block kgdb_module_load_nb = {
-+      .notifier_call = module_event,
-+};
++#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)               \
++              remap_pfn_range(vma, vaddr, pfn, size, prot)
 +
-+void kgdb_nmihook(int cpu, void *regs)
-+{
-+#ifdef CONFIG_SMP
-+      if (!atomic_read(&procindebug[cpu]) && atomic_read(&debugger_active) != (cpu + 1))
-+              kgdb_wait((struct pt_regs *)regs);
-+#endif
-+}
+ /*
+  * No page table caches to initialise
+  */
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/pgtable-ppc64.h linux-2.6.22-570/include/asm-powerpc/pgtable-ppc64.h
+--- linux-2.6.22-590/include/asm-powerpc/pgtable-ppc64.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/pgtable-ppc64.h       2007-07-08 19:32:17.000000000 -0400
+@@ -7,7 +7,11 @@
+ #ifndef __ASSEMBLY__
+ #include <linux/stddef.h>
++#include <asm/processor.h>            /* For TASK_SIZE */
++#include <asm/mmu.h>
++#include <asm/page.h>
+ #include <asm/tlbflush.h>
++struct mm_struct;
+ #endif /* __ASSEMBLY__ */
+ #ifdef CONFIG_PPC_64K_PAGES
+@@ -23,7 +27,7 @@
+  */
+ #define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
+                           PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
+-#define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE)
++#define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE)
+ #if TASK_SIZE_USER64 > PGTABLE_RANGE
+ #error TASK_SIZE_USER64 exceeds pagetable range
+@@ -33,28 +37,19 @@
+ #error TASK_SIZE_USER64 exceeds user VSID range
+ #endif
+-
+ /*
+  * Define the address range of the vmalloc VM area.
+  */
+ #define VMALLOC_START ASM_CONST(0xD000000000000000)
+-#define VMALLOC_SIZE  (PGTABLE_RANGE >> 1)
++#define VMALLOC_SIZE  ASM_CONST(0x80000000000)
+ #define VMALLOC_END   (VMALLOC_START + VMALLOC_SIZE)
+ /*
+- * Define the address ranges for MMIO and IO space :
+- *
+- *  ISA_IO_BASE = VMALLOC_END, 64K reserved area
+- *  PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces
+- * IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE
+- */
+-#define FULL_IO_SIZE  0x80000000ul
+-#define  ISA_IO_BASE  (VMALLOC_END)
+-#define  ISA_IO_END   (VMALLOC_END + 0x10000ul)
+-#define  PHB_IO_BASE  (ISA_IO_END)
+-#define  PHB_IO_END   (VMALLOC_END + FULL_IO_SIZE)
+-#define IOREMAP_BASE  (PHB_IO_END)
+-#define IOREMAP_END   (VMALLOC_START + PGTABLE_RANGE)
++ * Define the address range of the imalloc VM area.
++ */
++#define PHBS_IO_BASE  VMALLOC_END
++#define IMALLOC_BASE  (PHBS_IO_BASE + 0x80000000ul)   /* Reserve 2 gigs for PHBs */
++#define IMALLOC_END   (VMALLOC_START + PGTABLE_RANGE)
+ /*
+  * Region IDs
+@@ -139,6 +134,16 @@
+ #define __S110        PAGE_SHARED_X
+ #define __S111        PAGE_SHARED_X
++#ifndef __ASSEMBLY__
 +
 +/*
-+ * This is called when a panic happens.  All we need to do is
-+ * breakpoint().
++ * ZERO_PAGE is a global shared page that is always zero: used
++ * for zero-mapped memory areas etc..
 + */
-+static int kgdb_panic_notify(struct notifier_block *self, unsigned long cmd,
-+                           void *ptr)
-+{
-+      breakpoint();
++extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
++#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
++#endif /* __ASSEMBLY__ */
 +
-+      return 0;
-+}
+ #ifdef CONFIG_HUGETLB_PAGE
+ #define HAVE_ARCH_UNMAPPED_AREA
+@@ -437,6 +442,10 @@
+ #define pgd_ERROR(e) \
+       printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
++extern pgd_t swapper_pg_dir[];
 +
-+static struct notifier_block kgdb_panic_notifier = {
-+      .notifier_call = kgdb_panic_notify,
-+};
++extern void paging_init(void);
 +
+ /* Encode and de-code a swap entry */
+ #define __swp_type(entry)     (((entry).val >> 1) & 0x3f)
+ #define __swp_offset(entry)   ((entry).val >> 8)
+@@ -447,6 +456,17 @@
+ #define pgoff_to_pte(off)     ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE})
+ #define PTE_FILE_MAX_BITS     (BITS_PER_LONG - PTE_RPN_SHIFT)
 +/*
-+ * Initialization that needs to be done in either of our entry points.
++ * kern_addr_valid is intended to indicate whether an address is a valid
++ * kernel address.  Most 32-bit archs define it as always true (like this)
++ * but most 64-bit archs actually perform a test.  What should we do here?
++ * The only use is in fs/ncpfs/dir.c
 + */
-+static void __init kgdb_internal_init(void)
-+{
-+      int i;
-+
-+      /* Initialize our spinlocks. */
-+      for (i = 0; i < NR_CPUS; i++)
-+              spin_lock_init(&slavecpulocks[i]);
++#define kern_addr_valid(addr) (1)
 +
-+      for (i = 0; i < MAX_BREAKPOINTS; i++)
-+              kgdb_break[i].state = bp_none;
++#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)               \
++              remap_pfn_range(vma, vaddr, pfn, size, prot)
 +
-+      /* Initialize the I/O handles */
-+      memset(&kgdb_io_ops_prev, 0, sizeof(kgdb_io_ops_prev));
+ void pgtable_cache_init(void);
+ /*
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/pgtable.h linux-2.6.22-570/include/asm-powerpc/pgtable.h
+--- linux-2.6.22-590/include/asm-powerpc/pgtable.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/pgtable.h     2007-07-08 19:32:17.000000000 -0400
+@@ -2,13 +2,6 @@
+ #define _ASM_POWERPC_PGTABLE_H
+ #ifdef __KERNEL__
+-#ifndef __ASSEMBLY__
+-#include <asm/processor.h>            /* For TASK_SIZE */
+-#include <asm/mmu.h>
+-#include <asm/page.h>
+-struct mm_struct;
+-#endif /* !__ASSEMBLY__ */
+-
+ #if defined(CONFIG_PPC64)
+ #  include <asm/pgtable-ppc64.h>
+ #else
+@@ -16,27 +9,6 @@
+ #endif
+ #ifndef __ASSEMBLY__
+-/*
+- * ZERO_PAGE is a global shared page that is always zero: used
+- * for zero-mapped memory areas etc..
+- */
+-extern unsigned long empty_zero_page[];
+-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+-
+-extern pgd_t swapper_pg_dir[];
+-
+-extern void paging_init(void);
+-
+-/*
+- * kern_addr_valid is intended to indicate whether an address is a valid
+- * kernel address.  Most 32-bit archs define it as always true (like this)
+- * but most 64-bit archs actually perform a test.  What should we do here?
+- */
+-#define kern_addr_valid(addr) (1)
+-
+-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)               \
+-              remap_pfn_range(vma, vaddr, pfn, size, prot)
+-
+ #include <asm-generic/pgtable.h>
+ #endif /* __ASSEMBLY__ */
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/ppc-pci.h linux-2.6.22-570/include/asm-powerpc/ppc-pci.h
+--- linux-2.6.22-590/include/asm-powerpc/ppc-pci.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/ppc-pci.h     2007-07-08 19:32:17.000000000 -0400
+@@ -26,7 +26,7 @@
+ extern void find_and_init_phbs(void);
+-extern struct pci_dev *isa_bridge_pcidev;     /* may be NULL if no ISA bus */
++extern struct pci_dev *ppc64_isabridge_dev;   /* may be NULL if no ISA bus */
+ /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */
+ #define BUID_HI(buid) ((buid) >> 32)
+@@ -47,8 +47,8 @@
+ extern unsigned long get_phb_buid (struct device_node *);
+ extern int rtas_setup_phb(struct pci_controller *phb);
+-/* From iSeries PCI */
+-extern void iSeries_pcibios_init(void);
++/* From pSeries_pci.h */
++extern void pSeries_final_fixup(void);
+ extern unsigned long pci_probe_only;
+@@ -139,9 +139,6 @@
+  */
+ struct device_node * find_device_pe(struct device_node *dn);
+-void eeh_sysfs_add_device(struct pci_dev *pdev);
+-void eeh_sysfs_remove_device(struct pci_dev *pdev);
+-
+ #endif /* CONFIG_EEH */
+ #else /* CONFIG_PCI */
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/ptrace.h linux-2.6.22-570/include/asm-powerpc/ptrace.h
+--- linux-2.6.22-590/include/asm-powerpc/ptrace.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/ptrace.h      2007-07-08 19:32:17.000000000 -0400
+@@ -92,11 +92,6 @@
+               set_thread_flag(TIF_NOERROR); \
+       } while(0)
+-struct task_struct;
+-extern unsigned long ptrace_get_reg(struct task_struct *task, int regno);
+-extern int ptrace_put_reg(struct task_struct *task, int regno,
+-                        unsigned long data);
+-
+ /*
+  * We use the least-significant bit of the trap field to indicate
+  * whether we have saved the full set of registers, or only a
+@@ -163,7 +158,9 @@
+ #define PT_NIP        32
+ #define PT_MSR        33
++#ifdef __KERNEL__
+ #define PT_ORIG_R3 34
++#endif
+ #define PT_CTR        35
+ #define PT_LNK        36
+ #define PT_XER        37
+@@ -172,12 +169,11 @@
+ #define PT_MQ 39
+ #else
+ #define PT_SOFTE 39
+-#endif
+ #define PT_TRAP       40
+ #define PT_DAR        41
+ #define PT_DSISR 42
+ #define PT_RESULT 43
+-#define PT_REGS_COUNT 44
++#endif
+ #define PT_FPR0       48      /* each FP reg occupies 2 slots in this space */
+@@ -233,17 +229,7 @@
+ #define PTRACE_GET_DEBUGREG   25
+ #define PTRACE_SET_DEBUGREG   26
+-/* (new) PTRACE requests using the same numbers as x86 and the same
+- * argument ordering. Additionally, they support more registers too
+- */
+-#define PTRACE_GETREGS            12
+-#define PTRACE_SETREGS            13
+-#define PTRACE_GETFPREGS          14
+-#define PTRACE_SETFPREGS          15
+-#define PTRACE_GETREGS64        22
+-#define PTRACE_SETREGS64        23
+-
+-/* (old) PTRACE requests with inverted arguments */
++/* Additional PTRACE requests implemented on PowerPC. */
+ #define PPC_PTRACE_GETREGS    0x99    /* Get GPRs 0 - 31 */
+ #define PPC_PTRACE_SETREGS    0x98    /* Set GPRs 0 - 31 */
+ #define PPC_PTRACE_GETFPREGS  0x97    /* Get FPRs 0 - 31 */
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/syscalls.h linux-2.6.22-570/include/asm-powerpc/syscalls.h
+--- linux-2.6.22-590/include/asm-powerpc/syscalls.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/syscalls.h    2007-07-08 19:32:17.000000000 -0400
+@@ -43,9 +43,16 @@
+ asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset,
+               size_t sigsetsize);
 +
-+      /* We can't do much if this fails */
-+      register_module_notifier(&kgdb_module_load_nb);
++#ifndef __powerpc64__
++asmlinkage long sys_sigaltstack(const stack_t __user *uss,
++              stack_t __user *uoss, int r5, int r6, int r7, int r8,
++              struct pt_regs *regs);
++#else /* __powerpc64__ */
+ asmlinkage long sys_sigaltstack(const stack_t __user *uss,
+               stack_t __user *uoss, unsigned long r5, unsigned long r6,
+               unsigned long r7, unsigned long r8, struct pt_regs *regs);
++#endif /* __powerpc64__ */
+ #endif /* __KERNEL__ */
+ #endif /* __ASM_POWERPC_SYSCALLS_H */
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/systbl.h linux-2.6.22-570/include/asm-powerpc/systbl.h
+--- linux-2.6.22-590/include/asm-powerpc/systbl.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/systbl.h      2008-01-23 19:16:04.000000000 -0500
+@@ -312,4 +312,3 @@
+ COMPAT_SYS_SPU(timerfd)
+ SYSCALL_SPU(eventfd)
+ COMPAT_SYS_SPU(sync_file_range2)
+-COMPAT_SYS(fallocate)
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/thread_info.h linux-2.6.22-570/include/asm-powerpc/thread_info.h
+--- linux-2.6.22-590/include/asm-powerpc/thread_info.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/thread_info.h 2007-07-08 19:32:17.000000000 -0400
+@@ -113,8 +113,8 @@
+ #define TIF_POLLING_NRFLAG    4       /* true if poll_idle() is polling
+                                          TIF_NEED_RESCHED */
+ #define TIF_32BIT             5       /* 32 bit binary */
+-#define TIF_PERFMON_WORK      6       /* work for pfm_handle_work() */
+-#define TIF_PERFMON_CTXSW     7       /* perfmon needs ctxsw calls */
++#define TIF_RUNLATCH          6       /* Is the runlatch enabled? */
++#define TIF_ABI_PENDING               7       /* 32/64 bit switch needed */
+ #define TIF_SYSCALL_AUDIT     8       /* syscall auditing active */
+ #define TIF_SINGLESTEP                9       /* singlestepping active */
+ #define TIF_MEMDIE            10
+@@ -123,8 +123,6 @@
+ #define TIF_NOERROR           14      /* Force successful syscall return */
+ #define TIF_RESTORE_SIGMASK   15      /* Restore signal mask in do_signal */
+ #define TIF_FREEZE            16      /* Freezing for suspend */
+-#define TIF_RUNLATCH          17      /* Is the runlatch enabled? */
+-#define TIF_ABI_PENDING               18      /* 32/64 bit switch needed */
+ /* as above, but as bit values */
+ #define _TIF_SYSCALL_TRACE    (1<<TIF_SYSCALL_TRACE)
+@@ -133,8 +131,8 @@
+ #define _TIF_NEED_RESCHED     (1<<TIF_NEED_RESCHED)
+ #define _TIF_POLLING_NRFLAG   (1<<TIF_POLLING_NRFLAG)
+ #define _TIF_32BIT            (1<<TIF_32BIT)
+-#define _TIF_PERFMON_WORK     (1<<TIF_PERFMON_WORK)
+-#define _TIF_PERFMON_CTXSW    (1<<TIF_PERFMON_CTXSW)
++#define _TIF_RUNLATCH         (1<<TIF_RUNLATCH)
++#define _TIF_ABI_PENDING      (1<<TIF_ABI_PENDING)
+ #define _TIF_SYSCALL_AUDIT    (1<<TIF_SYSCALL_AUDIT)
+ #define _TIF_SINGLESTEP               (1<<TIF_SINGLESTEP)
+ #define _TIF_SECCOMP          (1<<TIF_SECCOMP)
+@@ -142,8 +140,6 @@
+ #define _TIF_NOERROR          (1<<TIF_NOERROR)
+ #define _TIF_RESTORE_SIGMASK  (1<<TIF_RESTORE_SIGMASK)
+ #define _TIF_FREEZE           (1<<TIF_FREEZE)
+-#define _TIF_RUNLATCH         (1<<TIF_RUNLATCH)
+-#define _TIF_ABI_PENDING      (1<<TIF_ABI_PENDING)
+ #define _TIF_SYSCALL_T_OR_A   (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
+ #define _TIF_USER_WORK_MASK   (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/tlbflush.h linux-2.6.22-570/include/asm-powerpc/tlbflush.h
+--- linux-2.6.22-590/include/asm-powerpc/tlbflush.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/tlbflush.h    2007-07-08 19:32:17.000000000 -0400
+@@ -155,11 +155,6 @@
+ {
+ }
+-/* Private function for use by PCI IO mapping code */
+-extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
+-                                   unsigned long end);
+-
+-
+ #endif
+ /*
+diff -Nurb linux-2.6.22-590/include/asm-powerpc/unistd.h linux-2.6.22-570/include/asm-powerpc/unistd.h
+--- linux-2.6.22-590/include/asm-powerpc/unistd.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-powerpc/unistd.h      2008-01-23 19:16:04.000000000 -0500
+@@ -331,11 +331,10 @@
+ #define __NR_timerfd          306
+ #define __NR_eventfd          307
+ #define __NR_sync_file_range2 308
+-#define __NR_fallocate                309
+ #ifdef __KERNEL__
+-#define __NR_syscalls         310
++#define __NR_syscalls         309
+ #define __NR__exit __NR_exit
+ #define NR_syscalls   __NR_syscalls
+diff -Nurb linux-2.6.22-590/include/asm-ppc/kgdb.h linux-2.6.22-570/include/asm-ppc/kgdb.h
+--- linux-2.6.22-590/include/asm-ppc/kgdb.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-ppc/kgdb.h    2007-07-08 19:32:17.000000000 -0400
+@@ -1,18 +1,57 @@
++/*
++ * kgdb.h: Defines and declarations for serial line source level
++ *         remote debugging of the Linux kernel using gdb.
++ *
++ * PPC Mods (C) 1998 Michael Tesch (tesch@cs.wisc.edu)
++ *
++ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
++ */
+ #ifdef __KERNEL__
+-#ifndef __PPC_KGDB_H__
+-#define __PPC_KGDB_H__
+-#include <asm-powerpc/kgdb.h>
++#ifndef _PPC_KGDB_H
++#define _PPC_KGDB_H
 +
-+      kgdb_initialized = 1;
-+}
+ #ifndef __ASSEMBLY__
+- /* For taking exceptions
 +
-+static void kgdb_register_for_panic(void)
-+{
-+      /* Register for panics(). */
-+      /* The registration is done in the kgdb_register_for_panic
-+       * routine because KGDB should not try to handle a panic when
-+       * there are no kgdb_io_ops setup. It is assumed that the
-+       * kgdb_io_ops are setup at the time this method is called.
-+       */
-+      if (!kgdb_from_module_registered) {
-+              atomic_notifier_chain_register(&panic_notifier_list,
-+                                      &kgdb_panic_notifier);
-+              kgdb_from_module_registered = 1;
-+      }
-+}
++/* Things specific to the gen550 backend. */
++struct uart_port;
 +
-+static void kgdb_unregister_for_panic(void)
-+{
-+      /* When this routine is called KGDB should unregister from the
-+       * panic handler and clean up, making sure it is not handling any
-+       * break exceptions at the time.
-+       */
-+      if (kgdb_from_module_registered) {
-+              kgdb_from_module_registered = 0;
-+              atomic_notifier_chain_unregister(&panic_notifier_list,
-+                                        &kgdb_panic_notifier);
-+      }
-+}
++extern void gen550_progress(char *, unsigned short);
++extern void gen550_kgdb_map_scc(void);
++extern void gen550_init(int, struct uart_port *);
 +
-+int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops)
-+{
++/* Things specific to the pmac backend. */
++extern void zs_kgdb_hook(int tty_num);
 +
-+      if (kgdb_connected) {
-+              printk(KERN_ERR "kgdb: Cannot load I/O module while KGDB "
-+                     "connected.\n");
-+              return -EINVAL;
-+      }
++/* To init the kgdb engine. (called by serial hook)*/
++extern void set_debug_traps(void);
 +
-+      /* Save the old values so they can be restored */
-+      if (kgdb_io_handler_cnt >= MAX_KGDB_IO_HANDLERS) {
-+              printk(KERN_ERR "kgdb: No more I/O handles available.\n");
-+              return -EINVAL;
-+      }
++/* To enter the debugger explicitly. */
++extern void breakpoint(void);
 +
-+      /* Check to see if there is an existing driver and if so save its
-+       * values.  Also check to make sure the same driver was not trying
-+       * to re-register.
-+       */
-+      if (kgdb_io_ops.read_char != NULL &&
-+        kgdb_io_ops.read_char != local_kgdb_io_ops->read_char) {
-+              memcpy(&kgdb_io_ops_prev[kgdb_io_handler_cnt],
-+                     &kgdb_io_ops, sizeof(struct kgdb_io));
-+              kgdb_io_handler_cnt++;
-+      }
++/* For taking exceptions
+  * these are defined in traps.c
+  */
+-struct pt_regs;
+-extern void (*debugger)(struct pt_regs *regs);
++extern int (*debugger)(struct pt_regs *regs);
+ extern int (*debugger_bpt)(struct pt_regs *regs);
+ extern int (*debugger_sstep)(struct pt_regs *regs);
+ extern int (*debugger_iabr_match)(struct pt_regs *regs);
+ extern int (*debugger_dabr_match)(struct pt_regs *regs);
+ extern void (*debugger_fault_handler)(struct pt_regs *regs);
+-#endif /* !__ASSEMBLY__ */
+-#endif /* __PPC_KGDB_H__ */
 +
-+      /* Initialize the io values for this module */
-+      memcpy(&kgdb_io_ops, local_kgdb_io_ops, sizeof(struct kgdb_io));
++/* What we bring to the party */
++int kgdb_bpt(struct pt_regs *regs);
++int kgdb_sstep(struct pt_regs *regs);
++void kgdb(struct pt_regs *regs);
++int kgdb_iabr_match(struct pt_regs *regs);
++int kgdb_dabr_match(struct pt_regs *regs);
 +
-+      /* Make the call to register kgdb if is not initialized */
-+      kgdb_register_for_panic();
++/*
++ * external low-level support routines (ie macserial.c)
++ */
++extern void kgdb_interruptible(int); /* control interrupts from serial */
++extern void putDebugChar(char);   /* write a single character      */
++extern char getDebugChar(void);   /* read and return a single char */
 +
-+      return 0;
-+}
++#endif /* !(__ASSEMBLY__) */
++#endif /* !(_PPC_KGDB_H) */
+ #endif /* __KERNEL__ */
+diff -Nurb linux-2.6.22-590/include/asm-ppc/machdep.h linux-2.6.22-570/include/asm-ppc/machdep.h
+--- linux-2.6.22-590/include/asm-ppc/machdep.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-ppc/machdep.h 2007-07-08 19:32:17.000000000 -0400
+@@ -72,7 +72,9 @@
+       unsigned long   (*find_end_of_memory)(void);
+       void            (*setup_io_mappings)(void);
++      void            (*early_serial_map)(void);
+       void            (*progress)(char *, unsigned short);
++      void            (*kgdb_map_scc)(void);
+       unsigned char   (*nvram_read_val)(int addr);
+       void            (*nvram_write_val)(int addr, unsigned char val);
+diff -Nurb linux-2.6.22-590/include/asm-ppc/mv64x60.h linux-2.6.22-570/include/asm-ppc/mv64x60.h
+--- linux-2.6.22-590/include/asm-ppc/mv64x60.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-ppc/mv64x60.h 2007-07-08 19:32:17.000000000 -0400
+@@ -348,8 +348,6 @@
+ void mv64x60_progress_init(u32 base);
+ void mv64x60_mpsc_progress(char *s, unsigned short hex);
+-struct platform_device * mv64x60_early_get_pdev_data(const char *name,
+-              int id, int remove);
+ extern struct mv64x60_32bit_window
+       gt64260_32bit_windows[MV64x60_32BIT_WIN_COUNT];
+diff -Nurb linux-2.6.22-590/include/asm-ppc/mv64x60_defs.h linux-2.6.22-570/include/asm-ppc/mv64x60_defs.h
+--- linux-2.6.22-590/include/asm-ppc/mv64x60_defs.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-ppc/mv64x60_defs.h    2007-07-08 19:32:17.000000000 -0400
+@@ -57,8 +57,7 @@
+ #define       MV64x60_IRQ_I2C                         37
+ #define       MV64x60_IRQ_BRG                         39
+ #define       MV64x60_IRQ_MPSC_0                      40
+-#define       MV64360_IRQ_MPSC_1                      41
+-#define       GT64260_IRQ_MPSC_1                      42
++#define       MV64x60_IRQ_MPSC_1                      42
+ #define       MV64x60_IRQ_COMM                        43
+ #define       MV64x60_IRQ_P0_GPP_0_7                  56
+ #define       MV64x60_IRQ_P0_GPP_8_15                 57
+diff -Nurb linux-2.6.22-590/include/asm-s390/page.h linux-2.6.22-570/include/asm-s390/page.h
+--- linux-2.6.22-590/include/asm-s390/page.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-s390/page.h   2007-07-08 19:32:17.000000000 -0400
+@@ -64,8 +64,7 @@
+ #define clear_user_page(page, vaddr, pg)      clear_page(page)
+ #define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
+-#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+-      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
++#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+ #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+ /*
+diff -Nurb linux-2.6.22-590/include/asm-sh/kgdb.h linux-2.6.22-570/include/asm-sh/kgdb.h
+--- linux-2.6.22-590/include/asm-sh/kgdb.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-sh/kgdb.h     2007-07-08 19:32:17.000000000 -0400
+@@ -2,41 +2,78 @@
+  * May be copied or modified under the terms of the GNU General Public
+  * License.  See linux/COPYING for more information.
+  *
+- * Based on a file that was modified or based on files by: Glenn Engel,
+- * Jim Kingdon, David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
+- * Amit S. Kale <akale@veritas.com>, sh-stub.c from Ben Lee and
+- * Steve Chamberlain, Henry Bell <henry.bell@st.com>
++ * Based on original code by Glenn Engel, Jim Kingdon,
++ * David Grothe <dave@gcom.com>, Tigran Aivazian, <tigran@sco.com> and
++ * Amit S. Kale <akale@veritas.com>
+  * 
+- * Maintainer: Tom Rini <trini@kernel.crashing.org>
++ * Super-H port based on sh-stub.c (Ben Lee and Steve Chamberlain) by
++ * Henry Bell <henry.bell@st.com>
++ * 
++ * Header file for low-level support for remote debug using GDB. 
+  *
+  */
+ #ifndef __KGDB_H
+ #define __KGDB_H
+-#include <asm-generic/kgdb.h>
++#include <asm/ptrace.h>
++#include <asm/cacheflush.h>
+-/* Based on sh-gdb.c from gdb-6.1, Glenn
+-     Engel at HP  Ben Lee and Steve Chamberlain */
+-#define NUMREGBYTES   112     /* 92 */
+-#define NUMCRITREGBYTES       (9 << 2)
+-#define BUFMAX                400
++struct console;
+-#ifndef __ASSEMBLY__
++/* Same as pt_regs but has vbr in place of syscall_nr */
+ struct kgdb_regs {
+         unsigned long regs[16];
+         unsigned long pc;
+         unsigned long pr;
++        unsigned long sr;
+         unsigned long gbr;
+-        unsigned long vbr;
+         unsigned long mach;
+         unsigned long macl;
+-        unsigned long sr;
++        unsigned long vbr;
+ };
+-#define BREAKPOINT()          asm("trapa #0xff");
+-#define BREAK_INSTR_SIZE      2
+-#define CACHE_FLUSH_IS_SAFE   1
++/* State info */
++extern char kgdb_in_gdb_mode;
++extern int kgdb_done_init;
++extern int kgdb_enabled;
++extern int kgdb_nofault;      /* Ignore bus errors (in gdb mem access) */
++extern int kgdb_halt;         /* Execute initial breakpoint at startup */
++extern char in_nmi;           /* Debounce flag to prevent NMI reentry*/
++
++/* SCI */
++extern int kgdb_portnum;
++extern int kgdb_baud;
++extern char kgdb_parity;
++extern char kgdb_bits;
++
++/* Init and interface stuff */
++extern int kgdb_init(void);
++extern int (*kgdb_getchar)(void);
++extern void (*kgdb_putchar)(int);
++
++/* Trap functions */
++typedef void (kgdb_debug_hook_t)(struct pt_regs *regs);
++typedef void (kgdb_bus_error_hook_t)(void);
++extern kgdb_debug_hook_t  *kgdb_debug_hook;
++extern kgdb_bus_error_hook_t *kgdb_bus_err_hook;
++
++/* Console */
++void kgdb_console_write(struct console *co, const char *s, unsigned count);
++extern int kgdb_console_setup(struct console *, char *);
++
++/* Prototypes for jmp fns */
++#define _JBLEN 9
++typedef        int jmp_buf[_JBLEN];
++extern void    longjmp(jmp_buf __jmpb, int __retval);
++extern int     setjmp(jmp_buf __jmpb);
++
++/* Forced breakpoint */
++#define breakpoint()                                  \
++do {                                                  \
++      if (kgdb_enabled)                               \
++              __asm__ __volatile__("trapa   #0x3c");  \
++} while (0)
+ /* KGDB should be able to flush all kernel text space */
+ #if defined(CONFIG_CPU_SH4)
+@@ -63,5 +100,4 @@
+ {
+       return hexchars[x & 0xf];
+ }
+-#endif                                /* !__ASSEMBLY__ */
+ #endif
+diff -Nurb linux-2.6.22-590/include/asm-sh/system.h linux-2.6.22-570/include/asm-sh/system.h
+--- linux-2.6.22-590/include/asm-sh/system.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-sh/system.h   2007-07-08 19:32:17.000000000 -0400
+@@ -264,45 +264,6 @@
+ #define instruction_size(insn)        (2)
+ #endif
+-static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
+-      unsigned long new)
+-{
+-      __u32 retval;
+-      unsigned long flags;
+-
+-      local_irq_save(flags);
+-      retval = *m;
+-      if (retval == old)
+-              *m = new;
+-      local_irq_restore(flags);       /* implies memory barrier  */
+-      return retval;
+-}
+-
+-/* This function doesn't exist, so you'll get a linker error
+- * if something tries to do an invalid cmpxchg(). */
+-extern void __cmpxchg_called_with_bad_pointer(void);
+-
+-#define __HAVE_ARCH_CMPXCHG   1
+-
+-static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
+-              unsigned long new, int size)
+-{
+-      switch (size) {
+-      case 4:
+-              return __cmpxchg_u32(ptr, old, new);
+-      }
+-      __cmpxchg_called_with_bad_pointer();
+-      return old;
+-}
+-
+-#define cmpxchg(ptr,o,n)                                               \
+-  ({                                                                   \
+-     __typeof__(*(ptr)) _o_ = (o);                                     \
+-     __typeof__(*(ptr)) _n_ = (n);                                     \
+-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,                 \
+-                                  (unsigned long)_n_, sizeof(*(ptr))); \
+-  })
+-
+ /* XXX
+  * disable hlt during certain critical i/o operations
+  */
+diff -Nurb linux-2.6.22-590/include/asm-um/thread_info.h linux-2.6.22-570/include/asm-um/thread_info.h
+--- linux-2.6.22-590/include/asm-um/thread_info.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-um/thread_info.h      2007-07-08 19:32:17.000000000 -0400
+@@ -52,21 +52,10 @@
+       return ti;
+ }
+-#ifdef CONFIG_DEBUG_STACK_USAGE
+-
+-#define alloc_thread_info(tsk) \
+-      ((struct thread_info *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, \
+-                                               CONFIG_KERNEL_STACK_ORDER))
+-#else
+-
+ /* thread information allocation */
+ #define alloc_thread_info(tsk) \
+-      ((struct thread_info *) __get_free_pages(GFP_KERNEL, \
+-                                               CONFIG_KERNEL_STACK_ORDER))
+-#endif
+-
+-#define free_thread_info(ti) \
+-      free_pages((unsigned long)(ti),CONFIG_KERNEL_STACK_ORDER)
++      ((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
++#define free_thread_info(ti) kfree(ti)
+ #endif
+diff -Nurb linux-2.6.22-590/include/asm-x86_64/kdebug.h linux-2.6.22-570/include/asm-x86_64/kdebug.h
+--- linux-2.6.22-590/include/asm-x86_64/kdebug.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-x86_64/kdebug.h       2007-07-08 19:32:17.000000000 -0400
+@@ -23,7 +23,6 @@
+       DIE_CALL,
+       DIE_NMI_IPI,
+       DIE_PAGE_FAULT,
+-      DIE_PAGE_FAULT_NO_CONTEXT,
+ };
+ extern void printk_address(unsigned long address);
+diff -Nurb linux-2.6.22-590/include/asm-x86_64/kgdb.h linux-2.6.22-570/include/asm-x86_64/kgdb.h
+--- linux-2.6.22-590/include/asm-x86_64/kgdb.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-x86_64/kgdb.h 1969-12-31 19:00:00.000000000 -0500
+@@ -1,52 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef _ASM_KGDB_H_
+-#define _ASM_KGDB_H_
+-
+-/*
+- * Copyright (C) 2001-2004 Amit S. Kale
+- */
+-
+-#include <asm-generic/kgdb.h>
+-
+-/*
+- *  Note that this register image is in a different order than
+- *  the register image that Linux produces at interrupt time.
+- *
+- *  Linux's register image is defined by struct pt_regs in ptrace.h.
+- *  Just why GDB uses a different order is a historical mystery.
+- */
+-#define _RAX  0
+-#define _RDX  1
+-#define _RCX  2
+-#define _RBX  3
+-#define _RSI  4
+-#define _RDI  5
+-#define _RBP  6
+-#define _RSP  7
+-#define _R8   8
+-#define _R9   9
+-#define _R10  10
+-#define _R11  11
+-#define _R12  12
+-#define _R13  13
+-#define _R14  14
+-#define _R15  15
+-#define _PC   16
+-#define _PS   17
+-
+-/* Number of bytes of registers.  */
+-#define NUMREGBYTES           ((_PS+1)*8)
+-#define NUMCRITREGBYTES               (8 * 8)         /* 8 registers. */
+-
+-#ifndef __ASSEMBLY__
+-/* BUFMAX defines the maximum number of characters in inbound/outbound
+- * buffers at least NUMREGBYTES*2 are needed for register packets, and
+- * a longer buffer is needed to list all threads. */
+-#define BUFMAX                        1024
+-#define BREAKPOINT()          asm("   int $3");
+-#define CHECK_EXCEPTION_STACK() ((&__get_cpu_var(init_tss))[0].ist[0])
+-#define BREAK_INSTR_SIZE      1
+-#define CACHE_FLUSH_IS_SAFE   1
+-#endif                                /* !__ASSEMBLY__ */
+-#endif                                /* _ASM_KGDB_H_ */
+-#endif                                /* __KERNEL__ */
+diff -Nurb linux-2.6.22-590/include/asm-x86_64/page.h linux-2.6.22-570/include/asm-x86_64/page.h
+--- linux-2.6.22-590/include/asm-x86_64/page.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-x86_64/page.h 2007-07-08 19:32:17.000000000 -0400
+@@ -48,8 +48,7 @@
+ #define clear_user_page(page, vaddr, pg)      clear_page(page)
+ #define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
+-#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+-      alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
++#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+ #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+ /*
+  * These are used to make use of C type-checking..
+diff -Nurb linux-2.6.22-590/include/asm-x86_64/proto.h linux-2.6.22-570/include/asm-x86_64/proto.h
+--- linux-2.6.22-590/include/asm-x86_64/proto.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-x86_64/proto.h        2007-07-08 19:32:17.000000000 -0400
+@@ -75,6 +75,8 @@
+ extern void early_quirks(void);
+ extern void check_efer(void);
++extern int unhandled_signal(struct task_struct *tsk, int sig);
 +
-+void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops)
+ extern void select_idle_routine(const struct cpuinfo_x86 *c);
+ extern unsigned long table_start, table_end;
+diff -Nurb linux-2.6.22-590/include/asm-x86_64/system.h linux-2.6.22-570/include/asm-x86_64/system.h
+--- linux-2.6.22-590/include/asm-x86_64/system.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-x86_64/system.h       2007-07-08 19:32:17.000000000 -0400
+@@ -22,9 +22,7 @@
+ /* Save restore flags to clear handle leaking NT */
+ #define switch_to(prev,next,last) \
+-       asm volatile(".globl __switch_to_begin\n\t"                                \
+-                   "__switch_to_begin:\n\t"                                     \
+-                   SAVE_CONTEXT                                                 \
++      asm volatile(SAVE_CONTEXT                                                   \
+                    "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */       \
+                    "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */    \
+                    "call __switch_to\n\t"                                       \
+@@ -36,8 +34,6 @@
+                    "movq %%rax,%%rdi\n\t"                                       \
+                    "jc   ret_from_fork\n\t"                                     \
+                    RESTORE_CONTEXT                                                \
+-                   "\n.globl __switch_to_end\n\t"                               \
+-                   "__switch_to_end:\n\t"                                       \
+                    : "=a" (last)                                                \
+                    : [next] "S" (next), [prev] "D" (prev),                      \
+                      [threadrsp] "i" (offsetof(struct task_struct, thread.rsp)), \
+diff -Nurb linux-2.6.22-590/include/asm-x86_64/unistd.h linux-2.6.22-570/include/asm-x86_64/unistd.h
+--- linux-2.6.22-590/include/asm-x86_64/unistd.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-x86_64/unistd.h       2008-01-23 19:16:04.000000000 -0500
+@@ -630,8 +630,6 @@
+ __SYSCALL(__NR_timerfd, sys_timerfd)
+ #define __NR_eventfd          284
+ __SYSCALL(__NR_eventfd, sys_eventfd)
+-#define __NR_fallocate                284
+-__SYSCALL(__NR_fallocate, sys_fallocate)
+ #ifndef __NO_STUBS
+ #define __ARCH_WANT_OLD_READDIR
+diff -Nurb linux-2.6.22-590/include/asm-x86_64/unwind.h linux-2.6.22-570/include/asm-x86_64/unwind.h
+--- linux-2.6.22-590/include/asm-x86_64/unwind.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/asm-x86_64/unwind.h       2007-07-08 19:32:17.000000000 -0400
+@@ -1,100 +1,6 @@
+ #ifndef _ASM_X86_64_UNWIND_H
+ #define _ASM_X86_64_UNWIND_H
+-/*
+- * Copyright (C) 2002-2006 Novell, Inc.
+- *    Jan Beulich <jbeulich@novell.com>
+- * This code is released under version 2 of the GNU GPL.
+- */
+-
+-#ifdef CONFIG_STACK_UNWIND
+-
+-#include <linux/sched.h>
+-#include <asm/ptrace.h>
+-#include <asm/uaccess.h>
+-#include <asm/vsyscall.h>
+-
+-struct unwind_frame_info
+-{
+-      struct pt_regs regs;
+-      struct task_struct *task;
+-      unsigned call_frame:1;
+-};
+-
+-#define UNW_PC(frame)        (frame)->regs.rip
+-#define UNW_SP(frame)        (frame)->regs.rsp
+-#ifdef CONFIG_FRAME_POINTER
+-#define UNW_FP(frame)        (frame)->regs.rbp
+-#define FRAME_RETADDR_OFFSET 8
+-#define FRAME_LINK_OFFSET    0
+-#define STACK_BOTTOM(tsk)    (((tsk)->thread.rsp0 - 1) & ~(THREAD_SIZE - 1))
+-#define STACK_TOP(tsk)       ((tsk)->thread.rsp0)
+-#endif
+-/* Might need to account for the special exception and interrupt handling
+-   stacks here, since normally
+-      EXCEPTION_STACK_ORDER < THREAD_ORDER < IRQSTACK_ORDER,
+-   but the construct is needed only for getting across the stack switch to
+-   the interrupt stack - thus considering the IRQ stack itself is unnecessary,
+-   and the overhead of comparing against all exception handling stacks seems
+-   not desirable. */
+-#define STACK_LIMIT(ptr)     (((ptr) - 1) & ~(THREAD_SIZE - 1))
+-
+-#define UNW_REGISTER_INFO \
+-      PTREGS_INFO(rax), \
+-      PTREGS_INFO(rdx), \
+-      PTREGS_INFO(rcx), \
+-      PTREGS_INFO(rbx), \
+-      PTREGS_INFO(rsi), \
+-      PTREGS_INFO(rdi), \
+-      PTREGS_INFO(rbp), \
+-      PTREGS_INFO(rsp), \
+-      PTREGS_INFO(r8), \
+-      PTREGS_INFO(r9), \
+-      PTREGS_INFO(r10), \
+-      PTREGS_INFO(r11), \
+-      PTREGS_INFO(r12), \
+-      PTREGS_INFO(r13), \
+-      PTREGS_INFO(r14), \
+-      PTREGS_INFO(r15), \
+-      PTREGS_INFO(rip)
+-
+-#define UNW_DEFAULT_RA(raItem, dataAlign) \
+-      ((raItem).where == Memory && \
+-       !((raItem).value * (dataAlign) + 8))
+-
+-static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
+-                                            /*const*/ struct pt_regs *regs)
+-{
+-      info->regs = *regs;
+-}
+-
+-static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
+-{
+-      extern const char thread_return[];
+-
+-      memset(&info->regs, 0, sizeof(info->regs));
+-      info->regs.rip = (unsigned long)thread_return;
+-      info->regs.cs = __KERNEL_CS;
+-      __get_user(info->regs.rbp, (unsigned long *)info->task->thread.rsp);
+-      info->regs.rsp = info->task->thread.rsp;
+-      info->regs.ss = __KERNEL_DS;
+-}
+-
+-extern int arch_unwind_init_running(struct unwind_frame_info *,
+-                                    int (*callback)(struct unwind_frame_info *,
+-                                                    void *arg),
+-                                    void *arg);
+-
+-static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
+-{
+-      return user_mode(&info->regs)
+-             || (long)info->regs.rip >= 0
+-             || (info->regs.rip >= VSYSCALL_START && info->regs.rip < VSYSCALL_END)
+-             || (long)info->regs.rsp >= 0;
+-}
+-
+-#else
+-
+ #define UNW_PC(frame) ((void)(frame), 0UL)
+ #define UNW_SP(frame) ((void)(frame), 0UL)
+@@ -103,6 +9,4 @@
+       return 0;
+ }
+-#endif
+-
+ #endif /* _ASM_X86_64_UNWIND_H */
+diff -Nurb linux-2.6.22-590/include/linux/Kbuild linux-2.6.22-570/include/linux/Kbuild
+--- linux-2.6.22-590/include/linux/Kbuild      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/Kbuild      2008-01-23 19:16:04.000000000 -0500
+@@ -91,6 +91,7 @@
+ header-y += in_route.h
+ header-y += ioctl.h
+ header-y += ipmi_msgdefs.h
++header-y += ip_mp_alg.h
+ header-y += ipsec.h
+ header-y += ipx.h
+ header-y += irda.h
+diff -Nurb linux-2.6.22-590/include/linux/acpi.h linux-2.6.22-570/include/linux/acpi.h
+--- linux-2.6.22-590/include/linux/acpi.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/acpi.h      2007-07-08 19:32:17.000000000 -0400
+@@ -206,8 +206,11 @@
+ {
+       return max_cstate;
+ }
+-extern void (*acpi_do_set_cstate_limit)(void);
+-extern void acpi_set_cstate_limit(unsigned int new_limit);
++static inline void acpi_set_cstate_limit(unsigned int new_limit)
 +{
-+      int i;
-+
-+      /* Unregister KGDB if there were no other prior io hooks, else
-+       * restore the io hooks.
-+       */
-+      if (kgdb_io_handler_cnt > 0 && kgdb_io_ops_prev[0].read_char != NULL) {
-+              /* First check if the hook that is in use is the one being
-+               * removed */
-+              if (kgdb_io_ops.read_char == local_kgdb_io_ops->read_char) {
-+                      /* Set 'i' to the value of where the list should be
-+                       * shifed */
-+                      i = kgdb_io_handler_cnt - 1;
-+                      memcpy(&kgdb_io_ops, &kgdb_io_ops_prev[i],
-+                             sizeof(struct kgdb_io));
-+              } else {
-+                      /* Simple case to remove an entry for an I/O handler
-+                       * that is not in use */
-+                      for (i = 0; i < kgdb_io_handler_cnt; i++) {
-+                              if (kgdb_io_ops_prev[i].read_char ==
-+                                  local_kgdb_io_ops->read_char)
-+                                      break;
-+                      }
-+              }
-+
-+              /* Shift all the entries in the handler array so it is
-+               * ordered from oldest to newest.
-+               */
-+              kgdb_io_handler_cnt--;
-+              for (; i < kgdb_io_handler_cnt; i++) {
-+                      memcpy(&kgdb_io_ops_prev[i], &kgdb_io_ops_prev[i + 1],
-+                             sizeof(struct kgdb_io));
-+              }
-+              /* Handle the case if we are on the last element and set it
-+               * to NULL; */
-+              memset(&kgdb_io_ops_prev[kgdb_io_handler_cnt], 0,
-+                              sizeof(struct kgdb_io));
-+
-+              if (kgdb_connected)
-+                      printk(KERN_ERR "kgdb: WARNING: I/O method changed "
-+                             "while kgdb was connected state.\n");
-+      } else {
-+              /* KGDB is no longer able to communicate out, so
-+               * unregister our hooks and reset state. */
-+              kgdb_unregister_for_panic();
-+              if (kgdb_connected) {
-+                      printk(KERN_CRIT "kgdb: I/O module was unloaded while "
-+                                      "a debugging session was running.  "
-+                                      "KGDB will be reset.\n");
-+                      if (remove_all_break() < 0)
-+                              printk(KERN_CRIT "kgdb: Reset failed.\n");
-+                      kgdb_connected = 0;
-+              }
-+              memset(&kgdb_io_ops, 0, sizeof(struct kgdb_io));
-+      }
++      max_cstate = new_limit;
++      return;
 +}
+ #else
+ static inline unsigned int acpi_get_cstate_limit(void) { return 0; }
+ static inline void acpi_set_cstate_limit(unsigned int new_limit) { return; }
+diff -Nurb linux-2.6.22-590/include/linux/async_tx.h linux-2.6.22-570/include/linux/async_tx.h
+--- linux-2.6.22-590/include/linux/async_tx.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/async_tx.h  1969-12-31 19:00:00.000000000 -0500
+@@ -1,156 +0,0 @@
+-/*
+- * Copyright Â© 2006, Intel Corporation.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- *
+- */
+-#ifndef _ASYNC_TX_H_
+-#define _ASYNC_TX_H_
+-#include <linux/dmaengine.h>
+-#include <linux/spinlock.h>
+-#include <linux/interrupt.h>
+-
+-/**
+- * dma_chan_ref - object used to manage dma channels received from the
+- *   dmaengine core.
+- * @chan - the channel being tracked
+- * @node - node for the channel to be placed on async_tx_master_list
+- * @rcu - for list_del_rcu
+- * @count - number of times this channel is listed in the pool
+- *    (for channels with multiple capabiities)
+- */
+-struct dma_chan_ref {
+-      struct dma_chan *chan;
+-      struct list_head node;
+-      struct rcu_head rcu;
+-      atomic_t count;
+-};
+-
+-/**
+- * async_tx_flags - modifiers for the async_* calls
+- * @ASYNC_TX_XOR_ZERO_DST: this flag must be used for xor operations where the
+- * the destination address is not a source.  The asynchronous case handles this
+- * implicitly, the synchronous case needs to zero the destination block.
+- * @ASYNC_TX_XOR_DROP_DST: this flag must be used if the destination address is
+- * also one of the source addresses.  In the synchronous case the destination
+- * address is an implied source, whereas the asynchronous case it must be listed
+- * as a source.  The destination address must be the first address in the source
+- * array.
+- * @ASYNC_TX_ASSUME_COHERENT: skip cache maintenance operations
+- * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a
+- * dependency chain
+- * @ASYNC_TX_DEP_ACK: ack the dependency descriptor.  Useful for chaining.
+- * @ASYNC_TX_KMAP_SRC: if the transaction is to be performed synchronously
+- * take an atomic mapping (KM_USER0) on the source page(s)
+- * @ASYNC_TX_KMAP_DST: if the transaction is to be performed synchronously
+- * take an atomic mapping (KM_USER0) on the dest page(s)
+- */
+-enum async_tx_flags {
+-      ASYNC_TX_XOR_ZERO_DST    = (1 << 0),
+-      ASYNC_TX_XOR_DROP_DST    = (1 << 1),
+-      ASYNC_TX_ASSUME_COHERENT = (1 << 2),
+-      ASYNC_TX_ACK             = (1 << 3),
+-      ASYNC_TX_DEP_ACK         = (1 << 4),
+-      ASYNC_TX_KMAP_SRC        = (1 << 5),
+-      ASYNC_TX_KMAP_DST        = (1 << 6),
+-};
+-
+-#ifdef CONFIG_DMA_ENGINE
+-void async_tx_issue_pending_all(void);
+-enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
+-void async_tx_run_dependencies(struct dma_async_tx_descriptor *tx);
+-struct dma_chan *
+-async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+-      enum dma_transaction_type tx_type);
+-#else
+-static inline void async_tx_issue_pending_all(void)
+-{
+-      do { } while (0);
+-}
+-
+-static inline enum dma_status
+-dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
+-{
+-      return DMA_SUCCESS;
+-}
+-
+-static inline void
+-async_tx_run_dependencies(struct dma_async_tx_descriptor *tx,
+-      struct dma_chan *host_chan)
+-{
+-      do { } while (0);
+-}
+-
+-static inline struct dma_chan *
+-async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+-      enum dma_transaction_type tx_type)
+-{
+-      return NULL;
+-}
+-#endif
+-
+-/**
+- * async_tx_sync_epilog - actions to take if an operation is run synchronously
+- * @flags: async_tx flags
+- * @depend_tx: transaction depends on depend_tx
+- * @cb_fn: function to call when the transaction completes
+- * @cb_fn_param: parameter to pass to the callback routine
+- */
+-static inline void
+-async_tx_sync_epilog(unsigned long flags,
+-      struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_fn_param)
+-{
+-      if (cb_fn)
+-              cb_fn(cb_fn_param);
+-
+-      if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
+-              async_tx_ack(depend_tx);
+-}
+-
+-void
+-async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
+-      enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_fn_param);
+-
+-struct dma_async_tx_descriptor *
+-async_xor(struct page *dest, struct page **src_list, unsigned int offset,
+-      int src_cnt, size_t len, enum async_tx_flags flags,
+-      struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_fn_param);
+-
+-struct dma_async_tx_descriptor *
+-async_xor_zero_sum(struct page *dest, struct page **src_list,
+-      unsigned int offset, int src_cnt, size_t len,
+-      u32 *result, enum async_tx_flags flags,
+-      struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_fn_param);
+-
+-struct dma_async_tx_descriptor *
+-async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
+-      unsigned int src_offset, size_t len, enum async_tx_flags flags,
+-      struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_fn_param);
+-
+-struct dma_async_tx_descriptor *
+-async_memset(struct page *dest, int val, unsigned int offset,
+-      size_t len, enum async_tx_flags flags,
+-      struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_fn_param);
+-
+-struct dma_async_tx_descriptor *
+-async_trigger_callback(enum async_tx_flags flags,
+-      struct dma_async_tx_descriptor *depend_tx,
+-      dma_async_tx_callback cb_fn, void *cb_fn_param);
+-#endif /* _ASYNC_TX_H_ */
+diff -Nurb linux-2.6.22-590/include/linux/configfs.h linux-2.6.22-570/include/linux/configfs.h
+--- linux-2.6.22-590/include/linux/configfs.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/configfs.h  2007-07-08 19:32:17.000000000 -0400
+@@ -75,6 +75,7 @@
+ extern void config_item_init_type_name(struct config_item *item,
+                                      const char *name,
+                                      struct config_item_type *type);
++extern void config_item_cleanup(struct config_item *);
+ extern struct config_item * config_item_get(struct config_item *);
+ extern void config_item_put(struct config_item *);
+@@ -156,7 +157,6 @@
+       struct config_item *(*make_item)(struct config_group *group, const char *name);
+       struct config_group *(*make_group)(struct config_group *group, const char *name);
+       int (*commit_item)(struct config_item *item);
+-      void (*disconnect_notify)(struct config_group *group, struct config_item *item);
+       void (*drop_item)(struct config_group *group, struct config_item *item);
+ };
+@@ -175,11 +175,6 @@
+ int configfs_register_subsystem(struct configfs_subsystem *subsys);
+ void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
+-/* These functions can sleep and can alloc with GFP_KERNEL */
+-/* WARNING: These cannot be called underneath configfs callbacks!! */
+-int configfs_depend_item(struct configfs_subsystem *subsys, struct config_item *target);
+-void configfs_undepend_item(struct configfs_subsystem *subsys, struct config_item *target);
+-
+ #endif  /* __KERNEL__ */
+ #endif /* _CONFIGFS_H_ */
+diff -Nurb linux-2.6.22-590/include/linux/container.h linux-2.6.22-570/include/linux/container.h
+--- linux-2.6.22-590/include/linux/container.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/container.h 1969-12-31 19:00:00.000000000 -0500
+@@ -1,295 +0,0 @@
+-#ifndef _LINUX_CONTAINER_H
+-#define _LINUX_CONTAINER_H
+-/*
+- *  container interface
+- *
+- *  Copyright (C) 2003 BULL SA
+- *  Copyright (C) 2004-2006 Silicon Graphics, Inc.
+- *
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/kref.h>
+-#include <linux/cpumask.h>
+-#include <linux/nodemask.h>
+-#include <linux/rcupdate.h>
+-
+-#ifdef CONFIG_CONTAINERS
+-
+-struct containerfs_root;
+-struct inode;
+-
+-extern int container_init_early(void);
+-extern int container_init(void);
+-extern void container_init_smp(void);
+-extern void container_lock(void);
+-extern void container_unlock(void);
+-extern void container_fork(struct task_struct *p);
+-extern void container_fork_callbacks(struct task_struct *p);
+-extern void container_exit(struct task_struct *p, int run_callbacks);
+-
+-extern struct file_operations proc_container_operations;
+-
+-/* Define the enumeration of all container subsystems */
+-#define SUBSYS(_x) _x ## _subsys_id,
+-enum container_subsys_id {
+-#include <linux/container_subsys.h>
+-      CONTAINER_SUBSYS_COUNT
+-};
+-#undef SUBSYS
+-
+-/* Per-subsystem/per-container state maintained by the system. */
+-struct container_subsys_state {
+-      /* The container that this subsystem is attached to. Useful
+-       * for subsystems that want to know about the container
+-       * hierarchy structure */
+-      struct container *container;
+-
+-      /* State maintained by the container system to allow
+-       * subsystems to be "busy". Should be accessed via css_get()
+-       * and css_put() */
+-
+-      atomic_t refcnt;
+-};
+-
+-/*
+- * Call css_get() to hold a reference on the container;
+- *
+- */
+-
+-static inline void css_get(struct container_subsys_state *css)
+-{
+-      atomic_inc(&css->refcnt);
+-}
+-/*
+- * css_put() should be called to release a reference taken by
+- * css_get()
+- */
+-void css_put(struct container_subsys_state *css);
+-
+-struct container {
+-      unsigned long flags;            /* "unsigned long" so bitops work */
+-
+-      /* count users of this container. >0 means busy, but doesn't
+-       * necessarily indicate the number of tasks in the
+-       * container */
+-      atomic_t count;
+-
+-      /*
+-       * We link our 'sibling' struct into our parent's 'children'.
+-       * Our children link their 'sibling' into our 'children'.
+-       */
+-      struct list_head sibling;       /* my parent's children */
+-      struct list_head children;      /* my children */
+-
+-      struct container *parent;       /* my parent */
+-      struct dentry *dentry;          /* container fs entry */
+-
+-      /* Private pointers for each registered subsystem */
+-      struct container_subsys_state *subsys[CONTAINER_SUBSYS_COUNT];
+-
+-      struct containerfs_root *root;
+-      struct container *top_container;
+-
+-      /*
+-       * List of cg_container_links pointing at css_groups with
+-       * tasks in this container. Protected by css_group_lock
+-       */
+-      struct list_head css_groups;
+-
+-      /*
+-       * Linked list running through all containers that can
+-       * potentially be reaped by the release agent. Protected by
+-       * container_mutex
+-       */
+-      struct list_head release_list;
+-};
+-
+-/* A css_group is a structure holding pointers to a set of
+- * container_subsys_state objects. This saves space in the task struct
+- * object and speeds up fork()/exit(), since a single inc/dec and a
+- * list_add()/del() can bump the reference count on the entire
+- * container set for a task.
+- */
+-
+-struct css_group {
+-
+-      /* Reference count */
+-      struct kref ref;
+-
+-      /*
+-       * List running through all container groups. Protected by
+-       * css_group_lock
+-       */
+-      struct list_head list;
+-
+-      /*
+-       * List running through all tasks using this container
+-       * group. Protected by css_group_lock
+-       */
+-      struct list_head tasks;
+-
+-      /*
+-       * List of cg_container_link objects on link chains from
+-       * containers referenced from this css_group. Protected by
+-       * css_group_lock
+-       */
+-      struct list_head cg_links;
+-
+-      /* Set of subsystem states, one for each subsystem. NULL for
+-       * subsystems that aren't part of this hierarchy. These
+-       * pointers reduce the number of dereferences required to get
+-       * from a task to its state for a given container, but result
+-       * in increased space usage if tasks are in wildly different
+-       * groupings across different hierarchies. This array is
+-       * immutable after creation */
+-      struct container_subsys_state *subsys[CONTAINER_SUBSYS_COUNT];
+-
+-};
+-
+-/* struct cftype:
+- *
+- * The files in the container filesystem mostly have a very simple read/write
+- * handling, some common function will take care of it. Nevertheless some cases
+- * (read tasks) are special and therefore I define this structure for every
+- * kind of file.
+- *
+- *
+- * When reading/writing to a file:
+- *    - the container to use in file->f_dentry->d_parent->d_fsdata
+- *    - the 'cftype' of the file is file->f_dentry->d_fsdata
+- */
+-
+-#define MAX_CFTYPE_NAME 64
+-struct cftype {
+-      /* By convention, the name should begin with the name of the
+-       * subsystem, followed by a period */
+-      char name[MAX_CFTYPE_NAME];
+-      int private;
+-      int (*open) (struct inode *inode, struct file *file);
+-      ssize_t (*read) (struct container *cont, struct cftype *cft,
+-                       struct file *file,
+-                       char __user *buf, size_t nbytes, loff_t *ppos);
+-      /*
+-       * read_uint() is a shortcut for the common case of returning a
+-       * single integer. Use it in place of read()
+-       */
+-      u64 (*read_uint) (struct container *cont, struct cftype *cft);
+-      ssize_t (*write) (struct container *cont, struct cftype *cft,
+-                        struct file *file,
+-                        const char __user *buf, size_t nbytes, loff_t *ppos);
+-      int (*release) (struct inode *inode, struct file *file);
+-};
+-
+-/* Add a new file to the given container directory. Should only be
+- * called by subsystems from within a populate() method */
+-int container_add_file(struct container *cont, const struct cftype *cft);
+-
+-/* Add a set of new files to the given container directory. Should
+- * only be called by subsystems from within a populate() method */
+-int container_add_files(struct container *cont, const struct cftype cft[],
+-                      int count);
+-
+-int container_is_removed(const struct container *cont);
+-
+-int container_path(const struct container *cont, char *buf, int buflen);
+-
+-int container_task_count(const struct container *cont);
+-
+-/* Return true if the container is a descendant of the current container */
+-int container_is_descendant(const struct container *cont);
+-
+-/* Container subsystem type. See Documentation/containers.txt for details */
+-
+-struct container_subsys {
+-      int (*create)(struct container_subsys *ss,
+-                    struct container *cont);
+-      void (*destroy)(struct container_subsys *ss, struct container *cont);
+-      int (*can_attach)(struct container_subsys *ss,
+-                        struct container *cont, struct task_struct *tsk);
+-      void (*attach)(struct container_subsys *ss, struct container *cont,
+-                      struct container *old_cont, struct task_struct *tsk);
+-      void (*fork)(struct container_subsys *ss, struct task_struct *task);
+-      void (*exit)(struct container_subsys *ss, struct task_struct *task);
+-      int (*populate)(struct container_subsys *ss,
+-                      struct container *cont);
+-      void (*post_clone)(struct container_subsys *ss, struct container *cont);
+-      void (*bind)(struct container_subsys *ss, struct container *root);
+-      int subsys_id;
+-      int active;
+-      int early_init;
+-#define MAX_CONTAINER_TYPE_NAMELEN 32
+-      const char *name;
+-
+-      /* Protected by RCU */
+-      struct containerfs_root *root;
+-
+-      struct list_head sibling;
+-
+-      void *private;
+-};
+-
+-#define SUBSYS(_x) extern struct container_subsys _x ## _subsys;
+-#include <linux/container_subsys.h>
+-#undef SUBSYS
+-
+-static inline struct container_subsys_state *container_subsys_state(
+-      struct container *cont, int subsys_id)
+-{
+-      return cont->subsys[subsys_id];
+-}
+-
+-static inline struct container_subsys_state *task_subsys_state(
+-      struct task_struct *task, int subsys_id)
+-{
+-      return rcu_dereference(task->containers->subsys[subsys_id]);
+-}
+-
+-static inline struct container* task_container(struct task_struct *task,
+-                                             int subsys_id)
+-{
+-      return task_subsys_state(task, subsys_id)->container;
+-}
+-
+-int container_path(const struct container *cont, char *buf, int buflen);
+-
+-int container_clone(struct task_struct *tsk, struct container_subsys *ss);
+-
+-/* A container_iter should be treated as an opaque object */
+-struct container_iter {
+-      struct list_head *cg_link;
+-      struct list_head *task;
+-};
+-
+-/* To iterate across the tasks in a container:
+- *
+- * 1) call container_iter_start to intialize an iterator
+- *
+- * 2) call container_iter_next() to retrieve member tasks until it
+- *    returns NULL or until you want to end the iteration
+- *
+- * 3) call container_iter_end() to destroy the iterator.
+- */
+-void container_iter_start(struct container *cont, struct container_iter *it);
+-struct task_struct *container_iter_next(struct container *cont,
+-                                      struct container_iter *it);
+-void container_iter_end(struct container *cont, struct container_iter *it);
+-
+-void container_set_release_agent_path(struct container_subsys *ss,
+-                                    const char *path);
+-
+-#else /* !CONFIG_CONTAINERS */
+-
+-static inline int container_init_early(void) { return 0; }
+-static inline int container_init(void) { return 0; }
+-static inline void container_init_smp(void) {}
+-static inline void container_fork(struct task_struct *p) {}
+-static inline void container_fork_callbacks(struct task_struct *p) {}
+-static inline void container_exit(struct task_struct *p, int callbacks) {}
+-
+-static inline void container_lock(void) {}
+-static inline void container_unlock(void) {}
+-
+-#endif /* !CONFIG_CONTAINERS */
+-
+-#endif /* _LINUX_CONTAINER_H */
+diff -Nurb linux-2.6.22-590/include/linux/container_subsys.h linux-2.6.22-570/include/linux/container_subsys.h
+--- linux-2.6.22-590/include/linux/container_subsys.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/container_subsys.h  1969-12-31 19:00:00.000000000 -0500
+@@ -1,32 +0,0 @@
+-/* Add subsystem definitions of the form SUBSYS(<name>) in this
+- * file. Surround each one by a line of comment markers so that
+- * patches don't collide
+- */
+-
+-/* */
+-
+-/* */
+-
+-#ifdef CONFIG_CONTAINER_CPUACCT
+-SUBSYS(cpuacct)
+-#endif
+-
+-/* */
+-
+-#ifdef CONFIG_CPUSETS
+-SUBSYS(cpuset)
+-#endif
+-
+-/* */
+-
+-#ifdef CONFIG_CONTAINER_DEBUG
+-SUBSYS(debug)
+-#endif
+-
+-/* */
+-
+-#ifdef CONFIG_CONTAINER_NS
+-SUBSYS(ns)
+-#endif
+-
+-/* */
+diff -Nurb linux-2.6.22-590/include/linux/cpu_acct.h linux-2.6.22-570/include/linux/cpu_acct.h
+--- linux-2.6.22-590/include/linux/cpu_acct.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/cpu_acct.h  1969-12-31 19:00:00.000000000 -0500
+@@ -1,14 +0,0 @@
+-
+-#ifndef _LINUX_CPU_ACCT_H
+-#define _LINUX_CPU_ACCT_H
+-
+-#include <linux/container.h>
+-#include <asm/cputime.h>
+-
+-#ifdef CONFIG_CONTAINER_CPUACCT
+-extern void cpuacct_charge(struct task_struct *, cputime_t cputime);
+-#else
+-static void inline cpuacct_charge(struct task_struct *p, cputime_t cputime) {}
+-#endif
+-
+-#endif
+diff -Nurb linux-2.6.22-590/include/linux/cpuidle.h linux-2.6.22-570/include/linux/cpuidle.h
+--- linux-2.6.22-590/include/linux/cpuidle.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/cpuidle.h   1969-12-31 19:00:00.000000000 -0500
+@@ -1,189 +0,0 @@
+-/*
+- * cpuidle.h - a generic framework for CPU idle power management
+- *
+- * (C) 2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+- *          Shaohua Li <shaohua.li@intel.com>
+- *          Adam Belay <abelay@novell.com>
+- *
+- * This code is licenced under the GPL.
+- */
+-
+-#ifndef _LINUX_CPUIDLE_H
+-#define _LINUX_CPUIDLE_H
+-
+-#include <linux/percpu.h>
+-#include <linux/list.h>
+-#include <linux/module.h>
+-#include <linux/kobject.h>
+-#include <linux/completion.h>
+-
+-#define CPUIDLE_STATE_MAX     8
+-#define CPUIDLE_NAME_LEN      16
+-
+-struct cpuidle_device;
+-
+-
+-/****************************
+- * CPUIDLE DEVICE INTERFACE *
+- ****************************/
+-
+-struct cpuidle_state {
+-      char            name[CPUIDLE_NAME_LEN];
+-      void            *driver_data;
+-
+-      unsigned int    flags;
+-      unsigned int    exit_latency; /* in US */
+-      unsigned int    power_usage; /* in mW */
+-      unsigned int    target_residency; /* in US */
+-
+-      unsigned int    usage;
+-      unsigned int    time; /* in US */
+-
+-      int (*enter)    (struct cpuidle_device *dev,
+-                       struct cpuidle_state *state);
+-};
+-
+-/* Idle State Flags */
+-#define CPUIDLE_FLAG_TIME_VALID       (0x01) /* is residency time measurable? */
+-#define CPUIDLE_FLAG_CHECK_BM (0x02) /* BM activity will exit state */
+-#define CPUIDLE_FLAG_SHALLOW  (0x10) /* low latency, minimal savings */
+-#define CPUIDLE_FLAG_BALANCED (0x20) /* medium latency, moderate savings */
+-#define CPUIDLE_FLAG_DEEP     (0x40) /* high latency, large savings */
+-
+-#define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
+-
+-/**
+- * cpuidle_get_statedata - retrieves private driver state data
+- * @state: the state
+- */
+-static inline void * cpuidle_get_statedata(struct cpuidle_state *state)
+-{
+-      return state->driver_data;
+-}
+-
+-/**
+- * cpuidle_set_statedata - stores private driver state data
+- * @state: the state
+- * @data: the private data
+- */
+-static inline void
+-cpuidle_set_statedata(struct cpuidle_state *state, void *data)
+-{
+-      state->driver_data = data;
+-}
+-
+-struct cpuidle_state_kobj {
+-      struct cpuidle_state *state;
+-      struct completion kobj_unregister;
+-      struct kobject kobj;
+-};
+-
+-struct cpuidle_device {
+-      unsigned int            status;
+-      int                     cpu;
+-
+-      int                     last_residency;
+-      int                     state_count;
+-      struct cpuidle_state    states[CPUIDLE_STATE_MAX];
+-      struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
+-      struct cpuidle_state    *last_state;
+-
+-      struct list_head        device_list;
+-      struct kobject          kobj;
+-      struct completion       kobj_unregister;
+-      void                    *governor_data;
+-};
+-
+-DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+-
+-/* Device Status Flags */
+-#define CPUIDLE_STATUS_DETECTED                (0x1)
+-#define CPUIDLE_STATUS_DRIVER_ATTACHED         (0x2)
+-#define CPUIDLE_STATUS_GOVERNOR_ATTACHED (0x4)
+-#define CPUIDLE_STATUS_DOIDLE          (CPUIDLE_STATUS_DETECTED | \
+-                                        CPUIDLE_STATUS_DRIVER_ATTACHED | \
+-                                        CPUIDLE_STATUS_GOVERNOR_ATTACHED)
+-
+-/**
+- * cpuidle_get_last_residency - retrieves the last state's residency time
+- * @dev: the target CPU
+- *
+- * NOTE: this value is invalid if CPUIDLE_FLAG_TIME_VALID isn't set
+- */
+-static inline int cpuidle_get_last_residency(struct cpuidle_device *dev)
+-{
+-      return dev->last_residency;
+-}
+-
+-
+-/****************************
+- * CPUIDLE DRIVER INTERFACE *
+- ****************************/
+-
+-struct cpuidle_driver {
+-      char                    name[CPUIDLE_NAME_LEN];
+-      struct list_head        driver_list;
+-
+-      int  (*init)            (struct cpuidle_device *dev);
+-      void (*exit)            (struct cpuidle_device *dev);
+-      int  (*redetect)        (struct cpuidle_device *dev);
+-
+-      int  (*bm_check)        (void);
+-
+-      struct module           *owner;
+-};
+-
+-#ifdef CONFIG_CPU_IDLE
+-
+-extern int cpuidle_register_driver(struct cpuidle_driver *drv);
+-extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
+-extern int cpuidle_force_redetect(struct cpuidle_device *dev, struct cpuidle_driver *drv);
+-extern int cpuidle_force_redetect_devices(struct cpuidle_driver *drv);
+-
+-#else
+-
+-static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
+-{return 0;}
+-static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }
+-static inline int cpuidle_force_redetect(struct cpuidle_device *dev, struct cpuidle_driver *drv)
+-{return 0;}
+-static inline int cpuidle_force_redetect_devices(struct cpuidle_driver *drv)
+-{return 0;}
+-
+-#endif
+-
+-/******************************
+- * CPUIDLE GOVERNOR INTERFACE *
+- ******************************/
+-
+-struct cpuidle_governor {
+-      char                    name[CPUIDLE_NAME_LEN];
+-      struct list_head        governor_list;
+-
+-      int  (*init)            (struct cpuidle_device *dev);
+-      void (*exit)            (struct cpuidle_device *dev);
+-      void (*scan)            (struct cpuidle_device *dev);
+-
+-      int  (*select)          (struct cpuidle_device *dev);
+-      void (*reflect)         (struct cpuidle_device *dev);
+-
+-      struct module           *owner;
+-};
+-
+-#ifdef CONFIG_CPU_IDLE
+-
+-extern int cpuidle_register_governor(struct cpuidle_governor *gov);
+-extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
+-extern int cpuidle_get_bm_activity(void);
+-
+-#else
+-
+-static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
+-{return 0;}
+-static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { }
+-static inline int cpuidle_get_bm_activity(void)
+-{return 0;}
+-
+-#endif
+-
+-#endif /* _LINUX_CPUIDLE_H */
+diff -Nurb linux-2.6.22-590/include/linux/cpuset.h linux-2.6.22-570/include/linux/cpuset.h
+--- linux-2.6.22-590/include/linux/cpuset.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/cpuset.h    2007-07-08 19:32:17.000000000 -0400
+@@ -11,7 +11,6 @@
+ #include <linux/sched.h>
+ #include <linux/cpumask.h>
+ #include <linux/nodemask.h>
+-#include <linux/container.h>
+ #ifdef CONFIG_CPUSETS
+@@ -20,6 +19,8 @@
+ extern int cpuset_init_early(void);
+ extern int cpuset_init(void);
+ extern void cpuset_init_smp(void);
++extern void cpuset_fork(struct task_struct *p);
++extern void cpuset_exit(struct task_struct *p);
+ extern cpumask_t cpuset_cpus_allowed(struct task_struct *p);
+ extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
+ #define cpuset_current_mems_allowed (current->mems_allowed)
+@@ -74,13 +75,13 @@
+ extern void cpuset_track_online_nodes(void);
+-extern int current_cpuset_is_being_rebound(void);
+-
+ #else /* !CONFIG_CPUSETS */
+ static inline int cpuset_init_early(void) { return 0; }
+ static inline int cpuset_init(void) { return 0; }
+ static inline void cpuset_init_smp(void) {}
++static inline void cpuset_fork(struct task_struct *p) {}
++static inline void cpuset_exit(struct task_struct *p) {}
+ static inline cpumask_t cpuset_cpus_allowed(struct task_struct *p)
+ {
+@@ -145,11 +146,6 @@
+ static inline void cpuset_track_online_nodes(void) {}
+-static inline int current_cpuset_is_being_rebound(void)
+-{
+-      return 0;
+-}
+-
+ #endif /* !CONFIG_CPUSETS */
+ #endif /* _LINUX_CPUSET_H */
+diff -Nurb linux-2.6.22-590/include/linux/device.h linux-2.6.22-570/include/linux/device.h
+--- linux-2.6.22-590/include/linux/device.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/device.h    2007-07-08 19:32:17.000000000 -0400
+@@ -200,8 +200,6 @@
+       int     (*suspend)(struct device *, pm_message_t state);
+       int     (*resume)(struct device *);
+-
+-      const struct shadow_dir_operations *shadow_ops;
+ };
+ extern int __must_check class_register(struct class *);
+@@ -240,6 +238,7 @@
+  * @devt: for internal use by the driver core only.
+  * @node: for internal use by the driver core only.
+  * @kobj: for internal use by the driver core only.
++ * @devt_attr: for internal use by the driver core only.
+  * @groups: optional additional groups to be created
+  * @dev: if set, a symlink to the struct device is created in the sysfs
+  * directory for this struct class device.
+@@ -264,6 +263,8 @@
+       struct kobject          kobj;
+       struct class            * class;        /* required */
+       dev_t                   devt;           /* dev_t, creates the sysfs "dev" */
++      struct class_device_attribute *devt_attr;
++      struct class_device_attribute uevent_attr;
+       struct device           * dev;          /* not necessary, but nice to have */
+       void                    * class_data;   /* class-specific data */
+       struct class_device     *parent;        /* parent of this child device, if there is one */
+@@ -418,6 +419,8 @@
+       struct device_type      *type;
+       unsigned                is_registered:1;
+       unsigned                uevent_suppress:1;
++      struct device_attribute uevent_attr;
++      struct device_attribute *devt_attr;
+       struct semaphore        sem;    /* semaphore to synchronize calls to
+                                        * its driver.
+diff -Nurb linux-2.6.22-590/include/linux/dmaengine.h linux-2.6.22-570/include/linux/dmaengine.h
+--- linux-2.6.22-590/include/linux/dmaengine.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/dmaengine.h 2007-07-08 19:32:17.000000000 -0400
+@@ -21,40 +21,29 @@
+ #ifndef DMAENGINE_H
+ #define DMAENGINE_H
++#ifdef CONFIG_DMA_ENGINE
 +
-+/*
-+ * There are times we need to call a tasklet to cause a breakpoint
-+ * as calling breakpoint() at that point might be fatal.  We have to
-+ * check that the exception stack is setup, as tasklets may be scheduled
-+ * prior to this.  When that happens, it is up to the architecture to
-+ * schedule this when it is safe to run.
+ #include <linux/device.h>
+ #include <linux/uio.h>
+ #include <linux/kref.h>
+ #include <linux/completion.h>
+ #include <linux/rcupdate.h>
+-#include <linux/dma-mapping.h>
+ /**
+- * enum dma_state - resource PNP/power managment state
++ * enum dma_event - resource PNP/power managment events
+  * @DMA_RESOURCE_SUSPEND: DMA device going into low power state
+  * @DMA_RESOURCE_RESUME: DMA device returning to full power
+- * @DMA_RESOURCE_AVAILABLE: DMA device available to the system
++ * @DMA_RESOURCE_ADDED: DMA device added to the system
+  * @DMA_RESOURCE_REMOVED: DMA device removed from the system
+  */
+-enum dma_state {
++enum dma_event {
+       DMA_RESOURCE_SUSPEND,
+       DMA_RESOURCE_RESUME,
+-      DMA_RESOURCE_AVAILABLE,
++      DMA_RESOURCE_ADDED,
+       DMA_RESOURCE_REMOVED,
+ };
+ /**
+- * enum dma_state_client - state of the channel in the client
+- * @DMA_ACK: client would like to use, or was using this channel
+- * @DMA_DUP: client has already seen this channel, or is not using this channel
+- * @DMA_NAK: client does not want to see any more channels
+- */
+-enum dma_state_client {
+-      DMA_ACK,
+-      DMA_DUP,
+-      DMA_NAK,
+-};
+-
+-/**
+  * typedef dma_cookie_t - an opaque DMA cookie
+  *
+  * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code
+@@ -76,31 +65,6 @@
+ };
+ /**
+- * enum dma_transaction_type - DMA transaction types/indexes
+- */
+-enum dma_transaction_type {
+-      DMA_MEMCPY,
+-      DMA_XOR,
+-      DMA_PQ_XOR,
+-      DMA_DUAL_XOR,
+-      DMA_PQ_UPDATE,
+-      DMA_ZERO_SUM,
+-      DMA_PQ_ZERO_SUM,
+-      DMA_MEMSET,
+-      DMA_MEMCPY_CRC32C,
+-      DMA_INTERRUPT,
+-};
+-
+-/* last transaction type for creation of the capabilities mask */
+-#define DMA_TX_TYPE_END (DMA_INTERRUPT + 1)
+-
+-/**
+- * dma_cap_mask_t - capabilities bitmap modeled after cpumask_t.
+- * See linux/cpumask.h
+- */
+-typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t;
+-
+-/**
+  * struct dma_chan_percpu - the per-CPU part of struct dma_chan
+  * @refcount: local_t used for open-coded "bigref" counting
+  * @memcpy_count: transaction counter
+@@ -116,6 +80,7 @@
+ /**
+  * struct dma_chan - devices supply DMA channels, clients use them
++ * @client: ptr to the client user of this chan, will be %NULL when unused
+  * @device: ptr to the dma device who supplies this channel, always !%NULL
+  * @cookie: last cookie value returned to client
+  * @chan_id: channel ID for sysfs
+@@ -123,10 +88,12 @@
+  * @refcount: kref, used in "bigref" slow-mode
+  * @slow_ref: indicates that the DMA channel is free
+  * @rcu: the DMA channel's RCU head
++ * @client_node: used to add this to the client chan list
+  * @device_node: used to add this to the device chan list
+  * @local: per-cpu pointer to a struct dma_chan_percpu
+  */
+ struct dma_chan {
++      struct dma_client *client;
+       struct dma_device *device;
+       dma_cookie_t cookie;
+@@ -138,11 +105,11 @@
+       int slow_ref;
+       struct rcu_head rcu;
++      struct list_head client_node;
+       struct list_head device_node;
+       struct dma_chan_percpu *local;
+ };
+-
+ void dma_chan_cleanup(struct kref *kref);
+ static inline void dma_chan_get(struct dma_chan *chan)
+@@ -167,68 +134,27 @@
+ /*
+  * typedef dma_event_callback - function pointer to a DMA event callback
+- * For each channel added to the system this routine is called for each client.
+- * If the client would like to use the channel it returns '1' to signal (ack)
+- * the dmaengine core to take out a reference on the channel and its
+- * corresponding device.  A client must not 'ack' an available channel more
+- * than once.  When a channel is removed all clients are notified.  If a client
+- * is using the channel it must 'ack' the removal.  A client must not 'ack' a
+- * removed channel more than once.
+- * @client - 'this' pointer for the client context
+- * @chan - channel to be acted upon
+- * @state - available or removed
+- */
+-struct dma_client;
+-typedef enum dma_state_client (*dma_event_callback) (struct dma_client *client,
+-              struct dma_chan *chan, enum dma_state state);
++ */
++typedef void (*dma_event_callback) (struct dma_client *client,
++              struct dma_chan *chan, enum dma_event event);
+ /**
+  * struct dma_client - info on the entity making use of DMA services
+  * @event_callback: func ptr to call when something happens
+- * @cap_mask: only return channels that satisfy the requested capabilities
+- *  a value of zero corresponds to any capability
++ * @chan_count: number of chans allocated
++ * @chans_desired: number of chans requested. Can be +/- chan_count
++ * @lock: protects access to the channels list
++ * @channels: the list of DMA channels allocated
+  * @global_node: list_head for global dma_client_list
+  */
+ struct dma_client {
+       dma_event_callback      event_callback;
+-      dma_cap_mask_t          cap_mask;
+-      struct list_head        global_node;
+-};
++      unsigned int            chan_count;
++      unsigned int            chans_desired;
+-typedef void (*dma_async_tx_callback)(void *dma_async_param);
+-/**
+- * struct dma_async_tx_descriptor - async transaction descriptor
+- * @cookie: tracking cookie for this transaction, set to -EBUSY if
+- *    this tx is sitting on a dependency list
+- * @ack: the descriptor can not be reused until the client acknowledges
+- *    receipt, i.e. has has a chance to establish any dependency chains
+- * @callback: routine to call after this operation is complete
+- * @callback_param: general parameter to pass to the callback routine
+- * @chan: target channel for this operation
+- * @tx_submit: execute an operation
+- * @tx_set_dest: set a destination address in a hardware descriptor
+- * @tx_set_src: set a source address in a hardware descriptor
+- * @depend_list: at completion this list of transactions are submitted
+- * @depend_node: allow this transaction to be executed after another
+- *    transaction has completed
+- * @parent: pointer to the next level up in the dependency chain
+- * @lock: protect the dependency list
+- */
+-struct dma_async_tx_descriptor {
+-      dma_cookie_t cookie;
+-      int ack;
+-      dma_async_tx_callback callback;
+-      void *callback_param;
+-      struct dma_chan *chan;
+-      dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);
+-      void (*tx_set_dest)(dma_addr_t addr,
+-              struct dma_async_tx_descriptor *tx, int index);
+-      void (*tx_set_src)(dma_addr_t addr,
+-              struct dma_async_tx_descriptor *tx, int index);
+-      struct list_head depend_list;
+-      struct list_head depend_node;
+-      struct dma_async_tx_descriptor *parent;
+       spinlock_t              lock;
++      struct list_head        channels;
++      struct list_head        global_node;
+ };
+ /**
+@@ -236,130 +162,141 @@
+  * @chancnt: how many DMA channels are supported
+  * @channels: the list of struct dma_chan
+  * @global_node: list_head for global dma_device_list
+- * @cap_mask: one or more dma_capability flags
+- * @max_xor: maximum number of xor sources, 0 if no capability
+  * @refcount: reference count
+  * @done: IO completion struct
+  * @dev_id: unique device ID
+- * @dev: struct device reference for dma mapping api
+  * @device_alloc_chan_resources: allocate resources and return the
+  *    number of allocated descriptors
+  * @device_free_chan_resources: release DMA channel's resources
+- * @device_prep_dma_memcpy: prepares a memcpy operation
+- * @device_prep_dma_xor: prepares a xor operation
+- * @device_prep_dma_zero_sum: prepares a zero_sum operation
+- * @device_prep_dma_memset: prepares a memset operation
+- * @device_prep_dma_interrupt: prepares an end of chain interrupt operation
+- * @device_dependency_added: async_tx notifies the channel about new deps
+- * @device_issue_pending: push pending transactions to hardware
++ * @device_memcpy_buf_to_buf: memcpy buf pointer to buf pointer
++ * @device_memcpy_buf_to_pg: memcpy buf pointer to struct page
++ * @device_memcpy_pg_to_pg: memcpy struct page/offset to struct page/offset
++ * @device_memcpy_complete: poll the status of an IOAT DMA transaction
++ * @device_memcpy_issue_pending: push appended descriptors to hardware
+  */
+ struct dma_device {
+       unsigned int chancnt;
+       struct list_head channels;
+       struct list_head global_node;
+-      dma_cap_mask_t  cap_mask;
+-      int max_xor;
+       struct kref refcount;
+       struct completion done;
+       int dev_id;
+-      struct device *dev;
+       int (*device_alloc_chan_resources)(struct dma_chan *chan);
+       void (*device_free_chan_resources)(struct dma_chan *chan);
+-
+-      struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(
+-              struct dma_chan *chan, size_t len, int int_en);
+-      struct dma_async_tx_descriptor *(*device_prep_dma_xor)(
+-              struct dma_chan *chan, unsigned int src_cnt, size_t len,
+-              int int_en);
+-      struct dma_async_tx_descriptor *(*device_prep_dma_zero_sum)(
+-              struct dma_chan *chan, unsigned int src_cnt, size_t len,
+-              u32 *result, int int_en);
+-      struct dma_async_tx_descriptor *(*device_prep_dma_memset)(
+-              struct dma_chan *chan, int value, size_t len, int int_en);
+-      struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
+-              struct dma_chan *chan);
+-
+-      void (*device_dependency_added)(struct dma_chan *chan);
+-      enum dma_status (*device_is_tx_complete)(struct dma_chan *chan,
++      dma_cookie_t (*device_memcpy_buf_to_buf)(struct dma_chan *chan,
++                      void *dest, void *src, size_t len);
++      dma_cookie_t (*device_memcpy_buf_to_pg)(struct dma_chan *chan,
++                      struct page *page, unsigned int offset, void *kdata,
++                      size_t len);
++      dma_cookie_t (*device_memcpy_pg_to_pg)(struct dma_chan *chan,
++                      struct page *dest_pg, unsigned int dest_off,
++                      struct page *src_pg, unsigned int src_off, size_t len);
++      enum dma_status (*device_memcpy_complete)(struct dma_chan *chan,
+                       dma_cookie_t cookie, dma_cookie_t *last,
+                       dma_cookie_t *used);
+-      void (*device_issue_pending)(struct dma_chan *chan);
++      void (*device_memcpy_issue_pending)(struct dma_chan *chan);
+ };
+ /* --- public DMA engine API --- */
+-void dma_async_client_register(struct dma_client *client);
++struct dma_client *dma_async_client_register(dma_event_callback event_callback);
+ void dma_async_client_unregister(struct dma_client *client);
+-void dma_async_client_chan_request(struct dma_client *client);
+-dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
+-      void *dest, void *src, size_t len);
+-dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
+-      struct page *page, unsigned int offset, void *kdata, size_t len);
+-dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
+-      struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
+-      unsigned int src_off, size_t len);
+-void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+-      struct dma_chan *chan);
++void dma_async_client_chan_request(struct dma_client *client,
++              unsigned int number);
+-static inline void
+-async_tx_ack(struct dma_async_tx_descriptor *tx)
++/**
++ * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
++ * @chan: DMA channel to offload copy to
++ * @dest: destination address (virtual)
++ * @src: source address (virtual)
++ * @len: length
++ *
++ * Both @dest and @src must be mappable to a bus address according to the
++ * DMA mapping API rules for streaming mappings.
++ * Both @dest and @src must stay memory resident (kernel memory or locked
++ * user space pages).
++ */
++static inline dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
++      void *dest, void *src, size_t len)
+ {
+-      tx->ack = 1;
+-}
++      int cpu = get_cpu();
++      per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
++      per_cpu_ptr(chan->local, cpu)->memcpy_count++;
++      put_cpu();
+-#define first_dma_cap(mask) __first_dma_cap(&(mask))
+-static inline int __first_dma_cap(const dma_cap_mask_t *srcp)
+-{
+-      return min_t(int, DMA_TX_TYPE_END,
+-              find_first_bit(srcp->bits, DMA_TX_TYPE_END));
++      return chan->device->device_memcpy_buf_to_buf(chan, dest, src, len);
+ }
+-#define next_dma_cap(n, mask) __next_dma_cap((n), &(mask))
+-static inline int __next_dma_cap(int n, const dma_cap_mask_t *srcp)
++/**
++ * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
++ * @chan: DMA channel to offload copy to
++ * @page: destination page
++ * @offset: offset in page to copy to
++ * @kdata: source address (virtual)
++ * @len: length
++ *
++ * Both @page/@offset and @kdata must be mappable to a bus address according
++ * to the DMA mapping API rules for streaming mappings.
++ * Both @page/@offset and @kdata must stay memory resident (kernel memory or
++ * locked user space pages)
 + */
-+static void kgdb_tasklet_bpt(unsigned long ing)
-+{
-+      if (CHECK_EXCEPTION_STACK())
-+              breakpoint();
-+}
-+
-+DECLARE_TASKLET(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt, 0);
-+
-+/*
-+ * This function can be called very early, either via early_param() or
-+ * an explicit breakpoint() early on.
++static inline dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
++      struct page *page, unsigned int offset, void *kdata, size_t len)
+ {
+-      return min_t(int, DMA_TX_TYPE_END,
+-              find_next_bit(srcp->bits, DMA_TX_TYPE_END, n+1));
+-}
++      int cpu = get_cpu();
++      per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
++      per_cpu_ptr(chan->local, cpu)->memcpy_count++;
++      put_cpu();
+-#define dma_cap_set(tx, mask) __dma_cap_set((tx), &(mask))
+-static inline void
+-__dma_cap_set(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp)
+-{
+-      set_bit(tx_type, dstp->bits);
++      return chan->device->device_memcpy_buf_to_pg(chan, page, offset,
++                                                   kdata, len);
+ }
+-#define dma_has_cap(tx, mask) __dma_has_cap((tx), &(mask))
+-static inline int
+-__dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp)
++/**
++ * dma_async_memcpy_pg_to_pg - offloaded copy from page to page
++ * @chan: DMA channel to offload copy to
++ * @dest_pg: destination page
++ * @dest_off: offset in page to copy to
++ * @src_pg: source page
++ * @src_off: offset in page to copy from
++ * @len: length
++ *
++ * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
++ * address according to the DMA mapping API rules for streaming mappings.
++ * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
++ * (kernel memory or locked user space pages).
 + */
-+static void __init kgdb_early_entry(void)
-+{
-+      /* Let the architecture do any setup that it needs to. */
-+      kgdb_arch_init();
-+
-+      /*
-+       * Don't try and do anything until the architecture is able to
-+       * setup the exception stack.  In this case, it is up to the
-+       * architecture to hook in and look at us when they are ready.
-+       */
-+
-+      if (!CHECK_EXCEPTION_STACK()) {
-+              kgdb_initialized = -1;
-+              /* any kind of break point is deferred to late_init */
-+              return;
-+      }
-+
-+      /* Now try the I/O. */
-+      /* For early entry kgdb_io_ops.init must be defined */
-+      if (!kgdb_io_ops.init || kgdb_io_ops.init()) {
-+              /* Try again later. */
-+              kgdb_initialized = -1;
-+              return;
-+      }
-+
-+      /* Finish up. */
-+      kgdb_internal_init();
-+
-+      /* KGDB can assume that if kgdb_io_ops.init was defined that the
-+       * panic registion should be performed at this time. This means
-+       * kgdb_io_ops.init did not come from a kernel module and was
-+       * initialized statically by a built in.
-+       */
-+      if (kgdb_io_ops.init)
-+              kgdb_register_for_panic();
++static inline dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
++      struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
++      unsigned int src_off, size_t len)
+ {
+-      return test_bit(tx_type, srcp->bits);
+-}
++      int cpu = get_cpu();
++      per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
++      per_cpu_ptr(chan->local, cpu)->memcpy_count++;
++      put_cpu();
+-#define for_each_dma_cap_mask(cap, mask) \
+-      for ((cap) = first_dma_cap(mask);       \
+-              (cap) < DMA_TX_TYPE_END;        \
+-              (cap) = next_dma_cap((cap), (mask)))
++      return chan->device->device_memcpy_pg_to_pg(chan, dest_pg, dest_off,
++                                                  src_pg, src_off, len);
 +}
-+
-+/*
-+ * This function will always be invoked to make sure that KGDB will grab
-+ * what it needs to so that if something happens while the system is
-+ * running, KGDB will get involved.  If kgdb_early_entry() has already
-+ * been invoked, there is little we need to do.
-+ */
-+static int __init kgdb_late_entry(void)
+ /**
+- * dma_async_issue_pending - flush pending transactions to HW
++ * dma_async_memcpy_issue_pending - flush pending copies to HW
+  * @chan: target DMA channel
+  *
+  * This allows drivers to push copies to HW in batches,
+  * reducing MMIO writes where possible.
+  */
+-static inline void dma_async_issue_pending(struct dma_chan *chan)
++static inline void dma_async_memcpy_issue_pending(struct dma_chan *chan)
+ {
+-      return chan->device->device_issue_pending(chan);
++      return chan->device->device_memcpy_issue_pending(chan);
+ }
+-#define dma_async_memcpy_issue_pending(chan) dma_async_issue_pending(chan)
+-
+ /**
+- * dma_async_is_tx_complete - poll for transaction completion
++ * dma_async_memcpy_complete - poll for transaction completion
+  * @chan: DMA channel
+  * @cookie: transaction identifier to check status of
+  * @last: returns last completed cookie, can be NULL
+@@ -369,15 +306,12 @@
+  * internal state and can be used with dma_async_is_complete() to check
+  * the status of multiple cookies without re-checking hardware state.
+  */
+-static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
++static inline enum dma_status dma_async_memcpy_complete(struct dma_chan *chan,
+       dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
+ {
+-      return chan->device->device_is_tx_complete(chan, cookie, last, used);
++      return chan->device->device_memcpy_complete(chan, cookie, last, used);
+ }
+-#define dma_async_memcpy_complete(chan, cookie, last, used)\
+-      dma_async_is_tx_complete(chan, cookie, last, used)
+-
+ /**
+  * dma_async_is_complete - test a cookie against chan state
+  * @cookie: transaction identifier to test status of
+@@ -400,7 +334,6 @@
+       return DMA_IN_PROGRESS;
+ }
+-enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
+ /* --- DMA device --- */
+@@ -429,4 +362,5 @@
+       struct dma_pinned_list *pinned_list, struct page *page,
+       unsigned int offset, size_t len);
++#endif /* CONFIG_DMA_ENGINE */
+ #endif /* DMAENGINE_H */
+diff -Nurb linux-2.6.22-590/include/linux/etherdevice.h linux-2.6.22-570/include/linux/etherdevice.h
+--- linux-2.6.22-590/include/linux/etherdevice.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/etherdevice.h       2007-07-08 19:32:17.000000000 -0400
+@@ -40,6 +40,12 @@
+                                        struct hh_cache *hh);
+ extern struct net_device *alloc_etherdev(int sizeof_priv);
++static inline void eth_copy_and_sum (struct sk_buff *dest, 
++                                   const unsigned char *src, 
++                                   int len, int base)
 +{
-+      int need_break = 0;
-+
-+      /* If kgdb_initialized is -1 then we were passed kgdbwait. */
-+      if (kgdb_initialized == -1)
-+              need_break = 1;
-+
-+      /*
-+       * If we haven't tried to initialize KGDB yet, we need to call
-+       * kgdb_arch_init before moving onto the I/O.
-+       */
-+      if (!kgdb_initialized)
-+              kgdb_arch_init();
-+
-+      if (kgdb_initialized != 1) {
-+              if (kgdb_io_ops.init && kgdb_io_ops.init()) {
-+                      /* When KGDB allows I/O via modules and the core
-+                       * I/O init fails KGDB must default to defering the
-+                       * I/O setup, and appropriately print an error about
-+                       * it.
-+                       */
-+                      printk(KERN_ERR "kgdb: Could not setup core I/O "
-+                             "for KGDB.\n");
-+                      printk(KERN_INFO "kgdb: Defering I/O setup to kernel "
-+                             "module.\n");
-+                      memset(&kgdb_io_ops, 0, sizeof(struct kgdb_io));
-+              }
-+
-+              kgdb_internal_init();
-+
-+              /* KGDB can assume that if kgdb_io_ops.init was defined that
-+               * panic registion should be performed at this time. This means
-+               * kgdb_io_ops.init did not come from a kernel module and was
-+               * initialized statically by a built in.
-+               */
-+              if (kgdb_io_ops.init)
-+                      kgdb_register_for_panic();
-+      }
-+
-+      /* Registering to reboot notifier list*/
-+      register_reboot_notifier(&kgdb_reboot_notifier);
-+
-+      /* Now do any late init of the I/O. */
-+      if (kgdb_io_ops.late_init)
-+              kgdb_io_ops.late_init();
-+
-+      if (need_break) {
-+              printk(KERN_CRIT "kgdb: Waiting for connection from remote"
-+                     " gdb...\n");
-+              breakpoint();
-+      }
-+
-+      return 0;
++      memcpy (dest->data, src, len);
 +}
+ /**
+  * is_zero_ether_addr - Determine if give Ethernet address is all zeros.
+diff -Nurb linux-2.6.22-590/include/linux/freezer.h linux-2.6.22-570/include/linux/freezer.h
+--- linux-2.6.22-590/include/linux/freezer.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/freezer.h   2007-07-08 19:32:17.000000000 -0400
+@@ -115,14 +115,6 @@
+       return !!(p->flags & PF_FREEZER_SKIP);
+ }
+-/*
+- * Tell the freezer that the current task should be frozen by it
+- */
+-static inline void set_freezable(void)
+-{
+-      current->flags &= ~PF_NOFREEZE;
+-}
+-
+ #else
+ static inline int frozen(struct task_struct *p) { return 0; }
+ static inline int freezing(struct task_struct *p) { return 0; }
+@@ -138,5 +130,4 @@
+ static inline void freezer_do_not_count(void) {}
+ static inline void freezer_count(void) {}
+ static inline int freezer_should_skip(struct task_struct *p) { return 0; }
+-static inline void set_freezable(void) {}
+ #endif
+diff -Nurb linux-2.6.22-590/include/linux/fs.h linux-2.6.22-570/include/linux/fs.h
+--- linux-2.6.22-590/include/linux/fs.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/fs.h        2008-01-23 19:16:14.000000000 -0500
+@@ -283,17 +283,6 @@
+ #define SYNC_FILE_RANGE_WRITE         2
+ #define SYNC_FILE_RANGE_WAIT_AFTER    4
+-/*
+- * sys_fallocate modes
+- * Currently sys_fallocate supports two modes:
+- * FA_ALLOCATE  : This is the preallocate mode, using which an application/user
+- *              may request (pre)allocation of blocks.
+- * FA_DEALLOCATE: This is the deallocate mode, which can be used to free
+- *              the preallocated blocks.
+- */
+-#define FA_ALLOCATE   0x1
+-#define FA_DEALLOCATE 0x2
+-
+ #ifdef __KERNEL__
+ #include <linux/linkage.h>
+@@ -311,7 +300,6 @@
+ #include <linux/init.h>
+ #include <linux/pid.h>
+ #include <linux/mutex.h>
+-#include <linux/sysctl.h>
+ #include <asm/atomic.h>
+ #include <asm/semaphore.h>
+@@ -1151,7 +1139,6 @@
+       int (*flock) (struct file *, int, struct file_lock *);
+       ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
+       ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
+-      int (*revoke)(struct file *, struct address_space *);
+ };
+ struct inode_operations {
+@@ -1177,8 +1164,6 @@
+       ssize_t (*listxattr) (struct dentry *, char *, size_t);
+       int (*removexattr) (struct dentry *, const char *);
+       void (*truncate_range)(struct inode *, loff_t, loff_t);
+-      long (*fallocate)(struct inode *inode, int mode, loff_t offset,
+-                        loff_t len);
+       int (*sync_flags) (struct inode *);
+ };
+@@ -1824,13 +1809,6 @@
+ extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+               size_t len, unsigned int flags);
+-/* fs/revoke.c */
+-#ifdef CONFIG_MMU
+-extern int generic_file_revoke(struct file *, struct address_space *);
+-#else
+-#define generic_file_revoke NULL
+-#endif
+-
+ extern void
+ file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
+ extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
+@@ -2099,9 +2077,5 @@
+ { }
+ #endif        /* CONFIG_SECURITY */
+-int proc_nr_files(ctl_table *table, int write, struct file *filp,
+-                void __user *buffer, size_t *lenp, loff_t *ppos);
+-
+-
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_FS_H */
+diff -Nurb linux-2.6.22-590/include/linux/fs_stack.h linux-2.6.22-570/include/linux/fs_stack.h
+--- linux-2.6.22-590/include/linux/fs_stack.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/fs_stack.h  2007-07-08 19:32:17.000000000 -0400
+@@ -1,19 +1,7 @@
+-/*
+- * Copyright (c) 2006-2007 Erez Zadok
+- * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2006-2007 Stony Brook University
+- * Copyright (c) 2006-2007 The Research Foundation of SUNY
+- *
+- * 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.
+- */
+-
+ #ifndef _LINUX_FS_STACK_H
+ #define _LINUX_FS_STACK_H
+-/*
+- * This file defines generic functions used primarily by stackable
++/* This file defines generic functions used primarily by stackable
+  * filesystems; none of these functions require i_mutex to be held.
+  */
+@@ -23,8 +11,7 @@
+ extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
+                               int (*get_nlinks)(struct inode *));
+-extern void fsstack_copy_inode_size(struct inode *dst,
+-                                  const struct inode *src);
++extern void fsstack_copy_inode_size(struct inode *dst, const struct inode *src);
+ /* inlines */
+ static inline void fsstack_copy_attr_atime(struct inode *dest,
+diff -Nurb linux-2.6.22-590/include/linux/gfp.h linux-2.6.22-570/include/linux/gfp.h
+--- linux-2.6.22-590/include/linux/gfp.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/gfp.h       2007-07-08 19:32:17.000000000 -0400
+@@ -30,9 +30,6 @@
+  * cannot handle allocation failures.
+  *
+  * __GFP_NORETRY: The VM implementation must not retry indefinitely.
+- *
+- * __GFP_MOVABLE: Flag that this page will be movable by the page migration
+- * mechanism or reclaimed
+  */
+ #define __GFP_WAIT    ((__force gfp_t)0x10u)  /* Can wait and reschedule? */
+ #define __GFP_HIGH    ((__force gfp_t)0x20u)  /* Should access emergency pools? */
+@@ -48,21 +45,15 @@
+ #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
+ #define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
+ #define __GFP_THISNODE        ((__force gfp_t)0x40000u)/* No fallback, no policies */
+-#define __GFP_RECLAIMABLE ((__force gfp_t)0x80000u) /* Page is reclaimable */
+-#define __GFP_MOVABLE ((__force gfp_t)0x100000u)  /* Page is movable */
+-#define __GFP_BITS_SHIFT 21   /* Room for 21 __GFP_FOO bits */
++#define __GFP_BITS_SHIFT 20   /* Room for 20 __GFP_FOO bits */
+ #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
+ /* if you forget to add the bitmask here kernel will crash, period */
+ #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
+                       __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
+                       __GFP_NOFAIL|__GFP_NORETRY|__GFP_COMP| \
+-                      __GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE| \
+-                      __GFP_RECLAIMABLE|__GFP_MOVABLE)
+-
+-/* This mask makes up all the page movable related flags */
+-#define GFP_MOVABLE_MASK (__GFP_RECLAIMABLE|__GFP_MOVABLE)
++                      __GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE)
+ /* This equals 0, but use constants in case they ever change */
+ #define GFP_NOWAIT    (GFP_ATOMIC & ~__GFP_HIGH)
+@@ -71,20 +62,9 @@
+ #define GFP_NOIO      (__GFP_WAIT)
+ #define GFP_NOFS      (__GFP_WAIT | __GFP_IO)
+ #define GFP_KERNEL    (__GFP_WAIT | __GFP_IO | __GFP_FS)
+-#define GFP_TEMPORARY (__GFP_WAIT | __GFP_IO | __GFP_FS | \
+-                       __GFP_RECLAIMABLE)
+ #define GFP_USER      (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
+ #define GFP_HIGHUSER  (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \
+                        __GFP_HIGHMEM)
+-#define GFP_HIGHUSER_MOVABLE  (__GFP_WAIT | __GFP_IO | __GFP_FS | \
+-                               __GFP_HARDWALL | __GFP_HIGHMEM | \
+-                               __GFP_MOVABLE)
+-#define GFP_NOFS_PAGECACHE    (__GFP_WAIT | __GFP_IO | __GFP_MOVABLE)
+-#define GFP_USER_PAGECACHE    (__GFP_WAIT | __GFP_IO | __GFP_FS | \
+-                               __GFP_HARDWALL | __GFP_MOVABLE)
+-#define GFP_HIGHUSER_PAGECACHE        (__GFP_WAIT | __GFP_IO | __GFP_FS | \
+-                               __GFP_HARDWALL | __GFP_HIGHMEM | \
+-                               __GFP_MOVABLE)
+ #ifdef CONFIG_NUMA
+ #define GFP_THISNODE  (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
+@@ -119,12 +99,6 @@
+       return ZONE_NORMAL;
+ }
+-static inline gfp_t set_migrateflags(gfp_t gfp, gfp_t migrate_flags)
+-{
+-      BUG_ON((gfp & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK);
+-      return (gfp & ~(GFP_MOVABLE_MASK)) | migrate_flags;
+-}
+-
+ /*
+  * There is only one page-allocator function, and two main namespaces to
+  * it. The alloc_page*() variants return 'struct page *' and as such
+diff -Nurb linux-2.6.22-590/include/linux/highmem.h linux-2.6.22-570/include/linux/highmem.h
+--- linux-2.6.22-590/include/linux/highmem.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/highmem.h   2007-07-08 19:32:17.000000000 -0400
+@@ -73,27 +73,10 @@
+ }
+ #ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+-/**
+- * __alloc_zeroed_user_highpage - Allocate a zeroed HIGHMEM page for a VMA with caller-specified movable GFP flags
+- * @movableflags: The GFP flags related to the pages future ability to move like __GFP_MOVABLE
+- * @vma: The VMA the page is to be allocated for
+- * @vaddr: The virtual address the page will be inserted into
+- *
+- * This function will allocate a page for a VMA but the caller is expected
+- * to specify via movableflags whether the page will be movable in the
+- * future or not
+- *
+- * An architecture may override this function by defining
+- * __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE and providing their own
+- * implementation.
+- */
+ static inline struct page *
+-__alloc_zeroed_user_highpage(gfp_t movableflags,
+-                      struct vm_area_struct *vma,
+-                      unsigned long vaddr)
++alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr)
+ {
+-      struct page *page = alloc_page_vma(GFP_HIGHUSER | movableflags,
+-                      vma, vaddr);
++      struct page *page = alloc_page_vma(GFP_HIGHUSER, vma, vaddr);
+       if (page)
+               clear_user_highpage(page, vaddr);
+@@ -102,36 +85,6 @@
+ }
+ #endif
+-/**
+- * alloc_zeroed_user_highpage - Allocate a zeroed HIGHMEM page for a VMA
+- * @vma: The VMA the page is to be allocated for
+- * @vaddr: The virtual address the page will be inserted into
+- *
+- * This function will allocate a page for a VMA that the caller knows will
+- * not be able to move in the future using move_pages() or reclaim. If it
+- * is known that the page can move, use alloc_zeroed_user_highpage_movable
+- */
+-static inline struct page *
+-alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr)
+-{
+-      return __alloc_zeroed_user_highpage(0, vma, vaddr);
+-}
+-
+-/**
+- * alloc_zeroed_user_highpage_movable - Allocate a zeroed HIGHMEM page for a VMA that the caller knows can move
+- * @vma: The VMA the page is to be allocated for
+- * @vaddr: The virtual address the page will be inserted into
+- *
+- * This function will allocate a page for a VMA that the caller knows will
+- * be able to migrate in the future using move_pages() or reclaimed
+- */
+-static inline struct page *
+-alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma,
+-                                      unsigned long vaddr)
+-{
+-      return __alloc_zeroed_user_highpage(__GFP_MOVABLE, vma, vaddr);
+-}
+-
+ static inline void clear_highpage(struct page *page)
+ {
+       void *kaddr = kmap_atomic(page, KM_USER0);
+diff -Nurb linux-2.6.22-590/include/linux/hugetlb.h linux-2.6.22-570/include/linux/hugetlb.h
+--- linux-2.6.22-590/include/linux/hugetlb.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/hugetlb.h   2007-07-08 19:32:17.000000000 -0400
+@@ -15,7 +15,6 @@
+ }
+ int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
+-int hugetlb_treat_movable_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
+ int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
+ int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int);
+ void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
+@@ -30,8 +29,6 @@
+ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
+ extern unsigned long max_huge_pages;
+-extern unsigned long hugepages_treat_as_movable;
+-extern gfp_t htlb_alloc_mask;
+ extern const unsigned long hugetlb_zero, hugetlb_infinity;
+ extern int sysctl_hugetlb_shm_group;
+diff -Nurb linux-2.6.22-590/include/linux/idr.h linux-2.6.22-570/include/linux/idr.h
+--- linux-2.6.22-590/include/linux/idr.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/idr.h       2007-07-08 19:32:17.000000000 -0400
+@@ -83,33 +83,4 @@
+ void idr_destroy(struct idr *idp);
+ void idr_init(struct idr *idp);
+-
+-/*
+- * IDA - IDR based id allocator, use when translation from id to
+- * pointer isn't necessary.
+- */
+-#define IDA_CHUNK_SIZE                128     /* 128 bytes per chunk */
+-#define IDA_BITMAP_LONGS      (128 / sizeof(long) - 1)
+-#define IDA_BITMAP_BITS               (IDA_BITMAP_LONGS * sizeof(long) * 8)
+-
+-struct ida_bitmap {
+-      long                    nr_busy;
+-      unsigned long           bitmap[IDA_BITMAP_LONGS];
+-};
+-
+-struct ida {
+-      struct idr              idr;
+-      struct ida_bitmap       *free_bitmap;
+-};
+-
+-#define IDA_INIT(name)                { .idr = IDR_INIT(name), .free_bitmap = NULL, }
+-#define DEFINE_IDA(name)      struct ida name = IDA_INIT(name)
+-
+-int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
+-int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
+-int ida_get_new(struct ida *ida, int *p_id);
+-void ida_remove(struct ida *ida, int id);
+-void ida_destroy(struct ida *ida);
+-void ida_init(struct ida *ida);
+-
+ #endif /* __IDR_H__ */
+diff -Nurb linux-2.6.22-590/include/linux/if_bridge.h linux-2.6.22-570/include/linux/if_bridge.h
+--- linux-2.6.22-590/include/linux/if_bridge.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/if_bridge.h 2007-07-08 19:32:17.000000000 -0400
+@@ -104,7 +104,7 @@
+ #include <linux/netdevice.h>
+-extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
++extern void brioctl_set(int (*ioctl_hook)(unsigned int, void __user *));
+ extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
+                                              struct sk_buff *skb);
+ extern int (*br_should_route_hook)(struct sk_buff **pskb);
+diff -Nurb linux-2.6.22-590/include/linux/if_link.h linux-2.6.22-570/include/linux/if_link.h
+--- linux-2.6.22-590/include/linux/if_link.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/if_link.h   2007-07-08 19:32:17.000000000 -0400
+@@ -76,8 +76,6 @@
+ #define IFLA_WEIGHT IFLA_WEIGHT
+       IFLA_OPERSTATE,
+       IFLA_LINKMODE,
+-      IFLA_LINKINFO,
+-#define IFLA_LINKINFO IFLA_LINKINFO
+       __IFLA_MAX
+ };
+@@ -142,49 +140,4 @@
+       __u32   retrans_time;
+ };
+-enum
+-{
+-      IFLA_INFO_UNSPEC,
+-      IFLA_INFO_KIND,
+-      IFLA_INFO_DATA,
+-      IFLA_INFO_XSTATS,
+-      __IFLA_INFO_MAX,
+-};
+-
+-#define IFLA_INFO_MAX (__IFLA_INFO_MAX - 1)
+-
+-/* VLAN section */
+-
+-enum
+-{
+-      IFLA_VLAN_UNSPEC,
+-      IFLA_VLAN_ID,
+-      IFLA_VLAN_FLAGS,
+-      IFLA_VLAN_EGRESS_QOS,
+-      IFLA_VLAN_INGRESS_QOS,
+-      __IFLA_VLAN_MAX,
+-};
+-
+-#define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1)
+-
+-struct ifla_vlan_flags {
+-      __u32   flags;
+-      __u32   mask;
+-};
+-
+-enum
+-{
+-      IFLA_VLAN_QOS_UNSPEC,
+-      IFLA_VLAN_QOS_MAPPING,
+-      __IFLA_VLAN_QOS_MAX
+-};
+-
+-#define IFLA_VLAN_QOS_MAX     (__IFLA_VLAN_QOS_MAX - 1)
+-
+-struct ifla_vlan_qos_mapping
+-{
+-      __u32 from;
+-      __u32 to;
+-};
+-
+ #endif /* _LINUX_IF_LINK_H */
+diff -Nurb linux-2.6.22-590/include/linux/if_pppox.h linux-2.6.22-570/include/linux/if_pppox.h
+--- linux-2.6.22-590/include/linux/if_pppox.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/if_pppox.h  2007-07-08 19:32:17.000000000 -0400
+@@ -160,7 +160,7 @@
+ struct module;
+ struct pppox_proto {
+-      int             (*create)(struct net *net, struct socket *sock);
++      int             (*create)(struct socket *sock);
+       int             (*ioctl)(struct socket *sock, unsigned int cmd,
+                                unsigned long arg);
+       struct module   *owner;
+diff -Nurb linux-2.6.22-590/include/linux/if_tun.h linux-2.6.22-570/include/linux/if_tun.h
+--- linux-2.6.22-590/include/linux/if_tun.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/if_tun.h    2007-07-08 19:32:17.000000000 -0400
+@@ -36,7 +36,6 @@
+       unsigned long           flags;
+       int                     attached;
+       uid_t                   owner;
+-      gid_t                   group;
+       wait_queue_head_t       read_wait;
+       struct sk_buff_head     readq;
+@@ -79,7 +78,6 @@
+ #define TUNSETPERSIST _IOW('T', 203, int) 
+ #define TUNSETOWNER   _IOW('T', 204, int)
+ #define TUNSETLINK    _IOW('T', 205, int)
+-#define TUNSETGROUP   _IOW('T', 206, int)
+ /* TUNSETIFF ifr flags */
+ #define IFF_TUN               0x0001
+diff -Nurb linux-2.6.22-590/include/linux/if_vlan.h linux-2.6.22-570/include/linux/if_vlan.h
+--- linux-2.6.22-590/include/linux/if_vlan.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/if_vlan.h   2007-07-08 19:32:17.000000000 -0400
+@@ -62,7 +62,7 @@
+ #define VLAN_VID_MASK 0xfff
+ /* found in socket.c */
+-extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
++extern void vlan_ioctl_set(int (*hook)(void __user *));
+ #define VLAN_NAME "vlan"
+@@ -99,7 +99,7 @@
+ }
+ struct vlan_priority_tci_mapping {
+-      u32 priority;
++      unsigned long priority;
+       unsigned short vlan_qos; /* This should be shifted when first set, so we only do it
+                                 * at provisioning time.
+                                 * ((skb->priority << 13) & 0xE000)
+@@ -112,10 +112,7 @@
+       /** This will be the mapping that correlates skb->priority to
+        * 3 bits of VLAN QOS tags...
+        */
+-      unsigned int nr_ingress_mappings;
+-      u32 ingress_priority_map[8];
+-
+-      unsigned int nr_egress_mappings;
++      unsigned long ingress_priority_map[8];
+       struct vlan_priority_tci_mapping *egress_priority_map[16]; /* hash table */
+       unsigned short vlan_id;        /*  The VLAN Identifier for this interface. */
+@@ -398,10 +395,6 @@
+       GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
+ };
+-enum vlan_flags {
+-      VLAN_FLAG_REORDER_HDR   = 0x1,
+-};
+-
+ enum vlan_name_types {
+       VLAN_NAME_TYPE_PLUS_VID, /* Name will look like:  vlan0005 */
+       VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like:  eth1.0005 */
+diff -Nurb linux-2.6.22-590/include/linux/inetdevice.h linux-2.6.22-570/include/linux/inetdevice.h
+--- linux-2.6.22-590/include/linux/inetdevice.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/inetdevice.h        2007-07-08 19:32:17.000000000 -0400
+@@ -17,6 +17,8 @@
+       DECLARE_BITMAP(state, __NET_IPV4_CONF_MAX - 1);
+ };
++extern struct ipv4_devconf ipv4_devconf;
 +
-+late_initcall(kgdb_late_entry);
+ struct in_device
+ {
+       struct net_device       *dev;
+@@ -42,7 +44,7 @@
+ };
+ #define IPV4_DEVCONF(cnf, attr) ((cnf).data[NET_IPV4_CONF_ ## attr - 1])
+-#define IPV4_DEVCONF_ALL(net, attr) IPV4_DEVCONF(*((net)->ipv4_devconf), attr)
++#define IPV4_DEVCONF_ALL(attr) IPV4_DEVCONF(ipv4_devconf, attr)
+ static inline int ipv4_devconf_get(struct in_device *in_dev, int index)
+ {
+@@ -69,14 +71,14 @@
+       ipv4_devconf_set((in_dev), NET_IPV4_CONF_ ## attr, (val))
+ #define IN_DEV_ANDCONF(in_dev, attr) \
+-      (IPV4_DEVCONF_ALL((in_dev)->dev->nd_net, attr) && IN_DEV_CONF_GET((in_dev), attr))
++      (IPV4_DEVCONF_ALL(attr) && IN_DEV_CONF_GET((in_dev), attr))
+ #define IN_DEV_ORCONF(in_dev, attr) \
+-      (IPV4_DEVCONF_ALL((in_dev)->dev->nd_net, attr) || IN_DEV_CONF_GET((in_dev), attr))
++      (IPV4_DEVCONF_ALL(attr) || IN_DEV_CONF_GET((in_dev), attr))
+ #define IN_DEV_MAXCONF(in_dev, attr) \
+-      (max(IPV4_DEVCONF_ALL((in_dev)->dev->nd_net, attr), IN_DEV_CONF_GET((in_dev), attr)))
++      (max(IPV4_DEVCONF_ALL(attr), IN_DEV_CONF_GET((in_dev), attr)))
+ #define IN_DEV_FORWARD(in_dev)                IN_DEV_CONF_GET((in_dev), FORWARDING)
+-#define IN_DEV_MFORWARD(in_dev)               (IPV4_DEVCONF_ALL((in_dev)->dev->nd_net, MC_FORWARDING) && \
++#define IN_DEV_MFORWARD(in_dev)               (IPV4_DEVCONF_ALL(MC_FORWARDING) && \
+                                        IPV4_DEVCONF((in_dev)->cnf, \
+                                                     MC_FORWARDING))
+ #define IN_DEV_RPFILTER(in_dev)               IN_DEV_ANDCONF((in_dev), RP_FILTER)
+@@ -125,15 +127,15 @@
+ extern int register_inetaddr_notifier(struct notifier_block *nb);
+ extern int unregister_inetaddr_notifier(struct notifier_block *nb);
+-extern struct net_device      *ip_dev_find(struct net *net, __be32 addr);
++extern struct net_device      *ip_dev_find(__be32 addr);
+ extern int            inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
+-extern int            devinet_ioctl(struct net *net, unsigned int cmd, void __user *);
++extern int            devinet_ioctl(unsigned int cmd, void __user *);
+ extern void           devinet_init(void);
+-extern struct in_device       *inetdev_by_index(struct net *, int);
++extern struct in_device       *inetdev_by_index(int);
+ extern __be32         inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
+-extern __be32         inet_confirm_addr(struct net *net, const struct net_device *dev, __be32 dst, __be32 local, int scope);
++extern __be32         inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope);
+ extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix, __be32 mask);
+-extern void           inet_forward_change(struct net *net);
++extern void           inet_forward_change(void);
+ static __inline__ int inet_ifa_match(__be32 addr, struct in_ifaddr *ifa)
+ {
+diff -Nurb linux-2.6.22-590/include/linux/init_task.h linux-2.6.22-570/include/linux/init_task.h
+--- linux-2.6.22-590/include/linux/init_task.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/init_task.h 2008-01-23 19:16:05.000000000 -0500
+@@ -8,8 +8,6 @@
+ #include <linux/lockdep.h>
+ #include <linux/ipc.h>
+ #include <linux/pid_namespace.h>
+-#include <linux/user_namespace.h>
+-#include <net/net_namespace.h>
+ #define INIT_FDTABLE \
+ {                                                     \
+@@ -79,9 +77,7 @@
+       .nslock         = __SPIN_LOCK_UNLOCKED(nsproxy.nslock),         \
+       .uts_ns         = &init_uts_ns,                                 \
+       .mnt_ns         = NULL,                                         \
+-      .net_ns         = &init_net,                                    \
+       INIT_IPC_NS(ipc_ns)                                             \
+-      .user_ns        = &init_user_ns,                                \
+ }
+ #define INIT_SIGHAND(sighand) {                                               \
+diff -Nurb linux-2.6.22-590/include/linux/io.h linux-2.6.22-570/include/linux/io.h
+--- linux-2.6.22-590/include/linux/io.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/io.h        2007-07-08 19:32:17.000000000 -0400
+@@ -63,7 +63,32 @@
+ void __iomem * devm_ioremap_nocache(struct device *dev, unsigned long offset,
+                                   unsigned long size);
+ void devm_iounmap(struct device *dev, void __iomem *addr);
+-int check_signature(const volatile void __iomem *io_addr,
+-                      const unsigned char *signature, int length);
 +
-+/*
-+ * This function will generate a breakpoint exception.  It is used at the
-+ * beginning of a program to sync up with a debugger and can be used
-+ * otherwise as a quick means to stop program execution and "break" into
-+ * the debugger.
++/**
++ *    check_signature         -       find BIOS signatures
++ *    @io_addr: mmio address to check
++ *    @signature:  signature block
++ *    @length: length of signature
++ *
++ *    Perform a signature comparison with the mmio address io_addr. This
++ *    address should have been obtained by ioremap.
++ *    Returns 1 on a match.
 + */
-+void breakpoint(void)
-+{
-+      atomic_set(&kgdb_setting_breakpoint, 1);
-+      wmb();
-+      BREAKPOINT();
-+      wmb();
-+      atomic_set(&kgdb_setting_breakpoint, 0);
-+}
-+
-+EXPORT_SYMBOL(breakpoint);
-+
-+#ifdef CONFIG_MAGIC_SYSRQ
-+static void sysrq_handle_gdb(int key, struct tty_struct *tty)
-+{
-+      printk("Entering GDB stub\n");
-+      breakpoint();
-+}
-+static struct sysrq_key_op sysrq_gdb_op = {
-+      .handler = sysrq_handle_gdb,
-+      .help_msg = "Gdb",
-+      .action_msg = "GDB",
-+};
-+
-+static int gdb_register_sysrq(void)
-+{
-+      printk("Registering GDB sysrq handler\n");
-+      register_sysrq_key('g', &sysrq_gdb_op);
-+      return 0;
-+}
-+
-+module_init(gdb_register_sysrq);
-+#endif
 +
-+static int kgdb_notify_reboot(struct notifier_block *this,
-+                            unsigned long code, void *x)
++static inline int check_signature(const volatile void __iomem *io_addr,
++      const unsigned char *signature, int length)
 +{
-+
-+      unsigned long flags;
-+
-+      /* If we're debugging, or KGDB has not connected, don't try
-+       * and print. */
-+      if (!kgdb_connected || atomic_read(&debugger_active) != 0)
-+              return 0;
-+      if ((code == SYS_RESTART) || (code == SYS_HALT) || (code == SYS_POWER_OFF)){
-+              local_irq_save(flags);
-+              put_packet("X00");
-+              local_irq_restore(flags);
-+      }
-+      return NOTIFY_DONE;
++      int retval = 0;
++      do {
++              if (readb(io_addr) != *signature)
++                      goto out;
++              io_addr++;
++              signature++;
++              length--;
++      } while (length);
++      retval = 1;
++out:
++      return retval;
 +}
+ #endif /* _LINUX_IO_H */
+diff -Nurb linux-2.6.22-590/include/linux/ip_mp_alg.h linux-2.6.22-570/include/linux/ip_mp_alg.h
+--- linux-2.6.22-590/include/linux/ip_mp_alg.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/include/linux/ip_mp_alg.h 2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,22 @@
++/* ip_mp_alg.h: IPV4 multipath algorithm support, user-visible values.
++ *
++ * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
++ * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
++ */
 +
-+#ifdef CONFIG_KGDB_CONSOLE
-+void kgdb_console_write(struct console *co, const char *s, unsigned count)
-+{
-+      unsigned long flags;
-+
-+      /* If we're debugging, or KGDB has not connected, don't try
-+       * and print. */
-+      if (!kgdb_connected || atomic_read(&debugger_active) != 0)
-+              return;
-+
-+      local_irq_save(flags);
-+      kgdb_msg_write(s, count);
-+      local_irq_restore(flags);
-+}
++#ifndef _LINUX_IP_MP_ALG_H
++#define _LINUX_IP_MP_ALG_H
 +
-+struct console kgdbcons = {
-+      .name = "kgdb",
-+      .write = kgdb_console_write,
-+      .flags = CON_PRINTBUFFER | CON_ENABLED,
++enum ip_mp_alg {
++      IP_MP_ALG_NONE,
++      IP_MP_ALG_RR,
++      IP_MP_ALG_DRR,
++      IP_MP_ALG_RANDOM,
++      IP_MP_ALG_WRANDOM,
++      __IP_MP_ALG_MAX
 +};
-+static int __init kgdb_console_init(void)
-+{
-+      register_console(&kgdbcons);
-+      return 0;
-+}
-+
-+console_initcall(kgdb_console_init);
-+#endif
-+
-+static int __init opt_kgdb_enter(char *str)
-+{
-+      /* We've already done this by an explicit breakpoint() call. */
-+      if (kgdb_initialized)
-+              return 0;
 +
-+      kgdb_early_entry();
-+      if (kgdb_initialized == 1)
-+              printk(KERN_CRIT "Waiting for connection from remote "
-+                     "gdb...\n");
-+      else {
-+              printk(KERN_CRIT "KGDB cannot initialize I/O yet.\n");
-+              return 0;
-+      }
++#define IP_MP_ALG_MAX (__IP_MP_ALG_MAX - 1)
 +
-+      breakpoint();
++#endif /* _LINUX_IP_MP_ALG_H */
 +
-+      return 0;
-+}
+diff -Nurb linux-2.6.22-590/include/linux/ipc.h linux-2.6.22-570/include/linux/ipc.h
+--- linux-2.6.22-590/include/linux/ipc.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/ipc.h       2008-01-23 19:16:05.000000000 -0500
+@@ -93,7 +93,6 @@
+ #ifdef CONFIG_SYSVIPC
+ #define INIT_IPC_NS(ns)               .ns             = &init_ipc_ns,
+-extern void free_ipc_ns(struct kref *kref);
+ extern struct ipc_namespace *copy_ipcs(unsigned long flags,
+                                               struct ipc_namespace *ns);
+ #else
+@@ -105,9 +104,13 @@
+ }
+ #endif
++#ifdef CONFIG_IPC_NS
++extern void free_ipc_ns(struct kref *kref);
++#endif
 +
-+early_param("kgdbwait", opt_kgdb_enter);
-diff -Nurb linux-2.6.22-570/kernel/kmod.c linux-2.6.22-590/kernel/kmod.c
---- linux-2.6.22-570/kernel/kmod.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/kernel/kmod.c     2008-01-02 13:56:37.000000000 -0500
-@@ -119,9 +119,10 @@
-       char **argv;
-       char **envp;
-       struct key *ring;
--      int wait;
-+      enum umh_wait wait;
-       int retval;
-       struct file *stdin;
-+      void (*cleanup)(char **argv, char **envp);
- };
+ static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
+ {
+-#ifdef CONFIG_SYSVIPC
++#ifdef CONFIG_IPC_NS
+       if (ns)
+               kref_get(&ns->kref);
+ #endif
+@@ -116,7 +119,7 @@
  
- /*
-@@ -180,6 +181,14 @@
-       do_exit(0);
+ static inline void put_ipc_ns(struct ipc_namespace *ns)
+ {
+-#ifdef CONFIG_SYSVIPC
++#ifdef CONFIG_IPC_NS
+       kref_put(&ns->kref, free_ipc_ns);
+ #endif
  }
+@@ -124,3 +127,5 @@
+ #endif /* __KERNEL__ */
  
-+void call_usermodehelper_freeinfo(struct subprocess_info *info)
-+{
-+      if (info->cleanup)
-+              (*info->cleanup)(info->argv, info->envp);
-+      kfree(info);
-+}
-+EXPORT_SYMBOL(call_usermodehelper_freeinfo);
+ #endif /* _LINUX_IPC_H */
 +
- /* Keventd can't block, but this (a child) can. */
- static int wait_for_helper(void *data)
++
+diff -Nurb linux-2.6.22-590/include/linux/ipv6.h linux-2.6.22-570/include/linux/ipv6.h
+--- linux-2.6.22-590/include/linux/ipv6.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/ipv6.h      2007-07-08 19:32:17.000000000 -0400
+@@ -247,7 +247,7 @@
+       __u16                   lastopt;
+       __u32                   nhoff;
+       __u16                   flags;
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+       __u16                   dsthao;
+ #endif
+diff -Nurb linux-2.6.22-590/include/linux/kgdb.h linux-2.6.22-570/include/linux/kgdb.h
+--- linux-2.6.22-590/include/linux/kgdb.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/kgdb.h      1969-12-31 19:00:00.000000000 -0500
+@@ -1,291 +0,0 @@
+-/*
+- * include/linux/kgdb.h
+- *
+- * This provides the hooks and functions that KGDB needs to share between
+- * the core, I/O and arch-specific portions.
+- *
+- * Author: Amit Kale <amitkale@linsyssoft.com> and
+- *         Tom Rini <trini@kernel.crashing.org>
+- *
+- * 2001-2004 (c) Amit S. Kale and 2003-2005 (c) MontaVista Software, Inc.
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program is licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
+-#ifdef __KERNEL__
+-#ifndef _KGDB_H_
+-#define _KGDB_H_
+-
+-#include <asm/atomic.h>
+-
+-#ifdef CONFIG_KGDB
+-#include <asm/kgdb.h>
+-#include <linux/serial_8250.h>
+-#include <linux/linkage.h>
+-#include <linux/init.h>
+-
+-#ifndef CHECK_EXCEPTION_STACK
+-#define CHECK_EXCEPTION_STACK()       1
+-#endif
+-
+-struct tasklet_struct;
+-struct pt_regs;
+-struct task_struct;
+-struct uart_port;
+-
+-#ifdef CONFIG_KGDB_CONSOLE
+-extern struct console kgdbcons;
+-#endif
+-
+-/* To enter the debugger explicitly. */
+-extern void breakpoint(void);
+-extern int kgdb_connected;
+-extern int kgdb_may_fault;
+-extern struct tasklet_struct kgdb_tasklet_breakpoint;
+-
+-extern atomic_t kgdb_setting_breakpoint;
+-extern atomic_t cpu_doing_single_step;
+-extern atomic_t kgdb_sync_softlockup[NR_CPUS];
+-
+-extern struct task_struct *kgdb_usethread, *kgdb_contthread;
+-
+-enum kgdb_bptype {
+-      bp_breakpoint = '0',
+-      bp_hardware_breakpoint,
+-      bp_write_watchpoint,
+-      bp_read_watchpoint,
+-      bp_access_watchpoint
+-};
+-
+-enum kgdb_bpstate {
+-      bp_none = 0,
+-      bp_removed,
+-      bp_set,
+-      bp_active
+-};
+-
+-struct kgdb_bkpt {
+-      unsigned long bpt_addr;
+-      unsigned char saved_instr[BREAK_INSTR_SIZE];
+-      enum kgdb_bptype type;
+-      enum kgdb_bpstate state;
+-};
+-
+-/* The maximum number of KGDB I/O modules that can be loaded */
+-#define MAX_KGDB_IO_HANDLERS 3
+-
+-#ifndef MAX_BREAKPOINTS
+-#define MAX_BREAKPOINTS               1000
+-#endif
+-
+-#define KGDB_HW_BREAKPOINT    1
+-
+-/* Required functions. */
+-/**
+- *    kgdb_arch_init - Perform any architecture specific initalization.
+- *
+- *    This function will handle the initalization of any architecture
+- *    specific hooks.
+- */
+-extern int kgdb_arch_init(void);
+-
+-/**
+- *    regs_to_gdb_regs - Convert ptrace regs to GDB regs
+- *    @gdb_regs: A pointer to hold the registers in the order GDB wants.
+- *    @regs: The &struct pt_regs of the current process.
+- *
+- *    Convert the pt_regs in @regs into the format for registers that
+- *    GDB expects, stored in @gdb_regs.
+- */
+-extern void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs);
+-
+-/**
+- *    sleeping_regs_to_gdb_regs - Convert ptrace regs to GDB regs
+- *    @gdb_regs: A pointer to hold the registers in the order GDB wants.
+- *    @p: The &struct task_struct of the desired process.
+- *
+- *    Convert the register values of the sleeping process in @p to
+- *    the format that GDB expects.
+- *    This function is called when kgdb does not have access to the
+- *    &struct pt_regs and therefore it should fill the gdb registers
+- *    @gdb_regs with what has been saved in &struct thread_struct
+- *    thread field during switch_to.
+- */
+-extern void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
+-                                      struct task_struct *p);
+-
+-/**
+- *    gdb_regs_to_regs - Convert GDB regs to ptrace regs.
+- *    @gdb_regs: A pointer to hold the registers we've recieved from GDB.
+- *    @regs: A pointer to a &struct pt_regs to hold these values in.
+- *
+- *    Convert the GDB regs in @gdb_regs into the pt_regs, and store them
+- *    in @regs.
+- */
+-extern void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs);
+-
+-/**
+- *    kgdb_arch_handle_exception - Handle architecture specific GDB packets.
+- *    @vector: The error vector of the exception that happened.
+- *    @signo: The signal number of the exception that happened.
+- *    @err_code: The error code of the exception that happened.
+- *    @remcom_in_buffer: The buffer of the packet we have read.
+- *    @remcom_out_buffer: The buffer, of %BUFMAX to write a packet into.
+- *    @regs: The &struct pt_regs of the current process.
+- *
+- *    This function MUST handle the 'c' and 's' command packets,
+- *    as well packets to set / remove a hardware breakpoint, if used.
+- *    If there are additional packets which the hardware needs to handle,
+- *    they are handled here.  The code should return -1 if it wants to
+- *    process more packets, and a %0 or %1 if it wants to exit from the
+- *    kgdb hook.
+- */
+-extern int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+-                                    char *remcom_in_buffer,
+-                                    char *remcom_out_buffer,
+-                                    struct pt_regs *regs);
+-
+-/**
+- *    kgdb_roundup_cpus - Get other CPUs into a holding pattern
+- *    @flags: Current IRQ state
+- *
+- *    On SMP systems, we need to get the attention of the other CPUs
+- *    and get them be in a known state.  This should do what is needed
+- *    to get the other CPUs to call kgdb_wait(). Note that on some arches,
+- *    the NMI approach is not used for rounding up all the CPUs. For example,
+- *    in case of MIPS, smp_call_function() is used to roundup CPUs. In
+- *    this case, we have to make sure that interrupts are enabled before
+- *    calling smp_call_function(). The argument to this function is
+- *    the flags that will be used when restoring the interrupts. There is
+- *    local_irq_save() call before kgdb_roundup_cpus().
+- *
+- *    On non-SMP systems, this is not called.
+- */
+-extern void kgdb_roundup_cpus(unsigned long flags);
+-
+-#ifndef JMP_REGS_ALIGNMENT
+-#define JMP_REGS_ALIGNMENT
+-#endif
+-
+-extern unsigned long kgdb_fault_jmp_regs[];
+-
+-/**
+- *    kgdb_fault_setjmp - Store state in case we fault.
+- *    @curr_context: An array to store state into.
+- *
+- *    Certain functions may try and access memory, and in doing so may
+- *    cause a fault.  When this happens, we trap it, restore state to
+- *    this call, and let ourself know that something bad has happened.
+- */
+-extern asmlinkage int kgdb_fault_setjmp(unsigned long *curr_context);
+-
+-/**
+- *    kgdb_fault_longjmp - Restore state when we have faulted.
+- *    @curr_context: The previously stored state.
+- *
+- *    When something bad does happen, this function is called to
+- *    restore the known good state, and set the return value to 1, so
+- *    we know something bad happened.
+- */
+-extern asmlinkage void kgdb_fault_longjmp(unsigned long *curr_context);
+-
+-/* Optional functions. */
+-extern int kgdb_validate_break_address(unsigned long addr);
+-extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr);
+-extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle);
+-
+-/**
+- * struct kgdb_arch - Desribe architecture specific values.
+- * @gdb_bpt_instr: The instruction to trigger a breakpoint.
+- * @flags: Flags for the breakpoint, currently just %KGDB_HW_BREAKPOINT.
+- * @shadowth: A value of %1 indicates we shadow information on processes.
+- * @set_breakpoint: Allow an architecture to specify how to set a software
+- * breakpoint.
+- * @remove_breakpoint: Allow an architecture to specify how to remove a
+- * software breakpoint.
+- * @set_hw_breakpoint: Allow an architecture to specify how to set a hardware
+- * breakpoint.
+- * @remove_hw_breakpoint: Allow an architecture to specify how to remove a
+- * hardware breakpoint.
+- *
+- * The @shadowth flag is an option to shadow information not retrievable by
+- * gdb otherwise.  This is deprecated in favor of a binutils which supports
+- * CFI macros.
+- */
+-struct kgdb_arch {
+-      unsigned char gdb_bpt_instr[BREAK_INSTR_SIZE];
+-      unsigned long flags;
+-      unsigned shadowth;
+-      int (*set_breakpoint) (unsigned long, char *);
+-      int (*remove_breakpoint)(unsigned long, char *);
+-      int (*set_hw_breakpoint)(unsigned long, int, enum kgdb_bptype);
+-      int (*remove_hw_breakpoint)(unsigned long, int, enum kgdb_bptype);
+-      void (*remove_all_hw_break)(void);
+-      void (*correct_hw_break)(void);
+-};
+-
+-/* Thread reference */
+-typedef unsigned char threadref[8];
+-
+-/**
+- * struct kgdb_io - Desribe the interface for an I/O driver to talk with KGDB.
+- * @read_char: Pointer to a function that will return one char.
+- * @write_char: Pointer to a function that will write one char.
+- * @flush: Pointer to a function that will flush any pending writes.
+- * @init: Pointer to a function that will initialize the device.
+- * @late_init: Pointer to a function that will do any setup that has
+- * other dependencies.
+- * @pre_exception: Pointer to a function that will do any prep work for
+- * the I/O driver.
+- * @post_exception: Pointer to a function that will do any cleanup work
+- * for the I/O driver.
+- *
+- * The @init and @late_init function pointers allow for an I/O driver
+- * such as a serial driver to fully initialize the port with @init and
+- * be called very early, yet safely call request_irq() later in the boot
+- * sequence.
+- *
+- * @init is allowed to return a non-0 return value to indicate failure.
+- * If this is called early on, then KGDB will try again when it would call
+- * @late_init.  If it has failed later in boot as well, the user will be
+- * notified.
+- */
+-struct kgdb_io {
+-      int (*read_char) (void);
+-      void (*write_char) (u8);
+-      void (*flush) (void);
+-      int (*init) (void);
+-      void (*late_init) (void);
+-      void (*pre_exception) (void);
+-      void (*post_exception) (void);
+-};
+-
+-extern struct kgdb_io kgdb_io_ops;
+-extern struct kgdb_arch arch_kgdb_ops;
+-extern int kgdb_initialized;
+-
+-extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops);
+-extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops);
+-
+-extern void __init kgdb8250_add_port(int i, struct uart_port *serial_req);
+-extern void __init kgdb8250_add_platform_port(int i, struct plat_serial8250_port *serial_req);
+-
+-extern int kgdb_hex2long(char **ptr, long *long_val);
+-extern char *kgdb_mem2hex(char *mem, char *buf, int count);
+-extern char *kgdb_hex2mem(char *buf, char *mem, int count);
+-extern int kgdb_get_mem(char *addr, unsigned char *buf, int count);
+-extern int kgdb_set_mem(char *addr, unsigned char *buf, int count);
+-
+-int kgdb_isremovedbreak(unsigned long addr);
+-
+-extern int kgdb_handle_exception(int ex_vector, int signo, int err_code,
+-                              struct pt_regs *regs);
+-extern void kgdb_nmihook(int cpu, void *regs);
+-extern int debugger_step;
+-extern atomic_t debugger_active;
+-#else
+-/* Stubs for when KGDB is not set. */
+-static const atomic_t debugger_active = ATOMIC_INIT(0);
+-#endif                                /* CONFIG_KGDB */
+-#endif                                /* _KGDB_H_ */
+-#endif                                /* __KERNEL__ */
+diff -Nurb linux-2.6.22-590/include/linux/kmod.h linux-2.6.22-570/include/linux/kmod.h
+--- linux-2.6.22-590/include/linux/kmod.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/kmod.h      2007-07-08 19:32:17.000000000 -0400
+@@ -36,57 +36,13 @@
+ #define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
+ struct key;
+-struct file;
+-struct subprocess_info;
+-
+-/* Allocate a subprocess_info structure */
+-struct subprocess_info *call_usermodehelper_setup(char *path,
+-                                                char **argv, char **envp);
+-
+-/* Set various pieces of state into the subprocess_info structure */
+-void call_usermodehelper_setkeys(struct subprocess_info *info,
+-                               struct key *session_keyring);
+-int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info,
+-                                struct file **filp);
+-void call_usermodehelper_setcleanup(struct subprocess_info *info,
+-                                  void (*cleanup)(char **argv, char **envp));
+-
+-enum umh_wait {
+-      UMH_NO_WAIT = -1,       /* don't wait at all */
+-      UMH_WAIT_EXEC = 0,      /* wait for the exec, but not the process */
+-      UMH_WAIT_PROC = 1,      /* wait for the process to complete */
+-};
+-
+-/* Actually execute the sub-process */
+-int call_usermodehelper_exec(struct subprocess_info *info, enum umh_wait wait);
+-
+-/* Free the subprocess_info. This is only needed if you're not going
+-   to call call_usermodehelper_exec */
+-void call_usermodehelper_freeinfo(struct subprocess_info *info);
++extern int call_usermodehelper_keys(char *path, char *argv[], char *envp[],
++                                  struct key *session_keyring, int wait);
+ static inline int
+-call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)
++call_usermodehelper(char *path, char **argv, char **envp, int wait)
  {
-@@ -216,8 +225,8 @@
-                       sub_info->retval = ret;
-       }
+-      struct subprocess_info *info;
+-
+-      info = call_usermodehelper_setup(path, argv, envp);
+-      if (info == NULL)
+-              return -ENOMEM;
+-      return call_usermodehelper_exec(info, wait);
+-}
+-
+-static inline int
+-call_usermodehelper_keys(char *path, char **argv, char **envp,
+-                       struct key *session_keyring, enum umh_wait wait)
+-{
+-      struct subprocess_info *info;
+-
+-      info = call_usermodehelper_setup(path, argv, envp);
+-      if (info == NULL)
+-              return -ENOMEM;
+-
+-      call_usermodehelper_setkeys(info, session_keyring);
+-      return call_usermodehelper_exec(info, wait);
++      return call_usermodehelper_keys(path, argv, envp, NULL, wait);
+ }
  
--      if (sub_info->wait < 0)
--              kfree(sub_info);
-+      if (sub_info->wait == UMH_NO_WAIT)
-+              call_usermodehelper_freeinfo(sub_info);
-       else
-               complete(sub_info->complete);
-       return 0;
-@@ -229,101 +238,102 @@
-       struct subprocess_info *sub_info =
-               container_of(work, struct subprocess_info, work);
-       pid_t pid;
--      int wait = sub_info->wait;
-+      enum umh_wait wait = sub_info->wait;
+ extern void usermodehelper_init(void);
+diff -Nurb linux-2.6.22-590/include/linux/kobject.h linux-2.6.22-570/include/linux/kobject.h
+--- linux-2.6.22-590/include/linux/kobject.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/kobject.h   2007-07-08 19:32:17.000000000 -0400
+@@ -55,7 +55,7 @@
+       struct kobject          * parent;
+       struct kset             * kset;
+       struct kobj_type        * ktype;
+-      struct sysfs_dirent     * sd;
++      struct dentry           * dentry;
+       wait_queue_head_t       poll;
+ };
  
-       /* CLONE_VFORK: wait until the usermode helper has execve'd
-        * successfully We need the data structures to stay around
-        * until that is done.  */
--      if (wait)
-+      if (wait == UMH_WAIT_PROC)
-               pid = kernel_thread(wait_for_helper, sub_info,
-                                   CLONE_FS | CLONE_FILES | SIGCHLD);
-       else
-               pid = kernel_thread(____call_usermodehelper, sub_info,
-                                   CLONE_VFORK | SIGCHLD);
+@@ -71,9 +71,13 @@
+ extern void kobject_cleanup(struct kobject *);
  
--      if (wait < 0)
--              return;
+ extern int __must_check kobject_add(struct kobject *);
++extern int __must_check kobject_shadow_add(struct kobject *, struct dentry *);
+ extern void kobject_del(struct kobject *);
+ extern int __must_check kobject_rename(struct kobject *, const char *new_name);
++extern int __must_check kobject_shadow_rename(struct kobject *kobj,
++                                              struct dentry *new_parent,
++                                              const char *new_name);
+ extern int __must_check kobject_move(struct kobject *, struct kobject *);
+ extern int __must_check kobject_register(struct kobject *);
+diff -Nurb linux-2.6.22-590/include/linux/ktime.h linux-2.6.22-570/include/linux/ktime.h
+--- linux-2.6.22-590/include/linux/ktime.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/ktime.h     2007-07-08 19:32:17.000000000 -0400
+@@ -279,16 +279,6 @@
+       return (s64) tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
+ }
+-static inline s64 ktime_us_delta(const ktime_t later, const ktime_t earlier)
+-{
+-       return ktime_to_us(ktime_sub(later, earlier));
+-}
 -
--      if (pid < 0) {
-+      switch(wait) {
-+      case UMH_NO_WAIT:
-+              break;
+-static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec)
+-{
+-      return ktime_add_ns(kt, usec * 1000);
+-}
+-
+ /*
+  * The resolution of the clocks. The resolution value is returned in
+  * the clock_getres() system call to give application programmers an
+diff -Nurb linux-2.6.22-590/include/linux/magic.h linux-2.6.22-570/include/linux/magic.h
+--- linux-2.6.22-590/include/linux/magic.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/magic.h     2008-01-23 19:16:05.000000000 -0500
+@@ -36,12 +36,8 @@
+ #define REISERFS_SUPER_MAGIC_STRING   "ReIsErFs"
+ #define REISER2FS_SUPER_MAGIC_STRING  "ReIsEr2Fs"
+ #define REISER2FS_JR_SUPER_MAGIC_STRING       "ReIsEr3Fs"
+-#define REVOKEFS_MAGIC                0x5245564B      /* REVK */
+-
+-#define UNIONFS_SUPER_MAGIC 0xf15f083d
+ #define SMB_SUPER_MAGIC               0x517B
+ #define USBDEVICE_SUPER_MAGIC 0x9fa2
+-#define CONTAINER_SUPER_MAGIC 0x27e0eb
+ #endif /* __LINUX_MAGIC_H__ */
+diff -Nurb linux-2.6.22-590/include/linux/mempolicy.h linux-2.6.22-570/include/linux/mempolicy.h
+--- linux-2.6.22-590/include/linux/mempolicy.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/mempolicy.h 2007-07-08 19:32:17.000000000 -0400
+@@ -148,10 +148,18 @@
+                                       const nodemask_t *new);
+ extern void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new);
+ extern void mpol_fix_fork_child_flag(struct task_struct *p);
++#define set_cpuset_being_rebound(x) (cpuset_being_rebound = (x))
 +
-+      case UMH_WAIT_PROC:
-+              if (pid > 0)
-+                      break;
-               sub_info->retval = pid;
-+              /* FALLTHROUGH */
++#ifdef CONFIG_CPUSETS
++#define current_cpuset_is_being_rebound() \
++                              (cpuset_being_rebound == current->cpuset)
++#else
++#define current_cpuset_is_being_rebound() 0
++#endif
+ extern struct mempolicy default_policy;
+ extern struct zonelist *huge_zonelist(struct vm_area_struct *vma,
+-              unsigned long addr, gfp_t gfp_flags);
++              unsigned long addr);
+ extern unsigned slab_node(struct mempolicy *policy);
+ extern enum zone_type policy_zone;
+@@ -165,6 +173,8 @@
+ int do_migrate_pages(struct mm_struct *mm,
+       const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags);
++extern void *cpuset_being_rebound;    /* Trigger mpol_copy vma rebind */
 +
-+      case UMH_WAIT_EXEC:
-               complete(sub_info->complete);
--      } else if (!wait)
--              complete(sub_info->complete);
-+      }
+ #else
+ struct mempolicy {};
+@@ -243,10 +253,12 @@
+ {
  }
  
- /**
-- * call_usermodehelper_keys - start a usermode application
-- * @path: pathname for the application
-- * @argv: null-terminated argument list
-- * @envp: null-terminated environment list
-- * @session_keyring: session keyring for process (NULL for an empty keyring)
-- * @wait: wait for the application to finish and return status.
-- *        when -1 don't wait at all, but you get no useful error back when
-- *        the program couldn't be exec'ed. This makes it safe to call
-- *        from interrupt context.
-+ * call_usermodehelper_setup - prepare to call a usermode helper
-+ * @path - path to usermode executable
-+ * @argv - arg vector for process
-+ * @envp - environment for process
-  *
-- * Runs a user-space application.  The application is started
-- * asynchronously if wait is not set, and runs as a child of keventd.
-- * (ie. it runs with full root capabilities).
-- *
-- * Must be called from process context.  Returns a negative error code
-- * if program was not execed successfully, or 0.
-+ * Returns either NULL on allocation failure, or a subprocess_info
-+ * structure.  This should be passed to call_usermodehelper_exec to
-+ * exec the process and free the structure.
++#define set_cpuset_being_rebound(x) do {} while (0)
++
+ static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma,
+-              unsigned long addr, gfp_t gfp_flags)
++              unsigned long addr)
+ {
+-      return NODE_DATA(0)->node_zonelists + gfp_zone(gfp_flags);
++      return NODE_DATA(0)->node_zonelists + gfp_zone(GFP_HIGHUSER);
+ }
+ static inline int do_migrate_pages(struct mm_struct *mm,
+diff -Nurb linux-2.6.22-590/include/linux/mm.h linux-2.6.22-570/include/linux/mm.h
+--- linux-2.6.22-590/include/linux/mm.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/mm.h        2007-07-08 19:32:17.000000000 -0400
+@@ -42,8 +42,6 @@
+ #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
+-#define VM_REVOKED     0x20000000      /* Mapping has been revoked */
+-
+ /*
+  * Linux kernel virtual memory manager primitives.
+  * The idea being to have a "virtual" mm in the same way
+@@ -172,13 +170,6 @@
+ #define VM_INSERTPAGE 0x02000000      /* The vma has had "vm_insert_page()" done on it */
+ #define VM_ALWAYSDUMP 0x04000000      /* Always include in core dumps */
+-#define VM_CAN_INVALIDATE 0x08000000  /* The mapping may be invalidated,
+-                                       * eg. truncate or invalidate_inode_*.
+-                                       * In this case, do_no_page must
+-                                       * return with the page locked.
+-                                       */
+-#define VM_CAN_NONLINEAR 0x10000000   /* Has ->fault & does nonlinear pages */
+-
+ #ifndef VM_STACK_DEFAULT_FLAGS                /* arch can override this */
+ #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
+ #endif
+@@ -201,25 +192,6 @@
+  */
+ extern pgprot_t protection_map[16];
+-#define FAULT_FLAG_WRITE      0x01
+-#define FAULT_FLAG_NONLINEAR  0x02
+-
+-/*
+- * fault_data is filled in the the pagefault handler and passed to the
+- * vma's ->fault function. That function is responsible for filling in
+- * 'type', which is the type of fault if a page is returned, or the type
+- * of error if NULL is returned.
+- *
+- * pgoff should be used in favour of address, if possible. If pgoff is
+- * used, one may set VM_CAN_NONLINEAR in the vma->vm_flags to get
+- * nonlinear mapping support.
+- */
+-struct fault_data {
+-      unsigned long address;
+-      pgoff_t pgoff;
+-      unsigned int flags;
+-      int type;
+-};
+ /*
+  * These are the virtual MM functions - opening of an area, closing and
+@@ -229,15 +201,9 @@
+ struct vm_operations_struct {
+       void (*open)(struct vm_area_struct * area);
+       void (*close)(struct vm_area_struct * area);
+-      struct page *(*fault)(struct vm_area_struct *vma,
+-                      struct fault_data *fdata);
+-      struct page *(*nopage)(struct vm_area_struct *area,
+-                      unsigned long address, int *type);
+-      unsigned long (*nopfn)(struct vm_area_struct *area,
+-                      unsigned long address);
+-      int (*populate)(struct vm_area_struct *area, unsigned long address,
+-                      unsigned long len, pgprot_t prot, unsigned long pgoff,
+-                      int nonblock);
++      struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int *type);
++      unsigned long (*nopfn)(struct vm_area_struct * area, unsigned long address);
++      int (*populate)(struct vm_area_struct * area, unsigned long address, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock);
+       /* notification that a previously read-only page is about to become
+        * writable, if an error is returned it will cause a SIGBUS */
+@@ -690,6 +656,7 @@
   */
--int call_usermodehelper_keys(char *path, char **argv, char **envp,
--                           struct key *session_keyring, int wait)
-+struct subprocess_info *call_usermodehelper_setup(char *path,
-+                                                char **argv, char **envp)
+ #define NOPAGE_SIGBUS (NULL)
+ #define NOPAGE_OOM    ((struct page *) (-1))
++#define NOPAGE_REFAULT        ((struct page *) (-2))  /* Return to userspace, rerun */
+ /*
+  * Error return values for the *_nopfn functions
+@@ -777,16 +744,6 @@
+               struct vm_area_struct *start_vma, unsigned long start_addr,
+               unsigned long end_addr, unsigned long *nr_accounted,
+               struct zap_details *);
+-
+-struct mm_walk {
+-      int (*pgd_entry)(pgd_t *, unsigned long, unsigned long, void *);
+-      int (*pud_entry)(pud_t *, unsigned long, unsigned long, void *);
+-      int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, void *);
+-      int (*pte_entry)(pte_t *, unsigned long, unsigned long, void *);
+-};
+-
+-int walk_page_range(struct mm_struct *, unsigned long addr, unsigned long end,
+-                  struct mm_walk *walk, void *private);
+ void free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+               unsigned long end, unsigned long floor, unsigned long ceiling);
+ void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *start_vma,
+@@ -1101,7 +1058,6 @@
+ extern int insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
+ extern void __vma_link_rb(struct mm_struct *, struct vm_area_struct *,
+       struct rb_node **, struct rb_node *);
+-extern void __unlink_file_vma(struct vm_area_struct *);
+ extern void unlink_file_vma(struct vm_area_struct *);
+ extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
+       unsigned long addr, unsigned long len, pgoff_t pgoff);
+@@ -1141,11 +1097,9 @@
+                                      loff_t lstart, loff_t lend);
+ /* generic vm_area_ops exported for stackable file systems */
+-extern struct page *filemap_fault(struct vm_area_struct *, struct fault_data *);
+-extern struct page * __deprecated_for_modules
+-filemap_nopage(struct vm_area_struct *, unsigned long, int *);
+-extern int __deprecated_for_modules filemap_populate(struct vm_area_struct *,
+-              unsigned long, unsigned long, pgprot_t, unsigned long, int);
++extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int *);
++extern int filemap_populate(struct vm_area_struct *, unsigned long,
++              unsigned long, pgprot_t, unsigned long, int);
+ /* mm/page-writeback.c */
+ int write_one_page(struct page *page, int wait);
+@@ -1245,7 +1199,6 @@
+                                       void __user *, size_t *, loff_t *);
+ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
+                       unsigned long lru_pages);
+-extern void drop_pagecache_sb(struct super_block *);
+ void drop_pagecache(void);
+ void drop_slab(void);
+diff -Nurb linux-2.6.22-590/include/linux/mmc/card.h linux-2.6.22-570/include/linux/mmc/card.h
+--- linux-2.6.22-590/include/linux/mmc/card.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/mmc/card.h  2007-07-08 19:32:17.000000000 -0400
+@@ -72,7 +72,6 @@
+ #define MMC_STATE_READONLY    (1<<1)          /* card is read-only */
+ #define MMC_STATE_HIGHSPEED   (1<<2)          /* card is in high speed mode */
+ #define MMC_STATE_BLOCKADDR   (1<<3)          /* card uses block-addressing */
+-#define MMC_STATE_LOCKED      (1<<4)          /* card is currently locked */
+       u32                     raw_cid[4];     /* raw card CID */
+       u32                     raw_csd[4];     /* raw card CSD */
+       u32                     raw_scr[2];     /* raw card SCR */
+@@ -90,16 +89,11 @@
+ #define mmc_card_readonly(c)  ((c)->state & MMC_STATE_READONLY)
+ #define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
+ #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
+-#define mmc_card_locked(c)    ((c)->state & MMC_STATE_LOCKED)
+-
+-#define mmc_card_lockable(c)  (((c)->csd.cmdclass & CCC_LOCK_CARD) && \
+-                              ((c)->host->caps & MMC_CAP_BYTEBLOCK))
+ #define mmc_card_set_present(c)       ((c)->state |= MMC_STATE_PRESENT)
+ #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
+ #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
+ #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
+-#define mmc_card_set_locked(c)        ((c)->state |= MMC_STATE_LOCKED)
+ #define mmc_card_name(c)      ((c)->cid.prod_name)
+ #define mmc_card_id(c)                ((c)->dev.bus_id)
+diff -Nurb linux-2.6.22-590/include/linux/mmc/mmc.h linux-2.6.22-570/include/linux/mmc/mmc.h
+--- linux-2.6.22-590/include/linux/mmc/mmc.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/mmc/mmc.h   2007-07-08 19:32:17.000000000 -0400
+@@ -253,13 +253,5 @@
+ #define MMC_SWITCH_MODE_CLEAR_BITS    0x02    /* Clear bits which are 1 in value */
+ #define MMC_SWITCH_MODE_WRITE_BYTE    0x03    /* Set target to value */
+-/*
+- * MMC_LOCK_UNLOCK modes
+- */
+-#define MMC_LOCK_MODE_ERASE   (1<<3)
+-#define MMC_LOCK_MODE_UNLOCK  (1<<2)
+-#define MMC_LOCK_MODE_CLR_PWD (1<<1)
+-#define MMC_LOCK_MODE_SET_PWD (1<<0)
+-
+ #endif  /* MMC_MMC_PROTOCOL_H */
+diff -Nurb linux-2.6.22-590/include/linux/mmzone.h linux-2.6.22-570/include/linux/mmzone.h
+--- linux-2.6.22-590/include/linux/mmzone.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/mmzone.h    2007-07-08 19:32:17.000000000 -0400
+@@ -13,7 +13,6 @@
+ #include <linux/init.h>
+ #include <linux/seqlock.h>
+ #include <linux/nodemask.h>
+-#include <linux/pageblock-flags.h>
+ #include <asm/atomic.h>
+ #include <asm/page.h>
+@@ -25,24 +24,8 @@
+ #endif
+ #define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1))
+-#ifdef CONFIG_PAGE_GROUP_BY_MOBILITY
+-#define MIGRATE_UNMOVABLE     0
+-#define MIGRATE_RECLAIMABLE   1
+-#define MIGRATE_MOVABLE       2
+-#define MIGRATE_TYPES         3
+-#else
+-#define MIGRATE_UNMOVABLE     0
+-#define MIGRATE_UNRECLAIMABLE 0
+-#define MIGRATE_MOVABLE       0
+-#define MIGRATE_TYPES         1
+-#endif
+-
+-#define for_each_migratetype_order(order, type) \
+-      for (order = 0; order < MAX_ORDER; order++) \
+-              for (type = 0; type < MIGRATE_TYPES; type++)
+-
+ struct free_area {
+-      struct list_head        free_list[MIGRATE_TYPES];
++      struct list_head        free_list;
+       unsigned long           nr_free;
+ };
+@@ -230,14 +213,6 @@
+ #endif
+       struct free_area        free_area[MAX_ORDER];
+-#ifndef CONFIG_SPARSEMEM
+-      /*
+-       * Flags for a MAX_ORDER_NR_PAGES block. See pageblock-flags.h.
+-       * In SPARSEMEM, this map is stored in struct mem_section
+-       */
+-      unsigned long           *pageblock_flags;
+-#endif /* CONFIG_SPARSEMEM */
+-
+       ZONE_PADDING(_pad1_)
+@@ -493,7 +468,6 @@
+ void get_zone_counts(unsigned long *active, unsigned long *inactive,
+                       unsigned long *free);
+ void build_all_zonelists(void);
+-void raise_kswapd_order(unsigned int order);
+ void wakeup_kswapd(struct zone *zone, int order);
+ int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
+               int classzone_idx, int alloc_flags);
+@@ -688,9 +662,6 @@
+ #define PAGES_PER_SECTION       (1UL << PFN_SECTION_SHIFT)
+ #define PAGE_SECTION_MASK     (~(PAGES_PER_SECTION-1))
+-#define SECTION_BLOCKFLAGS_BITS \
+-              ((SECTION_SIZE_BITS - (MAX_ORDER-1)) * NR_PAGEBLOCK_BITS)
+-
+ #if (MAX_ORDER - 1 + PAGE_SHIFT) > SECTION_SIZE_BITS
+ #error Allocator MAX_ORDER exceeds SECTION_SIZE
+ #endif
+@@ -710,7 +681,6 @@
+        * before using it wrong.
+        */
+       unsigned long section_mem_map;
+-      DECLARE_BITMAP(pageblock_flags, SECTION_BLOCKFLAGS_BITS);
+ };
+ #ifdef CONFIG_SPARSEMEM_EXTREME
+diff -Nurb linux-2.6.22-590/include/linux/mnt_namespace.h linux-2.6.22-570/include/linux/mnt_namespace.h
+--- linux-2.6.22-590/include/linux/mnt_namespace.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/mnt_namespace.h     2007-07-08 19:32:17.000000000 -0400
+@@ -14,7 +14,7 @@
+       int event;
+ };
+-extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
++extern struct mnt_namespace *copy_mnt_ns(int, struct mnt_namespace *,
+               struct fs_struct *);
+ extern void __put_mnt_ns(struct mnt_namespace *ns);
+diff -Nurb linux-2.6.22-590/include/linux/module.h linux-2.6.22-570/include/linux/module.h
+--- linux-2.6.22-590/include/linux/module.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/module.h    2007-07-08 19:32:17.000000000 -0400
+@@ -227,17 +227,8 @@
+       MODULE_STATE_LIVE,
+       MODULE_STATE_COMING,
+       MODULE_STATE_GOING,
+-      MODULE_STATE_GONE,
+ };
+-#ifdef CONFIG_KGDB
+-#define MAX_SECTNAME 31
+-struct mod_section {
+-       void *address;
+-       char name[MAX_SECTNAME + 1];
+-};
+-#endif
+-
+ /* Similar stuff for section attributes. */
+ struct module_sect_attr
  {
--      DECLARE_COMPLETION_ONSTACK(done);
-       struct subprocess_info *sub_info;
--      int retval;
+@@ -265,13 +256,6 @@
+       /* Unique handle for this module */
+       char name[MODULE_NAME_LEN];
+-#ifdef CONFIG_KGDB
+-      /* keep kgdb info at the begining so that gdb doesn't have a chance to
+-       * miss out any fields */
+-      unsigned long num_sections;
+-      struct mod_section *mod_sections;
+-#endif
 -
--      if (!khelper_wq)
--              return -EBUSY;
+       /* Sysfs stuff. */
+       struct module_kobject mkobj;
+       struct module_param_attrs *param_attrs;
+diff -Nurb linux-2.6.22-590/include/linux/namei.h linux-2.6.22-570/include/linux/namei.h
+--- linux-2.6.22-590/include/linux/namei.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/namei.h     2007-07-08 19:32:17.000000000 -0400
+@@ -3,7 +3,6 @@
+ #include <linux/dcache.h>
+ #include <linux/linkage.h>
+-#include <linux/mount.h>
+ struct vfsmount;
+@@ -82,16 +81,9 @@
+ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
+ extern void release_open_intent(struct nameidata *);
+-extern struct dentry * lookup_one_len_nd(const char *, struct dentry *,
+-                                       int, struct nameidata *);
++extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
+ extern struct dentry *lookup_one_len_kern(const char *, struct dentry *, int);
+-static inline struct dentry *lookup_one_len(const char *name,
+-                      struct dentry *dir, int len)
+-{
+-      return lookup_one_len_nd(name, dir, len, NULL);
+-}
 -
--      if (path[0] == '\0')
--              return 0;
+ extern int follow_down(struct vfsmount **, struct dentry **);
+ extern int follow_up(struct vfsmount **, struct dentry **);
+@@ -108,16 +100,4 @@
+       return nd->saved_names[nd->depth];
+ }
+-static inline void pathget(struct path *path)
+-{
+-      mntget(path->mnt);
+-      dget(path->dentry);
+-}
 -
-       sub_info = kzalloc(sizeof(struct subprocess_info),  GFP_ATOMIC);
-       if (!sub_info)
--              return -ENOMEM;
-+              goto out;
+-static inline void pathput(struct path *path)
+-{
+-      dput(path->dentry);
+-      mntput(path->mnt);
+-}
+-
+ #endif /* _LINUX_NAMEI_H */
+diff -Nurb linux-2.6.22-590/include/linux/net.h linux-2.6.22-570/include/linux/net.h
+--- linux-2.6.22-590/include/linux/net.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/net.h       2008-01-23 19:16:05.000000000 -0500
+@@ -23,7 +23,6 @@
+ struct poll_table_struct;
+ struct inode;
+-struct net;
+ #define NPROTO                34              /* should be enough for now..   */
+@@ -171,7 +170,7 @@
+ struct net_proto_family {
+       int             family;
+-      int             (*create)(struct net *net, struct socket *sock, int protocol);
++      int             (*create)(struct socket *sock, int protocol);
+       struct module   *owner;
+ };
+diff -Nurb linux-2.6.22-590/include/linux/netdevice.h linux-2.6.22-570/include/linux/netdevice.h
+--- linux-2.6.22-590/include/linux/netdevice.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/netdevice.h 2008-01-23 19:15:56.000000000 -0500
+@@ -39,7 +39,6 @@
+ #include <linux/percpu.h>
+ #include <linux/dmaengine.h>
+-struct net;
+ struct vlan_group;
+ struct ethtool_ops;
+ struct netpoll_info;
+@@ -315,10 +314,9 @@
+       /* Net device features */
+       unsigned long           features;
+ #define NETIF_F_SG            1       /* Scatter/gather IO. */
+-#define NETIF_F_IP_CSUM               2       /* Can checksum TCP/UDP over IPv4. */
++#define NETIF_F_IP_CSUM               2       /* Can checksum only TCP/UDP over IPv4. */
+ #define NETIF_F_NO_CSUM               4       /* Does not require checksum. F.e. loopack. */
+ #define NETIF_F_HW_CSUM               8       /* Can checksum all the packets. */
+-#define NETIF_F_IPV6_CSUM     16      /* Can checksum TCP/UDP over IPV6 */
+ #define NETIF_F_HIGHDMA               32      /* Can DMA to high memory. */
+ #define NETIF_F_FRAGLIST      64      /* Scatter/gather IO. */
+ #define NETIF_F_HW_VLAN_TX    128     /* Transmit VLAN hw acceleration */
+@@ -327,7 +325,6 @@
+ #define NETIF_F_VLAN_CHALLENGED       1024    /* Device cannot handle VLAN packets */
+ #define NETIF_F_GSO           2048    /* Enable software GSO. */
+ #define NETIF_F_LLTX          4096    /* LockLess TX */
+-#define NETIF_F_NETNS_LOCAL   8192    /* Does not change network namespaces */
+       /* Segmentation offload features */
+ #define NETIF_F_GSO_SHIFT     16
+@@ -341,11 +338,8 @@
+       /* List of features with software fallbacks. */
+ #define NETIF_F_GSO_SOFTWARE  (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
+-
+ #define NETIF_F_GEN_CSUM      (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
+-#define NETIF_F_V4_CSUM               (NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM)
+-#define NETIF_F_V6_CSUM               (NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
+-#define NETIF_F_ALL_CSUM      (NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)
++#define NETIF_F_ALL_CSUM      (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
+       struct net_device       *next_sched;
+@@ -539,9 +533,6 @@
+       void                    (*poll_controller)(struct net_device *dev);
+ #endif
+-      /* Network namespace this network device is inside */
+-      struct net              *nd_net;
+-
+       /* bridge stuff */
+       struct net_bridge_port  *br_port;
+@@ -549,16 +540,13 @@
+       struct device           dev;
+       /* space for optional statistics and wireless sysfs groups */
+       struct attribute_group  *sysfs_groups[3];
+-
+-      /* rtnetlink link ops */
+-      const struct rtnl_link_ops *rtnl_link_ops;
+ };
+ #define to_net_dev(d) container_of(d, struct net_device, dev)
+ #define       NETDEV_ALIGN            32
+ #define       NETDEV_ALIGN_CONST      (NETDEV_ALIGN - 1)
+-static inline void *netdev_priv(const struct net_device *dev)
++static inline void *netdev_priv(struct net_device *dev)
+ {
+       return (char *)dev + ((sizeof(struct net_device)
+                                       + NETDEV_ALIGN_CONST)
+@@ -588,48 +576,45 @@
+ #include <linux/interrupt.h>
+ #include <linux/notifier.h>
++extern struct net_device              loopback_dev;           /* The loopback */
++extern struct list_head                       dev_base_head;          /* All devices */
+ extern rwlock_t                               dev_base_lock;          /* Device list lock */
+-
+-#define for_each_netdev(net, d)               \
+-              list_for_each_entry(d, &(net)->dev_base_head, dev_list)
+-#define for_each_netdev_safe(net, d, n)       \
+-              list_for_each_entry_safe(d, n, &(net)->dev_base_head, dev_list)
+-#define for_each_netdev_continue(net, d)              \
+-              list_for_each_entry_continue(d, &(net)->dev_base_head, dev_list)
++#define for_each_netdev(d)            \
++              list_for_each_entry(d, &dev_base_head, dev_list)
++#define for_each_netdev_safe(d, n)    \
++              list_for_each_entry_safe(d, n, &dev_base_head, dev_list)
++#define for_each_netdev_continue(d)           \
++              list_for_each_entry_continue(d, &dev_base_head, dev_list)
+ #define net_device_entry(lh)  list_entry(lh, struct net_device, dev_list)
+-#define next_net_device(d)                                            \
+-({                                                                    \
+-      struct net_device *dev = d;                                     \
+-      struct list_head *lh;                                           \
+-      struct net *net;                                                \
+-                                                                      \
+-      net = dev->nd_net;                                              \
+-      lh = dev->dev_list.next;                                        \
+-      lh == &net->dev_base_head ? NULL : net_device_entry(lh);        \
+-})
+-
+-#define first_net_device(N)                                   \
+-({                                                            \
+-      struct net *NET = (N);                                  \
+-      list_empty(&NET->dev_base_head) ? NULL :                \
+-              net_device_entry(NET->dev_base_head.next);      \
+-})
++static inline struct net_device *next_net_device(struct net_device *dev)
++{
++      struct list_head *lh;
++
++      lh = dev->dev_list.next;
++      return lh == &dev_base_head ? NULL : net_device_entry(lh);
++}
++
++static inline struct net_device *first_net_device(void)
++{
++      return list_empty(&dev_base_head) ? NULL :
++              net_device_entry(dev_base_head.next);
++}
+ extern int                    netdev_boot_setup_check(struct net_device *dev);
+ extern unsigned long          netdev_boot_base(const char *prefix, int unit);
+-extern struct net_device    *dev_getbyhwaddr(struct net *net, unsigned short type, char *hwaddr);
+-extern struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type);
+-extern struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short type);
++extern struct net_device    *dev_getbyhwaddr(unsigned short type, char *hwaddr);
++extern struct net_device *dev_getfirstbyhwtype(unsigned short type);
++extern struct net_device *__dev_getfirstbyhwtype(unsigned short type);
+ extern void           dev_add_pack(struct packet_type *pt);
+ extern void           dev_remove_pack(struct packet_type *pt);
+ extern void           __dev_remove_pack(struct packet_type *pt);
+-extern struct net_device      *dev_get_by_flags(struct net *net, unsigned short flags,
++extern struct net_device      *dev_get_by_flags(unsigned short flags,
+                                                 unsigned short mask);
+-extern struct net_device      *dev_get_by_name(struct net *net, const char *name);
+-extern struct net_device      *__dev_get_by_name(struct net *net, const char *name);
++extern struct net_device      *dev_get_by_name(const char *name);
++extern struct net_device      *__dev_get_by_name(const char *name);
+ extern int            dev_alloc_name(struct net_device *dev, const char *name);
+ extern int            dev_open(struct net_device *dev);
+ extern int            dev_close(struct net_device *dev);
+@@ -640,9 +625,9 @@
+ extern void           synchronize_net(void);
+ extern int            register_netdevice_notifier(struct notifier_block *nb);
+ extern int            unregister_netdevice_notifier(struct notifier_block *nb);
+-extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
+-extern struct net_device      *dev_get_by_index(struct net *net, int ifindex);
+-extern struct net_device      *__dev_get_by_index(struct net *net, int ifindex);
++extern int            call_netdevice_notifiers(unsigned long val, void *v);
++extern struct net_device      *dev_get_by_index(int ifindex);
++extern struct net_device      *__dev_get_by_index(int ifindex);
+ extern int            dev_restart(struct net_device *dev);
+ #ifdef CONFIG_NETPOLL_TRAP
+ extern int            netpoll_trap(void);
+@@ -747,13 +732,11 @@
+ #define HAVE_NETIF_RECEIVE_SKB 1
+ extern int            netif_receive_skb(struct sk_buff *skb);
+ extern int            dev_valid_name(const char *name);
+-extern int            dev_ioctl(struct net *net, unsigned int cmd, void __user *);
+-extern int            dev_ethtool(struct net *net, struct ifreq *);
++extern int            dev_ioctl(unsigned int cmd, void __user *);
++extern int            dev_ethtool(struct ifreq *);
+ extern unsigned               dev_get_flags(const struct net_device *);
+ extern int            dev_change_flags(struct net_device *, unsigned);
+ extern int            dev_change_name(struct net_device *, char *);
+-extern int            dev_change_net_namespace(struct net_device *,
+-                                               struct net *, const char *);
+ extern int            dev_set_mtu(struct net_device *, int);
+ extern int            dev_set_mac_address(struct net_device *,
+                                           struct sockaddr *);
+@@ -1023,7 +1006,7 @@
+ extern void           netdev_state_change(struct net_device *dev);
+ extern void           netdev_features_change(struct net_device *dev);
+ /* Load a device via the kmod */
+-extern void           dev_load(struct net *net, const char *name);
++extern void           dev_load(const char *name);
+ extern void           dev_mcast_init(void);
+ extern int            netdev_max_backlog;
+ extern int            weight_p;
+diff -Nurb linux-2.6.22-590/include/linux/netfilter/x_tables.h linux-2.6.22-570/include/linux/netfilter/x_tables.h
+--- linux-2.6.22-590/include/linux/netfilter/x_tables.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/netfilter/x_tables.h        2007-07-08 19:32:17.000000000 -0400
+@@ -289,7 +289,7 @@
+                          unsigned int size, const char *table, unsigned int hook,
+                          unsigned short proto, int inv_proto);
+-extern int xt_register_table(struct net *net, struct xt_table *table,
++extern int xt_register_table(struct xt_table *table,
+                            struct xt_table_info *bootstrap,
+                            struct xt_table_info *newinfo);
+ extern void *xt_unregister_table(struct xt_table *table);
+@@ -306,7 +306,7 @@
+ extern int xt_find_revision(int af, const char *name, u8 revision, int target,
+                           int *err);
  
-       INIT_WORK(&sub_info->work, __call_usermodehelper);
--      sub_info->complete = &done;
-       sub_info->path = path;
-       sub_info->argv = argv;
-       sub_info->envp = envp;
--      sub_info->ring = session_keyring;
--      sub_info->wait = wait;
+-extern struct xt_table *xt_find_table_lock(struct net *net, int af, const char *name);
++extern struct xt_table *xt_find_table_lock(int af, const char *name);
+ extern void xt_table_unlock(struct xt_table *t);
  
--      queue_work(khelper_wq, &sub_info->work);
--      if (wait < 0) /* task has freed sub_info */
--              return 0;
--      wait_for_completion(&done);
--      retval = sub_info->retval;
--      kfree(sub_info);
--      return retval;
-+  out:
-+      return sub_info;
+ extern int xt_proto_init(int af);
+diff -Nurb linux-2.6.22-590/include/linux/netfilter.h linux-2.6.22-570/include/linux/netfilter.h
+--- linux-2.6.22-590/include/linux/netfilter.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/netfilter.h 2007-07-08 19:32:17.000000000 -0400
+@@ -362,6 +362,11 @@
+ #endif
  }
--EXPORT_SYMBOL(call_usermodehelper_keys);
-+EXPORT_SYMBOL(call_usermodehelper_setup);
  
--int call_usermodehelper_pipe(char *path, char **argv, char **envp,
--                           struct file **filp)
-+/**
-+ * call_usermodehelper_setkeys - set the session keys for usermode helper
-+ * @info: a subprocess_info returned by call_usermodehelper_setup
-+ * @session_keyring: the session keyring for the process
-+ */
-+void call_usermodehelper_setkeys(struct subprocess_info *info,
-+                               struct key *session_keyring)
- {
--      DECLARE_COMPLETION(done);
--      struct subprocess_info sub_info = {
--              .work           = __WORK_INITIALIZER(sub_info.work,
--                                                   __call_usermodehelper),
--              .complete       = &done,
--              .path           = path,
--              .argv           = argv,
--              .envp           = envp,
--              .retval         = 0,
--      };
--      struct file *f;
-+      info->ring = session_keyring;
-+}
-+EXPORT_SYMBOL(call_usermodehelper_setkeys);
++#ifdef CONFIG_PROC_FS
++#include <linux/proc_fs.h>
++extern struct proc_dir_entry *proc_net_netfilter;
++#endif
++
+ #else /* !CONFIG_NETFILTER */
+ #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
+ #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
+diff -Nurb linux-2.6.22-590/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.22-570/include/linux/netfilter_ipv4/ip_tables.h
+--- linux-2.6.22-590/include/linux/netfilter_ipv4/ip_tables.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/netfilter_ipv4/ip_tables.h  2007-07-08 19:32:17.000000000 -0400
+@@ -292,7 +292,7 @@
+ #include <linux/init.h>
+ extern void ipt_init(void) __init;
  
--      if (!khelper_wq)
--              return -EBUSY;
-+/**
-+ * call_usermodehelper_setcleanup - set a cleanup function
-+ * @info: a subprocess_info returned by call_usermodehelper_setup
-+ * @cleanup: a cleanup function
-+ *
-+ * The cleanup function is just befor ethe subprocess_info is about to
-+ * be freed.  This can be used for freeing the argv and envp.  The
-+ * Function must be runnable in either a process context or the
-+ * context in which call_usermodehelper_exec is called.
-+ */
-+void call_usermodehelper_setcleanup(struct subprocess_info *info,
-+                                  void (*cleanup)(char **argv, char **envp))
-+{
-+      info->cleanup = cleanup;
-+}
-+EXPORT_SYMBOL(call_usermodehelper_setcleanup);
+-extern int ipt_register_table(struct net *net, struct xt_table *table,
++extern int ipt_register_table(struct xt_table *table,
+                             const struct ipt_replace *repl);
+ extern void ipt_unregister_table(struct xt_table *table);
  
--      if (path[0] == '\0')
--              return 0;
-+/**
-+ * call_usermodehelper_stdinpipe - set up a pipe to be used for stdin
-+ * @sub_info: a subprocess_info returned by call_usermodehelper_setup
-+ * @filp: set to the write-end of a pipe
-+ *
-+ * This constructs a pipe, and sets the read end to be the stdin of the
-+ * subprocess, and returns the write-end in *@filp.
-+ */
-+int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info,
-+                                struct file **filp)
-+{
-+      struct file *f;
+diff -Nurb linux-2.6.22-590/include/linux/netfilter_ipv4.h linux-2.6.22-570/include/linux/netfilter_ipv4.h
+--- linux-2.6.22-590/include/linux/netfilter_ipv4.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/netfilter_ipv4.h    2007-07-08 19:32:17.000000000 -0400
+@@ -75,7 +75,7 @@
+ #define SO_ORIGINAL_DST 80
  
-       f = create_write_pipe();
-       if (IS_ERR(f))
-@@ -335,11 +345,85 @@
-               free_write_pipe(*filp);
-               return PTR_ERR(f);
-       }
--      sub_info.stdin = f;
-+      sub_info->stdin = f;
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(call_usermodehelper_stdinpipe);
+ #ifdef __KERNEL__
+-extern int ip_route_me_harder(struct net *net, struct sk_buff **pskb, unsigned addr_type);
++extern int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type);
+ extern int ip_xfrm_me_harder(struct sk_buff **pskb);
+ extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+                                  unsigned int dataoff, u_int8_t protocol);
+diff -Nurb linux-2.6.22-590/include/linux/netlink.h linux-2.6.22-570/include/linux/netlink.h
+--- linux-2.6.22-590/include/linux/netlink.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/netlink.h   2008-01-23 19:15:56.000000000 -0500
+@@ -21,14 +21,12 @@
+ #define NETLINK_DNRTMSG               14      /* DECnet routing messages */
+ #define NETLINK_KOBJECT_UEVENT        15      /* Kernel messages to userspace */
+ #define NETLINK_GENERIC               16
+-#define NETLINK_DM            17      /* Device Mapper */
++/* leave room for NETLINK_DM (DM Events) */
+ #define NETLINK_SCSITRANSPORT 18      /* SCSI Transports */
+ #define NETLINK_ECRYPTFS      19
  
--      queue_work(khelper_wq, &sub_info.work);
-+/**
-+ * call_usermodehelper_exec - start a usermode application
-+ * @sub_info: information about the subprocessa
-+ * @wait: wait for the application to finish and return status.
-+ *        when -1 don't wait at all, but you get no useful error back when
-+ *        the program couldn't be exec'ed. This makes it safe to call
-+ *        from interrupt context.
-+ *
-+ * Runs a user-space application.  The application is started
-+ * asynchronously if wait is not set, and runs as a child of keventd.
-+ * (ie. it runs with full root capabilities).
-+ */
-+int call_usermodehelper_exec(struct subprocess_info *sub_info,
-+                           enum umh_wait wait)
-+{
-+      DECLARE_COMPLETION_ONSTACK(done);
-+      int retval;
-+
-+      if (sub_info->path[0] == '\0') {
-+              retval = 0;
-+              goto out;
-+      }
-+
-+      if (!khelper_wq) {
-+              retval = -EBUSY;
-+              goto out;
-+      }
-+
-+      sub_info->complete = &done;
-+      sub_info->wait = wait;
-+
-+      queue_work(khelper_wq, &sub_info->work);
-+      if (wait == UMH_NO_WAIT) /* task has freed sub_info */
-+              return 0;
-       wait_for_completion(&done);
--      return sub_info.retval;
-+      retval = sub_info->retval;
-+
-+  out:
-+      call_usermodehelper_freeinfo(sub_info);
-+      return retval;
-+}
-+EXPORT_SYMBOL(call_usermodehelper_exec);
-+
-+/**
-+ * call_usermodehelper_pipe - call a usermode helper process with a pipe stdin
-+ * @path: path to usermode executable
-+ * @argv: arg vector for process
-+ * @envp: environment for process
-+ * @filp: set to the write-end of a pipe
-+ *
-+ * This is a simple wrapper which executes a usermode-helper function
-+ * with a pipe as stdin.  It is implemented entirely in terms of
-+ * lower-level call_usermodehelper_* functions.
-+ */
-+int call_usermodehelper_pipe(char *path, char **argv, char **envp,
-+                           struct file **filp)
-+{
-+      struct subprocess_info *sub_info;
-+      int ret;
-+
-+      sub_info = call_usermodehelper_setup(path, argv, envp);
-+      if (sub_info == NULL)
-+              return -ENOMEM;
-+
-+      ret = call_usermodehelper_stdinpipe(sub_info, filp);
-+      if (ret < 0)
-+              goto out;
-+
-+      return call_usermodehelper_exec(sub_info, 1);
-+
-+  out:
-+      call_usermodehelper_freeinfo(sub_info);
-+      return ret;
- }
- EXPORT_SYMBOL(call_usermodehelper_pipe);
+ #define MAX_LINKS 32          
  
-diff -Nurb linux-2.6.22-570/kernel/module.c linux-2.6.22-590/kernel/module.c
---- linux-2.6.22-570/kernel/module.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/kernel/module.c   2008-01-02 13:56:37.000000000 -0500
-@@ -67,6 +67,7 @@
- /* List of modules, protected by module_mutex AND modlist_lock */
- static DEFINE_MUTEX(module_mutex);
- static LIST_HEAD(modules);
-+static DECLARE_MUTEX(notify_mutex);
+-struct net;
+-
+ struct sockaddr_nl
+ {
+       sa_family_t     nl_family;      /* AF_NETLINK   */
+@@ -159,8 +157,7 @@
+ #define NETLINK_CREDS(skb)    (&NETLINK_CB((skb)).creds)
  
- static BLOCKING_NOTIFIER_HEAD(module_notify_list);
  
-@@ -488,8 +489,7 @@
-         mod->field = NULL;                                            \
- }                                                                     \
- static struct module_attribute modinfo_##field = {                    \
--      .attr = { .name = __stringify(field), .mode = 0444,           \
--                .owner = THIS_MODULE },                             \
-+      .attr = { .name = __stringify(field), .mode = 0444 },         \
-       .show = show_modinfo_##field,                                 \
-       .setup = setup_modinfo_##field,                               \
-       .test = modinfo_##field##_exists,                             \
-@@ -713,6 +713,12 @@
-       if (ret != 0)
-               goto out;
+-extern struct sock *netlink_kernel_create(struct net *net,
+-                                        int unit,unsigned int groups,
++extern struct sock *netlink_kernel_create(int unit, unsigned int groups,
+                                         void (*input)(struct sock *sk, int len),
+                                         struct mutex *cb_mutex,
+                                         struct module *module);
+@@ -207,7 +204,6 @@
  
-+      down(&notify_mutex);
-+      blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING,
-+                              mod);
-+      up(&notify_mutex);
-+
-+
-       /* Never wait if forced. */
-       if (!forced && module_refcount(mod) != 0)
-               wait_for_zero_refcount(mod);
-@@ -725,6 +731,11 @@
-       }
-       free_module(mod);
+ struct netlink_notify
+ {
+-      struct net *net;
+       int pid;
+       int protocol;
+ };
+diff -Nurb linux-2.6.22-590/include/linux/netpoll.h linux-2.6.22-570/include/linux/netpoll.h
+--- linux-2.6.22-590/include/linux/netpoll.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/netpoll.h   2007-07-08 19:32:17.000000000 -0400
+@@ -16,7 +16,7 @@
+       struct net_device *dev;
+       char dev_name[IFNAMSIZ];
+       const char *name;
+-      void (*rx_hook)(struct netpoll *, int, char *, int, struct sk_buff *);
++      void (*rx_hook)(struct netpoll *, int, char *, int);
  
-+      down(&notify_mutex);
-+      blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GONE,
-+                      NULL);
-+      up(&notify_mutex);
-+
-  out:
-       mutex_unlock(&module_mutex);
-       return ret;
-@@ -793,7 +804,7 @@
- }
+       u32 local_ip, remote_ip;
+       u16 local_port, remote_port;
+diff -Nurb linux-2.6.22-590/include/linux/nfs4.h linux-2.6.22-570/include/linux/nfs4.h
+--- linux-2.6.22-590/include/linux/nfs4.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/nfs4.h      2007-07-08 19:32:17.000000000 -0400
+@@ -15,7 +15,6 @@
  
- static struct module_attribute refcnt = {
--      .attr = { .name = "refcnt", .mode = 0444, .owner = THIS_MODULE },
-+      .attr = { .name = "refcnt", .mode = 0444 },
-       .show = show_refcnt,
- };
+ #include <linux/types.h>
  
-@@ -846,12 +857,15 @@
-       case MODULE_STATE_GOING:
-               state = "going";
-               break;
-+      case MODULE_STATE_GONE:
-+              state = "gone";
-+              break;
-       }
-       return sprintf(buffer, "%s\n", state);
- }
+-#define NFS4_BITMAP_SIZE      2
+ #define NFS4_VERIFIER_SIZE    8
+ #define NFS4_STATEID_SIZE     16
+ #define NFS4_FHSIZE           128
+diff -Nurb linux-2.6.22-590/include/linux/nfs4_mount.h linux-2.6.22-570/include/linux/nfs4_mount.h
+--- linux-2.6.22-590/include/linux/nfs4_mount.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/nfs4_mount.h        2007-07-08 19:32:17.000000000 -0400
+@@ -65,7 +65,6 @@
+ #define NFS4_MOUNT_NOCTO      0x0010  /* 1 */
+ #define NFS4_MOUNT_NOAC               0x0020  /* 1 */
+ #define NFS4_MOUNT_STRICTLOCK 0x1000  /* 1 */
+-#define NFS4_MOUNT_UNSHARED   0x8000  /* 1 */
+ #define NFS4_MOUNT_FLAGMASK   0xFFFF
  
- static struct module_attribute initstate = {
--      .attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE },
-+      .attr = { .name = "initstate", .mode = 0444 },
-       .show = show_initstate,
- };
+ #endif
+diff -Nurb linux-2.6.22-590/include/linux/nfs_fs.h linux-2.6.22-570/include/linux/nfs_fs.h
+--- linux-2.6.22-590/include/linux/nfs_fs.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/nfs_fs.h    2007-07-08 19:32:17.000000000 -0400
+@@ -30,9 +30,7 @@
+ #ifdef __KERNEL__
  
-@@ -1032,7 +1046,6 @@
-               sattr->mattr.show = module_sect_show;
-               sattr->mattr.store = NULL;
-               sattr->mattr.attr.name = sattr->name;
--              sattr->mattr.attr.owner = mod;
-               sattr->mattr.attr.mode = S_IRUGO;
-               *(gattr++) = &(sattr++)->mattr.attr;
-       }
-@@ -1090,7 +1103,6 @@
-               if (!attr->test ||
-                   (attr->test && attr->test(mod))) {
-                       memcpy(temp_attr, attr, sizeof(*temp_attr));
--                      temp_attr->attr.owner = mod;
-                       error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);
-                       ++temp_attr;
-               }
-@@ -1212,6 +1224,11 @@
-       /* Arch-specific cleanup. */
-       module_arch_cleanup(mod);
+ #include <linux/in.h>
+-#include <linux/kref.h>
+ #include <linux/mm.h>
+-#include <linux/namei.h>
+ #include <linux/pagemap.h>
+ #include <linux/rbtree.h>
+ #include <linux/rwsem.h>
+@@ -71,8 +69,9 @@
  
-+#ifdef CONFIG_KGDB
-+      /* kgdb info */
-+      vfree(mod->mod_sections);
-+#endif
-+
-       /* Module unload stuff */
-       module_unload_free(mod);
+ struct nfs4_state;
+ struct nfs_open_context {
+-      struct kref kref;
+-      struct path path;
++      atomic_t count;
++      struct vfsmount *vfsmnt;
++      struct dentry *dentry;
+       struct rpc_cred *cred;
+       struct nfs4_state *state;
+       fl_owner_t lockowner;
+@@ -157,9 +156,12 @@
+        * This is the list of dirty unwritten pages.
+        */
+       spinlock_t              req_lock;
++      struct list_head        dirty;
++      struct list_head        commit;
+       struct radix_tree_root  nfs_page_tree;
  
-@@ -1471,6 +1488,31 @@
-       }
- }
+-      unsigned long           ncommit,
++      unsigned int            ndirty,
++                              ncommit,
+                               npages;
  
-+#ifdef CONFIG_KGDB
-+int add_modsects (struct module *mod, Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const
-+                char *secstrings)
-+{
-+        int i;
-+
-+        mod->num_sections = hdr->e_shnum - 1;
-+        mod->mod_sections = vmalloc((hdr->e_shnum - 1)*
-+              sizeof (struct mod_section));
-+
-+        if (mod->mod_sections == NULL) {
-+                return -ENOMEM;
-+        }
-+
-+        for (i = 1; i < hdr->e_shnum; i++) {
-+                mod->mod_sections[i - 1].address = (void *)sechdrs[i].sh_addr;
-+                strncpy(mod->mod_sections[i - 1].name, secstrings +
-+                                sechdrs[i].sh_name, MAX_SECTNAME);
-+                mod->mod_sections[i - 1].name[MAX_SECTNAME] = '\0';
-+      }
-+
-+      return 0;
-+}
-+#endif
-+
- #ifdef CONFIG_KALLSYMS
- static int is_exported(const char *name, const struct module *mod)
- {
-@@ -1886,6 +1928,12 @@
+       /* Open contexts for shared mmap writes */
+diff -Nurb linux-2.6.22-590/include/linux/nfs_fs_sb.h linux-2.6.22-570/include/linux/nfs_fs_sb.h
+--- linux-2.6.22-590/include/linux/nfs_fs_sb.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/nfs_fs_sb.h 2007-07-08 19:32:17.000000000 -0400
+@@ -16,6 +16,7 @@
+ #define NFS_CS_INITING                1               /* busy initialising */
+       int                     cl_nfsversion;  /* NFS protocol version */
+       unsigned long           cl_res_state;   /* NFS resources state */
++#define NFS_CS_RPCIOD         0               /* - rpciod started */
+ #define NFS_CS_CALLBACK               1               /* - callback started */
+ #define NFS_CS_IDMAP          2               /* - idmap started */
+ #define NFS_CS_RENEWD         3               /* - renewd started */
+diff -Nurb linux-2.6.22-590/include/linux/nfs_mount.h linux-2.6.22-570/include/linux/nfs_mount.h
+--- linux-2.6.22-590/include/linux/nfs_mount.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/nfs_mount.h 2008-01-23 19:16:05.000000000 -0500
+@@ -62,7 +62,6 @@
+ #define NFS_MOUNT_STRICTLOCK  0x1000  /* reserved for NFSv4 */
+ #define NFS_MOUNT_SECFLAVOUR  0x2000  /* 5 */
+ #define NFS_MOUNT_NORDIRPLUS  0x4000  /* 5 */
+-#define NFS_MOUNT_UNSHARED    0x8000  /* 5 */
+ #define NFS_MOUNT_TAGGED      0x8000  /* context tagging */
+ #define NFS_MOUNT_FLAGMASK    0xFFFF
  
-       add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
+diff -Nurb linux-2.6.22-590/include/linux/nfs_page.h linux-2.6.22-570/include/linux/nfs_page.h
+--- linux-2.6.22-590/include/linux/nfs_page.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/nfs_page.h  2007-07-08 19:32:17.000000000 -0400
+@@ -16,13 +16,12 @@
+ #include <linux/sunrpc/auth.h>
+ #include <linux/nfs_xdr.h>
  
-+#ifdef CONFIG_KGDB
-+        if ((err = add_modsects(mod, hdr, sechdrs, secstrings)) < 0) {
-+                goto nomodsectinfo;
-+        }
-+#endif
-+
-       err = module_finalize(hdr, sechdrs, mod);
-       if (err < 0)
-               goto cleanup;
-@@ -1946,6 +1994,11 @@
-  arch_cleanup:
-       module_arch_cleanup(mod);
-  cleanup:
-+
-+#ifdef CONFIG_KGDB
-+nomodsectinfo:
-+       vfree(mod->mod_sections);
-+#endif
-       module_unload_free(mod);
-       module_free(mod, mod->module_init);
-  free_core:
-@@ -2017,6 +2070,10 @@
-               /* Init routine failed: abort.  Try to protect us from
-                    buggy refcounters. */
-               mod->state = MODULE_STATE_GOING;
-+              down(&notify_mutex);
-+              blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING,
-+                              mod);
-+              up(&notify_mutex);
-               synchronize_sched();
-               if (mod->unsafe)
-                       printk(KERN_ERR "%s: module is now stuck!\n",
-diff -Nurb linux-2.6.22-570/kernel/ns_container.c linux-2.6.22-590/kernel/ns_container.c
---- linux-2.6.22-570/kernel/ns_container.c     1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/kernel/ns_container.c     2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,99 @@
-+/*
-+ * ns_container.c - namespace container subsystem
-+ *
-+ * Copyright 2006, 2007 IBM Corp
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/container.h>
-+#include <linux/fs.h>
-+
-+struct ns_container {
-+      struct container_subsys_state css;
-+      spinlock_t lock;
-+};
-+
-+struct container_subsys ns_subsys;
-+
-+static inline struct ns_container *container_to_ns(
-+              struct container *container)
-+{
-+      return container_of(container_subsys_state(container, ns_subsys_id),
-+                          struct ns_container, css);
-+}
-+
-+int ns_container_clone(struct task_struct *task)
-+{
-+      return container_clone(task, &ns_subsys);
-+}
-+
-+/*
-+ * Rules:
-+ *   1. you can only enter a container which is a child of your current
-+ *     container
-+ *   2. you can only place another process into a container if
-+ *     a. you have CAP_SYS_ADMIN
-+ *     b. your container is an ancestor of task's destination container
-+ *       (hence either you are in the same container as task, or in an
-+ *        ancestor container thereof)
-+ */
-+static int ns_can_attach(struct container_subsys *ss,
-+              struct container *new_container, struct task_struct *task)
-+{
-+      struct container *orig;
-+
-+      if (current != task) {
-+              if (!capable(CAP_SYS_ADMIN))
-+                      return -EPERM;
-+
-+              if (!container_is_descendant(new_container))
-+                      return -EPERM;
-+      }
-+
-+      if (atomic_read(&new_container->count) != 0)
-+              return -EPERM;
-+
-+      orig = task_container(task, ns_subsys_id);
-+      if (orig && orig != new_container->parent)
-+              return -EPERM;
-+
-+      return 0;
-+}
-+
-+/*
-+ * Rules: you can only create a container if
-+ *     1. you are capable(CAP_SYS_ADMIN)
-+ *     2. the target container is a descendant of your own container
-+ */
-+static int ns_create(struct container_subsys *ss, struct container *container)
-+{
-+      struct ns_container *ns_container;
-+
-+      if (!capable(CAP_SYS_ADMIN))
-+              return -EPERM;
-+      if (!container_is_descendant(container))
-+              return -EPERM;
-+
-+      ns_container = kzalloc(sizeof(*ns_container), GFP_KERNEL);
-+      if (!ns_container) return -ENOMEM;
-+      spin_lock_init(&ns_container->lock);
-+      container->subsys[ns_subsys.subsys_id] = &ns_container->css;
-+      return 0;
-+}
-+
-+static void ns_destroy(struct container_subsys *ss,
-+                      struct container *container)
-+{
-+      struct ns_container *ns_container;
-+
-+      ns_container = container_to_ns(container);
-+      kfree(ns_container);
-+}
-+
-+struct container_subsys ns_subsys = {
-+      .name = "ns",
-+      .can_attach = ns_can_attach,
-+      .create = ns_create,
-+      .destroy  = ns_destroy,
-+      .subsys_id = ns_subsys_id,
-+};
-diff -Nurb linux-2.6.22-570/kernel/nsproxy.c linux-2.6.22-590/kernel/nsproxy.c
---- linux-2.6.22-570/kernel/nsproxy.c  2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/nsproxy.c  2008-01-23 18:40:13.000000000 -0500
-@@ -19,10 +19,13 @@
- #include <linux/init_task.h>
- #include <linux/mnt_namespace.h>
- #include <linux/utsname.h>
-+#include <net/net_namespace.h>
- #include <linux/pid_namespace.h>
- #include <linux/vserver/global.h>
- #include <linux/vserver/debug.h>
+-#include <linux/kref.h>
++#include <asm/atomic.h>
  
-+static struct kmem_cache *nsproxy_cachep;
-+
- struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
+ /*
+  * Valid flags for the radix tree
+  */
+-#define NFS_PAGE_TAG_LOCKED   0
+-#define NFS_PAGE_TAG_COMMIT   1
++#define NFS_PAGE_TAG_WRITEBACK        0
  
- void get_task_namespaces(struct task_struct *tsk)
-@@ -58,6 +61,7 @@
-                       struct fs_struct *new_fs)
- {
-       struct nsproxy *new_nsp;
-+      int err = -ENOMEM;
+ /*
+  * Valid flags for a dirty buffer
+@@ -34,7 +33,8 @@
  
-       vxdprintk(VXD_CBIT(space, 4),
-               "unshare_namespaces(0x%08x,%p,%p)",
-@@ -83,8 +87,24 @@
-       if (IS_ERR(new_nsp->pid_ns))
-               goto out_pid;
+ struct nfs_inode;
+ struct nfs_page {
+-      struct list_head        wb_list;        /* Defines state of page: */
++      struct list_head        wb_list,        /* Defines state of page: */
++                              *wb_list_head;  /*      read/write/commit */
+       struct page             *wb_page;       /* page to read in/write out */
+       struct nfs_open_context *wb_context;    /* File state context info */
+       atomic_t                wb_complete;    /* i/os we're waiting for */
+@@ -42,7 +42,7 @@
+       unsigned int            wb_offset,      /* Offset & ~PAGE_CACHE_MASK */
+                               wb_pgbase,      /* Start of page data */
+                               wb_bytes;       /* Length of request */
+-      struct kref             wb_kref;        /* reference count */
++      atomic_t                wb_count;       /* reference count */
+       unsigned long           wb_flags;
+       struct nfs_writeverf    wb_verf;        /* Commit cookie */
+ };
+@@ -71,8 +71,8 @@
+ extern        void nfs_release_request(struct nfs_page *req);
  
-+      new_nsp->user_ns = copy_user_ns(flags, orig->user_ns);
-+      if (IS_ERR(new_nsp->user_ns))
-+              goto out_user;
-+
-+      new_nsp->net_ns = copy_net_ns(flags, orig->net_ns);
-+      if (IS_ERR(new_nsp->net_ns))
-+              goto out_net;
-+
-       return new_nsp;
  
-+out_net:
-+      if (new_nsp->user_ns)
-+              put_user_ns(new_nsp->user_ns);
-+      if (new_nsp->net_ns)
-+              put_net(new_nsp->net_ns);
-+out_user:
-+      if (new_nsp->pid_ns)
-+              put_pid_ns(new_nsp->pid_ns);
- out_pid:
-       if (new_nsp->ipc_ns)
-               put_ipc_ns(new_nsp->ipc_ns);
-@@ -95,11 +115,11 @@
-       if (new_nsp->mnt_ns)
-               put_mnt_ns(new_nsp->mnt_ns);
- out_ns:
--      kfree(new_nsp);
--      return ERR_PTR(-ENOMEM);
-+      kmem_cache_free(nsproxy_cachep, new_nsp);
-+      return ERR_PTR(err);
+-extern        int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *dst,
+-                        pgoff_t idx_start, unsigned int npages, int tag);
++extern        int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, struct list_head *dst,
++                        pgoff_t idx_start, unsigned int npages);
+ extern        void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
+                            struct inode *inode,
+                            int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
+@@ -84,11 +84,12 @@
+ extern        void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t);
+ extern  int nfs_wait_on_request(struct nfs_page *);
+ extern        void nfs_unlock_request(struct nfs_page *req);
+-extern  void nfs_clear_page_tag_locked(struct nfs_page *req);
++extern  int nfs_set_page_writeback_locked(struct nfs_page *req);
++extern  void nfs_clear_page_writeback(struct nfs_page *req);
+ /*
+- * Lock the page of an asynchronous request without getting a new reference
++ * Lock the page of an asynchronous request without incrementing the wb_count
+  */
+ static inline int
+ nfs_lock_request_dontget(struct nfs_page *req)
+@@ -97,14 +98,14 @@
  }
  
--static struct nsproxy *create_new_namespaces(int flags, struct task_struct *tsk,
-+static struct nsproxy *create_new_namespaces(unsigned long flags, struct task_struct *tsk,
-                       struct fs_struct *new_fs)
- {
-       return unshare_namespaces(flags, tsk->nsproxy, new_fs);
-@@ -130,7 +150,7 @@
-  * called from clone.  This now handles copy for nsproxy and all
-  * namespaces therein.
+ /*
+- * Lock the page of an asynchronous request and take a reference
++ * Lock the page of an asynchronous request
   */
--int copy_namespaces(int flags, struct task_struct *tsk)
-+int copy_namespaces(unsigned long flags, struct task_struct *tsk)
+ static inline int
+ nfs_lock_request(struct nfs_page *req)
  {
-       struct nsproxy *old_ns = tsk->nsproxy;
-       struct nsproxy *new_ns = NULL;
-@@ -144,9 +164,15 @@
+       if (test_and_set_bit(PG_BUSY, &req->wb_flags))
+               return 0;
+-      kref_get(&req->wb_kref);
++      atomic_inc(&req->wb_count);
+       return 1;
+ }
  
-       get_nsproxy(old_ns);
+@@ -117,6 +118,7 @@
+ nfs_list_add_request(struct nfs_page *req, struct list_head *head)
+ {
+       list_add_tail(&req->wb_list, head);
++      req->wb_list_head = head;
+ }
  
--      if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
-+      if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER | CLONE_NEWNET)))
-               return 0;
  
-+       #ifndef CONFIG_NET_NS
-+              if (unshare_flags & CLONE_NEWNET)
-+                      return -EINVAL;
-+       #endif
-+
-+
-       if (!capable(CAP_SYS_ADMIN)) {
-               err = -EPERM;
-               goto out;
-@@ -158,7 +184,14 @@
-               goto out;
-       }
+@@ -130,6 +132,7 @@
+       if (list_empty(&req->wb_list))
+               return;
+       list_del_init(&req->wb_list);
++      req->wb_list_head = NULL;
+ }
  
-+      err = ns_container_clone(tsk);
-+      if (err) {
-+              put_nsproxy(new_ns);
-+              goto out;
-+      }
-+
-       tsk->nsproxy = new_ns;
-+
- out:
-       put_nsproxy(old_ns);
-       vxdprintk(VXD_CBIT(space, 3),
-@@ -194,25 +227,37 @@
-               "unshare_nsproxy_namespaces(0x%08lx,[%p])",
-               unshare_flags, current->nsproxy);
+ static inline struct nfs_page *
+diff -Nurb linux-2.6.22-590/include/linux/nfs_xdr.h linux-2.6.22-570/include/linux/nfs_xdr.h
+--- linux-2.6.22-590/include/linux/nfs_xdr.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/nfs_xdr.h   2007-07-08 19:32:17.000000000 -0400
+@@ -144,7 +144,6 @@
+       nfs4_stateid            delegation;
+       __u32                   do_recall;
+       __u64                   maxsize;
+-      __u32                   attrset[NFS4_BITMAP_SIZE];
+ };
  
--      if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
-+      if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
-+                             CLONE_NEWUSER | CLONE_NEWNET)))
-               return 0;
+ /*
+diff -Nurb linux-2.6.22-590/include/linux/nsproxy.h linux-2.6.22-570/include/linux/nsproxy.h
+--- linux-2.6.22-590/include/linux/nsproxy.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/nsproxy.h   2008-01-23 19:16:05.000000000 -0500
+@@ -10,12 +10,6 @@
+ struct ipc_namespace;
+ struct pid_namespace;
  
--#ifndef CONFIG_IPC_NS
--      if (unshare_flags & CLONE_NEWIPC)
--              return -EINVAL;
+-#ifdef CONFIG_CONTAINER_NS
+-int ns_container_clone(struct task_struct *tsk);
+-#else
+-static inline int ns_container_clone(struct task_struct *tsk) { return 0; }
 -#endif
 -
--#ifndef CONFIG_UTS_NS
--      if (unshare_flags & CLONE_NEWUTS)
-+#ifndef CONFIG_NET_NS
-+      if (unshare_flags & CLONE_NEWNET)
-               return -EINVAL;
- #endif
--
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
+ /*
+  * A structure to contain pointers to all per-process
+  * namespaces - fs (mount), uts, network, sysvipc, etc.
+@@ -35,12 +29,10 @@
+       struct ipc_namespace *ipc_ns;
+       struct mnt_namespace *mnt_ns;
+       struct pid_namespace *pid_ns;
+-      struct user_namespace *user_ns;
+-      struct net           *net_ns;
+ };
+ extern struct nsproxy init_nsproxy;
  
-       *new_nsp = create_new_namespaces(unshare_flags, current,
-                               new_fs ? new_fs : current->fs);
--      if (IS_ERR(*new_nsp))
-+      if (IS_ERR(*new_nsp)) {
-               err = PTR_ERR(*new_nsp);
-+              goto out;
-+      }
-+
-+      err = ns_container_clone(current);
-+      if (err)
-+              put_nsproxy(*new_nsp);
-+
-+out:
-       return err;
- }
-+
-+static int __init nsproxy_cache_init(void)
-+{
-+      nsproxy_cachep = kmem_cache_create("nsproxy", sizeof(struct nsproxy),
-+                                         0, SLAB_PANIC, NULL, NULL);
-+      return 0;
-+}
-+
-+module_init(nsproxy_cache_init);
-diff -Nurb linux-2.6.22-570/kernel/nsproxy.c.orig linux-2.6.22-590/kernel/nsproxy.c.orig
---- linux-2.6.22-570/kernel/nsproxy.c.orig     1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/kernel/nsproxy.c.orig     2008-01-02 13:56:37.000000000 -0500
-@@ -0,0 +1,264 @@
-+/*
-+ *  Copyright (C) 2006 IBM Corporation
-+ *
-+ *  Author: Serge Hallyn <serue@us.ibm.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, version 2 of the
-+ *  License.
-+ *
-+ *  Jun 2006 - namespaces support
-+ *             OpenVZ, SWsoft Inc.
-+ *             Pavel Emelianov <xemul@openvz.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/version.h>
-+#include <linux/nsproxy.h>
-+#include <linux/init_task.h>
-+#include <linux/mnt_namespace.h>
-+#include <linux/utsname.h>
-+#include <net/net_namespace.h>
-+#include <linux/pid_namespace.h>
-+#include <linux/vserver/global.h>
-+#include <linux/vserver/debug.h>
-+
-+static struct kmem_cache *nsproxy_cachep;
-+
-+struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
-+
-+void get_task_namespaces(struct task_struct *tsk)
-+{
-+      struct nsproxy *ns = tsk->nsproxy;
-+      if (ns) {
-+              get_nsproxy(ns);
-+      }
-+}
-+
-+/*
-+ * creates a copy of "orig" with refcount 1.
-+ */
-+static inline struct nsproxy *clone_nsproxy(struct nsproxy *orig)
-+{
-+      struct nsproxy *ns;
-+
-+      ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL);
-+      if (ns)
-+              atomic_set(&ns->count, 1);
-+      vxdprintk(VXD_CBIT(space, 2), "clone_nsproxy(%p[%u] = %p[1]",
-+              orig, atomic_read(&orig->count), ns);
-+      atomic_inc(&vs_global_nsproxy);
-+      return ns;
-+}
-+
-+/*
-+ * Create new nsproxy and all of its the associated namespaces.
-+ * Return the newly created nsproxy.  Do not attach this to the task,
-+ * leave it to the caller to do proper locking and attach it to task.
-+ */
-+static struct nsproxy *unshare_namespaces(int flags, struct nsproxy *orig,
-+                      struct fs_struct *new_fs)
-+{
-+      struct nsproxy *new_nsp;
-+      int err = -ENOMEM;
-+
-+      vxdprintk(VXD_CBIT(space, 4),
-+              "unshare_namespaces(0x%08x,%p,%p)",
-+              flags, orig, new_fs);
-+
-+      new_nsp = clone_nsproxy(orig);
-+      if (!new_nsp)
-+              return ERR_PTR(-ENOMEM);
-+
-+      new_nsp->mnt_ns = copy_mnt_ns(flags, orig->mnt_ns, new_fs);
-+      if (IS_ERR(new_nsp->mnt_ns))
-+              goto out_ns;
-+
-+      new_nsp->uts_ns = copy_utsname(flags, orig->uts_ns);
-+      if (IS_ERR(new_nsp->uts_ns))
-+              goto out_uts;
-+
-+      new_nsp->ipc_ns = copy_ipcs(flags, orig->ipc_ns);
-+      if (IS_ERR(new_nsp->ipc_ns))
-+              goto out_ipc;
-+
-+      new_nsp->pid_ns = copy_pid_ns(flags, orig->pid_ns);
-+      if (IS_ERR(new_nsp->pid_ns))
-+              goto out_pid;
-+
-+      new_nsp->user_ns = copy_user_ns(flags, orig->user_ns);
-+      if (IS_ERR(new_nsp->user_ns))
-+              goto out_user;
-+
-+      new_nsp->net_ns = copy_net_ns(flags, orig->net_ns);
-+      if (IS_ERR(new_nsp->net_ns))
-+              goto out_net;
-+
-+      return new_nsp;
-+
-+out_net:
-+      if (new_nsp->user_ns)
-+              put_user_ns(new_nsp->user_ns);
-+      if (new_nsp->net_ns)
-+              put_net(new_nsp->net_ns);
-+out_user:
-+      if (new_nsp->pid_ns)
-+              put_pid_ns(new_nsp->pid_ns);
-+out_pid:
-+      if (new_nsp->ipc_ns)
-+              put_ipc_ns(new_nsp->ipc_ns);
-+out_ipc:
-+      if (new_nsp->uts_ns)
-+              put_uts_ns(new_nsp->uts_ns);
-+out_uts:
-+      if (new_nsp->mnt_ns)
-+              put_mnt_ns(new_nsp->mnt_ns);
-+out_ns:
-+      kmem_cache_free(nsproxy_cachep, new_nsp);
-+      return ERR_PTR(err);
-+}
-+
-+static struct nsproxy *create_new_namespaces(unsigned long flags, struct task_struct *tsk,
-+                      struct fs_struct *new_fs)
-+{
-+      return unshare_namespaces(flags, tsk->nsproxy, new_fs);
-+}
-+
-+/*
-+ * copies the nsproxy, setting refcount to 1, and grabbing a
-+ * reference to all contained namespaces.
-+ */
-+struct nsproxy *copy_nsproxy(struct nsproxy *orig)
-+{
-+      struct nsproxy *ns = clone_nsproxy(orig);
-+
-+      if (ns) {
-+              if (ns->mnt_ns)
-+                      get_mnt_ns(ns->mnt_ns);
-+              if (ns->uts_ns)
-+                      get_uts_ns(ns->uts_ns);
-+              if (ns->ipc_ns)
-+                      get_ipc_ns(ns->ipc_ns);
-+              if (ns->pid_ns)
-+                      get_pid_ns(ns->pid_ns);
-+      }
-+      return ns;
-+}
-+
-+/*
-+ * called from clone.  This now handles copy for nsproxy and all
-+ * namespaces therein.
-+ */
-+int copy_namespaces(unsigned long flags, struct task_struct *tsk)
+-int copy_namespaces(unsigned long flags, struct task_struct *tsk);
++int copy_namespaces(int flags, struct task_struct *tsk);
+ struct nsproxy *copy_nsproxy(struct nsproxy *orig);
+ void get_task_namespaces(struct task_struct *tsk);
+ void free_nsproxy(struct nsproxy *ns);
+diff -Nurb linux-2.6.22-590/include/linux/pageblock-flags.h linux-2.6.22-570/include/linux/pageblock-flags.h
+--- linux-2.6.22-590/include/linux/pageblock-flags.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/pageblock-flags.h   1969-12-31 19:00:00.000000000 -0500
+@@ -1,52 +0,0 @@
+-/*
+- * Macros for manipulating and testing flags related to a
+- * MAX_ORDER_NR_PAGES block of pages.
+- *
+- * 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 version 2 of the License
+- *
+- * 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.
+- *
+- * Copyright (C) IBM Corporation, 2006
+- *
+- * Original author, Mel Gorman
+- * Major cleanups and reduction of bit operations, Andy Whitcroft
+- */
+-#ifndef PAGEBLOCK_FLAGS_H
+-#define PAGEBLOCK_FLAGS_H
+-
+-#include <linux/types.h>
+-
+-/* Macro to aid the definition of ranges of bits */
+-#define PB_range(name, required_bits) \
+-      name, name ## _end = (name + required_bits) - 1
+-
+-/* Bit indices that affect a whole block of pages */
+-enum pageblock_bits {
+-      PB_range(PB_migrate, 2), /* 2 bits required for migrate types */
+-      NR_PAGEBLOCK_BITS
+-};
+-
+-/* Forward declaration */
+-struct page;
+-
+-/* Declarations for getting and setting flags. See mm/page_alloc.c */
+-unsigned long get_pageblock_flags_group(struct page *page,
+-                                      int start_bitidx, int end_bitidx);
+-void set_pageblock_flags_group(struct page *page, unsigned long flags,
+-                                      int start_bitidx, int end_bitidx);
+-
+-#define get_pageblock_flags(page) \
+-                      get_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
+-#define set_pageblock_flags(page) \
+-                      set_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
+-
+-#endif        /* PAGEBLOCK_FLAGS_H */
+diff -Nurb linux-2.6.22-590/include/linux/pci_ids.h linux-2.6.22-570/include/linux/pci_ids.h
+--- linux-2.6.22-590/include/linux/pci_ids.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/pci_ids.h   2008-01-23 19:15:56.000000000 -0500
+@@ -2003,7 +2003,6 @@
+ #define PCI_VENDOR_ID_ENE             0x1524
+ #define PCI_DEVICE_ID_ENE_CB712_SD    0x0550
+-#define PCI_DEVICE_ID_ENE_CB712_SD_2  0x0551
+ #define PCI_DEVICE_ID_ENE_1211                0x1211
+ #define PCI_DEVICE_ID_ENE_1225                0x1225
+ #define PCI_DEVICE_ID_ENE_1410                0x1410
+diff -Nurb linux-2.6.22-590/include/linux/pid_namespace.h linux-2.6.22-570/include/linux/pid_namespace.h
+--- linux-2.6.22-590/include/linux/pid_namespace.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/pid_namespace.h     2007-07-08 19:32:17.000000000 -0400
+@@ -29,7 +29,7 @@
+       kref_get(&ns->kref);
+ }
+-extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns);
++extern struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *ns);
+ extern void free_pid_ns(struct kref *kref);
+ static inline void put_pid_ns(struct pid_namespace *ns)
+diff -Nurb linux-2.6.22-590/include/linux/pnp.h linux-2.6.22-570/include/linux/pnp.h
+--- linux-2.6.22-590/include/linux/pnp.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/pnp.h       2007-07-08 19:32:17.000000000 -0400
+@@ -335,10 +335,6 @@
+       int (*set)(struct pnp_dev *dev, struct pnp_resource_table *res);
+       int (*disable)(struct pnp_dev *dev);
+-      /* protocol specific suspend/resume */
+-      int (*suspend)(struct pnp_dev *dev, pm_message_t state);
+-      int (*resume)(struct pnp_dev *dev);
+-
+       /* used by pnp layer only (look but don't touch) */
+       unsigned char           number;         /* protocol number*/
+       struct device           dev;            /* link to driver model */
+diff -Nurb linux-2.6.22-590/include/linux/prctl.h linux-2.6.22-570/include/linux/prctl.h
+--- linux-2.6.22-590/include/linux/prctl.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/prctl.h     2007-07-08 19:32:17.000000000 -0400
+@@ -59,8 +59,4 @@
+ # define PR_ENDIAN_LITTLE     1       /* True little endian mode */
+ # define PR_ENDIAN_PPC_LITTLE 2       /* "PowerPC" pseudo little endian */
+-/* Get/set process seccomp mode */
+-#define PR_GET_SECCOMP        21
+-#define PR_SET_SECCOMP        22
+-
+ #endif /* _LINUX_PRCTL_H */
+diff -Nurb linux-2.6.22-590/include/linux/proc_fs.h linux-2.6.22-570/include/linux/proc_fs.h
+--- linux-2.6.22-590/include/linux/proc_fs.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/proc_fs.h   2008-01-23 19:16:05.000000000 -0500
+@@ -86,6 +86,8 @@
+ extern struct proc_dir_entry proc_root;
+ extern struct proc_dir_entry *proc_root_fs;
++extern struct proc_dir_entry *proc_net;
++extern struct proc_dir_entry *proc_net_stat;
+ extern struct proc_dir_entry *proc_bus;
+ extern struct proc_dir_entry *proc_root_driver;
+ extern struct proc_dir_entry *proc_root_kcore;
+@@ -103,6 +105,7 @@
+ unsigned long task_vsize(struct mm_struct *);
+ int task_statm(struct mm_struct *, int *, int *, int *, int *);
+ char *task_mem(struct mm_struct *, char *);
++void clear_refs_smap(struct mm_struct *mm);
+ struct proc_dir_entry *de_get(struct proc_dir_entry *de);
+ void de_put(struct proc_dir_entry *de);
+@@ -110,10 +113,6 @@
+ extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
+                                               struct proc_dir_entry *parent);
+ extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
+-static inline void remove_proc_pde(struct proc_dir_entry *pde)
+-{
+-      return remove_proc_entry(pde->name, pde->parent);
+-}
+ extern struct vfsmount *proc_mnt;
+ extern int proc_fill_super(struct super_block *,void *,int);
+@@ -183,18 +182,42 @@
+       return res;
+ }
+  
++static inline struct proc_dir_entry *proc_net_create(const char *name,
++      mode_t mode, get_info_t *get_info)
 +{
-+      struct nsproxy *old_ns = tsk->nsproxy;
-+      struct nsproxy *new_ns = NULL;
-+      int err = 0;
-+
-+      vxdprintk(VXD_CBIT(space, 7), "copy_namespaces(0x%08x,%p[%p])",
-+              flags, tsk, old_ns);
-+
-+      if (!old_ns)
-+              return 0;
-+
-+      get_nsproxy(old_ns);
-+      return 0;
-+
-+      if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER | CLONE_NEWNET)))
-+              return 0;
-+
-+       #ifndef CONFIG_NET_NS
-+              if (unshare_flags & CLONE_NEWNET)
-+                      return -EINVAL;
-+       #endif
-+
-+
-+      if (!capable(CAP_SYS_ADMIN)) {
-+              err = -EPERM;
-+              goto out;
-+      }
-+
-+      new_ns = create_new_namespaces(flags, tsk, tsk->fs);
-+      if (IS_ERR(new_ns)) {
-+              err = PTR_ERR(new_ns);
-+              goto out;
-+      }
-+
-+      err = ns_container_clone(tsk);
-+      if (err) {
-+              put_nsproxy(new_ns);
-+              goto out;
-+      }
-+
-+      tsk->nsproxy = new_ns;
-+
-+out:
-+      put_nsproxy(old_ns);
-+      vxdprintk(VXD_CBIT(space, 3),
-+              "copy_namespaces(0x%08x,%p[%p]) = %d [%p]",
-+              flags, tsk, old_ns, err, new_ns);
-+      return err;
++      return create_proc_info_entry(name,mode,proc_net,get_info);
 +}
 +
-+void free_nsproxy(struct nsproxy *ns)
++static inline struct proc_dir_entry *proc_net_fops_create(const char *name,
++      mode_t mode, const struct file_operations *fops)
 +{
-+      if (ns->mnt_ns)
-+              put_mnt_ns(ns->mnt_ns);
-+      if (ns->uts_ns)
-+              put_uts_ns(ns->uts_ns);
-+      if (ns->ipc_ns)
-+              put_ipc_ns(ns->ipc_ns);
-+      if (ns->pid_ns)
-+              put_pid_ns(ns->pid_ns);
-+      atomic_dec(&vs_global_nsproxy);
-+      kfree(ns);
++      struct proc_dir_entry *res = create_proc_entry(name, mode, proc_net);
++      if (res)
++              res->proc_fops = fops;
++      return res;
 +}
 +
-+/*
-+ * Called from unshare. Unshare all the namespaces part of nsproxy.
-+ * On success, returns the new nsproxy.
-+ */
-+int unshare_nsproxy_namespaces(unsigned long unshare_flags,
-+              struct nsproxy **new_nsp, struct fs_struct *new_fs)
++static inline void proc_net_remove(const char *name)
 +{
-+      int err = 0;
-+
-+      vxdprintk(VXD_CBIT(space, 4),
-+              "unshare_nsproxy_namespaces(0x%08lx,[%p])",
-+              unshare_flags, current->nsproxy);
-+
-+      if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
-+                             CLONE_NEWUSER | CLONE_NEWNET)))
-+              return 0;
-+
-+#ifndef CONFIG_NET_NS
-+      if (unshare_flags & CLONE_NEWNET)
-+              return -EINVAL;
-+#endif
-+      if (!capable(CAP_SYS_ADMIN))
-+              return -EPERM;
-+
-+      *new_nsp = create_new_namespaces(unshare_flags, current,
-+                              new_fs ? new_fs : current->fs);
-+      if (IS_ERR(*new_nsp)) {
-+              err = PTR_ERR(*new_nsp);
-+              goto out;
-+      }
-+
-+      err = ns_container_clone(current);
-+      if (err)
-+              put_nsproxy(*new_nsp);
-+
-+out:
-+      return err;
++      remove_proc_entry(name,proc_net);
 +}
 +
-+static int __init nsproxy_cache_init(void)
-+{
-+      nsproxy_cachep = kmem_cache_create("nsproxy", sizeof(struct nsproxy),
-+                                         0, SLAB_PANIC, NULL, NULL);
-+      return 0;
-+}
+ #else
+ #define proc_root_driver NULL
++#define proc_net NULL
+ #define proc_bus NULL
++#define proc_net_fops_create(name, mode, fops)  ({ (void)(mode), NULL; })
++#define proc_net_create(name, mode, info)     ({ (void)(mode), NULL; })
++static inline void proc_net_remove(const char *name) {}
 +
-+module_init(nsproxy_cache_init);
-diff -Nurb linux-2.6.22-570/kernel/params.c linux-2.6.22-590/kernel/params.c
---- linux-2.6.22-570/kernel/params.c   2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/kernel/params.c   2008-01-02 13:56:37.000000000 -0500
-@@ -491,7 +491,6 @@
-                       pattr->mattr.show = param_attr_show;
-                       pattr->mattr.store = param_attr_store;
-                       pattr->mattr.attr.name = (char *)&kp->name[name_skip];
--                      pattr->mattr.attr.owner = mk->mod;
-                       pattr->mattr.attr.mode = kp->perm;
-                       *(gattr++) = &(pattr++)->mattr.attr;
-               }
-diff -Nurb linux-2.6.22-570/kernel/pid.c linux-2.6.22-590/kernel/pid.c
---- linux-2.6.22-570/kernel/pid.c      2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/pid.c      2008-01-02 13:56:37.000000000 -0500
-@@ -379,7 +379,7 @@
+ static inline void proc_flush_task(struct task_struct *task) { }
+ static inline struct proc_dir_entry *create_proc_entry(const char *name,
+       mode_t mode, struct proc_dir_entry *parent) { return NULL; }
+ #define remove_proc_entry(name, parent) do {} while (0)
+-#define remove_proc_pde(PDE) do {} while (0)
+ static inline struct proc_dir_entry *proc_symlink(const char *name,
+               struct proc_dir_entry *parent,const char *dest) {return NULL;}
+diff -Nurb linux-2.6.22-590/include/linux/raid/raid5.h linux-2.6.22-570/include/linux/raid/raid5.h
+--- linux-2.6.22-590/include/linux/raid/raid5.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/raid/raid5.h        2007-07-08 19:32:17.000000000 -0400
+@@ -116,46 +116,13 @@
+  *  attach a request to an active stripe (add_stripe_bh())
+  *     lockdev attach-buffer unlockdev
+  *  handle a stripe (handle_stripe())
+- *     lockstripe clrSTRIPE_HANDLE ...
+- *            (lockdev check-buffers unlockdev) ..
+- *            change-state ..
+- *            record io/ops needed unlockstripe schedule io/ops
++ *     lockstripe clrSTRIPE_HANDLE ... (lockdev check-buffers unlockdev) .. change-state .. record io needed unlockstripe schedule io
+  *  release an active stripe (release_stripe())
+  *     lockdev if (!--cnt) { if  STRIPE_HANDLE, add to handle_list else add to inactive-list } unlockdev
+  *
+  * The refcount counts each thread that have activated the stripe,
+  * plus raid5d if it is handling it, plus one for each active request
+- * on a cached buffer, and plus one if the stripe is undergoing stripe
+- * operations.
+- *
+- * Stripe operations are performed outside the stripe lock,
+- * the stripe operations are:
+- * -copying data between the stripe cache and user application buffers
+- * -computing blocks to save a disk access, or to recover a missing block
+- * -updating the parity on a write operation (reconstruct write and
+- *  read-modify-write)
+- * -checking parity correctness
+- * -running i/o to disk
+- * These operations are carried out by raid5_run_ops which uses the async_tx
+- * api to (optionally) offload operations to dedicated hardware engines.
+- * When requesting an operation handle_stripe sets the pending bit for the
+- * operation and increments the count.  raid5_run_ops is then run whenever
+- * the count is non-zero.
+- * There are some critical dependencies between the operations that prevent some
+- * from being requested while another is in flight.
+- * 1/ Parity check operations destroy the in cache version of the parity block,
+- *    so we prevent parity dependent operations like writes and compute_blocks
+- *    from starting while a check is in progress.  Some dma engines can perform
+- *    the check without damaging the parity block, in these cases the parity
+- *    block is re-marked up to date (assuming the check was successful) and is
+- *    not re-read from disk.
+- * 2/ When a write operation is requested we immediately lock the affected
+- *    blocks, and mark them as not up to date.  This causes new read requests
+- *    to be held off, as well as parity checks and compute block operations.
+- * 3/ Once a compute block operation has been requested handle_stripe treats
+- *    that block as if it is up to date.  raid5_run_ops guaruntees that any
+- *    operation that is dependent on the compute block result is initiated after
+- *    the compute block completes.
++ * on a cached buffer.
+  */
+ struct stripe_head {
+@@ -169,46 +136,15 @@
+       spinlock_t              lock;
+       int                     bm_seq; /* sequence number for bitmap flushes */
+       int                     disks;                  /* disks in stripe */
+-      /* stripe_operations
+-       * @pending - pending ops flags (set for request->issue->complete)
+-       * @ack - submitted ops flags (set for issue->complete)
+-       * @complete - completed ops flags (set for complete)
+-       * @target - STRIPE_OP_COMPUTE_BLK target
+-       * @count - raid5_runs_ops is set to run when this is non-zero
+-       */
+-      struct stripe_operations {
+-              unsigned long      pending;
+-              unsigned long      ack;
+-              unsigned long      complete;
+-              int                target;
+-              int                count;
+-              u32                zero_sum_result;
+-      } ops;
+       struct r5dev {
+               struct bio      req;
+               struct bio_vec  vec;
+               struct page     *page;
+-              struct bio      *toread, *read, *towrite, *written;
++              struct bio      *toread, *towrite, *written;
+               sector_t        sector;                 /* sector of this page */
+               unsigned long   flags;
+       } dev[1]; /* allocated with extra space depending of RAID geometry */
+ };
+-
+-/* stripe_head_state - collects and tracks the dynamic state of a stripe_head
+- *     for handle_stripe.  It is only valid under spin_lock(sh->lock);
+- */
+-struct stripe_head_state {
+-      int syncing, expanding, expanded;
+-      int locked, uptodate, to_read, to_write, failed, written;
+-      int to_fill, compute, req_compute, non_overwrite, dirty;
+-      int failed_num;
+-};
+-
+-/* r6_state - extra state data only relevant to r6 */
+-struct r6_state {
+-      int p_failed, q_failed, qd_idx, failed_num[2];
+-};
+-
+ /* Flags */
+ #define       R5_UPTODATE     0       /* page contains current data */
+ #define       R5_LOCKED       1       /* IO has been submitted on "req" */
+@@ -222,15 +158,6 @@
+ #define       R5_ReWrite      9       /* have tried to over-write the readerror */
+ #define       R5_Expanded     10      /* This block now has post-expand data */
+-#define       R5_Wantcompute  11 /* compute_block in progress treat as
+-                                  * uptodate
+-                                  */
+-#define       R5_Wantfill     12 /* dev->toread contains a bio that needs
+-                                  * filling
+-                                  */
+-#define       R5_Wantprexor   13 /* distinguish blocks ready for rmw from
+-                                  * other "towrites"
+-                                  */
+ /*
+  * Write method
+  */
+@@ -253,24 +180,6 @@
+ #define       STRIPE_EXPAND_SOURCE    10
+ #define       STRIPE_EXPAND_READY     11
+ /*
+- * Operations flags (in issue order)
+- */
+-#define STRIPE_OP_BIOFILL     0
+-#define STRIPE_OP_COMPUTE_BLK 1
+-#define STRIPE_OP_PREXOR      2
+-#define STRIPE_OP_BIODRAIN    3
+-#define STRIPE_OP_POSTXOR     4
+-#define STRIPE_OP_CHECK       5
+-#define STRIPE_OP_IO          6
+-
+-/* modifiers to the base operations
+- * STRIPE_OP_MOD_REPAIR_PD - compute the parity block and write it back
+- * STRIPE_OP_MOD_DMA_CHECK - parity is not corrupted by the check
+- */
+-#define STRIPE_OP_MOD_REPAIR_PD 7
+-#define STRIPE_OP_MOD_DMA_CHECK 8
+-
+-/*
+  * Plugging:
+  *
+  * To improve write throughput, we need to delay the handling of some
+diff -Nurb linux-2.6.22-590/include/linux/raid/xor.h linux-2.6.22-570/include/linux/raid/xor.h
+--- linux-2.6.22-590/include/linux/raid/xor.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/raid/xor.h  2007-07-08 19:32:17.000000000 -0400
+@@ -3,10 +3,9 @@
+ #include <linux/raid/md.h>
+-#define MAX_XOR_BLOCKS 4
++#define MAX_XOR_BLOCKS 5
+-extern void xor_blocks(unsigned int count, unsigned int bytes,
+-      void *dest, void **srcs);
++extern void xor_block(unsigned int count, unsigned int bytes, void **ptr);
+ struct xor_block_template {
+         struct xor_block_template *next;
+diff -Nurb linux-2.6.22-590/include/linux/reboot.h linux-2.6.22-570/include/linux/reboot.h
+--- linux-2.6.22-590/include/linux/reboot.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/reboot.h    2007-07-08 19:32:17.000000000 -0400
+@@ -67,11 +67,6 @@
+ void ctrl_alt_del(void);
+-#define POWEROFF_CMD_PATH_LEN 256
+-extern char poweroff_cmd[POWEROFF_CMD_PATH_LEN];
+-
+-extern int orderly_poweroff(bool force);
+-
+ /*
+  * Emergency restart, callable from an interrupt handler.
+  */
+diff -Nurb linux-2.6.22-590/include/linux/revoked_fs_i.h linux-2.6.22-570/include/linux/revoked_fs_i.h
+--- linux-2.6.22-590/include/linux/revoked_fs_i.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/revoked_fs_i.h      1969-12-31 19:00:00.000000000 -0500
+@@ -1,18 +0,0 @@
+-#ifndef _LINUX_REVOKED_FS_I_H
+-#define _LINUX_REVOKED_FS_I_H
+-
+-struct revokefs_inode_info {
+-      struct task_struct *owner;
+-      struct file *file;
+-      unsigned int fd;
+-      struct inode vfs_inode;
+-};
+-
+-static inline struct revokefs_inode_info *revokefs_i(struct inode *inode)
+-{
+-      return container_of(inode, struct revokefs_inode_info, vfs_inode);
+-}
+-
+-void make_revoked_inode(struct inode *, int);
+-
+-#endif
+diff -Nurb linux-2.6.22-590/include/linux/rtnetlink.h linux-2.6.22-570/include/linux/rtnetlink.h
+--- linux-2.6.22-590/include/linux/rtnetlink.h 2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/rtnetlink.h 2007-07-08 19:32:17.000000000 -0400
+@@ -261,7 +261,7 @@
+       RTA_FLOW,
+       RTA_CACHEINFO,
+       RTA_SESSION,
+-      RTA_MP_ALGO, /* no longer used */
++      RTA_MP_ALGO,
+       RTA_TABLE,
+       __RTA_MAX
+ };
+@@ -570,21 +570,15 @@
  }
- EXPORT_SYMBOL_GPL(find_get_pid);
  
--struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *old_ns)
-+struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns)
- {
-       BUG_ON(!old_ns);
-       get_pid_ns(old_ns);
-diff -Nurb linux-2.6.22-570/kernel/ptrace.c linux-2.6.22-590/kernel/ptrace.c
---- linux-2.6.22-570/kernel/ptrace.c   2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/ptrace.c   2008-01-02 13:56:37.000000000 -0500
-@@ -143,7 +143,7 @@
-               return -EPERM;
-       smp_rmb();
-       if (task->mm)
--              dumpable = task->mm->dumpable;
-+              dumpable = get_dumpable(task->mm);
-       if (!dumpable && !capable(CAP_SYS_PTRACE))
-               return -EPERM;
-       if (!vx_check(task->xid, VS_ADMIN_P|VS_IDENT))
-diff -Nurb linux-2.6.22-570/kernel/rcutorture.c linux-2.6.22-590/kernel/rcutorture.c
---- linux-2.6.22-570/kernel/rcutorture.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/kernel/rcutorture.c       2008-01-02 13:56:37.000000000 -0500
-@@ -40,6 +40,7 @@
- #include <linux/moduleparam.h>
- #include <linux/percpu.h>
- #include <linux/notifier.h>
-+#include <linux/freezer.h>
- #include <linux/cpu.h>
- #include <linux/random.h>
- #include <linux/delay.h>
-@@ -518,7 +519,6 @@
+ extern int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len);
+-extern int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
+-                                      struct rtattr *rta, int len);
  
-       VERBOSE_PRINTK_STRING("rcu_torture_writer task started");
-       set_user_nice(current, 19);
--      current->flags |= PF_NOFREEZE;
+ #define rtattr_parse_nested(tb, max, rta) \
+       rtattr_parse((tb), (max), RTA_DATA((rta)), RTA_PAYLOAD((rta)))
  
-       do {
-               schedule_timeout_uninterruptible(1);
-@@ -558,7 +558,6 @@
+-#define rtattr_parse_nested_compat(tb, max, rta, data, len) \
+-({    data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \
+-      __rtattr_parse_nested_compat(tb, max, rta, len); })
+-
+-extern int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, u32 group, int echo);
+-extern int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid);
+-extern int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
++extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo);
++extern int rtnl_unicast(struct sk_buff *skb, u32 pid);
++extern int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
+                      struct nlmsghdr *nlh, gfp_t flags);
+-extern void rtnl_set_sk_err(struct net *net, u32 group, int error);
++extern void rtnl_set_sk_err(u32 group, int error);
+ extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics);
+ extern int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst,
+                             u32 id, u32 ts, u32 tsage, long expires,
+@@ -644,18 +638,6 @@
+ ({    (start)->rta_len = skb_tail_pointer(skb) - (unsigned char *)(start); \
+       (skb)->len; })
  
-       VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task started");
-       set_user_nice(current, 19);
--      current->flags |= PF_NOFREEZE;
+-#define RTA_NEST_COMPAT(skb, type, attrlen, data) \
+-({    struct rtattr *__start = (struct rtattr *)skb_tail_pointer(skb); \
+-      RTA_PUT(skb, type, attrlen, data); \
+-      RTA_NEST(skb, type); \
+-      __start; })
+-
+-#define RTA_NEST_COMPAT_END(skb, start) \
+-({    struct rtattr *__nest = (void *)(start) + NLMSG_ALIGN((start)->rta_len); \
+-      (start)->rta_len = skb_tail_pointer(skb) - (unsigned char *)(start); \
+-      RTA_NEST_END(skb, __nest); \
+-      (skb)->len; })
+-
+ #define RTA_NEST_CANCEL(skb, start) \
+ ({    if (start) \
+               skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
+diff -Nurb linux-2.6.22-590/include/linux/sched.h linux-2.6.22-570/include/linux/sched.h
+--- linux-2.6.22-590/include/linux/sched.h     2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/sched.h     2008-01-23 19:16:05.000000000 -0500
+@@ -26,9 +26,7 @@
+ #define CLONE_STOPPED         0x02000000      /* Start in stopped state */
+ #define CLONE_NEWUTS          0x04000000      /* New utsname group? */
+ #define CLONE_NEWIPC          0x08000000      /* New ipcs */
+-#define CLONE_NEWUSER         0x20000000      /* New user namespace */
+ #define CLONE_KTHREAD         0x10000000      /* clone a kernel thread */
+-#define CLONE_NEWNET          0x40000000      /* New network namespace */
  
-       do {
-               schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
-@@ -589,7 +588,6 @@
+ /*
+  * Scheduling policies
+@@ -268,7 +266,6 @@
+ asmlinkage void schedule(void);
  
-       VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
-       set_user_nice(current, 19);
--      current->flags |= PF_NOFREEZE;
+ struct nsproxy;
+-struct user_namespace;
  
-       do {
-               idx = cur_ops->readlock();
-diff -Nurb linux-2.6.22-570/kernel/rtmutex-tester.c linux-2.6.22-590/kernel/rtmutex-tester.c
---- linux-2.6.22-570/kernel/rtmutex-tester.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/kernel/rtmutex-tester.c   2008-01-02 13:56:37.000000000 -0500
-@@ -260,6 +260,7 @@
-       int ret;
+ /* Maximum number of active map areas.. This is a random (large) number */
+ #define DEFAULT_MAX_MAP_COUNT 65536
+@@ -328,27 +325,6 @@
+               (mm)->hiwater_vm = (mm)->total_vm;      \
+ } while (0)
  
-       current->flags |= PF_MUTEX_TESTER;
-+      set_freezable();
-       allow_signal(SIGHUP);
+-extern void set_dumpable(struct mm_struct *mm, int value);
+-extern int get_dumpable(struct mm_struct *mm);
+-
+-/* mm flags */
+-/* dumpable bits */
+-#define MMF_DUMPABLE      0  /* core dump is permitted */
+-#define MMF_DUMP_SECURELY 1  /* core file is readable only by root */
+-#define MMF_DUMPABLE_BITS 2
+-
+-/* coredump filter bits */
+-#define MMF_DUMP_ANON_PRIVATE 2
+-#define MMF_DUMP_ANON_SHARED  3
+-#define MMF_DUMP_MAPPED_PRIVATE       4
+-#define MMF_DUMP_MAPPED_SHARED        5
+-#define MMF_DUMP_FILTER_SHIFT MMF_DUMPABLE_BITS
+-#define MMF_DUMP_FILTER_BITS  4
+-#define MMF_DUMP_FILTER_MASK \
+-      (((1 << MMF_DUMP_FILTER_BITS) - 1) << MMF_DUMP_FILTER_SHIFT)
+-#define MMF_DUMP_FILTER_DEFAULT \
+-      ((1 << MMF_DUMP_ANON_PRIVATE) | (1 << MMF_DUMP_ANON_SHARED))
+-
+ struct mm_struct {
+       struct vm_area_struct * mmap;           /* list of VMAs */
+       struct rb_root mm_rb;
+@@ -407,7 +383,7 @@
+       unsigned int token_priority;
+       unsigned int last_interval;
  
-       for(;;) {
-diff -Nurb linux-2.6.22-570/kernel/sched.c linux-2.6.22-590/kernel/sched.c
---- linux-2.6.22-570/kernel/sched.c    2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/sched.c    2008-01-02 13:56:38.000000000 -0500
-@@ -51,8 +51,10 @@
- #include <linux/times.h>
- #include <linux/tsacct_kern.h>
- #include <linux/kprobes.h>
-+#include <linux/kgdb.h>
- #include <linux/delayacct.h>
- #include <linux/reciprocal_div.h>
-+#include <linux/cpu_acct.h>
+-      unsigned long flags; /* Must use atomic bitops to access the bits */
++      unsigned char dumpable:2;
  
- #include <asm/tlb.h>
- #include <asm/unistd.h>
-@@ -3399,9 +3401,16 @@
-       struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
-       struct vx_info *vxi = p->vx_info;  /* p is _always_ current */
-       cputime64_t tmp;
-+      struct rq *rq = this_rq();
-       int nice = (TASK_NICE(p) > 0);
+       /* coredumping support */
+       int core_waiters;
+@@ -781,6 +757,9 @@
+ #endif
+ };
  
-       p->utime = cputime_add(p->utime, cputime);
++extern int partition_sched_domains(cpumask_t *partition1,
++                                  cpumask_t *partition2);
 +
+ /*
+  * Maximum cache size the migration-costs auto-tuning code will
+  * search from:
+@@ -791,6 +770,8 @@
+ struct io_context;                    /* See blkdev.h */
++struct cpuset;
 +
-+      if (p != rq->idle)
-+              cpuacct_charge(p, cputime);
-+ 
+ #define NGROUPS_SMALL         32
+ #define NGROUPS_PER_BLOCK     ((int)(PAGE_SIZE / sizeof(gid_t)))
+ struct group_info {
+@@ -931,7 +912,7 @@
+       unsigned int rt_priority;
+       cputime_t utime, stime;
+       unsigned long nvcsw, nivcsw; /* context switch counts */
+-      struct timespec start_time, real_start_time;
++      struct timespec start_time;
+ /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
+       unsigned long min_flt, maj_flt;
+@@ -1086,16 +1067,11 @@
+       short il_next;
+ #endif
+ #ifdef CONFIG_CPUSETS
++      struct cpuset *cpuset;
+       nodemask_t mems_allowed;
+       int cpuset_mems_generation;
+       int cpuset_mem_spread_rotor;
+ #endif
+-#ifdef CONFIG_CONTAINERS
+-      /* Container info protected by css_group_lock */
+-      struct css_group *containers;
+-      /* cg_list protected by css_group_lock and tsk->alloc_lock */
+-      struct list_head cg_list;
+-#endif
+       struct robust_list_head __user *robust_list;
+ #ifdef CONFIG_COMPAT
+       struct compat_robust_list_head __user *compat_robust_list;
+@@ -1538,8 +1514,7 @@
+ /*
+  * Protects ->fs, ->files, ->mm, ->group_info, ->comm, keyring
+  * subscriptions and synchronises with wait4().  Also used in procfs.  Also
+- * pins the final release of task.io_context.  Also protects ->cpuset and
+- * ->container.subsys[].
++ * pins the final release of task.io_context.  Also protects ->cpuset.
+  *
+  * Nests both inside and outside of read_lock(&tasklist_lock).
+  * It must not be nested with write_lock_irq(&tasklist_lock),
+diff -Nurb linux-2.6.22-590/include/linux/seccomp.h linux-2.6.22-570/include/linux/seccomp.h
+--- linux-2.6.22-590/include/linux/seccomp.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/seccomp.h   2007-07-08 19:32:17.000000000 -0400
+@@ -4,6 +4,8 @@
+ #ifdef CONFIG_SECCOMP
++#define NR_SECCOMP_MODES 1
 +
-       vx_account_user(vxi, cputime, nice);
+ #include <linux/thread_info.h>
+ #include <asm/seccomp.h>
  
-       /* Add user time to cpustat. */
-@@ -3435,9 +3444,10 @@
-               cpustat->irq = cputime64_add(cpustat->irq, tmp);
-       else if (softirq_count())
-               cpustat->softirq = cputime64_add(cpustat->softirq, tmp);
--      else if (p != rq->idle)
-+      else if (p != rq->idle) {
-               cpustat->system = cputime64_add(cpustat->system, tmp);
--      else if (atomic_read(&rq->nr_iowait) > 0)
-+              cpuacct_charge(p, cputime);
-+      } else if (atomic_read(&rq->nr_iowait) > 0)
-               cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
-       else
-               cpustat->idle = cputime64_add(cpustat->idle, tmp);
-@@ -3462,8 +3472,10 @@
-                       cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
-               else
-                       cpustat->idle = cputime64_add(cpustat->idle, tmp);
--      } else
-+      } else {
-               cpustat->steal = cputime64_add(cpustat->steal, tmp);
-+              cpuacct_charge(p, -tmp);
-+      }
+@@ -21,9 +23,6 @@
+       return unlikely(test_ti_thread_flag(ti, TIF_SECCOMP));
  }
  
- static void task_running_tick(struct rq *rq, struct task_struct *p, int cpu)
-@@ -5287,8 +5299,6 @@
-               struct migration_req *req;
-               struct list_head *head;
--              try_to_freeze();
+-extern long prctl_get_seccomp(void);
+-extern long prctl_set_seccomp(unsigned long);
 -
-               spin_lock_irq(&rq->lock);
+ #else /* CONFIG_SECCOMP */
  
-               if (cpu_is_offline(cpu)) {
-@@ -5522,7 +5532,6 @@
-               p = kthread_create(migration_thread, hcpu, "migration/%d",cpu);
-               if (IS_ERR(p))
-                       return NOTIFY_BAD;
--              p->flags |= PF_NOFREEZE;
-               kthread_bind(p, cpu);
-               /* Must be high prio: stop_machine expects to yield to it. */
-               rq = task_rq_lock(p, &flags);
-@@ -6926,33 +6935,6 @@
-       arch_destroy_sched_domains(cpu_map);
+ typedef struct { } seccomp_t;
+@@ -35,16 +34,6 @@
+       return 0;
  }
  
--/*
-- * Partition sched domains as specified by the cpumasks below.
-- * This attaches all cpus from the cpumasks to the NULL domain,
-- * waits for a RCU quiescent period, recalculates sched
-- * domain information and then attaches them back to the
-- * correct sched domains
-- * Call with hotplug lock held
-- */
--int partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2)
+-static inline long prctl_get_seccomp(void)
 -{
--      cpumask_t change_map;
--      int err = 0;
--
--      cpus_and(*partition1, *partition1, cpu_online_map);
--      cpus_and(*partition2, *partition2, cpu_online_map);
--      cpus_or(change_map, *partition1, *partition2);
--
--      /* Detach sched domains from all of the affected cpus */
--      detach_destroy_domains(&change_map);
--      if (!cpus_empty(*partition1))
--              err = build_sched_domains(partition1);
--      if (!err && !cpus_empty(*partition2))
--              err = build_sched_domains(partition2);
+-      return -EINVAL;
+-}
 -
--      return err;
+-static inline long prctl_set_seccomp(unsigned long arg2)
+-{
+-      return -EINVAL;
 -}
 -
- #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
- int arch_reinit_sched_domains(void)
+ #endif /* CONFIG_SECCOMP */
+ #endif /* _LINUX_SECCOMP_H */
+diff -Nurb linux-2.6.22-590/include/linux/security.h linux-2.6.22-570/include/linux/security.h
+--- linux-2.6.22-590/include/linux/security.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/security.h  2007-07-08 19:32:17.000000000 -0400
+@@ -71,7 +71,6 @@
+ extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
+ extern int cap_netlink_recv(struct sk_buff *skb, int cap);
+-extern unsigned long mmap_min_addr;
+ /*
+  * Values used in the task_security_ops calls
+  */
+@@ -1242,9 +1241,8 @@
+       int (*file_ioctl) (struct file * file, unsigned int cmd,
+                          unsigned long arg);
+       int (*file_mmap) (struct file * file,
+-                        unsigned long reqprot, unsigned long prot,
+-                        unsigned long flags, unsigned long addr,
+-                        unsigned long addr_only);
++                        unsigned long reqprot,
++                        unsigned long prot, unsigned long flags);
+       int (*file_mprotect) (struct vm_area_struct * vma,
+                             unsigned long reqprot,
+                             unsigned long prot);
+@@ -1816,12 +1814,9 @@
+ static inline int security_file_mmap (struct file *file, unsigned long reqprot,
+                                     unsigned long prot,
+-                                    unsigned long flags,
+-                                    unsigned long addr,
+-                                    unsigned long addr_only)
++                                    unsigned long flags)
  {
-@@ -7177,6 +7159,9 @@
- #ifdef in_atomic
-       static unsigned long prev_jiffy;        /* ratelimiting */
+-      return security_ops->file_mmap (file, reqprot, prot, flags, addr,
+-                                      addr_only);
++      return security_ops->file_mmap (file, reqprot, prot, flags);
+ }
  
-+      if (atomic_read(&debugger_active))
-+              return;
-+
-       if ((in_atomic() || irqs_disabled()) &&
-           system_state == SYSTEM_RUNNING && !oops_in_progress) {
-               if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
-diff -Nurb linux-2.6.22-570/kernel/seccomp.c linux-2.6.22-590/kernel/seccomp.c
---- linux-2.6.22-570/kernel/seccomp.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/kernel/seccomp.c  2008-01-02 13:56:38.000000000 -0500
-@@ -10,6 +10,7 @@
- #include <linux/sched.h>
+ static inline int security_file_mprotect (struct vm_area_struct *vma,
+@@ -2494,9 +2489,7 @@
  
- /* #define SECCOMP_DEBUG 1 */
-+#define NR_SECCOMP_MODES 1
+ static inline int security_file_mmap (struct file *file, unsigned long reqprot,
+                                     unsigned long prot,
+-                                    unsigned long flags,
+-                                    unsigned long addr,
+-                                    unsigned long addr_only)
++                                    unsigned long flags)
+ {
+       return 0;
+ }
+diff -Nurb linux-2.6.22-590/include/linux/serial_8250.h linux-2.6.22-570/include/linux/serial_8250.h
+--- linux-2.6.22-590/include/linux/serial_8250.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/serial_8250.h       2007-07-08 19:32:17.000000000 -0400
+@@ -57,7 +57,6 @@
+ int serial8250_register_port(struct uart_port *);
+ void serial8250_unregister_port(int line);
+-void serial8250_unregister_by_port(struct uart_port *port);
+ void serial8250_suspend_port(int line);
+ void serial8250_resume_port(int line);
+diff -Nurb linux-2.6.22-590/include/linux/signal.h linux-2.6.22-570/include/linux/signal.h
+--- linux-2.6.22-590/include/linux/signal.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/signal.h    2007-07-08 19:32:17.000000000 -0400
+@@ -238,15 +238,12 @@
+ extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
+ extern long do_sigpending(void __user *, unsigned long);
+ extern int sigprocmask(int, sigset_t *, sigset_t *);
+-extern int show_unhandled_signals;
+ struct pt_regs;
+ extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
  
+ extern struct kmem_cache *sighand_cachep;
+-int unhandled_signal(struct task_struct *tsk, int sig);
+-
  /*
-  * Secure computing mode 1 allows only read/write/exit/sigreturn.
-@@ -54,3 +55,28 @@
- #endif
-       do_exit(SIGKILL);
- }
-+
-+long prctl_get_seccomp(void)
-+{
-+      return current->seccomp.mode;
-+}
-+
-+long prctl_set_seccomp(unsigned long seccomp_mode)
-+{
-+      long ret;
-+
-+      /* can set it only once to be even more secure */
-+      ret = -EPERM;
-+      if (unlikely(current->seccomp.mode))
-+              goto out;
-+
-+      ret = -EINVAL;
-+      if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
-+              current->seccomp.mode = seccomp_mode;
-+              set_thread_flag(TIF_SECCOMP);
-+              ret = 0;
-+      }
-+
-+ out:
-+      return ret;
-+}
-diff -Nurb linux-2.6.22-570/kernel/signal.c linux-2.6.22-590/kernel/signal.c
---- linux-2.6.22-570/kernel/signal.c   2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/signal.c   2008-01-02 13:56:38.000000000 -0500
-@@ -257,6 +257,16 @@
-       }
+  * In POSIX a signal is sent either to a specific thread (Linux task)
+  * or to the process as a whole (Linux thread group).  How the signal
+diff -Nurb linux-2.6.22-590/include/linux/skbuff.h linux-2.6.22-570/include/linux/skbuff.h
+--- linux-2.6.22-590/include/linux/skbuff.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/skbuff.h    2008-01-23 19:16:10.000000000 -0500
+@@ -147,8 +147,8 @@
+ /* We divide dataref into two halves.  The higher 16 bits hold references
+  * to the payload part of skb->data.  The lower 16 bits hold references to
+- * the entire skb->data.  A clone of a headerless skb holds the length of
+- * the header in skb->hdr_len.
++ * the entire skb->data.  It is up to the users of the skb to agree on
++ * where the payload starts.
+  *
+  * All users must obey the rule that the skb->data reference count must be
+  * greater than or equal to the payload reference count.
+@@ -206,7 +206,6 @@
+  *    @len: Length of actual data
+  *    @data_len: Data length
+  *    @mac_len: Length of link layer header
+- *    @hdr_len: writable header length of cloned skb
+  *    @csum: Checksum (must include start/offset pair)
+  *    @csum_start: Offset from skb->head where checksumming should start
+  *    @csum_offset: Offset from csum_start where checksum should be stored
+@@ -261,9 +260,8 @@
+       char                    cb[48];
+       unsigned int            len,
+-                              data_len;
+-      __u16                   mac_len,
+-                              hdr_len;
++                              data_len,
++                              mac_len;
+       union {
+               __wsum          csum;
+               struct {
+@@ -1325,20 +1323,6 @@
  }
  
-+int unhandled_signal(struct task_struct *tsk, int sig)
-+{
-+      if (is_init(tsk))
-+              return 1;
-+      if (tsk->ptrace & PT_PTRACED)
-+              return 0;
-+      return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) ||
-+              (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL);
-+}
-+
+ /**
+- *    skb_clone_writable - is the header of a clone writable
+- *    @skb: buffer to check
+- *    @len: length up to which to write
+- *
+- *    Returns true if modifying the header part of the cloned buffer
+- *    does not requires the data to be copied.
+- */
+-static inline int skb_clone_writable(struct sk_buff *skb, int len)
+-{
+-      return !skb_header_cloned(skb) &&
+-             skb_headroom(skb) + len <= skb->hdr_len;
+-}
+-
+-/**
+  *    skb_cow - copy header of skb when it is required
+  *    @skb: buffer to cow
+  *    @headroom: needed headroom
+diff -Nurb linux-2.6.22-590/include/linux/slab.h linux-2.6.22-570/include/linux/slab.h
+--- linux-2.6.22-590/include/linux/slab.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/slab.h      2007-07-08 19:32:17.000000000 -0400
+@@ -26,14 +26,12 @@
+ #define SLAB_HWCACHE_ALIGN    0x00002000UL    /* Align objs on cache lines */
+ #define SLAB_CACHE_DMA                0x00004000UL    /* Use GFP_DMA memory */
+ #define SLAB_STORE_USER               0x00010000UL    /* DEBUG: Store the last owner for bug hunting */
++#define SLAB_RECLAIM_ACCOUNT  0x00020000UL    /* Objects are reclaimable */
+ #define SLAB_PANIC            0x00040000UL    /* Panic if kmem_cache_create() fails */
+ #define SLAB_DESTROY_BY_RCU   0x00080000UL    /* Defer freeing slabs to RCU */
+ #define SLAB_MEM_SPREAD               0x00100000UL    /* Spread some memory over cpuset */
+ #define SLAB_TRACE            0x00200000UL    /* Trace allocations and frees */
  
- /* Notify the system that a driver wants to block all signals for this
-  * process, and wants to be notified if any signals at all were to be
-diff -Nurb linux-2.6.22-570/kernel/softirq.c linux-2.6.22-590/kernel/softirq.c
---- linux-2.6.22-570/kernel/softirq.c  2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/softirq.c  2008-01-02 13:56:38.000000000 -0500
-@@ -14,6 +14,7 @@
- #include <linux/notifier.h>
- #include <linux/percpu.h>
- #include <linux/cpu.h>
-+#include <linux/freezer.h>
- #include <linux/kthread.h>
- #include <linux/rcupdate.h>
- #include <linux/smp.h>
-@@ -304,11 +305,6 @@
-       if (!in_interrupt() && local_softirq_pending())
-               invoke_softirq();
+-/* The following flags affect the page allocator grouping pages by mobility */
+-#define SLAB_RECLAIM_ACCOUNT  0x00020000UL            /* Objects are reclaimable */
+-#define SLAB_TEMPORARY                SLAB_RECLAIM_ACCOUNT    /* Objects are short-lived */
+ /*
+  * struct kmem_cache related prototypes
+  */
+diff -Nurb linux-2.6.22-590/include/linux/socket.h linux-2.6.22-570/include/linux/socket.h
+--- linux-2.6.22-590/include/linux/socket.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/socket.h    2008-01-23 19:16:10.000000000 -0500
+@@ -24,6 +24,7 @@
+ #include <linux/types.h>              /* pid_t                        */
+ #include <linux/compiler.h>           /* __user                       */
++extern int sysctl_somaxconn;
+ #ifdef CONFIG_PROC_FS
+ struct seq_file;
+ extern void socket_seq_show(struct seq_file *seq);
+diff -Nurb linux-2.6.22-590/include/linux/string.h linux-2.6.22-570/include/linux/string.h
+--- linux-2.6.22-590/include/linux/string.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/string.h    2007-07-08 19:32:17.000000000 -0400
+@@ -105,12 +105,8 @@
+ #endif
  
--#ifdef CONFIG_NO_HZ
--      /* Make sure that timer wheel updates are propagated */
--      if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
--              tick_nohz_stop_sched_tick();
--#endif
-       preempt_enable_no_resched();
+ extern char *kstrdup(const char *s, gfp_t gfp);
+-extern char *kstrndup(const char *s, size_t len, gfp_t gfp);
+ extern void *kmemdup(const void *src, size_t len, gfp_t gfp);
+-extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
+-extern void argv_free(char **argv);
+-
+ #ifdef __cplusplus
  }
+ #endif
+diff -Nurb linux-2.6.22-590/include/linux/sunrpc/auth.h linux-2.6.22-570/include/linux/sunrpc/auth.h
+--- linux-2.6.22-590/include/linux/sunrpc/auth.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/sunrpc/auth.h       2008-01-23 19:16:05.000000000 -0500
+@@ -16,7 +16,6 @@
+ #include <linux/sunrpc/xdr.h>
  
-@@ -490,7 +486,6 @@
- static int ksoftirqd(void * __bind_cpu)
- {
-       set_user_nice(current, 19);
--      current->flags |= PF_NOFREEZE;
+ #include <asm/atomic.h>
+-#include <linux/rcupdate.h>
  
-       set_current_state(TASK_INTERRUPTIBLE);
+ /* size of the nodename buffer */
+ #define UNX_MAXNODENAME       32
+@@ -32,28 +31,22 @@
+ /*
+  * Client user credentials
+  */
+-struct rpc_auth;
+-struct rpc_credops;
+ struct rpc_cred {
+       struct hlist_node       cr_hash;        /* hash chain */
+-      struct list_head        cr_lru;         /* lru garbage collection */
+-      struct rcu_head         cr_rcu;
+-      struct rpc_auth *       cr_auth;
+-      const struct rpc_credops *cr_ops;
++      struct rpc_credops *    cr_ops;
++      unsigned long           cr_expire;      /* when to gc */
++      atomic_t                cr_count;       /* ref count */
++      unsigned short          cr_flags;       /* various flags */
+ #ifdef RPC_DEBUG
+       unsigned long           cr_magic;       /* 0x0f4aa4f0 */
+ #endif
+-      unsigned long           cr_expire;      /* when to gc */
+-      unsigned long           cr_flags;       /* various flags */
+-      atomic_t                cr_count;       /* ref count */
  
-diff -Nurb linux-2.6.22-570/kernel/softlockup.c linux-2.6.22-590/kernel/softlockup.c
---- linux-2.6.22-570/kernel/softlockup.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/kernel/softlockup.c       2008-01-02 13:56:38.000000000 -0500
-@@ -10,9 +10,11 @@
- #include <linux/cpu.h>
- #include <linux/init.h>
- #include <linux/delay.h>
-+#include <linux/freezer.h>
- #include <linux/kthread.h>
- #include <linux/notifier.h>
- #include <linux/module.h>
-+#include <linux/kgdb.h>
+       uid_t                   cr_uid;
  
- static DEFINE_SPINLOCK(print_lock);
+       /* per-flavor data */
+ };
+-#define RPCAUTH_CRED_NEW      0
+-#define RPCAUTH_CRED_UPTODATE 1
+-#define RPCAUTH_CRED_HASHED   2
++#define RPCAUTH_CRED_NEW      0x0001
++#define RPCAUTH_CRED_UPTODATE 0x0002
  
-@@ -47,6 +49,9 @@
- void touch_softlockup_watchdog(void)
- {
-       __raw_get_cpu_var(touch_timestamp) = get_timestamp();
-+#ifdef CONFIG_KGDB
-+      atomic_set(&kgdb_sync_softlockup[raw_smp_processor_id()], 0);
-+#endif
- }
- EXPORT_SYMBOL(touch_softlockup_watchdog);
+ #define RPCAUTH_CRED_MAGIC    0x0f4aa4f0
  
-@@ -116,7 +121,6 @@
-       struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+@@ -64,10 +57,10 @@
+ #define RPC_CREDCACHE_MASK    (RPC_CREDCACHE_NR - 1)
+ struct rpc_cred_cache {
+       struct hlist_head       hashtable[RPC_CREDCACHE_NR];
+-      spinlock_t              lock;
++      unsigned long           nextgc;         /* next garbage collection */
++      unsigned long           expire;         /* cache expiry interval */
+ };
  
-       sched_setscheduler(current, SCHED_FIFO, &param);
--      current->flags |= PF_NOFREEZE;
+-struct rpc_authops;
+ struct rpc_auth {
+       unsigned int            au_cslack;      /* call cred size estimate */
+                               /* guess at number of u32's auth adds before
+@@ -77,7 +70,7 @@
+       unsigned int            au_verfsize;
  
-       /* initialize timestamp */
-       touch_softlockup_watchdog();
-diff -Nurb linux-2.6.22-570/kernel/sys.c linux-2.6.22-590/kernel/sys.c
---- linux-2.6.22-570/kernel/sys.c      2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/sys.c      2008-01-02 13:56:38.000000000 -0500
-@@ -31,6 +31,7 @@
- #include <linux/cn_proc.h>
- #include <linux/getcpu.h>
- #include <linux/task_io_accounting_ops.h>
-+#include <linux/seccomp.h>
- #include <linux/cpu.h>
+       unsigned int            au_flags;       /* various flags */
+-      const struct rpc_authops *au_ops;               /* operations */
++      struct rpc_authops *    au_ops;         /* operations */
+       rpc_authflavor_t        au_flavor;      /* pseudoflavor (note may
+                                                * differ from the flavor in
+                                                * au_ops->au_flavor in gss
+@@ -123,19 +116,17 @@
+                                               void *, __be32 *, void *);
+ };
  
- #include <linux/compat.h>
-@@ -1043,7 +1044,7 @@
-                       return -EPERM;
-       }
-       if (new_egid != old_egid) {
--              current->mm->dumpable = suid_dumpable;
-+              set_dumpable(current->mm, suid_dumpable);
-               smp_wmb();
-       }
-       if (rgid != (gid_t) -1 ||
-@@ -1073,13 +1074,13 @@
+-extern const struct rpc_authops       authunix_ops;
+-extern const struct rpc_authops       authnull_ops;
+-
+-void __init           rpc_init_authunix(void);
+-void __init           rpcauth_init_module(void);
+-void __exit           rpcauth_remove_module(void);
++extern struct rpc_authops     authunix_ops;
++extern struct rpc_authops     authnull_ops;
++#ifdef CONFIG_SUNRPC_SECURE
++extern struct rpc_authops     authdes_ops;
++#endif
  
-       if (capable(CAP_SETGID)) {
-               if (old_egid != gid) {
--                      current->mm->dumpable = suid_dumpable;
-+                      set_dumpable(current->mm, suid_dumpable);
-                       smp_wmb();
-               }
-               current->gid = current->egid = current->sgid = current->fsgid = gid;
-       } else if ((gid == current->gid) || (gid == current->sgid)) {
-               if (old_egid != gid) {
--                      current->mm->dumpable = suid_dumpable;
-+                      set_dumpable(current->mm, suid_dumpable);
-                       smp_wmb();
-               }
-               current->egid = current->fsgid = gid;
-@@ -1110,7 +1111,7 @@
-       switch_uid(new_user);
+-int                   rpcauth_register(const struct rpc_authops *);
+-int                   rpcauth_unregister(const struct rpc_authops *);
++int                   rpcauth_register(struct rpc_authops *);
++int                   rpcauth_unregister(struct rpc_authops *);
+ struct rpc_auth *     rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
+-void                  rpcauth_release(struct rpc_auth *);
++void                  rpcauth_destroy(struct rpc_auth *);
+ struct rpc_cred *     rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
+-void                  rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
+ struct rpc_cred *     rpcauth_lookupcred(struct rpc_auth *, int);
+ struct rpc_cred *     rpcauth_bindcred(struct rpc_task *);
+ void                  rpcauth_holdcred(struct rpc_task *);
+@@ -148,9 +139,8 @@
+ int                   rpcauth_refreshcred(struct rpc_task *);
+ void                  rpcauth_invalcred(struct rpc_task *);
+ int                   rpcauth_uptodatecred(struct rpc_task *);
+-int                   rpcauth_init_credcache(struct rpc_auth *);
+-void                  rpcauth_destroy_credcache(struct rpc_auth *);
+-void                  rpcauth_clear_credcache(struct rpc_cred_cache *);
++int                   rpcauth_init_credcache(struct rpc_auth *, unsigned long);
++void                  rpcauth_free_credcache(struct rpc_auth *);
  
-       if (dumpclear) {
--              current->mm->dumpable = suid_dumpable;
-+              set_dumpable(current->mm, suid_dumpable);
-               smp_wmb();
-       }
-       current->uid = new_ruid;
-@@ -1166,7 +1167,7 @@
              return -EAGAIN;
+ static inline
+ struct rpc_cred *     get_rpccred(struct rpc_cred *cred)
+diff -Nurb linux-2.6.22-590/include/linux/sunrpc/auth_gss.h linux-2.6.22-570/include/linux/sunrpc/auth_gss.h
+--- linux-2.6.22-590/include/linux/sunrpc/auth_gss.h   2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/sunrpc/auth_gss.h   2007-07-08 19:32:17.000000000 -0400
+@@ -85,6 +85,11 @@
+       struct gss_upcall_msg   *gc_upcall;
};
  
-       if (new_euid != old_euid) {
--              current->mm->dumpable = suid_dumpable;
-+              set_dumpable(current->mm, suid_dumpable);
-               smp_wmb();
-       }
-       current->fsuid = current->euid = new_euid;
-@@ -1216,7 +1217,7 @@
-               return -EPERM;
++#define gc_uid                        gc_base.cr_uid
++#define gc_count              gc_base.cr_count
++#define gc_flags              gc_base.cr_flags
++#define gc_expire             gc_base.cr_expire
++
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_SUNRPC_AUTH_GSS_H */
  
-       if (old_euid != uid) {
--              current->mm->dumpable = suid_dumpable;
-+              set_dumpable(current->mm, suid_dumpable);
-               smp_wmb();
-       }
-       current->fsuid = current->euid = uid;
-@@ -1261,7 +1262,7 @@
-       }
-       if (euid != (uid_t) -1) {
-               if (euid != current->euid) {
--                      current->mm->dumpable = suid_dumpable;
-+                      set_dumpable(current->mm, suid_dumpable);
-                       smp_wmb();
-               }
-               current->euid = euid;
-@@ -1311,7 +1312,7 @@
-       }
-       if (egid != (gid_t) -1) {
-               if (egid != current->egid) {
--                      current->mm->dumpable = suid_dumpable;
-+                      set_dumpable(current->mm, suid_dumpable);
-                       smp_wmb();
-               }
-               current->egid = egid;
-@@ -1357,7 +1358,7 @@
-           uid == current->suid || uid == current->fsuid || 
-           capable(CAP_SETUID)) {
-               if (uid != old_fsuid) {
--                      current->mm->dumpable = suid_dumpable;
-+                      set_dumpable(current->mm, suid_dumpable);
-                       smp_wmb();
-               }
-               current->fsuid = uid;
-@@ -1386,7 +1387,7 @@
-           gid == current->sgid || gid == current->fsgid || 
-           capable(CAP_SETGID)) {
-               if (gid != old_fsgid) {
--                      current->mm->dumpable = suid_dumpable;
-+                      set_dumpable(current->mm, suid_dumpable);
-                       smp_wmb();
-               }
-               current->fsgid = gid;
-@@ -2185,14 +2186,14 @@
-                       error = put_user(current->pdeath_signal, (int __user *)arg2);
-                       break;
-               case PR_GET_DUMPABLE:
--                      error = current->mm->dumpable;
-+                      error = get_dumpable(current->mm);
-                       break;
-               case PR_SET_DUMPABLE:
-                       if (arg2 < 0 || arg2 > 1) {
-                               error = -EINVAL;
-                               break;
-                       }
--                      current->mm->dumpable = arg2;
-+                      set_dumpable(current->mm, arg2);
-                       break;
+diff -Nurb linux-2.6.22-590/include/linux/sunrpc/clnt.h linux-2.6.22-570/include/linux/sunrpc/clnt.h
+--- linux-2.6.22-590/include/linux/sunrpc/clnt.h       2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/sunrpc/clnt.h       2008-01-23 19:16:05.000000000 -0500
+@@ -24,10 +24,8 @@
+  * The high-level client handle
+  */
+ struct rpc_clnt {
+-      struct kref             cl_kref;        /* Number of references */
+-      struct list_head        cl_clients;     /* Global list of clients */
+-      struct list_head        cl_tasks;       /* List of tasks */
+-      spinlock_t              cl_lock;        /* spinlock */
++      atomic_t                cl_count;       /* Number of clones */
++      atomic_t                cl_users;       /* number of references */
+       struct rpc_xprt *       cl_xprt;        /* transport */
+       struct rpc_procinfo *   cl_procinfo;    /* procedure info */
+       u32                     cl_prog,        /* RPC program number */
+@@ -43,7 +41,10 @@
+       unsigned int            cl_softrtry : 1,/* soft timeouts */
+                               cl_intr     : 1,/* interruptible */
+                               cl_discrtry : 1,/* disconnect before retry */
+-                              cl_autobind : 1;/* use getport() */
++                              cl_autobind : 1,/* use getport() */
++                              cl_oneshot  : 1,/* dispose after use */
++                              cl_dead     : 1,/* abandoned */
++                              cl_tag      : 1;/* context tagging */
  
-               case PR_SET_UNALIGN:
-@@ -2261,6 +2262,13 @@
-                       error = SET_ENDIAN(current, arg2);
-                       break;
+       struct rpc_rtt *        cl_rtt;         /* RTO estimator data */
  
-+              case PR_GET_SECCOMP:
-+                      error = prctl_get_seccomp();
-+                      break;
-+              case PR_SET_SECCOMP:
-+                      error = prctl_set_seccomp(arg2);
-+                      break;
-+
-               default:
-                       error = -EINVAL;
-                       break;
-@@ -2297,3 +2305,61 @@
-       }
-       return err ? -EFAULT : 0;
- }
-+
-+char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
-+
-+static void argv_cleanup(char **argv, char **envp)
-+{
-+      argv_free(argv);
-+}
-+
-+/**
-+ * Trigger an orderly system poweroff
-+ * @force: force poweroff if command execution fails
-+ *
-+ * This may be called from any context to trigger a system shutdown.
-+ * If the orderly shutdown fails, it will force an immediate shutdown.
-+ */
-+int orderly_poweroff(bool force)
-+{
-+      int argc;
-+      char **argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc);
-+      static char *envp[] = {
-+              "HOME=/",
-+              "PATH=/sbin:/bin:/usr/sbin:/usr/bin",
-+              NULL
-+      };
-+      int ret = -ENOMEM;
-+      struct subprocess_info *info;
-+
-+      if (argv == NULL) {
-+              printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n",
-+                     __func__, poweroff_cmd);
-+              goto out;
-+      }
-+
-+      info = call_usermodehelper_setup(argv[0], argv, envp);
-+      if (info == NULL) {
-+              argv_free(argv);
-+              goto out;
-+      }
-+
-+      call_usermodehelper_setcleanup(info, argv_cleanup);
-+
-+      ret = call_usermodehelper_exec(info, UMH_NO_WAIT);
-+
-+  out:
-+      if (ret && force) {
-+              printk(KERN_WARNING "Failed to start orderly shutdown: "
-+                     "forcing the issue\n");
-+
-+              /* I guess this should try to kick off some daemon to
-+                 sync and poweroff asap.  Or not even bother syncing
-+                 if we're doing an emergency shutdown? */
-+              emergency_sync();
-+              kernel_power_off();
-+      }
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(orderly_poweroff);
-diff -Nurb linux-2.6.22-570/kernel/sysctl.c linux-2.6.22-590/kernel/sysctl.c
---- linux-2.6.22-570/kernel/sysctl.c   2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/sysctl.c   2008-01-02 13:56:38.000000000 -0500
-@@ -45,13 +45,13 @@
- #include <linux/syscalls.h>
- #include <linux/nfs_fs.h>
- #include <linux/acpi.h>
-+#include <linux/reboot.h>
-+#include <linux/fs.h>
-+#include <net/net_namespace.h>
+@@ -110,15 +111,17 @@
+ #define RPC_CLNT_CREATE_HARDRTRY      (1UL << 0)
+ #define RPC_CLNT_CREATE_INTR          (1UL << 1)
+ #define RPC_CLNT_CREATE_AUTOBIND      (1UL << 2)
+-#define RPC_CLNT_CREATE_NONPRIVPORT   (1UL << 3)
+-#define RPC_CLNT_CREATE_NOPING                (1UL << 4)
+-#define RPC_CLNT_CREATE_DISCRTRY      (1UL << 5)
++#define RPC_CLNT_CREATE_ONESHOT               (1UL << 3)
++#define RPC_CLNT_CREATE_NONPRIVPORT   (1UL << 4)
++#define RPC_CLNT_CREATE_NOPING                (1UL << 5)
++#define RPC_CLNT_CREATE_DISCRTRY      (1UL << 6)
  
- #include <asm/uaccess.h>
- #include <asm/processor.h>
+ struct rpc_clnt *rpc_create(struct rpc_create_args *args);
+ struct rpc_clnt       *rpc_bind_new_program(struct rpc_clnt *,
+                               struct rpc_program *, int);
+ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
+-void          rpc_shutdown_client(struct rpc_clnt *);
++int           rpc_shutdown_client(struct rpc_clnt *);
++int           rpc_destroy_client(struct rpc_clnt *);
+ void          rpc_release_client(struct rpc_clnt *);
+ int           rpcb_register(u32, u32, int, unsigned short, int *);
+ void          rpcb_getport(struct rpc_task *);
+@@ -130,14 +133,13 @@
+                              void *calldata);
+ int           rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
+                             int flags);
+-struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
+-                             int flags);
+ void          rpc_restart_call(struct rpc_task *);
+ void          rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
+ void          rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
+ void          rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
+ size_t                rpc_max_payload(struct rpc_clnt *);
+ void          rpc_force_rebind(struct rpc_clnt *);
++int           rpc_ping(struct rpc_clnt *clnt, int flags);
+ size_t                rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);
+ char *                rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t);
  
--extern int proc_nr_files(ctl_table *table, int write, struct file *filp,
--                     void __user *buffer, size_t *lenp, loff_t *ppos);
--
- #ifdef CONFIG_X86
- #include <asm/nmi.h>
- #include <asm/stacktrace.h>
-@@ -140,6 +140,10 @@
-                              void __user *buffer, size_t *lenp, loff_t *ppos);
- #endif
+diff -Nurb linux-2.6.22-590/include/linux/sunrpc/gss_api.h linux-2.6.22-570/include/linux/sunrpc/gss_api.h
+--- linux-2.6.22-590/include/linux/sunrpc/gss_api.h    2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/sunrpc/gss_api.h    2007-07-08 19:32:17.000000000 -0400
+@@ -77,7 +77,7 @@
+       struct module           *gm_owner;
+       struct xdr_netobj       gm_oid;
+       char                    *gm_name;
+-      const struct gss_api_ops *gm_ops;
++      struct gss_api_ops      *gm_ops;
+       /* pseudoflavors supported by this mechanism: */
+       int                     gm_pf_num;
+       struct pf_desc *        gm_pfs;
+diff -Nurb linux-2.6.22-590/include/linux/sunrpc/rpc_pipe_fs.h linux-2.6.22-570/include/linux/sunrpc/rpc_pipe_fs.h
+--- linux-2.6.22-590/include/linux/sunrpc/rpc_pipe_fs.h        2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/sunrpc/rpc_pipe_fs.h        2007-07-08 19:32:17.000000000 -0400
+@@ -23,11 +23,9 @@
+       void *private;
+       struct list_head pipe;
+       struct list_head in_upcall;
+-      struct list_head in_downcall;
+       int pipelen;
+       int nreaders;
+       int nwriters;
+-      int nkern_readwriters;
+       wait_queue_head_t waitq;
+ #define RPC_PIPE_WAIT_FOR_OPEN        1
+       int flags;
+diff -Nurb linux-2.6.22-590/include/linux/sunrpc/sched.h linux-2.6.22-570/include/linux/sunrpc/sched.h
+--- linux-2.6.22-590/include/linux/sunrpc/sched.h      2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/sunrpc/sched.h      2007-07-08 19:32:17.000000000 -0400
+@@ -110,6 +110,11 @@
+       if (!list_empty(head) &&  \
+           ((task=list_entry((head)->next, struct rpc_task, u.tk_wait.list)),1))
  
-+#ifdef CONFIG_NET
-+static void sysctl_net_init(struct net *net);
-+#endif
++/* .. and walking list of all tasks */
++#define       alltask_for_each(task, pos, head) \
++      list_for_each(pos, head) \
++              if ((task=list_entry(pos, struct rpc_task, tk_task)),1)
 +
- static ctl_table root_table[];
- static struct ctl_table_header root_table_header =
-       { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) };
-@@ -203,7 +207,10 @@
-               .mode           = 0555,
-               .child          = dev_table,
-       },
--
-+/*
-+ * NOTE: do not add new entries to this table unless you have read
-+ * Documentation/sysctl/ctl_unnumbered.txt
-+ */
-       { .ctl_name = 0 }
- };
+ typedef void                  (*rpc_action)(struct rpc_task *);
  
-@@ -217,6 +224,15 @@
-               .proc_handler   = &proc_dointvec,
-       },
-       {
-+              .ctl_name       = KERN_POWEROFF_CMD,
-+              .procname       = "poweroff_cmd",
-+              .data           = &poweroff_cmd,
-+              .maxlen         = POWEROFF_CMD_PATH_LEN,
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dostring,
-+              .strategy       = &sysctl_string,
-+      },
-+      {
-               .ctl_name       = KERN_CORE_USES_PID,
-               .procname       = "core_uses_pid",
-               .data           = &core_uses_pid,
-@@ -625,7 +641,20 @@
-               .proc_handler   = &proc_dointvec,
-       },
- #endif
+ struct rpc_call_ops {
+diff -Nurb linux-2.6.22-590/include/linux/syscalls.h linux-2.6.22-570/include/linux/syscalls.h
+--- linux-2.6.22-590/include/linux/syscalls.h  2008-01-23 19:16:20.000000000 -0500
++++ linux-2.6.22-570/include/linux/syscalls.h  2008-01-23 19:16:05.000000000 -0500
+@@ -110,9 +110,6 @@
+ asmlinkage long sys_capset(cap_user_header_t header,
+                               const cap_user_data_t data);
+ asmlinkage long sys_personality(u_long personality);
+-asmlinkage long sys_sync_file_range2(int fd, unsigned int flags,
+-                                   loff_t offset, loff_t nbytes);
 -
-+#ifdef CONFIG_SECURITY
-+      {
-+              .ctl_name       = CTL_UNNUMBERED,
-+              .procname       = "mmap_min_addr",
-+              .data           = &mmap_min_addr,
-+              .maxlen         = sizeof(unsigned long),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_doulongvec_minmax,
-+      },
-+#endif
-+/*
-+ * NOTE: do not add new entries to this table unless you have read
-+ * Documentation/sysctl/ctl_unnumbered.txt
-+ */
-       { .ctl_name = 0 }
- };
  
-@@ -744,6 +773,14 @@
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-        },
-+       {
-+              .ctl_name       = VM_HUGETLB_TREAT_MOVABLE,
-+              .procname       = "hugepages_treat_as_movable",
-+              .data           = &hugepages_treat_as_movable,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &hugetlb_treat_movable_handler,
-+      },
- #endif
-       {
-               .ctl_name       = VM_LOWMEM_RESERVE_RATIO,
-@@ -892,6 +929,10 @@
-               .extra1         = &zero,
-       },
- #endif
-+/*
-+ * NOTE: do not add new entries to this table unless you have read
-+ * Documentation/sysctl/ctl_unnumbered.txt
-+ */
-       { .ctl_name = 0 }
- };
+ asmlinkage long sys_sigpending(old_sigset_t __user *set);
+ asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set,
+@@ -615,11 +612,7 @@
+ asmlinkage long sys_timerfd(int ufd, int clockid, int flags,
+                           const struct itimerspec __user *utmr);
+ asmlinkage long sys_eventfd(unsigned int count);
+-asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len);
  
-@@ -1032,10 +1073,28 @@
-               .child          = binfmt_misc_table,
-       },
+ int kernel_execve(const char *filename, char *const argv[], char *const envp[]);
+-asmlinkage long sys_revokeat(int dfd, const char __user *filename);
+-asmlinkage long sys_frevoke(unsigned int fd);
+-
  #endif
-+/*
-+ * NOTE: do not add new entries to this table unless you have read
-+ * Documentation/sysctl/ctl_unnumbered.txt
-+ */
-       { .ctl_name = 0 }
+diff -Nurb linux-2.6.22-590/include/linux/sysctl.h linux-2.6.22-570/include/linux/sysctl.h
+--- linux-2.6.22-590/include/linux/sysctl.h    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/linux/sysctl.h    2008-01-23 19:16:09.000000000 -0500
+@@ -31,7 +31,6 @@
+ struct file;
+ struct completion;
+-struct net;
+ #define CTL_MAXNAME 10                /* how many path components do we allow in a
+                                  call to sysctl?   In other words, what is
+@@ -167,7 +166,6 @@
+       KERN_MAX_LOCK_DEPTH=74,
+       KERN_NMI_WATCHDOG=75, /* int: enable/disable nmi watchdog */
+       KERN_PANIC_ON_NMI=76, /* int: whether we will panic on an unrecovered */
+-      KERN_POWEROFF_CMD=77,   /* string: poweroff command line */
  };
  
- static ctl_table debug_table[] = {
-+#ifdef CONFIG_X86
-+      {
-+              .ctl_name       = DEBUG_UNHANDLED_SIGNALS,
-+              .procname       = "show-unhandled-signals",
-+              .data           = &show_unhandled_signals,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = proc_dointvec
-+      },
-+#endif
-+/*
-+ * NOTE: do not add new entries to this table unless you have read
-+ * Documentation/sysctl/ctl_unnumbered.txt
-+ */
-       { .ctl_name = 0 }
+@@ -210,7 +208,6 @@
+       VM_PANIC_ON_OOM=33,     /* panic at out-of-memory */
+       VM_VDSO_ENABLED=34,     /* map VDSO into new processes? */
+       VM_MIN_SLAB=35,          /* Percent pages ignored by zone reclaim */
+-      VM_HUGETLB_TREAT_MOVABLE=36, /* Allocate hugepages from ZONE_MOVABLE */
+       /* s390 vm cmm sysctls */
+       VM_CMM_PAGES=1111,
+@@ -846,9 +843,6 @@
  };
  
-@@ -1097,6 +1156,11 @@
- {
-       struct ctl_table_header *head;
-       struct list_head *tmp;
-+      struct net *net = current->nsproxy->net_ns;
-+
-+      if (!net->net_table_header.ctl_table)
-+              sysctl_net_init(net);
-+
-       spin_lock(&sysctl_lock);
-       if (prev) {
-               tmp = &prev->ctl_entry;
-@@ -1114,6 +1178,10 @@
-       next:
-               tmp = tmp->next;
-               if (tmp == &root_table_header.ctl_entry)
-+#ifdef CONFIG_NET
-+                      tmp = &net->net_table_header.ctl_entry;
-+              else if (tmp == &net->net_table_header.ctl_entry)
-+#endif
-                       break;
-       }
-       spin_unlock(&sysctl_lock);
-@@ -1229,7 +1297,6 @@
-                       void __user *newval, size_t newlen)
- {
-       int op = 0, rc;
--      size_t len;
+ /* CTL_DEBUG names: */
+-enum {
+-      DEBUG_UNHANDLED_SIGNALS = 1,
+-};
  
-       if (oldval)
-               op |= 004;
-@@ -1250,25 +1317,10 @@
-       /* If there is no strategy routine, or if the strategy returns
-        * zero, proceed with automatic r/w */
-       if (table->data && table->maxlen) {
--              if (oldval && oldlenp) {
--                      if (get_user(len, oldlenp))
--                              return -EFAULT;
--                      if (len) {
--                              if (len > table->maxlen)
--                                      len = table->maxlen;
--                              if(copy_to_user(oldval, table->data, len))
--                                      return -EFAULT;
--                              if(put_user(len, oldlenp))
--                                      return -EFAULT;
--                      }
--              }
--              if (newval && newlen) {
--                      len = newlen;
--                      if (len > table->maxlen)
--                              len = table->maxlen;
--                      if(copy_from_user(table->data, newval, len))
--                              return -EFAULT;
--              }
-+              rc = sysctl_data(table, name, nlen, oldval, oldlenp,
-+                               newval, newlen);
-+              if (rc < 0)
-+                      return rc;
-       }
-       return 0;
+ /* CTL_DEV names: */
+ enum {
+@@ -986,7 +980,6 @@
+                              void __user *oldval, size_t __user *oldlenp,
+                              void __user *newval, size_t newlen);
+-extern ctl_handler sysctl_data;
+ extern ctl_handler sysctl_string;
+ extern ctl_handler sysctl_intvec;
+ extern ctl_handler sysctl_jiffies;
+@@ -1063,12 +1056,6 @@
+ void unregister_sysctl_table(struct ctl_table_header * table);
+-#ifdef CONFIG_NET
+-extern struct ctl_table_header *register_net_sysctl_table(struct net *net, struct ctl_table *table);
+-extern void unregister_net_sysctl_table(struct ctl_table_header *header);
+-extern ctl_table net_root_table[];
+-#endif
+-
+ #else /* __KERNEL__ */
+ #endif /* __KERNEL__ */
+diff -Nurb linux-2.6.22-590/include/linux/sysdev.h linux-2.6.22-570/include/linux/sysdev.h
+--- linux-2.6.22-590/include/linux/sysdev.h    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/linux/sysdev.h    2007-07-08 19:32:17.000000000 -0400
+@@ -101,7 +101,8 @@
+ #define _SYSDEV_ATTR(_name,_mode,_show,_store)                        \
+ {                                                             \
+-      .attr = { .name = __stringify(_name), .mode = _mode },  \
++      .attr = { .name = __stringify(_name), .mode = _mode,    \
++               .owner = THIS_MODULE },                        \
+       .show   = _show,                                        \
+       .store  = _store,                                       \
  }
-@@ -1359,7 +1411,8 @@
-  * This routine returns %NULL on a failure to register, and a pointer
-  * to the table header on success.
+diff -Nurb linux-2.6.22-590/include/linux/sysfs.h linux-2.6.22-570/include/linux/sysfs.h
+--- linux-2.6.22-590/include/linux/sysfs.h     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/linux/sysfs.h     2008-01-23 19:16:05.000000000 -0500
+@@ -19,11 +19,9 @@
+ struct kobject;
+ struct module;
++struct nameidata;
++struct dentry;
+-/* FIXME
+- * The *owner field is no longer used, but leave around
+- * until the tree gets cleaned up fully.
+- */
+ struct attribute {
+       const char              * name;
+       struct module           * owner;
+@@ -43,13 +41,13 @@
   */
--struct ctl_table_header *register_sysctl_table(ctl_table * table)
-+static struct ctl_table_header *__register_sysctl_table(
-+      struct ctl_table_header *root, ctl_table * table)
- {
-       struct ctl_table_header *tmp;
-       tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
-@@ -1371,11 +1424,16 @@
-       tmp->unregistering = NULL;
-       sysctl_set_parent(NULL, table);
-       spin_lock(&sysctl_lock);
--      list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
-+      list_add_tail(&tmp->ctl_entry, &root->ctl_entry);
-       spin_unlock(&sysctl_lock);
-       return tmp;
+ #define __ATTR(_name,_mode,_show,_store) { \
+-      .attr = {.name = __stringify(_name), .mode = _mode },   \
++      .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },     \
+       .show   = _show,                                        \
+       .store  = _store,                                       \
  }
  
-+struct ctl_table_header *register_sysctl_table(ctl_table *table)
-+{
-+      return __register_sysctl_table(&root_table_header, table);
-+}
-+
- /**
-  * unregister_sysctl_table - unregister a sysctl table hierarchy
-  * @header: the header returned from register_sysctl_table
-@@ -1392,6 +1450,92 @@
-       kfree(header);
+ #define __ATTR_RO(_name) { \
+-      .attr   = { .name = __stringify(_name), .mode = 0444 }, \
++      .attr   = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE },   \
+       .show   = _name##_show, \
  }
  
-+#ifdef CONFIG_NET
-+
-+static void *fixup_table_addr(void *addr,
-+                            const char *start, size_t size, const char *new)
-+{
-+      char *ptr = addr;
-+      if ((ptr >= start) && (ptr < (start + size)))
-+              ptr += new - start;
-+      return ptr;
-+}
-+
-+static void table_fixup(struct ctl_table *table,
-+                      const void *start, size_t size, const void *new)
-+{
-+      for (; table->ctl_name || table->procname; table++) {
-+              table->data   = fixup_table_addr(table->data, start, size, new);
-+              table->extra1 = fixup_table_addr(table->extra1, start, size, new);
-+              table->extra2 = fixup_table_addr(table->extra2, start, size, new);
-+
-+              /* Whee recursive functions on the kernel stack */
-+              if (table->child)
-+                      table_fixup(table->child, start, size, new);
-+      }
-+}
-+
-+static unsigned count_table_entries(struct ctl_table *table)
-+{
-+      unsigned entries = 0;
-+      for (; table->ctl_name || table->procname; table++) {
-+              entries += 1;
-+
-+              if (table->child)
-+                      entries += count_table_entries(table->child);
-+      }
-+      entries += 1; /* Null terminating entry */
-+      return entries;
-+}
-+
-+static struct ctl_table *copy_table_entries(
-+      struct ctl_table *dest, struct ctl_table *src)
-+{
-+      struct ctl_table *table = dest;
-+      for (; src->ctl_name || src->procname; src++) {
-+              *dest++ = *table;
-+      }
-+      dest++; /* Null terminating entry */
-+      for (; table->ctl_name || table->procname; table++) {
-+              if (table->child)
-+                      dest = copy_table_entries(dest, table->child);
-+      }
-+      return dest;
-+}
-+
-+static void sysctl_net_init(struct net *net)
-+{
-+      unsigned entries;
-+      struct ctl_table *table;
-+      
-+      entries = count_table_entries(net_root_table);
-+      table = kzalloc(GFP_KERNEL, sizeof(*table)*entries);
-+      /* FIXME free table... */
-+
-+      copy_table_entries(table, net_root_table);
-+      table_fixup(table, &init_net, sizeof(init_net), net);
-+
-+      net->net_table_header.ctl_table = table;
-+      INIT_LIST_HEAD(&net->net_table_header.ctl_entry);
-+}
-+
-+struct ctl_table_header *register_net_sysctl_table(struct net *net, struct ctl_table *table)
-+{
-+      if (!net->net_table_header.ctl_table)
-+              sysctl_net_init(net);
-+      table_fixup(table, &init_net, sizeof(init_net), net);
-+      return __register_sysctl_table(&net->net_table_header, table);
-+}
-+EXPORT_SYMBOL_GPL(register_net_sysctl_table);
-+
-+void unregister_net_sysctl_table(struct ctl_table_header *header)
-+{
-+      return unregister_sysctl_table(header);
-+}
-+EXPORT_SYMBOL_GPL(unregister_net_sysctl_table);
-+#endif
-+
-+
- #else /* !CONFIG_SYSCTL */
- struct ctl_table_header *register_sysctl_table(ctl_table * table)
- {
-@@ -2167,6 +2311,40 @@
-  * General sysctl support routines 
-  */
+@@ -63,10 +61,8 @@
+       struct attribute        attr;
+       size_t                  size;
+       void                    *private;
+-      ssize_t (*read)(struct kobject *, struct bin_attribute *,
+-                      char *, loff_t, size_t);
+-      ssize_t (*write)(struct kobject *, struct bin_attribute *,
+-                       char *, loff_t, size_t);
++      ssize_t (*read)(struct kobject *, char *, loff_t, size_t);
++      ssize_t (*write)(struct kobject *, char *, loff_t, size_t);
+       int (*mmap)(struct kobject *, struct bin_attribute *attr,
+                   struct vm_area_struct *vma);
+ };
+@@ -76,23 +72,12 @@
+       ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
+ };
+-struct shadow_dir_operations {
+-      const void *(*current_tag)(void);
+-      const void *(*kobject_tag)(struct kobject *kobj);
+-};
+-
+-#define SYSFS_TYPE_MASK               0x00ff
+ #define SYSFS_ROOT            0x0001
+ #define SYSFS_DIR             0x0002
+ #define SYSFS_KOBJ_ATTR       0x0004
+ #define SYSFS_KOBJ_BIN_ATTR   0x0008
+ #define SYSFS_KOBJ_LINK       0x0020
+-#define SYSFS_SHADOW_DIR      0x0040
+-#define SYSFS_COPY_NAME               (SYSFS_DIR | SYSFS_KOBJ_LINK)
+-
+-#define SYSFS_FLAG_MASK               ~SYSFS_TYPE_MASK
+-#define SYSFS_FLAG_REMOVED    0x0100
+-#define SYSFS_FLAG_SHADOWED   0x0200
++#define SYSFS_NOT_PINNED      (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK)
+ #ifdef CONFIG_SYSFS
+@@ -100,13 +85,13 @@
+               void (*func)(void *), void *data, struct module *owner);
+ extern int __must_check
+-sysfs_create_dir(struct kobject *);
++sysfs_create_dir(struct kobject *, struct dentry *);
+ extern void
+ sysfs_remove_dir(struct kobject *);
+ extern int __must_check
+-sysfs_rename_dir(struct kobject *kobj, const char *new_name);
++sysfs_rename_dir(struct kobject *, struct dentry *, const char *new_name);
+ extern int __must_check
+ sysfs_move_dir(struct kobject *, struct kobject *);
+@@ -129,13 +114,6 @@
+ extern void
+ sysfs_remove_link(struct kobject *, const char * name);
+-extern int
+-sysfs_rename_link(struct kobject *kobj, struct kobject *target,
+-                      const char *old_name, const char *new_name);
+-
+-extern void
+-sysfs_delete_link(struct kobject *dir, struct kobject *targ, const char *name);
+-
+ int __must_check sysfs_create_bin_file(struct kobject *kobj,
+                                       struct bin_attribute *attr);
+ void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr);
+@@ -150,7 +128,11 @@
  
-+/* The generic sysctl data routine (used if no strategy routine supplied) */
-+int sysctl_data(ctl_table *table, int __user *name, int nlen,
-+              void __user *oldval, size_t __user *oldlenp,
-+              void __user *newval, size_t newlen)
-+{
-+      size_t len;
-+
-+      /* Get out of I don't have a variable */
-+      if (!table->data || !table->maxlen)
-+              return -ENOTDIR;
-+
-+      if (oldval && oldlenp) {
-+              if (get_user(len, oldlenp))
-+                      return -EFAULT;
-+              if (len) {
-+                      if (len > table->maxlen)
-+                              len = table->maxlen;
-+                      if (copy_to_user(oldval, table->data, len))
-+                              return -EFAULT;
-+                      if (put_user(len, oldlenp))
-+                              return -EFAULT;
-+              }
-+      }
-+
-+      if (newval && newlen) {
-+              if (newlen > table->maxlen)
-+                      newlen = table->maxlen;
-+
-+              if (copy_from_user(table->data, newval, newlen))
-+                      return -EFAULT;
-+      }
-+      return 1;
-+}
+ void sysfs_notify(struct kobject * k, char *dir, char *attr);
+-int sysfs_enable_shadowing(struct kobject *, const struct shadow_dir_operations *);
 +
- /* The generic string strategy routine: */
- int sysctl_string(ctl_table *table, int __user *name, int nlen,
-                 void __user *oldval, size_t __user *oldlenp,
-@@ -2355,6 +2533,13 @@
++extern int sysfs_make_shadowed_dir(struct kobject *kobj,
++      void * (*follow_link)(struct dentry *, struct nameidata *));
++extern struct dentry *sysfs_create_shadow_dir(struct kobject *kobj);
++extern void sysfs_remove_shadow_dir(struct dentry *dir);
+ extern int __must_check sysfs_init(void);
+@@ -162,7 +144,7 @@
        return -ENOSYS;
  }
  
-+int sysctl_data(ctl_table *table, int __user *name, int nlen,
-+                void __user *oldval, size_t __user *oldlenp,
-+                void __user *newval, size_t newlen)
-+{
-+      return -ENOSYS;
-+}
-+
- int sysctl_string(ctl_table *table, int __user *name, int nlen,
-                 void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen)
-@@ -2402,4 +2587,5 @@
- EXPORT_SYMBOL(sysctl_jiffies);
- EXPORT_SYMBOL(sysctl_ms_jiffies);
- EXPORT_SYMBOL(sysctl_string);
-+EXPORT_SYMBOL(sysctl_data);
- EXPORT_SYMBOL(unregister_sysctl_table);
-diff -Nurb linux-2.6.22-570/kernel/taskstats.c linux-2.6.22-590/kernel/taskstats.c
---- linux-2.6.22-570/kernel/taskstats.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/kernel/taskstats.c        2008-01-02 13:56:38.000000000 -0500
-@@ -196,6 +196,8 @@
-       /* fill in basic acct fields */
-       stats->version = TASKSTATS_VERSION;
-+      stats->nvcsw = tsk->nvcsw;
-+      stats->nivcsw = tsk->nivcsw;
-       bacct_add_tsk(stats, tsk);
+-static inline int sysfs_create_dir(struct kobject * kobj)
++static inline int sysfs_create_dir(struct kobject * k, struct dentry *shadow)
+ {
+       return 0;
+ }
+@@ -172,7 +154,9 @@
+       ;
+ }
  
-       /* fill in extended acct fields */
-@@ -242,6 +244,8 @@
-                */
-               delayacct_add_tsk(stats, tsk);
+-static inline int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
++static inline int sysfs_rename_dir(struct kobject * k,
++                                      struct dentry *new_parent,
++                                      const char *new_name)
+ {
+       return 0;
+ }
+@@ -211,17 +195,6 @@
+       ;
+ }
  
-+              stats->nvcsw += tsk->nvcsw;
-+              stats->nivcsw += tsk->nivcsw;
-       } while_each_thread(first, tsk);
+-static inline int
+-sysfs_rename_link(struct kobject * k, struct kobject *t,
+-                      const char *old_name, const char * new_name)
+-{
+-      return 0;
+-}
+-
+-static inline void
+-sysfs_delete_link(struct kobject *k, struct kobject *t, const char *name)
+-{
+-}
  
-       unlock_task_sighand(first, &flags);
-diff -Nurb linux-2.6.22-570/kernel/time/tick-sched.c linux-2.6.22-590/kernel/time/tick-sched.c
---- linux-2.6.22-570/kernel/time/tick-sched.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/kernel/time/tick-sched.c  2008-01-02 13:56:38.000000000 -0500
-@@ -153,6 +153,7 @@
-       unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
-       struct tick_sched *ts;
-       ktime_t last_update, expires, now, delta;
-+      struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
-       int cpu;
+ static inline int sysfs_create_bin_file(struct kobject * k, struct bin_attribute * a)
+ {
+@@ -258,8 +231,8 @@
+ {
+ }
  
-       local_irq_save(flags);
-@@ -290,11 +291,34 @@
- out:
-       ts->next_jiffies = next_jiffies;
-       ts->last_jiffies = last_jiffies;
-+      ts->sleep_length = ktime_sub(dev->next_event, now);
- end:
-       local_irq_restore(flags);
+-static inline int sysfs_enable_shadowing(struct kobject *kobj,
+-                              const struct shadow_dir_operations *shadow_ops)
++static inline int sysfs_make_shadowed_dir(struct kobject *kobj,
++      void * (*follow_link)(struct dentry *, struct nameidata *))
+ {
+       return 0;
  }
+diff -Nurb linux-2.6.22-590/include/linux/taskstats.h linux-2.6.22-570/include/linux/taskstats.h
+--- linux-2.6.22-590/include/linux/taskstats.h 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/linux/taskstats.h 2007-07-08 19:32:17.000000000 -0400
+@@ -31,7 +31,7 @@
+  */
  
- /**
-+ * tick_nohz_get_sleep_length - return the length of the current sleep
-+ *
-+ * Called from power state control code with interrupts disabled
-+ */
-+ktime_t tick_nohz_get_sleep_length(void)
-+{
-+       struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
-+
-+       return ts->sleep_length;
-+}
-+
-+/**
-+ * tick_nohz_get_idle_jiffies - returns the current idle jiffie count
-+ */
-+unsigned long tick_nohz_get_idle_jiffies(void)
-+{
-+       struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
-+
-+       return ts->idle_jiffies;
-+}
-+
-+/**
-  * nohz_restart_sched_tick - restart the idle tick from the idle task
-  *
-  * Restart the idle tick when the CPU is woken up from idle
-diff -Nurb linux-2.6.22-570/kernel/time/timekeeping.c linux-2.6.22-590/kernel/time/timekeeping.c
---- linux-2.6.22-570/kernel/time/timekeeping.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/kernel/time/timekeeping.c 2008-01-02 13:56:38.000000000 -0500
-@@ -39,7 +39,7 @@
+-#define TASKSTATS_VERSION     5
++#define TASKSTATS_VERSION     4
+ #define TS_COMM_LEN           32      /* should be >= TASK_COMM_LEN
+                                        * in linux/sched.h */
+@@ -149,9 +149,6 @@
+       __u64   read_bytes;             /* bytes of read I/O */
+       __u64   write_bytes;            /* bytes of write I/O */
+       __u64   cancelled_write_bytes;  /* bytes of cancelled write I/O */
+-
+-      __u64  nvcsw;                   /* voluntary_ctxt_switches */
+-      __u64  nivcsw;                  /* nonvoluntary_ctxt_switches */
+ };
+diff -Nurb linux-2.6.22-590/include/linux/tick.h linux-2.6.22-570/include/linux/tick.h
+--- linux-2.6.22-590/include/linux/tick.h      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/linux/tick.h      2007-07-08 19:32:17.000000000 -0400
+@@ -40,7 +40,6 @@
+  * @idle_sleeps:      Number of idle calls, where the sched tick was stopped
+  * @idle_entrytime:   Time when the idle call was entered
+  * @idle_sleeptime:   Sum of the time slept in idle with sched tick stopped
+- * @sleep_length:     Duration of the current idle sleep
   */
- struct timespec xtime __attribute__ ((aligned (16)));
- struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
+ struct tick_sched {
+       struct hrtimer                  sched_timer;
+@@ -53,7 +52,6 @@
+       unsigned long                   idle_sleeps;
+       ktime_t                         idle_entrytime;
+       ktime_t                         idle_sleeptime;
+-      ktime_t                         sleep_length;
+       unsigned long                   last_jiffies;
+       unsigned long                   next_jiffies;
+       ktime_t                         idle_expires;
+@@ -102,18 +100,10 @@
+ extern void tick_nohz_stop_sched_tick(void);
+ extern void tick_nohz_restart_sched_tick(void);
+ extern void tick_nohz_update_jiffies(void);
+-extern ktime_t tick_nohz_get_sleep_length(void);
+-extern unsigned long tick_nohz_get_idle_jiffies(void);
+ # else
+ static inline void tick_nohz_stop_sched_tick(void) { }
+ static inline void tick_nohz_restart_sched_tick(void) { }
+ static inline void tick_nohz_update_jiffies(void) { }
+-static inline ktime_t tick_nohz_get_sleep_length(void)
+-{
+-      ktime_t len = { .tv64 = NSEC_PER_SEC/HZ };
 -
-+static unsigned long total_sleep_time;
- EXPORT_SYMBOL(xtime);
+-      return len;
+-}
+ # endif /* !NO_HZ */
  
+ #endif
+diff -Nurb linux-2.6.22-590/include/linux/time.h linux-2.6.22-570/include/linux/time.h
+--- linux-2.6.22-590/include/linux/time.h      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/linux/time.h      2008-01-23 19:16:05.000000000 -0500
+@@ -116,8 +116,6 @@
+ extern unsigned int alarm_setitimer(unsigned int seconds);
+ extern int do_getitimer(int which, struct itimerval *value);
+ extern void getnstimeofday(struct timespec *tv);
+-extern void getboottime(struct timespec *ts);
+-extern void monotonic_to_bootbased(struct timespec *ts);
  
-@@ -251,6 +251,7 @@
-       xtime.tv_nsec = 0;
-       set_normalized_timespec(&wall_to_monotonic,
-               -xtime.tv_sec, -xtime.tv_nsec);
-+      total_sleep_time = 0;
+ extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
+ extern int timekeeping_is_continuous(void);
+diff -Nurb linux-2.6.22-590/include/linux/union_fs.h linux-2.6.22-570/include/linux/union_fs.h
+--- linux-2.6.22-590/include/linux/union_fs.h  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/linux/union_fs.h  1969-12-31 19:00:00.000000000 -0500
+@@ -1,29 +0,0 @@
+-/*
+- * Copyright (c) 2003-2007 Erez Zadok
+- * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
+- * Copyright (c) 2003-2007 Stony Brook University
+- * Copyright (c) 2003-2007 The Research Foundation of SUNY
+- *
+- * 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.
+- */
+-
+-#ifndef _LINUX_UNION_FS_H
+-#define _LINUX_UNION_FS_H
+-
+-#define UNIONFS_VERSION  "2.0"
+-/*
+- * DEFINITIONS FOR USER AND KERNEL CODE:
+- */
+-# define UNIONFS_IOCTL_INCGEN         _IOR(0x15, 11, int)
+-# define UNIONFS_IOCTL_QUERYFILE      _IOR(0x15, 15, int)
+-
+-/* We don't support normal remount, but unionctl uses it. */
+-# define UNIONFS_REMOUNT_MAGIC                0x4a5a4380
+-
+-/* should be at least LAST_USED_UNIONFS_PERMISSION<<1 */
+-#define MAY_NFSRO                     16
+-
+-#endif /* _LINUX_UNIONFS_H */
+-
+diff -Nurb linux-2.6.22-590/include/linux/unwind.h linux-2.6.22-570/include/linux/unwind.h
+--- linux-2.6.22-590/include/linux/unwind.h    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/linux/unwind.h    2007-07-08 19:32:17.000000000 -0400
+@@ -14,63 +14,6 @@
  
-       write_sequnlock_irqrestore(&xtime_lock, flags);
- }
-@@ -282,6 +283,7 @@
+ struct module;
  
-               xtime.tv_sec += sleep_length;
-               wall_to_monotonic.tv_sec -= sleep_length;
-+              total_sleep_time += sleep_length;
-       }
-       /* re-base the last cycle value */
-       clock->cycle_last = clocksource_read(clock);
-@@ -476,3 +478,34 @@
-       change_clocksource();
-       update_vsyscall(&xtime, clock);
- }
-+
-+/**
-+ * getboottime - Return the real time of system boot.
-+ * @ts:               pointer to the timespec to be set
-+ *
-+ * Returns the time of day in a timespec.
-+ *
-+ * This is based on the wall_to_monotonic offset and the total suspend
-+ * time. Calls to settimeofday will affect the value returned (which
-+ * basically means that however wrong your real time clock is at boot time,
-+ * you get the right time here).
-+ */
-+void getboottime(struct timespec *ts)
-+{
-+      set_normalized_timespec(ts,
-+              - (wall_to_monotonic.tv_sec + total_sleep_time),
-+              - wall_to_monotonic.tv_nsec);
-+}
-+
-+EXPORT_SYMBOL(getboottime);
-+
-+/**
-+ * monotonic_to_bootbased - Convert the monotonic time to boot based.
-+ * @ts:               pointer to the timespec to be converted
-+ */
-+void monotonic_to_bootbased(struct timespec *ts)
-+{
-+      ts->tv_sec += total_sleep_time;
-+}
-+
-+EXPORT_SYMBOL(monotonic_to_bootbased);
-diff -Nurb linux-2.6.22-570/kernel/timer.c linux-2.6.22-590/kernel/timer.c
---- linux-2.6.22-570/kernel/timer.c    2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/timer.c    2008-01-02 13:56:38.000000000 -0500
-@@ -36,6 +36,7 @@
- #include <linux/delay.h>
- #include <linux/tick.h>
- #include <linux/kallsyms.h>
-+#include <linux/kgdb.h>
- #include <linux/vs_base.h>
- #include <linux/vs_cvirt.h>
- #include <linux/vs_pid.h>
-@@ -886,7 +887,11 @@
-  */
- void run_local_timers(void)
- {
-+      int this_cpu = smp_processor_id();
-       raise_softirq(TIMER_SOFTIRQ);
-+#ifdef CONFIG_KGDB
-+      if(!atomic_read(&kgdb_sync_softlockup[this_cpu]))
-+#endif
-       softlockup_tick();
- }
+-#ifdef CONFIG_STACK_UNWIND
+-
+-#include <asm/unwind.h>
+-
+-#ifndef ARCH_UNWIND_SECTION_NAME
+-#define ARCH_UNWIND_SECTION_NAME ".eh_frame"
+-#endif
+-
+-/*
+- * Initialize unwind support.
+- */
+-extern void unwind_init(void);
+-extern void unwind_setup(void);
+-
+-#ifdef CONFIG_MODULES
+-
+-extern void *unwind_add_table(struct module *,
+-                              const void *table_start,
+-                              unsigned long table_size);
+-
+-extern void unwind_remove_table(void *handle, int init_only);
+-
+-#endif
+-
+-extern int unwind_init_frame_info(struct unwind_frame_info *,
+-                                  struct task_struct *,
+-                                  /*const*/ struct pt_regs *);
+-
+-/*
+- * Prepare to unwind a blocked task.
+- */
+-extern int unwind_init_blocked(struct unwind_frame_info *,
+-                               struct task_struct *);
+-
+-/*
+- * Prepare to unwind the currently running thread.
+- */
+-extern int unwind_init_running(struct unwind_frame_info *,
+-                               asmlinkage int (*callback)(struct unwind_frame_info *,
+-                                                          void *arg),
+-                               void *arg);
+-
+-/*
+- * Unwind to previous to frame.  Returns 0 if successful, negative
+- * number in case of an error.
+- */
+-extern int unwind(struct unwind_frame_info *);
+-
+-/*
+- * Unwind until the return pointer is in user-land (or until an error
+- * occurs).  Returns 0 if successful, negative number in case of
+- * error.
+- */
+-extern int unwind_to_user(struct unwind_frame_info *);
+-
+-#else
+-
+ struct unwind_frame_info {};
+ static inline void unwind_init(void) {}
+@@ -85,12 +28,12 @@
+       return NULL;
+ }
+-#endif
+-
+ static inline void unwind_remove_table(void *handle, int init_only)
+ {
+ }
  
-@@ -1125,6 +1130,7 @@
-               getnstimeofday(&tp);
-               tp.tv_sec += wall_to_monotonic.tv_sec;
-               tp.tv_nsec += wall_to_monotonic.tv_nsec;
-+              monotonic_to_bootbased(&tp);
-               if (tp.tv_nsec - NSEC_PER_SEC >= 0) {
-                       tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC;
-                       tp.tv_sec++;
-diff -Nurb linux-2.6.22-570/kernel/unwind.c linux-2.6.22-590/kernel/unwind.c
---- linux-2.6.22-570/kernel/unwind.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/kernel/unwind.c   2008-01-02 13:56:38.000000000 -0500
-@@ -0,0 +1,1288 @@
-+/*
-+ * Copyright (C) 2002-2006 Novell, Inc.
-+ *    Jan Beulich <jbeulich@novell.com>
-+ * This code is released under version 2 of the GNU GPL.
-+ *
-+ * A simple API for unwinding kernel stacks.  This is used for
-+ * debugging and error reporting purposes.  The kernel doesn't need
-+ * full-blown stack unwinding with all the bells and whistles, so there
-+ * is not much point in implementing the full Dwarf2 unwind API.
-+ */
-+
-+#include <linux/unwind.h>
-+#include <linux/module.h>
-+#include <linux/bootmem.h>
-+#include <linux/sort.h>
-+#include <linux/stop_machine.h>
-+#include <linux/uaccess.h>
-+#include <asm/sections.h>
-+#include <asm/uaccess.h>
-+#include <asm/unaligned.h>
-+
-+extern const char __start_unwind[], __end_unwind[];
-+extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];
-+
-+#define MAX_STACK_DEPTH 8
-+
-+#define EXTRA_INFO(f) { \
-+              BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
-+                                % FIELD_SIZEOF(struct unwind_frame_info, f)) \
-+              + offsetof(struct unwind_frame_info, f) \
-+                / FIELD_SIZEOF(struct unwind_frame_info, f), \
-+              FIELD_SIZEOF(struct unwind_frame_info, f) \
-+      }
-+#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
-+
-+static const struct {
-+      unsigned offs:BITS_PER_LONG / 2;
-+      unsigned width:BITS_PER_LONG / 2;
-+} reg_info[] = {
-+      UNW_REGISTER_INFO
-+};
-+
-+#undef PTREGS_INFO
-+#undef EXTRA_INFO
-+
-+#ifndef REG_INVALID
-+#define REG_INVALID(r) (reg_info[r].width == 0)
-+#endif
-+
-+#define DW_CFA_nop                          0x00
-+#define DW_CFA_set_loc                      0x01
-+#define DW_CFA_advance_loc1                 0x02
-+#define DW_CFA_advance_loc2                 0x03
-+#define DW_CFA_advance_loc4                 0x04
-+#define DW_CFA_offset_extended              0x05
-+#define DW_CFA_restore_extended             0x06
-+#define DW_CFA_undefined                    0x07
-+#define DW_CFA_same_value                   0x08
-+#define DW_CFA_register                     0x09
-+#define DW_CFA_remember_state               0x0a
-+#define DW_CFA_restore_state                0x0b
-+#define DW_CFA_def_cfa                      0x0c
-+#define DW_CFA_def_cfa_register             0x0d
-+#define DW_CFA_def_cfa_offset               0x0e
-+#define DW_CFA_def_cfa_expression           0x0f
-+#define DW_CFA_expression                   0x10
-+#define DW_CFA_offset_extended_sf           0x11
-+#define DW_CFA_def_cfa_sf                   0x12
-+#define DW_CFA_def_cfa_offset_sf            0x13
-+#define DW_CFA_val_offset                   0x14
-+#define DW_CFA_val_offset_sf                0x15
-+#define DW_CFA_val_expression               0x16
-+#define DW_CFA_lo_user                      0x1c
-+#define DW_CFA_GNU_window_save              0x2d
-+#define DW_CFA_GNU_args_size                0x2e
-+#define DW_CFA_GNU_negative_offset_extended 0x2f
-+#define DW_CFA_hi_user                      0x3f
-+
-+#define DW_EH_PE_FORM     0x07
-+#define DW_EH_PE_native   0x00
-+#define DW_EH_PE_leb128   0x01
-+#define DW_EH_PE_data2    0x02
-+#define DW_EH_PE_data4    0x03
-+#define DW_EH_PE_data8    0x04
-+#define DW_EH_PE_signed   0x08
-+#define DW_EH_PE_ADJUST   0x70
-+#define DW_EH_PE_abs      0x00
-+#define DW_EH_PE_pcrel    0x10
-+#define DW_EH_PE_textrel  0x20
-+#define DW_EH_PE_datarel  0x30
-+#define DW_EH_PE_funcrel  0x40
-+#define DW_EH_PE_aligned  0x50
-+#define DW_EH_PE_indirect 0x80
-+#define DW_EH_PE_omit     0xff
-+
-+typedef unsigned long uleb128_t;
-+typedef   signed long sleb128_t;
-+#define sleb128abs __builtin_labs
-+
-+static struct unwind_table {
-+      struct {
-+              unsigned long pc;
-+              unsigned long range;
-+      } core, init;
-+      const void *address;
-+      unsigned long size;
-+      const unsigned char *header;
-+      unsigned long hdrsz;
-+      struct unwind_table *link;
-+      const char *name;
-+} root_table;
-+
-+struct unwind_item {
-+      enum item_location {
-+              Nowhere,
-+              Memory,
-+              Register,
-+              Value
-+      } where;
-+      uleb128_t value;
-+};
-+
-+struct unwind_state {
-+      uleb128_t loc, org;
-+      const u8 *cieStart, *cieEnd;
-+      uleb128_t codeAlign;
-+      sleb128_t dataAlign;
-+      struct cfa {
-+              uleb128_t reg, offs;
-+      } cfa;
-+      struct unwind_item regs[ARRAY_SIZE(reg_info)];
-+      unsigned stackDepth:8;
-+      unsigned version:8;
-+      const u8 *label;
-+      const u8 *stack[MAX_STACK_DEPTH];
-+};
-+
-+static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
-+
-+static unsigned unwind_debug;
-+static int __init unwind_debug_setup(char *s)
-+{
-+      unwind_debug = simple_strtoul(s, NULL, 0);
-+      return 1;
-+}
-+__setup("unwind_debug=", unwind_debug_setup);
-+#define dprintk(lvl, fmt, args...) \
-+      ((void)(lvl > unwind_debug \
-+       || printk(KERN_DEBUG "unwind: " fmt "\n", ##args)))
-+
-+static struct unwind_table *find_table(unsigned long pc)
-+{
-+      struct unwind_table *table;
-+
-+      for (table = &root_table; table; table = table->link)
-+              if ((pc >= table->core.pc
-+                   && pc < table->core.pc + table->core.range)
-+                  || (pc >= table->init.pc
-+                      && pc < table->init.pc + table->init.range))
-+                      break;
-+
-+      return table;
-+}
-+
-+static unsigned long read_pointer(const u8 **pLoc,
-+                                  const void *end,
-+                                  signed ptrType,
-+                                  unsigned long text_base,
-+                                  unsigned long data_base);
-+
-+static void init_unwind_table(struct unwind_table *table,
-+                              const char *name,
-+                              const void *core_start,
-+                              unsigned long core_size,
-+                              const void *init_start,
-+                              unsigned long init_size,
-+                              const void *table_start,
-+                              unsigned long table_size,
-+                              const u8 *header_start,
-+                              unsigned long header_size)
-+{
-+      const u8 *ptr = header_start + 4;
-+      const u8 *end = header_start + header_size;
-+
-+      table->core.pc = (unsigned long)core_start;
-+      table->core.range = core_size;
-+      table->init.pc = (unsigned long)init_start;
-+      table->init.range = init_size;
-+      table->address = table_start;
-+      table->size = table_size;
-+      /* See if the linker provided table looks valid. */
-+      if (header_size <= 4
-+          || header_start[0] != 1
-+          || (void *)read_pointer(&ptr, end, header_start[1], 0, 0)
-+             != table_start
-+          || !read_pointer(&ptr, end, header_start[2], 0, 0)
-+          || !read_pointer(&ptr, end, header_start[3], 0,
-+                           (unsigned long)header_start)
-+          || !read_pointer(&ptr, end, header_start[3], 0,
-+                           (unsigned long)header_start))
-+              header_start = NULL;
-+      table->hdrsz = header_size;
-+      smp_wmb();
-+      table->header = header_start;
-+      table->link = NULL;
-+      table->name = name;
-+}
-+
-+void __init unwind_init(void)
-+{
-+      init_unwind_table(&root_table, "kernel",
-+                        _text, _end - _text,
-+                        NULL, 0,
-+                        __start_unwind, __end_unwind - __start_unwind,
-+                        __start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);
-+}
-+
-+static const u32 bad_cie, not_fde;
-+static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
-+static signed fde_pointer_type(const u32 *cie);
-+
-+struct eh_frame_hdr_table_entry {
-+      unsigned long start, fde;
-+};
-+
-+static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
-+{
-+      const struct eh_frame_hdr_table_entry *e1 = p1;
-+      const struct eh_frame_hdr_table_entry *e2 = p2;
-+
-+      return (e1->start > e2->start) - (e1->start < e2->start);
-+}
-+
-+static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
-+{
-+      struct eh_frame_hdr_table_entry *e1 = p1;
-+      struct eh_frame_hdr_table_entry *e2 = p2;
-+      unsigned long v;
-+
-+      v = e1->start;
-+      e1->start = e2->start;
-+      e2->start = v;
-+      v = e1->fde;
-+      e1->fde = e2->fde;
-+      e2->fde = v;
-+}
-+
-+static void __init setup_unwind_table(struct unwind_table *table,
-+                                      void *(*alloc)(unsigned long))
-+{
-+      const u8 *ptr;
-+      unsigned long tableSize = table->size, hdrSize;
-+      unsigned n;
-+      const u32 *fde;
-+      struct {
-+              u8 version;
-+              u8 eh_frame_ptr_enc;
-+              u8 fde_count_enc;
-+              u8 table_enc;
-+              unsigned long eh_frame_ptr;
-+              unsigned int fde_count;
-+              struct eh_frame_hdr_table_entry table[];
-+      } __attribute__((__packed__)) *header;
-+
-+      if (table->header)
-+              return;
-+
-+      if (table->hdrsz)
-+              printk(KERN_WARNING ".eh_frame_hdr for '%s' present but unusable\n",
-+                     table->name);
-+
-+      if (tableSize & (sizeof(*fde) - 1))
-+              return;
-+
-+      for (fde = table->address, n = 0;
-+           tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
-+           tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
-+              const u32 *cie = cie_for_fde(fde, table);
-+              signed ptrType;
-+
-+              if (cie == &not_fde)
-+                      continue;
-+              if (cie == NULL
-+                  || cie == &bad_cie
-+                  || (ptrType = fde_pointer_type(cie)) < 0)
-+                      return;
-+              ptr = (const u8 *)(fde + 2);
-+              if (!read_pointer(&ptr,
-+                                (const u8 *)(fde + 1) + *fde,
-+                                ptrType, 0, 0))
-+                      return;
-+              ++n;
-+      }
-+
-+      if (tableSize || !n)
-+              return;
-+
-+      hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
-+              + 2 * n * sizeof(unsigned long);
-+      dprintk(2, "Binary lookup table size for %s: %lu bytes", table->name, hdrSize);
-+      header = alloc(hdrSize);
-+      if (!header)
-+              return;
-+      header->version          = 1;
-+      header->eh_frame_ptr_enc = DW_EH_PE_abs|DW_EH_PE_native;
-+      header->fde_count_enc    = DW_EH_PE_abs|DW_EH_PE_data4;
-+      header->table_enc        = DW_EH_PE_abs|DW_EH_PE_native;
-+      put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
-+      BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
-+                   % __alignof(typeof(header->fde_count)));
-+      header->fde_count        = n;
-+
-+      BUILD_BUG_ON(offsetof(typeof(*header), table)
-+                   % __alignof(typeof(*header->table)));
-+      for (fde = table->address, tableSize = table->size, n = 0;
-+           tableSize;
-+           tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
-+              const u32 *cie = fde + 1 - fde[1] / sizeof(*fde);
-+
-+              if (!fde[1])
-+                      continue; /* this is a CIE */
-+              ptr = (const u8 *)(fde + 2);
-+              header->table[n].start = read_pointer(&ptr,
-+                                                    (const u8 *)(fde + 1) + *fde,
-+                                                    fde_pointer_type(cie), 0, 0);
-+              header->table[n].fde = (unsigned long)fde;
-+              ++n;
-+      }
-+      WARN_ON(n != header->fde_count);
-+
-+      sort(header->table,
-+           n,
-+           sizeof(*header->table),
-+           cmp_eh_frame_hdr_table_entries,
-+           swap_eh_frame_hdr_table_entries);
-+
-+      table->hdrsz = hdrSize;
-+      smp_wmb();
-+      table->header = (const void *)header;
-+}
-+
-+static void *__init balloc(unsigned long sz)
-+{
-+      return __alloc_bootmem_nopanic(sz,
-+                                     sizeof(unsigned int),
-+                                     __pa(MAX_DMA_ADDRESS));
-+}
-+
-+void __init unwind_setup(void)
-+{
-+      setup_unwind_table(&root_table, balloc);
-+}
-+
-+#ifdef CONFIG_MODULES
-+
-+static struct unwind_table *last_table;
-+
-+/* Must be called with module_mutex held. */
-+void *unwind_add_table(struct module *module,
-+                       const void *table_start,
-+                       unsigned long table_size)
-+{
-+      struct unwind_table *table;
-+
-+      if (table_size <= 0)
-+              return NULL;
-+
-+      table = kmalloc(sizeof(*table), GFP_KERNEL);
-+      if (!table)
-+              return NULL;
-+
-+      init_unwind_table(table, module->name,
-+                        module->module_core, module->core_size,
-+                        module->module_init, module->init_size,
-+                        table_start, table_size,
-+                        NULL, 0);
-+
-+      if (last_table)
-+              last_table->link = table;
-+      else
-+              root_table.link = table;
-+      last_table = table;
-+
-+      return table;
-+}
-+
-+struct unlink_table_info
-+{
-+      struct unwind_table *table;
-+      int init_only;
-+};
-+
-+static int unlink_table(void *arg)
-+{
-+      struct unlink_table_info *info = arg;
-+      struct unwind_table *table = info->table, *prev;
-+
-+      for (prev = &root_table; prev->link && prev->link != table; prev = prev->link)
-+              ;
-+
-+      if (prev->link) {
-+              if (info->init_only) {
-+                      table->init.pc = 0;
-+                      table->init.range = 0;
-+                      info->table = NULL;
-+              } else {
-+                      prev->link = table->link;
-+                      if (!prev->link)
-+                              last_table = prev;
-+              }
-+      } else
-+              info->table = NULL;
-+
-+      return 0;
-+}
-+
-+/* Must be called with module_mutex held. */
-+void unwind_remove_table(void *handle, int init_only)
-+{
-+      struct unwind_table *table = handle;
-+      struct unlink_table_info info;
-+
-+      if (!table || table == &root_table)
-+              return;
-+
-+      if (init_only && table == last_table) {
-+              table->init.pc = 0;
-+              table->init.range = 0;
-+              return;
-+      }
-+
-+      info.table = table;
-+      info.init_only = init_only;
-+      stop_machine_run(unlink_table, &info, NR_CPUS);
-+
-+      if (info.table)
-+              kfree(table);
-+}
-+
-+#endif /* CONFIG_MODULES */
-+
-+static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
-+{
-+      const u8 *cur = *pcur;
-+      uleb128_t value;
-+      unsigned shift;
-+
-+      for (shift = 0, value = 0; cur < end; shift += 7) {
-+              if (shift + 7 > 8 * sizeof(value)
-+                  && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
-+                      cur = end + 1;
-+                      break;
-+              }
-+              value |= (uleb128_t)(*cur & 0x7f) << shift;
-+              if (!(*cur++ & 0x80))
-+                      break;
-+      }
-+      *pcur = cur;
-+
-+      return value;
-+}
-+
-+static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
-+{
-+      const u8 *cur = *pcur;
-+      sleb128_t value;
-+      unsigned shift;
-+
-+      for (shift = 0, value = 0; cur < end; shift += 7) {
-+              if (shift + 7 > 8 * sizeof(value)
-+                  && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
-+                      cur = end + 1;
-+                      break;
-+              }
-+              value |= (sleb128_t)(*cur & 0x7f) << shift;
-+              if (!(*cur & 0x80)) {
-+                      value |= -(*cur++ & 0x40) << shift;
-+                      break;
-+              }
-+      }
-+      *pcur = cur;
-+
-+      return value;
-+}
-+
-+static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
-+{
-+      const u32 *cie;
-+
-+      if (!*fde || (*fde & (sizeof(*fde) - 1)))
-+              return &bad_cie;
-+      if (!fde[1])
-+              return &not_fde; /* this is a CIE */
-+      if ((fde[1] & (sizeof(*fde) - 1))
-+          || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address)
-+              return NULL; /* this is not a valid FDE */
-+      cie = fde + 1 - fde[1] / sizeof(*fde);
-+      if (*cie <= sizeof(*cie) + 4
-+          || *cie >= fde[1] - sizeof(*fde)
-+          || (*cie & (sizeof(*cie) - 1))
-+          || cie[1])
-+              return NULL; /* this is not a (valid) CIE */
-+      return cie;
-+}
-+
-+static unsigned long read_pointer(const u8 **pLoc,
-+                                  const void *end,
-+                                  signed ptrType,
-+                                  unsigned long text_base,
-+                                  unsigned long data_base)
-+{
-+      unsigned long value = 0;
-+      union {
-+              const u8 *p8;
-+              const u16 *p16u;
-+              const s16 *p16s;
-+              const u32 *p32u;
-+              const s32 *p32s;
-+              const unsigned long *pul;
-+      } ptr;
-+
-+      if (ptrType < 0 || ptrType == DW_EH_PE_omit) {
-+              dprintk(1, "Invalid pointer encoding %02X (%p,%p).", ptrType, *pLoc, end);
-+              return 0;
-+      }
-+      ptr.p8 = *pLoc;
-+      switch(ptrType & DW_EH_PE_FORM) {
-+      case DW_EH_PE_data2:
-+              if (end < (const void *)(ptr.p16u + 1)) {
-+                      dprintk(1, "Data16 overrun (%p,%p).", ptr.p8, end);
-+                      return 0;
-+              }
-+              if(ptrType & DW_EH_PE_signed)
-+                      value = get_unaligned(ptr.p16s++);
-+              else
-+                      value = get_unaligned(ptr.p16u++);
-+              break;
-+      case DW_EH_PE_data4:
-+#ifdef CONFIG_64BIT
-+              if (end < (const void *)(ptr.p32u + 1)) {
-+                      dprintk(1, "Data32 overrun (%p,%p).", ptr.p8, end);
-+                      return 0;
-+              }
-+              if(ptrType & DW_EH_PE_signed)
-+                      value = get_unaligned(ptr.p32s++);
-+              else
-+                      value = get_unaligned(ptr.p32u++);
-+              break;
-+      case DW_EH_PE_data8:
-+              BUILD_BUG_ON(sizeof(u64) != sizeof(value));
-+#else
-+              BUILD_BUG_ON(sizeof(u32) != sizeof(value));
-+#endif
-+      case DW_EH_PE_native:
-+              if (end < (const void *)(ptr.pul + 1)) {
-+                      dprintk(1, "DataUL overrun (%p,%p).", ptr.p8, end);
-+                      return 0;
-+              }
-+              value = get_unaligned(ptr.pul++);
-+              break;
-+      case DW_EH_PE_leb128:
-+              BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
-+              value = ptrType & DW_EH_PE_signed
-+                      ? get_sleb128(&ptr.p8, end)
-+                      : get_uleb128(&ptr.p8, end);
-+              if ((const void *)ptr.p8 > end) {
-+                      dprintk(1, "DataLEB overrun (%p,%p).", ptr.p8, end);
-+                      return 0;
-+              }
-+              break;
-+      default:
-+              dprintk(2, "Cannot decode pointer type %02X (%p,%p).",
-+                      ptrType, ptr.p8, end);
-+              return 0;
-+      }
-+      switch(ptrType & DW_EH_PE_ADJUST) {
-+      case DW_EH_PE_abs:
-+              break;
-+      case DW_EH_PE_pcrel:
-+              value += (unsigned long)*pLoc;
-+              break;
-+      case DW_EH_PE_textrel:
-+              if (likely(text_base)) {
-+                      value += text_base;
-+                      break;
-+              }
-+              dprintk(2, "Text-relative encoding %02X (%p,%p), but zero text base.",
-+                      ptrType, *pLoc, end);
-+              return 0;
-+      case DW_EH_PE_datarel:
-+              if (likely(data_base)) {
-+                      value += data_base;
-+                      break;
-+              }
-+              dprintk(2, "Data-relative encoding %02X (%p,%p), but zero data base.",
-+                      ptrType, *pLoc, end);
-+              return 0;
-+      default:
-+              dprintk(2, "Cannot adjust pointer type %02X (%p,%p).",
-+                      ptrType, *pLoc, end);
-+              return 0;
-+      }
-+      if ((ptrType & DW_EH_PE_indirect)
-+          && probe_kernel_address((unsigned long *)value, value)) {
-+              dprintk(1, "Cannot read indirect value %lx (%p,%p).",
-+                      value, *pLoc, end);
-+              return 0;
-+      }
-+      *pLoc = ptr.p8;
-+
-+      return value;
-+}
-+
-+static signed fde_pointer_type(const u32 *cie)
-+{
-+      const u8 *ptr = (const u8 *)(cie + 2);
-+      unsigned version = *ptr;
-+
-+      if (version != 1)
-+              return -1; /* unsupported */
-+      if (*++ptr) {
-+              const char *aug;
-+              const u8 *end = (const u8 *)(cie + 1) + *cie;
-+              uleb128_t len;
-+
-+              /* check if augmentation size is first (and thus present) */
-+              if (*ptr != 'z')
-+                      return -1;
-+              /* check if augmentation string is nul-terminated */
-+              if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
-+                      return -1;
-+              ++ptr; /* skip terminator */
-+              get_uleb128(&ptr, end); /* skip code alignment */
-+              get_sleb128(&ptr, end); /* skip data alignment */
-+              /* skip return address column */
-+              version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end);
-+              len = get_uleb128(&ptr, end); /* augmentation length */
-+              if (ptr + len < ptr || ptr + len > end)
-+                      return -1;
-+              end = ptr + len;
-+              while (*++aug) {
-+                      if (ptr >= end)
-+                              return -1;
-+                      switch(*aug) {
-+                      case 'L':
-+                              ++ptr;
-+                              break;
-+                      case 'P': {
-+                                      signed ptrType = *ptr++;
-+
-+                                      if (!read_pointer(&ptr, end, ptrType, 0, 0)
-+                                          || ptr > end)
-+                                              return -1;
-+                              }
-+                              break;
-+                      case 'R':
-+                              return *ptr;
-+                      default:
-+                              return -1;
-+                      }
-+              }
-+      }
-+      return DW_EH_PE_native|DW_EH_PE_abs;
-+}
-+
-+static int advance_loc(unsigned long delta, struct unwind_state *state)
-+{
-+      state->loc += delta * state->codeAlign;
-+
-+      return delta > 0;
-+}
-+
-+static void set_rule(uleb128_t reg,
-+                     enum item_location where,
-+                     uleb128_t value,
-+                     struct unwind_state *state)
-+{
-+      if (reg < ARRAY_SIZE(state->regs)) {
-+              state->regs[reg].where = where;
-+              state->regs[reg].value = value;
-+      }
-+}
-+
-+static int processCFI(const u8 *start,
-+                      const u8 *end,
-+                      unsigned long targetLoc,
-+                      signed ptrType,
-+                      struct unwind_state *state)
-+{
-+      union {
-+              const u8 *p8;
-+              const u16 *p16;
-+              const u32 *p32;
-+      } ptr;
-+      int result = 1;
-+
-+      if (start != state->cieStart) {
-+              state->loc = state->org;
-+              result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state);
-+              if (targetLoc == 0 && state->label == NULL)
-+                      return result;
-+      }
-+      for (ptr.p8 = start; result && ptr.p8 < end; ) {
-+              switch(*ptr.p8 >> 6) {
-+                      uleb128_t value;
-+
-+              case 0:
-+                      switch(*ptr.p8++) {
-+                      case DW_CFA_nop:
-+                              break;
-+                      case DW_CFA_set_loc:
-+                              state->loc = read_pointer(&ptr.p8, end, ptrType, 0, 0);
-+                              if (state->loc == 0)
-+                                      result = 0;
-+                              break;
-+                      case DW_CFA_advance_loc1:
-+                              result = ptr.p8 < end && advance_loc(*ptr.p8++, state);
-+                              break;
-+                      case DW_CFA_advance_loc2:
-+                              result = ptr.p8 <= end + 2
-+                                       && advance_loc(*ptr.p16++, state);
-+                              break;
-+                      case DW_CFA_advance_loc4:
-+                              result = ptr.p8 <= end + 4
-+                                       && advance_loc(*ptr.p32++, state);
-+                              break;
-+                      case DW_CFA_offset_extended:
-+                              value = get_uleb128(&ptr.p8, end);
-+                              set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
-+                              break;
-+                      case DW_CFA_val_offset:
-+                              value = get_uleb128(&ptr.p8, end);
-+                              set_rule(value, Value, get_uleb128(&ptr.p8, end), state);
-+                              break;
-+                      case DW_CFA_offset_extended_sf:
-+                              value = get_uleb128(&ptr.p8, end);
-+                              set_rule(value, Memory, get_sleb128(&ptr.p8, end), state);
-+                              break;
-+                      case DW_CFA_val_offset_sf:
-+                              value = get_uleb128(&ptr.p8, end);
-+                              set_rule(value, Value, get_sleb128(&ptr.p8, end), state);
-+                              break;
-+                      case DW_CFA_restore_extended:
-+                      case DW_CFA_undefined:
-+                      case DW_CFA_same_value:
-+                              set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state);
-+                              break;
-+                      case DW_CFA_register:
-+                              value = get_uleb128(&ptr.p8, end);
-+                              set_rule(value,
-+                                       Register,
-+                                       get_uleb128(&ptr.p8, end), state);
-+                              break;
-+                      case DW_CFA_remember_state:
-+                              if (ptr.p8 == state->label) {
-+                                      state->label = NULL;
-+                                      return 1;
-+                              }
-+                              if (state->stackDepth >= MAX_STACK_DEPTH) {
-+                                      dprintk(1, "State stack overflow (%p,%p).", ptr.p8, end);
-+                                      return 0;
-+                              }
-+                              state->stack[state->stackDepth++] = ptr.p8;
-+                              break;
-+                      case DW_CFA_restore_state:
-+                              if (state->stackDepth) {
-+                                      const uleb128_t loc = state->loc;
-+                                      const u8 *label = state->label;
-+
-+                                      state->label = state->stack[state->stackDepth - 1];
-+                                      memcpy(&state->cfa, &badCFA, sizeof(state->cfa));
-+                                      memset(state->regs, 0, sizeof(state->regs));
-+                                      state->stackDepth = 0;
-+                                      result = processCFI(start, end, 0, ptrType, state);
-+                                      state->loc = loc;
-+                                      state->label = label;
-+                              } else {
-+                                      dprintk(1, "State stack underflow (%p,%p).", ptr.p8, end);
-+                                      return 0;
-+                              }
-+                              break;
-+                      case DW_CFA_def_cfa:
-+                              state->cfa.reg = get_uleb128(&ptr.p8, end);
-+                              /*nobreak*/
-+                      case DW_CFA_def_cfa_offset:
-+                              state->cfa.offs = get_uleb128(&ptr.p8, end);
-+                              break;
-+                      case DW_CFA_def_cfa_sf:
-+                              state->cfa.reg = get_uleb128(&ptr.p8, end);
-+                              /*nobreak*/
-+                      case DW_CFA_def_cfa_offset_sf:
-+                              state->cfa.offs = get_sleb128(&ptr.p8, end)
-+                                                * state->dataAlign;
-+                              break;
-+                      case DW_CFA_def_cfa_register:
-+                              state->cfa.reg = get_uleb128(&ptr.p8, end);
-+                              break;
-+                      /*todo case DW_CFA_def_cfa_expression: */
-+                      /*todo case DW_CFA_expression: */
-+                      /*todo case DW_CFA_val_expression: */
-+                      case DW_CFA_GNU_args_size:
-+                              get_uleb128(&ptr.p8, end);
-+                              break;
-+                      case DW_CFA_GNU_negative_offset_extended:
-+                              value = get_uleb128(&ptr.p8, end);
-+                              set_rule(value,
-+                                       Memory,
-+                                       (uleb128_t)0 - get_uleb128(&ptr.p8, end), state);
-+                              break;
-+                      case DW_CFA_GNU_window_save:
-+                      default:
-+                              dprintk(1, "Unrecognized CFI op %02X (%p,%p).", ptr.p8[-1], ptr.p8 - 1, end);
-+                              result = 0;
-+                              break;
-+                      }
-+                      break;
-+              case 1:
-+                      result = advance_loc(*ptr.p8++ & 0x3f, state);
-+                      break;
-+              case 2:
-+                      value = *ptr.p8++ & 0x3f;
-+                      set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
-+                      break;
-+              case 3:
-+                      set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
-+                      break;
-+              }
-+              if (ptr.p8 > end) {
-+                      dprintk(1, "Data overrun (%p,%p).", ptr.p8, end);
-+                      result = 0;
-+              }
-+              if (result && targetLoc != 0 && targetLoc < state->loc)
-+                      return 1;
-+      }
-+
-+      if (result && ptr.p8 < end)
-+              dprintk(1, "Data underrun (%p,%p).", ptr.p8, end);
-+
-+      return result
-+         && ptr.p8 == end
-+         && (targetLoc == 0
-+          || (/*todo While in theory this should apply, gcc in practice omits
-+                everything past the function prolog, and hence the location
-+                never reaches the end of the function.
-+              targetLoc < state->loc &&*/ state->label == NULL));
-+}
-+
-+/* Unwind to previous to frame.  Returns 0 if successful, negative
-+ * number in case of an error. */
-+int unwind(struct unwind_frame_info *frame)
-+{
-+#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
-+      const u32 *fde = NULL, *cie = NULL;
-+      const u8 *ptr = NULL, *end = NULL;
-+      unsigned long pc = UNW_PC(frame) - frame->call_frame, sp;
-+      unsigned long startLoc = 0, endLoc = 0, cfa;
-+      unsigned i;
-+      signed ptrType = -1;
-+      uleb128_t retAddrReg = 0;
-+      const struct unwind_table *table;
-+      struct unwind_state state;
-+
-+      if (UNW_PC(frame) == 0)
-+              return -EINVAL;
-+      if ((table = find_table(pc)) != NULL
-+          && !(table->size & (sizeof(*fde) - 1))) {
-+              const u8 *hdr = table->header;
-+              unsigned long tableSize;
-+
-+              smp_rmb();
-+              if (hdr && hdr[0] == 1) {
-+                      switch(hdr[3] & DW_EH_PE_FORM) {
-+                      case DW_EH_PE_native: tableSize = sizeof(unsigned long); break;
-+                      case DW_EH_PE_data2: tableSize = 2; break;
-+                      case DW_EH_PE_data4: tableSize = 4; break;
-+                      case DW_EH_PE_data8: tableSize = 8; break;
-+                      default: tableSize = 0; break;
-+                      }
-+                      ptr = hdr + 4;
-+                      end = hdr + table->hdrsz;
-+                      if (tableSize
-+                          && read_pointer(&ptr, end, hdr[1], 0, 0)
-+                             == (unsigned long)table->address
-+                          && (i = read_pointer(&ptr, end, hdr[2], 0, 0)) > 0
-+                          && i == (end - ptr) / (2 * tableSize)
-+                          && !((end - ptr) % (2 * tableSize))) {
-+                              do {
-+                                      const u8 *cur = ptr + (i / 2) * (2 * tableSize);
-+
-+                                      startLoc = read_pointer(&cur,
-+                                                              cur + tableSize,
-+                                                              hdr[3], 0,
-+                                                              (unsigned long)hdr);
-+                                      if (pc < startLoc)
-+                                              i /= 2;
-+                                      else {
-+                                              ptr = cur - tableSize;
-+                                              i = (i + 1) / 2;
-+                                      }
-+                              } while (startLoc && i > 1);
-+                              if (i == 1
-+                                  && (startLoc = read_pointer(&ptr,
-+                                                              ptr + tableSize,
-+                                                              hdr[3], 0,
-+                                                              (unsigned long)hdr)) != 0
-+                                  && pc >= startLoc)
-+                                      fde = (void *)read_pointer(&ptr,
-+                                                                 ptr + tableSize,
-+                                                                 hdr[3], 0,
-+                                                                 (unsigned long)hdr);
-+                      }
-+              }
-+              if(hdr && !fde)
-+                      dprintk(3, "Binary lookup for %lx failed.", pc);
-+
-+              if (fde != NULL) {
-+                      cie = cie_for_fde(fde, table);
-+                      ptr = (const u8 *)(fde + 2);
-+                      if(cie != NULL
-+                         && cie != &bad_cie
-+                         && cie != &not_fde
-+                         && (ptrType = fde_pointer_type(cie)) >= 0
-+                         && read_pointer(&ptr,
-+                                         (const u8 *)(fde + 1) + *fde,
-+                                         ptrType, 0, 0) == startLoc) {
-+                              if (!(ptrType & DW_EH_PE_indirect))
-+                                      ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
-+                              endLoc = startLoc
-+                                       + read_pointer(&ptr,
-+                                                      (const u8 *)(fde + 1) + *fde,
-+                                                      ptrType, 0, 0);
-+                              if(pc >= endLoc)
-+                                      fde = NULL;
-+                      } else
-+                              fde = NULL;
-+                      if(!fde)
-+                              dprintk(1, "Binary lookup result for %lx discarded.", pc);
-+              }
-+              if (fde == NULL) {
-+                      for (fde = table->address, tableSize = table->size;
-+                           cie = NULL, tableSize > sizeof(*fde)
-+                           && tableSize - sizeof(*fde) >= *fde;
-+                           tableSize -= sizeof(*fde) + *fde,
-+                           fde += 1 + *fde / sizeof(*fde)) {
-+                              cie = cie_for_fde(fde, table);
-+                              if (cie == &bad_cie) {
-+                                      cie = NULL;
-+                                      break;
-+                              }
-+                              if (cie == NULL
-+                                  || cie == &not_fde
-+                                  || (ptrType = fde_pointer_type(cie)) < 0)
-+                                      continue;
-+                              ptr = (const u8 *)(fde + 2);
-+                              startLoc = read_pointer(&ptr,
-+                                                      (const u8 *)(fde + 1) + *fde,
-+                                                      ptrType, 0, 0);
-+                              if (!startLoc)
-+                                      continue;
-+                              if (!(ptrType & DW_EH_PE_indirect))
-+                                      ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
-+                              endLoc = startLoc
-+                                       + read_pointer(&ptr,
-+                                                      (const u8 *)(fde + 1) + *fde,
-+                                                      ptrType, 0, 0);
-+                              if (pc >= startLoc && pc < endLoc)
-+                                      break;
-+                      }
-+                      if(!fde)
-+                              dprintk(3, "Linear lookup for %lx failed.", pc);
-+              }
-+      }
-+      if (cie != NULL) {
-+              memset(&state, 0, sizeof(state));
-+              state.cieEnd = ptr; /* keep here temporarily */
-+              ptr = (const u8 *)(cie + 2);
-+              end = (const u8 *)(cie + 1) + *cie;
-+              frame->call_frame = 1;
-+              if ((state.version = *ptr) != 1)
-+                      cie = NULL; /* unsupported version */
-+              else if (*++ptr) {
-+                      /* check if augmentation size is first (and thus present) */
-+                      if (*ptr == 'z') {
-+                              while (++ptr < end && *ptr) {
-+                                      switch(*ptr) {
-+                                      /* check for ignorable (or already handled)
-+                                       * nul-terminated augmentation string */
-+                                      case 'L':
-+                                      case 'P':
-+                                      case 'R':
-+                                              continue;
-+                                      case 'S':
-+                                              frame->call_frame = 0;
-+                                              continue;
-+                                      default:
-+                                              break;
-+                                      }
-+                                      break;
-+                              }
-+                      }
-+                      if (ptr >= end || *ptr)
-+                              cie = NULL;
-+              }
-+              if(!cie)
-+                      dprintk(1, "CIE unusable (%p,%p).", ptr, end);
-+              ++ptr;
-+      }
-+      if (cie != NULL) {
-+              /* get code aligment factor */
-+              state.codeAlign = get_uleb128(&ptr, end);
-+              /* get data aligment factor */
-+              state.dataAlign = get_sleb128(&ptr, end);
-+              if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
-+                      cie = NULL;
-+              else if (UNW_PC(frame) % state.codeAlign
-+                       || UNW_SP(frame) % sleb128abs(state.dataAlign)) {
-+                      dprintk(1, "Input pointer(s) misaligned (%lx,%lx).",
-+                              UNW_PC(frame), UNW_SP(frame));
-+                      return -EPERM;
-+              } else {
-+                      retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
-+                      /* skip augmentation */
-+                      if (((const char *)(cie + 2))[1] == 'z') {
-+                              uleb128_t augSize = get_uleb128(&ptr, end);
-+
-+                              ptr += augSize;
-+                      }
-+                      if (ptr > end
-+                         || retAddrReg >= ARRAY_SIZE(reg_info)
-+                         || REG_INVALID(retAddrReg)
-+                         || reg_info[retAddrReg].width != sizeof(unsigned long))
-+                              cie = NULL;
-+              }
-+              if(!cie)
-+                      dprintk(1, "CIE validation failed (%p,%p).", ptr, end);
-+      }
-+      if (cie != NULL) {
-+              state.cieStart = ptr;
-+              ptr = state.cieEnd;
-+              state.cieEnd = end;
-+              end = (const u8 *)(fde + 1) + *fde;
-+              /* skip augmentation */
-+              if (((const char *)(cie + 2))[1] == 'z') {
-+                      uleb128_t augSize = get_uleb128(&ptr, end);
-+
-+                      if ((ptr += augSize) > end)
-+                              fde = NULL;
-+              }
-+              if(!fde)
-+                      dprintk(1, "FDE validation failed (%p,%p).", ptr, end);
-+      }
-+      if (cie == NULL || fde == NULL) {
-+#ifdef CONFIG_FRAME_POINTER
-+              unsigned long top, bottom;
-+
-+              if ((UNW_SP(frame) | UNW_FP(frame)) % sizeof(unsigned long))
-+                      return -EPERM;
-+              top = STACK_TOP(frame->task);
-+              bottom = STACK_BOTTOM(frame->task);
-+# if FRAME_RETADDR_OFFSET < 0
-+              if (UNW_SP(frame) < top
-+                  && UNW_FP(frame) <= UNW_SP(frame)
-+                  && bottom < UNW_FP(frame)
-+# else
-+              if (UNW_SP(frame) > top
-+                  && UNW_FP(frame) >= UNW_SP(frame)
-+                  && bottom > UNW_FP(frame)
-+# endif
-+                 && !((UNW_SP(frame) | UNW_FP(frame))
-+                      & (sizeof(unsigned long) - 1))) {
-+                      unsigned long link;
-+
-+                      if (!probe_kernel_address(
-+                                      (unsigned long *)(UNW_FP(frame)
-+                                                        + FRAME_LINK_OFFSET),
-+                                                link)
-+# if FRAME_RETADDR_OFFSET < 0
-+                         && link > bottom && link < UNW_FP(frame)
-+# else
-+                         && link > UNW_FP(frame) && link < bottom
-+# endif
-+                         && !(link & (sizeof(link) - 1))
-+                         && !probe_kernel_address(
-+                                        (unsigned long *)(UNW_FP(frame)
-+                                                          + FRAME_RETADDR_OFFSET), UNW_PC(frame))) {
-+                              UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
-+# if FRAME_RETADDR_OFFSET < 0
-+                                      -
-+# else
-+                                      +
-+# endif
-+                                        sizeof(UNW_PC(frame));
-+                              UNW_FP(frame) = link;
-+                              return 0;
-+                      }
-+              }
-+#endif
-+              return -ENXIO;
-+      }
-+      state.org = startLoc;
-+      memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
-+      /* process instructions */
-+      if (!processCFI(ptr, end, pc, ptrType, &state)
-+         || state.loc > endLoc
-+         || state.regs[retAddrReg].where == Nowhere
-+         || state.cfa.reg >= ARRAY_SIZE(reg_info)
-+         || reg_info[state.cfa.reg].width != sizeof(unsigned long)
-+         || FRAME_REG(state.cfa.reg, unsigned long) % sizeof(unsigned long)
-+         || state.cfa.offs % sizeof(unsigned long)) {
-+              dprintk(1, "Unusable unwind info (%p,%p).", ptr, end);
-+              return -EIO;
-+      }
-+      /* update frame */
-+#ifndef CONFIG_AS_CFI_SIGNAL_FRAME
-+      if(frame->call_frame
-+         && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
-+              frame->call_frame = 0;
-+#endif
-+      cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
-+      startLoc = min((unsigned long)UNW_SP(frame), cfa);
-+      endLoc = max((unsigned long)UNW_SP(frame), cfa);
-+      if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
-+              startLoc = min(STACK_LIMIT(cfa), cfa);
-+              endLoc = max(STACK_LIMIT(cfa), cfa);
-+      }
-+#ifndef CONFIG_64BIT
-+# define CASES CASE(8); CASE(16); CASE(32)
-+#else
-+# define CASES CASE(8); CASE(16); CASE(32); CASE(64)
 +#endif
-+      pc = UNW_PC(frame);
-+      sp = UNW_SP(frame);
-+      for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
-+              if (REG_INVALID(i)) {
-+                      if (state.regs[i].where == Nowhere)
-+                              continue;
-+                      dprintk(1, "Cannot restore register %u (%d).",
-+                              i, state.regs[i].where);
-+                      return -EIO;
-+              }
-+              switch(state.regs[i].where) {
-+              default:
-+                      break;
-+              case Register:
-+                      if (state.regs[i].value >= ARRAY_SIZE(reg_info)
-+                         || REG_INVALID(state.regs[i].value)
-+                         || reg_info[i].width > reg_info[state.regs[i].value].width) {
-+                              dprintk(1, "Cannot restore register %u from register %lu.",
-+                                      i, state.regs[i].value);
-+                              return -EIO;
-+                      }
-+                      switch(reg_info[state.regs[i].value].width) {
-+#define CASE(n) \
-+                      case sizeof(u##n): \
-+                              state.regs[i].value = FRAME_REG(state.regs[i].value, \
-+                                                              const u##n); \
-+                              break
-+                      CASES;
-+#undef CASE
-+                      default:
-+                              dprintk(1, "Unsupported register size %u (%lu).",
-+                                      reg_info[state.regs[i].value].width,
-+                                      state.regs[i].value);
-+                              return -EIO;
-+                      }
-+                      break;
-+              }
-+      }
-+      for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
-+              if (REG_INVALID(i))
-+                      continue;
-+              switch(state.regs[i].where) {
-+              case Nowhere:
-+                      if (reg_info[i].width != sizeof(UNW_SP(frame))
-+                         || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
-+                            != &UNW_SP(frame))
-+                              continue;
-+                      UNW_SP(frame) = cfa;
-+                      break;
-+              case Register:
-+                      switch(reg_info[i].width) {
-+#define CASE(n) case sizeof(u##n): \
-+                              FRAME_REG(i, u##n) = state.regs[i].value; \
-+                              break
-+                      CASES;
-+#undef CASE
-+                      default:
-+                              dprintk(1, "Unsupported register size %u (%u).",
-+                                      reg_info[i].width, i);
-+                              return -EIO;
-+                      }
-+                      break;
-+              case Value:
-+                      if (reg_info[i].width != sizeof(unsigned long)) {
-+                              dprintk(1, "Unsupported value size %u (%u).",
-+                                      reg_info[i].width, i);
-+                              return -EIO;
-+                      }
-+                      FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
-+                                                          * state.dataAlign;
-+                      break;
-+              case Memory: {
-+                              unsigned long addr = cfa + state.regs[i].value
-+                                                         * state.dataAlign;
-+
-+                              if ((state.regs[i].value * state.dataAlign)
-+                                  % sizeof(unsigned long)
-+                                  || addr < startLoc
-+                                  || addr + sizeof(unsigned long) < addr
-+                                  || addr + sizeof(unsigned long) > endLoc) {
-+                                      dprintk(1, "Bad memory location %lx (%lx).",
-+                                              addr, state.regs[i].value);
-+                                      return -EIO;
-+                              }
-+                              switch(reg_info[i].width) {
-+#define CASE(n)     case sizeof(u##n): \
-+                                      probe_kernel_address((u##n *)addr, FRAME_REG(i, u##n)); \
-+                                      break
-+                              CASES;
-+#undef CASE
-+                              default:
-+                                      dprintk(1, "Unsupported memory size %u (%u).",
-+                                              reg_info[i].width, i);
-+                                      return -EIO;
-+                              }
-+                      }
-+                      break;
-+              }
-+      }
-+
-+      if (UNW_PC(frame) % state.codeAlign
-+          || UNW_SP(frame) % sleb128abs(state.dataAlign)) {
-+              dprintk(1, "Output pointer(s) misaligned (%lx,%lx).",
-+                      UNW_PC(frame), UNW_SP(frame));
-+              return -EIO;
-+      }
-+      if (pc == UNW_PC(frame) && sp == UNW_SP(frame)) {
-+              dprintk(1, "No progress (%lx,%lx).", pc, sp);
-+              return -EIO;
-+      }
-+
-+      return 0;
-+#undef CASES
-+#undef FRAME_REG
-+}
-+EXPORT_SYMBOL(unwind);
-+
-+int unwind_init_frame_info(struct unwind_frame_info *info,
-+                           struct task_struct *tsk,
-+                           /*const*/ struct pt_regs *regs)
-+{
-+      info->task = tsk;
-+      info->call_frame = 0;
-+      arch_unw_init_frame_info(info, regs);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(unwind_init_frame_info);
 +
-+/*
-+ * Prepare to unwind a blocked task.
-+ */
-+int unwind_init_blocked(struct unwind_frame_info *info,
-+                        struct task_struct *tsk)
+ static inline int unwind_init_frame_info(struct unwind_frame_info *info,
+                                          struct task_struct *tsk,
+                                          const struct pt_regs *regs)
+@@ -122,6 +65,4 @@
+       return -ENOSYS;
+ }
+-#endif
+-
+ #endif /* _LINUX_UNWIND_H */
+diff -Nurb linux-2.6.22-590/include/linux/usb.h linux-2.6.22-570/include/linux/usb.h
+--- linux-2.6.22-590/include/linux/usb.h       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/linux/usb.h       2007-07-08 19:32:17.000000000 -0400
+@@ -146,10 +146,6 @@
+                                        * active alternate setting */
+       unsigned num_altsetting;        /* number of alternate settings */
+-      /* If there is an interface association descriptor then it will list
+-       * the associated interfaces */
+-      struct usb_interface_assoc_descriptor *intf_assoc;
+-
+       int minor;                      /* minor number this interface is
+                                        * bound to */
+       enum usb_interface_condition condition;         /* state of binding */
+@@ -179,7 +175,6 @@
+ /* this maximum is arbitrary */
+ #define USB_MAXINTERFACES     32
+-#define USB_MAXIADS           USB_MAXINTERFACES/2
+ /**
+  * struct usb_interface_cache - long-term representation of a device interface
+@@ -250,11 +245,6 @@
+       struct usb_config_descriptor    desc;
+       char *string;           /* iConfiguration string, if present */
+-
+-      /* List of any Interface Association Descriptors in this
+-       * configuration. */
+-      struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];
+-
+       /* the interfaces associated with this configuration,
+        * stored in no particular order */
+       struct usb_interface *interface[USB_MAXINTERFACES];
+diff -Nurb linux-2.6.22-590/include/linux/user_namespace.h linux-2.6.22-570/include/linux/user_namespace.h
+--- linux-2.6.22-590/include/linux/user_namespace.h    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/linux/user_namespace.h    1969-12-31 19:00:00.000000000 -0500
+@@ -1,61 +0,0 @@
+-#ifndef _LINUX_USER_NAMESPACE_H
+-#define _LINUX_USER_NAMESPACE_H
+-
+-#include <linux/kref.h>
+-#include <linux/nsproxy.h>
+-#include <linux/sched.h>
+-#include <linux/err.h>
+-
+-#define UIDHASH_BITS  (CONFIG_BASE_SMALL ? 3 : 8)
+-#define UIDHASH_SZ    (1 << UIDHASH_BITS)
+-
+-struct user_namespace {
+-      struct kref             kref;
+-      struct list_head        uidhash_table[UIDHASH_SZ];
+-      struct user_struct      *root_user;
+-};
+-
+-extern struct user_namespace init_user_ns;
+-
+-#ifdef CONFIG_USER_NS
+-
+-static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
+-{
+-      if (ns)
+-              kref_get(&ns->kref);
+-      return ns;
+-}
+-
+-extern struct user_namespace *copy_user_ns(int flags,
+-                                         struct user_namespace *old_ns);
+-extern void free_user_ns(struct kref *kref);
+-
+-static inline void put_user_ns(struct user_namespace *ns)
+-{
+-      if (ns)
+-              kref_put(&ns->kref, free_user_ns);
+-}
+-
+-#else
+-
+-static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
+-{
+-      return &init_user_ns;
+-}
+-
+-static inline struct user_namespace *copy_user_ns(int flags,
+-                                                struct user_namespace *old_ns)
+-{
+-      if (flags & CLONE_NEWUSER)
+-              return ERR_PTR(-EINVAL);
+-
+-      return NULL;
+-}
+-
+-static inline void put_user_ns(struct user_namespace *ns)
+-{
+-}
+-
+-#endif
+-
+-#endif /* _LINUX_USER_H */
+diff -Nurb linux-2.6.22-590/include/linux/utsname.h linux-2.6.22-570/include/linux/utsname.h
+--- linux-2.6.22-590/include/linux/utsname.h   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/linux/utsname.h   2007-07-08 19:32:17.000000000 -0400
+@@ -48,14 +48,26 @@
+       kref_get(&ns->kref);
+ }
+-extern struct uts_namespace *copy_utsname(unsigned long flags,
+-                                      struct uts_namespace *ns);
++#ifdef CONFIG_UTS_NS
++extern struct uts_namespace *copy_utsname(int flags, struct uts_namespace *ns);
+ extern void free_uts_ns(struct kref *kref);
+ static inline void put_uts_ns(struct uts_namespace *ns)
+ {
+       kref_put(&ns->kref, free_uts_ns);
+ }
++#else
++static inline struct uts_namespace *copy_utsname(int flags,
++                                              struct uts_namespace *ns)
 +{
-+      info->task = tsk;
-+      info->call_frame = 0;
-+      arch_unw_init_blocked(info);
-+
-+      return 0;
++      return ns;
 +}
-+EXPORT_SYMBOL(unwind_init_blocked);
 +
-+/*
-+ * Prepare to unwind the currently running thread.
-+ */
-+int unwind_init_running(struct unwind_frame_info *info,
-+                        asmlinkage int (*callback)(struct unwind_frame_info *,
-+                                                   void *arg),
-+                        void *arg)
++static inline void put_uts_ns(struct uts_namespace *ns)
 +{
-+      info->task = current;
-+      info->call_frame = 0;
-+
-+      return arch_unwind_init_running(info, callback, arg);
 +}
-+EXPORT_SYMBOL(unwind_init_running);
++#endif
 +
-diff -Nurb linux-2.6.22-570/kernel/user.c linux-2.6.22-590/kernel/user.c
---- linux-2.6.22-570/kernel/user.c     2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/user.c     2008-01-02 13:56:38.000000000 -0500
-@@ -14,17 +14,17 @@
- #include <linux/bitops.h>
- #include <linux/key.h>
- #include <linux/interrupt.h>
-+#include <linux/module.h>
-+#include <linux/user_namespace.h>
+ static inline struct new_utsname *utsname(void)
+ {
+       return &current->nsproxy->uts_ns->name;
+diff -Nurb linux-2.6.22-590/include/linux/vmalloc.h linux-2.6.22-570/include/linux/vmalloc.h
+--- linux-2.6.22-590/include/linux/vmalloc.h   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/linux/vmalloc.h   2007-07-08 19:32:17.000000000 -0400
+@@ -65,10 +65,9 @@
+                                         unsigned long flags, int node,
+                                         gfp_t gfp_mask);
+ extern struct vm_struct *remove_vm_area(void *addr);
+-
+ extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
+                       struct page ***pages);
+-extern void unmap_kernel_range(unsigned long addr, unsigned long size);
++extern void unmap_vm_area(struct vm_struct *area);
  
  /*
-  * UID task count cache, to get fast user lookup in "alloc_uid"
-  * when changing user ID's (ie setuid() and friends).
-  */
+  *    Internals.  Dont't use..
+diff -Nurb linux-2.6.22-590/include/net/addrconf.h linux-2.6.22-570/include/net/addrconf.h
+--- linux-2.6.22-590/include/net/addrconf.h    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/addrconf.h    2008-01-23 19:16:05.000000000 -0500
+@@ -61,7 +61,7 @@
+ extern int                    ipv6_chk_addr(struct in6_addr *addr,
+                                             struct net_device *dev,
+                                             int strict);
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+ extern int                    ipv6_chk_home_addr(struct in6_addr *addr);
+ #endif
+ extern struct inet6_ifaddr *  ipv6_get_ifaddr(struct in6_addr *addr,
+diff -Nurb linux-2.6.22-590/include/net/af_unix.h linux-2.6.22-570/include/net/af_unix.h
+--- linux-2.6.22-590/include/net/af_unix.h     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/af_unix.h     2008-01-23 19:16:05.000000000 -0500
+@@ -91,11 +91,12 @@
+ #define unix_sk(__sk) ((struct unix_sock *)__sk)
  
--#define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 8)
--#define UIDHASH_SZ            (1 << UIDHASH_BITS)
- #define UIDHASH_MASK          (UIDHASH_SZ - 1)
- #define __uidhashfn(xid,uid)  ((((uid) >> UIDHASH_BITS) + ((uid)^(xid))) & UIDHASH_MASK)
--#define uidhashentry(xid,uid) (uidhash_table + __uidhashfn((xid),(uid)))
-+#define uidhashentry(ns, xid, uid)    ((ns)->uidhash_table + __uidhashfn(xid, uid))
+ #ifdef CONFIG_SYSCTL
+-extern void unix_sysctl_register(struct net *net);
+-extern void unix_sysctl_unregister(struct net *net);
++extern int sysctl_unix_max_dgram_qlen;
++extern void unix_sysctl_register(void);
++extern void unix_sysctl_unregister(void);
+ #else
+-static inline void unix_sysctl_register(struct net *net) {}
+-static inline void unix_sysctl_unregister(struct net *net) {}
++static inline void unix_sysctl_register(void) {}
++static inline void unix_sysctl_unregister(void) {}
+ #endif
+ #endif
+ #endif
+diff -Nurb linux-2.6.22-590/include/net/arp.h linux-2.6.22-570/include/net/arp.h
+--- linux-2.6.22-590/include/net/arp.h 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/arp.h 2007-07-08 19:32:17.000000000 -0400
+@@ -11,7 +11,7 @@
  
- static struct kmem_cache *uid_cachep;
- static struct list_head uidhash_table[UIDHASH_SZ];
-@@ -94,9 +94,10 @@
+ extern void   arp_init(void);
+ extern int    arp_find(unsigned char *haddr, struct sk_buff *skb);
+-extern int    arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);
++extern int    arp_ioctl(unsigned int cmd, void __user *arg);
+ extern void     arp_send(int type, int ptype, __be32 dest_ip,
+                        struct net_device *dev, __be32 src_ip,
+                        unsigned char *dest_hw, unsigned char *src_hw, unsigned char *th);
+diff -Nurb linux-2.6.22-590/include/net/dst.h linux-2.6.22-570/include/net/dst.h
+--- linux-2.6.22-590/include/net/dst.h 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/dst.h 2007-07-08 19:32:17.000000000 -0400
+@@ -47,6 +47,7 @@
+ #define DST_NOXFRM            2
+ #define DST_NOPOLICY          4
+ #define DST_NOHASH            8
++#define DST_BALANCED            0x10
+       unsigned long           expires;
+       unsigned short          header_len;     /* more space at head required */
+diff -Nurb linux-2.6.22-590/include/net/fib_rules.h linux-2.6.22-570/include/net/fib_rules.h
+--- linux-2.6.22-590/include/net/fib_rules.h   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/fib_rules.h   2007-07-08 19:32:17.000000000 -0400
+@@ -56,12 +56,12 @@
+       int                     (*fill)(struct fib_rule *, struct sk_buff *,
+                                       struct nlmsghdr *,
+                                       struct fib_rule_hdr *);
+-      u32                     (*default_pref)(struct fib_rules_ops *ops);
++      u32                     (*default_pref)(void);
+       size_t                  (*nlmsg_payload)(struct fib_rule *);
+       /* Called after modifications to the rules set, must flush
+        * the route cache if one exists. */
+-      void                    (*flush_cache)(struct fib_rules_ops *ops);
++      void                    (*flush_cache)(void);
+       int                     nlgroup;
+       const struct nla_policy *policy;
+@@ -101,8 +101,8 @@
+       return frh->table;
+ }
+-extern int                    fib_rules_register(struct net *net, struct fib_rules_ops *);
+-extern int                    fib_rules_unregister(struct net *net, struct fib_rules_ops *);
++extern int                    fib_rules_register(struct fib_rules_ops *);
++extern int                    fib_rules_unregister(struct fib_rules_ops *);
+ extern int                    fib_rules_lookup(struct fib_rules_ops *,
+                                                struct flowi *, int flags,
+diff -Nurb linux-2.6.22-590/include/net/flow.h linux-2.6.22-570/include/net/flow.h
+--- linux-2.6.22-590/include/net/flow.h        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/flow.h        2007-07-08 19:32:17.000000000 -0400
+@@ -8,11 +8,9 @@
+ #define _NET_FLOW_H
+ #include <linux/in6.h>
+-#include <net/net_namespace.h>
+ #include <asm/atomic.h>
+ struct flowi {
+-      struct net *fl_net;
+       int     oif;
+       int     iif;
+       __u32   mark;
+@@ -69,16 +67,20 @@
+               __be32          spi;
++#ifdef CONFIG_IPV6_MIP6
+               struct {
+                       __u8    type;
+               } mht;
++#endif
+       } uli_u;
+ #define fl_ip_sport   uli_u.ports.sport
+ #define fl_ip_dport   uli_u.ports.dport
+ #define fl_icmp_type  uli_u.icmpt.type
+ #define fl_icmp_code  uli_u.icmpt.code
+ #define fl_ipsec_spi  uli_u.spi
++#ifdef CONFIG_IPV6_MIP6
+ #define fl_mh_type    uli_u.mht.type
++#endif
+       __u32           secid;  /* used by xfrm; see secid.txt */
+ } __attribute__((__aligned__(BITS_PER_LONG/8)));
+diff -Nurb linux-2.6.22-590/include/net/inet6_hashtables.h linux-2.6.22-570/include/net/inet6_hashtables.h
+--- linux-2.6.22-590/include/net/inet6_hashtables.h    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/inet6_hashtables.h    2007-07-08 19:32:17.000000000 -0400
+@@ -62,31 +62,31 @@
+                                          const __be16 sport,
+                                          const struct in6_addr *daddr,
+                                          const u16 hnum,
+-                                         const int dif, struct net *net);
++                                         const int dif);
+ extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
+                                         const struct in6_addr *daddr,
+                                         const unsigned short hnum,
+-                                        const int dif, struct net *net);
++                                        const int dif);
+ static inline struct sock *__inet6_lookup(struct inet_hashinfo *hashinfo,
+                                         const struct in6_addr *saddr,
+                                         const __be16 sport,
+                                         const struct in6_addr *daddr,
+                                         const u16 hnum,
+-                                        const int dif, struct net *net)
++                                        const int dif)
  {
-       struct user_struct *ret;
-       unsigned long flags;
-+      struct user_namespace *ns = current->nsproxy->user_ns;
+       struct sock *sk = __inet6_lookup_established(hashinfo, saddr, sport,
+-                                                   daddr, hnum, dif, net);
++                                                   daddr, hnum, dif);
+       if (sk)
+               return sk;
  
-       spin_lock_irqsave(&uidhash_lock, flags);
--      ret = uid_hash_find(xid, uid, uidhashentry(xid, uid));
-+      ret = uid_hash_find(xid, uid, uidhashentry(ns, xid, uid));
-       spin_unlock_irqrestore(&uidhash_lock, flags);
-       return ret;
+-      return inet6_lookup_listener(hashinfo, daddr, hnum, dif, net);
++      return inet6_lookup_listener(hashinfo, daddr, hnum, dif);
+ }
+ extern struct sock *inet6_lookup(struct inet_hashinfo *hashinfo,
+                                const struct in6_addr *saddr, const __be16 sport,
+                                const struct in6_addr *daddr, const __be16 dport,
+-                               const int dif, struct net *net);
++                               const int dif);
+ #endif /* defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) */
+ #endif /* _INET6_HASHTABLES_H */
+diff -Nurb linux-2.6.22-590/include/net/inet_hashtables.h linux-2.6.22-570/include/net/inet_hashtables.h
+--- linux-2.6.22-590/include/net/inet_hashtables.h     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/inet_hashtables.h     2007-07-08 19:32:17.000000000 -0400
+@@ -75,7 +75,6 @@
+  * ports are created in O(1) time?  I thought so. ;-) -DaveM
+  */
+ struct inet_bind_bucket {
+-      struct net              *net;
+       unsigned short          port;
+       signed short            fastreuse;
+       struct hlist_node       node;
+@@ -139,35 +138,34 @@
+ extern struct inet_bind_bucket *
+                   inet_bind_bucket_create(struct kmem_cache *cachep,
+                                           struct inet_bind_hashbucket *head,
+-                                          struct net *net,
+                                           const unsigned short snum);
+ extern void inet_bind_bucket_destroy(struct kmem_cache *cachep,
+                                    struct inet_bind_bucket *tb);
+-static inline int inet_bhashfn(struct net *net, const __u16 lport, const int bhash_size)
++static inline int inet_bhashfn(const __u16 lport, const int bhash_size)
+ {
+-      return (((unsigned long)net) ^ lport) & (bhash_size - 1);
++      return lport & (bhash_size - 1);
  }
-@@ -122,7 +123,8 @@
  
- struct user_struct * alloc_uid(xid_t xid, uid_t uid)
+ extern void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
+                          const unsigned short snum);
+ /* These can have wildcards, don't try too hard. */
+-static inline int inet_lhashfn(struct net *net, const unsigned short num)
++static inline int inet_lhashfn(const unsigned short num)
  {
--      struct list_head *hashent = uidhashentry(xid, uid);
-+      struct user_namespace *ns = current->nsproxy->user_ns;
-+      struct list_head *hashent = uidhashentry(ns,xid, uid);
-       struct user_struct *up;
+-      return (((unsigned long)net) ^ num) & (INET_LHTABLE_SIZE - 1);
++      return num & (INET_LHTABLE_SIZE - 1);
+ }
  
-       spin_lock_irq(&uidhash_lock);
-@@ -212,11 +214,11 @@
-                       0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+ static inline int inet_sk_listen_hashfn(const struct sock *sk)
+ {
+-      return inet_lhashfn(sk->sk_net, inet_sk(sk)->num);
++      return inet_lhashfn(inet_sk(sk)->num);
+ }
  
-       for(n = 0; n < UIDHASH_SZ; ++n)
--              INIT_LIST_HEAD(uidhash_table + n);
-+              INIT_LIST_HEAD(init_user_ns.uidhash_table + n);
+ /* Caller must disable local BH processing. */
+ static inline void __inet_inherit_port(struct inet_hashinfo *table,
+                                      struct sock *sk, struct sock *child)
+ {
+-      const int bhash = inet_bhashfn(sk->sk_net, inet_sk(child)->num, table->bhash_size);
++      const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size);
+       struct inet_bind_hashbucket *head = &table->bhash[bhash];
+       struct inet_bind_bucket *tb;
  
-       /* Insert the root user immediately (init already runs as root) */
-       spin_lock_irq(&uidhash_lock);
--      uid_hash_insert(&root_user, uidhashentry(0,0));
-+      uid_hash_insert(&root_user, uidhashentry(&init_user_ns, 0, 0));
-       spin_unlock_irq(&uidhash_lock);
+@@ -276,13 +274,12 @@
+ extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
+                                          const __be32 daddr,
+                                          const unsigned short hnum,
+-                                         const int dif, struct net *net);
++                                         const int dif);
  
-       return 0;
-diff -Nurb linux-2.6.22-570/kernel/user_namespace.c linux-2.6.22-590/kernel/user_namespace.c
---- linux-2.6.22-570/kernel/user_namespace.c   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/kernel/user_namespace.c   2008-01-02 13:56:38.000000000 -0500
-@@ -0,0 +1,87 @@
-+/*
-+ *  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, version 2 of the
-+ *  License.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/version.h>
-+#include <linux/nsproxy.h>
-+#include <linux/user_namespace.h>
-+
-+struct user_namespace init_user_ns = {
-+      .kref = {
-+              .refcount       = ATOMIC_INIT(2),
-+      },
-+      .root_user = &root_user,
-+};
-+
-+EXPORT_SYMBOL_GPL(init_user_ns);
-+
-+#ifdef CONFIG_USER_NS
-+
-+/*
-+ * Clone a new ns copying an original user ns, setting refcount to 1
-+ * @old_ns: namespace to clone
-+ * Return NULL on error (failure to kmalloc), new ns otherwise
-+ */
-+static struct user_namespace *clone_user_ns(struct user_namespace *old_ns)
-+{
-+      struct user_namespace *ns;
-+      struct user_struct *new_user;
-+      int n;
-+
-+      ns = kmalloc(sizeof(struct user_namespace), GFP_KERNEL);
-+      if (!ns)
-+              return ERR_PTR(-ENOMEM);
-+
-+      kref_init(&ns->kref);
-+
-+      for (n = 0; n < UIDHASH_SZ; ++n)
-+              INIT_LIST_HEAD(ns->uidhash_table + n);
-+
-+      /* Insert new root user.  */
-+      ns->root_user = alloc_uid(ns, 0);
-+      if (!ns->root_user) {
-+              kfree(ns);
-+              return ERR_PTR(-ENOMEM);
-+      }
-+
-+      /* Reset current->user with a new one */
-+      new_user = alloc_uid(ns, current->uid);
-+      if (!new_user) {
-+              free_uid(ns->root_user);
-+              kfree(ns);
-+              return ERR_PTR(-ENOMEM);
-+      }
-+
-+      switch_uid(new_user);
-+      return ns;
-+}
-+
-+struct user_namespace * copy_user_ns(int flags, struct user_namespace *old_ns)
-+{
-+      struct user_namespace *new_ns;
-+
-+      BUG_ON(!old_ns);
-+      get_user_ns(old_ns);
-+
-+      if (!(flags & CLONE_NEWUSER))
-+              return old_ns;
-+
-+      new_ns = clone_user_ns(old_ns);
-+
-+      put_user_ns(old_ns);
-+      return new_ns;
-+}
-+
-+void free_user_ns(struct kref *kref)
-+{
-+      struct user_namespace *ns;
-+
-+      ns = container_of(kref, struct user_namespace, kref);
-+      kfree(ns);
-+}
-+
-+#endif /* CONFIG_USER_NS */
-diff -Nurb linux-2.6.22-570/kernel/utsname.c linux-2.6.22-590/kernel/utsname.c
---- linux-2.6.22-570/kernel/utsname.c  2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/kernel/utsname.c  2008-01-02 13:56:38.000000000 -0500
-@@ -14,6 +14,7 @@
- #include <linux/utsname.h>
- #include <linux/version.h>
- #include <linux/vserver/global.h>
-+#include <linux/err.h>
+ static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo,
+-                                              __be32 daddr, __be16 dport,
+-                                              int dif, struct net *net)
++                                              __be32 daddr, __be16 dport, int dif)
+ {
+-      return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif, net);
++      return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif);
+ }
+ /* Socket demux engine toys. */
+@@ -316,34 +313,30 @@
+                                  (((__force __u64)(__be32)(__daddr)) << 32) | \
+                                  ((__force __u64)(__be32)(__saddr)));
+ #endif /* __BIG_ENDIAN */
+-#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif, __net)\
++#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+       (((__sk)->sk_hash == (__hash))                          &&      \
+        ((*((__addrpair *)&(inet_sk(__sk)->daddr))) == (__cookie))     &&      \
+        ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))      &&      \
+-       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))) && \
+-       ((__sk)->sk_net == __net))
+-#define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif, __net)\
++       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
++#define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+       (((__sk)->sk_hash == (__hash))                          &&      \
+        ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&     \
+        ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&      \
+-       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))) && \
+-       ((__sk)->sk_net == __net))
++       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+ #else /* 32-bit arch */
+ #define INET_ADDR_COOKIE(__name, __saddr, __daddr)
+-#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif, __net) \
++#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)  \
+       (((__sk)->sk_hash == (__hash))                          &&      \
+        (inet_sk(__sk)->daddr          == (__saddr))           &&      \
+        (inet_sk(__sk)->rcv_saddr      == (__daddr))           &&      \
+        ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))      &&      \
+-       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))) && \
+-       ((__sk)->sk_net == __net))
+-#define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif, __net) \
++       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
++#define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif)        \
+       (((__sk)->sk_hash == (__hash))                          &&      \
+        (inet_twsk(__sk)->tw_daddr     == (__saddr))           &&      \
+        (inet_twsk(__sk)->tw_rcv_saddr == (__daddr))           &&      \
+        ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&      \
+-       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))) && \
+-       ((__sk)->sk_net == __net))
++       (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+ #endif /* 64-bit arch */
  
  /*
-  * Clone a new ns copying an original utsname, setting refcount to 1
-@@ -25,11 +26,12 @@
-       struct uts_namespace *ns;
+@@ -356,7 +349,7 @@
+       __inet_lookup_established(struct inet_hashinfo *hashinfo,
+                                 const __be32 saddr, const __be16 sport,
+                                 const __be32 daddr, const u16 hnum,
+-                                const int dif, struct net *net)
++                                const int dif)
+ {
+       INET_ADDR_COOKIE(acookie, saddr, daddr)
+       const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
+@@ -365,19 +358,19 @@
+       /* Optimize here for direct hit, only listening connections can
+        * have wildcards anyways.
+        */
+-      unsigned int hash = inet_ehashfn(net, daddr, hnum, saddr, sport);
++      unsigned int hash = inet_ehashfn(daddr, hnum, saddr, sport);
+       struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
  
-       ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL);
--      if (ns) {
-+      if (!ns)
-+              return ERR_PTR(-ENOMEM);
-+ 
-               memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
-               kref_init(&ns->kref);
--              atomic_inc(&vs_global_uts_ns);
--      }
-+
-       return ns;
- }
+       prefetch(head->chain.first);
+       read_lock(&head->lock);
+       sk_for_each(sk, node, &head->chain) {
+-              if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif, net))
++              if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
+                       goto hit; /* You sunk my battleship! */
+       }
  
-@@ -39,7 +41,7 @@
-  * utsname of this process won't be seen by parent, and vice
-  * versa.
-  */
--struct uts_namespace *copy_utsname(int flags, struct uts_namespace *old_ns)
-+struct uts_namespace *copy_utsname(unsigned long flags, struct uts_namespace *old_ns)
+       /* Must check for a TIME_WAIT'er before going to listener hash. */
+       sk_for_each(sk, node, &head->twchain) {
+-              if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif, net))
++              if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
+                       goto hit;
+       }
+       sk = NULL;
+@@ -393,32 +386,32 @@
+       inet_lookup_established(struct inet_hashinfo *hashinfo,
+                               const __be32 saddr, const __be16 sport,
+                               const __be32 daddr, const __be16 dport,
+-                              const int dif, struct net *net)
++                              const int dif)
  {
-       struct uts_namespace *new_ns;
+       return __inet_lookup_established(hashinfo, saddr, sport, daddr,
+-                                       ntohs(dport), dif, net);
++                                       ntohs(dport), dif);
+ }
  
-diff -Nurb linux-2.6.22-570/kernel/utsname_sysctl.c linux-2.6.22-590/kernel/utsname_sysctl.c
---- linux-2.6.22-570/kernel/utsname_sysctl.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/kernel/utsname_sysctl.c   2008-01-02 13:56:38.000000000 -0500
-@@ -18,10 +18,7 @@
- static void *get_uts(ctl_table *table, int write)
+ static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo,
+                                        const __be32 saddr, const __be16 sport,
+                                        const __be32 daddr, const __be16 dport,
+-                                       const int dif, struct net *net)
++                                       const int dif)
  {
-       char *which = table->data;
--#ifdef CONFIG_UTS_NS
--      struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
--      which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
--#endif
-+
-       if (!write)
-               down_read(&uts_sem);
-       else
-diff -Nurb linux-2.6.22-570/kernel/workqueue.c linux-2.6.22-590/kernel/workqueue.c
---- linux-2.6.22-570/kernel/workqueue.c        2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/kernel/workqueue.c        2008-01-02 13:56:38.000000000 -0500
-@@ -282,8 +282,8 @@
-       struct cpu_workqueue_struct *cwq = __cwq;
-       DEFINE_WAIT(wait);
+       u16 hnum = ntohs(dport);
+       struct sock *sk = __inet_lookup_established(hashinfo, saddr, sport, daddr,
+-                                                  hnum, dif, net);
+-      return sk ? : __inet_lookup_listener(hashinfo, daddr, hnum, dif, net);
++                                                  hnum, dif);
++      return sk ? : __inet_lookup_listener(hashinfo, daddr, hnum, dif);
+ }
  
--      if (!cwq->wq->freezeable)
--              current->flags |= PF_NOFREEZE;
-+      if (cwq->wq->freezeable)
-+              set_freezable();
+ static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
+                                      const __be32 saddr, const __be16 sport,
+                                      const __be32 daddr, const __be16 dport,
+-                                     const int dif, struct net *net)
++                                     const int dif)
+ {
+       struct sock *sk;
  
-       set_user_nice(current, -5);
+       local_bh_disable();
+-      sk = __inet_lookup(hashinfo, saddr, sport, daddr, dport, dif, net);
++      sk = __inet_lookup(hashinfo, saddr, sport, daddr, dport, dif);
+       local_bh_enable();
  
-diff -Nurb linux-2.6.22-570/lib/Kconfig.debug linux-2.6.22-590/lib/Kconfig.debug
---- linux-2.6.22-570/lib/Kconfig.debug 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/lib/Kconfig.debug 2008-01-02 13:56:38.000000000 -0500
-@@ -364,6 +364,24 @@
-         some architectures or if you use external debuggers.
-         If you don't debug the kernel, you can say N.
+       return sk;
+diff -Nurb linux-2.6.22-590/include/net/inet_sock.h linux-2.6.22-570/include/net/inet_sock.h
+--- linux-2.6.22-590/include/net/inet_sock.h   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/inet_sock.h   2007-07-08 19:32:17.000000000 -0400
+@@ -171,12 +171,10 @@
+ extern u32 inet_ehash_secret;
+ extern void build_ehash_secret(void);
  
-+config UNWIND_INFO
-+      bool "Compile the kernel with frame unwind information"
-+      depends on !IA64 && !PARISC && !ARM
-+      depends on !MODULES || !(MIPS || PPC || SUPERH || V850)
-+      help
-+        If you say Y here the resulting kernel image will be slightly larger
-+        but not slower, and it will give very useful debugging information.
-+        If you don't debug the kernel, you can say N, but we may not be able
-+        to solve problems without frame unwind information or frame pointers.
-+
-+config STACK_UNWIND
-+      bool "Stack unwind support"
-+      depends on UNWIND_INFO
-+      depends on X86
-+      help
-+        This enables more precise stack traces, omitting all unrelated
-+        occurrences of pointers into kernel code from the dump.
-+
- config FORCED_INLINING
-       bool "Force gcc to inline functions marked 'inline'"
-       depends on DEBUG_KERNEL
-@@ -409,6 +427,9 @@
- config FAULT_INJECTION
-       bool "Fault-injection framework"
-       depends on DEBUG_KERNEL
-+      # could support fp on X86_32 here too, but let's not
-+      select UNWIND_INFO if X86
-+      select STACK_UNWIND if X86
-       help
-         Provide fault-injection framework.
-         For more details, see Documentation/fault-injection/.
-@@ -445,3 +466,5 @@
-       select FRAME_POINTER
-       help
-         Provide stacktrace filter for fault-injection capabilities
-+
-+source "lib/Kconfig.kgdb"
-diff -Nurb linux-2.6.22-570/lib/Kconfig.kgdb linux-2.6.22-590/lib/Kconfig.kgdb
---- linux-2.6.22-570/lib/Kconfig.kgdb  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/lib/Kconfig.kgdb  2008-01-02 13:56:38.000000000 -0500
-@@ -0,0 +1,255 @@
-+
-+config WANT_EXTRA_DEBUG_INFORMATION
-+      bool
-+      select DEBUG_INFO
-+      select UNWIND_INFO
-+      select FRAME_POINTER if X86 || SUPERH
-+      default n
-+
-+config UNWIND_INFO
-+      bool
-+      default n
-+
-+config KGDB
-+      bool "KGDB: kernel debugging with remote gdb"
-+      select WANT_EXTRA_DEBUG_INFORMATION
-+      select KGDB_ARCH_HAS_SHADOW_INFO if X86_64
-+      depends on DEBUG_KERNEL && (ARM || X86 || MIPS || (SUPERH && !SUPERH64) || IA64 || PPC)
-+      help
-+        If you say Y here, it will be possible to remotely debug the
-+        kernel using gdb.  Documentation of kernel debugger is available
-+        at http://kgdb.sourceforge.net as well as in DocBook form
-+        in Documentation/DocBook/.  If unsure, say N.
-+
-+config KGDB_ARCH_HAS_SHADOW_INFO
-+      bool
-+
-+config KGDB_CONSOLE
-+      bool "KGDB: Console messages through gdb"
-+      depends on KGDB
-+        help
-+          If you say Y here, console messages will appear through gdb.
-+          Other consoles such as tty or ttyS will continue to work as usual.
-+          Note, that if you use this in conjunction with KGDB_ETH, if the
-+          ethernet driver runs into an error condition during use with KGDB
-+          it is possible to hit an infinite recusrion, causing the kernel
-+          to crash, and typically reboot.  For this reason, it is preferable
-+          to use NETCONSOLE in conjunction with KGDB_ETH instead of
-+          KGDB_CONSOLE.
-+
-+choice
-+      prompt "Method for KGDB communication"
-+      depends on KGDB
-+      default KGDB_MPSC if SERIAL_MPSC
-+      default KGDB_CPM_UART if (CPM2 || 8xx)
-+      default KGDB_SIBYTE if SIBYTE_SB1xxx_SOC
-+      default KGDB_TXX9 if CPU_TX49XX
-+      default KGDB_SH_SCI if SERIAL_SH_SCI
-+      default KGDB_PXA_SERIAL if ARCH_PXA
-+      default KGDB_AMBA_PL011 if ARM_AMBA
-+      default KGDB_8250_NOMODULE
-+      help
-+        There are a number of different ways in which you can communicate
-+        with KGDB.  The most common is via serial, with the 8250 driver
-+        (should your hardware have an 8250, or ns1655x style uart).
-+        Another option is to use the NETPOLL framework and UDP, should
-+        your ethernet card support this.  Other options may exist.
-+        You can elect to have one core I/O driver that is built into the
-+        kernel for debugging as the kernel is booting, or using only
-+        kernel modules.
-+
-+config KGDB_ONLY_MODULES
-+      bool "KGDB: Use only kernel modules for I/O"
-+      depends on MODULES
-+      help
-+        Use only kernel modules to configure KGDB I/O after the
-+        kernel is booted.
-+
-+config KGDB_8250_NOMODULE
-+      bool "KGDB: On generic serial port (8250)"
-+      select KGDB_8250
-+      help
-+        Uses generic serial port (8250) to communicate with the host
-+        GDB.  This is independent of the normal (SERIAL_8250) driver
-+        for this chipset.
-+
-+config KGDBOE_NOMODULE
-+      bool "KGDB: On ethernet - in kernel"
-+      select KGDBOE
-+      help
-+        Uses the NETPOLL API to communicate with the host GDB via UDP.
-+        In order for this to work, the ethernet interface specified must
-+        support the NETPOLL API, and this must be initialized at boot.
-+        See the documentation for syntax.
-+
-+config KGDB_MPSC
-+      bool "KGDB: On MV64x60 MPSC"
-+      depends on SERIAL_MPSC
-+      help
-+        Uses a Marvell GT64260B or MV64x60 Multi-Purpose Serial
-+        Controller (MPSC) channel. Note that the GT64260A is not
-+        supported.
-+
-+config KGDB_CPM_UART
-+      bool "KGDB: On CPM UART"
-+      depends on PPC && (CPM2 || 8xx)
-+      help
-+        Uses CPM UART to communicate with the host GDB.
-+
-+config KGDB_SIBYTE
-+      bool "KGDB: On Broadcom SB1xxx serial port"
-+      depends on MIPS && SIBYTE_SB1xxx_SOC
-+
-+config KGDB_TXX9
-+      bool "KGDB: On TX49xx serial port"
-+      depends on MIPS && CPU_TX49XX
-+      help
-+        Uses TX49xx serial port to communicate with the host KGDB.
-+
-+config KGDB_SH_SCI
-+      bool "KGDB: On SH SCI(F) serial port"
-+      depends on SUPERH && SERIAL_SH_SCI
-+      help
-+        Uses the SH SCI(F) serial port to communicate with the host GDB.
-+
-+config KGDB_AMBA_PL011
-+      bool "KGDB: On ARM AMBA PL011 Serial Port"
-+      depends on ARM && ARCH_VERSATILE
-+      help
-+        Enables the KGDB serial driver for the AMBA bus PL011 serial
-+          devices from ARM.
-+
-+config KGDB_PXA_SERIAL
-+      bool "KGDB: On the PXA2xx serial port"
-+      depends on ARCH_PXA
-+      help
-+        Enables the KGDB serial driver for Intel PXA SOC
-+endchoice
-+
-+choice
-+      prompt "PXA UART to use for KGDB"
-+      depends on KGDB_PXA_SERIAL
-+      default KGDB_PXA_FFUART
-+
-+config KGDB_PXA_FFUART
-+      bool "FFUART"
-+
-+config KGDB_PXA_BTUART
-+      bool "BTUART"
-+
-+config KGDB_PXA_STUART
-+      bool "STUART"
-+endchoice
-+
-+choice
-+      prompt "SCC/SMC to use for KGDB"
-+      depends on KGDB_CPM_UART
-+      default KGDB_CPM_UART_SCC4 if ADS8272
-+
-+config KGDB_CPM_UART_SCC1
-+      bool "SCC1"
-+      depends on SERIAL_CPM_SCC1
-+
-+config KGDB_CPM_UART_SCC2
-+      bool "SCC2"
-+      depends on SERIAL_CPM_SCC2
-+
-+config KGDB_CPM_UART_SCC3
-+      bool "SCC3"
-+      depends on SERIAL_CPM_SCC3
-+
-+config KGDB_CPM_UART_SCC4
-+      bool "SCC4"
-+      depends on SERIAL_CPM_SCC4
-+
-+config KGDB_CPM_UART_SMC1
-+      bool "SMC1"
-+      depends on SERIAL_CPM_SMC1
-+
-+config KGDB_CPM_UART_SMC2
-+      bool "SMC2"
-+      depends on SERIAL_CPM_SMC2
-+endchoice
-+
-+config KGDBOE
-+      tristate "KGDB: On ethernet" if !KGDBOE_NOMODULE
-+      depends on m && KGDB
-+      select NETPOLL
-+      select NETPOLL_TRAP
-+      help
-+        Uses the NETPOLL API to communicate with the host GDB via UDP.
-+        In order for this to work, the ethernet interface specified must
-+        support the NETPOLL API, and this must be initialized at boot.
-+        See the documentation for syntax.
-+
-+config KGDB_8250
-+      tristate "KGDB: On generic serial port (8250)" if !KGDB_8250_NOMODULE
-+      depends on m && KGDB_ONLY_MODULES
-+      help
-+        Uses generic serial port (8250) to communicate with the host
-+        GDB.  This is independent of the normal (SERIAL_8250) driver
-+        for this chipset.
-+
-+config KGDB_SIMPLE_SERIAL
-+      bool "Simple selection of KGDB serial port"
-+      depends on KGDB_8250_NOMODULE
-+      default y
-+      help
-+        If you say Y here, you will only have to pick the baud rate
-+        and port number that you wish to use for KGDB.  Note that this
-+        only works on architectures that register known serial ports
-+        early on.  If you say N, you will have to provide, either here
-+        or on the command line, the type (I/O or MMIO), IRQ and
-+        address to use.  If in doubt, say Y.
-+
-+config KGDB_BAUDRATE
-+      int "Debug serial port baud rate"
-+      depends on (KGDB_8250 && KGDB_SIMPLE_SERIAL) || \
-+              KGDB_MPSC || KGDB_CPM_UART || \
-+              KGDB_TXX9 || KGDB_PXA_SERIAL || KGDB_AMBA_PL011
-+      default "115200"
-+      help
-+        gdb and the kernel stub need to agree on the baud rate to be
-+        used.  Standard rates from 9600 to 115200 are allowed, and this
-+        may be overridden via the commandline.
-+
-+config KGDB_PORT_NUM
-+      int "Serial port number for KGDB"
-+      range 0 1 if KGDB_MPSC
-+      range 0 3
-+      depends on (KGDB_8250 && KGDB_SIMPLE_SERIAL) || KGDB_MPSC || KGDB_TXX9
-+      default "1"
-+      help
-+        Pick the port number (0 based) for KGDB to use.
-+
-+config KGDB_AMBA_BASE
-+      hex "AMBA PL011 Serial Port Base Address"
-+      default 0x101f2000 if ARCH_VERSATILE
-+      depends on KGDB_AMBA_PL011
-+      help
-+        Base address of the AMBA port that KGDB will use.
-+
-+config KGDB_AMBA_UARTCLK
-+      int "AMBAPL011 Serial UART Clock Frequency"
-+      default 24000000 if ARCH_VERSATILE
-+      depends on KGDB_AMBA_PL011
-+      help
-+        Frequency (in HZ) of the ARM AMBA UART clock
-+
-+config KGDB_AMBA_IRQ
-+      int "AMBA PL011 Serial Port IRQ"
-+      default 13 if ARCH_VERSATILE
-+      depends on KGDB_AMBA_PL011
-+      help
-+        Pick the IRQ of the AMBA port that KGDB will use.
-+
-+config KGDB_8250_CONF_STRING
-+      string "Configuration string for KGDB"
-+      depends on KGDB_8250_NOMODULE && !KGDB_SIMPLE_SERIAL
-+      default "io,2f8,115200,3" if X86
-+      help
-+        The format of this string should be <io or
-+        mmio>,<address>,<baud rate>,<irq>.  For example, to use the
-+        serial port on an i386 box located at 0x2f8 and 115200 baud
-+        on IRQ 3 at use:
-+        io,2f8,115200,3
-diff -Nurb linux-2.6.22-570/lib/Makefile linux-2.6.22-590/lib/Makefile
---- linux-2.6.22-570/lib/Makefile      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/lib/Makefile      2008-01-02 13:56:38.000000000 -0500
-@@ -5,9 +5,10 @@
- lib-y := ctype.o string.o vsprintf.o cmdline.o \
-        rbtree.o radix-tree.o dump_stack.o \
-        idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \
--       sha1.o irq_regs.o reciprocal_div.o
-+       sha1.o irq_regs.o reciprocal_div.o argv_split.o \
-+       check_signature.o
+-static inline unsigned int inet_ehashfn(struct net *net,
+-                                      const __be32 laddr, const __u16 lport,
++static inline unsigned int inet_ehashfn(const __be32 laddr, const __u16 lport,
+                                       const __be32 faddr, const __be16 fport)
+ {
+-      return jhash_2words((__force __u32) laddr ^ (__force __u32) faddr ^
+-                          (__force __u32) ((unsigned long)net),
++      return jhash_2words((__force __u32) laddr ^ (__force __u32) faddr,
+                           ((__u32) lport) << 16 | (__force __u32)fport,
+                           inet_ehash_secret);
+ }
+@@ -189,7 +187,7 @@
+       const __be32 faddr = inet->daddr;
+       const __be16 fport = inet->dport;
  
--lib-$(CONFIG_MMU) += ioremap.o
-+lib-$(CONFIG_MMU) += ioremap.o pagewalk.o
- lib-$(CONFIG_SMP) += cpumask.o
+-      return inet_ehashfn(sk->sk_net, laddr, lport, faddr, fport);
++      return inet_ehashfn(laddr, lport, faddr, fport);
+ }
  
- lib-y += kobject.o kref.o kobject_uevent.o klist.o
-diff -Nurb linux-2.6.22-570/lib/argv_split.c linux-2.6.22-590/lib/argv_split.c
---- linux-2.6.22-570/lib/argv_split.c  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/lib/argv_split.c  2008-01-02 13:56:38.000000000 -0500
-@@ -0,0 +1,159 @@
-+/*
-+ * Helper function for splitting a string into an argv-like array.
-+ */
-+
-+#ifndef TEST
-+#include <linux/kernel.h>
-+#include <linux/ctype.h>
-+#include <linux/bug.h>
-+#endif
-+
-+static const char *skip_sep(const char *cp)
-+{
-+      while (*cp && isspace(*cp))
-+              cp++;
-+
-+      return cp;
-+}
-+
-+static const char *skip_arg(const char *cp)
-+{
-+      while (*cp && !isspace(*cp))
-+              cp++;
-+
-+      return cp;
-+}
-+
-+static int count_argc(const char *str)
-+{
-+      int count = 0;
-+
-+      while (*str) {
-+              str = skip_sep(str);
-+              if (*str) {
-+                      count++;
-+                      str = skip_arg(str);
-+              }
-+      }
-+
-+      return count;
-+}
-+
-+/**
-+ * argv_free - free an argv
-+ *
-+ * @argv - the argument vector to be freed
-+ *
-+ * Frees an argv and the strings it points to.
-+ */
-+void argv_free(char **argv)
-+{
-+      char **p;
-+      for (p = argv; *p; p++)
-+              kfree(*p);
-+
-+      kfree(argv);
-+}
-+EXPORT_SYMBOL(argv_free);
-+
-+/**
-+ * argv_split - split a string at whitespace, returning an argv
-+ * @gfp: the GFP mask used to allocate memory
-+ * @str: the string to be split
-+ * @argcp: returned argument count
-+ *
-+ * Returns an array of pointers to strings which are split out from
-+ * @str.  This is performed by strictly splitting on white-space; no
-+ * quote processing is performed.  Multiple whitespace characters are
-+ * considered to be a single argument separator.  The returned array
-+ * is always NULL-terminated.  Returns NULL on memory allocation
-+ * failure.
-+ */
-+char **argv_split(gfp_t gfp, const char *str, int *argcp)
+ #endif        /* _INET_SOCK_H */
+diff -Nurb linux-2.6.22-590/include/net/inet_timewait_sock.h linux-2.6.22-570/include/net/inet_timewait_sock.h
+--- linux-2.6.22-590/include/net/inet_timewait_sock.h  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/inet_timewait_sock.h  2008-01-23 19:16:05.000000000 -0500
+@@ -115,7 +115,6 @@
+ #define tw_refcnt             __tw_common.skc_refcnt
+ #define tw_hash                       __tw_common.skc_hash
+ #define tw_prot                       __tw_common.skc_prot
+-#define tw_net                        __tw_common.skc_net
+ #define tw_xid                __tw_common.skc_xid
+ #define tw_vx_info            __tw_common.skc_vx_info
+ #define tw_nid                __tw_common.skc_nid
+diff -Nurb linux-2.6.22-590/include/net/inetpeer.h linux-2.6.22-570/include/net/inetpeer.h
+--- linux-2.6.22-590/include/net/inetpeer.h    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/inetpeer.h    2007-07-08 19:32:17.000000000 -0400
+@@ -15,8 +15,6 @@
+ #include <linux/spinlock.h>
+ #include <asm/atomic.h>
+-struct net;
+-
+ struct inet_peer
+ {
+       /* group together avl_left,avl_right,v4daddr to speedup lookups */
+@@ -24,11 +22,7 @@
+       __be32                  v4daddr;        /* peer's address */
+       __u16                   avl_height;
+       __u16                   ip_id_count;    /* IP ID for the next packet */
+-      union {
+-              struct inet_peer        *unused_next;
+-              struct net              *net;
+-      } u;
+-      struct inet_peer        **unused_prevp;
++      struct inet_peer        *unused_next, **unused_prevp;
+       __u32                   dtime;          /* the time of last use of not
+                                                * referenced entries */
+       atomic_t                refcnt;
+@@ -40,7 +34,7 @@
+ void                  inet_initpeers(void) __init;
+ /* can be called with or without local BH being disabled */
+-struct inet_peer      *inet_getpeer(struct net *net, __be32 daddr, int create);
++struct inet_peer      *inet_getpeer(__be32 daddr, int create);
+ /* can be called from BH context or outside */
+ extern void inet_putpeer(struct inet_peer *p);
+diff -Nurb linux-2.6.22-590/include/net/ip.h linux-2.6.22-570/include/net/ip.h
+--- linux-2.6.22-590/include/net/ip.h  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/ip.h  2007-07-08 19:32:17.000000000 -0400
+@@ -149,6 +149,13 @@
+ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
+                  unsigned int len); 
++struct ipv4_config
 +{
-+      int argc = count_argc(str);
-+      char **argv = kzalloc(sizeof(*argv) * (argc+1), gfp);
-+      char **argvp;
-+
-+      if (argv == NULL)
-+              goto out;
-+
-+      *argcp = argc;
-+      argvp = argv;
-+
-+      while (*str) {
-+              str = skip_sep(str);
-+
-+              if (*str) {
-+                      const char *p = str;
-+                      char *t;
-+
-+                      str = skip_arg(str);
-+
-+                      t = kstrndup(p, str-p, gfp);
-+                      if (t == NULL)
-+                              goto fail;
-+                      *argvp++ = t;
-+              }
-+      }
-+      *argvp = NULL;
-+
-+  out:
-+      return argv;
-+
-+  fail:
-+      argv_free(argv);
-+      return NULL;
-+}
-+EXPORT_SYMBOL(argv_split);
-+
-+#ifdef TEST
-+#define _GNU_SOURCE
-+#include <ctype.h>
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <string.h>
-+
-+typedef enum {
-+      GFP_KERNEL,
-+} gfp_t;
-+#define kzalloc(size, x)      malloc(size)
-+#define kfree(x)              free(x)
-+#define kstrndup(s, n, gfp)   strndup(s, n)
-+#define BUG() abort()
-+
-+int main() {
-+      const char *testvec[] = {
-+              "",
-+              "x",
-+              "\"",
-+              "\\\0",
-+              "\"",
-+              "test one two three",
-+              "arg\"foo\"bar biff",
-+              "one two\\ three four",
-+              "one \"two three\" four",
-+              NULL,
-+      };
-+      const char **t;
-+
-+      for (t = testvec; *t; t++) {
-+              char **argv;
-+              int argc;
-+              char **a;
++      int     log_martians;
++      int     no_pmtu_disc;
++};
 +
-+              printf("%d: test [%s]\n", t-testvec, *t);
++extern struct ipv4_config ipv4_config;
+ DECLARE_SNMP_STAT(struct ipstats_mib, ip_statistics);
+ #define IP_INC_STATS(field)           SNMP_INC_STATS(ip_statistics, field)
+ #define IP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(ip_statistics, field)
+@@ -164,6 +171,27 @@
+ extern int snmp_mib_init(void *ptr[2], size_t mibsize, size_t mibalign);
+ extern void snmp_mib_free(void *ptr[2]);
++extern int sysctl_local_port_range[2];
++extern int sysctl_ip_default_ttl;
++extern int sysctl_ip_nonlocal_bind;
 +
-+              argv = argv_split(GFP_KERNEL, *t, &argc);
++/* From ip_fragment.c */
++extern int sysctl_ipfrag_high_thresh; 
++extern int sysctl_ipfrag_low_thresh;
++extern int sysctl_ipfrag_time;
++extern int sysctl_ipfrag_secret_interval;
++extern int sysctl_ipfrag_max_dist;
 +
-+              printf("argc=%d vec=", argc);
-+              for (a = argv; *a; a++)
-+                      printf("[%s] ", *a);
-+              printf("\n");
++/* From inetpeer.c */
++extern int inet_peer_threshold;
++extern int inet_peer_minttl;
++extern int inet_peer_maxttl;
++extern int inet_peer_gc_mintime;
++extern int inet_peer_gc_maxtime;
 +
-+              argv_free(argv);
-+      }
++/* From ip_output.c */
++extern int sysctl_ip_dynaddr;
 +
-+      return 0;
-+}
+ extern void ipfrag_init(void);
+ #ifdef CONFIG_INET
+@@ -304,6 +332,8 @@
+ };
+ struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user);
++extern int ip_frag_nqueues;
++extern atomic_t ip_frag_mem;
+ /*
+  *    Functions provided by ip_forward.c
+@@ -362,6 +392,5 @@
+ #endif
+ extern struct ctl_table ipv4_table[];
+-extern struct ctl_table multi_ipv4_table[];
+ #endif        /* _IP_H */
+diff -Nurb linux-2.6.22-590/include/net/ip_fib.h linux-2.6.22-570/include/net/ip_fib.h
+--- linux-2.6.22-590/include/net/ip_fib.h      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/ip_fib.h      2007-07-08 19:32:17.000000000 -0400
+@@ -39,6 +39,7 @@
+       int                     fc_mx_len;
+       int                     fc_mp_len;
+       u32                     fc_flow;
++      u32                     fc_mp_alg;
+       u32                     fc_nlflags;
+       struct nl_info          fc_nlinfo;
+  };
+@@ -88,7 +89,6 @@
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+       u32                     fib_mp_alg;
+ #endif
+-      struct net *            fib_net;
+       struct fib_nh           fib_nh[0];
+ #define fib_dev               fib_nh[0].nh_dev
+ };
+@@ -103,6 +103,10 @@
+       unsigned char   nh_sel;
+       unsigned char   type;
+       unsigned char   scope;
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      __be32          network;
++      __be32          netmask;
 +#endif
-diff -Nurb linux-2.6.22-570/lib/check_signature.c linux-2.6.22-590/lib/check_signature.c
---- linux-2.6.22-570/lib/check_signature.c     1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/lib/check_signature.c     2008-01-02 13:56:38.000000000 -0500
-@@ -0,0 +1,26 @@
-+#include <linux/io.h>
-+#include <linux/module.h>
-+
-+/**
-+ *    check_signature         -       find BIOS signatures
-+ *    @io_addr: mmio address to check
-+ *    @signature:  signature block
-+ *    @length: length of signature
-+ *
-+ *    Perform a signature comparison with the mmio address io_addr. This
-+ *    address should have been obtained by ioremap.
-+ *    Returns 1 on a match.
-+ */
-+
-+int check_signature(const volatile void __iomem *io_addr,
-+                      const unsigned char *signature, int length)
-+{
-+      while (length--) {
-+              if (readb(io_addr) != *signature)
-+                      return 0;
-+              io_addr++;
-+              signature++;
-+      }
-+      return 1;
-+}
-+EXPORT_SYMBOL(check_signature);
-diff -Nurb linux-2.6.22-570/lib/idr.c linux-2.6.22-590/lib/idr.c
---- linux-2.6.22-570/lib/idr.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/lib/idr.c 2008-01-02 13:56:38.000000000 -0500
-@@ -70,6 +70,26 @@
-       spin_unlock_irqrestore(&idp->lock, flags);
- }
+       struct fib_info *fi;
+ #ifdef CONFIG_IP_MULTIPLE_TABLES
+       struct fib_rule *r;
+@@ -141,6 +145,14 @@
+ #define FIB_RES_DEV(res)              (FIB_RES_NH(res).nh_dev)
+ #define FIB_RES_OIF(res)              (FIB_RES_NH(res).nh_oif)
  
-+static void idr_mark_full(struct idr_layer **pa, int id)
-+{
-+      struct idr_layer *p = pa[0];
-+      int l = 0;
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++#define FIB_RES_NETWORK(res)          ((res).network)
++#define FIB_RES_NETMASK(res)          ((res).netmask)
++#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
++#define FIB_RES_NETWORK(res)          (0)
++#define FIB_RES_NETMASK(res)          (0)
++#endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */
 +
-+      __set_bit(id & IDR_MASK, &p->bitmap);
-+      /*
-+       * If this layer is full mark the bit in the layer above to
-+       * show that this part of the radix tree is full.  This may
-+       * complete the layer above and require walking up the radix
-+       * tree.
-+       */
-+      while (p->bitmap == IDR_FULL) {
-+              if (!(p = pa[++l]))
-+                      break;
-+              id = id >> IDR_BITS;
-+              __set_bit((id & IDR_MASK), &p->bitmap);
-+      }
-+}
+ struct fib_table {
+       struct hlist_node tb_hlist;
+       u32             tb_id;
+@@ -159,43 +171,43 @@
+ #ifndef CONFIG_IP_MULTIPLE_TABLES
+-static inline struct fib_table *fib_get_table(struct net *net, u32 id)
++extern struct fib_table *ip_fib_local_table;
++extern struct fib_table *ip_fib_main_table;
 +
- /**
-  * idr_pre_get - reserver resources for idr allocation
-  * @idp:      idr handle
-@@ -95,11 +115,10 @@
++static inline struct fib_table *fib_get_table(u32 id)
+ {
+       if (id != RT_TABLE_LOCAL)
+-              return net->ip_fib_main_table;
+-      return net->ip_fib_local_table;
++              return ip_fib_main_table;
++      return ip_fib_local_table;
  }
- EXPORT_SYMBOL(idr_pre_get);
  
--static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
-+static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
+-static inline struct fib_table *fib_new_table(struct net *net, u32 id)
++static inline struct fib_table *fib_new_table(u32 id)
  {
-       int n, m, sh;
-       struct idr_layer *p, *new;
--      struct idr_layer *pa[MAX_LEVEL];
-       int l, id;
-       long bm;
+-      return fib_get_table(net, id);
++      return fib_get_table(id);
+ }
  
-@@ -144,30 +163,13 @@
-               pa[l--] = p;
-               p = p->ary[m];
-       }
--      /*
--       * We have reached the leaf node, plant the
--       * users pointer and return the raw id.
--       */
--      p->ary[m] = (struct idr_layer *)ptr;
--      __set_bit(m, &p->bitmap);
--      p->count++;
--      /*
--       * If this layer is full mark the bit in the layer above
--       * to show that this part of the radix tree is full.
--       * This may complete the layer above and require walking
--       * up the radix tree.
--       */
--      n = id;
--      while (p->bitmap == IDR_FULL) {
--              if (!(p = pa[++l]))
--                      break;
--              n = n >> IDR_BITS;
--              __set_bit((n & IDR_MASK), &p->bitmap);
--      }
--      return(id);
-+
-+      pa[l] = p;
-+      return id;
+ static inline int fib_lookup(const struct flowi *flp, struct fib_result *res)
+ {
+-      struct net *net = flp->fl_net;
+-      struct fib_table *local_table = net->ip_fib_local_table;
+-      struct fib_table *main_table = net->ip_fib_main_table;
+-      if (local_table->tb_lookup(local_table, flp, res) &&
+-          main_table->tb_lookup(main_table, flp, res))
++      if (ip_fib_local_table->tb_lookup(ip_fib_local_table, flp, res) &&
++          ip_fib_main_table->tb_lookup(ip_fib_main_table, flp, res))
+               return -ENETUNREACH;
+       return 0;
  }
  
--static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
-+static int idr_get_empty_slot(struct idr *idp, int starting_id,
-+                            struct idr_layer **pa)
+ static inline void fib_select_default(const struct flowi *flp, struct fib_result *res)
  {
-       struct idr_layer *p, *new;
-       int layers, v, id;
-@@ -213,12 +215,31 @@
-       }
-       idp->top = p;
-       idp->layers = layers;
--      v = sub_alloc(idp, ptr, &id);
-+      v = sub_alloc(idp, &id, pa);
-       if (v == -2)
-               goto build_up;
-       return(v);
+-      struct net *net = flp->fl_net;
+-      struct fib_table *main_table = net->ip_fib_main_table;
+       if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
+-              main_table->tb_select_default(main_table, flp, res);
++              ip_fib_main_table->tb_select_default(ip_fib_main_table, flp, res);
  }
  
-+static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
-+{
-+      struct idr_layer *pa[MAX_LEVEL];
-+      int id;
-+
-+      id = idr_get_empty_slot(idp, starting_id, pa);
-+      if (id >= 0) {
-+              /*
-+               * Successfully found an empty slot.  Install the user
-+               * pointer and mark the slot full.
-+               */
-+              pa[0]->ary[id & IDR_MASK] = (struct idr_layer *)ptr;
-+              pa[0]->count++;
-+              idr_mark_full(pa, id);
-+      }
-+
-+      return id;
-+}
-+
- /**
-  * idr_get_new_above - allocate new idr entry above or equal to a start id
-  * @idp: idr handle
-@@ -473,3 +494,248 @@
-       spin_lock_init(&idp->lock);
+ #else /* CONFIG_IP_MULTIPLE_TABLES */
++#define ip_fib_local_table fib_get_table(RT_TABLE_LOCAL)
++#define ip_fib_main_table fib_get_table(RT_TABLE_MAIN)
+ extern int fib_lookup(struct flowi *flp, struct fib_result *res);
+-extern struct fib_table *fib_new_table(struct net *net, u32 id);
+-extern struct fib_table *fib_get_table(struct net *net, u32 id);
++extern struct fib_table *fib_new_table(u32 id);
++extern struct fib_table *fib_get_table(u32 id);
+ extern void fib_select_default(const struct flowi *flp, struct fib_result *res);
+ #endif /* CONFIG_IP_MULTIPLE_TABLES */
+@@ -211,17 +223,15 @@
+ /* Exported by fib_semantics.c */
+ extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
+-extern int fib_sync_down(struct net *net, __be32 local, struct net_device *dev, int force);
++extern int fib_sync_down(__be32 local, struct net_device *dev, int force);
+ extern int fib_sync_up(struct net_device *dev);
+ extern __be32  __fib_res_prefsrc(struct fib_result *res);
+ /* Exported by fib_hash.c */
+ extern struct fib_table *fib_hash_init(u32 id);
+-extern void fib_hash_exit(struct fib_table *tb);
+ #ifdef CONFIG_IP_MULTIPLE_TABLES
+-extern void fib4_rules_init(struct net * net);
+-extern void fib4_rules_exit(struct net * net);
++extern void __init fib4_rules_init(void);
+ #ifdef CONFIG_NET_CLS_ROUTE
+ extern u32 fib_rules_tclass(struct fib_result *res);
+@@ -264,11 +274,8 @@
  }
- EXPORT_SYMBOL(idr_init);
-+
-+
-+/*
-+ * IDA - IDR based ID allocator
-+ *
-+ * this is id allocator without id -> pointer translation.  Memory
-+ * usage is much lower than full blown idr because each id only
-+ * occupies a bit.  ida uses a custom leaf node which contains
-+ * IDA_BITMAP_BITS slots.
+ #ifdef CONFIG_PROC_FS
+-extern int  fib_proc_init(struct net * net);
+-extern void fib_proc_exit(struct net * net);
++extern int  fib_proc_init(void);
++extern void fib_proc_exit(void);
+ #endif
+-extern int  fib_info_init(struct net *net);
+-extern void fib_info_exit(struct net *net);
+-
+ #endif  /* _NET_FIB_H */
+diff -Nurb linux-2.6.22-590/include/net/ip_mp_alg.h linux-2.6.22-570/include/net/ip_mp_alg.h
+--- linux-2.6.22-590/include/net/ip_mp_alg.h   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/include/net/ip_mp_alg.h   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,96 @@
++/* ip_mp_alg.h: IPV4 multipath algorithm support.
 + *
-+ * 2007-04-25  written by Tejun Heo <htejun@gmail.com>
++ * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
++ * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
 + */
 +
-+static void free_bitmap(struct ida *ida, struct ida_bitmap *bitmap)
-+{
-+      unsigned long flags;
-+
-+      if (!ida->free_bitmap) {
-+              spin_lock_irqsave(&ida->idr.lock, flags);
-+              if (!ida->free_bitmap) {
-+                      ida->free_bitmap = bitmap;
-+                      bitmap = NULL;
-+              }
-+              spin_unlock_irqrestore(&ida->idr.lock, flags);
-+      }
-+
-+      kfree(bitmap);
-+}
++#ifndef _NET_IP_MP_ALG_H
++#define _NET_IP_MP_ALG_H
 +
-+/**
-+ * ida_pre_get - reserve resources for ida allocation
-+ * @ida:      ida handle
-+ * @gfp_mask: memory allocation flag
-+ *
-+ * This function should be called prior to locking and calling the
-+ * following function.  It preallocates enough memory to satisfy the
-+ * worst possible allocation.
-+ *
-+ * If the system is REALLY out of memory this function returns 0,
-+ * otherwise 1.
-+ */
-+int ida_pre_get(struct ida *ida, gfp_t gfp_mask)
-+{
-+      /* allocate idr_layers */
-+      if (!idr_pre_get(&ida->idr, gfp_mask))
-+              return 0;
++#include <linux/ip_mp_alg.h>
++#include <net/flow.h>
++#include <net/route.h>
 +
-+      /* allocate free_bitmap */
-+      if (!ida->free_bitmap) {
-+              struct ida_bitmap *bitmap;
++struct fib_nh;
 +
-+              bitmap = kmalloc(sizeof(struct ida_bitmap), gfp_mask);
-+              if (!bitmap)
-+                      return 0;
++struct ip_mp_alg_ops {
++      void    (*mp_alg_select_route)(const struct flowi *flp,
++                                     struct rtable *rth, struct rtable **rp);
++      void    (*mp_alg_flush)(void);
++      void    (*mp_alg_set_nhinfo)(__be32 network, __be32 netmask,
++                                   unsigned char prefixlen,
++                                   const struct fib_nh *nh);
++      void    (*mp_alg_remove)(struct rtable *rth);
++};
 +
-+              free_bitmap(ida, bitmap);
-+      }
++extern int multipath_alg_register(struct ip_mp_alg_ops *, enum ip_mp_alg);
++extern void multipath_alg_unregister(struct ip_mp_alg_ops *, enum ip_mp_alg);
 +
-+      return 1;
-+}
-+EXPORT_SYMBOL(ida_pre_get);
++extern struct ip_mp_alg_ops *ip_mp_alg_table[];
 +
-+/**
-+ * ida_get_new_above - allocate new ID above or equal to a start id
-+ * @ida:      ida handle
-+ * @staring_id:       id to start search at
-+ * @p_id:     pointer to the allocated handle
-+ *
-+ * Allocate new ID above or equal to @ida.  It should be called with
-+ * any required locks.
-+ *
-+ * If memory is required, it will return -EAGAIN, you should unlock
-+ * and go back to the ida_pre_get() call.  If the ida is full, it will
-+ * return -ENOSPC.
-+ *
-+ * @p_id returns a value in the range 0 ... 0x7fffffff.
-+ */
-+int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
++static inline int multipath_select_route(const struct flowi *flp,
++                                       struct rtable *rth,
++                                       struct rtable **rp)
 +{
-+      struct idr_layer *pa[MAX_LEVEL];
-+      struct ida_bitmap *bitmap;
-+      unsigned long flags;
-+      int idr_id = starting_id / IDA_BITMAP_BITS;
-+      int offset = starting_id % IDA_BITMAP_BITS;
-+      int t, id;
-+
-+ restart:
-+      /* get vacant slot */
-+      t = idr_get_empty_slot(&ida->idr, idr_id, pa);
-+      if (t < 0) {
-+              if (t == -1)
-+                      return -EAGAIN;
-+              else /* will be -3 */
-+                      return -ENOSPC;
-+      }
-+
-+      if (t * IDA_BITMAP_BITS >= MAX_ID_BIT)
-+              return -ENOSPC;
-+
-+      if (t != idr_id)
-+              offset = 0;
-+      idr_id = t;
-+
-+      /* if bitmap isn't there, create a new one */
-+      bitmap = (void *)pa[0]->ary[idr_id & IDR_MASK];
-+      if (!bitmap) {
-+              spin_lock_irqsave(&ida->idr.lock, flags);
-+              bitmap = ida->free_bitmap;
-+              ida->free_bitmap = NULL;
-+              spin_unlock_irqrestore(&ida->idr.lock, flags);
-+
-+              if (!bitmap)
-+                      return -EAGAIN;
-+
-+              memset(bitmap, 0, sizeof(struct ida_bitmap));
-+              pa[0]->ary[idr_id & IDR_MASK] = (void *)bitmap;
-+              pa[0]->count++;
-+      }
-+
-+      /* lookup for empty slot */
-+      t = find_next_zero_bit(bitmap->bitmap, IDA_BITMAP_BITS, offset);
-+      if (t == IDA_BITMAP_BITS) {
-+              /* no empty slot after offset, continue to the next chunk */
-+              idr_id++;
-+              offset = 0;
-+              goto restart;
-+      }
-+
-+      id = idr_id * IDA_BITMAP_BITS + t;
-+      if (id >= MAX_ID_BIT)
-+              return -ENOSPC;
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
 +
-+      __set_bit(t, bitmap->bitmap);
-+      if (++bitmap->nr_busy == IDA_BITMAP_BITS)
-+              idr_mark_full(pa, idr_id);
-+
-+      *p_id = id;
-+
-+      /* Each leaf node can handle nearly a thousand slots and the
-+       * whole idea of ida is to have small memory foot print.
-+       * Throw away extra resources one by one after each successful
-+       * allocation.
-+       */
-+      if (ida->idr.id_free_cnt || ida->free_bitmap) {
-+              struct idr_layer *p = alloc_layer(&ida->idr);
-+              if (p)
-+                      kmem_cache_free(idr_layer_cache, p);
++      /* mp_alg_select_route _MUST_ be implemented */
++      if (ops && (rth->u.dst.flags & DST_BALANCED)) {
++              ops->mp_alg_select_route(flp, rth, rp);
++              return 1;
 +      }
-+
++#endif
 +      return 0;
 +}
-+EXPORT_SYMBOL(ida_get_new_above);
-+
-+/**
-+ * ida_get_new - allocate new ID
-+ * @ida:      idr handle
-+ * @p_id:     pointer to the allocated handle
-+ *
-+ * Allocate new ID.  It should be called with any required locks.
-+ *
-+ * If memory is required, it will return -EAGAIN, you should unlock
-+ * and go back to the idr_pre_get() call.  If the idr is full, it will
-+ * return -ENOSPC.
-+ *
-+ * @id returns a value in the range 0 ... 0x7fffffff.
-+ */
-+int ida_get_new(struct ida *ida, int *p_id)
-+{
-+      return ida_get_new_above(ida, 0, p_id);
-+}
-+EXPORT_SYMBOL(ida_get_new);
 +
-+/**
-+ * ida_remove - remove the given ID
-+ * @ida:      ida handle
-+ * @id:               ID to free
-+ */
-+void ida_remove(struct ida *ida, int id)
++static inline void multipath_flush(void)
 +{
-+      struct idr_layer *p = ida->idr.top;
-+      int shift = (ida->idr.layers - 1) * IDR_BITS;
-+      int idr_id = id / IDA_BITMAP_BITS;
-+      int offset = id % IDA_BITMAP_BITS;
-+      int n;
-+      struct ida_bitmap *bitmap;
-+
-+      /* clear full bits while looking up the leaf idr_layer */
-+      while ((shift > 0) && p) {
-+              n = (idr_id >> shift) & IDR_MASK;
-+              __clear_bit(n, &p->bitmap);
-+              p = p->ary[n];
-+              shift -= IDR_BITS;
-+      }
-+
-+      if (p == NULL)
-+              goto err;
-+
-+      n = idr_id & IDR_MASK;
-+      __clear_bit(n, &p->bitmap);
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      int i;
 +
-+      bitmap = (void *)p->ary[n];
-+      if (!test_bit(offset, bitmap->bitmap))
-+              goto err;
++      for (i = IP_MP_ALG_NONE; i <= IP_MP_ALG_MAX; i++) {
++              struct ip_mp_alg_ops *ops = ip_mp_alg_table[i];
 +
-+      /* update bitmap and remove it if empty */
-+      __clear_bit(offset, bitmap->bitmap);
-+      if (--bitmap->nr_busy == 0) {
-+              __set_bit(n, &p->bitmap);       /* to please idr_remove() */
-+              idr_remove(&ida->idr, idr_id);
-+              free_bitmap(ida, bitmap);
++              if (ops && ops->mp_alg_flush)
++                      ops->mp_alg_flush();
 +      }
++#endif
++}
 +
-+      return;
++static inline void multipath_set_nhinfo(struct rtable *rth,
++                                      __be32 network, __be32 netmask,
++                                      unsigned char prefixlen,
++                                      const struct fib_nh *nh)
++{
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
 +
-+ err:
-+      printk(KERN_WARNING
-+             "ida_remove called for id=%d which is not allocated.\n", id);
++      if (ops && ops->mp_alg_set_nhinfo)
++              ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh);
++#endif
 +}
-+EXPORT_SYMBOL(ida_remove);
 +
-+/**
-+ * ida_destroy - release all cached layers within an ida tree
-+ * ida:               ida handle
-+ */
-+void ida_destroy(struct ida *ida)
++static inline void multipath_remove(struct rtable *rth)
 +{
-+      idr_destroy(&ida->idr);
-+      kfree(ida->free_bitmap);
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
++
++      if (ops && ops->mp_alg_remove &&
++          (rth->u.dst.flags & DST_BALANCED))
++              ops->mp_alg_remove(rth);
++#endif
 +}
-+EXPORT_SYMBOL(ida_destroy);
 +
-+/**
-+ * ida_init - initialize ida handle
-+ * @ida:      ida handle
-+ *
-+ * This function is use to set up the handle (@ida) that you will pass
-+ * to the rest of the functions.
-+ */
-+void ida_init(struct ida *ida)
++static inline int multipath_comparekeys(const struct flowi *flp1,
++                                      const struct flowi *flp2)
 +{
-+      memset(ida, 0, sizeof(struct ida));
-+      idr_init(&ida->idr);
-+
++      return flp1->fl4_dst == flp2->fl4_dst &&
++              flp1->fl4_src == flp2->fl4_src &&
++              flp1->oif == flp2->oif &&
++              flp1->mark == flp2->mark &&
++              !((flp1->fl4_tos ^ flp2->fl4_tos) &
++                (IPTOS_RT_MASK | RTO_ONLINK));
 +}
-+EXPORT_SYMBOL(ida_init);
-diff -Nurb linux-2.6.22-570/lib/kobject.c linux-2.6.22-590/lib/kobject.c
---- linux-2.6.22-570/lib/kobject.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/lib/kobject.c     2008-01-02 13:56:38.000000000 -0500
-@@ -44,11 +44,11 @@
-       return error;
++
++#endif /* _NET_IP_MP_ALG_H */
+diff -Nurb linux-2.6.22-590/include/net/llc_conn.h linux-2.6.22-570/include/net/llc_conn.h
+--- linux-2.6.22-590/include/net/llc_conn.h    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/llc_conn.h    2007-07-08 19:32:17.000000000 -0400
+@@ -93,7 +93,7 @@
+       return skb->cb[sizeof(skb->cb) - 1];
  }
  
--static int create_dir(struct kobject * kobj, struct dentry *shadow_parent)
-+static int create_dir(struct kobject * kobj)
- {
-       int error = 0;
-       if (kobject_name(kobj)) {
--              error = sysfs_create_dir(kobj, shadow_parent);
-+              error = sysfs_create_dir(kobj);
-               if (!error) {
-                       if ((error = populate_dir(kobj)))
-                               sysfs_remove_dir(kobj);
-@@ -157,12 +157,11 @@
- }
+-extern struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority,
++extern struct sock *llc_sk_alloc(int family, gfp_t priority,
+                                struct proto *prot);
+ extern void llc_sk_free(struct sock *sk);
  
- /**
-- *    kobject_shadow_add - add an object to the hierarchy.
-+ *    kobject_add - add an object to the hierarchy.
-  *    @kobj:  object.
-- *    @shadow_parent: sysfs directory to add to.
-  */
+diff -Nurb linux-2.6.22-590/include/net/mip6.h linux-2.6.22-570/include/net/mip6.h
+--- linux-2.6.22-590/include/net/mip6.h        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/mip6.h        2007-07-08 19:32:17.000000000 -0400
+@@ -54,4 +54,8 @@
+ #define IP6_MH_TYPE_BERROR    7   /* Binding Error */
+ #define IP6_MH_TYPE_MAX               IP6_MH_TYPE_BERROR
  
--int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
-+int kobject_add(struct kobject * kobj)
++extern int mip6_init(void);
++extern void mip6_fini(void);
++extern int mip6_mh_filter(struct sock *sk, struct sk_buff *skb);
++
+ #endif
+diff -Nurb linux-2.6.22-590/include/net/neighbour.h linux-2.6.22-570/include/net/neighbour.h
+--- linux-2.6.22-590/include/net/neighbour.h   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/neighbour.h   2007-07-08 19:32:17.000000000 -0400
+@@ -34,7 +34,6 @@
+ struct neigh_parms
  {
-       int error = 0;
-       struct kobject * parent;
-@@ -194,7 +193,7 @@
-               kobj->parent = parent;
-       }
+-      struct net *net;
+       struct net_device *dev;
+       struct neigh_parms *next;
+       int     (*neigh_setup)(struct neighbour *);
+@@ -127,7 +126,6 @@
+ struct pneigh_entry
+ {
+       struct pneigh_entry     *next;
+-      struct net              *net;
+       struct net_device               *dev;
+       u8                      flags;
+       u8                      key[0];
+@@ -189,7 +187,6 @@
+                                            const void *pkey,
+                                            struct net_device *dev);
+ extern struct neighbour *     neigh_lookup_nodev(struct neigh_table *tbl,
+-                                                 struct net *net,
+                                                  const void *pkey);
+ extern struct neighbour *     neigh_create(struct neigh_table *tbl,
+                                            const void *pkey,
+@@ -208,24 +205,21 @@
+                                               struct net_device *dev);
  
--      error = create_dir(kobj, shadow_parent);
-+      error = create_dir(kobj);
-       if (error) {
-               /* unlink does the kobject_put() for us */
-               unlink(kobj);
-@@ -216,16 +215,6 @@
+ extern struct neigh_parms     *neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl);
+-extern struct neigh_parms     *neigh_parms_alloc_default(struct neigh_table *tbl, struct net *net);
+ extern void                   neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms);
+ extern void                   neigh_parms_destroy(struct neigh_parms *parms);
+ extern unsigned long          neigh_rand_reach_time(unsigned long base);
+ extern void                   pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
+                                              struct sk_buff *skb);
+-extern struct pneigh_entry    *pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev, int creat);
+-extern int                    pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev);
++extern struct pneigh_entry    *pneigh_lookup(struct neigh_table *tbl, const void *key, struct net_device *dev, int creat);
++extern int                    pneigh_delete(struct neigh_table *tbl, const void *key, struct net_device *dev);
+ extern void neigh_app_ns(struct neighbour *n);
+ extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie);
+ extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *));
+ extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *));
+-struct neigh_seq_state
+-{
+-      struct net *net;
++struct neigh_seq_state {
+       struct neigh_table *tbl;
+       void *(*neigh_sub_iter)(struct neigh_seq_state *state,
+                               struct neighbour *n, loff_t *pos);
+diff -Nurb linux-2.6.22-590/include/net/net_namespace.h linux-2.6.22-570/include/net/net_namespace.h
+--- linux-2.6.22-590/include/net/net_namespace.h       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/net_namespace.h       1969-12-31 19:00:00.000000000 -0500
+@@ -1,236 +0,0 @@
+-/*
+- * Operations on the network namespace
+- */
+-#ifndef __NET_NET_NAMESPACE_H
+-#define __NET_NET_NAMESPACE_H
+-
+-#include <asm/atomic.h>
+-#include <linux/workqueue.h>
+-#include <linux/list.h>
+-#include <linux/proc_fs.h>
+-#include <linux/sysctl.h>
+-#include <linux/netdevice.h>
+-#include <linux/timer.h>
+-
+-struct sock;
+-struct xt_af_pernet;
+-struct ipv4_devconf;
+-struct neigh_parms;
+-struct inet_peer;
+-struct xt_table;
+-struct net {
+-      atomic_t count;         /* To decided when the network namespace
+-                               * should go
+-                               */
+-      atomic_t use_count;     /* For references we destroy on demand */
+-      struct list_head list;  /* list of network namespace structures */
+-      struct work_struct work;        /* work struct for freeing */
+-
+-#ifdef CONFIG_PROC_FS
+-      struct proc_dir_entry *proc_net;
+-      struct proc_dir_entry *proc_net_stat;
+-      struct proc_dir_entry proc_net_root;
+-# ifdef CONFIG_NETFILTER
+-      struct proc_dir_entry *proc_net_netfilter;
+-# endif
+-#endif
+-#ifdef CONFIG_SYSCTL
+-      struct ctl_table_header net_table_header;
+-#endif
+-      struct net_device       loopback_dev;           /* The loopback */
+-      struct list_head        dev_base_head;          /* All devices */
+-
+-      struct hlist_head       *dev_name_head;
+-      struct hlist_head       *dev_index_head;
+-
+-      struct sock *           rtnl;   /* rtnetlink socket */
+-
+-
+-      /* core netfilter */
+-      struct xt_af_pernet *   xtn;
+-
+-      /* core fib_rules */
+-      struct list_head        rules_ops;
+-      spinlock_t              rules_mod_lock;
+-
+-#ifdef CONFIG_XFRM
+-      u32                     sysctl_xfrm_aevent_etime;
+-      u32                     sysctl_xfrm_aevent_rseqth;
+-      int                     sysctl_xfrm_larval_drop;
+-      u32                     sysctl_xfrm_acq_expires;
+-#endif /* CONFIG_XFRM */
+-
+-      int                     sysctl_somaxconn;
+-
+-#ifdef CONFIG_PACKET
+-      /* List of all packet sockets. */
+-      rwlock_t                packet_sklist_lock;
+-      struct hlist_head       packet_sklist;
+-#endif /* CONFIG_PACKET */
+-#ifdef CONFIG_UNIX
+-      int                     sysctl_unix_max_dgram_qlen;
+-      void *                  unix_sysctl;
+-#endif /* CONFIG_UNIX */
+-#ifdef CONFIG_IP_MULTIPLE_TABLES
+-      void *                  fib4_table;
+-#endif /* CONFIG_IP_MULTIPLE_TABLES */
+-#ifdef CONFIG_IP_FIB_HASH
+-      int                     fn_hash_last_dflt;
+-#endif
+-#ifdef CONFIG_IP_FIB_TRIE
+-      int                     trie_last_dflt;
+-#endif
+-#ifndef CONFIG_IP_MULTIPLE_TABLES
+-      struct fib_table        *ip_fib_local_table;
+-      struct fib_table        *ip_fib_main_table;
+-#endif
+-      struct hlist_head       *ip_fib_table_hash;
+-      struct sock             *nlfl;
+-
+-      /* fib_semantics */
+-      struct hlist_head       *fib_info_hash;
+-      struct hlist_head       *fib_info_laddrhash;
+-      unsigned int            fib_info_hash_size;
+-      unsigned int            fib_info_cnt;
+-      struct hlist_head       *fib_info_devhash;
+-
+-      /* af_inet.c */
+-      int                     sysctl_ip_nonlocal_bind; /* __read_mostly */
+-      int                     sysctl_ip_default_ttl;  /* __read_mostly */
+-      int                     sysctl_ipfrag_high_thresh;
+-      int                     sysctl_ipfrag_low_thresh;
+-      int                     sysctl_ipfrag_time;
+-      int                     sysctl_ipfrag_secret_interval;
+-      int                     sysctl_ipfrag_max_dist;
+-      int                     sysctl_ipv4_no_pmtu_disc;
+-      int                     sysctl_local_port_range[2];
+-      int                     sysctl_ip_dynaddr;
+-      int                     sysctl_tcp_timestamps;  /* __read_mostly */
+-      int                     sysctl_tcp_window_scaling; /* __read_mostly */
+-      /* inetpeer.c */
+-      int                     inet_peer_threshold;
+-      int                     inet_peer_minttl;
+-      int                     inet_peer_maxttl;
+-      int                     inet_peer_gc_mintime;
+-      int                     inet_peer_gc_maxtime;
+-
+-      /* devinet */
+-      struct ipv4_devconf     *ipv4_devconf;
+-      struct ipv4_devconf     *ipv4_devconf_dflt;
+-
+-      /* arp.c */
+-      struct neigh_parms      *arp_neigh_parms_default;
+-
+-      /* icmp.c */
+-      struct socket           **__icmp_socket;
+-
+-      /* inetpeer.c */
+-      struct inet_peer        *peer_root;
+-      int                     peer_total;
+-      struct inet_peer        *inet_peer_unused_head;
+-      struct inet_peer        **inet_peer_unused_tailp;
+-      struct timer_list       peer_periodic_timer;
+-
+-      /* ip_fragment.c */
+-      struct hlist_head       *ipq_hash;
+-      u32                     ipfrag_hash_rnd;
+-      struct list_head        ipq_lru_list;
+-      int                     ip_frag_nqueues;
+-      atomic_t                ip_frag_mem;
+-      struct timer_list       ipfrag_secret_timer;
+-
+-      /* udp.c */
+-      int                     udp_port_rover;
+-
+-      /* iptable_filter.c */
+-      struct xt_table         *ip_packet_filter;
+-};
+-
+-extern struct net init_net;
+-extern struct list_head net_namespace_list;
+-
+-extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns);
+-extern void __put_net(struct net *net);
+-
+-static inline struct net *get_net(struct net *net)
+-{
+-      atomic_inc(&net->count);
+-      return net;
+-}
+-
+-static inline void put_net(struct net *net)
+-{
+-      if (atomic_dec_and_test(&net->count))
+-              __put_net(net);
+-}
+-
+-static inline struct net *hold_net(struct net *net)
+-{
+-      atomic_inc(&net->use_count);
+-      return net;
+-}
+-
+-static inline void release_net(struct net *net)
+-{
+-      atomic_dec(&net->use_count);
+-}
+-
+-extern void net_lock(void);
+-extern void net_unlock(void);
+-
+-#define for_each_net(VAR)                             \
+-      list_for_each_entry(VAR, &net_namespace_list, list)
+-
+-
+-struct pernet_operations {
+-      struct list_head list;
+-      int (*init)(struct net *net);
+-      void (*exit)(struct net *net);
+-};
+-
+-extern int register_pernet_subsys(struct pernet_operations *);
+-extern void unregister_pernet_subsys(struct pernet_operations *);
+-extern int register_pernet_device(struct pernet_operations *);
+-extern void unregister_pernet_device(struct pernet_operations *);
+-
+-#ifdef CONFIG_PROC_FS
+-static inline struct net *PDE_NET(struct proc_dir_entry *pde)
+-{
+-      return pde->parent->data;
+-}
+-
+-static inline struct net *PROC_NET(const struct inode *inode)
+-{
+-      return PDE_NET(PDE(inode));
+-}
+-
+-static inline struct proc_dir_entry *proc_net_create(struct net *net,
+-      const char *name, mode_t mode, get_info_t *get_info)
+-{
+-      return create_proc_info_entry(name,mode, net->proc_net, get_info);
+-}
+-
+-static inline struct proc_dir_entry *proc_net_fops_create(struct net *net,
+-      const char *name, mode_t mode, const struct file_operations *fops)
+-{
+-      struct proc_dir_entry *res = 
+-              create_proc_entry(name, mode, net->proc_net);
+-      if (res)
+-              res->proc_fops = fops;
+-      return res;
+-}
+-
+-static inline void proc_net_remove(struct net *net, const char *name)
+-{
+-      remove_proc_entry(name, net->proc_net);
+-}
+-
+-#else
+-
+-#define proc_net_fops_create(net, name, mode, fops)  ({ (void)(mode), NULL; })
+-#define proc_net_create(net, name, mode, info)        ({ (void)(mode), NULL; })
+-static inline void proc_net_remove(struct net *net, const char *name) {}
+-
+-#endif /* CONFIG_PROC_FS */
+-
+-#endif /* __NET_NET_NAMESPACE_H */
+diff -Nurb linux-2.6.22-590/include/net/netlink.h linux-2.6.22-570/include/net/netlink.h
+--- linux-2.6.22-590/include/net/netlink.h     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/netlink.h     2007-07-08 19:32:17.000000000 -0400
+@@ -118,9 +118,6 @@
+  * Nested Attributes Construction:
+  *   nla_nest_start(skb, type)                start a nested attribute
+  *   nla_nest_end(skb, nla)           finalize a nested attribute
+- *   nla_nest_compat_start(skb, type, start a nested compat attribute
+- *                       len, data)
+- *   nla_nest_compat_end(skb, type)   finalize a nested compat attribute
+  *   nla_nest_cancel(skb, nla)                cancel nested attribute construction
+  *
+  * Attribute Length Calculations:
+@@ -155,7 +152,6 @@
+  *   nla_find_nested()                        find attribute in nested attributes
+  *   nla_parse()                      parse and validate stream of attrs
+  *   nla_parse_nested()                       parse nested attribuets
+- *   nla_parse_nested_compat()                parse nested compat attributes
+  *   nla_for_each_attr()              loop over all attributes
+  *   nla_for_each_nested()            loop over the nested attributes
+  *=========================================================================
+@@ -174,7 +170,6 @@
+       NLA_FLAG,
+       NLA_MSECS,
+       NLA_NESTED,
+-      NLA_NESTED_COMPAT,
+       NLA_NUL_STRING,
+       NLA_BINARY,
+       __NLA_TYPE_MAX,
+@@ -195,7 +190,6 @@
+  *    NLA_NUL_STRING       Maximum length of string (excluding NUL)
+  *    NLA_FLAG             Unused
+  *    NLA_BINARY           Maximum length of attribute payload
+- *    NLA_NESTED_COMPAT    Exact length of structure payload
+  *    All other            Exact length of attribute payload
+  *
+  * Example:
+@@ -218,7 +212,6 @@
+ struct nl_info {
+       struct nlmsghdr         *nlh;
+       u32                     pid;
+-      struct net              *net;
+ };
+ extern void           netlink_run_queue(struct sock *sk, unsigned int *qlen,
+@@ -740,39 +733,6 @@
+ {
+       return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
+ }
+-
+-/**
+- * nla_parse_nested_compat - parse nested compat attributes
+- * @tb: destination array with maxtype+1 elements
+- * @maxtype: maximum attribute type to be expected
+- * @nla: attribute containing the nested attributes
+- * @data: pointer to point to contained structure
+- * @len: length of contained structure
+- * @policy: validation policy
+- *
+- * Parse a nested compat attribute. The compat attribute contains a structure
+- * and optionally a set of nested attributes. On success the data pointer
+- * points to the nested data and tb contains the parsed attributes
+- * (see nla_parse).
+- */
+-static inline int __nla_parse_nested_compat(struct nlattr *tb[], int maxtype,
+-                                          struct nlattr *nla,
+-                                          const struct nla_policy *policy,
+-                                          int len)
+-{
+-      if (nla_len(nla) < len)
+-              return -1;
+-      if (nla_len(nla) >= NLA_ALIGN(len) + sizeof(struct nlattr))
+-              return nla_parse_nested(tb, maxtype,
+-                                      nla_data(nla) + NLA_ALIGN(len),
+-                                      policy);
+-      memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
+-      return 0;
+-}
+-
+-#define nla_parse_nested_compat(tb, maxtype, nla, policy, data, len) \
+-({    data = nla_len(nla) >= len ? nla_data(nla) : NULL; \
+-      __nla_parse_nested_compat(tb, maxtype, nla, policy, len); })
+ /**
+  * nla_put_u8 - Add a u16 netlink attribute to a socket buffer
+  * @skb: socket buffer to add attribute to
+@@ -1005,51 +965,6 @@
  }
  
  /**
-- *    kobject_add - add an object to the hierarchy.
-- *    @kobj:  object.
+- * nla_nest_compat_start - Start a new level of nested compat attributes
+- * @skb: socket buffer to add attributes to
+- * @attrtype: attribute type of container
+- * @attrlen: length of structure
+- * @data: pointer to structure
+- *
+- * Start a nested compat attribute that contains both a structure and
+- * a set of nested attributes.
+- *
+- * Returns the container attribute
 - */
--int kobject_add(struct kobject * kobj)
+-static inline struct nlattr *nla_nest_compat_start(struct sk_buff *skb,
+-                                                 int attrtype, int attrlen,
+-                                                 const void *data)
 -{
--      return kobject_shadow_add(kobj, NULL);
--}
+-      struct nlattr *start = (struct nlattr *)skb_tail_pointer(skb);
 -
+-      if (nla_put(skb, attrtype, attrlen, data) < 0)
+-              return NULL;
+-      if (nla_nest_start(skb, attrtype) == NULL) {
+-              nlmsg_trim(skb, start);
+-              return NULL;
+-      }
+-      return start;
+-}
 -
 -/**
-  *    kobject_register - initialize and add an object.
-  *    @kobj:  object in question.
-  */
-@@ -338,7 +327,7 @@
-       /* Note : if we want to send the new name alone, not the full path,
-        * we could probably use kobject_name(kobj); */
--      error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name);
-+      error = sysfs_rename_dir(kobj, new_name);
-       /* This function is mostly/only used for network interface.
-        * Some hotplug package track interfaces by their name and
-@@ -355,27 +344,6 @@
- }
- /**
-- *    kobject_rename - change the name of an object
-- *    @kobj:  object in question.
-- *    @new_parent: object's new parent
-- *    @new_name: object's new name
+- * nla_nest_compat_end - Finalize nesting of compat attributes
+- * @skb: socket buffer the attribtues are stored in
+- * @start: container attribute
+- *
+- * Corrects the container attribute header to include the all
+- * appeneded attributes.
+- *
+- * Returns the total data length of the skb.
 - */
--
--int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent,
--                        const char *new_name)
+-static inline int nla_nest_compat_end(struct sk_buff *skb, struct nlattr *start)
 -{
--      int error = 0;
--
--      kobj = kobject_get(kobj);
--      if (!kobj)
--              return -EINVAL;
--      error = sysfs_rename_dir(kobj, new_parent, new_name);
--      kobject_put(kobj);
+-      struct nlattr *nest = (void *)start + NLMSG_ALIGN(start->nla_len);
 -
--      return error;
+-      start->nla_len = skb_tail_pointer(skb) - (unsigned char *)start;
+-      return nla_nest_end(skb, nest);
 -}
 -
 -/**
-  *    kobject_move - move object to another parent
-  *    @kobj:  object in question.
-  *    @new_parent: object's new parent (can be NULL)
-diff -Nurb linux-2.6.22-570/lib/kobject_uevent.c linux-2.6.22-590/lib/kobject_uevent.c
---- linux-2.6.22-570/lib/kobject_uevent.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/lib/kobject_uevent.c      2008-01-02 13:56:38.000000000 -0500
-@@ -208,7 +208,7 @@
-               argv [0] = uevent_helper;
-               argv [1] = (char *)subsystem;
-               argv [2] = NULL;
--              call_usermodehelper (argv[0], argv, envp, 0);
-+              call_usermodehelper (argv[0], argv, envp, UMH_WAIT_EXEC);
+  * nla_nest_cancel - Cancel nesting of attributes
+  * @skb: socket buffer the message is stored in
+  * @start: container attribute
+diff -Nurb linux-2.6.22-590/include/net/pkt_cls.h linux-2.6.22-570/include/net/pkt_cls.h
+--- linux-2.6.22-590/include/net/pkt_cls.h     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/pkt_cls.h     2007-07-08 19:32:17.000000000 -0400
+@@ -2,7 +2,6 @@
+ #define __NET_PKT_CLS_H
+ #include <linux/pkt_cls.h>
+-#include <net/net_namespace.h>
+ #include <net/sch_generic.h>
+ #include <net/act_api.h>
+@@ -358,7 +357,7 @@
+       if (indev[0]) {
+               if  (!skb->iif)
+                       return 0;
+-              dev = __dev_get_by_index(&init_net, skb->iif);
++              dev = __dev_get_by_index(skb->iif);
+               if (!dev || strcmp(indev, dev->name))
+                       return 0;
        }
+diff -Nurb linux-2.6.22-590/include/net/protocol.h linux-2.6.22-570/include/net/protocol.h
+--- linux-2.6.22-590/include/net/protocol.h    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/protocol.h    2007-07-08 19:32:17.000000000 -0400
+@@ -86,7 +86,6 @@
+ #define INET_PROTOSW_REUSE 0x01            /* Are ports automatically reusable? */
+ #define INET_PROTOSW_PERMANENT 0x02  /* Permanent protocols are unremovable. */
+ #define INET_PROTOSW_ICSK      0x04  /* Is this an inet_connection_sock? */
+-#define INET_PROTOSW_NETNS     0x08  /* Multiple namespaces support? */
  
- exit:
-@@ -290,9 +290,8 @@
- #if defined(CONFIG_NET)
- static int __init kobject_uevent_init(void)
- {
--      uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
--                                          NULL, THIS_MODULE);
--
-+      uevent_sock = netlink_kernel_create(&init_net, NETLINK_KOBJECT_UEVENT,
-+                                          1, NULL, NULL, THIS_MODULE);
-       if (!uevent_sock) {
-               printk(KERN_ERR
-                      "kobject_uevent: unable to create netlink socket!\n");
-diff -Nurb linux-2.6.22-570/lib/pagewalk.c linux-2.6.22-590/lib/pagewalk.c
---- linux-2.6.22-570/lib/pagewalk.c    1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/lib/pagewalk.c    2008-01-02 13:56:38.000000000 -0500
-@@ -0,0 +1,112 @@
-+#include <linux/mm.h>
-+#include <linux/highmem.h>
-+
-+static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
-+                        struct mm_walk *walk, void *private)
-+{
-+      pte_t *pte;
-+      int err;
-+
-+      for (pte = pte_offset_map(pmd, addr); addr != end;
-+           addr += PAGE_SIZE, pte++) {
-+              if (pte_none(*pte))
-+                      continue;
-+              err = walk->pte_entry(pte, addr, addr, private);
-+              if (err) {
-+                      pte_unmap(pte);
-+                      return err;
-+              }
-+      }
-+      pte_unmap(pte);
-+      return 0;
-+}
-+
-+static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
-+                        struct mm_walk *walk, void *private)
-+{
-+      pmd_t *pmd;
-+      unsigned long next;
-+      int err;
-+
-+      for (pmd = pmd_offset(pud, addr); addr != end;
-+           pmd++, addr = next) {
-+              next = pmd_addr_end(addr, end);
-+              if (pmd_none_or_clear_bad(pmd))
-+                      continue;
-+              if (walk->pmd_entry) {
-+                      err = walk->pmd_entry(pmd, addr, next, private);
-+                      if (err)
-+                              return err;
-+              }
-+              if (walk->pte_entry) {
-+                      err = walk_pte_range(pmd, addr, next, walk, private);
-+                      if (err)
-+                              return err;
-+              }
-+      }
-+      return 0;
-+}
-+
-+static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
-+                        struct mm_walk *walk, void *private)
-+{
-+      pud_t *pud;
-+      unsigned long next;
-+      int err;
-+
-+      for (pud = pud_offset(pgd, addr); addr != end;
-+           pud++, addr = next) {
-+              next = pud_addr_end(addr, end);
-+              if (pud_none_or_clear_bad(pud))
-+                      continue;
-+              if (walk->pud_entry) {
-+                      err = walk->pud_entry(pud, addr, next, private);
-+                      if (err)
-+                              return err;
-+              }
-+              if (walk->pmd_entry || walk->pte_entry) {
-+                      err = walk_pmd_range(pud, addr, next, walk, private);
-+                      if (err)
-+                              return err;
-+              }
-+      }
-+      return 0;
-+}
-+
-+/*
-+ * walk_page_range - walk a memory map's page tables with a callback
-+ * @mm - memory map to walk
-+ * @addr - starting address
-+ * @end - ending address
-+ * @walk - set of callbacks to invoke for each level of the tree
-+ * @private - private data passed to the callback function
-+ *
-+ * Recursively walk the page table for the memory area in a VMA, calling
-+ * a callback for every bottom-level (PTE) page table.
-+ */
-+int walk_page_range(struct mm_struct *mm,
-+                  unsigned long addr, unsigned long end,
-+                  struct mm_walk *walk, void *private)
-+{
-+      pgd_t *pgd;
-+      unsigned long next;
-+      int err;
-+
-+      for (pgd = pgd_offset(mm, addr); addr != end;
-+           pgd++, addr = next) {
-+              next = pgd_addr_end(addr, end);
-+              if (pgd_none_or_clear_bad(pgd))
-+                      continue;
-+              if (walk->pgd_entry) {
-+                      err = walk->pgd_entry(pgd, addr, next, private);
-+                      if (err)
-+                              return err;
-+              }
-+              if (walk->pud_entry || walk->pmd_entry || walk->pte_entry) {
-+                      err = walk_pud_range(pgd, addr, next, walk, private);
-+                      if (err)
-+                              return err;
-+              }
-+      }
-+      return 0;
-+}
-diff -Nurb linux-2.6.22-570/lib/radix-tree.c linux-2.6.22-590/lib/radix-tree.c
---- linux-2.6.22-570/lib/radix-tree.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/lib/radix-tree.c  2008-01-02 13:56:38.000000000 -0500
-@@ -93,7 +93,8 @@
-       struct radix_tree_node *ret;
-       gfp_t gfp_mask = root_gfp_mask(root);
+ extern struct net_protocol *inet_protocol_base;
+ extern struct net_protocol *inet_protos[MAX_INET_PROTOS];
+diff -Nurb linux-2.6.22-590/include/net/raw.h linux-2.6.22-570/include/net/raw.h
+--- linux-2.6.22-590/include/net/raw.h 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/raw.h 2008-01-23 19:16:10.000000000 -0500
+@@ -34,7 +34,7 @@
+ extern rwlock_t raw_v4_lock;
  
--      ret = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
-+      ret = kmem_cache_alloc(radix_tree_node_cachep,
-+                              set_migrateflags(gfp_mask, __GFP_RECLAIMABLE));
-       if (ret == NULL && !(gfp_mask & __GFP_WAIT)) {
-               struct radix_tree_preload *rtp;
  
-@@ -137,7 +138,8 @@
-       rtp = &__get_cpu_var(radix_tree_preloads);
-       while (rtp->nr < ARRAY_SIZE(rtp->nodes)) {
-               preempt_enable();
--              node = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
-+              node = kmem_cache_alloc(radix_tree_node_cachep,
-+                              set_migrateflags(gfp_mask, __GFP_RECLAIMABLE));
-               if (node == NULL)
-                       goto out;
-               preempt_disable();
-diff -Nurb linux-2.6.22-570/mm/filemap.c linux-2.6.22-590/mm/filemap.c
---- linux-2.6.22-570/mm/filemap.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/mm/filemap.c      2008-01-02 13:56:38.000000000 -0500
-@@ -1334,39 +1334,38 @@
- #define MMAP_LOTSAMISS  (100)
+-extern struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, unsigned short num,
++extern struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
+                                   __be32 raddr, __be32 laddr,
+                                   int dif, int tag);
  
- /**
-- * filemap_nopage - read in file data for page fault handling
-- * @area:     the applicable vm_area
-- * @address:  target address to read in
-- * @type:     returned with VM_FAULT_{MINOR,MAJOR} if not %NULL
-+ * filemap_fault - read in file data for page fault handling
-+ * @vma:      user vma (not used)
-+ * @fdata:    the applicable fault_data
-  *
-- * filemap_nopage() is invoked via the vma operations vector for a
-+ * filemap_fault() is invoked via the vma operations vector for a
-  * mapped memory region to read in file data during a page fault.
-  *
-  * The goto's are kind of ugly, but this streamlines the normal case of having
-  * it in the page cache, and handles the special cases reasonably without
-  * having a lot of duplicated code.
-  */
--struct page *filemap_nopage(struct vm_area_struct *area,
--                              unsigned long address, int *type)
-+struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
- {
-       int error;
--      struct file *file = area->vm_file;
-+      struct file *file = vma->vm_file;
-       struct address_space *mapping = file->f_mapping;
-       struct file_ra_state *ra = &file->f_ra;
-       struct inode *inode = mapping->host;
-       struct page *page;
--      unsigned long size, pgoff;
--      int did_readaround = 0, majmin = VM_FAULT_MINOR;
-+      unsigned long size;
-+      int did_readaround = 0;
+diff -Nurb linux-2.6.22-590/include/net/rawv6.h linux-2.6.22-570/include/net/rawv6.h
+--- linux-2.6.22-590/include/net/rawv6.h       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/rawv6.h       2007-07-08 19:32:17.000000000 -0400
+@@ -3,8 +3,6 @@
  
--      pgoff = ((address-area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
-+      fdata->type = VM_FAULT_MINOR;
-+
-+      BUG_ON(!(vma->vm_flags & VM_CAN_INVALIDATE));
+ #ifdef __KERNEL__
  
--retry_all:
-       size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
--      if (pgoff >= size)
-+      if (fdata->pgoff >= size)
-               goto outside_data_content;
+-#include <net/protocol.h>
+-
+ #define RAWV6_HTABLE_SIZE     MAX_INET_PROTOS
+ extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE];
+ extern rwlock_t raw_v6_lock;
+@@ -25,13 +23,6 @@
+                                         int type, int code, 
+                                         int offset, __be32 info);
  
-       /* If we don't want any read-ahead, don't bother */
--      if (VM_RandomReadHint(area))
-+      if (VM_RandomReadHint(vma))
-               goto no_cached_page;
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+-int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
+-                                         struct sk_buff *skb));
+-int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
+-                                           struct sk_buff *skb));
+-#endif
+-
+ #endif
  
-       /*
-@@ -1375,19 +1374,19 @@
-        *
-        * For sequential accesses, we use the generic readahead logic.
-        */
--      if (VM_SequentialReadHint(area))
--              page_cache_readahead(mapping, ra, file, pgoff, 1);
-+      if (VM_SequentialReadHint(vma))
-+              page_cache_readahead(mapping, ra, file, fdata->pgoff, 1);
+ #endif
+diff -Nurb linux-2.6.22-590/include/net/route.h linux-2.6.22-570/include/net/route.h
+--- linux-2.6.22-590/include/net/route.h       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/route.h       2008-01-23 19:16:05.000000000 -0500
+@@ -27,7 +27,6 @@
+ #include <net/dst.h>
+ #include <net/inetpeer.h>
+ #include <net/flow.h>
+-#include <net/sock.h>
+ #include <net/inet_sock.h>
+ #include <linux/in_route.h>
+ #include <linux/rtnetlink.h>
+@@ -67,6 +66,7 @@
+       
+       unsigned                rt_flags;
+       __u16                   rt_type;
++      __u16                   rt_multipath_alg;
  
-       /*
-        * Do we have something in the page cache already?
-        */
- retry_find:
--      page = find_get_page(mapping, pgoff);
-+      page = find_lock_page(mapping, fdata->pgoff);
-       if (!page) {
-               unsigned long ra_pages;
+       __be32                  rt_dst; /* Path destination     */
+       __be32                  rt_src; /* Path source          */
+@@ -123,9 +123,9 @@
+ extern unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu);
+ extern void           ip_rt_send_redirect(struct sk_buff *skb);
  
--              if (VM_SequentialReadHint(area)) {
--                      handle_ra_miss(mapping, ra, pgoff);
-+              if (VM_SequentialReadHint(vma)) {
-+                      handle_ra_miss(mapping, ra, fdata->pgoff);
-                       goto no_cached_page;
-               }
-               ra->mmap_miss++;
-@@ -1404,7 +1403,7 @@
-                * check did_readaround, as this is an inner loop.
-                */
-               if (!did_readaround) {
--                      majmin = VM_FAULT_MAJOR;
-+                      fdata->type = VM_FAULT_MAJOR;
-                       count_vm_event(PGMAJFAULT);
-               }
-               did_readaround = 1;
-@@ -1412,11 +1411,11 @@
-               if (ra_pages) {
-                       pgoff_t start = 0;
+-extern unsigned               inet_addr_type(struct net *net, __be32 addr);
++extern unsigned               inet_addr_type(__be32 addr);
+ extern void           ip_rt_multicast_event(struct in_device *);
+-extern int            ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg);
++extern int            ip_rt_ioctl(unsigned int cmd, void __user *arg);
+ extern void           ip_rt_get_source(u8 *src, struct rtable *rt);
+ extern int            ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb);
  
--                      if (pgoff > ra_pages / 2)
--                              start = pgoff - ra_pages / 2;
-+                      if (fdata->pgoff > ra_pages / 2)
-+                              start = fdata->pgoff - ra_pages / 2;
-                       do_page_cache_readahead(mapping, file, start, ra_pages);
-               }
--              page = find_get_page(mapping, pgoff);
-+              page = find_lock_page(mapping, fdata->pgoff);
-               if (!page)
-                       goto no_cached_page;
-       }
-@@ -1425,19 +1424,23 @@
-               ra->mmap_hit++;
+@@ -154,8 +154,7 @@
+                                  __be16 sport, __be16 dport, struct sock *sk,
+                                  int flags)
+ {
+-      struct flowi fl = { .fl_net = sk->sk_net,
+-                          .oif = oif,
++      struct flowi fl = { .oif = oif,
+                           .nl_u = { .ip4_u = { .daddr = dst,
+                                                .saddr = src,
+                                                .tos   = tos } },
+@@ -200,7 +199,6 @@
+               struct flowi fl;
  
-       /*
--       * Ok, found a page in the page cache, now we need to check
--       * that it's up-to-date.
-+       * We have a locked page in the page cache, now we need to check
-+       * that it's up-to-date. If not, it is going to be due to an error.
-        */
--      if (!PageUptodate(page))
-+      if (unlikely(!PageUptodate(page)))
-               goto page_not_uptodate;
+               memcpy(&fl, &(*rp)->fl, sizeof(fl));
+-              fl.fl_net = sk->sk_net;
+               fl.fl_ip_sport = sport;
+               fl.fl_ip_dport = dport;
+               fl.proto = protocol;
+diff -Nurb linux-2.6.22-590/include/net/rtnetlink.h linux-2.6.22-570/include/net/rtnetlink.h
+--- linux-2.6.22-590/include/net/rtnetlink.h   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/rtnetlink.h   2007-07-08 19:32:17.000000000 -0400
+@@ -22,62 +22,4 @@
+               return AF_UNSPEC;
+ }
  
--success:
-+      /* Must recheck i_size under page lock */
-+      size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-+      if (unlikely(fdata->pgoff >= size)) {
-+              unlock_page(page);
-+              goto outside_data_content;
-+      }
-+
-       /*
-        * Found the page and have a reference on it.
-        */
-       mark_page_accessed(page);
--      if (type)
--              *type = majmin;
-       return page;
+-/**
+- *    struct rtnl_link_ops - rtnetlink link operations
+- *
+- *    @list: Used internally
+- *    @kind: Identifier
+- *    @maxtype: Highest device specific netlink attribute number
+- *    @policy: Netlink policy for device specific attribute validation
+- *    @validate: Optional validation function for netlink/changelink parameters
+- *    @priv_size: sizeof net_device private space
+- *    @setup: net_device setup function
+- *    @newlink: Function for configuring and registering a new device
+- *    @changelink: Function for changing parameters of an existing device
+- *    @dellink: Function to remove a device
+- *    @get_size: Function to calculate required room for dumping device
+- *               specific netlink attributes
+- *    @fill_info: Function to dump device specific netlink attributes
+- *    @get_xstats_size: Function to calculate required room for dumping devic
+- *                      specific statistics
+- *    @fill_xstats: Function to dump device specific statistics
+- */
+-struct rtnl_link_ops {
+-      struct list_head        list;
+-
+-      const char              *kind;
+-
+-      size_t                  priv_size;
+-      void                    (*setup)(struct net_device *dev);
+-
+-      int                     maxtype;
+-      const struct nla_policy *policy;
+-      int                     (*validate)(struct nlattr *tb[],
+-                                          struct nlattr *data[]);
+-
+-      int                     (*newlink)(struct net_device *dev,
+-                                         struct nlattr *tb[],
+-                                         struct nlattr *data[]);
+-      int                     (*changelink)(struct net_device *dev,
+-                                            struct nlattr *tb[],
+-                                            struct nlattr *data[]);
+-      void                    (*dellink)(struct net_device *dev);
+-
+-      size_t                  (*get_size)(const struct net_device *dev);
+-      int                     (*fill_info)(struct sk_buff *skb,
+-                                           const struct net_device *dev);
+-
+-      size_t                  (*get_xstats_size)(const struct net_device *dev);
+-      int                     (*fill_xstats)(struct sk_buff *skb,
+-                                             const struct net_device *dev);
+-};
+-
+-extern int    __rtnl_link_register(struct rtnl_link_ops *ops);
+-extern void   __rtnl_link_unregister(struct rtnl_link_ops *ops);
+-
+-extern int    rtnl_link_register(struct rtnl_link_ops *ops);
+-extern void   rtnl_link_unregister(struct rtnl_link_ops *ops);
+-
+-#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
+-
+ #endif
+diff -Nurb linux-2.6.22-590/include/net/sock.h linux-2.6.22-570/include/net/sock.h
+--- linux-2.6.22-590/include/net/sock.h        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/sock.h        2008-01-23 19:16:05.000000000 -0500
+@@ -55,7 +55,6 @@
+ #include <asm/atomic.h>
+ #include <net/dst.h>
+ #include <net/checksum.h>
+-#include <net/net_namespace.h>
  
- outside_data_content:
-@@ -1445,15 +1448,17 @@
-        * An external ptracer can access pages that normally aren't
-        * accessible..
-        */
--      if (area->vm_mm == current->mm)
--              return NOPAGE_SIGBUS;
-+      if (vma->vm_mm == current->mm) {
-+              fdata->type = VM_FAULT_SIGBUS;
-+              return NULL;
-+      }
-       /* Fall through to the non-read-ahead case */
- no_cached_page:
-       /*
-        * We're only likely to ever get here if MADV_RANDOM is in
-        * effect.
-        */
--      error = page_cache_read(file, pgoff);
-+      error = page_cache_read(file, fdata->pgoff);
+ /*
+  * This structure really needs to be cleaned up.
+@@ -106,7 +105,6 @@
+  *    @skc_refcnt: reference count
+  *    @skc_hash: hash value used with various protocol lookup tables
+  *    @skc_prot: protocol handlers inside a network family
+- *    @skc_net: reference to the network namespace of this socket
+  *
+  *    This is the minimal network layer representation of sockets, the header
+  *    for struct sock and struct inet_timewait_sock.
+@@ -121,7 +119,6 @@
+       atomic_t                skc_refcnt;
+       unsigned int            skc_hash;
+       struct proto            *skc_prot;
+-      struct net              *skc_net;
+       xid_t                   skc_xid;
+       struct vx_info          *skc_vx_info;
+       nid_t                   skc_nid;
+@@ -202,7 +199,6 @@
+ #define sk_refcnt             __sk_common.skc_refcnt
+ #define sk_hash                       __sk_common.skc_hash
+ #define sk_prot                       __sk_common.skc_prot
+-#define sk_net                        __sk_common.skc_net
+ #define sk_xid                        __sk_common.skc_xid
+ #define sk_vx_info            __sk_common.skc_vx_info
+ #define sk_nid                        __sk_common.skc_nid
+@@ -785,7 +781,7 @@
+                               SINGLE_DEPTH_NESTING)
+ #define bh_unlock_sock(__sk)  spin_unlock(&((__sk)->sk_lock.slock))
  
-       /*
-        * The page we want has now been added to the page cache.
-@@ -1469,12 +1474,15 @@
-        * to schedule I/O.
-        */
-       if (error == -ENOMEM)
--              return NOPAGE_OOM;
--      return NOPAGE_SIGBUS;
-+              fdata->type = VM_FAULT_OOM;
-+      else
-+              fdata->type = VM_FAULT_SIGBUS;
-+      return NULL;
+-extern struct sock            *sk_alloc(struct net *net, int family,
++extern struct sock            *sk_alloc(int family,
+                                         gfp_t priority,
+                                         struct proto *prot, int zero_it);
+ extern void                   sk_free(struct sock *sk);
+@@ -1014,7 +1010,6 @@
+ #endif
  
- page_not_uptodate:
-+      /* IO error path */
-       if (!did_readaround) {
--              majmin = VM_FAULT_MAJOR;
-+              fdata->type = VM_FAULT_MAJOR;
-               count_vm_event(PGMAJFAULT);
-       }
+       memcpy(nsk, osk, osk->sk_prot->obj_size);
+-      get_net(nsk->sk_net);
+ #ifdef CONFIG_SECURITY_NETWORK
+       nsk->sk_security = sptr;
+       security_sk_clone(osk, nsk);
+@@ -1378,7 +1373,6 @@
  
-@@ -1484,38 +1492,39 @@
-        * because there really aren't any performance issues here
-        * and we need to check for errors.
-        */
--      lock_page(page);
--
--      /* Somebody truncated the page on us? */
--      if (!page->mapping) {
--              unlock_page(page);
--              page_cache_release(page);
--              goto retry_all;
--      }
--
--      /* Somebody else successfully read it in? */
--      if (PageUptodate(page)) {
--              unlock_page(page);
--              goto success;
--      }
-       ClearPageError(page);
-       error = mapping->a_ops->readpage(file, page);
--      if (!error) {
--              wait_on_page_locked(page);
--              if (PageUptodate(page))
--                      goto success;
--      } else if (error == AOP_TRUNCATED_PAGE) {
-               page_cache_release(page);
-+
-+      if (!error || error == AOP_TRUNCATED_PAGE)
-               goto retry_find;
--      }
+ #ifdef CONFIG_SYSCTL
+ extern struct ctl_table core_table[];
+-extern struct ctl_table multi_core_table[];
+ #endif
  
--      /*
--       * Things didn't work out. Return zero to tell the
--       * mm layer so, possibly freeing the page cache page first.
--       */
-+      /* Things didn't work out. Return zero to tell the mm layer so. */
-       shrink_readahead_size_eio(file, ra);
--      page_cache_release(page);
--      return NOPAGE_SIGBUS;
-+      fdata->type = VM_FAULT_SIGBUS;
-+      return NULL;
-+}
-+EXPORT_SYMBOL(filemap_fault);
-+
-+/*
-+ * filemap_nopage and filemap_populate are legacy exports that are not used
-+ * in tree. Scheduled for removal.
-+ */
-+struct page *filemap_nopage(struct vm_area_struct *area,
-+                              unsigned long address, int *type)
-+{
-+      struct page *page;
-+      struct fault_data fdata;
-+      fdata.address = address;
-+      fdata.pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT)
-+                      + area->vm_pgoff;
-+      fdata.flags = 0;
-+
-+      page = filemap_fault(area, &fdata);
-+      if (type)
-+              *type = fdata.type;
-+
-+      return page;
- }
- EXPORT_SYMBOL(filemap_nopage);
+ extern int sysctl_optmem_max;
+diff -Nurb linux-2.6.22-590/include/net/tcp.h linux-2.6.22-570/include/net/tcp.h
+--- linux-2.6.22-590/include/net/tcp.h 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/tcp.h 2008-01-23 19:15:56.000000000 -0500
+@@ -191,6 +191,8 @@
+ extern struct inet_timewait_death_row tcp_death_row;
  
-@@ -1693,8 +1702,7 @@
- EXPORT_SYMBOL(filemap_populate);
+ /* sysctl variables for tcp */
++extern int sysctl_tcp_timestamps;
++extern int sysctl_tcp_window_scaling;
+ extern int sysctl_tcp_sack;
+ extern int sysctl_tcp_fin_timeout;
+ extern int sysctl_tcp_keepalive_time;
+@@ -1291,7 +1293,6 @@
+ };
  
- struct vm_operations_struct generic_file_vm_ops = {
--      .nopage         = filemap_nopage,
--      .populate       = filemap_populate,
-+      .fault          = filemap_fault,
+ struct tcp_iter_state {
+-      struct net              *net;
+       sa_family_t             family;
+       enum tcp_seq_states     state;
+       struct sock             *syn_wait_sk;
+@@ -1299,8 +1300,8 @@
+       struct seq_operations   seq_ops;
  };
  
- /* This is used for a general mmap of a disk file */
-@@ -1707,6 +1715,7 @@
-               return -ENOEXEC;
-       file_accessed(file);
-       vma->vm_ops = &generic_file_vm_ops;
-+      vma->vm_flags |= VM_CAN_INVALIDATE | VM_CAN_NONLINEAR;
-       return 0;
- }
+-extern int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo);
+-extern void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo);
++extern int tcp_proc_register(struct tcp_seq_afinfo *afinfo);
++extern void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo);
  
-diff -Nurb linux-2.6.22-570/mm/filemap_xip.c linux-2.6.22-590/mm/filemap_xip.c
---- linux-2.6.22-570/mm/filemap_xip.c  2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/mm/filemap_xip.c  2008-01-02 13:56:38.000000000 -0500
-@@ -228,62 +228,67 @@
- }
+ extern struct request_sock_ops tcp_request_sock_ops;
  
+diff -Nurb linux-2.6.22-590/include/net/tipc/tipc_port.h linux-2.6.22-570/include/net/tipc/tipc_port.h
+--- linux-2.6.22-590/include/net/tipc/tipc_port.h      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/tipc/tipc_port.h      2007-07-08 19:32:17.000000000 -0400
+@@ -1,8 +1,8 @@
  /*
-- * xip_nopage() is invoked via the vma operations vector for a
-+ * xip_fault() is invoked via the vma operations vector for a
-  * mapped memory region to read in file data during a page fault.
+  * include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports
+  * 
+- * Copyright (c) 1994-2007, Ericsson AB
+- * Copyright (c) 2005-2007, Wind River Systems
++ * Copyright (c) 1994-2006, Ericsson AB
++ * Copyright (c) 2005, Wind River Systems
+  * All rights reserved.
   *
-- * This function is derived from filemap_nopage, but used for execute in place
-+ * This function is derived from filemap_fault, but used for execute in place
+  * Redistribution and use in source and binary forms, with or without
+@@ -55,7 +55,6 @@
+  * @conn_unacked: number of unacknowledged messages received from peer port
+  * @published: non-zero if port has one or more associated names
+  * @congested: non-zero if cannot send because of link or port congestion
+- * @max_pkt: maximum packet size "hint" used when building messages sent by port
+  * @ref: unique reference to port in TIPC object registry
+  * @phdr: preformatted message header used when sending messages
+  */
+@@ -69,7 +68,6 @@
+       u32 conn_unacked;
+       int published;
+       u32 congested;
+-      u32 max_pkt;
+       u32 ref;
+       struct tipc_msg phdr;
+ };
+diff -Nurb linux-2.6.22-590/include/net/udp.h linux-2.6.22-570/include/net/udp.h
+--- linux-2.6.22-590/include/net/udp.h 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/udp.h 2007-07-08 19:32:17.000000000 -0400
+@@ -160,7 +160,6 @@
+ };
+ struct udp_iter_state {
+-      struct net              *net;
+       sa_family_t             family;
+       struct hlist_head       *hashtable;
+       int                     bucket;
+@@ -168,8 +167,8 @@
+ };
+ #ifdef CONFIG_PROC_FS
+-extern int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo);
+-extern void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo);
++extern int udp_proc_register(struct udp_seq_afinfo *afinfo);
++extern void udp_proc_unregister(struct udp_seq_afinfo *afinfo);
+ extern int  udp4_proc_init(void);
+ extern void udp4_proc_exit(void);
+diff -Nurb linux-2.6.22-590/include/net/wext.h linux-2.6.22-570/include/net/wext.h
+--- linux-2.6.22-590/include/net/wext.h        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/wext.h        2007-07-08 19:32:17.000000000 -0400
+@@ -5,23 +5,16 @@
+  * wireless extensions interface to the core code
   */
--static struct page *
--xip_file_nopage(struct vm_area_struct * area,
--                 unsigned long address,
--                 int *type)
-+static struct page *xip_file_fault(struct vm_area_struct *area,
-+                                      struct fault_data *fdata)
+-struct net;
+-
+ #ifdef CONFIG_WIRELESS_EXT
+-extern int wext_proc_init(struct net *net);
+-extern void wext_proc_exit(struct net *net);
+-extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
++extern int wext_proc_init(void);
++extern int wext_handle_ioctl(struct ifreq *ifr, unsigned int cmd,
+                            void __user *arg);
+ #else
+-static inline int wext_proc_init(struct net *net)
++static inline int wext_proc_init(void)
  {
-       struct file *file = area->vm_file;
-       struct address_space *mapping = file->f_mapping;
-       struct inode *inode = mapping->host;
-       struct page *page;
--      unsigned long size, pgoff, endoff;
-+      pgoff_t size;
+       return 0;
+ }
+-static inline void wext_proc_exit(struct net *net)
+-{
+-      return;
+-}
+-static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
++static inline int wext_handle_ioctl(struct ifreq *ifr, unsigned int cmd,
+                                   void __user *arg)
+ {
+       return -EINVAL;
+diff -Nurb linux-2.6.22-590/include/net/xfrm.h linux-2.6.22-570/include/net/xfrm.h
+--- linux-2.6.22-590/include/net/xfrm.h        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/net/xfrm.h        2008-01-23 19:15:56.000000000 -0500
+@@ -19,21 +19,13 @@
+ #include <net/ipv6.h>
+ #include <net/ip6_fib.h>
  
--      pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT)
--              + area->vm_pgoff;
--      endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT)
--              + area->vm_pgoff;
-+      /* XXX: are VM_FAULT_ codes OK? */
+-#define XFRM_PROTO_ESP                50
+-#define XFRM_PROTO_AH         51
+-#define XFRM_PROTO_COMP               108
+-#define XFRM_PROTO_IPIP               4
+-#define XFRM_PROTO_IPV6               41
+-#define XFRM_PROTO_ROUTING    IPPROTO_ROUTING
+-#define XFRM_PROTO_DSTOPTS    IPPROTO_DSTOPTS
+-
+ #define XFRM_ALIGN8(len)      (((len) + 7) & ~7)
+ #define MODULE_ALIAS_XFRM_MODE(family, encap) \
+       MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
+-#define MODULE_ALIAS_XFRM_TYPE(family, proto) \
+-      MODULE_ALIAS("xfrm-type-" __stringify(family) "-" __stringify(proto))
  
-       size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
--      if (pgoff >= size)
--              return NOPAGE_SIGBUS;
-+      if (fdata->pgoff >= size) {
-+              fdata->type = VM_FAULT_SIGBUS;
-+              return NULL;
-+      }
+ extern struct sock *xfrm_nl;
++extern u32 sysctl_xfrm_aevent_etime;
++extern u32 sysctl_xfrm_aevent_rseqth;
  
--      page = mapping->a_ops->get_xip_page(mapping, pgoff*(PAGE_SIZE/512), 0);
-+      page = mapping->a_ops->get_xip_page(mapping,
-+                                      fdata->pgoff*(PAGE_SIZE/512), 0);
-       if (!IS_ERR(page))
-               goto out;
--      if (PTR_ERR(page) != -ENODATA)
--              return NOPAGE_SIGBUS;
-+      if (PTR_ERR(page) != -ENODATA) {
-+              fdata->type = VM_FAULT_OOM;
-+              return NULL;
-+      }
+ extern struct mutex xfrm_cfg_mutex;
  
-       /* sparse block */
-       if ((area->vm_flags & (VM_WRITE | VM_MAYWRITE)) &&
-           (area->vm_flags & (VM_SHARED| VM_MAYSHARE)) &&
-           (!(mapping->host->i_sb->s_flags & MS_RDONLY))) {
-               /* maybe shared writable, allocate new block */
--              page = mapping->a_ops->get_xip_page (mapping,
--                      pgoff*(PAGE_SIZE/512), 1);
--              if (IS_ERR(page))
--                      return NOPAGE_SIGBUS;
-+              page = mapping->a_ops->get_xip_page(mapping,
-+                                      fdata->pgoff*(PAGE_SIZE/512), 1);
-+              if (IS_ERR(page)) {
-+                      fdata->type = VM_FAULT_SIGBUS;
-+                      return NULL;
-+              }
-               /* unmap page at pgoff from all other vmas */
--              __xip_unmap(mapping, pgoff);
-+              __xip_unmap(mapping, fdata->pgoff);
-       } else {
-               /* not shared and writable, use xip_sparse_page() */
-               page = xip_sparse_page();
--              if (!page)
--                      return NOPAGE_OOM;
-+              if (!page) {
-+                      fdata->type = VM_FAULT_OOM;
-+                      return NULL;
-+              }
+@@ -517,9 +509,11 @@
+       case IPPROTO_ICMPV6:
+               port = htons(fl->fl_icmp_type);
+               break;
++#ifdef CONFIG_IPV6_MIP6
+       case IPPROTO_MH:
+               port = htons(fl->fl_mh_type);
+               break;
++#endif
+       default:
+               port = 0;       /*XXX*/
        }
+diff -Nurb linux-2.6.22-590/include/scsi/iscsi_if.h linux-2.6.22-570/include/scsi/iscsi_if.h
+--- linux-2.6.22-590/include/scsi/iscsi_if.h   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/scsi/iscsi_if.h   2007-07-08 19:32:17.000000000 -0400
+@@ -48,7 +48,6 @@
+       ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT    = UEVENT_BASE + 14,
+       ISCSI_UEVENT_TGT_DSCVR          = UEVENT_BASE + 15,
+-      ISCSI_UEVENT_SET_HOST_PARAM     = UEVENT_BASE + 16,
+       /* up events */
+       ISCSI_KEVENT_RECV_PDU           = KEVENT_BASE + 1,
+@@ -72,8 +71,6 @@
+               /* messages u -> k */
+               struct msg_create_session {
+                       uint32_t        initial_cmdsn;
+-                      uint16_t        cmds_max;
+-                      uint16_t        queue_depth;
+               } c_session;
+               struct msg_destroy_session {
+                       uint32_t        sid;
+@@ -139,11 +136,6 @@
+                        */
+                       uint32_t        enable;
+               } tgt_dscvr;
+-              struct msg_set_host_param {
+-                      uint32_t        host_no;
+-                      uint32_t        param; /* enum iscsi_host_param */
+-                      uint32_t        len;
+-              } set_host_param;
+       } u;
+       union {
+               /* messages k -> u */
+@@ -231,11 +223,6 @@
+       ISCSI_PARAM_CONN_PORT,
+       ISCSI_PARAM_CONN_ADDRESS,
+-      ISCSI_PARAM_USERNAME,
+-      ISCSI_PARAM_USERNAME_IN,
+-      ISCSI_PARAM_PASSWORD,
+-      ISCSI_PARAM_PASSWORD_IN,
+-
+       /* must always be last */
+       ISCSI_PARAM_MAX,
+ };
+@@ -262,24 +249,6 @@
+ #define ISCSI_SESS_RECOVERY_TMO               (1 << ISCSI_PARAM_SESS_RECOVERY_TMO)
+ #define ISCSI_CONN_PORT                       (1 << ISCSI_PARAM_CONN_PORT)
+ #define ISCSI_CONN_ADDRESS            (1 << ISCSI_PARAM_CONN_ADDRESS)
+-#define ISCSI_USERNAME                        (1 << ISCSI_PARAM_USERNAME)
+-#define ISCSI_USERNAME_IN             (1 << ISCSI_PARAM_USERNAME_IN)
+-#define ISCSI_PASSWORD                        (1 << ISCSI_PARAM_PASSWORD)
+-#define ISCSI_PASSWORD_IN             (1 << ISCSI_PARAM_PASSWORD_IN)
+-
+-/* iSCSI HBA params */
+-enum iscsi_host_param {
+-      ISCSI_HOST_PARAM_HWADDRESS,
+-      ISCSI_HOST_PARAM_INITIATOR_NAME,
+-      ISCSI_HOST_PARAM_NETDEV_NAME,
+-      ISCSI_HOST_PARAM_IPADDRESS,
+-      ISCSI_HOST_PARAM_MAX,
+-};
+-
+-#define ISCSI_HOST_HWADDRESS          (1 << ISCSI_HOST_PARAM_HWADDRESS)
+-#define ISCSI_HOST_INITIATOR_NAME     (1 << ISCSI_HOST_PARAM_INITIATOR_NAME)
+-#define ISCSI_HOST_NETDEV_NAME                (1 << ISCSI_HOST_PARAM_NETDEV_NAME)
+-#define ISCSI_HOST_IPADDRESS          (1 << ISCSI_HOST_PARAM_IPADDRESS)
+ #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
+ #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
+@@ -303,9 +272,6 @@
+ #define CAP_MULTI_CONN                0x40
+ #define CAP_TEXT_NEGO         0x80
+ #define CAP_MARKERS           0x100
+-#define CAP_FW_DB             0x200
+-#define CAP_SENDTARGETS_OFFLOAD       0x400
+-#define CAP_DATA_PATH_OFFLOAD 0x800
  
- out:
-+      fdata->type = VM_FAULT_MINOR;
-       page_cache_get(page);
-       return page;
- }
+ /*
+  * These flags describes reason of stop_conn() call
+diff -Nurb linux-2.6.22-590/include/scsi/libiscsi.h linux-2.6.22-570/include/scsi/libiscsi.h
+--- linux-2.6.22-590/include/scsi/libiscsi.h   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/scsi/libiscsi.h   2007-07-08 19:32:17.000000000 -0400
+@@ -48,8 +48,9 @@
+ #define debug_scsi(fmt...)
+ #endif
  
- static struct vm_operations_struct xip_file_vm_ops = {
--      .nopage         = xip_file_nopage,
-+      .fault  = xip_file_fault,
- };
+-#define ISCSI_DEF_XMIT_CMDS_MAX       128     /* must be power of 2 */
+-#define ISCSI_MGMT_CMDS_MAX   16      /* must be power of 2 */
++#define ISCSI_XMIT_CMDS_MAX   128     /* must be power of 2 */
++#define ISCSI_MGMT_CMDS_MAX   32      /* must be power of 2 */
++#define ISCSI_CONN_MAX                        1
  
- int xip_file_mmap(struct file * file, struct vm_area_struct * vma)
-@@ -292,6 +297,7 @@
+ #define ISCSI_MGMT_ITT_OFFSET 0xa00
  
-       file_accessed(file);
-       vma->vm_ops = &xip_file_vm_ops;
-+      vma->vm_flags |= VM_CAN_NONLINEAR;
-       return 0;
- }
- EXPORT_SYMBOL_GPL(xip_file_mmap);
-diff -Nurb linux-2.6.22-570/mm/fremap.c linux-2.6.22-590/mm/fremap.c
---- linux-2.6.22-570/mm/fremap.c       2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/mm/fremap.c       2008-01-02 13:56:38.000000000 -0500
-@@ -129,6 +129,25 @@
-       return err;
- }
+@@ -72,8 +73,6 @@
+ #define ISCSI_AGE_SHIFT                       28
+ #define ISCSI_AGE_MASK                        (0xf << ISCSI_AGE_SHIFT)
  
-+static int populate_range(struct mm_struct *mm, struct vm_area_struct *vma,
-+                      unsigned long addr, unsigned long size, pgoff_t pgoff)
-+{
-+      int err;
-+
-+      do {
-+              err = install_file_pte(mm, vma, addr, pgoff, vma->vm_page_prot);
-+              if (err)
-+                      return err;
-+
-+              size -= PAGE_SIZE;
-+              addr += PAGE_SIZE;
-+              pgoff++;
-+      } while (size);
-+
-+        return 0;
-+
-+}
-+
- /***
-  * sys_remap_file_pages - remap arbitrary pages of a shared backing store
-  *                        file within an existing vma.
-@@ -186,15 +205,27 @@
-        * the single existing vma.  vm_private_data is used as a
-        * swapout cursor in a VM_NONLINEAR vma.
+-#define ISCSI_ADDRESS_BUF_LEN         64
+-
+ struct iscsi_mgmt_task {
+       /*
+        * Becuae LLDs allocate their hdr differently, this is a pointer to
+@@ -81,7 +80,7 @@
         */
--      if (vma && (vma->vm_flags & VM_SHARED) &&
--              (!vma->vm_private_data || (vma->vm_flags & VM_NONLINEAR)) &&
--              vma->vm_ops && vma->vm_ops->populate &&
--                      end > start && start >= vma->vm_start &&
--                              end <= vma->vm_end) {
-+      if (!vma || !(vma->vm_flags & VM_SHARED))
-+              goto out;
-+
-+      if (vma->vm_private_data && !(vma->vm_flags & VM_NONLINEAR))
-+              goto out;
-+
-+      if ((!vma->vm_ops || !vma->vm_ops->populate) &&
-+                                      !(vma->vm_flags & VM_CAN_NONLINEAR))
-+              goto out;
-+
-+      if (end <= start || start < vma->vm_start || end > vma->vm_end)
-+              goto out;
-               /* Must set VM_NONLINEAR before any pages are populated. */
--              if (pgoff != linear_page_index(vma, start) &&
--                  !(vma->vm_flags & VM_NONLINEAR)) {
-+      if (!(vma->vm_flags & VM_NONLINEAR)) {
-+              /* Don't need a nonlinear mapping, exit success */
-+              if (pgoff == linear_page_index(vma, start)) {
-+                      err = 0;
-+                      goto out;
-+              }
-+
-                       if (!has_write_lock) {
-                               up_read(&mm->mmap_sem);
-                               down_write(&mm->mmap_sem);
-@@ -211,8 +242,17 @@
-                       spin_unlock(&mapping->i_mmap_lock);
-               }
+       struct iscsi_hdr        *hdr;
+       char                    *data;          /* mgmt payload */
+-      unsigned                data_count;     /* counts data to be sent */
++      int                     data_count;     /* counts data to be sent */
+       uint32_t                itt;            /* this ITT */
+       void                    *dd_data;       /* driver/transport data */
+       struct list_head        running;
+@@ -91,7 +90,6 @@
+       ISCSI_TASK_COMPLETED,
+       ISCSI_TASK_PENDING,
+       ISCSI_TASK_RUNNING,
+-      ISCSI_TASK_ABORTING,
+ };
  
--              err = vma->vm_ops->populate(vma, start, size,
--                                          vma->vm_page_prot,
-+      if (vma->vm_flags & VM_CAN_NONLINEAR) {
-+              err = populate_range(mm, vma, start, size, pgoff);
-+              if (!err && !(flags & MAP_NONBLOCK)) {
-+                      if (unlikely(has_write_lock)) {
-+                              downgrade_write(&mm->mmap_sem);
-+                              has_write_lock = 0;
-+                      }
-+                      make_pages_present(start, start+size);
-+              }
-+      } else
-+              err = vma->vm_ops->populate(vma, start, size, vma->vm_page_prot,
-                                           pgoff, flags & MAP_NONBLOCK);
+ struct iscsi_cmd_task {
+@@ -101,14 +99,16 @@
+        */
+       struct iscsi_cmd        *hdr;
+       int                     itt;            /* this ITT */
++      int                     datasn;         /* DataSN */
  
-               /*
-@@ -220,7 +260,8 @@
-                * it after ->populate completes, and that would prevent
-                * downgrading the lock.  (Locks can't be upgraded).
-                */
--      }
-+
-+out:
-       if (likely(!has_write_lock))
-               up_read(&mm->mmap_sem);
-       else
-diff -Nurb linux-2.6.22-570/mm/hugetlb.c linux-2.6.22-590/mm/hugetlb.c
---- linux-2.6.22-570/mm/hugetlb.c      2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/mm/hugetlb.c      2008-01-02 13:56:38.000000000 -0500
-@@ -28,6 +28,9 @@
- static struct list_head hugepage_freelists[MAX_NUMNODES];
- static unsigned int nr_huge_pages_node[MAX_NUMNODES];
- static unsigned int free_huge_pages_node[MAX_NUMNODES];
-+gfp_t htlb_alloc_mask = GFP_HIGHUSER;
-+unsigned long hugepages_treat_as_movable;
-+
- /*
-  * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages
-  */
-@@ -67,14 +70,15 @@
- static struct page *dequeue_huge_page(struct vm_area_struct *vma,
-                               unsigned long address)
- {
--      int nid = numa_node_id();
-+      int nid;
-       struct page *page = NULL;
--      struct zonelist *zonelist = huge_zonelist(vma, address);
-+      struct zonelist *zonelist = huge_zonelist(vma, address,
-+                                              htlb_alloc_mask);
-       struct zone **z;
+       uint32_t                unsol_datasn;
+-      unsigned                imm_count;      /* imm-data (bytes)   */
+-      unsigned                unsol_count;    /* unsolicited (bytes)*/
++      int                     imm_count;      /* imm-data (bytes)   */
++      int                     unsol_count;    /* unsolicited (bytes)*/
+       /* offset in unsolicited stream (bytes); */
+-      unsigned                unsol_offset;
+-      unsigned                data_count;     /* remaining Data-Out */
++      int                     unsol_offset;
++      int                     data_count;     /* remaining Data-Out */
+       struct scsi_cmnd        *sc;            /* associated SCSI cmd*/
++      int                     total_length;
+       struct iscsi_conn       *conn;          /* used connection    */
+       struct iscsi_mgmt_task  *mtask;         /* tmf mtask in progr */
  
-       for (z = zonelist->zones; *z; z++) {
-               nid = zone_to_nid(*z);
--              if (cpuset_zone_allowed_softwall(*z, GFP_HIGHUSER) &&
-+              if (cpuset_zone_allowed_softwall(*z, htlb_alloc_mask) &&
-                   !list_empty(&hugepage_freelists[nid]))
-                       break;
-       }
-@@ -114,7 +118,7 @@
-       prev_nid = nid;
-       spin_unlock(&nid_lock);
+@@ -152,11 +152,18 @@
+       struct iscsi_cmd_task   *ctask;         /* xmit ctask in progress */
  
--      page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP|__GFP_NOWARN,
-+      page = alloc_pages_node(nid, htlb_alloc_mask|__GFP_COMP|__GFP_NOWARN,
-                                       HUGETLB_PAGE_ORDER);
-       if (page) {
-               set_compound_page_dtor(page, free_huge_page);
-@@ -264,6 +268,19 @@
-       max_huge_pages = set_max_huge_pages(max_huge_pages);
-       return 0;
- }
-+
-+int hugetlb_treat_movable_handler(struct ctl_table *table, int write,
-+                      struct file *file, void __user *buffer,
-+                      size_t *length, loff_t *ppos)
-+{
-+      proc_dointvec(table, write, file, buffer, length, ppos);
-+      if (hugepages_treat_as_movable)
-+              htlb_alloc_mask = GFP_HIGH_MOVABLE;
-+      else
-+              htlb_alloc_mask = GFP_HIGHUSER;
-+      return 0;
-+}
+       /* xmit */
++      struct kfifo            *immqueue;      /* immediate xmit queue */
+       struct kfifo            *mgmtqueue;     /* mgmt (control) xmit queue */
+       struct list_head        mgmt_run_list;  /* list of control tasks */
+       struct list_head        xmitqueue;      /* data-path cmd queue */
+       struct list_head        run_list;       /* list of cmds in progress */
+       struct work_struct      xmitwork;       /* per-conn. xmit workqueue */
++      /*
++       * serializes connection xmit, access to kfifos:
++       * xmitqueue, immqueue, mgmtqueue
++       */
++      struct mutex            xmitmutex;
 +
- #endif /* CONFIG_SYSCTL */
+       unsigned long           suspend_tx;     /* suspend Tx */
+       unsigned long           suspend_rx;     /* suspend Rx */
  
- int hugetlb_report_meminfo(char *buf)
-diff -Nurb linux-2.6.22-570/mm/memory.c linux-2.6.22-590/mm/memory.c
---- linux-2.6.22-570/mm/memory.c       2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/mm/memory.c       2008-01-02 13:56:38.000000000 -0500
-@@ -1052,7 +1052,8 @@
-               if (pages)
-                       foll_flags |= FOLL_GET;
-               if (!write && !(vma->vm_flags & VM_LOCKED) &&
--                  (!vma->vm_ops || !vma->vm_ops->nopage))
-+                  (!vma->vm_ops || (!vma->vm_ops->nopage &&
-+                                      !vma->vm_ops->fault)))
-                       foll_flags |= FOLL_ANON;
+@@ -167,8 +174,8 @@
+       int                     tmabort_state;  /* see TMABORT_INITIAL, etc.*/
  
-               do {
-@@ -1712,11 +1713,11 @@
-       if (unlikely(anon_vma_prepare(vma)))
-               goto oom;
-       if (old_page == ZERO_PAGE(address)) {
--              new_page = alloc_zeroed_user_highpage(vma, address);
-+              new_page = alloc_zeroed_user_highpage_movable(vma, address);
-               if (!new_page)
-                       goto oom;
-       } else {
--              new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
-+              new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
-               if (!new_page)
-                       goto oom;
-               cow_user_page(new_page, old_page, address, vma);
-@@ -1828,6 +1829,13 @@
-       unsigned long restart_addr;
-       int need_break;
+       /* negotiated params */
+-      unsigned                max_recv_dlength; /* initiator_max_recv_dsl*/
+-      unsigned                max_xmit_dlength; /* target_max_recv_dsl */
++      int                     max_recv_dlength; /* initiator_max_recv_dsl*/
++      int                     max_xmit_dlength; /* target_max_recv_dsl */
+       int                     hdrdgst_en;
+       int                     datadgst_en;
+       int                     ifmarker_en;
+@@ -176,12 +183,6 @@
+       /* values userspace uses to id a conn */
+       int                     persistent_port;
+       char                    *persistent_address;
+-      /* remote portal currently connected to */
+-      int                     portal_port;
+-      char                    portal_address[ISCSI_ADDRESS_BUF_LEN];
+-      /* local address */
+-      int                     local_port;
+-      char                    local_address[ISCSI_ADDRESS_BUF_LEN];
  
-+      /*
-+       * files that support invalidating or truncating portions of the
-+       * file from under mmaped areas must set the VM_CAN_INVALIDATE flag, and
-+       * have their .nopage function return the page locked.
-+       */
-+      BUG_ON(!(vma->vm_flags & VM_CAN_INVALIDATE));
+       /* MIB-statistics */
+       uint64_t                txdata_octets;
+@@ -212,25 +213,18 @@
+       /* configuration */
+       int                     initial_r2t_en;
+-      unsigned                max_r2t;
++      int                     max_r2t;
+       int                     imm_data_en;
+-      unsigned                first_burst;
+-      unsigned                max_burst;
++      int                     first_burst;
++      int                     max_burst;
+       int                     time2wait;
+       int                     time2retain;
+       int                     pdu_inorder_en;
+       int                     dataseq_inorder_en;
+       int                     erl;
+       int                     tpgt;
+-      char                    *username;
+-      char                    *username_in;
+-      char                    *password;
+-      char                    *password_in;
+       char                    *targetname;
+-      char                    *initiatorname;
+-      /* hw address or netdev iscsi connection is bound to */
+-      char                    *hwaddress;
+-      char                    *netdev;
 +
- again:
-       restart_addr = vma->vm_truncate_count;
-       if (is_restart_addr(restart_addr) && start_addr < restart_addr) {
-@@ -1956,17 +1964,8 @@
+       /* control data */
+       struct iscsi_transport  *tt;
+       struct Scsi_Host        *host;
+@@ -261,22 +255,12 @@
+ extern int iscsi_queuecommand(struct scsi_cmnd *sc,
+                             void (*done)(struct scsi_cmnd *));
  
-       spin_lock(&mapping->i_mmap_lock);
+-
+-/*
+- * iSCSI host helpers.
+- */
+-extern int iscsi_host_set_param(struct Scsi_Host *shost,
+-                              enum iscsi_host_param param, char *buf,
+-                              int buflen);
+-extern int iscsi_host_get_param(struct Scsi_Host *shost,
+-                              enum iscsi_host_param param, char *buf);
+-
+ /*
+  * session management
+  */
+ extern struct iscsi_cls_session *
+ iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *,
+-                  uint16_t, uint16_t, int, int, uint32_t, uint32_t *);
++                  int, int, uint32_t, uint32_t *);
+ extern void iscsi_session_teardown(struct iscsi_cls_session *);
+ extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *);
+ extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
+@@ -305,7 +289,8 @@
+ /*
+  * pdu and task processing
+  */
+-extern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *);
++extern int iscsi_check_assign_cmdsn(struct iscsi_session *,
++                                  struct iscsi_nopin *);
+ extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *,
+                                       struct iscsi_data *hdr);
+ extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
+diff -Nurb linux-2.6.22-590/include/scsi/scsi_cmnd.h linux-2.6.22-570/include/scsi/scsi_cmnd.h
+--- linux-2.6.22-590/include/scsi/scsi_cmnd.h  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/scsi/scsi_cmnd.h  2007-07-08 19:32:17.000000000 -0400
+@@ -135,24 +135,4 @@
+ extern struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *, gfp_t);
+ extern void scsi_free_sgtable(struct scatterlist *, int);
  
--      /* serialize i_size write against truncate_count write */
--      smp_wmb();
--      /* Protect against page faults, and endless unmapping loops */
-+      /* Protect against endless unmapping loops */
-       mapping->truncate_count++;
--      /*
--       * For archs where spin_lock has inclusive semantics like ia64
--       * this smp_mb() will prevent to read pagetable contents
--       * before the truncate_count increment is visible to
--       * other cpus.
--       */
--      smp_mb();
-       if (unlikely(is_restart_addr(mapping->truncate_count))) {
-               if (mapping->truncate_count == 0)
-                       reset_vma_truncate_counts(mapping);
-@@ -2005,8 +2004,18 @@
-       if (IS_SWAPFILE(inode))
-               goto out_busy;
-       i_size_write(inode, offset);
+-extern int scsi_dma_map(struct scsi_cmnd *cmd);
+-extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
+-
+-#define scsi_sg_count(cmd) ((cmd)->use_sg)
+-#define scsi_sglist(cmd) ((struct scatterlist *)(cmd)->request_buffer)
+-#define scsi_bufflen(cmd) ((cmd)->request_bufflen)
+-
+-static inline void scsi_set_resid(struct scsi_cmnd *cmd, int resid)
+-{
+-      cmd->resid = resid;
+-}
+-
+-static inline int scsi_get_resid(struct scsi_cmnd *cmd)
+-{
+-      return cmd->resid;
+-}
+-
+-#define scsi_for_each_sg(cmd, sg, nseg, __i)                  \
+-      for (__i = 0, sg = scsi_sglist(cmd); __i < (nseg); __i++, (sg)++)
+-
+ #endif /* _SCSI_SCSI_CMND_H */
+diff -Nurb linux-2.6.22-590/include/scsi/scsi_device.h linux-2.6.22-570/include/scsi/scsi_device.h
+--- linux-2.6.22-590/include/scsi/scsi_device.h        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/scsi/scsi_device.h        2007-07-08 19:32:17.000000000 -0400
+@@ -287,7 +287,6 @@
+ extern void scsi_target_unblock(struct device *);
+ extern void scsi_remove_target(struct device *);
+ extern void int_to_scsilun(unsigned int, struct scsi_lun *);
+-extern int scsilun_to_int(struct scsi_lun *);
+ extern const char *scsi_device_state_name(enum scsi_device_state);
+ extern int scsi_is_sdev_device(const struct device *);
+ extern int scsi_is_target_device(const struct device *);
+diff -Nurb linux-2.6.22-590/include/scsi/scsi_host.h linux-2.6.22-570/include/scsi/scsi_host.h
+--- linux-2.6.22-590/include/scsi/scsi_host.h  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/scsi/scsi_host.h  2007-07-08 19:32:17.000000000 -0400
+@@ -339,6 +339,12 @@
+       enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
+       /*
++       * suspend support
++       */
++      int (*resume)(struct scsi_device *);
++      int (*suspend)(struct scsi_device *, pm_message_t state);
 +
 +      /*
-+       * unmap_mapping_range is called twice, first simply for efficiency
-+       * so that truncate_inode_pages does fewer single-page unmaps. However
-+       * after this first call, and before truncate_inode_pages finishes,
-+       * it is possible for private pages to be COWed, which remain after
-+       * truncate_inode_pages finishes, hence the second unmap_mapping_range
-+       * call must be made for correctness.
-+       */
-       unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
-       truncate_inode_pages(mapping, offset);
-+      unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
-       goto out_truncate;
+        * Name of proc directory
+        */
+       char *proc_name;
+@@ -671,10 +677,6 @@
+ #define shost_printk(prefix, shost, fmt, a...)        \
+       dev_printk(prefix, &(shost)->shost_gendev, fmt, ##a)
  
- do_expand:
-@@ -2046,6 +2055,7 @@
-       down_write(&inode->i_alloc_sem);
-       unmap_mapping_range(mapping, offset, (end - offset), 1);
-       truncate_inode_pages_range(mapping, offset, end);
-+      unmap_mapping_range(mapping, offset, (end - offset), 1);
-       inode->i_op->truncate_range(inode, offset, end);
-       up_write(&inode->i_alloc_sem);
-       mutex_unlock(&inode->i_mutex);
-@@ -2208,7 +2218,6 @@
+-static inline void *shost_priv(struct Scsi_Host *shost)
+-{
+-      return (void *)shost->hostdata;
+-}
  
-       /* No need to invalidate - it was non-present before */
-       update_mmu_cache(vma, address, pte);
--      lazy_mmu_prot_update(pte);
- unlock:
-       pte_unmap_unlock(page_table, ptl);
- out:
-@@ -2241,7 +2250,7 @@
-                       goto oom;
-               if (unlikely(anon_vma_prepare(vma)))
-                       goto oom;
--              page = alloc_zeroed_user_highpage(vma, address);
-+              page = alloc_zeroed_user_highpage_movable(vma, address);
-               if (!page)
-                       goto oom;
+ int scsi_is_host_device(const struct device *);
  
-@@ -2284,10 +2293,10 @@
- }
+diff -Nurb linux-2.6.22-590/include/scsi/scsi_transport_fc.h linux-2.6.22-570/include/scsi/scsi_transport_fc.h
+--- linux-2.6.22-590/include/scsi/scsi_transport_fc.h  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/scsi/scsi_transport_fc.h  2007-07-08 19:32:17.000000000 -0400
+@@ -19,7 +19,7 @@
+  *
+  *  ========
+  *
+- *  Copyright (C) 2004-2007   James Smart, Emulex Corporation
++ *  Copyright (C) 2004-2005   James Smart, Emulex Corporation
+  *    Rewrite for host, target, device, and remote port attributes,
+  *    statistics, and service functions...
+  *
+@@ -62,10 +62,8 @@
+       FC_PORTTYPE_NLPORT,             /* (Public) Loop w/ FLPort */
+       FC_PORTTYPE_LPORT,              /* (Private) Loop w/o FLPort */
+       FC_PORTTYPE_PTP,                /* Point to Point w/ another NPort */
+-      FC_PORTTYPE_NPIV,               /* VPORT based on NPIV */
+ };
  
+-
  /*
-- * do_no_page() tries to create a new page mapping. It aggressively
-+ * __do_fault() tries to create a new page mapping. It aggressively
-  * tries to share with existing pages, but makes a separate copy if
-- * the "write_access" parameter is true in order to avoid the next
-- * page fault.
-+ * the FAULT_FLAG_WRITE is set in the flags parameter in order to avoid
-+ * the next page fault.
-  *
-  * As this is called only for pages that do not currently exist, we
-  * do not need to flush old virtual caches or the TLB.
-@@ -2296,92 +2305,85 @@
-  * but allow concurrent faults), and pte mapped but not yet locked.
-  * We return with mmap_sem still held, but pte unmapped and unlocked.
-  */
--static int do_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
-+static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
-               unsigned long address, pte_t *page_table, pmd_t *pmd,
--              int write_access)
--{
-+              pgoff_t pgoff, unsigned int flags, pte_t orig_pte)
-+  {
-       spinlock_t *ptl;
--      struct page *new_page;
--      struct address_space *mapping = NULL;
-+      struct page *page, *faulted_page;
-       pte_t entry;
--      unsigned int sequence = 0;
--      int ret = VM_FAULT_MINOR;
-       int anon = 0;
-       struct page *dirty_page = NULL;
-+      struct fault_data fdata;
-+ 
-+      fdata.address = address & PAGE_MASK;
-+      fdata.pgoff = pgoff;
-+      fdata.flags = flags;
+  * fc_port_state: If you alter this, you also need to alter scsi_transport_fc.c
+  * (for the ascii descriptions).
+@@ -86,25 +84,6 @@
  
-       pte_unmap(page_table);
-       BUG_ON(vma->vm_flags & VM_PFNMAP);
  
--      if (!vx_rss_avail(mm, 1))
-+      if (likely(vma->vm_ops->fault)) {
-+              fdata.type = -1;
-+              faulted_page = vma->vm_ops->fault(vma, &fdata);
-+              WARN_ON(fdata.type == -1);
-+              if (unlikely(!faulted_page))
-+                      return fdata.type;
-+      } else {
-+              /* Legacy ->nopage path */
-+              fdata.type = VM_FAULT_MINOR;
-+              faulted_page = vma->vm_ops->nopage(vma, address & PAGE_MASK,
-+                                                              &fdata.type);
-+              /* no page was available -- either SIGBUS or OOM */
-+              if (unlikely(faulted_page == NOPAGE_SIGBUS))
-+                      return VM_FAULT_SIGBUS;
-+              else if (unlikely(faulted_page == NOPAGE_OOM))
-               return VM_FAULT_OOM;
-+      }
+ /* 
+- * fc_vport_state: If you alter this, you also need to alter
+- * scsi_transport_fc.c (for the ascii descriptions).
+- */
+-enum fc_vport_state {
+-      FC_VPORT_UNKNOWN,
+-      FC_VPORT_ACTIVE,
+-      FC_VPORT_DISABLED,
+-      FC_VPORT_LINKDOWN,
+-      FC_VPORT_INITIALIZING,
+-      FC_VPORT_NO_FABRIC_SUPP,
+-      FC_VPORT_NO_FABRIC_RSCS,
+-      FC_VPORT_FABRIC_LOGOUT,
+-      FC_VPORT_FABRIC_REJ_WWN,
+-      FC_VPORT_FAILED,
+-};
+-
+-
+-
+-/*
+  * FC Classes of Service
+  * Note: values are not enumerated, as they can be "or'd" together
+  * for reporting (e.g. report supported_classes). If you alter this list,
+@@ -145,116 +124,18 @@
+ };
  
--      if (vma->vm_file) {
--              mapping = vma->vm_file->f_mapping;
--              sequence = mapping->truncate_count;
--              smp_rmb(); /* serializes i_size against truncate_count */
--      }
--retry:
--      new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, &ret);
--      /*
--       * No smp_rmb is needed here as long as there's a full
--       * spin_lock/unlock sequence inside the ->nopage callback
--       * (for the pagecache lookup) that acts as an implicit
--       * smp_mb() and prevents the i_size read to happen
--       * after the next truncate_count read.
-+      /*
-+       * For consistency in subsequent calls, make the faulted_page always
-+       * locked.
-        */
+ /*
+- * FC Port Roles
++ * FC Remote Port Roles
+  * Note: values are not enumerated, as they can be "or'd" together
+  * for reporting (e.g. report roles). If you alter this list,
+  * you also need to alter scsi_transport_fc.c (for the ascii descriptions).
+  */
+-#define FC_PORT_ROLE_UNKNOWN                  0x00
+-#define FC_PORT_ROLE_FCP_TARGET                       0x01
+-#define FC_PORT_ROLE_FCP_INITIATOR            0x02
+-#define FC_PORT_ROLE_IP_PORT                  0x04
+-
+-/* The following are for compatibility */
+-#define FC_RPORT_ROLE_UNKNOWN                 FC_PORT_ROLE_UNKNOWN
+-#define FC_RPORT_ROLE_FCP_TARGET              FC_PORT_ROLE_FCP_TARGET
+-#define FC_RPORT_ROLE_FCP_INITIATOR           FC_PORT_ROLE_FCP_INITIATOR
+-#define FC_RPORT_ROLE_IP_PORT                 FC_PORT_ROLE_IP_PORT
 -
--      /* no page was available -- either SIGBUS, OOM or REFAULT */
--      if (unlikely(new_page == NOPAGE_SIGBUS))
--              return VM_FAULT_SIGBUS;
--      else if (unlikely(new_page == NOPAGE_OOM))
--              return VM_FAULT_OOM;
--      else if (unlikely(new_page == NOPAGE_REFAULT))
--              return VM_FAULT_MINOR;
-+      if (unlikely(!(vma->vm_flags & VM_CAN_INVALIDATE)))
-+              lock_page(faulted_page);
-+      else
-+              BUG_ON(!PageLocked(faulted_page));
+-
+-/* Macro for use in defining Virtual Port attributes */
+-#define FC_VPORT_ATTR(_name,_mode,_show,_store)                               \
+-struct class_device_attribute class_device_attr_vport_##_name =       \
+-      __ATTR(_name,_mode,_show,_store)
++#define FC_RPORT_ROLE_UNKNOWN                 0x00
++#define FC_RPORT_ROLE_FCP_TARGET              0x01
++#define FC_RPORT_ROLE_FCP_INITIATOR           0x02
++#define FC_RPORT_ROLE_IP_PORT                 0x04
  
-       /*
-        * Should we do an early C-O-W break?
-        */
--      if (write_access) {
-+      page = faulted_page;
-+      if (flags & FAULT_FLAG_WRITE) {
-               if (!(vma->vm_flags & VM_SHARED)) {
--                      struct page *page;
--
--                      if (unlikely(anon_vma_prepare(vma)))
--                              goto oom;
--                      page = alloc_page_vma(GFP_HIGHUSER, vma, address);
--                      if (!page)
--                              goto oom;
--                      copy_user_highpage(page, new_page, address, vma);
--                      page_cache_release(new_page);
--                      new_page = page;
-                       anon = 1;
--
-+                      if (unlikely(anon_vma_prepare(vma))) {
-+                              fdata.type = VM_FAULT_OOM;
-+                              goto out;
-+                      }
-+                      page = alloc_page_vma(GFP_HIGHUSER, vma, address);
-+                      if (!page) {
-+                              fdata.type = VM_FAULT_OOM;
-+                              goto out;
-+                      }
-+                      copy_user_highpage(page, faulted_page, address, vma);
-               } else {
--                      /* if the page will be shareable, see if the backing
-+                      /*
-+                       * If the page will be shareable, see if the backing
-                        * address space wants to know that the page is about
--                       * to become writable */
-+                       * to become writable
-+                       */
-                       if (vma->vm_ops->page_mkwrite &&
--                          vma->vm_ops->page_mkwrite(vma, new_page) < 0
--                          ) {
--                              page_cache_release(new_page);
--                              return VM_FAULT_SIGBUS;
-+                          vma->vm_ops->page_mkwrite(vma, page) < 0) {
-+                              fdata.type = VM_FAULT_SIGBUS;
-+                              anon = 1; /* no anon but release faulted_page */
-+                              goto out;
-                       }
-               }
-+ 
-       }
  
-       page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
--      /*
--       * For a file-backed vma, someone could have truncated or otherwise
--       * invalidated this page.  If unmap_mapping_range got called,
--       * retry getting the page.
--       */
--      if (mapping && unlikely(sequence != mapping->truncate_count)) {
--              pte_unmap_unlock(page_table, ptl);
--              page_cache_release(new_page);
--              cond_resched();
--              sequence = mapping->truncate_count;
--              smp_rmb();
--              goto retry;
--      }
+ /*
+- * FC Virtual Port Attributes
+- *
+- * This structure exists for each FC port is a virtual FC port. Virtual
+- * ports share the physical link with the Physical port. Each virtual
+- * ports has a unique presense on the SAN, and may be instantiated via
+- * NPIV, Virtual Fabrics, or via additional ALPAs. As the vport is a
+- * unique presense, each vport has it's own view of the fabric,
+- * authentication priviledge, and priorities.
+- *
+- * A virtual port may support 1 or more FC4 roles. Typically it is a
+- * FCP Initiator. It could be a FCP Target, or exist sole for an IP over FC
+- * roles. FC port attributes for the vport will be reported on any
+- * fc_host class object allocated for an FCP Initiator.
+- *
+- * --
+- *
+- * Fixed attributes are not expected to change. The driver is
+- * expected to set these values after receiving the fc_vport structure
+- * via the vport_create() call from the transport.
+- * The transport fully manages all get functions w/o driver interaction.
+- *
+- * Dynamic attributes are expected to change. The driver participates
+- * in all get/set operations via functions provided by the driver.
+- *
+- * Private attributes are transport-managed values. They are fully
+- * managed by the transport w/o driver interaction.
+- */
+-
+-#define FC_VPORT_SYMBOLIC_NAMELEN             64
+-struct fc_vport {
+-      /* Fixed Attributes */
+-
+-      /* Dynamic Attributes */
+-
+-      /* Private (Transport-managed) Attributes */
+-      enum fc_vport_state vport_state;
+-      enum fc_vport_state vport_last_state;
+-      u64 node_name;
+-      u64 port_name;
+-      u32 roles;
+-      u32 vport_id;           /* Admin Identifier for the vport */
+-      enum fc_port_type vport_type;
+-      char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
+-
+-      /* exported data */
+-      void *dd_data;                  /* Used for driver-specific storage */
+-
+-      /* internal data */
+-      struct Scsi_Host *shost;        /* Physical Port Parent */
+-      unsigned int channel;
+-      u32 number;
+-      u8 flags;
+-      struct list_head peers;
+-      struct device dev;
+-      struct work_struct vport_delete_work;
+-} __attribute__((aligned(sizeof(unsigned long))));
+-
+-/* bit field values for struct fc_vport "flags" field: */
+-#define FC_VPORT_CREATING             0x01
+-#define FC_VPORT_DELETING             0x02
+-#define FC_VPORT_DELETED              0x04
+-#define FC_VPORT_DEL                  0x06    /* Any DELETE state */
+-
+-#define       dev_to_vport(d)                         \
+-      container_of(d, struct fc_vport, dev)
+-#define transport_class_to_vport(classdev)    \
+-      dev_to_vport(classdev->dev)
+-#define vport_to_shost(v)                     \
+-      (v->shost)
+-#define vport_to_shost_channel(v)             \
+-      (v->channel)
+-#define vport_to_parent(v)                    \
+-      (v->dev.parent)
+-
+-
+-/* Error return codes for vport_create() callback */
+-#define VPCERR_UNSUPPORTED            -ENOSYS         /* no driver/adapter
+-                                                         support */
+-#define VPCERR_BAD_WWN                        -ENOTUNIQ       /* driver validation
+-                                                         of WWNs failed */
+-#define VPCERR_NO_FABRIC_SUPP         -EOPNOTSUPP     /* Fabric connection
+-                                                         is loop or the
+-                                                         Fabric Port does
+-                                                         not support NPIV */
+-
+-/*
+  * fc_rport_identifiers: This set of data contains all elements
+  * to uniquely identify a remote FC port. The driver uses this data
+  * to report the existence of a remote FC port in the topology. Internally,
+@@ -268,7 +149,6 @@
+       u32 roles;
+ };
  
-       /*
-        * This silly early PAGE_DIRTY setting removes a race
-@@ -2394,43 +2396,68 @@
-        * handle that later.
-        */
-       /* Only go through if we didn't race with anybody else... */
--      if (pte_none(*page_table)) {
--              flush_icache_page(vma, new_page);
--              entry = mk_pte(new_page, vma->vm_page_prot);
--              if (write_access)
-+      if (likely(pte_same(*page_table, orig_pte))) {
-+              flush_icache_page(vma, page);
-+              entry = mk_pte(page, vma->vm_page_prot);
-+              if (flags & FAULT_FLAG_WRITE)
-                       entry = maybe_mkwrite(pte_mkdirty(entry), vma);
-               set_pte_at(mm, address, page_table, entry);
-               if (anon) {
-                       inc_mm_counter(mm, anon_rss);
--                      lru_cache_add_active(new_page);
--                      page_add_new_anon_rmap(new_page, vma, address);
-+                        lru_cache_add_active(page);
-+                        page_add_new_anon_rmap(page, vma, address);
-               } else {
-                       inc_mm_counter(mm, file_rss);
--                      page_add_file_rmap(new_page);
--                      if (write_access) {
--                              dirty_page = new_page;
-+                      page_add_file_rmap(page);
-+                      if (flags & FAULT_FLAG_WRITE) {
-+                              dirty_page = page;
-                               get_page(dirty_page);
-                       }
-               }
--      } else {
--              /* One of our sibling threads was faster, back out. */
--              page_cache_release(new_page);
--              goto unlock;
--      }
+-
+ /* Macro for use in defining Remote Port attributes */
+ #define FC_RPORT_ATTR(_name,_mode,_show,_store)                               \
+ struct class_device_attribute class_device_attr_rport_##_name =       \
+@@ -463,7 +343,6 @@
+       u8  supported_fc4s[FC_FC4_LIST_SIZE];
+       u32 supported_speeds;
+       u32 maxframe_size;
+-      u16 max_npiv_vports;
+       char serial_number[FC_SERIAL_NUMBER_SIZE];
  
--      /* no need to invalidate: a not-present page shouldn't be cached */
-+              /* no need to invalidate: a not-present page won't be cached */
-       update_mmu_cache(vma, address, entry);
-       lazy_mmu_prot_update(entry);
--unlock:
-+      } else {
-+              if (anon)
-+                      page_cache_release(page);
-+              else
-+                      anon = 1; /* no anon but release faulted_page */
-+      }
-+
-       pte_unmap_unlock(page_table, ptl);
--      if (dirty_page) {
-+
-+out:
-+      unlock_page(faulted_page);
-+      if (anon)
-+              page_cache_release(faulted_page);
-+      else if (dirty_page) {
-               set_page_dirty_balance(dirty_page);
-               put_page(dirty_page);
-       }
--      return ret;
--oom:
--      page_cache_release(new_page);
--      return VM_FAULT_OOM;
-+
-+      return fdata.type;
-+}
-+
-+static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
-+              unsigned long address, pte_t *page_table, pmd_t *pmd,
-+              int write_access, pte_t orig_pte)
-+{
-+      pgoff_t pgoff = (((address & PAGE_MASK)
-+                      - vma->vm_start) >> PAGE_CACHE_SHIFT) + vma->vm_pgoff;
-+      unsigned int flags = (write_access ? FAULT_FLAG_WRITE : 0);
-+
-+      return __do_fault(mm, vma, address, page_table, pmd, pgoff, flags, orig_pte);
-+}
-+
-+static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
-+              unsigned long address, pte_t *page_table, pmd_t *pmd,
-+              int write_access, pgoff_t pgoff, pte_t orig_pte)
-+{
-+      unsigned int flags = FAULT_FLAG_NONLINEAR |
-+                              (write_access ? FAULT_FLAG_WRITE : 0);
-+
-+      return __do_fault(mm, vma, address, page_table, pmd, pgoff, flags, orig_pte);
- }
+       /* Dynamic Attributes */
+@@ -482,11 +361,8 @@
+       /* internal data */
+       struct list_head rports;
+       struct list_head rport_bindings;
+-      struct list_head vports;
+       u32 next_rport_number;
+       u32 next_target_id;
+-      u32 next_vport_number;
+-      u16 npiv_vports_inuse;
  
- /*
-@@ -2509,9 +2536,14 @@
-               print_bad_pte(vma, orig_pte, address);
-               return VM_FAULT_OOM;
-       }
--      /* We can then assume vm->vm_ops && vma->vm_ops->populate */
+       /* work queues for rport state manipulation */
+       char work_q_name[KOBJ_NAME_LEN];
+@@ -512,8 +388,6 @@
+       (((struct fc_host_attrs *)(x)->shost_data)->supported_speeds)
+ #define fc_host_maxframe_size(x)      \
+       (((struct fc_host_attrs *)(x)->shost_data)->maxframe_size)
+-#define fc_host_max_npiv_vports(x)    \
+-      (((struct fc_host_attrs *)(x)->shost_data)->max_npiv_vports)
+ #define fc_host_serial_number(x)      \
+       (((struct fc_host_attrs *)(x)->shost_data)->serial_number)
+ #define fc_host_port_id(x)    \
+@@ -538,16 +412,10 @@
+       (((struct fc_host_attrs *)(x)->shost_data)->rports)
+ #define fc_host_rport_bindings(x) \
+       (((struct fc_host_attrs *)(x)->shost_data)->rport_bindings)
+-#define fc_host_vports(x) \
+-      (((struct fc_host_attrs *)(x)->shost_data)->vports)
+ #define fc_host_next_rport_number(x) \
+       (((struct fc_host_attrs *)(x)->shost_data)->next_rport_number)
+ #define fc_host_next_target_id(x) \
+       (((struct fc_host_attrs *)(x)->shost_data)->next_target_id)
+-#define fc_host_next_vport_number(x) \
+-      (((struct fc_host_attrs *)(x)->shost_data)->next_vport_number)
+-#define fc_host_npiv_vports_inuse(x)  \
+-      (((struct fc_host_attrs *)(x)->shost_data)->npiv_vports_inuse)
+ #define fc_host_work_q_name(x) \
+       (((struct fc_host_attrs *)(x)->shost_data)->work_q_name)
+ #define fc_host_work_q(x) \
+@@ -584,14 +452,8 @@
+       void    (*dev_loss_tmo_callbk)(struct fc_rport *);
+       void    (*terminate_rport_io)(struct fc_rport *);
  
-       pgoff = pte_to_pgoff(orig_pte);
-+
-+      if (vma->vm_ops && vma->vm_ops->fault)
-+              return do_nonlinear_fault(mm, vma, address, page_table, pmd,
-+                                      write_access, pgoff, orig_pte);
-+
-+      /* We can then assume vm->vm_ops && vma->vm_ops->populate */
-       err = vma->vm_ops->populate(vma, address & PAGE_MASK, PAGE_SIZE,
-                                       vma->vm_page_prot, pgoff, 0);
-       if (err == -ENOMEM)
-@@ -2546,10 +2578,9 @@
-       if (!pte_present(entry)) {
-               if (pte_none(entry)) {
-                       if (vma->vm_ops) {
--                              if (vma->vm_ops->nopage)
--                                      return do_no_page(mm, vma, address,
--                                                        pte, pmd,
--                                                        write_access);
-+                              if (vma->vm_ops->fault || vma->vm_ops->nopage)
-+                                      return do_linear_fault(mm, vma, address,
-+                                              pte, pmd, write_access, entry);
-                               if (unlikely(vma->vm_ops->nopfn))
-                                       return do_no_pfn(mm, vma, address, pte,
-                                                        pmd, write_access);
-diff -Nurb linux-2.6.22-570/mm/mempolicy.c linux-2.6.22-590/mm/mempolicy.c
---- linux-2.6.22-570/mm/mempolicy.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/mm/mempolicy.c    2008-01-02 13:56:38.000000000 -0500
-@@ -594,7 +594,7 @@
+-      void    (*set_vport_symbolic_name)(struct fc_vport *);
+-      int     (*vport_create)(struct fc_vport *, bool);
+-      int     (*vport_disable)(struct fc_vport *, bool);
+-      int     (*vport_delete)(struct fc_vport *);
+-
+       /* allocation lengths for host-specific data */
+       u32                             dd_fcrport_size;
+-      u32                             dd_fcvport_size;
  
- static struct page *new_node_page(struct page *page, unsigned long node, int **x)
- {
--      return alloc_pages_node(node, GFP_HIGHUSER, 0);
-+      return alloc_pages_node(node, GFP_HIGHUSER_MOVABLE, 0);
+       /* 
+        * The driver sets these to tell the transport class it
+@@ -650,7 +512,7 @@
+       switch (rport->port_state) {
+       case FC_PORTSTATE_ONLINE:
+-              if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
++              if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+                       result = 0;
+               else if (rport->flags & FC_RPORT_DEVLOSS_PENDING)
+                       result = DID_IMM_RETRY << 16;
+@@ -687,27 +549,6 @@
+       wwn[7] = inm & 0xff;
  }
  
- /*
-@@ -710,7 +710,8 @@
- {
-       struct vm_area_struct *vma = (struct vm_area_struct *)private;
+-/**
+- * fc_vport_set_state() - called to set a vport's state. Saves the old state,
+- *   excepting the transitory states of initializing and sending the ELS
+- *   traffic to instantiate the vport on the link.
+- *
+- * Assumes the driver has surrounded this with the proper locking to ensure
+- * a coherent state change.
+- *
+- * @vport:    virtual port whose state is changing
+- * @new_state:  new state
+- **/
+-static inline void
+-fc_vport_set_state(struct fc_vport *vport, enum fc_vport_state new_state)
+-{
+-      if ((new_state != FC_VPORT_UNKNOWN) &&
+-          (new_state != FC_VPORT_INITIALIZING))
+-              vport->vport_last_state = vport->vport_state;
+-      vport->vport_state = new_state;
+-}
+-
+-
+ struct scsi_transport_template *fc_attach_transport(
+                       struct fc_function_template *);
+ void fc_release_transport(struct scsi_transport_template *);
+@@ -726,6 +567,5 @@
+        *   be sure to read the Vendor Type and ID formatting requirements
+        *   specified in scsi_netlink.h
+        */
+-int fc_vport_terminate(struct fc_vport *vport);
+ #endif /* SCSI_TRANSPORT_FC_H */
+diff -Nurb linux-2.6.22-590/include/scsi/scsi_transport_iscsi.h linux-2.6.22-570/include/scsi/scsi_transport_iscsi.h
+--- linux-2.6.22-590/include/scsi/scsi_transport_iscsi.h       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/include/scsi/scsi_transport_iscsi.h       2007-07-08 19:32:17.000000000 -0400
+@@ -79,8 +79,7 @@
+       char *name;
+       unsigned int caps;
+       /* LLD sets this to indicate what values it can export to sysfs */
+-      uint64_t param_mask;
+-      uint64_t host_param_mask;
++      unsigned int param_mask;
+       struct scsi_host_template *host_template;
+       /* LLD connection data size */
+       int conndata_size;
+@@ -90,8 +89,7 @@
+       unsigned int max_conn;
+       unsigned int max_cmd_len;
+       struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it,
+-              struct scsi_transport_template *t, uint16_t, uint16_t,
+-              uint32_t sn, uint32_t *hn);
++              struct scsi_transport_template *t, uint32_t sn, uint32_t *hn);
+       void (*destroy_session) (struct iscsi_cls_session *session);
+       struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
+                               uint32_t cid);
+@@ -107,18 +105,14 @@
+                              enum iscsi_param param, char *buf);
+       int (*get_session_param) (struct iscsi_cls_session *session,
+                                 enum iscsi_param param, char *buf);
+-      int (*get_host_param) (struct Scsi_Host *shost,
+-                              enum iscsi_host_param param, char *buf);
+-      int (*set_host_param) (struct Scsi_Host *shost,
+-                             enum iscsi_host_param param, char *buf,
+-                             int buflen);
+       int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
+                        char *data, uint32_t data_size);
+       void (*get_stats) (struct iscsi_cls_conn *conn,
+                          struct iscsi_stats *stats);
+       void (*init_cmd_task) (struct iscsi_cmd_task *ctask);
+       void (*init_mgmt_task) (struct iscsi_conn *conn,
+-                              struct iscsi_mgmt_task *mtask);
++                              struct iscsi_mgmt_task *mtask,
++                              char *data, uint32_t data_size);
+       int (*xmit_cmd_task) (struct iscsi_conn *conn,
+                             struct iscsi_cmd_task *ctask);
+       void (*cleanup_cmd_task) (struct iscsi_conn *conn,
+@@ -130,7 +124,7 @@
+                          uint64_t *ep_handle);
+       int (*ep_poll) (uint64_t ep_handle, int timeout_ms);
+       void (*ep_disconnect) (uint64_t ep_handle);
+-      int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
++      int (*tgt_dscvr) (enum iscsi_tgt_dscvr type, uint32_t host_no,
+                         uint32_t enable, struct sockaddr *dst_addr);
+ };
  
--      return alloc_page_vma(GFP_HIGHUSER, vma, page_address_in_vma(page, vma));
-+      return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma,
-+                                      page_address_in_vma(page, vma));
- }
- #else
+diff -Nurb linux-2.6.22-590/init/Kconfig linux-2.6.22-570/init/Kconfig
+--- linux-2.6.22-590/init/Kconfig      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/init/Kconfig      2008-01-23 19:16:13.000000000 -0500
+@@ -120,6 +120,15 @@
+         section 6.4 of the Linux Programmer's Guide, available from
+         <http://www.tldp.org/guides.html>.
  
-@@ -1202,7 +1203,8 @@
++config IPC_NS
++      bool "IPC Namespaces"
++      depends on SYSVIPC
++      default n
++      help
++        Support ipc namespaces.  This allows containers, i.e. virtual
++        environments, to use ipc namespaces to provide different ipc
++        objects for different servers.  If unsure, say N.
++
+ config SYSVIPC_SYSCTL
+       bool
+       depends on SYSVIPC
+@@ -209,14 +218,13 @@
  
- #ifdef CONFIG_HUGETLBFS
- /* Return a zonelist suitable for a huge page allocation. */
--struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr)
-+struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr,
-+                                                      gfp_t gfp_flags)
- {
-       struct mempolicy *pol = get_vma_policy(current, vma, addr);
+         Say N if unsure.
  
-@@ -1210,7 +1212,7 @@
-               unsigned nid;
+-config USER_NS
+-      bool "User Namespaces (EXPERIMENTAL)"
++config UTS_NS
++      bool "UTS Namespaces"
+       default n
+-      depends on EXPERIMENTAL
+       help
+-        Support user namespaces.  This allows containers, i.e.
+-        vservers, to use user namespaces to provide different
+-        user info for different servers.  If unsure, say N.
++        Support uts namespaces.  This allows containers, i.e.
++        vservers, to use uts namespaces to provide different
++        uts info for different servers.  If unsure, say N.
  
-               nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT);
--              return NODE_DATA(nid)->node_zonelists + gfp_zone(GFP_HIGHUSER);
-+              return NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_flags);
-       }
-       return zonelist_policy(GFP_HIGHUSER, pol);
- }
-@@ -1309,7 +1311,6 @@
-  * keeps mempolicies cpuset relative after its cpuset moves.  See
-  * further kernel/cpuset.c update_nodemask().
-  */
--void *cpuset_being_rebound;
+ config AUDIT
+       bool "Auditing support"
+@@ -290,23 +298,9 @@
+       depends on !OOM_PANIC
+       default y
  
- /* Slow path of a mempolicy copy */
- struct mempolicy *__mpol_copy(struct mempolicy *old)
-@@ -1908,4 +1909,3 @@
-               m->version = (vma != priv->tail_vma) ? vma->vm_start : 0;
-       return 0;
- }
+-config CONTAINERS
+-      bool
 -
-diff -Nurb linux-2.6.22-570/mm/migrate.c linux-2.6.22-590/mm/migrate.c
---- linux-2.6.22-570/mm/migrate.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/mm/migrate.c      2008-01-02 13:56:38.000000000 -0500
-@@ -761,7 +761,8 @@
-       *result = &pm->status;
+-config CONTAINER_DEBUG
+-      bool "Example debug container subsystem"
+-      select CONTAINERS
+-      help
+-        This option enables a simple container subsystem that
+-        exports useful debugging information about the containers
+-        framework
+-
+-        Say N if unsure
+-
+ config CPUSETS
+       bool "Cpuset support"
+       depends on SMP
+-      select CONTAINERS
+       help
+         This option will let you create and manage CPUSETs which
+         allow dynamically partitioning a system into sets of CPUs and
+@@ -335,27 +329,6 @@
+         If you are using a distro that was released in 2006 or later,
+         it should be safe to say N here.
  
--      return alloc_pages_node(pm->node, GFP_HIGHUSER | GFP_THISNODE, 0);
-+      return alloc_pages_node(pm->node,
-+                              GFP_HIGHUSER_MOVABLE | GFP_THISNODE, 0);
- }
+-config CONTAINER_CPUACCT
+-      bool "Simple CPU accounting container subsystem"
+-      select CONTAINERS
+-      help
+-        Provides a simple Resource Controller for monitoring the
+-        total CPU consumed by the tasks in a container
+-
+-config CONTAINER_NS
+-        bool "Namespace container subsystem"
+-        select CONTAINERS
+-        help
+-          Provides a simple namespace container subsystem to
+-          provide hierarchical naming of sets of namespaces,
+-          for instance virtual servers and checkpoint/restart
+-          jobs.
+-
+-config PROC_PID_CPUSET
+-      bool "Include legacy /proc/<pid>/cpuset file"
+-      depends on CPUSETS
+-      default y
+-
+ config RELAY
+       bool "Kernel->user space relay support (formerly relayfs)"
+       help
+@@ -632,33 +605,6 @@
  
- /*
-diff -Nurb linux-2.6.22-570/mm/mmap.c linux-2.6.22-590/mm/mmap.c
---- linux-2.6.22-570/mm/mmap.c 2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/mm/mmap.c 2008-01-02 13:56:38.000000000 -0500
-@@ -202,6 +202,17 @@
- }
+ endchoice
  
- /*
-+ * Requires inode->i_mapping->i_mmap_lock
-+ */
-+void __unlink_file_vma(struct vm_area_struct *vma)
-+{
-+      struct file *file = vma->vm_file;
-+      struct address_space *mapping = file->f_mapping;
-+
-+      __remove_shared_vm_struct(vma, file, mapping);
-+}
-+
-+/*
-  * Unlink a file-based vm structure from its prio_tree, to hide
-  * vma from rmap and vmtruncate before freeing its page tables.
-  */
-@@ -1023,7 +1034,7 @@
-               }
-       }
+-config PROC_SMAPS
+-      default y
+-      bool "Enable /proc/pid/smaps support" if EMBEDDED && PROC_FS && MMU
+-      help
+-        The /proc/pid/smaps interface reports a process's private and
+-          shared memory per mapping. Disabling this interface will reduce
+-          the size of the kernel for small machines.
+-
+-config PROC_CLEAR_REFS
+-      default y
+-      bool "Enable /proc/pid/clear_refs support" if EMBEDDED && PROC_FS && MMU
+-      help
+-        The /proc/pid/clear_refs interface allows clearing the
+-          referenced bits on a process's memory maps to allow monitoring
+-          working set size. Disabling this interface will reduce
+-          the size of the kernel for small machines.
+-
+-config PROC_PAGEMAP
+-      default y
+-      bool "Enable /proc/pid/pagemap support" if EMBEDDED && PROC_FS && MMU
+-      help
+-        The /proc/pid/pagemap interface allows reading the
+-          kernel's virtual memory to page frame mapping to determine which
+-          individual pages a process has mapped and which pages it shares
+-          with other processes. Disabling this interface will reduce the
+-          size of the kernel for small machines.
+-
+ endmenu               # General setup
  
--      error = security_file_mmap(file, reqprot, prot, flags);
-+      error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
-       if (error)
-               return error;
-               
-@@ -1150,12 +1161,8 @@
-               vx_vmlocked_add(mm, len >> PAGE_SHIFT);
-               make_pages_present(addr, addr + len);
-       }
--      if (flags & MAP_POPULATE) {
--              up_write(&mm->mmap_sem);
--              sys_remap_file_pages(addr, len, 0,
--                                      pgoff, flags & MAP_NONBLOCK);
--              down_write(&mm->mmap_sem);
--      }
-+      if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK))
-+              make_pages_present(addr, addr + len);
-       return addr;
+ config RT_MUTEXES
+@@ -674,19 +620,6 @@
+       default 0 if BASE_FULL
+       default 1 if !BASE_FULL
  
- unmap_and_free_vma:
-diff -Nurb linux-2.6.22-570/mm/mremap.c linux-2.6.22-590/mm/mremap.c
---- linux-2.6.22-570/mm/mremap.c       2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/mm/mremap.c       2008-01-02 13:56:38.000000000 -0500
-@@ -292,6 +292,10 @@
-               if ((addr <= new_addr) && (addr+old_len) > new_addr)
-                       goto out;
+-config PAGE_GROUP_BY_MOBILITY
+-      bool "Group pages based on their mobility in the page allocator"
+-      def_bool y
+-      help
+-        The standard allocator will fragment memory over time which means
+-        that high order allocations will fail even if kswapd is running. If
+-        this option is set, the allocator will try and group page types
+-        based on their ability to migrate or reclaim. This is a best effort
+-        attempt at lowering fragmentation which a few workloads care about.
+-        The loss is a more complex allocator that may perform slower. If
+-        you are interested in working with large pages, say Y and set
+-        /proc/sys/vm/min_free_bytes to 16374. Otherwise say N
+-
+ menu "Loadable module support"
  
-+              ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
-+              if (ret)
-+                      goto out;
-+
-               ret = do_munmap(mm, new_addr, new_len);
-               if (ret)
-                       goto out;
-@@ -394,8 +398,13 @@
+ config MODULES
+diff -Nurb linux-2.6.22-590/init/do_mounts_initrd.c linux-2.6.22-570/init/do_mounts_initrd.c
+--- linux-2.6.22-590/init/do_mounts_initrd.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/init/do_mounts_initrd.c   2007-07-08 19:32:17.000000000 -0400
+@@ -56,9 +56,12 @@
+       sys_chroot(".");
  
-                       new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
-                                               vma->vm_pgoff, map_flags);
-+                      if (new_addr & ~PAGE_MASK) {
-                       ret = new_addr;
--                      if (new_addr & ~PAGE_MASK)
-+                              goto out;
-+                      }
-+
-+                      ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
-+                      if (ret)
-                               goto out;
-               }
-               ret = move_vma(vma, addr, old_len, new_len, new_addr);
-diff -Nurb linux-2.6.22-570/mm/nommu.c linux-2.6.22-590/mm/nommu.c
---- linux-2.6.22-570/mm/nommu.c        2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/mm/nommu.c        2008-01-02 13:56:38.000000000 -0500
-@@ -639,7 +639,7 @@
-       }
+       pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
+-      if (pid > 0)
+-              while (pid != sys_wait4(-1, NULL, 0, NULL))
++      if (pid > 0) {
++              while (pid != sys_wait4(-1, NULL, 0, NULL)) {
++                      try_to_freeze();
+                       yield();
++              }
++      }
  
-       /* allow the security API to have its say */
--      ret = security_file_mmap(file, reqprot, prot, flags);
-+      ret = security_file_mmap(file, reqprot, prot, flags, addr, 0);
-       if (ret < 0)
-               return ret;
+       /* move initrd to rootfs' /old */
+       sys_fchdir(old_fd);
+diff -Nurb linux-2.6.22-590/init/main.c linux-2.6.22-570/init/main.c
+--- linux-2.6.22-590/init/main.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/init/main.c       2008-01-23 19:16:05.000000000 -0500
+@@ -39,7 +39,6 @@
+ #include <linux/writeback.h>
+ #include <linux/cpu.h>
+ #include <linux/cpuset.h>
+-#include <linux/container.h>
+ #include <linux/efi.h>
+ #include <linux/tick.h>
+ #include <linux/interrupt.h>
+@@ -503,7 +502,6 @@
+       char * command_line;
+       extern struct kernel_param __start___param[], __stop___param[];
  
-@@ -1336,8 +1336,7 @@
-       return 0;
- }
+-      container_init_early();
+       smp_setup_processor_id();
  
--struct page *filemap_nopage(struct vm_area_struct *area,
--                      unsigned long address, int *type)
-+struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
- {
-       BUG();
-       return NULL;
-diff -Nurb linux-2.6.22-570/mm/page_alloc.c linux-2.6.22-590/mm/page_alloc.c
---- linux-2.6.22-570/mm/page_alloc.c   2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/mm/page_alloc.c   2008-01-02 13:56:38.000000000 -0500
-@@ -143,6 +143,42 @@
- EXPORT_SYMBOL(nr_node_ids);
+       /*
+@@ -629,7 +627,6 @@
+ #ifdef CONFIG_PROC_FS
+       proc_root_init();
+ #endif
+-      container_init();
+       cpuset_init();
+       taskstats_init_early();
+       delayacct_init();
+diff -Nurb linux-2.6.22-590/ipc/msg.c linux-2.6.22-570/ipc/msg.c
+--- linux-2.6.22-590/ipc/msg.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/ipc/msg.c 2008-01-23 19:16:05.000000000 -0500
+@@ -88,7 +88,7 @@
+ static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
  #endif
  
-+#ifdef CONFIG_PAGE_GROUP_BY_MOBILITY
-+static inline int get_pageblock_migratetype(struct page *page)
-+{
-+      return get_pageblock_flags_group(page, PB_migrate, PB_migrate_end);
-+}
-+
-+static void set_pageblock_migratetype(struct page *page, int migratetype)
-+{
-+      set_pageblock_flags_group(page, (unsigned long)migratetype,
-+                                      PB_migrate, PB_migrate_end);
-+}
-+
-+static inline int gfpflags_to_migratetype(gfp_t gfp_flags)
-+{
-+      WARN_ON((gfp_flags & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK);
-+
-+      return (((gfp_flags & __GFP_MOVABLE) != 0) << 1) |
-+              ((gfp_flags & __GFP_RECLAIMABLE) != 0);
-+}
-+
-+#else
-+static inline int get_pageblock_migratetype(struct page *page)
-+{
-+      return MIGRATE_UNMOVABLE;
-+}
-+
-+static void set_pageblock_migratetype(struct page *page, int migratetype)
-+{
-+}
-+
-+static inline int gfpflags_to_migratetype(gfp_t gfp_flags)
-+{
-+      return MIGRATE_UNMOVABLE;
-+}
-+#endif /* CONFIG_PAGE_GROUP_BY_MOBILITY */
-+
- #ifdef CONFIG_DEBUG_VM
- static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
+-static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
++static void __ipc_init __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
  {
-@@ -397,6 +433,7 @@
- {
-       unsigned long page_idx;
-       int order_size = 1 << order;
-+      int migratetype = get_pageblock_migratetype(page);
-       if (unlikely(PageCompound(page)))
-               destroy_compound_page(page, order);
-@@ -409,7 +446,6 @@
-       __mod_zone_page_state(zone, NR_FREE_PAGES, order_size);
-       while (order < MAX_ORDER-1) {
-               unsigned long combined_idx;
--              struct free_area *area;
-               struct page *buddy;
-               buddy = __page_find_buddy(page, page_idx, order);
-@@ -417,8 +453,7 @@
-                       break;          /* Move the buddy up one level. */
-               list_del(&buddy->lru);
--              area = zone->free_area + order;
--              area->nr_free--;
-+              zone->free_area[order].nr_free--;
-               rmv_page_order(buddy);
-               combined_idx = __find_combined_index(page_idx, order);
-               page = page + (combined_idx - page_idx);
-@@ -426,7 +461,8 @@
-               order++;
-       }
-       set_page_order(page, order);
--      list_add(&page->lru, &zone->free_area[order].free_list);
-+      list_add(&page->lru,
-+              &zone->free_area[order].free_list[migratetype]);
-       zone->free_area[order].nr_free++;
+       ns->ids[IPC_MSG_IDS] = ids;
+       ns->msg_ctlmax = MSGMAX;
+@@ -97,6 +97,7 @@
+       ipc_init_ids(ids, ns->msg_ctlmni);
  }
  
-@@ -566,7 +602,8 @@
-  * -- wli
-  */
- static inline void expand(struct zone *zone, struct page *page,
--      int low, int high, struct free_area *area)
-+      int low, int high, struct free_area *area,
-+      int migratetype)
++#ifdef CONFIG_IPC_NS
+ int msg_init_ns(struct ipc_namespace *ns)
  {
-       unsigned long size = 1 << high;
-@@ -575,7 +612,7 @@
-               high--;
-               size >>= 1;
-               VM_BUG_ON(bad_range(zone, &page[size]));
--              list_add(&page[size].lru, &area->free_list);
-+              list_add(&page[size].lru, &area->free_list[migratetype]);
-               area->nr_free++;
-               set_page_order(&page[size], high);
-       }
-@@ -628,31 +665,172 @@
-       return 0;
+       struct ipc_ids *ids;
+@@ -128,6 +129,7 @@
+       kfree(ns->ids[IPC_MSG_IDS]);
+       ns->ids[IPC_MSG_IDS] = NULL;
  }
-+#ifdef CONFIG_PAGE_GROUP_BY_MOBILITY
-+/*
-+ * This array describes the order lists are fallen back to when
-+ * the free lists for the desirable migrate type are depleted
-+ */
-+static int fallbacks[MIGRATE_TYPES][MIGRATE_TYPES-1] = {
-+      [MIGRATE_UNMOVABLE]   = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE   },
-+      [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE,   MIGRATE_MOVABLE   },
-+      [MIGRATE_MOVABLE]     = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE },
-+};
-+
-+/*
-+ * Move the free pages in a range to the free lists of the requested type.
-+ * Note that start_page and end_pages are not aligned in a MAX_ORDER_NR_PAGES
-+ * boundary. If alignment is required, use move_freepages_block()
-+ */
-+int move_freepages(struct zone *zone,
-+                      struct page *start_page, struct page *end_page,
-+                      int migratetype)
-+{
-+      struct page *page;
-+      unsigned long order;
-+      int blocks_moved = 0;
-+
-+#ifndef CONFIG_HOLES_IN_ZONE
-+      /*
-+       * page_zone is not safe to call in this context when
-+       * CONFIG_HOLES_IN_ZONE is set. This bug check is probably redundant
-+       * anyway as we check zone boundaries in move_freepages_block().
-+       * Remove at a later date when no bug reports exist related to
-+       * CONFIG_PAGE_GROUP_BY_MOBILITY
-+       */
-+      BUG_ON(page_zone(start_page) != page_zone(end_page));
 +#endif
-+
-+      for (page = start_page; page <= end_page;) {
-+              if (!pfn_valid_within(page_to_pfn(page))) {
-+                      page++;
-+                      continue;
-+              }
-+
-+              if (!PageBuddy(page)) {
-+                      page++;
-+                      continue;
-+              }
-+
-+              order = page_order(page);
-+              list_del(&page->lru);
-+              list_add(&page->lru,
-+                      &zone->free_area[order].free_list[migratetype]);
-+              page += 1 << order;
-+              blocks_moved++;
-+      }
-+
-+      return blocks_moved;
-+}
-+
-+int move_freepages_block(struct zone *zone, struct page *page, int migratetype)
-+{
-+      unsigned long start_pfn, end_pfn;
-+      struct page *start_page, *end_page;
-+
-+      start_pfn = page_to_pfn(page);
-+      start_pfn = start_pfn & ~(MAX_ORDER_NR_PAGES-1);
-+      start_page = pfn_to_page(start_pfn);
-+      end_page = start_page + MAX_ORDER_NR_PAGES - 1;
-+      end_pfn = start_pfn + MAX_ORDER_NR_PAGES - 1;
-+
-+      /* Do not cross zone boundaries */
-+      if (start_pfn < zone->zone_start_pfn)
-+              start_page = page;
-+      if (end_pfn >= zone->zone_start_pfn + zone->spanned_pages)
-+              return 0;
-+
-+      return move_freepages(zone, start_page, end_page, migratetype);
-+}
-+
-+/* Remove an element from the buddy allocator from the fallback list */
-+static struct page *__rmqueue_fallback(struct zone *zone, int order,
-+                                              int start_migratetype)
-+{
-+      struct free_area * area;
-+      int current_order;
-+      struct page *page;
-+      int migratetype, i;
-+
-+      /* Find the largest possible block of pages in the other list */
-+      for (current_order = MAX_ORDER-1; current_order >= order;
-+                                              --current_order) {
-+              for (i = 0; i < MIGRATE_TYPES - 1; i++) {
-+                      migratetype = fallbacks[start_migratetype][i];
-+
-+                      area = &(zone->free_area[current_order]);
-+                      if (list_empty(&area->free_list[migratetype]))
-+                              continue;
-+
-+                      page = list_entry(area->free_list[migratetype].next,
-+                                      struct page, lru);
-+                      area->nr_free--;
-+
-+                      /*
-+                       * If breaking a large block of pages, move all free
-+                       * pages to the preferred allocation list
-+                       */
-+                      if (unlikely(current_order >= MAX_ORDER / 2)) {
-+                              migratetype = start_migratetype;
-+                              move_freepages_block(zone, page, migratetype);
-+                      }
-+
-+                      /* Remove the page from the freelists */
-+                      list_del(&page->lru);
-+                      rmv_page_order(page);
-+                      __mod_zone_page_state(zone, NR_FREE_PAGES,
-+                                                      -(1UL << order));
-+
-+                      if (current_order == MAX_ORDER - 1)
-+                              set_pageblock_migratetype(page,
-+                                                      start_migratetype);
-+
-+                      expand(zone, page, order, current_order, area, migratetype);
-+                      return page;
-+              }
-+      }
-+
-+      return NULL;
-+}
-+#else
-+static struct page *__rmqueue_fallback(struct zone *zone, int order,
-+                                              int start_migratetype)
-+{
-+      return NULL;
-+}
-+#endif /* CONFIG_PAGE_GROUP_BY_MOBILITY */
-+
- /* 
-  * Do the hard work of removing an element from the buddy allocator.
-  * Call me with the zone->lock already held.
-  */
--static struct page *__rmqueue(struct zone *zone, unsigned int order)
-+static struct page *__rmqueue(struct zone *zone, unsigned int order,
-+                                              int migratetype)
- {
-       struct free_area * area;
-       unsigned int current_order;
-       struct page *page;
-+      /* Find a page of the appropriate size in the preferred list */
-       for (current_order = order; current_order < MAX_ORDER; ++current_order) {
--              area = zone->free_area + current_order;
--              if (list_empty(&area->free_list))
-+              area = &(zone->free_area[current_order]);
-+              if (list_empty(&area->free_list[migratetype]))
-                       continue;
  
--              page = list_entry(area->free_list.next, struct page, lru);
-+              page = list_entry(area->free_list[migratetype].next,
-+                                                      struct page, lru);
-               list_del(&page->lru);
-               rmv_page_order(page);
-               area->nr_free--;
-               __mod_zone_page_state(zone, NR_FREE_PAGES, - (1UL << order));
--              expand(zone, page, order, current_order, area);
--              return page;
-+              expand(zone, page, order, current_order, area, migratetype);
-+              goto got_page;
-       }
+ void __init msg_init(void)
+ {
+diff -Nurb linux-2.6.22-590/ipc/sem.c linux-2.6.22-570/ipc/sem.c
+--- linux-2.6.22-590/ipc/sem.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/ipc/sem.c 2008-01-23 19:16:05.000000000 -0500
+@@ -123,7 +123,7 @@
+ #define sc_semopm     sem_ctls[2]
+ #define sc_semmni     sem_ctls[3]
  
--      return NULL;
-+      page = __rmqueue_fallback(zone, order, migratetype);
-+
-+got_page:
-+
-+      return page;
+-static void __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
++static void __ipc_init __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
+ {
+       ns->ids[IPC_SEM_IDS] = ids;
+       ns->sc_semmsl = SEMMSL;
+@@ -134,6 +134,7 @@
+       ipc_init_ids(ids, ns->sc_semmni);
  }
  
- /* 
-@@ -661,16 +839,18 @@
-  * Returns the number of new pages which were placed at *list.
-  */
- static int rmqueue_bulk(struct zone *zone, unsigned int order, 
--                      unsigned long count, struct list_head *list)
-+                      unsigned long count, struct list_head *list,
-+                      int migratetype)
- {
-       int i;
-       
-       spin_lock(&zone->lock);
-       for (i = 0; i < count; ++i) {
--              struct page *page = __rmqueue(zone, order);
-+              struct page *page = __rmqueue(zone, order, migratetype);
-               if (unlikely(page == NULL))
-                       break;
--              list_add_tail(&page->lru, list);
-+              list_add(&page->lru, list);
-+              set_page_private(page, migratetype);
-       }
-       spin_unlock(&zone->lock);
-       return i;
-@@ -732,7 +912,7 @@
++#ifdef CONFIG_IPC_NS
+ int sem_init_ns(struct ipc_namespace *ns)
  {
-       unsigned long pfn, max_zone_pfn;
-       unsigned long flags;
--      int order;
-+      int order, t;
-       struct list_head *curr;
-       if (!zone->spanned_pages)
-@@ -749,15 +929,15 @@
-                               swsusp_unset_page_free(page);
-               }
--      for (order = MAX_ORDER - 1; order >= 0; --order)
--              list_for_each(curr, &zone->free_area[order].free_list) {
-+      for_each_migratetype_order(order, t) {
-+              list_for_each(curr, &zone->free_area[order].free_list[t]) {
-                       unsigned long i;
-                       pfn = page_to_pfn(list_entry(curr, struct page, lru));
-                       for (i = 0; i < (1UL << order); i++)
-                               swsusp_set_page_free(pfn_to_page(pfn + i));
-               }
--
-+      }
-       spin_unlock_irqrestore(&zone->lock, flags);
+       struct ipc_ids *ids;
+@@ -165,6 +166,7 @@
+       kfree(ns->ids[IPC_SEM_IDS]);
+       ns->ids[IPC_SEM_IDS] = NULL;
  }
++#endif
  
-@@ -797,6 +977,7 @@
-       local_irq_save(flags);
-       __count_vm_event(PGFREE);
-       list_add(&page->lru, &pcp->list);
-+      set_page_private(page, get_pageblock_migratetype(page));
-       pcp->count++;
-       if (pcp->count >= pcp->high) {
-               free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
-@@ -846,6 +1027,7 @@
-       struct page *page;
-       int cold = !!(gfp_flags & __GFP_COLD);
-       int cpu;
-+      int migratetype = gfpflags_to_migratetype(gfp_flags);
+ void __init sem_init (void)
+ {
+diff -Nurb linux-2.6.22-590/ipc/shm.c linux-2.6.22-570/ipc/shm.c
+--- linux-2.6.22-590/ipc/shm.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/ipc/shm.c 2008-01-23 19:16:05.000000000 -0500
+@@ -79,7 +79,7 @@
+ static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
+ #endif
  
- again:
-       cpu  = get_cpu();
-@@ -856,16 +1038,32 @@
-               local_irq_save(flags);
-               if (!pcp->count) {
-                       pcp->count = rmqueue_bulk(zone, 0,
--                                              pcp->batch, &pcp->list);
-+                                      pcp->batch, &pcp->list, migratetype);
-                       if (unlikely(!pcp->count))
-                               goto failed;
-               }
-+
-+#ifdef CONFIG_PAGE_GROUP_BY_MOBILITY
-+              /* Find a page of the appropriate migrate type */
-+              list_for_each_entry(page, &pcp->list, lru)
-+                      if (page_private(page) == migratetype)
-+                              break;
-+
-+              /* Allocate more to the pcp list if necessary */
-+              if (unlikely(&page->lru == &pcp->list)) {
-+                      pcp->count += rmqueue_bulk(zone, 0,
-+                                      pcp->batch, &pcp->list, migratetype);
-+                      page = list_entry(pcp->list.next, struct page, lru);
-+              }
-+#else
-               page = list_entry(pcp->list.next, struct page, lru);
-+#endif /* CONFIG_PAGE_GROUP_BY_MOBILITY */
-+
-               list_del(&page->lru);
-               pcp->count--;
-       } else {
-               spin_lock_irqsave(&zone->lock, flags);
--              page = __rmqueue(zone, order);
-+              page = __rmqueue(zone, order, migratetype);
-               spin_unlock(&zone->lock);
-               if (!page)
-                       goto failed;
-@@ -1952,6 +2150,16 @@
-               init_page_count(page);
-               reset_page_mapcount(page);
-               SetPageReserved(page);
-+
-+              /*
-+               * Mark the block movable so that blocks are reserved for
-+               * movable at startup. This will force kernel allocations
-+               * to reserve their blocks rather than leaking throughout
-+               * the address space during boot when many long-lived
-+               * kernel allocations are made
-+               */
-+              set_pageblock_migratetype(page, MIGRATE_MOVABLE);
-+
-               INIT_LIST_HEAD(&page->lru);
- #ifdef WANT_PAGE_VIRTUAL
-               /* The shift won't overflow because ZONE_NORMAL is below 4G. */
-@@ -1964,9 +2172,9 @@
- void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone,
-                               unsigned long size)
+-static void __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
++static void __ipc_init __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
  {
--      int order;
--      for (order = 0; order < MAX_ORDER ; order++) {
--              INIT_LIST_HEAD(&zone->free_area[order].free_list);
-+      int order, t;
-+      for_each_migratetype_order(order, t) {
-+              INIT_LIST_HEAD(&zone->free_area[order].free_list[t]);
-               zone->free_area[order].nr_free = 0;
-       }
- }
-@@ -2584,6 +2792,41 @@
-                                                       realtotalpages);
+       ns->ids[IPC_SHM_IDS] = ids;
+       ns->shm_ctlmax = SHMMAX;
+@@ -100,6 +100,7 @@
+               shm_destroy(ns, shp);
  }
  
-+#ifndef CONFIG_SPARSEMEM
-+/*
-+ * Calculate the size of the zone->blockflags rounded to an unsigned long
-+ * Start by making sure zonesize is a multiple of MAX_ORDER-1 by rounding up
-+ * Then figure 1 NR_PAGEBLOCK_BITS worth of bits per MAX_ORDER-1, finally
-+ * round what is now in bits to nearest long in bits, then return it in
-+ * bytes.
-+ */
-+static unsigned long __init usemap_size(unsigned long zonesize)
-+{
-+      unsigned long usemapsize;
-+
-+      usemapsize = roundup(zonesize, MAX_ORDER_NR_PAGES);
-+      usemapsize = usemapsize >> (MAX_ORDER-1);
-+      usemapsize *= NR_PAGEBLOCK_BITS;
-+      usemapsize = roundup(usemapsize, 8 * sizeof(unsigned long));
-+
-+      return usemapsize / 8;
-+}
-+
-+static void __init setup_usemap(struct pglist_data *pgdat,
-+                              struct zone *zone, unsigned long zonesize)
-+{
-+      unsigned long usemapsize = usemap_size(zonesize);
-+      zone->pageblock_flags = NULL;
-+      if (usemapsize) {
-+              zone->pageblock_flags = alloc_bootmem_node(pgdat, usemapsize);
-+              memset(zone->pageblock_flags, 0, usemapsize);
-+      }
-+}
-+#else
-+static void inline setup_usemap(struct pglist_data *pgdat,
-+                              struct zone *zone, unsigned long zonesize) {}
-+#endif /* CONFIG_SPARSEMEM */
-+
- /*
-  * Set up the zone data structures:
-  *   - mark all pages reserved
-@@ -2664,6 +2907,7 @@
-               if (!size)
-                       continue;
-+              setup_usemap(pgdat, zone, size);
-               ret = init_currently_empty_zone(zone, zone_start_pfn,
-                                               size, MEMMAP_EARLY);
-               BUG_ON(ret);
-@@ -3363,6 +3607,21 @@
-                       for (order = 0; ((1UL << order) << PAGE_SHIFT) < size; order++)
-                               ;
-                       table = (void*) __get_free_pages(GFP_ATOMIC, order);
-+                      /*
-+                       * If bucketsize is not a power-of-two, we may free
-+                       * some pages at the end of hash table.
-+                       */
-+                      if (table) {
-+                              unsigned long alloc_end = (unsigned long)table +
-+                                              (PAGE_SIZE << order);
-+                              unsigned long used = (unsigned long)table +
-+                                              PAGE_ALIGN(size);
-+                              split_page(virt_to_page(table), order);
-+                              while (used < alloc_end) {
-+                                      free_page(used);
-+                                      used += PAGE_SIZE;
-+                              }
-+                      }
-               }
-       } while (!table && size > PAGE_SIZE && --log2qty);
-@@ -3396,4 +3655,79 @@
- EXPORT_SYMBOL(page_to_pfn);
- #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
++#ifdef CONFIG_IPC_NS
+ int shm_init_ns(struct ipc_namespace *ns)
+ {
+       struct ipc_ids *ids;
+@@ -131,6 +132,7 @@
+       kfree(ns->ids[IPC_SHM_IDS]);
+       ns->ids[IPC_SHM_IDS] = NULL;
+ }
++#endif
  
-+/* Return a pointer to the bitmap storing bits affecting a block of pages */
-+static inline unsigned long *get_pageblock_bitmap(struct zone *zone,
-+                                                      unsigned long pfn)
-+{
-+#ifdef CONFIG_SPARSEMEM
-+      return __pfn_to_section(pfn)->pageblock_flags;
-+#else
-+      return zone->pageblock_flags;
-+#endif /* CONFIG_SPARSEMEM */
-+}
+ void __init shm_init (void)
+ {
+@@ -232,13 +234,13 @@
+       mutex_unlock(&shm_ids(ns).mutex);
+ }
  
-+static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn)
-+{
-+#ifdef CONFIG_SPARSEMEM
-+      pfn &= (PAGES_PER_SECTION-1);
-+      return (pfn >> (MAX_ORDER-1)) * NR_PAGEBLOCK_BITS;
-+#else
-+      pfn = pfn - zone->zone_start_pfn;
-+      return (pfn >> (MAX_ORDER-1)) * NR_PAGEBLOCK_BITS;
-+#endif /* CONFIG_SPARSEMEM */
-+}
-+
-+/**
-+ * get_pageblock_flags_group - Return the requested group of flags for the MAX_ORDER_NR_PAGES block of pages
-+ * @page: The page within the block of interest
-+ * @start_bitidx: The first bit of interest to retrieve
-+ * @end_bitidx: The last bit of interest
-+ * returns pageblock_bits flags
-+ */
-+unsigned long get_pageblock_flags_group(struct page *page,
-+                                      int start_bitidx, int end_bitidx)
-+{
-+      struct zone *zone;
-+      unsigned long *bitmap;
-+      unsigned long pfn, bitidx;
-+      unsigned long flags = 0;
-+      unsigned long value = 1;
-+
-+      zone = page_zone(page);
-+      pfn = page_to_pfn(page);
-+      bitmap = get_pageblock_bitmap(zone, pfn);
-+      bitidx = pfn_to_bitidx(zone, pfn);
-+
-+      for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)
-+              if (test_bit(bitidx + start_bitidx, bitmap))
-+                      flags |= value;
-+
-+      return flags;
-+}
-+
-+/**
-+ * set_pageblock_flags_group - Set the requested group of flags for a MAX_ORDER_NR_PAGES block of pages
-+ * @page: The page within the block of interest
-+ * @start_bitidx: The first bit of interest
-+ * @end_bitidx: The last bit of interest
-+ * @flags: The flags to set
-+ */
-+void set_pageblock_flags_group(struct page *page, unsigned long flags,
-+                                      int start_bitidx, int end_bitidx)
-+{
-+      struct zone *zone;
-+      unsigned long *bitmap;
-+      unsigned long pfn, bitidx;
-+      unsigned long value = 1;
-+
-+      zone = page_zone(page);
-+      pfn = page_to_pfn(page);
-+      bitmap = get_pageblock_bitmap(zone, pfn);
-+      bitidx = pfn_to_bitidx(zone, pfn);
-+
-+      for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)
-+              if (flags & value)
-+                      __set_bit(bitidx + start_bitidx, bitmap);
-+              else
-+                      __clear_bit(bitidx + start_bitidx, bitmap);
-+}
-diff -Nurb linux-2.6.22-570/mm/pdflush.c linux-2.6.22-590/mm/pdflush.c
---- linux-2.6.22-570/mm/pdflush.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/mm/pdflush.c      2008-01-02 13:56:38.000000000 -0500
-@@ -92,6 +92,7 @@
- static int __pdflush(struct pdflush_work *my_work)
+-static struct page *shm_fault(struct vm_area_struct *vma,
+-                                      struct fault_data *fdata)
++static struct page *shm_nopage(struct vm_area_struct *vma,
++                             unsigned long address, int *type)
  {
-       current->flags |= PF_FLUSHER | PF_SWAPWRITE;
-+      set_freezable();
-       my_work->fn = NULL;
-       my_work->who = current;
-       INIT_LIST_HEAD(&my_work->list);
-diff -Nurb linux-2.6.22-570/mm/rmap.c linux-2.6.22-590/mm/rmap.c
---- linux-2.6.22-570/mm/rmap.c 2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/mm/rmap.c 2008-01-02 13:56:38.000000000 -0500
-@@ -622,8 +622,10 @@
-                       printk (KERN_EMERG "  page->count = %x\n", page_count(page));
-                       printk (KERN_EMERG "  page->mapping = %p\n", page->mapping);
-                       print_symbol (KERN_EMERG "  vma->vm_ops = %s\n", (unsigned long)vma->vm_ops);
--                      if (vma->vm_ops)
-+                      if (vma->vm_ops) {
-                               print_symbol (KERN_EMERG "  vma->vm_ops->nopage = %s\n", (unsigned long)vma->vm_ops->nopage);
-+                              print_symbol (KERN_EMERG "  vma->vm_ops->fault = %s\n", (unsigned long)vma->vm_ops->fault);
-+                      }
-                       if (vma->vm_file && vma->vm_file->f_op)
-                               print_symbol (KERN_EMERG "  vma->vm_file->f_op->mmap = %s\n", (unsigned long)vma->vm_file->f_op->mmap);
-                       BUG();
-diff -Nurb linux-2.6.22-570/mm/shmem.c linux-2.6.22-590/mm/shmem.c
---- linux-2.6.22-570/mm/shmem.c        2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/mm/shmem.c        2008-01-02 13:56:38.000000000 -0500
-@@ -81,6 +81,7 @@
-       SGP_READ,       /* don't exceed i_size, don't allocate page */
-       SGP_CACHE,      /* don't exceed i_size, may allocate page */
-       SGP_WRITE,      /* may exceed i_size, may allocate page */
-+      SGP_FAULT,      /* same as SGP_CACHE, return with page locked */
- };
+       struct file *file = vma->vm_file;
+       struct shm_file_data *sfd = shm_file_data(file);
  
- static int shmem_getpage(struct inode *inode, unsigned long idx,
-@@ -92,8 +93,11 @@
-        * The above definition of ENTRIES_PER_PAGE, and the use of
-        * BLOCKS_PER_PAGE on indirect pages, assume PAGE_CACHE_SIZE:
-        * might be reconsidered if it ever diverges from PAGE_SIZE.
-+       *
-+       * Mobility flags are masked out as swap vectors cannot move
-        */
--      return alloc_pages(gfp_mask, PAGE_CACHE_SHIFT-PAGE_SHIFT);
-+      return alloc_pages((gfp_mask & ~GFP_MOVABLE_MASK) | __GFP_ZERO,
-+                              PAGE_CACHE_SHIFT-PAGE_SHIFT);
+-      return sfd->vm_ops->fault(vma, fdata);
++      return sfd->vm_ops->nopage(vma, address, type);
  }
  
- static inline void shmem_dir_free(struct page *page)
-@@ -371,7 +375,7 @@
-               }
-               spin_unlock(&info->lock);
--              page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping) | __GFP_ZERO);
-+              page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping));
-               if (page)
-                       set_page_private(page, 0);
-               spin_lock(&info->lock);
-@@ -1110,6 +1114,10 @@
+ #ifdef CONFIG_NUMA
+@@ -277,7 +279,6 @@
+       if (ret != 0)
+               return ret;
+       sfd->vm_ops = vma->vm_ops;
+-      BUG_ON(!sfd->vm_ops->fault);
+       vma->vm_ops = &shm_vm_ops;
+       shm_open(vma);
  
-       if (idx >= SHMEM_MAX_INDEX)
-               return -EFBIG;
-+
-+      if (type)
-+              *type = VM_FAULT_MINOR;
-+
-       /*
-        * Normally, filepage is NULL on entry, and either found
-        * uptodate immediately, or allocated and zeroed, or read
-@@ -1299,8 +1307,10 @@
-       }
- done:
-       if (*pagep != filepage) {
--              unlock_page(filepage);
-               *pagep = filepage;
-+              if (sgp != SGP_FAULT)
-+                      unlock_page(filepage);
-+
-       }
-       return 0;
+@@ -336,7 +337,7 @@
+ static struct vm_operations_struct shm_vm_ops = {
+       .open   = shm_open,     /* callback for a new vm-area open */
+       .close  = shm_close,    /* callback for when the vm-area is released */
+-      .fault  = shm_fault,
++      .nopage = shm_nopage,
+ #if defined(CONFIG_NUMA)
+       .set_policy = shm_set_policy,
+       .get_policy = shm_get_policy,
+diff -Nurb linux-2.6.22-590/ipc/util.c linux-2.6.22-570/ipc/util.c
+--- linux-2.6.22-590/ipc/util.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/ipc/util.c        2008-01-23 19:16:05.000000000 -0500
+@@ -52,6 +52,7 @@
+       },
+ };
  
-@@ -1312,72 +1322,29 @@
-       return error;
++#ifdef CONFIG_IPC_NS
+ static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
+ {
+       int err;
+@@ -113,6 +114,14 @@
+       atomic_dec(&vs_global_ipc_ns);
+       kfree(ns);
  }
++#else
++struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
++{
++      if (flags & CLONE_NEWIPC)
++              return ERR_PTR(-EINVAL);
++      return ns;
++}
++#endif
  
--static struct page *shmem_nopage(struct vm_area_struct *vma,
--                               unsigned long address, int *type)
-+static struct page *shmem_fault(struct vm_area_struct *vma,
-+                                      struct fault_data *fdata)
+ /**
+  *    ipc_init        -       initialise IPC subsystem
+@@ -140,7 +149,7 @@
+  *    array itself. 
+  */
+  
+-void ipc_init_ids(struct ipc_ids* ids, int size)
++void __ipc_init ipc_init_ids(struct ipc_ids* ids, int size)
  {
-       struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
-       struct page *page = NULL;
--      unsigned long idx;
-       int error;
+       int i;
  
--      idx = (address - vma->vm_start) >> PAGE_SHIFT;
--      idx += vma->vm_pgoff;
--      idx >>= PAGE_CACHE_SHIFT - PAGE_SHIFT;
--      if (((loff_t) idx << PAGE_CACHE_SHIFT) >= i_size_read(inode))
--              return NOPAGE_SIGBUS;
--
--      error = shmem_getpage(inode, idx, &page, SGP_CACHE, type);
--      if (error)
--              return (error == -ENOMEM)? NOPAGE_OOM: NOPAGE_SIGBUS;
--
--      mark_page_accessed(page);
--      return page;
--}
--
--static int shmem_populate(struct vm_area_struct *vma,
--      unsigned long addr, unsigned long len,
--      pgprot_t prot, unsigned long pgoff, int nonblock)
--{
--      struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
--      struct mm_struct *mm = vma->vm_mm;
--      enum sgp_type sgp = nonblock? SGP_QUICK: SGP_CACHE;
--      unsigned long size;
+diff -Nurb linux-2.6.22-590/ipc/util.h linux-2.6.22-570/ipc/util.h
+--- linux-2.6.22-590/ipc/util.h        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/ipc/util.h        2007-07-08 19:32:17.000000000 -0400
+@@ -41,8 +41,12 @@
+ };
+ struct seq_file;
 -
--      size = (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
--      if (pgoff >= size || pgoff + (len >> PAGE_SHIFT) > size)
--              return -EINVAL;
-+      BUG_ON(!(vma->vm_flags & VM_CAN_INVALIDATE));
+-void ipc_init_ids(struct ipc_ids *ids, int size);
++#ifdef CONFIG_IPC_NS
++#define __ipc_init
++#else
++#define __ipc_init    __init
++#endif
++void __ipc_init ipc_init_ids(struct ipc_ids *ids, int size);
+ #ifdef CONFIG_PROC_FS
+ void __init ipc_init_proc_interface(const char *path, const char *header,
+               int ids, int (*show)(struct seq_file *, void *));
+diff -Nurb linux-2.6.22-590/kernel/Makefile linux-2.6.22-570/kernel/Makefile
+--- linux-2.6.22-590/kernel/Makefile   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/Makefile   2008-01-23 19:16:05.000000000 -0500
+@@ -4,12 +4,11 @@
  
--      while ((long) len > 0) {
--              struct page *page = NULL;
--              int err;
--              /*
--               * Will need changing if PAGE_CACHE_SIZE != PAGE_SIZE
--               */
--              err = shmem_getpage(inode, pgoff, &page, sgp, NULL);
--              if (err)
--                      return err;
--              /* Page may still be null, but only if nonblock was set. */
--              if (page) {
--                      mark_page_accessed(page);
--                      err = install_page(mm, vma, addr, page, prot);
--                      if (err) {
--                              page_cache_release(page);
--                              return err;
--                      }
--              } else if (vma->vm_flags & VM_NONLINEAR) {
--                      /* No page was found just because we can't read it in
--                       * now (being here implies nonblock != 0), but the page
--                       * may exist, so set the PTE to fault it in later. */
--                      err = install_file_pte(mm, vma, addr, pgoff, prot);
--                      if (err)
--                              return err;
-+      if (((loff_t)fdata->pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
-+              fdata->type = VM_FAULT_SIGBUS;
-+              return NULL;
-               }
+ obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
+           exit.o itimer.o time.o softirq.o resource.o \
+-          sysctl.o capability.o ptrace.o timer.o user.o user_namespace.o \
++          sysctl.o capability.o ptrace.o timer.o user.o \
+           signal.o sys.o kmod.o workqueue.o pid.o \
+           rcupdate.o extable.o params.o posix-timers.o \
+           kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
+-          hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o \
+-          utsname.o
++          hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o
  
--              len -= PAGE_SIZE;
--              addr += PAGE_SIZE;
--              pgoff++;
-+      error = shmem_getpage(inode, fdata->pgoff, &page,
-+                                              SGP_FAULT, &fdata->type);
-+      if (error) {
-+              fdata->type = ((error == -ENOMEM)?VM_FAULT_OOM:VM_FAULT_SIGBUS);
-+              return NULL;
-       }
--      return 0;
-+
-+      mark_page_accessed(page);
-+      return page;
- }
+ obj-y   += vserver/
  
- #ifdef CONFIG_NUMA
-@@ -1424,6 +1391,7 @@
+@@ -34,22 +33,16 @@
+ obj-$(CONFIG_UID16) += uid16.o
+ obj-$(CONFIG_MODULES) += module.o
+ obj-$(CONFIG_KALLSYMS) += kallsyms.o
+-obj-$(CONFIG_STACK_UNWIND) += unwind.o
+ obj-$(CONFIG_PM) += power/
+ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
+ obj-$(CONFIG_KEXEC) += kexec.o
+ obj-$(CONFIG_COMPAT) += compat.o
+-obj-$(CONFIG_CONTAINERS) += container.o
+-obj-$(CONFIG_CONTAINER_DEBUG) += container_debug.o
+ obj-$(CONFIG_CPUSETS) += cpuset.o
+-obj-$(CONFIG_CONTAINER_CPUACCT) += cpu_acct.o
+-obj-$(CONFIG_CONTAINER_NS) += ns_container.o
+ obj-$(CONFIG_IKCONFIG) += configs.o
+ obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
+ obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
+ obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
+ obj-$(CONFIG_KPROBES) += kprobes.o
+-obj-$(CONFIG_KGDB) += kgdb.o
+ obj-$(CONFIG_SYSFS) += ksysfs.o
+ obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
+ obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
+@@ -57,6 +50,7 @@
+ obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
+ obj-$(CONFIG_RELAY) += relay.o
+ obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
++obj-$(CONFIG_UTS_NS) += utsname.o
+ obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
+ obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
+diff -Nurb linux-2.6.22-590/kernel/audit.c linux-2.6.22-570/kernel/audit.c
+--- linux-2.6.22-590/kernel/audit.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/audit.c    2007-07-08 19:32:17.000000000 -0400
+@@ -391,7 +391,6 @@
  {
-       file_accessed(file);
-       vma->vm_ops = &shmem_vm_ops;
-+      vma->vm_flags |= VM_CAN_INVALIDATE | VM_CAN_NONLINEAR;
-       return 0;
- }
+       struct sk_buff *skb;
  
-@@ -2477,8 +2445,7 @@
- };
+-      set_freezable();
+       while (!kthread_should_stop()) {
+               skb = skb_dequeue(&audit_skb_queue);
+               wake_up(&audit_backlog_wait);
+@@ -795,8 +794,8 @@
  
- static struct vm_operations_struct shmem_vm_ops = {
--      .nopage         = shmem_nopage,
--      .populate       = shmem_populate,
-+      .fault          = shmem_fault,
- #ifdef CONFIG_NUMA
-       .set_policy     = shmem_set_policy,
-       .get_policy     = shmem_get_policy,
-@@ -2614,5 +2581,6 @@
-               fput(vma->vm_file);
-       vma->vm_file = file;
-       vma->vm_ops = &shmem_vm_ops;
-+      vma->vm_flags |= VM_CAN_INVALIDATE;
-       return 0;
+       printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
+              audit_default ? "enabled" : "disabled");
+-      audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, 0,
+-                                         audit_receive, NULL, THIS_MODULE);
++      audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive,
++                                         NULL, THIS_MODULE);
+       if (!audit_sock)
+               audit_panic("cannot initialize netlink socket");
+       else
+diff -Nurb linux-2.6.22-590/kernel/auditsc.c linux-2.6.22-570/kernel/auditsc.c
+--- linux-2.6.22-590/kernel/auditsc.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/auditsc.c  2008-01-23 19:15:56.000000000 -0500
+@@ -1500,7 +1500,6 @@
+                       context->names[idx].ino = (unsigned long)-1;
+       }
  }
-diff -Nurb linux-2.6.22-570/mm/shmem.c.orig linux-2.6.22-590/mm/shmem.c.orig
---- linux-2.6.22-570/mm/shmem.c.orig   2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/mm/shmem.c.orig   1969-12-31 19:00:00.000000000 -0500
-@@ -1,2619 +0,0 @@
+-EXPORT_SYMBOL(__audit_inode_child);
+ /**
+  * auditsc_get_stamp - get local copies of audit_context values
+diff -Nurb linux-2.6.22-590/kernel/container.c linux-2.6.22-570/kernel/container.c
+--- linux-2.6.22-590/kernel/container.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/container.c        1969-12-31 19:00:00.000000000 -0500
+@@ -1,2545 +0,0 @@
 -/*
-- * Resizable virtual memory filesystem for Linux.
+- *  kernel/container.c
 - *
-- * Copyright (C) 2000 Linus Torvalds.
-- *             2000 Transmeta Corp.
-- *             2000-2001 Christoph Rohland
-- *             2000-2001 SAP AG
-- *             2002 Red Hat Inc.
-- * Copyright (C) 2002-2005 Hugh Dickins.
-- * Copyright (C) 2002-2005 VERITAS Software Corporation.
-- * Copyright (C) 2004 Andi Kleen, SuSE Labs
+- *  Generic process-grouping system.
 - *
-- * Extended attribute support for tmpfs:
-- * Copyright (c) 2004, Luke Kenneth Casson Leighton <lkcl@lkcl.net>
-- * Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
+- *  Based originally on the cpuset system, extracted by Paul Menage
+- *  Copyright (C) 2006 Google, Inc
 - *
-- * This file is released under the GPL.
-- */
--
--/*
-- * This virtual memory filesystem is heavily based on the ramfs. It
-- * extends ramfs by the ability to use swap and honor resource limits
-- * which makes it a completely usable filesystem.
+- *  Copyright notices from the original cpuset code:
+- *  --------------------------------------------------
+- *  Copyright (C) 2003 BULL SA.
+- *  Copyright (C) 2004-2006 Silicon Graphics, Inc.
+- *
+- *  Portions derived from Patrick Mochel's sysfs code.
+- *  sysfs is Copyright (c) 2001-3 Patrick Mochel
+- *
+- *  2003-10-10 Written by Simon Derr.
+- *  2003-10-22 Updates by Stephen Hemminger.
+- *  2004 May-July Rework by Paul Jackson.
+- *  ---------------------------------------------------
+- *
+- *  This file is subject to the terms and conditions of the GNU General Public
+- *  License.  See the file COPYING in the main directory of the Linux
+- *  distribution for more details.
 - */
 -
--#include <linux/module.h>
--#include <linux/init.h>
+-#include <linux/cpu.h>
+-#include <linux/cpumask.h>
+-#include <linux/container.h>
+-#include <linux/err.h>
+-#include <linux/errno.h>
+-#include <linux/file.h>
 -#include <linux/fs.h>
--#include <linux/xattr.h>
--#include <linux/generic_acl.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/kernel.h>
+-#include <linux/kmod.h>
+-#include <linux/list.h>
+-#include <linux/mempolicy.h>
 -#include <linux/mm.h>
--#include <linux/mman.h>
--#include <linux/file.h>
--#include <linux/swap.h>
--#include <linux/pagemap.h>
--#include <linux/string.h>
--#include <linux/slab.h>
--#include <linux/backing-dev.h>
--#include <linux/shmem_fs.h>
+-#include <linux/mutex.h>
+-#include <linux/module.h>
 -#include <linux/mount.h>
--#include <linux/writeback.h>
--#include <linux/vfs.h>
--#include <linux/blkdev.h>
--#include <linux/security.h>
--#include <linux/swapops.h>
--#include <linux/mempolicy.h>
 -#include <linux/namei.h>
--#include <linux/ctype.h>
--#include <linux/migrate.h>
--#include <linux/highmem.h>
+-#include <linux/pagemap.h>
+-#include <linux/proc_fs.h>
+-#include <linux/rcupdate.h>
+-#include <linux/uaccess.h>
+-#include <linux/sched.h>
+-#include <linux/seq_file.h>
+-#include <linux/security.h>
+-#include <linux/slab.h>
+-#include <linux/magic.h>
+-#include <linux/smp_lock.h>
+-#include <linux/spinlock.h>
+-#include <linux/stat.h>
+-#include <linux/string.h>
+-#include <linux/time.h>
 -#include <linux/backing-dev.h>
+-#include <linux/sort.h>
 -
--#include <asm/uaccess.h>
--#include <asm/div64.h>
--#include <asm/pgtable.h>
+-#include <asm/atomic.h>
+-
+-static DEFINE_MUTEX(container_mutex);
 -
--/* This magic number is used in glibc for posix shared memory */
--#define TMPFS_MAGIC   0x01021994
+-/* Generate an array of container subsystem pointers */
+-#define SUBSYS(_x) &_x ## _subsys,
+-
+-static struct container_subsys *subsys[] = {
+-#include <linux/container_subsys.h>
+-};
 -
--#define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))
--#define ENTRIES_PER_PAGEPAGE (ENTRIES_PER_PAGE*ENTRIES_PER_PAGE)
--#define BLOCKS_PER_PAGE  (PAGE_CACHE_SIZE/512)
+-/* A containerfs_root represents the root of a container hierarchy,
+- * and may be associated with a superblock to form an active
+- * hierarchy */
+-struct containerfs_root {
+-      struct super_block *sb;
 -
--#define SHMEM_MAX_INDEX  (SHMEM_NR_DIRECT + (ENTRIES_PER_PAGEPAGE/2) * (ENTRIES_PER_PAGE+1))
--#define SHMEM_MAX_BYTES  ((unsigned long long)SHMEM_MAX_INDEX << PAGE_CACHE_SHIFT)
+-      /* The bitmask of subsystems attached to this hierarchy */
+-      unsigned long subsys_bits;
 -
--#define VM_ACCT(size)    (PAGE_CACHE_ALIGN(size) >> PAGE_SHIFT)
+-      /* A list running through the attached subsystems */
+-      struct list_head subsys_list;
 -
--/* info->flags needs VM_flags to handle pagein/truncate races efficiently */
--#define SHMEM_PAGEIN   VM_READ
--#define SHMEM_TRUNCATE         VM_WRITE
+-      /* The root container for this hierarchy */
+-      struct container top_container;
 -
--/* Definition to limit shmem_truncate's steps between cond_rescheds */
--#define LATENCY_LIMIT  64
+-      /* Tracks how many containers are currently defined in hierarchy.*/
+-      int number_of_containers;
 -
--/* Pretend that each entry is of this size in directory's i_size */
--#define BOGO_DIRENT_SIZE 20
+-      /* A list running through the mounted hierarchies */
+-      struct list_head root_list;
 -
--/* Flag allocation requirements to shmem_getpage and shmem_swp_alloc */
--enum sgp_type {
--      SGP_QUICK,      /* don't try more than file page cache lookup */
--      SGP_READ,       /* don't exceed i_size, don't allocate page */
--      SGP_CACHE,      /* don't exceed i_size, may allocate page */
--      SGP_WRITE,      /* may exceed i_size, may allocate page */
+-      /* The path to use for release notifications. No locking
+-       * between setting and use - so if userspace updates this
+-       * while subcontainers exist, you could miss a
+-       * notification. We ensure that it's always a valid
+-       * NUL-terminated string */
+-      char release_agent_path[PATH_MAX];
 -};
 -
--static int shmem_getpage(struct inode *inode, unsigned long idx,
--                       struct page **pagep, enum sgp_type sgp, int *type);
 -
--static inline struct page *shmem_dir_alloc(gfp_t gfp_mask)
--{
--      /*
--       * The above definition of ENTRIES_PER_PAGE, and the use of
--       * BLOCKS_PER_PAGE on indirect pages, assume PAGE_CACHE_SIZE:
--       * might be reconsidered if it ever diverges from PAGE_SIZE.
--       */
--      return alloc_pages(gfp_mask, PAGE_CACHE_SHIFT-PAGE_SHIFT);
--}
+-/* The "rootnode" hierarchy is the "dummy hierarchy", reserved for the
+- * subsystems that are otherwise unattached - it never has more than a
+- * single container, and all tasks are part of that container. */
 -
--static inline void shmem_dir_free(struct page *page)
--{
--      __free_pages(page, PAGE_CACHE_SHIFT-PAGE_SHIFT);
--}
+-static struct containerfs_root rootnode;
+-
+-/* The list of hierarchy roots */
+-
+-static LIST_HEAD(roots);
+-static int root_count;
+-
+-/* dummytop is a shorthand for the dummy hierarchy's top container */
+-#define dummytop (&rootnode.top_container)
+-
+-/* This flag indicates whether tasks in the fork and exit paths should
+- * take callback_mutex and check for fork/exit handlers to call. This
+- * avoids us having to do extra work in the fork/exit path if none of the
+- * subsystems need to be called.
+- */
+-static int need_forkexit_callback;
+-
+-/* bits in struct container flags field */
+-enum {
+-      /* Container is dead */
+-      CONT_REMOVED,
+-      /* Container has previously had a child container or a task,
+-       * but no longer (only if CONT_NOTIFY_ON_RELEASE is set) */
+-      CONT_RELEASABLE,
+-      /* Container requires release notifications to userspace */
+-      CONT_NOTIFY_ON_RELEASE,
+-};
 -
--static struct page **shmem_dir_map(struct page *page)
+-/* convenient tests for these bits */
+-inline int container_is_removed(const struct container *cont)
 -{
--      return (struct page **)kmap_atomic(page, KM_USER0);
+-      return test_bit(CONT_REMOVED, &cont->flags);
 -}
 -
--static inline void shmem_dir_unmap(struct page **dir)
+-inline int container_is_releasable(const struct container *cont)
 -{
--      kunmap_atomic(dir, KM_USER0);
+-      const int bits =
+-              (1 << CONT_RELEASABLE) |
+-              (1 << CONT_NOTIFY_ON_RELEASE);
+-      return (cont->flags & bits) == bits;
 -}
 -
--static swp_entry_t *shmem_swp_map(struct page *page)
+-inline int notify_on_release(const struct container *cont)
 -{
--      return (swp_entry_t *)kmap_atomic(page, KM_USER1);
+-      return test_bit(CONT_NOTIFY_ON_RELEASE, &cont->flags);
 -}
 -
--static inline void shmem_swp_balance_unmap(void)
--{
+-/* for_each_subsys() allows you to iterate on each subsystem attached to
+- * an active hierarchy */
+-#define for_each_subsys(_root, _ss) \
+-list_for_each_entry(_ss, &_root->subsys_list, sibling)
+-
+-/* for_each_root() allows you to iterate across the active hierarchies */
+-#define for_each_root(_root) \
+-list_for_each_entry(_root, &roots, root_list)
+-
+-/* the list of containers eligible for automatic release */
+-static LIST_HEAD(release_list);
+-static void container_release_agent(struct work_struct *work);
+-static DECLARE_WORK(release_agent_work, container_release_agent);
+-static void check_for_release(struct container *cont);
+-
+-/* Link structure for associating css_group objects with containers */
+-struct cg_container_link {
 -      /*
--       * When passing a pointer to an i_direct entry, to code which
--       * also handles indirect entries and so will shmem_swp_unmap,
--       * we must arrange for the preempt count to remain in balance.
--       * What kmap_atomic of a lowmem page does depends on config
--       * and architecture, so pretend to kmap_atomic some lowmem page.
+-       * List running through cg_container_links associated with a
+-       * container, anchored on container->css_groups
 -       */
--      (void) kmap_atomic(ZERO_PAGE(0), KM_USER1);
--}
+-      struct list_head cont_link_list;
+-      /*
+-       * List running through cg_container_links pointing at a
+-       * single css_group object, anchored on css_group->cg_links
+-       */
+-      struct list_head cg_link_list;
+-      struct css_group *cg;
+-};
 -
--static inline void shmem_swp_unmap(swp_entry_t *entry)
--{
--      kunmap_atomic(entry, KM_USER1);
--}
+-/* The default css_group - used by init and its children prior to any
+- * hierarchies being mounted. It contains a pointer to the root state
+- * for each subsystem. Also used to anchor the list of css_groups. Not
+- * reference-counted, to improve performance when child containers
+- * haven't been created.
+- */
 -
--static inline struct shmem_sb_info *SHMEM_SB(struct super_block *sb)
--{
--      return sb->s_fs_info;
--}
+-static struct css_group init_css_group;
+-static struct cg_container_link init_css_group_link;
+-
+-/* css_group_lock protects the list of css_group objects, and the
+- * chain of tasks off each css_group. Nests inside task->alloc_lock */
+-static DEFINE_RWLOCK(css_group_lock);
+-static int css_group_count;
+-
+-
+-/* When we create or destroy a css_group, the operation simply
+- * takes/releases a reference count on all the containers referenced
+- * by subsystems in this css_group. This can end up multiple-counting
+- * some containers, but that's OK - the ref-count is just a
+- * busy/not-busy indicator; ensuring that we only count each container
+- * once would require taking a global lock to ensure that no
+- * subsystems moved between hierarchies while we were doing so.
+- *
+- * Possible TODO: decide at boot time based on the number of
+- * registered subsystems and the number of CPUs or NUMA nodes whether
+- * it's better for performance to ref-count every subsystem, or to
+- * take a global lock and only add one ref count to each hierarchy.
+- */
 -
 -/*
-- * shmem_file_setup pre-accounts the whole fixed size of a VM object,
-- * for shared memory and for shared anonymous (/dev/zero) mappings
-- * (unless MAP_NORESERVE and sysctl_overcommit_memory <= 1),
-- * consistent with the pre-accounting of private mappings ...
+- * unlink a css_group from the list and free it
 - */
--static inline int shmem_acct_size(unsigned long flags, loff_t size)
+-static void unlink_css_group(struct css_group *cg)
 -{
--      return (flags & VM_ACCOUNT)?
--              security_vm_enough_memory(VM_ACCT(size)): 0;
+-      write_lock(&css_group_lock);
+-      list_del(&cg->list);
+-      css_group_count--;
+-      while (!list_empty(&cg->cg_links)) {
+-              struct cg_container_link *link;
+-              link = list_entry(cg->cg_links.next,
+-                                struct cg_container_link, cg_link_list);
+-              list_del(&link->cg_link_list);
+-              list_del(&link->cont_link_list);
+-              kfree(link);
+-      }
+-      write_unlock(&css_group_lock);
 -}
 -
--static inline void shmem_unacct_size(unsigned long flags, loff_t size)
+-static void release_css_group(struct kref *k)
 -{
--      if (flags & VM_ACCOUNT)
--              vm_unacct_memory(VM_ACCT(size));
+-      int i;
+-      struct css_group *cg = container_of(k, struct css_group, ref);
+-
+-      BUG_ON(!mutex_is_locked(&container_mutex));
+-      unlink_css_group(cg);
+-      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
+-              struct container *cont = cg->subsys[i]->container;
+-              if (atomic_dec_and_test(&cont->count) &&
+-                  container_is_releasable(cont)) {
+-                      check_for_release(cont);
+-              }
+-      }
+-      kfree(cg);
 -}
 -
 -/*
-- * ... whereas tmpfs objects are accounted incrementally as
-- * pages are allocated, in order to allow huge sparse files.
-- * shmem_getpage reports shmem_acct_block failure as -ENOSPC not -ENOMEM,
-- * so that a failure on a sparse tmpfs mapping will give SIGBUS not OOM.
+- * In the task exit path we want to avoid taking container_mutex
+- * unless absolutely necessary, so the release process is slightly
+- * different.
 - */
--static inline int shmem_acct_block(unsigned long flags)
+-static void release_css_group_taskexit(struct kref *k)
 -{
--      return (flags & VM_ACCOUNT)?
--              0: security_vm_enough_memory(VM_ACCT(PAGE_CACHE_SIZE));
+-      int i;
+-      struct css_group *cg = container_of(k, struct css_group, ref);
+-
+-      unlink_css_group(cg);
+-      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
+-              struct container *cont = cg->subsys[i]->container;
+-              if (notify_on_release(cont)) {
+-                      mutex_lock(&container_mutex);
+-                      set_bit(CONT_RELEASABLE, &cont->flags);
+-                      if (atomic_dec_and_test(&cont->count))
+-                              check_for_release(cont);
+-                      mutex_unlock(&container_mutex);
+-              } else {
+-                      atomic_dec(&cont->count);
+-              }
+-      }
+-      kfree(cg);
 -}
 -
--static inline void shmem_unacct_blocks(unsigned long flags, long pages)
+-/*
+- * refcounted get/put for css_group objects
+- */
+-static inline void get_css_group(struct css_group *cg)
 -{
--      if (!(flags & VM_ACCOUNT))
--              vm_unacct_memory(pages * VM_ACCT(PAGE_CACHE_SIZE));
+-      kref_get(&cg->ref);
 -}
 -
--static const struct super_operations shmem_ops;
--static const struct address_space_operations shmem_aops;
--static const struct file_operations shmem_file_operations;
--static const struct inode_operations shmem_inode_operations;
--static const struct inode_operations shmem_dir_inode_operations;
--static const struct inode_operations shmem_special_inode_operations;
--static struct vm_operations_struct shmem_vm_ops;
--
--static struct backing_dev_info shmem_backing_dev_info  __read_mostly = {
--      .ra_pages       = 0,    /* No readahead */
--      .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
--      .unplug_io_fn   = default_unplug_io_fn,
--};
--
--static LIST_HEAD(shmem_swaplist);
--static DEFINE_SPINLOCK(shmem_swaplist_lock);
--
--static void shmem_free_blocks(struct inode *inode, long pages)
+-static inline void put_css_group(struct css_group *cg)
 -{
--      struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
--      if (sbinfo->max_blocks) {
--              spin_lock(&sbinfo->stat_lock);
--              sbinfo->free_blocks += pages;
--              inode->i_blocks -= pages*BLOCKS_PER_PAGE;
--              spin_unlock(&sbinfo->stat_lock);
--      }
+-      kref_put(&cg->ref, release_css_group);
 -}
 -
--/*
-- * shmem_recalc_inode - recalculate the size of an inode
-- *
-- * @inode: inode to recalc
-- *
-- * We have to calculate the free blocks since the mm can drop
-- * undirtied hole pages behind our back.
-- *
-- * But normally   info->alloced == inode->i_mapping->nrpages + info->swapped
-- * So mm freed is info->alloced - (inode->i_mapping->nrpages + info->swapped)
-- *
-- * It has to be called with the spinlock held.
-- */
--static void shmem_recalc_inode(struct inode *inode)
+-static inline void put_css_group_taskexit(struct css_group *cg)
 -{
--      struct shmem_inode_info *info = SHMEM_I(inode);
--      long freed;
--
--      freed = info->alloced - info->swapped - inode->i_mapping->nrpages;
--      if (freed > 0) {
--              info->alloced -= freed;
--              shmem_unacct_blocks(info->flags, freed);
--              shmem_free_blocks(inode, freed);
--      }
+-      kref_put(&cg->ref, release_css_group_taskexit);
 -}
 -
 -/*
-- * shmem_swp_entry - find the swap vector position in the info structure
-- *
-- * @info:  info structure for the inode
-- * @index: index of the page to find
-- * @page:  optional page to add to the structure. Has to be preset to
-- *         all zeros
-- *
-- * If there is no space allocated yet it will return NULL when
-- * page is NULL, else it will use the page for the needed block,
-- * setting it to NULL on return to indicate that it has been used.
-- *
-- * The swap vector is organized the following way:
+- * find_existing_css_group() is a helper for
+- * find_css_group(), and checks to see whether an existing
+- * css_group is suitable. This currently walks a linked-list for
+- * simplicity; a later patch will use a hash table for better
+- * performance
 - *
-- * There are SHMEM_NR_DIRECT entries directly stored in the
-- * shmem_inode_info structure. So small files do not need an addional
-- * allocation.
+- * oldcg: the container group that we're using before the container
+- * transition
 - *
-- * For pages with index > SHMEM_NR_DIRECT there is the pointer
-- * i_indirect which points to a page which holds in the first half
-- * doubly indirect blocks, in the second half triple indirect blocks:
+- * cont: the container that we're moving into
 - *
-- * For an artificial ENTRIES_PER_PAGE = 4 this would lead to the
-- * following layout (for SHMEM_NR_DIRECT == 16):
-- *
-- * i_indirect -> dir --> 16-19
-- *          |      +-> 20-23
-- *          |
-- *          +-->dir2 --> 24-27
-- *          |        +-> 28-31
-- *          |        +-> 32-35
-- *          |        +-> 36-39
-- *          |
-- *          +-->dir3 --> 40-43
-- *                   +-> 44-47
-- *                   +-> 48-51
-- *                   +-> 52-55
+- * template: location in which to build the desired set of subsystem
+- * state objects for the new container group
 - */
--static swp_entry_t *shmem_swp_entry(struct shmem_inode_info *info, unsigned long index, struct page **page)
+-
+-static struct css_group *find_existing_css_group(
+-      struct css_group *oldcg,
+-      struct container *cont,
+-      struct container_subsys_state *template[])
 -{
--      unsigned long offset;
--      struct page **dir;
--      struct page *subdir;
--
--      if (index < SHMEM_NR_DIRECT) {
--              shmem_swp_balance_unmap();
--              return info->i_direct+index;
--      }
--      if (!info->i_indirect) {
--              if (page) {
--                      info->i_indirect = *page;
--                      *page = NULL;
--              }
--              return NULL;                    /* need another page */
--      }
--
--      index -= SHMEM_NR_DIRECT;
--      offset = index % ENTRIES_PER_PAGE;
--      index /= ENTRIES_PER_PAGE;
--      dir = shmem_dir_map(info->i_indirect);
--
--      if (index >= ENTRIES_PER_PAGE/2) {
--              index -= ENTRIES_PER_PAGE/2;
--              dir += ENTRIES_PER_PAGE/2 + index/ENTRIES_PER_PAGE;
--              index %= ENTRIES_PER_PAGE;
--              subdir = *dir;
--              if (!subdir) {
--                      if (page) {
--                              *dir = *page;
--                              *page = NULL;
--                      }
--                      shmem_dir_unmap(dir);
--                      return NULL;            /* need another page */
+-      int i;
+-      struct containerfs_root *root = cont->root;
+-      struct list_head *l = &init_css_group.list;
+-
+-      /* Built the set of subsystem state objects that we want to
+-       * see in the new css_group */
+-      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
+-              if (root->subsys_bits & (1ull << i)) {
+-                      /* Subsystem is in this hierarchy. So we want
+-                       * the subsystem state from the new
+-                       * container */
+-                      template[i] = cont->subsys[i];
+-              } else {
+-                      /* Subsystem is not in this hierarchy, so we
+-                       * don't want to change the subsystem state */
+-                      template[i] = oldcg->subsys[i];
 -              }
--              shmem_dir_unmap(dir);
--              dir = shmem_dir_map(subdir);
 -      }
 -
--      dir += index;
--      subdir = *dir;
--      if (!subdir) {
--              if (!page || !(subdir = *page)) {
--                      shmem_dir_unmap(dir);
--                      return NULL;            /* need a page */
--              }
--              *dir = subdir;
--              *page = NULL;
--      }
--      shmem_dir_unmap(dir);
--      return shmem_swp_map(subdir) + offset;
--}
+-      /* Look through existing container groups to find one to reuse */
+-      do {
+-              struct css_group *cg =
+-                      list_entry(l, struct css_group, list);
 -
--static void shmem_swp_set(struct shmem_inode_info *info, swp_entry_t *entry, unsigned long value)
--{
--      long incdec = value? 1: -1;
+-              if (!memcmp(template, cg->subsys, sizeof(cg->subsys))) {
+-                      /* All subsystems matched */
+-                      return cg;
+-              }
+-              /* Try the next container group */
+-              l = l->next;
+-      } while (l != &init_css_group.list);
 -
--      entry->val = value;
--      info->swapped += incdec;
--      if ((unsigned long)(entry - info->i_direct) >= SHMEM_NR_DIRECT) {
--              struct page *page = kmap_atomic_to_page(entry);
--              set_page_private(page, page_private(page) + incdec);
--      }
+-      /* No existing container group matched */
+-      return NULL;
 -}
 -
 -/*
-- * shmem_swp_alloc - get the position of the swap entry for the page.
-- *                   If it does not exist allocate the entry.
-- *
-- * @info:     info structure for the inode
-- * @index:    index of the page to find
-- * @sgp:      check and recheck i_size? skip allocation?
+- * allocate_cg_links() allocates "count" cg_container_link structures
+- * and chains them on tmp through their cont_link_list fields. Returns 0 on
+- * success or a negative error
 - */
--static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long index, enum sgp_type sgp)
--{
--      struct inode *inode = &info->vfs_inode;
--      struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
--      struct page *page = NULL;
--      swp_entry_t *entry;
--
--      if (sgp != SGP_WRITE &&
--          ((loff_t) index << PAGE_CACHE_SHIFT) >= i_size_read(inode))
--              return ERR_PTR(-EINVAL);
 -
--      while (!(entry = shmem_swp_entry(info, index, &page))) {
--              if (sgp == SGP_READ)
--                      return shmem_swp_map(ZERO_PAGE(0));
--              /*
--               * Test free_blocks against 1 not 0, since we have 1 data
--               * page (and perhaps indirect index pages) yet to allocate:
--               * a waste to allocate index if we cannot allocate data.
--               */
--              if (sbinfo->max_blocks) {
--                      spin_lock(&sbinfo->stat_lock);
--                      if (sbinfo->free_blocks <= 1) {
--                              spin_unlock(&sbinfo->stat_lock);
--                              return ERR_PTR(-ENOSPC);
+-static int allocate_cg_links(int count, struct list_head *tmp)
+-{
+-      struct cg_container_link *link;
+-      int i;
+-      INIT_LIST_HEAD(tmp);
+-      for (i = 0; i < count; i++) {
+-              link = kmalloc(sizeof(*link), GFP_KERNEL);
+-              if (!link) {
+-                      while (!list_empty(tmp)) {
+-                              link = list_entry(tmp->next,
+-                                                struct cg_container_link,
+-                                                cont_link_list);
+-                              list_del(&link->cont_link_list);
+-                              kfree(link);
 -                      }
--                      sbinfo->free_blocks--;
--                      inode->i_blocks += BLOCKS_PER_PAGE;
--                      spin_unlock(&sbinfo->stat_lock);
--              }
--
--              spin_unlock(&info->lock);
--              page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping) | __GFP_ZERO);
--              if (page)
--                      set_page_private(page, 0);
--              spin_lock(&info->lock);
--
--              if (!page) {
--                      shmem_free_blocks(inode, 1);
--                      return ERR_PTR(-ENOMEM);
--              }
--              if (sgp != SGP_WRITE &&
--                  ((loff_t) index << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
--                      entry = ERR_PTR(-EINVAL);
--                      break;
+-                      return -ENOMEM;
 -              }
--              if (info->next_index <= index)
--                      info->next_index = index + 1;
--      }
--      if (page) {
--              /* another task gave its page, or truncated the file */
--              shmem_free_blocks(inode, 1);
--              shmem_dir_free(page);
+-              list_add(&link->cont_link_list, tmp);
 -      }
--      if (info->next_index <= index && !IS_ERR(entry))
--              info->next_index = index + 1;
--      return entry;
+-      return 0;
 -}
 -
 -/*
-- * shmem_free_swp - free some swap entries in a directory
-- *
-- * @dir:        pointer to the directory
-- * @edir:       pointer after last entry of the directory
-- * @punch_lock: pointer to spinlock when needed for the holepunch case
-- */
--static int shmem_free_swp(swp_entry_t *dir, swp_entry_t *edir,
--                                              spinlock_t *punch_lock)
--{
--      spinlock_t *punch_unlock = NULL;
--      swp_entry_t *ptr;
--      int freed = 0;
--
--      for (ptr = dir; ptr < edir; ptr++) {
--              if (ptr->val) {
--                      if (unlikely(punch_lock)) {
--                              punch_unlock = punch_lock;
--                              punch_lock = NULL;
--                              spin_lock(punch_unlock);
--                              if (!ptr->val)
--                                      continue;
--                      }
--                      free_swap_and_cache(*ptr);
--                      *ptr = (swp_entry_t){0};
--                      freed++;
--              }
--      }
--      if (punch_unlock)
--              spin_unlock(punch_unlock);
--      return freed;
--}
--
--static int shmem_map_and_free_swp(struct page *subdir, int offset,
--              int limit, struct page ***dir, spinlock_t *punch_lock)
--{
--      swp_entry_t *ptr;
--      int freed = 0;
--
--      ptr = shmem_swp_map(subdir);
--      for (; offset < limit; offset += LATENCY_LIMIT) {
--              int size = limit - offset;
--              if (size > LATENCY_LIMIT)
--                      size = LATENCY_LIMIT;
--              freed += shmem_free_swp(ptr+offset, ptr+offset+size,
--                                                      punch_lock);
--              if (need_resched()) {
--                      shmem_swp_unmap(ptr);
--                      if (*dir) {
--                              shmem_dir_unmap(*dir);
--                              *dir = NULL;
--                      }
--                      cond_resched();
--                      ptr = shmem_swp_map(subdir);
--              }
--      }
--      shmem_swp_unmap(ptr);
--      return freed;
--}
+- * find_css_group() takes an existing container group and a
+- * container object, and returns a css_group object that's
+- * equivalent to the old group, but with the given container
+- * substituted into the appropriate hierarchy. Must be called with
+- * container_mutex held
+- */
 -
--static void shmem_free_pages(struct list_head *next)
+-static struct css_group *find_css_group(
+-      struct css_group *oldcg, struct container *cont)
 -{
--      struct page *page;
--      int freed = 0;
--
--      do {
--              page = container_of(next, struct page, lru);
--              next = next->next;
--              shmem_dir_free(page);
--              freed++;
--              if (freed >= LATENCY_LIMIT) {
--                      cond_resched();
--                      freed = 0;
--              }
--      } while (next);
--}
+-      struct css_group *res;
+-      struct container_subsys_state *template[CONTAINER_SUBSYS_COUNT];
+-      int i;
 -
--static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end)
--{
--      struct shmem_inode_info *info = SHMEM_I(inode);
--      unsigned long idx;
--      unsigned long size;
--      unsigned long limit;
--      unsigned long stage;
--      unsigned long diroff;
--      struct page **dir;
--      struct page *topdir;
--      struct page *middir;
--      struct page *subdir;
--      swp_entry_t *ptr;
--      LIST_HEAD(pages_to_free);
--      long nr_pages_to_free = 0;
--      long nr_swaps_freed = 0;
--      int offset;
--      int freed;
--      int punch_hole;
--      spinlock_t *needs_lock;
--      spinlock_t *punch_lock;
--      unsigned long upper_limit;
+-      struct list_head tmp_cg_links;
+-      struct cg_container_link *link;
 -
--      inode->i_ctime = inode->i_mtime = CURRENT_TIME;
--      idx = (start + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
--      if (idx >= info->next_index)
--              return;
+-      /* First see if we already have a container group that matches
+-       * the desired set */
+-      write_lock(&css_group_lock);
+-      res = find_existing_css_group(oldcg, cont, template);
+-      if (res)
+-              get_css_group(res);
+-      write_unlock(&css_group_lock);
 -
--      spin_lock(&info->lock);
--      info->flags |= SHMEM_TRUNCATE;
--      if (likely(end == (loff_t) -1)) {
--              limit = info->next_index;
--              upper_limit = SHMEM_MAX_INDEX;
--              info->next_index = idx;
--              needs_lock = NULL;
--              punch_hole = 0;
--      } else {
--              if (end + 1 >= inode->i_size) { /* we may free a little more */
--                      limit = (inode->i_size + PAGE_CACHE_SIZE - 1) >>
--                                                      PAGE_CACHE_SHIFT;
--                      upper_limit = SHMEM_MAX_INDEX;
--              } else {
--                      limit = (end + 1) >> PAGE_CACHE_SHIFT;
--                      upper_limit = limit;
--              }
--              needs_lock = &info->lock;
--              punch_hole = 1;
--      }
+-      if (res)
+-              return res;
 -
--      topdir = info->i_indirect;
--      if (topdir && idx <= SHMEM_NR_DIRECT && !punch_hole) {
--              info->i_indirect = NULL;
--              nr_pages_to_free++;
--              list_add(&topdir->lru, &pages_to_free);
--      }
--      spin_unlock(&info->lock);
+-      res = kmalloc(sizeof(*res), GFP_KERNEL);
+-      if (!res)
+-              return NULL;
 -
--      if (info->swapped && idx < SHMEM_NR_DIRECT) {
--              ptr = info->i_direct;
--              size = limit;
--              if (size > SHMEM_NR_DIRECT)
--                      size = SHMEM_NR_DIRECT;
--              nr_swaps_freed = shmem_free_swp(ptr+idx, ptr+size, needs_lock);
+-      /* Allocate all the cg_container_link objects that we'll need */
+-      if (allocate_cg_links(root_count, &tmp_cg_links) < 0) {
+-              kfree(res);
+-              return NULL;
 -      }
 -
--      /*
--       * If there are no indirect blocks or we are punching a hole
--       * below indirect blocks, nothing to be done.
--       */
--      if (!topdir || limit <= SHMEM_NR_DIRECT)
--              goto done2;
+-      kref_init(&res->ref);
+-      INIT_LIST_HEAD(&res->cg_links);
+-      INIT_LIST_HEAD(&res->tasks);
 -
--      /*
--       * The truncation case has already dropped info->lock, and we're safe
--       * because i_size and next_index have already been lowered, preventing
--       * access beyond.  But in the punch_hole case, we still need to take
--       * the lock when updating the swap directory, because there might be
--       * racing accesses by shmem_getpage(SGP_CACHE), shmem_unuse_inode or
--       * shmem_writepage.  However, whenever we find we can remove a whole
--       * directory page (not at the misaligned start or end of the range),
--       * we first NULLify its pointer in the level above, and then have no
--       * need to take the lock when updating its contents: needs_lock and
--       * punch_lock (either pointing to info->lock or NULL) manage this.
--       */
+-      /* Copy the set of subsystem state objects generated in
+-       * find_existing_css_group() */
+-      memcpy(res->subsys, template, sizeof(res->subsys));
 -
--      upper_limit -= SHMEM_NR_DIRECT;
--      limit -= SHMEM_NR_DIRECT;
--      idx = (idx > SHMEM_NR_DIRECT)? (idx - SHMEM_NR_DIRECT): 0;
--      offset = idx % ENTRIES_PER_PAGE;
--      idx -= offset;
--
--      dir = shmem_dir_map(topdir);
--      stage = ENTRIES_PER_PAGEPAGE/2;
--      if (idx < ENTRIES_PER_PAGEPAGE/2) {
--              middir = topdir;
--              diroff = idx/ENTRIES_PER_PAGE;
--      } else {
--              dir += ENTRIES_PER_PAGE/2;
--              dir += (idx - ENTRIES_PER_PAGEPAGE/2)/ENTRIES_PER_PAGEPAGE;
--              while (stage <= idx)
--                      stage += ENTRIES_PER_PAGEPAGE;
--              middir = *dir;
--              if (*dir) {
--                      diroff = ((idx - ENTRIES_PER_PAGEPAGE/2) %
--                              ENTRIES_PER_PAGEPAGE) / ENTRIES_PER_PAGE;
--                      if (!diroff && !offset && upper_limit >= stage) {
--                              if (needs_lock) {
--                                      spin_lock(needs_lock);
--                                      *dir = NULL;
--                                      spin_unlock(needs_lock);
--                                      needs_lock = NULL;
--                              } else
--                                      *dir = NULL;
--                              nr_pages_to_free++;
--                              list_add(&middir->lru, &pages_to_free);
--                      }
--                      shmem_dir_unmap(dir);
--                      dir = shmem_dir_map(middir);
--              } else {
--                      diroff = 0;
--                      offset = 0;
--                      idx = stage;
--              }
--      }
--
--      for (; idx < limit; idx += ENTRIES_PER_PAGE, diroff++) {
--              if (unlikely(idx == stage)) {
--                      shmem_dir_unmap(dir);
--                      dir = shmem_dir_map(topdir) +
--                          ENTRIES_PER_PAGE/2 + idx/ENTRIES_PER_PAGEPAGE;
--                      while (!*dir) {
--                              dir++;
--                              idx += ENTRIES_PER_PAGEPAGE;
--                              if (idx >= limit)
--                                      goto done1;
--                      }
--                      stage = idx + ENTRIES_PER_PAGEPAGE;
--                      middir = *dir;
--                      if (punch_hole)
--                              needs_lock = &info->lock;
--                      if (upper_limit >= stage) {
--                              if (needs_lock) {
--                                      spin_lock(needs_lock);
--                                      *dir = NULL;
--                                      spin_unlock(needs_lock);
--                                      needs_lock = NULL;
--                              } else
--                                      *dir = NULL;
--                              nr_pages_to_free++;
--                              list_add(&middir->lru, &pages_to_free);
--                      }
--                      shmem_dir_unmap(dir);
--                      cond_resched();
--                      dir = shmem_dir_map(middir);
--                      diroff = 0;
--              }
--              punch_lock = needs_lock;
--              subdir = dir[diroff];
--              if (subdir && !offset && upper_limit-idx >= ENTRIES_PER_PAGE) {
--                      if (needs_lock) {
--                              spin_lock(needs_lock);
--                              dir[diroff] = NULL;
--                              spin_unlock(needs_lock);
--                              punch_lock = NULL;
--                      } else
--                              dir[diroff] = NULL;
--                      nr_pages_to_free++;
--                      list_add(&subdir->lru, &pages_to_free);
--              }
--              if (subdir && page_private(subdir) /* has swap entries */) {
--                      size = limit - idx;
--                      if (size > ENTRIES_PER_PAGE)
--                              size = ENTRIES_PER_PAGE;
--                      freed = shmem_map_and_free_swp(subdir,
--                                      offset, size, &dir, punch_lock);
--                      if (!dir)
--                              dir = shmem_dir_map(middir);
--                      nr_swaps_freed += freed;
--                      if (offset || punch_lock) {
--                              spin_lock(&info->lock);
--                              set_page_private(subdir,
--                                      page_private(subdir) - freed);
--                              spin_unlock(&info->lock);
--                      } else
--                              BUG_ON(page_private(subdir) != freed);
--              }
--              offset = 0;
--      }
--done1:
--      shmem_dir_unmap(dir);
--done2:
--      if (inode->i_mapping->nrpages && (info->flags & SHMEM_PAGEIN)) {
+-      write_lock(&css_group_lock);
+-      /* Add reference counts and links from the new css_group. */
+-      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
+-              struct container *cont = res->subsys[i]->container;
+-              struct container_subsys *ss = subsys[i];
+-              atomic_inc(&cont->count);
 -              /*
--               * Call truncate_inode_pages again: racing shmem_unuse_inode
--               * may have swizzled a page in from swap since vmtruncate or
--               * generic_delete_inode did it, before we lowered next_index.
--               * Also, though shmem_getpage checks i_size before adding to
--               * cache, no recheck after: so fix the narrow window there too.
--               *
--               * Recalling truncate_inode_pages_range and unmap_mapping_range
--               * every time for punch_hole (which never got a chance to clear
--               * SHMEM_PAGEIN at the start of vmtruncate_range) is expensive,
--               * yet hardly ever necessary: try to optimize them out later.
+-               * We want to add a link once per container, so we
+-               * only do it for the first subsystem in each
+-               * hierarchy
 -               */
--              truncate_inode_pages_range(inode->i_mapping, start, end);
--              if (punch_hole)
--                      unmap_mapping_range(inode->i_mapping, start,
--                                                      end - start, 1);
+-              if (ss->root->subsys_list.next == &ss->sibling) {
+-                      BUG_ON(list_empty(&tmp_cg_links));
+-                      link = list_entry(tmp_cg_links.next,
+-                                        struct cg_container_link,
+-                                        cont_link_list);
+-                      list_del(&link->cont_link_list);
+-                      list_add(&link->cont_link_list, &cont->css_groups);
+-                      link->cg = res;
+-                      list_add(&link->cg_link_list, &res->cg_links);
+-              }
 -      }
--
--      spin_lock(&info->lock);
--      info->flags &= ~SHMEM_TRUNCATE;
--      info->swapped -= nr_swaps_freed;
--      if (nr_pages_to_free)
--              shmem_free_blocks(inode, nr_pages_to_free);
--      shmem_recalc_inode(inode);
--      spin_unlock(&info->lock);
--
--      /*
--       * Empty swap vector directory pages to be freed?
--       */
--      if (!list_empty(&pages_to_free)) {
--              pages_to_free.prev->next = NULL;
--              shmem_free_pages(pages_to_free.next);
+-      if (list_empty(&rootnode.subsys_list)) {
+-              link = list_entry(tmp_cg_links.next,
+-                                struct cg_container_link,
+-                                cont_link_list);
+-              list_del(&link->cont_link_list);
+-              list_add(&link->cont_link_list, &dummytop->css_groups);
+-              link->cg = res;
+-              list_add(&link->cg_link_list, &res->cg_links);
 -      }
--}
--
--static void shmem_truncate(struct inode *inode)
--{
--      shmem_truncate_range(inode, inode->i_size, (loff_t)-1);
--}
 -
--static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
--{
--      struct inode *inode = dentry->d_inode;
--      struct page *page = NULL;
--      int error;
+-      BUG_ON(!list_empty(&tmp_cg_links));
 -
--      if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
--              if (attr->ia_size < inode->i_size) {
--                      /*
--                       * If truncating down to a partial page, then
--                       * if that page is already allocated, hold it
--                       * in memory until the truncation is over, so
--                       * truncate_partial_page cannnot miss it were
--                       * it assigned to swap.
--                       */
--                      if (attr->ia_size & (PAGE_CACHE_SIZE-1)) {
--                              (void) shmem_getpage(inode,
--                                      attr->ia_size>>PAGE_CACHE_SHIFT,
--                                              &page, SGP_READ, NULL);
--                      }
--                      /*
--                       * Reset SHMEM_PAGEIN flag so that shmem_truncate can
--                       * detect if any pages might have been added to cache
--                       * after truncate_inode_pages.  But we needn't bother
--                       * if it's being fully truncated to zero-length: the
--                       * nrpages check is efficient enough in that case.
--                       */
--                      if (attr->ia_size) {
--                              struct shmem_inode_info *info = SHMEM_I(inode);
--                              spin_lock(&info->lock);
--                              info->flags &= ~SHMEM_PAGEIN;
--                              spin_unlock(&info->lock);
--                      }
--              }
--      }
+-      /* Link this container group into the list */
+-      list_add(&res->list, &init_css_group.list);
+-      css_group_count++;
+-      INIT_LIST_HEAD(&res->tasks);
+-      write_unlock(&css_group_lock);
 -
--      error = inode_change_ok(inode, attr);
--      if (!error)
--              error = inode_setattr(inode, attr);
--#ifdef CONFIG_TMPFS_POSIX_ACL
--      if (!error && (attr->ia_valid & ATTR_MODE))
--              error = generic_acl_chmod(inode, &shmem_acl_ops);
--#endif
--      if (page)
--              page_cache_release(page);
--      return error;
+-      return res;
 -}
 -
--static void shmem_delete_inode(struct inode *inode)
--{
--      struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
--      struct shmem_inode_info *info = SHMEM_I(inode);
+-/*
+- * There is one global container mutex. We also require taking
+- * task_lock() when dereferencing a task's container subsys pointers.
+- * See "The task_lock() exception", at the end of this comment.
+- *
+- * A task must hold container_mutex to modify containers.
+- *
+- * Any task can increment and decrement the count field without lock.
+- * So in general, code holding container_mutex can't rely on the count
+- * field not changing.  However, if the count goes to zero, then only
+- * attach_task() can increment it again.  Because a count of zero
+- * means that no tasks are currently attached, therefore there is no
+- * way a task attached to that container can fork (the other way to
+- * increment the count).  So code holding container_mutex can safely
+- * assume that if the count is zero, it will stay zero. Similarly, if
+- * a task holds container_mutex on a container with zero count, it
+- * knows that the container won't be removed, as container_rmdir()
+- * needs that mutex.
+- *
+- * The container_common_file_write handler for operations that modify
+- * the container hierarchy holds container_mutex across the entire operation,
+- * single threading all such container modifications across the system.
+- *
+- * The fork and exit callbacks container_fork() and container_exit(), don't
+- * (usually) take container_mutex.  These are the two most performance
+- * critical pieces of code here.  The exception occurs on container_exit(),
+- * when a task in a notify_on_release container exits.  Then container_mutex
+- * is taken, and if the container count is zero, a usermode call made
+- * to /sbin/container_release_agent with the name of the container (path
+- * relative to the root of container file system) as the argument.
+- *
+- * A container can only be deleted if both its 'count' of using tasks
+- * is zero, and its list of 'children' containers is empty.  Since all
+- * tasks in the system use _some_ container, and since there is always at
+- * least one task in the system (init, pid == 1), therefore, top_container
+- * always has either children containers and/or using tasks.  So we don't
+- * need a special hack to ensure that top_container cannot be deleted.
+- *
+- *    The task_lock() exception
+- *
+- * The need for this exception arises from the action of
+- * attach_task(), which overwrites one tasks container pointer with
+- * another.  It does so using container_mutexe, however there are
+- * several performance critical places that need to reference
+- * task->container without the expense of grabbing a system global
+- * mutex.  Therefore except as noted below, when dereferencing or, as
+- * in attach_task(), modifying a task'ss container pointer we use
+- * task_lock(), which acts on a spinlock (task->alloc_lock) already in
+- * the task_struct routinely used for such matters.
+- *
+- * P.S.  One more locking exception.  RCU is used to guard the
+- * update of a tasks container pointer by attach_task()
+- */
 -
--      if (inode->i_op->truncate == shmem_truncate) {
--              truncate_inode_pages(inode->i_mapping, 0);
--              shmem_unacct_size(info->flags, inode->i_size);
--              inode->i_size = 0;
--              shmem_truncate(inode);
--              if (!list_empty(&info->swaplist)) {
--                      spin_lock(&shmem_swaplist_lock);
--                      list_del_init(&info->swaplist);
--                      spin_unlock(&shmem_swaplist_lock);
--              }
--      }
--      BUG_ON(inode->i_blocks);
--      if (sbinfo->max_inodes) {
--              spin_lock(&sbinfo->stat_lock);
--              sbinfo->free_inodes++;
--              spin_unlock(&sbinfo->stat_lock);
--      }
--      clear_inode(inode);
--}
+-/**
+- * container_lock - lock out any changes to container structures
+- *
+- */
 -
--static inline int shmem_find_swp(swp_entry_t entry, swp_entry_t *dir, swp_entry_t *edir)
+-void container_lock(void)
 -{
--      swp_entry_t *ptr;
--
--      for (ptr = dir; ptr < edir; ptr++) {
--              if (ptr->val == entry.val)
--                      return ptr - dir;
--      }
--      return -1;
+-      mutex_lock(&container_mutex);
 -}
 -
--static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, struct page *page)
+-/**
+- * container_unlock - release lock on container changes
+- *
+- * Undo the lock taken in a previous container_lock() call.
+- */
+-
+-void container_unlock(void)
 -{
--      struct inode *inode;
--      unsigned long idx;
--      unsigned long size;
--      unsigned long limit;
--      unsigned long stage;
--      struct page **dir;
--      struct page *subdir;
--      swp_entry_t *ptr;
--      int offset;
--
--      idx = 0;
--      ptr = info->i_direct;
--      spin_lock(&info->lock);
--      limit = info->next_index;
--      size = limit;
--      if (size > SHMEM_NR_DIRECT)
--              size = SHMEM_NR_DIRECT;
--      offset = shmem_find_swp(entry, ptr, ptr+size);
--      if (offset >= 0) {
--              shmem_swp_balance_unmap();
--              goto found;
--      }
--      if (!info->i_indirect)
--              goto lost2;
--
--      dir = shmem_dir_map(info->i_indirect);
--      stage = SHMEM_NR_DIRECT + ENTRIES_PER_PAGEPAGE/2;
--
--      for (idx = SHMEM_NR_DIRECT; idx < limit; idx += ENTRIES_PER_PAGE, dir++) {
--              if (unlikely(idx == stage)) {
--                      shmem_dir_unmap(dir-1);
--                      dir = shmem_dir_map(info->i_indirect) +
--                          ENTRIES_PER_PAGE/2 + idx/ENTRIES_PER_PAGEPAGE;
--                      while (!*dir) {
--                              dir++;
--                              idx += ENTRIES_PER_PAGEPAGE;
--                              if (idx >= limit)
--                                      goto lost1;
--                      }
--                      stage = idx + ENTRIES_PER_PAGEPAGE;
--                      subdir = *dir;
--                      shmem_dir_unmap(dir);
--                      dir = shmem_dir_map(subdir);
--              }
--              subdir = *dir;
--              if (subdir && page_private(subdir)) {
--                      ptr = shmem_swp_map(subdir);
--                      size = limit - idx;
--                      if (size > ENTRIES_PER_PAGE)
--                              size = ENTRIES_PER_PAGE;
--                      offset = shmem_find_swp(entry, ptr, ptr+size);
--                      if (offset >= 0) {
--                              shmem_dir_unmap(dir);
--                              goto found;
--                      }
--                      shmem_swp_unmap(ptr);
--              }
--      }
--lost1:
--      shmem_dir_unmap(dir-1);
--lost2:
--      spin_unlock(&info->lock);
--      return 0;
--found:
--      idx += offset;
--      inode = &info->vfs_inode;
--      if (move_from_swap_cache(page, idx, inode->i_mapping) == 0) {
--              info->flags |= SHMEM_PAGEIN;
--              shmem_swp_set(info, ptr + offset, 0);
--      }
--      shmem_swp_unmap(ptr);
--      spin_unlock(&info->lock);
--      /*
--       * Decrement swap count even when the entry is left behind:
--       * try_to_unuse will skip over mms, then reincrement count.
--       */
--      swap_free(entry);
--      return 1;
+-      mutex_unlock(&container_mutex);
 -}
 -
 -/*
-- * shmem_unuse() search for an eventually swapped out shmem page.
+- * A couple of forward declarations required, due to cyclic reference loop:
+- * container_mkdir -> container_create -> container_populate_dir ->
+- * container_add_file -> container_create_file -> container_dir_inode_operations
+- * -> container_mkdir.
 - */
--int shmem_unuse(swp_entry_t entry, struct page *page)
--{
--      struct list_head *p, *next;
--      struct shmem_inode_info *info;
--      int found = 0;
 -
--      spin_lock(&shmem_swaplist_lock);
--      list_for_each_safe(p, next, &shmem_swaplist) {
--              info = list_entry(p, struct shmem_inode_info, swaplist);
--              if (!info->swapped)
--                      list_del_init(&info->swaplist);
--              else if (shmem_unuse_inode(info, entry, page)) {
--                      /* move head to start search for next from here */
--                      list_move_tail(&shmem_swaplist, &info->swaplist);
--                      found = 1;
--                      break;
--              }
--      }
--      spin_unlock(&shmem_swaplist_lock);
--      return found;
--}
+-static int container_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+-static int container_rmdir(struct inode *unused_dir, struct dentry *dentry);
+-static int container_populate_dir(struct container *cont);
+-static struct inode_operations container_dir_inode_operations;
+-static struct file_operations proc_containerstats_operations;
 -
--/*
-- * Move the page from the page cache to the swap cache.
-- */
--static int shmem_writepage(struct page *page, struct writeback_control *wbc)
+-static struct inode *container_new_inode(mode_t mode, struct super_block *sb)
 -{
--      struct shmem_inode_info *info;
--      swp_entry_t *entry, swap;
--      struct address_space *mapping;
--      unsigned long index;
--      struct inode *inode;
+-      struct inode *inode = new_inode(sb);
+-      static struct backing_dev_info container_backing_dev_info = {
+-              .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+-      };
 -
--      BUG_ON(!PageLocked(page));
--      /*
--       * shmem_backing_dev_info's capabilities prevent regular writeback or
--       * sync from ever calling shmem_writepage; but a stacking filesystem
--       * may use the ->writepage of its underlying filesystem, in which case
--       * we want to do nothing when that underlying filesystem is tmpfs
--       * (writing out to swap is useful as a response to memory pressure, but
--       * of no use to stabilize the data) - just redirty the page, unlock it
--       * and claim success in this case.  AOP_WRITEPAGE_ACTIVATE, and the
--       * page_mapped check below, must be avoided unless we're in reclaim.
--       */
--      if (!wbc->for_reclaim) {
--              set_page_dirty(page);
--              unlock_page(page);
--              return 0;
--      }
--      BUG_ON(page_mapped(page));
--
--      mapping = page->mapping;
--      index = page->index;
--      inode = mapping->host;
--      info = SHMEM_I(inode);
--      if (info->flags & VM_LOCKED)
--              goto redirty;
--      swap = get_swap_page();
--      if (!swap.val)
--              goto redirty;
--
--      spin_lock(&info->lock);
--      shmem_recalc_inode(inode);
--      if (index >= info->next_index) {
--              BUG_ON(!(info->flags & SHMEM_TRUNCATE));
--              goto unlock;
--      }
--      entry = shmem_swp_entry(info, index, NULL);
--      BUG_ON(!entry);
--      BUG_ON(entry->val);
--
--      if (move_to_swap_cache(page, swap) == 0) {
--              shmem_swp_set(info, entry, swap.val);
--              shmem_swp_unmap(entry);
--              spin_unlock(&info->lock);
--              if (list_empty(&info->swaplist)) {
--                      spin_lock(&shmem_swaplist_lock);
--                      /* move instead of add in case we're racing */
--                      list_move_tail(&info->swaplist, &shmem_swaplist);
--                      spin_unlock(&shmem_swaplist_lock);
--              }
--              unlock_page(page);
--              return 0;
+-      if (inode) {
+-              inode->i_mode = mode;
+-              inode->i_uid = current->fsuid;
+-              inode->i_gid = current->fsgid;
+-              inode->i_blocks = 0;
+-              inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+-              inode->i_mapping->backing_dev_info = &container_backing_dev_info;
 -      }
--
--      shmem_swp_unmap(entry);
--unlock:
--      spin_unlock(&info->lock);
--      swap_free(swap);
--redirty:
--      set_page_dirty(page);
--      return AOP_WRITEPAGE_ACTIVATE;  /* Return with the page locked */
+-      return inode;
 -}
 -
--#ifdef CONFIG_NUMA
--static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_nodes)
+-static void container_diput(struct dentry *dentry, struct inode *inode)
 -{
--      char *nodelist = strchr(value, ':');
--      int err = 1;
--
--      if (nodelist) {
--              /* NUL-terminate policy string */
--              *nodelist++ = '\0';
--              if (nodelist_parse(nodelist, *policy_nodes))
--                      goto out;
--              if (!nodes_subset(*policy_nodes, node_online_map))
--                      goto out;
--      }
--      if (!strcmp(value, "default")) {
--              *policy = MPOL_DEFAULT;
--              /* Don't allow a nodelist */
--              if (!nodelist)
--                      err = 0;
--      } else if (!strcmp(value, "prefer")) {
--              *policy = MPOL_PREFERRED;
--              /* Insist on a nodelist of one node only */
--              if (nodelist) {
--                      char *rest = nodelist;
--                      while (isdigit(*rest))
--                              rest++;
--                      if (!*rest)
--                              err = 0;
--              }
--      } else if (!strcmp(value, "bind")) {
--              *policy = MPOL_BIND;
--              /* Insist on a nodelist */
--              if (nodelist)
--                      err = 0;
--      } else if (!strcmp(value, "interleave")) {
--              *policy = MPOL_INTERLEAVE;
--              /* Default to nodes online if no nodelist */
--              if (!nodelist)
--                      *policy_nodes = node_online_map;
--              err = 0;
+-      /* is dentry a directory ? if so, kfree() associated container */
+-      if (S_ISDIR(inode->i_mode)) {
+-              struct container *cont = dentry->d_fsdata;
+-              BUG_ON(!(container_is_removed(cont)));
+-              kfree(cont);
 -      }
--out:
--      /* Restore string for error message */
--      if (nodelist)
--              *--nodelist = ':';
--      return err;
+-      iput(inode);
 -}
 -
--static struct page *shmem_swapin_async(struct shared_policy *p,
--                                     swp_entry_t entry, unsigned long idx)
+-static struct dentry *container_get_dentry(struct dentry *parent,
+-                                         const char *name)
 -{
--      struct page *page;
--      struct vm_area_struct pvma;
--
--      /* Create a pseudo vma that just contains the policy */
--      memset(&pvma, 0, sizeof(struct vm_area_struct));
--      pvma.vm_end = PAGE_SIZE;
--      pvma.vm_pgoff = idx;
--      pvma.vm_policy = mpol_shared_policy_lookup(p, idx);
--      page = read_swap_cache_async(entry, &pvma, 0);
--      mpol_free(pvma.vm_policy);
--      return page;
+-      struct dentry *d = lookup_one_len(name, parent, strlen(name));
+-      static struct dentry_operations container_dops = {
+-              .d_iput = container_diput,
+-      };
+-
+-      if (!IS_ERR(d))
+-              d->d_op = &container_dops;
+-      return d;
 -}
 -
--struct page *shmem_swapin(struct shmem_inode_info *info, swp_entry_t entry,
--                        unsigned long idx)
+-static void remove_dir(struct dentry *d)
 -{
--      struct shared_policy *p = &info->policy;
--      int i, num;
--      struct page *page;
--      unsigned long offset;
+-      struct dentry *parent = dget(d->d_parent);
 -
--      num = valid_swaphandles(entry, &offset);
--      for (i = 0; i < num; offset++, i++) {
--              page = shmem_swapin_async(p,
--                              swp_entry(swp_type(entry), offset), idx);
--              if (!page)
--                      break;
--              page_cache_release(page);
--      }
--      lru_add_drain();        /* Push any new pages onto the LRU now */
--      return shmem_swapin_async(p, entry, idx);
+-      d_delete(d);
+-      simple_rmdir(parent->d_inode, d);
+-      dput(parent);
 -}
 -
--static struct page *
--shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info,
--               unsigned long idx)
+-static void container_clear_directory(struct dentry *dentry)
 -{
--      struct vm_area_struct pvma;
--      struct page *page;
+-      struct list_head *node;
 -
--      memset(&pvma, 0, sizeof(struct vm_area_struct));
--      pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx);
--      pvma.vm_pgoff = idx;
--      pvma.vm_end = PAGE_SIZE;
--      page = alloc_page_vma(gfp | __GFP_ZERO, &pvma, 0);
--      mpol_free(pvma.vm_policy);
--      return page;
--}
--#else
--static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_nodes)
--{
--      return 1;
+-      BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
+-      spin_lock(&dcache_lock);
+-      node = dentry->d_subdirs.next;
+-      while (node != &dentry->d_subdirs) {
+-              struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
+-              list_del_init(node);
+-              if (d->d_inode) {
+-                      /* This should never be called on a container
+-                       * directory with child containers */
+-                      BUG_ON(d->d_inode->i_mode & S_IFDIR);
+-                      d = dget_locked(d);
+-                      spin_unlock(&dcache_lock);
+-                      d_delete(d);
+-                      simple_unlink(dentry->d_inode, d);
+-                      dput(d);
+-                      spin_lock(&dcache_lock);
+-              }
+-              node = dentry->d_subdirs.next;
+-      }
+-      spin_unlock(&dcache_lock);
 -}
 -
--static inline struct page *
--shmem_swapin(struct shmem_inode_info *info,swp_entry_t entry,unsigned long idx)
+-/*
+- * NOTE : the dentry must have been dget()'ed
+- */
+-static void container_d_remove_dir(struct dentry *dentry)
 -{
--      swapin_readahead(entry, 0, NULL);
--      return read_swap_cache_async(entry, NULL, 0);
--}
+-      container_clear_directory(dentry);
 -
--static inline struct page *
--shmem_alloc_page(gfp_t gfp,struct shmem_inode_info *info, unsigned long idx)
--{
--      return alloc_page(gfp | __GFP_ZERO);
+-      spin_lock(&dcache_lock);
+-      list_del_init(&dentry->d_u.d_child);
+-      spin_unlock(&dcache_lock);
+-      remove_dir(dentry);
 -}
--#endif
 -
--/*
-- * shmem_getpage - either get the page from swap or allocate a new one
-- *
-- * If we allocate a new one we do not mark it dirty. That's up to the
-- * vm. If we swap it in we mark it dirty since we also free the swap
-- * entry since a page cannot live in both the swap and page cache
-- */
--static int shmem_getpage(struct inode *inode, unsigned long idx,
--                      struct page **pagep, enum sgp_type sgp, int *type)
+-static int rebind_subsystems(struct containerfs_root *root,
+-                            unsigned long final_bits)
 -{
--      struct address_space *mapping = inode->i_mapping;
--      struct shmem_inode_info *info = SHMEM_I(inode);
--      struct shmem_sb_info *sbinfo;
--      struct page *filepage = *pagep;
--      struct page *swappage;
--      swp_entry_t *entry;
--      swp_entry_t swap;
--      int error;
+-      unsigned long added_bits, removed_bits;
+-      struct container *cont = &root->top_container;
+-      int i;
 -
--      if (idx >= SHMEM_MAX_INDEX)
--              return -EFBIG;
--      /*
--       * Normally, filepage is NULL on entry, and either found
--       * uptodate immediately, or allocated and zeroed, or read
--       * in under swappage, which is then assigned to filepage.
--       * But shmem_prepare_write passes in a locked filepage,
--       * which may be found not uptodate by other callers too,
--       * and may need to be copied from the swappage read in.
--       */
--repeat:
--      if (!filepage)
--              filepage = find_lock_page(mapping, idx);
--      if (filepage && PageUptodate(filepage))
--              goto done;
--      error = 0;
--      if (sgp == SGP_QUICK)
--              goto failed;
--
--      spin_lock(&info->lock);
--      shmem_recalc_inode(inode);
--      entry = shmem_swp_alloc(info, idx, sgp);
--      if (IS_ERR(entry)) {
--              spin_unlock(&info->lock);
--              error = PTR_ERR(entry);
--              goto failed;
--      }
--      swap = *entry;
--
--      if (swap.val) {
--              /* Look it up and read it in.. */
--              swappage = lookup_swap_cache(swap);
--              if (!swappage) {
--                      shmem_swp_unmap(entry);
--                      /* here we actually do the io */
--                      if (type && *type == VM_FAULT_MINOR) {
--                              __count_vm_event(PGMAJFAULT);
--                              *type = VM_FAULT_MAJOR;
--                      }
--                      spin_unlock(&info->lock);
--                      swappage = shmem_swapin(info, swap, idx);
--                      if (!swappage) {
--                              spin_lock(&info->lock);
--                              entry = shmem_swp_alloc(info, idx, sgp);
--                              if (IS_ERR(entry))
--                                      error = PTR_ERR(entry);
--                              else {
--                                      if (entry->val == swap.val)
--                                              error = -ENOMEM;
--                                      shmem_swp_unmap(entry);
--                              }
--                              spin_unlock(&info->lock);
--                              if (error)
--                                      goto failed;
--                              goto repeat;
--                      }
--                      wait_on_page_locked(swappage);
--                      page_cache_release(swappage);
--                      goto repeat;
+-      removed_bits = root->subsys_bits & ~final_bits;
+-      added_bits = final_bits & ~root->subsys_bits;
+-      /* Check that any added subsystems are currently free */
+-      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
+-              unsigned long long bit = 1ull << i;
+-              struct container_subsys *ss = subsys[i];
+-              if (!(bit & added_bits))
+-                      continue;
+-              if (ss->root != &rootnode) {
+-                      /* Subsystem isn't free */
+-                      return -EBUSY;
 -              }
+-      }
 -
--              /* We have to do this with page locked to prevent races */
--              if (TestSetPageLocked(swappage)) {
--                      shmem_swp_unmap(entry);
--                      spin_unlock(&info->lock);
--                      wait_on_page_locked(swappage);
--                      page_cache_release(swappage);
--                      goto repeat;
--              }
--              if (PageWriteback(swappage)) {
--                      shmem_swp_unmap(entry);
--                      spin_unlock(&info->lock);
--                      wait_on_page_writeback(swappage);
--                      unlock_page(swappage);
--                      page_cache_release(swappage);
--                      goto repeat;
--              }
--              if (!PageUptodate(swappage)) {
--                      shmem_swp_unmap(entry);
--                      spin_unlock(&info->lock);
--                      unlock_page(swappage);
--                      page_cache_release(swappage);
--                      error = -EIO;
--                      goto failed;
--              }
+-      /* Currently we don't handle adding/removing subsystems when
+-       * any subcontainers exist. This is theoretically supportable
+-       * but involves complex error handling, so it's being left until
+-       * later */
+-      if (!list_empty(&cont->children))
+-              return -EBUSY;
 -
--              if (filepage) {
--                      shmem_swp_set(info, entry, 0);
--                      shmem_swp_unmap(entry);
--                      delete_from_swap_cache(swappage);
--                      spin_unlock(&info->lock);
--                      copy_highpage(filepage, swappage);
--                      unlock_page(swappage);
--                      page_cache_release(swappage);
--                      flush_dcache_page(filepage);
--                      SetPageUptodate(filepage);
--                      set_page_dirty(filepage);
--                      swap_free(swap);
--              } else if (!(error = move_from_swap_cache(
--                              swappage, idx, mapping))) {
--                      info->flags |= SHMEM_PAGEIN;
--                      shmem_swp_set(info, entry, 0);
--                      shmem_swp_unmap(entry);
--                      spin_unlock(&info->lock);
--                      filepage = swappage;
--                      swap_free(swap);
+-      /* Process each subsystem */
+-      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
+-              struct container_subsys *ss = subsys[i];
+-              unsigned long bit = 1UL << i;
+-              if (bit & added_bits) {
+-                      /* We're binding this subsystem to this hierarchy */
+-                      BUG_ON(cont->subsys[i]);
+-                      BUG_ON(!dummytop->subsys[i]);
+-                      BUG_ON(dummytop->subsys[i]->container != dummytop);
+-                      cont->subsys[i] = dummytop->subsys[i];
+-                      cont->subsys[i]->container = cont;
+-                      list_add(&ss->sibling, &root->subsys_list);
+-                      rcu_assign_pointer(ss->root, root);
+-                      if (ss->bind)
+-                              ss->bind(ss, cont);
+-
+-              } else if (bit & removed_bits) {
+-                      /* We're removing this subsystem */
+-                      BUG_ON(cont->subsys[i] != dummytop->subsys[i]);
+-                      BUG_ON(cont->subsys[i]->container != cont);
+-                      if (ss->bind)
+-                              ss->bind(ss, dummytop);
+-                      dummytop->subsys[i]->container = dummytop;
+-                      cont->subsys[i] = NULL;
+-                      rcu_assign_pointer(subsys[i]->root, &rootnode);
+-                      list_del(&ss->sibling);
+-              } else if (bit & final_bits) {
+-                      /* Subsystem state should already exist */
+-                      BUG_ON(!cont->subsys[i]);
 -              } else {
--                      shmem_swp_unmap(entry);
--                      spin_unlock(&info->lock);
--                      unlock_page(swappage);
--                      page_cache_release(swappage);
--                      if (error == -ENOMEM) {
--                              /* let kswapd refresh zone for GFP_ATOMICs */
--                              congestion_wait(WRITE, HZ/50);
--                      }
--                      goto repeat;
--              }
--      } else if (sgp == SGP_READ && !filepage) {
--              shmem_swp_unmap(entry);
--              filepage = find_get_page(mapping, idx);
--              if (filepage &&
--                  (!PageUptodate(filepage) || TestSetPageLocked(filepage))) {
--                      spin_unlock(&info->lock);
--                      wait_on_page_locked(filepage);
--                      page_cache_release(filepage);
--                      filepage = NULL;
--                      goto repeat;
--              }
--              spin_unlock(&info->lock);
--      } else {
--              shmem_swp_unmap(entry);
--              sbinfo = SHMEM_SB(inode->i_sb);
--              if (sbinfo->max_blocks) {
--                      spin_lock(&sbinfo->stat_lock);
--                      if (sbinfo->free_blocks == 0 ||
--                          shmem_acct_block(info->flags)) {
--                              spin_unlock(&sbinfo->stat_lock);
--                              spin_unlock(&info->lock);
--                              error = -ENOSPC;
--                              goto failed;
--                      }
--                      sbinfo->free_blocks--;
--                      inode->i_blocks += BLOCKS_PER_PAGE;
--                      spin_unlock(&sbinfo->stat_lock);
--              } else if (shmem_acct_block(info->flags)) {
--                      spin_unlock(&info->lock);
--                      error = -ENOSPC;
--                      goto failed;
+-                      /* Subsystem state shouldn't exist */
+-                      BUG_ON(cont->subsys[i]);
 -              }
+-      }
+-      root->subsys_bits = final_bits;
+-      synchronize_rcu();
 -
--              if (!filepage) {
--                      spin_unlock(&info->lock);
--                      filepage = shmem_alloc_page(mapping_gfp_mask(mapping),
--                                                  info,
--                                                  idx);
--                      if (!filepage) {
--                              shmem_unacct_blocks(info->flags, 1);
--                              shmem_free_blocks(inode, 1);
--                              error = -ENOMEM;
--                              goto failed;
--                      }
+-      return 0;
+-}
 -
--                      spin_lock(&info->lock);
--                      entry = shmem_swp_alloc(info, idx, sgp);
--                      if (IS_ERR(entry))
--                              error = PTR_ERR(entry);
--                      else {
--                              swap = *entry;
--                              shmem_swp_unmap(entry);
--                      }
--                      if (error || swap.val || 0 != add_to_page_cache_lru(
--                                      filepage, mapping, idx, GFP_ATOMIC)) {
--                              spin_unlock(&info->lock);
--                              page_cache_release(filepage);
--                              shmem_unacct_blocks(info->flags, 1);
--                              shmem_free_blocks(inode, 1);
--                              filepage = NULL;
--                              if (error)
--                                      goto failed;
--                              goto repeat;
--                      }
--                      info->flags |= SHMEM_PAGEIN;
--              }
+-/*
+- * Release the last use of a hierarchy.  Will never be called when
+- * there are active subcontainers since each subcontainer bumps the
+- * value of sb->s_active.
+- */
+-static void container_put_super(struct super_block *sb)
+-{
+-      struct containerfs_root *root = sb->s_fs_info;
+-      struct container *cont = &root->top_container;
+-      int ret;
 -
--              info->alloced++;
--              spin_unlock(&info->lock);
--              flush_dcache_page(filepage);
--              SetPageUptodate(filepage);
--      }
--done:
--      if (*pagep != filepage) {
--              unlock_page(filepage);
--              *pagep = filepage;
--      }
--      return 0;
+-      root->sb = NULL;
+-      sb->s_fs_info = NULL;
+-
+-      mutex_lock(&container_mutex);
+-
+-      BUG_ON(root->number_of_containers != 1);
+-      BUG_ON(!list_empty(&cont->children));
+-      BUG_ON(!list_empty(&cont->sibling));
+-      BUG_ON(!root->subsys_bits);
+-
+-      /* Rebind all subsystems back to the default hierarchy */
+-      ret = rebind_subsystems(root, 0);
+-      BUG_ON(ret);
 -
--failed:
--      if (*pagep != filepage) {
--              unlock_page(filepage);
--              page_cache_release(filepage);
+-      write_lock(&css_group_lock);
+-      while (!list_empty(&cont->css_groups)) {
+-              struct cg_container_link *link;
+-              link = list_entry(cont->css_groups.next,
+-                                struct cg_container_link, cont_link_list);
+-              list_del(&link->cg_link_list);
+-              list_del(&link->cont_link_list);
+-              kfree(link);
 -      }
--      return error;
+-      write_unlock(&css_group_lock);
+-
+-      list_del(&root->root_list);
+-      root_count--;
+-      kfree(root);
+-      mutex_unlock(&container_mutex);
 -}
 -
--static struct page *shmem_nopage(struct vm_area_struct *vma,
--                               unsigned long address, int *type)
+-static int container_show_options(struct seq_file *seq, struct vfsmount *vfs)
 -{
--      struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
--      struct page *page = NULL;
--      unsigned long idx;
--      int error;
--
--      idx = (address - vma->vm_start) >> PAGE_SHIFT;
--      idx += vma->vm_pgoff;
--      idx >>= PAGE_CACHE_SHIFT - PAGE_SHIFT;
--      if (((loff_t) idx << PAGE_CACHE_SHIFT) >= i_size_read(inode))
--              return NOPAGE_SIGBUS;
--
--      error = shmem_getpage(inode, idx, &page, SGP_CACHE, type);
--      if (error)
--              return (error == -ENOMEM)? NOPAGE_OOM: NOPAGE_SIGBUS;
+-      struct containerfs_root *root = vfs->mnt_sb->s_fs_info;
+-      struct container_subsys *ss;
 -
--      mark_page_accessed(page);
--      return page;
+-      for_each_subsys(root, ss)
+-              seq_printf(seq, ",%s", ss->name);
+-      return 0;
 -}
 -
--static int shmem_populate(struct vm_area_struct *vma,
--      unsigned long addr, unsigned long len,
--      pgprot_t prot, unsigned long pgoff, int nonblock)
+-/* Convert a hierarchy specifier into a bitmask. LL=container_mutex */
+-static int parse_containerfs_options(char *opts, unsigned long *bits)
 -{
--      struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
--      struct mm_struct *mm = vma->vm_mm;
--      enum sgp_type sgp = nonblock? SGP_QUICK: SGP_CACHE;
--      unsigned long size;
+-      char *token, *o = opts ?: "all";
 -
--      size = (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
--      if (pgoff >= size || pgoff + (len >> PAGE_SHIFT) > size)
--              return -EINVAL;
+-      *bits = 0;
 -
--      while ((long) len > 0) {
--              struct page *page = NULL;
--              int err;
--              /*
--               * Will need changing if PAGE_CACHE_SIZE != PAGE_SIZE
--               */
--              err = shmem_getpage(inode, pgoff, &page, sgp, NULL);
--              if (err)
--                      return err;
--              /* Page may still be null, but only if nonblock was set. */
--              if (page) {
--                      mark_page_accessed(page);
--                      err = install_page(mm, vma, addr, page, prot);
--                      if (err) {
--                              page_cache_release(page);
--                              return err;
+-      while ((token = strsep(&o, ",")) != NULL) {
+-              if (!*token)
+-                      return -EINVAL;
+-              if (!strcmp(token, "all")) {
+-                      *bits = (1 << CONTAINER_SUBSYS_COUNT) - 1;
+-              } else {
+-                      struct container_subsys *ss;
+-                      int i;
+-                      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
+-                              ss = subsys[i];
+-                              if (!strcmp(token, ss->name)) {
+-                                      *bits |= 1 << i;
+-                                      break;
+-                              }
 -                      }
--              } else if (vma->vm_flags & VM_NONLINEAR) {
--                      /* No page was found just because we can't read it in
--                       * now (being here implies nonblock != 0), but the page
--                       * may exist, so set the PTE to fault it in later. */
--                      err = install_file_pte(mm, vma, addr, pgoff, prot);
--                      if (err)
--                              return err;
+-                      if (i == CONTAINER_SUBSYS_COUNT)
+-                              return -ENOENT;
 -              }
--
--              len -= PAGE_SIZE;
--              addr += PAGE_SIZE;
--              pgoff++;
 -      }
+-
+-      /* We can't have an empty hierarchy */
+-      if (!*bits)
+-              return -EINVAL;
+-
 -      return 0;
 -}
 -
--#ifdef CONFIG_NUMA
--int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
+-static int container_remount(struct super_block *sb, int *flags, char *data)
 -{
--      struct inode *i = vma->vm_file->f_path.dentry->d_inode;
--      return mpol_set_shared_policy(&SHMEM_I(i)->policy, vma, new);
--}
+-      int ret = 0;
+-      unsigned long subsys_bits;
+-      struct containerfs_root *root = sb->s_fs_info;
+-      struct container *cont = &root->top_container;
 -
--struct mempolicy *
--shmem_get_policy(struct vm_area_struct *vma, unsigned long addr)
--{
--      struct inode *i = vma->vm_file->f_path.dentry->d_inode;
--      unsigned long idx;
+-      mutex_lock(&cont->dentry->d_inode->i_mutex);
+-      mutex_lock(&container_mutex);
+-
+-      /* See what subsystems are wanted */
+-      ret = parse_containerfs_options(data, &subsys_bits);
+-      if (ret)
+-              goto out_unlock;
+-
+-      ret = rebind_subsystems(root, subsys_bits);
 -
--      idx = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
--      return mpol_shared_policy_lookup(&SHMEM_I(i)->policy, idx);
+-      /* (re)populate subsystem files */
+-      if (!ret)
+-              container_populate_dir(cont);
+-
+- out_unlock:
+-      mutex_unlock(&container_mutex);
+-      mutex_unlock(&cont->dentry->d_inode->i_mutex);
+-      return ret;
 -}
--#endif
 -
--int shmem_lock(struct file *file, int lock, struct user_struct *user)
+-static struct super_operations container_ops = {
+-      .statfs = simple_statfs,
+-      .drop_inode = generic_delete_inode,
+-      .put_super = container_put_super,
+-      .show_options = container_show_options,
+-      .remount_fs = container_remount,
+-};
+-
+-static int container_fill_super(struct super_block *sb, void *options,
+-                              int unused_silent)
 -{
--      struct inode *inode = file->f_path.dentry->d_inode;
--      struct shmem_inode_info *info = SHMEM_I(inode);
--      int retval = -ENOMEM;
+-      struct inode *inode;
+-      struct dentry *root;
+-      struct containerfs_root *hroot = options;
 -
--      spin_lock(&info->lock);
--      if (lock && !(info->flags & VM_LOCKED)) {
--              if (!user_shm_lock(inode->i_size, user))
--                      goto out_nomem;
--              info->flags |= VM_LOCKED;
--      }
--      if (!lock && (info->flags & VM_LOCKED) && user) {
--              user_shm_unlock(inode->i_size, user);
--              info->flags &= ~VM_LOCKED;
+-      sb->s_blocksize = PAGE_CACHE_SIZE;
+-      sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+-      sb->s_magic = CONTAINER_SUPER_MAGIC;
+-      sb->s_op = &container_ops;
+-
+-      inode = container_new_inode(S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR, sb);
+-      if (!inode)
+-              return -ENOMEM;
+-
+-      inode->i_op = &simple_dir_inode_operations;
+-      inode->i_fop = &simple_dir_operations;
+-      inode->i_op = &container_dir_inode_operations;
+-      /* directories start off with i_nlink == 2 (for "." entry) */
+-      inc_nlink(inode);
+-
+-      root = d_alloc_root(inode);
+-      if (!root) {
+-              iput(inode);
+-              return -ENOMEM;
 -      }
--      retval = 0;
--out_nomem:
--      spin_unlock(&info->lock);
--      return retval;
+-      sb->s_root = root;
+-      root->d_fsdata = &hroot->top_container;
+-      hroot->top_container.dentry = root;
+-
+-      strcpy(hroot->release_agent_path, "");
+-      sb->s_fs_info = hroot;
+-      hroot->sb = sb;
+-
+-      return 0;
 -}
 -
--static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
+-static void init_container_root(struct containerfs_root *root)
 -{
--      file_accessed(file);
--      vma->vm_ops = &shmem_vm_ops;
--      return 0;
+-      struct container *cont = &root->top_container;
+-      INIT_LIST_HEAD(&root->subsys_list);
+-      root->number_of_containers = 1;
+-      cont->root = root;
+-      cont->top_container = cont;
+-      INIT_LIST_HEAD(&cont->sibling);
+-      INIT_LIST_HEAD(&cont->children);
+-      INIT_LIST_HEAD(&cont->css_groups);
+-      INIT_LIST_HEAD(&cont->release_list);
+-      list_add(&root->root_list, &roots);
+-      root_count++;
 -}
 -
--static struct inode *
--shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
+-static int container_get_sb(struct file_system_type *fs_type,
+-                       int flags, const char *unused_dev_name,
+-                       void *data, struct vfsmount *mnt)
 -{
--      struct inode *inode;
--      struct shmem_inode_info *info;
--      struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
+-      unsigned long subsys_bits = 0;
+-      int ret = 0;
+-      struct containerfs_root *root = NULL;
+-      int use_existing = 0;
 -
--      if (sbinfo->max_inodes) {
--              spin_lock(&sbinfo->stat_lock);
--              if (!sbinfo->free_inodes) {
--                      spin_unlock(&sbinfo->stat_lock);
--                      return NULL;
--              }
--              sbinfo->free_inodes--;
--              spin_unlock(&sbinfo->stat_lock);
--      }
+-      mutex_lock(&container_mutex);
 -
--      inode = new_inode(sb);
--      if (inode) {
--              inode->i_mode = mode;
--              inode->i_uid = current->fsuid;
--              inode->i_gid = current->fsgid;
--              inode->i_blocks = 0;
--              inode->i_mapping->a_ops = &shmem_aops;
--              inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
--              inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
--              inode->i_generation = get_seconds();
--              info = SHMEM_I(inode);
--              memset(info, 0, (char *)inode - (char *)info);
--              spin_lock_init(&info->lock);
--              INIT_LIST_HEAD(&info->swaplist);
+-      /* First find the desired set of resource controllers */
+-      ret = parse_containerfs_options(data, &subsys_bits);
+-      if (ret)
+-              goto out_unlock;
 -
--              switch (mode & S_IFMT) {
--              default:
--                      inode->i_op = &shmem_special_inode_operations;
--                      init_special_inode(inode, mode, dev);
--                      break;
--              case S_IFREG:
--                      inode->i_op = &shmem_inode_operations;
--                      inode->i_fop = &shmem_file_operations;
--                      mpol_shared_policy_init(&info->policy, sbinfo->policy,
--                                                      &sbinfo->policy_nodes);
--                      break;
--              case S_IFDIR:
--                      inc_nlink(inode);
--                      /* Some things misbehave if size == 0 on a directory */
--                      inode->i_size = 2 * BOGO_DIRENT_SIZE;
--                      inode->i_op = &shmem_dir_inode_operations;
--                      inode->i_fop = &simple_dir_operations;
--                      break;
--              case S_IFLNK:
--                      /*
--                       * Must not load anything in the rbtree,
--                       * mpol_free_shared_policy will not be called.
--                       */
--                      mpol_shared_policy_init(&info->policy, MPOL_DEFAULT,
--                                              NULL);
+-      /* See if we already have a hierarchy containing this set */
+-
+-      for_each_root(root) {
+-              /* We match - use this hieracrchy */
+-              if (root->subsys_bits == subsys_bits) {
+-                      use_existing = 1;
 -                      break;
 -              }
--      } else if (sbinfo->max_inodes) {
--              spin_lock(&sbinfo->stat_lock);
--              sbinfo->free_inodes++;
--              spin_unlock(&sbinfo->stat_lock);
+-              /* We clash - fail */
+-              if (root->subsys_bits & subsys_bits) {
+-                      ret = -EBUSY;
+-                      goto out_unlock;
+-              }
 -      }
--      return inode;
+-
+-      if (!use_existing) {
+-              /* We need a new root */
+-              struct list_head tmp_cg_links, *l;
+-              root = kzalloc(sizeof(*root), GFP_KERNEL);
+-              if (!root) {
+-                      ret = -ENOMEM;
+-                      goto out_unlock;
+-              }
+-              /* We're accessing css_group_count without locking
+-               * here, but that's OK - it can only be increased by
+-               * someone holding container_lock, and that's us. The
+-               * worst that can happen is that we have some link
+-               * structures left over */
+-              ret = allocate_cg_links(css_group_count, &tmp_cg_links);
+-              if (ret < 0) {
+-                      kfree(root);
+-                      goto out_unlock;
+-              }
+-              init_container_root(root);
+-
+-              /* Link the top container in this hierarchy into all
+-               * the css_group objects */
+-              write_lock(&css_group_lock);
+-              l = &init_css_group.list;
+-              do {
+-                      struct css_group *cg;
+-                      struct cg_container_link *link;
+-                      cg = list_entry(l, struct css_group, list);
+-                      BUG_ON(list_empty(&tmp_cg_links));
+-                      link = list_entry(tmp_cg_links.next,
+-                                        struct cg_container_link,
+-                                        cont_link_list);
+-                      list_del(&link->cont_link_list);
+-                      link->cg = cg;
+-                      list_add(&link->cont_link_list,
+-                               &root->top_container.css_groups);
+-                      list_add(&link->cg_link_list, &cg->cg_links);
+-                      l = l->next;
+-              } while (l != &init_css_group.list);
+-              write_unlock(&css_group_lock);
+-
+-              while (!list_empty(&tmp_cg_links)) {
+-                      /* Probably shouldn't happen */
+-                      struct cg_container_link *link;
+-                      printk(KERN_INFO "Freeing unused cg_container_link\n");
+-                      link = list_entry(tmp_cg_links.next,
+-                                        struct cg_container_link,
+-                                        cont_link_list);
+-                      list_del(&link->cont_link_list);
+-                      kfree(link);
+-              }
+-      }
+-
+-      if (!root->sb) {
+-              /* We need a new superblock for this container combination */
+-              struct container *cont = &root->top_container;
+-
+-              BUG_ON(root->subsys_bits);
+-              ret = get_sb_nodev(fs_type, flags, root,
+-                                 container_fill_super, mnt);
+-              if (ret)
+-                      goto out_unlock;
+-
+-              BUG_ON(!list_empty(&cont->sibling));
+-              BUG_ON(!list_empty(&cont->children));
+-              BUG_ON(root->number_of_containers != 1);
+-
+-              ret = rebind_subsystems(root, subsys_bits);
+-
+-              /* It's safe to nest i_mutex inside container_mutex in
+-               * this case, since no-one else can be accessing this
+-               * directory yet */
+-              mutex_lock(&cont->dentry->d_inode->i_mutex);
+-              container_populate_dir(cont);
+-              mutex_unlock(&cont->dentry->d_inode->i_mutex);
+-              BUG_ON(ret);
+-      } else {
+-              /* Reuse the existing superblock */
+-              down_write(&(root->sb->s_umount));
+-              ret = simple_set_mnt(mnt, root->sb);
+-              if (!ret)
+-                      atomic_inc(&root->sb->s_active);
+-      }
+-
+- out_unlock:
+-      mutex_unlock(&container_mutex);
+-      return ret;
 -}
 -
--#ifdef CONFIG_TMPFS
--static const struct inode_operations shmem_symlink_inode_operations;
--static const struct inode_operations shmem_symlink_inline_operations;
+-static struct file_system_type container_fs_type = {
+-      .name = "container",
+-      .get_sb = container_get_sb,
+-      .kill_sb = kill_litter_super,
+-};
 -
--/*
-- * Normally tmpfs makes no use of shmem_prepare_write, but it
-- * lets a tmpfs file be used read-write below the loop driver.
-- */
--static int
--shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+-static inline struct container *__d_cont(struct dentry *dentry)
 -{
--      struct inode *inode = page->mapping->host;
--      return shmem_getpage(inode, page->index, &page, SGP_WRITE, NULL);
+-      return dentry->d_fsdata;
 -}
 -
--static ssize_t
--shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+-static inline struct cftype *__d_cft(struct dentry *dentry)
 -{
--      struct inode    *inode = file->f_path.dentry->d_inode;
--      loff_t          pos;
--      unsigned long   written;
--      ssize_t         err;
--
--      if ((ssize_t) count < 0)
--              return -EINVAL;
+-      return dentry->d_fsdata;
+-}
 -
--      if (!access_ok(VERIFY_READ, buf, count))
--              return -EFAULT;
+-/*
+- * Called with container_mutex held.  Writes path of container into buf.
+- * Returns 0 on success, -errno on error.
+- */
+-int container_path(const struct container *cont, char *buf, int buflen)
+-{
+-      char *start;
 -
--      mutex_lock(&inode->i_mutex);
+-      start = buf + buflen;
 -
--      pos = *ppos;
--      written = 0;
+-      *--start = '\0';
+-      for (;;) {
+-              int len = cont->dentry->d_name.len;
+-              if ((start -= len) < buf)
+-                      return -ENAMETOOLONG;
+-              memcpy(start, cont->dentry->d_name.name, len);
+-              cont = cont->parent;
+-              if (!cont)
+-                      break;
+-              if (!cont->parent)
+-                      continue;
+-              if (--start < buf)
+-                      return -ENAMETOOLONG;
+-              *start = '/';
+-      }
+-      memmove(buf, start, buf + buflen - start);
+-      return 0;
+-}
 -
--      err = generic_write_checks(file, &pos, &count, 0);
--      if (err || !count)
--              goto out;
+-static void get_first_subsys(const struct container *cont,
+-                      struct container_subsys_state **css, int *subsys_id)
+-{
+-      const struct containerfs_root *root = cont->root;
+-      const struct container_subsys *test_ss;
+-      BUG_ON(list_empty(&root->subsys_list));
+-      test_ss = list_entry(root->subsys_list.next,
+-                           struct container_subsys, sibling);
+-      if (css) {
+-              *css = cont->subsys[test_ss->subsys_id];
+-              BUG_ON(!*css);
+-      }
+-      if (subsys_id)
+-              *subsys_id = test_ss->subsys_id;
+-}
 -
--      err = remove_suid(file->f_path.dentry);
--      if (err)
--              goto out;
+-/*
+- * Attach task 'tsk' to container 'cont'
+- *
+- * Call holding container_mutex.  May take task_lock of
+- * the task 'pid' during call.
+- */
+-static int attach_task(struct container *cont, struct task_struct *tsk)
+-{
+-      int retval = 0;
+-      struct container_subsys *ss;
+-      struct container *oldcont;
+-      struct css_group *cg = tsk->containers;
+-      struct css_group *newcg;
+-      struct containerfs_root *root = cont->root;
+-      int subsys_id;
+-
+-      get_first_subsys(cont, NULL, &subsys_id);
+-
+-      /* Nothing to do if the task is already in that container */
+-      oldcont = task_container(tsk, subsys_id);
+-      if (cont == oldcont)
+-              return 0;
 -
--      inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+-      for_each_subsys(root, ss) {
+-              if (ss->can_attach) {
+-                      retval = ss->can_attach(ss, cont, tsk);
+-                      if (retval) {
+-                              return retval;
+-                      }
+-              }
+-      }
 -
--      do {
--              struct page *page = NULL;
--              unsigned long bytes, index, offset;
--              char *kaddr;
--              int left;
+-      /* Locate or allocate a new css_group for this task,
+-       * based on its final set of containers */
+-      newcg = find_css_group(cg, cont);
+-      if (!newcg) {
+-              return -ENOMEM;
+-      }
 -
--              offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
--              index = pos >> PAGE_CACHE_SHIFT;
--              bytes = PAGE_CACHE_SIZE - offset;
--              if (bytes > count)
--                      bytes = count;
+-      task_lock(tsk);
+-      if (tsk->flags & PF_EXITING) {
+-              task_unlock(tsk);
+-              put_css_group(newcg);
+-              return -ESRCH;
+-      }
+-      rcu_assign_pointer(tsk->containers, newcg);
+-      if (!list_empty(&tsk->cg_list)) {
+-              write_lock(&css_group_lock);
+-              list_del(&tsk->cg_list);
+-              list_add(&tsk->cg_list, &newcg->tasks);
+-              write_unlock(&css_group_lock);
+-      }
+-      task_unlock(tsk);
 -
--              /*
--               * We don't hold page lock across copy from user -
--               * what would it guard against? - so no deadlock here.
--               * But it still may be a good idea to prefault below.
--               */
+-      for_each_subsys(root, ss) {
+-              if (ss->attach) {
+-                      ss->attach(ss, cont, oldcont, tsk);
+-              }
+-      }
+-      set_bit(CONT_RELEASABLE, &oldcont->flags);
+-      synchronize_rcu();
+-      put_css_group(cg);
+-      return 0;
+-}
 -
--              err = shmem_getpage(inode, index, &page, SGP_WRITE, NULL);
--              if (err)
--                      break;
+-/*
+- * Attach task with pid 'pid' to container 'cont'. Call with
+- * container_mutex, may take task_lock of task
+- */
+-static int attach_task_by_pid(struct container *cont, char *pidbuf)
+-{
+-      pid_t pid;
+-      struct task_struct *tsk;
+-      int ret;
 -
--              left = bytes;
--              if (PageHighMem(page)) {
--                      volatile unsigned char dummy;
--                      __get_user(dummy, buf);
--                      __get_user(dummy, buf + bytes - 1);
+-      if (sscanf(pidbuf, "%d", &pid) != 1)
+-              return -EIO;
 -
--                      kaddr = kmap_atomic(page, KM_USER0);
--                      left = __copy_from_user_inatomic(kaddr + offset,
--                                                      buf, bytes);
--                      kunmap_atomic(kaddr, KM_USER0);
--              }
--              if (left) {
--                      kaddr = kmap(page);
--                      left = __copy_from_user(kaddr + offset, buf, bytes);
--                      kunmap(page);
+-      if (pid) {
+-              rcu_read_lock();
+-              tsk = find_task_by_pid(pid);
+-              if (!tsk || tsk->flags & PF_EXITING) {
+-                      rcu_read_unlock();
+-                      return -ESRCH;
 -              }
+-              get_task_struct(tsk);
+-              rcu_read_unlock();
 -
--              written += bytes;
--              count -= bytes;
--              pos += bytes;
--              buf += bytes;
--              if (pos > inode->i_size)
--                      i_size_write(inode, pos);
--
--              flush_dcache_page(page);
--              set_page_dirty(page);
--              mark_page_accessed(page);
--              page_cache_release(page);
--
--              if (left) {
--                      pos -= left;
--                      written -= left;
--                      err = -EFAULT;
--                      break;
+-              if ((current->euid) && (current->euid != tsk->uid)
+-                  && (current->euid != tsk->suid)) {
+-                      put_task_struct(tsk);
+-                      return -EACCES;
 -              }
+-      } else {
+-              tsk = current;
+-              get_task_struct(tsk);
+-      }
 -
--              /*
--               * Our dirty pages are not counted in nr_dirty,
--               * and we do not attempt to balance dirty pages.
--               */
+-      ret = attach_task(cont, tsk);
+-      put_task_struct(tsk);
+-      return ret;
+-}
 -
--              cond_resched();
--      } while (count);
+-/* The various types of files and directories in a container file system */
 -
--      *ppos = pos;
--      if (written)
--              err = written;
--out:
--      mutex_unlock(&inode->i_mutex);
--      return err;
--}
+-enum container_filetype {
+-      FILE_ROOT,
+-      FILE_DIR,
+-      FILE_TASKLIST,
+-      FILE_NOTIFY_ON_RELEASE,
+-      FILE_RELEASABLE,
+-      FILE_RELEASE_AGENT,
+-};
 -
--static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor)
+-static ssize_t container_common_file_write(struct container *cont,
+-                                         struct cftype *cft,
+-                                         struct file *file,
+-                                         const char __user *userbuf,
+-                                         size_t nbytes, loff_t *unused_ppos)
 -{
--      struct inode *inode = filp->f_path.dentry->d_inode;
--      struct address_space *mapping = inode->i_mapping;
--      unsigned long index, offset;
+-      enum container_filetype type = cft->private;
+-      char *buffer;
+-      int retval = 0;
 -
--      index = *ppos >> PAGE_CACHE_SHIFT;
--      offset = *ppos & ~PAGE_CACHE_MASK;
+-      if (nbytes >= PATH_MAX)
+-              return -E2BIG;
 -
--      for (;;) {
--              struct page *page = NULL;
--              unsigned long end_index, nr, ret;
--              loff_t i_size = i_size_read(inode);
+-      /* +1 for nul-terminator */
+-      buffer = kmalloc(nbytes + 1, GFP_KERNEL);
+-      if (buffer == NULL)
+-              return -ENOMEM;
 -
--              end_index = i_size >> PAGE_CACHE_SHIFT;
--              if (index > end_index)
--                      break;
--              if (index == end_index) {
--                      nr = i_size & ~PAGE_CACHE_MASK;
--                      if (nr <= offset)
--                              break;
--              }
+-      if (copy_from_user(buffer, userbuf, nbytes)) {
+-              retval = -EFAULT;
+-              goto out1;
+-      }
+-      buffer[nbytes] = 0;     /* nul-terminate */
 -
--              desc->error = shmem_getpage(inode, index, &page, SGP_READ, NULL);
--              if (desc->error) {
--                      if (desc->error == -EINVAL)
--                              desc->error = 0;
--                      break;
--              }
+-      mutex_lock(&container_mutex);
 -
--              /*
--               * We must evaluate after, since reads (unlike writes)
--               * are called without i_mutex protection against truncate
--               */
--              nr = PAGE_CACHE_SIZE;
--              i_size = i_size_read(inode);
--              end_index = i_size >> PAGE_CACHE_SHIFT;
--              if (index == end_index) {
--                      nr = i_size & ~PAGE_CACHE_MASK;
--                      if (nr <= offset) {
--                              if (page)
--                                      page_cache_release(page);
--                              break;
--                      }
--              }
--              nr -= offset;
+-      if (container_is_removed(cont)) {
+-              retval = -ENODEV;
+-              goto out2;
+-      }
 -
--              if (page) {
--                      /*
--                       * If users can be writing to this page using arbitrary
--                       * virtual addresses, take care about potential aliasing
--                       * before reading the page on the kernel side.
--                       */
--                      if (mapping_writably_mapped(mapping))
--                              flush_dcache_page(page);
--                      /*
--                       * Mark the page accessed if we read the beginning.
--                       */
--                      if (!offset)
--                              mark_page_accessed(page);
+-      switch (type) {
+-      case FILE_TASKLIST:
+-              retval = attach_task_by_pid(cont, buffer);
+-              break;
+-      case FILE_NOTIFY_ON_RELEASE:
+-              clear_bit(CONT_RELEASABLE, &cont->flags);
+-              if (simple_strtoul(buffer, NULL, 10) != 0)
+-                      set_bit(CONT_NOTIFY_ON_RELEASE, &cont->flags);
+-              else
+-                      clear_bit(CONT_NOTIFY_ON_RELEASE, &cont->flags);
+-              break;
+-      case FILE_RELEASE_AGENT:
+-      {
+-              struct containerfs_root *root = cont->root;
+-              if (nbytes < sizeof(root->release_agent_path)) {
+-                      /* We never write anything other than '\0'
+-                       * into the last char of release_agent_path,
+-                       * so it always remains a NUL-terminated
+-                       * string */
+-                      strncpy(root->release_agent_path, buffer, nbytes);
+-                      root->release_agent_path[nbytes] = 0;
 -              } else {
--                      page = ZERO_PAGE(0);
--                      page_cache_get(page);
+-                      retval = -ENOSPC;
 -              }
--
--              /*
--               * Ok, we have the page, and it's up-to-date, so
--               * now we can copy it to user space...
--               *
--               * The actor routine returns how many bytes were actually used..
--               * NOTE! This may not be the same as how much of a user buffer
--               * we filled up (we may be padding etc), so we can only update
--               * "pos" here (the actor routine has to update the user buffer
--               * pointers and the remaining count).
--               */
--              ret = actor(desc, page, offset, nr);
--              offset += ret;
--              index += offset >> PAGE_CACHE_SHIFT;
--              offset &= ~PAGE_CACHE_MASK;
--
--              page_cache_release(page);
--              if (ret != nr || !desc->count)
--                      break;
--
--              cond_resched();
+-              break;
+-      }
+-      default:
+-              retval = -EINVAL;
+-              goto out2;
 -      }
 -
--      *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
--      file_accessed(filp);
+-      if (retval == 0)
+-              retval = nbytes;
+-out2:
+-      mutex_unlock(&container_mutex);
+-out1:
+-      kfree(buffer);
+-      return retval;
 -}
 -
--static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
+-static ssize_t container_file_write(struct file *file, const char __user *buf,
+-                                              size_t nbytes, loff_t *ppos)
 -{
--      read_descriptor_t desc;
+-      struct cftype *cft = __d_cft(file->f_dentry);
+-      struct container *cont = __d_cont(file->f_dentry->d_parent);
 -
--      if ((ssize_t) count < 0)
+-      if (!cft)
+-              return -ENODEV;
+-      if (!cft->write)
 -              return -EINVAL;
--      if (!access_ok(VERIFY_WRITE, buf, count))
--              return -EFAULT;
--      if (!count)
--              return 0;
 -
--      desc.written = 0;
--      desc.count = count;
--      desc.arg.buf = buf;
--      desc.error = 0;
--
--      do_shmem_file_read(filp, ppos, &desc, file_read_actor);
--      if (desc.written)
--              return desc.written;
--      return desc.error;
+-      return cft->write(cont, cft, file, buf, nbytes, ppos);
 -}
 -
--static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos,
--                       size_t count, read_actor_t actor, void *target)
+-static ssize_t container_read_uint(struct container *cont, struct cftype *cft,
+-                                 struct file *file,
+-                                 char __user *buf, size_t nbytes,
+-                                 loff_t *ppos)
 -{
--      read_descriptor_t desc;
--
--      if (!count)
--              return 0;
+-      char tmp[64];
+-      u64 val = cft->read_uint(cont, cft);
+-      int len = sprintf(tmp, "%llu\n", (unsigned long long) val);
 -
--      desc.written = 0;
--      desc.count = count;
--      desc.arg.data = target;
--      desc.error = 0;
--
--      do_shmem_file_read(in_file, ppos, &desc, actor);
--      if (desc.written)
--              return desc.written;
--      return desc.error;
+-      return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
 -}
 -
--static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
+-static ssize_t container_common_file_read(struct container *cont,
+-                                        struct cftype *cft,
+-                                        struct file *file,
+-                                        char __user *buf,
+-                                        size_t nbytes, loff_t *ppos)
 -{
--      struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
+-      enum container_filetype type = cft->private;
+-      char *page;
+-      ssize_t retval = 0;
+-      char *s;
 -
--      buf->f_type = TMPFS_MAGIC;
--      buf->f_bsize = PAGE_CACHE_SIZE;
--      buf->f_namelen = NAME_MAX;
--      spin_lock(&sbinfo->stat_lock);
--      if (sbinfo->max_blocks) {
--              buf->f_blocks = sbinfo->max_blocks;
--              buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;
+-      if (!(page = (char *)__get_free_page(GFP_KERNEL)))
+-              return -ENOMEM;
+-
+-      s = page;
+-
+-      switch (type) {
+-      case FILE_RELEASE_AGENT:
+-      {
+-              struct containerfs_root *root;
+-              size_t n;
+-              mutex_lock(&container_mutex);
+-              root = cont->root;
+-              n = strnlen(root->release_agent_path,
+-                          sizeof(root->release_agent_path));
+-              n = min(n, (size_t) PAGE_SIZE);
+-              strncpy(s, root->release_agent_path, n);
+-              mutex_unlock(&container_mutex);
+-              s += n;
+-              break;
 -      }
--      if (sbinfo->max_inodes) {
--              buf->f_files = sbinfo->max_inodes;
--              buf->f_ffree = sbinfo->free_inodes;
+-      default:
+-              retval = -EINVAL;
+-              goto out;
 -      }
--      /* else leave those fields 0 like simple_statfs */
--      spin_unlock(&sbinfo->stat_lock);
--      return 0;
+-      *s++ = '\n';
+-
+-      retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page);
+-out:
+-      free_page((unsigned long)page);
+-      return retval;
 -}
 -
--/*
-- * File creation. Allocate an inode, and we're done..
-- */
--static int
--shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+-static ssize_t container_file_read(struct file *file, char __user *buf,
+-                                 size_t nbytes, loff_t *ppos)
 -{
--      struct inode *inode = shmem_get_inode(dir->i_sb, mode, dev);
--      int error = -ENOSPC;
+-      struct cftype *cft = __d_cft(file->f_dentry);
+-      struct container *cont = __d_cont(file->f_dentry->d_parent);
 -
--      if (inode) {
--              error = security_inode_init_security(inode, dir, NULL, NULL,
--                                                   NULL);
--              if (error) {
--                      if (error != -EOPNOTSUPP) {
--                              iput(inode);
--                              return error;
--                      }
--              }
--              error = shmem_acl_init(inode, dir);
--              if (error) {
--                      iput(inode);
--                      return error;
--              }
--              if (dir->i_mode & S_ISGID) {
--                      inode->i_gid = dir->i_gid;
--                      if (S_ISDIR(mode))
--                              inode->i_mode |= S_ISGID;
--              }
--              dir->i_size += BOGO_DIRENT_SIZE;
--              dir->i_ctime = dir->i_mtime = CURRENT_TIME;
--              d_instantiate(dentry, inode);
--              dget(dentry); /* Extra count - pin the dentry in core */
--      }
--      return error;
+-      if (!cft)
+-              return -ENODEV;
+-
+-      if (cft->read)
+-              return cft->read(cont, cft, file, buf, nbytes, ppos);
+-      if (cft->read_uint)
+-              return container_read_uint(cont, cft, file, buf, nbytes, ppos);
+-      return -EINVAL;
 -}
 -
--static int shmem_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+-static int container_file_open(struct inode *inode, struct file *file)
 -{
--      int error;
+-      int err;
+-      struct cftype *cft;
 -
--      if ((error = shmem_mknod(dir, dentry, mode | S_IFDIR, 0)))
--              return error;
--      inc_nlink(dir);
--      return 0;
+-      err = generic_file_open(inode, file);
+-      if (err)
+-              return err;
+-
+-      cft = __d_cft(file->f_dentry);
+-      if (!cft)
+-              return -ENODEV;
+-      if (cft->open)
+-              err = cft->open(inode, file);
+-      else
+-              err = 0;
+-
+-      return err;
 -}
 -
--static int shmem_create(struct inode *dir, struct dentry *dentry, int mode,
--              struct nameidata *nd)
+-static int container_file_release(struct inode *inode, struct file *file)
 -{
--      return shmem_mknod(dir, dentry, mode | S_IFREG, 0);
+-      struct cftype *cft = __d_cft(file->f_dentry);
+-      if (cft->release)
+-              return cft->release(inode, file);
+-      return 0;
 -}
 -
 -/*
-- * Link a file..
+- * container_rename - Only allow simple rename of directories in place.
 - */
--static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+-static int container_rename(struct inode *old_dir, struct dentry *old_dentry,
+-                          struct inode *new_dir, struct dentry *new_dentry)
 -{
--      struct inode *inode = old_dentry->d_inode;
--      struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
+-      if (!S_ISDIR(old_dentry->d_inode->i_mode))
+-              return -ENOTDIR;
+-      if (new_dentry->d_inode)
+-              return -EEXIST;
+-      if (old_dir != new_dir)
+-              return -EIO;
+-      return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
+-}
 -
--      /*
--       * No ordinary (disk based) filesystem counts links as inodes;
--       * but each new link needs a new dentry, pinning lowmem, and
--       * tmpfs dentries cannot be pruned until they are unlinked.
--       */
--      if (sbinfo->max_inodes) {
--              spin_lock(&sbinfo->stat_lock);
--              if (!sbinfo->free_inodes) {
--                      spin_unlock(&sbinfo->stat_lock);
--                      return -ENOSPC;
--              }
--              sbinfo->free_inodes--;
--              spin_unlock(&sbinfo->stat_lock);
+-static struct file_operations container_file_operations = {
+-      .read = container_file_read,
+-      .write = container_file_write,
+-      .llseek = generic_file_llseek,
+-      .open = container_file_open,
+-      .release = container_file_release,
+-};
+-
+-static struct inode_operations container_dir_inode_operations = {
+-      .lookup = simple_lookup,
+-      .mkdir = container_mkdir,
+-      .rmdir = container_rmdir,
+-      .rename = container_rename,
+-};
+-
+-static int container_create_file(struct dentry *dentry, int mode,
+-                              struct super_block *sb)
+-{
+-      struct inode *inode;
+-
+-      if (!dentry)
+-              return -ENOENT;
+-      if (dentry->d_inode)
+-              return -EEXIST;
+-
+-      inode = container_new_inode(mode, sb);
+-      if (!inode)
+-              return -ENOMEM;
+-
+-      if (S_ISDIR(mode)) {
+-              inode->i_op = &container_dir_inode_operations;
+-              inode->i_fop = &simple_dir_operations;
+-
+-              /* start off with i_nlink == 2 (for "." entry) */
+-              inc_nlink(inode);
+-
+-              /* start with the directory inode held, so that we can
+-               * populate it without racing with another mkdir */
+-              mutex_lock(&inode->i_mutex);
+-      } else if (S_ISREG(mode)) {
+-              inode->i_size = 0;
+-              inode->i_fop = &container_file_operations;
 -      }
 -
--      dir->i_size += BOGO_DIRENT_SIZE;
--      inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
--      inc_nlink(inode);
--      atomic_inc(&inode->i_count);    /* New dentry reference */
--      dget(dentry);           /* Extra pinning count for the created dentry */
 -      d_instantiate(dentry, inode);
+-      dget(dentry);   /* Extra count - pin the dentry in core */
 -      return 0;
 -}
 -
--static int shmem_unlink(struct inode *dir, struct dentry *dentry)
+-/*
+- *    container_create_dir - create a directory for an object.
+- *    cont:   the container we create the directory for.
+- *            It must have a valid ->parent field
+- *            And we are going to fill its ->dentry field.
+- *    name:   The name to give to the container directory. Will be copied.
+- *    mode:   mode to set on new directory.
+- */
+-static int container_create_dir(struct container *cont, struct dentry *dentry,
+-                              int mode)
 -{
--      struct inode *inode = dentry->d_inode;
+-      struct dentry *parent;
+-      int error = 0;
 -
--      if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) {
--              struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
--              if (sbinfo->max_inodes) {
--                      spin_lock(&sbinfo->stat_lock);
--                      sbinfo->free_inodes++;
--                      spin_unlock(&sbinfo->stat_lock);
--              }
+-      parent = cont->parent->dentry;
+-      if (IS_ERR(dentry))
+-              return PTR_ERR(dentry);
+-      error = container_create_file(dentry, S_IFDIR | mode, cont->root->sb);
+-      if (!error) {
+-              dentry->d_fsdata = cont;
+-              inc_nlink(parent->d_inode);
+-              cont->dentry = dentry;
 -      }
+-      dput(dentry);
 -
--      dir->i_size -= BOGO_DIRENT_SIZE;
--      inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
--      drop_nlink(inode);
--      dput(dentry);   /* Undo the count from "create" - this does all the work */
--      return 0;
+-      return error;
 -}
 -
--static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
+-int container_add_file(struct container *cont, const struct cftype *cft)
 -{
--      if (!simple_empty(dentry))
--              return -ENOTEMPTY;
+-      struct dentry *dir = cont->dentry;
+-      struct dentry *dentry;
+-      int error;
 -
--      drop_nlink(dentry->d_inode);
--      drop_nlink(dir);
--      return shmem_unlink(dir, dentry);
+-      BUG_ON(!mutex_is_locked(&dir->d_inode->i_mutex));
+-      dentry = container_get_dentry(dir, cft->name);
+-      if (!IS_ERR(dentry)) {
+-              error = container_create_file(dentry, 0644 | S_IFREG,
+-                                              cont->root->sb);
+-              if (!error)
+-                      dentry->d_fsdata = (void *)cft;
+-              dput(dentry);
+-      } else
+-              error = PTR_ERR(dentry);
+-      return error;
 -}
 -
--/*
-- * The VFS layer already does all the dentry stuff for rename,
-- * we just have to decrement the usage count for the target if
-- * it exists so that the VFS layer correctly free's it when it
-- * gets overwritten.
-- */
--static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
+-int container_add_files(struct container *cont, const struct cftype cft[],
+-                      int count)
 -{
--      struct inode *inode = old_dentry->d_inode;
--      int they_are_dirs = S_ISDIR(inode->i_mode);
--
--      if (!simple_empty(new_dentry))
--              return -ENOTEMPTY;
--
--      if (new_dentry->d_inode) {
--              (void) shmem_unlink(new_dir, new_dentry);
--              if (they_are_dirs)
--                      drop_nlink(old_dir);
--      } else if (they_are_dirs) {
--              drop_nlink(old_dir);
--              inc_nlink(new_dir);
+-      int i, err;
+-      for (i = 0; i < count; i++) {
+-              err = container_add_file(cont, &cft[i]);
+-              if (err)
+-                      return err;
 -      }
--
--      old_dir->i_size -= BOGO_DIRENT_SIZE;
--      new_dir->i_size += BOGO_DIRENT_SIZE;
--      old_dir->i_ctime = old_dir->i_mtime =
--      new_dir->i_ctime = new_dir->i_mtime =
--      inode->i_ctime = CURRENT_TIME;
 -      return 0;
 -}
 -
--static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
--{
--      int error;
--      int len;
--      struct inode *inode;
--      struct page *page = NULL;
--      char *kaddr;
--      struct shmem_inode_info *info;
--
--      len = strlen(symname) + 1;
--      if (len > PAGE_CACHE_SIZE)
--              return -ENAMETOOLONG;
+-/* Count the number of tasks in a container. */
 -
--      inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
--      if (!inode)
--              return -ENOSPC;
+-int container_task_count(const struct container *cont)
+-{
+-      int count = 0;
+-      struct list_head *l;
 -
--      error = security_inode_init_security(inode, dir, NULL, NULL,
--                                           NULL);
--      if (error) {
--              if (error != -EOPNOTSUPP) {
--                      iput(inode);
--                      return error;
--              }
--              error = 0;
+-      read_lock(&css_group_lock);
+-      l = cont->css_groups.next;
+-      while (l != &cont->css_groups) {
+-              struct cg_container_link *link =
+-                      list_entry(l, struct cg_container_link, cont_link_list);
+-              count += atomic_read(&link->cg->ref.refcount);
+-              l = l->next;
 -      }
--
--      info = SHMEM_I(inode);
--      inode->i_size = len-1;
--      if (len <= (char *)inode - (char *)info) {
--              /* do it inline */
--              memcpy(info, symname, len);
--              inode->i_op = &shmem_symlink_inline_operations;
--      } else {
--              error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
--              if (error) {
--                      iput(inode);
--                      return error;
--              }
--              inode->i_op = &shmem_symlink_inode_operations;
--              kaddr = kmap_atomic(page, KM_USER0);
--              memcpy(kaddr, symname, len);
--              kunmap_atomic(kaddr, KM_USER0);
--              set_page_dirty(page);
--              page_cache_release(page);
--      }
--      if (dir->i_mode & S_ISGID)
--              inode->i_gid = dir->i_gid;
--      dir->i_size += BOGO_DIRENT_SIZE;
--      dir->i_ctime = dir->i_mtime = CURRENT_TIME;
--      d_instantiate(dentry, inode);
--      dget(dentry);
--      return 0;
+-      read_unlock(&css_group_lock);
+-      return count;
 -}
 -
--static void *shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
+-/* Advance a list_head iterator pointing at a cg_container_link's */
+-static void container_advance_iter(struct container *cont,
+-                                        struct container_iter *it)
 -{
--      nd_set_link(nd, (char *)SHMEM_I(dentry->d_inode));
--      return NULL;
+-      struct list_head *l = it->cg_link;
+-      struct cg_container_link *link;
+-      struct css_group *cg;
+-
+-      /* Advance to the next non-empty css_group */
+-      do {
+-              l = l->next;
+-              if (l == &cont->css_groups) {
+-                      it->cg_link = NULL;
+-                      return;
+-              }
+-              link = list_entry(l, struct cg_container_link, cont_link_list);
+-              cg = link->cg;
+-      } while (list_empty(&cg->tasks));
+-      it->cg_link = l;
+-      it->task = cg->tasks.next;
 -}
 -
--static void *shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
+-void container_iter_start(struct container *cont, struct container_iter *it)
 -{
--      struct page *page = NULL;
--      int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL);
--      nd_set_link(nd, res ? ERR_PTR(res) : kmap(page));
--      return page;
+-      read_lock(&css_group_lock);
+-      it->cg_link = &cont->css_groups;
+-      container_advance_iter(cont, it);
 -}
 -
--static void shmem_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
+-struct task_struct *container_iter_next(struct container *cont,
+-                                      struct container_iter *it)
 -{
--      if (!IS_ERR(nd_get_link(nd))) {
--              struct page *page = cookie;
--              kunmap(page);
--              mark_page_accessed(page);
--              page_cache_release(page);
+-      struct task_struct *res;
+-      struct list_head *l = it->task;
+-
+-      /* If the iterator cg is NULL, we have no tasks */
+-      if (!it->cg_link)
+-              return NULL;
+-      res = list_entry(l, struct task_struct, cg_list);
+-      /* Advance iterator to find next entry */
+-      l = l->next;
+-      if (l == &res->containers->tasks) {
+-              /* We reached the end of this task list - move on to
+-               * the next cg_container_link */
+-              container_advance_iter(cont, it);
+-      } else {
+-              it->task = l;
 -      }
+-      return res;
 -}
 -
--static const struct inode_operations shmem_symlink_inline_operations = {
--      .readlink       = generic_readlink,
--      .follow_link    = shmem_follow_link_inline,
--};
+-void container_iter_end(struct container *cont, struct container_iter *it)
+-{
+-      read_unlock(&css_group_lock);
+-}
 -
--static const struct inode_operations shmem_symlink_inode_operations = {
--      .truncate       = shmem_truncate,
--      .readlink       = generic_readlink,
--      .follow_link    = shmem_follow_link,
--      .put_link       = shmem_put_link,
+-/*
+- * Stuff for reading the 'tasks' file.
+- *
+- * Reading this file can return large amounts of data if a container has
+- * *lots* of attached tasks. So it may need several calls to read(),
+- * but we cannot guarantee that the information we produce is correct
+- * unless we produce it entirely atomically.
+- *
+- * Upon tasks file open(), a struct ctr_struct is allocated, that
+- * will have a pointer to an array (also allocated here).  The struct
+- * ctr_struct * is stored in file->private_data.  Its resources will
+- * be freed by release() when the file is closed.  The array is used
+- * to sprintf the PIDs and then used by read().
+- */
+-struct ctr_struct {
+-      char *buf;
+-      int bufsz;
 -};
 -
--#ifdef CONFIG_TMPFS_POSIX_ACL
--/**
-- * Superblocks without xattr inode operations will get security.* xattr
-- * support from the VFS "for free". As soon as we have any other xattrs
-- * like ACLs, we also need to implement the security.* handlers at
-- * filesystem level, though.
+-/*
+- * Load into 'pidarray' up to 'npids' of the tasks using container
+- * 'cont'.  Return actual number of pids loaded.  No need to
+- * task_lock(p) when reading out p->container, since we're in an RCU
+- * read section, so the css_group can't go away, and is
+- * immutable after creation.
 - */
--
--static size_t shmem_xattr_security_list(struct inode *inode, char *list,
--                                      size_t list_len, const char *name,
--                                      size_t name_len)
+-static int pid_array_load(pid_t *pidarray, int npids, struct container *cont)
 -{
--      return security_inode_listsecurity(inode, list, list_len);
+-      int n = 0;
+-      struct container_iter it;
+-      struct task_struct *tsk;
+-      container_iter_start(cont, &it);
+-      while ((tsk = container_iter_next(cont, &it))) {
+-              if (unlikely(n == npids))
+-                      break;
+-              pidarray[n++] = pid_nr(task_pid(tsk));
+-      }
+-      container_iter_end(cont, &it);
+-      return n;
 -}
 -
--static int shmem_xattr_security_get(struct inode *inode, const char *name,
--                                  void *buffer, size_t size)
+-static int cmppid(const void *a, const void *b)
 -{
--      if (strcmp(name, "") == 0)
--              return -EINVAL;
--      return security_inode_getsecurity(inode, name, buffer, size,
--                                        -EOPNOTSUPP);
+-      return *(pid_t *)a - *(pid_t *)b;
 -}
 -
--static int shmem_xattr_security_set(struct inode *inode, const char *name,
--                                  const void *value, size_t size, int flags)
+-/*
+- * Convert array 'a' of 'npids' pid_t's to a string of newline separated
+- * decimal pids in 'buf'.  Don't write more than 'sz' chars, but return
+- * count 'cnt' of how many chars would be written if buf were large enough.
+- */
+-static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids)
 -{
--      if (strcmp(name, "") == 0)
--              return -EINVAL;
--      return security_inode_setsecurity(inode, name, value, size, flags);
+-      int cnt = 0;
+-      int i;
+-
+-      for (i = 0; i < npids; i++)
+-              cnt += snprintf(buf + cnt, max(sz - cnt, 0), "%d\n", a[i]);
+-      return cnt;
 -}
 -
--static struct xattr_handler shmem_xattr_security_handler = {
--      .prefix = XATTR_SECURITY_PREFIX,
--      .list   = shmem_xattr_security_list,
--      .get    = shmem_xattr_security_get,
--      .set    = shmem_xattr_security_set,
--};
+-/*
+- * Handle an open on 'tasks' file.  Prepare a buffer listing the
+- * process id's of tasks currently attached to the container being opened.
+- *
+- * Does not require any specific container mutexes, and does not take any.
+- */
+-static int container_tasks_open(struct inode *unused, struct file *file)
+-{
+-      struct container *cont = __d_cont(file->f_dentry->d_parent);
+-      struct ctr_struct *ctr;
+-      pid_t *pidarray;
+-      int npids;
+-      char c;
 -
--static struct xattr_handler *shmem_xattr_handlers[] = {
--      &shmem_xattr_acl_access_handler,
--      &shmem_xattr_acl_default_handler,
--      &shmem_xattr_security_handler,
--      NULL
--};
--#endif
+-      if (!(file->f_mode & FMODE_READ))
+-              return 0;
 -
--static struct dentry *shmem_get_parent(struct dentry *child)
--{
--      return ERR_PTR(-ESTALE);
+-      ctr = kmalloc(sizeof(*ctr), GFP_KERNEL);
+-      if (!ctr)
+-              goto err0;
+-
+-      /*
+-       * If container gets more users after we read count, we won't have
+-       * enough space - tough.  This race is indistinguishable to the
+-       * caller from the case that the additional container users didn't
+-       * show up until sometime later on.
+-       */
+-      npids = container_task_count(cont);
+-      if (npids) {
+-              pidarray = kmalloc(npids * sizeof(pid_t), GFP_KERNEL);
+-              if (!pidarray)
+-                      goto err1;
+-
+-              npids = pid_array_load(pidarray, npids, cont);
+-              sort(pidarray, npids, sizeof(pid_t), cmppid, NULL);
+-
+-              /* Call pid_array_to_buf() twice, first just to get bufsz */
+-              ctr->bufsz = pid_array_to_buf(&c, sizeof(c), pidarray, npids) + 1;
+-              ctr->buf = kmalloc(ctr->bufsz, GFP_KERNEL);
+-              if (!ctr->buf)
+-                      goto err2;
+-              ctr->bufsz = pid_array_to_buf(ctr->buf, ctr->bufsz, pidarray, npids);
+-
+-              kfree(pidarray);
+-      } else {
+-              ctr->buf = 0;
+-              ctr->bufsz = 0;
+-      }
+-      file->private_data = ctr;
+-      return 0;
+-
+-err2:
+-      kfree(pidarray);
+-err1:
+-      kfree(ctr);
+-err0:
+-      return -ENOMEM;
 -}
 -
--static int shmem_match(struct inode *ino, void *vfh)
+-static ssize_t container_tasks_read(struct container *cont,
+-                                  struct cftype *cft,
+-                                  struct file *file, char __user *buf,
+-                                  size_t nbytes, loff_t *ppos)
 -{
--      __u32 *fh = vfh;
--      __u64 inum = fh[2];
--      inum = (inum << 32) | fh[1];
--      return ino->i_ino == inum && fh[0] == ino->i_generation;
+-      struct ctr_struct *ctr = file->private_data;
+-
+-      return simple_read_from_buffer(buf, nbytes, ppos, ctr->buf, ctr->bufsz);
 -}
 -
--static struct dentry *shmem_get_dentry(struct super_block *sb, void *vfh)
+-static int container_tasks_release(struct inode *unused_inode,
+-                                      struct file *file)
 -{
--      struct dentry *de = NULL;
--      struct inode *inode;
--      __u32 *fh = vfh;
--      __u64 inum = fh[2];
--      inum = (inum << 32) | fh[1];
+-      struct ctr_struct *ctr;
 -
--      inode = ilookup5(sb, (unsigned long)(inum+fh[0]), shmem_match, vfh);
--      if (inode) {
--              de = d_find_alias(inode);
--              iput(inode);
+-      if (file->f_mode & FMODE_READ) {
+-              ctr = file->private_data;
+-              kfree(ctr->buf);
+-              kfree(ctr);
 -      }
--
--      return de? de: ERR_PTR(-ESTALE);
+-      return 0;
 -}
 -
--static struct dentry *shmem_decode_fh(struct super_block *sb, __u32 *fh,
--              int len, int type,
--              int (*acceptable)(void *context, struct dentry *de),
--              void *context)
+-static u64 container_read_notify_on_release(struct container *cont,
+-                                          struct cftype *cft)
 -{
--      if (len < 3)
--              return ERR_PTR(-ESTALE);
--
--      return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable,
--                                                      context);
+-      return notify_on_release(cont);
 -}
 -
--static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
--                              int connectable)
+-static u64 container_read_releasable(struct container *cont, struct cftype *cft)
 -{
--      struct inode *inode = dentry->d_inode;
--
--      if (*len < 3)
--              return 255;
+-      return test_bit(CONT_RELEASABLE, &cont->flags);
+-}
 -
--      if (hlist_unhashed(&inode->i_hash)) {
--              /* Unfortunately insert_inode_hash is not idempotent,
--               * so as we hash inodes here rather than at creation
--               * time, we need a lock to ensure we only try
--               * to do it once
--               */
--              static DEFINE_SPINLOCK(lock);
--              spin_lock(&lock);
--              if (hlist_unhashed(&inode->i_hash))
--                      __insert_inode_hash(inode,
--                                          inode->i_ino + inode->i_generation);
--              spin_unlock(&lock);
--      }
+-/*
+- * for the common functions, 'private' gives the type of file
+- */
+-static struct cftype files[] = {
+-      {
+-              .name = "tasks",
+-              .open = container_tasks_open,
+-              .read = container_tasks_read,
+-              .write = container_common_file_write,
+-              .release = container_tasks_release,
+-              .private = FILE_TASKLIST,
+-      },
 -
--      fh[0] = inode->i_generation;
--      fh[1] = inode->i_ino;
--      fh[2] = ((__u64)inode->i_ino) >> 32;
+-      {
+-              .name = "notify_on_release",
+-              .read_uint = container_read_notify_on_release,
+-              .write = container_common_file_write,
+-              .private = FILE_NOTIFY_ON_RELEASE,
+-      },
 -
--      *len = 3;
--      return 1;
--}
+-      {
+-              .name = "releasable",
+-              .read_uint = container_read_releasable,
+-              .private = FILE_RELEASABLE,
+-      }
+-};
 -
--static struct export_operations shmem_export_ops = {
--      .get_parent     = shmem_get_parent,
--      .get_dentry     = shmem_get_dentry,
--      .encode_fh      = shmem_encode_fh,
--      .decode_fh      = shmem_decode_fh,
+-static struct cftype cft_release_agent = {
+-      .name = "release_agent",
+-      .read = container_common_file_read,
+-      .write = container_common_file_write,
+-      .private = FILE_RELEASE_AGENT,
 -};
 -
--static int shmem_parse_options(char *options, int *mode, uid_t *uid,
--      gid_t *gid, unsigned long *blocks, unsigned long *inodes,
--      int *policy, nodemask_t *policy_nodes)
+-static int container_populate_dir(struct container *cont)
 -{
--      char *this_char, *value, *rest;
+-      int err;
+-      struct container_subsys *ss;
 -
--      while (options != NULL) {
--              this_char = options;
--              for (;;) {
--                      /*
--                       * NUL-terminate this option: unfortunately,
--                       * mount options form a comma-separated list,
--                       * but mpol's nodelist may also contain commas.
--                       */
--                      options = strchr(options, ',');
--                      if (options == NULL)
--                              break;
--                      options++;
--                      if (!isdigit(*options)) {
--                              options[-1] = '\0';
--                              break;
--                      }
--              }
--              if (!*this_char)
--                      continue;
--              if ((value = strchr(this_char,'=')) != NULL) {
--                      *value++ = 0;
--              } else {
--                      printk(KERN_ERR
--                          "tmpfs: No value for mount option '%s'\n",
--                          this_char);
--                      return 1;
--              }
+-      /* First clear out any existing files */
+-      container_clear_directory(cont->dentry);
 -
--              if (!strcmp(this_char,"size")) {
--                      unsigned long long size;
--                      size = memparse(value,&rest);
--                      if (*rest == '%') {
--                              size <<= PAGE_SHIFT;
--                              size *= totalram_pages;
--                              do_div(size, 100);
--                              rest++;
--                      }
--                      if (*rest)
--                              goto bad_val;
--                      *blocks = size >> PAGE_CACHE_SHIFT;
--              } else if (!strcmp(this_char,"nr_blocks")) {
--                      *blocks = memparse(value,&rest);
--                      if (*rest)
--                              goto bad_val;
--              } else if (!strcmp(this_char,"nr_inodes")) {
--                      *inodes = memparse(value,&rest);
--                      if (*rest)
--                              goto bad_val;
--              } else if (!strcmp(this_char,"mode")) {
--                      if (!mode)
--                              continue;
--                      *mode = simple_strtoul(value,&rest,8);
--                      if (*rest)
--                              goto bad_val;
--              } else if (!strcmp(this_char,"uid")) {
--                      if (!uid)
--                              continue;
--                      *uid = simple_strtoul(value,&rest,0);
--                      if (*rest)
--                              goto bad_val;
--              } else if (!strcmp(this_char,"gid")) {
--                      if (!gid)
--                              continue;
--                      *gid = simple_strtoul(value,&rest,0);
--                      if (*rest)
--                              goto bad_val;
--              } else if (!strcmp(this_char,"mpol")) {
--                      if (shmem_parse_mpol(value,policy,policy_nodes))
--                              goto bad_val;
--              } else {
--                      printk(KERN_ERR "tmpfs: Bad mount option %s\n",
--                             this_char);
--                      return 1;
--              }
+-      err = container_add_files(cont, files, ARRAY_SIZE(files));
+-      if (err < 0)
+-              return err;
+-
+-      if (cont == cont->top_container) {
+-              if ((err = container_add_file(cont, &cft_release_agent)) < 0)
+-                      return err;
 -      }
--      return 0;
 -
--bad_val:
--      printk(KERN_ERR "tmpfs: Bad value '%s' for mount option '%s'\n",
--             value, this_char);
--      return 1;
+-      for_each_subsys(cont->root, ss) {
+-              if (ss->populate && (err = ss->populate(ss, cont)) < 0)
+-                      return err;
+-      }
 -
+-      return 0;
 -}
 -
--static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
+-static void init_container_css(struct container_subsys *ss,
+-                             struct container *cont)
 -{
--      struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
--      unsigned long max_blocks = sbinfo->max_blocks;
--      unsigned long max_inodes = sbinfo->max_inodes;
--      int policy = sbinfo->policy;
--      nodemask_t policy_nodes = sbinfo->policy_nodes;
--      unsigned long blocks;
--      unsigned long inodes;
--      int error = -EINVAL;
+-      struct container_subsys_state *css = cont->subsys[ss->subsys_id];
+-      css->container = cont;
+-      atomic_set(&css->refcnt, 0);
+-}
 -
--      if (shmem_parse_options(data, NULL, NULL, NULL, &max_blocks,
--                              &max_inodes, &policy, &policy_nodes))
--              return error;
+-/*
+- *    container_create - create a container
+- *    parent: container that will be parent of the new container.
+- *    name:           name of the new container. Will be strcpy'ed.
+- *    mode:           mode to set on new inode
+- *
+- *    Must be called with the mutex on the parent inode held
+- */
 -
--      spin_lock(&sbinfo->stat_lock);
--      blocks = sbinfo->max_blocks - sbinfo->free_blocks;
--      inodes = sbinfo->max_inodes - sbinfo->free_inodes;
--      if (max_blocks < blocks)
--              goto out;
--      if (max_inodes < inodes)
--              goto out;
--      /*
--       * Those tests also disallow limited->unlimited while any are in
--       * use, so i_blocks will always be zero when max_blocks is zero;
--       * but we must separately disallow unlimited->limited, because
--       * in that case we have no record of how much is already in use.
--       */
--      if (max_blocks && !sbinfo->max_blocks)
--              goto out;
--      if (max_inodes && !sbinfo->max_inodes)
--              goto out;
+-static long container_create(struct container *parent, struct dentry *dentry,
+-                           int mode)
+-{
+-      struct container *cont;
+-      struct containerfs_root *root = parent->root;
+-      int err = 0;
+-      struct container_subsys *ss;
+-      struct super_block *sb = root->sb;
 -
--      error = 0;
--      sbinfo->max_blocks  = max_blocks;
--      sbinfo->free_blocks = max_blocks - blocks;
--      sbinfo->max_inodes  = max_inodes;
--      sbinfo->free_inodes = max_inodes - inodes;
--      sbinfo->policy = policy;
--      sbinfo->policy_nodes = policy_nodes;
--out:
--      spin_unlock(&sbinfo->stat_lock);
--      return error;
--}
--#endif
+-      cont = kzalloc(sizeof(*cont), GFP_KERNEL);
+-      if (!cont)
+-              return -ENOMEM;
 -
--static void shmem_put_super(struct super_block *sb)
--{
--      kfree(sb->s_fs_info);
--      sb->s_fs_info = NULL;
--}
+-      /* Grab a reference on the superblock so the hierarchy doesn't
+-       * get deleted on unmount if there are child containers.  This
+-       * can be done outside container_mutex, since the sb can't
+-       * disappear while someone has an open control file on the
+-       * fs */
+-      atomic_inc(&sb->s_active);
 -
--static int shmem_fill_super(struct super_block *sb,
--                          void *data, int silent)
--{
--      struct inode *inode;
--      struct dentry *root;
--      int mode   = S_IRWXUGO | S_ISVTX;
--      uid_t uid = current->fsuid;
--      gid_t gid = current->fsgid;
--      int err = -ENOMEM;
--      struct shmem_sb_info *sbinfo;
--      unsigned long blocks = 0;
--      unsigned long inodes = 0;
--      int policy = MPOL_DEFAULT;
--      nodemask_t policy_nodes = node_online_map;
+-      mutex_lock(&container_mutex);
 -
--#ifdef CONFIG_TMPFS
--      /*
--       * Per default we only allow half of the physical ram per
--       * tmpfs instance, limiting inodes to one per page of lowmem;
--       * but the internal instance is left unlimited.
--       */
--      if (!(sb->s_flags & MS_NOUSER)) {
--              blocks = totalram_pages / 2;
--              inodes = totalram_pages - totalhigh_pages;
--              if (inodes > blocks)
--                      inodes = blocks;
--              if (shmem_parse_options(data, &mode, &uid, &gid, &blocks,
--                                      &inodes, &policy, &policy_nodes))
--                      return -EINVAL;
+-      cont->flags = 0;
+-      INIT_LIST_HEAD(&cont->sibling);
+-      INIT_LIST_HEAD(&cont->children);
+-      INIT_LIST_HEAD(&cont->css_groups);
+-      INIT_LIST_HEAD(&cont->release_list);
+-
+-      cont->parent = parent;
+-      cont->root = parent->root;
+-      cont->top_container = parent->top_container;
+-
+-      for_each_subsys(root, ss) {
+-              err = ss->create(ss, cont);
+-              if (err)
+-                      goto err_destroy;
+-              init_container_css(ss, cont);
 -      }
--      sb->s_export_op = &shmem_export_ops;
--#else
--      sb->s_flags |= MS_NOUSER;
--#endif
 -
--      /* Round up to L1_CACHE_BYTES to resist false sharing */
--      sbinfo = kmalloc(max((int)sizeof(struct shmem_sb_info),
--                              L1_CACHE_BYTES), GFP_KERNEL);
--      if (!sbinfo)
--              return -ENOMEM;
+-      list_add(&cont->sibling, &cont->parent->children);
+-      root->number_of_containers++;
 -
--      spin_lock_init(&sbinfo->stat_lock);
--      sbinfo->max_blocks = blocks;
--      sbinfo->free_blocks = blocks;
--      sbinfo->max_inodes = inodes;
--      sbinfo->free_inodes = inodes;
--      sbinfo->policy = policy;
--      sbinfo->policy_nodes = policy_nodes;
+-      err = container_create_dir(cont, dentry, mode);
+-      if (err < 0)
+-              goto err_remove;
 -
--      sb->s_fs_info = sbinfo;
--      sb->s_maxbytes = SHMEM_MAX_BYTES;
--      sb->s_blocksize = PAGE_CACHE_SIZE;
--      sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
--      sb->s_magic = TMPFS_MAGIC;
--      sb->s_op = &shmem_ops;
--      sb->s_time_gran = 1;
--#ifdef CONFIG_TMPFS_POSIX_ACL
--      sb->s_xattr = shmem_xattr_handlers;
--      sb->s_flags |= MS_POSIXACL;
--#endif
+-      /* The container directory was pre-locked for us */
+-      BUG_ON(!mutex_is_locked(&cont->dentry->d_inode->i_mutex));
+-
+-      err = container_populate_dir(cont);
+-      /* If err < 0, we have a half-filled directory - oh well ;) */
+-
+-      mutex_unlock(&container_mutex);
+-      mutex_unlock(&cont->dentry->d_inode->i_mutex);
 -
--      inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
--      if (!inode)
--              goto failed;
--      inode->i_uid = uid;
--      inode->i_gid = gid;
--      root = d_alloc_root(inode);
--      if (!root)
--              goto failed_iput;
--      sb->s_root = root;
 -      return 0;
 -
--failed_iput:
--      iput(inode);
--failed:
--      shmem_put_super(sb);
--      return err;
--}
+- err_remove:
 -
--static struct kmem_cache *shmem_inode_cachep;
+-      list_del(&cont->sibling);
+-      root->number_of_containers--;
 -
--static struct inode *shmem_alloc_inode(struct super_block *sb)
--{
--      struct shmem_inode_info *p;
--      p = (struct shmem_inode_info *)kmem_cache_alloc(shmem_inode_cachep, GFP_KERNEL);
--      if (!p)
--              return NULL;
--      return &p->vfs_inode;
--}
+- err_destroy:
 -
--static void shmem_destroy_inode(struct inode *inode)
--{
--      if ((inode->i_mode & S_IFMT) == S_IFREG) {
--              /* only struct inode is valid if it's an inline symlink */
--              mpol_free_shared_policy(&SHMEM_I(inode)->policy);
+-      for_each_subsys(root, ss) {
+-              if (cont->subsys[ss->subsys_id])
+-                      ss->destroy(ss, cont);
 -      }
--      shmem_acl_destroy_inode(inode);
--      kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
+-
+-      mutex_unlock(&container_mutex);
+-
+-      /* Release the reference count that we took on the superblock */
+-      deactivate_super(sb);
+-
+-      kfree(cont);
+-      return err;
 -}
 -
--static void init_once(void *foo, struct kmem_cache *cachep,
--                    unsigned long flags)
+-static int container_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 -{
--      struct shmem_inode_info *p = (struct shmem_inode_info *) foo;
+-      struct container *c_parent = dentry->d_parent->d_fsdata;
 -
--      inode_init_once(&p->vfs_inode);
--#ifdef CONFIG_TMPFS_POSIX_ACL
--      p->i_acl = NULL;
--      p->i_default_acl = NULL;
--#endif
+-      /* the vfs holds inode->i_mutex already */
+-      return container_create(c_parent, dentry, mode | S_IFDIR);
 -}
 -
--static int init_inodecache(void)
+-static inline int container_has_css_refs(struct container *cont)
 -{
--      shmem_inode_cachep = kmem_cache_create("shmem_inode_cache",
--                              sizeof(struct shmem_inode_info),
--                              0, 0, init_once, NULL);
--      if (shmem_inode_cachep == NULL)
--              return -ENOMEM;
+-      /* Check the reference count on each subsystem. Since we
+-       * already established that there are no tasks in the
+-       * container, if the css refcount is also 0, then there should
+-       * be no outstanding references, so the subsystem is safe to
+-       * destroy */
+-      struct container_subsys *ss;
+-      for_each_subsys(cont->root, ss) {
+-              struct container_subsys_state *css;
+-              css = cont->subsys[ss->subsys_id];
+-              if (atomic_read(&css->refcnt)) {
+-                      return 1;
+-              }
+-      }
 -      return 0;
 -}
 -
--static void destroy_inodecache(void)
+-static int container_rmdir(struct inode *unused_dir, struct dentry *dentry)
 -{
--      kmem_cache_destroy(shmem_inode_cachep);
--}
--
--static const struct address_space_operations shmem_aops = {
--      .writepage      = shmem_writepage,
--      .set_page_dirty = __set_page_dirty_no_writeback,
--#ifdef CONFIG_TMPFS
--      .prepare_write  = shmem_prepare_write,
--      .commit_write   = simple_commit_write,
--#endif
--      .migratepage    = migrate_page,
--};
+-      struct container *cont = dentry->d_fsdata;
+-      struct dentry *d;
+-      struct container *parent;
+-      struct container_subsys *ss;
+-      struct super_block *sb;
+-      struct containerfs_root *root;
 -
--static const struct file_operations shmem_file_operations = {
--      .mmap           = shmem_mmap,
--#ifdef CONFIG_TMPFS
--      .llseek         = generic_file_llseek,
--      .read           = shmem_file_read,
--      .write          = shmem_file_write,
--      .fsync          = simple_sync_file,
--      .sendfile       = shmem_file_sendfile,
--#endif
--};
+-      /* the vfs holds both inode->i_mutex already */
 -
--static const struct inode_operations shmem_inode_operations = {
--      .truncate       = shmem_truncate,
--      .setattr        = shmem_notify_change,
--      .truncate_range = shmem_truncate_range,
--#ifdef CONFIG_TMPFS_POSIX_ACL
--      .setxattr       = generic_setxattr,
--      .getxattr       = generic_getxattr,
--      .listxattr      = generic_listxattr,
--      .removexattr    = generic_removexattr,
--      .permission     = shmem_permission,
--#endif
+-      mutex_lock(&container_mutex);
+-      if (atomic_read(&cont->count) != 0) {
+-              mutex_unlock(&container_mutex);
+-              return -EBUSY;
+-      }
+-      if (!list_empty(&cont->children)) {
+-              mutex_unlock(&container_mutex);
+-              return -EBUSY;
+-      }
 -
--};
+-      parent = cont->parent;
+-      root = cont->root;
+-      sb = root->sb;
 -
--static const struct inode_operations shmem_dir_inode_operations = {
--#ifdef CONFIG_TMPFS
--      .create         = shmem_create,
--      .lookup         = simple_lookup,
--      .link           = shmem_link,
--      .unlink         = shmem_unlink,
--      .symlink        = shmem_symlink,
--      .mkdir          = shmem_mkdir,
--      .rmdir          = shmem_rmdir,
--      .mknod          = shmem_mknod,
--      .rename         = shmem_rename,
--#endif
--#ifdef CONFIG_TMPFS_POSIX_ACL
--      .setattr        = shmem_notify_change,
--      .setxattr       = generic_setxattr,
--      .getxattr       = generic_getxattr,
--      .listxattr      = generic_listxattr,
--      .removexattr    = generic_removexattr,
--      .permission     = shmem_permission,
--#endif
--};
+-      if (container_has_css_refs(cont)) {
+-              mutex_unlock(&container_mutex);
+-              return -EBUSY;
+-      }
 -
--static const struct inode_operations shmem_special_inode_operations = {
--#ifdef CONFIG_TMPFS_POSIX_ACL
--      .setattr        = shmem_notify_change,
--      .setxattr       = generic_setxattr,
--      .getxattr       = generic_getxattr,
--      .listxattr      = generic_listxattr,
--      .removexattr    = generic_removexattr,
--      .permission     = shmem_permission,
--#endif
--};
+-      for_each_subsys(root, ss) {
+-              if (cont->subsys[ss->subsys_id])
+-                      ss->destroy(ss, cont);
+-      }
 -
--static const struct super_operations shmem_ops = {
--      .alloc_inode    = shmem_alloc_inode,
--      .destroy_inode  = shmem_destroy_inode,
--#ifdef CONFIG_TMPFS
--      .statfs         = shmem_statfs,
--      .remount_fs     = shmem_remount_fs,
--#endif
--      .delete_inode   = shmem_delete_inode,
--      .drop_inode     = generic_delete_inode,
--      .put_super      = shmem_put_super,
--};
+-      set_bit(CONT_REMOVED, &cont->flags);
+-      /* delete my sibling from parent->children */
+-      list_del(&cont->sibling);
+-      spin_lock(&cont->dentry->d_lock);
+-      d = dget(cont->dentry);
+-      cont->dentry = NULL;
+-      spin_unlock(&d->d_lock);
 -
--static struct vm_operations_struct shmem_vm_ops = {
--      .nopage         = shmem_nopage,
--      .populate       = shmem_populate,
--#ifdef CONFIG_NUMA
--      .set_policy     = shmem_set_policy,
--      .get_policy     = shmem_get_policy,
--#endif
--};
+-      container_d_remove_dir(d);
+-      dput(d);
+-      root->number_of_containers--;
 -
+-      if (!list_empty(&cont->release_list))
+-              list_del(&cont->release_list);
+-      set_bit(CONT_RELEASABLE, &parent->flags);
+-      check_for_release(parent);
 -
--static int shmem_get_sb(struct file_system_type *fs_type,
--      int flags, const char *dev_name, void *data, struct vfsmount *mnt)
--{
--      return get_sb_nodev(fs_type, flags, data, shmem_fill_super, mnt);
+-      mutex_unlock(&container_mutex);
+-      /* Drop the active superblock reference that we took when we
+-       * created the container */
+-      deactivate_super(sb);
+-      return 0;
 -}
 -
--static struct file_system_type tmpfs_fs_type = {
--      .owner          = THIS_MODULE,
--      .name           = "tmpfs",
--      .get_sb         = shmem_get_sb,
--      .kill_sb        = kill_litter_super,
--};
--static struct vfsmount *shm_mnt;
--
--static int __init init_tmpfs(void)
+-static void container_init_subsys(struct container_subsys *ss)
 -{
--      int error;
+-      int retval;
+-      struct container_subsys_state *css;
+-      struct list_head *l;
+-      printk(KERN_ERR "Initializing container subsys %s\n", ss->name);
+-
+-      /* Create the top container state for this subsystem */
+-      ss->root = &rootnode;
+-      retval = ss->create(ss, dummytop);
+-      BUG_ON(retval);
+-      BUG_ON(!dummytop->subsys[ss->subsys_id]);
+-      init_container_css(ss, dummytop);
+-      css = dummytop->subsys[ss->subsys_id];
+-
+-      /* Update all container groups to contain a subsys
+-       * pointer to this state - since the subsystem is
+-       * newly registered, all tasks and hence all container
+-       * groups are in the subsystem's top container. */
+-      write_lock(&css_group_lock);
+-      l = &init_css_group.list;
+-      do {
+-              struct css_group *cg =
+-                      list_entry(l, struct css_group, list);
+-              cg->subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id];
+-              l = l->next;
+-      } while (l != &init_css_group.list);
+-      write_unlock(&css_group_lock);
 -
--      error = init_inodecache();
--      if (error)
--              goto out3;
+-      /* If this subsystem requested that it be notified with fork
+-       * events, we should send it one now for every process in the
+-       * system */
+-      if (ss->fork) {
+-              struct task_struct *g, *p;
 -
--      error = register_filesystem(&tmpfs_fs_type);
--      if (error) {
--              printk(KERN_ERR "Could not register tmpfs\n");
--              goto out2;
--      }
+-              read_lock(&tasklist_lock);
+-              do_each_thread(g, p) {
+-                      ss->fork(ss, p);
+-              } while_each_thread(g, p);
+-              read_unlock(&tasklist_lock);
+-      }
 -
--      shm_mnt = vfs_kern_mount(&tmpfs_fs_type, MS_NOUSER,
--                              tmpfs_fs_type.name, NULL);
--      if (IS_ERR(shm_mnt)) {
--              error = PTR_ERR(shm_mnt);
--              printk(KERN_ERR "Could not kern_mount tmpfs\n");
--              goto out1;
--      }
--      return 0;
+-      need_forkexit_callback |= ss->fork || ss->exit;
 -
--out1:
--      unregister_filesystem(&tmpfs_fs_type);
--out2:
--      destroy_inodecache();
--out3:
--      shm_mnt = ERR_PTR(error);
--      return error;
+-      ss->active = 1;
 -}
--module_init(init_tmpfs)
 -
--/*
-- * shmem_file_setup - get an unlinked file living in tmpfs
-- *
-- * @name: name for dentry (to be seen in /proc/<pid>/maps
-- * @size: size to be set for the file
-- *
+-/**
+- * container_init_early - initialize containers at system boot, and
+- * initialize any subsystems that request early init.
 - */
--struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
+-int __init container_init_early(void)
 -{
--      int error;
--      struct file *file;
--      struct inode *inode;
--      struct dentry *dentry, *root;
--      struct qstr this;
--
--      if (IS_ERR(shm_mnt))
--              return (void *)shm_mnt;
--
--      if (size < 0 || size > SHMEM_MAX_BYTES)
--              return ERR_PTR(-EINVAL);
--
--      if (shmem_acct_size(flags, size))
--              return ERR_PTR(-ENOMEM);
--
--      error = -ENOMEM;
--      this.name = name;
--      this.len = strlen(name);
--      this.hash = 0; /* will go */
--      root = shm_mnt->mnt_root;
--      dentry = d_alloc(root, &this);
--      if (!dentry)
--              goto put_memory;
--
--      error = -ENFILE;
--      file = get_empty_filp();
--      if (!file)
--              goto put_dentry;
--
--      error = -ENOSPC;
--      inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
--      if (!inode)
--              goto close_file;
+-      int i;
+-      kref_init(&init_css_group.ref);
+-      kref_get(&init_css_group.ref);
+-      INIT_LIST_HEAD(&init_css_group.list);
+-      INIT_LIST_HEAD(&init_css_group.cg_links);
+-      INIT_LIST_HEAD(&init_css_group.tasks);
+-      css_group_count = 1;
+-      init_container_root(&rootnode);
+-      init_task.containers = &init_css_group;
+-
+-      init_css_group_link.cg = &init_css_group;
+-      list_add(&init_css_group_link.cont_link_list,
+-               &rootnode.top_container.css_groups);
+-      list_add(&init_css_group_link.cg_link_list,
+-               &init_css_group.cg_links);
+-
+-      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
+-              struct container_subsys *ss = subsys[i];
+-
+-              BUG_ON(!ss->name);
+-              BUG_ON(strlen(ss->name) > MAX_CONTAINER_TYPE_NAMELEN);
+-              BUG_ON(!ss->create);
+-              BUG_ON(!ss->destroy);
+-              if (ss->subsys_id != i) {
+-                      printk(KERN_ERR "Subsys %s id == %d\n",
+-                             ss->name, ss->subsys_id);
+-                      BUG();
+-              }
 -
--      SHMEM_I(inode)->flags = flags & VM_ACCOUNT;
--      d_instantiate(dentry, inode);
--      inode->i_size = size;
--      inode->i_nlink = 0;     /* It is unlinked */
--      file->f_path.mnt = mntget(shm_mnt);
--      file->f_path.dentry = dentry;
--      file->f_mapping = inode->i_mapping;
--      file->f_op = &shmem_file_operations;
--      file->f_mode = FMODE_WRITE | FMODE_READ;
--      return file;
--
--close_file:
--      put_filp(file);
--put_dentry:
--      dput(dentry);
--put_memory:
--      shmem_unacct_size(flags, size);
--      return ERR_PTR(error);
+-              if (ss->early_init)
+-                      container_init_subsys(ss);
+-      }
+-      return 0;
 -}
 -
--/*
-- * shmem_zero_setup - setup a shared anonymous mapping
-- *
-- * @vma: the vma to be mmapped is prepared by do_mmap_pgoff
+-/**
+- * container_init - register container filesystem and /proc file, and
+- * initialize any subsystems that didn't request early init.
 - */
--int shmem_zero_setup(struct vm_area_struct *vma)
+-int __init container_init(void)
 -{
--      struct file *file;
--      loff_t size = vma->vm_end - vma->vm_start;
--
--      file = shmem_file_setup("dev/zero", size, vma->vm_flags);
--      if (IS_ERR(file))
--              return PTR_ERR(file);
+-      int err;
+-      int i;
+-      struct proc_dir_entry *entry;
 -
--      if (vma->vm_file)
--              fput(vma->vm_file);
--      vma->vm_file = file;
--      vma->vm_ops = &shmem_vm_ops;
--      return 0;
--}
-diff -Nurb linux-2.6.22-570/mm/slab.c linux-2.6.22-590/mm/slab.c
---- linux-2.6.22-570/mm/slab.c 2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/mm/slab.c 2008-01-02 13:56:38.000000000 -0500
-@@ -1639,6 +1639,8 @@
- #endif
-       flags |= cachep->gfpflags;
-+      if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
-+              flags |= __GFP_RECLAIMABLE;
-       page = alloc_pages_node(nodeid, flags, cachep->gfporder);
-       if (!page)
-diff -Nurb linux-2.6.22-570/mm/slub.c linux-2.6.22-590/mm/slub.c
---- linux-2.6.22-570/mm/slub.c 2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/mm/slub.c 2008-01-02 13:56:38.000000000 -0500
-@@ -985,6 +985,9 @@
-       if (s->flags & SLAB_CACHE_DMA)
-               flags |= SLUB_DMA;
-+      if (s->flags & SLAB_RECLAIM_ACCOUNT)
-+              flags |= __GFP_RECLAIMABLE;
-+
-       if (node == -1)
-               page = alloc_pages(flags, s->order);
-       else
-@@ -1989,6 +1992,7 @@
- #ifdef CONFIG_NUMA
-       s->defrag_ratio = 100;
- #endif
-+      raise_kswapd_order(s->order);
-       if (init_kmem_cache_nodes(s, gfpflags & ~SLUB_DMA))
-               return 1;
-diff -Nurb linux-2.6.22-570/mm/swap_state.c linux-2.6.22-590/mm/swap_state.c
---- linux-2.6.22-570/mm/swap_state.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/mm/swap_state.c   2008-01-02 13:56:38.000000000 -0500
-@@ -334,7 +334,8 @@
-                * Get a new page to read into from swap.
-                */
-               if (!new_page) {
--                      new_page = alloc_page_vma(GFP_HIGHUSER, vma, addr);
-+                      new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE,
-+                                                              vma, addr);
-                       if (!new_page)
-                               break;          /* Out of memory */
-               }
-diff -Nurb linux-2.6.22-570/mm/truncate.c linux-2.6.22-590/mm/truncate.c
---- linux-2.6.22-570/mm/truncate.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/mm/truncate.c     2008-01-02 13:56:38.000000000 -0500
-@@ -82,7 +82,7 @@
- /*
-  * If truncate cannot remove the fs-private metadata from the page, the page
-  * becomes anonymous.  It will be left on the LRU and may even be mapped into
-- * user pagetables if we're racing with filemap_nopage().
-+ * user pagetables if we're racing with filemap_fault().
-  *
-  * We need to bale out if page->mapping is no longer equal to the original
-  * mapping.  This happens a) when the VM reclaimed the page while we waited on
-@@ -192,6 +192,11 @@
-                               unlock_page(page);
-                               continue;
-                       }
-+                      if (page_mapped(page)) {
-+                              unmap_mapping_range(mapping,
-+                                (loff_t)page_index<<PAGE_CACHE_SHIFT,
-+                                PAGE_CACHE_SIZE, 0);
-+                      }
-                       truncate_complete_page(mapping, page);
-                       unlock_page(page);
-               }
-@@ -229,6 +234,11 @@
-                               break;
-                       lock_page(page);
-                       wait_on_page_writeback(page);
-+                      if (page_mapped(page)) {
-+                              unmap_mapping_range(mapping,
-+                                (loff_t)page->index<<PAGE_CACHE_SHIFT,
-+                                PAGE_CACHE_SIZE, 0);
-+                      }
-                       if (page->index > next)
-                               next = page->index;
-                       next++;
-@@ -397,7 +407,7 @@
-                               break;
-                       }
-                       wait_on_page_writeback(page);
--                      while (page_mapped(page)) {
-+                      if (page_mapped(page)) {
-                               if (!did_range_unmap) {
-                                       /*
-                                        * Zap the rest of the file in one hit.
-@@ -417,6 +427,7 @@
-                                         PAGE_CACHE_SIZE, 0);
-                               }
-                       }
-+                      BUG_ON(page_mapped(page));
-                       ret = do_launder_page(mapping, page);
-                       if (ret == 0 && !invalidate_complete_page2(mapping, page))
-                               ret = -EIO;
-diff -Nurb linux-2.6.22-570/mm/util.c linux-2.6.22-590/mm/util.c
---- linux-2.6.22-570/mm/util.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/mm/util.c 2008-01-02 13:56:38.000000000 -0500
-@@ -18,9 +18,8 @@
- }
- EXPORT_SYMBOL(__kzalloc);
--/*
-+/**
-  * kstrdup - allocate space for and copy an existing string
-- *
-  * @s: the string to duplicate
-  * @gfp: the GFP mask used in the kmalloc() call when allocating memory
-  */
-@@ -41,6 +40,32 @@
- EXPORT_SYMBOL(kstrdup);
- /**
-+ * kstrndup - allocate space for and copy an existing string
-+ * @s: the string to duplicate
-+ * @max: read at most @max chars from @s
-+ * @gfp: the GFP mask used in the kmalloc() call when allocating memory
-+ */
-+char *kstrndup(const char *s, size_t max, gfp_t gfp)
-+{
-+      size_t len;
-+      char *buf;
-+
-+      if (!s)
-+              return NULL;
-+
-+      len = strlen(s);
-+      if (len > max)
-+              len = max;
-+      buf = kmalloc_track_caller(len+1, gfp);
-+      if (buf) {
-+              memcpy(buf, s, len);
-+              buf[len] = '\0';
-+      }
-+      return buf;
-+}
-+EXPORT_SYMBOL(kstrndup);
-+
-+/**
-  * kmemdup - duplicate region of memory
-  *
-  * @src: memory region to duplicate
-@@ -60,7 +85,6 @@
- /*
-  * strndup_user - duplicate an existing string from user space
-- *
-  * @s: The string to duplicate
-  * @n: Maximum number of bytes to copy, including the trailing NUL.
-  */
-diff -Nurb linux-2.6.22-570/mm/vmalloc.c linux-2.6.22-590/mm/vmalloc.c
---- linux-2.6.22-570/mm/vmalloc.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/mm/vmalloc.c      2008-01-02 13:56:38.000000000 -0500
-@@ -68,12 +68,12 @@
-       } while (pud++, addr = next, addr != end);
- }
--void unmap_vm_area(struct vm_struct *area)
-+void unmap_kernel_range(unsigned long addr, unsigned long size)
- {
-       pgd_t *pgd;
-       unsigned long next;
--      unsigned long addr = (unsigned long) area->addr;
--      unsigned long end = addr + area->size;
-+      unsigned long start = addr;
-+      unsigned long end = addr + size;
-       BUG_ON(addr >= end);
-       pgd = pgd_offset_k(addr);
-@@ -84,7 +84,12 @@
-                       continue;
-               vunmap_pud_range(pgd, addr, next);
-       } while (pgd++, addr = next, addr != end);
--      flush_tlb_kernel_range((unsigned long) area->addr, end);
-+      flush_tlb_kernel_range(start, end);
-+}
-+
-+static void unmap_vm_area(struct vm_struct *area)
-+{
-+      unmap_kernel_range((unsigned long)area->addr, area->size);
- }
- static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
-diff -Nurb linux-2.6.22-570/mm/vmscan.c linux-2.6.22-590/mm/vmscan.c
---- linux-2.6.22-570/mm/vmscan.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/mm/vmscan.c       2008-01-02 13:56:38.000000000 -0500
-@@ -1272,6 +1272,34 @@
-       return nr_reclaimed;
- }
-+static unsigned int kswapd_min_order __read_mostly;
-+
-+static inline int kswapd_order(unsigned int order)
-+{
-+      return max(kswapd_min_order, order);
-+}
-+
-+/**
-+ * raise_kswapd_order - Raise the minimum order that kswapd reclaims
-+ * @order: The minimum order kswapd should reclaim at
-+ *
-+ * kswapd normally reclaims at order 0 unless there is a higher-order
-+ * allocation being serviced. This function is used to set the minimum
-+ * order that kswapd reclaims at when it is known there will be regular
-+ * high-order allocations at a given order.
-+ */
-+void raise_kswapd_order(unsigned int order)
-+{
-+      if (order >= MAX_ORDER)
-+              return;
-+
-+      /* Update order if necessary and inform if changed */
-+      if (order > kswapd_min_order) {
-+              kswapd_min_order = order;
-+              printk(KERN_INFO "kswapd reclaim order set to %d\n", order);
-+      }
-+}
-+
- /*
-  * The background pageout daemon, started as a kernel thread
-  * from the init process. 
-@@ -1314,13 +1342,14 @@
-        * trying to free the first piece of memory in the first place).
-        */
-       tsk->flags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
-+      set_freezable();
--      order = 0;
-+      order = kswapd_order(0);
-       for ( ; ; ) {
-               unsigned long new_order;
-               prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE);
--              new_order = pgdat->kswapd_max_order;
-+              new_order = kswapd_order(pgdat->kswapd_max_order);
-               pgdat->kswapd_max_order = 0;
-               if (order < new_order) {
-                       /*
-@@ -1332,7 +1361,7 @@
-                       if (!freezing(current))
-                               schedule();
--                      order = pgdat->kswapd_max_order;
-+                      order = kswapd_order(pgdat->kswapd_max_order);
-               }
-               finish_wait(&pgdat->kswapd_wait, &wait);
-diff -Nurb linux-2.6.22-570/net/802/tr.c linux-2.6.22-590/net/802/tr.c
---- linux-2.6.22-570/net/802/tr.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/802/tr.c      2008-01-02 13:56:38.000000000 -0500
-@@ -36,6 +36,7 @@
- #include <linux/seq_file.h>
- #include <linux/init.h>
- #include <net/arp.h>
-+#include <net/net_namespace.h>
- static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev);
- static void rif_check_expire(unsigned long dummy);
-@@ -532,7 +533,7 @@
-               seq_puts(seq,
-                    "if     TR address       TTL   rcf   routing segments\n");
-       else {
--              struct net_device *dev = dev_get_by_index(entry->iface);
-+              struct net_device *dev = dev_get_by_index(&init_net, entry->iface);
-               long ttl = (long) (entry->last_used + sysctl_tr_rif_timeout)
-                               - (long) jiffies;
-@@ -639,7 +640,7 @@
-       rif_timer.function = rif_check_expire;
-       add_timer(&rif_timer);
--      proc_net_fops_create("tr_rif", S_IRUGO, &rif_seq_fops);
-+      proc_net_fops_create(&init_net, "tr_rif", S_IRUGO, &rif_seq_fops);
-       return 0;
- }
-diff -Nurb linux-2.6.22-570/net/8021q/Makefile linux-2.6.22-590/net/8021q/Makefile
---- linux-2.6.22-570/net/8021q/Makefile        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/8021q/Makefile        2008-01-02 13:56:38.000000000 -0500
-@@ -4,7 +4,7 @@
- obj-$(CONFIG_VLAN_8021Q) += 8021q.o
--8021q-objs := vlan.o vlan_dev.o
-+8021q-objs := vlan.o vlan_dev.o vlan_netlink.o
- ifeq ($(CONFIG_PROC_FS),y)
- 8021q-objs += vlanproc.o
-diff -Nurb linux-2.6.22-570/net/8021q/vlan.c linux-2.6.22-590/net/8021q/vlan.c
---- linux-2.6.22-570/net/8021q/vlan.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/8021q/vlan.c  2008-01-02 13:56:38.000000000 -0500
-@@ -31,6 +31,7 @@
- #include <net/arp.h>
- #include <linux/rtnetlink.h>
- #include <linux/notifier.h>
-+#include <net/net_namespace.h>
- #include <linux/if_vlan.h>
- #include "vlan.h"
-@@ -50,7 +51,7 @@
- static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
- static int vlan_device_event(struct notifier_block *, unsigned long, void *);
--static int vlan_ioctl_handler(void __user *);
-+static int vlan_ioctl_handler(struct net *net, void __user *);
- static int unregister_vlan_dev(struct net_device *, unsigned short );
- static struct notifier_block vlan_notifier_block = {
-@@ -97,15 +98,22 @@
-       /* Register us to receive netdevice events */
-       err = register_netdevice_notifier(&vlan_notifier_block);
--      if (err < 0) {
--              dev_remove_pack(&vlan_packet_type);
--              vlan_proc_cleanup();
--              return err;
+-      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
+-              struct container_subsys *ss = subsys[i];
+-              if (!ss->early_init)
+-                      container_init_subsys(ss);
 -      }
-+      if (err < 0)
-+              goto err1;
--      vlan_ioctl_set(vlan_ioctl_handler);
-+      err = vlan_netlink_init();
-+      if (err < 0)
-+              goto err2;
-+      vlan_ioctl_set(vlan_ioctl_handler);
-       return 0;
-+
-+err2:
-+      unregister_netdevice_notifier(&vlan_notifier_block);
-+err1:
-+      vlan_proc_cleanup();
-+      dev_remove_pack(&vlan_packet_type);
-+      return err;
- }
- /* Cleanup all vlan devices
-@@ -117,7 +125,7 @@
-       struct net_device *dev, *nxt;
-       rtnl_lock();
--      for_each_netdev_safe(dev, nxt) {
-+      for_each_netdev_safe(&init_net, dev, nxt) {
-               if (dev->priv_flags & IFF_802_1Q_VLAN) {
-                       unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
-                                           VLAN_DEV_INFO(dev)->vlan_id);
-@@ -136,6 +144,7 @@
- {
-       int i;
-+      vlan_netlink_fini();
-       vlan_ioctl_set(NULL);
-       /* Un-register us from receiving netdevice events */
-@@ -197,6 +206,34 @@
-       kfree(grp);
- }
-+static struct vlan_group *vlan_group_alloc(int ifindex)
-+{
-+      struct vlan_group *grp;
-+      unsigned int size;
-+      unsigned int i;
-+
-+      grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
-+      if (!grp)
-+              return NULL;
-+
-+      size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
-+
-+      for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
-+              grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL);
-+              if (!grp->vlan_devices_arrays[i])
-+                      goto err;
-+      }
-+
-+      grp->real_dev_ifindex = ifindex;
-+      hlist_add_head_rcu(&grp->hlist,
-+                         &vlan_group_hash[vlan_grp_hashfn(ifindex)]);
-+      return grp;
-+
-+err:
-+      vlan_group_free(grp);
-+      return NULL;
-+}
-+
- static void vlan_rcu_free(struct rcu_head *rcu)
- {
-       vlan_group_free(container_of(rcu, struct vlan_group, rcu));
-@@ -278,47 +315,62 @@
-       return ret;
- }
--static int unregister_vlan_device(const char *vlan_IF_name)
-+int unregister_vlan_device(struct net_device *dev)
- {
--      struct net_device *dev = NULL;
-       int ret;
 -
--      dev = dev_get_by_name(vlan_IF_name);
--      ret = -EINVAL;
--      if (dev) {
--              if (dev->priv_flags & IFF_802_1Q_VLAN) {
--                      rtnl_lock();
+-      err = register_filesystem(&container_fs_type);
+-      if (err < 0)
+-              goto out;
 -
-                       ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
-                                                 VLAN_DEV_INFO(dev)->vlan_id);
+-      entry = create_proc_entry("containers", 0, NULL);
+-      if (entry)
+-              entry->proc_fops = &proc_containerstats_operations;
 -
--                      dev_put(dev);
-                       unregister_netdevice(dev);
--                      rtnl_unlock();
+-out:
+-      return err;
+-}
 -
-                       if (ret == 1)
-                               ret = 0;
-+      return ret;
-+}
-+
-+/*
-+ * vlan network devices have devices nesting below it, and are a special
-+ * "super class" of normal network devices; split their locks off into a
-+ * separate class since they always nest.
-+ */
-+static struct lock_class_key vlan_netdev_xmit_lock_key;
-+
-+static int vlan_dev_init(struct net_device *dev)
-+{
-+      struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
-+
-+      /* IFF_BROADCAST|IFF_MULTICAST; ??? */
-+      dev->flags  = real_dev->flags & ~IFF_UP;
-+      dev->iflink = real_dev->ifindex;
-+      dev->state  = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
-+                                        (1<<__LINK_STATE_DORMANT))) |
-+                    (1<<__LINK_STATE_PRESENT);
-+
-+      /* TODO: maybe just assign it to be ETHERNET? */
-+      dev->type = real_dev->type;
-+
-+      memcpy(dev->broadcast, real_dev->broadcast, real_dev->addr_len);
-+      memcpy(dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
-+      dev->addr_len = real_dev->addr_len;
-+
-+      if (real_dev->features & NETIF_F_HW_VLAN_TX) {
-+              dev->hard_header     = real_dev->hard_header;
-+              dev->hard_header_len = real_dev->hard_header_len;
-+              dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
-+              dev->rebuild_header  = real_dev->rebuild_header;
-               } else {
--                      printk(VLAN_ERR
--                             "%s: ERROR:      Tried to remove a non-vlan device "
--                             "with VLAN code, name: %s  priv_flags: %hX\n",
--                             __FUNCTION__, dev->name, dev->priv_flags);
--                      dev_put(dev);
--                      ret = -EPERM;
--              }
--      } else {
--#ifdef VLAN_DEBUG
--              printk(VLAN_DBG "%s: WARNING: Could not find dev.\n", __FUNCTION__);
--#endif
--              ret = -EINVAL;
-+              dev->hard_header     = vlan_dev_hard_header;
-+              dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
-+              dev->hard_start_xmit = vlan_dev_hard_start_xmit;
-+              dev->rebuild_header  = vlan_dev_rebuild_header;
-       }
-+      dev->hard_header_parse = real_dev->hard_header_parse;
--      return ret;
-+      lockdep_set_class(&dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
-+      return 0;
- }
--static void vlan_setup(struct net_device *new_dev)
-+void vlan_setup(struct net_device *new_dev)
- {
-       SET_MODULE_OWNER(new_dev);
-@@ -338,6 +390,7 @@
-       /* set up method calls */
-       new_dev->change_mtu = vlan_dev_change_mtu;
-+      new_dev->init = vlan_dev_init;
-       new_dev->open = vlan_dev_open;
-       new_dev->stop = vlan_dev_stop;
-       new_dev->set_mac_address = vlan_dev_set_mac_address;
-@@ -366,77 +419,110 @@
-       }
- }
 -/*
-- * vlan network devices have devices nesting below it, and are a special
-- * "super class" of normal network devices; split their locks off into a
-- * separate class since they always nest.
+- * proc_container_show()
+- *  - Print task's container paths into seq_file, one line for each hierarchy
+- *  - Used for /proc/<pid>/container.
+- *  - No need to task_lock(tsk) on this tsk->container reference, as it
+- *    doesn't really matter if tsk->container changes after we read it,
+- *    and we take container_mutex, keeping attach_task() from changing it
+- *    anyway.  No need to check that tsk->container != NULL, thanks to
+- *    the_top_container_hack in container_exit(), which sets an exiting tasks
+- *    container to top_container.
 - */
--static struct lock_class_key vlan_netdev_xmit_lock_key;
 -
+-/* TODO: Use a proper seq_file iterator */
+-static int proc_container_show(struct seq_file *m, void *v)
+-{
+-      struct pid *pid;
+-      struct task_struct *tsk;
+-      char *buf;
+-      int retval;
+-      struct containerfs_root *root;
+-
+-      retval = -ENOMEM;
+-      buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+-      if (!buf)
+-              goto out;
 -
--/*  Attach a VLAN device to a mac address (ie Ethernet Card).
-- *  Returns the device that was created, or NULL if there was
-- *  an error of some kind.
-- */
--static struct net_device *register_vlan_device(const char *eth_IF_name,
--                                             unsigned short VLAN_ID)
-+int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id)
- {
--      struct vlan_group *grp;
--      struct net_device *new_dev;
--      struct net_device *real_dev; /* the ethernet device */
--      char name[IFNAMSIZ];
--      int i;
+-      retval = -ESRCH;
+-      pid = m->private;
+-      tsk = get_pid_task(pid, PIDTYPE_PID);
+-      if (!tsk)
+-              goto out_free;
 -
--#ifdef VLAN_DEBUG
--      printk(VLAN_DBG "%s: if_name -:%s:-     vid: %i\n",
--              __FUNCTION__, eth_IF_name, VLAN_ID);
--#endif
+-      retval = 0;
 -
--      if (VLAN_ID >= VLAN_VID_MASK)
--              goto out_ret_null;
+-      mutex_lock(&container_mutex);
 -
--      /* find the device relating to eth_IF_name. */
--      real_dev = dev_get_by_name(eth_IF_name);
--      if (!real_dev)
--              goto out_ret_null;
+-      for_each_root(root) {
+-              struct container_subsys *ss;
+-              struct container *cont;
+-              int subsys_id;
+-              int count = 0;
 -
-       if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
-               printk(VLAN_DBG "%s: VLANs not supported on %s.\n",
-                       __FUNCTION__, real_dev->name);
--              goto out_put_dev;
-+              return -EOPNOTSUPP;
-       }
-       if ((real_dev->features & NETIF_F_HW_VLAN_RX) &&
-           !real_dev->vlan_rx_register) {
-               printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
-                       __FUNCTION__, real_dev->name);
--              goto out_put_dev;
-+              return -EOPNOTSUPP;
-       }
-       if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
-           (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) {
-               printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
-                       __FUNCTION__, real_dev->name);
--              goto out_put_dev;
-+              return -EOPNOTSUPP;
-       }
--      /* From this point on, all the data structures must remain
--       * consistent.
--       */
--      rtnl_lock();
+-              /* Skip this hierarchy if it has no active subsystems */
+-              if (!root->subsys_bits)
+-                      continue;
+-              for_each_subsys(root, ss)
+-                      seq_printf(m, "%s%s", count++ ? "," : "", ss->name);
+-              seq_putc(m, ':');
+-              get_first_subsys(&root->top_container, NULL, &subsys_id);
+-              cont = task_container(tsk, subsys_id);
+-              retval = container_path(cont, buf, PAGE_SIZE);
+-              if (retval < 0)
+-                      goto out_unlock;
+-              seq_puts(m, buf);
+-              seq_putc(m, '\n');
+-      }
 -
-       /* The real device must be up and operating in order to
-        * assosciate a VLAN device with it.
-        */
-       if (!(real_dev->flags & IFF_UP))
--              goto out_unlock;
-+              return -ENETDOWN;
--      if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) {
-+      if (__find_vlan_dev(real_dev, vlan_id) != NULL) {
-               /* was already registered. */
-               printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__);
--              goto out_unlock;
-+              return -EEXIST;
-       }
-+      return 0;
-+}
-+
-+int register_vlan_dev(struct net_device *dev)
-+{
-+      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
-+      struct net_device *real_dev = vlan->real_dev;
-+      unsigned short vlan_id = vlan->vlan_id;
-+      struct vlan_group *grp, *ngrp = NULL;
-+      int err;
-+
-+      grp = __vlan_find_group(real_dev->ifindex);
-+      if (!grp) {
-+              ngrp = grp = vlan_group_alloc(real_dev->ifindex);
-+              if (!grp)
-+                      return -ENOBUFS;
-+      }
-+
-+      err = register_netdevice(dev);
-+      if (err < 0)
-+              goto out_free_group;
-+
-+      /* Account for reference in struct vlan_dev_info */
-+      dev_hold(real_dev);
-+
-+      vlan_transfer_operstate(real_dev, dev);
-+      linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */
-+
-+      /* So, got the sucker initialized, now lets place
-+       * it into our local structure.
-+       */
-+      vlan_group_set_device(grp, vlan_id, dev);
-+      if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
-+              real_dev->vlan_rx_register(real_dev, ngrp);
-+      if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
-+              real_dev->vlan_rx_add_vid(real_dev, vlan_id);
-+
-+      if (vlan_proc_add_dev(dev) < 0)
-+              printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
-+                     dev->name);
-+      return 0;
-+
-+out_free_group:
-+      if (ngrp)
-+              vlan_group_free(ngrp);
-+      return err;
-+}
-+
-+/*  Attach a VLAN device to a mac address (ie Ethernet Card).
-+ *  Returns 0 if the device was created or a negative error code otherwise.
-+ */
-+static int register_vlan_device(struct net_device *real_dev,
-+                              unsigned short VLAN_ID)
-+{
-+      struct net_device *new_dev;
-+      char name[IFNAMSIZ];
-+      int err;
-+
-+#ifdef VLAN_DEBUG
-+      printk(VLAN_DBG "%s: if_name -:%s:-     vid: %i\n",
-+              __FUNCTION__, eth_IF_name, VLAN_ID);
-+#endif
-+
-+      if (VLAN_ID >= VLAN_VID_MASK)
-+              return -ERANGE;
-+
-+      err = vlan_check_real_dev(real_dev, VLAN_ID);
-+      if (err < 0)
-+              return err;
-+
-       /* Gotta set up the fields for the device. */
- #ifdef VLAN_DEBUG
-       printk(VLAN_DBG "About to allocate name, vlan_name_type: %i\n",
-@@ -471,138 +557,40 @@
-                              vlan_setup);
-       if (new_dev == NULL)
--              goto out_unlock;
+-out_unlock:
+-      mutex_unlock(&container_mutex);
+-      put_task_struct(tsk);
+-out_free:
+-      kfree(buf);
+-out:
+-      return retval;
+-}
 -
--#ifdef VLAN_DEBUG
--      printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
--#endif
--      /* IFF_BROADCAST|IFF_MULTICAST; ??? */
--      new_dev->flags = real_dev->flags;
--      new_dev->flags &= ~IFF_UP;
+-static int container_open(struct inode *inode, struct file *file)
+-{
+-      struct pid *pid = PROC_I(inode)->pid;
+-      return single_open(file, proc_container_show, pid);
+-}
 -
--      new_dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
--                                           (1<<__LINK_STATE_DORMANT))) |
--                       (1<<__LINK_STATE_PRESENT);
-+              return -ENOBUFS;
-       /* need 4 bytes for extra VLAN header info,
-        * hope the underlying device can handle it.
-        */
-       new_dev->mtu = real_dev->mtu;
--      /* TODO: maybe just assign it to be ETHERNET? */
--      new_dev->type = real_dev->type;
+-struct file_operations proc_container_operations = {
+-      .open           = container_open,
+-      .read           = seq_read,
+-      .llseek         = seq_lseek,
+-      .release        = single_release,
+-};
 -
--      new_dev->hard_header_len = real_dev->hard_header_len;
--      if (!(real_dev->features & NETIF_F_HW_VLAN_TX)) {
--              /* Regular ethernet + 4 bytes (18 total). */
--              new_dev->hard_header_len += VLAN_HLEN;
+-/* Display information about each subsystem and each hierarchy */
+-static int proc_containerstats_show(struct seq_file *m, void *v)
+-{
+-      int i;
+-      struct containerfs_root *root;
+-
+-      mutex_lock(&container_mutex);
+-      seq_puts(m, "Hierarchies:\n");
+-      for_each_root(root) {
+-              struct container_subsys *ss;
+-              int first = 1;
+-              seq_printf(m, "%p: bits=%lx containers=%d (", root,
+-                         root->subsys_bits, root->number_of_containers);
+-              for_each_subsys(root, ss) {
+-                      seq_printf(m, "%s%s", first ? "" : ", ", ss->name);
+-                      first = false;
+-              }
+-              seq_putc(m, ')');
+-              if (root->sb) {
+-                      seq_printf(m, " s_active=%d",
+-                                 atomic_read(&root->sb->s_active));
+-              }
+-              seq_putc(m, '\n');
 -      }
+-      seq_puts(m, "Subsystems:\n");
+-      for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
+-              struct container_subsys *ss = subsys[i];
+-              seq_printf(m, "%d: name=%s hierarchy=%p\n",
+-                         i, ss->name, ss->root);
+-      }
+-      seq_printf(m, "Container groups: %d\n", css_group_count);
+-      mutex_unlock(&container_mutex);
+-      return 0;
+-}
 -
-+#ifdef VLAN_DEBUG
-+      printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
-       VLAN_MEM_DBG("new_dev->priv malloc, addr: %p  size: %i\n",
-                    new_dev->priv,
-                    sizeof(struct vlan_dev_info));
+-static int containerstats_open(struct inode *inode, struct file *file)
+-{
+-      return single_open(file, proc_containerstats_show, 0);
+-}
 -
--      memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len);
--      memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
--      new_dev->addr_len = real_dev->addr_len;
+-static struct file_operations proc_containerstats_operations = {
+-      .open = containerstats_open,
+-      .read = seq_read,
+-      .llseek = seq_lseek,
+-      .release = single_release,
+-};
 -
--      if (real_dev->features & NETIF_F_HW_VLAN_TX) {
--              new_dev->hard_header = real_dev->hard_header;
--              new_dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
--              new_dev->rebuild_header = real_dev->rebuild_header;
--      } else {
--              new_dev->hard_header = vlan_dev_hard_header;
--              new_dev->hard_start_xmit = vlan_dev_hard_start_xmit;
--              new_dev->rebuild_header = vlan_dev_rebuild_header;
+-/**
+- * container_fork - attach newly forked task to its parents container.
+- * @tsk: pointer to task_struct of forking parent process.
+- *
+- * Description: A task inherits its parent's container at fork().
+- *
+- * A pointer to the shared css_group was automatically copied in
+- * fork.c by dup_task_struct().  However, we ignore that copy, since
+- * it was not made under the protection of RCU or container_mutex, so
+- * might no longer be a valid container pointer.  attach_task() might
+- * have already changed current->containers, allowing the previously
+- * referenced container group to be removed and freed.
+- *
+- * At the point that container_fork() is called, 'current' is the parent
+- * task, and the passed argument 'child' points to the child task.
+- */
+-void container_fork(struct task_struct *child)
+-{
+-      write_lock(&css_group_lock);
+-      child->containers = current->containers;
+-      get_css_group(child->containers);
+-      list_add(&child->cg_list, &child->containers->tasks);
+-      write_unlock(&css_group_lock);
+-}
+-
+-/**
+- * container_fork_callbacks - called on a new task very soon before
+- * adding it to the tasklist. No need to take any locks since no-one
+- * can be operating on this task
+- */
+-void container_fork_callbacks(struct task_struct *child)
+-{
+-      if (need_forkexit_callback) {
+-              int i;
+-              for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
+-                      struct container_subsys *ss = subsys[i];
+-                      if (ss->fork)
+-                              ss->fork(ss, child);
+-              }
 -      }
--      new_dev->hard_header_parse = real_dev->hard_header_parse;
-+#endif
-       VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */
-       VLAN_DEV_INFO(new_dev)->real_dev = real_dev;
-       VLAN_DEV_INFO(new_dev)->dent = NULL;
--      VLAN_DEV_INFO(new_dev)->flags = 1;
-+      VLAN_DEV_INFO(new_dev)->flags = VLAN_FLAG_REORDER_HDR;
--#ifdef VLAN_DEBUG
--      printk(VLAN_DBG "About to go find the group for idx: %i\n",
--             real_dev->ifindex);
--#endif
+-}
 -
--      if (register_netdevice(new_dev))
-+      new_dev->rtnl_link_ops = &vlan_link_ops;
-+      err = register_vlan_dev(new_dev);
-+      if (err < 0)
-               goto out_free_newdev;
--      lockdep_set_class(&new_dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
+-/**
+- * container_exit - detach container from exiting task
+- * @tsk: pointer to task_struct of exiting process
+- *
+- * Description: Detach container from @tsk and release it.
+- *
+- * Note that containers marked notify_on_release force every task in
+- * them to take the global container_mutex mutex when exiting.
+- * This could impact scaling on very large systems.  Be reluctant to
+- * use notify_on_release containers where very high task exit scaling
+- * is required on large systems.
+- *
+- * the_top_container_hack:
+- *
+- *    Set the exiting tasks container to the root container (top_container).
+- *
+- *    We call container_exit() while the task is still competent to
+- *    handle notify_on_release(), then leave the task attached to the
+- *    root container in each hierarchy for the remainder of its exit.
+- *
+- *    To do this properly, we would increment the reference count on
+- *    top_container, and near the very end of the kernel/exit.c do_exit()
+- *    code we would add a second container function call, to drop that
+- *    reference.  This would just create an unnecessary hot spot on
+- *    the top_container reference count, to no avail.
+- *
+- *    Normally, holding a reference to a container without bumping its
+- *    count is unsafe.   The container could go away, or someone could
+- *    attach us to a different container, decrementing the count on
+- *    the first container that we never incremented.  But in this case,
+- *    top_container isn't going away, and either task has PF_EXITING set,
+- *    which wards off any attach_task() attempts, or task is a failed
+- *    fork, never visible to attach_task.
+- *
+- */
+-void container_exit(struct task_struct *tsk, int run_callbacks)
+-{
+-      int i;
+-      struct css_group *cg = NULL;
 -
--      new_dev->iflink = real_dev->ifindex;
--      vlan_transfer_operstate(real_dev, new_dev);
--      linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */
+-      if (run_callbacks && need_forkexit_callback) {
+-              for (i = 0; i < CONTAINER_SUBSYS_COUNT; i++) {
+-                      struct container_subsys *ss = subsys[i];
+-                      if (ss->exit)
+-                              ss->exit(ss, tsk);
+-              }
+-      }
 -
--      /* So, got the sucker initialized, now lets place
--       * it into our local structure.
--       */
--      grp = __vlan_find_group(real_dev->ifindex);
+-      /* Reassign the task to the init_css_group. */
+-      task_lock(tsk);
+-      write_lock(&css_group_lock);
+-      list_del(&tsk->cg_list);
+-      write_unlock(&css_group_lock);
 -
--      /* Note, we are running under the RTNL semaphore
--       * so it cannot "appear" on us.
--       */
--      if (!grp) { /* need to add a new group */
--              grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
--              if (!grp)
--                      goto out_free_unregister;
+-      cg = tsk->containers;
+-      tsk->containers = &init_css_group;
+-      task_unlock(tsk);
+-      if (cg)
+-              put_css_group_taskexit(cg);
+-}
 -
--              for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
--                      grp->vlan_devices_arrays[i] = kzalloc(
--                              sizeof(struct net_device *)*VLAN_GROUP_ARRAY_PART_LEN,
--                              GFP_KERNEL);
+-/**
+- * container_clone - duplicate the current container in the hierarchy
+- * that the given subsystem is attached to, and move this task into
+- * the new child
+- */
+-int container_clone(struct task_struct *tsk, struct container_subsys *subsys)
+-{
+-      struct dentry *dentry;
+-      int ret = 0;
+-      char nodename[MAX_CONTAINER_TYPE_NAMELEN];
+-      struct container *parent, *child;
+-      struct inode *inode;
+-      struct css_group *cg;
+-      struct containerfs_root *root;
+-      struct container_subsys *ss;
+-
+-      /* We shouldn't be called by an unregistered subsystem */
+-      BUG_ON(!subsys->active);
+-
+-      /* First figure out what hierarchy and container we're dealing
+-       * with, and pin them so we can drop container_mutex */
+-      mutex_lock(&container_mutex);
+- again:
+-      root = subsys->root;
+-      if (root == &rootnode) {
+-              printk(KERN_INFO
+-                     "Not cloning container for unused subsystem %s\n",
+-                     subsys->name);
+-              mutex_unlock(&container_mutex);
+-              return 0;
+-      }
+-      cg = tsk->containers;
+-      parent = task_container(tsk, subsys->subsys_id);
 -
--                      if (!grp->vlan_devices_arrays[i])
--                              goto out_free_arrays;
--              }
+-      snprintf(nodename, MAX_CONTAINER_TYPE_NAMELEN, "node_%d", tsk->pid);
 -
--              /* printk(KERN_ALERT "VLAN REGISTER:  Allocated new group.\n"); */
--              grp->real_dev_ifindex = real_dev->ifindex;
+-      /* Pin the hierarchy */
+-      atomic_inc(&parent->root->sb->s_active);
 -
--              hlist_add_head_rcu(&grp->hlist,
--                                 &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
+-      /* Keep the container alive */
+-      get_css_group(cg);
+-      mutex_unlock(&container_mutex);
 -
--              if (real_dev->features & NETIF_F_HW_VLAN_RX)
--                      real_dev->vlan_rx_register(real_dev, grp);
+-      /* Now do the VFS work to create a container */
+-      inode = parent->dentry->d_inode;
+-
+-      /* Hold the parent directory mutex across this operation to
+-       * stop anyone else deleting the new container */
+-      mutex_lock(&inode->i_mutex);
+-      dentry = container_get_dentry(parent->dentry, nodename);
+-      if (IS_ERR(dentry)) {
+-              printk(KERN_INFO
+-                     "Couldn't allocate dentry for %s: %ld\n", nodename,
+-                     PTR_ERR(dentry));
+-              ret = PTR_ERR(dentry);
+-              goto out_release;
 -      }
 -
--      vlan_group_set_device(grp, VLAN_ID, new_dev);
+-      /* Create the container directory, which also creates the container */
+-      ret = vfs_mkdir(inode, dentry, S_IFDIR | 0755, NULL);
+-      child = __d_cont(dentry);
+-      dput(dentry);
+-      if (ret) {
+-              printk(KERN_INFO
+-                     "Failed to create container %s: %d\n", nodename,
+-                     ret);
+-              goto out_release;
+-      }
 -
--      if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */
--              printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
--                                                       new_dev->name);
+-      if (!child) {
+-              printk(KERN_INFO
+-                     "Couldn't find new container %s\n", nodename);
+-              ret = -ENOMEM;
+-              goto out_release;
+-      }
 -
--      if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
--              real_dev->vlan_rx_add_vid(real_dev, VLAN_ID);
+-      /* The container now exists. Retake container_mutex and check
+-       * that we're still in the same state that we thought we
+-       * were. */
+-      mutex_lock(&container_mutex);
+-      if ((root != subsys->root) ||
+-          (parent != task_container(tsk, subsys->subsys_id))) {
+-              /* Aargh, we raced ... */
+-              mutex_unlock(&inode->i_mutex);
+-              put_css_group(cg);
+-
+-              deactivate_super(parent->root->sb);
+-              /* The container is still accessible in the VFS, but
+-               * we're not going to try to rmdir() it at this
+-               * point. */
+-              printk(KERN_INFO
+-                     "Race in container_clone() - leaking container %s\n",
+-                     nodename);
+-              goto again;
+-      }
 -
--      rtnl_unlock();
+-      /* do any required auto-setup */
+-      for_each_subsys(root, ss) {
+-              if (ss->post_clone)
+-                      ss->post_clone(ss, child);
+-      }
 -
+-      /* All seems fine. Finish by moving the task into the new container */
+-      ret = attach_task(child, tsk);
+-      mutex_unlock(&container_mutex);
 -
-+      /* Account for reference in struct vlan_dev_info */
-+      dev_hold(real_dev);
- #ifdef VLAN_DEBUG
-       printk(VLAN_DBG "Allocated new device successfully, returning.\n");
- #endif
--      return new_dev;
+- out_release:
+-      mutex_unlock(&inode->i_mutex);
 -
--out_free_arrays:
--      vlan_group_free(grp);
+-      mutex_lock(&container_mutex);
+-      put_css_group(cg);
+-      mutex_unlock(&container_mutex);
+-      deactivate_super(parent->root->sb);
+-      return ret;
+-}
 -
--out_free_unregister:
--      unregister_netdev(new_dev);
--      goto out_unlock;
-+      return 0;
- out_free_newdev:
-       free_netdev(new_dev);
+-/* See if "cont" is a descendant of the current task's container in
+- * the appropriate hierarchy */
 -
--out_unlock:
--      rtnl_unlock();
+-int container_is_descendant(const struct container *cont)
+-{
+-      int ret;
+-      struct container *target;
+-      int subsys_id;
 -
--out_put_dev:
--      dev_put(real_dev);
+-      if (cont == dummytop)
+-              return 1;
+-      get_first_subsys(cont, NULL, &subsys_id);
+-      target = task_container(current, subsys_id);
+-      while (cont != target && cont!= cont->top_container) {
+-              cont = cont->parent;
+-      }
+-      ret = (cont == target);
+-      return ret;
+-}
 -
--out_ret_null:
--      return NULL;
-+      return err;
- }
- static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
-@@ -612,6 +600,9 @@
-       int i, flgs;
-       struct net_device *vlandev;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (!grp)
-               goto out;
-@@ -691,11 +682,12 @@
-  *    o execute requested action or pass command to the device driver
-  *   arg is really a struct vlan_ioctl_args __user *.
-  */
--static int vlan_ioctl_handler(void __user *arg)
-+static int vlan_ioctl_handler(struct net *net, void __user *arg)
- {
--      int err = 0;
-+      int err;
-       unsigned short vid = 0;
-       struct vlan_ioctl_args args;
-+      struct net_device *dev = NULL;
-       if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
-               return -EFAULT;
-@@ -708,35 +700,61 @@
-       printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd);
- #endif
-+      rtnl_lock();
-+
-       switch (args.cmd) {
-       case SET_VLAN_INGRESS_PRIORITY_CMD:
-+      case SET_VLAN_EGRESS_PRIORITY_CMD:
-+      case SET_VLAN_FLAG_CMD:
-+      case ADD_VLAN_CMD:
-+      case DEL_VLAN_CMD:
-+      case GET_VLAN_REALDEV_NAME_CMD:
-+      case GET_VLAN_VID_CMD:
-+              err = -ENODEV;
-+              dev = __dev_get_by_name(&init_net, args.device1);
-+              if (!dev)
-+                      goto out;
-+
-+              err = -EINVAL;
-+              if (args.cmd != ADD_VLAN_CMD &&
-+                  !(dev->priv_flags & IFF_802_1Q_VLAN))
-+                      goto out;
-+      }
-+
-+      switch (args.cmd) {
-+      case SET_VLAN_INGRESS_PRIORITY_CMD:
-+              err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
--                      return -EPERM;
--              err = vlan_dev_set_ingress_priority(args.device1,
-+                      break;
-+              vlan_dev_set_ingress_priority(dev,
-                                                   args.u.skb_priority,
-                                                   args.vlan_qos);
-               break;
-       case SET_VLAN_EGRESS_PRIORITY_CMD:
-+              err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
--                      return -EPERM;
--              err = vlan_dev_set_egress_priority(args.device1,
-+                      break;
-+              err = vlan_dev_set_egress_priority(dev,
-                                                  args.u.skb_priority,
-                                                  args.vlan_qos);
-               break;
-       case SET_VLAN_FLAG_CMD:
-+              err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
--                      return -EPERM;
--              err = vlan_dev_set_vlan_flag(args.device1,
-+                      break;
-+              err = vlan_dev_set_vlan_flag(dev,
-                                            args.u.flag,
-                                            args.vlan_qos);
-               break;
-       case SET_VLAN_NAME_TYPE_CMD:
-+              err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
-                       return -EPERM;
--              if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) {
-+              if ((args.u.name_type >= 0) &&
-+                  (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
-                       vlan_name_type = args.u.name_type;
-                       err = 0;
-               } else {
-@@ -745,26 +763,17 @@
-               break;
-       case ADD_VLAN_CMD:
-+              err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
--                      return -EPERM;
--              /* we have been given the name of the Ethernet Device we want to
--               * talk to:  args.dev1   We also have the
--               * VLAN ID:  args.u.VID
--               */
--              if (register_vlan_device(args.device1, args.u.VID)) {
--                      err = 0;
--              } else {
--                      err = -EINVAL;
+-static void check_for_release(struct container *cont)
+-{
+-      BUG_ON(!mutex_is_locked(&container_mutex));
+-      if (container_is_releasable(cont) && !atomic_read(&cont->count)
+-          && list_empty(&cont->children) && !container_has_css_refs(cont)) {
+-              /* Container is currently removeable. If it's not
+-               * already queued for a userspace notification, queue
+-               * it now */
+-              if (list_empty(&cont->release_list)) {
+-                      list_add(&cont->release_list, &release_list);
+-                      schedule_work(&release_agent_work);
 -              }
-+                      break;
-+              err = register_vlan_device(dev, args.u.VID);
-               break;
-       case DEL_VLAN_CMD:
-+              err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
--                      return -EPERM;
--              /* Here, the args.dev1 is the actual VLAN we want
--               * to get rid of.
--               */
--              err = unregister_vlan_device(args.device1);
-+                      break;
-+              err = unregister_vlan_device(dev);
-               break;
-       case GET_VLAN_INGRESS_PRIORITY_CMD:
-@@ -788,9 +797,7 @@
-               err = -EINVAL;
-               break;
-       case GET_VLAN_REALDEV_NAME_CMD:
--              err = vlan_dev_get_realdev_name(args.device1, args.u.device2);
--              if (err)
--                      goto out;
-+              vlan_dev_get_realdev_name(dev, args.u.device2);
-               if (copy_to_user(arg, &args,
-                                sizeof(struct vlan_ioctl_args))) {
-                       err = -EFAULT;
-@@ -798,9 +805,7 @@
-               break;
-       case GET_VLAN_VID_CMD:
--              err = vlan_dev_get_vid(args.device1, &vid);
--              if (err)
--                      goto out;
-+              vlan_dev_get_vid(dev, &vid);
-               args.u.VID = vid;
-               if (copy_to_user(arg, &args,
-                                sizeof(struct vlan_ioctl_args))) {
-@@ -812,9 +817,11 @@
-               /* pass on to underlying device instead?? */
-               printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",
-                       __FUNCTION__, args.cmd);
--              return -EINVAL;
-+              err = -EINVAL;
-+              break;
-       }
- out:
-+      rtnl_unlock();
-       return err;
- }
-diff -Nurb linux-2.6.22-570/net/8021q/vlan.h linux-2.6.22-590/net/8021q/vlan.h
---- linux-2.6.22-570/net/8021q/vlan.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/8021q/vlan.h  2008-01-02 13:56:38.000000000 -0500
-@@ -62,11 +62,24 @@
- int vlan_dev_open(struct net_device* dev);
- int vlan_dev_stop(struct net_device* dev);
- int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd);
--int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
--int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
--int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
--int vlan_dev_get_realdev_name(const char* dev_name, char* result);
--int vlan_dev_get_vid(const char* dev_name, unsigned short* result);
-+void vlan_dev_set_ingress_priority(const struct net_device *dev,
-+                                 u32 skb_prio, short vlan_prio);
-+int vlan_dev_set_egress_priority(const struct net_device *dev,
-+                               u32 skb_prio, short vlan_prio);
-+int vlan_dev_set_vlan_flag(const struct net_device *dev,
-+                         u32 flag, short flag_val);
-+void vlan_dev_get_realdev_name(const struct net_device *dev, char *result);
-+void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result);
- void vlan_dev_set_multicast_list(struct net_device *vlan_dev);
-+int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id);
-+void vlan_setup(struct net_device *dev);
-+int register_vlan_dev(struct net_device *dev);
-+int unregister_vlan_device(struct net_device *dev);
-+
-+int vlan_netlink_init(void);
-+void vlan_netlink_fini(void);
-+
-+extern struct rtnl_link_ops vlan_link_ops;
-+
- #endif /* !(__BEN_VLAN_802_1Q_INC__) */
-diff -Nurb linux-2.6.22-570/net/8021q/vlan_dev.c linux-2.6.22-590/net/8021q/vlan_dev.c
---- linux-2.6.22-570/net/8021q/vlan_dev.c      2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/8021q/vlan_dev.c      2008-01-02 13:56:38.000000000 -0500
-@@ -73,7 +73,7 @@
- static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb)
- {
--      if (VLAN_DEV_INFO(skb->dev)->flags & 1) {
-+      if (VLAN_DEV_INFO(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) {
-               if (skb_shared(skb) || skb_cloned(skb)) {
-                       struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
-                       kfree_skb(skb);
-@@ -132,6 +132,11 @@
-       vhdr = (struct vlan_hdr *)(skb->data);
-+      if (dev->nd_net != &init_net) {
-+              kfree_skb(skb);
-+              return 0;
-+      }
-+
-       /* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */
-       vlan_TCI = ntohs(vhdr->h_vlan_TCI);
-@@ -360,7 +365,8 @@
-        * header shuffling in the hard_start_xmit.  Users can turn off this
-        * REORDER behaviour with the vconfig tool.
-        */
--      build_vlan_header = ((VLAN_DEV_INFO(dev)->flags & 1) == 0);
-+      if (!(VLAN_DEV_INFO(dev)->flags & VLAN_FLAG_REORDER_HDR))
-+              build_vlan_header = 1;
-       if (build_vlan_header) {
-               vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN);
-@@ -544,136 +550,83 @@
-       return 0;
- }
--int vlan_dev_set_ingress_priority(char *dev_name, __u32 skb_prio, short vlan_prio)
-+void vlan_dev_set_ingress_priority(const struct net_device *dev,
-+                                 u32 skb_prio, short vlan_prio)
- {
--      struct net_device *dev = dev_get_by_name(dev_name);
-+      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
--      if (dev) {
--              if (dev->priv_flags & IFF_802_1Q_VLAN) {
--                      /* see if a priority mapping exists.. */
--                      VLAN_DEV_INFO(dev)->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
--                      dev_put(dev);
--                      return 0;
+-      }
+-}
+-
+-void css_put(struct container_subsys_state *css)
+-{
+-      struct container *cont = css->container;
+-      if (notify_on_release(cont)) {
+-              mutex_lock(&container_mutex);
+-              set_bit(CONT_RELEASABLE, &cont->flags);
+-              if (atomic_dec_and_test(&css->refcnt)) {
+-                      check_for_release(cont);
 -              }
-+      if (vlan->ingress_priority_map[vlan_prio & 0x7] && !skb_prio)
-+              vlan->nr_ingress_mappings--;
-+      else if (!vlan->ingress_priority_map[vlan_prio & 0x7] && skb_prio)
-+              vlan->nr_ingress_mappings++;
--              dev_put(dev);
+-              mutex_unlock(&container_mutex);
+-      } else {
+-              atomic_dec(&css->refcnt);
 -      }
--      return -EINVAL;
-+      vlan->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
- }
--int vlan_dev_set_egress_priority(char *dev_name, __u32 skb_prio, short vlan_prio)
-+int vlan_dev_set_egress_priority(const struct net_device *dev,
-+                               u32 skb_prio, short vlan_prio)
- {
--      struct net_device *dev = dev_get_by_name(dev_name);
-+      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
-       struct vlan_priority_tci_mapping *mp = NULL;
-       struct vlan_priority_tci_mapping *np;
-+      u32 vlan_qos = (vlan_prio << 13) & 0xE000;
--      if (dev) {
--              if (dev->priv_flags & IFF_802_1Q_VLAN) {
-                       /* See if a priority mapping exists.. */
--                      mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF];
-+      mp = vlan->egress_priority_map[skb_prio & 0xF];
-                       while (mp) {
-                               if (mp->priority == skb_prio) {
--                                      mp->vlan_qos = ((vlan_prio << 13) & 0xE000);
--                                      dev_put(dev);
-+                      if (mp->vlan_qos && !vlan_qos)
-+                              vlan->nr_egress_mappings--;
-+                      else if (!mp->vlan_qos && vlan_qos)
-+                              vlan->nr_egress_mappings++;
-+                      mp->vlan_qos = vlan_qos;
-                                       return 0;
-                               }
-                               mp = mp->next;
-                       }
-                       /* Create a new mapping then. */
--                      mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF];
-+      mp = vlan->egress_priority_map[skb_prio & 0xF];
-                       np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL);
--                      if (np) {
-+      if (!np)
-+              return -ENOBUFS;
-+
-                               np->next = mp;
-                               np->priority = skb_prio;
--                              np->vlan_qos = ((vlan_prio << 13) & 0xE000);
--                              VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF] = np;
--                              dev_put(dev);
-+      np->vlan_qos = vlan_qos;
-+      vlan->egress_priority_map[skb_prio & 0xF] = np;
-+      if (vlan_qos)
-+              vlan->nr_egress_mappings++;
-                               return 0;
--                      } else {
--                              dev_put(dev);
--                              return -ENOBUFS;
--                      }
+-}
+-
+-void container_set_release_agent_path(struct container_subsys *ss,
+-                                    const char *path)
+-{
+-      mutex_lock(&container_mutex);
+-      strcpy(ss->root->release_agent_path, path);
+-      mutex_unlock(&container_mutex);
+-}
+-
+-/*
+- * Notify userspace when a container is released, by running the
+- * configured release agent with the name of the container (path
+- * relative to the root of container file system) as the argument.
+- *
+- * Most likely, this user command will try to rmdir this container.
+- *
+- * This races with the possibility that some other task will be
+- * attached to this container before it is removed, or that some other
+- * user task will 'mkdir' a child container of this container.  That's ok.
+- * The presumed 'rmdir' will fail quietly if this container is no longer
+- * unused, and this container will be reprieved from its death sentence,
+- * to continue to serve a useful existence.  Next time it's released,
+- * we will get notified again, if it still has 'notify_on_release' set.
+- *
+- * The final arg to call_usermodehelper() is UMH_WAIT_EXEC, which
+- * means only wait until the task is successfully execve()'d.  The
+- * separate release agent task is forked by call_usermodehelper(),
+- * then control in this thread returns here, without waiting for the
+- * release agent task.  We don't bother to wait because the caller of
+- * this routine has no use for the exit status of the release agent
+- * task, so no sense holding our caller up for that.
+- *
+- */
+-
+-static void container_release_agent(struct work_struct *work)
+-{
+-      BUG_ON(work != &release_agent_work);
+-      mutex_lock(&container_mutex);
+-      while (!list_empty(&release_list)) {
+-              char *argv[3], *envp[3];
+-              int i;
+-              char *pathbuf;
+-              struct container *cont = list_entry(release_list.next,
+-                                                  struct container,
+-                                                  release_list);
+-              list_del_init(&cont->release_list);
+-
+-              pathbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+-              if (!pathbuf)
+-                      continue;
+-
+-              if (container_path(cont, pathbuf, PAGE_SIZE) < 0) {
+-                      kfree(pathbuf);
+-                      continue;
 -              }
--              dev_put(dev);
+-
+-              i = 0;
+-              argv[i++] = cont->root->release_agent_path;
+-              argv[i++] = (char *)pathbuf;
+-              argv[i] = NULL;
+-
+-              i = 0;
+-              /* minimal command environment */
+-              envp[i++] = "HOME=/";
+-              envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+-              envp[i] = NULL;
+-
+-              /* Drop the lock while we invoke the usermode helper,
+-               * since the exec could involve hitting disk and hence
+-               * be a slow process */
+-              mutex_unlock(&container_mutex);
+-              call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
+-              kfree(pathbuf);
+-              mutex_lock(&container_mutex);
 -      }
--      return -EINVAL;
- }
--/* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */
--int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val)
-+/* Flags are defined in the vlan_flags enum in include/linux/if_vlan.h file. */
-+int vlan_dev_set_vlan_flag(const struct net_device *dev,
-+                         u32 flag, short flag_val)
- {
--      struct net_device *dev = dev_get_by_name(dev_name);
+-      mutex_unlock(&container_mutex);
+-}
+diff -Nurb linux-2.6.22-590/kernel/container_debug.c linux-2.6.22-570/kernel/container_debug.c
+--- linux-2.6.22-590/kernel/container_debug.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/container_debug.c  1969-12-31 19:00:00.000000000 -0500
+@@ -1,89 +0,0 @@
+-/*
+- * kernel/ccontainer_debug.c - Example container subsystem that
+- * exposes debug info
+- *
+- * Copyright (C) Google Inc, 2007
+- *
+- * Developed by Paul Menage (menage@google.com)
+- *
+- */
+-
+-#include <linux/container.h>
+-#include <linux/fs.h>
+-
+-static int debug_create(struct container_subsys *ss, struct container *cont)
+-{
+-      struct container_subsys_state *css = kzalloc(sizeof(*css), GFP_KERNEL);
+-      if (!css)
+-              return -ENOMEM;
+-      cont->subsys[debug_subsys_id] = css;
+-      return 0;
+-}
+-
+-static void debug_destroy(struct container_subsys *ss, struct container *cont)
+-{
+-      kfree(cont->subsys[debug_subsys_id]);
+-}
+-
+-static u64 container_refcount_read(struct container *cont, struct cftype *cft)
+-{
+-      return atomic_read(&cont->count);
+-}
+-
+-static u64 taskcount_read(struct container *cont, struct cftype *cft)
+-{
+-      u64 count;
+-      container_lock();
+-      count = container_task_count(cont);
+-      container_unlock();
+-      return count;
+-}
+-
+-static u64 current_css_group_read(struct container *cont, struct cftype *cft)
+-{
+-      return (u64) current->containers;
+-}
+-
+-static u64 current_css_group_refcount_read(struct container *cont,
+-                                         struct cftype *cft)
+-{
+-      u64 count;
+-      rcu_read_lock();
+-      count = atomic_read(&current->containers->ref.refcount);
+-      rcu_read_unlock();
+-      return count;
+-}
+-
+-static struct cftype files[] =  {
+-      {
+-              .name = "debug.container_refcount",
+-              .read_uint = container_refcount_read,
+-      },
+-      {
+-              .name = "debug.taskcount",
+-              .read_uint = taskcount_read,
+-      },
+-
+-      {
+-              .name = "debug.current_css_group",
+-              .read_uint = current_css_group_read,
+-      },
+-
+-      {
+-              .name = "debug.current_css_group_refcount",
+-              .read_uint = current_css_group_refcount_read,
+-      },
+-};
+-
+-static int debug_populate(struct container_subsys *ss, struct container *cont)
+-{
+-      return container_add_files(cont, files, ARRAY_SIZE(files));
+-}
+-
+-struct container_subsys debug_subsys = {
+-      .name = "debug",
+-      .create = debug_create,
+-      .destroy = debug_destroy,
+-      .populate = debug_populate,
+-      .subsys_id = debug_subsys_id,
+-};
+diff -Nurb linux-2.6.22-590/kernel/cpu_acct.c linux-2.6.22-570/kernel/cpu_acct.c
+--- linux-2.6.22-590/kernel/cpu_acct.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/cpu_acct.c 1969-12-31 19:00:00.000000000 -0500
+@@ -1,185 +0,0 @@
+-/*
+- * kernel/cpu_acct.c - CPU accounting container subsystem
+- *
+- * Copyright (C) Google Inc, 2006
+- *
+- * Developed by Paul Menage (menage@google.com) and Balbir Singh
+- * (balbir@in.ibm.com)
+- *
+- */
 -
--      if (dev) {
--              if (dev->priv_flags & IFF_802_1Q_VLAN) {
-                       /* verify flag is supported */
--                      if (flag == 1) {
-+      if (flag == VLAN_FLAG_REORDER_HDR) {
-                               if (flag_val) {
--                                      VLAN_DEV_INFO(dev)->flags |= 1;
-+                      VLAN_DEV_INFO(dev)->flags |= VLAN_FLAG_REORDER_HDR;
-                               } else {
--                                      VLAN_DEV_INFO(dev)->flags &= ~1;
-+                      VLAN_DEV_INFO(dev)->flags &= ~VLAN_FLAG_REORDER_HDR;
-                               }
--                              dev_put(dev);
-                               return 0;
--                      } else {
--                              printk(KERN_ERR  "%s: flag %i is not valid.\n",
--                                      __FUNCTION__, (int)(flag));
--                              dev_put(dev);
--                              return -EINVAL;
-                       }
+-/*
+- * Example container subsystem for reporting total CPU usage of tasks in a
+- * container, along with percentage load over a time interval
+- */
+-
+-#include <linux/module.h>
+-#include <linux/container.h>
+-#include <linux/fs.h>
+-#include <asm/div64.h>
+-
+-struct cpuacct {
+-      struct container_subsys_state css;
+-      spinlock_t lock;
+-      /* total time used by this class */
+-      cputime64_t time;
+-
+-      /* time when next load calculation occurs */
+-      u64 next_interval_check;
+-
+-      /* time used in current period */
+-      cputime64_t current_interval_time;
+-
+-      /* time used in last period */
+-      cputime64_t last_interval_time;
+-};
+-
+-struct container_subsys cpuacct_subsys;
+-
+-static inline struct cpuacct *container_ca(struct container *cont)
+-{
+-      return container_of(container_subsys_state(cont, cpuacct_subsys_id),
+-                          struct cpuacct, css);
+-}
+-
+-static inline struct cpuacct *task_ca(struct task_struct *task)
+-{
+-      return container_of(task_subsys_state(task, cpuacct_subsys_id),
+-                          struct cpuacct, css);
+-}
+-
+-#define INTERVAL (HZ * 10)
+-
+-static inline u64 next_interval_boundary(u64 now) {
+-      /* calculate the next interval boundary beyond the
+-       * current time */
+-      do_div(now, INTERVAL);
+-      return (now + 1) * INTERVAL;
+-}
+-
+-static int cpuacct_create(struct container_subsys *ss, struct container *cont)
+-{
+-      struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
+-      if (!ca)
+-              return -ENOMEM;
+-      spin_lock_init(&ca->lock);
+-      ca->next_interval_check = next_interval_boundary(get_jiffies_64());
+-      cont->subsys[cpuacct_subsys_id] = &ca->css;
+-      return 0;
+-}
+-
+-static void cpuacct_destroy(struct container_subsys *ss,
+-                          struct container *cont)
+-{
+-      kfree(container_ca(cont));
+-}
+-
+-/* Lazily update the load calculation if necessary. Called with ca locked */
+-static void cpuusage_update(struct cpuacct *ca)
+-{
+-      u64 now = get_jiffies_64();
+-      /* If we're not due for an update, return */
+-      if (ca->next_interval_check > now)
+-              return;
+-
+-      if (ca->next_interval_check <= (now - INTERVAL)) {
+-              /* If it's been more than an interval since the last
+-               * check, then catch up - the last interval must have
+-               * been zero load */
+-              ca->last_interval_time = 0;
+-              ca->next_interval_check = next_interval_boundary(now);
+-      } else {
+-              /* If a steal takes the last interval time negative,
+-               * then we just ignore it */
+-              if ((s64)ca->current_interval_time > 0) {
+-                      ca->last_interval_time = ca->current_interval_time;
 -              } else {
--                      printk(KERN_ERR
--                             "%s: %s is not a vlan device, priv_flags: %hX.\n",
--                             __FUNCTION__, dev->name, dev->priv_flags);
--                      dev_put(dev);
+-                      ca->last_interval_time = 0;
 -              }
--      } else {
--              printk(KERN_ERR  "%s: Could not find device: %s\n",
--                      __FUNCTION__, dev_name);
+-              ca->next_interval_check += INTERVAL;
 -      }
+-      ca->current_interval_time = 0;
+-}
 -
-+      printk(KERN_ERR "%s: flag %i is not valid.\n", __FUNCTION__, flag);
-       return -EINVAL;
- }
+-static u64 cpuusage_read(struct container *cont,
+-                       struct cftype *cft)
+-{
+-      struct cpuacct *ca = container_ca(cont);
+-      u64 time;
 -
--int vlan_dev_get_realdev_name(const char *dev_name, char* result)
-+void vlan_dev_get_realdev_name(const struct net_device *dev, char *result)
- {
--      struct net_device *dev = dev_get_by_name(dev_name);
--      int rv = 0;
--      if (dev) {
--              if (dev->priv_flags & IFF_802_1Q_VLAN) {
-                       strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
--                      rv = 0;
--              } else {
--                      rv = -EINVAL;
--              }
--              dev_put(dev);
--      } else {
--              rv = -ENODEV;
+-      spin_lock_irq(&ca->lock);
+-      cpuusage_update(ca);
+-      time = cputime64_to_jiffies64(ca->time);
+-      spin_unlock_irq(&ca->lock);
+-
+-      /* Convert 64-bit jiffies to seconds */
+-      time *= 1000;
+-      do_div(time, HZ);
+-      return time;
+-}
+-
+-static u64 load_read(struct container *cont,
+-                   struct cftype *cft)
+-{
+-      struct cpuacct *ca = container_ca(cont);
+-      u64 time;
+-
+-      /* Find the time used in the previous interval */
+-      spin_lock_irq(&ca->lock);
+-      cpuusage_update(ca);
+-      time = cputime64_to_jiffies64(ca->last_interval_time);
+-      spin_unlock_irq(&ca->lock);
+-
+-      /* Convert time to a percentage, to give the load in the
+-       * previous period */
+-      time *= 100;
+-      do_div(time, INTERVAL);
+-
+-      return time;
+-}
+-
+-static struct cftype files[] = {
+-      {
+-              .name = "cpuacct.usage",
+-              .read_uint = cpuusage_read,
+-      },
+-      {
+-              .name = "cpuacct.load",
+-              .read_uint = load_read,
 -      }
--      return rv;
- }
--int vlan_dev_get_vid(const char *dev_name, unsigned short* result)
-+void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result)
- {
--      struct net_device *dev = dev_get_by_name(dev_name);
--      int rv = 0;
--      if (dev) {
--              if (dev->priv_flags & IFF_802_1Q_VLAN) {
-                       *result = VLAN_DEV_INFO(dev)->vlan_id;
--                      rv = 0;
--              } else {
--                      rv = -EINVAL;
--              }
--              dev_put(dev);
--      } else {
--              rv = -ENODEV;
+-};
+-
+-static int cpuacct_populate(struct container_subsys *ss,
+-                          struct container *cont)
+-{
+-      return container_add_files(cont, files, ARRAY_SIZE(files));
+-}
+-
+-void cpuacct_charge(struct task_struct *task, cputime_t cputime)
+-{
+-
+-      struct cpuacct *ca;
+-      unsigned long flags;
+-
+-      if (!cpuacct_subsys.active)
+-              return;
+-      rcu_read_lock();
+-      ca = task_ca(task);
+-      if (ca) {
+-              spin_lock_irqsave(&ca->lock, flags);
+-              cpuusage_update(ca);
+-              ca->time = cputime64_add(ca->time, cputime);
+-              ca->current_interval_time =
+-                      cputime64_add(ca->current_interval_time, cputime);
+-              spin_unlock_irqrestore(&ca->lock, flags);
 -      }
--      return rv;
- }
+-      rcu_read_unlock();
+-}
 -
- int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
- {
-       struct sockaddr *addr = (struct sockaddr *)(addr_struct_p);
-@@ -828,7 +781,7 @@
-               break;
-       case SIOCETHTOOL:
--              err = dev_ethtool(&ifrr);
-+              err = dev_ethtool(real_dev->nd_net, &ifrr);
-       }
-       if (!err)
-diff -Nurb linux-2.6.22-570/net/8021q/vlan_netlink.c linux-2.6.22-590/net/8021q/vlan_netlink.c
---- linux-2.6.22-570/net/8021q/vlan_netlink.c  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/net/8021q/vlan_netlink.c  2008-01-02 13:56:38.000000000 -0500
-@@ -0,0 +1,237 @@
-+/*
-+ *    VLAN netlink control interface
-+ *
-+ *    Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
-+ *
-+ *    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/netdevice.h>
-+#include <linux/if_vlan.h>
-+#include <net/net_namespace.h>
-+#include <net/netlink.h>
-+#include <net/rtnetlink.h>
-+#include "vlan.h"
-+
-+
-+static const struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = {
-+      [IFLA_VLAN_ID]          = { .type = NLA_U16 },
-+      [IFLA_VLAN_FLAGS]       = { .len = sizeof(struct ifla_vlan_flags) },
-+      [IFLA_VLAN_EGRESS_QOS]  = { .type = NLA_NESTED },
-+      [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED },
-+};
-+
-+static const struct nla_policy vlan_map_policy[IFLA_VLAN_QOS_MAX + 1] = {
-+      [IFLA_VLAN_QOS_MAPPING] = { .len = sizeof(struct ifla_vlan_qos_mapping) },
-+};
-+
-+
-+static inline int vlan_validate_qos_map(struct nlattr *attr)
-+{
-+      if (!attr)
-+              return 0;
-+      return nla_validate_nested(attr, IFLA_VLAN_QOS_MAX, vlan_map_policy);
-+}
-+
-+static int vlan_validate(struct nlattr *tb[], struct nlattr *data[])
-+{
-+      struct ifla_vlan_flags *flags;
-+      u16 id;
-+      int err;
-+
-+      if (!data)
-+              return -EINVAL;
-+
-+      if (data[IFLA_VLAN_ID]) {
-+              id = nla_get_u16(data[IFLA_VLAN_ID]);
-+              if (id >= VLAN_VID_MASK)
-+                      return -ERANGE;
-+      }
-+      if (data[IFLA_VLAN_FLAGS]) {
-+              flags = nla_data(data[IFLA_VLAN_FLAGS]);
-+              if ((flags->flags & flags->mask) & ~VLAN_FLAG_REORDER_HDR)
-+                      return -EINVAL;
-+      }
-+
-+      err = vlan_validate_qos_map(data[IFLA_VLAN_INGRESS_QOS]);
-+      if (err < 0)
-+              return err;
-+      err = vlan_validate_qos_map(data[IFLA_VLAN_EGRESS_QOS]);
-+      if (err < 0)
-+              return err;
-+      return 0;
-+}
-+
-+static int vlan_changelink(struct net_device *dev,
-+                         struct nlattr *tb[], struct nlattr *data[])
-+{
-+      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
-+      struct ifla_vlan_flags *flags;
-+      struct ifla_vlan_qos_mapping *m;
-+      struct nlattr *attr;
-+      int rem;
-+
-+      if (data[IFLA_VLAN_FLAGS]) {
-+              flags = nla_data(data[IFLA_VLAN_FLAGS]);
-+              vlan->flags = (vlan->flags & ~flags->mask) |
-+                            (flags->flags & flags->mask);
-+      }
-+      if (data[IFLA_VLAN_INGRESS_QOS]) {
-+              nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
-+                      m = nla_data(attr);
-+                      vlan_dev_set_ingress_priority(dev, m->to, m->from);
-+              }
-+      }
-+      if (data[IFLA_VLAN_EGRESS_QOS]) {
-+              nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
-+                      m = nla_data(attr);
-+                      vlan_dev_set_egress_priority(dev, m->from, m->to);
-+              }
-+      }
-+      return 0;
-+}
-+
-+static int vlan_newlink(struct net_device *dev,
-+                      struct nlattr *tb[], struct nlattr *data[])
-+{
-+      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
-+      struct net_device *real_dev;
-+      int err;
-+
-+      if (!data[IFLA_VLAN_ID])
-+              return -EINVAL;
-+
-+      if (!tb[IFLA_LINK])
-+              return -EINVAL;
-+      real_dev = __dev_get_by_index(&init_net, nla_get_u32(tb[IFLA_LINK]));
-+      if (!real_dev)
-+              return -ENODEV;
-+
-+      vlan->vlan_id  = nla_get_u16(data[IFLA_VLAN_ID]);
-+      vlan->real_dev = real_dev;
-+      vlan->flags    = VLAN_FLAG_REORDER_HDR;
-+
-+      err = vlan_check_real_dev(real_dev, vlan->vlan_id);
-+      if (err < 0)
-+              return err;
-+
-+      if (!tb[IFLA_MTU])
-+              dev->mtu = real_dev->mtu;
-+      else if (dev->mtu > real_dev->mtu)
-+              return -EINVAL;
-+
-+      err = vlan_changelink(dev, tb, data);
-+      if (err < 0)
-+              return err;
-+
-+      return register_vlan_dev(dev);
-+}
-+
-+static void vlan_dellink(struct net_device *dev)
-+{
-+      unregister_vlan_device(dev);
-+}
-+
-+static inline size_t vlan_qos_map_size(unsigned int n)
-+{
-+      if (n == 0)
-+              return 0;
-+      /* IFLA_VLAN_{EGRESS,INGRESS}_QOS + n * IFLA_VLAN_QOS_MAPPING */
-+      return nla_total_size(sizeof(struct nlattr)) +
-+             nla_total_size(sizeof(struct ifla_vlan_qos_mapping)) * n;
-+}
-+
-+static size_t vlan_get_size(const struct net_device *dev)
-+{
-+      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
-+
-+      return nla_total_size(2) +      /* IFLA_VLAN_ID */
-+             vlan_qos_map_size(vlan->nr_ingress_mappings) +
-+             vlan_qos_map_size(vlan->nr_egress_mappings);
-+}
-+
-+static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
-+{
-+      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
-+      struct vlan_priority_tci_mapping *pm;
-+      struct ifla_vlan_flags f;
-+      struct ifla_vlan_qos_mapping m;
-+      struct nlattr *nest;
-+      unsigned int i;
-+
-+      NLA_PUT_U16(skb, IFLA_VLAN_ID, VLAN_DEV_INFO(dev)->vlan_id);
-+      if (vlan->flags) {
-+              f.flags = vlan->flags;
-+              f.mask  = ~0;
-+              NLA_PUT(skb, IFLA_VLAN_FLAGS, sizeof(f), &f);
-+      }
-+      if (vlan->nr_ingress_mappings) {
-+              nest = nla_nest_start(skb, IFLA_VLAN_INGRESS_QOS);
-+              if (nest == NULL)
-+                      goto nla_put_failure;
-+
-+              for (i = 0; i < ARRAY_SIZE(vlan->ingress_priority_map); i++) {
-+                      if (!vlan->ingress_priority_map[i])
-+                              continue;
-+
-+                      m.from = i;
-+                      m.to   = vlan->ingress_priority_map[i];
-+                      NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING,
-+                              sizeof(m), &m);
-+              }
-+              nla_nest_end(skb, nest);
-+      }
-+
-+      if (vlan->nr_egress_mappings) {
-+              nest = nla_nest_start(skb, IFLA_VLAN_EGRESS_QOS);
-+              if (nest == NULL)
-+                      goto nla_put_failure;
-+
-+              for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) {
-+                      for (pm = vlan->egress_priority_map[i]; pm;
-+                           pm = pm->next) {
-+                              if (!pm->vlan_qos)
-+                                      continue;
-+
-+                              m.from = pm->priority;
-+                              m.to   = (pm->vlan_qos >> 13) & 0x7;
-+                              NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING,
-+                                      sizeof(m), &m);
-+                      }
-+              }
-+              nla_nest_end(skb, nest);
-+      }
-+      return 0;
-+
-+nla_put_failure:
-+      return -EMSGSIZE;
-+}
-+
-+struct rtnl_link_ops vlan_link_ops __read_mostly = {
-+      .kind           = "vlan",
-+      .maxtype        = IFLA_VLAN_MAX,
-+      .policy         = vlan_policy,
-+      .priv_size      = sizeof(struct vlan_dev_info),
-+      .setup          = vlan_setup,
-+      .validate       = vlan_validate,
-+      .newlink        = vlan_newlink,
-+      .changelink     = vlan_changelink,
-+      .dellink        = vlan_dellink,
-+      .get_size       = vlan_get_size,
-+      .fill_info      = vlan_fill_info,
-+};
-+
-+int __init vlan_netlink_init(void)
-+{
-+      return rtnl_link_register(&vlan_link_ops);
-+}
-+
-+void __exit vlan_netlink_fini(void)
-+{
-+      rtnl_link_unregister(&vlan_link_ops);
-+}
-+
-+MODULE_ALIAS_RTNL_LINK("vlan");
-diff -Nurb linux-2.6.22-570/net/8021q/vlanproc.c linux-2.6.22-590/net/8021q/vlanproc.c
---- linux-2.6.22-570/net/8021q/vlanproc.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/8021q/vlanproc.c      2008-01-02 13:56:38.000000000 -0500
-@@ -33,6 +33,7 @@
- #include <linux/fs.h>
- #include <linux/netdevice.h>
- #include <linux/if_vlan.h>
-+#include <net/net_namespace.h>
- #include "vlanproc.h"
- #include "vlan.h"
-@@ -143,7 +144,7 @@
-               remove_proc_entry(name_conf, proc_vlan_dir);
-       if (proc_vlan_dir)
--              proc_net_remove(name_root);
-+              proc_net_remove(&init_net, name_root);
-       /* Dynamically added entries should be cleaned up as their vlan_device
-        * is removed, so we should not have to take care of it here...
-@@ -156,7 +157,7 @@
- int __init vlan_proc_init(void)
- {
--      proc_vlan_dir = proc_mkdir(name_root, proc_net);
-+      proc_vlan_dir = proc_mkdir(name_root, init_net.proc_net);
-       if (proc_vlan_dir) {
-               proc_vlan_conf = create_proc_entry(name_conf,
-                                                  S_IFREG|S_IRUSR|S_IWUSR,
-@@ -253,7 +254,7 @@
-       if (*pos == 0)
-               return SEQ_START_TOKEN;
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if (!is_vlan_dev(dev))
-                       continue;
-@@ -272,9 +273,9 @@
-       dev = (struct net_device *)v;
-       if (v == SEQ_START_TOKEN)
--              dev = net_device_entry(&dev_base_head);
-+              dev = net_device_entry(&init_net.dev_base_head);
--      for_each_netdev_continue(dev) {
-+      for_each_netdev_continue(&init_net, dev) {
-               if (!is_vlan_dev(dev))
-                       continue;
-@@ -342,7 +343,7 @@
-       seq_printf(seq, "Device: %s", dev_info->real_dev->name);
-       /* now show all PRIORITY mappings relating to this VLAN */
-       seq_printf(seq,
--                     "\nINGRESS priority mappings: 0:%lu  1:%lu  2:%lu  3:%lu  4:%lu  5:%lu  6:%lu 7:%lu\n",
-+                     "\nINGRESS priority mappings: 0:%u  1:%u  2:%u  3:%u  4:%u  5:%u  6:%u 7:%u\n",
-                      dev_info->ingress_priority_map[0],
-                      dev_info->ingress_priority_map[1],
-                      dev_info->ingress_priority_map[2],
-@@ -357,7 +358,7 @@
-               const struct vlan_priority_tci_mapping *mp
-                       = dev_info->egress_priority_map[i];
-               while (mp) {
--                      seq_printf(seq, "%lu:%hu ",
-+                      seq_printf(seq, "%u:%hu ",
-                                  mp->priority, ((mp->vlan_qos >> 13) & 0x7));
-                       mp = mp->next;
-               }
-diff -Nurb linux-2.6.22-570/net/Kconfig linux-2.6.22-590/net/Kconfig
---- linux-2.6.22-570/net/Kconfig       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/Kconfig       2008-01-02 13:56:38.000000000 -0500
-@@ -27,6 +27,13 @@
- menu "Networking options"
-+config NET_NS
-+      bool "Network namespace support"
-+      depends on EXPERIMENTAL
-+      help
-+        Support what appear to user space as multiple instances of the 
-+        network stack.
-+
- source "net/packet/Kconfig"
- source "net/unix/Kconfig"
- source "net/xfrm/Kconfig"
-diff -Nurb linux-2.6.22-570/net/Makefile linux-2.6.22-590/net/Makefile
---- linux-2.6.22-570/net/Makefile      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/Makefile      2008-01-02 13:56:38.000000000 -0500
-@@ -14,7 +14,7 @@
- # LLC has to be linked before the files in net/802/
- obj-$(CONFIG_LLC)             += llc/
--obj-$(CONFIG_NET)             += ethernet/ 802/ sched/ netlink/
-+obj-$(CONFIG_NET)             += ethernet/ sched/ netlink/ 802/
- obj-$(CONFIG_NETFILTER)               += netfilter/
- obj-$(CONFIG_INET)            += ipv4/
- obj-$(CONFIG_XFRM)            += xfrm/
-diff -Nurb linux-2.6.22-570/net/appletalk/aarp.c linux-2.6.22-590/net/appletalk/aarp.c
---- linux-2.6.22-570/net/appletalk/aarp.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/appletalk/aarp.c      2008-01-02 13:56:38.000000000 -0500
-@@ -330,15 +330,19 @@
- static int aarp_device_event(struct notifier_block *this, unsigned long event,
-                            void *ptr)
- {
-+      struct net_device *dev = ptr;
-       int ct;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (event == NETDEV_DOWN) {
-               write_lock_bh(&aarp_lock);
-               for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
--                      __aarp_expire_device(&resolved[ct], ptr);
--                      __aarp_expire_device(&unresolved[ct], ptr);
--                      __aarp_expire_device(&proxies[ct], ptr);
-+                      __aarp_expire_device(&resolved[ct], dev);
-+                      __aarp_expire_device(&unresolved[ct], dev);
-+                      __aarp_expire_device(&proxies[ct], dev);
-               }
-               write_unlock_bh(&aarp_lock);
-@@ -712,6 +716,9 @@
-       struct atalk_addr sa, *ma, da;
-       struct atalk_iface *ifa;
-+      if (dev->nd_net != &init_net)
-+              goto out0;
-+
-       /* We only do Ethernet SNAP AARP. */
-       if (dev->type != ARPHRD_ETHER)
-               goto out0;
-diff -Nurb linux-2.6.22-570/net/appletalk/atalk_proc.c linux-2.6.22-590/net/appletalk/atalk_proc.c
---- linux-2.6.22-570/net/appletalk/atalk_proc.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/appletalk/atalk_proc.c        2008-01-02 13:56:38.000000000 -0500
-@@ -13,6 +13,7 @@
- #include <linux/seq_file.h>
- #include <net/sock.h>
- #include <linux/atalk.h>
-+#include <net/net_namespace.h>
- static __inline__ struct atalk_iface *atalk_get_interface_idx(loff_t pos)
-@@ -271,7 +272,7 @@
-       struct proc_dir_entry *p;
-       int rc = -ENOMEM;
--      atalk_proc_dir = proc_mkdir("atalk", proc_net);
-+      atalk_proc_dir = proc_mkdir("atalk", init_net.proc_net);
-       if (!atalk_proc_dir)
-               goto out;
-       atalk_proc_dir->owner = THIS_MODULE;
-@@ -306,7 +307,7 @@
- out_route:
-       remove_proc_entry("interface", atalk_proc_dir);
- out_interface:
--      remove_proc_entry("atalk", proc_net);
-+      remove_proc_entry("atalk", init_net.proc_net);
-       goto out;
- }
-@@ -316,5 +317,5 @@
-       remove_proc_entry("route", atalk_proc_dir);
-       remove_proc_entry("socket", atalk_proc_dir);
-       remove_proc_entry("arp", atalk_proc_dir);
--      remove_proc_entry("atalk", proc_net);
-+      remove_proc_entry("atalk", init_net.proc_net);
- }
-diff -Nurb linux-2.6.22-570/net/appletalk/ddp.c linux-2.6.22-590/net/appletalk/ddp.c
---- linux-2.6.22-570/net/appletalk/ddp.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/appletalk/ddp.c       2008-01-02 13:56:38.000000000 -0500
-@@ -647,9 +647,14 @@
- static int ddp_device_event(struct notifier_block *this, unsigned long event,
-                           void *ptr)
- {
-+      struct net_device *dev = ptr;
-+
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (event == NETDEV_DOWN)
-               /* Discard any use of this */
--              atalk_dev_down(ptr);
-+              atalk_dev_down(dev);
-       return NOTIFY_DONE;
- }
-@@ -672,7 +677,7 @@
-       if (copy_from_user(&atreq, arg, sizeof(atreq)))
-               return -EFAULT;
--      dev = __dev_get_by_name(atreq.ifr_name);
-+      dev = __dev_get_by_name(&init_net, atreq.ifr_name);
-       if (!dev)
-               return -ENODEV;
-@@ -896,7 +901,7 @@
-                               if (copy_from_user(name, rt.rt_dev, IFNAMSIZ-1))
-                                       return -EFAULT;
-                               name[IFNAMSIZ-1] = '\0';
--                              dev = __dev_get_by_name(name);
-+                              dev = __dev_get_by_name(&init_net, name);
-                               if (!dev)
-                                       return -ENODEV;
-                       }
-@@ -1024,11 +1029,14 @@
-  * Create a socket. Initialise the socket, blank the addresses
-  * set the state.
-  */
--static int atalk_create(struct socket *sock, int protocol)
-+static int atalk_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct sock *sk;
-       int rc = -ESOCKTNOSUPPORT;
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
-+
-       /*
-        * We permit SOCK_DGRAM and RAW is an extension. It is trivial to do
-        * and gives you the full ELAP frame. Should be handy for CAP 8)
-@@ -1036,7 +1044,7 @@
-       if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
-               goto out;
-       rc = -ENOMEM;
--      sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, &ddp_proto, 1);
-+      sk = sk_alloc(net, PF_APPLETALK, GFP_KERNEL, &ddp_proto, 1);
-       if (!sk)
-               goto out;
-       rc = 0;
-@@ -1265,7 +1273,7 @@
- static int handle_ip_over_ddp(struct sk_buff *skb)
- {
--      struct net_device *dev = __dev_get_by_name("ipddp0");
-+      struct net_device *dev = __dev_get_by_name(&init_net, "ipddp0");
-       struct net_device_stats *stats;
-       /* This needs to be able to handle ipddp"N" devices */
-@@ -1398,6 +1406,9 @@
-       int origlen;
-       __u16 len_hops;
-+      if (dev->nd_net != &init_net)
-+              goto freeit;
-+
-       /* Don't mangle buffer if shared */
-       if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
-               goto out;
-@@ -1483,6 +1494,9 @@
- static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
-                    struct packet_type *pt, struct net_device *orig_dev)
- {
-+      if (dev->nd_net != &init_net)
-+              goto freeit;
-+
-       /* Expand any short form frames */
-       if (skb_mac_header(skb)[2] == 1) {
-               struct ddpehdr *ddp;
-diff -Nurb linux-2.6.22-570/net/atm/clip.c linux-2.6.22-590/net/atm/clip.c
---- linux-2.6.22-570/net/atm/clip.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/atm/clip.c    2008-01-02 13:56:38.000000000 -0500
-@@ -293,7 +293,7 @@
-       struct neigh_parms *parms;
-       DPRINTK("clip_constructor (neigh %p, entry %p)\n", neigh, entry);
--      neigh->type = inet_addr_type(entry->ip);
-+      neigh->type = inet_addr_type(&init_net, entry->ip);
-       if (neigh->type != RTN_UNICAST)
-               return -EINVAL;
-@@ -525,7 +525,10 @@
-       struct atmarp_entry *entry;
-       int error;
-       struct clip_vcc *clip_vcc;
--      struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1}} };
-+      struct flowi fl = { 
-+              .fl_net = &init_net,
-+              .nl_u = { .ip4_u = { .daddr = ip, .tos = 1}} 
-+      };
-       struct rtable *rt;
-       if (vcc->push != clip_push) {
-@@ -620,6 +623,9 @@
- {
-       struct net_device *dev = arg;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (event == NETDEV_UNREGISTER) {
-               neigh_ifdown(&clip_tbl, dev);
-               return NOTIFY_DONE;
-@@ -954,6 +960,7 @@
-       seq = file->private_data;
-       seq->private = state;
-+      state->ns.net = get_net(PROC_NET(inode));
- out:
-       return rc;
-@@ -962,11 +969,19 @@
-       goto out;
- }
-+static int arp_seq_release(struct inode *inode, struct file *file)
-+{
-+      struct seq_file *seq = file->private_data;
-+      struct clip_seq_state *state = seq->private;
-+      put_net(state->ns.net);
-+      return seq_release_private(inode, file);
-+}
-+
- static const struct file_operations arp_seq_fops = {
-       .open           = arp_seq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
--      .release        = seq_release_private,
-+      .release        = arp_seq_release,
-       .owner          = THIS_MODULE
- };
- #endif
-diff -Nurb linux-2.6.22-570/net/atm/common.c linux-2.6.22-590/net/atm/common.c
---- linux-2.6.22-570/net/atm/common.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/atm/common.c  2008-01-02 13:56:38.000000000 -0500
-@@ -132,7 +132,7 @@
-       .obj_size = sizeof(struct atm_vcc),
- };
--int vcc_create(struct socket *sock, int protocol, int family)
-+int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
- {
-       struct sock *sk;
-       struct atm_vcc *vcc;
-@@ -140,7 +140,7 @@
-       sock->sk = NULL;
-       if (sock->type == SOCK_STREAM)
-               return -EINVAL;
--      sk = sk_alloc(family, GFP_KERNEL, &vcc_proto, 1);
-+      sk = sk_alloc(net, family, GFP_KERNEL, &vcc_proto, 1);
-       if (!sk)
-               return -ENOMEM;
-       sock_init_data(sock, sk);
-diff -Nurb linux-2.6.22-570/net/atm/common.h linux-2.6.22-590/net/atm/common.h
---- linux-2.6.22-570/net/atm/common.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/atm/common.h  2008-01-02 13:56:38.000000000 -0500
-@@ -10,7 +10,7 @@
- #include <linux/poll.h> /* for poll_table */
--int vcc_create(struct socket *sock, int protocol, int family);
-+int vcc_create(struct net *net, struct socket *sock, int protocol, int family);
- int vcc_release(struct socket *sock);
- int vcc_connect(struct socket *sock, int itf, short vpi, int vci);
- int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-diff -Nurb linux-2.6.22-570/net/atm/mpc.c linux-2.6.22-590/net/atm/mpc.c
---- linux-2.6.22-570/net/atm/mpc.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/atm/mpc.c     2008-01-02 13:56:38.000000000 -0500
-@@ -244,7 +244,7 @@
-       char name[IFNAMSIZ];
-       sprintf(name, "lec%d", itf);
--      dev = dev_get_by_name(name);
-+      dev = dev_get_by_name(&init_net, name);
-       return dev;
- }
-@@ -956,6 +956,10 @@
-       struct lec_priv *priv;
-       dev = (struct net_device *)dev_ptr;
-+
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (dev->name == NULL || strncmp(dev->name, "lec", 3))
-               return NOTIFY_DONE; /* we are only interested in lec:s */
-diff -Nurb linux-2.6.22-570/net/atm/proc.c linux-2.6.22-590/net/atm/proc.c
---- linux-2.6.22-570/net/atm/proc.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/atm/proc.c    2008-01-02 13:56:38.000000000 -0500
-@@ -22,6 +22,7 @@
- #include <linux/netdevice.h>
- #include <linux/atmclip.h>
- #include <linux/init.h> /* for __init */
-+#include <net/net_namespace.h>
- #include <net/atmclip.h>
- #include <asm/uaccess.h>
- #include <asm/atomic.h>
-@@ -475,7 +476,7 @@
-               if (e->dirent)
-                       remove_proc_entry(e->name, atm_proc_root);
-       }
--      remove_proc_entry("net/atm", NULL);
-+      remove_proc_entry("atm", init_net.proc_net);
- }
- int __init atm_proc_init(void)
-@@ -483,7 +484,7 @@
-       static struct atm_proc_entry *e;
-       int ret;
--      atm_proc_root = proc_mkdir("net/atm",NULL);
-+      atm_proc_root = proc_mkdir("atm", init_net.proc_net);
-       if (!atm_proc_root)
-               goto err_out;
-       for (e = atm_proc_ents; e->name; e++) {
-diff -Nurb linux-2.6.22-570/net/atm/pvc.c linux-2.6.22-590/net/atm/pvc.c
---- linux-2.6.22-570/net/atm/pvc.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/atm/pvc.c     2008-01-02 13:56:38.000000000 -0500
-@@ -124,10 +124,13 @@
- };
--static int pvc_create(struct socket *sock,int protocol)
-+static int pvc_create(struct net *net, struct socket *sock,int protocol)
- {
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
-+
-       sock->ops = &pvc_proto_ops;
--      return vcc_create(sock, protocol, PF_ATMPVC);
-+      return vcc_create(net, sock, protocol, PF_ATMPVC);
- }
-diff -Nurb linux-2.6.22-570/net/atm/svc.c linux-2.6.22-590/net/atm/svc.c
---- linux-2.6.22-570/net/atm/svc.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/atm/svc.c     2008-01-02 13:56:38.000000000 -0500
-@@ -33,7 +33,7 @@
- #endif
--static int svc_create(struct socket *sock,int protocol);
-+static int svc_create(struct net *net, struct socket *sock,int protocol);
- /*
-@@ -335,7 +335,7 @@
-       lock_sock(sk);
--      error = svc_create(newsock,0);
-+      error = svc_create(sk->sk_net, newsock,0);
-       if (error)
-               goto out;
-@@ -636,12 +636,15 @@
- };
--static int svc_create(struct socket *sock,int protocol)
-+static int svc_create(struct net *net, struct socket *sock,int protocol)
- {
-       int error;
+-struct container_subsys cpuacct_subsys = {
+-      .name = "cpuacct",
+-      .create = cpuacct_create,
+-      .destroy = cpuacct_destroy,
+-      .populate = cpuacct_populate,
+-      .subsys_id = cpuacct_subsys_id,
+-};
+diff -Nurb linux-2.6.22-590/kernel/cpuset.c linux-2.6.22-570/kernel/cpuset.c
+--- linux-2.6.22-590/kernel/cpuset.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/cpuset.c   2007-07-08 19:32:17.000000000 -0400
+@@ -5,7 +5,6 @@
+  *
+  *  Copyright (C) 2003 BULL SA.
+  *  Copyright (C) 2004-2006 Silicon Graphics, Inc.
+- *  Copyright (C) 2006 Google, Inc
+  *
+  *  Portions derived from Patrick Mochel's sysfs code.
+  *  sysfs is Copyright (c) 2001-3 Patrick Mochel
+@@ -13,7 +12,6 @@
+  *  2003-10-10 Written by Simon Derr.
+  *  2003-10-22 Updates by Stephen Hemminger.
+  *  2004 May-July Rework by Paul Jackson.
+- *  2006 Rework by Paul Menage to use generic containers
+  *
+  *  This file is subject to the terms and conditions of the GNU General Public
+  *  License.  See the file COPYING in the main directory of the Linux
+@@ -55,6 +53,8 @@
+ #include <asm/atomic.h>
+ #include <linux/mutex.h>
  
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
++#define CPUSET_SUPER_MAGIC            0x27e0eb
 +
-       sock->ops = &svc_proto_ops;
--      error = vcc_create(sock, protocol, AF_ATMSVC);
-+      error = vcc_create(net, sock, protocol, AF_ATMSVC);
-       if (error) return error;
-       ATM_SD(sock)->local.sas_family = AF_ATMSVC;
-       ATM_SD(sock)->remote.sas_family = AF_ATMSVC;
-diff -Nurb linux-2.6.22-570/net/ax25/af_ax25.c linux-2.6.22-590/net/ax25/af_ax25.c
---- linux-2.6.22-570/net/ax25/af_ax25.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ax25/af_ax25.c        2008-01-02 13:56:38.000000000 -0500
-@@ -47,6 +47,7 @@
- #include <net/tcp_states.h>
- #include <net/ip.h>
- #include <net/arp.h>
-+#include <net/net_namespace.h>
-@@ -103,6 +104,9 @@
- {
-       struct net_device *dev = (struct net_device *)ptr;
+ /*
+  * Tracks how many cpusets are currently defined in system.
+  * When there is only one cpuset (the root cpuset) we can
+@@ -62,10 +62,6 @@
+  */
+ int number_of_cpusets __read_mostly;
  
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       /* Reject non AX.25 devices */
-       if (dev->type != ARPHRD_AX25)
-               return NOTIFY_DONE;
-@@ -627,7 +631,7 @@
-                       break;
-               }
+-/* Retrieve the cpuset from a container */
+-struct container_subsys cpuset_subsys;
+-struct cpuset;
+-
+ /* See "Frequency meter" comments, below. */
  
--              dev = dev_get_by_name(devname);
-+              dev = dev_get_by_name(&init_net, devname);
-               if (dev == NULL) {
-                       res = -ENODEV;
-                       break;
-@@ -779,11 +783,14 @@
-       .obj_size = sizeof(struct sock),
+ struct fmeter {
+@@ -76,13 +72,24 @@
  };
  
--static int ax25_create(struct socket *sock, int protocol)
-+static int ax25_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct sock *sk;
-       ax25_cb *ax25;
+ struct cpuset {
+-      struct container_subsys_state css;
+-
+       unsigned long flags;            /* "unsigned long" so bitops work */
+       cpumask_t cpus_allowed;         /* CPUs allowed to tasks in cpuset */
+       nodemask_t mems_allowed;        /* Memory Nodes allowed to tasks */
  
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
++      /*
++       * Count is atomic so can incr (fork) or decr (exit) without a lock.
++       */
++      atomic_t count;                 /* count tasks using this cpuset */
 +
-       switch (sock->type) {
-       case SOCK_DGRAM:
-               if (protocol == 0 || protocol == PF_AX25)
-@@ -829,7 +836,7 @@
-               return -ESOCKTNOSUPPORT;
-       }
--      if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, &ax25_proto, 1)) == NULL)
-+      if ((sk = sk_alloc(net, PF_AX25, GFP_ATOMIC, &ax25_proto, 1)) == NULL)
-               return -ENOMEM;
-       ax25 = sk->sk_protinfo = ax25_create_cb();
-@@ -854,7 +861,7 @@
-       struct sock *sk;
-       ax25_cb *ax25, *oax25;
--      if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
-+      if ((sk = sk_alloc(osk->sk_net, PF_AX25, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
-               return NULL;
++      /*
++       * We link our 'sibling' struct into our parents 'children'.
++       * Our children link their 'sibling' into our 'children'.
++       */
++      struct list_head sibling;       /* my parents children */
++      struct list_head children;      /* my children */
++
+       struct cpuset *parent;          /* my parent */
++      struct dentry *dentry;          /* cpuset fs entry */
  
-       if ((ax25 = ax25_create_cb()) == NULL) {
-@@ -1998,9 +2005,9 @@
-       register_netdevice_notifier(&ax25_dev_notifier);
-       ax25_register_sysctl();
+       /*
+        * Copy of global cpuset_mems_generation as of the most
+@@ -93,32 +100,13 @@
+       struct fmeter fmeter;           /* memory_pressure filter */
+ };
  
--      proc_net_fops_create("ax25_route", S_IRUGO, &ax25_route_fops);
--      proc_net_fops_create("ax25", S_IRUGO, &ax25_info_fops);
--      proc_net_fops_create("ax25_calls", S_IRUGO, &ax25_uid_fops);
-+      proc_net_fops_create(&init_net, "ax25_route", S_IRUGO, &ax25_route_fops);
-+      proc_net_fops_create(&init_net, "ax25", S_IRUGO, &ax25_info_fops);
-+      proc_net_fops_create(&init_net, "ax25_calls", S_IRUGO, &ax25_uid_fops);
- out:
-       return rc;
+-/* Update the cpuset for a container */
+-static inline void set_container_cs(struct container *cont, struct cpuset *cs)
+-{
+-      cont->subsys[cpuset_subsys_id] = &cs->css;
+-}
+-
+-/* Retrieve the cpuset for a container */
+-static inline struct cpuset *container_cs(struct container *cont)
+-{
+-      return container_of(container_subsys_state(cont, cpuset_subsys_id),
+-                          struct cpuset, css);
+-}
+-
+-/* Retrieve the cpuset for a task */
+-static inline struct cpuset *task_cs(struct task_struct *task)
+-{
+-      return container_of(task_subsys_state(task, cpuset_subsys_id),
+-                          struct cpuset, css);
+-}
+-
+-
+ /* bits in struct cpuset flags field */
+ typedef enum {
+       CS_CPU_EXCLUSIVE,
+       CS_MEM_EXCLUSIVE,
+       CS_MEMORY_MIGRATE,
++      CS_REMOVED,
++      CS_NOTIFY_ON_RELEASE,
+       CS_SPREAD_PAGE,
+       CS_SPREAD_SLAB,
+ } cpuset_flagbits_t;
+@@ -134,6 +122,16 @@
+       return test_bit(CS_MEM_EXCLUSIVE, &cs->flags);
  }
-@@ -2014,9 +2021,9 @@
- static void __exit ax25_exit(void)
- {
--      proc_net_remove("ax25_route");
--      proc_net_remove("ax25");
--      proc_net_remove("ax25_calls");
-+      proc_net_remove(&init_net, "ax25_route");
-+      proc_net_remove(&init_net, "ax25");
-+      proc_net_remove(&init_net, "ax25_calls");
-       ax25_rt_free();
-       ax25_uid_free();
-       ax25_dev_free();
-diff -Nurb linux-2.6.22-570/net/ax25/ax25_in.c linux-2.6.22-590/net/ax25/ax25_in.c
---- linux-2.6.22-570/net/ax25/ax25_in.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ax25/ax25_in.c        2008-01-02 13:56:38.000000000 -0500
-@@ -451,6 +451,11 @@
-       skb->sk = NULL;         /* Initially we don't know who it's for */
-       skb->destructor = NULL; /* Who initializes this, dammit?! */
  
-+      if (dev->nd_net != &init_net) {
-+              kfree_skb(skb);
-+              return 0;
-+      }
++static inline int is_removed(const struct cpuset *cs)
++{
++      return test_bit(CS_REMOVED, &cs->flags);
++}
 +
-       if ((*skb->data & 0x0F) != 0) {
-               kfree_skb(skb); /* Not a KISS data frame */
-               return 0;
-diff -Nurb linux-2.6.22-570/net/bluetooth/af_bluetooth.c linux-2.6.22-590/net/bluetooth/af_bluetooth.c
---- linux-2.6.22-570/net/bluetooth/af_bluetooth.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bluetooth/af_bluetooth.c      2008-01-02 13:56:38.000000000 -0500
-@@ -95,10 +95,13 @@
- }
- EXPORT_SYMBOL(bt_sock_unregister);
--static int bt_sock_create(struct socket *sock, int proto)
-+static int bt_sock_create(struct net *net, struct socket *sock, int proto)
- {
-       int err;
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
++static inline int notify_on_release(const struct cpuset *cs)
++{
++      return test_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
++}
 +
-       if (proto < 0 || proto >= BT_MAX_PROTO)
-               return -EINVAL;
-@@ -113,7 +116,7 @@
-       read_lock(&bt_proto_lock);
-       if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
--              err = bt_proto[proto]->create(sock, proto);
-+              err = bt_proto[proto]->create(net, sock, proto);
-               module_put(bt_proto[proto]->owner);
-       }
-diff -Nurb linux-2.6.22-570/net/bluetooth/bnep/core.c linux-2.6.22-590/net/bluetooth/bnep/core.c
---- linux-2.6.22-570/net/bluetooth/bnep/core.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bluetooth/bnep/core.c 2008-01-02 13:56:38.000000000 -0500
-@@ -36,6 +36,7 @@
- #include <linux/signal.h>
- #include <linux/init.h>
- #include <linux/wait.h>
-+#include <linux/freezer.h>
- #include <linux/errno.h>
- #include <linux/net.h>
- #include <net/sock.h>
-@@ -474,7 +475,6 @@
-       daemonize("kbnepd %s", dev->name);
-       set_user_nice(current, -15);
--      current->flags |= PF_NOFREEZE;
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(sk->sk_sleep, &wait);
-diff -Nurb linux-2.6.22-570/net/bluetooth/bnep/sock.c linux-2.6.22-590/net/bluetooth/bnep/sock.c
---- linux-2.6.22-570/net/bluetooth/bnep/sock.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bluetooth/bnep/sock.c 2008-01-02 13:56:38.000000000 -0500
-@@ -204,7 +204,7 @@
-       .obj_size       = sizeof(struct bt_sock)
- };
--static int bnep_sock_create(struct socket *sock, int protocol)
-+static int bnep_sock_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct sock *sk;
-@@ -213,7 +213,7 @@
-       if (sock->type != SOCK_RAW)
-               return -ESOCKTNOSUPPORT;
--      sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
-+      sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
-       if (!sk)
-               return -ENOMEM;
-diff -Nurb linux-2.6.22-570/net/bluetooth/cmtp/core.c linux-2.6.22-590/net/bluetooth/cmtp/core.c
---- linux-2.6.22-570/net/bluetooth/cmtp/core.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bluetooth/cmtp/core.c 2008-01-02 13:56:38.000000000 -0500
-@@ -29,6 +29,7 @@
- #include <linux/slab.h>
- #include <linux/poll.h>
- #include <linux/fcntl.h>
-+#include <linux/freezer.h>
- #include <linux/skbuff.h>
- #include <linux/socket.h>
- #include <linux/ioctl.h>
-@@ -287,7 +288,6 @@
-       daemonize("kcmtpd_ctr_%d", session->num);
-       set_user_nice(current, -15);
--      current->flags |= PF_NOFREEZE;
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(sk->sk_sleep, &wait);
-diff -Nurb linux-2.6.22-570/net/bluetooth/cmtp/sock.c linux-2.6.22-590/net/bluetooth/cmtp/sock.c
---- linux-2.6.22-570/net/bluetooth/cmtp/sock.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bluetooth/cmtp/sock.c 2008-01-02 13:56:38.000000000 -0500
-@@ -195,7 +195,7 @@
-       .obj_size       = sizeof(struct bt_sock)
- };
--static int cmtp_sock_create(struct socket *sock, int protocol)
-+static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol)
+ static inline int is_memory_migrate(const struct cpuset *cs)
  {
-       struct sock *sk;
-@@ -204,7 +204,7 @@
-       if (sock->type != SOCK_RAW)
-               return -ESOCKTNOSUPPORT;
--      sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
-+      sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
-       if (!sk)
-               return -ENOMEM;
-diff -Nurb linux-2.6.22-570/net/bluetooth/hci_sock.c linux-2.6.22-590/net/bluetooth/hci_sock.c
---- linux-2.6.22-570/net/bluetooth/hci_sock.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bluetooth/hci_sock.c  2008-01-02 13:56:38.000000000 -0500
-@@ -618,7 +618,7 @@
-       .obj_size       = sizeof(struct hci_pinfo)
+       return test_bit(CS_MEMORY_MIGRATE, &cs->flags);
+@@ -174,8 +172,14 @@
+       .flags = ((1 << CS_CPU_EXCLUSIVE) | (1 << CS_MEM_EXCLUSIVE)),
+       .cpus_allowed = CPU_MASK_ALL,
+       .mems_allowed = NODE_MASK_ALL,
++      .count = ATOMIC_INIT(0),
++      .sibling = LIST_HEAD_INIT(top_cpuset.sibling),
++      .children = LIST_HEAD_INIT(top_cpuset.children),
  };
  
--static int hci_sock_create(struct socket *sock, int protocol)
-+static int hci_sock_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct sock *sk;
-@@ -629,7 +629,7 @@
-       sock->ops = &hci_sock_ops;
--      sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
-+      sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
-       if (!sk)
-               return -ENOMEM;
-diff -Nurb linux-2.6.22-570/net/bluetooth/hidp/core.c linux-2.6.22-590/net/bluetooth/hidp/core.c
---- linux-2.6.22-570/net/bluetooth/hidp/core.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bluetooth/hidp/core.c 2008-01-02 13:56:38.000000000 -0500
-@@ -28,6 +28,7 @@
- #include <linux/sched.h>
- #include <linux/slab.h>
- #include <linux/poll.h>
-+#include <linux/freezer.h>
- #include <linux/fcntl.h>
- #include <linux/skbuff.h>
- #include <linux/socket.h>
-@@ -547,7 +548,6 @@
-       daemonize("khidpd_%04x%04x", vendor, product);
-       set_user_nice(current, -15);
--      current->flags |= PF_NOFREEZE;
++static struct vfsmount *cpuset_mount;
++static struct super_block *cpuset_sb;
++
+ /*
+  * We have two global cpuset mutexes below.  They can nest.
+  * It is ok to first take manage_mutex, then nest callback_mutex.  We also
+@@ -259,36 +263,297 @@
+  * the routine cpuset_update_task_memory_state().
+  */
  
-       init_waitqueue_entry(&ctrl_wait, current);
-       init_waitqueue_entry(&intr_wait, current);
-diff -Nurb linux-2.6.22-570/net/bluetooth/hidp/sock.c linux-2.6.22-590/net/bluetooth/hidp/sock.c
---- linux-2.6.22-570/net/bluetooth/hidp/sock.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bluetooth/hidp/sock.c 2008-01-02 13:56:38.000000000 -0500
-@@ -246,7 +246,7 @@
-       .obj_size       = sizeof(struct bt_sock)
- };
++static DEFINE_MUTEX(manage_mutex);
+ static DEFINE_MUTEX(callback_mutex);
  
--static int hidp_sock_create(struct socket *sock, int protocol)
-+static int hidp_sock_create(struct net *net, struct socket *sock, int protocol)
+-/* This is ugly, but preserves the userspace API for existing cpuset
+- * users. If someone tries to mount the "cpuset" filesystem, we
+- * silently switch it to mount "container" instead */
++/*
++ * A couple of forward declarations required, due to cyclic reference loop:
++ *  cpuset_mkdir -> cpuset_create -> cpuset_populate_dir -> cpuset_add_file
++ *  -> cpuset_create_file -> cpuset_dir_inode_operations -> cpuset_mkdir.
++ */
++
++static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode);
++static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry);
++
++static struct backing_dev_info cpuset_backing_dev_info = {
++      .ra_pages = 0,          /* No readahead */
++      .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
++};
++
++static struct inode *cpuset_new_inode(mode_t mode)
++{
++      struct inode *inode = new_inode(cpuset_sb);
++
++      if (inode) {
++              inode->i_mode = mode;
++              inode->i_uid = current->fsuid;
++              inode->i_gid = current->fsgid;
++              inode->i_blocks = 0;
++              inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++              inode->i_mapping->backing_dev_info = &cpuset_backing_dev_info;
++      }
++      return inode;
++}
++
++static void cpuset_diput(struct dentry *dentry, struct inode *inode)
++{
++      /* is dentry a directory ? if so, kfree() associated cpuset */
++      if (S_ISDIR(inode->i_mode)) {
++              struct cpuset *cs = dentry->d_fsdata;
++              BUG_ON(!(is_removed(cs)));
++              kfree(cs);
++      }
++      iput(inode);
++}
++
++static struct dentry_operations cpuset_dops = {
++      .d_iput = cpuset_diput,
++};
++
++static struct dentry *cpuset_get_dentry(struct dentry *parent, const char *name)
++{
++      struct dentry *d = lookup_one_len(name, parent, strlen(name));
++      if (!IS_ERR(d))
++              d->d_op = &cpuset_dops;
++      return d;
++}
++
++static void remove_dir(struct dentry *d)
++{
++      struct dentry *parent = dget(d->d_parent);
++
++      d_delete(d);
++      simple_rmdir(parent->d_inode, d);
++      dput(parent);
++}
++
++/*
++ * NOTE : the dentry must have been dget()'ed
++ */
++static void cpuset_d_remove_dir(struct dentry *dentry)
++{
++      struct list_head *node;
++
++      spin_lock(&dcache_lock);
++      node = dentry->d_subdirs.next;
++      while (node != &dentry->d_subdirs) {
++              struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
++              list_del_init(node);
++              if (d->d_inode) {
++                      d = dget_locked(d);
++                      spin_unlock(&dcache_lock);
++                      d_delete(d);
++                      simple_unlink(dentry->d_inode, d);
++                      dput(d);
++                      spin_lock(&dcache_lock);
++              }
++              node = dentry->d_subdirs.next;
++      }
++      list_del_init(&dentry->d_u.d_child);
++      spin_unlock(&dcache_lock);
++      remove_dir(dentry);
++}
++
++static struct super_operations cpuset_ops = {
++      .statfs = simple_statfs,
++      .drop_inode = generic_delete_inode,
++};
++
++static int cpuset_fill_super(struct super_block *sb, void *unused_data,
++                                                      int unused_silent)
++{
++      struct inode *inode;
++      struct dentry *root;
++
++      sb->s_blocksize = PAGE_CACHE_SIZE;
++      sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
++      sb->s_magic = CPUSET_SUPER_MAGIC;
++      sb->s_op = &cpuset_ops;
++      cpuset_sb = sb;
++
++      inode = cpuset_new_inode(S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR);
++      if (inode) {
++              inode->i_op = &simple_dir_inode_operations;
++              inode->i_fop = &simple_dir_operations;
++              /* directories start off with i_nlink == 2 (for "." entry) */
++              inc_nlink(inode);
++      } else {
++              return -ENOMEM;
++      }
++
++      root = d_alloc_root(inode);
++      if (!root) {
++              iput(inode);
++              return -ENOMEM;
++      }
++      sb->s_root = root;
++      return 0;
++}
++
+ static int cpuset_get_sb(struct file_system_type *fs_type,
+                        int flags, const char *unused_dev_name,
+                        void *data, struct vfsmount *mnt)
  {
-       struct sock *sk;
-@@ -255,7 +255,7 @@
-       if (sock->type != SOCK_RAW)
-               return -ESOCKTNOSUPPORT;
--      sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
-+      sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
-       if (!sk)
-               return -ENOMEM;
+-      struct file_system_type *container_fs = get_fs_type("container");
+-      int ret = -ENODEV;
+-      if (container_fs) {
+-              ret = container_fs->get_sb(container_fs, flags,
+-                                         unused_dev_name,
+-                                         "cpuset", mnt);
+-              put_filesystem(container_fs);
+-              if (!ret) {
+-                      container_set_release_agent_path(
+-                              &cpuset_subsys,
+-                              "/sbin/cpuset_release_agent");
+-              }
+-      }
+-      return ret;
++      return get_sb_single(fs_type, flags, data, cpuset_fill_super, mnt);
+ }
  
-diff -Nurb linux-2.6.22-570/net/bluetooth/l2cap.c linux-2.6.22-590/net/bluetooth/l2cap.c
---- linux-2.6.22-570/net/bluetooth/l2cap.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bluetooth/l2cap.c     2008-01-02 13:56:38.000000000 -0500
-@@ -518,11 +518,11 @@
-       .obj_size       = sizeof(struct l2cap_pinfo)
+ static struct file_system_type cpuset_fs_type = {
+       .name = "cpuset",
+       .get_sb = cpuset_get_sb,
++      .kill_sb = kill_litter_super,
++};
++
++/* struct cftype:
++ *
++ * The files in the cpuset filesystem mostly have a very simple read/write
++ * handling, some common function will take care of it. Nevertheless some cases
++ * (read tasks) are special and therefore I define this structure for every
++ * kind of file.
++ *
++ *
++ * When reading/writing to a file:
++ *    - the cpuset to use in file->f_path.dentry->d_parent->d_fsdata
++ *    - the 'cftype' of the file is file->f_path.dentry->d_fsdata
++ */
++
++struct cftype {
++      char *name;
++      int private;
++      int (*open) (struct inode *inode, struct file *file);
++      ssize_t (*read) (struct file *file, char __user *buf, size_t nbytes,
++                                                      loff_t *ppos);
++      int (*write) (struct file *file, const char __user *buf, size_t nbytes,
++                                                      loff_t *ppos);
++      int (*release) (struct inode *inode, struct file *file);
  };
  
--static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, gfp_t prio)
-+static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
- {
-       struct sock *sk;
++static inline struct cpuset *__d_cs(struct dentry *dentry)
++{
++      return dentry->d_fsdata;
++}
++
++static inline struct cftype *__d_cft(struct dentry *dentry)
++{
++      return dentry->d_fsdata;
++}
++
++/*
++ * Call with manage_mutex held.  Writes path of cpuset into buf.
++ * Returns 0 on success, -errno on error.
++ */
++
++static int cpuset_path(const struct cpuset *cs, char *buf, int buflen)
++{
++      char *start;
++
++      start = buf + buflen;
++
++      *--start = '\0';
++      for (;;) {
++              int len = cs->dentry->d_name.len;
++              if ((start -= len) < buf)
++                      return -ENAMETOOLONG;
++              memcpy(start, cs->dentry->d_name.name, len);
++              cs = cs->parent;
++              if (!cs)
++                      break;
++              if (!cs->parent)
++                      continue;
++              if (--start < buf)
++                      return -ENAMETOOLONG;
++              *start = '/';
++      }
++      memmove(buf, start, buf + buflen - start);
++      return 0;
++}
++
++/*
++ * Notify userspace when a cpuset is released, by running
++ * /sbin/cpuset_release_agent with the name of the cpuset (path
++ * relative to the root of cpuset file system) as the argument.
++ *
++ * Most likely, this user command will try to rmdir this cpuset.
++ *
++ * This races with the possibility that some other task will be
++ * attached to this cpuset before it is removed, or that some other
++ * user task will 'mkdir' a child cpuset of this cpuset.  That's ok.
++ * The presumed 'rmdir' will fail quietly if this cpuset is no longer
++ * unused, and this cpuset will be reprieved from its death sentence,
++ * to continue to serve a useful existence.  Next time it's released,
++ * we will get notified again, if it still has 'notify_on_release' set.
++ *
++ * The final arg to call_usermodehelper() is 0, which means don't
++ * wait.  The separate /sbin/cpuset_release_agent task is forked by
++ * call_usermodehelper(), then control in this thread returns here,
++ * without waiting for the release agent task.  We don't bother to
++ * wait because the caller of this routine has no use for the exit
++ * status of the /sbin/cpuset_release_agent task, so no sense holding
++ * our caller up for that.
++ *
++ * When we had only one cpuset mutex, we had to call this
++ * without holding it, to avoid deadlock when call_usermodehelper()
++ * allocated memory.  With two locks, we could now call this while
++ * holding manage_mutex, but we still don't, so as to minimize
++ * the time manage_mutex is held.
++ */
++
++static void cpuset_release_agent(const char *pathbuf)
++{
++      char *argv[3], *envp[3];
++      int i;
++
++      if (!pathbuf)
++              return;
++
++      i = 0;
++      argv[i++] = "/sbin/cpuset_release_agent";
++      argv[i++] = (char *)pathbuf;
++      argv[i] = NULL;
++
++      i = 0;
++      /* minimal command environment */
++      envp[i++] = "HOME=/";
++      envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
++      envp[i] = NULL;
++
++      call_usermodehelper(argv[0], argv, envp, 0);
++      kfree(pathbuf);
++}
++
++/*
++ * Either cs->count of using tasks transitioned to zero, or the
++ * cs->children list of child cpusets just became empty.  If this
++ * cs is notify_on_release() and now both the user count is zero and
++ * the list of children is empty, prepare cpuset path in a kmalloc'd
++ * buffer, to be returned via ppathbuf, so that the caller can invoke
++ * cpuset_release_agent() with it later on, once manage_mutex is dropped.
++ * Call here with manage_mutex held.
++ *
++ * This check_for_release() routine is responsible for kmalloc'ing
++ * pathbuf.  The above cpuset_release_agent() is responsible for
++ * kfree'ing pathbuf.  The caller of these routines is responsible
++ * for providing a pathbuf pointer, initialized to NULL, then
++ * calling check_for_release() with manage_mutex held and the address
++ * of the pathbuf pointer, then dropping manage_mutex, then calling
++ * cpuset_release_agent() with pathbuf, as set by check_for_release().
++ */
++
++static void check_for_release(struct cpuset *cs, char **ppathbuf)
++{
++      if (notify_on_release(cs) && atomic_read(&cs->count) == 0 &&
++          list_empty(&cs->children)) {
++              char *buf;
++
++              buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
++              if (!buf)
++                      return;
++              if (cpuset_path(cs, buf, PAGE_SIZE) < 0)
++                      kfree(buf);
++              else
++                      *ppathbuf = buf;
++      }
++}
++
+ /*
+  * Return in *pmask the portion of a cpusets's cpus_allowed that
+  * are online.  If none are online, walk up the cpuset hierarchy
+@@ -386,19 +651,20 @@
+       struct task_struct *tsk = current;
+       struct cpuset *cs;
  
--      sk = sk_alloc(PF_BLUETOOTH, prio, &l2cap_proto, 1);
-+      sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto, 1);
-       if (!sk)
-               return NULL;
+-      if (task_cs(tsk) == &top_cpuset) {
++      if (tsk->cpuset == &top_cpuset) {
+               /* Don't need rcu for top_cpuset.  It's never freed. */
+               my_cpusets_mem_gen = top_cpuset.mems_generation;
+       } else {
+               rcu_read_lock();
+-              my_cpusets_mem_gen = task_cs(current)->mems_generation;
++              cs = rcu_dereference(tsk->cpuset);
++              my_cpusets_mem_gen = cs->mems_generation;
+               rcu_read_unlock();
+       }
  
-@@ -543,7 +543,7 @@
-       return sk;
- }
+       if (my_cpusets_mem_gen != tsk->cpuset_mems_generation) {
+               mutex_lock(&callback_mutex);
+               task_lock(tsk);
+-              cs = task_cs(tsk); /* Maybe changed when task not locked */
++              cs = tsk->cpuset;       /* Maybe changed when task not locked */
+               guarantee_online_mems(cs, &tsk->mems_allowed);
+               tsk->cpuset_mems_generation = cs->mems_generation;
+               if (is_spread_page(cs))
+@@ -453,12 +719,11 @@
  
--static int l2cap_sock_create(struct socket *sock, int protocol)
-+static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol)
+ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
  {
-       struct sock *sk;
-@@ -560,7 +560,7 @@
-       sock->ops = &l2cap_sock_ops;
--      sk = l2cap_sock_alloc(sock, protocol, GFP_ATOMIC);
-+      sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
-       if (!sk)
-               return -ENOMEM;
+-      struct container *cont;
+       struct cpuset *c, *par;
  
-@@ -1425,7 +1425,7 @@
-               goto response;
+       /* Each of our child cpusets must be a subset of us */
+-      list_for_each_entry(cont, &cur->css.container->children, sibling) {
+-              if (!is_cpuset_subset(container_cs(cont), trial))
++      list_for_each_entry(c, &cur->children, sibling) {
++              if (!is_cpuset_subset(c, trial))
+                       return -EBUSY;
        }
  
--      sk = l2cap_sock_alloc(NULL, BTPROTO_L2CAP, GFP_ATOMIC);
-+      sk = l2cap_sock_alloc(parent->sk_net, NULL, BTPROTO_L2CAP, GFP_ATOMIC);
-       if (!sk)
-               goto response;
-diff -Nurb linux-2.6.22-570/net/bluetooth/rfcomm/core.c linux-2.6.22-590/net/bluetooth/rfcomm/core.c
---- linux-2.6.22-570/net/bluetooth/rfcomm/core.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bluetooth/rfcomm/core.c       2008-01-02 13:56:38.000000000 -0500
-@@ -33,6 +33,7 @@
- #include <linux/sched.h>
- #include <linux/signal.h>
- #include <linux/init.h>
-+#include <linux/freezer.h>
- #include <linux/wait.h>
- #include <linux/device.h>
- #include <linux/net.h>
-@@ -1940,7 +1941,6 @@
-       daemonize("krfcommd");
-       set_user_nice(current, -10);
--      current->flags |= PF_NOFREEZE;
+@@ -473,8 +738,7 @@
+               return -EACCES;
  
-       BT_DBG("");
+       /* If either I or some sibling (!= me) is exclusive, we can't overlap */
+-      list_for_each_entry(cont, &par->css.container->children, sibling) {
+-              c = container_cs(cont);
++      list_for_each_entry(c, &par->children, sibling) {
+               if ((is_cpu_exclusive(trial) || is_cpu_exclusive(c)) &&
+                   c != cur &&
+                   cpus_intersects(trial->cpus_allowed, c->cpus_allowed))
+@@ -489,13 +753,68 @@
+ }
  
-diff -Nurb linux-2.6.22-570/net/bluetooth/rfcomm/sock.c linux-2.6.22-590/net/bluetooth/rfcomm/sock.c
---- linux-2.6.22-570/net/bluetooth/rfcomm/sock.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bluetooth/rfcomm/sock.c       2008-01-02 13:56:38.000000000 -0500
-@@ -282,12 +282,12 @@
-       .obj_size       = sizeof(struct rfcomm_pinfo)
- };
+ /*
++ * For a given cpuset cur, partition the system as follows
++ * a. All cpus in the parent cpuset's cpus_allowed that are not part of any
++ *    exclusive child cpusets
++ * b. All cpus in the current cpuset's cpus_allowed that are not part of any
++ *    exclusive child cpusets
++ * Build these two partitions by calling partition_sched_domains
++ *
++ * Call with manage_mutex held.  May nest a call to the
++ * lock_cpu_hotplug()/unlock_cpu_hotplug() pair.
++ * Must not be called holding callback_mutex, because we must
++ * not call lock_cpu_hotplug() while holding callback_mutex.
++ */
++
++static void update_cpu_domains(struct cpuset *cur)
++{
++      struct cpuset *c, *par = cur->parent;
++      cpumask_t pspan, cspan;
++
++      if (par == NULL || cpus_empty(cur->cpus_allowed))
++              return;
++
++      /*
++       * Get all cpus from parent's cpus_allowed not part of exclusive
++       * children
++       */
++      pspan = par->cpus_allowed;
++      list_for_each_entry(c, &par->children, sibling) {
++              if (is_cpu_exclusive(c))
++                      cpus_andnot(pspan, pspan, c->cpus_allowed);
++      }
++      if (!is_cpu_exclusive(cur)) {
++              cpus_or(pspan, pspan, cur->cpus_allowed);
++              if (cpus_equal(pspan, cur->cpus_allowed))
++                      return;
++              cspan = CPU_MASK_NONE;
++      } else {
++              if (cpus_empty(pspan))
++                      return;
++              cspan = cur->cpus_allowed;
++              /*
++               * Get all cpus from current cpuset's cpus_allowed not part
++               * of exclusive children
++               */
++              list_for_each_entry(c, &cur->children, sibling) {
++                      if (is_cpu_exclusive(c))
++                              cpus_andnot(cspan, cspan, c->cpus_allowed);
++              }
++      }
++
++      lock_cpu_hotplug();
++      partition_sched_domains(&pspan, &cspan);
++      unlock_cpu_hotplug();
++}
++
++/*
+  * Call with manage_mutex held.  May take callback_mutex during call.
+  */
  
--static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, gfp_t prio)
-+static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
+ static int update_cpumask(struct cpuset *cs, char *buf)
  {
-       struct rfcomm_dlc *d;
-       struct sock *sk;
+       struct cpuset trialcs;
+-      int retval;
++      int retval, cpus_unchanged;
+       /* top_cpuset.cpus_allowed tracks cpu_online_map; it's read-only */
+       if (cs == &top_cpuset)
+@@ -517,15 +836,17 @@
+       }
+       cpus_and(trialcs.cpus_allowed, trialcs.cpus_allowed, cpu_online_map);
+       /* cpus_allowed cannot be empty for a cpuset with attached tasks. */
+-      if (container_task_count(cs->css.container) &&
+-            cpus_empty(trialcs.cpus_allowed))
++      if (atomic_read(&cs->count) && cpus_empty(trialcs.cpus_allowed))
+               return -ENOSPC;
+       retval = validate_change(cs, &trialcs);
+       if (retval < 0)
+               return retval;
++      cpus_unchanged = cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed);
+       mutex_lock(&callback_mutex);
+       cs->cpus_allowed = trialcs.cpus_allowed;
+       mutex_unlock(&callback_mutex);
++      if (is_cpu_exclusive(cs) && !cpus_unchanged)
++              update_cpu_domains(cs);
+       return 0;
+ }
  
--      sk = sk_alloc(PF_BLUETOOTH, prio, &rfcomm_proto, 1);
-+      sk = sk_alloc(net, PF_BLUETOOTH, prio, &rfcomm_proto, 1);
-       if (!sk)
-               return NULL;
+@@ -574,7 +895,7 @@
+       do_migrate_pages(mm, from, to, MPOL_MF_MOVE_ALL);
  
-@@ -323,7 +323,7 @@
-       return sk;
+       mutex_lock(&callback_mutex);
+-      guarantee_online_mems(task_cs(tsk),&tsk->mems_allowed);
++      guarantee_online_mems(tsk->cpuset, &tsk->mems_allowed);
+       mutex_unlock(&callback_mutex);
  }
  
--static int rfcomm_sock_create(struct socket *sock, int protocol)
-+static int rfcomm_sock_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct sock *sk;
+@@ -592,19 +913,16 @@
+  * their mempolicies to the cpusets new mems_allowed.
+  */
  
-@@ -336,7 +336,7 @@
+-static void *cpuset_being_rebound;
+-
+ static int update_nodemask(struct cpuset *cs, char *buf)
+ {
+       struct cpuset trialcs;
+       nodemask_t oldmem;
+-      struct task_struct *p;
++      struct task_struct *g, *p;
+       struct mm_struct **mmarray;
+       int i, n, ntasks;
+       int migrate;
+       int fudge;
+       int retval;
+-      struct container_iter it;
  
-       sock->ops = &rfcomm_sock_ops;
+       /* top_cpuset.mems_allowed tracks node_online_map; it's read-only */
+       if (cs == &top_cpuset)
+@@ -631,8 +949,7 @@
+               goto done;
+       }
+       /* mems_allowed cannot be empty for a cpuset with attached tasks. */
+-      if (container_task_count(cs->css.container) &&
+-          nodes_empty(trialcs.mems_allowed)) {
++      if (atomic_read(&cs->count) && nodes_empty(trialcs.mems_allowed)) {
+               retval = -ENOSPC;
+               goto done;
+       }
+@@ -645,7 +962,7 @@
+       cs->mems_generation = cpuset_mems_generation++;
+       mutex_unlock(&callback_mutex);
  
--      sk = rfcomm_sock_alloc(sock, protocol, GFP_ATOMIC);
-+      sk = rfcomm_sock_alloc(net, sock, protocol, GFP_ATOMIC);
-       if (!sk)
-               return -ENOMEM;
+-      cpuset_being_rebound = cs;              /* causes mpol_copy() rebind */
++      set_cpuset_being_rebound(cs);           /* causes mpol_copy() rebind */
  
-@@ -868,7 +868,7 @@
-               goto done;
+       fudge = 10;                             /* spare mmarray[] slots */
+       fudge += cpus_weight(cs->cpus_allowed); /* imagine one fork-bomb/cpu */
+@@ -659,37 +976,37 @@
+        * enough mmarray[] w/o using GFP_ATOMIC.
+        */
+       while (1) {
+-              ntasks = container_task_count(cs->css.container);  /* guess */
++              ntasks = atomic_read(&cs->count);       /* guess */
+               ntasks += fudge;
+               mmarray = kmalloc(ntasks * sizeof(*mmarray), GFP_KERNEL);
+               if (!mmarray)
+                       goto done;
+-              read_lock(&tasklist_lock);              /* block fork */
+-              if (container_task_count(cs->css.container) <= ntasks)
++              write_lock_irq(&tasklist_lock);         /* block fork */
++              if (atomic_read(&cs->count) <= ntasks)
+                       break;                          /* got enough */
+-              read_unlock(&tasklist_lock);            /* try again */
++              write_unlock_irq(&tasklist_lock);       /* try again */
+               kfree(mmarray);
        }
  
--      sk = rfcomm_sock_alloc(NULL, BTPROTO_RFCOMM, GFP_ATOMIC);
-+      sk = rfcomm_sock_alloc(parent->sk_net, NULL, BTPROTO_RFCOMM, GFP_ATOMIC);
-       if (!sk)
-               goto done;
+       n = 0;
  
-diff -Nurb linux-2.6.22-570/net/bluetooth/sco.c linux-2.6.22-590/net/bluetooth/sco.c
---- linux-2.6.22-570/net/bluetooth/sco.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bluetooth/sco.c       2008-01-02 13:56:38.000000000 -0500
-@@ -414,11 +414,11 @@
-       .obj_size       = sizeof(struct sco_pinfo)
- };
+       /* Load up mmarray[] with mm reference for each task in cpuset. */
+-      container_iter_start(cs->css.container, &it);
+-      while ((p = container_iter_next(cs->css.container, &it))) {
++      do_each_thread(g, p) {
+               struct mm_struct *mm;
  
--static struct sock *sco_sock_alloc(struct socket *sock, int proto, gfp_t prio)
-+static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
- {
-       struct sock *sk;
+               if (n >= ntasks) {
+                       printk(KERN_WARNING
+                               "Cpuset mempolicy rebind incomplete.\n");
+-                      break;
++                      continue;
+               }
++              if (p->cpuset != cs)
++                      continue;
+               mm = get_task_mm(p);
+               if (!mm)
+                       continue;
+               mmarray[n++] = mm;
+-      }
+-      container_iter_end(cs->css.container, &it);
+-      read_unlock(&tasklist_lock);
++      } while_each_thread(g, p);
++      write_unlock_irq(&tasklist_lock);
  
--      sk = sk_alloc(PF_BLUETOOTH, prio, &sco_proto, 1);
-+      sk = sk_alloc(net, PF_BLUETOOTH, prio, &sco_proto, 1);
-       if (!sk)
-               return NULL;
+       /*
+        * Now that we've dropped the tasklist spinlock, we can
+@@ -716,17 +1033,12 @@
  
-@@ -439,7 +439,7 @@
-       return sk;
+       /* We're done rebinding vma's to this cpusets new mems_allowed. */
+       kfree(mmarray);
+-      cpuset_being_rebound = NULL;
++      set_cpuset_being_rebound(NULL);
+       retval = 0;
+ done:
+       return retval;
  }
  
--static int sco_sock_create(struct socket *sock, int protocol)
-+static int sco_sock_create(struct net *net, struct socket *sock, int protocol)
+-int current_cpuset_is_being_rebound(void)
+-{
+-      return task_cs(current) == cpuset_being_rebound;
+-}
+-
+ /*
+  * Call with manage_mutex held.
+  */
+@@ -755,7 +1067,7 @@
  {
-       struct sock *sk;
+       int turning_on;
+       struct cpuset trialcs;
+-      int err;
++      int err, cpu_exclusive_changed;
  
-@@ -452,7 +452,7 @@
+       turning_on = (simple_strtoul(buf, NULL, 10) != 0);
  
-       sock->ops = &sco_sock_ops;
+@@ -768,10 +1080,14 @@
+       err = validate_change(cs, &trialcs);
+       if (err < 0)
+               return err;
++      cpu_exclusive_changed =
++              (is_cpu_exclusive(cs) != is_cpu_exclusive(&trialcs));
+       mutex_lock(&callback_mutex);
+       cs->flags = trialcs.flags;
+       mutex_unlock(&callback_mutex);
  
--      sk = sco_sock_alloc(sock, protocol, GFP_ATOMIC);
-+      sk = sco_sock_alloc(net, sock, protocol, GFP_ATOMIC);
-       if (!sk)
-               return -ENOMEM;
++      if (cpu_exclusive_changed)
++                update_cpu_domains(cs);
+       return 0;
+ }
  
-@@ -807,7 +807,7 @@
+@@ -873,34 +1189,85 @@
+       return val;
+ }
  
-               bh_lock_sock(parent);
+-int cpuset_can_attach(struct container_subsys *ss,
+-                    struct container *cont, struct task_struct *tsk)
++/*
++ * Attack task specified by pid in 'pidbuf' to cpuset 'cs', possibly
++ * writing the path of the old cpuset in 'ppathbuf' if it needs to be
++ * notified on release.
++ *
++ * Call holding manage_mutex.  May take callback_mutex and task_lock of
++ * the task 'pid' during call.
++ */
++
++static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
+ {
+-      struct cpuset *cs = container_cs(cont);
++      pid_t pid;
++      struct task_struct *tsk;
++      struct cpuset *oldcs;
++      cpumask_t cpus;
++      nodemask_t from, to;
++      struct mm_struct *mm;
++      int retval;
  
--              sk = sco_sock_alloc(NULL, BTPROTO_SCO, GFP_ATOMIC);
-+              sk = sco_sock_alloc(parent->sk_net, NULL, BTPROTO_SCO, GFP_ATOMIC);
-               if (!sk) {
-                       bh_unlock_sock(parent);
-                       goto done;
-diff -Nurb linux-2.6.22-570/net/bridge/br_if.c linux-2.6.22-590/net/bridge/br_if.c
---- linux-2.6.22-570/net/bridge/br_if.c        2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/bridge/br_if.c        2008-01-02 13:56:38.000000000 -0500
-@@ -45,7 +45,7 @@
++      if (sscanf(pidbuf, "%d", &pid) != 1)
++              return -EIO;
+       if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed))
+               return -ENOSPC;
  
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
--      err = dev_ethtool(&ifr);
-+      err = dev_ethtool(dev->nd_net, &ifr);
-       set_fs(old_fs);
+-      return security_task_setscheduler(tsk, 0, NULL);
+-}
++      if (pid) {
++              read_lock(&tasklist_lock);
  
-       if (!err) {
-@@ -314,7 +314,7 @@
-       int ret = 0;
+-void cpuset_attach(struct container_subsys *ss,
+-                 struct container *cont, struct container *oldcont,
+-                 struct task_struct *tsk)
+-{
+-      cpumask_t cpus;
+-      nodemask_t from, to;
+-      struct mm_struct *mm;
+-      struct cpuset *cs = container_cs(cont);
+-      struct cpuset *oldcs = container_cs(oldcont);
++              tsk = find_task_by_pid(pid);
++              if (!tsk || tsk->flags & PF_EXITING) {
++                      read_unlock(&tasklist_lock);
++                      return -ESRCH;
++              }
++
++              get_task_struct(tsk);
++              read_unlock(&tasklist_lock);
++
++              if ((current->euid) && (current->euid != tsk->uid)
++                  && (current->euid != tsk->suid)) {
++                      put_task_struct(tsk);
++                      return -EACCES;
++              }
++      } else {
++              tsk = current;
++              get_task_struct(tsk);
++      }
++
++      retval = security_task_setscheduler(tsk, 0, NULL);
++      if (retval) {
++              put_task_struct(tsk);
++              return retval;
++      }
  
-       rtnl_lock();
--      dev = __dev_get_by_name(name);
-+      dev = __dev_get_by_name(&init_net, name);
-       if (dev == NULL)
-               ret =  -ENXIO;  /* Could not find device */
+       mutex_lock(&callback_mutex);
++
++      task_lock(tsk);
++      oldcs = tsk->cpuset;
++      /*
++       * After getting 'oldcs' cpuset ptr, be sure still not exiting.
++       * If 'oldcs' might be the top_cpuset due to the_top_cpuset_hack
++       * then fail this attach_task(), to avoid breaking top_cpuset.count.
++       */
++      if (tsk->flags & PF_EXITING) {
++              task_unlock(tsk);
++              mutex_unlock(&callback_mutex);
++              put_task_struct(tsk);
++              return -ESRCH;
++      }
++      atomic_inc(&cs->count);
++      rcu_assign_pointer(tsk->cpuset, cs);
++      task_unlock(tsk);
++
+       guarantee_online_cpus(cs, &cpus);
+       set_cpus_allowed(tsk, cpus);
+-      mutex_unlock(&callback_mutex);
  
-@@ -455,7 +455,7 @@
-       struct net_device *dev, *nxt;
+       from = oldcs->mems_allowed;
+       to = cs->mems_allowed;
++
++      mutex_unlock(&callback_mutex);
++
+       mm = get_task_mm(tsk);
+       if (mm) {
+               mpol_rebind_mm(mm, &to);
+@@ -909,31 +1276,40 @@
+               mmput(mm);
+       }
  
-       rtnl_lock();
--      for_each_netdev_safe(dev, nxt)
-+      for_each_netdev_safe(&init_net, dev, nxt)
-               if (dev->priv_flags & IFF_EBRIDGE)
-                       del_br(dev->priv);
-       rtnl_unlock();
-diff -Nurb linux-2.6.22-570/net/bridge/br_ioctl.c linux-2.6.22-590/net/bridge/br_ioctl.c
---- linux-2.6.22-570/net/bridge/br_ioctl.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bridge/br_ioctl.c     2008-01-02 13:56:38.000000000 -0500
-@@ -18,6 +18,7 @@
- #include <linux/if_bridge.h>
- #include <linux/netdevice.h>
- #include <linux/times.h>
-+#include <net/net_namespace.h>
- #include <asm/uaccess.h>
- #include "br_private.h"
++      put_task_struct(tsk);
++      synchronize_rcu();
++      if (atomic_dec_and_test(&oldcs->count))
++              check_for_release(oldcs, ppathbuf);
++      return 0;
+ }
  
-@@ -27,7 +28,7 @@
-       struct net_device *dev;
-       int i = 0;
+ /* The various types of files and directories in a cpuset file system */
  
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if (i >= num)
-                       break;
-               if (dev->priv_flags & IFF_EBRIDGE)
-@@ -90,7 +91,7 @@
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
+ typedef enum {
++      FILE_ROOT,
++      FILE_DIR,
+       FILE_MEMORY_MIGRATE,
+       FILE_CPULIST,
+       FILE_MEMLIST,
+       FILE_CPU_EXCLUSIVE,
+       FILE_MEM_EXCLUSIVE,
++      FILE_NOTIFY_ON_RELEASE,
+       FILE_MEMORY_PRESSURE_ENABLED,
+       FILE_MEMORY_PRESSURE,
+       FILE_SPREAD_PAGE,
+       FILE_SPREAD_SLAB,
++      FILE_TASKLIST,
+ } cpuset_filetype_t;
  
--      dev = dev_get_by_index(ifindex);
-+      dev = dev_get_by_index(&init_net, ifindex);
-       if (dev == NULL)
-               return -EINVAL;
+-static ssize_t cpuset_common_file_write(struct container *cont,
+-                                      struct cftype *cft,
+-                                      struct file *file,
++static ssize_t cpuset_common_file_write(struct file *file,
+                                       const char __user *userbuf,
+                                       size_t nbytes, loff_t *unused_ppos)
+ {
+-      struct cpuset *cs = container_cs(cont);
++      struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
++      struct cftype *cft = __d_cft(file->f_path.dentry);
+       cpuset_filetype_t type = cft->private;
+       char *buffer;
++      char *pathbuf = NULL;
+       int retval = 0;
  
-@@ -364,7 +365,7 @@
-       return -EOPNOTSUPP;
- }
+       /* Crude upper limit on largest legitimate cpulist user might write. */
+@@ -950,9 +1326,9 @@
+       }
+       buffer[nbytes] = 0;     /* nul-terminate */
  
--int br_ioctl_deviceless_stub(unsigned int cmd, void __user *uarg)
-+int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg)
- {
-       switch (cmd) {
-       case SIOCGIFBR:
-diff -Nurb linux-2.6.22-570/net/bridge/br_netfilter.c linux-2.6.22-590/net/bridge/br_netfilter.c
---- linux-2.6.22-570/net/bridge/br_netfilter.c 2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/bridge/br_netfilter.c 2008-01-02 13:56:38.000000000 -0500
-@@ -310,6 +310,7 @@
-               if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) {
-                       struct rtable *rt;
-                       struct flowi fl = {
-+                              .fl_net = &init_net,
-                               .nl_u = {
-                                       .ip4_u = {
-                                                .daddr = iph->daddr,
-@@ -518,6 +519,10 @@
-       if (unlikely(!pskb_may_pull(skb, len)))
-               goto out;
+-      container_lock();
++      mutex_lock(&manage_mutex);
+-      if (container_is_removed(cont)) {
++      if (is_removed(cs)) {
+               retval = -ENODEV;
+               goto out2;
+       }
+@@ -970,6 +1346,9 @@
+       case FILE_MEM_EXCLUSIVE:
+               retval = update_flag(CS_MEM_EXCLUSIVE, cs, buffer);
+               break;
++      case FILE_NOTIFY_ON_RELEASE:
++              retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer);
++              break;
+       case FILE_MEMORY_MIGRATE:
+               retval = update_flag(CS_MEMORY_MIGRATE, cs, buffer);
+               break;
+@@ -987,6 +1366,9 @@
+               retval = update_flag(CS_SPREAD_SLAB, cs, buffer);
+               cs->mems_generation = cpuset_mems_generation++;
+               break;
++      case FILE_TASKLIST:
++              retval = attach_task(cs, buffer, &pathbuf);
++              break;
+       default:
+               retval = -EINVAL;
+               goto out2;
+@@ -995,12 +1377,30 @@
+       if (retval == 0)
+               retval = nbytes;
+ out2:
+-      container_unlock();
++      mutex_unlock(&manage_mutex);
++      cpuset_release_agent(pathbuf);
+ out1:
+       kfree(buffer);
+       return retval;
+ }
  
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++static ssize_t cpuset_file_write(struct file *file, const char __user *buf,
++                                              size_t nbytes, loff_t *ppos)
++{
++      ssize_t retval = 0;
++      struct cftype *cft = __d_cft(file->f_path.dentry);
++      if (!cft)
++              return -ENODEV;
 +
-       if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb) ||
-           IS_PPPOE_IPV6(skb)) {
- #ifdef CONFIG_SYSCTL
-@@ -591,6 +596,10 @@
++      /* special function ? */
++      if (cft->write)
++              retval = cft->write(file, buf, nbytes, ppos);
++      else
++              retval = cpuset_common_file_write(file, buf, nbytes, ppos);
++
++      return retval;
++}
++
+ /*
+  * These ascii lists should be read in a single call, by using a user
+  * buffer large enough to hold the entire map.  If read in smaller
+@@ -1035,19 +1435,17 @@
+       return nodelist_scnprintf(page, PAGE_SIZE, mask);
+ }
+-static ssize_t cpuset_common_file_read(struct container *cont,
+-                                     struct cftype *cft,
+-                                     struct file *file,
+-                                     char __user *buf,
++static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
+                               size_t nbytes, loff_t *ppos)
  {
-       struct sk_buff *skb = *pskb;
+-      struct cpuset *cs = container_cs(cont);
++      struct cftype *cft = __d_cft(file->f_path.dentry);
++      struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
+       cpuset_filetype_t type = cft->private;
+       char *page;
+       ssize_t retval = 0;
+       char *s;
  
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       if (skb->dst == (struct dst_entry *)&__fake_rtable) {
-               dst_release(skb->dst);
-               skb->dst = NULL;
-@@ -635,6 +644,10 @@
-       struct net_device *parent;
-       int pf;
+-      if (!(page = (char *)__get_free_page(GFP_TEMPORARY)))
++      if (!(page = (char *)__get_free_page(GFP_KERNEL)))
+               return -ENOMEM;
+       s = page;
+@@ -1065,6 +1463,9 @@
+       case FILE_MEM_EXCLUSIVE:
+               *s++ = is_mem_exclusive(cs) ? '1' : '0';
+               break;
++      case FILE_NOTIFY_ON_RELEASE:
++              *s++ = notify_on_release(cs) ? '1' : '0';
++              break;
+       case FILE_MEMORY_MIGRATE:
+               *s++ = is_memory_migrate(cs) ? '1' : '0';
+               break;
+@@ -1092,140 +1493,390 @@
+       return retval;
+ }
  
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++static ssize_t cpuset_file_read(struct file *file, char __user *buf, size_t nbytes,
++                                                              loff_t *ppos)
++{
++      ssize_t retval = 0;
++      struct cftype *cft = __d_cft(file->f_path.dentry);
++      if (!cft)
++              return -ENODEV;
++
++      /* special function ? */
++      if (cft->read)
++              retval = cft->read(file, buf, nbytes, ppos);
++      else
++              retval = cpuset_common_file_read(file, buf, nbytes, ppos);
++
++      return retval;
++}
++
++static int cpuset_file_open(struct inode *inode, struct file *file)
++{
++      int err;
++      struct cftype *cft;
++
++      err = generic_file_open(inode, file);
++      if (err)
++              return err;
++
++      cft = __d_cft(file->f_path.dentry);
++      if (!cft)
++              return -ENODEV;
++      if (cft->open)
++              err = cft->open(inode, file);
++      else
++              err = 0;
++
++      return err;
++}
++
++static int cpuset_file_release(struct inode *inode, struct file *file)
++{
++      struct cftype *cft = __d_cft(file->f_path.dentry);
++      if (cft->release)
++              return cft->release(inode, file);
++      return 0;
++}
++
++/*
++ * cpuset_rename - Only allow simple rename of directories in place.
++ */
++static int cpuset_rename(struct inode *old_dir, struct dentry *old_dentry,
++                  struct inode *new_dir, struct dentry *new_dentry)
++{
++      if (!S_ISDIR(old_dentry->d_inode->i_mode))
++              return -ENOTDIR;
++      if (new_dentry->d_inode)
++              return -EEXIST;
++      if (old_dir != new_dir)
++              return -EIO;
++      return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
++}
++
++static const struct file_operations cpuset_file_operations = {
++      .read = cpuset_file_read,
++      .write = cpuset_file_write,
++      .llseek = generic_file_llseek,
++      .open = cpuset_file_open,
++      .release = cpuset_file_release,
++};
++
++static const struct inode_operations cpuset_dir_inode_operations = {
++      .lookup = simple_lookup,
++      .mkdir = cpuset_mkdir,
++      .rmdir = cpuset_rmdir,
++      .rename = cpuset_rename,
++};
++
++static int cpuset_create_file(struct dentry *dentry, int mode)
++{
++      struct inode *inode;
++
++      if (!dentry)
++              return -ENOENT;
++      if (dentry->d_inode)
++              return -EEXIST;
++
++      inode = cpuset_new_inode(mode);
++      if (!inode)
++              return -ENOMEM;
++
++      if (S_ISDIR(mode)) {
++              inode->i_op = &cpuset_dir_inode_operations;
++              inode->i_fop = &simple_dir_operations;
++
++              /* start off with i_nlink == 2 (for "." entry) */
++              inc_nlink(inode);
++      } else if (S_ISREG(mode)) {
++              inode->i_size = 0;
++              inode->i_fop = &cpuset_file_operations;
++      }
++
++      d_instantiate(dentry, inode);
++      dget(dentry);   /* Extra count - pin the dentry in core */
++      return 0;
++}
++
++/*
++ *    cpuset_create_dir - create a directory for an object.
++ *    cs:     the cpuset we create the directory for.
++ *            It must have a valid ->parent field
++ *            And we are going to fill its ->dentry field.
++ *    name:   The name to give to the cpuset directory. Will be copied.
++ *    mode:   mode to set on new directory.
++ */
++
++static int cpuset_create_dir(struct cpuset *cs, const char *name, int mode)
++{
++      struct dentry *dentry = NULL;
++      struct dentry *parent;
++      int error = 0;
++
++      parent = cs->parent->dentry;
++      dentry = cpuset_get_dentry(parent, name);
++      if (IS_ERR(dentry))
++              return PTR_ERR(dentry);
++      error = cpuset_create_file(dentry, S_IFDIR | mode);
++      if (!error) {
++              dentry->d_fsdata = cs;
++              inc_nlink(parent->d_inode);
++              cs->dentry = dentry;
++      }
++      dput(dentry);
++
++      return error;
++}
++
++static int cpuset_add_file(struct dentry *dir, const struct cftype *cft)
++{
++      struct dentry *dentry;
++      int error;
++
++      mutex_lock(&dir->d_inode->i_mutex);
++      dentry = cpuset_get_dentry(dir, cft->name);
++      if (!IS_ERR(dentry)) {
++              error = cpuset_create_file(dentry, 0644 | S_IFREG);
++              if (!error)
++                      dentry->d_fsdata = (void *)cft;
++              dput(dentry);
++      } else
++              error = PTR_ERR(dentry);
++      mutex_unlock(&dir->d_inode->i_mutex);
++      return error;
++}
++
++/*
++ * Stuff for reading the 'tasks' file.
++ *
++ * Reading this file can return large amounts of data if a cpuset has
++ * *lots* of attached tasks. So it may need several calls to read(),
++ * but we cannot guarantee that the information we produce is correct
++ * unless we produce it entirely atomically.
++ *
++ * Upon tasks file open(), a struct ctr_struct is allocated, that
++ * will have a pointer to an array (also allocated here).  The struct
++ * ctr_struct * is stored in file->private_data.  Its resources will
++ * be freed by release() when the file is closed.  The array is used
++ * to sprintf the PIDs and then used by read().
++ */
++
++/* cpusets_tasks_read array */
++
++struct ctr_struct {
++      char *buf;
++      int bufsz;
++};
++
++/*
++ * Load into 'pidarray' up to 'npids' of the tasks using cpuset 'cs'.
++ * Return actual number of pids loaded.  No need to task_lock(p)
++ * when reading out p->cpuset, as we don't really care if it changes
++ * on the next cycle, and we are not going to try to dereference it.
++ */
++static int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs)
++{
++      int n = 0;
++      struct task_struct *g, *p;
++
++      read_lock(&tasklist_lock);
++
++      do_each_thread(g, p) {
++              if (p->cpuset == cs) {
++                      if (unlikely(n == npids))
++                              goto array_full;
++                      pidarray[n++] = p->pid;
++              }
++      } while_each_thread(g, p);
++
++array_full:
++      read_unlock(&tasklist_lock);
++      return n;
++}
++
++static int cmppid(const void *a, const void *b)
++{
++      return *(pid_t *)a - *(pid_t *)b;
++}
++
++/*
++ * Convert array 'a' of 'npids' pid_t's to a string of newline separated
++ * decimal pids in 'buf'.  Don't write more than 'sz' chars, but return
++ * count 'cnt' of how many chars would be written if buf were large enough.
++ */
++static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids)
++{
++      int cnt = 0;
++      int i;
++
++      for (i = 0; i < npids; i++)
++              cnt += snprintf(buf + cnt, max(sz - cnt, 0), "%d\n", a[i]);
++      return cnt;
++}
++
++/*
++ * Handle an open on 'tasks' file.  Prepare a buffer listing the
++ * process id's of tasks currently attached to the cpuset being opened.
++ *
++ * Does not require any specific cpuset mutexes, and does not take any.
++ */
++static int cpuset_tasks_open(struct inode *unused, struct file *file)
++{
++      struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
++      struct ctr_struct *ctr;
++      pid_t *pidarray;
++      int npids;
++      char c;
++
++      if (!(file->f_mode & FMODE_READ))
++              return 0;
++
++      ctr = kmalloc(sizeof(*ctr), GFP_KERNEL);
++      if (!ctr)
++              goto err0;
 +
-       if (!skb->nf_bridge)
-               return NF_ACCEPT;
-@@ -674,6 +687,10 @@
-       struct sk_buff *skb = *pskb;
-       struct net_device **d = (struct net_device **)(skb->cb);
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++      /*
++       * If cpuset gets more users after we read count, we won't have
++       * enough space - tough.  This race is indistinguishable to the
++       * caller from the case that the additional cpuset users didn't
++       * show up until sometime later on.
++       */
++      npids = atomic_read(&cs->count);
++      pidarray = kmalloc(npids * sizeof(pid_t), GFP_KERNEL);
++      if (!pidarray)
++              goto err1;
 +
- #ifdef CONFIG_SYSCTL
-       if (!brnf_call_arptables)
-               return NF_ACCEPT;
-@@ -718,6 +735,10 @@
-       struct sk_buff *skb = *pskb;
-       struct nf_bridge_info *nf_bridge;
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++      npids = pid_array_load(pidarray, npids, cs);
++      sort(pidarray, npids, sizeof(pid_t), cmppid, NULL);
 +
-       if (!skb->nf_bridge)
-               return NF_ACCEPT;
-@@ -762,6 +783,10 @@
-       struct net_device *realoutdev = bridge_parent(skb->dev);
-       int pf;
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++      /* Call pid_array_to_buf() twice, first just to get bufsz */
++      ctr->bufsz = pid_array_to_buf(&c, sizeof(c), pidarray, npids) + 1;
++      ctr->buf = kmalloc(ctr->bufsz, GFP_KERNEL);
++      if (!ctr->buf)
++              goto err2;
++      ctr->bufsz = pid_array_to_buf(ctr->buf, ctr->bufsz, pidarray, npids);
 +
- #ifdef CONFIG_NETFILTER_DEBUG
-       /* Be very paranoid. This probably won't happen anymore, but let's
-        * keep the check just to be sure... */
-@@ -833,6 +858,10 @@
-                                  const struct net_device *out,
-                                  int (*okfn)(struct sk_buff *))
- {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++      kfree(pidarray);
++      file->private_data = ctr;
++      return 0;
 +
-       if ((*pskb)->nf_bridge &&
-           !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
-               return NF_STOP;
-diff -Nurb linux-2.6.22-570/net/bridge/br_netlink.c linux-2.6.22-590/net/bridge/br_netlink.c
---- linux-2.6.22-570/net/bridge/br_netlink.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bridge/br_netlink.c   2008-01-02 13:56:38.000000000 -0500
-@@ -12,6 +12,8 @@
++err2:
++      kfree(pidarray);
++err1:
++      kfree(ctr);
++err0:
++      return -ENOMEM;
++}
++
++static ssize_t cpuset_tasks_read(struct file *file, char __user *buf,
++                                              size_t nbytes, loff_t *ppos)
++{
++      struct ctr_struct *ctr = file->private_data;
  
- #include <linux/kernel.h>
- #include <net/rtnetlink.h>
-+#include <net/net_namespace.h>
-+#include <net/sock.h>
- #include "br_private.h"
++      return simple_read_from_buffer(buf, nbytes, ppos, ctr->buf, ctr->bufsz);
++}
  
- static inline size_t br_nlmsg_size(void)
-@@ -95,10 +97,10 @@
-               kfree_skb(skb);
-               goto errout;
-       }
--      err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
-+      err = rtnl_notify(skb, &init_net,0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
- errout:
-       if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_LINK, err);
-+              rtnl_set_sk_err(&init_net, RTNLGRP_LINK, err);
- }
++static int cpuset_tasks_release(struct inode *unused_inode, struct file *file)
++{
++      struct ctr_struct *ctr;
  
- /*
-@@ -106,11 +108,15 @@
-  */
- static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct net_device *dev;
-       int idx;
++      if (file->f_mode & FMODE_READ) {
++              ctr = file->private_data;
++              kfree(ctr->buf);
++              kfree(ctr);
++      }
++      return 0;
++}
  
-+      if (net != &init_net)
-+              return 0;
-+
-       idx = 0;
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               /* not a bridge port */
-               if (dev->br_port == NULL || idx < cb->args[0])
-                       goto skip;
-@@ -134,12 +140,16 @@
+ /*
+  * for the common functions, 'private' gives the type of file
   */
- static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct ifinfomsg *ifm;
-       struct nlattr *protinfo;
-       struct net_device *dev;
-       struct net_bridge_port *p;
-       u8 new_state;
  
-+      if (net != &init_net)
-+              return -EINVAL;
++static struct cftype cft_tasks = {
++      .name = "tasks",
++      .open = cpuset_tasks_open,
++      .read = cpuset_tasks_read,
++      .release = cpuset_tasks_release,
++      .private = FILE_TASKLIST,
++};
 +
-       if (nlmsg_len(nlh) < sizeof(*ifm))
-               return -EINVAL;
-@@ -155,7 +165,7 @@
-       if (new_state > BR_STATE_BLOCKING)
              return -EINVAL;
+ static struct cftype cft_cpus = {
+       .name = "cpus",
+-      .read = cpuset_common_file_read,
+-      .write = cpuset_common_file_write,
+       .private = FILE_CPULIST,
};
  
--      dev = __dev_get_by_index(ifm->ifi_index);
-+      dev = __dev_get_by_index(&init_net, ifm->ifi_index);
-       if (!dev)
-               return -ENODEV;
+ static struct cftype cft_mems = {
+       .name = "mems",
+-      .read = cpuset_common_file_read,
+-      .write = cpuset_common_file_write,
+       .private = FILE_MEMLIST,
+ };
  
-diff -Nurb linux-2.6.22-570/net/bridge/br_notify.c linux-2.6.22-590/net/bridge/br_notify.c
---- linux-2.6.22-570/net/bridge/br_notify.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bridge/br_notify.c    2008-01-02 13:56:38.000000000 -0500
-@@ -15,6 +15,7 @@
+ static struct cftype cft_cpu_exclusive = {
+       .name = "cpu_exclusive",
+-      .read = cpuset_common_file_read,
+-      .write = cpuset_common_file_write,
+       .private = FILE_CPU_EXCLUSIVE,
+ };
  
- #include <linux/kernel.h>
- #include <linux/rtnetlink.h>
-+#include <net/net_namespace.h>
+ static struct cftype cft_mem_exclusive = {
+       .name = "mem_exclusive",
+-      .read = cpuset_common_file_read,
+-      .write = cpuset_common_file_write,
+       .private = FILE_MEM_EXCLUSIVE,
+ };
  
- #include "br_private.h"
++static struct cftype cft_notify_on_release = {
++      .name = "notify_on_release",
++      .private = FILE_NOTIFY_ON_RELEASE,
++};
++
+ static struct cftype cft_memory_migrate = {
+       .name = "memory_migrate",
+-      .read = cpuset_common_file_read,
+-      .write = cpuset_common_file_write,
+       .private = FILE_MEMORY_MIGRATE,
+ };
  
-@@ -36,6 +37,9 @@
-       struct net_bridge_port *p = dev->br_port;
-       struct net_bridge *br;
+ static struct cftype cft_memory_pressure_enabled = {
+       .name = "memory_pressure_enabled",
+-      .read = cpuset_common_file_read,
+-      .write = cpuset_common_file_write,
+       .private = FILE_MEMORY_PRESSURE_ENABLED,
+ };
  
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       /* not a port of a bridge */
-       if (p == NULL)
-               return NOTIFY_DONE;
-diff -Nurb linux-2.6.22-570/net/bridge/br_private.h linux-2.6.22-590/net/bridge/br_private.h
---- linux-2.6.22-570/net/bridge/br_private.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bridge/br_private.h   2008-01-02 13:56:38.000000000 -0500
-@@ -196,7 +196,7 @@
+ static struct cftype cft_memory_pressure = {
+       .name = "memory_pressure",
+-      .read = cpuset_common_file_read,
+-      .write = cpuset_common_file_write,
+       .private = FILE_MEMORY_PRESSURE,
+ };
  
- /* br_ioctl.c */
- extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
--extern int br_ioctl_deviceless_stub(unsigned int cmd, void __user *arg);
-+extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *arg);
+ static struct cftype cft_spread_page = {
+       .name = "memory_spread_page",
+-      .read = cpuset_common_file_read,
+-      .write = cpuset_common_file_write,
+       .private = FILE_SPREAD_PAGE,
+ };
  
- /* br_netfilter.c */
- #ifdef CONFIG_BRIDGE_NETFILTER
-diff -Nurb linux-2.6.22-570/net/bridge/br_stp_bpdu.c linux-2.6.22-590/net/bridge/br_stp_bpdu.c
---- linux-2.6.22-570/net/bridge/br_stp_bpdu.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bridge/br_stp_bpdu.c  2008-01-02 13:56:38.000000000 -0500
-@@ -17,6 +17,7 @@
- #include <linux/netfilter_bridge.h>
- #include <linux/etherdevice.h>
- #include <linux/llc.h>
-+#include <net/net_namespace.h>
- #include <net/llc.h>
- #include <net/llc_pdu.h>
- #include <asm/unaligned.h>
-@@ -141,6 +142,9 @@
-       struct net_bridge *br;
-       const unsigned char *buf;
+ static struct cftype cft_spread_slab = {
+       .name = "memory_spread_slab",
+-      .read = cpuset_common_file_read,
+-      .write = cpuset_common_file_write,
+       .private = FILE_SPREAD_SLAB,
+ };
  
-+      if (dev->nd_net != &init_net)
-+              goto err;
-+
-       if (!p)
-               goto err;
+-int cpuset_populate(struct container_subsys *ss, struct container *cont)
++static int cpuset_populate_dir(struct dentry *cs_dentry)
+ {
+       int err;
  
-diff -Nurb linux-2.6.22-570/net/bridge/br_stp_if.c linux-2.6.22-590/net/bridge/br_stp_if.c
---- linux-2.6.22-570/net/bridge/br_stp_if.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bridge/br_stp_if.c    2008-01-02 13:56:38.000000000 -0500
-@@ -125,7 +125,7 @@
-       char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL };
-       char *envp[] = { NULL };
+-      if ((err = container_add_file(cont, &cft_cpus)) < 0)
++      if ((err = cpuset_add_file(cs_dentry, &cft_cpus)) < 0)
+               return err;
+-      if ((err = container_add_file(cont, &cft_mems)) < 0)
++      if ((err = cpuset_add_file(cs_dentry, &cft_mems)) < 0)
+               return err;
+-      if ((err = container_add_file(cont, &cft_cpu_exclusive)) < 0)
++      if ((err = cpuset_add_file(cs_dentry, &cft_cpu_exclusive)) < 0)
+               return err;
+-      if ((err = container_add_file(cont, &cft_mem_exclusive)) < 0)
++      if ((err = cpuset_add_file(cs_dentry, &cft_mem_exclusive)) < 0)
+               return err;
+-      if ((err = container_add_file(cont, &cft_memory_migrate)) < 0)
++      if ((err = cpuset_add_file(cs_dentry, &cft_notify_on_release)) < 0)
+               return err;
+-      if ((err = container_add_file(cont, &cft_memory_pressure)) < 0)
++      if ((err = cpuset_add_file(cs_dentry, &cft_memory_migrate)) < 0)
+               return err;
+-      if ((err = container_add_file(cont, &cft_spread_page)) < 0)
++      if ((err = cpuset_add_file(cs_dentry, &cft_memory_pressure)) < 0)
+               return err;
+-      if ((err = container_add_file(cont, &cft_spread_slab)) < 0)
++      if ((err = cpuset_add_file(cs_dentry, &cft_spread_page)) < 0)
++              return err;
++      if ((err = cpuset_add_file(cs_dentry, &cft_spread_slab)) < 0)
++              return err;
++      if ((err = cpuset_add_file(cs_dentry, &cft_tasks)) < 0)
+               return err;
+-      /* memory_pressure_enabled is in root cpuset only */
+-      if (err == 0 && !cont->parent)
+-              err = container_add_file(cont, &cft_memory_pressure_enabled);
+       return 0;
+ }
  
--      r = call_usermodehelper(BR_STP_PROG, argv, envp, 1);
-+      r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
-       if (r == 0) {
-               br->stp_enabled = BR_USER_STP;
-               printk(KERN_INFO "%s: userspace STP started\n", br->dev->name);
-diff -Nurb linux-2.6.22-570/net/bridge/br_sysfs_br.c linux-2.6.22-590/net/bridge/br_sysfs_br.c
---- linux-2.6.22-570/net/bridge/br_sysfs_br.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bridge/br_sysfs_br.c  2008-01-02 13:56:38.000000000 -0500
-@@ -360,8 +360,9 @@
-  *
-  * Returns the number of bytes read.
+ /*
+- * post_clone() is called at the end of container_clone().
+- * 'container' was just created automatically as a result of
+- * a container_clone(), and the current task is about to
+- * be moved into 'container'.
+- *
+- * Currently we refuse to set up the container - thereby
+- * refusing the task to be entered, and as a result refusing
+- * the sys_unshare() or clone() which initiated it - if any
+- * sibling cpusets have exclusive cpus or mem.
+- *
+- * If this becomes a problem for some users who wish to
+- * allow that scenario, then cpuset_post_clone() could be
+- * changed to grant parent->cpus_allowed-sibling_cpus_exclusive
+- * (and likewise for mems) to the new container.
+- */
+-void cpuset_post_clone(struct container_subsys *ss,
+-              struct container *container)
+-{
+-      struct container *parent, *child;
+-      struct cpuset *cs, *parent_cs;
+-
+-      parent = container->parent;
+-      list_for_each_entry(child, &parent->children, sibling) {
+-              cs = container_cs(child);
+-              if (is_mem_exclusive(cs) || is_cpu_exclusive(cs))
+-                      return;
+-      }
+-      cs = container_cs(container);
+-      parent_cs = container_cs(parent);
+-
+-      cs->mems_allowed = parent_cs->mems_allowed;
+-      cs->cpus_allowed = parent_cs->cpus_allowed;
+-      return;
+-}
+-
+-/*
+  *    cpuset_create - create a cpuset
+  *    parent: cpuset that will be parent of the new cpuset.
+  *    name:           name of the new cpuset. Will be strcpy'ed.
+@@ -1234,62 +1885,124 @@
+  *    Must be called with the mutex on the parent inode held
   */
--static ssize_t brforward_read(struct kobject *kobj, char *buf,
--                         loff_t off, size_t count)
-+static ssize_t brforward_read(struct kobject *kobj,
-+                            struct bin_attribute *bin_attr,
-+                            char *buf, loff_t off, size_t count)
+-int cpuset_create(struct container_subsys *ss, struct container *cont)
++static long cpuset_create(struct cpuset *parent, const char *name, int mode)
  {
-       struct device *dev = to_dev(kobj);
-       struct net_bridge *br = to_bridge(dev);
-@@ -383,8 +384,7 @@
+       struct cpuset *cs;
+-      struct cpuset *parent;
++      int err;
  
- static struct bin_attribute bridge_forward = {
-       .attr = { .name = SYSFS_BRIDGE_FDB,
--                .mode = S_IRUGO,
--                .owner = THIS_MODULE, },
-+                .mode = S_IRUGO, },
-       .read = brforward_read,
- };
+-      if (!cont->parent) {
+-              /* This is early initialization for the top container */
+-              set_container_cs(cont, &top_cpuset);
+-              top_cpuset.css.container = cont;
+-              top_cpuset.mems_generation = cpuset_mems_generation++;
+-              return 0;
+-      }
+-      parent = container_cs(cont->parent);
+       cs = kmalloc(sizeof(*cs), GFP_KERNEL);
+       if (!cs)
+               return -ENOMEM;
  
-diff -Nurb linux-2.6.22-570/net/bridge/br_sysfs_if.c linux-2.6.22-590/net/bridge/br_sysfs_if.c
---- linux-2.6.22-570/net/bridge/br_sysfs_if.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bridge/br_sysfs_if.c  2008-01-02 13:56:38.000000000 -0500
-@@ -29,8 +29,7 @@
- #define BRPORT_ATTR(_name,_mode,_show,_store)                 \
- struct brport_attribute brport_attr_##_name = {               \
-       .attr = {.name = __stringify(_name),                    \
--               .mode = _mode,                                 \
--               .owner = THIS_MODULE, },                       \
-+               .mode = _mode },                               \
-       .show   = _show,                                        \
-       .store  = _store,                                       \
- };
-diff -Nurb linux-2.6.22-570/net/bridge/netfilter/ebt_ulog.c linux-2.6.22-590/net/bridge/netfilter/ebt_ulog.c
---- linux-2.6.22-570/net/bridge/netfilter/ebt_ulog.c   2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/bridge/netfilter/ebt_ulog.c   2008-01-02 13:56:38.000000000 -0500
-@@ -301,8 +301,9 @@
-               spin_lock_init(&ulog_buffers[i].lock);
-       }
++      mutex_lock(&manage_mutex);
+       cpuset_update_task_memory_state();
+       cs->flags = 0;
++      if (notify_on_release(parent))
++              set_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
+       if (is_spread_page(parent))
+               set_bit(CS_SPREAD_PAGE, &cs->flags);
+       if (is_spread_slab(parent))
+               set_bit(CS_SPREAD_SLAB, &cs->flags);
+       cs->cpus_allowed = CPU_MASK_NONE;
+       cs->mems_allowed = NODE_MASK_NONE;
++      atomic_set(&cs->count, 0);
++      INIT_LIST_HEAD(&cs->sibling);
++      INIT_LIST_HEAD(&cs->children);
+       cs->mems_generation = cpuset_mems_generation++;
+       fmeter_init(&cs->fmeter);
  
--      ebtulognl = netlink_kernel_create(NETLINK_NFLOG, EBT_ULOG_MAXNLGROUPS,
--                                        NULL, NULL, THIS_MODULE);
-+      ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG,
-+                                        EBT_ULOG_MAXNLGROUPS, NULL, NULL,
-+                                        THIS_MODULE);
-       if (!ebtulognl)
-               ret = -ENOMEM;
-       else if ((ret = ebt_register_watcher(&ulog)))
-diff -Nurb linux-2.6.22-570/net/bridge/netfilter/ebtable_filter.c linux-2.6.22-590/net/bridge/netfilter/ebtable_filter.c
---- linux-2.6.22-570/net/bridge/netfilter/ebtable_filter.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bridge/netfilter/ebtable_filter.c     2008-01-02 13:56:38.000000000 -0500
-@@ -64,6 +64,10 @@
- ebt_hook (unsigned int hook, struct sk_buff **pskb, const struct net_device *in,
-    const struct net_device *out, int (*okfn)(struct sk_buff *))
- {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
+       cs->parent = parent;
+-      set_container_cs(cont, cs);
+-      cs->css.container = cont;
 +
-       return ebt_do_table(hook, pskb, in, out, &frame_filter);
++      mutex_lock(&callback_mutex);
++      list_add(&cs->sibling, &cs->parent->children);
+       number_of_cpusets++;
++      mutex_unlock(&callback_mutex);
++
++      err = cpuset_create_dir(cs, name, mode);
++      if (err < 0)
++              goto err;
++
++      /*
++       * Release manage_mutex before cpuset_populate_dir() because it
++       * will down() this new directory's i_mutex and if we race with
++       * another mkdir, we might deadlock.
++       */
++      mutex_unlock(&manage_mutex);
++
++      err = cpuset_populate_dir(cs->dentry);
++      /* If err < 0, we have a half-filled directory - oh well ;) */
+       return 0;
++err:
++      list_del(&cs->sibling);
++      mutex_unlock(&manage_mutex);
++      kfree(cs);
++      return err;
++}
++
++static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++      struct cpuset *c_parent = dentry->d_parent->d_fsdata;
++
++      /* the vfs holds inode->i_mutex already */
++      return cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR);
  }
  
-diff -Nurb linux-2.6.22-570/net/bridge/netfilter/ebtable_nat.c linux-2.6.22-590/net/bridge/netfilter/ebtable_nat.c
---- linux-2.6.22-570/net/bridge/netfilter/ebtable_nat.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bridge/netfilter/ebtable_nat.c        2008-01-02 13:56:38.000000000 -0500
-@@ -64,6 +64,10 @@
- ebt_nat_dst(unsigned int hook, struct sk_buff **pskb, const struct net_device *in
-    , const struct net_device *out, int (*okfn)(struct sk_buff *))
+-void cpuset_destroy(struct container_subsys *ss, struct container *cont)
++/*
++ * Locking note on the strange update_flag() call below:
++ *
++ * If the cpuset being removed is marked cpu_exclusive, then simulate
++ * turning cpu_exclusive off, which will call update_cpu_domains().
++ * The lock_cpu_hotplug() call in update_cpu_domains() must not be
++ * made while holding callback_mutex.  Elsewhere the kernel nests
++ * callback_mutex inside lock_cpu_hotplug() calls.  So the reverse
++ * nesting would risk an ABBA deadlock.
++ */
++
++static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
  {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
+-      struct cpuset *cs = container_cs(cont);
++      struct cpuset *cs = dentry->d_fsdata;
++      struct dentry *d;
++      struct cpuset *parent;
++      char *pathbuf = NULL;
 +
-       return ebt_do_table(hook, pskb, in, out, &frame_nat);
++      /* the vfs holds both inode->i_mutex already */
++      mutex_lock(&manage_mutex);
+       cpuset_update_task_memory_state();
++      if (atomic_read(&cs->count) > 0) {
++              mutex_unlock(&manage_mutex);
++              return -EBUSY;
++      }
++      if (!list_empty(&cs->children)) {
++              mutex_unlock(&manage_mutex);
++              return -EBUSY;
++      }
++      if (is_cpu_exclusive(cs)) {
++              int retval = update_flag(CS_CPU_EXCLUSIVE, cs, "0");
++              if (retval < 0) {
++                      mutex_unlock(&manage_mutex);
++                      return retval;
++              }
++      }
++      parent = cs->parent;
++      mutex_lock(&callback_mutex);
++      set_bit(CS_REMOVED, &cs->flags);
++      list_del(&cs->sibling); /* delete my sibling from parent->children */
++      spin_lock(&cs->dentry->d_lock);
++      d = dget(cs->dentry);
++      cs->dentry = NULL;
++      spin_unlock(&d->d_lock);
++      cpuset_d_remove_dir(d);
++      dput(d);
+       number_of_cpusets--;
+-      kfree(cs);
++      mutex_unlock(&callback_mutex);
++      if (list_empty(&parent->children))
++              check_for_release(parent, &pathbuf);
++      mutex_unlock(&manage_mutex);
++      cpuset_release_agent(pathbuf);
++      return 0;
  }
  
-@@ -71,6 +75,10 @@
- ebt_nat_src(unsigned int hook, struct sk_buff **pskb, const struct net_device *in
-    , const struct net_device *out, int (*okfn)(struct sk_buff *))
+-struct container_subsys cpuset_subsys = {
+-      .name = "cpuset",
+-      .create = cpuset_create,
+-      .destroy  = cpuset_destroy,
+-      .can_attach = cpuset_can_attach,
+-      .attach = cpuset_attach,
+-      .populate = cpuset_populate,
+-      .post_clone = cpuset_post_clone,
+-      .subsys_id = cpuset_subsys_id,
+-      .early_init = 1,
+-};
+-
+ /*
+  * cpuset_init_early - just enough so that the calls to
+  * cpuset_update_task_memory_state() in early init code
+@@ -1298,11 +2011,13 @@
+ int __init cpuset_init_early(void)
  {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
+-      top_cpuset.mems_generation = cpuset_mems_generation++;
++      struct task_struct *tsk = current;
 +
-       return ebt_do_table(hook, pskb, in, out, &frame_nat);
++      tsk->cpuset = &top_cpuset;
++      tsk->cpuset->mems_generation = cpuset_mems_generation++;
+       return 0;
  }
  
-diff -Nurb linux-2.6.22-570/net/bridge/netfilter/ebtables.c linux-2.6.22-590/net/bridge/netfilter/ebtables.c
---- linux-2.6.22-570/net/bridge/netfilter/ebtables.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/bridge/netfilter/ebtables.c   2008-01-02 13:56:38.000000000 -0500
-@@ -28,6 +28,7 @@
- #include <linux/smp.h>
- #include <linux/cpumask.h>
- #include <net/sock.h>
-+#include <net/net_namespace.h>
- /* needed for logical [in,out]-dev filtering */
- #include "../br_private.h"
+-
+ /**
+  * cpuset_init - initialize cpusets at system boot
+  *
+@@ -1311,7 +2026,8 @@
  
-@@ -1438,6 +1439,9 @@
+ int __init cpuset_init(void)
  {
-       int ret;
+-      int err = 0;
++      struct dentry *root;
++      int err;
  
-+      if (sk->sk_net != &init_net)
-+              return -ENOPROTOOPT;
-+
-       switch(cmd) {
-       case EBT_SO_SET_ENTRIES:
-               ret = do_replace(user, len);
-@@ -1457,6 +1461,9 @@
-       struct ebt_replace tmp;
-       struct ebt_table *t;
+       top_cpuset.cpus_allowed = CPU_MASK_ALL;
+       top_cpuset.mems_allowed = NODE_MASK_ALL;
+@@ -1319,12 +2035,30 @@
+       fmeter_init(&top_cpuset.fmeter);
+       top_cpuset.mems_generation = cpuset_mems_generation++;
  
-+      if (sk->sk_net != &init_net)
-+              return -ENOPROTOOPT;
++      init_task.cpuset = &top_cpuset;
 +
-       if (copy_from_user(&tmp, user, sizeof(tmp)))
-               return -EFAULT;
+       err = register_filesystem(&cpuset_fs_type);
+       if (err < 0)
+-      return err;
+-
++              goto out;
++      cpuset_mount = kern_mount(&cpuset_fs_type);
++      if (IS_ERR(cpuset_mount)) {
++              printk(KERN_ERR "cpuset: could not mount!\n");
++              err = PTR_ERR(cpuset_mount);
++              cpuset_mount = NULL;
++              goto out;
++      }
++      root = cpuset_mount->mnt_sb->s_root;
++      root->d_fsdata = &top_cpuset;
++      inc_nlink(root->d_inode);
++      top_cpuset.dentry = root;
++      root->d_inode->i_op = &cpuset_dir_inode_operations;
+       number_of_cpusets = 1;
+-      return 0;
++      err = cpuset_populate_dir(root);
++      /* memory_pressure_enabled is in root cpuset only */
++      if (err == 0)
++              err = cpuset_add_file(root, &cft_memory_pressure_enabled);
++out:
++      return err;
+ }
  
-diff -Nurb linux-2.6.22-570/net/core/Makefile linux-2.6.22-590/net/core/Makefile
---- linux-2.6.22-570/net/core/Makefile 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/core/Makefile 2008-01-02 13:56:38.000000000 -0500
-@@ -3,7 +3,7 @@
- #
+ /*
+@@ -1350,12 +2084,10 @@
  
- obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
--       gen_stats.o gen_estimator.o
-+       gen_stats.o gen_estimator.o net_namespace.o
+ static void guarantee_online_cpus_mems_in_subtree(const struct cpuset *cur)
+ {
+-      struct container *cont;
+       struct cpuset *c;
  
- obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
+       /* Each of our child cpusets mems must be online */
+-      list_for_each_entry(cont, &cur->css.container->children, sibling) {
+-              c = container_cs(cont);
++      list_for_each_entry(c, &cur->children, sibling) {
+               guarantee_online_cpus_mems_in_subtree(c);
+               if (!cpus_empty(c->cpus_allowed))
+                       guarantee_online_cpus(c, &c->cpus_allowed);
+@@ -1382,7 +2114,7 @@
  
-diff -Nurb linux-2.6.22-570/net/core/dev.c linux-2.6.22-590/net/core/dev.c
---- linux-2.6.22-570/net/core/dev.c    2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/core/dev.c    2008-01-02 13:56:38.000000000 -0500
-@@ -116,6 +116,7 @@
- #include <linux/dmaengine.h>
- #include <linux/err.h>
- #include <linux/ctype.h>
-+#include <net/net_namespace.h>
- #include <linux/if_arp.h>
- #include <linux/vs_inet.h>
+ static void common_cpu_mem_hotplug_unplug(void)
+ {
+-      container_lock();
++      mutex_lock(&manage_mutex);
+       mutex_lock(&callback_mutex);
  
-@@ -152,9 +153,22 @@
- static struct list_head ptype_all __read_mostly;      /* Taps */
+       guarantee_online_cpus_mems_in_subtree(&top_cpuset);
+@@ -1390,7 +2122,7 @@
+       top_cpuset.mems_allowed = node_online_map;
  
- #ifdef CONFIG_NET_DMA
--static struct dma_client *net_dma_client;
--static unsigned int net_dma_count;
--static spinlock_t net_dma_event_lock;
-+struct net_dma {
-+      struct dma_client client;
-+      spinlock_t lock;
-+      cpumask_t channel_mask;
-+      struct dma_chan *channels[NR_CPUS];
-+};
-+
-+static enum dma_state_client
-+netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
-+      enum dma_state state);
-+
-+static struct net_dma net_dma = {
-+      .client = {
-+              .event_callback = netdev_dma_event,
-+      },
-+};
- #endif
+       mutex_unlock(&callback_mutex);
+-      container_unlock();
++      mutex_unlock(&manage_mutex);
+ }
  
  /*
-@@ -176,25 +190,50 @@
-  * unregister_netdevice(), which must be called with the rtnl
-  * semaphore held.
-  */
--LIST_HEAD(dev_base_head);
- DEFINE_RWLOCK(dev_base_lock);
--EXPORT_SYMBOL(dev_base_head);
- EXPORT_SYMBOL(dev_base_lock);
+@@ -1438,7 +2170,109 @@
+ }
  
- #define NETDEV_HASHBITS       8
--static struct hlist_head dev_name_head[1<<NETDEV_HASHBITS];
--static struct hlist_head dev_index_head[1<<NETDEV_HASHBITS];
-+#define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS)
+ /**
++ * cpuset_fork - attach newly forked task to its parents cpuset.
++ * @tsk: pointer to task_struct of forking parent process.
++ *
++ * Description: A task inherits its parent's cpuset at fork().
++ *
++ * A pointer to the shared cpuset was automatically copied in fork.c
++ * by dup_task_struct().  However, we ignore that copy, since it was
++ * not made under the protection of task_lock(), so might no longer be
++ * a valid cpuset pointer.  attach_task() might have already changed
++ * current->cpuset, allowing the previously referenced cpuset to
++ * be removed and freed.  Instead, we task_lock(current) and copy
++ * its present value of current->cpuset for our freshly forked child.
++ *
++ * At the point that cpuset_fork() is called, 'current' is the parent
++ * task, and the passed argument 'child' points to the child task.
++ **/
  
--static inline struct hlist_head *dev_name_hash(const char *name)
-+static inline struct hlist_head *dev_name_hash(struct net *net, const char *name)
- {
-       unsigned hash = full_name_hash(name, strnlen(name, IFNAMSIZ));
--      return &dev_name_head[hash & ((1<<NETDEV_HASHBITS)-1)];
-+      return &net->dev_name_head[hash & ((1 << NETDEV_HASHBITS) - 1)];
-+}
-+
-+static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)
++void cpuset_fork(struct task_struct *child)
 +{
-+      return &net->dev_index_head[ifindex & ((1 << NETDEV_HASHBITS) - 1)];
++      task_lock(current);
++      child->cpuset = current->cpuset;
++      atomic_inc(&child->cpuset->count);
++      task_unlock(current);
 +}
 +
-+/* Device list insertion */
-+static int list_netdevice(struct net_device *dev)
++/**
++ * cpuset_exit - detach cpuset from exiting task
++ * @tsk: pointer to task_struct of exiting process
++ *
++ * Description: Detach cpuset from @tsk and release it.
++ *
++ * Note that cpusets marked notify_on_release force every task in
++ * them to take the global manage_mutex mutex when exiting.
++ * This could impact scaling on very large systems.  Be reluctant to
++ * use notify_on_release cpusets where very high task exit scaling
++ * is required on large systems.
++ *
++ * Don't even think about derefencing 'cs' after the cpuset use count
++ * goes to zero, except inside a critical section guarded by manage_mutex
++ * or callback_mutex.   Otherwise a zero cpuset use count is a license to
++ * any other task to nuke the cpuset immediately, via cpuset_rmdir().
++ *
++ * This routine has to take manage_mutex, not callback_mutex, because
++ * it is holding that mutex while calling check_for_release(),
++ * which calls kmalloc(), so can't be called holding callback_mutex().
++ *
++ * the_top_cpuset_hack:
++ *
++ *    Set the exiting tasks cpuset to the root cpuset (top_cpuset).
++ *
++ *    Don't leave a task unable to allocate memory, as that is an
++ *    accident waiting to happen should someone add a callout in
++ *    do_exit() after the cpuset_exit() call that might allocate.
++ *    If a task tries to allocate memory with an invalid cpuset,
++ *    it will oops in cpuset_update_task_memory_state().
++ *
++ *    We call cpuset_exit() while the task is still competent to
++ *    handle notify_on_release(), then leave the task attached to
++ *    the root cpuset (top_cpuset) for the remainder of its exit.
++ *
++ *    To do this properly, we would increment the reference count on
++ *    top_cpuset, and near the very end of the kernel/exit.c do_exit()
++ *    code we would add a second cpuset function call, to drop that
++ *    reference.  This would just create an unnecessary hot spot on
++ *    the top_cpuset reference count, to no avail.
++ *
++ *    Normally, holding a reference to a cpuset without bumping its
++ *    count is unsafe.   The cpuset could go away, or someone could
++ *    attach us to a different cpuset, decrementing the count on
++ *    the first cpuset that we never incremented.  But in this case,
++ *    top_cpuset isn't going away, and either task has PF_EXITING set,
++ *    which wards off any attach_task() attempts, or task is a failed
++ *    fork, never visible to attach_task.
++ *
++ *    Another way to do this would be to set the cpuset pointer
++ *    to NULL here, and check in cpuset_update_task_memory_state()
++ *    for a NULL pointer.  This hack avoids that NULL check, for no
++ *    cost (other than this way too long comment ;).
++ **/
++
++void cpuset_exit(struct task_struct *tsk)
 +{
-+      struct net *net = dev->nd_net;
++      struct cpuset *cs;
 +
-+      ASSERT_RTNL();
++      task_lock(current);
++      cs = tsk->cpuset;
++      tsk->cpuset = &top_cpuset;      /* the_top_cpuset_hack - see above */
++      task_unlock(current);
 +
-+      write_lock_bh(&dev_base_lock);
-+      list_add_tail(&dev->dev_list, &net->dev_base_head);
-+      hlist_add_head(&dev->name_hlist, dev_name_hash(net, dev->name));
-+      hlist_add_head(&dev->index_hlist, dev_index_hash(net, dev->ifindex));
-+      write_unlock_bh(&dev_base_lock);
-+      return 0;
- }
--static inline struct hlist_head *dev_index_hash(int ifindex)
-+/* Device list removal */
-+static void unlist_netdevice(struct net_device *dev)
- {
--      return &dev_index_head[ifindex & ((1<<NETDEV_HASHBITS)-1)];
-+      ASSERT_RTNL();
++      if (notify_on_release(cs)) {
++              char *pathbuf = NULL;
 +
-+      /* Unlink dev from the device chain */
-+      write_lock_bh(&dev_base_lock);
-+      list_del(&dev->dev_list);
-+      hlist_del(&dev->name_hlist);
-+      hlist_del(&dev->index_hlist);
-+      write_unlock_bh(&dev_base_lock);
- }
- /*
-@@ -477,7 +516,7 @@
-        * If device already registered then return base of 1
-        * to indicate not to probe for this interface
-        */
--      if (__dev_get_by_name(name))
-+      if (__dev_get_by_name(&init_net, name))
-               return 1;
-       for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++)
-@@ -532,11 +571,11 @@
-  *    careful with locks.
-  */
++              mutex_lock(&manage_mutex);
++              if (atomic_dec_and_test(&cs->count))
++                      check_for_release(cs, &pathbuf);
++              mutex_unlock(&manage_mutex);
++              cpuset_release_agent(pathbuf);
++      } else {
++              atomic_dec(&cs->count);
++      }
++}
++
++/**
+  * cpuset_cpus_allowed - return cpus_allowed mask from a tasks cpuset.
+  * @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed.
+  *
+@@ -1454,7 +2288,7 @@
  
--struct net_device *__dev_get_by_name(const char *name)
-+struct net_device *__dev_get_by_name(struct net *net, const char *name)
- {
-       struct hlist_node *p;
+       mutex_lock(&callback_mutex);
+       task_lock(tsk);
+-      guarantee_online_cpus(task_cs(tsk), &mask);
++      guarantee_online_cpus(tsk->cpuset, &mask);
+       task_unlock(tsk);
+       mutex_unlock(&callback_mutex);
  
--      hlist_for_each(p, dev_name_hash(name)) {
-+      hlist_for_each(p, dev_name_hash(net, name)) {
-               struct net_device *dev
-                       = hlist_entry(p, struct net_device, name_hlist);
-               if (!strncmp(dev->name, name, IFNAMSIZ))
-@@ -556,12 +595,12 @@
-  *    matching device is found.
-  */
+@@ -1482,7 +2316,7 @@
  
--struct net_device *dev_get_by_name(const char *name)
-+struct net_device *dev_get_by_name(struct net *net, const char *name)
- {
-       struct net_device *dev;
+       mutex_lock(&callback_mutex);
+       task_lock(tsk);
+-      guarantee_online_mems(task_cs(tsk), &mask);
++      guarantee_online_mems(tsk->cpuset, &mask);
+       task_unlock(tsk);
+       mutex_unlock(&callback_mutex);
  
-       read_lock(&dev_base_lock);
--      dev = __dev_get_by_name(name);
-+      dev = __dev_get_by_name(net, name);
-       if (dev)
-               dev_hold(dev);
-       read_unlock(&dev_base_lock);
-@@ -579,11 +618,11 @@
-  *    or @dev_base_lock.
-  */
+@@ -1613,7 +2447,7 @@
+       mutex_lock(&callback_mutex);
  
--struct net_device *__dev_get_by_index(int ifindex)
-+struct net_device *__dev_get_by_index(struct net *net, int ifindex)
- {
-       struct hlist_node *p;
+       task_lock(current);
+-      cs = nearest_exclusive_ancestor(task_cs(current));
++      cs = nearest_exclusive_ancestor(current->cpuset);
+       task_unlock(current);
  
--      hlist_for_each(p, dev_index_hash(ifindex)) {
-+      hlist_for_each(p, dev_index_hash(net, ifindex)) {
-               struct net_device *dev
-                       = hlist_entry(p, struct net_device, index_hlist);
-               if (dev->ifindex == ifindex)
-@@ -603,12 +642,12 @@
-  *    dev_put to indicate they have finished with it.
-  */
+       allowed = node_isset(node, cs->mems_allowed);
+@@ -1750,7 +2584,7 @@
+               task_unlock(current);
+               goto done;
+       }
+-      cs1 = nearest_exclusive_ancestor(task_cs(current));
++      cs1 = nearest_exclusive_ancestor(current->cpuset);
+       task_unlock(current);
  
--struct net_device *dev_get_by_index(int ifindex)
-+struct net_device *dev_get_by_index(struct net *net, int ifindex)
- {
-       struct net_device *dev;
+       task_lock((struct task_struct *)p);
+@@ -1758,7 +2592,7 @@
+               task_unlock((struct task_struct *)p);
+               goto done;
+       }
+-      cs2 = nearest_exclusive_ancestor(task_cs((struct task_struct *)p));
++      cs2 = nearest_exclusive_ancestor(p->cpuset);
+       task_unlock((struct task_struct *)p);
  
-       read_lock(&dev_base_lock);
--      dev = __dev_get_by_index(ifindex);
-+      dev = __dev_get_by_index(net, ifindex);
-       if (dev)
-               dev_hold(dev);
-       read_unlock(&dev_base_lock);
-@@ -629,13 +668,13 @@
-  *    If the API was consistent this would be __dev_get_by_hwaddr
-  */
+       overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed);
+@@ -1794,12 +2628,14 @@
  
--struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
-+struct net_device *dev_getbyhwaddr(struct net *net, unsigned short type, char *ha)
+ void __cpuset_memory_pressure_bump(void)
  {
-       struct net_device *dev;
-       ASSERT_RTNL();
--      for_each_netdev(dev)
-+      for_each_netdev(&init_net, dev)
-               if (dev->type == type &&
-                   !memcmp(dev->dev_addr, ha, dev->addr_len))
-                       return dev;
-@@ -645,12 +684,12 @@
++      struct cpuset *cs;
++
+       task_lock(current);
+-      fmeter_markevent(&task_cs(current)->fmeter);
++      cs = current->cpuset;
++      fmeter_markevent(&cs->fmeter);
+       task_unlock(current);
+ }
  
- EXPORT_SYMBOL(dev_getbyhwaddr);
+-#ifdef CONFIG_PROC_PID_CPUSET
+ /*
+  * proc_cpuset_show()
+  *  - Print tasks cpuset path into seq_file.
+@@ -1816,7 +2652,6 @@
+       struct pid *pid;
+       struct task_struct *tsk;
+       char *buf;
+-      struct container_subsys_state *css;
+       int retval;
  
--struct net_device *__dev_getfirstbyhwtype(unsigned short type)
-+struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short type)
- {
-       struct net_device *dev;
+       retval = -ENOMEM;
+@@ -1831,15 +2666,15 @@
+               goto out_free;
  
-       ASSERT_RTNL();
--      for_each_netdev(dev)
-+      for_each_netdev(net, dev)
-               if (dev->type == type)
-                       return dev;
+       retval = -EINVAL;
+-      container_lock();
+-      css = task_subsys_state(tsk, cpuset_subsys_id);
+-      retval = container_path(css->container, buf, PAGE_SIZE);
++      mutex_lock(&manage_mutex);
++
++      retval = cpuset_path(tsk->cpuset, buf, PAGE_SIZE);
+       if (retval < 0)
+               goto out_unlock;
+       seq_puts(m, buf);
+       seq_putc(m, '\n');
+ out_unlock:
+-      container_unlock();
++      mutex_unlock(&manage_mutex);
+       put_task_struct(tsk);
+ out_free:
+       kfree(buf);
+@@ -1859,7 +2694,6 @@
+       .llseek         = seq_lseek,
+       .release        = single_release,
+ };
+-#endif /* CONFIG_PROC_PID_CPUSET */
  
-@@ -659,12 +698,12 @@
+ /* Display task cpus_allowed, mems_allowed in /proc/<pid>/status file. */
+ char *cpuset_task_status_allowed(struct task_struct *task, char *buffer)
+diff -Nurb linux-2.6.22-590/kernel/exit.c linux-2.6.22-570/kernel/exit.c
+--- linux-2.6.22-590/kernel/exit.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/exit.c     2008-01-23 19:16:05.000000000 -0500
+@@ -31,8 +31,7 @@
+ #include <linux/mempolicy.h>
+ #include <linux/taskstats_kern.h>
+ #include <linux/delayacct.h>
+-#include <linux/freezer.h>
+-#include <linux/container.h>
++#include <linux/cpuset.h>
+ #include <linux/syscalls.h>
+ #include <linux/signal.h>
+ #include <linux/posix-timers.h>
+@@ -394,11 +393,6 @@
+        * they would be locked into memory.
+        */
+       exit_mm(current);
+-      /*
+-       * We don't want to have TIF_FREEZE set if the system-wide hibernation
+-       * or suspend transition begins right now.
+-       */
+-      current->flags |= PF_NOFREEZE;
  
- EXPORT_SYMBOL(__dev_getfirstbyhwtype);
+       set_special_pids(1, 1);
+       proc_clear_tty(current);
+@@ -881,34 +875,6 @@
+               release_task(tsk);
+ }
  
--struct net_device *dev_getfirstbyhwtype(unsigned short type)
-+struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type)
+-#ifdef CONFIG_DEBUG_STACK_USAGE
+-static void check_stack_usage(void)
+-{
+-      static DEFINE_SPINLOCK(low_water_lock);
+-      static int lowest_to_date = THREAD_SIZE;
+-      unsigned long *n = end_of_stack(current);
+-      unsigned long free;
+-
+-      while (*n == 0)
+-              n++;
+-      free = (unsigned long)n - (unsigned long)end_of_stack(current);
+-
+-      if (free >= lowest_to_date)
+-              return;
+-
+-      spin_lock(&low_water_lock);
+-      if (free < lowest_to_date) {
+-              printk(KERN_WARNING "%s used greatest stack depth: %lu bytes "
+-                              "left\n",
+-                              current->comm, free);
+-              lowest_to_date = free;
+-      }
+-      spin_unlock(&low_water_lock);
+-}
+-#else
+-static inline void check_stack_usage(void) {}
+-#endif
+-
+ fastcall NORET_TYPE void do_exit(long code)
  {
-       struct net_device *dev;
+       struct task_struct *tsk = current;
+@@ -1000,9 +966,8 @@
+       exit_sem(tsk);
+       __exit_files(tsk);
+       __exit_fs(tsk);
+-      check_stack_usage();
+       exit_thread();
+-      container_exit(tsk, 1);
++      cpuset_exit(tsk);
+       exit_keys(tsk);
  
-       rtnl_lock();
--      dev = __dev_getfirstbyhwtype(type);
-+      dev = __dev_getfirstbyhwtype(net, type);
-       if (dev)
-               dev_hold(dev);
-       rtnl_unlock();
-@@ -684,13 +723,13 @@
-  *    dev_put to indicate they have finished with it.
-  */
+       if (group_dead && tsk->signal->leader)
+diff -Nurb linux-2.6.22-590/kernel/fork.c linux-2.6.22-570/kernel/fork.c
+--- linux-2.6.22-590/kernel/fork.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/fork.c     2008-01-23 19:16:05.000000000 -0500
+@@ -29,7 +29,7 @@
+ #include <linux/nsproxy.h>
+ #include <linux/capability.h>
+ #include <linux/cpu.h>
+-#include <linux/container.h>
++#include <linux/cpuset.h>
+ #include <linux/security.h>
+ #include <linux/swap.h>
+ #include <linux/syscalls.h>
+@@ -342,8 +342,6 @@
+       atomic_set(&mm->mm_count, 1);
+       init_rwsem(&mm->mmap_sem);
+       INIT_LIST_HEAD(&mm->mmlist);
+-      mm->flags = (current->mm) ? current->mm->flags
+-                                : MMF_DUMP_FILTER_DEFAULT;
+       mm->core_waiters = 0;
+       mm->nr_ptes = 0;
+       __set_mm_counter(mm, file_rss, 0);
+@@ -938,7 +936,7 @@
+ {
+       unsigned long new_flags = p->flags;
  
--struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mask)
-+struct net_device * dev_get_by_flags(struct net *net, unsigned short if_flags, unsigned short mask)
+-      new_flags &= ~PF_SUPERPRIV;
++      new_flags &= ~(PF_SUPERPRIV | PF_NOFREEZE);
+       new_flags |= PF_FORKNOEXEC;
+       if (!(clone_flags & CLONE_PTRACE))
+               p->ptrace = 0;
+@@ -979,7 +977,6 @@
  {
-       struct net_device *dev, *ret;
+       int retval;
+       struct task_struct *p = NULL;
+-      int container_callbacks_done = 0;
+       struct vx_info *vxi;
+       struct nx_info *nxi;
  
-       ret = NULL;
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(net, dev) {
-               if (((dev->flags ^ if_flags) & mask) == 0) {
-                       dev_hold(dev);
-                       ret = dev;
-@@ -727,9 +766,10 @@
- }
+@@ -1064,6 +1061,11 @@
+       delayacct_tsk_init(p);  /* Must remain after dup_task_struct() */
+       copy_flags(clone_flags, p);
+       p->pid = pid_nr(pid);
++      retval = -EFAULT;
++      if (clone_flags & CLONE_PARENT_SETTID)
++              if (put_user(p->pid, parent_tidptr))
++                      goto bad_fork_cleanup_delays_binfmt;
++
+       INIT_LIST_HEAD(&p->children);
+       INIT_LIST_HEAD(&p->sibling);
+       p->vfork_done = NULL;
+@@ -1093,19 +1095,17 @@
  
- /**
-- *    dev_alloc_name - allocate a name for a device
-- *    @dev: device
-+ *    __dev_alloc_name - allocate a name for a device
-+ *    @net: network namespace to allocate the device name in
-  *    @name: name format string
-+ *    @buf:  scratch buffer and result name string
-  *
-  *    Passed a format string - eg "lt%d" it will try and find a suitable
-  *    id. It scans list of devices to build up a free map, then chooses
-@@ -740,10 +780,9 @@
-  *    Returns the number of the unit assigned or a negative errno code.
-  */
+       p->lock_depth = -1;             /* -1 = no lock */
+       do_posix_clock_monotonic_gettime(&p->start_time);
+-      p->real_start_time = p->start_time;
+-      monotonic_to_bootbased(&p->real_start_time);
+       p->security = NULL;
+       p->io_context = NULL;
+       p->io_wait = NULL;
+       p->audit_context = NULL;
+-      container_fork(p);
++      cpuset_fork(p);
+ #ifdef CONFIG_NUMA
+       p->mempolicy = mpol_copy(p->mempolicy);
+       if (IS_ERR(p->mempolicy)) {
+               retval = PTR_ERR(p->mempolicy);
+               p->mempolicy = NULL;
+-              goto bad_fork_cleanup_container;
++              goto bad_fork_cleanup_cpuset;
+       }
+       mpol_fix_fork_child_flag(p);
+ #endif
+@@ -1215,12 +1215,6 @@
+       /* Perform scheduler related setup. Assign this task to a CPU. */
+       sched_fork(p, clone_flags);
  
--int dev_alloc_name(struct net_device *dev, const char *name)
-+static int __dev_alloc_name(struct net *net, const char *name, char *buf)
- {
-       int i = 0;
--      char buf[IFNAMSIZ];
-       const char *p;
-       const int max_netdevices = 8*PAGE_SIZE;
-       long *inuse;
-@@ -764,14 +803,14 @@
-               if (!inuse)
-                       return -ENOMEM;
+-      /* Now that the task is set up, run container callbacks if
+-       * necessary. We need to run them before the task is visible
+-       * on the tasklist. */
+-      container_fork_callbacks(p);
+-      container_callbacks_done = 1;
+-
+       /* Need tasklist lock for parent etc handling! */
+       write_lock_irq(&tasklist_lock);
  
--              for_each_netdev(d) {
-+              for_each_netdev(net, d) {
-                       if (!sscanf(d->name, name, &i))
-                               continue;
-                       if (i < 0 || i >= max_netdevices)
-                               continue;
+@@ -1320,14 +1314,6 @@
+       if (nxi)
+               claim_nx_info(nxi, p);
+       write_unlock_irq(&tasklist_lock);
+-
+-      /*
+-       * Now that we know the fork has succeeded, record the new
+-       * TID.  It's too late to back out if this fails.
+-       */
+-      if (clone_flags & CLONE_PARENT_SETTID)
+-              put_user(p->pid, parent_tidptr);
+-
+       proc_fork_connector(p);
+       return p;
  
-                       /*  avoid cases where sscanf is not exact inverse of printf */
--                      snprintf(buf, sizeof(buf), name, i);
-+                      snprintf(buf, IFNAMSIZ, name, i);
-                       if (!strncmp(buf, d->name, IFNAMSIZ))
-                               set_bit(i, inuse);
-               }
-@@ -780,11 +819,9 @@
-               free_page((unsigned long) inuse);
-       }
+@@ -1355,9 +1341,10 @@
+ bad_fork_cleanup_policy:
+ #ifdef CONFIG_NUMA
+       mpol_free(p->mempolicy);
+-bad_fork_cleanup_container:
++bad_fork_cleanup_cpuset:
+ #endif
+-      container_exit(p, container_callbacks_done);
++      cpuset_exit(p);
++bad_fork_cleanup_delays_binfmt:
+       delayacct_tsk_free(p);
+       if (p->binfmt)
+               module_put(p->binfmt->module);
+@@ -1674,7 +1661,7 @@
+       err = -EINVAL;
+       if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
+                               CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
+-                              CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWUSER))
++                              CLONE_NEWUTS|CLONE_NEWIPC))
+               goto bad_unshare_out;
  
--      snprintf(buf, sizeof(buf), name, i);
--      if (!__dev_get_by_name(buf)) {
--              strlcpy(dev->name, buf, IFNAMSIZ);
-+      snprintf(buf, IFNAMSIZ, name, i);
-+      if (!__dev_get_by_name(net, buf))
-               return i;
+       if ((err = unshare_thread(unshare_flags)))
+diff -Nurb linux-2.6.22-590/kernel/kgdb.c linux-2.6.22-570/kernel/kgdb.c
+--- linux-2.6.22-590/kernel/kgdb.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/kgdb.c     1969-12-31 19:00:00.000000000 -0500
+@@ -1,1866 +0,0 @@
+-/*
+- * kernel/kgdb.c
+- *
+- * Maintainer: Jason Wessel <jason.wessel@windriver.com>
+- *
+- * Copyright (C) 2000-2001 VERITAS Software Corporation.
+- * Copyright (C) 2002-2004 Timesys Corporation
+- * Copyright (C) 2003-2004 Amit S. Kale <amitkale@linsyssoft.com>
+- * Copyright (C) 2004 Pavel Machek <pavel@suse.cz>
+- * Copyright (C) 2004-2006 Tom Rini <trini@kernel.crashing.org>
+- * Copyright (C) 2004-2006 LinSysSoft Technologies Pvt. Ltd.
+- * Copyright (C) 2005-2007 Wind River Systems, Inc.
+- *
+- * Contributors at various stages not listed above:
+- *  Jason Wessel ( jason.wessel@windriver.com )
+- *  George Anzinger <george@mvista.com>
+- *  Anurekh Saxena (anurekh.saxena@timesys.com)
+- *  Lake Stevens Instrument Division (Glenn Engel)
+- *  Jim Kingdon, Cygnus Support.
+- *
+- * Original KGDB stub: David Grothe <dave@gcom.com>,
+- * Tigran Aivazian <tigran@sco.com>
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program is licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
+-
+-#include <linux/string.h>
+-#include <linux/kernel.h>
+-#include <linux/interrupt.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/spinlock.h>
+-#include <linux/delay.h>
+-#include <linux/mm.h>
+-#include <linux/threads.h>
+-#include <linux/reboot.h>
+-#include <asm/system.h>
+-#include <asm/ptrace.h>
+-#include <asm/uaccess.h>
+-#include <linux/kgdb.h>
+-#include <asm/atomic.h>
+-#include <linux/notifier.h>
+-#include <linux/module.h>
+-#include <asm/cacheflush.h>
+-#include <linux/init.h>
+-#include <linux/sysrq.h>
+-#include <linux/console.h>
+-#include <linux/sched.h>
+-#include <linux/pid_namespace.h>
+-#include <asm/byteorder.h>
+-
+-extern int pid_max;
+-/* How many times to count all of the waiting CPUs */
+-#define ROUNDUP_WAIT          640000  /* Arbitrary, increase if needed. */
+-#define BUF_THREAD_ID_SIZE    16
+-
+-/*
+- * kgdb_initialized with a value of 1 indicates that kgdb is setup and is
+- * all ready to serve breakpoints and other kernel exceptions.  A value of
+- * -1 indicates that we have tried to initialize early, and need to try
+- * again later.
+- */
+-int kgdb_initialized;
+-/* Is a host GDB connected to us? */
+-int kgdb_connected;
+-/* Could we be about to try and access a bad memory location? If so we
+- * also need to flag this has happend. */
+-int kgdb_may_fault;
+-#ifdef CONFIG_PREEMPT
+-static int kgdb_fault_preempt_count;
+-#endif
+-
+-/* All the KGDB handlers are installed */
+-int kgdb_from_module_registered = 0;
+-/* Guard for recursive entry */
+-static int exception_level = 0;
+-
+-/* We provide a kgdb_io_ops structure that may be overriden. */
+-struct kgdb_io __attribute__ ((weak)) kgdb_io_ops;
+-
+-static struct kgdb_io kgdb_io_ops_prev[MAX_KGDB_IO_HANDLERS];
+-static int kgdb_io_handler_cnt = 0;
+-
+-/* Export the following symbols for use with kernel modules */
+-EXPORT_SYMBOL(kgdb_io_ops);
+-EXPORT_SYMBOL(kgdb_tasklet_breakpoint);
+-EXPORT_SYMBOL(kgdb_connected);
+-EXPORT_SYMBOL(kgdb_register_io_module);
+-EXPORT_SYMBOL(kgdb_unregister_io_module);
+-EXPORT_SYMBOL(debugger_active);
+-
+-/*
+- * Holds information about breakpoints in a kernel. These breakpoints are
+- * added and removed by gdb.
+- */
+-struct kgdb_bkpt kgdb_break[MAX_BREAKPOINTS];
+-
+-struct kgdb_arch *kgdb_ops = &arch_kgdb_ops;
+-
+-static const char hexchars[] = "0123456789abcdef";
+-
+-static spinlock_t slavecpulocks[NR_CPUS];
+-static atomic_t procindebug[NR_CPUS];
+-atomic_t kgdb_setting_breakpoint;
+-EXPORT_SYMBOL(kgdb_setting_breakpoint);
+-struct task_struct *kgdb_usethread, *kgdb_contthread;
+-
+-int debugger_step;
+-atomic_t debugger_active;
+-
+-/* Our I/O buffers. */
+-static char remcom_in_buffer[BUFMAX];
+-static char remcom_out_buffer[BUFMAX];
+-/* Storage for the registers, in GDB format. */
+-static unsigned long gdb_regs[(NUMREGBYTES + sizeof(unsigned long) - 1) /
+-                            sizeof(unsigned long)];
+-/* Storage of registers for handling a fault. */
+-unsigned long kgdb_fault_jmp_regs[NUMCRITREGBYTES / sizeof(unsigned long)]
+- JMP_REGS_ALIGNMENT;
+-static int kgdb_notify_reboot(struct notifier_block *this,
+-                              unsigned long code ,void *x);
+-struct debuggerinfo_struct {
+-      void *debuggerinfo;
+-      struct task_struct *task;
+-} kgdb_info[NR_CPUS];
+-
+-/* to keep track of the CPU which is doing the single stepping*/
+-atomic_t cpu_doing_single_step = ATOMIC_INIT(-1);
+-
+-atomic_t  kgdb_sync_softlockup[NR_CPUS] = {ATOMIC_INIT(0)};
+-
+-/* reboot notifier block */
+-static struct notifier_block kgdb_reboot_notifier = {
+-      .notifier_call  = kgdb_notify_reboot,
+-      .next           = NULL,
+-      .priority       = INT_MAX,
+-};
+-
+-int __attribute__ ((weak))
+-     kgdb_validate_break_address(unsigned long addr)
+-{
+-      int error = 0;
+-      char tmp_variable[BREAK_INSTR_SIZE];
+-      error = kgdb_get_mem((char *)addr, tmp_variable, BREAK_INSTR_SIZE);
+-      return error;
+-}
+-
+-int __attribute__ ((weak))
+-     kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
+-{
+-      int error = 0;
+-      if ((error = kgdb_get_mem((char *)addr,
+-              saved_instr, BREAK_INSTR_SIZE)) < 0)
+-                      return error;
+-
+-      if ((error = kgdb_set_mem((char *)addr, kgdb_ops->gdb_bpt_instr,
+-              BREAK_INSTR_SIZE)) < 0)
+-                      return error;
+-      return 0;
+-}
+-
+-int __attribute__ ((weak))
+-     kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
+-{
+-
+-      int error = 0;
+-      if ((error =kgdb_set_mem((char *)addr, (char *)bundle,
+-              BREAK_INSTR_SIZE)) < 0)
+-                      return error;
+-      return 0;
+-}
+-
+-unsigned long __attribute__ ((weak))
+-    kgdb_arch_pc(int exception, struct pt_regs *regs)
+-{
+-      return instruction_pointer(regs);
+-}
+-
+-static int hex(char ch)
+-{
+-      if ((ch >= 'a') && (ch <= 'f'))
+-              return (ch - 'a' + 10);
+-      if ((ch >= '0') && (ch <= '9'))
+-              return (ch - '0');
+-      if ((ch >= 'A') && (ch <= 'F'))
+-              return (ch - 'A' + 10);
+-      return (-1);
+-}
+-
+-/* scan for the sequence $<data>#<checksum>   */
+-static void get_packet(char *buffer)
+-{
+-      unsigned char checksum;
+-      unsigned char xmitcsum;
+-      int count;
+-      char ch;
+-      if (!kgdb_io_ops.read_char)
+-              return;
+-      do {
+-              /* Spin and wait around for the start character, ignore all
+-               * other characters */
+-              while ((ch = (kgdb_io_ops.read_char())) != '$') ;
+-              kgdb_connected = 1;
+-              checksum = 0;
+-              xmitcsum = -1;
+-
+-              count = 0;
+-
+-              /* now, read until a # or end of buffer is found */
+-              while (count < (BUFMAX - 1)) {
+-                      ch = kgdb_io_ops.read_char();
+-                      if (ch == '#')
+-                              break;
+-                      checksum = checksum + ch;
+-                      buffer[count] = ch;
+-                      count = count + 1;
+-              }
+-              buffer[count] = 0;
+-
+-              if (ch == '#') {
+-                      xmitcsum = hex(kgdb_io_ops.read_char()) << 4;
+-                      xmitcsum += hex(kgdb_io_ops.read_char());
+-
+-                      if (checksum != xmitcsum)
+-                              /* failed checksum */
+-                              kgdb_io_ops.write_char('-');
+-                      else
+-                              /* successful transfer */
+-                              kgdb_io_ops.write_char('+');
+-                      if (kgdb_io_ops.flush)
+-                              kgdb_io_ops.flush();
+-              }
+-      } while (checksum != xmitcsum);
+-}
+-
+-static void kgdb_set_may_fault(void) {
+-      kgdb_may_fault = 1;
+-#ifdef CONFIG_PREEMPT
+-      kgdb_fault_preempt_count = preempt_count();
+-#endif
+-}
+-
+-static void kgdb_unset_may_fault(void) {
+-      kgdb_may_fault = 0;
+-#ifdef CONFIG_PREEMPT
+-      preempt_count() = kgdb_fault_preempt_count;
+-#endif
+-}
+-
+-/*
+- * Send the packet in buffer.
+- * Check for gdb connection if asked for.
+- */
+-static void put_packet(char *buffer)
+-{
+-      unsigned char checksum;
+-      int count;
+-      char ch;
+-
+-      if (!kgdb_io_ops.write_char)
+-              return;
+-      /* $<packet info>#<checksum>. */
+-      while (1) {
+-              kgdb_io_ops.write_char('$');
+-              checksum = 0;
+-              count = 0;
+-
+-              while ((ch = buffer[count])) {
+-                      kgdb_io_ops.write_char(ch);
+-                      checksum += ch;
+-                      count++;
+-              }
+-
+-              kgdb_io_ops.write_char('#');
+-              kgdb_io_ops.write_char(hexchars[checksum >> 4]);
+-              kgdb_io_ops.write_char(hexchars[checksum % 16]);
+-              if (kgdb_io_ops.flush)
+-                      kgdb_io_ops.flush();
+-
+-              /* Now see what we get in reply. */
+-              ch = kgdb_io_ops.read_char();
+-
+-              if (ch == 3)
+-                      ch = kgdb_io_ops.read_char();
+-
+-              /* If we get an ACK, we are done. */
+-              if (ch == '+')
+-                      return;
+-
+-              /* If we get the start of another packet, this means
+-               * that GDB is attempting to reconnect.  We will NAK
+-               * the packet being sent, and stop trying to send this
+-               * packet. */
+-              if (ch == '$') {
+-                      kgdb_io_ops.write_char('-');
+-                      if (kgdb_io_ops.flush)
+-                              kgdb_io_ops.flush();
+-                      return;
+-              }
+-      }
+-}
+-
+-/*
+- * convert the memory pointed to by mem into hex, placing result in buf
+- * return a pointer to the last char put in buf (null). May return an error.
+- */
+-char *kgdb_mem2hex(char *mem, char *buf, int count)
+-{
+-      kgdb_set_may_fault();
+-      if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
+-              kgdb_unset_may_fault();
+-              return ERR_PTR(-EINVAL);
+-      }
+-      /* Accessing some registers in a single load instruction is
+-       * required to avoid bad side effects for some I/O registers.
+-       */
+-      if ((count == 2) && (((long)mem & 1) == 0)) {
+-              unsigned short tmp_s = *(unsigned short *)mem;
+-              mem += 2;
+-#ifdef __BIG_ENDIAN
+-              *buf++ = hexchars[(tmp_s >> 12) & 0xf];
+-              *buf++ = hexchars[(tmp_s >> 8) & 0xf];
+-              *buf++ = hexchars[(tmp_s >> 4) & 0xf];
+-              *buf++ = hexchars[tmp_s & 0xf];
+-#else
+-              *buf++ = hexchars[(tmp_s >> 4) & 0xf];
+-              *buf++ = hexchars[tmp_s & 0xf];
+-              *buf++ = hexchars[(tmp_s >> 12) & 0xf];
+-              *buf++ = hexchars[(tmp_s >> 8) & 0xf];
+-#endif
+-      } else if ((count == 4) && (((long)mem & 3) == 0)) {
+-              unsigned long tmp_l = *(unsigned int *)mem;
+-              mem += 4;
+-#ifdef __BIG_ENDIAN
+-              *buf++ = hexchars[(tmp_l >> 28) & 0xf];
+-              *buf++ = hexchars[(tmp_l >> 24) & 0xf];
+-              *buf++ = hexchars[(tmp_l >> 20) & 0xf];
+-              *buf++ = hexchars[(tmp_l >> 16) & 0xf];
+-              *buf++ = hexchars[(tmp_l >> 12) & 0xf];
+-              *buf++ = hexchars[(tmp_l >> 8) & 0xf];
+-              *buf++ = hexchars[(tmp_l >> 4) & 0xf];
+-              *buf++ = hexchars[tmp_l & 0xf];
+-#else
+-              *buf++ = hexchars[(tmp_l >> 4) & 0xf];
+-              *buf++ = hexchars[tmp_l & 0xf];
+-              *buf++ = hexchars[(tmp_l >> 12) & 0xf];
+-              *buf++ = hexchars[(tmp_l >> 8) & 0xf];
+-              *buf++ = hexchars[(tmp_l >> 20) & 0xf];
+-              *buf++ = hexchars[(tmp_l >> 16) & 0xf];
+-              *buf++ = hexchars[(tmp_l >> 28) & 0xf];
+-              *buf++ = hexchars[(tmp_l >> 24) & 0xf];
+-#endif
+-#ifdef CONFIG_64BIT
+-      } else if ((count == 8) && (((long)mem & 7) == 0)) {
+-              unsigned long long tmp_ll = *(unsigned long long *)mem;
+-              mem += 8;
+-#ifdef __BIG_ENDIAN
+-              *buf++ = hexchars[(tmp_ll >> 60) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 56) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 52) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 48) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 44) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 40) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 36) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 32) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 28) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 24) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 20) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 16) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 12) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 8) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 4) & 0xf];
+-              *buf++ = hexchars[tmp_ll & 0xf];
+-#else
+-              *buf++ = hexchars[(tmp_ll >> 4) & 0xf];
+-              *buf++ = hexchars[tmp_ll & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 12) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 8) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 20) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 16) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 28) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 24) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 36) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 32) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 44) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 40) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 52) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 48) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 60) & 0xf];
+-              *buf++ = hexchars[(tmp_ll >> 56) & 0xf];
+-#endif
+-#endif
+-      } else {
+-              while (count-- > 0) {
+-                      unsigned char ch = *mem++;
+-                      *buf++ = hexchars[ch >> 4];
+-                      *buf++ = hexchars[ch & 0xf];
+-              }
+-      }
+-      kgdb_unset_may_fault();
+-      *buf = 0;
+-      return (buf);
+-}
+-
+-/*
+- * Copy the binary array pointed to by buf into mem.  Fix $, #, and
+- * 0x7d escaped with 0x7d.  Return a pointer to the character after
+- * the last byte written.
+- */
+-static char *kgdb_ebin2mem(char *buf, char *mem, int count)
+-{
+-      kgdb_set_may_fault();
+-      if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
+-              kgdb_unset_may_fault();
+-              return ERR_PTR(-EINVAL);
+-      }
+-      for (; count > 0; count--, buf++) {
+-              if (*buf == 0x7d)
+-                      *mem++ = *(++buf) ^ 0x20;
+-              else
+-                      *mem++ = *buf;
+-      }
+-      kgdb_unset_may_fault();
+-      return mem;
+-}
+-
+-/*
+- * convert the hex array pointed to by buf into binary to be placed in mem
+- * return a pointer to the character AFTER the last byte written
+- * May return an error.
+- */
+-char *kgdb_hex2mem(char *buf, char *mem, int count)
+-{
+-      kgdb_set_may_fault();
+-      if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
+-              kgdb_unset_may_fault();
+-              return ERR_PTR(-EINVAL);
+-      }
+-      if ((count == 2) && (((long)mem & 1) == 0)) {
+-              unsigned short tmp_s = 0;
+-#ifdef __BIG_ENDIAN
+-              tmp_s |= hex(*buf++) << 12;
+-              tmp_s |= hex(*buf++) << 8;
+-              tmp_s |= hex(*buf++) << 4;
+-              tmp_s |= hex(*buf++);
+-#else
+-              tmp_s |= hex(*buf++) << 4;
+-              tmp_s |= hex(*buf++);
+-              tmp_s |= hex(*buf++) << 12;
+-              tmp_s |= hex(*buf++) << 8;
+-#endif
+-              *(unsigned short *)mem = tmp_s;
+-              mem += 2;
+-      } else if ((count == 4) && (((long)mem & 3) == 0)) {
+-              unsigned long tmp_l = 0;
+-#ifdef __BIG_ENDIAN
+-              tmp_l |= hex(*buf++) << 28;
+-              tmp_l |= hex(*buf++) << 24;
+-              tmp_l |= hex(*buf++) << 20;
+-              tmp_l |= hex(*buf++) << 16;
+-              tmp_l |= hex(*buf++) << 12;
+-              tmp_l |= hex(*buf++) << 8;
+-              tmp_l |= hex(*buf++) << 4;
+-              tmp_l |= hex(*buf++);
+-#else
+-              tmp_l |= hex(*buf++) << 4;
+-              tmp_l |= hex(*buf++);
+-              tmp_l |= hex(*buf++) << 12;
+-              tmp_l |= hex(*buf++) << 8;
+-              tmp_l |= hex(*buf++) << 20;
+-              tmp_l |= hex(*buf++) << 16;
+-              tmp_l |= hex(*buf++) << 28;
+-              tmp_l |= hex(*buf++) << 24;
+-#endif
+-              *(unsigned long *)mem = tmp_l;
+-              mem += 4;
+-      } else {
+-              int i;
+-              for (i = 0; i < count; i++) {
+-                      unsigned char ch = hex(*buf++) << 4;
+-                      ch |= hex(*buf++);
+-                      *mem++ = ch;
+-              }
+-      }
+-      kgdb_unset_may_fault();
+-      return (mem);
+-}
+-
+-/*
+- * While we find nice hex chars, build a long_val.
+- * Return number of chars processed.
+- */
+-int kgdb_hex2long(char **ptr, long *long_val)
+-{
+-      int hex_val, num = 0;
+-
+-      *long_val = 0;
+-
+-      while (**ptr) {
+-              hex_val = hex(**ptr);
+-              if (hex_val >= 0) {
+-                      *long_val = (*long_val << 4) | hex_val;
+-                      num++;
+-              } else
+-                      break;
+-
+-              (*ptr)++;
+-      }
+-
+-      return (num);
+-}
+-
+-/* Write memory due to an 'M' or 'X' packet. */
+-static char *write_mem_msg(int binary)
+-{
+-      char *ptr = &remcom_in_buffer[1];
+-      unsigned long addr, length;
+-
+-      if (kgdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' &&
+-          kgdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') {
+-              if (binary)
+-                      ptr = kgdb_ebin2mem(ptr, (char *)addr, length);
+-              else
+-                      ptr = kgdb_hex2mem(ptr, (char *)addr, length);
+-              if (CACHE_FLUSH_IS_SAFE)
+-                      flush_icache_range(addr, addr + length + 1);
+-              if (IS_ERR(ptr))
+-                      return ptr;
+-              return NULL;
+-      }
+-
+-      return ERR_PTR(-EINVAL);
+-}
+-
+-static inline char *pack_hex_byte(char *pkt, int byte)
+-{
+-      *pkt++ = hexchars[(byte >> 4) & 0xf];
+-      *pkt++ = hexchars[(byte & 0xf)];
+-      return pkt;
+-}
+-
+-static inline void error_packet(char *pkt, int error)
+-{
+-      error = -error;
+-      pkt[0] = 'E';
+-      pkt[1] = hexchars[(error / 10)];
+-      pkt[2] = hexchars[(error % 10)];
+-      pkt[3] = '\0';
+-}
+-
+-static char *pack_threadid(char *pkt, threadref * id)
+-{
+-      char *limit;
+-      unsigned char *altid;
+-
+-      altid = (unsigned char *)id;
+-      limit = pkt + BUF_THREAD_ID_SIZE;
+-      while (pkt < limit)
+-              pkt = pack_hex_byte(pkt, *altid++);
+-
+-      return pkt;
+-}
+-
+-void int_to_threadref(threadref * id, int value)
+-{
+-      unsigned char *scan;
+-      int i = 4;
+-
+-      scan = (unsigned char *)id;
+-      while (i--)
+-              *scan++ = 0;
+-      *scan++ = (value >> 24) & 0xff;
+-      *scan++ = (value >> 16) & 0xff;
+-      *scan++ = (value >> 8) & 0xff;
+-      *scan++ = (value & 0xff);
+-}
+-
+-static struct task_struct *getthread(struct pt_regs *regs, int tid)
+-{
+-      if (init_pid_ns.last_pid == 0)
+-              return current;
+-
+-      if (num_online_cpus() &&
+-          (tid >= pid_max + num_online_cpus() + kgdb_ops->shadowth))
+-              return NULL;
+-
+-      if (kgdb_ops->shadowth && (tid >= pid_max + num_online_cpus()))
+-              return kgdb_get_shadow_thread(regs, tid - pid_max -
+-                                            num_online_cpus());
+-
+-      if (tid >= pid_max)
+-              return idle_task(tid - pid_max);
+-
+-      if (!tid)
+-              return NULL;
+-
+-      return find_task_by_pid(tid);
+-}
+-
+-#ifdef CONFIG_SMP
+-static void kgdb_wait(struct pt_regs *regs)
+-{
+-      unsigned long flags;
+-      int processor;
+-
+-      local_irq_save(flags);
+-      processor = raw_smp_processor_id();
+-      kgdb_info[processor].debuggerinfo = regs;
+-      kgdb_info[processor].task = current;
+-      atomic_set(&procindebug[processor], 1);
+-      atomic_set(&kgdb_sync_softlockup[raw_smp_processor_id()], 1);
+-
+-      /* Wait till master processor goes completely into the debugger.
+-       * FIXME: this looks racy */
+-      while (!atomic_read(&procindebug[atomic_read(&debugger_active) - 1])) {
+-              int i = 10;     /* an arbitrary number */
+-
+-              while (--i)
+-                      cpu_relax();
+-      }
+-
+-      /* Wait till master processor is done with debugging */
+-      spin_lock(&slavecpulocks[processor]);
+-
+-      kgdb_info[processor].debuggerinfo = NULL;
+-      kgdb_info[processor].task = NULL;
+-
+-      /* fix up hardware debug registers on local cpu */
+-      if (kgdb_ops->correct_hw_break)
+-              kgdb_ops->correct_hw_break();
+-      /* Signal the master processor that we are done */
+-      atomic_set(&procindebug[processor], 0);
+-      spin_unlock(&slavecpulocks[processor]);
+-      local_irq_restore(flags);
+-}
+-#endif
+-
+-int kgdb_get_mem(char *addr, unsigned char *buf, int count)
+-{
+-      kgdb_set_may_fault();
+-      if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
+-              kgdb_unset_may_fault();
+-              return -EINVAL;
+-      }
+-      while (count) {
+-              if ((unsigned long)addr < TASK_SIZE) {
+-                      kgdb_unset_may_fault();
+-                      return -EINVAL;
+-              }
+-              *buf++ = *addr++;
+-              count--;
+-      }
+-      kgdb_unset_may_fault();
+-      return 0;
+-}
+-
+-int kgdb_set_mem(char *addr, unsigned char *buf, int count)
+-{
+-      kgdb_set_may_fault();
+-      if ((kgdb_fault_setjmp(kgdb_fault_jmp_regs)) != 0) {
+-              kgdb_unset_may_fault();
+-              return -EINVAL;
+-      }
+-      while (count) {
+-              if ((unsigned long)addr < TASK_SIZE) {
+-                      kgdb_unset_may_fault();
+-                      return -EINVAL;
+-              }
+-              *addr++ = *buf++;
+-              count--;
+-      }
+-      kgdb_unset_may_fault();
+-      return 0;
+-}
+-int kgdb_activate_sw_breakpoints(void)
+-{
+-      int i;
+-      int error = 0;
+-      unsigned long addr;
+-      for (i = 0; i < MAX_BREAKPOINTS; i++) {
+-              if (kgdb_break[i].state != bp_set)
+-                      continue;
+-              addr = kgdb_break[i].bpt_addr;
+-              if ((error = kgdb_arch_set_breakpoint(addr,
+-                                      kgdb_break[i].saved_instr)))
+-                      return error;
+-
+-              if (CACHE_FLUSH_IS_SAFE) {
+-                      if (current->mm && addr < TASK_SIZE)
+-                              flush_cache_range(current->mm->mmap_cache,
+-                                              addr, addr + BREAK_INSTR_SIZE);
+-                      else
+-                              flush_icache_range(addr, addr +
+-                                              BREAK_INSTR_SIZE);
+-              }
+-
+-              kgdb_break[i].state = bp_active;
+-        }
+-      return 0;
+-}
+-
+-static int kgdb_set_sw_break(unsigned long addr)
+-{
+-      int i, breakno = -1;
+-      int error = 0;
+-      if ((error = kgdb_validate_break_address(addr)) < 0)
+-              return error;
+-      for (i = 0; i < MAX_BREAKPOINTS; i++) {
+-              if ((kgdb_break[i].state == bp_set) &&
+-                      (kgdb_break[i].bpt_addr == addr))
+-                      return -EEXIST;
+-      }
+-      for (i = 0; i < MAX_BREAKPOINTS; i++) {
+-              if (kgdb_break[i].state == bp_removed &&
+-                              kgdb_break[i].bpt_addr == addr) {
+-                      breakno = i;
+-                      break;
+-              }
+-      }
+-
+-      if (breakno == -1) {
+-              for (i = 0; i < MAX_BREAKPOINTS; i++) {
+-                      if (kgdb_break[i].state == bp_none) {
+-                              breakno = i;
+-                              break;
+-                      }
+-              }
+-      }
+-      if (breakno == -1)
+-              return -E2BIG;
+-
+-      kgdb_break[breakno].state = bp_set;
+-      kgdb_break[breakno].type = bp_breakpoint;
+-      kgdb_break[breakno].bpt_addr = addr;
+-
+-      return 0;
+-}
+-
+-int kgdb_deactivate_sw_breakpoints(void)
+-{
+-      int i;
+-      int error = 0;
+-      unsigned long addr;
+-      for (i = 0; i < MAX_BREAKPOINTS; i++) {
+-              if (kgdb_break[i].state != bp_active)
+-                      continue;
+-              addr = kgdb_break[i].bpt_addr;
+-              if ((error = kgdb_arch_remove_breakpoint(addr,
+-                                      kgdb_break[i].saved_instr)))
+-                      return error;
+-
+-              if (CACHE_FLUSH_IS_SAFE && current->mm &&
+-                              addr < TASK_SIZE)
+-                      flush_cache_range(current->mm->mmap_cache,
+-                                      addr, addr + BREAK_INSTR_SIZE);
+-              else if (CACHE_FLUSH_IS_SAFE)
+-                      flush_icache_range(addr,
+-                                      addr + BREAK_INSTR_SIZE);
+-              kgdb_break[i].state = bp_set;
+-      }
+-      return 0;
+-}
+-
+-static int kgdb_remove_sw_break(unsigned long addr)
+-{
+-      int i;
+-
+-      for (i = 0; i < MAX_BREAKPOINTS; i++) {
+-              if ((kgdb_break[i].state == bp_set) &&
+-                      (kgdb_break[i].bpt_addr == addr)) {
+-                      kgdb_break[i].state = bp_removed;
+-                      return 0;
+-              }
+-      }
+-      return -ENOENT;
+-}
+-
+-int kgdb_isremovedbreak(unsigned long addr)
+-{
+-      int i;
+-      for (i = 0; i < MAX_BREAKPOINTS; i++) {
+-              if ((kgdb_break[i].state == bp_removed) &&
+-                      (kgdb_break[i].bpt_addr == addr)) {
+-                      return 1;
+-              }
+-      }
+-      return 0;
+-}
+-
+-int remove_all_break(void)
+-{
+-      int i;
+-      int error;
+-      unsigned long addr;
+-
+-      /* Clear memory breakpoints. */
+-      for (i = 0; i < MAX_BREAKPOINTS; i++) {
+-              if (kgdb_break[i].state != bp_set)
+-                      continue;
+-              addr = kgdb_break[i].bpt_addr;
+-              if ((error = kgdb_arch_remove_breakpoint(addr,
+-                                      kgdb_break[i].saved_instr)))
+-                      return error;
+-              kgdb_break[i].state = bp_removed;
+-      }
+-
+-      /* Clear hardware breakpoints. */
+-      if (kgdb_ops->remove_all_hw_break)
+-              kgdb_ops->remove_all_hw_break();
+-
+-      return 0;
+-}
+-
+-static inline int shadow_pid(int realpid)
+-{
+-      if (realpid) {
+-              return realpid;
 -      }
-       /* It is possible to run out of possible slots
-        * when the name is long and there isn't enough space left
-@@ -793,6 +830,34 @@
-       return -ENFILE;
- }
-+/**
-+ *    dev_alloc_name - allocate a name for a device
-+ *    @dev: device
-+ *    @name: name format string
-+ *
-+ *    Passed a format string - eg "lt%d" it will try and find a suitable
-+ *    id. It scans list of devices to build up a free map, then chooses
-+ *    the first empty slot. The caller must hold the dev_base or rtnl lock
-+ *    while allocating the name and adding the device in order to avoid
-+ *    duplicates.
-+ *    Limited to bits_per_byte * page size devices (ie 32K on most platforms).
-+ *    Returns the number of the unit assigned or a negative errno code.
-+ */
-+
-+int dev_alloc_name(struct net_device *dev, const char *name)
-+{
-+      char buf[IFNAMSIZ];
-+      struct net *net;
-+      int ret;
-+
-+      BUG_ON(!dev->nd_net);
-+      net = dev->nd_net;
-+      ret = __dev_alloc_name(net, name, buf);
-+      if (ret >= 0)
-+              strlcpy(dev->name, buf, IFNAMSIZ);
-+      return ret;
-+}
-+
- /**
-  *    dev_change_name - change name of a device
-@@ -805,9 +870,12 @@
- int dev_change_name(struct net_device *dev, char *newname)
- {
-       int err = 0;
-+      struct net *net;
-       ASSERT_RTNL();
-+      BUG_ON(!dev->nd_net);
-+      net = dev->nd_net;
-       if (dev->flags & IFF_UP)
-               return -EBUSY;
-@@ -820,14 +888,18 @@
-                       return err;
-               strcpy(newname, dev->name);
-       }
--      else if (__dev_get_by_name(newname))
-+      else if (__dev_get_by_name(net, newname))
-               return -EEXIST;
--      else
-+      else {
-+              if (strncmp(newname, dev->name, IFNAMSIZ))
-+                      printk(KERN_INFO "%s renamed to %s\n",
-+                                      dev->name, newname);
-               strlcpy(dev->name, newname, IFNAMSIZ);
-+      }
-       device_rename(&dev->dev, dev->name);
-       hlist_del(&dev->name_hlist);
--      hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
-+      hlist_add_head(&dev->name_hlist, dev_name_hash(net, dev->name));
-       raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
-       return err;
-@@ -871,12 +943,12 @@
-  *    available in this kernel then it becomes a nop.
-  */
--void dev_load(const char *name)
-+void dev_load(struct net *net, const char *name)
- {
-       struct net_device *dev;
-       read_lock(&dev_base_lock);
--      dev = __dev_get_by_name(name);
-+      dev = __dev_get_by_name(net, name);
-       read_unlock(&dev_base_lock);
-       if (!dev && capable(CAP_SYS_MODULE))
-@@ -1019,6 +1091,8 @@
- }
-+static int dev_boot_phase = 1;
-+
- /*
-  *    Device change register/unregister. These are not inline or static
-  *    as we export them to the world.
-@@ -1045,14 +1119,17 @@
-       rtnl_lock();
-       err = raw_notifier_chain_register(&netdev_chain, nb);
--      if (!err) {
--              for_each_netdev(dev) {
-+      if (!err && !dev_boot_phase) {
-+              struct net *net;
-+              for_each_net(net) {
-+                      for_each_netdev(net, dev) {
-                       nb->notifier_call(nb, NETDEV_REGISTER, dev);
-                       if (dev->flags & IFF_UP)
-                               nb->notifier_call(nb, NETDEV_UP, dev);
-               }
-       }
-+      }
-       rtnl_unlock();
-       return err;
- }
-@@ -1086,9 +1163,9 @@
-  *    are as for raw_notifier_call_chain().
-  */
--int call_netdevice_notifiers(unsigned long val, void *v)
-+int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
- {
--      return raw_notifier_call_chain(&netdev_chain, val, v);
-+      return raw_notifier_call_chain(&netdev_chain, val, dev);
- }
- /* When > 0 there are consumers of rx skb time stamps */
-@@ -1510,9 +1587,11 @@
-               skb_set_transport_header(skb, skb->csum_start -
-                                             skb_headroom(skb));
--              if (!(dev->features & NETIF_F_GEN_CSUM) &&
--                  (!(dev->features & NETIF_F_IP_CSUM) ||
--                   skb->protocol != htons(ETH_P_IP)))
-+              if (!(dev->features & NETIF_F_GEN_CSUM)
-+                  || ((dev->features & NETIF_F_IP_CSUM)
-+                      && skb->protocol == htons(ETH_P_IP))
-+                  || ((dev->features & NETIF_F_IPV6_CSUM)
-+                      && skb->protocol == htons(ETH_P_IPV6)))
-                       if (skb_checksum_help(skb))
-                               goto out_kfree_skb;
-       }
-@@ -2016,12 +2095,13 @@
-        * There may not be any more sk_buffs coming right now, so push
-        * any pending DMA copies to hardware
-        */
--      if (net_dma_client) {
--              struct dma_chan *chan;
--              rcu_read_lock();
--              list_for_each_entry_rcu(chan, &net_dma_client->channels, client_node)
-+      if (!cpus_empty(net_dma.channel_mask)) {
-+              int chan_idx;
-+              for_each_cpu_mask(chan_idx, net_dma.channel_mask) {
-+                      struct dma_chan *chan = net_dma.channels[chan_idx];
-+                      if (chan)
-                       dma_async_memcpy_issue_pending(chan);
--              rcu_read_unlock();
-+              }
-       }
- #endif
-       return;
-@@ -2063,7 +2143,7 @@
-  *    match.  --pb
-  */
--static int dev_ifname(struct ifreq __user *arg)
-+static int dev_ifname(struct net *net, struct ifreq __user *arg)
- {
-       struct net_device *dev;
-       struct ifreq ifr;
-@@ -2076,7 +2156,7 @@
-               return -EFAULT;
-       read_lock(&dev_base_lock);
--      dev = __dev_get_by_index(ifr.ifr_ifindex);
-+      dev = __dev_get_by_index(net, ifr.ifr_ifindex);
-       if (!dev) {
-               read_unlock(&dev_base_lock);
-               return -ENODEV;
-@@ -2096,7 +2176,7 @@
-  *    Thus we will need a 'compatibility mode'.
-  */
--static int dev_ifconf(char __user *arg)
-+static int dev_ifconf(struct net *net, char __user *arg)
- {
-       struct ifconf ifc;
-       struct net_device *dev;
-@@ -2120,7 +2200,7 @@
-        */
-       total = 0;
--      for_each_netdev(dev) {
-+      for_each_netdev(net, dev) {
-               if (!nx_dev_visible(current->nx_info, dev))
-                       continue;
-               for (i = 0; i < NPROTO; i++) {
-@@ -2156,6 +2236,7 @@
-  */
- void *dev_seq_start(struct seq_file *seq, loff_t *pos)
- {
-+      struct net *net = seq->private;
-       loff_t off;
-       struct net_device *dev;
-@@ -2164,7 +2245,7 @@
-               return SEQ_START_TOKEN;
-       off = 1;
--      for_each_netdev(dev)
-+      for_each_netdev(net, dev)
-               if (off++ == *pos)
-                       return dev;
-@@ -2173,9 +2254,10 @@
- void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
- {
-+      struct net *net = seq->private;
-       ++*pos;
-       return v == SEQ_START_TOKEN ?
--              first_net_device() : next_net_device((struct net_device *)v);
-+              first_net_device(net) : next_net_device((struct net_device *)v);
- }
- void dev_seq_stop(struct seq_file *seq, void *v)
-@@ -2274,7 +2356,22 @@
- static int dev_seq_open(struct inode *inode, struct file *file)
- {
--      return seq_open(file, &dev_seq_ops);
-+      struct seq_file *seq;
-+      int res;
-+      res =  seq_open(file, &dev_seq_ops);
-+      if (!res) {
-+              seq = file->private_data;
-+              seq->private = get_net(PROC_NET(inode));
-+      }
-+      return res;
-+}
-+
-+static int dev_seq_release(struct inode *inode, struct file *file)
-+{
-+      struct seq_file *seq = file->private_data;
-+      struct net *net = seq->private;
-+      put_net(net);
-+      return seq_release(inode, file);
- }
- static const struct file_operations dev_seq_fops = {
-@@ -2282,7 +2379,7 @@
-       .open    = dev_seq_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
--      .release = seq_release,
-+      .release = dev_seq_release,
- };
- static const struct seq_operations softnet_seq_ops = {
-@@ -2434,30 +2531,49 @@
- };
--static int __init dev_proc_init(void)
-+static int dev_proc_net_init(struct net *net)
- {
-       int rc = -ENOMEM;
--      if (!proc_net_fops_create("dev", S_IRUGO, &dev_seq_fops))
-+      if (!proc_net_fops_create(net, "dev", S_IRUGO, &dev_seq_fops))
-               goto out;
--      if (!proc_net_fops_create("softnet_stat", S_IRUGO, &softnet_seq_fops))
-+      if (!proc_net_fops_create(net, "softnet_stat", S_IRUGO, &softnet_seq_fops))
-               goto out_dev;
--      if (!proc_net_fops_create("ptype", S_IRUGO, &ptype_seq_fops))
--              goto out_dev2;
+-      return pid_max + raw_smp_processor_id();
+-}
+-
+-static char gdbmsgbuf[BUFMAX + 1];
+-static void kgdb_msg_write(const char *s, int len)
+-{
+-      int i;
+-      int wcount;
+-      char *bufptr;
+-
+-      /* 'O'utput */
+-      gdbmsgbuf[0] = 'O';
+-
+-      /* Fill and send buffers... */
+-      while (len > 0) {
+-              bufptr = gdbmsgbuf + 1;
+-
+-              /* Calculate how many this time */
+-              if ((len << 1) > (BUFMAX - 2))
+-                      wcount = (BUFMAX - 2) >> 1;
+-              else
+-                      wcount = len;
+-
+-              /* Pack in hex chars */
+-              for (i = 0; i < wcount; i++)
+-                      bufptr = pack_hex_byte(bufptr, s[i]);
+-              *bufptr = '\0';
+-
+-              /* Move up */
+-              s += wcount;
+-              len -= wcount;
+-
+-              /* Write packet */
+-              put_packet(gdbmsgbuf);
+-      }
+-}
+-
+-/*
+- * This function does all command procesing for interfacing to gdb.
+- *
+- * Locking hierarchy:
+- *    interface locks, if any (begin_session)
+- *    kgdb lock (debugger_active)
+- *
+- * Note that since we can be in here prior to our cpumask being filled
+- * out, we err on the side of caution and loop over NR_CPUS instead
+- * of a for_each_online_cpu.
+- *
+- */
+-int kgdb_handle_exception(int ex_vector, int signo, int err_code,
+-                        struct pt_regs *linux_regs)
+-{
+-      unsigned long length, addr;
+-      char *ptr;
+-      unsigned long flags;
+-      unsigned i;
+-      long threadid;
+-      threadref thref;
+-      struct task_struct *thread = NULL;
+-      unsigned procid;
+-      int numshadowth = num_online_cpus() + kgdb_ops->shadowth;
+-      long kgdb_usethreadid = 0;
+-      int error = 0, all_cpus_synced = 0;
+-      struct pt_regs *shadowregs;
+-      int processor = raw_smp_processor_id();
+-      void *local_debuggerinfo;
+-
+-      /* Panic on recursive debugger calls. */
+-      if (atomic_read(&debugger_active) == raw_smp_processor_id() + 1) {
+-              exception_level++;
+-              addr = kgdb_arch_pc(ex_vector, linux_regs);
+-              kgdb_deactivate_sw_breakpoints();
+-              if (kgdb_remove_sw_break(addr) == 0) {
+-                      /* If the break point removed ok at the place exception
+-                       * occurred, try to recover and print a warning to the end
+-                       * user because the user planted a breakpoint in a place
+-                       * that KGDB needs in order to function.
+-                       */
+-                      exception_level = 0;
+-                      kgdb_skipexception(ex_vector, linux_regs);
+-                      kgdb_activate_sw_breakpoints();
+-                      printk(KERN_CRIT "KGDB: re-enter exception: breakpoint removed\n");
+-                      WARN_ON(1);
+-                      return 0;
+-              }
+-              remove_all_break();
+-              kgdb_skipexception(ex_vector, linux_regs);
+-              if (exception_level > 1)
+-                      panic("Recursive entry to debugger");
+-
+-              printk(KERN_CRIT "KGDB: re-enter exception: ALL breakpoints removed\n");
+-              panic("Recursive entry to debugger");
+-              return 0;
+-      }
+-
+- acquirelock:
+-
+-      /*
+-       * Interrupts will be restored by the 'trap return' code, except when
+-       * single stepping.
+-       */
+-      local_irq_save(flags);
+-
+-      /* Hold debugger_active */
+-      procid = raw_smp_processor_id();
+-
+-      while (cmpxchg(&atomic_read(&debugger_active), 0, (procid + 1)) != 0) {
+-              int i = 25;     /* an arbitrary number */
+-
+-              while (--i)
+-                      cpu_relax();
+-
+-              if (atomic_read(&cpu_doing_single_step) != -1 &&
+-                              atomic_read(&cpu_doing_single_step) != procid)
+-                      udelay(1);
+-      }
+-
+-      atomic_set(&kgdb_sync_softlockup[raw_smp_processor_id()], 1);
+-
+-      /*
+-       * Don't enter if the last instance of the exception handler wanted to
+-       * come into the debugger again.
+-       */
+-      if (atomic_read(&cpu_doing_single_step) != -1 &&
+-          atomic_read(&cpu_doing_single_step) != procid) {
+-              atomic_set(&debugger_active, 0);
+-              local_irq_restore(flags);
+-              goto acquirelock;
+-      }
+-
+-      /*
+-      * Don't enter if we have hit a removed breakpoint.
+-      */
+-      if (kgdb_skipexception(ex_vector, linux_regs))
+-              goto kgdb_restore;
+-
+-      /*
+-       * Call the I/O drivers pre_exception routine
+-       * if the I/O driver defined one
+-       */
+-      if (kgdb_io_ops.pre_exception)
+-              kgdb_io_ops.pre_exception();
+-
+-      kgdb_info[processor].debuggerinfo = linux_regs;
+-      kgdb_info[processor].task = current;
+-
+-      kgdb_disable_hw_debug(linux_regs);
+-
+-      if (!debugger_step || !kgdb_contthread)
+-              for (i = 0; i < NR_CPUS; i++)
+-                      spin_lock(&slavecpulocks[i]);
+-
+-#ifdef CONFIG_SMP
+-      /* Make sure we get the other CPUs */
+-      if (!debugger_step || !kgdb_contthread)
+-              kgdb_roundup_cpus(flags);
+-#endif
+-
+-      /* spin_lock code is good enough as a barrier so we don't
+-       * need one here */
+-      atomic_set(&procindebug[processor], 1);
+-
+-      /* Wait a reasonable time for the other CPUs to be notified and
+-       * be waiting for us.  Very early on this could be imperfect
+-       * as num_online_cpus() could be 0.*/
+-      for (i = 0; i < ROUNDUP_WAIT; i++) {
+-              int cpu, num = 0;
+-              for (cpu = 0; cpu < NR_CPUS; cpu++) {
+-                      if (atomic_read(&procindebug[cpu]))
+-                              num++;
+-              }
+-              if (num >= num_online_cpus()) {
+-                      all_cpus_synced = 1;
+-                      break;
+-              }
+-      }
+-
+-      /* Clear the out buffer. */
+-      memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
+-
+-      /* Master processor is completely in the debugger */
+-      kgdb_post_master_code(linux_regs, ex_vector, err_code);
+-      kgdb_deactivate_sw_breakpoints();
+-      debugger_step = 0;
+-      kgdb_contthread = NULL;
+-      exception_level = 0;
+-
+-      if (kgdb_connected) {
+-              /* If we're still unable to roundup all of the CPUs,
+-               * send an 'O' packet informing the user again. */
+-              if (!all_cpus_synced)
+-                      kgdb_msg_write("Not all CPUs have been synced for "
+-                                     "KGDB\n", 39);
+-              /* Reply to host that an exception has occurred */
+-              ptr = remcom_out_buffer;
+-              *ptr++ = 'T';
+-              *ptr++ = hexchars[(signo >> 4) % 16];
+-              *ptr++ = hexchars[signo % 16];
+-              ptr += strlen(strcpy(ptr, "thread:"));
+-              int_to_threadref(&thref, shadow_pid(current->pid));
+-              ptr = pack_threadid(ptr, &thref);
+-              *ptr++ = ';';
+-
+-              put_packet(remcom_out_buffer);
+-      }
+-
+-      kgdb_usethread = kgdb_info[processor].task;
+-      kgdb_usethreadid = shadow_pid(kgdb_info[processor].task->pid);
+-
+-      while (kgdb_io_ops.read_char) {
+-              char *bpt_type;
+-              error = 0;
+-
+-              /* Clear the out buffer. */
+-              memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
+-
+-              get_packet(remcom_in_buffer);
+-
+-              switch (remcom_in_buffer[0]) {
+-              case '?':
+-                      /* We know that this packet is only sent
+-                       * during initial connect.  So to be safe,
+-                       * we clear out our breakpoints now incase
+-                       * GDB is reconnecting. */
+-                      remove_all_break();
+-                      /* Also, if we haven't been able to roundup all
+-                       * CPUs, send an 'O' packet informing the user
+-                       * as much.  Only need to do this once. */
+-                      if (!all_cpus_synced)
+-                              kgdb_msg_write("Not all CPUs have been "
+-                                             "synced for KGDB\n", 39);
+-                      remcom_out_buffer[0] = 'S';
+-                      remcom_out_buffer[1] = hexchars[signo >> 4];
+-                      remcom_out_buffer[2] = hexchars[signo % 16];
+-                      break;
+-
+-              case 'g':       /* return the value of the CPU registers */
+-                      thread = kgdb_usethread;
+-
+-                      if (!thread) {
+-                              thread = kgdb_info[processor].task;
+-                              local_debuggerinfo =
+-                                  kgdb_info[processor].debuggerinfo;
+-                      } else {
+-                              local_debuggerinfo = NULL;
+-                              for (i = 0; i < NR_CPUS; i++) {
+-                                      /* Try to find the task on some other
+-                                       * or possibly this node if we do not
+-                                       * find the matching task then we try
+-                                       * to approximate the results.
+-                                       */
+-                                      if (thread == kgdb_info[i].task)
+-                                              local_debuggerinfo =
+-                                                  kgdb_info[i].debuggerinfo;
+-                              }
+-                      }
+-
+-                      /* All threads that don't have debuggerinfo should be
+-                       * in __schedule() sleeping, since all other CPUs
+-                       * are in kgdb_wait, and thus have debuggerinfo. */
+-                      if (kgdb_ops->shadowth &&
+-                          kgdb_usethreadid >= pid_max + num_online_cpus()) {
+-                              shadowregs = kgdb_shadow_regs(linux_regs,
+-                                                            kgdb_usethreadid -
+-                                                            pid_max -
+-                                                            num_online_cpus
+-                                                            ());
+-                              if (!shadowregs) {
+-                                      error_packet(remcom_out_buffer,
+-                                                   -EINVAL);
+-                                      break;
+-                              }
+-                              regs_to_gdb_regs(gdb_regs, shadowregs);
+-                      } else if (local_debuggerinfo)
+-                              regs_to_gdb_regs(gdb_regs, local_debuggerinfo);
+-                      else {
+-                              /* Pull stuff saved during
+-                               * switch_to; nothing else is
+-                               * accessible (or even particularly relevant).
+-                               * This should be enough for a stack trace. */
+-                              sleeping_thread_to_gdb_regs(gdb_regs, thread);
+-                      }
+-                      kgdb_mem2hex((char *)gdb_regs, remcom_out_buffer,
+-                                   NUMREGBYTES);
+-                      break;
+-
+-                      /* set the value of the CPU registers - return OK */
+-              case 'G':
+-                      kgdb_hex2mem(&remcom_in_buffer[1], (char *)gdb_regs,
+-                                   NUMREGBYTES);
+-
+-                      if (kgdb_usethread && kgdb_usethread != current)
+-                              error_packet(remcom_out_buffer, -EINVAL);
+-                      else {
+-                              gdb_regs_to_regs(gdb_regs, linux_regs);
+-                              strcpy(remcom_out_buffer, "OK");
+-                      }
+-                      break;
+-
+-                      /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
+-              case 'm':
+-                      ptr = &remcom_in_buffer[1];
+-                      if (kgdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' &&
+-                          kgdb_hex2long(&ptr, &length) > 0) {
+-                              if (IS_ERR(ptr = kgdb_mem2hex((char *)addr,
+-                                                            remcom_out_buffer,
+-                                                            length)))
+-                                      error_packet(remcom_out_buffer,
+-                                                   PTR_ERR(ptr));
+-                      } else
+-                              error_packet(remcom_out_buffer, -EINVAL);
+-                      break;
+-
+-                      /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA */
+-              case 'M':
+-                      if (IS_ERR(ptr = write_mem_msg(0)))
+-                              error_packet(remcom_out_buffer, PTR_ERR(ptr));
+-                      else
+-                              strcpy(remcom_out_buffer, "OK");
+-                      break;
+-                      /* XAA..AA,LLLL: Write LLLL bytes at address AA..AA */
+-              case 'X':
+-                      if (IS_ERR(ptr = write_mem_msg(1)))
+-                              error_packet(remcom_out_buffer, PTR_ERR(ptr));
+-                      else
+-                              strcpy(remcom_out_buffer, "OK");
+-                      break;
+-
+-                      /* kill or detach. KGDB should treat this like a
+-                       * continue.
+-                       */
+-              case 'D':
+-                      if ((error = remove_all_break()) < 0) {
+-                              error_packet(remcom_out_buffer, error);
+-                      } else {
+-                              strcpy(remcom_out_buffer, "OK");
+-                              kgdb_connected = 0;
+-                      }
+-                      put_packet(remcom_out_buffer);
+-                      goto default_handle;
+-
+-              case 'k':
+-                      /* Don't care about error from remove_all_break */
+-                      remove_all_break();
+-                      kgdb_connected = 0;
+-                      goto default_handle;
+-
+-                      /* Reboot */
+-              case 'R':
+-                      /* For now, only honor R0 */
+-                      if (strcmp(remcom_in_buffer, "R0") == 0) {
+-                              printk(KERN_CRIT "Executing reboot\n");
+-                              strcpy(remcom_out_buffer, "OK");
+-                              put_packet(remcom_out_buffer);
+-                              emergency_sync();
+-                              /* Execution should not return from
+-                               * machine_restart()
+-                               */
+-                              machine_restart(NULL);
+-                              kgdb_connected = 0;
+-                              goto default_handle;
+-                      }
+-
+-                      /* query */
+-              case 'q':
+-                      switch (remcom_in_buffer[1]) {
+-                      case 's':
+-                      case 'f':
+-                              if (memcmp(remcom_in_buffer + 2, "ThreadInfo",
+-                                         10)) {
+-                                      error_packet(remcom_out_buffer,
+-                                                   -EINVAL);
+-                                      break;
+-                              }
+-
+-                              /*
+-                               * If we have not yet completed in
+-                               * pidhash_init() there isn't much we
+-                               * can give back.
+-                               */
+-                              if (init_pid_ns.last_pid == 0) {
+-                                      if (remcom_in_buffer[1] == 'f')
+-                                              strcpy(remcom_out_buffer,
+-                                                     "m0000000000000001");
+-                                      break;
+-                              }
+-
+-                              if (remcom_in_buffer[1] == 'f') {
+-                                      threadid = 1;
+-                              }
+-                              remcom_out_buffer[0] = 'm';
+-                              ptr = remcom_out_buffer + 1;
+-                              for (i = 0; i < 17 && threadid < pid_max +
+-                                   numshadowth; threadid++) {
+-                                      thread = getthread(linux_regs,
+-                                                         threadid);
+-                                      if (thread) {
+-                                              int_to_threadref(&thref,
+-                                                               threadid);
+-                                              pack_threadid(ptr, &thref);
+-                                              ptr += 16;
+-                                              *(ptr++) = ',';
+-                                              i++;
+-                                      }
+-                              }
+-                              *(--ptr) = '\0';
+-                              break;
+-
+-                      case 'C':
+-                              /* Current thread id */
+-                              strcpy(remcom_out_buffer, "QC");
+-
+-                              threadid = shadow_pid(current->pid);
+-
+-                              int_to_threadref(&thref, threadid);
+-                              pack_threadid(remcom_out_buffer + 2, &thref);
+-                              break;
+-                      case 'T':
+-                              if (memcmp(remcom_in_buffer + 1,
+-                                         "ThreadExtraInfo,", 16)) {
+-                                      error_packet(remcom_out_buffer,
+-                                                   -EINVAL);
+-                                      break;
+-                              }
+-                              threadid = 0;
+-                              ptr = remcom_in_buffer + 17;
+-                              kgdb_hex2long(&ptr, &threadid);
+-                              if (!getthread(linux_regs, threadid)) {
+-                                      error_packet(remcom_out_buffer,
+-                                                   -EINVAL);
+-                                      break;
+-                              }
+-                              if (threadid < pid_max) {
+-                                      kgdb_mem2hex(getthread(linux_regs,
+-                                                             threadid)->comm,
+-                                                   remcom_out_buffer, 16);
+-                              } else if (threadid >= pid_max +
+-                                         num_online_cpus()) {
+-                                      kgdb_shadowinfo(linux_regs,
+-                                                      remcom_out_buffer,
+-                                                      threadid - pid_max -
+-                                                      num_online_cpus());
+-                              } else {
+-                                      static char tmpstr[23 +
+-                                                         BUF_THREAD_ID_SIZE];
+-                                      sprintf(tmpstr, "Shadow task %d"
+-                                              " for pid 0",
+-                                              (int)(threadid - pid_max));
+-                                      kgdb_mem2hex(tmpstr, remcom_out_buffer,
+-                                                   strlen(tmpstr));
+-                              }
+-                              break;
+-                      }
+-                      break;
+-
+-                      /* task related */
+-              case 'H':
+-                      switch (remcom_in_buffer[1]) {
+-                      case 'g':
+-                              ptr = &remcom_in_buffer[2];
+-                              kgdb_hex2long(&ptr, &threadid);
+-                              thread = getthread(linux_regs, threadid);
+-                              if (!thread && threadid > 0) {
+-                                      error_packet(remcom_out_buffer,
+-                                                   -EINVAL);
+-                                      break;
+-                              }
+-                              kgdb_usethread = thread;
+-                              kgdb_usethreadid = threadid;
+-                              strcpy(remcom_out_buffer, "OK");
+-                              break;
+-
+-                      case 'c':
+-                              ptr = &remcom_in_buffer[2];
+-                              kgdb_hex2long(&ptr, &threadid);
+-                              if (!threadid) {
+-                                      kgdb_contthread = NULL;
+-                              } else {
+-                                      thread = getthread(linux_regs,
+-                                                         threadid);
+-                                      if (!thread && threadid > 0) {
+-                                              error_packet(remcom_out_buffer,
+-                                                           -EINVAL);
+-                                              break;
+-                                      }
+-                                      kgdb_contthread = thread;
+-                              }
+-                              strcpy(remcom_out_buffer, "OK");
+-                              break;
+-                      }
+-                      break;
+-
+-                      /* Query thread status */
+-              case 'T':
+-                      ptr = &remcom_in_buffer[1];
+-                      kgdb_hex2long(&ptr, &threadid);
+-                      thread = getthread(linux_regs, threadid);
+-                      if (thread)
+-                              strcpy(remcom_out_buffer, "OK");
+-                      else
+-                              error_packet(remcom_out_buffer, -EINVAL);
+-                      break;
+-              /* Since GDB-5.3, it's been drafted that '0' is a software
+-               * breakpoint, '1' is a hardware breakpoint, so let's do
+-               * that.
+-               */
+-              case 'z':
+-              case 'Z':
+-                      bpt_type = &remcom_in_buffer[1];
+-                      ptr = &remcom_in_buffer[2];
+-
+-                      if (kgdb_ops->set_hw_breakpoint && *bpt_type >= '1') {
+-                              /* Unsupported */
+-                              if (*bpt_type > '4')
+-                                      break;
+-                      } else if (*bpt_type != '0' && *bpt_type != '1')
+-                              /* Unsupported. */
+-                              break;
+-                      /* Test if this is a hardware breakpoint, and
+-                       * if we support it. */
+-                      if (*bpt_type == '1' &&
+-                          !(kgdb_ops->flags & KGDB_HW_BREAKPOINT))
+-                              /* Unsupported. */
+-                              break;
+-
+-                      if (*(ptr++) != ',') {
+-                              error_packet(remcom_out_buffer, -EINVAL);
+-                              break;
+-                      } else if (kgdb_hex2long(&ptr, &addr)) {
+-                              if (*(ptr++) != ',' ||
+-                                  !kgdb_hex2long(&ptr, &length)) {
+-                                      error_packet(remcom_out_buffer,
+-                                                   -EINVAL);
+-                                      break;
+-                              }
+-                      } else {
+-                              error_packet(remcom_out_buffer, -EINVAL);
+-                              break;
+-                      }
+-
+-                      if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0')
+-                              error = kgdb_set_sw_break(addr);
+-                      else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0')
+-                              error = kgdb_remove_sw_break(addr);
+-                      else if (remcom_in_buffer[0] == 'Z')
+-                              error = kgdb_ops->set_hw_breakpoint(addr,
+-                                                                  (int)length,
+-                                                                  *bpt_type);
+-                      else if (remcom_in_buffer[0] == 'z')
+-                              error = kgdb_ops->remove_hw_breakpoint(addr,
+-                                                                     (int)
+-                                                                     length,
+-                                                                     *bpt_type);
+-
+-                      if (error == 0)
+-                              strcpy(remcom_out_buffer, "OK");
+-                      else
+-                              error_packet(remcom_out_buffer, error);
+-
+-                      break;
+-              case 'c':
+-              case 's':
+-                      if (kgdb_contthread && kgdb_contthread != current) {
+-                              /* Can't switch threads in kgdb */
+-                              error_packet(remcom_out_buffer, -EINVAL);
+-                              break;
+-                      }
+-                      kgdb_activate_sw_breakpoints();
+-                      /* Followthrough to default processing */
+-              default:
+-                    default_handle:
+-                      error = kgdb_arch_handle_exception(ex_vector, signo,
+-                                                         err_code,
+-                                                         remcom_in_buffer,
+-                                                         remcom_out_buffer,
+-                                                         linux_regs);
+-
+-                      if (error >= 0 || remcom_in_buffer[0] == 'D' ||
+-                          remcom_in_buffer[0] == 'k')
+-                              goto kgdb_exit;
+-
+-              }               /* switch */
+-
+-              /* reply to the request */
+-              put_packet(remcom_out_buffer);
+-      }
+-
+- kgdb_exit:
+-      /*
+-       * Call the I/O driver's post_exception routine
+-       * if the I/O driver defined one.
+-       */
+-      if (kgdb_io_ops.post_exception)
+-              kgdb_io_ops.post_exception();
+-
+-      kgdb_info[processor].debuggerinfo = NULL;
+-      kgdb_info[processor].task = NULL;
+-      atomic_set(&procindebug[processor], 0);
+-
+-      if (!debugger_step || !kgdb_contthread) {
+-              for (i = 0; i < NR_CPUS; i++)
+-                      spin_unlock(&slavecpulocks[i]);
+-              /* Wait till all the processors have quit
+-               * from the debugger. */
+-              for (i = 0; i < NR_CPUS; i++) {
+-                      while (atomic_read(&procindebug[i])) {
+-                              int j = 10;     /* an arbitrary number */
+-
+-                              while (--j)
+-                                      cpu_relax();
+-                      }
+-              }
+-      }
+-
+-#ifdef CONFIG_SMP
+-      /* This delay has a real purpose.  The problem is that if you
+-       * are single-stepping, you are sending an NMI to all the
+-       * other processors to stop them.  Interrupts come in, but
+-       * don't get handled.  Then you let them go just long enough
+-       * to get into their interrupt routines and use up some stack.
+-       * You stop them again, and then do the same thing.  After a
+-       * while you blow the stack on the other processors.  This
+-       * delay gives some time for interrupts to be cleared out on
+-       * the other processors.
+-       */
+-      if (debugger_step)
+-              mdelay(2);
+-#endif
+- kgdb_restore:
+-      /* Free debugger_active */
+-      atomic_set(&debugger_active, 0);
+-      local_irq_restore(flags);
+-
+-      return error;
+-}
+-
+-/*
+- * GDB places a breakpoint at this function to know dynamically
+- * loaded objects. It's not defined static so that only one instance with this
+- * name exists in the kernel.
+- */
+-
+-int module_event(struct notifier_block *self, unsigned long val, void *data)
+-{
+-      return 0;
+-}
+-
+-static struct notifier_block kgdb_module_load_nb = {
+-      .notifier_call = module_event,
+-};
+-
+-void kgdb_nmihook(int cpu, void *regs)
+-{
+-#ifdef CONFIG_SMP
+-      if (!atomic_read(&procindebug[cpu]) && atomic_read(&debugger_active) != (cpu + 1))
+-              kgdb_wait((struct pt_regs *)regs);
+-#endif
+-}
+-
+-/*
+- * This is called when a panic happens.  All we need to do is
+- * breakpoint().
+- */
+-static int kgdb_panic_notify(struct notifier_block *self, unsigned long cmd,
+-                           void *ptr)
+-{
+-      breakpoint();
+-
+-      return 0;
+-}
+-
+-static struct notifier_block kgdb_panic_notifier = {
+-      .notifier_call = kgdb_panic_notify,
+-};
+-
+-/*
+- * Initialization that needs to be done in either of our entry points.
+- */
+-static void __init kgdb_internal_init(void)
+-{
+-      int i;
+-
+-      /* Initialize our spinlocks. */
+-      for (i = 0; i < NR_CPUS; i++)
+-              spin_lock_init(&slavecpulocks[i]);
+-
+-      for (i = 0; i < MAX_BREAKPOINTS; i++)
+-              kgdb_break[i].state = bp_none;
+-
+-      /* Initialize the I/O handles */
+-      memset(&kgdb_io_ops_prev, 0, sizeof(kgdb_io_ops_prev));
+-
+-      /* We can't do much if this fails */
+-      register_module_notifier(&kgdb_module_load_nb);
+-
+-      kgdb_initialized = 1;
+-}
+-
+-static void kgdb_register_for_panic(void)
+-{
+-      /* Register for panics(). */
+-      /* The registration is done in the kgdb_register_for_panic
+-       * routine because KGDB should not try to handle a panic when
+-       * there are no kgdb_io_ops setup. It is assumed that the
+-       * kgdb_io_ops are setup at the time this method is called.
+-       */
+-      if (!kgdb_from_module_registered) {
+-              atomic_notifier_chain_register(&panic_notifier_list,
+-                                      &kgdb_panic_notifier);
+-              kgdb_from_module_registered = 1;
+-      }
+-}
+-
+-static void kgdb_unregister_for_panic(void)
+-{
+-      /* When this routine is called KGDB should unregister from the
+-       * panic handler and clean up, making sure it is not handling any
+-       * break exceptions at the time.
+-       */
+-      if (kgdb_from_module_registered) {
+-              kgdb_from_module_registered = 0;
+-              atomic_notifier_chain_unregister(&panic_notifier_list,
+-                                        &kgdb_panic_notifier);
+-      }
+-}
+-
+-int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops)
+-{
+-
+-      if (kgdb_connected) {
+-              printk(KERN_ERR "kgdb: Cannot load I/O module while KGDB "
+-                     "connected.\n");
+-              return -EINVAL;
+-      }
+-
+-      /* Save the old values so they can be restored */
+-      if (kgdb_io_handler_cnt >= MAX_KGDB_IO_HANDLERS) {
+-              printk(KERN_ERR "kgdb: No more I/O handles available.\n");
+-              return -EINVAL;
+-      }
+-
+-      /* Check to see if there is an existing driver and if so save its
+-       * values.  Also check to make sure the same driver was not trying
+-       * to re-register.
+-       */
+-      if (kgdb_io_ops.read_char != NULL &&
+-        kgdb_io_ops.read_char != local_kgdb_io_ops->read_char) {
+-              memcpy(&kgdb_io_ops_prev[kgdb_io_handler_cnt],
+-                     &kgdb_io_ops, sizeof(struct kgdb_io));
+-              kgdb_io_handler_cnt++;
+-      }
+-
+-      /* Initialize the io values for this module */
+-      memcpy(&kgdb_io_ops, local_kgdb_io_ops, sizeof(struct kgdb_io));
+-
+-      /* Make the call to register kgdb if is not initialized */
+-      kgdb_register_for_panic();
+-
+-      return 0;
+-}
+-
+-void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops)
+-{
+-      int i;
+-
+-      /* Unregister KGDB if there were no other prior io hooks, else
+-       * restore the io hooks.
+-       */
+-      if (kgdb_io_handler_cnt > 0 && kgdb_io_ops_prev[0].read_char != NULL) {
+-              /* First check if the hook that is in use is the one being
+-               * removed */
+-              if (kgdb_io_ops.read_char == local_kgdb_io_ops->read_char) {
+-                      /* Set 'i' to the value of where the list should be
+-                       * shifed */
+-                      i = kgdb_io_handler_cnt - 1;
+-                      memcpy(&kgdb_io_ops, &kgdb_io_ops_prev[i],
+-                             sizeof(struct kgdb_io));
+-              } else {
+-                      /* Simple case to remove an entry for an I/O handler
+-                       * that is not in use */
+-                      for (i = 0; i < kgdb_io_handler_cnt; i++) {
+-                              if (kgdb_io_ops_prev[i].read_char ==
+-                                  local_kgdb_io_ops->read_char)
+-                                      break;
+-                      }
+-              }
+-
+-              /* Shift all the entries in the handler array so it is
+-               * ordered from oldest to newest.
+-               */
+-              kgdb_io_handler_cnt--;
+-              for (; i < kgdb_io_handler_cnt; i++) {
+-                      memcpy(&kgdb_io_ops_prev[i], &kgdb_io_ops_prev[i + 1],
+-                             sizeof(struct kgdb_io));
+-              }
+-              /* Handle the case if we are on the last element and set it
+-               * to NULL; */
+-              memset(&kgdb_io_ops_prev[kgdb_io_handler_cnt], 0,
+-                              sizeof(struct kgdb_io));
+-
+-              if (kgdb_connected)
+-                      printk(KERN_ERR "kgdb: WARNING: I/O method changed "
+-                             "while kgdb was connected state.\n");
+-      } else {
+-              /* KGDB is no longer able to communicate out, so
+-               * unregister our hooks and reset state. */
+-              kgdb_unregister_for_panic();
+-              if (kgdb_connected) {
+-                      printk(KERN_CRIT "kgdb: I/O module was unloaded while "
+-                                      "a debugging session was running.  "
+-                                      "KGDB will be reset.\n");
+-                      if (remove_all_break() < 0)
+-                              printk(KERN_CRIT "kgdb: Reset failed.\n");
+-                      kgdb_connected = 0;
+-              }
+-              memset(&kgdb_io_ops, 0, sizeof(struct kgdb_io));
+-      }
+-}
+-
+-/*
+- * There are times we need to call a tasklet to cause a breakpoint
+- * as calling breakpoint() at that point might be fatal.  We have to
+- * check that the exception stack is setup, as tasklets may be scheduled
+- * prior to this.  When that happens, it is up to the architecture to
+- * schedule this when it is safe to run.
+- */
+-static void kgdb_tasklet_bpt(unsigned long ing)
+-{
+-      if (CHECK_EXCEPTION_STACK())
+-              breakpoint();
+-}
+-
+-DECLARE_TASKLET(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt, 0);
+-
+-/*
+- * This function can be called very early, either via early_param() or
+- * an explicit breakpoint() early on.
+- */
+-static void __init kgdb_early_entry(void)
+-{
+-      /* Let the architecture do any setup that it needs to. */
+-      kgdb_arch_init();
+-
+-      /*
+-       * Don't try and do anything until the architecture is able to
+-       * setup the exception stack.  In this case, it is up to the
+-       * architecture to hook in and look at us when they are ready.
+-       */
+-
+-      if (!CHECK_EXCEPTION_STACK()) {
+-              kgdb_initialized = -1;
+-              /* any kind of break point is deferred to late_init */
+-              return;
+-      }
+-
+-      /* Now try the I/O. */
+-      /* For early entry kgdb_io_ops.init must be defined */
+-      if (!kgdb_io_ops.init || kgdb_io_ops.init()) {
+-              /* Try again later. */
+-              kgdb_initialized = -1;
+-              return;
+-      }
+-
+-      /* Finish up. */
+-      kgdb_internal_init();
+-
+-      /* KGDB can assume that if kgdb_io_ops.init was defined that the
+-       * panic registion should be performed at this time. This means
+-       * kgdb_io_ops.init did not come from a kernel module and was
+-       * initialized statically by a built in.
+-       */
+-      if (kgdb_io_ops.init)
+-              kgdb_register_for_panic();
+-}
+-
+-/*
+- * This function will always be invoked to make sure that KGDB will grab
+- * what it needs to so that if something happens while the system is
+- * running, KGDB will get involved.  If kgdb_early_entry() has already
+- * been invoked, there is little we need to do.
+- */
+-static int __init kgdb_late_entry(void)
+-{
+-      int need_break = 0;
+-
+-      /* If kgdb_initialized is -1 then we were passed kgdbwait. */
+-      if (kgdb_initialized == -1)
+-              need_break = 1;
+-
+-      /*
+-       * If we haven't tried to initialize KGDB yet, we need to call
+-       * kgdb_arch_init before moving onto the I/O.
+-       */
+-      if (!kgdb_initialized)
+-              kgdb_arch_init();
+-
+-      if (kgdb_initialized != 1) {
+-              if (kgdb_io_ops.init && kgdb_io_ops.init()) {
+-                      /* When KGDB allows I/O via modules and the core
+-                       * I/O init fails KGDB must default to defering the
+-                       * I/O setup, and appropriately print an error about
+-                       * it.
+-                       */
+-                      printk(KERN_ERR "kgdb: Could not setup core I/O "
+-                             "for KGDB.\n");
+-                      printk(KERN_INFO "kgdb: Defering I/O setup to kernel "
+-                             "module.\n");
+-                      memset(&kgdb_io_ops, 0, sizeof(struct kgdb_io));
+-              }
+-
+-              kgdb_internal_init();
+-
+-              /* KGDB can assume that if kgdb_io_ops.init was defined that
+-               * panic registion should be performed at this time. This means
+-               * kgdb_io_ops.init did not come from a kernel module and was
+-               * initialized statically by a built in.
+-               */
+-              if (kgdb_io_ops.init)
+-                      kgdb_register_for_panic();
+-      }
+-
+-      /* Registering to reboot notifier list*/
+-      register_reboot_notifier(&kgdb_reboot_notifier);
+-
+-      /* Now do any late init of the I/O. */
+-      if (kgdb_io_ops.late_init)
+-              kgdb_io_ops.late_init();
+-
+-      if (need_break) {
+-              printk(KERN_CRIT "kgdb: Waiting for connection from remote"
+-                     " gdb...\n");
+-              breakpoint();
+-      }
+-
+-      return 0;
+-}
+-
+-late_initcall(kgdb_late_entry);
+-
+-/*
+- * This function will generate a breakpoint exception.  It is used at the
+- * beginning of a program to sync up with a debugger and can be used
+- * otherwise as a quick means to stop program execution and "break" into
+- * the debugger.
+- */
+-void breakpoint(void)
+-{
+-      atomic_set(&kgdb_setting_breakpoint, 1);
+-      wmb();
+-      BREAKPOINT();
+-      wmb();
+-      atomic_set(&kgdb_setting_breakpoint, 0);
+-}
+-
+-EXPORT_SYMBOL(breakpoint);
+-
+-#ifdef CONFIG_MAGIC_SYSRQ
+-static void sysrq_handle_gdb(int key, struct tty_struct *tty)
+-{
+-      printk("Entering GDB stub\n");
+-      breakpoint();
+-}
+-static struct sysrq_key_op sysrq_gdb_op = {
+-      .handler = sysrq_handle_gdb,
+-      .help_msg = "Gdb",
+-      .action_msg = "GDB",
+-};
 -
--      if (wext_proc_init())
-+      if (!proc_net_fops_create(net, "ptype", S_IRUGO, &ptype_seq_fops))
-               goto out_softnet;
-+
-+      if (wext_proc_init(net))
-+              goto out_ptype;
-       rc = 0;
- out:
-       return rc;
-+out_ptype:
-+      proc_net_remove(net, "ptype");
- out_softnet:
--      proc_net_remove("ptype");
--out_dev2:
--      proc_net_remove("softnet_stat");
-+      proc_net_remove(net, "softnet_stat");
- out_dev:
--      proc_net_remove("dev");
-+      proc_net_remove(net, "dev");
-       goto out;
- }
-+
-+static void dev_proc_net_exit(struct net *net)
-+{
-+      wext_proc_exit(net);
-+
-+      proc_net_remove(net, "ptype");
-+      proc_net_remove(net, "softnet_stat");
-+      proc_net_remove(net, "dev");
-+}
-+
-+static struct pernet_operations dev_proc_ops = {
-+      .init = dev_proc_net_init,
-+      .exit = dev_proc_net_exit,
-+};
-+
-+static int __init dev_proc_init(void)
-+{
-+      return register_pernet_subsys(&dev_proc_ops);
-+}
- #else
- #define dev_proc_init() 0
- #endif        /* CONFIG_PROC_FS */
-@@ -2691,10 +2807,10 @@
- /*
-  *    Perform the SIOCxIFxxx calls.
-  */
--static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
-+static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
- {
-       int err;
--      struct net_device *dev = __dev_get_by_name(ifr->ifr_name);
-+      struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
-       if (!dev)
-               return -ENODEV;
-@@ -2847,7 +2963,7 @@
-  *    positive or a negative errno code on error.
-  */
--int dev_ioctl(unsigned int cmd, void __user *arg)
-+int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
- {
-       struct ifreq ifr;
-       int ret;
-@@ -2860,12 +2976,12 @@
-       if (cmd == SIOCGIFCONF) {
-               rtnl_lock();
--              ret = dev_ifconf((char __user *) arg);
-+              ret = dev_ifconf(net, (char __user *) arg);
-               rtnl_unlock();
-               return ret;
-       }
-       if (cmd == SIOCGIFNAME)
--              return dev_ifname((struct ifreq __user *)arg);
-+              return dev_ifname(net, (struct ifreq __user *)arg);
-       if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
-               return -EFAULT;
-@@ -2895,9 +3011,9 @@
-               case SIOCGIFMAP:
-               case SIOCGIFINDEX:
-               case SIOCGIFTXQLEN:
--                      dev_load(ifr.ifr_name);
-+                      dev_load(net, ifr.ifr_name);
-                       read_lock(&dev_base_lock);
--                      ret = dev_ifsioc(&ifr, cmd);
-+                      ret = dev_ifsioc(net, &ifr, cmd);
-                       read_unlock(&dev_base_lock);
-                       if (!ret) {
-                               if (colon)
-@@ -2909,9 +3025,9 @@
-                       return ret;
-               case SIOCETHTOOL:
--                      dev_load(ifr.ifr_name);
-+                      dev_load(net, ifr.ifr_name);
-                       rtnl_lock();
--                      ret = dev_ethtool(&ifr);
-+                      ret = dev_ethtool(net, &ifr);
-                       rtnl_unlock();
-                       if (!ret) {
-                               if (colon)
-@@ -2933,9 +3049,9 @@
-               case SIOCSIFNAME:
-                       if (!capable(CAP_NET_ADMIN))
-                               return -EPERM;
--                      dev_load(ifr.ifr_name);
-+                      dev_load(net, ifr.ifr_name);
-                       rtnl_lock();
--                      ret = dev_ifsioc(&ifr, cmd);
-+                      ret = dev_ifsioc(net, &ifr, cmd);
-                       rtnl_unlock();
-                       if (!ret) {
-                               if (colon)
-@@ -2974,9 +3090,9 @@
-                       /* fall through */
-               case SIOCBONDSLAVEINFOQUERY:
-               case SIOCBONDINFOQUERY:
--                      dev_load(ifr.ifr_name);
-+                      dev_load(net, ifr.ifr_name);
-                       rtnl_lock();
--                      ret = dev_ifsioc(&ifr, cmd);
-+                      ret = dev_ifsioc(net, &ifr, cmd);
-                       rtnl_unlock();
-                       return ret;
-@@ -2996,9 +3112,9 @@
-                       if (cmd == SIOCWANDEV ||
-                           (cmd >= SIOCDEVPRIVATE &&
-                            cmd <= SIOCDEVPRIVATE + 15)) {
--                              dev_load(ifr.ifr_name);
-+                              dev_load(net, ifr.ifr_name);
-                               rtnl_lock();
--                              ret = dev_ifsioc(&ifr, cmd);
-+                              ret = dev_ifsioc(net, &ifr, cmd);
-                               rtnl_unlock();
-                               if (!ret && copy_to_user(arg, &ifr,
-                                                        sizeof(struct ifreq)))
-@@ -3007,7 +3123,7 @@
-                       }
-                       /* Take care of Wireless Extensions */
-                       if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
--                              return wext_handle_ioctl(&ifr, cmd, arg);
-+                              return wext_handle_ioctl(net, &ifr, cmd, arg);
-                       return -EINVAL;
-       }
- }
-@@ -3020,19 +3136,17 @@
-  *    number.  The caller must hold the rtnl semaphore or the
-  *    dev_base_lock to be sure it remains unique.
-  */
--static int dev_new_index(void)
-+static int dev_new_index(struct net *net)
- {
-       static int ifindex;
-       for (;;) {
-               if (++ifindex <= 0)
-                       ifindex = 1;
--              if (!__dev_get_by_index(ifindex))
-+              if (!__dev_get_by_index(net, ifindex))
-                       return ifindex;
-       }
- }
--static int dev_boot_phase = 1;
+-static int gdb_register_sysrq(void)
+-{
+-      printk("Registering GDB sysrq handler\n");
+-      register_sysrq_key('g', &sysrq_gdb_op);
+-      return 0;
+-}
 -
- /* Delayed registration/unregisteration */
- static DEFINE_SPINLOCK(net_todo_list_lock);
- static struct list_head net_todo_list = LIST_HEAD_INIT(net_todo_list);
-@@ -3066,6 +3180,7 @@
-       struct hlist_head *head;
-       struct hlist_node *p;
-       int ret;
-+      struct net *net;
-       BUG_ON(dev_boot_phase);
-       ASSERT_RTNL();
-@@ -3074,6 +3189,8 @@
-       /* When net_device's are persistent, this will be fatal. */
-       BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
-+      BUG_ON(!dev->nd_net);
-+      net = dev->nd_net;
-       spin_lock_init(&dev->queue_lock);
-       spin_lock_init(&dev->_xmit_lock);
-@@ -3098,12 +3215,12 @@
-               goto out;
-       }
--      dev->ifindex = dev_new_index();
-+      dev->ifindex = dev_new_index(net);
-       if (dev->iflink == -1)
-               dev->iflink = dev->ifindex;
-       /* Check for existence of name */
--      head = dev_name_hash(dev->name);
-+      head = dev_name_hash(net, dev->name);
-       hlist_for_each(p, head) {
-               struct net_device *d
-                       = hlist_entry(p, struct net_device, name_hlist);
-@@ -3113,6 +3230,22 @@
-               }
-       }
-+      /* Fix illegal checksum combinations */
-+      if ((dev->features & NETIF_F_HW_CSUM) &&
-+          (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
-+              printk(KERN_NOTICE "%s: mixed HW and IP checksum settings.\n",
-+                     dev->name);
-+              dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
-+      }
-+
-+      if ((dev->features & NETIF_F_NO_CSUM) &&
-+          (dev->features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
-+              printk(KERN_NOTICE "%s: mixed no checksumming and other settings.\n",
-+                     dev->name);
-+              dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
-+      }
-+
-+
-       /* Fix illegal SG+CSUM combinations. */
-       if ((dev->features & NETIF_F_SG) &&
-           !(dev->features & NETIF_F_ALL_CSUM)) {
-@@ -3164,12 +3297,8 @@
-       set_bit(__LINK_STATE_PRESENT, &dev->state);
-       dev_init_scheduler(dev);
--      write_lock_bh(&dev_base_lock);
--      list_add_tail(&dev->dev_list, &dev_base_head);
--      hlist_add_head(&dev->name_hlist, head);
--      hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex));
-       dev_hold(dev);
--      write_unlock_bh(&dev_base_lock);
-+      list_netdevice(dev);
-       /* Notify protocols, that a new device appeared. */
-       raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
-@@ -3379,6 +3508,7 @@
-       dev = (struct net_device *)
-               (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
-       dev->padded = (char *)dev - (char *)p;
-+      dev->nd_net = &init_net;
-       if (sizeof_priv)
-               dev->priv = netdev_priv(dev);
-@@ -3457,11 +3587,7 @@
-               dev_close(dev);
-       /* And unlink it from device chain. */
--      write_lock_bh(&dev_base_lock);
--      list_del(&dev->dev_list);
--      hlist_del(&dev->name_hlist);
--      hlist_del(&dev->index_hlist);
--      write_unlock_bh(&dev_base_lock);
-+      unlist_netdevice(dev);
-       dev->reg_state = NETREG_UNREGISTERING;
-@@ -3519,6 +3645,122 @@
- EXPORT_SYMBOL(unregister_netdev);
-+/**
-+ *    dev_change_net_namespace - move device to different nethost namespace
-+ *    @dev: device
-+ *    @net: network namespace
-+ *    @pat: If not NULL name pattern to try if the current device name
-+ *          is already taken in the destination network namespace.
-+ *
-+ *    This function shuts down a device interface and moves it
-+ *    to a new network namespace. On success 0 is returned, on
-+ *    a failure a netagive errno code is returned.
-+ *
-+ *    Callers must hold the rtnl semaphore.
-+ */
-+
-+int dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat)
-+{
-+      char buf[IFNAMSIZ];
-+      const char *destname;
-+      int err;
-+
-+      ASSERT_RTNL();
-+
-+      /* Don't allow namespace local devices to be moved. */
-+      err = -EINVAL;
-+      if (dev->features & NETIF_F_NETNS_LOCAL)
-+              goto out;
-+
-+      /* Ensure the device has been registrered */
-+      err = -EINVAL;
-+      if (dev->reg_state != NETREG_REGISTERED)
-+              goto out;
-+      
-+      /* Get out if there is nothing todo */
-+      err = 0;
-+      if (dev->nd_net == net)
-+              goto out;
-+
-+      /* Pick the destination device name, and ensure
-+       * we can use it in the destination network namespace.
-+       */
-+      err = -EEXIST;
-+      destname = dev->name;
-+      if (__dev_get_by_name(net, destname)) {
-+              /* We get here if we can't use the current device name */
-+              if (!pat)
-+                      goto out;
-+              if (!dev_valid_name(pat))
-+                      goto out;
-+              if (strchr(pat, '%')) {
-+                      if (__dev_alloc_name(net, pat, buf) < 0)
-+                              goto out;
-+                      destname = buf;
-+              } else
-+                      destname = pat;
-+              if (__dev_get_by_name(net, destname))
-+                      goto out;
-+      }
-+
-+      /*
-+       * And now a mini version of register_netdevice unregister_netdevice. 
-+       */
-+
-+      /* If device is running close it first. */
-+      if (dev->flags & IFF_UP)
-+              dev_close(dev);
-+
-+      /* And unlink it from device chain */
-+      err = -ENODEV;
-+      unlist_netdevice(dev);
-+      
-+      synchronize_net();
-+      
-+      /* Shutdown queueing discipline. */
-+      dev_shutdown(dev);
-+
-+      /* Notify protocols, that we are about to destroy
-+         this device. They should clean all the things.
-+      */
-+      call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
-+      
-+      /*
-+       *      Flush the multicast chain
-+       */
-+      dev_mc_discard(dev);
-+
-+      /* Actually switch the network namespace */
-+      dev->nd_net = net;
-+      
-+      /* Assign the new device name */
-+      if (destname != dev->name)
-+              strcpy(dev->name, destname);
-+
-+      /* If there is an ifindex conflict assign a new one */
-+      if (__dev_get_by_index(net, dev->ifindex)) {
-+              int iflink = (dev->iflink == dev->ifindex);
-+              dev->ifindex = dev_new_index(net);
-+              if (iflink)
-+                      dev->iflink = dev->ifindex;
-+      }
-+
-+      /* Fixup sysfs */
-+      err = device_rename(&dev->dev, dev->name);
-+      BUG_ON(err);
-+
-+      /* Add the device back in the hashes */
-+      list_netdevice(dev);
-+
-+      /* Notify protocols, that a new device appeared. */
-+      call_netdevice_notifiers(NETDEV_REGISTER, dev);
-+
-+      synchronize_net();
-+      err = 0;
-+out:
-+      return err;
-+}
-+
- static int dev_cpu_callback(struct notifier_block *nfb,
-                           unsigned long action,
-                           void *ocpu)
-@@ -3569,12 +3811,13 @@
-  * This is called when the number of channels allocated to the net_dma_client
-  * changes.  The net_dma_client tries to have one DMA channel per CPU.
-  */
--static void net_dma_rebalance(void)
-+
-+static void net_dma_rebalance(struct net_dma *net_dma)
- {
--      unsigned int cpu, i, n;
-+      unsigned int cpu, i, n, chan_idx;
-       struct dma_chan *chan;
--      if (net_dma_count == 0) {
-+      if (cpus_empty(net_dma->channel_mask)) {
-               for_each_online_cpu(cpu)
-                       rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL);
-               return;
-@@ -3583,10 +3826,12 @@
-       i = 0;
-       cpu = first_cpu(cpu_online_map);
--      rcu_read_lock();
--      list_for_each_entry(chan, &net_dma_client->channels, client_node) {
--              n = ((num_online_cpus() / net_dma_count)
--                 + (i < (num_online_cpus() % net_dma_count) ? 1 : 0));
-+      for_each_cpu_mask(chan_idx, net_dma->channel_mask) {
-+              chan = net_dma->channels[chan_idx];
-+
-+              n = ((num_online_cpus() / cpus_weight(net_dma->channel_mask))
-+                 + (i < (num_online_cpus() %
-+                      cpus_weight(net_dma->channel_mask)) ? 1 : 0));
-               while(n) {
-                       per_cpu(softnet_data, cpu).net_dma = chan;
-@@ -3595,7 +3840,6 @@
-               }
-               i++;
-       }
--      rcu_read_unlock();
- }
- /**
-@@ -3604,23 +3848,53 @@
-  * @chan: DMA channel for the event
-  * @event: event type
-  */
--static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
--      enum dma_event event)
--{
--      spin_lock(&net_dma_event_lock);
--      switch (event) {
--      case DMA_RESOURCE_ADDED:
--              net_dma_count++;
--              net_dma_rebalance();
-+static enum dma_state_client
-+netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
-+      enum dma_state state)
-+{
-+      int i, found = 0, pos = -1;
-+      struct net_dma *net_dma =
-+              container_of(client, struct net_dma, client);
-+      enum dma_state_client ack = DMA_DUP; /* default: take no action */
-+
-+      spin_lock(&net_dma->lock);
-+      switch (state) {
-+      case DMA_RESOURCE_AVAILABLE:
-+              for (i = 0; i < NR_CPUS; i++)
-+                      if (net_dma->channels[i] == chan) {
-+                              found = 1;
-+                              break;
-+                      } else if (net_dma->channels[i] == NULL && pos < 0)
-+                              pos = i;
-+
-+              if (!found && pos >= 0) {
-+                      ack = DMA_ACK;
-+                      net_dma->channels[pos] = chan;
-+                      cpu_set(pos, net_dma->channel_mask);
-+                      net_dma_rebalance(net_dma);
-+              }
-               break;
-       case DMA_RESOURCE_REMOVED:
--              net_dma_count--;
--              net_dma_rebalance();
-+              for (i = 0; i < NR_CPUS; i++)
-+                      if (net_dma->channels[i] == chan) {
-+                              found = 1;
-+                              pos = i;
-+                              break;
-+                      }
-+
-+              if (found) {
-+                      ack = DMA_ACK;
-+                      cpu_clear(pos, net_dma->channel_mask);
-+                      net_dma->channels[i] = NULL;
-+                      net_dma_rebalance(net_dma);
-+              }
-               break;
-       default:
-               break;
-       }
--      spin_unlock(&net_dma_event_lock);
-+      spin_unlock(&net_dma->lock);
-+
-+      return ack;
- }
- /**
-@@ -3628,12 +3902,10 @@
-  */
- static int __init netdev_dma_register(void)
- {
--      spin_lock_init(&net_dma_event_lock);
--      net_dma_client = dma_async_client_register(netdev_dma_event);
--      if (net_dma_client == NULL)
--              return -ENOMEM;
+-module_init(gdb_register_sysrq);
+-#endif
 -
--      dma_async_client_chan_request(net_dma_client, num_online_cpus());
-+      spin_lock_init(&net_dma.lock);
-+      dma_cap_set(DMA_MEMCPY, net_dma.client.cap_mask);
-+      dma_async_client_register(&net_dma.client);
-+      dma_async_client_chan_request(&net_dma.client);
-       return 0;
- }
-@@ -3679,6 +3951,75 @@
- }
- EXPORT_SYMBOL(netdev_compute_features);
-+/* Initialize per network namespace state */
-+static int netdev_init(struct net *net)
-+{
-+      int i;
-+      INIT_LIST_HEAD(&net->dev_base_head);
-+      rwlock_init(&dev_base_lock);
-+
-+      net->dev_name_head = kmalloc(
-+              sizeof(*net->dev_name_head)*NETDEV_HASHENTRIES, GFP_KERNEL);
-+      if (!net->dev_name_head)
-+              return -ENOMEM;
-+
-+      net->dev_index_head = kmalloc(
-+              sizeof(*net->dev_index_head)*NETDEV_HASHENTRIES, GFP_KERNEL);
-+      if (!net->dev_index_head) {
-+              kfree(net->dev_name_head);
-+              return -ENOMEM;
-+      }
-+
-+      for (i = 0; i < NETDEV_HASHENTRIES; i++)
-+              INIT_HLIST_HEAD(&net->dev_name_head[i]);
-+      
-+      for (i = 0; i < NETDEV_HASHENTRIES; i++)
-+              INIT_HLIST_HEAD(&net->dev_index_head[i]);
-+
-+      return 0;
-+}
-+
-+static void netdev_exit(struct net *net)
-+{
-+      kfree(net->dev_name_head);
-+      kfree(net->dev_index_head);
-+}
-+
-+static struct pernet_operations netdev_net_ops = {
-+      .init = netdev_init,
-+      .exit = netdev_exit,
-+};
-+
-+static void default_device_exit(struct net *net)
-+{
-+      struct net_device *dev, *next;
-+      /*
-+       * Push all migratable of the network devices back to the
-+       * initial network namespace 
-+       */
-+      rtnl_lock();
-+      for_each_netdev_safe(net, dev, next) {
-+              int err;
-+
-+              /* Ignore unmoveable devices (i.e. loopback) */
-+              if (dev->features & NETIF_F_NETNS_LOCAL)
-+                      continue;
-+
-+              /* Push remaing network devices to init_net */
-+              err = dev_change_net_namespace(dev, &init_net, "dev%d");
-+              if (err) {
-+                      printk(KERN_WARNING "%s: failed to move %s to init_net: %d\n",
-+                              __func__, dev->name, err);
-+                      unregister_netdevice(dev);
-+              }
-+      }
-+      rtnl_unlock();
-+}
-+
-+static struct pernet_operations default_device_ops = {
-+      .exit = default_device_exit,
-+};
-+
- /*
-  *    Initialize the DEV module. At boot time this walks the device list and
-  *    unhooks any devices that fail to initialise (normally hardware not
-@@ -3706,11 +4047,11 @@
-       for (i = 0; i < 16; i++)
-               INIT_LIST_HEAD(&ptype_base[i]);
--      for (i = 0; i < ARRAY_SIZE(dev_name_head); i++)
--              INIT_HLIST_HEAD(&dev_name_head[i]);
-+      if (register_pernet_subsys(&netdev_net_ops))
-+              goto out;
--      for (i = 0; i < ARRAY_SIZE(dev_index_head); i++)
--              INIT_HLIST_HEAD(&dev_index_head[i]);
-+      if (register_pernet_device(&default_device_ops))
-+              goto out;
-       /*
-        *      Initialise the packet receive queues.
-diff -Nurb linux-2.6.22-570/net/core/dev_mcast.c linux-2.6.22-590/net/core/dev_mcast.c
---- linux-2.6.22-570/net/core/dev_mcast.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/core/dev_mcast.c      2008-01-02 13:56:38.000000000 -0500
-@@ -46,6 +46,7 @@
- #include <linux/skbuff.h>
- #include <net/sock.h>
- #include <net/arp.h>
-+#include <net/net_namespace.h>
- /*
-@@ -219,11 +220,12 @@
- #ifdef CONFIG_PROC_FS
- static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)
- {
-+      struct net *net = seq->private;
-       struct net_device *dev;
-       loff_t off = 0;
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(net, dev) {
-               if (off++ == *pos)
-                       return dev;
-       }
-@@ -272,7 +274,22 @@
- static int dev_mc_seq_open(struct inode *inode, struct file *file)
- {
--      return seq_open(file, &dev_mc_seq_ops);
-+      struct seq_file *seq;
-+      int res;
-+      res = seq_open(file, &dev_mc_seq_ops);
-+      if (!res) {
-+              seq = file->private_data;
-+              seq->private = get_net(PROC_NET(inode));
-+      }
-+      return res;
-+}
-+
-+static int dev_mc_seq_release(struct inode *inode, struct file *file)
-+{
-+      struct seq_file *seq = file->private_data;
-+      struct net *net = seq->private;
-+      put_net(net);
-+      return seq_release(inode, file);
- }
- static const struct file_operations dev_mc_seq_fops = {
-@@ -280,14 +297,31 @@
-       .open    = dev_mc_seq_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
--      .release = seq_release,
-+      .release = dev_mc_seq_release,
- };
- #endif
-+static int dev_mc_net_init(struct net *net)
-+{
-+      if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops))
-+              return -ENOMEM;
-+      return 0;
-+}
-+
-+static void dev_mc_net_exit(struct net *net)
-+{
-+      proc_net_remove(net, "dev_mcast");
-+}
-+
-+static struct pernet_operations dev_mc_net_ops = {
-+      .init = dev_mc_net_init,
-+      .exit = dev_mc_net_exit,
-+};
-+
- void __init dev_mcast_init(void)
- {
--      proc_net_fops_create("dev_mcast", 0, &dev_mc_seq_fops);
-+      register_pernet_subsys(&dev_mc_net_ops);
- }
- EXPORT_SYMBOL(dev_mc_add);
-diff -Nurb linux-2.6.22-570/net/core/dst.c linux-2.6.22-590/net/core/dst.c
---- linux-2.6.22-570/net/core/dst.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/core/dst.c    2008-01-02 13:56:38.000000000 -0500
-@@ -15,7 +15,9 @@
- #include <linux/skbuff.h>
- #include <linux/string.h>
- #include <linux/types.h>
-+#include <net/net_namespace.h>
-+#include <net/net_namespace.h>
- #include <net/dst.h>
- /* Locking strategy:
-@@ -236,13 +238,14 @@
-       if (!unregister) {
-               dst->input = dst->output = dst_discard;
-       } else {
--              dst->dev = &loopback_dev;
--              dev_hold(&loopback_dev);
-+              struct net *net = dev->nd_net;
-+              dst->dev = &net->loopback_dev;
-+              dev_hold(dst->dev);
-               dev_put(dev);
-               if (dst->neighbour && dst->neighbour->dev == dev) {
--                      dst->neighbour->dev = &loopback_dev;
-+                      dst->neighbour->dev = &net->loopback_dev;
-                       dev_put(dev);
--                      dev_hold(&loopback_dev);
-+                      dev_hold(dst->neighbour->dev);
-               }
-       }
- }
-@@ -252,6 +255,9 @@
-       struct net_device *dev = ptr;
-       struct dst_entry *dst;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       switch (event) {
-       case NETDEV_UNREGISTER:
-       case NETDEV_DOWN:
-diff -Nurb linux-2.6.22-570/net/core/ethtool.c linux-2.6.22-590/net/core/ethtool.c
---- linux-2.6.22-570/net/core/ethtool.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/core/ethtool.c        2008-01-02 13:56:38.000000000 -0500
-@@ -798,9 +798,9 @@
- /* The main entry point in this file.  Called from net/core/dev.c */
--int dev_ethtool(struct ifreq *ifr)
-+int dev_ethtool(struct net *net, struct ifreq *ifr)
- {
--      struct net_device *dev = __dev_get_by_name(ifr->ifr_name);
-+      struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
-       void __user *useraddr = ifr->ifr_data;
-       u32 ethcmd;
-       int rc;
-diff -Nurb linux-2.6.22-570/net/core/fib_rules.c linux-2.6.22-590/net/core/fib_rules.c
---- linux-2.6.22-570/net/core/fib_rules.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/core/fib_rules.c      2008-01-02 13:56:38.000000000 -0500
-@@ -11,21 +11,20 @@
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/list.h>
-+#include <net/net_namespace.h>
-+#include <net/sock.h>
- #include <net/fib_rules.h>
--static LIST_HEAD(rules_ops);
--static DEFINE_SPINLOCK(rules_mod_lock);
+-static int kgdb_notify_reboot(struct notifier_block *this,
+-                            unsigned long code, void *x)
+-{
 -
--static void notify_rule_change(int event, struct fib_rule *rule,
-+static void notify_rule_change(struct net *net, int event, struct fib_rule *rule,
-                              struct fib_rules_ops *ops, struct nlmsghdr *nlh,
-                              u32 pid);
--static struct fib_rules_ops *lookup_rules_ops(int family)
-+static struct fib_rules_ops *lookup_rules_ops(struct net *net, int family)
- {
-       struct fib_rules_ops *ops;
-       rcu_read_lock();
--      list_for_each_entry_rcu(ops, &rules_ops, list) {
-+      list_for_each_entry_rcu(ops, &net->rules_ops, list) {
-               if (ops->family == family) {
-                       if (!try_module_get(ops->owner))
-                               ops = NULL;
-@@ -47,10 +46,10 @@
- static void flush_route_cache(struct fib_rules_ops *ops)
- {
-       if (ops->flush_cache)
--              ops->flush_cache();
-+              ops->flush_cache(ops);
- }
--int fib_rules_register(struct fib_rules_ops *ops)
-+int fib_rules_register(struct net *net, struct fib_rules_ops *ops)
- {
-       int err = -EEXIST;
-       struct fib_rules_ops *o;
-@@ -63,15 +62,16 @@
-           ops->action == NULL)
-               return -EINVAL;
--      spin_lock(&rules_mod_lock);
--      list_for_each_entry(o, &rules_ops, list)
-+      spin_lock(&net->rules_mod_lock);
-+      list_for_each_entry(o, &net->rules_ops, list)
-               if (ops->family == o->family)
-                       goto errout;
--      list_add_tail_rcu(&ops->list, &rules_ops);
-+      hold_net(net);
-+      list_add_tail_rcu(&ops->list, &net->rules_ops);
-       err = 0;
- errout:
--      spin_unlock(&rules_mod_lock);
-+      spin_unlock(&net->rules_mod_lock);
-       return err;
- }
-@@ -88,13 +88,13 @@
-       }
- }
--int fib_rules_unregister(struct fib_rules_ops *ops)
-+int fib_rules_unregister(struct net *net, struct fib_rules_ops *ops)
- {
-       int err = 0;
-       struct fib_rules_ops *o;
--      spin_lock(&rules_mod_lock);
--      list_for_each_entry(o, &rules_ops, list) {
-+      spin_lock(&net->rules_mod_lock);
-+      list_for_each_entry(o, &net->rules_ops, list) {
-               if (o == ops) {
-                       list_del_rcu(&o->list);
-                       cleanup_ops(ops);
-@@ -104,9 +104,11 @@
-       err = -ENOENT;
- out:
--      spin_unlock(&rules_mod_lock);
-+      spin_unlock(&net->rules_mod_lock);
-       synchronize_rcu();
-+      if (!err)
-+              release_net(net);
+-      unsigned long flags;
+-
+-      /* If we're debugging, or KGDB has not connected, don't try
+-       * and print. */
+-      if (!kgdb_connected || atomic_read(&debugger_active) != 0)
+-              return 0;
+-      if ((code == SYS_RESTART) || (code == SYS_HALT) || (code == SYS_POWER_OFF)){
+-              local_irq_save(flags);
+-              put_packet("X00");
+-              local_irq_restore(flags);
+-      }
+-      return NOTIFY_DONE;
+-}
+-
+-#ifdef CONFIG_KGDB_CONSOLE
+-void kgdb_console_write(struct console *co, const char *s, unsigned count)
+-{
+-      unsigned long flags;
+-
+-      /* If we're debugging, or KGDB has not connected, don't try
+-       * and print. */
+-      if (!kgdb_connected || atomic_read(&debugger_active) != 0)
+-              return;
+-
+-      local_irq_save(flags);
+-      kgdb_msg_write(s, count);
+-      local_irq_restore(flags);
+-}
+-
+-struct console kgdbcons = {
+-      .name = "kgdb",
+-      .write = kgdb_console_write,
+-      .flags = CON_PRINTBUFFER | CON_ENABLED,
+-};
+-static int __init kgdb_console_init(void)
+-{
+-      register_console(&kgdbcons);
+-      return 0;
+-}
+-
+-console_initcall(kgdb_console_init);
+-#endif
+-
+-static int __init opt_kgdb_enter(char *str)
+-{
+-      /* We've already done this by an explicit breakpoint() call. */
+-      if (kgdb_initialized)
+-              return 0;
+-
+-      kgdb_early_entry();
+-      if (kgdb_initialized == 1)
+-              printk(KERN_CRIT "Waiting for connection from remote "
+-                     "gdb...\n");
+-      else {
+-              printk(KERN_CRIT "KGDB cannot initialize I/O yet.\n");
+-              return 0;
+-      }
+-
+-      breakpoint();
+-
+-      return 0;
+-}
+-
+-early_param("kgdbwait", opt_kgdb_enter);
+diff -Nurb linux-2.6.22-590/kernel/kmod.c linux-2.6.22-570/kernel/kmod.c
+--- linux-2.6.22-590/kernel/kmod.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/kmod.c     2007-07-08 19:32:17.000000000 -0400
+@@ -119,10 +119,9 @@
+       char **argv;
+       char **envp;
+       struct key *ring;
+-      enum umh_wait wait;
++      int wait;
+       int retval;
+       struct file *stdin;
+-      void (*cleanup)(char **argv, char **envp);
+ };
  
-       return err;
+ /*
+@@ -181,14 +180,6 @@
+       do_exit(0);
  }
-@@ -197,6 +199,7 @@
  
- static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+-void call_usermodehelper_freeinfo(struct subprocess_info *info)
+-{
+-      if (info->cleanup)
+-              (*info->cleanup)(info->argv, info->envp);
+-      kfree(info);
+-}
+-EXPORT_SYMBOL(call_usermodehelper_freeinfo);
+-
+ /* Keventd can't block, but this (a child) can. */
+ static int wait_for_helper(void *data)
  {
-+      struct net *net = skb->sk->sk_net;
-       struct fib_rule_hdr *frh = nlmsg_data(nlh);
-       struct fib_rules_ops *ops = NULL;
-       struct fib_rule *rule, *r, *last = NULL;
-@@ -206,7 +209,7 @@
-       if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
-               goto errout;
--      ops = lookup_rules_ops(frh->family);
-+      ops = lookup_rules_ops(net, frh->family);
-       if (ops == NULL) {
-               err = EAFNOSUPPORT;
-               goto errout;
-@@ -234,7 +237,7 @@
-               rule->ifindex = -1;
-               nla_strlcpy(rule->ifname, tb[FRA_IFNAME], IFNAMSIZ);
--              dev = __dev_get_by_name(rule->ifname);
-+              dev = __dev_get_by_name(net, rule->ifname);
-               if (dev)
-                       rule->ifindex = dev->ifindex;
+@@ -225,8 +216,8 @@
+                       sub_info->retval = ret;
        }
-@@ -256,7 +259,7 @@
-       rule->table = frh_get_table(frh, tb);
-       if (!rule->pref && ops->default_pref)
--              rule->pref = ops->default_pref();
-+              rule->pref = ops->default_pref(ops);
  
-       err = -EINVAL;
-       if (tb[FRA_GOTO]) {
-@@ -319,7 +322,7 @@
+-      if (sub_info->wait == UMH_NO_WAIT)
+-              call_usermodehelper_freeinfo(sub_info);
++      if (sub_info->wait < 0)
++              kfree(sub_info);
        else
-               list_add_rcu(&rule->list, ops->rules_list);
--      notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid);
-+      notify_rule_change(net, RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid);
-       flush_route_cache(ops);
-       rules_ops_put(ops);
+               complete(sub_info->complete);
        return 0;
-@@ -333,6 +336,7 @@
- static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct fib_rule_hdr *frh = nlmsg_data(nlh);
-       struct fib_rules_ops *ops = NULL;
-       struct fib_rule *rule, *tmp;
-@@ -342,7 +346,7 @@
-       if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
-               goto errout;
--      ops = lookup_rules_ops(frh->family);
-+      ops = lookup_rules_ops(net, frh->family);
-       if (ops == NULL) {
-               err = EAFNOSUPPORT;
-               goto errout;
-@@ -408,7 +412,7 @@
-               }
-               synchronize_rcu();
--              notify_rule_change(RTM_DELRULE, rule, ops, nlh,
-+              notify_rule_change(net, RTM_DELRULE, rule, ops, nlh,
-                                  NETLINK_CB(skb).pid);
-               fib_rule_put(rule);
-               flush_route_cache(ops);
-@@ -514,13 +518,17 @@
- static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct fib_rules_ops *ops;
-       int idx = 0, family;
-+      if (net != &init_net)
-+              return -EINVAL;
-+
-       family = rtnl_msg_family(cb->nlh);
-       if (family != AF_UNSPEC) {
-               /* Protocol specific dump request */
--              ops = lookup_rules_ops(family);
-+              ops = lookup_rules_ops(net, family);
-               if (ops == NULL)
-                       return -EAFNOSUPPORT;
-@@ -528,7 +536,7 @@
-       }
+@@ -238,122 +229,34 @@
+       struct subprocess_info *sub_info =
+               container_of(work, struct subprocess_info, work);
+       pid_t pid;
+-      enum umh_wait wait = sub_info->wait;
++      int wait = sub_info->wait;
  
-       rcu_read_lock();
--      list_for_each_entry_rcu(ops, &rules_ops, list) {
-+      list_for_each_entry_rcu(ops, &net->rules_ops, list) {
-               if (idx < cb->args[0] || !try_module_get(ops->owner))
-                       goto skip;
+       /* CLONE_VFORK: wait until the usermode helper has execve'd
+        * successfully We need the data structures to stay around
+        * until that is done.  */
+-      if (wait == UMH_WAIT_PROC)
++      if (wait)
+               pid = kernel_thread(wait_for_helper, sub_info,
+                                   CLONE_FS | CLONE_FILES | SIGCHLD);
+       else
+               pid = kernel_thread(____call_usermodehelper, sub_info,
+                                   CLONE_VFORK | SIGCHLD);
  
-@@ -545,7 +553,7 @@
-       return skb->len;
- }
+-      switch(wait) {
+-      case UMH_NO_WAIT:
+-              break;
+-
+-      case UMH_WAIT_PROC:
+-              if (pid > 0)
+-                      break;
+-              sub_info->retval = pid;
+-              /* FALLTHROUGH */
++      if (wait < 0)
++              return;
  
--static void notify_rule_change(int event, struct fib_rule *rule,
-+static void notify_rule_change(struct net *net, int event, struct fib_rule *rule,
-                              struct fib_rules_ops *ops, struct nlmsghdr *nlh,
-                              u32 pid)
- {
-@@ -563,10 +571,10 @@
-               kfree_skb(skb);
-               goto errout;
-       }
--      err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
-+      err = rtnl_notify(skb, net, pid, ops->nlgroup, nlh, GFP_KERNEL);
- errout:
-       if (err < 0)
--              rtnl_set_sk_err(ops->nlgroup, err);
-+              rtnl_set_sk_err(net, ops->nlgroup, err);
+-      case UMH_WAIT_EXEC:
++      if (pid < 0) {
++              sub_info->retval = pid;
++              complete(sub_info->complete);
++      } else if (!wait)
+               complete(sub_info->complete);
+-      }
+-}
+-
+-/**
+- * call_usermodehelper_setup - prepare to call a usermode helper
+- * @path - path to usermode executable
+- * @argv - arg vector for process
+- * @envp - environment for process
+- *
+- * Returns either NULL on allocation failure, or a subprocess_info
+- * structure.  This should be passed to call_usermodehelper_exec to
+- * exec the process and free the structure.
+- */
+-struct subprocess_info *call_usermodehelper_setup(char *path,
+-                                                char **argv, char **envp)
+-{
+-      struct subprocess_info *sub_info;
+-      sub_info = kzalloc(sizeof(struct subprocess_info),  GFP_ATOMIC);
+-      if (!sub_info)
+-              goto out;
+-
+-      INIT_WORK(&sub_info->work, __call_usermodehelper);
+-      sub_info->path = path;
+-      sub_info->argv = argv;
+-      sub_info->envp = envp;
+-
+-  out:
+-      return sub_info;
+-}
+-EXPORT_SYMBOL(call_usermodehelper_setup);
+-
+-/**
+- * call_usermodehelper_setkeys - set the session keys for usermode helper
+- * @info: a subprocess_info returned by call_usermodehelper_setup
+- * @session_keyring: the session keyring for the process
+- */
+-void call_usermodehelper_setkeys(struct subprocess_info *info,
+-                               struct key *session_keyring)
+-{
+-      info->ring = session_keyring;
+-}
+-EXPORT_SYMBOL(call_usermodehelper_setkeys);
+-
+-/**
+- * call_usermodehelper_setcleanup - set a cleanup function
+- * @info: a subprocess_info returned by call_usermodehelper_setup
+- * @cleanup: a cleanup function
+- *
+- * The cleanup function is just befor ethe subprocess_info is about to
+- * be freed.  This can be used for freeing the argv and envp.  The
+- * Function must be runnable in either a process context or the
+- * context in which call_usermodehelper_exec is called.
+- */
+-void call_usermodehelper_setcleanup(struct subprocess_info *info,
+-                                  void (*cleanup)(char **argv, char **envp))
+-{
+-      info->cleanup = cleanup;
+-}
+-EXPORT_SYMBOL(call_usermodehelper_setcleanup);
+-
+-/**
+- * call_usermodehelper_stdinpipe - set up a pipe to be used for stdin
+- * @sub_info: a subprocess_info returned by call_usermodehelper_setup
+- * @filp: set to the write-end of a pipe
+- *
+- * This constructs a pipe, and sets the read end to be the stdin of the
+- * subprocess, and returns the write-end in *@filp.
+- */
+-int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info,
+-                                struct file **filp)
+-{
+-      struct file *f;
+-
+-      f = create_write_pipe();
+-      if (IS_ERR(f))
+-              return PTR_ERR(f);
+-      *filp = f;
+-
+-      f = create_read_pipe(f);
+-      if (IS_ERR(f)) {
+-              free_write_pipe(*filp);
+-              return PTR_ERR(f);
+-      }
+-      sub_info->stdin = f;
+-
+-      return 0;
  }
+-EXPORT_SYMBOL(call_usermodehelper_stdinpipe);
  
- static void attach_rules(struct list_head *rules, struct net_device *dev)
-@@ -594,19 +602,23 @@
-                           void *ptr)
+ /**
+- * call_usermodehelper_exec - start a usermode application
+- * @sub_info: information about the subprocessa
++ * call_usermodehelper_keys - start a usermode application
++ * @path: pathname for the application
++ * @argv: null-terminated argument list
++ * @envp: null-terminated environment list
++ * @session_keyring: session keyring for process (NULL for an empty keyring)
+  * @wait: wait for the application to finish and return status.
+  *        when -1 don't wait at all, but you get no useful error back when
+  *        the program couldn't be exec'ed. This makes it safe to call
+@@ -362,68 +265,81 @@
+  * Runs a user-space application.  The application is started
+  * asynchronously if wait is not set, and runs as a child of keventd.
+  * (ie. it runs with full root capabilities).
++ *
++ * Must be called from process context.  Returns a negative error code
++ * if program was not execed successfully, or 0.
+  */
+-int call_usermodehelper_exec(struct subprocess_info *sub_info,
+-                           enum umh_wait wait)
++int call_usermodehelper_keys(char *path, char **argv, char **envp,
++                           struct key *session_keyring, int wait)
  {
-       struct net_device *dev = ptr;
-+      struct net *net = dev->nd_net;
-       struct fib_rules_ops *ops;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       ASSERT_RTNL();
-       rcu_read_lock();
+       DECLARE_COMPLETION_ONSTACK(done);
++      struct subprocess_info *sub_info;
+       int retval;
  
-       switch (event) {
-       case NETDEV_REGISTER:
--              list_for_each_entry(ops, &rules_ops, list)
-+              list_for_each_entry(ops, &net->rules_ops, list)
-                       attach_rules(ops->rules_list, dev);
-               break;
+-      if (sub_info->path[0] == '\0') {
+-              retval = 0;
+-              goto out;
+-      }
++      if (!khelper_wq)
++              return -EBUSY;
  
-       case NETDEV_UNREGISTER:
--              list_for_each_entry(ops, &rules_ops, list)
-+              list_for_each_entry(ops, &net->rules_ops, list)
-                       detach_rules(ops->rules_list, dev);
-               break;
-       }
-@@ -620,13 +632,28 @@
-       .notifier_call = fib_rules_event,
- };
+-      if (!khelper_wq) {
+-              retval = -EBUSY;
+-              goto out;
+-      }
++      if (path[0] == '\0')
++              return 0;
  
-+static int fib_rules_net_init(struct net *net)
-+{
-+      INIT_LIST_HEAD(&net->rules_ops);
-+      spin_lock_init(&net->rules_mod_lock);
-+      return 0;
-+}
-+
-+static struct pernet_operations fib_rules_net_ops = {
-+      .init = fib_rules_net_init,
-+};
++      sub_info = kzalloc(sizeof(struct subprocess_info),  GFP_ATOMIC);
++      if (!sub_info)
++              return -ENOMEM;
 +
- static int __init fib_rules_init(void)
- {
-+      int ret;
-       rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL);
-       rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL);
-       rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule);
--      return register_netdevice_notifier(&fib_rules_notifier);
-+      ret = register_pernet_subsys(&fib_rules_net_ops);
-+      if (!ret)
-+              ret = register_netdevice_notifier(&fib_rules_notifier);
-+      return ret;
- }
- subsys_initcall(fib_rules_init);
-diff -Nurb linux-2.6.22-570/net/core/neighbour.c linux-2.6.22-590/net/core/neighbour.c
---- linux-2.6.22-570/net/core/neighbour.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/core/neighbour.c      2008-01-02 13:56:38.000000000 -0500
-@@ -33,6 +33,7 @@
- #include <linux/rtnetlink.h>
- #include <linux/random.h>
- #include <linux/string.h>
-+#include <net/net_namespace.h>
- #define NEIGH_DEBUG 1
-@@ -361,7 +362,7 @@
-       return n;
- }
--struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, const void *pkey)
-+struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net * net, const void *pkey)
- {
-       struct neighbour *n;
-       int key_len = tbl->key_len;
-@@ -371,7 +372,8 @@
-       read_lock_bh(&tbl->lock);
-       for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
--              if (!memcmp(n->primary_key, pkey, key_len)) {
-+              if (!memcmp(n->primary_key, pkey, key_len) &&
-+                  (net == n->dev->nd_net)) {
-                       neigh_hold(n);
-                       NEIGH_CACHE_STAT_INC(tbl, hits);
-                       break;
-@@ -449,7 +451,8 @@
-       goto out;
- }
--struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey,
-+struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
-+                                  struct net * net, const void *pkey,
-                                   struct net_device *dev, int creat)
- {
-       struct pneigh_entry *n;
-@@ -465,6 +468,7 @@
-       for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
-               if (!memcmp(n->key, pkey, key_len) &&
-+                  (n->net == net) &&
-                   (n->dev == dev || !n->dev)) {
-                       read_unlock_bh(&tbl->lock);
-                       goto out;
-@@ -479,6 +483,7 @@
-       if (!n)
-               goto out;
-+      n->net = hold_net(net);
-       memcpy(n->key, pkey, key_len);
-       n->dev = dev;
-       if (dev)
-@@ -501,7 +506,7 @@
++      INIT_WORK(&sub_info->work, __call_usermodehelper);
+       sub_info->complete = &done;
++      sub_info->path = path;
++      sub_info->argv = argv;
++      sub_info->envp = envp;
++      sub_info->ring = session_keyring;
+       sub_info->wait = wait;
+       queue_work(khelper_wq, &sub_info->work);
+-      if (wait == UMH_NO_WAIT) /* task has freed sub_info */
++      if (wait < 0) /* task has freed sub_info */
+               return 0;
+       wait_for_completion(&done);
+       retval = sub_info->retval;
+-
+-  out:
+-      call_usermodehelper_freeinfo(sub_info);
++      kfree(sub_info);
+       return retval;
  }
+-EXPORT_SYMBOL(call_usermodehelper_exec);
++EXPORT_SYMBOL(call_usermodehelper_keys);
  
--int pneigh_delete(struct neigh_table *tbl, const void *pkey,
-+int pneigh_delete(struct neigh_table *tbl, struct net * net, const void *pkey,
-                 struct net_device *dev)
+-/**
+- * call_usermodehelper_pipe - call a usermode helper process with a pipe stdin
+- * @path: path to usermode executable
+- * @argv: arg vector for process
+- * @envp: environment for process
+- * @filp: set to the write-end of a pipe
+- *
+- * This is a simple wrapper which executes a usermode-helper function
+- * with a pipe as stdin.  It is implemented entirely in terms of
+- * lower-level call_usermodehelper_* functions.
+- */
+ int call_usermodehelper_pipe(char *path, char **argv, char **envp,
+                            struct file **filp)
  {
-       struct pneigh_entry *n, **np;
-@@ -516,13 +521,15 @@
-       write_lock_bh(&tbl->lock);
-       for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
-            np = &n->next) {
--              if (!memcmp(n->key, pkey, key_len) && n->dev == dev) {
-+              if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
-+                  (n->net == net)) {
-                       *np = n->next;
-                       write_unlock_bh(&tbl->lock);
-                       if (tbl->pdestructor)
-                               tbl->pdestructor(n);
-                       if (n->dev)
-                               dev_put(n->dev);
-+                      release_net(n->net);
-                       kfree(n);
-                       return 0;
-               }
-@@ -545,6 +552,7 @@
-                                       tbl->pdestructor(n);
-                               if (n->dev)
-                                       dev_put(n->dev);
-+                              release_net(n->net);
-                               kfree(n);
-                               continue;
-                       }
-@@ -1266,12 +1274,37 @@
-       spin_unlock(&tbl->proxy_queue.lock);
- }
-+static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
-+                                                    struct net * net, int ifindex)
-+{
-+      struct neigh_parms *p;
-+      
-+      for (p = &tbl->parms; p; p = p->next) {
-+              if (p->net != net)
-+                      continue;
-+              if ((p->dev && p->dev->ifindex == ifindex) ||
-+                  (!p->dev && !ifindex))
-+                      return p;
-+      }
-+
-+      return NULL;
-+}
+-      struct subprocess_info *sub_info;
+-      int ret;
++      DECLARE_COMPLETION(done);
++      struct subprocess_info sub_info = {
++              .work           = __WORK_INITIALIZER(sub_info.work,
++                                                   __call_usermodehelper),
++              .complete       = &done,
++              .path           = path,
++              .argv           = argv,
++              .envp           = envp,
++              .retval         = 0,
++      };
++      struct file *f;
  
- struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
-                                     struct neigh_table *tbl)
- {
--      struct neigh_parms *p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
-+      struct neigh_parms *p, *ref;
-+      struct net * net;
+-      sub_info = call_usermodehelper_setup(path, argv, envp);
+-      if (sub_info == NULL)
+-              return -ENOMEM;
++      if (!khelper_wq)
++              return -EBUSY;
 +
-+      net = &init_net;
-+      if (dev)
-+              net = dev->nd_net;
++      if (path[0] == '\0')
++              return 0;
 +
-+      ref = lookup_neigh_params(tbl, net, 0);
-+      if (!ref)
-+              return NULL;
-+      p = kmemdup(ref, sizeof(*p), GFP_KERNEL);
-       if (p) {
-               p->tbl            = tbl;
-               atomic_set(&p->refcnt, 1);
-@@ -1287,6 +1320,7 @@
-                       dev_hold(dev);
-                       p->dev = dev;
-               }
-+              p->net = hold_net(net);
-               p->sysctl_table = NULL;
-               write_lock_bh(&tbl->lock);
-               p->next         = tbl->parms.next;
-@@ -1296,6 +1330,20 @@
-       return p;
- }
++      f = create_write_pipe();
++      if (IS_ERR(f))
++              return PTR_ERR(f);
++      *filp = f;
  
-+struct neigh_parms *neigh_parms_alloc_default(struct neigh_table *tbl,
-+                                              struct net *net)
-+{
-+      struct neigh_parms *parms;
-+      if (net != &init_net) {
-+              parms = neigh_parms_alloc(NULL, tbl);
-+              release_net(parms->net);
-+              parms->net = hold_net(net);
+-      ret = call_usermodehelper_stdinpipe(sub_info, filp);
+-      if (ret < 0)
+-              goto out;
+-
+-      return call_usermodehelper_exec(sub_info, 1);
+-
+-  out:
+-      call_usermodehelper_freeinfo(sub_info);
+-      return ret;
++      f = create_read_pipe(f);
++      if (IS_ERR(f)) {
++              free_write_pipe(*filp);
++              return PTR_ERR(f);
 +      }
-+      else
-+              parms = neigh_parms_clone(&tbl->parms);
-+      return parms;
-+}
++      sub_info.stdin = f;
 +
- static void neigh_rcu_free_parms(struct rcu_head *head)
- {
-       struct neigh_parms *parms =
-@@ -1328,6 +1376,7 @@
- void neigh_parms_destroy(struct neigh_parms *parms)
- {
-+      release_net(parms->net);
-       kfree(parms);
++      queue_work(khelper_wq, &sub_info.work);
++      wait_for_completion(&done);
++      return sub_info.retval;
  }
+ EXPORT_SYMBOL(call_usermodehelper_pipe);
  
-@@ -1338,6 +1387,7 @@
-       unsigned long now = jiffies;
-       unsigned long phsize;
-+      tbl->parms.net = &init_net;
-       atomic_set(&tbl->parms.refcnt, 1);
-       INIT_RCU_HEAD(&tbl->parms.rcu_head);
-       tbl->parms.reachable_time =
-@@ -1353,7 +1403,7 @@
-               panic("cannot create neighbour cache statistics");
- #ifdef CONFIG_PROC_FS
--      tbl->pde = create_proc_entry(tbl->id, 0, proc_net_stat);
-+      tbl->pde = create_proc_entry(tbl->id, 0, init_net.proc_net_stat);
-       if (!tbl->pde)
-               panic("cannot create neighbour proc dir entry");
-       tbl->pde->proc_fops = &neigh_stat_seq_fops;
-@@ -1443,6 +1493,7 @@
- static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct ndmsg *ndm;
-       struct nlattr *dst_attr;
-       struct neigh_table *tbl;
-@@ -1458,7 +1509,7 @@
-       ndm = nlmsg_data(nlh);
-       if (ndm->ndm_ifindex) {
--              dev = dev_get_by_index(ndm->ndm_ifindex);
-+              dev = dev_get_by_index(net, ndm->ndm_ifindex);
-               if (dev == NULL) {
-                       err = -ENODEV;
-                       goto out;
-@@ -1477,7 +1528,7 @@
-                       goto out_dev_put;
-               if (ndm->ndm_flags & NTF_PROXY) {
--                      err = pneigh_delete(tbl, nla_data(dst_attr), dev);
-+                      err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
-                       goto out_dev_put;
-               }
-@@ -1508,6 +1559,7 @@
- static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct ndmsg *ndm;
-       struct nlattr *tb[NDA_MAX+1];
-       struct neigh_table *tbl;
-@@ -1524,7 +1576,7 @@
+diff -Nurb linux-2.6.22-590/kernel/module.c linux-2.6.22-570/kernel/module.c
+--- linux-2.6.22-590/kernel/module.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/module.c   2007-07-08 19:32:17.000000000 -0400
+@@ -67,7 +67,6 @@
+ /* List of modules, protected by module_mutex AND modlist_lock */
+ static DEFINE_MUTEX(module_mutex);
+ static LIST_HEAD(modules);
+-static DECLARE_MUTEX(notify_mutex);
  
-       ndm = nlmsg_data(nlh);
-       if (ndm->ndm_ifindex) {
--              dev = dev_get_by_index(ndm->ndm_ifindex);
-+              dev = dev_get_by_index(net, ndm->ndm_ifindex);
-               if (dev == NULL) {
-                       err = -ENODEV;
-                       goto out;
-@@ -1553,7 +1605,7 @@
-                       struct pneigh_entry *pn;
+ static BLOCKING_NOTIFIER_HEAD(module_notify_list);
  
-                       err = -ENOBUFS;
--                      pn = pneigh_lookup(tbl, dst, dev, 1);
-+                      pn = pneigh_lookup(tbl, net, dst, dev, 1);
-                       if (pn) {
-                               pn->flags = ndm->ndm_flags;
-                               err = 0;
-@@ -1748,19 +1800,6 @@
-       return -EMSGSIZE;
- }
+@@ -489,7 +488,8 @@
+         mod->field = NULL;                                            \
+ }                                                                     \
+ static struct module_attribute modinfo_##field = {                    \
+-      .attr = { .name = __stringify(field), .mode = 0444 },         \
++      .attr = { .name = __stringify(field), .mode = 0444,           \
++                .owner = THIS_MODULE },                             \
+       .show = show_modinfo_##field,                                 \
+       .setup = setup_modinfo_##field,                               \
+       .test = modinfo_##field##_exists,                             \
+@@ -713,12 +713,6 @@
+       if (ret != 0)
+               goto out;
  
--static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
--                                                    int ifindex)
--{
--      struct neigh_parms *p;
--
--      for (p = &tbl->parms; p; p = p->next)
--              if ((p->dev && p->dev->ifindex == ifindex) ||
--                  (!p->dev && !ifindex))
--                      return p;
+-      down(&notify_mutex);
+-      blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING,
+-                              mod);
+-      up(&notify_mutex);
 -
--      return NULL;
--}
 -
- static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
-       [NDTA_NAME]             = { .type = NLA_STRING },
-       [NDTA_THRESH1]          = { .type = NLA_U32 },
-@@ -1788,6 +1827,7 @@
- static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct neigh_table *tbl;
-       struct ndtmsg *ndtmsg;
-       struct nlattr *tb[NDTA_MAX+1];
-@@ -1837,7 +1877,7 @@
-               if (tbp[NDTPA_IFINDEX])
-                       ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
--              p = lookup_neigh_params(tbl, ifindex);
-+              p = lookup_neigh_params(tbl, net, ifindex);
-               if (p == NULL) {
-                       err = -ENOENT;
-                       goto errout_tbl_lock;
-@@ -1912,6 +1952,7 @@
- static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
- {
-+      struct net *net = skb->sk->sk_net;
-       int family, tidx, nidx = 0;
-       int tbl_skip = cb->args[0];
-       int neigh_skip = cb->args[1];
-@@ -1931,8 +1972,11 @@
-                                      NLM_F_MULTI) <= 0)
-                       break;
--              for (nidx = 0, p = tbl->parms.next; p; p = p->next, nidx++) {
--                      if (nidx < neigh_skip)
-+              for (nidx = 0, p = tbl->parms.next; p; p = p->next) {
-+                      if (net != p->net)
-+                              continue;
-+
-+                      if (nidx++ < neigh_skip)
-                               continue;
-                       if (neightbl_fill_param_info(skb, tbl, p,
-@@ -2003,6 +2047,7 @@
- static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
-                           struct netlink_callback *cb)
- {
-+      struct net * net = skb->sk->sk_net;
-       struct neighbour *n;
-       int rc, h, s_h = cb->args[1];
-       int idx, s_idx = idx = cb->args[2];
-@@ -2013,8 +2058,12 @@
-                       continue;
-               if (h > s_h)
-                       s_idx = 0;
--              for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next, idx++) {
--                      if (idx < s_idx)
-+              for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) {
-+                      int lidx;
-+                      if (n->dev->nd_net != net)
-+                              continue;
-+                      lidx = idx++;
-+                      if (lidx < s_idx)
-                               continue;
-                       if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,
-                                           cb->nlh->nlmsg_seq,
-@@ -2109,6 +2158,7 @@
- static struct neighbour *neigh_get_first(struct seq_file *seq)
- {
-       struct neigh_seq_state *state = seq->private;
-+      struct net * net = state->net;
-       struct neigh_table *tbl = state->tbl;
-       struct neighbour *n = NULL;
-       int bucket = state->bucket;
-@@ -2118,6 +2168,8 @@
-               n = tbl->hash_buckets[bucket];
-               while (n) {
-+                      if (n->dev->nd_net != net)
-+                              goto next;
-                       if (state->neigh_sub_iter) {
-                               loff_t fakep = 0;
-                               void *v;
-@@ -2147,6 +2199,7 @@
-                                       loff_t *pos)
- {
-       struct neigh_seq_state *state = seq->private;
-+      struct net * net = state->net;
-       struct neigh_table *tbl = state->tbl;
-       if (state->neigh_sub_iter) {
-@@ -2158,6 +2211,8 @@
-       while (1) {
-               while (n) {
-+                      if (n->dev->nd_net != net)
-+                              goto next;
-                       if (state->neigh_sub_iter) {
-                               void *v = state->neigh_sub_iter(state, n, pos);
-                               if (v)
-@@ -2204,6 +2259,7 @@
- static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
- {
-       struct neigh_seq_state *state = seq->private;
-+      struct net * net = state->net;
-       struct neigh_table *tbl = state->tbl;
-       struct pneigh_entry *pn = NULL;
-       int bucket = state->bucket;
-@@ -2211,6 +2267,8 @@
-       state->flags |= NEIGH_SEQ_IS_PNEIGH;
-       for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
-               pn = tbl->phash_buckets[bucket];
-+              while (pn && (pn->net != net))
-+                      pn = pn->next;
-               if (pn)
-                       break;
-       }
-@@ -2224,6 +2282,7 @@
-                                           loff_t *pos)
- {
-       struct neigh_seq_state *state = seq->private;
-+      struct net * net = state->net;
-       struct neigh_table *tbl = state->tbl;
-       pn = pn->next;
-@@ -2231,6 +2290,8 @@
-               if (++state->bucket > PNEIGH_HASHMASK)
-                       break;
-               pn = tbl->phash_buckets[state->bucket];
-+              while (pn && (pn->net != net))
-+                      pn = pn->next;
-               if (pn)
-                       break;
-       }
-@@ -2433,6 +2494,7 @@
- static void __neigh_notify(struct neighbour *n, int type, int flags)
- {
-+      struct net * net = n->dev->nd_net;
-       struct sk_buff *skb;
-       int err = -ENOBUFS;
-@@ -2447,10 +2509,10 @@
-               kfree_skb(skb);
-               goto errout;
-       }
--      err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
-+      err = rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
- errout:
-       if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_NEIGH, err);
-+              rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
- }
- void neigh_app_ns(struct neighbour *n)
-@@ -2648,6 +2710,7 @@
-       if (!t)
-               return -ENOBUFS;
-+
-       t->neigh_vars[0].data  = &p->mcast_probes;
-       t->neigh_vars[1].data  = &p->ucast_probes;
-       t->neigh_vars[2].data  = &p->app_probes;
-@@ -2716,7 +2779,7 @@
-       t->neigh_proto_dir[0].child    = t->neigh_neigh_dir;
-       t->neigh_root_dir[0].child     = t->neigh_proto_dir;
--      t->sysctl_header = register_sysctl_table(t->neigh_root_dir);
-+      t->sysctl_header = register_net_sysctl_table(p->net, t->neigh_root_dir);
-       if (!t->sysctl_header) {
-               err = -ENOBUFS;
-               goto free_procname;
-@@ -2738,7 +2801,7 @@
-       if (p->sysctl_table) {
-               struct neigh_sysctl_table *t = p->sysctl_table;
-               p->sysctl_table = NULL;
--              unregister_sysctl_table(t->sysctl_header);
-+              unregister_net_sysctl_table(t->sysctl_header);
-               kfree(t->neigh_dev[0].procname);
-               kfree(t);
-       }
-@@ -2771,6 +2834,7 @@
- EXPORT_SYMBOL(neigh_lookup);
- EXPORT_SYMBOL(neigh_lookup_nodev);
- EXPORT_SYMBOL(neigh_parms_alloc);
-+EXPORT_SYMBOL(neigh_parms_alloc_default);
- EXPORT_SYMBOL(neigh_parms_release);
- EXPORT_SYMBOL(neigh_rand_reach_time);
- EXPORT_SYMBOL(neigh_resolve_output);
-diff -Nurb linux-2.6.22-570/net/core/net-sysfs.c linux-2.6.22-590/net/core/net-sysfs.c
---- linux-2.6.22-570/net/core/net-sysfs.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/core/net-sysfs.c      2008-01-02 13:56:38.000000000 -0500
-@@ -13,7 +13,9 @@
- #include <linux/kernel.h>
- #include <linux/netdevice.h>
- #include <linux/if_arp.h>
-+#include <linux/nsproxy.h>
- #include <net/sock.h>
-+#include <net/net_namespace.h>
- #include <linux/rtnetlink.h>
- #include <linux/wireless.h>
- #include <net/iw_handler.h>
-@@ -29,16 +31,16 @@
- }
- /* use same locking rules as GIF* ioctl's */
--static ssize_t netdev_show(const struct device *dev,
-+static ssize_t netdev_show(const struct device *device,
-                          struct device_attribute *attr, char *buf,
-                          ssize_t (*format)(const struct net_device *, char *))
- {
--      struct net_device *net = to_net_dev(dev);
-+      struct net_device *dev = to_net_dev(device);
-       ssize_t ret = -EINVAL;
-       read_lock(&dev_base_lock);
--      if (dev_isalive(net))
--              ret = (*format)(net, buf);
-+      if (dev_isalive(dev))
-+              ret = (*format)(dev, buf);
-       read_unlock(&dev_base_lock);
+       /* Never wait if forced. */
+       if (!forced && module_refcount(mod) != 0)
+               wait_for_zero_refcount(mod);
+@@ -731,11 +725,6 @@
+       }
+       free_module(mod);
  
+-      down(&notify_mutex);
+-      blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GONE,
+-                      NULL);
+-      up(&notify_mutex);
+-
+  out:
+       mutex_unlock(&module_mutex);
        return ret;
-@@ -46,9 +48,9 @@
- /* generate a show function for simple field */
- #define NETDEVICE_SHOW(field, format_string)                          \
--static ssize_t format_##field(const struct net_device *net, char *buf)        \
-+static ssize_t format_##field(const struct net_device *dev, char *buf)        \
- {                                                                     \
--      return sprintf(buf, format_string, net->field);                 \
-+      return sprintf(buf, format_string, dev->field);                 \
- }                                                                     \
- static ssize_t show_##field(struct device *dev,                               \
-                           struct device_attribute *attr, char *buf)   \
-@@ -58,11 +60,11 @@
+@@ -804,7 +793,7 @@
+ }
  
- /* use same locking and permission rules as SIF* ioctl's */
--static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
-+static ssize_t netdev_store(struct device *device, struct device_attribute *attr,
-                           const char *buf, size_t len,
-                           int (*set)(struct net_device *, unsigned long))
- {
--      struct net_device *net = to_net_dev(dev);
-+      struct net_device *dev = to_net_dev(device);
-       char *endp;
-       unsigned long new;
-       int ret = -EINVAL;
-@@ -75,8 +77,8 @@
-               goto err;
+ static struct module_attribute refcnt = {
+-      .attr = { .name = "refcnt", .mode = 0444 },
++      .attr = { .name = "refcnt", .mode = 0444, .owner = THIS_MODULE },
+       .show = show_refcnt,
+ };
  
-       rtnl_lock();
--      if (dev_isalive(net)) {
--              if ((ret = (*set)(net, new)) == 0)
-+      if (dev_isalive(dev)) {
-+              if ((ret = (*set)(dev, new)) == 0)
-                       ret = len;
+@@ -857,15 +846,12 @@
+       case MODULE_STATE_GOING:
+               state = "going";
+               break;
+-      case MODULE_STATE_GONE:
+-              state = "gone";
+-              break;
        }
-       rtnl_unlock();
-@@ -103,45 +105,45 @@
-       return cp - buf;
+       return sprintf(buffer, "%s\n", state);
  }
  
--static ssize_t show_address(struct device *dev, struct device_attribute *attr,
-+static ssize_t show_address(struct device *device, struct device_attribute *attr,
-                           char *buf)
- {
--      struct net_device *net = to_net_dev(dev);
-+      struct net_device *dev = to_net_dev(device);
-       ssize_t ret = -EINVAL;
+ static struct module_attribute initstate = {
+-      .attr = { .name = "initstate", .mode = 0444 },
++      .attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE },
+       .show = show_initstate,
+ };
  
-       read_lock(&dev_base_lock);
--      if (dev_isalive(net))
--          ret = format_addr(buf, net->dev_addr, net->addr_len);
-+      if (dev_isalive(dev))
-+          ret = format_addr(buf, dev->dev_addr, dev->addr_len);
-       read_unlock(&dev_base_lock);
-       return ret;
- }
+@@ -1046,6 +1032,7 @@
+               sattr->mattr.show = module_sect_show;
+               sattr->mattr.store = NULL;
+               sattr->mattr.attr.name = sattr->name;
++              sattr->mattr.attr.owner = mod;
+               sattr->mattr.attr.mode = S_IRUGO;
+               *(gattr++) = &(sattr++)->mattr.attr;
+       }
+@@ -1103,6 +1090,7 @@
+               if (!attr->test ||
+                   (attr->test && attr->test(mod))) {
+                       memcpy(temp_attr, attr, sizeof(*temp_attr));
++                      temp_attr->attr.owner = mod;
+                       error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);
+                       ++temp_attr;
+               }
+@@ -1224,11 +1212,6 @@
+       /* Arch-specific cleanup. */
+       module_arch_cleanup(mod);
  
--static ssize_t show_broadcast(struct device *dev,
-+static ssize_t show_broadcast(struct device *device,
-                           struct device_attribute *attr, char *buf)
- {
--      struct net_device *net = to_net_dev(dev);
--      if (dev_isalive(net))
--              return format_addr(buf, net->broadcast, net->addr_len);
-+      struct net_device *dev = to_net_dev(device);
-+      if (dev_isalive(dev))
-+              return format_addr(buf, dev->broadcast, dev->addr_len);
-       return -EINVAL;
- }
+-#ifdef CONFIG_KGDB
+-      /* kgdb info */
+-      vfree(mod->mod_sections);
+-#endif
+-
+       /* Module unload stuff */
+       module_unload_free(mod);
  
--static ssize_t show_carrier(struct device *dev,
-+static ssize_t show_carrier(struct device *device,
-                           struct device_attribute *attr, char *buf)
- {
--      struct net_device *netdev = to_net_dev(dev);
--      if (netif_running(netdev)) {
--              return sprintf(buf, fmt_dec, !!netif_carrier_ok(netdev));
-+      struct net_device *dev = to_net_dev(device);
-+      if (netif_running(dev)) {
-+              return sprintf(buf, fmt_dec, !!netif_carrier_ok(dev));
+@@ -1488,31 +1471,6 @@
        }
-       return -EINVAL;
  }
  
--static ssize_t show_dormant(struct device *dev,
-+static ssize_t show_dormant(struct device *device,
-                           struct device_attribute *attr, char *buf)
+-#ifdef CONFIG_KGDB
+-int add_modsects (struct module *mod, Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const
+-                char *secstrings)
+-{
+-        int i;
+-
+-        mod->num_sections = hdr->e_shnum - 1;
+-        mod->mod_sections = vmalloc((hdr->e_shnum - 1)*
+-              sizeof (struct mod_section));
+-
+-        if (mod->mod_sections == NULL) {
+-                return -ENOMEM;
+-        }
+-
+-        for (i = 1; i < hdr->e_shnum; i++) {
+-                mod->mod_sections[i - 1].address = (void *)sechdrs[i].sh_addr;
+-                strncpy(mod->mod_sections[i - 1].name, secstrings +
+-                                sechdrs[i].sh_name, MAX_SECTNAME);
+-                mod->mod_sections[i - 1].name[MAX_SECTNAME] = '\0';
+-      }
+-
+-      return 0;
+-}
+-#endif
+-
+ #ifdef CONFIG_KALLSYMS
+ static int is_exported(const char *name, const struct module *mod)
  {
--      struct net_device *netdev = to_net_dev(dev);
-+      struct net_device *dev = to_net_dev(device);
+@@ -1928,12 +1886,6 @@
  
--      if (netif_running(netdev))
--              return sprintf(buf, fmt_dec, !!netif_dormant(netdev));
-+      if (netif_running(dev))
-+              return sprintf(buf, fmt_dec, !!netif_dormant(dev));
+       add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
  
-       return -EINVAL;
- }
-@@ -156,15 +158,15 @@
-       "up"
- };
+-#ifdef CONFIG_KGDB
+-        if ((err = add_modsects(mod, hdr, sechdrs, secstrings)) < 0) {
+-                goto nomodsectinfo;
+-        }
+-#endif
+-
+       err = module_finalize(hdr, sechdrs, mod);
+       if (err < 0)
+               goto cleanup;
+@@ -1994,11 +1946,6 @@
+  arch_cleanup:
+       module_arch_cleanup(mod);
+  cleanup:
+-
+-#ifdef CONFIG_KGDB
+-nomodsectinfo:
+-       vfree(mod->mod_sections);
+-#endif
+       module_unload_free(mod);
+       module_free(mod, mod->module_init);
+  free_core:
+@@ -2070,10 +2017,6 @@
+               /* Init routine failed: abort.  Try to protect us from
+                    buggy refcounters. */
+               mod->state = MODULE_STATE_GOING;
+-              down(&notify_mutex);
+-              blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING,
+-                              mod);
+-              up(&notify_mutex);
+               synchronize_sched();
+               if (mod->unsafe)
+                       printk(KERN_ERR "%s: module is now stuck!\n",
+diff -Nurb linux-2.6.22-590/kernel/ns_container.c linux-2.6.22-570/kernel/ns_container.c
+--- linux-2.6.22-590/kernel/ns_container.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/ns_container.c     1969-12-31 19:00:00.000000000 -0500
+@@ -1,99 +0,0 @@
+-/*
+- * ns_container.c - namespace container subsystem
+- *
+- * Copyright 2006, 2007 IBM Corp
+- */
+-
+-#include <linux/module.h>
+-#include <linux/container.h>
+-#include <linux/fs.h>
+-
+-struct ns_container {
+-      struct container_subsys_state css;
+-      spinlock_t lock;
+-};
+-
+-struct container_subsys ns_subsys;
+-
+-static inline struct ns_container *container_to_ns(
+-              struct container *container)
+-{
+-      return container_of(container_subsys_state(container, ns_subsys_id),
+-                          struct ns_container, css);
+-}
+-
+-int ns_container_clone(struct task_struct *task)
+-{
+-      return container_clone(task, &ns_subsys);
+-}
+-
+-/*
+- * Rules:
+- *   1. you can only enter a container which is a child of your current
+- *     container
+- *   2. you can only place another process into a container if
+- *     a. you have CAP_SYS_ADMIN
+- *     b. your container is an ancestor of task's destination container
+- *       (hence either you are in the same container as task, or in an
+- *        ancestor container thereof)
+- */
+-static int ns_can_attach(struct container_subsys *ss,
+-              struct container *new_container, struct task_struct *task)
+-{
+-      struct container *orig;
+-
+-      if (current != task) {
+-              if (!capable(CAP_SYS_ADMIN))
+-                      return -EPERM;
+-
+-              if (!container_is_descendant(new_container))
+-                      return -EPERM;
+-      }
+-
+-      if (atomic_read(&new_container->count) != 0)
+-              return -EPERM;
+-
+-      orig = task_container(task, ns_subsys_id);
+-      if (orig && orig != new_container->parent)
+-              return -EPERM;
+-
+-      return 0;
+-}
+-
+-/*
+- * Rules: you can only create a container if
+- *     1. you are capable(CAP_SYS_ADMIN)
+- *     2. the target container is a descendant of your own container
+- */
+-static int ns_create(struct container_subsys *ss, struct container *container)
+-{
+-      struct ns_container *ns_container;
+-
+-      if (!capable(CAP_SYS_ADMIN))
+-              return -EPERM;
+-      if (!container_is_descendant(container))
+-              return -EPERM;
+-
+-      ns_container = kzalloc(sizeof(*ns_container), GFP_KERNEL);
+-      if (!ns_container) return -ENOMEM;
+-      spin_lock_init(&ns_container->lock);
+-      container->subsys[ns_subsys.subsys_id] = &ns_container->css;
+-      return 0;
+-}
+-
+-static void ns_destroy(struct container_subsys *ss,
+-                      struct container *container)
+-{
+-      struct ns_container *ns_container;
+-
+-      ns_container = container_to_ns(container);
+-      kfree(ns_container);
+-}
+-
+-struct container_subsys ns_subsys = {
+-      .name = "ns",
+-      .can_attach = ns_can_attach,
+-      .create = ns_create,
+-      .destroy  = ns_destroy,
+-      .subsys_id = ns_subsys_id,
+-};
+diff -Nurb linux-2.6.22-590/kernel/nsproxy.c linux-2.6.22-570/kernel/nsproxy.c
+--- linux-2.6.22-590/kernel/nsproxy.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/nsproxy.c  2008-01-23 19:16:05.000000000 -0500
+@@ -19,13 +19,10 @@
+ #include <linux/init_task.h>
+ #include <linux/mnt_namespace.h>
+ #include <linux/utsname.h>
+-#include <net/net_namespace.h>
+ #include <linux/pid_namespace.h>
+ #include <linux/vserver/global.h>
+ #include <linux/vserver/debug.h>
  
--static ssize_t show_operstate(struct device *dev,
-+static ssize_t show_operstate(struct device *device,
-                             struct device_attribute *attr, char *buf)
+-static struct kmem_cache *nsproxy_cachep;
+-
+ struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
+ void get_task_namespaces(struct task_struct *tsk)
+@@ -61,7 +58,6 @@
+                       struct fs_struct *new_fs)
  {
--      const struct net_device *netdev = to_net_dev(dev);
-+      const struct net_device *dev = to_net_dev(device);
-       unsigned char operstate;
+       struct nsproxy *new_nsp;
+-      int err = -ENOMEM;
  
-       read_lock(&dev_base_lock);
--      operstate = netdev->operstate;
--      if (!netif_running(netdev))
-+      operstate = dev->operstate;
-+      if (!netif_running(dev))
-               operstate = IF_OPER_DOWN;
-       read_unlock(&dev_base_lock);
+       vxdprintk(VXD_CBIT(space, 4),
+               "unshare_namespaces(0x%08x,%p,%p)",
+@@ -87,24 +83,8 @@
+       if (IS_ERR(new_nsp->pid_ns))
+               goto out_pid;
  
-@@ -177,57 +179,57 @@
- /* read-write attributes */
- NETDEVICE_SHOW(mtu, fmt_dec);
+-      new_nsp->user_ns = copy_user_ns(flags, orig->user_ns);
+-      if (IS_ERR(new_nsp->user_ns))
+-              goto out_user;
+-
+-      new_nsp->net_ns = copy_net_ns(flags, orig->net_ns);
+-      if (IS_ERR(new_nsp->net_ns))
+-              goto out_net;
+-
+       return new_nsp;
  
--static int change_mtu(struct net_device *net, unsigned long new_mtu)
-+static int change_mtu(struct net_device *dev, unsigned long new_mtu)
- {
--      return dev_set_mtu(net, (int) new_mtu);
-+      return dev_set_mtu(dev, (int) new_mtu);
+-out_net:
+-      if (new_nsp->user_ns)
+-              put_user_ns(new_nsp->user_ns);
+-      if (new_nsp->net_ns)
+-              put_net(new_nsp->net_ns);
+-out_user:
+-      if (new_nsp->pid_ns)
+-              put_pid_ns(new_nsp->pid_ns);
+ out_pid:
+       if (new_nsp->ipc_ns)
+               put_ipc_ns(new_nsp->ipc_ns);
+@@ -115,11 +95,11 @@
+       if (new_nsp->mnt_ns)
+               put_mnt_ns(new_nsp->mnt_ns);
+ out_ns:
+-      kmem_cache_free(nsproxy_cachep, new_nsp);
+-      return ERR_PTR(err);
++      kfree(new_nsp);
++      return ERR_PTR(-ENOMEM);
  }
  
--static ssize_t store_mtu(struct device *dev, struct device_attribute *attr,
-+static ssize_t store_mtu(struct device *device, struct device_attribute *attr,
-                        const char *buf, size_t len)
+-static struct nsproxy *create_new_namespaces(unsigned long flags, struct task_struct *tsk,
++static struct nsproxy *create_new_namespaces(int flags, struct task_struct *tsk,
+                       struct fs_struct *new_fs)
  {
--      return netdev_store(dev, attr, buf, len, change_mtu);
-+      return netdev_store(device, attr, buf, len, change_mtu);
- }
- NETDEVICE_SHOW(flags, fmt_hex);
--static int change_flags(struct net_device *net, unsigned long new_flags)
-+static int change_flags(struct net_device *dev, unsigned long new_flags)
+       return unshare_namespaces(flags, tsk->nsproxy, new_fs);
+@@ -150,7 +130,7 @@
+  * called from clone.  This now handles copy for nsproxy and all
+  * namespaces therein.
+  */
+-int copy_namespaces(unsigned long flags, struct task_struct *tsk)
++int copy_namespaces(int flags, struct task_struct *tsk)
  {
--      return dev_change_flags(net, (unsigned) new_flags);
-+      return dev_change_flags(dev, (unsigned) new_flags);
- }
+       struct nsproxy *old_ns = tsk->nsproxy;
+       struct nsproxy *new_ns = NULL;
+@@ -164,15 +144,9 @@
  
--static ssize_t store_flags(struct device *dev, struct device_attribute *attr,
-+static ssize_t store_flags(struct device *device, struct device_attribute *attr,
-                          const char *buf, size_t len)
- {
--      return netdev_store(dev, attr, buf, len, change_flags);
-+      return netdev_store(device, attr, buf, len, change_flags);
- }
+       get_nsproxy(old_ns);
  
- NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
+-      if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER | CLONE_NEWNET)))
++      if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
+               return 0;
  
--static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
-+static int change_tx_queue_len(struct net_device *dev, unsigned long new_len)
- {
--      net->tx_queue_len = new_len;
-+      dev->tx_queue_len = new_len;
-       return 0;
- }
+-       #ifndef CONFIG_NET_NS
+-              if (unshare_flags & CLONE_NEWNET)
+-                      return -EINVAL;
+-       #endif
+-
+-
+       if (!capable(CAP_SYS_ADMIN)) {
+               err = -EPERM;
+               goto out;
+@@ -184,14 +158,7 @@
+               goto out;
+       }
  
--static ssize_t store_tx_queue_len(struct device *dev,
-+static ssize_t store_tx_queue_len(struct device *device,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t len)
- {
--      return netdev_store(dev, attr, buf, len, change_tx_queue_len);
-+      return netdev_store(device, attr, buf, len, change_tx_queue_len);
- }
+-      err = ns_container_clone(tsk);
+-      if (err) {
+-              put_nsproxy(new_ns);
+-              goto out;
+-      }
+-
+       tsk->nsproxy = new_ns;
+-
+ out:
+       put_nsproxy(old_ns);
+       vxdprintk(VXD_CBIT(space, 3),
+@@ -227,37 +194,25 @@
+               "unshare_nsproxy_namespaces(0x%08lx,[%p])",
+               unshare_flags, current->nsproxy);
  
- NETDEVICE_SHOW(weight, fmt_dec);
+-      if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
+-                             CLONE_NEWUSER | CLONE_NEWNET)))
++      if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
+               return 0;
  
--static int change_weight(struct net_device *net, unsigned long new_weight)
-+static int change_weight(struct net_device *dev, unsigned long new_weight)
- {
--      net->weight = new_weight;
-+      dev->weight = new_weight;
-       return 0;
+-#ifndef CONFIG_NET_NS
+-      if (unshare_flags & CLONE_NEWNET)
++#ifndef CONFIG_IPC_NS
++      if (unshare_flags & CLONE_NEWIPC)
++              return -EINVAL;
++#endif
++
++#ifndef CONFIG_UTS_NS
++      if (unshare_flags & CLONE_NEWUTS)
+               return -EINVAL;
+ #endif
++
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       *new_nsp = create_new_namespaces(unshare_flags, current,
+                               new_fs ? new_fs : current->fs);
+-      if (IS_ERR(*new_nsp)) {
++      if (IS_ERR(*new_nsp))
+               err = PTR_ERR(*new_nsp);
+-              goto out;
+-      }
+-
+-      err = ns_container_clone(current);
+-      if (err)
+-              put_nsproxy(*new_nsp);
+-
+-out:
+       return err;
+ }
+-
+-static int __init nsproxy_cache_init(void)
+-{
+-      nsproxy_cachep = kmem_cache_create("nsproxy", sizeof(struct nsproxy),
+-                                         0, SLAB_PANIC, NULL, NULL);
+-      return 0;
+-}
+-
+-module_init(nsproxy_cache_init);
+diff -Nurb linux-2.6.22-590/kernel/nsproxy.c.orig linux-2.6.22-570/kernel/nsproxy.c.orig
+--- linux-2.6.22-590/kernel/nsproxy.c.orig     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/nsproxy.c.orig     1969-12-31 19:00:00.000000000 -0500
+@@ -1,264 +0,0 @@
+-/*
+- *  Copyright (C) 2006 IBM Corporation
+- *
+- *  Author: Serge Hallyn <serue@us.ibm.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, version 2 of the
+- *  License.
+- *
+- *  Jun 2006 - namespaces support
+- *             OpenVZ, SWsoft Inc.
+- *             Pavel Emelianov <xemul@openvz.org>
+- */
+-
+-#include <linux/module.h>
+-#include <linux/version.h>
+-#include <linux/nsproxy.h>
+-#include <linux/init_task.h>
+-#include <linux/mnt_namespace.h>
+-#include <linux/utsname.h>
+-#include <net/net_namespace.h>
+-#include <linux/pid_namespace.h>
+-#include <linux/vserver/global.h>
+-#include <linux/vserver/debug.h>
+-
+-static struct kmem_cache *nsproxy_cachep;
+-
+-struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
+-
+-void get_task_namespaces(struct task_struct *tsk)
+-{
+-      struct nsproxy *ns = tsk->nsproxy;
+-      if (ns) {
+-              get_nsproxy(ns);
+-      }
+-}
+-
+-/*
+- * creates a copy of "orig" with refcount 1.
+- */
+-static inline struct nsproxy *clone_nsproxy(struct nsproxy *orig)
+-{
+-      struct nsproxy *ns;
+-
+-      ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL);
+-      if (ns)
+-              atomic_set(&ns->count, 1);
+-      vxdprintk(VXD_CBIT(space, 2), "clone_nsproxy(%p[%u] = %p[1]",
+-              orig, atomic_read(&orig->count), ns);
+-      atomic_inc(&vs_global_nsproxy);
+-      return ns;
+-}
+-
+-/*
+- * Create new nsproxy and all of its the associated namespaces.
+- * Return the newly created nsproxy.  Do not attach this to the task,
+- * leave it to the caller to do proper locking and attach it to task.
+- */
+-static struct nsproxy *unshare_namespaces(int flags, struct nsproxy *orig,
+-                      struct fs_struct *new_fs)
+-{
+-      struct nsproxy *new_nsp;
+-      int err = -ENOMEM;
+-
+-      vxdprintk(VXD_CBIT(space, 4),
+-              "unshare_namespaces(0x%08x,%p,%p)",
+-              flags, orig, new_fs);
+-
+-      new_nsp = clone_nsproxy(orig);
+-      if (!new_nsp)
+-              return ERR_PTR(-ENOMEM);
+-
+-      new_nsp->mnt_ns = copy_mnt_ns(flags, orig->mnt_ns, new_fs);
+-      if (IS_ERR(new_nsp->mnt_ns))
+-              goto out_ns;
+-
+-      new_nsp->uts_ns = copy_utsname(flags, orig->uts_ns);
+-      if (IS_ERR(new_nsp->uts_ns))
+-              goto out_uts;
+-
+-      new_nsp->ipc_ns = copy_ipcs(flags, orig->ipc_ns);
+-      if (IS_ERR(new_nsp->ipc_ns))
+-              goto out_ipc;
+-
+-      new_nsp->pid_ns = copy_pid_ns(flags, orig->pid_ns);
+-      if (IS_ERR(new_nsp->pid_ns))
+-              goto out_pid;
+-
+-      new_nsp->user_ns = copy_user_ns(flags, orig->user_ns);
+-      if (IS_ERR(new_nsp->user_ns))
+-              goto out_user;
+-
+-      new_nsp->net_ns = copy_net_ns(flags, orig->net_ns);
+-      if (IS_ERR(new_nsp->net_ns))
+-              goto out_net;
+-
+-      return new_nsp;
+-
+-out_net:
+-      if (new_nsp->user_ns)
+-              put_user_ns(new_nsp->user_ns);
+-      if (new_nsp->net_ns)
+-              put_net(new_nsp->net_ns);
+-out_user:
+-      if (new_nsp->pid_ns)
+-              put_pid_ns(new_nsp->pid_ns);
+-out_pid:
+-      if (new_nsp->ipc_ns)
+-              put_ipc_ns(new_nsp->ipc_ns);
+-out_ipc:
+-      if (new_nsp->uts_ns)
+-              put_uts_ns(new_nsp->uts_ns);
+-out_uts:
+-      if (new_nsp->mnt_ns)
+-              put_mnt_ns(new_nsp->mnt_ns);
+-out_ns:
+-      kmem_cache_free(nsproxy_cachep, new_nsp);
+-      return ERR_PTR(err);
+-}
+-
+-static struct nsproxy *create_new_namespaces(unsigned long flags, struct task_struct *tsk,
+-                      struct fs_struct *new_fs)
+-{
+-      return unshare_namespaces(flags, tsk->nsproxy, new_fs);
+-}
+-
+-/*
+- * copies the nsproxy, setting refcount to 1, and grabbing a
+- * reference to all contained namespaces.
+- */
+-struct nsproxy *copy_nsproxy(struct nsproxy *orig)
+-{
+-      struct nsproxy *ns = clone_nsproxy(orig);
+-
+-      if (ns) {
+-              if (ns->mnt_ns)
+-                      get_mnt_ns(ns->mnt_ns);
+-              if (ns->uts_ns)
+-                      get_uts_ns(ns->uts_ns);
+-              if (ns->ipc_ns)
+-                      get_ipc_ns(ns->ipc_ns);
+-              if (ns->pid_ns)
+-                      get_pid_ns(ns->pid_ns);
+-      }
+-      return ns;
+-}
+-
+-/*
+- * called from clone.  This now handles copy for nsproxy and all
+- * namespaces therein.
+- */
+-int copy_namespaces(unsigned long flags, struct task_struct *tsk)
+-{
+-      struct nsproxy *old_ns = tsk->nsproxy;
+-      struct nsproxy *new_ns = NULL;
+-      int err = 0;
+-
+-      vxdprintk(VXD_CBIT(space, 7), "copy_namespaces(0x%08x,%p[%p])",
+-              flags, tsk, old_ns);
+-
+-      if (!old_ns)
+-              return 0;
+-
+-      get_nsproxy(old_ns);
+-      return 0;
+-
+-      if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER | CLONE_NEWNET)))
+-              return 0;
+-
+-       #ifndef CONFIG_NET_NS
+-              if (unshare_flags & CLONE_NEWNET)
+-                      return -EINVAL;
+-       #endif
+-
+-
+-      if (!capable(CAP_SYS_ADMIN)) {
+-              err = -EPERM;
+-              goto out;
+-      }
+-
+-      new_ns = create_new_namespaces(flags, tsk, tsk->fs);
+-      if (IS_ERR(new_ns)) {
+-              err = PTR_ERR(new_ns);
+-              goto out;
+-      }
+-
+-      err = ns_container_clone(tsk);
+-      if (err) {
+-              put_nsproxy(new_ns);
+-              goto out;
+-      }
+-
+-      tsk->nsproxy = new_ns;
+-
+-out:
+-      put_nsproxy(old_ns);
+-      vxdprintk(VXD_CBIT(space, 3),
+-              "copy_namespaces(0x%08x,%p[%p]) = %d [%p]",
+-              flags, tsk, old_ns, err, new_ns);
+-      return err;
+-}
+-
+-void free_nsproxy(struct nsproxy *ns)
+-{
+-      if (ns->mnt_ns)
+-              put_mnt_ns(ns->mnt_ns);
+-      if (ns->uts_ns)
+-              put_uts_ns(ns->uts_ns);
+-      if (ns->ipc_ns)
+-              put_ipc_ns(ns->ipc_ns);
+-      if (ns->pid_ns)
+-              put_pid_ns(ns->pid_ns);
+-      atomic_dec(&vs_global_nsproxy);
+-      kfree(ns);
+-}
+-
+-/*
+- * Called from unshare. Unshare all the namespaces part of nsproxy.
+- * On success, returns the new nsproxy.
+- */
+-int unshare_nsproxy_namespaces(unsigned long unshare_flags,
+-              struct nsproxy **new_nsp, struct fs_struct *new_fs)
+-{
+-      int err = 0;
+-
+-      vxdprintk(VXD_CBIT(space, 4),
+-              "unshare_nsproxy_namespaces(0x%08lx,[%p])",
+-              unshare_flags, current->nsproxy);
+-
+-      if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
+-                             CLONE_NEWUSER | CLONE_NEWNET)))
+-              return 0;
+-
+-#ifndef CONFIG_NET_NS
+-      if (unshare_flags & CLONE_NEWNET)
+-              return -EINVAL;
+-#endif
+-      if (!capable(CAP_SYS_ADMIN))
+-              return -EPERM;
+-
+-      *new_nsp = create_new_namespaces(unshare_flags, current,
+-                              new_fs ? new_fs : current->fs);
+-      if (IS_ERR(*new_nsp)) {
+-              err = PTR_ERR(*new_nsp);
+-              goto out;
+-      }
+-
+-      err = ns_container_clone(current);
+-      if (err)
+-              put_nsproxy(*new_nsp);
+-
+-out:
+-      return err;
+-}
+-
+-static int __init nsproxy_cache_init(void)
+-{
+-      nsproxy_cachep = kmem_cache_create("nsproxy", sizeof(struct nsproxy),
+-                                         0, SLAB_PANIC, NULL, NULL);
+-      return 0;
+-}
+-
+-module_init(nsproxy_cache_init);
+diff -Nurb linux-2.6.22-590/kernel/params.c linux-2.6.22-570/kernel/params.c
+--- linux-2.6.22-590/kernel/params.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/params.c   2008-01-23 19:15:56.000000000 -0500
+@@ -491,6 +491,7 @@
+                       pattr->mattr.show = param_attr_show;
+                       pattr->mattr.store = param_attr_store;
+                       pattr->mattr.attr.name = (char *)&kp->name[name_skip];
++                      pattr->mattr.attr.owner = mk->mod;
+                       pattr->mattr.attr.mode = kp->perm;
+                       *(gattr++) = &(pattr++)->mattr.attr;
+               }
+diff -Nurb linux-2.6.22-590/kernel/pid.c linux-2.6.22-570/kernel/pid.c
+--- linux-2.6.22-590/kernel/pid.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/pid.c      2008-01-23 19:16:05.000000000 -0500
+@@ -379,7 +379,7 @@
  }
+ EXPORT_SYMBOL_GPL(find_get_pid);
  
--static ssize_t store_weight(struct device *dev, struct device_attribute *attr,
-+static ssize_t store_weight(struct device *device, struct device_attribute *attr,
-                           const char *buf, size_t len)
+-struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns)
++struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *old_ns)
  {
--      return netdev_store(dev, attr, buf, len, change_weight);
-+      return netdev_store(device, attr, buf, len, change_weight);
- }
+       BUG_ON(!old_ns);
+       get_pid_ns(old_ns);
+diff -Nurb linux-2.6.22-590/kernel/ptrace.c linux-2.6.22-570/kernel/ptrace.c
+--- linux-2.6.22-590/kernel/ptrace.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/ptrace.c   2008-01-23 19:16:05.000000000 -0500
+@@ -143,7 +143,7 @@
+               return -EPERM;
+       smp_rmb();
+       if (task->mm)
+-              dumpable = get_dumpable(task->mm);
++              dumpable = task->mm->dumpable;
+       if (!dumpable && !capable(CAP_SYS_PTRACE))
+               return -EPERM;
+       if (!vx_check(task->xid, VS_ADMIN_P|VS_IDENT))
+diff -Nurb linux-2.6.22-590/kernel/rcutorture.c linux-2.6.22-570/kernel/rcutorture.c
+--- linux-2.6.22-590/kernel/rcutorture.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/rcutorture.c       2007-07-08 19:32:17.000000000 -0400
+@@ -40,7 +40,6 @@
+ #include <linux/moduleparam.h>
+ #include <linux/percpu.h>
+ #include <linux/notifier.h>
+-#include <linux/freezer.h>
+ #include <linux/cpu.h>
+ #include <linux/random.h>
+ #include <linux/delay.h>
+@@ -519,6 +518,7 @@
  
- static struct device_attribute net_class_attributes[] = {
-@@ -447,6 +449,23 @@
-       kfree((char *)dev - dev->padded);
- }
+       VERBOSE_PRINTK_STRING("rcu_torture_writer task started");
+       set_user_nice(current, 19);
++      current->flags |= PF_NOFREEZE;
  
-+static const void *net_current_tag(void)
-+{
-+      return current->nsproxy->net_ns;
-+}
-+
-+static const void *net_kobject_tag(struct kobject *kobj)
-+{
-+      struct net_device *dev;
-+      dev = container_of(kobj, struct net_device, dev.kobj);
-+      return dev->nd_net;
-+}
-+
-+static const struct shadow_dir_operations net_shadow_dir_operations = {
-+      .current_tag = net_current_tag,
-+      .kobject_tag = net_kobject_tag,
-+};
-+
- static struct class net_class = {
-       .name = "net",
-       .dev_release = netdev_release,
-@@ -454,42 +473,43 @@
- #ifdef CONFIG_HOTPLUG
-       .dev_uevent = netdev_uevent,
- #endif
-+      .shadow_ops = &net_shadow_dir_operations,
- };
+       do {
+               schedule_timeout_uninterruptible(1);
+@@ -558,6 +558,7 @@
  
- /* Delete sysfs entries but hold kobject reference until after all
-  * netdev references are gone.
-  */
--void netdev_unregister_sysfs(struct net_device * net)
-+void netdev_unregister_sysfs(struct net_device * dev)
- {
--      struct device *dev = &(net->dev);
-+      struct device *device = &(dev->dev);
+       VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task started");
+       set_user_nice(current, 19);
++      current->flags |= PF_NOFREEZE;
  
--      kobject_get(&dev->kobj);
--      device_del(dev);
-+      kobject_get(&device->kobj);
-+      device_del(device);
- }
+       do {
+               schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
+@@ -588,6 +589,7 @@
  
- /* Create sysfs entries for network device. */
--int netdev_register_sysfs(struct net_device *net)
-+int netdev_register_sysfs(struct net_device *dev)
- {
--      struct device *dev = &(net->dev);
--      struct attribute_group **groups = net->sysfs_groups;
-+      struct device *device = &(dev->dev);
-+      struct attribute_group **groups = dev->sysfs_groups;
--      device_initialize(dev);
--      dev->class = &net_class;
--      dev->platform_data = net;
--      dev->groups = groups;
-+      device_initialize(device);
-+      device->class = &net_class;
-+      device->platform_data = dev;
-+      device->groups = groups;
+       VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
+       set_user_nice(current, 19);
++      current->flags |= PF_NOFREEZE;
  
-       BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ);
--      strlcpy(dev->bus_id, net->name, BUS_ID_SIZE);
-+      strlcpy(device->bus_id, dev->name, BUS_ID_SIZE);
+       do {
+               idx = cur_ops->readlock();
+diff -Nurb linux-2.6.22-590/kernel/rtmutex-tester.c linux-2.6.22-570/kernel/rtmutex-tester.c
+--- linux-2.6.22-590/kernel/rtmutex-tester.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/rtmutex-tester.c   2007-07-08 19:32:17.000000000 -0400
+@@ -260,7 +260,6 @@
+       int ret;
  
--      if (net->get_stats)
-+      if (dev->get_stats)
-               *groups++ = &netstat_group;
+       current->flags |= PF_MUTEX_TESTER;
+-      set_freezable();
+       allow_signal(SIGHUP);
  
- #ifdef CONFIG_WIRELESS_EXT
--      if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
-+      if (dev->wireless_handlers && dev->wireless_handlers->get_wireless_stats)
-               *groups++ = &wireless_group;
- #endif
+       for(;;) {
+diff -Nurb linux-2.6.22-590/kernel/sched.c linux-2.6.22-570/kernel/sched.c
+--- linux-2.6.22-590/kernel/sched.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/sched.c    2008-01-23 19:16:05.000000000 -0500
+@@ -51,10 +51,8 @@
+ #include <linux/times.h>
+ #include <linux/tsacct_kern.h>
+ #include <linux/kprobes.h>
+-#include <linux/kgdb.h>
+ #include <linux/delayacct.h>
+ #include <linux/reciprocal_div.h>
+-#include <linux/cpu_acct.h>
  
--      return device_add(dev);
-+      return device_add(device);
- }
+ #include <asm/tlb.h>
+ #include <asm/unistd.h>
+@@ -3401,16 +3399,9 @@
+       struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
+       struct vx_info *vxi = p->vx_info;  /* p is _always_ current */
+       cputime64_t tmp;
+-      struct rq *rq = this_rq();
+       int nice = (TASK_NICE(p) > 0);
  
- int netdev_sysfs_init(void)
-diff -Nurb linux-2.6.22-570/net/core/net_namespace.c linux-2.6.22-590/net/core/net_namespace.c
---- linux-2.6.22-570/net/core/net_namespace.c  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/net/core/net_namespace.c  2008-01-02 13:56:38.000000000 -0500
-@@ -0,0 +1,332 @@
-+#include <linux/workqueue.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/cache.h>
-+#include <linux/slab.h>
-+#include <linux/list.h>
-+#include <linux/delay.h>
-+#include <net/net_namespace.h>
-+
-+/*
-+ *    Our network namespace constructor/destructor lists
-+ */
-+
-+static LIST_HEAD(pernet_list);
-+static struct list_head *first_device = &pernet_list;
-+static DEFINE_MUTEX(net_mutex);
-+
-+static DEFINE_MUTEX(net_list_mutex);
-+LIST_HEAD(net_namespace_list);
-+
-+static struct kmem_cache *net_cachep;
-+
-+struct net init_net;
-+EXPORT_SYMBOL_GPL(init_net);
-+
-+void net_lock(void)
-+{
-+      mutex_lock(&net_list_mutex);
-+}
-+
-+void net_unlock(void)
-+{
-+      mutex_unlock(&net_list_mutex);
-+}
-+
-+static struct net *net_alloc(void)
-+{
-+      return kmem_cache_alloc(net_cachep, GFP_KERNEL);
-+}
-+
-+static void net_free(struct net *net)
-+{
-+      if (!net)
-+              return;
-+
-+      if (unlikely(atomic_read(&net->use_count) != 0)) {
-+              printk(KERN_EMERG "network namespace not free! Usage: %d\n",
-+                      atomic_read(&net->use_count));
-+              return;
-+      }
-+
-+      kmem_cache_free(net_cachep, net);
-+}
-+
-+static void cleanup_net(struct work_struct *work)
-+{
-+      struct pernet_operations *ops;
-+      struct list_head *ptr;
-+      struct net *net;
-+
-+      net = container_of(work, struct net, work);
-+
-+      mutex_lock(&net_mutex);
-+
-+      /* Don't let anyone else find us. */
-+      net_lock();
-+      list_del(&net->list);
-+      net_unlock();
-+
-+      /* Run all of the network namespace exit methods */
-+      list_for_each_prev(ptr, &pernet_list) {
-+              ops = list_entry(ptr, struct pernet_operations, list);
-+              if (ops->exit)
-+                      ops->exit(net);
-+      }
-+
-+      mutex_unlock(&net_mutex);
-+
-+      /* Ensure there are no outstanding rcu callbacks using this
-+       * network namespace.
-+       */
-+      rcu_barrier();
-+
-+      /* Finally it is safe to free my network namespace structure */
-+      net_free(net);
-+}
-+
-+
-+void __put_net(struct net *net)
-+{
-+      /* Cleanup the network namespace in process context */
-+      INIT_WORK(&net->work, cleanup_net);
-+      schedule_work(&net->work);
-+}
-+EXPORT_SYMBOL_GPL(__put_net);
+       p->utime = cputime_add(p->utime, cputime);
+-
+-
+-      if (p != rq->idle)
+-              cpuacct_charge(p, cputime);
+- 
+-
+       vx_account_user(vxi, cputime, nice);
+       /* Add user time to cpustat. */
+@@ -3444,10 +3435,9 @@
+               cpustat->irq = cputime64_add(cpustat->irq, tmp);
+       else if (softirq_count())
+               cpustat->softirq = cputime64_add(cpustat->softirq, tmp);
+-      else if (p != rq->idle) {
++      else if (p != rq->idle)
+               cpustat->system = cputime64_add(cpustat->system, tmp);
+-              cpuacct_charge(p, cputime);
+-      } else if (atomic_read(&rq->nr_iowait) > 0)
++      else if (atomic_read(&rq->nr_iowait) > 0)
+               cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
+       else
+               cpustat->idle = cputime64_add(cpustat->idle, tmp);
+@@ -3472,10 +3462,8 @@
+                       cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
+               else
+                       cpustat->idle = cputime64_add(cpustat->idle, tmp);
+-      } else {
++      } else
+               cpustat->steal = cputime64_add(cpustat->steal, tmp);
+-              cpuacct_charge(p, -tmp);
+-      }
+ }
+ static void task_running_tick(struct rq *rq, struct task_struct *p, int cpu)
+@@ -5299,6 +5287,8 @@
+               struct migration_req *req;
+               struct list_head *head;
++              try_to_freeze();
 +
+               spin_lock_irq(&rq->lock);
+               if (cpu_is_offline(cpu)) {
+@@ -5532,6 +5522,7 @@
+               p = kthread_create(migration_thread, hcpu, "migration/%d",cpu);
+               if (IS_ERR(p))
+                       return NOTIFY_BAD;
++              p->flags |= PF_NOFREEZE;
+               kthread_bind(p, cpu);
+               /* Must be high prio: stop_machine expects to yield to it. */
+               rq = task_rq_lock(p, &flags);
+@@ -6935,6 +6926,33 @@
+       arch_destroy_sched_domains(cpu_map);
+ }
 +/*
-+ * setup_net runs the initializers for the network namespace object.
++ * Partition sched domains as specified by the cpumasks below.
++ * This attaches all cpus from the cpumasks to the NULL domain,
++ * waits for a RCU quiescent period, recalculates sched
++ * domain information and then attaches them back to the
++ * correct sched domains
++ * Call with hotplug lock held
 + */
-+static int setup_net(struct net *net)
-+{
-+      /* Must be called with net_mutex held */
-+      struct pernet_operations *ops;
-+      struct list_head *ptr;
-+      int error;
-+
-+      memset(net, 0, sizeof(struct net));
-+      atomic_set(&net->count, 1);
-+      atomic_set(&net->use_count, 0);
-+
-+      error = 0;
-+      list_for_each(ptr, &pernet_list) {
-+              ops = list_entry(ptr, struct pernet_operations, list);
-+              if (ops->init) {
-+                      error = ops->init(net);
-+                      if (error < 0)
-+                              goto out_undo;
-+              }
-+      }
-+out:
-+      return error;
-+out_undo:
-+      /* Walk through the list backwards calling the exit functions
-+       * for the pernet modules whose init functions did not fail.
-+       */
-+      for (ptr = ptr->prev; ptr != &pernet_list; ptr = ptr->prev) {
-+              ops = list_entry(ptr, struct pernet_operations, list);
-+              if (ops->exit)
-+                      ops->exit(net);
-+      }
-+      goto out;
-+}
-+
-+struct net *copy_net_ns(unsigned long flags, struct net *old_net)
-+{
-+      struct net *new_net = NULL;
-+      int err;
-+
-+      get_net(old_net);
-+
-+      if (!(flags & CLONE_NEWNET))
-+              return old_net;
-+
-+      err = -EPERM;
-+      if (!capable(CAP_SYS_ADMIN))
-+              goto out;
-+
-+      err = -ENOMEM;
-+      new_net = net_alloc();
-+      if (!new_net)
-+              goto out;
-+
-+      mutex_lock(&net_mutex);
-+      err = setup_net(new_net);
-+      if (err)
-+              goto out_unlock;
-+
-+      net_lock();
-+      list_add_tail(&new_net->list, &net_namespace_list);
-+      net_unlock();
-+
-+
-+out_unlock:
-+      mutex_unlock(&net_mutex);
-+out:
-+      put_net(old_net);
-+      if (err) {
-+              net_free(new_net);
-+              new_net = ERR_PTR(err);
-+      }
-+      return new_net;
-+}
-+
-+static int __init net_ns_init(void)
-+{
-+      int err;
-+
-+      printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
-+      net_cachep = kmem_cache_create("net_namespace", sizeof(struct net),
-+                                      SMP_CACHE_BYTES,
-+                                      SLAB_PANIC, NULL, NULL);
-+      mutex_lock(&net_mutex);
-+      err = setup_net(&init_net);
-+
-+      net_lock();
-+      list_add_tail(&init_net.list, &net_namespace_list);
-+      net_unlock();
-+
-+      mutex_unlock(&net_mutex);
-+      if (err)
-+              panic("Could not setup the initial network namespace");
-+
-+      return 0;
-+}
-+
-+pure_initcall(net_ns_init);
-+
-+static int register_pernet_operations(struct list_head *list,
-+                                    struct pernet_operations *ops)
-+{
-+      struct net *net, *undo_net;
-+      int error;
-+
-+      error = 0;
-+      list_add_tail(&ops->list, list);
-+      for_each_net(net) {
-+              if (ops->init) {
-+                      error = ops->init(net);
-+                      if (error)
-+                              goto out_undo;
-+              }
-+      }
-+out:
-+      return error;
-+
-+out_undo:
-+      /* If I have an error cleanup all namespaces I initialized */
-+      list_del(&ops->list);
-+      for_each_net(undo_net) {
-+              if (undo_net == net)
-+                      goto undone;
-+              if (ops->exit)
-+                      ops->exit(undo_net);
-+      }
-+undone:
-+      goto out;
-+}
-+
-+static void unregister_pernet_operations(struct pernet_operations *ops)
++int partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2)
 +{
-+      struct net *net;
-+
-+      list_del(&ops->list);
-+      for_each_net(net)
-+              if (ops->exit)
-+                      ops->exit(net);
-+}
++      cpumask_t change_map;
++      int err = 0;
 +
-+/**
-+ *      register_pernet_subsys - register a network namespace subsystem
-+ *    @ops:  pernet operations structure for the subsystem
-+ *
-+ *    Register a subsystem which has init and exit functions
-+ *    that are called when network namespaces are created and
-+ *    destroyed respectively.
-+ *
-+ *    When registered all network namespace init functions are
-+ *    called for every existing network namespace.  Allowing kernel
-+ *    modules to have a race free view of the set of network namespaces.
-+ *
-+ *    When a new network namespace is created all of the init
-+ *    methods are called in the order in which they were registered.
-+ *
-+ *    When a network namespace is destroyed all of the exit methods
-+ *    are called in the reverse of the order with which they were
-+ *    registered.
-+ */
-+int register_pernet_subsys(struct pernet_operations *ops)
-+{
-+      int error;
-+      mutex_lock(&net_mutex);
-+      error =  register_pernet_operations(first_device, ops);
-+      mutex_unlock(&net_mutex);
-+      return error;
-+}
-+EXPORT_SYMBOL_GPL(register_pernet_subsys);
++      cpus_and(*partition1, *partition1, cpu_online_map);
++      cpus_and(*partition2, *partition2, cpu_online_map);
++      cpus_or(change_map, *partition1, *partition2);
 +
-+/**
-+ *      unregister_pernet_subsys - unregister a network namespace subsystem
-+ *    @ops: pernet operations structure to manipulate
-+ *
-+ *    Remove the pernet operations structure from the list to be
-+ *    used when network namespaces are created or destoryed.  In
-+ *    addition run the exit method for all existing network
-+ *    namespaces.
-+ */
-+void unregister_pernet_subsys(struct pernet_operations *module)
-+{
-+      mutex_lock(&net_mutex);
-+      unregister_pernet_operations(module);
-+      mutex_unlock(&net_mutex);
-+}
-+EXPORT_SYMBOL_GPL(unregister_pernet_subsys);
++      /* Detach sched domains from all of the affected cpus */
++      detach_destroy_domains(&change_map);
++      if (!cpus_empty(*partition1))
++              err = build_sched_domains(partition1);
++      if (!err && !cpus_empty(*partition2))
++              err = build_sched_domains(partition2);
 +
-+/**
-+ *      register_pernet_device - register a network namespace device
-+ *    @ops:  pernet operations structure for the subsystem
-+ *
-+ *    Register a device which has init and exit functions
-+ *    that are called when network namespaces are created and
-+ *    destroyed respectively.
-+ *
-+ *    When registered all network namespace init functions are
-+ *    called for every existing network namespace.  Allowing kernel
-+ *    modules to have a race free view of the set of network namespaces.
-+ *
-+ *    When a new network namespace is created all of the init
-+ *    methods are called in the order in which they were registered.
-+ *
-+ *    When a network namespace is destroyed all of the exit methods
-+ *    are called in the reverse of the order with which they were
-+ *    registered.
-+ */
-+int register_pernet_device(struct pernet_operations *ops)
-+{
-+      int error;
-+      mutex_lock(&net_mutex);
-+      error = register_pernet_operations(&pernet_list, ops);
-+      if (!error && (first_device == &pernet_list))
-+              first_device = &ops->list;
-+      mutex_unlock(&net_mutex);
-+      return error;
++      return err;
 +}
-+EXPORT_SYMBOL_GPL(register_pernet_device);
 +
-+/**
-+ *      unregister_pernet_device - unregister a network namespace netdevice
-+ *    @ops: pernet operations structure to manipulate
-+ *
-+ *    Remove the pernet operations structure from the list to be
-+ *    used when network namespaces are created or destoryed.  In
-+ *    addition run the exit method for all existing network
-+ *    namespaces.
-+ */
-+void unregister_pernet_device(struct pernet_operations *ops)
-+{
-+      mutex_lock(&net_mutex);
-+      if (&ops->list == first_device)
-+              first_device = first_device->next;
-+      unregister_pernet_operations(ops);
-+      mutex_unlock(&net_mutex);
-+}
-+EXPORT_SYMBOL_GPL(unregister_pernet_device);
-diff -Nurb linux-2.6.22-570/net/core/netpoll.c linux-2.6.22-590/net/core/netpoll.c
---- linux-2.6.22-570/net/core/netpoll.c        2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/core/netpoll.c        2008-01-02 13:56:38.000000000 -0500
-@@ -503,7 +503,8 @@
+ #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
+ int arch_reinit_sched_domains(void)
+ {
+@@ -7159,9 +7177,6 @@
+ #ifdef in_atomic
+       static unsigned long prev_jiffy;        /* ratelimiting */
  
-       np->rx_hook(np, ntohs(uh->source),
-                   (char *)(uh+1),
--                  ulen - sizeof(struct udphdr));
-+                  ulen - sizeof(struct udphdr),
-+                  skb);
+-      if (atomic_read(&debugger_active))
+-              return;
+-
+       if ((in_atomic() || irqs_disabled()) &&
+           system_state == SYSTEM_RUNNING && !oops_in_progress) {
+               if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
+diff -Nurb linux-2.6.22-590/kernel/seccomp.c linux-2.6.22-570/kernel/seccomp.c
+--- linux-2.6.22-590/kernel/seccomp.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/seccomp.c  2007-07-08 19:32:17.000000000 -0400
+@@ -10,7 +10,6 @@
+ #include <linux/sched.h>
  
-       kfree_skb(skb);
-       return 1;
-@@ -633,7 +634,7 @@
-       int err;
+ /* #define SECCOMP_DEBUG 1 */
+-#define NR_SECCOMP_MODES 1
  
-       if (np->dev_name)
--              ndev = dev_get_by_name(np->dev_name);
-+              ndev = dev_get_by_name(&init_net, np->dev_name);
-       if (!ndev) {
-               printk(KERN_ERR "%s: %s doesn't exist, aborting.\n",
-                      np->name, np->dev_name);
-diff -Nurb linux-2.6.22-570/net/core/pktgen.c linux-2.6.22-590/net/core/pktgen.c
---- linux-2.6.22-570/net/core/pktgen.c 2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/core/pktgen.c 2008-01-02 13:56:38.000000000 -0500
-@@ -155,6 +155,7 @@
- #include <net/checksum.h>
- #include <net/ipv6.h>
- #include <net/addrconf.h>
-+#include <net/net_namespace.h>
- #include <asm/byteorder.h>
+ /*
+  * Secure computing mode 1 allows only read/write/exit/sigreturn.
+@@ -55,28 +54,3 @@
+ #endif
+       do_exit(SIGKILL);
+ }
+-
+-long prctl_get_seccomp(void)
+-{
+-      return current->seccomp.mode;
+-}
+-
+-long prctl_set_seccomp(unsigned long seccomp_mode)
+-{
+-      long ret;
+-
+-      /* can set it only once to be even more secure */
+-      ret = -EPERM;
+-      if (unlikely(current->seccomp.mode))
+-              goto out;
+-
+-      ret = -EINVAL;
+-      if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
+-              current->seccomp.mode = seccomp_mode;
+-              set_thread_flag(TIF_SECCOMP);
+-              ret = 0;
+-      }
+-
+- out:
+-      return ret;
+-}
+diff -Nurb linux-2.6.22-590/kernel/signal.c linux-2.6.22-570/kernel/signal.c
+--- linux-2.6.22-590/kernel/signal.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/signal.c   2008-01-23 19:16:05.000000000 -0500
+@@ -257,16 +257,6 @@
+       }
+ }
+-int unhandled_signal(struct task_struct *tsk, int sig)
+-{
+-      if (is_init(tsk))
+-              return 1;
+-      if (tsk->ptrace & PT_PTRACED)
+-              return 0;
+-      return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) ||
+-              (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL);
+-}
+-
+ /* Notify the system that a driver wants to block all signals for this
+  * process, and wants to be notified if any signals at all were to be
+diff -Nurb linux-2.6.22-590/kernel/softirq.c linux-2.6.22-570/kernel/softirq.c
+--- linux-2.6.22-590/kernel/softirq.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/softirq.c  2008-01-23 19:16:05.000000000 -0500
+@@ -14,7 +14,6 @@
+ #include <linux/notifier.h>
+ #include <linux/percpu.h>
+ #include <linux/cpu.h>
+-#include <linux/freezer.h>
+ #include <linux/kthread.h>
  #include <linux/rcupdate.h>
- #include <asm/bitops.h>
-@@ -1903,6 +1904,9 @@
- {
-       struct net_device *dev = ptr;
+ #include <linux/smp.h>
+@@ -305,6 +304,11 @@
+       if (!in_interrupt() && local_softirq_pending())
+               invoke_softirq();
  
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       /* It is OK that we do not hold the group lock right now,
-        * as we run under the RTNL lock.
-        */
-@@ -1933,7 +1937,7 @@
-               pkt_dev->odev = NULL;
-       }
++#ifdef CONFIG_NO_HZ
++      /* Make sure that timer wheel updates are propagated */
++      if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
++              tick_nohz_stop_sched_tick();
++#endif
+       preempt_enable_no_resched();
+ }
  
--      odev = dev_get_by_name(ifname);
-+      odev = dev_get_by_name(&init_net, ifname);
-       if (!odev) {
-               printk("pktgen: no such netdevice: \"%s\"\n", ifname);
-               return -ENODEV;
-@@ -3284,6 +3288,8 @@
+@@ -486,6 +490,7 @@
+ static int ksoftirqd(void * __bind_cpu)
+ {
+       set_user_nice(current, 19);
++      current->flags |= PF_NOFREEZE;
  
        set_current_state(TASK_INTERRUPTIBLE);
  
-+      set_freezable();
-+
-       while (!kthread_should_stop()) {
-               pkt_dev = next_to_run(t);
+diff -Nurb linux-2.6.22-590/kernel/softlockup.c linux-2.6.22-570/kernel/softlockup.c
+--- linux-2.6.22-590/kernel/softlockup.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/softlockup.c       2007-07-08 19:32:17.000000000 -0400
+@@ -10,11 +10,9 @@
+ #include <linux/cpu.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+-#include <linux/freezer.h>
+ #include <linux/kthread.h>
+ #include <linux/notifier.h>
+ #include <linux/module.h>
+-#include <linux/kgdb.h>
  
-@@ -3568,7 +3574,7 @@
+ static DEFINE_SPINLOCK(print_lock);
  
-       printk(version);
+@@ -49,9 +47,6 @@
+ void touch_softlockup_watchdog(void)
+ {
+       __raw_get_cpu_var(touch_timestamp) = get_timestamp();
+-#ifdef CONFIG_KGDB
+-      atomic_set(&kgdb_sync_softlockup[raw_smp_processor_id()], 0);
+-#endif
+ }
+ EXPORT_SYMBOL(touch_softlockup_watchdog);
  
--      pg_proc_dir = proc_mkdir(PG_PROC_DIR, proc_net);
-+      pg_proc_dir = proc_mkdir(PG_PROC_DIR, init_net.proc_net);
-       if (!pg_proc_dir)
-               return -ENODEV;
-       pg_proc_dir->owner = THIS_MODULE;
-@@ -3577,7 +3583,7 @@
-       if (pe == NULL) {
-               printk("pktgen: ERROR: cannot create %s procfs entry.\n",
-                      PGCTRL);
--              proc_net_remove(PG_PROC_DIR);
-+              proc_net_remove(&init_net, PG_PROC_DIR);
-               return -EINVAL;
-       }
+@@ -121,6 +116,7 @@
+       struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
  
-@@ -3600,7 +3606,7 @@
-               printk("pktgen: ERROR: Initialization failed for all threads\n");
-               unregister_netdevice_notifier(&pktgen_notifier_block);
-               remove_proc_entry(PGCTRL, pg_proc_dir);
--              proc_net_remove(PG_PROC_DIR);
-+              proc_net_remove(&init_net, PG_PROC_DIR);
-               return -ENODEV;
+       sched_setscheduler(current, SCHED_FIFO, &param);
++      current->flags |= PF_NOFREEZE;
+       /* initialize timestamp */
+       touch_softlockup_watchdog();
+diff -Nurb linux-2.6.22-590/kernel/sys.c linux-2.6.22-570/kernel/sys.c
+--- linux-2.6.22-590/kernel/sys.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/sys.c      2008-01-23 19:16:05.000000000 -0500
+@@ -31,7 +31,6 @@
+ #include <linux/cn_proc.h>
+ #include <linux/getcpu.h>
+ #include <linux/task_io_accounting_ops.h>
+-#include <linux/seccomp.h>
+ #include <linux/cpu.h>
+ #include <linux/compat.h>
+@@ -1044,7 +1043,7 @@
+                       return -EPERM;
        }
+       if (new_egid != old_egid) {
+-              set_dumpable(current->mm, suid_dumpable);
++              current->mm->dumpable = suid_dumpable;
+               smp_wmb();
+       }
+       if (rgid != (gid_t) -1 ||
+@@ -1074,13 +1073,13 @@
  
-@@ -3627,7 +3633,7 @@
+       if (capable(CAP_SETGID)) {
+               if (old_egid != gid) {
+-                      set_dumpable(current->mm, suid_dumpable);
++                      current->mm->dumpable = suid_dumpable;
+                       smp_wmb();
+               }
+               current->gid = current->egid = current->sgid = current->fsgid = gid;
+       } else if ((gid == current->gid) || (gid == current->sgid)) {
+               if (old_egid != gid) {
+-                      set_dumpable(current->mm, suid_dumpable);
++                      current->mm->dumpable = suid_dumpable;
+                       smp_wmb();
+               }
+               current->egid = current->fsgid = gid;
+@@ -1111,7 +1110,7 @@
+       switch_uid(new_user);
  
-       /* Clean up proc file system */
-       remove_proc_entry(PGCTRL, pg_proc_dir);
--      proc_net_remove(PG_PROC_DIR);
-+      proc_net_remove(&init_net, PG_PROC_DIR);
- }
+       if (dumpclear) {
+-              set_dumpable(current->mm, suid_dumpable);
++              current->mm->dumpable = suid_dumpable;
+               smp_wmb();
+       }
+       current->uid = new_ruid;
+@@ -1167,7 +1166,7 @@
+               return -EAGAIN;
  
- module_init(pg_init);
-diff -Nurb linux-2.6.22-570/net/core/rtnetlink.c linux-2.6.22-590/net/core/rtnetlink.c
---- linux-2.6.22-570/net/core/rtnetlink.c      2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/core/rtnetlink.c      2008-01-02 13:56:38.000000000 -0500
-@@ -59,7 +59,6 @@
- };
+       if (new_euid != old_euid) {
+-              set_dumpable(current->mm, suid_dumpable);
++              current->mm->dumpable = suid_dumpable;
+               smp_wmb();
+       }
+       current->fsuid = current->euid = new_euid;
+@@ -1217,7 +1216,7 @@
+               return -EPERM;
  
- static DEFINE_MUTEX(rtnl_mutex);
--static struct sock *rtnl;
+       if (old_euid != uid) {
+-              set_dumpable(current->mm, suid_dumpable);
++              current->mm->dumpable = suid_dumpable;
+               smp_wmb();
+       }
+       current->fsuid = current->euid = uid;
+@@ -1262,7 +1261,7 @@
+       }
+       if (euid != (uid_t) -1) {
+               if (euid != current->euid) {
+-                      set_dumpable(current->mm, suid_dumpable);
++                      current->mm->dumpable = suid_dumpable;
+                       smp_wmb();
+               }
+               current->euid = euid;
+@@ -1312,7 +1311,7 @@
+       }
+       if (egid != (gid_t) -1) {
+               if (egid != current->egid) {
+-                      set_dumpable(current->mm, suid_dumpable);
++                      current->mm->dumpable = suid_dumpable;
+                       smp_wmb();
+               }
+               current->egid = egid;
+@@ -1358,7 +1357,7 @@
+           uid == current->suid || uid == current->fsuid || 
+           capable(CAP_SETUID)) {
+               if (uid != old_fsuid) {
+-                      set_dumpable(current->mm, suid_dumpable);
++                      current->mm->dumpable = suid_dumpable;
+                       smp_wmb();
+               }
+               current->fsuid = uid;
+@@ -1387,7 +1386,7 @@
+           gid == current->sgid || gid == current->fsgid || 
+           capable(CAP_SETGID)) {
+               if (gid != old_fsgid) {
+-                      set_dumpable(current->mm, suid_dumpable);
++                      current->mm->dumpable = suid_dumpable;
+                       smp_wmb();
+               }
+               current->fsgid = gid;
+@@ -2186,14 +2185,14 @@
+                       error = put_user(current->pdeath_signal, (int __user *)arg2);
+                       break;
+               case PR_GET_DUMPABLE:
+-                      error = get_dumpable(current->mm);
++                      error = current->mm->dumpable;
+                       break;
+               case PR_SET_DUMPABLE:
+                       if (arg2 < 0 || arg2 > 1) {
+                               error = -EINVAL;
+                               break;
+                       }
+-                      set_dumpable(current->mm, arg2);
++                      current->mm->dumpable = arg2;
+                       break;
  
- void rtnl_lock(void)
- {
-@@ -73,9 +72,17 @@
+               case PR_SET_UNALIGN:
+@@ -2262,13 +2261,6 @@
+                       error = SET_ENDIAN(current, arg2);
+                       break;
  
- void rtnl_unlock(void)
- {
-+      struct net *net;
-       mutex_unlock(&rtnl_mutex);
-+      
-+      net_lock();
-+      for_each_net(net) {
-+              struct sock *rtnl = net->rtnl;
-       if (rtnl && rtnl->sk_receive_queue.qlen)
-               rtnl->sk_data_ready(rtnl, 0);
-+      }
-+      net_unlock();
-+
-       netdev_run_todo();
+-              case PR_GET_SECCOMP:
+-                      error = prctl_get_seccomp();
+-                      break;
+-              case PR_SET_SECCOMP:
+-                      error = prctl_set_seccomp(arg2);
+-                      break;
+-
+               default:
+                       error = -EINVAL;
+                       break;
+@@ -2305,61 +2297,3 @@
+       }
+       return err ? -EFAULT : 0;
  }
+-
+-char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
+-
+-static void argv_cleanup(char **argv, char **envp)
+-{
+-      argv_free(argv);
+-}
+-
+-/**
+- * Trigger an orderly system poweroff
+- * @force: force poweroff if command execution fails
+- *
+- * This may be called from any context to trigger a system shutdown.
+- * If the orderly shutdown fails, it will force an immediate shutdown.
+- */
+-int orderly_poweroff(bool force)
+-{
+-      int argc;
+-      char **argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc);
+-      static char *envp[] = {
+-              "HOME=/",
+-              "PATH=/sbin:/bin:/usr/sbin:/usr/bin",
+-              NULL
+-      };
+-      int ret = -ENOMEM;
+-      struct subprocess_info *info;
+-
+-      if (argv == NULL) {
+-              printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n",
+-                     __func__, poweroff_cmd);
+-              goto out;
+-      }
+-
+-      info = call_usermodehelper_setup(argv[0], argv, envp);
+-      if (info == NULL) {
+-              argv_free(argv);
+-              goto out;
+-      }
+-
+-      call_usermodehelper_setcleanup(info, argv_cleanup);
+-
+-      ret = call_usermodehelper_exec(info, UMH_NO_WAIT);
+-
+-  out:
+-      if (ret && force) {
+-              printk(KERN_WARNING "Failed to start orderly shutdown: "
+-                     "forcing the issue\n");
+-
+-              /* I guess this should try to kick off some daemon to
+-                 sync and poweroff asap.  Or not even bother syncing
+-                 if we're doing an emergency shutdown? */
+-              emergency_sync();
+-              kernel_power_off();
+-      }
+-
+-      return ret;
+-}
+-EXPORT_SYMBOL_GPL(orderly_poweroff);
+diff -Nurb linux-2.6.22-590/kernel/sysctl.c linux-2.6.22-570/kernel/sysctl.c
+--- linux-2.6.22-590/kernel/sysctl.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/sysctl.c   2008-01-23 19:16:05.000000000 -0500
+@@ -45,13 +45,13 @@
+ #include <linux/syscalls.h>
+ #include <linux/nfs_fs.h>
+ #include <linux/acpi.h>
+-#include <linux/reboot.h>
+-#include <linux/fs.h>
+-#include <net/net_namespace.h>
  
-@@ -97,6 +104,19 @@
-       return 0;
- }
+ #include <asm/uaccess.h>
+ #include <asm/processor.h>
  
-+int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
-+                               struct rtattr *rta, int len)
-+{
-+      if (RTA_PAYLOAD(rta) < len)
-+              return -1;
-+      if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) {
-+              rta = RTA_DATA(rta) + RTA_ALIGN(len);
-+              return rtattr_parse_nested(tb, maxattr, rta);
-+      }
-+      memset(tb, 0, sizeof(struct rtattr *) * maxattr);
-+      return 0;
-+}
++extern int proc_nr_files(ctl_table *table, int write, struct file *filp,
++                     void __user *buffer, size_t *lenp, loff_t *ppos);
 +
- static struct rtnl_link *rtnl_msg_handlers[NPROTO];
- static inline int rtm_msgindex(int msgtype)
-@@ -243,6 +263,143 @@
- EXPORT_SYMBOL_GPL(rtnl_unregister_all);
+ #ifdef CONFIG_X86
+ #include <asm/nmi.h>
+ #include <asm/stacktrace.h>
+@@ -140,10 +140,6 @@
+                              void __user *buffer, size_t *lenp, loff_t *ppos);
+ #endif
  
-+static LIST_HEAD(link_ops);
-+
-+/**
-+ * __rtnl_link_register - Register rtnl_link_ops with rtnetlink.
-+ * @ops: struct rtnl_link_ops * to register
-+ *
-+ * The caller must hold the rtnl_mutex. This function should be used
-+ * by drivers that create devices during module initialization. It
-+ * must be called before registering the devices.
-+ *
-+ * Returns 0 on success or a negative error code.
-+ */
-+int __rtnl_link_register(struct rtnl_link_ops *ops)
-+{
-+      list_add_tail(&ops->list, &link_ops);
-+      return 0;
-+}
-+
-+EXPORT_SYMBOL_GPL(__rtnl_link_register);
-+
-+/**
-+ * rtnl_link_register - Register rtnl_link_ops with rtnetlink.
-+ * @ops: struct rtnl_link_ops * to register
-+ *
-+ * Returns 0 on success or a negative error code.
-+ */
-+int rtnl_link_register(struct rtnl_link_ops *ops)
-+{
-+      int err;
-+
-+      rtnl_lock();
-+      err = __rtnl_link_register(ops);
-+      rtnl_unlock();
-+      return err;
-+}
-+
-+EXPORT_SYMBOL_GPL(rtnl_link_register);
-+
-+/**
-+ * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
-+ * @ops: struct rtnl_link_ops * to unregister
-+ *
-+ * The caller must hold the rtnl_mutex. This function should be used
-+ * by drivers that unregister devices during module unloading. It must
-+ * be called after unregistering the devices.
-+ */
-+void __rtnl_link_unregister(struct rtnl_link_ops *ops)
-+{
-+      list_del(&ops->list);
-+}
-+
-+EXPORT_SYMBOL_GPL(__rtnl_link_unregister);
-+
-+/**
-+ * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
-+ * @ops: struct rtnl_link_ops * to unregister
-+ */
-+void rtnl_link_unregister(struct rtnl_link_ops *ops)
-+{
-+      rtnl_lock();
-+      __rtnl_link_unregister(ops);
-+      rtnl_unlock();
-+}
-+
-+EXPORT_SYMBOL_GPL(rtnl_link_unregister);
-+
-+static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind)
-+{
-+      const struct rtnl_link_ops *ops;
-+
-+      list_for_each_entry(ops, &link_ops, list) {
-+              if (!strcmp(ops->kind, kind))
-+                      return ops;
-+      }
-+      return NULL;
-+}
-+
-+static size_t rtnl_link_get_size(const struct net_device *dev)
-+{
-+      const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
-+      size_t size;
-+
-+      if (!ops)
-+              return 0;
-+
-+      size = nlmsg_total_size(sizeof(struct nlattr)) + /* IFLA_LINKINFO */
-+             nlmsg_total_size(strlen(ops->kind) + 1);  /* IFLA_INFO_KIND */
-+
-+      if (ops->get_size)
-+              /* IFLA_INFO_DATA + nested data */
-+              size += nlmsg_total_size(sizeof(struct nlattr)) +
-+                      ops->get_size(dev);
-+
-+      if (ops->get_xstats_size)
-+              size += ops->get_xstats_size(dev);      /* IFLA_INFO_XSTATS */
-+
-+      return size;
-+}
-+
-+static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev)
-+{
-+      const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
-+      struct nlattr *linkinfo, *data;
-+      int err = -EMSGSIZE;
-+
-+      linkinfo = nla_nest_start(skb, IFLA_LINKINFO);
-+      if (linkinfo == NULL)
-+              goto out;
-+
-+      if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0)
-+              goto err_cancel_link;
-+      if (ops->fill_xstats) {
-+              err = ops->fill_xstats(skb, dev);
-+              if (err < 0)
-+                      goto err_cancel_link;
-+      }
-+      if (ops->fill_info) {
-+              data = nla_nest_start(skb, IFLA_INFO_DATA);
-+              if (data == NULL)
-+                      goto err_cancel_link;
-+              err = ops->fill_info(skb, dev);
-+              if (err < 0)
-+                      goto err_cancel_data;
-+              nla_nest_end(skb, data);
-+      }
-+
-+      nla_nest_end(skb, linkinfo);
-+      return 0;
+-#ifdef CONFIG_NET
+-static void sysctl_net_init(struct net *net);
+-#endif
+-
+ static ctl_table root_table[];
+ static struct ctl_table_header root_table_header =
+       { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) };
+@@ -207,10 +203,7 @@
+               .mode           = 0555,
+               .child          = dev_table,
+       },
+-/*
+- * NOTE: do not add new entries to this table unless you have read
+- * Documentation/sysctl/ctl_unnumbered.txt
+- */
 +
-+err_cancel_data:
-+      nla_nest_cancel(skb, data);
-+err_cancel_link:
-+      nla_nest_cancel(skb, linkinfo);
-+out:
-+      return err;
-+}
+       { .ctl_name = 0 }
+ };
+@@ -224,15 +217,6 @@
+               .proc_handler   = &proc_dointvec,
+       },
+       {
+-              .ctl_name       = KERN_POWEROFF_CMD,
+-              .procname       = "poweroff_cmd",
+-              .data           = &poweroff_cmd,
+-              .maxlen         = POWEROFF_CMD_PATH_LEN,
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dostring,
+-              .strategy       = &sysctl_string,
+-      },
+-      {
+               .ctl_name       = KERN_CORE_USES_PID,
+               .procname       = "core_uses_pid",
+               .data           = &core_uses_pid,
+@@ -641,20 +625,7 @@
+               .proc_handler   = &proc_dointvec,
+       },
+ #endif
+-#ifdef CONFIG_SECURITY
+-      {
+-              .ctl_name       = CTL_UNNUMBERED,
+-              .procname       = "mmap_min_addr",
+-              .data           = &mmap_min_addr,
+-              .maxlen         = sizeof(unsigned long),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_doulongvec_minmax,
+-      },
+-#endif
+-/*
+- * NOTE: do not add new entries to this table unless you have read
+- * Documentation/sysctl/ctl_unnumbered.txt
+- */
 +
- static const int rtm_min[RTM_NR_FAMILIES] =
- {
-       [RTM_FAM(RTM_NEWLINK)]      = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
-@@ -296,8 +453,9 @@
-       return ret;
- }
+       { .ctl_name = 0 }
+ };
+@@ -773,14 +744,6 @@
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+        },
+-       {
+-              .ctl_name       = VM_HUGETLB_TREAT_MOVABLE,
+-              .procname       = "hugepages_treat_as_movable",
+-              .data           = &hugepages_treat_as_movable,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &hugetlb_treat_movable_handler,
+-      },
+ #endif
+       {
+               .ctl_name       = VM_LOWMEM_RESERVE_RATIO,
+@@ -929,10 +892,6 @@
+               .extra1         = &zero,
+       },
+ #endif
+-/*
+- * NOTE: do not add new entries to this table unless you have read
+- * Documentation/sysctl/ctl_unnumbered.txt
+- */
+       { .ctl_name = 0 }
+ };
  
--int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
-+int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo)
- {
-+      struct sock *rtnl = net->rtnl;
-       int err = 0;
+@@ -1073,28 +1032,10 @@
+               .child          = binfmt_misc_table,
+       },
+ #endif
+-/*
+- * NOTE: do not add new entries to this table unless you have read
+- * Documentation/sysctl/ctl_unnumbered.txt
+- */
+       { .ctl_name = 0 }
+ };
  
-       NETLINK_CB(skb).dst_group = group;
-@@ -309,14 +467,17 @@
-       return err;
- }
+ static ctl_table debug_table[] = {
+-#ifdef CONFIG_X86
+-      {
+-              .ctl_name       = DEBUG_UNHANDLED_SIGNALS,
+-              .procname       = "show-unhandled-signals",
+-              .data           = &show_unhandled_signals,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = proc_dointvec
+-      },
+-#endif
+-/*
+- * NOTE: do not add new entries to this table unless you have read
+- * Documentation/sysctl/ctl_unnumbered.txt
+- */
+       { .ctl_name = 0 }
+ };
  
--int rtnl_unicast(struct sk_buff *skb, u32 pid)
-+int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid)
+@@ -1156,11 +1097,6 @@
  {
-+      struct sock *rtnl = net->rtnl;
-+
-       return nlmsg_unicast(rtnl, skb, pid);
- }
--int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
-+int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
-               struct nlmsghdr *nlh, gfp_t flags)
+       struct ctl_table_header *head;
+       struct list_head *tmp;
+-      struct net *net = current->nsproxy->net_ns;
+-
+-      if (!net->net_table_header.ctl_table)
+-              sysctl_net_init(net);
+-
+       spin_lock(&sysctl_lock);
+       if (prev) {
+               tmp = &prev->ctl_entry;
+@@ -1178,10 +1114,6 @@
+       next:
+               tmp = tmp->next;
+               if (tmp == &root_table_header.ctl_entry)
+-#ifdef CONFIG_NET
+-                      tmp = &net->net_table_header.ctl_entry;
+-              else if (tmp == &net->net_table_header.ctl_entry)
+-#endif
+                       break;
+       }
+       spin_unlock(&sysctl_lock);
+@@ -1297,6 +1229,7 @@
+                       void __user *newval, size_t newlen)
  {
-+      struct sock *rtnl = net->rtnl;
-       int report = 0;
+       int op = 0, rc;
++      size_t len;
  
-       if (nlh)
-@@ -325,8 +486,10 @@
-       return nlmsg_notify(rtnl, skb, pid, group, report, flags);
+       if (oldval)
+               op |= 004;
+@@ -1317,10 +1250,25 @@
+       /* If there is no strategy routine, or if the strategy returns
+        * zero, proceed with automatic r/w */
+       if (table->data && table->maxlen) {
+-              rc = sysctl_data(table, name, nlen, oldval, oldlenp,
+-                               newval, newlen);
+-              if (rc < 0)
+-                      return rc;
++              if (oldval && oldlenp) {
++                      if (get_user(len, oldlenp))
++                              return -EFAULT;
++                      if (len) {
++                              if (len > table->maxlen)
++                                      len = table->maxlen;
++                              if(copy_to_user(oldval, table->data, len))
++                                      return -EFAULT;
++                              if(put_user(len, oldlenp))
++                                      return -EFAULT;
++                      }
++              }
++              if (newval && newlen) {
++                      len = newlen;
++                      if (len > table->maxlen)
++                              len = table->maxlen;
++                      if(copy_from_user(table->data, newval, len))
++                              return -EFAULT;
++              }
+       }
+       return 0;
  }
--void rtnl_set_sk_err(u32 group, int error)
-+void rtnl_set_sk_err(struct net *net, u32 group, int error)
+@@ -1411,8 +1359,7 @@
+  * This routine returns %NULL on a failure to register, and a pointer
+  * to the table header on success.
+  */
+-static struct ctl_table_header *__register_sysctl_table(
+-      struct ctl_table_header *root, ctl_table * table)
++struct ctl_table_header *register_sysctl_table(ctl_table * table)
  {
-+      struct sock *rtnl = net->rtnl;
-+
-       netlink_set_err(rtnl, 0, group, error);
+       struct ctl_table_header *tmp;
+       tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
+@@ -1424,16 +1371,11 @@
+       tmp->unregistering = NULL;
+       sysctl_set_parent(NULL, table);
+       spin_lock(&sysctl_lock);
+-      list_add_tail(&tmp->ctl_entry, &root->ctl_entry);
++      list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
+       spin_unlock(&sysctl_lock);
+       return tmp;
  }
  
-@@ -437,7 +600,7 @@
-       a->tx_compressed = b->tx_compressed;
- };
+-struct ctl_table_header *register_sysctl_table(ctl_table *table)
+-{
+-      return __register_sysctl_table(&root_table_header, table);
+-}
+-
+ /**
+  * unregister_sysctl_table - unregister a sysctl table hierarchy
+  * @header: the header returned from register_sysctl_table
+@@ -1450,92 +1392,6 @@
+       kfree(header);
+ }
  
--static inline size_t if_nlmsg_size(void)
-+static inline size_t if_nlmsg_size(const struct net_device *dev)
+-#ifdef CONFIG_NET
+-
+-static void *fixup_table_addr(void *addr,
+-                            const char *start, size_t size, const char *new)
+-{
+-      char *ptr = addr;
+-      if ((ptr >= start) && (ptr < (start + size)))
+-              ptr += new - start;
+-      return ptr;
+-}
+-
+-static void table_fixup(struct ctl_table *table,
+-                      const void *start, size_t size, const void *new)
+-{
+-      for (; table->ctl_name || table->procname; table++) {
+-              table->data   = fixup_table_addr(table->data, start, size, new);
+-              table->extra1 = fixup_table_addr(table->extra1, start, size, new);
+-              table->extra2 = fixup_table_addr(table->extra2, start, size, new);
+-
+-              /* Whee recursive functions on the kernel stack */
+-              if (table->child)
+-                      table_fixup(table->child, start, size, new);
+-      }
+-}
+-
+-static unsigned count_table_entries(struct ctl_table *table)
+-{
+-      unsigned entries = 0;
+-      for (; table->ctl_name || table->procname; table++) {
+-              entries += 1;
+-
+-              if (table->child)
+-                      entries += count_table_entries(table->child);
+-      }
+-      entries += 1; /* Null terminating entry */
+-      return entries;
+-}
+-
+-static struct ctl_table *copy_table_entries(
+-      struct ctl_table *dest, struct ctl_table *src)
+-{
+-      struct ctl_table *table = dest;
+-      for (; src->ctl_name || src->procname; src++) {
+-              *dest++ = *table;
+-      }
+-      dest++; /* Null terminating entry */
+-      for (; table->ctl_name || table->procname; table++) {
+-              if (table->child)
+-                      dest = copy_table_entries(dest, table->child);
+-      }
+-      return dest;
+-}
+-
+-static void sysctl_net_init(struct net *net)
+-{
+-      unsigned entries;
+-      struct ctl_table *table;
+-      
+-      entries = count_table_entries(net_root_table);
+-      table = kzalloc(GFP_KERNEL, sizeof(*table)*entries);
+-      /* FIXME free table... */
+-
+-      copy_table_entries(table, net_root_table);
+-      table_fixup(table, &init_net, sizeof(init_net), net);
+-
+-      net->net_table_header.ctl_table = table;
+-      INIT_LIST_HEAD(&net->net_table_header.ctl_entry);
+-}
+-
+-struct ctl_table_header *register_net_sysctl_table(struct net *net, struct ctl_table *table)
+-{
+-      if (!net->net_table_header.ctl_table)
+-              sysctl_net_init(net);
+-      table_fixup(table, &init_net, sizeof(init_net), net);
+-      return __register_sysctl_table(&net->net_table_header, table);
+-}
+-EXPORT_SYMBOL_GPL(register_net_sysctl_table);
+-
+-void unregister_net_sysctl_table(struct ctl_table_header *header)
+-{
+-      return unregister_sysctl_table(header);
+-}
+-EXPORT_SYMBOL_GPL(unregister_net_sysctl_table);
+-#endif
+-
+-
+ #else /* !CONFIG_SYSCTL */
+ struct ctl_table_header *register_sysctl_table(ctl_table * table)
  {
-       return NLMSG_ALIGN(sizeof(struct ifinfomsg))
-              + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
-@@ -452,7 +615,8 @@
-              + nla_total_size(4) /* IFLA_LINK */
-              + nla_total_size(4) /* IFLA_MASTER */
-              + nla_total_size(1) /* IFLA_OPERSTATE */
--             + nla_total_size(1); /* IFLA_LINKMODE */
-+             + nla_total_size(1) /* IFLA_LINKMODE */
-+             + rtnl_link_get_size(dev); /* IFLA_LINKINFO */
+@@ -2311,40 +2167,6 @@
+  * General sysctl support routines 
+  */
+-/* The generic sysctl data routine (used if no strategy routine supplied) */
+-int sysctl_data(ctl_table *table, int __user *name, int nlen,
+-              void __user *oldval, size_t __user *oldlenp,
+-              void __user *newval, size_t newlen)
+-{
+-      size_t len;
+-
+-      /* Get out of I don't have a variable */
+-      if (!table->data || !table->maxlen)
+-              return -ENOTDIR;
+-
+-      if (oldval && oldlenp) {
+-              if (get_user(len, oldlenp))
+-                      return -EFAULT;
+-              if (len) {
+-                      if (len > table->maxlen)
+-                              len = table->maxlen;
+-                      if (copy_to_user(oldval, table->data, len))
+-                              return -EFAULT;
+-                      if (put_user(len, oldlenp))
+-                              return -EFAULT;
+-              }
+-      }
+-
+-      if (newval && newlen) {
+-              if (newlen > table->maxlen)
+-                      newlen = table->maxlen;
+-
+-              if (copy_from_user(table->data, newval, newlen))
+-                      return -EFAULT;
+-      }
+-      return 1;
+-}
+-
+ /* The generic string strategy routine: */
+ int sysctl_string(ctl_table *table, int __user *name, int nlen,
+                 void __user *oldval, size_t __user *oldlenp,
+@@ -2533,13 +2355,6 @@
+       return -ENOSYS;
  }
  
- static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
-@@ -522,6 +686,11 @@
-               }
-       }
+-int sysctl_data(ctl_table *table, int __user *name, int nlen,
+-                void __user *oldval, size_t __user *oldlenp,
+-                void __user *newval, size_t newlen)
+-{
+-      return -ENOSYS;
+-}
+-
+ int sysctl_string(ctl_table *table, int __user *name, int nlen,
+                 void __user *oldval, size_t __user *oldlenp,
+                 void __user *newval, size_t newlen)
+@@ -2587,5 +2402,4 @@
+ EXPORT_SYMBOL(sysctl_jiffies);
+ EXPORT_SYMBOL(sysctl_ms_jiffies);
+ EXPORT_SYMBOL(sysctl_string);
+-EXPORT_SYMBOL(sysctl_data);
+ EXPORT_SYMBOL(unregister_sysctl_table);
+diff -Nurb linux-2.6.22-590/kernel/taskstats.c linux-2.6.22-570/kernel/taskstats.c
+--- linux-2.6.22-590/kernel/taskstats.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/taskstats.c        2007-07-08 19:32:17.000000000 -0400
+@@ -196,8 +196,6 @@
  
-+      if (dev->rtnl_link_ops) {
-+              if (rtnl_link_fill(skb, dev) < 0)
-+                      goto nla_put_failure;
-+      }
+       /* fill in basic acct fields */
+       stats->version = TASKSTATS_VERSION;
+-      stats->nvcsw = tsk->nvcsw;
+-      stats->nivcsw = tsk->nivcsw;
+       bacct_add_tsk(stats, tsk);
+       /* fill in extended acct fields */
+@@ -244,8 +242,6 @@
+                */
+               delayacct_add_tsk(stats, tsk);
+-              stats->nvcsw += tsk->nvcsw;
+-              stats->nivcsw += tsk->nivcsw;
+       } while_each_thread(first, tsk);
+       unlock_task_sighand(first, &flags);
+diff -Nurb linux-2.6.22-590/kernel/time/tick-sched.c linux-2.6.22-570/kernel/time/tick-sched.c
+--- linux-2.6.22-590/kernel/time/tick-sched.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/time/tick-sched.c  2007-07-08 19:32:17.000000000 -0400
+@@ -153,7 +153,6 @@
+       unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
+       struct tick_sched *ts;
+       ktime_t last_update, expires, now, delta;
+-      struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+       int cpu;
+       local_irq_save(flags);
+@@ -291,34 +290,11 @@
+ out:
+       ts->next_jiffies = next_jiffies;
+       ts->last_jiffies = last_jiffies;
+-      ts->sleep_length = ktime_sub(dev->next_event, now);
+ end:
+       local_irq_restore(flags);
+ }
+ /**
+- * tick_nohz_get_sleep_length - return the length of the current sleep
+- *
+- * Called from power state control code with interrupts disabled
+- */
+-ktime_t tick_nohz_get_sleep_length(void)
+-{
+-       struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+-
+-       return ts->sleep_length;
+-}
+-
+-/**
+- * tick_nohz_get_idle_jiffies - returns the current idle jiffie count
+- */
+-unsigned long tick_nohz_get_idle_jiffies(void)
+-{
+-       struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
+-
+-       return ts->idle_jiffies;
+-}
+-
+-/**
+  * nohz_restart_sched_tick - restart the idle tick from the idle task
+  *
+  * Restart the idle tick when the CPU is woken up from idle
+diff -Nurb linux-2.6.22-590/kernel/time/timekeeping.c linux-2.6.22-570/kernel/time/timekeeping.c
+--- linux-2.6.22-590/kernel/time/timekeeping.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/time/timekeeping.c 2007-07-08 19:32:17.000000000 -0400
+@@ -39,7 +39,7 @@
+  */
+ struct timespec xtime __attribute__ ((aligned (16)));
+ struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
+-static unsigned long total_sleep_time;
 +
      return nlmsg_end(skb, nlh);
EXPORT_SYMBOL(xtime);
  
- nla_put_failure:
-@@ -531,12 +700,13 @@
  
- static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
- {
-+      struct net *net = skb->sk->sk_net;
-       int idx;
-       int s_idx = cb->args[0];
-       struct net_device *dev;
+@@ -251,7 +251,6 @@
+       xtime.tv_nsec = 0;
+       set_normalized_timespec(&wall_to_monotonic,
+               -xtime.tv_sec, -xtime.tv_nsec);
+-      total_sleep_time = 0;
  
-       idx = 0;
--      for_each_netdev(dev) {
-+      for_each_netdev(net, dev) {
-               if (!nx_dev_visible(skb->sk->sk_nx_info, dev))
-                       continue;
-               if (idx < s_idx)
-@@ -555,6 +725,8 @@
+       write_sequnlock_irqrestore(&xtime_lock, flags);
+ }
+@@ -283,7 +282,6 @@
  
- static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
-       [IFLA_IFNAME]           = { .type = NLA_STRING, .len = IFNAMSIZ-1 },
-+      [IFLA_ADDRESS]          = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
-+      [IFLA_BROADCAST]        = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
-       [IFLA_MAP]              = { .len = sizeof(struct rtnl_link_ifmap) },
-       [IFLA_MTU]              = { .type = NLA_U32 },
-       [IFLA_TXQLEN]           = { .type = NLA_U32 },
-@@ -563,44 +735,16 @@
-       [IFLA_LINKMODE]         = { .type = NLA_U8 },
- };
+               xtime.tv_sec += sleep_length;
+               wall_to_monotonic.tv_sec -= sleep_length;
+-              total_sleep_time += sleep_length;
+       }
+       /* re-base the last cycle value */
+       clock->cycle_last = clocksource_read(clock);
+@@ -478,34 +476,3 @@
+       change_clocksource();
+       update_vsyscall(&xtime, clock);
+ }
+-
+-/**
+- * getboottime - Return the real time of system boot.
+- * @ts:               pointer to the timespec to be set
+- *
+- * Returns the time of day in a timespec.
+- *
+- * This is based on the wall_to_monotonic offset and the total suspend
+- * time. Calls to settimeofday will affect the value returned (which
+- * basically means that however wrong your real time clock is at boot time,
+- * you get the right time here).
+- */
+-void getboottime(struct timespec *ts)
+-{
+-      set_normalized_timespec(ts,
+-              - (wall_to_monotonic.tv_sec + total_sleep_time),
+-              - wall_to_monotonic.tv_nsec);
+-}
+-
+-EXPORT_SYMBOL(getboottime);
+-
+-/**
+- * monotonic_to_bootbased - Convert the monotonic time to boot based.
+- * @ts:               pointer to the timespec to be converted
+- */
+-void monotonic_to_bootbased(struct timespec *ts)
+-{
+-      ts->tv_sec += total_sleep_time;
+-}
+-
+-EXPORT_SYMBOL(monotonic_to_bootbased);
+diff -Nurb linux-2.6.22-590/kernel/timer.c linux-2.6.22-570/kernel/timer.c
+--- linux-2.6.22-590/kernel/timer.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/timer.c    2008-01-23 19:16:05.000000000 -0500
+@@ -36,7 +36,6 @@
+ #include <linux/delay.h>
+ #include <linux/tick.h>
+ #include <linux/kallsyms.h>
+-#include <linux/kgdb.h>
+ #include <linux/vs_base.h>
+ #include <linux/vs_cvirt.h>
+ #include <linux/vs_pid.h>
+@@ -887,11 +886,7 @@
+  */
+ void run_local_timers(void)
+ {
+-      int this_cpu = smp_processor_id();
+       raise_softirq(TIMER_SOFTIRQ);
+-#ifdef CONFIG_KGDB
+-      if(!atomic_read(&kgdb_sync_softlockup[this_cpu]))
+-#endif
+       softlockup_tick();
+ }
  
--static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+@@ -1130,7 +1125,6 @@
+               getnstimeofday(&tp);
+               tp.tv_sec += wall_to_monotonic.tv_sec;
+               tp.tv_nsec += wall_to_monotonic.tv_nsec;
+-              monotonic_to_bootbased(&tp);
+               if (tp.tv_nsec - NSEC_PER_SEC >= 0) {
+                       tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC;
+                       tp.tv_sec++;
+diff -Nurb linux-2.6.22-590/kernel/unwind.c linux-2.6.22-570/kernel/unwind.c
+--- linux-2.6.22-590/kernel/unwind.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/unwind.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,1288 +0,0 @@
+-/*
+- * Copyright (C) 2002-2006 Novell, Inc.
+- *    Jan Beulich <jbeulich@novell.com>
+- * This code is released under version 2 of the GNU GPL.
+- *
+- * A simple API for unwinding kernel stacks.  This is used for
+- * debugging and error reporting purposes.  The kernel doesn't need
+- * full-blown stack unwinding with all the bells and whistles, so there
+- * is not much point in implementing the full Dwarf2 unwind API.
+- */
+-
+-#include <linux/unwind.h>
+-#include <linux/module.h>
+-#include <linux/bootmem.h>
+-#include <linux/sort.h>
+-#include <linux/stop_machine.h>
+-#include <linux/uaccess.h>
+-#include <asm/sections.h>
+-#include <asm/uaccess.h>
+-#include <asm/unaligned.h>
+-
+-extern const char __start_unwind[], __end_unwind[];
+-extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];
+-
+-#define MAX_STACK_DEPTH 8
+-
+-#define EXTRA_INFO(f) { \
+-              BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
+-                                % FIELD_SIZEOF(struct unwind_frame_info, f)) \
+-              + offsetof(struct unwind_frame_info, f) \
+-                / FIELD_SIZEOF(struct unwind_frame_info, f), \
+-              FIELD_SIZEOF(struct unwind_frame_info, f) \
+-      }
+-#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
+-
+-static const struct {
+-      unsigned offs:BITS_PER_LONG / 2;
+-      unsigned width:BITS_PER_LONG / 2;
+-} reg_info[] = {
+-      UNW_REGISTER_INFO
+-};
+-
+-#undef PTREGS_INFO
+-#undef EXTRA_INFO
+-
+-#ifndef REG_INVALID
+-#define REG_INVALID(r) (reg_info[r].width == 0)
+-#endif
+-
+-#define DW_CFA_nop                          0x00
+-#define DW_CFA_set_loc                      0x01
+-#define DW_CFA_advance_loc1                 0x02
+-#define DW_CFA_advance_loc2                 0x03
+-#define DW_CFA_advance_loc4                 0x04
+-#define DW_CFA_offset_extended              0x05
+-#define DW_CFA_restore_extended             0x06
+-#define DW_CFA_undefined                    0x07
+-#define DW_CFA_same_value                   0x08
+-#define DW_CFA_register                     0x09
+-#define DW_CFA_remember_state               0x0a
+-#define DW_CFA_restore_state                0x0b
+-#define DW_CFA_def_cfa                      0x0c
+-#define DW_CFA_def_cfa_register             0x0d
+-#define DW_CFA_def_cfa_offset               0x0e
+-#define DW_CFA_def_cfa_expression           0x0f
+-#define DW_CFA_expression                   0x10
+-#define DW_CFA_offset_extended_sf           0x11
+-#define DW_CFA_def_cfa_sf                   0x12
+-#define DW_CFA_def_cfa_offset_sf            0x13
+-#define DW_CFA_val_offset                   0x14
+-#define DW_CFA_val_offset_sf                0x15
+-#define DW_CFA_val_expression               0x16
+-#define DW_CFA_lo_user                      0x1c
+-#define DW_CFA_GNU_window_save              0x2d
+-#define DW_CFA_GNU_args_size                0x2e
+-#define DW_CFA_GNU_negative_offset_extended 0x2f
+-#define DW_CFA_hi_user                      0x3f
+-
+-#define DW_EH_PE_FORM     0x07
+-#define DW_EH_PE_native   0x00
+-#define DW_EH_PE_leb128   0x01
+-#define DW_EH_PE_data2    0x02
+-#define DW_EH_PE_data4    0x03
+-#define DW_EH_PE_data8    0x04
+-#define DW_EH_PE_signed   0x08
+-#define DW_EH_PE_ADJUST   0x70
+-#define DW_EH_PE_abs      0x00
+-#define DW_EH_PE_pcrel    0x10
+-#define DW_EH_PE_textrel  0x20
+-#define DW_EH_PE_datarel  0x30
+-#define DW_EH_PE_funcrel  0x40
+-#define DW_EH_PE_aligned  0x50
+-#define DW_EH_PE_indirect 0x80
+-#define DW_EH_PE_omit     0xff
+-
+-typedef unsigned long uleb128_t;
+-typedef   signed long sleb128_t;
+-#define sleb128abs __builtin_labs
+-
+-static struct unwind_table {
+-      struct {
+-              unsigned long pc;
+-              unsigned long range;
+-      } core, init;
+-      const void *address;
+-      unsigned long size;
+-      const unsigned char *header;
+-      unsigned long hdrsz;
+-      struct unwind_table *link;
+-      const char *name;
+-} root_table;
+-
+-struct unwind_item {
+-      enum item_location {
+-              Nowhere,
+-              Memory,
+-              Register,
+-              Value
+-      } where;
+-      uleb128_t value;
+-};
+-
+-struct unwind_state {
+-      uleb128_t loc, org;
+-      const u8 *cieStart, *cieEnd;
+-      uleb128_t codeAlign;
+-      sleb128_t dataAlign;
+-      struct cfa {
+-              uleb128_t reg, offs;
+-      } cfa;
+-      struct unwind_item regs[ARRAY_SIZE(reg_info)];
+-      unsigned stackDepth:8;
+-      unsigned version:8;
+-      const u8 *label;
+-      const u8 *stack[MAX_STACK_DEPTH];
+-};
+-
+-static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
+-
+-static unsigned unwind_debug;
+-static int __init unwind_debug_setup(char *s)
+-{
+-      unwind_debug = simple_strtoul(s, NULL, 0);
+-      return 1;
+-}
+-__setup("unwind_debug=", unwind_debug_setup);
+-#define dprintk(lvl, fmt, args...) \
+-      ((void)(lvl > unwind_debug \
+-       || printk(KERN_DEBUG "unwind: " fmt "\n", ##args)))
+-
+-static struct unwind_table *find_table(unsigned long pc)
+-{
+-      struct unwind_table *table;
+-
+-      for (table = &root_table; table; table = table->link)
+-              if ((pc >= table->core.pc
+-                   && pc < table->core.pc + table->core.range)
+-                  || (pc >= table->init.pc
+-                      && pc < table->init.pc + table->init.range))
+-                      break;
+-
+-      return table;
+-}
+-
+-static unsigned long read_pointer(const u8 **pLoc,
+-                                  const void *end,
+-                                  signed ptrType,
+-                                  unsigned long text_base,
+-                                  unsigned long data_base);
+-
+-static void init_unwind_table(struct unwind_table *table,
+-                              const char *name,
+-                              const void *core_start,
+-                              unsigned long core_size,
+-                              const void *init_start,
+-                              unsigned long init_size,
+-                              const void *table_start,
+-                              unsigned long table_size,
+-                              const u8 *header_start,
+-                              unsigned long header_size)
+-{
+-      const u8 *ptr = header_start + 4;
+-      const u8 *end = header_start + header_size;
+-
+-      table->core.pc = (unsigned long)core_start;
+-      table->core.range = core_size;
+-      table->init.pc = (unsigned long)init_start;
+-      table->init.range = init_size;
+-      table->address = table_start;
+-      table->size = table_size;
+-      /* See if the linker provided table looks valid. */
+-      if (header_size <= 4
+-          || header_start[0] != 1
+-          || (void *)read_pointer(&ptr, end, header_start[1], 0, 0)
+-             != table_start
+-          || !read_pointer(&ptr, end, header_start[2], 0, 0)
+-          || !read_pointer(&ptr, end, header_start[3], 0,
+-                           (unsigned long)header_start)
+-          || !read_pointer(&ptr, end, header_start[3], 0,
+-                           (unsigned long)header_start))
+-              header_start = NULL;
+-      table->hdrsz = header_size;
+-      smp_wmb();
+-      table->header = header_start;
+-      table->link = NULL;
+-      table->name = name;
+-}
+-
+-void __init unwind_init(void)
+-{
+-      init_unwind_table(&root_table, "kernel",
+-                        _text, _end - _text,
+-                        NULL, 0,
+-                        __start_unwind, __end_unwind - __start_unwind,
+-                        __start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);
+-}
+-
+-static const u32 bad_cie, not_fde;
+-static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
+-static signed fde_pointer_type(const u32 *cie);
+-
+-struct eh_frame_hdr_table_entry {
+-      unsigned long start, fde;
+-};
+-
+-static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
+-{
+-      const struct eh_frame_hdr_table_entry *e1 = p1;
+-      const struct eh_frame_hdr_table_entry *e2 = p2;
+-
+-      return (e1->start > e2->start) - (e1->start < e2->start);
+-}
+-
+-static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
+-{
+-      struct eh_frame_hdr_table_entry *e1 = p1;
+-      struct eh_frame_hdr_table_entry *e2 = p2;
+-      unsigned long v;
+-
+-      v = e1->start;
+-      e1->start = e2->start;
+-      e2->start = v;
+-      v = e1->fde;
+-      e1->fde = e2->fde;
+-      e2->fde = v;
+-}
+-
+-static void __init setup_unwind_table(struct unwind_table *table,
+-                                      void *(*alloc)(unsigned long))
+-{
+-      const u8 *ptr;
+-      unsigned long tableSize = table->size, hdrSize;
+-      unsigned n;
+-      const u32 *fde;
+-      struct {
+-              u8 version;
+-              u8 eh_frame_ptr_enc;
+-              u8 fde_count_enc;
+-              u8 table_enc;
+-              unsigned long eh_frame_ptr;
+-              unsigned int fde_count;
+-              struct eh_frame_hdr_table_entry table[];
+-      } __attribute__((__packed__)) *header;
+-
+-      if (table->header)
+-              return;
+-
+-      if (table->hdrsz)
+-              printk(KERN_WARNING ".eh_frame_hdr for '%s' present but unusable\n",
+-                     table->name);
+-
+-      if (tableSize & (sizeof(*fde) - 1))
+-              return;
+-
+-      for (fde = table->address, n = 0;
+-           tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
+-           tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
+-              const u32 *cie = cie_for_fde(fde, table);
+-              signed ptrType;
+-
+-              if (cie == &not_fde)
+-                      continue;
+-              if (cie == NULL
+-                  || cie == &bad_cie
+-                  || (ptrType = fde_pointer_type(cie)) < 0)
+-                      return;
+-              ptr = (const u8 *)(fde + 2);
+-              if (!read_pointer(&ptr,
+-                                (const u8 *)(fde + 1) + *fde,
+-                                ptrType, 0, 0))
+-                      return;
+-              ++n;
+-      }
+-
+-      if (tableSize || !n)
+-              return;
+-
+-      hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
+-              + 2 * n * sizeof(unsigned long);
+-      dprintk(2, "Binary lookup table size for %s: %lu bytes", table->name, hdrSize);
+-      header = alloc(hdrSize);
+-      if (!header)
+-              return;
+-      header->version          = 1;
+-      header->eh_frame_ptr_enc = DW_EH_PE_abs|DW_EH_PE_native;
+-      header->fde_count_enc    = DW_EH_PE_abs|DW_EH_PE_data4;
+-      header->table_enc        = DW_EH_PE_abs|DW_EH_PE_native;
+-      put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
+-      BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
+-                   % __alignof(typeof(header->fde_count)));
+-      header->fde_count        = n;
+-
+-      BUILD_BUG_ON(offsetof(typeof(*header), table)
+-                   % __alignof(typeof(*header->table)));
+-      for (fde = table->address, tableSize = table->size, n = 0;
+-           tableSize;
+-           tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
+-              const u32 *cie = fde + 1 - fde[1] / sizeof(*fde);
+-
+-              if (!fde[1])
+-                      continue; /* this is a CIE */
+-              ptr = (const u8 *)(fde + 2);
+-              header->table[n].start = read_pointer(&ptr,
+-                                                    (const u8 *)(fde + 1) + *fde,
+-                                                    fde_pointer_type(cie), 0, 0);
+-              header->table[n].fde = (unsigned long)fde;
+-              ++n;
+-      }
+-      WARN_ON(n != header->fde_count);
+-
+-      sort(header->table,
+-           n,
+-           sizeof(*header->table),
+-           cmp_eh_frame_hdr_table_entries,
+-           swap_eh_frame_hdr_table_entries);
+-
+-      table->hdrsz = hdrSize;
+-      smp_wmb();
+-      table->header = (const void *)header;
+-}
+-
+-static void *__init balloc(unsigned long sz)
+-{
+-      return __alloc_bootmem_nopanic(sz,
+-                                     sizeof(unsigned int),
+-                                     __pa(MAX_DMA_ADDRESS));
+-}
+-
+-void __init unwind_setup(void)
+-{
+-      setup_unwind_table(&root_table, balloc);
+-}
+-
+-#ifdef CONFIG_MODULES
+-
+-static struct unwind_table *last_table;
+-
+-/* Must be called with module_mutex held. */
+-void *unwind_add_table(struct module *module,
+-                       const void *table_start,
+-                       unsigned long table_size)
+-{
+-      struct unwind_table *table;
+-
+-      if (table_size <= 0)
+-              return NULL;
+-
+-      table = kmalloc(sizeof(*table), GFP_KERNEL);
+-      if (!table)
+-              return NULL;
+-
+-      init_unwind_table(table, module->name,
+-                        module->module_core, module->core_size,
+-                        module->module_init, module->init_size,
+-                        table_start, table_size,
+-                        NULL, 0);
+-
+-      if (last_table)
+-              last_table->link = table;
+-      else
+-              root_table.link = table;
+-      last_table = table;
+-
+-      return table;
+-}
+-
+-struct unlink_table_info
+-{
+-      struct unwind_table *table;
+-      int init_only;
+-};
+-
+-static int unlink_table(void *arg)
+-{
+-      struct unlink_table_info *info = arg;
+-      struct unwind_table *table = info->table, *prev;
+-
+-      for (prev = &root_table; prev->link && prev->link != table; prev = prev->link)
+-              ;
+-
+-      if (prev->link) {
+-              if (info->init_only) {
+-                      table->init.pc = 0;
+-                      table->init.range = 0;
+-                      info->table = NULL;
+-              } else {
+-                      prev->link = table->link;
+-                      if (!prev->link)
+-                              last_table = prev;
+-              }
+-      } else
+-              info->table = NULL;
+-
+-      return 0;
+-}
+-
+-/* Must be called with module_mutex held. */
+-void unwind_remove_table(void *handle, int init_only)
+-{
+-      struct unwind_table *table = handle;
+-      struct unlink_table_info info;
+-
+-      if (!table || table == &root_table)
+-              return;
+-
+-      if (init_only && table == last_table) {
+-              table->init.pc = 0;
+-              table->init.range = 0;
+-              return;
+-      }
+-
+-      info.table = table;
+-      info.init_only = init_only;
+-      stop_machine_run(unlink_table, &info, NR_CPUS);
+-
+-      if (info.table)
+-              kfree(table);
+-}
+-
+-#endif /* CONFIG_MODULES */
+-
+-static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
+-{
+-      const u8 *cur = *pcur;
+-      uleb128_t value;
+-      unsigned shift;
+-
+-      for (shift = 0, value = 0; cur < end; shift += 7) {
+-              if (shift + 7 > 8 * sizeof(value)
+-                  && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
+-                      cur = end + 1;
+-                      break;
+-              }
+-              value |= (uleb128_t)(*cur & 0x7f) << shift;
+-              if (!(*cur++ & 0x80))
+-                      break;
+-      }
+-      *pcur = cur;
+-
+-      return value;
+-}
+-
+-static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
+-{
+-      const u8 *cur = *pcur;
+-      sleb128_t value;
+-      unsigned shift;
+-
+-      for (shift = 0, value = 0; cur < end; shift += 7) {
+-              if (shift + 7 > 8 * sizeof(value)
+-                  && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
+-                      cur = end + 1;
+-                      break;
+-              }
+-              value |= (sleb128_t)(*cur & 0x7f) << shift;
+-              if (!(*cur & 0x80)) {
+-                      value |= -(*cur++ & 0x40) << shift;
+-                      break;
+-              }
+-      }
+-      *pcur = cur;
+-
+-      return value;
+-}
+-
+-static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
+-{
+-      const u32 *cie;
+-
+-      if (!*fde || (*fde & (sizeof(*fde) - 1)))
+-              return &bad_cie;
+-      if (!fde[1])
+-              return &not_fde; /* this is a CIE */
+-      if ((fde[1] & (sizeof(*fde) - 1))
+-          || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address)
+-              return NULL; /* this is not a valid FDE */
+-      cie = fde + 1 - fde[1] / sizeof(*fde);
+-      if (*cie <= sizeof(*cie) + 4
+-          || *cie >= fde[1] - sizeof(*fde)
+-          || (*cie & (sizeof(*cie) - 1))
+-          || cie[1])
+-              return NULL; /* this is not a (valid) CIE */
+-      return cie;
+-}
+-
+-static unsigned long read_pointer(const u8 **pLoc,
+-                                  const void *end,
+-                                  signed ptrType,
+-                                  unsigned long text_base,
+-                                  unsigned long data_base)
+-{
+-      unsigned long value = 0;
+-      union {
+-              const u8 *p8;
+-              const u16 *p16u;
+-              const s16 *p16s;
+-              const u32 *p32u;
+-              const s32 *p32s;
+-              const unsigned long *pul;
+-      } ptr;
+-
+-      if (ptrType < 0 || ptrType == DW_EH_PE_omit) {
+-              dprintk(1, "Invalid pointer encoding %02X (%p,%p).", ptrType, *pLoc, end);
+-              return 0;
+-      }
+-      ptr.p8 = *pLoc;
+-      switch(ptrType & DW_EH_PE_FORM) {
+-      case DW_EH_PE_data2:
+-              if (end < (const void *)(ptr.p16u + 1)) {
+-                      dprintk(1, "Data16 overrun (%p,%p).", ptr.p8, end);
+-                      return 0;
+-              }
+-              if(ptrType & DW_EH_PE_signed)
+-                      value = get_unaligned(ptr.p16s++);
+-              else
+-                      value = get_unaligned(ptr.p16u++);
+-              break;
+-      case DW_EH_PE_data4:
+-#ifdef CONFIG_64BIT
+-              if (end < (const void *)(ptr.p32u + 1)) {
+-                      dprintk(1, "Data32 overrun (%p,%p).", ptr.p8, end);
+-                      return 0;
+-              }
+-              if(ptrType & DW_EH_PE_signed)
+-                      value = get_unaligned(ptr.p32s++);
+-              else
+-                      value = get_unaligned(ptr.p32u++);
+-              break;
+-      case DW_EH_PE_data8:
+-              BUILD_BUG_ON(sizeof(u64) != sizeof(value));
+-#else
+-              BUILD_BUG_ON(sizeof(u32) != sizeof(value));
+-#endif
+-      case DW_EH_PE_native:
+-              if (end < (const void *)(ptr.pul + 1)) {
+-                      dprintk(1, "DataUL overrun (%p,%p).", ptr.p8, end);
+-                      return 0;
+-              }
+-              value = get_unaligned(ptr.pul++);
+-              break;
+-      case DW_EH_PE_leb128:
+-              BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
+-              value = ptrType & DW_EH_PE_signed
+-                      ? get_sleb128(&ptr.p8, end)
+-                      : get_uleb128(&ptr.p8, end);
+-              if ((const void *)ptr.p8 > end) {
+-                      dprintk(1, "DataLEB overrun (%p,%p).", ptr.p8, end);
+-                      return 0;
+-              }
+-              break;
+-      default:
+-              dprintk(2, "Cannot decode pointer type %02X (%p,%p).",
+-                      ptrType, ptr.p8, end);
+-              return 0;
+-      }
+-      switch(ptrType & DW_EH_PE_ADJUST) {
+-      case DW_EH_PE_abs:
+-              break;
+-      case DW_EH_PE_pcrel:
+-              value += (unsigned long)*pLoc;
+-              break;
+-      case DW_EH_PE_textrel:
+-              if (likely(text_base)) {
+-                      value += text_base;
+-                      break;
+-              }
+-              dprintk(2, "Text-relative encoding %02X (%p,%p), but zero text base.",
+-                      ptrType, *pLoc, end);
+-              return 0;
+-      case DW_EH_PE_datarel:
+-              if (likely(data_base)) {
+-                      value += data_base;
+-                      break;
+-              }
+-              dprintk(2, "Data-relative encoding %02X (%p,%p), but zero data base.",
+-                      ptrType, *pLoc, end);
+-              return 0;
+-      default:
+-              dprintk(2, "Cannot adjust pointer type %02X (%p,%p).",
+-                      ptrType, *pLoc, end);
+-              return 0;
+-      }
+-      if ((ptrType & DW_EH_PE_indirect)
+-          && probe_kernel_address((unsigned long *)value, value)) {
+-              dprintk(1, "Cannot read indirect value %lx (%p,%p).",
+-                      value, *pLoc, end);
+-              return 0;
+-      }
+-      *pLoc = ptr.p8;
+-
+-      return value;
+-}
+-
+-static signed fde_pointer_type(const u32 *cie)
+-{
+-      const u8 *ptr = (const u8 *)(cie + 2);
+-      unsigned version = *ptr;
+-
+-      if (version != 1)
+-              return -1; /* unsupported */
+-      if (*++ptr) {
+-              const char *aug;
+-              const u8 *end = (const u8 *)(cie + 1) + *cie;
+-              uleb128_t len;
+-
+-              /* check if augmentation size is first (and thus present) */
+-              if (*ptr != 'z')
+-                      return -1;
+-              /* check if augmentation string is nul-terminated */
+-              if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
+-                      return -1;
+-              ++ptr; /* skip terminator */
+-              get_uleb128(&ptr, end); /* skip code alignment */
+-              get_sleb128(&ptr, end); /* skip data alignment */
+-              /* skip return address column */
+-              version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end);
+-              len = get_uleb128(&ptr, end); /* augmentation length */
+-              if (ptr + len < ptr || ptr + len > end)
+-                      return -1;
+-              end = ptr + len;
+-              while (*++aug) {
+-                      if (ptr >= end)
+-                              return -1;
+-                      switch(*aug) {
+-                      case 'L':
+-                              ++ptr;
+-                              break;
+-                      case 'P': {
+-                                      signed ptrType = *ptr++;
+-
+-                                      if (!read_pointer(&ptr, end, ptrType, 0, 0)
+-                                          || ptr > end)
+-                                              return -1;
+-                              }
+-                              break;
+-                      case 'R':
+-                              return *ptr;
+-                      default:
+-                              return -1;
+-                      }
+-              }
+-      }
+-      return DW_EH_PE_native|DW_EH_PE_abs;
+-}
+-
+-static int advance_loc(unsigned long delta, struct unwind_state *state)
+-{
+-      state->loc += delta * state->codeAlign;
+-
+-      return delta > 0;
+-}
+-
+-static void set_rule(uleb128_t reg,
+-                     enum item_location where,
+-                     uleb128_t value,
+-                     struct unwind_state *state)
+-{
+-      if (reg < ARRAY_SIZE(state->regs)) {
+-              state->regs[reg].where = where;
+-              state->regs[reg].value = value;
+-      }
+-}
+-
+-static int processCFI(const u8 *start,
+-                      const u8 *end,
+-                      unsigned long targetLoc,
+-                      signed ptrType,
+-                      struct unwind_state *state)
+-{
+-      union {
+-              const u8 *p8;
+-              const u16 *p16;
+-              const u32 *p32;
+-      } ptr;
+-      int result = 1;
+-
+-      if (start != state->cieStart) {
+-              state->loc = state->org;
+-              result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state);
+-              if (targetLoc == 0 && state->label == NULL)
+-                      return result;
+-      }
+-      for (ptr.p8 = start; result && ptr.p8 < end; ) {
+-              switch(*ptr.p8 >> 6) {
+-                      uleb128_t value;
+-
+-              case 0:
+-                      switch(*ptr.p8++) {
+-                      case DW_CFA_nop:
+-                              break;
+-                      case DW_CFA_set_loc:
+-                              state->loc = read_pointer(&ptr.p8, end, ptrType, 0, 0);
+-                              if (state->loc == 0)
+-                                      result = 0;
+-                              break;
+-                      case DW_CFA_advance_loc1:
+-                              result = ptr.p8 < end && advance_loc(*ptr.p8++, state);
+-                              break;
+-                      case DW_CFA_advance_loc2:
+-                              result = ptr.p8 <= end + 2
+-                                       && advance_loc(*ptr.p16++, state);
+-                              break;
+-                      case DW_CFA_advance_loc4:
+-                              result = ptr.p8 <= end + 4
+-                                       && advance_loc(*ptr.p32++, state);
+-                              break;
+-                      case DW_CFA_offset_extended:
+-                              value = get_uleb128(&ptr.p8, end);
+-                              set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
+-                              break;
+-                      case DW_CFA_val_offset:
+-                              value = get_uleb128(&ptr.p8, end);
+-                              set_rule(value, Value, get_uleb128(&ptr.p8, end), state);
+-                              break;
+-                      case DW_CFA_offset_extended_sf:
+-                              value = get_uleb128(&ptr.p8, end);
+-                              set_rule(value, Memory, get_sleb128(&ptr.p8, end), state);
+-                              break;
+-                      case DW_CFA_val_offset_sf:
+-                              value = get_uleb128(&ptr.p8, end);
+-                              set_rule(value, Value, get_sleb128(&ptr.p8, end), state);
+-                              break;
+-                      case DW_CFA_restore_extended:
+-                      case DW_CFA_undefined:
+-                      case DW_CFA_same_value:
+-                              set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state);
+-                              break;
+-                      case DW_CFA_register:
+-                              value = get_uleb128(&ptr.p8, end);
+-                              set_rule(value,
+-                                       Register,
+-                                       get_uleb128(&ptr.p8, end), state);
+-                              break;
+-                      case DW_CFA_remember_state:
+-                              if (ptr.p8 == state->label) {
+-                                      state->label = NULL;
+-                                      return 1;
+-                              }
+-                              if (state->stackDepth >= MAX_STACK_DEPTH) {
+-                                      dprintk(1, "State stack overflow (%p,%p).", ptr.p8, end);
+-                                      return 0;
+-                              }
+-                              state->stack[state->stackDepth++] = ptr.p8;
+-                              break;
+-                      case DW_CFA_restore_state:
+-                              if (state->stackDepth) {
+-                                      const uleb128_t loc = state->loc;
+-                                      const u8 *label = state->label;
+-
+-                                      state->label = state->stack[state->stackDepth - 1];
+-                                      memcpy(&state->cfa, &badCFA, sizeof(state->cfa));
+-                                      memset(state->regs, 0, sizeof(state->regs));
+-                                      state->stackDepth = 0;
+-                                      result = processCFI(start, end, 0, ptrType, state);
+-                                      state->loc = loc;
+-                                      state->label = label;
+-                              } else {
+-                                      dprintk(1, "State stack underflow (%p,%p).", ptr.p8, end);
+-                                      return 0;
+-                              }
+-                              break;
+-                      case DW_CFA_def_cfa:
+-                              state->cfa.reg = get_uleb128(&ptr.p8, end);
+-                              /*nobreak*/
+-                      case DW_CFA_def_cfa_offset:
+-                              state->cfa.offs = get_uleb128(&ptr.p8, end);
+-                              break;
+-                      case DW_CFA_def_cfa_sf:
+-                              state->cfa.reg = get_uleb128(&ptr.p8, end);
+-                              /*nobreak*/
+-                      case DW_CFA_def_cfa_offset_sf:
+-                              state->cfa.offs = get_sleb128(&ptr.p8, end)
+-                                                * state->dataAlign;
+-                              break;
+-                      case DW_CFA_def_cfa_register:
+-                              state->cfa.reg = get_uleb128(&ptr.p8, end);
+-                              break;
+-                      /*todo case DW_CFA_def_cfa_expression: */
+-                      /*todo case DW_CFA_expression: */
+-                      /*todo case DW_CFA_val_expression: */
+-                      case DW_CFA_GNU_args_size:
+-                              get_uleb128(&ptr.p8, end);
+-                              break;
+-                      case DW_CFA_GNU_negative_offset_extended:
+-                              value = get_uleb128(&ptr.p8, end);
+-                              set_rule(value,
+-                                       Memory,
+-                                       (uleb128_t)0 - get_uleb128(&ptr.p8, end), state);
+-                              break;
+-                      case DW_CFA_GNU_window_save:
+-                      default:
+-                              dprintk(1, "Unrecognized CFI op %02X (%p,%p).", ptr.p8[-1], ptr.p8 - 1, end);
+-                              result = 0;
+-                              break;
+-                      }
+-                      break;
+-              case 1:
+-                      result = advance_loc(*ptr.p8++ & 0x3f, state);
+-                      break;
+-              case 2:
+-                      value = *ptr.p8++ & 0x3f;
+-                      set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
+-                      break;
+-              case 3:
+-                      set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
+-                      break;
+-              }
+-              if (ptr.p8 > end) {
+-                      dprintk(1, "Data overrun (%p,%p).", ptr.p8, end);
+-                      result = 0;
+-              }
+-              if (result && targetLoc != 0 && targetLoc < state->loc)
+-                      return 1;
+-      }
+-
+-      if (result && ptr.p8 < end)
+-              dprintk(1, "Data underrun (%p,%p).", ptr.p8, end);
+-
+-      return result
+-         && ptr.p8 == end
+-         && (targetLoc == 0
+-          || (/*todo While in theory this should apply, gcc in practice omits
+-                everything past the function prolog, and hence the location
+-                never reaches the end of the function.
+-              targetLoc < state->loc &&*/ state->label == NULL));
+-}
+-
+-/* Unwind to previous to frame.  Returns 0 if successful, negative
+- * number in case of an error. */
+-int unwind(struct unwind_frame_info *frame)
 -{
--      struct ifinfomsg *ifm;
--      struct net_device *dev;
--      int err, send_addr_notify = 0, modified = 0;
--      struct nlattr *tb[IFLA_MAX+1];
--      char ifname[IFNAMSIZ];
+-#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
+-      const u32 *fde = NULL, *cie = NULL;
+-      const u8 *ptr = NULL, *end = NULL;
+-      unsigned long pc = UNW_PC(frame) - frame->call_frame, sp;
+-      unsigned long startLoc = 0, endLoc = 0, cfa;
+-      unsigned i;
+-      signed ptrType = -1;
+-      uleb128_t retAddrReg = 0;
+-      const struct unwind_table *table;
+-      struct unwind_state state;
 -
--      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
--      if (err < 0)
--              goto errout;
+-      if (UNW_PC(frame) == 0)
+-              return -EINVAL;
+-      if ((table = find_table(pc)) != NULL
+-          && !(table->size & (sizeof(*fde) - 1))) {
+-              const u8 *hdr = table->header;
+-              unsigned long tableSize;
 -
--      if (tb[IFLA_IFNAME])
--              nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
--      else
--              ifname[0] = '\0';
+-              smp_rmb();
+-              if (hdr && hdr[0] == 1) {
+-                      switch(hdr[3] & DW_EH_PE_FORM) {
+-                      case DW_EH_PE_native: tableSize = sizeof(unsigned long); break;
+-                      case DW_EH_PE_data2: tableSize = 2; break;
+-                      case DW_EH_PE_data4: tableSize = 4; break;
+-                      case DW_EH_PE_data8: tableSize = 8; break;
+-                      default: tableSize = 0; break;
+-                      }
+-                      ptr = hdr + 4;
+-                      end = hdr + table->hdrsz;
+-                      if (tableSize
+-                          && read_pointer(&ptr, end, hdr[1], 0, 0)
+-                             == (unsigned long)table->address
+-                          && (i = read_pointer(&ptr, end, hdr[2], 0, 0)) > 0
+-                          && i == (end - ptr) / (2 * tableSize)
+-                          && !((end - ptr) % (2 * tableSize))) {
+-                              do {
+-                                      const u8 *cur = ptr + (i / 2) * (2 * tableSize);
+-
+-                                      startLoc = read_pointer(&cur,
+-                                                              cur + tableSize,
+-                                                              hdr[3], 0,
+-                                                              (unsigned long)hdr);
+-                                      if (pc < startLoc)
+-                                              i /= 2;
+-                                      else {
+-                                              ptr = cur - tableSize;
+-                                              i = (i + 1) / 2;
+-                                      }
+-                              } while (startLoc && i > 1);
+-                              if (i == 1
+-                                  && (startLoc = read_pointer(&ptr,
+-                                                              ptr + tableSize,
+-                                                              hdr[3], 0,
+-                                                              (unsigned long)hdr)) != 0
+-                                  && pc >= startLoc)
+-                                      fde = (void *)read_pointer(&ptr,
+-                                                                 ptr + tableSize,
+-                                                                 hdr[3], 0,
+-                                                                 (unsigned long)hdr);
+-                      }
+-              }
+-              if(hdr && !fde)
+-                      dprintk(3, "Binary lookup for %lx failed.", pc);
+-
+-              if (fde != NULL) {
+-                      cie = cie_for_fde(fde, table);
+-                      ptr = (const u8 *)(fde + 2);
+-                      if(cie != NULL
+-                         && cie != &bad_cie
+-                         && cie != &not_fde
+-                         && (ptrType = fde_pointer_type(cie)) >= 0
+-                         && read_pointer(&ptr,
+-                                         (const u8 *)(fde + 1) + *fde,
+-                                         ptrType, 0, 0) == startLoc) {
+-                              if (!(ptrType & DW_EH_PE_indirect))
+-                                      ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
+-                              endLoc = startLoc
+-                                       + read_pointer(&ptr,
+-                                                      (const u8 *)(fde + 1) + *fde,
+-                                                      ptrType, 0, 0);
+-                              if(pc >= endLoc)
+-                                      fde = NULL;
+-                      } else
+-                              fde = NULL;
+-                      if(!fde)
+-                              dprintk(1, "Binary lookup result for %lx discarded.", pc);
+-              }
+-              if (fde == NULL) {
+-                      for (fde = table->address, tableSize = table->size;
+-                           cie = NULL, tableSize > sizeof(*fde)
+-                           && tableSize - sizeof(*fde) >= *fde;
+-                           tableSize -= sizeof(*fde) + *fde,
+-                           fde += 1 + *fde / sizeof(*fde)) {
+-                              cie = cie_for_fde(fde, table);
+-                              if (cie == &bad_cie) {
+-                                      cie = NULL;
+-                                      break;
+-                              }
+-                              if (cie == NULL
+-                                  || cie == &not_fde
+-                                  || (ptrType = fde_pointer_type(cie)) < 0)
+-                                      continue;
+-                              ptr = (const u8 *)(fde + 2);
+-                              startLoc = read_pointer(&ptr,
+-                                                      (const u8 *)(fde + 1) + *fde,
+-                                                      ptrType, 0, 0);
+-                              if (!startLoc)
+-                                      continue;
+-                              if (!(ptrType & DW_EH_PE_indirect))
+-                                      ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
+-                              endLoc = startLoc
+-                                       + read_pointer(&ptr,
+-                                                      (const u8 *)(fde + 1) + *fde,
+-                                                      ptrType, 0, 0);
+-                              if (pc >= startLoc && pc < endLoc)
+-                                      break;
+-                      }
+-                      if(!fde)
+-                              dprintk(3, "Linear lookup for %lx failed.", pc);
+-              }
+-      }
+-      if (cie != NULL) {
+-              memset(&state, 0, sizeof(state));
+-              state.cieEnd = ptr; /* keep here temporarily */
+-              ptr = (const u8 *)(cie + 2);
+-              end = (const u8 *)(cie + 1) + *cie;
+-              frame->call_frame = 1;
+-              if ((state.version = *ptr) != 1)
+-                      cie = NULL; /* unsupported version */
+-              else if (*++ptr) {
+-                      /* check if augmentation size is first (and thus present) */
+-                      if (*ptr == 'z') {
+-                              while (++ptr < end && *ptr) {
+-                                      switch(*ptr) {
+-                                      /* check for ignorable (or already handled)
+-                                       * nul-terminated augmentation string */
+-                                      case 'L':
+-                                      case 'P':
+-                                      case 'R':
+-                                              continue;
+-                                      case 'S':
+-                                              frame->call_frame = 0;
+-                                              continue;
+-                                      default:
+-                                              break;
+-                                      }
+-                                      break;
+-                              }
+-                      }
+-                      if (ptr >= end || *ptr)
+-                              cie = NULL;
+-              }
+-              if(!cie)
+-                      dprintk(1, "CIE unusable (%p,%p).", ptr, end);
+-              ++ptr;
+-      }
+-      if (cie != NULL) {
+-              /* get code aligment factor */
+-              state.codeAlign = get_uleb128(&ptr, end);
+-              /* get data aligment factor */
+-              state.dataAlign = get_sleb128(&ptr, end);
+-              if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
+-                      cie = NULL;
+-              else if (UNW_PC(frame) % state.codeAlign
+-                       || UNW_SP(frame) % sleb128abs(state.dataAlign)) {
+-                      dprintk(1, "Input pointer(s) misaligned (%lx,%lx).",
+-                              UNW_PC(frame), UNW_SP(frame));
+-                      return -EPERM;
+-              } else {
+-                      retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
+-                      /* skip augmentation */
+-                      if (((const char *)(cie + 2))[1] == 'z') {
+-                              uleb128_t augSize = get_uleb128(&ptr, end);
 -
--      err = -EINVAL;
--      ifm = nlmsg_data(nlh);
--      if (ifm->ifi_index > 0)
--              dev = dev_get_by_index(ifm->ifi_index);
--      else if (tb[IFLA_IFNAME])
--              dev = dev_get_by_name(ifname);
--      else
--              goto errout;
+-                              ptr += augSize;
+-                      }
+-                      if (ptr > end
+-                         || retAddrReg >= ARRAY_SIZE(reg_info)
+-                         || REG_INVALID(retAddrReg)
+-                         || reg_info[retAddrReg].width != sizeof(unsigned long))
+-                              cie = NULL;
+-              }
+-              if(!cie)
+-                      dprintk(1, "CIE validation failed (%p,%p).", ptr, end);
+-      }
+-      if (cie != NULL) {
+-              state.cieStart = ptr;
+-              ptr = state.cieEnd;
+-              state.cieEnd = end;
+-              end = (const u8 *)(fde + 1) + *fde;
+-              /* skip augmentation */
+-              if (((const char *)(cie + 2))[1] == 'z') {
+-                      uleb128_t augSize = get_uleb128(&ptr, end);
+-
+-                      if ((ptr += augSize) > end)
+-                              fde = NULL;
+-              }
+-              if(!fde)
+-                      dprintk(1, "FDE validation failed (%p,%p).", ptr, end);
+-      }
+-      if (cie == NULL || fde == NULL) {
+-#ifdef CONFIG_FRAME_POINTER
+-              unsigned long top, bottom;
 -
--      if (dev == NULL) {
--              err = -ENODEV;
--              goto errout;
+-              if ((UNW_SP(frame) | UNW_FP(frame)) % sizeof(unsigned long))
+-                      return -EPERM;
+-              top = STACK_TOP(frame->task);
+-              bottom = STACK_BOTTOM(frame->task);
+-# if FRAME_RETADDR_OFFSET < 0
+-              if (UNW_SP(frame) < top
+-                  && UNW_FP(frame) <= UNW_SP(frame)
+-                  && bottom < UNW_FP(frame)
+-# else
+-              if (UNW_SP(frame) > top
+-                  && UNW_FP(frame) >= UNW_SP(frame)
+-                  && bottom > UNW_FP(frame)
+-# endif
+-                 && !((UNW_SP(frame) | UNW_FP(frame))
+-                      & (sizeof(unsigned long) - 1))) {
+-                      unsigned long link;
+-
+-                      if (!probe_kernel_address(
+-                                      (unsigned long *)(UNW_FP(frame)
+-                                                        + FRAME_LINK_OFFSET),
+-                                                link)
+-# if FRAME_RETADDR_OFFSET < 0
+-                         && link > bottom && link < UNW_FP(frame)
+-# else
+-                         && link > UNW_FP(frame) && link < bottom
+-# endif
+-                         && !(link & (sizeof(link) - 1))
+-                         && !probe_kernel_address(
+-                                        (unsigned long *)(UNW_FP(frame)
+-                                                          + FRAME_RETADDR_OFFSET), UNW_PC(frame))) {
+-                              UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
+-# if FRAME_RETADDR_OFFSET < 0
+-                                      -
+-# else
+-                                      +
+-# endif
+-                                        sizeof(UNW_PC(frame));
+-                              UNW_FP(frame) = link;
+-                              return 0;
+-                      }
+-              }
+-#endif
+-              return -ENXIO;
+-      }
+-      state.org = startLoc;
+-      memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
+-      /* process instructions */
+-      if (!processCFI(ptr, end, pc, ptrType, &state)
+-         || state.loc > endLoc
+-         || state.regs[retAddrReg].where == Nowhere
+-         || state.cfa.reg >= ARRAY_SIZE(reg_info)
+-         || reg_info[state.cfa.reg].width != sizeof(unsigned long)
+-         || FRAME_REG(state.cfa.reg, unsigned long) % sizeof(unsigned long)
+-         || state.cfa.offs % sizeof(unsigned long)) {
+-              dprintk(1, "Unusable unwind info (%p,%p).", ptr, end);
+-              return -EIO;
+-      }
+-      /* update frame */
+-#ifndef CONFIG_AS_CFI_SIGNAL_FRAME
+-      if(frame->call_frame
+-         && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
+-              frame->call_frame = 0;
+-#endif
+-      cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
+-      startLoc = min((unsigned long)UNW_SP(frame), cfa);
+-      endLoc = max((unsigned long)UNW_SP(frame), cfa);
+-      if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
+-              startLoc = min(STACK_LIMIT(cfa), cfa);
+-              endLoc = max(STACK_LIMIT(cfa), cfa);
+-      }
+-#ifndef CONFIG_64BIT
+-# define CASES CASE(8); CASE(16); CASE(32)
+-#else
+-# define CASES CASE(8); CASE(16); CASE(32); CASE(64)
+-#endif
+-      pc = UNW_PC(frame);
+-      sp = UNW_SP(frame);
+-      for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
+-              if (REG_INVALID(i)) {
+-                      if (state.regs[i].where == Nowhere)
+-                              continue;
+-                      dprintk(1, "Cannot restore register %u (%d).",
+-                              i, state.regs[i].where);
+-                      return -EIO;
+-              }
+-              switch(state.regs[i].where) {
+-              default:
+-                      break;
+-              case Register:
+-                      if (state.regs[i].value >= ARRAY_SIZE(reg_info)
+-                         || REG_INVALID(state.regs[i].value)
+-                         || reg_info[i].width > reg_info[state.regs[i].value].width) {
+-                              dprintk(1, "Cannot restore register %u from register %lu.",
+-                                      i, state.regs[i].value);
+-                              return -EIO;
+-                      }
+-                      switch(reg_info[state.regs[i].value].width) {
+-#define CASE(n) \
+-                      case sizeof(u##n): \
+-                              state.regs[i].value = FRAME_REG(state.regs[i].value, \
+-                                                              const u##n); \
+-                              break
+-                      CASES;
+-#undef CASE
+-                      default:
+-                              dprintk(1, "Unsupported register size %u (%lu).",
+-                                      reg_info[state.regs[i].value].width,
+-                                      state.regs[i].value);
+-                              return -EIO;
+-                      }
+-                      break;
+-              }
+-      }
+-      for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
+-              if (REG_INVALID(i))
+-                      continue;
+-              switch(state.regs[i].where) {
+-              case Nowhere:
+-                      if (reg_info[i].width != sizeof(UNW_SP(frame))
+-                         || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
+-                            != &UNW_SP(frame))
+-                              continue;
+-                      UNW_SP(frame) = cfa;
+-                      break;
+-              case Register:
+-                      switch(reg_info[i].width) {
+-#define CASE(n) case sizeof(u##n): \
+-                              FRAME_REG(i, u##n) = state.regs[i].value; \
+-                              break
+-                      CASES;
+-#undef CASE
+-                      default:
+-                              dprintk(1, "Unsupported register size %u (%u).",
+-                                      reg_info[i].width, i);
+-                              return -EIO;
+-                      }
+-                      break;
+-              case Value:
+-                      if (reg_info[i].width != sizeof(unsigned long)) {
+-                              dprintk(1, "Unsupported value size %u (%u).",
+-                                      reg_info[i].width, i);
+-                              return -EIO;
+-                      }
+-                      FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
+-                                                          * state.dataAlign;
+-                      break;
+-              case Memory: {
+-                              unsigned long addr = cfa + state.regs[i].value
+-                                                         * state.dataAlign;
+-
+-                              if ((state.regs[i].value * state.dataAlign)
+-                                  % sizeof(unsigned long)
+-                                  || addr < startLoc
+-                                  || addr + sizeof(unsigned long) < addr
+-                                  || addr + sizeof(unsigned long) > endLoc) {
+-                                      dprintk(1, "Bad memory location %lx (%lx).",
+-                                              addr, state.regs[i].value);
+-                                      return -EIO;
+-                              }
+-                              switch(reg_info[i].width) {
+-#define CASE(n)     case sizeof(u##n): \
+-                                      probe_kernel_address((u##n *)addr, FRAME_REG(i, u##n)); \
+-                                      break
+-                              CASES;
+-#undef CASE
+-                              default:
+-                                      dprintk(1, "Unsupported memory size %u (%u).",
+-                                              reg_info[i].width, i);
+-                                      return -EIO;
+-                              }
+-                      }
+-                      break;
+-              }
 -      }
 -
--      if (tb[IFLA_ADDRESS] &&
--          nla_len(tb[IFLA_ADDRESS]) < dev->addr_len)
--              goto errout_dev;
-+static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
-+      [IFLA_INFO_KIND]        = { .type = NLA_STRING },
-+      [IFLA_INFO_DATA]        = { .type = NLA_NESTED },
-+};
--      if (tb[IFLA_BROADCAST] &&
--          nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
--              goto errout_dev;
-+static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
-+                    struct nlattr **tb, char *ifname, int modified)
-+{
-+      int send_addr_notify = 0;
-+      int err;
-       if (tb[IFLA_MAP]) {
-               struct rtnl_link_ifmap *u_map;
-@@ -608,12 +752,12 @@
-               if (!dev->set_config) {
-                       err = -EOPNOTSUPP;
--                      goto errout_dev;
-+                      goto errout;
-               }
-               if (!netif_device_present(dev)) {
-                       err = -ENODEV;
--                      goto errout_dev;
-+                      goto errout;
-               }
-               u_map = nla_data(tb[IFLA_MAP]);
-@@ -626,7 +770,7 @@
-               err = dev->set_config(dev, &k_map);
-               if (err < 0)
--                      goto errout_dev;
-+                      goto errout;
-               modified = 1;
-       }
-@@ -637,19 +781,19 @@
-               if (!dev->set_mac_address) {
-                       err = -EOPNOTSUPP;
--                      goto errout_dev;
-+                      goto errout;
-               }
-               if (!netif_device_present(dev)) {
-                       err = -ENODEV;
--                      goto errout_dev;
-+                      goto errout;
-               }
-               len = sizeof(sa_family_t) + dev->addr_len;
-               sa = kmalloc(len, GFP_KERNEL);
-               if (!sa) {
-                       err = -ENOMEM;
--                      goto errout_dev;
-+                      goto errout;
-               }
-               sa->sa_family = dev->type;
-               memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
-@@ -657,7 +801,7 @@
-               err = dev->set_mac_address(dev, sa);
-               kfree(sa);
-               if (err)
--                      goto errout_dev;
-+                      goto errout;
-               send_addr_notify = 1;
-               modified = 1;
-       }
-@@ -665,7 +809,7 @@
-       if (tb[IFLA_MTU]) {
-               err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
-               if (err < 0)
--                      goto errout_dev;
-+                      goto errout;
-               modified = 1;
-       }
-@@ -677,7 +821,7 @@
-       if (ifm->ifi_index > 0 && ifname[0]) {
-               err = dev_change_name(dev, ifname);
-               if (err < 0)
--                      goto errout_dev;
-+                      goto errout;
-               modified = 1;
-       }
-@@ -686,7 +830,6 @@
-               send_addr_notify = 1;
-       }
+-      if (UNW_PC(frame) % state.codeAlign
+-          || UNW_SP(frame) % sleb128abs(state.dataAlign)) {
+-              dprintk(1, "Output pointer(s) misaligned (%lx,%lx).",
+-                      UNW_PC(frame), UNW_SP(frame));
+-              return -EIO;
+-      }
+-      if (pc == UNW_PC(frame) && sp == UNW_SP(frame)) {
+-              dprintk(1, "No progress (%lx,%lx).", pc, sp);
+-              return -EIO;
+-      }
 -
-       if (ifm->ifi_flags || ifm->ifi_change) {
-               unsigned int flags = ifm->ifi_flags;
-@@ -714,7 +857,7 @@
-       err = 0;
--errout_dev:
-+errout:
-       if (err < 0 && modified && net_ratelimit())
-               printk(KERN_WARNING "A link change request failed with "
-                      "some changes comitted already. Interface %s may "
-@@ -723,14 +866,237 @@
-       if (send_addr_notify)
-               call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
-+      return err;
-+}
-+
-+static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
-+{
-+      struct net *net = skb->sk->sk_net;
-+      struct ifinfomsg *ifm;
-+      struct net_device *dev;
-+      int err;
-+      struct nlattr *tb[IFLA_MAX+1];
-+      char ifname[IFNAMSIZ];
-+      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
-+      if (err < 0)
-+              goto errout;
-+
-+      if (tb[IFLA_IFNAME])
-+              nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
-+      else
-+              ifname[0] = '\0';
-+
-+      err = -EINVAL;
-+      ifm = nlmsg_data(nlh);
-+      if (ifm->ifi_index > 0)
-+              dev = dev_get_by_index(net, ifm->ifi_index);
-+      else if (tb[IFLA_IFNAME])
-+              dev = dev_get_by_name(net, ifname);
-+      else
-+              goto errout;
-+
-+      if (dev == NULL) {
-+              err = -ENODEV;
-+              goto errout;
-+      }
-+
-+      if (tb[IFLA_ADDRESS] &&
-+          nla_len(tb[IFLA_ADDRESS]) < dev->addr_len)
-+              goto errout_dev;
-+
-+      if (tb[IFLA_BROADCAST] &&
-+          nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
-+              goto errout_dev;
-+
-+      err = do_setlink(dev, ifm, tb, ifname, 0);
-+errout_dev:
-       dev_put(dev);
- errout:
-       return err;
- }
-+static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
-+{
-+      struct net *net = skb->sk->sk_net;
-+      const struct rtnl_link_ops *ops;
-+      struct net_device *dev;
-+      struct ifinfomsg *ifm;
-+      char ifname[IFNAMSIZ];
-+      struct nlattr *tb[IFLA_MAX+1];
-+      int err;
-+
-+      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
-+      if (err < 0)
-+              return err;
-+
-+      if (tb[IFLA_IFNAME])
-+              nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
-+
-+      ifm = nlmsg_data(nlh);
-+      if (ifm->ifi_index > 0)
-+              dev = __dev_get_by_index(net, ifm->ifi_index);
-+      else if (tb[IFLA_IFNAME])
-+              dev = __dev_get_by_name(net, ifname);
-+      else
-+              return -EINVAL;
-+
-+      if (!dev)
-+              return -ENODEV;
-+
-+      ops = dev->rtnl_link_ops;
-+      if (!ops)
-+              return -EOPNOTSUPP;
-+
-+      ops->dellink(dev);
-+      return 0;
-+}
-+
-+static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
-+{
-+      struct net *net = skb->sk->sk_net;
-+      const struct rtnl_link_ops *ops;
-+      struct net_device *dev;
-+      struct ifinfomsg *ifm;
-+      char kind[MODULE_NAME_LEN];
-+      char ifname[IFNAMSIZ];
-+      struct nlattr *tb[IFLA_MAX+1];
-+      struct nlattr *linkinfo[IFLA_INFO_MAX+1];
-+      int err;
-+
-+replay:
-+      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
-+      if (err < 0)
-+              return err;
-+
-+      if (tb[IFLA_IFNAME])
-+              nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
-+      else
-+              ifname[0] = '\0';
-+
-+      ifm = nlmsg_data(nlh);
-+      if (ifm->ifi_index > 0)
-+              dev = __dev_get_by_index(net, ifm->ifi_index);
-+      else if (ifname[0])
-+              dev = __dev_get_by_name(net, ifname);
-+      else
-+              dev = NULL;
-+
-+      if (tb[IFLA_LINKINFO]) {
-+              err = nla_parse_nested(linkinfo, IFLA_INFO_MAX,
-+                                     tb[IFLA_LINKINFO], ifla_info_policy);
-+              if (err < 0)
-+                      return err;
-+      } else
-+              memset(linkinfo, 0, sizeof(linkinfo));
-+
-+      if (linkinfo[IFLA_INFO_KIND]) {
-+              nla_strlcpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind));
-+              ops = rtnl_link_ops_get(kind);
-+      } else {
-+              kind[0] = '\0';
-+              ops = NULL;
-+      }
-+
-+      if (1) {
-+              struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL;
-+
-+              if (ops) {
-+                      if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) {
-+                              err = nla_parse_nested(attr, ops->maxtype,
-+                                                     linkinfo[IFLA_INFO_DATA],
-+                                                     ops->policy);
-+                              if (err < 0)
-+                                      return err;
-+                              data = attr;
-+                      }
-+                      if (ops->validate) {
-+                              err = ops->validate(tb, data);
-+                              if (err < 0)
-+                                      return err;
-+                      }
-+              }
-+
-+              if (dev) {
-+                      int modified = 0;
-+
-+                      if (nlh->nlmsg_flags & NLM_F_EXCL)
-+                              return -EEXIST;
-+                      if (nlh->nlmsg_flags & NLM_F_REPLACE)
-+                              return -EOPNOTSUPP;
-+
-+                      if (linkinfo[IFLA_INFO_DATA]) {
-+                              if (!ops || ops != dev->rtnl_link_ops ||
-+                                  !ops->changelink)
-+                                      return -EOPNOTSUPP;
-+
-+                              err = ops->changelink(dev, tb, data);
-+                              if (err < 0)
-+                                      return err;
-+                              modified = 1;
-+                      }
-+
-+                      return do_setlink(dev, ifm, tb, ifname, modified);
-+              }
-+
-+              if (!(nlh->nlmsg_flags & NLM_F_CREATE))
-+                      return -ENODEV;
-+
-+              if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change)
-+                      return -EOPNOTSUPP;
-+              if (tb[IFLA_ADDRESS] || tb[IFLA_BROADCAST] || tb[IFLA_MAP] ||
-+                  tb[IFLA_MASTER] || tb[IFLA_PROTINFO])
-+                      return -EOPNOTSUPP;
-+
-+              if (!ops) {
-+#ifdef CONFIG_KMOD
-+                      if (kind[0]) {
-+                              __rtnl_unlock();
-+                              request_module("rtnl-link-%s", kind);
-+                              rtnl_lock();
-+                              ops = rtnl_link_ops_get(kind);
-+                              if (ops)
-+                                      goto replay;
-+                      }
-+#endif
-+                      return -EOPNOTSUPP;
-+              }
-+
-+              if (!ifname[0])
-+                      snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
-+              dev = alloc_netdev(ops->priv_size, ifname, ops->setup);
-+              if (!dev)
-+                      return -ENOMEM;
-+
-+              if (strchr(dev->name, '%')) {
-+                      err = dev_alloc_name(dev, dev->name);
-+                      if (err < 0)
-+                              goto err_free;
-+              }
-+              dev->rtnl_link_ops = ops;
-+
-+              if (tb[IFLA_MTU])
-+                      dev->mtu = nla_get_u32(tb[IFLA_MTU]);
-+              if (tb[IFLA_TXQLEN])
-+                      dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
-+              if (tb[IFLA_WEIGHT])
-+                      dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);
-+              if (tb[IFLA_OPERSTATE])
-+                      set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
-+              if (tb[IFLA_LINKMODE])
-+                      dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
-+
-+              err = ops->newlink(dev, tb, data);
-+err_free:
-+              if (err < 0)
-+                      free_netdev(dev);
-+              return err;
-+      }
-+}
-+
- static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct ifinfomsg *ifm;
-       struct nlattr *tb[IFLA_MAX+1];
-       struct net_device *dev = NULL;
-@@ -743,13 +1109,13 @@
-       ifm = nlmsg_data(nlh);
-       if (ifm->ifi_index > 0) {
--              dev = dev_get_by_index(ifm->ifi_index);
-+              dev = dev_get_by_index(net, ifm->ifi_index);
-               if (dev == NULL)
-                       return -ENODEV;
-       } else
-               return -EINVAL;
--      nskb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL);
-+      nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
-       if (nskb == NULL) {
-               err = -ENOBUFS;
-               goto errout;
-@@ -763,7 +1129,7 @@
-               kfree_skb(nskb);
-               goto errout;
-       }
--      err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
-+      err = rtnl_unicast(nskb, net, NETLINK_CB(skb).pid);
- errout:
-       dev_put(dev);
-@@ -796,13 +1162,14 @@
- void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
- {
-+      struct net *net = dev->nd_net;
-       struct sk_buff *skb;
-       int err = -ENOBUFS;
-       if (!nx_dev_visible(current->nx_info, dev))
-               return;
--      skb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL);
-+      skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
-       if (skb == NULL)
-               goto errout;
-@@ -813,10 +1180,10 @@
-               kfree_skb(skb);
-               goto errout;
-       }
--      err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
-+      err = rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
- errout:
-       if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_LINK, err);
-+              rtnl_set_sk_err(net, RTNLGRP_LINK, err);
- }
- /* Protected by RTNL sempahore.  */
-@@ -827,6 +1194,7 @@
- static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
- {
-+      struct net *net = skb->sk->sk_net;
-       rtnl_doit_func doit;
-       int sz_idx, kind;
-       int min_len;
-@@ -855,6 +1223,7 @@
-               return -EPERM;
-       if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
-+              struct sock *rtnl;
-               rtnl_dumpit_func dumpit;
-               dumpit = rtnl_get_dumpit(family, type);
-@@ -862,6 +1231,7 @@
-                       return -EOPNOTSUPP;
-               __rtnl_unlock();
-+              rtnl = net->rtnl;
-               err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
-               rtnl_lock();
-               return err;
-@@ -911,6 +1281,10 @@
- static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
- {
-       struct net_device *dev = ptr;
-+
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       switch (event) {
-       case NETDEV_UNREGISTER:
-               rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
-@@ -936,6 +1310,36 @@
-       .notifier_call  = rtnetlink_event,
- };
-+
-+static int rtnetlink_net_init(struct net *net)
-+{
-+      struct sock *sk;
-+      sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX,
-+                                 rtnetlink_rcv, &rtnl_mutex, THIS_MODULE);
-+      if (!sk)
-+              return -ENOMEM;
-+
-+      /* Don't hold an extra reference on the namespace */
-+      put_net(sk->sk_net);
-+      net->rtnl = sk;
-+      return 0;
-+}
-+
-+static void rtnetlink_net_exit(struct net *net)
-+{
-+      /* At the last minute lie and say this is a socket for the
-+       * initial network namespace.  So the socket will be safe to
-+       * free.
-+       */
-+      net->rtnl->sk_net = get_net(&init_net);
-+      sock_put(net->rtnl);
-+}
-+
-+static struct pernet_operations rtnetlink_net_ops = {
-+      .init = rtnetlink_net_init,
-+      .exit = rtnetlink_net_exit,
-+};
-+
- void __init rtnetlink_init(void)
- {
-       int i;
-@@ -948,15 +1352,16 @@
-       if (!rta_buf)
-               panic("rtnetlink_init: cannot allocate rta_buf\n");
--      rtnl = netlink_kernel_create(NETLINK_ROUTE, RTNLGRP_MAX, rtnetlink_rcv,
--                                   &rtnl_mutex, THIS_MODULE);
--      if (rtnl == NULL)
-+      if (register_pernet_subsys(&rtnetlink_net_ops))
-               panic("rtnetlink_init: cannot initialize rtnetlink\n");
-+
-       netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
-       register_netdevice_notifier(&rtnetlink_dev_notifier);
-       rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo);
-       rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL);
-+      rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL);
-+      rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL);
-       rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all);
-       rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all);
-@@ -965,6 +1370,7 @@
- EXPORT_SYMBOL(__rta_fill);
- EXPORT_SYMBOL(rtattr_strlcpy);
- EXPORT_SYMBOL(rtattr_parse);
-+EXPORT_SYMBOL(__rtattr_parse_nested_compat);
- EXPORT_SYMBOL(rtnetlink_put_metrics);
- EXPORT_SYMBOL(rtnl_lock);
- EXPORT_SYMBOL(rtnl_trylock);
-diff -Nurb linux-2.6.22-570/net/core/skbuff.c linux-2.6.22-590/net/core/skbuff.c
---- linux-2.6.22-570/net/core/skbuff.c 2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/net/core/skbuff.c 2008-01-02 13:56:38.000000000 -0500
-@@ -417,6 +417,7 @@
-       C(csum);
-       C(local_df);
-       n->cloned = 1;
-+      n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
-       n->nohdr = 0;
-       C(pkt_type);
-       C(ip_summed);
-@@ -681,6 +682,7 @@
-       skb->network_header   += off;
-       skb->mac_header       += off;
-       skb->cloned   = 0;
-+      skb->hdr_len  = 0;
-       skb->nohdr    = 0;
-       atomic_set(&skb_shinfo(skb)->dataref, 1);
-       return 0;
-@@ -2012,13 +2014,13 @@
-       skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
-                                             sizeof(struct sk_buff),
-                                             0,
--                                            SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+                              SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_TEMPORARY,
-                                             NULL, NULL);
-       skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache",
-                                               (2*sizeof(struct sk_buff)) +
-                                               sizeof(atomic_t),
-                                               0,
--                                              SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+                              SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_TEMPORARY,
-                                               NULL, NULL);
- }
-diff -Nurb linux-2.6.22-570/net/core/sock.c linux-2.6.22-590/net/core/sock.c
---- linux-2.6.22-570/net/core/sock.c   2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/net/core/sock.c   2008-01-02 13:56:38.000000000 -0500
-@@ -123,6 +123,7 @@
- #include <net/sock.h>
- #include <net/xfrm.h>
- #include <linux/ipsec.h>
-+#include <net/net_namespace.h>
+-      return 0;
+-#undef CASES
+-#undef FRAME_REG
+-}
+-EXPORT_SYMBOL(unwind);
+-
+-int unwind_init_frame_info(struct unwind_frame_info *info,
+-                           struct task_struct *tsk,
+-                           /*const*/ struct pt_regs *regs)
+-{
+-      info->task = tsk;
+-      info->call_frame = 0;
+-      arch_unw_init_frame_info(info, regs);
+-
+-      return 0;
+-}
+-EXPORT_SYMBOL(unwind_init_frame_info);
+-
+-/*
+- * Prepare to unwind a blocked task.
+- */
+-int unwind_init_blocked(struct unwind_frame_info *info,
+-                        struct task_struct *tsk)
+-{
+-      info->task = tsk;
+-      info->call_frame = 0;
+-      arch_unw_init_blocked(info);
+-
+-      return 0;
+-}
+-EXPORT_SYMBOL(unwind_init_blocked);
+-
+-/*
+- * Prepare to unwind the currently running thread.
+- */
+-int unwind_init_running(struct unwind_frame_info *info,
+-                        asmlinkage int (*callback)(struct unwind_frame_info *,
+-                                                   void *arg),
+-                        void *arg)
+-{
+-      info->task = current;
+-      info->call_frame = 0;
+-
+-      return arch_unwind_init_running(info, callback, arg);
+-}
+-EXPORT_SYMBOL(unwind_init_running);
+-
+diff -Nurb linux-2.6.22-590/kernel/user.c linux-2.6.22-570/kernel/user.c
+--- linux-2.6.22-590/kernel/user.c     2008-01-23 23:14:57.000000000 -0500
++++ linux-2.6.22-570/kernel/user.c     2008-01-23 19:16:05.000000000 -0500
+@@ -14,17 +14,17 @@
+ #include <linux/bitops.h>
+ #include <linux/key.h>
+ #include <linux/interrupt.h>
+-#include <linux/module.h>
+-#include <linux/user_namespace.h>
  
- #include <linux/filter.h>
- #include <linux/vs_socket.h>
-@@ -360,6 +361,7 @@
-                   char __user *optval, int optlen)
- {
-       struct sock *sk=sock->sk;
-+      struct net *net = sk->sk_net;
-       struct sk_filter *filter;
-       int val;
-       int valbool;
-@@ -614,7 +616,7 @@
-                       if (devname[0] == '\0') {
-                               sk->sk_bound_dev_if = 0;
-                       } else {
--                              struct net_device *dev = dev_get_by_name(devname);
-+                              struct net_device *dev = dev_get_by_name(net, devname);
-                               if (!dev) {
-                                       ret = -ENODEV;
-                                       break;
-@@ -867,7 +869,7 @@
-  *    @prot: struct proto associated with this new sock instance
-  *    @zero_it: if we should zero the newly allocated sock
+ /*
+  * UID task count cache, to get fast user lookup in "alloc_uid"
+  * when changing user ID's (ie setuid() and friends).
   */
--struct sock *sk_alloc(int family, gfp_t priority,
-+struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
-                     struct proto *prot, int zero_it)
- {
-       struct sock *sk = NULL;
-@@ -888,6 +890,7 @@
-                        */
-                       sk->sk_prot = sk->sk_prot_creator = prot;
-                       sock_lock_init(sk);
-+                      sk->sk_net = get_net(net);
-               }
-               sock_vx_init(sk);
-               sock_nx_init(sk);
-@@ -929,6 +932,7 @@
-                      __FUNCTION__, atomic_read(&sk->sk_omem_alloc));
  
-       security_sk_free(sk);
-+      put_net(sk->sk_net);
-       vx_sock_dec(sk);
-       clr_vx_info(&sk->sk_vx_info);
-       sk->sk_xid = -1;
-@@ -943,7 +947,7 @@
++#define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 8)
++#define UIDHASH_SZ            (1 << UIDHASH_BITS)
+ #define UIDHASH_MASK          (UIDHASH_SZ - 1)
+ #define __uidhashfn(xid,uid)  ((((uid) >> UIDHASH_BITS) + ((uid)^(xid))) & UIDHASH_MASK)
+-#define uidhashentry(xid, uid)        (uidhash_table + __uidhashfn(xid, uid))
++#define uidhashentry(xid,uid) (uidhash_table + __uidhashfn((xid),(uid)))
  
- struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
+ static struct kmem_cache *uid_cachep;
+ static struct list_head uidhash_table[UIDHASH_SZ];
+@@ -94,7 +94,6 @@
  {
--      struct sock *newsk = sk_alloc(sk->sk_family, priority, sk->sk_prot, 0);
-+      struct sock *newsk = sk_alloc(sk->sk_net, sk->sk_family, priority, sk->sk_prot, 0);
+       struct user_struct *ret;
+       unsigned long flags;
+-      struct user_namespace *ns = current->nsproxy->user_ns;
  
-       if (newsk != NULL) {
-               struct sk_filter *filter;
-@@ -2017,7 +2021,7 @@
- static int __init proto_init(void)
- {
-       /* register /proc/net/protocols */
--      return proc_net_fops_create("protocols", S_IRUGO, &proto_seq_fops) == NULL ? -ENOBUFS : 0;
-+      return proc_net_fops_create(&init_net, "protocols", S_IRUGO, &proto_seq_fops) == NULL ? -ENOBUFS : 0;
- }
+       spin_lock_irqsave(&uidhash_lock, flags);
+       ret = uid_hash_find(xid, uid, uidhashentry(xid, uid));
+@@ -213,11 +212,11 @@
+                       0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+       for(n = 0; n < UIDHASH_SZ; ++n)
+-              INIT_LIST_HEAD(init_user_ns.uidhash_table + n);
++              INIT_LIST_HEAD(uidhash_table + n);
  
- subsys_initcall(proto_init);
-diff -Nurb linux-2.6.22-570/net/core/sysctl_net_core.c linux-2.6.22-590/net/core/sysctl_net_core.c
---- linux-2.6.22-570/net/core/sysctl_net_core.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/core/sysctl_net_core.c        2008-01-02 13:56:38.000000000 -0500
-@@ -9,25 +9,10 @@
- #include <linux/sysctl.h>
- #include <linux/module.h>
- #include <linux/socket.h>
-+#include <linux/netdevice.h>
-+#include <net/xfrm.h>
- #include <net/sock.h>
+       /* Insert the root user immediately (init already runs as root) */
+       spin_lock_irq(&uidhash_lock);
+-      uid_hash_insert(&root_user, uidhashentry(0, 0));
++      uid_hash_insert(&root_user, uidhashentry(0,0));
+       spin_unlock_irq(&uidhash_lock);
  
--#ifdef CONFIG_SYSCTL
+       return 0;
+diff -Nurb linux-2.6.22-590/kernel/user.c.orig linux-2.6.22-570/kernel/user.c.orig
+--- linux-2.6.22-590/kernel/user.c.orig        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/user.c.orig        1969-12-31 19:00:00.000000000 -0500
+@@ -1,227 +0,0 @@
+-/*
+- * The "user cache".
+- *
+- * (C) Copyright 1991-2000 Linus Torvalds
+- *
+- * We have a per-user structure to keep track of how many
+- * processes, files etc the user has claimed, in order to be
+- * able to have per-user limits for system resources. 
+- */
+-
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/slab.h>
+-#include <linux/bitops.h>
+-#include <linux/key.h>
+-#include <linux/interrupt.h>
+-#include <linux/module.h>
+-#include <linux/user_namespace.h>
 -
--extern int netdev_max_backlog;
--extern int weight_p;
+-/*
+- * UID task count cache, to get fast user lookup in "alloc_uid"
+- * when changing user ID's (ie setuid() and friends).
+- */
 -
--extern __u32 sysctl_wmem_max;
--extern __u32 sysctl_rmem_max;
+-#define UIDHASH_MASK          (UIDHASH_SZ - 1)
+-#define __uidhashfn(xid,uid)  ((((uid) >> UIDHASH_BITS) + ((uid)^(xid))) & UIDHASH_MASK)
+-#define uidhashentry(ns, xid, uid)    ((ns)->uidhash_table + __uidhashfn(xid, uid))
 -
--extern int sysctl_core_destroy_delay;
+-static struct kmem_cache *uid_cachep;
+-static struct list_head uidhash_table[UIDHASH_SZ];
 -
--#ifdef CONFIG_XFRM
--extern u32 sysctl_xfrm_aevent_etime;
--extern u32 sysctl_xfrm_aevent_rseqth;
--extern int sysctl_xfrm_larval_drop;
--extern u32 sysctl_xfrm_acq_expires;
+-/*
+- * The uidhash_lock is mostly taken from process context, but it is
+- * occasionally also taken from softirq/tasklet context, when
+- * task-structs get RCU-freed. Hence all locking must be softirq-safe.
+- * But free_uid() is also called with local interrupts disabled, and running
+- * local_bh_enable() with local interrupts disabled is an error - we'll run
+- * softirq callbacks, and they can unconditionally enable interrupts, and
+- * the caller of free_uid() didn't expect that..
+- */
+-static DEFINE_SPINLOCK(uidhash_lock);
+-
+-struct user_struct root_user = {
+-      .__count        = ATOMIC_INIT(1),
+-      .processes      = ATOMIC_INIT(1),
+-      .files          = ATOMIC_INIT(0),
+-      .sigpending     = ATOMIC_INIT(0),
+-      .mq_bytes       = 0,
+-      .locked_shm     = 0,
+-#ifdef CONFIG_KEYS
+-      .uid_keyring    = &root_user_keyring,
+-      .session_keyring = &root_session_keyring,
 -#endif
+-};
 -
- ctl_table core_table[] = {
- #ifdef CONFIG_NET
-       {
-@@ -103,11 +88,32 @@
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec
-       },
-+#endif /* CONFIG_NET */
-+      {
-+              .ctl_name       = NET_CORE_BUDGET,
-+              .procname       = "netdev_budget",
-+              .data           = &netdev_budget,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec
-+      },
-+      {
-+              .ctl_name       = NET_CORE_WARNINGS,
-+              .procname       = "warnings",
-+              .data           = &net_msg_warn,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec
-+      },
-+      { .ctl_name = 0 }
-+};
-+
-+struct ctl_table multi_core_table[] = {
- #ifdef CONFIG_XFRM
-       {
-               .ctl_name       = NET_CORE_AEVENT_ETIME,
-               .procname       = "xfrm_aevent_etime",
--              .data           = &sysctl_xfrm_aevent_etime,
-+              .data           = &init_net.sysctl_xfrm_aevent_etime,
-               .maxlen         = sizeof(u32),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec
-@@ -115,7 +121,7 @@
-       {
-               .ctl_name       = NET_CORE_AEVENT_RSEQTH,
-               .procname       = "xfrm_aevent_rseqth",
--              .data           = &sysctl_xfrm_aevent_rseqth,
-+              .data           = &init_net.sysctl_xfrm_aevent_rseqth,
-               .maxlen         = sizeof(u32),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec
-@@ -123,7 +129,7 @@
-       {
-               .ctl_name       = CTL_UNNUMBERED,
-               .procname       = "xfrm_larval_drop",
--              .data           = &sysctl_xfrm_larval_drop,
-+              .data           = &init_net.sysctl_xfrm_larval_drop,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec
-@@ -131,38 +137,19 @@
-       {
-               .ctl_name       = CTL_UNNUMBERED,
-               .procname       = "xfrm_acq_expires",
--              .data           = &sysctl_xfrm_acq_expires,
-+              .data           = &init_net.sysctl_xfrm_acq_expires,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec
-       },
- #endif /* CONFIG_XFRM */
--#endif /* CONFIG_NET */
-       {
-               .ctl_name       = NET_CORE_SOMAXCONN,
-               .procname       = "somaxconn",
--              .data           = &sysctl_somaxconn,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec
--      },
--      {
--              .ctl_name       = NET_CORE_BUDGET,
--              .procname       = "netdev_budget",
--              .data           = &netdev_budget,
-+              .data           = &init_net.sysctl_somaxconn,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec
-       },
--      {
--              .ctl_name       = NET_CORE_WARNINGS,
--              .procname       = "warnings",
--              .data           = &net_msg_warn,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec
+-/*
+- * These routines must be called with the uidhash spinlock held!
+- */
+-static inline void uid_hash_insert(struct user_struct *up, struct list_head *hashent)
+-{
+-      list_add(&up->uidhash_list, hashent);
+-}
+-
+-static inline void uid_hash_remove(struct user_struct *up)
+-{
+-      list_del(&up->uidhash_list);
+-}
+-
+-static inline struct user_struct *uid_hash_find(xid_t xid, uid_t uid, struct list_head *hashent)
+-{
+-      struct list_head *up;
+-
+-      list_for_each(up, hashent) {
+-              struct user_struct *user;
+-
+-              user = list_entry(up, struct user_struct, uidhash_list);
+-
+-              if(user->uid == uid && user->xid == xid) {
+-                      atomic_inc(&user->__count);
+-                      return user;
+-              }
+-      }
+-
+-      return NULL;
+-}
+-
+-/*
+- * Locate the user_struct for the passed UID.  If found, take a ref on it.  The
+- * caller must undo that ref with free_uid().
+- *
+- * If the user_struct could not be found, return NULL.
+- */
+-struct user_struct *find_user(xid_t xid, uid_t uid)
+-{
+-      struct user_struct *ret;
+-      unsigned long flags;
+-      struct user_namespace *ns = current->nsproxy->user_ns;
+-
+-      spin_lock_irqsave(&uidhash_lock, flags);
+-      ret = uid_hash_find(xid, uid, uidhashentry(ns, xid, uid));
+-      spin_unlock_irqrestore(&uidhash_lock, flags);
+-      return ret;
+-}
+-
+-void free_uid(struct user_struct *up)
+-{
+-      unsigned long flags;
+-
+-      if (!up)
+-              return;
+-
+-      local_irq_save(flags);
+-      if (atomic_dec_and_lock(&up->__count, &uidhash_lock)) {
+-              uid_hash_remove(up);
+-              spin_unlock_irqrestore(&uidhash_lock, flags);
+-              key_put(up->uid_keyring);
+-              key_put(up->session_keyring);
+-              kmem_cache_free(uid_cachep, up);
+-      } else {
+-              local_irq_restore(flags);
+-      }
+-}
+-
+-struct user_struct * alloc_uid(xid_t xid, uid_t uid)
+-{
+-      struct user_namespace *ns = current->nsproxy->user_ns;
+-      struct list_head *hashent = uidhashentry(ns,xid, uid);
+-      struct user_struct *up;
+-
+-      spin_lock_irq(&uidhash_lock);
+-      up = uid_hash_find(xid, uid, hashent);
+-      spin_unlock_irq(&uidhash_lock);
+-
+-      if (!up) {
+-              struct user_struct *new;
+-
+-              new = kmem_cache_alloc(uid_cachep, GFP_KERNEL);
+-              if (!new)
+-                      return NULL;
+-              new->uid = uid;
+-              new->xid = xid;
+-              atomic_set(&new->__count, 1);
+-              atomic_set(&new->processes, 0);
+-              atomic_set(&new->files, 0);
+-              atomic_set(&new->sigpending, 0);
+-#ifdef CONFIG_INOTIFY_USER
+-              atomic_set(&new->inotify_watches, 0);
+-              atomic_set(&new->inotify_devs, 0);
+-#endif
+-
+-              new->mq_bytes = 0;
+-              new->locked_shm = 0;
+-
+-              if (alloc_uid_keyring(new, current) < 0) {
+-                      kmem_cache_free(uid_cachep, new);
+-                      return NULL;
+-              }
+-
+-              /*
+-               * Before adding this, check whether we raced
+-               * on adding the same user already..
+-               */
+-              spin_lock_irq(&uidhash_lock);
+-              up = uid_hash_find(xid, uid, hashent);
+-              if (up) {
+-                      key_put(new->uid_keyring);
+-                      key_put(new->session_keyring);
+-                      kmem_cache_free(uid_cachep, new);
+-              } else {
+-                      uid_hash_insert(new, hashent);
+-                      up = new;
+-              }
+-              spin_unlock_irq(&uidhash_lock);
+-
+-      }
+-      return up;
+-}
+-
+-void switch_uid(struct user_struct *new_user)
+-{
+-      struct user_struct *old_user;
+-
+-      /* What if a process setreuid()'s and this brings the
+-       * new uid over his NPROC rlimit?  We can check this now
+-       * cheaply with the new uid cache, so if it matters
+-       * we should be checking for it.  -DaveM
+-       */
+-      old_user = current->user;
+-      atomic_inc(&new_user->processes);
+-      atomic_dec(&old_user->processes);
+-      switch_uid_keyring(new_user);
+-      current->user = new_user;
+-
+-      /*
+-       * We need to synchronize with __sigqueue_alloc()
+-       * doing a get_uid(p->user).. If that saw the old
+-       * user value, we need to wait until it has exited
+-       * its critical region before we can free the old
+-       * structure.
+-       */
+-      smp_mb();
+-      spin_unlock_wait(&current->sighand->siglock);
+-
+-      free_uid(old_user);
+-      suid_keys(current);
+-}
+-
+-
+-static int __init uid_cache_init(void)
+-{
+-      int n;
+-
+-      uid_cachep = kmem_cache_create("uid_cache", sizeof(struct user_struct),
+-                      0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+-
+-      for(n = 0; n < UIDHASH_SZ; ++n)
+-              INIT_LIST_HEAD(init_user_ns.uidhash_table + n);
+-
+-      /* Insert the root user immediately (init already runs as root) */
+-      spin_lock_irq(&uidhash_lock);
+-      uid_hash_insert(&root_user, uidhashentry(&init_user_ns, 0, 0));
+-      spin_unlock_irq(&uidhash_lock);
+-
+-      return 0;
+-}
+-
+-module_init(uid_cache_init);
+diff -Nurb linux-2.6.22-590/kernel/user_namespace.c linux-2.6.22-570/kernel/user_namespace.c
+--- linux-2.6.22-590/kernel/user_namespace.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/user_namespace.c   1969-12-31 19:00:00.000000000 -0500
+@@ -1,87 +0,0 @@
+-/*
+- *  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, version 2 of the
+- *  License.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/version.h>
+-#include <linux/nsproxy.h>
+-#include <linux/user_namespace.h>
+-
+-struct user_namespace init_user_ns = {
+-      .kref = {
+-              .refcount       = ATOMIC_INIT(2),
 -      },
--      { .ctl_name = 0 }
-+      {}
- };
+-      .root_user = &root_user,
+-};
 -
--#endif
-diff -Nurb linux-2.6.22-570/net/dccp/ccids/ccid3.c linux-2.6.22-590/net/dccp/ccids/ccid3.c
---- linux-2.6.22-570/net/dccp/ccids/ccid3.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/dccp/ccids/ccid3.c    2008-01-02 13:56:38.000000000 -0500
-@@ -1,8 +1,8 @@
- /*
-  *  net/dccp/ccids/ccid3.c
-  *
-- *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
-- *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
-+ *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
-+ *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
-  *
-  *  An implementation of the DCCP protocol
-  *
-@@ -49,7 +49,6 @@
- static struct dccp_tx_hist *ccid3_tx_hist;
- static struct dccp_rx_hist *ccid3_rx_hist;
--static struct dccp_li_hist *ccid3_li_hist;
+-EXPORT_SYMBOL_GPL(init_user_ns);
+-
+-#ifdef CONFIG_USER_NS
+-
+-/*
+- * Clone a new ns copying an original user ns, setting refcount to 1
+- * @old_ns: namespace to clone
+- * Return NULL on error (failure to kmalloc), new ns otherwise
+- */
+-static struct user_namespace *clone_user_ns(struct user_namespace *old_ns)
+-{
+-      struct user_namespace *ns;
+-      struct user_struct *new_user;
+-      int n;
+-
+-      ns = kmalloc(sizeof(struct user_namespace), GFP_KERNEL);
+-      if (!ns)
+-              return ERR_PTR(-ENOMEM);
+-
+-      kref_init(&ns->kref);
+-
+-      for (n = 0; n < UIDHASH_SZ; ++n)
+-              INIT_LIST_HEAD(ns->uidhash_table + n);
+-
+-      /* Insert new root user.  */
+-      ns->root_user = alloc_uid(ns, 0);
+-      if (!ns->root_user) {
+-              kfree(ns);
+-              return ERR_PTR(-ENOMEM);
+-      }
+-
+-      /* Reset current->user with a new one */
+-      new_user = alloc_uid(ns, current->uid);
+-      if (!new_user) {
+-              free_uid(ns->root_user);
+-              kfree(ns);
+-              return ERR_PTR(-ENOMEM);
+-      }
+-
+-      switch_uid(new_user);
+-      return ns;
+-}
+-
+-struct user_namespace * copy_user_ns(int flags, struct user_namespace *old_ns)
+-{
+-      struct user_namespace *new_ns;
+-
+-      BUG_ON(!old_ns);
+-      get_user_ns(old_ns);
+-
+-      if (!(flags & CLONE_NEWUSER))
+-              return old_ns;
+-
+-      new_ns = clone_user_ns(old_ns);
+-
+-      put_user_ns(old_ns);
+-      return new_ns;
+-}
+-
+-void free_user_ns(struct kref *kref)
+-{
+-      struct user_namespace *ns;
+-
+-      ns = container_of(kref, struct user_namespace, kref);
+-      kfree(ns);
+-}
+-
+-#endif /* CONFIG_USER_NS */
+diff -Nurb linux-2.6.22-590/kernel/utsname.c linux-2.6.22-570/kernel/utsname.c
+--- linux-2.6.22-590/kernel/utsname.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/utsname.c  2008-01-23 19:16:05.000000000 -0500
+@@ -14,7 +14,6 @@
+ #include <linux/utsname.h>
+ #include <linux/version.h>
+ #include <linux/vserver/global.h>
+-#include <linux/err.h>
  
  /*
-  *    Transmitter Half-Connection Routines
-@@ -194,25 +193,20 @@
-  *    The algorithm is not applicable if RTT < 4 microseconds.
-  */
- static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx,
--                                              struct timeval *now)
-+                                              ktime_t now)
- {
--      suseconds_t delta;
-       u32 quarter_rtts;
-       if (unlikely(hctx->ccid3hctx_rtt < 4))  /* avoid divide-by-zero */
-               return;
--      delta = timeval_delta(now, &hctx->ccid3hctx_t_last_win_count);
--      DCCP_BUG_ON(delta < 0);
--
--      quarter_rtts = (u32)delta / (hctx->ccid3hctx_rtt / 4);
-+      quarter_rtts = ktime_us_delta(now, hctx->ccid3hctx_t_last_win_count);
-+      quarter_rtts /= hctx->ccid3hctx_rtt / 4;
+  * Clone a new ns copying an original utsname, setting refcount to 1
+@@ -26,12 +25,11 @@
+       struct uts_namespace *ns;
  
-       if (quarter_rtts > 0) {
--              hctx->ccid3hctx_t_last_win_count = *now;
-+              hctx->ccid3hctx_t_last_win_count = now;
-               hctx->ccid3hctx_last_win_count  += min_t(u32, quarter_rtts, 5);
-               hctx->ccid3hctx_last_win_count  &= 0xF;         /* mod 16 */
+       ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL);
+-      if (!ns)
+-              return ERR_PTR(-ENOMEM);
+- 
++      if (ns) {
+               memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
+               kref_init(&ns->kref);
 -
--              ccid3_pr_debug("now at %#X\n", hctx->ccid3hctx_last_win_count);
-       }
++              atomic_inc(&vs_global_uts_ns);
++      }
+       return ns;
  }
  
-@@ -312,8 +306,8 @@
+@@ -41,7 +39,7 @@
+  * utsname of this process won't be seen by parent, and vice
+  * versa.
+  */
+-struct uts_namespace *copy_utsname(unsigned long flags, struct uts_namespace *old_ns)
++struct uts_namespace *copy_utsname(int flags, struct uts_namespace *old_ns)
  {
-       struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
--      struct timeval now;
--      suseconds_t delay;
-+      ktime_t now = ktime_get_real();
-+      s64 delay;
-       BUG_ON(hctx == NULL);
-@@ -325,8 +319,6 @@
-       if (unlikely(skb->len == 0))
-               return -EBADMSG;
+       struct uts_namespace *new_ns;
  
--      dccp_timestamp(sk, &now);
+diff -Nurb linux-2.6.22-590/kernel/utsname_sysctl.c linux-2.6.22-570/kernel/utsname_sysctl.c
+--- linux-2.6.22-590/kernel/utsname_sysctl.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/utsname_sysctl.c   2007-07-08 19:32:17.000000000 -0400
+@@ -18,7 +18,10 @@
+ static void *get_uts(ctl_table *table, int write)
+ {
+       char *which = table->data;
 -
-       switch (hctx->ccid3hctx_state) {
-       case TFRC_SSTATE_NO_SENT:
-               sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
-@@ -349,7 +341,7 @@
-                       ccid3_pr_debug("SYN RTT = %uus\n", dp->dccps_syn_rtt);
-                       hctx->ccid3hctx_rtt  = dp->dccps_syn_rtt;
-                       hctx->ccid3hctx_x    = rfc3390_initial_rate(sk);
--                      hctx->ccid3hctx_t_ld = now;
-+                      hctx->ccid3hctx_t_ld = ktime_to_timeval(now);
-               } else {
-                       /* Sender does not have RTT sample: X = MSS/second */
-                       hctx->ccid3hctx_x = dp->dccps_mss_cache;
-@@ -361,7 +353,7 @@
-               break;
-       case TFRC_SSTATE_NO_FBACK:
-       case TFRC_SSTATE_FBACK:
--              delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
-+              delay = ktime_us_delta(hctx->ccid3hctx_t_nom, now);
-               ccid3_pr_debug("delay=%ld\n", (long)delay);
-               /*
-                *      Scheduling of packet transmissions [RFC 3448, 4.6]
-@@ -371,10 +363,10 @@
-                * else
-                *       // send the packet in (t_nom - t_now) milliseconds.
-                */
--              if (delay - (suseconds_t)hctx->ccid3hctx_delta >= 0)
--                      return delay / 1000L;
-+              if (delay - (s64)hctx->ccid3hctx_delta >= 1000)
-+                      return (u32)delay / 1000L;
++#ifdef CONFIG_UTS_NS
++      struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
++      which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
++#endif
+       if (!write)
+               down_read(&uts_sem);
+       else
+diff -Nurb linux-2.6.22-590/kernel/workqueue.c linux-2.6.22-570/kernel/workqueue.c
+--- linux-2.6.22-590/kernel/workqueue.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/kernel/workqueue.c        2008-01-23 19:15:56.000000000 -0500
+@@ -282,8 +282,8 @@
+       struct cpu_workqueue_struct *cwq = __cwq;
+       DEFINE_WAIT(wait);
  
--              ccid3_hc_tx_update_win_count(hctx, &now);
-+              ccid3_hc_tx_update_win_count(hctx, now);
-               break;
-       case TFRC_SSTATE_TERM:
-               DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
-@@ -387,8 +379,8 @@
-       hctx->ccid3hctx_idle = 0;
+-      if (cwq->wq->freezeable)
+-              set_freezable();
++      if (!cwq->wq->freezeable)
++              current->flags |= PF_NOFREEZE;
  
-       /* set the nominal send time for the next following packet */
--      timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
--
-+      hctx->ccid3hctx_t_nom = ktime_add_us(hctx->ccid3hctx_t_nom,
-+                                           hctx->ccid3hctx_t_ipi);
-       return 0;
- }
+       set_user_nice(current, -5);
  
-@@ -819,154 +811,6 @@
-       return 0;
- }
+diff -Nurb linux-2.6.22-590/lib/Kconfig.debug linux-2.6.22-570/lib/Kconfig.debug
+--- linux-2.6.22-590/lib/Kconfig.debug 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/lib/Kconfig.debug 2007-07-08 19:32:17.000000000 -0400
+@@ -364,24 +364,6 @@
+         some architectures or if you use external debuggers.
+         If you don't debug the kernel, you can say N.
  
--/* calculate first loss interval
-- *
-- * returns estimated loss interval in usecs */
+-config UNWIND_INFO
+-      bool "Compile the kernel with frame unwind information"
+-      depends on !IA64 && !PARISC && !ARM
+-      depends on !MODULES || !(MIPS || PPC || SUPERH || V850)
+-      help
+-        If you say Y here the resulting kernel image will be slightly larger
+-        but not slower, and it will give very useful debugging information.
+-        If you don't debug the kernel, you can say N, but we may not be able
+-        to solve problems without frame unwind information or frame pointers.
+-
+-config STACK_UNWIND
+-      bool "Stack unwind support"
+-      depends on UNWIND_INFO
+-      depends on X86
+-      help
+-        This enables more precise stack traces, omitting all unrelated
+-        occurrences of pointers into kernel code from the dump.
 -
--static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
--{
--      struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
--      struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
--      u32 x_recv, p;
--      suseconds_t rtt, delta;
--      struct timeval tstamp = { 0, };
--      int interval = 0;
--      int win_count = 0;
--      int step = 0;
--      u64 fval;
+ config FORCED_INLINING
+       bool "Force gcc to inline functions marked 'inline'"
+       depends on DEBUG_KERNEL
+@@ -427,9 +409,6 @@
+ config FAULT_INJECTION
+       bool "Fault-injection framework"
+       depends on DEBUG_KERNEL
+-      # could support fp on X86_32 here too, but let's not
+-      select UNWIND_INFO if X86
+-      select STACK_UNWIND if X86
+       help
+         Provide fault-injection framework.
+         For more details, see Documentation/fault-injection/.
+@@ -466,5 +445,3 @@
+       select FRAME_POINTER
+       help
+         Provide stacktrace filter for fault-injection capabilities
 -
--      list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
--                               dccphrx_node) {
--              if (dccp_rx_hist_entry_data_packet(entry)) {
--                      tail = entry;
+-source "lib/Kconfig.kgdb"
+diff -Nurb linux-2.6.22-590/lib/Kconfig.kgdb linux-2.6.22-570/lib/Kconfig.kgdb
+--- linux-2.6.22-590/lib/Kconfig.kgdb  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/lib/Kconfig.kgdb  1969-12-31 19:00:00.000000000 -0500
+@@ -1,255 +0,0 @@
 -
--                      switch (step) {
--                      case 0:
--                              tstamp    = entry->dccphrx_tstamp;
--                              win_count = entry->dccphrx_ccval;
--                              step = 1;
--                              break;
--                      case 1:
--                              interval = win_count - entry->dccphrx_ccval;
--                              if (interval < 0)
--                                      interval += TFRC_WIN_COUNT_LIMIT;
--                              if (interval > 4)
--                                      goto found;
--                              break;
--                      }
--              }
--      }
+-config WANT_EXTRA_DEBUG_INFORMATION
+-      bool
+-      select DEBUG_INFO
+-      select UNWIND_INFO
+-      select FRAME_POINTER if X86 || SUPERH
+-      default n
 -
--      if (unlikely(step == 0)) {
--              DCCP_WARN("%s(%p), packet history has no data packets!\n",
--                        dccp_role(sk), sk);
--              return ~0;
--      }
+-config UNWIND_INFO
+-      bool
+-      default n
 -
--      if (unlikely(interval == 0)) {
--              DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
--                        "Defaulting to 1\n", dccp_role(sk), sk);
--              interval = 1;
--      }
--found:
--      if (!tail) {
--              DCCP_CRIT("tail is null\n");
--              return ~0;
--      }
+-config KGDB
+-      bool "KGDB: kernel debugging with remote gdb"
+-      select WANT_EXTRA_DEBUG_INFORMATION
+-      select KGDB_ARCH_HAS_SHADOW_INFO if X86_64
+-      depends on DEBUG_KERNEL && (ARM || X86 || MIPS || (SUPERH && !SUPERH64) || IA64 || PPC)
+-      help
+-        If you say Y here, it will be possible to remotely debug the
+-        kernel using gdb.  Documentation of kernel debugger is available
+-        at http://kgdb.sourceforge.net as well as in DocBook form
+-        in Documentation/DocBook/.  If unsure, say N.
 -
--      delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
--      DCCP_BUG_ON(delta < 0);
+-config KGDB_ARCH_HAS_SHADOW_INFO
+-      bool
 -
--      rtt = delta * 4 / interval;
--      ccid3_pr_debug("%s(%p), approximated RTT to %dus\n",
--                     dccp_role(sk), sk, (int)rtt);
+-config KGDB_CONSOLE
+-      bool "KGDB: Console messages through gdb"
+-      depends on KGDB
+-        help
+-          If you say Y here, console messages will appear through gdb.
+-          Other consoles such as tty or ttyS will continue to work as usual.
+-          Note, that if you use this in conjunction with KGDB_ETH, if the
+-          ethernet driver runs into an error condition during use with KGDB
+-          it is possible to hit an infinite recusrion, causing the kernel
+-          to crash, and typically reboot.  For this reason, it is preferable
+-          to use NETCONSOLE in conjunction with KGDB_ETH instead of
+-          KGDB_CONSOLE.
 -
--      /*
--       * Determine the length of the first loss interval via inverse lookup.
--       * Assume that X_recv can be computed by the throughput equation
--       *                  s
--       *      X_recv = --------
--       *               R * fval
--       * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
--       */
--      if (rtt == 0) {                 /* would result in divide-by-zero */
--              DCCP_WARN("RTT==0\n");
--              return ~0;
--      }
+-choice
+-      prompt "Method for KGDB communication"
+-      depends on KGDB
+-      default KGDB_MPSC if SERIAL_MPSC
+-      default KGDB_CPM_UART if (CPM2 || 8xx)
+-      default KGDB_SIBYTE if SIBYTE_SB1xxx_SOC
+-      default KGDB_TXX9 if CPU_TX49XX
+-      default KGDB_SH_SCI if SERIAL_SH_SCI
+-      default KGDB_PXA_SERIAL if ARCH_PXA
+-      default KGDB_AMBA_PL011 if ARM_AMBA
+-      default KGDB_8250_NOMODULE
+-      help
+-        There are a number of different ways in which you can communicate
+-        with KGDB.  The most common is via serial, with the 8250 driver
+-        (should your hardware have an 8250, or ns1655x style uart).
+-        Another option is to use the NETPOLL framework and UDP, should
+-        your ethernet card support this.  Other options may exist.
+-        You can elect to have one core I/O driver that is built into the
+-        kernel for debugging as the kernel is booting, or using only
+-        kernel modules.
+-
+-config KGDB_ONLY_MODULES
+-      bool "KGDB: Use only kernel modules for I/O"
+-      depends on MODULES
+-      help
+-        Use only kernel modules to configure KGDB I/O after the
+-        kernel is booted.
 -
--      dccp_timestamp(sk, &tstamp);
--      delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
--      DCCP_BUG_ON(delta <= 0);
+-config KGDB_8250_NOMODULE
+-      bool "KGDB: On generic serial port (8250)"
+-      select KGDB_8250
+-      help
+-        Uses generic serial port (8250) to communicate with the host
+-        GDB.  This is independent of the normal (SERIAL_8250) driver
+-        for this chipset.
 -
--      x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
--      if (x_recv == 0) {              /* would also trigger divide-by-zero */
--              DCCP_WARN("X_recv==0\n");
--              if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) {
--                      DCCP_BUG("stored value of X_recv is zero");
--                      return ~0;
+-config KGDBOE_NOMODULE
+-      bool "KGDB: On ethernet - in kernel"
+-      select KGDBOE
+-      help
+-        Uses the NETPOLL API to communicate with the host GDB via UDP.
+-        In order for this to work, the ethernet interface specified must
+-        support the NETPOLL API, and this must be initialized at boot.
+-        See the documentation for syntax.
+-
+-config KGDB_MPSC
+-      bool "KGDB: On MV64x60 MPSC"
+-      depends on SERIAL_MPSC
+-      help
+-        Uses a Marvell GT64260B or MV64x60 Multi-Purpose Serial
+-        Controller (MPSC) channel. Note that the GT64260A is not
+-        supported.
+-
+-config KGDB_CPM_UART
+-      bool "KGDB: On CPM UART"
+-      depends on PPC && (CPM2 || 8xx)
+-      help
+-        Uses CPM UART to communicate with the host GDB.
+-
+-config KGDB_SIBYTE
+-      bool "KGDB: On Broadcom SB1xxx serial port"
+-      depends on MIPS && SIBYTE_SB1xxx_SOC
+-
+-config KGDB_TXX9
+-      bool "KGDB: On TX49xx serial port"
+-      depends on MIPS && CPU_TX49XX
+-      help
+-        Uses TX49xx serial port to communicate with the host KGDB.
+-
+-config KGDB_SH_SCI
+-      bool "KGDB: On SH SCI(F) serial port"
+-      depends on SUPERH && SERIAL_SH_SCI
+-      help
+-        Uses the SH SCI(F) serial port to communicate with the host GDB.
+-
+-config KGDB_AMBA_PL011
+-      bool "KGDB: On ARM AMBA PL011 Serial Port"
+-      depends on ARM && ARCH_VERSATILE
+-      help
+-        Enables the KGDB serial driver for the AMBA bus PL011 serial
+-          devices from ARM.
+-
+-config KGDB_PXA_SERIAL
+-      bool "KGDB: On the PXA2xx serial port"
+-      depends on ARCH_PXA
+-      help
+-        Enables the KGDB serial driver for Intel PXA SOC
+-endchoice
+-
+-choice
+-      prompt "PXA UART to use for KGDB"
+-      depends on KGDB_PXA_SERIAL
+-      default KGDB_PXA_FFUART
+-
+-config KGDB_PXA_FFUART
+-      bool "FFUART"
+-
+-config KGDB_PXA_BTUART
+-      bool "BTUART"
+-
+-config KGDB_PXA_STUART
+-      bool "STUART"
+-endchoice
+-
+-choice
+-      prompt "SCC/SMC to use for KGDB"
+-      depends on KGDB_CPM_UART
+-      default KGDB_CPM_UART_SCC4 if ADS8272
+-
+-config KGDB_CPM_UART_SCC1
+-      bool "SCC1"
+-      depends on SERIAL_CPM_SCC1
+-
+-config KGDB_CPM_UART_SCC2
+-      bool "SCC2"
+-      depends on SERIAL_CPM_SCC2
+-
+-config KGDB_CPM_UART_SCC3
+-      bool "SCC3"
+-      depends on SERIAL_CPM_SCC3
+-
+-config KGDB_CPM_UART_SCC4
+-      bool "SCC4"
+-      depends on SERIAL_CPM_SCC4
+-
+-config KGDB_CPM_UART_SMC1
+-      bool "SMC1"
+-      depends on SERIAL_CPM_SMC1
+-
+-config KGDB_CPM_UART_SMC2
+-      bool "SMC2"
+-      depends on SERIAL_CPM_SMC2
+-endchoice
+-
+-config KGDBOE
+-      tristate "KGDB: On ethernet" if !KGDBOE_NOMODULE
+-      depends on m && KGDB
+-      select NETPOLL
+-      select NETPOLL_TRAP
+-      help
+-        Uses the NETPOLL API to communicate with the host GDB via UDP.
+-        In order for this to work, the ethernet interface specified must
+-        support the NETPOLL API, and this must be initialized at boot.
+-        See the documentation for syntax.
+-
+-config KGDB_8250
+-      tristate "KGDB: On generic serial port (8250)" if !KGDB_8250_NOMODULE
+-      depends on m && KGDB_ONLY_MODULES
+-      help
+-        Uses generic serial port (8250) to communicate with the host
+-        GDB.  This is independent of the normal (SERIAL_8250) driver
+-        for this chipset.
+-
+-config KGDB_SIMPLE_SERIAL
+-      bool "Simple selection of KGDB serial port"
+-      depends on KGDB_8250_NOMODULE
+-      default y
+-      help
+-        If you say Y here, you will only have to pick the baud rate
+-        and port number that you wish to use for KGDB.  Note that this
+-        only works on architectures that register known serial ports
+-        early on.  If you say N, you will have to provide, either here
+-        or on the command line, the type (I/O or MMIO), IRQ and
+-        address to use.  If in doubt, say Y.
+-
+-config KGDB_BAUDRATE
+-      int "Debug serial port baud rate"
+-      depends on (KGDB_8250 && KGDB_SIMPLE_SERIAL) || \
+-              KGDB_MPSC || KGDB_CPM_UART || \
+-              KGDB_TXX9 || KGDB_PXA_SERIAL || KGDB_AMBA_PL011
+-      default "115200"
+-      help
+-        gdb and the kernel stub need to agree on the baud rate to be
+-        used.  Standard rates from 9600 to 115200 are allowed, and this
+-        may be overridden via the commandline.
+-
+-config KGDB_PORT_NUM
+-      int "Serial port number for KGDB"
+-      range 0 1 if KGDB_MPSC
+-      range 0 3
+-      depends on (KGDB_8250 && KGDB_SIMPLE_SERIAL) || KGDB_MPSC || KGDB_TXX9
+-      default "1"
+-      help
+-        Pick the port number (0 based) for KGDB to use.
+-
+-config KGDB_AMBA_BASE
+-      hex "AMBA PL011 Serial Port Base Address"
+-      default 0x101f2000 if ARCH_VERSATILE
+-      depends on KGDB_AMBA_PL011
+-      help
+-        Base address of the AMBA port that KGDB will use.
+-
+-config KGDB_AMBA_UARTCLK
+-      int "AMBAPL011 Serial UART Clock Frequency"
+-      default 24000000 if ARCH_VERSATILE
+-      depends on KGDB_AMBA_PL011
+-      help
+-        Frequency (in HZ) of the ARM AMBA UART clock
+-
+-config KGDB_AMBA_IRQ
+-      int "AMBA PL011 Serial Port IRQ"
+-      default 13 if ARCH_VERSATILE
+-      depends on KGDB_AMBA_PL011
+-      help
+-        Pick the IRQ of the AMBA port that KGDB will use.
+-
+-config KGDB_8250_CONF_STRING
+-      string "Configuration string for KGDB"
+-      depends on KGDB_8250_NOMODULE && !KGDB_SIMPLE_SERIAL
+-      default "io,2f8,115200,3" if X86
+-      help
+-        The format of this string should be <io or
+-        mmio>,<address>,<baud rate>,<irq>.  For example, to use the
+-        serial port on an i386 box located at 0x2f8 and 115200 baud
+-        on IRQ 3 at use:
+-        io,2f8,115200,3
+diff -Nurb linux-2.6.22-590/lib/Makefile linux-2.6.22-570/lib/Makefile
+--- linux-2.6.22-590/lib/Makefile      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/lib/Makefile      2007-07-08 19:32:17.000000000 -0400
+@@ -5,10 +5,9 @@
+ lib-y := ctype.o string.o vsprintf.o cmdline.o \
+        rbtree.o radix-tree.o dump_stack.o \
+        idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \
+-       sha1.o irq_regs.o reciprocal_div.o argv_split.o \
+-       check_signature.o
++       sha1.o irq_regs.o reciprocal_div.o
+-lib-$(CONFIG_MMU) += ioremap.o pagewalk.o
++lib-$(CONFIG_MMU) += ioremap.o
+ lib-$(CONFIG_SMP) += cpumask.o
+ lib-y += kobject.o kref.o kobject_uevent.o klist.o
+diff -Nurb linux-2.6.22-590/lib/argv_split.c linux-2.6.22-570/lib/argv_split.c
+--- linux-2.6.22-590/lib/argv_split.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/lib/argv_split.c  1969-12-31 19:00:00.000000000 -0500
+@@ -1,159 +0,0 @@
+-/*
+- * Helper function for splitting a string into an argv-like array.
+- */
+-
+-#ifndef TEST
+-#include <linux/kernel.h>
+-#include <linux/ctype.h>
+-#include <linux/bug.h>
+-#endif
+-
+-static const char *skip_sep(const char *cp)
+-{
+-      while (*cp && isspace(*cp))
+-              cp++;
+-
+-      return cp;
+-}
+-
+-static const char *skip_arg(const char *cp)
+-{
+-      while (*cp && !isspace(*cp))
+-              cp++;
+-
+-      return cp;
+-}
+-
+-static int count_argc(const char *str)
+-{
+-      int count = 0;
+-
+-      while (*str) {
+-              str = skip_sep(str);
+-              if (*str) {
+-                      count++;
+-                      str = skip_arg(str);
 -              }
 -      }
 -
--      fval = scaled_div(hcrx->ccid3hcrx_s, rtt);
--      fval = scaled_div32(fval, x_recv);
--      p = tfrc_calc_x_reverse_lookup(fval);
+-      return count;
+-}
 -
--      ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
--                     "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
+-/**
+- * argv_free - free an argv
+- *
+- * @argv - the argument vector to be freed
+- *
+- * Frees an argv and the strings it points to.
+- */
+-void argv_free(char **argv)
+-{
+-      char **p;
+-      for (p = argv; *p; p++)
+-              kfree(*p);
 -
--      if (p == 0)
--              return ~0;
--      else
--              return 1000000 / p;
+-      kfree(argv);
 -}
+-EXPORT_SYMBOL(argv_free);
 -
--static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
+-/**
+- * argv_split - split a string at whitespace, returning an argv
+- * @gfp: the GFP mask used to allocate memory
+- * @str: the string to be split
+- * @argcp: returned argument count
+- *
+- * Returns an array of pointers to strings which are split out from
+- * @str.  This is performed by strictly splitting on white-space; no
+- * quote processing is performed.  Multiple whitespace characters are
+- * considered to be a single argument separator.  The returned array
+- * is always NULL-terminated.  Returns NULL on memory allocation
+- * failure.
+- */
+-char **argv_split(gfp_t gfp, const char *str, int *argcp)
 -{
--      struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
--      struct dccp_li_hist_entry *head;
--      u64 seq_temp;
+-      int argc = count_argc(str);
+-      char **argv = kzalloc(sizeof(*argv) * (argc+1), gfp);
+-      char **argvp;
 -
--      if (list_empty(&hcrx->ccid3hcrx_li_hist)) {
--              if (!dccp_li_hist_interval_new(ccid3_li_hist,
--                 &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss))
--                      return;
+-      if (argv == NULL)
+-              goto out;
 -
--              head = list_entry(hcrx->ccid3hcrx_li_hist.next,
--                 struct dccp_li_hist_entry, dccplih_node);
--              head->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
--      } else {
--              struct dccp_li_hist_entry *entry;
--              struct list_head *tail;
+-      *argcp = argc;
+-      argvp = argv;
 -
--              head = list_entry(hcrx->ccid3hcrx_li_hist.next,
--                 struct dccp_li_hist_entry, dccplih_node);
--              /* FIXME win count check removed as was wrong */
--              /* should make this check with receive history */
--              /* and compare there as per section 10.2 of RFC4342 */
+-      while (*str) {
+-              str = skip_sep(str);
 -
--              /* new loss event detected */
--              /* calculate last interval length */
--              seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
--              entry = dccp_li_hist_entry_new(ccid3_li_hist, GFP_ATOMIC);
+-              if (*str) {
+-                      const char *p = str;
+-                      char *t;
+-
+-                      str = skip_arg(str);
+-
+-                      t = kstrndup(p, str-p, gfp);
+-                      if (t == NULL)
+-                              goto fail;
+-                      *argvp++ = t;
+-              }
+-      }
+-      *argvp = NULL;
+-
+-  out:
+-      return argv;
+-
+-  fail:
+-      argv_free(argv);
+-      return NULL;
+-}
+-EXPORT_SYMBOL(argv_split);
+-
+-#ifdef TEST
+-#define _GNU_SOURCE
+-#include <ctype.h>
+-#include <stdlib.h>
+-#include <stdio.h>
+-#include <string.h>
+-
+-typedef enum {
+-      GFP_KERNEL,
+-} gfp_t;
+-#define kzalloc(size, x)      malloc(size)
+-#define kfree(x)              free(x)
+-#define kstrndup(s, n, gfp)   strndup(s, n)
+-#define BUG() abort()
+-
+-int main() {
+-      const char *testvec[] = {
+-              "",
+-              "x",
+-              "\"",
+-              "\\\0",
+-              "\"",
+-              "test one two three",
+-              "arg\"foo\"bar biff",
+-              "one two\\ three four",
+-              "one \"two three\" four",
+-              NULL,
+-      };
+-      const char **t;
 -
--              if (entry == NULL) {
--                      DCCP_BUG("out of memory - can not allocate entry");
--                      return;
--              }
+-      for (t = testvec; *t; t++) {
+-              char **argv;
+-              int argc;
+-              char **a;
 -
--              list_add(&entry->dccplih_node, &hcrx->ccid3hcrx_li_hist);
+-              printf("%d: test [%s]\n", t-testvec, *t);
 -
--              tail = hcrx->ccid3hcrx_li_hist.prev;
--              list_del(tail);
--              kmem_cache_free(ccid3_li_hist->dccplih_slab, tail);
+-              argv = argv_split(GFP_KERNEL, *t, &argc);
 -
--              /* Create the newest interval */
--              entry->dccplih_seqno = seq_loss;
--              entry->dccplih_interval = seq_temp;
--              entry->dccplih_win_count = win_loss;
+-              printf("argc=%d vec=", argc);
+-              for (a = argv; *a; a++)
+-                      printf("[%s] ", *a);
+-              printf("\n");
+-
+-              argv_free(argv);
 -      }
+-
+-      return 0;
 -}
+-#endif
+diff -Nurb linux-2.6.22-590/lib/check_signature.c linux-2.6.22-570/lib/check_signature.c
+--- linux-2.6.22-590/lib/check_signature.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/lib/check_signature.c     1969-12-31 19:00:00.000000000 -0500
+@@ -1,26 +0,0 @@
+-#include <linux/io.h>
+-#include <linux/module.h>
 -
- static int ccid3_hc_rx_detect_loss(struct sock *sk,
-                                   struct dccp_rx_hist_entry *packet)
- {
-@@ -992,7 +836,14 @@
-       while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno)
-          > TFRC_RECV_NUM_LATE_LOSS) {
-               loss = 1;
--              ccid3_hc_rx_update_li(sk, hcrx->ccid3hcrx_seqno_nonloss,
-+              dccp_li_update_li(sk,
-+                                &hcrx->ccid3hcrx_li_hist,
-+                                &hcrx->ccid3hcrx_hist,
-+                                &hcrx->ccid3hcrx_tstamp_last_feedback,
-+                                hcrx->ccid3hcrx_s,
-+                                hcrx->ccid3hcrx_bytes_recv,
-+                                hcrx->ccid3hcrx_x_recv,
-+                                hcrx->ccid3hcrx_seqno_nonloss,
-                  hcrx->ccid3hcrx_ccval_nonloss);
-               tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
-               dccp_inc_seqno(&tmp_seqno);
-@@ -1152,7 +1003,7 @@
-       dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
-       /* Empty loss interval history */
--      dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
-+      dccp_li_hist_purge(&hcrx->ccid3hcrx_li_hist);
- }
- static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
-@@ -1236,19 +1087,12 @@
-       if (ccid3_tx_hist == NULL)
-               goto out_free_rx;
--      ccid3_li_hist = dccp_li_hist_new("ccid3");
--      if (ccid3_li_hist == NULL)
--              goto out_free_tx;
+-/**
+- *    check_signature         -       find BIOS signatures
+- *    @io_addr: mmio address to check
+- *    @signature:  signature block
+- *    @length: length of signature
+- *
+- *    Perform a signature comparison with the mmio address io_addr. This
+- *    address should have been obtained by ioremap.
+- *    Returns 1 on a match.
+- */
 -
-       rc = ccid_register(&ccid3);
-       if (rc != 0)
--              goto out_free_loss_interval_history;
-+              goto out_free_tx;
- out:
-       return rc;
--out_free_loss_interval_history:
--      dccp_li_hist_delete(ccid3_li_hist);
--      ccid3_li_hist = NULL;
- out_free_tx:
-       dccp_tx_hist_delete(ccid3_tx_hist);
-       ccid3_tx_hist = NULL;
-@@ -1271,10 +1115,6 @@
-               dccp_rx_hist_delete(ccid3_rx_hist);
-               ccid3_rx_hist = NULL;
-       }
--      if (ccid3_li_hist != NULL) {
--              dccp_li_hist_delete(ccid3_li_hist);
--              ccid3_li_hist = NULL;
+-int check_signature(const volatile void __iomem *io_addr,
+-                      const unsigned char *signature, int length)
+-{
+-      while (length--) {
+-              if (readb(io_addr) != *signature)
+-                      return 0;
+-              io_addr++;
+-              signature++;
 -      }
+-      return 1;
+-}
+-EXPORT_SYMBOL(check_signature);
+diff -Nurb linux-2.6.22-590/lib/idr.c linux-2.6.22-570/lib/idr.c
+--- linux-2.6.22-590/lib/idr.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/lib/idr.c 2007-07-08 19:32:17.000000000 -0400
+@@ -70,26 +70,6 @@
+       spin_unlock_irqrestore(&idp->lock, flags);
  }
- module_exit(ccid3_module_exit);
-diff -Nurb linux-2.6.22-570/net/dccp/ccids/ccid3.h linux-2.6.22-590/net/dccp/ccids/ccid3.h
---- linux-2.6.22-570/net/dccp/ccids/ccid3.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/dccp/ccids/ccid3.h    2008-01-02 13:56:38.000000000 -0500
-@@ -36,6 +36,7 @@
- #ifndef _DCCP_CCID3_H_
- #define _DCCP_CCID3_H_
-+#include <linux/ktime.h>
- #include <linux/list.h>
- #include <linux/time.h>
- #include <linux/types.h>
-@@ -108,10 +109,10 @@
-       enum ccid3_hc_tx_states         ccid3hctx_state:8;
-       u8                              ccid3hctx_last_win_count;
-       u8                              ccid3hctx_idle;
--      struct timeval                  ccid3hctx_t_last_win_count;
-+      ktime_t                         ccid3hctx_t_last_win_count;
-       struct timer_list               ccid3hctx_no_feedback_timer;
-       struct timeval                  ccid3hctx_t_ld;
--      struct timeval                  ccid3hctx_t_nom;
-+      ktime_t                         ccid3hctx_t_nom;
-       u32                             ccid3hctx_delta;
-       struct list_head                ccid3hctx_hist;
-       struct ccid3_options_received   ccid3hctx_options_received;
-diff -Nurb linux-2.6.22-570/net/dccp/ccids/lib/loss_interval.c linux-2.6.22-590/net/dccp/ccids/lib/loss_interval.c
---- linux-2.6.22-570/net/dccp/ccids/lib/loss_interval.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/dccp/ccids/lib/loss_interval.c        2008-01-02 13:56:38.000000000 -0500
-@@ -1,8 +1,8 @@
- /*
-  *  net/dccp/ccids/lib/loss_interval.c
-  *
-- *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
-- *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
-+ *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
-+ *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
-  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
-  *
-  *  This program is free software; you can redistribute it and/or modify
-@@ -15,58 +15,38 @@
- #include <net/sock.h>
- #include "../../dccp.h"
- #include "loss_interval.h"
-+#include "packet_history.h"
-+#include "tfrc.h"
  
--struct dccp_li_hist *dccp_li_hist_new(const char *name)
+-static void idr_mark_full(struct idr_layer **pa, int id)
 -{
--      struct dccp_li_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
--      static const char dccp_li_hist_mask[] = "li_hist_%s";
--      char *slab_name;
--
--      if (hist == NULL)
--              goto out;
+-      struct idr_layer *p = pa[0];
+-      int l = 0;
 -
--      slab_name = kmalloc(strlen(name) + sizeof(dccp_li_hist_mask) - 1,
--                          GFP_ATOMIC);
--      if (slab_name == NULL)
--              goto out_free_hist;
-+#define DCCP_LI_HIST_IVAL_F_LENGTH  8
--      sprintf(slab_name, dccp_li_hist_mask, name);
--      hist->dccplih_slab = kmem_cache_create(slab_name,
--                                           sizeof(struct dccp_li_hist_entry),
--                                             0, SLAB_HWCACHE_ALIGN,
--                                             NULL, NULL);
--      if (hist->dccplih_slab == NULL)
--              goto out_free_slab_name;
--out:
--      return hist;
--out_free_slab_name:
--      kfree(slab_name);
--out_free_hist:
--      kfree(hist);
--      hist = NULL;
--      goto out;
+-      __set_bit(id & IDR_MASK, &p->bitmap);
+-      /*
+-       * If this layer is full mark the bit in the layer above to
+-       * show that this part of the radix tree is full.  This may
+-       * complete the layer above and require walking up the radix
+-       * tree.
+-       */
+-      while (p->bitmap == IDR_FULL) {
+-              if (!(p = pa[++l]))
+-                      break;
+-              id = id >> IDR_BITS;
+-              __set_bit((id & IDR_MASK), &p->bitmap);
+-      }
 -}
-+struct dccp_li_hist_entry {
-+      struct list_head dccplih_node;
-+      u64              dccplih_seqno:48,
-+                       dccplih_win_count:4;
-+      u32              dccplih_interval;
-+};
--EXPORT_SYMBOL_GPL(dccp_li_hist_new);
-+struct kmem_cache *dccp_li_cachep __read_mostly;
--void dccp_li_hist_delete(struct dccp_li_hist *hist)
-+static inline struct dccp_li_hist_entry *dccp_li_hist_entry_new(const gfp_t prio)
- {
--      const char* name = kmem_cache_name(hist->dccplih_slab);
 -
--      kmem_cache_destroy(hist->dccplih_slab);
--      kfree(name);
--      kfree(hist);
-+      return kmem_cache_alloc(dccp_li_cachep, prio);
+ /**
+  * idr_pre_get - reserver resources for idr allocation
+  * @idp:      idr handle
+@@ -115,10 +95,11 @@
  }
+ EXPORT_SYMBOL(idr_pre_get);
  
--EXPORT_SYMBOL_GPL(dccp_li_hist_delete);
-+static inline void dccp_li_hist_entry_delete(struct dccp_li_hist_entry *entry)
-+{
-+      if (entry != NULL)
-+              kmem_cache_free(dccp_li_cachep, entry);
-+}
--void dccp_li_hist_purge(struct dccp_li_hist *hist, struct list_head *list)
-+void dccp_li_hist_purge(struct list_head *list)
+-static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
++static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
  {
-       struct dccp_li_hist_entry *entry, *next;
+       int n, m, sh;
+       struct idr_layer *p, *new;
++      struct idr_layer *pa[MAX_LEVEL];
+       int l, id;
+       long bm;
  
-       list_for_each_entry_safe(entry, next, list, dccplih_node) {
-               list_del_init(&entry->dccplih_node);
--              kmem_cache_free(hist->dccplih_slab, entry);
-+              kmem_cache_free(dccp_li_cachep, entry);
+@@ -163,13 +144,30 @@
+               pa[l--] = p;
+               p = p->ary[m];
        }
- }
-@@ -118,16 +98,16 @@
- EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
--int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
--   struct list_head *list, const u64 seq_loss, const u8 win_loss)
-+static int dccp_li_hist_interval_new(struct list_head *list,
-+                                   const u64 seq_loss, const u8 win_loss)
- {
-       struct dccp_li_hist_entry *entry;
-       int i;
-       for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) {
--              entry = dccp_li_hist_entry_new(hist, GFP_ATOMIC);
-+              entry = dccp_li_hist_entry_new(GFP_ATOMIC);
-               if (entry == NULL) {
--                      dccp_li_hist_purge(hist, list);
-+                      dccp_li_hist_purge(list);
-                       DCCP_BUG("loss interval list entry is NULL");
-                       return 0;
-               }
-@@ -140,4 +120,176 @@
-       return 1;
- }
--EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new);
-+/* calculate first loss interval
-+ *
-+ * returns estimated loss interval in usecs */
-+static u32 dccp_li_calc_first_li(struct sock *sk,
-+                               struct list_head *hist_list,
-+                               struct timeval *last_feedback,
-+                               u16 s, u32 bytes_recv,
-+                               u32 previous_x_recv)
-+{
-+      struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
-+      u32 x_recv, p;
-+      suseconds_t rtt, delta;
-+      struct timeval tstamp = { 0, 0 };
-+      int interval = 0;
-+      int win_count = 0;
-+      int step = 0;
-+      u64 fval;
-+
-+      list_for_each_entry_safe(entry, next, hist_list, dccphrx_node) {
-+              if (dccp_rx_hist_entry_data_packet(entry)) {
-+                      tail = entry;
-+
-+                      switch (step) {
-+                      case 0:
-+                              tstamp    = entry->dccphrx_tstamp;
-+                              win_count = entry->dccphrx_ccval;
-+                              step = 1;
-+                              break;
-+                      case 1:
-+                              interval = win_count - entry->dccphrx_ccval;
-+                              if (interval < 0)
-+                                      interval += TFRC_WIN_COUNT_LIMIT;
-+                              if (interval > 4)
-+                                      goto found;
-+                              break;
-+                      }
-+              }
-+      }
-+
-+      if (unlikely(step == 0)) {
-+              DCCP_WARN("%s(%p), packet history has no data packets!\n",
-+                        dccp_role(sk), sk);
-+              return ~0;
-+      }
-+
-+      if (unlikely(interval == 0)) {
-+              DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
-+                        "Defaulting to 1\n", dccp_role(sk), sk);
-+              interval = 1;
-+      }
-+found:
-+      if (!tail) {
-+              DCCP_CRIT("tail is null\n");
-+              return ~0;
-+      }
-+
-+      delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
-+      DCCP_BUG_ON(delta < 0);
-+
-+      rtt = delta * 4 / interval;
-+      dccp_pr_debug("%s(%p), approximated RTT to %dus\n",
-+                    dccp_role(sk), sk, (int)rtt);
-+
+-
+-      pa[l] = p;
+-      return id;
 +      /*
-+       * Determine the length of the first loss interval via inverse lookup.
-+       * Assume that X_recv can be computed by the throughput equation
-+       *                  s
-+       *      X_recv = --------
-+       *               R * fval
-+       * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
++       * We have reached the leaf node, plant the
++       * users pointer and return the raw id.
 +       */
-+      if (rtt == 0) {                 /* would result in divide-by-zero */
-+              DCCP_WARN("RTT==0\n");
-+              return ~0;
-+      }
-+
-+      dccp_timestamp(sk, &tstamp);
-+      delta = timeval_delta(&tstamp, last_feedback);
-+      DCCP_BUG_ON(delta <= 0);
-+
-+      x_recv = scaled_div32(bytes_recv, delta);
-+      if (x_recv == 0) {              /* would also trigger divide-by-zero */
-+              DCCP_WARN("X_recv==0\n");
-+              if (previous_x_recv == 0) {
-+                      DCCP_BUG("stored value of X_recv is zero");
-+                      return ~0;
-+              }
-+              x_recv = previous_x_recv;
-+      }
-+
-+      fval = scaled_div(s, rtt);
-+      fval = scaled_div32(fval, x_recv);
-+      p = tfrc_calc_x_reverse_lookup(fval);
-+
-+      dccp_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
-+                    "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
-+
-+      if (p == 0)
-+              return ~0;
-+      else
-+              return 1000000 / p;
-+}
-+
-+void dccp_li_update_li(struct sock *sk,
-+                     struct list_head *li_hist_list,
-+                     struct list_head *hist_list,
-+                     struct timeval *last_feedback, u16 s, u32 bytes_recv,
-+                       u32 previous_x_recv, u64 seq_loss, u8 win_loss)
-+{
-+      struct dccp_li_hist_entry *head;
-+      u64 seq_temp;
-+
-+      if (list_empty(li_hist_list)) {
-+              if (!dccp_li_hist_interval_new(li_hist_list, seq_loss,
-+                                             win_loss))
-+                      return;
-+
-+              head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
-+                                dccplih_node);
-+              head->dccplih_interval = dccp_li_calc_first_li(sk, hist_list,
-+                                                             last_feedback,
-+                                                             s, bytes_recv,
-+                                                             previous_x_recv);
-+      } else {
-+              struct dccp_li_hist_entry *entry;
-+              struct list_head *tail;
-+
-+              head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
-+                                dccplih_node);
-+              /* FIXME win count check removed as was wrong */
-+              /* should make this check with receive history */
-+              /* and compare there as per section 10.2 of RFC4342 */
-+
-+              /* new loss event detected */
-+              /* calculate last interval length */
-+              seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
-+              entry = dccp_li_hist_entry_new(GFP_ATOMIC);
-+
-+              if (entry == NULL) {
-+                      DCCP_BUG("out of memory - can not allocate entry");
-+                      return;
-+              }
-+
-+              list_add(&entry->dccplih_node, li_hist_list);
-+
-+              tail = li_hist_list->prev;
-+              list_del(tail);
-+              kmem_cache_free(dccp_li_cachep, tail);
-+
-+              /* Create the newest interval */
-+              entry->dccplih_seqno = seq_loss;
-+              entry->dccplih_interval = seq_temp;
-+              entry->dccplih_win_count = win_loss;
++      p->ary[m] = (struct idr_layer *)ptr;
++      __set_bit(m, &p->bitmap);
++      p->count++;
++      /*
++       * If this layer is full mark the bit in the layer above
++       * to show that this part of the radix tree is full.
++       * This may complete the layer above and require walking
++       * up the radix tree.
++       */
++      n = id;
++      while (p->bitmap == IDR_FULL) {
++              if (!(p = pa[++l]))
++                      break;
++              n = n >> IDR_BITS;
++              __set_bit((n & IDR_MASK), &p->bitmap);
 +      }
-+}
-+
-+EXPORT_SYMBOL_GPL(dccp_li_update_li);
-+
-+static __init int dccp_li_init(void)
-+{
-+      dccp_li_cachep = kmem_cache_create("dccp_li_hist",
-+                                         sizeof(struct dccp_li_hist_entry),
-+                                         0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-+      return dccp_li_cachep == NULL ? -ENOBUFS : 0;
-+}
-+
-+static __exit void dccp_li_exit(void)
-+{
-+      kmem_cache_destroy(dccp_li_cachep);
-+}
-+
-+module_init(dccp_li_init);
-+module_exit(dccp_li_exit);
-diff -Nurb linux-2.6.22-570/net/dccp/ccids/lib/loss_interval.h linux-2.6.22-590/net/dccp/ccids/lib/loss_interval.h
---- linux-2.6.22-570/net/dccp/ccids/lib/loss_interval.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/dccp/ccids/lib/loss_interval.h        2008-01-02 13:56:38.000000000 -0500
-@@ -3,8 +3,8 @@
- /*
-  *  net/dccp/ccids/lib/loss_interval.h
-  *
-- *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
-- *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
-+ *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
-+ *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
-  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
-  *
-  *  This program is free software; you can redistribute it and/or modify it
-@@ -14,44 +14,16 @@
-  */
++      return(id);
+ }
  
- #include <linux/list.h>
--#include <linux/slab.h>
- #include <linux/time.h>
+-static int idr_get_empty_slot(struct idr *idp, int starting_id,
+-                            struct idr_layer **pa)
++static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
+ {
+       struct idr_layer *p, *new;
+       int layers, v, id;
+@@ -215,31 +213,12 @@
+       }
+       idp->top = p;
+       idp->layers = layers;
+-      v = sub_alloc(idp, &id, pa);
++      v = sub_alloc(idp, ptr, &id);
+       if (v == -2)
+               goto build_up;
+       return(v);
+ }
  
--#define DCCP_LI_HIST_IVAL_F_LENGTH  8
+-static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
+-{
+-      struct idr_layer *pa[MAX_LEVEL];
+-      int id;
 -
--struct dccp_li_hist {
--      struct kmem_cache *dccplih_slab;
--};
+-      id = idr_get_empty_slot(idp, starting_id, pa);
+-      if (id >= 0) {
+-              /*
+-               * Successfully found an empty slot.  Install the user
+-               * pointer and mark the slot full.
+-               */
+-              pa[0]->ary[id & IDR_MASK] = (struct idr_layer *)ptr;
+-              pa[0]->count++;
+-              idr_mark_full(pa, id);
+-      }
 -
--extern struct dccp_li_hist *dccp_li_hist_new(const char *name);
--extern void dccp_li_hist_delete(struct dccp_li_hist *hist);
+-      return id;
+-}
 -
--struct dccp_li_hist_entry {
--      struct list_head dccplih_node;
--      u64              dccplih_seqno:48,
--                       dccplih_win_count:4;
--      u32              dccplih_interval;
--};
+ /**
+  * idr_get_new_above - allocate new idr entry above or equal to a start id
+  * @idp: idr handle
+@@ -494,248 +473,3 @@
+       spin_lock_init(&idp->lock);
+ }
+ EXPORT_SYMBOL(idr_init);
+-
+-
+-/*
+- * IDA - IDR based ID allocator
+- *
+- * this is id allocator without id -> pointer translation.  Memory
+- * usage is much lower than full blown idr because each id only
+- * occupies a bit.  ida uses a custom leaf node which contains
+- * IDA_BITMAP_BITS slots.
+- *
+- * 2007-04-25  written by Tejun Heo <htejun@gmail.com>
+- */
 -
--static inline struct dccp_li_hist_entry *
--              dccp_li_hist_entry_new(struct dccp_li_hist *hist,
--                                     const gfp_t prio)
+-static void free_bitmap(struct ida *ida, struct ida_bitmap *bitmap)
 -{
--      return kmem_cache_alloc(hist->dccplih_slab, prio);
+-      unsigned long flags;
+-
+-      if (!ida->free_bitmap) {
+-              spin_lock_irqsave(&ida->idr.lock, flags);
+-              if (!ida->free_bitmap) {
+-                      ida->free_bitmap = bitmap;
+-                      bitmap = NULL;
+-              }
+-              spin_unlock_irqrestore(&ida->idr.lock, flags);
+-      }
+-
+-      kfree(bitmap);
 -}
 -
--static inline void dccp_li_hist_entry_delete(struct dccp_li_hist *hist,
--                                           struct dccp_li_hist_entry *entry)
+-/**
+- * ida_pre_get - reserve resources for ida allocation
+- * @ida:      ida handle
+- * @gfp_mask: memory allocation flag
+- *
+- * This function should be called prior to locking and calling the
+- * following function.  It preallocates enough memory to satisfy the
+- * worst possible allocation.
+- *
+- * If the system is REALLY out of memory this function returns 0,
+- * otherwise 1.
+- */
+-int ida_pre_get(struct ida *ida, gfp_t gfp_mask)
 -{
--      if (entry != NULL)
--              kmem_cache_free(hist->dccplih_slab, entry);
+-      /* allocate idr_layers */
+-      if (!idr_pre_get(&ida->idr, gfp_mask))
+-              return 0;
+-
+-      /* allocate free_bitmap */
+-      if (!ida->free_bitmap) {
+-              struct ida_bitmap *bitmap;
+-
+-              bitmap = kmalloc(sizeof(struct ida_bitmap), gfp_mask);
+-              if (!bitmap)
+-                      return 0;
+-
+-              free_bitmap(ida, bitmap);
+-      }
+-
+-      return 1;
 -}
+-EXPORT_SYMBOL(ida_pre_get);
 -
--extern void dccp_li_hist_purge(struct dccp_li_hist *hist,
--                             struct list_head *list);
-+extern void dccp_li_hist_purge(struct list_head *list);
- extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
--extern int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
--   struct list_head *list, const u64 seq_loss, const u8 win_loss);
-+extern void dccp_li_update_li(struct sock *sk,
-+                            struct list_head *li_hist_list,
-+                            struct list_head *hist_list,
-+                            struct timeval *last_feedback, u16 s,
-+                            u32 bytes_recv, u32 previous_x_recv,
-+                            u64 seq_loss, u8 win_loss);
- #endif /* _DCCP_LI_HIST_ */
-diff -Nurb linux-2.6.22-570/net/dccp/dccp.h linux-2.6.22-590/net/dccp/dccp.h
---- linux-2.6.22-570/net/dccp/dccp.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/dccp/dccp.h   2008-01-02 13:56:38.000000000 -0500
-@@ -184,7 +184,7 @@
- /*
-  *    Checksumming routines
-  */
--static inline int dccp_csum_coverage(const struct sk_buff *skb)
-+static inline unsigned int dccp_csum_coverage(const struct sk_buff *skb)
- {
-       const struct dccp_hdr* dh = dccp_hdr(skb);
-@@ -195,7 +195,7 @@
- static inline void dccp_csum_outgoing(struct sk_buff *skb)
- {
--      int cov = dccp_csum_coverage(skb);
-+      unsigned int cov = dccp_csum_coverage(skb);
-       if (cov >= skb->len)
-               dccp_hdr(skb)->dccph_cscov = 0;
-diff -Nurb linux-2.6.22-570/net/dccp/ipv4.c linux-2.6.22-590/net/dccp/ipv4.c
---- linux-2.6.22-570/net/dccp/ipv4.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/dccp/ipv4.c   2008-01-02 13:56:38.000000000 -0500
-@@ -202,6 +202,7 @@
-  */
- static void dccp_v4_err(struct sk_buff *skb, u32 info)
- {
-+      struct net *net = skb->dev->nd_net;
-       const struct iphdr *iph = (struct iphdr *)skb->data;
-       const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data +
-                                                       (iph->ihl << 2));
-@@ -213,13 +214,16 @@
-       __u64 seq;
-       int err;
-+      if (skb->dev->nd_net != &init_net)
-+              return;
-+
-       if (skb->len < (iph->ihl << 2) + 8) {
-               ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
-               return;
-       }
-       sk = inet_lookup(&dccp_hashinfo, iph->daddr, dh->dccph_dport,
--                       iph->saddr, dh->dccph_sport, inet_iif(skb));
-+                       iph->saddr, dh->dccph_sport, inet_iif(skb), net);
-       if (sk == NULL) {
-               ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
-               return;
-@@ -441,7 +445,7 @@
-       nsk = inet_lookup_established(&dccp_hashinfo,
-                                     iph->saddr, dh->dccph_sport,
-                                     iph->daddr, dh->dccph_dport,
--                                    inet_iif(skb));
-+                                    inet_iif(skb), sk->sk_net);
-       if (nsk != NULL) {
-               if (nsk->sk_state != DCCP_TIME_WAIT) {
-                       bh_lock_sock(nsk);
-@@ -458,7 +462,8 @@
-                                          struct sk_buff *skb)
- {
-       struct rtable *rt;
--      struct flowi fl = { .oif = ((struct rtable *)skb->dst)->rt_iif,
-+      struct flowi fl = { .fl_net = &init_net,
-+                          .oif = ((struct rtable *)skb->dst)->rt_iif,
-                           .nl_u = { .ip4_u =
-                                     { .daddr = ip_hdr(skb)->saddr,
-                                       .saddr = ip_hdr(skb)->daddr,
-@@ -809,11 +814,16 @@
- /* this is called when real data arrives */
- static int dccp_v4_rcv(struct sk_buff *skb)
- {
-+      struct net *net = skb->dev->nd_net;
-       const struct dccp_hdr *dh;
-       const struct iphdr *iph;
-       struct sock *sk;
-       int min_cov;
-+      if (skb->dev->nd_net != &init_net) {
-+              kfree_skb(skb);
-+              return 0;
-+      }
-       /* Step 1: Check header basics */
-       if (dccp_invalid_packet(skb))
-@@ -852,7 +862,7 @@
-        *      Look up flow ID in table and get corresponding socket */
-       sk = __inet_lookup(&dccp_hashinfo,
-                          iph->saddr, dh->dccph_sport,
--                         iph->daddr, dh->dccph_dport, inet_iif(skb));
-+                         iph->daddr, dh->dccph_dport, inet_iif(skb), net);
-       /*
-        * Step 2:
-        *      If no socket ...
-diff -Nurb linux-2.6.22-570/net/dccp/ipv6.c linux-2.6.22-590/net/dccp/ipv6.c
---- linux-2.6.22-570/net/dccp/ipv6.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/dccp/ipv6.c   2008-01-02 13:56:38.000000000 -0500
-@@ -94,6 +94,7 @@
- static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-                       int type, int code, int offset, __be32 info)
- {
-+      struct net *net = skb->dev->nd_net;
-       struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data;
-       const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
-       struct ipv6_pinfo *np;
-@@ -102,7 +103,7 @@
-       __u64 seq;
-       sk = inet6_lookup(&dccp_hashinfo, &hdr->daddr, dh->dccph_dport,
--                        &hdr->saddr, dh->dccph_sport, inet6_iif(skb));
-+                        &hdr->saddr, dh->dccph_sport, inet6_iif(skb), net);
-       if (sk == NULL) {
-               ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
-@@ -142,6 +143,7 @@
-                          for now.
-                        */
-                       memset(&fl, 0, sizeof(fl));
-+                      fl.fl_net = &init_net;
-                       fl.proto = IPPROTO_DCCP;
-                       ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
-                       ipv6_addr_copy(&fl.fl6_src, &np->saddr);
-@@ -242,6 +244,7 @@
-       int err = -1;
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net,
-       fl.proto = IPPROTO_DCCP;
-       ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
-       ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
-@@ -358,6 +361,7 @@
-                                                     &rxip6h->daddr);
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       ipv6_addr_copy(&fl.fl6_dst, &rxip6h->saddr);
-       ipv6_addr_copy(&fl.fl6_src, &rxip6h->daddr);
-@@ -407,7 +411,7 @@
-       nsk = __inet6_lookup_established(&dccp_hashinfo,
-                                        &iph->saddr, dh->dccph_sport,
-                                        &iph->daddr, ntohs(dh->dccph_dport),
--                                       inet6_iif(skb));
-+                                       inet6_iif(skb), sk->sk_net);
-       if (nsk != NULL) {
-               if (nsk->sk_state != DCCP_TIME_WAIT) {
-                       bh_lock_sock(nsk);
-@@ -584,6 +588,7 @@
-               struct flowi fl;
-               memset(&fl, 0, sizeof(fl));
-+              fl.fl_net = &init_net;
-               fl.proto = IPPROTO_DCCP;
-               ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
-               if (opt != NULL && opt->srcrt != NULL) {
-@@ -819,6 +824,7 @@
- {
-       const struct dccp_hdr *dh;
-       struct sk_buff *skb = *pskb;
-+      struct net *net = skb->dev->nd_net;
-       struct sock *sk;
-       int min_cov;
-@@ -849,7 +855,7 @@
-       sk = __inet6_lookup(&dccp_hashinfo, &ipv6_hdr(skb)->saddr,
-                           dh->dccph_sport,
-                           &ipv6_hdr(skb)->daddr, ntohs(dh->dccph_dport),
--                          inet6_iif(skb));
-+                          inet6_iif(skb), net);
-       /*
-        * Step 2:
-        *      If no socket ...
-@@ -937,6 +943,7 @@
-               return -EAFNOSUPPORT;
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       if (np->sndflow) {
-               fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
-diff -Nurb linux-2.6.22-570/net/dccp/probe.c linux-2.6.22-590/net/dccp/probe.c
---- linux-2.6.22-570/net/dccp/probe.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/dccp/probe.c  2008-01-02 13:56:38.000000000 -0500
-@@ -30,6 +30,7 @@
- #include <linux/module.h>
- #include <linux/kfifo.h>
- #include <linux/vmalloc.h>
-+#include <net/net_namespace.h>
- #include "dccp.h"
- #include "ccid.h"
-@@ -168,7 +169,7 @@
-       if (IS_ERR(dccpw.fifo))
-               return PTR_ERR(dccpw.fifo);
--      if (!proc_net_fops_create(procname, S_IRUSR, &dccpprobe_fops))
-+      if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &dccpprobe_fops))
-               goto err0;
-       ret = register_jprobe(&dccp_send_probe);
-@@ -178,7 +179,7 @@
-       pr_info("DCCP watch registered (port=%d)\n", port);
-       return 0;
- err1:
--      proc_net_remove(procname);
-+      proc_net_remove(&init_net, procname);
- err0:
-       kfifo_free(dccpw.fifo);
-       return ret;
-@@ -188,7 +189,7 @@
- static __exit void dccpprobe_exit(void)
- {
-       kfifo_free(dccpw.fifo);
--      proc_net_remove(procname);
-+      proc_net_remove(&init_net, procname);
-       unregister_jprobe(&dccp_send_probe);
+-/**
+- * ida_get_new_above - allocate new ID above or equal to a start id
+- * @ida:      ida handle
+- * @staring_id:       id to start search at
+- * @p_id:     pointer to the allocated handle
+- *
+- * Allocate new ID above or equal to @ida.  It should be called with
+- * any required locks.
+- *
+- * If memory is required, it will return -EAGAIN, you should unlock
+- * and go back to the ida_pre_get() call.  If the ida is full, it will
+- * return -ENOSPC.
+- *
+- * @p_id returns a value in the range 0 ... 0x7fffffff.
+- */
+-int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
+-{
+-      struct idr_layer *pa[MAX_LEVEL];
+-      struct ida_bitmap *bitmap;
+-      unsigned long flags;
+-      int idr_id = starting_id / IDA_BITMAP_BITS;
+-      int offset = starting_id % IDA_BITMAP_BITS;
+-      int t, id;
+-
+- restart:
+-      /* get vacant slot */
+-      t = idr_get_empty_slot(&ida->idr, idr_id, pa);
+-      if (t < 0) {
+-              if (t == -1)
+-                      return -EAGAIN;
+-              else /* will be -3 */
+-                      return -ENOSPC;
+-      }
+-
+-      if (t * IDA_BITMAP_BITS >= MAX_ID_BIT)
+-              return -ENOSPC;
+-
+-      if (t != idr_id)
+-              offset = 0;
+-      idr_id = t;
+-
+-      /* if bitmap isn't there, create a new one */
+-      bitmap = (void *)pa[0]->ary[idr_id & IDR_MASK];
+-      if (!bitmap) {
+-              spin_lock_irqsave(&ida->idr.lock, flags);
+-              bitmap = ida->free_bitmap;
+-              ida->free_bitmap = NULL;
+-              spin_unlock_irqrestore(&ida->idr.lock, flags);
+-
+-              if (!bitmap)
+-                      return -EAGAIN;
+-
+-              memset(bitmap, 0, sizeof(struct ida_bitmap));
+-              pa[0]->ary[idr_id & IDR_MASK] = (void *)bitmap;
+-              pa[0]->count++;
+-      }
+-
+-      /* lookup for empty slot */
+-      t = find_next_zero_bit(bitmap->bitmap, IDA_BITMAP_BITS, offset);
+-      if (t == IDA_BITMAP_BITS) {
+-              /* no empty slot after offset, continue to the next chunk */
+-              idr_id++;
+-              offset = 0;
+-              goto restart;
+-      }
+-
+-      id = idr_id * IDA_BITMAP_BITS + t;
+-      if (id >= MAX_ID_BIT)
+-              return -ENOSPC;
+-
+-      __set_bit(t, bitmap->bitmap);
+-      if (++bitmap->nr_busy == IDA_BITMAP_BITS)
+-              idr_mark_full(pa, idr_id);
+-
+-      *p_id = id;
+-
+-      /* Each leaf node can handle nearly a thousand slots and the
+-       * whole idea of ida is to have small memory foot print.
+-       * Throw away extra resources one by one after each successful
+-       * allocation.
+-       */
+-      if (ida->idr.id_free_cnt || ida->free_bitmap) {
+-              struct idr_layer *p = alloc_layer(&ida->idr);
+-              if (p)
+-                      kmem_cache_free(idr_layer_cache, p);
+-      }
+-
+-      return 0;
+-}
+-EXPORT_SYMBOL(ida_get_new_above);
+-
+-/**
+- * ida_get_new - allocate new ID
+- * @ida:      idr handle
+- * @p_id:     pointer to the allocated handle
+- *
+- * Allocate new ID.  It should be called with any required locks.
+- *
+- * If memory is required, it will return -EAGAIN, you should unlock
+- * and go back to the idr_pre_get() call.  If the idr is full, it will
+- * return -ENOSPC.
+- *
+- * @id returns a value in the range 0 ... 0x7fffffff.
+- */
+-int ida_get_new(struct ida *ida, int *p_id)
+-{
+-      return ida_get_new_above(ida, 0, p_id);
+-}
+-EXPORT_SYMBOL(ida_get_new);
+-
+-/**
+- * ida_remove - remove the given ID
+- * @ida:      ida handle
+- * @id:               ID to free
+- */
+-void ida_remove(struct ida *ida, int id)
+-{
+-      struct idr_layer *p = ida->idr.top;
+-      int shift = (ida->idr.layers - 1) * IDR_BITS;
+-      int idr_id = id / IDA_BITMAP_BITS;
+-      int offset = id % IDA_BITMAP_BITS;
+-      int n;
+-      struct ida_bitmap *bitmap;
+-
+-      /* clear full bits while looking up the leaf idr_layer */
+-      while ((shift > 0) && p) {
+-              n = (idr_id >> shift) & IDR_MASK;
+-              __clear_bit(n, &p->bitmap);
+-              p = p->ary[n];
+-              shift -= IDR_BITS;
+-      }
+-
+-      if (p == NULL)
+-              goto err;
+-
+-      n = idr_id & IDR_MASK;
+-      __clear_bit(n, &p->bitmap);
+-
+-      bitmap = (void *)p->ary[n];
+-      if (!test_bit(offset, bitmap->bitmap))
+-              goto err;
+-
+-      /* update bitmap and remove it if empty */
+-      __clear_bit(offset, bitmap->bitmap);
+-      if (--bitmap->nr_busy == 0) {
+-              __set_bit(n, &p->bitmap);       /* to please idr_remove() */
+-              idr_remove(&ida->idr, idr_id);
+-              free_bitmap(ida, bitmap);
+-      }
+-
+-      return;
+-
+- err:
+-      printk(KERN_WARNING
+-             "ida_remove called for id=%d which is not allocated.\n", id);
+-}
+-EXPORT_SYMBOL(ida_remove);
+-
+-/**
+- * ida_destroy - release all cached layers within an ida tree
+- * ida:               ida handle
+- */
+-void ida_destroy(struct ida *ida)
+-{
+-      idr_destroy(&ida->idr);
+-      kfree(ida->free_bitmap);
+-}
+-EXPORT_SYMBOL(ida_destroy);
+-
+-/**
+- * ida_init - initialize ida handle
+- * @ida:      ida handle
+- *
+- * This function is use to set up the handle (@ida) that you will pass
+- * to the rest of the functions.
+- */
+-void ida_init(struct ida *ida)
+-{
+-      memset(ida, 0, sizeof(struct ida));
+-      idr_init(&ida->idr);
+-
+-}
+-EXPORT_SYMBOL(ida_init);
+diff -Nurb linux-2.6.22-590/lib/kobject.c linux-2.6.22-570/lib/kobject.c
+--- linux-2.6.22-590/lib/kobject.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/lib/kobject.c     2007-07-08 19:32:17.000000000 -0400
+@@ -44,11 +44,11 @@
+       return error;
  }
-diff -Nurb linux-2.6.22-570/net/decnet/af_decnet.c linux-2.6.22-590/net/decnet/af_decnet.c
---- linux-2.6.22-570/net/decnet/af_decnet.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/decnet/af_decnet.c    2008-01-02 13:56:38.000000000 -0500
-@@ -131,6 +131,7 @@
- #include <net/neighbour.h>
- #include <net/dst.h>
- #include <net/fib_rules.h>
-+#include <net/net_namespace.h>
- #include <net/dn.h>
- #include <net/dn_nsp.h>
- #include <net/dn_dev.h>
-@@ -470,10 +471,10 @@
-       .obj_size               = sizeof(struct dn_sock),
- };
  
--static struct sock *dn_alloc_sock(struct socket *sock, gfp_t gfp)
-+static struct sock *dn_alloc_sock(struct net *net, struct socket *sock, gfp_t gfp)
+-static int create_dir(struct kobject * kobj)
++static int create_dir(struct kobject * kobj, struct dentry *shadow_parent)
  {
-       struct dn_scp *scp;
--      struct sock *sk = sk_alloc(PF_DECnet, gfp, &dn_proto, 1);
-+      struct sock *sk = sk_alloc(net, PF_DECnet, gfp, &dn_proto, 1);
-       if  (!sk)
-               goto out;
-@@ -674,10 +675,13 @@
+       int error = 0;
+       if (kobject_name(kobj)) {
+-              error = sysfs_create_dir(kobj);
++              error = sysfs_create_dir(kobj, shadow_parent);
+               if (!error) {
+                       if ((error = populate_dir(kobj)))
+                               sysfs_remove_dir(kobj);
+@@ -157,11 +157,12 @@
+ }
  
+ /**
+- *    kobject_add - add an object to the hierarchy.
++ *    kobject_shadow_add - add an object to the hierarchy.
+  *    @kobj:  object.
++ *    @shadow_parent: sysfs directory to add to.
+  */
  
--static int dn_create(struct socket *sock, int protocol)
-+static int dn_create(struct net *net, struct socket *sock, int protocol)
+-int kobject_add(struct kobject * kobj)
++int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
  {
-       struct sock *sk;
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
-+
-       switch(sock->type) {
-               case SOCK_SEQPACKET:
-                       if (protocol != DNPROTO_NSP)
-@@ -690,7 +694,7 @@
+       int error = 0;
+       struct kobject * parent;
+@@ -193,7 +194,7 @@
+               kobj->parent = parent;
        }
  
+-      error = create_dir(kobj);
++      error = create_dir(kobj, shadow_parent);
+       if (error) {
+               /* unlink does the kobject_put() for us */
+               unlink(kobj);
+@@ -215,6 +216,16 @@
+ }
  
--      if ((sk = dn_alloc_sock(sock, GFP_KERNEL)) == NULL)
-+      if ((sk = dn_alloc_sock(net, sock, GFP_KERNEL)) == NULL)
-               return -ENOBUFS;
-       sk->sk_protocol = protocol;
-@@ -747,7 +751,7 @@
-               if (dn_ntohs(saddr->sdn_nodeaddrl)) {
-                       read_lock(&dev_base_lock);
-                       ldev = NULL;
--                      for_each_netdev(dev) {
-+                      for_each_netdev(&init_net, dev) {
-                               if (!dev->dn_ptr)
-                                       continue;
-                               if (dn_dev_islocal(dev, dn_saddr2dn(saddr))) {
-@@ -943,6 +947,7 @@
-       err = -EHOSTUNREACH;
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       fl.oif = sk->sk_bound_dev_if;
-       fl.fld_dst = dn_saddr2dn(&scp->peer);
-       fl.fld_src = dn_saddr2dn(&scp->addr);
-@@ -1090,7 +1095,7 @@
-       cb = DN_SKB_CB(skb);
-       sk->sk_ack_backlog--;
--      newsk = dn_alloc_sock(newsock, sk->sk_allocation);
-+      newsk = dn_alloc_sock(sk->sk_net, newsock, sk->sk_allocation);
-       if (newsk == NULL) {
-               release_sock(sk);
-               kfree_skb(skb);
-@@ -2085,6 +2090,9 @@
- {
-       struct net_device *dev = (struct net_device *)ptr;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
+ /**
++ *    kobject_add - add an object to the hierarchy.
++ *    @kobj:  object.
++ */
++int kobject_add(struct kobject * kobj)
++{
++      return kobject_shadow_add(kobj, NULL);
++}
 +
-       switch(event) {
-               case NETDEV_UP:
-                       dn_dev_up(dev);
-@@ -2399,7 +2407,7 @@
-       dev_add_pack(&dn_dix_packet_type);
-       register_netdevice_notifier(&dn_dev_notifier);
--      proc_net_fops_create("decnet", S_IRUGO, &dn_socket_seq_fops);
-+      proc_net_fops_create(&init_net, "decnet", S_IRUGO, &dn_socket_seq_fops);
-       dn_register_sysctl();
- out:
-       return rc;
-@@ -2428,7 +2436,7 @@
-       dn_neigh_cleanup();
-       dn_fib_cleanup();
++
++/**
+  *    kobject_register - initialize and add an object.
+  *    @kobj:  object in question.
+  */
+@@ -327,7 +338,7 @@
+       /* Note : if we want to send the new name alone, not the full path,
+        * we could probably use kobject_name(kobj); */
  
--      proc_net_remove("decnet");
-+      proc_net_remove(&init_net, "decnet");
+-      error = sysfs_rename_dir(kobj, new_name);
++      error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name);
  
-       proto_unregister(&dn_proto);
+       /* This function is mostly/only used for network interface.
+        * Some hotplug package track interfaces by their name and
+@@ -344,6 +355,27 @@
  }
-diff -Nurb linux-2.6.22-570/net/decnet/dn_dev.c linux-2.6.22-590/net/decnet/dn_dev.c
---- linux-2.6.22-570/net/decnet/dn_dev.c       2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/decnet/dn_dev.c       2008-01-02 13:56:38.000000000 -0500
-@@ -47,6 +47,7 @@
- #include <net/flow.h>
- #include <net/fib_rules.h>
- #include <net/netlink.h>
-+#include <net/net_namespace.h>
- #include <net/dn.h>
- #include <net/dn_dev.h>
- #include <net/dn_route.h>
-@@ -513,7 +514,7 @@
-       ifr->ifr_name[IFNAMSIZ-1] = 0;
- #ifdef CONFIG_KMOD
--      dev_load(ifr->ifr_name);
-+      dev_load(&init_net, ifr->ifr_name);
- #endif
-       switch(cmd) {
-@@ -531,7 +532,7 @@
-       rtnl_lock();
--      if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL) {
-+      if ((dev = __dev_get_by_name(&init_net, ifr->ifr_name)) == NULL) {
-               ret = -ENODEV;
-               goto done;
-       }
-@@ -629,7 +630,7 @@
- {
-       struct net_device *dev;
-       struct dn_dev *dn_dev = NULL;
--      dev = dev_get_by_index(ifindex);
-+      dev = dev_get_by_index(&init_net, ifindex);
-       if (dev) {
-               dn_dev = dev->dn_ptr;
-               dev_put(dev);
-@@ -647,12 +648,16 @@
- static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct nlattr *tb[IFA_MAX+1];
-       struct dn_dev *dn_db;
-       struct ifaddrmsg *ifm;
-       struct dn_ifaddr *ifa, **ifap;
-       int err = -EADDRNOTAVAIL;
  
-+      if (net != &init_net)
-+              goto errout;
+ /**
++ *    kobject_rename - change the name of an object
++ *    @kobj:  object in question.
++ *    @new_parent: object's new parent
++ *    @new_name: object's new name
++ */
 +
-       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy);
-       if (err < 0)
-               goto errout;
-@@ -679,6 +684,7 @@
- static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct nlattr *tb[IFA_MAX+1];
-       struct net_device *dev;
-       struct dn_dev *dn_db;
-@@ -686,6 +692,9 @@
-       struct dn_ifaddr *ifa;
-       int err;
-+      if (net != &init_net)
++int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent,
++                        const char *new_name)
++{
++      int error = 0;
++
++      kobj = kobject_get(kobj);
++      if (!kobj)
 +              return -EINVAL;
++      error = sysfs_rename_dir(kobj, new_parent, new_name);
++      kobject_put(kobj);
 +
-       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy);
-       if (err < 0)
-               return err;
-@@ -694,7 +703,7 @@
-               return -EINVAL;
-       ifm = nlmsg_data(nlh);
--      if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL)
-+      if ((dev = __dev_get_by_index(&init_net, ifm->ifa_index)) == NULL)
-               return -ENODEV;
-       if ((dn_db = dev->dn_ptr) == NULL) {
-@@ -783,24 +792,28 @@
-               kfree_skb(skb);
-               goto errout;
++      return error;
++}
++
++/**
+  *    kobject_move - move object to another parent
+  *    @kobj:  object in question.
+  *    @new_parent: object's new parent (can be NULL)
+diff -Nurb linux-2.6.22-590/lib/kobject_uevent.c linux-2.6.22-570/lib/kobject_uevent.c
+--- linux-2.6.22-590/lib/kobject_uevent.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/lib/kobject_uevent.c      2007-07-08 19:32:17.000000000 -0400
+@@ -208,7 +208,7 @@
+               argv [0] = uevent_helper;
+               argv [1] = (char *)subsystem;
+               argv [2] = NULL;
+-              call_usermodehelper (argv[0], argv, envp, UMH_WAIT_EXEC);
++              call_usermodehelper (argv[0], argv, envp, 0);
        }
--      err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
-+      err = rtnl_notify(skb, &init_net, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
- errout:
-       if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_DECnet_IFADDR, err);
-+              rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_IFADDR, err);
- }
  
- static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ exit:
+@@ -290,8 +290,9 @@
+ #if defined(CONFIG_NET)
+ static int __init kobject_uevent_init(void)
  {
-+      struct net *net = skb->sk->sk_net;
-       int idx, dn_idx = 0, skip_ndevs, skip_naddr;
-       struct net_device *dev;
-       struct dn_dev *dn_db;
-       struct dn_ifaddr *ifa;
-+      if (net != &init_net)
-+              return 0;
+-      uevent_sock = netlink_kernel_create(&init_net, NETLINK_KOBJECT_UEVENT,
+-                                          1, NULL, NULL, THIS_MODULE);
++      uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
++                                          NULL, THIS_MODULE);
 +
-       skip_ndevs = cb->args[0];
-       skip_naddr = cb->args[1];
-       idx = 0;
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if (idx < skip_ndevs)
-                       goto cont;
-               else if (idx > skip_ndevs) {
-@@ -869,10 +882,10 @@
-               rv = dn_dev_get_first(dev, addr);
-               read_unlock(&dev_base_lock);
-               dev_put(dev);
--              if (rv == 0 || dev == &loopback_dev)
-+              if (rv == 0 || dev == &init_net.loopback_dev)
-                       return rv;
-       }
--      dev = &loopback_dev;
-+      dev = &init_net.loopback_dev;
-       dev_hold(dev);
-       goto last_chance;
- }
-@@ -1299,7 +1312,7 @@
-       struct net_device *dev;
+       if (!uevent_sock) {
+               printk(KERN_ERR
+                      "kobject_uevent: unable to create netlink socket!\n");
+diff -Nurb linux-2.6.22-590/lib/pagewalk.c linux-2.6.22-570/lib/pagewalk.c
+--- linux-2.6.22-590/lib/pagewalk.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/lib/pagewalk.c    1969-12-31 19:00:00.000000000 -0500
+@@ -1,112 +0,0 @@
+-#include <linux/mm.h>
+-#include <linux/highmem.h>
+-
+-static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+-                        struct mm_walk *walk, void *private)
+-{
+-      pte_t *pte;
+-      int err;
+-
+-      for (pte = pte_offset_map(pmd, addr); addr != end;
+-           addr += PAGE_SIZE, pte++) {
+-              if (pte_none(*pte))
+-                      continue;
+-              err = walk->pte_entry(pte, addr, addr, private);
+-              if (err) {
+-                      pte_unmap(pte);
+-                      return err;
+-              }
+-      }
+-      pte_unmap(pte);
+-      return 0;
+-}
+-
+-static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
+-                        struct mm_walk *walk, void *private)
+-{
+-      pmd_t *pmd;
+-      unsigned long next;
+-      int err;
+-
+-      for (pmd = pmd_offset(pud, addr); addr != end;
+-           pmd++, addr = next) {
+-              next = pmd_addr_end(addr, end);
+-              if (pmd_none_or_clear_bad(pmd))
+-                      continue;
+-              if (walk->pmd_entry) {
+-                      err = walk->pmd_entry(pmd, addr, next, private);
+-                      if (err)
+-                              return err;
+-              }
+-              if (walk->pte_entry) {
+-                      err = walk_pte_range(pmd, addr, next, walk, private);
+-                      if (err)
+-                              return err;
+-              }
+-      }
+-      return 0;
+-}
+-
+-static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
+-                        struct mm_walk *walk, void *private)
+-{
+-      pud_t *pud;
+-      unsigned long next;
+-      int err;
+-
+-      for (pud = pud_offset(pgd, addr); addr != end;
+-           pud++, addr = next) {
+-              next = pud_addr_end(addr, end);
+-              if (pud_none_or_clear_bad(pud))
+-                      continue;
+-              if (walk->pud_entry) {
+-                      err = walk->pud_entry(pud, addr, next, private);
+-                      if (err)
+-                              return err;
+-              }
+-              if (walk->pmd_entry || walk->pte_entry) {
+-                      err = walk_pmd_range(pud, addr, next, walk, private);
+-                      if (err)
+-                              return err;
+-              }
+-      }
+-      return 0;
+-}
+-
+-/*
+- * walk_page_range - walk a memory map's page tables with a callback
+- * @mm - memory map to walk
+- * @addr - starting address
+- * @end - ending address
+- * @walk - set of callbacks to invoke for each level of the tree
+- * @private - private data passed to the callback function
+- *
+- * Recursively walk the page table for the memory area in a VMA, calling
+- * a callback for every bottom-level (PTE) page table.
+- */
+-int walk_page_range(struct mm_struct *mm,
+-                  unsigned long addr, unsigned long end,
+-                  struct mm_walk *walk, void *private)
+-{
+-      pgd_t *pgd;
+-      unsigned long next;
+-      int err;
+-
+-      for (pgd = pgd_offset(mm, addr); addr != end;
+-           pgd++, addr = next) {
+-              next = pgd_addr_end(addr, end);
+-              if (pgd_none_or_clear_bad(pgd))
+-                      continue;
+-              if (walk->pgd_entry) {
+-                      err = walk->pgd_entry(pgd, addr, next, private);
+-                      if (err)
+-                              return err;
+-              }
+-              if (walk->pud_entry || walk->pmd_entry || walk->pte_entry) {
+-                      err = walk_pud_range(pgd, addr, next, walk, private);
+-                      if (err)
+-                              return err;
+-              }
+-      }
+-      return 0;
+-}
+diff -Nurb linux-2.6.22-590/lib/radix-tree.c linux-2.6.22-570/lib/radix-tree.c
+--- linux-2.6.22-590/lib/radix-tree.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/lib/radix-tree.c  2007-07-08 19:32:17.000000000 -0400
+@@ -93,8 +93,7 @@
+       struct radix_tree_node *ret;
+       gfp_t gfp_mask = root_gfp_mask(root);
  
-       rtnl_lock();
--      for_each_netdev(dev)
-+      for_each_netdev(&init_net, dev)
-               dn_dev_down(dev);
-       rtnl_unlock();
+-      ret = kmem_cache_alloc(radix_tree_node_cachep,
+-                              set_migrateflags(gfp_mask, __GFP_RECLAIMABLE));
++      ret = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
+       if (ret == NULL && !(gfp_mask & __GFP_WAIT)) {
+               struct radix_tree_preload *rtp;
  
-@@ -1310,7 +1323,7 @@
-       struct net_device *dev;
+@@ -138,8 +137,7 @@
+       rtp = &__get_cpu_var(radix_tree_preloads);
+       while (rtp->nr < ARRAY_SIZE(rtp->nodes)) {
+               preempt_enable();
+-              node = kmem_cache_alloc(radix_tree_node_cachep,
+-                              set_migrateflags(gfp_mask, __GFP_RECLAIMABLE));
++              node = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
+               if (node == NULL)
+                       goto out;
+               preempt_disable();
+diff -Nurb linux-2.6.22-590/mm/filemap.c linux-2.6.22-570/mm/filemap.c
+--- linux-2.6.22-590/mm/filemap.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/filemap.c      2007-07-08 19:32:17.000000000 -0400
+@@ -1334,38 +1334,39 @@
+ #define MMAP_LOTSAMISS  (100)
  
-       rtnl_lock();
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if (dev->flags & IFF_UP)
-                       dn_dev_up(dev);
-       }
-@@ -1344,7 +1357,7 @@
-               return SEQ_START_TOKEN;
+ /**
+- * filemap_fault - read in file data for page fault handling
+- * @vma:      user vma (not used)
+- * @fdata:    the applicable fault_data
++ * filemap_nopage - read in file data for page fault handling
++ * @area:     the applicable vm_area
++ * @address:  target address to read in
++ * @type:     returned with VM_FAULT_{MINOR,MAJOR} if not %NULL
+  *
+- * filemap_fault() is invoked via the vma operations vector for a
++ * filemap_nopage() is invoked via the vma operations vector for a
+  * mapped memory region to read in file data during a page fault.
+  *
+  * The goto's are kind of ugly, but this streamlines the normal case of having
+  * it in the page cache, and handles the special cases reasonably without
+  * having a lot of duplicated code.
+  */
+-struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
++struct page *filemap_nopage(struct vm_area_struct *area,
++                              unsigned long address, int *type)
+ {
+       int error;
+-      struct file *file = vma->vm_file;
++      struct file *file = area->vm_file;
+       struct address_space *mapping = file->f_mapping;
+       struct file_ra_state *ra = &file->f_ra;
+       struct inode *inode = mapping->host;
+       struct page *page;
+-      unsigned long size;
+-      int did_readaround = 0;
++      unsigned long size, pgoff;
++      int did_readaround = 0, majmin = VM_FAULT_MINOR;
  
-       i = 1;
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if (!is_dn_dev(dev))
-                       continue;
+-      fdata->type = VM_FAULT_MINOR;
+-
+-      BUG_ON(!(vma->vm_flags & VM_CAN_INVALIDATE));
++      pgoff = ((address-area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
  
-@@ -1363,9 +1376,9 @@
++retry_all:
+       size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+-      if (fdata->pgoff >= size)
++      if (pgoff >= size)
+               goto outside_data_content;
  
-       dev = (struct net_device *)v;
-       if (v == SEQ_START_TOKEN)
--              dev = net_device_entry(&dev_base_head);
-+              dev = net_device_entry(&init_net.dev_base_head);
+       /* If we don't want any read-ahead, don't bother */
+-      if (VM_RandomReadHint(vma))
++      if (VM_RandomReadHint(area))
+               goto no_cached_page;
  
--      for_each_netdev_continue(dev) {
-+      for_each_netdev_continue(&init_net, dev) {
-               if (!is_dn_dev(dev))
-                       continue;
+       /*
+@@ -1374,19 +1375,19 @@
+        *
+        * For sequential accesses, we use the generic readahead logic.
+        */
+-      if (VM_SequentialReadHint(vma))
+-              page_cache_readahead(mapping, ra, file, fdata->pgoff, 1);
++      if (VM_SequentialReadHint(area))
++              page_cache_readahead(mapping, ra, file, pgoff, 1);
  
-@@ -1465,7 +1478,7 @@
-       rtnl_register(PF_DECnet, RTM_DELADDR, dn_nl_deladdr, NULL);
-       rtnl_register(PF_DECnet, RTM_GETADDR, NULL, dn_nl_dump_ifaddr);
+       /*
+        * Do we have something in the page cache already?
+        */
+ retry_find:
+-      page = find_lock_page(mapping, fdata->pgoff);
++      page = find_get_page(mapping, pgoff);
+       if (!page) {
+               unsigned long ra_pages;
  
--      proc_net_fops_create("decnet_dev", S_IRUGO, &dn_dev_seq_fops);
-+      proc_net_fops_create(&init_net, "decnet_dev", S_IRUGO, &dn_dev_seq_fops);
+-              if (VM_SequentialReadHint(vma)) {
+-                      handle_ra_miss(mapping, ra, fdata->pgoff);
++              if (VM_SequentialReadHint(area)) {
++                      handle_ra_miss(mapping, ra, pgoff);
+                       goto no_cached_page;
+               }
+               ra->mmap_miss++;
+@@ -1403,7 +1404,7 @@
+                * check did_readaround, as this is an inner loop.
+                */
+               if (!did_readaround) {
+-                      fdata->type = VM_FAULT_MAJOR;
++                      majmin = VM_FAULT_MAJOR;
+                       count_vm_event(PGMAJFAULT);
+               }
+               did_readaround = 1;
+@@ -1411,11 +1412,11 @@
+               if (ra_pages) {
+                       pgoff_t start = 0;
  
- #ifdef CONFIG_SYSCTL
-       {
-@@ -1486,7 +1499,7 @@
+-                      if (fdata->pgoff > ra_pages / 2)
+-                              start = fdata->pgoff - ra_pages / 2;
++                      if (pgoff > ra_pages / 2)
++                              start = pgoff - ra_pages / 2;
+                       do_page_cache_readahead(mapping, file, start, ra_pages);
+               }
+-              page = find_lock_page(mapping, fdata->pgoff);
++              page = find_get_page(mapping, pgoff);
+               if (!page)
+                       goto no_cached_page;
        }
- #endif /* CONFIG_SYSCTL */
--      proc_net_remove("decnet_dev");
-+      proc_net_remove(&init_net, "decnet_dev");
+@@ -1424,23 +1425,19 @@
+               ra->mmap_hit++;
  
-       dn_dev_devices_off();
- }
-diff -Nurb linux-2.6.22-570/net/decnet/dn_fib.c linux-2.6.22-590/net/decnet/dn_fib.c
---- linux-2.6.22-570/net/decnet/dn_fib.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/decnet/dn_fib.c       2008-01-02 13:56:38.000000000 -0500
-@@ -203,8 +203,6 @@
-               struct flowi fl;
-               struct dn_fib_res res;
+       /*
+-       * We have a locked page in the page cache, now we need to check
+-       * that it's up-to-date. If not, it is going to be due to an error.
++       * Ok, found a page in the page cache, now we need to check
++       * that it's up-to-date.
+        */
+-      if (unlikely(!PageUptodate(page)))
++      if (!PageUptodate(page))
+               goto page_not_uptodate;
  
--              memset(&fl, 0, sizeof(fl));
+-      /* Must recheck i_size under page lock */
+-      size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+-      if (unlikely(fdata->pgoff >= size)) {
+-              unlock_page(page);
+-              goto outside_data_content;
+-      }
 -
-               if (nh->nh_flags&RTNH_F_ONLINK) {
-                       struct net_device *dev;
++success:
+       /*
+        * Found the page and have a reference on it.
+        */
+       mark_page_accessed(page);
++      if (type)
++              *type = majmin;
+       return page;
  
-@@ -212,7 +210,7 @@
-                               return -EINVAL;
-                       if (dnet_addr_type(nh->nh_gw) != RTN_UNICAST)
-                               return -EINVAL;
--                      if ((dev = __dev_get_by_index(nh->nh_oif)) == NULL)
-+                      if ((dev = __dev_get_by_index(&init_net, nh->nh_oif)) == NULL)
-                               return -ENODEV;
-                       if (!(dev->flags&IFF_UP))
-                               return -ENETDOWN;
-@@ -223,6 +221,7 @@
-               }
+ outside_data_content:
+@@ -1448,17 +1445,15 @@
+        * An external ptracer can access pages that normally aren't
+        * accessible..
+        */
+-      if (vma->vm_mm == current->mm) {
+-              fdata->type = VM_FAULT_SIGBUS;
+-              return NULL;
+-      }
++      if (area->vm_mm == current->mm)
++              return NOPAGE_SIGBUS;
+       /* Fall through to the non-read-ahead case */
+ no_cached_page:
+       /*
+        * We're only likely to ever get here if MADV_RANDOM is in
+        * effect.
+        */
+-      error = page_cache_read(file, fdata->pgoff);
++      error = page_cache_read(file, pgoff);
  
-               memset(&fl, 0, sizeof(fl));
-+              fl.fl_net = &init_net;
-               fl.fld_dst = nh->nh_gw;
-               fl.oif = nh->nh_oif;
-               fl.fld_scope = r->rtm_scope + 1;
-@@ -255,7 +254,7 @@
-               if (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK))
-                       return -EINVAL;
+       /*
+        * The page we want has now been added to the page cache.
+@@ -1474,15 +1469,12 @@
+        * to schedule I/O.
+        */
+       if (error == -ENOMEM)
+-              fdata->type = VM_FAULT_OOM;
+-      else
+-              fdata->type = VM_FAULT_SIGBUS;
+-      return NULL;
++              return NOPAGE_OOM;
++      return NOPAGE_SIGBUS;
  
--              dev = __dev_get_by_index(nh->nh_oif);
-+              dev = __dev_get_by_index(&init_net, nh->nh_oif);
-               if (dev == NULL || dev->dn_ptr == NULL)
-                       return -ENODEV;
-               if (!(dev->flags&IFF_UP))
-@@ -355,7 +354,7 @@
-               if (nhs != 1 || nh->nh_gw)
-                       goto err_inval;
-               nh->nh_scope = RT_SCOPE_NOWHERE;
--              nh->nh_dev = dev_get_by_index(fi->fib_nh->nh_oif);
-+              nh->nh_dev = dev_get_by_index(&init_net, fi->fib_nh->nh_oif);
-               err = -ENODEV;
-               if (nh->nh_dev == NULL)
-                       goto failure;
-@@ -506,10 +505,14 @@
+ page_not_uptodate:
+-      /* IO error path */
+       if (!did_readaround) {
+-              fdata->type = VM_FAULT_MAJOR;
++              majmin = VM_FAULT_MAJOR;
+               count_vm_event(PGMAJFAULT);
+       }
+@@ -1492,39 +1484,38 @@
+        * because there really aren't any performance issues here
+        * and we need to check for errors.
+        */
++      lock_page(page);
++
++      /* Somebody truncated the page on us? */
++      if (!page->mapping) {
++              unlock_page(page);
++              page_cache_release(page);
++              goto retry_all;
++      }
++
++      /* Somebody else successfully read it in? */
++      if (PageUptodate(page)) {
++              unlock_page(page);
++              goto success;
++      }
+       ClearPageError(page);
+       error = mapping->a_ops->readpage(file, page);
++      if (!error) {
++              wait_on_page_locked(page);
++              if (PageUptodate(page))
++                      goto success;
++      } else if (error == AOP_TRUNCATED_PAGE) {
+               page_cache_release(page);
+-
+-      if (!error || error == AOP_TRUNCATED_PAGE)
+               goto retry_find;
++      }
+-      /* Things didn't work out. Return zero to tell the mm layer so. */
+-      shrink_readahead_size_eio(file, ra);
+-      fdata->type = VM_FAULT_SIGBUS;
+-      return NULL;
+-}
+-EXPORT_SYMBOL(filemap_fault);
+-
+-/*
+- * filemap_nopage and filemap_populate are legacy exports that are not used
+- * in tree. Scheduled for removal.
++      /*
++       * Things didn't work out. Return zero to tell the
++       * mm layer so, possibly freeing the page cache page first.
+  */
+-struct page *filemap_nopage(struct vm_area_struct *area,
+-                              unsigned long address, int *type)
+-{
+-      struct page *page;
+-      struct fault_data fdata;
+-      fdata.address = address;
+-      fdata.pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT)
+-                      + area->vm_pgoff;
+-      fdata.flags = 0;
+-
+-      page = filemap_fault(area, &fdata);
+-      if (type)
+-              *type = fdata.type;
+-
+-      return page;
++      shrink_readahead_size_eio(file, ra);
++      page_cache_release(page);
++      return NOPAGE_SIGBUS;
+ }
+ EXPORT_SYMBOL(filemap_nopage);
  
- static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct dn_fib_table *tb;
-       struct rtattr **rta = arg;
-       struct rtmsg *r = NLMSG_DATA(nlh);
+@@ -1702,7 +1693,8 @@
+ EXPORT_SYMBOL(filemap_populate);
  
-+      if (net != &init_net)
-+              return -EINVAL;
-+
-       if (dn_fib_check_attr(r, rta))
-               return -EINVAL;
+ struct vm_operations_struct generic_file_vm_ops = {
+-      .fault          = filemap_fault,
++      .nopage         = filemap_nopage,
++      .populate       = filemap_populate,
+ };
+ /* This is used for a general mmap of a disk file */
+@@ -1715,7 +1707,6 @@
+               return -ENOEXEC;
+       file_accessed(file);
+       vma->vm_ops = &generic_file_vm_ops;
+-      vma->vm_flags |= VM_CAN_INVALIDATE | VM_CAN_NONLINEAR;
+       return 0;
+ }
  
-@@ -522,10 +525,14 @@
+diff -Nurb linux-2.6.22-590/mm/filemap_xip.c linux-2.6.22-570/mm/filemap_xip.c
+--- linux-2.6.22-590/mm/filemap_xip.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/filemap_xip.c  2008-01-23 19:16:05.000000000 -0500
+@@ -228,67 +228,62 @@
+ }
  
- static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ /*
+- * xip_fault() is invoked via the vma operations vector for a
++ * xip_nopage() is invoked via the vma operations vector for a
+  * mapped memory region to read in file data during a page fault.
+  *
+- * This function is derived from filemap_fault, but used for execute in place
++ * This function is derived from filemap_nopage, but used for execute in place
+  */
+-static struct page *xip_file_fault(struct vm_area_struct *area,
+-                                      struct fault_data *fdata)
++static struct page *
++xip_file_nopage(struct vm_area_struct * area,
++                 unsigned long address,
++                 int *type)
  {
-+      struct net *net = skb->sk->sk_net;
-       struct dn_fib_table *tb;
-       struct rtattr **rta = arg;
-       struct rtmsg *r = NLMSG_DATA(nlh);
+       struct file *file = area->vm_file;
+       struct address_space *mapping = file->f_mapping;
+       struct inode *inode = mapping->host;
+       struct page *page;
+-      pgoff_t size;
++      unsigned long size, pgoff, endoff;
  
-+      if (net != &init_net)
-+              return -EINVAL;
-+
-       if (dn_fib_check_attr(r, rta))
-               return -EINVAL;
+-      /* XXX: are VM_FAULT_ codes OK? */
++      pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT)
++              + area->vm_pgoff;
++      endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT)
++              + area->vm_pgoff;
  
-@@ -602,7 +609,7 @@
+       size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+-      if (fdata->pgoff >= size) {
+-              fdata->type = VM_FAULT_SIGBUS;
+-              return NULL;
+-      }
++      if (pgoff >= size)
++              return NOPAGE_SIGBUS;
  
-       /* Scan device list */
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               dn_db = dev->dn_ptr;
-               if (dn_db == NULL)
-                       continue;
-diff -Nurb linux-2.6.22-570/net/decnet/dn_neigh.c linux-2.6.22-590/net/decnet/dn_neigh.c
---- linux-2.6.22-570/net/decnet/dn_neigh.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/decnet/dn_neigh.c     2008-01-02 13:56:38.000000000 -0500
-@@ -38,6 +38,7 @@
- #include <linux/rcupdate.h>
- #include <linux/jhash.h>
- #include <asm/atomic.h>
-+#include <net/net_namespace.h>
- #include <net/neighbour.h>
- #include <net/dst.h>
- #include <net/flow.h>
-@@ -591,6 +592,7 @@
+-      page = mapping->a_ops->get_xip_page(mapping,
+-                                      fdata->pgoff*(PAGE_SIZE/512), 0);
++      page = mapping->a_ops->get_xip_page(mapping, pgoff*(PAGE_SIZE/512), 0);
+       if (!IS_ERR(page))
+               goto out;
+-      if (PTR_ERR(page) != -ENODATA) {
+-              fdata->type = VM_FAULT_OOM;
+-              return NULL;
+-      }
++      if (PTR_ERR(page) != -ENODATA)
++              return NOPAGE_SIGBUS;
+       /* sparse block */
+       if ((area->vm_flags & (VM_WRITE | VM_MAYWRITE)) &&
+           (area->vm_flags & (VM_SHARED| VM_MAYSHARE)) &&
+           (!(mapping->host->i_sb->s_flags & MS_RDONLY))) {
+               /* maybe shared writable, allocate new block */
+-              page = mapping->a_ops->get_xip_page(mapping,
+-                                      fdata->pgoff*(PAGE_SIZE/512), 1);
+-              if (IS_ERR(page)) {
+-                      fdata->type = VM_FAULT_SIGBUS;
+-                      return NULL;
+-              }
++              page = mapping->a_ops->get_xip_page (mapping,
++                      pgoff*(PAGE_SIZE/512), 1);
++              if (IS_ERR(page))
++                      return NOPAGE_SIGBUS;
+               /* unmap page at pgoff from all other vmas */
+-              __xip_unmap(mapping, fdata->pgoff);
++              __xip_unmap(mapping, pgoff);
+       } else {
+               /* not shared and writable, use xip_sparse_page() */
+               page = xip_sparse_page();
+-              if (!page) {
+-                      fdata->type = VM_FAULT_OOM;
+-                      return NULL;
+-              }
++              if (!page)
++                      return NOPAGE_OOM;
+       }
  
-       seq          = file->private_data;
-       seq->private = s;
-+      s->net = get_net(PROC_NET(inode));
  out:
-       return rc;
- out_kfree:
-@@ -598,12 +600,20 @@
-       goto out;
+-      fdata->type = VM_FAULT_MINOR;
+       page_cache_get(page);
+       return page;
  }
  
-+static int dn_neigh_seq_release(struct inode *inode, struct file *file)
-+{
-+      struct seq_file *seq = file->private_data;
-+      struct neigh_seq_state *state = seq->private;
-+      put_net(state->net);
-+      return seq_release_private(inode, file);
-+}
-+
- static const struct file_operations dn_neigh_seq_fops = {
-       .owner          = THIS_MODULE,
-       .open           = dn_neigh_seq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
--      .release        = seq_release_private,
-+      .release        = dn_neigh_seq_release,
+ static struct vm_operations_struct xip_file_vm_ops = {
+-      .fault  = xip_file_fault,
++      .nopage         = xip_file_nopage,
  };
  
- #endif
-@@ -611,11 +621,11 @@
- void __init dn_neigh_init(void)
- {
-       neigh_table_init(&dn_neigh_table);
--      proc_net_fops_create("decnet_neigh", S_IRUGO, &dn_neigh_seq_fops);
-+      proc_net_fops_create(&init_net, "decnet_neigh", S_IRUGO, &dn_neigh_seq_fops);
- }
+ int xip_file_mmap(struct file * file, struct vm_area_struct * vma)
+@@ -297,7 +292,6 @@
  
- void __exit dn_neigh_cleanup(void)
- {
--      proc_net_remove("decnet_neigh");
-+      proc_net_remove(&init_net, "decnet_neigh");
-       neigh_table_clear(&dn_neigh_table);
+       file_accessed(file);
+       vma->vm_ops = &xip_file_vm_ops;
+-      vma->vm_flags |= VM_CAN_NONLINEAR;
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(xip_file_mmap);
+diff -Nurb linux-2.6.22-590/mm/fremap.c linux-2.6.22-570/mm/fremap.c
+--- linux-2.6.22-590/mm/fremap.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/fremap.c       2008-01-23 19:16:05.000000000 -0500
+@@ -129,25 +129,6 @@
+       return err;
  }
-diff -Nurb linux-2.6.22-570/net/decnet/dn_nsp_out.c linux-2.6.22-590/net/decnet/dn_nsp_out.c
---- linux-2.6.22-570/net/decnet/dn_nsp_out.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/decnet/dn_nsp_out.c   2008-01-02 13:56:38.000000000 -0500
-@@ -91,6 +91,7 @@
-       }
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       fl.oif = sk->sk_bound_dev_if;
-       fl.fld_src = dn_saddr2dn(&scp->addr);
-       fl.fld_dst = dn_saddr2dn(&scp->peer);
-diff -Nurb linux-2.6.22-570/net/decnet/dn_route.c linux-2.6.22-590/net/decnet/dn_route.c
---- linux-2.6.22-570/net/decnet/dn_route.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/decnet/dn_route.c     2008-01-02 13:56:38.000000000 -0500
-@@ -82,6 +82,7 @@
- #include <net/dst.h>
- #include <net/flow.h>
- #include <net/fib_rules.h>
-+#include <net/net_namespace.h>
- #include <net/dn.h>
- #include <net/dn_dev.h>
- #include <net/dn_nsp.h>
-@@ -583,6 +584,9 @@
-       struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr;
-       unsigned char padlen = 0;
-+      if (dev->nd_net != &init_net)
-+              goto dump_it;
-+
-       if (dn == NULL)
-               goto dump_it;
-@@ -877,13 +881,14 @@
  
- static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *oldflp, int try_hard)
- {
--      struct flowi fl = { .nl_u = { .dn_u =
-+      struct flowi fl = { .fl_net = &init_net,
-+                          .nl_u = { .dn_u =
-                                     { .daddr = oldflp->fld_dst,
-                                       .saddr = oldflp->fld_src,
-                                       .scope = RT_SCOPE_UNIVERSE,
-                                    } },
-                           .mark = oldflp->mark,
--                          .iif = loopback_dev.ifindex,
-+                          .iif = init_net.loopback_dev.ifindex,
-                           .oif = oldflp->oif };
-       struct dn_route *rt = NULL;
-       struct net_device *dev_out = NULL, *dev;
-@@ -900,11 +905,11 @@
-                      "dn_route_output_slow: dst=%04x src=%04x mark=%d"
-                      " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst),
-                      dn_ntohs(oldflp->fld_src),
--                     oldflp->mark, loopback_dev.ifindex, oldflp->oif);
-+                     oldflp->mark, init_net.loopback_dev.ifindex, oldflp->oif);
+-static int populate_range(struct mm_struct *mm, struct vm_area_struct *vma,
+-                      unsigned long addr, unsigned long size, pgoff_t pgoff)
+-{
+-      int err;
+-
+-      do {
+-              err = install_file_pte(mm, vma, addr, pgoff, vma->vm_page_prot);
+-              if (err)
+-                      return err;
+-
+-              size -= PAGE_SIZE;
+-              addr += PAGE_SIZE;
+-              pgoff++;
+-      } while (size);
+-
+-        return 0;
+-
+-}
+-
+ /***
+  * sys_remap_file_pages - remap arbitrary pages of a shared backing store
+  *                        file within an existing vma.
+@@ -205,27 +186,15 @@
+        * the single existing vma.  vm_private_data is used as a
+        * swapout cursor in a VM_NONLINEAR vma.
+        */
+-      if (!vma || !(vma->vm_flags & VM_SHARED))
+-              goto out;
+-
+-      if (vma->vm_private_data && !(vma->vm_flags & VM_NONLINEAR))
+-              goto out;
+-
+-      if ((!vma->vm_ops || !vma->vm_ops->populate) &&
+-                                      !(vma->vm_flags & VM_CAN_NONLINEAR))
+-              goto out;
+-
+-      if (end <= start || start < vma->vm_start || end > vma->vm_end)
+-              goto out;
++      if (vma && (vma->vm_flags & VM_SHARED) &&
++              (!vma->vm_private_data || (vma->vm_flags & VM_NONLINEAR)) &&
++              vma->vm_ops && vma->vm_ops->populate &&
++                      end > start && start >= vma->vm_start &&
++                              end <= vma->vm_end) {
  
-       /* If we have an output interface, verify its a DECnet device */
-       if (oldflp->oif) {
--              dev_out = dev_get_by_index(oldflp->oif);
-+              dev_out = dev_get_by_index(&init_net, oldflp->oif);
-               err = -ENODEV;
-               if (dev_out && dev_out->dn_ptr == NULL) {
-                       dev_put(dev_out);
-@@ -925,7 +930,7 @@
-                       goto out;
-               }
-               read_lock(&dev_base_lock);
--              for_each_netdev(dev) {
-+              for_each_netdev(&init_net, dev) {
-                       if (!dev->dn_ptr)
-                               continue;
-                       if (!dn_dev_islocal(dev, oldflp->fld_src))
-@@ -953,7 +958,7 @@
-               err = -EADDRNOTAVAIL;
-               if (dev_out)
-                       dev_put(dev_out);
--              dev_out = &loopback_dev;
-+              dev_out = &init_net.loopback_dev;
-               dev_hold(dev_out);
-               if (!fl.fld_dst) {
-                       fl.fld_dst =
-@@ -962,7 +967,7 @@
-                       if (!fl.fld_dst)
-                               goto out;
+               /* Must set VM_NONLINEAR before any pages are populated. */
+-      if (!(vma->vm_flags & VM_NONLINEAR)) {
+-              /* Don't need a nonlinear mapping, exit success */
+-              if (pgoff == linear_page_index(vma, start)) {
+-                      err = 0;
+-                      goto out;
+-              }
+-
++              if (pgoff != linear_page_index(vma, start) &&
++                  !(vma->vm_flags & VM_NONLINEAR)) {
+                       if (!has_write_lock) {
+                               up_read(&mm->mmap_sem);
+                               down_write(&mm->mmap_sem);
+@@ -242,17 +211,8 @@
+                       spin_unlock(&mapping->i_mmap_lock);
                }
--              fl.oif = loopback_dev.ifindex;
-+              fl.oif = init_net.loopback_dev.ifindex;
-               res.type = RTN_LOCAL;
-               goto make_route;
-       }
-@@ -995,7 +1000,7 @@
-                * here
-                */
-               if (!try_hard) {
--                      neigh = neigh_lookup_nodev(&dn_neigh_table, &fl.fld_dst);
-+                      neigh = neigh_lookup_nodev(&dn_neigh_table, &init_net, &fl.fld_dst);
-                       if (neigh) {
-                               if ((oldflp->oif &&
-                                   (neigh->dev->ifindex != oldflp->oif)) ||
-@@ -1008,7 +1013,7 @@
-                                       if (dev_out)
-                                               dev_put(dev_out);
-                                       if (dn_dev_islocal(neigh->dev, fl.fld_dst)) {
--                                              dev_out = &loopback_dev;
-+                                              dev_out = &init_net.loopback_dev;
-                                               res.type = RTN_LOCAL;
-                                       } else {
-                                               dev_out = neigh->dev;
-@@ -1029,7 +1034,7 @@
-               /* Possible improvement - check all devices for local addr */
-               if (dn_dev_islocal(dev_out, fl.fld_dst)) {
-                       dev_put(dev_out);
--                      dev_out = &loopback_dev;
-+                      dev_out = &init_net.loopback_dev;
-                       dev_hold(dev_out);
-                       res.type = RTN_LOCAL;
-                       goto select_source;
-@@ -1065,7 +1070,7 @@
-                       fl.fld_src = fl.fld_dst;
-               if (dev_out)
-                       dev_put(dev_out);
--              dev_out = &loopback_dev;
-+              dev_out = &init_net.loopback_dev;
-               dev_hold(dev_out);
-               fl.oif = dev_out->ifindex;
-               if (res.fi)
-@@ -1103,6 +1108,7 @@
-       atomic_set(&rt->u.dst.__refcnt, 1);
-       rt->u.dst.flags   = DST_HOST;
  
-+      rt->fl.fl_net     = &init_net;
-       rt->fl.fld_src    = oldflp->fld_src;
-       rt->fl.fld_dst    = oldflp->fld_dst;
-       rt->fl.oif        = oldflp->oif;
-@@ -1226,7 +1232,8 @@
-       int flags = 0;
-       __le16 gateway = 0;
-       __le16 local_src = 0;
--      struct flowi fl = { .nl_u = { .dn_u =
-+      struct flowi fl = { .fl_net = &init_net,
-+                          .nl_u = { .dn_u = 
-                                    { .daddr = cb->dst,
-                                      .saddr = cb->src,
-                                      .scope = RT_SCOPE_UNIVERSE,
-@@ -1374,6 +1381,7 @@
-       rt->rt_dst_map    = fl.fld_dst;
-       rt->rt_src_map    = fl.fld_src;
+-      if (vma->vm_flags & VM_CAN_NONLINEAR) {
+-              err = populate_range(mm, vma, start, size, pgoff);
+-              if (!err && !(flags & MAP_NONBLOCK)) {
+-                      if (unlikely(has_write_lock)) {
+-                              downgrade_write(&mm->mmap_sem);
+-                              has_write_lock = 0;
+-                      }
+-                      make_pages_present(start, start+size);
+-              }
+-      } else
+-              err = vma->vm_ops->populate(vma, start, size, vma->vm_page_prot,
++              err = vma->vm_ops->populate(vma, start, size,
++                                          vma->vm_page_prot,
+                                           pgoff, flags & MAP_NONBLOCK);
  
-+      rt->fl.fl_net     = &init_net;
-       rt->fl.fld_src    = cb->src;
-       rt->fl.fld_dst    = cb->dst;
-       rt->fl.oif        = 0;
-@@ -1526,6 +1534,7 @@
+               /*
+@@ -260,8 +220,7 @@
+                * it after ->populate completes, and that would prevent
+                * downgrading the lock.  (Locks can't be upgraded).
+                */
+-
+-out:
++      }
+       if (likely(!has_write_lock))
+               up_read(&mm->mmap_sem);
+       else
+diff -Nurb linux-2.6.22-590/mm/hugetlb.c linux-2.6.22-570/mm/hugetlb.c
+--- linux-2.6.22-590/mm/hugetlb.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/hugetlb.c      2008-01-23 19:16:05.000000000 -0500
+@@ -28,9 +28,6 @@
+ static struct list_head hugepage_freelists[MAX_NUMNODES];
+ static unsigned int nr_huge_pages_node[MAX_NUMNODES];
+ static unsigned int free_huge_pages_node[MAX_NUMNODES];
+-gfp_t htlb_alloc_mask = GFP_HIGHUSER;
+-unsigned long hugepages_treat_as_movable;
+-
+ /*
+  * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages
   */
- static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
+@@ -70,15 +67,14 @@
+ static struct page *dequeue_huge_page(struct vm_area_struct *vma,
+                               unsigned long address)
  {
-+      struct net *net = in_skb->sk->sk_net;
-       struct rtattr **rta = arg;
-       struct rtmsg *rtm = NLMSG_DATA(nlh);
-       struct dn_route *rt = NULL;
-@@ -1534,7 +1543,11 @@
-       struct sk_buff *skb;
-       struct flowi fl;
+-      int nid;
++      int nid = numa_node_id();
+       struct page *page = NULL;
+-      struct zonelist *zonelist = huge_zonelist(vma, address,
+-                                              htlb_alloc_mask);
++      struct zonelist *zonelist = huge_zonelist(vma, address);
+       struct zone **z;
  
-+      if (net != &init_net)
-+              return -EINVAL;
-+
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       fl.proto = DNPROTO_NSP;
+       for (z = zonelist->zones; *z; z++) {
+               nid = zone_to_nid(*z);
+-              if (cpuset_zone_allowed_softwall(*z, htlb_alloc_mask) &&
++              if (cpuset_zone_allowed_softwall(*z, GFP_HIGHUSER) &&
+                   !list_empty(&hugepage_freelists[nid]))
+                       break;
+       }
+@@ -118,7 +114,7 @@
+       prev_nid = nid;
+       spin_unlock(&nid_lock);
  
-       skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
-@@ -1552,7 +1565,7 @@
+-      page = alloc_pages_node(nid, htlb_alloc_mask|__GFP_COMP|__GFP_NOWARN,
++      page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP|__GFP_NOWARN,
+                                       HUGETLB_PAGE_ORDER);
+       if (page) {
+               set_compound_page_dtor(page, free_huge_page);
+@@ -268,19 +264,6 @@
+       max_huge_pages = set_max_huge_pages(max_huge_pages);
+       return 0;
+ }
+-
+-int hugetlb_treat_movable_handler(struct ctl_table *table, int write,
+-                      struct file *file, void __user *buffer,
+-                      size_t *length, loff_t *ppos)
+-{
+-      proc_dointvec(table, write, file, buffer, length, ppos);
+-      if (hugepages_treat_as_movable)
+-              htlb_alloc_mask = GFP_HIGH_MOVABLE;
+-      else
+-              htlb_alloc_mask = GFP_HIGHUSER;
+-      return 0;
+-}
+-
+ #endif /* CONFIG_SYSCTL */
  
-       if (fl.iif) {
-               struct net_device *dev;
--              if ((dev = dev_get_by_index(fl.iif)) == NULL) {
-+              if ((dev = dev_get_by_index(&init_net, fl.iif)) == NULL) {
-                       kfree_skb(skb);
-                       return -ENODEV;
-               }
-@@ -1598,7 +1611,7 @@
-               goto out_free;
-       }
+ int hugetlb_report_meminfo(char *buf)
+diff -Nurb linux-2.6.22-590/mm/memory.c linux-2.6.22-570/mm/memory.c
+--- linux-2.6.22-590/mm/memory.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/memory.c       2008-01-23 19:16:05.000000000 -0500
+@@ -1052,8 +1052,7 @@
+               if (pages)
+                       foll_flags |= FOLL_GET;
+               if (!write && !(vma->vm_flags & VM_LOCKED) &&
+-                  (!vma->vm_ops || (!vma->vm_ops->nopage &&
+-                                      !vma->vm_ops->fault)))
++                  (!vma->vm_ops || !vma->vm_ops->nopage))
+                       foll_flags |= FOLL_ANON;
  
--      return rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
-+      return rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
+               do {
+@@ -1713,11 +1712,11 @@
+       if (unlikely(anon_vma_prepare(vma)))
+               goto oom;
+       if (old_page == ZERO_PAGE(address)) {
+-              new_page = alloc_zeroed_user_highpage_movable(vma, address);
++              new_page = alloc_zeroed_user_highpage(vma, address);
+               if (!new_page)
+                       goto oom;
+       } else {
+-              new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
++              new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
+               if (!new_page)
+                       goto oom;
+               cow_user_page(new_page, old_page, address, vma);
+@@ -1829,13 +1828,6 @@
+       unsigned long restart_addr;
+       int need_break;
  
- out_free:
-       kfree_skb(skb);
-@@ -1611,10 +1624,14 @@
-  */
- int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct dn_route *rt;
-       int h, s_h;
-       int idx, s_idx;
+-      /*
+-       * files that support invalidating or truncating portions of the
+-       * file from under mmaped areas must set the VM_CAN_INVALIDATE flag, and
+-       * have their .nopage function return the page locked.
+-       */
+-      BUG_ON(!(vma->vm_flags & VM_CAN_INVALIDATE));
+-
+ again:
+       restart_addr = vma->vm_truncate_count;
+       if (is_restart_addr(restart_addr) && start_addr < restart_addr) {
+@@ -1964,8 +1956,17 @@
  
-+      if (net != &init_net)
-+              return 0;
-+
-       if (NLMSG_PAYLOAD(cb->nlh, 0) < sizeof(struct rtmsg))
-               return -EINVAL;
-       if (!(((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED))
-@@ -1814,7 +1831,7 @@
+       spin_lock(&mapping->i_mmap_lock);
  
-       dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
+-      /* Protect against endless unmapping loops */
++      /* serialize i_size write against truncate_count write */
++      smp_wmb();
++      /* Protect against page faults, and endless unmapping loops */
+       mapping->truncate_count++;
++      /*
++       * For archs where spin_lock has inclusive semantics like ia64
++       * this smp_mb() will prevent to read pagetable contents
++       * before the truncate_count increment is visible to
++       * other cpus.
++       */
++      smp_mb();
+       if (unlikely(is_restart_addr(mapping->truncate_count))) {
+               if (mapping->truncate_count == 0)
+                       reset_vma_truncate_counts(mapping);
+@@ -2004,18 +2005,8 @@
+       if (IS_SWAPFILE(inode))
+               goto out_busy;
+       i_size_write(inode, offset);
+-
+-      /*
+-       * unmap_mapping_range is called twice, first simply for efficiency
+-       * so that truncate_inode_pages does fewer single-page unmaps. However
+-       * after this first call, and before truncate_inode_pages finishes,
+-       * it is possible for private pages to be COWed, which remain after
+-       * truncate_inode_pages finishes, hence the second unmap_mapping_range
+-       * call must be made for correctness.
+-       */
+       unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
+       truncate_inode_pages(mapping, offset);
+-      unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
+       goto out_truncate;
  
--      proc_net_fops_create("decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops);
-+      proc_net_fops_create(&init_net, "decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops);
+ do_expand:
+@@ -2055,7 +2046,6 @@
+       down_write(&inode->i_alloc_sem);
+       unmap_mapping_range(mapping, offset, (end - offset), 1);
+       truncate_inode_pages_range(mapping, offset, end);
+-      unmap_mapping_range(mapping, offset, (end - offset), 1);
+       inode->i_op->truncate_range(inode, offset, end);
+       up_write(&inode->i_alloc_sem);
+       mutex_unlock(&inode->i_mutex);
+@@ -2218,6 +2208,7 @@
  
- #ifdef CONFIG_DECNET_ROUTER
-       rtnl_register(PF_DECnet, RTM_GETROUTE, dn_cache_getroute, dn_fib_dump);
-@@ -1829,6 +1846,6 @@
-       del_timer(&dn_route_timer);
-       dn_run_flush(0);
+       /* No need to invalidate - it was non-present before */
+       update_mmu_cache(vma, address, pte);
++      lazy_mmu_prot_update(pte);
+ unlock:
+       pte_unmap_unlock(page_table, ptl);
+ out:
+@@ -2250,7 +2241,7 @@
+                       goto oom;
+               if (unlikely(anon_vma_prepare(vma)))
+                       goto oom;
+-              page = alloc_zeroed_user_highpage_movable(vma, address);
++              page = alloc_zeroed_user_highpage(vma, address);
+               if (!page)
+                       goto oom;
  
--      proc_net_remove("decnet_cache");
-+      proc_net_remove(&init_net, "decnet_cache");
+@@ -2293,10 +2284,10 @@
  }
  
-diff -Nurb linux-2.6.22-570/net/decnet/dn_rules.c linux-2.6.22-590/net/decnet/dn_rules.c
---- linux-2.6.22-570/net/decnet/dn_rules.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/decnet/dn_rules.c     2008-01-02 13:56:38.000000000 -0500
-@@ -186,7 +186,10 @@
+ /*
+- * __do_fault() tries to create a new page mapping. It aggressively
++ * do_no_page() tries to create a new page mapping. It aggressively
+  * tries to share with existing pages, but makes a separate copy if
+- * the FAULT_FLAG_WRITE is set in the flags parameter in order to avoid
+- * the next page fault.
++ * the "write_access" parameter is true in order to avoid the next
++ * page fault.
+  *
+  * As this is called only for pages that do not currently exist, we
+  * do not need to flush old virtual caches or the TLB.
+@@ -2305,85 +2296,92 @@
+  * but allow concurrent faults), and pte mapped but not yet locked.
+  * We return with mmap_sem still held, but pte unmapped and unlocked.
+  */
+-static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
++static int do_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
+               unsigned long address, pte_t *page_table, pmd_t *pmd,
+-              pgoff_t pgoff, unsigned int flags, pte_t orig_pte)
+-  {
++              int write_access)
++{
+       spinlock_t *ptl;
+-      struct page *page, *faulted_page;
++      struct page *new_page;
++      struct address_space *mapping = NULL;
+       pte_t entry;
++      unsigned int sequence = 0;
++      int ret = VM_FAULT_MINOR;
+       int anon = 0;
+       struct page *dirty_page = NULL;
+-      struct fault_data fdata;
+- 
+-      fdata.address = address & PAGE_MASK;
+-      fdata.pgoff = pgoff;
+-      fdata.flags = flags;
+       pte_unmap(page_table);
+       BUG_ON(vma->vm_flags & VM_PFNMAP);
  
- unsigned dnet_addr_type(__le16 addr)
- {
--      struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } };
-+      struct flowi fl = { 
-+              .fl_net = &init_net,
-+              .nl_u = { .dn_u = { .daddr = addr } } 
-+      };
-       struct dn_fib_res res;
-       unsigned ret = RTN_UNICAST;
-       struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0);
-@@ -223,7 +226,7 @@
-       return -ENOBUFS;
- }
+-      if (likely(vma->vm_ops->fault)) {
+-              fdata.type = -1;
+-              faulted_page = vma->vm_ops->fault(vma, &fdata);
+-              WARN_ON(fdata.type == -1);
+-              if (unlikely(!faulted_page))
+-                      return fdata.type;
+-      } else {
+-              /* Legacy ->nopage path */
+-              fdata.type = VM_FAULT_MINOR;
+-              faulted_page = vma->vm_ops->nopage(vma, address & PAGE_MASK,
+-                                                              &fdata.type);
+-              /* no page was available -- either SIGBUS or OOM */
+-              if (unlikely(faulted_page == NOPAGE_SIGBUS))
+-                      return VM_FAULT_SIGBUS;
+-              else if (unlikely(faulted_page == NOPAGE_OOM))
++      if (!vx_rss_avail(mm, 1))
+               return VM_FAULT_OOM;
+-      }
  
--static u32 dn_fib_rule_default_pref(void)
-+static u32 dn_fib_rule_default_pref(struct fib_rules_ops *ops)
- {
-       struct list_head *pos;
-       struct fib_rule *rule;
-@@ -240,7 +243,7 @@
-       return 0;
- }
+-      /*
+-       * For consistency in subsequent calls, make the faulted_page always
+-       * locked.
++      if (vma->vm_file) {
++              mapping = vma->vm_file->f_mapping;
++              sequence = mapping->truncate_count;
++              smp_rmb(); /* serializes i_size against truncate_count */
++      }
++retry:
++      new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, &ret);
++      /*
++       * No smp_rmb is needed here as long as there's a full
++       * spin_lock/unlock sequence inside the ->nopage callback
++       * (for the pagecache lookup) that acts as an implicit
++       * smp_mb() and prevents the i_size read to happen
++       * after the next truncate_count read.
+        */
+-      if (unlikely(!(vma->vm_flags & VM_CAN_INVALIDATE)))
+-              lock_page(faulted_page);
+-      else
+-              BUG_ON(!PageLocked(faulted_page));
++
++      /* no page was available -- either SIGBUS, OOM or REFAULT */
++      if (unlikely(new_page == NOPAGE_SIGBUS))
++              return VM_FAULT_SIGBUS;
++      else if (unlikely(new_page == NOPAGE_OOM))
++              return VM_FAULT_OOM;
++      else if (unlikely(new_page == NOPAGE_REFAULT))
++              return VM_FAULT_MINOR;
  
--static void dn_fib_rule_flush_cache(void)
-+static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops)
- {
-       dn_rt_cache_flush(-1);
- }
-@@ -265,12 +268,12 @@
- void __init dn_fib_rules_init(void)
- {
-       list_add_tail(&default_rule.common.list, &dn_fib_rules);
--      fib_rules_register(&dn_fib_rules_ops);
-+      fib_rules_register(&init_net, &dn_fib_rules_ops);
- }
+       /*
+        * Should we do an early C-O-W break?
+        */
+-      page = faulted_page;
+-      if (flags & FAULT_FLAG_WRITE) {
++      if (write_access) {
+               if (!(vma->vm_flags & VM_SHARED)) {
+-                      anon = 1;
+-                      if (unlikely(anon_vma_prepare(vma))) {
+-                              fdata.type = VM_FAULT_OOM;
+-                              goto out;
+-                      }
++                      struct page *page;
++
++                      if (unlikely(anon_vma_prepare(vma)))
++                              goto oom;
+                       page = alloc_page_vma(GFP_HIGHUSER, vma, address);
+-                      if (!page) {
+-                              fdata.type = VM_FAULT_OOM;
+-                              goto out;
+-                      }
+-                      copy_user_highpage(page, faulted_page, address, vma);
++                      if (!page)
++                              goto oom;
++                      copy_user_highpage(page, new_page, address, vma);
++                      page_cache_release(new_page);
++                      new_page = page;
++                      anon = 1;
++
+               } else {
+-                      /*
+-                       * If the page will be shareable, see if the backing
++                      /* if the page will be shareable, see if the backing
+                        * address space wants to know that the page is about
+-                       * to become writable
+-                       */
++                       * to become writable */
+                       if (vma->vm_ops->page_mkwrite &&
+-                          vma->vm_ops->page_mkwrite(vma, page) < 0) {
+-                              fdata.type = VM_FAULT_SIGBUS;
+-                              anon = 1; /* no anon but release faulted_page */
+-                              goto out;
++                          vma->vm_ops->page_mkwrite(vma, new_page) < 0
++                          ) {
++                              page_cache_release(new_page);
++                              return VM_FAULT_SIGBUS;
+                       }
+               }
+- 
+       }
  
- void __exit dn_fib_rules_cleanup(void)
- {
--      fib_rules_unregister(&dn_fib_rules_ops);
-+      fib_rules_unregister(&init_net, &dn_fib_rules_ops);
- }
+       page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
++      /*
++       * For a file-backed vma, someone could have truncated or otherwise
++       * invalidated this page.  If unmap_mapping_range got called,
++       * retry getting the page.
++       */
++      if (mapping && unlikely(sequence != mapping->truncate_count)) {
++              pte_unmap_unlock(page_table, ptl);
++              page_cache_release(new_page);
++              cond_resched();
++              sequence = mapping->truncate_count;
++              smp_rmb();
++              goto retry;
++      }
  
+       /*
+        * This silly early PAGE_DIRTY setting removes a race
+@@ -2396,68 +2394,43 @@
+        * handle that later.
+        */
+       /* Only go through if we didn't race with anybody else... */
+-      if (likely(pte_same(*page_table, orig_pte))) {
+-              flush_icache_page(vma, page);
+-              entry = mk_pte(page, vma->vm_page_prot);
+-              if (flags & FAULT_FLAG_WRITE)
++      if (pte_none(*page_table)) {
++              flush_icache_page(vma, new_page);
++              entry = mk_pte(new_page, vma->vm_page_prot);
++              if (write_access)
+                       entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+               set_pte_at(mm, address, page_table, entry);
+               if (anon) {
+                       inc_mm_counter(mm, anon_rss);
+-                        lru_cache_add_active(page);
+-                        page_add_new_anon_rmap(page, vma, address);
++                      lru_cache_add_active(new_page);
++                      page_add_new_anon_rmap(new_page, vma, address);
+               } else {
+                       inc_mm_counter(mm, file_rss);
+-                      page_add_file_rmap(page);
+-                      if (flags & FAULT_FLAG_WRITE) {
+-                              dirty_page = page;
++                      page_add_file_rmap(new_page);
++                      if (write_access) {
++                              dirty_page = new_page;
+                               get_page(dirty_page);
+                       }
+               }
+-
+-              /* no need to invalidate: a not-present page won't be cached */
+-      update_mmu_cache(vma, address, entry);
+-      lazy_mmu_prot_update(entry);
+       } else {
+-              if (anon)
+-                      page_cache_release(page);
+-              else
+-                      anon = 1; /* no anon but release faulted_page */
++              /* One of our sibling threads was faster, back out. */
++              page_cache_release(new_page);
++              goto unlock;
+       }
  
-diff -Nurb linux-2.6.22-570/net/decnet/dn_table.c linux-2.6.22-590/net/decnet/dn_table.c
---- linux-2.6.22-570/net/decnet/dn_table.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/decnet/dn_table.c     2008-01-02 13:56:38.000000000 -0500
-@@ -375,10 +375,10 @@
-               kfree_skb(skb);
-               goto errout;
++      /* no need to invalidate: a not-present page shouldn't be cached */
++      update_mmu_cache(vma, address, entry);
++      lazy_mmu_prot_update(entry);
++unlock:
+       pte_unmap_unlock(page_table, ptl);
+-
+-out:
+-      unlock_page(faulted_page);
+-      if (anon)
+-              page_cache_release(faulted_page);
+-      else if (dirty_page) {
++      if (dirty_page) {
+               set_page_dirty_balance(dirty_page);
+               put_page(dirty_page);
        }
--      err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
-+      err = rtnl_notify(skb, &init_net, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
- errout:
-       if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_DECnet_ROUTE, err);
-+              rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_ROUTE, err);
+-
+-      return fdata.type;
+-}
+-
+-static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+-              unsigned long address, pte_t *page_table, pmd_t *pmd,
+-              int write_access, pte_t orig_pte)
+-{
+-      pgoff_t pgoff = (((address & PAGE_MASK)
+-                      - vma->vm_start) >> PAGE_CACHE_SHIFT) + vma->vm_pgoff;
+-      unsigned int flags = (write_access ? FAULT_FLAG_WRITE : 0);
+-
+-      return __do_fault(mm, vma, address, page_table, pmd, pgoff, flags, orig_pte);
+-}
+-
+-static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+-              unsigned long address, pte_t *page_table, pmd_t *pmd,
+-              int write_access, pgoff_t pgoff, pte_t orig_pte)
+-{
+-      unsigned int flags = FAULT_FLAG_NONLINEAR |
+-                              (write_access ? FAULT_FLAG_WRITE : 0);
+-
+-      return __do_fault(mm, vma, address, page_table, pmd, pgoff, flags, orig_pte);
++      return ret;
++oom:
++      page_cache_release(new_page);
++      return VM_FAULT_OOM;
  }
  
- static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb,
-@@ -463,12 +463,16 @@
+ /*
+@@ -2536,14 +2509,9 @@
+               print_bad_pte(vma, orig_pte, address);
+               return VM_FAULT_OOM;
+       }
++      /* We can then assume vm->vm_ops && vma->vm_ops->populate */
  
- int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
- {
-+      struct net *net = skb->sk->sk_net;
-       unsigned int h, s_h;
-       unsigned int e = 0, s_e;
-       struct dn_fib_table *tb;
-       struct hlist_node *node;
-       int dumped = 0;
+       pgoff = pte_to_pgoff(orig_pte);
+-
+-      if (vma->vm_ops && vma->vm_ops->fault)
+-              return do_nonlinear_fault(mm, vma, address, page_table, pmd,
+-                                      write_access, pgoff, orig_pte);
+-
+-      /* We can then assume vm->vm_ops && vma->vm_ops->populate */
+       err = vma->vm_ops->populate(vma, address & PAGE_MASK, PAGE_SIZE,
+                                       vma->vm_page_prot, pgoff, 0);
+       if (err == -ENOMEM)
+@@ -2578,9 +2546,10 @@
+       if (!pte_present(entry)) {
+               if (pte_none(entry)) {
+                       if (vma->vm_ops) {
+-                              if (vma->vm_ops->fault || vma->vm_ops->nopage)
+-                                      return do_linear_fault(mm, vma, address,
+-                                              pte, pmd, write_access, entry);
++                              if (vma->vm_ops->nopage)
++                                      return do_no_page(mm, vma, address,
++                                                        pte, pmd,
++                                                        write_access);
+                               if (unlikely(vma->vm_ops->nopfn))
+                                       return do_no_pfn(mm, vma, address, pte,
+                                                        pmd, write_access);
+diff -Nurb linux-2.6.22-590/mm/mempolicy.c linux-2.6.22-570/mm/mempolicy.c
+--- linux-2.6.22-590/mm/mempolicy.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/mempolicy.c    2007-07-08 19:32:17.000000000 -0400
+@@ -594,7 +594,7 @@
  
-+      if (net != &init_net)
-+              return 0;
-+
-       if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
-               ((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
-                       return dn_cache_dump(skb, cb);
-diff -Nurb linux-2.6.22-570/net/decnet/netfilter/dn_rtmsg.c linux-2.6.22-590/net/decnet/netfilter/dn_rtmsg.c
---- linux-2.6.22-570/net/decnet/netfilter/dn_rtmsg.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/decnet/netfilter/dn_rtmsg.c   2008-01-02 13:56:38.000000000 -0500
-@@ -93,6 +93,10 @@
-                       const struct net_device *out,
-                       int (*okfn)(struct sk_buff *))
+ static struct page *new_node_page(struct page *page, unsigned long node, int **x)
  {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       dnrmg_send_peer(*pskb);
-       return NF_ACCEPT;
+-      return alloc_pages_node(node, GFP_HIGHUSER_MOVABLE, 0);
++      return alloc_pages_node(node, GFP_HIGHUSER, 0);
  }
-@@ -137,7 +141,8 @@
- {
-       int rv = 0;
  
--      dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, DNRNG_NLGRP_MAX,
-+      dnrmg = netlink_kernel_create(&init_net,
-+                                    NETLINK_DNRTMSG, DNRNG_NLGRP_MAX,
-                                     dnrmg_receive_user_sk, NULL, THIS_MODULE);
-       if (dnrmg == NULL) {
-               printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket");
-diff -Nurb linux-2.6.22-570/net/decnet/sysctl_net_decnet.c linux-2.6.22-590/net/decnet/sysctl_net_decnet.c
---- linux-2.6.22-570/net/decnet/sysctl_net_decnet.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/decnet/sysctl_net_decnet.c    2008-01-02 13:56:38.000000000 -0500
-@@ -259,7 +259,7 @@
+ /*
+@@ -710,8 +710,7 @@
+ {
+       struct vm_area_struct *vma = (struct vm_area_struct *)private;
  
-               devname[newlen] = 0;
+-      return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma,
+-                                      page_address_in_vma(page, vma));
++      return alloc_page_vma(GFP_HIGHUSER, vma, page_address_in_vma(page, vma));
+ }
+ #else
  
--              dev = dev_get_by_name(devname);
-+              dev = dev_get_by_name(&init_net, devname);
-               if (dev == NULL)
-                       return -ENODEV;
+@@ -1203,8 +1202,7 @@
  
-@@ -299,7 +299,7 @@
-               devname[*lenp] = 0;
-               strip_it(devname);
+ #ifdef CONFIG_HUGETLBFS
+ /* Return a zonelist suitable for a huge page allocation. */
+-struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr,
+-                                                      gfp_t gfp_flags)
++struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr)
+ {
+       struct mempolicy *pol = get_vma_policy(current, vma, addr);
  
--              dev = dev_get_by_name(devname);
-+              dev = dev_get_by_name(&init_net, devname);
-               if (dev == NULL)
-                       return -ENODEV;
+@@ -1212,7 +1210,7 @@
+               unsigned nid;
  
-diff -Nurb linux-2.6.22-570/net/econet/af_econet.c linux-2.6.22-590/net/econet/af_econet.c
---- linux-2.6.22-570/net/econet/af_econet.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/econet/af_econet.c    2008-01-02 13:56:38.000000000 -0500
-@@ -608,12 +608,15 @@
-  *    Create an Econet socket
+               nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT);
+-              return NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_flags);
++              return NODE_DATA(nid)->node_zonelists + gfp_zone(GFP_HIGHUSER);
+       }
+       return zonelist_policy(GFP_HIGHUSER, pol);
+ }
+@@ -1311,6 +1309,7 @@
+  * keeps mempolicies cpuset relative after its cpuset moves.  See
+  * further kernel/cpuset.c update_nodemask().
   */
++void *cpuset_being_rebound;
  
--static int econet_create(struct socket *sock, int protocol)
-+static int econet_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct sock *sk;
-       struct econet_sock *eo;
-       int err;
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
+ /* Slow path of a mempolicy copy */
+ struct mempolicy *__mpol_copy(struct mempolicy *old)
+@@ -1909,3 +1908,4 @@
+               m->version = (vma != priv->tail_vma) ? vma->vm_start : 0;
+       return 0;
+ }
 +
-       /* Econet only provides datagram services. */
-       if (sock->type != SOCK_DGRAM)
-               return -ESOCKTNOSUPPORT;
-@@ -621,7 +624,7 @@
-       sock->state = SS_UNCONNECTED;
+diff -Nurb linux-2.6.22-590/mm/migrate.c linux-2.6.22-570/mm/migrate.c
+--- linux-2.6.22-590/mm/migrate.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/migrate.c      2007-07-08 19:32:17.000000000 -0400
+@@ -761,8 +761,7 @@
  
-       err = -ENOBUFS;
--      sk = sk_alloc(PF_ECONET, GFP_KERNEL, &econet_proto, 1);
-+      sk = sk_alloc(net, PF_ECONET, GFP_KERNEL, &econet_proto, 1);
-       if (sk == NULL)
-               goto out;
+       *result = &pm->status;
  
-@@ -659,7 +662,7 @@
-       if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
-               return -EFAULT;
+-      return alloc_pages_node(pm->node,
+-                              GFP_HIGHUSER_MOVABLE | GFP_THISNODE, 0);
++      return alloc_pages_node(pm->node, GFP_HIGHUSER | GFP_THISNODE, 0);
+ }
  
--      if ((dev = dev_get_by_name(ifr.ifr_name)) == NULL)
-+      if ((dev = dev_get_by_name(&init_net, ifr.ifr_name)) == NULL)
-               return -ENODEV;
+ /*
+diff -Nurb linux-2.6.22-590/mm/mmap.c linux-2.6.22-570/mm/mmap.c
+--- linux-2.6.22-590/mm/mmap.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/mmap.c 2008-01-23 19:16:05.000000000 -0500
+@@ -202,17 +202,6 @@
+ }
  
-       sec = (struct sockaddr_ec *)&ifr.ifr_addr;
-@@ -1062,6 +1065,9 @@
-       struct sock *sk;
-       struct ec_device *edev = dev->ec_ptr;
+ /*
+- * Requires inode->i_mapping->i_mmap_lock
+- */
+-void __unlink_file_vma(struct vm_area_struct *vma)
+-{
+-      struct file *file = vma->vm_file;
+-      struct address_space *mapping = file->f_mapping;
+-
+-      __remove_shared_vm_struct(vma, file, mapping);
+-}
+-
+-/*
+  * Unlink a file-based vm structure from its prio_tree, to hide
+  * vma from rmap and vmtruncate before freeing its page tables.
+  */
+@@ -1034,7 +1023,7 @@
+               }
+       }
  
-+      if (dev->nd_net != &init_net)
-+              goto drop;
-+
-       if (skb->pkt_type == PACKET_OTHERHOST)
-               goto drop;
+-      error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
++      error = security_file_mmap(file, reqprot, prot, flags);
+       if (error)
+               return error;
+               
+@@ -1161,8 +1150,12 @@
+               vx_vmlocked_add(mm, len >> PAGE_SHIFT);
+               make_pages_present(addr, addr + len);
+       }
+-      if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK))
+-              make_pages_present(addr, addr + len);
++      if (flags & MAP_POPULATE) {
++              up_write(&mm->mmap_sem);
++              sys_remap_file_pages(addr, len, 0,
++                                      pgoff, flags & MAP_NONBLOCK);
++              down_write(&mm->mmap_sem);
++      }
+       return addr;
  
-@@ -1116,6 +1122,9 @@
-       struct net_device *dev = (struct net_device *)data;
-       struct ec_device *edev;
+ unmap_and_free_vma:
+diff -Nurb linux-2.6.22-590/mm/mremap.c linux-2.6.22-570/mm/mremap.c
+--- linux-2.6.22-590/mm/mremap.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/mremap.c       2008-01-23 19:16:05.000000000 -0500
+@@ -292,10 +292,6 @@
+               if ((addr <= new_addr) && (addr+old_len) > new_addr)
+                       goto out;
  
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       switch (msg) {
-       case NETDEV_UNREGISTER:
-               /* A device has gone down - kill any data we hold for it. */
-diff -Nurb linux-2.6.22-570/net/ieee80211/ieee80211_module.c linux-2.6.22-590/net/ieee80211/ieee80211_module.c
---- linux-2.6.22-570/net/ieee80211/ieee80211_module.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ieee80211/ieee80211_module.c  2008-01-02 13:56:38.000000000 -0500
-@@ -264,7 +264,7 @@
-       struct proc_dir_entry *e;
+-              ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
+-              if (ret)
+-                      goto out;
+-
+               ret = do_munmap(mm, new_addr, new_len);
+               if (ret)
+                       goto out;
+@@ -398,13 +394,8 @@
  
-       ieee80211_debug_level = debug;
--      ieee80211_proc = proc_mkdir(DRV_NAME, proc_net);
-+      ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
-       if (ieee80211_proc == NULL) {
-               IEEE80211_ERROR("Unable to create " DRV_NAME
-                               " proc directory\n");
-@@ -273,7 +273,7 @@
-       e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
-                             ieee80211_proc);
-       if (!e) {
--              remove_proc_entry(DRV_NAME, proc_net);
-+              remove_proc_entry(DRV_NAME, init_net.proc_net);
-               ieee80211_proc = NULL;
-               return -EIO;
-       }
-@@ -293,7 +293,7 @@
- #ifdef CONFIG_IEEE80211_DEBUG
-       if (ieee80211_proc) {
-               remove_proc_entry("debug_level", ieee80211_proc);
--              remove_proc_entry(DRV_NAME, proc_net);
-+              remove_proc_entry(DRV_NAME, init_net.proc_net);
-               ieee80211_proc = NULL;
+                       new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
+                                               vma->vm_pgoff, map_flags);
+-                      if (new_addr & ~PAGE_MASK) {
+                       ret = new_addr;
+-                              goto out;
+-                      }
+-
+-                      ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
+-                      if (ret)
++                      if (new_addr & ~PAGE_MASK)
+                               goto out;
+               }
+               ret = move_vma(vma, addr, old_len, new_len, new_addr);
+diff -Nurb linux-2.6.22-590/mm/nommu.c linux-2.6.22-570/mm/nommu.c
+--- linux-2.6.22-590/mm/nommu.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/nommu.c        2008-01-23 19:16:05.000000000 -0500
+@@ -639,7 +639,7 @@
        }
- #endif                                /* CONFIG_IEEE80211_DEBUG */
-diff -Nurb linux-2.6.22-570/net/ipv4/Kconfig linux-2.6.22-590/net/ipv4/Kconfig
---- linux-2.6.22-570/net/ipv4/Kconfig  2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/Kconfig  2008-01-02 13:56:38.000000000 -0500
-@@ -116,48 +116,6 @@
-         equal "cost" and chooses one of them in a non-deterministic fashion
-         if a matching packet arrives.
  
--config IP_ROUTE_MULTIPATH_CACHED
--      bool "IP: equal cost multipath with caching support (EXPERIMENTAL)"
--      depends on IP_ROUTE_MULTIPATH
--      help
--        Normally, equal cost multipath routing is not supported by the
--        routing cache. If you say Y here, alternative routes are cached
--        and on cache lookup a route is chosen in a configurable fashion.
+       /* allow the security API to have its say */
+-      ret = security_file_mmap(file, reqprot, prot, flags, addr, 0);
++      ret = security_file_mmap(file, reqprot, prot, flags);
+       if (ret < 0)
+               return ret;
+@@ -1336,7 +1336,8 @@
+       return 0;
+ }
+-struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
++struct page *filemap_nopage(struct vm_area_struct *area,
++                      unsigned long address, int *type)
+ {
+       BUG();
+       return NULL;
+diff -Nurb linux-2.6.22-590/mm/page_alloc.c linux-2.6.22-570/mm/page_alloc.c
+--- linux-2.6.22-590/mm/page_alloc.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/page_alloc.c   2008-01-23 19:16:05.000000000 -0500
+@@ -143,42 +143,6 @@
+ EXPORT_SYMBOL(nr_node_ids);
+ #endif
+-#ifdef CONFIG_PAGE_GROUP_BY_MOBILITY
+-static inline int get_pageblock_migratetype(struct page *page)
+-{
+-      return get_pageblock_flags_group(page, PB_migrate, PB_migrate_end);
+-}
 -
--        If unsure, say N.
+-static void set_pageblock_migratetype(struct page *page, int migratetype)
+-{
+-      set_pageblock_flags_group(page, (unsigned long)migratetype,
+-                                      PB_migrate, PB_migrate_end);
+-}
 -
--config IP_ROUTE_MULTIPATH_RR
--      tristate "MULTIPATH: round robin algorithm"
--      depends on IP_ROUTE_MULTIPATH_CACHED
--      help
--        Multipath routes are chosen according to Round Robin
+-static inline int gfpflags_to_migratetype(gfp_t gfp_flags)
+-{
+-      WARN_ON((gfp_flags & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK);
 -
--config IP_ROUTE_MULTIPATH_RANDOM
--      tristate "MULTIPATH: random algorithm"
--      depends on IP_ROUTE_MULTIPATH_CACHED
--      help
--        Multipath routes are chosen in a random fashion. Actually,
--        there is no weight for a route. The advantage of this policy
--        is that it is implemented stateless and therefore introduces only
--        a very small delay.
--
--config IP_ROUTE_MULTIPATH_WRANDOM
--      tristate "MULTIPATH: weighted random algorithm"
--      depends on IP_ROUTE_MULTIPATH_CACHED
--      help
--        Multipath routes are chosen in a weighted random fashion. 
--        The per route weights are the weights visible via ip route 2. As the
--        corresponding state management introduces some overhead routing delay
--        is increased.
--
--config IP_ROUTE_MULTIPATH_DRR
--      tristate "MULTIPATH: interface round robin algorithm"
--      depends on IP_ROUTE_MULTIPATH_CACHED
--      help
--        Connections are distributed in a round robin fashion over the
--        available interfaces. This policy makes sense if the connections 
--        should be primarily distributed on interfaces and not on routes. 
+-      return (((gfp_flags & __GFP_MOVABLE) != 0) << 1) |
+-              ((gfp_flags & __GFP_RECLAIMABLE) != 0);
+-}
 -
- config IP_ROUTE_VERBOSE
-       bool "IP: verbose route monitoring"
-       depends on IP_ADVANCED_ROUTER
-diff -Nurb linux-2.6.22-570/net/ipv4/Makefile linux-2.6.22-590/net/ipv4/Makefile
---- linux-2.6.22-570/net/ipv4/Makefile 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/Makefile 2008-01-02 13:56:38.000000000 -0500
-@@ -29,14 +29,9 @@
- obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
- obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
- obj-$(CONFIG_IP_PNP) += ipconfig.o
--obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
--obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
--obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o
--obj-$(CONFIG_IP_ROUTE_MULTIPATH_DRR) += multipath_drr.o
- obj-$(CONFIG_NETFILTER)       += netfilter.o netfilter/
- obj-$(CONFIG_IP_VS) += ipvs/
- obj-$(CONFIG_INET_DIAG) += inet_diag.o 
--obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
- obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
- obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
- obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
-diff -Nurb linux-2.6.22-570/net/ipv4/af_inet.c linux-2.6.22-590/net/ipv4/af_inet.c
---- linux-2.6.22-570/net/ipv4/af_inet.c        2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/af_inet.c        2008-01-02 13:56:38.000000000 -0500
-@@ -244,7 +244,7 @@
-  *    Create an inet socket.
-  */
--static int inet_create(struct socket *sock, int protocol)
-+static int inet_create(struct net *net, struct socket *sock, int protocol)
+-#else
+-static inline int get_pageblock_migratetype(struct page *page)
+-{
+-      return MIGRATE_UNMOVABLE;
+-}
+-
+-static void set_pageblock_migratetype(struct page *page, int migratetype)
+-{
+-}
+-
+-static inline int gfpflags_to_migratetype(gfp_t gfp_flags)
+-{
+-      return MIGRATE_UNMOVABLE;
+-}
+-#endif /* CONFIG_PAGE_GROUP_BY_MOBILITY */
+-
+ #ifdef CONFIG_DEBUG_VM
+ static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
  {
-       struct sock *sk;
-       struct list_head *p;
-@@ -310,6 +310,10 @@
-                       goto out_rcu_unlock;
-       }
+@@ -433,7 +397,6 @@
+ {
+       unsigned long page_idx;
+       int order_size = 1 << order;
+-      int migratetype = get_pageblock_migratetype(page);
  
-+      err = -EPROTONOSUPPORT;
-+      if (!(answer->flags & INET_PROTOSW_NETNS) && (net != &init_net))
-+              goto out_rcu_unlock;
-+
-       err = -EPERM;
-       if ((protocol == IPPROTO_ICMP) &&
-               nx_capable(answer->capability, NXC_RAW_ICMP))
-@@ -326,7 +330,7 @@
-       BUG_TRAP(answer_prot->slab != NULL);
+       if (unlikely(PageCompound(page)))
+               destroy_compound_page(page, order);
+@@ -446,6 +409,7 @@
+       __mod_zone_page_state(zone, NR_FREE_PAGES, order_size);
+       while (order < MAX_ORDER-1) {
+               unsigned long combined_idx;
++              struct free_area *area;
+               struct page *buddy;
  
-       err = -ENOBUFS;
--      sk = sk_alloc(PF_INET, GFP_KERNEL, answer_prot, 1);
-+      sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot, 1);
-       if (sk == NULL)
-               goto out;
+               buddy = __page_find_buddy(page, page_idx, order);
+@@ -453,7 +417,8 @@
+                       break;          /* Move the buddy up one level. */
  
-@@ -344,7 +348,7 @@
-                       inet->hdrincl = 1;
+               list_del(&buddy->lru);
+-              zone->free_area[order].nr_free--;
++              area = zone->free_area + order;
++              area->nr_free--;
+               rmv_page_order(buddy);
+               combined_idx = __find_combined_index(page_idx, order);
+               page = page + (combined_idx - page_idx);
+@@ -461,8 +426,7 @@
+               order++;
        }
--      if (ipv4_config.no_pmtu_disc)
-+      if (net->sysctl_ipv4_no_pmtu_disc)
-               inet->pmtudisc = IP_PMTUDISC_DONT;
-       else
-               inet->pmtudisc = IP_PMTUDISC_WANT;
-@@ -423,12 +427,12 @@
+       set_page_order(page, order);
+-      list_add(&page->lru,
+-              &zone->free_area[order].free_list[migratetype]);
++      list_add(&page->lru, &zone->free_area[order].free_list);
+       zone->free_area[order].nr_free++;
  }
  
- /* It is off by default, see below. */
--int sysctl_ip_nonlocal_bind __read_mostly;
- int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+@@ -602,8 +566,7 @@
+  * -- wli
+  */
+ static inline void expand(struct zone *zone, struct page *page,
+-      int low, int high, struct free_area *area,
+-      int migratetype)
++      int low, int high, struct free_area *area)
  {
-       struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
-       struct sock *sk = sock->sk;
-+      struct net *net = sk->sk_net;
-       struct inet_sock *inet = inet_sk(sk);
-       struct nx_v4_sock_addr nsa;
-       unsigned short snum;
-@@ -448,7 +452,7 @@
-       if (err)
-               goto out;
+       unsigned long size = 1 << high;
  
--      chk_addr_ret = inet_addr_type(nsa.saddr);
-+      chk_addr_ret = inet_addr_type(net, nsa.saddr);
+@@ -612,7 +575,7 @@
+               high--;
+               size >>= 1;
+               VM_BUG_ON(bad_range(zone, &page[size]));
+-              list_add(&page[size].lru, &area->free_list[migratetype]);
++              list_add(&page[size].lru, &area->free_list);
+               area->nr_free++;
+               set_page_order(&page[size], high);
+       }
+@@ -665,172 +628,31 @@
+       return 0;
+ }
  
-       /* Not specified by any standard per-se, however it breaks too
-        * many applications when removed.  It is unfortunate since
-@@ -458,7 +462,7 @@
-        *  is temporarily down)
-        */
-       err = -EADDRNOTAVAIL;
--      if (!sysctl_ip_nonlocal_bind &&
-+      if (!net->sysctl_ip_nonlocal_bind &&
-           !inet->freebind &&
-           nsa.saddr != INADDR_ANY &&
-           chk_addr_ret != RTN_LOCAL &&
-@@ -787,6 +791,7 @@
- int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+-#ifdef CONFIG_PAGE_GROUP_BY_MOBILITY
+-/*
+- * This array describes the order lists are fallen back to when
+- * the free lists for the desirable migrate type are depleted
+- */
+-static int fallbacks[MIGRATE_TYPES][MIGRATE_TYPES-1] = {
+-      [MIGRATE_UNMOVABLE]   = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE   },
+-      [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE,   MIGRATE_MOVABLE   },
+-      [MIGRATE_MOVABLE]     = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE },
+-};
+-
+-/*
+- * Move the free pages in a range to the free lists of the requested type.
+- * Note that start_page and end_pages are not aligned in a MAX_ORDER_NR_PAGES
+- * boundary. If alignment is required, use move_freepages_block()
+- */
+-int move_freepages(struct zone *zone,
+-                      struct page *start_page, struct page *end_page,
+-                      int migratetype)
+-{
+-      struct page *page;
+-      unsigned long order;
+-      int blocks_moved = 0;
+-
+-#ifndef CONFIG_HOLES_IN_ZONE
+-      /*
+-       * page_zone is not safe to call in this context when
+-       * CONFIG_HOLES_IN_ZONE is set. This bug check is probably redundant
+-       * anyway as we check zone boundaries in move_freepages_block().
+-       * Remove at a later date when no bug reports exist related to
+-       * CONFIG_PAGE_GROUP_BY_MOBILITY
+-       */
+-      BUG_ON(page_zone(start_page) != page_zone(end_page));
+-#endif
+-
+-      for (page = start_page; page <= end_page;) {
+-              if (!pfn_valid_within(page_to_pfn(page))) {
+-                      page++;
+-                      continue;
+-              }
+-
+-              if (!PageBuddy(page)) {
+-                      page++;
+-                      continue;
+-              }
+-
+-              order = page_order(page);
+-              list_del(&page->lru);
+-              list_add(&page->lru,
+-                      &zone->free_area[order].free_list[migratetype]);
+-              page += 1 << order;
+-              blocks_moved++;
+-      }
+-
+-      return blocks_moved;
+-}
+-
+-int move_freepages_block(struct zone *zone, struct page *page, int migratetype)
+-{
+-      unsigned long start_pfn, end_pfn;
+-      struct page *start_page, *end_page;
+-
+-      start_pfn = page_to_pfn(page);
+-      start_pfn = start_pfn & ~(MAX_ORDER_NR_PAGES-1);
+-      start_page = pfn_to_page(start_pfn);
+-      end_page = start_page + MAX_ORDER_NR_PAGES - 1;
+-      end_pfn = start_pfn + MAX_ORDER_NR_PAGES - 1;
+-
+-      /* Do not cross zone boundaries */
+-      if (start_pfn < zone->zone_start_pfn)
+-              start_page = page;
+-      if (end_pfn >= zone->zone_start_pfn + zone->spanned_pages)
+-              return 0;
+-
+-      return move_freepages(zone, start_page, end_page, migratetype);
+-}
+-
+-/* Remove an element from the buddy allocator from the fallback list */
+-static struct page *__rmqueue_fallback(struct zone *zone, int order,
+-                                              int start_migratetype)
+-{
+-      struct free_area * area;
+-      int current_order;
+-      struct page *page;
+-      int migratetype, i;
+-
+-      /* Find the largest possible block of pages in the other list */
+-      for (current_order = MAX_ORDER-1; current_order >= order;
+-                                              --current_order) {
+-              for (i = 0; i < MIGRATE_TYPES - 1; i++) {
+-                      migratetype = fallbacks[start_migratetype][i];
+-
+-                      area = &(zone->free_area[current_order]);
+-                      if (list_empty(&area->free_list[migratetype]))
+-                              continue;
+-
+-                      page = list_entry(area->free_list[migratetype].next,
+-                                      struct page, lru);
+-                      area->nr_free--;
+-
+-                      /*
+-                       * If breaking a large block of pages, move all free
+-                       * pages to the preferred allocation list
+-                       */
+-                      if (unlikely(current_order >= MAX_ORDER / 2)) {
+-                              migratetype = start_migratetype;
+-                              move_freepages_block(zone, page, migratetype);
+-                      }
+-
+-                      /* Remove the page from the freelists */
+-                      list_del(&page->lru);
+-                      rmv_page_order(page);
+-                      __mod_zone_page_state(zone, NR_FREE_PAGES,
+-                                                      -(1UL << order));
+-
+-                      if (current_order == MAX_ORDER - 1)
+-                              set_pageblock_migratetype(page,
+-                                                      start_migratetype);
+-
+-                      expand(zone, page, order, current_order, area, migratetype);
+-                      return page;
+-              }
+-      }
+-
+-      return NULL;
+-}
+-#else
+-static struct page *__rmqueue_fallback(struct zone *zone, int order,
+-                                              int start_migratetype)
+-{
+-      return NULL;
+-}
+-#endif /* CONFIG_PAGE_GROUP_BY_MOBILITY */
+-
+ /* 
+  * Do the hard work of removing an element from the buddy allocator.
+  * Call me with the zone->lock already held.
+  */
+-static struct page *__rmqueue(struct zone *zone, unsigned int order,
+-                                              int migratetype)
++static struct page *__rmqueue(struct zone *zone, unsigned int order)
  {
-       struct sock *sk = sock->sk;
-+      struct net *net = sk->sk_net;
-       int err = 0;
-       switch (cmd) {
-@@ -799,12 +804,12 @@
-               case SIOCADDRT:
-               case SIOCDELRT:
-               case SIOCRTMSG:
--                      err = ip_rt_ioctl(cmd, (void __user *)arg);
-+                      err = ip_rt_ioctl(net, cmd, (void __user *)arg);
-                       break;
-               case SIOCDARP:
-               case SIOCGARP:
-               case SIOCSARP:
--                      err = arp_ioctl(cmd, (void __user *)arg);
-+                      err = arp_ioctl(net, cmd, (void __user *)arg);
-                       break;
-               case SIOCGIFADDR:
-               case SIOCSIFADDR:
-@@ -817,7 +822,7 @@
-               case SIOCSIFPFLAGS:
-               case SIOCGIFPFLAGS:
-               case SIOCSIFFLAGS:
--                      err = devinet_ioctl(cmd, (void __user *)arg);
-+                      err = devinet_ioctl(net, cmd, (void __user *)arg);
-                       break;
-               default:
-                       if (sk->sk_prot->ioctl)
-@@ -927,7 +932,8 @@
-               .capability = -1,
-               .no_check =   0,
-               .flags =      INET_PROTOSW_PERMANENT |
--                            INET_PROTOSW_ICSK,
-+                            INET_PROTOSW_ICSK |
-+                            INET_PROTOSW_NETNS,
-       },
+       struct free_area * area;
+       unsigned int current_order;
+       struct page *page;
  
-       {
-@@ -937,7 +943,8 @@
-               .ops =        &inet_dgram_ops,
-               .capability = -1,
-               .no_check =   UDP_CSUM_DEFAULT,
--              .flags =      INET_PROTOSW_PERMANENT,
-+              .flags =      INET_PROTOSW_PERMANENT |
-+                            INET_PROTOSW_NETNS,
-        },
+-      /* Find a page of the appropriate size in the preferred list */
+       for (current_order = order; current_order < MAX_ORDER; ++current_order) {
+-              area = &(zone->free_area[current_order]);
+-              if (list_empty(&area->free_list[migratetype]))
++              area = zone->free_area + current_order;
++              if (list_empty(&area->free_list))
+                       continue;
  
+-              page = list_entry(area->free_list[migratetype].next,
+-                                                      struct page, lru);
++              page = list_entry(area->free_list.next, struct page, lru);
+               list_del(&page->lru);
+               rmv_page_order(page);
+               area->nr_free--;
+               __mod_zone_page_state(zone, NR_FREE_PAGES, - (1UL << order));
+-              expand(zone, page, order, current_order, area, migratetype);
+-              goto got_page;
++              expand(zone, page, order, current_order, area);
++              return page;
+       }
  
-@@ -948,7 +955,8 @@
-              .ops =        &inet_sockraw_ops,
-              .capability = CAP_NET_RAW,
-              .no_check =   UDP_CSUM_DEFAULT,
--             .flags =      INET_PROTOSW_REUSE,
-+             .flags =      INET_PROTOSW_REUSE |
-+                           INET_PROTOSW_NETNS,
-        }
- };
+-      page = __rmqueue_fallback(zone, order, migratetype);
+-
+-got_page:
+-
+-      return page;
++      return NULL;
+ }
  
-@@ -1029,8 +1037,6 @@
-  *      Shall we try to damage output packets if routing dev changes?
+ /* 
+@@ -839,18 +661,16 @@
+  * Returns the number of new pages which were placed at *list.
   */
--int sysctl_ip_dynaddr __read_mostly;
--
- static int inet_sk_reselect_saddr(struct sock *sk)
+ static int rmqueue_bulk(struct zone *zone, unsigned int order, 
+-                      unsigned long count, struct list_head *list,
+-                      int migratetype)
++                      unsigned long count, struct list_head *list)
  {
-       struct inet_sock *inet = inet_sk(sk);
-@@ -1059,7 +1065,7 @@
-       if (new_saddr == old_saddr)
-               return 0;
--      if (sysctl_ip_dynaddr > 1) {
-+      if (sk->sk_net->sysctl_ip_dynaddr > 1) {
-               printk(KERN_INFO "%s(): shifting inet->"
-                                "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
-                      __FUNCTION__,
-@@ -1098,6 +1104,7 @@
-               daddr = inet->opt->faddr;
+       int i;
+       
+       spin_lock(&zone->lock);
+       for (i = 0; i < count; ++i) {
+-              struct page *page = __rmqueue(zone, order, migratetype);
++              struct page *page = __rmqueue(zone, order);
+               if (unlikely(page == NULL))
+                       break;
+-              list_add(&page->lru, list);
+-              set_page_private(page, migratetype);
++              list_add_tail(&page->lru, list);
+       }
+       spin_unlock(&zone->lock);
+       return i;
+@@ -912,7 +732,7 @@
  {
-       struct flowi fl = {
-+              .fl_net = sk->sk_net,
-               .oif = sk->sk_bound_dev_if,
-               .nl_u = {
-                       .ip4_u = {
-@@ -1127,7 +1134,7 @@
-                * Other protocols have to map its equivalent state to TCP_SYN_SENT.
-                * DCCP maps its DCCP_REQUESTING state to TCP_SYN_SENT. -acme
-                */
--              if (!sysctl_ip_dynaddr ||
-+              if (!sk->sk_net->sysctl_ip_dynaddr ||
-                   sk->sk_state != TCP_SYN_SENT ||
-                   (sk->sk_userlocks & SOCK_BINDADDR_LOCK) ||
-                   (err = inet_sk_reselect_saddr(sk)) != 0)
-@@ -1183,6 +1190,9 @@
-       int ihl;
-       int id;
-+      if (!(features & NETIF_F_V4_CSUM))
-+              features &= ~NETIF_F_SG;
-+
-       if (unlikely(skb_shinfo(skb)->gso_type &
-                    ~(SKB_GSO_TCPV4 |
-                      SKB_GSO_UDP |
-@@ -1353,6 +1363,24 @@
-       .gso_segment = inet_gso_segment,
- };
+       unsigned long pfn, max_zone_pfn;
+       unsigned long flags;
+-      int order, t;
++      int order;
+       struct list_head *curr;
  
-+
-+static int inet_net_init(struct net *net)
-+{
-+      net->sysctl_ip_default_ttl = IPDEFTTL;
-+      net->sysctl_ip_dynaddr = 0;
-+
-+      return 0;
-+}
-+
-+static void inet_net_exit(struct net *net)
-+{
-+}
-+
-+static struct pernet_operations inet_net_ops = {
-+      .init = inet_net_init,
-+      .exit = inet_net_exit,
-+};
-+
- static int __init inet_init(void)
- {
-       struct sk_buff *dummy_skb;
-@@ -1374,6 +1402,10 @@
-       if (rc)
-               goto out_unregister_udp_proto;
+       if (!zone->spanned_pages)
+@@ -929,15 +749,15 @@
+                               swsusp_unset_page_free(page);
+               }
  
-+      rc = register_pernet_subsys(&inet_net_ops);
-+      if (rc)
-+              goto out_unregister_raw_proto;
-+
-       /*
-        *      Tell SOCKET that we are alive...
-        */
-@@ -1450,6 +1482,8 @@
-       rc = 0;
- out:
-       return rc;
-+out_unregister_raw_proto:
-+      proto_unregister(&raw_prot);
- out_unregister_udp_proto:
-       proto_unregister(&udp_prot);
- out_unregister_tcp_proto:
-@@ -1472,15 +1506,11 @@
-               goto out_tcp;
-       if (udp4_proc_init())
-               goto out_udp;
--      if (fib_proc_init())
--              goto out_fib;
-       if (ip_misc_proc_init())
-               goto out_misc;
- out:
-       return rc;
- out_misc:
--      fib_proc_exit();
--out_fib:
-       udp4_proc_exit();
- out_udp:
-       tcp4_proc_exit();
-@@ -1516,4 +1546,3 @@
- EXPORT_SYMBOL(inet_stream_ops);
- EXPORT_SYMBOL(inet_unregister_protosw);
- EXPORT_SYMBOL(net_statistics);
--EXPORT_SYMBOL(sysctl_ip_nonlocal_bind);
-diff -Nurb linux-2.6.22-570/net/ipv4/ah4.c linux-2.6.22-590/net/ipv4/ah4.c
---- linux-2.6.22-570/net/ipv4/ah4.c    2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/ah4.c    2008-01-02 13:56:38.000000000 -0500
-@@ -198,6 +198,9 @@
-       struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+(iph->ihl<<2));
-       struct xfrm_state *x;
+-      for_each_migratetype_order(order, t) {
+-              list_for_each(curr, &zone->free_area[order].free_list[t]) {
++      for (order = MAX_ORDER - 1; order >= 0; --order)
++              list_for_each(curr, &zone->free_area[order].free_list) {
+                       unsigned long i;
  
-+      if (skb->dev->nd_net != &init_net)
-+              return;
+                       pfn = page_to_pfn(list_entry(curr, struct page, lru));
+                       for (i = 0; i < (1UL << order); i++)
+                               swsusp_set_page_free(pfn_to_page(pfn + i));
+               }
+-      }
 +
-       if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH ||
-           icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
-               return;
-@@ -339,3 +342,4 @@
- module_init(ah4_init);
- module_exit(ah4_fini);
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_AH);
-diff -Nurb linux-2.6.22-570/net/ipv4/arp.c linux-2.6.22-590/net/ipv4/arp.c
---- linux-2.6.22-570/net/ipv4/arp.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/arp.c    2008-01-02 13:56:38.000000000 -0500
-@@ -109,6 +109,7 @@
- #include <net/protocol.h>
- #include <net/tcp.h>
- #include <net/sock.h>
-+#include <net/net_namespace.h>
- #include <net/arp.h>
- #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- #include <net/ax25.h>
-@@ -235,10 +236,11 @@
- {
-       __be32 addr = *(__be32*)neigh->primary_key;
-       struct net_device *dev = neigh->dev;
-+      struct net *net = dev->nd_net;
-       struct in_device *in_dev;
-       struct neigh_parms *parms;
--      neigh->type = inet_addr_type(addr);
-+      neigh->type = inet_addr_type(net, addr);
+       spin_unlock_irqrestore(&zone->lock, flags);
+ }
  
-       rcu_read_lock();
-       in_dev = __in_dev_get_rcu(dev);
-@@ -332,6 +334,7 @@
-       __be32 saddr = 0;
-       u8  *dst_ha = NULL;
-       struct net_device *dev = neigh->dev;
-+      struct net *net = dev->nd_net;
-       __be32 target = *(__be32*)neigh->primary_key;
-       int probes = atomic_read(&neigh->probes);
-       struct in_device *in_dev = in_dev_get(dev);
-@@ -342,14 +345,14 @@
-       switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
-       default:
-       case 0:         /* By default announce any local IP */
--              if (skb && inet_addr_type(ip_hdr(skb)->saddr) == RTN_LOCAL)
-+              if (skb && inet_addr_type(net, ip_hdr(skb)->saddr) == RTN_LOCAL)
-                       saddr = ip_hdr(skb)->saddr;
-               break;
-       case 1:         /* Restrict announcements of saddr in same subnet */
-               if (!skb)
-                       break;
-               saddr = ip_hdr(skb)->saddr;
--              if (inet_addr_type(saddr) == RTN_LOCAL) {
-+              if (inet_addr_type(net, saddr) == RTN_LOCAL) {
-                       /* saddr should be known to target */
-                       if (inet_addr_onlink(in_dev, target, saddr))
-                               break;
-@@ -386,6 +389,7 @@
- static int arp_ignore(struct in_device *in_dev, struct net_device *dev,
-                     __be32 sip, __be32 tip)
- {
-+      struct net *net = dev->nd_net;
-       int scope;
+@@ -977,7 +797,6 @@
+       local_irq_save(flags);
+       __count_vm_event(PGFREE);
+       list_add(&page->lru, &pcp->list);
+-      set_page_private(page, get_pageblock_migratetype(page));
+       pcp->count++;
+       if (pcp->count >= pcp->high) {
+               free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
+@@ -1027,7 +846,6 @@
+       struct page *page;
+       int cold = !!(gfp_flags & __GFP_COLD);
+       int cpu;
+-      int migratetype = gfpflags_to_migratetype(gfp_flags);
  
-       switch (IN_DEV_ARP_IGNORE(in_dev)) {
-@@ -416,13 +420,15 @@
-       default:
-               return 0;
+ again:
+       cpu  = get_cpu();
+@@ -1038,32 +856,16 @@
+               local_irq_save(flags);
+               if (!pcp->count) {
+                       pcp->count = rmqueue_bulk(zone, 0,
+-                                      pcp->batch, &pcp->list, migratetype);
++                                              pcp->batch, &pcp->list);
+                       if (unlikely(!pcp->count))
+                               goto failed;
+               }
+-
+-#ifdef CONFIG_PAGE_GROUP_BY_MOBILITY
+-              /* Find a page of the appropriate migrate type */
+-              list_for_each_entry(page, &pcp->list, lru)
+-                      if (page_private(page) == migratetype)
+-                              break;
+-
+-              /* Allocate more to the pcp list if necessary */
+-              if (unlikely(&page->lru == &pcp->list)) {
+-                      pcp->count += rmqueue_bulk(zone, 0,
+-                                      pcp->batch, &pcp->list, migratetype);
+-                      page = list_entry(pcp->list.next, struct page, lru);
+-              }
+-#else
+               page = list_entry(pcp->list.next, struct page, lru);
+-#endif /* CONFIG_PAGE_GROUP_BY_MOBILITY */
+-
+               list_del(&page->lru);
+               pcp->count--;
+       } else {
+               spin_lock_irqsave(&zone->lock, flags);
+-              page = __rmqueue(zone, order, migratetype);
++              page = __rmqueue(zone, order);
+               spin_unlock(&zone->lock);
+               if (!page)
+                       goto failed;
+@@ -2150,16 +1952,6 @@
+               init_page_count(page);
+               reset_page_mapcount(page);
+               SetPageReserved(page);
+-
+-              /*
+-               * Mark the block movable so that blocks are reserved for
+-               * movable at startup. This will force kernel allocations
+-               * to reserve their blocks rather than leaking throughout
+-               * the address space during boot when many long-lived
+-               * kernel allocations are made
+-               */
+-              set_pageblock_migratetype(page, MIGRATE_MOVABLE);
+-
+               INIT_LIST_HEAD(&page->lru);
+ #ifdef WANT_PAGE_VIRTUAL
+               /* The shift won't overflow because ZONE_NORMAL is below 4G. */
+@@ -2172,9 +1964,9 @@
+ void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone,
+                               unsigned long size)
+ {
+-      int order, t;
+-      for_each_migratetype_order(order, t) {
+-              INIT_LIST_HEAD(&zone->free_area[order].free_list[t]);
++      int order;
++      for (order = 0; order < MAX_ORDER ; order++) {
++              INIT_LIST_HEAD(&zone->free_area[order].free_list);
+               zone->free_area[order].nr_free = 0;
        }
--      return !inet_confirm_addr(dev, sip, tip, scope);
-+      return !inet_confirm_addr(net, dev, sip, tip, scope);
+ }
+@@ -2792,41 +2584,6 @@
+                                                       realtotalpages);
  }
  
- static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
- {
--      struct flowi fl = { .nl_u = { .ip4_u = { .daddr = sip,
--                                               .saddr = tip } } };
-+      struct flowi fl = {
-+              .fl_net = dev->nd_net,
-+              .nl_u = { .ip4_u = { .daddr = sip, .saddr = tip } }
-+      };
-       struct rtable *rt;
-       int flag = 0;
-       /*unsigned long now; */
-@@ -469,6 +475,7 @@
- int arp_find(unsigned char *haddr, struct sk_buff *skb)
- {
-       struct net_device *dev = skb->dev;
-+      struct net *net = dev->nd_net;
-       __be32 paddr;
-       struct neighbour *n;
+-#ifndef CONFIG_SPARSEMEM
+-/*
+- * Calculate the size of the zone->blockflags rounded to an unsigned long
+- * Start by making sure zonesize is a multiple of MAX_ORDER-1 by rounding up
+- * Then figure 1 NR_PAGEBLOCK_BITS worth of bits per MAX_ORDER-1, finally
+- * round what is now in bits to nearest long in bits, then return it in
+- * bytes.
+- */
+-static unsigned long __init usemap_size(unsigned long zonesize)
+-{
+-      unsigned long usemapsize;
+-
+-      usemapsize = roundup(zonesize, MAX_ORDER_NR_PAGES);
+-      usemapsize = usemapsize >> (MAX_ORDER-1);
+-      usemapsize *= NR_PAGEBLOCK_BITS;
+-      usemapsize = roundup(usemapsize, 8 * sizeof(unsigned long));
+-
+-      return usemapsize / 8;
+-}
+-
+-static void __init setup_usemap(struct pglist_data *pgdat,
+-                              struct zone *zone, unsigned long zonesize)
+-{
+-      unsigned long usemapsize = usemap_size(zonesize);
+-      zone->pageblock_flags = NULL;
+-      if (usemapsize) {
+-              zone->pageblock_flags = alloc_bootmem_node(pgdat, usemapsize);
+-              memset(zone->pageblock_flags, 0, usemapsize);
+-      }
+-}
+-#else
+-static void inline setup_usemap(struct pglist_data *pgdat,
+-                              struct zone *zone, unsigned long zonesize) {}
+-#endif /* CONFIG_SPARSEMEM */
+-
+ /*
+  * Set up the zone data structures:
+  *   - mark all pages reserved
+@@ -2907,7 +2664,6 @@
+               if (!size)
+                       continue;
  
-@@ -480,7 +487,7 @@
+-              setup_usemap(pgdat, zone, size);
+               ret = init_currently_empty_zone(zone, zone_start_pfn,
+                                               size, MEMMAP_EARLY);
+               BUG_ON(ret);
+@@ -3607,21 +3363,6 @@
+                       for (order = 0; ((1UL << order) << PAGE_SHIFT) < size; order++)
+                               ;
+                       table = (void*) __get_free_pages(GFP_ATOMIC, order);
+-                      /*
+-                       * If bucketsize is not a power-of-two, we may free
+-                       * some pages at the end of hash table.
+-                       */
+-                      if (table) {
+-                              unsigned long alloc_end = (unsigned long)table +
+-                                              (PAGE_SIZE << order);
+-                              unsigned long used = (unsigned long)table +
+-                                              PAGE_ALIGN(size);
+-                              split_page(virt_to_page(table), order);
+-                              while (used < alloc_end) {
+-                                      free_page(used);
+-                                      used += PAGE_SIZE;
+-                              }
+-                      }
+               }
+       } while (!table && size > PAGE_SIZE && --log2qty);
  
-       paddr = ((struct rtable*)skb->dst)->rt_gateway;
+@@ -3655,79 +3396,4 @@
+ EXPORT_SYMBOL(page_to_pfn);
+ #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
  
--      if (arp_set_predefined(inet_addr_type(paddr), haddr, paddr, dev))
-+      if (arp_set_predefined(inet_addr_type(net, paddr), haddr, paddr, dev))
-               return 0;
+-/* Return a pointer to the bitmap storing bits affecting a block of pages */
+-static inline unsigned long *get_pageblock_bitmap(struct zone *zone,
+-                                                      unsigned long pfn)
+-{
+-#ifdef CONFIG_SPARSEMEM
+-      return __pfn_to_section(pfn)->pageblock_flags;
+-#else
+-      return zone->pageblock_flags;
+-#endif /* CONFIG_SPARSEMEM */
+-}
  
-       n = __neigh_lookup(&arp_tbl, &paddr, dev, 1);
-@@ -704,6 +711,7 @@
- static int arp_process(struct sk_buff *skb)
+-static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn)
+-{
+-#ifdef CONFIG_SPARSEMEM
+-      pfn &= (PAGES_PER_SECTION-1);
+-      return (pfn >> (MAX_ORDER-1)) * NR_PAGEBLOCK_BITS;
+-#else
+-      pfn = pfn - zone->zone_start_pfn;
+-      return (pfn >> (MAX_ORDER-1)) * NR_PAGEBLOCK_BITS;
+-#endif /* CONFIG_SPARSEMEM */
+-}
+-
+-/**
+- * get_pageblock_flags_group - Return the requested group of flags for the MAX_ORDER_NR_PAGES block of pages
+- * @page: The page within the block of interest
+- * @start_bitidx: The first bit of interest to retrieve
+- * @end_bitidx: The last bit of interest
+- * returns pageblock_bits flags
+- */
+-unsigned long get_pageblock_flags_group(struct page *page,
+-                                      int start_bitidx, int end_bitidx)
+-{
+-      struct zone *zone;
+-      unsigned long *bitmap;
+-      unsigned long pfn, bitidx;
+-      unsigned long flags = 0;
+-      unsigned long value = 1;
+-
+-      zone = page_zone(page);
+-      pfn = page_to_pfn(page);
+-      bitmap = get_pageblock_bitmap(zone, pfn);
+-      bitidx = pfn_to_bitidx(zone, pfn);
+-
+-      for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)
+-              if (test_bit(bitidx + start_bitidx, bitmap))
+-                      flags |= value;
+-
+-      return flags;
+-}
+-
+-/**
+- * set_pageblock_flags_group - Set the requested group of flags for a MAX_ORDER_NR_PAGES block of pages
+- * @page: The page within the block of interest
+- * @start_bitidx: The first bit of interest
+- * @end_bitidx: The last bit of interest
+- * @flags: The flags to set
+- */
+-void set_pageblock_flags_group(struct page *page, unsigned long flags,
+-                                      int start_bitidx, int end_bitidx)
+-{
+-      struct zone *zone;
+-      unsigned long *bitmap;
+-      unsigned long pfn, bitidx;
+-      unsigned long value = 1;
+-
+-      zone = page_zone(page);
+-      pfn = page_to_pfn(page);
+-      bitmap = get_pageblock_bitmap(zone, pfn);
+-      bitidx = pfn_to_bitidx(zone, pfn);
+-
+-      for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)
+-              if (flags & value)
+-                      __set_bit(bitidx + start_bitidx, bitmap);
+-              else
+-                      __clear_bit(bitidx + start_bitidx, bitmap);
+-}
+diff -Nurb linux-2.6.22-590/mm/pdflush.c linux-2.6.22-570/mm/pdflush.c
+--- linux-2.6.22-590/mm/pdflush.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/pdflush.c      2007-07-08 19:32:17.000000000 -0400
+@@ -92,7 +92,6 @@
+ static int __pdflush(struct pdflush_work *my_work)
  {
-       struct net_device *dev = skb->dev;
-+      struct net *net = dev->nd_net;
-       struct in_device *in_dev = in_dev_get(dev);
-       struct arphdr *arp;
-       unsigned char *arp_ptr;
-@@ -824,7 +832,7 @@
-       /* Special case: IPv4 duplicate address detection packet (RFC2131) */
-       if (sip == 0) {
-               if (arp->ar_op == htons(ARPOP_REQUEST) &&
--                  inet_addr_type(tip) == RTN_LOCAL &&
-+                  inet_addr_type(net, tip) == RTN_LOCAL &&
-                   !arp_ignore(in_dev,dev,sip,tip))
-                       arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr);
-               goto out;
-@@ -854,7 +862,7 @@
-               } else if (IN_DEV_FORWARD(in_dev)) {
-                       if ((rt->rt_flags&RTCF_DNAT) ||
-                           (addr_type == RTN_UNICAST  && rt->u.dst.dev != dev &&
--                           (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, &tip, dev, 0)))) {
-+                           (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))) {
-                               n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
-                               if (n)
-                                       neigh_release(n);
-@@ -877,14 +885,14 @@
-       n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
--      if (IPV4_DEVCONF_ALL(ARP_ACCEPT)) {
-+      if (IPV4_DEVCONF_ALL(net, ARP_ACCEPT)) {
-               /* Unsolicited ARP is not accepted by default.
-                  It is possible, that this option should be enabled for some
-                  devices (strip is candidate)
-                */
-               if (n == NULL &&
-                   arp->ar_op == htons(ARPOP_REPLY) &&
--                  inet_addr_type(sip) == RTN_UNICAST)
-+                  inet_addr_type(net, sip) == RTN_UNICAST)
-                       n = __neigh_lookup(&arp_tbl, &sip, dev, -1);
-       }
+       current->flags |= PF_FLUSHER | PF_SWAPWRITE;
+-      set_freezable();
+       my_work->fn = NULL;
+       my_work->who = current;
+       INIT_LIST_HEAD(&my_work->list);
+diff -Nurb linux-2.6.22-590/mm/rmap.c linux-2.6.22-570/mm/rmap.c
+--- linux-2.6.22-590/mm/rmap.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/rmap.c 2008-01-23 19:16:05.000000000 -0500
+@@ -622,10 +622,8 @@
+                       printk (KERN_EMERG "  page->count = %x\n", page_count(page));
+                       printk (KERN_EMERG "  page->mapping = %p\n", page->mapping);
+                       print_symbol (KERN_EMERG "  vma->vm_ops = %s\n", (unsigned long)vma->vm_ops);
+-                      if (vma->vm_ops) {
++                      if (vma->vm_ops)
+                               print_symbol (KERN_EMERG "  vma->vm_ops->nopage = %s\n", (unsigned long)vma->vm_ops->nopage);
+-                              print_symbol (KERN_EMERG "  vma->vm_ops->fault = %s\n", (unsigned long)vma->vm_ops->fault);
+-                      }
+                       if (vma->vm_file && vma->vm_file->f_op)
+                               print_symbol (KERN_EMERG "  vma->vm_file->f_op->mmap = %s\n", (unsigned long)vma->vm_file->f_op->mmap);
+                       BUG();
+diff -Nurb linux-2.6.22-590/mm/shmem.c linux-2.6.22-570/mm/shmem.c
+--- linux-2.6.22-590/mm/shmem.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/shmem.c        2008-01-23 19:16:05.000000000 -0500
+@@ -81,7 +81,6 @@
+       SGP_READ,       /* don't exceed i_size, don't allocate page */
+       SGP_CACHE,      /* don't exceed i_size, may allocate page */
+       SGP_WRITE,      /* may exceed i_size, may allocate page */
+-      SGP_FAULT,      /* same as SGP_CACHE, return with page locked */
+ };
  
-@@ -966,7 +974,7 @@
-  *    Set (create) an ARP cache entry.
-  */
+ static int shmem_getpage(struct inode *inode, unsigned long idx,
+@@ -93,11 +92,8 @@
+        * The above definition of ENTRIES_PER_PAGE, and the use of
+        * BLOCKS_PER_PAGE on indirect pages, assume PAGE_CACHE_SIZE:
+        * might be reconsidered if it ever diverges from PAGE_SIZE.
+-       *
+-       * Mobility flags are masked out as swap vectors cannot move
+        */
+-      return alloc_pages((gfp_mask & ~GFP_MOVABLE_MASK) | __GFP_ZERO,
+-                              PAGE_CACHE_SHIFT-PAGE_SHIFT);
++      return alloc_pages(gfp_mask, PAGE_CACHE_SHIFT-PAGE_SHIFT);
+ }
  
--static int arp_req_set(struct arpreq *r, struct net_device * dev)
-+static int arp_req_set(struct net *net, struct arpreq *r, struct net_device * dev)
- {
-       __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
-       struct neighbour *neigh;
-@@ -977,17 +985,17 @@
-               if (mask && mask != htonl(0xFFFFFFFF))
-                       return -EINVAL;
-               if (!dev && (r->arp_flags & ATF_COM)) {
--                      dev = dev_getbyhwaddr(r->arp_ha.sa_family, r->arp_ha.sa_data);
-+                      dev = dev_getbyhwaddr(net, r->arp_ha.sa_family, r->arp_ha.sa_data);
-                       if (!dev)
-                               return -ENODEV;
-               }
-               if (mask) {
--                      if (pneigh_lookup(&arp_tbl, &ip, dev, 1) == NULL)
-+                      if (pneigh_lookup(&arp_tbl, net, &ip, dev, 1) == NULL)
-                               return -ENOBUFS;
-                       return 0;
-               }
-               if (dev == NULL) {
--                      IPV4_DEVCONF_ALL(PROXY_ARP) = 1;
-+                      IPV4_DEVCONF_ALL(net, PROXY_ARP) = 1;
-                       return 0;
+ static inline void shmem_dir_free(struct page *page)
+@@ -375,7 +371,7 @@
                }
-               if (__in_dev_get_rtnl(dev)) {
-@@ -1000,8 +1008,10 @@
-       if (r->arp_flags & ATF_PERM)
-               r->arp_flags |= ATF_COM;
-       if (dev == NULL) {
--              struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,
--                                                       .tos = RTO_ONLINK } } };
-+              struct flowi fl = { 
-+                      .fl_net = net,
-+                      .nl_u = { .ip4_u = { .daddr = ip, .tos = RTO_ONLINK } }
-+              };
-               struct rtable * rt;
-               if ((err = ip_route_output_key(&rt, &fl)) != 0)
-                       return err;
-@@ -1080,7 +1090,7 @@
-       return err;
- }
  
--static int arp_req_delete(struct arpreq *r, struct net_device * dev)
-+static int arp_req_delete(struct net *net, struct arpreq *r, struct net_device * dev)
- {
-       int err;
-       __be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
-@@ -1090,10 +1100,10 @@
-               __be32 mask =
-                      ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr;
-               if (mask == htonl(0xFFFFFFFF))
--                      return pneigh_delete(&arp_tbl, &ip, dev);
-+                      return pneigh_delete(&arp_tbl, net, &ip, dev);
-               if (mask == 0) {
-                       if (dev == NULL) {
--                              IPV4_DEVCONF_ALL(PROXY_ARP) = 0;
-+                              IPV4_DEVCONF_ALL(net, PROXY_ARP) = 0;
-                               return 0;
-                       }
-                       if (__in_dev_get_rtnl(dev)) {
-@@ -1107,8 +1117,10 @@
+               spin_unlock(&info->lock);
+-              page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping));
++              page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping) | __GFP_ZERO);
+               if (page)
+                       set_page_private(page, 0);
+               spin_lock(&info->lock);
+@@ -1114,10 +1110,6 @@
+       if (idx >= SHMEM_MAX_INDEX)
+               return -EFBIG;
+-
+-      if (type)
+-              *type = VM_FAULT_MINOR;
+-
+       /*
+        * Normally, filepage is NULL on entry, and either found
+        * uptodate immediately, or allocated and zeroed, or read
+@@ -1307,10 +1299,8 @@
+       }
+ done:
+       if (*pagep != filepage) {
+-              *pagep = filepage;
+-              if (sgp != SGP_FAULT)
+                       unlock_page(filepage);
+-
++              *pagep = filepage;
        }
+       return 0;
  
-       if (dev == NULL) {
--              struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,
--                                                       .tos = RTO_ONLINK } } };
-+              struct flowi fl = {
-+                      .fl_net = net,
-+                      .nl_u = { .ip4_u = { .daddr = ip, .tos = RTO_ONLINK } }
-+              };
-               struct rtable * rt;
-               if ((err = ip_route_output_key(&rt, &fl)) != 0)
-                       return err;
-@@ -1133,7 +1145,7 @@
-  *    Handle an ARP layer I/O control request.
-  */
+@@ -1322,31 +1312,74 @@
+       return error;
+ }
  
--int arp_ioctl(unsigned int cmd, void __user *arg)
-+int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
+-static struct page *shmem_fault(struct vm_area_struct *vma,
+-                                      struct fault_data *fdata)
++static struct page *shmem_nopage(struct vm_area_struct *vma,
++                               unsigned long address, int *type)
  {
-       int err;
-       struct arpreq r;
-@@ -1165,7 +1177,7 @@
-       rtnl_lock();
-       if (r.arp_dev[0]) {
-               err = -ENODEV;
--              if ((dev = __dev_get_by_name(r.arp_dev)) == NULL)
-+              if ((dev = __dev_get_by_name(net, r.arp_dev)) == NULL)
-                       goto out;
+       struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+       struct page *page = NULL;
++      unsigned long idx;
+       int error;
  
-               /* Mmmm... It is wrong... ARPHRD_NETROM==0 */
-@@ -1181,10 +1193,10 @@
+-      BUG_ON(!(vma->vm_flags & VM_CAN_INVALIDATE));
+-
+-      if (((loff_t)fdata->pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
+-              fdata->type = VM_FAULT_SIGBUS;
+-              return NULL;
+-              }
++      idx = (address - vma->vm_start) >> PAGE_SHIFT;
++      idx += vma->vm_pgoff;
++      idx >>= PAGE_CACHE_SHIFT - PAGE_SHIFT;
++      if (((loff_t) idx << PAGE_CACHE_SHIFT) >= i_size_read(inode))
++              return NOPAGE_SIGBUS;
+-      error = shmem_getpage(inode, fdata->pgoff, &page,
+-                                              SGP_FAULT, &fdata->type);
+-      if (error) {
+-              fdata->type = ((error == -ENOMEM)?VM_FAULT_OOM:VM_FAULT_SIGBUS);
+-              return NULL;
+-      }
++      error = shmem_getpage(inode, idx, &page, SGP_CACHE, type);
++      if (error)
++              return (error == -ENOMEM)? NOPAGE_OOM: NOPAGE_SIGBUS;
  
-       switch (cmd) {
-       case SIOCDARP:
--              err = arp_req_delete(&r, dev);
-+              err = arp_req_delete(net, &r, dev);
-               break;
-       case SIOCSARP:
--              err = arp_req_set(&r, dev);
-+              err = arp_req_set(net, &r, dev);
-               break;
-       case SIOCGARP:
-               err = arp_req_get(&r, dev);
-@@ -1201,6 +1213,9 @@
- {
-       struct net_device *dev = ptr;
+       mark_page_accessed(page);
+       return page;
+ }
  
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
++static int shmem_populate(struct vm_area_struct *vma,
++      unsigned long addr, unsigned long len,
++      pgprot_t prot, unsigned long pgoff, int nonblock)
++{
++      struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
++      struct mm_struct *mm = vma->vm_mm;
++      enum sgp_type sgp = nonblock? SGP_QUICK: SGP_CACHE;
++      unsigned long size;
 +
-       switch (event) {
-       case NETDEV_CHANGEADDR:
-               neigh_changeaddr(&arp_tbl, dev);
-@@ -1227,6 +1242,54 @@
++      size = (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
++      if (pgoff >= size || pgoff + (len >> PAGE_SHIFT) > size)
++              return -EINVAL;
++
++      while ((long) len > 0) {
++              struct page *page = NULL;
++              int err;
++              /*
++               * Will need changing if PAGE_CACHE_SIZE != PAGE_SIZE
++               */
++              err = shmem_getpage(inode, pgoff, &page, sgp, NULL);
++              if (err)
++                      return err;
++              /* Page may still be null, but only if nonblock was set. */
++              if (page) {
++                      mark_page_accessed(page);
++                      err = install_page(mm, vma, addr, page, prot);
++                      if (err) {
++                              page_cache_release(page);
++                              return err;
++                      }
++              } else if (vma->vm_flags & VM_NONLINEAR) {
++                      /* No page was found just because we can't read it in
++                       * now (being here implies nonblock != 0), but the page
++                       * may exist, so set the PTE to fault it in later. */
++                      err = install_file_pte(mm, vma, addr, pgoff, prot);
++                      if (err)
++                              return err;
++              }
++
++              len -= PAGE_SIZE;
++              addr += PAGE_SIZE;
++              pgoff++;
++      }
++      return 0;
++}
++
+ #ifdef CONFIG_NUMA
+ int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
+ {
+@@ -1391,7 +1424,6 @@
+ {
+       file_accessed(file);
+       vma->vm_ops = &shmem_vm_ops;
+-      vma->vm_flags |= VM_CAN_INVALIDATE | VM_CAN_NONLINEAR;
+       return 0;
  }
  
+@@ -2445,7 +2477,8 @@
+ };
  
-+static int arp_proc_init(struct net *net);
-+static void arp_proc_exit(struct net *net);
+ static struct vm_operations_struct shmem_vm_ops = {
+-      .fault          = shmem_fault,
++      .nopage         = shmem_nopage,
++      .populate       = shmem_populate,
+ #ifdef CONFIG_NUMA
+       .set_policy     = shmem_set_policy,
+       .get_policy     = shmem_get_policy,
+@@ -2581,6 +2614,5 @@
+               fput(vma->vm_file);
+       vma->vm_file = file;
+       vma->vm_ops = &shmem_vm_ops;
+-      vma->vm_flags |= VM_CAN_INVALIDATE;
+       return 0;
+ }
+diff -Nurb linux-2.6.22-590/mm/shmem.c.orig linux-2.6.22-570/mm/shmem.c.orig
+--- linux-2.6.22-590/mm/shmem.c.orig   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/mm/shmem.c.orig   2008-01-23 19:15:56.000000000 -0500
+@@ -0,0 +1,2619 @@
++/*
++ * Resizable virtual memory filesystem for Linux.
++ *
++ * Copyright (C) 2000 Linus Torvalds.
++ *             2000 Transmeta Corp.
++ *             2000-2001 Christoph Rohland
++ *             2000-2001 SAP AG
++ *             2002 Red Hat Inc.
++ * Copyright (C) 2002-2005 Hugh Dickins.
++ * Copyright (C) 2002-2005 VERITAS Software Corporation.
++ * Copyright (C) 2004 Andi Kleen, SuSE Labs
++ *
++ * Extended attribute support for tmpfs:
++ * Copyright (c) 2004, Luke Kenneth Casson Leighton <lkcl@lkcl.net>
++ * Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
++ *
++ * This file is released under the GPL.
++ */
++
++/*
++ * This virtual memory filesystem is heavily based on the ramfs. It
++ * extends ramfs by the ability to use swap and honor resource limits
++ * which makes it a completely usable filesystem.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/xattr.h>
++#include <linux/generic_acl.h>
++#include <linux/mm.h>
++#include <linux/mman.h>
++#include <linux/file.h>
++#include <linux/swap.h>
++#include <linux/pagemap.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/backing-dev.h>
++#include <linux/shmem_fs.h>
++#include <linux/mount.h>
++#include <linux/writeback.h>
++#include <linux/vfs.h>
++#include <linux/blkdev.h>
++#include <linux/security.h>
++#include <linux/swapops.h>
++#include <linux/mempolicy.h>
++#include <linux/namei.h>
++#include <linux/ctype.h>
++#include <linux/migrate.h>
++#include <linux/highmem.h>
++#include <linux/backing-dev.h>
++
++#include <asm/uaccess.h>
++#include <asm/div64.h>
++#include <asm/pgtable.h>
++
++/* This magic number is used in glibc for posix shared memory */
++#define TMPFS_MAGIC   0x01021994
++
++#define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))
++#define ENTRIES_PER_PAGEPAGE (ENTRIES_PER_PAGE*ENTRIES_PER_PAGE)
++#define BLOCKS_PER_PAGE  (PAGE_CACHE_SIZE/512)
++
++#define SHMEM_MAX_INDEX  (SHMEM_NR_DIRECT + (ENTRIES_PER_PAGEPAGE/2) * (ENTRIES_PER_PAGE+1))
++#define SHMEM_MAX_BYTES  ((unsigned long long)SHMEM_MAX_INDEX << PAGE_CACHE_SHIFT)
++
++#define VM_ACCT(size)    (PAGE_CACHE_ALIGN(size) >> PAGE_SHIFT)
++
++/* info->flags needs VM_flags to handle pagein/truncate races efficiently */
++#define SHMEM_PAGEIN   VM_READ
++#define SHMEM_TRUNCATE         VM_WRITE
++
++/* Definition to limit shmem_truncate's steps between cond_rescheds */
++#define LATENCY_LIMIT  64
++
++/* Pretend that each entry is of this size in directory's i_size */
++#define BOGO_DIRENT_SIZE 20
++
++/* Flag allocation requirements to shmem_getpage and shmem_swp_alloc */
++enum sgp_type {
++      SGP_QUICK,      /* don't try more than file page cache lookup */
++      SGP_READ,       /* don't exceed i_size, don't allocate page */
++      SGP_CACHE,      /* don't exceed i_size, may allocate page */
++      SGP_WRITE,      /* may exceed i_size, may allocate page */
++};
++
++static int shmem_getpage(struct inode *inode, unsigned long idx,
++                       struct page **pagep, enum sgp_type sgp, int *type);
++
++static inline struct page *shmem_dir_alloc(gfp_t gfp_mask)
++{
++      /*
++       * The above definition of ENTRIES_PER_PAGE, and the use of
++       * BLOCKS_PER_PAGE on indirect pages, assume PAGE_CACHE_SIZE:
++       * might be reconsidered if it ever diverges from PAGE_SIZE.
++       */
++      return alloc_pages(gfp_mask, PAGE_CACHE_SHIFT-PAGE_SHIFT);
++}
++
++static inline void shmem_dir_free(struct page *page)
++{
++      __free_pages(page, PAGE_CACHE_SHIFT-PAGE_SHIFT);
++}
++
++static struct page **shmem_dir_map(struct page *page)
++{
++      return (struct page **)kmap_atomic(page, KM_USER0);
++}
++
++static inline void shmem_dir_unmap(struct page **dir)
++{
++      kunmap_atomic(dir, KM_USER0);
++}
++
++static swp_entry_t *shmem_swp_map(struct page *page)
++{
++      return (swp_entry_t *)kmap_atomic(page, KM_USER1);
++}
++
++static inline void shmem_swp_balance_unmap(void)
++{
++      /*
++       * When passing a pointer to an i_direct entry, to code which
++       * also handles indirect entries and so will shmem_swp_unmap,
++       * we must arrange for the preempt count to remain in balance.
++       * What kmap_atomic of a lowmem page does depends on config
++       * and architecture, so pretend to kmap_atomic some lowmem page.
++       */
++      (void) kmap_atomic(ZERO_PAGE(0), KM_USER1);
++}
++
++static inline void shmem_swp_unmap(swp_entry_t *entry)
++{
++      kunmap_atomic(entry, KM_USER1);
++}
++
++static inline struct shmem_sb_info *SHMEM_SB(struct super_block *sb)
++{
++      return sb->s_fs_info;
++}
++
++/*
++ * shmem_file_setup pre-accounts the whole fixed size of a VM object,
++ * for shared memory and for shared anonymous (/dev/zero) mappings
++ * (unless MAP_NORESERVE and sysctl_overcommit_memory <= 1),
++ * consistent with the pre-accounting of private mappings ...
++ */
++static inline int shmem_acct_size(unsigned long flags, loff_t size)
++{
++      return (flags & VM_ACCOUNT)?
++              security_vm_enough_memory(VM_ACCT(size)): 0;
++}
++
++static inline void shmem_unacct_size(unsigned long flags, loff_t size)
++{
++      if (flags & VM_ACCOUNT)
++              vm_unacct_memory(VM_ACCT(size));
++}
++
++/*
++ * ... whereas tmpfs objects are accounted incrementally as
++ * pages are allocated, in order to allow huge sparse files.
++ * shmem_getpage reports shmem_acct_block failure as -ENOSPC not -ENOMEM,
++ * so that a failure on a sparse tmpfs mapping will give SIGBUS not OOM.
++ */
++static inline int shmem_acct_block(unsigned long flags)
++{
++      return (flags & VM_ACCOUNT)?
++              0: security_vm_enough_memory(VM_ACCT(PAGE_CACHE_SIZE));
++}
++
++static inline void shmem_unacct_blocks(unsigned long flags, long pages)
++{
++      if (!(flags & VM_ACCOUNT))
++              vm_unacct_memory(pages * VM_ACCT(PAGE_CACHE_SIZE));
++}
++
++static const struct super_operations shmem_ops;
++static const struct address_space_operations shmem_aops;
++static const struct file_operations shmem_file_operations;
++static const struct inode_operations shmem_inode_operations;
++static const struct inode_operations shmem_dir_inode_operations;
++static const struct inode_operations shmem_special_inode_operations;
++static struct vm_operations_struct shmem_vm_ops;
 +
++static struct backing_dev_info shmem_backing_dev_info  __read_mostly = {
++      .ra_pages       = 0,    /* No readahead */
++      .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
++      .unplug_io_fn   = default_unplug_io_fn,
++};
++
++static LIST_HEAD(shmem_swaplist);
++static DEFINE_SPINLOCK(shmem_swaplist_lock);
++
++static void shmem_free_blocks(struct inode *inode, long pages)
++{
++      struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
++      if (sbinfo->max_blocks) {
++              spin_lock(&sbinfo->stat_lock);
++              sbinfo->free_blocks += pages;
++              inode->i_blocks -= pages*BLOCKS_PER_PAGE;
++              spin_unlock(&sbinfo->stat_lock);
++      }
++}
++
++/*
++ * shmem_recalc_inode - recalculate the size of an inode
++ *
++ * @inode: inode to recalc
++ *
++ * We have to calculate the free blocks since the mm can drop
++ * undirtied hole pages behind our back.
++ *
++ * But normally   info->alloced == inode->i_mapping->nrpages + info->swapped
++ * So mm freed is info->alloced - (inode->i_mapping->nrpages + info->swapped)
++ *
++ * It has to be called with the spinlock held.
++ */
++static void shmem_recalc_inode(struct inode *inode)
++{
++      struct shmem_inode_info *info = SHMEM_I(inode);
++      long freed;
++
++      freed = info->alloced - info->swapped - inode->i_mapping->nrpages;
++      if (freed > 0) {
++              info->alloced -= freed;
++              shmem_unacct_blocks(info->flags, freed);
++              shmem_free_blocks(inode, freed);
++      }
++}
++
++/*
++ * shmem_swp_entry - find the swap vector position in the info structure
++ *
++ * @info:  info structure for the inode
++ * @index: index of the page to find
++ * @page:  optional page to add to the structure. Has to be preset to
++ *         all zeros
++ *
++ * If there is no space allocated yet it will return NULL when
++ * page is NULL, else it will use the page for the needed block,
++ * setting it to NULL on return to indicate that it has been used.
++ *
++ * The swap vector is organized the following way:
++ *
++ * There are SHMEM_NR_DIRECT entries directly stored in the
++ * shmem_inode_info structure. So small files do not need an addional
++ * allocation.
++ *
++ * For pages with index > SHMEM_NR_DIRECT there is the pointer
++ * i_indirect which points to a page which holds in the first half
++ * doubly indirect blocks, in the second half triple indirect blocks:
++ *
++ * For an artificial ENTRIES_PER_PAGE = 4 this would lead to the
++ * following layout (for SHMEM_NR_DIRECT == 16):
++ *
++ * i_indirect -> dir --> 16-19
++ *          |      +-> 20-23
++ *          |
++ *          +-->dir2 --> 24-27
++ *          |        +-> 28-31
++ *          |        +-> 32-35
++ *          |        +-> 36-39
++ *          |
++ *          +-->dir3 --> 40-43
++ *                   +-> 44-47
++ *                   +-> 48-51
++ *                   +-> 52-55
++ */
++static swp_entry_t *shmem_swp_entry(struct shmem_inode_info *info, unsigned long index, struct page **page)
++{
++      unsigned long offset;
++      struct page **dir;
++      struct page *subdir;
++
++      if (index < SHMEM_NR_DIRECT) {
++              shmem_swp_balance_unmap();
++              return info->i_direct+index;
++      }
++      if (!info->i_indirect) {
++              if (page) {
++                      info->i_indirect = *page;
++                      *page = NULL;
++              }
++              return NULL;                    /* need another page */
++      }
++
++      index -= SHMEM_NR_DIRECT;
++      offset = index % ENTRIES_PER_PAGE;
++      index /= ENTRIES_PER_PAGE;
++      dir = shmem_dir_map(info->i_indirect);
++
++      if (index >= ENTRIES_PER_PAGE/2) {
++              index -= ENTRIES_PER_PAGE/2;
++              dir += ENTRIES_PER_PAGE/2 + index/ENTRIES_PER_PAGE;
++              index %= ENTRIES_PER_PAGE;
++              subdir = *dir;
++              if (!subdir) {
++                      if (page) {
++                              *dir = *page;
++                              *page = NULL;
++                      }
++                      shmem_dir_unmap(dir);
++                      return NULL;            /* need another page */
++              }
++              shmem_dir_unmap(dir);
++              dir = shmem_dir_map(subdir);
++      }
++
++      dir += index;
++      subdir = *dir;
++      if (!subdir) {
++              if (!page || !(subdir = *page)) {
++                      shmem_dir_unmap(dir);
++                      return NULL;            /* need a page */
++              }
++              *dir = subdir;
++              *page = NULL;
++      }
++      shmem_dir_unmap(dir);
++      return shmem_swp_map(subdir) + offset;
++}
++
++static void shmem_swp_set(struct shmem_inode_info *info, swp_entry_t *entry, unsigned long value)
++{
++      long incdec = value? 1: -1;
++
++      entry->val = value;
++      info->swapped += incdec;
++      if ((unsigned long)(entry - info->i_direct) >= SHMEM_NR_DIRECT) {
++              struct page *page = kmap_atomic_to_page(entry);
++              set_page_private(page, page_private(page) + incdec);
++      }
++}
++
++/*
++ * shmem_swp_alloc - get the position of the swap entry for the page.
++ *                   If it does not exist allocate the entry.
++ *
++ * @info:     info structure for the inode
++ * @index:    index of the page to find
++ * @sgp:      check and recheck i_size? skip allocation?
++ */
++static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long index, enum sgp_type sgp)
++{
++      struct inode *inode = &info->vfs_inode;
++      struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
++      struct page *page = NULL;
++      swp_entry_t *entry;
++
++      if (sgp != SGP_WRITE &&
++          ((loff_t) index << PAGE_CACHE_SHIFT) >= i_size_read(inode))
++              return ERR_PTR(-EINVAL);
++
++      while (!(entry = shmem_swp_entry(info, index, &page))) {
++              if (sgp == SGP_READ)
++                      return shmem_swp_map(ZERO_PAGE(0));
++              /*
++               * Test free_blocks against 1 not 0, since we have 1 data
++               * page (and perhaps indirect index pages) yet to allocate:
++               * a waste to allocate index if we cannot allocate data.
++               */
++              if (sbinfo->max_blocks) {
++                      spin_lock(&sbinfo->stat_lock);
++                      if (sbinfo->free_blocks <= 1) {
++                              spin_unlock(&sbinfo->stat_lock);
++                              return ERR_PTR(-ENOSPC);
++                      }
++                      sbinfo->free_blocks--;
++                      inode->i_blocks += BLOCKS_PER_PAGE;
++                      spin_unlock(&sbinfo->stat_lock);
++              }
++
++              spin_unlock(&info->lock);
++              page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping) | __GFP_ZERO);
++              if (page)
++                      set_page_private(page, 0);
++              spin_lock(&info->lock);
++
++              if (!page) {
++                      shmem_free_blocks(inode, 1);
++                      return ERR_PTR(-ENOMEM);
++              }
++              if (sgp != SGP_WRITE &&
++                  ((loff_t) index << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
++                      entry = ERR_PTR(-EINVAL);
++                      break;
++              }
++              if (info->next_index <= index)
++                      info->next_index = index + 1;
++      }
++      if (page) {
++              /* another task gave its page, or truncated the file */
++              shmem_free_blocks(inode, 1);
++              shmem_dir_free(page);
++      }
++      if (info->next_index <= index && !IS_ERR(entry))
++              info->next_index = index + 1;
++      return entry;
++}
++
++/*
++ * shmem_free_swp - free some swap entries in a directory
++ *
++ * @dir:        pointer to the directory
++ * @edir:       pointer after last entry of the directory
++ * @punch_lock: pointer to spinlock when needed for the holepunch case
++ */
++static int shmem_free_swp(swp_entry_t *dir, swp_entry_t *edir,
++                                              spinlock_t *punch_lock)
++{
++      spinlock_t *punch_unlock = NULL;
++      swp_entry_t *ptr;
++      int freed = 0;
++
++      for (ptr = dir; ptr < edir; ptr++) {
++              if (ptr->val) {
++                      if (unlikely(punch_lock)) {
++                              punch_unlock = punch_lock;
++                              punch_lock = NULL;
++                              spin_lock(punch_unlock);
++                              if (!ptr->val)
++                                      continue;
++                      }
++                      free_swap_and_cache(*ptr);
++                      *ptr = (swp_entry_t){0};
++                      freed++;
++              }
++      }
++      if (punch_unlock)
++              spin_unlock(punch_unlock);
++      return freed;
++}
++
++static int shmem_map_and_free_swp(struct page *subdir, int offset,
++              int limit, struct page ***dir, spinlock_t *punch_lock)
++{
++      swp_entry_t *ptr;
++      int freed = 0;
++
++      ptr = shmem_swp_map(subdir);
++      for (; offset < limit; offset += LATENCY_LIMIT) {
++              int size = limit - offset;
++              if (size > LATENCY_LIMIT)
++                      size = LATENCY_LIMIT;
++              freed += shmem_free_swp(ptr+offset, ptr+offset+size,
++                                                      punch_lock);
++              if (need_resched()) {
++                      shmem_swp_unmap(ptr);
++                      if (*dir) {
++                              shmem_dir_unmap(*dir);
++                              *dir = NULL;
++                      }
++                      cond_resched();
++                      ptr = shmem_swp_map(subdir);
++              }
++      }
++      shmem_swp_unmap(ptr);
++      return freed;
++}
++
++static void shmem_free_pages(struct list_head *next)
++{
++      struct page *page;
++      int freed = 0;
++
++      do {
++              page = container_of(next, struct page, lru);
++              next = next->next;
++              shmem_dir_free(page);
++              freed++;
++              if (freed >= LATENCY_LIMIT) {
++                      cond_resched();
++                      freed = 0;
++              }
++      } while (next);
++}
++
++static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end)
++{
++      struct shmem_inode_info *info = SHMEM_I(inode);
++      unsigned long idx;
++      unsigned long size;
++      unsigned long limit;
++      unsigned long stage;
++      unsigned long diroff;
++      struct page **dir;
++      struct page *topdir;
++      struct page *middir;
++      struct page *subdir;
++      swp_entry_t *ptr;
++      LIST_HEAD(pages_to_free);
++      long nr_pages_to_free = 0;
++      long nr_swaps_freed = 0;
++      int offset;
++      int freed;
++      int punch_hole;
++      spinlock_t *needs_lock;
++      spinlock_t *punch_lock;
++      unsigned long upper_limit;
++
++      inode->i_ctime = inode->i_mtime = CURRENT_TIME;
++      idx = (start + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
++      if (idx >= info->next_index)
++              return;
++
++      spin_lock(&info->lock);
++      info->flags |= SHMEM_TRUNCATE;
++      if (likely(end == (loff_t) -1)) {
++              limit = info->next_index;
++              upper_limit = SHMEM_MAX_INDEX;
++              info->next_index = idx;
++              needs_lock = NULL;
++              punch_hole = 0;
++      } else {
++              if (end + 1 >= inode->i_size) { /* we may free a little more */
++                      limit = (inode->i_size + PAGE_CACHE_SIZE - 1) >>
++                                                      PAGE_CACHE_SHIFT;
++                      upper_limit = SHMEM_MAX_INDEX;
++              } else {
++                      limit = (end + 1) >> PAGE_CACHE_SHIFT;
++                      upper_limit = limit;
++              }
++              needs_lock = &info->lock;
++              punch_hole = 1;
++      }
++
++      topdir = info->i_indirect;
++      if (topdir && idx <= SHMEM_NR_DIRECT && !punch_hole) {
++              info->i_indirect = NULL;
++              nr_pages_to_free++;
++              list_add(&topdir->lru, &pages_to_free);
++      }
++      spin_unlock(&info->lock);
++
++      if (info->swapped && idx < SHMEM_NR_DIRECT) {
++              ptr = info->i_direct;
++              size = limit;
++              if (size > SHMEM_NR_DIRECT)
++                      size = SHMEM_NR_DIRECT;
++              nr_swaps_freed = shmem_free_swp(ptr+idx, ptr+size, needs_lock);
++      }
++
++      /*
++       * If there are no indirect blocks or we are punching a hole
++       * below indirect blocks, nothing to be done.
++       */
++      if (!topdir || limit <= SHMEM_NR_DIRECT)
++              goto done2;
++
++      /*
++       * The truncation case has already dropped info->lock, and we're safe
++       * because i_size and next_index have already been lowered, preventing
++       * access beyond.  But in the punch_hole case, we still need to take
++       * the lock when updating the swap directory, because there might be
++       * racing accesses by shmem_getpage(SGP_CACHE), shmem_unuse_inode or
++       * shmem_writepage.  However, whenever we find we can remove a whole
++       * directory page (not at the misaligned start or end of the range),
++       * we first NULLify its pointer in the level above, and then have no
++       * need to take the lock when updating its contents: needs_lock and
++       * punch_lock (either pointing to info->lock or NULL) manage this.
++       */
++
++      upper_limit -= SHMEM_NR_DIRECT;
++      limit -= SHMEM_NR_DIRECT;
++      idx = (idx > SHMEM_NR_DIRECT)? (idx - SHMEM_NR_DIRECT): 0;
++      offset = idx % ENTRIES_PER_PAGE;
++      idx -= offset;
++
++      dir = shmem_dir_map(topdir);
++      stage = ENTRIES_PER_PAGEPAGE/2;
++      if (idx < ENTRIES_PER_PAGEPAGE/2) {
++              middir = topdir;
++              diroff = idx/ENTRIES_PER_PAGE;
++      } else {
++              dir += ENTRIES_PER_PAGE/2;
++              dir += (idx - ENTRIES_PER_PAGEPAGE/2)/ENTRIES_PER_PAGEPAGE;
++              while (stage <= idx)
++                      stage += ENTRIES_PER_PAGEPAGE;
++              middir = *dir;
++              if (*dir) {
++                      diroff = ((idx - ENTRIES_PER_PAGEPAGE/2) %
++                              ENTRIES_PER_PAGEPAGE) / ENTRIES_PER_PAGE;
++                      if (!diroff && !offset && upper_limit >= stage) {
++                              if (needs_lock) {
++                                      spin_lock(needs_lock);
++                                      *dir = NULL;
++                                      spin_unlock(needs_lock);
++                                      needs_lock = NULL;
++                              } else
++                                      *dir = NULL;
++                              nr_pages_to_free++;
++                              list_add(&middir->lru, &pages_to_free);
++                      }
++                      shmem_dir_unmap(dir);
++                      dir = shmem_dir_map(middir);
++              } else {
++                      diroff = 0;
++                      offset = 0;
++                      idx = stage;
++              }
++      }
++
++      for (; idx < limit; idx += ENTRIES_PER_PAGE, diroff++) {
++              if (unlikely(idx == stage)) {
++                      shmem_dir_unmap(dir);
++                      dir = shmem_dir_map(topdir) +
++                          ENTRIES_PER_PAGE/2 + idx/ENTRIES_PER_PAGEPAGE;
++                      while (!*dir) {
++                              dir++;
++                              idx += ENTRIES_PER_PAGEPAGE;
++                              if (idx >= limit)
++                                      goto done1;
++                      }
++                      stage = idx + ENTRIES_PER_PAGEPAGE;
++                      middir = *dir;
++                      if (punch_hole)
++                              needs_lock = &info->lock;
++                      if (upper_limit >= stage) {
++                              if (needs_lock) {
++                                      spin_lock(needs_lock);
++                                      *dir = NULL;
++                                      spin_unlock(needs_lock);
++                                      needs_lock = NULL;
++                              } else
++                                      *dir = NULL;
++                              nr_pages_to_free++;
++                              list_add(&middir->lru, &pages_to_free);
++                      }
++                      shmem_dir_unmap(dir);
++                      cond_resched();
++                      dir = shmem_dir_map(middir);
++                      diroff = 0;
++              }
++              punch_lock = needs_lock;
++              subdir = dir[diroff];
++              if (subdir && !offset && upper_limit-idx >= ENTRIES_PER_PAGE) {
++                      if (needs_lock) {
++                              spin_lock(needs_lock);
++                              dir[diroff] = NULL;
++                              spin_unlock(needs_lock);
++                              punch_lock = NULL;
++                      } else
++                              dir[diroff] = NULL;
++                      nr_pages_to_free++;
++                      list_add(&subdir->lru, &pages_to_free);
++              }
++              if (subdir && page_private(subdir) /* has swap entries */) {
++                      size = limit - idx;
++                      if (size > ENTRIES_PER_PAGE)
++                              size = ENTRIES_PER_PAGE;
++                      freed = shmem_map_and_free_swp(subdir,
++                                      offset, size, &dir, punch_lock);
++                      if (!dir)
++                              dir = shmem_dir_map(middir);
++                      nr_swaps_freed += freed;
++                      if (offset || punch_lock) {
++                              spin_lock(&info->lock);
++                              set_page_private(subdir,
++                                      page_private(subdir) - freed);
++                              spin_unlock(&info->lock);
++                      } else
++                              BUG_ON(page_private(subdir) != freed);
++              }
++              offset = 0;
++      }
++done1:
++      shmem_dir_unmap(dir);
++done2:
++      if (inode->i_mapping->nrpages && (info->flags & SHMEM_PAGEIN)) {
++              /*
++               * Call truncate_inode_pages again: racing shmem_unuse_inode
++               * may have swizzled a page in from swap since vmtruncate or
++               * generic_delete_inode did it, before we lowered next_index.
++               * Also, though shmem_getpage checks i_size before adding to
++               * cache, no recheck after: so fix the narrow window there too.
++               *
++               * Recalling truncate_inode_pages_range and unmap_mapping_range
++               * every time for punch_hole (which never got a chance to clear
++               * SHMEM_PAGEIN at the start of vmtruncate_range) is expensive,
++               * yet hardly ever necessary: try to optimize them out later.
++               */
++              truncate_inode_pages_range(inode->i_mapping, start, end);
++              if (punch_hole)
++                      unmap_mapping_range(inode->i_mapping, start,
++                                                      end - start, 1);
++      }
++
++      spin_lock(&info->lock);
++      info->flags &= ~SHMEM_TRUNCATE;
++      info->swapped -= nr_swaps_freed;
++      if (nr_pages_to_free)
++              shmem_free_blocks(inode, nr_pages_to_free);
++      shmem_recalc_inode(inode);
++      spin_unlock(&info->lock);
++
++      /*
++       * Empty swap vector directory pages to be freed?
++       */
++      if (!list_empty(&pages_to_free)) {
++              pages_to_free.prev->next = NULL;
++              shmem_free_pages(pages_to_free.next);
++      }
++}
++
++static void shmem_truncate(struct inode *inode)
++{
++      shmem_truncate_range(inode, inode->i_size, (loff_t)-1);
++}
 +
-+static int arp_net_init(struct net *net)
++static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
 +{
++      struct inode *inode = dentry->d_inode;
++      struct page *page = NULL;
 +      int error;
-+      if ((error = arp_proc_init(net)))
-+              goto out_proc;
 +
-+      error = -ENOMEM;
-+      net->arp_neigh_parms_default = neigh_parms_alloc_default(&arp_tbl, net);
-+      if (!net->arp_neigh_parms_default)
-+              goto out_parm;
++      if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
++              if (attr->ia_size < inode->i_size) {
++                      /*
++                       * If truncating down to a partial page, then
++                       * if that page is already allocated, hold it
++                       * in memory until the truncation is over, so
++                       * truncate_partial_page cannnot miss it were
++                       * it assigned to swap.
++                       */
++                      if (attr->ia_size & (PAGE_CACHE_SIZE-1)) {
++                              (void) shmem_getpage(inode,
++                                      attr->ia_size>>PAGE_CACHE_SHIFT,
++                                              &page, SGP_READ, NULL);
++                      }
++                      /*
++                       * Reset SHMEM_PAGEIN flag so that shmem_truncate can
++                       * detect if any pages might have been added to cache
++                       * after truncate_inode_pages.  But we needn't bother
++                       * if it's being fully truncated to zero-length: the
++                       * nrpages check is efficient enough in that case.
++                       */
++                      if (attr->ia_size) {
++                              struct shmem_inode_info *info = SHMEM_I(inode);
++                              spin_lock(&info->lock);
++                              info->flags &= ~SHMEM_PAGEIN;
++                              spin_unlock(&info->lock);
++                      }
++              }
++      }
 +
-+#ifdef CONFIG_SYSCTL
-+      if ((error = neigh_sysctl_register(
-+                   NULL, net->arp_neigh_parms_default,
-+                   NET_IPV4, NET_IPV4_NEIGH, "ipv4", NULL, NULL)))
-+              goto out_sysctl;
++      error = inode_change_ok(inode, attr);
++      if (!error)
++              error = inode_setattr(inode, attr);
++#ifdef CONFIG_TMPFS_POSIX_ACL
++      if (!error && (attr->ia_valid & ATTR_MODE))
++              error = generic_acl_chmod(inode, &shmem_acl_ops);
 +#endif
++      if (page)
++              page_cache_release(page);
++      return error;
++}
++
++static void shmem_delete_inode(struct inode *inode)
++{
++      struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
++      struct shmem_inode_info *info = SHMEM_I(inode);
++
++      if (inode->i_op->truncate == shmem_truncate) {
++              truncate_inode_pages(inode->i_mapping, 0);
++              shmem_unacct_size(info->flags, inode->i_size);
++              inode->i_size = 0;
++              shmem_truncate(inode);
++              if (!list_empty(&info->swaplist)) {
++                      spin_lock(&shmem_swaplist_lock);
++                      list_del_init(&info->swaplist);
++                      spin_unlock(&shmem_swaplist_lock);
++              }
++      }
++      BUG_ON(inode->i_blocks);
++      if (sbinfo->max_inodes) {
++              spin_lock(&sbinfo->stat_lock);
++              sbinfo->free_inodes++;
++              spin_unlock(&sbinfo->stat_lock);
++      }
++      clear_inode(inode);
++}
++
++static inline int shmem_find_swp(swp_entry_t entry, swp_entry_t *dir, swp_entry_t *edir)
++{
++      swp_entry_t *ptr;
++
++      for (ptr = dir; ptr < edir; ptr++) {
++              if (ptr->val == entry.val)
++                      return ptr - dir;
++      }
++      return -1;
++}
++
++static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, struct page *page)
++{
++      struct inode *inode;
++      unsigned long idx;
++      unsigned long size;
++      unsigned long limit;
++      unsigned long stage;
++      struct page **dir;
++      struct page *subdir;
++      swp_entry_t *ptr;
++      int offset;
++
++      idx = 0;
++      ptr = info->i_direct;
++      spin_lock(&info->lock);
++      limit = info->next_index;
++      size = limit;
++      if (size > SHMEM_NR_DIRECT)
++              size = SHMEM_NR_DIRECT;
++      offset = shmem_find_swp(entry, ptr, ptr+size);
++      if (offset >= 0) {
++              shmem_swp_balance_unmap();
++              goto found;
++      }
++      if (!info->i_indirect)
++              goto lost2;
++
++      dir = shmem_dir_map(info->i_indirect);
++      stage = SHMEM_NR_DIRECT + ENTRIES_PER_PAGEPAGE/2;
++
++      for (idx = SHMEM_NR_DIRECT; idx < limit; idx += ENTRIES_PER_PAGE, dir++) {
++              if (unlikely(idx == stage)) {
++                      shmem_dir_unmap(dir-1);
++                      dir = shmem_dir_map(info->i_indirect) +
++                          ENTRIES_PER_PAGE/2 + idx/ENTRIES_PER_PAGEPAGE;
++                      while (!*dir) {
++                              dir++;
++                              idx += ENTRIES_PER_PAGEPAGE;
++                              if (idx >= limit)
++                                      goto lost1;
++                      }
++                      stage = idx + ENTRIES_PER_PAGEPAGE;
++                      subdir = *dir;
++                      shmem_dir_unmap(dir);
++                      dir = shmem_dir_map(subdir);
++              }
++              subdir = *dir;
++              if (subdir && page_private(subdir)) {
++                      ptr = shmem_swp_map(subdir);
++                      size = limit - idx;
++                      if (size > ENTRIES_PER_PAGE)
++                              size = ENTRIES_PER_PAGE;
++                      offset = shmem_find_swp(entry, ptr, ptr+size);
++                      if (offset >= 0) {
++                              shmem_dir_unmap(dir);
++                              goto found;
++                      }
++                      shmem_swp_unmap(ptr);
++              }
++      }
++lost1:
++      shmem_dir_unmap(dir-1);
++lost2:
++      spin_unlock(&info->lock);
++      return 0;
++found:
++      idx += offset;
++      inode = &info->vfs_inode;
++      if (move_from_swap_cache(page, idx, inode->i_mapping) == 0) {
++              info->flags |= SHMEM_PAGEIN;
++              shmem_swp_set(info, ptr + offset, 0);
++      }
++      shmem_swp_unmap(ptr);
++      spin_unlock(&info->lock);
++      /*
++       * Decrement swap count even when the entry is left behind:
++       * try_to_unuse will skip over mms, then reincrement count.
++       */
++      swap_free(entry);
++      return 1;
++}
++
++/*
++ * shmem_unuse() search for an eventually swapped out shmem page.
++ */
++int shmem_unuse(swp_entry_t entry, struct page *page)
++{
++      struct list_head *p, *next;
++      struct shmem_inode_info *info;
++      int found = 0;
++
++      spin_lock(&shmem_swaplist_lock);
++      list_for_each_safe(p, next, &shmem_swaplist) {
++              info = list_entry(p, struct shmem_inode_info, swaplist);
++              if (!info->swapped)
++                      list_del_init(&info->swaplist);
++              else if (shmem_unuse_inode(info, entry, page)) {
++                      /* move head to start search for next from here */
++                      list_move_tail(&shmem_swaplist, &info->swaplist);
++                      found = 1;
++                      break;
++              }
++      }
++      spin_unlock(&shmem_swaplist_lock);
++      return found;
++}
++
++/*
++ * Move the page from the page cache to the swap cache.
++ */
++static int shmem_writepage(struct page *page, struct writeback_control *wbc)
++{
++      struct shmem_inode_info *info;
++      swp_entry_t *entry, swap;
++      struct address_space *mapping;
++      unsigned long index;
++      struct inode *inode;
 +
++      BUG_ON(!PageLocked(page));
++      /*
++       * shmem_backing_dev_info's capabilities prevent regular writeback or
++       * sync from ever calling shmem_writepage; but a stacking filesystem
++       * may use the ->writepage of its underlying filesystem, in which case
++       * we want to do nothing when that underlying filesystem is tmpfs
++       * (writing out to swap is useful as a response to memory pressure, but
++       * of no use to stabilize the data) - just redirty the page, unlock it
++       * and claim success in this case.  AOP_WRITEPAGE_ACTIVATE, and the
++       * page_mapped check below, must be avoided unless we're in reclaim.
++       */
++      if (!wbc->for_reclaim) {
++              set_page_dirty(page);
++              unlock_page(page);
++              return 0;
++      }
++      BUG_ON(page_mapped(page));
++
++      mapping = page->mapping;
++      index = page->index;
++      inode = mapping->host;
++      info = SHMEM_I(inode);
++      if (info->flags & VM_LOCKED)
++              goto redirty;
++      swap = get_swap_page();
++      if (!swap.val)
++              goto redirty;
++
++      spin_lock(&info->lock);
++      shmem_recalc_inode(inode);
++      if (index >= info->next_index) {
++              BUG_ON(!(info->flags & SHMEM_TRUNCATE));
++              goto unlock;
++      }
++      entry = shmem_swp_entry(info, index, NULL);
++      BUG_ON(!entry);
++      BUG_ON(entry->val);
++
++      if (move_to_swap_cache(page, swap) == 0) {
++              shmem_swp_set(info, entry, swap.val);
++              shmem_swp_unmap(entry);
++              spin_unlock(&info->lock);
++              if (list_empty(&info->swaplist)) {
++                      spin_lock(&shmem_swaplist_lock);
++                      /* move instead of add in case we're racing */
++                      list_move_tail(&info->swaplist, &shmem_swaplist);
++                      spin_unlock(&shmem_swaplist_lock);
++              }
++              unlock_page(page);
++              return 0;
++      }
++
++      shmem_swp_unmap(entry);
++unlock:
++      spin_unlock(&info->lock);
++      swap_free(swap);
++redirty:
++      set_page_dirty(page);
++      return AOP_WRITEPAGE_ACTIVATE;  /* Return with the page locked */
++}
++
++#ifdef CONFIG_NUMA
++static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_nodes)
++{
++      char *nodelist = strchr(value, ':');
++      int err = 1;
++
++      if (nodelist) {
++              /* NUL-terminate policy string */
++              *nodelist++ = '\0';
++              if (nodelist_parse(nodelist, *policy_nodes))
++                      goto out;
++              if (!nodes_subset(*policy_nodes, node_online_map))
++                      goto out;
++      }
++      if (!strcmp(value, "default")) {
++              *policy = MPOL_DEFAULT;
++              /* Don't allow a nodelist */
++              if (!nodelist)
++                      err = 0;
++      } else if (!strcmp(value, "prefer")) {
++              *policy = MPOL_PREFERRED;
++              /* Insist on a nodelist of one node only */
++              if (nodelist) {
++                      char *rest = nodelist;
++                      while (isdigit(*rest))
++                              rest++;
++                      if (!*rest)
++                              err = 0;
++              }
++      } else if (!strcmp(value, "bind")) {
++              *policy = MPOL_BIND;
++              /* Insist on a nodelist */
++              if (nodelist)
++                      err = 0;
++      } else if (!strcmp(value, "interleave")) {
++              *policy = MPOL_INTERLEAVE;
++              /* Default to nodes online if no nodelist */
++              if (!nodelist)
++                      *policy_nodes = node_online_map;
++              err = 0;
++      }
 +out:
-+      return error;
++      /* Restore string for error message */
++      if (nodelist)
++              *--nodelist = ':';
++      return err;
++}
 +
-+#ifdef CONFIG_SYSCTL
-+out_sysctl:
-+      neigh_parms_release(&arp_tbl, net->arp_neigh_parms_default);
-+#endif
-+out_parm:
-+      arp_proc_exit(net);
-+out_proc:
-+      goto out;
++static struct page *shmem_swapin_async(struct shared_policy *p,
++                                     swp_entry_t entry, unsigned long idx)
++{
++      struct page *page;
++      struct vm_area_struct pvma;
++
++      /* Create a pseudo vma that just contains the policy */
++      memset(&pvma, 0, sizeof(struct vm_area_struct));
++      pvma.vm_end = PAGE_SIZE;
++      pvma.vm_pgoff = idx;
++      pvma.vm_policy = mpol_shared_policy_lookup(p, idx);
++      page = read_swap_cache_async(entry, &pvma, 0);
++      mpol_free(pvma.vm_policy);
++      return page;
 +}
 +
-+static void arp_net_exit(struct net *net)
++struct page *shmem_swapin(struct shmem_inode_info *info, swp_entry_t entry,
++                        unsigned long idx)
 +{
-+#ifdef CONFIG_SYSCTL
-+      neigh_sysctl_unregister(net->arp_neigh_parms_default);
-+#endif
-+      neigh_parms_release(&arp_tbl, net->arp_neigh_parms_default);
-+      arp_proc_exit(net);
++      struct shared_policy *p = &info->policy;
++      int i, num;
++      struct page *page;
++      unsigned long offset;
++
++      num = valid_swaphandles(entry, &offset);
++      for (i = 0; i < num; offset++, i++) {
++              page = shmem_swapin_async(p,
++                              swp_entry(swp_type(entry), offset), idx);
++              if (!page)
++                      break;
++              page_cache_release(page);
++      }
++      lru_add_drain();        /* Push any new pages onto the LRU now */
++      return shmem_swapin_async(p, entry, idx);
 +}
 +
-+static struct pernet_operations arp_net_ops = {
-+      .init = arp_net_init,
-+      .exit = arp_net_exit,
-+};
- /*
-  *    Called once on startup.
-  */
-@@ -1236,18 +1299,12 @@
-       .func = arp_rcv,
- };
--static int arp_proc_init(void);
--
- void __init arp_init(void)
- {
-       neigh_table_init(&arp_tbl);
-       dev_add_pack(&arp_packet_type);
--      arp_proc_init();
--#ifdef CONFIG_SYSCTL
--      neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4,
--                            NET_IPV4_NEIGH, "ipv4", NULL, NULL);
--#endif
-+      register_pernet_subsys(&arp_net_ops);
-       register_netdevice_notifier(&arp_netdev_notifier);
- }
-@@ -1383,6 +1440,8 @@
-       seq          = file->private_data;
-       seq->private = s;
-+      s->net = get_net(PROC_NET(inode));
++static struct page *
++shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info,
++               unsigned long idx)
++{
++      struct vm_area_struct pvma;
++      struct page *page;
 +
- out:
-       return rc;
- out_kfree:
-@@ -1390,28 +1449,46 @@
-       goto out;
- }
-+static int arp_seq_release(struct inode *inode, struct file *file)
++      memset(&pvma, 0, sizeof(struct vm_area_struct));
++      pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx);
++      pvma.vm_pgoff = idx;
++      pvma.vm_end = PAGE_SIZE;
++      page = alloc_page_vma(gfp | __GFP_ZERO, &pvma, 0);
++      mpol_free(pvma.vm_policy);
++      return page;
++}
++#else
++static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_nodes)
 +{
-+      struct seq_file *seq = file->private_data;
-+      struct neigh_seq_state *state = seq->private;
-+      put_net(state->net);
-+      return seq_release_private(inode, file);
++      return 1;
 +}
 +
- static const struct file_operations arp_seq_fops = {
-       .owner          = THIS_MODULE,
-       .open           = arp_seq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
--      .release        = seq_release_private,
-+      .release        = arp_seq_release,
- };
--static int __init arp_proc_init(void)
-+static int arp_proc_init(struct net *net)
- {
--      if (!proc_net_fops_create("arp", S_IRUGO, &arp_seq_fops))
-+      if (!proc_net_fops_create(net, "arp", S_IRUGO, &arp_seq_fops))
-               return -ENOMEM;
-       return 0;
- }
-+static void arp_proc_exit(struct net *net)
++static inline struct page *
++shmem_swapin(struct shmem_inode_info *info,swp_entry_t entry,unsigned long idx)
 +{
-+      proc_net_remove(net, "arp");
++      swapin_readahead(entry, 0, NULL);
++      return read_swap_cache_async(entry, NULL, 0);
 +}
 +
- #else /* CONFIG_PROC_FS */
--static int __init arp_proc_init(void)
-+static int arp_proc_init(struct net *net)
- {
-       return 0;
- }
-+static void arp_proc_exit(struct net *net)
++static inline struct page *
++shmem_alloc_page(gfp_t gfp,struct shmem_inode_info *info, unsigned long idx)
 +{
-+      return;
++      return alloc_page(gfp | __GFP_ZERO);
 +}
++#endif
 +
- #endif /* CONFIG_PROC_FS */
- EXPORT_SYMBOL(arp_broken_ops);
-diff -Nurb linux-2.6.22-570/net/ipv4/devinet.c linux-2.6.22-590/net/ipv4/devinet.c
---- linux-2.6.22-570/net/ipv4/devinet.c        2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/devinet.c        2008-01-02 13:56:38.000000000 -0500
-@@ -63,7 +63,7 @@
- #include <net/ip_fib.h>
- #include <net/rtnetlink.h>
--struct ipv4_devconf ipv4_devconf = {
-+static struct ipv4_devconf ipv4_devconf_template = {
-       .data = {
-               [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
-               [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
-@@ -72,7 +72,7 @@
-       },
- };
--static struct ipv4_devconf ipv4_devconf_dflt = {
-+static struct ipv4_devconf ipv4_devconf_dflt_template = {
-       .data = {
-               [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
-               [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
-@@ -82,7 +82,7 @@
-       },
- };
--#define IPV4_DEVCONF_DFLT(attr) IPV4_DEVCONF(ipv4_devconf_dflt, attr)
-+#define IPV4_DEVCONF_DFLT(net, attr) IPV4_DEVCONF(*((net)->ipv4_devconf_dflt), attr)
- static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = {
-       [IFA_LOCAL]             = { .type = NLA_U32 },
-@@ -98,7 +98,7 @@
- static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
-                        int destroy);
- #ifdef CONFIG_SYSCTL
--static void devinet_sysctl_register(struct in_device *in_dev,
-+static void devinet_sysctl_register(struct net *net, struct in_device *in_dev,
-                                   struct ipv4_devconf *p);
- static void devinet_sysctl_unregister(struct ipv4_devconf *p);
- #endif
-@@ -149,6 +149,7 @@
- static struct in_device *inetdev_init(struct net_device *dev)
- {
-+      struct net *net = dev->nd_net;
-       struct in_device *in_dev;
-       ASSERT_RTNL();
-@@ -157,7 +158,7 @@
-       if (!in_dev)
-               goto out;
-       INIT_RCU_HEAD(&in_dev->rcu_head);
--      memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf));
-+      memcpy(&in_dev->cnf, &net->ipv4_devconf_dflt, sizeof(in_dev->cnf));
-       in_dev->cnf.sysctl = NULL;
-       in_dev->dev = dev;
-       if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL)
-@@ -173,7 +174,7 @@
-       in_dev_hold(in_dev);
- #ifdef CONFIG_SYSCTL
--      devinet_sysctl_register(in_dev, &in_dev->cnf);
-+      devinet_sysctl_register(net, in_dev, &in_dev->cnf);
- #endif
-       ip_mc_init_dev(in_dev);
-       if (dev->flags & IFF_UP)
-@@ -203,8 +204,6 @@
-       ASSERT_RTNL();
-       dev = in_dev->dev;
--      if (dev == &loopback_dev)
--              return;
-       in_dev->dead = 1;
-@@ -415,12 +414,12 @@
-       return inet_insert_ifa(ifa);
- }
--struct in_device *inetdev_by_index(int ifindex)
-+struct in_device *inetdev_by_index(struct net *net, int ifindex)
- {
-       struct net_device *dev;
-       struct in_device *in_dev = NULL;
-       read_lock(&dev_base_lock);
--      dev = __dev_get_by_index(ifindex);
-+      dev = __dev_get_by_index(net, ifindex);
-       if (dev)
-               in_dev = in_dev_get(dev);
-       read_unlock(&dev_base_lock);
-@@ -444,6 +443,7 @@
- static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct nlattr *tb[IFA_MAX+1];
-       struct in_device *in_dev;
-       struct ifaddrmsg *ifm;
-@@ -457,7 +457,7 @@
-               goto errout;
-       ifm = nlmsg_data(nlh);
--      in_dev = inetdev_by_index(ifm->ifa_index);
-+      in_dev = inetdev_by_index(net, ifm->ifa_index);
-       if (in_dev == NULL) {
-               err = -ENODEV;
-               goto errout;
-@@ -488,7 +488,7 @@
-       return err;
- }
--static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
-+static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh)
- {
-       struct nlattr *tb[IFA_MAX+1];
-       struct in_ifaddr *ifa;
-@@ -507,7 +507,7 @@
-               goto errout;
-       }
--      dev = __dev_get_by_index(ifm->ifa_index);
-+      dev = __dev_get_by_index(net, ifm->ifa_index);
-       if (dev == NULL) {
-               err = -ENODEV;
-               goto errout;
-@@ -564,11 +564,12 @@
- static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct in_ifaddr *ifa;
-       ASSERT_RTNL();
--      ifa = rtm_to_ifaddr(nlh);
-+      ifa = rtm_to_ifaddr(net, nlh);
-       if (IS_ERR(ifa))
-               return PTR_ERR(ifa);
-@@ -600,7 +601,7 @@
- }
--int devinet_ioctl(unsigned int cmd, void __user *arg)
-+int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
- {
-       struct ifreq ifr;
-       struct sockaddr_in sin_orig;
-@@ -629,7 +630,7 @@
-               *colon = 0;
- #ifdef CONFIG_KMOD
--      dev_load(ifr.ifr_name);
-+      dev_load(net, ifr.ifr_name);
- #endif
-       switch (cmd) {
-@@ -670,7 +671,7 @@
-       rtnl_lock();
-       ret = -ENODEV;
--      if ((dev = __dev_get_by_name(ifr.ifr_name)) == NULL)
-+      if ((dev = __dev_get_by_name(net, ifr.ifr_name)) == NULL)
-               goto done;
-       if (colon)
-@@ -889,6 +890,7 @@
- __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
- {
-+      struct net *net = dev->nd_net;
-       __be32 addr = 0;
-       struct in_device *in_dev;
-@@ -919,7 +921,7 @@
-        */
-       read_lock(&dev_base_lock);
-       rcu_read_lock();
--      for_each_netdev(dev) {
-+      for_each_netdev(net, dev) {
-               if ((in_dev = __in_dev_get_rcu(dev)) == NULL)
-                       continue;
-@@ -982,7 +984,7 @@
-  * - local: address, 0=autoselect the local address
-  * - scope: maximum allowed scope value for the local address
-  */
--__be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope)
-+__be32 inet_confirm_addr(struct net *net, const struct net_device *dev, __be32 dst, __be32 local, int scope)
- {
-       __be32 addr = 0;
-       struct in_device *in_dev;
-@@ -998,7 +1000,7 @@
-       read_lock(&dev_base_lock);
-       rcu_read_lock();
--      for_each_netdev(dev) {
-+      for_each_netdev(net, dev) {
-               if ((in_dev = __in_dev_get_rcu(dev))) {
-                       addr = confirm_addr_indev(in_dev, dst, local, scope);
-                       if (addr)
-@@ -1059,6 +1061,7 @@
-                        void *ptr)
- {
-       struct net_device *dev = ptr;
-+      struct net *net = dev->nd_net;
-       struct in_device *in_dev = __in_dev_get_rtnl(dev);
-       ASSERT_RTNL();
-@@ -1066,7 +1069,7 @@
-       if (!in_dev) {
-               if (event == NETDEV_REGISTER) {
-                       in_dev = inetdev_init(dev);
--                      if (dev == &loopback_dev) {
-+                      if (dev == &net->loopback_dev) {
-                               if (!in_dev)
-                                       panic("devinet: "
-                                             "Failed to create loopback\n");
-@@ -1085,7 +1088,7 @@
-       case NETDEV_UP:
-               if (dev->mtu < 68)
-                       break;
--              if (dev == &loopback_dev) {
-+              if (dev == &net->loopback_dev) {
-                       struct in_ifaddr *ifa;
-                       if ((ifa = inet_alloc_ifa()) != NULL) {
-                               ifa->ifa_local =
-@@ -1122,7 +1125,7 @@
-               neigh_sysctl_unregister(in_dev->arp_parms);
-               neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
-                                     NET_IPV4_NEIGH, "ipv4", NULL, NULL);
--              devinet_sysctl_register(in_dev, &in_dev->cnf);
-+              devinet_sysctl_register(net, in_dev, &in_dev->cnf);
- #endif
-               break;
-       }
-@@ -1185,6 +1188,7 @@
- static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
- {
-+      struct net *net = skb->sk->sk_net;
-       int idx, ip_idx;
-       struct net_device *dev;
-       struct in_device *in_dev;
-@@ -1194,7 +1198,7 @@
-       s_ip_idx = ip_idx = cb->args[1];
-       idx = 0;
--      for_each_netdev(dev) {
-+      for_each_netdev(net, dev) {
-               if (idx < s_idx)
-                       goto cont;
-               if (idx > s_idx)
-@@ -1228,6 +1232,7 @@
-                     u32 pid)
- {
-       struct sk_buff *skb;
-+      struct net *net = ifa->ifa_dev->dev->nd_net;
-       u32 seq = nlh ? nlh->nlmsg_seq : 0;
-       int err = -ENOBUFS;
-@@ -1242,25 +1247,25 @@
-               kfree_skb(skb);
-               goto errout;
-       }
--      err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
-+      err = rtnl_notify(skb, net, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
- errout:
-       if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_IPV4_IFADDR, err);
-+              rtnl_set_sk_err(net, RTNLGRP_IPV4_IFADDR, err);
- }
- #ifdef CONFIG_SYSCTL
--static void devinet_copy_dflt_conf(int i)
-+static void devinet_copy_dflt_conf(struct net *net, int i)
- {
-       struct net_device *dev;
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(net, dev) {
-               struct in_device *in_dev;
-               rcu_read_lock();
-               in_dev = __in_dev_get_rcu(dev);
-               if (in_dev && !test_bit(i, in_dev->cnf.state))
--                      in_dev->cnf.data[i] = ipv4_devconf_dflt.data[i];
-+                      in_dev->cnf.data[i] = net->ipv4_devconf_dflt->data[i];
-               rcu_read_unlock();
-       }
-       read_unlock(&dev_base_lock);
-@@ -1274,12 +1279,13 @@
-       if (write) {
-               struct ipv4_devconf *cnf = ctl->extra1;
-+              struct net *net = ctl->extra2;
-               int i = (int *)ctl->data - cnf->data;
-               set_bit(i, cnf->state);
--              if (cnf == &ipv4_devconf_dflt)
--                      devinet_copy_dflt_conf(i);
-+              if (cnf == net->ipv4_devconf_dflt)
-+                      devinet_copy_dflt_conf(net, i);
-       }
-       return ret;
-@@ -1291,6 +1297,7 @@
- {
-       struct ipv4_devconf *cnf;
-       int *valp = table->data;
-+      struct net *net;
-       int new;
-       int i;
-@@ -1325,26 +1332,27 @@
-       *valp = new;
-       cnf = table->extra1;
-+      net = table->extra2;
-       i = (int *)table->data - cnf->data;
-       set_bit(i, cnf->state);
--      if (cnf == &ipv4_devconf_dflt)
--              devinet_copy_dflt_conf(i);
-+      if (cnf == net->ipv4_devconf_dflt)
-+              devinet_copy_dflt_conf(net, i);
-       return 1;
- }
--void inet_forward_change(void)
-+void inet_forward_change(struct net *net)
- {
-       struct net_device *dev;
--      int on = IPV4_DEVCONF_ALL(FORWARDING);
-+      int on = IPV4_DEVCONF_ALL(net, FORWARDING);
--      IPV4_DEVCONF_ALL(ACCEPT_REDIRECTS) = !on;
--      IPV4_DEVCONF_DFLT(FORWARDING) = on;
-+      IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on;
-+      IPV4_DEVCONF_DFLT(net, FORWARDING) = on;
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(net, dev) {
-               struct in_device *in_dev;
-               rcu_read_lock();
-               in_dev = __in_dev_get_rcu(dev);
-@@ -1364,11 +1372,12 @@
-       int *valp = ctl->data;
-       int val = *valp;
-       int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
-+      struct net *net = ctl->extra2;
-       if (write && *valp != val) {
--              if (valp == &IPV4_DEVCONF_ALL(FORWARDING))
--                      inet_forward_change();
--              else if (valp != &IPV4_DEVCONF_DFLT(FORWARDING))
-+              if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING))
-+                      inet_forward_change(net);
-+              else if (valp != &IPV4_DEVCONF_DFLT(net, FORWARDING))
-                       rt_cache_flush(0);
-       }
-@@ -1407,13 +1416,14 @@
-       { \
-               .ctl_name       = NET_IPV4_CONF_ ## attr, \
-               .procname       = name, \
--              .data           = ipv4_devconf.data + \
-+              .data           = ipv4_devconf_template.data + \
-                                 NET_IPV4_CONF_ ## attr - 1, \
-               .maxlen         = sizeof(int), \
-               .mode           = mval, \
-               .proc_handler   = proc, \
-               .strategy       = sysctl, \
--              .extra1         = &ipv4_devconf, \
-+              .extra1         = &ipv4_devconf_template, \
-+              .extra2         = &init_net, \
-       }
- #define DEVINET_SYSCTL_RW_ENTRY(attr, name) \
-@@ -1503,25 +1513,29 @@
-       },
- };
--static void devinet_sysctl_register(struct in_device *in_dev,
-+static void devinet_sysctl_register(struct net *net, struct in_device *in_dev,
-                                   struct ipv4_devconf *p)
- {
-       int i;
-       struct net_device *dev = in_dev ? in_dev->dev : NULL;
--      struct devinet_sysctl_table *t = kmemdup(&devinet_sysctl, sizeof(*t),
--                                               GFP_KERNEL);
-+      struct devinet_sysctl_table *t;
-       char *dev_name = NULL;
-+      t = kmemdup(&devinet_sysctl, sizeof(*t), GFP_KERNEL);
-       if (!t)
-               return;
-       for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
--              t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
-+              t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf_template;
-               t->devinet_vars[i].extra1 = p;
-+              t->devinet_vars[i].extra2 = net;
-       }
-       if (dev) {
-               dev_name = dev->name;
-               t->devinet_dev[0].ctl_name = dev->ifindex;
-+      } else if (p == net->ipv4_devconf) {
-+              dev_name = "all";
-+              t->devinet_dev[0].ctl_name = NET_PROTO_CONF_ALL;
-       } else {
-               dev_name = "default";
-               t->devinet_dev[0].ctl_name = NET_PROTO_CONF_DEFAULT;
-@@ -1542,7 +1556,7 @@
-       t->devinet_proto_dir[0].child = t->devinet_conf_dir;
-       t->devinet_root_dir[0].child  = t->devinet_proto_dir;
--      t->sysctl_header = register_sysctl_table(t->devinet_root_dir);
-+      t->sysctl_header = register_net_sysctl_table(net, t->devinet_root_dir);
-       if (!t->sysctl_header)
-           goto free_procname;
-@@ -1562,26 +1576,59 @@
-       if (p->sysctl) {
-               struct devinet_sysctl_table *t = p->sysctl;
-               p->sysctl = NULL;
--              unregister_sysctl_table(t->sysctl_header);
-+              unregister_net_sysctl_table(t->sysctl_header);
-               kfree(t->devinet_dev[0].procname);
-               kfree(t);
-       }
- }
- #endif
-+static int devinet_net_init(struct net *net)
++/*
++ * shmem_getpage - either get the page from swap or allocate a new one
++ *
++ * If we allocate a new one we do not mark it dirty. That's up to the
++ * vm. If we swap it in we mark it dirty since we also free the swap
++ * entry since a page cannot live in both the swap and page cache
++ */
++static int shmem_getpage(struct inode *inode, unsigned long idx,
++                      struct page **pagep, enum sgp_type sgp, int *type)
++{
++      struct address_space *mapping = inode->i_mapping;
++      struct shmem_inode_info *info = SHMEM_I(inode);
++      struct shmem_sb_info *sbinfo;
++      struct page *filepage = *pagep;
++      struct page *swappage;
++      swp_entry_t *entry;
++      swp_entry_t swap;
++      int error;
++
++      if (idx >= SHMEM_MAX_INDEX)
++              return -EFBIG;
++      /*
++       * Normally, filepage is NULL on entry, and either found
++       * uptodate immediately, or allocated and zeroed, or read
++       * in under swappage, which is then assigned to filepage.
++       * But shmem_prepare_write passes in a locked filepage,
++       * which may be found not uptodate by other callers too,
++       * and may need to be copied from the swappage read in.
++       */
++repeat:
++      if (!filepage)
++              filepage = find_lock_page(mapping, idx);
++      if (filepage && PageUptodate(filepage))
++              goto done;
++      error = 0;
++      if (sgp == SGP_QUICK)
++              goto failed;
++
++      spin_lock(&info->lock);
++      shmem_recalc_inode(inode);
++      entry = shmem_swp_alloc(info, idx, sgp);
++      if (IS_ERR(entry)) {
++              spin_unlock(&info->lock);
++              error = PTR_ERR(entry);
++              goto failed;
++      }
++      swap = *entry;
++
++      if (swap.val) {
++              /* Look it up and read it in.. */
++              swappage = lookup_swap_cache(swap);
++              if (!swappage) {
++                      shmem_swp_unmap(entry);
++                      /* here we actually do the io */
++                      if (type && *type == VM_FAULT_MINOR) {
++                              __count_vm_event(PGMAJFAULT);
++                              *type = VM_FAULT_MAJOR;
++                      }
++                      spin_unlock(&info->lock);
++                      swappage = shmem_swapin(info, swap, idx);
++                      if (!swappage) {
++                              spin_lock(&info->lock);
++                              entry = shmem_swp_alloc(info, idx, sgp);
++                              if (IS_ERR(entry))
++                                      error = PTR_ERR(entry);
++                              else {
++                                      if (entry->val == swap.val)
++                                              error = -ENOMEM;
++                                      shmem_swp_unmap(entry);
++                              }
++                              spin_unlock(&info->lock);
++                              if (error)
++                                      goto failed;
++                              goto repeat;
++                      }
++                      wait_on_page_locked(swappage);
++                      page_cache_release(swappage);
++                      goto repeat;
++              }
++
++              /* We have to do this with page locked to prevent races */
++              if (TestSetPageLocked(swappage)) {
++                      shmem_swp_unmap(entry);
++                      spin_unlock(&info->lock);
++                      wait_on_page_locked(swappage);
++                      page_cache_release(swappage);
++                      goto repeat;
++              }
++              if (PageWriteback(swappage)) {
++                      shmem_swp_unmap(entry);
++                      spin_unlock(&info->lock);
++                      wait_on_page_writeback(swappage);
++                      unlock_page(swappage);
++                      page_cache_release(swappage);
++                      goto repeat;
++              }
++              if (!PageUptodate(swappage)) {
++                      shmem_swp_unmap(entry);
++                      spin_unlock(&info->lock);
++                      unlock_page(swappage);
++                      page_cache_release(swappage);
++                      error = -EIO;
++                      goto failed;
++              }
++
++              if (filepage) {
++                      shmem_swp_set(info, entry, 0);
++                      shmem_swp_unmap(entry);
++                      delete_from_swap_cache(swappage);
++                      spin_unlock(&info->lock);
++                      copy_highpage(filepage, swappage);
++                      unlock_page(swappage);
++                      page_cache_release(swappage);
++                      flush_dcache_page(filepage);
++                      SetPageUptodate(filepage);
++                      set_page_dirty(filepage);
++                      swap_free(swap);
++              } else if (!(error = move_from_swap_cache(
++                              swappage, idx, mapping))) {
++                      info->flags |= SHMEM_PAGEIN;
++                      shmem_swp_set(info, entry, 0);
++                      shmem_swp_unmap(entry);
++                      spin_unlock(&info->lock);
++                      filepage = swappage;
++                      swap_free(swap);
++              } else {
++                      shmem_swp_unmap(entry);
++                      spin_unlock(&info->lock);
++                      unlock_page(swappage);
++                      page_cache_release(swappage);
++                      if (error == -ENOMEM) {
++                              /* let kswapd refresh zone for GFP_ATOMICs */
++                              congestion_wait(WRITE, HZ/50);
++                      }
++                      goto repeat;
++              }
++      } else if (sgp == SGP_READ && !filepage) {
++              shmem_swp_unmap(entry);
++              filepage = find_get_page(mapping, idx);
++              if (filepage &&
++                  (!PageUptodate(filepage) || TestSetPageLocked(filepage))) {
++                      spin_unlock(&info->lock);
++                      wait_on_page_locked(filepage);
++                      page_cache_release(filepage);
++                      filepage = NULL;
++                      goto repeat;
++              }
++              spin_unlock(&info->lock);
++      } else {
++              shmem_swp_unmap(entry);
++              sbinfo = SHMEM_SB(inode->i_sb);
++              if (sbinfo->max_blocks) {
++                      spin_lock(&sbinfo->stat_lock);
++                      if (sbinfo->free_blocks == 0 ||
++                          shmem_acct_block(info->flags)) {
++                              spin_unlock(&sbinfo->stat_lock);
++                              spin_unlock(&info->lock);
++                              error = -ENOSPC;
++                              goto failed;
++                      }
++                      sbinfo->free_blocks--;
++                      inode->i_blocks += BLOCKS_PER_PAGE;
++                      spin_unlock(&sbinfo->stat_lock);
++              } else if (shmem_acct_block(info->flags)) {
++                      spin_unlock(&info->lock);
++                      error = -ENOSPC;
++                      goto failed;
++              }
++
++              if (!filepage) {
++                      spin_unlock(&info->lock);
++                      filepage = shmem_alloc_page(mapping_gfp_mask(mapping),
++                                                  info,
++                                                  idx);
++                      if (!filepage) {
++                              shmem_unacct_blocks(info->flags, 1);
++                              shmem_free_blocks(inode, 1);
++                              error = -ENOMEM;
++                              goto failed;
++                      }
++
++                      spin_lock(&info->lock);
++                      entry = shmem_swp_alloc(info, idx, sgp);
++                      if (IS_ERR(entry))
++                              error = PTR_ERR(entry);
++                      else {
++                              swap = *entry;
++                              shmem_swp_unmap(entry);
++                      }
++                      if (error || swap.val || 0 != add_to_page_cache_lru(
++                                      filepage, mapping, idx, GFP_ATOMIC)) {
++                              spin_unlock(&info->lock);
++                              page_cache_release(filepage);
++                              shmem_unacct_blocks(info->flags, 1);
++                              shmem_free_blocks(inode, 1);
++                              filepage = NULL;
++                              if (error)
++                                      goto failed;
++                              goto repeat;
++                      }
++                      info->flags |= SHMEM_PAGEIN;
++              }
++
++              info->alloced++;
++              spin_unlock(&info->lock);
++              flush_dcache_page(filepage);
++              SetPageUptodate(filepage);
++      }
++done:
++      if (*pagep != filepage) {
++              unlock_page(filepage);
++              *pagep = filepage;
++      }
++      return 0;
++
++failed:
++      if (*pagep != filepage) {
++              unlock_page(filepage);
++              page_cache_release(filepage);
++      }
++      return error;
++}
++
++static struct page *shmem_nopage(struct vm_area_struct *vma,
++                               unsigned long address, int *type)
++{
++      struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
++      struct page *page = NULL;
++      unsigned long idx;
++      int error;
++
++      idx = (address - vma->vm_start) >> PAGE_SHIFT;
++      idx += vma->vm_pgoff;
++      idx >>= PAGE_CACHE_SHIFT - PAGE_SHIFT;
++      if (((loff_t) idx << PAGE_CACHE_SHIFT) >= i_size_read(inode))
++              return NOPAGE_SIGBUS;
++
++      error = shmem_getpage(inode, idx, &page, SGP_CACHE, type);
++      if (error)
++              return (error == -ENOMEM)? NOPAGE_OOM: NOPAGE_SIGBUS;
++
++      mark_page_accessed(page);
++      return page;
++}
++
++static int shmem_populate(struct vm_area_struct *vma,
++      unsigned long addr, unsigned long len,
++      pgprot_t prot, unsigned long pgoff, int nonblock)
 +{
-+#ifdef CONFIG_SYSCTL
-+      net->ipv4_devconf = kmemdup(&ipv4_devconf_template, 
-+                                  sizeof(ipv4_devconf_template), GFP_KERNEL);
-+      if (!net->ipv4_devconf)
-+              return -ENOMEM;
-+      
-+      net->ipv4_devconf_dflt = kmemdup(&ipv4_devconf_dflt_template, 
-+                                       sizeof(ipv4_devconf_template),
-+                                       GFP_KERNEL);
-+      if (!net->ipv4_devconf_dflt) {
-+              kfree(net->ipv4_devconf);
-+              return -ENOMEM;
++      struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
++      struct mm_struct *mm = vma->vm_mm;
++      enum sgp_type sgp = nonblock? SGP_QUICK: SGP_CACHE;
++      unsigned long size;
++
++      size = (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
++      if (pgoff >= size || pgoff + (len >> PAGE_SHIFT) > size)
++              return -EINVAL;
++
++      while ((long) len > 0) {
++              struct page *page = NULL;
++              int err;
++              /*
++               * Will need changing if PAGE_CACHE_SIZE != PAGE_SIZE
++               */
++              err = shmem_getpage(inode, pgoff, &page, sgp, NULL);
++              if (err)
++                      return err;
++              /* Page may still be null, but only if nonblock was set. */
++              if (page) {
++                      mark_page_accessed(page);
++                      err = install_page(mm, vma, addr, page, prot);
++                      if (err) {
++                              page_cache_release(page);
++                              return err;
++                      }
++              } else if (vma->vm_flags & VM_NONLINEAR) {
++                      /* No page was found just because we can't read it in
++                       * now (being here implies nonblock != 0), but the page
++                       * may exist, so set the PTE to fault it in later. */
++                      err = install_file_pte(mm, vma, addr, pgoff, prot);
++                      if (err)
++                              return err;
++              }
++
++              len -= PAGE_SIZE;
++              addr += PAGE_SIZE;
++              pgoff++;
 +      }
++      return 0;
++}
++
++#ifdef CONFIG_NUMA
++int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
++{
++      struct inode *i = vma->vm_file->f_path.dentry->d_inode;
++      return mpol_set_shared_policy(&SHMEM_I(i)->policy, vma, new);
++}
 +
-+      devinet_sysctl_register(net, NULL, net->ipv4_devconf);
-+      devinet_sysctl_register(net, NULL, net->ipv4_devconf_dflt);
++struct mempolicy *
++shmem_get_policy(struct vm_area_struct *vma, unsigned long addr)
++{
++      struct inode *i = vma->vm_file->f_path.dentry->d_inode;
++      unsigned long idx;
 +
-+      multi_ipv4_table[0].data = &IPV4_DEVCONF_ALL(net, FORWARDING);
++      idx = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
++      return mpol_shared_policy_lookup(&SHMEM_I(i)->policy, idx);
++}
 +#endif
++
++int shmem_lock(struct file *file, int lock, struct user_struct *user)
++{
++      struct inode *inode = file->f_path.dentry->d_inode;
++      struct shmem_inode_info *info = SHMEM_I(inode);
++      int retval = -ENOMEM;
++
++      spin_lock(&info->lock);
++      if (lock && !(info->flags & VM_LOCKED)) {
++              if (!user_shm_lock(inode->i_size, user))
++                      goto out_nomem;
++              info->flags |= VM_LOCKED;
++      }
++      if (!lock && (info->flags & VM_LOCKED) && user) {
++              user_shm_unlock(inode->i_size, user);
++              info->flags &= ~VM_LOCKED;
++      }
++      retval = 0;
++out_nomem:
++      spin_unlock(&info->lock);
++      return retval;
++}
++
++static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
++{
++      file_accessed(file);
++      vma->vm_ops = &shmem_vm_ops;
 +      return 0;
 +}
 +
-+static void devinet_net_exit(struct net *net)
++static struct inode *
++shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
 +{
-+#ifdef CONFIG_SYSCTL
-+      devinet_sysctl_unregister(net->ipv4_devconf_dflt);
-+      devinet_sysctl_unregister(net->ipv4_devconf);
-+#endif
++      struct inode *inode;
++      struct shmem_inode_info *info;
++      struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
++
++      if (sbinfo->max_inodes) {
++              spin_lock(&sbinfo->stat_lock);
++              if (!sbinfo->free_inodes) {
++                      spin_unlock(&sbinfo->stat_lock);
++                      return NULL;
++              }
++              sbinfo->free_inodes--;
++              spin_unlock(&sbinfo->stat_lock);
++      }
++
++      inode = new_inode(sb);
++      if (inode) {
++              inode->i_mode = mode;
++              inode->i_uid = current->fsuid;
++              inode->i_gid = current->fsgid;
++              inode->i_blocks = 0;
++              inode->i_mapping->a_ops = &shmem_aops;
++              inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
++              inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++              inode->i_generation = get_seconds();
++              info = SHMEM_I(inode);
++              memset(info, 0, (char *)inode - (char *)info);
++              spin_lock_init(&info->lock);
++              INIT_LIST_HEAD(&info->swaplist);
++
++              switch (mode & S_IFMT) {
++              default:
++                      inode->i_op = &shmem_special_inode_operations;
++                      init_special_inode(inode, mode, dev);
++                      break;
++              case S_IFREG:
++                      inode->i_op = &shmem_inode_operations;
++                      inode->i_fop = &shmem_file_operations;
++                      mpol_shared_policy_init(&info->policy, sbinfo->policy,
++                                                      &sbinfo->policy_nodes);
++                      break;
++              case S_IFDIR:
++                      inc_nlink(inode);
++                      /* Some things misbehave if size == 0 on a directory */
++                      inode->i_size = 2 * BOGO_DIRENT_SIZE;
++                      inode->i_op = &shmem_dir_inode_operations;
++                      inode->i_fop = &simple_dir_operations;
++                      break;
++              case S_IFLNK:
++                      /*
++                       * Must not load anything in the rbtree,
++                       * mpol_free_shared_policy will not be called.
++                       */
++                      mpol_shared_policy_init(&info->policy, MPOL_DEFAULT,
++                                              NULL);
++                      break;
++              }
++      } else if (sbinfo->max_inodes) {
++              spin_lock(&sbinfo->stat_lock);
++              sbinfo->free_inodes++;
++              spin_unlock(&sbinfo->stat_lock);
++      }
++      return inode;
 +}
 +
-+static struct pernet_operations devinet_net_ops = {
-+      .init = devinet_net_init,
-+      .exit = devinet_net_exit,
-+};
++#ifdef CONFIG_TMPFS
++static const struct inode_operations shmem_symlink_inode_operations;
++static const struct inode_operations shmem_symlink_inline_operations;
 +
- void __init devinet_init(void)
- {
-+      register_pernet_subsys(&devinet_net_ops);
-       register_gifconf(PF_INET, inet_gifconf);
-       register_netdevice_notifier(&ip_netdev_notifier);
-       rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL);
-       rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL);
-       rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr);
--#ifdef CONFIG_SYSCTL
--      devinet_sysctl.sysctl_header =
--              register_sysctl_table(devinet_sysctl.devinet_root_dir);
--      devinet_sysctl_register(NULL, &ipv4_devconf_dflt);
--#endif
- }
- EXPORT_SYMBOL(in_dev_finish_destroy);
-diff -Nurb linux-2.6.22-570/net/ipv4/esp4.c linux-2.6.22-590/net/ipv4/esp4.c
---- linux-2.6.22-570/net/ipv4/esp4.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/esp4.c   2008-01-02 13:56:38.000000000 -0500
-@@ -307,6 +307,9 @@
-       struct ip_esp_hdr *esph = (struct ip_esp_hdr*)(skb->data+(iph->ihl<<2));
-       struct xfrm_state *x;
-+      if (skb->dev->nd_net != &init_net)
-+              return;
++/*
++ * Normally tmpfs makes no use of shmem_prepare_write, but it
++ * lets a tmpfs file be used read-write below the loop driver.
++ */
++static int
++shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
++{
++      struct inode *inode = page->mapping->host;
++      return shmem_getpage(inode, page->index, &page, SGP_WRITE, NULL);
++}
 +
-       if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH ||
-           icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
-               return;
-@@ -481,3 +484,4 @@
- module_init(esp4_init);
- module_exit(esp4_fini);
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_ESP);
-diff -Nurb linux-2.6.22-570/net/ipv4/fib_frontend.c linux-2.6.22-590/net/ipv4/fib_frontend.c
---- linux-2.6.22-570/net/ipv4/fib_frontend.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/fib_frontend.c   2008-01-02 13:56:38.000000000 -0500
-@@ -51,38 +51,34 @@
- #ifndef CONFIG_IP_MULTIPLE_TABLES
--struct fib_table *ip_fib_local_table;
--struct fib_table *ip_fib_main_table;
--
- #define FIB_TABLE_HASHSZ 1
--static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
- #else
- #define FIB_TABLE_HASHSZ 256
--static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
--struct fib_table *fib_new_table(u32 id)
-+struct fib_table *fib_new_table(struct net *net, u32 id)
- {
-       struct fib_table *tb;
-       unsigned int h;
-       if (id == 0)
-               id = RT_TABLE_MAIN;
--      tb = fib_get_table(id);
-+      tb = fib_get_table(net, id);
-       if (tb)
-               return tb;
-       tb = fib_hash_init(id);
-       if (!tb)
-               return NULL;
-       h = id & (FIB_TABLE_HASHSZ - 1);
--      hlist_add_head_rcu(&tb->tb_hlist, &fib_table_hash[h]);
-+      hlist_add_head_rcu(&tb->tb_hlist, &net->ip_fib_table_hash[h]);
-       return tb;
- }
--struct fib_table *fib_get_table(u32 id)
-+struct fib_table *fib_get_table(struct net *net, u32 id)
- {
-       struct fib_table *tb;
-+      struct hlist_head *head;
-       struct hlist_node *node;
-       unsigned int h;
-@@ -90,7 +86,8 @@
-               id = RT_TABLE_MAIN;
-       h = id & (FIB_TABLE_HASHSZ - 1);
-       rcu_read_lock();
--      hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb_hlist) {
-+      head = &net->ip_fib_table_hash[h];
-+      hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
-               if (tb->tb_id == id) {
-                       rcu_read_unlock();
-                       return tb;
-@@ -99,9 +96,10 @@
-       rcu_read_unlock();
-       return NULL;
- }
++static ssize_t
++shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
++{
++      struct inode    *inode = file->f_path.dentry->d_inode;
++      loff_t          pos;
++      unsigned long   written;
++      ssize_t         err;
 +
- #endif /* CONFIG_IP_MULTIPLE_TABLES */
--static void fib_flush(void)
-+static void fib_flush(struct net *net)
- {
-       int flushed = 0;
-       struct fib_table *tb;
-@@ -109,7 +107,8 @@
-       unsigned int h;
-       for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
--              hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist)
-+              struct hlist_head *head = &net->ip_fib_table_hash[h];
-+              hlist_for_each_entry(tb, node, head, tb_hlist)
-                       flushed += tb->tb_flush(tb);
-       }
-@@ -121,18 +120,23 @@
-  *    Find the first device with a given source address.
-  */
--struct net_device * ip_dev_find(__be32 addr)
-+struct net_device * ip_dev_find(struct net *net, __be32 addr)
- {
--      struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
-+      struct flowi fl = { 
-+              .fl_net = net,
-+              .nl_u = { .ip4_u = { .daddr = addr } }
-+      };
-       struct fib_result res;
-       struct net_device *dev = NULL;
-+      struct fib_table *local_table;
- #ifdef CONFIG_IP_MULTIPLE_TABLES
-       res.r = NULL;
- #endif
--      if (!ip_fib_local_table ||
--          ip_fib_local_table->tb_lookup(ip_fib_local_table, &fl, &res))
-+      local_table = fib_get_table(net, RT_TABLE_LOCAL);
-+      if (!local_table ||
-+          local_table->tb_lookup(local_table, &fl, &res))
-               return NULL;
-       if (res.type != RTN_LOCAL)
-               goto out;
-@@ -145,11 +149,15 @@
-       return dev;
- }
--unsigned inet_addr_type(__be32 addr)
-+unsigned inet_addr_type(struct net *net, __be32 addr)
- {
--      struct flowi            fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
-+      struct flowi            fl = {
-+              .fl_net = net,
-+              .nl_u = { .ip4_u = { .daddr = addr } }
-+      };
-       struct fib_result       res;
-       unsigned ret = RTN_BROADCAST;
-+      struct fib_table *local_table;
-       if (ZERONET(addr) || BADCLASS(addr))
-               return RTN_BROADCAST;
-@@ -160,10 +168,10 @@
-       res.r = NULL;
- #endif
--      if (ip_fib_local_table) {
-+      local_table = fib_get_table(net, RT_TABLE_LOCAL);
-+      if (local_table) {
-               ret = RTN_UNICAST;
--              if (!ip_fib_local_table->tb_lookup(ip_fib_local_table,
--                                                 &fl, &res)) {
-+              if (!local_table->tb_lookup(local_table, &fl, &res)) {
-                       ret = res.type;
-                       fib_res_put(&res);
-               }
-@@ -183,7 +191,8 @@
-                       struct net_device *dev, __be32 *spec_dst, u32 *itag)
- {
-       struct in_device *in_dev;
--      struct flowi fl = { .nl_u = { .ip4_u =
-+      struct flowi fl = { .fl_net = dev->nd_net,
-+                          .nl_u = { .ip4_u =
-                                     { .daddr = src,
-                                       .saddr = dst,
-                                       .tos = tos } },
-@@ -267,13 +276,16 @@
-       return len + nla_total_size(4);
- }
--static int rtentry_to_fib_config(int cmd, struct rtentry *rt,
-+static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
-                                struct fib_config *cfg)
- {
-       __be32 addr;
-       int plen;
-       memset(cfg, 0, sizeof(*cfg));
-+      cfg->fc_nlinfo.pid = 0;
-+      cfg->fc_nlinfo.nlh = NULL;
-+      cfg->fc_nlinfo.net = net;
-       if (rt->rt_dst.sa_family != AF_INET)
-               return -EAFNOSUPPORT;
-@@ -334,7 +346,7 @@
-               colon = strchr(devname, ':');
-               if (colon)
-                       *colon = 0;
--              dev = __dev_get_by_name(devname);
-+              dev = __dev_get_by_name(net, devname);
-               if (!dev)
-                       return -ENODEV;
-               cfg->fc_oif = dev->ifindex;
-@@ -357,7 +369,7 @@
-       if (rt->rt_gateway.sa_family == AF_INET && addr) {
-               cfg->fc_gw = addr;
-               if (rt->rt_flags & RTF_GATEWAY &&
--                  inet_addr_type(addr) == RTN_UNICAST)
-+                  inet_addr_type(net, addr) == RTN_UNICAST)
-                       cfg->fc_scope = RT_SCOPE_UNIVERSE;
-       }
-@@ -398,7 +410,7 @@
-  *    Handle IP routing ioctl calls. These are used to manipulate the routing tables
-  */
--int ip_rt_ioctl(unsigned int cmd, void __user *arg)
-+int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
- {
-       struct fib_config cfg;
-       struct rtentry rt;
-@@ -414,18 +426,18 @@
-                       return -EFAULT;
-               rtnl_lock();
--              err = rtentry_to_fib_config(cmd, &rt, &cfg);
-+              err = rtentry_to_fib_config(net, cmd, &rt, &cfg);
-               if (err == 0) {
-                       struct fib_table *tb;
-                       if (cmd == SIOCDELRT) {
--                              tb = fib_get_table(cfg.fc_table);
-+                              tb = fib_get_table(net, cfg.fc_table);
-                               if (tb)
-                                       err = tb->tb_delete(tb, &cfg);
-                               else
-                                       err = -ESRCH;
-                       } else {
--                              tb = fib_new_table(cfg.fc_table);
-+                              tb = fib_new_table(net, cfg.fc_table);
-                               if (tb)
-                                       err = tb->tb_insert(tb, &cfg);
-                               else
-@@ -453,7 +465,6 @@
-       [RTA_MULTIPATH]         = { .len = sizeof(struct rtnexthop) },
-       [RTA_PROTOINFO]         = { .type = NLA_U32 },
-       [RTA_FLOW]              = { .type = NLA_U32 },
--      [RTA_MP_ALGO]           = { .type = NLA_U32 },
- };
- static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
-@@ -481,6 +492,7 @@
-       cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
-       cfg->fc_nlinfo.nlh = nlh;
-+      cfg->fc_nlinfo.net = skb->sk->sk_net;
-       if (cfg->fc_type > RTN_MAX) {
-               err = -EINVAL;
-@@ -515,9 +527,6 @@
-               case RTA_FLOW:
-                       cfg->fc_flow = nla_get_u32(attr);
-                       break;
--              case RTA_MP_ALGO:
--                      cfg->fc_mp_alg = nla_get_u32(attr);
--                      break;
-               case RTA_TABLE:
-                       cfg->fc_table = nla_get_u32(attr);
-                       break;
-@@ -531,6 +540,7 @@
- static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct fib_config cfg;
-       struct fib_table *tb;
-       int err;
-@@ -539,7 +549,7 @@
-       if (err < 0)
-               goto errout;
--      tb = fib_get_table(cfg.fc_table);
-+      tb = fib_get_table(net, cfg.fc_table);
-       if (tb == NULL) {
-               err = -ESRCH;
-               goto errout;
-@@ -552,6 +562,7 @@
- static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct fib_config cfg;
-       struct fib_table *tb;
-       int err;
-@@ -560,7 +571,7 @@
-       if (err < 0)
-               goto errout;
--      tb = fib_new_table(cfg.fc_table);
-+      tb = fib_new_table(net, cfg.fc_table);
-       if (tb == NULL) {
-               err = -ENOBUFS;
-               goto errout;
-@@ -573,6 +584,7 @@
- static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
- {
-+      struct net *net = skb->sk->sk_net;
-       unsigned int h, s_h;
-       unsigned int e = 0, s_e;
-       struct fib_table *tb;
-@@ -587,8 +599,9 @@
-       s_e = cb->args[1];
-       for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
-+              struct hlist_head *head = &net->ip_fib_table_hash[h];
-               e = 0;
--              hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist) {
-+              hlist_for_each_entry(tb, node, head, tb_hlist) {
-                       if (e < s_e)
-                               goto next;
-                       if (dumped)
-@@ -617,6 +630,7 @@
- static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
- {
-+      struct net *net = ifa->ifa_dev->dev->nd_net;
-       struct fib_table *tb;
-       struct fib_config cfg = {
-               .fc_protocol = RTPROT_KERNEL,
-@@ -626,12 +640,13 @@
-               .fc_prefsrc = ifa->ifa_local,
-               .fc_oif = ifa->ifa_dev->dev->ifindex,
-               .fc_nlflags = NLM_F_CREATE | NLM_F_APPEND,
-+              .fc_nlinfo.net = net,
-       };
-       if (type == RTN_UNICAST)
--              tb = fib_new_table(RT_TABLE_MAIN);
-+              tb = fib_new_table(net, RT_TABLE_MAIN);
-       else
--              tb = fib_new_table(RT_TABLE_LOCAL);
-+              tb = fib_new_table(net, RT_TABLE_LOCAL);
-       if (tb == NULL)
-               return;
-@@ -692,6 +707,7 @@
- {
-       struct in_device *in_dev = ifa->ifa_dev;
-       struct net_device *dev = in_dev->dev;
-+      struct net *net = dev->nd_net;
-       struct in_ifaddr *ifa1;
-       struct in_ifaddr *prim = ifa;
-       __be32 brd = ifa->ifa_address|~ifa->ifa_mask;
-@@ -740,15 +756,15 @@
-               fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
-               /* Check, that this local address finally disappeared. */
--              if (inet_addr_type(ifa->ifa_local) != RTN_LOCAL) {
-+              if (inet_addr_type(net, ifa->ifa_local) != RTN_LOCAL) {
-                       /* And the last, but not the least thing.
-                          We must flush stray FIB entries.
-                          First of all, we scan fib_info list searching
-                          for stray nexthop entries, then ignite fib_flush.
-                       */
--                      if (fib_sync_down(ifa->ifa_local, NULL, 0))
--                              fib_flush();
-+                      if (fib_sync_down(net, ifa->ifa_local, NULL, 0))
-+                              fib_flush(net);
-               }
-       }
- #undef LOCAL_OK
-@@ -757,11 +773,12 @@
- #undef BRD1_OK
- }
--static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
-+static void nl_fib_lookup(struct net *net, struct fib_result_nl *frn, struct fib_table *tb )
- {
-       struct fib_result       res;
--      struct flowi            fl = { .mark = frn->fl_mark,
-+      struct flowi            fl = { .fl_net = net,
-+                                     .mark = frn->fl_mark,
-                                      .nl_u = { .ip4_u = { .daddr = frn->fl_addr,
-                                                           .tos = frn->fl_tos,
-                                                           .scope = frn->fl_scope } } };
-@@ -790,6 +807,7 @@
- static void nl_fib_input(struct sock *sk, int len)
- {
-+      struct net *net = sk->sk_net;
-       struct sk_buff *skb = NULL;
-       struct nlmsghdr *nlh = NULL;
-       struct fib_result_nl *frn;
-@@ -808,9 +826,9 @@
-       }
-       frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
--      tb = fib_get_table(frn->tb_id_in);
-+      tb = fib_get_table(net, frn->tb_id_in);
--      nl_fib_lookup(frn, tb);
-+      nl_fib_lookup(net, frn, tb);
-       pid = NETLINK_CB(skb).pid;       /* pid of sending process */
-       NETLINK_CB(skb).pid = 0;         /* from kernel */
-@@ -818,16 +836,36 @@
-       netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
- }
--static void nl_fib_lookup_init(void)
-+static int nl_fib_lookup_init(struct net *net)
- {
--      netlink_kernel_create(NETLINK_FIB_LOOKUP, 0, nl_fib_input, NULL,
--                                  THIS_MODULE);
-+      int error = -ENOMEM;
-+      struct sock *sk;
-+      sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0, nl_fib_input,
-+                                      NULL, THIS_MODULE);
-+      if (sk) {
-+              /* Don't hold an extra reference on the namespace */
-+              put_net(sk->sk_net);
-+              net->nlfl = sk;
-+              error = 0;
++      if ((ssize_t) count < 0)
++              return -EINVAL;
++
++      if (!access_ok(VERIFY_READ, buf, count))
++              return -EFAULT;
++
++      mutex_lock(&inode->i_mutex);
++
++      pos = *ppos;
++      written = 0;
++
++      err = generic_write_checks(file, &pos, &count, 0);
++      if (err || !count)
++              goto out;
++
++      err = remove_suid(file->f_path.dentry);
++      if (err)
++              goto out;
++
++      inode->i_ctime = inode->i_mtime = CURRENT_TIME;
++
++      do {
++              struct page *page = NULL;
++              unsigned long bytes, index, offset;
++              char *kaddr;
++              int left;
++
++              offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
++              index = pos >> PAGE_CACHE_SHIFT;
++              bytes = PAGE_CACHE_SIZE - offset;
++              if (bytes > count)
++                      bytes = count;
++
++              /*
++               * We don't hold page lock across copy from user -
++               * what would it guard against? - so no deadlock here.
++               * But it still may be a good idea to prefault below.
++               */
++
++              err = shmem_getpage(inode, index, &page, SGP_WRITE, NULL);
++              if (err)
++                      break;
++
++              left = bytes;
++              if (PageHighMem(page)) {
++                      volatile unsigned char dummy;
++                      __get_user(dummy, buf);
++                      __get_user(dummy, buf + bytes - 1);
++
++                      kaddr = kmap_atomic(page, KM_USER0);
++                      left = __copy_from_user_inatomic(kaddr + offset,
++                                                      buf, bytes);
++                      kunmap_atomic(kaddr, KM_USER0);
++              }
++              if (left) {
++                      kaddr = kmap(page);
++                      left = __copy_from_user(kaddr + offset, buf, bytes);
++                      kunmap(page);
++              }
++
++              written += bytes;
++              count -= bytes;
++              pos += bytes;
++              buf += bytes;
++              if (pos > inode->i_size)
++                      i_size_write(inode, pos);
++
++              flush_dcache_page(page);
++              set_page_dirty(page);
++              mark_page_accessed(page);
++              page_cache_release(page);
++
++              if (left) {
++                      pos -= left;
++                      written -= left;
++                      err = -EFAULT;
++                      break;
++              }
++
++              /*
++               * Our dirty pages are not counted in nr_dirty,
++               * and we do not attempt to balance dirty pages.
++               */
++
++              cond_resched();
++      } while (count);
++
++      *ppos = pos;
++      if (written)
++              err = written;
++out:
++      mutex_unlock(&inode->i_mutex);
++      return err;
++}
++
++static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor)
++{
++      struct inode *inode = filp->f_path.dentry->d_inode;
++      struct address_space *mapping = inode->i_mapping;
++      unsigned long index, offset;
++
++      index = *ppos >> PAGE_CACHE_SHIFT;
++      offset = *ppos & ~PAGE_CACHE_MASK;
++
++      for (;;) {
++              struct page *page = NULL;
++              unsigned long end_index, nr, ret;
++              loff_t i_size = i_size_read(inode);
++
++              end_index = i_size >> PAGE_CACHE_SHIFT;
++              if (index > end_index)
++                      break;
++              if (index == end_index) {
++                      nr = i_size & ~PAGE_CACHE_MASK;
++                      if (nr <= offset)
++                              break;
++              }
++
++              desc->error = shmem_getpage(inode, index, &page, SGP_READ, NULL);
++              if (desc->error) {
++                      if (desc->error == -EINVAL)
++                              desc->error = 0;
++                      break;
++              }
++
++              /*
++               * We must evaluate after, since reads (unlike writes)
++               * are called without i_mutex protection against truncate
++               */
++              nr = PAGE_CACHE_SIZE;
++              i_size = i_size_read(inode);
++              end_index = i_size >> PAGE_CACHE_SHIFT;
++              if (index == end_index) {
++                      nr = i_size & ~PAGE_CACHE_MASK;
++                      if (nr <= offset) {
++                              if (page)
++                                      page_cache_release(page);
++                              break;
++                      }
++              }
++              nr -= offset;
++
++              if (page) {
++                      /*
++                       * If users can be writing to this page using arbitrary
++                       * virtual addresses, take care about potential aliasing
++                       * before reading the page on the kernel side.
++                       */
++                      if (mapping_writably_mapped(mapping))
++                              flush_dcache_page(page);
++                      /*
++                       * Mark the page accessed if we read the beginning.
++                       */
++                      if (!offset)
++                              mark_page_accessed(page);
++              } else {
++                      page = ZERO_PAGE(0);
++                      page_cache_get(page);
++              }
++
++              /*
++               * Ok, we have the page, and it's up-to-date, so
++               * now we can copy it to user space...
++               *
++               * The actor routine returns how many bytes were actually used..
++               * NOTE! This may not be the same as how much of a user buffer
++               * we filled up (we may be padding etc), so we can only update
++               * "pos" here (the actor routine has to update the user buffer
++               * pointers and the remaining count).
++               */
++              ret = actor(desc, page, offset, nr);
++              offset += ret;
++              index += offset >> PAGE_CACHE_SHIFT;
++              offset &= ~PAGE_CACHE_MASK;
++
++              page_cache_release(page);
++              if (ret != nr || !desc->count)
++                      break;
++
++              cond_resched();
++      }
++
++      *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
++      file_accessed(filp);
++}
++
++static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
++{
++      read_descriptor_t desc;
++
++      if ((ssize_t) count < 0)
++              return -EINVAL;
++      if (!access_ok(VERIFY_WRITE, buf, count))
++              return -EFAULT;
++      if (!count)
++              return 0;
++
++      desc.written = 0;
++      desc.count = count;
++      desc.arg.buf = buf;
++      desc.error = 0;
++
++      do_shmem_file_read(filp, ppos, &desc, file_read_actor);
++      if (desc.written)
++              return desc.written;
++      return desc.error;
++}
++
++static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos,
++                       size_t count, read_actor_t actor, void *target)
++{
++      read_descriptor_t desc;
++
++      if (!count)
++              return 0;
++
++      desc.written = 0;
++      desc.count = count;
++      desc.arg.data = target;
++      desc.error = 0;
++
++      do_shmem_file_read(in_file, ppos, &desc, actor);
++      if (desc.written)
++              return desc.written;
++      return desc.error;
++}
++
++static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++      struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
++
++      buf->f_type = TMPFS_MAGIC;
++      buf->f_bsize = PAGE_CACHE_SIZE;
++      buf->f_namelen = NAME_MAX;
++      spin_lock(&sbinfo->stat_lock);
++      if (sbinfo->max_blocks) {
++              buf->f_blocks = sbinfo->max_blocks;
++              buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;
++      }
++      if (sbinfo->max_inodes) {
++              buf->f_files = sbinfo->max_inodes;
++              buf->f_ffree = sbinfo->free_inodes;
++      }
++      /* else leave those fields 0 like simple_statfs */
++      spin_unlock(&sbinfo->stat_lock);
++      return 0;
++}
++
++/*
++ * File creation. Allocate an inode, and we're done..
++ */
++static int
++shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
++{
++      struct inode *inode = shmem_get_inode(dir->i_sb, mode, dev);
++      int error = -ENOSPC;
++
++      if (inode) {
++              error = security_inode_init_security(inode, dir, NULL, NULL,
++                                                   NULL);
++              if (error) {
++                      if (error != -EOPNOTSUPP) {
++                              iput(inode);
++                              return error;
++                      }
++              }
++              error = shmem_acl_init(inode, dir);
++              if (error) {
++                      iput(inode);
++                      return error;
++              }
++              if (dir->i_mode & S_ISGID) {
++                      inode->i_gid = dir->i_gid;
++                      if (S_ISDIR(mode))
++                              inode->i_mode |= S_ISGID;
++              }
++              dir->i_size += BOGO_DIRENT_SIZE;
++              dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++              d_instantiate(dentry, inode);
++              dget(dentry); /* Extra count - pin the dentry in core */
 +      }
 +      return error;
 +}
 +
-+static void nl_fib_lookup_exit(struct net *net)
++static int shmem_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 +{
-+      /* At the last minute lie and say this is a socket for the
-+       * initial network namespace.  So the socket will  be safe to
-+       * free. 
-+       */
-+      net->nlfl->sk_net = get_net(&init_net);
-+      sock_put(net->nlfl);
- }
- static void fib_disable_ip(struct net_device *dev, int force)
- {
--      if (fib_sync_down(0, dev, force))
--              fib_flush();
-+      struct net *net = dev->nd_net;
-+      if (fib_sync_down(net, 0, dev, force))
-+              fib_flush(net);
-       rt_cache_flush(0);
-       arp_ifdown(dev);
- }
-@@ -864,6 +902,9 @@
-       struct net_device *dev = ptr;
-       struct in_device *in_dev = __in_dev_get_rtnl(dev);
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
++      int error;
 +
-       if (event == NETDEV_UNREGISTER) {
-               fib_disable_ip(dev, 2);
-               return NOTIFY_DONE;
-@@ -893,6 +934,85 @@
-       return NOTIFY_DONE;
- }
-+static int ip_fib_net_init(struct net *net)
++      if ((error = shmem_mknod(dir, dentry, mode | S_IFDIR, 0)))
++              return error;
++      inc_nlink(dir);
++      return 0;
++}
++
++static int shmem_create(struct inode *dir, struct dentry *dentry, int mode,
++              struct nameidata *nd)
 +{
-+      unsigned int i;
++      return shmem_mknod(dir, dentry, mode | S_IFREG, 0);
++}
 +
-+      net->ip_fib_table_hash = kzalloc(
-+              sizeof(struct hlist_head)*FIB_TABLE_HASHSZ, GFP_KERNEL);
-+      if (!net->ip_fib_table_hash)
-+              return -ENOMEM;
++/*
++ * Link a file..
++ */
++static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
++{
++      struct inode *inode = old_dentry->d_inode;
++      struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
++
++      /*
++       * No ordinary (disk based) filesystem counts links as inodes;
++       * but each new link needs a new dentry, pinning lowmem, and
++       * tmpfs dentries cannot be pruned until they are unlinked.
++       */
++      if (sbinfo->max_inodes) {
++              spin_lock(&sbinfo->stat_lock);
++              if (!sbinfo->free_inodes) {
++                      spin_unlock(&sbinfo->stat_lock);
++                      return -ENOSPC;
++              }
++              sbinfo->free_inodes--;
++              spin_unlock(&sbinfo->stat_lock);
++      }
 +
-+      for (i = 0; i < FIB_TABLE_HASHSZ; i++)
-+              INIT_HLIST_HEAD(&net->ip_fib_table_hash[i]);
-+#ifndef CONFIG_IP_MULTIPLE_TABLES
-+      net->ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
-+      hlist_add_head_rcu(&net->ip_fib_local_table->tb_hlist,
-+                              &net->ip_fib_table_hash[0]);
-+      net->ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN);
-+      hlist_add_head_rcu(&net->ip_fib_main_table->tb_hlist,
-+                              &net->ip_fib_table_hash[0]);
-+#else
-+      fib4_rules_init(net);
-+#endif
++      dir->i_size += BOGO_DIRENT_SIZE;
++      inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++      inc_nlink(inode);
++      atomic_inc(&inode->i_count);    /* New dentry reference */
++      dget(dentry);           /* Extra pinning count for the created dentry */
++      d_instantiate(dentry, inode);
 +      return 0;
 +}
 +
-+static void ip_fib_net_exit(struct net *net)
++static int shmem_unlink(struct inode *dir, struct dentry *dentry)
 +{
-+      unsigned int i;
-+
-+#ifdef CONFIG_IP_MULTIPLE_TABLES
-+      fib4_rules_exit(net);
-+#endif
-+
-+      synchronize_rcu(); /* needed? */
-+      for (i = 0; i < FIB_TABLE_HASHSZ; i++) {
-+              struct fib_table *tb;
-+              struct hlist_head *head;
-+              struct hlist_node *node, *tmp;
++      struct inode *inode = dentry->d_inode;
 +
-+              head = &net->ip_fib_table_hash[i];
-+              hlist_for_each_entry_safe(tb, node, tmp, head, tb_hlist) {
-+                      hlist_del(node);
-+                      fib_hash_exit(tb);
++      if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) {
++              struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
++              if (sbinfo->max_inodes) {
++                      spin_lock(&sbinfo->stat_lock);
++                      sbinfo->free_inodes++;
++                      spin_unlock(&sbinfo->stat_lock);
 +              }
 +      }
-+      kfree(net->ip_fib_table_hash);
++
++      dir->i_size -= BOGO_DIRENT_SIZE;
++      inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++      drop_nlink(inode);
++      dput(dentry);   /* Undo the count from "create" - this does all the work */
++      return 0;
 +}
 +
-+static int fib_net_init(struct net *net)
++static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
 +{
-+      int error;
++      if (!simple_empty(dentry))
++              return -ENOTEMPTY;
 +
-+      error = 0;
-+      if ((error = ip_fib_net_init(net)))
-+              goto out;
-+      if ((error = fib_info_init(net)))
-+              goto out_info;
-+      if ((error = nl_fib_lookup_init(net)))
-+              goto out_nlfl;
-+      if ((error = fib_proc_init(net)))
-+              goto out_proc;
-+out:
-+      return error;
-+out_proc:
-+      nl_fib_lookup_exit(net);
-+out_nlfl:
-+      fib_info_exit(net);
-+out_info:
-+      ip_fib_net_exit(net);
-+      goto out;
++      drop_nlink(dentry->d_inode);
++      drop_nlink(dir);
++      return shmem_unlink(dir, dentry);
 +}
 +
-+static void fib_net_exit(struct net *net)
++/*
++ * The VFS layer already does all the dentry stuff for rename,
++ * we just have to decrement the usage count for the target if
++ * it exists so that the VFS layer correctly free's it when it
++ * gets overwritten.
++ */
++static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
 +{
-+      fib_proc_exit(net);
-+      nl_fib_lookup_exit(net);
-+      fib_info_exit(net);
-+      ip_fib_net_exit(net);
-+}
++      struct inode *inode = old_dentry->d_inode;
++      int they_are_dirs = S_ISDIR(inode->i_mode);
 +
- static struct notifier_block fib_inetaddr_notifier = {
-       .notifier_call =fib_inetaddr_event,
- };
-@@ -901,28 +1021,20 @@
-       .notifier_call =fib_netdev_event,
- };
-+static struct pernet_operations fib_net_ops = {
-+      .init = fib_net_init,
-+      .exit = fib_net_exit,
-+};
++      if (!simple_empty(new_dentry))
++              return -ENOTEMPTY;
 +
- void __init ip_fib_init(void)
- {
--      unsigned int i;
--
--      for (i = 0; i < FIB_TABLE_HASHSZ; i++)
--              INIT_HLIST_HEAD(&fib_table_hash[i]);
--#ifndef CONFIG_IP_MULTIPLE_TABLES
--      ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
--      hlist_add_head_rcu(&ip_fib_local_table->tb_hlist, &fib_table_hash[0]);
--      ip_fib_main_table  = fib_hash_init(RT_TABLE_MAIN);
--      hlist_add_head_rcu(&ip_fib_main_table->tb_hlist, &fib_table_hash[0]);
--#else
--      fib4_rules_init();
--#endif
--
--      register_netdevice_notifier(&fib_netdev_notifier);
--      register_inetaddr_notifier(&fib_inetaddr_notifier);
--      nl_fib_lookup_init();
--
-       rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL);
-       rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL);
-       rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib);
++      if (new_dentry->d_inode) {
++              (void) shmem_unlink(new_dir, new_dentry);
++              if (they_are_dirs)
++                      drop_nlink(old_dir);
++      } else if (they_are_dirs) {
++              drop_nlink(old_dir);
++              inc_nlink(new_dir);
++      }
 +
-+      register_pernet_subsys(&fib_net_ops);
-+      register_netdevice_notifier(&fib_netdev_notifier);
-+      register_inetaddr_notifier(&fib_inetaddr_notifier);
- }
- EXPORT_SYMBOL(inet_addr_type);
-diff -Nurb linux-2.6.22-570/net/ipv4/fib_hash.c linux-2.6.22-590/net/ipv4/fib_hash.c
---- linux-2.6.22-570/net/ipv4/fib_hash.c       2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/fib_hash.c       2008-01-02 13:56:38.000000000 -0500
-@@ -40,6 +40,7 @@
- #include <net/route.h>
- #include <net/tcp.h>
- #include <net/sock.h>
-+#include <net/net_namespace.h>
- #include <net/ip_fib.h>
- #include "fib_lookup.h"
-@@ -274,11 +275,10 @@
-       return err;
- }
--static int fn_hash_last_dflt=-1;
--
- static void
- fn_hash_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
- {
-+      struct net *net = flp->fl_net;
-       int order, last_idx;
-       struct hlist_node *node;
-       struct fib_node *f;
-@@ -316,12 +316,12 @@
-                               if (next_fi != res->fi)
-                                       break;
-                       } else if (!fib_detect_death(fi, order, &last_resort,
--                                                   &last_idx, &fn_hash_last_dflt)) {
-+                                                   &last_idx, &net->fn_hash_last_dflt)) {
-                               if (res->fi)
-                                       fib_info_put(res->fi);
-                               res->fi = fi;
-                               atomic_inc(&fi->fib_clntref);
--                              fn_hash_last_dflt = order;
-+                              net->fn_hash_last_dflt = order;
-                               goto out;
-                       }
-                       fi = next_fi;
-@@ -330,16 +330,16 @@
-       }
-       if (order <= 0 || fi == NULL) {
--              fn_hash_last_dflt = -1;
-+              net->fn_hash_last_dflt = -1;
-               goto out;
-       }
--      if (!fib_detect_death(fi, order, &last_resort, &last_idx, &fn_hash_last_dflt)) {
-+      if (!fib_detect_death(fi, order, &last_resort, &last_idx, &net->fn_hash_last_dflt)) {
-               if (res->fi)
-                       fib_info_put(res->fi);
-               res->fi = fi;
-               atomic_inc(&fi->fib_clntref);
--              fn_hash_last_dflt = order;
-+              net->fn_hash_last_dflt = order;
-               goto out;
-       }
-@@ -350,7 +350,7 @@
-               if (last_resort)
-                       atomic_inc(&last_resort->fib_clntref);
-       }
--      fn_hash_last_dflt = last_idx;
-+      net->fn_hash_last_dflt = last_idx;
- out:
-       read_unlock(&fib_hash_lock);
- }
-@@ -759,11 +759,15 @@
-       return skb->len;
- }
--#ifdef CONFIG_IP_MULTIPLE_TABLES
-+void fib_hash_exit(struct fib_table *tb)
-+{
-+      if (!tb)
-+              return;
-+      fn_hash_flush(tb);
-+      kfree(tb);
++      old_dir->i_size -= BOGO_DIRENT_SIZE;
++      new_dir->i_size += BOGO_DIRENT_SIZE;
++      old_dir->i_ctime = old_dir->i_mtime =
++      new_dir->i_ctime = new_dir->i_mtime =
++      inode->i_ctime = CURRENT_TIME;
++      return 0;
 +}
 +
- struct fib_table * fib_hash_init(u32 id)
--#else
--struct fib_table * __init fib_hash_init(u32 id)
--#endif
- {
-       struct fib_table *tb;
-@@ -799,6 +803,7 @@
- #ifdef CONFIG_PROC_FS
- struct fib_iter_state {
-+      struct net *net;
-       struct fn_zone  *zone;
-       int             bucket;
-       struct hlist_head *hash_head;
-@@ -812,7 +817,8 @@
- static struct fib_alias *fib_get_first(struct seq_file *seq)
- {
-       struct fib_iter_state *iter = seq->private;
--      struct fn_hash *table = (struct fn_hash *) ip_fib_main_table->tb_data;
-+      struct fib_table *main_table = fib_get_table(iter->net, RT_TABLE_MAIN);
-+      struct fn_hash *table = (struct fn_hash *) main_table->tb_data;
-       iter->bucket    = 0;
-       iter->hash_head = NULL;
-@@ -948,10 +954,11 @@
- static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
- {
-+      struct fib_iter_state *iter = seq->private;
-       void *v = NULL;
-       read_lock(&fib_hash_lock);
--      if (ip_fib_main_table)
-+      if (fib_get_table(iter->net, RT_TABLE_MAIN))
-               v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
-       return v;
- }
-@@ -1051,6 +1058,7 @@
-       seq          = file->private_data;
-       seq->private = s;
-+      s->net = get_net(PROC_NET(inode));
- out:
-       return rc;
- out_kfree:
-@@ -1058,23 +1066,32 @@
-       goto out;
- }
-+static int fib_seq_release(struct inode *inode, struct file *file)
++static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 +{
-+      struct seq_file *seq = file->private_data;
-+      struct fib_iter_state *iter = seq->private;
-+      put_net(iter->net);
-+      return seq_release_private(inode, file);
-+}
++      int error;
++      int len;
++      struct inode *inode;
++      struct page *page = NULL;
++      char *kaddr;
++      struct shmem_inode_info *info;
 +
- static const struct file_operations fib_seq_fops = {
-       .owner          = THIS_MODULE,
-       .open           = fib_seq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
--      .release        = seq_release_private,
-+      .release        = fib_seq_release,
- };
--int __init fib_proc_init(void)
-+int fib_proc_init(struct net *net)
- {
--      if (!proc_net_fops_create("route", S_IRUGO, &fib_seq_fops))
-+      net->fn_hash_last_dflt = -1;
-+      if (!proc_net_fops_create(net, "route", S_IRUGO, &fib_seq_fops))
-               return -ENOMEM;
-       return 0;
- }
--void __init fib_proc_exit(void)
-+void fib_proc_exit(struct net *net)
- {
--      proc_net_remove("route");
-+      proc_net_remove(net, "route");
- }
- #endif /* CONFIG_PROC_FS */
-diff -Nurb linux-2.6.22-570/net/ipv4/fib_rules.c linux-2.6.22-590/net/ipv4/fib_rules.c
---- linux-2.6.22-570/net/ipv4/fib_rules.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/fib_rules.c      2008-01-02 13:56:38.000000000 -0500
-@@ -32,8 +32,6 @@
- #include <net/ip_fib.h>
- #include <net/fib_rules.h>
--static struct fib_rules_ops fib4_rules_ops;
--
- struct fib4_rule
- {
-       struct fib_rule         common;
-@@ -49,35 +47,14 @@
- #endif
- };
--static struct fib4_rule default_rule = {
--      .common = {
--              .refcnt =       ATOMIC_INIT(2),
--              .pref =         0x7FFF,
--              .table =        RT_TABLE_DEFAULT,
--              .action =       FR_ACT_TO_TBL,
--      },
-+struct fib4_rule_table {
-+      struct list_head        fib4_rules;
-+      struct fib4_rule        default_rule;
-+      struct fib4_rule        main_rule;
-+      struct fib4_rule        local_rule;
-+      struct fib_rules_ops    fib4_rules_ops;
- };
--static struct fib4_rule main_rule = {
--      .common = {
--              .refcnt =       ATOMIC_INIT(2),
--              .pref =         0x7FFE,
--              .table =        RT_TABLE_MAIN,
--              .action =       FR_ACT_TO_TBL,
--      },
--};
--
--static struct fib4_rule local_rule = {
--      .common = {
--              .refcnt =       ATOMIC_INIT(2),
--              .table =        RT_TABLE_LOCAL,
--              .action =       FR_ACT_TO_TBL,
--              .flags =        FIB_RULE_PERMANENT,
--      },
--};
--
--static LIST_HEAD(fib4_rules);
--
- #ifdef CONFIG_NET_CLS_ROUTE
- u32 fib_rules_tclass(struct fib_result *res)
- {
-@@ -87,12 +64,14 @@
- int fib_lookup(struct flowi *flp, struct fib_result *res)
- {
-+      struct net *net = flp->fl_net;
-+      struct fib4_rule_table *table = net->fib4_table;
-       struct fib_lookup_arg arg = {
-               .result = res,
-       };
-       int err;
--      err = fib_rules_lookup(&fib4_rules_ops, flp, 0, &arg);
-+      err = fib_rules_lookup(&table->fib4_rules_ops, flp, 0, &arg);
-       res->r = arg.rule;
-       return err;
-@@ -122,7 +101,7 @@
-               goto errout;
-       }
--      if ((tbl = fib_get_table(rule->table)) == NULL)
-+      if ((tbl = fib_get_table(flp->fl_net, rule->table)) == NULL)
-               goto errout;
-       err = tbl->tb_lookup(tbl, flp, (struct fib_result *) arg->result);
-@@ -138,7 +117,7 @@
-       if (res->r && res->r->action == FR_ACT_TO_TBL &&
-           FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) {
-               struct fib_table *tb;
--              if ((tb = fib_get_table(res->r->table)) != NULL)
-+              if ((tb = fib_get_table(flp->fl_net, res->r->table)) != NULL)
-                       tb->tb_select_default(tb, flp, res);
-       }
- }
-@@ -159,13 +138,13 @@
-       return 1;
- }
--static struct fib_table *fib_empty_table(void)
-+static struct fib_table *fib_empty_table(struct net *net)
- {
-       u32 id;
-       for (id = 1; id <= RT_TABLE_MAX; id++)
--              if (fib_get_table(id) == NULL)
--                      return fib_new_table(id);
-+              if (fib_get_table(net, id) == NULL)
-+                      return fib_new_table(net, id);
-       return NULL;
- }
-@@ -178,6 +157,7 @@
-                              struct nlmsghdr *nlh, struct fib_rule_hdr *frh,
-                              struct nlattr **tb)
- {
-+      struct net *net = skb->sk->sk_net;
-       int err = -EINVAL;
-       struct fib4_rule *rule4 = (struct fib4_rule *) rule;
-@@ -188,7 +168,7 @@
-               if (rule->action == FR_ACT_TO_TBL) {
-                       struct fib_table *table;
--                      table = fib_empty_table();
-+                      table = fib_empty_table(net);
-                       if (table == NULL) {
-                               err = -ENOBUFS;
-                               goto errout;
-@@ -274,14 +254,15 @@
-       return -ENOBUFS;
- }
--static u32 fib4_rule_default_pref(void)
-+static u32 fib4_rule_default_pref(struct fib_rules_ops *ops)
- {
--      struct list_head *pos;
-+      struct list_head *list, *pos;
-       struct fib_rule *rule;
--      if (!list_empty(&fib4_rules)) {
--              pos = fib4_rules.next;
--              if (pos->next != &fib4_rules) {
-+      list = ops->rules_list;
-+      if (!list_empty(list)) {
-+              pos = list->next;
-+              if (pos->next != list) {
-                       rule = list_entry(pos->next, struct fib_rule, list);
-                       if (rule->pref)
-                               return rule->pref - 1;
-@@ -298,12 +279,37 @@
-              + nla_total_size(4); /* flow */
- }
--static void fib4_rule_flush_cache(void)
-+static void fib4_rule_flush_cache(struct fib_rules_ops *ops)
- {
-       rt_cache_flush(-1);
- }
--static struct fib_rules_ops fib4_rules_ops = {
-+static struct fib4_rule_table fib4_rule_table = {
-+      .default_rule = {
-+              .common = {
-+                      .refcnt =       ATOMIC_INIT(2),
-+                      .pref =         0x7FFF,
-+                      .table =        RT_TABLE_DEFAULT,
-+                      .action =       FR_ACT_TO_TBL,
-+              },
-+      },
-+      .main_rule = {
-+              .common = {
-+                      .refcnt =       ATOMIC_INIT(2),
-+                      .pref =         0x7FFE,
-+                      .table =        RT_TABLE_MAIN,
-+                      .action =       FR_ACT_TO_TBL,
-+              },
-+      },
-+      .local_rule = {
-+              .common = {
-+                      .refcnt =       ATOMIC_INIT(2),
-+                      .table =        RT_TABLE_LOCAL,
-+                      .action =       FR_ACT_TO_TBL,
-+                      .flags =        FIB_RULE_PERMANENT,
-+              },
-+      },
-+      .fib4_rules_ops = {
-       .family         = AF_INET,
-       .rule_size      = sizeof(struct fib4_rule),
-       .addr_size      = sizeof(u32),
-@@ -317,15 +323,34 @@
-       .flush_cache    = fib4_rule_flush_cache,
-       .nlgroup        = RTNLGRP_IPV4_RULE,
-       .policy         = fib4_rule_policy,
--      .rules_list     = &fib4_rules,
-+              .rules_list     = &fib4_rule_table.fib4_rules, /* &fib4_rules, */
-       .owner          = THIS_MODULE,
-+      },
- };
--void __init fib4_rules_init(void)
++      len = strlen(symname) + 1;
++      if (len > PAGE_CACHE_SIZE)
++              return -ENAMETOOLONG;
 +
-+void fib4_rules_init(struct net *net)
- {
--      list_add_tail(&local_rule.common.list, &fib4_rules);
--      list_add_tail(&main_rule.common.list, &fib4_rules);
--      list_add_tail(&default_rule.common.list, &fib4_rules);
-+      struct fib4_rule_table *table;
-+      table = kmemdup(&fib4_rule_table, sizeof(*table), GFP_KERNEL);
-+      if (!table)
-+              return;
-+      INIT_LIST_HEAD(&table->fib4_rules);
-+      list_add_tail(&table->local_rule.common.list,   &table->fib4_rules);
-+      list_add_tail(&table->main_rule.common.list,    &table->fib4_rules);
-+      list_add_tail(&table->default_rule.common.list, &table->fib4_rules);
-+      table->fib4_rules_ops.rules_list = &table->fib4_rules;
-+      if (fib_rules_register(net, &table->fib4_rules_ops)) {
-+              kfree(table);
-+              return;
-+      }
-+      net->fib4_table = table;
-+}
--      fib_rules_register(&fib4_rules_ops);
-+void fib4_rules_exit(struct net *net)
-+{
-+      struct fib4_rule_table *table = net->fib4_table;
-+      if (table)
-+              fib_rules_unregister(net, &table->fib4_rules_ops);
-+      kfree(table);
- }
-diff -Nurb linux-2.6.22-570/net/ipv4/fib_semantics.c linux-2.6.22-590/net/ipv4/fib_semantics.c
---- linux-2.6.22-570/net/ipv4/fib_semantics.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/fib_semantics.c  2008-01-02 13:56:38.000000000 -0500
-@@ -42,7 +42,6 @@
- #include <net/tcp.h>
- #include <net/sock.h>
- #include <net/ip_fib.h>
--#include <net/ip_mp_alg.h>
- #include <net/netlink.h>
- #include <net/nexthop.h>
-@@ -51,14 +50,9 @@
- #define FSprintk(a...)
- static DEFINE_SPINLOCK(fib_info_lock);
--static struct hlist_head *fib_info_hash;
--static struct hlist_head *fib_info_laddrhash;
--static unsigned int fib_hash_size;
--static unsigned int fib_info_cnt;
- #define DEVINDEX_HASHBITS 8
- #define DEVINDEX_HASHSIZE (1U << DEVINDEX_HASHBITS)
--static struct hlist_head fib_info_devhash[DEVINDEX_HASHSIZE];
- #ifdef CONFIG_IP_ROUTE_MULTIPATH
-@@ -154,7 +148,8 @@
-                       dev_put(nh->nh_dev);
-               nh->nh_dev = NULL;
-       } endfor_nexthops(fi);
--      fib_info_cnt--;
-+      fi->fib_net->fib_info_cnt--;
-+      release_net(fi->fib_net);
-       kfree(fi);
- }
-@@ -197,9 +192,9 @@
-       return 0;
- }
--static inline unsigned int fib_info_hashfn(const struct fib_info *fi)
-+static inline unsigned int fib_info_hashfn(struct net *net, const struct fib_info *fi)
- {
--      unsigned int mask = (fib_hash_size - 1);
-+      unsigned int mask = net->fib_info_hash_size - 1;
-       unsigned int val = fi->fib_nhs;
-       val ^= fi->fib_protocol;
-@@ -209,15 +204,15 @@
-       return (val ^ (val >> 7) ^ (val >> 12)) & mask;
- }
--static struct fib_info *fib_find_info(const struct fib_info *nfi)
-+static struct fib_info *fib_find_info(struct net *net, const struct fib_info *nfi)
- {
-       struct hlist_head *head;
-       struct hlist_node *node;
-       struct fib_info *fi;
-       unsigned int hash;
--      hash = fib_info_hashfn(nfi);
--      head = &fib_info_hash[hash];
-+      hash = fib_info_hashfn(net, nfi);
-+      head = &net->fib_info_hash[hash];
-       hlist_for_each_entry(fi, node, head, fib_hash) {
-               if (fi->fib_nhs != nfi->fib_nhs)
-@@ -250,6 +245,7 @@
- int ip_fib_check_default(__be32 gw, struct net_device *dev)
- {
-+      struct net *net = dev->nd_net;
-       struct hlist_head *head;
-       struct hlist_node *node;
-       struct fib_nh *nh;
-@@ -258,7 +254,7 @@
-       spin_lock(&fib_info_lock);
-       hash = fib_devindex_hashfn(dev->ifindex);
--      head = &fib_info_devhash[hash];
-+      head = &net->fib_info_devhash[hash];
-       hlist_for_each_entry(nh, node, head, nh_hash) {
-               if (nh->nh_dev == dev &&
-                   nh->nh_gw == gw &&
-@@ -321,11 +317,11 @@
-               kfree_skb(skb);
-               goto errout;
-       }
--      err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
-+      err = rtnl_notify(skb, info->net, info->pid, RTNLGRP_IPV4_ROUTE,
-                         info->nlh, GFP_KERNEL);
- errout:
-       if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_IPV4_ROUTE, err);
-+              rtnl_set_sk_err(info->net, RTNLGRP_IPV4_ROUTE, err);
- }
- /* Return the first fib alias matching TOS with
-@@ -518,6 +514,7 @@
- static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
-                       struct fib_nh *nh)
- {
-+      struct net *net = cfg->fc_nlinfo.net;
-       int err;
-       if (nh->nh_gw) {
-@@ -532,9 +529,9 @@
-                       if (cfg->fc_scope >= RT_SCOPE_LINK)
-                               return -EINVAL;
--                      if (inet_addr_type(nh->nh_gw) != RTN_UNICAST)
-+                      if (inet_addr_type(net, nh->nh_gw) != RTN_UNICAST)
-                               return -EINVAL;
--                      if ((dev = __dev_get_by_index(nh->nh_oif)) == NULL)
-+                      if ((dev = __dev_get_by_index(net, nh->nh_oif)) == NULL)
-                               return -ENODEV;
-                       if (!(dev->flags&IFF_UP))
-                               return -ENETDOWN;
-@@ -545,6 +542,7 @@
-               }
-               {
-                       struct flowi fl = {
-+                              .fl_net = net,
-                               .nl_u = {
-                                       .ip4_u = {
-                                               .daddr = nh->nh_gw,
-@@ -581,7 +579,7 @@
-               if (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK))
-                       return -EINVAL;
--              in_dev = inetdev_by_index(nh->nh_oif);
-+              in_dev = inetdev_by_index(net, nh->nh_oif);
-               if (in_dev == NULL)
-                       return -ENODEV;
-               if (!(in_dev->dev->flags&IFF_UP)) {
-@@ -596,9 +594,9 @@
-       return 0;
- }
--static inline unsigned int fib_laddr_hashfn(__be32 val)
-+static inline unsigned int fib_laddr_hashfn(struct net *net, __be32 val)
- {
--      unsigned int mask = (fib_hash_size - 1);
-+      unsigned int mask = net->fib_info_hash_size - 1;
-       return ((__force u32)val ^ ((__force u32)val >> 7) ^ ((__force u32)val >> 14)) & mask;
- }
-@@ -623,21 +621,22 @@
-               free_pages((unsigned long) hash, get_order(bytes));
- }
--static void fib_hash_move(struct hlist_head *new_info_hash,
-+static void fib_hash_move(struct net *net,
-+                        struct hlist_head *new_info_hash,
-                         struct hlist_head *new_laddrhash,
-                         unsigned int new_size)
- {
-       struct hlist_head *old_info_hash, *old_laddrhash;
--      unsigned int old_size = fib_hash_size;
-+      unsigned int old_size = net->fib_info_hash_size;
-       unsigned int i, bytes;
-       spin_lock_bh(&fib_info_lock);
--      old_info_hash = fib_info_hash;
--      old_laddrhash = fib_info_laddrhash;
--      fib_hash_size = new_size;
-+      old_info_hash = net->fib_info_hash;
-+      old_laddrhash = net->fib_info_laddrhash;
-+      net->fib_info_hash_size = new_size;
-       for (i = 0; i < old_size; i++) {
--              struct hlist_head *head = &fib_info_hash[i];
-+              struct hlist_head *head = &net->fib_info_hash[i];
-               struct hlist_node *node, *n;
-               struct fib_info *fi;
-@@ -647,15 +646,15 @@
-                       hlist_del(&fi->fib_hash);
--                      new_hash = fib_info_hashfn(fi);
-+                      new_hash = fib_info_hashfn(net, fi);
-                       dest = &new_info_hash[new_hash];
-                       hlist_add_head(&fi->fib_hash, dest);
-               }
-       }
--      fib_info_hash = new_info_hash;
-+      net->fib_info_hash = new_info_hash;
-       for (i = 0; i < old_size; i++) {
--              struct hlist_head *lhead = &fib_info_laddrhash[i];
-+              struct hlist_head *lhead = &net->fib_info_laddrhash[i];
-               struct hlist_node *node, *n;
-               struct fib_info *fi;
-@@ -665,12 +664,12 @@
-                       hlist_del(&fi->fib_lhash);
--                      new_hash = fib_laddr_hashfn(fi->fib_prefsrc);
-+                      new_hash = fib_laddr_hashfn(net, fi->fib_prefsrc);
-                       ldest = &new_laddrhash[new_hash];
-                       hlist_add_head(&fi->fib_lhash, ldest);
-               }
-       }
--      fib_info_laddrhash = new_laddrhash;
-+      net->fib_info_laddrhash = new_laddrhash;
-       spin_unlock_bh(&fib_info_lock);
-@@ -681,6 +680,7 @@
- struct fib_info *fib_create_info(struct fib_config *cfg)
- {
-+      struct net *net = cfg->fc_nlinfo.net;
-       int err;
-       struct fib_info *fi = NULL;
-       struct fib_info *ofi;
-@@ -697,17 +697,10 @@
-                       goto err_inval;
-       }
- #endif
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      if (cfg->fc_mp_alg) {
--              if (cfg->fc_mp_alg < IP_MP_ALG_NONE ||
--                  cfg->fc_mp_alg > IP_MP_ALG_MAX)
--                      goto err_inval;
--      }
--#endif
-       err = -ENOBUFS;
--      if (fib_info_cnt >= fib_hash_size) {
--              unsigned int new_size = fib_hash_size << 1;
-+      if (net->fib_info_cnt >= net->fib_info_hash_size) {
-+              unsigned int new_size = net->fib_info_hash_size << 1;
-               struct hlist_head *new_info_hash;
-               struct hlist_head *new_laddrhash;
-               unsigned int bytes;
-@@ -724,18 +717,19 @@
-                       memset(new_info_hash, 0, bytes);
-                       memset(new_laddrhash, 0, bytes);
--                      fib_hash_move(new_info_hash, new_laddrhash, new_size);
-+                      fib_hash_move(net, new_info_hash, new_laddrhash, new_size);
-               }
--              if (!fib_hash_size)
-+              if (!net->fib_info_hash_size)
-                       goto failure;
-       }
-       fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
-       if (fi == NULL)
-               goto failure;
--      fib_info_cnt++;
-+      net->fib_info_cnt++;
-+      fi->fib_net = hold_net(net);
-       fi->fib_protocol = cfg->fc_protocol;
-       fi->fib_flags = cfg->fc_flags;
-       fi->fib_priority = cfg->fc_priority;
-@@ -791,10 +785,6 @@
- #endif
-       }
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      fi->fib_mp_alg = cfg->fc_mp_alg;
--#endif
--
-       if (fib_props[cfg->fc_type].error) {
-               if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
-                       goto err_inval;
-@@ -811,7 +801,7 @@
-               if (nhs != 1 || nh->nh_gw)
-                       goto err_inval;
-               nh->nh_scope = RT_SCOPE_NOWHERE;
--              nh->nh_dev = dev_get_by_index(fi->fib_nh->nh_oif);
-+              nh->nh_dev = dev_get_by_index(net, fi->fib_nh->nh_oif);
-               err = -ENODEV;
-               if (nh->nh_dev == NULL)
-                       goto failure;
-@@ -825,12 +815,12 @@
-       if (fi->fib_prefsrc) {
-               if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
-                   fi->fib_prefsrc != cfg->fc_dst)
--                      if (inet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
-+                      if (inet_addr_type(net, fi->fib_prefsrc) != RTN_LOCAL)
-                               goto err_inval;
-       }
- link_it:
--      if ((ofi = fib_find_info(fi)) != NULL) {
-+      if ((ofi = fib_find_info(net, fi)) != NULL) {
-               fi->fib_dead = 1;
-               free_fib_info(fi);
-               ofi->fib_treeref++;
-@@ -841,11 +831,13 @@
-       atomic_inc(&fi->fib_clntref);
-       spin_lock_bh(&fib_info_lock);
-       hlist_add_head(&fi->fib_hash,
--                     &fib_info_hash[fib_info_hashfn(fi)]);
-+                     &net->fib_info_hash[fib_info_hashfn(net, fi)]);
-       if (fi->fib_prefsrc) {
-               struct hlist_head *head;
-+              unsigned int hash;
--              head = &fib_info_laddrhash[fib_laddr_hashfn(fi->fib_prefsrc)];
-+              hash = fib_laddr_hashfn(net, fi->fib_prefsrc);
-+              head = &net->fib_info_laddrhash[hash];
-               hlist_add_head(&fi->fib_lhash, head);
-       }
-       change_nexthops(fi) {
-@@ -855,7 +847,7 @@
-               if (!nh->nh_dev)
-                       continue;
-               hash = fib_devindex_hashfn(nh->nh_dev->ifindex);
--              head = &fib_info_devhash[hash];
-+              head = &net->fib_info_devhash[hash];
-               hlist_add_head(&nh->nh_hash, head);
-       } endfor_nexthops(fi)
-       spin_unlock_bh(&fib_info_lock);
-@@ -940,10 +932,6 @@
-       res->type = fa->fa_type;
-       res->scope = fa->fa_scope;
-       res->fi = fa->fa_info;
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      res->netmask = mask;
--      res->network = zone & inet_make_mask(prefixlen);
--#endif
-       atomic_inc(&res->fi->fib_clntref);
-       return 0;
- }
-@@ -1046,7 +1034,7 @@
-    - device went down -> we must shutdown all nexthops going via it.
-  */
--int fib_sync_down(__be32 local, struct net_device *dev, int force)
-+int fib_sync_down(struct net *net, __be32 local, struct net_device *dev, int force)
- {
-       int ret = 0;
-       int scope = RT_SCOPE_NOWHERE;
-@@ -1054,9 +1042,9 @@
-       if (force)
-               scope = -1;
--      if (local && fib_info_laddrhash) {
--              unsigned int hash = fib_laddr_hashfn(local);
--              struct hlist_head *head = &fib_info_laddrhash[hash];
-+      if (local && net->fib_info_laddrhash) {
-+              unsigned int hash = fib_laddr_hashfn(net, local);
-+              struct hlist_head *head = &net->fib_info_laddrhash[hash];
-               struct hlist_node *node;
-               struct fib_info *fi;
-@@ -1071,7 +1059,7 @@
-       if (dev) {
-               struct fib_info *prev_fi = NULL;
-               unsigned int hash = fib_devindex_hashfn(dev->ifindex);
--              struct hlist_head *head = &fib_info_devhash[hash];
-+              struct hlist_head *head = &net->fib_info_devhash[hash];
-               struct hlist_node *node;
-               struct fib_nh *nh;
-@@ -1124,6 +1112,7 @@
- int fib_sync_up(struct net_device *dev)
- {
-+      struct net *net = dev->nd_net;
-       struct fib_info *prev_fi;
-       unsigned int hash;
-       struct hlist_head *head;
-@@ -1136,7 +1125,7 @@
-       prev_fi = NULL;
-       hash = fib_devindex_hashfn(dev->ifindex);
--      head = &fib_info_devhash[hash];
-+      head = &net->fib_info_devhash[hash];
-       ret = 0;
-       hlist_for_each_entry(nh, node, head, nh_hash) {
-@@ -1226,3 +1215,17 @@
-       spin_unlock_bh(&fib_multipath_lock);
- }
- #endif
++      inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
++      if (!inode)
++              return -ENOSPC;
++
++      error = security_inode_init_security(inode, dir, NULL, NULL,
++                                           NULL);
++      if (error) {
++              if (error != -EOPNOTSUPP) {
++                      iput(inode);
++                      return error;
++              }
++              error = 0;
++      }
++
++      info = SHMEM_I(inode);
++      inode->i_size = len-1;
++      if (len <= (char *)inode - (char *)info) {
++              /* do it inline */
++              memcpy(info, symname, len);
++              inode->i_op = &shmem_symlink_inline_operations;
++      } else {
++              error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
++              if (error) {
++                      iput(inode);
++                      return error;
++              }
++              inode->i_op = &shmem_symlink_inode_operations;
++              kaddr = kmap_atomic(page, KM_USER0);
++              memcpy(kaddr, symname, len);
++              kunmap_atomic(kaddr, KM_USER0);
++              set_page_dirty(page);
++              page_cache_release(page);
++      }
++      if (dir->i_mode & S_ISGID)
++              inode->i_gid = dir->i_gid;
++      dir->i_size += BOGO_DIRENT_SIZE;
++      dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++      d_instantiate(dentry, inode);
++      dget(dentry);
++      return 0;
++}
++
++static void *shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
++{
++      nd_set_link(nd, (char *)SHMEM_I(dentry->d_inode));
++      return NULL;
++}
++
++static void *shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
++{
++      struct page *page = NULL;
++      int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL);
++      nd_set_link(nd, res ? ERR_PTR(res) : kmap(page));
++      return page;
++}
++
++static void shmem_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
++{
++      if (!IS_ERR(nd_get_link(nd))) {
++              struct page *page = cookie;
++              kunmap(page);
++              mark_page_accessed(page);
++              page_cache_release(page);
++      }
++}
++
++static const struct inode_operations shmem_symlink_inline_operations = {
++      .readlink       = generic_readlink,
++      .follow_link    = shmem_follow_link_inline,
++};
++
++static const struct inode_operations shmem_symlink_inode_operations = {
++      .truncate       = shmem_truncate,
++      .readlink       = generic_readlink,
++      .follow_link    = shmem_follow_link,
++      .put_link       = shmem_put_link,
++};
++
++#ifdef CONFIG_TMPFS_POSIX_ACL
++/**
++ * Superblocks without xattr inode operations will get security.* xattr
++ * support from the VFS "for free". As soon as we have any other xattrs
++ * like ACLs, we also need to implement the security.* handlers at
++ * filesystem level, though.
++ */
++
++static size_t shmem_xattr_security_list(struct inode *inode, char *list,
++                                      size_t list_len, const char *name,
++                                      size_t name_len)
++{
++      return security_inode_listsecurity(inode, list, list_len);
++}
++
++static int shmem_xattr_security_get(struct inode *inode, const char *name,
++                                  void *buffer, size_t size)
++{
++      if (strcmp(name, "") == 0)
++              return -EINVAL;
++      return security_inode_getsecurity(inode, name, buffer, size,
++                                        -EOPNOTSUPP);
++}
++
++static int shmem_xattr_security_set(struct inode *inode, const char *name,
++                                  const void *value, size_t size, int flags)
++{
++      if (strcmp(name, "") == 0)
++              return -EINVAL;
++      return security_inode_setsecurity(inode, name, value, size, flags);
++}
++
++static struct xattr_handler shmem_xattr_security_handler = {
++      .prefix = XATTR_SECURITY_PREFIX,
++      .list   = shmem_xattr_security_list,
++      .get    = shmem_xattr_security_get,
++      .set    = shmem_xattr_security_set,
++};
++
++static struct xattr_handler *shmem_xattr_handlers[] = {
++      &shmem_xattr_acl_access_handler,
++      &shmem_xattr_acl_default_handler,
++      &shmem_xattr_security_handler,
++      NULL
++};
++#endif
++
++static struct dentry *shmem_get_parent(struct dentry *child)
++{
++      return ERR_PTR(-ESTALE);
++}
++
++static int shmem_match(struct inode *ino, void *vfh)
++{
++      __u32 *fh = vfh;
++      __u64 inum = fh[2];
++      inum = (inum << 32) | fh[1];
++      return ino->i_ino == inum && fh[0] == ino->i_generation;
++}
++
++static struct dentry *shmem_get_dentry(struct super_block *sb, void *vfh)
++{
++      struct dentry *de = NULL;
++      struct inode *inode;
++      __u32 *fh = vfh;
++      __u64 inum = fh[2];
++      inum = (inum << 32) | fh[1];
++
++      inode = ilookup5(sb, (unsigned long)(inum+fh[0]), shmem_match, vfh);
++      if (inode) {
++              de = d_find_alias(inode);
++              iput(inode);
++      }
++
++      return de? de: ERR_PTR(-ESTALE);
++}
++
++static struct dentry *shmem_decode_fh(struct super_block *sb, __u32 *fh,
++              int len, int type,
++              int (*acceptable)(void *context, struct dentry *de),
++              void *context)
++{
++      if (len < 3)
++              return ERR_PTR(-ESTALE);
++
++      return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable,
++                                                      context);
++}
++
++static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
++                              int connectable)
++{
++      struct inode *inode = dentry->d_inode;
++
++      if (*len < 3)
++              return 255;
++
++      if (hlist_unhashed(&inode->i_hash)) {
++              /* Unfortunately insert_inode_hash is not idempotent,
++               * so as we hash inodes here rather than at creation
++               * time, we need a lock to ensure we only try
++               * to do it once
++               */
++              static DEFINE_SPINLOCK(lock);
++              spin_lock(&lock);
++              if (hlist_unhashed(&inode->i_hash))
++                      __insert_inode_hash(inode,
++                                          inode->i_ino + inode->i_generation);
++              spin_unlock(&lock);
++      }
++
++      fh[0] = inode->i_generation;
++      fh[1] = inode->i_ino;
++      fh[2] = ((__u64)inode->i_ino) >> 32;
++
++      *len = 3;
++      return 1;
++}
++
++static struct export_operations shmem_export_ops = {
++      .get_parent     = shmem_get_parent,
++      .get_dentry     = shmem_get_dentry,
++      .encode_fh      = shmem_encode_fh,
++      .decode_fh      = shmem_decode_fh,
++};
++
++static int shmem_parse_options(char *options, int *mode, uid_t *uid,
++      gid_t *gid, unsigned long *blocks, unsigned long *inodes,
++      int *policy, nodemask_t *policy_nodes)
++{
++      char *this_char, *value, *rest;
++
++      while (options != NULL) {
++              this_char = options;
++              for (;;) {
++                      /*
++                       * NUL-terminate this option: unfortunately,
++                       * mount options form a comma-separated list,
++                       * but mpol's nodelist may also contain commas.
++                       */
++                      options = strchr(options, ',');
++                      if (options == NULL)
++                              break;
++                      options++;
++                      if (!isdigit(*options)) {
++                              options[-1] = '\0';
++                              break;
++                      }
++              }
++              if (!*this_char)
++                      continue;
++              if ((value = strchr(this_char,'=')) != NULL) {
++                      *value++ = 0;
++              } else {
++                      printk(KERN_ERR
++                          "tmpfs: No value for mount option '%s'\n",
++                          this_char);
++                      return 1;
++              }
++
++              if (!strcmp(this_char,"size")) {
++                      unsigned long long size;
++                      size = memparse(value,&rest);
++                      if (*rest == '%') {
++                              size <<= PAGE_SHIFT;
++                              size *= totalram_pages;
++                              do_div(size, 100);
++                              rest++;
++                      }
++                      if (*rest)
++                              goto bad_val;
++                      *blocks = size >> PAGE_CACHE_SHIFT;
++              } else if (!strcmp(this_char,"nr_blocks")) {
++                      *blocks = memparse(value,&rest);
++                      if (*rest)
++                              goto bad_val;
++              } else if (!strcmp(this_char,"nr_inodes")) {
++                      *inodes = memparse(value,&rest);
++                      if (*rest)
++                              goto bad_val;
++              } else if (!strcmp(this_char,"mode")) {
++                      if (!mode)
++                              continue;
++                      *mode = simple_strtoul(value,&rest,8);
++                      if (*rest)
++                              goto bad_val;
++              } else if (!strcmp(this_char,"uid")) {
++                      if (!uid)
++                              continue;
++                      *uid = simple_strtoul(value,&rest,0);
++                      if (*rest)
++                              goto bad_val;
++              } else if (!strcmp(this_char,"gid")) {
++                      if (!gid)
++                              continue;
++                      *gid = simple_strtoul(value,&rest,0);
++                      if (*rest)
++                              goto bad_val;
++              } else if (!strcmp(this_char,"mpol")) {
++                      if (shmem_parse_mpol(value,policy,policy_nodes))
++                              goto bad_val;
++              } else {
++                      printk(KERN_ERR "tmpfs: Bad mount option %s\n",
++                             this_char);
++                      return 1;
++              }
++      }
++      return 0;
++
++bad_val:
++      printk(KERN_ERR "tmpfs: Bad value '%s' for mount option '%s'\n",
++             value, this_char);
++      return 1;
++
++}
++
++static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
++{
++      struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
++      unsigned long max_blocks = sbinfo->max_blocks;
++      unsigned long max_inodes = sbinfo->max_inodes;
++      int policy = sbinfo->policy;
++      nodemask_t policy_nodes = sbinfo->policy_nodes;
++      unsigned long blocks;
++      unsigned long inodes;
++      int error = -EINVAL;
++
++      if (shmem_parse_options(data, NULL, NULL, NULL, &max_blocks,
++                              &max_inodes, &policy, &policy_nodes))
++              return error;
++
++      spin_lock(&sbinfo->stat_lock);
++      blocks = sbinfo->max_blocks - sbinfo->free_blocks;
++      inodes = sbinfo->max_inodes - sbinfo->free_inodes;
++      if (max_blocks < blocks)
++              goto out;
++      if (max_inodes < inodes)
++              goto out;
++      /*
++       * Those tests also disallow limited->unlimited while any are in
++       * use, so i_blocks will always be zero when max_blocks is zero;
++       * but we must separately disallow unlimited->limited, because
++       * in that case we have no record of how much is already in use.
++       */
++      if (max_blocks && !sbinfo->max_blocks)
++              goto out;
++      if (max_inodes && !sbinfo->max_inodes)
++              goto out;
++
++      error = 0;
++      sbinfo->max_blocks  = max_blocks;
++      sbinfo->free_blocks = max_blocks - blocks;
++      sbinfo->max_inodes  = max_inodes;
++      sbinfo->free_inodes = max_inodes - inodes;
++      sbinfo->policy = policy;
++      sbinfo->policy_nodes = policy_nodes;
++out:
++      spin_unlock(&sbinfo->stat_lock);
++      return error;
++}
++#endif
++
++static void shmem_put_super(struct super_block *sb)
++{
++      kfree(sb->s_fs_info);
++      sb->s_fs_info = NULL;
++}
 +
-+int fib_info_init(struct net *net)
++static int shmem_fill_super(struct super_block *sb,
++                          void *data, int silent)
 +{
-+      net->fib_info_devhash = kzalloc(
-+              sizeof(struct hlist_head)*DEVINDEX_HASHSIZE, GFP_KERNEL);
-+      if (!net->fib_info_devhash)
++      struct inode *inode;
++      struct dentry *root;
++      int mode   = S_IRWXUGO | S_ISVTX;
++      uid_t uid = current->fsuid;
++      gid_t gid = current->fsgid;
++      int err = -ENOMEM;
++      struct shmem_sb_info *sbinfo;
++      unsigned long blocks = 0;
++      unsigned long inodes = 0;
++      int policy = MPOL_DEFAULT;
++      nodemask_t policy_nodes = node_online_map;
++
++#ifdef CONFIG_TMPFS
++      /*
++       * Per default we only allow half of the physical ram per
++       * tmpfs instance, limiting inodes to one per page of lowmem;
++       * but the internal instance is left unlimited.
++       */
++      if (!(sb->s_flags & MS_NOUSER)) {
++              blocks = totalram_pages / 2;
++              inodes = totalram_pages - totalhigh_pages;
++              if (inodes > blocks)
++                      inodes = blocks;
++              if (shmem_parse_options(data, &mode, &uid, &gid, &blocks,
++                                      &inodes, &policy, &policy_nodes))
++                      return -EINVAL;
++      }
++      sb->s_export_op = &shmem_export_ops;
++#else
++      sb->s_flags |= MS_NOUSER;
++#endif
++
++      /* Round up to L1_CACHE_BYTES to resist false sharing */
++      sbinfo = kmalloc(max((int)sizeof(struct shmem_sb_info),
++                              L1_CACHE_BYTES), GFP_KERNEL);
++      if (!sbinfo)
 +              return -ENOMEM;
++
++      spin_lock_init(&sbinfo->stat_lock);
++      sbinfo->max_blocks = blocks;
++      sbinfo->free_blocks = blocks;
++      sbinfo->max_inodes = inodes;
++      sbinfo->free_inodes = inodes;
++      sbinfo->policy = policy;
++      sbinfo->policy_nodes = policy_nodes;
++
++      sb->s_fs_info = sbinfo;
++      sb->s_maxbytes = SHMEM_MAX_BYTES;
++      sb->s_blocksize = PAGE_CACHE_SIZE;
++      sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
++      sb->s_magic = TMPFS_MAGIC;
++      sb->s_op = &shmem_ops;
++      sb->s_time_gran = 1;
++#ifdef CONFIG_TMPFS_POSIX_ACL
++      sb->s_xattr = shmem_xattr_handlers;
++      sb->s_flags |= MS_POSIXACL;
++#endif
++
++      inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
++      if (!inode)
++              goto failed;
++      inode->i_uid = uid;
++      inode->i_gid = gid;
++      root = d_alloc_root(inode);
++      if (!root)
++              goto failed_iput;
++      sb->s_root = root;
 +      return 0;
++
++failed_iput:
++      iput(inode);
++failed:
++      shmem_put_super(sb);
++      return err;
 +}
 +
-+void fib_info_exit(struct net *net)
++static struct kmem_cache *shmem_inode_cachep;
++
++static struct inode *shmem_alloc_inode(struct super_block *sb)
 +{
-+      kfree(net->fib_info_devhash);
++      struct shmem_inode_info *p;
++      p = (struct shmem_inode_info *)kmem_cache_alloc(shmem_inode_cachep, GFP_KERNEL);
++      if (!p)
++              return NULL;
++      return &p->vfs_inode;
 +}
-diff -Nurb linux-2.6.22-570/net/ipv4/fib_trie.c linux-2.6.22-590/net/ipv4/fib_trie.c
---- linux-2.6.22-570/net/ipv4/fib_trie.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/fib_trie.c       2008-01-02 13:56:38.000000000 -0500
-@@ -78,6 +78,7 @@
- #include <net/route.h>
- #include <net/tcp.h>
- #include <net/sock.h>
-+#include <net/net_namespace.h>
- #include <net/ip_fib.h>
- #include "fib_lookup.h"
-@@ -172,7 +173,6 @@
- static void tnode_free(struct tnode *tn);
- static struct kmem_cache *fn_alias_kmem __read_mostly;
--static struct trie *trie_local = NULL, *trie_main = NULL;
- /* rcu_read_lock needs to be hold by caller from readside */
-@@ -290,11 +290,10 @@
-       WARN_ON(tn && tn->pos+tn->bits > 32);
- }
--static int halve_threshold = 25;
--static int inflate_threshold = 50;
--static int halve_threshold_root = 8;
--static int inflate_threshold_root = 15;
--
-+static const int halve_threshold = 25;
-+static const int inflate_threshold = 50;
-+static const int halve_threshold_root = 15;
-+static const int inflate_threshold_root = 25;
- static void __alias_free_mem(struct rcu_head *head)
- {
-@@ -1771,11 +1770,10 @@
-       return found;
- }
--static int trie_last_dflt = -1;
--
- static void
- fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
- {
-+      struct net *net = flp->fl_net;
-       struct trie *t = (struct trie *) tb->tb_data;
-       int order, last_idx;
-       struct fib_info *fi = NULL;
-@@ -1819,28 +1817,28 @@
-                       if (next_fi != res->fi)
-                               break;
-               } else if (!fib_detect_death(fi, order, &last_resort,
--                                           &last_idx, &trie_last_dflt)) {
-+                                           &last_idx, &net->trie_last_dflt)) {
-                       if (res->fi)
-                               fib_info_put(res->fi);
-                       res->fi = fi;
-                       atomic_inc(&fi->fib_clntref);
--                      trie_last_dflt = order;
-+                      net->trie_last_dflt = order;
-                       goto out;
-               }
-               fi = next_fi;
-               order++;
-       }
-       if (order <= 0 || fi == NULL) {
--              trie_last_dflt = -1;
-+              net->trie_last_dflt = -1;
-               goto out;
-       }
--      if (!fib_detect_death(fi, order, &last_resort, &last_idx, &trie_last_dflt)) {
-+      if (!fib_detect_death(fi, order, &last_resort, &last_idx, &net->trie_last_dflt)) {
-               if (res->fi)
-                       fib_info_put(res->fi);
-               res->fi = fi;
-               atomic_inc(&fi->fib_clntref);
--              trie_last_dflt = order;
-+              net->trie_last_dflt = order;
-               goto out;
-       }
-       if (last_idx >= 0) {
-@@ -1850,7 +1848,7 @@
-               if (last_resort)
-                       atomic_inc(&last_resort->fib_clntref);
-       }
--      trie_last_dflt = last_idx;
-+      net->trie_last_dflt = last_idx;
-  out:;
-       rcu_read_unlock();
- }
-@@ -1957,11 +1955,15 @@
- /* Fix more generic FIB names for init later */
--#ifdef CONFIG_IP_MULTIPLE_TABLES
-+void fib_hash_exit(struct fib_table *tb)
++
++static void shmem_destroy_inode(struct inode *inode)
 +{
-+      if (!tb)
-+              return;
-+      fn_trie_flush(tb);
-+      kfree(tb);
++      if ((inode->i_mode & S_IFMT) == S_IFREG) {
++              /* only struct inode is valid if it's an inline symlink */
++              mpol_free_shared_policy(&SHMEM_I(inode)->policy);
++      }
++      shmem_acl_destroy_inode(inode);
++      kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
 +}
 +
- struct fib_table * fib_hash_init(u32 id)
--#else
--struct fib_table * __init fib_hash_init(u32 id)
--#endif
- {
-       struct fib_table *tb;
-       struct trie *t;
-@@ -1991,11 +1993,6 @@
-       trie_init(t);
-       if (id == RT_TABLE_LOCAL)
--              trie_local = t;
--      else if (id == RT_TABLE_MAIN)
--              trie_main = t;
--
--      if (id == RT_TABLE_LOCAL)
-               printk(KERN_INFO "IPv4 FIB: Using LC-trie version %s\n", VERSION);
-       return tb;
-@@ -2004,6 +2001,8 @@
- #ifdef CONFIG_PROC_FS
- /* Depth first Trie walk iterator */
- struct fib_trie_iter {
-+      struct net *net;
-+      struct trie *trie_local, *trie_main;
-       struct tnode *tnode;
-       struct trie *trie;
-       unsigned index;
-@@ -2170,7 +2169,21 @@
- static int fib_triestat_seq_show(struct seq_file *seq, void *v)
- {
-+      struct net *net = seq->private;
-+      struct trie *trie_local, *trie_main;
-       struct trie_stat *stat;
-+      struct fib_table *tb;
++static void init_once(void *foo, struct kmem_cache *cachep,
++                    unsigned long flags)
++{
++      struct shmem_inode_info *p = (struct shmem_inode_info *) foo;
 +
-+      trie_local = NULL;
-+      tb = fib_get_table(net, RT_TABLE_LOCAL);
-+      if (tb)
-+              trie_local = (struct trie *) tb->tb_data;
++      inode_init_once(&p->vfs_inode);
++#ifdef CONFIG_TMPFS_POSIX_ACL
++      p->i_acl = NULL;
++      p->i_default_acl = NULL;
++#endif
++}
 +
-+      trie_main = NULL;
-+      tb = fib_get_table(net, RT_TABLE_MAIN);
-+      if (tb)
-+              trie_main = (struct trie *) tb->tb_data;
++static int init_inodecache(void)
++{
++      shmem_inode_cachep = kmem_cache_create("shmem_inode_cache",
++                              sizeof(struct shmem_inode_info),
++                              0, 0, init_once, NULL);
++      if (shmem_inode_cachep == NULL)
++              return -ENOMEM;
++      return 0;
++}
 +
-       stat = kmalloc(sizeof(*stat), GFP_KERNEL);
-       if (!stat)
-@@ -2197,7 +2210,15 @@
- static int fib_triestat_seq_open(struct inode *inode, struct file *file)
- {
--      return single_open(file, fib_triestat_seq_show, NULL);
-+      return single_open(file, fib_triestat_seq_show, 
-+                              get_net(PROC_NET(inode)));
++static void destroy_inodecache(void)
++{
++      kmem_cache_destroy(shmem_inode_cachep);
 +}
 +
-+static int fib_triestat_seq_release(struct inode *inode, struct file *file)
++static const struct address_space_operations shmem_aops = {
++      .writepage      = shmem_writepage,
++      .set_page_dirty = __set_page_dirty_no_writeback,
++#ifdef CONFIG_TMPFS
++      .prepare_write  = shmem_prepare_write,
++      .commit_write   = simple_commit_write,
++#endif
++      .migratepage    = migrate_page,
++};
++
++static const struct file_operations shmem_file_operations = {
++      .mmap           = shmem_mmap,
++#ifdef CONFIG_TMPFS
++      .llseek         = generic_file_llseek,
++      .read           = shmem_file_read,
++      .write          = shmem_file_write,
++      .fsync          = simple_sync_file,
++      .sendfile       = shmem_file_sendfile,
++#endif
++};
++
++static const struct inode_operations shmem_inode_operations = {
++      .truncate       = shmem_truncate,
++      .setattr        = shmem_notify_change,
++      .truncate_range = shmem_truncate_range,
++#ifdef CONFIG_TMPFS_POSIX_ACL
++      .setxattr       = generic_setxattr,
++      .getxattr       = generic_getxattr,
++      .listxattr      = generic_listxattr,
++      .removexattr    = generic_removexattr,
++      .permission     = shmem_permission,
++#endif
++
++};
++
++static const struct inode_operations shmem_dir_inode_operations = {
++#ifdef CONFIG_TMPFS
++      .create         = shmem_create,
++      .lookup         = simple_lookup,
++      .link           = shmem_link,
++      .unlink         = shmem_unlink,
++      .symlink        = shmem_symlink,
++      .mkdir          = shmem_mkdir,
++      .rmdir          = shmem_rmdir,
++      .mknod          = shmem_mknod,
++      .rename         = shmem_rename,
++#endif
++#ifdef CONFIG_TMPFS_POSIX_ACL
++      .setattr        = shmem_notify_change,
++      .setxattr       = generic_setxattr,
++      .getxattr       = generic_getxattr,
++      .listxattr      = generic_listxattr,
++      .removexattr    = generic_removexattr,
++      .permission     = shmem_permission,
++#endif
++};
++
++static const struct inode_operations shmem_special_inode_operations = {
++#ifdef CONFIG_TMPFS_POSIX_ACL
++      .setattr        = shmem_notify_change,
++      .setxattr       = generic_setxattr,
++      .getxattr       = generic_getxattr,
++      .listxattr      = generic_listxattr,
++      .removexattr    = generic_removexattr,
++      .permission     = shmem_permission,
++#endif
++};
++
++static const struct super_operations shmem_ops = {
++      .alloc_inode    = shmem_alloc_inode,
++      .destroy_inode  = shmem_destroy_inode,
++#ifdef CONFIG_TMPFS
++      .statfs         = shmem_statfs,
++      .remount_fs     = shmem_remount_fs,
++#endif
++      .delete_inode   = shmem_delete_inode,
++      .drop_inode     = generic_delete_inode,
++      .put_super      = shmem_put_super,
++};
++
++static struct vm_operations_struct shmem_vm_ops = {
++      .nopage         = shmem_nopage,
++      .populate       = shmem_populate,
++#ifdef CONFIG_NUMA
++      .set_policy     = shmem_set_policy,
++      .get_policy     = shmem_get_policy,
++#endif
++};
++
++
++static int shmem_get_sb(struct file_system_type *fs_type,
++      int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 +{
-+      struct seq_file *seq = file->private_data;
-+      put_net(seq->private);
-+      return single_release(inode, file);
- }
- static const struct file_operations fib_triestat_fops = {
-@@ -2205,7 +2226,7 @@
-       .open   = fib_triestat_seq_open,
-       .read   = seq_read,
-       .llseek = seq_lseek,
--      .release = single_release,
-+      .release = fib_triestat_seq_release,
- };
- static struct node *fib_trie_get_idx(struct fib_trie_iter *iter,
-@@ -2214,13 +2235,13 @@
-       loff_t idx = 0;
-       struct node *n;
--      for (n = fib_trie_get_first(iter, trie_local);
-+      for (n = fib_trie_get_first(iter, iter->trie_local);
-            n; ++idx, n = fib_trie_get_next(iter)) {
-               if (pos == idx)
-                       return n;
-       }
--      for (n = fib_trie_get_first(iter, trie_main);
-+      for (n = fib_trie_get_first(iter, iter->trie_main);
-            n; ++idx, n = fib_trie_get_next(iter)) {
-               if (pos == idx)
-                       return n;
-@@ -2230,10 +2251,23 @@
- static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
- {
-+      struct fib_trie_iter *iter = seq->private;
-+      struct fib_table *tb;
++      return get_sb_nodev(fs_type, flags, data, shmem_fill_super, mnt);
++}
++
++static struct file_system_type tmpfs_fs_type = {
++      .owner          = THIS_MODULE,
++      .name           = "tmpfs",
++      .get_sb         = shmem_get_sb,
++      .kill_sb        = kill_litter_super,
++};
++static struct vfsmount *shm_mnt;
++
++static int __init init_tmpfs(void)
++{
++      int error;
++
++      error = init_inodecache();
++      if (error)
++              goto out3;
 +
-+      if (!iter->trie_local) {
-+              tb = fib_get_table(iter->net, RT_TABLE_LOCAL);
-+              if (tb)
-+                      iter->trie_local = (struct trie *) tb->tb_data;
++      error = register_filesystem(&tmpfs_fs_type);
++      if (error) {
++              printk(KERN_ERR "Could not register tmpfs\n");
++              goto out2;
 +      }
-+      if (!iter->trie_main) {
-+              tb = fib_get_table(iter->net, RT_TABLE_MAIN);
-+              if (tb)
-+                      iter->trie_main = (struct trie *) tb->tb_data;
++
++      shm_mnt = vfs_kern_mount(&tmpfs_fs_type, MS_NOUSER,
++                              tmpfs_fs_type.name, NULL);
++      if (IS_ERR(shm_mnt)) {
++              error = PTR_ERR(shm_mnt);
++              printk(KERN_ERR "Could not kern_mount tmpfs\n");
++              goto out1;
 +      }
-       rcu_read_lock();
-       if (*pos == 0)
-               return SEQ_START_TOKEN;
--      return fib_trie_get_idx(seq->private, *pos - 1);
-+      return fib_trie_get_idx(iter, *pos - 1);
- }
- static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-@@ -2251,8 +2285,8 @@
-               return v;
-       /* continue scan in next trie */
--      if (iter->trie == trie_local)
--              return fib_trie_get_first(iter, trie_main);
-+      if (iter->trie == iter->trie_local)
-+              return fib_trie_get_first(iter, iter->trie_main);
-       return NULL;
- }
-@@ -2318,7 +2352,7 @@
-               return 0;
-       if (!NODE_PARENT(n)) {
--              if (iter->trie == trie_local)
-+              if (iter->trie == iter->trie_local)
-                       seq_puts(seq, "<local>:\n");
-               else
-                       seq_puts(seq, "<main>:\n");
-@@ -2384,6 +2418,7 @@
-       seq          = file->private_data;
-       seq->private = s;
-       memset(s, 0, sizeof(*s));
-+      s->net = get_net(PROC_NET(inode));
- out:
-       return rc;
- out_kfree:
-@@ -2391,12 +2426,20 @@
-       goto out;
- }
-+static int fib_trie_seq_release(struct inode *inode, struct file *file)
++      return 0;
++
++out1:
++      unregister_filesystem(&tmpfs_fs_type);
++out2:
++      destroy_inodecache();
++out3:
++      shm_mnt = ERR_PTR(error);
++      return error;
++}
++module_init(init_tmpfs)
++
++/*
++ * shmem_file_setup - get an unlinked file living in tmpfs
++ *
++ * @name: name for dentry (to be seen in /proc/<pid>/maps
++ * @size: size to be set for the file
++ *
++ */
++struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
 +{
-+      struct seq_file *seq = file->private_data;
-+      struct fib_trie_iter *iter = seq->private;
-+      put_net(iter->net);
-+      return seq_release_private(inode, file);
++      int error;
++      struct file *file;
++      struct inode *inode;
++      struct dentry *dentry, *root;
++      struct qstr this;
++
++      if (IS_ERR(shm_mnt))
++              return (void *)shm_mnt;
++
++      if (size < 0 || size > SHMEM_MAX_BYTES)
++              return ERR_PTR(-EINVAL);
++
++      if (shmem_acct_size(flags, size))
++              return ERR_PTR(-ENOMEM);
++
++      error = -ENOMEM;
++      this.name = name;
++      this.len = strlen(name);
++      this.hash = 0; /* will go */
++      root = shm_mnt->mnt_root;
++      dentry = d_alloc(root, &this);
++      if (!dentry)
++              goto put_memory;
++
++      error = -ENFILE;
++      file = get_empty_filp();
++      if (!file)
++              goto put_dentry;
++
++      error = -ENOSPC;
++      inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
++      if (!inode)
++              goto close_file;
++
++      SHMEM_I(inode)->flags = flags & VM_ACCOUNT;
++      d_instantiate(dentry, inode);
++      inode->i_size = size;
++      inode->i_nlink = 0;     /* It is unlinked */
++      file->f_path.mnt = mntget(shm_mnt);
++      file->f_path.dentry = dentry;
++      file->f_mapping = inode->i_mapping;
++      file->f_op = &shmem_file_operations;
++      file->f_mode = FMODE_WRITE | FMODE_READ;
++      return file;
++
++close_file:
++      put_filp(file);
++put_dentry:
++      dput(dentry);
++put_memory:
++      shmem_unacct_size(flags, size);
++      return ERR_PTR(error);
 +}
 +
- static const struct file_operations fib_trie_fops = {
-       .owner  = THIS_MODULE,
-       .open   = fib_trie_seq_open,
-       .read   = seq_read,
-       .llseek = seq_lseek,
--      .release = seq_release_private,
-+      .release = fib_trie_seq_release,
- };
- static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
-@@ -2434,7 +2477,7 @@
-               return 0;
-       }
--      if (iter->trie == trie_local)
-+      if (iter->trie == iter->trie_local)
-               return 0;
-       if (IS_TNODE(l))
-               return 0;
-@@ -2505,6 +2548,7 @@
-       seq          = file->private_data;
-       seq->private = s;
-       memset(s, 0, sizeof(*s));
-+      s->net = get_net(PROC_NET(inode));
- out:
-       return rc;
- out_kfree:
-@@ -2517,35 +2561,37 @@
-       .open   = fib_route_seq_open,
-       .read   = seq_read,
-       .llseek = seq_lseek,
--      .release = seq_release_private,
-+      .release = fib_trie_seq_release,
- };
--int __init fib_proc_init(void)
-+int fib_proc_init(struct net *net)
- {
--      if (!proc_net_fops_create("fib_trie", S_IRUGO, &fib_trie_fops))
-+      net->trie_last_dflt = -1;
++/*
++ * shmem_zero_setup - setup a shared anonymous mapping
++ *
++ * @vma: the vma to be mmapped is prepared by do_mmap_pgoff
++ */
++int shmem_zero_setup(struct vm_area_struct *vma)
++{
++      struct file *file;
++      loff_t size = vma->vm_end - vma->vm_start;
 +
-+      if (!proc_net_fops_create(net, "fib_trie", S_IRUGO, &fib_trie_fops))
-               goto out1;
--      if (!proc_net_fops_create("fib_triestat", S_IRUGO, &fib_triestat_fops))
-+      if (!proc_net_fops_create(net, "fib_triestat", S_IRUGO, &fib_triestat_fops))
-               goto out2;
++      file = shmem_file_setup("dev/zero", size, vma->vm_flags);
++      if (IS_ERR(file))
++              return PTR_ERR(file);
++
++      if (vma->vm_file)
++              fput(vma->vm_file);
++      vma->vm_file = file;
++      vma->vm_ops = &shmem_vm_ops;
++      return 0;
++}
+diff -Nurb linux-2.6.22-590/mm/slab.c linux-2.6.22-570/mm/slab.c
+--- linux-2.6.22-590/mm/slab.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/slab.c 2008-01-23 19:16:05.000000000 -0500
+@@ -1639,8 +1639,6 @@
+ #endif
  
--      if (!proc_net_fops_create("route", S_IRUGO, &fib_route_fops))
-+      if (!proc_net_fops_create(net, "route", S_IRUGO, &fib_route_fops))
-               goto out3;
+       flags |= cachep->gfpflags;
+-      if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
+-              flags |= __GFP_RECLAIMABLE;
  
-       return 0;
+       page = alloc_pages_node(nodeid, flags, cachep->gfporder);
+       if (!page)
+diff -Nurb linux-2.6.22-590/mm/slub.c linux-2.6.22-570/mm/slub.c
+--- linux-2.6.22-590/mm/slub.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/slub.c 2008-01-23 19:15:56.000000000 -0500
+@@ -985,9 +985,6 @@
+       if (s->flags & SLAB_CACHE_DMA)
+               flags |= SLUB_DMA;
  
- out3:
--      proc_net_remove("fib_triestat");
-+      proc_net_remove(net, "fib_triestat");
- out2:
--      proc_net_remove("fib_trie");
-+      proc_net_remove(net, "fib_trie");
- out1:
-       return -ENOMEM;
- }
+-      if (s->flags & SLAB_RECLAIM_ACCOUNT)
+-              flags |= __GFP_RECLAIMABLE;
+-
+       if (node == -1)
+               page = alloc_pages(flags, s->order);
+       else
+@@ -1992,7 +1989,6 @@
+ #ifdef CONFIG_NUMA
+       s->defrag_ratio = 100;
+ #endif
+-      raise_kswapd_order(s->order);
  
--void __init fib_proc_exit(void)
-+void fib_proc_exit(struct net *net)
- {
--      proc_net_remove("fib_trie");
--      proc_net_remove("fib_triestat");
--      proc_net_remove("route");
-+      proc_net_remove(net, "fib_trie");
-+      proc_net_remove(net, "fib_triestat");
-+      proc_net_remove(net, "route");
+       if (init_kmem_cache_nodes(s, gfpflags & ~SLUB_DMA))
+               return 1;
+diff -Nurb linux-2.6.22-590/mm/swap_state.c linux-2.6.22-570/mm/swap_state.c
+--- linux-2.6.22-590/mm/swap_state.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/swap_state.c   2007-07-08 19:32:17.000000000 -0400
+@@ -334,8 +334,7 @@
+                * Get a new page to read into from swap.
+                */
+               if (!new_page) {
+-                      new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE,
+-                                                              vma, addr);
++                      new_page = alloc_page_vma(GFP_HIGHUSER, vma, addr);
+                       if (!new_page)
+                               break;          /* Out of memory */
+               }
+diff -Nurb linux-2.6.22-590/mm/truncate.c linux-2.6.22-570/mm/truncate.c
+--- linux-2.6.22-590/mm/truncate.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/truncate.c     2007-07-08 19:32:17.000000000 -0400
+@@ -82,7 +82,7 @@
+ /*
+  * If truncate cannot remove the fs-private metadata from the page, the page
+  * becomes anonymous.  It will be left on the LRU and may even be mapped into
+- * user pagetables if we're racing with filemap_fault().
++ * user pagetables if we're racing with filemap_nopage().
+  *
+  * We need to bale out if page->mapping is no longer equal to the original
+  * mapping.  This happens a) when the VM reclaimed the page while we waited on
+@@ -192,11 +192,6 @@
+                               unlock_page(page);
+                               continue;
+                       }
+-                      if (page_mapped(page)) {
+-                              unmap_mapping_range(mapping,
+-                                (loff_t)page_index<<PAGE_CACHE_SHIFT,
+-                                PAGE_CACHE_SIZE, 0);
+-                      }
+                       truncate_complete_page(mapping, page);
+                       unlock_page(page);
+               }
+@@ -234,11 +229,6 @@
+                               break;
+                       lock_page(page);
+                       wait_on_page_writeback(page);
+-                      if (page_mapped(page)) {
+-                              unmap_mapping_range(mapping,
+-                                (loff_t)page->index<<PAGE_CACHE_SHIFT,
+-                                PAGE_CACHE_SIZE, 0);
+-                      }
+                       if (page->index > next)
+                               next = page->index;
+                       next++;
+@@ -407,7 +397,7 @@
+                               break;
+                       }
+                       wait_on_page_writeback(page);
+-                      if (page_mapped(page)) {
++                      while (page_mapped(page)) {
+                               if (!did_range_unmap) {
+                                       /*
+                                        * Zap the rest of the file in one hit.
+@@ -427,7 +417,6 @@
+                                         PAGE_CACHE_SIZE, 0);
+                               }
+                       }
+-                      BUG_ON(page_mapped(page));
+                       ret = do_launder_page(mapping, page);
+                       if (ret == 0 && !invalidate_complete_page2(mapping, page))
+                               ret = -EIO;
+diff -Nurb linux-2.6.22-590/mm/util.c linux-2.6.22-570/mm/util.c
+--- linux-2.6.22-590/mm/util.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/util.c 2007-07-08 19:32:17.000000000 -0400
+@@ -18,8 +18,9 @@
  }
+ EXPORT_SYMBOL(__kzalloc);
  
- #endif /* CONFIG_PROC_FS */
-diff -Nurb linux-2.6.22-570/net/ipv4/icmp.c linux-2.6.22-590/net/ipv4/icmp.c
---- linux-2.6.22-570/net/ipv4/icmp.c   2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/icmp.c   2008-01-02 13:56:38.000000000 -0500
-@@ -229,14 +229,13 @@
-  *
-  *    On SMP we have one ICMP socket per-cpu.
+-/**
++/*
+  * kstrdup - allocate space for and copy an existing string
++ *
+  * @s: the string to duplicate
+  * @gfp: the GFP mask used in the kmalloc() call when allocating memory
   */
--static DEFINE_PER_CPU(struct socket *, __icmp_socket) = NULL;
--#define icmp_socket   __get_cpu_var(__icmp_socket)
-+#define icmp_socket(NET) (*per_cpu_ptr((NET)->__icmp_socket, smp_processor_id()))
--static __inline__ int icmp_xmit_lock(void)
-+static __inline__ int icmp_xmit_lock(struct net *net)
- {
-       local_bh_disable();
--      if (unlikely(!spin_trylock(&icmp_socket->sk->sk_lock.slock))) {
-+      if (unlikely(!spin_trylock(&icmp_socket(net)->sk->sk_lock.slock))) {
-               /* This can happen if the output path signals a
-                * dst_link_failure() for an outgoing ICMP packet.
-                */
-@@ -246,9 +245,9 @@
-       return 0;
- }
+@@ -40,32 +41,6 @@
+ EXPORT_SYMBOL(kstrdup);
  
--static void icmp_xmit_unlock(void)
-+static void icmp_xmit_unlock(struct net *net)
- {
--      spin_unlock_bh(&icmp_socket->sk->sk_lock.slock);
-+      spin_unlock_bh(&icmp_socket(net)->sk->sk_lock.slock);
- }
+ /**
+- * kstrndup - allocate space for and copy an existing string
+- * @s: the string to duplicate
+- * @max: read at most @max chars from @s
+- * @gfp: the GFP mask used in the kmalloc() call when allocating memory
+- */
+-char *kstrndup(const char *s, size_t max, gfp_t gfp)
+-{
+-      size_t len;
+-      char *buf;
+-
+-      if (!s)
+-              return NULL;
+-
+-      len = strlen(s);
+-      if (len > max)
+-              len = max;
+-      buf = kmalloc_track_caller(len+1, gfp);
+-      if (buf) {
+-              memcpy(buf, s, len);
+-              buf[len] = '\0';
+-      }
+-      return buf;
+-}
+-EXPORT_SYMBOL(kstrndup);
+-
+-/**
+  * kmemdup - duplicate region of memory
+  *
+  * @src: memory region to duplicate
+@@ -85,6 +60,7 @@
  
  /*
-@@ -347,19 +346,20 @@
- static void icmp_push_reply(struct icmp_bxm *icmp_param,
-                           struct ipcm_cookie *ipc, struct rtable *rt)
- {
-+      struct net *net = icmp_param->skb->dev->nd_net;
-       struct sk_buff *skb;
--      if (ip_append_data(icmp_socket->sk, icmp_glue_bits, icmp_param,
-+      if (ip_append_data(icmp_socket(net)->sk, icmp_glue_bits, icmp_param,
-                          icmp_param->data_len+icmp_param->head_len,
-                          icmp_param->head_len,
-                          ipc, rt, MSG_DONTWAIT) < 0)
--              ip_flush_pending_frames(icmp_socket->sk);
--      else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) {
-+              ip_flush_pending_frames(icmp_socket(net)->sk);
-+      else if ((skb = skb_peek(&icmp_socket(net)->sk->sk_write_queue)) != NULL) {
-               struct icmphdr *icmph = icmp_hdr(skb);
-               __wsum csum = 0;
-               struct sk_buff *skb1;
--              skb_queue_walk(&icmp_socket->sk->sk_write_queue, skb1) {
-+              skb_queue_walk(&icmp_socket(net)->sk->sk_write_queue, skb1) {
-                       csum = csum_add(csum, skb1->csum);
-               }
-               csum = csum_partial_copy_nocheck((void *)&icmp_param->data,
-@@ -367,7 +367,7 @@
-                                                icmp_param->head_len, csum);
-               icmph->checksum = csum_fold(csum);
-               skb->ip_summed = CHECKSUM_NONE;
--              ip_push_pending_frames(icmp_socket->sk);
-+              ip_push_pending_frames(icmp_socket(net)->sk);
-       }
+  * strndup_user - duplicate an existing string from user space
++ *
+  * @s: The string to duplicate
+  * @n: Maximum number of bytes to copy, including the trailing NUL.
+  */
+diff -Nurb linux-2.6.22-590/mm/vmalloc.c linux-2.6.22-570/mm/vmalloc.c
+--- linux-2.6.22-590/mm/vmalloc.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/vmalloc.c      2007-07-08 19:32:17.000000000 -0400
+@@ -68,12 +68,12 @@
+       } while (pud++, addr = next, addr != end);
  }
  
-@@ -377,7 +377,8 @@
- static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
+-void unmap_kernel_range(unsigned long addr, unsigned long size)
++void unmap_vm_area(struct vm_struct *area)
  {
--      struct sock *sk = icmp_socket->sk;
-+      struct net *net = icmp_param->skb->dev->nd_net;
-+      struct sock *sk = icmp_socket(net)->sk;
-       struct inet_sock *inet = inet_sk(sk);
-       struct ipcm_cookie ipc;
-       struct rtable *rt = (struct rtable *)skb->dst;
-@@ -386,7 +387,7 @@
-       if (ip_options_echo(&icmp_param->replyopts, skb))
-               return;
--      if (icmp_xmit_lock())
-+      if (icmp_xmit_lock(net))
-               return;
+       pgd_t *pgd;
+       unsigned long next;
+-      unsigned long start = addr;
+-      unsigned long end = addr + size;
++      unsigned long addr = (unsigned long) area->addr;
++      unsigned long end = addr + area->size;
  
-       icmp_param->data.icmph.checksum = 0;
-@@ -401,7 +402,8 @@
-                       daddr = icmp_param->replyopts.faddr;
-       }
-       {
--              struct flowi fl = { .nl_u = { .ip4_u =
-+              struct flowi fl = { .fl_net = net,
-+                                  .nl_u = { .ip4_u =
-                                             { .daddr = daddr,
-                                               .saddr = rt->rt_spec_dst,
-                                               .tos = RT_TOS(ip_hdr(skb)->tos) } },
-@@ -415,7 +417,7 @@
-               icmp_push_reply(icmp_param, &ipc, rt);
-       ip_rt_put(rt);
- out_unlock:
--      icmp_xmit_unlock();
-+      icmp_xmit_unlock(net);
+       BUG_ON(addr >= end);
+       pgd = pgd_offset_k(addr);
+@@ -84,12 +84,7 @@
+                       continue;
+               vunmap_pud_range(pgd, addr, next);
+       } while (pgd++, addr = next, addr != end);
+-      flush_tlb_kernel_range(start, end);
+-}
+-
+-static void unmap_vm_area(struct vm_struct *area)
+-{
+-      unmap_kernel_range((unsigned long)area->addr, area->size);
++      flush_tlb_kernel_range((unsigned long) area->addr, end);
  }
  
-@@ -436,6 +438,7 @@
-       int room;
-       struct icmp_bxm icmp_param;
-       struct rtable *rt = (struct rtable *)skb_in->dst;
-+      struct net *net;
-       struct ipcm_cookie ipc;
-       __be32 saddr;
-       u8  tos;
-@@ -443,6 +446,7 @@
-       if (!rt)
-               goto out;
-+      net = rt->fl.fl_net;
-       /*
-        *      Find the original header. It is expected to be valid, of course.
-        *      Check this, icmp_send is called from the most obscure devices
-@@ -505,7 +509,7 @@
-               }
-       }
--      if (icmp_xmit_lock())
-+      if (icmp_xmit_lock(net))
-               return;
-       /*
-@@ -517,7 +521,7 @@
-               struct net_device *dev = NULL;
-               if (rt->fl.iif && sysctl_icmp_errors_use_inbound_ifaddr)
--                      dev = dev_get_by_index(rt->fl.iif);
-+                      dev = dev_get_by_index(&init_net, rt->fl.iif);
-               if (dev) {
-                       saddr = inet_select_addr(dev, 0, RT_SCOPE_LINK);
-@@ -545,12 +549,13 @@
-       icmp_param.skb    = skb_in;
-       icmp_param.offset = skb_network_offset(skb_in);
-       icmp_out_count(icmp_param.data.icmph.type);
--      inet_sk(icmp_socket->sk)->tos = tos;
-+      inet_sk(icmp_socket(net)->sk)->tos = tos;
-       ipc.addr = iph->saddr;
-       ipc.opt = &icmp_param.replyopts;
-       {
-               struct flowi fl = {
-+                      .fl_net = net,
-                       .nl_u = {
-                               .ip4_u = {
-                                       .daddr = icmp_param.replyopts.srr ?
-@@ -593,7 +598,7 @@
- ende:
-       ip_rt_put(rt);
- out_unlock:
--      icmp_xmit_unlock();
-+      icmp_xmit_unlock(net);
- out:;
+ static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
+diff -Nurb linux-2.6.22-590/mm/vmscan.c linux-2.6.22-570/mm/vmscan.c
+--- linux-2.6.22-590/mm/vmscan.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/mm/vmscan.c       2007-07-08 19:32:17.000000000 -0400
+@@ -1272,34 +1272,6 @@
+       return nr_reclaimed;
  }
  
-@@ -604,6 +609,7 @@
- static void icmp_unreach(struct sk_buff *skb)
- {
-+      struct net *net = skb->dev->nd_net;
-       struct iphdr *iph;
-       struct icmphdr *icmph;
-       int hash, protocol;
-@@ -634,7 +640,7 @@
-               case ICMP_PORT_UNREACH:
-                       break;
-               case ICMP_FRAG_NEEDED:
--                      if (ipv4_config.no_pmtu_disc) {
-+                      if (net->sysctl_ipv4_no_pmtu_disc) {
-                               LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: "
-                                                        "fragmentation needed "
-                                                        "and DF set.\n",
-@@ -678,7 +684,7 @@
+-static unsigned int kswapd_min_order __read_mostly;
+-
+-static inline int kswapd_order(unsigned int order)
+-{
+-      return max(kswapd_min_order, order);
+-}
+-
+-/**
+- * raise_kswapd_order - Raise the minimum order that kswapd reclaims
+- * @order: The minimum order kswapd should reclaim at
+- *
+- * kswapd normally reclaims at order 0 unless there is a higher-order
+- * allocation being serviced. This function is used to set the minimum
+- * order that kswapd reclaims at when it is known there will be regular
+- * high-order allocations at a given order.
+- */
+-void raise_kswapd_order(unsigned int order)
+-{
+-      if (order >= MAX_ORDER)
+-              return;
+-
+-      /* Update order if necessary and inform if changed */
+-      if (order > kswapd_min_order) {
+-              kswapd_min_order = order;
+-              printk(KERN_INFO "kswapd reclaim order set to %d\n", order);
+-      }
+-}
+-
+ /*
+  * The background pageout daemon, started as a kernel thread
+  * from the init process. 
+@@ -1342,14 +1314,13 @@
+        * trying to free the first piece of memory in the first place).
         */
+       tsk->flags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
+-      set_freezable();
  
-       if (!sysctl_icmp_ignore_bogus_error_responses &&
--          inet_addr_type(iph->daddr) == RTN_BROADCAST) {
-+          inet_addr_type(net, iph->daddr) == RTN_BROADCAST) {
-               if (net_ratelimit())
-                       printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP "
-                                           "type %u, code %u "
-@@ -707,7 +713,7 @@
-       hash = protocol & (MAX_INET_PROTOS - 1);
-       read_lock(&raw_v4_lock);
-       if ((raw_sk = sk_head(&raw_v4_htable[hash])) != NULL) {
--              while ((raw_sk = __raw_v4_lookup(raw_sk, protocol, iph->daddr,
-+              while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol, iph->daddr,
-                                                iph->saddr,
-                                                skb->dev->ifindex, skb->skb_tag)) != NULL) {
-                       raw_err(raw_sk, skb, info);
-@@ -1179,29 +1185,54 @@
-       },
- };
--void __init icmp_init(struct net_proto_family *ops)
-+static void icmp_net_exit(struct net *net)
- {
--      struct inet_sock *inet;
-+      struct socket **sock;
-       int i;
-       for_each_possible_cpu(i) {
-+              sock = percpu_ptr(net->__icmp_socket, i);
-+              if (!*sock)
-+                      continue;
-+              /* At the last minute lie and say this is a socket for
-+               * the initial network namespace.  So the socket will
-+               * be safe to free. 
-+               */
-+              (*sock)->sk->sk_net = get_net(&init_net);
-+              sock_release(*sock);
-+              *sock = NULL;
-+      }
-+      percpu_free(net->__icmp_socket);
-+}
-+
-+static int icmp_net_init(struct net *net)
-+{
-+      struct socket **sock;
-+      struct inet_sock *inet;
-               int err;
-+      int i;
-+
-+      net->__icmp_socket = alloc_percpu(struct socket *);
-+      if (!net->__icmp_socket)
-+              return -ENOMEM;
-+      
-+      for_each_possible_cpu(i) {
+-      order = kswapd_order(0);
++      order = 0;
+       for ( ; ; ) {
+               unsigned long new_order;
  
--              err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
--                                     &per_cpu(__icmp_socket, i));
-+              sock = percpu_ptr(net->__icmp_socket, i);
+               prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE);
+-              new_order = kswapd_order(pgdat->kswapd_max_order);
++              new_order = pgdat->kswapd_max_order;
+               pgdat->kswapd_max_order = 0;
+               if (order < new_order) {
+                       /*
+@@ -1361,7 +1332,7 @@
+                       if (!freezing(current))
+                               schedule();
  
-+              err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP, sock);
-               if (err < 0)
--                      panic("Failed to create the ICMP control socket.\n");
-+                      goto fail;
+-                      order = kswapd_order(pgdat->kswapd_max_order);
++                      order = pgdat->kswapd_max_order;
+               }
+               finish_wait(&pgdat->kswapd_wait, &wait);
  
--              per_cpu(__icmp_socket, i)->sk->sk_allocation = GFP_ATOMIC;
-+              (*sock)->sk->sk_allocation = GFP_ATOMIC;
+diff -Nurb linux-2.6.22-590/net/802/tr.c linux-2.6.22-570/net/802/tr.c
+--- linux-2.6.22-590/net/802/tr.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/802/tr.c      2007-07-08 19:32:17.000000000 -0400
+@@ -36,7 +36,6 @@
+ #include <linux/seq_file.h>
+ #include <linux/init.h>
+ #include <net/arp.h>
+-#include <net/net_namespace.h>
  
-               /* Enough space for 2 64K ICMP packets, including
-                * sk_buff struct overhead.
-                */
--              per_cpu(__icmp_socket, i)->sk->sk_sndbuf =
-+              (*sock)->sk->sk_sndbuf =
-                       (2 * ((64 * 1024) + sizeof(struct sk_buff)));
+ static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev);
+ static void rif_check_expire(unsigned long dummy);
+@@ -533,7 +532,7 @@
+               seq_puts(seq,
+                    "if     TR address       TTL   rcf   routing segments\n");
+       else {
+-              struct net_device *dev = dev_get_by_index(&init_net, entry->iface);
++              struct net_device *dev = dev_get_by_index(entry->iface);
+               long ttl = (long) (entry->last_used + sysctl_tr_rif_timeout)
+                               - (long) jiffies;
  
--              inet = inet_sk(per_cpu(__icmp_socket, i)->sk);
-+              inet = inet_sk((*sock)->sk);
-               inet->uc_ttl = -1;
-               inet->pmtudisc = IP_PMTUDISC_DONT;
+@@ -640,7 +639,7 @@
+       rif_timer.function = rif_check_expire;
+       add_timer(&rif_timer);
  
-@@ -1209,8 +1240,27 @@
-                * see it, we do not wish this socket to see incoming
-                * packets.
-                */
--              per_cpu(__icmp_socket, i)->sk->sk_prot->unhash(per_cpu(__icmp_socket, i)->sk);
-+              (*sock)->sk->sk_prot->unhash((*sock)->sk);
-+
-+              /* Don't hold an extra reference on the namespace */
-+              put_net((*sock)->sk->sk_net);
-       }
-+      return 0;
-+fail:
-+      icmp_net_exit(net);
-+      return err;
-+
-+}
-+
-+static struct pernet_operations icmp_net_ops = {
-+      .init = icmp_net_init,
-+      .exit = icmp_net_exit,
-+};
-+
-+void __init icmp_init(struct net_proto_family *ops)
-+{
-+      if (register_pernet_subsys(&icmp_net_ops))
-+              panic("Failed to create the ICMP control socket.\n");
+-      proc_net_fops_create(&init_net, "tr_rif", S_IRUGO, &rif_seq_fops);
++      proc_net_fops_create("tr_rif", S_IRUGO, &rif_seq_fops);
+       return 0;
  }
  
- EXPORT_SYMBOL(icmp_err_convert);
-diff -Nurb linux-2.6.22-570/net/ipv4/igmp.c linux-2.6.22-590/net/ipv4/igmp.c
---- linux-2.6.22-570/net/ipv4/igmp.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/igmp.c   2008-01-02 13:56:38.000000000 -0500
-@@ -97,6 +97,7 @@
- #include <net/route.h>
- #include <net/sock.h>
- #include <net/checksum.h>
-+#include <net/net_namespace.h>
- #include <linux/netfilter_ipv4.h>
- #ifdef CONFIG_IP_MROUTE
- #include <linux/mroute.h>
-@@ -129,12 +130,12 @@
-  */
- #define IGMP_V1_SEEN(in_dev) \
--      (IPV4_DEVCONF_ALL(FORCE_IGMP_VERSION) == 1 || \
-+      (IPV4_DEVCONF_ALL((in_dev)->dev->nd_net, FORCE_IGMP_VERSION) == 1 || \
-        IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \
-        ((in_dev)->mr_v1_seen && \
-         time_before(jiffies, (in_dev)->mr_v1_seen)))
- #define IGMP_V2_SEEN(in_dev) \
--      (IPV4_DEVCONF_ALL(FORCE_IGMP_VERSION) == 2 || \
-+      (IPV4_DEVCONF_ALL((in_dev)->dev->nd_net, FORCE_IGMP_VERSION) == 2 || \
-        IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2 || \
-        ((in_dev)->mr_v2_seen && \
-         time_before(jiffies, (in_dev)->mr_v2_seen)))
-@@ -296,7 +297,8 @@
-               return NULL;
+diff -Nurb linux-2.6.22-590/net/8021q/Makefile linux-2.6.22-570/net/8021q/Makefile
+--- linux-2.6.22-590/net/8021q/Makefile        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/8021q/Makefile        2007-07-08 19:32:17.000000000 -0400
+@@ -4,7 +4,7 @@
  
-       {
--              struct flowi fl = { .oif = dev->ifindex,
-+              struct flowi fl = { .fl_net = &init_net,
-+                                  .oif = dev->ifindex,
-                                   .nl_u = { .ip4_u = {
-                                   .daddr = IGMPV3_ALL_MCR } },
-                                   .proto = IPPROTO_IGMP };
-@@ -646,7 +648,8 @@
-               dst = group;
+ obj-$(CONFIG_VLAN_8021Q) += 8021q.o
  
-       {
--              struct flowi fl = { .oif = dev->ifindex,
-+              struct flowi fl = { .fl_net = &init_net,
-+                                  .oif = dev->ifindex,
-                                   .nl_u = { .ip4_u = { .daddr = dst } },
-                                   .proto = IPPROTO_IGMP };
-               if (ip_route_output_key(&rt, &fl))
-@@ -929,6 +932,11 @@
-       struct in_device *in_dev = in_dev_get(skb->dev);
-       int len = skb->len;
+-8021q-objs := vlan.o vlan_dev.o vlan_netlink.o
++8021q-objs := vlan.o vlan_dev.o
  
-+      if (skb->dev->nd_net != &init_net) {
-+              kfree_skb(skb);
-+              return 0;
-+      }
-+
-       if (in_dev==NULL) {
-               kfree_skb(skb);
-               return 0;
-@@ -1393,20 +1401,22 @@
+ ifeq ($(CONFIG_PROC_FS),y)
+ 8021q-objs += vlanproc.o
+diff -Nurb linux-2.6.22-590/net/8021q/vlan.c linux-2.6.22-570/net/8021q/vlan.c
+--- linux-2.6.22-590/net/8021q/vlan.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/8021q/vlan.c  2007-07-08 19:32:17.000000000 -0400
+@@ -31,7 +31,6 @@
+ #include <net/arp.h>
+ #include <linux/rtnetlink.h>
+ #include <linux/notifier.h>
+-#include <net/net_namespace.h>
  
- static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
- {
--      struct flowi fl = { .nl_u = { .ip4_u =
--                                    { .daddr = imr->imr_multiaddr.s_addr } } };
-+      struct flowi fl = { 
-+              .fl_net = &init_net,
-+              .nl_u = { .ip4_u = { .daddr = imr->imr_multiaddr.s_addr } }
-+      };
-       struct rtable *rt;
-       struct net_device *dev = NULL;
-       struct in_device *idev = NULL;
+ #include <linux/if_vlan.h>
+ #include "vlan.h"
+@@ -51,7 +50,7 @@
+ static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
  
-       if (imr->imr_ifindex) {
--              idev = inetdev_by_index(imr->imr_ifindex);
-+              idev = inetdev_by_index(&init_net, imr->imr_ifindex);
-               if (idev)
-                       __in_dev_put(idev);
-               return idev;
-       }
-       if (imr->imr_address.s_addr) {
--              dev = ip_dev_find(imr->imr_address.s_addr);
-+              dev = ip_dev_find(&init_net, imr->imr_address.s_addr);
-               if (!dev)
-                       return NULL;
-               dev_put(dev);
-@@ -2234,7 +2244,7 @@
-               struct in_device *in_dev;
-               inet->mc_list = iml->next;
+ static int vlan_device_event(struct notifier_block *, unsigned long, void *);
+-static int vlan_ioctl_handler(struct net *net, void __user *);
++static int vlan_ioctl_handler(void __user *);
+ static int unregister_vlan_dev(struct net_device *, unsigned short );
  
--              in_dev = inetdev_by_index(iml->multi.imr_ifindex);
-+              in_dev = inetdev_by_index(&init_net, iml->multi.imr_ifindex);
-               (void) ip_mc_leave_src(sk, iml, in_dev);
-               if (in_dev != NULL) {
-                       ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
-@@ -2291,7 +2301,7 @@
-       struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
+ static struct notifier_block vlan_notifier_block = {
+@@ -98,22 +97,15 @@
  
-       state->in_dev = NULL;
--      for_each_netdev(state->dev) {
-+      for_each_netdev(&init_net, state->dev) {
-               struct in_device *in_dev;
-               in_dev = in_dev_get(state->dev);
-               if (!in_dev)
-@@ -2453,7 +2463,7 @@
+       /* Register us to receive netdevice events */
+       err = register_netdevice_notifier(&vlan_notifier_block);
+-      if (err < 0)
+-              goto err1;
+-
+-      err = vlan_netlink_init();
+-      if (err < 0)
+-              goto err2;
++      if (err < 0) {
++              dev_remove_pack(&vlan_packet_type);
++              vlan_proc_cleanup();
++              return err;
++      }
  
-       state->idev = NULL;
-       state->im = NULL;
--      for_each_netdev(state->dev) {
-+      for_each_netdev(&init_net, state->dev) {
-               struct in_device *idev;
-               idev = in_dev_get(state->dev);
-               if (unlikely(idev == NULL))
-@@ -2613,8 +2623,8 @@
+       vlan_ioctl_set(vlan_ioctl_handler);
+-      return 0;
  
- int __init igmp_mc_proc_init(void)
- {
--      proc_net_fops_create("igmp", S_IRUGO, &igmp_mc_seq_fops);
--      proc_net_fops_create("mcfilter", S_IRUGO, &igmp_mcf_seq_fops);
-+      proc_net_fops_create(&init_net, "igmp", S_IRUGO, &igmp_mc_seq_fops);
-+      proc_net_fops_create(&init_net, "mcfilter", S_IRUGO, &igmp_mcf_seq_fops);
-       return 0;
+-err2:
+-      unregister_netdevice_notifier(&vlan_notifier_block);
+-err1:
+-      vlan_proc_cleanup();
+-      dev_remove_pack(&vlan_packet_type);
+-      return err;
++      return 0;
  }
- #endif
-diff -Nurb linux-2.6.22-570/net/ipv4/inet_connection_sock.c linux-2.6.22-590/net/ipv4/inet_connection_sock.c
---- linux-2.6.22-570/net/ipv4/inet_connection_sock.c   2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/inet_connection_sock.c   2008-01-02 13:56:38.000000000 -0500
-@@ -32,7 +32,7 @@
- /*
-  * This array holds the first and last local port number.
-  */
--int sysctl_local_port_range[2] = { 32768, 61000 };
-+//int sysctl_local_port_range[2] = { 32768, 61000 };
  
- int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
- {
-@@ -74,6 +74,7 @@
+ /* Cleanup all vlan devices
+@@ -125,7 +117,7 @@
+       struct net_device *dev, *nxt;
  
-       sk_for_each_bound(sk2, node, &tb->owners) {
-               if (sk != sk2 &&
-+                  (sk->sk_net == sk2->sk_net) &&
-                   !inet_v6_ipv6only(sk2) &&
-                   (!sk->sk_bound_dev_if ||
-                    !sk2->sk_bound_dev_if ||
-@@ -98,6 +99,7 @@
-                     int (*bind_conflict)(const struct sock *sk,
-                                          const struct inet_bind_bucket *tb))
+       rtnl_lock();
+-      for_each_netdev_safe(&init_net, dev, nxt) {
++      for_each_netdev_safe(dev, nxt) {
+               if (dev->priv_flags & IFF_802_1Q_VLAN) {
+                       unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
+                                           VLAN_DEV_INFO(dev)->vlan_id);
+@@ -144,7 +136,6 @@
  {
-+      struct net *net = sk->sk_net;
-       struct inet_bind_hashbucket *head;
-       struct hlist_node *node;
-       struct inet_bind_bucket *tb;
-@@ -105,16 +107,16 @@
-       local_bh_disable();
-       if (!snum) {
--              int low = sysctl_local_port_range[0];
--              int high = sysctl_local_port_range[1];
-+              int low = sk->sk_net->sysctl_local_port_range[0];
-+              int high = sk->sk_net->sysctl_local_port_range[1];
-               int remaining = (high - low) + 1;
-               int rover = net_random() % (high - low) + low;
+       int i;
  
-               do {
--                      head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)];
-+                      head = &hashinfo->bhash[inet_bhashfn(net, rover, hashinfo->bhash_size)];
-                       spin_lock(&head->lock);
-                       inet_bind_bucket_for_each(tb, node, &head->chain)
--                              if (tb->port == rover)
-+                              if ((tb->port == rover) && (tb->net == net))
-                                       goto next;
-                       break;
-               next:
-@@ -138,10 +140,10 @@
-                */
-               snum = rover;
-       } else {
--              head = &hashinfo->bhash[inet_bhashfn(snum, hashinfo->bhash_size)];
-+              head = &hashinfo->bhash[inet_bhashfn(net, snum, hashinfo->bhash_size)];
-               spin_lock(&head->lock);
-               inet_bind_bucket_for_each(tb, node, &head->chain)
--                      if (tb->port == snum)
-+                      if ((tb->port == snum) && (tb->net==net))
-                               goto tb_found;
-       }
-       tb = NULL;
-@@ -161,7 +163,7 @@
-       }
- tb_not_found:
-       ret = 1;
--      if (!tb && (tb = inet_bind_bucket_create(hashinfo->bind_bucket_cachep, head, snum)) == NULL)
-+      if (!tb && (tb = inet_bind_bucket_create(hashinfo->bind_bucket_cachep, head, net, snum)) == NULL)
-               goto fail_unlock;
-       if (hlist_empty(&tb->owners)) {
-               if (sk->sk_reuse && sk->sk_state != TCP_LISTEN)
-@@ -341,7 +343,8 @@
-       struct rtable *rt;
-       const struct inet_request_sock *ireq = inet_rsk(req);
-       struct ip_options *opt = inet_rsk(req)->opt;
--      struct flowi fl = { .oif = sk->sk_bound_dev_if,
-+      struct flowi fl = { .fl_net = sk->sk_net,
-+                      .oif = sk->sk_bound_dev_if,
-                           .nl_u = { .ip4_u =
-                                     { .daddr = ((opt && opt->srr) ?
-                                                 opt->faddr :
-diff -Nurb linux-2.6.22-570/net/ipv4/inet_diag.c linux-2.6.22-590/net/ipv4/inet_diag.c
---- linux-2.6.22-570/net/ipv4/inet_diag.c      2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/inet_diag.c      2008-01-02 13:56:38.000000000 -0500
-@@ -227,6 +227,7 @@
- static int inet_diag_get_exact(struct sk_buff *in_skb,
-                              const struct nlmsghdr *nlh)
- {
-+      struct net *net = in_skb->sk->sk_net;
-       int err;
-       struct sock *sk;
-       struct inet_diag_req *req = NLMSG_DATA(nlh);
-@@ -242,7 +243,7 @@
-               /* TODO: lback */
-               sk = inet_lookup(hashinfo, req->id.idiag_dst[0],
-                                req->id.idiag_dport, req->id.idiag_src[0],
--                               req->id.idiag_sport, req->id.idiag_if);
-+                               req->id.idiag_sport, req->id.idiag_if, net);
-       }
- #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-       else if (req->idiag_family == AF_INET6) {
-@@ -251,7 +252,7 @@
-                                 req->id.idiag_dport,
-                                 (struct in6_addr *)req->id.idiag_src,
-                                 req->id.idiag_sport,
--                                req->id.idiag_if);
-+                                req->id.idiag_if, net);
-       }
- #endif
-       else {
-@@ -906,8 +907,8 @@
-       if (!inet_diag_table)
-               goto out;
+-      vlan_netlink_fini();
+       vlan_ioctl_set(NULL);
  
--      idiagnl = netlink_kernel_create(NETLINK_INET_DIAG, 0, inet_diag_rcv,
--                                      NULL, THIS_MODULE);
-+      idiagnl = netlink_kernel_create(&init_net, NETLINK_INET_DIAG, 0,
-+                                      inet_diag_rcv, NULL, THIS_MODULE);
-       if (idiagnl == NULL)
-               goto out_free_table;
-       err = 0;
-diff -Nurb linux-2.6.22-570/net/ipv4/inet_hashtables.c linux-2.6.22-590/net/ipv4/inet_hashtables.c
---- linux-2.6.22-570/net/ipv4/inet_hashtables.c        2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/inet_hashtables.c        2008-01-02 13:56:38.000000000 -0500
-@@ -29,11 +29,13 @@
-  */
- struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
-                                                struct inet_bind_hashbucket *head,
-+                                               struct net *net,
-                                                const unsigned short snum)
- {
-       struct inet_bind_bucket *tb = kmem_cache_alloc(cachep, GFP_ATOMIC);
+       /* Un-register us from receiving netdevice events */
+@@ -206,34 +197,6 @@
+       kfree(grp);
+ }
  
-       if (tb != NULL) {
-+              tb->net       = net;
-               tb->port      = snum;
-               tb->fastreuse = 0;
-               INIT_HLIST_HEAD(&tb->owners);
-@@ -66,7 +68,7 @@
-  */
- static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
+-static struct vlan_group *vlan_group_alloc(int ifindex)
+-{
+-      struct vlan_group *grp;
+-      unsigned int size;
+-      unsigned int i;
+-
+-      grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
+-      if (!grp)
+-              return NULL;
+-
+-      size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
+-
+-      for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
+-              grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL);
+-              if (!grp->vlan_devices_arrays[i])
+-                      goto err;
+-      }
+-
+-      grp->real_dev_ifindex = ifindex;
+-      hlist_add_head_rcu(&grp->hlist,
+-                         &vlan_group_hash[vlan_grp_hashfn(ifindex)]);
+-      return grp;
+-
+-err:
+-      vlan_group_free(grp);
+-      return NULL;
+-}
+-
+ static void vlan_rcu_free(struct rcu_head *rcu)
  {
--      const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size);
-+      const int bhash = inet_bhashfn(sk->sk_net, inet_sk(sk)->num, hashinfo->bhash_size);
-       struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
-       struct inet_bind_bucket *tb;
+       vlan_group_free(container_of(rcu, struct vlan_group, rcu));
+@@ -315,62 +278,47 @@
+       return ret;
+ }
  
-@@ -127,7 +129,7 @@
- static struct sock *inet_lookup_listener_slow(const struct hlist_head *head,
-                                             const __be32 daddr,
-                                             const unsigned short hnum,
--                                            const int dif)
-+                                            const int dif, struct net *net)
- {
-       struct sock *result = NULL, *sk;
-       const struct hlist_node *node;
-@@ -149,6 +151,8 @@
-                                       continue;
-                               score += 2;
-                       }
-+                      if (sk->sk_net != net)
-+                              continue;
-                       if (score == 5)
-                               return sk;
-                       if (score > hiscore) {
-@@ -163,22 +167,22 @@
- /* Optimize the common listener case. */
- struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
-                                   const __be32 daddr, const unsigned short hnum,
--                                  const int dif)
-+                                  const int dif, struct net *net)
+-int unregister_vlan_device(struct net_device *dev)
++static int unregister_vlan_device(const char *vlan_IF_name)
  {
-       struct sock *sk = NULL;
-       const struct hlist_head *head;
++      struct net_device *dev = NULL;
+       int ret;
  
-       read_lock(&hashinfo->lhash_lock);
--      head = &hashinfo->listening_hash[inet_lhashfn(hnum)];
-+      head = &hashinfo->listening_hash[net, inet_lhashfn(net, hnum)];
-       if (!hlist_empty(head)) {
-               const struct inet_sock *inet = inet_sk((sk = __sk_head(head)));
++
++      dev = dev_get_by_name(vlan_IF_name);
++      ret = -EINVAL;
++      if (dev) {
++              if (dev->priv_flags & IFF_802_1Q_VLAN) {
++                      rtnl_lock();
++
+                       ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
+                                                 VLAN_DEV_INFO(dev)->vlan_id);
++
++                      dev_put(dev);
+                       unregister_netdevice(dev);
  
-               if (inet->num == hnum && !sk->sk_node.next &&
-                   v4_inet_addr_match(sk->sk_nx_info, daddr, inet->rcv_saddr) &&
-                   (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
--                  !sk->sk_bound_dev_if)
-+                  !sk->sk_bound_dev_if && (sk->sk_net == net))
-                       goto sherry_cache;
--              sk = inet_lookup_listener_slow(head, daddr, hnum, dif);
-+              sk = inet_lookup_listener_slow(head, daddr, hnum, dif,net );
++                      rtnl_unlock();
++
+                       if (ret == 1)
+                               ret = 0;
+-      return ret;
+-}
+-
+-/*
+- * vlan network devices have devices nesting below it, and are a special
+- * "super class" of normal network devices; split their locks off into a
+- * separate class since they always nest.
+- */
+-static struct lock_class_key vlan_netdev_xmit_lock_key;
+-
+-static int vlan_dev_init(struct net_device *dev)
+-{
+-      struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
+-
+-      /* IFF_BROADCAST|IFF_MULTICAST; ??? */
+-      dev->flags  = real_dev->flags & ~IFF_UP;
+-      dev->iflink = real_dev->ifindex;
+-      dev->state  = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
+-                                        (1<<__LINK_STATE_DORMANT))) |
+-                    (1<<__LINK_STATE_PRESENT);
+-
+-      /* TODO: maybe just assign it to be ETHERNET? */
+-      dev->type = real_dev->type;
+-
+-      memcpy(dev->broadcast, real_dev->broadcast, real_dev->addr_len);
+-      memcpy(dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
+-      dev->addr_len = real_dev->addr_len;
+-
+-      if (real_dev->features & NETIF_F_HW_VLAN_TX) {
+-              dev->hard_header     = real_dev->hard_header;
+-              dev->hard_header_len = real_dev->hard_header_len;
+-              dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
+-              dev->rebuild_header  = real_dev->rebuild_header;
+               } else {
+-              dev->hard_header     = vlan_dev_hard_header;
+-              dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
+-              dev->hard_start_xmit = vlan_dev_hard_start_xmit;
+-              dev->rebuild_header  = vlan_dev_rebuild_header;
++                      printk(VLAN_ERR
++                             "%s: ERROR:      Tried to remove a non-vlan device "
++                             "with VLAN code, name: %s  priv_flags: %hX\n",
++                             __FUNCTION__, dev->name, dev->priv_flags);
++                      dev_put(dev);
++                      ret = -EPERM;
++              }
++      } else {
++#ifdef VLAN_DEBUG
++              printk(VLAN_DBG "%s: WARNING: Could not find dev.\n", __FUNCTION__);
++#endif
++              ret = -EINVAL;
        }
-       if (sk) {
- sherry_cache:
-@@ -196,12 +200,13 @@
- {
-       struct inet_hashinfo *hinfo = death_row->hashinfo;
-       struct inet_sock *inet = inet_sk(sk);
-+      struct net *net = sk->sk_net;
-       __be32 daddr = inet->rcv_saddr;
-       __be32 saddr = inet->daddr;
-       int dif = sk->sk_bound_dev_if;
-       INET_ADDR_COOKIE(acookie, saddr, daddr)
-       const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport);
--      unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
-+      unsigned int hash = inet_ehashfn(net, daddr, lport, saddr, inet->dport);
-       struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
-       struct sock *sk2;
-       const struct hlist_node *node;
-@@ -214,7 +219,7 @@
-       sk_for_each(sk2, node, &head->twchain) {
-               tw = inet_twsk(sk2);
--              if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) {
-+              if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif, net)) {
-                       if (twsk_unique(sk, sk2, twp))
-                               goto unique;
-                       else
-@@ -225,7 +230,7 @@
+-      dev->hard_header_parse = real_dev->hard_header_parse;
  
-       /* And established part... */
-       sk_for_each(sk2, node, &head->chain) {
--              if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif))
-+              if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif, net))
-                       goto not_unique;
-       }
+-      lockdep_set_class(&dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
+-      return 0;
++      return ret;
+ }
  
-@@ -271,6 +276,7 @@
- int inet_hash_connect(struct inet_timewait_death_row *death_row,
-                     struct sock *sk)
+-void vlan_setup(struct net_device *new_dev)
++static void vlan_setup(struct net_device *new_dev)
  {
-+      struct net *net = sk->sk_net;
-       struct inet_hashinfo *hinfo = death_row->hashinfo;
-       const unsigned short snum = inet_sk(sk)->num;
-       struct inet_bind_hashbucket *head;
-@@ -278,8 +284,8 @@
-       int ret;
+       SET_MODULE_OWNER(new_dev);
  
-       if (!snum) {
--              int low = sysctl_local_port_range[0];
--              int high = sysctl_local_port_range[1];
-+              int low = sk->sk_net->sysctl_local_port_range[0];
-+              int high = sk->sk_net->sysctl_local_port_range[1];
-               int range = high - low;
-               int i;
-               int port;
-@@ -291,7 +297,7 @@
-               local_bh_disable();
-               for (i = 1; i <= range; i++) {
-                       port = low + (i + offset) % range;
--                      head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)];
-+                      head = &hinfo->bhash[inet_bhashfn(net, port, hinfo->bhash_size)];
-                       spin_lock(&head->lock);
+@@ -390,7 +338,6 @@
  
-                       /* Does not bother with rcv_saddr checks,
-@@ -299,7 +305,7 @@
-                        * unique enough.
-                        */
-                       inet_bind_bucket_for_each(tb, node, &head->chain) {
--                              if (tb->port == port) {
-+                              if ((tb->port == port) && (tb->net == net)) {
-                                       BUG_TRAP(!hlist_empty(&tb->owners));
-                                       if (tb->fastreuse >= 0)
-                                               goto next_port;
-@@ -311,7 +317,7 @@
-                               }
-                       }
+       /* set up method calls */
+       new_dev->change_mtu = vlan_dev_change_mtu;
+-      new_dev->init = vlan_dev_init;
+       new_dev->open = vlan_dev_open;
+       new_dev->stop = vlan_dev_stop;
+       new_dev->set_mac_address = vlan_dev_set_mac_address;
+@@ -419,110 +366,77 @@
+       }
+ }
  
--                      tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, head, port);
-+                      tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, head, net, port);
-                       if (!tb) {
-                               spin_unlock(&head->lock);
-                               break;
-@@ -346,7 +352,7 @@
-               goto out;
+-int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id)
++/*
++ * vlan network devices have devices nesting below it, and are a special
++ * "super class" of normal network devices; split their locks off into a
++ * separate class since they always nest.
++ */
++static struct lock_class_key vlan_netdev_xmit_lock_key;
++
++
++/*  Attach a VLAN device to a mac address (ie Ethernet Card).
++ *  Returns the device that was created, or NULL if there was
++ *  an error of some kind.
++ */
++static struct net_device *register_vlan_device(const char *eth_IF_name,
++                                             unsigned short VLAN_ID)
+ {
++      struct vlan_group *grp;
++      struct net_device *new_dev;
++      struct net_device *real_dev; /* the ethernet device */
++      char name[IFNAMSIZ];
++      int i;
++
++#ifdef VLAN_DEBUG
++      printk(VLAN_DBG "%s: if_name -:%s:-     vid: %i\n",
++              __FUNCTION__, eth_IF_name, VLAN_ID);
++#endif
++
++      if (VLAN_ID >= VLAN_VID_MASK)
++              goto out_ret_null;
++
++      /* find the device relating to eth_IF_name. */
++      real_dev = dev_get_by_name(eth_IF_name);
++      if (!real_dev)
++              goto out_ret_null;
++
+       if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
+               printk(VLAN_DBG "%s: VLANs not supported on %s.\n",
+                       __FUNCTION__, real_dev->name);
+-              return -EOPNOTSUPP;
++              goto out_put_dev;
        }
  
--      head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)];
-+      head = &hinfo->bhash[inet_bhashfn(net, snum, hinfo->bhash_size)];
-       tb  = inet_csk(sk)->icsk_bind_hash;
-       spin_lock_bh(&head->lock);
-       if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
-diff -Nurb linux-2.6.22-570/net/ipv4/inet_timewait_sock.c linux-2.6.22-590/net/ipv4/inet_timewait_sock.c
---- linux-2.6.22-570/net/ipv4/inet_timewait_sock.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/inet_timewait_sock.c     2008-01-02 13:56:38.000000000 -0500
-@@ -31,7 +31,7 @@
-       write_unlock(&ehead->lock);
+       if ((real_dev->features & NETIF_F_HW_VLAN_RX) &&
+           !real_dev->vlan_rx_register) {
+               printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
+                       __FUNCTION__, real_dev->name);
+-              return -EOPNOTSUPP;
++              goto out_put_dev;
+       }
  
-       /* Disassociate with bind bucket. */
--      bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_num, hashinfo->bhash_size)];
-+      bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_net, tw->tw_num, hashinfo->bhash_size)];
-       spin_lock(&bhead->lock);
-       tb = tw->tw_tb;
-       __hlist_del(&tw->tw_bind_node);
-@@ -65,7 +65,7 @@
-          Note, that any socket with inet->num != 0 MUST be bound in
-          binding cache, even if it is closed.
-        */
--      bhead = &hashinfo->bhash[inet_bhashfn(inet->num, hashinfo->bhash_size)];
-+      bhead = &hashinfo->bhash[inet_bhashfn(sk->sk_net, inet->num, hashinfo->bhash_size)];
-       spin_lock(&bhead->lock);
-       tw->tw_tb = icsk->icsk_bind_hash;
-       BUG_TRAP(icsk->icsk_bind_hash);
-diff -Nurb linux-2.6.22-570/net/ipv4/inetpeer.c linux-2.6.22-590/net/ipv4/inetpeer.c
---- linux-2.6.22-570/net/ipv4/inetpeer.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/inetpeer.c       2008-01-02 13:56:38.000000000 -0500
-@@ -81,71 +81,94 @@
-       .avl_height     = 0
- };
- #define peer_avl_empty (&peer_fake_node)
--static struct inet_peer *peer_root = peer_avl_empty;
- static DEFINE_RWLOCK(peer_pool_lock);
- #define PEER_MAXDEPTH 40 /* sufficient for about 2^27 nodes */
+       if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
+           (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) {
+               printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
+                       __FUNCTION__, real_dev->name);
+-              return -EOPNOTSUPP;
++              goto out_put_dev;
+       }
  
--static int peer_total;
--/* Exported for sysctl_net_ipv4.  */
--int inet_peer_threshold __read_mostly = 65536 + 128;  /* start to throw entries more
--                                       * aggressively at this stage */
--int inet_peer_minttl __read_mostly = 120 * HZ;        /* TTL under high load: 120 sec */
--int inet_peer_maxttl __read_mostly = 10 * 60 * HZ;    /* usual time to live: 10 min */
--int inet_peer_gc_mintime __read_mostly = 10 * HZ;
--int inet_peer_gc_maxtime __read_mostly = 120 * HZ;
--
--static struct inet_peer *inet_peer_unused_head;
--static struct inet_peer **inet_peer_unused_tailp = &inet_peer_unused_head;
- static DEFINE_SPINLOCK(inet_peer_unused_lock);
++      /* From this point on, all the data structures must remain
++       * consistent.
++       */
++      rtnl_lock();
++
+       /* The real device must be up and operating in order to
+        * assosciate a VLAN device with it.
+        */
+       if (!(real_dev->flags & IFF_UP))
+-              return -ENETDOWN;
++              goto out_unlock;
  
- static void peer_check_expire(unsigned long dummy);
--static DEFINE_TIMER(peer_periodic_timer, peer_check_expire, 0, 0);
+-      if (__find_vlan_dev(real_dev, vlan_id) != NULL) {
++      if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) {
+               /* was already registered. */
+               printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__);
+-              return -EEXIST;
++              goto out_unlock;
+       }
  
-+static int inet_peers_net_init(struct net *net);
-+static void inet_peers_net_exit(struct net *net);
-+static struct pernet_operations inet_peers_net_ops = {
-+      .init = inet_peers_net_init,
-+      .exit = inet_peers_net_exit,
-+};
+-      return 0;
+-}
+-
+-int register_vlan_dev(struct net_device *dev)
+-{
+-      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+-      struct net_device *real_dev = vlan->real_dev;
+-      unsigned short vlan_id = vlan->vlan_id;
+-      struct vlan_group *grp, *ngrp = NULL;
+-      int err;
+-
+-      grp = __vlan_find_group(real_dev->ifindex);
+-      if (!grp) {
+-              ngrp = grp = vlan_group_alloc(real_dev->ifindex);
+-              if (!grp)
+-                      return -ENOBUFS;
+-      }
+-
+-      err = register_netdevice(dev);
+-      if (err < 0)
+-              goto out_free_group;
+-
+-      /* Account for reference in struct vlan_dev_info */
+-      dev_hold(real_dev);
+-
+-      vlan_transfer_operstate(real_dev, dev);
+-      linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */
+-
+-      /* So, got the sucker initialized, now lets place
+-       * it into our local structure.
+-       */
+-      vlan_group_set_device(grp, vlan_id, dev);
+-      if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
+-              real_dev->vlan_rx_register(real_dev, ngrp);
+-      if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
+-              real_dev->vlan_rx_add_vid(real_dev, vlan_id);
+-
+-      if (vlan_proc_add_dev(dev) < 0)
+-              printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
+-                     dev->name);
+-      return 0;
+-
+-out_free_group:
+-      if (ngrp)
+-              vlan_group_free(ngrp);
+-      return err;
+-}
+-
+-/*  Attach a VLAN device to a mac address (ie Ethernet Card).
+- *  Returns 0 if the device was created or a negative error code otherwise.
+- */
+-static int register_vlan_device(struct net_device *real_dev,
+-                              unsigned short VLAN_ID)
+-{
+-      struct net_device *new_dev;
+-      char name[IFNAMSIZ];
+-      int err;
+-
+-#ifdef VLAN_DEBUG
+-      printk(VLAN_DBG "%s: if_name -:%s:-     vid: %i\n",
+-              __FUNCTION__, eth_IF_name, VLAN_ID);
+-#endif
+-
+-      if (VLAN_ID >= VLAN_VID_MASK)
+-              return -ERANGE;
+-
+-      err = vlan_check_real_dev(real_dev, VLAN_ID);
+-      if (err < 0)
+-              return err;
+-
+       /* Gotta set up the fields for the device. */
+ #ifdef VLAN_DEBUG
+       printk(VLAN_DBG "About to allocate name, vlan_name_type: %i\n",
+@@ -557,40 +471,138 @@
+                              vlan_setup);
  
- /* Called from ip_output.c:ip_init  */
- void __init inet_initpeers(void)
- {
-+      peer_cachep = kmem_cache_create("inet_peer_cache",
-+                      sizeof(struct inet_peer),
-+                      0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+                      NULL, NULL);
+       if (new_dev == NULL)
+-              return -ENOBUFS;
++              goto out_unlock;
 +
-+      register_pernet_subsys(&inet_peers_net_ops);
-+}
++#ifdef VLAN_DEBUG
++      printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
++#endif
++      /* IFF_BROADCAST|IFF_MULTICAST; ??? */
++      new_dev->flags = real_dev->flags;
++      new_dev->flags &= ~IFF_UP;
 +
-+static int inet_peers_net_init(struct net *net)
-+{
-       struct sysinfo si;
++      new_dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
++                                           (1<<__LINK_STATE_DORMANT))) |
++                       (1<<__LINK_STATE_PRESENT);
+       /* need 4 bytes for extra VLAN header info,
+        * hope the underlying device can handle it.
+        */
+       new_dev->mtu = real_dev->mtu;
  
-+      net->peer_root = peer_avl_empty;
-+      net->inet_peer_unused_tailp = &net->inet_peer_unused_head;
+-#ifdef VLAN_DEBUG
+-      printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
++      /* TODO: maybe just assign it to be ETHERNET? */
++      new_dev->type = real_dev->type;
 +
-+      net->inet_peer_threshold = 65536 + 128; /* start to throw entries more
-+                                               * aggressively at this stage */
-+      net->inet_peer_minttl = 120 * HZ;       /* TTL under high load: 120 sec */
-+      net->inet_peer_maxttl = 10 * 60 * HZ;   /* usual time to live: 10 min */
-+      net->inet_peer_gc_mintime = 10 * HZ;
-+      net->inet_peer_gc_maxtime = 120 * HZ;
++      new_dev->hard_header_len = real_dev->hard_header_len;
++      if (!(real_dev->features & NETIF_F_HW_VLAN_TX)) {
++              /* Regular ethernet + 4 bytes (18 total). */
++              new_dev->hard_header_len += VLAN_HLEN;
++      }
 +
-       /* Use the straight interface to information about memory. */
-       si_meminfo(&si);
+       VLAN_MEM_DBG("new_dev->priv malloc, addr: %p  size: %i\n",
+                    new_dev->priv,
+                    sizeof(struct vlan_dev_info));
+-#endif
 +
-       /* The values below were suggested by Alexey Kuznetsov
-        * <kuznet@ms2.inr.ac.ru>.  I don't have any opinion about the values
-        * myself.  --SAW
-        */
-       if (si.totalram <= (32768*1024)/PAGE_SIZE)
--              inet_peer_threshold >>= 1; /* max pool size about 1MB on IA32 */
-+              net->inet_peer_threshold >>= 1; /* max pool size about 1MB on IA32 */
-       if (si.totalram <= (16384*1024)/PAGE_SIZE)
--              inet_peer_threshold >>= 1; /* about 512KB */
-+              net->inet_peer_threshold >>= 1; /* about 512KB */
-       if (si.totalram <= (8192*1024)/PAGE_SIZE)
--              inet_peer_threshold >>= 2; /* about 128KB */
-+              net->inet_peer_threshold >>= 2; /* about 128KB */
++      memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len);
++      memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
++      new_dev->addr_len = real_dev->addr_len;
++
++      if (real_dev->features & NETIF_F_HW_VLAN_TX) {
++              new_dev->hard_header = real_dev->hard_header;
++              new_dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
++              new_dev->rebuild_header = real_dev->rebuild_header;
++      } else {
++              new_dev->hard_header = vlan_dev_hard_header;
++              new_dev->hard_start_xmit = vlan_dev_hard_start_xmit;
++              new_dev->rebuild_header = vlan_dev_rebuild_header;
++      }
++      new_dev->hard_header_parse = real_dev->hard_header_parse;
  
--      peer_cachep = kmem_cache_create("inet_peer_cache",
--                      sizeof(struct inet_peer),
--                      0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
--                      NULL, NULL);
+       VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */
+       VLAN_DEV_INFO(new_dev)->real_dev = real_dev;
+       VLAN_DEV_INFO(new_dev)->dent = NULL;
+-      VLAN_DEV_INFO(new_dev)->flags = VLAN_FLAG_REORDER_HDR;
++      VLAN_DEV_INFO(new_dev)->flags = 1;
  
-+      init_timer(&net->peer_periodic_timer);
-+      net->peer_periodic_timer.function = peer_check_expire;
-       /* All the timers, started at system startup tend
-          to synchronize. Perturb it a bit.
-        */
--      peer_periodic_timer.expires = jiffies
--              + net_random() % inet_peer_gc_maxtime
--              + inet_peer_gc_maxtime;
--      add_timer(&peer_periodic_timer);
-+      net->peer_periodic_timer.expires = jiffies
-+              + net_random() % net->inet_peer_gc_maxtime
-+              + net->inet_peer_gc_maxtime;
-+      /* Remember our namespace */
-+      net->peer_periodic_timer.data = (unsigned long)net;
-+      add_timer(&net->peer_periodic_timer);
-+      
-+      return 0;
-+}
+-      new_dev->rtnl_link_ops = &vlan_link_ops;
+-      err = register_vlan_dev(new_dev);
+-      if (err < 0)
++#ifdef VLAN_DEBUG
++      printk(VLAN_DBG "About to go find the group for idx: %i\n",
++             real_dev->ifindex);
++#endif
 +
-+static void inet_peers_net_exit(struct net *net)
-+{
-+      del_timer(&net->peer_periodic_timer);
-+      /* CHECKME do I need to do something to release all of the peers */
- }
++      if (register_netdevice(new_dev))
+               goto out_free_newdev;
  
- /* Called with or without local BH being disabled. */
--static void unlink_from_unused(struct inet_peer *p)
-+static void unlink_from_unused(struct net *net, struct inet_peer *p)
- {
-       spin_lock_bh(&inet_peer_unused_lock);
-       if (p->unused_prevp != NULL) {
-               /* On unused list. */
--              *p->unused_prevp = p->unused_next;
--              if (p->unused_next != NULL)
--                      p->unused_next->unused_prevp = p->unused_prevp;
-+              *p->unused_prevp = p->u.unused_next;
-+              if (p->u.unused_next != NULL)
-+                      p->u.unused_next->unused_prevp = p->unused_prevp;
-               else
--                      inet_peer_unused_tailp = p->unused_prevp;
-+                      net->inet_peer_unused_tailp = p->unused_prevp;
-               p->unused_prevp = NULL; /* mark it as removed */
-+              p->u.net = hold_net(net); /* Remember the net */
-       }
-       spin_unlock_bh(&inet_peer_unused_lock);
+-      /* Account for reference in struct vlan_dev_info */
+-      dev_hold(real_dev);
++      lockdep_set_class(&new_dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
++
++      new_dev->iflink = real_dev->ifindex;
++      vlan_transfer_operstate(real_dev, new_dev);
++      linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */
++
++      /* So, got the sucker initialized, now lets place
++       * it into our local structure.
++       */
++      grp = __vlan_find_group(real_dev->ifindex);
++
++      /* Note, we are running under the RTNL semaphore
++       * so it cannot "appear" on us.
++       */
++      if (!grp) { /* need to add a new group */
++              grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
++              if (!grp)
++                      goto out_free_unregister;
++
++              for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
++                      grp->vlan_devices_arrays[i] = kzalloc(
++                              sizeof(struct net_device *)*VLAN_GROUP_ARRAY_PART_LEN,
++                              GFP_KERNEL);
++
++                      if (!grp->vlan_devices_arrays[i])
++                              goto out_free_arrays;
++              }
++
++              /* printk(KERN_ALERT "VLAN REGISTER:  Allocated new group.\n"); */
++              grp->real_dev_ifindex = real_dev->ifindex;
++
++              hlist_add_head_rcu(&grp->hlist,
++                                 &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
++
++              if (real_dev->features & NETIF_F_HW_VLAN_RX)
++                      real_dev->vlan_rx_register(real_dev, grp);
++      }
++
++      vlan_group_set_device(grp, VLAN_ID, new_dev);
++
++      if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */
++              printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
++                                                       new_dev->name);
++
++      if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
++              real_dev->vlan_rx_add_vid(real_dev, VLAN_ID);
++
++      rtnl_unlock();
++
++
+ #ifdef VLAN_DEBUG
+       printk(VLAN_DBG "Allocated new device successfully, returning.\n");
+ #endif
+-      return 0;
++      return new_dev;
++
++out_free_arrays:
++      vlan_group_free(grp);
++
++out_free_unregister:
++      unregister_netdev(new_dev);
++      goto out_unlock;
+ out_free_newdev:
+       free_netdev(new_dev);
+-      return err;
++
++out_unlock:
++      rtnl_unlock();
++
++out_put_dev:
++      dev_put(real_dev);
++
++out_ret_null:
++      return NULL;
  }
-@@ -160,9 +183,9 @@
-       struct inet_peer *u, **v;                               \
-       if (_stack) {                                           \
-               stackptr = _stack;                              \
--              *stackptr++ = &peer_root;                       \
-+              *stackptr++ = &net->peer_root;                  \
-       }                                                       \
--      for (u = peer_root; u != peer_avl_empty; ) {            \
-+      for (u = net->peer_root; u != peer_avl_empty; ) {       \
-               if (_daddr == u->v4daddr)                       \
-                       break;                                  \
-               if ((__force __u32)_daddr < (__force __u32)u->v4daddr)  \
-@@ -279,7 +302,7 @@
- } while(0)
  
- /* May be called with local BH enabled. */
--static void unlink_from_pool(struct inet_peer *p)
-+static void unlink_from_pool(struct net *net, struct inet_peer *p)
- {
-       int do_free;
+ static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
+@@ -600,9 +612,6 @@
+       int i, flgs;
+       struct net_device *vlandev;
  
-@@ -317,7 +340,7 @@
-                       delp[1] = &t->avl_left; /* was &p->avl_left */
-               }
-               peer_avl_rebalance(stack, stackptr);
--              peer_total--;
-+              net->peer_total--;
-               do_free = 1;
-       }
-       write_unlock_bh(&peer_pool_lock);
-@@ -335,13 +358,13 @@
- }
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       if (!grp)
+               goto out;
  
- /* May be called with local BH enabled. */
--static int cleanup_once(unsigned long ttl)
-+static int cleanup_once(struct net *net, unsigned long ttl)
+@@ -682,12 +691,11 @@
+  *    o execute requested action or pass command to the device driver
+  *   arg is really a struct vlan_ioctl_args __user *.
+  */
+-static int vlan_ioctl_handler(struct net *net, void __user *arg)
++static int vlan_ioctl_handler(void __user *arg)
  {
-       struct inet_peer *p;
+-      int err;
++      int err = 0;
+       unsigned short vid = 0;
+       struct vlan_ioctl_args args;
+-      struct net_device *dev = NULL;
  
-       /* Remove the first entry from the list of unused nodes. */
-       spin_lock_bh(&inet_peer_unused_lock);
--      p = inet_peer_unused_head;
-+      p = net->inet_peer_unused_head;
-       if (p != NULL) {
-               __u32 delta = (__u32)jiffies - p->dtime;
-               if (delta < ttl) {
-@@ -349,12 +372,13 @@
-                       spin_unlock_bh(&inet_peer_unused_lock);
-                       return -1;
-               }
--              inet_peer_unused_head = p->unused_next;
--              if (p->unused_next != NULL)
--                      p->unused_next->unused_prevp = p->unused_prevp;
-+              net->inet_peer_unused_head = p->u.unused_next;
-+              if (p->u.unused_next != NULL)
-+                      p->u.unused_next->unused_prevp = p->unused_prevp;
-               else
--                      inet_peer_unused_tailp = p->unused_prevp;
-+                      net->inet_peer_unused_tailp = p->unused_prevp;
-               p->unused_prevp = NULL; /* mark as not on the list */
-+              p->u.net = hold_net(net);
-               /* Grab an extra reference to prevent node disappearing
-                * before unlink_from_pool() call. */
-               atomic_inc(&p->refcnt);
-@@ -367,12 +391,12 @@
-                * happen because of entry limits in route cache. */
-               return -1;
+       if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
+               return -EFAULT;
+@@ -700,61 +708,35 @@
+       printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd);
+ #endif
  
--      unlink_from_pool(p);
-+      unlink_from_pool(net, p);
-       return 0;
- }
+-      rtnl_lock();
+-
+       switch (args.cmd) {
+       case SET_VLAN_INGRESS_PRIORITY_CMD:
+-      case SET_VLAN_EGRESS_PRIORITY_CMD:
+-      case SET_VLAN_FLAG_CMD:
+-      case ADD_VLAN_CMD:
+-      case DEL_VLAN_CMD:
+-      case GET_VLAN_REALDEV_NAME_CMD:
+-      case GET_VLAN_VID_CMD:
+-              err = -ENODEV;
+-              dev = __dev_get_by_name(&init_net, args.device1);
+-              if (!dev)
+-                      goto out;
+-
+-              err = -EINVAL;
+-              if (args.cmd != ADD_VLAN_CMD &&
+-                  !(dev->priv_flags & IFF_802_1Q_VLAN))
+-                      goto out;
+-      }
+-
+-      switch (args.cmd) {
+-      case SET_VLAN_INGRESS_PRIORITY_CMD:
+-              err = -EPERM;
+               if (!capable(CAP_NET_ADMIN))
+-                      break;
+-              vlan_dev_set_ingress_priority(dev,
++                      return -EPERM;
++              err = vlan_dev_set_ingress_priority(args.device1,
+                                                   args.u.skb_priority,
+                                                   args.vlan_qos);
+               break;
  
- /* Called with or without local BH being disabled. */
--struct inet_peer *inet_getpeer(__be32 daddr, int create)
-+struct inet_peer *inet_getpeer(struct net *net, __be32 daddr, int create)
- {
-       struct inet_peer *p, *n;
-       struct inet_peer **stack[PEER_MAXDEPTH], ***stackptr;
-@@ -387,7 +411,7 @@
-       if (p != peer_avl_empty) {
-               /* The existing node has been found. */
-               /* Remove the entry from unused list if it was there. */
--              unlink_from_unused(p);
-+              unlink_from_unused(net, p);
-               return p;
-       }
+       case SET_VLAN_EGRESS_PRIORITY_CMD:
+-              err = -EPERM;
+               if (!capable(CAP_NET_ADMIN))
+-                      break;
+-              err = vlan_dev_set_egress_priority(dev,
++                      return -EPERM;
++              err = vlan_dev_set_egress_priority(args.device1,
+                                                  args.u.skb_priority,
+                                                  args.vlan_qos);
+               break;
  
-@@ -413,13 +437,13 @@
-       /* Link the node. */
-       link_to_pool(n);
-       n->unused_prevp = NULL; /* not on the list */
--      peer_total++;
-+      n->u.net = hold_net(net); /* Remember the net */
-+      net->peer_total++;
-       write_unlock_bh(&peer_pool_lock);
+       case SET_VLAN_FLAG_CMD:
+-              err = -EPERM;
+               if (!capable(CAP_NET_ADMIN))
+-                      break;
+-              err = vlan_dev_set_vlan_flag(dev,
++                      return -EPERM;
++              err = vlan_dev_set_vlan_flag(args.device1,
+                                            args.u.flag,
+                                            args.vlan_qos);
+               break;
  
--      if (peer_total >= inet_peer_threshold)
-+      if (net->peer_total >= net->inet_peer_threshold)
-               /* Remove one less-recently-used entry. */
--              cleanup_once(0);
--
-+              cleanup_once(net, 0);
-       return n;
+       case SET_VLAN_NAME_TYPE_CMD:
+-              err = -EPERM;
+               if (!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+-              if ((args.u.name_type >= 0) &&
+-                  (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
++              if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) {
+                       vlan_name_type = args.u.name_type;
+                       err = 0;
+               } else {
+@@ -763,17 +745,26 @@
+               break;
  
- out_free:
-@@ -427,25 +451,26 @@
-       atomic_inc(&p->refcnt);
-       write_unlock_bh(&peer_pool_lock);
-       /* Remove the entry from unused list if it was there. */
--      unlink_from_unused(p);
-+      unlink_from_unused(net, p);
-       /* Free preallocated the preallocated node. */
-       kmem_cache_free(peer_cachep, n);
-       return p;
- }
+       case ADD_VLAN_CMD:
+-              err = -EPERM;
+               if (!capable(CAP_NET_ADMIN))
+-                      break;
+-              err = register_vlan_device(dev, args.u.VID);
++                      return -EPERM;
++              /* we have been given the name of the Ethernet Device we want to
++               * talk to:  args.dev1   We also have the
++               * VLAN ID:  args.u.VID
++               */
++              if (register_vlan_device(args.device1, args.u.VID)) {
++                      err = 0;
++              } else {
++                      err = -EINVAL;
++              }
+               break;
  
- /* Called with local BH disabled. */
--static void peer_check_expire(unsigned long dummy)
-+static void peer_check_expire(unsigned long arg)
- {
-+      struct net *net = (void *)arg;
-       unsigned long now = jiffies;
-       int ttl;
+       case DEL_VLAN_CMD:
+-              err = -EPERM;
+               if (!capable(CAP_NET_ADMIN))
+-                      break;
+-              err = unregister_vlan_device(dev);
++                      return -EPERM;
++              /* Here, the args.dev1 is the actual VLAN we want
++               * to get rid of.
++               */
++              err = unregister_vlan_device(args.device1);
+               break;
  
--      if (peer_total >= inet_peer_threshold)
--              ttl = inet_peer_minttl;
-+      if (net->peer_total >= net->inet_peer_threshold)
-+              ttl = net->inet_peer_minttl;
-       else
--              ttl = inet_peer_maxttl
--                              - (inet_peer_maxttl - inet_peer_minttl) / HZ *
--                                      peer_total / inet_peer_threshold * HZ;
--      while (!cleanup_once(ttl)) {
-+              ttl = net->inet_peer_maxttl
-+                      - (net->inet_peer_maxttl - net->inet_peer_minttl) / HZ *
-+                              net->peer_total / net->inet_peer_threshold * HZ;
-+      while (!cleanup_once(net, ttl)) {
-               if (jiffies != now)
-                       break;
-       }
-@@ -453,25 +478,30 @@
-       /* Trigger the timer after inet_peer_gc_mintime .. inet_peer_gc_maxtime
-        * interval depending on the total number of entries (more entries,
-        * less interval). */
--      if (peer_total >= inet_peer_threshold)
--              peer_periodic_timer.expires = jiffies + inet_peer_gc_mintime;
-+      if (net->peer_total >= net->inet_peer_threshold)
-+              net->peer_periodic_timer.expires = jiffies 
-+                      + net->inet_peer_gc_mintime;
-       else
--              peer_periodic_timer.expires = jiffies
--                      + inet_peer_gc_maxtime
--                      - (inet_peer_gc_maxtime - inet_peer_gc_mintime) / HZ *
--                              peer_total / inet_peer_threshold * HZ;
--      add_timer(&peer_periodic_timer);
-+              net->peer_periodic_timer.expires = jiffies
-+                      + net->inet_peer_gc_maxtime
-+                      - (net->inet_peer_gc_maxtime - net->inet_peer_gc_mintime) / HZ *
-+                              net->peer_total / net->inet_peer_threshold * HZ;
-+      add_timer(&net->peer_periodic_timer);
- }
+       case GET_VLAN_INGRESS_PRIORITY_CMD:
+@@ -797,7 +788,9 @@
+               err = -EINVAL;
+               break;
+       case GET_VLAN_REALDEV_NAME_CMD:
+-              vlan_dev_get_realdev_name(dev, args.u.device2);
++              err = vlan_dev_get_realdev_name(args.device1, args.u.device2);
++              if (err)
++                      goto out;
+               if (copy_to_user(arg, &args,
+                                sizeof(struct vlan_ioctl_args))) {
+                       err = -EFAULT;
+@@ -805,7 +798,9 @@
+               break;
  
- void inet_putpeer(struct inet_peer *p)
- {
-       spin_lock_bh(&inet_peer_unused_lock);
-       if (atomic_dec_and_test(&p->refcnt)) {
--              p->unused_prevp = inet_peer_unused_tailp;
--              p->unused_next = NULL;
--              *inet_peer_unused_tailp = p;
--              inet_peer_unused_tailp = &p->unused_next;
-+              struct net *net = p->u.net;
-+
-+              p->unused_prevp = net->inet_peer_unused_tailp;
-+              p->u.unused_next = NULL;
-+              *net->inet_peer_unused_tailp = p;
-+              net->inet_peer_unused_tailp = &p->u.unused_next;
-               p->dtime = (__u32)jiffies;
-+
-+              release_net(net);
+       case GET_VLAN_VID_CMD:
+-              vlan_dev_get_vid(dev, &vid);
++              err = vlan_dev_get_vid(args.device1, &vid);
++              if (err)
++                      goto out;
+               args.u.VID = vid;
+               if (copy_to_user(arg, &args,
+                                sizeof(struct vlan_ioctl_args))) {
+@@ -817,11 +812,9 @@
+               /* pass on to underlying device instead?? */
+               printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",
+                       __FUNCTION__, args.cmd);
+-              err = -EINVAL;
+-              break;
++              return -EINVAL;
        }
-       spin_unlock_bh(&inet_peer_unused_lock);
+ out:
+-      rtnl_unlock();
+       return err;
  }
-diff -Nurb linux-2.6.22-570/net/ipv4/ip_fragment.c linux-2.6.22-590/net/ipv4/ip_fragment.c
---- linux-2.6.22-570/net/ipv4/ip_fragment.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ip_fragment.c    2008-01-02 13:56:38.000000000 -0500
-@@ -49,21 +49,6 @@
-  * as well. Or notify me, at least. --ANK
-  */
  
--/* Fragment cache limits. We will commit 256K at one time. Should we
-- * cross that limit we will prune down to 192K. This should cope with
-- * even the most extreme cases without allowing an attacker to measurably
-- * harm machine performance.
-- */
--int sysctl_ipfrag_high_thresh __read_mostly = 256*1024;
--int sysctl_ipfrag_low_thresh __read_mostly = 192*1024;
+diff -Nurb linux-2.6.22-590/net/8021q/vlan.h linux-2.6.22-570/net/8021q/vlan.h
+--- linux-2.6.22-590/net/8021q/vlan.h  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/8021q/vlan.h  2007-07-08 19:32:17.000000000 -0400
+@@ -62,24 +62,11 @@
+ int vlan_dev_open(struct net_device* dev);
+ int vlan_dev_stop(struct net_device* dev);
+ int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd);
+-void vlan_dev_set_ingress_priority(const struct net_device *dev,
+-                                 u32 skb_prio, short vlan_prio);
+-int vlan_dev_set_egress_priority(const struct net_device *dev,
+-                               u32 skb_prio, short vlan_prio);
+-int vlan_dev_set_vlan_flag(const struct net_device *dev,
+-                         u32 flag, short flag_val);
+-void vlan_dev_get_realdev_name(const struct net_device *dev, char *result);
+-void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result);
++int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
++int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
++int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
++int vlan_dev_get_realdev_name(const char* dev_name, char* result);
++int vlan_dev_get_vid(const char* dev_name, unsigned short* result);
+ void vlan_dev_set_multicast_list(struct net_device *vlan_dev);
+-int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id);
+-void vlan_setup(struct net_device *dev);
+-int register_vlan_dev(struct net_device *dev);
+-int unregister_vlan_device(struct net_device *dev);
 -
--int sysctl_ipfrag_max_dist __read_mostly = 64;
+-int vlan_netlink_init(void);
+-void vlan_netlink_fini(void);
 -
--/* Important NOTE! Fragment queue must be destroyed before MSL expires.
-- * RFC791 is wrong proposing to prolongate timer each fragment arrival by TTL.
-- */
--int sysctl_ipfrag_time __read_mostly = IP_FRAG_TIME;
+-extern struct rtnl_link_ops vlan_link_ops;
 -
- struct ipfrag_skb_cb
- {
-       struct inet_skb_parm    h;
-@@ -96,6 +81,7 @@
-       int             iif;
-       unsigned int    rid;
-       struct inet_peer *peer;
-+      struct net      *net;
- };
+ #endif /* !(__BEN_VLAN_802_1Q_INC__) */
+diff -Nurb linux-2.6.22-590/net/8021q/vlan_dev.c linux-2.6.22-570/net/8021q/vlan_dev.c
+--- linux-2.6.22-590/net/8021q/vlan_dev.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/8021q/vlan_dev.c      2008-01-23 19:15:56.000000000 -0500
+@@ -73,7 +73,7 @@
  
- /* Hash table. */
-@@ -103,17 +89,13 @@
- #define IPQ_HASHSZ    64
+ static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb)
+ {
+-      if (VLAN_DEV_INFO(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) {
++      if (VLAN_DEV_INFO(skb->dev)->flags & 1) {
+               if (skb_shared(skb) || skb_cloned(skb)) {
+                       struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
+                       kfree_skb(skb);
+@@ -132,11 +132,6 @@
  
- /* Per-bucket lock is easy to add now. */
--static struct hlist_head ipq_hash[IPQ_HASHSZ];
- static DEFINE_RWLOCK(ipfrag_lock);
--static u32 ipfrag_hash_rnd;
--static LIST_HEAD(ipq_lru_list);
--int ip_frag_nqueues = 0;
+       vhdr = (struct vlan_hdr *)(skb->data);
  
- static __inline__ void __ipq_unlink(struct ipq *qp)
- {
-       hlist_del(&qp->list);
-       list_del(&qp->lru_list);
--      ip_frag_nqueues--;
-+      qp->net->ip_frag_nqueues--;
- }
+-      if (dev->nd_net != &init_net) {
+-              kfree_skb(skb);
+-              return 0;
+-      }
+-
+       /* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */
+       vlan_TCI = ntohs(vhdr->h_vlan_TCI);
  
- static __inline__ void ipq_unlink(struct ipq *ipq)
-@@ -123,70 +105,71 @@
-       write_unlock(&ipfrag_lock);
- }
+@@ -365,8 +360,7 @@
+        * header shuffling in the hard_start_xmit.  Users can turn off this
+        * REORDER behaviour with the vconfig tool.
+        */
+-      if (!(VLAN_DEV_INFO(dev)->flags & VLAN_FLAG_REORDER_HDR))
+-              build_vlan_header = 1;
++      build_vlan_header = ((VLAN_DEV_INFO(dev)->flags & 1) == 0);
  
--static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
-+static unsigned int ipqhashfn(struct net *net, __be16 id, __be32 saddr, __be32 daddr, u8 prot)
- {
-       return jhash_3words((__force u32)id << 16 | prot,
-                           (__force u32)saddr, (__force u32)daddr,
--                          ipfrag_hash_rnd) & (IPQ_HASHSZ - 1);
-+                          net->ipfrag_hash_rnd) & (IPQ_HASHSZ - 1);
+       if (build_vlan_header) {
+               vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN);
+@@ -550,83 +544,136 @@
+       return 0;
  }
  
--static struct timer_list ipfrag_secret_timer;
--int sysctl_ipfrag_secret_interval __read_mostly = 10 * 60 * HZ;
--
--static void ipfrag_secret_rebuild(unsigned long dummy)
-+static void ipfrag_secret_rebuild(unsigned long arg)
+-void vlan_dev_set_ingress_priority(const struct net_device *dev,
+-                                 u32 skb_prio, short vlan_prio)
++int vlan_dev_set_ingress_priority(char *dev_name, __u32 skb_prio, short vlan_prio)
  {
-+      struct net *net = (void *)arg;
-       unsigned long now = jiffies;
-       int i;
+-      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
++      struct net_device *dev = dev_get_by_name(dev_name);
  
-       write_lock(&ipfrag_lock);
--      get_random_bytes(&ipfrag_hash_rnd, sizeof(u32));
-+      get_random_bytes(&net->ipfrag_hash_rnd, sizeof(u32));
-       for (i = 0; i < IPQ_HASHSZ; i++) {
-               struct ipq *q;
-+              struct hlist_head *head;
-               struct hlist_node *p, *n;
+-      if (vlan->ingress_priority_map[vlan_prio & 0x7] && !skb_prio)
+-              vlan->nr_ingress_mappings--;
+-      else if (!vlan->ingress_priority_map[vlan_prio & 0x7] && skb_prio)
+-              vlan->nr_ingress_mappings++;
++      if (dev) {
++              if (dev->priv_flags & IFF_802_1Q_VLAN) {
++                      /* see if a priority mapping exists.. */
++                      VLAN_DEV_INFO(dev)->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
++                      dev_put(dev);
++                      return 0;
++              }
  
--              hlist_for_each_entry_safe(q, p, n, &ipq_hash[i], list) {
--                      unsigned int hval = ipqhashfn(q->id, q->saddr,
-+              head = &net->ipq_hash[i];
-+              hlist_for_each_entry_safe(q, p, n, head, list) {
-+                      unsigned int hval = ipqhashfn(net, q->id, q->saddr,
-                                                     q->daddr, q->protocol);
+-      vlan->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
++              dev_put(dev);
++      }
++      return -EINVAL;
+ }
  
-                       if (hval != i) {
-                               hlist_del(&q->list);
+-int vlan_dev_set_egress_priority(const struct net_device *dev,
+-                               u32 skb_prio, short vlan_prio)
++int vlan_dev_set_egress_priority(char *dev_name, __u32 skb_prio, short vlan_prio)
+ {
+-      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
++      struct net_device *dev = dev_get_by_name(dev_name);
+       struct vlan_priority_tci_mapping *mp = NULL;
+       struct vlan_priority_tci_mapping *np;
+-      u32 vlan_qos = (vlan_prio << 13) & 0xE000;
  
-                               /* Relink to new hash chain. */
--                              hlist_add_head(&q->list, &ipq_hash[hval]);
-+                              hlist_add_head(&q->list, &net->ipq_hash[hval]);
++      if (dev) {
++              if (dev->priv_flags & IFF_802_1Q_VLAN) {
+                       /* See if a priority mapping exists.. */
+-      mp = vlan->egress_priority_map[skb_prio & 0xF];
++                      mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF];
+                       while (mp) {
+                               if (mp->priority == skb_prio) {
+-                      if (mp->vlan_qos && !vlan_qos)
+-                              vlan->nr_egress_mappings--;
+-                      else if (!mp->vlan_qos && vlan_qos)
+-                              vlan->nr_egress_mappings++;
+-                      mp->vlan_qos = vlan_qos;
++                                      mp->vlan_qos = ((vlan_prio << 13) & 0xE000);
++                                      dev_put(dev);
+                                       return 0;
+                               }
+                               mp = mp->next;
                        }
-               }
-       }
-       write_unlock(&ipfrag_lock);
  
--      mod_timer(&ipfrag_secret_timer, now + sysctl_ipfrag_secret_interval);
-+      mod_timer(&net->ipfrag_secret_timer, 
-+              now + net->sysctl_ipfrag_secret_interval);
+                       /* Create a new mapping then. */
+-      mp = vlan->egress_priority_map[skb_prio & 0xF];
++                      mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF];
+                       np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL);
+-      if (!np)
+-              return -ENOBUFS;
+-
++                      if (np) {
+                               np->next = mp;
+                               np->priority = skb_prio;
+-      np->vlan_qos = vlan_qos;
+-      vlan->egress_priority_map[skb_prio & 0xF] = np;
+-      if (vlan_qos)
+-              vlan->nr_egress_mappings++;
++                              np->vlan_qos = ((vlan_prio << 13) & 0xE000);
++                              VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF] = np;
++                              dev_put(dev);
+                               return 0;
++                      } else {
++                              dev_put(dev);
++                              return -ENOBUFS;
++                      }
++              }
++              dev_put(dev);
++      }
++      return -EINVAL;
  }
  
--atomic_t ip_frag_mem = ATOMIC_INIT(0);        /* Memory used for fragments */
--
- /* Memory Tracking Functions. */
--static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work)
-+static __inline__ void frag_kfree_skb(struct net *net, struct sk_buff *skb, int *work)
+-/* Flags are defined in the vlan_flags enum in include/linux/if_vlan.h file. */
+-int vlan_dev_set_vlan_flag(const struct net_device *dev,
+-                         u32 flag, short flag_val)
++/* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */
++int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val)
  {
-       if (work)
-               *work -= skb->truesize;
--      atomic_sub(skb->truesize, &ip_frag_mem);
-+      atomic_sub(skb->truesize, &net->ip_frag_mem);
-       kfree_skb(skb);
++      struct net_device *dev = dev_get_by_name(dev_name);
++
++      if (dev) {
++              if (dev->priv_flags & IFF_802_1Q_VLAN) {
+                       /* verify flag is supported */
+-      if (flag == VLAN_FLAG_REORDER_HDR) {
++                      if (flag == 1) {
+                               if (flag_val) {
+-                      VLAN_DEV_INFO(dev)->flags |= VLAN_FLAG_REORDER_HDR;
++                                      VLAN_DEV_INFO(dev)->flags |= 1;
+                               } else {
+-                      VLAN_DEV_INFO(dev)->flags &= ~VLAN_FLAG_REORDER_HDR;
++                                      VLAN_DEV_INFO(dev)->flags &= ~1;
+                               }
++                              dev_put(dev);
+                               return 0;
++                      } else {
++                              printk(KERN_ERR  "%s: flag %i is not valid.\n",
++                                      __FUNCTION__, (int)(flag));
++                              dev_put(dev);
++                              return -EINVAL;
+                       }
+-      printk(KERN_ERR "%s: flag %i is not valid.\n", __FUNCTION__, flag);
++              } else {
++                      printk(KERN_ERR
++                             "%s: %s is not a vlan device, priv_flags: %hX.\n",
++                             __FUNCTION__, dev->name, dev->priv_flags);
++                      dev_put(dev);
++              }
++      } else {
++              printk(KERN_ERR  "%s: Could not find device: %s\n",
++                      __FUNCTION__, dev_name);
++      }
++
+       return -EINVAL;
  }
  
- static __inline__ void frag_free_queue(struct ipq *qp, int *work)
+-void vlan_dev_get_realdev_name(const struct net_device *dev, char *result)
++
++int vlan_dev_get_realdev_name(const char *dev_name, char* result)
  {
-+      struct net *net = qp->net;
-       if (work)
-               *work -= sizeof(struct ipq);
--      atomic_sub(sizeof(struct ipq), &ip_frag_mem);
-+      atomic_sub(sizeof(struct ipq), &net->ip_frag_mem);
-+      release_net(net);
-       kfree(qp);
++      struct net_device *dev = dev_get_by_name(dev_name);
++      int rv = 0;
++      if (dev) {
++              if (dev->priv_flags & IFF_802_1Q_VLAN) {
+                       strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
++                      rv = 0;
++              } else {
++                      rv = -EINVAL;
++              }
++              dev_put(dev);
++      } else {
++              rv = -ENODEV;
++      }
++      return rv;
  }
  
--static __inline__ struct ipq *frag_alloc_queue(void)
-+static __inline__ struct ipq *frag_alloc_queue(struct net *net)
+-void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result)
++int vlan_dev_get_vid(const char *dev_name, unsigned short* result)
  {
-       struct ipq *qp = kmalloc(sizeof(struct ipq), GFP_ATOMIC);
-       if (!qp)
-               return NULL;
--      atomic_add(sizeof(struct ipq), &ip_frag_mem);
-+      atomic_add(sizeof(struct ipq), &net->ip_frag_mem);
-       return qp;
++      struct net_device *dev = dev_get_by_name(dev_name);
++      int rv = 0;
++      if (dev) {
++              if (dev->priv_flags & IFF_802_1Q_VLAN) {
+                       *result = VLAN_DEV_INFO(dev)->vlan_id;
++                      rv = 0;
++              } else {
++                      rv = -EINVAL;
++              }
++              dev_put(dev);
++      } else {
++              rv = -ENODEV;
++      }
++      return rv;
  }
  
-@@ -209,7 +192,7 @@
-       while (fp) {
-               struct sk_buff *xp = fp->next;
++
+ int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
+ {
+       struct sockaddr *addr = (struct sockaddr *)(addr_struct_p);
+@@ -781,7 +828,7 @@
+               break;
  
--              frag_kfree_skb(fp, work);
-+              frag_kfree_skb(qp->net, fp, work);
-               fp = xp;
+       case SIOCETHTOOL:
+-              err = dev_ethtool(real_dev->nd_net, &ifrr);
++              err = dev_ethtool(&ifrr);
        }
  
-@@ -241,23 +224,23 @@
- /* Memory limiting on fragments.  Evictor trashes the oldest
-  * fragment queue until we are back under the threshold.
-  */
--static void ip_evictor(void)
-+static void ip_evictor(struct net *net)
- {
-       struct ipq *qp;
-       struct list_head *tmp;
-       int work;
+       if (!err)
+diff -Nurb linux-2.6.22-590/net/8021q/vlan_netlink.c linux-2.6.22-570/net/8021q/vlan_netlink.c
+--- linux-2.6.22-590/net/8021q/vlan_netlink.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/8021q/vlan_netlink.c  1969-12-31 19:00:00.000000000 -0500
+@@ -1,237 +0,0 @@
+-/*
+- *    VLAN netlink control interface
+- *
+- *    Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
+- *
+- *    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/netdevice.h>
+-#include <linux/if_vlan.h>
+-#include <net/net_namespace.h>
+-#include <net/netlink.h>
+-#include <net/rtnetlink.h>
+-#include "vlan.h"
+-
+-
+-static const struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = {
+-      [IFLA_VLAN_ID]          = { .type = NLA_U16 },
+-      [IFLA_VLAN_FLAGS]       = { .len = sizeof(struct ifla_vlan_flags) },
+-      [IFLA_VLAN_EGRESS_QOS]  = { .type = NLA_NESTED },
+-      [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED },
+-};
+-
+-static const struct nla_policy vlan_map_policy[IFLA_VLAN_QOS_MAX + 1] = {
+-      [IFLA_VLAN_QOS_MAPPING] = { .len = sizeof(struct ifla_vlan_qos_mapping) },
+-};
+-
+-
+-static inline int vlan_validate_qos_map(struct nlattr *attr)
+-{
+-      if (!attr)
+-              return 0;
+-      return nla_validate_nested(attr, IFLA_VLAN_QOS_MAX, vlan_map_policy);
+-}
+-
+-static int vlan_validate(struct nlattr *tb[], struct nlattr *data[])
+-{
+-      struct ifla_vlan_flags *flags;
+-      u16 id;
+-      int err;
+-
+-      if (!data)
+-              return -EINVAL;
+-
+-      if (data[IFLA_VLAN_ID]) {
+-              id = nla_get_u16(data[IFLA_VLAN_ID]);
+-              if (id >= VLAN_VID_MASK)
+-                      return -ERANGE;
+-      }
+-      if (data[IFLA_VLAN_FLAGS]) {
+-              flags = nla_data(data[IFLA_VLAN_FLAGS]);
+-              if ((flags->flags & flags->mask) & ~VLAN_FLAG_REORDER_HDR)
+-                      return -EINVAL;
+-      }
+-
+-      err = vlan_validate_qos_map(data[IFLA_VLAN_INGRESS_QOS]);
+-      if (err < 0)
+-              return err;
+-      err = vlan_validate_qos_map(data[IFLA_VLAN_EGRESS_QOS]);
+-      if (err < 0)
+-              return err;
+-      return 0;
+-}
+-
+-static int vlan_changelink(struct net_device *dev,
+-                         struct nlattr *tb[], struct nlattr *data[])
+-{
+-      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+-      struct ifla_vlan_flags *flags;
+-      struct ifla_vlan_qos_mapping *m;
+-      struct nlattr *attr;
+-      int rem;
+-
+-      if (data[IFLA_VLAN_FLAGS]) {
+-              flags = nla_data(data[IFLA_VLAN_FLAGS]);
+-              vlan->flags = (vlan->flags & ~flags->mask) |
+-                            (flags->flags & flags->mask);
+-      }
+-      if (data[IFLA_VLAN_INGRESS_QOS]) {
+-              nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
+-                      m = nla_data(attr);
+-                      vlan_dev_set_ingress_priority(dev, m->to, m->from);
+-              }
+-      }
+-      if (data[IFLA_VLAN_EGRESS_QOS]) {
+-              nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
+-                      m = nla_data(attr);
+-                      vlan_dev_set_egress_priority(dev, m->from, m->to);
+-              }
+-      }
+-      return 0;
+-}
+-
+-static int vlan_newlink(struct net_device *dev,
+-                      struct nlattr *tb[], struct nlattr *data[])
+-{
+-      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+-      struct net_device *real_dev;
+-      int err;
+-
+-      if (!data[IFLA_VLAN_ID])
+-              return -EINVAL;
+-
+-      if (!tb[IFLA_LINK])
+-              return -EINVAL;
+-      real_dev = __dev_get_by_index(&init_net, nla_get_u32(tb[IFLA_LINK]));
+-      if (!real_dev)
+-              return -ENODEV;
+-
+-      vlan->vlan_id  = nla_get_u16(data[IFLA_VLAN_ID]);
+-      vlan->real_dev = real_dev;
+-      vlan->flags    = VLAN_FLAG_REORDER_HDR;
+-
+-      err = vlan_check_real_dev(real_dev, vlan->vlan_id);
+-      if (err < 0)
+-              return err;
+-
+-      if (!tb[IFLA_MTU])
+-              dev->mtu = real_dev->mtu;
+-      else if (dev->mtu > real_dev->mtu)
+-              return -EINVAL;
+-
+-      err = vlan_changelink(dev, tb, data);
+-      if (err < 0)
+-              return err;
+-
+-      return register_vlan_dev(dev);
+-}
+-
+-static void vlan_dellink(struct net_device *dev)
+-{
+-      unregister_vlan_device(dev);
+-}
+-
+-static inline size_t vlan_qos_map_size(unsigned int n)
+-{
+-      if (n == 0)
+-              return 0;
+-      /* IFLA_VLAN_{EGRESS,INGRESS}_QOS + n * IFLA_VLAN_QOS_MAPPING */
+-      return nla_total_size(sizeof(struct nlattr)) +
+-             nla_total_size(sizeof(struct ifla_vlan_qos_mapping)) * n;
+-}
+-
+-static size_t vlan_get_size(const struct net_device *dev)
+-{
+-      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+-
+-      return nla_total_size(2) +      /* IFLA_VLAN_ID */
+-             vlan_qos_map_size(vlan->nr_ingress_mappings) +
+-             vlan_qos_map_size(vlan->nr_egress_mappings);
+-}
+-
+-static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
+-{
+-      struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+-      struct vlan_priority_tci_mapping *pm;
+-      struct ifla_vlan_flags f;
+-      struct ifla_vlan_qos_mapping m;
+-      struct nlattr *nest;
+-      unsigned int i;
+-
+-      NLA_PUT_U16(skb, IFLA_VLAN_ID, VLAN_DEV_INFO(dev)->vlan_id);
+-      if (vlan->flags) {
+-              f.flags = vlan->flags;
+-              f.mask  = ~0;
+-              NLA_PUT(skb, IFLA_VLAN_FLAGS, sizeof(f), &f);
+-      }
+-      if (vlan->nr_ingress_mappings) {
+-              nest = nla_nest_start(skb, IFLA_VLAN_INGRESS_QOS);
+-              if (nest == NULL)
+-                      goto nla_put_failure;
+-
+-              for (i = 0; i < ARRAY_SIZE(vlan->ingress_priority_map); i++) {
+-                      if (!vlan->ingress_priority_map[i])
+-                              continue;
+-
+-                      m.from = i;
+-                      m.to   = vlan->ingress_priority_map[i];
+-                      NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING,
+-                              sizeof(m), &m);
+-              }
+-              nla_nest_end(skb, nest);
+-      }
+-
+-      if (vlan->nr_egress_mappings) {
+-              nest = nla_nest_start(skb, IFLA_VLAN_EGRESS_QOS);
+-              if (nest == NULL)
+-                      goto nla_put_failure;
+-
+-              for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) {
+-                      for (pm = vlan->egress_priority_map[i]; pm;
+-                           pm = pm->next) {
+-                              if (!pm->vlan_qos)
+-                                      continue;
+-
+-                              m.from = pm->priority;
+-                              m.to   = (pm->vlan_qos >> 13) & 0x7;
+-                              NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING,
+-                                      sizeof(m), &m);
+-                      }
+-              }
+-              nla_nest_end(skb, nest);
+-      }
+-      return 0;
+-
+-nla_put_failure:
+-      return -EMSGSIZE;
+-}
+-
+-struct rtnl_link_ops vlan_link_ops __read_mostly = {
+-      .kind           = "vlan",
+-      .maxtype        = IFLA_VLAN_MAX,
+-      .policy         = vlan_policy,
+-      .priv_size      = sizeof(struct vlan_dev_info),
+-      .setup          = vlan_setup,
+-      .validate       = vlan_validate,
+-      .newlink        = vlan_newlink,
+-      .changelink     = vlan_changelink,
+-      .dellink        = vlan_dellink,
+-      .get_size       = vlan_get_size,
+-      .fill_info      = vlan_fill_info,
+-};
+-
+-int __init vlan_netlink_init(void)
+-{
+-      return rtnl_link_register(&vlan_link_ops);
+-}
+-
+-void __exit vlan_netlink_fini(void)
+-{
+-      rtnl_link_unregister(&vlan_link_ops);
+-}
+-
+-MODULE_ALIAS_RTNL_LINK("vlan");
+diff -Nurb linux-2.6.22-590/net/8021q/vlanproc.c linux-2.6.22-570/net/8021q/vlanproc.c
+--- linux-2.6.22-590/net/8021q/vlanproc.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/8021q/vlanproc.c      2007-07-08 19:32:17.000000000 -0400
+@@ -33,7 +33,6 @@
+ #include <linux/fs.h>
+ #include <linux/netdevice.h>
+ #include <linux/if_vlan.h>
+-#include <net/net_namespace.h>
+ #include "vlanproc.h"
+ #include "vlan.h"
  
--      work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh;
-+      work = atomic_read(&net->ip_frag_mem) - net->sysctl_ipfrag_low_thresh;
-       if (work <= 0)
-               return;
+@@ -144,7 +143,7 @@
+               remove_proc_entry(name_conf, proc_vlan_dir);
  
-       while (work > 0) {
-               read_lock(&ipfrag_lock);
--              if (list_empty(&ipq_lru_list)) {
-+              if (list_empty(&net->ipq_lru_list)) {
-                       read_unlock(&ipfrag_lock);
-                       return;
-               }
--              tmp = ipq_lru_list.next;
-+              tmp = net->ipq_lru_list.next;
-               qp = list_entry(tmp, struct ipq, lru_list);
-               atomic_inc(&qp->refcnt);
-               read_unlock(&ipfrag_lock);
-@@ -292,7 +275,7 @@
-       if ((qp->last_in&FIRST_IN) && qp->fragments != NULL) {
-               struct sk_buff *head = qp->fragments;
-               /* Send an ICMP "Fragment Reassembly Timeout" message. */
--              if ((head->dev = dev_get_by_index(qp->iif)) != NULL) {
-+              if ((head->dev = dev_get_by_index(qp->net, qp->iif)) != NULL) {
-                       icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
-                       dev_put(head->dev);
-               }
-@@ -304,7 +287,7 @@
+       if (proc_vlan_dir)
+-              proc_net_remove(&init_net, name_root);
++              proc_net_remove(name_root);
  
- /* Creation primitives. */
+       /* Dynamically added entries should be cleaned up as their vlan_device
+        * is removed, so we should not have to take care of it here...
+@@ -157,7 +156,7 @@
  
--static struct ipq *ip_frag_intern(struct ipq *qp_in)
-+static struct ipq *ip_frag_intern(struct net *net, struct ipq *qp_in)
+ int __init vlan_proc_init(void)
  {
-       struct ipq *qp;
- #ifdef CONFIG_SMP
-@@ -313,14 +296,14 @@
-       unsigned int hash;
-       write_lock(&ipfrag_lock);
--      hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
-+      hash = ipqhashfn(net, qp_in->id, qp_in->saddr, qp_in->daddr,
-                        qp_in->protocol);
- #ifdef CONFIG_SMP
-       /* With SMP race we have to recheck hash table, because
-        * such entry could be created on other cpu, while we
-        * promoted read lock to write lock.
-        */
--      hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
-+      hlist_for_each_entry(qp, n, &net->ipq_hash[hash], list) {
-               if (qp->id == qp_in->id         &&
-                   qp->saddr == qp_in->saddr   &&
-                   qp->daddr == qp_in->daddr   &&
-@@ -336,26 +319,27 @@
- #endif
-       qp = qp_in;
+-      proc_vlan_dir = proc_mkdir(name_root, init_net.proc_net);
++      proc_vlan_dir = proc_mkdir(name_root, proc_net);
+       if (proc_vlan_dir) {
+               proc_vlan_conf = create_proc_entry(name_conf,
+                                                  S_IFREG|S_IRUSR|S_IWUSR,
+@@ -254,7 +253,7 @@
+       if (*pos == 0)
+               return SEQ_START_TOKEN;
  
--      if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time))
-+      if (!mod_timer(&qp->timer, jiffies + net->sysctl_ipfrag_time))
-               atomic_inc(&qp->refcnt);
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if (!is_vlan_dev(dev))
+                       continue;
  
-       atomic_inc(&qp->refcnt);
--      hlist_add_head(&qp->list, &ipq_hash[hash]);
-+      hlist_add_head(&qp->list, &net->ipq_hash[hash]);
-       INIT_LIST_HEAD(&qp->lru_list);
--      list_add_tail(&qp->lru_list, &ipq_lru_list);
--      ip_frag_nqueues++;
-+      list_add_tail(&qp->lru_list, &net->ipq_lru_list);
-+      net->ip_frag_nqueues++;
-       write_unlock(&ipfrag_lock);
-       return qp;
- }
+@@ -273,9 +272,9 @@
  
- /* Add an entry to the 'ipq' queue for a newly received IP datagram. */
--static struct ipq *ip_frag_create(struct iphdr *iph, u32 user)
-+static struct ipq *ip_frag_create(struct net *net, struct iphdr *iph, u32 user)
- {
-       struct ipq *qp;
+       dev = (struct net_device *)v;
+       if (v == SEQ_START_TOKEN)
+-              dev = net_device_entry(&init_net.dev_base_head);
++              dev = net_device_entry(&dev_base_head);
  
--      if ((qp = frag_alloc_queue()) == NULL)
-+      if ((qp = frag_alloc_queue(net)) == NULL)
-               goto out_nomem;
+-      for_each_netdev_continue(&init_net, dev) {
++      for_each_netdev_continue(dev) {
+               if (!is_vlan_dev(dev))
+                       continue;
  
-+      qp->net = hold_net(net);
-       qp->protocol = iph->protocol;
-       qp->last_in = 0;
-       qp->id = iph->id;
-@@ -366,7 +350,8 @@
-       qp->meat = 0;
-       qp->fragments = NULL;
-       qp->iif = 0;
--      qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL;
-+      qp->peer = net->sysctl_ipfrag_max_dist ?
-+              inet_getpeer(net, iph->saddr, 1) : NULL;
+@@ -343,7 +342,7 @@
+       seq_printf(seq, "Device: %s", dev_info->real_dev->name);
+       /* now show all PRIORITY mappings relating to this VLAN */
+       seq_printf(seq,
+-                     "\nINGRESS priority mappings: 0:%u  1:%u  2:%u  3:%u  4:%u  5:%u  6:%u 7:%u\n",
++                     "\nINGRESS priority mappings: 0:%lu  1:%lu  2:%lu  3:%lu  4:%lu  5:%lu  6:%lu 7:%lu\n",
+                      dev_info->ingress_priority_map[0],
+                      dev_info->ingress_priority_map[1],
+                      dev_info->ingress_priority_map[2],
+@@ -358,7 +357,7 @@
+               const struct vlan_priority_tci_mapping *mp
+                       = dev_info->egress_priority_map[i];
+               while (mp) {
+-                      seq_printf(seq, "%u:%hu ",
++                      seq_printf(seq, "%lu:%hu ",
+                                  mp->priority, ((mp->vlan_qos >> 13) & 0x7));
+                       mp = mp->next;
+               }
+diff -Nurb linux-2.6.22-590/net/Kconfig linux-2.6.22-570/net/Kconfig
+--- linux-2.6.22-590/net/Kconfig       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/Kconfig       2007-07-08 19:32:17.000000000 -0400
+@@ -27,13 +27,6 @@
  
-       /* Initialize a timer for this entry. */
-       init_timer(&qp->timer);
-@@ -375,7 +360,7 @@
-       spin_lock_init(&qp->lock);
-       atomic_set(&qp->refcnt, 1);
+ menu "Networking options"
  
--      return ip_frag_intern(qp);
-+      return ip_frag_intern(net, qp);
+-config NET_NS
+-      bool "Network namespace support"
+-      depends on EXPERIMENTAL
+-      help
+-        Support what appear to user space as multiple instances of the 
+-        network stack.
+-
+ source "net/packet/Kconfig"
+ source "net/unix/Kconfig"
+ source "net/xfrm/Kconfig"
+diff -Nurb linux-2.6.22-590/net/Makefile linux-2.6.22-570/net/Makefile
+--- linux-2.6.22-590/net/Makefile      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/Makefile      2007-07-08 19:32:17.000000000 -0400
+@@ -14,7 +14,7 @@
  
- out_nomem:
-       LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n");
-@@ -385,7 +370,7 @@
- /* Find the correct entry in the "incomplete datagrams" queue for
-  * this IP datagram, and create new one, if nothing is found.
-  */
--static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
-+static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user)
+ # LLC has to be linked before the files in net/802/
+ obj-$(CONFIG_LLC)             += llc/
+-obj-$(CONFIG_NET)             += ethernet/ sched/ netlink/ 802/
++obj-$(CONFIG_NET)             += ethernet/ 802/ sched/ netlink/
+ obj-$(CONFIG_NETFILTER)               += netfilter/
+ obj-$(CONFIG_INET)            += ipv4/
+ obj-$(CONFIG_XFRM)            += xfrm/
+diff -Nurb linux-2.6.22-590/net/appletalk/aarp.c linux-2.6.22-570/net/appletalk/aarp.c
+--- linux-2.6.22-590/net/appletalk/aarp.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/appletalk/aarp.c      2007-07-08 19:32:17.000000000 -0400
+@@ -330,19 +330,15 @@
+ static int aarp_device_event(struct notifier_block *this, unsigned long event,
+                            void *ptr)
  {
-       __be16 id = iph->id;
-       __be32 saddr = iph->saddr;
-@@ -396,8 +381,8 @@
-       struct hlist_node *n;
+-      struct net_device *dev = ptr;
+       int ct;
  
-       read_lock(&ipfrag_lock);
--      hash = ipqhashfn(id, saddr, daddr, protocol);
--      hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
-+      hash = ipqhashfn(net, id, saddr, daddr, protocol);
-+      hlist_for_each_entry(qp, n, &net->ipq_hash[hash], list) {
-               if (qp->id == id                &&
-                   qp->saddr == saddr  &&
-                   qp->daddr == daddr  &&
-@@ -410,14 +395,14 @@
-       }
-       read_unlock(&ipfrag_lock);
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       if (event == NETDEV_DOWN) {
+               write_lock_bh(&aarp_lock);
  
--      return ip_frag_create(iph, user);
-+      return ip_frag_create(net, iph, user);
- }
+               for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
+-                      __aarp_expire_device(&resolved[ct], dev);
+-                      __aarp_expire_device(&unresolved[ct], dev);
+-                      __aarp_expire_device(&proxies[ct], dev);
++                      __aarp_expire_device(&resolved[ct], ptr);
++                      __aarp_expire_device(&unresolved[ct], ptr);
++                      __aarp_expire_device(&proxies[ct], ptr);
+               }
  
- /* Is the fragment too far ahead to be part of ipq? */
- static inline int ip_frag_too_far(struct ipq *qp)
- {
-       struct inet_peer *peer = qp->peer;
--      unsigned int max = sysctl_ipfrag_max_dist;
-+      unsigned int max = qp->net->sysctl_ipfrag_max_dist;
-       unsigned int start, end;
+               write_unlock_bh(&aarp_lock);
+@@ -716,9 +712,6 @@
+       struct atalk_addr sa, *ma, da;
+       struct atalk_iface *ifa;
  
-       int rc;
-@@ -442,7 +427,7 @@
- {
-       struct sk_buff *fp;
+-      if (dev->nd_net != &init_net)
+-              goto out0;
+-
+       /* We only do Ethernet SNAP AARP. */
+       if (dev->type != ARPHRD_ETHER)
+               goto out0;
+diff -Nurb linux-2.6.22-590/net/appletalk/atalk_proc.c linux-2.6.22-570/net/appletalk/atalk_proc.c
+--- linux-2.6.22-590/net/appletalk/atalk_proc.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/appletalk/atalk_proc.c        2007-07-08 19:32:17.000000000 -0400
+@@ -13,7 +13,6 @@
+ #include <linux/seq_file.h>
+ #include <net/sock.h>
+ #include <linux/atalk.h>
+-#include <net/net_namespace.h>
  
--      if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time)) {
-+      if (!mod_timer(&qp->timer, jiffies + qp->net->sysctl_ipfrag_time)) {
-               atomic_inc(&qp->refcnt);
-               return -ETIMEDOUT;
-       }
-@@ -450,7 +435,7 @@
-       fp = qp->fragments;
-       do {
-               struct sk_buff *xp = fp->next;
--              frag_kfree_skb(fp, NULL);
-+              frag_kfree_skb(qp->net, fp, NULL);
-               fp = xp;
-       } while (fp);
  
-@@ -466,6 +451,7 @@
- /* Add new segment to existing queue. */
- static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
- {
-+      struct net *net = qp->net;
-       struct sk_buff *prev, *next;
-       int flags, offset;
-       int ihl, end;
-@@ -576,7 +562,7 @@
-                               qp->fragments = next;
+ static __inline__ struct atalk_iface *atalk_get_interface_idx(loff_t pos)
+@@ -272,7 +271,7 @@
+       struct proc_dir_entry *p;
+       int rc = -ENOMEM;
  
-                       qp->meat -= free_it->len;
--                      frag_kfree_skb(free_it, NULL);
-+                      frag_kfree_skb(net, free_it, NULL);
-               }
-       }
+-      atalk_proc_dir = proc_mkdir("atalk", init_net.proc_net);
++      atalk_proc_dir = proc_mkdir("atalk", proc_net);
+       if (!atalk_proc_dir)
+               goto out;
+       atalk_proc_dir->owner = THIS_MODULE;
+@@ -307,7 +306,7 @@
+ out_route:
+       remove_proc_entry("interface", atalk_proc_dir);
+ out_interface:
+-      remove_proc_entry("atalk", init_net.proc_net);
++      remove_proc_entry("atalk", proc_net);
+       goto out;
+ }
  
-@@ -594,12 +580,12 @@
-       skb->dev = NULL;
-       qp->stamp = skb->tstamp;
-       qp->meat += skb->len;
--      atomic_add(skb->truesize, &ip_frag_mem);
-+      atomic_add(skb->truesize, &net->ip_frag_mem);
-       if (offset == 0)
-               qp->last_in |= FIRST_IN;
+@@ -317,5 +316,5 @@
+       remove_proc_entry("route", atalk_proc_dir);
+       remove_proc_entry("socket", atalk_proc_dir);
+       remove_proc_entry("arp", atalk_proc_dir);
+-      remove_proc_entry("atalk", init_net.proc_net);
++      remove_proc_entry("atalk", proc_net);
+ }
+diff -Nurb linux-2.6.22-590/net/appletalk/ddp.c linux-2.6.22-570/net/appletalk/ddp.c
+--- linux-2.6.22-590/net/appletalk/ddp.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/appletalk/ddp.c       2007-07-08 19:32:17.000000000 -0400
+@@ -647,14 +647,9 @@
+ static int ddp_device_event(struct notifier_block *this, unsigned long event,
+                           void *ptr)
+ {
+-      struct net_device *dev = ptr;
+-
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       if (event == NETDEV_DOWN)
+               /* Discard any use of this */
+-              atalk_dev_down(dev);
++              atalk_dev_down(ptr);
  
-       write_lock(&ipfrag_lock);
--      list_move_tail(&qp->lru_list, &ipq_lru_list);
-+      list_move_tail(&qp->lru_list, &net->ipq_lru_list);
-       write_unlock(&ipfrag_lock);
+       return NOTIFY_DONE;
+ }
+@@ -677,7 +672,7 @@
+       if (copy_from_user(&atreq, arg, sizeof(atreq)))
+               return -EFAULT;
  
-       return;
-@@ -613,6 +599,7 @@
+-      dev = __dev_get_by_name(&init_net, atreq.ifr_name);
++      dev = __dev_get_by_name(atreq.ifr_name);
+       if (!dev)
+               return -ENODEV;
  
- static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
+@@ -901,7 +896,7 @@
+                               if (copy_from_user(name, rt.rt_dev, IFNAMSIZ-1))
+                                       return -EFAULT;
+                               name[IFNAMSIZ-1] = '\0';
+-                              dev = __dev_get_by_name(&init_net, name);
++                              dev = __dev_get_by_name(name);
+                               if (!dev)
+                                       return -ENODEV;
+                       }
+@@ -1029,14 +1024,11 @@
+  * Create a socket. Initialise the socket, blank the addresses
+  * set the state.
+  */
+-static int atalk_create(struct net *net, struct socket *sock, int protocol)
++static int atalk_create(struct socket *sock, int protocol)
  {
-+      struct net *net = qp->net;
-       struct iphdr *iph;
-       struct sk_buff *fp, *head = qp->fragments;
-       int len;
-@@ -654,12 +641,12 @@
-               head->len -= clone->len;
-               clone->csum = 0;
-               clone->ip_summed = head->ip_summed;
--              atomic_add(clone->truesize, &ip_frag_mem);
-+              atomic_add(clone->truesize, &net->ip_frag_mem);
-       }
-       skb_shinfo(head)->frag_list = head->next;
-       skb_push(head, head->data - skb_network_header(head));
--      atomic_sub(head->truesize, &ip_frag_mem);
-+      atomic_sub(head->truesize, &net->ip_frag_mem);
+       struct sock *sk;
+       int rc = -ESOCKTNOSUPPORT;
  
-       for (fp=head->next; fp; fp = fp->next) {
-               head->data_len += fp->len;
-@@ -669,7 +656,7 @@
-               else if (head->ip_summed == CHECKSUM_COMPLETE)
-                       head->csum = csum_add(head->csum, fp->csum);
-               head->truesize += fp->truesize;
--              atomic_sub(fp->truesize, &ip_frag_mem);
-+              atomic_sub(fp->truesize, &net->ip_frag_mem);
-       }
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
+-
+       /*
+        * We permit SOCK_DGRAM and RAW is an extension. It is trivial to do
+        * and gives you the full ELAP frame. Should be handy for CAP 8)
+@@ -1044,7 +1036,7 @@
+       if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
+               goto out;
+       rc = -ENOMEM;
+-      sk = sk_alloc(net, PF_APPLETALK, GFP_KERNEL, &ddp_proto, 1);
++      sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, &ddp_proto, 1);
+       if (!sk)
+               goto out;
+       rc = 0;
+@@ -1273,7 +1265,7 @@
  
-       head->next = NULL;
-@@ -700,19 +687,20 @@
- /* Process an incoming IP datagram fragment. */
- struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
+ static int handle_ip_over_ddp(struct sk_buff *skb)
  {
-+      struct net *net = skb->dev->nd_net;
-       struct ipq *qp;
-       struct net_device *dev;
-       IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS);
+-      struct net_device *dev = __dev_get_by_name(&init_net, "ipddp0");
++      struct net_device *dev = __dev_get_by_name("ipddp0");
+       struct net_device_stats *stats;
  
-       /* Start by cleaning up the memory. */
--      if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh)
--              ip_evictor();
-+      if (atomic_read(&net->ip_frag_mem) > net->sysctl_ipfrag_high_thresh)
-+              ip_evictor(net);
+       /* This needs to be able to handle ipddp"N" devices */
+@@ -1406,9 +1398,6 @@
+       int origlen;
+       __u16 len_hops;
  
-       dev = skb->dev;
+-      if (dev->nd_net != &init_net)
+-              goto freeit;
+-
+       /* Don't mangle buffer if shared */
+       if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
+               goto out;
+@@ -1494,9 +1483,6 @@
+ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
+                    struct packet_type *pt, struct net_device *orig_dev)
+ {
+-      if (dev->nd_net != &init_net)
+-              goto freeit;
+-
+       /* Expand any short form frames */
+       if (skb_mac_header(skb)[2] == 1) {
+               struct ddpehdr *ddp;
+diff -Nurb linux-2.6.22-590/net/atm/clip.c linux-2.6.22-570/net/atm/clip.c
+--- linux-2.6.22-590/net/atm/clip.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/atm/clip.c    2007-07-08 19:32:17.000000000 -0400
+@@ -293,7 +293,7 @@
+       struct neigh_parms *parms;
  
-       /* Lookup (or create) queue header */
--      if ((qp = ip_find(ip_hdr(skb), user)) != NULL) {
-+      if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) {
-               struct sk_buff *ret = NULL;
+       DPRINTK("clip_constructor (neigh %p, entry %p)\n", neigh, entry);
+-      neigh->type = inet_addr_type(&init_net, entry->ip);
++      neigh->type = inet_addr_type(entry->ip);
+       if (neigh->type != RTN_UNICAST)
+               return -EINVAL;
  
-               spin_lock(&qp->lock);
-@@ -733,15 +721,70 @@
-       return NULL;
- }
+@@ -525,10 +525,7 @@
+       struct atmarp_entry *entry;
+       int error;
+       struct clip_vcc *clip_vcc;
+-      struct flowi fl = { 
+-              .fl_net = &init_net,
+-              .nl_u = { .ip4_u = { .daddr = ip, .tos = 1}} 
+-      };
++      struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1}} };
+       struct rtable *rt;
  
--void __init ipfrag_init(void)
-+static int ipfrag_net_init(struct net *net)
+       if (vcc->push != clip_push) {
+@@ -623,9 +620,6 @@
  {
--      ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
-+      struct timer_list *secret_timer;
-+      int i;
-+
-+      /* Fragment cache limits. We will commit 256K at one time. Should we
-+       * cross that limit we will prune down to 192K. This should cope with
-+       * even the most extreme cases without allowing an attacker to measurably
-+       * harm machine performance.
-+       */
-+      net->sysctl_ipfrag_high_thresh = 256*1024;
-+      net->sysctl_ipfrag_low_thresh = 192*1024;
-+      net->sysctl_ipfrag_max_dist = 64;
-+
-+      /* Important NOTE! Fragment queue must be destroyed before MSL expires.
-+       * RFC791 is wrong proposing to prolongate timer each fragment arrival by TTL.
-+       */
-+      net->sysctl_ipfrag_time = IP_FRAG_TIME;
-+
-+      net->sysctl_ipfrag_secret_interval = 10 * 60 * HZ;
-+
-+      net->ipq_hash = kzalloc(sizeof(*net->ipq_hash)*IPQ_HASHSZ, GFP_KERNEL);
-+      if (!net->ipq_hash)
-+              return -ENOMEM;
-+
-+      for (i = 0; i < IPQ_HASHSZ; i++)
-+              INIT_HLIST_HEAD(&net->ipq_hash[i]);
-+      INIT_LIST_HEAD(&net->ipq_lru_list);
-+      net->ip_frag_nqueues = 0;
-+      atomic_set(&net->ip_frag_mem, 0);
-+
-+
-+      net->ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
-                                (jiffies ^ (jiffies >> 6)));
+       struct net_device *dev = arg;
  
--      init_timer(&ipfrag_secret_timer);
--      ipfrag_secret_timer.function = ipfrag_secret_rebuild;
--      ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval;
--      add_timer(&ipfrag_secret_timer);
-+      secret_timer = &net->ipfrag_secret_timer;
-+      init_timer(secret_timer);
-+      secret_timer->function = ipfrag_secret_rebuild;
-+      secret_timer->expires = jiffies + net->sysctl_ipfrag_secret_interval;
-+      secret_timer->data = (unsigned long)net;
-+      add_timer(secret_timer);
-+
-+      return 0;
-+}
-+
-+static void ipfrag_net_exit(struct net *net)
-+{
-+      del_timer(&net->ipfrag_secret_timer);
-+
-+      net->sysctl_ipfrag_low_thresh = 0;
-+      while (atomic_read(&net->ip_frag_mem))
-+              ip_evictor(net);
-+
-+      kfree(net->ipq_hash);
-+}
-+
-+static struct pernet_operations ipfrag_net_ops = {
-+      .init = ipfrag_net_init,
-+      .exit = ipfrag_net_exit,
-+};
-+
-+void ipfrag_init(void)
-+{
-+      register_pernet_subsys(&ipfrag_net_ops);
- }
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       if (event == NETDEV_UNREGISTER) {
+               neigh_ifdown(&clip_tbl, dev);
+               return NOTIFY_DONE;
+@@ -960,7 +954,6 @@
  
- EXPORT_SYMBOL(ip_defrag);
-diff -Nurb linux-2.6.22-570/net/ipv4/ip_gre.c linux-2.6.22-590/net/ipv4/ip_gre.c
---- linux-2.6.22-570/net/ipv4/ip_gre.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ip_gre.c 2008-01-02 13:56:38.000000000 -0500
-@@ -262,7 +262,7 @@
-               int i;
-               for (i=1; i<100; i++) {
-                       sprintf(name, "gre%d", i);
--                      if (__dev_get_by_name(name) == NULL)
-+                      if (__dev_get_by_name(&init_net, name) == NULL)
-                               break;
-               }
-               if (i==100)
-@@ -397,6 +397,9 @@
-       struct flowi fl;
-       struct rtable *rt;
+       seq = file->private_data;
+       seq->private = state;
+-      state->ns.net = get_net(PROC_NET(inode));
+ out:
+       return rc;
  
-+      if (skb->dev->nd_net != &init_net)
-+              return;
-+
-       if (p[1] != htons(ETH_P_IP))
-               return;
+@@ -969,19 +962,11 @@
+       goto out;
+ }
  
-@@ -475,6 +478,7 @@
+-static int arp_seq_release(struct inode *inode, struct file *file)
+-{
+-      struct seq_file *seq = file->private_data;
+-      struct clip_seq_state *state = seq->private;
+-      put_net(state->ns.net);
+-      return seq_release_private(inode, file);
+-}
+-
+ static const struct file_operations arp_seq_fops = {
+       .open           = arp_seq_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+-      .release        = arp_seq_release,
++      .release        = seq_release_private,
+       .owner          = THIS_MODULE
+ };
+ #endif
+diff -Nurb linux-2.6.22-590/net/atm/common.c linux-2.6.22-570/net/atm/common.c
+--- linux-2.6.22-590/net/atm/common.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/atm/common.c  2007-07-08 19:32:17.000000000 -0400
+@@ -132,7 +132,7 @@
+       .obj_size = sizeof(struct atm_vcc),
+ };
  
-       /* Try to guess incoming interface */
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       fl.fl4_dst = eiph->saddr;
-       fl.fl4_tos = RT_TOS(eiph->tos);
-       fl.proto = IPPROTO_GRE;
-@@ -559,6 +563,10 @@
-       struct ip_tunnel *tunnel;
-       int    offset = 4;
+-int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
++int vcc_create(struct socket *sock, int protocol, int family)
+ {
+       struct sock *sk;
+       struct atm_vcc *vcc;
+@@ -140,7 +140,7 @@
+       sock->sk = NULL;
+       if (sock->type == SOCK_STREAM)
+               return -EINVAL;
+-      sk = sk_alloc(net, family, GFP_KERNEL, &vcc_proto, 1);
++      sk = sk_alloc(family, GFP_KERNEL, &vcc_proto, 1);
+       if (!sk)
+               return -ENOMEM;
+       sock_init_data(sock, sk);
+diff -Nurb linux-2.6.22-590/net/atm/common.h linux-2.6.22-570/net/atm/common.h
+--- linux-2.6.22-590/net/atm/common.h  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/atm/common.h  2007-07-08 19:32:17.000000000 -0400
+@@ -10,7 +10,7 @@
+ #include <linux/poll.h> /* for poll_table */
  
-+      if (skb->dev->nd_net != &init_net) {
-+              kfree_skb(skb);
-+              return 0;
-+      }
-       if (!pskb_may_pull(skb, 16))
-               goto drop_nolock;
  
-@@ -740,7 +748,8 @@
-       }
+-int vcc_create(struct net *net, struct socket *sock, int protocol, int family);
++int vcc_create(struct socket *sock, int protocol, int family);
+ int vcc_release(struct socket *sock);
+ int vcc_connect(struct socket *sock, int itf, short vpi, int vci);
+ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
+diff -Nurb linux-2.6.22-590/net/atm/mpc.c linux-2.6.22-570/net/atm/mpc.c
+--- linux-2.6.22-590/net/atm/mpc.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/atm/mpc.c     2007-07-08 19:32:17.000000000 -0400
+@@ -244,7 +244,7 @@
+       char name[IFNAMSIZ];
  
-       {
--              struct flowi fl = { .oif = tunnel->parms.link,
-+              struct flowi fl = { .fl_net = &init_net,
-+                                  .oif = tunnel->parms.link,
-                                   .nl_u = { .ip4_u =
-                                             { .daddr = dst,
-                                               .saddr = tiph->saddr,
-@@ -1095,7 +1104,8 @@
-       struct ip_tunnel *t = netdev_priv(dev);
+       sprintf(name, "lec%d", itf);
+-      dev = dev_get_by_name(&init_net, name);
++      dev = dev_get_by_name(name);
  
-       if (MULTICAST(t->parms.iph.daddr)) {
--              struct flowi fl = { .oif = t->parms.link,
-+              struct flowi fl = { .fl_net = &init_net,
-+                                  .oif = t->parms.link,
-                                   .nl_u = { .ip4_u =
-                                             { .daddr = t->parms.iph.daddr,
-                                               .saddr = t->parms.iph.saddr,
-@@ -1118,7 +1128,7 @@
- {
-       struct ip_tunnel *t = netdev_priv(dev);
-       if (MULTICAST(t->parms.iph.daddr) && t->mlink) {
--              struct in_device *in_dev = inetdev_by_index(t->mlink);
-+              struct in_device *in_dev = inetdev_by_index(&init_net, t->mlink);
-               if (in_dev) {
-                       ip_mc_dec_group(in_dev, t->parms.iph.daddr);
-                       in_dev_put(in_dev);
-@@ -1168,7 +1178,8 @@
-       /* Guess output device to choose reasonable mtu and hard_header_len */
+       return dev;
+ }
+@@ -956,10 +956,6 @@
+       struct lec_priv *priv;
  
-       if (iph->daddr) {
--              struct flowi fl = { .oif = tunnel->parms.link,
-+              struct flowi fl = { .fl_net = &init_net,
-+                                  .oif = tunnel->parms.link,
-                                   .nl_u = { .ip4_u =
-                                             { .daddr = iph->daddr,
-                                               .saddr = iph->saddr,
-@@ -1195,7 +1206,7 @@
-       }
+       dev = (struct net_device *)dev_ptr;
+-
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       if (dev->name == NULL || strncmp(dev->name, "lec", 3))
+               return NOTIFY_DONE; /* we are only interested in lec:s */
  
-       if (!tdev && tunnel->parms.link)
--              tdev = __dev_get_by_index(tunnel->parms.link);
-+              tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
+diff -Nurb linux-2.6.22-590/net/atm/proc.c linux-2.6.22-570/net/atm/proc.c
+--- linux-2.6.22-590/net/atm/proc.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/atm/proc.c    2007-07-08 19:32:17.000000000 -0400
+@@ -22,7 +22,6 @@
+ #include <linux/netdevice.h>
+ #include <linux/atmclip.h>
+ #include <linux/init.h> /* for __init */
+-#include <net/net_namespace.h>
+ #include <net/atmclip.h>
+ #include <asm/uaccess.h>
+ #include <asm/atomic.h>
+@@ -476,7 +475,7 @@
+               if (e->dirent)
+                       remove_proc_entry(e->name, atm_proc_root);
+       }
+-      remove_proc_entry("atm", init_net.proc_net);
++      remove_proc_entry("net/atm", NULL);
+ }
  
-       if (tdev) {
-               hlen = tdev->hard_header_len;
-diff -Nurb linux-2.6.22-570/net/ipv4/ip_input.c linux-2.6.22-590/net/ipv4/ip_input.c
---- linux-2.6.22-570/net/ipv4/ip_input.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ip_input.c       2008-01-02 13:56:38.000000000 -0500
-@@ -280,6 +280,10 @@
-       struct iphdr *iph;
-       struct net_device *dev = skb->dev;
+ int __init atm_proc_init(void)
+@@ -484,7 +483,7 @@
+       static struct atm_proc_entry *e;
+       int ret;
  
-+
-+      if (skb->dev->nd_net != &init_net)
-+              goto drop;
-+
-       /* It looks as overkill, because not all
-          IP options require packet mangling.
-          But it is the easiest for now, especially taking
-diff -Nurb linux-2.6.22-570/net/ipv4/ip_options.c linux-2.6.22-590/net/ipv4/ip_options.c
---- linux-2.6.22-570/net/ipv4/ip_options.c     2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/ip_options.c     2008-01-02 13:56:38.000000000 -0500
-@@ -151,7 +151,7 @@
-                                               __be32 addr;
+-      atm_proc_root = proc_mkdir("atm", init_net.proc_net);
++      atm_proc_root = proc_mkdir("net/atm",NULL);
+       if (!atm_proc_root)
+               goto err_out;
+       for (e = atm_proc_ents; e->name; e++) {
+diff -Nurb linux-2.6.22-590/net/atm/pvc.c linux-2.6.22-570/net/atm/pvc.c
+--- linux-2.6.22-590/net/atm/pvc.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/atm/pvc.c     2007-07-08 19:32:17.000000000 -0400
+@@ -124,13 +124,10 @@
+ };
  
-                                               memcpy(&addr, sptr+soffset-1, 4);
--                                              if (inet_addr_type(addr) != RTN_LOCAL) {
-+                                              if (inet_addr_type(&init_net, addr) != RTN_LOCAL) {
-                                                       dopt->ts_needtime = 1;
-                                                       soffset += 8;
-                                               }
-@@ -400,7 +400,7 @@
-                                       {
-                                               __be32 addr;
-                                               memcpy(&addr, &optptr[optptr[2]-1], 4);
--                                              if (inet_addr_type(addr) == RTN_UNICAST)
-+                                              if (inet_addr_type(&init_net, addr) == RTN_UNICAST)
-                                                       break;
-                                               if (skb)
-                                                       timeptr = (__be32*)&optptr[optptr[2]+3];
-diff -Nurb linux-2.6.22-570/net/ipv4/ip_output.c linux-2.6.22-590/net/ipv4/ip_output.c
---- linux-2.6.22-570/net/ipv4/ip_output.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ip_output.c      2008-01-02 13:56:38.000000000 -0500
-@@ -83,8 +83,6 @@
- #include <linux/netlink.h>
- #include <linux/tcp.h>
  
--int sysctl_ip_default_ttl __read_mostly = IPDEFTTL;
--
- /* Generate a checksum for an outgoing IP datagram. */
- __inline__ void ip_send_check(struct iphdr *iph)
+-static int pvc_create(struct net *net, struct socket *sock,int protocol)
++static int pvc_create(struct socket *sock,int protocol)
  {
-@@ -317,7 +315,8 @@
-                       daddr = opt->faddr;
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
+-
+       sock->ops = &pvc_proto_ops;
+-      return vcc_create(net, sock, protocol, PF_ATMPVC);
++      return vcc_create(sock, protocol, PF_ATMPVC);
+ }
  
-               {
--                      struct flowi fl = { .oif = sk->sk_bound_dev_if,
-+                      struct flowi fl = { .fl_net = sk->sk_net,
-+                                          .oif = sk->sk_bound_dev_if,
-                                           .nl_u = { .ip4_u =
-                                                     { .daddr = daddr,
-                                                       .saddr = inet->saddr,
-@@ -837,7 +836,7 @@
-        */
-       if (transhdrlen &&
-           length + fragheaderlen <= mtu &&
--          rt->u.dst.dev->features & NETIF_F_ALL_CSUM &&
-+          rt->u.dst.dev->features & NETIF_F_V4_CSUM &&
-           !exthdrlen)
-               csummode = CHECKSUM_PARTIAL;
  
-@@ -1352,7 +1351,8 @@
-       }
+diff -Nurb linux-2.6.22-590/net/atm/svc.c linux-2.6.22-570/net/atm/svc.c
+--- linux-2.6.22-590/net/atm/svc.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/atm/svc.c     2007-07-08 19:32:17.000000000 -0400
+@@ -33,7 +33,7 @@
+ #endif
  
-       {
--              struct flowi fl = { .oif = arg->bound_dev_if,
-+              struct flowi fl = { .fl_net = sk->sk_net,
-+                                  .oif = arg->bound_dev_if,
-                                   .nl_u = { .ip4_u =
-                                             { .daddr = daddr,
-                                               .saddr = rt->rt_spec_dst,
-diff -Nurb linux-2.6.22-570/net/ipv4/ip_sockglue.c linux-2.6.22-590/net/ipv4/ip_sockglue.c
---- linux-2.6.22-570/net/ipv4/ip_sockglue.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ip_sockglue.c    2008-01-02 13:56:38.000000000 -0500
-@@ -411,6 +411,7 @@
- static int do_ip_setsockopt(struct sock *sk, int level,
-                           int optname, char __user *optval, int optlen)
- {
-+      struct net *net = sk->sk_net;
-       struct inet_sock *inet = inet_sk(sk);
-       int val=0,err;
  
-@@ -596,13 +597,13 @@
-                               err = 0;
-                               break;
-                       }
--                      dev = ip_dev_find(mreq.imr_address.s_addr);
-+                      dev = ip_dev_find(net, mreq.imr_address.s_addr);
-                       if (dev) {
-                               mreq.imr_ifindex = dev->ifindex;
-                               dev_put(dev);
-                       }
-               } else
--                      dev = __dev_get_by_index(mreq.imr_ifindex);
-+                      dev = __dev_get_by_index(net, mreq.imr_ifindex);
+-static int svc_create(struct net *net, struct socket *sock,int protocol);
++static int svc_create(struct socket *sock,int protocol);
  
  
-               err = -EADDRNOTAVAIL;
-@@ -956,6 +957,7 @@
- static int do_ip_getsockopt(struct sock *sk, int level, int optname,
-                           char __user *optval, int __user *optlen)
- {
-+      struct net *net = sk->sk_net;
-       struct inet_sock *inet = inet_sk(sk);
-       int val;
-       int len;
-@@ -1023,7 +1025,7 @@
-               break;
-       case IP_TTL:
-               val = (inet->uc_ttl == -1 ?
--                     sysctl_ip_default_ttl :
-+                     net->sysctl_ip_default_ttl :
-                      inet->uc_ttl);
-               break;
-       case IP_HDRINCL:
-diff -Nurb linux-2.6.22-570/net/ipv4/ipcomp.c linux-2.6.22-590/net/ipv4/ipcomp.c
---- linux-2.6.22-570/net/ipv4/ipcomp.c 2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/ipcomp.c 2008-01-02 13:56:38.000000000 -0500
-@@ -175,6 +175,9 @@
-       struct ip_comp_hdr *ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
-       struct xfrm_state *x;
+ /*
+@@ -335,7 +335,7 @@
  
-+      if (skb->dev->nd_net != &init_net)
-+              return;
-+
-       if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH ||
-           icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
-               return;
-@@ -486,3 +489,4 @@
- MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) - RFC3173");
- MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
+       lock_sock(sk);
  
-+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_COMP);
-diff -Nurb linux-2.6.22-570/net/ipv4/ipconfig.c linux-2.6.22-590/net/ipv4/ipconfig.c
---- linux-2.6.22-570/net/ipv4/ipconfig.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ipconfig.c       2008-01-02 13:56:38.000000000 -0500
-@@ -59,6 +59,7 @@
- #include <net/ip.h>
- #include <net/ipconfig.h>
- #include <net/route.h>
-+#include <net/net_namespace.h>
+-      error = svc_create(sk->sk_net, newsock,0);
++      error = svc_create(newsock,0);
+       if (error)
+               goto out;
  
- #include <asm/uaccess.h>
- #include <net/checksum.h>
-@@ -184,16 +185,18 @@
-       struct ic_device *d, **last;
-       struct net_device *dev;
-       unsigned short oflags;
-+      struct net_device *lo;
+@@ -636,15 +636,12 @@
+ };
  
-       last = &ic_first_dev;
-       rtnl_lock();
  
-       /* bring loopback device up first */
--      if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0)
--              printk(KERN_ERR "IP-Config: Failed to open %s\n", loopback_dev.name);
-+      lo = &init_net.loopback_dev;
-+      if (dev_change_flags(lo, lo->flags | IFF_UP) < 0)
-+              printk(KERN_ERR "IP-Config: Failed to open %s\n", lo->name);
--      for_each_netdev(dev) {
--              if (dev == &loopback_dev)
-+      for_each_netdev(&init_net, dev) {
-+              if (dev == lo)
-                       continue;
-               if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
-                   (!(dev->flags & IFF_LOOPBACK) &&
-@@ -283,7 +286,7 @@
+-static int svc_create(struct net *net, struct socket *sock,int protocol)
++static int svc_create(struct socket *sock,int protocol)
+ {
+       int error;
  
-       mm_segment_t oldfs = get_fs();
-       set_fs(get_ds());
--      res = devinet_ioctl(cmd, (struct ifreq __user *) arg);
-+      res = devinet_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
-       set_fs(oldfs);
-       return res;
- }
-@@ -294,7 +297,7 @@
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
+-
+       sock->ops = &svc_proto_ops;
+-      error = vcc_create(net, sock, protocol, AF_ATMSVC);
++      error = vcc_create(sock, protocol, AF_ATMSVC);
+       if (error) return error;
+       ATM_SD(sock)->local.sas_family = AF_ATMSVC;
+       ATM_SD(sock)->remote.sas_family = AF_ATMSVC;
+diff -Nurb linux-2.6.22-590/net/ax25/af_ax25.c linux-2.6.22-570/net/ax25/af_ax25.c
+--- linux-2.6.22-590/net/ax25/af_ax25.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ax25/af_ax25.c        2007-07-08 19:32:17.000000000 -0400
+@@ -47,7 +47,6 @@
+ #include <net/tcp_states.h>
+ #include <net/ip.h>
+ #include <net/arp.h>
+-#include <net/net_namespace.h>
  
-       mm_segment_t oldfs = get_fs();
-       set_fs(get_ds());
--      res = ip_rt_ioctl(cmd, (void __user *) arg);
-+      res = ip_rt_ioctl(&init_net, cmd, (void __user *) arg);
-       set_fs(oldfs);
-       return res;
- }
-@@ -425,6 +428,9 @@
-       unsigned char *sha, *tha;               /* s for "source", t for "target" */
-       struct ic_device *d;
  
-+      if (dev->nd_net != &init_net)
-+              goto drop;
-+
-       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
-               return NET_RX_DROP;
  
-@@ -834,6 +840,9 @@
-       struct ic_device *d;
-       int len, ext_len;
+@@ -104,9 +103,6 @@
+ {
+       struct net_device *dev = (struct net_device *)ptr;
  
-+      if (dev->nd_net != &init_net)
-+              goto drop;
-+
-       /* Perform verifications before taking the lock.  */
-       if (skb->pkt_type == PACKET_OTHERHOST)
-               goto drop;
-@@ -1253,7 +1262,7 @@
-       __be32 addr;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       /* Reject non AX.25 devices */
+       if (dev->type != ARPHRD_AX25)
+               return NOTIFY_DONE;
+@@ -631,7 +627,7 @@
+                       break;
+               }
  
- #ifdef CONFIG_PROC_FS
--      proc_net_fops_create("pnp", S_IRUGO, &pnp_seq_fops);
-+      proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops);
- #endif /* CONFIG_PROC_FS */
+-              dev = dev_get_by_name(&init_net, devname);
++              dev = dev_get_by_name(devname);
+               if (dev == NULL) {
+                       res = -ENODEV;
+                       break;
+@@ -783,14 +779,11 @@
+       .obj_size = sizeof(struct sock),
+ };
  
-       if (!ic_enable)
-diff -Nurb linux-2.6.22-570/net/ipv4/ipip.c linux-2.6.22-590/net/ipv4/ipip.c
---- linux-2.6.22-570/net/ipv4/ipip.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ipip.c   2008-01-02 13:56:38.000000000 -0500
-@@ -225,7 +225,7 @@
-               int i;
-               for (i=1; i<100; i++) {
-                       sprintf(name, "tunl%d", i);
--                      if (__dev_get_by_name(name) == NULL)
-+                      if (__dev_get_by_name(&init_net, name) == NULL)
-                               break;
-               }
-               if (i==100)
-@@ -403,6 +403,7 @@
+-static int ax25_create(struct net *net, struct socket *sock, int protocol)
++static int ax25_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
+       ax25_cb *ax25;
  
-       /* Try to guess incoming interface */
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       fl.fl4_daddr = eiph->saddr;
-       fl.fl4_tos = RT_TOS(eiph->tos);
-       fl.proto = IPPROTO_IPIP;
-@@ -542,7 +543,8 @@
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
+-
+       switch (sock->type) {
+       case SOCK_DGRAM:
+               if (protocol == 0 || protocol == PF_AX25)
+@@ -836,7 +829,7 @@
+               return -ESOCKTNOSUPPORT;
        }
  
-       {
--              struct flowi fl = { .oif = tunnel->parms.link,
-+              struct flowi fl = { .fl_net = &init_net,
-+                                  .oif = tunnel->parms.link,
-                                   .nl_u = { .ip4_u =
-                                             { .daddr = dst,
-                                               .saddr = tiph->saddr,
-@@ -806,7 +808,8 @@
-       memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
+-      if ((sk = sk_alloc(net, PF_AX25, GFP_ATOMIC, &ax25_proto, 1)) == NULL)
++      if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, &ax25_proto, 1)) == NULL)
+               return -ENOMEM;
  
-       if (iph->daddr) {
--              struct flowi fl = { .oif = tunnel->parms.link,
-+              struct flowi fl = { .fl_net = &init_net,
-+                                  .oif = tunnel->parms.link,
-                                   .nl_u = { .ip4_u =
-                                             { .daddr = iph->daddr,
-                                               .saddr = iph->saddr,
-@@ -821,7 +824,7 @@
-       }
+       ax25 = sk->sk_protinfo = ax25_create_cb();
+@@ -861,7 +854,7 @@
+       struct sock *sk;
+       ax25_cb *ax25, *oax25;
  
-       if (!tdev && tunnel->parms.link)
--              tdev = __dev_get_by_index(tunnel->parms.link);
-+              tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
+-      if ((sk = sk_alloc(osk->sk_net, PF_AX25, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
++      if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
+               return NULL;
  
-       if (tdev) {
-               dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
-diff -Nurb linux-2.6.22-570/net/ipv4/ipmr.c linux-2.6.22-590/net/ipv4/ipmr.c
---- linux-2.6.22-570/net/ipv4/ipmr.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ipmr.c   2008-01-02 13:56:38.000000000 -0500
-@@ -62,6 +62,7 @@
- #include <linux/netfilter_ipv4.h>
- #include <net/ipip.h>
- #include <net/checksum.h>
-+#include <net/net_namespace.h>
- #include <net/netlink.h>
+       if ((ax25 = ax25_create_cb()) == NULL) {
+@@ -2005,9 +1998,9 @@
+       register_netdevice_notifier(&ax25_dev_notifier);
+       ax25_register_sysctl();
  
- #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
-@@ -124,7 +125,7 @@
- {
-       struct net_device  *dev;
+-      proc_net_fops_create(&init_net, "ax25_route", S_IRUGO, &ax25_route_fops);
+-      proc_net_fops_create(&init_net, "ax25", S_IRUGO, &ax25_info_fops);
+-      proc_net_fops_create(&init_net, "ax25_calls", S_IRUGO, &ax25_uid_fops);
++      proc_net_fops_create("ax25_route", S_IRUGO, &ax25_route_fops);
++      proc_net_fops_create("ax25", S_IRUGO, &ax25_info_fops);
++      proc_net_fops_create("ax25_calls", S_IRUGO, &ax25_uid_fops);
+ out:
+       return rc;
+ }
+@@ -2021,9 +2014,9 @@
  
--      dev = __dev_get_by_name("tunl0");
-+      dev = __dev_get_by_name(&init_net, "tunl0");
+ static void __exit ax25_exit(void)
+ {
+-      proc_net_remove(&init_net, "ax25_route");
+-      proc_net_remove(&init_net, "ax25");
+-      proc_net_remove(&init_net, "ax25_calls");
++      proc_net_remove("ax25_route");
++      proc_net_remove("ax25");
++      proc_net_remove("ax25_calls");
+       ax25_rt_free();
+       ax25_uid_free();
+       ax25_dev_free();
+diff -Nurb linux-2.6.22-590/net/ax25/ax25_in.c linux-2.6.22-570/net/ax25/ax25_in.c
+--- linux-2.6.22-590/net/ax25/ax25_in.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ax25/ax25_in.c        2007-07-08 19:32:17.000000000 -0400
+@@ -451,11 +451,6 @@
+       skb->sk = NULL;         /* Initially we don't know who it's for */
+       skb->destructor = NULL; /* Who initializes this, dammit?! */
  
-       if (dev) {
-               int err;
-@@ -148,7 +149,7 @@
+-      if (dev->nd_net != &init_net) {
+-              kfree_skb(skb);
+-              return 0;
+-      }
+-
+       if ((*skb->data & 0x0F) != 0) {
+               kfree_skb(skb); /* Not a KISS data frame */
+               return 0;
+diff -Nurb linux-2.6.22-590/net/bluetooth/af_bluetooth.c linux-2.6.22-570/net/bluetooth/af_bluetooth.c
+--- linux-2.6.22-590/net/bluetooth/af_bluetooth.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bluetooth/af_bluetooth.c      2007-07-08 19:32:17.000000000 -0400
+@@ -95,13 +95,10 @@
+ }
+ EXPORT_SYMBOL(bt_sock_unregister);
  
-               dev = NULL;
+-static int bt_sock_create(struct net *net, struct socket *sock, int proto)
++static int bt_sock_create(struct socket *sock, int proto)
+ {
+       int err;
  
--              if (err == 0 && (dev = __dev_get_by_name(p.name)) != NULL) {
-+              if (err == 0 && (dev = __dev_get_by_name(&init_net, p.name)) != NULL) {
-                       dev->flags |= IFF_MULTICAST;
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
+-
+       if (proto < 0 || proto >= BT_MAX_PROTO)
+               return -EINVAL;
  
-                       in_dev = __in_dev_get_rtnl(dev);
-@@ -320,7 +321,7 @@
-                       e->error = -ETIMEDOUT;
-                       memset(&e->msg, 0, sizeof(e->msg));
+@@ -116,7 +113,7 @@
+       read_lock(&bt_proto_lock);
  
--                      rtnl_unicast(skb, NETLINK_CB(skb).pid);
-+                      rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
-               } else
-                       kfree_skb(skb);
+       if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
+-              err = bt_proto[proto]->create(net, sock, proto);
++              err = bt_proto[proto]->create(sock, proto);
+               module_put(bt_proto[proto]->owner);
        }
-@@ -422,7 +423,7 @@
-                       return -ENOBUFS;
-               break;
-       case 0:
--              dev = ip_dev_find(vifc->vifc_lcl_addr.s_addr);
-+              dev = ip_dev_find(&init_net, vifc->vifc_lcl_addr.s_addr);
-               if (!dev)
-                       return -EADDRNOTAVAIL;
-               dev_put(dev);
-@@ -532,7 +533,7 @@
-                               memset(&e->msg, 0, sizeof(e->msg));
-                       }
  
--                      rtnl_unicast(skb, NETLINK_CB(skb).pid);
-+                      rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
-               } else
-                       ip_mr_forward(skb, c, 0);
-       }
-@@ -848,7 +849,7 @@
- {
-       rtnl_lock();
-       if (sk == mroute_socket) {
--              IPV4_DEVCONF_ALL(MC_FORWARDING)--;
-+              IPV4_DEVCONF_ALL(sk->sk_net, MC_FORWARDING)--;
+diff -Nurb linux-2.6.22-590/net/bluetooth/bnep/core.c linux-2.6.22-570/net/bluetooth/bnep/core.c
+--- linux-2.6.22-590/net/bluetooth/bnep/core.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bluetooth/bnep/core.c 2007-07-08 19:32:17.000000000 -0400
+@@ -36,7 +36,6 @@
+ #include <linux/signal.h>
+ #include <linux/init.h>
+ #include <linux/wait.h>
+-#include <linux/freezer.h>
+ #include <linux/errno.h>
+ #include <linux/net.h>
+ #include <net/sock.h>
+@@ -475,6 +474,7 @@
  
-               write_lock_bh(&mrt_lock);
-               mroute_socket=NULL;
-@@ -897,7 +898,7 @@
-                       mroute_socket=sk;
-                       write_unlock_bh(&mrt_lock);
+       daemonize("kbnepd %s", dev->name);
+       set_user_nice(current, -15);
++      current->flags |= PF_NOFREEZE;
  
--                      IPV4_DEVCONF_ALL(MC_FORWARDING)++;
-+                      IPV4_DEVCONF_ALL(sk->sk_net, MC_FORWARDING)++;
-               }
-               rtnl_unlock();
-               return ret;
-@@ -1082,13 +1083,18 @@
+       init_waitqueue_entry(&wait, current);
+       add_wait_queue(sk->sk_sleep, &wait);
+diff -Nurb linux-2.6.22-590/net/bluetooth/bnep/sock.c linux-2.6.22-570/net/bluetooth/bnep/sock.c
+--- linux-2.6.22-590/net/bluetooth/bnep/sock.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bluetooth/bnep/sock.c 2007-07-08 19:32:17.000000000 -0400
+@@ -204,7 +204,7 @@
+       .obj_size       = sizeof(struct bt_sock)
+ };
  
- static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
+-static int bnep_sock_create(struct net *net, struct socket *sock, int protocol)
++static int bnep_sock_create(struct socket *sock, int protocol)
  {
-+      struct net_device *dev = ptr;
-       struct vif_device *v;
-       int ct;
-+
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (event != NETDEV_UNREGISTER)
-               return NOTIFY_DONE;
-       v=&vif_table[0];
-       for (ct=0;ct<maxvif;ct++,v++) {
--              if (v->dev==ptr)
-+              if (v->dev==dev)
-                       vif_delete(ct);
-       }
-       return NOTIFY_DONE;
-@@ -1171,7 +1177,8 @@
- #endif
-       if (vif->flags&VIFF_TUNNEL) {
--              struct flowi fl = { .oif = vif->link,
-+              struct flowi fl = { .fl_net = &init_net,
-+                                  .oif = vif->link,
-                                   .nl_u = { .ip4_u =
-                                             { .daddr = vif->remote,
-                                               .saddr = vif->local,
-@@ -1181,7 +1188,8 @@
-                       goto out_free;
-               encap = sizeof(struct iphdr);
-       } else {
--              struct flowi fl = { .oif = vif->link,
-+              struct flowi fl = { .fl_net = &init_net,
-+                                  .oif = vif->link,
-                                   .nl_u = { .ip4_u =
-                                             { .daddr = iph->daddr,
-                                               .tos = RT_TOS(iph->tos) } },
-@@ -1498,6 +1506,10 @@
-       struct iphdr   *encap;
-       struct net_device  *reg_dev = NULL;
+       struct sock *sk;
  
-+      if (skb->dev->nd_net != &init_net) {
-+              kfree_skb(skb);
-+              return 0;
-+      }
-       if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
-               goto drop;
+@@ -213,7 +213,7 @@
+       if (sock->type != SOCK_RAW)
+               return -ESOCKTNOSUPPORT;
  
-@@ -1922,7 +1934,7 @@
-       ipmr_expire_timer.function=ipmr_expire_process;
-       register_netdevice_notifier(&ip_mr_notifier);
- #ifdef CONFIG_PROC_FS
--      proc_net_fops_create("ip_mr_vif", 0, &ipmr_vif_fops);
--      proc_net_fops_create("ip_mr_cache", 0, &ipmr_mfc_fops);
-+      proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops);
-+      proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops);
- #endif
- }
-diff -Nurb linux-2.6.22-570/net/ipv4/ipvs/ip_vs_app.c linux-2.6.22-590/net/ipv4/ipvs/ip_vs_app.c
---- linux-2.6.22-570/net/ipv4/ipvs/ip_vs_app.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ipvs/ip_vs_app.c 2008-01-02 13:56:38.000000000 -0500
-@@ -32,6 +32,7 @@
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/mutex.h>
-+#include <net/net_namespace.h>
+-      sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
++      sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
+       if (!sk)
+               return -ENOMEM;
  
- #include <net/ip_vs.h>
+diff -Nurb linux-2.6.22-590/net/bluetooth/cmtp/core.c linux-2.6.22-570/net/bluetooth/cmtp/core.c
+--- linux-2.6.22-590/net/bluetooth/cmtp/core.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bluetooth/cmtp/core.c 2007-07-08 19:32:17.000000000 -0400
+@@ -29,7 +29,6 @@
+ #include <linux/slab.h>
+ #include <linux/poll.h>
+ #include <linux/fcntl.h>
+-#include <linux/freezer.h>
+ #include <linux/skbuff.h>
+ #include <linux/socket.h>
+ #include <linux/ioctl.h>
+@@ -288,6 +287,7 @@
  
-@@ -616,12 +617,12 @@
- int ip_vs_app_init(void)
- {
-       /* we will replace it with proc_net_ipvs_create() soon */
--      proc_net_fops_create("ip_vs_app", 0, &ip_vs_app_fops);
-+      proc_net_fops_create(&init_net, "ip_vs_app", 0, &ip_vs_app_fops);
-       return 0;
- }
+       daemonize("kcmtpd_ctr_%d", session->num);
+       set_user_nice(current, -15);
++      current->flags |= PF_NOFREEZE;
  
+       init_waitqueue_entry(&wait, current);
+       add_wait_queue(sk->sk_sleep, &wait);
+diff -Nurb linux-2.6.22-590/net/bluetooth/cmtp/sock.c linux-2.6.22-570/net/bluetooth/cmtp/sock.c
+--- linux-2.6.22-590/net/bluetooth/cmtp/sock.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bluetooth/cmtp/sock.c 2007-07-08 19:32:17.000000000 -0400
+@@ -195,7 +195,7 @@
+       .obj_size       = sizeof(struct bt_sock)
+ };
  
- void ip_vs_app_cleanup(void)
+-static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol)
++static int cmtp_sock_create(struct socket *sock, int protocol)
  {
--      proc_net_remove("ip_vs_app");
-+      proc_net_remove(&init_net, "ip_vs_app");
- }
-diff -Nurb linux-2.6.22-570/net/ipv4/ipvs/ip_vs_conn.c linux-2.6.22-590/net/ipv4/ipvs/ip_vs_conn.c
---- linux-2.6.22-570/net/ipv4/ipvs/ip_vs_conn.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ipvs/ip_vs_conn.c        2008-01-02 13:56:38.000000000 -0500
-@@ -34,6 +34,7 @@
- #include <linux/seq_file.h>
- #include <linux/jhash.h>
- #include <linux/random.h>
-+#include <net/net_namespace.h>
+       struct sock *sk;
  
- #include <net/ip_vs.h>
+@@ -204,7 +204,7 @@
+       if (sock->type != SOCK_RAW)
+               return -ESOCKTNOSUPPORT;
  
-@@ -922,7 +923,7 @@
-               rwlock_init(&__ip_vs_conntbl_lock_array[idx].l);
-       }
+-      sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
++      sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
+       if (!sk)
+               return -ENOMEM;
  
--      proc_net_fops_create("ip_vs_conn", 0, &ip_vs_conn_fops);
-+      proc_net_fops_create(&init_net, "ip_vs_conn", 0, &ip_vs_conn_fops);
+diff -Nurb linux-2.6.22-590/net/bluetooth/hci_sock.c linux-2.6.22-570/net/bluetooth/hci_sock.c
+--- linux-2.6.22-590/net/bluetooth/hci_sock.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bluetooth/hci_sock.c  2007-07-08 19:32:17.000000000 -0400
+@@ -618,7 +618,7 @@
+       .obj_size       = sizeof(struct hci_pinfo)
+ };
  
-       /* calculate the random value for connection hash */
-       get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd));
-@@ -938,6 +939,6 @@
+-static int hci_sock_create(struct net *net, struct socket *sock, int protocol)
++static int hci_sock_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
  
-       /* Release the empty cache */
-       kmem_cache_destroy(ip_vs_conn_cachep);
--      proc_net_remove("ip_vs_conn");
-+      proc_net_remove(&init_net, "ip_vs_conn");
-       vfree(ip_vs_conn_tab);
- }
-diff -Nurb linux-2.6.22-570/net/ipv4/ipvs/ip_vs_core.c linux-2.6.22-590/net/ipv4/ipvs/ip_vs_core.c
---- linux-2.6.22-570/net/ipv4/ipvs/ip_vs_core.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ipvs/ip_vs_core.c        2008-01-02 13:56:38.000000000 -0500
-@@ -460,7 +460,7 @@
-          and the destination is RTN_UNICAST (and not local), then create
-          a cache_bypass connection entry */
-       if (sysctl_ip_vs_cache_bypass && svc->fwmark
--          && (inet_addr_type(iph->daddr) == RTN_UNICAST)) {
-+          && (inet_addr_type(&init_net, iph->daddr) == RTN_UNICAST)) {
-               int ret, cs;
-               struct ip_vs_conn *cp;
+@@ -629,7 +629,7 @@
  
-@@ -530,6 +530,10 @@
-                                      const struct net_device *out,
-                                      int (*okfn)(struct sk_buff *))
- {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       if (!((*pskb)->ipvs_property))
-               return NF_ACCEPT;
-       /* The packet was sent from IPVS, exit this chain */
-@@ -734,6 +738,10 @@
-       struct ip_vs_conn *cp;
-       int ihl;
+       sock->ops = &hci_sock_ops;
  
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       EnterFunction(11);
+-      sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
++      sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
+       if (!sk)
+               return -ENOMEM;
  
-       if (skb->ipvs_property)
-@@ -818,7 +826,7 @@
-        * if it came from this machine itself.  So re-compute
-        * the routing information.
-        */
--      if (ip_route_me_harder(pskb, RTN_LOCAL) != 0)
-+      if (ip_route_me_harder(&init_net, pskb, RTN_LOCAL) != 0)
-               goto drop;
-       skb = *pskb;
+diff -Nurb linux-2.6.22-590/net/bluetooth/hidp/core.c linux-2.6.22-570/net/bluetooth/hidp/core.c
+--- linux-2.6.22-590/net/bluetooth/hidp/core.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bluetooth/hidp/core.c 2007-07-08 19:32:17.000000000 -0400
+@@ -28,7 +28,6 @@
+ #include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/poll.h>
+-#include <linux/freezer.h>
+ #include <linux/fcntl.h>
+ #include <linux/skbuff.h>
+ #include <linux/socket.h>
+@@ -548,6 +547,7 @@
  
-@@ -956,12 +964,16 @@
-       int ret, restart;
-       int ihl;
+       daemonize("khidpd_%04x%04x", vendor, product);
+       set_user_nice(current, -15);
++      current->flags |= PF_NOFREEZE;
+       init_waitqueue_entry(&ctrl_wait, current);
+       init_waitqueue_entry(&intr_wait, current);
+diff -Nurb linux-2.6.22-590/net/bluetooth/hidp/sock.c linux-2.6.22-570/net/bluetooth/hidp/sock.c
+--- linux-2.6.22-590/net/bluetooth/hidp/sock.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bluetooth/hidp/sock.c 2007-07-08 19:32:17.000000000 -0400
+@@ -246,7 +246,7 @@
+       .obj_size       = sizeof(struct bt_sock)
+ };
  
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       /*
-        *      Big tappo: only PACKET_HOST (neither loopback nor mcasts)
-        *      ... don't know why 1st test DOES NOT include 2nd (?)
-        */
-       if (unlikely(skb->pkt_type != PACKET_HOST
--                   || skb->dev == &loopback_dev || skb->sk)) {
-+                   || skb->dev == &init_net.loopback_dev || skb->sk)) {
-               IP_VS_DBG(12, "packet type=%d proto=%d daddr=%d.%d.%d.%d ignored\n",
-                         skb->pkt_type,
-                         ip_hdr(skb)->protocol,
-@@ -1062,6 +1074,10 @@
+-static int hidp_sock_create(struct net *net, struct socket *sock, int protocol)
++static int hidp_sock_create(struct socket *sock, int protocol)
  {
-       int r;
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       if (ip_hdr(*pskb)->protocol != IPPROTO_ICMP)
-               return NF_ACCEPT;
+       struct sock *sk;
  
-diff -Nurb linux-2.6.22-570/net/ipv4/ipvs/ip_vs_ctl.c linux-2.6.22-590/net/ipv4/ipvs/ip_vs_ctl.c
---- linux-2.6.22-570/net/ipv4/ipvs/ip_vs_ctl.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ipvs/ip_vs_ctl.c 2008-01-02 13:56:38.000000000 -0500
-@@ -39,6 +39,7 @@
- #include <net/ip.h>
- #include <net/route.h>
- #include <net/sock.h>
-+#include <net/net_namespace.h>
+@@ -255,7 +255,7 @@
+       if (sock->type != SOCK_RAW)
+               return -ESOCKTNOSUPPORT;
  
- #include <asm/uaccess.h>
+-      sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
++      sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
+       if (!sk)
+               return -ENOMEM;
  
-@@ -679,7 +680,7 @@
-       conn_flags = udest->conn_flags | IP_VS_CONN_F_INACTIVE;
+diff -Nurb linux-2.6.22-590/net/bluetooth/l2cap.c linux-2.6.22-570/net/bluetooth/l2cap.c
+--- linux-2.6.22-590/net/bluetooth/l2cap.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bluetooth/l2cap.c     2007-07-08 19:32:17.000000000 -0400
+@@ -518,11 +518,11 @@
+       .obj_size       = sizeof(struct l2cap_pinfo)
+ };
  
-       /* check if local node and update the flags */
--      if (inet_addr_type(udest->addr) == RTN_LOCAL) {
-+      if (inet_addr_type(&init_net, udest->addr) == RTN_LOCAL) {
-               conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK)
-                       | IP_VS_CONN_F_LOCALNODE;
-       }
-@@ -731,7 +732,7 @@
+-static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
++static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, gfp_t prio)
+ {
+       struct sock *sk;
  
-       EnterFunction(2);
+-      sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto, 1);
++      sk = sk_alloc(PF_BLUETOOTH, prio, &l2cap_proto, 1);
+       if (!sk)
+               return NULL;
  
--      atype = inet_addr_type(udest->addr);
-+      atype = inet_addr_type(&init_net, udest->addr);
-       if (atype != RTN_LOCAL && atype != RTN_UNICAST)
-               return -EINVAL;
+@@ -543,7 +543,7 @@
+       return sk;
+ }
  
-@@ -1932,6 +1933,9 @@
-       struct ip_vs_service *svc;
-       struct ip_vs_dest_user *udest;
+-static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol)
++static int l2cap_sock_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
  
-+      if (sk->sk_net != &init_net)
-+              return -ENOPROTOOPT;
-+
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
+@@ -560,7 +560,7 @@
  
-@@ -2196,6 +2200,9 @@
-       unsigned char arg[128];
-       int ret = 0;
+       sock->ops = &l2cap_sock_ops;
  
-+      if (sk->sk_net != &init_net)
-+              return -ENOPROTOOPT;
-+
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
+-      sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
++      sk = l2cap_sock_alloc(sock, protocol, GFP_ATOMIC);
+       if (!sk)
+               return -ENOMEM;
  
-@@ -2356,8 +2363,8 @@
-               return ret;
+@@ -1425,7 +1425,7 @@
+               goto response;
        }
  
--      proc_net_fops_create("ip_vs", 0, &ip_vs_info_fops);
--      proc_net_fops_create("ip_vs_stats",0, &ip_vs_stats_fops);
-+      proc_net_fops_create(&init_net, "ip_vs", 0, &ip_vs_info_fops);
-+      proc_net_fops_create(&init_net, "ip_vs_stats",0, &ip_vs_stats_fops);
+-      sk = l2cap_sock_alloc(parent->sk_net, NULL, BTPROTO_L2CAP, GFP_ATOMIC);
++      sk = l2cap_sock_alloc(NULL, BTPROTO_L2CAP, GFP_ATOMIC);
+       if (!sk)
+               goto response;
  
-       sysctl_header = register_sysctl_table(vs_root_table);
+diff -Nurb linux-2.6.22-590/net/bluetooth/rfcomm/core.c linux-2.6.22-570/net/bluetooth/rfcomm/core.c
+--- linux-2.6.22-590/net/bluetooth/rfcomm/core.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bluetooth/rfcomm/core.c       2007-07-08 19:32:17.000000000 -0400
+@@ -33,7 +33,6 @@
+ #include <linux/sched.h>
+ #include <linux/signal.h>
+ #include <linux/init.h>
+-#include <linux/freezer.h>
+ #include <linux/wait.h>
+ #include <linux/device.h>
+ #include <linux/net.h>
+@@ -1941,6 +1940,7 @@
  
-@@ -2390,8 +2397,8 @@
-       cancel_work_sync(&defense_work.work);
-       ip_vs_kill_estimator(&ip_vs_stats);
-       unregister_sysctl_table(sysctl_header);
--      proc_net_remove("ip_vs_stats");
--      proc_net_remove("ip_vs");
-+      proc_net_remove(&init_net, "ip_vs_stats");
-+      proc_net_remove(&init_net, "ip_vs");
-       nf_unregister_sockopt(&ip_vs_sockopts);
-       LeaveFunction(2);
- }
-diff -Nurb linux-2.6.22-570/net/ipv4/ipvs/ip_vs_lblcr.c linux-2.6.22-590/net/ipv4/ipvs/ip_vs_lblcr.c
---- linux-2.6.22-570/net/ipv4/ipvs/ip_vs_lblcr.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ipvs/ip_vs_lblcr.c       2008-01-02 13:56:38.000000000 -0500
-@@ -843,7 +843,7 @@
-       INIT_LIST_HEAD(&ip_vs_lblcr_scheduler.n_list);
-       sysctl_header = register_sysctl_table(lblcr_root_table);
- #ifdef CONFIG_IP_VS_LBLCR_DEBUG
--      proc_net_create("ip_vs_lblcr", 0, ip_vs_lblcr_getinfo);
-+      proc_net_create(&init_net, "ip_vs_lblcr", 0, ip_vs_lblcr_getinfo);
- #endif
-       return register_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
- }
-@@ -852,7 +852,7 @@
- static void __exit ip_vs_lblcr_cleanup(void)
- {
- #ifdef CONFIG_IP_VS_LBLCR_DEBUG
--      proc_net_remove("ip_vs_lblcr");
-+      proc_net_remove(&init_net, "ip_vs_lblcr");
- #endif
-       unregister_sysctl_table(sysctl_header);
-       unregister_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
-diff -Nurb linux-2.6.22-570/net/ipv4/ipvs/ip_vs_sync.c linux-2.6.22-590/net/ipv4/ipvs/ip_vs_sync.c
---- linux-2.6.22-570/net/ipv4/ipvs/ip_vs_sync.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ipvs/ip_vs_sync.c        2008-01-02 13:56:38.000000000 -0500
-@@ -387,7 +387,7 @@
-       struct net_device *dev;
-       struct inet_sock *inet = inet_sk(sk);
+       daemonize("krfcommd");
+       set_user_nice(current, -10);
++      current->flags |= PF_NOFREEZE;
  
--      if ((dev = __dev_get_by_name(ifname)) == NULL)
-+      if ((dev = __dev_get_by_name(&init_net, ifname)) == NULL)
-               return -ENODEV;
+       BT_DBG("");
  
-       if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
-@@ -412,7 +412,7 @@
-       int num;
+diff -Nurb linux-2.6.22-590/net/bluetooth/rfcomm/sock.c linux-2.6.22-570/net/bluetooth/rfcomm/sock.c
+--- linux-2.6.22-590/net/bluetooth/rfcomm/sock.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bluetooth/rfcomm/sock.c       2007-07-08 19:32:17.000000000 -0400
+@@ -282,12 +282,12 @@
+       .obj_size       = sizeof(struct rfcomm_pinfo)
+ };
  
-       if (sync_state == IP_VS_STATE_MASTER) {
--              if ((dev = __dev_get_by_name(ip_vs_master_mcast_ifn)) == NULL)
-+              if ((dev = __dev_get_by_name(&init_net, ip_vs_master_mcast_ifn)) == NULL)
-                       return -ENODEV;
+-static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
++static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, gfp_t prio)
+ {
+       struct rfcomm_dlc *d;
+       struct sock *sk;
  
-               num = (dev->mtu - sizeof(struct iphdr) -
-@@ -423,7 +423,7 @@
-               IP_VS_DBG(7, "setting the maximum length of sync sending "
-                         "message %d.\n", sync_send_mesg_maxlen);
-       } else if (sync_state == IP_VS_STATE_BACKUP) {
--              if ((dev = __dev_get_by_name(ip_vs_backup_mcast_ifn)) == NULL)
-+              if ((dev = __dev_get_by_name(&init_net, ip_vs_backup_mcast_ifn)) == NULL)
-                       return -ENODEV;
+-      sk = sk_alloc(net, PF_BLUETOOTH, prio, &rfcomm_proto, 1);
++      sk = sk_alloc(PF_BLUETOOTH, prio, &rfcomm_proto, 1);
+       if (!sk)
+               return NULL;
  
-               sync_recv_mesg_maxlen = dev->mtu -
-@@ -451,7 +451,7 @@
-       memset(&mreq, 0, sizeof(mreq));
-       memcpy(&mreq.imr_multiaddr, addr, sizeof(struct in_addr));
+@@ -323,7 +323,7 @@
+       return sk;
+ }
  
--      if ((dev = __dev_get_by_name(ifname)) == NULL)
-+      if ((dev = __dev_get_by_name(&init_net, ifname)) == NULL)
-               return -ENODEV;
-       if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
-               return -EINVAL;
-@@ -472,7 +472,7 @@
-       __be32 addr;
-       struct sockaddr_in sin;
+-static int rfcomm_sock_create(struct net *net, struct socket *sock, int protocol)
++static int rfcomm_sock_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
  
--      if ((dev = __dev_get_by_name(ifname)) == NULL)
-+      if ((dev = __dev_get_by_name(&init_net, ifname)) == NULL)
-               return -ENODEV;
+@@ -336,7 +336,7 @@
  
-       addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
-diff -Nurb linux-2.6.22-570/net/ipv4/ipvs/ip_vs_xmit.c linux-2.6.22-590/net/ipv4/ipvs/ip_vs_xmit.c
---- linux-2.6.22-570/net/ipv4/ipvs/ip_vs_xmit.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/ipvs/ip_vs_xmit.c        2008-01-02 13:56:38.000000000 -0500
-@@ -70,6 +70,7 @@
-               if (!(rt = (struct rtable *)
-                     __ip_vs_dst_check(dest, rtos, 0))) {
-                       struct flowi fl = {
-+                              .fl_net = &init_net,
-                               .oif = 0,
-                               .nl_u = {
-                                       .ip4_u = {
-@@ -93,6 +94,7 @@
-               spin_unlock(&dest->dst_lock);
-       } else {
-               struct flowi fl = {
-+                      .fl_net = &init_net,
-                       .oif = 0,
-                       .nl_u = {
-                               .ip4_u = {
-@@ -160,6 +162,7 @@
-       u8     tos = iph->tos;
-       int    mtu;
-       struct flowi fl = {
-+              .fl_net = &init_net,
-               .oif = 0,
-               .nl_u = {
-                       .ip4_u = {
-diff -Nurb linux-2.6.22-570/net/ipv4/multipath.c linux-2.6.22-590/net/ipv4/multipath.c
---- linux-2.6.22-570/net/ipv4/multipath.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/multipath.c      1969-12-31 19:00:00.000000000 -0500
-@@ -1,55 +0,0 @@
--/* multipath.c: IPV4 multipath algorithm support.
-- *
-- * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
-- * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
-- */
--
--#include <linux/module.h>
--#include <linux/errno.h>
--#include <linux/netdevice.h>
--#include <linux/spinlock.h>
--
--#include <net/ip_mp_alg.h>
--
--static DEFINE_SPINLOCK(alg_table_lock);
--struct ip_mp_alg_ops *ip_mp_alg_table[IP_MP_ALG_MAX + 1];
--
--int multipath_alg_register(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
--{
--      struct ip_mp_alg_ops **slot;
--      int err;
--
--      if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX ||
--          !ops->mp_alg_select_route)
--              return -EINVAL;
--
--      spin_lock(&alg_table_lock);
--      slot = &ip_mp_alg_table[n];
--      if (*slot != NULL) {
--              err = -EBUSY;
--      } else {
--              *slot = ops;
--              err = 0;
--      }
--      spin_unlock(&alg_table_lock);
--
--      return err;
--}
--EXPORT_SYMBOL(multipath_alg_register);
--
--void multipath_alg_unregister(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
--{
--      struct ip_mp_alg_ops **slot;
--
--      if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX)
--              return;
--
--      spin_lock(&alg_table_lock);
--      slot = &ip_mp_alg_table[n];
--      if (*slot == ops)
--              *slot = NULL;
--      spin_unlock(&alg_table_lock);
--
--      synchronize_net();
--}
--EXPORT_SYMBOL(multipath_alg_unregister);
-diff -Nurb linux-2.6.22-570/net/ipv4/multipath_drr.c linux-2.6.22-590/net/ipv4/multipath_drr.c
---- linux-2.6.22-570/net/ipv4/multipath_drr.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/multipath_drr.c  1969-12-31 19:00:00.000000000 -0500
-@@ -1,249 +0,0 @@
--/*
-- *              Device round robin policy for multipath.
-- *
-- *
-- * Version:   $Id: multipath_drr.c,v 1.1.2.1 2004/09/16 07:42:34 elueck Exp $
-- *
-- * Authors:   Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
-- *
-- *            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.
-- */
--
--#include <asm/system.h>
--#include <asm/uaccess.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/kernel.h>
--#include <linux/fcntl.h>
--#include <linux/stat.h>
--#include <linux/socket.h>
--#include <linux/in.h>
--#include <linux/inet.h>
--#include <linux/netdevice.h>
--#include <linux/inetdevice.h>
--#include <linux/igmp.h>
--#include <linux/proc_fs.h>
--#include <linux/seq_file.h>
--#include <linux/module.h>
--#include <linux/mroute.h>
--#include <linux/init.h>
--#include <net/ip.h>
--#include <net/protocol.h>
--#include <linux/skbuff.h>
--#include <net/sock.h>
--#include <net/icmp.h>
--#include <net/udp.h>
--#include <net/raw.h>
--#include <linux/notifier.h>
--#include <linux/if_arp.h>
--#include <linux/netfilter_ipv4.h>
--#include <net/ipip.h>
--#include <net/checksum.h>
--#include <net/ip_mp_alg.h>
--
--struct multipath_device {
--      int             ifi; /* interface index of device */
--      atomic_t        usecount;
--      int             allocated;
--};
--
--#define MULTIPATH_MAX_DEVICECANDIDATES 10
--
--static struct multipath_device state[MULTIPATH_MAX_DEVICECANDIDATES];
--static DEFINE_SPINLOCK(state_lock);
--
--static int inline __multipath_findslot(void)
--{
--      int i;
--
--      for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) {
--              if (state[i].allocated == 0)
--                      return i;
--      }
--      return -1;
--}
--
--static int inline __multipath_finddev(int ifindex)
--{
--      int i;
--
--      for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) {
--              if (state[i].allocated != 0 &&
--                  state[i].ifi == ifindex)
--                      return i;
--      }
--      return -1;
--}
--
--static int drr_dev_event(struct notifier_block *this,
--                       unsigned long event, void *ptr)
--{
--      struct net_device *dev = ptr;
--      int devidx;
--
--      switch (event) {
--      case NETDEV_UNREGISTER:
--      case NETDEV_DOWN:
--              spin_lock_bh(&state_lock);
--
--              devidx = __multipath_finddev(dev->ifindex);
--              if (devidx != -1) {
--                      state[devidx].allocated = 0;
--                      state[devidx].ifi = 0;
--                      atomic_set(&state[devidx].usecount, 0);
--              }
--
--              spin_unlock_bh(&state_lock);
--              break;
--      }
--
--      return NOTIFY_DONE;
--}
--
--static struct notifier_block drr_dev_notifier = {
--      .notifier_call  = drr_dev_event,
--};
--
--
--static void drr_safe_inc(atomic_t *usecount)
--{
--      int n;
--
--      atomic_inc(usecount);
--
--      n = atomic_read(usecount);
--      if (n <= 0) {
--              int i;
--
--              spin_lock_bh(&state_lock);
--
--              for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++)
--                      atomic_set(&state[i].usecount, 0);
--
--              spin_unlock_bh(&state_lock);
--      }
--}
--
--static void drr_select_route(const struct flowi *flp,
--                           struct rtable *first, struct rtable **rp)
--{
--      struct rtable *nh, *result, *cur_min;
--      int min_usecount = -1;
--      int devidx = -1;
--      int cur_min_devidx = -1;
--
--      /* 1. make sure all alt. nexthops have the same GC related data */
--      /* 2. determine the new candidate to be returned */
--      result = NULL;
--      cur_min = NULL;
--      for (nh = rcu_dereference(first); nh;
--           nh = rcu_dereference(nh->u.dst.rt_next)) {
--              if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
--                  multipath_comparekeys(&nh->fl, flp)) {
--                      int nh_ifidx = nh->u.dst.dev->ifindex;
--
--                      nh->u.dst.lastuse = jiffies;
--                      nh->u.dst.__use++;
--                      if (result != NULL)
--                              continue;
--
--                      /* search for the output interface */
--
--                      /* this is not SMP safe, only add/remove are
--                       * SMP safe as wrong usecount updates have no big
--                       * impact
--                       */
--                      devidx = __multipath_finddev(nh_ifidx);
--                      if (devidx == -1) {
--                              /* add the interface to the array
--                               * SMP safe
--                               */
--                              spin_lock_bh(&state_lock);
--
--                              /* due to SMP: search again */
--                              devidx = __multipath_finddev(nh_ifidx);
--                              if (devidx == -1) {
--                                      /* add entry for device */
--                                      devidx = __multipath_findslot();
--                                      if (devidx == -1) {
--                                              /* unlikely but possible */
--                                              continue;
--                                      }
--
--                                      state[devidx].allocated = 1;
--                                      state[devidx].ifi = nh_ifidx;
--                                      atomic_set(&state[devidx].usecount, 0);
--                                      min_usecount = 0;
--                              }
--
--                              spin_unlock_bh(&state_lock);
--                      }
--
--                      if (min_usecount == 0) {
--                              /* if the device has not been used it is
--                               * the primary target
--                               */
--                              drr_safe_inc(&state[devidx].usecount);
--                              result = nh;
--                      } else {
--                              int count =
--                                      atomic_read(&state[devidx].usecount);
--
--                              if (min_usecount == -1 ||
--                                  count < min_usecount) {
--                                      cur_min = nh;
--                                      cur_min_devidx = devidx;
--                                      min_usecount = count;
--                              }
--                      }
--              }
--      }
--
--      if (!result) {
--              if (cur_min) {
--                      drr_safe_inc(&state[cur_min_devidx].usecount);
--                      result = cur_min;
--              } else {
--                      result = first;
--              }
--      }
--
--      *rp = result;
--}
--
--static struct ip_mp_alg_ops drr_ops = {
--      .mp_alg_select_route    =       drr_select_route,
--};
--
--static int __init drr_init(void)
--{
--      int err = register_netdevice_notifier(&drr_dev_notifier);
--
--      if (err)
--              return err;
--
--      err = multipath_alg_register(&drr_ops, IP_MP_ALG_DRR);
--      if (err)
--              goto fail;
--
--      return 0;
--
--fail:
--      unregister_netdevice_notifier(&drr_dev_notifier);
--      return err;
--}
--
--static void __exit drr_exit(void)
--{
--      unregister_netdevice_notifier(&drr_dev_notifier);
--      multipath_alg_unregister(&drr_ops, IP_MP_ALG_DRR);
--}
--
--module_init(drr_init);
--module_exit(drr_exit);
--MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/net/ipv4/multipath_random.c linux-2.6.22-590/net/ipv4/multipath_random.c
---- linux-2.6.22-570/net/ipv4/multipath_random.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/multipath_random.c       1969-12-31 19:00:00.000000000 -0500
-@@ -1,114 +0,0 @@
--/*
-- *              Random policy for multipath.
-- *
-- *
-- * Version:   $Id: multipath_random.c,v 1.1.2.3 2004/09/21 08:42:11 elueck Exp $
-- *
-- * Authors:   Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
-- *
-- *            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.
-- */
--
--#include <asm/system.h>
--#include <asm/uaccess.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/kernel.h>
--#include <linux/fcntl.h>
--#include <linux/stat.h>
--#include <linux/socket.h>
--#include <linux/in.h>
--#include <linux/inet.h>
--#include <linux/netdevice.h>
--#include <linux/inetdevice.h>
--#include <linux/igmp.h>
--#include <linux/proc_fs.h>
--#include <linux/seq_file.h>
--#include <linux/module.h>
--#include <linux/mroute.h>
--#include <linux/init.h>
--#include <linux/random.h>
--#include <net/ip.h>
--#include <net/protocol.h>
--#include <linux/skbuff.h>
--#include <net/sock.h>
--#include <net/icmp.h>
--#include <net/udp.h>
--#include <net/raw.h>
--#include <linux/notifier.h>
--#include <linux/if_arp.h>
--#include <linux/netfilter_ipv4.h>
--#include <net/ipip.h>
--#include <net/checksum.h>
--#include <net/ip_mp_alg.h>
--
--#define MULTIPATH_MAX_CANDIDATES 40
--
--static void random_select_route(const struct flowi *flp,
--                              struct rtable *first,
--                              struct rtable **rp)
--{
--      struct rtable *rt;
--      struct rtable *decision;
--      unsigned char candidate_count = 0;
--
--      /* count all candidate */
--      for (rt = rcu_dereference(first); rt;
--           rt = rcu_dereference(rt->u.dst.rt_next)) {
--              if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
--                  multipath_comparekeys(&rt->fl, flp))
--                      ++candidate_count;
--      }
--
--      /* choose a random candidate */
--      decision = first;
--      if (candidate_count > 1) {
--              unsigned char i = 0;
--              unsigned char candidate_no = (unsigned char)
--                      (random32() % candidate_count);
--
--              /* find chosen candidate and adjust GC data for all candidates
--               * to ensure they stay in cache
--               */
--              for (rt = first; rt; rt = rt->u.dst.rt_next) {
--                      if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
--                          multipath_comparekeys(&rt->fl, flp)) {
--                              rt->u.dst.lastuse = jiffies;
--
--                              if (i == candidate_no)
--                                      decision = rt;
--
--                              if (i >= candidate_count)
--                                      break;
--
--                              i++;
--                      }
--              }
--      }
--
--      decision->u.dst.__use++;
--      *rp = decision;
--}
--
--static struct ip_mp_alg_ops random_ops = {
--      .mp_alg_select_route    =       random_select_route,
--};
--
--static int __init random_init(void)
--{
--      return multipath_alg_register(&random_ops, IP_MP_ALG_RANDOM);
--}
--
--static void __exit random_exit(void)
--{
--      multipath_alg_unregister(&random_ops, IP_MP_ALG_RANDOM);
--}
--
--module_init(random_init);
--module_exit(random_exit);
--MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/net/ipv4/multipath_rr.c linux-2.6.22-590/net/ipv4/multipath_rr.c
---- linux-2.6.22-570/net/ipv4/multipath_rr.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/multipath_rr.c   1969-12-31 19:00:00.000000000 -0500
-@@ -1,95 +0,0 @@
--/*
-- *              Round robin policy for multipath.
-- *
-- *
-- * Version:   $Id: multipath_rr.c,v 1.1.2.2 2004/09/16 07:42:34 elueck Exp $
-- *
-- * Authors:   Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
-- *
-- *            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.
-- */
--
--#include <asm/system.h>
--#include <asm/uaccess.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/kernel.h>
--#include <linux/fcntl.h>
--#include <linux/stat.h>
--#include <linux/socket.h>
--#include <linux/in.h>
--#include <linux/inet.h>
--#include <linux/netdevice.h>
--#include <linux/inetdevice.h>
--#include <linux/igmp.h>
--#include <linux/proc_fs.h>
--#include <linux/seq_file.h>
--#include <linux/module.h>
--#include <linux/mroute.h>
--#include <linux/init.h>
--#include <net/ip.h>
--#include <net/protocol.h>
--#include <linux/skbuff.h>
--#include <net/sock.h>
--#include <net/icmp.h>
--#include <net/udp.h>
--#include <net/raw.h>
--#include <linux/notifier.h>
--#include <linux/if_arp.h>
--#include <linux/netfilter_ipv4.h>
--#include <net/ipip.h>
--#include <net/checksum.h>
--#include <net/ip_mp_alg.h>
--
--static void rr_select_route(const struct flowi *flp,
--                          struct rtable *first, struct rtable **rp)
--{
--      struct rtable *nh, *result, *min_use_cand = NULL;
--      int min_use = -1;
--
--      /* 1. make sure all alt. nexthops have the same GC related data
--       * 2. determine the new candidate to be returned
--       */
--      result = NULL;
--      for (nh = rcu_dereference(first); nh;
--           nh = rcu_dereference(nh->u.dst.rt_next)) {
--              if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
--                  multipath_comparekeys(&nh->fl, flp)) {
--                      nh->u.dst.lastuse = jiffies;
--
--                      if (min_use == -1 || nh->u.dst.__use < min_use) {
--                              min_use = nh->u.dst.__use;
--                              min_use_cand = nh;
--                      }
--              }
--      }
--      result = min_use_cand;
--      if (!result)
--              result = first;
--
--      result->u.dst.__use++;
--      *rp = result;
--}
--
--static struct ip_mp_alg_ops rr_ops = {
--      .mp_alg_select_route    =       rr_select_route,
--};
--
--static int __init rr_init(void)
--{
--      return multipath_alg_register(&rr_ops, IP_MP_ALG_RR);
--}
--
--static void __exit rr_exit(void)
--{
--      multipath_alg_unregister(&rr_ops, IP_MP_ALG_RR);
--}
--
--module_init(rr_init);
--module_exit(rr_exit);
--MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/net/ipv4/multipath_wrandom.c linux-2.6.22-590/net/ipv4/multipath_wrandom.c
---- linux-2.6.22-570/net/ipv4/multipath_wrandom.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/multipath_wrandom.c      1969-12-31 19:00:00.000000000 -0500
-@@ -1,329 +0,0 @@
--/*
-- *              Weighted random policy for multipath.
-- *
-- *
-- * Version:   $Id: multipath_wrandom.c,v 1.1.2.3 2004/09/22 07:51:40 elueck Exp $
-- *
-- * Authors:   Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
-- *
-- *            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.
-- */
--
--#include <asm/system.h>
--#include <asm/uaccess.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/kernel.h>
--#include <linux/fcntl.h>
--#include <linux/stat.h>
--#include <linux/socket.h>
--#include <linux/in.h>
--#include <linux/inet.h>
--#include <linux/netdevice.h>
--#include <linux/inetdevice.h>
--#include <linux/igmp.h>
--#include <linux/proc_fs.h>
--#include <linux/seq_file.h>
--#include <linux/module.h>
--#include <linux/mroute.h>
--#include <linux/init.h>
--#include <linux/random.h>
--#include <net/ip.h>
--#include <net/protocol.h>
--#include <linux/skbuff.h>
--#include <net/sock.h>
--#include <net/icmp.h>
--#include <net/udp.h>
--#include <net/raw.h>
--#include <linux/notifier.h>
--#include <linux/if_arp.h>
--#include <linux/netfilter_ipv4.h>
--#include <net/ipip.h>
--#include <net/checksum.h>
--#include <net/ip_fib.h>
--#include <net/ip_mp_alg.h>
--
--#define MULTIPATH_STATE_SIZE 15
--
--struct multipath_candidate {
--      struct multipath_candidate      *next;
--      int                             power;
--      struct rtable                   *rt;
--};
--
--struct multipath_dest {
--      struct list_head        list;
--
--      const struct fib_nh     *nh_info;
--      __be32                  netmask;
--      __be32                  network;
--      unsigned char           prefixlen;
--
--      struct rcu_head         rcu;
--};
--
--struct multipath_bucket {
--      struct list_head        head;
--      spinlock_t              lock;
--};
--
--struct multipath_route {
--      struct list_head        list;
--
--      int                     oif;
--      __be32                  gw;
--      struct list_head        dests;
--
--      struct rcu_head         rcu;
--};
--
--/* state: primarily weight per route information */
--static struct multipath_bucket state[MULTIPATH_STATE_SIZE];
--
--static unsigned char __multipath_lookup_weight(const struct flowi *fl,
--                                             const struct rtable *rt)
--{
--      const int state_idx = rt->idev->dev->ifindex % MULTIPATH_STATE_SIZE;
--      struct multipath_route *r;
--      struct multipath_route *target_route = NULL;
--      struct multipath_dest *d;
--      int weight = 1;
--
--      /* lookup the weight information for a certain route */
--      rcu_read_lock();
--
--      /* find state entry for gateway or add one if necessary */
--      list_for_each_entry_rcu(r, &state[state_idx].head, list) {
--              if (r->gw == rt->rt_gateway &&
--                  r->oif == rt->idev->dev->ifindex) {
--                      target_route = r;
--                      break;
--              }
--      }
--
--      if (!target_route) {
--              /* this should not happen... but we are prepared */
--              printk( KERN_CRIT"%s: missing state for gateway: %u and " \
--                      "device %d\n", __FUNCTION__, rt->rt_gateway,
--                      rt->idev->dev->ifindex);
--              goto out;
--      }
--
--      /* find state entry for destination */
--      list_for_each_entry_rcu(d, &target_route->dests, list) {
--              __be32 targetnetwork = fl->fl4_dst &
--                      inet_make_mask(d->prefixlen);
--
--              if ((targetnetwork & d->netmask) == d->network) {
--                      weight = d->nh_info->nh_weight;
--                      goto out;
--              }
--      }
--
--out:
--      rcu_read_unlock();
--      return weight;
--}
--
--static void wrandom_init_state(void)
--{
--      int i;
--
--      for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
--              INIT_LIST_HEAD(&state[i].head);
--              spin_lock_init(&state[i].lock);
--      }
--}
--
--static void wrandom_select_route(const struct flowi *flp,
--                               struct rtable *first,
--                               struct rtable **rp)
--{
--      struct rtable *rt;
--      struct rtable *decision;
--      struct multipath_candidate *first_mpc = NULL;
--      struct multipath_candidate *mpc, *last_mpc = NULL;
--      int power = 0;
--      int last_power;
--      int selector;
--      const size_t size_mpc = sizeof(struct multipath_candidate);
--
--      /* collect all candidates and identify their weights */
--      for (rt = rcu_dereference(first); rt;
--           rt = rcu_dereference(rt->u.dst.rt_next)) {
--              if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
--                  multipath_comparekeys(&rt->fl, flp)) {
--                      struct multipath_candidate* mpc =
--                              (struct multipath_candidate*)
--                              kmalloc(size_mpc, GFP_ATOMIC);
--
--                      if (!mpc)
--                              return;
--
--                      power += __multipath_lookup_weight(flp, rt) * 10000;
--
--                      mpc->power = power;
--                      mpc->rt = rt;
--                      mpc->next = NULL;
--
--                      if (!first_mpc)
--                              first_mpc = mpc;
--                      else
--                              last_mpc->next = mpc;
--
--                      last_mpc = mpc;
--              }
--      }
--
--      /* choose a weighted random candidate */
--      decision = first;
--      selector = random32() % power;
--      last_power = 0;
--
--      /* select candidate, adjust GC data and cleanup local state */
--      decision = first;
--      last_mpc = NULL;
--      for (mpc = first_mpc; mpc; mpc = mpc->next) {
--              mpc->rt->u.dst.lastuse = jiffies;
--              if (last_power <= selector && selector < mpc->power)
--                      decision = mpc->rt;
--
--              last_power = mpc->power;
--              kfree(last_mpc);
--              last_mpc = mpc;
--      }
--
--      /* concurrent __multipath_flush may lead to !last_mpc */
--      kfree(last_mpc);
--
--      decision->u.dst.__use++;
--      *rp = decision;
--}
--
--static void wrandom_set_nhinfo(__be32 network,
--                             __be32 netmask,
--                             unsigned char prefixlen,
--                             const struct fib_nh *nh)
--{
--      const int state_idx = nh->nh_oif % MULTIPATH_STATE_SIZE;
--      struct multipath_route *r, *target_route = NULL;
--      struct multipath_dest *d, *target_dest = NULL;
--
--      /* store the weight information for a certain route */
--      spin_lock_bh(&state[state_idx].lock);
--
--      /* find state entry for gateway or add one if necessary */
--      list_for_each_entry_rcu(r, &state[state_idx].head, list) {
--              if (r->gw == nh->nh_gw && r->oif == nh->nh_oif) {
--                      target_route = r;
--                      break;
--              }
--      }
--
--      if (!target_route) {
--              const size_t size_rt = sizeof(struct multipath_route);
--              target_route = (struct multipath_route *)
--                      kmalloc(size_rt, GFP_ATOMIC);
--
--              target_route->gw = nh->nh_gw;
--              target_route->oif = nh->nh_oif;
--              memset(&target_route->rcu, 0, sizeof(struct rcu_head));
--              INIT_LIST_HEAD(&target_route->dests);
--
--              list_add_rcu(&target_route->list, &state[state_idx].head);
--      }
--
--      /* find state entry for destination or add one if necessary */
--      list_for_each_entry_rcu(d, &target_route->dests, list) {
--              if (d->nh_info == nh) {
--                      target_dest = d;
--                      break;
--              }
--      }
--
--      if (!target_dest) {
--              const size_t size_dst = sizeof(struct multipath_dest);
--              target_dest = (struct multipath_dest*)
--                      kmalloc(size_dst, GFP_ATOMIC);
--
--              target_dest->nh_info = nh;
--              target_dest->network = network;
--              target_dest->netmask = netmask;
--              target_dest->prefixlen = prefixlen;
--              memset(&target_dest->rcu, 0, sizeof(struct rcu_head));
--
--              list_add_rcu(&target_dest->list, &target_route->dests);
--      }
--      /* else: we already stored this info for another destination =>
--       * we are finished
--       */
--
--      spin_unlock_bh(&state[state_idx].lock);
--}
--
--static void __multipath_free(struct rcu_head *head)
--{
--      struct multipath_route *rt = container_of(head, struct multipath_route,
--                                                rcu);
--      kfree(rt);
--}
+       sock->ops = &rfcomm_sock_ops;
+-      sk = rfcomm_sock_alloc(net, sock, protocol, GFP_ATOMIC);
++      sk = rfcomm_sock_alloc(sock, protocol, GFP_ATOMIC);
+       if (!sk)
+               return -ENOMEM;
+@@ -868,7 +868,7 @@
+               goto done;
+       }
+-      sk = rfcomm_sock_alloc(parent->sk_net, NULL, BTPROTO_RFCOMM, GFP_ATOMIC);
++      sk = rfcomm_sock_alloc(NULL, BTPROTO_RFCOMM, GFP_ATOMIC);
+       if (!sk)
+               goto done;
+diff -Nurb linux-2.6.22-590/net/bluetooth/sco.c linux-2.6.22-570/net/bluetooth/sco.c
+--- linux-2.6.22-590/net/bluetooth/sco.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bluetooth/sco.c       2007-07-08 19:32:17.000000000 -0400
+@@ -414,11 +414,11 @@
+       .obj_size       = sizeof(struct sco_pinfo)
+ };
+-static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
++static struct sock *sco_sock_alloc(struct socket *sock, int proto, gfp_t prio)
+ {
+       struct sock *sk;
+-      sk = sk_alloc(net, PF_BLUETOOTH, prio, &sco_proto, 1);
++      sk = sk_alloc(PF_BLUETOOTH, prio, &sco_proto, 1);
+       if (!sk)
+               return NULL;
+@@ -439,7 +439,7 @@
+       return sk;
+ }
+-static int sco_sock_create(struct net *net, struct socket *sock, int protocol)
++static int sco_sock_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
+@@ -452,7 +452,7 @@
+       sock->ops = &sco_sock_ops;
+-      sk = sco_sock_alloc(net, sock, protocol, GFP_ATOMIC);
++      sk = sco_sock_alloc(sock, protocol, GFP_ATOMIC);
+       if (!sk)
+               return -ENOMEM;
+@@ -807,7 +807,7 @@
+               bh_lock_sock(parent);
+-              sk = sco_sock_alloc(parent->sk_net, NULL, BTPROTO_SCO, GFP_ATOMIC);
++              sk = sco_sock_alloc(NULL, BTPROTO_SCO, GFP_ATOMIC);
+               if (!sk) {
+                       bh_unlock_sock(parent);
+                       goto done;
+diff -Nurb linux-2.6.22-590/net/bridge/br_if.c linux-2.6.22-570/net/bridge/br_if.c
+--- linux-2.6.22-590/net/bridge/br_if.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/br_if.c        2008-01-23 19:15:56.000000000 -0500
+@@ -45,7 +45,7 @@
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+-      err = dev_ethtool(dev->nd_net, &ifr);
++      err = dev_ethtool(&ifr);
+       set_fs(old_fs);
+       if (!err) {
+@@ -314,7 +314,7 @@
+       int ret = 0;
+       rtnl_lock();
+-      dev = __dev_get_by_name(&init_net, name);
++      dev = __dev_get_by_name(name);
+       if (dev == NULL)
+               ret =  -ENXIO;  /* Could not find device */
+@@ -455,7 +455,7 @@
+       struct net_device *dev, *nxt;
+       rtnl_lock();
+-      for_each_netdev_safe(&init_net, dev, nxt)
++      for_each_netdev_safe(dev, nxt)
+               if (dev->priv_flags & IFF_EBRIDGE)
+                       del_br(dev->priv);
+       rtnl_unlock();
+diff -Nurb linux-2.6.22-590/net/bridge/br_ioctl.c linux-2.6.22-570/net/bridge/br_ioctl.c
+--- linux-2.6.22-590/net/bridge/br_ioctl.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/br_ioctl.c     2007-07-08 19:32:17.000000000 -0400
+@@ -18,7 +18,6 @@
+ #include <linux/if_bridge.h>
+ #include <linux/netdevice.h>
+ #include <linux/times.h>
+-#include <net/net_namespace.h>
+ #include <asm/uaccess.h>
+ #include "br_private.h"
+@@ -28,7 +27,7 @@
+       struct net_device *dev;
+       int i = 0;
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if (i >= num)
+                       break;
+               if (dev->priv_flags & IFF_EBRIDGE)
+@@ -91,7 +90,7 @@
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+-      dev = dev_get_by_index(&init_net, ifindex);
++      dev = dev_get_by_index(ifindex);
+       if (dev == NULL)
+               return -EINVAL;
+@@ -365,7 +364,7 @@
+       return -EOPNOTSUPP;
+ }
+-int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg)
++int br_ioctl_deviceless_stub(unsigned int cmd, void __user *uarg)
+ {
+       switch (cmd) {
+       case SIOCGIFBR:
+diff -Nurb linux-2.6.22-590/net/bridge/br_netfilter.c linux-2.6.22-570/net/bridge/br_netfilter.c
+--- linux-2.6.22-590/net/bridge/br_netfilter.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/br_netfilter.c 2008-01-23 19:15:56.000000000 -0500
+@@ -310,7 +310,6 @@
+               if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) {
+                       struct rtable *rt;
+                       struct flowi fl = {
+-                              .fl_net = &init_net,
+                               .nl_u = {
+                                       .ip4_u = {
+                                                .daddr = iph->daddr,
+@@ -519,10 +518,6 @@
+       if (unlikely(!pskb_may_pull(skb, len)))
+               goto out;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--static void __multipath_free_dst(struct rcu_head *head)
--{
--      struct multipath_dest *dst = container_of(head,
--                                                struct multipath_dest,
--                                                rcu);
--      kfree(dst);
--}
+       if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb) ||
+           IS_PPPOE_IPV6(skb)) {
+ #ifdef CONFIG_SYSCTL
+@@ -596,10 +591,6 @@
+ {
+       struct sk_buff *skb = *pskb;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--static void wrandom_flush(void)
--{
--      int i;
+       if (skb->dst == (struct dst_entry *)&__fake_rtable) {
+               dst_release(skb->dst);
+               skb->dst = NULL;
+@@ -644,10 +635,6 @@
+       struct net_device *parent;
+       int pf;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--      /* defere delete to all entries */
--      for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
--              struct multipath_route *r;
--
--              spin_lock_bh(&state[i].lock);
--              list_for_each_entry_rcu(r, &state[i].head, list) {
--                      struct multipath_dest *d;
--                      list_for_each_entry_rcu(d, &r->dests, list) {
--                              list_del_rcu(&d->list);
--                              call_rcu(&d->rcu,
--                                       __multipath_free_dst);
--                      }
--                      list_del_rcu(&r->list);
--                      call_rcu(&r->rcu,
--                               __multipath_free);
--              }
+       if (!skb->nf_bridge)
+               return NF_ACCEPT;
+@@ -687,10 +674,6 @@
+       struct sk_buff *skb = *pskb;
+       struct net_device **d = (struct net_device **)(skb->cb);
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--              spin_unlock_bh(&state[i].lock);
--      }
--}
+ #ifdef CONFIG_SYSCTL
+       if (!brnf_call_arptables)
+               return NF_ACCEPT;
+@@ -735,10 +718,6 @@
+       struct sk_buff *skb = *pskb;
+       struct nf_bridge_info *nf_bridge;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--static struct ip_mp_alg_ops wrandom_ops = {
--      .mp_alg_select_route    =       wrandom_select_route,
--      .mp_alg_flush           =       wrandom_flush,
--      .mp_alg_set_nhinfo      =       wrandom_set_nhinfo,
--};
+       if (!skb->nf_bridge)
+               return NF_ACCEPT;
+@@ -783,10 +762,6 @@
+       struct net_device *realoutdev = bridge_parent(skb->dev);
+       int pf;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--static int __init wrandom_init(void)
--{
--      wrandom_init_state();
+ #ifdef CONFIG_NETFILTER_DEBUG
+       /* Be very paranoid. This probably won't happen anymore, but let's
+        * keep the check just to be sure... */
+@@ -858,10 +833,6 @@
+                                  const struct net_device *out,
+                                  int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--      return multipath_alg_register(&wrandom_ops, IP_MP_ALG_WRANDOM);
--}
+       if ((*pskb)->nf_bridge &&
+           !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
+               return NF_STOP;
+diff -Nurb linux-2.6.22-590/net/bridge/br_netlink.c linux-2.6.22-570/net/bridge/br_netlink.c
+--- linux-2.6.22-590/net/bridge/br_netlink.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/br_netlink.c   2007-07-08 19:32:17.000000000 -0400
+@@ -12,8 +12,6 @@
+ #include <linux/kernel.h>
+ #include <net/rtnetlink.h>
+-#include <net/net_namespace.h>
+-#include <net/sock.h>
+ #include "br_private.h"
+ static inline size_t br_nlmsg_size(void)
+@@ -97,10 +95,10 @@
+               kfree_skb(skb);
+               goto errout;
+       }
+-      err = rtnl_notify(skb, &init_net,0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
++      err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
+ errout:
+       if (err < 0)
+-              rtnl_set_sk_err(&init_net, RTNLGRP_LINK, err);
++              rtnl_set_sk_err(RTNLGRP_LINK, err);
+ }
+ /*
+@@ -108,15 +106,11 @@
+  */
+ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct net_device *dev;
+       int idx;
+-      if (net != &init_net)
+-              return 0;
 -
--static void __exit wrandom_exit(void)
--{
--      multipath_alg_unregister(&wrandom_ops, IP_MP_ALG_WRANDOM);
--}
+       idx = 0;
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               /* not a bridge port */
+               if (dev->br_port == NULL || idx < cb->args[0])
+                       goto skip;
+@@ -140,16 +134,12 @@
+  */
+ static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct ifinfomsg *ifm;
+       struct nlattr *protinfo;
+       struct net_device *dev;
+       struct net_bridge_port *p;
+       u8 new_state;
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--module_init(wrandom_init);
--module_exit(wrandom_exit);
--MODULE_LICENSE("GPL");
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/arp_tables.c linux-2.6.22-590/net/ipv4/netfilter/arp_tables.c
---- linux-2.6.22-570/net/ipv4/netfilter/arp_tables.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/arp_tables.c   2008-01-02 13:56:38.000000000 -0500
-@@ -19,6 +19,7 @@
- #include <linux/proc_fs.h>
- #include <linux/module.h>
- #include <linux/init.h>
-+#include <net/sock.h>
+       if (nlmsg_len(nlh) < sizeof(*ifm))
+               return -EINVAL;
  
- #include <asm/uaccess.h>
- #include <linux/mutex.h>
-@@ -773,7 +774,7 @@
-       int ret;
-       struct arpt_table *t;
+@@ -165,7 +155,7 @@
+       if (new_state > BR_STATE_BLOCKING)
+               return -EINVAL;
  
--      t = xt_find_table_lock(NF_ARP, entries->name);
-+      t = xt_find_table_lock(&init_net, NF_ARP, entries->name);
-       if (t && !IS_ERR(t)) {
-               struct xt_table_info *private = t->private;
-               duprintf("t->private->number = %u\n",
-@@ -843,7 +844,7 @@
+-      dev = __dev_get_by_index(&init_net, ifm->ifi_index);
++      dev = __dev_get_by_index(ifm->ifi_index);
+       if (!dev)
+               return -ENODEV;
  
-       duprintf("arp_tables: Translated table\n");
+diff -Nurb linux-2.6.22-590/net/bridge/br_notify.c linux-2.6.22-570/net/bridge/br_notify.c
+--- linux-2.6.22-590/net/bridge/br_notify.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/br_notify.c    2007-07-08 19:32:17.000000000 -0400
+@@ -15,7 +15,6 @@
  
--      t = try_then_request_module(xt_find_table_lock(NF_ARP, tmp.name),
-+      t = try_then_request_module(xt_find_table_lock(&init_net, NF_ARP, tmp.name),
-                                   "arptable_%s", tmp.name);
-       if (!t || IS_ERR(t)) {
-               ret = t ? PTR_ERR(t) : -ENOENT;
-@@ -936,7 +937,7 @@
-               goto free;
-       }
+ #include <linux/kernel.h>
+ #include <linux/rtnetlink.h>
+-#include <net/net_namespace.h>
  
--      t = xt_find_table_lock(NF_ARP, tmp.name);
-+      t = xt_find_table_lock(&init_net, NF_ARP, tmp.name);
-       if (!t || IS_ERR(t)) {
-               ret = t ? PTR_ERR(t) : -ENOENT;
-               goto free;
-@@ -971,6 +972,9 @@
- {
-       int ret;
+ #include "br_private.h"
  
-+      if (sk->sk_net != &init_net)
-+              return -ENOPROTOOPT;
-+
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
+@@ -37,9 +36,6 @@
+       struct net_bridge_port *p = dev->br_port;
+       struct net_bridge *br;
  
-@@ -995,6 +999,9 @@
- {
-       int ret;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       /* not a port of a bridge */
+       if (p == NULL)
+               return NOTIFY_DONE;
+diff -Nurb linux-2.6.22-590/net/bridge/br_private.h linux-2.6.22-570/net/bridge/br_private.h
+--- linux-2.6.22-590/net/bridge/br_private.h   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/br_private.h   2007-07-08 19:32:17.000000000 -0400
+@@ -196,7 +196,7 @@
  
-+      if (sk->sk_net != &init_net)
-+              return -ENOPROTOOPT;
-+
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
+ /* br_ioctl.c */
+ extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+-extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *arg);
++extern int br_ioctl_deviceless_stub(unsigned int cmd, void __user *arg);
  
-@@ -1016,7 +1023,7 @@
-               }
-               name[ARPT_TABLE_MAXNAMELEN-1] = '\0';
+ /* br_netfilter.c */
+ #ifdef CONFIG_BRIDGE_NETFILTER
+diff -Nurb linux-2.6.22-590/net/bridge/br_stp_bpdu.c linux-2.6.22-570/net/bridge/br_stp_bpdu.c
+--- linux-2.6.22-590/net/bridge/br_stp_bpdu.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/br_stp_bpdu.c  2007-07-08 19:32:17.000000000 -0400
+@@ -17,7 +17,6 @@
+ #include <linux/netfilter_bridge.h>
+ #include <linux/etherdevice.h>
+ #include <linux/llc.h>
+-#include <net/net_namespace.h>
+ #include <net/llc.h>
+ #include <net/llc_pdu.h>
+ #include <asm/unaligned.h>
+@@ -142,9 +141,6 @@
+       struct net_bridge *br;
+       const unsigned char *buf;
  
--              t = try_then_request_module(xt_find_table_lock(NF_ARP, name),
-+              t = try_then_request_module(xt_find_table_lock(&init_net, NF_ARP, name),
-                                           "arptable_%s", name);
-               if (t && !IS_ERR(t)) {
-                       struct arpt_getinfo info;
-@@ -1116,7 +1123,7 @@
-               return ret;
+-      if (dev->nd_net != &init_net)
+-              goto err;
+-
+       if (!p)
+               goto err;
+diff -Nurb linux-2.6.22-590/net/bridge/br_stp_if.c linux-2.6.22-570/net/bridge/br_stp_if.c
+--- linux-2.6.22-590/net/bridge/br_stp_if.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/br_stp_if.c    2007-07-08 19:32:17.000000000 -0400
+@@ -125,7 +125,7 @@
+       char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL };
+       char *envp[] = { NULL };
+-      r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
++      r = call_usermodehelper(BR_STP_PROG, argv, envp, 1);
+       if (r == 0) {
+               br->stp_enabled = BR_USER_STP;
+               printk(KERN_INFO "%s: userspace STP started\n", br->dev->name);
+diff -Nurb linux-2.6.22-590/net/bridge/br_sysfs_br.c linux-2.6.22-570/net/bridge/br_sysfs_br.c
+--- linux-2.6.22-590/net/bridge/br_sysfs_br.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/br_sysfs_br.c  2007-07-08 19:32:17.000000000 -0400
+@@ -360,9 +360,8 @@
+  *
+  * Returns the number of bytes read.
+  */
+-static ssize_t brforward_read(struct kobject *kobj,
+-                            struct bin_attribute *bin_attr,
+-                            char *buf, loff_t off, size_t count)
++static ssize_t brforward_read(struct kobject *kobj, char *buf,
++                         loff_t off, size_t count)
+ {
+       struct device *dev = to_dev(kobj);
+       struct net_bridge *br = to_bridge(dev);
+@@ -384,7 +383,8 @@
+ static struct bin_attribute bridge_forward = {
+       .attr = { .name = SYSFS_BRIDGE_FDB,
+-                .mode = S_IRUGO, },
++                .mode = S_IRUGO,
++                .owner = THIS_MODULE, },
+       .read = brforward_read,
+ };
+diff -Nurb linux-2.6.22-590/net/bridge/br_sysfs_if.c linux-2.6.22-570/net/bridge/br_sysfs_if.c
+--- linux-2.6.22-590/net/bridge/br_sysfs_if.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/br_sysfs_if.c  2007-07-08 19:32:17.000000000 -0400
+@@ -29,7 +29,8 @@
+ #define BRPORT_ATTR(_name,_mode,_show,_store)                 \
+ struct brport_attribute brport_attr_##_name = {               \
+       .attr = {.name = __stringify(_name),                    \
+-               .mode = _mode },                               \
++               .mode = _mode,                                 \
++               .owner = THIS_MODULE, },                       \
+       .show   = _show,                                        \
+       .store  = _store,                                       \
+ };
+diff -Nurb linux-2.6.22-590/net/bridge/netfilter/ebt_ulog.c linux-2.6.22-570/net/bridge/netfilter/ebt_ulog.c
+--- linux-2.6.22-590/net/bridge/netfilter/ebt_ulog.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/netfilter/ebt_ulog.c   2008-01-23 19:15:56.000000000 -0500
+@@ -301,9 +301,8 @@
+               spin_lock_init(&ulog_buffers[i].lock);
        }
  
--      ret = xt_register_table(table, &bootstrap, newinfo);
-+      ret = xt_register_table(&init_net, table, &bootstrap, newinfo);
-       if (ret != 0) {
-               xt_free_table_info(newinfo);
-               return ret;
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/arptable_filter.c linux-2.6.22-590/net/ipv4/netfilter/arptable_filter.c
---- linux-2.6.22-570/net/ipv4/netfilter/arptable_filter.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/arptable_filter.c      2008-01-02 13:56:38.000000000 -0500
-@@ -61,6 +61,10 @@
-                             const struct net_device *out,
-                             int (*okfn)(struct sk_buff *))
+-      ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG,
+-                                        EBT_ULOG_MAXNLGROUPS, NULL, NULL,
+-                                        THIS_MODULE);
++      ebtulognl = netlink_kernel_create(NETLINK_NFLOG, EBT_ULOG_MAXNLGROUPS,
++                                        NULL, NULL, THIS_MODULE);
+       if (!ebtulognl)
+               ret = -ENOMEM;
+       else if ((ret = ebt_register_watcher(&ulog)))
+diff -Nurb linux-2.6.22-590/net/bridge/netfilter/ebtable_filter.c linux-2.6.22-570/net/bridge/netfilter/ebtable_filter.c
+--- linux-2.6.22-590/net/bridge/netfilter/ebtable_filter.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/netfilter/ebtable_filter.c     2007-07-08 19:32:17.000000000 -0400
+@@ -64,10 +64,6 @@
+ ebt_hook (unsigned int hook, struct sk_buff **pskb, const struct net_device *in,
+    const struct net_device *out, int (*okfn)(struct sk_buff *))
  {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       return arpt_do_table(pskb, hook, in, out, &packet_filter);
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
+       return ebt_do_table(hook, pskb, in, out, &frame_filter);
  }
  
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/ip_queue.c linux-2.6.22-590/net/ipv4/netfilter/ip_queue.c
---- linux-2.6.22-570/net/ipv4/netfilter/ip_queue.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/ip_queue.c     2008-01-02 13:56:38.000000000 -0500
-@@ -26,6 +26,7 @@
- #include <linux/mutex.h>
+diff -Nurb linux-2.6.22-590/net/bridge/netfilter/ebtable_nat.c linux-2.6.22-570/net/bridge/netfilter/ebtable_nat.c
+--- linux-2.6.22-590/net/bridge/netfilter/ebtable_nat.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/netfilter/ebtable_nat.c        2007-07-08 19:32:17.000000000 -0400
+@@ -64,10 +64,6 @@
+ ebt_nat_dst(unsigned int hook, struct sk_buff **pskb, const struct net_device *in
+    , const struct net_device *out, int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
+       return ebt_do_table(hook, pskb, in, out, &frame_nat);
+ }
+@@ -75,10 +71,6 @@
+ ebt_nat_src(unsigned int hook, struct sk_buff **pskb, const struct net_device *in
+    , const struct net_device *out, int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
+       return ebt_do_table(hook, pskb, in, out, &frame_nat);
+ }
+diff -Nurb linux-2.6.22-590/net/bridge/netfilter/ebtables.c linux-2.6.22-570/net/bridge/netfilter/ebtables.c
+--- linux-2.6.22-590/net/bridge/netfilter/ebtables.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/bridge/netfilter/ebtables.c   2007-07-08 19:32:17.000000000 -0400
+@@ -28,7 +28,6 @@
+ #include <linux/smp.h>
+ #include <linux/cpumask.h>
  #include <net/sock.h>
- #include <net/route.h>
-+#include <net/net_namespace.h>
+-#include <net/net_namespace.h>
+ /* needed for logical [in,out]-dev filtering */
+ #include "../br_private.h"
  
- #define IPQ_QMAX_DEFAULT 1024
- #define IPQ_PROC_FS_NAME "ip_queue"
-@@ -556,6 +557,9 @@
+@@ -1439,9 +1438,6 @@
  {
-       struct net_device *dev = ptr;
+       int ret;
  
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       /* Drop any packets associated with the downed device */
-       if (event == NETDEV_DOWN)
-               ipq_dev_drop(dev->ifindex);
-@@ -575,7 +579,7 @@
-       if (event == NETLINK_URELEASE &&
-           n->protocol == NETLINK_FIREWALL && n->pid) {
-               write_lock_bh(&queue_lock);
--              if (n->pid == peer_pid)
-+              if ((n->net == &init_net) && (n->pid == peer_pid))
-                       __ipq_reset();
-               write_unlock_bh(&queue_lock);
-       }
-@@ -667,14 +671,14 @@
-       struct proc_dir_entry *proc;
+-      if (sk->sk_net != &init_net)
+-              return -ENOPROTOOPT;
+-
+       switch(cmd) {
+       case EBT_SO_SET_ENTRIES:
+               ret = do_replace(user, len);
+@@ -1461,9 +1457,6 @@
+       struct ebt_replace tmp;
+       struct ebt_table *t;
  
-       netlink_register_notifier(&ipq_nl_notifier);
--      ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
--                                    NULL, THIS_MODULE);
-+      ipqnl = netlink_kernel_create(&init_net, NETLINK_FIREWALL, 0,
-+                                    ipq_rcv_sk, NULL, THIS_MODULE);
-       if (ipqnl == NULL) {
-               printk(KERN_ERR "ip_queue: failed to create netlink socket\n");
-               goto cleanup_netlink_notifier;
-       }
+-      if (sk->sk_net != &init_net)
+-              return -ENOPROTOOPT;
+-
+       if (copy_from_user(&tmp, user, sizeof(tmp)))
+               return -EFAULT;
  
--      proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ipq_get_info);
-+      proc = proc_net_create(&init_net, IPQ_PROC_FS_NAME, 0, ipq_get_info);
-       if (proc)
-               proc->owner = THIS_MODULE;
-       else {
-@@ -695,8 +699,7 @@
- cleanup_sysctl:
-       unregister_sysctl_table(ipq_sysctl_header);
-       unregister_netdevice_notifier(&ipq_dev_notifier);
--      proc_net_remove(IPQ_PROC_FS_NAME);
+diff -Nurb linux-2.6.22-590/net/core/Makefile linux-2.6.22-570/net/core/Makefile
+--- linux-2.6.22-590/net/core/Makefile 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/Makefile 2007-07-08 19:32:17.000000000 -0400
+@@ -3,7 +3,7 @@
+ #
+ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
+-       gen_stats.o gen_estimator.o net_namespace.o
++       gen_stats.o gen_estimator.o
+ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
+diff -Nurb linux-2.6.22-590/net/core/dev.c linux-2.6.22-570/net/core/dev.c
+--- linux-2.6.22-590/net/core/dev.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/dev.c    2008-01-23 19:16:05.000000000 -0500
+@@ -116,7 +116,6 @@
+ #include <linux/dmaengine.h>
+ #include <linux/err.h>
+ #include <linux/ctype.h>
+-#include <net/net_namespace.h>
+ #include <linux/if_arp.h>
+ #include <linux/vs_inet.h>
+@@ -153,22 +152,9 @@
+ static struct list_head ptype_all __read_mostly;      /* Taps */
+ #ifdef CONFIG_NET_DMA
+-struct net_dma {
+-      struct dma_client client;
+-      spinlock_t lock;
+-      cpumask_t channel_mask;
+-      struct dma_chan *channels[NR_CPUS];
+-};
 -
-+      proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
- cleanup_ipqnl:
-       sock_release(ipqnl->sk_socket);
-       mutex_lock(&ipqnl_mutex);
-@@ -715,7 +718,7 @@
+-static enum dma_state_client
+-netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
+-      enum dma_state state);
+-
+-static struct net_dma net_dma = {
+-      .client = {
+-              .event_callback = netdev_dma_event,
+-      },
+-};
++static struct dma_client *net_dma_client;
++static unsigned int net_dma_count;
++static spinlock_t net_dma_event_lock;
+ #endif
  
-       unregister_sysctl_table(ipq_sysctl_header);
-       unregister_netdevice_notifier(&ipq_dev_notifier);
--      proc_net_remove(IPQ_PROC_FS_NAME);
-+      proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
+ /*
+@@ -190,50 +176,25 @@
+  * unregister_netdevice(), which must be called with the rtnl
+  * semaphore held.
+  */
++LIST_HEAD(dev_base_head);
+ DEFINE_RWLOCK(dev_base_lock);
  
-       sock_release(ipqnl->sk_socket);
-       mutex_lock(&ipqnl_mutex);
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/ip_tables.c linux-2.6.22-590/net/ipv4/netfilter/ip_tables.c
---- linux-2.6.22-570/net/ipv4/netfilter/ip_tables.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/ip_tables.c    2008-01-02 13:56:38.000000000 -0500
-@@ -1039,7 +1039,7 @@
++EXPORT_SYMBOL(dev_base_head);
+ EXPORT_SYMBOL(dev_base_lock);
+ #define NETDEV_HASHBITS       8
+-#define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS)
++static struct hlist_head dev_name_head[1<<NETDEV_HASHBITS];
++static struct hlist_head dev_index_head[1<<NETDEV_HASHBITS];
+-static inline struct hlist_head *dev_name_hash(struct net *net, const char *name)
++static inline struct hlist_head *dev_name_hash(const char *name)
+ {
+       unsigned hash = full_name_hash(name, strnlen(name, IFNAMSIZ));
+-      return &net->dev_name_head[hash & ((1 << NETDEV_HASHBITS) - 1)];
+-}
+-
+-static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)
+-{
+-      return &net->dev_index_head[ifindex & ((1 << NETDEV_HASHBITS) - 1)];
+-}
+-
+-/* Device list insertion */
+-static int list_netdevice(struct net_device *dev)
+-{
+-      struct net *net = dev->nd_net;
+-
+-      ASSERT_RTNL();
+-
+-      write_lock_bh(&dev_base_lock);
+-      list_add_tail(&dev->dev_list, &net->dev_base_head);
+-      hlist_add_head(&dev->name_hlist, dev_name_hash(net, dev->name));
+-      hlist_add_head(&dev->index_hlist, dev_index_hash(net, dev->ifindex));
+-      write_unlock_bh(&dev_base_lock);
+-      return 0;
++      return &dev_name_head[hash & ((1<<NETDEV_HASHBITS)-1)];
  }
- #endif
  
--static int get_info(void __user *user, int *len, int compat)
-+static int get_info(struct net *net, void __user *user, int *len, int compat)
+-/* Device list removal */
+-static void unlist_netdevice(struct net_device *dev)
++static inline struct hlist_head *dev_index_hash(int ifindex)
  {
-       char name[IPT_TABLE_MAXNAMELEN];
-       struct xt_table *t;
-@@ -1059,7 +1059,7 @@
-       if (compat)
-               xt_compat_lock(AF_INET);
- #endif
--      t = try_then_request_module(xt_find_table_lock(AF_INET, name),
-+      t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
-                       "iptable_%s", name);
-       if (t && !IS_ERR(t)) {
-               struct ipt_getinfo info;
-@@ -1099,7 +1099,7 @@
+-      ASSERT_RTNL();
+-
+-      /* Unlink dev from the device chain */
+-      write_lock_bh(&dev_base_lock);
+-      list_del(&dev->dev_list);
+-      hlist_del(&dev->name_hlist);
+-      hlist_del(&dev->index_hlist);
+-      write_unlock_bh(&dev_base_lock);
++      return &dev_index_head[ifindex & ((1<<NETDEV_HASHBITS)-1)];
  }
  
- static int
--get_entries(struct ipt_get_entries __user *uptr, int *len)
-+get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
+ /*
+@@ -516,7 +477,7 @@
+        * If device already registered then return base of 1
+        * to indicate not to probe for this interface
+        */
+-      if (__dev_get_by_name(&init_net, name))
++      if (__dev_get_by_name(name))
+               return 1;
+       for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++)
+@@ -571,11 +532,11 @@
+  *    careful with locks.
+  */
+-struct net_device *__dev_get_by_name(struct net *net, const char *name)
++struct net_device *__dev_get_by_name(const char *name)
  {
-       int ret;
-       struct ipt_get_entries get;
-@@ -1119,7 +1119,7 @@
-               return -EINVAL;
-       }
+       struct hlist_node *p;
  
--      t = xt_find_table_lock(AF_INET, get.name);
-+      t = xt_find_table_lock(net, AF_INET, get.name);
-       if (t && !IS_ERR(t)) {
-               struct xt_table_info *private = t->private;
-               duprintf("t->private->number = %u\n",
-@@ -1142,7 +1142,7 @@
- }
+-      hlist_for_each(p, dev_name_hash(net, name)) {
++      hlist_for_each(p, dev_name_hash(name)) {
+               struct net_device *dev
+                       = hlist_entry(p, struct net_device, name_hlist);
+               if (!strncmp(dev->name, name, IFNAMSIZ))
+@@ -595,12 +556,12 @@
+  *    matching device is found.
+  */
  
- static int
--__do_replace(const char *name, unsigned int valid_hooks,
-+__do_replace(struct net *net, const char *name, unsigned int valid_hooks,
-               struct xt_table_info *newinfo, unsigned int num_counters,
-               void __user *counters_ptr)
+-struct net_device *dev_get_by_name(struct net *net, const char *name)
++struct net_device *dev_get_by_name(const char *name)
  {
-@@ -1159,7 +1159,7 @@
-               goto out;
-       }
+       struct net_device *dev;
  
--      t = try_then_request_module(xt_find_table_lock(AF_INET, name),
-+      t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
-                                   "iptable_%s", name);
-       if (!t || IS_ERR(t)) {
-               ret = t ? PTR_ERR(t) : -ENOENT;
-@@ -1211,7 +1211,7 @@
- }
+       read_lock(&dev_base_lock);
+-      dev = __dev_get_by_name(net, name);
++      dev = __dev_get_by_name(name);
+       if (dev)
+               dev_hold(dev);
+       read_unlock(&dev_base_lock);
+@@ -618,11 +579,11 @@
+  *    or @dev_base_lock.
+  */
  
- static int
--do_replace(void __user *user, unsigned int len)
-+do_replace(struct net *net, void __user *user, unsigned int len)
+-struct net_device *__dev_get_by_index(struct net *net, int ifindex)
++struct net_device *__dev_get_by_index(int ifindex)
  {
-       int ret;
-       struct ipt_replace tmp;
-@@ -1252,7 +1252,7 @@
+       struct hlist_node *p;
  
-       duprintf("ip_tables: Translated table\n");
+-      hlist_for_each(p, dev_index_hash(net, ifindex)) {
++      hlist_for_each(p, dev_index_hash(ifindex)) {
+               struct net_device *dev
+                       = hlist_entry(p, struct net_device, index_hlist);
+               if (dev->ifindex == ifindex)
+@@ -642,12 +603,12 @@
+  *    dev_put to indicate they have finished with it.
+  */
  
--      ret = __do_replace(tmp.name, tmp.valid_hooks,
-+      ret = __do_replace(net, tmp.name, tmp.valid_hooks,
-                             newinfo, tmp.num_counters,
-                             tmp.counters);
-       if (ret)
-@@ -1289,7 +1289,7 @@
- }
+-struct net_device *dev_get_by_index(struct net *net, int ifindex)
++struct net_device *dev_get_by_index(int ifindex)
+ {
+       struct net_device *dev;
  
- static int
--do_add_counters(void __user *user, unsigned int len, int compat)
-+do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
+       read_lock(&dev_base_lock);
+-      dev = __dev_get_by_index(net, ifindex);
++      dev = __dev_get_by_index(ifindex);
+       if (dev)
+               dev_hold(dev);
+       read_unlock(&dev_base_lock);
+@@ -668,13 +629,13 @@
+  *    If the API was consistent this would be __dev_get_by_hwaddr
+  */
+-struct net_device *dev_getbyhwaddr(struct net *net, unsigned short type, char *ha)
++struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
  {
-       unsigned int i;
-       struct xt_counters_info tmp;
-@@ -1341,7 +1341,7 @@
-               goto free;
-       }
+       struct net_device *dev;
  
--      t = xt_find_table_lock(AF_INET, name);
-+      t = xt_find_table_lock(net, AF_INET, name);
-       if (!t || IS_ERR(t)) {
-               ret = t ? PTR_ERR(t) : -ENOENT;
-               goto free;
-@@ -1745,7 +1745,7 @@
- }
+       ASSERT_RTNL();
+-      for_each_netdev(&init_net, dev)
++      for_each_netdev(dev)
+               if (dev->type == type &&
+                   !memcmp(dev->dev_addr, ha, dev->addr_len))
+                       return dev;
+@@ -684,12 +645,12 @@
+ EXPORT_SYMBOL(dev_getbyhwaddr);
  
- static int
--compat_do_replace(void __user *user, unsigned int len)
-+compat_do_replace(struct net *net, void __user *user, unsigned int len)
+-struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short type)
++struct net_device *__dev_getfirstbyhwtype(unsigned short type)
  {
-       int ret;
-       struct compat_ipt_replace tmp;
-@@ -1786,7 +1786,7 @@
+       struct net_device *dev;
  
-       duprintf("compat_do_replace: Translated table\n");
+       ASSERT_RTNL();
+-      for_each_netdev(net, dev)
++      for_each_netdev(dev)
+               if (dev->type == type)
+                       return dev;
  
--      ret = __do_replace(tmp.name, tmp.valid_hooks,
-+      ret = __do_replace(net, tmp.name, tmp.valid_hooks,
-                             newinfo, tmp.num_counters,
-                             compat_ptr(tmp.counters));
-       if (ret)
-@@ -1811,11 +1811,11 @@
+@@ -698,12 +659,12 @@
  
-       switch (cmd) {
-       case IPT_SO_SET_REPLACE:
--              ret = compat_do_replace(user, len);
-+              ret = compat_do_replace(sk->sk_net, user, len);
-               break;
+ EXPORT_SYMBOL(__dev_getfirstbyhwtype);
  
-       case IPT_SO_SET_ADD_COUNTERS:
--              ret = do_add_counters(user, len, 1);
-+              ret = do_add_counters(sk->sk_net, user, len, 1);
-               break;
+-struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type)
++struct net_device *dev_getfirstbyhwtype(unsigned short type)
+ {
+       struct net_device *dev;
  
-       default:
-@@ -1904,7 +1904,7 @@
- }
+       rtnl_lock();
+-      dev = __dev_getfirstbyhwtype(net, type);
++      dev = __dev_getfirstbyhwtype(type);
+       if (dev)
+               dev_hold(dev);
+       rtnl_unlock();
+@@ -723,13 +684,13 @@
+  *    dev_put to indicate they have finished with it.
+  */
  
- static int
--compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
-+compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr, int *len)
+-struct net_device * dev_get_by_flags(struct net *net, unsigned short if_flags, unsigned short mask)
++struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mask)
  {
-       int ret;
-       struct compat_ipt_get_entries get;
-@@ -1928,7 +1928,7 @@
-       }
-       xt_compat_lock(AF_INET);
--      t = xt_find_table_lock(AF_INET, get.name);
-+      t = xt_find_table_lock(net, AF_INET, get.name);
-       if (t && !IS_ERR(t)) {
-               struct xt_table_info *private = t->private;
-               struct xt_table_info info;
-@@ -1966,10 +1966,10 @@
+       struct net_device *dev, *ret;
  
-       switch (cmd) {
-       case IPT_SO_GET_INFO:
--              ret = get_info(user, len, 1);
-+              ret = get_info(sk->sk_net, user, len, 1);
-               break;
-       case IPT_SO_GET_ENTRIES:
--              ret = compat_get_entries(user, len);
-+              ret = compat_get_entries(sk->sk_net, user, len);
-               break;
-       default:
-               ret = do_ipt_get_ctl(sk, cmd, user, len);
-@@ -1988,11 +1988,11 @@
+       ret = NULL;
+       read_lock(&dev_base_lock);
+-      for_each_netdev(net, dev) {
++      for_each_netdev(dev) {
+               if (((dev->flags ^ if_flags) & mask) == 0) {
+                       dev_hold(dev);
+                       ret = dev;
+@@ -766,10 +727,9 @@
+ }
  
-       switch (cmd) {
-       case IPT_SO_SET_REPLACE:
--              ret = do_replace(user, len);
-+              ret = do_replace(sk->sk_net, user, len);
-               break;
+ /**
+- *    __dev_alloc_name - allocate a name for a device
+- *    @net: network namespace to allocate the device name in
++ *    dev_alloc_name - allocate a name for a device
++ *    @dev: device
+  *    @name: name format string
+- *    @buf:  scratch buffer and result name string
+  *
+  *    Passed a format string - eg "lt%d" it will try and find a suitable
+  *    id. It scans list of devices to build up a free map, then chooses
+@@ -780,9 +740,10 @@
+  *    Returns the number of the unit assigned or a negative errno code.
+  */
  
-       case IPT_SO_SET_ADD_COUNTERS:
--              ret = do_add_counters(user, len, 0);
-+              ret = do_add_counters(sk->sk_net, user, len, 0);
-               break;
+-static int __dev_alloc_name(struct net *net, const char *name, char *buf)
++int dev_alloc_name(struct net_device *dev, const char *name)
+ {
+       int i = 0;
++      char buf[IFNAMSIZ];
+       const char *p;
+       const int max_netdevices = 8*PAGE_SIZE;
+       long *inuse;
+@@ -803,14 +764,14 @@
+               if (!inuse)
+                       return -ENOMEM;
  
-       default:
-@@ -2013,11 +2013,11 @@
+-              for_each_netdev(net, d) {
++              for_each_netdev(d) {
+                       if (!sscanf(d->name, name, &i))
+                               continue;
+                       if (i < 0 || i >= max_netdevices)
+                               continue;
  
-       switch (cmd) {
-       case IPT_SO_GET_INFO:
--              ret = get_info(user, len, 0);
-+              ret = get_info(sk->sk_net, user, len, 0);
-               break;
+                       /*  avoid cases where sscanf is not exact inverse of printf */
+-                      snprintf(buf, IFNAMSIZ, name, i);
++                      snprintf(buf, sizeof(buf), name, i);
+                       if (!strncmp(buf, d->name, IFNAMSIZ))
+                               set_bit(i, inuse);
+               }
+@@ -819,9 +780,11 @@
+               free_page((unsigned long) inuse);
+       }
  
-       case IPT_SO_GET_ENTRIES:
--              ret = get_entries(user, len);
-+              ret = get_entries(sk->sk_net, user, len);
-               break;
+-      snprintf(buf, IFNAMSIZ, name, i);
+-      if (!__dev_get_by_name(net, buf))
++      snprintf(buf, sizeof(buf), name, i);
++      if (!__dev_get_by_name(buf)) {
++              strlcpy(dev->name, buf, IFNAMSIZ);
+               return i;
++      }
  
-       case IPT_SO_GET_REVISION_MATCH:
-@@ -2054,7 +2054,7 @@
-       return ret;
+       /* It is possible to run out of possible slots
+        * when the name is long and there isn't enough space left
+@@ -830,34 +793,6 @@
+       return -ENFILE;
  }
  
--int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
-+int ipt_register_table(struct net *net, struct xt_table *table, const struct ipt_replace *repl)
+-/**
+- *    dev_alloc_name - allocate a name for a device
+- *    @dev: device
+- *    @name: name format string
+- *
+- *    Passed a format string - eg "lt%d" it will try and find a suitable
+- *    id. It scans list of devices to build up a free map, then chooses
+- *    the first empty slot. The caller must hold the dev_base or rtnl lock
+- *    while allocating the name and adding the device in order to avoid
+- *    duplicates.
+- *    Limited to bits_per_byte * page size devices (ie 32K on most platforms).
+- *    Returns the number of the unit assigned or a negative errno code.
+- */
+-
+-int dev_alloc_name(struct net_device *dev, const char *name)
+-{
+-      char buf[IFNAMSIZ];
+-      struct net *net;
+-      int ret;
+-
+-      BUG_ON(!dev->nd_net);
+-      net = dev->nd_net;
+-      ret = __dev_alloc_name(net, name, buf);
+-      if (ret >= 0)
+-              strlcpy(dev->name, buf, IFNAMSIZ);
+-      return ret;
+-}
+-
+ /**
+  *    dev_change_name - change name of a device
+@@ -870,12 +805,9 @@
+ int dev_change_name(struct net_device *dev, char *newname)
  {
-       int ret;
-       struct xt_table_info *newinfo;
-@@ -2082,7 +2082,7 @@
-               return ret;
-       }
+       int err = 0;
+-      struct net *net;
  
--      ret = xt_register_table(table, &bootstrap, newinfo);
-+      ret = xt_register_table(net, table, &bootstrap, newinfo);
-       if (ret != 0) {
-               xt_free_table_info(newinfo);
-               return ret;
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/ipt_CLUSTERIP.c linux-2.6.22-590/net/ipv4/netfilter/ipt_CLUSTERIP.c
---- linux-2.6.22-570/net/ipv4/netfilter/ipt_CLUSTERIP.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/ipt_CLUSTERIP.c        2008-01-02 13:56:38.000000000 -0500
-@@ -27,6 +27,7 @@
- #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
- #include <net/netfilter/nf_conntrack.h>
- #include <net/checksum.h>
-+#include <net/net_namespace.h>
+       ASSERT_RTNL();
+-      BUG_ON(!dev->nd_net);
  
- #define CLUSTERIP_VERSION "0.8"
+-      net = dev->nd_net;
+       if (dev->flags & IFF_UP)
+               return -EBUSY;
  
-@@ -427,7 +428,7 @@
-                               return 0;
-                       }
+@@ -888,18 +820,14 @@
+                       return err;
+               strcpy(newname, dev->name);
+       }
+-      else if (__dev_get_by_name(net, newname))
++      else if (__dev_get_by_name(newname))
+               return -EEXIST;
+-      else {
+-              if (strncmp(newname, dev->name, IFNAMSIZ))
+-                      printk(KERN_INFO "%s renamed to %s\n",
+-                                      dev->name, newname);
++      else
+               strlcpy(dev->name, newname, IFNAMSIZ);
+-      }
  
--                      dev = dev_get_by_name(e->ip.iniface);
-+                      dev = dev_get_by_name(&init_net, e->ip.iniface);
-                       if (!dev) {
-                               printk(KERN_WARNING "CLUSTERIP: no such interface %s\n", e->ip.iniface);
-                               return 0;
-@@ -523,6 +524,10 @@
-       struct arp_payload *payload;
-       struct clusterip_config *c;
+       device_rename(&dev->dev, dev->name);
+       hlist_del(&dev->name_hlist);
+-      hlist_add_head(&dev->name_hlist, dev_name_hash(net, dev->name));
++      hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
+       raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
  
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       /* we don't care about non-ethernet and non-ipv4 ARP */
-       if (arp->ar_hrd != htons(ARPHRD_ETHER)
-           || arp->ar_pro != htons(ETH_P_IP)
-@@ -735,7 +740,7 @@
-               goto cleanup_target;
+       return err;
+@@ -943,12 +871,12 @@
+  *    available in this kernel then it becomes a nop.
+  */
  
- #ifdef CONFIG_PROC_FS
--      clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net);
-+      clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", init_net.proc_net);
-       if (!clusterip_procdir) {
-               printk(KERN_ERR "CLUSTERIP: Unable to proc dir entry\n");
-               ret = -ENOMEM;
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/ipt_MASQUERADE.c linux-2.6.22-590/net/ipv4/netfilter/ipt_MASQUERADE.c
---- linux-2.6.22-570/net/ipv4/netfilter/ipt_MASQUERADE.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/ipt_MASQUERADE.c       2008-01-02 13:56:38.000000000 -0500
-@@ -131,6 +131,9 @@
+-void dev_load(struct net *net, const char *name)
++void dev_load(const char *name)
  {
-       struct net_device *dev = ptr;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (event == NETDEV_DOWN) {
-               /* Device was downed.  Search entire table for
-                  conntracks which were associated with that device,
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/ipt_REJECT.c linux-2.6.22-590/net/ipv4/netfilter/ipt_REJECT.c
---- linux-2.6.22-570/net/ipv4/netfilter/ipt_REJECT.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/ipt_REJECT.c   2008-01-02 13:56:38.000000000 -0500
-@@ -137,7 +137,7 @@
-          )
-               addr_type = RTN_LOCAL;
+       struct net_device *dev;
  
--      if (ip_route_me_harder(&nskb, addr_type))
-+      if (ip_route_me_harder(&init_net, &nskb, addr_type))
-               goto free_nskb;
+       read_lock(&dev_base_lock);
+-      dev = __dev_get_by_name(net, name);
++      dev = __dev_get_by_name(name);
+       read_unlock(&dev_base_lock);
  
-       nskb->ip_summed = CHECKSUM_NONE;
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/ipt_ULOG.c linux-2.6.22-590/net/ipv4/netfilter/ipt_ULOG.c
---- linux-2.6.22-570/net/ipv4/netfilter/ipt_ULOG.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/ipt_ULOG.c     2008-01-02 13:56:38.000000000 -0500
-@@ -419,7 +419,8 @@
-       for (i = 0; i < ULOG_MAXNLGROUPS; i++)
-               setup_timer(&ulog_buffers[i].timer, ulog_timer, i);
+       if (!dev && capable(CAP_SYS_MODULE))
+@@ -1091,8 +1019,6 @@
+ }
  
--      nflognl = netlink_kernel_create(NETLINK_NFLOG, ULOG_MAXNLGROUPS, NULL,
-+      nflognl = netlink_kernel_create(&init_net,
-+                                      NETLINK_NFLOG, ULOG_MAXNLGROUPS, NULL,
-                                       NULL, THIS_MODULE);
-       if (!nflognl)
-               return -ENOMEM;
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.22-590/net/ipv4/netfilter/ipt_addrtype.c
---- linux-2.6.22-570/net/ipv4/netfilter/ipt_addrtype.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/ipt_addrtype.c 2008-01-02 13:56:38.000000000 -0500
-@@ -24,7 +24,7 @@
  
- static inline int match_type(__be32 addr, u_int16_t mask)
- {
--      return !!(mask & (1 << inet_addr_type(addr)));
-+      return !!(mask & (1 << inet_addr_type(&init_net, addr)));
- }
+-static int dev_boot_phase = 1;
+-
+ /*
+  *    Device change register/unregister. These are not inline or static
+  *    as we export them to the world.
+@@ -1119,17 +1045,14 @@
  
- static int match(const struct sk_buff *skb,
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/ipt_recent.c linux-2.6.22-590/net/ipv4/netfilter/ipt_recent.c
---- linux-2.6.22-570/net/ipv4/netfilter/ipt_recent.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/ipt_recent.c   2008-01-02 13:56:38.000000000 -0500
-@@ -24,6 +24,7 @@
- #include <linux/bitops.h>
- #include <linux/skbuff.h>
- #include <linux/inet.h>
-+#include <net/net_namespace.h>
+       rtnl_lock();
+       err = raw_notifier_chain_register(&netdev_chain, nb);
+-      if (!err && !dev_boot_phase) {
+-              struct net *net;
+-              for_each_net(net) {
+-                      for_each_netdev(net, dev) {
++      if (!err) {
++              for_each_netdev(dev) {
+                       nb->notifier_call(nb, NETDEV_REGISTER, dev);
  
- #include <linux/netfilter/x_tables.h>
- #include <linux/netfilter_ipv4/ipt_recent.h>
-@@ -485,7 +486,7 @@
- #ifdef CONFIG_PROC_FS
-       if (err)
-               return err;
--      proc_dir = proc_mkdir("ipt_recent", proc_net);
-+      proc_dir = proc_mkdir("ipt_recent", init_net.proc_net);
-       if (proc_dir == NULL) {
-               xt_unregister_match(&recent_match);
-               err = -ENOMEM;
-@@ -499,7 +500,7 @@
-       BUG_ON(!list_empty(&tables));
-       xt_unregister_match(&recent_match);
- #ifdef CONFIG_PROC_FS
--      remove_proc_entry("ipt_recent", proc_net);
-+      remove_proc_entry("ipt_recent", init_net.proc_net);
- #endif
+                       if (dev->flags & IFF_UP)
+                               nb->notifier_call(nb, NETDEV_UP, dev);
+               }
+       }
+-      }
+       rtnl_unlock();
+       return err;
  }
+@@ -1163,9 +1086,9 @@
+  *    are as for raw_notifier_call_chain().
+  */
  
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/iptable_filter.c linux-2.6.22-590/net/ipv4/netfilter/iptable_filter.c
---- linux-2.6.22-570/net/ipv4/netfilter/iptable_filter.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/iptable_filter.c       2008-01-02 13:56:38.000000000 -0500
-@@ -26,7 +26,7 @@
-       struct ipt_replace repl;
-       struct ipt_standard entries[3];
-       struct ipt_error term;
--} initial_table __initdata = {
-+} initial_table = {
-       .repl = {
-               .name = "filter",
-               .valid_hooks = FILTER_VALID_HOOKS,
-@@ -51,7 +51,7 @@
-       .term = IPT_ERROR_INIT,                 /* ERROR */
- };
--static struct xt_table packet_filter = {
-+static struct xt_table ip_packet_filter_dflt = {
-       .name           = "filter",
-       .valid_hooks    = FILTER_VALID_HOOKS,
-       .lock           = RW_LOCK_UNLOCKED,
-@@ -67,7 +67,9 @@
-        const struct net_device *out,
-        int (*okfn)(struct sk_buff *))
+-int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
++int call_netdevice_notifiers(unsigned long val, void *v)
  {
--      return ipt_do_table(pskb, hook, in, out, &packet_filter);
-+      struct net *net = (in?in:out)->nd_net;
-+
-+      return ipt_do_table(pskb, hook, in, out, net->ip_packet_filter);
+-      return raw_notifier_call_chain(&netdev_chain, val, dev);
++      return raw_notifier_call_chain(&netdev_chain, val, v);
  }
  
- static unsigned int
-@@ -77,6 +79,8 @@
-                  const struct net_device *out,
-                  int (*okfn)(struct sk_buff *))
- {
-+      struct net *net = (in?in:out)->nd_net;
-+
-       /* root is playing with raw sockets. */
-       if ((*pskb)->len < sizeof(struct iphdr)
-           || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
-@@ -86,7 +90,7 @@
-               return NF_ACCEPT;
+ /* When > 0 there are consumers of rx skb time stamps */
+@@ -1587,11 +1510,9 @@
+               skb_set_transport_header(skb, skb->csum_start -
+                                             skb_headroom(skb));
+-              if (!(dev->features & NETIF_F_GEN_CSUM)
+-                  || ((dev->features & NETIF_F_IP_CSUM)
+-                      && skb->protocol == htons(ETH_P_IP))
+-                  || ((dev->features & NETIF_F_IPV6_CSUM)
+-                      && skb->protocol == htons(ETH_P_IPV6)))
++              if (!(dev->features & NETIF_F_GEN_CSUM) &&
++                  (!(dev->features & NETIF_F_IP_CSUM) ||
++                   skb->protocol != htons(ETH_P_IP)))
+                       if (skb_checksum_help(skb))
+                               goto out_kfree_skb;
+       }
+@@ -2095,13 +2016,12 @@
+        * There may not be any more sk_buffs coming right now, so push
+        * any pending DMA copies to hardware
+        */
+-      if (!cpus_empty(net_dma.channel_mask)) {
+-              int chan_idx;
+-              for_each_cpu_mask(chan_idx, net_dma.channel_mask) {
+-                      struct dma_chan *chan = net_dma.channels[chan_idx];
+-                      if (chan)
++      if (net_dma_client) {
++              struct dma_chan *chan;
++              rcu_read_lock();
++              list_for_each_entry_rcu(chan, &net_dma_client->channels, client_node)
+                       dma_async_memcpy_issue_pending(chan);
+-              }
++              rcu_read_unlock();
        }
+ #endif
+       return;
+@@ -2143,7 +2063,7 @@
+  *    match.  --pb
+  */
  
--      return ipt_do_table(pskb, hook, in, out, &packet_filter);
-+      return ipt_do_table(pskb, hook, in, out, net->ip_packet_filter);
- }
+-static int dev_ifname(struct net *net, struct ifreq __user *arg)
++static int dev_ifname(struct ifreq __user *arg)
+ {
+       struct net_device *dev;
+       struct ifreq ifr;
+@@ -2156,7 +2076,7 @@
+               return -EFAULT;
  
- static struct nf_hook_ops ipt_ops[] = {
-@@ -117,6 +121,30 @@
- static int forward = NF_ACCEPT;
- module_param(forward, bool, 0000);
+       read_lock(&dev_base_lock);
+-      dev = __dev_get_by_index(net, ifr.ifr_ifindex);
++      dev = __dev_get_by_index(ifr.ifr_ifindex);
+       if (!dev) {
+               read_unlock(&dev_base_lock);
+               return -ENODEV;
+@@ -2176,7 +2096,7 @@
+  *    Thus we will need a 'compatibility mode'.
+  */
  
-+static int iptable_filter_net_init(struct net *net)
-+{
-+      /* Allocate the table */
-+      net->ip_packet_filter = kmemdup(&ip_packet_filter_dflt,
-+                                      sizeof(*net->ip_packet_filter),
-+                                      GFP_KERNEL);
-+      if (!net->ip_packet_filter)
-+              return -ENOMEM;
-+
-+      /* Register table */
-+      return ipt_register_table(net, net->ip_packet_filter, &initial_table.repl);
-+}
-+
-+static void iptable_filter_net_exit(struct net *net)
-+{
-+      ipt_unregister_table(net->ip_packet_filter);
-+      kfree(net->ip_packet_filter);
-+}
-+
-+static struct pernet_operations iptable_filter_net_ops = {
-+      .init = iptable_filter_net_init,
-+      .exit = iptable_filter_net_exit,
-+};
-+
- static int __init iptable_filter_init(void)
+-static int dev_ifconf(struct net *net, char __user *arg)
++static int dev_ifconf(char __user *arg)
  {
-       int ret;
-@@ -130,7 +158,7 @@
-       initial_table.entries[1].target.verdict = -forward - 1;
+       struct ifconf ifc;
+       struct net_device *dev;
+@@ -2200,7 +2120,7 @@
+        */
  
-       /* Register table */
--      ret = ipt_register_table(&packet_filter, &initial_table.repl);
-+      ret = register_pernet_subsys(&iptable_filter_net_ops);
-       if (ret < 0)
-               return ret;
+       total = 0;
+-      for_each_netdev(net, dev) {
++      for_each_netdev(dev) {
+               if (!nx_dev_visible(current->nx_info, dev))
+                       continue;
+               for (i = 0; i < NPROTO; i++) {
+@@ -2236,7 +2156,6 @@
+  */
+ void *dev_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+-      struct net *net = seq->private;
+       loff_t off;
+       struct net_device *dev;
  
-@@ -142,14 +170,14 @@
-       return ret;
+@@ -2245,7 +2164,7 @@
+               return SEQ_START_TOKEN;
  
-  cleanup_table:
--      ipt_unregister_table(&packet_filter);
-+      unregister_pernet_subsys(&iptable_filter_net_ops);
-       return ret;
- }
+       off = 1;
+-      for_each_netdev(net, dev)
++      for_each_netdev(dev)
+               if (off++ == *pos)
+                       return dev;
  
- static void __exit iptable_filter_fini(void)
+@@ -2254,10 +2173,9 @@
+ void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
-       nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
--      ipt_unregister_table(&packet_filter);
-+      unregister_pernet_subsys(&iptable_filter_net_ops);
+-      struct net *net = seq->private;
+       ++*pos;
+       return v == SEQ_START_TOKEN ?
+-              first_net_device(net) : next_net_device((struct net_device *)v);
++              first_net_device() : next_net_device((struct net_device *)v);
  }
  
- module_init(iptable_filter_init);
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/iptable_mangle.c linux-2.6.22-590/net/ipv4/netfilter/iptable_mangle.c
---- linux-2.6.22-570/net/ipv4/netfilter/iptable_mangle.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/iptable_mangle.c       2008-01-02 13:56:38.000000000 -0500
-@@ -80,6 +80,10 @@
-        const struct net_device *out,
-        int (*okfn)(struct sk_buff *))
+ void dev_seq_stop(struct seq_file *seq, void *v)
+@@ -2356,22 +2274,7 @@
+ static int dev_seq_open(struct inode *inode, struct file *file)
  {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       return ipt_do_table(pskb, hook, in, out, &packet_mangler);
+-      struct seq_file *seq;
+-      int res;
+-      res =  seq_open(file, &dev_seq_ops);
+-      if (!res) {
+-              seq = file->private_data;
+-              seq->private = get_net(PROC_NET(inode));
+-      }
+-      return res;
+-}
+-
+-static int dev_seq_release(struct inode *inode, struct file *file)
+-{
+-      struct seq_file *seq = file->private_data;
+-      struct net *net = seq->private;
+-      put_net(net);
+-      return seq_release(inode, file);
++      return seq_open(file, &dev_seq_ops);
  }
  
-@@ -96,6 +100,10 @@
-       __be32 saddr, daddr;
-       u_int32_t mark;
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       /* root is playing with raw sockets. */
-       if ((*pskb)->len < sizeof(struct iphdr)
-           || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
-@@ -121,7 +129,7 @@
-                   iph->daddr != daddr ||
-                   (*pskb)->mark != mark ||
-                   iph->tos != tos)
--                      if (ip_route_me_harder(pskb, RTN_UNSPEC))
-+                      if (ip_route_me_harder(&init_net, pskb, RTN_UNSPEC))
-                               ret = NF_DROP;
-       }
+ static const struct file_operations dev_seq_fops = {
+@@ -2379,7 +2282,7 @@
+       .open    = dev_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+-      .release = dev_seq_release,
++      .release = seq_release,
+ };
  
-@@ -171,7 +179,7 @@
-       int ret;
+ static const struct seq_operations softnet_seq_ops = {
+@@ -2531,49 +2434,30 @@
+ };
  
-       /* Register table */
--      ret = ipt_register_table(&packet_mangler, &initial_table.repl);
-+      ret = ipt_register_table(&init_net, &packet_mangler, &initial_table.repl);
-       if (ret < 0)
-               return ret;
  
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/iptable_raw.c linux-2.6.22-590/net/ipv4/netfilter/iptable_raw.c
---- linux-2.6.22-570/net/ipv4/netfilter/iptable_raw.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/iptable_raw.c  2008-01-02 13:56:38.000000000 -0500
-@@ -52,6 +52,10 @@
-        const struct net_device *out,
-        int (*okfn)(struct sk_buff *))
+-static int dev_proc_net_init(struct net *net)
++static int __init dev_proc_init(void)
  {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       return ipt_do_table(pskb, hook, in, out, &packet_raw);
- }
+       int rc = -ENOMEM;
  
-@@ -96,7 +100,7 @@
-       int ret;
+-      if (!proc_net_fops_create(net, "dev", S_IRUGO, &dev_seq_fops))
++      if (!proc_net_fops_create("dev", S_IRUGO, &dev_seq_fops))
+               goto out;
+-      if (!proc_net_fops_create(net, "softnet_stat", S_IRUGO, &softnet_seq_fops))
++      if (!proc_net_fops_create("softnet_stat", S_IRUGO, &softnet_seq_fops))
+               goto out_dev;
+-      if (!proc_net_fops_create(net, "ptype", S_IRUGO, &ptype_seq_fops))
+-              goto out_softnet;
++      if (!proc_net_fops_create("ptype", S_IRUGO, &ptype_seq_fops))
++              goto out_dev2;
+-      if (wext_proc_init(net))
+-              goto out_ptype;
++      if (wext_proc_init())
++              goto out_softnet;
+       rc = 0;
+ out:
+       return rc;
+-out_ptype:
+-      proc_net_remove(net, "ptype");
+ out_softnet:
+-      proc_net_remove(net, "softnet_stat");
++      proc_net_remove("ptype");
++out_dev2:
++      proc_net_remove("softnet_stat");
+ out_dev:
+-      proc_net_remove(net, "dev");
++      proc_net_remove("dev");
+       goto out;
+ }
+-
+-static void dev_proc_net_exit(struct net *net)
+-{
+-      wext_proc_exit(net);
+-
+-      proc_net_remove(net, "ptype");
+-      proc_net_remove(net, "softnet_stat");
+-      proc_net_remove(net, "dev");
+-}
+-
+-static struct pernet_operations dev_proc_ops = {
+-      .init = dev_proc_net_init,
+-      .exit = dev_proc_net_exit,
+-};
+-
+-static int __init dev_proc_init(void)
+-{
+-      return register_pernet_subsys(&dev_proc_ops);
+-}
+ #else
+ #define dev_proc_init() 0
+ #endif        /* CONFIG_PROC_FS */
+@@ -2807,10 +2691,10 @@
+ /*
+  *    Perform the SIOCxIFxxx calls.
+  */
+-static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
++static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
+ {
+       int err;
+-      struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
++      struct net_device *dev = __dev_get_by_name(ifr->ifr_name);
  
-       /* Register table */
--      ret = ipt_register_table(&packet_raw, &initial_table.repl);
-+      ret = ipt_register_table(&init_net, &packet_raw, &initial_table.repl);
-       if (ret < 0)
-               return ret;
+       if (!dev)
+               return -ENODEV;
+@@ -2963,7 +2847,7 @@
+  *    positive or a negative errno code on error.
+  */
  
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c linux-2.6.22-590/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
---- linux-2.6.22-570/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c    2008-01-02 13:56:38.000000000 -0500
-@@ -120,6 +120,10 @@
-                                const struct net_device *out,
-                                int (*okfn)(struct sk_buff *))
+-int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
++int dev_ioctl(unsigned int cmd, void __user *arg)
  {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       /* We've seen it coming out the other side: confirm it */
-       return nf_conntrack_confirm(pskb);
- }
-@@ -135,6 +139,10 @@
-       struct nf_conn_help *help;
-       struct nf_conntrack_helper *helper;
+       struct ifreq ifr;
+       int ret;
+@@ -2976,12 +2860,12 @@
  
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       /* This is where we call the helper: as the packet goes out. */
-       ct = nf_ct_get(*pskb, &ctinfo);
-       if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
-@@ -157,6 +165,10 @@
-                                         const struct net_device *out,
-                                         int (*okfn)(struct sk_buff *))
- {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       /* Previously seen (loopback)?  Ignore.  Do this before
-          fragment check. */
-       if ((*pskb)->nfct)
-@@ -180,6 +192,10 @@
-                                     const struct net_device *out,
-                                     int (*okfn)(struct sk_buff *))
- {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       return nf_conntrack_in(PF_INET, hooknum, pskb);
- }
+       if (cmd == SIOCGIFCONF) {
+               rtnl_lock();
+-              ret = dev_ifconf(net, (char __user *) arg);
++              ret = dev_ifconf((char __user *) arg);
+               rtnl_unlock();
+               return ret;
+       }
+       if (cmd == SIOCGIFNAME)
+-              return dev_ifname(net, (struct ifreq __user *)arg);
++              return dev_ifname((struct ifreq __user *)arg);
  
-@@ -189,6 +205,10 @@
-                                        const struct net_device *out,
-                                        int (*okfn)(struct sk_buff *))
- {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       /* root is playing with raw sockets. */
-       if ((*pskb)->len < sizeof(struct iphdr)
-           || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
-@@ -325,6 +345,9 @@
-       struct nf_conntrack_tuple_hash *h;
-       struct nf_conntrack_tuple tuple;
+       if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
+               return -EFAULT;
+@@ -3011,9 +2895,9 @@
+               case SIOCGIFMAP:
+               case SIOCGIFINDEX:
+               case SIOCGIFTXQLEN:
+-                      dev_load(net, ifr.ifr_name);
++                      dev_load(ifr.ifr_name);
+                       read_lock(&dev_base_lock);
+-                      ret = dev_ifsioc(net, &ifr, cmd);
++                      ret = dev_ifsioc(&ifr, cmd);
+                       read_unlock(&dev_base_lock);
+                       if (!ret) {
+                               if (colon)
+@@ -3025,9 +2909,9 @@
+                       return ret;
  
-+      if (sk->sk_net != &init_net)
-+              return -ENOPROTOOPT;
-+
-       NF_CT_TUPLE_U_BLANK(&tuple);
-       tuple.src.u3.ip = inet->rcv_saddr;
-       tuple.src.u.tcp.port = inet->sport;
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c linux-2.6.22-590/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
---- linux-2.6.22-570/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c     2008-01-02 13:56:38.000000000 -0500
-@@ -11,6 +11,7 @@
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/percpu.h>
-+#include <net/net_namespace.h>
+               case SIOCETHTOOL:
+-                      dev_load(net, ifr.ifr_name);
++                      dev_load(ifr.ifr_name);
+                       rtnl_lock();
+-                      ret = dev_ethtool(net, &ifr);
++                      ret = dev_ethtool(&ifr);
+                       rtnl_unlock();
+                       if (!ret) {
+                               if (colon)
+@@ -3049,9 +2933,9 @@
+               case SIOCSIFNAME:
+                       if (!capable(CAP_NET_ADMIN))
+                               return -EPERM;
+-                      dev_load(net, ifr.ifr_name);
++                      dev_load(ifr.ifr_name);
+                       rtnl_lock();
+-                      ret = dev_ifsioc(net, &ifr, cmd);
++                      ret = dev_ifsioc(&ifr, cmd);
+                       rtnl_unlock();
+                       if (!ret) {
+                               if (colon)
+@@ -3090,9 +2974,9 @@
+                       /* fall through */
+               case SIOCBONDSLAVEINFOQUERY:
+               case SIOCBONDINFOQUERY:
+-                      dev_load(net, ifr.ifr_name);
++                      dev_load(ifr.ifr_name);
+                       rtnl_lock();
+-                      ret = dev_ifsioc(net, &ifr, cmd);
++                      ret = dev_ifsioc(&ifr, cmd);
+                       rtnl_unlock();
+                       return ret;
  
- #include <linux/netfilter.h>
- #include <net/netfilter/nf_conntrack_core.h>
-@@ -378,16 +379,16 @@
+@@ -3112,9 +2996,9 @@
+                       if (cmd == SIOCWANDEV ||
+                           (cmd >= SIOCDEVPRIVATE &&
+                            cmd <= SIOCDEVPRIVATE + 15)) {
+-                              dev_load(net, ifr.ifr_name);
++                              dev_load(ifr.ifr_name);
+                               rtnl_lock();
+-                              ret = dev_ifsioc(net, &ifr, cmd);
++                              ret = dev_ifsioc(&ifr, cmd);
+                               rtnl_unlock();
+                               if (!ret && copy_to_user(arg, &ifr,
+                                                        sizeof(struct ifreq)))
+@@ -3123,7 +3007,7 @@
+                       }
+                       /* Take care of Wireless Extensions */
+                       if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
+-                              return wext_handle_ioctl(net, &ifr, cmd, arg);
++                              return wext_handle_ioctl(&ifr, cmd, arg);
+                       return -EINVAL;
+       }
+ }
+@@ -3136,17 +3020,19 @@
+  *    number.  The caller must hold the rtnl semaphore or the
+  *    dev_base_lock to be sure it remains unique.
+  */
+-static int dev_new_index(struct net *net)
++static int dev_new_index(void)
  {
-       struct proc_dir_entry *proc, *proc_exp, *proc_stat;
--      proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
-+      proc = proc_net_fops_create(&init_net, "ip_conntrack", 0440, &ct_file_ops);
-       if (!proc)
-               goto err1;
+       static int ifindex;
+       for (;;) {
+               if (++ifindex <= 0)
+                       ifindex = 1;
+-              if (!__dev_get_by_index(net, ifindex))
++              if (!__dev_get_by_index(ifindex))
+                       return ifindex;
+       }
+ }
  
--      proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
-+      proc_exp = proc_net_fops_create(&init_net, "ip_conntrack_expect", 0440,
-                                       &ip_exp_file_ops);
-       if (!proc_exp)
-               goto err2;
++static int dev_boot_phase = 1;
++
+ /* Delayed registration/unregisteration */
+ static DEFINE_SPINLOCK(net_todo_list_lock);
+ static struct list_head net_todo_list = LIST_HEAD_INIT(net_todo_list);
+@@ -3180,7 +3066,6 @@
+       struct hlist_head *head;
+       struct hlist_node *p;
+       int ret;
+-      struct net *net;
  
--      proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
-+      proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, init_net.proc_net_stat);
-       if (!proc_stat)
-               goto err3;
+       BUG_ON(dev_boot_phase);
+       ASSERT_RTNL();
+@@ -3189,8 +3074,6 @@
  
-@@ -397,16 +398,16 @@
-       return 0;
+       /* When net_device's are persistent, this will be fatal. */
+       BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
+-      BUG_ON(!dev->nd_net);
+-      net = dev->nd_net;
  
- err3:
--      proc_net_remove("ip_conntrack_expect");
-+      proc_net_remove(&init_net, "ip_conntrack_expect");
- err2:
--      proc_net_remove("ip_conntrack");
-+      proc_net_remove(&init_net, "ip_conntrack");
- err1:
-       return -ENOMEM;
- }
+       spin_lock_init(&dev->queue_lock);
+       spin_lock_init(&dev->_xmit_lock);
+@@ -3215,12 +3098,12 @@
+               goto out;
+       }
  
- void __exit nf_conntrack_ipv4_compat_fini(void)
- {
--      remove_proc_entry("ip_conntrack", proc_net_stat);
--      proc_net_remove("ip_conntrack_expect");
--      proc_net_remove("ip_conntrack");
-+      remove_proc_entry("ip_conntrack", init_net.proc_net_stat);
-+      proc_net_remove(&init_net, "ip_conntrack_expect");
-+      proc_net_remove(&init_net, "ip_conntrack");
- }
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/nf_nat_helper.c linux-2.6.22-590/net/ipv4/netfilter/nf_nat_helper.c
---- linux-2.6.22-570/net/ipv4/netfilter/nf_nat_helper.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/nf_nat_helper.c        2008-01-02 13:56:38.000000000 -0500
-@@ -178,7 +178,7 @@
-       datalen = (*pskb)->len - iph->ihl*4;
-       if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
-               if (!(rt->rt_flags & RTCF_LOCAL) &&
--                  (*pskb)->dev->features & NETIF_F_ALL_CSUM) {
-+                  (*pskb)->dev->features & NETIF_F_V4_CSUM) {
-                       (*pskb)->ip_summed = CHECKSUM_PARTIAL;
-                       (*pskb)->csum_start = skb_headroom(*pskb) +
-                                             skb_network_offset(*pskb) +
-@@ -265,7 +265,7 @@
+-      dev->ifindex = dev_new_index(net);
++      dev->ifindex = dev_new_index();
+       if (dev->iflink == -1)
+               dev->iflink = dev->ifindex;
  
-       if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
-               if (!(rt->rt_flags & RTCF_LOCAL) &&
--                  (*pskb)->dev->features & NETIF_F_ALL_CSUM) {
-+                  (*pskb)->dev->features & NETIF_F_V4_CSUM) {
-                       (*pskb)->ip_summed = CHECKSUM_PARTIAL;
-                       (*pskb)->csum_start = skb_headroom(*pskb) +
-                                             skb_network_offset(*pskb) +
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/nf_nat_rule.c linux-2.6.22-590/net/ipv4/netfilter/nf_nat_rule.c
---- linux-2.6.22-570/net/ipv4/netfilter/nf_nat_rule.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/nf_nat_rule.c  2008-01-02 13:56:38.000000000 -0500
-@@ -98,7 +98,10 @@
- static void warn_if_extra_mangle(__be32 dstip, __be32 srcip)
- {
-       static int warned = 0;
--      struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } };
-+      struct flowi fl = {
-+              .fl_net = &init_net,
-+              .nl_u = { .ip4_u = { .daddr = dstip } }
-+      };
-       struct rtable *rt;
+       /* Check for existence of name */
+-      head = dev_name_hash(net, dev->name);
++      head = dev_name_hash(dev->name);
+       hlist_for_each(p, head) {
+               struct net_device *d
+                       = hlist_entry(p, struct net_device, name_hlist);
+@@ -3230,22 +3113,6 @@
+               }
+       }
  
-       if (ip_route_output_key(&rt, &fl) != 0)
-@@ -252,7 +255,7 @@
- {
-       int ret;
+-      /* Fix illegal checksum combinations */
+-      if ((dev->features & NETIF_F_HW_CSUM) &&
+-          (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+-              printk(KERN_NOTICE "%s: mixed HW and IP checksum settings.\n",
+-                     dev->name);
+-              dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
+-      }
+-
+-      if ((dev->features & NETIF_F_NO_CSUM) &&
+-          (dev->features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+-              printk(KERN_NOTICE "%s: mixed no checksumming and other settings.\n",
+-                     dev->name);
+-              dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
+-      }
+-
+-
+       /* Fix illegal SG+CSUM combinations. */
+       if ((dev->features & NETIF_F_SG) &&
+           !(dev->features & NETIF_F_ALL_CSUM)) {
+@@ -3297,8 +3164,12 @@
+       set_bit(__LINK_STATE_PRESENT, &dev->state);
  
--      ret = ipt_register_table(&nat_table, &nat_initial_table.repl);
-+      ret = ipt_register_table(&init_net, &nat_table, &nat_initial_table.repl);
-       if (ret != 0)
-               return ret;
-       ret = xt_register_target(&ipt_snat_reg);
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter/nf_nat_standalone.c linux-2.6.22-590/net/ipv4/netfilter/nf_nat_standalone.c
---- linux-2.6.22-570/net/ipv4/netfilter/nf_nat_standalone.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter/nf_nat_standalone.c    2008-01-02 13:56:38.000000000 -0500
-@@ -83,6 +83,10 @@
-       /* maniptype == SRC for postrouting. */
-       enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
+       dev_init_scheduler(dev);
++      write_lock_bh(&dev_base_lock);
++      list_add_tail(&dev->dev_list, &dev_base_head);
++      hlist_add_head(&dev->name_hlist, head);
++      hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex));
+       dev_hold(dev);
+-      list_netdevice(dev);
++      write_unlock_bh(&dev_base_lock);
  
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       /* We never see fragments: conntrack defrags on pre-routing
-          and local-out, and nf_nat_out protects post-routing. */
-       NF_CT_ASSERT(!(ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)));
-@@ -172,6 +176,10 @@
-       unsigned int ret;
-       __be32 daddr = ip_hdr(*pskb)->daddr;
+       /* Notify protocols, that a new device appeared. */
+       raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
+@@ -3508,7 +3379,6 @@
+       dev = (struct net_device *)
+               (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
+       dev->padded = (char *)dev - (char *)p;
+-      dev->nd_net = &init_net;
  
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
-       if (ret != NF_DROP && ret != NF_STOLEN &&
-           daddr != ip_hdr(*pskb)->daddr) {
-@@ -194,6 +202,10 @@
- #endif
-       unsigned int ret;
+       if (sizeof_priv)
+               dev->priv = netdev_priv(dev);
+@@ -3587,7 +3457,11 @@
+               dev_close(dev);
  
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       /* root is playing with raw sockets. */
-       if ((*pskb)->len < sizeof(struct iphdr) ||
-           ip_hdrlen(*pskb) < sizeof(struct iphdr))
-@@ -227,6 +239,10 @@
-       enum ip_conntrack_info ctinfo;
-       unsigned int ret;
+       /* And unlink it from device chain. */
+-      unlist_netdevice(dev);
++      write_lock_bh(&dev_base_lock);
++      list_del(&dev->dev_list);
++      hlist_del(&dev->name_hlist);
++      hlist_del(&dev->index_hlist);
++      write_unlock_bh(&dev_base_lock);
  
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       /* root is playing with raw sockets. */
-       if ((*pskb)->len < sizeof(struct iphdr) ||
-           ip_hdrlen(*pskb) < sizeof(struct iphdr))
-@@ -239,7 +255,7 @@
+       dev->reg_state = NETREG_UNREGISTERING;
  
-               if (ct->tuplehash[dir].tuple.dst.u3.ip !=
-                   ct->tuplehash[!dir].tuple.src.u3.ip) {
--                      if (ip_route_me_harder(pskb, RTN_UNSPEC))
-+                      if (ip_route_me_harder(&init_net, pskb, RTN_UNSPEC))
-                               ret = NF_DROP;
-               }
- #ifdef CONFIG_XFRM
-@@ -262,6 +278,10 @@
-       struct nf_conn *ct;
-       enum ip_conntrack_info ctinfo;
+@@ -3645,122 +3519,6 @@
  
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       ct = nf_ct_get(*pskb, &ctinfo);
-       if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
-               DEBUGP("nf_nat_standalone: adjusting sequence number\n");
-diff -Nurb linux-2.6.22-570/net/ipv4/netfilter.c linux-2.6.22-590/net/ipv4/netfilter.c
---- linux-2.6.22-570/net/ipv4/netfilter.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/netfilter.c      2008-01-02 13:56:38.000000000 -0500
-@@ -8,7 +8,7 @@
- #include <net/ip.h>
+ EXPORT_SYMBOL(unregister_netdev);
  
- /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
--int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
-+int ip_route_me_harder(struct net *net, struct sk_buff **pskb, unsigned addr_type)
+-/**
+- *    dev_change_net_namespace - move device to different nethost namespace
+- *    @dev: device
+- *    @net: network namespace
+- *    @pat: If not NULL name pattern to try if the current device name
+- *          is already taken in the destination network namespace.
+- *
+- *    This function shuts down a device interface and moves it
+- *    to a new network namespace. On success 0 is returned, on
+- *    a failure a netagive errno code is returned.
+- *
+- *    Callers must hold the rtnl semaphore.
+- */
+-
+-int dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat)
+-{
+-      char buf[IFNAMSIZ];
+-      const char *destname;
+-      int err;
+-
+-      ASSERT_RTNL();
+-
+-      /* Don't allow namespace local devices to be moved. */
+-      err = -EINVAL;
+-      if (dev->features & NETIF_F_NETNS_LOCAL)
+-              goto out;
+-
+-      /* Ensure the device has been registrered */
+-      err = -EINVAL;
+-      if (dev->reg_state != NETREG_REGISTERED)
+-              goto out;
+-      
+-      /* Get out if there is nothing todo */
+-      err = 0;
+-      if (dev->nd_net == net)
+-              goto out;
+-
+-      /* Pick the destination device name, and ensure
+-       * we can use it in the destination network namespace.
+-       */
+-      err = -EEXIST;
+-      destname = dev->name;
+-      if (__dev_get_by_name(net, destname)) {
+-              /* We get here if we can't use the current device name */
+-              if (!pat)
+-                      goto out;
+-              if (!dev_valid_name(pat))
+-                      goto out;
+-              if (strchr(pat, '%')) {
+-                      if (__dev_alloc_name(net, pat, buf) < 0)
+-                              goto out;
+-                      destname = buf;
+-              } else
+-                      destname = pat;
+-              if (__dev_get_by_name(net, destname))
+-                      goto out;
+-      }
+-
+-      /*
+-       * And now a mini version of register_netdevice unregister_netdevice. 
+-       */
+-
+-      /* If device is running close it first. */
+-      if (dev->flags & IFF_UP)
+-              dev_close(dev);
+-
+-      /* And unlink it from device chain */
+-      err = -ENODEV;
+-      unlist_netdevice(dev);
+-      
+-      synchronize_net();
+-      
+-      /* Shutdown queueing discipline. */
+-      dev_shutdown(dev);
+-
+-      /* Notify protocols, that we are about to destroy
+-         this device. They should clean all the things.
+-      */
+-      call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
+-      
+-      /*
+-       *      Flush the multicast chain
+-       */
+-      dev_mc_discard(dev);
+-
+-      /* Actually switch the network namespace */
+-      dev->nd_net = net;
+-      
+-      /* Assign the new device name */
+-      if (destname != dev->name)
+-              strcpy(dev->name, destname);
+-
+-      /* If there is an ifindex conflict assign a new one */
+-      if (__dev_get_by_index(net, dev->ifindex)) {
+-              int iflink = (dev->iflink == dev->ifindex);
+-              dev->ifindex = dev_new_index(net);
+-              if (iflink)
+-                      dev->iflink = dev->ifindex;
+-      }
+-
+-      /* Fixup sysfs */
+-      err = device_rename(&dev->dev, dev->name);
+-      BUG_ON(err);
+-
+-      /* Add the device back in the hashes */
+-      list_netdevice(dev);
+-
+-      /* Notify protocols, that a new device appeared. */
+-      call_netdevice_notifiers(NETDEV_REGISTER, dev);
+-
+-      synchronize_net();
+-      err = 0;
+-out:
+-      return err;
+-}
+-
+ static int dev_cpu_callback(struct notifier_block *nfb,
+                           unsigned long action,
+                           void *ocpu)
+@@ -3811,13 +3569,12 @@
+  * This is called when the number of channels allocated to the net_dma_client
+  * changes.  The net_dma_client tries to have one DMA channel per CPU.
+  */
+-
+-static void net_dma_rebalance(struct net_dma *net_dma)
++static void net_dma_rebalance(void)
  {
-       const struct iphdr *iph = ip_hdr(*pskb);
-       struct rtable *rt;
-@@ -17,7 +17,8 @@
-       unsigned int hh_len;
-       unsigned int type;
+-      unsigned int cpu, i, n, chan_idx;
++      unsigned int cpu, i, n;
+       struct dma_chan *chan;
  
--      type = inet_addr_type(iph->saddr);
-+      fl.fl_net = net;
-+      type = inet_addr_type(net, iph->saddr);
-       if (addr_type == RTN_UNSPEC)
-               addr_type = type;
+-      if (cpus_empty(net_dma->channel_mask)) {
++      if (net_dma_count == 0) {
+               for_each_online_cpu(cpu)
+                       rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL);
+               return;
+@@ -3826,12 +3583,10 @@
+       i = 0;
+       cpu = first_cpu(cpu_online_map);
  
-@@ -155,12 +156,13 @@
-       const struct ip_rt_info *rt_info = nf_info_reroute(info);
+-      for_each_cpu_mask(chan_idx, net_dma->channel_mask) {
+-              chan = net_dma->channels[chan_idx];
+-
+-              n = ((num_online_cpus() / cpus_weight(net_dma->channel_mask))
+-                 + (i < (num_online_cpus() %
+-                      cpus_weight(net_dma->channel_mask)) ? 1 : 0));
++      rcu_read_lock();
++      list_for_each_entry(chan, &net_dma_client->channels, client_node) {
++              n = ((num_online_cpus() / net_dma_count)
++                 + (i < (num_online_cpus() % net_dma_count) ? 1 : 0));
  
-       if (info->hook == NF_IP_LOCAL_OUT) {
-+              struct net *net = (info->indev?info->indev:info->outdev)->nd_net;
-               const struct iphdr *iph = ip_hdr(*pskb);
+               while(n) {
+                       per_cpu(softnet_data, cpu).net_dma = chan;
+@@ -3840,6 +3595,7 @@
+               }
+               i++;
+       }
++      rcu_read_unlock();
+ }
  
-               if (!(iph->tos == rt_info->tos
-                     && iph->daddr == rt_info->daddr
-                     && iph->saddr == rt_info->saddr))
--                      return ip_route_me_harder(pskb, RTN_UNSPEC);
-+                      return ip_route_me_harder(net, pskb, RTN_UNSPEC);
+ /**
+@@ -3848,53 +3604,23 @@
+  * @chan: DMA channel for the event
+  * @event: event type
+  */
+-static enum dma_state_client
+-netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
+-      enum dma_state state)
+-{
+-      int i, found = 0, pos = -1;
+-      struct net_dma *net_dma =
+-              container_of(client, struct net_dma, client);
+-      enum dma_state_client ack = DMA_DUP; /* default: take no action */
+-
+-      spin_lock(&net_dma->lock);
+-      switch (state) {
+-      case DMA_RESOURCE_AVAILABLE:
+-              for (i = 0; i < NR_CPUS; i++)
+-                      if (net_dma->channels[i] == chan) {
+-                              found = 1;
+-                              break;
+-                      } else if (net_dma->channels[i] == NULL && pos < 0)
+-                              pos = i;
+-
+-              if (!found && pos >= 0) {
+-                      ack = DMA_ACK;
+-                      net_dma->channels[pos] = chan;
+-                      cpu_set(pos, net_dma->channel_mask);
+-                      net_dma_rebalance(net_dma);
+-              }
++static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
++      enum dma_event event)
++{
++      spin_lock(&net_dma_event_lock);
++      switch (event) {
++      case DMA_RESOURCE_ADDED:
++              net_dma_count++;
++              net_dma_rebalance();
+               break;
+       case DMA_RESOURCE_REMOVED:
+-              for (i = 0; i < NR_CPUS; i++)
+-                      if (net_dma->channels[i] == chan) {
+-                              found = 1;
+-                              pos = i;
+-                              break;
+-                      }
+-
+-              if (found) {
+-                      ack = DMA_ACK;
+-                      cpu_clear(pos, net_dma->channel_mask);
+-                      net_dma->channels[i] = NULL;
+-                      net_dma_rebalance(net_dma);
+-              }
++              net_dma_count--;
++              net_dma_rebalance();
+               break;
+       default:
+               break;
        }
-       return 0;
+-      spin_unlock(&net_dma->lock);
+-
+-      return ack;
++      spin_unlock(&net_dma_event_lock);
  }
-diff -Nurb linux-2.6.22-570/net/ipv4/proc.c linux-2.6.22-590/net/ipv4/proc.c
---- linux-2.6.22-570/net/ipv4/proc.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/proc.c   2008-01-02 13:56:38.000000000 -0500
-@@ -44,6 +44,7 @@
- #include <linux/seq_file.h>
- #include <net/sock.h>
- #include <net/raw.h>
-+#include <net/net_namespace.h>
  
- static int fold_prot_inuse(struct proto *proto)
+ /**
+@@ -3902,10 +3628,12 @@
+  */
+ static int __init netdev_dma_register(void)
  {
-@@ -69,8 +70,9 @@
-       seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot));
-       seq_printf(seq, "UDPLITE: inuse %d\n", fold_prot_inuse(&udplite_prot));
-       seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot));
--      seq_printf(seq,  "FRAG: inuse %d memory %d\n", ip_frag_nqueues,
--                 atomic_read(&ip_frag_mem));
-+      seq_printf(seq,  "FRAG: inuse %d memory %d\n", 
-+                 init_net.ip_frag_nqueues,
-+                 atomic_read(&init_net.ip_frag_mem));
+-      spin_lock_init(&net_dma.lock);
+-      dma_cap_set(DMA_MEMCPY, net_dma.client.cap_mask);
+-      dma_async_client_register(&net_dma.client);
+-      dma_async_client_chan_request(&net_dma.client);
++      spin_lock_init(&net_dma_event_lock);
++      net_dma_client = dma_async_client_register(netdev_dma_event);
++      if (net_dma_client == NULL)
++              return -ENOMEM;
++
++      dma_async_client_chan_request(net_dma_client, num_online_cpus());
        return 0;
  }
  
-@@ -260,7 +262,8 @@
-               seq_printf(seq, " %s", snmp4_ipstats_list[i].name);
-       seq_printf(seq, "\nIp: %d %d",
--                 IPV4_DEVCONF_ALL(FORWARDING) ? 1 : 2, sysctl_ip_default_ttl);
-+                 IPV4_DEVCONF_ALL(&init_net, FORWARDING) ? 1 : 2,
-+                 init_net.sysctl_ip_default_ttl);
+@@ -3951,75 +3679,6 @@
+ }
+ EXPORT_SYMBOL(netdev_compute_features);
  
-       for (i = 0; snmp4_ipstats_list[i].name != NULL; i++)
-               seq_printf(seq, " %lu",
-@@ -380,20 +383,20 @@
- {
-       int rc = 0;
+-/* Initialize per network namespace state */
+-static int netdev_init(struct net *net)
+-{
+-      int i;
+-      INIT_LIST_HEAD(&net->dev_base_head);
+-      rwlock_init(&dev_base_lock);
+-
+-      net->dev_name_head = kmalloc(
+-              sizeof(*net->dev_name_head)*NETDEV_HASHENTRIES, GFP_KERNEL);
+-      if (!net->dev_name_head)
+-              return -ENOMEM;
+-
+-      net->dev_index_head = kmalloc(
+-              sizeof(*net->dev_index_head)*NETDEV_HASHENTRIES, GFP_KERNEL);
+-      if (!net->dev_index_head) {
+-              kfree(net->dev_name_head);
+-              return -ENOMEM;
+-      }
+-
+-      for (i = 0; i < NETDEV_HASHENTRIES; i++)
+-              INIT_HLIST_HEAD(&net->dev_name_head[i]);
+-      
+-      for (i = 0; i < NETDEV_HASHENTRIES; i++)
+-              INIT_HLIST_HEAD(&net->dev_index_head[i]);
+-
+-      return 0;
+-}
+-
+-static void netdev_exit(struct net *net)
+-{
+-      kfree(net->dev_name_head);
+-      kfree(net->dev_index_head);
+-}
+-
+-static struct pernet_operations netdev_net_ops = {
+-      .init = netdev_init,
+-      .exit = netdev_exit,
+-};
+-
+-static void default_device_exit(struct net *net)
+-{
+-      struct net_device *dev, *next;
+-      /*
+-       * Push all migratable of the network devices back to the
+-       * initial network namespace 
+-       */
+-      rtnl_lock();
+-      for_each_netdev_safe(net, dev, next) {
+-              int err;
+-
+-              /* Ignore unmoveable devices (i.e. loopback) */
+-              if (dev->features & NETIF_F_NETNS_LOCAL)
+-                      continue;
+-
+-              /* Push remaing network devices to init_net */
+-              err = dev_change_net_namespace(dev, &init_net, "dev%d");
+-              if (err) {
+-                      printk(KERN_WARNING "%s: failed to move %s to init_net: %d\n",
+-                              __func__, dev->name, err);
+-                      unregister_netdevice(dev);
+-              }
+-      }
+-      rtnl_unlock();
+-}
+-
+-static struct pernet_operations default_device_ops = {
+-      .exit = default_device_exit,
+-};
+-
+ /*
+  *    Initialize the DEV module. At boot time this walks the device list and
+  *    unhooks any devices that fail to initialise (normally hardware not
+@@ -4047,11 +3706,11 @@
+       for (i = 0; i < 16; i++)
+               INIT_LIST_HEAD(&ptype_base[i]);
  
--      if (!proc_net_fops_create("netstat", S_IRUGO, &netstat_seq_fops))
-+      if (!proc_net_fops_create(&init_net, "netstat", S_IRUGO, &netstat_seq_fops))
-               goto out_netstat;
+-      if (register_pernet_subsys(&netdev_net_ops))
+-              goto out;
++      for (i = 0; i < ARRAY_SIZE(dev_name_head); i++)
++              INIT_HLIST_HEAD(&dev_name_head[i]);
  
--      if (!proc_net_fops_create("snmp", S_IRUGO, &snmp_seq_fops))
-+      if (!proc_net_fops_create(&init_net, "snmp", S_IRUGO, &snmp_seq_fops))
-               goto out_snmp;
+-      if (register_pernet_device(&default_device_ops))
+-              goto out;
++      for (i = 0; i < ARRAY_SIZE(dev_index_head); i++)
++              INIT_HLIST_HEAD(&dev_index_head[i]);
  
--      if (!proc_net_fops_create("sockstat", S_IRUGO, &sockstat_seq_fops))
-+      if (!proc_net_fops_create(&init_net, "sockstat", S_IRUGO, &sockstat_seq_fops))
-               goto out_sockstat;
- out:
-       return rc;
- out_sockstat:
--      proc_net_remove("snmp");
-+      proc_net_remove(&init_net, "snmp");
- out_snmp:
--      proc_net_remove("netstat");
-+      proc_net_remove(&init_net, "netstat");
- out_netstat:
-       rc = -ENOMEM;
-       goto out;
-diff -Nurb linux-2.6.22-570/net/ipv4/raw.c linux-2.6.22-590/net/ipv4/raw.c
---- linux-2.6.22-570/net/ipv4/raw.c    2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/raw.c    2008-01-02 13:56:38.000000000 -0500
-@@ -73,6 +73,7 @@
- #include <net/inet_common.h>
- #include <net/checksum.h>
- #include <net/xfrm.h>
-+#include <net/net_namespace.h>
- #include <linux/rtnetlink.h>
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
-@@ -101,7 +102,7 @@
-       write_unlock_bh(&raw_v4_lock);
- }
+       /*
+        *      Initialise the packet receive queues.
+diff -Nurb linux-2.6.22-590/net/core/dev_mcast.c linux-2.6.22-570/net/core/dev_mcast.c
+--- linux-2.6.22-590/net/core/dev_mcast.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/dev_mcast.c      2007-07-08 19:32:17.000000000 -0400
+@@ -46,7 +46,6 @@
+ #include <linux/skbuff.h>
+ #include <net/sock.h>
+ #include <net/arp.h>
+-#include <net/net_namespace.h>
  
--struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
-+struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, unsigned short num,
-                            __be32 raddr, __be32 laddr,
-                            int dif, int tag)
- {
-@@ -110,6 +111,9 @@
-       sk_for_each_from(sk, node) {
-               struct inet_sock *inet = inet_sk(sk);
  
-+              if (sk->sk_net != net)
-+                      continue;
-+
-               if (inet->num == num                                    &&
-                   !(inet->daddr && inet->daddr != raddr)              &&
-                   (!sk->sk_nx_info || tag == 1 || sk->sk_nid == tag)  &&
-@@ -152,6 +156,7 @@
-  */
- int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
+ /*
+@@ -220,12 +219,11 @@
+ #ifdef CONFIG_PROC_FS
+ static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)
  {
-+      struct net *net = skb->dev->nd_net;
-       struct sock *sk;
-       struct hlist_head *head;
-       int delivered = 0;
-@@ -160,7 +165,7 @@
-       head = &raw_v4_htable[hash];
-       if (hlist_empty(head))
-               goto out;
--      sk = __raw_v4_lookup(__sk_head(head), iph->protocol,
-+      sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol,
-                            iph->saddr, iph->daddr,
-                            skb->dev->ifindex, skb->skb_tag);
+-      struct net *net = seq->private;
+       struct net_device *dev;
+       loff_t off = 0;
  
-@@ -173,7 +178,7 @@
-                       if (clone)
-                               raw_rcv(sk, clone);
-               }
--              sk = __raw_v4_lookup(sk_next(sk), iph->protocol,
-+              sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol,
-                                    iph->saddr, iph->daddr,
-                                    skb->dev->ifindex, skb->skb_tag);
-       }
-@@ -484,7 +489,8 @@
+       read_lock(&dev_base_lock);
+-      for_each_netdev(net, dev) {
++      for_each_netdev(dev) {
+               if (off++ == *pos)
+                       return dev;
        }
+@@ -274,22 +272,7 @@
  
-       {
--              struct flowi fl = { .oif = ipc.oif,
-+              struct flowi fl = { .fl_net = sk->sk_net,
-+                                  .oif = ipc.oif,
-                                   .nl_u = { .ip4_u =
-                                             { .daddr = daddr,
-                                               .saddr = saddr,
-@@ -574,7 +580,7 @@
-       if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in))
-               goto out;
-       v4_map_sock_addr(inet, addr, &nsa);
--      chk_addr_ret = inet_addr_type(nsa.saddr);
-+      chk_addr_ret = inet_addr_type(sk->sk_net, nsa.saddr);
-       ret = -EADDRNOTAVAIL;
-       if (nsa.saddr && chk_addr_ret != RTN_LOCAL &&
-           chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
-@@ -798,6 +804,7 @@
+ static int dev_mc_seq_open(struct inode *inode, struct file *file)
+ {
+-      struct seq_file *seq;
+-      int res;
+-      res = seq_open(file, &dev_mc_seq_ops);
+-      if (!res) {
+-              seq = file->private_data;
+-              seq->private = get_net(PROC_NET(inode));
+-      }
+-      return res;
+-}
+-
+-static int dev_mc_seq_release(struct inode *inode, struct file *file)
+-{
+-      struct seq_file *seq = file->private_data;
+-      struct net *net = seq->private;
+-      put_net(net);
+-      return seq_release(inode, file);
++      return seq_open(file, &dev_mc_seq_ops);
+ }
  
- #ifdef CONFIG_PROC_FS
- struct raw_iter_state {
-+      struct net *net;
-       int bucket;
+ static const struct file_operations dev_mc_seq_fops = {
+@@ -297,31 +280,14 @@
+       .open    = dev_mc_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+-      .release = dev_mc_seq_release,
++      .release = seq_release,
  };
  
-@@ -811,11 +818,14 @@
-       for (state->bucket = 0; state->bucket < RAWV4_HTABLE_SIZE; ++state->bucket) {
-               struct hlist_node *node;
--              sk_for_each(sk, node, &raw_v4_htable[state->bucket])
-+              sk_for_each(sk, node, &raw_v4_htable[state->bucket]) {
-+                      if (sk->sk_net != state->net)
-+                              continue;
-                       if (sk->sk_family == PF_INET &&
-                               nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT))
-                               goto found;
-       }
-+      }
-       sk = NULL;
- found:
-       return sk;
-@@ -830,7 +840,7 @@
- try_again:
-               ;
-       } while (sk && (sk->sk_family != PF_INET ||
--              !nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT)));
-+              !nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT) || (sk->sk_net != state->net)));
+ #endif
  
-       if (!sk && ++state->bucket < RAWV4_HTABLE_SIZE) {
-               sk = sk_head(&raw_v4_htable[state->bucket]);
-@@ -933,6 +943,7 @@
-       seq = file->private_data;
-       seq->private = s;
-       memset(s, 0, sizeof(*s));
-+      s->net = get_net(PROC_NET(inode));
- out:
-       return rc;
- out_kfree:
-@@ -940,23 +951,46 @@
-       goto out;
+-static int dev_mc_net_init(struct net *net)
+-{
+-      if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops))
+-              return -ENOMEM;
+-      return 0;
+-}
+-
+-static void dev_mc_net_exit(struct net *net)
+-{
+-      proc_net_remove(net, "dev_mcast");
+-}
+-
+-static struct pernet_operations dev_mc_net_ops = {
+-      .init = dev_mc_net_init,
+-      .exit = dev_mc_net_exit,
+-};
+-
+ void __init dev_mcast_init(void)
+ {
+-      register_pernet_subsys(&dev_mc_net_ops);
++      proc_net_fops_create("dev_mcast", 0, &dev_mc_seq_fops);
  }
  
-+static int raw_seq_release(struct inode *inode, struct file *file)
-+{
-+      struct seq_file *seq = file->private_data;
-+      struct raw_iter_state *state = seq->private;
-+      put_net(state->net);
-+      return seq_release_private(inode, file);
-+}
-+
- static const struct file_operations raw_seq_fops = {
-       .owner   = THIS_MODULE,
-       .open    = raw_seq_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
--      .release = seq_release_private,
-+      .release = raw_seq_release,
- };
+ EXPORT_SYMBOL(dev_mc_add);
+diff -Nurb linux-2.6.22-590/net/core/dst.c linux-2.6.22-570/net/core/dst.c
+--- linux-2.6.22-590/net/core/dst.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/dst.c    2007-07-08 19:32:17.000000000 -0400
+@@ -15,9 +15,7 @@
+ #include <linux/skbuff.h>
+ #include <linux/string.h>
+ #include <linux/types.h>
+-#include <net/net_namespace.h>
  
--int __init raw_proc_init(void)
-+static int raw_proc_net_init(struct net *net)
- {
--      if (!proc_net_fops_create("raw", S_IRUGO, &raw_seq_fops))
-+      if (!proc_net_fops_create(net, "raw", S_IRUGO, &raw_seq_fops))
-               return -ENOMEM;
-       return 0;
- }
+-#include <net/net_namespace.h>
+ #include <net/dst.h>
  
-+static void raw_proc_net_exit(struct net *net)
-+{
-+      proc_net_remove(net, "raw");
-+}
-+
-+static struct pernet_operations raw_proc_net_ops = {
-+      .init = raw_proc_net_init,
-+      .exit = raw_proc_net_exit,
-+};
-+
-+int __init raw_proc_init(void)
-+{
-+      return register_pernet_subsys(&raw_proc_net_ops);
-+}
-+
- void __init raw_proc_exit(void)
- {
--      proc_net_remove("raw");
-+      unregister_pernet_subsys(&raw_proc_net_ops);
+ /* Locking strategy:
+@@ -238,14 +236,13 @@
+       if (!unregister) {
+               dst->input = dst->output = dst_discard;
+       } else {
+-              struct net *net = dev->nd_net;
+-              dst->dev = &net->loopback_dev;
+-              dev_hold(dst->dev);
++              dst->dev = &loopback_dev;
++              dev_hold(&loopback_dev);
+               dev_put(dev);
+               if (dst->neighbour && dst->neighbour->dev == dev) {
+-                      dst->neighbour->dev = &net->loopback_dev;
++                      dst->neighbour->dev = &loopback_dev;
+                       dev_put(dev);
+-                      dev_hold(dst->neighbour->dev);
++                      dev_hold(&loopback_dev);
+               }
+       }
  }
- #endif /* CONFIG_PROC_FS */
-diff -Nurb linux-2.6.22-570/net/ipv4/route.c linux-2.6.22-590/net/ipv4/route.c
---- linux-2.6.22-570/net/ipv4/route.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/route.c  2008-01-02 13:56:38.000000000 -0500
-@@ -101,8 +101,8 @@
- #include <net/tcp.h>
- #include <net/icmp.h>
- #include <net/xfrm.h>
--#include <net/ip_mp_alg.h>
- #include <net/netevent.h>
-+#include <net/net_namespace.h>
- #include <net/rtnetlink.h>
- #ifdef CONFIG_SYSCTL
- #include <linux/sysctl.h>
-@@ -266,6 +266,7 @@
+@@ -255,9 +252,6 @@
+       struct net_device *dev = ptr;
+       struct dst_entry *dst;
  
- #ifdef CONFIG_PROC_FS
- struct rt_cache_iter_state {
-+      struct net *net;
-       int bucket;
- };
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       switch (event) {
+       case NETDEV_UNREGISTER:
+       case NETDEV_DOWN:
+diff -Nurb linux-2.6.22-590/net/core/ethtool.c linux-2.6.22-570/net/core/ethtool.c
+--- linux-2.6.22-590/net/core/ethtool.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/ethtool.c        2007-07-08 19:32:17.000000000 -0400
+@@ -798,9 +798,9 @@
  
-@@ -334,6 +335,7 @@
+ /* The main entry point in this file.  Called from net/core/dev.c */
  
- static int rt_cache_seq_show(struct seq_file *seq, void *v)
+-int dev_ethtool(struct net *net, struct ifreq *ifr)
++int dev_ethtool(struct ifreq *ifr)
  {
-+      struct rt_cache_iter_state *st = seq->private;
-       if (v == SEQ_START_TOKEN)
-               seq_printf(seq, "%-127s\n",
-                          "Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\t"
-@@ -343,6 +345,9 @@
-               struct rtable *r = v;
-               char temp[256];
-+              if (r->fl.fl_net != st->net)
-+                      return 0;
-+
-               sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t"
-                             "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X",
-                       r->u.dst.dev ? r->u.dst.dev->name : "*",
-@@ -385,6 +390,7 @@
-       seq          = file->private_data;
-       seq->private = s;
-       memset(s, 0, sizeof(*s));
-+      s->net = get_net(PROC_NET(inode));
- out:
-       return rc;
- out_kfree:
-@@ -392,12 +398,20 @@
-       goto out;
- }
+-      struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
++      struct net_device *dev = __dev_get_by_name(ifr->ifr_name);
+       void __user *useraddr = ifr->ifr_data;
+       u32 ethcmd;
+       int rc;
+diff -Nurb linux-2.6.22-590/net/core/fib_rules.c linux-2.6.22-570/net/core/fib_rules.c
+--- linux-2.6.22-590/net/core/fib_rules.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/fib_rules.c      2007-07-08 19:32:17.000000000 -0400
+@@ -11,20 +11,21 @@
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
+-#include <net/net_namespace.h>
+-#include <net/sock.h>
+ #include <net/fib_rules.h>
  
-+static int rt_cache_seq_release(struct inode *inode, struct file *file)
-+{
-+      struct seq_file *seq = file->private_data;
-+      struct rt_cache_iter_state *st = seq->private;
-+      put_net(st->net);
-+      return seq_release_private(inode, file);
-+}
+-static void notify_rule_change(struct net *net, int event, struct fib_rule *rule,
++static LIST_HEAD(rules_ops);
++static DEFINE_SPINLOCK(rules_mod_lock);
 +
- static const struct file_operations rt_cache_seq_fops = {
-       .owner   = THIS_MODULE,
-       .open    = rt_cache_seq_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
--      .release = seq_release_private,
-+      .release = rt_cache_seq_release,
- };
++static void notify_rule_change(int event, struct fib_rule *rule,
+                              struct fib_rules_ops *ops, struct nlmsghdr *nlh,
+                              u32 pid);
  
-@@ -495,13 +509,11 @@
+-static struct fib_rules_ops *lookup_rules_ops(struct net *net, int family)
++static struct fib_rules_ops *lookup_rules_ops(int family)
+ {
+       struct fib_rules_ops *ops;
  
- static __inline__ void rt_free(struct rtable *rt)
+       rcu_read_lock();
+-      list_for_each_entry_rcu(ops, &net->rules_ops, list) {
++      list_for_each_entry_rcu(ops, &rules_ops, list) {
+               if (ops->family == family) {
+                       if (!try_module_get(ops->owner))
+                               ops = NULL;
+@@ -46,10 +47,10 @@
+ static void flush_route_cache(struct fib_rules_ops *ops)
  {
--      multipath_remove(rt);
-       call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
+       if (ops->flush_cache)
+-              ops->flush_cache(ops);
++              ops->flush_cache();
  }
  
- static __inline__ void rt_drop(struct rtable *rt)
+-int fib_rules_register(struct net *net, struct fib_rules_ops *ops)
++int fib_rules_register(struct fib_rules_ops *ops)
  {
--      multipath_remove(rt);
-       ip_rt_put(rt);
-       call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
+       int err = -EEXIST;
+       struct fib_rules_ops *o;
+@@ -62,16 +63,15 @@
+           ops->action == NULL)
+               return -EINVAL;
+-      spin_lock(&net->rules_mod_lock);
+-      list_for_each_entry(o, &net->rules_ops, list)
++      spin_lock(&rules_mod_lock);
++      list_for_each_entry(o, &rules_ops, list)
+               if (ops->family == o->family)
+                       goto errout;
+-      hold_net(net);
+-      list_add_tail_rcu(&ops->list, &net->rules_ops);
++      list_add_tail_rcu(&ops->list, &rules_ops);
+       err = 0;
+ errout:
+-      spin_unlock(&net->rules_mod_lock);
++      spin_unlock(&rules_mod_lock);
+       return err;
+ }
+@@ -88,13 +88,13 @@
+       }
  }
-@@ -565,61 +577,16 @@
  
- static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
+-int fib_rules_unregister(struct net *net, struct fib_rules_ops *ops)
++int fib_rules_unregister(struct fib_rules_ops *ops)
  {
--      return ((__force u32)((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
-+      return (((__force u32)((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
-               (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr)) |
-               (fl1->mark ^ fl2->mark) |
-               (*(u16 *)&fl1->nl_u.ip4_u.tos ^
-                *(u16 *)&fl2->nl_u.ip4_u.tos) |
-               (fl1->oif ^ fl2->oif) |
--              (fl1->iif ^ fl2->iif)) == 0;
-+              (fl1->iif ^ fl2->iif)) == 0) &&
-+              fl1->fl_net == fl2->fl_net;
+       int err = 0;
+       struct fib_rules_ops *o;
+-      spin_lock(&net->rules_mod_lock);
+-      list_for_each_entry(o, &net->rules_ops, list) {
++      spin_lock(&rules_mod_lock);
++      list_for_each_entry(o, &rules_ops, list) {
+               if (o == ops) {
+                       list_del_rcu(&o->list);
+                       cleanup_ops(ops);
+@@ -104,11 +104,9 @@
+       err = -ENOENT;
+ out:
+-      spin_unlock(&net->rules_mod_lock);
++      spin_unlock(&rules_mod_lock);
+       synchronize_rcu();
+-      if (!err)
+-              release_net(net);
+       return err;
  }
+@@ -199,7 +197,6 @@
  
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--static struct rtable **rt_remove_balanced_route(struct rtable **chain_head,
--                                              struct rtable *expentry,
--                                              int *removed_count)
--{
--      int passedexpired = 0;
--      struct rtable **nextstep = NULL;
--      struct rtable **rthp = chain_head;
--      struct rtable *rth;
--
--      if (removed_count)
--              *removed_count = 0;
--
--      while ((rth = *rthp) != NULL) {
--              if (rth == expentry)
--                      passedexpired = 1;
--
--              if (((*rthp)->u.dst.flags & DST_BALANCED) != 0  &&
--                  compare_keys(&(*rthp)->fl, &expentry->fl)) {
--                      if (*rthp == expentry) {
--                              *rthp = rth->u.dst.rt_next;
--                              continue;
--                      } else {
--                              *rthp = rth->u.dst.rt_next;
--                              rt_free(rth);
--                              if (removed_count)
--                                      ++(*removed_count);
--                      }
--              } else {
--                      if (!((*rthp)->u.dst.flags & DST_BALANCED) &&
--                          passedexpired && !nextstep)
--                              nextstep = &rth->u.dst.rt_next;
--
--                      rthp = &rth->u.dst.rt_next;
--              }
--      }
--
--      rt_free(expentry);
--      if (removed_count)
--              ++(*removed_count);
--
--      return nextstep;
--}
--#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
--
--
- /* This runs via a timer and thus is always in BH context. */
- static void rt_check_expire(unsigned long dummy)
+ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
  {
-@@ -658,23 +625,9 @@
-                       }
+-      struct net *net = skb->sk->sk_net;
+       struct fib_rule_hdr *frh = nlmsg_data(nlh);
+       struct fib_rules_ops *ops = NULL;
+       struct fib_rule *rule, *r, *last = NULL;
+@@ -209,7 +206,7 @@
+       if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
+               goto errout;
  
-                       /* Cleanup aged off entries. */
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--                      /* remove all related balanced entries if necessary */
--                      if (rth->u.dst.flags & DST_BALANCED) {
--                              rthp = rt_remove_balanced_route(
--                                      &rt_hash_table[i].chain,
--                                      rth, NULL);
--                              if (!rthp)
--                                      break;
--                      } else {
-                               *rthp = rth->u.dst.rt_next;
-                               rt_free(rth);
-                       }
--#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
--                      *rthp = rth->u.dst.rt_next;
--                      rt_free(rth);
--#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
--              }
-               spin_unlock(rt_hash_lock_addr(i));
+-      ops = lookup_rules_ops(net, frh->family);
++      ops = lookup_rules_ops(frh->family);
+       if (ops == NULL) {
+               err = EAFNOSUPPORT;
+               goto errout;
+@@ -237,7 +234,7 @@
  
-               /* Fallback loop breaker. */
-@@ -721,9 +674,6 @@
-       if (delay < 0)
-               delay = ip_rt_min_delay;
+               rule->ifindex = -1;
+               nla_strlcpy(rule->ifname, tb[FRA_IFNAME], IFNAMSIZ);
+-              dev = __dev_get_by_name(net, rule->ifname);
++              dev = __dev_get_by_name(rule->ifname);
+               if (dev)
+                       rule->ifindex = dev->ifindex;
+       }
+@@ -259,7 +256,7 @@
+       rule->table = frh_get_table(frh, tb);
  
--      /* flush existing multipath state*/
--      multipath_flush();
--
-       spin_lock_bh(&rt_flush_lock);
+       if (!rule->pref && ops->default_pref)
+-              rule->pref = ops->default_pref(ops);
++              rule->pref = ops->default_pref();
  
-       if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) {
-@@ -842,31 +792,10 @@
-                                       rthp = &rth->u.dst.rt_next;
-                                       continue;
-                               }
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--                              /* remove all related balanced entries
--                               * if necessary
--                               */
--                              if (rth->u.dst.flags & DST_BALANCED) {
--                                      int r;
--
--                                      rthp = rt_remove_balanced_route(
--                                              &rt_hash_table[k].chain,
--                                              rth,
--                                              &r);
--                                      goal -= r;
--                                      if (!rthp)
--                                              break;
--                              } else {
-                                       *rthp = rth->u.dst.rt_next;
-                                       rt_free(rth);
-                                       goal--;
-                               }
--#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
--                              *rthp = rth->u.dst.rt_next;
--                              rt_free(rth);
--                              goal--;
--#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
--                      }
-                       spin_unlock_bh(rt_hash_lock_addr(k));
-                       if (goal <= 0)
-                               break;
-@@ -939,12 +868,7 @@
+       err = -EINVAL;
+       if (tb[FRA_GOTO]) {
+@@ -322,7 +319,7 @@
+       else
+               list_add_rcu(&rule->list, ops->rules_list);
  
-       spin_lock_bh(rt_hash_lock_addr(hash));
-       while ((rth = *rthp) != NULL) {
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--              if (!(rth->u.dst.flags & DST_BALANCED) &&
--                  compare_keys(&rth->fl, &rt->fl)) {
--#else
-               if (compare_keys(&rth->fl, &rt->fl)) {
--#endif
-                       /* Put it first */
-                       *rthp = rth->u.dst.rt_next;
-                       /*
-@@ -1055,7 +979,7 @@
-       static DEFINE_SPINLOCK(rt_peer_lock);
-       struct inet_peer *peer;
+-      notify_rule_change(net, RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid);
++      notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid);
+       flush_route_cache(ops);
+       rules_ops_put(ops);
+       return 0;
+@@ -336,7 +333,6 @@
  
--      peer = inet_getpeer(rt->rt_dst, create);
-+      peer = inet_getpeer(rt->fl.fl_net, rt->rt_dst, create);
+ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct fib_rule_hdr *frh = nlmsg_data(nlh);
+       struct fib_rules_ops *ops = NULL;
+       struct fib_rule *rule, *tmp;
+@@ -346,7 +342,7 @@
+       if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
+               goto errout;
  
-       spin_lock_bh(&rt_peer_lock);
-       if (rt->peer == NULL) {
-@@ -1148,7 +1072,7 @@
-               if (IN_DEV_SEC_REDIRECTS(in_dev) && ip_fib_check_default(new_gw, dev))
-                       goto reject_redirect;
-       } else {
--              if (inet_addr_type(new_gw) != RTN_UNICAST)
-+              if (inet_addr_type(dev->nd_net, new_gw) != RTN_UNICAST)
-                       goto reject_redirect;
-       }
+-      ops = lookup_rules_ops(net, frh->family);
++      ops = lookup_rules_ops(frh->family);
+       if (ops == NULL) {
+               err = EAFNOSUPPORT;
+               goto errout;
+@@ -412,7 +408,7 @@
+               }
  
-@@ -1189,6 +1113,7 @@
+               synchronize_rcu();
+-              notify_rule_change(net, RTM_DELRULE, rule, ops, nlh,
++              notify_rule_change(RTM_DELRULE, rule, ops, nlh,
+                                  NETLINK_CB(skb).pid);
+               fib_rule_put(rule);
+               flush_route_cache(ops);
+@@ -518,17 +514,13 @@
  
-                               /* Copy all the information. */
-                               *rt = *rth;
-+                              hold_net(rt->fl.fl_net);
-                               INIT_RCU_HEAD(&rt->u.dst.rcu_head);
-                               rt->u.dst.__use         = 1;
-                               atomic_set(&rt->u.dst.__refcnt, 1);
-@@ -1407,7 +1332,7 @@
-       __be32  daddr = iph->daddr;
-       unsigned short est_mtu = 0;
+ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct fib_rules_ops *ops;
+       int idx = 0, family;
  
--      if (ipv4_config.no_pmtu_disc)
-+      if (init_net.sysctl_ipv4_no_pmtu_disc)
-               return 0;
+-      if (net != &init_net)
+-              return -EINVAL;
+-
+       family = rtnl_msg_family(cb->nlh);
+       if (family != AF_UNSPEC) {
+               /* Protocol specific dump request */
+-              ops = lookup_rules_ops(net, family);
++              ops = lookup_rules_ops(family);
+               if (ops == NULL)
+                       return -EAFNOSUPPORT;
  
-       for (i = 0; i < 2; i++) {
-@@ -1489,6 +1414,7 @@
-               rt->idev = NULL;
-               in_dev_put(idev);
+@@ -536,7 +528,7 @@
        }
-+      release_net(rt->fl.fl_net);
+       rcu_read_lock();
+-      list_for_each_entry_rcu(ops, &net->rules_ops, list) {
++      list_for_each_entry_rcu(ops, &rules_ops, list) {
+               if (idx < cb->args[0] || !try_module_get(ops->owner))
+                       goto skip;
+@@ -553,7 +545,7 @@
+       return skb->len;
  }
  
- static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
-@@ -1496,8 +1422,9 @@
+-static void notify_rule_change(struct net *net, int event, struct fib_rule *rule,
++static void notify_rule_change(int event, struct fib_rule *rule,
+                              struct fib_rules_ops *ops, struct nlmsghdr *nlh,
+                              u32 pid)
  {
-       struct rtable *rt = (struct rtable *) dst;
-       struct in_device *idev = rt->idev;
--      if (dev != &loopback_dev && idev && idev->dev == dev) {
--              struct in_device *loopback_idev = in_dev_get(&loopback_dev);
-+      struct net *net = dev->nd_net;
-+      if (dev != &net->loopback_dev && idev && idev->dev == dev) {
-+              struct in_device *loopback_idev = in_dev_get(&net->loopback_dev);
-               if (loopback_idev) {
-                       rt->idev = loopback_idev;
-                       in_dev_put(idev);
-@@ -1584,7 +1511,7 @@
-               rt->u.dst.metrics[RTAX_MTU-1]= rt->u.dst.dev->mtu;
+@@ -571,10 +563,10 @@
+               kfree_skb(skb);
+               goto errout;
+       }
+-      err = rtnl_notify(skb, net, pid, ops->nlgroup, nlh, GFP_KERNEL);
++      err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
+ errout:
+       if (err < 0)
+-              rtnl_set_sk_err(net, ops->nlgroup, err);
++              rtnl_set_sk_err(ops->nlgroup, err);
+ }
  
-       if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0)
--              rt->u.dst.metrics[RTAX_HOPLIMIT-1] = sysctl_ip_default_ttl;
-+              rt->u.dst.metrics[RTAX_HOPLIMIT-1] = init_net.sysctl_ip_default_ttl;
-       if (rt->u.dst.metrics[RTAX_MTU-1] > IP_MAX_MTU)
-               rt->u.dst.metrics[RTAX_MTU-1] = IP_MAX_MTU;
-       if (rt->u.dst.metrics[RTAX_ADVMSS-1] == 0)
-@@ -1605,6 +1532,7 @@
- static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
-                               u8 tos, struct net_device *dev, int our)
+ static void attach_rules(struct list_head *rules, struct net_device *dev)
+@@ -602,23 +594,19 @@
+                           void *ptr)
  {
-+      struct net *net = dev->nd_net;
-       unsigned hash;
-       struct rtable *rth;
-       __be32 spec_dst;
-@@ -1638,6 +1566,7 @@
-       rth->u.dst.flags= DST_HOST;
-       if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
-               rth->u.dst.flags |= DST_NOPOLICY;
-+      rth->fl.fl_net  = hold_net(net);
-       rth->fl.fl4_dst = daddr;
-       rth->rt_dst     = daddr;
-       rth->fl.fl4_tos = tos;
-@@ -1649,7 +1578,7 @@
- #endif
-       rth->rt_iif     =
-       rth->fl.iif     = dev->ifindex;
--      rth->u.dst.dev  = &loopback_dev;
-+      rth->u.dst.dev  = &net->loopback_dev;
-       dev_hold(rth->u.dst.dev);
-       rth->idev       = in_dev_get(rth->u.dst.dev);
-       rth->fl.oif     = 0;
-@@ -1774,14 +1703,11 @@
+       struct net_device *dev = ptr;
+-      struct net *net = dev->nd_net;
+       struct fib_rules_ops *ops;
  
-       atomic_set(&rth->u.dst.__refcnt, 1);
-       rth->u.dst.flags= DST_HOST;
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      if (res->fi->fib_nhs > 1)
--              rth->u.dst.flags |= DST_BALANCED;
--#endif
-       if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
-               rth->u.dst.flags |= DST_NOPOLICY;
-       if (IN_DEV_CONF_GET(out_dev, NOXFRM))
-               rth->u.dst.flags |= DST_NOXFRM;
-+      rth->fl.fl_net  = hold_net(in_dev->dev->nd_net);
-       rth->fl.fl4_dst = daddr;
-       rth->rt_dst     = daddr;
-       rth->fl.fl4_tos = tos;
-@@ -1812,7 +1738,7 @@
-       return err;
- }
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       ASSERT_RTNL();
+       rcu_read_lock();
  
--static inline int ip_mkroute_input_def(struct sk_buff *skb,
-+static inline int ip_mkroute_input(struct sk_buff *skb,
-                                      struct fib_result* res,
-                                      const struct flowi *fl,
-                                      struct in_device *in_dev,
-@@ -1837,63 +1763,6 @@
-       return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
- }
+       switch (event) {
+       case NETDEV_REGISTER:
+-              list_for_each_entry(ops, &net->rules_ops, list)
++              list_for_each_entry(ops, &rules_ops, list)
+                       attach_rules(ops->rules_list, dev);
+               break;
  
--static inline int ip_mkroute_input(struct sk_buff *skb,
--                                 struct fib_result* res,
--                                 const struct flowi *fl,
--                                 struct in_device *in_dev,
--                                 __be32 daddr, __be32 saddr, u32 tos)
--{
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      struct rtable* rth = NULL, *rtres;
--      unsigned char hop, hopcount;
--      int err = -EINVAL;
--      unsigned int hash;
--
--      if (res->fi)
--              hopcount = res->fi->fib_nhs;
--      else
--              hopcount = 1;
--
--      /* distinguish between multipath and singlepath */
--      if (hopcount < 2)
--              return ip_mkroute_input_def(skb, res, fl, in_dev, daddr,
--                                          saddr, tos);
--
--      /* add all alternatives to the routing cache */
--      for (hop = 0; hop < hopcount; hop++) {
--              res->nh_sel = hop;
--
--              /* put reference to previous result */
--              if (hop)
--                      ip_rt_put(rtres);
--
--              /* create a routing cache entry */
--              err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos,
--                                    &rth);
--              if (err)
--                      return err;
--
--              /* put it into the cache */
--              hash = rt_hash(daddr, saddr, fl->iif);
--              err = rt_intern_hash(hash, rth, &rtres);
--              if (err)
--                      return err;
--
--              /* forward hop information to multipath impl. */
--              multipath_set_nhinfo(rth,
--                                   FIB_RES_NETWORK(*res),
--                                   FIB_RES_NETMASK(*res),
--                                   res->prefixlen,
--                                   &FIB_RES_NH(*res));
--      }
--      skb->dst = &rtres->u.dst;
--      return err;
--#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED  */
--      return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);
--#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED  */
+       case NETDEV_UNREGISTER:
+-              list_for_each_entry(ops, &net->rules_ops, list)
++              list_for_each_entry(ops, &rules_ops, list)
+                       detach_rules(ops->rules_list, dev);
+               break;
+       }
+@@ -632,28 +620,13 @@
+       .notifier_call = fib_rules_event,
+ };
+-static int fib_rules_net_init(struct net *net)
+-{
+-      INIT_LIST_HEAD(&net->rules_ops);
+-      spin_lock_init(&net->rules_mod_lock);
+-      return 0;
 -}
 -
+-static struct pernet_operations fib_rules_net_ops = {
+-      .init = fib_rules_net_init,
+-};
 -
- /*
-  *    NOTE. We drop all the packets that has local source
-  *    addresses, because every properly looped back packet
-@@ -1907,9 +1776,11 @@
- static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
-                              u8 tos, struct net_device *dev)
+ static int __init fib_rules_init(void)
  {
-+      struct net *net = dev->nd_net;
-       struct fib_result res;
-       struct in_device *in_dev = in_dev_get(dev);
--      struct flowi fl = { .nl_u = { .ip4_u =
-+      struct flowi fl = { .fl_net = net,
-+                          .nl_u = { .ip4_u =
-                                     { .daddr = daddr,
-                                       .saddr = saddr,
-                                       .tos = tos,
-@@ -1967,7 +1838,7 @@
-       if (res.type == RTN_LOCAL) {
-               int result;
-               result = fib_validate_source(saddr, daddr, tos,
--                                           loopback_dev.ifindex,
-+                                           net->loopback_dev.ifindex,
-                                            dev, &spec_dst, &itag);
-               if (result < 0)
-                       goto martian_source;
-@@ -2023,6 +1894,7 @@
-       rth->u.dst.flags= DST_HOST;
-       if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
-               rth->u.dst.flags |= DST_NOPOLICY;
-+      rth->fl.fl_net  = hold_net(net);
-       rth->fl.fl4_dst = daddr;
-       rth->rt_dst     = daddr;
-       rth->fl.fl4_tos = tos;
-@@ -2034,7 +1906,7 @@
- #endif
-       rth->rt_iif     =
-       rth->fl.iif     = dev->ifindex;
--      rth->u.dst.dev  = &loopback_dev;
-+      rth->u.dst.dev  = &net->loopback_dev;
-       dev_hold(rth->u.dst.dev);
-       rth->idev       = in_dev_get(rth->u.dst.dev);
-       rth->rt_gateway = daddr;
-@@ -2092,6 +1964,7 @@
-       struct rtable * rth;
-       unsigned        hash;
-       int iif = dev->ifindex;
-+      struct net *net = dev->nd_net;
+-      int ret;
+       rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL);
+       rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL);
+       rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule);
  
-       tos &= IPTOS_RT_MASK;
-       hash = rt_hash(daddr, saddr, iif);
-@@ -2104,7 +1977,8 @@
-                   rth->fl.iif == iif &&
-                   rth->fl.oif == 0 &&
-                   rth->fl.mark == skb->mark &&
--                  rth->fl.fl4_tos == tos) {
-+                  rth->fl.fl4_tos == tos &&
-+                  rth->fl.fl_net == net) {
-                       rth->u.dst.lastuse = jiffies;
-                       dst_hold(&rth->u.dst);
-                       rth->u.dst.__use++;
-@@ -2211,18 +2085,12 @@
+-      ret = register_pernet_subsys(&fib_rules_net_ops);
+-      if (!ret)
+-              ret = register_netdevice_notifier(&fib_rules_notifier);
+-      return ret;
++      return register_netdevice_notifier(&fib_rules_notifier);
+ }
  
-       atomic_set(&rth->u.dst.__refcnt, 1);
-       rth->u.dst.flags= DST_HOST;
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      if (res->fi) {
--              rth->rt_multipath_alg = res->fi->fib_mp_alg;
--              if (res->fi->fib_nhs > 1)
--                      rth->u.dst.flags |= DST_BALANCED;
--      }
--#endif
-       if (IN_DEV_CONF_GET(in_dev, NOXFRM))
-               rth->u.dst.flags |= DST_NOXFRM;
-       if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
-               rth->u.dst.flags |= DST_NOPOLICY;
+ subsys_initcall(fib_rules_init);
+diff -Nurb linux-2.6.22-590/net/core/neighbour.c linux-2.6.22-570/net/core/neighbour.c
+--- linux-2.6.22-590/net/core/neighbour.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/neighbour.c      2007-07-08 19:32:17.000000000 -0400
+@@ -33,7 +33,6 @@
+ #include <linux/rtnetlink.h>
+ #include <linux/random.h>
+ #include <linux/string.h>
+-#include <net/net_namespace.h>
  
-+      rth->fl.fl_net  = hold_net(oldflp->fl_net);
-       rth->fl.fl4_dst = oldflp->fl4_dst;
-       rth->fl.fl4_tos = tos;
-       rth->fl.fl4_src = oldflp->fl4_src;
-@@ -2277,7 +2145,7 @@
-       return err;
+ #define NEIGH_DEBUG 1
+@@ -362,7 +361,7 @@
+       return n;
  }
  
--static inline int ip_mkroute_output_def(struct rtable **rp,
-+static inline int ip_mkroute_output(struct rtable **rp,
-                                       struct fib_result* res,
-                                       const struct flowi *fl,
-                                       const struct flowi *oldflp,
-@@ -2295,68 +2163,6 @@
-       return err;
+-struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net * net, const void *pkey)
++struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, const void *pkey)
+ {
+       struct neighbour *n;
+       int key_len = tbl->key_len;
+@@ -372,8 +371,7 @@
+       read_lock_bh(&tbl->lock);
+       for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
+-              if (!memcmp(n->primary_key, pkey, key_len) &&
+-                  (net == n->dev->nd_net)) {
++              if (!memcmp(n->primary_key, pkey, key_len)) {
+                       neigh_hold(n);
+                       NEIGH_CACHE_STAT_INC(tbl, hits);
+                       break;
+@@ -451,8 +449,7 @@
+       goto out;
+ }
+-struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
+-                                  struct net * net, const void *pkey,
++struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey,
+                                   struct net_device *dev, int creat)
+ {
+       struct pneigh_entry *n;
+@@ -468,7 +465,6 @@
+       for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
+               if (!memcmp(n->key, pkey, key_len) &&
+-                  (n->net == net) &&
+                   (n->dev == dev || !n->dev)) {
+                       read_unlock_bh(&tbl->lock);
+                       goto out;
+@@ -483,7 +479,6 @@
+       if (!n)
+               goto out;
+-      n->net = hold_net(net);
+       memcpy(n->key, pkey, key_len);
+       n->dev = dev;
+       if (dev)
+@@ -506,7 +501,7 @@
+ }
+-int pneigh_delete(struct neigh_table *tbl, struct net * net, const void *pkey,
++int pneigh_delete(struct neigh_table *tbl, const void *pkey,
+                 struct net_device *dev)
+ {
+       struct pneigh_entry *n, **np;
+@@ -521,15 +516,13 @@
+       write_lock_bh(&tbl->lock);
+       for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
+            np = &n->next) {
+-              if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
+-                  (n->net == net)) {
++              if (!memcmp(n->key, pkey, key_len) && n->dev == dev) {
+                       *np = n->next;
+                       write_unlock_bh(&tbl->lock);
+                       if (tbl->pdestructor)
+                               tbl->pdestructor(n);
+                       if (n->dev)
+                               dev_put(n->dev);
+-                      release_net(n->net);
+                       kfree(n);
+                       return 0;
+               }
+@@ -552,7 +545,6 @@
+                                       tbl->pdestructor(n);
+                               if (n->dev)
+                                       dev_put(n->dev);
+-                              release_net(n->net);
+                               kfree(n);
+                               continue;
+                       }
+@@ -1274,37 +1266,12 @@
+       spin_unlock(&tbl->proxy_queue.lock);
  }
  
--static inline int ip_mkroute_output(struct rtable** rp,
--                                  struct fib_result* res,
--                                  const struct flowi *fl,
--                                  const struct flowi *oldflp,
--                                  struct net_device *dev_out,
--                                  unsigned flags)
+-static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
+-                                                    struct net * net, int ifindex)
 -{
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      unsigned char hop;
--      unsigned hash;
--      int err = -EINVAL;
--      struct rtable *rth = NULL;
--
--      if (res->fi && res->fi->fib_nhs > 1) {
--              unsigned char hopcount = res->fi->fib_nhs;
--
--              for (hop = 0; hop < hopcount; hop++) {
--                      struct net_device *dev2nexthop;
--
--                      res->nh_sel = hop;
--
--                      /* hold a work reference to the output device */
--                      dev2nexthop = FIB_RES_DEV(*res);
--                      dev_hold(dev2nexthop);
--
--                      /* put reference to previous result */
--                      if (hop)
--                              ip_rt_put(*rp);
--
--                      err = __mkroute_output(&rth, res, fl, oldflp,
--                                             dev2nexthop, flags);
--
--                      if (err != 0)
--                              goto cleanup;
+-      struct neigh_parms *p;
+-      
+-      for (p = &tbl->parms; p; p = p->next) {
+-              if (p->net != net)
+-                      continue;
+-              if ((p->dev && p->dev->ifindex == ifindex) ||
+-                  (!p->dev && !ifindex))
+-                      return p;
+-      }
 -
--                      hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src,
--                                      oldflp->oif);
--                      err = rt_intern_hash(hash, rth, rp);
+-      return NULL;
+-}
+ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
+                                     struct neigh_table *tbl)
+ {
+-      struct neigh_parms *p, *ref;
+-      struct net * net;
 -
--                      /* forward hop information to multipath impl. */
--                      multipath_set_nhinfo(rth,
--                                           FIB_RES_NETWORK(*res),
--                                           FIB_RES_NETMASK(*res),
--                                           res->prefixlen,
--                                           &FIB_RES_NH(*res));
--              cleanup:
--                      /* release work reference to output device */
--                      dev_put(dev2nexthop);
+-      net = &init_net;
+-      if (dev)
+-              net = dev->nd_net;
 -
--                      if (err != 0)
--                              return err;
--              }
--              return err;
--      } else {
--              return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out,
--                                           flags);
+-      ref = lookup_neigh_params(tbl, net, 0);
+-      if (!ref)
+-              return NULL;
++      struct neigh_parms *p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
+-      p = kmemdup(ref, sizeof(*p), GFP_KERNEL);
+       if (p) {
+               p->tbl            = tbl;
+               atomic_set(&p->refcnt, 1);
+@@ -1320,7 +1287,6 @@
+                       dev_hold(dev);
+                       p->dev = dev;
+               }
+-              p->net = hold_net(net);
+               p->sysctl_table = NULL;
+               write_lock_bh(&tbl->lock);
+               p->next         = tbl->parms.next;
+@@ -1330,20 +1296,6 @@
+       return p;
+ }
+-struct neigh_parms *neigh_parms_alloc_default(struct neigh_table *tbl,
+-                                              struct net *net)
+-{
+-      struct neigh_parms *parms;
+-      if (net != &init_net) {
+-              parms = neigh_parms_alloc(NULL, tbl);
+-              release_net(parms->net);
+-              parms->net = hold_net(net);
 -      }
--#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
--      return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, flags);
--#endif
+-      else
+-              parms = neigh_parms_clone(&tbl->parms);
+-      return parms;
 -}
 -
- /*
-  * Major route resolver routine.
-  */
-@@ -2364,7 +2170,9 @@
- static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
+ static void neigh_rcu_free_parms(struct rcu_head *head)
  {
-       u32 tos = RT_FL_TOS(oldflp);
--      struct flowi fl = { .nl_u = { .ip4_u =
-+      struct net *net = oldflp->fl_net;
-+      struct flowi fl = { .fl_net = net,
-+                          .nl_u = { .ip4_u =
-                                     { .daddr = oldflp->fl4_dst,
-                                       .saddr = oldflp->fl4_src,
-                                       .tos = tos & IPTOS_RT_MASK,
-@@ -2373,7 +2181,7 @@
-                                                 RT_SCOPE_UNIVERSE),
-                                     } },
-                           .mark = oldflp->mark,
--                          .iif = loopback_dev.ifindex,
-+                          .iif = net->loopback_dev.ifindex,
-                           .oif = oldflp->oif };
-       struct fib_result res;
-       unsigned flags = 0;
-@@ -2395,7 +2203,7 @@
-                       goto out;
-               /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
--              dev_out = ip_dev_find(oldflp->fl4_src);
-+              dev_out = ip_dev_find(net, oldflp->fl4_src);
-               if (dev_out == NULL)
-                       goto out;
+       struct neigh_parms *parms =
+@@ -1376,7 +1328,6 @@
  
-@@ -2434,7 +2242,7 @@
+ void neigh_parms_destroy(struct neigh_parms *parms)
+ {
+-      release_net(parms->net);
+       kfree(parms);
+ }
  
+@@ -1387,7 +1338,6 @@
+       unsigned long now = jiffies;
+       unsigned long phsize;
  
-       if (oldflp->oif) {
--              dev_out = dev_get_by_index(oldflp->oif);
-+              dev_out = dev_get_by_index(net, oldflp->oif);
-               err = -ENODEV;
-               if (dev_out == NULL)
-                       goto out;
-@@ -2467,9 +2275,9 @@
-                       fl.fl4_dst = fl.fl4_src = htonl(INADDR_LOOPBACK);
-               if (dev_out)
-                       dev_put(dev_out);
--              dev_out = &loopback_dev;
-+              dev_out = &net->loopback_dev;
-               dev_hold(dev_out);
--              fl.oif = loopback_dev.ifindex;
-+              fl.oif = net->loopback_dev.ifindex;
-               res.type = RTN_LOCAL;
-               flags |= RTCF_LOCAL;
-               goto make_route;
-@@ -2514,7 +2322,7 @@
-                       fl.fl4_src = fl.fl4_dst;
-               if (dev_out)
-                       dev_put(dev_out);
--              dev_out = &loopback_dev;
-+              dev_out = &net->loopback_dev;
-               dev_hold(dev_out);
-               fl.oif = dev_out->ifindex;
-               if (res.fi)
-@@ -2568,19 +2376,9 @@
-                   rth->fl.iif == 0 &&
-                   rth->fl.oif == flp->oif &&
-                   rth->fl.mark == flp->mark &&
-+                  rth->fl.fl_net == flp->fl_net &&
-                   !((rth->fl.fl4_tos ^ flp->fl4_tos) &
-                           (IPTOS_RT_MASK | RTO_ONLINK))) {
--
--                      /* check for multipath routes and choose one if
--                       * necessary
--                       */
--                      if (multipath_select_route(flp, rth, rp)) {
--                              dst_hold(&(*rp)->u.dst);
--                              RT_CACHE_STAT_INC(out_hit);
--                              rcu_read_unlock_bh();
--                              return 0;
--                      }
--
-                       rth->u.dst.lastuse = jiffies;
-                       dst_hold(&rth->u.dst);
-                       rth->u.dst.__use++;
-@@ -2729,10 +2527,6 @@
-       if (rt->u.dst.tclassid)
-               NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid);
- #endif
--#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
--      if (rt->rt_multipath_alg != IP_MP_ALG_NONE)
--              NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg);
--#endif
-       if (rt->fl.iif)
-               NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst);
-       else if (rt->rt_src != rt->fl.fl4_src)
-@@ -2759,7 +2553,7 @@
-               __be32 dst = rt->rt_dst;
+-      tbl->parms.net = &init_net;
+       atomic_set(&tbl->parms.refcnt, 1);
+       INIT_RCU_HEAD(&tbl->parms.rcu_head);
+       tbl->parms.reachable_time =
+@@ -1403,7 +1353,7 @@
+               panic("cannot create neighbour cache statistics");
  
-               if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&
--                  IPV4_DEVCONF_ALL(MC_FORWARDING)) {
-+                  IPV4_DEVCONF_ALL(&init_net, MC_FORWARDING)) {
-                       int err = ipmr_get_route(skb, r, nowait);
-                       if (err <= 0) {
-                               if (!nowait) {
-@@ -2790,6 +2584,7 @@
+ #ifdef CONFIG_PROC_FS
+-      tbl->pde = create_proc_entry(tbl->id, 0, init_net.proc_net_stat);
++      tbl->pde = create_proc_entry(tbl->id, 0, proc_net_stat);
+       if (!tbl->pde)
+               panic("cannot create neighbour proc dir entry");
+       tbl->pde->proc_fops = &neigh_stat_seq_fops;
+@@ -1493,7 +1443,6 @@
  
- static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
+ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
  {
-+      struct net *net = in_skb->sk->sk_net;
-       struct rtmsg *rtm;
-       struct nlattr *tb[RTA_MAX+1];
-       struct rtable *rt = NULL;
-@@ -2828,7 +2623,7 @@
-       if (iif) {
-               struct net_device *dev;
+-      struct net *net = skb->sk->sk_net;
+       struct ndmsg *ndm;
+       struct nlattr *dst_attr;
+       struct neigh_table *tbl;
+@@ -1509,7 +1458,7 @@
  
--              dev = __dev_get_by_index(iif);
-+              dev = __dev_get_by_index(net, iif);
+       ndm = nlmsg_data(nlh);
+       if (ndm->ndm_ifindex) {
+-              dev = dev_get_by_index(net, ndm->ndm_ifindex);
++              dev = dev_get_by_index(ndm->ndm_ifindex);
                if (dev == NULL) {
                        err = -ENODEV;
-                       goto errout_free;
-@@ -2845,6 +2640,7 @@
-                       err = -rt->u.dst.error;
-       } else {
-               struct flowi fl = {
-+                      .fl_net = net,
-                       .nl_u = {
-                               .ip4_u = {
-                                       .daddr = dst,
-@@ -2869,7 +2665,7 @@
-       if (err <= 0)
-               goto errout_free;
+                       goto out;
+@@ -1528,7 +1477,7 @@
+                       goto out_dev_put;
  
--      err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
-+      err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid);
- errout:
-       return err;
+               if (ndm->ndm_flags & NTF_PROXY) {
+-                      err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
++                      err = pneigh_delete(tbl, nla_data(dst_attr), dev);
+                       goto out_dev_put;
+               }
+@@ -1559,7 +1508,6 @@
+ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct ndmsg *ndm;
+       struct nlattr *tb[NDA_MAX+1];
+       struct neigh_table *tbl;
+@@ -1576,7 +1524,7 @@
+       ndm = nlmsg_data(nlh);
+       if (ndm->ndm_ifindex) {
+-              dev = dev_get_by_index(net, ndm->ndm_ifindex);
++              dev = dev_get_by_index(ndm->ndm_ifindex);
+               if (dev == NULL) {
+                       err = -ENODEV;
+                       goto out;
+@@ -1605,7 +1553,7 @@
+                       struct pneigh_entry *pn;
  
-@@ -3182,6 +2978,48 @@
+                       err = -ENOBUFS;
+-                      pn = pneigh_lookup(tbl, net, dst, dev, 1);
++                      pn = pneigh_lookup(tbl, dst, dev, 1);
+                       if (pn) {
+                               pn->flags = ndm->ndm_flags;
+                               err = 0;
+@@ -1800,6 +1748,19 @@
+       return -EMSGSIZE;
  }
- __setup("rhash_entries=", set_rhash_entries);
  
-+
-+static void ip_rt_net_exit(struct net *net)
++static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
++                                                    int ifindex)
 +{
-+#ifdef CONFIG_PROC_FS
-+# ifdef CONFIG_NET_CLS_ROUTE
-+      proc_net_remove(net, "rt_acct");
-+# endif
-+      remove_proc_entry("rt_cache", net->proc_net_stat);
-+      proc_net_remove(net, "rt_cache");
-+#endif
-+      rt_run_flush(0);
-+}
++      struct neigh_parms *p;
 +
-+static int ip_rt_net_init(struct net *net)
-+{
-+      int error = -ENOMEM;
-+#ifdef CONFIG_PROC_FS
-+      struct proc_dir_entry *rtstat_pde;
-+      if (!proc_net_fops_create(net, "rt_cache", S_IRUGO, &rt_cache_seq_fops))
-+              goto out;
-+      if (!(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO,
-+                      net->proc_net_stat)))
-+              goto out;
-+      rtstat_pde->proc_fops = &rt_cpu_seq_fops;
-+# ifdef CONFIG_NET_CLS_ROUTE
-+      if (!create_proc_read_entry("rt_acct", 0, net->proc_net,
-+                  ip_rt_acct_read, NULL))
-+              goto out;
-+# endif
-+#endif
-+      error = 0;
-+out:
-+      if (error)
-+              ip_rt_net_exit(net);
-+      return error;
++      for (p = &tbl->parms; p; p = p->next)
++              if ((p->dev && p->dev->ifindex == ifindex) ||
++                  (!p->dev && !ifindex))
++                      return p;
++
++      return NULL;
 +}
 +
-+struct pernet_operations ip_rt_net_ops = {
-+      .init = ip_rt_net_init,
-+      .exit = ip_rt_net_exit,
-+};
-+ 
- int __init ip_rt_init(void)
- {
-       int rc = 0;
-@@ -3245,20 +3083,7 @@
-               ip_rt_secret_interval;
-       add_timer(&rt_secret_timer);
--#ifdef CONFIG_PROC_FS
--      {
--      struct proc_dir_entry *rtstat_pde = NULL; /* keep gcc happy */
--      if (!proc_net_fops_create("rt_cache", S_IRUGO, &rt_cache_seq_fops) ||
--          !(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO,
--                                           proc_net_stat))) {
--              return -ENOMEM;
--      }
--      rtstat_pde->proc_fops = &rt_cpu_seq_fops;
--      }
--#ifdef CONFIG_NET_CLS_ROUTE
--      create_proc_read_entry("rt_acct", 0, proc_net, ip_rt_acct_read, NULL);
--#endif
--#endif
-+      register_pernet_subsys(&ip_rt_net_ops);
- #ifdef CONFIG_XFRM
-       xfrm_init();
-       xfrm4_init();
-diff -Nurb linux-2.6.22-570/net/ipv4/syncookies.c linux-2.6.22-590/net/ipv4/syncookies.c
---- linux-2.6.22-570/net/ipv4/syncookies.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/syncookies.c     2008-01-02 13:56:38.000000000 -0500
-@@ -253,7 +253,8 @@
-        * no easy way to do this.
-        */
-       {
--              struct flowi fl = { .nl_u = { .ip4_u =
-+              struct flowi fl = { .fl_net = &init_net,
-+                                  .nl_u = { .ip4_u =
-                                             { .daddr = ((opt && opt->srr) ?
-                                                         opt->faddr :
-                                                         ireq->rmt_addr),
-diff -Nurb linux-2.6.22-570/net/ipv4/sysctl_net_ipv4.c linux-2.6.22-590/net/ipv4/sysctl_net_ipv4.c
---- linux-2.6.22-570/net/ipv4/sysctl_net_ipv4.c        2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/sysctl_net_ipv4.c        2008-01-02 13:56:38.000000000 -0500
-@@ -29,21 +29,21 @@
- static int ip_local_port_range_max[] = { 65535, 65535 };
- #endif
--struct ipv4_config ipv4_config;
--
- #ifdef CONFIG_SYSCTL
+ static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
+       [NDTA_NAME]             = { .type = NLA_STRING },
+       [NDTA_THRESH1]          = { .type = NLA_U32 },
+@@ -1827,7 +1788,6 @@
  
- static
- int ipv4_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
-                       void __user *buffer, size_t *lenp, loff_t *ppos)
+ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
  {
--      int val = IPV4_DEVCONF_ALL(FORWARDING);
-+      struct net *net = ctl->extra2;
-+      int *valp = ctl->data;
-+      int old = *valp;
-       int ret;
-       ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+-      struct net *net = skb->sk->sk_net;
+       struct neigh_table *tbl;
+       struct ndtmsg *ndtmsg;
+       struct nlattr *tb[NDTA_MAX+1];
+@@ -1877,7 +1837,7 @@
+               if (tbp[NDTPA_IFINDEX])
+                       ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
  
--      if (write && IPV4_DEVCONF_ALL(FORWARDING) != val)
--              inet_forward_change();
-+      if (write && *valp != old)
-+              inet_forward_change(net);
+-              p = lookup_neigh_params(tbl, net, ifindex);
++              p = lookup_neigh_params(tbl, ifindex);
+               if (p == NULL) {
+                       err = -ENOENT;
+                       goto errout_tbl_lock;
+@@ -1952,7 +1912,6 @@
  
-       return ret;
- }
-@@ -53,6 +53,7 @@
-                        void __user *oldval, size_t __user *oldlenp,
-                        void __user *newval, size_t newlen)
+ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
  {
-+      struct net *net = table->extra2;
-       int *valp = table->data;
-       int new;
+-      struct net *net = skb->sk->sk_net;
+       int family, tidx, nidx = 0;
+       int tbl_skip = cb->args[0];
+       int neigh_skip = cb->args[1];
+@@ -1972,11 +1931,8 @@
+                                      NLM_F_MULTI) <= 0)
+                       break;
  
-@@ -85,7 +86,7 @@
-       }
+-              for (nidx = 0, p = tbl->parms.next; p; p = p->next) {
+-                      if (net != p->net)
+-                              continue;
+-
+-                      if (nidx++ < neigh_skip)
++              for (nidx = 0, p = tbl->parms.next; p; p = p->next, nidx++) {
++                      if (nidx < neigh_skip)
+                               continue;
  
-       *valp = new;
--      inet_forward_change();
-+      inet_forward_change(net);
-       return 1;
- }
+                       if (neightbl_fill_param_info(skb, tbl, p,
+@@ -2047,7 +2003,6 @@
+ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
+                           struct netlink_callback *cb)
+ {
+-      struct net * net = skb->sk->sk_net;
+       struct neighbour *n;
+       int rc, h, s_h = cb->args[1];
+       int idx, s_idx = idx = cb->args[2];
+@@ -2058,12 +2013,8 @@
+                       continue;
+               if (h > s_h)
+                       s_idx = 0;
+-              for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) {
+-                      int lidx;
+-                      if (n->dev->nd_net != net)
+-                              continue;
+-                      lidx = idx++;
+-                      if (lidx < s_idx)
++              for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next, idx++) {
++                      if (idx < s_idx)
+                               continue;
+                       if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,
+                                           cb->nlh->nlmsg_seq,
+@@ -2158,7 +2109,6 @@
+ static struct neighbour *neigh_get_first(struct seq_file *seq)
+ {
+       struct neigh_seq_state *state = seq->private;
+-      struct net * net = state->net;
+       struct neigh_table *tbl = state->tbl;
+       struct neighbour *n = NULL;
+       int bucket = state->bucket;
+@@ -2168,8 +2118,6 @@
+               n = tbl->hash_buckets[bucket];
  
-@@ -188,22 +189,6 @@
+               while (n) {
+-                      if (n->dev->nd_net != net)
+-                              goto next;
+                       if (state->neigh_sub_iter) {
+                               loff_t fakep = 0;
+                               void *v;
+@@ -2199,7 +2147,6 @@
+                                       loff_t *pos)
+ {
+       struct neigh_seq_state *state = seq->private;
+-      struct net * net = state->net;
+       struct neigh_table *tbl = state->tbl;
  
- ctl_table ipv4_table[] = {
-       {
--              .ctl_name       = NET_IPV4_TCP_TIMESTAMPS,
--              .procname       = "tcp_timestamps",
--              .data           = &sysctl_tcp_timestamps,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec
--      },
--      {
--              .ctl_name       = NET_IPV4_TCP_WINDOW_SCALING,
--              .procname       = "tcp_window_scaling",
--              .data           = &sysctl_tcp_window_scaling,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec
--      },
--      {
-               .ctl_name       = NET_IPV4_TCP_SACK,
-               .procname       = "tcp_sack",
-               .data           = &sysctl_tcp_sack,
-@@ -220,40 +205,6 @@
-               .proc_handler   = &proc_dointvec
-       },
-       {
--              .ctl_name       = NET_IPV4_FORWARD,
--              .procname       = "ip_forward",
--              .data           = &IPV4_DEVCONF_ALL(FORWARDING),
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &ipv4_sysctl_forward,
--              .strategy       = &ipv4_sysctl_forward_strategy
--      },
--      {
--              .ctl_name       = NET_IPV4_DEFAULT_TTL,
--              .procname       = "ip_default_ttl",
--              .data           = &sysctl_ip_default_ttl,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &ipv4_doint_and_flush,
--              .strategy       = &ipv4_doint_and_flush_strategy,
--      },
--      {
--              .ctl_name       = NET_IPV4_NO_PMTU_DISC,
--              .procname       = "ip_no_pmtu_disc",
--              .data           = &ipv4_config.no_pmtu_disc,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec
--      },
--      {
--              .ctl_name       = NET_IPV4_NONLOCAL_BIND,
--              .procname       = "ip_nonlocal_bind",
--              .data           = &sysctl_ip_nonlocal_bind,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec
--      },
--      {
-               .ctl_name       = NET_IPV4_TCP_SYN_RETRIES,
-               .procname       = "tcp_syn_retries",
-               .data           = &sysctl_tcp_syn_retries,
-@@ -286,39 +237,6 @@
-               .proc_handler   = &proc_dointvec
-       },
-       {
--              .ctl_name       = NET_IPV4_IPFRAG_HIGH_THRESH,
--              .procname       = "ipfrag_high_thresh",
--              .data           = &sysctl_ipfrag_high_thresh,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec
--      },
--      {
--              .ctl_name       = NET_IPV4_IPFRAG_LOW_THRESH,
--              .procname       = "ipfrag_low_thresh",
--              .data           = &sysctl_ipfrag_low_thresh,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec
--      },
--      {
--              .ctl_name       = NET_IPV4_DYNADDR,
--              .procname       = "ip_dynaddr",
--              .data           = &sysctl_ip_dynaddr,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec
--      },
--      {
--              .ctl_name       = NET_IPV4_IPFRAG_TIME,
--              .procname       = "ipfrag_time",
--              .data           = &sysctl_ipfrag_time,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec_jiffies,
--              .strategy       = &sysctl_jiffies
--      },
--      {
-               .ctl_name       = NET_IPV4_TCP_KEEPALIVE_TIME,
-               .procname       = "tcp_keepalive_time",
-               .data           = &sysctl_tcp_keepalive_time,
-@@ -422,17 +340,6 @@
-               .proc_handler   = &proc_dointvec
-       },
-       {
--              .ctl_name       = NET_IPV4_LOCAL_PORT_RANGE,
--              .procname       = "ip_local_port_range",
--              .data           = &sysctl_local_port_range,
--              .maxlen         = sizeof(sysctl_local_port_range),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec_minmax,
--              .strategy       = &sysctl_intvec,
--              .extra1         = ip_local_port_range_min,
--              .extra2         = ip_local_port_range_max
--      },
--      {
-               .ctl_name       = NET_IPV4_ICMP_ECHO_IGNORE_ALL,
-               .procname       = "icmp_echo_ignore_all",
-               .data           = &sysctl_icmp_echo_ignore_all,
-@@ -534,50 +441,6 @@
-               .proc_handler   = &proc_dointvec
-       },
-       {
--              .ctl_name       = NET_IPV4_INET_PEER_THRESHOLD,
--              .procname       = "inet_peer_threshold",
--              .data           = &inet_peer_threshold,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec
--      },
--      {
--              .ctl_name       = NET_IPV4_INET_PEER_MINTTL,
--              .procname       = "inet_peer_minttl",
--              .data           = &inet_peer_minttl,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec_jiffies,
--              .strategy       = &sysctl_jiffies
--      },
--      {
--              .ctl_name       = NET_IPV4_INET_PEER_MAXTTL,
--              .procname       = "inet_peer_maxttl",
--              .data           = &inet_peer_maxttl,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec_jiffies,
--              .strategy       = &sysctl_jiffies
--      },
--      {
--              .ctl_name       = NET_IPV4_INET_PEER_GC_MINTIME,
--              .procname       = "inet_peer_gc_mintime",
--              .data           = &inet_peer_gc_mintime,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec_jiffies,
--              .strategy       = &sysctl_jiffies
--      },
--      {
--              .ctl_name       = NET_IPV4_INET_PEER_GC_MAXTIME,
--              .procname       = "inet_peer_gc_maxtime",
--              .data           = &inet_peer_gc_maxtime,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec_jiffies,
--              .strategy       = &sysctl_jiffies
--      },
--      {
-               .ctl_name       = NET_TCP_ORPHAN_RETRIES,
-               .procname       = "tcp_orphan_retries",
-               .data           = &sysctl_tcp_orphan_retries,
-@@ -706,24 +569,6 @@
-               .proc_handler   = &proc_dointvec
-       },
-       {
--              .ctl_name       = NET_IPV4_IPFRAG_SECRET_INTERVAL,
--              .procname       = "ipfrag_secret_interval",
--              .data           = &sysctl_ipfrag_secret_interval,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec_jiffies,
--              .strategy       = &sysctl_jiffies
--      },
--      {
--              .ctl_name       = NET_IPV4_IPFRAG_MAX_DIST,
--              .procname       = "ipfrag_max_dist",
--              .data           = &sysctl_ipfrag_max_dist,
--              .maxlen         = sizeof(int),
--              .mode           = 0644,
--              .proc_handler   = &proc_dointvec_minmax,
--              .extra1         = &zero
--      },
--      {
-               .ctl_name       = NET_TCP_NO_METRICS_SAVE,
-               .procname       = "tcp_no_metrics_save",
-               .data           = &sysctl_tcp_nometrics_save,
-@@ -865,6 +710,181 @@
-       { .ctl_name = 0 }
- };
+       if (state->neigh_sub_iter) {
+@@ -2211,8 +2158,6 @@
  
--#endif /* CONFIG_SYSCTL */
-+struct ctl_table multi_ipv4_table[] = {
-+      {
-+              /* .data is filled in by devinet_net_init.
-+               * As a consequence this table entry must be the first
-+               * entry in multi_ipv4_table.
-+               */
-+              .ctl_name       = NET_IPV4_FORWARD,
-+              .procname       = "ip_forward",
-+              .data           = NULL,
-+              .extra2         = &init_net,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &ipv4_sysctl_forward,
-+              .strategy       = &ipv4_sysctl_forward_strategy
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_DEFAULT_TTL,
-+              .procname       = "ip_default_ttl",
-+              .data           = &init_net.sysctl_ip_default_ttl,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &ipv4_doint_and_flush,
-+              .strategy       = &ipv4_doint_and_flush_strategy,
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_NO_PMTU_DISC,
-+              .procname       = "ip_no_pmtu_disc",
-+              .data           = &init_net.sysctl_ipv4_no_pmtu_disc,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_NONLOCAL_BIND,
-+              .procname       = "ip_nonlocal_bind",
-+              .data           = &init_net.sysctl_ip_nonlocal_bind,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_LOCAL_PORT_RANGE,
-+              .procname       = "ip_local_port_range",
-+              .data           = &init_net.sysctl_local_port_range,
-+              .maxlen         = sizeof(init_net.sysctl_local_port_range),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec_minmax,
-+              .strategy       = &sysctl_intvec,
-+              .extra1         = ip_local_port_range_min,
-+              .extra2         = ip_local_port_range_max
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_IPFRAG_HIGH_THRESH,
-+              .procname       = "ipfrag_high_thresh",
-+              .data           = &init_net.sysctl_ipfrag_high_thresh,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_IPFRAG_LOW_THRESH,
-+              .procname       = "ipfrag_low_thresh",
-+              .data           = &init_net.sysctl_ipfrag_low_thresh,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_IPFRAG_TIME,
-+              .procname       = "ipfrag_time",
-+              .data           = &init_net.sysctl_ipfrag_time,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec_jiffies,
-+              .strategy       = &sysctl_jiffies
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_IPFRAG_SECRET_INTERVAL,
-+              .procname       = "ipfrag_secret_interval",
-+              .data           = &init_net.sysctl_ipfrag_secret_interval,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec_jiffies,
-+              .strategy       = &sysctl_jiffies
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_IPFRAG_MAX_DIST,
-+              .procname       = "ipfrag_max_dist",
-+              .data           = &init_net.sysctl_ipfrag_max_dist,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec_minmax,
-+              .extra1         = &zero
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_DYNADDR,
-+              .procname       = "ip_dynaddr",
-+              .data           = &init_net.sysctl_ip_dynaddr,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_LOCAL_PORT_RANGE,
-+              .procname       = "ip_local_port_range",
-+              .data           = &init_net.sysctl_local_port_range,
-+              .maxlen         = sizeof(init_net.sysctl_local_port_range),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec_minmax,
-+              .strategy       = &sysctl_intvec,
-+              .extra1         = ip_local_port_range_min,
-+              .extra2         = ip_local_port_range_max
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_INET_PEER_THRESHOLD,
-+              .procname       = "inet_peer_threshold",
-+              .data           = &init_net.inet_peer_threshold,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_INET_PEER_MINTTL,
-+              .procname       = "inet_peer_minttl",
-+              .data           = &init_net.inet_peer_minttl,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec_jiffies,
-+              .strategy       = &sysctl_jiffies
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_INET_PEER_MAXTTL,
-+              .procname       = "inet_peer_maxttl",
-+              .data           = &init_net.inet_peer_maxttl,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec_jiffies,
-+              .strategy       = &sysctl_jiffies
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_INET_PEER_GC_MINTIME,
-+              .procname       = "inet_peer_gc_mintime",
-+              .data           = &init_net.inet_peer_gc_mintime,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec_jiffies,
-+              .strategy       = &sysctl_jiffies
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_INET_PEER_GC_MAXTIME,
-+              .procname       = "inet_peer_gc_maxtime",
-+              .data           = &init_net.inet_peer_gc_maxtime,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec_jiffies,
-+              .strategy       = &sysctl_jiffies
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_TCP_TIMESTAMPS,
-+              .procname       = "tcp_timestamps",
-+              .data           = &init_net.sysctl_tcp_timestamps,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec
-+
-+      },
-+      {
-+              .ctl_name       = NET_IPV4_TCP_WINDOW_SCALING,
-+              .procname       = "tcp_window_scaling",
-+              .data           = &init_net.sysctl_tcp_window_scaling,
-+              .maxlen         = sizeof(int),
-+              .mode           = 0644,
-+              .proc_handler   = &proc_dointvec
-+      },
-+      {}
-+};
+       while (1) {
+               while (n) {
+-                      if (n->dev->nd_net != net)
+-                              goto next;
+                       if (state->neigh_sub_iter) {
+                               void *v = state->neigh_sub_iter(state, n, pos);
+                               if (v)
+@@ -2259,7 +2204,6 @@
+ static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
+ {
+       struct neigh_seq_state *state = seq->private;
+-      struct net * net = state->net;
+       struct neigh_table *tbl = state->tbl;
+       struct pneigh_entry *pn = NULL;
+       int bucket = state->bucket;
+@@ -2267,8 +2211,6 @@
+       state->flags |= NEIGH_SEQ_IS_PNEIGH;
+       for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
+               pn = tbl->phash_buckets[bucket];
+-              while (pn && (pn->net != net))
+-                      pn = pn->next;
+               if (pn)
+                       break;
+       }
+@@ -2282,7 +2224,6 @@
+                                           loff_t *pos)
+ {
+       struct neigh_seq_state *state = seq->private;
+-      struct net * net = state->net;
+       struct neigh_table *tbl = state->tbl;
+       pn = pn->next;
+@@ -2290,8 +2231,6 @@
+               if (++state->bucket > PNEIGH_HASHMASK)
+                       break;
+               pn = tbl->phash_buckets[state->bucket];
+-              while (pn && (pn->net != net))
+-                      pn = pn->next;
+               if (pn)
+                       break;
+       }
+@@ -2494,7 +2433,6 @@
+ static void __neigh_notify(struct neighbour *n, int type, int flags)
+ {
+-      struct net * net = n->dev->nd_net;
+       struct sk_buff *skb;
+       int err = -ENOBUFS;
  
--EXPORT_SYMBOL(ipv4_config);
-+#endif /* CONFIG_SYSCTL */
-diff -Nurb linux-2.6.22-570/net/ipv4/tcp.c linux-2.6.22-590/net/ipv4/tcp.c
---- linux-2.6.22-570/net/ipv4/tcp.c    2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/tcp.c    2008-01-02 13:56:38.000000000 -0500
-@@ -2409,6 +2409,23 @@
+@@ -2509,10 +2447,10 @@
+               kfree_skb(skb);
+               goto errout;
+       }
+-      err = rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
++      err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
+ errout:
+       if (err < 0)
+-              rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
++              rtnl_set_sk_err(RTNLGRP_NEIGH, err);
  }
- __setup("thash_entries=", set_thash_entries);
  
-+static int tcp_net_init(struct net *net)
-+{
-+      /*
-+       * This array holds the first and last local port number.
-+       */
-+      net->sysctl_local_port_range[0] = 32768;
-+      net->sysctl_local_port_range[1] = 61000;
-+
-+      net->sysctl_tcp_timestamps = 1;
-+      net->sysctl_tcp_window_scaling = 1;
-+      return 0;
-+}
-+
-+static struct pernet_operations tcp_net_ops = {
-+      .init = tcp_net_init,
-+};
-+
- void __init tcp_init(void)
+ void neigh_app_ns(struct neighbour *n)
+@@ -2710,7 +2648,6 @@
+       if (!t)
+               return -ENOBUFS;
+-
+       t->neigh_vars[0].data  = &p->mcast_probes;
+       t->neigh_vars[1].data  = &p->ucast_probes;
+       t->neigh_vars[2].data  = &p->app_probes;
+@@ -2779,7 +2716,7 @@
+       t->neigh_proto_dir[0].child    = t->neigh_neigh_dir;
+       t->neigh_root_dir[0].child     = t->neigh_proto_dir;
+-      t->sysctl_header = register_net_sysctl_table(p->net, t->neigh_root_dir);
++      t->sysctl_header = register_sysctl_table(t->neigh_root_dir);
+       if (!t->sysctl_header) {
+               err = -ENOBUFS;
+               goto free_procname;
+@@ -2801,7 +2738,7 @@
+       if (p->sysctl_table) {
+               struct neigh_sysctl_table *t = p->sysctl_table;
+               p->sysctl_table = NULL;
+-              unregister_net_sysctl_table(t->sysctl_header);
++              unregister_sysctl_table(t->sysctl_header);
+               kfree(t->neigh_dev[0].procname);
+               kfree(t);
+       }
+@@ -2834,7 +2771,6 @@
+ EXPORT_SYMBOL(neigh_lookup);
+ EXPORT_SYMBOL(neigh_lookup_nodev);
+ EXPORT_SYMBOL(neigh_parms_alloc);
+-EXPORT_SYMBOL(neigh_parms_alloc_default);
+ EXPORT_SYMBOL(neigh_parms_release);
+ EXPORT_SYMBOL(neigh_rand_reach_time);
+ EXPORT_SYMBOL(neigh_resolve_output);
+diff -Nurb linux-2.6.22-590/net/core/net-sysfs.c linux-2.6.22-570/net/core/net-sysfs.c
+--- linux-2.6.22-590/net/core/net-sysfs.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/net-sysfs.c      2007-07-08 19:32:17.000000000 -0400
+@@ -13,9 +13,7 @@
+ #include <linux/kernel.h>
+ #include <linux/netdevice.h>
+ #include <linux/if_arp.h>
+-#include <linux/nsproxy.h>
+ #include <net/sock.h>
+-#include <net/net_namespace.h>
+ #include <linux/rtnetlink.h>
+ #include <linux/wireless.h>
+ #include <net/iw_handler.h>
+@@ -31,16 +29,16 @@
+ }
+ /* use same locking rules as GIF* ioctl's */
+-static ssize_t netdev_show(const struct device *device,
++static ssize_t netdev_show(const struct device *dev,
+                          struct device_attribute *attr, char *buf,
+                          ssize_t (*format)(const struct net_device *, char *))
  {
-       struct sk_buff *skb = NULL;
-@@ -2502,6 +2519,8 @@
-       sysctl_tcp_rmem[1] = 87380;
-       sysctl_tcp_rmem[2] = max(87380, max_share);
+-      struct net_device *dev = to_net_dev(device);
++      struct net_device *net = to_net_dev(dev);
+       ssize_t ret = -EINVAL;
  
-+      register_pernet_subsys(&tcp_net_ops);
-+
-       printk(KERN_INFO "TCP: Hash tables configured "
-              "(established %d bind %d)\n",
-              tcp_hashinfo.ehash_size, tcp_hashinfo.bhash_size);
-diff -Nurb linux-2.6.22-570/net/ipv4/tcp_input.c linux-2.6.22-590/net/ipv4/tcp_input.c
---- linux-2.6.22-570/net/ipv4/tcp_input.c      2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/tcp_input.c      2008-01-02 13:56:38.000000000 -0500
-@@ -72,8 +72,6 @@
- #include <asm/unaligned.h>
- #include <net/netdma.h>
+       read_lock(&dev_base_lock);
+-      if (dev_isalive(dev))
+-              ret = (*format)(dev, buf);
++      if (dev_isalive(net))
++              ret = (*format)(net, buf);
+       read_unlock(&dev_base_lock);
  
--int sysctl_tcp_timestamps __read_mostly = 1;
--int sysctl_tcp_window_scaling __read_mostly = 1;
- int sysctl_tcp_sack __read_mostly = 1;
- int sysctl_tcp_fack __read_mostly = 1;
- int sysctl_tcp_reordering __read_mostly = TCP_FASTRETRANS_THRESH;
-@@ -2922,7 +2920,7 @@
-                                       break;
-                               case TCPOPT_WINDOW:
-                                       if (opsize==TCPOLEN_WINDOW && th->syn && !estab)
--                                              if (sysctl_tcp_window_scaling) {
-+                                              if (init_net.sysctl_tcp_window_scaling) {
-                                                       __u8 snd_wscale = *(__u8 *) ptr;
-                                                       opt_rx->wscale_ok = 1;
-                                                       if (snd_wscale > 14) {
-@@ -2938,7 +2936,7 @@
-                               case TCPOPT_TIMESTAMP:
-                                       if (opsize==TCPOLEN_TIMESTAMP) {
-                                               if ((estab && opt_rx->tstamp_ok) ||
--                                                  (!estab && sysctl_tcp_timestamps)) {
-+                                                  (!estab && init_net.sysctl_tcp_timestamps)) {
-                                                       opt_rx->saw_tstamp = 1;
-                                                       opt_rx->rcv_tsval = ntohl(get_unaligned((__be32 *)ptr));
-                                                       opt_rx->rcv_tsecr = ntohl(get_unaligned((__be32 *)(ptr+4)));
-diff -Nurb linux-2.6.22-570/net/ipv4/tcp_ipv4.c linux-2.6.22-590/net/ipv4/tcp_ipv4.c
---- linux-2.6.22-570/net/ipv4/tcp_ipv4.c       2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/tcp_ipv4.c       2008-01-02 13:56:38.000000000 -0500
-@@ -71,6 +71,7 @@
- #include <net/timewait_sock.h>
- #include <net/xfrm.h>
- #include <net/netdma.h>
-+#include <net/net_namespace.h>
+       return ret;
+@@ -48,9 +46,9 @@
  
- #include <linux/inet.h>
- #include <linux/ipv6.h>
-@@ -353,6 +354,7 @@
+ /* generate a show function for simple field */
+ #define NETDEVICE_SHOW(field, format_string)                          \
+-static ssize_t format_##field(const struct net_device *dev, char *buf)        \
++static ssize_t format_##field(const struct net_device *net, char *buf)        \
+ {                                                                     \
+-      return sprintf(buf, format_string, dev->field);                 \
++      return sprintf(buf, format_string, net->field);                 \
+ }                                                                     \
+ static ssize_t show_##field(struct device *dev,                               \
+                           struct device_attribute *attr, char *buf)   \
+@@ -60,11 +58,11 @@
  
- void tcp_v4_err(struct sk_buff *skb, u32 info)
+ /* use same locking and permission rules as SIF* ioctl's */
+-static ssize_t netdev_store(struct device *device, struct device_attribute *attr,
++static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t len,
+                           int (*set)(struct net_device *, unsigned long))
  {
-+      struct net *net = skb->dev->nd_net;
-       struct iphdr *iph = (struct iphdr *)skb->data;
-       struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
-       struct tcp_sock *tp;
-@@ -369,7 +371,7 @@
+-      struct net_device *dev = to_net_dev(device);
++      struct net_device *net = to_net_dev(dev);
+       char *endp;
+       unsigned long new;
+       int ret = -EINVAL;
+@@ -77,8 +75,8 @@
+               goto err;
+       rtnl_lock();
+-      if (dev_isalive(dev)) {
+-              if ((ret = (*set)(dev, new)) == 0)
++      if (dev_isalive(net)) {
++              if ((ret = (*set)(net, new)) == 0)
+                       ret = len;
        }
+       rtnl_unlock();
+@@ -105,45 +103,45 @@
+       return cp - buf;
+ }
  
-       sk = inet_lookup(&tcp_hashinfo, iph->daddr, th->dest, iph->saddr,
--                       th->source, inet_iif(skb));
-+                       th->source, inet_iif(skb), net);
-       if (!sk) {
-               ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
-               return;
-@@ -1499,7 +1501,8 @@
-               return tcp_check_req(sk, skb, req, prev);
+-static ssize_t show_address(struct device *device, struct device_attribute *attr,
++static ssize_t show_address(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+ {
+-      struct net_device *dev = to_net_dev(device);
++      struct net_device *net = to_net_dev(dev);
+       ssize_t ret = -EINVAL;
  
-       nsk = inet_lookup_established(&tcp_hashinfo, iph->saddr, th->source,
--                                    iph->daddr, th->dest, inet_iif(skb));
-+                                    iph->daddr, th->dest, inet_iif(skb),
-+                                    sk->sk_net);
+       read_lock(&dev_base_lock);
+-      if (dev_isalive(dev))
+-          ret = format_addr(buf, dev->dev_addr, dev->addr_len);
++      if (dev_isalive(net))
++          ret = format_addr(buf, net->dev_addr, net->addr_len);
+       read_unlock(&dev_base_lock);
+       return ret;
+ }
  
-       if (nsk) {
-               if (nsk->sk_state != TCP_TIME_WAIT) {
-@@ -1618,6 +1621,7 @@
+-static ssize_t show_broadcast(struct device *device,
++static ssize_t show_broadcast(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+ {
+-      struct net_device *dev = to_net_dev(device);
+-      if (dev_isalive(dev))
+-              return format_addr(buf, dev->broadcast, dev->addr_len);
++      struct net_device *net = to_net_dev(dev);
++      if (dev_isalive(net))
++              return format_addr(buf, net->broadcast, net->addr_len);
+       return -EINVAL;
+ }
  
- int tcp_v4_rcv(struct sk_buff *skb)
+-static ssize_t show_carrier(struct device *device,
++static ssize_t show_carrier(struct device *dev,
+                           struct device_attribute *attr, char *buf)
  {
-+      struct net *net = skb->dev->nd_net;
-       const struct iphdr *iph;
-       struct tcphdr *th;
-       struct sock *sk;
-@@ -1657,7 +1661,7 @@
-       TCP_SKB_CB(skb)->sacked  = 0;
+-      struct net_device *dev = to_net_dev(device);
+-      if (netif_running(dev)) {
+-              return sprintf(buf, fmt_dec, !!netif_carrier_ok(dev));
++      struct net_device *netdev = to_net_dev(dev);
++      if (netif_running(netdev)) {
++              return sprintf(buf, fmt_dec, !!netif_carrier_ok(netdev));
+       }
+       return -EINVAL;
+ }
  
-       sk = __inet_lookup(&tcp_hashinfo, iph->saddr, th->source,
--                         iph->daddr, th->dest, inet_iif(skb));
-+                         iph->daddr, th->dest, inet_iif(skb), net);
-       if (!sk)
-               goto no_tcp_socket;
+-static ssize_t show_dormant(struct device *device,
++static ssize_t show_dormant(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+ {
+-      struct net_device *dev = to_net_dev(device);
++      struct net_device *netdev = to_net_dev(dev);
  
-@@ -1732,7 +1736,7 @@
-       case TCP_TW_SYN: {
-               struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo,
-                                                       iph->daddr, th->dest,
--                                                      inet_iif(skb));
-+                                                      inet_iif(skb), net);
-               if (sk2) {
-                       inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
-                       inet_twsk_put(inet_twsk(sk));
-@@ -1766,7 +1770,7 @@
-       int release_it = 0;
+-      if (netif_running(dev))
+-              return sprintf(buf, fmt_dec, !!netif_dormant(dev));
++      if (netif_running(netdev))
++              return sprintf(buf, fmt_dec, !!netif_dormant(netdev));
  
-       if (!rt || rt->rt_dst != inet->daddr) {
--              peer = inet_getpeer(inet->daddr, 1);
-+              peer = inet_getpeer(sk->sk_net, inet->daddr, 1);
-               release_it = 1;
-       } else {
-               if (!rt->peer)
-@@ -1791,7 +1795,7 @@
+       return -EINVAL;
+ }
+@@ -158,15 +156,15 @@
+       "up"
+ };
  
- int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
+-static ssize_t show_operstate(struct device *device,
++static ssize_t show_operstate(struct device *dev,
+                             struct device_attribute *attr, char *buf)
  {
--      struct inet_peer *peer = inet_getpeer(tw->tw_daddr, 1);
-+      struct inet_peer *peer = inet_getpeer(tw->tw_net, tw->tw_daddr, 1);
+-      const struct net_device *dev = to_net_dev(device);
++      const struct net_device *netdev = to_net_dev(dev);
+       unsigned char operstate;
  
-       if (peer) {
-               const struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
-@@ -1980,7 +1984,8 @@
-                               if (req->sk &&
-                                       !nx_check(req->sk->sk_nid, VS_WATCH_P | VS_IDENT))
-                                       continue;
--                              if (req->rsk_ops->family == st->family) {
-+                              if ((req->rsk_ops->family == st->family) &&
-+                                  (req->sk->sk_net == st->net)) {
-                                       cur = req;
-                                       goto out;
-                               }
-@@ -2004,6 +2009,8 @@
-       }
- get_sk:
-       sk_for_each_from(sk, node) {
-+              if (sk->sk_net != st->net)
-+                      continue;
-               vxdprintk(VXD_CBIT(net, 6), "sk: %p [#%d] (from %d)",
-                       sk, sk->sk_nid, nx_current_nid());
-               if (!nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT))
-@@ -2054,11 +2061,10 @@
-               struct hlist_node *node;
-               struct inet_timewait_sock *tw;
+       read_lock(&dev_base_lock);
+-      operstate = dev->operstate;
+-      if (!netif_running(dev))
++      operstate = netdev->operstate;
++      if (!netif_running(netdev))
+               operstate = IF_OPER_DOWN;
+       read_unlock(&dev_base_lock);
  
--              /* We can reschedule _before_ having picked the target: */
--              cond_resched_softirq();
--
--              read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
-+              read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
-               sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
-+                      if (sk->sk_net != st->net)
-+                              continue;
-                       vxdprintk(VXD_CBIT(net, 6),
-                               "sk,egf: %p [#%d] (from %d)",
-                               sk, sk->sk_nid, nx_current_nid());
-@@ -2072,6 +2078,8 @@
-               st->state = TCP_SEQ_STATE_TIME_WAIT;
-               inet_twsk_for_each(tw, node,
-                                  &tcp_hashinfo.ehash[st->bucket].twchain) {
-+                      if (tw->tw_net != st->net)
-+                              continue;
-                       vxdprintk(VXD_CBIT(net, 6),
-                               "tw: %p [#%d] (from %d)",
-                               tw, tw->tw_nid, nx_current_nid());
-@@ -2082,7 +2090,7 @@
-                       rc = tw;
-                       goto out;
-               }
--              read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
-+              read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
-               st->state = TCP_SEQ_STATE_ESTABLISHED;
-       }
- out:
-@@ -2102,7 +2110,8 @@
-               tw = cur;
-               tw = tw_next(tw);
- get_tw:
--              while (tw && (tw->tw_family != st->family ||
-+              while (tw && ((tw->tw_net != st->net) || 
-+                                      (tw->tw_family != st->family) ||
-                       !nx_check(tw->tw_nid, VS_WATCH_P | VS_IDENT))) {
-                       tw = tw_next(tw);
-               }
-@@ -2110,14 +2119,11 @@
-                       cur = tw;
-                       goto out;
-               }
--              read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
-+              read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
-               st->state = TCP_SEQ_STATE_ESTABLISHED;
+@@ -179,57 +177,57 @@
+ /* read-write attributes */
+ NETDEVICE_SHOW(mtu, fmt_dec);
  
--              /* We can reschedule between buckets: */
--              cond_resched_softirq();
--
-               if (++st->bucket < tcp_hashinfo.ehash_size) {
--                      read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
-+                      read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
-                       sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
-               } else {
-                       cur = NULL;
-@@ -2130,6 +2136,8 @@
-               vxdprintk(VXD_CBIT(net, 6),
-                       "sk,egn: %p [#%d] (from %d)",
-                       sk, sk->sk_nid, nx_current_nid());
-+              if (sk->sk_net != st->net)
-+                      continue;
-               if (!nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT))
-                       continue;
-               if (sk->sk_family == st->family)
-@@ -2167,7 +2175,6 @@
+-static int change_mtu(struct net_device *dev, unsigned long new_mtu)
++static int change_mtu(struct net_device *net, unsigned long new_mtu)
+ {
+-      return dev_set_mtu(dev, (int) new_mtu);
++      return dev_set_mtu(net, (int) new_mtu);
+ }
  
-       if (!rc) {
-               inet_listen_unlock(&tcp_hashinfo);
--              local_bh_disable();
-               st->state = TCP_SEQ_STATE_ESTABLISHED;
-               rc        = established_get_idx(seq, pos);
-       }
-@@ -2200,7 +2207,6 @@
-               rc = listening_get_next(seq, v);
-               if (!rc) {
-                       inet_listen_unlock(&tcp_hashinfo);
--                      local_bh_disable();
-                       st->state = TCP_SEQ_STATE_ESTABLISHED;
-                       rc        = established_get_first(seq);
-               }
-@@ -2232,8 +2238,7 @@
-       case TCP_SEQ_STATE_TIME_WAIT:
-       case TCP_SEQ_STATE_ESTABLISHED:
-               if (v)
--                      read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
--              local_bh_enable();
-+                      read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
-               break;
-       }
+-static ssize_t store_mtu(struct device *device, struct device_attribute *attr,
++static ssize_t store_mtu(struct device *dev, struct device_attribute *attr,
+                        const char *buf, size_t len)
+ {
+-      return netdev_store(device, attr, buf, len, change_mtu);
++      return netdev_store(dev, attr, buf, len, change_mtu);
  }
-@@ -2262,6 +2267,7 @@
-               goto out_kfree;
-       seq          = file->private_data;
-       seq->private = s;
-+      s->net = get_net(PROC_NET(inode));
- out:
-       return rc;
- out_kfree:
-@@ -2269,20 +2275,30 @@
-       goto out;
+ NETDEVICE_SHOW(flags, fmt_hex);
+-static int change_flags(struct net_device *dev, unsigned long new_flags)
++static int change_flags(struct net_device *net, unsigned long new_flags)
+ {
+-      return dev_change_flags(dev, (unsigned) new_flags);
++      return dev_change_flags(net, (unsigned) new_flags);
  }
  
--int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
-+static int tcp_seq_release(struct inode *inode, struct file *file)
-+{
-+      struct seq_file *seq = file->private_data;
-+      struct tcp_iter_state *st = seq->private;
-+      put_net(st->net);
-+      return seq_release_private(inode, file);
-+}
-+
-+int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo)
+-static ssize_t store_flags(struct device *device, struct device_attribute *attr,
++static ssize_t store_flags(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t len)
  {
-       int rc = 0;
-       struct proc_dir_entry *p;
+-      return netdev_store(device, attr, buf, len, change_flags);
++      return netdev_store(dev, attr, buf, len, change_flags);
+ }
  
-       if (!afinfo)
-               return -EINVAL;
-+      if (net == &init_net) {
-       afinfo->seq_fops->owner         = afinfo->owner;
-       afinfo->seq_fops->open          = tcp_seq_open;
-       afinfo->seq_fops->read          = seq_read;
-       afinfo->seq_fops->llseek        = seq_lseek;
--      afinfo->seq_fops->release       = seq_release_private;
-+              afinfo->seq_fops->release       = tcp_seq_release;
-+      }
+ NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
  
--      p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);
-+      p = proc_net_fops_create(net, afinfo->name, S_IRUGO, afinfo->seq_fops);
-       if (p)
-               p->data = afinfo;
-       else
-@@ -2290,11 +2306,12 @@
-       return rc;
+-static int change_tx_queue_len(struct net_device *dev, unsigned long new_len)
++static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
+ {
+-      dev->tx_queue_len = new_len;
++      net->tx_queue_len = new_len;
+       return 0;
  }
  
--void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo)
-+void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo)
+-static ssize_t store_tx_queue_len(struct device *device,
++static ssize_t store_tx_queue_len(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t len)
  {
-       if (!afinfo)
-               return;
--      proc_net_remove(afinfo->name);
-+      proc_net_remove(net, afinfo->name);
-+      if (net == &init_net)
-       memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
+-      return netdev_store(device, attr, buf, len, change_tx_queue_len);
++      return netdev_store(dev, attr, buf, len, change_tx_queue_len);
  }
  
-@@ -2439,14 +2456,29 @@
-       .seq_fops       = &tcp4_seq_fops,
- };
+ NETDEVICE_SHOW(weight, fmt_dec);
  
-+static int tcp4_proc_net_init(struct net *net)
-+{
-+      return tcp_proc_register(net, &tcp4_seq_afinfo);
-+}
-+
-+static void tcp4_proc_net_exit(struct net *net)
-+{
-+      tcp_proc_unregister(net, &tcp4_seq_afinfo);
-+}
-+
-+static struct pernet_operations tcp4_proc_net_ops = {
-+      .init = tcp4_proc_net_init,
-+      .exit = tcp4_proc_net_exit,
-+};
-+
- int __init tcp4_proc_init(void)
+-static int change_weight(struct net_device *dev, unsigned long new_weight)
++static int change_weight(struct net_device *net, unsigned long new_weight)
  {
--      return tcp_proc_register(&tcp4_seq_afinfo);
-+      return register_pernet_subsys(&tcp4_proc_net_ops);
+-      dev->weight = new_weight;
++      net->weight = new_weight;
+       return 0;
  }
  
- void tcp4_proc_exit(void)
+-static ssize_t store_weight(struct device *device, struct device_attribute *attr,
++static ssize_t store_weight(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t len)
  {
--      tcp_proc_unregister(&tcp4_seq_afinfo);
-+      unregister_pernet_subsys(&tcp4_proc_net_ops);
+-      return netdev_store(device, attr, buf, len, change_weight);
++      return netdev_store(dev, attr, buf, len, change_weight);
  }
- #endif /* CONFIG_PROC_FS */
  
-@@ -2508,6 +2540,5 @@
- EXPORT_SYMBOL(tcp_proc_register);
- EXPORT_SYMBOL(tcp_proc_unregister);
- #endif
--EXPORT_SYMBOL(sysctl_local_port_range);
- EXPORT_SYMBOL(sysctl_tcp_low_latency);
+ static struct device_attribute net_class_attributes[] = {
+@@ -449,23 +447,6 @@
+       kfree((char *)dev - dev->padded);
+ }
  
-diff -Nurb linux-2.6.22-570/net/ipv4/tcp_ipv4.c.orig linux-2.6.22-590/net/ipv4/tcp_ipv4.c.orig
---- linux-2.6.22-570/net/ipv4/tcp_ipv4.c.orig  2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/tcp_ipv4.c.orig  1969-12-31 19:00:00.000000000 -0500
-@@ -1,2483 +0,0 @@
--/*
-- * INET               An implementation of the TCP/IP protocol suite for the LINUX
-- *            operating system.  INET is implemented using the  BSD Socket
-- *            interface as the means of communication with the user level.
-- *
-- *            Implementation of the Transmission Control Protocol(TCP).
-- *
-- * Version:   $Id: tcp_ipv4.c,v 1.240 2002/02/01 22:01:04 davem Exp $
-- *
-- *            IPv4 specific functions
-- *
-- *
-- *            code split from:
-- *            linux/ipv4/tcp.c
-- *            linux/ipv4/tcp_input.c
-- *            linux/ipv4/tcp_output.c
-- *
-- *            See tcp.c for author information
-- *
-- *    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.
-- */
+-static const void *net_current_tag(void)
+-{
+-      return current->nsproxy->net_ns;
+-}
 -
--/*
-- * Changes:
-- *            David S. Miller :       New socket lookup architecture.
-- *                                    This code is dedicated to John Dyson.
-- *            David S. Miller :       Change semantics of established hash,
-- *                                    half is devoted to TIME_WAIT sockets
-- *                                    and the rest go in the other half.
-- *            Andi Kleen :            Add support for syncookies and fixed
-- *                                    some bugs: ip options weren't passed to
-- *                                    the TCP layer, missed a check for an
-- *                                    ACK bit.
-- *            Andi Kleen :            Implemented fast path mtu discovery.
-- *                                    Fixed many serious bugs in the
-- *                                    request_sock handling and moved
-- *                                    most of it into the af independent code.
-- *                                    Added tail drop and some other bugfixes.
-- *                                    Added new listen semantics.
-- *            Mike McLagan    :       Routing by source
-- *    Juan Jose Ciarlante:            ip_dynaddr bits
-- *            Andi Kleen:             various fixes.
-- *    Vitaly E. Lavrov        :       Transparent proxy revived after year
-- *                                    coma.
-- *    Andi Kleen              :       Fix new listen.
-- *    Andi Kleen              :       Fix accept error reporting.
-- *    YOSHIFUJI Hideaki @USAGI and:   Support IPV6_V6ONLY socket option, which
-- *    Alexey Kuznetsov                allow both IPv4 and IPv6 sockets to bind
-- *                                    a single port at the same time.
-- */
+-static const void *net_kobject_tag(struct kobject *kobj)
+-{
+-      struct net_device *dev;
+-      dev = container_of(kobj, struct net_device, dev.kobj);
+-      return dev->nd_net;
+-}
 -
+-static const struct shadow_dir_operations net_shadow_dir_operations = {
+-      .current_tag = net_current_tag,
+-      .kobject_tag = net_kobject_tag,
+-};
 -
--#include <linux/types.h>
--#include <linux/fcntl.h>
--#include <linux/module.h>
--#include <linux/random.h>
+ static struct class net_class = {
+       .name = "net",
+       .dev_release = netdev_release,
+@@ -473,43 +454,42 @@
+ #ifdef CONFIG_HOTPLUG
+       .dev_uevent = netdev_uevent,
+ #endif
+-      .shadow_ops = &net_shadow_dir_operations,
+ };
+ /* Delete sysfs entries but hold kobject reference until after all
+  * netdev references are gone.
+  */
+-void netdev_unregister_sysfs(struct net_device * dev)
++void netdev_unregister_sysfs(struct net_device * net)
+ {
+-      struct device *device = &(dev->dev);
++      struct device *dev = &(net->dev);
+-      kobject_get(&device->kobj);
+-      device_del(device);
++      kobject_get(&dev->kobj);
++      device_del(dev);
+ }
+ /* Create sysfs entries for network device. */
+-int netdev_register_sysfs(struct net_device *dev)
++int netdev_register_sysfs(struct net_device *net)
+ {
+-      struct device *device = &(dev->dev);
+-      struct attribute_group **groups = dev->sysfs_groups;
++      struct device *dev = &(net->dev);
++      struct attribute_group **groups = net->sysfs_groups;
+-      device_initialize(device);
+-      device->class = &net_class;
+-      device->platform_data = dev;
+-      device->groups = groups;
++      device_initialize(dev);
++      dev->class = &net_class;
++      dev->platform_data = net;
++      dev->groups = groups;
+       BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ);
+-      strlcpy(device->bus_id, dev->name, BUS_ID_SIZE);
++      strlcpy(dev->bus_id, net->name, BUS_ID_SIZE);
+-      if (dev->get_stats)
++      if (net->get_stats)
+               *groups++ = &netstat_group;
+ #ifdef CONFIG_WIRELESS_EXT
+-      if (dev->wireless_handlers && dev->wireless_handlers->get_wireless_stats)
++      if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
+               *groups++ = &wireless_group;
+ #endif
+-      return device_add(device);
++      return device_add(dev);
+ }
+ int netdev_sysfs_init(void)
+diff -Nurb linux-2.6.22-590/net/core/net_namespace.c linux-2.6.22-570/net/core/net_namespace.c
+--- linux-2.6.22-590/net/core/net_namespace.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/net_namespace.c  1969-12-31 19:00:00.000000000 -0500
+@@ -1,332 +0,0 @@
+-#include <linux/workqueue.h>
+-#include <linux/rtnetlink.h>
 -#include <linux/cache.h>
--#include <linux/jhash.h>
--#include <linux/init.h>
--#include <linux/times.h>
--
--#include <net/icmp.h>
--#include <net/inet_hashtables.h>
--#include <net/tcp.h>
--#include <net/transp_v6.h>
--#include <net/ipv6.h>
--#include <net/inet_common.h>
--#include <net/timewait_sock.h>
--#include <net/xfrm.h>
--#include <net/netdma.h>
--
--#include <linux/inet.h>
--#include <linux/ipv6.h>
--#include <linux/stddef.h>
--#include <linux/proc_fs.h>
--#include <linux/seq_file.h>
--
--#include <linux/crypto.h>
--#include <linux/scatterlist.h>
--
--int sysctl_tcp_tw_reuse __read_mostly;
--int sysctl_tcp_low_latency __read_mostly;
--
--/* Check TCP sequence numbers in ICMP packets. */
--#define ICMP_MIN_LENGTH 8
+-#include <linux/slab.h>
+-#include <linux/list.h>
+-#include <linux/delay.h>
+-#include <net/net_namespace.h>
 -
--/* Socket used for sending RSTs */
--static struct socket *tcp_socket __read_mostly;
+-/*
+- *    Our network namespace constructor/destructor lists
+- */
 -
--void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
+-static LIST_HEAD(pernet_list);
+-static struct list_head *first_device = &pernet_list;
+-static DEFINE_MUTEX(net_mutex);
 -
--#ifdef CONFIG_TCP_MD5SIG
--static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk,
--                                                 __be32 addr);
--static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
--                                 __be32 saddr, __be32 daddr,
--                                 struct tcphdr *th, int protocol,
--                                 int tcplen);
--#endif
+-static DEFINE_MUTEX(net_list_mutex);
+-LIST_HEAD(net_namespace_list);
 -
--struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
--      .lhash_lock  = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock),
--      .lhash_users = ATOMIC_INIT(0),
--      .lhash_wait  = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait),
--};
+-static struct kmem_cache *net_cachep;
 -
--static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
--{
--      return inet_csk_get_port(&tcp_hashinfo, sk, snum,
--                               inet_csk_bind_conflict);
--}
+-struct net init_net;
+-EXPORT_SYMBOL_GPL(init_net);
 -
--static void tcp_v4_hash(struct sock *sk)
+-void net_lock(void)
 -{
--      inet_hash(&tcp_hashinfo, sk);
+-      mutex_lock(&net_list_mutex);
 -}
 -
--void tcp_unhash(struct sock *sk)
+-void net_unlock(void)
 -{
--      inet_unhash(&tcp_hashinfo, sk);
+-      mutex_unlock(&net_list_mutex);
 -}
 -
--static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb)
+-static struct net *net_alloc(void)
 -{
--      return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
--                                        ip_hdr(skb)->saddr,
--                                        tcp_hdr(skb)->dest,
--                                        tcp_hdr(skb)->source);
+-      return kmem_cache_alloc(net_cachep, GFP_KERNEL);
 -}
 -
--int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
+-static void net_free(struct net *net)
 -{
--      const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw);
--      struct tcp_sock *tp = tcp_sk(sk);
--
--      /* With PAWS, it is safe from the viewpoint
--         of data integrity. Even without PAWS it is safe provided sequence
--         spaces do not overlap i.e. at data rates <= 80Mbit/sec.
--
--         Actually, the idea is close to VJ's one, only timestamp cache is
--         held not per host, but per port pair and TW bucket is used as state
--         holder.
+-      if (!net)
+-              return;
 -
--         If TW bucket has been already destroyed we fall back to VJ's scheme
--         and use initial timestamp retrieved from peer table.
--       */
--      if (tcptw->tw_ts_recent_stamp &&
--          (twp == NULL || (sysctl_tcp_tw_reuse &&
--                           get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {
--              tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
--              if (tp->write_seq == 0)
--                      tp->write_seq = 1;
--              tp->rx_opt.ts_recent       = tcptw->tw_ts_recent;
--              tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
--              sock_hold(sktw);
--              return 1;
+-      if (unlikely(atomic_read(&net->use_count) != 0)) {
+-              printk(KERN_EMERG "network namespace not free! Usage: %d\n",
+-                      atomic_read(&net->use_count));
+-              return;
 -      }
 -
--      return 0;
+-      kmem_cache_free(net_cachep, net);
 -}
 -
--EXPORT_SYMBOL_GPL(tcp_twsk_unique);
--
--/* This will initiate an outgoing connection. */
--int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+-static void cleanup_net(struct work_struct *work)
 -{
--      struct inet_sock *inet = inet_sk(sk);
--      struct tcp_sock *tp = tcp_sk(sk);
--      struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
--      struct rtable *rt;
--      __be32 daddr, nexthop;
--      int tmp;
--      int err;
--
--      if (addr_len < sizeof(struct sockaddr_in))
--              return -EINVAL;
--
--      if (usin->sin_family != AF_INET)
--              return -EAFNOSUPPORT;
--
--      nexthop = daddr = usin->sin_addr.s_addr;
--      if (inet->opt && inet->opt->srr) {
--              if (!daddr)
--                      return -EINVAL;
--              nexthop = inet->opt->faddr;
--      }
--
--      tmp = ip_route_connect(&rt, nexthop, inet->saddr,
--                             RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
--                             IPPROTO_TCP,
--                             inet->sport, usin->sin_port, sk, 1);
--      if (tmp < 0) {
--              if (tmp == -ENETUNREACH)
--                      IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
--              return tmp;
--      }
--
--      if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
--              ip_rt_put(rt);
--              return -ENETUNREACH;
--      }
+-      struct pernet_operations *ops;
+-      struct list_head *ptr;
+-      struct net *net;
 -
--      if (!inet->opt || !inet->opt->srr)
--              daddr = rt->rt_dst;
+-      net = container_of(work, struct net, work);
 -
--      if (!inet->saddr)
--              inet->saddr = rt->rt_src;
--      inet->rcv_saddr = inet->saddr;
+-      mutex_lock(&net_mutex);
 -
--      if (tp->rx_opt.ts_recent_stamp && inet->daddr != daddr) {
--              /* Reset inherited state */
--              tp->rx_opt.ts_recent       = 0;
--              tp->rx_opt.ts_recent_stamp = 0;
--              tp->write_seq              = 0;
--      }
+-      /* Don't let anyone else find us. */
+-      net_lock();
+-      list_del(&net->list);
+-      net_unlock();
 -
--      if (tcp_death_row.sysctl_tw_recycle &&
--          !tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) {
--              struct inet_peer *peer = rt_get_peer(rt);
--              /*
--               * VJ's idea. We save last timestamp seen from
--               * the destination in peer table, when entering state
--               * TIME-WAIT * and initialize rx_opt.ts_recent from it,
--               * when trying new connection.
--               */
--              if (peer != NULL &&
--                  peer->tcp_ts_stamp + TCP_PAWS_MSL >= get_seconds()) {
--                      tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
--                      tp->rx_opt.ts_recent = peer->tcp_ts;
--              }
+-      /* Run all of the network namespace exit methods */
+-      list_for_each_prev(ptr, &pernet_list) {
+-              ops = list_entry(ptr, struct pernet_operations, list);
+-              if (ops->exit)
+-                      ops->exit(net);
 -      }
 -
--      inet->dport = usin->sin_port;
--      inet->daddr = daddr;
--
--      inet_csk(sk)->icsk_ext_hdr_len = 0;
--      if (inet->opt)
--              inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen;
+-      mutex_unlock(&net_mutex);
 -
--      tp->rx_opt.mss_clamp = 536;
--
--      /* Socket identity is still unknown (sport may be zero).
--       * However we set state to SYN-SENT and not releasing socket
--       * lock select source port, enter ourselves into the hash tables and
--       * complete initialization after this.
+-      /* Ensure there are no outstanding rcu callbacks using this
+-       * network namespace.
 -       */
--      tcp_set_state(sk, TCP_SYN_SENT);
--      err = inet_hash_connect(&tcp_death_row, sk);
--      if (err)
--              goto failure;
--
--      err = ip_route_newports(&rt, IPPROTO_TCP,
--                              inet->sport, inet->dport, sk);
--      if (err)
--              goto failure;
--
--      /* OK, now commit destination to socket.  */
--      sk->sk_gso_type = SKB_GSO_TCPV4;
--      sk_setup_caps(sk, &rt->u.dst);
--
--      if (!tp->write_seq)
--              tp->write_seq = secure_tcp_sequence_number(inet->saddr,
--                                                         inet->daddr,
--                                                         inet->sport,
--                                                         usin->sin_port);
--
--      inet->id = tp->write_seq ^ jiffies;
--
--      err = tcp_connect(sk);
--      rt = NULL;
--      if (err)
--              goto failure;
--
--      return 0;
+-      rcu_barrier();
 -
--failure:
--      /*
--       * This unhashes the socket and releases the local port,
--       * if necessary.
--       */
--      tcp_set_state(sk, TCP_CLOSE);
--      ip_rt_put(rt);
--      sk->sk_route_caps = 0;
--      inet->dport = 0;
--      return err;
+-      /* Finally it is safe to free my network namespace structure */
+-      net_free(net);
 -}
 -
--/*
-- * This routine does path mtu discovery as defined in RFC1191.
-- */
--static void do_pmtu_discovery(struct sock *sk, struct iphdr *iph, u32 mtu)
--{
--      struct dst_entry *dst;
--      struct inet_sock *inet = inet_sk(sk);
--
--      /* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs
--       * send out by Linux are always <576bytes so they should go through
--       * unfragmented).
--       */
--      if (sk->sk_state == TCP_LISTEN)
--              return;
--
--      /* We don't check in the destentry if pmtu discovery is forbidden
--       * on this route. We just assume that no packet_to_big packets
--       * are send back when pmtu discovery is not active.
--       * There is a small race when the user changes this flag in the
--       * route, but I think that's acceptable.
--       */
--      if ((dst = __sk_dst_check(sk, 0)) == NULL)
--              return;
--
--      dst->ops->update_pmtu(dst, mtu);
 -
--      /* Something is about to be wrong... Remember soft error
--       * for the case, if this connection will not able to recover.
--       */
--      if (mtu < dst_mtu(dst) && ip_dont_fragment(sk, dst))
--              sk->sk_err_soft = EMSGSIZE;
--
--      mtu = dst_mtu(dst);
--
--      if (inet->pmtudisc != IP_PMTUDISC_DONT &&
--          inet_csk(sk)->icsk_pmtu_cookie > mtu) {
--              tcp_sync_mss(sk, mtu);
--
--              /* Resend the TCP packet because it's
--               * clear that the old packet has been
--               * dropped. This is the new "fast" path mtu
--               * discovery.
--               */
--              tcp_simple_retransmit(sk);
--      } /* else let the usual retransmit timer handle it */
+-void __put_net(struct net *net)
+-{
+-      /* Cleanup the network namespace in process context */
+-      INIT_WORK(&net->work, cleanup_net);
+-      schedule_work(&net->work);
 -}
+-EXPORT_SYMBOL_GPL(__put_net);
 -
 -/*
-- * This routine is called by the ICMP module when it gets some
-- * sort of error condition.  If err < 0 then the socket should
-- * be closed and the error returned to the user.  If err > 0
-- * it's just the icmp type << 8 | icmp code.  After adjustment
-- * header points to the first 8 bytes of the tcp header.  We need
-- * to find the appropriate port.
-- *
-- * The locking strategy used here is very "optimistic". When
-- * someone else accesses the socket the ICMP is just dropped
-- * and for some paths there is no check at all.
-- * A more general error queue to queue errors for later handling
-- * is probably better.
-- *
+- * setup_net runs the initializers for the network namespace object.
 - */
--
--void tcp_v4_err(struct sk_buff *skb, u32 info)
+-static int setup_net(struct net *net)
 -{
--      struct iphdr *iph = (struct iphdr *)skb->data;
--      struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
--      struct tcp_sock *tp;
--      struct inet_sock *inet;
--      const int type = icmp_hdr(skb)->type;
--      const int code = icmp_hdr(skb)->code;
--      struct sock *sk;
--      __u32 seq;
--      int err;
+-      /* Must be called with net_mutex held */
+-      struct pernet_operations *ops;
+-      struct list_head *ptr;
+-      int error;
 -
--      if (skb->len < (iph->ihl << 2) + 8) {
--              ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
--              return;
--      }
+-      memset(net, 0, sizeof(struct net));
+-      atomic_set(&net->count, 1);
+-      atomic_set(&net->use_count, 0);
 -
--      sk = inet_lookup(&tcp_hashinfo, iph->daddr, th->dest, iph->saddr,
--                       th->source, inet_iif(skb));
--      if (!sk) {
--              ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
--              return;
--      }
--      if (sk->sk_state == TCP_TIME_WAIT) {
--              inet_twsk_put(inet_twsk(sk));
--              return;
+-      error = 0;
+-      list_for_each(ptr, &pernet_list) {
+-              ops = list_entry(ptr, struct pernet_operations, list);
+-              if (ops->init) {
+-                      error = ops->init(net);
+-                      if (error < 0)
+-                              goto out_undo;
+-              }
 -      }
--
--      bh_lock_sock(sk);
--      /* If too many ICMPs get dropped on busy
--       * servers this needs to be solved differently.
+-out:
+-      return error;
+-out_undo:
+-      /* Walk through the list backwards calling the exit functions
+-       * for the pernet modules whose init functions did not fail.
 -       */
--      if (sock_owned_by_user(sk))
--              NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS);
--
--      if (sk->sk_state == TCP_CLOSE)
--              goto out;
--
--      tp = tcp_sk(sk);
--      seq = ntohl(th->seq);
--      if (sk->sk_state != TCP_LISTEN &&
--          !between(seq, tp->snd_una, tp->snd_nxt)) {
--              NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
--              goto out;
--      }
--
--      switch (type) {
--      case ICMP_SOURCE_QUENCH:
--              /* Just silently ignore these. */
--              goto out;
--      case ICMP_PARAMETERPROB:
--              err = EPROTO;
--              break;
--      case ICMP_DEST_UNREACH:
--              if (code > NR_ICMP_UNREACH)
--                      goto out;
--
--              if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
--                      if (!sock_owned_by_user(sk))
--                              do_pmtu_discovery(sk, iph, info);
--                      goto out;
--              }
--
--              err = icmp_err_convert[code].errno;
--              break;
--      case ICMP_TIME_EXCEEDED:
--              err = EHOSTUNREACH;
--              break;
--      default:
--              goto out;
+-      for (ptr = ptr->prev; ptr != &pernet_list; ptr = ptr->prev) {
+-              ops = list_entry(ptr, struct pernet_operations, list);
+-              if (ops->exit)
+-                      ops->exit(net);
 -      }
+-      goto out;
+-}
 -
--      switch (sk->sk_state) {
--              struct request_sock *req, **prev;
--      case TCP_LISTEN:
--              if (sock_owned_by_user(sk))
--                      goto out;
--
--              req = inet_csk_search_req(sk, &prev, th->dest,
--                                        iph->daddr, iph->saddr);
--              if (!req)
--                      goto out;
+-struct net *copy_net_ns(unsigned long flags, struct net *old_net)
+-{
+-      struct net *new_net = NULL;
+-      int err;
 -
--              /* ICMPs are not backlogged, hence we cannot get
--                 an established socket here.
--               */
--              BUG_TRAP(!req->sk);
+-      get_net(old_net);
 -
--              if (seq != tcp_rsk(req)->snt_isn) {
--                      NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
--                      goto out;
--              }
+-      if (!(flags & CLONE_NEWNET))
+-              return old_net;
 -
--              /*
--               * Still in SYN_RECV, just remove it silently.
--               * There is no good way to pass the error to the newly
--               * created socket, and POSIX does not want network
--               * errors returned from accept().
--               */
--              inet_csk_reqsk_queue_drop(sk, req, prev);
+-      err = -EPERM;
+-      if (!capable(CAP_SYS_ADMIN))
 -              goto out;
 -
--      case TCP_SYN_SENT:
--      case TCP_SYN_RECV:  /* Cannot happen.
--                             It can f.e. if SYNs crossed.
--                           */
--              if (!sock_owned_by_user(sk)) {
--                      sk->sk_err = err;
--
--                      sk->sk_error_report(sk);
--
--                      tcp_done(sk);
--              } else {
--                      sk->sk_err_soft = err;
--              }
+-      err = -ENOMEM;
+-      new_net = net_alloc();
+-      if (!new_net)
 -              goto out;
--      }
--
--      /* If we've already connected we will keep trying
--       * until we time out, or the user gives up.
--       *
--       * rfc1122 4.2.3.9 allows to consider as hard errors
--       * only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
--       * but it is obsoleted by pmtu discovery).
--       *
--       * Note, that in modern internet, where routing is unreliable
--       * and in each dark corner broken firewalls sit, sending random
--       * errors ordered by their masters even this two messages finally lose
--       * their original sense (even Linux sends invalid PORT_UNREACHs)
--       *
--       * Now we are in compliance with RFCs.
--       *                                                      --ANK (980905)
--       */
 -
--      inet = inet_sk(sk);
--      if (!sock_owned_by_user(sk) && inet->recverr) {
--              sk->sk_err = err;
--              sk->sk_error_report(sk);
--      } else  { /* Only an error on timeout */
--              sk->sk_err_soft = err;
--      }
+-      mutex_lock(&net_mutex);
+-      err = setup_net(new_net);
+-      if (err)
+-              goto out_unlock;
 -
--out:
--      bh_unlock_sock(sk);
--      sock_put(sk);
--}
+-      net_lock();
+-      list_add_tail(&new_net->list, &net_namespace_list);
+-      net_unlock();
 -
--/* This routine computes an IPv4 TCP checksum. */
--void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
--{
--      struct inet_sock *inet = inet_sk(sk);
--      struct tcphdr *th = tcp_hdr(skb);
 -
--      if (skb->ip_summed == CHECKSUM_PARTIAL) {
--              th->check = ~tcp_v4_check(len, inet->saddr,
--                                        inet->daddr, 0);
--              skb->csum_start = skb_transport_header(skb) - skb->head;
--              skb->csum_offset = offsetof(struct tcphdr, check);
--      } else {
--              th->check = tcp_v4_check(len, inet->saddr, inet->daddr,
--                                       csum_partial((char *)th,
--                                                    th->doff << 2,
--                                                    skb->csum));
+-out_unlock:
+-      mutex_unlock(&net_mutex);
+-out:
+-      put_net(old_net);
+-      if (err) {
+-              net_free(new_net);
+-              new_net = ERR_PTR(err);
 -      }
+-      return new_net;
 -}
 -
--int tcp_v4_gso_send_check(struct sk_buff *skb)
+-static int __init net_ns_init(void)
 -{
--      const struct iphdr *iph;
--      struct tcphdr *th;
+-      int err;
 -
--      if (!pskb_may_pull(skb, sizeof(*th)))
--              return -EINVAL;
+-      printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
+-      net_cachep = kmem_cache_create("net_namespace", sizeof(struct net),
+-                                      SMP_CACHE_BYTES,
+-                                      SLAB_PANIC, NULL, NULL);
+-      mutex_lock(&net_mutex);
+-      err = setup_net(&init_net);
 -
--      iph = ip_hdr(skb);
--      th = tcp_hdr(skb);
+-      net_lock();
+-      list_add_tail(&init_net.list, &net_namespace_list);
+-      net_unlock();
+-
+-      mutex_unlock(&net_mutex);
+-      if (err)
+-              panic("Could not setup the initial network namespace");
 -
--      th->check = 0;
--      th->check = ~tcp_v4_check(skb->len, iph->saddr, iph->daddr, 0);
--      skb->csum_start = skb_transport_header(skb) - skb->head;
--      skb->csum_offset = offsetof(struct tcphdr, check);
--      skb->ip_summed = CHECKSUM_PARTIAL;
 -      return 0;
 -}
 -
--/*
-- *    This routine will send an RST to the other tcp.
-- *
-- *    Someone asks: why I NEVER use socket parameters (TOS, TTL etc.)
-- *                  for reset.
-- *    Answer: if a packet caused RST, it is not for a socket
-- *            existing in our system, if it is matched to a socket,
-- *            it is just duplicate segment or bug in other side's TCP.
-- *            So that we build reply only basing on parameters
-- *            arrived with segment.
-- *    Exception: precedence violation. We do not implement it in any case.
-- */
+-pure_initcall(net_ns_init);
 -
--static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
+-static int register_pernet_operations(struct list_head *list,
+-                                    struct pernet_operations *ops)
 -{
--      struct tcphdr *th = tcp_hdr(skb);
--      struct {
--              struct tcphdr th;
--#ifdef CONFIG_TCP_MD5SIG
--              __be32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)];
--#endif
--      } rep;
--      struct ip_reply_arg arg;
--#ifdef CONFIG_TCP_MD5SIG
--      struct tcp_md5sig_key *key;
--#endif
--
--      /* Never send a reset in response to a reset. */
--      if (th->rst)
--              return;
--
--      if (((struct rtable *)skb->dst)->rt_type != RTN_LOCAL)
--              return;
+-      struct net *net, *undo_net;
+-      int error;
 -
--      /* Swap the send and the receive. */
--      memset(&rep, 0, sizeof(rep));
--      rep.th.dest   = th->source;
--      rep.th.source = th->dest;
--      rep.th.doff   = sizeof(struct tcphdr) / 4;
--      rep.th.rst    = 1;
+-      error = 0;
+-      list_add_tail(&ops->list, list);
+-      for_each_net(net) {
+-              if (ops->init) {
+-                      error = ops->init(net);
+-                      if (error)
+-                              goto out_undo;
+-              }
+-      }
+-out:
+-      return error;
 -
--      if (th->ack) {
--              rep.th.seq = th->ack_seq;
--      } else {
--              rep.th.ack = 1;
--              rep.th.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin +
--                                     skb->len - (th->doff << 2));
--      }
--
--      memset(&arg, 0, sizeof(arg));
--      arg.iov[0].iov_base = (unsigned char *)&rep;
--      arg.iov[0].iov_len  = sizeof(rep.th);
--
--#ifdef CONFIG_TCP_MD5SIG
--      key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr) : NULL;
--      if (key) {
--              rep.opt[0] = htonl((TCPOPT_NOP << 24) |
--                                 (TCPOPT_NOP << 16) |
--                                 (TCPOPT_MD5SIG << 8) |
--                                 TCPOLEN_MD5SIG);
--              /* Update length and the length the header thinks exists */
--              arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
--              rep.th.doff = arg.iov[0].iov_len / 4;
--
--              tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[1],
--                                      key,
--                                      ip_hdr(skb)->daddr,
--                                      ip_hdr(skb)->saddr,
--                                      &rep.th, IPPROTO_TCP,
--                                      arg.iov[0].iov_len);
+-out_undo:
+-      /* If I have an error cleanup all namespaces I initialized */
+-      list_del(&ops->list);
+-      for_each_net(undo_net) {
+-              if (undo_net == net)
+-                      goto undone;
+-              if (ops->exit)
+-                      ops->exit(undo_net);
 -      }
--#endif
--      arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
--                                    ip_hdr(skb)->saddr, /* XXX */
--                                    sizeof(struct tcphdr), IPPROTO_TCP, 0);
--      arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+-undone:
+-      goto out;
+-}
 -
--      ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
+-static void unregister_pernet_operations(struct pernet_operations *ops)
+-{
+-      struct net *net;
 -
--      TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
--      TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
+-      list_del(&ops->list);
+-      for_each_net(net)
+-              if (ops->exit)
+-                      ops->exit(net);
 -}
 -
--/* The code following below sending ACKs in SYN-RECV and TIME-WAIT states
--   outside socket context is ugly, certainly. What can I do?
+-/**
+- *      register_pernet_subsys - register a network namespace subsystem
+- *    @ops:  pernet operations structure for the subsystem
+- *
+- *    Register a subsystem which has init and exit functions
+- *    that are called when network namespaces are created and
+- *    destroyed respectively.
+- *
+- *    When registered all network namespace init functions are
+- *    called for every existing network namespace.  Allowing kernel
+- *    modules to have a race free view of the set of network namespaces.
+- *
+- *    When a new network namespace is created all of the init
+- *    methods are called in the order in which they were registered.
+- *
+- *    When a network namespace is destroyed all of the exit methods
+- *    are called in the reverse of the order with which they were
+- *    registered.
 - */
--
--static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
--                          struct sk_buff *skb, u32 seq, u32 ack,
--                          u32 win, u32 ts)
+-int register_pernet_subsys(struct pernet_operations *ops)
 -{
--      struct tcphdr *th = tcp_hdr(skb);
--      struct {
--              struct tcphdr th;
--              __be32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2)
--#ifdef CONFIG_TCP_MD5SIG
--                         + (TCPOLEN_MD5SIG_ALIGNED >> 2)
--#endif
--                      ];
--      } rep;
--      struct ip_reply_arg arg;
--#ifdef CONFIG_TCP_MD5SIG
--      struct tcp_md5sig_key *key;
--      struct tcp_md5sig_key tw_key;
--#endif
--
--      memset(&rep.th, 0, sizeof(struct tcphdr));
--      memset(&arg, 0, sizeof(arg));
--
--      arg.iov[0].iov_base = (unsigned char *)&rep;
--      arg.iov[0].iov_len  = sizeof(rep.th);
--      if (ts) {
--              rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
--                                 (TCPOPT_TIMESTAMP << 8) |
--                                 TCPOLEN_TIMESTAMP);
--              rep.opt[1] = htonl(tcp_time_stamp);
--              rep.opt[2] = htonl(ts);
--              arg.iov[0].iov_len += TCPOLEN_TSTAMP_ALIGNED;
--      }
--
--      /* Swap the send and the receive. */
--      rep.th.dest    = th->source;
--      rep.th.source  = th->dest;
--      rep.th.doff    = arg.iov[0].iov_len / 4;
--      rep.th.seq     = htonl(seq);
--      rep.th.ack_seq = htonl(ack);
--      rep.th.ack     = 1;
--      rep.th.window  = htons(win);
--
--#ifdef CONFIG_TCP_MD5SIG
--      /*
--       * The SKB holds an imcoming packet, but may not have a valid ->sk
--       * pointer. This is especially the case when we're dealing with a
--       * TIME_WAIT ack, because the sk structure is long gone, and only
--       * the tcp_timewait_sock remains. So the md5 key is stashed in that
--       * structure, and we use it in preference.  I believe that (twsk ||
--       * skb->sk) holds true, but we program defensively.
--       */
--      if (!twsk && skb->sk) {
--              key = tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr);
--      } else if (twsk && twsk->tw_md5_keylen) {
--              tw_key.key = twsk->tw_md5_key;
--              tw_key.keylen = twsk->tw_md5_keylen;
--              key = &tw_key;
--      } else
--              key = NULL;
--
--      if (key) {
--              int offset = (ts) ? 3 : 0;
--
--              rep.opt[offset++] = htonl((TCPOPT_NOP << 24) |
--                                        (TCPOPT_NOP << 16) |
--                                        (TCPOPT_MD5SIG << 8) |
--                                        TCPOLEN_MD5SIG);
--              arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
--              rep.th.doff = arg.iov[0].iov_len/4;
--
--              tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[offset],
--                                      key,
--                                      ip_hdr(skb)->daddr,
--                                      ip_hdr(skb)->saddr,
--                                      &rep.th, IPPROTO_TCP,
--                                      arg.iov[0].iov_len);
--      }
--#endif
--      arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
--                                    ip_hdr(skb)->saddr, /* XXX */
--                                    arg.iov[0].iov_len, IPPROTO_TCP, 0);
--      arg.csumoffset = offsetof(struct tcphdr, check) / 2;
--      if (twsk)
--              arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
--
--      ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
--
--      TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
+-      int error;
+-      mutex_lock(&net_mutex);
+-      error =  register_pernet_operations(first_device, ops);
+-      mutex_unlock(&net_mutex);
+-      return error;
 -}
+-EXPORT_SYMBOL_GPL(register_pernet_subsys);
 -
--static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
+-/**
+- *      unregister_pernet_subsys - unregister a network namespace subsystem
+- *    @ops: pernet operations structure to manipulate
+- *
+- *    Remove the pernet operations structure from the list to be
+- *    used when network namespaces are created or destoryed.  In
+- *    addition run the exit method for all existing network
+- *    namespaces.
+- */
+-void unregister_pernet_subsys(struct pernet_operations *module)
 -{
--      struct inet_timewait_sock *tw = inet_twsk(sk);
--      struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
--
--      tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
--                      tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
--                      tcptw->tw_ts_recent);
--
--      inet_twsk_put(tw);
+-      mutex_lock(&net_mutex);
+-      unregister_pernet_operations(module);
+-      mutex_unlock(&net_mutex);
 -}
+-EXPORT_SYMBOL_GPL(unregister_pernet_subsys);
 -
--static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
--                                struct request_sock *req)
+-/**
+- *      register_pernet_device - register a network namespace device
+- *    @ops:  pernet operations structure for the subsystem
+- *
+- *    Register a device which has init and exit functions
+- *    that are called when network namespaces are created and
+- *    destroyed respectively.
+- *
+- *    When registered all network namespace init functions are
+- *    called for every existing network namespace.  Allowing kernel
+- *    modules to have a race free view of the set of network namespaces.
+- *
+- *    When a new network namespace is created all of the init
+- *    methods are called in the order in which they were registered.
+- *
+- *    When a network namespace is destroyed all of the exit methods
+- *    are called in the reverse of the order with which they were
+- *    registered.
+- */
+-int register_pernet_device(struct pernet_operations *ops)
 -{
--      tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1,
--                      tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
--                      req->ts_recent);
+-      int error;
+-      mutex_lock(&net_mutex);
+-      error = register_pernet_operations(&pernet_list, ops);
+-      if (!error && (first_device == &pernet_list))
+-              first_device = &ops->list;
+-      mutex_unlock(&net_mutex);
+-      return error;
 -}
+-EXPORT_SYMBOL_GPL(register_pernet_device);
 -
--/*
-- *    Send a SYN-ACK after having received an ACK.
-- *    This still operates on a request_sock only, not on a big
-- *    socket.
+-/**
+- *      unregister_pernet_device - unregister a network namespace netdevice
+- *    @ops: pernet operations structure to manipulate
+- *
+- *    Remove the pernet operations structure from the list to be
+- *    used when network namespaces are created or destoryed.  In
+- *    addition run the exit method for all existing network
+- *    namespaces.
 - */
--static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
--                            struct dst_entry *dst)
+-void unregister_pernet_device(struct pernet_operations *ops)
 -{
--      const struct inet_request_sock *ireq = inet_rsk(req);
--      int err = -1;
--      struct sk_buff * skb;
--
--      /* First, grab a route. */
--      if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL)
--              goto out;
--
--      skb = tcp_make_synack(sk, dst, req);
--
--      if (skb) {
--              struct tcphdr *th = tcp_hdr(skb);
+-      mutex_lock(&net_mutex);
+-      if (&ops->list == first_device)
+-              first_device = first_device->next;
+-      unregister_pernet_operations(ops);
+-      mutex_unlock(&net_mutex);
+-}
+-EXPORT_SYMBOL_GPL(unregister_pernet_device);
+diff -Nurb linux-2.6.22-590/net/core/netpoll.c linux-2.6.22-570/net/core/netpoll.c
+--- linux-2.6.22-590/net/core/netpoll.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/netpoll.c        2008-01-23 19:15:56.000000000 -0500
+@@ -503,8 +503,7 @@
+       np->rx_hook(np, ntohs(uh->source),
+                   (char *)(uh+1),
+-                  ulen - sizeof(struct udphdr),
+-                  skb);
++                  ulen - sizeof(struct udphdr));
+       kfree_skb(skb);
+       return 1;
+@@ -634,7 +633,7 @@
+       int err;
+       if (np->dev_name)
+-              ndev = dev_get_by_name(&init_net, np->dev_name);
++              ndev = dev_get_by_name(np->dev_name);
+       if (!ndev) {
+               printk(KERN_ERR "%s: %s doesn't exist, aborting.\n",
+                      np->name, np->dev_name);
+diff -Nurb linux-2.6.22-590/net/core/pktgen.c linux-2.6.22-570/net/core/pktgen.c
+--- linux-2.6.22-590/net/core/pktgen.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/pktgen.c 2008-01-23 19:15:56.000000000 -0500
+@@ -155,7 +155,6 @@
+ #include <net/checksum.h>
+ #include <net/ipv6.h>
+ #include <net/addrconf.h>
+-#include <net/net_namespace.h>
+ #include <asm/byteorder.h>
+ #include <linux/rcupdate.h>
+ #include <asm/bitops.h>
+@@ -1904,9 +1903,6 @@
+ {
+       struct net_device *dev = ptr;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--              th->check = tcp_v4_check(skb->len,
--                                       ireq->loc_addr,
--                                       ireq->rmt_addr,
--                                       csum_partial((char *)th, skb->len,
--                                                    skb->csum));
+       /* It is OK that we do not hold the group lock right now,
+        * as we run under the RTNL lock.
+        */
+@@ -1937,7 +1933,7 @@
+               pkt_dev->odev = NULL;
+       }
+-      odev = dev_get_by_name(&init_net, ifname);
++      odev = dev_get_by_name(ifname);
+       if (!odev) {
+               printk("pktgen: no such netdevice: \"%s\"\n", ifname);
+               return -ENODEV;
+@@ -3288,8 +3284,6 @@
+       set_current_state(TASK_INTERRUPTIBLE);
+-      set_freezable();
 -
--              err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
--                                          ireq->rmt_addr,
--                                          ireq->opt);
--              err = net_xmit_eval(err);
+       while (!kthread_should_stop()) {
+               pkt_dev = next_to_run(t);
+@@ -3574,7 +3568,7 @@
+       printk(version);
+-      pg_proc_dir = proc_mkdir(PG_PROC_DIR, init_net.proc_net);
++      pg_proc_dir = proc_mkdir(PG_PROC_DIR, proc_net);
+       if (!pg_proc_dir)
+               return -ENODEV;
+       pg_proc_dir->owner = THIS_MODULE;
+@@ -3583,7 +3577,7 @@
+       if (pe == NULL) {
+               printk("pktgen: ERROR: cannot create %s procfs entry.\n",
+                      PGCTRL);
+-              proc_net_remove(&init_net, PG_PROC_DIR);
++              proc_net_remove(PG_PROC_DIR);
+               return -EINVAL;
+       }
+@@ -3606,7 +3600,7 @@
+               printk("pktgen: ERROR: Initialization failed for all threads\n");
+               unregister_netdevice_notifier(&pktgen_notifier_block);
+               remove_proc_entry(PGCTRL, pg_proc_dir);
+-              proc_net_remove(&init_net, PG_PROC_DIR);
++              proc_net_remove(PG_PROC_DIR);
+               return -ENODEV;
+       }
+@@ -3633,7 +3627,7 @@
+       /* Clean up proc file system */
+       remove_proc_entry(PGCTRL, pg_proc_dir);
+-      proc_net_remove(&init_net, PG_PROC_DIR);
++      proc_net_remove(PG_PROC_DIR);
+ }
+ module_init(pg_init);
+diff -Nurb linux-2.6.22-590/net/core/rtnetlink.c linux-2.6.22-570/net/core/rtnetlink.c
+--- linux-2.6.22-590/net/core/rtnetlink.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/rtnetlink.c      2008-01-23 19:16:05.000000000 -0500
+@@ -59,6 +59,7 @@
+ };
+ static DEFINE_MUTEX(rtnl_mutex);
++static struct sock *rtnl;
+ void rtnl_lock(void)
+ {
+@@ -72,17 +73,9 @@
+ void rtnl_unlock(void)
+ {
+-      struct net *net;
+       mutex_unlock(&rtnl_mutex);
+-      
+-      net_lock();
+-      for_each_net(net) {
+-              struct sock *rtnl = net->rtnl;
+       if (rtnl && rtnl->sk_receive_queue.qlen)
+               rtnl->sk_data_ready(rtnl, 0);
 -      }
+-      net_unlock();
 -
--out:
--      dst_release(dst);
--      return err;
+       netdev_run_todo();
+ }
+@@ -104,19 +97,6 @@
+       return 0;
+ }
+-int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
+-                               struct rtattr *rta, int len)
+-{
+-      if (RTA_PAYLOAD(rta) < len)
+-              return -1;
+-      if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) {
+-              rta = RTA_DATA(rta) + RTA_ALIGN(len);
+-              return rtattr_parse_nested(tb, maxattr, rta);
+-      }
+-      memset(tb, 0, sizeof(struct rtattr *) * maxattr);
+-      return 0;
 -}
 -
--/*
-- *    IPv4 request_sock destructor.
+ static struct rtnl_link *rtnl_msg_handlers[NPROTO];
+ static inline int rtm_msgindex(int msgtype)
+@@ -263,143 +243,6 @@
+ EXPORT_SYMBOL_GPL(rtnl_unregister_all);
+-static LIST_HEAD(link_ops);
+-
+-/**
+- * __rtnl_link_register - Register rtnl_link_ops with rtnetlink.
+- * @ops: struct rtnl_link_ops * to register
+- *
+- * The caller must hold the rtnl_mutex. This function should be used
+- * by drivers that create devices during module initialization. It
+- * must be called before registering the devices.
+- *
+- * Returns 0 on success or a negative error code.
 - */
--static void tcp_v4_reqsk_destructor(struct request_sock *req)
+-int __rtnl_link_register(struct rtnl_link_ops *ops)
 -{
--      kfree(inet_rsk(req)->opt);
+-      list_add_tail(&ops->list, &link_ops);
+-      return 0;
 -}
 -
--#ifdef CONFIG_SYN_COOKIES
--static void syn_flood_warning(struct sk_buff *skb)
+-EXPORT_SYMBOL_GPL(__rtnl_link_register);
+-
+-/**
+- * rtnl_link_register - Register rtnl_link_ops with rtnetlink.
+- * @ops: struct rtnl_link_ops * to register
+- *
+- * Returns 0 on success or a negative error code.
+- */
+-int rtnl_link_register(struct rtnl_link_ops *ops)
 -{
--      static unsigned long warntime;
+-      int err;
 -
--      if (time_after(jiffies, (warntime + HZ * 60))) {
--              warntime = jiffies;
--              printk(KERN_INFO
--                     "possible SYN flooding on port %d. Sending cookies.\n",
--                     ntohs(tcp_hdr(skb)->dest));
--      }
+-      rtnl_lock();
+-      err = __rtnl_link_register(ops);
+-      rtnl_unlock();
+-      return err;
 -}
--#endif
 -
--/*
-- * Save and compile IPv4 options into the request_sock if needed.
+-EXPORT_SYMBOL_GPL(rtnl_link_register);
+-
+-/**
+- * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
+- * @ops: struct rtnl_link_ops * to unregister
+- *
+- * The caller must hold the rtnl_mutex. This function should be used
+- * by drivers that unregister devices during module unloading. It must
+- * be called after unregistering the devices.
 - */
--static struct ip_options *tcp_v4_save_options(struct sock *sk,
--                                            struct sk_buff *skb)
+-void __rtnl_link_unregister(struct rtnl_link_ops *ops)
 -{
--      struct ip_options *opt = &(IPCB(skb)->opt);
--      struct ip_options *dopt = NULL;
--
--      if (opt && opt->optlen) {
--              int opt_size = optlength(opt);
--              dopt = kmalloc(opt_size, GFP_ATOMIC);
--              if (dopt) {
--                      if (ip_options_echo(dopt, skb)) {
--                              kfree(dopt);
--                              dopt = NULL;
--                      }
--              }
--      }
--      return dopt;
+-      list_del(&ops->list);
 -}
 -
--#ifdef CONFIG_TCP_MD5SIG
--/*
-- * RFC2385 MD5 checksumming requires a mapping of
-- * IP address->MD5 Key.
-- * We need to maintain these in the sk structure.
+-EXPORT_SYMBOL_GPL(__rtnl_link_unregister);
+-
+-/**
+- * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
+- * @ops: struct rtnl_link_ops * to unregister
 - */
+-void rtnl_link_unregister(struct rtnl_link_ops *ops)
+-{
+-      rtnl_lock();
+-      __rtnl_link_unregister(ops);
+-      rtnl_unlock();
+-}
 -
--/* Find the Key structure for an address.  */
--static struct tcp_md5sig_key *
--                      tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
+-EXPORT_SYMBOL_GPL(rtnl_link_unregister);
+-
+-static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind)
 -{
--      struct tcp_sock *tp = tcp_sk(sk);
--      int i;
+-      const struct rtnl_link_ops *ops;
 -
--      if (!tp->md5sig_info || !tp->md5sig_info->entries4)
--              return NULL;
--      for (i = 0; i < tp->md5sig_info->entries4; i++) {
--              if (tp->md5sig_info->keys4[i].addr == addr)
--                      return &tp->md5sig_info->keys4[i].base;
+-      list_for_each_entry(ops, &link_ops, list) {
+-              if (!strcmp(ops->kind, kind))
+-                      return ops;
 -      }
 -      return NULL;
 -}
 -
--struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
--                                       struct sock *addr_sk)
+-static size_t rtnl_link_get_size(const struct net_device *dev)
 -{
--      return tcp_v4_md5_do_lookup(sk, inet_sk(addr_sk)->daddr);
--}
+-      const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
+-      size_t size;
 -
--EXPORT_SYMBOL(tcp_v4_md5_lookup);
+-      if (!ops)
+-              return 0;
 -
--static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk,
--                                                    struct request_sock *req)
--{
--      return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr);
--}
+-      size = nlmsg_total_size(sizeof(struct nlattr)) + /* IFLA_LINKINFO */
+-             nlmsg_total_size(strlen(ops->kind) + 1);  /* IFLA_INFO_KIND */
 -
--/* This can be called on a newly created socket, from other files */
--int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
--                    u8 *newkey, u8 newkeylen)
--{
--      /* Add Key to the list */
--      struct tcp4_md5sig_key *key;
--      struct tcp_sock *tp = tcp_sk(sk);
--      struct tcp4_md5sig_key *keys;
+-      if (ops->get_size)
+-              /* IFLA_INFO_DATA + nested data */
+-              size += nlmsg_total_size(sizeof(struct nlattr)) +
+-                      ops->get_size(dev);
 -
--      key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr);
--      if (key) {
--              /* Pre-existing entry - just update that one. */
--              kfree(key->base.key);
--              key->base.key = newkey;
--              key->base.keylen = newkeylen;
--      } else {
--              struct tcp_md5sig_info *md5sig;
+-      if (ops->get_xstats_size)
+-              size += ops->get_xstats_size(dev);      /* IFLA_INFO_XSTATS */
 -
--              if (!tp->md5sig_info) {
--                      tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info),
--                                                GFP_ATOMIC);
--                      if (!tp->md5sig_info) {
--                              kfree(newkey);
--                              return -ENOMEM;
--                      }
--                      sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
--              }
--              if (tcp_alloc_md5sig_pool() == NULL) {
--                      kfree(newkey);
--                      return -ENOMEM;
--              }
--              md5sig = tp->md5sig_info;
+-      return size;
+-}
 -
--              if (md5sig->alloced4 == md5sig->entries4) {
--                      keys = kmalloc((sizeof(*keys) *
--                                      (md5sig->entries4 + 1)), GFP_ATOMIC);
--                      if (!keys) {
--                              kfree(newkey);
--                              tcp_free_md5sig_pool();
--                              return -ENOMEM;
--                      }
+-static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev)
+-{
+-      const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
+-      struct nlattr *linkinfo, *data;
+-      int err = -EMSGSIZE;
 -
--                      if (md5sig->entries4)
--                              memcpy(keys, md5sig->keys4,
--                                     sizeof(*keys) * md5sig->entries4);
+-      linkinfo = nla_nest_start(skb, IFLA_LINKINFO);
+-      if (linkinfo == NULL)
+-              goto out;
 -
--                      /* Free old key list, and reference new one */
--                      if (md5sig->keys4)
--                              kfree(md5sig->keys4);
--                      md5sig->keys4 = keys;
--                      md5sig->alloced4++;
--              }
--              md5sig->entries4++;
--              md5sig->keys4[md5sig->entries4 - 1].addr        = addr;
--              md5sig->keys4[md5sig->entries4 - 1].base.key    = newkey;
--              md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen;
+-      if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0)
+-              goto err_cancel_link;
+-      if (ops->fill_xstats) {
+-              err = ops->fill_xstats(skb, dev);
+-              if (err < 0)
+-                      goto err_cancel_link;
+-      }
+-      if (ops->fill_info) {
+-              data = nla_nest_start(skb, IFLA_INFO_DATA);
+-              if (data == NULL)
+-                      goto err_cancel_link;
+-              err = ops->fill_info(skb, dev);
+-              if (err < 0)
+-                      goto err_cancel_data;
+-              nla_nest_end(skb, data);
 -      }
+-
+-      nla_nest_end(skb, linkinfo);
 -      return 0;
+-
+-err_cancel_data:
+-      nla_nest_cancel(skb, data);
+-err_cancel_link:
+-      nla_nest_cancel(skb, linkinfo);
+-out:
+-      return err;
 -}
 -
--EXPORT_SYMBOL(tcp_v4_md5_do_add);
+ static const int rtm_min[RTM_NR_FAMILIES] =
+ {
+       [RTM_FAM(RTM_NEWLINK)]      = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+@@ -453,9 +296,8 @@
+       return ret;
+ }
+-int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo)
++int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
+ {
+-      struct sock *rtnl = net->rtnl;
+       int err = 0;
+       NETLINK_CB(skb).dst_group = group;
+@@ -467,17 +309,14 @@
+       return err;
+ }
+-int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid)
++int rtnl_unicast(struct sk_buff *skb, u32 pid)
+ {
+-      struct sock *rtnl = net->rtnl;
 -
--static int tcp_v4_md5_add_func(struct sock *sk, struct sock *addr_sk,
--                             u8 *newkey, u8 newkeylen)
--{
--      return tcp_v4_md5_do_add(sk, inet_sk(addr_sk)->daddr,
--                               newkey, newkeylen);
+       return nlmsg_unicast(rtnl, skb, pid);
+ }
+-int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
++int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
+               struct nlmsghdr *nlh, gfp_t flags)
+ {
+-      struct sock *rtnl = net->rtnl;
+       int report = 0;
+       if (nlh)
+@@ -486,10 +325,8 @@
+       return nlmsg_notify(rtnl, skb, pid, group, report, flags);
+ }
+-void rtnl_set_sk_err(struct net *net, u32 group, int error)
++void rtnl_set_sk_err(u32 group, int error)
+ {
+-      struct sock *rtnl = net->rtnl;
+-
+       netlink_set_err(rtnl, 0, group, error);
+ }
+@@ -600,7 +437,7 @@
+       a->tx_compressed = b->tx_compressed;
+ };
+-static inline size_t if_nlmsg_size(const struct net_device *dev)
++static inline size_t if_nlmsg_size(void)
+ {
+       return NLMSG_ALIGN(sizeof(struct ifinfomsg))
+              + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+@@ -615,8 +452,7 @@
+              + nla_total_size(4) /* IFLA_LINK */
+              + nla_total_size(4) /* IFLA_MASTER */
+              + nla_total_size(1) /* IFLA_OPERSTATE */
+-             + nla_total_size(1) /* IFLA_LINKMODE */
+-             + rtnl_link_get_size(dev); /* IFLA_LINKINFO */
++             + nla_total_size(1); /* IFLA_LINKMODE */
+ }
+ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
+@@ -686,11 +522,6 @@
+               }
+       }
+-      if (dev->rtnl_link_ops) {
+-              if (rtnl_link_fill(skb, dev) < 0)
+-                      goto nla_put_failure;
+-      }
+-
+       return nlmsg_end(skb, nlh);
+ nla_put_failure:
+@@ -700,13 +531,12 @@
+ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       int idx;
+       int s_idx = cb->args[0];
+       struct net_device *dev;
+       idx = 0;
+-      for_each_netdev(net, dev) {
++      for_each_netdev(dev) {
+               if (!nx_dev_visible(skb->sk->sk_nx_info, dev))
+                       continue;
+               if (idx < s_idx)
+@@ -725,8 +555,6 @@
+ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
+       [IFLA_IFNAME]           = { .type = NLA_STRING, .len = IFNAMSIZ-1 },
+-      [IFLA_ADDRESS]          = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
+-      [IFLA_BROADCAST]        = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
+       [IFLA_MAP]              = { .len = sizeof(struct rtnl_link_ifmap) },
+       [IFLA_MTU]              = { .type = NLA_U32 },
+       [IFLA_TXQLEN]           = { .type = NLA_U32 },
+@@ -735,16 +563,44 @@
+       [IFLA_LINKMODE]         = { .type = NLA_U8 },
+ };
+-static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
+-      [IFLA_INFO_KIND]        = { .type = NLA_STRING },
+-      [IFLA_INFO_DATA]        = { .type = NLA_NESTED },
+-};
+-
+-static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
+-                    struct nlattr **tb, char *ifname, int modified)
++static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-      int send_addr_notify = 0;
+-      int err;
++      struct ifinfomsg *ifm;
++      struct net_device *dev;
++      int err, send_addr_notify = 0, modified = 0;
++      struct nlattr *tb[IFLA_MAX+1];
++      char ifname[IFNAMSIZ];
++
++      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
++      if (err < 0)
++              goto errout;
++
++      if (tb[IFLA_IFNAME])
++              nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
++      else
++              ifname[0] = '\0';
++
++      err = -EINVAL;
++      ifm = nlmsg_data(nlh);
++      if (ifm->ifi_index > 0)
++              dev = dev_get_by_index(ifm->ifi_index);
++      else if (tb[IFLA_IFNAME])
++              dev = dev_get_by_name(ifname);
++      else
++              goto errout;
++
++      if (dev == NULL) {
++              err = -ENODEV;
++              goto errout;
++      }
++
++      if (tb[IFLA_ADDRESS] &&
++          nla_len(tb[IFLA_ADDRESS]) < dev->addr_len)
++              goto errout_dev;
++
++      if (tb[IFLA_BROADCAST] &&
++          nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
++              goto errout_dev;
+       if (tb[IFLA_MAP]) {
+               struct rtnl_link_ifmap *u_map;
+@@ -752,12 +608,12 @@
+               if (!dev->set_config) {
+                       err = -EOPNOTSUPP;
+-                      goto errout;
++                      goto errout_dev;
+               }
+               if (!netif_device_present(dev)) {
+                       err = -ENODEV;
+-                      goto errout;
++                      goto errout_dev;
+               }
+               u_map = nla_data(tb[IFLA_MAP]);
+@@ -770,7 +626,7 @@
+               err = dev->set_config(dev, &k_map);
+               if (err < 0)
+-                      goto errout;
++                      goto errout_dev;
+               modified = 1;
+       }
+@@ -781,19 +637,19 @@
+               if (!dev->set_mac_address) {
+                       err = -EOPNOTSUPP;
+-                      goto errout;
++                      goto errout_dev;
+               }
+               if (!netif_device_present(dev)) {
+                       err = -ENODEV;
+-                      goto errout;
++                      goto errout_dev;
+               }
+               len = sizeof(sa_family_t) + dev->addr_len;
+               sa = kmalloc(len, GFP_KERNEL);
+               if (!sa) {
+                       err = -ENOMEM;
+-                      goto errout;
++                      goto errout_dev;
+               }
+               sa->sa_family = dev->type;
+               memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
+@@ -801,7 +657,7 @@
+               err = dev->set_mac_address(dev, sa);
+               kfree(sa);
+               if (err)
+-                      goto errout;
++                      goto errout_dev;
+               send_addr_notify = 1;
+               modified = 1;
+       }
+@@ -809,7 +665,7 @@
+       if (tb[IFLA_MTU]) {
+               err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
+               if (err < 0)
+-                      goto errout;
++                      goto errout_dev;
+               modified = 1;
+       }
+@@ -821,7 +677,7 @@
+       if (ifm->ifi_index > 0 && ifname[0]) {
+               err = dev_change_name(dev, ifname);
+               if (err < 0)
+-                      goto errout;
++                      goto errout_dev;
+               modified = 1;
+       }
+@@ -830,6 +686,7 @@
+               send_addr_notify = 1;
+       }
++
+       if (ifm->ifi_flags || ifm->ifi_change) {
+               unsigned int flags = ifm->ifi_flags;
+@@ -857,7 +714,7 @@
+       err = 0;
+-errout:
++errout_dev:
+       if (err < 0 && modified && net_ratelimit())
+               printk(KERN_WARNING "A link change request failed with "
+                      "some changes comitted already. Interface %s may "
+@@ -866,237 +723,14 @@
+       if (send_addr_notify)
+               call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+-      return err;
 -}
 -
--int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
+-static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 -{
--      struct tcp_sock *tp = tcp_sk(sk);
--      int i;
+-      struct net *net = skb->sk->sk_net;
+-      struct ifinfomsg *ifm;
+-      struct net_device *dev;
+-      int err;
+-      struct nlattr *tb[IFLA_MAX+1];
+-      char ifname[IFNAMSIZ];
+-      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+-      if (err < 0)
+-              goto errout;
 -
--      for (i = 0; i < tp->md5sig_info->entries4; i++) {
--              if (tp->md5sig_info->keys4[i].addr == addr) {
--                      /* Free the key */
--                      kfree(tp->md5sig_info->keys4[i].base.key);
--                      tp->md5sig_info->entries4--;
--
--                      if (tp->md5sig_info->entries4 == 0) {
--                              kfree(tp->md5sig_info->keys4);
--                              tp->md5sig_info->keys4 = NULL;
--                              tp->md5sig_info->alloced4 = 0;
--                      } else if (tp->md5sig_info->entries4 != i) {
--                              /* Need to do some manipulation */
--                              memcpy(&tp->md5sig_info->keys4[i],
--                                     &tp->md5sig_info->keys4[i+1],
--                                     (tp->md5sig_info->entries4 - i) *
--                                      sizeof(struct tcp4_md5sig_key));
--                      }
--                      tcp_free_md5sig_pool();
--                      return 0;
--              }
+-      if (tb[IFLA_IFNAME])
+-              nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
+-      else
+-              ifname[0] = '\0';
+-
+-      err = -EINVAL;
+-      ifm = nlmsg_data(nlh);
+-      if (ifm->ifi_index > 0)
+-              dev = dev_get_by_index(net, ifm->ifi_index);
+-      else if (tb[IFLA_IFNAME])
+-              dev = dev_get_by_name(net, ifname);
+-      else
+-              goto errout;
+-
+-      if (dev == NULL) {
+-              err = -ENODEV;
+-              goto errout;
 -      }
--      return -ENOENT;
--}
 -
--EXPORT_SYMBOL(tcp_v4_md5_do_del);
+-      if (tb[IFLA_ADDRESS] &&
+-          nla_len(tb[IFLA_ADDRESS]) < dev->addr_len)
+-              goto errout_dev;
+-
+-      if (tb[IFLA_BROADCAST] &&
+-          nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
+-              goto errout_dev;
 -
--static void tcp_v4_clear_md5_list(struct sock *sk)
+-      err = do_setlink(dev, ifm, tb, ifname, 0);
+-errout_dev:
+       dev_put(dev);
+ errout:
+       return err;
+ }
+-static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 -{
--      struct tcp_sock *tp = tcp_sk(sk);
+-      struct net *net = skb->sk->sk_net;
+-      const struct rtnl_link_ops *ops;
+-      struct net_device *dev;
+-      struct ifinfomsg *ifm;
+-      char ifname[IFNAMSIZ];
+-      struct nlattr *tb[IFLA_MAX+1];
+-      int err;
 -
--      /* Free each key, then the set of key keys,
--       * the crypto element, and then decrement our
--       * hold on the last resort crypto.
--       */
--      if (tp->md5sig_info->entries4) {
--              int i;
--              for (i = 0; i < tp->md5sig_info->entries4; i++)
--                      kfree(tp->md5sig_info->keys4[i].base.key);
--              tp->md5sig_info->entries4 = 0;
--              tcp_free_md5sig_pool();
--      }
--      if (tp->md5sig_info->keys4) {
--              kfree(tp->md5sig_info->keys4);
--              tp->md5sig_info->keys4 = NULL;
--              tp->md5sig_info->alloced4  = 0;
--      }
+-      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+-      if (err < 0)
+-              return err;
+-
+-      if (tb[IFLA_IFNAME])
+-              nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
+-
+-      ifm = nlmsg_data(nlh);
+-      if (ifm->ifi_index > 0)
+-              dev = __dev_get_by_index(net, ifm->ifi_index);
+-      else if (tb[IFLA_IFNAME])
+-              dev = __dev_get_by_name(net, ifname);
+-      else
+-              return -EINVAL;
+-
+-      if (!dev)
+-              return -ENODEV;
+-
+-      ops = dev->rtnl_link_ops;
+-      if (!ops)
+-              return -EOPNOTSUPP;
+-
+-      ops->dellink(dev);
+-      return 0;
 -}
 -
--static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
--                               int optlen)
+-static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 -{
--      struct tcp_md5sig cmd;
--      struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr;
--      u8 *newkey;
+-      struct net *net = skb->sk->sk_net;
+-      const struct rtnl_link_ops *ops;
+-      struct net_device *dev;
+-      struct ifinfomsg *ifm;
+-      char kind[MODULE_NAME_LEN];
+-      char ifname[IFNAMSIZ];
+-      struct nlattr *tb[IFLA_MAX+1];
+-      struct nlattr *linkinfo[IFLA_INFO_MAX+1];
+-      int err;
 -
--      if (optlen < sizeof(cmd))
--              return -EINVAL;
+-replay:
+-      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+-      if (err < 0)
+-              return err;
 -
--      if (copy_from_user(&cmd, optval, sizeof(cmd)))
--              return -EFAULT;
+-      if (tb[IFLA_IFNAME])
+-              nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
+-      else
+-              ifname[0] = '\0';
 -
--      if (sin->sin_family != AF_INET)
--              return -EINVAL;
+-      ifm = nlmsg_data(nlh);
+-      if (ifm->ifi_index > 0)
+-              dev = __dev_get_by_index(net, ifm->ifi_index);
+-      else if (ifname[0])
+-              dev = __dev_get_by_name(net, ifname);
+-      else
+-              dev = NULL;
+-
+-      if (tb[IFLA_LINKINFO]) {
+-              err = nla_parse_nested(linkinfo, IFLA_INFO_MAX,
+-                                     tb[IFLA_LINKINFO], ifla_info_policy);
+-              if (err < 0)
+-                      return err;
+-      } else
+-              memset(linkinfo, 0, sizeof(linkinfo));
+-
+-      if (linkinfo[IFLA_INFO_KIND]) {
+-              nla_strlcpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind));
+-              ops = rtnl_link_ops_get(kind);
+-      } else {
+-              kind[0] = '\0';
+-              ops = NULL;
+-      }
+-
+-      if (1) {
+-              struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL;
+-
+-              if (ops) {
+-                      if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) {
+-                              err = nla_parse_nested(attr, ops->maxtype,
+-                                                     linkinfo[IFLA_INFO_DATA],
+-                                                     ops->policy);
+-                              if (err < 0)
+-                                      return err;
+-                              data = attr;
+-                      }
+-                      if (ops->validate) {
+-                              err = ops->validate(tb, data);
+-                              if (err < 0)
+-                                      return err;
+-                      }
+-              }
+-
+-              if (dev) {
+-                      int modified = 0;
 -
--      if (!cmd.tcpm_key || !cmd.tcpm_keylen) {
--              if (!tcp_sk(sk)->md5sig_info)
--                      return -ENOENT;
--              return tcp_v4_md5_do_del(sk, sin->sin_addr.s_addr);
--      }
+-                      if (nlh->nlmsg_flags & NLM_F_EXCL)
+-                              return -EEXIST;
+-                      if (nlh->nlmsg_flags & NLM_F_REPLACE)
+-                              return -EOPNOTSUPP;
+-
+-                      if (linkinfo[IFLA_INFO_DATA]) {
+-                              if (!ops || ops != dev->rtnl_link_ops ||
+-                                  !ops->changelink)
+-                                      return -EOPNOTSUPP;
+-
+-                              err = ops->changelink(dev, tb, data);
+-                              if (err < 0)
+-                                      return err;
+-                              modified = 1;
+-                      }
 -
--      if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
--              return -EINVAL;
+-                      return do_setlink(dev, ifm, tb, ifname, modified);
+-              }
 -
--      if (!tcp_sk(sk)->md5sig_info) {
--              struct tcp_sock *tp = tcp_sk(sk);
--              struct tcp_md5sig_info *p = kzalloc(sizeof(*p), GFP_KERNEL);
+-              if (!(nlh->nlmsg_flags & NLM_F_CREATE))
+-                      return -ENODEV;
+-
+-              if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change)
+-                      return -EOPNOTSUPP;
+-              if (tb[IFLA_ADDRESS] || tb[IFLA_BROADCAST] || tb[IFLA_MAP] ||
+-                  tb[IFLA_MASTER] || tb[IFLA_PROTINFO])
+-                      return -EOPNOTSUPP;
+-
+-              if (!ops) {
+-#ifdef CONFIG_KMOD
+-                      if (kind[0]) {
+-                              __rtnl_unlock();
+-                              request_module("rtnl-link-%s", kind);
+-                              rtnl_lock();
+-                              ops = rtnl_link_ops_get(kind);
+-                              if (ops)
+-                                      goto replay;
+-                      }
+-#endif
+-                      return -EOPNOTSUPP;
+-              }
 -
--              if (!p)
--                      return -EINVAL;
+-              if (!ifname[0])
+-                      snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
+-              dev = alloc_netdev(ops->priv_size, ifname, ops->setup);
+-              if (!dev)
+-                      return -ENOMEM;
 -
--              tp->md5sig_info = p;
--              sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
+-              if (strchr(dev->name, '%')) {
+-                      err = dev_alloc_name(dev, dev->name);
+-                      if (err < 0)
+-                              goto err_free;
+-              }
+-              dev->rtnl_link_ops = ops;
+-
+-              if (tb[IFLA_MTU])
+-                      dev->mtu = nla_get_u32(tb[IFLA_MTU]);
+-              if (tb[IFLA_TXQLEN])
+-                      dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
+-              if (tb[IFLA_WEIGHT])
+-                      dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);
+-              if (tb[IFLA_OPERSTATE])
+-                      set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
+-              if (tb[IFLA_LINKMODE])
+-                      dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
+-
+-              err = ops->newlink(dev, tb, data);
+-err_free:
+-              if (err < 0)
+-                      free_netdev(dev);
+-              return err;
 -      }
+-}
 -
--      newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
--      if (!newkey)
--              return -ENOMEM;
--      return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr,
--                               newkey, cmd.tcpm_keylen);
--}
--
--static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
--                                 __be32 saddr, __be32 daddr,
--                                 struct tcphdr *th, int protocol,
--                                 int tcplen)
--{
--      struct scatterlist sg[4];
--      __u16 data_len;
--      int block = 0;
--      __sum16 old_checksum;
--      struct tcp_md5sig_pool *hp;
--      struct tcp4_pseudohdr *bp;
--      struct hash_desc *desc;
--      int err;
--      unsigned int nbytes = 0;
--
--      /*
--       * Okay, so RFC2385 is turned on for this connection,
--       * so we need to generate the MD5 hash for the packet now.
--       */
+ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct ifinfomsg *ifm;
+       struct nlattr *tb[IFLA_MAX+1];
+       struct net_device *dev = NULL;
+@@ -1109,13 +743,13 @@
+       ifm = nlmsg_data(nlh);
+       if (ifm->ifi_index > 0) {
+-              dev = dev_get_by_index(net, ifm->ifi_index);
++              dev = dev_get_by_index(ifm->ifi_index);
+               if (dev == NULL)
+                       return -ENODEV;
+       } else
+               return -EINVAL;
+-      nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
++      nskb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL);
+       if (nskb == NULL) {
+               err = -ENOBUFS;
+               goto errout;
+@@ -1129,7 +763,7 @@
+               kfree_skb(nskb);
+               goto errout;
+       }
+-      err = rtnl_unicast(nskb, net, NETLINK_CB(skb).pid);
++      err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
+ errout:
+       dev_put(dev);
+@@ -1162,14 +796,13 @@
+ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
+ {
+-      struct net *net = dev->nd_net;
+       struct sk_buff *skb;
+       int err = -ENOBUFS;
+       if (!nx_dev_visible(current->nx_info, dev))
+               return;
+-      skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
++      skb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL);
+       if (skb == NULL)
+               goto errout;
+@@ -1180,10 +813,10 @@
+               kfree_skb(skb);
+               goto errout;
+       }
+-      err = rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
++      err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
+ errout:
+       if (err < 0)
+-              rtnl_set_sk_err(net, RTNLGRP_LINK, err);
++              rtnl_set_sk_err(RTNLGRP_LINK, err);
+ }
+ /* Protected by RTNL sempahore.  */
+@@ -1194,7 +827,6 @@
+ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
+-      struct net *net = skb->sk->sk_net;
+       rtnl_doit_func doit;
+       int sz_idx, kind;
+       int min_len;
+@@ -1223,7 +855,6 @@
+               return -EPERM;
+       if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
+-              struct sock *rtnl;
+               rtnl_dumpit_func dumpit;
+               dumpit = rtnl_get_dumpit(family, type);
+@@ -1231,7 +862,6 @@
+                       return -EOPNOTSUPP;
+               __rtnl_unlock();
+-              rtnl = net->rtnl;
+               err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
+               rtnl_lock();
+               return err;
+@@ -1281,10 +911,6 @@
+ static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
+ {
+       struct net_device *dev = ptr;
 -
--      hp = tcp_get_md5sig_pool();
--      if (!hp)
--              goto clear_hash_noput;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--      bp = &hp->md5_blk.ip4;
--      desc = &hp->md5_desc;
+       switch (event) {
+       case NETDEV_UNREGISTER:
+               rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
+@@ -1310,36 +936,6 @@
+       .notifier_call  = rtnetlink_event,
+ };
 -
--      /*
--       * 1. the TCP pseudo-header (in the order: source IP address,
--       * destination IP address, zero-padded protocol number, and
--       * segment length)
--       */
--      bp->saddr = saddr;
--      bp->daddr = daddr;
--      bp->pad = 0;
--      bp->protocol = protocol;
--      bp->len = htons(tcplen);
--      sg_set_buf(&sg[block++], bp, sizeof(*bp));
--      nbytes += sizeof(*bp);
--
--      /* 2. the TCP header, excluding options, and assuming a
--       * checksum of zero/
--       */
--      old_checksum = th->check;
--      th->check = 0;
--      sg_set_buf(&sg[block++], th, sizeof(struct tcphdr));
--      nbytes += sizeof(struct tcphdr);
+-static int rtnetlink_net_init(struct net *net)
+-{
+-      struct sock *sk;
+-      sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX,
+-                                 rtnetlink_rcv, &rtnl_mutex, THIS_MODULE);
+-      if (!sk)
+-              return -ENOMEM;
 -
--      /* 3. the TCP segment data (if any) */
--      data_len = tcplen - (th->doff << 2);
--      if (data_len > 0) {
--              unsigned char *data = (unsigned char *)th + (th->doff << 2);
--              sg_set_buf(&sg[block++], data, data_len);
--              nbytes += data_len;
--      }
+-      /* Don't hold an extra reference on the namespace */
+-      put_net(sk->sk_net);
+-      net->rtnl = sk;
+-      return 0;
+-}
 -
--      /* 4. an independently-specified key or password, known to both
--       * TCPs and presumably connection-specific
+-static void rtnetlink_net_exit(struct net *net)
+-{
+-      /* At the last minute lie and say this is a socket for the
+-       * initial network namespace.  So the socket will be safe to
+-       * free.
 -       */
--      sg_set_buf(&sg[block++], key->key, key->keylen);
--      nbytes += key->keylen;
+-      net->rtnl->sk_net = get_net(&init_net);
+-      sock_put(net->rtnl);
+-}
 -
--      /* Now store the Hash into the packet */
--      err = crypto_hash_init(desc);
--      if (err)
--              goto clear_hash;
--      err = crypto_hash_update(desc, sg, nbytes);
--      if (err)
--              goto clear_hash;
--      err = crypto_hash_final(desc, md5_hash);
--      if (err)
--              goto clear_hash;
+-static struct pernet_operations rtnetlink_net_ops = {
+-      .init = rtnetlink_net_init,
+-      .exit = rtnetlink_net_exit,
+-};
 -
--      /* Reset header, and free up the crypto */
--      tcp_put_md5sig_pool();
--      th->check = old_checksum;
+ void __init rtnetlink_init(void)
+ {
+       int i;
+@@ -1352,16 +948,15 @@
+       if (!rta_buf)
+               panic("rtnetlink_init: cannot allocate rta_buf\n");
+-      if (register_pernet_subsys(&rtnetlink_net_ops))
++      rtnl = netlink_kernel_create(NETLINK_ROUTE, RTNLGRP_MAX, rtnetlink_rcv,
++                                   &rtnl_mutex, THIS_MODULE);
++      if (rtnl == NULL)
+               panic("rtnetlink_init: cannot initialize rtnetlink\n");
 -
--out:
--      return 0;
--clear_hash:
--      tcp_put_md5sig_pool();
--clear_hash_noput:
--      memset(md5_hash, 0, 16);
--      goto out;
+       netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
+       register_netdevice_notifier(&rtnetlink_dev_notifier);
+       rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo);
+       rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL);
+-      rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL);
+       rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all);
+       rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all);
+@@ -1370,7 +965,6 @@
+ EXPORT_SYMBOL(__rta_fill);
+ EXPORT_SYMBOL(rtattr_strlcpy);
+ EXPORT_SYMBOL(rtattr_parse);
+-EXPORT_SYMBOL(__rtattr_parse_nested_compat);
+ EXPORT_SYMBOL(rtnetlink_put_metrics);
+ EXPORT_SYMBOL(rtnl_lock);
+ EXPORT_SYMBOL(rtnl_trylock);
+diff -Nurb linux-2.6.22-590/net/core/skbuff.c linux-2.6.22-570/net/core/skbuff.c
+--- linux-2.6.22-590/net/core/skbuff.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/skbuff.c 2008-01-23 19:16:10.000000000 -0500
+@@ -417,7 +417,6 @@
+       C(csum);
+       C(local_df);
+       n->cloned = 1;
+-      n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
+       n->nohdr = 0;
+       C(pkt_type);
+       C(ip_summed);
+@@ -682,7 +681,6 @@
+       skb->network_header   += off;
+       skb->mac_header       += off;
+       skb->cloned   = 0;
+-      skb->hdr_len  = 0;
+       skb->nohdr    = 0;
+       atomic_set(&skb_shinfo(skb)->dataref, 1);
+       return 0;
+@@ -2014,13 +2012,13 @@
+       skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
+                                             sizeof(struct sk_buff),
+                                             0,
+-                              SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_TEMPORARY,
++                                            SLAB_HWCACHE_ALIGN|SLAB_PANIC,
+                                             NULL, NULL);
+       skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache",
+                                               (2*sizeof(struct sk_buff)) +
+                                               sizeof(atomic_t),
+                                               0,
+-                              SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_TEMPORARY,
++                                              SLAB_HWCACHE_ALIGN|SLAB_PANIC,
+                                               NULL, NULL);
+ }
+diff -Nurb linux-2.6.22-590/net/core/sock.c linux-2.6.22-570/net/core/sock.c
+--- linux-2.6.22-590/net/core/sock.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/sock.c   2008-01-23 19:16:10.000000000 -0500
+@@ -123,7 +123,6 @@
+ #include <net/sock.h>
+ #include <net/xfrm.h>
+ #include <linux/ipsec.h>
+-#include <net/net_namespace.h>
+ #include <linux/filter.h>
+ #include <linux/vs_socket.h>
+@@ -361,7 +360,6 @@
+                   char __user *optval, int optlen)
+ {
+       struct sock *sk=sock->sk;
+-      struct net *net = sk->sk_net;
+       struct sk_filter *filter;
+       int val;
+       int valbool;
+@@ -616,7 +614,7 @@
+                       if (devname[0] == '\0') {
+                               sk->sk_bound_dev_if = 0;
+                       } else {
+-                              struct net_device *dev = dev_get_by_name(net, devname);
++                              struct net_device *dev = dev_get_by_name(devname);
+                               if (!dev) {
+                                       ret = -ENODEV;
+                                       break;
+@@ -869,7 +867,7 @@
+  *    @prot: struct proto associated with this new sock instance
+  *    @zero_it: if we should zero the newly allocated sock
+  */
+-struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
++struct sock *sk_alloc(int family, gfp_t priority,
+                     struct proto *prot, int zero_it)
+ {
+       struct sock *sk = NULL;
+@@ -890,7 +888,6 @@
+                        */
+                       sk->sk_prot = sk->sk_prot_creator = prot;
+                       sock_lock_init(sk);
+-                      sk->sk_net = get_net(net);
+               }
+               sock_vx_init(sk);
+               sock_nx_init(sk);
+@@ -932,7 +929,6 @@
+                      __FUNCTION__, atomic_read(&sk->sk_omem_alloc));
+       security_sk_free(sk);
+-      put_net(sk->sk_net);
+       vx_sock_dec(sk);
+       clr_vx_info(&sk->sk_vx_info);
+       sk->sk_xid = -1;
+@@ -947,7 +943,7 @@
+ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
+ {
+-      struct sock *newsk = sk_alloc(sk->sk_net, sk->sk_family, priority, sk->sk_prot, 0);
++      struct sock *newsk = sk_alloc(sk->sk_family, priority, sk->sk_prot, 0);
+       if (newsk != NULL) {
+               struct sk_filter *filter;
+@@ -2021,7 +2017,7 @@
+ static int __init proto_init(void)
+ {
+       /* register /proc/net/protocols */
+-      return proc_net_fops_create(&init_net, "protocols", S_IRUGO, &proto_seq_fops) == NULL ? -ENOBUFS : 0;
++      return proc_net_fops_create("protocols", S_IRUGO, &proto_seq_fops) == NULL ? -ENOBUFS : 0;
+ }
+ subsys_initcall(proto_init);
+diff -Nurb linux-2.6.22-590/net/core/sysctl_net_core.c linux-2.6.22-570/net/core/sysctl_net_core.c
+--- linux-2.6.22-590/net/core/sysctl_net_core.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/core/sysctl_net_core.c        2007-07-08 19:32:17.000000000 -0400
+@@ -9,10 +9,25 @@
+ #include <linux/sysctl.h>
+ #include <linux/module.h>
+ #include <linux/socket.h>
+-#include <linux/netdevice.h>
+-#include <net/xfrm.h>
+ #include <net/sock.h>
++#ifdef CONFIG_SYSCTL
++
++extern int netdev_max_backlog;
++extern int weight_p;
++
++extern __u32 sysctl_wmem_max;
++extern __u32 sysctl_rmem_max;
++
++extern int sysctl_core_destroy_delay;
++
++#ifdef CONFIG_XFRM
++extern u32 sysctl_xfrm_aevent_etime;
++extern u32 sysctl_xfrm_aevent_rseqth;
++extern int sysctl_xfrm_larval_drop;
++extern u32 sysctl_xfrm_acq_expires;
++#endif
++
+ ctl_table core_table[] = {
+ #ifdef CONFIG_NET
+       {
+@@ -88,32 +103,11 @@
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+       },
+-#endif /* CONFIG_NET */
+-      {
+-              .ctl_name       = NET_CORE_BUDGET,
+-              .procname       = "netdev_budget",
+-              .data           = &netdev_budget,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec
+-      },
+-      {
+-              .ctl_name       = NET_CORE_WARNINGS,
+-              .procname       = "warnings",
+-              .data           = &net_msg_warn,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec
+-      },
+-      { .ctl_name = 0 }
+-};
+-
+-struct ctl_table multi_core_table[] = {
+ #ifdef CONFIG_XFRM
+       {
+               .ctl_name       = NET_CORE_AEVENT_ETIME,
+               .procname       = "xfrm_aevent_etime",
+-              .data           = &init_net.sysctl_xfrm_aevent_etime,
++              .data           = &sysctl_xfrm_aevent_etime,
+               .maxlen         = sizeof(u32),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+@@ -121,7 +115,7 @@
+       {
+               .ctl_name       = NET_CORE_AEVENT_RSEQTH,
+               .procname       = "xfrm_aevent_rseqth",
+-              .data           = &init_net.sysctl_xfrm_aevent_rseqth,
++              .data           = &sysctl_xfrm_aevent_rseqth,
+               .maxlen         = sizeof(u32),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+@@ -129,7 +123,7 @@
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "xfrm_larval_drop",
+-              .data           = &init_net.sysctl_xfrm_larval_drop,
++              .data           = &sysctl_xfrm_larval_drop,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+@@ -137,19 +131,38 @@
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "xfrm_acq_expires",
+-              .data           = &init_net.sysctl_xfrm_acq_expires,
++              .data           = &sysctl_xfrm_acq_expires,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+       },
+ #endif /* CONFIG_XFRM */
++#endif /* CONFIG_NET */
+       {
+               .ctl_name       = NET_CORE_SOMAXCONN,
+               .procname       = "somaxconn",
+-              .data           = &init_net.sysctl_somaxconn,
++              .data           = &sysctl_somaxconn,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec
++      },
++      {
++              .ctl_name       = NET_CORE_BUDGET,
++              .procname       = "netdev_budget",
++              .data           = &netdev_budget,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+       },
+-      {}
++      {
++              .ctl_name       = NET_CORE_WARNINGS,
++              .procname       = "warnings",
++              .data           = &net_msg_warn,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec
++      },
++      { .ctl_name = 0 }
+ };
++
++#endif
+diff -Nurb linux-2.6.22-590/net/dccp/ccids/ccid3.c linux-2.6.22-570/net/dccp/ccids/ccid3.c
+--- linux-2.6.22-590/net/dccp/ccids/ccid3.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/dccp/ccids/ccid3.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1,8 +1,8 @@
+ /*
+  *  net/dccp/ccids/ccid3.c
+  *
+- *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+- *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
++ *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
++ *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
+  *
+  *  An implementation of the DCCP protocol
+  *
+@@ -49,6 +49,7 @@
+ static struct dccp_tx_hist *ccid3_tx_hist;
+ static struct dccp_rx_hist *ccid3_rx_hist;
++static struct dccp_li_hist *ccid3_li_hist;
+ /*
+  *    Transmitter Half-Connection Routines
+@@ -193,20 +194,25 @@
+  *    The algorithm is not applicable if RTT < 4 microseconds.
+  */
+ static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx,
+-                                              ktime_t now)
++                                              struct timeval *now)
+ {
++      suseconds_t delta;
+       u32 quarter_rtts;
+       if (unlikely(hctx->ccid3hctx_rtt < 4))  /* avoid divide-by-zero */
+               return;
+-      quarter_rtts = ktime_us_delta(now, hctx->ccid3hctx_t_last_win_count);
+-      quarter_rtts /= hctx->ccid3hctx_rtt / 4;
++      delta = timeval_delta(now, &hctx->ccid3hctx_t_last_win_count);
++      DCCP_BUG_ON(delta < 0);
++
++      quarter_rtts = (u32)delta / (hctx->ccid3hctx_rtt / 4);
+       if (quarter_rtts > 0) {
+-              hctx->ccid3hctx_t_last_win_count = now;
++              hctx->ccid3hctx_t_last_win_count = *now;
+               hctx->ccid3hctx_last_win_count  += min_t(u32, quarter_rtts, 5);
+               hctx->ccid3hctx_last_win_count  &= 0xF;         /* mod 16 */
++
++              ccid3_pr_debug("now at %#X\n", hctx->ccid3hctx_last_win_count);
+       }
+ }
+@@ -306,8 +312,8 @@
+ {
+       struct dccp_sock *dp = dccp_sk(sk);
+       struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+-      ktime_t now = ktime_get_real();
+-      s64 delay;
++      struct timeval now;
++      suseconds_t delay;
+       BUG_ON(hctx == NULL);
+@@ -319,6 +325,8 @@
+       if (unlikely(skb->len == 0))
+               return -EBADMSG;
++      dccp_timestamp(sk, &now);
++
+       switch (hctx->ccid3hctx_state) {
+       case TFRC_SSTATE_NO_SENT:
+               sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
+@@ -341,7 +349,7 @@
+                       ccid3_pr_debug("SYN RTT = %uus\n", dp->dccps_syn_rtt);
+                       hctx->ccid3hctx_rtt  = dp->dccps_syn_rtt;
+                       hctx->ccid3hctx_x    = rfc3390_initial_rate(sk);
+-                      hctx->ccid3hctx_t_ld = ktime_to_timeval(now);
++                      hctx->ccid3hctx_t_ld = now;
+               } else {
+                       /* Sender does not have RTT sample: X = MSS/second */
+                       hctx->ccid3hctx_x = dp->dccps_mss_cache;
+@@ -353,7 +361,7 @@
+               break;
+       case TFRC_SSTATE_NO_FBACK:
+       case TFRC_SSTATE_FBACK:
+-              delay = ktime_us_delta(hctx->ccid3hctx_t_nom, now);
++              delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
+               ccid3_pr_debug("delay=%ld\n", (long)delay);
+               /*
+                *      Scheduling of packet transmissions [RFC 3448, 4.6]
+@@ -363,10 +371,10 @@
+                * else
+                *       // send the packet in (t_nom - t_now) milliseconds.
+                */
+-              if (delay - (s64)hctx->ccid3hctx_delta >= 1000)
+-                      return (u32)delay / 1000L;
++              if (delay - (suseconds_t)hctx->ccid3hctx_delta >= 0)
++                      return delay / 1000L;
+-              ccid3_hc_tx_update_win_count(hctx, now);
++              ccid3_hc_tx_update_win_count(hctx, &now);
+               break;
+       case TFRC_SSTATE_TERM:
+               DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
+@@ -379,8 +387,8 @@
+       hctx->ccid3hctx_idle = 0;
+       /* set the nominal send time for the next following packet */
+-      hctx->ccid3hctx_t_nom = ktime_add_us(hctx->ccid3hctx_t_nom,
+-                                           hctx->ccid3hctx_t_ipi);
++      timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
++
+       return 0;
+ }
+@@ -811,6 +819,154 @@
+       return 0;
+ }
++/* calculate first loss interval
++ *
++ * returns estimated loss interval in usecs */
++
++static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
++{
++      struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
++      struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
++      u32 x_recv, p;
++      suseconds_t rtt, delta;
++      struct timeval tstamp = { 0, };
++      int interval = 0;
++      int win_count = 0;
++      int step = 0;
++      u64 fval;
++
++      list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
++                               dccphrx_node) {
++              if (dccp_rx_hist_entry_data_packet(entry)) {
++                      tail = entry;
++
++                      switch (step) {
++                      case 0:
++                              tstamp    = entry->dccphrx_tstamp;
++                              win_count = entry->dccphrx_ccval;
++                              step = 1;
++                              break;
++                      case 1:
++                              interval = win_count - entry->dccphrx_ccval;
++                              if (interval < 0)
++                                      interval += TFRC_WIN_COUNT_LIMIT;
++                              if (interval > 4)
++                                      goto found;
++                              break;
++                      }
++              }
++      }
++
++      if (unlikely(step == 0)) {
++              DCCP_WARN("%s(%p), packet history has no data packets!\n",
++                        dccp_role(sk), sk);
++              return ~0;
++      }
++
++      if (unlikely(interval == 0)) {
++              DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
++                        "Defaulting to 1\n", dccp_role(sk), sk);
++              interval = 1;
++      }
++found:
++      if (!tail) {
++              DCCP_CRIT("tail is null\n");
++              return ~0;
++      }
++
++      delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
++      DCCP_BUG_ON(delta < 0);
++
++      rtt = delta * 4 / interval;
++      ccid3_pr_debug("%s(%p), approximated RTT to %dus\n",
++                     dccp_role(sk), sk, (int)rtt);
++
++      /*
++       * Determine the length of the first loss interval via inverse lookup.
++       * Assume that X_recv can be computed by the throughput equation
++       *                  s
++       *      X_recv = --------
++       *               R * fval
++       * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
++       */
++      if (rtt == 0) {                 /* would result in divide-by-zero */
++              DCCP_WARN("RTT==0\n");
++              return ~0;
++      }
++
++      dccp_timestamp(sk, &tstamp);
++      delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
++      DCCP_BUG_ON(delta <= 0);
++
++      x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
++      if (x_recv == 0) {              /* would also trigger divide-by-zero */
++              DCCP_WARN("X_recv==0\n");
++              if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) {
++                      DCCP_BUG("stored value of X_recv is zero");
++                      return ~0;
++              }
++      }
++
++      fval = scaled_div(hcrx->ccid3hcrx_s, rtt);
++      fval = scaled_div32(fval, x_recv);
++      p = tfrc_calc_x_reverse_lookup(fval);
++
++      ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
++                     "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
++
++      if (p == 0)
++              return ~0;
++      else
++              return 1000000 / p;
++}
++
++static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
++{
++      struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
++      struct dccp_li_hist_entry *head;
++      u64 seq_temp;
++
++      if (list_empty(&hcrx->ccid3hcrx_li_hist)) {
++              if (!dccp_li_hist_interval_new(ccid3_li_hist,
++                 &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss))
++                      return;
++
++              head = list_entry(hcrx->ccid3hcrx_li_hist.next,
++                 struct dccp_li_hist_entry, dccplih_node);
++              head->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
++      } else {
++              struct dccp_li_hist_entry *entry;
++              struct list_head *tail;
++
++              head = list_entry(hcrx->ccid3hcrx_li_hist.next,
++                 struct dccp_li_hist_entry, dccplih_node);
++              /* FIXME win count check removed as was wrong */
++              /* should make this check with receive history */
++              /* and compare there as per section 10.2 of RFC4342 */
++
++              /* new loss event detected */
++              /* calculate last interval length */
++              seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
++              entry = dccp_li_hist_entry_new(ccid3_li_hist, GFP_ATOMIC);
++
++              if (entry == NULL) {
++                      DCCP_BUG("out of memory - can not allocate entry");
++                      return;
++              }
++
++              list_add(&entry->dccplih_node, &hcrx->ccid3hcrx_li_hist);
++
++              tail = hcrx->ccid3hcrx_li_hist.prev;
++              list_del(tail);
++              kmem_cache_free(ccid3_li_hist->dccplih_slab, tail);
++
++              /* Create the newest interval */
++              entry->dccplih_seqno = seq_loss;
++              entry->dccplih_interval = seq_temp;
++              entry->dccplih_win_count = win_loss;
++      }
++}
++
+ static int ccid3_hc_rx_detect_loss(struct sock *sk,
+                                   struct dccp_rx_hist_entry *packet)
+ {
+@@ -836,14 +992,7 @@
+       while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno)
+          > TFRC_RECV_NUM_LATE_LOSS) {
+               loss = 1;
+-              dccp_li_update_li(sk,
+-                                &hcrx->ccid3hcrx_li_hist,
+-                                &hcrx->ccid3hcrx_hist,
+-                                &hcrx->ccid3hcrx_tstamp_last_feedback,
+-                                hcrx->ccid3hcrx_s,
+-                                hcrx->ccid3hcrx_bytes_recv,
+-                                hcrx->ccid3hcrx_x_recv,
+-                                hcrx->ccid3hcrx_seqno_nonloss,
++              ccid3_hc_rx_update_li(sk, hcrx->ccid3hcrx_seqno_nonloss,
+                  hcrx->ccid3hcrx_ccval_nonloss);
+               tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
+               dccp_inc_seqno(&tmp_seqno);
+@@ -1003,7 +1152,7 @@
+       dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
+       /* Empty loss interval history */
+-      dccp_li_hist_purge(&hcrx->ccid3hcrx_li_hist);
++      dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
+ }
+ static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
+@@ -1087,12 +1236,19 @@
+       if (ccid3_tx_hist == NULL)
+               goto out_free_rx;
++      ccid3_li_hist = dccp_li_hist_new("ccid3");
++      if (ccid3_li_hist == NULL)
++              goto out_free_tx;
++
+       rc = ccid_register(&ccid3);
+       if (rc != 0)
+-              goto out_free_tx;
++              goto out_free_loss_interval_history;
+ out:
+       return rc;
++out_free_loss_interval_history:
++      dccp_li_hist_delete(ccid3_li_hist);
++      ccid3_li_hist = NULL;
+ out_free_tx:
+       dccp_tx_hist_delete(ccid3_tx_hist);
+       ccid3_tx_hist = NULL;
+@@ -1115,6 +1271,10 @@
+               dccp_rx_hist_delete(ccid3_rx_hist);
+               ccid3_rx_hist = NULL;
+       }
++      if (ccid3_li_hist != NULL) {
++              dccp_li_hist_delete(ccid3_li_hist);
++              ccid3_li_hist = NULL;
++      }
+ }
+ module_exit(ccid3_module_exit);
+diff -Nurb linux-2.6.22-590/net/dccp/ccids/ccid3.h linux-2.6.22-570/net/dccp/ccids/ccid3.h
+--- linux-2.6.22-590/net/dccp/ccids/ccid3.h    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/dccp/ccids/ccid3.h    2007-07-08 19:32:17.000000000 -0400
+@@ -36,7 +36,6 @@
+ #ifndef _DCCP_CCID3_H_
+ #define _DCCP_CCID3_H_
+-#include <linux/ktime.h>
+ #include <linux/list.h>
+ #include <linux/time.h>
+ #include <linux/types.h>
+@@ -109,10 +108,10 @@
+       enum ccid3_hc_tx_states         ccid3hctx_state:8;
+       u8                              ccid3hctx_last_win_count;
+       u8                              ccid3hctx_idle;
+-      ktime_t                         ccid3hctx_t_last_win_count;
++      struct timeval                  ccid3hctx_t_last_win_count;
+       struct timer_list               ccid3hctx_no_feedback_timer;
+       struct timeval                  ccid3hctx_t_ld;
+-      ktime_t                         ccid3hctx_t_nom;
++      struct timeval                  ccid3hctx_t_nom;
+       u32                             ccid3hctx_delta;
+       struct list_head                ccid3hctx_hist;
+       struct ccid3_options_received   ccid3hctx_options_received;
+diff -Nurb linux-2.6.22-590/net/dccp/ccids/lib/loss_interval.c linux-2.6.22-570/net/dccp/ccids/lib/loss_interval.c
+--- linux-2.6.22-590/net/dccp/ccids/lib/loss_interval.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/dccp/ccids/lib/loss_interval.c        2007-07-08 19:32:17.000000000 -0400
+@@ -1,8 +1,8 @@
+ /*
+  *  net/dccp/ccids/lib/loss_interval.c
+  *
+- *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+- *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
++ *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
++ *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
+  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+  *
+  *  This program is free software; you can redistribute it and/or modify
+@@ -15,38 +15,58 @@
+ #include <net/sock.h>
+ #include "../../dccp.h"
+ #include "loss_interval.h"
+-#include "packet_history.h"
+-#include "tfrc.h"
+-#define DCCP_LI_HIST_IVAL_F_LENGTH  8
++struct dccp_li_hist *dccp_li_hist_new(const char *name)
++{
++      struct dccp_li_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
++      static const char dccp_li_hist_mask[] = "li_hist_%s";
++      char *slab_name;
++
++      if (hist == NULL)
++              goto out;
++
++      slab_name = kmalloc(strlen(name) + sizeof(dccp_li_hist_mask) - 1,
++                          GFP_ATOMIC);
++      if (slab_name == NULL)
++              goto out_free_hist;
+-struct dccp_li_hist_entry {
+-      struct list_head dccplih_node;
+-      u64              dccplih_seqno:48,
+-                       dccplih_win_count:4;
+-      u32              dccplih_interval;
+-};
++      sprintf(slab_name, dccp_li_hist_mask, name);
++      hist->dccplih_slab = kmem_cache_create(slab_name,
++                                           sizeof(struct dccp_li_hist_entry),
++                                             0, SLAB_HWCACHE_ALIGN,
++                                             NULL, NULL);
++      if (hist->dccplih_slab == NULL)
++              goto out_free_slab_name;
++out:
++      return hist;
++out_free_slab_name:
++      kfree(slab_name);
++out_free_hist:
++      kfree(hist);
++      hist = NULL;
++      goto out;
++}
+-struct kmem_cache *dccp_li_cachep __read_mostly;
++EXPORT_SYMBOL_GPL(dccp_li_hist_new);
+-static inline struct dccp_li_hist_entry *dccp_li_hist_entry_new(const gfp_t prio)
++void dccp_li_hist_delete(struct dccp_li_hist *hist)
+ {
+-      return kmem_cache_alloc(dccp_li_cachep, prio);
 -}
--
--int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
--                       struct sock *sk,
--                       struct dst_entry *dst,
--                       struct request_sock *req,
--                       struct tcphdr *th, int protocol,
--                       int tcplen)
++      const char* name = kmem_cache_name(hist->dccplih_slab);
+-static inline void dccp_li_hist_entry_delete(struct dccp_li_hist_entry *entry)
 -{
--      __be32 saddr, daddr;
--
--      if (sk) {
--              saddr = inet_sk(sk)->saddr;
--              daddr = inet_sk(sk)->daddr;
--      } else {
--              struct rtable *rt = (struct rtable *)dst;
--              BUG_ON(!rt);
--              saddr = rt->rt_src;
--              daddr = rt->rt_dst;
--      }
--      return tcp_v4_do_calc_md5_hash(md5_hash, key,
--                                     saddr, daddr,
--                                     th, protocol, tcplen);
--}
--
--EXPORT_SYMBOL(tcp_v4_calc_md5_hash);
--
--static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb)
+-      if (entry != NULL)
+-              kmem_cache_free(dccp_li_cachep, entry);
++      kmem_cache_destroy(hist->dccplih_slab);
++      kfree(name);
++      kfree(hist);
+ }
+-void dccp_li_hist_purge(struct list_head *list)
++EXPORT_SYMBOL_GPL(dccp_li_hist_delete);
++
++void dccp_li_hist_purge(struct dccp_li_hist *hist, struct list_head *list)
+ {
+       struct dccp_li_hist_entry *entry, *next;
+       list_for_each_entry_safe(entry, next, list, dccplih_node) {
+               list_del_init(&entry->dccplih_node);
+-              kmem_cache_free(dccp_li_cachep, entry);
++              kmem_cache_free(hist->dccplih_slab, entry);
+       }
+ }
+@@ -98,16 +118,16 @@
+ EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
+-static int dccp_li_hist_interval_new(struct list_head *list,
+-                                   const u64 seq_loss, const u8 win_loss)
++int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
++   struct list_head *list, const u64 seq_loss, const u8 win_loss)
+ {
+       struct dccp_li_hist_entry *entry;
+       int i;
+       for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) {
+-              entry = dccp_li_hist_entry_new(GFP_ATOMIC);
++              entry = dccp_li_hist_entry_new(hist, GFP_ATOMIC);
+               if (entry == NULL) {
+-                      dccp_li_hist_purge(list);
++                      dccp_li_hist_purge(hist, list);
+                       DCCP_BUG("loss interval list entry is NULL");
+                       return 0;
+               }
+@@ -120,176 +140,4 @@
+       return 1;
+ }
+-/* calculate first loss interval
+- *
+- * returns estimated loss interval in usecs */
+-static u32 dccp_li_calc_first_li(struct sock *sk,
+-                               struct list_head *hist_list,
+-                               struct timeval *last_feedback,
+-                               u16 s, u32 bytes_recv,
+-                               u32 previous_x_recv)
 -{
--      /*
--       * This gets called for each TCP segment that arrives
--       * so we want to be efficient.
--       * We have 3 drop cases:
--       * o No MD5 hash and one expected.
--       * o MD5 hash and we're not expecting one.
--       * o MD5 hash and its wrong.
--       */
--      __u8 *hash_location = NULL;
--      struct tcp_md5sig_key *hash_expected;
--      const struct iphdr *iph = ip_hdr(skb);
--      struct tcphdr *th = tcp_hdr(skb);
--      int length = (th->doff << 2) - sizeof(struct tcphdr);
--      int genhash;
--      unsigned char *ptr;
--      unsigned char newhash[16];
--
--      hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr);
--
--      /*
--       * If the TCP option length is less than the TCP_MD5SIG
--       * option length, then we can shortcut
--       */
--      if (length < TCPOLEN_MD5SIG) {
--              if (hash_expected)
--                      return 1;
--              else
--                      return 0;
--      }
--
--      /* Okay, we can't shortcut - we have to grub through the options */
--      ptr = (unsigned char *)(th + 1);
--      while (length > 0) {
--              int opcode = *ptr++;
--              int opsize;
--
--              switch (opcode) {
--              case TCPOPT_EOL:
--                      goto done_opts;
--              case TCPOPT_NOP:
--                      length--;
--                      continue;
--              default:
--                      opsize = *ptr++;
--                      if (opsize < 2)
--                              goto done_opts;
--                      if (opsize > length)
--                              goto done_opts;
--
--                      if (opcode == TCPOPT_MD5SIG) {
--                              hash_location = ptr;
--                              goto done_opts;
--                      }
--              }
--              ptr += opsize-2;
--              length -= opsize;
--      }
--done_opts:
--      /* We've parsed the options - do we have a hash? */
--      if (!hash_expected && !hash_location)
--              return 0;
--
--      if (hash_expected && !hash_location) {
--              LIMIT_NETDEBUG(KERN_INFO "MD5 Hash expected but NOT found "
--                             "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n",
--                             NIPQUAD(iph->saddr), ntohs(th->source),
--                             NIPQUAD(iph->daddr), ntohs(th->dest));
--              return 1;
--      }
--
--      if (!hash_expected && hash_location) {
--              LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found "
--                             "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n",
--                             NIPQUAD(iph->saddr), ntohs(th->source),
--                             NIPQUAD(iph->daddr), ntohs(th->dest));
--              return 1;
--      }
--
--      /* Okay, so this is hash_expected and hash_location -
--       * so we need to calculate the checksum.
--       */
--      genhash = tcp_v4_do_calc_md5_hash(newhash,
--                                        hash_expected,
--                                        iph->saddr, iph->daddr,
--                                        th, sk->sk_protocol,
--                                        skb->len);
--
--      if (genhash || memcmp(hash_location, newhash, 16) != 0) {
--              if (net_ratelimit()) {
--                      printk(KERN_INFO "MD5 Hash failed for "
--                             "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)%s\n",
--                             NIPQUAD(iph->saddr), ntohs(th->source),
--                             NIPQUAD(iph->daddr), ntohs(th->dest),
--                             genhash ? " tcp_v4_calc_md5_hash failed" : "");
--              }
--              return 1;
--      }
--      return 0;
--}
--
--#endif
--
--struct request_sock_ops tcp_request_sock_ops __read_mostly = {
--      .family         =       PF_INET,
--      .obj_size       =       sizeof(struct tcp_request_sock),
--      .rtx_syn_ack    =       tcp_v4_send_synack,
--      .send_ack       =       tcp_v4_reqsk_send_ack,
--      .destructor     =       tcp_v4_reqsk_destructor,
--      .send_reset     =       tcp_v4_send_reset,
--};
--
--#ifdef CONFIG_TCP_MD5SIG
--static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
--      .md5_lookup     =       tcp_v4_reqsk_md5_lookup,
--};
--#endif
--
--static struct timewait_sock_ops tcp_timewait_sock_ops = {
--      .twsk_obj_size  = sizeof(struct tcp_timewait_sock),
--      .twsk_unique    = tcp_twsk_unique,
--      .twsk_destructor= tcp_twsk_destructor,
--};
--
--int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
--{
--      struct inet_request_sock *ireq;
--      struct tcp_options_received tmp_opt;
--      struct request_sock *req;
--      __be32 saddr = ip_hdr(skb)->saddr;
--      __be32 daddr = ip_hdr(skb)->daddr;
--      __u32 isn = TCP_SKB_CB(skb)->when;
--      struct dst_entry *dst = NULL;
--#ifdef CONFIG_SYN_COOKIES
--      int want_cookie = 0;
--#else
--#define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */
--#endif
--
--      /* Never answer to SYNs send to broadcast or multicast */
--      if (((struct rtable *)skb->dst)->rt_flags &
--          (RTCF_BROADCAST | RTCF_MULTICAST))
--              goto drop;
--
--      /* TW buckets are converted to open requests without
--       * limitations, they conserve resources and peer is
--       * evidently real one.
--       */
--      if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
--#ifdef CONFIG_SYN_COOKIES
--              if (sysctl_tcp_syncookies) {
--                      want_cookie = 1;
--              } else
--#endif
--              goto drop;
--      }
--
--      /* Accept backlog is full. If we have already queued enough
--       * of warm entries in syn queue, drop request. It is better than
--       * clogging syn queue with openreqs with exponentially increasing
--       * timeout.
--       */
--      if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
--              goto drop;
--
--      req = reqsk_alloc(&tcp_request_sock_ops);
--      if (!req)
--              goto drop;
--
--#ifdef CONFIG_TCP_MD5SIG
--      tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops;
--#endif
--
--      tcp_clear_options(&tmp_opt);
--      tmp_opt.mss_clamp = 536;
--      tmp_opt.user_mss  = tcp_sk(sk)->rx_opt.user_mss;
--
--      tcp_parse_options(skb, &tmp_opt, 0);
--
--      if (want_cookie) {
--              tcp_clear_options(&tmp_opt);
--              tmp_opt.saw_tstamp = 0;
--      }
--
--      if (tmp_opt.saw_tstamp && !tmp_opt.rcv_tsval) {
--              /* Some OSes (unknown ones, but I see them on web server, which
--               * contains information interesting only for windows'
--               * users) do not send their stamp in SYN. It is easy case.
--               * We simply do not advertise TS support.
--               */
--              tmp_opt.saw_tstamp = 0;
--              tmp_opt.tstamp_ok  = 0;
--      }
--      tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
--
--      tcp_openreq_init(req, &tmp_opt, skb);
--
--      if (security_inet_conn_request(sk, skb, req))
--              goto drop_and_free;
+-      struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
+-      u32 x_recv, p;
+-      suseconds_t rtt, delta;
+-      struct timeval tstamp = { 0, 0 };
+-      int interval = 0;
+-      int win_count = 0;
+-      int step = 0;
+-      u64 fval;
 -
--      ireq = inet_rsk(req);
--      ireq->loc_addr = daddr;
--      ireq->rmt_addr = saddr;
--      ireq->opt = tcp_v4_save_options(sk, skb);
--      if (!want_cookie)
--              TCP_ECN_create_request(req, tcp_hdr(skb));
+-      list_for_each_entry_safe(entry, next, hist_list, dccphrx_node) {
+-              if (dccp_rx_hist_entry_data_packet(entry)) {
+-                      tail = entry;
 -
--      if (want_cookie) {
--#ifdef CONFIG_SYN_COOKIES
--              syn_flood_warning(skb);
--#endif
--              isn = cookie_v4_init_sequence(sk, skb, &req->mss);
--      } else if (!isn) {
--              struct inet_peer *peer = NULL;
--
--              /* VJ's idea. We save last timestamp seen
--               * from the destination in peer table, when entering
--               * state TIME-WAIT, and check against it before
--               * accepting new connection request.
--               *
--               * If "isn" is not zero, this request hit alive
--               * timewait bucket, so that all the necessary checks
--               * are made in the function processing timewait state.
--               */
--              if (tmp_opt.saw_tstamp &&
--                  tcp_death_row.sysctl_tw_recycle &&
--                  (dst = inet_csk_route_req(sk, req)) != NULL &&
--                  (peer = rt_get_peer((struct rtable *)dst)) != NULL &&
--                  peer->v4daddr == saddr) {
--                      if (get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
--                          (s32)(peer->tcp_ts - req->ts_recent) >
--                                                      TCP_PAWS_WINDOW) {
--                              NET_INC_STATS_BH(LINUX_MIB_PAWSPASSIVEREJECTED);
--                              dst_release(dst);
--                              goto drop_and_free;
+-                      switch (step) {
+-                      case 0:
+-                              tstamp    = entry->dccphrx_tstamp;
+-                              win_count = entry->dccphrx_ccval;
+-                              step = 1;
+-                              break;
+-                      case 1:
+-                              interval = win_count - entry->dccphrx_ccval;
+-                              if (interval < 0)
+-                                      interval += TFRC_WIN_COUNT_LIMIT;
+-                              if (interval > 4)
+-                                      goto found;
+-                              break;
 -                      }
 -              }
--              /* Kill the following clause, if you dislike this way. */
--              else if (!sysctl_tcp_syncookies &&
--                       (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) <
--                        (sysctl_max_syn_backlog >> 2)) &&
--                       (!peer || !peer->tcp_ts_stamp) &&
--                       (!dst || !dst_metric(dst, RTAX_RTT))) {
--                      /* Without syncookies last quarter of
--                       * backlog is filled with destinations,
--                       * proven to be alive.
--                       * It means that we continue to communicate
--                       * to destinations, already remembered
--                       * to the moment of synflood.
--                       */
--                      LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open "
--                                     "request from %u.%u.%u.%u/%u\n",
--                                     NIPQUAD(saddr),
--                                     ntohs(tcp_hdr(skb)->source));
--                      dst_release(dst);
--                      goto drop_and_free;
--              }
--
--              isn = tcp_v4_init_sequence(skb);
--      }
--      tcp_rsk(req)->snt_isn = isn;
--
--      if (tcp_v4_send_synack(sk, req, dst))
--              goto drop_and_free;
--
--      if (want_cookie) {
--              reqsk_free(req);
--      } else {
--              inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
 -      }
--      return 0;
--
--drop_and_free:
--      reqsk_free(req);
--drop:
--      return 0;
--}
--
--
--/*
-- * The three way handshake has completed - we got a valid synack -
-- * now create the new socket.
-- */
--struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
--                                struct request_sock *req,
--                                struct dst_entry *dst)
--{
--      struct inet_request_sock *ireq;
--      struct inet_sock *newinet;
--      struct tcp_sock *newtp;
--      struct sock *newsk;
--#ifdef CONFIG_TCP_MD5SIG
--      struct tcp_md5sig_key *key;
--#endif
--
--      if (sk_acceptq_is_full(sk))
--              goto exit_overflow;
 -
--      if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL)
--              goto exit;
--
--      newsk = tcp_create_openreq_child(sk, req, skb);
--      if (!newsk)
--              goto exit;
--
--      newsk->sk_gso_type = SKB_GSO_TCPV4;
--      sk_setup_caps(newsk, dst);
--
--      newtp                 = tcp_sk(newsk);
--      newinet               = inet_sk(newsk);
--      ireq                  = inet_rsk(req);
--      newinet->daddr        = ireq->rmt_addr;
--      newinet->rcv_saddr    = ireq->loc_addr;
--      newinet->saddr        = ireq->loc_addr;
--      newinet->opt          = ireq->opt;
--      ireq->opt             = NULL;
--      newinet->mc_index     = inet_iif(skb);
--      newinet->mc_ttl       = ip_hdr(skb)->ttl;
--      inet_csk(newsk)->icsk_ext_hdr_len = 0;
--      if (newinet->opt)
--              inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen;
--      newinet->id = newtp->write_seq ^ jiffies;
--
--      tcp_mtup_init(newsk);
--      tcp_sync_mss(newsk, dst_mtu(dst));
--      newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
--      tcp_initialize_rcv_mss(newsk);
--
--#ifdef CONFIG_TCP_MD5SIG
--      /* Copy over the MD5 key from the original socket */
--      if ((key = tcp_v4_md5_do_lookup(sk, newinet->daddr)) != NULL) {
--              /*
--               * We're using one, so create a matching key
--               * on the newsk structure. If we fail to get
--               * memory, then we end up not copying the key
--               * across. Shucks.
--               */
--              char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC);
--              if (newkey != NULL)
--                      tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr,
--                                        newkey, key->keylen);
+-      if (unlikely(step == 0)) {
+-              DCCP_WARN("%s(%p), packet history has no data packets!\n",
+-                        dccp_role(sk), sk);
+-              return ~0;
 -      }
--#endif
--
--      __inet_hash(&tcp_hashinfo, newsk, 0);
--      __inet_inherit_port(&tcp_hashinfo, sk, newsk);
--
--      return newsk;
--
--exit_overflow:
--      NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS);
--exit:
--      NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS);
--      dst_release(dst);
--      return NULL;
--}
--
--static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
--{
--      struct tcphdr *th = tcp_hdr(skb);
--      const struct iphdr *iph = ip_hdr(skb);
--      struct sock *nsk;
--      struct request_sock **prev;
--      /* Find possible connection requests. */
--      struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
--                                                     iph->saddr, iph->daddr);
--      if (req)
--              return tcp_check_req(sk, skb, req, prev);
--
--      nsk = inet_lookup_established(&tcp_hashinfo, iph->saddr, th->source,
--                                    iph->daddr, th->dest, inet_iif(skb));
 -
--      if (nsk) {
--              if (nsk->sk_state != TCP_TIME_WAIT) {
--                      bh_lock_sock(nsk);
--                      return nsk;
--              }
--              inet_twsk_put(inet_twsk(nsk));
--              return NULL;
+-      if (unlikely(interval == 0)) {
+-              DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
+-                        "Defaulting to 1\n", dccp_role(sk), sk);
+-              interval = 1;
 -      }
--
--#ifdef CONFIG_SYN_COOKIES
--      if (!th->rst && !th->syn && th->ack)
--              sk = cookie_v4_check(sk, skb, &(IPCB(skb)->opt));
--#endif
--      return sk;
--}
--
--static __sum16 tcp_v4_checksum_init(struct sk_buff *skb)
--{
--      const struct iphdr *iph = ip_hdr(skb);
--
--      if (skb->ip_summed == CHECKSUM_COMPLETE) {
--              if (!tcp_v4_check(skb->len, iph->saddr,
--                                iph->daddr, skb->csum)) {
--                      skb->ip_summed = CHECKSUM_UNNECESSARY;
--                      return 0;
--              }
+-found:
+-      if (!tail) {
+-              DCCP_CRIT("tail is null\n");
+-              return ~0;
 -      }
 -
--      skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
--                                     skb->len, IPPROTO_TCP, 0);
--
--      if (skb->len <= 76) {
--              return __skb_checksum_complete(skb);
--      }
--      return 0;
--}
+-      delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
+-      DCCP_BUG_ON(delta < 0);
 -
+-      rtt = delta * 4 / interval;
+-      dccp_pr_debug("%s(%p), approximated RTT to %dus\n",
+-                    dccp_role(sk), sk, (int)rtt);
 -
--/* The socket must have it's spinlock held when we get
-- * here.
-- *
-- * We have a potential double-lock case here, so even when
-- * doing backlog processing we use the BH locking scheme.
-- * This is because we cannot sleep with the original spinlock
-- * held.
-- */
--int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
--{
--      struct sock *rsk;
--#ifdef CONFIG_TCP_MD5SIG
 -      /*
--       * We really want to reject the packet as early as possible
--       * if:
--       *  o We're expecting an MD5'd packet and this is no MD5 tcp option
--       *  o There is an MD5 option and we're not expecting one
+-       * Determine the length of the first loss interval via inverse lookup.
+-       * Assume that X_recv can be computed by the throughput equation
+-       *                  s
+-       *      X_recv = --------
+-       *               R * fval
+-       * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
 -       */
--      if (tcp_v4_inbound_md5_hash(sk, skb))
--              goto discard;
--#endif
--
--      if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
--              TCP_CHECK_TIMER(sk);
--              if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
--                      rsk = sk;
--                      goto reset;
--              }
--              TCP_CHECK_TIMER(sk);
--              return 0;
+-      if (rtt == 0) {                 /* would result in divide-by-zero */
+-              DCCP_WARN("RTT==0\n");
+-              return ~0;
 -      }
 -
--      if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
--              goto csum_err;
--
--      if (sk->sk_state == TCP_LISTEN) {
--              struct sock *nsk = tcp_v4_hnd_req(sk, skb);
--              if (!nsk)
--                      goto discard;
+-      dccp_timestamp(sk, &tstamp);
+-      delta = timeval_delta(&tstamp, last_feedback);
+-      DCCP_BUG_ON(delta <= 0);
 -
--              if (nsk != sk) {
--                      if (tcp_child_process(sk, nsk, skb)) {
--                              rsk = nsk;
--                              goto reset;
--                      }
--                      return 0;
+-      x_recv = scaled_div32(bytes_recv, delta);
+-      if (x_recv == 0) {              /* would also trigger divide-by-zero */
+-              DCCP_WARN("X_recv==0\n");
+-              if (previous_x_recv == 0) {
+-                      DCCP_BUG("stored value of X_recv is zero");
+-                      return ~0;
 -              }
+-              x_recv = previous_x_recv;
 -      }
 -
--      TCP_CHECK_TIMER(sk);
--      if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) {
--              rsk = sk;
--              goto reset;
--      }
--      TCP_CHECK_TIMER(sk);
--      return 0;
+-      fval = scaled_div(s, rtt);
+-      fval = scaled_div32(fval, x_recv);
+-      p = tfrc_calc_x_reverse_lookup(fval);
 -
--reset:
--      tcp_v4_send_reset(rsk, skb);
--discard:
--      kfree_skb(skb);
--      /* Be careful here. If this function gets more complicated and
--       * gcc suffers from register pressure on the x86, sk (in %ebx)
--       * might be destroyed here. This current version compiles correctly,
--       * but you have been warned.
--       */
--      return 0;
+-      dccp_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
+-                    "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
 -
--csum_err:
--      TCP_INC_STATS_BH(TCP_MIB_INERRS);
--      goto discard;
+-      if (p == 0)
+-              return ~0;
+-      else
+-              return 1000000 / p;
 -}
 -
--/*
-- *    From tcp_input.c
-- */
--
--int tcp_v4_rcv(struct sk_buff *skb)
+-void dccp_li_update_li(struct sock *sk,
+-                     struct list_head *li_hist_list,
+-                     struct list_head *hist_list,
+-                     struct timeval *last_feedback, u16 s, u32 bytes_recv,
+-                       u32 previous_x_recv, u64 seq_loss, u8 win_loss)
 -{
--      const struct iphdr *iph;
--      struct tcphdr *th;
--      struct sock *sk;
--      int ret;
--
--      if (skb->pkt_type != PACKET_HOST)
--              goto discard_it;
--
--      /* Count it even if it's bad */
--      TCP_INC_STATS_BH(TCP_MIB_INSEGS);
--
--      if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
--              goto discard_it;
--
--      th = tcp_hdr(skb);
--
--      if (th->doff < sizeof(struct tcphdr) / 4)
--              goto bad_packet;
--      if (!pskb_may_pull(skb, th->doff * 4))
--              goto discard_it;
--
--      /* An explanation is required here, I think.
--       * Packet length and doff are validated by header prediction,
--       * provided case of th->doff==0 is eliminated.
--       * So, we defer the checks. */
--      if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb))
--              goto bad_packet;
--
--      th = tcp_hdr(skb);
--      iph = ip_hdr(skb);
--      TCP_SKB_CB(skb)->seq = ntohl(th->seq);
--      TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
--                                  skb->len - th->doff * 4);
--      TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
--      TCP_SKB_CB(skb)->when    = 0;
--      TCP_SKB_CB(skb)->flags   = iph->tos;
--      TCP_SKB_CB(skb)->sacked  = 0;
--
--      sk = __inet_lookup(&tcp_hashinfo, iph->saddr, th->source,
--                         iph->daddr, th->dest, inet_iif(skb));
--      if (!sk)
--              goto no_tcp_socket;
--
--process:
--      if (sk->sk_state == TCP_TIME_WAIT)
--              goto do_time_wait;
--
--      if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
--              goto discard_and_relse;
--      nf_reset(skb);
--
--      if (sk_filter(sk, skb))
--              goto discard_and_relse;
--
--      skb->dev = NULL;
--
--      bh_lock_sock_nested(sk);
--      ret = 0;
--      if (!sock_owned_by_user(sk)) {
--#ifdef CONFIG_NET_DMA
--              struct tcp_sock *tp = tcp_sk(sk);
--              if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
--                      tp->ucopy.dma_chan = get_softnet_dma();
--              if (tp->ucopy.dma_chan)
--                      ret = tcp_v4_do_rcv(sk, skb);
--              else
--#endif
--              {
--                      if (!tcp_prequeue(sk, skb))
--                      ret = tcp_v4_do_rcv(sk, skb);
--              }
--      } else
--              sk_add_backlog(sk, skb);
--      bh_unlock_sock(sk);
--
--      sock_put(sk);
--
--      return ret;
--
--no_tcp_socket:
--      if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
--              goto discard_it;
--
--      if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
--bad_packet:
--              TCP_INC_STATS_BH(TCP_MIB_INERRS);
--      } else {
--              tcp_v4_send_reset(NULL, skb);
--      }
--
--discard_it:
--      /* Discard frame. */
--      kfree_skb(skb);
--      return 0;
--
--discard_and_relse:
--      sock_put(sk);
--      goto discard_it;
--
--do_time_wait:
--      if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
--              inet_twsk_put(inet_twsk(sk));
--              goto discard_it;
--      }
--
--      if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
--              TCP_INC_STATS_BH(TCP_MIB_INERRS);
--              inet_twsk_put(inet_twsk(sk));
--              goto discard_it;
--      }
--      switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
--      case TCP_TW_SYN: {
--              struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo,
--                                                      iph->daddr, th->dest,
--                                                      inet_iif(skb));
--              if (sk2) {
--                      inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
--                      inet_twsk_put(inet_twsk(sk));
--                      sk = sk2;
--                      goto process;
--              }
--              /* Fall through to ACK */
--      }
--      case TCP_TW_ACK:
--              tcp_v4_timewait_ack(sk, skb);
--              break;
--      case TCP_TW_RST:
--              goto no_tcp_socket;
--      case TCP_TW_SUCCESS:;
--      }
--      goto discard_it;
--}
--
--/* VJ's idea. Save last timestamp seen from this destination
-- * and hold it at least for normal timewait interval to use for duplicate
-- * segment detection in subsequent connections, before they enter synchronized
-- * state.
-- */
+-      struct dccp_li_hist_entry *head;
+-      u64 seq_temp;
 -
--int tcp_v4_remember_stamp(struct sock *sk)
--{
--      struct inet_sock *inet = inet_sk(sk);
--      struct tcp_sock *tp = tcp_sk(sk);
--      struct rtable *rt = (struct rtable *)__sk_dst_get(sk);
--      struct inet_peer *peer = NULL;
--      int release_it = 0;
+-      if (list_empty(li_hist_list)) {
+-              if (!dccp_li_hist_interval_new(li_hist_list, seq_loss,
+-                                             win_loss))
+-                      return;
 -
--      if (!rt || rt->rt_dst != inet->daddr) {
--              peer = inet_getpeer(inet->daddr, 1);
--              release_it = 1;
+-              head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
+-                                dccplih_node);
+-              head->dccplih_interval = dccp_li_calc_first_li(sk, hist_list,
+-                                                             last_feedback,
+-                                                             s, bytes_recv,
+-                                                             previous_x_recv);
 -      } else {
--              if (!rt->peer)
--                      rt_bind_peer(rt, 1);
--              peer = rt->peer;
--      }
--
--      if (peer) {
--              if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 ||
--                  (peer->tcp_ts_stamp + TCP_PAWS_MSL < get_seconds() &&
--                   peer->tcp_ts_stamp <= tp->rx_opt.ts_recent_stamp)) {
--                      peer->tcp_ts_stamp = tp->rx_opt.ts_recent_stamp;
--                      peer->tcp_ts = tp->rx_opt.ts_recent;
--              }
--              if (release_it)
--                      inet_putpeer(peer);
--              return 1;
--      }
--
--      return 0;
--}
+-              struct dccp_li_hist_entry *entry;
+-              struct list_head *tail;
 -
--int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
--{
--      struct inet_peer *peer = inet_getpeer(tw->tw_daddr, 1);
+-              head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
+-                                dccplih_node);
+-              /* FIXME win count check removed as was wrong */
+-              /* should make this check with receive history */
+-              /* and compare there as per section 10.2 of RFC4342 */
 -
--      if (peer) {
--              const struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
+-              /* new loss event detected */
+-              /* calculate last interval length */
+-              seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
+-              entry = dccp_li_hist_entry_new(GFP_ATOMIC);
 -
--              if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 ||
--                  (peer->tcp_ts_stamp + TCP_PAWS_MSL < get_seconds() &&
--                   peer->tcp_ts_stamp <= tcptw->tw_ts_recent_stamp)) {
--                      peer->tcp_ts_stamp = tcptw->tw_ts_recent_stamp;
--                      peer->tcp_ts       = tcptw->tw_ts_recent;
+-              if (entry == NULL) {
+-                      DCCP_BUG("out of memory - can not allocate entry");
+-                      return;
 -              }
--              inet_putpeer(peer);
--              return 1;
--      }
--
--      return 0;
--}
--
--struct inet_connection_sock_af_ops ipv4_specific = {
--      .queue_xmit        = ip_queue_xmit,
--      .send_check        = tcp_v4_send_check,
--      .rebuild_header    = inet_sk_rebuild_header,
--      .conn_request      = tcp_v4_conn_request,
--      .syn_recv_sock     = tcp_v4_syn_recv_sock,
--      .remember_stamp    = tcp_v4_remember_stamp,
--      .net_header_len    = sizeof(struct iphdr),
--      .setsockopt        = ip_setsockopt,
--      .getsockopt        = ip_getsockopt,
--      .addr2sockaddr     = inet_csk_addr2sockaddr,
--      .sockaddr_len      = sizeof(struct sockaddr_in),
--#ifdef CONFIG_COMPAT
--      .compat_setsockopt = compat_ip_setsockopt,
--      .compat_getsockopt = compat_ip_getsockopt,
--#endif
--};
--
--#ifdef CONFIG_TCP_MD5SIG
--static struct tcp_sock_af_ops tcp_sock_ipv4_specific = {
--      .md5_lookup             = tcp_v4_md5_lookup,
--      .calc_md5_hash          = tcp_v4_calc_md5_hash,
--      .md5_add                = tcp_v4_md5_add_func,
--      .md5_parse              = tcp_v4_parse_md5_keys,
--};
--#endif
--
--/* NOTE: A lot of things set to zero explicitly by call to
-- *       sk_alloc() so need not be done here.
-- */
--static int tcp_v4_init_sock(struct sock *sk)
--{
--      struct inet_connection_sock *icsk = inet_csk(sk);
--      struct tcp_sock *tp = tcp_sk(sk);
--
--      skb_queue_head_init(&tp->out_of_order_queue);
--      tcp_init_xmit_timers(sk);
--      tcp_prequeue_init(tp);
--
--      icsk->icsk_rto = TCP_TIMEOUT_INIT;
--      tp->mdev = TCP_TIMEOUT_INIT;
--
--      /* So many TCP implementations out there (incorrectly) count the
--       * initial SYN frame in their delayed-ACK and congestion control
--       * algorithms that we must have the following bandaid to talk
--       * efficiently to them.  -DaveM
--       */
--      tp->snd_cwnd = 2;
--
--      /* See draft-stevens-tcpca-spec-01 for discussion of the
--       * initialization of these values.
--       */
--      tp->snd_ssthresh = 0x7fffffff;  /* Infinity */
--      tp->snd_cwnd_clamp = ~0;
--      tp->mss_cache = 536;
--
--      tp->reordering = sysctl_tcp_reordering;
--      icsk->icsk_ca_ops = &tcp_init_congestion_ops;
--
--      sk->sk_state = TCP_CLOSE;
--
--      sk->sk_write_space = sk_stream_write_space;
--      sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
--
--      icsk->icsk_af_ops = &ipv4_specific;
--      icsk->icsk_sync_mss = tcp_sync_mss;
--#ifdef CONFIG_TCP_MD5SIG
--      tp->af_specific = &tcp_sock_ipv4_specific;
--#endif
--
--      sk->sk_sndbuf = sysctl_tcp_wmem[1];
--      sk->sk_rcvbuf = sysctl_tcp_rmem[1];
--
--      atomic_inc(&tcp_sockets_allocated);
--
--      return 0;
--}
--
--int tcp_v4_destroy_sock(struct sock *sk)
--{
--      struct tcp_sock *tp = tcp_sk(sk);
--
--      tcp_clear_xmit_timers(sk);
--
--      tcp_cleanup_congestion_control(sk);
--
--      /* Cleanup up the write buffer. */
--      tcp_write_queue_purge(sk);
--
--      /* Cleans up our, hopefully empty, out_of_order_queue. */
--      __skb_queue_purge(&tp->out_of_order_queue);
--
--#ifdef CONFIG_TCP_MD5SIG
--      /* Clean up the MD5 key list, if any */
--      if (tp->md5sig_info) {
--              tcp_v4_clear_md5_list(sk);
--              kfree(tp->md5sig_info);
--              tp->md5sig_info = NULL;
--      }
--#endif
 -
--#ifdef CONFIG_NET_DMA
--      /* Cleans up our sk_async_wait_queue */
--      __skb_queue_purge(&sk->sk_async_wait_queue);
--#endif
--
--      /* Clean prequeue, it must be empty really */
--      __skb_queue_purge(&tp->ucopy.prequeue);
+-              list_add(&entry->dccplih_node, li_hist_list);
 -
--      /* Clean up a referenced TCP bind bucket. */
--      if (inet_csk(sk)->icsk_bind_hash)
--              inet_put_port(&tcp_hashinfo, sk);
+-              tail = li_hist_list->prev;
+-              list_del(tail);
+-              kmem_cache_free(dccp_li_cachep, tail);
 -
--      /*
--       * If sendmsg cached page exists, toss it.
--       */
--      if (sk->sk_sndmsg_page) {
--              __free_page(sk->sk_sndmsg_page);
--              sk->sk_sndmsg_page = NULL;
+-              /* Create the newest interval */
+-              entry->dccplih_seqno = seq_loss;
+-              entry->dccplih_interval = seq_temp;
+-              entry->dccplih_win_count = win_loss;
 -      }
--
--      atomic_dec(&tcp_sockets_allocated);
--
--      return 0;
--}
--
--EXPORT_SYMBOL(tcp_v4_destroy_sock);
--
--#ifdef CONFIG_PROC_FS
--/* Proc filesystem TCP sock list dumping. */
--
--static inline struct inet_timewait_sock *tw_head(struct hlist_head *head)
--{
--      return hlist_empty(head) ? NULL :
--              list_entry(head->first, struct inet_timewait_sock, tw_node);
--}
--
--static inline struct inet_timewait_sock *tw_next(struct inet_timewait_sock *tw)
--{
--      return tw->tw_node.next ?
--              hlist_entry(tw->tw_node.next, typeof(*tw), tw_node) : NULL;
 -}
 -
--static void *listening_get_next(struct seq_file *seq, void *cur)
--{
--      struct inet_connection_sock *icsk;
--      struct hlist_node *node;
--      struct sock *sk = cur;
--      struct tcp_iter_state* st = seq->private;
--
--      if (!sk) {
--              st->bucket = 0;
--              sk = sk_head(&tcp_hashinfo.listening_hash[0]);
--              goto get_sk;
--      }
--
--      ++st->num;
--
--      if (st->state == TCP_SEQ_STATE_OPENREQ) {
--              struct request_sock *req = cur;
--
--              icsk = inet_csk(st->syn_wait_sk);
--              req = req->dl_next;
--              while (1) {
--                      while (req) {
--                              if (req->rsk_ops->family == st->family) {
--                                      cur = req;
--                                      goto out;
--                              }
--                              req = req->dl_next;
--                      }
--                      if (++st->sbucket >= icsk->icsk_accept_queue.listen_opt->nr_table_entries)
--                              break;
--get_req:
--                      req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket];
--              }
--              sk        = sk_next(st->syn_wait_sk);
--              st->state = TCP_SEQ_STATE_LISTENING;
--              read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
--      } else {
--              icsk = inet_csk(sk);
--              read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
--              if (reqsk_queue_len(&icsk->icsk_accept_queue))
--                      goto start_req;
--              read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
--              sk = sk_next(sk);
--      }
--get_sk:
--      sk_for_each_from(sk, node) {
--              if (sk->sk_family == st->family) {
--                      cur = sk;
--                      goto out;
--              }
--              icsk = inet_csk(sk);
--              read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
--              if (reqsk_queue_len(&icsk->icsk_accept_queue)) {
--start_req:
--                      st->uid         = sock_i_uid(sk);
--                      st->syn_wait_sk = sk;
--                      st->state       = TCP_SEQ_STATE_OPENREQ;
--                      st->sbucket     = 0;
--                      goto get_req;
--              }
--              read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
--      }
--      if (++st->bucket < INET_LHTABLE_SIZE) {
--              sk = sk_head(&tcp_hashinfo.listening_hash[st->bucket]);
--              goto get_sk;
--      }
--      cur = NULL;
--out:
--      return cur;
--}
+-EXPORT_SYMBOL_GPL(dccp_li_update_li);
 -
--static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
+-static __init int dccp_li_init(void)
 -{
--      void *rc = listening_get_next(seq, NULL);
--
--      while (rc && *pos) {
--              rc = listening_get_next(seq, rc);
--              --*pos;
--      }
--      return rc;
+-      dccp_li_cachep = kmem_cache_create("dccp_li_hist",
+-                                         sizeof(struct dccp_li_hist_entry),
+-                                         0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+-      return dccp_li_cachep == NULL ? -ENOBUFS : 0;
 -}
 -
--static void *established_get_first(struct seq_file *seq)
+-static __exit void dccp_li_exit(void)
 -{
--      struct tcp_iter_state* st = seq->private;
--      void *rc = NULL;
--
--      for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) {
--              struct sock *sk;
--              struct hlist_node *node;
--              struct inet_timewait_sock *tw;
--
--              /* We can reschedule _before_ having picked the target: */
--              cond_resched_softirq();
--
--              read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
--              sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
--                      if (sk->sk_family != st->family) {
--                              continue;
--                      }
--                      rc = sk;
--                      goto out;
--              }
--              st->state = TCP_SEQ_STATE_TIME_WAIT;
--              inet_twsk_for_each(tw, node,
--                                 &tcp_hashinfo.ehash[st->bucket].twchain) {
--                      if (tw->tw_family != st->family) {
--                              continue;
--                      }
--                      rc = tw;
--                      goto out;
--              }
--              read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
--              st->state = TCP_SEQ_STATE_ESTABLISHED;
--      }
--out:
--      return rc;
+-      kmem_cache_destroy(dccp_li_cachep);
 -}
 -
--static void *established_get_next(struct seq_file *seq, void *cur)
--{
--      struct sock *sk = cur;
--      struct inet_timewait_sock *tw;
--      struct hlist_node *node;
--      struct tcp_iter_state* st = seq->private;
--
--      ++st->num;
--
--      if (st->state == TCP_SEQ_STATE_TIME_WAIT) {
--              tw = cur;
--              tw = tw_next(tw);
--get_tw:
--              while (tw && tw->tw_family != st->family) {
--                      tw = tw_next(tw);
--              }
--              if (tw) {
--                      cur = tw;
--                      goto out;
--              }
--              read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
--              st->state = TCP_SEQ_STATE_ESTABLISHED;
--
--              /* We can reschedule between buckets: */
--              cond_resched_softirq();
--
--              if (++st->bucket < tcp_hashinfo.ehash_size) {
--                      read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
--                      sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
--              } else {
--                      cur = NULL;
--                      goto out;
--              }
--      } else
--              sk = sk_next(sk);
+-module_init(dccp_li_init);
+-module_exit(dccp_li_exit);
++EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new);
+diff -Nurb linux-2.6.22-590/net/dccp/ccids/lib/loss_interval.h linux-2.6.22-570/net/dccp/ccids/lib/loss_interval.h
+--- linux-2.6.22-590/net/dccp/ccids/lib/loss_interval.h        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/dccp/ccids/lib/loss_interval.h        2007-07-08 19:32:17.000000000 -0400
+@@ -3,8 +3,8 @@
+ /*
+  *  net/dccp/ccids/lib/loss_interval.h
+  *
+- *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+- *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
++ *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
++ *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
+  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+  *
+  *  This program is free software; you can redistribute it and/or modify it
+@@ -14,16 +14,44 @@
+  */
+ #include <linux/list.h>
++#include <linux/slab.h>
+ #include <linux/time.h>
+-extern void dccp_li_hist_purge(struct list_head *list);
++#define DCCP_LI_HIST_IVAL_F_LENGTH  8
++
++struct dccp_li_hist {
++      struct kmem_cache *dccplih_slab;
++};
++
++extern struct dccp_li_hist *dccp_li_hist_new(const char *name);
++extern void dccp_li_hist_delete(struct dccp_li_hist *hist);
++
++struct dccp_li_hist_entry {
++      struct list_head dccplih_node;
++      u64              dccplih_seqno:48,
++                       dccplih_win_count:4;
++      u32              dccplih_interval;
++};
++
++static inline struct dccp_li_hist_entry *
++              dccp_li_hist_entry_new(struct dccp_li_hist *hist,
++                                     const gfp_t prio)
++{
++      return kmem_cache_alloc(hist->dccplih_slab, prio);
++}
++
++static inline void dccp_li_hist_entry_delete(struct dccp_li_hist *hist,
++                                           struct dccp_li_hist_entry *entry)
++{
++      if (entry != NULL)
++              kmem_cache_free(hist->dccplih_slab, entry);
++}
++
++extern void dccp_li_hist_purge(struct dccp_li_hist *hist,
++                             struct list_head *list);
+ extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
+-extern void dccp_li_update_li(struct sock *sk,
+-                            struct list_head *li_hist_list,
+-                            struct list_head *hist_list,
+-                            struct timeval *last_feedback, u16 s,
+-                            u32 bytes_recv, u32 previous_x_recv,
+-                            u64 seq_loss, u8 win_loss);
++extern int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
++   struct list_head *list, const u64 seq_loss, const u8 win_loss);
+ #endif /* _DCCP_LI_HIST_ */
+diff -Nurb linux-2.6.22-590/net/dccp/dccp.h linux-2.6.22-570/net/dccp/dccp.h
+--- linux-2.6.22-590/net/dccp/dccp.h   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/dccp/dccp.h   2007-07-08 19:32:17.000000000 -0400
+@@ -184,7 +184,7 @@
+ /*
+  *    Checksumming routines
+  */
+-static inline unsigned int dccp_csum_coverage(const struct sk_buff *skb)
++static inline int dccp_csum_coverage(const struct sk_buff *skb)
+ {
+       const struct dccp_hdr* dh = dccp_hdr(skb);
+@@ -195,7 +195,7 @@
+ static inline void dccp_csum_outgoing(struct sk_buff *skb)
+ {
+-      unsigned int cov = dccp_csum_coverage(skb);
++      int cov = dccp_csum_coverage(skb);
+       if (cov >= skb->len)
+               dccp_hdr(skb)->dccph_cscov = 0;
+diff -Nurb linux-2.6.22-590/net/dccp/ipv4.c linux-2.6.22-570/net/dccp/ipv4.c
+--- linux-2.6.22-590/net/dccp/ipv4.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/dccp/ipv4.c   2007-07-08 19:32:17.000000000 -0400
+@@ -202,7 +202,6 @@
+  */
+ static void dccp_v4_err(struct sk_buff *skb, u32 info)
+ {
+-      struct net *net = skb->dev->nd_net;
+       const struct iphdr *iph = (struct iphdr *)skb->data;
+       const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data +
+                                                       (iph->ihl << 2));
+@@ -214,16 +213,13 @@
+       __u64 seq;
+       int err;
+-      if (skb->dev->nd_net != &init_net)
+-              return;
 -
--      sk_for_each_from(sk, node) {
--              if (sk->sk_family == st->family)
--                      goto found;
+       if (skb->len < (iph->ihl << 2) + 8) {
+               ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+               return;
+       }
+       sk = inet_lookup(&dccp_hashinfo, iph->daddr, dh->dccph_dport,
+-                       iph->saddr, dh->dccph_sport, inet_iif(skb), net);
++                       iph->saddr, dh->dccph_sport, inet_iif(skb));
+       if (sk == NULL) {
+               ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+               return;
+@@ -445,7 +441,7 @@
+       nsk = inet_lookup_established(&dccp_hashinfo,
+                                     iph->saddr, dh->dccph_sport,
+                                     iph->daddr, dh->dccph_dport,
+-                                    inet_iif(skb), sk->sk_net);
++                                    inet_iif(skb));
+       if (nsk != NULL) {
+               if (nsk->sk_state != DCCP_TIME_WAIT) {
+                       bh_lock_sock(nsk);
+@@ -462,8 +458,7 @@
+                                          struct sk_buff *skb)
+ {
+       struct rtable *rt;
+-      struct flowi fl = { .fl_net = &init_net,
+-                          .oif = ((struct rtable *)skb->dst)->rt_iif,
++      struct flowi fl = { .oif = ((struct rtable *)skb->dst)->rt_iif,
+                           .nl_u = { .ip4_u =
+                                     { .daddr = ip_hdr(skb)->saddr,
+                                       .saddr = ip_hdr(skb)->daddr,
+@@ -814,16 +809,11 @@
+ /* this is called when real data arrives */
+ static int dccp_v4_rcv(struct sk_buff *skb)
+ {
+-      struct net *net = skb->dev->nd_net;
+       const struct dccp_hdr *dh;
+       const struct iphdr *iph;
+       struct sock *sk;
+       int min_cov;
+-      if (skb->dev->nd_net != &init_net) {
+-              kfree_skb(skb);
+-              return 0;
 -      }
+       /* Step 1: Check header basics */
+       if (dccp_invalid_packet(skb))
+@@ -862,7 +852,7 @@
+        *      Look up flow ID in table and get corresponding socket */
+       sk = __inet_lookup(&dccp_hashinfo,
+                          iph->saddr, dh->dccph_sport,
+-                         iph->daddr, dh->dccph_dport, inet_iif(skb), net);
++                         iph->daddr, dh->dccph_dport, inet_iif(skb));
+       /*
+        * Step 2:
+        *      If no socket ...
+diff -Nurb linux-2.6.22-590/net/dccp/ipv6.c linux-2.6.22-570/net/dccp/ipv6.c
+--- linux-2.6.22-590/net/dccp/ipv6.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/dccp/ipv6.c   2007-07-08 19:32:17.000000000 -0400
+@@ -94,7 +94,6 @@
+ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+                       int type, int code, int offset, __be32 info)
+ {
+-      struct net *net = skb->dev->nd_net;
+       struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data;
+       const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
+       struct ipv6_pinfo *np;
+@@ -103,7 +102,7 @@
+       __u64 seq;
+       sk = inet6_lookup(&dccp_hashinfo, &hdr->daddr, dh->dccph_dport,
+-                        &hdr->saddr, dh->dccph_sport, inet6_iif(skb), net);
++                        &hdr->saddr, dh->dccph_sport, inet6_iif(skb));
+       if (sk == NULL) {
+               ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
+@@ -143,7 +142,6 @@
+                          for now.
+                        */
+                       memset(&fl, 0, sizeof(fl));
+-                      fl.fl_net = &init_net;
+                       fl.proto = IPPROTO_DCCP;
+                       ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
+                       ipv6_addr_copy(&fl.fl6_src, &np->saddr);
+@@ -244,7 +242,6 @@
+       int err = -1;
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net,
+       fl.proto = IPPROTO_DCCP;
+       ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
+       ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
+@@ -361,7 +358,6 @@
+                                                     &rxip6h->daddr);
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       ipv6_addr_copy(&fl.fl6_dst, &rxip6h->saddr);
+       ipv6_addr_copy(&fl.fl6_src, &rxip6h->daddr);
+@@ -411,7 +407,7 @@
+       nsk = __inet6_lookup_established(&dccp_hashinfo,
+                                        &iph->saddr, dh->dccph_sport,
+                                        &iph->daddr, ntohs(dh->dccph_dport),
+-                                       inet6_iif(skb), sk->sk_net);
++                                       inet6_iif(skb));
+       if (nsk != NULL) {
+               if (nsk->sk_state != DCCP_TIME_WAIT) {
+                       bh_lock_sock(nsk);
+@@ -588,7 +584,6 @@
+               struct flowi fl;
+               memset(&fl, 0, sizeof(fl));
+-              fl.fl_net = &init_net;
+               fl.proto = IPPROTO_DCCP;
+               ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
+               if (opt != NULL && opt->srcrt != NULL) {
+@@ -824,7 +819,6 @@
+ {
+       const struct dccp_hdr *dh;
+       struct sk_buff *skb = *pskb;
+-      struct net *net = skb->dev->nd_net;
+       struct sock *sk;
+       int min_cov;
+@@ -855,7 +849,7 @@
+       sk = __inet6_lookup(&dccp_hashinfo, &ipv6_hdr(skb)->saddr,
+                           dh->dccph_sport,
+                           &ipv6_hdr(skb)->daddr, ntohs(dh->dccph_dport),
+-                          inet6_iif(skb), net);
++                          inet6_iif(skb));
+       /*
+        * Step 2:
+        *      If no socket ...
+@@ -943,7 +937,6 @@
+               return -EAFNOSUPPORT;
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       if (np->sndflow) {
+               fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
+diff -Nurb linux-2.6.22-590/net/dccp/probe.c linux-2.6.22-570/net/dccp/probe.c
+--- linux-2.6.22-590/net/dccp/probe.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/dccp/probe.c  2007-07-08 19:32:17.000000000 -0400
+@@ -30,7 +30,6 @@
+ #include <linux/module.h>
+ #include <linux/kfifo.h>
+ #include <linux/vmalloc.h>
+-#include <net/net_namespace.h>
+ #include "dccp.h"
+ #include "ccid.h"
+@@ -169,7 +168,7 @@
+       if (IS_ERR(dccpw.fifo))
+               return PTR_ERR(dccpw.fifo);
+-      if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &dccpprobe_fops))
++      if (!proc_net_fops_create(procname, S_IRUSR, &dccpprobe_fops))
+               goto err0;
+       ret = register_jprobe(&dccp_send_probe);
+@@ -179,7 +178,7 @@
+       pr_info("DCCP watch registered (port=%d)\n", port);
+       return 0;
+ err1:
+-      proc_net_remove(&init_net, procname);
++      proc_net_remove(procname);
+ err0:
+       kfifo_free(dccpw.fifo);
+       return ret;
+@@ -189,7 +188,7 @@
+ static __exit void dccpprobe_exit(void)
+ {
+       kfifo_free(dccpw.fifo);
+-      proc_net_remove(&init_net, procname);
++      proc_net_remove(procname);
+       unregister_jprobe(&dccp_send_probe);
+ }
+diff -Nurb linux-2.6.22-590/net/decnet/af_decnet.c linux-2.6.22-570/net/decnet/af_decnet.c
+--- linux-2.6.22-590/net/decnet/af_decnet.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/decnet/af_decnet.c    2007-07-08 19:32:17.000000000 -0400
+@@ -131,7 +131,6 @@
+ #include <net/neighbour.h>
+ #include <net/dst.h>
+ #include <net/fib_rules.h>
+-#include <net/net_namespace.h>
+ #include <net/dn.h>
+ #include <net/dn_nsp.h>
+ #include <net/dn_dev.h>
+@@ -471,10 +470,10 @@
+       .obj_size               = sizeof(struct dn_sock),
+ };
+-static struct sock *dn_alloc_sock(struct net *net, struct socket *sock, gfp_t gfp)
++static struct sock *dn_alloc_sock(struct socket *sock, gfp_t gfp)
+ {
+       struct dn_scp *scp;
+-      struct sock *sk = sk_alloc(net, PF_DECnet, gfp, &dn_proto, 1);
++      struct sock *sk = sk_alloc(PF_DECnet, gfp, &dn_proto, 1);
+       if  (!sk)
+               goto out;
+@@ -675,13 +674,10 @@
+-static int dn_create(struct net *net, struct socket *sock, int protocol)
++static int dn_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
 -
--      st->state = TCP_SEQ_STATE_TIME_WAIT;
--      tw = tw_head(&tcp_hashinfo.ehash[st->bucket].twchain);
--      goto get_tw;
--found:
--      cur = sk;
--out:
--      return cur;
--}
--
--static void *established_get_idx(struct seq_file *seq, loff_t pos)
--{
--      void *rc = established_get_first(seq);
+       switch(sock->type) {
+               case SOCK_SEQPACKET:
+                       if (protocol != DNPROTO_NSP)
+@@ -694,7 +690,7 @@
+       }
+-      if ((sk = dn_alloc_sock(net, sock, GFP_KERNEL)) == NULL)
++      if ((sk = dn_alloc_sock(sock, GFP_KERNEL)) == NULL)
+               return -ENOBUFS;
+       sk->sk_protocol = protocol;
+@@ -751,7 +747,7 @@
+               if (dn_ntohs(saddr->sdn_nodeaddrl)) {
+                       read_lock(&dev_base_lock);
+                       ldev = NULL;
+-                      for_each_netdev(&init_net, dev) {
++                      for_each_netdev(dev) {
+                               if (!dev->dn_ptr)
+                                       continue;
+                               if (dn_dev_islocal(dev, dn_saddr2dn(saddr))) {
+@@ -947,7 +943,6 @@
+       err = -EHOSTUNREACH;
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       fl.oif = sk->sk_bound_dev_if;
+       fl.fld_dst = dn_saddr2dn(&scp->peer);
+       fl.fld_src = dn_saddr2dn(&scp->addr);
+@@ -1095,7 +1090,7 @@
+       cb = DN_SKB_CB(skb);
+       sk->sk_ack_backlog--;
+-      newsk = dn_alloc_sock(sk->sk_net, newsock, sk->sk_allocation);
++      newsk = dn_alloc_sock(newsock, sk->sk_allocation);
+       if (newsk == NULL) {
+               release_sock(sk);
+               kfree_skb(skb);
+@@ -2090,9 +2085,6 @@
+ {
+       struct net_device *dev = (struct net_device *)ptr;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--      while (rc && pos) {
--              rc = established_get_next(seq, rc);
--              --pos;
--      }
--      return rc;
--}
+       switch(event) {
+               case NETDEV_UP:
+                       dn_dev_up(dev);
+@@ -2407,7 +2399,7 @@
+       dev_add_pack(&dn_dix_packet_type);
+       register_netdevice_notifier(&dn_dev_notifier);
+-      proc_net_fops_create(&init_net, "decnet", S_IRUGO, &dn_socket_seq_fops);
++      proc_net_fops_create("decnet", S_IRUGO, &dn_socket_seq_fops);
+       dn_register_sysctl();
+ out:
+       return rc;
+@@ -2436,7 +2428,7 @@
+       dn_neigh_cleanup();
+       dn_fib_cleanup();
+-      proc_net_remove(&init_net, "decnet");
++      proc_net_remove("decnet");
+       proto_unregister(&dn_proto);
+ }
+diff -Nurb linux-2.6.22-590/net/decnet/dn_dev.c linux-2.6.22-570/net/decnet/dn_dev.c
+--- linux-2.6.22-590/net/decnet/dn_dev.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/decnet/dn_dev.c       2008-01-23 19:15:56.000000000 -0500
+@@ -47,7 +47,6 @@
+ #include <net/flow.h>
+ #include <net/fib_rules.h>
+ #include <net/netlink.h>
+-#include <net/net_namespace.h>
+ #include <net/dn.h>
+ #include <net/dn_dev.h>
+ #include <net/dn_route.h>
+@@ -514,7 +513,7 @@
+       ifr->ifr_name[IFNAMSIZ-1] = 0;
+ #ifdef CONFIG_KMOD
+-      dev_load(&init_net, ifr->ifr_name);
++      dev_load(ifr->ifr_name);
+ #endif
+       switch(cmd) {
+@@ -532,7 +531,7 @@
+       rtnl_lock();
+-      if ((dev = __dev_get_by_name(&init_net, ifr->ifr_name)) == NULL) {
++      if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL) {
+               ret = -ENODEV;
+               goto done;
+       }
+@@ -630,7 +629,7 @@
+ {
+       struct net_device *dev;
+       struct dn_dev *dn_dev = NULL;
+-      dev = dev_get_by_index(&init_net, ifindex);
++      dev = dev_get_by_index(ifindex);
+       if (dev) {
+               dn_dev = dev->dn_ptr;
+               dev_put(dev);
+@@ -648,16 +647,12 @@
+ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct nlattr *tb[IFA_MAX+1];
+       struct dn_dev *dn_db;
+       struct ifaddrmsg *ifm;
+       struct dn_ifaddr *ifa, **ifap;
+       int err = -EADDRNOTAVAIL;
+-      if (net != &init_net)
+-              goto errout;
 -
--static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
--{
--      void *rc;
--      struct tcp_iter_state* st = seq->private;
+       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy);
+       if (err < 0)
+               goto errout;
+@@ -684,7 +679,6 @@
+ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct nlattr *tb[IFA_MAX+1];
+       struct net_device *dev;
+       struct dn_dev *dn_db;
+@@ -692,9 +686,6 @@
+       struct dn_ifaddr *ifa;
+       int err;
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--      inet_listen_lock(&tcp_hashinfo);
--      st->state = TCP_SEQ_STATE_LISTENING;
--      rc        = listening_get_idx(seq, &pos);
+       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy);
+       if (err < 0)
+               return err;
+@@ -703,7 +694,7 @@
+               return -EINVAL;
+       ifm = nlmsg_data(nlh);
+-      if ((dev = __dev_get_by_index(&init_net, ifm->ifa_index)) == NULL)
++      if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL)
+               return -ENODEV;
+       if ((dn_db = dev->dn_ptr) == NULL) {
+@@ -792,28 +783,24 @@
+               kfree_skb(skb);
+               goto errout;
+       }
+-      err = rtnl_notify(skb, &init_net, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
++      err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
+ errout:
+       if (err < 0)
+-              rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_IFADDR, err);
++              rtnl_set_sk_err(RTNLGRP_DECnet_IFADDR, err);
+ }
+ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       int idx, dn_idx = 0, skip_ndevs, skip_naddr;
+       struct net_device *dev;
+       struct dn_dev *dn_db;
+       struct dn_ifaddr *ifa;
+-      if (net != &init_net)
+-              return 0;
 -
--      if (!rc) {
--              inet_listen_unlock(&tcp_hashinfo);
--              local_bh_disable();
--              st->state = TCP_SEQ_STATE_ESTABLISHED;
--              rc        = established_get_idx(seq, pos);
--      }
+       skip_ndevs = cb->args[0];
+       skip_naddr = cb->args[1];
+       idx = 0;
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if (idx < skip_ndevs)
+                       goto cont;
+               else if (idx > skip_ndevs) {
+@@ -882,10 +869,10 @@
+               rv = dn_dev_get_first(dev, addr);
+               read_unlock(&dev_base_lock);
+               dev_put(dev);
+-              if (rv == 0 || dev == &init_net.loopback_dev)
++              if (rv == 0 || dev == &loopback_dev)
+                       return rv;
+       }
+-      dev = &init_net.loopback_dev;
++      dev = &loopback_dev;
+       dev_hold(dev);
+       goto last_chance;
+ }
+@@ -1312,7 +1299,7 @@
+       struct net_device *dev;
+       rtnl_lock();
+-      for_each_netdev(&init_net, dev)
++      for_each_netdev(dev)
+               dn_dev_down(dev);
+       rtnl_unlock();
+@@ -1323,7 +1310,7 @@
+       struct net_device *dev;
+       rtnl_lock();
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if (dev->flags & IFF_UP)
+                       dn_dev_up(dev);
+       }
+@@ -1357,7 +1344,7 @@
+               return SEQ_START_TOKEN;
+       i = 1;
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if (!is_dn_dev(dev))
+                       continue;
+@@ -1376,9 +1363,9 @@
+       dev = (struct net_device *)v;
+       if (v == SEQ_START_TOKEN)
+-              dev = net_device_entry(&init_net.dev_base_head);
++              dev = net_device_entry(&dev_base_head);
+-      for_each_netdev_continue(&init_net, dev) {
++      for_each_netdev_continue(dev) {
+               if (!is_dn_dev(dev))
+                       continue;
+@@ -1478,7 +1465,7 @@
+       rtnl_register(PF_DECnet, RTM_DELADDR, dn_nl_deladdr, NULL);
+       rtnl_register(PF_DECnet, RTM_GETADDR, NULL, dn_nl_dump_ifaddr);
+-      proc_net_fops_create(&init_net, "decnet_dev", S_IRUGO, &dn_dev_seq_fops);
++      proc_net_fops_create("decnet_dev", S_IRUGO, &dn_dev_seq_fops);
+ #ifdef CONFIG_SYSCTL
+       {
+@@ -1499,7 +1486,7 @@
+       }
+ #endif /* CONFIG_SYSCTL */
+-      proc_net_remove(&init_net, "decnet_dev");
++      proc_net_remove("decnet_dev");
+       dn_dev_devices_off();
+ }
+diff -Nurb linux-2.6.22-590/net/decnet/dn_fib.c linux-2.6.22-570/net/decnet/dn_fib.c
+--- linux-2.6.22-590/net/decnet/dn_fib.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/decnet/dn_fib.c       2007-07-08 19:32:17.000000000 -0400
+@@ -203,6 +203,8 @@
+               struct flowi fl;
+               struct dn_fib_res res;
++              memset(&fl, 0, sizeof(fl));
++
+               if (nh->nh_flags&RTNH_F_ONLINK) {
+                       struct net_device *dev;
+@@ -210,7 +212,7 @@
+                               return -EINVAL;
+                       if (dnet_addr_type(nh->nh_gw) != RTN_UNICAST)
+                               return -EINVAL;
+-                      if ((dev = __dev_get_by_index(&init_net, nh->nh_oif)) == NULL)
++                      if ((dev = __dev_get_by_index(nh->nh_oif)) == NULL)
+                               return -ENODEV;
+                       if (!(dev->flags&IFF_UP))
+                               return -ENETDOWN;
+@@ -221,7 +223,6 @@
+               }
+               memset(&fl, 0, sizeof(fl));
+-              fl.fl_net = &init_net;
+               fl.fld_dst = nh->nh_gw;
+               fl.oif = nh->nh_oif;
+               fl.fld_scope = r->rtm_scope + 1;
+@@ -254,7 +255,7 @@
+               if (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK))
+                       return -EINVAL;
+-              dev = __dev_get_by_index(&init_net, nh->nh_oif);
++              dev = __dev_get_by_index(nh->nh_oif);
+               if (dev == NULL || dev->dn_ptr == NULL)
+                       return -ENODEV;
+               if (!(dev->flags&IFF_UP))
+@@ -354,7 +355,7 @@
+               if (nhs != 1 || nh->nh_gw)
+                       goto err_inval;
+               nh->nh_scope = RT_SCOPE_NOWHERE;
+-              nh->nh_dev = dev_get_by_index(&init_net, fi->fib_nh->nh_oif);
++              nh->nh_dev = dev_get_by_index(fi->fib_nh->nh_oif);
+               err = -ENODEV;
+               if (nh->nh_dev == NULL)
+                       goto failure;
+@@ -505,14 +506,10 @@
+ static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct dn_fib_table *tb;
+       struct rtattr **rta = arg;
+       struct rtmsg *r = NLMSG_DATA(nlh);
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--      return rc;
--}
+       if (dn_fib_check_attr(r, rta))
+               return -EINVAL;
+@@ -525,14 +522,10 @@
+ static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct dn_fib_table *tb;
+       struct rtattr **rta = arg;
+       struct rtmsg *r = NLMSG_DATA(nlh);
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--static void *tcp_seq_start(struct seq_file *seq, loff_t *pos)
+       if (dn_fib_check_attr(r, rta))
+               return -EINVAL;
+@@ -609,7 +602,7 @@
+       /* Scan device list */
+       read_lock(&dev_base_lock);
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               dn_db = dev->dn_ptr;
+               if (dn_db == NULL)
+                       continue;
+diff -Nurb linux-2.6.22-590/net/decnet/dn_neigh.c linux-2.6.22-570/net/decnet/dn_neigh.c
+--- linux-2.6.22-590/net/decnet/dn_neigh.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/decnet/dn_neigh.c     2007-07-08 19:32:17.000000000 -0400
+@@ -38,7 +38,6 @@
+ #include <linux/rcupdate.h>
+ #include <linux/jhash.h>
+ #include <asm/atomic.h>
+-#include <net/net_namespace.h>
+ #include <net/neighbour.h>
+ #include <net/dst.h>
+ #include <net/flow.h>
+@@ -592,7 +591,6 @@
+       seq          = file->private_data;
+       seq->private = s;
+-      s->net = get_net(PROC_NET(inode));
+ out:
+       return rc;
+ out_kfree:
+@@ -600,20 +598,12 @@
+       goto out;
+ }
+-static int dn_neigh_seq_release(struct inode *inode, struct file *file)
 -{
--      struct tcp_iter_state* st = seq->private;
--      st->state = TCP_SEQ_STATE_LISTENING;
--      st->num = 0;
--      return *pos ? tcp_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+-      struct seq_file *seq = file->private_data;
+-      struct neigh_seq_state *state = seq->private;
+-      put_net(state->net);
+-      return seq_release_private(inode, file);
 -}
 -
--static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
--{
--      void *rc = NULL;
--      struct tcp_iter_state* st;
+ static const struct file_operations dn_neigh_seq_fops = {
+       .owner          = THIS_MODULE,
+       .open           = dn_neigh_seq_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+-      .release        = dn_neigh_seq_release,
++      .release        = seq_release_private,
+ };
+ #endif
+@@ -621,11 +611,11 @@
+ void __init dn_neigh_init(void)
+ {
+       neigh_table_init(&dn_neigh_table);
+-      proc_net_fops_create(&init_net, "decnet_neigh", S_IRUGO, &dn_neigh_seq_fops);
++      proc_net_fops_create("decnet_neigh", S_IRUGO, &dn_neigh_seq_fops);
+ }
+ void __exit dn_neigh_cleanup(void)
+ {
+-      proc_net_remove(&init_net, "decnet_neigh");
++      proc_net_remove("decnet_neigh");
+       neigh_table_clear(&dn_neigh_table);
+ }
+diff -Nurb linux-2.6.22-590/net/decnet/dn_nsp_out.c linux-2.6.22-570/net/decnet/dn_nsp_out.c
+--- linux-2.6.22-590/net/decnet/dn_nsp_out.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/decnet/dn_nsp_out.c   2007-07-08 19:32:17.000000000 -0400
+@@ -91,7 +91,6 @@
+       }
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       fl.oif = sk->sk_bound_dev_if;
+       fl.fld_src = dn_saddr2dn(&scp->addr);
+       fl.fld_dst = dn_saddr2dn(&scp->peer);
+diff -Nurb linux-2.6.22-590/net/decnet/dn_route.c linux-2.6.22-570/net/decnet/dn_route.c
+--- linux-2.6.22-590/net/decnet/dn_route.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/decnet/dn_route.c     2007-07-08 19:32:17.000000000 -0400
+@@ -82,7 +82,6 @@
+ #include <net/dst.h>
+ #include <net/flow.h>
+ #include <net/fib_rules.h>
+-#include <net/net_namespace.h>
+ #include <net/dn.h>
+ #include <net/dn_dev.h>
+ #include <net/dn_nsp.h>
+@@ -584,9 +583,6 @@
+       struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr;
+       unsigned char padlen = 0;
+-      if (dev->nd_net != &init_net)
+-              goto dump_it;
 -
--      if (v == SEQ_START_TOKEN) {
--              rc = tcp_get_idx(seq, 0);
--              goto out;
--      }
--      st = seq->private;
+       if (dn == NULL)
+               goto dump_it;
+@@ -881,14 +877,13 @@
+ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *oldflp, int try_hard)
+ {
+-      struct flowi fl = { .fl_net = &init_net,
+-                          .nl_u = { .dn_u =
++      struct flowi fl = { .nl_u = { .dn_u =
+                                     { .daddr = oldflp->fld_dst,
+                                       .saddr = oldflp->fld_src,
+                                       .scope = RT_SCOPE_UNIVERSE,
+                                    } },
+                           .mark = oldflp->mark,
+-                          .iif = init_net.loopback_dev.ifindex,
++                          .iif = loopback_dev.ifindex,
+                           .oif = oldflp->oif };
+       struct dn_route *rt = NULL;
+       struct net_device *dev_out = NULL, *dev;
+@@ -905,11 +900,11 @@
+                      "dn_route_output_slow: dst=%04x src=%04x mark=%d"
+                      " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst),
+                      dn_ntohs(oldflp->fld_src),
+-                     oldflp->mark, init_net.loopback_dev.ifindex, oldflp->oif);
++                     oldflp->mark, loopback_dev.ifindex, oldflp->oif);
+       /* If we have an output interface, verify its a DECnet device */
+       if (oldflp->oif) {
+-              dev_out = dev_get_by_index(&init_net, oldflp->oif);
++              dev_out = dev_get_by_index(oldflp->oif);
+               err = -ENODEV;
+               if (dev_out && dev_out->dn_ptr == NULL) {
+                       dev_put(dev_out);
+@@ -930,7 +925,7 @@
+                       goto out;
+               }
+               read_lock(&dev_base_lock);
+-              for_each_netdev(&init_net, dev) {
++              for_each_netdev(dev) {
+                       if (!dev->dn_ptr)
+                               continue;
+                       if (!dn_dev_islocal(dev, oldflp->fld_src))
+@@ -958,7 +953,7 @@
+               err = -EADDRNOTAVAIL;
+               if (dev_out)
+                       dev_put(dev_out);
+-              dev_out = &init_net.loopback_dev;
++              dev_out = &loopback_dev;
+               dev_hold(dev_out);
+               if (!fl.fld_dst) {
+                       fl.fld_dst =
+@@ -967,7 +962,7 @@
+                       if (!fl.fld_dst)
+                               goto out;
+               }
+-              fl.oif = init_net.loopback_dev.ifindex;
++              fl.oif = loopback_dev.ifindex;
+               res.type = RTN_LOCAL;
+               goto make_route;
+       }
+@@ -1000,7 +995,7 @@
+                * here
+                */
+               if (!try_hard) {
+-                      neigh = neigh_lookup_nodev(&dn_neigh_table, &init_net, &fl.fld_dst);
++                      neigh = neigh_lookup_nodev(&dn_neigh_table, &fl.fld_dst);
+                       if (neigh) {
+                               if ((oldflp->oif &&
+                                   (neigh->dev->ifindex != oldflp->oif)) ||
+@@ -1013,7 +1008,7 @@
+                                       if (dev_out)
+                                               dev_put(dev_out);
+                                       if (dn_dev_islocal(neigh->dev, fl.fld_dst)) {
+-                                              dev_out = &init_net.loopback_dev;
++                                              dev_out = &loopback_dev;
+                                               res.type = RTN_LOCAL;
+                                       } else {
+                                               dev_out = neigh->dev;
+@@ -1034,7 +1029,7 @@
+               /* Possible improvement - check all devices for local addr */
+               if (dn_dev_islocal(dev_out, fl.fld_dst)) {
+                       dev_put(dev_out);
+-                      dev_out = &init_net.loopback_dev;
++                      dev_out = &loopback_dev;
+                       dev_hold(dev_out);
+                       res.type = RTN_LOCAL;
+                       goto select_source;
+@@ -1070,7 +1065,7 @@
+                       fl.fld_src = fl.fld_dst;
+               if (dev_out)
+                       dev_put(dev_out);
+-              dev_out = &init_net.loopback_dev;
++              dev_out = &loopback_dev;
+               dev_hold(dev_out);
+               fl.oif = dev_out->ifindex;
+               if (res.fi)
+@@ -1108,7 +1103,6 @@
+       atomic_set(&rt->u.dst.__refcnt, 1);
+       rt->u.dst.flags   = DST_HOST;
+-      rt->fl.fl_net     = &init_net;
+       rt->fl.fld_src    = oldflp->fld_src;
+       rt->fl.fld_dst    = oldflp->fld_dst;
+       rt->fl.oif        = oldflp->oif;
+@@ -1232,8 +1226,7 @@
+       int flags = 0;
+       __le16 gateway = 0;
+       __le16 local_src = 0;
+-      struct flowi fl = { .fl_net = &init_net,
+-                          .nl_u = { .dn_u = 
++      struct flowi fl = { .nl_u = { .dn_u =
+                                    { .daddr = cb->dst,
+                                      .saddr = cb->src,
+                                      .scope = RT_SCOPE_UNIVERSE,
+@@ -1381,7 +1374,6 @@
+       rt->rt_dst_map    = fl.fld_dst;
+       rt->rt_src_map    = fl.fld_src;
+-      rt->fl.fl_net     = &init_net;
+       rt->fl.fld_src    = cb->src;
+       rt->fl.fld_dst    = cb->dst;
+       rt->fl.oif        = 0;
+@@ -1534,7 +1526,6 @@
+  */
+ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
+ {
+-      struct net *net = in_skb->sk->sk_net;
+       struct rtattr **rta = arg;
+       struct rtmsg *rtm = NLMSG_DATA(nlh);
+       struct dn_route *rt = NULL;
+@@ -1543,11 +1534,7 @@
+       struct sk_buff *skb;
+       struct flowi fl;
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--      switch (st->state) {
--      case TCP_SEQ_STATE_OPENREQ:
--      case TCP_SEQ_STATE_LISTENING:
--              rc = listening_get_next(seq, v);
--              if (!rc) {
--                      inet_listen_unlock(&tcp_hashinfo);
--                      local_bh_disable();
--                      st->state = TCP_SEQ_STATE_ESTABLISHED;
--                      rc        = established_get_first(seq);
--              }
--              break;
--      case TCP_SEQ_STATE_ESTABLISHED:
--      case TCP_SEQ_STATE_TIME_WAIT:
--              rc = established_get_next(seq, v);
--              break;
--      }
--out:
--      ++*pos;
--      return rc;
--}
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       fl.proto = DNPROTO_NSP;
+       skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+@@ -1565,7 +1552,7 @@
+       if (fl.iif) {
+               struct net_device *dev;
+-              if ((dev = dev_get_by_index(&init_net, fl.iif)) == NULL) {
++              if ((dev = dev_get_by_index(fl.iif)) == NULL) {
+                       kfree_skb(skb);
+                       return -ENODEV;
+               }
+@@ -1611,7 +1598,7 @@
+               goto out_free;
+       }
+-      return rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
++      return rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
+ out_free:
+       kfree_skb(skb);
+@@ -1624,14 +1611,10 @@
+  */
+ int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct dn_route *rt;
+       int h, s_h;
+       int idx, s_idx;
+-      if (net != &init_net)
+-              return 0;
 -
--static void tcp_seq_stop(struct seq_file *seq, void *v)
--{
--      struct tcp_iter_state* st = seq->private;
+       if (NLMSG_PAYLOAD(cb->nlh, 0) < sizeof(struct rtmsg))
+               return -EINVAL;
+       if (!(((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED))
+@@ -1831,7 +1814,7 @@
+       dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
+-      proc_net_fops_create(&init_net, "decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops);
++      proc_net_fops_create("decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops);
+ #ifdef CONFIG_DECNET_ROUTER
+       rtnl_register(PF_DECnet, RTM_GETROUTE, dn_cache_getroute, dn_fib_dump);
+@@ -1846,6 +1829,6 @@
+       del_timer(&dn_route_timer);
+       dn_run_flush(0);
+-      proc_net_remove(&init_net, "decnet_cache");
++      proc_net_remove("decnet_cache");
+ }
+diff -Nurb linux-2.6.22-590/net/decnet/dn_rules.c linux-2.6.22-570/net/decnet/dn_rules.c
+--- linux-2.6.22-590/net/decnet/dn_rules.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/decnet/dn_rules.c     2007-07-08 19:32:17.000000000 -0400
+@@ -186,10 +186,7 @@
+ unsigned dnet_addr_type(__le16 addr)
+ {
+-      struct flowi fl = { 
+-              .fl_net = &init_net,
+-              .nl_u = { .dn_u = { .daddr = addr } } 
+-      };
++      struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } };
+       struct dn_fib_res res;
+       unsigned ret = RTN_UNICAST;
+       struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0);
+@@ -226,7 +223,7 @@
+       return -ENOBUFS;
+ }
+-static u32 dn_fib_rule_default_pref(struct fib_rules_ops *ops)
++static u32 dn_fib_rule_default_pref(void)
+ {
+       struct list_head *pos;
+       struct fib_rule *rule;
+@@ -243,7 +240,7 @@
+       return 0;
+ }
+-static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops)
++static void dn_fib_rule_flush_cache(void)
+ {
+       dn_rt_cache_flush(-1);
+ }
+@@ -268,12 +265,12 @@
+ void __init dn_fib_rules_init(void)
+ {
+       list_add_tail(&default_rule.common.list, &dn_fib_rules);
+-      fib_rules_register(&init_net, &dn_fib_rules_ops);
++      fib_rules_register(&dn_fib_rules_ops);
+ }
+ void __exit dn_fib_rules_cleanup(void)
+ {
+-      fib_rules_unregister(&init_net, &dn_fib_rules_ops);
++      fib_rules_unregister(&dn_fib_rules_ops);
+ }
+diff -Nurb linux-2.6.22-590/net/decnet/dn_table.c linux-2.6.22-570/net/decnet/dn_table.c
+--- linux-2.6.22-590/net/decnet/dn_table.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/decnet/dn_table.c     2007-07-08 19:32:17.000000000 -0400
+@@ -375,10 +375,10 @@
+               kfree_skb(skb);
+               goto errout;
+       }
+-      err = rtnl_notify(skb, &init_net, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
++      err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
+ errout:
+       if (err < 0)
+-              rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_ROUTE, err);
++              rtnl_set_sk_err(RTNLGRP_DECnet_ROUTE, err);
+ }
+ static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb,
+@@ -463,16 +463,12 @@
+ int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       unsigned int h, s_h;
+       unsigned int e = 0, s_e;
+       struct dn_fib_table *tb;
+       struct hlist_node *node;
+       int dumped = 0;
+-      if (net != &init_net)
+-              return 0;
 -
--      switch (st->state) {
--      case TCP_SEQ_STATE_OPENREQ:
--              if (v) {
--                      struct inet_connection_sock *icsk = inet_csk(st->syn_wait_sk);
--                      read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
--              }
--      case TCP_SEQ_STATE_LISTENING:
--              if (v != SEQ_START_TOKEN)
--                      inet_listen_unlock(&tcp_hashinfo);
--              break;
--      case TCP_SEQ_STATE_TIME_WAIT:
--      case TCP_SEQ_STATE_ESTABLISHED:
--              if (v)
--                      read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
--              local_bh_enable();
--              break;
--      }
--}
+       if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
+               ((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
+                       return dn_cache_dump(skb, cb);
+diff -Nurb linux-2.6.22-590/net/decnet/netfilter/dn_rtmsg.c linux-2.6.22-570/net/decnet/netfilter/dn_rtmsg.c
+--- linux-2.6.22-590/net/decnet/netfilter/dn_rtmsg.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/decnet/netfilter/dn_rtmsg.c   2007-07-08 19:32:17.000000000 -0400
+@@ -93,10 +93,6 @@
+                       const struct net_device *out,
+                       int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--static int tcp_seq_open(struct inode *inode, struct file *file)
--{
--      struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
--      struct seq_file *seq;
--      struct tcp_iter_state *s;
--      int rc;
+       dnrmg_send_peer(*pskb);
+       return NF_ACCEPT;
+ }
+@@ -141,8 +137,7 @@
+ {
+       int rv = 0;
+-      dnrmg = netlink_kernel_create(&init_net,
+-                                    NETLINK_DNRTMSG, DNRNG_NLGRP_MAX,
++      dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, DNRNG_NLGRP_MAX,
+                                     dnrmg_receive_user_sk, NULL, THIS_MODULE);
+       if (dnrmg == NULL) {
+               printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket");
+diff -Nurb linux-2.6.22-590/net/decnet/sysctl_net_decnet.c linux-2.6.22-570/net/decnet/sysctl_net_decnet.c
+--- linux-2.6.22-590/net/decnet/sysctl_net_decnet.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/decnet/sysctl_net_decnet.c    2007-07-08 19:32:17.000000000 -0400
+@@ -259,7 +259,7 @@
+               devname[newlen] = 0;
+-              dev = dev_get_by_name(&init_net, devname);
++              dev = dev_get_by_name(devname);
+               if (dev == NULL)
+                       return -ENODEV;
+@@ -299,7 +299,7 @@
+               devname[*lenp] = 0;
+               strip_it(devname);
+-              dev = dev_get_by_name(&init_net, devname);
++              dev = dev_get_by_name(devname);
+               if (dev == NULL)
+                       return -ENODEV;
+diff -Nurb linux-2.6.22-590/net/econet/af_econet.c linux-2.6.22-570/net/econet/af_econet.c
+--- linux-2.6.22-590/net/econet/af_econet.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/econet/af_econet.c    2007-07-08 19:32:17.000000000 -0400
+@@ -608,15 +608,12 @@
+  *    Create an Econet socket
+  */
+-static int econet_create(struct net *net, struct socket *sock, int protocol)
++static int econet_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
+       struct econet_sock *eo;
+       int err;
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
 -
--      if (unlikely(afinfo == NULL))
--              return -EINVAL;
+       /* Econet only provides datagram services. */
+       if (sock->type != SOCK_DGRAM)
+               return -ESOCKTNOSUPPORT;
+@@ -624,7 +621,7 @@
+       sock->state = SS_UNCONNECTED;
+       err = -ENOBUFS;
+-      sk = sk_alloc(net, PF_ECONET, GFP_KERNEL, &econet_proto, 1);
++      sk = sk_alloc(PF_ECONET, GFP_KERNEL, &econet_proto, 1);
+       if (sk == NULL)
+               goto out;
+@@ -662,7 +659,7 @@
+       if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
+               return -EFAULT;
+-      if ((dev = dev_get_by_name(&init_net, ifr.ifr_name)) == NULL)
++      if ((dev = dev_get_by_name(ifr.ifr_name)) == NULL)
+               return -ENODEV;
+       sec = (struct sockaddr_ec *)&ifr.ifr_addr;
+@@ -1065,9 +1062,6 @@
+       struct sock *sk;
+       struct ec_device *edev = dev->ec_ptr;
+-      if (dev->nd_net != &init_net)
+-              goto drop;
 -
--      s = kzalloc(sizeof(*s), GFP_KERNEL);
--      if (!s)
--              return -ENOMEM;
--      s->family               = afinfo->family;
--      s->seq_ops.start        = tcp_seq_start;
--      s->seq_ops.next         = tcp_seq_next;
--      s->seq_ops.show         = afinfo->seq_show;
--      s->seq_ops.stop         = tcp_seq_stop;
+       if (skb->pkt_type == PACKET_OTHERHOST)
+               goto drop;
+@@ -1122,9 +1116,6 @@
+       struct net_device *dev = (struct net_device *)data;
+       struct ec_device *edev;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--      rc = seq_open(file, &s->seq_ops);
--      if (rc)
--              goto out_kfree;
--      seq          = file->private_data;
--      seq->private = s;
--out:
--      return rc;
--out_kfree:
--      kfree(s);
--      goto out;
--}
+       switch (msg) {
+       case NETDEV_UNREGISTER:
+               /* A device has gone down - kill any data we hold for it. */
+diff -Nurb linux-2.6.22-590/net/ieee80211/ieee80211_module.c linux-2.6.22-570/net/ieee80211/ieee80211_module.c
+--- linux-2.6.22-590/net/ieee80211/ieee80211_module.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ieee80211/ieee80211_module.c  2007-07-08 19:32:17.000000000 -0400
+@@ -264,7 +264,7 @@
+       struct proc_dir_entry *e;
+       ieee80211_debug_level = debug;
+-      ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
++      ieee80211_proc = proc_mkdir(DRV_NAME, proc_net);
+       if (ieee80211_proc == NULL) {
+               IEEE80211_ERROR("Unable to create " DRV_NAME
+                               " proc directory\n");
+@@ -273,7 +273,7 @@
+       e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
+                             ieee80211_proc);
+       if (!e) {
+-              remove_proc_entry(DRV_NAME, init_net.proc_net);
++              remove_proc_entry(DRV_NAME, proc_net);
+               ieee80211_proc = NULL;
+               return -EIO;
+       }
+@@ -293,7 +293,7 @@
+ #ifdef CONFIG_IEEE80211_DEBUG
+       if (ieee80211_proc) {
+               remove_proc_entry("debug_level", ieee80211_proc);
+-              remove_proc_entry(DRV_NAME, init_net.proc_net);
++              remove_proc_entry(DRV_NAME, proc_net);
+               ieee80211_proc = NULL;
+       }
+ #endif                                /* CONFIG_IEEE80211_DEBUG */
+diff -Nurb linux-2.6.22-590/net/ipv4/Kconfig linux-2.6.22-570/net/ipv4/Kconfig
+--- linux-2.6.22-590/net/ipv4/Kconfig  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/Kconfig  2008-01-23 19:16:09.000000000 -0500
+@@ -116,6 +116,48 @@
+         equal "cost" and chooses one of them in a non-deterministic fashion
+         if a matching packet arrives.
++config IP_ROUTE_MULTIPATH_CACHED
++      bool "IP: equal cost multipath with caching support (EXPERIMENTAL)"
++      depends on IP_ROUTE_MULTIPATH
++      help
++        Normally, equal cost multipath routing is not supported by the
++        routing cache. If you say Y here, alternative routes are cached
++        and on cache lookup a route is chosen in a configurable fashion.
++
++        If unsure, say N.
++
++config IP_ROUTE_MULTIPATH_RR
++      tristate "MULTIPATH: round robin algorithm"
++      depends on IP_ROUTE_MULTIPATH_CACHED
++      help
++        Multipath routes are chosen according to Round Robin
++
++config IP_ROUTE_MULTIPATH_RANDOM
++      tristate "MULTIPATH: random algorithm"
++      depends on IP_ROUTE_MULTIPATH_CACHED
++      help
++        Multipath routes are chosen in a random fashion. Actually,
++        there is no weight for a route. The advantage of this policy
++        is that it is implemented stateless and therefore introduces only
++        a very small delay.
++
++config IP_ROUTE_MULTIPATH_WRANDOM
++      tristate "MULTIPATH: weighted random algorithm"
++      depends on IP_ROUTE_MULTIPATH_CACHED
++      help
++        Multipath routes are chosen in a weighted random fashion. 
++        The per route weights are the weights visible via ip route 2. As the
++        corresponding state management introduces some overhead routing delay
++        is increased.
++
++config IP_ROUTE_MULTIPATH_DRR
++      tristate "MULTIPATH: interface round robin algorithm"
++      depends on IP_ROUTE_MULTIPATH_CACHED
++      help
++        Connections are distributed in a round robin fashion over the
++        available interfaces. This policy makes sense if the connections 
++        should be primarily distributed on interfaces and not on routes. 
++
+ config IP_ROUTE_VERBOSE
+       bool "IP: verbose route monitoring"
+       depends on IP_ADVANCED_ROUTER
+diff -Nurb linux-2.6.22-590/net/ipv4/Makefile linux-2.6.22-570/net/ipv4/Makefile
+--- linux-2.6.22-590/net/ipv4/Makefile 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/Makefile 2007-07-08 19:32:17.000000000 -0400
+@@ -29,9 +29,14 @@
+ obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
+ obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
+ obj-$(CONFIG_IP_PNP) += ipconfig.o
++obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
++obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
++obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o
++obj-$(CONFIG_IP_ROUTE_MULTIPATH_DRR) += multipath_drr.o
+ obj-$(CONFIG_NETFILTER)       += netfilter.o netfilter/
+ obj-$(CONFIG_IP_VS) += ipvs/
+ obj-$(CONFIG_INET_DIAG) += inet_diag.o 
++obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
+ obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
+ obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
+ obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
+diff -Nurb linux-2.6.22-590/net/ipv4/af_inet.c linux-2.6.22-570/net/ipv4/af_inet.c
+--- linux-2.6.22-590/net/ipv4/af_inet.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/af_inet.c        2008-01-23 19:16:10.000000000 -0500
+@@ -244,7 +244,7 @@
+  *    Create an inet socket.
+  */
+-static int inet_create(struct net *net, struct socket *sock, int protocol)
++static int inet_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
+       struct list_head *p;
+@@ -310,10 +310,6 @@
+                       goto out_rcu_unlock;
+       }
+-      err = -EPROTONOSUPPORT;
+-      if (!(answer->flags & INET_PROTOSW_NETNS) && (net != &init_net))
+-              goto out_rcu_unlock;
 -
--int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
--{
--      int rc = 0;
--      struct proc_dir_entry *p;
+       err = -EPERM;
+       if ((protocol == IPPROTO_ICMP) &&
+               nx_capable(answer->capability, NXC_RAW_ICMP))
+@@ -330,7 +326,7 @@
+       BUG_TRAP(answer_prot->slab != NULL);
+       err = -ENOBUFS;
+-      sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot, 1);
++      sk = sk_alloc(PF_INET, GFP_KERNEL, answer_prot, 1);
+       if (sk == NULL)
+               goto out;
+@@ -348,7 +344,7 @@
+                       inet->hdrincl = 1;
+       }
+-      if (net->sysctl_ipv4_no_pmtu_disc)
++      if (ipv4_config.no_pmtu_disc)
+               inet->pmtudisc = IP_PMTUDISC_DONT;
+       else
+               inet->pmtudisc = IP_PMTUDISC_WANT;
+@@ -427,12 +423,12 @@
+ }
+ /* It is off by default, see below. */
++int sysctl_ip_nonlocal_bind __read_mostly;
+ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ {
+       struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
+       struct sock *sk = sock->sk;
+-      struct net *net = sk->sk_net;
+       struct inet_sock *inet = inet_sk(sk);
+       struct nx_v4_sock_addr nsa;
+       unsigned short snum;
+@@ -452,7 +448,7 @@
+       if (err)
+               goto out;
+-      chk_addr_ret = inet_addr_type(net, nsa.saddr);
++      chk_addr_ret = inet_addr_type(nsa.saddr);
+       /* Not specified by any standard per-se, however it breaks too
+        * many applications when removed.  It is unfortunate since
+@@ -462,7 +458,7 @@
+        *  is temporarily down)
+        */
+       err = -EADDRNOTAVAIL;
+-      if (!net->sysctl_ip_nonlocal_bind &&
++      if (!sysctl_ip_nonlocal_bind &&
+           !inet->freebind &&
+           nsa.saddr != INADDR_ANY &&
+           chk_addr_ret != RTN_LOCAL &&
+@@ -791,7 +787,6 @@
+ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ {
+       struct sock *sk = sock->sk;
+-      struct net *net = sk->sk_net;
+       int err = 0;
+       switch (cmd) {
+@@ -804,12 +799,12 @@
+               case SIOCADDRT:
+               case SIOCDELRT:
+               case SIOCRTMSG:
+-                      err = ip_rt_ioctl(net, cmd, (void __user *)arg);
++                      err = ip_rt_ioctl(cmd, (void __user *)arg);
+                       break;
+               case SIOCDARP:
+               case SIOCGARP:
+               case SIOCSARP:
+-                      err = arp_ioctl(net, cmd, (void __user *)arg);
++                      err = arp_ioctl(cmd, (void __user *)arg);
+                       break;
+               case SIOCGIFADDR:
+               case SIOCSIFADDR:
+@@ -822,7 +817,7 @@
+               case SIOCSIFPFLAGS:
+               case SIOCGIFPFLAGS:
+               case SIOCSIFFLAGS:
+-                      err = devinet_ioctl(net, cmd, (void __user *)arg);
++                      err = devinet_ioctl(cmd, (void __user *)arg);
+                       break;
+               default:
+                       if (sk->sk_prot->ioctl)
+@@ -932,8 +927,7 @@
+               .capability = -1,
+               .no_check =   0,
+               .flags =      INET_PROTOSW_PERMANENT |
+-                            INET_PROTOSW_ICSK |
+-                            INET_PROTOSW_NETNS,
++                            INET_PROTOSW_ICSK,
+       },
+       {
+@@ -943,8 +937,7 @@
+               .ops =        &inet_dgram_ops,
+               .capability = -1,
+               .no_check =   UDP_CSUM_DEFAULT,
+-              .flags =      INET_PROTOSW_PERMANENT |
+-                            INET_PROTOSW_NETNS,
++              .flags =      INET_PROTOSW_PERMANENT,
+        },
+@@ -955,8 +948,7 @@
+              .ops =        &inet_sockraw_ops,
+              .capability = CAP_NET_RAW,
+              .no_check =   UDP_CSUM_DEFAULT,
+-             .flags =      INET_PROTOSW_REUSE |
+-                           INET_PROTOSW_NETNS,
++             .flags =      INET_PROTOSW_REUSE,
+        }
+ };
+@@ -1037,6 +1029,8 @@
+  *      Shall we try to damage output packets if routing dev changes?
+  */
++int sysctl_ip_dynaddr __read_mostly;
++
+ static int inet_sk_reselect_saddr(struct sock *sk)
+ {
+       struct inet_sock *inet = inet_sk(sk);
+@@ -1065,7 +1059,7 @@
+       if (new_saddr == old_saddr)
+               return 0;
+-      if (sk->sk_net->sysctl_ip_dynaddr > 1) {
++      if (sysctl_ip_dynaddr > 1) {
+               printk(KERN_INFO "%s(): shifting inet->"
+                                "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
+                      __FUNCTION__,
+@@ -1104,7 +1098,6 @@
+               daddr = inet->opt->faddr;
+ {
+       struct flowi fl = {
+-              .fl_net = sk->sk_net,
+               .oif = sk->sk_bound_dev_if,
+               .nl_u = {
+                       .ip4_u = {
+@@ -1134,7 +1127,7 @@
+                * Other protocols have to map its equivalent state to TCP_SYN_SENT.
+                * DCCP maps its DCCP_REQUESTING state to TCP_SYN_SENT. -acme
+                */
+-              if (!sk->sk_net->sysctl_ip_dynaddr ||
++              if (!sysctl_ip_dynaddr ||
+                   sk->sk_state != TCP_SYN_SENT ||
+                   (sk->sk_userlocks & SOCK_BINDADDR_LOCK) ||
+                   (err = inet_sk_reselect_saddr(sk)) != 0)
+@@ -1190,9 +1183,6 @@
+       int ihl;
+       int id;
+-      if (!(features & NETIF_F_V4_CSUM))
+-              features &= ~NETIF_F_SG;
 -
--      if (!afinfo)
--              return -EINVAL;
--      afinfo->seq_fops->owner         = afinfo->owner;
--      afinfo->seq_fops->open          = tcp_seq_open;
--      afinfo->seq_fops->read          = seq_read;
--      afinfo->seq_fops->llseek        = seq_lseek;
--      afinfo->seq_fops->release       = seq_release_private;
--
--      p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);
--      if (p)
--              p->data = afinfo;
--      else
--              rc = -ENOMEM;
--      return rc;
--}
+       if (unlikely(skb_shinfo(skb)->gso_type &
+                    ~(SKB_GSO_TCPV4 |
+                      SKB_GSO_UDP |
+@@ -1363,24 +1353,6 @@
+       .gso_segment = inet_gso_segment,
+ };
 -
--void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo)
+-static int inet_net_init(struct net *net)
 -{
--      if (!afinfo)
--              return;
--      proc_net_remove(afinfo->name);
--      memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
--}
--
--static void get_openreq4(struct sock *sk, struct request_sock *req,
--                       char *tmpbuf, int i, int uid)
--{
--      const struct inet_request_sock *ireq = inet_rsk(req);
--      int ttd = req->expires - jiffies;
--
--      sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
--              " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p",
--              i,
--              ireq->loc_addr,
--              ntohs(inet_sk(sk)->sport),
--              ireq->rmt_addr,
--              ntohs(ireq->rmt_port),
--              TCP_SYN_RECV,
--              0, 0, /* could print option size, but that is af dependent. */
--              1,    /* timers active (only the expire timer) */
--              jiffies_to_clock_t(ttd),
--              req->retrans,
--              uid,
--              0,  /* non standard timer */
--              0, /* open_requests have no inode */
--              atomic_read(&sk->sk_refcnt),
--              req);
--}
--
--static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i)
--{
--      int timer_active;
--      unsigned long timer_expires;
--      struct tcp_sock *tp = tcp_sk(sk);
--      const struct inet_connection_sock *icsk = inet_csk(sk);
--      struct inet_sock *inet = inet_sk(sk);
--      __be32 dest = inet->daddr;
--      __be32 src = inet->rcv_saddr;
--      __u16 destp = ntohs(inet->dport);
--      __u16 srcp = ntohs(inet->sport);
--
--      if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
--              timer_active    = 1;
--              timer_expires   = icsk->icsk_timeout;
--      } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
--              timer_active    = 4;
--              timer_expires   = icsk->icsk_timeout;
--      } else if (timer_pending(&sk->sk_timer)) {
--              timer_active    = 2;
--              timer_expires   = sk->sk_timer.expires;
--      } else {
--              timer_active    = 0;
--              timer_expires = jiffies;
--      }
--
--      sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
--                      "%08X %5d %8d %lu %d %p %u %u %u %u %d",
--              i, src, srcp, dest, destp, sk->sk_state,
--              tp->write_seq - tp->snd_una,
--              sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog :
--                                           (tp->rcv_nxt - tp->copied_seq),
--              timer_active,
--              jiffies_to_clock_t(timer_expires - jiffies),
--              icsk->icsk_retransmits,
--              sock_i_uid(sk),
--              icsk->icsk_probes_out,
--              sock_i_ino(sk),
--              atomic_read(&sk->sk_refcnt), sk,
--              icsk->icsk_rto,
--              icsk->icsk_ack.ato,
--              (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
--              tp->snd_cwnd,
--              tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);
--}
--
--static void get_timewait4_sock(struct inet_timewait_sock *tw,
--                             char *tmpbuf, int i)
--{
--      __be32 dest, src;
--      __u16 destp, srcp;
--      int ttd = tw->tw_ttd - jiffies;
--
--      if (ttd < 0)
--              ttd = 0;
--
--      dest  = tw->tw_daddr;
--      src   = tw->tw_rcv_saddr;
--      destp = ntohs(tw->tw_dport);
--      srcp  = ntohs(tw->tw_sport);
--
--      sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
--              " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p",
--              i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
--              3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
--              atomic_read(&tw->tw_refcnt), tw);
--}
--
--#define TMPSZ 150
--
--static int tcp4_seq_show(struct seq_file *seq, void *v)
--{
--      struct tcp_iter_state* st;
--      char tmpbuf[TMPSZ + 1];
--
--      if (v == SEQ_START_TOKEN) {
--              seq_printf(seq, "%-*s\n", TMPSZ - 1,
--                         "  sl  local_address rem_address   st tx_queue "
--                         "rx_queue tr tm->when retrnsmt   uid  timeout "
--                         "inode");
--              goto out;
--      }
--      st = seq->private;
+-      net->sysctl_ip_default_ttl = IPDEFTTL;
+-      net->sysctl_ip_dynaddr = 0;
 -
--      switch (st->state) {
--      case TCP_SEQ_STATE_LISTENING:
--      case TCP_SEQ_STATE_ESTABLISHED:
--              get_tcp4_sock(v, tmpbuf, st->num);
--              break;
--      case TCP_SEQ_STATE_OPENREQ:
--              get_openreq4(st->syn_wait_sk, v, tmpbuf, st->num, st->uid);
--              break;
--      case TCP_SEQ_STATE_TIME_WAIT:
--              get_timewait4_sock(v, tmpbuf, st->num);
--              break;
--      }
--      seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);
--out:
 -      return 0;
 -}
 -
--static struct file_operations tcp4_seq_fops;
--static struct tcp_seq_afinfo tcp4_seq_afinfo = {
--      .owner          = THIS_MODULE,
--      .name           = "tcp",
--      .family         = AF_INET,
--      .seq_show       = tcp4_seq_show,
--      .seq_fops       = &tcp4_seq_fops,
--};
--
--int __init tcp4_proc_init(void)
--{
--      return tcp_proc_register(&tcp4_seq_afinfo);
--}
--
--void tcp4_proc_exit(void)
+-static void inet_net_exit(struct net *net)
 -{
--      tcp_proc_unregister(&tcp4_seq_afinfo);
 -}
--#endif /* CONFIG_PROC_FS */
 -
--struct proto tcp_prot = {
--      .name                   = "TCP",
--      .owner                  = THIS_MODULE,
--      .close                  = tcp_close,
--      .connect                = tcp_v4_connect,
--      .disconnect             = tcp_disconnect,
--      .accept                 = inet_csk_accept,
--      .ioctl                  = tcp_ioctl,
--      .init                   = tcp_v4_init_sock,
--      .destroy                = tcp_v4_destroy_sock,
--      .shutdown               = tcp_shutdown,
--      .setsockopt             = tcp_setsockopt,
--      .getsockopt             = tcp_getsockopt,
--      .recvmsg                = tcp_recvmsg,
--      .backlog_rcv            = tcp_v4_do_rcv,
--      .hash                   = tcp_v4_hash,
--      .unhash                 = tcp_unhash,
--      .get_port               = tcp_v4_get_port,
--      .enter_memory_pressure  = tcp_enter_memory_pressure,
--      .sockets_allocated      = &tcp_sockets_allocated,
--      .orphan_count           = &tcp_orphan_count,
--      .memory_allocated       = &tcp_memory_allocated,
--      .memory_pressure        = &tcp_memory_pressure,
--      .sysctl_mem             = sysctl_tcp_mem,
--      .sysctl_wmem            = sysctl_tcp_wmem,
--      .sysctl_rmem            = sysctl_tcp_rmem,
--      .max_header             = MAX_TCP_HEADER,
--      .obj_size               = sizeof(struct tcp_sock),
--      .twsk_prot              = &tcp_timewait_sock_ops,
--      .rsk_prot               = &tcp_request_sock_ops,
--#ifdef CONFIG_COMPAT
--      .compat_setsockopt      = compat_tcp_setsockopt,
--      .compat_getsockopt      = compat_tcp_getsockopt,
--#endif
+-static struct pernet_operations inet_net_ops = {
+-      .init = inet_net_init,
+-      .exit = inet_net_exit,
 -};
 -
--void __init tcp_v4_init(struct net_proto_family *ops)
--{
--      if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW,
--                                   IPPROTO_TCP) < 0)
--              panic("Failed to create the TCP control socket.\n");
--}
--
--EXPORT_SYMBOL(ipv4_specific);
--EXPORT_SYMBOL(tcp_hashinfo);
--EXPORT_SYMBOL(tcp_prot);
--EXPORT_SYMBOL(tcp_unhash);
--EXPORT_SYMBOL(tcp_v4_conn_request);
--EXPORT_SYMBOL(tcp_v4_connect);
--EXPORT_SYMBOL(tcp_v4_do_rcv);
--EXPORT_SYMBOL(tcp_v4_remember_stamp);
--EXPORT_SYMBOL(tcp_v4_send_check);
--EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
--
--#ifdef CONFIG_PROC_FS
--EXPORT_SYMBOL(tcp_proc_register);
--EXPORT_SYMBOL(tcp_proc_unregister);
--#endif
--EXPORT_SYMBOL(sysctl_local_port_range);
--EXPORT_SYMBOL(sysctl_tcp_low_latency);
+ static int __init inet_init(void)
+ {
+       struct sk_buff *dummy_skb;
+@@ -1402,10 +1374,6 @@
+       if (rc)
+               goto out_unregister_udp_proto;
+-      rc = register_pernet_subsys(&inet_net_ops);
+-      if (rc)
+-              goto out_unregister_raw_proto;
 -
-diff -Nurb linux-2.6.22-570/net/ipv4/tcp_output.c linux-2.6.22-590/net/ipv4/tcp_output.c
---- linux-2.6.22-570/net/ipv4/tcp_output.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/tcp_output.c     2008-01-02 13:56:38.000000000 -0500
-@@ -432,11 +432,11 @@
-       sysctl_flags = 0;
-       if (unlikely(tcb->flags & TCPCB_FLAG_SYN)) {
-               tcp_header_size = sizeof(struct tcphdr) + TCPOLEN_MSS;
--              if (sysctl_tcp_timestamps) {
-+              if (sk->sk_net->sysctl_tcp_timestamps) {
-                       tcp_header_size += TCPOLEN_TSTAMP_ALIGNED;
-                       sysctl_flags |= SYSCTL_FLAG_TSTAMPS;
-               }
--              if (sysctl_tcp_window_scaling) {
-+              if (sk->sk_net->sysctl_tcp_window_scaling) {
-                       tcp_header_size += TCPOLEN_WSCALE_ALIGNED;
-                       sysctl_flags |= SYSCTL_FLAG_WSCALE;
-               }
-@@ -2215,7 +2215,7 @@
-        * See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.
+       /*
+        *      Tell SOCKET that we are alive...
         */
-       tp->tcp_header_len = sizeof(struct tcphdr) +
--              (sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0);
-+              (sk->sk_net->sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0);
- #ifdef CONFIG_TCP_MD5SIG
-       if (tp->af_specific->md5_lookup(sk, sk) != NULL)
-@@ -2238,7 +2238,7 @@
-                                 tp->advmss - (tp->rx_opt.ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
-                                 &tp->rcv_wnd,
-                                 &tp->window_clamp,
--                                sysctl_tcp_window_scaling,
-+                                sk->sk_net->sysctl_tcp_window_scaling,
-                                 &rcv_wscale);
+@@ -1482,8 +1450,6 @@
+       rc = 0;
+ out:
+       return rc;
+-out_unregister_raw_proto:
+-      proto_unregister(&raw_prot);
+ out_unregister_udp_proto:
+       proto_unregister(&udp_prot);
+ out_unregister_tcp_proto:
+@@ -1506,11 +1472,15 @@
+               goto out_tcp;
+       if (udp4_proc_init())
+               goto out_udp;
++      if (fib_proc_init())
++              goto out_fib;
+       if (ip_misc_proc_init())
+               goto out_misc;
+ out:
+       return rc;
+ out_misc:
++      fib_proc_exit();
++out_fib:
+       udp4_proc_exit();
+ out_udp:
+       tcp4_proc_exit();
+@@ -1546,3 +1516,4 @@
+ EXPORT_SYMBOL(inet_stream_ops);
+ EXPORT_SYMBOL(inet_unregister_protosw);
+ EXPORT_SYMBOL(net_statistics);
++EXPORT_SYMBOL(sysctl_ip_nonlocal_bind);
+diff -Nurb linux-2.6.22-590/net/ipv4/ah4.c linux-2.6.22-570/net/ipv4/ah4.c
+--- linux-2.6.22-590/net/ipv4/ah4.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ah4.c    2008-01-23 19:15:56.000000000 -0500
+@@ -198,9 +198,6 @@
+       struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+(iph->ihl<<2));
+       struct xfrm_state *x;
  
-       tp->rx_opt.rcv_wscale = rcv_wscale;
-diff -Nurb linux-2.6.22-570/net/ipv4/tcp_probe.c linux-2.6.22-590/net/ipv4/tcp_probe.c
---- linux-2.6.22-570/net/ipv4/tcp_probe.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/tcp_probe.c      2008-01-02 13:56:38.000000000 -0500
-@@ -172,7 +172,7 @@
-       if (IS_ERR(tcpw.fifo))
-               return PTR_ERR(tcpw.fifo);
+-      if (skb->dev->nd_net != &init_net)
+-              return;
+-
+       if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH ||
+           icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
+               return;
+@@ -342,4 +339,3 @@
+ module_init(ah4_init);
+ module_exit(ah4_fini);
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_AH);
+diff -Nurb linux-2.6.22-590/net/ipv4/arp.c linux-2.6.22-570/net/ipv4/arp.c
+--- linux-2.6.22-590/net/ipv4/arp.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/arp.c    2007-07-08 19:32:17.000000000 -0400
+@@ -109,7 +109,6 @@
+ #include <net/protocol.h>
+ #include <net/tcp.h>
+ #include <net/sock.h>
+-#include <net/net_namespace.h>
+ #include <net/arp.h>
+ #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ #include <net/ax25.h>
+@@ -236,11 +235,10 @@
+ {
+       __be32 addr = *(__be32*)neigh->primary_key;
+       struct net_device *dev = neigh->dev;
+-      struct net *net = dev->nd_net;
+       struct in_device *in_dev;
+       struct neigh_parms *parms;
  
--      if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops))
-+      if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &tcpprobe_fops))
-               goto err0;
+-      neigh->type = inet_addr_type(net, addr);
++      neigh->type = inet_addr_type(addr);
  
-       ret = register_jprobe(&tcp_probe);
-@@ -182,7 +182,7 @@
-       pr_info("TCP watch registered (port=%d)\n", port);
-       return 0;
-  err1:
--      proc_net_remove(procname);
-+      proc_net_remove(&init_net, procname);
-  err0:
-       kfifo_free(tcpw.fifo);
-       return ret;
-@@ -192,7 +192,7 @@
- static __exit void tcpprobe_exit(void)
+       rcu_read_lock();
+       in_dev = __in_dev_get_rcu(dev);
+@@ -334,7 +332,6 @@
+       __be32 saddr = 0;
+       u8  *dst_ha = NULL;
+       struct net_device *dev = neigh->dev;
+-      struct net *net = dev->nd_net;
+       __be32 target = *(__be32*)neigh->primary_key;
+       int probes = atomic_read(&neigh->probes);
+       struct in_device *in_dev = in_dev_get(dev);
+@@ -345,14 +342,14 @@
+       switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
+       default:
+       case 0:         /* By default announce any local IP */
+-              if (skb && inet_addr_type(net, ip_hdr(skb)->saddr) == RTN_LOCAL)
++              if (skb && inet_addr_type(ip_hdr(skb)->saddr) == RTN_LOCAL)
+                       saddr = ip_hdr(skb)->saddr;
+               break;
+       case 1:         /* Restrict announcements of saddr in same subnet */
+               if (!skb)
+                       break;
+               saddr = ip_hdr(skb)->saddr;
+-              if (inet_addr_type(net, saddr) == RTN_LOCAL) {
++              if (inet_addr_type(saddr) == RTN_LOCAL) {
+                       /* saddr should be known to target */
+                       if (inet_addr_onlink(in_dev, target, saddr))
+                               break;
+@@ -389,7 +386,6 @@
+ static int arp_ignore(struct in_device *in_dev, struct net_device *dev,
+                     __be32 sip, __be32 tip)
  {
-       kfifo_free(tcpw.fifo);
--      proc_net_remove(procname);
-+      proc_net_remove(&init_net, procname);
-       unregister_jprobe(&tcp_probe);
+-      struct net *net = dev->nd_net;
+       int scope;
  
+       switch (IN_DEV_ARP_IGNORE(in_dev)) {
+@@ -420,15 +416,13 @@
+       default:
+               return 0;
+       }
+-      return !inet_confirm_addr(net, dev, sip, tip, scope);
++      return !inet_confirm_addr(dev, sip, tip, scope);
  }
-diff -Nurb linux-2.6.22-570/net/ipv4/tunnel4.c linux-2.6.22-590/net/ipv4/tunnel4.c
---- linux-2.6.22-570/net/ipv4/tunnel4.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/tunnel4.c        2008-01-02 13:56:38.000000000 -0500
-@@ -75,6 +75,10 @@
- {
-       struct xfrm_tunnel *handler;
-+      if (skb->dev->nd_net != &init_net) {
-+              kfree_skb(skb);
-+              return 0;
-+      }
-       if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-               goto drop;
  
-@@ -113,6 +117,9 @@
+ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
  {
-       struct xfrm_tunnel *handler;
+-      struct flowi fl = {
+-              .fl_net = dev->nd_net,
+-              .nl_u = { .ip4_u = { .daddr = sip, .saddr = tip } }
+-      };
++      struct flowi fl = { .nl_u = { .ip4_u = { .daddr = sip,
++                                               .saddr = tip } } };
+       struct rtable *rt;
+       int flag = 0;
+       /*unsigned long now; */
+@@ -475,7 +469,6 @@
+ int arp_find(unsigned char *haddr, struct sk_buff *skb)
+ {
+       struct net_device *dev = skb->dev;
+-      struct net *net = dev->nd_net;
+       __be32 paddr;
+       struct neighbour *n;
  
-+      if (skb->dev->nd_net != &init_net)
-+              return;
-+
-       for (handler = tunnel4_handlers; handler; handler = handler->next)
-               if (!handler->err_handler(skb, info))
-                       break;
-diff -Nurb linux-2.6.22-570/net/ipv4/udp.c linux-2.6.22-590/net/ipv4/udp.c
---- linux-2.6.22-570/net/ipv4/udp.c    2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/net/ipv4/udp.c    2008-01-02 13:56:38.000000000 -0500
-@@ -101,6 +101,7 @@
- #include <net/route.h>
- #include <net/checksum.h>
- #include <net/xfrm.h>
-+#include <net/net_namespace.h>
- #include "udp_impl.h"
+@@ -487,7 +480,7 @@
  
- /*
-@@ -112,16 +113,17 @@
- struct hlist_head udp_hash[UDP_HTABLE_SIZE];
- DEFINE_RWLOCK(udp_hash_lock);
+       paddr = ((struct rtable*)skb->dst)->rt_gateway;
  
--static int udp_port_rover;
--
--static inline int __udp_lib_lport_inuse(__u16 num, struct hlist_head udptable[])
-+static inline int __udp_lib_lport_inuse(struct net *net, __u16 num, struct hlist_head udptable[])
+-      if (arp_set_predefined(inet_addr_type(net, paddr), haddr, paddr, dev))
++      if (arp_set_predefined(inet_addr_type(paddr), haddr, paddr, dev))
+               return 0;
+       n = __neigh_lookup(&arp_tbl, &paddr, dev, 1);
+@@ -711,7 +704,6 @@
+ static int arp_process(struct sk_buff *skb)
  {
-       struct sock *sk;
-       struct hlist_node *node;
+       struct net_device *dev = skb->dev;
+-      struct net *net = dev->nd_net;
+       struct in_device *in_dev = in_dev_get(dev);
+       struct arphdr *arp;
+       unsigned char *arp_ptr;
+@@ -832,7 +824,7 @@
+       /* Special case: IPv4 duplicate address detection packet (RFC2131) */
+       if (sip == 0) {
+               if (arp->ar_op == htons(ARPOP_REQUEST) &&
+-                  inet_addr_type(net, tip) == RTN_LOCAL &&
++                  inet_addr_type(tip) == RTN_LOCAL &&
+                   !arp_ignore(in_dev,dev,sip,tip))
+                       arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr);
+               goto out;
+@@ -862,7 +854,7 @@
+               } else if (IN_DEV_FORWARD(in_dev)) {
+                       if ((rt->rt_flags&RTCF_DNAT) ||
+                           (addr_type == RTN_UNICAST  && rt->u.dst.dev != dev &&
+-                           (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))) {
++                           (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, &tip, dev, 0)))) {
+                               n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
+                               if (n)
+                                       neigh_release(n);
+@@ -885,14 +877,14 @@
  
--      sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
-+      sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)]) {
-+              if (sk->sk_net != net)
-+                      continue;
-               if (sk->sk_hash == num)
-                       return 1;
-+      }
-       return 0;
- }
+       n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
  
-@@ -148,9 +150,9 @@
-       if (snum == 0) {
-               int best_size_so_far, best, result, i;
+-      if (IPV4_DEVCONF_ALL(net, ARP_ACCEPT)) {
++      if (IPV4_DEVCONF_ALL(ARP_ACCEPT)) {
+               /* Unsolicited ARP is not accepted by default.
+                  It is possible, that this option should be enabled for some
+                  devices (strip is candidate)
+                */
+               if (n == NULL &&
+                   arp->ar_op == htons(ARPOP_REPLY) &&
+-                  inet_addr_type(net, sip) == RTN_UNICAST)
++                  inet_addr_type(sip) == RTN_UNICAST)
+                       n = __neigh_lookup(&arp_tbl, &sip, dev, -1);
+       }
  
--              if (*port_rover > sysctl_local_port_range[1] ||
--                  *port_rover < sysctl_local_port_range[0])
--                      *port_rover = sysctl_local_port_range[0];
-+              if (*port_rover > sk->sk_net->sysctl_local_port_range[1] ||
-+                  *port_rover < sk->sk_net->sysctl_local_port_range[0])
-+                      *port_rover = sk->sk_net->sysctl_local_port_range[0];
-               best_size_so_far = 32767;
-               best = result = *port_rover;
-               for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
-@@ -158,9 +160,9 @@
+@@ -974,7 +966,7 @@
+  *    Set (create) an ARP cache entry.
+  */
  
-                       head = &udptable[result & (UDP_HTABLE_SIZE - 1)];
-                       if (hlist_empty(head)) {
--                              if (result > sysctl_local_port_range[1])
--                                      result = sysctl_local_port_range[0] +
--                                              ((result - sysctl_local_port_range[0]) &
-+                              if (result > sk->sk_net->sysctl_local_port_range[1])
-+                                      result = sk->sk_net->sysctl_local_port_range[0] +
-+                                              ((result - sk->sk_net->sysctl_local_port_range[0]) &
-                                                (UDP_HTABLE_SIZE - 1));
-                               goto gotit;
-                       }
-@@ -177,11 +179,11 @@
-               result = best;
-               for (i = 0; i < (1 << 16) / UDP_HTABLE_SIZE;
-                    i++, result += UDP_HTABLE_SIZE) {
--                      if (result > sysctl_local_port_range[1])
--                              result = sysctl_local_port_range[0]
--                                      + ((result - sysctl_local_port_range[0]) &
-+                      if (result > sk->sk_net->sysctl_local_port_range[1])
-+                              result = sk->sk_net->sysctl_local_port_range[0]
-+                                      + ((result - sk->sk_net->sysctl_local_port_range[0]) &
-                                          (UDP_HTABLE_SIZE - 1));
--                      if (! __udp_lib_lport_inuse(result, udptable))
-+                      if (! __udp_lib_lport_inuse(sk->sk_net, result, udptable))
-                               break;
-               }
-               if (i >= (1 << 16) / UDP_HTABLE_SIZE)
-@@ -194,6 +196,7 @@
-               sk_for_each(sk2, node, head)
-                       if (sk2->sk_hash == snum                             &&
-                           sk2 != sk                                        &&
-+                          sk->sk_net == sk2->sk_net                        &&
-                           (!sk2->sk_reuse        || !sk->sk_reuse)         &&
-                           (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
-                            || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
-@@ -216,7 +219,7 @@
- int udp_get_port(struct sock *sk, unsigned short snum,
-                       int (*scmp)(const struct sock *, const struct sock *))
+-static int arp_req_set(struct net *net, struct arpreq *r, struct net_device * dev)
++static int arp_req_set(struct arpreq *r, struct net_device * dev)
  {
--      return  __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp);
-+      return  __udp_lib_get_port(sk, snum, udp_hash, &sk->sk_net->udp_port_rover, scmp);
+       __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
+       struct neighbour *neigh;
+@@ -985,17 +977,17 @@
+               if (mask && mask != htonl(0xFFFFFFFF))
+                       return -EINVAL;
+               if (!dev && (r->arp_flags & ATF_COM)) {
+-                      dev = dev_getbyhwaddr(net, r->arp_ha.sa_family, r->arp_ha.sa_data);
++                      dev = dev_getbyhwaddr(r->arp_ha.sa_family, r->arp_ha.sa_data);
+                       if (!dev)
+                               return -ENODEV;
+               }
+               if (mask) {
+-                      if (pneigh_lookup(&arp_tbl, net, &ip, dev, 1) == NULL)
++                      if (pneigh_lookup(&arp_tbl, &ip, dev, 1) == NULL)
+                               return -ENOBUFS;
+                       return 0;
+               }
+               if (dev == NULL) {
+-                      IPV4_DEVCONF_ALL(net, PROXY_ARP) = 1;
++                      IPV4_DEVCONF_ALL(PROXY_ARP) = 1;
+                       return 0;
+               }
+               if (__in_dev_get_rtnl(dev)) {
+@@ -1008,10 +1000,8 @@
+       if (r->arp_flags & ATF_PERM)
+               r->arp_flags |= ATF_COM;
+       if (dev == NULL) {
+-              struct flowi fl = { 
+-                      .fl_net = net,
+-                      .nl_u = { .ip4_u = { .daddr = ip, .tos = RTO_ONLINK } }
+-              };
++              struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,
++                                                       .tos = RTO_ONLINK } } };
+               struct rtable * rt;
+               if ((err = ip_route_output_key(&rt, &fl)) != 0)
+                       return err;
+@@ -1090,7 +1080,7 @@
+       return err;
  }
  
- extern int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2);
-@@ -229,7 +232,8 @@
- /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
-  * harder than this. -DaveM
-  */
--static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
-+static struct sock *__udp4_lib_lookup(struct net *net,
-+                                    __be32 saddr, __be16 sport,
-                                     __be32 daddr, __be16 dport,
-                                     int dif, struct hlist_head udptable[])
+-static int arp_req_delete(struct net *net, struct arpreq *r, struct net_device * dev)
++static int arp_req_delete(struct arpreq *r, struct net_device * dev)
  {
-@@ -243,6 +247,9 @@
-       sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
-               struct inet_sock *inet = inet_sk(sk);
-+              if (sk->sk_net != net)
-+                      continue;
-+
-               if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) {
-                       int score = (sk->sk_family == PF_INET ? 1 : 0);
-@@ -299,6 +306,9 @@
-       sk_for_each_from(s, node) {
-               struct inet_sock *inet = inet_sk(s);
+       int err;
+       __be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
+@@ -1100,10 +1090,10 @@
+               __be32 mask =
+                      ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr;
+               if (mask == htonl(0xFFFFFFFF))
+-                      return pneigh_delete(&arp_tbl, net, &ip, dev);
++                      return pneigh_delete(&arp_tbl, &ip, dev);
+               if (mask == 0) {
+                       if (dev == NULL) {
+-                              IPV4_DEVCONF_ALL(net, PROXY_ARP) = 0;
++                              IPV4_DEVCONF_ALL(PROXY_ARP) = 0;
+                               return 0;
+                       }
+                       if (__in_dev_get_rtnl(dev)) {
+@@ -1117,10 +1107,8 @@
+       }
  
-+              if (s->sk_net != sk->sk_net)
-+                      continue;
-+
-               if (s->sk_hash != hnum                                  ||
-                   (inet->daddr && inet->daddr != rmt_addr)            ||
-                   (inet->dport != rmt_port && inet->dport)            ||
-@@ -328,6 +338,7 @@
+       if (dev == NULL) {
+-              struct flowi fl = {
+-                      .fl_net = net,
+-                      .nl_u = { .ip4_u = { .daddr = ip, .tos = RTO_ONLINK } }
+-              };
++              struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,
++                                                       .tos = RTO_ONLINK } } };
+               struct rtable * rt;
+               if ((err = ip_route_output_key(&rt, &fl)) != 0)
+                       return err;
+@@ -1145,7 +1133,7 @@
+  *    Handle an ARP layer I/O control request.
+  */
  
- void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[])
+-int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
++int arp_ioctl(unsigned int cmd, void __user *arg)
  {
-+      struct net *net = skb->dev->nd_net;
-       struct inet_sock *inet;
-       struct iphdr *iph = (struct iphdr*)skb->data;
-       struct udphdr *uh = (struct udphdr*)(skb->data+(iph->ihl<<2));
-@@ -337,7 +348,7 @@
-       int harderr;
        int err;
+       struct arpreq r;
+@@ -1177,7 +1165,7 @@
+       rtnl_lock();
+       if (r.arp_dev[0]) {
+               err = -ENODEV;
+-              if ((dev = __dev_get_by_name(net, r.arp_dev)) == NULL)
++              if ((dev = __dev_get_by_name(r.arp_dev)) == NULL)
+                       goto out;
  
--      sk = __udp4_lib_lookup(iph->daddr, uh->dest, iph->saddr, uh->source,
-+      sk = __udp4_lib_lookup(net, iph->daddr, uh->dest, iph->saddr, uh->source,
-                              skb->dev->ifindex, udptable                  );
-       if (sk == NULL) {
-               ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
-@@ -623,7 +634,8 @@
-               rt = (struct rtable*)sk_dst_check(sk, 0);
+               /* Mmmm... It is wrong... ARPHRD_NETROM==0 */
+@@ -1193,10 +1181,10 @@
  
-       if (rt == NULL) {
--              struct flowi fl = { .oif = ipc.oif,
-+              struct flowi fl = { .fl_net = sk->sk_net,
-+                                  .oif = ipc.oif,
-                                   .nl_u = { .ip4_u =
-                                             { .daddr = faddr,
-                                               .saddr = saddr,
-@@ -1288,6 +1300,7 @@
- int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
-                  int proto)
+       switch (cmd) {
+       case SIOCDARP:
+-              err = arp_req_delete(net, &r, dev);
++              err = arp_req_delete(&r, dev);
+               break;
+       case SIOCSARP:
+-              err = arp_req_set(net, &r, dev);
++              err = arp_req_set(&r, dev);
+               break;
+       case SIOCGARP:
+               err = arp_req_get(&r, dev);
+@@ -1213,9 +1201,6 @@
  {
-+      struct net *net = skb->dev->nd_net;
-       struct sock *sk;
-       struct udphdr *uh = udp_hdr(skb);
-       unsigned short ulen;
-@@ -1322,7 +1335,7 @@
-       udp_ping_of_death(skb, uh, saddr);
- #endif
+       struct net_device *dev = ptr;
  
--      sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
-+      sk = __udp4_lib_lookup(net, saddr, uh->source, daddr, uh->dest,
-                              skb->dev->ifindex, udptable        );
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       switch (event) {
+       case NETDEV_CHANGEADDR:
+               neigh_changeaddr(&arp_tbl, dev);
+@@ -1242,54 +1227,6 @@
+ }
  
-       if (sk != NULL) {
-@@ -1651,7 +1664,7 @@
-               sk = sk_next(sk);
- try_again:
-               ;
--      } while (sk && (sk->sk_family != state->family ||
-+      } while (sk && ((sk->sk_net != state->net) || sk->sk_family != state->family ||
-               !nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT)));
  
-       if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {
-@@ -1717,6 +1730,7 @@
+-static int arp_proc_init(struct net *net);
+-static void arp_proc_exit(struct net *net);
+-
+-
+-static int arp_net_init(struct net *net)
+-{
+-      int error;
+-      if ((error = arp_proc_init(net)))
+-              goto out_proc;
+-
+-      error = -ENOMEM;
+-      net->arp_neigh_parms_default = neigh_parms_alloc_default(&arp_tbl, net);
+-      if (!net->arp_neigh_parms_default)
+-              goto out_parm;
+-
+-#ifdef CONFIG_SYSCTL
+-      if ((error = neigh_sysctl_register(
+-                   NULL, net->arp_neigh_parms_default,
+-                   NET_IPV4, NET_IPV4_NEIGH, "ipv4", NULL, NULL)))
+-              goto out_sysctl;
+-#endif
+-
+-out:
+-      return error;
+-
+-#ifdef CONFIG_SYSCTL
+-out_sysctl:
+-      neigh_parms_release(&arp_tbl, net->arp_neigh_parms_default);
+-#endif
+-out_parm:
+-      arp_proc_exit(net);
+-out_proc:
+-      goto out;
+-}
+-
+-static void arp_net_exit(struct net *net)
+-{
+-#ifdef CONFIG_SYSCTL
+-      neigh_sysctl_unregister(net->arp_neigh_parms_default);
+-#endif
+-      neigh_parms_release(&arp_tbl, net->arp_neigh_parms_default);
+-      arp_proc_exit(net);
+-}
+-
+-static struct pernet_operations arp_net_ops = {
+-      .init = arp_net_init,
+-      .exit = arp_net_exit,
+-};
+ /*
+  *    Called once on startup.
+  */
+@@ -1299,12 +1236,18 @@
+       .func = arp_rcv,
+ };
++static int arp_proc_init(void);
++
+ void __init arp_init(void)
+ {
+       neigh_table_init(&arp_tbl);
+       dev_add_pack(&arp_packet_type);
+-      register_pernet_subsys(&arp_net_ops);
++      arp_proc_init();
++#ifdef CONFIG_SYSCTL
++      neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4,
++                            NET_IPV4_NEIGH, "ipv4", NULL, NULL);
++#endif
+       register_netdevice_notifier(&arp_netdev_notifier);
+ }
+@@ -1440,8 +1383,6 @@
  
        seq          = file->private_data;
        seq->private = s;
-+      s->net       = get_net(PROC_NET(inode));
+-      s->net = get_net(PROC_NET(inode));
+-
  out:
        return rc;
  out_kfree:
-@@ -1724,21 +1738,31 @@
+@@ -1449,46 +1390,28 @@
        goto out;
  }
  
-+static int udp_seq_release(struct inode *inode, struct file *file)
-+{
-+      struct seq_file *seq = file->private_data;
-+      struct udp_iter_state *state = seq->private;
-+      put_net(state->net);
-+      return seq_release_private(inode, file);
-+}
-+
- /* ------------------------------------------------------------------------ */
--int udp_proc_register(struct udp_seq_afinfo *afinfo)
-+int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo)
- {
-       struct proc_dir_entry *p;
-       int rc = 0;
-       if (!afinfo)
-               return -EINVAL;
-+      if (net == &init_net) {
-       afinfo->seq_fops->owner         = afinfo->owner;
-       afinfo->seq_fops->open          = udp_seq_open;
-       afinfo->seq_fops->read          = seq_read;
-       afinfo->seq_fops->llseek        = seq_lseek;
--      afinfo->seq_fops->release       = seq_release_private;
-+              afinfo->seq_fops->release       = udp_seq_release;
-+      }
--      p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);
-+      p = proc_net_fops_create(net, afinfo->name, S_IRUGO, afinfo->seq_fops);
-       if (p)
-               p->data = afinfo;
-       else
-@@ -1746,11 +1770,12 @@
-       return rc;
- }
+-static int arp_seq_release(struct inode *inode, struct file *file)
+-{
+-      struct seq_file *seq = file->private_data;
+-      struct neigh_seq_state *state = seq->private;
+-      put_net(state->net);
+-      return seq_release_private(inode, file);
+-}
+-
+ static const struct file_operations arp_seq_fops = {
+       .owner          = THIS_MODULE,
+       .open           = arp_seq_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+-      .release        = arp_seq_release,
++      .release        = seq_release_private,
+ };
  
--void udp_proc_unregister(struct udp_seq_afinfo *afinfo)
-+void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo)
+-static int arp_proc_init(struct net *net)
++static int __init arp_proc_init(void)
  {
-       if (!afinfo)
-               return;
--      proc_net_remove(afinfo->name);
-+      proc_net_remove(net, afinfo->name);
-+      if (net == &init_net)
-       memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
+-      if (!proc_net_fops_create(net, "arp", S_IRUGO, &arp_seq_fops))
++      if (!proc_net_fops_create("arp", S_IRUGO, &arp_seq_fops))
+               return -ENOMEM;
+       return 0;
  }
  
-@@ -1803,14 +1828,30 @@
-       .seq_fops       = &udp4_seq_fops,
- };
+-static void arp_proc_exit(struct net *net)
+-{
+-      proc_net_remove(net, "arp");
+-}
+-
+ #else /* CONFIG_PROC_FS */
  
-+
-+static int udp4_proc_net_init(struct net *net)
-+{
-+      return udp_proc_register(net, &udp4_seq_afinfo);
-+}
-+
-+static void udp4_proc_net_exit(struct net *net)
-+{
-+      udp_proc_unregister(net, &udp4_seq_afinfo);
-+}
-+
-+static struct pernet_operations udp4_proc_net_ops = {
-+      .init = udp4_proc_net_init,
-+      .exit = udp4_proc_net_exit,
-+};
-+
- int __init udp4_proc_init(void)
+-static int arp_proc_init(struct net *net)
++static int __init arp_proc_init(void)
  {
--      return udp_proc_register(&udp4_seq_afinfo);
-+      return register_pernet_subsys(&udp4_proc_net_ops);
+       return 0;
  }
  
- void udp4_proc_exit(void)
- {
--      udp_proc_unregister(&udp4_seq_afinfo);
-+      unregister_pernet_subsys(&udp4_proc_net_ops);
- }
+-static void arp_proc_exit(struct net *net)
+-{
+-      return;
+-}
+-
  #endif /* CONFIG_PROC_FS */
  
-diff -Nurb linux-2.6.22-570/net/ipv4/udplite.c linux-2.6.22-590/net/ipv4/udplite.c
---- linux-2.6.22-570/net/ipv4/udplite.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/udplite.c        2008-01-02 13:56:38.000000000 -0500
-@@ -31,11 +31,18 @@
+ EXPORT_SYMBOL(arp_broken_ops);
+diff -Nurb linux-2.6.22-590/net/ipv4/devinet.c linux-2.6.22-570/net/ipv4/devinet.c
+--- linux-2.6.22-590/net/ipv4/devinet.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/devinet.c        2008-01-23 19:16:05.000000000 -0500
+@@ -63,7 +63,7 @@
+ #include <net/ip_fib.h>
+ #include <net/rtnetlink.h>
  
- static int udplite_rcv(struct sk_buff *skb)
- {
-+      if (skb->dev->nd_net != &init_net) {
-+              kfree_skb(skb);
-+              return 0;
-+      }
-       return __udp4_lib_rcv(skb, udplite_hash, IPPROTO_UDPLITE);
- }
+-static struct ipv4_devconf ipv4_devconf_template = {
++struct ipv4_devconf ipv4_devconf = {
+       .data = {
+               [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
+               [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
+@@ -72,7 +72,7 @@
+       },
+ };
  
- static void udplite_err(struct sk_buff *skb, u32 info)
- {
-+      if (skb->dev->nd_net != &init_net)
-+              return;
-+
-       return __udp4_lib_err(skb, info, udplite_hash);
- }
+-static struct ipv4_devconf ipv4_devconf_dflt_template = {
++static struct ipv4_devconf ipv4_devconf_dflt = {
+       .data = {
+               [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
+               [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
+@@ -82,7 +82,7 @@
+       },
+ };
  
-@@ -103,7 +110,7 @@
-       inet_register_protosw(&udplite4_protosw);
+-#define IPV4_DEVCONF_DFLT(net, attr) IPV4_DEVCONF(*((net)->ipv4_devconf_dflt), attr)
++#define IPV4_DEVCONF_DFLT(attr) IPV4_DEVCONF(ipv4_devconf_dflt, attr)
  
- #ifdef CONFIG_PROC_FS
--      if (udp_proc_register(&udplite4_seq_afinfo)) /* udplite4_proc_init() */
-+      if (udp_proc_register(&init_net, &udplite4_seq_afinfo)) /* udplite4_proc_init() */
-               printk(KERN_ERR "%s: Cannot register /proc!\n", __FUNCTION__);
+ static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = {
+       [IFA_LOCAL]             = { .type = NLA_U32 },
+@@ -98,7 +98,7 @@
+ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
+                        int destroy);
+ #ifdef CONFIG_SYSCTL
+-static void devinet_sysctl_register(struct net *net, struct in_device *in_dev,
++static void devinet_sysctl_register(struct in_device *in_dev,
+                                   struct ipv4_devconf *p);
+ static void devinet_sysctl_unregister(struct ipv4_devconf *p);
  #endif
-       return;
-diff -Nurb linux-2.6.22-570/net/ipv4/xfrm4_input.c linux-2.6.22-590/net/ipv4/xfrm4_input.c
---- linux-2.6.22-570/net/ipv4/xfrm4_input.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/xfrm4_input.c    2008-01-02 13:56:38.000000000 -0500
-@@ -18,6 +18,10 @@
+@@ -149,7 +149,6 @@
  
int xfrm4_rcv(struct sk_buff *skb)
static struct in_device *inetdev_init(struct net_device *dev)
  {
-+      if (skb->dev->nd_net != &init_net) {
-+              kfree_skb(skb);
-+              return 0;
-+      }
-       return xfrm4_rcv_encap(skb, 0);
- }
+-      struct net *net = dev->nd_net;
+       struct in_device *in_dev;
  
-diff -Nurb linux-2.6.22-570/net/ipv4/xfrm4_policy.c linux-2.6.22-590/net/ipv4/xfrm4_policy.c
---- linux-2.6.22-570/net/ipv4/xfrm4_policy.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/xfrm4_policy.c   2008-01-02 13:56:38.000000000 -0500
-@@ -25,6 +25,7 @@
- {
-       struct rtable *rt;
-       struct flowi fl_tunnel = {
-+              .fl_net = &init_net,
-               .nl_u = {
-                       .ip4_u = {
-                               .daddr = daddr->a4,
-@@ -73,6 +74,7 @@
-       struct rtable *rt0 = (struct rtable*)(*dst_p);
-       struct rtable *rt = rt0;
-       struct flowi fl_tunnel = {
-+              .fl_net = &init_net,
-               .nl_u = {
-                       .ip4_u = {
-                               .saddr = fl->fl4_src,
-@@ -213,6 +215,7 @@
-       u8 *xprth = skb_network_header(skb) + iph->ihl * 4;
+       ASSERT_RTNL();
+@@ -158,7 +157,7 @@
+       if (!in_dev)
+               goto out;
+       INIT_RCU_HEAD(&in_dev->rcu_head);
+-      memcpy(&in_dev->cnf, &net->ipv4_devconf_dflt, sizeof(in_dev->cnf));
++      memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf));
+       in_dev->cnf.sysctl = NULL;
+       in_dev->dev = dev;
+       if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL)
+@@ -174,7 +173,7 @@
+       in_dev_hold(in_dev);
  
-       memset(fl, 0, sizeof(struct flowi));
-+      fl->fl_net = &init_net;
-       if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) {
-               switch (iph->protocol) {
-               case IPPROTO_UDP:
-@@ -306,7 +309,7 @@
+ #ifdef CONFIG_SYSCTL
+-      devinet_sysctl_register(net, in_dev, &in_dev->cnf);
++      devinet_sysctl_register(in_dev, &in_dev->cnf);
+ #endif
+       ip_mc_init_dev(in_dev);
+       if (dev->flags & IFF_UP)
+@@ -204,6 +203,8 @@
+       ASSERT_RTNL();
  
-       xdst = (struct xfrm_dst *)dst;
-       if (xdst->u.rt.idev->dev == dev) {
--              struct in_device *loopback_idev = in_dev_get(&loopback_dev);
-+              struct in_device *loopback_idev = in_dev_get(&init_net.loopback_dev);
-               BUG_ON(!loopback_idev);
+       dev = in_dev->dev;
++      if (dev == &loopback_dev)
++              return;
  
-               do {
-diff -Nurb linux-2.6.22-570/net/ipv4/xfrm4_state.c linux-2.6.22-590/net/ipv4/xfrm4_state.c
---- linux-2.6.22-570/net/ipv4/xfrm4_state.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/xfrm4_state.c    2008-01-02 13:56:38.000000000 -0500
-@@ -16,7 +16,7 @@
+       in_dev->dead = 1;
  
- static int xfrm4_init_flags(struct xfrm_state *x)
- {
--      if (ipv4_config.no_pmtu_disc)
-+      if (init_net.sysctl_ipv4_no_pmtu_disc)
-               x->props.flags |= XFRM_STATE_NOPMTUDISC;
-       return 0;
+@@ -414,12 +415,12 @@
+       return inet_insert_ifa(ifa);
  }
-diff -Nurb linux-2.6.22-570/net/ipv4/xfrm4_tunnel.c linux-2.6.22-590/net/ipv4/xfrm4_tunnel.c
---- linux-2.6.22-570/net/ipv4/xfrm4_tunnel.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv4/xfrm4_tunnel.c   2008-01-02 13:56:38.000000000 -0500
-@@ -109,3 +109,4 @@
- module_init(ipip_init);
- module_exit(ipip_fini);
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP);
-diff -Nurb linux-2.6.22-570/net/ipv6/Kconfig linux-2.6.22-590/net/ipv6/Kconfig
---- linux-2.6.22-570/net/ipv6/Kconfig  2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/Kconfig  2008-01-02 13:56:38.000000000 -0500
-@@ -109,7 +109,7 @@
-         If unsure, say Y.
- config IPV6_MIP6
--      bool "IPv6: Mobility (EXPERIMENTAL)"
-+      tristate "IPv6: Mobility (EXPERIMENTAL)"
-       depends on IPV6 && EXPERIMENTAL
-       select XFRM
-       ---help---
-diff -Nurb linux-2.6.22-570/net/ipv6/Makefile linux-2.6.22-590/net/ipv6/Makefile
---- linux-2.6.22-570/net/ipv6/Makefile 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/Makefile 2008-01-02 13:56:38.000000000 -0500
-@@ -14,7 +14,6 @@
-       xfrm6_output.o
- ipv6-$(CONFIG_NETFILTER) += netfilter.o
- ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
--ipv6-$(CONFIG_IPV6_MIP6) += mip6.o
- ipv6-$(CONFIG_PROC_FS) += proc.o
- ipv6-objs += $(ipv6-y)
-@@ -28,6 +27,7 @@
- obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
- obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
- obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
-+obj-$(CONFIG_IPV6_MIP6) += mip6.o
- obj-$(CONFIG_NETFILTER)       += netfilter/
- obj-$(CONFIG_IPV6_SIT) += sit.o
-diff -Nurb linux-2.6.22-570/net/ipv6/addrconf.c linux-2.6.22-590/net/ipv6/addrconf.c
---- linux-2.6.22-570/net/ipv6/addrconf.c       2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/addrconf.c       2008-01-02 13:56:38.000000000 -0500
-@@ -73,6 +73,7 @@
- #include <net/tcp.h>
- #include <net/ip.h>
- #include <net/netlink.h>
-+#include <net/net_namespace.h>
- #include <net/pkt_sched.h>
- #include <linux/if_tunnel.h>
- #include <linux/rtnetlink.h>
-@@ -457,7 +458,7 @@
-       struct inet6_dev *idev;
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               rcu_read_lock();
-               idev = __in6_dev_get(dev);
-               if (idev) {
-@@ -920,7 +921,7 @@
-       read_lock(&dev_base_lock);
-       rcu_read_lock();
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               struct inet6_dev *idev;
-               struct inet6_ifaddr *ifa;
-@@ -1047,7 +1048,7 @@
-                       }
  
-                       /* Rule 4: Prefer home address */
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-                       if (hiscore.rule < 4) {
-                               if (ifa_result->flags & IFA_F_HOMEADDRESS)
-                                       hiscore.attrs |= IPV6_SADDR_SCORE_HOA;
-@@ -1882,7 +1883,7 @@
-       if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
-               goto err_exit;
--      dev = __dev_get_by_index(ireq.ifr6_ifindex);
-+      dev = __dev_get_by_index(&init_net, ireq.ifr6_ifindex);
-       err = -ENODEV;
-       if (dev == NULL)
-@@ -1913,7 +1914,7 @@
-               if (err == 0) {
-                       err = -ENOBUFS;
--                      if ((dev = __dev_get_by_name(p.name)) == NULL)
-+                      if ((dev = __dev_get_by_name(&init_net, p.name)) == NULL)
-                               goto err_exit;
-                       err = dev_open(dev);
-               }
-@@ -1943,7 +1944,7 @@
-       if (!valid_lft || prefered_lft > valid_lft)
-               return -EINVAL;
--      if ((dev = __dev_get_by_index(ifindex)) == NULL)
-+      if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL)
-               return -ENODEV;
-       if ((idev = addrconf_add_dev(dev)) == NULL)
-@@ -1994,7 +1995,7 @@
-       struct inet6_dev *idev;
+-struct in_device *inetdev_by_index(struct net *net, int ifindex)
++struct in_device *inetdev_by_index(int ifindex)
+ {
        struct net_device *dev;
+       struct in_device *in_dev = NULL;
+       read_lock(&dev_base_lock);
+-      dev = __dev_get_by_index(net, ifindex);
++      dev = __dev_get_by_index(ifindex);
+       if (dev)
+               in_dev = in_dev_get(dev);
+       read_unlock(&dev_base_lock);
+@@ -443,7 +444,6 @@
  
--      if ((dev = __dev_get_by_index(ifindex)) == NULL)
-+      if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL)
-               return -ENODEV;
-       if ((idev = __in6_dev_get(dev)) == NULL)
-@@ -2089,7 +2090,7 @@
-               return;
-       }
+ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct nlattr *tb[IFA_MAX+1];
+       struct in_device *in_dev;
+       struct ifaddrmsg *ifm;
+@@ -457,7 +457,7 @@
+               goto errout;
  
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               struct in_device * in_dev = __in_dev_get_rtnl(dev);
-               if (in_dev && (dev->flags & IFF_UP)) {
-                       struct in_ifaddr * ifa;
-@@ -2245,12 +2246,12 @@
+       ifm = nlmsg_data(nlh);
+-      in_dev = inetdev_by_index(net, ifm->ifa_index);
++      in_dev = inetdev_by_index(ifm->ifa_index);
+       if (in_dev == NULL) {
+               err = -ENODEV;
+               goto errout;
+@@ -488,7 +488,7 @@
+       return err;
+ }
  
-       /* first try to inherit the link-local address from the link device */
-       if (idev->dev->iflink &&
--          (link_dev = __dev_get_by_index(idev->dev->iflink))) {
-+          (link_dev = __dev_get_by_index(&init_net, idev->dev->iflink))) {
-               if (!ipv6_inherit_linklocal(idev, link_dev))
-                       return;
-       }
-       /* then try to inherit it from any device */
--      for_each_netdev(link_dev) {
-+      for_each_netdev(&init_net, link_dev) {
-               if (!ipv6_inherit_linklocal(idev, link_dev))
-                       return;
+-static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh)
++static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
+ {
+       struct nlattr *tb[IFA_MAX+1];
+       struct in_ifaddr *ifa;
+@@ -507,7 +507,7 @@
+               goto errout;
        }
-@@ -2282,6 +2283,9 @@
-       struct inet6_dev *idev = __in6_dev_get(dev);
-       int run_pending = 0;
  
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       switch(event) {
-       case NETDEV_REGISTER:
-               if (!idev && dev->mtu >= IPV6_MIN_MTU) {
-@@ -2419,7 +2423,7 @@
+-      dev = __dev_get_by_index(net, ifm->ifa_index);
++      dev = __dev_get_by_index(ifm->ifa_index);
+       if (dev == NULL) {
+               err = -ENODEV;
+               goto errout;
+@@ -564,12 +564,11 @@
  
-       ASSERT_RTNL();
+ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct in_ifaddr *ifa;
  
--      if (dev == &loopback_dev && how == 1)
-+      if (dev == &init_net.loopback_dev && how == 1)
-               how = 0;
+       ASSERT_RTNL();
  
-       rt6_ifdown(dev);
-@@ -2850,18 +2854,18 @@
+-      ifa = rtm_to_ifaddr(net, nlh);
++      ifa = rtm_to_ifaddr(nlh);
+       if (IS_ERR(ifa))
+               return PTR_ERR(ifa);
  
- int __init if6_proc_init(void)
- {
--      if (!proc_net_fops_create("if_inet6", S_IRUGO, &if6_fops))
-+      if (!proc_net_fops_create(&init_net, "if_inet6", S_IRUGO, &if6_fops))
-               return -ENOMEM;
-       return 0;
+@@ -601,7 +600,7 @@
  }
  
- void if6_proc_exit(void)
- {
--      proc_net_remove("if_inet6");
-+      proc_net_remove(&init_net, "if_inet6");
- }
- #endif        /* CONFIG_PROC_FS */
  
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- /* Check if address is a home address configured on any interface. */
- int ipv6_chk_home_addr(struct in6_addr *addr)
+-int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
++int devinet_ioctl(unsigned int cmd, void __user *arg)
  {
-@@ -3017,11 +3021,15 @@
- static int
- inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct ifaddrmsg *ifm;
-       struct nlattr *tb[IFA_MAX+1];
-       struct in6_addr *pfx;
-       int err;
+       struct ifreq ifr;
+       struct sockaddr_in sin_orig;
+@@ -630,7 +629,7 @@
+               *colon = 0;
  
-+      if (net != &init_net)
-+              return -EINVAL;
-+
-       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
-       if (err < 0)
-               return err;
-@@ -3074,6 +3082,7 @@
- static int
- inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct ifaddrmsg *ifm;
-       struct nlattr *tb[IFA_MAX+1];
-       struct in6_addr *pfx;
-@@ -3083,6 +3092,9 @@
-       u8 ifa_flags;
-       int err;
+ #ifdef CONFIG_KMOD
+-      dev_load(net, ifr.ifr_name);
++      dev_load(ifr.ifr_name);
+ #endif
  
-+      if (net != &init_net)
-+              return -EINVAL;
-+
-       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
-       if (err < 0)
-               return err;
-@@ -3103,7 +3115,7 @@
-               valid_lft = INFINITY_LIFE_TIME;
-       }
+       switch (cmd) {
+@@ -671,7 +670,7 @@
+       rtnl_lock();
  
--      dev =  __dev_get_by_index(ifm->ifa_index);
-+      dev =  __dev_get_by_index(&init_net, ifm->ifa_index);
-       if (dev == NULL)
-               return -ENODEV;
+       ret = -ENODEV;
+-      if ((dev = __dev_get_by_name(net, ifr.ifr_name)) == NULL)
++      if ((dev = __dev_get_by_name(ifr.ifr_name)) == NULL)
+               goto done;
  
-@@ -3292,7 +3304,7 @@
-       s_ip_idx = ip_idx = cb->args[1];
+       if (colon)
+@@ -890,7 +889,6 @@
  
-       idx = 0;
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if (idx < s_idx)
-                       goto cont;
-               if (idx > s_idx)
-@@ -3367,26 +3379,42 @@
+ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
+ {
+-      struct net *net = dev->nd_net;
+       __be32 addr = 0;
+       struct in_device *in_dev;
  
- static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+@@ -921,7 +919,7 @@
+        */
+       read_lock(&dev_base_lock);
+       rcu_read_lock();
+-      for_each_netdev(net, dev) {
++      for_each_netdev(dev) {
+               if ((in_dev = __in_dev_get_rcu(dev)) == NULL)
+                       continue;
+@@ -984,7 +982,7 @@
+  * - local: address, 0=autoselect the local address
+  * - scope: maximum allowed scope value for the local address
+  */
+-__be32 inet_confirm_addr(struct net *net, const struct net_device *dev, __be32 dst, __be32 local, int scope)
++__be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope)
  {
-+      struct net *net = skb->sk->sk_net;
-       enum addr_type_t type = UNICAST_ADDR;
-+
-+      if (net != &init_net)
-+              return 0;
-+
-       return inet6_dump_addr(skb, cb, type);
- }
+       __be32 addr = 0;
+       struct in_device *in_dev;
+@@ -1000,7 +998,7 @@
  
- static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb)
+       read_lock(&dev_base_lock);
+       rcu_read_lock();
+-      for_each_netdev(net, dev) {
++      for_each_netdev(dev) {
+               if ((in_dev = __in_dev_get_rcu(dev))) {
+                       addr = confirm_addr_indev(in_dev, dst, local, scope);
+                       if (addr)
+@@ -1061,7 +1059,6 @@
+                        void *ptr)
  {
-+      struct net *net = skb->sk->sk_net;
-       enum addr_type_t type = MULTICAST_ADDR;
-+
-+      if (net != &init_net)
-+              return 0;
-+
-       return inet6_dump_addr(skb, cb, type);
- }
+       struct net_device *dev = ptr;
+-      struct net *net = dev->nd_net;
+       struct in_device *in_dev = __in_dev_get_rtnl(dev);
  
+       ASSERT_RTNL();
+@@ -1069,7 +1066,7 @@
+       if (!in_dev) {
+               if (event == NETDEV_REGISTER) {
+                       in_dev = inetdev_init(dev);
+-                      if (dev == &net->loopback_dev) {
++                      if (dev == &loopback_dev) {
+                               if (!in_dev)
+                                       panic("devinet: "
+                                             "Failed to create loopback\n");
+@@ -1088,7 +1085,7 @@
+       case NETDEV_UP:
+               if (dev->mtu < 68)
+                       break;
+-              if (dev == &net->loopback_dev) {
++              if (dev == &loopback_dev) {
+                       struct in_ifaddr *ifa;
+                       if ((ifa = inet_alloc_ifa()) != NULL) {
+                               ifa->ifa_local =
+@@ -1125,7 +1122,7 @@
+               neigh_sysctl_unregister(in_dev->arp_parms);
+               neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
+                                     NET_IPV4_NEIGH, "ipv4", NULL, NULL);
+-              devinet_sysctl_register(net, in_dev, &in_dev->cnf);
++              devinet_sysctl_register(in_dev, &in_dev->cnf);
+ #endif
+               break;
+       }
+@@ -1188,7 +1185,6 @@
  
- static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
  {
-+      struct net *net = skb->sk->sk_net;
-       enum addr_type_t type = ANYCAST_ADDR;
-+
-+      if (net != &init_net)
-+              return 0;
-+
-       return inet6_dump_addr(skb, cb, type);
- }
+-      struct net *net = skb->sk->sk_net;
+       int idx, ip_idx;
+       struct net_device *dev;
+       struct in_device *in_dev;
+@@ -1198,7 +1194,7 @@
  
- static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
-                            void *arg)
+       s_ip_idx = ip_idx = cb->args[1];
+       idx = 0;
+-      for_each_netdev(net, dev) {
++      for_each_netdev(dev) {
+               if (idx < s_idx)
+                       goto cont;
+               if (idx > s_idx)
+@@ -1232,7 +1228,6 @@
+                     u32 pid)
  {
-+      struct net *net = in_skb->sk->sk_net;
-       struct ifaddrmsg *ifm;
-       struct nlattr *tb[IFA_MAX+1];
-       struct in6_addr *addr = NULL;
-@@ -3395,6 +3423,9 @@
        struct sk_buff *skb;
-       int err;
-+      if (net != &init_net)
-+              return -EINVAL;
-+
-       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
-       if (err < 0)
-               goto errout;
-@@ -3407,7 +3438,7 @@
-       ifm = nlmsg_data(nlh);
-       if (ifm->ifa_index)
--              dev = __dev_get_by_index(ifm->ifa_index);
-+              dev = __dev_get_by_index(&init_net, ifm->ifa_index);
+-      struct net *net = ifa->ifa_dev->dev->nd_net;
+       u32 seq = nlh ? nlh->nlmsg_seq : 0;
+       int err = -ENOBUFS;
  
-       if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) {
-               err = -EADDRNOTAVAIL;
-@@ -3427,7 +3458,7 @@
-               kfree_skb(skb);
-               goto errout_ifa;
-       }
--      err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
-+      err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
- errout_ifa:
-       in6_ifa_put(ifa);
- errout:
-@@ -3450,10 +3481,10 @@
+@@ -1247,25 +1242,25 @@
                kfree_skb(skb);
                goto errout;
        }
--      err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
-+      err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
+-      err = rtnl_notify(skb, net, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
++      err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
  errout:
        if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
-+              rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err);
+-              rtnl_set_sk_err(net, RTNLGRP_IPV4_IFADDR, err);
++              rtnl_set_sk_err(RTNLGRP_IPV4_IFADDR, err);
  }
  
- static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
-@@ -3612,19 +3643,22 @@
+ #ifdef CONFIG_SYSCTL
  
- static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+-static void devinet_copy_dflt_conf(struct net *net, int i)
++static void devinet_copy_dflt_conf(int i)
  {
-+      struct net *net = skb->sk->sk_net;
-       int idx, err;
-       int s_idx = cb->args[0];
        struct net_device *dev;
-       struct inet6_dev *idev;
-       struct nx_info *nxi = skb->sk ? skb->sk->sk_nx_info : NULL;
-+      if (net != &init_net)
-+              return 0;
-       /* FIXME: maybe disable ipv6 on non v6 guests?
-       if (skb->sk && skb->sk->sk_vx_info)
-               return skb->len;        */
  
        read_lock(&dev_base_lock);
-       idx = 0;
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if (idx < s_idx)
-                       goto cont;
-               if (!v6_dev_in_nx_info(dev, nxi))
-@@ -3661,10 +3695,10 @@
-               kfree_skb(skb);
-               goto errout;
+-      for_each_netdev(net, dev) {
++      for_each_netdev(dev) {
+               struct in_device *in_dev;
+               rcu_read_lock();
+               in_dev = __in_dev_get_rcu(dev);
+               if (in_dev && !test_bit(i, in_dev->cnf.state))
+-                      in_dev->cnf.data[i] = net->ipv4_devconf_dflt->data[i];
++                      in_dev->cnf.data[i] = ipv4_devconf_dflt.data[i];
+               rcu_read_unlock();
        }
--      err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
-+      err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
- errout:
-       if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
-+              rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err);
- }
+       read_unlock(&dev_base_lock);
+@@ -1279,13 +1274,12 @@
  
- static inline size_t inet6_prefix_nlmsg_size(void)
-@@ -3730,10 +3764,10 @@
-               kfree_skb(skb);
-               goto errout;
+       if (write) {
+               struct ipv4_devconf *cnf = ctl->extra1;
+-              struct net *net = ctl->extra2;
+               int i = (int *)ctl->data - cnf->data;
+               set_bit(i, cnf->state);
+-              if (cnf == net->ipv4_devconf_dflt)
+-                      devinet_copy_dflt_conf(net, i);
++              if (cnf == &ipv4_devconf_dflt)
++                      devinet_copy_dflt_conf(i);
        }
--      err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
-+      err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
- errout:
-       if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_IPV6_PREFIX, err);
-+              rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_PREFIX, err);
- }
  
- static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
-@@ -4244,16 +4278,16 @@
-        * device and it being up should be removed.
-        */
-       rtnl_lock();
--      if (!ipv6_add_dev(&loopback_dev))
-+      if (!ipv6_add_dev(&init_net.loopback_dev))
-               err = -ENOMEM;
-       rtnl_unlock();
-       if (err)
-               return err;
+       return ret;
+@@ -1297,7 +1291,6 @@
+ {
+       struct ipv4_devconf *cnf;
+       int *valp = table->data;
+-      struct net *net;
+       int new;
+       int i;
  
--      ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);
-+      ip6_null_entry.rt6i_idev = in6_dev_get(&init_net.loopback_dev);
- #ifdef CONFIG_IPV6_MULTIPLE_TABLES
--      ip6_prohibit_entry.rt6i_idev = in6_dev_get(&loopback_dev);
--      ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&loopback_dev);
-+      ip6_prohibit_entry.rt6i_idev = in6_dev_get(&init_net.loopback_dev);
-+      ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&init_net.loopback_dev);
- #endif
+@@ -1332,27 +1325,26 @@
+       *valp = new;
  
-       register_netdevice_notifier(&ipv6_dev_notf);
-@@ -4304,12 +4338,12 @@
-        *      clean dev list.
-        */
+       cnf = table->extra1;
+-      net = table->extra2;
+       i = (int *)table->data - cnf->data;
  
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if ((idev = __in6_dev_get(dev)) == NULL)
-                       continue;
-               addrconf_ifdown(dev, 1);
-       }
--      addrconf_ifdown(&loopback_dev, 2);
-+      addrconf_ifdown(&init_net.loopback_dev, 2);
+       set_bit(i, cnf->state);
  
-       /*
-        *      Check hash table.
-@@ -4335,6 +4369,6 @@
-       rtnl_unlock();
+-      if (cnf == net->ipv4_devconf_dflt)
+-              devinet_copy_dflt_conf(net, i);
++      if (cnf == &ipv4_devconf_dflt)
++              devinet_copy_dflt_conf(i);
  
- #ifdef CONFIG_PROC_FS
--      proc_net_remove("if_inet6");
-+      proc_net_remove(&init_net, "if_inet6");
- #endif
- }
-diff -Nurb linux-2.6.22-570/net/ipv6/addrconf.c.orig linux-2.6.22-590/net/ipv6/addrconf.c.orig
---- linux-2.6.22-570/net/ipv6/addrconf.c.orig  2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/addrconf.c.orig  1969-12-31 19:00:00.000000000 -0500
-@@ -1,4301 +0,0 @@
--/*
-- *    IPv6 Address [auto]configuration
-- *    Linux INET6 implementation
-- *
-- *    Authors:
-- *    Pedro Roque             <roque@di.fc.ul.pt>
-- *    Alexey Kuznetsov        <kuznet@ms2.inr.ac.ru>
-- *
-- *    $Id: addrconf.c,v 1.69 2001/10/31 21:55:54 davem Exp $
-- *
-- *    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.
-- */
--
--/*
-- *    Changes:
-- *
-- *    Janos Farkas                    :       delete timer on ifdown
-- *    <chexum@bankinf.banki.hu>
-- *    Andi Kleen                      :       kill double kfree on module
-- *                                            unload.
-- *    Maciej W. Rozycki               :       FDDI support
-- *    sekiya@USAGI                    :       Don't send too many RS
-- *                                            packets.
-- *    yoshfuji@USAGI                  :       Fixed interval between DAD
-- *                                            packets.
-- *    YOSHIFUJI Hideaki @USAGI        :       improved accuracy of
-- *                                            address validation timer.
-- *    YOSHIFUJI Hideaki @USAGI        :       Privacy Extensions (RFC3041)
-- *                                            support.
-- *    Yuji SEKIYA @USAGI              :       Don't assign a same IPv6
-- *                                            address on a same interface.
-- *    YOSHIFUJI Hideaki @USAGI        :       ARCnet support
-- *    YOSHIFUJI Hideaki @USAGI        :       convert /proc/net/if_inet6 to
-- *                                            seq_file.
-- *    YOSHIFUJI Hideaki @USAGI        :       improved source address
-- *                                            selection; consider scope,
-- *                                            status etc.
-- */
--
--#include <linux/errno.h>
--#include <linux/types.h>
--#include <linux/socket.h>
--#include <linux/sockios.h>
--#include <linux/net.h>
--#include <linux/in6.h>
--#include <linux/netdevice.h>
--#include <linux/if_addr.h>
--#include <linux/if_arp.h>
--#include <linux/if_arcnet.h>
--#include <linux/if_infiniband.h>
--#include <linux/route.h>
--#include <linux/inetdevice.h>
--#include <linux/init.h>
--#ifdef CONFIG_SYSCTL
--#include <linux/sysctl.h>
--#endif
--#include <linux/capability.h>
--#include <linux/delay.h>
--#include <linux/notifier.h>
--#include <linux/string.h>
--
--#include <net/sock.h>
--#include <net/snmp.h>
--
--#include <net/ipv6.h>
--#include <net/protocol.h>
--#include <net/ndisc.h>
--#include <net/ip6_route.h>
--#include <net/addrconf.h>
--#include <net/tcp.h>
--#include <net/ip.h>
--#include <net/netlink.h>
--#include <net/pkt_sched.h>
--#include <linux/if_tunnel.h>
--#include <linux/rtnetlink.h>
--
--#ifdef CONFIG_IPV6_PRIVACY
--#include <linux/random.h>
--#endif
--
--#include <asm/uaccess.h>
--#include <asm/unaligned.h>
--
--#include <linux/proc_fs.h>
--#include <linux/seq_file.h>
--
--/* Set to 3 to get tracing... */
--#define ACONF_DEBUG 2
--
--#if ACONF_DEBUG >= 3
--#define ADBG(x) printk x
--#else
--#define ADBG(x)
--#endif
--
--#define       INFINITY_LIFE_TIME      0xFFFFFFFF
--#define TIME_DELTA(a,b) ((unsigned long)((long)(a) - (long)(b)))
--
--#ifdef CONFIG_SYSCTL
--static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf *p);
--static void addrconf_sysctl_unregister(struct ipv6_devconf *p);
--#endif
--
--#ifdef CONFIG_IPV6_PRIVACY
--static int __ipv6_regen_rndid(struct inet6_dev *idev);
--static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
--static void ipv6_regen_rndid(unsigned long data);
--
--static int desync_factor = MAX_DESYNC_FACTOR * HZ;
--#endif
--
--static int ipv6_count_addresses(struct inet6_dev *idev);
--
--/*
-- *    Configured unicast address hash table
-- */
--static struct inet6_ifaddr            *inet6_addr_lst[IN6_ADDR_HSIZE];
--static DEFINE_RWLOCK(addrconf_hash_lock);
--
--static void addrconf_verify(unsigned long);
--
--static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0);
--static DEFINE_SPINLOCK(addrconf_verify_lock);
--
--static void addrconf_join_anycast(struct inet6_ifaddr *ifp);
--static void addrconf_leave_anycast(struct inet6_ifaddr *ifp);
--
--static int addrconf_ifdown(struct net_device *dev, int how);
--
--static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags);
--static void addrconf_dad_timer(unsigned long data);
--static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
--static void addrconf_dad_run(struct inet6_dev *idev);
--static void addrconf_rs_timer(unsigned long data);
--static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
--static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
--
--static void inet6_prefix_notify(int event, struct inet6_dev *idev,
--                              struct prefix_info *pinfo);
--static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev);
--
--static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
--
--struct ipv6_devconf ipv6_devconf __read_mostly = {
--      .forwarding             = 0,
--      .hop_limit              = IPV6_DEFAULT_HOPLIMIT,
--      .mtu6                   = IPV6_MIN_MTU,
--      .accept_ra              = 1,
--      .accept_redirects       = 1,
--      .autoconf               = 1,
--      .force_mld_version      = 0,
--      .dad_transmits          = 1,
--      .rtr_solicits           = MAX_RTR_SOLICITATIONS,
--      .rtr_solicit_interval   = RTR_SOLICITATION_INTERVAL,
--      .rtr_solicit_delay      = MAX_RTR_SOLICITATION_DELAY,
--#ifdef CONFIG_IPV6_PRIVACY
--      .use_tempaddr           = 0,
--      .temp_valid_lft         = TEMP_VALID_LIFETIME,
--      .temp_prefered_lft      = TEMP_PREFERRED_LIFETIME,
--      .regen_max_retry        = REGEN_MAX_RETRY,
--      .max_desync_factor      = MAX_DESYNC_FACTOR,
--#endif
--      .max_addresses          = IPV6_MAX_ADDRESSES,
--      .accept_ra_defrtr       = 1,
--      .accept_ra_pinfo        = 1,
--#ifdef CONFIG_IPV6_ROUTER_PREF
--      .accept_ra_rtr_pref     = 1,
--      .rtr_probe_interval     = 60 * HZ,
--#ifdef CONFIG_IPV6_ROUTE_INFO
--      .accept_ra_rt_info_max_plen = 0,
--#endif
--#endif
--      .proxy_ndp              = 0,
--      .accept_source_route    = 0,    /* we do not accept RH0 by default. */
--};
--
--static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
--      .forwarding             = 0,
--      .hop_limit              = IPV6_DEFAULT_HOPLIMIT,
--      .mtu6                   = IPV6_MIN_MTU,
--      .accept_ra              = 1,
--      .accept_redirects       = 1,
--      .autoconf               = 1,
--      .dad_transmits          = 1,
--      .rtr_solicits           = MAX_RTR_SOLICITATIONS,
--      .rtr_solicit_interval   = RTR_SOLICITATION_INTERVAL,
--      .rtr_solicit_delay      = MAX_RTR_SOLICITATION_DELAY,
--#ifdef CONFIG_IPV6_PRIVACY
--      .use_tempaddr           = 0,
--      .temp_valid_lft         = TEMP_VALID_LIFETIME,
--      .temp_prefered_lft      = TEMP_PREFERRED_LIFETIME,
--      .regen_max_retry        = REGEN_MAX_RETRY,
--      .max_desync_factor      = MAX_DESYNC_FACTOR,
--#endif
--      .max_addresses          = IPV6_MAX_ADDRESSES,
--      .accept_ra_defrtr       = 1,
--      .accept_ra_pinfo        = 1,
--#ifdef CONFIG_IPV6_ROUTER_PREF
--      .accept_ra_rtr_pref     = 1,
--      .rtr_probe_interval     = 60 * HZ,
--#ifdef CONFIG_IPV6_ROUTE_INFO
--      .accept_ra_rt_info_max_plen = 0,
--#endif
--#endif
--      .proxy_ndp              = 0,
--      .accept_source_route    = 0,    /* we do not accept RH0 by default. */
--};
--
--/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
--const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
--const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
--
--/* Check if a valid qdisc is available */
--static inline int addrconf_qdisc_ok(struct net_device *dev)
--{
--      return (dev->qdisc != &noop_qdisc);
--}
--
--static void addrconf_del_timer(struct inet6_ifaddr *ifp)
--{
--      if (del_timer(&ifp->timer))
--              __in6_ifa_put(ifp);
--}
--
--enum addrconf_timer_t
--{
--      AC_NONE,
--      AC_DAD,
--      AC_RS,
--};
--
--static void addrconf_mod_timer(struct inet6_ifaddr *ifp,
--                             enum addrconf_timer_t what,
--                             unsigned long when)
--{
--      if (!del_timer(&ifp->timer))
--              in6_ifa_hold(ifp);
--
--      switch (what) {
--      case AC_DAD:
--              ifp->timer.function = addrconf_dad_timer;
--              break;
--      case AC_RS:
--              ifp->timer.function = addrconf_rs_timer;
--              break;
--      default:;
--      }
--      ifp->timer.expires = jiffies + when;
--      add_timer(&ifp->timer);
--}
--
--static int snmp6_alloc_dev(struct inet6_dev *idev)
--{
--      int err = -ENOMEM;
--
--      if (!idev || !idev->dev)
--              return -EINVAL;
--
--      if (snmp_mib_init((void **)idev->stats.ipv6,
--                        sizeof(struct ipstats_mib),
--                        __alignof__(struct ipstats_mib)) < 0)
--              goto err_ip;
--      if (snmp_mib_init((void **)idev->stats.icmpv6,
--                        sizeof(struct icmpv6_mib),
--                        __alignof__(struct icmpv6_mib)) < 0)
--              goto err_icmp;
--
--      return 0;
--
--err_icmp:
--      snmp_mib_free((void **)idev->stats.ipv6);
--err_ip:
--      return err;
--}
--
--static int snmp6_free_dev(struct inet6_dev *idev)
--{
--      snmp_mib_free((void **)idev->stats.icmpv6);
--      snmp_mib_free((void **)idev->stats.ipv6);
--      return 0;
--}
--
--/* Nobody refers to this device, we may destroy it. */
--
--static void in6_dev_finish_destroy_rcu(struct rcu_head *head)
--{
--      struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu);
--      kfree(idev);
--}
--
--void in6_dev_finish_destroy(struct inet6_dev *idev)
--{
--      struct net_device *dev = idev->dev;
--      BUG_TRAP(idev->addr_list==NULL);
--      BUG_TRAP(idev->mc_list==NULL);
--#ifdef NET_REFCNT_DEBUG
--      printk(KERN_DEBUG "in6_dev_finish_destroy: %s\n", dev ? dev->name : "NIL");
--#endif
--      dev_put(dev);
--      if (!idev->dead) {
--              printk("Freeing alive inet6 device %p\n", idev);
--              return;
--      }
--      snmp6_free_dev(idev);
--      call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu);
--}
--
--EXPORT_SYMBOL(in6_dev_finish_destroy);
--
--static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
--{
--      struct inet6_dev *ndev;
--      struct in6_addr maddr;
--
--      ASSERT_RTNL();
--
--      if (dev->mtu < IPV6_MIN_MTU)
--              return NULL;
--
--      ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL);
--
--      if (ndev == NULL)
--              return NULL;
--
--      rwlock_init(&ndev->lock);
--      ndev->dev = dev;
--      memcpy(&ndev->cnf, &ipv6_devconf_dflt, sizeof(ndev->cnf));
--      ndev->cnf.mtu6 = dev->mtu;
--      ndev->cnf.sysctl = NULL;
--      ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
--      if (ndev->nd_parms == NULL) {
--              kfree(ndev);
--              return NULL;
--      }
--      /* We refer to the device */
--      dev_hold(dev);
--
--      if (snmp6_alloc_dev(ndev) < 0) {
--              ADBG((KERN_WARNING
--                      "%s(): cannot allocate memory for statistics; dev=%s.\n",
--                      __FUNCTION__, dev->name));
--              neigh_parms_release(&nd_tbl, ndev->nd_parms);
--              ndev->dead = 1;
--              in6_dev_finish_destroy(ndev);
--              return NULL;
--      }
--
--      if (snmp6_register_dev(ndev) < 0) {
--              ADBG((KERN_WARNING
--                      "%s(): cannot create /proc/net/dev_snmp6/%s\n",
--                      __FUNCTION__, dev->name));
--              neigh_parms_release(&nd_tbl, ndev->nd_parms);
--              ndev->dead = 1;
--              in6_dev_finish_destroy(ndev);
--              return NULL;
--      }
--
--      /* One reference from device.  We must do this before
--       * we invoke __ipv6_regen_rndid().
--       */
--      in6_dev_hold(ndev);
--
--#ifdef CONFIG_IPV6_PRIVACY
--      init_timer(&ndev->regen_timer);
--      ndev->regen_timer.function = ipv6_regen_rndid;
--      ndev->regen_timer.data = (unsigned long) ndev;
--      if ((dev->flags&IFF_LOOPBACK) ||
--          dev->type == ARPHRD_TUNNEL ||
--#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
--          dev->type == ARPHRD_SIT ||
--#endif
--          dev->type == ARPHRD_NONE) {
--              printk(KERN_INFO
--                     "%s: Disabled Privacy Extensions\n",
--                     dev->name);
--              ndev->cnf.use_tempaddr = -1;
--      } else {
--              in6_dev_hold(ndev);
--              ipv6_regen_rndid((unsigned long) ndev);
--      }
--#endif
--
--      if (netif_running(dev) && addrconf_qdisc_ok(dev))
--              ndev->if_flags |= IF_READY;
--
--      ipv6_mc_init_dev(ndev);
--      ndev->tstamp = jiffies;
--#ifdef CONFIG_SYSCTL
--      neigh_sysctl_register(dev, ndev->nd_parms, NET_IPV6,
--                            NET_IPV6_NEIGH, "ipv6",
--                            &ndisc_ifinfo_sysctl_change,
--                            NULL);
--      addrconf_sysctl_register(ndev, &ndev->cnf);
--#endif
--      /* protected by rtnl_lock */
--      rcu_assign_pointer(dev->ip6_ptr, ndev);
--
--      /* Join all-node multicast group */
--      ipv6_addr_all_nodes(&maddr);
--      ipv6_dev_mc_inc(dev, &maddr);
--
--      return ndev;
--}
--
--static struct inet6_dev * ipv6_find_idev(struct net_device *dev)
--{
--      struct inet6_dev *idev;
--
--      ASSERT_RTNL();
--
--      if ((idev = __in6_dev_get(dev)) == NULL) {
--              if ((idev = ipv6_add_dev(dev)) == NULL)
--                      return NULL;
--      }
--
--      if (dev->flags&IFF_UP)
--              ipv6_mc_up(idev);
--      return idev;
--}
--
--#ifdef CONFIG_SYSCTL
--static void dev_forward_change(struct inet6_dev *idev)
--{
--      struct net_device *dev;
--      struct inet6_ifaddr *ifa;
--      struct in6_addr addr;
--
--      if (!idev)
--              return;
--      dev = idev->dev;
--      if (dev && (dev->flags & IFF_MULTICAST)) {
--              ipv6_addr_all_routers(&addr);
--
--              if (idev->cnf.forwarding)
--                      ipv6_dev_mc_inc(dev, &addr);
--              else
--                      ipv6_dev_mc_dec(dev, &addr);
--      }
--      for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
--              if (ifa->flags&IFA_F_TENTATIVE)
--                      continue;
--              if (idev->cnf.forwarding)
--                      addrconf_join_anycast(ifa);
--              else
--                      addrconf_leave_anycast(ifa);
--      }
--}
--
--
--static void addrconf_forward_change(void)
--{
--      struct net_device *dev;
--      struct inet6_dev *idev;
--
--      read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
--              rcu_read_lock();
--              idev = __in6_dev_get(dev);
--              if (idev) {
--                      int changed = (!idev->cnf.forwarding) ^ (!ipv6_devconf.forwarding);
--                      idev->cnf.forwarding = ipv6_devconf.forwarding;
--                      if (changed)
--                              dev_forward_change(idev);
--              }
--              rcu_read_unlock();
--      }
--      read_unlock(&dev_base_lock);
--}
--#endif
--
--/* Nobody refers to this ifaddr, destroy it */
--
--void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
--{
--      BUG_TRAP(ifp->if_next==NULL);
--      BUG_TRAP(ifp->lst_next==NULL);
--#ifdef NET_REFCNT_DEBUG
--      printk(KERN_DEBUG "inet6_ifa_finish_destroy\n");
--#endif
--
--      in6_dev_put(ifp->idev);
--
--      if (del_timer(&ifp->timer))
--              printk("Timer is still running, when freeing ifa=%p\n", ifp);
--
--      if (!ifp->dead) {
--              printk("Freeing alive inet6 address %p\n", ifp);
--              return;
--      }
--      dst_release(&ifp->rt->u.dst);
--
--      kfree(ifp);
--}
--
--static void
--ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp)
--{
--      struct inet6_ifaddr *ifa, **ifap;
--      int ifp_scope = ipv6_addr_src_scope(&ifp->addr);
--
--      /*
--       * Each device address list is sorted in order of scope -
--       * global before linklocal.
--       */
--      for (ifap = &idev->addr_list; (ifa = *ifap) != NULL;
--           ifap = &ifa->if_next) {
--              if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr))
--                      break;
--      }
--
--      ifp->if_next = *ifap;
--      *ifap = ifp;
--}
--
--/* On success it returns ifp with increased reference count */
--
--static struct inet6_ifaddr *
--ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
--            int scope, u32 flags)
--{
--      struct inet6_ifaddr *ifa = NULL;
--      struct rt6_info *rt;
--      int hash;
--      int err = 0;
--
--      rcu_read_lock_bh();
--      if (idev->dead) {
--              err = -ENODEV;                  /*XXX*/
--              goto out2;
--      }
--
--      write_lock(&addrconf_hash_lock);
--
--      /* Ignore adding duplicate addresses on an interface */
--      if (ipv6_chk_same_addr(addr, idev->dev)) {
--              ADBG(("ipv6_add_addr: already assigned\n"));
--              err = -EEXIST;
--              goto out;
--      }
--
--      ifa = kzalloc(sizeof(struct inet6_ifaddr), GFP_ATOMIC);
--
--      if (ifa == NULL) {
--              ADBG(("ipv6_add_addr: malloc failed\n"));
--              err = -ENOBUFS;
--              goto out;
--      }
--
--      rt = addrconf_dst_alloc(idev, addr, 0);
--      if (IS_ERR(rt)) {
--              err = PTR_ERR(rt);
--              goto out;
--      }
--
--      ipv6_addr_copy(&ifa->addr, addr);
--
--      spin_lock_init(&ifa->lock);
--      init_timer(&ifa->timer);
--      ifa->timer.data = (unsigned long) ifa;
--      ifa->scope = scope;
--      ifa->prefix_len = pfxlen;
--      ifa->flags = flags | IFA_F_TENTATIVE;
--      ifa->cstamp = ifa->tstamp = jiffies;
--
--      ifa->rt = rt;
--
--      /*
--       * part one of RFC 4429, section 3.3
--       * We should not configure an address as
--       * optimistic if we do not yet know the link
--       * layer address of our nexhop router
--       */
--
--      if (rt->rt6i_nexthop == NULL)
--              ifa->flags &= ~IFA_F_OPTIMISTIC;
--
--      ifa->idev = idev;
--      in6_dev_hold(idev);
--      /* For caller */
--      in6_ifa_hold(ifa);
--
--      /* Add to big hash table */
--      hash = ipv6_addr_hash(addr);
--
--      ifa->lst_next = inet6_addr_lst[hash];
--      inet6_addr_lst[hash] = ifa;
--      in6_ifa_hold(ifa);
--      write_unlock(&addrconf_hash_lock);
--
--      write_lock(&idev->lock);
--      /* Add to inet6_dev unicast addr list. */
--      ipv6_link_dev_addr(idev, ifa);
--
--#ifdef CONFIG_IPV6_PRIVACY
--      if (ifa->flags&IFA_F_TEMPORARY) {
--              ifa->tmp_next = idev->tempaddr_list;
--              idev->tempaddr_list = ifa;
--              in6_ifa_hold(ifa);
--      }
--#endif
--
--      in6_ifa_hold(ifa);
--      write_unlock(&idev->lock);
--out2:
--      rcu_read_unlock_bh();
--
--      if (likely(err == 0))
--              atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
--      else {
--              kfree(ifa);
--              ifa = ERR_PTR(err);
--      }
--
--      return ifa;
--out:
--      write_unlock(&addrconf_hash_lock);
--      goto out2;
--}
--
--/* This function wants to get referenced ifp and releases it before return */
--
--static void ipv6_del_addr(struct inet6_ifaddr *ifp)
--{
--      struct inet6_ifaddr *ifa, **ifap;
--      struct inet6_dev *idev = ifp->idev;
--      int hash;
--      int deleted = 0, onlink = 0;
--      unsigned long expires = jiffies;
--
--      hash = ipv6_addr_hash(&ifp->addr);
--
--      ifp->dead = 1;
--
--      write_lock_bh(&addrconf_hash_lock);
--      for (ifap = &inet6_addr_lst[hash]; (ifa=*ifap) != NULL;
--           ifap = &ifa->lst_next) {
--              if (ifa == ifp) {
--                      *ifap = ifa->lst_next;
--                      __in6_ifa_put(ifp);
--                      ifa->lst_next = NULL;
--                      break;
--              }
--      }
--      write_unlock_bh(&addrconf_hash_lock);
--
--      write_lock_bh(&idev->lock);
--#ifdef CONFIG_IPV6_PRIVACY
--      if (ifp->flags&IFA_F_TEMPORARY) {
--              for (ifap = &idev->tempaddr_list; (ifa=*ifap) != NULL;
--                   ifap = &ifa->tmp_next) {
--                      if (ifa == ifp) {
--                              *ifap = ifa->tmp_next;
--                              if (ifp->ifpub) {
--                                      in6_ifa_put(ifp->ifpub);
--                                      ifp->ifpub = NULL;
--                              }
--                              __in6_ifa_put(ifp);
--                              ifa->tmp_next = NULL;
--                              break;
--                      }
--              }
--      }
--#endif
--
--      for (ifap = &idev->addr_list; (ifa=*ifap) != NULL;) {
--              if (ifa == ifp) {
--                      *ifap = ifa->if_next;
--                      __in6_ifa_put(ifp);
--                      ifa->if_next = NULL;
--                      if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0)
--                              break;
--                      deleted = 1;
--                      continue;
--              } else if (ifp->flags & IFA_F_PERMANENT) {
--                      if (ipv6_prefix_equal(&ifa->addr, &ifp->addr,
--                                            ifp->prefix_len)) {
--                              if (ifa->flags & IFA_F_PERMANENT) {
--                                      onlink = 1;
--                                      if (deleted)
--                                              break;
--                              } else {
--                                      unsigned long lifetime;
--
--                                      if (!onlink)
--                                              onlink = -1;
--
--                                      spin_lock(&ifa->lock);
--                                      lifetime = min_t(unsigned long,
--                                                       ifa->valid_lft, 0x7fffffffUL/HZ);
--                                      if (time_before(expires,
--                                                      ifa->tstamp + lifetime * HZ))
--                                              expires = ifa->tstamp + lifetime * HZ;
--                                      spin_unlock(&ifa->lock);
--                              }
--                      }
--              }
--              ifap = &ifa->if_next;
--      }
--      write_unlock_bh(&idev->lock);
--
--      ipv6_ifa_notify(RTM_DELADDR, ifp);
--
--      atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp);
--
--      addrconf_del_timer(ifp);
--
--      /*
--       * Purge or update corresponding prefix
--       *
--       * 1) we don't purge prefix here if address was not permanent.
--       *    prefix is managed by its own lifetime.
--       * 2) if there're no addresses, delete prefix.
--       * 3) if there're still other permanent address(es),
--       *    corresponding prefix is still permanent.
--       * 4) otherwise, update prefix lifetime to the
--       *    longest valid lifetime among the corresponding
--       *    addresses on the device.
--       *    Note: subsequent RA will update lifetime.
--       *
--       * --yoshfuji
--       */
--      if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) {
--              struct in6_addr prefix;
--              struct rt6_info *rt;
--
--              ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
--              rt = rt6_lookup(&prefix, NULL, ifp->idev->dev->ifindex, 1);
--
--              if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
--                      if (onlink == 0) {
--                              ip6_del_rt(rt);
--                              rt = NULL;
--                      } else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
--                              rt->rt6i_expires = expires;
--                              rt->rt6i_flags |= RTF_EXPIRES;
--                      }
--              }
--              dst_release(&rt->u.dst);
--      }
--
--      in6_ifa_put(ifp);
--}
--
--#ifdef CONFIG_IPV6_PRIVACY
--static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *ift)
+       return 1;
+ }
+-void inet_forward_change(struct net *net)
++void inet_forward_change(void)
+ {
+       struct net_device *dev;
+-      int on = IPV4_DEVCONF_ALL(net, FORWARDING);
++      int on = IPV4_DEVCONF_ALL(FORWARDING);
+-      IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on;
+-      IPV4_DEVCONF_DFLT(net, FORWARDING) = on;
++      IPV4_DEVCONF_ALL(ACCEPT_REDIRECTS) = !on;
++      IPV4_DEVCONF_DFLT(FORWARDING) = on;
+       read_lock(&dev_base_lock);
+-      for_each_netdev(net, dev) {
++      for_each_netdev(dev) {
+               struct in_device *in_dev;
+               rcu_read_lock();
+               in_dev = __in_dev_get_rcu(dev);
+@@ -1372,12 +1364,11 @@
+       int *valp = ctl->data;
+       int val = *valp;
+       int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+-      struct net *net = ctl->extra2;
+       if (write && *valp != val) {
+-              if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING))
+-                      inet_forward_change(net);
+-              else if (valp != &IPV4_DEVCONF_DFLT(net, FORWARDING))
++              if (valp == &IPV4_DEVCONF_ALL(FORWARDING))
++                      inet_forward_change();
++              else if (valp != &IPV4_DEVCONF_DFLT(FORWARDING))
+                       rt_cache_flush(0);
+       }
+@@ -1416,14 +1407,13 @@
+       { \
+               .ctl_name       = NET_IPV4_CONF_ ## attr, \
+               .procname       = name, \
+-              .data           = ipv4_devconf_template.data + \
++              .data           = ipv4_devconf.data + \
+                                 NET_IPV4_CONF_ ## attr - 1, \
+               .maxlen         = sizeof(int), \
+               .mode           = mval, \
+               .proc_handler   = proc, \
+               .strategy       = sysctl, \
+-              .extra1         = &ipv4_devconf_template, \
+-              .extra2         = &init_net, \
++              .extra1         = &ipv4_devconf, \
+       }
+ #define DEVINET_SYSCTL_RW_ENTRY(attr, name) \
+@@ -1513,29 +1503,25 @@
+       },
+ };
+-static void devinet_sysctl_register(struct net *net, struct in_device *in_dev,
++static void devinet_sysctl_register(struct in_device *in_dev,
+                                   struct ipv4_devconf *p)
+ {
+       int i;
+       struct net_device *dev = in_dev ? in_dev->dev : NULL;
+-      struct devinet_sysctl_table *t;
++      struct devinet_sysctl_table *t = kmemdup(&devinet_sysctl, sizeof(*t),
++                                               GFP_KERNEL);
+       char *dev_name = NULL;
+-      t = kmemdup(&devinet_sysctl, sizeof(*t), GFP_KERNEL);
+       if (!t)
+               return;
+       for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
+-              t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf_template;
++              t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
+               t->devinet_vars[i].extra1 = p;
+-              t->devinet_vars[i].extra2 = net;
+       }
+       if (dev) {
+               dev_name = dev->name;
+               t->devinet_dev[0].ctl_name = dev->ifindex;
+-      } else if (p == net->ipv4_devconf) {
+-              dev_name = "all";
+-              t->devinet_dev[0].ctl_name = NET_PROTO_CONF_ALL;
+       } else {
+               dev_name = "default";
+               t->devinet_dev[0].ctl_name = NET_PROTO_CONF_DEFAULT;
+@@ -1556,7 +1542,7 @@
+       t->devinet_proto_dir[0].child = t->devinet_conf_dir;
+       t->devinet_root_dir[0].child  = t->devinet_proto_dir;
+-      t->sysctl_header = register_net_sysctl_table(net, t->devinet_root_dir);
++      t->sysctl_header = register_sysctl_table(t->devinet_root_dir);
+       if (!t->sysctl_header)
+           goto free_procname;
+@@ -1576,59 +1562,26 @@
+       if (p->sysctl) {
+               struct devinet_sysctl_table *t = p->sysctl;
+               p->sysctl = NULL;
+-              unregister_net_sysctl_table(t->sysctl_header);
++              unregister_sysctl_table(t->sysctl_header);
+               kfree(t->devinet_dev[0].procname);
+               kfree(t);
+       }
+ }
+ #endif
+-static int devinet_net_init(struct net *net)
 -{
--      struct inet6_dev *idev = ifp->idev;
--      struct in6_addr addr, *tmpaddr;
--      unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp;
--      int tmp_plen;
--      int ret = 0;
--      int max_addresses;
--      u32 addr_flags;
--
--      write_lock(&idev->lock);
--      if (ift) {
--              spin_lock_bh(&ift->lock);
--              memcpy(&addr.s6_addr[8], &ift->addr.s6_addr[8], 8);
--              spin_unlock_bh(&ift->lock);
--              tmpaddr = &addr;
--      } else {
--              tmpaddr = NULL;
--      }
--retry:
--      in6_dev_hold(idev);
--      if (idev->cnf.use_tempaddr <= 0) {
--              write_unlock(&idev->lock);
--              printk(KERN_INFO
--                      "ipv6_create_tempaddr(): use_tempaddr is disabled.\n");
--              in6_dev_put(idev);
--              ret = -1;
--              goto out;
--      }
--      spin_lock_bh(&ifp->lock);
--      if (ifp->regen_count++ >= idev->cnf.regen_max_retry) {
--              idev->cnf.use_tempaddr = -1;    /*XXX*/
--              spin_unlock_bh(&ifp->lock);
--              write_unlock(&idev->lock);
--              printk(KERN_WARNING
--                      "ipv6_create_tempaddr(): regeneration time exceeded. disabled temporary address support.\n");
--              in6_dev_put(idev);
--              ret = -1;
--              goto out;
--      }
--      in6_ifa_hold(ifp);
--      memcpy(addr.s6_addr, ifp->addr.s6_addr, 8);
--      if (__ipv6_try_regen_rndid(idev, tmpaddr) < 0) {
--              spin_unlock_bh(&ifp->lock);
--              write_unlock(&idev->lock);
--              printk(KERN_WARNING
--                      "ipv6_create_tempaddr(): regeneration of randomized interface id failed.\n");
--              in6_ifa_put(ifp);
--              in6_dev_put(idev);
--              ret = -1;
--              goto out;
--      }
--      memcpy(&addr.s6_addr[8], idev->rndid, 8);
--      tmp_valid_lft = min_t(__u32,
--                            ifp->valid_lft,
--                            idev->cnf.temp_valid_lft);
--      tmp_prefered_lft = min_t(__u32,
--                               ifp->prefered_lft,
--                               idev->cnf.temp_prefered_lft - desync_factor / HZ);
--      tmp_plen = ifp->prefix_len;
--      max_addresses = idev->cnf.max_addresses;
--      tmp_cstamp = ifp->cstamp;
--      tmp_tstamp = ifp->tstamp;
--      spin_unlock_bh(&ifp->lock);
--
--      write_unlock(&idev->lock);
--
--      addr_flags = IFA_F_TEMPORARY;
--      /* set in addrconf_prefix_rcv() */
--      if (ifp->flags & IFA_F_OPTIMISTIC)
--              addr_flags |= IFA_F_OPTIMISTIC;
--
--      ift = !max_addresses ||
--            ipv6_count_addresses(idev) < max_addresses ?
--              ipv6_add_addr(idev, &addr, tmp_plen,
--                            ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK,
--                            addr_flags) : NULL;
--      if (!ift || IS_ERR(ift)) {
--              in6_ifa_put(ifp);
--              in6_dev_put(idev);
--              printk(KERN_INFO
--                      "ipv6_create_tempaddr(): retry temporary address regeneration.\n");
--              tmpaddr = &addr;
--              write_lock(&idev->lock);
--              goto retry;
+-#ifdef CONFIG_SYSCTL
+-      net->ipv4_devconf = kmemdup(&ipv4_devconf_template, 
+-                                  sizeof(ipv4_devconf_template), GFP_KERNEL);
+-      if (!net->ipv4_devconf)
+-              return -ENOMEM;
+-      
+-      net->ipv4_devconf_dflt = kmemdup(&ipv4_devconf_dflt_template, 
+-                                       sizeof(ipv4_devconf_template),
+-                                       GFP_KERNEL);
+-      if (!net->ipv4_devconf_dflt) {
+-              kfree(net->ipv4_devconf);
+-              return -ENOMEM;
 -      }
 -
--      spin_lock_bh(&ift->lock);
--      ift->ifpub = ifp;
--      ift->valid_lft = tmp_valid_lft;
--      ift->prefered_lft = tmp_prefered_lft;
--      ift->cstamp = tmp_cstamp;
--      ift->tstamp = tmp_tstamp;
--      spin_unlock_bh(&ift->lock);
+-      devinet_sysctl_register(net, NULL, net->ipv4_devconf);
+-      devinet_sysctl_register(net, NULL, net->ipv4_devconf_dflt);
 -
--      addrconf_dad_start(ift, 0);
--      in6_ifa_put(ift);
--      in6_dev_put(idev);
--out:
--      return ret;
--}
+-      multi_ipv4_table[0].data = &IPV4_DEVCONF_ALL(net, FORWARDING);
 -#endif
--
--/*
-- *    Choose an appropriate source address (RFC3484)
-- */
--struct ipv6_saddr_score {
--      int             addr_type;
--      unsigned int    attrs;
--      int             matchlen;
--      int             scope;
--      unsigned int    rule;
--};
--
--#define IPV6_SADDR_SCORE_LOCAL                0x0001
--#define IPV6_SADDR_SCORE_PREFERRED    0x0004
--#define IPV6_SADDR_SCORE_HOA          0x0008
--#define IPV6_SADDR_SCORE_OIF          0x0010
--#define IPV6_SADDR_SCORE_LABEL                0x0020
--#define IPV6_SADDR_SCORE_PRIVACY      0x0040
--
--static inline int ipv6_saddr_preferred(int type)
--{
--      if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4|
--                  IPV6_ADDR_LOOPBACK|IPV6_ADDR_RESERVED))
--              return 1;
 -      return 0;
 -}
 -
--/* static matching label */
--static inline int ipv6_saddr_label(const struct in6_addr *addr, int type)
--{
-- /*
--  *   prefix (longest match)  label
--  *   -----------------------------
--  *   ::1/128                 0
--  *   ::/0                    1
--  *   2002::/16               2
--  *   ::/96                   3
--  *   ::ffff:0:0/96           4
--  *   fc00::/7                5
--  *   2001::/32               6
--  */
--      if (type & IPV6_ADDR_LOOPBACK)
--              return 0;
--      else if (type & IPV6_ADDR_COMPATv4)
--              return 3;
--      else if (type & IPV6_ADDR_MAPPED)
--              return 4;
--      else if (addr->s6_addr32[0] == htonl(0x20010000))
--              return 6;
--      else if (addr->s6_addr16[0] == htons(0x2002))
--              return 2;
--      else if ((addr->s6_addr[0] & 0xfe) == 0xfc)
--              return 5;
--      return 1;
--}
--
--int ipv6_dev_get_saddr(struct net_device *daddr_dev,
--                     struct in6_addr *daddr, struct in6_addr *saddr)
+-static void devinet_net_exit(struct net *net)
 -{
--      struct ipv6_saddr_score hiscore;
--      struct inet6_ifaddr *ifa_result = NULL;
--      int daddr_type = __ipv6_addr_type(daddr);
--      int daddr_scope = __ipv6_addr_src_scope(daddr_type);
--      u32 daddr_label = ipv6_saddr_label(daddr, daddr_type);
--      struct net_device *dev;
--
--      memset(&hiscore, 0, sizeof(hiscore));
--
--      read_lock(&dev_base_lock);
--      rcu_read_lock();
--
--      for_each_netdev(dev) {
--              struct inet6_dev *idev;
--              struct inet6_ifaddr *ifa;
--
--              /* Rule 0: Candidate Source Address (section 4)
--               *  - multicast and link-local destination address,
--               *    the set of candidate source address MUST only
--               *    include addresses assigned to interfaces
--               *    belonging to the same link as the outgoing
--               *    interface.
--               * (- For site-local destination addresses, the
--               *    set of candidate source addresses MUST only
--               *    include addresses assigned to interfaces
--               *    belonging to the same site as the outgoing
--               *    interface.)
--               */
--              if ((daddr_type & IPV6_ADDR_MULTICAST ||
--                   daddr_scope <= IPV6_ADDR_SCOPE_LINKLOCAL) &&
--                  daddr_dev && dev != daddr_dev)
--                      continue;
--
--              idev = __in6_dev_get(dev);
--              if (!idev)
--                      continue;
--
--              read_lock_bh(&idev->lock);
--              for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) {
--                      struct ipv6_saddr_score score;
--
--                      score.addr_type = __ipv6_addr_type(&ifa->addr);
--
--                      /* Rule 0:
--                       * - Tentative Address (RFC2462 section 5.4)
--                       *  - A tentative address is not considered
--                       *    "assigned to an interface" in the traditional
--                       *    sense, unless it is also flagged as optimistic.
--                       * - Candidate Source Address (section 4)
--                       *  - In any case, anycast addresses, multicast
--                       *    addresses, and the unspecified address MUST
--                       *    NOT be included in a candidate set.
--                       */
--                      if ((ifa->flags & IFA_F_TENTATIVE) &&
--                          (!(ifa->flags & IFA_F_OPTIMISTIC)))
--                              continue;
--                      if (unlikely(score.addr_type == IPV6_ADDR_ANY ||
--                                   score.addr_type & IPV6_ADDR_MULTICAST)) {
--                              LIMIT_NETDEBUG(KERN_DEBUG
--                                             "ADDRCONF: unspecified / multicast address"
--                                             "assigned as unicast address on %s",
--                                             dev->name);
--                              continue;
--                      }
--
--                      score.attrs = 0;
--                      score.matchlen = 0;
--                      score.scope = 0;
--                      score.rule = 0;
--
--                      if (ifa_result == NULL) {
--                              /* record it if the first available entry */
--                              goto record_it;
--                      }
--
--                      /* Rule 1: Prefer same address */
--                      if (hiscore.rule < 1) {
--                              if (ipv6_addr_equal(&ifa_result->addr, daddr))
--                                      hiscore.attrs |= IPV6_SADDR_SCORE_LOCAL;
--                              hiscore.rule++;
--                      }
--                      if (ipv6_addr_equal(&ifa->addr, daddr)) {
--                              score.attrs |= IPV6_SADDR_SCORE_LOCAL;
--                              if (!(hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)) {
--                                      score.rule = 1;
--                                      goto record_it;
--                              }
--                      } else {
--                              if (hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)
--                                      continue;
--                      }
--
--                      /* Rule 2: Prefer appropriate scope */
--                      if (hiscore.rule < 2) {
--                              hiscore.scope = __ipv6_addr_src_scope(hiscore.addr_type);
--                              hiscore.rule++;
--                      }
--                      score.scope = __ipv6_addr_src_scope(score.addr_type);
--                      if (hiscore.scope < score.scope) {
--                              if (hiscore.scope < daddr_scope) {
--                                      score.rule = 2;
--                                      goto record_it;
--                              } else
--                                      continue;
--                      } else if (score.scope < hiscore.scope) {
--                              if (score.scope < daddr_scope)
--                                      break; /* addresses sorted by scope */
--                              else {
--                                      score.rule = 2;
--                                      goto record_it;
--                              }
--                      }
--
--                      /* Rule 3: Avoid deprecated and optimistic addresses */
--                      if (hiscore.rule < 3) {
--                              if (ipv6_saddr_preferred(hiscore.addr_type) ||
--                                 (((ifa_result->flags &
--                                  (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0)))
--                                      hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED;
--                              hiscore.rule++;
--                      }
--                      if (ipv6_saddr_preferred(score.addr_type) ||
--                         (((ifa->flags &
--                          (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) {
--                              score.attrs |= IPV6_SADDR_SCORE_PREFERRED;
--                              if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) {
--                                      score.rule = 3;
--                                      goto record_it;
--                              }
--                      } else {
--                              if (hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)
--                                      continue;
--                      }
--
--                      /* Rule 4: Prefer home address */
--#ifdef CONFIG_IPV6_MIP6
--                      if (hiscore.rule < 4) {
--                              if (ifa_result->flags & IFA_F_HOMEADDRESS)
--                                      hiscore.attrs |= IPV6_SADDR_SCORE_HOA;
--                              hiscore.rule++;
--                      }
--                      if (ifa->flags & IFA_F_HOMEADDRESS) {
--                              score.attrs |= IPV6_SADDR_SCORE_HOA;
--                              if (!(ifa_result->flags & IFA_F_HOMEADDRESS)) {
--                                      score.rule = 4;
--                                      goto record_it;
--                              }
--                      } else {
--                              if (hiscore.attrs & IPV6_SADDR_SCORE_HOA)
--                                      continue;
--                      }
--#else
--                      if (hiscore.rule < 4)
--                              hiscore.rule++;
--#endif
--
--                      /* Rule 5: Prefer outgoing interface */
--                      if (hiscore.rule < 5) {
--                              if (daddr_dev == NULL ||
--                                  daddr_dev == ifa_result->idev->dev)
--                                      hiscore.attrs |= IPV6_SADDR_SCORE_OIF;
--                              hiscore.rule++;
--                      }
--                      if (daddr_dev == NULL ||
--                          daddr_dev == ifa->idev->dev) {
--                              score.attrs |= IPV6_SADDR_SCORE_OIF;
--                              if (!(hiscore.attrs & IPV6_SADDR_SCORE_OIF)) {
--                                      score.rule = 5;
--                                      goto record_it;
--                              }
--                      } else {
--                              if (hiscore.attrs & IPV6_SADDR_SCORE_OIF)
--                                      continue;
--                      }
--
--                      /* Rule 6: Prefer matching label */
--                      if (hiscore.rule < 6) {
--                              if (ipv6_saddr_label(&ifa_result->addr, hiscore.addr_type) == daddr_label)
--                                      hiscore.attrs |= IPV6_SADDR_SCORE_LABEL;
--                              hiscore.rule++;
--                      }
--                      if (ipv6_saddr_label(&ifa->addr, score.addr_type) == daddr_label) {
--                              score.attrs |= IPV6_SADDR_SCORE_LABEL;
--                              if (!(hiscore.attrs & IPV6_SADDR_SCORE_LABEL)) {
--                                      score.rule = 6;
--                                      goto record_it;
--                              }
--                      } else {
--                              if (hiscore.attrs & IPV6_SADDR_SCORE_LABEL)
--                                      continue;
--                      }
--
--#ifdef CONFIG_IPV6_PRIVACY
--                      /* Rule 7: Prefer public address
--                       * Note: prefer temprary address if use_tempaddr >= 2
--                       */
--                      if (hiscore.rule < 7) {
--                              if ((!(ifa_result->flags & IFA_F_TEMPORARY)) ^
--                                  (ifa_result->idev->cnf.use_tempaddr >= 2))
--                                      hiscore.attrs |= IPV6_SADDR_SCORE_PRIVACY;
--                              hiscore.rule++;
--                      }
--                      if ((!(ifa->flags & IFA_F_TEMPORARY)) ^
--                          (ifa->idev->cnf.use_tempaddr >= 2)) {
--                              score.attrs |= IPV6_SADDR_SCORE_PRIVACY;
--                              if (!(hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)) {
--                                      score.rule = 7;
--                                      goto record_it;
--                              }
--                      } else {
--                              if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)
--                                      continue;
--                      }
--#else
--                      if (hiscore.rule < 7)
--                              hiscore.rule++;
--#endif
--                      /* Rule 8: Use longest matching prefix */
--                      if (hiscore.rule < 8) {
--                              hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr);
--                              hiscore.rule++;
--                      }
--                      score.matchlen = ipv6_addr_diff(&ifa->addr, daddr);
--                      if (score.matchlen > hiscore.matchlen) {
--                              score.rule = 8;
--                              goto record_it;
--                      }
--#if 0
--                      else if (score.matchlen < hiscore.matchlen)
--                              continue;
+-#ifdef CONFIG_SYSCTL
+-      devinet_sysctl_unregister(net->ipv4_devconf_dflt);
+-      devinet_sysctl_unregister(net->ipv4_devconf);
 -#endif
--
--                      /* Final Rule: choose first available one */
--                      continue;
--record_it:
--                      if (ifa_result)
--                              in6_ifa_put(ifa_result);
--                      in6_ifa_hold(ifa);
--                      ifa_result = ifa;
--                      hiscore = score;
--              }
--              read_unlock_bh(&idev->lock);
--      }
--      rcu_read_unlock();
--      read_unlock(&dev_base_lock);
--
--      if (!ifa_result)
--              return -EADDRNOTAVAIL;
--
--      ipv6_addr_copy(saddr, &ifa_result->addr);
--      in6_ifa_put(ifa_result);
--      return 0;
--}
--
--
--int ipv6_get_saddr(struct dst_entry *dst,
--                 struct in6_addr *daddr, struct in6_addr *saddr)
--{
--      return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr);
--}
--
--EXPORT_SYMBOL(ipv6_get_saddr);
--
--int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
--                  unsigned char banned_flags)
--{
--      struct inet6_dev *idev;
--      int err = -EADDRNOTAVAIL;
--
--      rcu_read_lock();
--      if ((idev = __in6_dev_get(dev)) != NULL) {
--              struct inet6_ifaddr *ifp;
--
--              read_lock_bh(&idev->lock);
--              for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) {
--                      if (ifp->scope == IFA_LINK && !(ifp->flags & banned_flags)) {
--                              ipv6_addr_copy(addr, &ifp->addr);
--                              err = 0;
--                              break;
--                      }
--              }
--              read_unlock_bh(&idev->lock);
--      }
--      rcu_read_unlock();
--      return err;
--}
--
--static int ipv6_count_addresses(struct inet6_dev *idev)
--{
--      int cnt = 0;
--      struct inet6_ifaddr *ifp;
--
--      read_lock_bh(&idev->lock);
--      for (ifp=idev->addr_list; ifp; ifp=ifp->if_next)
--              cnt++;
--      read_unlock_bh(&idev->lock);
--      return cnt;
--}
--
--int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev, int strict)
--{
--      struct inet6_ifaddr * ifp;
--      u8 hash = ipv6_addr_hash(addr);
--
--      read_lock_bh(&addrconf_hash_lock);
--      for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
--              if (ipv6_addr_equal(&ifp->addr, addr) &&
--                  !(ifp->flags&IFA_F_TENTATIVE)) {
--                      if (dev == NULL || ifp->idev->dev == dev ||
--                          !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))
--                              break;
--              }
--      }
--      read_unlock_bh(&addrconf_hash_lock);
--      return ifp != NULL;
--}
--
--EXPORT_SYMBOL(ipv6_chk_addr);
--
--static
--int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev)
--{
--      struct inet6_ifaddr * ifp;
--      u8 hash = ipv6_addr_hash(addr);
--
--      for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
--              if (ipv6_addr_equal(&ifp->addr, addr)) {
--                      if (dev == NULL || ifp->idev->dev == dev)
--                              break;
--              }
--      }
--      return ifp != NULL;
--}
--
--struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device *dev, int strict)
--{
--      struct inet6_ifaddr * ifp;
--      u8 hash = ipv6_addr_hash(addr);
--
--      read_lock_bh(&addrconf_hash_lock);
--      for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
--              if (ipv6_addr_equal(&ifp->addr, addr)) {
--                      if (dev == NULL || ifp->idev->dev == dev ||
--                          !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) {
--                              in6_ifa_hold(ifp);
--                              break;
--                      }
--              }
--      }
--      read_unlock_bh(&addrconf_hash_lock);
--
--      return ifp;
 -}
 -
--int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
--{
--      const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr;
--      const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);
--      __be32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr;
--      __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
--      int sk_ipv6only = ipv6_only_sock(sk);
--      int sk2_ipv6only = inet_v6_ipv6only(sk2);
--      int addr_type = ipv6_addr_type(sk_rcv_saddr6);
--      int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED;
--
--      if (!sk2_rcv_saddr && !sk_ipv6only)
--              return 1;
--
--      if (addr_type2 == IPV6_ADDR_ANY &&
--          !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED))
--              return 1;
--
--      if (addr_type == IPV6_ADDR_ANY &&
--          !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED))
--              return 1;
--
--      if (sk2_rcv_saddr6 &&
--          ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6))
--              return 1;
+-static struct pernet_operations devinet_net_ops = {
+-      .init = devinet_net_init,
+-      .exit = devinet_net_exit,
+-};
 -
--      if (addr_type == IPV6_ADDR_MAPPED &&
--          !sk2_ipv6only &&
--          (!sk2_rcv_saddr || !sk_rcv_saddr || sk_rcv_saddr == sk2_rcv_saddr))
--              return 1;
+ void __init devinet_init(void)
+ {
+-      register_pernet_subsys(&devinet_net_ops);
+       register_gifconf(PF_INET, inet_gifconf);
+       register_netdevice_notifier(&ip_netdev_notifier);
+       rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL);
+       rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL);
+       rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr);
++#ifdef CONFIG_SYSCTL
++      devinet_sysctl.sysctl_header =
++              register_sysctl_table(devinet_sysctl.devinet_root_dir);
++      devinet_sysctl_register(NULL, &ipv4_devconf_dflt);
++#endif
+ }
+ EXPORT_SYMBOL(in_dev_finish_destroy);
+diff -Nurb linux-2.6.22-590/net/ipv4/esp4.c linux-2.6.22-570/net/ipv4/esp4.c
+--- linux-2.6.22-590/net/ipv4/esp4.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/esp4.c   2007-07-08 19:32:17.000000000 -0400
+@@ -307,9 +307,6 @@
+       struct ip_esp_hdr *esph = (struct ip_esp_hdr*)(skb->data+(iph->ihl<<2));
+       struct xfrm_state *x;
+-      if (skb->dev->nd_net != &init_net)
+-              return;
 -
--      return 0;
--}
+       if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH ||
+           icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
+               return;
+@@ -484,4 +481,3 @@
+ module_init(esp4_init);
+ module_exit(esp4_fini);
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_ESP);
+diff -Nurb linux-2.6.22-590/net/ipv4/fib_frontend.c linux-2.6.22-570/net/ipv4/fib_frontend.c
+--- linux-2.6.22-590/net/ipv4/fib_frontend.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/fib_frontend.c   2007-07-08 19:32:17.000000000 -0400
+@@ -51,34 +51,38 @@
+ #ifndef CONFIG_IP_MULTIPLE_TABLES
++struct fib_table *ip_fib_local_table;
++struct fib_table *ip_fib_main_table;
++
+ #define FIB_TABLE_HASHSZ 1
++static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
+ #else
+ #define FIB_TABLE_HASHSZ 256
++static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
+-struct fib_table *fib_new_table(struct net *net, u32 id)
++struct fib_table *fib_new_table(u32 id)
+ {
+       struct fib_table *tb;
+       unsigned int h;
+       if (id == 0)
+               id = RT_TABLE_MAIN;
+-      tb = fib_get_table(net, id);
++      tb = fib_get_table(id);
+       if (tb)
+               return tb;
+       tb = fib_hash_init(id);
+       if (!tb)
+               return NULL;
+       h = id & (FIB_TABLE_HASHSZ - 1);
+-      hlist_add_head_rcu(&tb->tb_hlist, &net->ip_fib_table_hash[h]);
++      hlist_add_head_rcu(&tb->tb_hlist, &fib_table_hash[h]);
+       return tb;
+ }
+-struct fib_table *fib_get_table(struct net *net, u32 id)
++struct fib_table *fib_get_table(u32 id)
+ {
+       struct fib_table *tb;
+-      struct hlist_head *head;
+       struct hlist_node *node;
+       unsigned int h;
+@@ -86,8 +90,7 @@
+               id = RT_TABLE_MAIN;
+       h = id & (FIB_TABLE_HASHSZ - 1);
+       rcu_read_lock();
+-      head = &net->ip_fib_table_hash[h];
+-      hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
++      hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb_hlist) {
+               if (tb->tb_id == id) {
+                       rcu_read_unlock();
+                       return tb;
+@@ -96,10 +99,9 @@
+       rcu_read_unlock();
+       return NULL;
+ }
 -
--/* Gets referenced address, destroys ifaddr */
--
--static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
--{
--      if (ifp->flags&IFA_F_PERMANENT) {
--              spin_lock_bh(&ifp->lock);
--              addrconf_del_timer(ifp);
--              ifp->flags |= IFA_F_TENTATIVE;
--              spin_unlock_bh(&ifp->lock);
--              in6_ifa_put(ifp);
--#ifdef CONFIG_IPV6_PRIVACY
--      } else if (ifp->flags&IFA_F_TEMPORARY) {
--              struct inet6_ifaddr *ifpub;
--              spin_lock_bh(&ifp->lock);
--              ifpub = ifp->ifpub;
--              if (ifpub) {
--                      in6_ifa_hold(ifpub);
--                      spin_unlock_bh(&ifp->lock);
--                      ipv6_create_tempaddr(ifpub, ifp);
--                      in6_ifa_put(ifpub);
--              } else {
--                      spin_unlock_bh(&ifp->lock);
--              }
--              ipv6_del_addr(ifp);
--#endif
--      } else
--              ipv6_del_addr(ifp);
+ #endif /* CONFIG_IP_MULTIPLE_TABLES */
+-static void fib_flush(struct net *net)
++static void fib_flush(void)
+ {
+       int flushed = 0;
+       struct fib_table *tb;
+@@ -107,8 +109,7 @@
+       unsigned int h;
+       for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
+-              struct hlist_head *head = &net->ip_fib_table_hash[h];
+-              hlist_for_each_entry(tb, node, head, tb_hlist)
++              hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist)
+                       flushed += tb->tb_flush(tb);
+       }
+@@ -120,23 +121,18 @@
+  *    Find the first device with a given source address.
+  */
+-struct net_device * ip_dev_find(struct net *net, __be32 addr)
++struct net_device * ip_dev_find(__be32 addr)
+ {
+-      struct flowi fl = { 
+-              .fl_net = net,
+-              .nl_u = { .ip4_u = { .daddr = addr } }
+-      };
++      struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
+       struct fib_result res;
+       struct net_device *dev = NULL;
+-      struct fib_table *local_table;
+ #ifdef CONFIG_IP_MULTIPLE_TABLES
+       res.r = NULL;
+ #endif
+-      local_table = fib_get_table(net, RT_TABLE_LOCAL);
+-      if (!local_table ||
+-          local_table->tb_lookup(local_table, &fl, &res))
++      if (!ip_fib_local_table ||
++          ip_fib_local_table->tb_lookup(ip_fib_local_table, &fl, &res))
+               return NULL;
+       if (res.type != RTN_LOCAL)
+               goto out;
+@@ -149,15 +145,11 @@
+       return dev;
+ }
+-unsigned inet_addr_type(struct net *net, __be32 addr)
++unsigned inet_addr_type(__be32 addr)
+ {
+-      struct flowi            fl = {
+-              .fl_net = net,
+-              .nl_u = { .ip4_u = { .daddr = addr } }
+-      };
++      struct flowi            fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
+       struct fib_result       res;
+       unsigned ret = RTN_BROADCAST;
+-      struct fib_table *local_table;
+       if (ZERONET(addr) || BADCLASS(addr))
+               return RTN_BROADCAST;
+@@ -168,10 +160,10 @@
+       res.r = NULL;
+ #endif
+-      local_table = fib_get_table(net, RT_TABLE_LOCAL);
+-      if (local_table) {
++      if (ip_fib_local_table) {
+               ret = RTN_UNICAST;
+-              if (!local_table->tb_lookup(local_table, &fl, &res)) {
++              if (!ip_fib_local_table->tb_lookup(ip_fib_local_table,
++                                                 &fl, &res)) {
+                       ret = res.type;
+                       fib_res_put(&res);
+               }
+@@ -191,8 +183,7 @@
+                       struct net_device *dev, __be32 *spec_dst, u32 *itag)
+ {
+       struct in_device *in_dev;
+-      struct flowi fl = { .fl_net = dev->nd_net,
+-                          .nl_u = { .ip4_u =
++      struct flowi fl = { .nl_u = { .ip4_u =
+                                     { .daddr = src,
+                                       .saddr = dst,
+                                       .tos = tos } },
+@@ -276,16 +267,13 @@
+       return len + nla_total_size(4);
+ }
+-static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
++static int rtentry_to_fib_config(int cmd, struct rtentry *rt,
+                                struct fib_config *cfg)
+ {
+       __be32 addr;
+       int plen;
+       memset(cfg, 0, sizeof(*cfg));
+-      cfg->fc_nlinfo.pid = 0;
+-      cfg->fc_nlinfo.nlh = NULL;
+-      cfg->fc_nlinfo.net = net;
+       if (rt->rt_dst.sa_family != AF_INET)
+               return -EAFNOSUPPORT;
+@@ -346,7 +334,7 @@
+               colon = strchr(devname, ':');
+               if (colon)
+                       *colon = 0;
+-              dev = __dev_get_by_name(net, devname);
++              dev = __dev_get_by_name(devname);
+               if (!dev)
+                       return -ENODEV;
+               cfg->fc_oif = dev->ifindex;
+@@ -369,7 +357,7 @@
+       if (rt->rt_gateway.sa_family == AF_INET && addr) {
+               cfg->fc_gw = addr;
+               if (rt->rt_flags & RTF_GATEWAY &&
+-                  inet_addr_type(net, addr) == RTN_UNICAST)
++                  inet_addr_type(addr) == RTN_UNICAST)
+                       cfg->fc_scope = RT_SCOPE_UNIVERSE;
+       }
+@@ -410,7 +398,7 @@
+  *    Handle IP routing ioctl calls. These are used to manipulate the routing tables
+  */
+-int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
++int ip_rt_ioctl(unsigned int cmd, void __user *arg)
+ {
+       struct fib_config cfg;
+       struct rtentry rt;
+@@ -426,18 +414,18 @@
+                       return -EFAULT;
+               rtnl_lock();
+-              err = rtentry_to_fib_config(net, cmd, &rt, &cfg);
++              err = rtentry_to_fib_config(cmd, &rt, &cfg);
+               if (err == 0) {
+                       struct fib_table *tb;
+                       if (cmd == SIOCDELRT) {
+-                              tb = fib_get_table(net, cfg.fc_table);
++                              tb = fib_get_table(cfg.fc_table);
+                               if (tb)
+                                       err = tb->tb_delete(tb, &cfg);
+                               else
+                                       err = -ESRCH;
+                       } else {
+-                              tb = fib_new_table(net, cfg.fc_table);
++                              tb = fib_new_table(cfg.fc_table);
+                               if (tb)
+                                       err = tb->tb_insert(tb, &cfg);
+                               else
+@@ -465,6 +453,7 @@
+       [RTA_MULTIPATH]         = { .len = sizeof(struct rtnexthop) },
+       [RTA_PROTOINFO]         = { .type = NLA_U32 },
+       [RTA_FLOW]              = { .type = NLA_U32 },
++      [RTA_MP_ALGO]           = { .type = NLA_U32 },
+ };
+ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
+@@ -492,7 +481,6 @@
+       cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
+       cfg->fc_nlinfo.nlh = nlh;
+-      cfg->fc_nlinfo.net = skb->sk->sk_net;
+       if (cfg->fc_type > RTN_MAX) {
+               err = -EINVAL;
+@@ -527,6 +515,9 @@
+               case RTA_FLOW:
+                       cfg->fc_flow = nla_get_u32(attr);
+                       break;
++              case RTA_MP_ALGO:
++                      cfg->fc_mp_alg = nla_get_u32(attr);
++                      break;
+               case RTA_TABLE:
+                       cfg->fc_table = nla_get_u32(attr);
+                       break;
+@@ -540,7 +531,6 @@
+ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct fib_config cfg;
+       struct fib_table *tb;
+       int err;
+@@ -549,7 +539,7 @@
+       if (err < 0)
+               goto errout;
+-      tb = fib_get_table(net, cfg.fc_table);
++      tb = fib_get_table(cfg.fc_table);
+       if (tb == NULL) {
+               err = -ESRCH;
+               goto errout;
+@@ -562,7 +552,6 @@
+ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct fib_config cfg;
+       struct fib_table *tb;
+       int err;
+@@ -571,7 +560,7 @@
+       if (err < 0)
+               goto errout;
+-      tb = fib_new_table(net, cfg.fc_table);
++      tb = fib_new_table(cfg.fc_table);
+       if (tb == NULL) {
+               err = -ENOBUFS;
+               goto errout;
+@@ -584,7 +573,6 @@
+ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       unsigned int h, s_h;
+       unsigned int e = 0, s_e;
+       struct fib_table *tb;
+@@ -599,9 +587,8 @@
+       s_e = cb->args[1];
+       for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
+-              struct hlist_head *head = &net->ip_fib_table_hash[h];
+               e = 0;
+-              hlist_for_each_entry(tb, node, head, tb_hlist) {
++              hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist) {
+                       if (e < s_e)
+                               goto next;
+                       if (dumped)
+@@ -630,7 +617,6 @@
+ static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
+ {
+-      struct net *net = ifa->ifa_dev->dev->nd_net;
+       struct fib_table *tb;
+       struct fib_config cfg = {
+               .fc_protocol = RTPROT_KERNEL,
+@@ -640,13 +626,12 @@
+               .fc_prefsrc = ifa->ifa_local,
+               .fc_oif = ifa->ifa_dev->dev->ifindex,
+               .fc_nlflags = NLM_F_CREATE | NLM_F_APPEND,
+-              .fc_nlinfo.net = net,
+       };
+       if (type == RTN_UNICAST)
+-              tb = fib_new_table(net, RT_TABLE_MAIN);
++              tb = fib_new_table(RT_TABLE_MAIN);
+       else
+-              tb = fib_new_table(net, RT_TABLE_LOCAL);
++              tb = fib_new_table(RT_TABLE_LOCAL);
+       if (tb == NULL)
+               return;
+@@ -707,7 +692,6 @@
+ {
+       struct in_device *in_dev = ifa->ifa_dev;
+       struct net_device *dev = in_dev->dev;
+-      struct net *net = dev->nd_net;
+       struct in_ifaddr *ifa1;
+       struct in_ifaddr *prim = ifa;
+       __be32 brd = ifa->ifa_address|~ifa->ifa_mask;
+@@ -756,15 +740,15 @@
+               fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
+               /* Check, that this local address finally disappeared. */
+-              if (inet_addr_type(net, ifa->ifa_local) != RTN_LOCAL) {
++              if (inet_addr_type(ifa->ifa_local) != RTN_LOCAL) {
+                       /* And the last, but not the least thing.
+                          We must flush stray FIB entries.
+                          First of all, we scan fib_info list searching
+                          for stray nexthop entries, then ignite fib_flush.
+                       */
+-                      if (fib_sync_down(net, ifa->ifa_local, NULL, 0))
+-                              fib_flush(net);
++                      if (fib_sync_down(ifa->ifa_local, NULL, 0))
++                              fib_flush();
+               }
+       }
+ #undef LOCAL_OK
+@@ -773,12 +757,11 @@
+ #undef BRD1_OK
+ }
+-static void nl_fib_lookup(struct net *net, struct fib_result_nl *frn, struct fib_table *tb )
++static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
+ {
+       struct fib_result       res;
+-      struct flowi            fl = { .fl_net = net,
+-                                     .mark = frn->fl_mark,
++      struct flowi            fl = { .mark = frn->fl_mark,
+                                      .nl_u = { .ip4_u = { .daddr = frn->fl_addr,
+                                                           .tos = frn->fl_tos,
+                                                           .scope = frn->fl_scope } } };
+@@ -807,7 +790,6 @@
+ static void nl_fib_input(struct sock *sk, int len)
+ {
+-      struct net *net = sk->sk_net;
+       struct sk_buff *skb = NULL;
+       struct nlmsghdr *nlh = NULL;
+       struct fib_result_nl *frn;
+@@ -826,9 +808,9 @@
+       }
+       frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
+-      tb = fib_get_table(net, frn->tb_id_in);
++      tb = fib_get_table(frn->tb_id_in);
+-      nl_fib_lookup(net, frn, tb);
++      nl_fib_lookup(frn, tb);
+       pid = NETLINK_CB(skb).pid;       /* pid of sending process */
+       NETLINK_CB(skb).pid = 0;         /* from kernel */
+@@ -836,36 +818,16 @@
+       netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
+ }
+-static int nl_fib_lookup_init(struct net *net)
++static void nl_fib_lookup_init(void)
+ {
+-      int error = -ENOMEM;
+-      struct sock *sk;
+-      sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0, nl_fib_input,
+-                                      NULL, THIS_MODULE);
+-      if (sk) {
+-              /* Don't hold an extra reference on the namespace */
+-              put_net(sk->sk_net);
+-              net->nlfl = sk;
+-              error = 0;
+-      }
+-      return error;
 -}
 -
--void addrconf_dad_failure(struct inet6_ifaddr *ifp)
+-static void nl_fib_lookup_exit(struct net *net)
 -{
--      if (net_ratelimit())
--              printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
--      addrconf_dad_stop(ifp);
--}
--
--/* Join to solicited addr multicast group. */
+-      /* At the last minute lie and say this is a socket for the
+-       * initial network namespace.  So the socket will  be safe to
+-       * free. 
+-       */
+-      net->nlfl->sk_net = get_net(&init_net);
+-      sock_put(net->nlfl);
++      netlink_kernel_create(NETLINK_FIB_LOOKUP, 0, nl_fib_input, NULL,
++                                  THIS_MODULE);
+ }
+ static void fib_disable_ip(struct net_device *dev, int force)
+ {
+-      struct net *net = dev->nd_net;
+-      if (fib_sync_down(net, 0, dev, force))
+-              fib_flush(net);
++      if (fib_sync_down(0, dev, force))
++              fib_flush();
+       rt_cache_flush(0);
+       arp_ifdown(dev);
+ }
+@@ -902,9 +864,6 @@
+       struct net_device *dev = ptr;
+       struct in_device *in_dev = __in_dev_get_rtnl(dev);
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr)
+       if (event == NETDEV_UNREGISTER) {
+               fib_disable_ip(dev, 2);
+               return NOTIFY_DONE;
+@@ -934,85 +893,6 @@
+       return NOTIFY_DONE;
+ }
+-static int ip_fib_net_init(struct net *net)
 -{
--      struct in6_addr maddr;
+-      unsigned int i;
 -
--      if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))
--              return;
+-      net->ip_fib_table_hash = kzalloc(
+-              sizeof(struct hlist_head)*FIB_TABLE_HASHSZ, GFP_KERNEL);
+-      if (!net->ip_fib_table_hash)
+-              return -ENOMEM;
 -
--      addrconf_addr_solict_mult(addr, &maddr);
--      ipv6_dev_mc_inc(dev, &maddr);
+-      for (i = 0; i < FIB_TABLE_HASHSZ; i++)
+-              INIT_HLIST_HEAD(&net->ip_fib_table_hash[i]);
+-#ifndef CONFIG_IP_MULTIPLE_TABLES
+-      net->ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
+-      hlist_add_head_rcu(&net->ip_fib_local_table->tb_hlist,
+-                              &net->ip_fib_table_hash[0]);
+-      net->ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN);
+-      hlist_add_head_rcu(&net->ip_fib_main_table->tb_hlist,
+-                              &net->ip_fib_table_hash[0]);
+-#else
+-      fib4_rules_init(net);
+-#endif
+-      return 0;
 -}
 -
--void addrconf_leave_solict(struct inet6_dev *idev, struct in6_addr *addr)
+-static void ip_fib_net_exit(struct net *net)
 -{
--      struct in6_addr maddr;
--
--      if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP))
--              return;
+-      unsigned int i;
 -
--      addrconf_addr_solict_mult(addr, &maddr);
--      __ipv6_dev_mc_dec(idev, &maddr);
--}
+-#ifdef CONFIG_IP_MULTIPLE_TABLES
+-      fib4_rules_exit(net);
+-#endif
 -
--static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
--{
--      struct in6_addr addr;
--      ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
--      if (ipv6_addr_any(&addr))
--              return;
--      ipv6_dev_ac_inc(ifp->idev->dev, &addr);
--}
+-      synchronize_rcu(); /* needed? */
+-      for (i = 0; i < FIB_TABLE_HASHSZ; i++) {
+-              struct fib_table *tb;
+-              struct hlist_head *head;
+-              struct hlist_node *node, *tmp;
 -
--static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
--{
--      struct in6_addr addr;
--      ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
--      if (ipv6_addr_any(&addr))
--              return;
--      __ipv6_dev_ac_dec(ifp->idev, &addr);
+-              head = &net->ip_fib_table_hash[i];
+-              hlist_for_each_entry_safe(tb, node, tmp, head, tb_hlist) {
+-                      hlist_del(node);
+-                      fib_hash_exit(tb);
+-              }
+-      }
+-      kfree(net->ip_fib_table_hash);
 -}
 -
--static int addrconf_ifid_eui48(u8 *eui, struct net_device *dev)
+-static int fib_net_init(struct net *net)
 -{
--      if (dev->addr_len != ETH_ALEN)
--              return -1;
--      memcpy(eui, dev->dev_addr, 3);
--      memcpy(eui + 5, dev->dev_addr + 3, 3);
+-      int error;
 -
--      /*
--       * The zSeries OSA network cards can be shared among various
--       * OS instances, but the OSA cards have only one MAC address.
--       * This leads to duplicate address conflicts in conjunction
--       * with IPv6 if more than one instance uses the same card.
--       *
--       * The driver for these cards can deliver a unique 16-bit
--       * identifier for each instance sharing the same card.  It is
--       * placed instead of 0xFFFE in the interface identifier.  The
--       * "u" bit of the interface identifier is not inverted in this
--       * case.  Hence the resulting interface identifier has local
--       * scope according to RFC2373.
--       */
--      if (dev->dev_id) {
--              eui[3] = (dev->dev_id >> 8) & 0xFF;
--              eui[4] = dev->dev_id & 0xFF;
--      } else {
--              eui[3] = 0xFF;
--              eui[4] = 0xFE;
--              eui[0] ^= 2;
--      }
--      return 0;
+-      error = 0;
+-      if ((error = ip_fib_net_init(net)))
+-              goto out;
+-      if ((error = fib_info_init(net)))
+-              goto out_info;
+-      if ((error = nl_fib_lookup_init(net)))
+-              goto out_nlfl;
+-      if ((error = fib_proc_init(net)))
+-              goto out_proc;
+-out:
+-      return error;
+-out_proc:
+-      nl_fib_lookup_exit(net);
+-out_nlfl:
+-      fib_info_exit(net);
+-out_info:
+-      ip_fib_net_exit(net);
+-      goto out;
 -}
 -
--static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev)
+-static void fib_net_exit(struct net *net)
 -{
--      /* XXX: inherit EUI-64 from other interface -- yoshfuji */
--      if (dev->addr_len != ARCNET_ALEN)
--              return -1;
--      memset(eui, 0, 7);
--      eui[7] = *(u8*)dev->dev_addr;
--      return 0;
+-      fib_proc_exit(net);
+-      nl_fib_lookup_exit(net);
+-      fib_info_exit(net);
+-      ip_fib_net_exit(net);
 -}
 -
--static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev)
+ static struct notifier_block fib_inetaddr_notifier = {
+       .notifier_call =fib_inetaddr_event,
+ };
+@@ -1021,20 +901,28 @@
+       .notifier_call =fib_netdev_event,
+ };
+-static struct pernet_operations fib_net_ops = {
+-      .init = fib_net_init,
+-      .exit = fib_net_exit,
+-};
+-
+ void __init ip_fib_init(void)
+ {
+-      rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL);
+-      rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL);
+-      rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib);
++      unsigned int i;
++
++      for (i = 0; i < FIB_TABLE_HASHSZ; i++)
++              INIT_HLIST_HEAD(&fib_table_hash[i]);
++#ifndef CONFIG_IP_MULTIPLE_TABLES
++      ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
++      hlist_add_head_rcu(&ip_fib_local_table->tb_hlist, &fib_table_hash[0]);
++      ip_fib_main_table  = fib_hash_init(RT_TABLE_MAIN);
++      hlist_add_head_rcu(&ip_fib_main_table->tb_hlist, &fib_table_hash[0]);
++#else
++      fib4_rules_init();
++#endif
+-      register_pernet_subsys(&fib_net_ops);
+       register_netdevice_notifier(&fib_netdev_notifier);
+       register_inetaddr_notifier(&fib_inetaddr_notifier);
++      nl_fib_lookup_init();
++
++      rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL);
++      rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL);
++      rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib);
+ }
+ EXPORT_SYMBOL(inet_addr_type);
+diff -Nurb linux-2.6.22-590/net/ipv4/fib_hash.c linux-2.6.22-570/net/ipv4/fib_hash.c
+--- linux-2.6.22-590/net/ipv4/fib_hash.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/fib_hash.c       2008-01-23 19:16:05.000000000 -0500
+@@ -40,7 +40,6 @@
+ #include <net/route.h>
+ #include <net/tcp.h>
+ #include <net/sock.h>
+-#include <net/net_namespace.h>
+ #include <net/ip_fib.h>
+ #include "fib_lookup.h"
+@@ -275,10 +274,11 @@
+       return err;
+ }
++static int fn_hash_last_dflt=-1;
++
+ static void
+ fn_hash_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
+ {
+-      struct net *net = flp->fl_net;
+       int order, last_idx;
+       struct hlist_node *node;
+       struct fib_node *f;
+@@ -316,12 +316,12 @@
+                               if (next_fi != res->fi)
+                                       break;
+                       } else if (!fib_detect_death(fi, order, &last_resort,
+-                                                   &last_idx, &net->fn_hash_last_dflt)) {
++                                                   &last_idx, &fn_hash_last_dflt)) {
+                               if (res->fi)
+                                       fib_info_put(res->fi);
+                               res->fi = fi;
+                               atomic_inc(&fi->fib_clntref);
+-                              net->fn_hash_last_dflt = order;
++                              fn_hash_last_dflt = order;
+                               goto out;
+                       }
+                       fi = next_fi;
+@@ -330,16 +330,16 @@
+       }
+       if (order <= 0 || fi == NULL) {
+-              net->fn_hash_last_dflt = -1;
++              fn_hash_last_dflt = -1;
+               goto out;
+       }
+-      if (!fib_detect_death(fi, order, &last_resort, &last_idx, &net->fn_hash_last_dflt)) {
++      if (!fib_detect_death(fi, order, &last_resort, &last_idx, &fn_hash_last_dflt)) {
+               if (res->fi)
+                       fib_info_put(res->fi);
+               res->fi = fi;
+               atomic_inc(&fi->fib_clntref);
+-              net->fn_hash_last_dflt = order;
++              fn_hash_last_dflt = order;
+               goto out;
+       }
+@@ -350,7 +350,7 @@
+               if (last_resort)
+                       atomic_inc(&last_resort->fib_clntref);
+       }
+-      net->fn_hash_last_dflt = last_idx;
++      fn_hash_last_dflt = last_idx;
+ out:
+       read_unlock(&fib_hash_lock);
+ }
+@@ -759,15 +759,11 @@
+       return skb->len;
+ }
+-void fib_hash_exit(struct fib_table *tb)
 -{
--      if (dev->addr_len != INFINIBAND_ALEN)
--              return -1;
--      memcpy(eui, dev->dev_addr + 12, 8);
--      eui[0] |= 2;
--      return 0;
+-      if (!tb)
+-              return;
+-      fn_hash_flush(tb);
+-      kfree(tb);
 -}
 -
--static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
++#ifdef CONFIG_IP_MULTIPLE_TABLES
+ struct fib_table * fib_hash_init(u32 id)
++#else
++struct fib_table * __init fib_hash_init(u32 id)
++#endif
+ {
+       struct fib_table *tb;
+@@ -803,7 +799,6 @@
+ #ifdef CONFIG_PROC_FS
+ struct fib_iter_state {
+-      struct net *net;
+       struct fn_zone  *zone;
+       int             bucket;
+       struct hlist_head *hash_head;
+@@ -817,8 +812,7 @@
+ static struct fib_alias *fib_get_first(struct seq_file *seq)
+ {
+       struct fib_iter_state *iter = seq->private;
+-      struct fib_table *main_table = fib_get_table(iter->net, RT_TABLE_MAIN);
+-      struct fn_hash *table = (struct fn_hash *) main_table->tb_data;
++      struct fn_hash *table = (struct fn_hash *) ip_fib_main_table->tb_data;
+       iter->bucket    = 0;
+       iter->hash_head = NULL;
+@@ -954,11 +948,10 @@
+ static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+-      struct fib_iter_state *iter = seq->private;
+       void *v = NULL;
+       read_lock(&fib_hash_lock);
+-      if (fib_get_table(iter->net, RT_TABLE_MAIN))
++      if (ip_fib_main_table)
+               v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+       return v;
+ }
+@@ -1058,7 +1051,6 @@
+       seq          = file->private_data;
+       seq->private = s;
+-      s->net = get_net(PROC_NET(inode));
+ out:
+       return rc;
+ out_kfree:
+@@ -1066,32 +1058,23 @@
+       goto out;
+ }
+-static int fib_seq_release(struct inode *inode, struct file *file)
 -{
--      switch (dev->type) {
--      case ARPHRD_ETHER:
--      case ARPHRD_FDDI:
--      case ARPHRD_IEEE802_TR:
--              return addrconf_ifid_eui48(eui, dev);
--      case ARPHRD_ARCNET:
--              return addrconf_ifid_arcnet(eui, dev);
--      case ARPHRD_INFINIBAND:
--              return addrconf_ifid_infiniband(eui, dev);
--      }
--      return -1;
+-      struct seq_file *seq = file->private_data;
+-      struct fib_iter_state *iter = seq->private;
+-      put_net(iter->net);
+-      return seq_release_private(inode, file);
 -}
 -
--static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
--{
--      int err = -1;
--      struct inet6_ifaddr *ifp;
+ static const struct file_operations fib_seq_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fib_seq_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+-      .release        = fib_seq_release,
++      .release        = seq_release_private,
+ };
+-int fib_proc_init(struct net *net)
++int __init fib_proc_init(void)
+ {
+-      net->fn_hash_last_dflt = -1;
+-      if (!proc_net_fops_create(net, "route", S_IRUGO, &fib_seq_fops))
++      if (!proc_net_fops_create("route", S_IRUGO, &fib_seq_fops))
+               return -ENOMEM;
+       return 0;
+ }
+-void fib_proc_exit(struct net *net)
++void __init fib_proc_exit(void)
+ {
+-      proc_net_remove(net, "route");
++      proc_net_remove("route");
+ }
+ #endif /* CONFIG_PROC_FS */
+diff -Nurb linux-2.6.22-590/net/ipv4/fib_rules.c linux-2.6.22-570/net/ipv4/fib_rules.c
+--- linux-2.6.22-590/net/ipv4/fib_rules.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/fib_rules.c      2007-07-08 19:32:17.000000000 -0400
+@@ -32,6 +32,8 @@
+ #include <net/ip_fib.h>
+ #include <net/fib_rules.h>
++static struct fib_rules_ops fib4_rules_ops;
++
+ struct fib4_rule
+ {
+       struct fib_rule         common;
+@@ -47,14 +49,35 @@
+ #endif
+ };
+-struct fib4_rule_table {
+-      struct list_head        fib4_rules;
+-      struct fib4_rule        default_rule;
+-      struct fib4_rule        main_rule;
+-      struct fib4_rule        local_rule;
+-      struct fib_rules_ops    fib4_rules_ops;
++static struct fib4_rule default_rule = {
++      .common = {
++              .refcnt =       ATOMIC_INIT(2),
++              .pref =         0x7FFF,
++              .table =        RT_TABLE_DEFAULT,
++              .action =       FR_ACT_TO_TBL,
++      },
+ };
++static struct fib4_rule main_rule = {
++      .common = {
++              .refcnt =       ATOMIC_INIT(2),
++              .pref =         0x7FFE,
++              .table =        RT_TABLE_MAIN,
++              .action =       FR_ACT_TO_TBL,
++      },
++};
++
++static struct fib4_rule local_rule = {
++      .common = {
++              .refcnt =       ATOMIC_INIT(2),
++              .table =        RT_TABLE_LOCAL,
++              .action =       FR_ACT_TO_TBL,
++              .flags =        FIB_RULE_PERMANENT,
++      },
++};
++
++static LIST_HEAD(fib4_rules);
++
+ #ifdef CONFIG_NET_CLS_ROUTE
+ u32 fib_rules_tclass(struct fib_result *res)
+ {
+@@ -64,14 +87,12 @@
+ int fib_lookup(struct flowi *flp, struct fib_result *res)
+ {
+-      struct net *net = flp->fl_net;
+-      struct fib4_rule_table *table = net->fib4_table;
+       struct fib_lookup_arg arg = {
+               .result = res,
+       };
+       int err;
+-      err = fib_rules_lookup(&table->fib4_rules_ops, flp, 0, &arg);
++      err = fib_rules_lookup(&fib4_rules_ops, flp, 0, &arg);
+       res->r = arg.rule;
+       return err;
+@@ -101,7 +122,7 @@
+               goto errout;
+       }
+-      if ((tbl = fib_get_table(flp->fl_net, rule->table)) == NULL)
++      if ((tbl = fib_get_table(rule->table)) == NULL)
+               goto errout;
+       err = tbl->tb_lookup(tbl, flp, (struct fib_result *) arg->result);
+@@ -117,7 +138,7 @@
+       if (res->r && res->r->action == FR_ACT_TO_TBL &&
+           FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) {
+               struct fib_table *tb;
+-              if ((tb = fib_get_table(flp->fl_net, res->r->table)) != NULL)
++              if ((tb = fib_get_table(res->r->table)) != NULL)
+                       tb->tb_select_default(tb, flp, res);
+       }
+ }
+@@ -138,13 +159,13 @@
+       return 1;
+ }
+-static struct fib_table *fib_empty_table(struct net *net)
++static struct fib_table *fib_empty_table(void)
+ {
+       u32 id;
+       for (id = 1; id <= RT_TABLE_MAX; id++)
+-              if (fib_get_table(net, id) == NULL)
+-                      return fib_new_table(net, id);
++              if (fib_get_table(id) == NULL)
++                      return fib_new_table(id);
+       return NULL;
+ }
+@@ -157,7 +178,6 @@
+                              struct nlmsghdr *nlh, struct fib_rule_hdr *frh,
+                              struct nlattr **tb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       int err = -EINVAL;
+       struct fib4_rule *rule4 = (struct fib4_rule *) rule;
+@@ -168,7 +188,7 @@
+               if (rule->action == FR_ACT_TO_TBL) {
+                       struct fib_table *table;
+-                      table = fib_empty_table(net);
++                      table = fib_empty_table();
+                       if (table == NULL) {
+                               err = -ENOBUFS;
+                               goto errout;
+@@ -254,15 +274,14 @@
+       return -ENOBUFS;
+ }
+-static u32 fib4_rule_default_pref(struct fib_rules_ops *ops)
++static u32 fib4_rule_default_pref(void)
+ {
+-      struct list_head *list, *pos;
++      struct list_head *pos;
+       struct fib_rule *rule;
+-      list = ops->rules_list;
+-      if (!list_empty(list)) {
+-              pos = list->next;
+-              if (pos->next != list) {
++      if (!list_empty(&fib4_rules)) {
++              pos = fib4_rules.next;
++              if (pos->next != &fib4_rules) {
+                       rule = list_entry(pos->next, struct fib_rule, list);
+                       if (rule->pref)
+                               return rule->pref - 1;
+@@ -279,37 +298,12 @@
+              + nla_total_size(4); /* flow */
+ }
+-static void fib4_rule_flush_cache(struct fib_rules_ops *ops)
++static void fib4_rule_flush_cache(void)
+ {
+       rt_cache_flush(-1);
+ }
+-static struct fib4_rule_table fib4_rule_table = {
+-      .default_rule = {
+-              .common = {
+-                      .refcnt =       ATOMIC_INIT(2),
+-                      .pref =         0x7FFF,
+-                      .table =        RT_TABLE_DEFAULT,
+-                      .action =       FR_ACT_TO_TBL,
+-              },
+-      },
+-      .main_rule = {
+-              .common = {
+-                      .refcnt =       ATOMIC_INIT(2),
+-                      .pref =         0x7FFE,
+-                      .table =        RT_TABLE_MAIN,
+-                      .action =       FR_ACT_TO_TBL,
+-              },
+-      },
+-      .local_rule = {
+-              .common = {
+-                      .refcnt =       ATOMIC_INIT(2),
+-                      .table =        RT_TABLE_LOCAL,
+-                      .action =       FR_ACT_TO_TBL,
+-                      .flags =        FIB_RULE_PERMANENT,
+-              },
+-      },
+-      .fib4_rules_ops = {
++static struct fib_rules_ops fib4_rules_ops = {
+       .family         = AF_INET,
+       .rule_size      = sizeof(struct fib4_rule),
+       .addr_size      = sizeof(u32),
+@@ -323,34 +317,15 @@
+       .flush_cache    = fib4_rule_flush_cache,
+       .nlgroup        = RTNLGRP_IPV4_RULE,
+       .policy         = fib4_rule_policy,
+-              .rules_list     = &fib4_rule_table.fib4_rules, /* &fib4_rules, */
++      .rules_list     = &fib4_rules,
+       .owner          = THIS_MODULE,
+-      },
+ };
 -
--      read_lock_bh(&idev->lock);
--      for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) {
--              if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) {
--                      memcpy(eui, ifp->addr.s6_addr+8, 8);
--                      err = 0;
--                      break;
--              }
+-void fib4_rules_init(struct net *net)
++void __init fib4_rules_init(void)
+ {
+-      struct fib4_rule_table *table;
+-      table = kmemdup(&fib4_rule_table, sizeof(*table), GFP_KERNEL);
+-      if (!table)
+-              return;
+-      INIT_LIST_HEAD(&table->fib4_rules);
+-      list_add_tail(&table->local_rule.common.list,   &table->fib4_rules);
+-      list_add_tail(&table->main_rule.common.list,    &table->fib4_rules);
+-      list_add_tail(&table->default_rule.common.list, &table->fib4_rules);
+-      table->fib4_rules_ops.rules_list = &table->fib4_rules;
+-      if (fib_rules_register(net, &table->fib4_rules_ops)) {
+-              kfree(table);
+-              return;
 -      }
--      read_unlock_bh(&idev->lock);
--      return err;
+-      net->fib4_table = table;
 -}
++      list_add_tail(&local_rule.common.list, &fib4_rules);
++      list_add_tail(&main_rule.common.list, &fib4_rules);
++      list_add_tail(&default_rule.common.list, &fib4_rules);
+-void fib4_rules_exit(struct net *net)
+-{
+-      struct fib4_rule_table *table = net->fib4_table;
+-      if (table)
+-              fib_rules_unregister(net, &table->fib4_rules_ops);
+-      kfree(table);
++      fib_rules_register(&fib4_rules_ops);
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/fib_semantics.c linux-2.6.22-570/net/ipv4/fib_semantics.c
+--- linux-2.6.22-590/net/ipv4/fib_semantics.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/fib_semantics.c  2007-07-08 19:32:17.000000000 -0400
+@@ -42,6 +42,7 @@
+ #include <net/tcp.h>
+ #include <net/sock.h>
+ #include <net/ip_fib.h>
++#include <net/ip_mp_alg.h>
+ #include <net/netlink.h>
+ #include <net/nexthop.h>
+@@ -50,9 +51,14 @@
+ #define FSprintk(a...)
+ static DEFINE_SPINLOCK(fib_info_lock);
++static struct hlist_head *fib_info_hash;
++static struct hlist_head *fib_info_laddrhash;
++static unsigned int fib_hash_size;
++static unsigned int fib_info_cnt;
+ #define DEVINDEX_HASHBITS 8
+ #define DEVINDEX_HASHSIZE (1U << DEVINDEX_HASHBITS)
++static struct hlist_head fib_info_devhash[DEVINDEX_HASHSIZE];
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+@@ -148,8 +154,7 @@
+                       dev_put(nh->nh_dev);
+               nh->nh_dev = NULL;
+       } endfor_nexthops(fi);
+-      fi->fib_net->fib_info_cnt--;
+-      release_net(fi->fib_net);
++      fib_info_cnt--;
+       kfree(fi);
+ }
+@@ -192,9 +197,9 @@
+       return 0;
+ }
+-static inline unsigned int fib_info_hashfn(struct net *net, const struct fib_info *fi)
++static inline unsigned int fib_info_hashfn(const struct fib_info *fi)
+ {
+-      unsigned int mask = net->fib_info_hash_size - 1;
++      unsigned int mask = (fib_hash_size - 1);
+       unsigned int val = fi->fib_nhs;
+       val ^= fi->fib_protocol;
+@@ -204,15 +209,15 @@
+       return (val ^ (val >> 7) ^ (val >> 12)) & mask;
+ }
+-static struct fib_info *fib_find_info(struct net *net, const struct fib_info *nfi)
++static struct fib_info *fib_find_info(const struct fib_info *nfi)
+ {
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct fib_info *fi;
+       unsigned int hash;
+-      hash = fib_info_hashfn(net, nfi);
+-      head = &net->fib_info_hash[hash];
++      hash = fib_info_hashfn(nfi);
++      head = &fib_info_hash[hash];
+       hlist_for_each_entry(fi, node, head, fib_hash) {
+               if (fi->fib_nhs != nfi->fib_nhs)
+@@ -245,7 +250,6 @@
+ int ip_fib_check_default(__be32 gw, struct net_device *dev)
+ {
+-      struct net *net = dev->nd_net;
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct fib_nh *nh;
+@@ -254,7 +258,7 @@
+       spin_lock(&fib_info_lock);
+       hash = fib_devindex_hashfn(dev->ifindex);
+-      head = &net->fib_info_devhash[hash];
++      head = &fib_info_devhash[hash];
+       hlist_for_each_entry(nh, node, head, nh_hash) {
+               if (nh->nh_dev == dev &&
+                   nh->nh_gw == gw &&
+@@ -317,11 +321,11 @@
+               kfree_skb(skb);
+               goto errout;
+       }
+-      err = rtnl_notify(skb, info->net, info->pid, RTNLGRP_IPV4_ROUTE,
++      err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
+                         info->nlh, GFP_KERNEL);
+ errout:
+       if (err < 0)
+-              rtnl_set_sk_err(info->net, RTNLGRP_IPV4_ROUTE, err);
++              rtnl_set_sk_err(RTNLGRP_IPV4_ROUTE, err);
+ }
+ /* Return the first fib alias matching TOS with
+@@ -514,7 +518,6 @@
+ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
+                       struct fib_nh *nh)
+ {
+-      struct net *net = cfg->fc_nlinfo.net;
+       int err;
+       if (nh->nh_gw) {
+@@ -529,9 +532,9 @@
+                       if (cfg->fc_scope >= RT_SCOPE_LINK)
+                               return -EINVAL;
+-                      if (inet_addr_type(net, nh->nh_gw) != RTN_UNICAST)
++                      if (inet_addr_type(nh->nh_gw) != RTN_UNICAST)
+                               return -EINVAL;
+-                      if ((dev = __dev_get_by_index(net, nh->nh_oif)) == NULL)
++                      if ((dev = __dev_get_by_index(nh->nh_oif)) == NULL)
+                               return -ENODEV;
+                       if (!(dev->flags&IFF_UP))
+                               return -ENETDOWN;
+@@ -542,7 +545,6 @@
+               }
+               {
+                       struct flowi fl = {
+-                              .fl_net = net,
+                               .nl_u = {
+                                       .ip4_u = {
+                                               .daddr = nh->nh_gw,
+@@ -579,7 +581,7 @@
+               if (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK))
+                       return -EINVAL;
+-              in_dev = inetdev_by_index(net, nh->nh_oif);
++              in_dev = inetdev_by_index(nh->nh_oif);
+               if (in_dev == NULL)
+                       return -ENODEV;
+               if (!(in_dev->dev->flags&IFF_UP)) {
+@@ -594,9 +596,9 @@
+       return 0;
+ }
+-static inline unsigned int fib_laddr_hashfn(struct net *net, __be32 val)
++static inline unsigned int fib_laddr_hashfn(__be32 val)
+ {
+-      unsigned int mask = net->fib_info_hash_size - 1;
++      unsigned int mask = (fib_hash_size - 1);
+       return ((__force u32)val ^ ((__force u32)val >> 7) ^ ((__force u32)val >> 14)) & mask;
+ }
+@@ -621,22 +623,21 @@
+               free_pages((unsigned long) hash, get_order(bytes));
+ }
+-static void fib_hash_move(struct net *net,
+-                        struct hlist_head *new_info_hash,
++static void fib_hash_move(struct hlist_head *new_info_hash,
+                         struct hlist_head *new_laddrhash,
+                         unsigned int new_size)
+ {
+       struct hlist_head *old_info_hash, *old_laddrhash;
+-      unsigned int old_size = net->fib_info_hash_size;
++      unsigned int old_size = fib_hash_size;
+       unsigned int i, bytes;
+       spin_lock_bh(&fib_info_lock);
+-      old_info_hash = net->fib_info_hash;
+-      old_laddrhash = net->fib_info_laddrhash;
+-      net->fib_info_hash_size = new_size;
++      old_info_hash = fib_info_hash;
++      old_laddrhash = fib_info_laddrhash;
++      fib_hash_size = new_size;
+       for (i = 0; i < old_size; i++) {
+-              struct hlist_head *head = &net->fib_info_hash[i];
++              struct hlist_head *head = &fib_info_hash[i];
+               struct hlist_node *node, *n;
+               struct fib_info *fi;
+@@ -646,15 +647,15 @@
+                       hlist_del(&fi->fib_hash);
+-                      new_hash = fib_info_hashfn(net, fi);
++                      new_hash = fib_info_hashfn(fi);
+                       dest = &new_info_hash[new_hash];
+                       hlist_add_head(&fi->fib_hash, dest);
+               }
+       }
+-      net->fib_info_hash = new_info_hash;
++      fib_info_hash = new_info_hash;
+       for (i = 0; i < old_size; i++) {
+-              struct hlist_head *lhead = &net->fib_info_laddrhash[i];
++              struct hlist_head *lhead = &fib_info_laddrhash[i];
+               struct hlist_node *node, *n;
+               struct fib_info *fi;
+@@ -664,12 +665,12 @@
+                       hlist_del(&fi->fib_lhash);
+-                      new_hash = fib_laddr_hashfn(net, fi->fib_prefsrc);
++                      new_hash = fib_laddr_hashfn(fi->fib_prefsrc);
+                       ldest = &new_laddrhash[new_hash];
+                       hlist_add_head(&fi->fib_lhash, ldest);
+               }
+       }
+-      net->fib_info_laddrhash = new_laddrhash;
++      fib_info_laddrhash = new_laddrhash;
+       spin_unlock_bh(&fib_info_lock);
+@@ -680,7 +681,6 @@
+ struct fib_info *fib_create_info(struct fib_config *cfg)
+ {
+-      struct net *net = cfg->fc_nlinfo.net;
+       int err;
+       struct fib_info *fi = NULL;
+       struct fib_info *ofi;
+@@ -697,10 +697,17 @@
+                       goto err_inval;
+       }
+ #endif
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      if (cfg->fc_mp_alg) {
++              if (cfg->fc_mp_alg < IP_MP_ALG_NONE ||
++                  cfg->fc_mp_alg > IP_MP_ALG_MAX)
++                      goto err_inval;
++      }
++#endif
+       err = -ENOBUFS;
+-      if (net->fib_info_cnt >= net->fib_info_hash_size) {
+-              unsigned int new_size = net->fib_info_hash_size << 1;
++      if (fib_info_cnt >= fib_hash_size) {
++              unsigned int new_size = fib_hash_size << 1;
+               struct hlist_head *new_info_hash;
+               struct hlist_head *new_laddrhash;
+               unsigned int bytes;
+@@ -717,19 +724,18 @@
+                       memset(new_info_hash, 0, bytes);
+                       memset(new_laddrhash, 0, bytes);
+-                      fib_hash_move(net, new_info_hash, new_laddrhash, new_size);
++                      fib_hash_move(new_info_hash, new_laddrhash, new_size);
+               }
+-              if (!net->fib_info_hash_size)
++              if (!fib_hash_size)
+                       goto failure;
+       }
+       fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
+       if (fi == NULL)
+               goto failure;
+-      net->fib_info_cnt++;
++      fib_info_cnt++;
+-      fi->fib_net = hold_net(net);
+       fi->fib_protocol = cfg->fc_protocol;
+       fi->fib_flags = cfg->fc_flags;
+       fi->fib_priority = cfg->fc_priority;
+@@ -785,6 +791,10 @@
+ #endif
+       }
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      fi->fib_mp_alg = cfg->fc_mp_alg;
++#endif
++
+       if (fib_props[cfg->fc_type].error) {
+               if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
+                       goto err_inval;
+@@ -801,7 +811,7 @@
+               if (nhs != 1 || nh->nh_gw)
+                       goto err_inval;
+               nh->nh_scope = RT_SCOPE_NOWHERE;
+-              nh->nh_dev = dev_get_by_index(net, fi->fib_nh->nh_oif);
++              nh->nh_dev = dev_get_by_index(fi->fib_nh->nh_oif);
+               err = -ENODEV;
+               if (nh->nh_dev == NULL)
+                       goto failure;
+@@ -815,12 +825,12 @@
+       if (fi->fib_prefsrc) {
+               if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
+                   fi->fib_prefsrc != cfg->fc_dst)
+-                      if (inet_addr_type(net, fi->fib_prefsrc) != RTN_LOCAL)
++                      if (inet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
+                               goto err_inval;
+       }
+ link_it:
+-      if ((ofi = fib_find_info(net, fi)) != NULL) {
++      if ((ofi = fib_find_info(fi)) != NULL) {
+               fi->fib_dead = 1;
+               free_fib_info(fi);
+               ofi->fib_treeref++;
+@@ -831,13 +841,11 @@
+       atomic_inc(&fi->fib_clntref);
+       spin_lock_bh(&fib_info_lock);
+       hlist_add_head(&fi->fib_hash,
+-                     &net->fib_info_hash[fib_info_hashfn(net, fi)]);
++                     &fib_info_hash[fib_info_hashfn(fi)]);
+       if (fi->fib_prefsrc) {
+               struct hlist_head *head;
+-              unsigned int hash;
+-              hash = fib_laddr_hashfn(net, fi->fib_prefsrc);
+-              head = &net->fib_info_laddrhash[hash];
++              head = &fib_info_laddrhash[fib_laddr_hashfn(fi->fib_prefsrc)];
+               hlist_add_head(&fi->fib_lhash, head);
+       }
+       change_nexthops(fi) {
+@@ -847,7 +855,7 @@
+               if (!nh->nh_dev)
+                       continue;
+               hash = fib_devindex_hashfn(nh->nh_dev->ifindex);
+-              head = &net->fib_info_devhash[hash];
++              head = &fib_info_devhash[hash];
+               hlist_add_head(&nh->nh_hash, head);
+       } endfor_nexthops(fi)
+       spin_unlock_bh(&fib_info_lock);
+@@ -932,6 +940,10 @@
+       res->type = fa->fa_type;
+       res->scope = fa->fa_scope;
+       res->fi = fa->fa_info;
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      res->netmask = mask;
++      res->network = zone & inet_make_mask(prefixlen);
++#endif
+       atomic_inc(&res->fi->fib_clntref);
+       return 0;
+ }
+@@ -1034,7 +1046,7 @@
+    - device went down -> we must shutdown all nexthops going via it.
+  */
+-int fib_sync_down(struct net *net, __be32 local, struct net_device *dev, int force)
++int fib_sync_down(__be32 local, struct net_device *dev, int force)
+ {
+       int ret = 0;
+       int scope = RT_SCOPE_NOWHERE;
+@@ -1042,9 +1054,9 @@
+       if (force)
+               scope = -1;
+-      if (local && net->fib_info_laddrhash) {
+-              unsigned int hash = fib_laddr_hashfn(net, local);
+-              struct hlist_head *head = &net->fib_info_laddrhash[hash];
++      if (local && fib_info_laddrhash) {
++              unsigned int hash = fib_laddr_hashfn(local);
++              struct hlist_head *head = &fib_info_laddrhash[hash];
+               struct hlist_node *node;
+               struct fib_info *fi;
+@@ -1059,7 +1071,7 @@
+       if (dev) {
+               struct fib_info *prev_fi = NULL;
+               unsigned int hash = fib_devindex_hashfn(dev->ifindex);
+-              struct hlist_head *head = &net->fib_info_devhash[hash];
++              struct hlist_head *head = &fib_info_devhash[hash];
+               struct hlist_node *node;
+               struct fib_nh *nh;
+@@ -1112,7 +1124,6 @@
+ int fib_sync_up(struct net_device *dev)
+ {
+-      struct net *net = dev->nd_net;
+       struct fib_info *prev_fi;
+       unsigned int hash;
+       struct hlist_head *head;
+@@ -1125,7 +1136,7 @@
+       prev_fi = NULL;
+       hash = fib_devindex_hashfn(dev->ifindex);
+-      head = &net->fib_info_devhash[hash];
++      head = &fib_info_devhash[hash];
+       ret = 0;
+       hlist_for_each_entry(nh, node, head, nh_hash) {
+@@ -1215,17 +1226,3 @@
+       spin_unlock_bh(&fib_multipath_lock);
+ }
+ #endif
 -
--#ifdef CONFIG_IPV6_PRIVACY
--/* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */
--static int __ipv6_regen_rndid(struct inet6_dev *idev)
+-int fib_info_init(struct net *net)
 -{
--regen:
--      get_random_bytes(idev->rndid, sizeof(idev->rndid));
--      idev->rndid[0] &= ~0x02;
--
--      /*
--       * <draft-ietf-ipngwg-temp-addresses-v2-00.txt>:
--       * check if generated address is not inappropriate
--       *
--       *  - Reserved subnet anycast (RFC 2526)
--       *      11111101 11....11 1xxxxxxx
--       *  - ISATAP (draft-ietf-ngtrans-isatap-13.txt) 5.1
--       *      00-00-5E-FE-xx-xx-xx-xx
--       *  - value 0
--       *  - XXX: already assigned to an address on the device
--       */
--      if (idev->rndid[0] == 0xfd &&
--          (idev->rndid[1]&idev->rndid[2]&idev->rndid[3]&idev->rndid[4]&idev->rndid[5]&idev->rndid[6]) == 0xff &&
--          (idev->rndid[7]&0x80))
--              goto regen;
--      if ((idev->rndid[0]|idev->rndid[1]) == 0) {
--              if (idev->rndid[2] == 0x5e && idev->rndid[3] == 0xfe)
--                      goto regen;
--              if ((idev->rndid[2]|idev->rndid[3]|idev->rndid[4]|idev->rndid[5]|idev->rndid[6]|idev->rndid[7]) == 0x00)
--                      goto regen;
--      }
--
+-      net->fib_info_devhash = kzalloc(
+-              sizeof(struct hlist_head)*DEVINDEX_HASHSIZE, GFP_KERNEL);
+-      if (!net->fib_info_devhash)
+-              return -ENOMEM;
 -      return 0;
 -}
 -
--static void ipv6_regen_rndid(unsigned long data)
--{
--      struct inet6_dev *idev = (struct inet6_dev *) data;
--      unsigned long expires;
--
--      rcu_read_lock_bh();
--      write_lock_bh(&idev->lock);
--
--      if (idev->dead)
--              goto out;
--
--      if (__ipv6_regen_rndid(idev) < 0)
--              goto out;
--
--      expires = jiffies +
--              idev->cnf.temp_prefered_lft * HZ -
--              idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor;
--      if (time_before(expires, jiffies)) {
--              printk(KERN_WARNING
--                      "ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n",
--                      idev->dev->name);
--              goto out;
--      }
--
--      if (!mod_timer(&idev->regen_timer, expires))
--              in6_dev_hold(idev);
--
--out:
--      write_unlock_bh(&idev->lock);
--      rcu_read_unlock_bh();
--      in6_dev_put(idev);
--}
--
--static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr) {
--      int ret = 0;
--
--      if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0)
--              ret = __ipv6_regen_rndid(idev);
--      return ret;
--}
--#endif
--
--/*
-- *    Add prefix route.
-- */
--
--static void
--addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
--                    unsigned long expires, u32 flags)
--{
--      struct fib6_config cfg = {
--              .fc_table = RT6_TABLE_PREFIX,
--              .fc_metric = IP6_RT_PRIO_ADDRCONF,
--              .fc_ifindex = dev->ifindex,
--              .fc_expires = expires,
--              .fc_dst_len = plen,
--              .fc_flags = RTF_UP | flags,
--      };
--
--      ipv6_addr_copy(&cfg.fc_dst, pfx);
--
--      /* Prevent useless cloning on PtP SIT.
--         This thing is done here expecting that the whole
--         class of non-broadcast devices need not cloning.
--       */
--#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
--      if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
--              cfg.fc_flags |= RTF_NONEXTHOP;
--#endif
--
--      ip6_route_add(&cfg);
--}
--
--/* Create "default" multicast route to the interface */
--
--static void addrconf_add_mroute(struct net_device *dev)
--{
--      struct fib6_config cfg = {
--              .fc_table = RT6_TABLE_LOCAL,
--              .fc_metric = IP6_RT_PRIO_ADDRCONF,
--              .fc_ifindex = dev->ifindex,
--              .fc_dst_len = 8,
--              .fc_flags = RTF_UP,
--      };
--
--      ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0);
--
--      ip6_route_add(&cfg);
--}
--
--#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
--static void sit_route_add(struct net_device *dev)
+-void fib_info_exit(struct net *net)
 -{
--      struct fib6_config cfg = {
--              .fc_table = RT6_TABLE_MAIN,
--              .fc_metric = IP6_RT_PRIO_ADDRCONF,
--              .fc_ifindex = dev->ifindex,
--              .fc_dst_len = 96,
--              .fc_flags = RTF_UP | RTF_NONEXTHOP,
--      };
--
--      /* prefix length - 96 bits "::d.d.d.d" */
--      ip6_route_add(&cfg);
+-      kfree(net->fib_info_devhash);
 -}
--#endif
--
--static void addrconf_add_lroute(struct net_device *dev)
+diff -Nurb linux-2.6.22-590/net/ipv4/fib_trie.c linux-2.6.22-570/net/ipv4/fib_trie.c
+--- linux-2.6.22-590/net/ipv4/fib_trie.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/fib_trie.c       2007-07-08 19:32:17.000000000 -0400
+@@ -78,7 +78,6 @@
+ #include <net/route.h>
+ #include <net/tcp.h>
+ #include <net/sock.h>
+-#include <net/net_namespace.h>
+ #include <net/ip_fib.h>
+ #include "fib_lookup.h"
+@@ -173,6 +172,7 @@
+ static void tnode_free(struct tnode *tn);
+ static struct kmem_cache *fn_alias_kmem __read_mostly;
++static struct trie *trie_local = NULL, *trie_main = NULL;
+ /* rcu_read_lock needs to be hold by caller from readside */
+@@ -290,10 +290,11 @@
+       WARN_ON(tn && tn->pos+tn->bits > 32);
+ }
+-static const int halve_threshold = 25;
+-static const int inflate_threshold = 50;
+-static const int halve_threshold_root = 15;
+-static const int inflate_threshold_root = 25;
++static int halve_threshold = 25;
++static int inflate_threshold = 50;
++static int halve_threshold_root = 8;
++static int inflate_threshold_root = 15;
++
+ static void __alias_free_mem(struct rcu_head *head)
+ {
+@@ -1770,10 +1771,11 @@
+       return found;
+ }
++static int trie_last_dflt = -1;
++
+ static void
+ fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
+ {
+-      struct net *net = flp->fl_net;
+       struct trie *t = (struct trie *) tb->tb_data;
+       int order, last_idx;
+       struct fib_info *fi = NULL;
+@@ -1817,28 +1819,28 @@
+                       if (next_fi != res->fi)
+                               break;
+               } else if (!fib_detect_death(fi, order, &last_resort,
+-                                           &last_idx, &net->trie_last_dflt)) {
++                                           &last_idx, &trie_last_dflt)) {
+                       if (res->fi)
+                               fib_info_put(res->fi);
+                       res->fi = fi;
+                       atomic_inc(&fi->fib_clntref);
+-                      net->trie_last_dflt = order;
++                      trie_last_dflt = order;
+                       goto out;
+               }
+               fi = next_fi;
+               order++;
+       }
+       if (order <= 0 || fi == NULL) {
+-              net->trie_last_dflt = -1;
++              trie_last_dflt = -1;
+               goto out;
+       }
+-      if (!fib_detect_death(fi, order, &last_resort, &last_idx, &net->trie_last_dflt)) {
++      if (!fib_detect_death(fi, order, &last_resort, &last_idx, &trie_last_dflt)) {
+               if (res->fi)
+                       fib_info_put(res->fi);
+               res->fi = fi;
+               atomic_inc(&fi->fib_clntref);
+-              net->trie_last_dflt = order;
++              trie_last_dflt = order;
+               goto out;
+       }
+       if (last_idx >= 0) {
+@@ -1848,7 +1850,7 @@
+               if (last_resort)
+                       atomic_inc(&last_resort->fib_clntref);
+       }
+-      net->trie_last_dflt = last_idx;
++      trie_last_dflt = last_idx;
+  out:;
+       rcu_read_unlock();
+ }
+@@ -1955,15 +1957,11 @@
+ /* Fix more generic FIB names for init later */
+-void fib_hash_exit(struct fib_table *tb)
 -{
--      struct in6_addr addr;
--
--      ipv6_addr_set(&addr,  htonl(0xFE800000), 0, 0, 0);
--      addrconf_prefix_route(&addr, 64, dev, 0, 0);
+-      if (!tb)
+-              return;
+-      fn_trie_flush(tb);
+-      kfree(tb);
 -}
 -
--static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
--{
--      struct inet6_dev *idev;
--
--      ASSERT_RTNL();
++#ifdef CONFIG_IP_MULTIPLE_TABLES
+ struct fib_table * fib_hash_init(u32 id)
++#else
++struct fib_table * __init fib_hash_init(u32 id)
++#endif
+ {
+       struct fib_table *tb;
+       struct trie *t;
+@@ -1993,6 +1991,11 @@
+       trie_init(t);
+       if (id == RT_TABLE_LOCAL)
++              trie_local = t;
++      else if (id == RT_TABLE_MAIN)
++              trie_main = t;
++
++      if (id == RT_TABLE_LOCAL)
+               printk(KERN_INFO "IPv4 FIB: Using LC-trie version %s\n", VERSION);
+       return tb;
+@@ -2001,8 +2004,6 @@
+ #ifdef CONFIG_PROC_FS
+ /* Depth first Trie walk iterator */
+ struct fib_trie_iter {
+-      struct net *net;
+-      struct trie *trie_local, *trie_main;
+       struct tnode *tnode;
+       struct trie *trie;
+       unsigned index;
+@@ -2169,21 +2170,7 @@
+ static int fib_triestat_seq_show(struct seq_file *seq, void *v)
+ {
+-      struct net *net = seq->private;
+-      struct trie *trie_local, *trie_main;
+       struct trie_stat *stat;
+-      struct fib_table *tb;
 -
--      if ((idev = ipv6_find_idev(dev)) == NULL)
--              return NULL;
+-      trie_local = NULL;
+-      tb = fib_get_table(net, RT_TABLE_LOCAL);
+-      if (tb)
+-              trie_local = (struct trie *) tb->tb_data;
 -
--      /* Add default multicast route */
--      addrconf_add_mroute(dev);
+-      trie_main = NULL;
+-      tb = fib_get_table(net, RT_TABLE_MAIN);
+-      if (tb)
+-              trie_main = (struct trie *) tb->tb_data;
 -
--      /* Add link local route */
--      addrconf_add_lroute(dev);
--      return idev;
+       stat = kmalloc(sizeof(*stat), GFP_KERNEL);
+       if (!stat)
+@@ -2210,15 +2197,7 @@
+ static int fib_triestat_seq_open(struct inode *inode, struct file *file)
+ {
+-      return single_open(file, fib_triestat_seq_show, 
+-                              get_net(PROC_NET(inode)));
 -}
 -
--void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
+-static int fib_triestat_seq_release(struct inode *inode, struct file *file)
 -{
--      struct prefix_info *pinfo;
--      __u32 valid_lft;
--      __u32 prefered_lft;
--      int addr_type;
--      unsigned long rt_expires;
--      struct inet6_dev *in6_dev;
--
--      pinfo = (struct prefix_info *) opt;
--
--      if (len < sizeof(struct prefix_info)) {
--              ADBG(("addrconf: prefix option too short\n"));
--              return;
--      }
--
--      /*
--       *      Validation checks ([ADDRCONF], page 19)
--       */
--
--      addr_type = ipv6_addr_type(&pinfo->prefix);
--
--      if (addr_type & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL))
--              return;
--
--      valid_lft = ntohl(pinfo->valid);
--      prefered_lft = ntohl(pinfo->prefered);
--
--      if (prefered_lft > valid_lft) {
--              if (net_ratelimit())
--                      printk(KERN_WARNING "addrconf: prefix option has invalid lifetime\n");
--              return;
--      }
--
--      in6_dev = in6_dev_get(dev);
--
--      if (in6_dev == NULL) {
--              if (net_ratelimit())
--                      printk(KERN_DEBUG "addrconf: device %s not configured\n", dev->name);
--              return;
--      }
--
--      /*
--       *      Two things going on here:
--       *      1) Add routes for on-link prefixes
--       *      2) Configure prefixes with the auto flag set
--       */
--
--      /* Avoid arithmetic overflow. Really, we could
--         save rt_expires in seconds, likely valid_lft,
--         but it would require division in fib gc, that it
--         not good.
--       */
--      if (valid_lft >= 0x7FFFFFFF/HZ)
--              rt_expires = 0x7FFFFFFF - (0x7FFFFFFF % HZ);
--      else
--              rt_expires = valid_lft * HZ;
+-      struct seq_file *seq = file->private_data;
+-      put_net(seq->private);
+-      return single_release(inode, file);
++      return single_open(file, fib_triestat_seq_show, NULL);
+ }
+ static const struct file_operations fib_triestat_fops = {
+@@ -2226,7 +2205,7 @@
+       .open   = fib_triestat_seq_open,
+       .read   = seq_read,
+       .llseek = seq_lseek,
+-      .release = fib_triestat_seq_release,
++      .release = single_release,
+ };
+ static struct node *fib_trie_get_idx(struct fib_trie_iter *iter,
+@@ -2235,13 +2214,13 @@
+       loff_t idx = 0;
+       struct node *n;
+-      for (n = fib_trie_get_first(iter, iter->trie_local);
++      for (n = fib_trie_get_first(iter, trie_local);
+            n; ++idx, n = fib_trie_get_next(iter)) {
+               if (pos == idx)
+                       return n;
+       }
+-      for (n = fib_trie_get_first(iter, iter->trie_main);
++      for (n = fib_trie_get_first(iter, trie_main);
+            n; ++idx, n = fib_trie_get_next(iter)) {
+               if (pos == idx)
+                       return n;
+@@ -2251,23 +2230,10 @@
+ static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+-      struct fib_trie_iter *iter = seq->private;
+-      struct fib_table *tb;
 -
--      /*
--       * We convert this (in jiffies) to clock_t later.
--       * Avoid arithmetic overflow there as well.
--       * Overflow can happen only if HZ < USER_HZ.
--       */
--      if (HZ < USER_HZ && rt_expires > 0x7FFFFFFF / USER_HZ)
--              rt_expires = 0x7FFFFFFF / USER_HZ;
--
--      if (pinfo->onlink) {
--              struct rt6_info *rt;
--              rt = rt6_lookup(&pinfo->prefix, NULL, dev->ifindex, 1);
--
--              if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
--                      if (rt->rt6i_flags&RTF_EXPIRES) {
--                              if (valid_lft == 0) {
--                                      ip6_del_rt(rt);
--                                      rt = NULL;
--                              } else {
--                                      rt->rt6i_expires = jiffies + rt_expires;
--                              }
--                      }
--              } else if (valid_lft) {
--                      addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
--                                            dev, jiffies_to_clock_t(rt_expires), RTF_ADDRCONF|RTF_EXPIRES|RTF_PREFIX_RT);
--              }
--              if (rt)
--                      dst_release(&rt->u.dst);
+-      if (!iter->trie_local) {
+-              tb = fib_get_table(iter->net, RT_TABLE_LOCAL);
+-              if (tb)
+-                      iter->trie_local = (struct trie *) tb->tb_data;
 -      }
--
--      /* Try to figure out our local address for this prefix */
--
--      if (pinfo->autoconf && in6_dev->cnf.autoconf) {
--              struct inet6_ifaddr * ifp;
--              struct in6_addr addr;
--              int create = 0, update_lft = 0;
--
--              if (pinfo->prefix_len == 64) {
--                      memcpy(&addr, &pinfo->prefix, 8);
--                      if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
--                          ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
--                              in6_dev_put(in6_dev);
--                              return;
--                      }
--                      goto ok;
--              }
--              if (net_ratelimit())
--                      printk(KERN_DEBUG "IPv6 addrconf: prefix with wrong length %d\n",
--                             pinfo->prefix_len);
--              in6_dev_put(in6_dev);
--              return;
--
--ok:
--
--              ifp = ipv6_get_ifaddr(&addr, dev, 1);
--
--              if (ifp == NULL && valid_lft) {
--                      int max_addresses = in6_dev->cnf.max_addresses;
--                      u32 addr_flags = 0;
--
--#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
--                      if (in6_dev->cnf.optimistic_dad &&
--                          !ipv6_devconf.forwarding)
--                              addr_flags = IFA_F_OPTIMISTIC;
--#endif
--
--                      /* Do not allow to create too much of autoconfigured
--                       * addresses; this would be too easy way to crash kernel.
--                       */
--                      if (!max_addresses ||
--                          ipv6_count_addresses(in6_dev) < max_addresses)
--                              ifp = ipv6_add_addr(in6_dev, &addr, pinfo->prefix_len,
--                                                  addr_type&IPV6_ADDR_SCOPE_MASK,
--                                                  addr_flags);
--
--                      if (!ifp || IS_ERR(ifp)) {
--                              in6_dev_put(in6_dev);
--                              return;
--                      }
--
--                      update_lft = create = 1;
--                      ifp->cstamp = jiffies;
--                      addrconf_dad_start(ifp, RTF_ADDRCONF|RTF_PREFIX_RT);
--              }
--
--              if (ifp) {
--                      int flags;
--                      unsigned long now;
--#ifdef CONFIG_IPV6_PRIVACY
--                      struct inet6_ifaddr *ift;
--#endif
--                      u32 stored_lft;
--
--                      /* update lifetime (RFC2462 5.5.3 e) */
--                      spin_lock(&ifp->lock);
--                      now = jiffies;
--                      if (ifp->valid_lft > (now - ifp->tstamp) / HZ)
--                              stored_lft = ifp->valid_lft - (now - ifp->tstamp) / HZ;
--                      else
--                              stored_lft = 0;
--                      if (!update_lft && stored_lft) {
--                              if (valid_lft > MIN_VALID_LIFETIME ||
--                                  valid_lft > stored_lft)
--                                      update_lft = 1;
--                              else if (stored_lft <= MIN_VALID_LIFETIME) {
--                                      /* valid_lft <= stored_lft is always true */
--                                      /* XXX: IPsec */
--                                      update_lft = 0;
--                              } else {
--                                      valid_lft = MIN_VALID_LIFETIME;
--                                      if (valid_lft < prefered_lft)
--                                              prefered_lft = valid_lft;
--                                      update_lft = 1;
--                              }
--                      }
--
--                      if (update_lft) {
--                              ifp->valid_lft = valid_lft;
--                              ifp->prefered_lft = prefered_lft;
--                              ifp->tstamp = now;
--                              flags = ifp->flags;
--                              ifp->flags &= ~IFA_F_DEPRECATED;
--                              spin_unlock(&ifp->lock);
--
--                              if (!(flags&IFA_F_TENTATIVE))
--                                      ipv6_ifa_notify(0, ifp);
--                      } else
--                              spin_unlock(&ifp->lock);
--
--#ifdef CONFIG_IPV6_PRIVACY
--                      read_lock_bh(&in6_dev->lock);
--                      /* update all temporary addresses in the list */
--                      for (ift=in6_dev->tempaddr_list; ift; ift=ift->tmp_next) {
--                              /*
--                               * When adjusting the lifetimes of an existing
--                               * temporary address, only lower the lifetimes.
--                               * Implementations must not increase the
--                               * lifetimes of an existing temporary address
--                               * when processing a Prefix Information Option.
--                               */
--                              spin_lock(&ift->lock);
--                              flags = ift->flags;
--                              if (ift->valid_lft > valid_lft &&
--                                  ift->valid_lft - valid_lft > (jiffies - ift->tstamp) / HZ)
--                                      ift->valid_lft = valid_lft + (jiffies - ift->tstamp) / HZ;
--                              if (ift->prefered_lft > prefered_lft &&
--                                  ift->prefered_lft - prefered_lft > (jiffies - ift->tstamp) / HZ)
--                                      ift->prefered_lft = prefered_lft + (jiffies - ift->tstamp) / HZ;
--                              spin_unlock(&ift->lock);
--                              if (!(flags&IFA_F_TENTATIVE))
--                                      ipv6_ifa_notify(0, ift);
--                      }
--
--                      if (create && in6_dev->cnf.use_tempaddr > 0) {
--                              /*
--                               * When a new public address is created as described in [ADDRCONF],
--                               * also create a new temporary address.
--                               */
--                              read_unlock_bh(&in6_dev->lock);
--                              ipv6_create_tempaddr(ifp, NULL);
--                      } else {
--                              read_unlock_bh(&in6_dev->lock);
--                      }
--#endif
--                      in6_ifa_put(ifp);
--                      addrconf_verify(0);
--              }
+-      if (!iter->trie_main) {
+-              tb = fib_get_table(iter->net, RT_TABLE_MAIN);
+-              if (tb)
+-                      iter->trie_main = (struct trie *) tb->tb_data;
 -      }
--      inet6_prefix_notify(RTM_NEWPREFIX, in6_dev, pinfo);
--      in6_dev_put(in6_dev);
--}
--
--/*
-- *    Set destination address.
-- *    Special case for SIT interfaces where we create a new "virtual"
-- *    device.
-- */
--int addrconf_set_dstaddr(void __user *arg)
+       rcu_read_lock();
+       if (*pos == 0)
+               return SEQ_START_TOKEN;
+-      return fib_trie_get_idx(iter, *pos - 1);
++      return fib_trie_get_idx(seq->private, *pos - 1);
+ }
+ static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+@@ -2285,8 +2251,8 @@
+               return v;
+       /* continue scan in next trie */
+-      if (iter->trie == iter->trie_local)
+-              return fib_trie_get_first(iter, iter->trie_main);
++      if (iter->trie == trie_local)
++              return fib_trie_get_first(iter, trie_main);
+       return NULL;
+ }
+@@ -2352,7 +2318,7 @@
+               return 0;
+       if (!NODE_PARENT(n)) {
+-              if (iter->trie == iter->trie_local)
++              if (iter->trie == trie_local)
+                       seq_puts(seq, "<local>:\n");
+               else
+                       seq_puts(seq, "<main>:\n");
+@@ -2418,7 +2384,6 @@
+       seq          = file->private_data;
+       seq->private = s;
+       memset(s, 0, sizeof(*s));
+-      s->net = get_net(PROC_NET(inode));
+ out:
+       return rc;
+ out_kfree:
+@@ -2426,20 +2391,12 @@
+       goto out;
+ }
+-static int fib_trie_seq_release(struct inode *inode, struct file *file)
 -{
--      struct in6_ifreq ireq;
--      struct net_device *dev;
--      int err = -EINVAL;
--
--      rtnl_lock();
--
--      err = -EFAULT;
--      if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
--              goto err_exit;
--
--      dev = __dev_get_by_index(ireq.ifr6_ifindex);
--
--      err = -ENODEV;
--      if (dev == NULL)
--              goto err_exit;
--
--#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
--      if (dev->type == ARPHRD_SIT) {
--              struct ifreq ifr;
--              mm_segment_t    oldfs;
--              struct ip_tunnel_parm p;
--
--              err = -EADDRNOTAVAIL;
--              if (!(ipv6_addr_type(&ireq.ifr6_addr) & IPV6_ADDR_COMPATv4))
--                      goto err_exit;
--
--              memset(&p, 0, sizeof(p));
--              p.iph.daddr = ireq.ifr6_addr.s6_addr32[3];
--              p.iph.saddr = 0;
--              p.iph.version = 4;
--              p.iph.ihl = 5;
--              p.iph.protocol = IPPROTO_IPV6;
--              p.iph.ttl = 64;
--              ifr.ifr_ifru.ifru_data = (void __user *)&p;
--
--              oldfs = get_fs(); set_fs(KERNEL_DS);
--              err = dev->do_ioctl(dev, &ifr, SIOCADDTUNNEL);
--              set_fs(oldfs);
--
--              if (err == 0) {
--                      err = -ENOBUFS;
--                      if ((dev = __dev_get_by_name(p.name)) == NULL)
--                              goto err_exit;
--                      err = dev_open(dev);
--              }
--      }
--#endif
--
--err_exit:
--      rtnl_unlock();
--      return err;
+-      struct seq_file *seq = file->private_data;
+-      struct fib_trie_iter *iter = seq->private;
+-      put_net(iter->net);
+-      return seq_release_private(inode, file);
 -}
 -
--/*
-- *    Manual configuration of address on an interface
-- */
--static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
--                        __u8 ifa_flags, __u32 prefered_lft, __u32 valid_lft)
--{
--      struct inet6_ifaddr *ifp;
--      struct inet6_dev *idev;
--      struct net_device *dev;
--      int scope;
--      u32 flags = RTF_EXPIRES;
--
--      ASSERT_RTNL();
--
--      /* check the lifetime */
--      if (!valid_lft || prefered_lft > valid_lft)
--              return -EINVAL;
--
--      if ((dev = __dev_get_by_index(ifindex)) == NULL)
--              return -ENODEV;
--
--      if ((idev = addrconf_add_dev(dev)) == NULL)
--              return -ENOBUFS;
--
--      scope = ipv6_addr_scope(pfx);
--
--      if (valid_lft == INFINITY_LIFE_TIME) {
--              ifa_flags |= IFA_F_PERMANENT;
--              flags = 0;
--      } else if (valid_lft >= 0x7FFFFFFF/HZ)
--              valid_lft = 0x7FFFFFFF/HZ;
--
--      if (prefered_lft == 0)
--              ifa_flags |= IFA_F_DEPRECATED;
--      else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
--               (prefered_lft != INFINITY_LIFE_TIME))
--              prefered_lft = 0x7FFFFFFF/HZ;
--
--      ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags);
--
--      if (!IS_ERR(ifp)) {
--              spin_lock_bh(&ifp->lock);
--              ifp->valid_lft = valid_lft;
--              ifp->prefered_lft = prefered_lft;
--              ifp->tstamp = jiffies;
--              spin_unlock_bh(&ifp->lock);
--
--              addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
--                                    jiffies_to_clock_t(valid_lft * HZ), flags);
--              /*
--               * Note that section 3.1 of RFC 4429 indicates
--               * that the Optimistic flag should not be set for
--               * manually configured addresses
--               */
--              addrconf_dad_start(ifp, 0);
--              in6_ifa_put(ifp);
--              addrconf_verify(0);
--              return 0;
--      }
--
--      return PTR_ERR(ifp);
--}
+ static const struct file_operations fib_trie_fops = {
+       .owner  = THIS_MODULE,
+       .open   = fib_trie_seq_open,
+       .read   = seq_read,
+       .llseek = seq_lseek,
+-      .release = fib_trie_seq_release,
++      .release = seq_release_private,
+ };
+ static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
+@@ -2477,7 +2434,7 @@
+               return 0;
+       }
+-      if (iter->trie == iter->trie_local)
++      if (iter->trie == trie_local)
+               return 0;
+       if (IS_TNODE(l))
+               return 0;
+@@ -2548,7 +2505,6 @@
+       seq          = file->private_data;
+       seq->private = s;
+       memset(s, 0, sizeof(*s));
+-      s->net = get_net(PROC_NET(inode));
+ out:
+       return rc;
+ out_kfree:
+@@ -2561,37 +2517,35 @@
+       .open   = fib_route_seq_open,
+       .read   = seq_read,
+       .llseek = seq_lseek,
+-      .release = fib_trie_seq_release,
++      .release = seq_release_private,
+ };
+-int fib_proc_init(struct net *net)
++int __init fib_proc_init(void)
+ {
+-      net->trie_last_dflt = -1;
 -
--static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen)
+-      if (!proc_net_fops_create(net, "fib_trie", S_IRUGO, &fib_trie_fops))
++      if (!proc_net_fops_create("fib_trie", S_IRUGO, &fib_trie_fops))
+               goto out1;
+-      if (!proc_net_fops_create(net, "fib_triestat", S_IRUGO, &fib_triestat_fops))
++      if (!proc_net_fops_create("fib_triestat", S_IRUGO, &fib_triestat_fops))
+               goto out2;
+-      if (!proc_net_fops_create(net, "route", S_IRUGO, &fib_route_fops))
++      if (!proc_net_fops_create("route", S_IRUGO, &fib_route_fops))
+               goto out3;
+       return 0;
+ out3:
+-      proc_net_remove(net, "fib_triestat");
++      proc_net_remove("fib_triestat");
+ out2:
+-      proc_net_remove(net, "fib_trie");
++      proc_net_remove("fib_trie");
+ out1:
+       return -ENOMEM;
+ }
+-void fib_proc_exit(struct net *net)
++void __init fib_proc_exit(void)
+ {
+-      proc_net_remove(net, "fib_trie");
+-      proc_net_remove(net, "fib_triestat");
+-      proc_net_remove(net, "route");
++      proc_net_remove("fib_trie");
++      proc_net_remove("fib_triestat");
++      proc_net_remove("route");
+ }
+ #endif /* CONFIG_PROC_FS */
+diff -Nurb linux-2.6.22-590/net/ipv4/icmp.c linux-2.6.22-570/net/ipv4/icmp.c
+--- linux-2.6.22-590/net/ipv4/icmp.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/icmp.c   2008-01-23 19:16:10.000000000 -0500
+@@ -229,13 +229,14 @@
+  *
+  *    On SMP we have one ICMP socket per-cpu.
+  */
+-#define icmp_socket(NET) (*per_cpu_ptr((NET)->__icmp_socket, smp_processor_id()))
++static DEFINE_PER_CPU(struct socket *, __icmp_socket) = NULL;
++#define icmp_socket   __get_cpu_var(__icmp_socket)
+-static __inline__ int icmp_xmit_lock(struct net *net)
++static __inline__ int icmp_xmit_lock(void)
+ {
+       local_bh_disable();
+-      if (unlikely(!spin_trylock(&icmp_socket(net)->sk->sk_lock.slock))) {
++      if (unlikely(!spin_trylock(&icmp_socket->sk->sk_lock.slock))) {
+               /* This can happen if the output path signals a
+                * dst_link_failure() for an outgoing ICMP packet.
+                */
+@@ -245,9 +246,9 @@
+       return 0;
+ }
+-static void icmp_xmit_unlock(struct net *net)
++static void icmp_xmit_unlock(void)
+ {
+-      spin_unlock_bh(&icmp_socket(net)->sk->sk_lock.slock);
++      spin_unlock_bh(&icmp_socket->sk->sk_lock.slock);
+ }
+ /*
+@@ -346,20 +347,19 @@
+ static void icmp_push_reply(struct icmp_bxm *icmp_param,
+                           struct ipcm_cookie *ipc, struct rtable *rt)
+ {
+-      struct net *net = icmp_param->skb->dev->nd_net;
+       struct sk_buff *skb;
+-      if (ip_append_data(icmp_socket(net)->sk, icmp_glue_bits, icmp_param,
++      if (ip_append_data(icmp_socket->sk, icmp_glue_bits, icmp_param,
+                          icmp_param->data_len+icmp_param->head_len,
+                          icmp_param->head_len,
+                          ipc, rt, MSG_DONTWAIT) < 0)
+-              ip_flush_pending_frames(icmp_socket(net)->sk);
+-      else if ((skb = skb_peek(&icmp_socket(net)->sk->sk_write_queue)) != NULL) {
++              ip_flush_pending_frames(icmp_socket->sk);
++      else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) {
+               struct icmphdr *icmph = icmp_hdr(skb);
+               __wsum csum = 0;
+               struct sk_buff *skb1;
+-              skb_queue_walk(&icmp_socket(net)->sk->sk_write_queue, skb1) {
++              skb_queue_walk(&icmp_socket->sk->sk_write_queue, skb1) {
+                       csum = csum_add(csum, skb1->csum);
+               }
+               csum = csum_partial_copy_nocheck((void *)&icmp_param->data,
+@@ -367,7 +367,7 @@
+                                                icmp_param->head_len, csum);
+               icmph->checksum = csum_fold(csum);
+               skb->ip_summed = CHECKSUM_NONE;
+-              ip_push_pending_frames(icmp_socket(net)->sk);
++              ip_push_pending_frames(icmp_socket->sk);
+       }
+ }
+@@ -377,8 +377,7 @@
+ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
+ {
+-      struct net *net = icmp_param->skb->dev->nd_net;
+-      struct sock *sk = icmp_socket(net)->sk;
++      struct sock *sk = icmp_socket->sk;
+       struct inet_sock *inet = inet_sk(sk);
+       struct ipcm_cookie ipc;
+       struct rtable *rt = (struct rtable *)skb->dst;
+@@ -387,7 +386,7 @@
+       if (ip_options_echo(&icmp_param->replyopts, skb))
+               return;
+-      if (icmp_xmit_lock(net))
++      if (icmp_xmit_lock())
+               return;
+       icmp_param->data.icmph.checksum = 0;
+@@ -402,8 +401,7 @@
+                       daddr = icmp_param->replyopts.faddr;
+       }
+       {
+-              struct flowi fl = { .fl_net = net,
+-                                  .nl_u = { .ip4_u =
++              struct flowi fl = { .nl_u = { .ip4_u =
+                                             { .daddr = daddr,
+                                               .saddr = rt->rt_spec_dst,
+                                               .tos = RT_TOS(ip_hdr(skb)->tos) } },
+@@ -417,7 +415,7 @@
+               icmp_push_reply(icmp_param, &ipc, rt);
+       ip_rt_put(rt);
+ out_unlock:
+-      icmp_xmit_unlock(net);
++      icmp_xmit_unlock();
+ }
+@@ -438,7 +436,6 @@
+       int room;
+       struct icmp_bxm icmp_param;
+       struct rtable *rt = (struct rtable *)skb_in->dst;
+-      struct net *net;
+       struct ipcm_cookie ipc;
+       __be32 saddr;
+       u8  tos;
+@@ -446,7 +443,6 @@
+       if (!rt)
+               goto out;
+-      net = rt->fl.fl_net;
+       /*
+        *      Find the original header. It is expected to be valid, of course.
+        *      Check this, icmp_send is called from the most obscure devices
+@@ -509,7 +505,7 @@
+               }
+       }
+-      if (icmp_xmit_lock(net))
++      if (icmp_xmit_lock())
+               return;
+       /*
+@@ -521,7 +517,7 @@
+               struct net_device *dev = NULL;
+               if (rt->fl.iif && sysctl_icmp_errors_use_inbound_ifaddr)
+-                      dev = dev_get_by_index(&init_net, rt->fl.iif);
++                      dev = dev_get_by_index(rt->fl.iif);
+               if (dev) {
+                       saddr = inet_select_addr(dev, 0, RT_SCOPE_LINK);
+@@ -549,13 +545,12 @@
+       icmp_param.skb    = skb_in;
+       icmp_param.offset = skb_network_offset(skb_in);
+       icmp_out_count(icmp_param.data.icmph.type);
+-      inet_sk(icmp_socket(net)->sk)->tos = tos;
++      inet_sk(icmp_socket->sk)->tos = tos;
+       ipc.addr = iph->saddr;
+       ipc.opt = &icmp_param.replyopts;
+       {
+               struct flowi fl = {
+-                      .fl_net = net,
+                       .nl_u = {
+                               .ip4_u = {
+                                       .daddr = icmp_param.replyopts.srr ?
+@@ -598,7 +593,7 @@
+ ende:
+       ip_rt_put(rt);
+ out_unlock:
+-      icmp_xmit_unlock(net);
++      icmp_xmit_unlock();
+ out:;
+ }
+@@ -609,7 +604,6 @@
+ static void icmp_unreach(struct sk_buff *skb)
+ {
+-      struct net *net = skb->dev->nd_net;
+       struct iphdr *iph;
+       struct icmphdr *icmph;
+       int hash, protocol;
+@@ -640,7 +634,7 @@
+               case ICMP_PORT_UNREACH:
+                       break;
+               case ICMP_FRAG_NEEDED:
+-                      if (net->sysctl_ipv4_no_pmtu_disc) {
++                      if (ipv4_config.no_pmtu_disc) {
+                               LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: "
+                                                        "fragmentation needed "
+                                                        "and DF set.\n",
+@@ -684,7 +678,7 @@
+        */
+       if (!sysctl_icmp_ignore_bogus_error_responses &&
+-          inet_addr_type(net, iph->daddr) == RTN_BROADCAST) {
++          inet_addr_type(iph->daddr) == RTN_BROADCAST) {
+               if (net_ratelimit())
+                       printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP "
+                                           "type %u, code %u "
+@@ -713,7 +707,7 @@
+       hash = protocol & (MAX_INET_PROTOS - 1);
+       read_lock(&raw_v4_lock);
+       if ((raw_sk = sk_head(&raw_v4_htable[hash])) != NULL) {
+-              while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol, iph->daddr,
++              while ((raw_sk = __raw_v4_lookup(raw_sk, protocol, iph->daddr,
+                                                iph->saddr,
+                                                skb->dev->ifindex, skb->skb_tag)) != NULL) {
+                       raw_err(raw_sk, skb, info);
+@@ -1185,54 +1179,29 @@
+       },
+ };
+-static void icmp_net_exit(struct net *net)
 -{
--      struct inet6_ifaddr *ifp;
--      struct inet6_dev *idev;
--      struct net_device *dev;
--
--      if ((dev = __dev_get_by_index(ifindex)) == NULL)
--              return -ENODEV;
--
--      if ((idev = __in6_dev_get(dev)) == NULL)
--              return -ENXIO;
--
--      read_lock_bh(&idev->lock);
--      for (ifp = idev->addr_list; ifp; ifp=ifp->if_next) {
--              if (ifp->prefix_len == plen &&
--                  ipv6_addr_equal(pfx, &ifp->addr)) {
--                      in6_ifa_hold(ifp);
--                      read_unlock_bh(&idev->lock);
--
--                      ipv6_del_addr(ifp);
+-      struct socket **sock;
+-      int i;
 -
--                      /* If the last address is deleted administratively,
--                         disable IPv6 on this interface.
--                       */
--                      if (idev->addr_list == NULL)
--                              addrconf_ifdown(idev->dev, 1);
--                      return 0;
--              }
+-      for_each_possible_cpu(i) {
+-              sock = percpu_ptr(net->__icmp_socket, i);
+-              if (!*sock)
+-                      continue;
+-              /* At the last minute lie and say this is a socket for
+-               * the initial network namespace.  So the socket will
+-               * be safe to free. 
+-               */
+-              (*sock)->sk->sk_net = get_net(&init_net);
+-              sock_release(*sock);
+-              *sock = NULL;
 -      }
--      read_unlock_bh(&idev->lock);
--      return -EADDRNOTAVAIL;
--}
--
--
--int addrconf_add_ifaddr(void __user *arg)
--{
--      struct in6_ifreq ireq;
--      int err;
--
--      if (!capable(CAP_NET_ADMIN))
--              return -EPERM;
--
--      if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
--              return -EFAULT;
--
--      rtnl_lock();
--      err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen,
--                           IFA_F_PERMANENT, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
--      rtnl_unlock();
--      return err;
+-      percpu_free(net->__icmp_socket);
 -}
 -
--int addrconf_del_ifaddr(void __user *arg)
--{
--      struct in6_ifreq ireq;
--      int err;
--
--      if (!capable(CAP_NET_ADMIN))
--              return -EPERM;
--
--      if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
--              return -EFAULT;
+-static int icmp_net_init(struct net *net)
++void __init icmp_init(struct net_proto_family *ops)
+ {
+-      struct socket **sock;
+       struct inet_sock *inet;
+-              int err;
+       int i;
+-      net->__icmp_socket = alloc_percpu(struct socket *);
+-      if (!net->__icmp_socket)
+-              return -ENOMEM;
+-      
+       for_each_possible_cpu(i) {
++              int err;
+-              sock = percpu_ptr(net->__icmp_socket, i);
++              err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
++                                     &per_cpu(__icmp_socket, i));
+-              err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP, sock);
+               if (err < 0)
+-                      goto fail;
++                      panic("Failed to create the ICMP control socket.\n");
+-              (*sock)->sk->sk_allocation = GFP_ATOMIC;
++              per_cpu(__icmp_socket, i)->sk->sk_allocation = GFP_ATOMIC;
+               /* Enough space for 2 64K ICMP packets, including
+                * sk_buff struct overhead.
+                */
+-              (*sock)->sk->sk_sndbuf =
++              per_cpu(__icmp_socket, i)->sk->sk_sndbuf =
+                       (2 * ((64 * 1024) + sizeof(struct sk_buff)));
+-              inet = inet_sk((*sock)->sk);
++              inet = inet_sk(per_cpu(__icmp_socket, i)->sk);
+               inet->uc_ttl = -1;
+               inet->pmtudisc = IP_PMTUDISC_DONT;
+@@ -1240,27 +1209,8 @@
+                * see it, we do not wish this socket to see incoming
+                * packets.
+                */
+-              (*sock)->sk->sk_prot->unhash((*sock)->sk);
 -
--      rtnl_lock();
--      err = inet6_addr_del(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen);
--      rtnl_unlock();
+-              /* Don't hold an extra reference on the namespace */
+-              put_net((*sock)->sk->sk_net);
++              per_cpu(__icmp_socket, i)->sk->sk_prot->unhash(per_cpu(__icmp_socket, i)->sk);
+       }
+-      return 0;
+-fail:
+-      icmp_net_exit(net);
 -      return err;
--}
--
--#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
--static void sit_add_v4_addrs(struct inet6_dev *idev)
--{
--      struct inet6_ifaddr * ifp;
--      struct in6_addr addr;
--      struct net_device *dev;
--      int scope;
--
--      ASSERT_RTNL();
--
--      memset(&addr, 0, sizeof(struct in6_addr));
--      memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4);
--
--      if (idev->dev->flags&IFF_POINTOPOINT) {
--              addr.s6_addr32[0] = htonl(0xfe800000);
--              scope = IFA_LINK;
--      } else {
--              scope = IPV6_ADDR_COMPATv4;
--      }
--
--      if (addr.s6_addr32[3]) {
--              ifp = ipv6_add_addr(idev, &addr, 128, scope, IFA_F_PERMANENT);
--              if (!IS_ERR(ifp)) {
--                      spin_lock_bh(&ifp->lock);
--                      ifp->flags &= ~IFA_F_TENTATIVE;
--                      spin_unlock_bh(&ifp->lock);
--                      ipv6_ifa_notify(RTM_NEWADDR, ifp);
--                      in6_ifa_put(ifp);
--              }
--              return;
--      }
--
--      for_each_netdev(dev) {
--              struct in_device * in_dev = __in_dev_get_rtnl(dev);
--              if (in_dev && (dev->flags & IFF_UP)) {
--                      struct in_ifaddr * ifa;
--
--                      int flag = scope;
--
--                      for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
--                              int plen;
--
--                              addr.s6_addr32[3] = ifa->ifa_local;
--
--                              if (ifa->ifa_scope == RT_SCOPE_LINK)
--                                      continue;
--                              if (ifa->ifa_scope >= RT_SCOPE_HOST) {
--                                      if (idev->dev->flags&IFF_POINTOPOINT)
--                                              continue;
--                                      flag |= IFA_HOST;
--                              }
--                              if (idev->dev->flags&IFF_POINTOPOINT)
--                                      plen = 64;
--                              else
--                                      plen = 96;
--
--                              ifp = ipv6_add_addr(idev, &addr, plen, flag,
--                                                  IFA_F_PERMANENT);
--                              if (!IS_ERR(ifp)) {
--                                      spin_lock_bh(&ifp->lock);
--                                      ifp->flags &= ~IFA_F_TENTATIVE;
--                                      spin_unlock_bh(&ifp->lock);
--                                      ipv6_ifa_notify(RTM_NEWADDR, ifp);
--                                      in6_ifa_put(ifp);
--                              }
--                      }
--              }
--      }
--}
--#endif
--
--static void init_loopback(struct net_device *dev)
--{
--      struct inet6_dev  *idev;
--      struct inet6_ifaddr * ifp;
--
--      /* ::1 */
--
--      ASSERT_RTNL();
--
--      if ((idev = ipv6_find_idev(dev)) == NULL) {
--              printk(KERN_DEBUG "init loopback: add_dev failed\n");
--              return;
--      }
--
--      ifp = ipv6_add_addr(idev, &in6addr_loopback, 128, IFA_HOST, IFA_F_PERMANENT);
--      if (!IS_ERR(ifp)) {
--              spin_lock_bh(&ifp->lock);
--              ifp->flags &= ~IFA_F_TENTATIVE;
--              spin_unlock_bh(&ifp->lock);
--              ipv6_ifa_notify(RTM_NEWADDR, ifp);
--              in6_ifa_put(ifp);
--      }
--}
--
--static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr)
--{
--      struct inet6_ifaddr * ifp;
--      u32 addr_flags = IFA_F_PERMANENT;
--
--#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
--      if (idev->cnf.optimistic_dad &&
--          !ipv6_devconf.forwarding)
--              addr_flags |= IFA_F_OPTIMISTIC;
--#endif
--
--
--      ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, addr_flags);
--      if (!IS_ERR(ifp)) {
--              addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
--              addrconf_dad_start(ifp, 0);
--              in6_ifa_put(ifp);
--      }
--}
--
--static void addrconf_dev_config(struct net_device *dev)
--{
--      struct in6_addr addr;
--      struct inet6_dev    * idev;
 -
--      ASSERT_RTNL();
--
--      if ((dev->type != ARPHRD_ETHER) &&
--          (dev->type != ARPHRD_FDDI) &&
--          (dev->type != ARPHRD_IEEE802_TR) &&
--          (dev->type != ARPHRD_ARCNET) &&
--          (dev->type != ARPHRD_INFINIBAND)) {
--              /* Alas, we support only Ethernet autoconfiguration. */
--              return;
--      }
--
--      idev = addrconf_add_dev(dev);
--      if (idev == NULL)
--              return;
--
--      memset(&addr, 0, sizeof(struct in6_addr));
--      addr.s6_addr32[0] = htonl(0xFE800000);
--
--      if (ipv6_generate_eui64(addr.s6_addr + 8, dev) == 0)
--              addrconf_add_linklocal(idev, &addr);
 -}
 -
--#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
--static void addrconf_sit_config(struct net_device *dev)
--{
--      struct inet6_dev *idev;
--
--      ASSERT_RTNL();
--
--      /*
--       * Configure the tunnel with one of our IPv4
--       * addresses... we should configure all of
--       * our v4 addrs in the tunnel
--       */
--
--      if ((idev = ipv6_find_idev(dev)) == NULL) {
--              printk(KERN_DEBUG "init sit: add_dev failed\n");
--              return;
--      }
--
--      sit_add_v4_addrs(idev);
--
--      if (dev->flags&IFF_POINTOPOINT) {
--              addrconf_add_mroute(dev);
--              addrconf_add_lroute(dev);
--      } else
--              sit_route_add(dev);
--}
--#endif
+-static struct pernet_operations icmp_net_ops = {
+-      .init = icmp_net_init,
+-      .exit = icmp_net_exit,
+-};
 -
--static inline int
--ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev)
+-void __init icmp_init(struct net_proto_family *ops)
 -{
--      struct in6_addr lladdr;
--
--      if (!ipv6_get_lladdr(link_dev, &lladdr, IFA_F_TENTATIVE)) {
--              addrconf_add_linklocal(idev, &lladdr);
+-      if (register_pernet_subsys(&icmp_net_ops))
+-              panic("Failed to create the ICMP control socket.\n");
+ }
+ EXPORT_SYMBOL(icmp_err_convert);
+diff -Nurb linux-2.6.22-590/net/ipv4/igmp.c linux-2.6.22-570/net/ipv4/igmp.c
+--- linux-2.6.22-590/net/ipv4/igmp.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/igmp.c   2007-07-08 19:32:17.000000000 -0400
+@@ -97,7 +97,6 @@
+ #include <net/route.h>
+ #include <net/sock.h>
+ #include <net/checksum.h>
+-#include <net/net_namespace.h>
+ #include <linux/netfilter_ipv4.h>
+ #ifdef CONFIG_IP_MROUTE
+ #include <linux/mroute.h>
+@@ -130,12 +129,12 @@
+  */
+ #define IGMP_V1_SEEN(in_dev) \
+-      (IPV4_DEVCONF_ALL((in_dev)->dev->nd_net, FORCE_IGMP_VERSION) == 1 || \
++      (IPV4_DEVCONF_ALL(FORCE_IGMP_VERSION) == 1 || \
+        IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \
+        ((in_dev)->mr_v1_seen && \
+         time_before(jiffies, (in_dev)->mr_v1_seen)))
+ #define IGMP_V2_SEEN(in_dev) \
+-      (IPV4_DEVCONF_ALL((in_dev)->dev->nd_net, FORCE_IGMP_VERSION) == 2 || \
++      (IPV4_DEVCONF_ALL(FORCE_IGMP_VERSION) == 2 || \
+        IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2 || \
+        ((in_dev)->mr_v2_seen && \
+         time_before(jiffies, (in_dev)->mr_v2_seen)))
+@@ -297,8 +296,7 @@
+               return NULL;
+       {
+-              struct flowi fl = { .fl_net = &init_net,
+-                                  .oif = dev->ifindex,
++              struct flowi fl = { .oif = dev->ifindex,
+                                   .nl_u = { .ip4_u = {
+                                   .daddr = IGMPV3_ALL_MCR } },
+                                   .proto = IPPROTO_IGMP };
+@@ -648,8 +646,7 @@
+               dst = group;
+       {
+-              struct flowi fl = { .fl_net = &init_net,
+-                                  .oif = dev->ifindex,
++              struct flowi fl = { .oif = dev->ifindex,
+                                   .nl_u = { .ip4_u = { .daddr = dst } },
+                                   .proto = IPPROTO_IGMP };
+               if (ip_route_output_key(&rt, &fl))
+@@ -932,11 +929,6 @@
+       struct in_device *in_dev = in_dev_get(skb->dev);
+       int len = skb->len;
+-      if (skb->dev->nd_net != &init_net) {
+-              kfree_skb(skb);
 -              return 0;
 -      }
--      return -1;
--}
--
--static void ip6_tnl_add_linklocal(struct inet6_dev *idev)
--{
--      struct net_device *link_dev;
--
--      /* first try to inherit the link-local address from the link device */
--      if (idev->dev->iflink &&
--          (link_dev = __dev_get_by_index(idev->dev->iflink))) {
--              if (!ipv6_inherit_linklocal(idev, link_dev))
--                      return;
--      }
--      /* then try to inherit it from any device */
--      for_each_netdev(link_dev) {
--              if (!ipv6_inherit_linklocal(idev, link_dev))
--                      return;
--      }
--      printk(KERN_DEBUG "init ip6-ip6: add_linklocal failed\n");
--}
--
--/*
-- * Autoconfigure tunnel with a link-local address so routing protocols,
-- * DHCPv6, MLD etc. can be run over the virtual link
-- */
--
--static void addrconf_ip6_tnl_config(struct net_device *dev)
--{
--      struct inet6_dev *idev;
--
--      ASSERT_RTNL();
--
--      if ((idev = addrconf_add_dev(dev)) == NULL) {
--              printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n");
--              return;
--      }
--      ip6_tnl_add_linklocal(idev);
--}
--
--static int addrconf_notify(struct notifier_block *this, unsigned long event,
--                         void * data)
--{
--      struct net_device *dev = (struct net_device *) data;
--      struct inet6_dev *idev = __in6_dev_get(dev);
--      int run_pending = 0;
--
--      switch(event) {
--      case NETDEV_REGISTER:
--              if (!idev && dev->mtu >= IPV6_MIN_MTU) {
--                      idev = ipv6_add_dev(dev);
--                      if (!idev)
--                              printk(KERN_WARNING "IPv6: add_dev failed for %s\n",
--                                      dev->name);
--              }
--              break;
--      case NETDEV_UP:
--      case NETDEV_CHANGE:
--              if (event == NETDEV_UP) {
--                      if (!addrconf_qdisc_ok(dev)) {
--                              /* device is not ready yet. */
--                              printk(KERN_INFO
--                                      "ADDRCONF(NETDEV_UP): %s: "
--                                      "link is not ready\n",
--                                      dev->name);
--                              break;
--                      }
--
--                      if (idev)
--                              idev->if_flags |= IF_READY;
--              } else {
--                      if (!addrconf_qdisc_ok(dev)) {
--                              /* device is still not ready. */
--                              break;
--                      }
--
--                      if (idev) {
--                              if (idev->if_flags & IF_READY) {
--                                      /* device is already configured. */
--                                      break;
--                              }
--                              idev->if_flags |= IF_READY;
--                      }
--
--                      printk(KERN_INFO
--                                      "ADDRCONF(NETDEV_CHANGE): %s: "
--                                      "link becomes ready\n",
--                                      dev->name);
--
--                      run_pending = 1;
--              }
--
--              switch(dev->type) {
--#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
--              case ARPHRD_SIT:
--                      addrconf_sit_config(dev);
--                      break;
--#endif
--              case ARPHRD_TUNNEL6:
--                      addrconf_ip6_tnl_config(dev);
--                      break;
--              case ARPHRD_LOOPBACK:
--                      init_loopback(dev);
--                      break;
--
--              default:
--                      addrconf_dev_config(dev);
--                      break;
--              }
--              if (idev) {
--                      if (run_pending)
--                              addrconf_dad_run(idev);
--
--                      /* If the MTU changed during the interface down, when the
--                         interface up, the changed MTU must be reflected in the
--                         idev as well as routers.
--                       */
--                      if (idev->cnf.mtu6 != dev->mtu && dev->mtu >= IPV6_MIN_MTU) {
--                              rt6_mtu_change(dev, dev->mtu);
--                              idev->cnf.mtu6 = dev->mtu;
--                      }
--                      idev->tstamp = jiffies;
--                      inet6_ifinfo_notify(RTM_NEWLINK, idev);
--                      /* If the changed mtu during down is lower than IPV6_MIN_MTU
--                         stop IPv6 on this interface.
--                       */
--                      if (dev->mtu < IPV6_MIN_MTU)
--                              addrconf_ifdown(dev, event != NETDEV_DOWN);
--              }
--              break;
--
--      case NETDEV_CHANGEMTU:
--              if ( idev && dev->mtu >= IPV6_MIN_MTU) {
--                      rt6_mtu_change(dev, dev->mtu);
--                      idev->cnf.mtu6 = dev->mtu;
--                      break;
--              }
--
--              /* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */
--
--      case NETDEV_DOWN:
--      case NETDEV_UNREGISTER:
--              /*
--               *      Remove all addresses from this interface.
--               */
--              addrconf_ifdown(dev, event != NETDEV_DOWN);
--              break;
--
--      case NETDEV_CHANGENAME:
--              if (idev) {
--                      snmp6_unregister_dev(idev);
--#ifdef CONFIG_SYSCTL
--                      addrconf_sysctl_unregister(&idev->cnf);
--                      neigh_sysctl_unregister(idev->nd_parms);
--                      neigh_sysctl_register(dev, idev->nd_parms,
--                                            NET_IPV6, NET_IPV6_NEIGH, "ipv6",
--                                            &ndisc_ifinfo_sysctl_change,
--                                            NULL);
--                      addrconf_sysctl_register(idev, &idev->cnf);
--#endif
--                      snmp6_register_dev(idev);
--              }
--              break;
--      }
--
--      return NOTIFY_OK;
--}
 -
--/*
-- *    addrconf module should be notified of a device going up
-- */
--static struct notifier_block ipv6_dev_notf = {
--      .notifier_call = addrconf_notify,
--      .priority = 0
+       if (in_dev==NULL) {
+               kfree_skb(skb);
+               return 0;
+@@ -1401,22 +1393,20 @@
+ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
+ {
+-      struct flowi fl = { 
+-              .fl_net = &init_net,
+-              .nl_u = { .ip4_u = { .daddr = imr->imr_multiaddr.s_addr } }
+-      };
++      struct flowi fl = { .nl_u = { .ip4_u =
++                                    { .daddr = imr->imr_multiaddr.s_addr } } };
+       struct rtable *rt;
+       struct net_device *dev = NULL;
+       struct in_device *idev = NULL;
+       if (imr->imr_ifindex) {
+-              idev = inetdev_by_index(&init_net, imr->imr_ifindex);
++              idev = inetdev_by_index(imr->imr_ifindex);
+               if (idev)
+                       __in_dev_put(idev);
+               return idev;
+       }
+       if (imr->imr_address.s_addr) {
+-              dev = ip_dev_find(&init_net, imr->imr_address.s_addr);
++              dev = ip_dev_find(imr->imr_address.s_addr);
+               if (!dev)
+                       return NULL;
+               dev_put(dev);
+@@ -2244,7 +2234,7 @@
+               struct in_device *in_dev;
+               inet->mc_list = iml->next;
+-              in_dev = inetdev_by_index(&init_net, iml->multi.imr_ifindex);
++              in_dev = inetdev_by_index(iml->multi.imr_ifindex);
+               (void) ip_mc_leave_src(sk, iml, in_dev);
+               if (in_dev != NULL) {
+                       ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
+@@ -2301,7 +2291,7 @@
+       struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
+       state->in_dev = NULL;
+-      for_each_netdev(&init_net, state->dev) {
++      for_each_netdev(state->dev) {
+               struct in_device *in_dev;
+               in_dev = in_dev_get(state->dev);
+               if (!in_dev)
+@@ -2463,7 +2453,7 @@
+       state->idev = NULL;
+       state->im = NULL;
+-      for_each_netdev(&init_net, state->dev) {
++      for_each_netdev(state->dev) {
+               struct in_device *idev;
+               idev = in_dev_get(state->dev);
+               if (unlikely(idev == NULL))
+@@ -2623,8 +2613,8 @@
+ int __init igmp_mc_proc_init(void)
+ {
+-      proc_net_fops_create(&init_net, "igmp", S_IRUGO, &igmp_mc_seq_fops);
+-      proc_net_fops_create(&init_net, "mcfilter", S_IRUGO, &igmp_mcf_seq_fops);
++      proc_net_fops_create("igmp", S_IRUGO, &igmp_mc_seq_fops);
++      proc_net_fops_create("mcfilter", S_IRUGO, &igmp_mcf_seq_fops);
+       return 0;
+ }
+ #endif
+diff -Nurb linux-2.6.22-590/net/ipv4/inet_connection_sock.c linux-2.6.22-570/net/ipv4/inet_connection_sock.c
+--- linux-2.6.22-590/net/ipv4/inet_connection_sock.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/inet_connection_sock.c   2008-01-23 19:16:05.000000000 -0500
+@@ -32,7 +32,7 @@
+ /*
+  * This array holds the first and last local port number.
+  */
+-//int sysctl_local_port_range[2] = { 32768, 61000 };
++int sysctl_local_port_range[2] = { 32768, 61000 };
+ int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
+ {
+@@ -74,7 +74,6 @@
+       sk_for_each_bound(sk2, node, &tb->owners) {
+               if (sk != sk2 &&
+-                  (sk->sk_net == sk2->sk_net) &&
+                   !inet_v6_ipv6only(sk2) &&
+                   (!sk->sk_bound_dev_if ||
+                    !sk2->sk_bound_dev_if ||
+@@ -99,7 +98,6 @@
+                     int (*bind_conflict)(const struct sock *sk,
+                                          const struct inet_bind_bucket *tb))
+ {
+-      struct net *net = sk->sk_net;
+       struct inet_bind_hashbucket *head;
+       struct hlist_node *node;
+       struct inet_bind_bucket *tb;
+@@ -107,16 +105,16 @@
+       local_bh_disable();
+       if (!snum) {
+-              int low = sk->sk_net->sysctl_local_port_range[0];
+-              int high = sk->sk_net->sysctl_local_port_range[1];
++              int low = sysctl_local_port_range[0];
++              int high = sysctl_local_port_range[1];
+               int remaining = (high - low) + 1;
+               int rover = net_random() % (high - low) + low;
+               do {
+-                      head = &hashinfo->bhash[inet_bhashfn(net, rover, hashinfo->bhash_size)];
++                      head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)];
+                       spin_lock(&head->lock);
+                       inet_bind_bucket_for_each(tb, node, &head->chain)
+-                              if ((tb->port == rover) && (tb->net == net))
++                              if (tb->port == rover)
+                                       goto next;
+                       break;
+               next:
+@@ -140,10 +138,10 @@
+                */
+               snum = rover;
+       } else {
+-              head = &hashinfo->bhash[inet_bhashfn(net, snum, hashinfo->bhash_size)];
++              head = &hashinfo->bhash[inet_bhashfn(snum, hashinfo->bhash_size)];
+               spin_lock(&head->lock);
+               inet_bind_bucket_for_each(tb, node, &head->chain)
+-                      if ((tb->port == snum) && (tb->net==net))
++                      if (tb->port == snum)
+                               goto tb_found;
+       }
+       tb = NULL;
+@@ -163,7 +161,7 @@
+       }
+ tb_not_found:
+       ret = 1;
+-      if (!tb && (tb = inet_bind_bucket_create(hashinfo->bind_bucket_cachep, head, net, snum)) == NULL)
++      if (!tb && (tb = inet_bind_bucket_create(hashinfo->bind_bucket_cachep, head, snum)) == NULL)
+               goto fail_unlock;
+       if (hlist_empty(&tb->owners)) {
+               if (sk->sk_reuse && sk->sk_state != TCP_LISTEN)
+@@ -343,8 +341,7 @@
+       struct rtable *rt;
+       const struct inet_request_sock *ireq = inet_rsk(req);
+       struct ip_options *opt = inet_rsk(req)->opt;
+-      struct flowi fl = { .fl_net = sk->sk_net,
+-                      .oif = sk->sk_bound_dev_if,
++      struct flowi fl = { .oif = sk->sk_bound_dev_if,
+                           .nl_u = { .ip4_u =
+                                     { .daddr = ((opt && opt->srr) ?
+                                                 opt->faddr :
+diff -Nurb linux-2.6.22-590/net/ipv4/inet_diag.c linux-2.6.22-570/net/ipv4/inet_diag.c
+--- linux-2.6.22-590/net/ipv4/inet_diag.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/inet_diag.c      2008-01-23 19:16:05.000000000 -0500
+@@ -227,7 +227,6 @@
+ static int inet_diag_get_exact(struct sk_buff *in_skb,
+                              const struct nlmsghdr *nlh)
+ {
+-      struct net *net = in_skb->sk->sk_net;
+       int err;
+       struct sock *sk;
+       struct inet_diag_req *req = NLMSG_DATA(nlh);
+@@ -243,7 +242,7 @@
+               /* TODO: lback */
+               sk = inet_lookup(hashinfo, req->id.idiag_dst[0],
+                                req->id.idiag_dport, req->id.idiag_src[0],
+-                               req->id.idiag_sport, req->id.idiag_if, net);
++                               req->id.idiag_sport, req->id.idiag_if);
+       }
+ #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+       else if (req->idiag_family == AF_INET6) {
+@@ -252,7 +251,7 @@
+                                 req->id.idiag_dport,
+                                 (struct in6_addr *)req->id.idiag_src,
+                                 req->id.idiag_sport,
+-                                req->id.idiag_if, net);
++                                req->id.idiag_if);
+       }
+ #endif
+       else {
+@@ -907,8 +906,8 @@
+       if (!inet_diag_table)
+               goto out;
+-      idiagnl = netlink_kernel_create(&init_net, NETLINK_INET_DIAG, 0,
+-                                      inet_diag_rcv, NULL, THIS_MODULE);
++      idiagnl = netlink_kernel_create(NETLINK_INET_DIAG, 0, inet_diag_rcv,
++                                      NULL, THIS_MODULE);
+       if (idiagnl == NULL)
+               goto out_free_table;
+       err = 0;
+diff -Nurb linux-2.6.22-590/net/ipv4/inet_hashtables.c linux-2.6.22-570/net/ipv4/inet_hashtables.c
+--- linux-2.6.22-590/net/ipv4/inet_hashtables.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/inet_hashtables.c        2008-01-23 19:16:05.000000000 -0500
+@@ -29,13 +29,11 @@
+  */
+ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
+                                                struct inet_bind_hashbucket *head,
+-                                               struct net *net,
+                                                const unsigned short snum)
+ {
+       struct inet_bind_bucket *tb = kmem_cache_alloc(cachep, GFP_ATOMIC);
+       if (tb != NULL) {
+-              tb->net       = net;
+               tb->port      = snum;
+               tb->fastreuse = 0;
+               INIT_HLIST_HEAD(&tb->owners);
+@@ -68,7 +66,7 @@
+  */
+ static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
+ {
+-      const int bhash = inet_bhashfn(sk->sk_net, inet_sk(sk)->num, hashinfo->bhash_size);
++      const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size);
+       struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
+       struct inet_bind_bucket *tb;
+@@ -129,7 +127,7 @@
+ static struct sock *inet_lookup_listener_slow(const struct hlist_head *head,
+                                             const __be32 daddr,
+                                             const unsigned short hnum,
+-                                            const int dif, struct net *net)
++                                            const int dif)
+ {
+       struct sock *result = NULL, *sk;
+       const struct hlist_node *node;
+@@ -151,8 +149,6 @@
+                                       continue;
+                               score += 2;
+                       }
+-                      if (sk->sk_net != net)
+-                              continue;
+                       if (score == 5)
+                               return sk;
+                       if (score > hiscore) {
+@@ -167,22 +163,22 @@
+ /* Optimize the common listener case. */
+ struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
+                                   const __be32 daddr, const unsigned short hnum,
+-                                  const int dif, struct net *net)
++                                  const int dif)
+ {
+       struct sock *sk = NULL;
+       const struct hlist_head *head;
+       read_lock(&hashinfo->lhash_lock);
+-      head = &hashinfo->listening_hash[net, inet_lhashfn(net, hnum)];
++      head = &hashinfo->listening_hash[inet_lhashfn(hnum)];
+       if (!hlist_empty(head)) {
+               const struct inet_sock *inet = inet_sk((sk = __sk_head(head)));
+               if (inet->num == hnum && !sk->sk_node.next &&
+                   v4_inet_addr_match(sk->sk_nx_info, daddr, inet->rcv_saddr) &&
+                   (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
+-                  !sk->sk_bound_dev_if && (sk->sk_net == net))
++                  !sk->sk_bound_dev_if)
+                       goto sherry_cache;
+-              sk = inet_lookup_listener_slow(head, daddr, hnum, dif,net );
++              sk = inet_lookup_listener_slow(head, daddr, hnum, dif);
+       }
+       if (sk) {
+ sherry_cache:
+@@ -200,13 +196,12 @@
+ {
+       struct inet_hashinfo *hinfo = death_row->hashinfo;
+       struct inet_sock *inet = inet_sk(sk);
+-      struct net *net = sk->sk_net;
+       __be32 daddr = inet->rcv_saddr;
+       __be32 saddr = inet->daddr;
+       int dif = sk->sk_bound_dev_if;
+       INET_ADDR_COOKIE(acookie, saddr, daddr)
+       const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport);
+-      unsigned int hash = inet_ehashfn(net, daddr, lport, saddr, inet->dport);
++      unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
+       struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
+       struct sock *sk2;
+       const struct hlist_node *node;
+@@ -219,7 +214,7 @@
+       sk_for_each(sk2, node, &head->twchain) {
+               tw = inet_twsk(sk2);
+-              if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif, net)) {
++              if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) {
+                       if (twsk_unique(sk, sk2, twp))
+                               goto unique;
+                       else
+@@ -230,7 +225,7 @@
+       /* And established part... */
+       sk_for_each(sk2, node, &head->chain) {
+-              if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif, net))
++              if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif))
+                       goto not_unique;
+       }
+@@ -276,7 +271,6 @@
+ int inet_hash_connect(struct inet_timewait_death_row *death_row,
+                     struct sock *sk)
+ {
+-      struct net *net = sk->sk_net;
+       struct inet_hashinfo *hinfo = death_row->hashinfo;
+       const unsigned short snum = inet_sk(sk)->num;
+       struct inet_bind_hashbucket *head;
+@@ -284,8 +278,8 @@
+       int ret;
+       if (!snum) {
+-              int low = sk->sk_net->sysctl_local_port_range[0];
+-              int high = sk->sk_net->sysctl_local_port_range[1];
++              int low = sysctl_local_port_range[0];
++              int high = sysctl_local_port_range[1];
+               int range = high - low;
+               int i;
+               int port;
+@@ -297,7 +291,7 @@
+               local_bh_disable();
+               for (i = 1; i <= range; i++) {
+                       port = low + (i + offset) % range;
+-                      head = &hinfo->bhash[inet_bhashfn(net, port, hinfo->bhash_size)];
++                      head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)];
+                       spin_lock(&head->lock);
+                       /* Does not bother with rcv_saddr checks,
+@@ -305,7 +299,7 @@
+                        * unique enough.
+                        */
+                       inet_bind_bucket_for_each(tb, node, &head->chain) {
+-                              if ((tb->port == port) && (tb->net == net)) {
++                              if (tb->port == port) {
+                                       BUG_TRAP(!hlist_empty(&tb->owners));
+                                       if (tb->fastreuse >= 0)
+                                               goto next_port;
+@@ -317,7 +311,7 @@
+                               }
+                       }
+-                      tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, head, net, port);
++                      tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, head, port);
+                       if (!tb) {
+                               spin_unlock(&head->lock);
+                               break;
+@@ -352,7 +346,7 @@
+               goto out;
+       }
+-      head = &hinfo->bhash[inet_bhashfn(net, snum, hinfo->bhash_size)];
++      head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)];
+       tb  = inet_csk(sk)->icsk_bind_hash;
+       spin_lock_bh(&head->lock);
+       if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
+diff -Nurb linux-2.6.22-590/net/ipv4/inet_timewait_sock.c linux-2.6.22-570/net/ipv4/inet_timewait_sock.c
+--- linux-2.6.22-590/net/ipv4/inet_timewait_sock.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/inet_timewait_sock.c     2007-07-08 19:32:17.000000000 -0400
+@@ -31,7 +31,7 @@
+       write_unlock(&ehead->lock);
+       /* Disassociate with bind bucket. */
+-      bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_net, tw->tw_num, hashinfo->bhash_size)];
++      bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_num, hashinfo->bhash_size)];
+       spin_lock(&bhead->lock);
+       tb = tw->tw_tb;
+       __hlist_del(&tw->tw_bind_node);
+@@ -65,7 +65,7 @@
+          Note, that any socket with inet->num != 0 MUST be bound in
+          binding cache, even if it is closed.
+        */
+-      bhead = &hashinfo->bhash[inet_bhashfn(sk->sk_net, inet->num, hashinfo->bhash_size)];
++      bhead = &hashinfo->bhash[inet_bhashfn(inet->num, hashinfo->bhash_size)];
+       spin_lock(&bhead->lock);
+       tw->tw_tb = icsk->icsk_bind_hash;
+       BUG_TRAP(icsk->icsk_bind_hash);
+diff -Nurb linux-2.6.22-590/net/ipv4/inetpeer.c linux-2.6.22-570/net/ipv4/inetpeer.c
+--- linux-2.6.22-590/net/ipv4/inetpeer.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/inetpeer.c       2007-07-08 19:32:17.000000000 -0400
+@@ -81,94 +81,71 @@
+       .avl_height     = 0
+ };
+ #define peer_avl_empty (&peer_fake_node)
++static struct inet_peer *peer_root = peer_avl_empty;
+ static DEFINE_RWLOCK(peer_pool_lock);
+ #define PEER_MAXDEPTH 40 /* sufficient for about 2^27 nodes */
++static int peer_total;
++/* Exported for sysctl_net_ipv4.  */
++int inet_peer_threshold __read_mostly = 65536 + 128;  /* start to throw entries more
++                                       * aggressively at this stage */
++int inet_peer_minttl __read_mostly = 120 * HZ;        /* TTL under high load: 120 sec */
++int inet_peer_maxttl __read_mostly = 10 * 60 * HZ;    /* usual time to live: 10 min */
++int inet_peer_gc_mintime __read_mostly = 10 * HZ;
++int inet_peer_gc_maxtime __read_mostly = 120 * HZ;
++
++static struct inet_peer *inet_peer_unused_head;
++static struct inet_peer **inet_peer_unused_tailp = &inet_peer_unused_head;
+ static DEFINE_SPINLOCK(inet_peer_unused_lock);
+ static void peer_check_expire(unsigned long dummy);
++static DEFINE_TIMER(peer_periodic_timer, peer_check_expire, 0, 0);
+-static int inet_peers_net_init(struct net *net);
+-static void inet_peers_net_exit(struct net *net);
+-static struct pernet_operations inet_peers_net_ops = {
+-      .init = inet_peers_net_init,
+-      .exit = inet_peers_net_exit,
 -};
+ /* Called from ip_output.c:ip_init  */
+ void __init inet_initpeers(void)
+ {
+-      peer_cachep = kmem_cache_create("inet_peer_cache",
+-                      sizeof(struct inet_peer),
+-                      0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
+-                      NULL, NULL);
 -
--static int addrconf_ifdown(struct net_device *dev, int how)
--{
--      struct inet6_dev *idev;
--      struct inet6_ifaddr *ifa, **bifa;
--      int i;
--
--      ASSERT_RTNL();
--
--      if (dev == &loopback_dev && how == 1)
--              how = 0;
--
--      rt6_ifdown(dev);
--      neigh_ifdown(&nd_tbl, dev);
--
--      idev = __in6_dev_get(dev);
--      if (idev == NULL)
--              return -ENODEV;
--
--      /* Step 1: remove reference to ipv6 device from parent device.
--                 Do not dev_put!
--       */
--      if (how == 1) {
--              idev->dead = 1;
--
--              /* protected by rtnl_lock */
--              rcu_assign_pointer(dev->ip6_ptr, NULL);
--
--              /* Step 1.5: remove snmp6 entry */
--              snmp6_unregister_dev(idev);
--
--      }
--
--      /* Step 2: clear hash table */
--      for (i=0; i<IN6_ADDR_HSIZE; i++) {
--              bifa = &inet6_addr_lst[i];
--
--              write_lock_bh(&addrconf_hash_lock);
--              while ((ifa = *bifa) != NULL) {
--                      if (ifa->idev == idev) {
--                              *bifa = ifa->lst_next;
--                              ifa->lst_next = NULL;
--                              addrconf_del_timer(ifa);
--                              in6_ifa_put(ifa);
--                              continue;
--                      }
--                      bifa = &ifa->lst_next;
--              }
--              write_unlock_bh(&addrconf_hash_lock);
--      }
--
--      write_lock_bh(&idev->lock);
--
--      /* Step 3: clear flags for stateless addrconf */
--      if (how != 1)
--              idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY);
--
--      /* Step 4: clear address list */
--#ifdef CONFIG_IPV6_PRIVACY
--      if (how == 1 && del_timer(&idev->regen_timer))
--              in6_dev_put(idev);
--
--      /* clear tempaddr list */
--      while ((ifa = idev->tempaddr_list) != NULL) {
--              idev->tempaddr_list = ifa->tmp_next;
--              ifa->tmp_next = NULL;
--              ifa->dead = 1;
--              write_unlock_bh(&idev->lock);
--              spin_lock_bh(&ifa->lock);
--
--              if (ifa->ifpub) {
--                      in6_ifa_put(ifa->ifpub);
--                      ifa->ifpub = NULL;
--              }
--              spin_unlock_bh(&ifa->lock);
--              in6_ifa_put(ifa);
--              write_lock_bh(&idev->lock);
--      }
--#endif
--      while ((ifa = idev->addr_list) != NULL) {
--              idev->addr_list = ifa->if_next;
--              ifa->if_next = NULL;
--              ifa->dead = 1;
--              addrconf_del_timer(ifa);
--              write_unlock_bh(&idev->lock);
--
--              __ipv6_ifa_notify(RTM_DELADDR, ifa);
--              atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa);
--              in6_ifa_put(ifa);
--
--              write_lock_bh(&idev->lock);
--      }
--      write_unlock_bh(&idev->lock);
--
--      /* Step 5: Discard multicast list */
--
--      if (how == 1)
--              ipv6_mc_destroy_dev(idev);
--      else
--              ipv6_mc_down(idev);
--
--      /* Step 5: netlink notification of this interface */
--      idev->tstamp = jiffies;
--      inet6_ifinfo_notify(RTM_DELLINK, idev);
--
--      /* Shot the device (if unregistered) */
--
--      if (how == 1) {
--#ifdef CONFIG_SYSCTL
--              addrconf_sysctl_unregister(&idev->cnf);
--              neigh_sysctl_unregister(idev->nd_parms);
--#endif
--              neigh_parms_release(&nd_tbl, idev->nd_parms);
--              neigh_ifdown(&nd_tbl, dev);
--              in6_dev_put(idev);
--      }
--      return 0;
+-      register_pernet_subsys(&inet_peers_net_ops);
 -}
 -
--static void addrconf_rs_timer(unsigned long data)
+-static int inet_peers_net_init(struct net *net)
 -{
--      struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data;
--
--      if (ifp->idev->cnf.forwarding)
--              goto out;
--
--      if (ifp->idev->if_flags & IF_RA_RCVD) {
--              /*
--               *      Announcement received after solicitation
--               *      was sent
--               */
--              goto out;
--      }
--
--      spin_lock(&ifp->lock);
--      if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) {
--              struct in6_addr all_routers;
--
--              /* The wait after the last probe can be shorter */
--              addrconf_mod_timer(ifp, AC_RS,
--                                 (ifp->probes == ifp->idev->cnf.rtr_solicits) ?
--                                 ifp->idev->cnf.rtr_solicit_delay :
--                                 ifp->idev->cnf.rtr_solicit_interval);
--              spin_unlock(&ifp->lock);
--
--              ipv6_addr_all_routers(&all_routers);
--
--              ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers);
--      } else {
--              spin_unlock(&ifp->lock);
--              /*
--               * Note: we do not support deprecated "all on-link"
--               * assumption any longer.
--               */
--              printk(KERN_DEBUG "%s: no IPv6 routers present\n",
--                     ifp->idev->dev->name);
--      }
--
--out:
--      in6_ifa_put(ifp);
--}
+       struct sysinfo si;
+-      net->peer_root = peer_avl_empty;
+-      net->inet_peer_unused_tailp = &net->inet_peer_unused_head;
 -
--/*
-- *    Duplicate Address Detection
-- */
--static void addrconf_dad_kick(struct inet6_ifaddr *ifp)
--{
--      unsigned long rand_num;
--      struct inet6_dev *idev = ifp->idev;
+-      net->inet_peer_threshold = 65536 + 128; /* start to throw entries more
+-                                               * aggressively at this stage */
+-      net->inet_peer_minttl = 120 * HZ;       /* TTL under high load: 120 sec */
+-      net->inet_peer_maxttl = 10 * 60 * HZ;   /* usual time to live: 10 min */
+-      net->inet_peer_gc_mintime = 10 * HZ;
+-      net->inet_peer_gc_maxtime = 120 * HZ;
 -
--      if (ifp->flags & IFA_F_OPTIMISTIC)
--              rand_num = 0;
--      else
--              rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1);
+       /* Use the straight interface to information about memory. */
+       si_meminfo(&si);
 -
--      ifp->probes = idev->cnf.dad_transmits;
--      addrconf_mod_timer(ifp, AC_DAD, rand_num);
+       /* The values below were suggested by Alexey Kuznetsov
+        * <kuznet@ms2.inr.ac.ru>.  I don't have any opinion about the values
+        * myself.  --SAW
+        */
+       if (si.totalram <= (32768*1024)/PAGE_SIZE)
+-              net->inet_peer_threshold >>= 1; /* max pool size about 1MB on IA32 */
++              inet_peer_threshold >>= 1; /* max pool size about 1MB on IA32 */
+       if (si.totalram <= (16384*1024)/PAGE_SIZE)
+-              net->inet_peer_threshold >>= 1; /* about 512KB */
++              inet_peer_threshold >>= 1; /* about 512KB */
+       if (si.totalram <= (8192*1024)/PAGE_SIZE)
+-              net->inet_peer_threshold >>= 2; /* about 128KB */
++              inet_peer_threshold >>= 2; /* about 128KB */
++      peer_cachep = kmem_cache_create("inet_peer_cache",
++                      sizeof(struct inet_peer),
++                      0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
++                      NULL, NULL);
+-      init_timer(&net->peer_periodic_timer);
+-      net->peer_periodic_timer.function = peer_check_expire;
+       /* All the timers, started at system startup tend
+          to synchronize. Perturb it a bit.
+        */
+-      net->peer_periodic_timer.expires = jiffies
+-              + net_random() % net->inet_peer_gc_maxtime
+-              + net->inet_peer_gc_maxtime;
+-      /* Remember our namespace */
+-      net->peer_periodic_timer.data = (unsigned long)net;
+-      add_timer(&net->peer_periodic_timer);
+-      
+-      return 0;
 -}
 -
--static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
+-static void inet_peers_net_exit(struct net *net)
 -{
--      struct inet6_dev *idev = ifp->idev;
--      struct net_device *dev = idev->dev;
--
--      addrconf_join_solict(dev, &ifp->addr);
--
--      net_srandom(ifp->addr.s6_addr32[3]);
--
--      read_lock_bh(&idev->lock);
--      if (ifp->dead)
--              goto out;
--      spin_lock_bh(&ifp->lock);
--
--      if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
--          !(ifp->flags&IFA_F_TENTATIVE) ||
--          ifp->flags & IFA_F_NODAD) {
--              ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC);
--              spin_unlock_bh(&ifp->lock);
--              read_unlock_bh(&idev->lock);
--
--              addrconf_dad_completed(ifp);
--              return;
--      }
+-      del_timer(&net->peer_periodic_timer);
+-      /* CHECKME do I need to do something to release all of the peers */
++      peer_periodic_timer.expires = jiffies
++              + net_random() % inet_peer_gc_maxtime
++              + inet_peer_gc_maxtime;
++      add_timer(&peer_periodic_timer);
+ }
+ /* Called with or without local BH being disabled. */
+-static void unlink_from_unused(struct net *net, struct inet_peer *p)
++static void unlink_from_unused(struct inet_peer *p)
+ {
+       spin_lock_bh(&inet_peer_unused_lock);
+       if (p->unused_prevp != NULL) {
+               /* On unused list. */
+-              *p->unused_prevp = p->u.unused_next;
+-              if (p->u.unused_next != NULL)
+-                      p->u.unused_next->unused_prevp = p->unused_prevp;
++              *p->unused_prevp = p->unused_next;
++              if (p->unused_next != NULL)
++                      p->unused_next->unused_prevp = p->unused_prevp;
+               else
+-                      net->inet_peer_unused_tailp = p->unused_prevp;
++                      inet_peer_unused_tailp = p->unused_prevp;
+               p->unused_prevp = NULL; /* mark it as removed */
+-              p->u.net = hold_net(net); /* Remember the net */
+       }
+       spin_unlock_bh(&inet_peer_unused_lock);
+ }
+@@ -183,9 +160,9 @@
+       struct inet_peer *u, **v;                               \
+       if (_stack) {                                           \
+               stackptr = _stack;                              \
+-              *stackptr++ = &net->peer_root;                  \
++              *stackptr++ = &peer_root;                       \
+       }                                                       \
+-      for (u = net->peer_root; u != peer_avl_empty; ) {       \
++      for (u = peer_root; u != peer_avl_empty; ) {            \
+               if (_daddr == u->v4daddr)                       \
+                       break;                                  \
+               if ((__force __u32)_daddr < (__force __u32)u->v4daddr)  \
+@@ -302,7 +279,7 @@
+ } while(0)
+ /* May be called with local BH enabled. */
+-static void unlink_from_pool(struct net *net, struct inet_peer *p)
++static void unlink_from_pool(struct inet_peer *p)
+ {
+       int do_free;
+@@ -340,7 +317,7 @@
+                       delp[1] = &t->avl_left; /* was &p->avl_left */
+               }
+               peer_avl_rebalance(stack, stackptr);
+-              net->peer_total--;
++              peer_total--;
+               do_free = 1;
+       }
+       write_unlock_bh(&peer_pool_lock);
+@@ -358,13 +335,13 @@
+ }
+ /* May be called with local BH enabled. */
+-static int cleanup_once(struct net *net, unsigned long ttl)
++static int cleanup_once(unsigned long ttl)
+ {
+       struct inet_peer *p;
+       /* Remove the first entry from the list of unused nodes. */
+       spin_lock_bh(&inet_peer_unused_lock);
+-      p = net->inet_peer_unused_head;
++      p = inet_peer_unused_head;
+       if (p != NULL) {
+               __u32 delta = (__u32)jiffies - p->dtime;
+               if (delta < ttl) {
+@@ -372,13 +349,12 @@
+                       spin_unlock_bh(&inet_peer_unused_lock);
+                       return -1;
+               }
+-              net->inet_peer_unused_head = p->u.unused_next;
+-              if (p->u.unused_next != NULL)
+-                      p->u.unused_next->unused_prevp = p->unused_prevp;
++              inet_peer_unused_head = p->unused_next;
++              if (p->unused_next != NULL)
++                      p->unused_next->unused_prevp = p->unused_prevp;
+               else
+-                      net->inet_peer_unused_tailp = p->unused_prevp;
++                      inet_peer_unused_tailp = p->unused_prevp;
+               p->unused_prevp = NULL; /* mark as not on the list */
+-              p->u.net = hold_net(net);
+               /* Grab an extra reference to prevent node disappearing
+                * before unlink_from_pool() call. */
+               atomic_inc(&p->refcnt);
+@@ -391,12 +367,12 @@
+                * happen because of entry limits in route cache. */
+               return -1;
+-      unlink_from_pool(net, p);
++      unlink_from_pool(p);
+       return 0;
+ }
+ /* Called with or without local BH being disabled. */
+-struct inet_peer *inet_getpeer(struct net *net, __be32 daddr, int create)
++struct inet_peer *inet_getpeer(__be32 daddr, int create)
+ {
+       struct inet_peer *p, *n;
+       struct inet_peer **stack[PEER_MAXDEPTH], ***stackptr;
+@@ -411,7 +387,7 @@
+       if (p != peer_avl_empty) {
+               /* The existing node has been found. */
+               /* Remove the entry from unused list if it was there. */
+-              unlink_from_unused(net, p);
++              unlink_from_unused(p);
+               return p;
+       }
+@@ -437,13 +413,13 @@
+       /* Link the node. */
+       link_to_pool(n);
+       n->unused_prevp = NULL; /* not on the list */
+-      n->u.net = hold_net(net); /* Remember the net */
+-      net->peer_total++;
++      peer_total++;
+       write_unlock_bh(&peer_pool_lock);
+-      if (net->peer_total >= net->inet_peer_threshold)
++      if (peer_total >= inet_peer_threshold)
+               /* Remove one less-recently-used entry. */
+-              cleanup_once(net, 0);
++              cleanup_once(0);
++
+       return n;
+ out_free:
+@@ -451,26 +427,25 @@
+       atomic_inc(&p->refcnt);
+       write_unlock_bh(&peer_pool_lock);
+       /* Remove the entry from unused list if it was there. */
+-      unlink_from_unused(net, p);
++      unlink_from_unused(p);
+       /* Free preallocated the preallocated node. */
+       kmem_cache_free(peer_cachep, n);
+       return p;
+ }
+ /* Called with local BH disabled. */
+-static void peer_check_expire(unsigned long arg)
++static void peer_check_expire(unsigned long dummy)
+ {
+-      struct net *net = (void *)arg;
+       unsigned long now = jiffies;
+       int ttl;
+-      if (net->peer_total >= net->inet_peer_threshold)
+-              ttl = net->inet_peer_minttl;
++      if (peer_total >= inet_peer_threshold)
++              ttl = inet_peer_minttl;
+       else
+-              ttl = net->inet_peer_maxttl
+-                      - (net->inet_peer_maxttl - net->inet_peer_minttl) / HZ *
+-                              net->peer_total / net->inet_peer_threshold * HZ;
+-      while (!cleanup_once(net, ttl)) {
++              ttl = inet_peer_maxttl
++                              - (inet_peer_maxttl - inet_peer_minttl) / HZ *
++                                      peer_total / inet_peer_threshold * HZ;
++      while (!cleanup_once(ttl)) {
+               if (jiffies != now)
+                       break;
+       }
+@@ -478,30 +453,25 @@
+       /* Trigger the timer after inet_peer_gc_mintime .. inet_peer_gc_maxtime
+        * interval depending on the total number of entries (more entries,
+        * less interval). */
+-      if (net->peer_total >= net->inet_peer_threshold)
+-              net->peer_periodic_timer.expires = jiffies 
+-                      + net->inet_peer_gc_mintime;
++      if (peer_total >= inet_peer_threshold)
++              peer_periodic_timer.expires = jiffies + inet_peer_gc_mintime;
+       else
+-              net->peer_periodic_timer.expires = jiffies
+-                      + net->inet_peer_gc_maxtime
+-                      - (net->inet_peer_gc_maxtime - net->inet_peer_gc_mintime) / HZ *
+-                              net->peer_total / net->inet_peer_threshold * HZ;
+-      add_timer(&net->peer_periodic_timer);
++              peer_periodic_timer.expires = jiffies
++                      + inet_peer_gc_maxtime
++                      - (inet_peer_gc_maxtime - inet_peer_gc_mintime) / HZ *
++                              peer_total / inet_peer_threshold * HZ;
++      add_timer(&peer_periodic_timer);
+ }
+ void inet_putpeer(struct inet_peer *p)
+ {
+       spin_lock_bh(&inet_peer_unused_lock);
+       if (atomic_dec_and_test(&p->refcnt)) {
+-              struct net *net = p->u.net;
+-
+-              p->unused_prevp = net->inet_peer_unused_tailp;
+-              p->u.unused_next = NULL;
+-              *net->inet_peer_unused_tailp = p;
+-              net->inet_peer_unused_tailp = &p->u.unused_next;
++              p->unused_prevp = inet_peer_unused_tailp;
++              p->unused_next = NULL;
++              *inet_peer_unused_tailp = p;
++              inet_peer_unused_tailp = &p->unused_next;
+               p->dtime = (__u32)jiffies;
 -
--      if (!(idev->if_flags & IF_READY)) {
--              spin_unlock_bh(&ifp->lock);
--              read_unlock_bh(&idev->lock);
--              /*
--               * If the defice is not ready:
--               * - keep it tentative if it is a permanent address.
--               * - otherwise, kill it.
--               */
--              in6_ifa_hold(ifp);
--              addrconf_dad_stop(ifp);
--              return;
--      }
+-              release_net(net);
+       }
+       spin_unlock_bh(&inet_peer_unused_lock);
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/ip_fragment.c linux-2.6.22-570/net/ipv4/ip_fragment.c
+--- linux-2.6.22-590/net/ipv4/ip_fragment.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ip_fragment.c    2007-07-08 19:32:17.000000000 -0400
+@@ -49,6 +49,21 @@
+  * as well. Or notify me, at least. --ANK
+  */
++/* Fragment cache limits. We will commit 256K at one time. Should we
++ * cross that limit we will prune down to 192K. This should cope with
++ * even the most extreme cases without allowing an attacker to measurably
++ * harm machine performance.
++ */
++int sysctl_ipfrag_high_thresh __read_mostly = 256*1024;
++int sysctl_ipfrag_low_thresh __read_mostly = 192*1024;
++
++int sysctl_ipfrag_max_dist __read_mostly = 64;
++
++/* Important NOTE! Fragment queue must be destroyed before MSL expires.
++ * RFC791 is wrong proposing to prolongate timer each fragment arrival by TTL.
++ */
++int sysctl_ipfrag_time __read_mostly = IP_FRAG_TIME;
++
+ struct ipfrag_skb_cb
+ {
+       struct inet_skb_parm    h;
+@@ -81,7 +96,6 @@
+       int             iif;
+       unsigned int    rid;
+       struct inet_peer *peer;
+-      struct net      *net;
+ };
+ /* Hash table. */
+@@ -89,13 +103,17 @@
+ #define IPQ_HASHSZ    64
+ /* Per-bucket lock is easy to add now. */
++static struct hlist_head ipq_hash[IPQ_HASHSZ];
+ static DEFINE_RWLOCK(ipfrag_lock);
++static u32 ipfrag_hash_rnd;
++static LIST_HEAD(ipq_lru_list);
++int ip_frag_nqueues = 0;
+ static __inline__ void __ipq_unlink(struct ipq *qp)
+ {
+       hlist_del(&qp->list);
+       list_del(&qp->lru_list);
+-      qp->net->ip_frag_nqueues--;
++      ip_frag_nqueues--;
+ }
+ static __inline__ void ipq_unlink(struct ipq *ipq)
+@@ -105,71 +123,70 @@
+       write_unlock(&ipfrag_lock);
+ }
+-static unsigned int ipqhashfn(struct net *net, __be16 id, __be32 saddr, __be32 daddr, u8 prot)
++static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
+ {
+       return jhash_3words((__force u32)id << 16 | prot,
+                           (__force u32)saddr, (__force u32)daddr,
+-                          net->ipfrag_hash_rnd) & (IPQ_HASHSZ - 1);
++                          ipfrag_hash_rnd) & (IPQ_HASHSZ - 1);
+ }
+-static void ipfrag_secret_rebuild(unsigned long arg)
++static struct timer_list ipfrag_secret_timer;
++int sysctl_ipfrag_secret_interval __read_mostly = 10 * 60 * HZ;
++
++static void ipfrag_secret_rebuild(unsigned long dummy)
+ {
+-      struct net *net = (void *)arg;
+       unsigned long now = jiffies;
+       int i;
+       write_lock(&ipfrag_lock);
+-      get_random_bytes(&net->ipfrag_hash_rnd, sizeof(u32));
++      get_random_bytes(&ipfrag_hash_rnd, sizeof(u32));
+       for (i = 0; i < IPQ_HASHSZ; i++) {
+               struct ipq *q;
+-              struct hlist_head *head;
+               struct hlist_node *p, *n;
+-              head = &net->ipq_hash[i];
+-              hlist_for_each_entry_safe(q, p, n, head, list) {
+-                      unsigned int hval = ipqhashfn(net, q->id, q->saddr,
++              hlist_for_each_entry_safe(q, p, n, &ipq_hash[i], list) {
++                      unsigned int hval = ipqhashfn(q->id, q->saddr,
+                                                     q->daddr, q->protocol);
+                       if (hval != i) {
+                               hlist_del(&q->list);
+                               /* Relink to new hash chain. */
+-                              hlist_add_head(&q->list, &net->ipq_hash[hval]);
++                              hlist_add_head(&q->list, &ipq_hash[hval]);
+                       }
+               }
+       }
+       write_unlock(&ipfrag_lock);
+-      mod_timer(&net->ipfrag_secret_timer, 
+-              now + net->sysctl_ipfrag_secret_interval);
++      mod_timer(&ipfrag_secret_timer, now + sysctl_ipfrag_secret_interval);
+ }
++atomic_t ip_frag_mem = ATOMIC_INIT(0);        /* Memory used for fragments */
++
+ /* Memory Tracking Functions. */
+-static __inline__ void frag_kfree_skb(struct net *net, struct sk_buff *skb, int *work)
++static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work)
+ {
+       if (work)
+               *work -= skb->truesize;
+-      atomic_sub(skb->truesize, &net->ip_frag_mem);
++      atomic_sub(skb->truesize, &ip_frag_mem);
+       kfree_skb(skb);
+ }
+ static __inline__ void frag_free_queue(struct ipq *qp, int *work)
+ {
+-      struct net *net = qp->net;
+       if (work)
+               *work -= sizeof(struct ipq);
+-      atomic_sub(sizeof(struct ipq), &net->ip_frag_mem);
+-      release_net(net);
++      atomic_sub(sizeof(struct ipq), &ip_frag_mem);
+       kfree(qp);
+ }
+-static __inline__ struct ipq *frag_alloc_queue(struct net *net)
++static __inline__ struct ipq *frag_alloc_queue(void)
+ {
+       struct ipq *qp = kmalloc(sizeof(struct ipq), GFP_ATOMIC);
+       if (!qp)
+               return NULL;
+-      atomic_add(sizeof(struct ipq), &net->ip_frag_mem);
++      atomic_add(sizeof(struct ipq), &ip_frag_mem);
+       return qp;
+ }
+@@ -192,7 +209,7 @@
+       while (fp) {
+               struct sk_buff *xp = fp->next;
+-              frag_kfree_skb(qp->net, fp, work);
++              frag_kfree_skb(fp, work);
+               fp = xp;
+       }
+@@ -224,23 +241,23 @@
+ /* Memory limiting on fragments.  Evictor trashes the oldest
+  * fragment queue until we are back under the threshold.
+  */
+-static void ip_evictor(struct net *net)
++static void ip_evictor(void)
+ {
+       struct ipq *qp;
+       struct list_head *tmp;
+       int work;
+-      work = atomic_read(&net->ip_frag_mem) - net->sysctl_ipfrag_low_thresh;
++      work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh;
+       if (work <= 0)
+               return;
+       while (work > 0) {
+               read_lock(&ipfrag_lock);
+-              if (list_empty(&net->ipq_lru_list)) {
++              if (list_empty(&ipq_lru_list)) {
+                       read_unlock(&ipfrag_lock);
+                       return;
+               }
+-              tmp = net->ipq_lru_list.next;
++              tmp = ipq_lru_list.next;
+               qp = list_entry(tmp, struct ipq, lru_list);
+               atomic_inc(&qp->refcnt);
+               read_unlock(&ipfrag_lock);
+@@ -275,7 +292,7 @@
+       if ((qp->last_in&FIRST_IN) && qp->fragments != NULL) {
+               struct sk_buff *head = qp->fragments;
+               /* Send an ICMP "Fragment Reassembly Timeout" message. */
+-              if ((head->dev = dev_get_by_index(qp->net, qp->iif)) != NULL) {
++              if ((head->dev = dev_get_by_index(qp->iif)) != NULL) {
+                       icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
+                       dev_put(head->dev);
+               }
+@@ -287,7 +304,7 @@
+ /* Creation primitives. */
+-static struct ipq *ip_frag_intern(struct net *net, struct ipq *qp_in)
++static struct ipq *ip_frag_intern(struct ipq *qp_in)
+ {
+       struct ipq *qp;
+ #ifdef CONFIG_SMP
+@@ -296,14 +313,14 @@
+       unsigned int hash;
+       write_lock(&ipfrag_lock);
+-      hash = ipqhashfn(net, qp_in->id, qp_in->saddr, qp_in->daddr,
++      hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
+                        qp_in->protocol);
+ #ifdef CONFIG_SMP
+       /* With SMP race we have to recheck hash table, because
+        * such entry could be created on other cpu, while we
+        * promoted read lock to write lock.
+        */
+-      hlist_for_each_entry(qp, n, &net->ipq_hash[hash], list) {
++      hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
+               if (qp->id == qp_in->id         &&
+                   qp->saddr == qp_in->saddr   &&
+                   qp->daddr == qp_in->daddr   &&
+@@ -319,27 +336,26 @@
+ #endif
+       qp = qp_in;
+-      if (!mod_timer(&qp->timer, jiffies + net->sysctl_ipfrag_time))
++      if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time))
+               atomic_inc(&qp->refcnt);
+       atomic_inc(&qp->refcnt);
+-      hlist_add_head(&qp->list, &net->ipq_hash[hash]);
++      hlist_add_head(&qp->list, &ipq_hash[hash]);
+       INIT_LIST_HEAD(&qp->lru_list);
+-      list_add_tail(&qp->lru_list, &net->ipq_lru_list);
+-      net->ip_frag_nqueues++;
++      list_add_tail(&qp->lru_list, &ipq_lru_list);
++      ip_frag_nqueues++;
+       write_unlock(&ipfrag_lock);
+       return qp;
+ }
+ /* Add an entry to the 'ipq' queue for a newly received IP datagram. */
+-static struct ipq *ip_frag_create(struct net *net, struct iphdr *iph, u32 user)
++static struct ipq *ip_frag_create(struct iphdr *iph, u32 user)
+ {
+       struct ipq *qp;
+-      if ((qp = frag_alloc_queue(net)) == NULL)
++      if ((qp = frag_alloc_queue()) == NULL)
+               goto out_nomem;
+-      qp->net = hold_net(net);
+       qp->protocol = iph->protocol;
+       qp->last_in = 0;
+       qp->id = iph->id;
+@@ -350,8 +366,7 @@
+       qp->meat = 0;
+       qp->fragments = NULL;
+       qp->iif = 0;
+-      qp->peer = net->sysctl_ipfrag_max_dist ?
+-              inet_getpeer(net, iph->saddr, 1) : NULL;
++      qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL;
+       /* Initialize a timer for this entry. */
+       init_timer(&qp->timer);
+@@ -360,7 +375,7 @@
+       spin_lock_init(&qp->lock);
+       atomic_set(&qp->refcnt, 1);
+-      return ip_frag_intern(net, qp);
++      return ip_frag_intern(qp);
+ out_nomem:
+       LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n");
+@@ -370,7 +385,7 @@
+ /* Find the correct entry in the "incomplete datagrams" queue for
+  * this IP datagram, and create new one, if nothing is found.
+  */
+-static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user)
++static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
+ {
+       __be16 id = iph->id;
+       __be32 saddr = iph->saddr;
+@@ -381,8 +396,8 @@
+       struct hlist_node *n;
+       read_lock(&ipfrag_lock);
+-      hash = ipqhashfn(net, id, saddr, daddr, protocol);
+-      hlist_for_each_entry(qp, n, &net->ipq_hash[hash], list) {
++      hash = ipqhashfn(id, saddr, daddr, protocol);
++      hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
+               if (qp->id == id                &&
+                   qp->saddr == saddr  &&
+                   qp->daddr == daddr  &&
+@@ -395,14 +410,14 @@
+       }
+       read_unlock(&ipfrag_lock);
+-      return ip_frag_create(net, iph, user);
++      return ip_frag_create(iph, user);
+ }
+ /* Is the fragment too far ahead to be part of ipq? */
+ static inline int ip_frag_too_far(struct ipq *qp)
+ {
+       struct inet_peer *peer = qp->peer;
+-      unsigned int max = qp->net->sysctl_ipfrag_max_dist;
++      unsigned int max = sysctl_ipfrag_max_dist;
+       unsigned int start, end;
+       int rc;
+@@ -427,7 +442,7 @@
+ {
+       struct sk_buff *fp;
+-      if (!mod_timer(&qp->timer, jiffies + qp->net->sysctl_ipfrag_time)) {
++      if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time)) {
+               atomic_inc(&qp->refcnt);
+               return -ETIMEDOUT;
+       }
+@@ -435,7 +450,7 @@
+       fp = qp->fragments;
+       do {
+               struct sk_buff *xp = fp->next;
+-              frag_kfree_skb(qp->net, fp, NULL);
++              frag_kfree_skb(fp, NULL);
+               fp = xp;
+       } while (fp);
+@@ -451,7 +466,6 @@
+ /* Add new segment to existing queue. */
+ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
+ {
+-      struct net *net = qp->net;
+       struct sk_buff *prev, *next;
+       int flags, offset;
+       int ihl, end;
+@@ -562,7 +576,7 @@
+                               qp->fragments = next;
+                       qp->meat -= free_it->len;
+-                      frag_kfree_skb(net, free_it, NULL);
++                      frag_kfree_skb(free_it, NULL);
+               }
+       }
+@@ -580,12 +594,12 @@
+       skb->dev = NULL;
+       qp->stamp = skb->tstamp;
+       qp->meat += skb->len;
+-      atomic_add(skb->truesize, &net->ip_frag_mem);
++      atomic_add(skb->truesize, &ip_frag_mem);
+       if (offset == 0)
+               qp->last_in |= FIRST_IN;
+       write_lock(&ipfrag_lock);
+-      list_move_tail(&qp->lru_list, &net->ipq_lru_list);
++      list_move_tail(&qp->lru_list, &ipq_lru_list);
+       write_unlock(&ipfrag_lock);
+       return;
+@@ -599,7 +613,6 @@
+ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
+ {
+-      struct net *net = qp->net;
+       struct iphdr *iph;
+       struct sk_buff *fp, *head = qp->fragments;
+       int len;
+@@ -641,12 +654,12 @@
+               head->len -= clone->len;
+               clone->csum = 0;
+               clone->ip_summed = head->ip_summed;
+-              atomic_add(clone->truesize, &net->ip_frag_mem);
++              atomic_add(clone->truesize, &ip_frag_mem);
+       }
+       skb_shinfo(head)->frag_list = head->next;
+       skb_push(head, head->data - skb_network_header(head));
+-      atomic_sub(head->truesize, &net->ip_frag_mem);
++      atomic_sub(head->truesize, &ip_frag_mem);
+       for (fp=head->next; fp; fp = fp->next) {
+               head->data_len += fp->len;
+@@ -656,7 +669,7 @@
+               else if (head->ip_summed == CHECKSUM_COMPLETE)
+                       head->csum = csum_add(head->csum, fp->csum);
+               head->truesize += fp->truesize;
+-              atomic_sub(fp->truesize, &net->ip_frag_mem);
++              atomic_sub(fp->truesize, &ip_frag_mem);
+       }
+       head->next = NULL;
+@@ -687,20 +700,19 @@
+ /* Process an incoming IP datagram fragment. */
+ struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
+ {
+-      struct net *net = skb->dev->nd_net;
+       struct ipq *qp;
+       struct net_device *dev;
+       IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS);
+       /* Start by cleaning up the memory. */
+-      if (atomic_read(&net->ip_frag_mem) > net->sysctl_ipfrag_high_thresh)
+-              ip_evictor(net);
++      if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh)
++              ip_evictor();
+       dev = skb->dev;
+       /* Lookup (or create) queue header */
+-      if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) {
++      if ((qp = ip_find(ip_hdr(skb), user)) != NULL) {
+               struct sk_buff *ret = NULL;
+               spin_lock(&qp->lock);
+@@ -721,70 +733,15 @@
+       return NULL;
+ }
+-static int ipfrag_net_init(struct net *net)
++void __init ipfrag_init(void)
+ {
+-      struct timer_list *secret_timer;
+-      int i;
 -
--      /*
--       * Optimistic nodes can start receiving
--       * Frames right away
+-      /* Fragment cache limits. We will commit 256K at one time. Should we
+-       * cross that limit we will prune down to 192K. This should cope with
+-       * even the most extreme cases without allowing an attacker to measurably
+-       * harm machine performance.
 -       */
--      if(ifp->flags & IFA_F_OPTIMISTIC)
--              ip6_ins_rt(ifp->rt);
--
--      addrconf_dad_kick(ifp);
--      spin_unlock_bh(&ifp->lock);
--out:
--      read_unlock_bh(&idev->lock);
--}
--
--static void addrconf_dad_timer(unsigned long data)
--{
--      struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data;
--      struct inet6_dev *idev = ifp->idev;
--      struct in6_addr unspec;
--      struct in6_addr mcaddr;
--
--      read_lock_bh(&idev->lock);
--      if (idev->dead) {
--              read_unlock_bh(&idev->lock);
--              goto out;
--      }
--      spin_lock_bh(&ifp->lock);
--      if (ifp->probes == 0) {
--              /*
--               * DAD was successful
--               */
--
--              ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC);
--              spin_unlock_bh(&ifp->lock);
--              read_unlock_bh(&idev->lock);
--
--              addrconf_dad_completed(ifp);
--
--              goto out;
--      }
--
--      ifp->probes--;
--      addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time);
--      spin_unlock_bh(&ifp->lock);
--      read_unlock_bh(&idev->lock);
--
--      /* send a neighbour solicitation for our addr */
--      memset(&unspec, 0, sizeof(unspec));
--      addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
--      ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec);
--out:
--      in6_ifa_put(ifp);
--}
--
--static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
--{
--      struct net_device *     dev = ifp->idev->dev;
+-      net->sysctl_ipfrag_high_thresh = 256*1024;
+-      net->sysctl_ipfrag_low_thresh = 192*1024;
+-      net->sysctl_ipfrag_max_dist = 64;
 -
--      /*
--       *      Configure the address for reception. Now it is valid.
+-      /* Important NOTE! Fragment queue must be destroyed before MSL expires.
+-       * RFC791 is wrong proposing to prolongate timer each fragment arrival by TTL.
 -       */
+-      net->sysctl_ipfrag_time = IP_FRAG_TIME;
 -
--      ipv6_ifa_notify(RTM_NEWADDR, ifp);
+-      net->sysctl_ipfrag_secret_interval = 10 * 60 * HZ;
 -
--      /* If added prefix is link local and forwarding is off,
--         start sending router solicitations.
--       */
+-      net->ipq_hash = kzalloc(sizeof(*net->ipq_hash)*IPQ_HASHSZ, GFP_KERNEL);
+-      if (!net->ipq_hash)
+-              return -ENOMEM;
 -
--      if (ifp->idev->cnf.forwarding == 0 &&
--          ifp->idev->cnf.rtr_solicits > 0 &&
--          (dev->flags&IFF_LOOPBACK) == 0 &&
--          (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
--              struct in6_addr all_routers;
+-      for (i = 0; i < IPQ_HASHSZ; i++)
+-              INIT_HLIST_HEAD(&net->ipq_hash[i]);
+-      INIT_LIST_HEAD(&net->ipq_lru_list);
+-      net->ip_frag_nqueues = 0;
+-      atomic_set(&net->ip_frag_mem, 0);
 -
--              ipv6_addr_all_routers(&all_routers);
 -
--              /*
--               *      If a host as already performed a random delay
--               *      [...] as part of DAD [...] there is no need
--               *      to delay again before sending the first RS
--               */
--              ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers);
+-      net->ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
++      ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
+                                (jiffies ^ (jiffies >> 6)));
+-      secret_timer = &net->ipfrag_secret_timer;
+-      init_timer(secret_timer);
+-      secret_timer->function = ipfrag_secret_rebuild;
+-      secret_timer->expires = jiffies + net->sysctl_ipfrag_secret_interval;
+-      secret_timer->data = (unsigned long)net;
+-      add_timer(secret_timer);
 -
--              spin_lock_bh(&ifp->lock);
--              ifp->probes = 1;
--              ifp->idev->if_flags |= IF_RS_SENT;
--              addrconf_mod_timer(ifp, AC_RS, ifp->idev->cnf.rtr_solicit_interval);
--              spin_unlock_bh(&ifp->lock);
--      }
+-      return 0;
 -}
 -
--static void addrconf_dad_run(struct inet6_dev *idev) {
--      struct inet6_ifaddr *ifp;
+-static void ipfrag_net_exit(struct net *net)
+-{
+-      del_timer(&net->ipfrag_secret_timer);
 -
--      read_lock_bh(&idev->lock);
--      for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) {
--              spin_lock_bh(&ifp->lock);
--              if (!(ifp->flags & IFA_F_TENTATIVE)) {
--                      spin_unlock_bh(&ifp->lock);
--                      continue;
--              }
--              spin_unlock_bh(&ifp->lock);
--              addrconf_dad_kick(ifp);
--      }
--      read_unlock_bh(&idev->lock);
+-      net->sysctl_ipfrag_low_thresh = 0;
+-      while (atomic_read(&net->ip_frag_mem))
+-              ip_evictor(net);
+-
+-      kfree(net->ipq_hash);
 -}
 -
--#ifdef CONFIG_PROC_FS
--struct if6_iter_state {
--      int bucket;
+-static struct pernet_operations ipfrag_net_ops = {
+-      .init = ipfrag_net_init,
+-      .exit = ipfrag_net_exit,
 -};
 -
--static struct inet6_ifaddr *if6_get_first(struct seq_file *seq)
+-void ipfrag_init(void)
 -{
--      struct inet6_ifaddr *ifa = NULL;
--      struct if6_iter_state *state = seq->private;
+-      register_pernet_subsys(&ipfrag_net_ops);
++      init_timer(&ipfrag_secret_timer);
++      ipfrag_secret_timer.function = ipfrag_secret_rebuild;
++      ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval;
++      add_timer(&ipfrag_secret_timer);
+ }
+ EXPORT_SYMBOL(ip_defrag);
+diff -Nurb linux-2.6.22-590/net/ipv4/ip_gre.c linux-2.6.22-570/net/ipv4/ip_gre.c
+--- linux-2.6.22-590/net/ipv4/ip_gre.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ip_gre.c 2007-07-08 19:32:17.000000000 -0400
+@@ -262,7 +262,7 @@
+               int i;
+               for (i=1; i<100; i++) {
+                       sprintf(name, "gre%d", i);
+-                      if (__dev_get_by_name(&init_net, name) == NULL)
++                      if (__dev_get_by_name(name) == NULL)
+                               break;
+               }
+               if (i==100)
+@@ -397,9 +397,6 @@
+       struct flowi fl;
+       struct rtable *rt;
+-      if (skb->dev->nd_net != &init_net)
+-              return;
 -
--      for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) {
--              ifa = inet6_addr_lst[state->bucket];
--              if (ifa)
--                      break;
+       if (p[1] != htons(ETH_P_IP))
+               return;
+@@ -478,7 +475,6 @@
+       /* Try to guess incoming interface */
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       fl.fl4_dst = eiph->saddr;
+       fl.fl4_tos = RT_TOS(eiph->tos);
+       fl.proto = IPPROTO_GRE;
+@@ -563,10 +559,6 @@
+       struct ip_tunnel *tunnel;
+       int    offset = 4;
+-      if (skb->dev->nd_net != &init_net) {
+-              kfree_skb(skb);
+-              return 0;
 -      }
--      return ifa;
--}
+       if (!pskb_may_pull(skb, 16))
+               goto drop_nolock;
+@@ -748,8 +740,7 @@
+       }
+       {
+-              struct flowi fl = { .fl_net = &init_net,
+-                                  .oif = tunnel->parms.link,
++              struct flowi fl = { .oif = tunnel->parms.link,
+                                   .nl_u = { .ip4_u =
+                                             { .daddr = dst,
+                                               .saddr = tiph->saddr,
+@@ -1104,8 +1095,7 @@
+       struct ip_tunnel *t = netdev_priv(dev);
+       if (MULTICAST(t->parms.iph.daddr)) {
+-              struct flowi fl = { .fl_net = &init_net,
+-                                  .oif = t->parms.link,
++              struct flowi fl = { .oif = t->parms.link,
+                                   .nl_u = { .ip4_u =
+                                             { .daddr = t->parms.iph.daddr,
+                                               .saddr = t->parms.iph.saddr,
+@@ -1128,7 +1118,7 @@
+ {
+       struct ip_tunnel *t = netdev_priv(dev);
+       if (MULTICAST(t->parms.iph.daddr) && t->mlink) {
+-              struct in_device *in_dev = inetdev_by_index(&init_net, t->mlink);
++              struct in_device *in_dev = inetdev_by_index(t->mlink);
+               if (in_dev) {
+                       ip_mc_dec_group(in_dev, t->parms.iph.daddr);
+                       in_dev_put(in_dev);
+@@ -1178,8 +1168,7 @@
+       /* Guess output device to choose reasonable mtu and hard_header_len */
+       if (iph->daddr) {
+-              struct flowi fl = { .fl_net = &init_net,
+-                                  .oif = tunnel->parms.link,
++              struct flowi fl = { .oif = tunnel->parms.link,
+                                   .nl_u = { .ip4_u =
+                                             { .daddr = iph->daddr,
+                                               .saddr = iph->saddr,
+@@ -1206,7 +1195,7 @@
+       }
+       if (!tdev && tunnel->parms.link)
+-              tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
++              tdev = __dev_get_by_index(tunnel->parms.link);
+       if (tdev) {
+               hlen = tdev->hard_header_len;
+diff -Nurb linux-2.6.22-590/net/ipv4/ip_input.c linux-2.6.22-570/net/ipv4/ip_input.c
+--- linux-2.6.22-590/net/ipv4/ip_input.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ip_input.c       2007-07-08 19:32:17.000000000 -0400
+@@ -280,10 +280,6 @@
+       struct iphdr *iph;
+       struct net_device *dev = skb->dev;
 -
--static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa)
--{
--      struct if6_iter_state *state = seq->private;
+-      if (skb->dev->nd_net != &init_net)
+-              goto drop;
+-
+       /* It looks as overkill, because not all
+          IP options require packet mangling.
+          But it is the easiest for now, especially taking
+diff -Nurb linux-2.6.22-590/net/ipv4/ip_options.c linux-2.6.22-570/net/ipv4/ip_options.c
+--- linux-2.6.22-590/net/ipv4/ip_options.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ip_options.c     2008-01-23 19:16:10.000000000 -0500
+@@ -151,7 +151,7 @@
+                                               __be32 addr;
+                                               memcpy(&addr, sptr+soffset-1, 4);
+-                                              if (inet_addr_type(&init_net, addr) != RTN_LOCAL) {
++                                              if (inet_addr_type(addr) != RTN_LOCAL) {
+                                                       dopt->ts_needtime = 1;
+                                                       soffset += 8;
+                                               }
+@@ -400,7 +400,7 @@
+                                       {
+                                               __be32 addr;
+                                               memcpy(&addr, &optptr[optptr[2]-1], 4);
+-                                              if (inet_addr_type(&init_net, addr) == RTN_UNICAST)
++                                              if (inet_addr_type(addr) == RTN_UNICAST)
+                                                       break;
+                                               if (skb)
+                                                       timeptr = (__be32*)&optptr[optptr[2]+3];
+diff -Nurb linux-2.6.22-590/net/ipv4/ip_output.c linux-2.6.22-570/net/ipv4/ip_output.c
+--- linux-2.6.22-590/net/ipv4/ip_output.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ip_output.c      2007-07-08 19:32:17.000000000 -0400
+@@ -83,6 +83,8 @@
+ #include <linux/netlink.h>
+ #include <linux/tcp.h>
++int sysctl_ip_default_ttl __read_mostly = IPDEFTTL;
++
+ /* Generate a checksum for an outgoing IP datagram. */
+ __inline__ void ip_send_check(struct iphdr *iph)
+ {
+@@ -315,8 +317,7 @@
+                       daddr = opt->faddr;
+               {
+-                      struct flowi fl = { .fl_net = sk->sk_net,
+-                                          .oif = sk->sk_bound_dev_if,
++                      struct flowi fl = { .oif = sk->sk_bound_dev_if,
+                                           .nl_u = { .ip4_u =
+                                                     { .daddr = daddr,
+                                                       .saddr = inet->saddr,
+@@ -836,7 +837,7 @@
+        */
+       if (transhdrlen &&
+           length + fragheaderlen <= mtu &&
+-          rt->u.dst.dev->features & NETIF_F_V4_CSUM &&
++          rt->u.dst.dev->features & NETIF_F_ALL_CSUM &&
+           !exthdrlen)
+               csummode = CHECKSUM_PARTIAL;
+@@ -1351,8 +1352,7 @@
+       }
+       {
+-              struct flowi fl = { .fl_net = sk->sk_net,
+-                                  .oif = arg->bound_dev_if,
++              struct flowi fl = { .oif = arg->bound_dev_if,
+                                   .nl_u = { .ip4_u =
+                                             { .daddr = daddr,
+                                               .saddr = rt->rt_spec_dst,
+diff -Nurb linux-2.6.22-590/net/ipv4/ip_sockglue.c linux-2.6.22-570/net/ipv4/ip_sockglue.c
+--- linux-2.6.22-590/net/ipv4/ip_sockglue.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ip_sockglue.c    2007-07-08 19:32:17.000000000 -0400
+@@ -411,7 +411,6 @@
+ static int do_ip_setsockopt(struct sock *sk, int level,
+                           int optname, char __user *optval, int optlen)
+ {
+-      struct net *net = sk->sk_net;
+       struct inet_sock *inet = inet_sk(sk);
+       int val=0,err;
+@@ -597,13 +596,13 @@
+                               err = 0;
+                               break;
+                       }
+-                      dev = ip_dev_find(net, mreq.imr_address.s_addr);
++                      dev = ip_dev_find(mreq.imr_address.s_addr);
+                       if (dev) {
+                               mreq.imr_ifindex = dev->ifindex;
+                               dev_put(dev);
+                       }
+               } else
+-                      dev = __dev_get_by_index(net, mreq.imr_ifindex);
++                      dev = __dev_get_by_index(mreq.imr_ifindex);
+               err = -EADDRNOTAVAIL;
+@@ -957,7 +956,6 @@
+ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
+                           char __user *optval, int __user *optlen)
+ {
+-      struct net *net = sk->sk_net;
+       struct inet_sock *inet = inet_sk(sk);
+       int val;
+       int len;
+@@ -1025,7 +1023,7 @@
+               break;
+       case IP_TTL:
+               val = (inet->uc_ttl == -1 ?
+-                     net->sysctl_ip_default_ttl :
++                     sysctl_ip_default_ttl :
+                      inet->uc_ttl);
+               break;
+       case IP_HDRINCL:
+diff -Nurb linux-2.6.22-590/net/ipv4/ipcomp.c linux-2.6.22-570/net/ipv4/ipcomp.c
+--- linux-2.6.22-590/net/ipv4/ipcomp.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ipcomp.c 2008-01-23 19:15:56.000000000 -0500
+@@ -175,9 +175,6 @@
+       struct ip_comp_hdr *ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
+       struct xfrm_state *x;
+-      if (skb->dev->nd_net != &init_net)
+-              return;
+-
+       if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH ||
+           icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
+               return;
+@@ -489,4 +486,3 @@
+ MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) - RFC3173");
+ MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
+-MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_COMP);
+diff -Nurb linux-2.6.22-590/net/ipv4/ipconfig.c linux-2.6.22-570/net/ipv4/ipconfig.c
+--- linux-2.6.22-590/net/ipv4/ipconfig.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ipconfig.c       2007-07-08 19:32:17.000000000 -0400
+@@ -59,7 +59,6 @@
+ #include <net/ip.h>
+ #include <net/ipconfig.h>
+ #include <net/route.h>
+-#include <net/net_namespace.h>
+ #include <asm/uaccess.h>
+ #include <net/checksum.h>
+@@ -185,18 +184,16 @@
+       struct ic_device *d, **last;
+       struct net_device *dev;
+       unsigned short oflags;
+-      struct net_device *lo;
+       last = &ic_first_dev;
+       rtnl_lock();
+       /* bring loopback device up first */
+-      lo = &init_net.loopback_dev;
+-      if (dev_change_flags(lo, lo->flags | IFF_UP) < 0)
+-              printk(KERN_ERR "IP-Config: Failed to open %s\n", lo->name);
++      if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0)
++              printk(KERN_ERR "IP-Config: Failed to open %s\n", loopback_dev.name);
+-      for_each_netdev(&init_net, dev) {
+-              if (dev == lo)
++      for_each_netdev(dev) {
++              if (dev == &loopback_dev)
+                       continue;
+               if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
+                   (!(dev->flags & IFF_LOOPBACK) &&
+@@ -286,7 +283,7 @@
+       mm_segment_t oldfs = get_fs();
+       set_fs(get_ds());
+-      res = devinet_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
++      res = devinet_ioctl(cmd, (struct ifreq __user *) arg);
+       set_fs(oldfs);
+       return res;
+ }
+@@ -297,7 +294,7 @@
+       mm_segment_t oldfs = get_fs();
+       set_fs(get_ds());
+-      res = ip_rt_ioctl(&init_net, cmd, (void __user *) arg);
++      res = ip_rt_ioctl(cmd, (void __user *) arg);
+       set_fs(oldfs);
+       return res;
+ }
+@@ -428,9 +425,6 @@
+       unsigned char *sha, *tha;               /* s for "source", t for "target" */
+       struct ic_device *d;
+-      if (dev->nd_net != &init_net)
+-              goto drop;
+-
+       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+               return NET_RX_DROP;
+@@ -840,9 +834,6 @@
+       struct ic_device *d;
+       int len, ext_len;
+-      if (dev->nd_net != &init_net)
+-              goto drop;
+-
+       /* Perform verifications before taking the lock.  */
+       if (skb->pkt_type == PACKET_OTHERHOST)
+               goto drop;
+@@ -1262,7 +1253,7 @@
+       __be32 addr;
+ #ifdef CONFIG_PROC_FS
+-      proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops);
++      proc_net_fops_create("pnp", S_IRUGO, &pnp_seq_fops);
+ #endif /* CONFIG_PROC_FS */
+       if (!ic_enable)
+diff -Nurb linux-2.6.22-590/net/ipv4/ipip.c linux-2.6.22-570/net/ipv4/ipip.c
+--- linux-2.6.22-590/net/ipv4/ipip.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ipip.c   2007-07-08 19:32:17.000000000 -0400
+@@ -225,7 +225,7 @@
+               int i;
+               for (i=1; i<100; i++) {
+                       sprintf(name, "tunl%d", i);
+-                      if (__dev_get_by_name(&init_net, name) == NULL)
++                      if (__dev_get_by_name(name) == NULL)
+                               break;
+               }
+               if (i==100)
+@@ -403,7 +403,6 @@
+       /* Try to guess incoming interface */
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       fl.fl4_daddr = eiph->saddr;
+       fl.fl4_tos = RT_TOS(eiph->tos);
+       fl.proto = IPPROTO_IPIP;
+@@ -543,8 +542,7 @@
+       }
+       {
+-              struct flowi fl = { .fl_net = &init_net,
+-                                  .oif = tunnel->parms.link,
++              struct flowi fl = { .oif = tunnel->parms.link,
+                                   .nl_u = { .ip4_u =
+                                             { .daddr = dst,
+                                               .saddr = tiph->saddr,
+@@ -808,8 +806,7 @@
+       memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
+       if (iph->daddr) {
+-              struct flowi fl = { .fl_net = &init_net,
+-                                  .oif = tunnel->parms.link,
++              struct flowi fl = { .oif = tunnel->parms.link,
+                                   .nl_u = { .ip4_u =
+                                             { .daddr = iph->daddr,
+                                               .saddr = iph->saddr,
+@@ -824,7 +821,7 @@
+       }
+       if (!tdev && tunnel->parms.link)
+-              tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
++              tdev = __dev_get_by_index(tunnel->parms.link);
+       if (tdev) {
+               dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
+diff -Nurb linux-2.6.22-590/net/ipv4/ipmr.c linux-2.6.22-570/net/ipv4/ipmr.c
+--- linux-2.6.22-590/net/ipv4/ipmr.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ipmr.c   2007-07-08 19:32:17.000000000 -0400
+@@ -62,7 +62,6 @@
+ #include <linux/netfilter_ipv4.h>
+ #include <net/ipip.h>
+ #include <net/checksum.h>
+-#include <net/net_namespace.h>
+ #include <net/netlink.h>
+ #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
+@@ -125,7 +124,7 @@
+ {
+       struct net_device  *dev;
+-      dev = __dev_get_by_name(&init_net, "tunl0");
++      dev = __dev_get_by_name("tunl0");
+       if (dev) {
+               int err;
+@@ -149,7 +148,7 @@
+               dev = NULL;
+-              if (err == 0 && (dev = __dev_get_by_name(&init_net, p.name)) != NULL) {
++              if (err == 0 && (dev = __dev_get_by_name(p.name)) != NULL) {
+                       dev->flags |= IFF_MULTICAST;
+                       in_dev = __in_dev_get_rtnl(dev);
+@@ -321,7 +320,7 @@
+                       e->error = -ETIMEDOUT;
+                       memset(&e->msg, 0, sizeof(e->msg));
+-                      rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
++                      rtnl_unicast(skb, NETLINK_CB(skb).pid);
+               } else
+                       kfree_skb(skb);
+       }
+@@ -423,7 +422,7 @@
+                       return -ENOBUFS;
+               break;
+       case 0:
+-              dev = ip_dev_find(&init_net, vifc->vifc_lcl_addr.s_addr);
++              dev = ip_dev_find(vifc->vifc_lcl_addr.s_addr);
+               if (!dev)
+                       return -EADDRNOTAVAIL;
+               dev_put(dev);
+@@ -533,7 +532,7 @@
+                               memset(&e->msg, 0, sizeof(e->msg));
+                       }
+-                      rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
++                      rtnl_unicast(skb, NETLINK_CB(skb).pid);
+               } else
+                       ip_mr_forward(skb, c, 0);
+       }
+@@ -849,7 +848,7 @@
+ {
+       rtnl_lock();
+       if (sk == mroute_socket) {
+-              IPV4_DEVCONF_ALL(sk->sk_net, MC_FORWARDING)--;
++              IPV4_DEVCONF_ALL(MC_FORWARDING)--;
+               write_lock_bh(&mrt_lock);
+               mroute_socket=NULL;
+@@ -898,7 +897,7 @@
+                       mroute_socket=sk;
+                       write_unlock_bh(&mrt_lock);
+-                      IPV4_DEVCONF_ALL(sk->sk_net, MC_FORWARDING)++;
++                      IPV4_DEVCONF_ALL(MC_FORWARDING)++;
+               }
+               rtnl_unlock();
+               return ret;
+@@ -1083,18 +1082,13 @@
+ static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
+ {
+-      struct net_device *dev = ptr;
+       struct vif_device *v;
+       int ct;
+-
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--      ifa = ifa->lst_next;
--try_again:
--      if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) {
--              ifa = inet6_addr_lst[state->bucket];
--              goto try_again;
+       if (event != NETDEV_UNREGISTER)
+               return NOTIFY_DONE;
+       v=&vif_table[0];
+       for (ct=0;ct<maxvif;ct++,v++) {
+-              if (v->dev==dev)
++              if (v->dev==ptr)
+                       vif_delete(ct);
+       }
+       return NOTIFY_DONE;
+@@ -1177,8 +1171,7 @@
+ #endif
+       if (vif->flags&VIFF_TUNNEL) {
+-              struct flowi fl = { .fl_net = &init_net,
+-                                  .oif = vif->link,
++              struct flowi fl = { .oif = vif->link,
+                                   .nl_u = { .ip4_u =
+                                             { .daddr = vif->remote,
+                                               .saddr = vif->local,
+@@ -1188,8 +1181,7 @@
+                       goto out_free;
+               encap = sizeof(struct iphdr);
+       } else {
+-              struct flowi fl = { .fl_net = &init_net,
+-                                  .oif = vif->link,
++              struct flowi fl = { .oif = vif->link,
+                                   .nl_u = { .ip4_u =
+                                             { .daddr = iph->daddr,
+                                               .tos = RT_TOS(iph->tos) } },
+@@ -1506,10 +1498,6 @@
+       struct iphdr   *encap;
+       struct net_device  *reg_dev = NULL;
+-      if (skb->dev->nd_net != &init_net) {
+-              kfree_skb(skb);
+-              return 0;
 -      }
--      return ifa;
--}
+       if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
+               goto drop;
+@@ -1934,7 +1922,7 @@
+       ipmr_expire_timer.function=ipmr_expire_process;
+       register_netdevice_notifier(&ip_mr_notifier);
+ #ifdef CONFIG_PROC_FS
+-      proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops);
+-      proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops);
++      proc_net_fops_create("ip_mr_vif", 0, &ipmr_vif_fops);
++      proc_net_fops_create("ip_mr_cache", 0, &ipmr_mfc_fops);
+ #endif
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/ipvs/ip_vs_app.c linux-2.6.22-570/net/ipv4/ipvs/ip_vs_app.c
+--- linux-2.6.22-590/net/ipv4/ipvs/ip_vs_app.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ipvs/ip_vs_app.c 2007-07-08 19:32:17.000000000 -0400
+@@ -32,7 +32,6 @@
+ #include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
+ #include <linux/mutex.h>
+-#include <net/net_namespace.h>
+ #include <net/ip_vs.h>
+@@ -617,12 +616,12 @@
+ int ip_vs_app_init(void)
+ {
+       /* we will replace it with proc_net_ipvs_create() soon */
+-      proc_net_fops_create(&init_net, "ip_vs_app", 0, &ip_vs_app_fops);
++      proc_net_fops_create("ip_vs_app", 0, &ip_vs_app_fops);
+       return 0;
+ }
+ void ip_vs_app_cleanup(void)
+ {
+-      proc_net_remove(&init_net, "ip_vs_app");
++      proc_net_remove("ip_vs_app");
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/ipvs/ip_vs_conn.c linux-2.6.22-570/net/ipv4/ipvs/ip_vs_conn.c
+--- linux-2.6.22-590/net/ipv4/ipvs/ip_vs_conn.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ipvs/ip_vs_conn.c        2007-07-08 19:32:17.000000000 -0400
+@@ -34,7 +34,6 @@
+ #include <linux/seq_file.h>
+ #include <linux/jhash.h>
+ #include <linux/random.h>
+-#include <net/net_namespace.h>
+ #include <net/ip_vs.h>
+@@ -923,7 +922,7 @@
+               rwlock_init(&__ip_vs_conntbl_lock_array[idx].l);
+       }
+-      proc_net_fops_create(&init_net, "ip_vs_conn", 0, &ip_vs_conn_fops);
++      proc_net_fops_create("ip_vs_conn", 0, &ip_vs_conn_fops);
+       /* calculate the random value for connection hash */
+       get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd));
+@@ -939,6 +938,6 @@
+       /* Release the empty cache */
+       kmem_cache_destroy(ip_vs_conn_cachep);
+-      proc_net_remove(&init_net, "ip_vs_conn");
++      proc_net_remove("ip_vs_conn");
+       vfree(ip_vs_conn_tab);
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/ipvs/ip_vs_core.c linux-2.6.22-570/net/ipv4/ipvs/ip_vs_core.c
+--- linux-2.6.22-590/net/ipv4/ipvs/ip_vs_core.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ipvs/ip_vs_core.c        2007-07-08 19:32:17.000000000 -0400
+@@ -460,7 +460,7 @@
+          and the destination is RTN_UNICAST (and not local), then create
+          a cache_bypass connection entry */
+       if (sysctl_ip_vs_cache_bypass && svc->fwmark
+-          && (inet_addr_type(&init_net, iph->daddr) == RTN_UNICAST)) {
++          && (inet_addr_type(iph->daddr) == RTN_UNICAST)) {
+               int ret, cs;
+               struct ip_vs_conn *cp;
+@@ -530,10 +530,6 @@
+                                      const struct net_device *out,
+                                      int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos)
--{
--      struct inet6_ifaddr *ifa = if6_get_first(seq);
+       if (!((*pskb)->ipvs_property))
+               return NF_ACCEPT;
+       /* The packet was sent from IPVS, exit this chain */
+@@ -738,10 +734,6 @@
+       struct ip_vs_conn *cp;
+       int ihl;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--      if (ifa)
--              while(pos && (ifa = if6_get_next(seq, ifa)) != NULL)
--                      --pos;
--      return pos ? NULL : ifa;
--}
+       EnterFunction(11);
+       if (skb->ipvs_property)
+@@ -826,7 +818,7 @@
+        * if it came from this machine itself.  So re-compute
+        * the routing information.
+        */
+-      if (ip_route_me_harder(&init_net, pskb, RTN_LOCAL) != 0)
++      if (ip_route_me_harder(pskb, RTN_LOCAL) != 0)
+               goto drop;
+       skb = *pskb;
+@@ -964,16 +956,12 @@
+       int ret, restart;
+       int ihl;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--static void *if6_seq_start(struct seq_file *seq, loff_t *pos)
--{
--      read_lock_bh(&addrconf_hash_lock);
--      return if6_get_idx(seq, *pos);
--}
+       /*
+        *      Big tappo: only PACKET_HOST (neither loopback nor mcasts)
+        *      ... don't know why 1st test DOES NOT include 2nd (?)
+        */
+       if (unlikely(skb->pkt_type != PACKET_HOST
+-                   || skb->dev == &init_net.loopback_dev || skb->sk)) {
++                   || skb->dev == &loopback_dev || skb->sk)) {
+               IP_VS_DBG(12, "packet type=%d proto=%d daddr=%d.%d.%d.%d ignored\n",
+                         skb->pkt_type,
+                         ip_hdr(skb)->protocol,
+@@ -1074,10 +1062,6 @@
+ {
+       int r;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
--{
--      struct inet6_ifaddr *ifa;
+       if (ip_hdr(*pskb)->protocol != IPPROTO_ICMP)
+               return NF_ACCEPT;
+diff -Nurb linux-2.6.22-590/net/ipv4/ipvs/ip_vs_ctl.c linux-2.6.22-570/net/ipv4/ipvs/ip_vs_ctl.c
+--- linux-2.6.22-590/net/ipv4/ipvs/ip_vs_ctl.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ipvs/ip_vs_ctl.c 2007-07-08 19:32:17.000000000 -0400
+@@ -39,7 +39,6 @@
+ #include <net/ip.h>
+ #include <net/route.h>
+ #include <net/sock.h>
+-#include <net/net_namespace.h>
+ #include <asm/uaccess.h>
+@@ -680,7 +679,7 @@
+       conn_flags = udest->conn_flags | IP_VS_CONN_F_INACTIVE;
+       /* check if local node and update the flags */
+-      if (inet_addr_type(&init_net, udest->addr) == RTN_LOCAL) {
++      if (inet_addr_type(udest->addr) == RTN_LOCAL) {
+               conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK)
+                       | IP_VS_CONN_F_LOCALNODE;
+       }
+@@ -732,7 +731,7 @@
+       EnterFunction(2);
+-      atype = inet_addr_type(&init_net, udest->addr);
++      atype = inet_addr_type(udest->addr);
+       if (atype != RTN_LOCAL && atype != RTN_UNICAST)
+               return -EINVAL;
+@@ -1933,9 +1932,6 @@
+       struct ip_vs_service *svc;
+       struct ip_vs_dest_user *udest;
+-      if (sk->sk_net != &init_net)
+-              return -ENOPROTOOPT;
 -
--      ifa = if6_get_next(seq, v);
--      ++*pos;
--      return ifa;
--}
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+@@ -2200,9 +2196,6 @@
+       unsigned char arg[128];
+       int ret = 0;
+-      if (sk->sk_net != &init_net)
+-              return -ENOPROTOOPT;
 -
--static void if6_seq_stop(struct seq_file *seq, void *v)
--{
--      read_unlock_bh(&addrconf_hash_lock);
--}
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+@@ -2363,8 +2356,8 @@
+               return ret;
+       }
+-      proc_net_fops_create(&init_net, "ip_vs", 0, &ip_vs_info_fops);
+-      proc_net_fops_create(&init_net, "ip_vs_stats",0, &ip_vs_stats_fops);
++      proc_net_fops_create("ip_vs", 0, &ip_vs_info_fops);
++      proc_net_fops_create("ip_vs_stats",0, &ip_vs_stats_fops);
+       sysctl_header = register_sysctl_table(vs_root_table);
+@@ -2397,8 +2390,8 @@
+       cancel_work_sync(&defense_work.work);
+       ip_vs_kill_estimator(&ip_vs_stats);
+       unregister_sysctl_table(sysctl_header);
+-      proc_net_remove(&init_net, "ip_vs_stats");
+-      proc_net_remove(&init_net, "ip_vs");
++      proc_net_remove("ip_vs_stats");
++      proc_net_remove("ip_vs");
+       nf_unregister_sockopt(&ip_vs_sockopts);
+       LeaveFunction(2);
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/ipvs/ip_vs_lblcr.c linux-2.6.22-570/net/ipv4/ipvs/ip_vs_lblcr.c
+--- linux-2.6.22-590/net/ipv4/ipvs/ip_vs_lblcr.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ipvs/ip_vs_lblcr.c       2007-07-08 19:32:17.000000000 -0400
+@@ -843,7 +843,7 @@
+       INIT_LIST_HEAD(&ip_vs_lblcr_scheduler.n_list);
+       sysctl_header = register_sysctl_table(lblcr_root_table);
+ #ifdef CONFIG_IP_VS_LBLCR_DEBUG
+-      proc_net_create(&init_net, "ip_vs_lblcr", 0, ip_vs_lblcr_getinfo);
++      proc_net_create("ip_vs_lblcr", 0, ip_vs_lblcr_getinfo);
+ #endif
+       return register_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
+ }
+@@ -852,7 +852,7 @@
+ static void __exit ip_vs_lblcr_cleanup(void)
+ {
+ #ifdef CONFIG_IP_VS_LBLCR_DEBUG
+-      proc_net_remove(&init_net, "ip_vs_lblcr");
++      proc_net_remove("ip_vs_lblcr");
+ #endif
+       unregister_sysctl_table(sysctl_header);
+       unregister_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
+diff -Nurb linux-2.6.22-590/net/ipv4/ipvs/ip_vs_sync.c linux-2.6.22-570/net/ipv4/ipvs/ip_vs_sync.c
+--- linux-2.6.22-590/net/ipv4/ipvs/ip_vs_sync.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ipvs/ip_vs_sync.c        2007-07-08 19:32:17.000000000 -0400
+@@ -387,7 +387,7 @@
+       struct net_device *dev;
+       struct inet_sock *inet = inet_sk(sk);
+-      if ((dev = __dev_get_by_name(&init_net, ifname)) == NULL)
++      if ((dev = __dev_get_by_name(ifname)) == NULL)
+               return -ENODEV;
+       if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+@@ -412,7 +412,7 @@
+       int num;
+       if (sync_state == IP_VS_STATE_MASTER) {
+-              if ((dev = __dev_get_by_name(&init_net, ip_vs_master_mcast_ifn)) == NULL)
++              if ((dev = __dev_get_by_name(ip_vs_master_mcast_ifn)) == NULL)
+                       return -ENODEV;
+               num = (dev->mtu - sizeof(struct iphdr) -
+@@ -423,7 +423,7 @@
+               IP_VS_DBG(7, "setting the maximum length of sync sending "
+                         "message %d.\n", sync_send_mesg_maxlen);
+       } else if (sync_state == IP_VS_STATE_BACKUP) {
+-              if ((dev = __dev_get_by_name(&init_net, ip_vs_backup_mcast_ifn)) == NULL)
++              if ((dev = __dev_get_by_name(ip_vs_backup_mcast_ifn)) == NULL)
+                       return -ENODEV;
+               sync_recv_mesg_maxlen = dev->mtu -
+@@ -451,7 +451,7 @@
+       memset(&mreq, 0, sizeof(mreq));
+       memcpy(&mreq.imr_multiaddr, addr, sizeof(struct in_addr));
+-      if ((dev = __dev_get_by_name(&init_net, ifname)) == NULL)
++      if ((dev = __dev_get_by_name(ifname)) == NULL)
+               return -ENODEV;
+       if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+               return -EINVAL;
+@@ -472,7 +472,7 @@
+       __be32 addr;
+       struct sockaddr_in sin;
+-      if ((dev = __dev_get_by_name(&init_net, ifname)) == NULL)
++      if ((dev = __dev_get_by_name(ifname)) == NULL)
+               return -ENODEV;
+       addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
+diff -Nurb linux-2.6.22-590/net/ipv4/ipvs/ip_vs_xmit.c linux-2.6.22-570/net/ipv4/ipvs/ip_vs_xmit.c
+--- linux-2.6.22-590/net/ipv4/ipvs/ip_vs_xmit.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/ipvs/ip_vs_xmit.c        2007-07-08 19:32:17.000000000 -0400
+@@ -70,7 +70,6 @@
+               if (!(rt = (struct rtable *)
+                     __ip_vs_dst_check(dest, rtos, 0))) {
+                       struct flowi fl = {
+-                              .fl_net = &init_net,
+                               .oif = 0,
+                               .nl_u = {
+                                       .ip4_u = {
+@@ -94,7 +93,6 @@
+               spin_unlock(&dest->dst_lock);
+       } else {
+               struct flowi fl = {
+-                      .fl_net = &init_net,
+                       .oif = 0,
+                       .nl_u = {
+                               .ip4_u = {
+@@ -162,7 +160,6 @@
+       u8     tos = iph->tos;
+       int    mtu;
+       struct flowi fl = {
+-              .fl_net = &init_net,
+               .oif = 0,
+               .nl_u = {
+                       .ip4_u = {
+diff -Nurb linux-2.6.22-590/net/ipv4/multipath.c linux-2.6.22-570/net/ipv4/multipath.c
+--- linux-2.6.22-590/net/ipv4/multipath.c      1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/multipath.c      2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,55 @@
++/* multipath.c: IPV4 multipath algorithm support.
++ *
++ * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
++ * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
++ */
++
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/netdevice.h>
++#include <linux/spinlock.h>
++
++#include <net/ip_mp_alg.h>
++
++static DEFINE_SPINLOCK(alg_table_lock);
++struct ip_mp_alg_ops *ip_mp_alg_table[IP_MP_ALG_MAX + 1];
++
++int multipath_alg_register(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
++{
++      struct ip_mp_alg_ops **slot;
++      int err;
++
++      if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX ||
++          !ops->mp_alg_select_route)
++              return -EINVAL;
++
++      spin_lock(&alg_table_lock);
++      slot = &ip_mp_alg_table[n];
++      if (*slot != NULL) {
++              err = -EBUSY;
++      } else {
++              *slot = ops;
++              err = 0;
++      }
++      spin_unlock(&alg_table_lock);
++
++      return err;
++}
++EXPORT_SYMBOL(multipath_alg_register);
++
++void multipath_alg_unregister(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
++{
++      struct ip_mp_alg_ops **slot;
++
++      if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX)
++              return;
++
++      spin_lock(&alg_table_lock);
++      slot = &ip_mp_alg_table[n];
++      if (*slot == ops)
++              *slot = NULL;
++      spin_unlock(&alg_table_lock);
++
++      synchronize_net();
++}
++EXPORT_SYMBOL(multipath_alg_unregister);
+diff -Nurb linux-2.6.22-590/net/ipv4/multipath_drr.c linux-2.6.22-570/net/ipv4/multipath_drr.c
+--- linux-2.6.22-590/net/ipv4/multipath_drr.c  1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/multipath_drr.c  2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,249 @@
++/*
++ *              Device round robin policy for multipath.
++ *
++ *
++ * Version:   $Id: multipath_drr.c,v 1.1.2.1 2004/09/16 07:42:34 elueck Exp $
++ *
++ * Authors:   Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
++ *
++ *            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.
++ */
++
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/timer.h>
++#include <linux/mm.h>
++#include <linux/kernel.h>
++#include <linux/fcntl.h>
++#include <linux/stat.h>
++#include <linux/socket.h>
++#include <linux/in.h>
++#include <linux/inet.h>
++#include <linux/netdevice.h>
++#include <linux/inetdevice.h>
++#include <linux/igmp.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/module.h>
++#include <linux/mroute.h>
++#include <linux/init.h>
++#include <net/ip.h>
++#include <net/protocol.h>
++#include <linux/skbuff.h>
++#include <net/sock.h>
++#include <net/icmp.h>
++#include <net/udp.h>
++#include <net/raw.h>
++#include <linux/notifier.h>
++#include <linux/if_arp.h>
++#include <linux/netfilter_ipv4.h>
++#include <net/ipip.h>
++#include <net/checksum.h>
++#include <net/ip_mp_alg.h>
++
++struct multipath_device {
++      int             ifi; /* interface index of device */
++      atomic_t        usecount;
++      int             allocated;
++};
++
++#define MULTIPATH_MAX_DEVICECANDIDATES 10
++
++static struct multipath_device state[MULTIPATH_MAX_DEVICECANDIDATES];
++static DEFINE_SPINLOCK(state_lock);
++
++static int inline __multipath_findslot(void)
++{
++      int i;
++
++      for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) {
++              if (state[i].allocated == 0)
++                      return i;
++      }
++      return -1;
++}
++
++static int inline __multipath_finddev(int ifindex)
++{
++      int i;
++
++      for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) {
++              if (state[i].allocated != 0 &&
++                  state[i].ifi == ifindex)
++                      return i;
++      }
++      return -1;
++}
++
++static int drr_dev_event(struct notifier_block *this,
++                       unsigned long event, void *ptr)
++{
++      struct net_device *dev = ptr;
++      int devidx;
++
++      switch (event) {
++      case NETDEV_UNREGISTER:
++      case NETDEV_DOWN:
++              spin_lock_bh(&state_lock);
++
++              devidx = __multipath_finddev(dev->ifindex);
++              if (devidx != -1) {
++                      state[devidx].allocated = 0;
++                      state[devidx].ifi = 0;
++                      atomic_set(&state[devidx].usecount, 0);
++              }
++
++              spin_unlock_bh(&state_lock);
++              break;
++      }
++
++      return NOTIFY_DONE;
++}
++
++static struct notifier_block drr_dev_notifier = {
++      .notifier_call  = drr_dev_event,
++};
++
++
++static void drr_safe_inc(atomic_t *usecount)
++{
++      int n;
++
++      atomic_inc(usecount);
++
++      n = atomic_read(usecount);
++      if (n <= 0) {
++              int i;
++
++              spin_lock_bh(&state_lock);
++
++              for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++)
++                      atomic_set(&state[i].usecount, 0);
++
++              spin_unlock_bh(&state_lock);
++      }
++}
++
++static void drr_select_route(const struct flowi *flp,
++                           struct rtable *first, struct rtable **rp)
++{
++      struct rtable *nh, *result, *cur_min;
++      int min_usecount = -1;
++      int devidx = -1;
++      int cur_min_devidx = -1;
++
++      /* 1. make sure all alt. nexthops have the same GC related data */
++      /* 2. determine the new candidate to be returned */
++      result = NULL;
++      cur_min = NULL;
++      for (nh = rcu_dereference(first); nh;
++           nh = rcu_dereference(nh->u.dst.rt_next)) {
++              if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
++                  multipath_comparekeys(&nh->fl, flp)) {
++                      int nh_ifidx = nh->u.dst.dev->ifindex;
++
++                      nh->u.dst.lastuse = jiffies;
++                      nh->u.dst.__use++;
++                      if (result != NULL)
++                              continue;
++
++                      /* search for the output interface */
++
++                      /* this is not SMP safe, only add/remove are
++                       * SMP safe as wrong usecount updates have no big
++                       * impact
++                       */
++                      devidx = __multipath_finddev(nh_ifidx);
++                      if (devidx == -1) {
++                              /* add the interface to the array
++                               * SMP safe
++                               */
++                              spin_lock_bh(&state_lock);
++
++                              /* due to SMP: search again */
++                              devidx = __multipath_finddev(nh_ifidx);
++                              if (devidx == -1) {
++                                      /* add entry for device */
++                                      devidx = __multipath_findslot();
++                                      if (devidx == -1) {
++                                              /* unlikely but possible */
++                                              continue;
++                                      }
++
++                                      state[devidx].allocated = 1;
++                                      state[devidx].ifi = nh_ifidx;
++                                      atomic_set(&state[devidx].usecount, 0);
++                                      min_usecount = 0;
++                              }
++
++                              spin_unlock_bh(&state_lock);
++                      }
++
++                      if (min_usecount == 0) {
++                              /* if the device has not been used it is
++                               * the primary target
++                               */
++                              drr_safe_inc(&state[devidx].usecount);
++                              result = nh;
++                      } else {
++                              int count =
++                                      atomic_read(&state[devidx].usecount);
++
++                              if (min_usecount == -1 ||
++                                  count < min_usecount) {
++                                      cur_min = nh;
++                                      cur_min_devidx = devidx;
++                                      min_usecount = count;
++                              }
++                      }
++              }
++      }
++
++      if (!result) {
++              if (cur_min) {
++                      drr_safe_inc(&state[cur_min_devidx].usecount);
++                      result = cur_min;
++              } else {
++                      result = first;
++              }
++      }
++
++      *rp = result;
++}
++
++static struct ip_mp_alg_ops drr_ops = {
++      .mp_alg_select_route    =       drr_select_route,
++};
++
++static int __init drr_init(void)
++{
++      int err = register_netdevice_notifier(&drr_dev_notifier);
++
++      if (err)
++              return err;
++
++      err = multipath_alg_register(&drr_ops, IP_MP_ALG_DRR);
++      if (err)
++              goto fail;
++
++      return 0;
++
++fail:
++      unregister_netdevice_notifier(&drr_dev_notifier);
++      return err;
++}
++
++static void __exit drr_exit(void)
++{
++      unregister_netdevice_notifier(&drr_dev_notifier);
++      multipath_alg_unregister(&drr_ops, IP_MP_ALG_DRR);
++}
++
++module_init(drr_init);
++module_exit(drr_exit);
++MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/net/ipv4/multipath_random.c linux-2.6.22-570/net/ipv4/multipath_random.c
+--- linux-2.6.22-590/net/ipv4/multipath_random.c       1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/multipath_random.c       2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,114 @@
++/*
++ *              Random policy for multipath.
++ *
++ *
++ * Version:   $Id: multipath_random.c,v 1.1.2.3 2004/09/21 08:42:11 elueck Exp $
++ *
++ * Authors:   Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
++ *
++ *            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.
++ */
++
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/timer.h>
++#include <linux/mm.h>
++#include <linux/kernel.h>
++#include <linux/fcntl.h>
++#include <linux/stat.h>
++#include <linux/socket.h>
++#include <linux/in.h>
++#include <linux/inet.h>
++#include <linux/netdevice.h>
++#include <linux/inetdevice.h>
++#include <linux/igmp.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/module.h>
++#include <linux/mroute.h>
++#include <linux/init.h>
++#include <linux/random.h>
++#include <net/ip.h>
++#include <net/protocol.h>
++#include <linux/skbuff.h>
++#include <net/sock.h>
++#include <net/icmp.h>
++#include <net/udp.h>
++#include <net/raw.h>
++#include <linux/notifier.h>
++#include <linux/if_arp.h>
++#include <linux/netfilter_ipv4.h>
++#include <net/ipip.h>
++#include <net/checksum.h>
++#include <net/ip_mp_alg.h>
++
++#define MULTIPATH_MAX_CANDIDATES 40
++
++static void random_select_route(const struct flowi *flp,
++                              struct rtable *first,
++                              struct rtable **rp)
++{
++      struct rtable *rt;
++      struct rtable *decision;
++      unsigned char candidate_count = 0;
++
++      /* count all candidate */
++      for (rt = rcu_dereference(first); rt;
++           rt = rcu_dereference(rt->u.dst.rt_next)) {
++              if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
++                  multipath_comparekeys(&rt->fl, flp))
++                      ++candidate_count;
++      }
++
++      /* choose a random candidate */
++      decision = first;
++      if (candidate_count > 1) {
++              unsigned char i = 0;
++              unsigned char candidate_no = (unsigned char)
++                      (random32() % candidate_count);
++
++              /* find chosen candidate and adjust GC data for all candidates
++               * to ensure they stay in cache
++               */
++              for (rt = first; rt; rt = rt->u.dst.rt_next) {
++                      if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
++                          multipath_comparekeys(&rt->fl, flp)) {
++                              rt->u.dst.lastuse = jiffies;
++
++                              if (i == candidate_no)
++                                      decision = rt;
++
++                              if (i >= candidate_count)
++                                      break;
++
++                              i++;
++                      }
++              }
++      }
++
++      decision->u.dst.__use++;
++      *rp = decision;
++}
++
++static struct ip_mp_alg_ops random_ops = {
++      .mp_alg_select_route    =       random_select_route,
++};
++
++static int __init random_init(void)
++{
++      return multipath_alg_register(&random_ops, IP_MP_ALG_RANDOM);
++}
++
++static void __exit random_exit(void)
++{
++      multipath_alg_unregister(&random_ops, IP_MP_ALG_RANDOM);
++}
++
++module_init(random_init);
++module_exit(random_exit);
++MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/net/ipv4/multipath_rr.c linux-2.6.22-570/net/ipv4/multipath_rr.c
+--- linux-2.6.22-590/net/ipv4/multipath_rr.c   1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/multipath_rr.c   2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,95 @@
++/*
++ *              Round robin policy for multipath.
++ *
++ *
++ * Version:   $Id: multipath_rr.c,v 1.1.2.2 2004/09/16 07:42:34 elueck Exp $
++ *
++ * Authors:   Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
++ *
++ *            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.
++ */
++
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/timer.h>
++#include <linux/mm.h>
++#include <linux/kernel.h>
++#include <linux/fcntl.h>
++#include <linux/stat.h>
++#include <linux/socket.h>
++#include <linux/in.h>
++#include <linux/inet.h>
++#include <linux/netdevice.h>
++#include <linux/inetdevice.h>
++#include <linux/igmp.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/module.h>
++#include <linux/mroute.h>
++#include <linux/init.h>
++#include <net/ip.h>
++#include <net/protocol.h>
++#include <linux/skbuff.h>
++#include <net/sock.h>
++#include <net/icmp.h>
++#include <net/udp.h>
++#include <net/raw.h>
++#include <linux/notifier.h>
++#include <linux/if_arp.h>
++#include <linux/netfilter_ipv4.h>
++#include <net/ipip.h>
++#include <net/checksum.h>
++#include <net/ip_mp_alg.h>
++
++static void rr_select_route(const struct flowi *flp,
++                          struct rtable *first, struct rtable **rp)
++{
++      struct rtable *nh, *result, *min_use_cand = NULL;
++      int min_use = -1;
++
++      /* 1. make sure all alt. nexthops have the same GC related data
++       * 2. determine the new candidate to be returned
++       */
++      result = NULL;
++      for (nh = rcu_dereference(first); nh;
++           nh = rcu_dereference(nh->u.dst.rt_next)) {
++              if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
++                  multipath_comparekeys(&nh->fl, flp)) {
++                      nh->u.dst.lastuse = jiffies;
++
++                      if (min_use == -1 || nh->u.dst.__use < min_use) {
++                              min_use = nh->u.dst.__use;
++                              min_use_cand = nh;
++                      }
++              }
++      }
++      result = min_use_cand;
++      if (!result)
++              result = first;
++
++      result->u.dst.__use++;
++      *rp = result;
++}
++
++static struct ip_mp_alg_ops rr_ops = {
++      .mp_alg_select_route    =       rr_select_route,
++};
++
++static int __init rr_init(void)
++{
++      return multipath_alg_register(&rr_ops, IP_MP_ALG_RR);
++}
++
++static void __exit rr_exit(void)
++{
++      multipath_alg_unregister(&rr_ops, IP_MP_ALG_RR);
++}
++
++module_init(rr_init);
++module_exit(rr_exit);
++MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/net/ipv4/multipath_wrandom.c linux-2.6.22-570/net/ipv4/multipath_wrandom.c
+--- linux-2.6.22-590/net/ipv4/multipath_wrandom.c      1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/multipath_wrandom.c      2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,329 @@
++/*
++ *              Weighted random policy for multipath.
++ *
++ *
++ * Version:   $Id: multipath_wrandom.c,v 1.1.2.3 2004/09/22 07:51:40 elueck Exp $
++ *
++ * Authors:   Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
++ *
++ *            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.
++ */
++
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/timer.h>
++#include <linux/mm.h>
++#include <linux/kernel.h>
++#include <linux/fcntl.h>
++#include <linux/stat.h>
++#include <linux/socket.h>
++#include <linux/in.h>
++#include <linux/inet.h>
++#include <linux/netdevice.h>
++#include <linux/inetdevice.h>
++#include <linux/igmp.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/module.h>
++#include <linux/mroute.h>
++#include <linux/init.h>
++#include <linux/random.h>
++#include <net/ip.h>
++#include <net/protocol.h>
++#include <linux/skbuff.h>
++#include <net/sock.h>
++#include <net/icmp.h>
++#include <net/udp.h>
++#include <net/raw.h>
++#include <linux/notifier.h>
++#include <linux/if_arp.h>
++#include <linux/netfilter_ipv4.h>
++#include <net/ipip.h>
++#include <net/checksum.h>
++#include <net/ip_fib.h>
++#include <net/ip_mp_alg.h>
++
++#define MULTIPATH_STATE_SIZE 15
++
++struct multipath_candidate {
++      struct multipath_candidate      *next;
++      int                             power;
++      struct rtable                   *rt;
++};
++
++struct multipath_dest {
++      struct list_head        list;
++
++      const struct fib_nh     *nh_info;
++      __be32                  netmask;
++      __be32                  network;
++      unsigned char           prefixlen;
++
++      struct rcu_head         rcu;
++};
++
++struct multipath_bucket {
++      struct list_head        head;
++      spinlock_t              lock;
++};
++
++struct multipath_route {
++      struct list_head        list;
++
++      int                     oif;
++      __be32                  gw;
++      struct list_head        dests;
++
++      struct rcu_head         rcu;
++};
++
++/* state: primarily weight per route information */
++static struct multipath_bucket state[MULTIPATH_STATE_SIZE];
++
++static unsigned char __multipath_lookup_weight(const struct flowi *fl,
++                                             const struct rtable *rt)
++{
++      const int state_idx = rt->idev->dev->ifindex % MULTIPATH_STATE_SIZE;
++      struct multipath_route *r;
++      struct multipath_route *target_route = NULL;
++      struct multipath_dest *d;
++      int weight = 1;
++
++      /* lookup the weight information for a certain route */
++      rcu_read_lock();
++
++      /* find state entry for gateway or add one if necessary */
++      list_for_each_entry_rcu(r, &state[state_idx].head, list) {
++              if (r->gw == rt->rt_gateway &&
++                  r->oif == rt->idev->dev->ifindex) {
++                      target_route = r;
++                      break;
++              }
++      }
++
++      if (!target_route) {
++              /* this should not happen... but we are prepared */
++              printk( KERN_CRIT"%s: missing state for gateway: %u and " \
++                      "device %d\n", __FUNCTION__, rt->rt_gateway,
++                      rt->idev->dev->ifindex);
++              goto out;
++      }
++
++      /* find state entry for destination */
++      list_for_each_entry_rcu(d, &target_route->dests, list) {
++              __be32 targetnetwork = fl->fl4_dst &
++                      inet_make_mask(d->prefixlen);
++
++              if ((targetnetwork & d->netmask) == d->network) {
++                      weight = d->nh_info->nh_weight;
++                      goto out;
++              }
++      }
++
++out:
++      rcu_read_unlock();
++      return weight;
++}
++
++static void wrandom_init_state(void)
++{
++      int i;
++
++      for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
++              INIT_LIST_HEAD(&state[i].head);
++              spin_lock_init(&state[i].lock);
++      }
++}
++
++static void wrandom_select_route(const struct flowi *flp,
++                               struct rtable *first,
++                               struct rtable **rp)
++{
++      struct rtable *rt;
++      struct rtable *decision;
++      struct multipath_candidate *first_mpc = NULL;
++      struct multipath_candidate *mpc, *last_mpc = NULL;
++      int power = 0;
++      int last_power;
++      int selector;
++      const size_t size_mpc = sizeof(struct multipath_candidate);
++
++      /* collect all candidates and identify their weights */
++      for (rt = rcu_dereference(first); rt;
++           rt = rcu_dereference(rt->u.dst.rt_next)) {
++              if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
++                  multipath_comparekeys(&rt->fl, flp)) {
++                      struct multipath_candidate* mpc =
++                              (struct multipath_candidate*)
++                              kmalloc(size_mpc, GFP_ATOMIC);
++
++                      if (!mpc)
++                              return;
++
++                      power += __multipath_lookup_weight(flp, rt) * 10000;
++
++                      mpc->power = power;
++                      mpc->rt = rt;
++                      mpc->next = NULL;
++
++                      if (!first_mpc)
++                              first_mpc = mpc;
++                      else
++                              last_mpc->next = mpc;
++
++                      last_mpc = mpc;
++              }
++      }
++
++      /* choose a weighted random candidate */
++      decision = first;
++      selector = random32() % power;
++      last_power = 0;
++
++      /* select candidate, adjust GC data and cleanup local state */
++      decision = first;
++      last_mpc = NULL;
++      for (mpc = first_mpc; mpc; mpc = mpc->next) {
++              mpc->rt->u.dst.lastuse = jiffies;
++              if (last_power <= selector && selector < mpc->power)
++                      decision = mpc->rt;
++
++              last_power = mpc->power;
++              kfree(last_mpc);
++              last_mpc = mpc;
++      }
++
++      /* concurrent __multipath_flush may lead to !last_mpc */
++      kfree(last_mpc);
++
++      decision->u.dst.__use++;
++      *rp = decision;
++}
++
++static void wrandom_set_nhinfo(__be32 network,
++                             __be32 netmask,
++                             unsigned char prefixlen,
++                             const struct fib_nh *nh)
++{
++      const int state_idx = nh->nh_oif % MULTIPATH_STATE_SIZE;
++      struct multipath_route *r, *target_route = NULL;
++      struct multipath_dest *d, *target_dest = NULL;
++
++      /* store the weight information for a certain route */
++      spin_lock_bh(&state[state_idx].lock);
++
++      /* find state entry for gateway or add one if necessary */
++      list_for_each_entry_rcu(r, &state[state_idx].head, list) {
++              if (r->gw == nh->nh_gw && r->oif == nh->nh_oif) {
++                      target_route = r;
++                      break;
++              }
++      }
++
++      if (!target_route) {
++              const size_t size_rt = sizeof(struct multipath_route);
++              target_route = (struct multipath_route *)
++                      kmalloc(size_rt, GFP_ATOMIC);
++
++              target_route->gw = nh->nh_gw;
++              target_route->oif = nh->nh_oif;
++              memset(&target_route->rcu, 0, sizeof(struct rcu_head));
++              INIT_LIST_HEAD(&target_route->dests);
++
++              list_add_rcu(&target_route->list, &state[state_idx].head);
++      }
++
++      /* find state entry for destination or add one if necessary */
++      list_for_each_entry_rcu(d, &target_route->dests, list) {
++              if (d->nh_info == nh) {
++                      target_dest = d;
++                      break;
++              }
++      }
++
++      if (!target_dest) {
++              const size_t size_dst = sizeof(struct multipath_dest);
++              target_dest = (struct multipath_dest*)
++                      kmalloc(size_dst, GFP_ATOMIC);
++
++              target_dest->nh_info = nh;
++              target_dest->network = network;
++              target_dest->netmask = netmask;
++              target_dest->prefixlen = prefixlen;
++              memset(&target_dest->rcu, 0, sizeof(struct rcu_head));
++
++              list_add_rcu(&target_dest->list, &target_route->dests);
++      }
++      /* else: we already stored this info for another destination =>
++       * we are finished
++       */
++
++      spin_unlock_bh(&state[state_idx].lock);
++}
++
++static void __multipath_free(struct rcu_head *head)
++{
++      struct multipath_route *rt = container_of(head, struct multipath_route,
++                                                rcu);
++      kfree(rt);
++}
++
++static void __multipath_free_dst(struct rcu_head *head)
++{
++      struct multipath_dest *dst = container_of(head,
++                                                struct multipath_dest,
++                                                rcu);
++      kfree(dst);
++}
++
++static void wrandom_flush(void)
++{
++      int i;
++
++      /* defere delete to all entries */
++      for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
++              struct multipath_route *r;
++
++              spin_lock_bh(&state[i].lock);
++              list_for_each_entry_rcu(r, &state[i].head, list) {
++                      struct multipath_dest *d;
++                      list_for_each_entry_rcu(d, &r->dests, list) {
++                              list_del_rcu(&d->list);
++                              call_rcu(&d->rcu,
++                                       __multipath_free_dst);
++                      }
++                      list_del_rcu(&r->list);
++                      call_rcu(&r->rcu,
++                               __multipath_free);
++              }
++
++              spin_unlock_bh(&state[i].lock);
++      }
++}
++
++static struct ip_mp_alg_ops wrandom_ops = {
++      .mp_alg_select_route    =       wrandom_select_route,
++      .mp_alg_flush           =       wrandom_flush,
++      .mp_alg_set_nhinfo      =       wrandom_set_nhinfo,
++};
++
++static int __init wrandom_init(void)
++{
++      wrandom_init_state();
++
++      return multipath_alg_register(&wrandom_ops, IP_MP_ALG_WRANDOM);
++}
++
++static void __exit wrandom_exit(void)
++{
++      multipath_alg_unregister(&wrandom_ops, IP_MP_ALG_WRANDOM);
++}
++
++module_init(wrandom_init);
++module_exit(wrandom_exit);
++MODULE_LICENSE("GPL");
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/arp_tables.c linux-2.6.22-570/net/ipv4/netfilter/arp_tables.c
+--- linux-2.6.22-590/net/ipv4/netfilter/arp_tables.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/arp_tables.c   2007-07-08 19:32:17.000000000 -0400
+@@ -19,7 +19,6 @@
+ #include <linux/proc_fs.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+-#include <net/sock.h>
+ #include <asm/uaccess.h>
+ #include <linux/mutex.h>
+@@ -774,7 +773,7 @@
+       int ret;
+       struct arpt_table *t;
+-      t = xt_find_table_lock(&init_net, NF_ARP, entries->name);
++      t = xt_find_table_lock(NF_ARP, entries->name);
+       if (t && !IS_ERR(t)) {
+               struct xt_table_info *private = t->private;
+               duprintf("t->private->number = %u\n",
+@@ -844,7 +843,7 @@
+       duprintf("arp_tables: Translated table\n");
+-      t = try_then_request_module(xt_find_table_lock(&init_net, NF_ARP, tmp.name),
++      t = try_then_request_module(xt_find_table_lock(NF_ARP, tmp.name),
+                                   "arptable_%s", tmp.name);
+       if (!t || IS_ERR(t)) {
+               ret = t ? PTR_ERR(t) : -ENOENT;
+@@ -937,7 +936,7 @@
+               goto free;
+       }
+-      t = xt_find_table_lock(&init_net, NF_ARP, tmp.name);
++      t = xt_find_table_lock(NF_ARP, tmp.name);
+       if (!t || IS_ERR(t)) {
+               ret = t ? PTR_ERR(t) : -ENOENT;
+               goto free;
+@@ -972,9 +971,6 @@
+ {
+       int ret;
+-      if (sk->sk_net != &init_net)
+-              return -ENOPROTOOPT;
 -
--static int if6_seq_show(struct seq_file *seq, void *v)
--{
--      struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v;
--      seq_printf(seq,
--                 NIP6_SEQFMT " %02x %02x %02x %02x %8s\n",
--                 NIP6(ifp->addr),
--                 ifp->idev->dev->ifindex,
--                 ifp->prefix_len,
--                 ifp->scope,
--                 ifp->flags,
--                 ifp->idev->dev->name);
--      return 0;
--}
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+@@ -999,9 +995,6 @@
+ {
+       int ret;
+-      if (sk->sk_net != &init_net)
+-              return -ENOPROTOOPT;
 -
--static struct seq_operations if6_seq_ops = {
--      .start  = if6_seq_start,
--      .next   = if6_seq_next,
--      .show   = if6_seq_show,
--      .stop   = if6_seq_stop,
--};
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+@@ -1023,7 +1016,7 @@
+               }
+               name[ARPT_TABLE_MAXNAMELEN-1] = '\0';
+-              t = try_then_request_module(xt_find_table_lock(&init_net, NF_ARP, name),
++              t = try_then_request_module(xt_find_table_lock(NF_ARP, name),
+                                           "arptable_%s", name);
+               if (t && !IS_ERR(t)) {
+                       struct arpt_getinfo info;
+@@ -1123,7 +1116,7 @@
+               return ret;
+       }
+-      ret = xt_register_table(&init_net, table, &bootstrap, newinfo);
++      ret = xt_register_table(table, &bootstrap, newinfo);
+       if (ret != 0) {
+               xt_free_table_info(newinfo);
+               return ret;
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/arptable_filter.c linux-2.6.22-570/net/ipv4/netfilter/arptable_filter.c
+--- linux-2.6.22-590/net/ipv4/netfilter/arptable_filter.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/arptable_filter.c      2007-07-08 19:32:17.000000000 -0400
+@@ -61,10 +61,6 @@
+                             const struct net_device *out,
+                             int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--static int if6_seq_open(struct inode *inode, struct file *file)
--{
--      struct seq_file *seq;
--      int rc = -ENOMEM;
--      struct if6_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
+       return arpt_do_table(pskb, hook, in, out, &packet_filter);
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/ip_queue.c linux-2.6.22-570/net/ipv4/netfilter/ip_queue.c
+--- linux-2.6.22-590/net/ipv4/netfilter/ip_queue.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/ip_queue.c     2007-07-08 19:32:17.000000000 -0400
+@@ -26,7 +26,6 @@
+ #include <linux/mutex.h>
+ #include <net/sock.h>
+ #include <net/route.h>
+-#include <net/net_namespace.h>
+ #define IPQ_QMAX_DEFAULT 1024
+ #define IPQ_PROC_FS_NAME "ip_queue"
+@@ -557,9 +556,6 @@
+ {
+       struct net_device *dev = ptr;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--      if (!s)
--              goto out;
+       /* Drop any packets associated with the downed device */
+       if (event == NETDEV_DOWN)
+               ipq_dev_drop(dev->ifindex);
+@@ -579,7 +575,7 @@
+       if (event == NETLINK_URELEASE &&
+           n->protocol == NETLINK_FIREWALL && n->pid) {
+               write_lock_bh(&queue_lock);
+-              if ((n->net == &init_net) && (n->pid == peer_pid))
++              if (n->pid == peer_pid)
+                       __ipq_reset();
+               write_unlock_bh(&queue_lock);
+       }
+@@ -671,14 +667,14 @@
+       struct proc_dir_entry *proc;
+       netlink_register_notifier(&ipq_nl_notifier);
+-      ipqnl = netlink_kernel_create(&init_net, NETLINK_FIREWALL, 0,
+-                                    ipq_rcv_sk, NULL, THIS_MODULE);
++      ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
++                                    NULL, THIS_MODULE);
+       if (ipqnl == NULL) {
+               printk(KERN_ERR "ip_queue: failed to create netlink socket\n");
+               goto cleanup_netlink_notifier;
+       }
+-      proc = proc_net_create(&init_net, IPQ_PROC_FS_NAME, 0, ipq_get_info);
++      proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ipq_get_info);
+       if (proc)
+               proc->owner = THIS_MODULE;
+       else {
+@@ -699,7 +695,8 @@
+ cleanup_sysctl:
+       unregister_sysctl_table(ipq_sysctl_header);
+       unregister_netdevice_notifier(&ipq_dev_notifier);
+-      proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
++      proc_net_remove(IPQ_PROC_FS_NAME);
++
+ cleanup_ipqnl:
+       sock_release(ipqnl->sk_socket);
+       mutex_lock(&ipqnl_mutex);
+@@ -718,7 +715,7 @@
+       unregister_sysctl_table(ipq_sysctl_header);
+       unregister_netdevice_notifier(&ipq_dev_notifier);
+-      proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
++      proc_net_remove(IPQ_PROC_FS_NAME);
+       sock_release(ipqnl->sk_socket);
+       mutex_lock(&ipqnl_mutex);
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/ip_tables.c linux-2.6.22-570/net/ipv4/netfilter/ip_tables.c
+--- linux-2.6.22-590/net/ipv4/netfilter/ip_tables.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/ip_tables.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1039,7 +1039,7 @@
+ }
+ #endif
+-static int get_info(struct net *net, void __user *user, int *len, int compat)
++static int get_info(void __user *user, int *len, int compat)
+ {
+       char name[IPT_TABLE_MAXNAMELEN];
+       struct xt_table *t;
+@@ -1059,7 +1059,7 @@
+       if (compat)
+               xt_compat_lock(AF_INET);
+ #endif
+-      t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
++      t = try_then_request_module(xt_find_table_lock(AF_INET, name),
+                       "iptable_%s", name);
+       if (t && !IS_ERR(t)) {
+               struct ipt_getinfo info;
+@@ -1099,7 +1099,7 @@
+ }
+ static int
+-get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
++get_entries(struct ipt_get_entries __user *uptr, int *len)
+ {
+       int ret;
+       struct ipt_get_entries get;
+@@ -1119,7 +1119,7 @@
+               return -EINVAL;
+       }
+-      t = xt_find_table_lock(net, AF_INET, get.name);
++      t = xt_find_table_lock(AF_INET, get.name);
+       if (t && !IS_ERR(t)) {
+               struct xt_table_info *private = t->private;
+               duprintf("t->private->number = %u\n",
+@@ -1142,7 +1142,7 @@
+ }
+ static int
+-__do_replace(struct net *net, const char *name, unsigned int valid_hooks,
++__do_replace(const char *name, unsigned int valid_hooks,
+               struct xt_table_info *newinfo, unsigned int num_counters,
+               void __user *counters_ptr)
+ {
+@@ -1159,7 +1159,7 @@
+               goto out;
+       }
+-      t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
++      t = try_then_request_module(xt_find_table_lock(AF_INET, name),
+                                   "iptable_%s", name);
+       if (!t || IS_ERR(t)) {
+               ret = t ? PTR_ERR(t) : -ENOENT;
+@@ -1211,7 +1211,7 @@
+ }
+ static int
+-do_replace(struct net *net, void __user *user, unsigned int len)
++do_replace(void __user *user, unsigned int len)
+ {
+       int ret;
+       struct ipt_replace tmp;
+@@ -1252,7 +1252,7 @@
+       duprintf("ip_tables: Translated table\n");
+-      ret = __do_replace(net, tmp.name, tmp.valid_hooks,
++      ret = __do_replace(tmp.name, tmp.valid_hooks,
+                             newinfo, tmp.num_counters,
+                             tmp.counters);
+       if (ret)
+@@ -1289,7 +1289,7 @@
+ }
+ static int
+-do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
++do_add_counters(void __user *user, unsigned int len, int compat)
+ {
+       unsigned int i;
+       struct xt_counters_info tmp;
+@@ -1341,7 +1341,7 @@
+               goto free;
+       }
+-      t = xt_find_table_lock(net, AF_INET, name);
++      t = xt_find_table_lock(AF_INET, name);
+       if (!t || IS_ERR(t)) {
+               ret = t ? PTR_ERR(t) : -ENOENT;
+               goto free;
+@@ -1745,7 +1745,7 @@
+ }
+ static int
+-compat_do_replace(struct net *net, void __user *user, unsigned int len)
++compat_do_replace(void __user *user, unsigned int len)
+ {
+       int ret;
+       struct compat_ipt_replace tmp;
+@@ -1786,7 +1786,7 @@
+       duprintf("compat_do_replace: Translated table\n");
+-      ret = __do_replace(net, tmp.name, tmp.valid_hooks,
++      ret = __do_replace(tmp.name, tmp.valid_hooks,
+                             newinfo, tmp.num_counters,
+                             compat_ptr(tmp.counters));
+       if (ret)
+@@ -1811,11 +1811,11 @@
+       switch (cmd) {
+       case IPT_SO_SET_REPLACE:
+-              ret = compat_do_replace(sk->sk_net, user, len);
++              ret = compat_do_replace(user, len);
+               break;
+       case IPT_SO_SET_ADD_COUNTERS:
+-              ret = do_add_counters(sk->sk_net, user, len, 1);
++              ret = do_add_counters(user, len, 1);
+               break;
+       default:
+@@ -1904,7 +1904,7 @@
+ }
+ static int
+-compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr, int *len)
++compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
+ {
+       int ret;
+       struct compat_ipt_get_entries get;
+@@ -1928,7 +1928,7 @@
+       }
+       xt_compat_lock(AF_INET);
+-      t = xt_find_table_lock(net, AF_INET, get.name);
++      t = xt_find_table_lock(AF_INET, get.name);
+       if (t && !IS_ERR(t)) {
+               struct xt_table_info *private = t->private;
+               struct xt_table_info info;
+@@ -1966,10 +1966,10 @@
+       switch (cmd) {
+       case IPT_SO_GET_INFO:
+-              ret = get_info(sk->sk_net, user, len, 1);
++              ret = get_info(user, len, 1);
+               break;
+       case IPT_SO_GET_ENTRIES:
+-              ret = compat_get_entries(sk->sk_net, user, len);
++              ret = compat_get_entries(user, len);
+               break;
+       default:
+               ret = do_ipt_get_ctl(sk, cmd, user, len);
+@@ -1988,11 +1988,11 @@
+       switch (cmd) {
+       case IPT_SO_SET_REPLACE:
+-              ret = do_replace(sk->sk_net, user, len);
++              ret = do_replace(user, len);
+               break;
+       case IPT_SO_SET_ADD_COUNTERS:
+-              ret = do_add_counters(sk->sk_net, user, len, 0);
++              ret = do_add_counters(user, len, 0);
+               break;
+       default:
+@@ -2013,11 +2013,11 @@
+       switch (cmd) {
+       case IPT_SO_GET_INFO:
+-              ret = get_info(sk->sk_net, user, len, 0);
++              ret = get_info(user, len, 0);
+               break;
+       case IPT_SO_GET_ENTRIES:
+-              ret = get_entries(sk->sk_net, user, len);
++              ret = get_entries(user, len);
+               break;
+       case IPT_SO_GET_REVISION_MATCH:
+@@ -2054,7 +2054,7 @@
+       return ret;
+ }
+-int ipt_register_table(struct net *net, struct xt_table *table, const struct ipt_replace *repl)
++int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
+ {
+       int ret;
+       struct xt_table_info *newinfo;
+@@ -2082,7 +2082,7 @@
+               return ret;
+       }
+-      ret = xt_register_table(net, table, &bootstrap, newinfo);
++      ret = xt_register_table(table, &bootstrap, newinfo);
+       if (ret != 0) {
+               xt_free_table_info(newinfo);
+               return ret;
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/ipt_CLUSTERIP.c linux-2.6.22-570/net/ipv4/netfilter/ipt_CLUSTERIP.c
+--- linux-2.6.22-590/net/ipv4/netfilter/ipt_CLUSTERIP.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/ipt_CLUSTERIP.c        2007-07-08 19:32:17.000000000 -0400
+@@ -27,7 +27,6 @@
+ #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
+ #include <net/netfilter/nf_conntrack.h>
+ #include <net/checksum.h>
+-#include <net/net_namespace.h>
+ #define CLUSTERIP_VERSION "0.8"
+@@ -428,7 +427,7 @@
+                               return 0;
+                       }
+-                      dev = dev_get_by_name(&init_net, e->ip.iniface);
++                      dev = dev_get_by_name(e->ip.iniface);
+                       if (!dev) {
+                               printk(KERN_WARNING "CLUSTERIP: no such interface %s\n", e->ip.iniface);
+                               return 0;
+@@ -524,10 +523,6 @@
+       struct arp_payload *payload;
+       struct clusterip_config *c;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--      rc = seq_open(file, &if6_seq_ops);
--      if (rc)
--              goto out_kfree;
+       /* we don't care about non-ethernet and non-ipv4 ARP */
+       if (arp->ar_hrd != htons(ARPHRD_ETHER)
+           || arp->ar_pro != htons(ETH_P_IP)
+@@ -740,7 +735,7 @@
+               goto cleanup_target;
+ #ifdef CONFIG_PROC_FS
+-      clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", init_net.proc_net);
++      clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net);
+       if (!clusterip_procdir) {
+               printk(KERN_ERR "CLUSTERIP: Unable to proc dir entry\n");
+               ret = -ENOMEM;
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/ipt_MASQUERADE.c linux-2.6.22-570/net/ipv4/netfilter/ipt_MASQUERADE.c
+--- linux-2.6.22-590/net/ipv4/netfilter/ipt_MASQUERADE.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/ipt_MASQUERADE.c       2007-07-08 19:32:17.000000000 -0400
+@@ -131,9 +131,6 @@
+ {
+       struct net_device *dev = ptr;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--      seq = file->private_data;
--      seq->private = s;
--out:
--      return rc;
--out_kfree:
--      kfree(s);
--      goto out;
--}
+       if (event == NETDEV_DOWN) {
+               /* Device was downed.  Search entire table for
+                  conntracks which were associated with that device,
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/ipt_REJECT.c linux-2.6.22-570/net/ipv4/netfilter/ipt_REJECT.c
+--- linux-2.6.22-590/net/ipv4/netfilter/ipt_REJECT.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/ipt_REJECT.c   2007-07-08 19:32:17.000000000 -0400
+@@ -137,7 +137,7 @@
+          )
+               addr_type = RTN_LOCAL;
+-      if (ip_route_me_harder(&init_net, &nskb, addr_type))
++      if (ip_route_me_harder(&nskb, addr_type))
+               goto free_nskb;
+       nskb->ip_summed = CHECKSUM_NONE;
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/ipt_ULOG.c linux-2.6.22-570/net/ipv4/netfilter/ipt_ULOG.c
+--- linux-2.6.22-590/net/ipv4/netfilter/ipt_ULOG.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/ipt_ULOG.c     2007-07-08 19:32:17.000000000 -0400
+@@ -419,8 +419,7 @@
+       for (i = 0; i < ULOG_MAXNLGROUPS; i++)
+               setup_timer(&ulog_buffers[i].timer, ulog_timer, i);
+-      nflognl = netlink_kernel_create(&init_net,
+-                                      NETLINK_NFLOG, ULOG_MAXNLGROUPS, NULL,
++      nflognl = netlink_kernel_create(NETLINK_NFLOG, ULOG_MAXNLGROUPS, NULL,
+                                       NULL, THIS_MODULE);
+       if (!nflognl)
+               return -ENOMEM;
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.22-570/net/ipv4/netfilter/ipt_addrtype.c
+--- linux-2.6.22-590/net/ipv4/netfilter/ipt_addrtype.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/ipt_addrtype.c 2007-07-08 19:32:17.000000000 -0400
+@@ -24,7 +24,7 @@
+ static inline int match_type(__be32 addr, u_int16_t mask)
+ {
+-      return !!(mask & (1 << inet_addr_type(&init_net, addr)));
++      return !!(mask & (1 << inet_addr_type(addr)));
+ }
+ static int match(const struct sk_buff *skb,
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/ipt_recent.c linux-2.6.22-570/net/ipv4/netfilter/ipt_recent.c
+--- linux-2.6.22-590/net/ipv4/netfilter/ipt_recent.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/ipt_recent.c   2007-07-08 19:32:17.000000000 -0400
+@@ -24,7 +24,6 @@
+ #include <linux/bitops.h>
+ #include <linux/skbuff.h>
+ #include <linux/inet.h>
+-#include <net/net_namespace.h>
+ #include <linux/netfilter/x_tables.h>
+ #include <linux/netfilter_ipv4/ipt_recent.h>
+@@ -486,7 +485,7 @@
+ #ifdef CONFIG_PROC_FS
+       if (err)
+               return err;
+-      proc_dir = proc_mkdir("ipt_recent", init_net.proc_net);
++      proc_dir = proc_mkdir("ipt_recent", proc_net);
+       if (proc_dir == NULL) {
+               xt_unregister_match(&recent_match);
+               err = -ENOMEM;
+@@ -500,7 +499,7 @@
+       BUG_ON(!list_empty(&tables));
+       xt_unregister_match(&recent_match);
+ #ifdef CONFIG_PROC_FS
+-      remove_proc_entry("ipt_recent", init_net.proc_net);
++      remove_proc_entry("ipt_recent", proc_net);
+ #endif
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/iptable_filter.c linux-2.6.22-570/net/ipv4/netfilter/iptable_filter.c
+--- linux-2.6.22-590/net/ipv4/netfilter/iptable_filter.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/iptable_filter.c       2007-07-08 19:32:17.000000000 -0400
+@@ -26,7 +26,7 @@
+       struct ipt_replace repl;
+       struct ipt_standard entries[3];
+       struct ipt_error term;
+-} initial_table = {
++} initial_table __initdata = {
+       .repl = {
+               .name = "filter",
+               .valid_hooks = FILTER_VALID_HOOKS,
+@@ -51,7 +51,7 @@
+       .term = IPT_ERROR_INIT,                 /* ERROR */
+ };
+-static struct xt_table ip_packet_filter_dflt = {
++static struct xt_table packet_filter = {
+       .name           = "filter",
+       .valid_hooks    = FILTER_VALID_HOOKS,
+       .lock           = RW_LOCK_UNLOCKED,
+@@ -67,9 +67,7 @@
+        const struct net_device *out,
+        int (*okfn)(struct sk_buff *))
+ {
+-      struct net *net = (in?in:out)->nd_net;
 -
--static const struct file_operations if6_fops = {
--      .owner          = THIS_MODULE,
--      .open           = if6_seq_open,
--      .read           = seq_read,
--      .llseek         = seq_lseek,
--      .release        = seq_release_private,
--};
+-      return ipt_do_table(pskb, hook, in, out, net->ip_packet_filter);
++      return ipt_do_table(pskb, hook, in, out, &packet_filter);
+ }
+ static unsigned int
+@@ -79,8 +77,6 @@
+                  const struct net_device *out,
+                  int (*okfn)(struct sk_buff *))
+ {
+-      struct net *net = (in?in:out)->nd_net;
 -
--int __init if6_proc_init(void)
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr)
+           || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
+@@ -90,7 +86,7 @@
+               return NF_ACCEPT;
+       }
+-      return ipt_do_table(pskb, hook, in, out, net->ip_packet_filter);
++      return ipt_do_table(pskb, hook, in, out, &packet_filter);
+ }
+ static struct nf_hook_ops ipt_ops[] = {
+@@ -121,30 +117,6 @@
+ static int forward = NF_ACCEPT;
+ module_param(forward, bool, 0000);
+-static int iptable_filter_net_init(struct net *net)
 -{
--      if (!proc_net_fops_create("if_inet6", S_IRUGO, &if6_fops))
+-      /* Allocate the table */
+-      net->ip_packet_filter = kmemdup(&ip_packet_filter_dflt,
+-                                      sizeof(*net->ip_packet_filter),
+-                                      GFP_KERNEL);
+-      if (!net->ip_packet_filter)
 -              return -ENOMEM;
--      return 0;
--}
 -
--void if6_proc_exit(void)
--{
--      proc_net_remove("if_inet6");
+-      /* Register table */
+-      return ipt_register_table(net, net->ip_packet_filter, &initial_table.repl);
 -}
--#endif        /* CONFIG_PROC_FS */
 -
--#ifdef CONFIG_IPV6_MIP6
--/* Check if address is a home address configured on any interface. */
--int ipv6_chk_home_addr(struct in6_addr *addr)
+-static void iptable_filter_net_exit(struct net *net)
 -{
--      int ret = 0;
--      struct inet6_ifaddr * ifp;
--      u8 hash = ipv6_addr_hash(addr);
--      read_lock_bh(&addrconf_hash_lock);
--      for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) {
--              if (ipv6_addr_cmp(&ifp->addr, addr) == 0 &&
--                  (ifp->flags & IFA_F_HOMEADDRESS)) {
--                      ret = 1;
--                      break;
--              }
--      }
--      read_unlock_bh(&addrconf_hash_lock);
--      return ret;
+-      ipt_unregister_table(net->ip_packet_filter);
+-      kfree(net->ip_packet_filter);
 -}
--#endif
 -
--/*
-- *    Periodic address status verification
-- */
--
--static void addrconf_verify(unsigned long foo)
--{
--      struct inet6_ifaddr *ifp;
--      unsigned long now, next;
--      int i;
--
--      spin_lock_bh(&addrconf_verify_lock);
--      now = jiffies;
--      next = now + ADDR_CHECK_FREQUENCY;
+-static struct pernet_operations iptable_filter_net_ops = {
+-      .init = iptable_filter_net_init,
+-      .exit = iptable_filter_net_exit,
+-};
 -
--      del_timer(&addr_chk_timer);
+ static int __init iptable_filter_init(void)
+ {
+       int ret;
+@@ -158,7 +130,7 @@
+       initial_table.entries[1].target.verdict = -forward - 1;
+       /* Register table */
+-      ret = register_pernet_subsys(&iptable_filter_net_ops);
++      ret = ipt_register_table(&packet_filter, &initial_table.repl);
+       if (ret < 0)
+               return ret;
+@@ -170,14 +142,14 @@
+       return ret;
+  cleanup_table:
+-      unregister_pernet_subsys(&iptable_filter_net_ops);
++      ipt_unregister_table(&packet_filter);
+       return ret;
+ }
+ static void __exit iptable_filter_fini(void)
+ {
+       nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
+-      unregister_pernet_subsys(&iptable_filter_net_ops);
++      ipt_unregister_table(&packet_filter);
+ }
+ module_init(iptable_filter_init);
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/iptable_mangle.c linux-2.6.22-570/net/ipv4/netfilter/iptable_mangle.c
+--- linux-2.6.22-590/net/ipv4/netfilter/iptable_mangle.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/iptable_mangle.c       2007-07-08 19:32:17.000000000 -0400
+@@ -80,10 +80,6 @@
+        const struct net_device *out,
+        int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--      for (i=0; i < IN6_ADDR_HSIZE; i++) {
+       return ipt_do_table(pskb, hook, in, out, &packet_mangler);
+ }
+@@ -100,10 +96,6 @@
+       __be32 saddr, daddr;
+       u_int32_t mark;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--restart:
--              read_lock(&addrconf_hash_lock);
--              for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) {
--                      unsigned long age;
--#ifdef CONFIG_IPV6_PRIVACY
--                      unsigned long regen_advance;
--#endif
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr)
+           || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
+@@ -129,7 +121,7 @@
+                   iph->daddr != daddr ||
+                   (*pskb)->mark != mark ||
+                   iph->tos != tos)
+-                      if (ip_route_me_harder(&init_net, pskb, RTN_UNSPEC))
++                      if (ip_route_me_harder(pskb, RTN_UNSPEC))
+                               ret = NF_DROP;
+       }
+@@ -179,7 +171,7 @@
+       int ret;
+       /* Register table */
+-      ret = ipt_register_table(&init_net, &packet_mangler, &initial_table.repl);
++      ret = ipt_register_table(&packet_mangler, &initial_table.repl);
+       if (ret < 0)
+               return ret;
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/iptable_raw.c linux-2.6.22-570/net/ipv4/netfilter/iptable_raw.c
+--- linux-2.6.22-590/net/ipv4/netfilter/iptable_raw.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/iptable_raw.c  2007-07-08 19:32:17.000000000 -0400
+@@ -52,10 +52,6 @@
+        const struct net_device *out,
+        int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--                      if (ifp->flags & IFA_F_PERMANENT)
--                              continue;
+       return ipt_do_table(pskb, hook, in, out, &packet_raw);
+ }
+@@ -100,7 +96,7 @@
+       int ret;
+       /* Register table */
+-      ret = ipt_register_table(&init_net, &packet_raw, &initial_table.repl);
++      ret = ipt_register_table(&packet_raw, &initial_table.repl);
+       if (ret < 0)
+               return ret;
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c linux-2.6.22-570/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+--- linux-2.6.22-590/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c    2007-07-08 19:32:17.000000000 -0400
+@@ -120,10 +120,6 @@
+                                const struct net_device *out,
+                                int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--                      spin_lock(&ifp->lock);
--                      age = (now - ifp->tstamp) / HZ;
+       /* We've seen it coming out the other side: confirm it */
+       return nf_conntrack_confirm(pskb);
+ }
+@@ -139,10 +135,6 @@
+       struct nf_conn_help *help;
+       struct nf_conntrack_helper *helper;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--#ifdef CONFIG_IPV6_PRIVACY
--                      regen_advance = ifp->idev->cnf.regen_max_retry *
--                                      ifp->idev->cnf.dad_transmits *
--                                      ifp->idev->nd_parms->retrans_time / HZ;
--#endif
+       /* This is where we call the helper: as the packet goes out. */
+       ct = nf_ct_get(*pskb, &ctinfo);
+       if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
+@@ -165,10 +157,6 @@
+                                         const struct net_device *out,
+                                         int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--                      if (ifp->valid_lft != INFINITY_LIFE_TIME &&
--                          age >= ifp->valid_lft) {
--                              spin_unlock(&ifp->lock);
--                              in6_ifa_hold(ifp);
--                              read_unlock(&addrconf_hash_lock);
--                              ipv6_del_addr(ifp);
--                              goto restart;
--                      } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) {
--                              spin_unlock(&ifp->lock);
--                              continue;
--                      } else if (age >= ifp->prefered_lft) {
--                              /* jiffies - ifp->tsamp > age >= ifp->prefered_lft */
--                              int deprecate = 0;
+       /* Previously seen (loopback)?  Ignore.  Do this before
+          fragment check. */
+       if ((*pskb)->nfct)
+@@ -192,10 +180,6 @@
+                                     const struct net_device *out,
+                                     int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--                              if (!(ifp->flags&IFA_F_DEPRECATED)) {
--                                      deprecate = 1;
--                                      ifp->flags |= IFA_F_DEPRECATED;
--                              }
+       return nf_conntrack_in(PF_INET, hooknum, pskb);
+ }
+@@ -205,10 +189,6 @@
+                                        const struct net_device *out,
+                                        int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--                              if (time_before(ifp->tstamp + ifp->valid_lft * HZ, next))
--                                      next = ifp->tstamp + ifp->valid_lft * HZ;
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr)
+           || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
+@@ -345,9 +325,6 @@
+       struct nf_conntrack_tuple_hash *h;
+       struct nf_conntrack_tuple tuple;
+-      if (sk->sk_net != &init_net)
+-              return -ENOPROTOOPT;
 -
--                              spin_unlock(&ifp->lock);
+       NF_CT_TUPLE_U_BLANK(&tuple);
+       tuple.src.u3.ip = inet->rcv_saddr;
+       tuple.src.u.tcp.port = inet->sport;
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c linux-2.6.22-570/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+--- linux-2.6.22-590/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c     2007-07-08 19:32:17.000000000 -0400
+@@ -11,7 +11,6 @@
+ #include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
+ #include <linux/percpu.h>
+-#include <net/net_namespace.h>
+ #include <linux/netfilter.h>
+ #include <net/netfilter/nf_conntrack_core.h>
+@@ -379,16 +378,16 @@
+ {
+       struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+-      proc = proc_net_fops_create(&init_net, "ip_conntrack", 0440, &ct_file_ops);
++      proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
+       if (!proc)
+               goto err1;
+-      proc_exp = proc_net_fops_create(&init_net, "ip_conntrack_expect", 0440,
++      proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
+                                       &ip_exp_file_ops);
+       if (!proc_exp)
+               goto err2;
+-      proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, init_net.proc_net_stat);
++      proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
+       if (!proc_stat)
+               goto err3;
+@@ -398,16 +397,16 @@
+       return 0;
+ err3:
+-      proc_net_remove(&init_net, "ip_conntrack_expect");
++      proc_net_remove("ip_conntrack_expect");
+ err2:
+-      proc_net_remove(&init_net, "ip_conntrack");
++      proc_net_remove("ip_conntrack");
+ err1:
+       return -ENOMEM;
+ }
+ void __exit nf_conntrack_ipv4_compat_fini(void)
+ {
+-      remove_proc_entry("ip_conntrack", init_net.proc_net_stat);
+-      proc_net_remove(&init_net, "ip_conntrack_expect");
+-      proc_net_remove(&init_net, "ip_conntrack");
++      remove_proc_entry("ip_conntrack", proc_net_stat);
++      proc_net_remove("ip_conntrack_expect");
++      proc_net_remove("ip_conntrack");
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/nf_nat_helper.c linux-2.6.22-570/net/ipv4/netfilter/nf_nat_helper.c
+--- linux-2.6.22-590/net/ipv4/netfilter/nf_nat_helper.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/nf_nat_helper.c        2007-07-08 19:32:17.000000000 -0400
+@@ -178,7 +178,7 @@
+       datalen = (*pskb)->len - iph->ihl*4;
+       if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
+               if (!(rt->rt_flags & RTCF_LOCAL) &&
+-                  (*pskb)->dev->features & NETIF_F_V4_CSUM) {
++                  (*pskb)->dev->features & NETIF_F_ALL_CSUM) {
+                       (*pskb)->ip_summed = CHECKSUM_PARTIAL;
+                       (*pskb)->csum_start = skb_headroom(*pskb) +
+                                             skb_network_offset(*pskb) +
+@@ -265,7 +265,7 @@
+       if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
+               if (!(rt->rt_flags & RTCF_LOCAL) &&
+-                  (*pskb)->dev->features & NETIF_F_V4_CSUM) {
++                  (*pskb)->dev->features & NETIF_F_ALL_CSUM) {
+                       (*pskb)->ip_summed = CHECKSUM_PARTIAL;
+                       (*pskb)->csum_start = skb_headroom(*pskb) +
+                                             skb_network_offset(*pskb) +
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/nf_nat_rule.c linux-2.6.22-570/net/ipv4/netfilter/nf_nat_rule.c
+--- linux-2.6.22-590/net/ipv4/netfilter/nf_nat_rule.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/nf_nat_rule.c  2007-07-08 19:32:17.000000000 -0400
+@@ -98,10 +98,7 @@
+ static void warn_if_extra_mangle(__be32 dstip, __be32 srcip)
+ {
+       static int warned = 0;
+-      struct flowi fl = {
+-              .fl_net = &init_net,
+-              .nl_u = { .ip4_u = { .daddr = dstip } }
+-      };
++      struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } };
+       struct rtable *rt;
+       if (ip_route_output_key(&rt, &fl) != 0)
+@@ -255,7 +252,7 @@
+ {
+       int ret;
+-      ret = ipt_register_table(&init_net, &nat_table, &nat_initial_table.repl);
++      ret = ipt_register_table(&nat_table, &nat_initial_table.repl);
+       if (ret != 0)
+               return ret;
+       ret = xt_register_target(&ipt_snat_reg);
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter/nf_nat_standalone.c linux-2.6.22-570/net/ipv4/netfilter/nf_nat_standalone.c
+--- linux-2.6.22-590/net/ipv4/netfilter/nf_nat_standalone.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter/nf_nat_standalone.c    2007-07-08 19:32:17.000000000 -0400
+@@ -83,10 +83,6 @@
+       /* maniptype == SRC for postrouting. */
+       enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--                              if (deprecate) {
--                                      in6_ifa_hold(ifp);
--                                      read_unlock(&addrconf_hash_lock);
+       /* We never see fragments: conntrack defrags on pre-routing
+          and local-out, and nf_nat_out protects post-routing. */
+       NF_CT_ASSERT(!(ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)));
+@@ -176,10 +172,6 @@
+       unsigned int ret;
+       __be32 daddr = ip_hdr(*pskb)->daddr;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--                                      ipv6_ifa_notify(0, ifp);
--                                      in6_ifa_put(ifp);
--                                      goto restart;
--                              }
--#ifdef CONFIG_IPV6_PRIVACY
--                      } else if ((ifp->flags&IFA_F_TEMPORARY) &&
--                                 !(ifp->flags&IFA_F_TENTATIVE)) {
--                              if (age >= ifp->prefered_lft - regen_advance) {
--                                      struct inet6_ifaddr *ifpub = ifp->ifpub;
--                                      if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
--                                              next = ifp->tstamp + ifp->prefered_lft * HZ;
--                                      if (!ifp->regen_count && ifpub) {
--                                              ifp->regen_count++;
--                                              in6_ifa_hold(ifp);
--                                              in6_ifa_hold(ifpub);
--                                              spin_unlock(&ifp->lock);
--                                              read_unlock(&addrconf_hash_lock);
--                                              spin_lock(&ifpub->lock);
--                                              ifpub->regen_count = 0;
--                                              spin_unlock(&ifpub->lock);
--                                              ipv6_create_tempaddr(ifpub, ifp);
--                                              in6_ifa_put(ifpub);
--                                              in6_ifa_put(ifp);
--                                              goto restart;
--                                      }
--                              } else if (time_before(ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ, next))
--                                      next = ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ;
--                              spin_unlock(&ifp->lock);
--#endif
--                      } else {
--                              /* ifp->prefered_lft <= ifp->valid_lft */
--                              if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
--                                      next = ifp->tstamp + ifp->prefered_lft * HZ;
--                              spin_unlock(&ifp->lock);
--                      }
--              }
--              read_unlock(&addrconf_hash_lock);
--      }
+       ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
+       if (ret != NF_DROP && ret != NF_STOLEN &&
+           daddr != ip_hdr(*pskb)->daddr) {
+@@ -202,10 +194,6 @@
+ #endif
+       unsigned int ret;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--      addr_chk_timer.expires = time_before(next, jiffies + HZ) ? jiffies + HZ : next;
--      add_timer(&addr_chk_timer);
--      spin_unlock_bh(&addrconf_verify_lock);
--}
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr) ||
+           ip_hdrlen(*pskb) < sizeof(struct iphdr))
+@@ -239,10 +227,6 @@
+       enum ip_conntrack_info ctinfo;
+       unsigned int ret;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local)
--{
--      struct in6_addr *pfx = NULL;
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr) ||
+           ip_hdrlen(*pskb) < sizeof(struct iphdr))
+@@ -255,7 +239,7 @@
+               if (ct->tuplehash[dir].tuple.dst.u3.ip !=
+                   ct->tuplehash[!dir].tuple.src.u3.ip) {
+-                      if (ip_route_me_harder(&init_net, pskb, RTN_UNSPEC))
++                      if (ip_route_me_harder(pskb, RTN_UNSPEC))
+                               ret = NF_DROP;
+               }
+ #ifdef CONFIG_XFRM
+@@ -278,10 +262,6 @@
+       struct nf_conn *ct;
+       enum ip_conntrack_info ctinfo;
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--      if (addr)
--              pfx = nla_data(addr);
+       ct = nf_ct_get(*pskb, &ctinfo);
+       if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
+               DEBUGP("nf_nat_standalone: adjusting sequence number\n");
+diff -Nurb linux-2.6.22-590/net/ipv4/netfilter.c linux-2.6.22-570/net/ipv4/netfilter.c
+--- linux-2.6.22-590/net/ipv4/netfilter.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/netfilter.c      2007-07-08 19:32:17.000000000 -0400
+@@ -8,7 +8,7 @@
+ #include <net/ip.h>
+ /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
+-int ip_route_me_harder(struct net *net, struct sk_buff **pskb, unsigned addr_type)
++int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
+ {
+       const struct iphdr *iph = ip_hdr(*pskb);
+       struct rtable *rt;
+@@ -17,8 +17,7 @@
+       unsigned int hh_len;
+       unsigned int type;
+-      fl.fl_net = net;
+-      type = inet_addr_type(net, iph->saddr);
++      type = inet_addr_type(iph->saddr);
+       if (addr_type == RTN_UNSPEC)
+               addr_type = type;
+@@ -156,13 +155,12 @@
+       const struct ip_rt_info *rt_info = nf_info_reroute(info);
+       if (info->hook == NF_IP_LOCAL_OUT) {
+-              struct net *net = (info->indev?info->indev:info->outdev)->nd_net;
+               const struct iphdr *iph = ip_hdr(*pskb);
+               if (!(iph->tos == rt_info->tos
+                     && iph->daddr == rt_info->daddr
+                     && iph->saddr == rt_info->saddr))
+-                      return ip_route_me_harder(net, pskb, RTN_UNSPEC);
++                      return ip_route_me_harder(pskb, RTN_UNSPEC);
+       }
+       return 0;
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/proc.c linux-2.6.22-570/net/ipv4/proc.c
+--- linux-2.6.22-590/net/ipv4/proc.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/proc.c   2007-07-08 19:32:17.000000000 -0400
+@@ -44,7 +44,6 @@
+ #include <linux/seq_file.h>
+ #include <net/sock.h>
+ #include <net/raw.h>
+-#include <net/net_namespace.h>
+ static int fold_prot_inuse(struct proto *proto)
+ {
+@@ -70,9 +69,8 @@
+       seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot));
+       seq_printf(seq, "UDPLITE: inuse %d\n", fold_prot_inuse(&udplite_prot));
+       seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot));
+-      seq_printf(seq,  "FRAG: inuse %d memory %d\n", 
+-                 init_net.ip_frag_nqueues,
+-                 atomic_read(&init_net.ip_frag_mem));
++      seq_printf(seq,  "FRAG: inuse %d memory %d\n", ip_frag_nqueues,
++                 atomic_read(&ip_frag_mem));
+       return 0;
+ }
+@@ -262,8 +260,7 @@
+               seq_printf(seq, " %s", snmp4_ipstats_list[i].name);
+       seq_printf(seq, "\nIp: %d %d",
+-                 IPV4_DEVCONF_ALL(&init_net, FORWARDING) ? 1 : 2,
+-                 init_net.sysctl_ip_default_ttl);
++                 IPV4_DEVCONF_ALL(FORWARDING) ? 1 : 2, sysctl_ip_default_ttl);
+       for (i = 0; snmp4_ipstats_list[i].name != NULL; i++)
+               seq_printf(seq, " %lu",
+@@ -383,20 +380,20 @@
+ {
+       int rc = 0;
+-      if (!proc_net_fops_create(&init_net, "netstat", S_IRUGO, &netstat_seq_fops))
++      if (!proc_net_fops_create("netstat", S_IRUGO, &netstat_seq_fops))
+               goto out_netstat;
+-      if (!proc_net_fops_create(&init_net, "snmp", S_IRUGO, &snmp_seq_fops))
++      if (!proc_net_fops_create("snmp", S_IRUGO, &snmp_seq_fops))
+               goto out_snmp;
+-      if (!proc_net_fops_create(&init_net, "sockstat", S_IRUGO, &sockstat_seq_fops))
++      if (!proc_net_fops_create("sockstat", S_IRUGO, &sockstat_seq_fops))
+               goto out_sockstat;
+ out:
+       return rc;
+ out_sockstat:
+-      proc_net_remove(&init_net, "snmp");
++      proc_net_remove("snmp");
+ out_snmp:
+-      proc_net_remove(&init_net, "netstat");
++      proc_net_remove("netstat");
+ out_netstat:
+       rc = -ENOMEM;
+       goto out;
+diff -Nurb linux-2.6.22-590/net/ipv4/raw.c linux-2.6.22-570/net/ipv4/raw.c
+--- linux-2.6.22-590/net/ipv4/raw.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/raw.c    2008-01-23 19:16:10.000000000 -0500
+@@ -73,7 +73,6 @@
+ #include <net/inet_common.h>
+ #include <net/checksum.h>
+ #include <net/xfrm.h>
+-#include <net/net_namespace.h>
+ #include <linux/rtnetlink.h>
+ #include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
+@@ -102,7 +101,7 @@
+       write_unlock_bh(&raw_v4_lock);
+ }
+-struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, unsigned short num,
++struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
+                            __be32 raddr, __be32 laddr,
+                            int dif, int tag)
+ {
+@@ -111,9 +110,6 @@
+       sk_for_each_from(sk, node) {
+               struct inet_sock *inet = inet_sk(sk);
+-              if (sk->sk_net != net)
+-                      continue;
 -
--      if (local) {
--              if (pfx && nla_memcmp(local, pfx, sizeof(*pfx)))
--                      pfx = NULL;
--              else
--                      pfx = nla_data(local);
+               if (inet->num == num                                    &&
+                   !(inet->daddr && inet->daddr != raddr)              &&
+                   (!sk->sk_nx_info || tag == 1 || sk->sk_nid == tag)  &&
+@@ -156,7 +152,6 @@
+  */
+ int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
+ {
+-      struct net *net = skb->dev->nd_net;
+       struct sock *sk;
+       struct hlist_head *head;
+       int delivered = 0;
+@@ -165,7 +160,7 @@
+       head = &raw_v4_htable[hash];
+       if (hlist_empty(head))
+               goto out;
+-      sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol,
++      sk = __raw_v4_lookup(__sk_head(head), iph->protocol,
+                            iph->saddr, iph->daddr,
+                            skb->dev->ifindex, skb->skb_tag);
+@@ -178,7 +173,7 @@
+                       if (clone)
+                               raw_rcv(sk, clone);
+               }
+-              sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol,
++              sk = __raw_v4_lookup(sk_next(sk), iph->protocol,
+                                    iph->saddr, iph->daddr,
+                                    skb->dev->ifindex, skb->skb_tag);
+       }
+@@ -489,8 +484,7 @@
+       }
+       {
+-              struct flowi fl = { .fl_net = sk->sk_net,
+-                                  .oif = ipc.oif,
++              struct flowi fl = { .oif = ipc.oif,
+                                   .nl_u = { .ip4_u =
+                                             { .daddr = daddr,
+                                               .saddr = saddr,
+@@ -580,7 +574,7 @@
+       if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in))
+               goto out;
+       v4_map_sock_addr(inet, addr, &nsa);
+-      chk_addr_ret = inet_addr_type(sk->sk_net, nsa.saddr);
++      chk_addr_ret = inet_addr_type(nsa.saddr);
+       ret = -EADDRNOTAVAIL;
+       if (nsa.saddr && chk_addr_ret != RTN_LOCAL &&
+           chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
+@@ -804,7 +798,6 @@
+ #ifdef CONFIG_PROC_FS
+ struct raw_iter_state {
+-      struct net *net;
+       int bucket;
+ };
+@@ -818,14 +811,11 @@
+       for (state->bucket = 0; state->bucket < RAWV4_HTABLE_SIZE; ++state->bucket) {
+               struct hlist_node *node;
+-              sk_for_each(sk, node, &raw_v4_htable[state->bucket]) {
+-                      if (sk->sk_net != state->net)
+-                              continue;
++              sk_for_each(sk, node, &raw_v4_htable[state->bucket])
+                       if (sk->sk_family == PF_INET &&
+                               nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT))
+                               goto found;
+       }
 -      }
--
--      return pfx;
--}
--
--static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
--      [IFA_ADDRESS]           = { .len = sizeof(struct in6_addr) },
--      [IFA_LOCAL]             = { .len = sizeof(struct in6_addr) },
--      [IFA_CACHEINFO]         = { .len = sizeof(struct ifa_cacheinfo) },
--};
--
--static int
--inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
--{
--      struct ifaddrmsg *ifm;
--      struct nlattr *tb[IFA_MAX+1];
--      struct in6_addr *pfx;
--      int err;
--
--      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
--      if (err < 0)
--              return err;
--
--      ifm = nlmsg_data(nlh);
--      pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
--      if (pfx == NULL)
--              return -EINVAL;
--
--      return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
--}
--
--static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
--                           u32 prefered_lft, u32 valid_lft)
+       sk = NULL;
+ found:
+       return sk;
+@@ -840,7 +830,7 @@
+ try_again:
+               ;
+       } while (sk && (sk->sk_family != PF_INET ||
+-              !nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT) || (sk->sk_net != state->net)));
++              !nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT)));
+       if (!sk && ++state->bucket < RAWV4_HTABLE_SIZE) {
+               sk = sk_head(&raw_v4_htable[state->bucket]);
+@@ -943,7 +933,6 @@
+       seq = file->private_data;
+       seq->private = s;
+       memset(s, 0, sizeof(*s));
+-      s->net = get_net(PROC_NET(inode));
+ out:
+       return rc;
+ out_kfree:
+@@ -951,46 +940,23 @@
+       goto out;
+ }
+-static int raw_seq_release(struct inode *inode, struct file *file)
 -{
--      u32 flags = RTF_EXPIRES;
--
--      if (!valid_lft || (prefered_lft > valid_lft))
--              return -EINVAL;
--
--      if (valid_lft == INFINITY_LIFE_TIME) {
--              ifa_flags |= IFA_F_PERMANENT;
--              flags = 0;
--      } else if (valid_lft >= 0x7FFFFFFF/HZ)
--              valid_lft = 0x7FFFFFFF/HZ;
--
--      if (prefered_lft == 0)
--              ifa_flags |= IFA_F_DEPRECATED;
--      else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
--               (prefered_lft != INFINITY_LIFE_TIME))
--              prefered_lft = 0x7FFFFFFF/HZ;
--
--      spin_lock_bh(&ifp->lock);
--      ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags;
--      ifp->tstamp = jiffies;
--      ifp->valid_lft = valid_lft;
--      ifp->prefered_lft = prefered_lft;
--
--      spin_unlock_bh(&ifp->lock);
--      if (!(ifp->flags&IFA_F_TENTATIVE))
--              ipv6_ifa_notify(0, ifp);
--
--      addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev,
--                            jiffies_to_clock_t(valid_lft * HZ), flags);
--      addrconf_verify(0);
--
--      return 0;
+-      struct seq_file *seq = file->private_data;
+-      struct raw_iter_state *state = seq->private;
+-      put_net(state->net);
+-      return seq_release_private(inode, file);
 -}
 -
--static int
--inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ static const struct file_operations raw_seq_fops = {
+       .owner   = THIS_MODULE,
+       .open    = raw_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+-      .release = raw_seq_release,
++      .release = seq_release_private,
+ };
+-static int raw_proc_net_init(struct net *net)
++int __init raw_proc_init(void)
+ {
+-      if (!proc_net_fops_create(net, "raw", S_IRUGO, &raw_seq_fops))
++      if (!proc_net_fops_create("raw", S_IRUGO, &raw_seq_fops))
+               return -ENOMEM;
+       return 0;
+ }
+-static void raw_proc_net_exit(struct net *net)
 -{
--      struct ifaddrmsg *ifm;
--      struct nlattr *tb[IFA_MAX+1];
--      struct in6_addr *pfx;
--      struct inet6_ifaddr *ifa;
--      struct net_device *dev;
--      u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
--      u8 ifa_flags;
--      int err;
--
--      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
--      if (err < 0)
--              return err;
--
--      ifm = nlmsg_data(nlh);
--      pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
--      if (pfx == NULL)
--              return -EINVAL;
--
--      if (tb[IFA_CACHEINFO]) {
--              struct ifa_cacheinfo *ci;
--
--              ci = nla_data(tb[IFA_CACHEINFO]);
--              valid_lft = ci->ifa_valid;
--              preferred_lft = ci->ifa_prefered;
--      } else {
--              preferred_lft = INFINITY_LIFE_TIME;
--              valid_lft = INFINITY_LIFE_TIME;
--      }
--
--      dev =  __dev_get_by_index(ifm->ifa_index);
--      if (dev == NULL)
--              return -ENODEV;
--
--      /* We ignore other flags so far. */
--      ifa_flags = ifm->ifa_flags & (IFA_F_NODAD | IFA_F_HOMEADDRESS);
--
--      ifa = ipv6_get_ifaddr(pfx, dev, 1);
--      if (ifa == NULL) {
--              /*
--               * It would be best to check for !NLM_F_CREATE here but
--               * userspace alreay relies on not having to provide this.
--               */
--              return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
--                                    ifa_flags, preferred_lft, valid_lft);
--      }
--
--      if (nlh->nlmsg_flags & NLM_F_EXCL ||
--          !(nlh->nlmsg_flags & NLM_F_REPLACE))
--              err = -EEXIST;
--      else
--              err = inet6_addr_modify(ifa, ifa_flags, preferred_lft, valid_lft);
--
--      in6_ifa_put(ifa);
--
--      return err;
+-      proc_net_remove(net, "raw");
 -}
 -
--static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u8 flags,
--                        u8 scope, int ifindex)
--{
--      struct ifaddrmsg *ifm;
--
--      ifm = nlmsg_data(nlh);
--      ifm->ifa_family = AF_INET6;
--      ifm->ifa_prefixlen = prefixlen;
--      ifm->ifa_flags = flags;
--      ifm->ifa_scope = scope;
--      ifm->ifa_index = ifindex;
--}
+-static struct pernet_operations raw_proc_net_ops = {
+-      .init = raw_proc_net_init,
+-      .exit = raw_proc_net_exit,
+-};
 -
--static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
--                       unsigned long tstamp, u32 preferred, u32 valid)
+-int __init raw_proc_init(void)
 -{
--      struct ifa_cacheinfo ci;
--
--      ci.cstamp = (u32)(TIME_DELTA(cstamp, INITIAL_JIFFIES) / HZ * 100
--                      + TIME_DELTA(cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
--      ci.tstamp = (u32)(TIME_DELTA(tstamp, INITIAL_JIFFIES) / HZ * 100
--                      + TIME_DELTA(tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
--      ci.ifa_prefered = preferred;
--      ci.ifa_valid = valid;
--
--      return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci);
+-      return register_pernet_subsys(&raw_proc_net_ops);
 -}
 -
--static inline int rt_scope(int ifa_scope)
--{
--      if (ifa_scope & IFA_HOST)
--              return RT_SCOPE_HOST;
--      else if (ifa_scope & IFA_LINK)
--              return RT_SCOPE_LINK;
--      else if (ifa_scope & IFA_SITE)
--              return RT_SCOPE_SITE;
--      else
--              return RT_SCOPE_UNIVERSE;
--}
+ void __init raw_proc_exit(void)
+ {
+-      unregister_pernet_subsys(&raw_proc_net_ops);
++      proc_net_remove("raw");
+ }
+ #endif /* CONFIG_PROC_FS */
+diff -Nurb linux-2.6.22-590/net/ipv4/route.c linux-2.6.22-570/net/ipv4/route.c
+--- linux-2.6.22-590/net/ipv4/route.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/route.c  2007-07-08 19:32:17.000000000 -0400
+@@ -101,8 +101,8 @@
+ #include <net/tcp.h>
+ #include <net/icmp.h>
+ #include <net/xfrm.h>
++#include <net/ip_mp_alg.h>
+ #include <net/netevent.h>
+-#include <net/net_namespace.h>
+ #include <net/rtnetlink.h>
+ #ifdef CONFIG_SYSCTL
+ #include <linux/sysctl.h>
+@@ -266,7 +266,6 @@
+ #ifdef CONFIG_PROC_FS
+ struct rt_cache_iter_state {
+-      struct net *net;
+       int bucket;
+ };
+@@ -335,7 +334,6 @@
+ static int rt_cache_seq_show(struct seq_file *seq, void *v)
+ {
+-      struct rt_cache_iter_state *st = seq->private;
+       if (v == SEQ_START_TOKEN)
+               seq_printf(seq, "%-127s\n",
+                          "Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\t"
+@@ -345,9 +343,6 @@
+               struct rtable *r = v;
+               char temp[256];
+-              if (r->fl.fl_net != st->net)
+-                      return 0;
 -
--static inline int inet6_ifaddr_msgsize(void)
+               sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t"
+                             "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X",
+                       r->u.dst.dev ? r->u.dst.dev->name : "*",
+@@ -390,7 +385,6 @@
+       seq          = file->private_data;
+       seq->private = s;
+       memset(s, 0, sizeof(*s));
+-      s->net = get_net(PROC_NET(inode));
+ out:
+       return rc;
+ out_kfree:
+@@ -398,20 +392,12 @@
+       goto out;
+ }
+-static int rt_cache_seq_release(struct inode *inode, struct file *file)
 -{
--      return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
--             + nla_total_size(16) /* IFA_ADDRESS */
--             + nla_total_size(sizeof(struct ifa_cacheinfo));
+-      struct seq_file *seq = file->private_data;
+-      struct rt_cache_iter_state *st = seq->private;
+-      put_net(st->net);
+-      return seq_release_private(inode, file);
 -}
 -
--static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
--                           u32 pid, u32 seq, int event, unsigned int flags)
--{
--      struct nlmsghdr  *nlh;
--      u32 preferred, valid;
--
--      nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
--      if (nlh == NULL)
--              return -EMSGSIZE;
--
--      put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
--                    ifa->idev->dev->ifindex);
--
--      if (!(ifa->flags&IFA_F_PERMANENT)) {
--              preferred = ifa->prefered_lft;
--              valid = ifa->valid_lft;
--              if (preferred != INFINITY_LIFE_TIME) {
--                      long tval = (jiffies - ifa->tstamp)/HZ;
--                      preferred -= tval;
--                      if (valid != INFINITY_LIFE_TIME)
--                              valid -= tval;
--              }
--      } else {
--              preferred = INFINITY_LIFE_TIME;
--              valid = INFINITY_LIFE_TIME;
--      }
--
--      if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 ||
--          put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) {
--              nlmsg_cancel(skb, nlh);
--              return -EMSGSIZE;
--      }
--
--      return nlmsg_end(skb, nlh);
--}
+ static const struct file_operations rt_cache_seq_fops = {
+       .owner   = THIS_MODULE,
+       .open    = rt_cache_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+-      .release = rt_cache_seq_release,
++      .release = seq_release_private,
+ };
+@@ -509,11 +495,13 @@
+ static __inline__ void rt_free(struct rtable *rt)
+ {
++      multipath_remove(rt);
+       call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
+ }
+ static __inline__ void rt_drop(struct rtable *rt)
+ {
++      multipath_remove(rt);
+       ip_rt_put(rt);
+       call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
+ }
+@@ -577,16 +565,61 @@
+ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
+ {
+-      return (((__force u32)((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
++      return ((__force u32)((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
+               (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr)) |
+               (fl1->mark ^ fl2->mark) |
+               (*(u16 *)&fl1->nl_u.ip4_u.tos ^
+                *(u16 *)&fl2->nl_u.ip4_u.tos) |
+               (fl1->oif ^ fl2->oif) |
+-              (fl1->iif ^ fl2->iif)) == 0) &&
+-              fl1->fl_net == fl2->fl_net;
++              (fl1->iif ^ fl2->iif)) == 0;
+ }
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++static struct rtable **rt_remove_balanced_route(struct rtable **chain_head,
++                                              struct rtable *expentry,
++                                              int *removed_count)
++{
++      int passedexpired = 0;
++      struct rtable **nextstep = NULL;
++      struct rtable **rthp = chain_head;
++      struct rtable *rth;
++
++      if (removed_count)
++              *removed_count = 0;
++
++      while ((rth = *rthp) != NULL) {
++              if (rth == expentry)
++                      passedexpired = 1;
++
++              if (((*rthp)->u.dst.flags & DST_BALANCED) != 0  &&
++                  compare_keys(&(*rthp)->fl, &expentry->fl)) {
++                      if (*rthp == expentry) {
++                              *rthp = rth->u.dst.rt_next;
++                              continue;
++                      } else {
++                              *rthp = rth->u.dst.rt_next;
++                              rt_free(rth);
++                              if (removed_count)
++                                      ++(*removed_count);
++                      }
++              } else {
++                      if (!((*rthp)->u.dst.flags & DST_BALANCED) &&
++                          passedexpired && !nextstep)
++                              nextstep = &rth->u.dst.rt_next;
++
++                      rthp = &rth->u.dst.rt_next;
++              }
++      }
++
++      rt_free(expentry);
++      if (removed_count)
++              ++(*removed_count);
++
++      return nextstep;
++}
++#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
++
++
+ /* This runs via a timer and thus is always in BH context. */
+ static void rt_check_expire(unsigned long dummy)
+ {
+@@ -625,9 +658,23 @@
+                       }
+                       /* Cleanup aged off entries. */
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++                      /* remove all related balanced entries if necessary */
++                      if (rth->u.dst.flags & DST_BALANCED) {
++                              rthp = rt_remove_balanced_route(
++                                      &rt_hash_table[i].chain,
++                                      rth, NULL);
++                              if (!rthp)
++                                      break;
++                      } else {
+                               *rthp = rth->u.dst.rt_next;
+                               rt_free(rth);
+                       }
++#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
++                      *rthp = rth->u.dst.rt_next;
++                      rt_free(rth);
++#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
++              }
+               spin_unlock(rt_hash_lock_addr(i));
+               /* Fallback loop breaker. */
+@@ -674,6 +721,9 @@
+       if (delay < 0)
+               delay = ip_rt_min_delay;
++      /* flush existing multipath state*/
++      multipath_flush();
++
+       spin_lock_bh(&rt_flush_lock);
+       if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) {
+@@ -792,10 +842,31 @@
+                                       rthp = &rth->u.dst.rt_next;
+                                       continue;
+                               }
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++                              /* remove all related balanced entries
++                               * if necessary
++                               */
++                              if (rth->u.dst.flags & DST_BALANCED) {
++                                      int r;
++
++                                      rthp = rt_remove_balanced_route(
++                                              &rt_hash_table[k].chain,
++                                              rth,
++                                              &r);
++                                      goal -= r;
++                                      if (!rthp)
++                                              break;
++                              } else {
+                                       *rthp = rth->u.dst.rt_next;
+                                       rt_free(rth);
+                                       goal--;
+                               }
++#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
++                              *rthp = rth->u.dst.rt_next;
++                              rt_free(rth);
++                              goal--;
++#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
++                      }
+                       spin_unlock_bh(rt_hash_lock_addr(k));
+                       if (goal <= 0)
+                               break;
+@@ -868,7 +939,12 @@
+       spin_lock_bh(rt_hash_lock_addr(hash));
+       while ((rth = *rthp) != NULL) {
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++              if (!(rth->u.dst.flags & DST_BALANCED) &&
++                  compare_keys(&rth->fl, &rt->fl)) {
++#else
+               if (compare_keys(&rth->fl, &rt->fl)) {
++#endif
+                       /* Put it first */
+                       *rthp = rth->u.dst.rt_next;
+                       /*
+@@ -979,7 +1055,7 @@
+       static DEFINE_SPINLOCK(rt_peer_lock);
+       struct inet_peer *peer;
+-      peer = inet_getpeer(rt->fl.fl_net, rt->rt_dst, create);
++      peer = inet_getpeer(rt->rt_dst, create);
+       spin_lock_bh(&rt_peer_lock);
+       if (rt->peer == NULL) {
+@@ -1072,7 +1148,7 @@
+               if (IN_DEV_SEC_REDIRECTS(in_dev) && ip_fib_check_default(new_gw, dev))
+                       goto reject_redirect;
+       } else {
+-              if (inet_addr_type(dev->nd_net, new_gw) != RTN_UNICAST)
++              if (inet_addr_type(new_gw) != RTN_UNICAST)
+                       goto reject_redirect;
+       }
+@@ -1113,7 +1189,6 @@
+                               /* Copy all the information. */
+                               *rt = *rth;
+-                              hold_net(rt->fl.fl_net);
+                               INIT_RCU_HEAD(&rt->u.dst.rcu_head);
+                               rt->u.dst.__use         = 1;
+                               atomic_set(&rt->u.dst.__refcnt, 1);
+@@ -1332,7 +1407,7 @@
+       __be32  daddr = iph->daddr;
+       unsigned short est_mtu = 0;
+-      if (init_net.sysctl_ipv4_no_pmtu_disc)
++      if (ipv4_config.no_pmtu_disc)
+               return 0;
+       for (i = 0; i < 2; i++) {
+@@ -1414,7 +1489,6 @@
+               rt->idev = NULL;
+               in_dev_put(idev);
+       }
+-      release_net(rt->fl.fl_net);
+ }
+ static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+@@ -1422,9 +1496,8 @@
+ {
+       struct rtable *rt = (struct rtable *) dst;
+       struct in_device *idev = rt->idev;
+-      struct net *net = dev->nd_net;
+-      if (dev != &net->loopback_dev && idev && idev->dev == dev) {
+-              struct in_device *loopback_idev = in_dev_get(&net->loopback_dev);
++      if (dev != &loopback_dev && idev && idev->dev == dev) {
++              struct in_device *loopback_idev = in_dev_get(&loopback_dev);
+               if (loopback_idev) {
+                       rt->idev = loopback_idev;
+                       in_dev_put(idev);
+@@ -1511,7 +1584,7 @@
+               rt->u.dst.metrics[RTAX_MTU-1]= rt->u.dst.dev->mtu;
+       if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0)
+-              rt->u.dst.metrics[RTAX_HOPLIMIT-1] = init_net.sysctl_ip_default_ttl;
++              rt->u.dst.metrics[RTAX_HOPLIMIT-1] = sysctl_ip_default_ttl;
+       if (rt->u.dst.metrics[RTAX_MTU-1] > IP_MAX_MTU)
+               rt->u.dst.metrics[RTAX_MTU-1] = IP_MAX_MTU;
+       if (rt->u.dst.metrics[RTAX_ADVMSS-1] == 0)
+@@ -1532,7 +1605,6 @@
+ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+                               u8 tos, struct net_device *dev, int our)
+ {
+-      struct net *net = dev->nd_net;
+       unsigned hash;
+       struct rtable *rth;
+       __be32 spec_dst;
+@@ -1566,7 +1638,6 @@
+       rth->u.dst.flags= DST_HOST;
+       if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
+               rth->u.dst.flags |= DST_NOPOLICY;
+-      rth->fl.fl_net  = hold_net(net);
+       rth->fl.fl4_dst = daddr;
+       rth->rt_dst     = daddr;
+       rth->fl.fl4_tos = tos;
+@@ -1578,7 +1649,7 @@
+ #endif
+       rth->rt_iif     =
+       rth->fl.iif     = dev->ifindex;
+-      rth->u.dst.dev  = &net->loopback_dev;
++      rth->u.dst.dev  = &loopback_dev;
+       dev_hold(rth->u.dst.dev);
+       rth->idev       = in_dev_get(rth->u.dst.dev);
+       rth->fl.oif     = 0;
+@@ -1703,11 +1774,14 @@
+       atomic_set(&rth->u.dst.__refcnt, 1);
+       rth->u.dst.flags= DST_HOST;
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      if (res->fi->fib_nhs > 1)
++              rth->u.dst.flags |= DST_BALANCED;
++#endif
+       if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
+               rth->u.dst.flags |= DST_NOPOLICY;
+       if (IN_DEV_CONF_GET(out_dev, NOXFRM))
+               rth->u.dst.flags |= DST_NOXFRM;
+-      rth->fl.fl_net  = hold_net(in_dev->dev->nd_net);
+       rth->fl.fl4_dst = daddr;
+       rth->rt_dst     = daddr;
+       rth->fl.fl4_tos = tos;
+@@ -1738,7 +1812,7 @@
+       return err;
+ }
+-static inline int ip_mkroute_input(struct sk_buff *skb,
++static inline int ip_mkroute_input_def(struct sk_buff *skb,
+                                      struct fib_result* res,
+                                      const struct flowi *fl,
+                                      struct in_device *in_dev,
+@@ -1763,6 +1837,63 @@
+       return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+ }
++static inline int ip_mkroute_input(struct sk_buff *skb,
++                                 struct fib_result* res,
++                                 const struct flowi *fl,
++                                 struct in_device *in_dev,
++                                 __be32 daddr, __be32 saddr, u32 tos)
++{
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      struct rtable* rth = NULL, *rtres;
++      unsigned char hop, hopcount;
++      int err = -EINVAL;
++      unsigned int hash;
++
++      if (res->fi)
++              hopcount = res->fi->fib_nhs;
++      else
++              hopcount = 1;
++
++      /* distinguish between multipath and singlepath */
++      if (hopcount < 2)
++              return ip_mkroute_input_def(skb, res, fl, in_dev, daddr,
++                                          saddr, tos);
++
++      /* add all alternatives to the routing cache */
++      for (hop = 0; hop < hopcount; hop++) {
++              res->nh_sel = hop;
++
++              /* put reference to previous result */
++              if (hop)
++                      ip_rt_put(rtres);
++
++              /* create a routing cache entry */
++              err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos,
++                                    &rth);
++              if (err)
++                      return err;
++
++              /* put it into the cache */
++              hash = rt_hash(daddr, saddr, fl->iif);
++              err = rt_intern_hash(hash, rth, &rtres);
++              if (err)
++                      return err;
++
++              /* forward hop information to multipath impl. */
++              multipath_set_nhinfo(rth,
++                                   FIB_RES_NETWORK(*res),
++                                   FIB_RES_NETMASK(*res),
++                                   res->prefixlen,
++                                   &FIB_RES_NH(*res));
++      }
++      skb->dst = &rtres->u.dst;
++      return err;
++#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED  */
++      return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);
++#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED  */
++}
++
++
+ /*
+  *    NOTE. We drop all the packets that has local source
+  *    addresses, because every properly looped back packet
+@@ -1776,11 +1907,9 @@
+ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+                              u8 tos, struct net_device *dev)
+ {
+-      struct net *net = dev->nd_net;
+       struct fib_result res;
+       struct in_device *in_dev = in_dev_get(dev);
+-      struct flowi fl = { .fl_net = net,
+-                          .nl_u = { .ip4_u =
++      struct flowi fl = { .nl_u = { .ip4_u =
+                                     { .daddr = daddr,
+                                       .saddr = saddr,
+                                       .tos = tos,
+@@ -1838,7 +1967,7 @@
+       if (res.type == RTN_LOCAL) {
+               int result;
+               result = fib_validate_source(saddr, daddr, tos,
+-                                           net->loopback_dev.ifindex,
++                                           loopback_dev.ifindex,
+                                            dev, &spec_dst, &itag);
+               if (result < 0)
+                       goto martian_source;
+@@ -1894,7 +2023,6 @@
+       rth->u.dst.flags= DST_HOST;
+       if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
+               rth->u.dst.flags |= DST_NOPOLICY;
+-      rth->fl.fl_net  = hold_net(net);
+       rth->fl.fl4_dst = daddr;
+       rth->rt_dst     = daddr;
+       rth->fl.fl4_tos = tos;
+@@ -1906,7 +2034,7 @@
+ #endif
+       rth->rt_iif     =
+       rth->fl.iif     = dev->ifindex;
+-      rth->u.dst.dev  = &net->loopback_dev;
++      rth->u.dst.dev  = &loopback_dev;
+       dev_hold(rth->u.dst.dev);
+       rth->idev       = in_dev_get(rth->u.dst.dev);
+       rth->rt_gateway = daddr;
+@@ -1964,7 +2092,6 @@
+       struct rtable * rth;
+       unsigned        hash;
+       int iif = dev->ifindex;
+-      struct net *net = dev->nd_net;
+       tos &= IPTOS_RT_MASK;
+       hash = rt_hash(daddr, saddr, iif);
+@@ -1977,8 +2104,7 @@
+                   rth->fl.iif == iif &&
+                   rth->fl.oif == 0 &&
+                   rth->fl.mark == skb->mark &&
+-                  rth->fl.fl4_tos == tos &&
+-                  rth->fl.fl_net == net) {
++                  rth->fl.fl4_tos == tos) {
+                       rth->u.dst.lastuse = jiffies;
+                       dst_hold(&rth->u.dst);
+                       rth->u.dst.__use++;
+@@ -2085,12 +2211,18 @@
+       atomic_set(&rth->u.dst.__refcnt, 1);
+       rth->u.dst.flags= DST_HOST;
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      if (res->fi) {
++              rth->rt_multipath_alg = res->fi->fib_mp_alg;
++              if (res->fi->fib_nhs > 1)
++                      rth->u.dst.flags |= DST_BALANCED;
++      }
++#endif
+       if (IN_DEV_CONF_GET(in_dev, NOXFRM))
+               rth->u.dst.flags |= DST_NOXFRM;
+       if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
+               rth->u.dst.flags |= DST_NOPOLICY;
+-      rth->fl.fl_net  = hold_net(oldflp->fl_net);
+       rth->fl.fl4_dst = oldflp->fl4_dst;
+       rth->fl.fl4_tos = tos;
+       rth->fl.fl4_src = oldflp->fl4_src;
+@@ -2145,7 +2277,7 @@
+       return err;
+ }
+-static inline int ip_mkroute_output(struct rtable **rp,
++static inline int ip_mkroute_output_def(struct rtable **rp,
+                                       struct fib_result* res,
+                                       const struct flowi *fl,
+                                       const struct flowi *oldflp,
+@@ -2163,6 +2295,68 @@
+       return err;
+ }
++static inline int ip_mkroute_output(struct rtable** rp,
++                                  struct fib_result* res,
++                                  const struct flowi *fl,
++                                  const struct flowi *oldflp,
++                                  struct net_device *dev_out,
++                                  unsigned flags)
++{
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      unsigned char hop;
++      unsigned hash;
++      int err = -EINVAL;
++      struct rtable *rth = NULL;
++
++      if (res->fi && res->fi->fib_nhs > 1) {
++              unsigned char hopcount = res->fi->fib_nhs;
++
++              for (hop = 0; hop < hopcount; hop++) {
++                      struct net_device *dev2nexthop;
++
++                      res->nh_sel = hop;
++
++                      /* hold a work reference to the output device */
++                      dev2nexthop = FIB_RES_DEV(*res);
++                      dev_hold(dev2nexthop);
++
++                      /* put reference to previous result */
++                      if (hop)
++                              ip_rt_put(*rp);
++
++                      err = __mkroute_output(&rth, res, fl, oldflp,
++                                             dev2nexthop, flags);
++
++                      if (err != 0)
++                              goto cleanup;
++
++                      hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src,
++                                      oldflp->oif);
++                      err = rt_intern_hash(hash, rth, rp);
++
++                      /* forward hop information to multipath impl. */
++                      multipath_set_nhinfo(rth,
++                                           FIB_RES_NETWORK(*res),
++                                           FIB_RES_NETMASK(*res),
++                                           res->prefixlen,
++                                           &FIB_RES_NH(*res));
++              cleanup:
++                      /* release work reference to output device */
++                      dev_put(dev2nexthop);
++
++                      if (err != 0)
++                              return err;
++              }
++              return err;
++      } else {
++              return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out,
++                                           flags);
++      }
++#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
++      return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, flags);
++#endif
++}
++
+ /*
+  * Major route resolver routine.
+  */
+@@ -2170,9 +2364,7 @@
+ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
+ {
+       u32 tos = RT_FL_TOS(oldflp);
+-      struct net *net = oldflp->fl_net;
+-      struct flowi fl = { .fl_net = net,
+-                          .nl_u = { .ip4_u =
++      struct flowi fl = { .nl_u = { .ip4_u =
+                                     { .daddr = oldflp->fl4_dst,
+                                       .saddr = oldflp->fl4_src,
+                                       .tos = tos & IPTOS_RT_MASK,
+@@ -2181,7 +2373,7 @@
+                                                 RT_SCOPE_UNIVERSE),
+                                     } },
+                           .mark = oldflp->mark,
+-                          .iif = net->loopback_dev.ifindex,
++                          .iif = loopback_dev.ifindex,
+                           .oif = oldflp->oif };
+       struct fib_result res;
+       unsigned flags = 0;
+@@ -2203,7 +2395,7 @@
+                       goto out;
+               /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
+-              dev_out = ip_dev_find(net, oldflp->fl4_src);
++              dev_out = ip_dev_find(oldflp->fl4_src);
+               if (dev_out == NULL)
+                       goto out;
+@@ -2242,7 +2434,7 @@
+       if (oldflp->oif) {
+-              dev_out = dev_get_by_index(net, oldflp->oif);
++              dev_out = dev_get_by_index(oldflp->oif);
+               err = -ENODEV;
+               if (dev_out == NULL)
+                       goto out;
+@@ -2275,9 +2467,9 @@
+                       fl.fl4_dst = fl.fl4_src = htonl(INADDR_LOOPBACK);
+               if (dev_out)
+                       dev_put(dev_out);
+-              dev_out = &net->loopback_dev;
++              dev_out = &loopback_dev;
+               dev_hold(dev_out);
+-              fl.oif = net->loopback_dev.ifindex;
++              fl.oif = loopback_dev.ifindex;
+               res.type = RTN_LOCAL;
+               flags |= RTCF_LOCAL;
+               goto make_route;
+@@ -2322,7 +2514,7 @@
+                       fl.fl4_src = fl.fl4_dst;
+               if (dev_out)
+                       dev_put(dev_out);
+-              dev_out = &net->loopback_dev;
++              dev_out = &loopback_dev;
+               dev_hold(dev_out);
+               fl.oif = dev_out->ifindex;
+               if (res.fi)
+@@ -2376,9 +2568,19 @@
+                   rth->fl.iif == 0 &&
+                   rth->fl.oif == flp->oif &&
+                   rth->fl.mark == flp->mark &&
+-                  rth->fl.fl_net == flp->fl_net &&
+                   !((rth->fl.fl4_tos ^ flp->fl4_tos) &
+                           (IPTOS_RT_MASK | RTO_ONLINK))) {
++
++                      /* check for multipath routes and choose one if
++                       * necessary
++                       */
++                      if (multipath_select_route(flp, rth, rp)) {
++                              dst_hold(&(*rp)->u.dst);
++                              RT_CACHE_STAT_INC(out_hit);
++                              rcu_read_unlock_bh();
++                              return 0;
++                      }
++
+                       rth->u.dst.lastuse = jiffies;
+                       dst_hold(&rth->u.dst);
+                       rth->u.dst.__use++;
+@@ -2527,6 +2729,10 @@
+       if (rt->u.dst.tclassid)
+               NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid);
+ #endif
++#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
++      if (rt->rt_multipath_alg != IP_MP_ALG_NONE)
++              NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg);
++#endif
+       if (rt->fl.iif)
+               NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst);
+       else if (rt->rt_src != rt->fl.fl4_src)
+@@ -2553,7 +2759,7 @@
+               __be32 dst = rt->rt_dst;
+               if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&
+-                  IPV4_DEVCONF_ALL(&init_net, MC_FORWARDING)) {
++                  IPV4_DEVCONF_ALL(MC_FORWARDING)) {
+                       int err = ipmr_get_route(skb, r, nowait);
+                       if (err <= 0) {
+                               if (!nowait) {
+@@ -2584,7 +2790,6 @@
+ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
+ {
+-      struct net *net = in_skb->sk->sk_net;
+       struct rtmsg *rtm;
+       struct nlattr *tb[RTA_MAX+1];
+       struct rtable *rt = NULL;
+@@ -2623,7 +2828,7 @@
+       if (iif) {
+               struct net_device *dev;
+-              dev = __dev_get_by_index(net, iif);
++              dev = __dev_get_by_index(iif);
+               if (dev == NULL) {
+                       err = -ENODEV;
+                       goto errout_free;
+@@ -2640,7 +2845,6 @@
+                       err = -rt->u.dst.error;
+       } else {
+               struct flowi fl = {
+-                      .fl_net = net,
+                       .nl_u = {
+                               .ip4_u = {
+                                       .daddr = dst,
+@@ -2665,7 +2869,7 @@
+       if (err <= 0)
+               goto errout_free;
+-      err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid);
++      err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
+ errout:
+       return err;
+@@ -2978,48 +3182,6 @@
+ }
+ __setup("rhash_entries=", set_rhash_entries);
 -
--static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
--                              u32 pid, u32 seq, int event, u16 flags)
+-static void ip_rt_net_exit(struct net *net)
 -{
--      struct nlmsghdr  *nlh;
--      u8 scope = RT_SCOPE_UNIVERSE;
--      int ifindex = ifmca->idev->dev->ifindex;
--
--      if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
--              scope = RT_SCOPE_SITE;
--
--      nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
--      if (nlh == NULL)
--              return -EMSGSIZE;
--
--      put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
--      if (nla_put(skb, IFA_MULTICAST, 16, &ifmca->mca_addr) < 0 ||
--          put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp,
--                        INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
--              nlmsg_cancel(skb, nlh);
--              return -EMSGSIZE;
--      }
--
--      return nlmsg_end(skb, nlh);
+-#ifdef CONFIG_PROC_FS
+-# ifdef CONFIG_NET_CLS_ROUTE
+-      proc_net_remove(net, "rt_acct");
+-# endif
+-      remove_proc_entry("rt_cache", net->proc_net_stat);
+-      proc_net_remove(net, "rt_cache");
+-#endif
+-      rt_run_flush(0);
 -}
 -
--static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
--                              u32 pid, u32 seq, int event, unsigned int flags)
+-static int ip_rt_net_init(struct net *net)
 -{
--      struct nlmsghdr  *nlh;
--      u8 scope = RT_SCOPE_UNIVERSE;
--      int ifindex = ifaca->aca_idev->dev->ifindex;
--
--      if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE)
--              scope = RT_SCOPE_SITE;
--
--      nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
--      if (nlh == NULL)
--              return -EMSGSIZE;
--
--      put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
--      if (nla_put(skb, IFA_ANYCAST, 16, &ifaca->aca_addr) < 0 ||
--          put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp,
--                        INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
--              nlmsg_cancel(skb, nlh);
--              return -EMSGSIZE;
--      }
--
--      return nlmsg_end(skb, nlh);
+-      int error = -ENOMEM;
+-#ifdef CONFIG_PROC_FS
+-      struct proc_dir_entry *rtstat_pde;
+-      if (!proc_net_fops_create(net, "rt_cache", S_IRUGO, &rt_cache_seq_fops))
+-              goto out;
+-      if (!(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO,
+-                      net->proc_net_stat)))
+-              goto out;
+-      rtstat_pde->proc_fops = &rt_cpu_seq_fops;
+-# ifdef CONFIG_NET_CLS_ROUTE
+-      if (!create_proc_read_entry("rt_acct", 0, net->proc_net,
+-                  ip_rt_acct_read, NULL))
+-              goto out;
+-# endif
+-#endif
+-      error = 0;
+-out:
+-      if (error)
+-              ip_rt_net_exit(net);
+-      return error;
 -}
 -
--enum addr_type_t
--{
--      UNICAST_ADDR,
--      MULTICAST_ADDR,
--      ANYCAST_ADDR,
+-struct pernet_operations ip_rt_net_ops = {
+-      .init = ip_rt_net_init,
+-      .exit = ip_rt_net_exit,
 -};
+- 
+ int __init ip_rt_init(void)
+ {
+       int rc = 0;
+@@ -3083,7 +3245,20 @@
+               ip_rt_secret_interval;
+       add_timer(&rt_secret_timer);
+-      register_pernet_subsys(&ip_rt_net_ops);
++#ifdef CONFIG_PROC_FS
++      {
++      struct proc_dir_entry *rtstat_pde = NULL; /* keep gcc happy */
++      if (!proc_net_fops_create("rt_cache", S_IRUGO, &rt_cache_seq_fops) ||
++          !(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO,
++                                           proc_net_stat))) {
++              return -ENOMEM;
++      }
++      rtstat_pde->proc_fops = &rt_cpu_seq_fops;
++      }
++#ifdef CONFIG_NET_CLS_ROUTE
++      create_proc_read_entry("rt_acct", 0, proc_net, ip_rt_acct_read, NULL);
++#endif
++#endif
+ #ifdef CONFIG_XFRM
+       xfrm_init();
+       xfrm4_init();
+diff -Nurb linux-2.6.22-590/net/ipv4/syncookies.c linux-2.6.22-570/net/ipv4/syncookies.c
+--- linux-2.6.22-590/net/ipv4/syncookies.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/syncookies.c     2007-07-08 19:32:17.000000000 -0400
+@@ -253,8 +253,7 @@
+        * no easy way to do this.
+        */
+       {
+-              struct flowi fl = { .fl_net = &init_net,
+-                                  .nl_u = { .ip4_u =
++              struct flowi fl = { .nl_u = { .ip4_u =
+                                             { .daddr = ((opt && opt->srr) ?
+                                                         opt->faddr :
+                                                         ireq->rmt_addr),
+diff -Nurb linux-2.6.22-590/net/ipv4/sysctl_net_ipv4.c linux-2.6.22-570/net/ipv4/sysctl_net_ipv4.c
+--- linux-2.6.22-590/net/ipv4/sysctl_net_ipv4.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/sysctl_net_ipv4.c        2008-01-23 19:16:09.000000000 -0500
+@@ -29,21 +29,21 @@
+ static int ip_local_port_range_max[] = { 65535, 65535 };
+ #endif
++struct ipv4_config ipv4_config;
++
+ #ifdef CONFIG_SYSCTL
+ static
+ int ipv4_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
+                       void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
+-      struct net *net = ctl->extra2;
+-      int *valp = ctl->data;
+-      int old = *valp;
++      int val = IPV4_DEVCONF_ALL(FORWARDING);
+       int ret;
+       ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+-      if (write && *valp != old)
+-              inet_forward_change(net);
++      if (write && IPV4_DEVCONF_ALL(FORWARDING) != val)
++              inet_forward_change();
+       return ret;
+ }
+@@ -53,7 +53,6 @@
+                        void __user *oldval, size_t __user *oldlenp,
+                        void __user *newval, size_t newlen)
+ {
+-      struct net *net = table->extra2;
+       int *valp = table->data;
+       int new;
+@@ -86,7 +85,7 @@
+       }
+       *valp = new;
+-      inet_forward_change(net);
++      inet_forward_change();
+       return 1;
+ }
+@@ -189,6 +188,22 @@
+ ctl_table ipv4_table[] = {
+       {
++              .ctl_name       = NET_IPV4_TCP_TIMESTAMPS,
++              .procname       = "tcp_timestamps",
++              .data           = &sysctl_tcp_timestamps,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec
++      },
++      {
++              .ctl_name       = NET_IPV4_TCP_WINDOW_SCALING,
++              .procname       = "tcp_window_scaling",
++              .data           = &sysctl_tcp_window_scaling,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec
++      },
++      {
+               .ctl_name       = NET_IPV4_TCP_SACK,
+               .procname       = "tcp_sack",
+               .data           = &sysctl_tcp_sack,
+@@ -205,6 +220,40 @@
+               .proc_handler   = &proc_dointvec
+       },
+       {
++              .ctl_name       = NET_IPV4_FORWARD,
++              .procname       = "ip_forward",
++              .data           = &IPV4_DEVCONF_ALL(FORWARDING),
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &ipv4_sysctl_forward,
++              .strategy       = &ipv4_sysctl_forward_strategy
++      },
++      {
++              .ctl_name       = NET_IPV4_DEFAULT_TTL,
++              .procname       = "ip_default_ttl",
++              .data           = &sysctl_ip_default_ttl,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &ipv4_doint_and_flush,
++              .strategy       = &ipv4_doint_and_flush_strategy,
++      },
++      {
++              .ctl_name       = NET_IPV4_NO_PMTU_DISC,
++              .procname       = "ip_no_pmtu_disc",
++              .data           = &ipv4_config.no_pmtu_disc,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec
++      },
++      {
++              .ctl_name       = NET_IPV4_NONLOCAL_BIND,
++              .procname       = "ip_nonlocal_bind",
++              .data           = &sysctl_ip_nonlocal_bind,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec
++      },
++      {
+               .ctl_name       = NET_IPV4_TCP_SYN_RETRIES,
+               .procname       = "tcp_syn_retries",
+               .data           = &sysctl_tcp_syn_retries,
+@@ -237,6 +286,39 @@
+               .proc_handler   = &proc_dointvec
+       },
+       {
++              .ctl_name       = NET_IPV4_IPFRAG_HIGH_THRESH,
++              .procname       = "ipfrag_high_thresh",
++              .data           = &sysctl_ipfrag_high_thresh,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec
++      },
++      {
++              .ctl_name       = NET_IPV4_IPFRAG_LOW_THRESH,
++              .procname       = "ipfrag_low_thresh",
++              .data           = &sysctl_ipfrag_low_thresh,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec
++      },
++      {
++              .ctl_name       = NET_IPV4_DYNADDR,
++              .procname       = "ip_dynaddr",
++              .data           = &sysctl_ip_dynaddr,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec
++      },
++      {
++              .ctl_name       = NET_IPV4_IPFRAG_TIME,
++              .procname       = "ipfrag_time",
++              .data           = &sysctl_ipfrag_time,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec_jiffies,
++              .strategy       = &sysctl_jiffies
++      },
++      {
+               .ctl_name       = NET_IPV4_TCP_KEEPALIVE_TIME,
+               .procname       = "tcp_keepalive_time",
+               .data           = &sysctl_tcp_keepalive_time,
+@@ -340,6 +422,17 @@
+               .proc_handler   = &proc_dointvec
+       },
+       {
++              .ctl_name       = NET_IPV4_LOCAL_PORT_RANGE,
++              .procname       = "ip_local_port_range",
++              .data           = &sysctl_local_port_range,
++              .maxlen         = sizeof(sysctl_local_port_range),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec_minmax,
++              .strategy       = &sysctl_intvec,
++              .extra1         = ip_local_port_range_min,
++              .extra2         = ip_local_port_range_max
++      },
++      {
+               .ctl_name       = NET_IPV4_ICMP_ECHO_IGNORE_ALL,
+               .procname       = "icmp_echo_ignore_all",
+               .data           = &sysctl_icmp_echo_ignore_all,
+@@ -441,6 +534,50 @@
+               .proc_handler   = &proc_dointvec
+       },
+       {
++              .ctl_name       = NET_IPV4_INET_PEER_THRESHOLD,
++              .procname       = "inet_peer_threshold",
++              .data           = &inet_peer_threshold,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec
++      },
++      {
++              .ctl_name       = NET_IPV4_INET_PEER_MINTTL,
++              .procname       = "inet_peer_minttl",
++              .data           = &inet_peer_minttl,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec_jiffies,
++              .strategy       = &sysctl_jiffies
++      },
++      {
++              .ctl_name       = NET_IPV4_INET_PEER_MAXTTL,
++              .procname       = "inet_peer_maxttl",
++              .data           = &inet_peer_maxttl,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec_jiffies,
++              .strategy       = &sysctl_jiffies
++      },
++      {
++              .ctl_name       = NET_IPV4_INET_PEER_GC_MINTIME,
++              .procname       = "inet_peer_gc_mintime",
++              .data           = &inet_peer_gc_mintime,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec_jiffies,
++              .strategy       = &sysctl_jiffies
++      },
++      {
++              .ctl_name       = NET_IPV4_INET_PEER_GC_MAXTIME,
++              .procname       = "inet_peer_gc_maxtime",
++              .data           = &inet_peer_gc_maxtime,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec_jiffies,
++              .strategy       = &sysctl_jiffies
++      },
++      {
+               .ctl_name       = NET_TCP_ORPHAN_RETRIES,
+               .procname       = "tcp_orphan_retries",
+               .data           = &sysctl_tcp_orphan_retries,
+@@ -569,6 +706,24 @@
+               .proc_handler   = &proc_dointvec
+       },
+       {
++              .ctl_name       = NET_IPV4_IPFRAG_SECRET_INTERVAL,
++              .procname       = "ipfrag_secret_interval",
++              .data           = &sysctl_ipfrag_secret_interval,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec_jiffies,
++              .strategy       = &sysctl_jiffies
++      },
++      {
++              .ctl_name       = NET_IPV4_IPFRAG_MAX_DIST,
++              .procname       = "ipfrag_max_dist",
++              .data           = &sysctl_ipfrag_max_dist,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = &proc_dointvec_minmax,
++              .extra1         = &zero
++      },
++      {
+               .ctl_name       = NET_TCP_NO_METRICS_SAVE,
+               .procname       = "tcp_no_metrics_save",
+               .data           = &sysctl_tcp_nometrics_save,
+@@ -710,181 +865,6 @@
+       { .ctl_name = 0 }
+ };
+-struct ctl_table multi_ipv4_table[] = {
+-      {
+-              /* .data is filled in by devinet_net_init.
+-               * As a consequence this table entry must be the first
+-               * entry in multi_ipv4_table.
+-               */
+-              .ctl_name       = NET_IPV4_FORWARD,
+-              .procname       = "ip_forward",
+-              .data           = NULL,
+-              .extra2         = &init_net,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &ipv4_sysctl_forward,
+-              .strategy       = &ipv4_sysctl_forward_strategy
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_DEFAULT_TTL,
+-              .procname       = "ip_default_ttl",
+-              .data           = &init_net.sysctl_ip_default_ttl,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &ipv4_doint_and_flush,
+-              .strategy       = &ipv4_doint_and_flush_strategy,
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_NO_PMTU_DISC,
+-              .procname       = "ip_no_pmtu_disc",
+-              .data           = &init_net.sysctl_ipv4_no_pmtu_disc,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_NONLOCAL_BIND,
+-              .procname       = "ip_nonlocal_bind",
+-              .data           = &init_net.sysctl_ip_nonlocal_bind,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_LOCAL_PORT_RANGE,
+-              .procname       = "ip_local_port_range",
+-              .data           = &init_net.sysctl_local_port_range,
+-              .maxlen         = sizeof(init_net.sysctl_local_port_range),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec_minmax,
+-              .strategy       = &sysctl_intvec,
+-              .extra1         = ip_local_port_range_min,
+-              .extra2         = ip_local_port_range_max
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_IPFRAG_HIGH_THRESH,
+-              .procname       = "ipfrag_high_thresh",
+-              .data           = &init_net.sysctl_ipfrag_high_thresh,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_IPFRAG_LOW_THRESH,
+-              .procname       = "ipfrag_low_thresh",
+-              .data           = &init_net.sysctl_ipfrag_low_thresh,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_IPFRAG_TIME,
+-              .procname       = "ipfrag_time",
+-              .data           = &init_net.sysctl_ipfrag_time,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec_jiffies,
+-              .strategy       = &sysctl_jiffies
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_IPFRAG_SECRET_INTERVAL,
+-              .procname       = "ipfrag_secret_interval",
+-              .data           = &init_net.sysctl_ipfrag_secret_interval,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec_jiffies,
+-              .strategy       = &sysctl_jiffies
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_IPFRAG_MAX_DIST,
+-              .procname       = "ipfrag_max_dist",
+-              .data           = &init_net.sysctl_ipfrag_max_dist,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec_minmax,
+-              .extra1         = &zero
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_DYNADDR,
+-              .procname       = "ip_dynaddr",
+-              .data           = &init_net.sysctl_ip_dynaddr,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_LOCAL_PORT_RANGE,
+-              .procname       = "ip_local_port_range",
+-              .data           = &init_net.sysctl_local_port_range,
+-              .maxlen         = sizeof(init_net.sysctl_local_port_range),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec_minmax,
+-              .strategy       = &sysctl_intvec,
+-              .extra1         = ip_local_port_range_min,
+-              .extra2         = ip_local_port_range_max
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_INET_PEER_THRESHOLD,
+-              .procname       = "inet_peer_threshold",
+-              .data           = &init_net.inet_peer_threshold,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_INET_PEER_MINTTL,
+-              .procname       = "inet_peer_minttl",
+-              .data           = &init_net.inet_peer_minttl,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec_jiffies,
+-              .strategy       = &sysctl_jiffies
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_INET_PEER_MAXTTL,
+-              .procname       = "inet_peer_maxttl",
+-              .data           = &init_net.inet_peer_maxttl,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec_jiffies,
+-              .strategy       = &sysctl_jiffies
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_INET_PEER_GC_MINTIME,
+-              .procname       = "inet_peer_gc_mintime",
+-              .data           = &init_net.inet_peer_gc_mintime,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec_jiffies,
+-              .strategy       = &sysctl_jiffies
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_INET_PEER_GC_MAXTIME,
+-              .procname       = "inet_peer_gc_maxtime",
+-              .data           = &init_net.inet_peer_gc_maxtime,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec_jiffies,
+-              .strategy       = &sysctl_jiffies
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_TCP_TIMESTAMPS,
+-              .procname       = "tcp_timestamps",
+-              .data           = &init_net.sysctl_tcp_timestamps,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec
 -
--static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
--                         enum addr_type_t type)
--{
--      int idx, ip_idx;
--      int s_idx, s_ip_idx;
--      int err = 1;
--      struct net_device *dev;
--      struct inet6_dev *idev = NULL;
--      struct inet6_ifaddr *ifa;
--      struct ifmcaddr6 *ifmca;
--      struct ifacaddr6 *ifaca;
--
--      s_idx = cb->args[0];
--      s_ip_idx = ip_idx = cb->args[1];
--
--      idx = 0;
--      for_each_netdev(dev) {
--              if (idx < s_idx)
--                      goto cont;
--              if (idx > s_idx)
--                      s_ip_idx = 0;
--              ip_idx = 0;
--              if ((idev = in6_dev_get(dev)) == NULL)
--                      goto cont;
--              read_lock_bh(&idev->lock);
--              switch (type) {
--              case UNICAST_ADDR:
--                      /* unicast address incl. temp addr */
--                      for (ifa = idev->addr_list; ifa;
--                           ifa = ifa->if_next, ip_idx++) {
--                              if (ip_idx < s_ip_idx)
--                                      continue;
--                              if ((err = inet6_fill_ifaddr(skb, ifa,
--                                  NETLINK_CB(cb->skb).pid,
--                                  cb->nlh->nlmsg_seq, RTM_NEWADDR,
--                                  NLM_F_MULTI)) <= 0)
--                                      goto done;
--                      }
--                      break;
--              case MULTICAST_ADDR:
--                      /* multicast address */
--                      for (ifmca = idev->mc_list; ifmca;
--                           ifmca = ifmca->next, ip_idx++) {
--                              if (ip_idx < s_ip_idx)
--                                      continue;
--                              if ((err = inet6_fill_ifmcaddr(skb, ifmca,
--                                  NETLINK_CB(cb->skb).pid,
--                                  cb->nlh->nlmsg_seq, RTM_GETMULTICAST,
--                                  NLM_F_MULTI)) <= 0)
--                                      goto done;
--                      }
--                      break;
--              case ANYCAST_ADDR:
--                      /* anycast address */
--                      for (ifaca = idev->ac_list; ifaca;
--                           ifaca = ifaca->aca_next, ip_idx++) {
--                              if (ip_idx < s_ip_idx)
--                                      continue;
--                              if ((err = inet6_fill_ifacaddr(skb, ifaca,
--                                  NETLINK_CB(cb->skb).pid,
--                                  cb->nlh->nlmsg_seq, RTM_GETANYCAST,
--                                  NLM_F_MULTI)) <= 0)
--                                      goto done;
--                      }
--                      break;
--              default:
--                      break;
--              }
--              read_unlock_bh(&idev->lock);
--              in6_dev_put(idev);
--cont:
--              idx++;
--      }
--done:
--      if (err <= 0) {
--              read_unlock_bh(&idev->lock);
--              in6_dev_put(idev);
--      }
--      cb->args[0] = idx;
--      cb->args[1] = ip_idx;
--      return skb->len;
--}
--
--static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
--{
--      enum addr_type_t type = UNICAST_ADDR;
--      return inet6_dump_addr(skb, cb, type);
--}
--
--static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb)
--{
--      enum addr_type_t type = MULTICAST_ADDR;
--      return inet6_dump_addr(skb, cb, type);
--}
--
--
--static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
--{
--      enum addr_type_t type = ANYCAST_ADDR;
--      return inet6_dump_addr(skb, cb, type);
--}
--
--static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
--                           void *arg)
--{
--      struct ifaddrmsg *ifm;
--      struct nlattr *tb[IFA_MAX+1];
--      struct in6_addr *addr = NULL;
--      struct net_device *dev = NULL;
--      struct inet6_ifaddr *ifa;
--      struct sk_buff *skb;
--      int err;
--
--      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
--      if (err < 0)
--              goto errout;
--
--      addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
--      if (addr == NULL) {
--              err = -EINVAL;
--              goto errout;
--      }
--
--      ifm = nlmsg_data(nlh);
--      if (ifm->ifa_index)
--              dev = __dev_get_by_index(ifm->ifa_index);
--
--      if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) {
--              err = -EADDRNOTAVAIL;
--              goto errout;
--      }
--
--      if ((skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL)) == NULL) {
--              err = -ENOBUFS;
--              goto errout_ifa;
--      }
--
--      err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
--                              nlh->nlmsg_seq, RTM_NEWADDR, 0);
--      if (err < 0) {
--              /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
--              WARN_ON(err == -EMSGSIZE);
--              kfree_skb(skb);
--              goto errout_ifa;
--      }
--      err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
--errout_ifa:
--      in6_ifa_put(ifa);
--errout:
--      return err;
--}
--
--static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
--{
--      struct sk_buff *skb;
--      int err = -ENOBUFS;
--
--      skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC);
--      if (skb == NULL)
--              goto errout;
--
--      err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0);
--      if (err < 0) {
--              /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
--              WARN_ON(err == -EMSGSIZE);
--              kfree_skb(skb);
--              goto errout;
--      }
--      err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
--errout:
--      if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
--}
--
--static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
--                              __s32 *array, int bytes)
--{
--      BUG_ON(bytes < (DEVCONF_MAX * 4));
--
--      memset(array, 0, bytes);
--      array[DEVCONF_FORWARDING] = cnf->forwarding;
--      array[DEVCONF_HOPLIMIT] = cnf->hop_limit;
--      array[DEVCONF_MTU6] = cnf->mtu6;
--      array[DEVCONF_ACCEPT_RA] = cnf->accept_ra;
--      array[DEVCONF_ACCEPT_REDIRECTS] = cnf->accept_redirects;
--      array[DEVCONF_AUTOCONF] = cnf->autoconf;
--      array[DEVCONF_DAD_TRANSMITS] = cnf->dad_transmits;
--      array[DEVCONF_RTR_SOLICITS] = cnf->rtr_solicits;
--      array[DEVCONF_RTR_SOLICIT_INTERVAL] = cnf->rtr_solicit_interval;
--      array[DEVCONF_RTR_SOLICIT_DELAY] = cnf->rtr_solicit_delay;
--      array[DEVCONF_FORCE_MLD_VERSION] = cnf->force_mld_version;
--#ifdef CONFIG_IPV6_PRIVACY
--      array[DEVCONF_USE_TEMPADDR] = cnf->use_tempaddr;
--      array[DEVCONF_TEMP_VALID_LFT] = cnf->temp_valid_lft;
--      array[DEVCONF_TEMP_PREFERED_LFT] = cnf->temp_prefered_lft;
--      array[DEVCONF_REGEN_MAX_RETRY] = cnf->regen_max_retry;
--      array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
--#endif
--      array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
--      array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr;
--      array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
--#ifdef CONFIG_IPV6_ROUTER_PREF
--      array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
--      array[DEVCONF_RTR_PROBE_INTERVAL] = cnf->rtr_probe_interval;
--#ifdef CONFIG_IPV6_ROUTE_INFO
--      array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
--#endif
--#endif
--      array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;
--      array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;
--#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
--      array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
--#endif
--}
--
--static inline size_t inet6_if_nlmsg_size(void)
--{
--      return NLMSG_ALIGN(sizeof(struct ifinfomsg))
--             + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
--             + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
--             + nla_total_size(4) /* IFLA_MTU */
--             + nla_total_size(4) /* IFLA_LINK */
--             + nla_total_size( /* IFLA_PROTINFO */
--                      nla_total_size(4) /* IFLA_INET6_FLAGS */
--                      + nla_total_size(sizeof(struct ifla_cacheinfo))
--                      + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
--                      + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
--                      + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
--               );
--}
+-      },
+-      {
+-              .ctl_name       = NET_IPV4_TCP_WINDOW_SCALING,
+-              .procname       = "tcp_window_scaling",
+-              .data           = &init_net.sysctl_tcp_window_scaling,
+-              .maxlen         = sizeof(int),
+-              .mode           = 0644,
+-              .proc_handler   = &proc_dointvec
+-      },
+-      {}
+-};
 -
--static inline void __snmp6_fill_stats(u64 *stats, void **mib, int items,
--                                    int bytes)
+ #endif /* CONFIG_SYSCTL */
++
++EXPORT_SYMBOL(ipv4_config);
+diff -Nurb linux-2.6.22-590/net/ipv4/tcp.c linux-2.6.22-570/net/ipv4/tcp.c
+--- linux-2.6.22-590/net/ipv4/tcp.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/tcp.c    2008-01-23 19:16:05.000000000 -0500
+@@ -2409,23 +2409,6 @@
+ }
+ __setup("thash_entries=", set_thash_entries);
+-static int tcp_net_init(struct net *net)
 -{
--      int i;
--      int pad = bytes - sizeof(u64) * items;
--      BUG_ON(pad < 0);
--
--      /* Use put_unaligned() because stats may not be aligned for u64. */
--      put_unaligned(items, &stats[0]);
--      for (i = 1; i < items; i++)
--              put_unaligned(snmp_fold_field(mib, i), &stats[i]);
--
--      memset(&stats[items], 0, pad);
--}
+-      /*
+-       * This array holds the first and last local port number.
+-       */
+-      net->sysctl_local_port_range[0] = 32768;
+-      net->sysctl_local_port_range[1] = 61000;
 -
--static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype,
--                           int bytes)
--{
--      switch(attrtype) {
--      case IFLA_INET6_STATS:
--              __snmp6_fill_stats(stats, (void **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes);
--              break;
--      case IFLA_INET6_ICMP6STATS:
--              __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes);
--              break;
--      }
+-      net->sysctl_tcp_timestamps = 1;
+-      net->sysctl_tcp_window_scaling = 1;
+-      return 0;
 -}
 -
--static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
--                           u32 pid, u32 seq, int event, unsigned int flags)
--{
--      struct net_device *dev = idev->dev;
--      struct nlattr *nla;
--      struct ifinfomsg *hdr;
--      struct nlmsghdr *nlh;
--      void *protoinfo;
--      struct ifla_cacheinfo ci;
--
--      nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
--      if (nlh == NULL)
--              return -EMSGSIZE;
--
--      hdr = nlmsg_data(nlh);
--      hdr->ifi_family = AF_INET6;
--      hdr->__ifi_pad = 0;
--      hdr->ifi_type = dev->type;
--      hdr->ifi_index = dev->ifindex;
--      hdr->ifi_flags = dev_get_flags(dev);
--      hdr->ifi_change = 0;
--
--      NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
--
--      if (dev->addr_len)
--              NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
--
--      NLA_PUT_U32(skb, IFLA_MTU, dev->mtu);
--      if (dev->ifindex != dev->iflink)
--              NLA_PUT_U32(skb, IFLA_LINK, dev->iflink);
--
--      protoinfo = nla_nest_start(skb, IFLA_PROTINFO);
--      if (protoinfo == NULL)
--              goto nla_put_failure;
--
--      NLA_PUT_U32(skb, IFLA_INET6_FLAGS, idev->if_flags);
--
--      ci.max_reasm_len = IPV6_MAXPLEN;
--      ci.tstamp = (__u32)(TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) / HZ * 100
--                  + TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
--      ci.reachable_time = idev->nd_parms->reachable_time;
--      ci.retrans_time = idev->nd_parms->retrans_time;
--      NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci);
--
--      nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
--      if (nla == NULL)
--              goto nla_put_failure;
--      ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla));
--
--      /* XXX - MC not implemented */
--
--      nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
--      if (nla == NULL)
--              goto nla_put_failure;
--      snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
--
--      nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
--      if (nla == NULL)
--              goto nla_put_failure;
--      snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
--
--      nla_nest_end(skb, protoinfo);
--      return nlmsg_end(skb, nlh);
+-static struct pernet_operations tcp_net_ops = {
+-      .init = tcp_net_init,
+-};
 -
--nla_put_failure:
--      nlmsg_cancel(skb, nlh);
--      return -EMSGSIZE;
--}
+ void __init tcp_init(void)
+ {
+       struct sk_buff *skb = NULL;
+@@ -2519,8 +2502,6 @@
+       sysctl_tcp_rmem[1] = 87380;
+       sysctl_tcp_rmem[2] = max(87380, max_share);
+-      register_pernet_subsys(&tcp_net_ops);
 -
--static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+       printk(KERN_INFO "TCP: Hash tables configured "
+              "(established %d bind %d)\n",
+              tcp_hashinfo.ehash_size, tcp_hashinfo.bhash_size);
+diff -Nurb linux-2.6.22-590/net/ipv4/tcp_input.c linux-2.6.22-570/net/ipv4/tcp_input.c
+--- linux-2.6.22-590/net/ipv4/tcp_input.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/tcp_input.c      2008-01-23 19:15:56.000000000 -0500
+@@ -72,6 +72,8 @@
+ #include <asm/unaligned.h>
+ #include <net/netdma.h>
++int sysctl_tcp_timestamps __read_mostly = 1;
++int sysctl_tcp_window_scaling __read_mostly = 1;
+ int sysctl_tcp_sack __read_mostly = 1;
+ int sysctl_tcp_fack __read_mostly = 1;
+ int sysctl_tcp_reordering __read_mostly = TCP_FASTRETRANS_THRESH;
+@@ -2920,7 +2922,7 @@
+                                       break;
+                               case TCPOPT_WINDOW:
+                                       if (opsize==TCPOLEN_WINDOW && th->syn && !estab)
+-                                              if (init_net.sysctl_tcp_window_scaling) {
++                                              if (sysctl_tcp_window_scaling) {
+                                                       __u8 snd_wscale = *(__u8 *) ptr;
+                                                       opt_rx->wscale_ok = 1;
+                                                       if (snd_wscale > 14) {
+@@ -2936,7 +2938,7 @@
+                               case TCPOPT_TIMESTAMP:
+                                       if (opsize==TCPOLEN_TIMESTAMP) {
+                                               if ((estab && opt_rx->tstamp_ok) ||
+-                                                  (!estab && init_net.sysctl_tcp_timestamps)) {
++                                                  (!estab && sysctl_tcp_timestamps)) {
+                                                       opt_rx->saw_tstamp = 1;
+                                                       opt_rx->rcv_tsval = ntohl(get_unaligned((__be32 *)ptr));
+                                                       opt_rx->rcv_tsecr = ntohl(get_unaligned((__be32 *)(ptr+4)));
+diff -Nurb linux-2.6.22-590/net/ipv4/tcp_ipv4.c linux-2.6.22-570/net/ipv4/tcp_ipv4.c
+--- linux-2.6.22-590/net/ipv4/tcp_ipv4.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/tcp_ipv4.c       2008-01-23 19:16:05.000000000 -0500
+@@ -71,7 +71,6 @@
+ #include <net/timewait_sock.h>
+ #include <net/xfrm.h>
+ #include <net/netdma.h>
+-#include <net/net_namespace.h>
+ #include <linux/inet.h>
+ #include <linux/ipv6.h>
+@@ -354,7 +353,6 @@
+ void tcp_v4_err(struct sk_buff *skb, u32 info)
+ {
+-      struct net *net = skb->dev->nd_net;
+       struct iphdr *iph = (struct iphdr *)skb->data;
+       struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
+       struct tcp_sock *tp;
+@@ -371,7 +369,7 @@
+       }
+       sk = inet_lookup(&tcp_hashinfo, iph->daddr, th->dest, iph->saddr,
+-                       th->source, inet_iif(skb), net);
++                       th->source, inet_iif(skb));
+       if (!sk) {
+               ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+               return;
+@@ -1501,8 +1499,7 @@
+               return tcp_check_req(sk, skb, req, prev);
+       nsk = inet_lookup_established(&tcp_hashinfo, iph->saddr, th->source,
+-                                    iph->daddr, th->dest, inet_iif(skb),
+-                                    sk->sk_net);
++                                    iph->daddr, th->dest, inet_iif(skb));
+       if (nsk) {
+               if (nsk->sk_state != TCP_TIME_WAIT) {
+@@ -1621,7 +1618,6 @@
+ int tcp_v4_rcv(struct sk_buff *skb)
+ {
+-      struct net *net = skb->dev->nd_net;
+       const struct iphdr *iph;
+       struct tcphdr *th;
+       struct sock *sk;
+@@ -1661,7 +1657,7 @@
+       TCP_SKB_CB(skb)->sacked  = 0;
+       sk = __inet_lookup(&tcp_hashinfo, iph->saddr, th->source,
+-                         iph->daddr, th->dest, inet_iif(skb), net);
++                         iph->daddr, th->dest, inet_iif(skb));
+       if (!sk)
+               goto no_tcp_socket;
+@@ -1736,7 +1732,7 @@
+       case TCP_TW_SYN: {
+               struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo,
+                                                       iph->daddr, th->dest,
+-                                                      inet_iif(skb), net);
++                                                      inet_iif(skb));
+               if (sk2) {
+                       inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
+                       inet_twsk_put(inet_twsk(sk));
+@@ -1770,7 +1766,7 @@
+       int release_it = 0;
+       if (!rt || rt->rt_dst != inet->daddr) {
+-              peer = inet_getpeer(sk->sk_net, inet->daddr, 1);
++              peer = inet_getpeer(inet->daddr, 1);
+               release_it = 1;
+       } else {
+               if (!rt->peer)
+@@ -1795,7 +1791,7 @@
+ int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
+ {
+-      struct inet_peer *peer = inet_getpeer(tw->tw_net, tw->tw_daddr, 1);
++      struct inet_peer *peer = inet_getpeer(tw->tw_daddr, 1);
+       if (peer) {
+               const struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
+@@ -1984,8 +1980,7 @@
+                               if (req->sk &&
+                                       !nx_check(req->sk->sk_nid, VS_WATCH_P | VS_IDENT))
+                                       continue;
+-                              if ((req->rsk_ops->family == st->family) &&
+-                                  (req->sk->sk_net == st->net)) {
++                              if (req->rsk_ops->family == st->family) {
+                                       cur = req;
+                                       goto out;
+                               }
+@@ -2009,8 +2004,6 @@
+       }
+ get_sk:
+       sk_for_each_from(sk, node) {
+-              if (sk->sk_net != st->net)
+-                      continue;
+               vxdprintk(VXD_CBIT(net, 6), "sk: %p [#%d] (from %d)",
+                       sk, sk->sk_nid, nx_current_nid());
+               if (!nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT))
+@@ -2061,10 +2054,11 @@
+               struct hlist_node *node;
+               struct inet_timewait_sock *tw;
+-              read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
++              /* We can reschedule _before_ having picked the target: */
++              cond_resched_softirq();
++
++              read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
+               sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
+-                      if (sk->sk_net != st->net)
+-                              continue;
+                       vxdprintk(VXD_CBIT(net, 6),
+                               "sk,egf: %p [#%d] (from %d)",
+                               sk, sk->sk_nid, nx_current_nid());
+@@ -2078,8 +2072,6 @@
+               st->state = TCP_SEQ_STATE_TIME_WAIT;
+               inet_twsk_for_each(tw, node,
+                                  &tcp_hashinfo.ehash[st->bucket].twchain) {
+-                      if (tw->tw_net != st->net)
+-                              continue;
+                       vxdprintk(VXD_CBIT(net, 6),
+                               "tw: %p [#%d] (from %d)",
+                               tw, tw->tw_nid, nx_current_nid());
+@@ -2090,7 +2082,7 @@
+                       rc = tw;
+                       goto out;
+               }
+-              read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
++              read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
+               st->state = TCP_SEQ_STATE_ESTABLISHED;
+       }
+ out:
+@@ -2110,8 +2102,7 @@
+               tw = cur;
+               tw = tw_next(tw);
+ get_tw:
+-              while (tw && ((tw->tw_net != st->net) || 
+-                                      (tw->tw_family != st->family) ||
++              while (tw && (tw->tw_family != st->family ||
+                       !nx_check(tw->tw_nid, VS_WATCH_P | VS_IDENT))) {
+                       tw = tw_next(tw);
+               }
+@@ -2119,11 +2110,14 @@
+                       cur = tw;
+                       goto out;
+               }
+-              read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
++              read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
+               st->state = TCP_SEQ_STATE_ESTABLISHED;
++              /* We can reschedule between buckets: */
++              cond_resched_softirq();
++
+               if (++st->bucket < tcp_hashinfo.ehash_size) {
+-                      read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
++                      read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
+                       sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
+               } else {
+                       cur = NULL;
+@@ -2136,8 +2130,6 @@
+               vxdprintk(VXD_CBIT(net, 6),
+                       "sk,egn: %p [#%d] (from %d)",
+                       sk, sk->sk_nid, nx_current_nid());
+-              if (sk->sk_net != st->net)
+-                      continue;
+               if (!nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT))
+                       continue;
+               if (sk->sk_family == st->family)
+@@ -2175,6 +2167,7 @@
+       if (!rc) {
+               inet_listen_unlock(&tcp_hashinfo);
++              local_bh_disable();
+               st->state = TCP_SEQ_STATE_ESTABLISHED;
+               rc        = established_get_idx(seq, pos);
+       }
+@@ -2207,6 +2200,7 @@
+               rc = listening_get_next(seq, v);
+               if (!rc) {
+                       inet_listen_unlock(&tcp_hashinfo);
++                      local_bh_disable();
+                       st->state = TCP_SEQ_STATE_ESTABLISHED;
+                       rc        = established_get_first(seq);
+               }
+@@ -2238,7 +2232,8 @@
+       case TCP_SEQ_STATE_TIME_WAIT:
+       case TCP_SEQ_STATE_ESTABLISHED:
+               if (v)
+-                      read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
++                      read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
++              local_bh_enable();
+               break;
+       }
+ }
+@@ -2267,7 +2262,6 @@
+               goto out_kfree;
+       seq          = file->private_data;
+       seq->private = s;
+-      s->net = get_net(PROC_NET(inode));
+ out:
+       return rc;
+ out_kfree:
+@@ -2275,30 +2269,20 @@
+       goto out;
+ }
+-static int tcp_seq_release(struct inode *inode, struct file *file)
 -{
--      int idx, err;
--      int s_idx = cb->args[0];
--      struct net_device *dev;
--      struct inet6_dev *idev;
--
--      read_lock(&dev_base_lock);
--      idx = 0;
--      for_each_netdev(dev) {
--              if (idx < s_idx)
--                      goto cont;
--              if ((idev = in6_dev_get(dev)) == NULL)
--                      goto cont;
--              err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid,
--                              cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
--              in6_dev_put(idev);
--              if (err <= 0)
--                      break;
--cont:
--              idx++;
--      }
--      read_unlock(&dev_base_lock);
--      cb->args[0] = idx;
--
--      return skb->len;
+-      struct seq_file *seq = file->private_data;
+-      struct tcp_iter_state *st = seq->private;
+-      put_net(st->net);
+-      return seq_release_private(inode, file);
 -}
 -
--void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
--{
--      struct sk_buff *skb;
--      int err = -ENOBUFS;
--
--      skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC);
--      if (skb == NULL)
--              goto errout;
--
--      err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
--      if (err < 0) {
--              /* -EMSGSIZE implies BUG in inet6_if_nlmsg_size() */
--              WARN_ON(err == -EMSGSIZE);
--              kfree_skb(skb);
--              goto errout;
+-int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo)
++int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
+ {
+       int rc = 0;
+       struct proc_dir_entry *p;
+       if (!afinfo)
+               return -EINVAL;
+-      if (net == &init_net) {
+       afinfo->seq_fops->owner         = afinfo->owner;
+       afinfo->seq_fops->open          = tcp_seq_open;
+       afinfo->seq_fops->read          = seq_read;
+       afinfo->seq_fops->llseek        = seq_lseek;
+-              afinfo->seq_fops->release       = tcp_seq_release;
 -      }
--      err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
--errout:
--      if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
--}
--
--static inline size_t inet6_prefix_nlmsg_size(void)
++      afinfo->seq_fops->release       = seq_release_private;
+-      p = proc_net_fops_create(net, afinfo->name, S_IRUGO, afinfo->seq_fops);
++      p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);
+       if (p)
+               p->data = afinfo;
+       else
+@@ -2306,12 +2290,11 @@
+       return rc;
+ }
+-void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo)
++void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo)
+ {
+       if (!afinfo)
+               return;
+-      proc_net_remove(net, afinfo->name);
+-      if (net == &init_net)
++      proc_net_remove(afinfo->name);
+       memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
+ }
+@@ -2456,29 +2439,14 @@
+       .seq_fops       = &tcp4_seq_fops,
+ };
+-static int tcp4_proc_net_init(struct net *net)
 -{
--      return NLMSG_ALIGN(sizeof(struct prefixmsg))
--             + nla_total_size(sizeof(struct in6_addr))
--             + nla_total_size(sizeof(struct prefix_cacheinfo));
+-      return tcp_proc_register(net, &tcp4_seq_afinfo);
 -}
 -
--static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
--                           struct prefix_info *pinfo, u32 pid, u32 seq,
--                           int event, unsigned int flags)
+-static void tcp4_proc_net_exit(struct net *net)
 -{
--      struct prefixmsg *pmsg;
--      struct nlmsghdr *nlh;
--      struct prefix_cacheinfo ci;
--
--      nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags);
--      if (nlh == NULL)
--              return -EMSGSIZE;
--
--      pmsg = nlmsg_data(nlh);
--      pmsg->prefix_family = AF_INET6;
--      pmsg->prefix_pad1 = 0;
--      pmsg->prefix_pad2 = 0;
--      pmsg->prefix_ifindex = idev->dev->ifindex;
--      pmsg->prefix_len = pinfo->prefix_len;
--      pmsg->prefix_type = pinfo->type;
--      pmsg->prefix_pad3 = 0;
--      pmsg->prefix_flags = 0;
--      if (pinfo->onlink)
--              pmsg->prefix_flags |= IF_PREFIX_ONLINK;
--      if (pinfo->autoconf)
--              pmsg->prefix_flags |= IF_PREFIX_AUTOCONF;
--
--      NLA_PUT(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix);
--
--      ci.preferred_time = ntohl(pinfo->prefered);
--      ci.valid_time = ntohl(pinfo->valid);
--      NLA_PUT(skb, PREFIX_CACHEINFO, sizeof(ci), &ci);
--
--      return nlmsg_end(skb, nlh);
--
--nla_put_failure:
--      nlmsg_cancel(skb, nlh);
--      return -EMSGSIZE;
+-      tcp_proc_unregister(net, &tcp4_seq_afinfo);
 -}
 -
--static void inet6_prefix_notify(int event, struct inet6_dev *idev,
--                       struct prefix_info *pinfo)
--{
--      struct sk_buff *skb;
--      int err = -ENOBUFS;
--
--      skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC);
--      if (skb == NULL)
--              goto errout;
+-static struct pernet_operations tcp4_proc_net_ops = {
+-      .init = tcp4_proc_net_init,
+-      .exit = tcp4_proc_net_exit,
+-};
 -
--      err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
--      if (err < 0) {
--              /* -EMSGSIZE implies BUG in inet6_prefix_nlmsg_size() */
--              WARN_ON(err == -EMSGSIZE);
+ int __init tcp4_proc_init(void)
+ {
+-      return register_pernet_subsys(&tcp4_proc_net_ops);
++      return tcp_proc_register(&tcp4_seq_afinfo);
+ }
+ void tcp4_proc_exit(void)
+ {
+-      unregister_pernet_subsys(&tcp4_proc_net_ops);
++      tcp_proc_unregister(&tcp4_seq_afinfo);
+ }
+ #endif /* CONFIG_PROC_FS */
+@@ -2540,5 +2508,6 @@
+ EXPORT_SYMBOL(tcp_proc_register);
+ EXPORT_SYMBOL(tcp_proc_unregister);
+ #endif
++EXPORT_SYMBOL(sysctl_local_port_range);
+ EXPORT_SYMBOL(sysctl_tcp_low_latency);
+diff -Nurb linux-2.6.22-590/net/ipv4/tcp_ipv4.c.orig linux-2.6.22-570/net/ipv4/tcp_ipv4.c.orig
+--- linux-2.6.22-590/net/ipv4/tcp_ipv4.c.orig  1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/tcp_ipv4.c.orig  2008-01-23 19:15:56.000000000 -0500
+@@ -0,0 +1,2483 @@
++/*
++ * INET               An implementation of the TCP/IP protocol suite for the LINUX
++ *            operating system.  INET is implemented using the  BSD Socket
++ *            interface as the means of communication with the user level.
++ *
++ *            Implementation of the Transmission Control Protocol(TCP).
++ *
++ * Version:   $Id: tcp_ipv4.c,v 1.240 2002/02/01 22:01:04 davem Exp $
++ *
++ *            IPv4 specific functions
++ *
++ *
++ *            code split from:
++ *            linux/ipv4/tcp.c
++ *            linux/ipv4/tcp_input.c
++ *            linux/ipv4/tcp_output.c
++ *
++ *            See tcp.c for author information
++ *
++ *    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.
++ */
++
++/*
++ * Changes:
++ *            David S. Miller :       New socket lookup architecture.
++ *                                    This code is dedicated to John Dyson.
++ *            David S. Miller :       Change semantics of established hash,
++ *                                    half is devoted to TIME_WAIT sockets
++ *                                    and the rest go in the other half.
++ *            Andi Kleen :            Add support for syncookies and fixed
++ *                                    some bugs: ip options weren't passed to
++ *                                    the TCP layer, missed a check for an
++ *                                    ACK bit.
++ *            Andi Kleen :            Implemented fast path mtu discovery.
++ *                                    Fixed many serious bugs in the
++ *                                    request_sock handling and moved
++ *                                    most of it into the af independent code.
++ *                                    Added tail drop and some other bugfixes.
++ *                                    Added new listen semantics.
++ *            Mike McLagan    :       Routing by source
++ *    Juan Jose Ciarlante:            ip_dynaddr bits
++ *            Andi Kleen:             various fixes.
++ *    Vitaly E. Lavrov        :       Transparent proxy revived after year
++ *                                    coma.
++ *    Andi Kleen              :       Fix new listen.
++ *    Andi Kleen              :       Fix accept error reporting.
++ *    YOSHIFUJI Hideaki @USAGI and:   Support IPV6_V6ONLY socket option, which
++ *    Alexey Kuznetsov                allow both IPv4 and IPv6 sockets to bind
++ *                                    a single port at the same time.
++ */
++
++
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/module.h>
++#include <linux/random.h>
++#include <linux/cache.h>
++#include <linux/jhash.h>
++#include <linux/init.h>
++#include <linux/times.h>
++
++#include <net/icmp.h>
++#include <net/inet_hashtables.h>
++#include <net/tcp.h>
++#include <net/transp_v6.h>
++#include <net/ipv6.h>
++#include <net/inet_common.h>
++#include <net/timewait_sock.h>
++#include <net/xfrm.h>
++#include <net/netdma.h>
++
++#include <linux/inet.h>
++#include <linux/ipv6.h>
++#include <linux/stddef.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++
++#include <linux/crypto.h>
++#include <linux/scatterlist.h>
++
++int sysctl_tcp_tw_reuse __read_mostly;
++int sysctl_tcp_low_latency __read_mostly;
++
++/* Check TCP sequence numbers in ICMP packets. */
++#define ICMP_MIN_LENGTH 8
++
++/* Socket used for sending RSTs */
++static struct socket *tcp_socket __read_mostly;
++
++void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
++
++#ifdef CONFIG_TCP_MD5SIG
++static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk,
++                                                 __be32 addr);
++static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
++                                 __be32 saddr, __be32 daddr,
++                                 struct tcphdr *th, int protocol,
++                                 int tcplen);
++#endif
++
++struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
++      .lhash_lock  = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock),
++      .lhash_users = ATOMIC_INIT(0),
++      .lhash_wait  = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait),
++};
++
++static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
++{
++      return inet_csk_get_port(&tcp_hashinfo, sk, snum,
++                               inet_csk_bind_conflict);
++}
++
++static void tcp_v4_hash(struct sock *sk)
++{
++      inet_hash(&tcp_hashinfo, sk);
++}
++
++void tcp_unhash(struct sock *sk)
++{
++      inet_unhash(&tcp_hashinfo, sk);
++}
++
++static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb)
++{
++      return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
++                                        ip_hdr(skb)->saddr,
++                                        tcp_hdr(skb)->dest,
++                                        tcp_hdr(skb)->source);
++}
++
++int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
++{
++      const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw);
++      struct tcp_sock *tp = tcp_sk(sk);
++
++      /* With PAWS, it is safe from the viewpoint
++         of data integrity. Even without PAWS it is safe provided sequence
++         spaces do not overlap i.e. at data rates <= 80Mbit/sec.
++
++         Actually, the idea is close to VJ's one, only timestamp cache is
++         held not per host, but per port pair and TW bucket is used as state
++         holder.
++
++         If TW bucket has been already destroyed we fall back to VJ's scheme
++         and use initial timestamp retrieved from peer table.
++       */
++      if (tcptw->tw_ts_recent_stamp &&
++          (twp == NULL || (sysctl_tcp_tw_reuse &&
++                           get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {
++              tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
++              if (tp->write_seq == 0)
++                      tp->write_seq = 1;
++              tp->rx_opt.ts_recent       = tcptw->tw_ts_recent;
++              tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
++              sock_hold(sktw);
++              return 1;
++      }
++
++      return 0;
++}
++
++EXPORT_SYMBOL_GPL(tcp_twsk_unique);
++
++/* This will initiate an outgoing connection. */
++int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
++{
++      struct inet_sock *inet = inet_sk(sk);
++      struct tcp_sock *tp = tcp_sk(sk);
++      struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
++      struct rtable *rt;
++      __be32 daddr, nexthop;
++      int tmp;
++      int err;
++
++      if (addr_len < sizeof(struct sockaddr_in))
++              return -EINVAL;
++
++      if (usin->sin_family != AF_INET)
++              return -EAFNOSUPPORT;
++
++      nexthop = daddr = usin->sin_addr.s_addr;
++      if (inet->opt && inet->opt->srr) {
++              if (!daddr)
++                      return -EINVAL;
++              nexthop = inet->opt->faddr;
++      }
++
++      tmp = ip_route_connect(&rt, nexthop, inet->saddr,
++                             RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
++                             IPPROTO_TCP,
++                             inet->sport, usin->sin_port, sk, 1);
++      if (tmp < 0) {
++              if (tmp == -ENETUNREACH)
++                      IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
++              return tmp;
++      }
++
++      if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
++              ip_rt_put(rt);
++              return -ENETUNREACH;
++      }
++
++      if (!inet->opt || !inet->opt->srr)
++              daddr = rt->rt_dst;
++
++      if (!inet->saddr)
++              inet->saddr = rt->rt_src;
++      inet->rcv_saddr = inet->saddr;
++
++      if (tp->rx_opt.ts_recent_stamp && inet->daddr != daddr) {
++              /* Reset inherited state */
++              tp->rx_opt.ts_recent       = 0;
++              tp->rx_opt.ts_recent_stamp = 0;
++              tp->write_seq              = 0;
++      }
++
++      if (tcp_death_row.sysctl_tw_recycle &&
++          !tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) {
++              struct inet_peer *peer = rt_get_peer(rt);
++              /*
++               * VJ's idea. We save last timestamp seen from
++               * the destination in peer table, when entering state
++               * TIME-WAIT * and initialize rx_opt.ts_recent from it,
++               * when trying new connection.
++               */
++              if (peer != NULL &&
++                  peer->tcp_ts_stamp + TCP_PAWS_MSL >= get_seconds()) {
++                      tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
++                      tp->rx_opt.ts_recent = peer->tcp_ts;
++              }
++      }
++
++      inet->dport = usin->sin_port;
++      inet->daddr = daddr;
++
++      inet_csk(sk)->icsk_ext_hdr_len = 0;
++      if (inet->opt)
++              inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen;
++
++      tp->rx_opt.mss_clamp = 536;
++
++      /* Socket identity is still unknown (sport may be zero).
++       * However we set state to SYN-SENT and not releasing socket
++       * lock select source port, enter ourselves into the hash tables and
++       * complete initialization after this.
++       */
++      tcp_set_state(sk, TCP_SYN_SENT);
++      err = inet_hash_connect(&tcp_death_row, sk);
++      if (err)
++              goto failure;
++
++      err = ip_route_newports(&rt, IPPROTO_TCP,
++                              inet->sport, inet->dport, sk);
++      if (err)
++              goto failure;
++
++      /* OK, now commit destination to socket.  */
++      sk->sk_gso_type = SKB_GSO_TCPV4;
++      sk_setup_caps(sk, &rt->u.dst);
++
++      if (!tp->write_seq)
++              tp->write_seq = secure_tcp_sequence_number(inet->saddr,
++                                                         inet->daddr,
++                                                         inet->sport,
++                                                         usin->sin_port);
++
++      inet->id = tp->write_seq ^ jiffies;
++
++      err = tcp_connect(sk);
++      rt = NULL;
++      if (err)
++              goto failure;
++
++      return 0;
++
++failure:
++      /*
++       * This unhashes the socket and releases the local port,
++       * if necessary.
++       */
++      tcp_set_state(sk, TCP_CLOSE);
++      ip_rt_put(rt);
++      sk->sk_route_caps = 0;
++      inet->dport = 0;
++      return err;
++}
++
++/*
++ * This routine does path mtu discovery as defined in RFC1191.
++ */
++static void do_pmtu_discovery(struct sock *sk, struct iphdr *iph, u32 mtu)
++{
++      struct dst_entry *dst;
++      struct inet_sock *inet = inet_sk(sk);
++
++      /* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs
++       * send out by Linux are always <576bytes so they should go through
++       * unfragmented).
++       */
++      if (sk->sk_state == TCP_LISTEN)
++              return;
++
++      /* We don't check in the destentry if pmtu discovery is forbidden
++       * on this route. We just assume that no packet_to_big packets
++       * are send back when pmtu discovery is not active.
++       * There is a small race when the user changes this flag in the
++       * route, but I think that's acceptable.
++       */
++      if ((dst = __sk_dst_check(sk, 0)) == NULL)
++              return;
++
++      dst->ops->update_pmtu(dst, mtu);
++
++      /* Something is about to be wrong... Remember soft error
++       * for the case, if this connection will not able to recover.
++       */
++      if (mtu < dst_mtu(dst) && ip_dont_fragment(sk, dst))
++              sk->sk_err_soft = EMSGSIZE;
++
++      mtu = dst_mtu(dst);
++
++      if (inet->pmtudisc != IP_PMTUDISC_DONT &&
++          inet_csk(sk)->icsk_pmtu_cookie > mtu) {
++              tcp_sync_mss(sk, mtu);
++
++              /* Resend the TCP packet because it's
++               * clear that the old packet has been
++               * dropped. This is the new "fast" path mtu
++               * discovery.
++               */
++              tcp_simple_retransmit(sk);
++      } /* else let the usual retransmit timer handle it */
++}
++
++/*
++ * This routine is called by the ICMP module when it gets some
++ * sort of error condition.  If err < 0 then the socket should
++ * be closed and the error returned to the user.  If err > 0
++ * it's just the icmp type << 8 | icmp code.  After adjustment
++ * header points to the first 8 bytes of the tcp header.  We need
++ * to find the appropriate port.
++ *
++ * The locking strategy used here is very "optimistic". When
++ * someone else accesses the socket the ICMP is just dropped
++ * and for some paths there is no check at all.
++ * A more general error queue to queue errors for later handling
++ * is probably better.
++ *
++ */
++
++void tcp_v4_err(struct sk_buff *skb, u32 info)
++{
++      struct iphdr *iph = (struct iphdr *)skb->data;
++      struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
++      struct tcp_sock *tp;
++      struct inet_sock *inet;
++      const int type = icmp_hdr(skb)->type;
++      const int code = icmp_hdr(skb)->code;
++      struct sock *sk;
++      __u32 seq;
++      int err;
++
++      if (skb->len < (iph->ihl << 2) + 8) {
++              ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
++              return;
++      }
++
++      sk = inet_lookup(&tcp_hashinfo, iph->daddr, th->dest, iph->saddr,
++                       th->source, inet_iif(skb));
++      if (!sk) {
++              ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
++              return;
++      }
++      if (sk->sk_state == TCP_TIME_WAIT) {
++              inet_twsk_put(inet_twsk(sk));
++              return;
++      }
++
++      bh_lock_sock(sk);
++      /* If too many ICMPs get dropped on busy
++       * servers this needs to be solved differently.
++       */
++      if (sock_owned_by_user(sk))
++              NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS);
++
++      if (sk->sk_state == TCP_CLOSE)
++              goto out;
++
++      tp = tcp_sk(sk);
++      seq = ntohl(th->seq);
++      if (sk->sk_state != TCP_LISTEN &&
++          !between(seq, tp->snd_una, tp->snd_nxt)) {
++              NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
++              goto out;
++      }
++
++      switch (type) {
++      case ICMP_SOURCE_QUENCH:
++              /* Just silently ignore these. */
++              goto out;
++      case ICMP_PARAMETERPROB:
++              err = EPROTO;
++              break;
++      case ICMP_DEST_UNREACH:
++              if (code > NR_ICMP_UNREACH)
++                      goto out;
++
++              if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
++                      if (!sock_owned_by_user(sk))
++                              do_pmtu_discovery(sk, iph, info);
++                      goto out;
++              }
++
++              err = icmp_err_convert[code].errno;
++              break;
++      case ICMP_TIME_EXCEEDED:
++              err = EHOSTUNREACH;
++              break;
++      default:
++              goto out;
++      }
++
++      switch (sk->sk_state) {
++              struct request_sock *req, **prev;
++      case TCP_LISTEN:
++              if (sock_owned_by_user(sk))
++                      goto out;
++
++              req = inet_csk_search_req(sk, &prev, th->dest,
++                                        iph->daddr, iph->saddr);
++              if (!req)
++                      goto out;
++
++              /* ICMPs are not backlogged, hence we cannot get
++                 an established socket here.
++               */
++              BUG_TRAP(!req->sk);
++
++              if (seq != tcp_rsk(req)->snt_isn) {
++                      NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
++                      goto out;
++              }
++
++              /*
++               * Still in SYN_RECV, just remove it silently.
++               * There is no good way to pass the error to the newly
++               * created socket, and POSIX does not want network
++               * errors returned from accept().
++               */
++              inet_csk_reqsk_queue_drop(sk, req, prev);
++              goto out;
++
++      case TCP_SYN_SENT:
++      case TCP_SYN_RECV:  /* Cannot happen.
++                             It can f.e. if SYNs crossed.
++                           */
++              if (!sock_owned_by_user(sk)) {
++                      sk->sk_err = err;
++
++                      sk->sk_error_report(sk);
++
++                      tcp_done(sk);
++              } else {
++                      sk->sk_err_soft = err;
++              }
++              goto out;
++      }
++
++      /* If we've already connected we will keep trying
++       * until we time out, or the user gives up.
++       *
++       * rfc1122 4.2.3.9 allows to consider as hard errors
++       * only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
++       * but it is obsoleted by pmtu discovery).
++       *
++       * Note, that in modern internet, where routing is unreliable
++       * and in each dark corner broken firewalls sit, sending random
++       * errors ordered by their masters even this two messages finally lose
++       * their original sense (even Linux sends invalid PORT_UNREACHs)
++       *
++       * Now we are in compliance with RFCs.
++       *                                                      --ANK (980905)
++       */
++
++      inet = inet_sk(sk);
++      if (!sock_owned_by_user(sk) && inet->recverr) {
++              sk->sk_err = err;
++              sk->sk_error_report(sk);
++      } else  { /* Only an error on timeout */
++              sk->sk_err_soft = err;
++      }
++
++out:
++      bh_unlock_sock(sk);
++      sock_put(sk);
++}
++
++/* This routine computes an IPv4 TCP checksum. */
++void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
++{
++      struct inet_sock *inet = inet_sk(sk);
++      struct tcphdr *th = tcp_hdr(skb);
++
++      if (skb->ip_summed == CHECKSUM_PARTIAL) {
++              th->check = ~tcp_v4_check(len, inet->saddr,
++                                        inet->daddr, 0);
++              skb->csum_start = skb_transport_header(skb) - skb->head;
++              skb->csum_offset = offsetof(struct tcphdr, check);
++      } else {
++              th->check = tcp_v4_check(len, inet->saddr, inet->daddr,
++                                       csum_partial((char *)th,
++                                                    th->doff << 2,
++                                                    skb->csum));
++      }
++}
++
++int tcp_v4_gso_send_check(struct sk_buff *skb)
++{
++      const struct iphdr *iph;
++      struct tcphdr *th;
++
++      if (!pskb_may_pull(skb, sizeof(*th)))
++              return -EINVAL;
++
++      iph = ip_hdr(skb);
++      th = tcp_hdr(skb);
++
++      th->check = 0;
++      th->check = ~tcp_v4_check(skb->len, iph->saddr, iph->daddr, 0);
++      skb->csum_start = skb_transport_header(skb) - skb->head;
++      skb->csum_offset = offsetof(struct tcphdr, check);
++      skb->ip_summed = CHECKSUM_PARTIAL;
++      return 0;
++}
++
++/*
++ *    This routine will send an RST to the other tcp.
++ *
++ *    Someone asks: why I NEVER use socket parameters (TOS, TTL etc.)
++ *                  for reset.
++ *    Answer: if a packet caused RST, it is not for a socket
++ *            existing in our system, if it is matched to a socket,
++ *            it is just duplicate segment or bug in other side's TCP.
++ *            So that we build reply only basing on parameters
++ *            arrived with segment.
++ *    Exception: precedence violation. We do not implement it in any case.
++ */
++
++static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
++{
++      struct tcphdr *th = tcp_hdr(skb);
++      struct {
++              struct tcphdr th;
++#ifdef CONFIG_TCP_MD5SIG
++              __be32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)];
++#endif
++      } rep;
++      struct ip_reply_arg arg;
++#ifdef CONFIG_TCP_MD5SIG
++      struct tcp_md5sig_key *key;
++#endif
++
++      /* Never send a reset in response to a reset. */
++      if (th->rst)
++              return;
++
++      if (((struct rtable *)skb->dst)->rt_type != RTN_LOCAL)
++              return;
++
++      /* Swap the send and the receive. */
++      memset(&rep, 0, sizeof(rep));
++      rep.th.dest   = th->source;
++      rep.th.source = th->dest;
++      rep.th.doff   = sizeof(struct tcphdr) / 4;
++      rep.th.rst    = 1;
++
++      if (th->ack) {
++              rep.th.seq = th->ack_seq;
++      } else {
++              rep.th.ack = 1;
++              rep.th.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin +
++                                     skb->len - (th->doff << 2));
++      }
++
++      memset(&arg, 0, sizeof(arg));
++      arg.iov[0].iov_base = (unsigned char *)&rep;
++      arg.iov[0].iov_len  = sizeof(rep.th);
++
++#ifdef CONFIG_TCP_MD5SIG
++      key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr) : NULL;
++      if (key) {
++              rep.opt[0] = htonl((TCPOPT_NOP << 24) |
++                                 (TCPOPT_NOP << 16) |
++                                 (TCPOPT_MD5SIG << 8) |
++                                 TCPOLEN_MD5SIG);
++              /* Update length and the length the header thinks exists */
++              arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
++              rep.th.doff = arg.iov[0].iov_len / 4;
++
++              tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[1],
++                                      key,
++                                      ip_hdr(skb)->daddr,
++                                      ip_hdr(skb)->saddr,
++                                      &rep.th, IPPROTO_TCP,
++                                      arg.iov[0].iov_len);
++      }
++#endif
++      arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
++                                    ip_hdr(skb)->saddr, /* XXX */
++                                    sizeof(struct tcphdr), IPPROTO_TCP, 0);
++      arg.csumoffset = offsetof(struct tcphdr, check) / 2;
++
++      ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
++
++      TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
++      TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
++}
++
++/* The code following below sending ACKs in SYN-RECV and TIME-WAIT states
++   outside socket context is ugly, certainly. What can I do?
++ */
++
++static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
++                          struct sk_buff *skb, u32 seq, u32 ack,
++                          u32 win, u32 ts)
++{
++      struct tcphdr *th = tcp_hdr(skb);
++      struct {
++              struct tcphdr th;
++              __be32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2)
++#ifdef CONFIG_TCP_MD5SIG
++                         + (TCPOLEN_MD5SIG_ALIGNED >> 2)
++#endif
++                      ];
++      } rep;
++      struct ip_reply_arg arg;
++#ifdef CONFIG_TCP_MD5SIG
++      struct tcp_md5sig_key *key;
++      struct tcp_md5sig_key tw_key;
++#endif
++
++      memset(&rep.th, 0, sizeof(struct tcphdr));
++      memset(&arg, 0, sizeof(arg));
++
++      arg.iov[0].iov_base = (unsigned char *)&rep;
++      arg.iov[0].iov_len  = sizeof(rep.th);
++      if (ts) {
++              rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
++                                 (TCPOPT_TIMESTAMP << 8) |
++                                 TCPOLEN_TIMESTAMP);
++              rep.opt[1] = htonl(tcp_time_stamp);
++              rep.opt[2] = htonl(ts);
++              arg.iov[0].iov_len += TCPOLEN_TSTAMP_ALIGNED;
++      }
++
++      /* Swap the send and the receive. */
++      rep.th.dest    = th->source;
++      rep.th.source  = th->dest;
++      rep.th.doff    = arg.iov[0].iov_len / 4;
++      rep.th.seq     = htonl(seq);
++      rep.th.ack_seq = htonl(ack);
++      rep.th.ack     = 1;
++      rep.th.window  = htons(win);
++
++#ifdef CONFIG_TCP_MD5SIG
++      /*
++       * The SKB holds an imcoming packet, but may not have a valid ->sk
++       * pointer. This is especially the case when we're dealing with a
++       * TIME_WAIT ack, because the sk structure is long gone, and only
++       * the tcp_timewait_sock remains. So the md5 key is stashed in that
++       * structure, and we use it in preference.  I believe that (twsk ||
++       * skb->sk) holds true, but we program defensively.
++       */
++      if (!twsk && skb->sk) {
++              key = tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr);
++      } else if (twsk && twsk->tw_md5_keylen) {
++              tw_key.key = twsk->tw_md5_key;
++              tw_key.keylen = twsk->tw_md5_keylen;
++              key = &tw_key;
++      } else
++              key = NULL;
++
++      if (key) {
++              int offset = (ts) ? 3 : 0;
++
++              rep.opt[offset++] = htonl((TCPOPT_NOP << 24) |
++                                        (TCPOPT_NOP << 16) |
++                                        (TCPOPT_MD5SIG << 8) |
++                                        TCPOLEN_MD5SIG);
++              arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
++              rep.th.doff = arg.iov[0].iov_len/4;
++
++              tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[offset],
++                                      key,
++                                      ip_hdr(skb)->daddr,
++                                      ip_hdr(skb)->saddr,
++                                      &rep.th, IPPROTO_TCP,
++                                      arg.iov[0].iov_len);
++      }
++#endif
++      arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
++                                    ip_hdr(skb)->saddr, /* XXX */
++                                    arg.iov[0].iov_len, IPPROTO_TCP, 0);
++      arg.csumoffset = offsetof(struct tcphdr, check) / 2;
++      if (twsk)
++              arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
++
++      ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
++
++      TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
++}
++
++static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
++{
++      struct inet_timewait_sock *tw = inet_twsk(sk);
++      struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
++
++      tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
++                      tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
++                      tcptw->tw_ts_recent);
++
++      inet_twsk_put(tw);
++}
++
++static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
++                                struct request_sock *req)
++{
++      tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1,
++                      tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
++                      req->ts_recent);
++}
++
++/*
++ *    Send a SYN-ACK after having received an ACK.
++ *    This still operates on a request_sock only, not on a big
++ *    socket.
++ */
++static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
++                            struct dst_entry *dst)
++{
++      const struct inet_request_sock *ireq = inet_rsk(req);
++      int err = -1;
++      struct sk_buff * skb;
++
++      /* First, grab a route. */
++      if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL)
++              goto out;
++
++      skb = tcp_make_synack(sk, dst, req);
++
++      if (skb) {
++              struct tcphdr *th = tcp_hdr(skb);
++
++              th->check = tcp_v4_check(skb->len,
++                                       ireq->loc_addr,
++                                       ireq->rmt_addr,
++                                       csum_partial((char *)th, skb->len,
++                                                    skb->csum));
++
++              err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
++                                          ireq->rmt_addr,
++                                          ireq->opt);
++              err = net_xmit_eval(err);
++      }
++
++out:
++      dst_release(dst);
++      return err;
++}
++
++/*
++ *    IPv4 request_sock destructor.
++ */
++static void tcp_v4_reqsk_destructor(struct request_sock *req)
++{
++      kfree(inet_rsk(req)->opt);
++}
++
++#ifdef CONFIG_SYN_COOKIES
++static void syn_flood_warning(struct sk_buff *skb)
++{
++      static unsigned long warntime;
++
++      if (time_after(jiffies, (warntime + HZ * 60))) {
++              warntime = jiffies;
++              printk(KERN_INFO
++                     "possible SYN flooding on port %d. Sending cookies.\n",
++                     ntohs(tcp_hdr(skb)->dest));
++      }
++}
++#endif
++
++/*
++ * Save and compile IPv4 options into the request_sock if needed.
++ */
++static struct ip_options *tcp_v4_save_options(struct sock *sk,
++                                            struct sk_buff *skb)
++{
++      struct ip_options *opt = &(IPCB(skb)->opt);
++      struct ip_options *dopt = NULL;
++
++      if (opt && opt->optlen) {
++              int opt_size = optlength(opt);
++              dopt = kmalloc(opt_size, GFP_ATOMIC);
++              if (dopt) {
++                      if (ip_options_echo(dopt, skb)) {
++                              kfree(dopt);
++                              dopt = NULL;
++                      }
++              }
++      }
++      return dopt;
++}
++
++#ifdef CONFIG_TCP_MD5SIG
++/*
++ * RFC2385 MD5 checksumming requires a mapping of
++ * IP address->MD5 Key.
++ * We need to maintain these in the sk structure.
++ */
++
++/* Find the Key structure for an address.  */
++static struct tcp_md5sig_key *
++                      tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
++{
++      struct tcp_sock *tp = tcp_sk(sk);
++      int i;
++
++      if (!tp->md5sig_info || !tp->md5sig_info->entries4)
++              return NULL;
++      for (i = 0; i < tp->md5sig_info->entries4; i++) {
++              if (tp->md5sig_info->keys4[i].addr == addr)
++                      return &tp->md5sig_info->keys4[i].base;
++      }
++      return NULL;
++}
++
++struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
++                                       struct sock *addr_sk)
++{
++      return tcp_v4_md5_do_lookup(sk, inet_sk(addr_sk)->daddr);
++}
++
++EXPORT_SYMBOL(tcp_v4_md5_lookup);
++
++static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk,
++                                                    struct request_sock *req)
++{
++      return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr);
++}
++
++/* This can be called on a newly created socket, from other files */
++int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
++                    u8 *newkey, u8 newkeylen)
++{
++      /* Add Key to the list */
++      struct tcp4_md5sig_key *key;
++      struct tcp_sock *tp = tcp_sk(sk);
++      struct tcp4_md5sig_key *keys;
++
++      key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr);
++      if (key) {
++              /* Pre-existing entry - just update that one. */
++              kfree(key->base.key);
++              key->base.key = newkey;
++              key->base.keylen = newkeylen;
++      } else {
++              struct tcp_md5sig_info *md5sig;
++
++              if (!tp->md5sig_info) {
++                      tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info),
++                                                GFP_ATOMIC);
++                      if (!tp->md5sig_info) {
++                              kfree(newkey);
++                              return -ENOMEM;
++                      }
++                      sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
++              }
++              if (tcp_alloc_md5sig_pool() == NULL) {
++                      kfree(newkey);
++                      return -ENOMEM;
++              }
++              md5sig = tp->md5sig_info;
++
++              if (md5sig->alloced4 == md5sig->entries4) {
++                      keys = kmalloc((sizeof(*keys) *
++                                      (md5sig->entries4 + 1)), GFP_ATOMIC);
++                      if (!keys) {
++                              kfree(newkey);
++                              tcp_free_md5sig_pool();
++                              return -ENOMEM;
++                      }
++
++                      if (md5sig->entries4)
++                              memcpy(keys, md5sig->keys4,
++                                     sizeof(*keys) * md5sig->entries4);
++
++                      /* Free old key list, and reference new one */
++                      if (md5sig->keys4)
++                              kfree(md5sig->keys4);
++                      md5sig->keys4 = keys;
++                      md5sig->alloced4++;
++              }
++              md5sig->entries4++;
++              md5sig->keys4[md5sig->entries4 - 1].addr        = addr;
++              md5sig->keys4[md5sig->entries4 - 1].base.key    = newkey;
++              md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen;
++      }
++      return 0;
++}
++
++EXPORT_SYMBOL(tcp_v4_md5_do_add);
++
++static int tcp_v4_md5_add_func(struct sock *sk, struct sock *addr_sk,
++                             u8 *newkey, u8 newkeylen)
++{
++      return tcp_v4_md5_do_add(sk, inet_sk(addr_sk)->daddr,
++                               newkey, newkeylen);
++}
++
++int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
++{
++      struct tcp_sock *tp = tcp_sk(sk);
++      int i;
++
++      for (i = 0; i < tp->md5sig_info->entries4; i++) {
++              if (tp->md5sig_info->keys4[i].addr == addr) {
++                      /* Free the key */
++                      kfree(tp->md5sig_info->keys4[i].base.key);
++                      tp->md5sig_info->entries4--;
++
++                      if (tp->md5sig_info->entries4 == 0) {
++                              kfree(tp->md5sig_info->keys4);
++                              tp->md5sig_info->keys4 = NULL;
++                              tp->md5sig_info->alloced4 = 0;
++                      } else if (tp->md5sig_info->entries4 != i) {
++                              /* Need to do some manipulation */
++                              memcpy(&tp->md5sig_info->keys4[i],
++                                     &tp->md5sig_info->keys4[i+1],
++                                     (tp->md5sig_info->entries4 - i) *
++                                      sizeof(struct tcp4_md5sig_key));
++                      }
++                      tcp_free_md5sig_pool();
++                      return 0;
++              }
++      }
++      return -ENOENT;
++}
++
++EXPORT_SYMBOL(tcp_v4_md5_do_del);
++
++static void tcp_v4_clear_md5_list(struct sock *sk)
++{
++      struct tcp_sock *tp = tcp_sk(sk);
++
++      /* Free each key, then the set of key keys,
++       * the crypto element, and then decrement our
++       * hold on the last resort crypto.
++       */
++      if (tp->md5sig_info->entries4) {
++              int i;
++              for (i = 0; i < tp->md5sig_info->entries4; i++)
++                      kfree(tp->md5sig_info->keys4[i].base.key);
++              tp->md5sig_info->entries4 = 0;
++              tcp_free_md5sig_pool();
++      }
++      if (tp->md5sig_info->keys4) {
++              kfree(tp->md5sig_info->keys4);
++              tp->md5sig_info->keys4 = NULL;
++              tp->md5sig_info->alloced4  = 0;
++      }
++}
++
++static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
++                               int optlen)
++{
++      struct tcp_md5sig cmd;
++      struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr;
++      u8 *newkey;
++
++      if (optlen < sizeof(cmd))
++              return -EINVAL;
++
++      if (copy_from_user(&cmd, optval, sizeof(cmd)))
++              return -EFAULT;
++
++      if (sin->sin_family != AF_INET)
++              return -EINVAL;
++
++      if (!cmd.tcpm_key || !cmd.tcpm_keylen) {
++              if (!tcp_sk(sk)->md5sig_info)
++                      return -ENOENT;
++              return tcp_v4_md5_do_del(sk, sin->sin_addr.s_addr);
++      }
++
++      if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
++              return -EINVAL;
++
++      if (!tcp_sk(sk)->md5sig_info) {
++              struct tcp_sock *tp = tcp_sk(sk);
++              struct tcp_md5sig_info *p = kzalloc(sizeof(*p), GFP_KERNEL);
++
++              if (!p)
++                      return -EINVAL;
++
++              tp->md5sig_info = p;
++              sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
++      }
++
++      newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
++      if (!newkey)
++              return -ENOMEM;
++      return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr,
++                               newkey, cmd.tcpm_keylen);
++}
++
++static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
++                                 __be32 saddr, __be32 daddr,
++                                 struct tcphdr *th, int protocol,
++                                 int tcplen)
++{
++      struct scatterlist sg[4];
++      __u16 data_len;
++      int block = 0;
++      __sum16 old_checksum;
++      struct tcp_md5sig_pool *hp;
++      struct tcp4_pseudohdr *bp;
++      struct hash_desc *desc;
++      int err;
++      unsigned int nbytes = 0;
++
++      /*
++       * Okay, so RFC2385 is turned on for this connection,
++       * so we need to generate the MD5 hash for the packet now.
++       */
++
++      hp = tcp_get_md5sig_pool();
++      if (!hp)
++              goto clear_hash_noput;
++
++      bp = &hp->md5_blk.ip4;
++      desc = &hp->md5_desc;
++
++      /*
++       * 1. the TCP pseudo-header (in the order: source IP address,
++       * destination IP address, zero-padded protocol number, and
++       * segment length)
++       */
++      bp->saddr = saddr;
++      bp->daddr = daddr;
++      bp->pad = 0;
++      bp->protocol = protocol;
++      bp->len = htons(tcplen);
++      sg_set_buf(&sg[block++], bp, sizeof(*bp));
++      nbytes += sizeof(*bp);
++
++      /* 2. the TCP header, excluding options, and assuming a
++       * checksum of zero/
++       */
++      old_checksum = th->check;
++      th->check = 0;
++      sg_set_buf(&sg[block++], th, sizeof(struct tcphdr));
++      nbytes += sizeof(struct tcphdr);
++
++      /* 3. the TCP segment data (if any) */
++      data_len = tcplen - (th->doff << 2);
++      if (data_len > 0) {
++              unsigned char *data = (unsigned char *)th + (th->doff << 2);
++              sg_set_buf(&sg[block++], data, data_len);
++              nbytes += data_len;
++      }
++
++      /* 4. an independently-specified key or password, known to both
++       * TCPs and presumably connection-specific
++       */
++      sg_set_buf(&sg[block++], key->key, key->keylen);
++      nbytes += key->keylen;
++
++      /* Now store the Hash into the packet */
++      err = crypto_hash_init(desc);
++      if (err)
++              goto clear_hash;
++      err = crypto_hash_update(desc, sg, nbytes);
++      if (err)
++              goto clear_hash;
++      err = crypto_hash_final(desc, md5_hash);
++      if (err)
++              goto clear_hash;
++
++      /* Reset header, and free up the crypto */
++      tcp_put_md5sig_pool();
++      th->check = old_checksum;
++
++out:
++      return 0;
++clear_hash:
++      tcp_put_md5sig_pool();
++clear_hash_noput:
++      memset(md5_hash, 0, 16);
++      goto out;
++}
++
++int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
++                       struct sock *sk,
++                       struct dst_entry *dst,
++                       struct request_sock *req,
++                       struct tcphdr *th, int protocol,
++                       int tcplen)
++{
++      __be32 saddr, daddr;
++
++      if (sk) {
++              saddr = inet_sk(sk)->saddr;
++              daddr = inet_sk(sk)->daddr;
++      } else {
++              struct rtable *rt = (struct rtable *)dst;
++              BUG_ON(!rt);
++              saddr = rt->rt_src;
++              daddr = rt->rt_dst;
++      }
++      return tcp_v4_do_calc_md5_hash(md5_hash, key,
++                                     saddr, daddr,
++                                     th, protocol, tcplen);
++}
++
++EXPORT_SYMBOL(tcp_v4_calc_md5_hash);
++
++static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb)
++{
++      /*
++       * This gets called for each TCP segment that arrives
++       * so we want to be efficient.
++       * We have 3 drop cases:
++       * o No MD5 hash and one expected.
++       * o MD5 hash and we're not expecting one.
++       * o MD5 hash and its wrong.
++       */
++      __u8 *hash_location = NULL;
++      struct tcp_md5sig_key *hash_expected;
++      const struct iphdr *iph = ip_hdr(skb);
++      struct tcphdr *th = tcp_hdr(skb);
++      int length = (th->doff << 2) - sizeof(struct tcphdr);
++      int genhash;
++      unsigned char *ptr;
++      unsigned char newhash[16];
++
++      hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr);
++
++      /*
++       * If the TCP option length is less than the TCP_MD5SIG
++       * option length, then we can shortcut
++       */
++      if (length < TCPOLEN_MD5SIG) {
++              if (hash_expected)
++                      return 1;
++              else
++                      return 0;
++      }
++
++      /* Okay, we can't shortcut - we have to grub through the options */
++      ptr = (unsigned char *)(th + 1);
++      while (length > 0) {
++              int opcode = *ptr++;
++              int opsize;
++
++              switch (opcode) {
++              case TCPOPT_EOL:
++                      goto done_opts;
++              case TCPOPT_NOP:
++                      length--;
++                      continue;
++              default:
++                      opsize = *ptr++;
++                      if (opsize < 2)
++                              goto done_opts;
++                      if (opsize > length)
++                              goto done_opts;
++
++                      if (opcode == TCPOPT_MD5SIG) {
++                              hash_location = ptr;
++                              goto done_opts;
++                      }
++              }
++              ptr += opsize-2;
++              length -= opsize;
++      }
++done_opts:
++      /* We've parsed the options - do we have a hash? */
++      if (!hash_expected && !hash_location)
++              return 0;
++
++      if (hash_expected && !hash_location) {
++              LIMIT_NETDEBUG(KERN_INFO "MD5 Hash expected but NOT found "
++                             "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n",
++                             NIPQUAD(iph->saddr), ntohs(th->source),
++                             NIPQUAD(iph->daddr), ntohs(th->dest));
++              return 1;
++      }
++
++      if (!hash_expected && hash_location) {
++              LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found "
++                             "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n",
++                             NIPQUAD(iph->saddr), ntohs(th->source),
++                             NIPQUAD(iph->daddr), ntohs(th->dest));
++              return 1;
++      }
++
++      /* Okay, so this is hash_expected and hash_location -
++       * so we need to calculate the checksum.
++       */
++      genhash = tcp_v4_do_calc_md5_hash(newhash,
++                                        hash_expected,
++                                        iph->saddr, iph->daddr,
++                                        th, sk->sk_protocol,
++                                        skb->len);
++
++      if (genhash || memcmp(hash_location, newhash, 16) != 0) {
++              if (net_ratelimit()) {
++                      printk(KERN_INFO "MD5 Hash failed for "
++                             "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)%s\n",
++                             NIPQUAD(iph->saddr), ntohs(th->source),
++                             NIPQUAD(iph->daddr), ntohs(th->dest),
++                             genhash ? " tcp_v4_calc_md5_hash failed" : "");
++              }
++              return 1;
++      }
++      return 0;
++}
++
++#endif
++
++struct request_sock_ops tcp_request_sock_ops __read_mostly = {
++      .family         =       PF_INET,
++      .obj_size       =       sizeof(struct tcp_request_sock),
++      .rtx_syn_ack    =       tcp_v4_send_synack,
++      .send_ack       =       tcp_v4_reqsk_send_ack,
++      .destructor     =       tcp_v4_reqsk_destructor,
++      .send_reset     =       tcp_v4_send_reset,
++};
++
++#ifdef CONFIG_TCP_MD5SIG
++static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
++      .md5_lookup     =       tcp_v4_reqsk_md5_lookup,
++};
++#endif
++
++static struct timewait_sock_ops tcp_timewait_sock_ops = {
++      .twsk_obj_size  = sizeof(struct tcp_timewait_sock),
++      .twsk_unique    = tcp_twsk_unique,
++      .twsk_destructor= tcp_twsk_destructor,
++};
++
++int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
++{
++      struct inet_request_sock *ireq;
++      struct tcp_options_received tmp_opt;
++      struct request_sock *req;
++      __be32 saddr = ip_hdr(skb)->saddr;
++      __be32 daddr = ip_hdr(skb)->daddr;
++      __u32 isn = TCP_SKB_CB(skb)->when;
++      struct dst_entry *dst = NULL;
++#ifdef CONFIG_SYN_COOKIES
++      int want_cookie = 0;
++#else
++#define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */
++#endif
++
++      /* Never answer to SYNs send to broadcast or multicast */
++      if (((struct rtable *)skb->dst)->rt_flags &
++          (RTCF_BROADCAST | RTCF_MULTICAST))
++              goto drop;
++
++      /* TW buckets are converted to open requests without
++       * limitations, they conserve resources and peer is
++       * evidently real one.
++       */
++      if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
++#ifdef CONFIG_SYN_COOKIES
++              if (sysctl_tcp_syncookies) {
++                      want_cookie = 1;
++              } else
++#endif
++              goto drop;
++      }
++
++      /* Accept backlog is full. If we have already queued enough
++       * of warm entries in syn queue, drop request. It is better than
++       * clogging syn queue with openreqs with exponentially increasing
++       * timeout.
++       */
++      if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
++              goto drop;
++
++      req = reqsk_alloc(&tcp_request_sock_ops);
++      if (!req)
++              goto drop;
++
++#ifdef CONFIG_TCP_MD5SIG
++      tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops;
++#endif
++
++      tcp_clear_options(&tmp_opt);
++      tmp_opt.mss_clamp = 536;
++      tmp_opt.user_mss  = tcp_sk(sk)->rx_opt.user_mss;
++
++      tcp_parse_options(skb, &tmp_opt, 0);
++
++      if (want_cookie) {
++              tcp_clear_options(&tmp_opt);
++              tmp_opt.saw_tstamp = 0;
++      }
++
++      if (tmp_opt.saw_tstamp && !tmp_opt.rcv_tsval) {
++              /* Some OSes (unknown ones, but I see them on web server, which
++               * contains information interesting only for windows'
++               * users) do not send their stamp in SYN. It is easy case.
++               * We simply do not advertise TS support.
++               */
++              tmp_opt.saw_tstamp = 0;
++              tmp_opt.tstamp_ok  = 0;
++      }
++      tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
++
++      tcp_openreq_init(req, &tmp_opt, skb);
++
++      if (security_inet_conn_request(sk, skb, req))
++              goto drop_and_free;
++
++      ireq = inet_rsk(req);
++      ireq->loc_addr = daddr;
++      ireq->rmt_addr = saddr;
++      ireq->opt = tcp_v4_save_options(sk, skb);
++      if (!want_cookie)
++              TCP_ECN_create_request(req, tcp_hdr(skb));
++
++      if (want_cookie) {
++#ifdef CONFIG_SYN_COOKIES
++              syn_flood_warning(skb);
++#endif
++              isn = cookie_v4_init_sequence(sk, skb, &req->mss);
++      } else if (!isn) {
++              struct inet_peer *peer = NULL;
++
++              /* VJ's idea. We save last timestamp seen
++               * from the destination in peer table, when entering
++               * state TIME-WAIT, and check against it before
++               * accepting new connection request.
++               *
++               * If "isn" is not zero, this request hit alive
++               * timewait bucket, so that all the necessary checks
++               * are made in the function processing timewait state.
++               */
++              if (tmp_opt.saw_tstamp &&
++                  tcp_death_row.sysctl_tw_recycle &&
++                  (dst = inet_csk_route_req(sk, req)) != NULL &&
++                  (peer = rt_get_peer((struct rtable *)dst)) != NULL &&
++                  peer->v4daddr == saddr) {
++                      if (get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
++                          (s32)(peer->tcp_ts - req->ts_recent) >
++                                                      TCP_PAWS_WINDOW) {
++                              NET_INC_STATS_BH(LINUX_MIB_PAWSPASSIVEREJECTED);
++                              dst_release(dst);
++                              goto drop_and_free;
++                      }
++              }
++              /* Kill the following clause, if you dislike this way. */
++              else if (!sysctl_tcp_syncookies &&
++                       (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) <
++                        (sysctl_max_syn_backlog >> 2)) &&
++                       (!peer || !peer->tcp_ts_stamp) &&
++                       (!dst || !dst_metric(dst, RTAX_RTT))) {
++                      /* Without syncookies last quarter of
++                       * backlog is filled with destinations,
++                       * proven to be alive.
++                       * It means that we continue to communicate
++                       * to destinations, already remembered
++                       * to the moment of synflood.
++                       */
++                      LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open "
++                                     "request from %u.%u.%u.%u/%u\n",
++                                     NIPQUAD(saddr),
++                                     ntohs(tcp_hdr(skb)->source));
++                      dst_release(dst);
++                      goto drop_and_free;
++              }
++
++              isn = tcp_v4_init_sequence(skb);
++      }
++      tcp_rsk(req)->snt_isn = isn;
++
++      if (tcp_v4_send_synack(sk, req, dst))
++              goto drop_and_free;
++
++      if (want_cookie) {
++              reqsk_free(req);
++      } else {
++              inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
++      }
++      return 0;
++
++drop_and_free:
++      reqsk_free(req);
++drop:
++      return 0;
++}
++
++
++/*
++ * The three way handshake has completed - we got a valid synack -
++ * now create the new socket.
++ */
++struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
++                                struct request_sock *req,
++                                struct dst_entry *dst)
++{
++      struct inet_request_sock *ireq;
++      struct inet_sock *newinet;
++      struct tcp_sock *newtp;
++      struct sock *newsk;
++#ifdef CONFIG_TCP_MD5SIG
++      struct tcp_md5sig_key *key;
++#endif
++
++      if (sk_acceptq_is_full(sk))
++              goto exit_overflow;
++
++      if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL)
++              goto exit;
++
++      newsk = tcp_create_openreq_child(sk, req, skb);
++      if (!newsk)
++              goto exit;
++
++      newsk->sk_gso_type = SKB_GSO_TCPV4;
++      sk_setup_caps(newsk, dst);
++
++      newtp                 = tcp_sk(newsk);
++      newinet               = inet_sk(newsk);
++      ireq                  = inet_rsk(req);
++      newinet->daddr        = ireq->rmt_addr;
++      newinet->rcv_saddr    = ireq->loc_addr;
++      newinet->saddr        = ireq->loc_addr;
++      newinet->opt          = ireq->opt;
++      ireq->opt             = NULL;
++      newinet->mc_index     = inet_iif(skb);
++      newinet->mc_ttl       = ip_hdr(skb)->ttl;
++      inet_csk(newsk)->icsk_ext_hdr_len = 0;
++      if (newinet->opt)
++              inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen;
++      newinet->id = newtp->write_seq ^ jiffies;
++
++      tcp_mtup_init(newsk);
++      tcp_sync_mss(newsk, dst_mtu(dst));
++      newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
++      tcp_initialize_rcv_mss(newsk);
++
++#ifdef CONFIG_TCP_MD5SIG
++      /* Copy over the MD5 key from the original socket */
++      if ((key = tcp_v4_md5_do_lookup(sk, newinet->daddr)) != NULL) {
++              /*
++               * We're using one, so create a matching key
++               * on the newsk structure. If we fail to get
++               * memory, then we end up not copying the key
++               * across. Shucks.
++               */
++              char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC);
++              if (newkey != NULL)
++                      tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr,
++                                        newkey, key->keylen);
++      }
++#endif
++
++      __inet_hash(&tcp_hashinfo, newsk, 0);
++      __inet_inherit_port(&tcp_hashinfo, sk, newsk);
++
++      return newsk;
++
++exit_overflow:
++      NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS);
++exit:
++      NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS);
++      dst_release(dst);
++      return NULL;
++}
++
++static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
++{
++      struct tcphdr *th = tcp_hdr(skb);
++      const struct iphdr *iph = ip_hdr(skb);
++      struct sock *nsk;
++      struct request_sock **prev;
++      /* Find possible connection requests. */
++      struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
++                                                     iph->saddr, iph->daddr);
++      if (req)
++              return tcp_check_req(sk, skb, req, prev);
++
++      nsk = inet_lookup_established(&tcp_hashinfo, iph->saddr, th->source,
++                                    iph->daddr, th->dest, inet_iif(skb));
++
++      if (nsk) {
++              if (nsk->sk_state != TCP_TIME_WAIT) {
++                      bh_lock_sock(nsk);
++                      return nsk;
++              }
++              inet_twsk_put(inet_twsk(nsk));
++              return NULL;
++      }
++
++#ifdef CONFIG_SYN_COOKIES
++      if (!th->rst && !th->syn && th->ack)
++              sk = cookie_v4_check(sk, skb, &(IPCB(skb)->opt));
++#endif
++      return sk;
++}
++
++static __sum16 tcp_v4_checksum_init(struct sk_buff *skb)
++{
++      const struct iphdr *iph = ip_hdr(skb);
++
++      if (skb->ip_summed == CHECKSUM_COMPLETE) {
++              if (!tcp_v4_check(skb->len, iph->saddr,
++                                iph->daddr, skb->csum)) {
++                      skb->ip_summed = CHECKSUM_UNNECESSARY;
++                      return 0;
++              }
++      }
++
++      skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
++                                     skb->len, IPPROTO_TCP, 0);
++
++      if (skb->len <= 76) {
++              return __skb_checksum_complete(skb);
++      }
++      return 0;
++}
++
++
++/* The socket must have it's spinlock held when we get
++ * here.
++ *
++ * We have a potential double-lock case here, so even when
++ * doing backlog processing we use the BH locking scheme.
++ * This is because we cannot sleep with the original spinlock
++ * held.
++ */
++int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
++{
++      struct sock *rsk;
++#ifdef CONFIG_TCP_MD5SIG
++      /*
++       * We really want to reject the packet as early as possible
++       * if:
++       *  o We're expecting an MD5'd packet and this is no MD5 tcp option
++       *  o There is an MD5 option and we're not expecting one
++       */
++      if (tcp_v4_inbound_md5_hash(sk, skb))
++              goto discard;
++#endif
++
++      if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
++              TCP_CHECK_TIMER(sk);
++              if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
++                      rsk = sk;
++                      goto reset;
++              }
++              TCP_CHECK_TIMER(sk);
++              return 0;
++      }
++
++      if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
++              goto csum_err;
++
++      if (sk->sk_state == TCP_LISTEN) {
++              struct sock *nsk = tcp_v4_hnd_req(sk, skb);
++              if (!nsk)
++                      goto discard;
++
++              if (nsk != sk) {
++                      if (tcp_child_process(sk, nsk, skb)) {
++                              rsk = nsk;
++                              goto reset;
++                      }
++                      return 0;
++              }
++      }
++
++      TCP_CHECK_TIMER(sk);
++      if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) {
++              rsk = sk;
++              goto reset;
++      }
++      TCP_CHECK_TIMER(sk);
++      return 0;
++
++reset:
++      tcp_v4_send_reset(rsk, skb);
++discard:
++      kfree_skb(skb);
++      /* Be careful here. If this function gets more complicated and
++       * gcc suffers from register pressure on the x86, sk (in %ebx)
++       * might be destroyed here. This current version compiles correctly,
++       * but you have been warned.
++       */
++      return 0;
++
++csum_err:
++      TCP_INC_STATS_BH(TCP_MIB_INERRS);
++      goto discard;
++}
++
++/*
++ *    From tcp_input.c
++ */
++
++int tcp_v4_rcv(struct sk_buff *skb)
++{
++      const struct iphdr *iph;
++      struct tcphdr *th;
++      struct sock *sk;
++      int ret;
++
++      if (skb->pkt_type != PACKET_HOST)
++              goto discard_it;
++
++      /* Count it even if it's bad */
++      TCP_INC_STATS_BH(TCP_MIB_INSEGS);
++
++      if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
++              goto discard_it;
++
++      th = tcp_hdr(skb);
++
++      if (th->doff < sizeof(struct tcphdr) / 4)
++              goto bad_packet;
++      if (!pskb_may_pull(skb, th->doff * 4))
++              goto discard_it;
++
++      /* An explanation is required here, I think.
++       * Packet length and doff are validated by header prediction,
++       * provided case of th->doff==0 is eliminated.
++       * So, we defer the checks. */
++      if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb))
++              goto bad_packet;
++
++      th = tcp_hdr(skb);
++      iph = ip_hdr(skb);
++      TCP_SKB_CB(skb)->seq = ntohl(th->seq);
++      TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
++                                  skb->len - th->doff * 4);
++      TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
++      TCP_SKB_CB(skb)->when    = 0;
++      TCP_SKB_CB(skb)->flags   = iph->tos;
++      TCP_SKB_CB(skb)->sacked  = 0;
++
++      sk = __inet_lookup(&tcp_hashinfo, iph->saddr, th->source,
++                         iph->daddr, th->dest, inet_iif(skb));
++      if (!sk)
++              goto no_tcp_socket;
++
++process:
++      if (sk->sk_state == TCP_TIME_WAIT)
++              goto do_time_wait;
++
++      if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
++              goto discard_and_relse;
++      nf_reset(skb);
++
++      if (sk_filter(sk, skb))
++              goto discard_and_relse;
++
++      skb->dev = NULL;
++
++      bh_lock_sock_nested(sk);
++      ret = 0;
++      if (!sock_owned_by_user(sk)) {
++#ifdef CONFIG_NET_DMA
++              struct tcp_sock *tp = tcp_sk(sk);
++              if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
++                      tp->ucopy.dma_chan = get_softnet_dma();
++              if (tp->ucopy.dma_chan)
++                      ret = tcp_v4_do_rcv(sk, skb);
++              else
++#endif
++              {
++                      if (!tcp_prequeue(sk, skb))
++                      ret = tcp_v4_do_rcv(sk, skb);
++              }
++      } else
++              sk_add_backlog(sk, skb);
++      bh_unlock_sock(sk);
++
++      sock_put(sk);
++
++      return ret;
++
++no_tcp_socket:
++      if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
++              goto discard_it;
++
++      if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
++bad_packet:
++              TCP_INC_STATS_BH(TCP_MIB_INERRS);
++      } else {
++              tcp_v4_send_reset(NULL, skb);
++      }
++
++discard_it:
++      /* Discard frame. */
++      kfree_skb(skb);
++      return 0;
++
++discard_and_relse:
++      sock_put(sk);
++      goto discard_it;
++
++do_time_wait:
++      if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
++              inet_twsk_put(inet_twsk(sk));
++              goto discard_it;
++      }
++
++      if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
++              TCP_INC_STATS_BH(TCP_MIB_INERRS);
++              inet_twsk_put(inet_twsk(sk));
++              goto discard_it;
++      }
++      switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
++      case TCP_TW_SYN: {
++              struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo,
++                                                      iph->daddr, th->dest,
++                                                      inet_iif(skb));
++              if (sk2) {
++                      inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
++                      inet_twsk_put(inet_twsk(sk));
++                      sk = sk2;
++                      goto process;
++              }
++              /* Fall through to ACK */
++      }
++      case TCP_TW_ACK:
++              tcp_v4_timewait_ack(sk, skb);
++              break;
++      case TCP_TW_RST:
++              goto no_tcp_socket;
++      case TCP_TW_SUCCESS:;
++      }
++      goto discard_it;
++}
++
++/* VJ's idea. Save last timestamp seen from this destination
++ * and hold it at least for normal timewait interval to use for duplicate
++ * segment detection in subsequent connections, before they enter synchronized
++ * state.
++ */
++
++int tcp_v4_remember_stamp(struct sock *sk)
++{
++      struct inet_sock *inet = inet_sk(sk);
++      struct tcp_sock *tp = tcp_sk(sk);
++      struct rtable *rt = (struct rtable *)__sk_dst_get(sk);
++      struct inet_peer *peer = NULL;
++      int release_it = 0;
++
++      if (!rt || rt->rt_dst != inet->daddr) {
++              peer = inet_getpeer(inet->daddr, 1);
++              release_it = 1;
++      } else {
++              if (!rt->peer)
++                      rt_bind_peer(rt, 1);
++              peer = rt->peer;
++      }
++
++      if (peer) {
++              if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 ||
++                  (peer->tcp_ts_stamp + TCP_PAWS_MSL < get_seconds() &&
++                   peer->tcp_ts_stamp <= tp->rx_opt.ts_recent_stamp)) {
++                      peer->tcp_ts_stamp = tp->rx_opt.ts_recent_stamp;
++                      peer->tcp_ts = tp->rx_opt.ts_recent;
++              }
++              if (release_it)
++                      inet_putpeer(peer);
++              return 1;
++      }
++
++      return 0;
++}
++
++int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
++{
++      struct inet_peer *peer = inet_getpeer(tw->tw_daddr, 1);
++
++      if (peer) {
++              const struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
++
++              if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 ||
++                  (peer->tcp_ts_stamp + TCP_PAWS_MSL < get_seconds() &&
++                   peer->tcp_ts_stamp <= tcptw->tw_ts_recent_stamp)) {
++                      peer->tcp_ts_stamp = tcptw->tw_ts_recent_stamp;
++                      peer->tcp_ts       = tcptw->tw_ts_recent;
++              }
++              inet_putpeer(peer);
++              return 1;
++      }
++
++      return 0;
++}
++
++struct inet_connection_sock_af_ops ipv4_specific = {
++      .queue_xmit        = ip_queue_xmit,
++      .send_check        = tcp_v4_send_check,
++      .rebuild_header    = inet_sk_rebuild_header,
++      .conn_request      = tcp_v4_conn_request,
++      .syn_recv_sock     = tcp_v4_syn_recv_sock,
++      .remember_stamp    = tcp_v4_remember_stamp,
++      .net_header_len    = sizeof(struct iphdr),
++      .setsockopt        = ip_setsockopt,
++      .getsockopt        = ip_getsockopt,
++      .addr2sockaddr     = inet_csk_addr2sockaddr,
++      .sockaddr_len      = sizeof(struct sockaddr_in),
++#ifdef CONFIG_COMPAT
++      .compat_setsockopt = compat_ip_setsockopt,
++      .compat_getsockopt = compat_ip_getsockopt,
++#endif
++};
++
++#ifdef CONFIG_TCP_MD5SIG
++static struct tcp_sock_af_ops tcp_sock_ipv4_specific = {
++      .md5_lookup             = tcp_v4_md5_lookup,
++      .calc_md5_hash          = tcp_v4_calc_md5_hash,
++      .md5_add                = tcp_v4_md5_add_func,
++      .md5_parse              = tcp_v4_parse_md5_keys,
++};
++#endif
++
++/* NOTE: A lot of things set to zero explicitly by call to
++ *       sk_alloc() so need not be done here.
++ */
++static int tcp_v4_init_sock(struct sock *sk)
++{
++      struct inet_connection_sock *icsk = inet_csk(sk);
++      struct tcp_sock *tp = tcp_sk(sk);
++
++      skb_queue_head_init(&tp->out_of_order_queue);
++      tcp_init_xmit_timers(sk);
++      tcp_prequeue_init(tp);
++
++      icsk->icsk_rto = TCP_TIMEOUT_INIT;
++      tp->mdev = TCP_TIMEOUT_INIT;
++
++      /* So many TCP implementations out there (incorrectly) count the
++       * initial SYN frame in their delayed-ACK and congestion control
++       * algorithms that we must have the following bandaid to talk
++       * efficiently to them.  -DaveM
++       */
++      tp->snd_cwnd = 2;
++
++      /* See draft-stevens-tcpca-spec-01 for discussion of the
++       * initialization of these values.
++       */
++      tp->snd_ssthresh = 0x7fffffff;  /* Infinity */
++      tp->snd_cwnd_clamp = ~0;
++      tp->mss_cache = 536;
++
++      tp->reordering = sysctl_tcp_reordering;
++      icsk->icsk_ca_ops = &tcp_init_congestion_ops;
++
++      sk->sk_state = TCP_CLOSE;
++
++      sk->sk_write_space = sk_stream_write_space;
++      sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
++
++      icsk->icsk_af_ops = &ipv4_specific;
++      icsk->icsk_sync_mss = tcp_sync_mss;
++#ifdef CONFIG_TCP_MD5SIG
++      tp->af_specific = &tcp_sock_ipv4_specific;
++#endif
++
++      sk->sk_sndbuf = sysctl_tcp_wmem[1];
++      sk->sk_rcvbuf = sysctl_tcp_rmem[1];
++
++      atomic_inc(&tcp_sockets_allocated);
++
++      return 0;
++}
++
++int tcp_v4_destroy_sock(struct sock *sk)
++{
++      struct tcp_sock *tp = tcp_sk(sk);
++
++      tcp_clear_xmit_timers(sk);
++
++      tcp_cleanup_congestion_control(sk);
++
++      /* Cleanup up the write buffer. */
++      tcp_write_queue_purge(sk);
++
++      /* Cleans up our, hopefully empty, out_of_order_queue. */
++      __skb_queue_purge(&tp->out_of_order_queue);
++
++#ifdef CONFIG_TCP_MD5SIG
++      /* Clean up the MD5 key list, if any */
++      if (tp->md5sig_info) {
++              tcp_v4_clear_md5_list(sk);
++              kfree(tp->md5sig_info);
++              tp->md5sig_info = NULL;
++      }
++#endif
++
++#ifdef CONFIG_NET_DMA
++      /* Cleans up our sk_async_wait_queue */
++      __skb_queue_purge(&sk->sk_async_wait_queue);
++#endif
++
++      /* Clean prequeue, it must be empty really */
++      __skb_queue_purge(&tp->ucopy.prequeue);
++
++      /* Clean up a referenced TCP bind bucket. */
++      if (inet_csk(sk)->icsk_bind_hash)
++              inet_put_port(&tcp_hashinfo, sk);
++
++      /*
++       * If sendmsg cached page exists, toss it.
++       */
++      if (sk->sk_sndmsg_page) {
++              __free_page(sk->sk_sndmsg_page);
++              sk->sk_sndmsg_page = NULL;
++      }
++
++      atomic_dec(&tcp_sockets_allocated);
++
++      return 0;
++}
++
++EXPORT_SYMBOL(tcp_v4_destroy_sock);
++
++#ifdef CONFIG_PROC_FS
++/* Proc filesystem TCP sock list dumping. */
++
++static inline struct inet_timewait_sock *tw_head(struct hlist_head *head)
++{
++      return hlist_empty(head) ? NULL :
++              list_entry(head->first, struct inet_timewait_sock, tw_node);
++}
++
++static inline struct inet_timewait_sock *tw_next(struct inet_timewait_sock *tw)
++{
++      return tw->tw_node.next ?
++              hlist_entry(tw->tw_node.next, typeof(*tw), tw_node) : NULL;
++}
++
++static void *listening_get_next(struct seq_file *seq, void *cur)
++{
++      struct inet_connection_sock *icsk;
++      struct hlist_node *node;
++      struct sock *sk = cur;
++      struct tcp_iter_state* st = seq->private;
++
++      if (!sk) {
++              st->bucket = 0;
++              sk = sk_head(&tcp_hashinfo.listening_hash[0]);
++              goto get_sk;
++      }
++
++      ++st->num;
++
++      if (st->state == TCP_SEQ_STATE_OPENREQ) {
++              struct request_sock *req = cur;
++
++              icsk = inet_csk(st->syn_wait_sk);
++              req = req->dl_next;
++              while (1) {
++                      while (req) {
++                              if (req->rsk_ops->family == st->family) {
++                                      cur = req;
++                                      goto out;
++                              }
++                              req = req->dl_next;
++                      }
++                      if (++st->sbucket >= icsk->icsk_accept_queue.listen_opt->nr_table_entries)
++                              break;
++get_req:
++                      req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket];
++              }
++              sk        = sk_next(st->syn_wait_sk);
++              st->state = TCP_SEQ_STATE_LISTENING;
++              read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
++      } else {
++              icsk = inet_csk(sk);
++              read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
++              if (reqsk_queue_len(&icsk->icsk_accept_queue))
++                      goto start_req;
++              read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
++              sk = sk_next(sk);
++      }
++get_sk:
++      sk_for_each_from(sk, node) {
++              if (sk->sk_family == st->family) {
++                      cur = sk;
++                      goto out;
++              }
++              icsk = inet_csk(sk);
++              read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
++              if (reqsk_queue_len(&icsk->icsk_accept_queue)) {
++start_req:
++                      st->uid         = sock_i_uid(sk);
++                      st->syn_wait_sk = sk;
++                      st->state       = TCP_SEQ_STATE_OPENREQ;
++                      st->sbucket     = 0;
++                      goto get_req;
++              }
++              read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
++      }
++      if (++st->bucket < INET_LHTABLE_SIZE) {
++              sk = sk_head(&tcp_hashinfo.listening_hash[st->bucket]);
++              goto get_sk;
++      }
++      cur = NULL;
++out:
++      return cur;
++}
++
++static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
++{
++      void *rc = listening_get_next(seq, NULL);
++
++      while (rc && *pos) {
++              rc = listening_get_next(seq, rc);
++              --*pos;
++      }
++      return rc;
++}
++
++static void *established_get_first(struct seq_file *seq)
++{
++      struct tcp_iter_state* st = seq->private;
++      void *rc = NULL;
++
++      for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) {
++              struct sock *sk;
++              struct hlist_node *node;
++              struct inet_timewait_sock *tw;
++
++              /* We can reschedule _before_ having picked the target: */
++              cond_resched_softirq();
++
++              read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
++              sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
++                      if (sk->sk_family != st->family) {
++                              continue;
++                      }
++                      rc = sk;
++                      goto out;
++              }
++              st->state = TCP_SEQ_STATE_TIME_WAIT;
++              inet_twsk_for_each(tw, node,
++                                 &tcp_hashinfo.ehash[st->bucket].twchain) {
++                      if (tw->tw_family != st->family) {
++                              continue;
++                      }
++                      rc = tw;
++                      goto out;
++              }
++              read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
++              st->state = TCP_SEQ_STATE_ESTABLISHED;
++      }
++out:
++      return rc;
++}
++
++static void *established_get_next(struct seq_file *seq, void *cur)
++{
++      struct sock *sk = cur;
++      struct inet_timewait_sock *tw;
++      struct hlist_node *node;
++      struct tcp_iter_state* st = seq->private;
++
++      ++st->num;
++
++      if (st->state == TCP_SEQ_STATE_TIME_WAIT) {
++              tw = cur;
++              tw = tw_next(tw);
++get_tw:
++              while (tw && tw->tw_family != st->family) {
++                      tw = tw_next(tw);
++              }
++              if (tw) {
++                      cur = tw;
++                      goto out;
++              }
++              read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
++              st->state = TCP_SEQ_STATE_ESTABLISHED;
++
++              /* We can reschedule between buckets: */
++              cond_resched_softirq();
++
++              if (++st->bucket < tcp_hashinfo.ehash_size) {
++                      read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
++                      sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
++              } else {
++                      cur = NULL;
++                      goto out;
++              }
++      } else
++              sk = sk_next(sk);
++
++      sk_for_each_from(sk, node) {
++              if (sk->sk_family == st->family)
++                      goto found;
++      }
++
++      st->state = TCP_SEQ_STATE_TIME_WAIT;
++      tw = tw_head(&tcp_hashinfo.ehash[st->bucket].twchain);
++      goto get_tw;
++found:
++      cur = sk;
++out:
++      return cur;
++}
++
++static void *established_get_idx(struct seq_file *seq, loff_t pos)
++{
++      void *rc = established_get_first(seq);
++
++      while (rc && pos) {
++              rc = established_get_next(seq, rc);
++              --pos;
++      }
++      return rc;
++}
++
++static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
++{
++      void *rc;
++      struct tcp_iter_state* st = seq->private;
++
++      inet_listen_lock(&tcp_hashinfo);
++      st->state = TCP_SEQ_STATE_LISTENING;
++      rc        = listening_get_idx(seq, &pos);
++
++      if (!rc) {
++              inet_listen_unlock(&tcp_hashinfo);
++              local_bh_disable();
++              st->state = TCP_SEQ_STATE_ESTABLISHED;
++              rc        = established_get_idx(seq, pos);
++      }
++
++      return rc;
++}
++
++static void *tcp_seq_start(struct seq_file *seq, loff_t *pos)
++{
++      struct tcp_iter_state* st = seq->private;
++      st->state = TCP_SEQ_STATE_LISTENING;
++      st->num = 0;
++      return *pos ? tcp_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
++}
++
++static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      void *rc = NULL;
++      struct tcp_iter_state* st;
++
++      if (v == SEQ_START_TOKEN) {
++              rc = tcp_get_idx(seq, 0);
++              goto out;
++      }
++      st = seq->private;
++
++      switch (st->state) {
++      case TCP_SEQ_STATE_OPENREQ:
++      case TCP_SEQ_STATE_LISTENING:
++              rc = listening_get_next(seq, v);
++              if (!rc) {
++                      inet_listen_unlock(&tcp_hashinfo);
++                      local_bh_disable();
++                      st->state = TCP_SEQ_STATE_ESTABLISHED;
++                      rc        = established_get_first(seq);
++              }
++              break;
++      case TCP_SEQ_STATE_ESTABLISHED:
++      case TCP_SEQ_STATE_TIME_WAIT:
++              rc = established_get_next(seq, v);
++              break;
++      }
++out:
++      ++*pos;
++      return rc;
++}
++
++static void tcp_seq_stop(struct seq_file *seq, void *v)
++{
++      struct tcp_iter_state* st = seq->private;
++
++      switch (st->state) {
++      case TCP_SEQ_STATE_OPENREQ:
++              if (v) {
++                      struct inet_connection_sock *icsk = inet_csk(st->syn_wait_sk);
++                      read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
++              }
++      case TCP_SEQ_STATE_LISTENING:
++              if (v != SEQ_START_TOKEN)
++                      inet_listen_unlock(&tcp_hashinfo);
++              break;
++      case TCP_SEQ_STATE_TIME_WAIT:
++      case TCP_SEQ_STATE_ESTABLISHED:
++              if (v)
++                      read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
++              local_bh_enable();
++              break;
++      }
++}
++
++static int tcp_seq_open(struct inode *inode, struct file *file)
++{
++      struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
++      struct seq_file *seq;
++      struct tcp_iter_state *s;
++      int rc;
++
++      if (unlikely(afinfo == NULL))
++              return -EINVAL;
++
++      s = kzalloc(sizeof(*s), GFP_KERNEL);
++      if (!s)
++              return -ENOMEM;
++      s->family               = afinfo->family;
++      s->seq_ops.start        = tcp_seq_start;
++      s->seq_ops.next         = tcp_seq_next;
++      s->seq_ops.show         = afinfo->seq_show;
++      s->seq_ops.stop         = tcp_seq_stop;
++
++      rc = seq_open(file, &s->seq_ops);
++      if (rc)
++              goto out_kfree;
++      seq          = file->private_data;
++      seq->private = s;
++out:
++      return rc;
++out_kfree:
++      kfree(s);
++      goto out;
++}
++
++int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
++{
++      int rc = 0;
++      struct proc_dir_entry *p;
++
++      if (!afinfo)
++              return -EINVAL;
++      afinfo->seq_fops->owner         = afinfo->owner;
++      afinfo->seq_fops->open          = tcp_seq_open;
++      afinfo->seq_fops->read          = seq_read;
++      afinfo->seq_fops->llseek        = seq_lseek;
++      afinfo->seq_fops->release       = seq_release_private;
++
++      p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);
++      if (p)
++              p->data = afinfo;
++      else
++              rc = -ENOMEM;
++      return rc;
++}
++
++void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo)
++{
++      if (!afinfo)
++              return;
++      proc_net_remove(afinfo->name);
++      memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
++}
++
++static void get_openreq4(struct sock *sk, struct request_sock *req,
++                       char *tmpbuf, int i, int uid)
++{
++      const struct inet_request_sock *ireq = inet_rsk(req);
++      int ttd = req->expires - jiffies;
++
++      sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
++              " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p",
++              i,
++              ireq->loc_addr,
++              ntohs(inet_sk(sk)->sport),
++              ireq->rmt_addr,
++              ntohs(ireq->rmt_port),
++              TCP_SYN_RECV,
++              0, 0, /* could print option size, but that is af dependent. */
++              1,    /* timers active (only the expire timer) */
++              jiffies_to_clock_t(ttd),
++              req->retrans,
++              uid,
++              0,  /* non standard timer */
++              0, /* open_requests have no inode */
++              atomic_read(&sk->sk_refcnt),
++              req);
++}
++
++static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i)
++{
++      int timer_active;
++      unsigned long timer_expires;
++      struct tcp_sock *tp = tcp_sk(sk);
++      const struct inet_connection_sock *icsk = inet_csk(sk);
++      struct inet_sock *inet = inet_sk(sk);
++      __be32 dest = inet->daddr;
++      __be32 src = inet->rcv_saddr;
++      __u16 destp = ntohs(inet->dport);
++      __u16 srcp = ntohs(inet->sport);
++
++      if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
++              timer_active    = 1;
++              timer_expires   = icsk->icsk_timeout;
++      } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
++              timer_active    = 4;
++              timer_expires   = icsk->icsk_timeout;
++      } else if (timer_pending(&sk->sk_timer)) {
++              timer_active    = 2;
++              timer_expires   = sk->sk_timer.expires;
++      } else {
++              timer_active    = 0;
++              timer_expires = jiffies;
++      }
++
++      sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
++                      "%08X %5d %8d %lu %d %p %u %u %u %u %d",
++              i, src, srcp, dest, destp, sk->sk_state,
++              tp->write_seq - tp->snd_una,
++              sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog :
++                                           (tp->rcv_nxt - tp->copied_seq),
++              timer_active,
++              jiffies_to_clock_t(timer_expires - jiffies),
++              icsk->icsk_retransmits,
++              sock_i_uid(sk),
++              icsk->icsk_probes_out,
++              sock_i_ino(sk),
++              atomic_read(&sk->sk_refcnt), sk,
++              icsk->icsk_rto,
++              icsk->icsk_ack.ato,
++              (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
++              tp->snd_cwnd,
++              tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);
++}
++
++static void get_timewait4_sock(struct inet_timewait_sock *tw,
++                             char *tmpbuf, int i)
++{
++      __be32 dest, src;
++      __u16 destp, srcp;
++      int ttd = tw->tw_ttd - jiffies;
++
++      if (ttd < 0)
++              ttd = 0;
++
++      dest  = tw->tw_daddr;
++      src   = tw->tw_rcv_saddr;
++      destp = ntohs(tw->tw_dport);
++      srcp  = ntohs(tw->tw_sport);
++
++      sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
++              " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p",
++              i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
++              3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
++              atomic_read(&tw->tw_refcnt), tw);
++}
++
++#define TMPSZ 150
++
++static int tcp4_seq_show(struct seq_file *seq, void *v)
++{
++      struct tcp_iter_state* st;
++      char tmpbuf[TMPSZ + 1];
++
++      if (v == SEQ_START_TOKEN) {
++              seq_printf(seq, "%-*s\n", TMPSZ - 1,
++                         "  sl  local_address rem_address   st tx_queue "
++                         "rx_queue tr tm->when retrnsmt   uid  timeout "
++                         "inode");
++              goto out;
++      }
++      st = seq->private;
++
++      switch (st->state) {
++      case TCP_SEQ_STATE_LISTENING:
++      case TCP_SEQ_STATE_ESTABLISHED:
++              get_tcp4_sock(v, tmpbuf, st->num);
++              break;
++      case TCP_SEQ_STATE_OPENREQ:
++              get_openreq4(st->syn_wait_sk, v, tmpbuf, st->num, st->uid);
++              break;
++      case TCP_SEQ_STATE_TIME_WAIT:
++              get_timewait4_sock(v, tmpbuf, st->num);
++              break;
++      }
++      seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);
++out:
++      return 0;
++}
++
++static struct file_operations tcp4_seq_fops;
++static struct tcp_seq_afinfo tcp4_seq_afinfo = {
++      .owner          = THIS_MODULE,
++      .name           = "tcp",
++      .family         = AF_INET,
++      .seq_show       = tcp4_seq_show,
++      .seq_fops       = &tcp4_seq_fops,
++};
++
++int __init tcp4_proc_init(void)
++{
++      return tcp_proc_register(&tcp4_seq_afinfo);
++}
++
++void tcp4_proc_exit(void)
++{
++      tcp_proc_unregister(&tcp4_seq_afinfo);
++}
++#endif /* CONFIG_PROC_FS */
++
++struct proto tcp_prot = {
++      .name                   = "TCP",
++      .owner                  = THIS_MODULE,
++      .close                  = tcp_close,
++      .connect                = tcp_v4_connect,
++      .disconnect             = tcp_disconnect,
++      .accept                 = inet_csk_accept,
++      .ioctl                  = tcp_ioctl,
++      .init                   = tcp_v4_init_sock,
++      .destroy                = tcp_v4_destroy_sock,
++      .shutdown               = tcp_shutdown,
++      .setsockopt             = tcp_setsockopt,
++      .getsockopt             = tcp_getsockopt,
++      .recvmsg                = tcp_recvmsg,
++      .backlog_rcv            = tcp_v4_do_rcv,
++      .hash                   = tcp_v4_hash,
++      .unhash                 = tcp_unhash,
++      .get_port               = tcp_v4_get_port,
++      .enter_memory_pressure  = tcp_enter_memory_pressure,
++      .sockets_allocated      = &tcp_sockets_allocated,
++      .orphan_count           = &tcp_orphan_count,
++      .memory_allocated       = &tcp_memory_allocated,
++      .memory_pressure        = &tcp_memory_pressure,
++      .sysctl_mem             = sysctl_tcp_mem,
++      .sysctl_wmem            = sysctl_tcp_wmem,
++      .sysctl_rmem            = sysctl_tcp_rmem,
++      .max_header             = MAX_TCP_HEADER,
++      .obj_size               = sizeof(struct tcp_sock),
++      .twsk_prot              = &tcp_timewait_sock_ops,
++      .rsk_prot               = &tcp_request_sock_ops,
++#ifdef CONFIG_COMPAT
++      .compat_setsockopt      = compat_tcp_setsockopt,
++      .compat_getsockopt      = compat_tcp_getsockopt,
++#endif
++};
++
++void __init tcp_v4_init(struct net_proto_family *ops)
++{
++      if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW,
++                                   IPPROTO_TCP) < 0)
++              panic("Failed to create the TCP control socket.\n");
++}
++
++EXPORT_SYMBOL(ipv4_specific);
++EXPORT_SYMBOL(tcp_hashinfo);
++EXPORT_SYMBOL(tcp_prot);
++EXPORT_SYMBOL(tcp_unhash);
++EXPORT_SYMBOL(tcp_v4_conn_request);
++EXPORT_SYMBOL(tcp_v4_connect);
++EXPORT_SYMBOL(tcp_v4_do_rcv);
++EXPORT_SYMBOL(tcp_v4_remember_stamp);
++EXPORT_SYMBOL(tcp_v4_send_check);
++EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
++
++#ifdef CONFIG_PROC_FS
++EXPORT_SYMBOL(tcp_proc_register);
++EXPORT_SYMBOL(tcp_proc_unregister);
++#endif
++EXPORT_SYMBOL(sysctl_local_port_range);
++EXPORT_SYMBOL(sysctl_tcp_low_latency);
++
+diff -Nurb linux-2.6.22-590/net/ipv4/tcp_output.c linux-2.6.22-570/net/ipv4/tcp_output.c
+--- linux-2.6.22-590/net/ipv4/tcp_output.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/tcp_output.c     2007-07-08 19:32:17.000000000 -0400
+@@ -432,11 +432,11 @@
+       sysctl_flags = 0;
+       if (unlikely(tcb->flags & TCPCB_FLAG_SYN)) {
+               tcp_header_size = sizeof(struct tcphdr) + TCPOLEN_MSS;
+-              if (sk->sk_net->sysctl_tcp_timestamps) {
++              if (sysctl_tcp_timestamps) {
+                       tcp_header_size += TCPOLEN_TSTAMP_ALIGNED;
+                       sysctl_flags |= SYSCTL_FLAG_TSTAMPS;
+               }
+-              if (sk->sk_net->sysctl_tcp_window_scaling) {
++              if (sysctl_tcp_window_scaling) {
+                       tcp_header_size += TCPOLEN_WSCALE_ALIGNED;
+                       sysctl_flags |= SYSCTL_FLAG_WSCALE;
+               }
+@@ -2215,7 +2215,7 @@
+        * See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.
+        */
+       tp->tcp_header_len = sizeof(struct tcphdr) +
+-              (sk->sk_net->sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0);
++              (sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0);
+ #ifdef CONFIG_TCP_MD5SIG
+       if (tp->af_specific->md5_lookup(sk, sk) != NULL)
+@@ -2238,7 +2238,7 @@
+                                 tp->advmss - (tp->rx_opt.ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
+                                 &tp->rcv_wnd,
+                                 &tp->window_clamp,
+-                                sk->sk_net->sysctl_tcp_window_scaling,
++                                sysctl_tcp_window_scaling,
+                                 &rcv_wscale);
+       tp->rx_opt.rcv_wscale = rcv_wscale;
+diff -Nurb linux-2.6.22-590/net/ipv4/tcp_probe.c linux-2.6.22-570/net/ipv4/tcp_probe.c
+--- linux-2.6.22-590/net/ipv4/tcp_probe.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/tcp_probe.c      2007-07-08 19:32:17.000000000 -0400
+@@ -172,7 +172,7 @@
+       if (IS_ERR(tcpw.fifo))
+               return PTR_ERR(tcpw.fifo);
+-      if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &tcpprobe_fops))
++      if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops))
+               goto err0;
+       ret = register_jprobe(&tcp_probe);
+@@ -182,7 +182,7 @@
+       pr_info("TCP watch registered (port=%d)\n", port);
+       return 0;
+  err1:
+-      proc_net_remove(&init_net, procname);
++      proc_net_remove(procname);
+  err0:
+       kfifo_free(tcpw.fifo);
+       return ret;
+@@ -192,7 +192,7 @@
+ static __exit void tcpprobe_exit(void)
+ {
+       kfifo_free(tcpw.fifo);
+-      proc_net_remove(&init_net, procname);
++      proc_net_remove(procname);
+       unregister_jprobe(&tcp_probe);
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/tunnel4.c linux-2.6.22-570/net/ipv4/tunnel4.c
+--- linux-2.6.22-590/net/ipv4/tunnel4.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/tunnel4.c        2007-07-08 19:32:17.000000000 -0400
+@@ -75,10 +75,6 @@
+ {
+       struct xfrm_tunnel *handler;
+-      if (skb->dev->nd_net != &init_net) {
 -              kfree_skb(skb);
--              goto errout;
--      }
--      err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
--errout:
--      if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_IPV6_PREFIX, err);
--}
--
--static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
--{
--      inet6_ifa_notify(event ? : RTM_NEWADDR, ifp);
--
--      switch (event) {
--      case RTM_NEWADDR:
--              /*
--               * If the address was optimistic
--               * we inserted the route at the start of
--               * our DAD process, so we don't need
--               * to do it again
--               */
--              if (!(ifp->rt->rt6i_node))
--                      ip6_ins_rt(ifp->rt);
--              if (ifp->idev->cnf.forwarding)
--                      addrconf_join_anycast(ifp);
--              break;
--      case RTM_DELADDR:
--              if (ifp->idev->cnf.forwarding)
--                      addrconf_leave_anycast(ifp);
--              addrconf_leave_solict(ifp->idev, &ifp->addr);
--              dst_hold(&ifp->rt->u.dst);
--              if (ip6_del_rt(ifp->rt))
--                      dst_free(&ifp->rt->u.dst);
--              break;
--      }
--}
--
--static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
--{
--      rcu_read_lock_bh();
--      if (likely(ifp->idev->dead == 0))
--              __ipv6_ifa_notify(event, ifp);
--      rcu_read_unlock_bh();
--}
--
--#ifdef CONFIG_SYSCTL
--
--static
--int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
--                         void __user *buffer, size_t *lenp, loff_t *ppos)
--{
--      int *valp = ctl->data;
--      int val = *valp;
--      int ret;
--
--      ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
--
--      if (write && valp != &ipv6_devconf_dflt.forwarding) {
--              if (valp != &ipv6_devconf.forwarding) {
--                      if ((!*valp) ^ (!val)) {
--                              struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1;
--                              if (idev == NULL)
--                                      return ret;
--                              dev_forward_change(idev);
--                      }
--              } else {
--                      ipv6_devconf_dflt.forwarding = ipv6_devconf.forwarding;
--                      addrconf_forward_change();
--              }
--              if (*valp)
--                      rt6_purge_dflt_routers();
--      }
--
--      return ret;
--}
--
--static int addrconf_sysctl_forward_strategy(ctl_table *table,
--                                          int __user *name, int nlen,
--                                          void __user *oldval,
--                                          size_t __user *oldlenp,
--                                          void __user *newval, size_t newlen)
--{
--      int *valp = table->data;
--      int new;
--
--      if (!newval || !newlen)
 -              return 0;
--      if (newlen != sizeof(int))
--              return -EINVAL;
--      if (get_user(new, (int __user *)newval))
--              return -EFAULT;
--      if (new == *valp)
--              return 0;
--      if (oldval && oldlenp) {
--              size_t len;
--              if (get_user(len, oldlenp))
--                      return -EFAULT;
--              if (len) {
--                      if (len > table->maxlen)
--                              len = table->maxlen;
--                      if (copy_to_user(oldval, valp, len))
--                              return -EFAULT;
--                      if (put_user(len, oldlenp))
--                              return -EFAULT;
--              }
 -      }
--
--      if (valp != &ipv6_devconf_dflt.forwarding) {
--              if (valp != &ipv6_devconf.forwarding) {
--                      struct inet6_dev *idev = (struct inet6_dev *)table->extra1;
--                      int changed;
--                      if (unlikely(idev == NULL))
--                              return -ENODEV;
--                      changed = (!*valp) ^ (!new);
--                      *valp = new;
--                      if (changed)
--                              dev_forward_change(idev);
--              } else {
--                      *valp = new;
--                      addrconf_forward_change();
--              }
--
--              if (*valp)
--                      rt6_purge_dflt_routers();
--      } else
--              *valp = new;
--
--      return 1;
--}
--
--static struct addrconf_sysctl_table
--{
--      struct ctl_table_header *sysctl_header;
--      ctl_table addrconf_vars[__NET_IPV6_MAX];
--      ctl_table addrconf_dev[2];
--      ctl_table addrconf_conf_dir[2];
--      ctl_table addrconf_proto_dir[2];
--      ctl_table addrconf_root_dir[2];
--} addrconf_sysctl __read_mostly = {
--      .sysctl_header = NULL,
--      .addrconf_vars = {
--              {
--                      .ctl_name       =       NET_IPV6_FORWARDING,
--                      .procname       =       "forwarding",
--                      .data           =       &ipv6_devconf.forwarding,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &addrconf_sysctl_forward,
--                      .strategy       =       &addrconf_sysctl_forward_strategy,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_HOP_LIMIT,
--                      .procname       =       "hop_limit",
--                      .data           =       &ipv6_devconf.hop_limit,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_MTU,
--                      .procname       =       "mtu",
--                      .data           =       &ipv6_devconf.mtu6,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_ACCEPT_RA,
--                      .procname       =       "accept_ra",
--                      .data           =       &ipv6_devconf.accept_ra,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_ACCEPT_REDIRECTS,
--                      .procname       =       "accept_redirects",
--                      .data           =       &ipv6_devconf.accept_redirects,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_AUTOCONF,
--                      .procname       =       "autoconf",
--                      .data           =       &ipv6_devconf.autoconf,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_DAD_TRANSMITS,
--                      .procname       =       "dad_transmits",
--                      .data           =       &ipv6_devconf.dad_transmits,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_RTR_SOLICITS,
--                      .procname       =       "router_solicitations",
--                      .data           =       &ipv6_devconf.rtr_solicits,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_RTR_SOLICIT_INTERVAL,
--                      .procname       =       "router_solicitation_interval",
--                      .data           =       &ipv6_devconf.rtr_solicit_interval,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec_jiffies,
--                      .strategy       =       &sysctl_jiffies,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_RTR_SOLICIT_DELAY,
--                      .procname       =       "router_solicitation_delay",
--                      .data           =       &ipv6_devconf.rtr_solicit_delay,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec_jiffies,
--                      .strategy       =       &sysctl_jiffies,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_FORCE_MLD_VERSION,
--                      .procname       =       "force_mld_version",
--                      .data           =       &ipv6_devconf.force_mld_version,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--#ifdef CONFIG_IPV6_PRIVACY
--              {
--                      .ctl_name       =       NET_IPV6_USE_TEMPADDR,
--                      .procname       =       "use_tempaddr",
--                      .data           =       &ipv6_devconf.use_tempaddr,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_TEMP_VALID_LFT,
--                      .procname       =       "temp_valid_lft",
--                      .data           =       &ipv6_devconf.temp_valid_lft,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_TEMP_PREFERED_LFT,
--                      .procname       =       "temp_prefered_lft",
--                      .data           =       &ipv6_devconf.temp_prefered_lft,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_REGEN_MAX_RETRY,
--                      .procname       =       "regen_max_retry",
--                      .data           =       &ipv6_devconf.regen_max_retry,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_MAX_DESYNC_FACTOR,
--                      .procname       =       "max_desync_factor",
--                      .data           =       &ipv6_devconf.max_desync_factor,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--#endif
--              {
--                      .ctl_name       =       NET_IPV6_MAX_ADDRESSES,
--                      .procname       =       "max_addresses",
--                      .data           =       &ipv6_devconf.max_addresses,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_ACCEPT_RA_DEFRTR,
--                      .procname       =       "accept_ra_defrtr",
--                      .data           =       &ipv6_devconf.accept_ra_defrtr,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_ACCEPT_RA_PINFO,
--                      .procname       =       "accept_ra_pinfo",
--                      .data           =       &ipv6_devconf.accept_ra_pinfo,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--#ifdef CONFIG_IPV6_ROUTER_PREF
--              {
--                      .ctl_name       =       NET_IPV6_ACCEPT_RA_RTR_PREF,
--                      .procname       =       "accept_ra_rtr_pref",
--                      .data           =       &ipv6_devconf.accept_ra_rtr_pref,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_RTR_PROBE_INTERVAL,
--                      .procname       =       "router_probe_interval",
--                      .data           =       &ipv6_devconf.rtr_probe_interval,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec_jiffies,
--                      .strategy       =       &sysctl_jiffies,
--              },
--#ifdef CONFIG_IPV6_ROUTE_INFO
--              {
--                      .ctl_name       =       NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN,
--                      .procname       =       "accept_ra_rt_info_max_plen",
--                      .data           =       &ipv6_devconf.accept_ra_rt_info_max_plen,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--#endif
--#endif
--              {
--                      .ctl_name       =       NET_IPV6_PROXY_NDP,
--                      .procname       =       "proxy_ndp",
--                      .data           =       &ipv6_devconf.proxy_ndp,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--              {
--                      .ctl_name       =       NET_IPV6_ACCEPT_SOURCE_ROUTE,
--                      .procname       =       "accept_source_route",
--                      .data           =       &ipv6_devconf.accept_source_route,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--              },
--#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
--              {
--                      .ctl_name       =       CTL_UNNUMBERED,
--                      .procname       =       "optimistic_dad",
--                      .data           =       &ipv6_devconf.optimistic_dad,
--                      .maxlen         =       sizeof(int),
--                      .mode           =       0644,
--                      .proc_handler   =       &proc_dointvec,
--
--              },
--#endif
--              {
--                      .ctl_name       =       0,      /* sentinel */
--              }
--      },
--      .addrconf_dev = {
--              {
--                      .ctl_name       =       NET_PROTO_CONF_ALL,
--                      .procname       =       "all",
--                      .mode           =       0555,
--                      .child          =       addrconf_sysctl.addrconf_vars,
--              },
--              {
--                      .ctl_name       =       0,      /* sentinel */
--              }
--      },
--      .addrconf_conf_dir = {
--              {
--                      .ctl_name       =       NET_IPV6_CONF,
--                      .procname       =       "conf",
--                      .mode           =       0555,
--                      .child          =       addrconf_sysctl.addrconf_dev,
--              },
--              {
--                      .ctl_name       =       0,      /* sentinel */
--              }
--      },
--      .addrconf_proto_dir = {
--              {
--                      .ctl_name       =       NET_IPV6,
--                      .procname       =       "ipv6",
--                      .mode           =       0555,
--                      .child          =       addrconf_sysctl.addrconf_conf_dir,
--              },
--              {
--                      .ctl_name       =       0,      /* sentinel */
--              }
--      },
--      .addrconf_root_dir = {
--              {
--                      .ctl_name       =       CTL_NET,
--                      .procname       =       "net",
--                      .mode           =       0555,
--                      .child          =       addrconf_sysctl.addrconf_proto_dir,
--              },
--              {
--                      .ctl_name       =       0,      /* sentinel */
--              }
--      },
--};
--
--static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf *p)
--{
--      int i;
--      struct net_device *dev = idev ? idev->dev : NULL;
--      struct addrconf_sysctl_table *t;
--      char *dev_name = NULL;
--
--      t = kmemdup(&addrconf_sysctl, sizeof(*t), GFP_KERNEL);
--      if (t == NULL)
+       if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+               goto drop;
+@@ -117,9 +113,6 @@
+ {
+       struct xfrm_tunnel *handler;
+-      if (skb->dev->nd_net != &init_net)
 -              return;
--      for (i=0; t->addrconf_vars[i].data; i++) {
--              t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf;
--              t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */
--      }
--      if (dev) {
--              dev_name = dev->name;
--              t->addrconf_dev[0].ctl_name = dev->ifindex;
--      } else {
--              dev_name = "default";
--              t->addrconf_dev[0].ctl_name = NET_PROTO_CONF_DEFAULT;
--      }
--
--      /*
--       * Make a copy of dev_name, because '.procname' is regarded as const
--       * by sysctl and we wouldn't want anyone to change it under our feet
--       * (see SIOCSIFNAME).
--       */
--      dev_name = kstrdup(dev_name, GFP_KERNEL);
--      if (!dev_name)
--          goto free;
--
--      t->addrconf_dev[0].procname = dev_name;
 -
--      t->addrconf_dev[0].child = t->addrconf_vars;
--      t->addrconf_conf_dir[0].child = t->addrconf_dev;
--      t->addrconf_proto_dir[0].child = t->addrconf_conf_dir;
--      t->addrconf_root_dir[0].child = t->addrconf_proto_dir;
--
--      t->sysctl_header = register_sysctl_table(t->addrconf_root_dir);
--      if (t->sysctl_header == NULL)
--              goto free_procname;
--      else
--              p->sysctl = t;
--      return;
--
--      /* error path */
-- free_procname:
--      kfree(dev_name);
-- free:
--      kfree(t);
--
--      return;
--}
--
--static void addrconf_sysctl_unregister(struct ipv6_devconf *p)
--{
--      if (p->sysctl) {
--              struct addrconf_sysctl_table *t = p->sysctl;
--              p->sysctl = NULL;
--              unregister_sysctl_table(t->sysctl_header);
--              kfree(t->addrconf_dev[0].procname);
--              kfree(t);
+       for (handler = tunnel4_handlers; handler; handler = handler->next)
+               if (!handler->err_handler(skb, info))
+                       break;
+diff -Nurb linux-2.6.22-590/net/ipv4/udp.c linux-2.6.22-570/net/ipv4/udp.c
+--- linux-2.6.22-590/net/ipv4/udp.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/udp.c    2008-01-23 19:16:09.000000000 -0500
+@@ -101,7 +101,6 @@
+ #include <net/route.h>
+ #include <net/checksum.h>
+ #include <net/xfrm.h>
+-#include <net/net_namespace.h>
+ #include "udp_impl.h"
+ /*
+@@ -113,17 +112,16 @@
+ struct hlist_head udp_hash[UDP_HTABLE_SIZE];
+ DEFINE_RWLOCK(udp_hash_lock);
+-static inline int __udp_lib_lport_inuse(struct net *net, __u16 num, struct hlist_head udptable[])
++static int udp_port_rover;
++
++static inline int __udp_lib_lport_inuse(__u16 num, struct hlist_head udptable[])
+ {
+       struct sock *sk;
+       struct hlist_node *node;
+-      sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)]) {
+-              if (sk->sk_net != net)
+-                      continue;
++      sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
+               if (sk->sk_hash == num)
+                       return 1;
 -      }
--}
--
--
--#endif
--
--/*
-- *      Device notifier
-- */
--
--int register_inet6addr_notifier(struct notifier_block *nb)
--{
--      return atomic_notifier_chain_register(&inet6addr_chain, nb);
--}
+       return 0;
+ }
+@@ -150,9 +148,9 @@
+       if (snum == 0) {
+               int best_size_so_far, best, result, i;
+-              if (*port_rover > sk->sk_net->sysctl_local_port_range[1] ||
+-                  *port_rover < sk->sk_net->sysctl_local_port_range[0])
+-                      *port_rover = sk->sk_net->sysctl_local_port_range[0];
++              if (*port_rover > sysctl_local_port_range[1] ||
++                  *port_rover < sysctl_local_port_range[0])
++                      *port_rover = sysctl_local_port_range[0];
+               best_size_so_far = 32767;
+               best = result = *port_rover;
+               for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
+@@ -160,9 +158,9 @@
+                       head = &udptable[result & (UDP_HTABLE_SIZE - 1)];
+                       if (hlist_empty(head)) {
+-                              if (result > sk->sk_net->sysctl_local_port_range[1])
+-                                      result = sk->sk_net->sysctl_local_port_range[0] +
+-                                              ((result - sk->sk_net->sysctl_local_port_range[0]) &
++                              if (result > sysctl_local_port_range[1])
++                                      result = sysctl_local_port_range[0] +
++                                              ((result - sysctl_local_port_range[0]) &
+                                                (UDP_HTABLE_SIZE - 1));
+                               goto gotit;
+                       }
+@@ -179,11 +177,11 @@
+               result = best;
+               for (i = 0; i < (1 << 16) / UDP_HTABLE_SIZE;
+                    i++, result += UDP_HTABLE_SIZE) {
+-                      if (result > sk->sk_net->sysctl_local_port_range[1])
+-                              result = sk->sk_net->sysctl_local_port_range[0]
+-                                      + ((result - sk->sk_net->sysctl_local_port_range[0]) &
++                      if (result > sysctl_local_port_range[1])
++                              result = sysctl_local_port_range[0]
++                                      + ((result - sysctl_local_port_range[0]) &
+                                          (UDP_HTABLE_SIZE - 1));
+-                      if (! __udp_lib_lport_inuse(sk->sk_net, result, udptable))
++                      if (! __udp_lib_lport_inuse(result, udptable))
+                               break;
+               }
+               if (i >= (1 << 16) / UDP_HTABLE_SIZE)
+@@ -196,7 +194,6 @@
+               sk_for_each(sk2, node, head)
+                       if (sk2->sk_hash == snum                             &&
+                           sk2 != sk                                        &&
+-                          sk->sk_net == sk2->sk_net                        &&
+                           (!sk2->sk_reuse        || !sk->sk_reuse)         &&
+                           (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
+                            || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
+@@ -219,7 +216,7 @@
+ int udp_get_port(struct sock *sk, unsigned short snum,
+                       int (*scmp)(const struct sock *, const struct sock *))
+ {
+-      return  __udp_lib_get_port(sk, snum, udp_hash, &sk->sk_net->udp_port_rover, scmp);
++      return  __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp);
+ }
+ extern int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2);
+@@ -232,8 +229,7 @@
+ /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
+  * harder than this. -DaveM
+  */
+-static struct sock *__udp4_lib_lookup(struct net *net,
+-                                    __be32 saddr, __be16 sport,
++static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
+                                     __be32 daddr, __be16 dport,
+                                     int dif, struct hlist_head udptable[])
+ {
+@@ -247,9 +243,6 @@
+       sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
+               struct inet_sock *inet = inet_sk(sk);
+-              if (sk->sk_net != net)
+-                      continue;
 -
--EXPORT_SYMBOL(register_inet6addr_notifier);
+               if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) {
+                       int score = (sk->sk_family == PF_INET ? 1 : 0);
+@@ -306,9 +299,6 @@
+       sk_for_each_from(s, node) {
+               struct inet_sock *inet = inet_sk(s);
+-              if (s->sk_net != sk->sk_net)
+-                      continue;
 -
--int unregister_inet6addr_notifier(struct notifier_block *nb)
+               if (s->sk_hash != hnum                                  ||
+                   (inet->daddr && inet->daddr != rmt_addr)            ||
+                   (inet->dport != rmt_port && inet->dport)            ||
+@@ -338,7 +328,6 @@
+ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[])
+ {
+-      struct net *net = skb->dev->nd_net;
+       struct inet_sock *inet;
+       struct iphdr *iph = (struct iphdr*)skb->data;
+       struct udphdr *uh = (struct udphdr*)(skb->data+(iph->ihl<<2));
+@@ -348,7 +337,7 @@
+       int harderr;
+       int err;
+-      sk = __udp4_lib_lookup(net, iph->daddr, uh->dest, iph->saddr, uh->source,
++      sk = __udp4_lib_lookup(iph->daddr, uh->dest, iph->saddr, uh->source,
+                              skb->dev->ifindex, udptable                  );
+       if (sk == NULL) {
+               ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+@@ -634,8 +623,7 @@
+               rt = (struct rtable*)sk_dst_check(sk, 0);
+       if (rt == NULL) {
+-              struct flowi fl = { .fl_net = sk->sk_net,
+-                                  .oif = ipc.oif,
++              struct flowi fl = { .oif = ipc.oif,
+                                   .nl_u = { .ip4_u =
+                                             { .daddr = faddr,
+                                               .saddr = saddr,
+@@ -1300,7 +1288,6 @@
+ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
+                  int proto)
+ {
+-      struct net *net = skb->dev->nd_net;
+       struct sock *sk;
+       struct udphdr *uh = udp_hdr(skb);
+       unsigned short ulen;
+@@ -1335,7 +1322,7 @@
+       udp_ping_of_death(skb, uh, saddr);
+ #endif
+-      sk = __udp4_lib_lookup(net, saddr, uh->source, daddr, uh->dest,
++      sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
+                              skb->dev->ifindex, udptable        );
+       if (sk != NULL) {
+@@ -1664,7 +1651,7 @@
+               sk = sk_next(sk);
+ try_again:
+               ;
+-      } while (sk && ((sk->sk_net != state->net) || sk->sk_family != state->family ||
++      } while (sk && (sk->sk_family != state->family ||
+               !nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT)));
+       if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {
+@@ -1730,7 +1717,6 @@
+       seq          = file->private_data;
+       seq->private = s;
+-      s->net       = get_net(PROC_NET(inode));
+ out:
+       return rc;
+ out_kfree:
+@@ -1738,31 +1724,21 @@
+       goto out;
+ }
+-static int udp_seq_release(struct inode *inode, struct file *file)
 -{
--      return atomic_notifier_chain_unregister(&inet6addr_chain,nb);
+-      struct seq_file *seq = file->private_data;
+-      struct udp_iter_state *state = seq->private;
+-      put_net(state->net);
+-      return seq_release_private(inode, file);
 -}
 -
--EXPORT_SYMBOL(unregister_inet6addr_notifier);
--
--/*
-- *    Init / cleanup code
-- */
--
--int __init addrconf_init(void)
--{
--      int err = 0;
--
--      /* The addrconf netdev notifier requires that loopback_dev
--       * has it's ipv6 private information allocated and setup
--       * before it can bring up and give link-local addresses
--       * to other devices which are up.
--       *
--       * Unfortunately, loopback_dev is not necessarily the first
--       * entry in the global dev_base list of net devices.  In fact,
--       * it is likely to be the very last entry on that list.
--       * So this causes the notifier registry below to try and
--       * give link-local addresses to all devices besides loopback_dev
--       * first, then loopback_dev, which cases all the non-loopback_dev
--       * devices to fail to get a link-local address.
--       *
--       * So, as a temporary fix, allocate the ipv6 structure for
--       * loopback_dev first by hand.
--       * Longer term, all of the dependencies ipv6 has upon the loopback
--       * device and it being up should be removed.
--       */
--      rtnl_lock();
--      if (!ipv6_add_dev(&loopback_dev))
--              err = -ENOMEM;
--      rtnl_unlock();
--      if (err)
--              return err;
--
--      ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);
--#ifdef CONFIG_IPV6_MULTIPLE_TABLES
--      ip6_prohibit_entry.rt6i_idev = in6_dev_get(&loopback_dev);
--      ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&loopback_dev);
--#endif
--
--      register_netdevice_notifier(&ipv6_dev_notf);
--
--      addrconf_verify(0);
--
--      err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo);
--      if (err < 0)
--              goto errout;
--
--      /* Only the first call to __rtnl_register can fail */
--      __rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL);
--      __rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL);
--      __rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr, inet6_dump_ifaddr);
--      __rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL, inet6_dump_ifmcaddr);
--      __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, inet6_dump_ifacaddr);
--
--#ifdef CONFIG_SYSCTL
--      addrconf_sysctl.sysctl_header =
--              register_sysctl_table(addrconf_sysctl.addrconf_root_dir);
--      addrconf_sysctl_register(NULL, &ipv6_devconf_dflt);
--#endif
--
--      return 0;
--errout:
--      unregister_netdevice_notifier(&ipv6_dev_notf);
+ /* ------------------------------------------------------------------------ */
+-int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo)
++int udp_proc_register(struct udp_seq_afinfo *afinfo)
+ {
+       struct proc_dir_entry *p;
+       int rc = 0;
+       if (!afinfo)
+               return -EINVAL;
+-      if (net == &init_net) {
+       afinfo->seq_fops->owner         = afinfo->owner;
+       afinfo->seq_fops->open          = udp_seq_open;
+       afinfo->seq_fops->read          = seq_read;
+       afinfo->seq_fops->llseek        = seq_lseek;
+-              afinfo->seq_fops->release       = udp_seq_release;
+-      }
++      afinfo->seq_fops->release       = seq_release_private;
+-      p = proc_net_fops_create(net, afinfo->name, S_IRUGO, afinfo->seq_fops);
++      p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);
+       if (p)
+               p->data = afinfo;
+       else
+@@ -1770,12 +1746,11 @@
+       return rc;
+ }
+-void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo)
++void udp_proc_unregister(struct udp_seq_afinfo *afinfo)
+ {
+       if (!afinfo)
+               return;
+-      proc_net_remove(net, afinfo->name);
+-      if (net == &init_net)
++      proc_net_remove(afinfo->name);
+       memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
+ }
+@@ -1828,30 +1803,14 @@
+       .seq_fops       = &udp4_seq_fops,
+ };
 -
--      return err;
+-static int udp4_proc_net_init(struct net *net)
+-{
+-      return udp_proc_register(net, &udp4_seq_afinfo);
 -}
 -
--void __exit addrconf_cleanup(void)
+-static void udp4_proc_net_exit(struct net *net)
 -{
--      struct net_device *dev;
--      struct inet6_dev *idev;
--      struct inet6_ifaddr *ifa;
--      int i;
--
--      unregister_netdevice_notifier(&ipv6_dev_notf);
--
--#ifdef CONFIG_SYSCTL
--      addrconf_sysctl_unregister(&ipv6_devconf_dflt);
--      addrconf_sysctl_unregister(&ipv6_devconf);
--#endif
+-      udp_proc_unregister(net, &udp4_seq_afinfo);
+-}
 -
--      rtnl_lock();
+-static struct pernet_operations udp4_proc_net_ops = {
+-      .init = udp4_proc_net_init,
+-      .exit = udp4_proc_net_exit,
+-};
 -
--      /*
--       *      clean dev list.
--       */
+ int __init udp4_proc_init(void)
+ {
+-      return register_pernet_subsys(&udp4_proc_net_ops);
++      return udp_proc_register(&udp4_seq_afinfo);
+ }
+ void udp4_proc_exit(void)
+ {
+-      unregister_pernet_subsys(&udp4_proc_net_ops);
++      udp_proc_unregister(&udp4_seq_afinfo);
+ }
+ #endif /* CONFIG_PROC_FS */
+diff -Nurb linux-2.6.22-590/net/ipv4/udplite.c linux-2.6.22-570/net/ipv4/udplite.c
+--- linux-2.6.22-590/net/ipv4/udplite.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/udplite.c        2007-07-08 19:32:17.000000000 -0400
+@@ -31,18 +31,11 @@
+ static int udplite_rcv(struct sk_buff *skb)
+ {
+-      if (skb->dev->nd_net != &init_net) {
+-              kfree_skb(skb);
+-              return 0;
+-      }
+       return __udp4_lib_rcv(skb, udplite_hash, IPPROTO_UDPLITE);
+ }
+ static void udplite_err(struct sk_buff *skb, u32 info)
+ {
+-      if (skb->dev->nd_net != &init_net)
+-              return;
 -
--      for_each_netdev(dev) {
--              if ((idev = __in6_dev_get(dev)) == NULL)
--                      continue;
--              addrconf_ifdown(dev, 1);
+       return __udp4_lib_err(skb, info, udplite_hash);
+ }
+@@ -110,7 +103,7 @@
+       inet_register_protosw(&udplite4_protosw);
+ #ifdef CONFIG_PROC_FS
+-      if (udp_proc_register(&init_net, &udplite4_seq_afinfo)) /* udplite4_proc_init() */
++      if (udp_proc_register(&udplite4_seq_afinfo)) /* udplite4_proc_init() */
+               printk(KERN_ERR "%s: Cannot register /proc!\n", __FUNCTION__);
+ #endif
+       return;
+diff -Nurb linux-2.6.22-590/net/ipv4/xfrm4_input.c linux-2.6.22-570/net/ipv4/xfrm4_input.c
+--- linux-2.6.22-590/net/ipv4/xfrm4_input.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/xfrm4_input.c    2007-07-08 19:32:17.000000000 -0400
+@@ -18,10 +18,6 @@
+ int xfrm4_rcv(struct sk_buff *skb)
+ {
+-      if (skb->dev->nd_net != &init_net) {
+-              kfree_skb(skb);
+-              return 0;
 -      }
--      addrconf_ifdown(&loopback_dev, 2);
+       return xfrm4_rcv_encap(skb, 0);
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/xfrm4_policy.c linux-2.6.22-570/net/ipv4/xfrm4_policy.c
+--- linux-2.6.22-590/net/ipv4/xfrm4_policy.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/xfrm4_policy.c   2007-07-08 19:32:17.000000000 -0400
+@@ -25,7 +25,6 @@
+ {
+       struct rtable *rt;
+       struct flowi fl_tunnel = {
+-              .fl_net = &init_net,
+               .nl_u = {
+                       .ip4_u = {
+                               .daddr = daddr->a4,
+@@ -74,7 +73,6 @@
+       struct rtable *rt0 = (struct rtable*)(*dst_p);
+       struct rtable *rt = rt0;
+       struct flowi fl_tunnel = {
+-              .fl_net = &init_net,
+               .nl_u = {
+                       .ip4_u = {
+                               .saddr = fl->fl4_src,
+@@ -215,7 +213,6 @@
+       u8 *xprth = skb_network_header(skb) + iph->ihl * 4;
+       memset(fl, 0, sizeof(struct flowi));
+-      fl->fl_net = &init_net;
+       if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) {
+               switch (iph->protocol) {
+               case IPPROTO_UDP:
+@@ -309,7 +306,7 @@
+       xdst = (struct xfrm_dst *)dst;
+       if (xdst->u.rt.idev->dev == dev) {
+-              struct in_device *loopback_idev = in_dev_get(&init_net.loopback_dev);
++              struct in_device *loopback_idev = in_dev_get(&loopback_dev);
+               BUG_ON(!loopback_idev);
+               do {
+diff -Nurb linux-2.6.22-590/net/ipv4/xfrm4_state.c linux-2.6.22-570/net/ipv4/xfrm4_state.c
+--- linux-2.6.22-590/net/ipv4/xfrm4_state.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/xfrm4_state.c    2007-07-08 19:32:17.000000000 -0400
+@@ -16,7 +16,7 @@
+ static int xfrm4_init_flags(struct xfrm_state *x)
+ {
+-      if (init_net.sysctl_ipv4_no_pmtu_disc)
++      if (ipv4_config.no_pmtu_disc)
+               x->props.flags |= XFRM_STATE_NOPMTUDISC;
+       return 0;
+ }
+diff -Nurb linux-2.6.22-590/net/ipv4/xfrm4_tunnel.c linux-2.6.22-570/net/ipv4/xfrm4_tunnel.c
+--- linux-2.6.22-590/net/ipv4/xfrm4_tunnel.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv4/xfrm4_tunnel.c   2007-07-08 19:32:17.000000000 -0400
+@@ -109,4 +109,3 @@
+ module_init(ipip_init);
+ module_exit(ipip_fini);
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP);
+diff -Nurb linux-2.6.22-590/net/ipv6/Kconfig linux-2.6.22-570/net/ipv6/Kconfig
+--- linux-2.6.22-590/net/ipv6/Kconfig  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/Kconfig  2008-01-23 19:16:05.000000000 -0500
+@@ -109,7 +109,7 @@
+         If unsure, say Y.
+ config IPV6_MIP6
+-      tristate "IPv6: Mobility (EXPERIMENTAL)"
++      bool "IPv6: Mobility (EXPERIMENTAL)"
+       depends on IPV6 && EXPERIMENTAL
+       select XFRM
+       ---help---
+diff -Nurb linux-2.6.22-590/net/ipv6/Makefile linux-2.6.22-570/net/ipv6/Makefile
+--- linux-2.6.22-590/net/ipv6/Makefile 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/Makefile 2007-07-08 19:32:17.000000000 -0400
+@@ -14,6 +14,7 @@
+       xfrm6_output.o
+ ipv6-$(CONFIG_NETFILTER) += netfilter.o
+ ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
++ipv6-$(CONFIG_IPV6_MIP6) += mip6.o
+ ipv6-$(CONFIG_PROC_FS) += proc.o
+ ipv6-objs += $(ipv6-y)
+@@ -27,7 +28,6 @@
+ obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
+ obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
+ obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
+-obj-$(CONFIG_IPV6_MIP6) += mip6.o
+ obj-$(CONFIG_NETFILTER)       += netfilter/
+ obj-$(CONFIG_IPV6_SIT) += sit.o
+diff -Nurb linux-2.6.22-590/net/ipv6/addrconf.c linux-2.6.22-570/net/ipv6/addrconf.c
+--- linux-2.6.22-590/net/ipv6/addrconf.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/addrconf.c       2008-01-23 19:16:05.000000000 -0500
+@@ -73,7 +73,6 @@
+ #include <net/tcp.h>
+ #include <net/ip.h>
+ #include <net/netlink.h>
+-#include <net/net_namespace.h>
+ #include <net/pkt_sched.h>
+ #include <linux/if_tunnel.h>
+ #include <linux/rtnetlink.h>
+@@ -458,7 +457,7 @@
+       struct inet6_dev *idev;
+       read_lock(&dev_base_lock);
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               rcu_read_lock();
+               idev = __in6_dev_get(dev);
+               if (idev) {
+@@ -921,7 +920,7 @@
+       read_lock(&dev_base_lock);
+       rcu_read_lock();
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               struct inet6_dev *idev;
+               struct inet6_ifaddr *ifa;
+@@ -1048,7 +1047,7 @@
+                       }
+                       /* Rule 4: Prefer home address */
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+                       if (hiscore.rule < 4) {
+                               if (ifa_result->flags & IFA_F_HOMEADDRESS)
+                                       hiscore.attrs |= IPV6_SADDR_SCORE_HOA;
+@@ -1883,7 +1882,7 @@
+       if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
+               goto err_exit;
+-      dev = __dev_get_by_index(&init_net, ireq.ifr6_ifindex);
++      dev = __dev_get_by_index(ireq.ifr6_ifindex);
+       err = -ENODEV;
+       if (dev == NULL)
+@@ -1914,7 +1913,7 @@
+               if (err == 0) {
+                       err = -ENOBUFS;
+-                      if ((dev = __dev_get_by_name(&init_net, p.name)) == NULL)
++                      if ((dev = __dev_get_by_name(p.name)) == NULL)
+                               goto err_exit;
+                       err = dev_open(dev);
+               }
+@@ -1944,7 +1943,7 @@
+       if (!valid_lft || prefered_lft > valid_lft)
+               return -EINVAL;
+-      if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL)
++      if ((dev = __dev_get_by_index(ifindex)) == NULL)
+               return -ENODEV;
+       if ((idev = addrconf_add_dev(dev)) == NULL)
+@@ -1995,7 +1994,7 @@
+       struct inet6_dev *idev;
+       struct net_device *dev;
+-      if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL)
++      if ((dev = __dev_get_by_index(ifindex)) == NULL)
+               return -ENODEV;
+       if ((idev = __in6_dev_get(dev)) == NULL)
+@@ -2090,7 +2089,7 @@
+               return;
+       }
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               struct in_device * in_dev = __in_dev_get_rtnl(dev);
+               if (in_dev && (dev->flags & IFF_UP)) {
+                       struct in_ifaddr * ifa;
+@@ -2246,12 +2245,12 @@
+       /* first try to inherit the link-local address from the link device */
+       if (idev->dev->iflink &&
+-          (link_dev = __dev_get_by_index(&init_net, idev->dev->iflink))) {
++          (link_dev = __dev_get_by_index(idev->dev->iflink))) {
+               if (!ipv6_inherit_linklocal(idev, link_dev))
+                       return;
+       }
+       /* then try to inherit it from any device */
+-      for_each_netdev(&init_net, link_dev) {
++      for_each_netdev(link_dev) {
+               if (!ipv6_inherit_linklocal(idev, link_dev))
+                       return;
+       }
+@@ -2283,9 +2282,6 @@
+       struct inet6_dev *idev = __in6_dev_get(dev);
+       int run_pending = 0;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--      /*
--       *      Check hash table.
--       */
+       switch(event) {
+       case NETDEV_REGISTER:
+               if (!idev && dev->mtu >= IPV6_MIN_MTU) {
+@@ -2423,7 +2419,7 @@
+       ASSERT_RTNL();
+-      if (dev == &init_net.loopback_dev && how == 1)
++      if (dev == &loopback_dev && how == 1)
+               how = 0;
+       rt6_ifdown(dev);
+@@ -2854,18 +2850,18 @@
+ int __init if6_proc_init(void)
+ {
+-      if (!proc_net_fops_create(&init_net, "if_inet6", S_IRUGO, &if6_fops))
++      if (!proc_net_fops_create("if_inet6", S_IRUGO, &if6_fops))
+               return -ENOMEM;
+       return 0;
+ }
+ void if6_proc_exit(void)
+ {
+-      proc_net_remove(&init_net, "if_inet6");
++      proc_net_remove("if_inet6");
+ }
+ #endif        /* CONFIG_PROC_FS */
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+ /* Check if address is a home address configured on any interface. */
+ int ipv6_chk_home_addr(struct in6_addr *addr)
+ {
+@@ -3021,15 +3017,11 @@
+ static int
+ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct ifaddrmsg *ifm;
+       struct nlattr *tb[IFA_MAX+1];
+       struct in6_addr *pfx;
+       int err;
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--      write_lock_bh(&addrconf_hash_lock);
--      for (i=0; i < IN6_ADDR_HSIZE; i++) {
--              for (ifa=inet6_addr_lst[i]; ifa; ) {
--                      struct inet6_ifaddr *bifa;
+       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
+       if (err < 0)
+               return err;
+@@ -3082,7 +3074,6 @@
+ static int
+ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct ifaddrmsg *ifm;
+       struct nlattr *tb[IFA_MAX+1];
+       struct in6_addr *pfx;
+@@ -3092,9 +3083,6 @@
+       u8 ifa_flags;
+       int err;
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--                      bifa = ifa;
--                      ifa = ifa->lst_next;
--                      printk(KERN_DEBUG "bug: IPv6 address leakage detected: ifa=%p\n", bifa);
--                      /* Do not free it; something is wrong.
--                         Now we can investigate it with debugger.
--                       */
--              }
--      }
--      write_unlock_bh(&addrconf_hash_lock);
+       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
+       if (err < 0)
+               return err;
+@@ -3115,7 +3103,7 @@
+               valid_lft = INFINITY_LIFE_TIME;
+       }
+-      dev =  __dev_get_by_index(&init_net, ifm->ifa_index);
++      dev =  __dev_get_by_index(ifm->ifa_index);
+       if (dev == NULL)
+               return -ENODEV;
+@@ -3304,7 +3292,7 @@
+       s_ip_idx = ip_idx = cb->args[1];
+       idx = 0;
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if (idx < s_idx)
+                       goto cont;
+               if (idx > s_idx)
+@@ -3379,42 +3367,26 @@
+ static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       enum addr_type_t type = UNICAST_ADDR;
 -
--      del_timer(&addr_chk_timer);
+-      if (net != &init_net)
+-              return 0;
 -
--      rtnl_unlock();
+       return inet6_dump_addr(skb, cb, type);
+ }
+ static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       enum addr_type_t type = MULTICAST_ADDR;
 -
--#ifdef CONFIG_PROC_FS
--      proc_net_remove("if_inet6");
--#endif
--}
-diff -Nurb linux-2.6.22-570/net/ipv6/af_inet6.c linux-2.6.22-590/net/ipv6/af_inet6.c
---- linux-2.6.22-570/net/ipv6/af_inet6.c       2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/af_inet6.c       2008-01-02 13:56:38.000000000 -0500
-@@ -59,9 +59,6 @@
- #ifdef CONFIG_IPV6_TUNNEL
- #include <net/ip6_tunnel.h>
- #endif
--#ifdef CONFIG_IPV6_MIP6
--#include <net/mip6.h>
--#endif
+-      if (net != &init_net)
+-              return 0;
+-
+       return inet6_dump_addr(skb, cb, type);
+ }
  
- #include <asm/uaccess.h>
- #include <asm/system.h>
-@@ -85,7 +82,7 @@
-       return (struct ipv6_pinfo *)(((u8 *)sk) + offset);
+ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       enum addr_type_t type = ANYCAST_ADDR;
+-
+-      if (net != &init_net)
+-              return 0;
+-
+       return inet6_dump_addr(skb, cb, type);
  }
  
--static int inet6_create(struct socket *sock, int protocol)
-+static int inet6_create(struct net *net, struct socket *sock, int protocol)
+ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
+                            void *arg)
  {
-       struct inet_sock *inet;
-       struct ipv6_pinfo *np;
-@@ -98,6 +95,9 @@
-       int try_loading_module = 0;
+-      struct net *net = in_skb->sk->sk_net;
+       struct ifaddrmsg *ifm;
+       struct nlattr *tb[IFA_MAX+1];
+       struct in6_addr *addr = NULL;
+@@ -3423,9 +3395,6 @@
+       struct sk_buff *skb;
        int err;
  
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
+-      if (net != &init_net)
+-              return -EINVAL;
+-
+       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
+       if (err < 0)
+               goto errout;
+@@ -3438,7 +3407,7 @@
+       ifm = nlmsg_data(nlh);
+       if (ifm->ifa_index)
+-              dev = __dev_get_by_index(&init_net, ifm->ifa_index);
++              dev = __dev_get_by_index(ifm->ifa_index);
+       if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) {
+               err = -EADDRNOTAVAIL;
+@@ -3458,7 +3427,7 @@
+               kfree_skb(skb);
+               goto errout_ifa;
+       }
+-      err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
++      err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
+ errout_ifa:
+       in6_ifa_put(ifa);
+ errout:
+@@ -3481,10 +3450,10 @@
+               kfree_skb(skb);
+               goto errout;
+       }
+-      err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
++      err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
+ errout:
+       if (err < 0)
+-              rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err);
++              rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
+ }
+ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
+@@ -3643,22 +3612,19 @@
+ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       int idx, err;
+       int s_idx = cb->args[0];
+       struct net_device *dev;
+       struct inet6_dev *idev;
+       struct nx_info *nxi = skb->sk ? skb->sk->sk_nx_info : NULL;
+-      if (net != &init_net)
+-              return 0;
+       /* FIXME: maybe disable ipv6 on non v6 guests?
+       if (skb->sk && skb->sk->sk_vx_info)
+               return skb->len;        */
+       read_lock(&dev_base_lock);
+       idx = 0;
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if (idx < s_idx)
+                       goto cont;
+               if (!v6_dev_in_nx_info(dev, nxi))
+@@ -3695,10 +3661,10 @@
+               kfree_skb(skb);
+               goto errout;
+       }
+-      err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
++      err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
+ errout:
+       if (err < 0)
+-              rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err);
++              rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
+ }
+ static inline size_t inet6_prefix_nlmsg_size(void)
+@@ -3764,10 +3730,10 @@
+               kfree_skb(skb);
+               goto errout;
+       }
+-      err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
++      err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
+ errout:
+       if (err < 0)
+-              rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_PREFIX, err);
++              rtnl_set_sk_err(RTNLGRP_IPV6_PREFIX, err);
+ }
+ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
+@@ -4278,16 +4244,16 @@
+        * device and it being up should be removed.
+        */
+       rtnl_lock();
+-      if (!ipv6_add_dev(&init_net.loopback_dev))
++      if (!ipv6_add_dev(&loopback_dev))
+               err = -ENOMEM;
+       rtnl_unlock();
+       if (err)
+               return err;
+-      ip6_null_entry.rt6i_idev = in6_dev_get(&init_net.loopback_dev);
++      ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);
+ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+-      ip6_prohibit_entry.rt6i_idev = in6_dev_get(&init_net.loopback_dev);
+-      ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&init_net.loopback_dev);
++      ip6_prohibit_entry.rt6i_idev = in6_dev_get(&loopback_dev);
++      ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&loopback_dev);
+ #endif
+       register_netdevice_notifier(&ipv6_dev_notf);
+@@ -4338,12 +4304,12 @@
+        *      clean dev list.
+        */
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if ((idev = __in6_dev_get(dev)) == NULL)
+                       continue;
+               addrconf_ifdown(dev, 1);
+       }
+-      addrconf_ifdown(&init_net.loopback_dev, 2);
++      addrconf_ifdown(&loopback_dev, 2);
+       /*
+        *      Check hash table.
+@@ -4369,6 +4335,6 @@
+       rtnl_unlock();
+ #ifdef CONFIG_PROC_FS
+-      proc_net_remove(&init_net, "if_inet6");
++      proc_net_remove("if_inet6");
+ #endif
+ }
+diff -Nurb linux-2.6.22-590/net/ipv6/addrconf.c.orig linux-2.6.22-570/net/ipv6/addrconf.c.orig
+--- linux-2.6.22-590/net/ipv6/addrconf.c.orig  1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/addrconf.c.orig  2008-01-23 19:15:56.000000000 -0500
+@@ -0,0 +1,4301 @@
++/*
++ *    IPv6 Address [auto]configuration
++ *    Linux INET6 implementation
++ *
++ *    Authors:
++ *    Pedro Roque             <roque@di.fc.ul.pt>
++ *    Alexey Kuznetsov        <kuznet@ms2.inr.ac.ru>
++ *
++ *    $Id: addrconf.c,v 1.69 2001/10/31 21:55:54 davem Exp $
++ *
++ *    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.
++ */
++
++/*
++ *    Changes:
++ *
++ *    Janos Farkas                    :       delete timer on ifdown
++ *    <chexum@bankinf.banki.hu>
++ *    Andi Kleen                      :       kill double kfree on module
++ *                                            unload.
++ *    Maciej W. Rozycki               :       FDDI support
++ *    sekiya@USAGI                    :       Don't send too many RS
++ *                                            packets.
++ *    yoshfuji@USAGI                  :       Fixed interval between DAD
++ *                                            packets.
++ *    YOSHIFUJI Hideaki @USAGI        :       improved accuracy of
++ *                                            address validation timer.
++ *    YOSHIFUJI Hideaki @USAGI        :       Privacy Extensions (RFC3041)
++ *                                            support.
++ *    Yuji SEKIYA @USAGI              :       Don't assign a same IPv6
++ *                                            address on a same interface.
++ *    YOSHIFUJI Hideaki @USAGI        :       ARCnet support
++ *    YOSHIFUJI Hideaki @USAGI        :       convert /proc/net/if_inet6 to
++ *                                            seq_file.
++ *    YOSHIFUJI Hideaki @USAGI        :       improved source address
++ *                                            selection; consider scope,
++ *                                            status etc.
++ */
++
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/socket.h>
++#include <linux/sockios.h>
++#include <linux/net.h>
++#include <linux/in6.h>
++#include <linux/netdevice.h>
++#include <linux/if_addr.h>
++#include <linux/if_arp.h>
++#include <linux/if_arcnet.h>
++#include <linux/if_infiniband.h>
++#include <linux/route.h>
++#include <linux/inetdevice.h>
++#include <linux/init.h>
++#ifdef CONFIG_SYSCTL
++#include <linux/sysctl.h>
++#endif
++#include <linux/capability.h>
++#include <linux/delay.h>
++#include <linux/notifier.h>
++#include <linux/string.h>
++
++#include <net/sock.h>
++#include <net/snmp.h>
++
++#include <net/ipv6.h>
++#include <net/protocol.h>
++#include <net/ndisc.h>
++#include <net/ip6_route.h>
++#include <net/addrconf.h>
++#include <net/tcp.h>
++#include <net/ip.h>
++#include <net/netlink.h>
++#include <net/pkt_sched.h>
++#include <linux/if_tunnel.h>
++#include <linux/rtnetlink.h>
++
++#ifdef CONFIG_IPV6_PRIVACY
++#include <linux/random.h>
++#endif
++
++#include <asm/uaccess.h>
++#include <asm/unaligned.h>
++
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++
++/* Set to 3 to get tracing... */
++#define ACONF_DEBUG 2
++
++#if ACONF_DEBUG >= 3
++#define ADBG(x) printk x
++#else
++#define ADBG(x)
++#endif
++
++#define       INFINITY_LIFE_TIME      0xFFFFFFFF
++#define TIME_DELTA(a,b) ((unsigned long)((long)(a) - (long)(b)))
++
++#ifdef CONFIG_SYSCTL
++static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf *p);
++static void addrconf_sysctl_unregister(struct ipv6_devconf *p);
++#endif
++
++#ifdef CONFIG_IPV6_PRIVACY
++static int __ipv6_regen_rndid(struct inet6_dev *idev);
++static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
++static void ipv6_regen_rndid(unsigned long data);
++
++static int desync_factor = MAX_DESYNC_FACTOR * HZ;
++#endif
++
++static int ipv6_count_addresses(struct inet6_dev *idev);
++
++/*
++ *    Configured unicast address hash table
++ */
++static struct inet6_ifaddr            *inet6_addr_lst[IN6_ADDR_HSIZE];
++static DEFINE_RWLOCK(addrconf_hash_lock);
++
++static void addrconf_verify(unsigned long);
++
++static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0);
++static DEFINE_SPINLOCK(addrconf_verify_lock);
++
++static void addrconf_join_anycast(struct inet6_ifaddr *ifp);
++static void addrconf_leave_anycast(struct inet6_ifaddr *ifp);
++
++static int addrconf_ifdown(struct net_device *dev, int how);
++
++static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags);
++static void addrconf_dad_timer(unsigned long data);
++static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
++static void addrconf_dad_run(struct inet6_dev *idev);
++static void addrconf_rs_timer(unsigned long data);
++static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
++static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
++
++static void inet6_prefix_notify(int event, struct inet6_dev *idev,
++                              struct prefix_info *pinfo);
++static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev);
++
++static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
++
++struct ipv6_devconf ipv6_devconf __read_mostly = {
++      .forwarding             = 0,
++      .hop_limit              = IPV6_DEFAULT_HOPLIMIT,
++      .mtu6                   = IPV6_MIN_MTU,
++      .accept_ra              = 1,
++      .accept_redirects       = 1,
++      .autoconf               = 1,
++      .force_mld_version      = 0,
++      .dad_transmits          = 1,
++      .rtr_solicits           = MAX_RTR_SOLICITATIONS,
++      .rtr_solicit_interval   = RTR_SOLICITATION_INTERVAL,
++      .rtr_solicit_delay      = MAX_RTR_SOLICITATION_DELAY,
++#ifdef CONFIG_IPV6_PRIVACY
++      .use_tempaddr           = 0,
++      .temp_valid_lft         = TEMP_VALID_LIFETIME,
++      .temp_prefered_lft      = TEMP_PREFERRED_LIFETIME,
++      .regen_max_retry        = REGEN_MAX_RETRY,
++      .max_desync_factor      = MAX_DESYNC_FACTOR,
++#endif
++      .max_addresses          = IPV6_MAX_ADDRESSES,
++      .accept_ra_defrtr       = 1,
++      .accept_ra_pinfo        = 1,
++#ifdef CONFIG_IPV6_ROUTER_PREF
++      .accept_ra_rtr_pref     = 1,
++      .rtr_probe_interval     = 60 * HZ,
++#ifdef CONFIG_IPV6_ROUTE_INFO
++      .accept_ra_rt_info_max_plen = 0,
++#endif
++#endif
++      .proxy_ndp              = 0,
++      .accept_source_route    = 0,    /* we do not accept RH0 by default. */
++};
++
++static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
++      .forwarding             = 0,
++      .hop_limit              = IPV6_DEFAULT_HOPLIMIT,
++      .mtu6                   = IPV6_MIN_MTU,
++      .accept_ra              = 1,
++      .accept_redirects       = 1,
++      .autoconf               = 1,
++      .dad_transmits          = 1,
++      .rtr_solicits           = MAX_RTR_SOLICITATIONS,
++      .rtr_solicit_interval   = RTR_SOLICITATION_INTERVAL,
++      .rtr_solicit_delay      = MAX_RTR_SOLICITATION_DELAY,
++#ifdef CONFIG_IPV6_PRIVACY
++      .use_tempaddr           = 0,
++      .temp_valid_lft         = TEMP_VALID_LIFETIME,
++      .temp_prefered_lft      = TEMP_PREFERRED_LIFETIME,
++      .regen_max_retry        = REGEN_MAX_RETRY,
++      .max_desync_factor      = MAX_DESYNC_FACTOR,
++#endif
++      .max_addresses          = IPV6_MAX_ADDRESSES,
++      .accept_ra_defrtr       = 1,
++      .accept_ra_pinfo        = 1,
++#ifdef CONFIG_IPV6_ROUTER_PREF
++      .accept_ra_rtr_pref     = 1,
++      .rtr_probe_interval     = 60 * HZ,
++#ifdef CONFIG_IPV6_ROUTE_INFO
++      .accept_ra_rt_info_max_plen = 0,
++#endif
++#endif
++      .proxy_ndp              = 0,
++      .accept_source_route    = 0,    /* we do not accept RH0 by default. */
++};
++
++/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
++const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
++const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
++
++/* Check if a valid qdisc is available */
++static inline int addrconf_qdisc_ok(struct net_device *dev)
++{
++      return (dev->qdisc != &noop_qdisc);
++}
++
++static void addrconf_del_timer(struct inet6_ifaddr *ifp)
++{
++      if (del_timer(&ifp->timer))
++              __in6_ifa_put(ifp);
++}
++
++enum addrconf_timer_t
++{
++      AC_NONE,
++      AC_DAD,
++      AC_RS,
++};
++
++static void addrconf_mod_timer(struct inet6_ifaddr *ifp,
++                             enum addrconf_timer_t what,
++                             unsigned long when)
++{
++      if (!del_timer(&ifp->timer))
++              in6_ifa_hold(ifp);
++
++      switch (what) {
++      case AC_DAD:
++              ifp->timer.function = addrconf_dad_timer;
++              break;
++      case AC_RS:
++              ifp->timer.function = addrconf_rs_timer;
++              break;
++      default:;
++      }
++      ifp->timer.expires = jiffies + when;
++      add_timer(&ifp->timer);
++}
++
++static int snmp6_alloc_dev(struct inet6_dev *idev)
++{
++      int err = -ENOMEM;
++
++      if (!idev || !idev->dev)
++              return -EINVAL;
++
++      if (snmp_mib_init((void **)idev->stats.ipv6,
++                        sizeof(struct ipstats_mib),
++                        __alignof__(struct ipstats_mib)) < 0)
++              goto err_ip;
++      if (snmp_mib_init((void **)idev->stats.icmpv6,
++                        sizeof(struct icmpv6_mib),
++                        __alignof__(struct icmpv6_mib)) < 0)
++              goto err_icmp;
++
++      return 0;
++
++err_icmp:
++      snmp_mib_free((void **)idev->stats.ipv6);
++err_ip:
++      return err;
++}
++
++static int snmp6_free_dev(struct inet6_dev *idev)
++{
++      snmp_mib_free((void **)idev->stats.icmpv6);
++      snmp_mib_free((void **)idev->stats.ipv6);
++      return 0;
++}
++
++/* Nobody refers to this device, we may destroy it. */
++
++static void in6_dev_finish_destroy_rcu(struct rcu_head *head)
++{
++      struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu);
++      kfree(idev);
++}
++
++void in6_dev_finish_destroy(struct inet6_dev *idev)
++{
++      struct net_device *dev = idev->dev;
++      BUG_TRAP(idev->addr_list==NULL);
++      BUG_TRAP(idev->mc_list==NULL);
++#ifdef NET_REFCNT_DEBUG
++      printk(KERN_DEBUG "in6_dev_finish_destroy: %s\n", dev ? dev->name : "NIL");
++#endif
++      dev_put(dev);
++      if (!idev->dead) {
++              printk("Freeing alive inet6 device %p\n", idev);
++              return;
++      }
++      snmp6_free_dev(idev);
++      call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu);
++}
++
++EXPORT_SYMBOL(in6_dev_finish_destroy);
++
++static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
++{
++      struct inet6_dev *ndev;
++      struct in6_addr maddr;
++
++      ASSERT_RTNL();
++
++      if (dev->mtu < IPV6_MIN_MTU)
++              return NULL;
++
++      ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL);
++
++      if (ndev == NULL)
++              return NULL;
++
++      rwlock_init(&ndev->lock);
++      ndev->dev = dev;
++      memcpy(&ndev->cnf, &ipv6_devconf_dflt, sizeof(ndev->cnf));
++      ndev->cnf.mtu6 = dev->mtu;
++      ndev->cnf.sysctl = NULL;
++      ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
++      if (ndev->nd_parms == NULL) {
++              kfree(ndev);
++              return NULL;
++      }
++      /* We refer to the device */
++      dev_hold(dev);
++
++      if (snmp6_alloc_dev(ndev) < 0) {
++              ADBG((KERN_WARNING
++                      "%s(): cannot allocate memory for statistics; dev=%s.\n",
++                      __FUNCTION__, dev->name));
++              neigh_parms_release(&nd_tbl, ndev->nd_parms);
++              ndev->dead = 1;
++              in6_dev_finish_destroy(ndev);
++              return NULL;
++      }
++
++      if (snmp6_register_dev(ndev) < 0) {
++              ADBG((KERN_WARNING
++                      "%s(): cannot create /proc/net/dev_snmp6/%s\n",
++                      __FUNCTION__, dev->name));
++              neigh_parms_release(&nd_tbl, ndev->nd_parms);
++              ndev->dead = 1;
++              in6_dev_finish_destroy(ndev);
++              return NULL;
++      }
++
++      /* One reference from device.  We must do this before
++       * we invoke __ipv6_regen_rndid().
++       */
++      in6_dev_hold(ndev);
++
++#ifdef CONFIG_IPV6_PRIVACY
++      init_timer(&ndev->regen_timer);
++      ndev->regen_timer.function = ipv6_regen_rndid;
++      ndev->regen_timer.data = (unsigned long) ndev;
++      if ((dev->flags&IFF_LOOPBACK) ||
++          dev->type == ARPHRD_TUNNEL ||
++#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
++          dev->type == ARPHRD_SIT ||
++#endif
++          dev->type == ARPHRD_NONE) {
++              printk(KERN_INFO
++                     "%s: Disabled Privacy Extensions\n",
++                     dev->name);
++              ndev->cnf.use_tempaddr = -1;
++      } else {
++              in6_dev_hold(ndev);
++              ipv6_regen_rndid((unsigned long) ndev);
++      }
++#endif
++
++      if (netif_running(dev) && addrconf_qdisc_ok(dev))
++              ndev->if_flags |= IF_READY;
++
++      ipv6_mc_init_dev(ndev);
++      ndev->tstamp = jiffies;
++#ifdef CONFIG_SYSCTL
++      neigh_sysctl_register(dev, ndev->nd_parms, NET_IPV6,
++                            NET_IPV6_NEIGH, "ipv6",
++                            &ndisc_ifinfo_sysctl_change,
++                            NULL);
++      addrconf_sysctl_register(ndev, &ndev->cnf);
++#endif
++      /* protected by rtnl_lock */
++      rcu_assign_pointer(dev->ip6_ptr, ndev);
++
++      /* Join all-node multicast group */
++      ipv6_addr_all_nodes(&maddr);
++      ipv6_dev_mc_inc(dev, &maddr);
++
++      return ndev;
++}
++
++static struct inet6_dev * ipv6_find_idev(struct net_device *dev)
++{
++      struct inet6_dev *idev;
++
++      ASSERT_RTNL();
++
++      if ((idev = __in6_dev_get(dev)) == NULL) {
++              if ((idev = ipv6_add_dev(dev)) == NULL)
++                      return NULL;
++      }
++
++      if (dev->flags&IFF_UP)
++              ipv6_mc_up(idev);
++      return idev;
++}
++
++#ifdef CONFIG_SYSCTL
++static void dev_forward_change(struct inet6_dev *idev)
++{
++      struct net_device *dev;
++      struct inet6_ifaddr *ifa;
++      struct in6_addr addr;
++
++      if (!idev)
++              return;
++      dev = idev->dev;
++      if (dev && (dev->flags & IFF_MULTICAST)) {
++              ipv6_addr_all_routers(&addr);
++
++              if (idev->cnf.forwarding)
++                      ipv6_dev_mc_inc(dev, &addr);
++              else
++                      ipv6_dev_mc_dec(dev, &addr);
++      }
++      for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
++              if (ifa->flags&IFA_F_TENTATIVE)
++                      continue;
++              if (idev->cnf.forwarding)
++                      addrconf_join_anycast(ifa);
++              else
++                      addrconf_leave_anycast(ifa);
++      }
++}
++
++
++static void addrconf_forward_change(void)
++{
++      struct net_device *dev;
++      struct inet6_dev *idev;
++
++      read_lock(&dev_base_lock);
++      for_each_netdev(dev) {
++              rcu_read_lock();
++              idev = __in6_dev_get(dev);
++              if (idev) {
++                      int changed = (!idev->cnf.forwarding) ^ (!ipv6_devconf.forwarding);
++                      idev->cnf.forwarding = ipv6_devconf.forwarding;
++                      if (changed)
++                              dev_forward_change(idev);
++              }
++              rcu_read_unlock();
++      }
++      read_unlock(&dev_base_lock);
++}
++#endif
++
++/* Nobody refers to this ifaddr, destroy it */
++
++void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
++{
++      BUG_TRAP(ifp->if_next==NULL);
++      BUG_TRAP(ifp->lst_next==NULL);
++#ifdef NET_REFCNT_DEBUG
++      printk(KERN_DEBUG "inet6_ifa_finish_destroy\n");
++#endif
++
++      in6_dev_put(ifp->idev);
++
++      if (del_timer(&ifp->timer))
++              printk("Timer is still running, when freeing ifa=%p\n", ifp);
++
++      if (!ifp->dead) {
++              printk("Freeing alive inet6 address %p\n", ifp);
++              return;
++      }
++      dst_release(&ifp->rt->u.dst);
++
++      kfree(ifp);
++}
++
++static void
++ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp)
++{
++      struct inet6_ifaddr *ifa, **ifap;
++      int ifp_scope = ipv6_addr_src_scope(&ifp->addr);
++
++      /*
++       * Each device address list is sorted in order of scope -
++       * global before linklocal.
++       */
++      for (ifap = &idev->addr_list; (ifa = *ifap) != NULL;
++           ifap = &ifa->if_next) {
++              if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr))
++                      break;
++      }
++
++      ifp->if_next = *ifap;
++      *ifap = ifp;
++}
++
++/* On success it returns ifp with increased reference count */
++
++static struct inet6_ifaddr *
++ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
++            int scope, u32 flags)
++{
++      struct inet6_ifaddr *ifa = NULL;
++      struct rt6_info *rt;
++      int hash;
++      int err = 0;
++
++      rcu_read_lock_bh();
++      if (idev->dead) {
++              err = -ENODEV;                  /*XXX*/
++              goto out2;
++      }
++
++      write_lock(&addrconf_hash_lock);
++
++      /* Ignore adding duplicate addresses on an interface */
++      if (ipv6_chk_same_addr(addr, idev->dev)) {
++              ADBG(("ipv6_add_addr: already assigned\n"));
++              err = -EEXIST;
++              goto out;
++      }
++
++      ifa = kzalloc(sizeof(struct inet6_ifaddr), GFP_ATOMIC);
++
++      if (ifa == NULL) {
++              ADBG(("ipv6_add_addr: malloc failed\n"));
++              err = -ENOBUFS;
++              goto out;
++      }
++
++      rt = addrconf_dst_alloc(idev, addr, 0);
++      if (IS_ERR(rt)) {
++              err = PTR_ERR(rt);
++              goto out;
++      }
++
++      ipv6_addr_copy(&ifa->addr, addr);
++
++      spin_lock_init(&ifa->lock);
++      init_timer(&ifa->timer);
++      ifa->timer.data = (unsigned long) ifa;
++      ifa->scope = scope;
++      ifa->prefix_len = pfxlen;
++      ifa->flags = flags | IFA_F_TENTATIVE;
++      ifa->cstamp = ifa->tstamp = jiffies;
++
++      ifa->rt = rt;
++
++      /*
++       * part one of RFC 4429, section 3.3
++       * We should not configure an address as
++       * optimistic if we do not yet know the link
++       * layer address of our nexhop router
++       */
++
++      if (rt->rt6i_nexthop == NULL)
++              ifa->flags &= ~IFA_F_OPTIMISTIC;
++
++      ifa->idev = idev;
++      in6_dev_hold(idev);
++      /* For caller */
++      in6_ifa_hold(ifa);
++
++      /* Add to big hash table */
++      hash = ipv6_addr_hash(addr);
++
++      ifa->lst_next = inet6_addr_lst[hash];
++      inet6_addr_lst[hash] = ifa;
++      in6_ifa_hold(ifa);
++      write_unlock(&addrconf_hash_lock);
++
++      write_lock(&idev->lock);
++      /* Add to inet6_dev unicast addr list. */
++      ipv6_link_dev_addr(idev, ifa);
++
++#ifdef CONFIG_IPV6_PRIVACY
++      if (ifa->flags&IFA_F_TEMPORARY) {
++              ifa->tmp_next = idev->tempaddr_list;
++              idev->tempaddr_list = ifa;
++              in6_ifa_hold(ifa);
++      }
++#endif
++
++      in6_ifa_hold(ifa);
++      write_unlock(&idev->lock);
++out2:
++      rcu_read_unlock_bh();
++
++      if (likely(err == 0))
++              atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
++      else {
++              kfree(ifa);
++              ifa = ERR_PTR(err);
++      }
++
++      return ifa;
++out:
++      write_unlock(&addrconf_hash_lock);
++      goto out2;
++}
++
++/* This function wants to get referenced ifp and releases it before return */
++
++static void ipv6_del_addr(struct inet6_ifaddr *ifp)
++{
++      struct inet6_ifaddr *ifa, **ifap;
++      struct inet6_dev *idev = ifp->idev;
++      int hash;
++      int deleted = 0, onlink = 0;
++      unsigned long expires = jiffies;
++
++      hash = ipv6_addr_hash(&ifp->addr);
++
++      ifp->dead = 1;
++
++      write_lock_bh(&addrconf_hash_lock);
++      for (ifap = &inet6_addr_lst[hash]; (ifa=*ifap) != NULL;
++           ifap = &ifa->lst_next) {
++              if (ifa == ifp) {
++                      *ifap = ifa->lst_next;
++                      __in6_ifa_put(ifp);
++                      ifa->lst_next = NULL;
++                      break;
++              }
++      }
++      write_unlock_bh(&addrconf_hash_lock);
++
++      write_lock_bh(&idev->lock);
++#ifdef CONFIG_IPV6_PRIVACY
++      if (ifp->flags&IFA_F_TEMPORARY) {
++              for (ifap = &idev->tempaddr_list; (ifa=*ifap) != NULL;
++                   ifap = &ifa->tmp_next) {
++                      if (ifa == ifp) {
++                              *ifap = ifa->tmp_next;
++                              if (ifp->ifpub) {
++                                      in6_ifa_put(ifp->ifpub);
++                                      ifp->ifpub = NULL;
++                              }
++                              __in6_ifa_put(ifp);
++                              ifa->tmp_next = NULL;
++                              break;
++                      }
++              }
++      }
++#endif
++
++      for (ifap = &idev->addr_list; (ifa=*ifap) != NULL;) {
++              if (ifa == ifp) {
++                      *ifap = ifa->if_next;
++                      __in6_ifa_put(ifp);
++                      ifa->if_next = NULL;
++                      if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0)
++                              break;
++                      deleted = 1;
++                      continue;
++              } else if (ifp->flags & IFA_F_PERMANENT) {
++                      if (ipv6_prefix_equal(&ifa->addr, &ifp->addr,
++                                            ifp->prefix_len)) {
++                              if (ifa->flags & IFA_F_PERMANENT) {
++                                      onlink = 1;
++                                      if (deleted)
++                                              break;
++                              } else {
++                                      unsigned long lifetime;
++
++                                      if (!onlink)
++                                              onlink = -1;
++
++                                      spin_lock(&ifa->lock);
++                                      lifetime = min_t(unsigned long,
++                                                       ifa->valid_lft, 0x7fffffffUL/HZ);
++                                      if (time_before(expires,
++                                                      ifa->tstamp + lifetime * HZ))
++                                              expires = ifa->tstamp + lifetime * HZ;
++                                      spin_unlock(&ifa->lock);
++                              }
++                      }
++              }
++              ifap = &ifa->if_next;
++      }
++      write_unlock_bh(&idev->lock);
++
++      ipv6_ifa_notify(RTM_DELADDR, ifp);
++
++      atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp);
++
++      addrconf_del_timer(ifp);
++
++      /*
++       * Purge or update corresponding prefix
++       *
++       * 1) we don't purge prefix here if address was not permanent.
++       *    prefix is managed by its own lifetime.
++       * 2) if there're no addresses, delete prefix.
++       * 3) if there're still other permanent address(es),
++       *    corresponding prefix is still permanent.
++       * 4) otherwise, update prefix lifetime to the
++       *    longest valid lifetime among the corresponding
++       *    addresses on the device.
++       *    Note: subsequent RA will update lifetime.
++       *
++       * --yoshfuji
++       */
++      if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) {
++              struct in6_addr prefix;
++              struct rt6_info *rt;
++
++              ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
++              rt = rt6_lookup(&prefix, NULL, ifp->idev->dev->ifindex, 1);
++
++              if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
++                      if (onlink == 0) {
++                              ip6_del_rt(rt);
++                              rt = NULL;
++                      } else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
++                              rt->rt6i_expires = expires;
++                              rt->rt6i_flags |= RTF_EXPIRES;
++                      }
++              }
++              dst_release(&rt->u.dst);
++      }
++
++      in6_ifa_put(ifp);
++}
++
++#ifdef CONFIG_IPV6_PRIVACY
++static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *ift)
++{
++      struct inet6_dev *idev = ifp->idev;
++      struct in6_addr addr, *tmpaddr;
++      unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp;
++      int tmp_plen;
++      int ret = 0;
++      int max_addresses;
++      u32 addr_flags;
++
++      write_lock(&idev->lock);
++      if (ift) {
++              spin_lock_bh(&ift->lock);
++              memcpy(&addr.s6_addr[8], &ift->addr.s6_addr[8], 8);
++              spin_unlock_bh(&ift->lock);
++              tmpaddr = &addr;
++      } else {
++              tmpaddr = NULL;
++      }
++retry:
++      in6_dev_hold(idev);
++      if (idev->cnf.use_tempaddr <= 0) {
++              write_unlock(&idev->lock);
++              printk(KERN_INFO
++                      "ipv6_create_tempaddr(): use_tempaddr is disabled.\n");
++              in6_dev_put(idev);
++              ret = -1;
++              goto out;
++      }
++      spin_lock_bh(&ifp->lock);
++      if (ifp->regen_count++ >= idev->cnf.regen_max_retry) {
++              idev->cnf.use_tempaddr = -1;    /*XXX*/
++              spin_unlock_bh(&ifp->lock);
++              write_unlock(&idev->lock);
++              printk(KERN_WARNING
++                      "ipv6_create_tempaddr(): regeneration time exceeded. disabled temporary address support.\n");
++              in6_dev_put(idev);
++              ret = -1;
++              goto out;
++      }
++      in6_ifa_hold(ifp);
++      memcpy(addr.s6_addr, ifp->addr.s6_addr, 8);
++      if (__ipv6_try_regen_rndid(idev, tmpaddr) < 0) {
++              spin_unlock_bh(&ifp->lock);
++              write_unlock(&idev->lock);
++              printk(KERN_WARNING
++                      "ipv6_create_tempaddr(): regeneration of randomized interface id failed.\n");
++              in6_ifa_put(ifp);
++              in6_dev_put(idev);
++              ret = -1;
++              goto out;
++      }
++      memcpy(&addr.s6_addr[8], idev->rndid, 8);
++      tmp_valid_lft = min_t(__u32,
++                            ifp->valid_lft,
++                            idev->cnf.temp_valid_lft);
++      tmp_prefered_lft = min_t(__u32,
++                               ifp->prefered_lft,
++                               idev->cnf.temp_prefered_lft - desync_factor / HZ);
++      tmp_plen = ifp->prefix_len;
++      max_addresses = idev->cnf.max_addresses;
++      tmp_cstamp = ifp->cstamp;
++      tmp_tstamp = ifp->tstamp;
++      spin_unlock_bh(&ifp->lock);
++
++      write_unlock(&idev->lock);
++
++      addr_flags = IFA_F_TEMPORARY;
++      /* set in addrconf_prefix_rcv() */
++      if (ifp->flags & IFA_F_OPTIMISTIC)
++              addr_flags |= IFA_F_OPTIMISTIC;
++
++      ift = !max_addresses ||
++            ipv6_count_addresses(idev) < max_addresses ?
++              ipv6_add_addr(idev, &addr, tmp_plen,
++                            ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK,
++                            addr_flags) : NULL;
++      if (!ift || IS_ERR(ift)) {
++              in6_ifa_put(ifp);
++              in6_dev_put(idev);
++              printk(KERN_INFO
++                      "ipv6_create_tempaddr(): retry temporary address regeneration.\n");
++              tmpaddr = &addr;
++              write_lock(&idev->lock);
++              goto retry;
++      }
++
++      spin_lock_bh(&ift->lock);
++      ift->ifpub = ifp;
++      ift->valid_lft = tmp_valid_lft;
++      ift->prefered_lft = tmp_prefered_lft;
++      ift->cstamp = tmp_cstamp;
++      ift->tstamp = tmp_tstamp;
++      spin_unlock_bh(&ift->lock);
++
++      addrconf_dad_start(ift, 0);
++      in6_ifa_put(ift);
++      in6_dev_put(idev);
++out:
++      return ret;
++}
++#endif
++
++/*
++ *    Choose an appropriate source address (RFC3484)
++ */
++struct ipv6_saddr_score {
++      int             addr_type;
++      unsigned int    attrs;
++      int             matchlen;
++      int             scope;
++      unsigned int    rule;
++};
++
++#define IPV6_SADDR_SCORE_LOCAL                0x0001
++#define IPV6_SADDR_SCORE_PREFERRED    0x0004
++#define IPV6_SADDR_SCORE_HOA          0x0008
++#define IPV6_SADDR_SCORE_OIF          0x0010
++#define IPV6_SADDR_SCORE_LABEL                0x0020
++#define IPV6_SADDR_SCORE_PRIVACY      0x0040
++
++static inline int ipv6_saddr_preferred(int type)
++{
++      if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4|
++                  IPV6_ADDR_LOOPBACK|IPV6_ADDR_RESERVED))
++              return 1;
++      return 0;
++}
++
++/* static matching label */
++static inline int ipv6_saddr_label(const struct in6_addr *addr, int type)
++{
++ /*
++  *   prefix (longest match)  label
++  *   -----------------------------
++  *   ::1/128                 0
++  *   ::/0                    1
++  *   2002::/16               2
++  *   ::/96                   3
++  *   ::ffff:0:0/96           4
++  *   fc00::/7                5
++  *   2001::/32               6
++  */
++      if (type & IPV6_ADDR_LOOPBACK)
++              return 0;
++      else if (type & IPV6_ADDR_COMPATv4)
++              return 3;
++      else if (type & IPV6_ADDR_MAPPED)
++              return 4;
++      else if (addr->s6_addr32[0] == htonl(0x20010000))
++              return 6;
++      else if (addr->s6_addr16[0] == htons(0x2002))
++              return 2;
++      else if ((addr->s6_addr[0] & 0xfe) == 0xfc)
++              return 5;
++      return 1;
++}
++
++int ipv6_dev_get_saddr(struct net_device *daddr_dev,
++                     struct in6_addr *daddr, struct in6_addr *saddr)
++{
++      struct ipv6_saddr_score hiscore;
++      struct inet6_ifaddr *ifa_result = NULL;
++      int daddr_type = __ipv6_addr_type(daddr);
++      int daddr_scope = __ipv6_addr_src_scope(daddr_type);
++      u32 daddr_label = ipv6_saddr_label(daddr, daddr_type);
++      struct net_device *dev;
++
++      memset(&hiscore, 0, sizeof(hiscore));
++
++      read_lock(&dev_base_lock);
++      rcu_read_lock();
++
++      for_each_netdev(dev) {
++              struct inet6_dev *idev;
++              struct inet6_ifaddr *ifa;
++
++              /* Rule 0: Candidate Source Address (section 4)
++               *  - multicast and link-local destination address,
++               *    the set of candidate source address MUST only
++               *    include addresses assigned to interfaces
++               *    belonging to the same link as the outgoing
++               *    interface.
++               * (- For site-local destination addresses, the
++               *    set of candidate source addresses MUST only
++               *    include addresses assigned to interfaces
++               *    belonging to the same site as the outgoing
++               *    interface.)
++               */
++              if ((daddr_type & IPV6_ADDR_MULTICAST ||
++                   daddr_scope <= IPV6_ADDR_SCOPE_LINKLOCAL) &&
++                  daddr_dev && dev != daddr_dev)
++                      continue;
++
++              idev = __in6_dev_get(dev);
++              if (!idev)
++                      continue;
++
++              read_lock_bh(&idev->lock);
++              for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) {
++                      struct ipv6_saddr_score score;
++
++                      score.addr_type = __ipv6_addr_type(&ifa->addr);
++
++                      /* Rule 0:
++                       * - Tentative Address (RFC2462 section 5.4)
++                       *  - A tentative address is not considered
++                       *    "assigned to an interface" in the traditional
++                       *    sense, unless it is also flagged as optimistic.
++                       * - Candidate Source Address (section 4)
++                       *  - In any case, anycast addresses, multicast
++                       *    addresses, and the unspecified address MUST
++                       *    NOT be included in a candidate set.
++                       */
++                      if ((ifa->flags & IFA_F_TENTATIVE) &&
++                          (!(ifa->flags & IFA_F_OPTIMISTIC)))
++                              continue;
++                      if (unlikely(score.addr_type == IPV6_ADDR_ANY ||
++                                   score.addr_type & IPV6_ADDR_MULTICAST)) {
++                              LIMIT_NETDEBUG(KERN_DEBUG
++                                             "ADDRCONF: unspecified / multicast address"
++                                             "assigned as unicast address on %s",
++                                             dev->name);
++                              continue;
++                      }
++
++                      score.attrs = 0;
++                      score.matchlen = 0;
++                      score.scope = 0;
++                      score.rule = 0;
++
++                      if (ifa_result == NULL) {
++                              /* record it if the first available entry */
++                              goto record_it;
++                      }
++
++                      /* Rule 1: Prefer same address */
++                      if (hiscore.rule < 1) {
++                              if (ipv6_addr_equal(&ifa_result->addr, daddr))
++                                      hiscore.attrs |= IPV6_SADDR_SCORE_LOCAL;
++                              hiscore.rule++;
++                      }
++                      if (ipv6_addr_equal(&ifa->addr, daddr)) {
++                              score.attrs |= IPV6_SADDR_SCORE_LOCAL;
++                              if (!(hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)) {
++                                      score.rule = 1;
++                                      goto record_it;
++                              }
++                      } else {
++                              if (hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)
++                                      continue;
++                      }
++
++                      /* Rule 2: Prefer appropriate scope */
++                      if (hiscore.rule < 2) {
++                              hiscore.scope = __ipv6_addr_src_scope(hiscore.addr_type);
++                              hiscore.rule++;
++                      }
++                      score.scope = __ipv6_addr_src_scope(score.addr_type);
++                      if (hiscore.scope < score.scope) {
++                              if (hiscore.scope < daddr_scope) {
++                                      score.rule = 2;
++                                      goto record_it;
++                              } else
++                                      continue;
++                      } else if (score.scope < hiscore.scope) {
++                              if (score.scope < daddr_scope)
++                                      break; /* addresses sorted by scope */
++                              else {
++                                      score.rule = 2;
++                                      goto record_it;
++                              }
++                      }
++
++                      /* Rule 3: Avoid deprecated and optimistic addresses */
++                      if (hiscore.rule < 3) {
++                              if (ipv6_saddr_preferred(hiscore.addr_type) ||
++                                 (((ifa_result->flags &
++                                  (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0)))
++                                      hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED;
++                              hiscore.rule++;
++                      }
++                      if (ipv6_saddr_preferred(score.addr_type) ||
++                         (((ifa->flags &
++                          (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) {
++                              score.attrs |= IPV6_SADDR_SCORE_PREFERRED;
++                              if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) {
++                                      score.rule = 3;
++                                      goto record_it;
++                              }
++                      } else {
++                              if (hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)
++                                      continue;
++                      }
++
++                      /* Rule 4: Prefer home address */
++#ifdef CONFIG_IPV6_MIP6
++                      if (hiscore.rule < 4) {
++                              if (ifa_result->flags & IFA_F_HOMEADDRESS)
++                                      hiscore.attrs |= IPV6_SADDR_SCORE_HOA;
++                              hiscore.rule++;
++                      }
++                      if (ifa->flags & IFA_F_HOMEADDRESS) {
++                              score.attrs |= IPV6_SADDR_SCORE_HOA;
++                              if (!(ifa_result->flags & IFA_F_HOMEADDRESS)) {
++                                      score.rule = 4;
++                                      goto record_it;
++                              }
++                      } else {
++                              if (hiscore.attrs & IPV6_SADDR_SCORE_HOA)
++                                      continue;
++                      }
++#else
++                      if (hiscore.rule < 4)
++                              hiscore.rule++;
++#endif
++
++                      /* Rule 5: Prefer outgoing interface */
++                      if (hiscore.rule < 5) {
++                              if (daddr_dev == NULL ||
++                                  daddr_dev == ifa_result->idev->dev)
++                                      hiscore.attrs |= IPV6_SADDR_SCORE_OIF;
++                              hiscore.rule++;
++                      }
++                      if (daddr_dev == NULL ||
++                          daddr_dev == ifa->idev->dev) {
++                              score.attrs |= IPV6_SADDR_SCORE_OIF;
++                              if (!(hiscore.attrs & IPV6_SADDR_SCORE_OIF)) {
++                                      score.rule = 5;
++                                      goto record_it;
++                              }
++                      } else {
++                              if (hiscore.attrs & IPV6_SADDR_SCORE_OIF)
++                                      continue;
++                      }
++
++                      /* Rule 6: Prefer matching label */
++                      if (hiscore.rule < 6) {
++                              if (ipv6_saddr_label(&ifa_result->addr, hiscore.addr_type) == daddr_label)
++                                      hiscore.attrs |= IPV6_SADDR_SCORE_LABEL;
++                              hiscore.rule++;
++                      }
++                      if (ipv6_saddr_label(&ifa->addr, score.addr_type) == daddr_label) {
++                              score.attrs |= IPV6_SADDR_SCORE_LABEL;
++                              if (!(hiscore.attrs & IPV6_SADDR_SCORE_LABEL)) {
++                                      score.rule = 6;
++                                      goto record_it;
++                              }
++                      } else {
++                              if (hiscore.attrs & IPV6_SADDR_SCORE_LABEL)
++                                      continue;
++                      }
++
++#ifdef CONFIG_IPV6_PRIVACY
++                      /* Rule 7: Prefer public address
++                       * Note: prefer temprary address if use_tempaddr >= 2
++                       */
++                      if (hiscore.rule < 7) {
++                              if ((!(ifa_result->flags & IFA_F_TEMPORARY)) ^
++                                  (ifa_result->idev->cnf.use_tempaddr >= 2))
++                                      hiscore.attrs |= IPV6_SADDR_SCORE_PRIVACY;
++                              hiscore.rule++;
++                      }
++                      if ((!(ifa->flags & IFA_F_TEMPORARY)) ^
++                          (ifa->idev->cnf.use_tempaddr >= 2)) {
++                              score.attrs |= IPV6_SADDR_SCORE_PRIVACY;
++                              if (!(hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)) {
++                                      score.rule = 7;
++                                      goto record_it;
++                              }
++                      } else {
++                              if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)
++                                      continue;
++                      }
++#else
++                      if (hiscore.rule < 7)
++                              hiscore.rule++;
++#endif
++                      /* Rule 8: Use longest matching prefix */
++                      if (hiscore.rule < 8) {
++                              hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr);
++                              hiscore.rule++;
++                      }
++                      score.matchlen = ipv6_addr_diff(&ifa->addr, daddr);
++                      if (score.matchlen > hiscore.matchlen) {
++                              score.rule = 8;
++                              goto record_it;
++                      }
++#if 0
++                      else if (score.matchlen < hiscore.matchlen)
++                              continue;
++#endif
++
++                      /* Final Rule: choose first available one */
++                      continue;
++record_it:
++                      if (ifa_result)
++                              in6_ifa_put(ifa_result);
++                      in6_ifa_hold(ifa);
++                      ifa_result = ifa;
++                      hiscore = score;
++              }
++              read_unlock_bh(&idev->lock);
++      }
++      rcu_read_unlock();
++      read_unlock(&dev_base_lock);
++
++      if (!ifa_result)
++              return -EADDRNOTAVAIL;
++
++      ipv6_addr_copy(saddr, &ifa_result->addr);
++      in6_ifa_put(ifa_result);
++      return 0;
++}
++
++
++int ipv6_get_saddr(struct dst_entry *dst,
++                 struct in6_addr *daddr, struct in6_addr *saddr)
++{
++      return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr);
++}
++
++EXPORT_SYMBOL(ipv6_get_saddr);
++
++int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
++                  unsigned char banned_flags)
++{
++      struct inet6_dev *idev;
++      int err = -EADDRNOTAVAIL;
++
++      rcu_read_lock();
++      if ((idev = __in6_dev_get(dev)) != NULL) {
++              struct inet6_ifaddr *ifp;
++
++              read_lock_bh(&idev->lock);
++              for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) {
++                      if (ifp->scope == IFA_LINK && !(ifp->flags & banned_flags)) {
++                              ipv6_addr_copy(addr, &ifp->addr);
++                              err = 0;
++                              break;
++                      }
++              }
++              read_unlock_bh(&idev->lock);
++      }
++      rcu_read_unlock();
++      return err;
++}
++
++static int ipv6_count_addresses(struct inet6_dev *idev)
++{
++      int cnt = 0;
++      struct inet6_ifaddr *ifp;
++
++      read_lock_bh(&idev->lock);
++      for (ifp=idev->addr_list; ifp; ifp=ifp->if_next)
++              cnt++;
++      read_unlock_bh(&idev->lock);
++      return cnt;
++}
++
++int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev, int strict)
++{
++      struct inet6_ifaddr * ifp;
++      u8 hash = ipv6_addr_hash(addr);
++
++      read_lock_bh(&addrconf_hash_lock);
++      for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
++              if (ipv6_addr_equal(&ifp->addr, addr) &&
++                  !(ifp->flags&IFA_F_TENTATIVE)) {
++                      if (dev == NULL || ifp->idev->dev == dev ||
++                          !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))
++                              break;
++              }
++      }
++      read_unlock_bh(&addrconf_hash_lock);
++      return ifp != NULL;
++}
++
++EXPORT_SYMBOL(ipv6_chk_addr);
++
++static
++int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev)
++{
++      struct inet6_ifaddr * ifp;
++      u8 hash = ipv6_addr_hash(addr);
++
++      for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
++              if (ipv6_addr_equal(&ifp->addr, addr)) {
++                      if (dev == NULL || ifp->idev->dev == dev)
++                              break;
++              }
++      }
++      return ifp != NULL;
++}
++
++struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device *dev, int strict)
++{
++      struct inet6_ifaddr * ifp;
++      u8 hash = ipv6_addr_hash(addr);
++
++      read_lock_bh(&addrconf_hash_lock);
++      for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
++              if (ipv6_addr_equal(&ifp->addr, addr)) {
++                      if (dev == NULL || ifp->idev->dev == dev ||
++                          !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) {
++                              in6_ifa_hold(ifp);
++                              break;
++                      }
++              }
++      }
++      read_unlock_bh(&addrconf_hash_lock);
++
++      return ifp;
++}
++
++int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
++{
++      const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr;
++      const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);
++      __be32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr;
++      __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
++      int sk_ipv6only = ipv6_only_sock(sk);
++      int sk2_ipv6only = inet_v6_ipv6only(sk2);
++      int addr_type = ipv6_addr_type(sk_rcv_saddr6);
++      int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED;
++
++      if (!sk2_rcv_saddr && !sk_ipv6only)
++              return 1;
++
++      if (addr_type2 == IPV6_ADDR_ANY &&
++          !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED))
++              return 1;
++
++      if (addr_type == IPV6_ADDR_ANY &&
++          !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED))
++              return 1;
++
++      if (sk2_rcv_saddr6 &&
++          ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6))
++              return 1;
++
++      if (addr_type == IPV6_ADDR_MAPPED &&
++          !sk2_ipv6only &&
++          (!sk2_rcv_saddr || !sk_rcv_saddr || sk_rcv_saddr == sk2_rcv_saddr))
++              return 1;
++
++      return 0;
++}
++
++/* Gets referenced address, destroys ifaddr */
++
++static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
++{
++      if (ifp->flags&IFA_F_PERMANENT) {
++              spin_lock_bh(&ifp->lock);
++              addrconf_del_timer(ifp);
++              ifp->flags |= IFA_F_TENTATIVE;
++              spin_unlock_bh(&ifp->lock);
++              in6_ifa_put(ifp);
++#ifdef CONFIG_IPV6_PRIVACY
++      } else if (ifp->flags&IFA_F_TEMPORARY) {
++              struct inet6_ifaddr *ifpub;
++              spin_lock_bh(&ifp->lock);
++              ifpub = ifp->ifpub;
++              if (ifpub) {
++                      in6_ifa_hold(ifpub);
++                      spin_unlock_bh(&ifp->lock);
++                      ipv6_create_tempaddr(ifpub, ifp);
++                      in6_ifa_put(ifpub);
++              } else {
++                      spin_unlock_bh(&ifp->lock);
++              }
++              ipv6_del_addr(ifp);
++#endif
++      } else
++              ipv6_del_addr(ifp);
++}
++
++void addrconf_dad_failure(struct inet6_ifaddr *ifp)
++{
++      if (net_ratelimit())
++              printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
++      addrconf_dad_stop(ifp);
++}
++
++/* Join to solicited addr multicast group. */
++
++void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr)
++{
++      struct in6_addr maddr;
++
++      if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))
++              return;
++
++      addrconf_addr_solict_mult(addr, &maddr);
++      ipv6_dev_mc_inc(dev, &maddr);
++}
++
++void addrconf_leave_solict(struct inet6_dev *idev, struct in6_addr *addr)
++{
++      struct in6_addr maddr;
++
++      if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP))
++              return;
++
++      addrconf_addr_solict_mult(addr, &maddr);
++      __ipv6_dev_mc_dec(idev, &maddr);
++}
++
++static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
++{
++      struct in6_addr addr;
++      ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
++      if (ipv6_addr_any(&addr))
++              return;
++      ipv6_dev_ac_inc(ifp->idev->dev, &addr);
++}
++
++static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
++{
++      struct in6_addr addr;
++      ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
++      if (ipv6_addr_any(&addr))
++              return;
++      __ipv6_dev_ac_dec(ifp->idev, &addr);
++}
++
++static int addrconf_ifid_eui48(u8 *eui, struct net_device *dev)
++{
++      if (dev->addr_len != ETH_ALEN)
++              return -1;
++      memcpy(eui, dev->dev_addr, 3);
++      memcpy(eui + 5, dev->dev_addr + 3, 3);
++
++      /*
++       * The zSeries OSA network cards can be shared among various
++       * OS instances, but the OSA cards have only one MAC address.
++       * This leads to duplicate address conflicts in conjunction
++       * with IPv6 if more than one instance uses the same card.
++       *
++       * The driver for these cards can deliver a unique 16-bit
++       * identifier for each instance sharing the same card.  It is
++       * placed instead of 0xFFFE in the interface identifier.  The
++       * "u" bit of the interface identifier is not inverted in this
++       * case.  Hence the resulting interface identifier has local
++       * scope according to RFC2373.
++       */
++      if (dev->dev_id) {
++              eui[3] = (dev->dev_id >> 8) & 0xFF;
++              eui[4] = dev->dev_id & 0xFF;
++      } else {
++              eui[3] = 0xFF;
++              eui[4] = 0xFE;
++              eui[0] ^= 2;
++      }
++      return 0;
++}
++
++static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev)
++{
++      /* XXX: inherit EUI-64 from other interface -- yoshfuji */
++      if (dev->addr_len != ARCNET_ALEN)
++              return -1;
++      memset(eui, 0, 7);
++      eui[7] = *(u8*)dev->dev_addr;
++      return 0;
++}
++
++static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev)
++{
++      if (dev->addr_len != INFINIBAND_ALEN)
++              return -1;
++      memcpy(eui, dev->dev_addr + 12, 8);
++      eui[0] |= 2;
++      return 0;
++}
++
++static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
++{
++      switch (dev->type) {
++      case ARPHRD_ETHER:
++      case ARPHRD_FDDI:
++      case ARPHRD_IEEE802_TR:
++              return addrconf_ifid_eui48(eui, dev);
++      case ARPHRD_ARCNET:
++              return addrconf_ifid_arcnet(eui, dev);
++      case ARPHRD_INFINIBAND:
++              return addrconf_ifid_infiniband(eui, dev);
++      }
++      return -1;
++}
++
++static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
++{
++      int err = -1;
++      struct inet6_ifaddr *ifp;
++
++      read_lock_bh(&idev->lock);
++      for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) {
++              if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) {
++                      memcpy(eui, ifp->addr.s6_addr+8, 8);
++                      err = 0;
++                      break;
++              }
++      }
++      read_unlock_bh(&idev->lock);
++      return err;
++}
++
++#ifdef CONFIG_IPV6_PRIVACY
++/* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */
++static int __ipv6_regen_rndid(struct inet6_dev *idev)
++{
++regen:
++      get_random_bytes(idev->rndid, sizeof(idev->rndid));
++      idev->rndid[0] &= ~0x02;
++
++      /*
++       * <draft-ietf-ipngwg-temp-addresses-v2-00.txt>:
++       * check if generated address is not inappropriate
++       *
++       *  - Reserved subnet anycast (RFC 2526)
++       *      11111101 11....11 1xxxxxxx
++       *  - ISATAP (draft-ietf-ngtrans-isatap-13.txt) 5.1
++       *      00-00-5E-FE-xx-xx-xx-xx
++       *  - value 0
++       *  - XXX: already assigned to an address on the device
++       */
++      if (idev->rndid[0] == 0xfd &&
++          (idev->rndid[1]&idev->rndid[2]&idev->rndid[3]&idev->rndid[4]&idev->rndid[5]&idev->rndid[6]) == 0xff &&
++          (idev->rndid[7]&0x80))
++              goto regen;
++      if ((idev->rndid[0]|idev->rndid[1]) == 0) {
++              if (idev->rndid[2] == 0x5e && idev->rndid[3] == 0xfe)
++                      goto regen;
++              if ((idev->rndid[2]|idev->rndid[3]|idev->rndid[4]|idev->rndid[5]|idev->rndid[6]|idev->rndid[7]) == 0x00)
++                      goto regen;
++      }
++
++      return 0;
++}
++
++static void ipv6_regen_rndid(unsigned long data)
++{
++      struct inet6_dev *idev = (struct inet6_dev *) data;
++      unsigned long expires;
++
++      rcu_read_lock_bh();
++      write_lock_bh(&idev->lock);
++
++      if (idev->dead)
++              goto out;
++
++      if (__ipv6_regen_rndid(idev) < 0)
++              goto out;
++
++      expires = jiffies +
++              idev->cnf.temp_prefered_lft * HZ -
++              idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor;
++      if (time_before(expires, jiffies)) {
++              printk(KERN_WARNING
++                      "ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n",
++                      idev->dev->name);
++              goto out;
++      }
++
++      if (!mod_timer(&idev->regen_timer, expires))
++              in6_dev_hold(idev);
++
++out:
++      write_unlock_bh(&idev->lock);
++      rcu_read_unlock_bh();
++      in6_dev_put(idev);
++}
++
++static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr) {
++      int ret = 0;
++
++      if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0)
++              ret = __ipv6_regen_rndid(idev);
++      return ret;
++}
++#endif
++
++/*
++ *    Add prefix route.
++ */
++
++static void
++addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
++                    unsigned long expires, u32 flags)
++{
++      struct fib6_config cfg = {
++              .fc_table = RT6_TABLE_PREFIX,
++              .fc_metric = IP6_RT_PRIO_ADDRCONF,
++              .fc_ifindex = dev->ifindex,
++              .fc_expires = expires,
++              .fc_dst_len = plen,
++              .fc_flags = RTF_UP | flags,
++      };
++
++      ipv6_addr_copy(&cfg.fc_dst, pfx);
++
++      /* Prevent useless cloning on PtP SIT.
++         This thing is done here expecting that the whole
++         class of non-broadcast devices need not cloning.
++       */
++#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
++      if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
++              cfg.fc_flags |= RTF_NONEXTHOP;
++#endif
++
++      ip6_route_add(&cfg);
++}
++
++/* Create "default" multicast route to the interface */
++
++static void addrconf_add_mroute(struct net_device *dev)
++{
++      struct fib6_config cfg = {
++              .fc_table = RT6_TABLE_LOCAL,
++              .fc_metric = IP6_RT_PRIO_ADDRCONF,
++              .fc_ifindex = dev->ifindex,
++              .fc_dst_len = 8,
++              .fc_flags = RTF_UP,
++      };
++
++      ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0);
++
++      ip6_route_add(&cfg);
++}
++
++#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
++static void sit_route_add(struct net_device *dev)
++{
++      struct fib6_config cfg = {
++              .fc_table = RT6_TABLE_MAIN,
++              .fc_metric = IP6_RT_PRIO_ADDRCONF,
++              .fc_ifindex = dev->ifindex,
++              .fc_dst_len = 96,
++              .fc_flags = RTF_UP | RTF_NONEXTHOP,
++      };
++
++      /* prefix length - 96 bits "::d.d.d.d" */
++      ip6_route_add(&cfg);
++}
++#endif
++
++static void addrconf_add_lroute(struct net_device *dev)
++{
++      struct in6_addr addr;
++
++      ipv6_addr_set(&addr,  htonl(0xFE800000), 0, 0, 0);
++      addrconf_prefix_route(&addr, 64, dev, 0, 0);
++}
++
++static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
++{
++      struct inet6_dev *idev;
++
++      ASSERT_RTNL();
++
++      if ((idev = ipv6_find_idev(dev)) == NULL)
++              return NULL;
++
++      /* Add default multicast route */
++      addrconf_add_mroute(dev);
++
++      /* Add link local route */
++      addrconf_add_lroute(dev);
++      return idev;
++}
++
++void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
++{
++      struct prefix_info *pinfo;
++      __u32 valid_lft;
++      __u32 prefered_lft;
++      int addr_type;
++      unsigned long rt_expires;
++      struct inet6_dev *in6_dev;
++
++      pinfo = (struct prefix_info *) opt;
++
++      if (len < sizeof(struct prefix_info)) {
++              ADBG(("addrconf: prefix option too short\n"));
++              return;
++      }
++
++      /*
++       *      Validation checks ([ADDRCONF], page 19)
++       */
++
++      addr_type = ipv6_addr_type(&pinfo->prefix);
++
++      if (addr_type & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL))
++              return;
++
++      valid_lft = ntohl(pinfo->valid);
++      prefered_lft = ntohl(pinfo->prefered);
++
++      if (prefered_lft > valid_lft) {
++              if (net_ratelimit())
++                      printk(KERN_WARNING "addrconf: prefix option has invalid lifetime\n");
++              return;
++      }
++
++      in6_dev = in6_dev_get(dev);
++
++      if (in6_dev == NULL) {
++              if (net_ratelimit())
++                      printk(KERN_DEBUG "addrconf: device %s not configured\n", dev->name);
++              return;
++      }
++
++      /*
++       *      Two things going on here:
++       *      1) Add routes for on-link prefixes
++       *      2) Configure prefixes with the auto flag set
++       */
++
++      /* Avoid arithmetic overflow. Really, we could
++         save rt_expires in seconds, likely valid_lft,
++         but it would require division in fib gc, that it
++         not good.
++       */
++      if (valid_lft >= 0x7FFFFFFF/HZ)
++              rt_expires = 0x7FFFFFFF - (0x7FFFFFFF % HZ);
++      else
++              rt_expires = valid_lft * HZ;
++
++      /*
++       * We convert this (in jiffies) to clock_t later.
++       * Avoid arithmetic overflow there as well.
++       * Overflow can happen only if HZ < USER_HZ.
++       */
++      if (HZ < USER_HZ && rt_expires > 0x7FFFFFFF / USER_HZ)
++              rt_expires = 0x7FFFFFFF / USER_HZ;
++
++      if (pinfo->onlink) {
++              struct rt6_info *rt;
++              rt = rt6_lookup(&pinfo->prefix, NULL, dev->ifindex, 1);
++
++              if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
++                      if (rt->rt6i_flags&RTF_EXPIRES) {
++                              if (valid_lft == 0) {
++                                      ip6_del_rt(rt);
++                                      rt = NULL;
++                              } else {
++                                      rt->rt6i_expires = jiffies + rt_expires;
++                              }
++                      }
++              } else if (valid_lft) {
++                      addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
++                                            dev, jiffies_to_clock_t(rt_expires), RTF_ADDRCONF|RTF_EXPIRES|RTF_PREFIX_RT);
++              }
++              if (rt)
++                      dst_release(&rt->u.dst);
++      }
++
++      /* Try to figure out our local address for this prefix */
++
++      if (pinfo->autoconf && in6_dev->cnf.autoconf) {
++              struct inet6_ifaddr * ifp;
++              struct in6_addr addr;
++              int create = 0, update_lft = 0;
++
++              if (pinfo->prefix_len == 64) {
++                      memcpy(&addr, &pinfo->prefix, 8);
++                      if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
++                          ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
++                              in6_dev_put(in6_dev);
++                              return;
++                      }
++                      goto ok;
++              }
++              if (net_ratelimit())
++                      printk(KERN_DEBUG "IPv6 addrconf: prefix with wrong length %d\n",
++                             pinfo->prefix_len);
++              in6_dev_put(in6_dev);
++              return;
++
++ok:
++
++              ifp = ipv6_get_ifaddr(&addr, dev, 1);
++
++              if (ifp == NULL && valid_lft) {
++                      int max_addresses = in6_dev->cnf.max_addresses;
++                      u32 addr_flags = 0;
++
++#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
++                      if (in6_dev->cnf.optimistic_dad &&
++                          !ipv6_devconf.forwarding)
++                              addr_flags = IFA_F_OPTIMISTIC;
++#endif
++
++                      /* Do not allow to create too much of autoconfigured
++                       * addresses; this would be too easy way to crash kernel.
++                       */
++                      if (!max_addresses ||
++                          ipv6_count_addresses(in6_dev) < max_addresses)
++                              ifp = ipv6_add_addr(in6_dev, &addr, pinfo->prefix_len,
++                                                  addr_type&IPV6_ADDR_SCOPE_MASK,
++                                                  addr_flags);
++
++                      if (!ifp || IS_ERR(ifp)) {
++                              in6_dev_put(in6_dev);
++                              return;
++                      }
++
++                      update_lft = create = 1;
++                      ifp->cstamp = jiffies;
++                      addrconf_dad_start(ifp, RTF_ADDRCONF|RTF_PREFIX_RT);
++              }
++
++              if (ifp) {
++                      int flags;
++                      unsigned long now;
++#ifdef CONFIG_IPV6_PRIVACY
++                      struct inet6_ifaddr *ift;
++#endif
++                      u32 stored_lft;
++
++                      /* update lifetime (RFC2462 5.5.3 e) */
++                      spin_lock(&ifp->lock);
++                      now = jiffies;
++                      if (ifp->valid_lft > (now - ifp->tstamp) / HZ)
++                              stored_lft = ifp->valid_lft - (now - ifp->tstamp) / HZ;
++                      else
++                              stored_lft = 0;
++                      if (!update_lft && stored_lft) {
++                              if (valid_lft > MIN_VALID_LIFETIME ||
++                                  valid_lft > stored_lft)
++                                      update_lft = 1;
++                              else if (stored_lft <= MIN_VALID_LIFETIME) {
++                                      /* valid_lft <= stored_lft is always true */
++                                      /* XXX: IPsec */
++                                      update_lft = 0;
++                              } else {
++                                      valid_lft = MIN_VALID_LIFETIME;
++                                      if (valid_lft < prefered_lft)
++                                              prefered_lft = valid_lft;
++                                      update_lft = 1;
++                              }
++                      }
++
++                      if (update_lft) {
++                              ifp->valid_lft = valid_lft;
++                              ifp->prefered_lft = prefered_lft;
++                              ifp->tstamp = now;
++                              flags = ifp->flags;
++                              ifp->flags &= ~IFA_F_DEPRECATED;
++                              spin_unlock(&ifp->lock);
++
++                              if (!(flags&IFA_F_TENTATIVE))
++                                      ipv6_ifa_notify(0, ifp);
++                      } else
++                              spin_unlock(&ifp->lock);
 +
-       if (sock->type != SOCK_RAW &&
-           sock->type != SOCK_DGRAM &&
-           !inet_ehash_secret)
-@@ -166,7 +166,7 @@
-       BUG_TRAP(answer_prot->slab != NULL);
-       err = -ENOBUFS;
--      sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1);
-+      sk = sk_alloc(net, PF_INET6, GFP_KERNEL, answer_prot, 1);
-       if (sk == NULL)
-               goto out;
-@@ -209,7 +209,7 @@
-       inet->mc_index  = 0;
-       inet->mc_list   = NULL;
--      if (ipv4_config.no_pmtu_disc)
-+      if (init_net.sysctl_ipv4_no_pmtu_disc)
-               inet->pmtudisc = IP_PMTUDISC_DONT;
-       else
-               inet->pmtudisc = IP_PMTUDISC_WANT;
-@@ -290,7 +290,7 @@
-       /* Check if the address belongs to the host. */
-       if (addr_type == IPV6_ADDR_MAPPED) {
-               v4addr = addr->sin6_addr.s6_addr32[3];
--              if (inet_addr_type(v4addr) != RTN_LOCAL) {
-+              if (inet_addr_type(&init_net, v4addr) != RTN_LOCAL) {
-                       err = -EADDRNOTAVAIL;
-                       goto out;
-               }
-@@ -316,7 +316,7 @@
-                                       err = -EINVAL;
-                                       goto out;
-                               }
--                              dev = dev_get_by_index(sk->sk_bound_dev_if);
-+                              dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
-                               if (!dev) {
-                                       err = -ENODEV;
-                                       goto out;
-@@ -675,6 +675,7 @@
-               struct flowi fl;
-               memset(&fl, 0, sizeof(fl));
-+              fl.fl_net = &init_net;
-               fl.proto = sk->sk_protocol;
-               ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
-               ipv6_addr_copy(&fl.fl6_src, &np->saddr);
-@@ -876,9 +877,6 @@
-       ipv6_frag_init();
-       ipv6_nodata_init();
-       ipv6_destopt_init();
--#ifdef CONFIG_IPV6_MIP6
--      mip6_init();
--#endif
-       /* Init v6 transport protocols. */
-       udpv6_init();
-@@ -944,9 +942,7 @@
-       /* Cleanup code parts. */
-       ipv6_packet_cleanup();
--#ifdef CONFIG_IPV6_MIP6
--      mip6_fini();
--#endif
++#ifdef CONFIG_IPV6_PRIVACY
++                      read_lock_bh(&in6_dev->lock);
++                      /* update all temporary addresses in the list */
++                      for (ift=in6_dev->tempaddr_list; ift; ift=ift->tmp_next) {
++                              /*
++                               * When adjusting the lifetimes of an existing
++                               * temporary address, only lower the lifetimes.
++                               * Implementations must not increase the
++                               * lifetimes of an existing temporary address
++                               * when processing a Prefix Information Option.
++                               */
++                              spin_lock(&ift->lock);
++                              flags = ift->flags;
++                              if (ift->valid_lft > valid_lft &&
++                                  ift->valid_lft - valid_lft > (jiffies - ift->tstamp) / HZ)
++                                      ift->valid_lft = valid_lft + (jiffies - ift->tstamp) / HZ;
++                              if (ift->prefered_lft > prefered_lft &&
++                                  ift->prefered_lft - prefered_lft > (jiffies - ift->tstamp) / HZ)
++                                      ift->prefered_lft = prefered_lft + (jiffies - ift->tstamp) / HZ;
++                              spin_unlock(&ift->lock);
++                              if (!(flags&IFA_F_TENTATIVE))
++                                      ipv6_ifa_notify(0, ift);
++                      }
 +
-       addrconf_cleanup();
-       ip6_flowlabel_cleanup();
-       ip6_route_cleanup();
-diff -Nurb linux-2.6.22-570/net/ipv6/ah6.c linux-2.6.22-590/net/ipv6/ah6.c
---- linux-2.6.22-570/net/ipv6/ah6.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/ah6.c    2008-01-02 13:56:38.000000000 -0500
-@@ -74,7 +74,7 @@
-       return 0;
- }
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- /**
-  *    ipv6_rearrange_destopt - rearrange IPv6 destination options header
-  *    @iph: IPv6 header
-@@ -132,6 +132,8 @@
- bad:
-       return;
- }
-+#else
-+static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt) {}
- #endif
- /**
-@@ -189,10 +191,8 @@
-       while (exthdr.raw < end) {
-               switch (nexthdr) {
-               case NEXTHDR_DEST:
--#ifdef CONFIG_IPV6_MIP6
-                       if (dir == XFRM_POLICY_OUT)
-                               ipv6_rearrange_destopt(iph, exthdr.opth);
--#endif
-               case NEXTHDR_HOP:
-                       if (!zero_out_mutable_opts(exthdr.opth)) {
-                               LIMIT_NETDEBUG(
-@@ -228,7 +228,7 @@
-       u8 nexthdr;
-       char tmp_base[8];
-       struct {
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-               struct in6_addr saddr;
- #endif
-               struct in6_addr daddr;
-@@ -255,7 +255,7 @@
-                       err = -ENOMEM;
-                       goto error;
-               }
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-               memcpy(tmp_ext, &top_iph->saddr, extlen);
- #else
-               memcpy(tmp_ext, &top_iph->daddr, extlen);
-@@ -294,7 +294,7 @@
-       memcpy(top_iph, tmp_base, sizeof(tmp_base));
-       if (tmp_ext) {
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-               memcpy(&top_iph->saddr, tmp_ext, extlen);
- #else
-               memcpy(&top_iph->daddr, tmp_ext, extlen);
-@@ -554,3 +554,4 @@
- module_exit(ah6_fini);
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_AH);
-diff -Nurb linux-2.6.22-570/net/ipv6/anycast.c linux-2.6.22-590/net/ipv6/anycast.c
---- linux-2.6.22-570/net/ipv6/anycast.c        2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/anycast.c        2008-01-02 13:56:38.000000000 -0500
-@@ -32,6 +32,7 @@
- #include <net/sock.h>
- #include <net/snmp.h>
-+#include <net/net_namespace.h>
- #include <net/ipv6.h>
- #include <net/protocol.h>
-@@ -112,10 +113,10 @@
-               } else {
-                       /* router, no matching interface: just pick one */
--                      dev = dev_get_by_flags(IFF_UP, IFF_UP|IFF_LOOPBACK);
-+                      dev = dev_get_by_flags(&init_net, IFF_UP, IFF_UP|IFF_LOOPBACK);
-               }
-       } else
--              dev = dev_get_by_index(ifindex);
-+              dev = dev_get_by_index(&init_net, ifindex);
-       if (dev == NULL) {
-               err = -ENODEV;
-@@ -196,7 +197,7 @@
-       write_unlock_bh(&ipv6_sk_ac_lock);
--      dev = dev_get_by_index(pac->acl_ifindex);
-+      dev = dev_get_by_index(&init_net, pac->acl_ifindex);
-       if (dev) {
-               ipv6_dev_ac_dec(dev, &pac->acl_addr);
-               dev_put(dev);
-@@ -224,7 +225,7 @@
-               if (pac->acl_ifindex != prev_index) {
-                       if (dev)
-                               dev_put(dev);
--                      dev = dev_get_by_index(pac->acl_ifindex);
-+                      dev = dev_get_by_index(&init_net, pac->acl_ifindex);
-                       prev_index = pac->acl_ifindex;
-               }
-               if (dev)
-@@ -429,7 +430,7 @@
-       if (dev)
-               return ipv6_chk_acast_dev(dev, addr);
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev)
-+      for_each_netdev(&init_net, dev)
-               if (ipv6_chk_acast_dev(dev, addr)) {
-                       found = 1;
-                       break;
-@@ -453,7 +454,7 @@
-       struct ac6_iter_state *state = ac6_seq_private(seq);
-       state->idev = NULL;
--      for_each_netdev(state->dev) {
-+      for_each_netdev(&init_net, state->dev) {
-               struct inet6_dev *idev;
-               idev = in6_dev_get(state->dev);
-               if (!idev)
-@@ -579,7 +580,7 @@
- int __init ac6_proc_init(void)
- {
--      if (!proc_net_fops_create("anycast6", S_IRUGO, &ac6_seq_fops))
-+      if (!proc_net_fops_create(&init_net, "anycast6", S_IRUGO, &ac6_seq_fops))
-               return -ENOMEM;
-       return 0;
-@@ -587,7 +588,7 @@
- void ac6_proc_exit(void)
- {
--      proc_net_remove("anycast6");
-+      proc_net_remove(&init_net, "anycast6");
- }
- #endif
-diff -Nurb linux-2.6.22-570/net/ipv6/datagram.c linux-2.6.22-590/net/ipv6/datagram.c
---- linux-2.6.22-570/net/ipv6/datagram.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/datagram.c       2008-01-02 13:56:38.000000000 -0500
-@@ -60,6 +60,7 @@
-               return -EAFNOSUPPORT;
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       if (np->sndflow) {
-               fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
-               if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
-@@ -544,7 +545,7 @@
-                               if (!src_info->ipi6_ifindex)
-                                       return -EINVAL;
-                               else {
--                                      dev = dev_get_by_index(src_info->ipi6_ifindex);
-+                                      dev = dev_get_by_index(&init_net, src_info->ipi6_ifindex);
-                                       if (!dev)
-                                               return -ENODEV;
-                               }
-@@ -658,7 +659,7 @@
-                       switch (rthdr->type) {
-                       case IPV6_SRCRT_TYPE_0:
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-                       case IPV6_SRCRT_TYPE_2:
- #endif
-                               break;
-diff -Nurb linux-2.6.22-570/net/ipv6/esp6.c linux-2.6.22-590/net/ipv6/esp6.c
---- linux-2.6.22-570/net/ipv6/esp6.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/esp6.c   2008-01-02 13:56:38.000000000 -0500
-@@ -421,3 +421,4 @@
- module_exit(esp6_fini);
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP);
-diff -Nurb linux-2.6.22-570/net/ipv6/exthdrs.c linux-2.6.22-590/net/ipv6/exthdrs.c
---- linux-2.6.22-570/net/ipv6/exthdrs.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/exthdrs.c        2008-01-02 13:56:38.000000000 -0500
-@@ -42,7 +42,7 @@
- #include <net/ndisc.h>
- #include <net/ip6_route.h>
- #include <net/addrconf.h>
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- #include <net/xfrm.h>
- #endif
-@@ -90,6 +90,7 @@
-  bad:
-       return -1;
- }
-+EXPORT_SYMBOL_GPL(ipv6_find_tlv);
- /*
-  *    Parsing tlv encoded headers.
-@@ -196,7 +197,7 @@
-   Destination options header.
-  *****************************/
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
- {
-       struct sk_buff *skb = *skbp;
-@@ -270,7 +271,7 @@
- #endif
- static struct tlvtype_proc tlvprocdestopt_lst[] = {
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-       {
-               .type   = IPV6_TLV_HAO,
-               .func   = ipv6_dest_hao,
-@@ -283,7 +284,7 @@
- {
-       struct sk_buff *skb = *skbp;
-       struct inet6_skb_parm *opt = IP6CB(skb);
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-       __u16 dstbuf;
- #endif
-       struct dst_entry *dst;
-@@ -298,7 +299,7 @@
-       }
-       opt->lastopt = opt->dst1 = skb_network_header_len(skb);
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-       dstbuf = opt->dst1;
- #endif
-@@ -308,7 +309,7 @@
-               skb = *skbp;
-               skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
-               opt = IP6CB(skb);
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-               opt->nhoff = dstbuf;
- #else
-               opt->nhoff = opt->dst1;
-@@ -427,7 +428,7 @@
- looped_back:
-       if (hdr->segments_left == 0) {
-               switch (hdr->type) {
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-               case IPV6_SRCRT_TYPE_2:
-                       /* Silently discard type 2 header unless it was
-                        * processed by own
-@@ -463,7 +464,7 @@
-                       return -1;
-               }
-               break;
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-       case IPV6_SRCRT_TYPE_2:
-               /* Silently discard invalid RTH type 2 */
-               if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
-@@ -520,7 +521,7 @@
-       addr += i - 1;
-       switch (hdr->type) {
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-       case IPV6_SRCRT_TYPE_2:
-               if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
-                                    (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
-diff -Nurb linux-2.6.22-570/net/ipv6/fib6_rules.c linux-2.6.22-590/net/ipv6/fib6_rules.c
---- linux-2.6.22-570/net/ipv6/fib6_rules.c     2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/fib6_rules.c     2008-01-02 13:56:38.000000000 -0500
-@@ -244,7 +244,7 @@
-       return -ENOBUFS;
- }
--static u32 fib6_rule_default_pref(void)
-+static u32 fib6_rule_default_pref(struct fib_rules_ops *ops)
- {
-       return 0x3FFF;
- }
-@@ -277,10 +277,10 @@
-       list_add_tail(&local_rule.common.list, &fib6_rules);
-       list_add_tail(&main_rule.common.list, &fib6_rules);
--      fib_rules_register(&fib6_rules_ops);
-+      fib_rules_register(&init_net, &fib6_rules_ops);
- }
- void fib6_rules_cleanup(void)
- {
--      fib_rules_unregister(&fib6_rules_ops);
-+      fib_rules_unregister(&init_net, &fib6_rules_ops);
- }
-diff -Nurb linux-2.6.22-570/net/ipv6/icmp.c linux-2.6.22-590/net/ipv6/icmp.c
---- linux-2.6.22-570/net/ipv6/icmp.c   2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/icmp.c   2008-01-02 13:56:38.000000000 -0500
-@@ -272,7 +272,7 @@
-       return 0;
- }
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- static void mip6_addr_swap(struct sk_buff *skb)
- {
-       struct ipv6hdr *iph = ipv6_hdr(skb);
-@@ -377,6 +377,7 @@
-       mip6_addr_swap(skb);
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       fl.proto = IPPROTO_ICMPV6;
-       ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
-       if (saddr)
-@@ -495,6 +496,7 @@
-       tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY;
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       fl.proto = IPPROTO_ICMPV6;
-       ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
-       if (saddr)
-diff -Nurb linux-2.6.22-570/net/ipv6/inet6_connection_sock.c linux-2.6.22-590/net/ipv6/inet6_connection_sock.c
---- linux-2.6.22-570/net/ipv6/inet6_connection_sock.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/inet6_connection_sock.c  2008-01-02 13:56:38.000000000 -0500
-@@ -149,6 +149,7 @@
-       struct in6_addr *final_p = NULL, final;
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       fl.proto = sk->sk_protocol;
-       ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
-       ipv6_addr_copy(&fl.fl6_src, &np->saddr);
-diff -Nurb linux-2.6.22-570/net/ipv6/inet6_hashtables.c linux-2.6.22-590/net/ipv6/inet6_hashtables.c
---- linux-2.6.22-570/net/ipv6/inet6_hashtables.c       2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/inet6_hashtables.c       2008-01-02 13:56:38.000000000 -0500
-@@ -61,7 +61,7 @@
-                                          const __be16 sport,
-                                          const struct in6_addr *daddr,
-                                          const u16 hnum,
--                                         const int dif)
-+                                         const int dif, struct net *net)
- {
-       struct sock *sk;
-       const struct hlist_node *node;
-@@ -105,7 +105,7 @@
- struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
-                                  const struct in6_addr *daddr,
--                                 const unsigned short hnum, const int dif)
-+                                 const unsigned short hnum, const int dif, struct net *net)
- {
-       struct sock *sk;
-       const struct hlist_node *node;
-@@ -113,7 +113,7 @@
-       int score, hiscore = 0;
-       read_lock(&hashinfo->lhash_lock);
--      sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) {
-+      sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(net, hnum)]) {
-               if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) {
-                       const struct ipv6_pinfo *np = inet6_sk(sk);
-@@ -152,12 +152,12 @@
- struct sock *inet6_lookup(struct inet_hashinfo *hashinfo,
-                         const struct in6_addr *saddr, const __be16 sport,
-                         const struct in6_addr *daddr, const __be16 dport,
--                        const int dif)
-+                        const int dif, struct net *net)
- {
-       struct sock *sk;
-       local_bh_disable();
--      sk = __inet6_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif);
-+      sk = __inet6_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif, net);
-       local_bh_enable();
-       return sk;
-@@ -251,6 +251,7 @@
- int inet6_hash_connect(struct inet_timewait_death_row *death_row,
-                      struct sock *sk)
- {
-+      struct net *net = sk->sk_net;
-       struct inet_hashinfo *hinfo = death_row->hashinfo;
-       const unsigned short snum = inet_sk(sk)->num;
-       struct inet_bind_hashbucket *head;
-@@ -258,8 +259,8 @@
-       int ret;
-       if (snum == 0) {
--              const int low = sysctl_local_port_range[0];
--              const int high = sysctl_local_port_range[1];
-+              const int low = sk->sk_net->sysctl_local_port_range[0];
-+              const int high = sk->sk_net->sysctl_local_port_range[1];
-               const int range = high - low;
-               int i, port;
-               static u32 hint;
-@@ -270,7 +271,7 @@
-               local_bh_disable();
-               for (i = 1; i <= range; i++) {
-                       port = low + (i + offset) % range;
--                      head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)];
-+                      head = &hinfo->bhash[inet_bhashfn(net, port, hinfo->bhash_size)];
-                       spin_lock(&head->lock);
-                       /* Does not bother with rcv_saddr checks,
-@@ -278,7 +279,7 @@
-                        * unique enough.
-                        */
-                       inet_bind_bucket_for_each(tb, node, &head->chain) {
--                              if (tb->port == port) {
-+                              if ((tb->port == port) && (tb->net == net)) {
-                                       BUG_TRAP(!hlist_empty(&tb->owners));
-                                       if (tb->fastreuse >= 0)
-                                               goto next_port;
-@@ -291,7 +292,7 @@
-                       }
-                       tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
--                                                   head, port);
-+                                                   head, net, port);
-                       if (!tb) {
-                               spin_unlock(&head->lock);
-                               break;
-@@ -326,7 +327,7 @@
-               goto out;
-       }
--      head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)];
-+      head = &hinfo->bhash[inet_bhashfn(net, snum, hinfo->bhash_size)];
-       tb   = inet_csk(sk)->icsk_bind_hash;
-       spin_lock_bh(&head->lock);
-diff -Nurb linux-2.6.22-570/net/ipv6/ip6_fib.c linux-2.6.22-590/net/ipv6/ip6_fib.c
---- linux-2.6.22-570/net/ipv6/ip6_fib.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/ip6_fib.c        2008-01-02 13:56:38.000000000 -0500
-@@ -361,6 +361,7 @@
- static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
- {
-+      struct net *net = skb->sk->sk_net;
-       unsigned int h, s_h;
-       unsigned int e = 0, s_e;
-       struct rt6_rtnl_dump_arg arg;
-@@ -369,6 +370,9 @@
-       struct hlist_node *node;
-       int res = 0;
-+      if (net != &init_net)
++                      if (create && in6_dev->cnf.use_tempaddr > 0) {
++                              /*
++                               * When a new public address is created as described in [ADDRCONF],
++                               * also create a new temporary address.
++                               */
++                              read_unlock_bh(&in6_dev->lock);
++                              ipv6_create_tempaddr(ifp, NULL);
++                      } else {
++                              read_unlock_bh(&in6_dev->lock);
++                      }
++#endif
++                      in6_ifa_put(ifp);
++                      addrconf_verify(0);
++              }
++      }
++      inet6_prefix_notify(RTM_NEWPREFIX, in6_dev, pinfo);
++      in6_dev_put(in6_dev);
++}
++
++/*
++ *    Set destination address.
++ *    Special case for SIT interfaces where we create a new "virtual"
++ *    device.
++ */
++int addrconf_set_dstaddr(void __user *arg)
++{
++      struct in6_ifreq ireq;
++      struct net_device *dev;
++      int err = -EINVAL;
++
++      rtnl_lock();
++
++      err = -EFAULT;
++      if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
++              goto err_exit;
++
++      dev = __dev_get_by_index(ireq.ifr6_ifindex);
++
++      err = -ENODEV;
++      if (dev == NULL)
++              goto err_exit;
++
++#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
++      if (dev->type == ARPHRD_SIT) {
++              struct ifreq ifr;
++              mm_segment_t    oldfs;
++              struct ip_tunnel_parm p;
++
++              err = -EADDRNOTAVAIL;
++              if (!(ipv6_addr_type(&ireq.ifr6_addr) & IPV6_ADDR_COMPATv4))
++                      goto err_exit;
++
++              memset(&p, 0, sizeof(p));
++              p.iph.daddr = ireq.ifr6_addr.s6_addr32[3];
++              p.iph.saddr = 0;
++              p.iph.version = 4;
++              p.iph.ihl = 5;
++              p.iph.protocol = IPPROTO_IPV6;
++              p.iph.ttl = 64;
++              ifr.ifr_ifru.ifru_data = (void __user *)&p;
++
++              oldfs = get_fs(); set_fs(KERNEL_DS);
++              err = dev->do_ioctl(dev, &ifr, SIOCADDTUNNEL);
++              set_fs(oldfs);
++
++              if (err == 0) {
++                      err = -ENOBUFS;
++                      if ((dev = __dev_get_by_name(p.name)) == NULL)
++                              goto err_exit;
++                      err = dev_open(dev);
++              }
++      }
++#endif
++
++err_exit:
++      rtnl_unlock();
++      return err;
++}
++
++/*
++ *    Manual configuration of address on an interface
++ */
++static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
++                        __u8 ifa_flags, __u32 prefered_lft, __u32 valid_lft)
++{
++      struct inet6_ifaddr *ifp;
++      struct inet6_dev *idev;
++      struct net_device *dev;
++      int scope;
++      u32 flags = RTF_EXPIRES;
++
++      ASSERT_RTNL();
++
++      /* check the lifetime */
++      if (!valid_lft || prefered_lft > valid_lft)
++              return -EINVAL;
++
++      if ((dev = __dev_get_by_index(ifindex)) == NULL)
++              return -ENODEV;
++
++      if ((idev = addrconf_add_dev(dev)) == NULL)
++              return -ENOBUFS;
++
++      scope = ipv6_addr_scope(pfx);
++
++      if (valid_lft == INFINITY_LIFE_TIME) {
++              ifa_flags |= IFA_F_PERMANENT;
++              flags = 0;
++      } else if (valid_lft >= 0x7FFFFFFF/HZ)
++              valid_lft = 0x7FFFFFFF/HZ;
++
++      if (prefered_lft == 0)
++              ifa_flags |= IFA_F_DEPRECATED;
++      else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
++               (prefered_lft != INFINITY_LIFE_TIME))
++              prefered_lft = 0x7FFFFFFF/HZ;
++
++      ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags);
++
++      if (!IS_ERR(ifp)) {
++              spin_lock_bh(&ifp->lock);
++              ifp->valid_lft = valid_lft;
++              ifp->prefered_lft = prefered_lft;
++              ifp->tstamp = jiffies;
++              spin_unlock_bh(&ifp->lock);
++
++              addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
++                                    jiffies_to_clock_t(valid_lft * HZ), flags);
++              /*
++               * Note that section 3.1 of RFC 4429 indicates
++               * that the Optimistic flag should not be set for
++               * manually configured addresses
++               */
++              addrconf_dad_start(ifp, 0);
++              in6_ifa_put(ifp);
++              addrconf_verify(0);
 +              return 0;
++      }
++
++      return PTR_ERR(ifp);
++}
++
++static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen)
++{
++      struct inet6_ifaddr *ifp;
++      struct inet6_dev *idev;
++      struct net_device *dev;
++
++      if ((dev = __dev_get_by_index(ifindex)) == NULL)
++              return -ENODEV;
++
++      if ((idev = __in6_dev_get(dev)) == NULL)
++              return -ENXIO;
++
++      read_lock_bh(&idev->lock);
++      for (ifp = idev->addr_list; ifp; ifp=ifp->if_next) {
++              if (ifp->prefix_len == plen &&
++                  ipv6_addr_equal(pfx, &ifp->addr)) {
++                      in6_ifa_hold(ifp);
++                      read_unlock_bh(&idev->lock);
++
++                      ipv6_del_addr(ifp);
++
++                      /* If the last address is deleted administratively,
++                         disable IPv6 on this interface.
++                       */
++                      if (idev->addr_list == NULL)
++                              addrconf_ifdown(idev->dev, 1);
++                      return 0;
++              }
++      }
++      read_unlock_bh(&idev->lock);
++      return -EADDRNOTAVAIL;
++}
++
++
++int addrconf_add_ifaddr(void __user *arg)
++{
++      struct in6_ifreq ireq;
++      int err;
++
++      if (!capable(CAP_NET_ADMIN))
++              return -EPERM;
++
++      if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
++              return -EFAULT;
++
++      rtnl_lock();
++      err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen,
++                           IFA_F_PERMANENT, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
++      rtnl_unlock();
++      return err;
++}
++
++int addrconf_del_ifaddr(void __user *arg)
++{
++      struct in6_ifreq ireq;
++      int err;
++
++      if (!capable(CAP_NET_ADMIN))
++              return -EPERM;
++
++      if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
++              return -EFAULT;
++
++      rtnl_lock();
++      err = inet6_addr_del(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen);
++      rtnl_unlock();
++      return err;
++}
++
++#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
++static void sit_add_v4_addrs(struct inet6_dev *idev)
++{
++      struct inet6_ifaddr * ifp;
++      struct in6_addr addr;
++      struct net_device *dev;
++      int scope;
++
++      ASSERT_RTNL();
++
++      memset(&addr, 0, sizeof(struct in6_addr));
++      memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4);
++
++      if (idev->dev->flags&IFF_POINTOPOINT) {
++              addr.s6_addr32[0] = htonl(0xfe800000);
++              scope = IFA_LINK;
++      } else {
++              scope = IPV6_ADDR_COMPATv4;
++      }
++
++      if (addr.s6_addr32[3]) {
++              ifp = ipv6_add_addr(idev, &addr, 128, scope, IFA_F_PERMANENT);
++              if (!IS_ERR(ifp)) {
++                      spin_lock_bh(&ifp->lock);
++                      ifp->flags &= ~IFA_F_TENTATIVE;
++                      spin_unlock_bh(&ifp->lock);
++                      ipv6_ifa_notify(RTM_NEWADDR, ifp);
++                      in6_ifa_put(ifp);
++              }
++              return;
++      }
++
++      for_each_netdev(dev) {
++              struct in_device * in_dev = __in_dev_get_rtnl(dev);
++              if (in_dev && (dev->flags & IFF_UP)) {
++                      struct in_ifaddr * ifa;
++
++                      int flag = scope;
++
++                      for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
++                              int plen;
++
++                              addr.s6_addr32[3] = ifa->ifa_local;
++
++                              if (ifa->ifa_scope == RT_SCOPE_LINK)
++                                      continue;
++                              if (ifa->ifa_scope >= RT_SCOPE_HOST) {
++                                      if (idev->dev->flags&IFF_POINTOPOINT)
++                                              continue;
++                                      flag |= IFA_HOST;
++                              }
++                              if (idev->dev->flags&IFF_POINTOPOINT)
++                                      plen = 64;
++                              else
++                                      plen = 96;
++
++                              ifp = ipv6_add_addr(idev, &addr, plen, flag,
++                                                  IFA_F_PERMANENT);
++                              if (!IS_ERR(ifp)) {
++                                      spin_lock_bh(&ifp->lock);
++                                      ifp->flags &= ~IFA_F_TENTATIVE;
++                                      spin_unlock_bh(&ifp->lock);
++                                      ipv6_ifa_notify(RTM_NEWADDR, ifp);
++                                      in6_ifa_put(ifp);
++                              }
++                      }
++              }
++      }
++}
++#endif
++
++static void init_loopback(struct net_device *dev)
++{
++      struct inet6_dev  *idev;
++      struct inet6_ifaddr * ifp;
++
++      /* ::1 */
++
++      ASSERT_RTNL();
++
++      if ((idev = ipv6_find_idev(dev)) == NULL) {
++              printk(KERN_DEBUG "init loopback: add_dev failed\n");
++              return;
++      }
++
++      ifp = ipv6_add_addr(idev, &in6addr_loopback, 128, IFA_HOST, IFA_F_PERMANENT);
++      if (!IS_ERR(ifp)) {
++              spin_lock_bh(&ifp->lock);
++              ifp->flags &= ~IFA_F_TENTATIVE;
++              spin_unlock_bh(&ifp->lock);
++              ipv6_ifa_notify(RTM_NEWADDR, ifp);
++              in6_ifa_put(ifp);
++      }
++}
++
++static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr)
++{
++      struct inet6_ifaddr * ifp;
++      u32 addr_flags = IFA_F_PERMANENT;
++
++#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
++      if (idev->cnf.optimistic_dad &&
++          !ipv6_devconf.forwarding)
++              addr_flags |= IFA_F_OPTIMISTIC;
++#endif
++
++
++      ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, addr_flags);
++      if (!IS_ERR(ifp)) {
++              addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
++              addrconf_dad_start(ifp, 0);
++              in6_ifa_put(ifp);
++      }
++}
++
++static void addrconf_dev_config(struct net_device *dev)
++{
++      struct in6_addr addr;
++      struct inet6_dev    * idev;
++
++      ASSERT_RTNL();
++
++      if ((dev->type != ARPHRD_ETHER) &&
++          (dev->type != ARPHRD_FDDI) &&
++          (dev->type != ARPHRD_IEEE802_TR) &&
++          (dev->type != ARPHRD_ARCNET) &&
++          (dev->type != ARPHRD_INFINIBAND)) {
++              /* Alas, we support only Ethernet autoconfiguration. */
++              return;
++      }
++
++      idev = addrconf_add_dev(dev);
++      if (idev == NULL)
++              return;
++
++      memset(&addr, 0, sizeof(struct in6_addr));
++      addr.s6_addr32[0] = htonl(0xFE800000);
++
++      if (ipv6_generate_eui64(addr.s6_addr + 8, dev) == 0)
++              addrconf_add_linklocal(idev, &addr);
++}
++
++#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
++static void addrconf_sit_config(struct net_device *dev)
++{
++      struct inet6_dev *idev;
++
++      ASSERT_RTNL();
++
++      /*
++       * Configure the tunnel with one of our IPv4
++       * addresses... we should configure all of
++       * our v4 addrs in the tunnel
++       */
 +
-       s_h = cb->args[0];
-       s_e = cb->args[1];
-@@ -1311,6 +1315,11 @@
- static int fib6_clean_node(struct fib6_walker_t *w)
- {
-+      struct nl_info info = {
-+              .nlh = NULL,
-+              .pid = 0,
-+              .net = &init_net,
-+      };
-       int res;
-       struct rt6_info *rt;
-       struct fib6_cleaner_t *c = (struct fib6_cleaner_t*)w;
-@@ -1319,7 +1328,7 @@
-               res = c->func(rt, c->arg);
-               if (res < 0) {
-                       w->leaf = rt;
--                      res = fib6_del(rt, NULL);
-+                      res = fib6_del(rt, &info);
-                       if (res) {
- #if RT6_DEBUG >= 2
-                               printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res);
-diff -Nurb linux-2.6.22-570/net/ipv6/ip6_flowlabel.c linux-2.6.22-590/net/ipv6/ip6_flowlabel.c
---- linux-2.6.22-570/net/ipv6/ip6_flowlabel.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/ip6_flowlabel.c  2008-01-02 13:56:38.000000000 -0500
-@@ -22,6 +22,7 @@
- #include <linux/seq_file.h>
- #include <net/sock.h>
-+#include <net/net_namespace.h>
- #include <net/ipv6.h>
- #include <net/ndisc.h>
-@@ -309,6 +310,7 @@
-               msg.msg_controllen = olen;
-               msg.msg_control = (void*)(fl->opt+1);
-+              flowi.fl_net = &init_net;
-               flowi.oif = 0;
-               err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk, &junk);
-@@ -690,7 +692,7 @@
- void ip6_flowlabel_init(void)
- {
- #ifdef CONFIG_PROC_FS
--      proc_net_fops_create("ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops);
-+      proc_net_fops_create(&init_net, "ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops);
- #endif
- }
-@@ -698,6 +700,6 @@
- {
-       del_timer(&ip6_fl_gc_timer);
- #ifdef CONFIG_PROC_FS
--      proc_net_remove("ip6_flowlabel");
-+      proc_net_remove(&init_net, "ip6_flowlabel");
- #endif
- }
-diff -Nurb linux-2.6.22-570/net/ipv6/ip6_input.c linux-2.6.22-590/net/ipv6/ip6_input.c
---- linux-2.6.22-570/net/ipv6/ip6_input.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/ip6_input.c      2008-01-02 13:56:38.000000000 -0500
-@@ -61,6 +61,11 @@
-       u32             pkt_len;
-       struct inet6_dev *idev;
-+      if (dev->nd_net != &init_net) {
-+              kfree_skb(skb);
++      if ((idev = ipv6_find_idev(dev)) == NULL) {
++              printk(KERN_DEBUG "init sit: add_dev failed\n");
++              return;
++      }
++
++      sit_add_v4_addrs(idev);
++
++      if (dev->flags&IFF_POINTOPOINT) {
++              addrconf_add_mroute(dev);
++              addrconf_add_lroute(dev);
++      } else
++              sit_route_add(dev);
++}
++#endif
++
++static inline int
++ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev)
++{
++      struct in6_addr lladdr;
++
++      if (!ipv6_get_lladdr(link_dev, &lladdr, IFA_F_TENTATIVE)) {
++              addrconf_add_linklocal(idev, &lladdr);
 +              return 0;
 +      }
++      return -1;
++}
 +
-       if (skb->pkt_type == PACKET_OTHERHOST) {
-               kfree_skb(skb);
-               return 0;
-diff -Nurb linux-2.6.22-570/net/ipv6/ip6_output.c linux-2.6.22-590/net/ipv6/ip6_output.c
---- linux-2.6.22-570/net/ipv6/ip6_output.c     2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/ip6_output.c     2008-01-02 13:56:38.000000000 -0500
-@@ -423,7 +423,7 @@
-       /* XXX: idev->cnf.proxy_ndp? */
-       if (ipv6_devconf.proxy_ndp &&
--          pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) {
-+          pneigh_lookup(&nd_tbl, &init_net, &hdr->daddr, skb->dev, 0)) {
-               int proxied = ip6_forward_proxy_check(skb);
-               if (proxied > 0)
-                       return ip6_input(skb);
-@@ -543,7 +543,7 @@
-                       found_rhdr = 1;
-                       break;
-               case NEXTHDR_DEST:
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-                       if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
-                               break;
- #endif
-diff -Nurb linux-2.6.22-570/net/ipv6/ip6_tunnel.c linux-2.6.22-590/net/ipv6/ip6_tunnel.c
---- linux-2.6.22-570/net/ipv6/ip6_tunnel.c     2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/ip6_tunnel.c     2008-01-02 13:56:38.000000000 -0500
-@@ -235,7 +235,7 @@
-               int i;
-               for (i = 1; i < IP6_TNL_MAX; i++) {
-                       sprintf(name, "ip6tnl%d", i);
--                      if (__dev_get_by_name(name) == NULL)
-+                      if (__dev_get_by_name(&init_net, name) == NULL)
-                               break;
-               }
-               if (i == IP6_TNL_MAX)
-@@ -651,7 +651,7 @@
-               struct net_device *ldev = NULL;
-               if (p->link)
--                      ldev = dev_get_by_index(p->link);
-+                      ldev = dev_get_by_index(&init_net, p->link);
-               if ((ipv6_addr_is_multicast(&p->laddr) ||
-                    likely(ipv6_chk_addr(&p->laddr, ldev, 0))) &&
-@@ -787,7 +787,7 @@
-               struct net_device *ldev = NULL;
-               if (p->link)
--                      ldev = dev_get_by_index(p->link);
-+                      ldev = dev_get_by_index(&init_net, p->link);
-               if (unlikely(!ipv6_chk_addr(&p->laddr, ldev, 0)))
-                       printk(KERN_WARNING
-diff -Nurb linux-2.6.22-570/net/ipv6/ipcomp6.c linux-2.6.22-590/net/ipv6/ipcomp6.c
---- linux-2.6.22-570/net/ipv6/ipcomp6.c        2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/ipcomp6.c        2008-01-02 13:56:38.000000000 -0500
-@@ -501,4 +501,4 @@
- MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) for IPv6 - RFC3173");
- MODULE_AUTHOR("Mitsuru KANDA <mk@linux-ipv6.org>");
--
-+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_COMP);
-diff -Nurb linux-2.6.22-570/net/ipv6/ipv6_sockglue.c linux-2.6.22-590/net/ipv6/ipv6_sockglue.c
---- linux-2.6.22-570/net/ipv6/ipv6_sockglue.c  2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/ipv6_sockglue.c  2008-01-02 13:56:38.000000000 -0500
-@@ -123,7 +123,7 @@
-       struct ipv6hdr *ipv6h;
-       struct inet6_protocol *ops;
--      if (!(features & NETIF_F_HW_CSUM))
-+      if (!(features & NETIF_F_V6_CSUM))
-               features &= ~NETIF_F_SG;
-       if (unlikely(skb_shinfo(skb)->gso_type &
-@@ -417,7 +417,7 @@
-                       struct ipv6_rt_hdr *rthdr = opt->srcrt;
-                       switch (rthdr->type) {
-                       case IPV6_SRCRT_TYPE_0:
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-                       case IPV6_SRCRT_TYPE_2:
- #endif
-                               break;
-@@ -463,6 +463,7 @@
-               struct flowi fl;
-               int junk;
-+              fl.fl_net = &init_net;
-               fl.fl6_flowlabel = 0;
-               fl.oif = sk->sk_bound_dev_if;
-@@ -547,7 +548,7 @@
-               if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val)
-                       goto e_inval;
--              if (__dev_get_by_index(val) == NULL) {
-+              if (__dev_get_by_index(&init_net, val) == NULL) {
-                       retv = -ENODEV;
-                       break;
-               }
-diff -Nurb linux-2.6.22-570/net/ipv6/mcast.c linux-2.6.22-590/net/ipv6/mcast.c
---- linux-2.6.22-570/net/ipv6/mcast.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/mcast.c  2008-01-02 13:56:38.000000000 -0500
-@@ -51,6 +51,7 @@
- #include <net/sock.h>
- #include <net/snmp.h>
-+#include <net/net_namespace.h>
- #include <net/ipv6.h>
- #include <net/protocol.h>
-@@ -214,7 +215,7 @@
-                       dst_release(&rt->u.dst);
-               }
-       } else
--              dev = dev_get_by_index(ifindex);
-+              dev = dev_get_by_index(&init_net, ifindex);
-       if (dev == NULL) {
-               sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
-@@ -265,7 +266,7 @@
-                       *lnk = mc_lst->next;
-                       write_unlock_bh(&ipv6_sk_mc_lock);
--                      if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) {
-+                      if ((dev = dev_get_by_index(&init_net, mc_lst->ifindex)) != NULL) {
-                               struct inet6_dev *idev = in6_dev_get(dev);
-                               (void) ip6_mc_leave_src(sk, mc_lst, idev);
-@@ -300,7 +301,7 @@
-                       dst_release(&rt->u.dst);
-               }
-       } else
--              dev = dev_get_by_index(ifindex);
-+              dev = dev_get_by_index(&init_net, ifindex);
-       if (!dev)
-               return NULL;
-@@ -331,7 +332,7 @@
-               np->ipv6_mc_list = mc_lst->next;
-               write_unlock_bh(&ipv6_sk_mc_lock);
--              dev = dev_get_by_index(mc_lst->ifindex);
-+              dev = dev_get_by_index(&init_net, mc_lst->ifindex);
-               if (dev) {
-                       struct inet6_dev *idev = in6_dev_get(dev);
-@@ -2332,7 +2333,7 @@
-       struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
-       state->idev = NULL;
--      for_each_netdev(state->dev) {
-+      for_each_netdev(&init_net, state->dev) {
-               struct inet6_dev *idev;
-               idev = in6_dev_get(state->dev);
-               if (!idev)
-@@ -2476,7 +2477,7 @@
-       state->idev = NULL;
-       state->im = NULL;
--      for_each_netdev(state->dev) {
-+      for_each_netdev(&init_net, state->dev) {
-               struct inet6_dev *idev;
-               idev = in6_dev_get(state->dev);
-               if (unlikely(idev == NULL))
-@@ -2658,8 +2659,8 @@
-       np->hop_limit = 1;
- #ifdef CONFIG_PROC_FS
--      proc_net_fops_create("igmp6", S_IRUGO, &igmp6_mc_seq_fops);
--      proc_net_fops_create("mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops);
-+      proc_net_fops_create(&init_net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops);
-+      proc_net_fops_create(&init_net, "mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops);
- #endif
-       return 0;
-@@ -2671,7 +2672,7 @@
-       igmp6_socket = NULL; /* for safety */
- #ifdef CONFIG_PROC_FS
--      proc_net_remove("mcfilter6");
--      proc_net_remove("igmp6");
-+      proc_net_remove(&init_net, "mcfilter6");
-+      proc_net_remove(&init_net, "igmp6");
- #endif
- }
-diff -Nurb linux-2.6.22-570/net/ipv6/mip6.c linux-2.6.22-590/net/ipv6/mip6.c
---- linux-2.6.22-570/net/ipv6/mip6.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/mip6.c   2008-01-02 13:56:38.000000000 -0500
-@@ -30,6 +30,7 @@
- #include <net/sock.h>
- #include <net/ipv6.h>
- #include <net/ip6_checksum.h>
-+#include <net/rawv6.h>
- #include <net/xfrm.h>
- #include <net/mip6.h>
-@@ -86,7 +87,7 @@
-       return len;
- }
--int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
-+static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
- {
-       struct ip6_mh *mh;
-@@ -471,7 +472,7 @@
-       .remote_addr    = mip6_xfrm_addr,
- };
--int __init mip6_init(void)
-+static int __init mip6_init(void)
- {
-       printk(KERN_INFO "Mobile IPv6\n");
-@@ -483,18 +484,35 @@
-               printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__);
-               goto mip6_rthdr_xfrm_fail;
-       }
-+      if (rawv6_mh_filter_register(mip6_mh_filter) < 0) {
-+              printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__);
-+              goto mip6_rawv6_mh_fail;
++static void ip6_tnl_add_linklocal(struct inet6_dev *idev)
++{
++      struct net_device *link_dev;
++
++      /* first try to inherit the link-local address from the link device */
++      if (idev->dev->iflink &&
++          (link_dev = __dev_get_by_index(idev->dev->iflink))) {
++              if (!ipv6_inherit_linklocal(idev, link_dev))
++                      return;
++      }
++      /* then try to inherit it from any device */
++      for_each_netdev(link_dev) {
++              if (!ipv6_inherit_linklocal(idev, link_dev))
++                      return;
++      }
++      printk(KERN_DEBUG "init ip6-ip6: add_linklocal failed\n");
++}
++
++/*
++ * Autoconfigure tunnel with a link-local address so routing protocols,
++ * DHCPv6, MLD etc. can be run over the virtual link
++ */
++
++static void addrconf_ip6_tnl_config(struct net_device *dev)
++{
++      struct inet6_dev *idev;
++
++      ASSERT_RTNL();
++
++      if ((idev = addrconf_add_dev(dev)) == NULL) {
++              printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n");
++              return;
++      }
++      ip6_tnl_add_linklocal(idev);
++}
++
++static int addrconf_notify(struct notifier_block *this, unsigned long event,
++                         void * data)
++{
++      struct net_device *dev = (struct net_device *) data;
++      struct inet6_dev *idev = __in6_dev_get(dev);
++      int run_pending = 0;
++
++      switch(event) {
++      case NETDEV_REGISTER:
++              if (!idev && dev->mtu >= IPV6_MIN_MTU) {
++                      idev = ipv6_add_dev(dev);
++                      if (!idev)
++                              printk(KERN_WARNING "IPv6: add_dev failed for %s\n",
++                                      dev->name);
++              }
++              break;
++      case NETDEV_UP:
++      case NETDEV_CHANGE:
++              if (event == NETDEV_UP) {
++                      if (!addrconf_qdisc_ok(dev)) {
++                              /* device is not ready yet. */
++                              printk(KERN_INFO
++                                      "ADDRCONF(NETDEV_UP): %s: "
++                                      "link is not ready\n",
++                                      dev->name);
++                              break;
++                      }
++
++                      if (idev)
++                              idev->if_flags |= IF_READY;
++              } else {
++                      if (!addrconf_qdisc_ok(dev)) {
++                              /* device is still not ready. */
++                              break;
++                      }
++
++                      if (idev) {
++                              if (idev->if_flags & IF_READY) {
++                                      /* device is already configured. */
++                                      break;
++                              }
++                              idev->if_flags |= IF_READY;
++                      }
++
++                      printk(KERN_INFO
++                                      "ADDRCONF(NETDEV_CHANGE): %s: "
++                                      "link becomes ready\n",
++                                      dev->name);
++
++                      run_pending = 1;
++              }
++
++              switch(dev->type) {
++#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
++              case ARPHRD_SIT:
++                      addrconf_sit_config(dev);
++                      break;
++#endif
++              case ARPHRD_TUNNEL6:
++                      addrconf_ip6_tnl_config(dev);
++                      break;
++              case ARPHRD_LOOPBACK:
++                      init_loopback(dev);
++                      break;
++
++              default:
++                      addrconf_dev_config(dev);
++                      break;
++              }
++              if (idev) {
++                      if (run_pending)
++                              addrconf_dad_run(idev);
++
++                      /* If the MTU changed during the interface down, when the
++                         interface up, the changed MTU must be reflected in the
++                         idev as well as routers.
++                       */
++                      if (idev->cnf.mtu6 != dev->mtu && dev->mtu >= IPV6_MIN_MTU) {
++                              rt6_mtu_change(dev, dev->mtu);
++                              idev->cnf.mtu6 = dev->mtu;
++                      }
++                      idev->tstamp = jiffies;
++                      inet6_ifinfo_notify(RTM_NEWLINK, idev);
++                      /* If the changed mtu during down is lower than IPV6_MIN_MTU
++                         stop IPv6 on this interface.
++                       */
++                      if (dev->mtu < IPV6_MIN_MTU)
++                              addrconf_ifdown(dev, event != NETDEV_DOWN);
++              }
++              break;
++
++      case NETDEV_CHANGEMTU:
++              if ( idev && dev->mtu >= IPV6_MIN_MTU) {
++                      rt6_mtu_change(dev, dev->mtu);
++                      idev->cnf.mtu6 = dev->mtu;
++                      break;
++              }
++
++              /* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */
++
++      case NETDEV_DOWN:
++      case NETDEV_UNREGISTER:
++              /*
++               *      Remove all addresses from this interface.
++               */
++              addrconf_ifdown(dev, event != NETDEV_DOWN);
++              break;
++
++      case NETDEV_CHANGENAME:
++              if (idev) {
++                      snmp6_unregister_dev(idev);
++#ifdef CONFIG_SYSCTL
++                      addrconf_sysctl_unregister(&idev->cnf);
++                      neigh_sysctl_unregister(idev->nd_parms);
++                      neigh_sysctl_register(dev, idev->nd_parms,
++                                            NET_IPV6, NET_IPV6_NEIGH, "ipv6",
++                                            &ndisc_ifinfo_sysctl_change,
++                                            NULL);
++                      addrconf_sysctl_register(idev, &idev->cnf);
++#endif
++                      snmp6_register_dev(idev);
++              }
++              break;
++      }
++
++      return NOTIFY_OK;
++}
++
++/*
++ *    addrconf module should be notified of a device going up
++ */
++static struct notifier_block ipv6_dev_notf = {
++      .notifier_call = addrconf_notify,
++      .priority = 0
++};
++
++static int addrconf_ifdown(struct net_device *dev, int how)
++{
++      struct inet6_dev *idev;
++      struct inet6_ifaddr *ifa, **bifa;
++      int i;
++
++      ASSERT_RTNL();
++
++      if (dev == &loopback_dev && how == 1)
++              how = 0;
++
++      rt6_ifdown(dev);
++      neigh_ifdown(&nd_tbl, dev);
++
++      idev = __in6_dev_get(dev);
++      if (idev == NULL)
++              return -ENODEV;
++
++      /* Step 1: remove reference to ipv6 device from parent device.
++                 Do not dev_put!
++       */
++      if (how == 1) {
++              idev->dead = 1;
++
++              /* protected by rtnl_lock */
++              rcu_assign_pointer(dev->ip6_ptr, NULL);
++
++              /* Step 1.5: remove snmp6 entry */
++              snmp6_unregister_dev(idev);
++
++      }
++
++      /* Step 2: clear hash table */
++      for (i=0; i<IN6_ADDR_HSIZE; i++) {
++              bifa = &inet6_addr_lst[i];
++
++              write_lock_bh(&addrconf_hash_lock);
++              while ((ifa = *bifa) != NULL) {
++                      if (ifa->idev == idev) {
++                              *bifa = ifa->lst_next;
++                              ifa->lst_next = NULL;
++                              addrconf_del_timer(ifa);
++                              in6_ifa_put(ifa);
++                              continue;
++                      }
++                      bifa = &ifa->lst_next;
++              }
++              write_unlock_bh(&addrconf_hash_lock);
++      }
++
++      write_lock_bh(&idev->lock);
++
++      /* Step 3: clear flags for stateless addrconf */
++      if (how != 1)
++              idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY);
++
++      /* Step 4: clear address list */
++#ifdef CONFIG_IPV6_PRIVACY
++      if (how == 1 && del_timer(&idev->regen_timer))
++              in6_dev_put(idev);
++
++      /* clear tempaddr list */
++      while ((ifa = idev->tempaddr_list) != NULL) {
++              idev->tempaddr_list = ifa->tmp_next;
++              ifa->tmp_next = NULL;
++              ifa->dead = 1;
++              write_unlock_bh(&idev->lock);
++              spin_lock_bh(&ifa->lock);
++
++              if (ifa->ifpub) {
++                      in6_ifa_put(ifa->ifpub);
++                      ifa->ifpub = NULL;
++              }
++              spin_unlock_bh(&ifa->lock);
++              in6_ifa_put(ifa);
++              write_lock_bh(&idev->lock);
++      }
++#endif
++      while ((ifa = idev->addr_list) != NULL) {
++              idev->addr_list = ifa->if_next;
++              ifa->if_next = NULL;
++              ifa->dead = 1;
++              addrconf_del_timer(ifa);
++              write_unlock_bh(&idev->lock);
++
++              __ipv6_ifa_notify(RTM_DELADDR, ifa);
++              atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa);
++              in6_ifa_put(ifa);
++
++              write_lock_bh(&idev->lock);
++      }
++      write_unlock_bh(&idev->lock);
++
++      /* Step 5: Discard multicast list */
++
++      if (how == 1)
++              ipv6_mc_destroy_dev(idev);
++      else
++              ipv6_mc_down(idev);
++
++      /* Step 5: netlink notification of this interface */
++      idev->tstamp = jiffies;
++      inet6_ifinfo_notify(RTM_DELLINK, idev);
++
++      /* Shot the device (if unregistered) */
++
++      if (how == 1) {
++#ifdef CONFIG_SYSCTL
++              addrconf_sysctl_unregister(&idev->cnf);
++              neigh_sysctl_unregister(idev->nd_parms);
++#endif
++              neigh_parms_release(&nd_tbl, idev->nd_parms);
++              neigh_ifdown(&nd_tbl, dev);
++              in6_dev_put(idev);
++      }
++      return 0;
++}
++
++static void addrconf_rs_timer(unsigned long data)
++{
++      struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data;
++
++      if (ifp->idev->cnf.forwarding)
++              goto out;
++
++      if (ifp->idev->if_flags & IF_RA_RCVD) {
++              /*
++               *      Announcement received after solicitation
++               *      was sent
++               */
++              goto out;
++      }
++
++      spin_lock(&ifp->lock);
++      if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) {
++              struct in6_addr all_routers;
++
++              /* The wait after the last probe can be shorter */
++              addrconf_mod_timer(ifp, AC_RS,
++                                 (ifp->probes == ifp->idev->cnf.rtr_solicits) ?
++                                 ifp->idev->cnf.rtr_solicit_delay :
++                                 ifp->idev->cnf.rtr_solicit_interval);
++              spin_unlock(&ifp->lock);
++
++              ipv6_addr_all_routers(&all_routers);
++
++              ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers);
++      } else {
++              spin_unlock(&ifp->lock);
++              /*
++               * Note: we do not support deprecated "all on-link"
++               * assumption any longer.
++               */
++              printk(KERN_DEBUG "%s: no IPv6 routers present\n",
++                     ifp->idev->dev->name);
++      }
++
++out:
++      in6_ifa_put(ifp);
++}
++
++/*
++ *    Duplicate Address Detection
++ */
++static void addrconf_dad_kick(struct inet6_ifaddr *ifp)
++{
++      unsigned long rand_num;
++      struct inet6_dev *idev = ifp->idev;
++
++      if (ifp->flags & IFA_F_OPTIMISTIC)
++              rand_num = 0;
++      else
++              rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1);
++
++      ifp->probes = idev->cnf.dad_transmits;
++      addrconf_mod_timer(ifp, AC_DAD, rand_num);
++}
++
++static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
++{
++      struct inet6_dev *idev = ifp->idev;
++      struct net_device *dev = idev->dev;
++
++      addrconf_join_solict(dev, &ifp->addr);
++
++      net_srandom(ifp->addr.s6_addr32[3]);
++
++      read_lock_bh(&idev->lock);
++      if (ifp->dead)
++              goto out;
++      spin_lock_bh(&ifp->lock);
++
++      if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
++          !(ifp->flags&IFA_F_TENTATIVE) ||
++          ifp->flags & IFA_F_NODAD) {
++              ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC);
++              spin_unlock_bh(&ifp->lock);
++              read_unlock_bh(&idev->lock);
++
++              addrconf_dad_completed(ifp);
++              return;
++      }
++
++      if (!(idev->if_flags & IF_READY)) {
++              spin_unlock_bh(&ifp->lock);
++              read_unlock_bh(&idev->lock);
++              /*
++               * If the defice is not ready:
++               * - keep it tentative if it is a permanent address.
++               * - otherwise, kill it.
++               */
++              in6_ifa_hold(ifp);
++              addrconf_dad_stop(ifp);
++              return;
++      }
++
++      /*
++       * Optimistic nodes can start receiving
++       * Frames right away
++       */
++      if(ifp->flags & IFA_F_OPTIMISTIC)
++              ip6_ins_rt(ifp->rt);
++
++      addrconf_dad_kick(ifp);
++      spin_unlock_bh(&ifp->lock);
++out:
++      read_unlock_bh(&idev->lock);
++}
++
++static void addrconf_dad_timer(unsigned long data)
++{
++      struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data;
++      struct inet6_dev *idev = ifp->idev;
++      struct in6_addr unspec;
++      struct in6_addr mcaddr;
++
++      read_lock_bh(&idev->lock);
++      if (idev->dead) {
++              read_unlock_bh(&idev->lock);
++              goto out;
++      }
++      spin_lock_bh(&ifp->lock);
++      if (ifp->probes == 0) {
++              /*
++               * DAD was successful
++               */
++
++              ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC);
++              spin_unlock_bh(&ifp->lock);
++              read_unlock_bh(&idev->lock);
++
++              addrconf_dad_completed(ifp);
++
++              goto out;
++      }
++
++      ifp->probes--;
++      addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time);
++      spin_unlock_bh(&ifp->lock);
++      read_unlock_bh(&idev->lock);
++
++      /* send a neighbour solicitation for our addr */
++      memset(&unspec, 0, sizeof(unspec));
++      addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
++      ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec);
++out:
++      in6_ifa_put(ifp);
++}
++
++static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
++{
++      struct net_device *     dev = ifp->idev->dev;
++
++      /*
++       *      Configure the address for reception. Now it is valid.
++       */
++
++      ipv6_ifa_notify(RTM_NEWADDR, ifp);
++
++      /* If added prefix is link local and forwarding is off,
++         start sending router solicitations.
++       */
++
++      if (ifp->idev->cnf.forwarding == 0 &&
++          ifp->idev->cnf.rtr_solicits > 0 &&
++          (dev->flags&IFF_LOOPBACK) == 0 &&
++          (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
++              struct in6_addr all_routers;
++
++              ipv6_addr_all_routers(&all_routers);
++
++              /*
++               *      If a host as already performed a random delay
++               *      [...] as part of DAD [...] there is no need
++               *      to delay again before sending the first RS
++               */
++              ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers);
++
++              spin_lock_bh(&ifp->lock);
++              ifp->probes = 1;
++              ifp->idev->if_flags |= IF_RS_SENT;
++              addrconf_mod_timer(ifp, AC_RS, ifp->idev->cnf.rtr_solicit_interval);
++              spin_unlock_bh(&ifp->lock);
++      }
++}
++
++static void addrconf_dad_run(struct inet6_dev *idev) {
++      struct inet6_ifaddr *ifp;
++
++      read_lock_bh(&idev->lock);
++      for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) {
++              spin_lock_bh(&ifp->lock);
++              if (!(ifp->flags & IFA_F_TENTATIVE)) {
++                      spin_unlock_bh(&ifp->lock);
++                      continue;
++              }
++              spin_unlock_bh(&ifp->lock);
++              addrconf_dad_kick(ifp);
++      }
++      read_unlock_bh(&idev->lock);
++}
++
++#ifdef CONFIG_PROC_FS
++struct if6_iter_state {
++      int bucket;
++};
++
++static struct inet6_ifaddr *if6_get_first(struct seq_file *seq)
++{
++      struct inet6_ifaddr *ifa = NULL;
++      struct if6_iter_state *state = seq->private;
++
++      for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) {
++              ifa = inet6_addr_lst[state->bucket];
++              if (ifa)
++                      break;
++      }
++      return ifa;
++}
++
++static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa)
++{
++      struct if6_iter_state *state = seq->private;
++
++      ifa = ifa->lst_next;
++try_again:
++      if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) {
++              ifa = inet6_addr_lst[state->bucket];
++              goto try_again;
++      }
++      return ifa;
++}
++
++static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos)
++{
++      struct inet6_ifaddr *ifa = if6_get_first(seq);
++
++      if (ifa)
++              while(pos && (ifa = if6_get_next(seq, ifa)) != NULL)
++                      --pos;
++      return pos ? NULL : ifa;
++}
++
++static void *if6_seq_start(struct seq_file *seq, loff_t *pos)
++{
++      read_lock_bh(&addrconf_hash_lock);
++      return if6_get_idx(seq, *pos);
++}
++
++static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      struct inet6_ifaddr *ifa;
++
++      ifa = if6_get_next(seq, v);
++      ++*pos;
++      return ifa;
++}
++
++static void if6_seq_stop(struct seq_file *seq, void *v)
++{
++      read_unlock_bh(&addrconf_hash_lock);
++}
++
++static int if6_seq_show(struct seq_file *seq, void *v)
++{
++      struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v;
++      seq_printf(seq,
++                 NIP6_SEQFMT " %02x %02x %02x %02x %8s\n",
++                 NIP6(ifp->addr),
++                 ifp->idev->dev->ifindex,
++                 ifp->prefix_len,
++                 ifp->scope,
++                 ifp->flags,
++                 ifp->idev->dev->name);
++      return 0;
++}
++
++static struct seq_operations if6_seq_ops = {
++      .start  = if6_seq_start,
++      .next   = if6_seq_next,
++      .show   = if6_seq_show,
++      .stop   = if6_seq_stop,
++};
++
++static int if6_seq_open(struct inode *inode, struct file *file)
++{
++      struct seq_file *seq;
++      int rc = -ENOMEM;
++      struct if6_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
++
++      if (!s)
++              goto out;
++
++      rc = seq_open(file, &if6_seq_ops);
++      if (rc)
++              goto out_kfree;
++
++      seq = file->private_data;
++      seq->private = s;
++out:
++      return rc;
++out_kfree:
++      kfree(s);
++      goto out;
++}
++
++static const struct file_operations if6_fops = {
++      .owner          = THIS_MODULE,
++      .open           = if6_seq_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = seq_release_private,
++};
++
++int __init if6_proc_init(void)
++{
++      if (!proc_net_fops_create("if_inet6", S_IRUGO, &if6_fops))
++              return -ENOMEM;
++      return 0;
++}
++
++void if6_proc_exit(void)
++{
++      proc_net_remove("if_inet6");
++}
++#endif        /* CONFIG_PROC_FS */
++
++#ifdef CONFIG_IPV6_MIP6
++/* Check if address is a home address configured on any interface. */
++int ipv6_chk_home_addr(struct in6_addr *addr)
++{
++      int ret = 0;
++      struct inet6_ifaddr * ifp;
++      u8 hash = ipv6_addr_hash(addr);
++      read_lock_bh(&addrconf_hash_lock);
++      for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) {
++              if (ipv6_addr_cmp(&ifp->addr, addr) == 0 &&
++                  (ifp->flags & IFA_F_HOMEADDRESS)) {
++                      ret = 1;
++                      break;
++              }
++      }
++      read_unlock_bh(&addrconf_hash_lock);
++      return ret;
++}
++#endif
++
++/*
++ *    Periodic address status verification
++ */
++
++static void addrconf_verify(unsigned long foo)
++{
++      struct inet6_ifaddr *ifp;
++      unsigned long now, next;
++      int i;
++
++      spin_lock_bh(&addrconf_verify_lock);
++      now = jiffies;
++      next = now + ADDR_CHECK_FREQUENCY;
++
++      del_timer(&addr_chk_timer);
++
++      for (i=0; i < IN6_ADDR_HSIZE; i++) {
++
++restart:
++              read_lock(&addrconf_hash_lock);
++              for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) {
++                      unsigned long age;
++#ifdef CONFIG_IPV6_PRIVACY
++                      unsigned long regen_advance;
++#endif
++
++                      if (ifp->flags & IFA_F_PERMANENT)
++                              continue;
++
++                      spin_lock(&ifp->lock);
++                      age = (now - ifp->tstamp) / HZ;
++
++#ifdef CONFIG_IPV6_PRIVACY
++                      regen_advance = ifp->idev->cnf.regen_max_retry *
++                                      ifp->idev->cnf.dad_transmits *
++                                      ifp->idev->nd_parms->retrans_time / HZ;
++#endif
++
++                      if (ifp->valid_lft != INFINITY_LIFE_TIME &&
++                          age >= ifp->valid_lft) {
++                              spin_unlock(&ifp->lock);
++                              in6_ifa_hold(ifp);
++                              read_unlock(&addrconf_hash_lock);
++                              ipv6_del_addr(ifp);
++                              goto restart;
++                      } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) {
++                              spin_unlock(&ifp->lock);
++                              continue;
++                      } else if (age >= ifp->prefered_lft) {
++                              /* jiffies - ifp->tsamp > age >= ifp->prefered_lft */
++                              int deprecate = 0;
++
++                              if (!(ifp->flags&IFA_F_DEPRECATED)) {
++                                      deprecate = 1;
++                                      ifp->flags |= IFA_F_DEPRECATED;
++                              }
++
++                              if (time_before(ifp->tstamp + ifp->valid_lft * HZ, next))
++                                      next = ifp->tstamp + ifp->valid_lft * HZ;
++
++                              spin_unlock(&ifp->lock);
++
++                              if (deprecate) {
++                                      in6_ifa_hold(ifp);
++                                      read_unlock(&addrconf_hash_lock);
++
++                                      ipv6_ifa_notify(0, ifp);
++                                      in6_ifa_put(ifp);
++                                      goto restart;
++                              }
++#ifdef CONFIG_IPV6_PRIVACY
++                      } else if ((ifp->flags&IFA_F_TEMPORARY) &&
++                                 !(ifp->flags&IFA_F_TENTATIVE)) {
++                              if (age >= ifp->prefered_lft - regen_advance) {
++                                      struct inet6_ifaddr *ifpub = ifp->ifpub;
++                                      if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
++                                              next = ifp->tstamp + ifp->prefered_lft * HZ;
++                                      if (!ifp->regen_count && ifpub) {
++                                              ifp->regen_count++;
++                                              in6_ifa_hold(ifp);
++                                              in6_ifa_hold(ifpub);
++                                              spin_unlock(&ifp->lock);
++                                              read_unlock(&addrconf_hash_lock);
++                                              spin_lock(&ifpub->lock);
++                                              ifpub->regen_count = 0;
++                                              spin_unlock(&ifpub->lock);
++                                              ipv6_create_tempaddr(ifpub, ifp);
++                                              in6_ifa_put(ifpub);
++                                              in6_ifa_put(ifp);
++                                              goto restart;
++                                      }
++                              } else if (time_before(ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ, next))
++                                      next = ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ;
++                              spin_unlock(&ifp->lock);
++#endif
++                      } else {
++                              /* ifp->prefered_lft <= ifp->valid_lft */
++                              if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
++                                      next = ifp->tstamp + ifp->prefered_lft * HZ;
++                              spin_unlock(&ifp->lock);
++                      }
++              }
++              read_unlock(&addrconf_hash_lock);
++      }
++
++      addr_chk_timer.expires = time_before(next, jiffies + HZ) ? jiffies + HZ : next;
++      add_timer(&addr_chk_timer);
++      spin_unlock_bh(&addrconf_verify_lock);
++}
++
++static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local)
++{
++      struct in6_addr *pfx = NULL;
++
++      if (addr)
++              pfx = nla_data(addr);
++
++      if (local) {
++              if (pfx && nla_memcmp(local, pfx, sizeof(*pfx)))
++                      pfx = NULL;
++              else
++                      pfx = nla_data(local);
 +      }
 +
++      return pfx;
++}
 +
-       return 0;
-+ mip6_rawv6_mh_fail:
-+      xfrm_unregister_type(&mip6_rthdr_type, AF_INET6);
-  mip6_rthdr_xfrm_fail:
-       xfrm_unregister_type(&mip6_destopt_type, AF_INET6);
-  mip6_destopt_xfrm_fail:
-       return -EAGAIN;
- }
--void __exit mip6_fini(void)
-+static void __exit mip6_fini(void)
- {
-+      if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0)
-+              printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__);
-       if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
-               printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__);
-       if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
-               printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__);
- }
++static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
++      [IFA_ADDRESS]           = { .len = sizeof(struct in6_addr) },
++      [IFA_LOCAL]             = { .len = sizeof(struct in6_addr) },
++      [IFA_CACHEINFO]         = { .len = sizeof(struct ifa_cacheinfo) },
++};
 +
-+module_init(mip6_init);
-+module_exit(mip6_fini);
++static int
++inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
++{
++      struct ifaddrmsg *ifm;
++      struct nlattr *tb[IFA_MAX+1];
++      struct in6_addr *pfx;
++      int err;
 +
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_DSTOPTS);
-+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ROUTING);
-diff -Nurb linux-2.6.22-570/net/ipv6/ndisc.c linux-2.6.22-590/net/ipv6/ndisc.c
---- linux-2.6.22-570/net/ipv6/ndisc.c  2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/ndisc.c  2008-01-02 13:56:38.000000000 -0500
-@@ -418,6 +418,7 @@
-                           int oif)
- {
-       memset(fl, 0, sizeof(*fl));
-+      fl->fl_net = &init_net;
-       ipv6_addr_copy(&fl->fl6_src, saddr);
-       ipv6_addr_copy(&fl->fl6_dst, daddr);
-       fl->proto               = IPPROTO_ICMPV6;
-@@ -760,7 +761,7 @@
-               if (ipv6_chk_acast_addr(dev, &msg->target) ||
-                   (idev->cnf.forwarding &&
-                    (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) &&
--                   (pneigh = pneigh_lookup(&nd_tbl,
-+                   (pneigh = pneigh_lookup(&nd_tbl, &init_net,
-                                            &msg->target, dev, 0)) != NULL)) {
-                       if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
-                           skb->pkt_type != PACKET_HOST &&
-@@ -901,7 +902,7 @@
-                */
-               if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
-                   ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp &&
--                  pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
-+                  pneigh_lookup(&nd_tbl, &init_net, &msg->target, dev, 0)) {
-                       /* XXX: idev->cnf.prixy_ndp */
-                       goto out;
-               }
-@@ -1525,6 +1526,9 @@
- {
-       struct net_device *dev = ptr;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
++      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
++      if (err < 0)
++              return err;
 +
-       switch (event) {
-       case NETDEV_CHANGEADDR:
-               neigh_changeaddr(&nd_tbl, dev);
-diff -Nurb linux-2.6.22-570/net/ipv6/netfilter/ip6_queue.c linux-2.6.22-590/net/ipv6/netfilter/ip6_queue.c
---- linux-2.6.22-570/net/ipv6/netfilter/ip6_queue.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/netfilter/ip6_queue.c    2008-01-02 13:56:38.000000000 -0500
-@@ -24,6 +24,7 @@
- #include <linux/sysctl.h>
- #include <linux/proc_fs.h>
- #include <linux/mutex.h>
-+#include <net/net_namespace.h>
- #include <net/sock.h>
- #include <net/ipv6.h>
- #include <net/ip6_route.h>
-@@ -546,6 +547,9 @@
- {
-       struct net_device *dev = ptr;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
++      ifm = nlmsg_data(nlh);
++      pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
++      if (pfx == NULL)
++              return -EINVAL;
 +
-       /* Drop any packets associated with the downed device */
-       if (event == NETDEV_DOWN)
-               ipq_dev_drop(dev->ifindex);
-@@ -565,7 +569,7 @@
-       if (event == NETLINK_URELEASE &&
-           n->protocol == NETLINK_IP6_FW && n->pid) {
-               write_lock_bh(&queue_lock);
--              if (n->pid == peer_pid)
-+              if ((n->net == &init_net) && (n->pid == peer_pid))
-                       __ipq_reset();
-               write_unlock_bh(&queue_lock);
-       }
-@@ -657,14 +661,14 @@
-       struct proc_dir_entry *proc;
-       netlink_register_notifier(&ipq_nl_notifier);
--      ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk, NULL,
--                                    THIS_MODULE);
-+      ipqnl = netlink_kernel_create(&init_net, NETLINK_IP6_FW, 0, ipq_rcv_sk,
-+                                      NULL, THIS_MODULE);
-       if (ipqnl == NULL) {
-               printk(KERN_ERR "ip6_queue: failed to create netlink socket\n");
-               goto cleanup_netlink_notifier;
-       }
--      proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ipq_get_info);
-+      proc = proc_net_create(&init_net, IPQ_PROC_FS_NAME, 0, ipq_get_info);
-       if (proc)
-               proc->owner = THIS_MODULE;
-       else {
-@@ -685,7 +689,7 @@
- cleanup_sysctl:
-       unregister_sysctl_table(ipq_sysctl_header);
-       unregister_netdevice_notifier(&ipq_dev_notifier);
--      proc_net_remove(IPQ_PROC_FS_NAME);
-+      proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
- cleanup_ipqnl:
-       sock_release(ipqnl->sk_socket);
-@@ -705,7 +709,7 @@
-       unregister_sysctl_table(ipq_sysctl_header);
-       unregister_netdevice_notifier(&ipq_dev_notifier);
--      proc_net_remove(IPQ_PROC_FS_NAME);
-+      proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
-       sock_release(ipqnl->sk_socket);
-       mutex_lock(&ipqnl_mutex);
-diff -Nurb linux-2.6.22-570/net/ipv6/netfilter/ip6_tables.c linux-2.6.22-590/net/ipv6/netfilter/ip6_tables.c
---- linux-2.6.22-570/net/ipv6/netfilter/ip6_tables.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/netfilter/ip6_tables.c   2008-01-02 13:56:38.000000000 -0500
-@@ -906,7 +906,7 @@
-       int ret;
-       struct xt_table *t;
--      t = xt_find_table_lock(AF_INET6, entries->name);
-+      t = xt_find_table_lock(&init_net, AF_INET6, entries->name);
-       if (t && !IS_ERR(t)) {
-               struct xt_table_info *private = t->private;
-               duprintf("t->private->number = %u\n", private->number);
-@@ -972,7 +972,7 @@
-       duprintf("ip_tables: Translated table\n");
--      t = try_then_request_module(xt_find_table_lock(AF_INET6, tmp.name),
-+      t = try_then_request_module(xt_find_table_lock(&init_net, AF_INET6, tmp.name),
-                                   "ip6table_%s", tmp.name);
-       if (!t || IS_ERR(t)) {
-               ret = t ? PTR_ERR(t) : -ENOENT;
-@@ -1073,7 +1073,7 @@
-               goto free;
-       }
--      t = xt_find_table_lock(AF_INET6, tmp.name);
-+      t = xt_find_table_lock(&init_net, AF_INET6, tmp.name);
-       if (!t || IS_ERR(t)) {
-               ret = t ? PTR_ERR(t) : -ENOENT;
-               goto free;
-@@ -1109,6 +1109,9 @@
- {
-       int ret;
-+      if (sk->sk_net != &init_net)
-+              return -ENOPROTOOPT;
++      return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
++}
 +
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
-@@ -1134,6 +1137,9 @@
- {
-       int ret;
-+      if (sk->sk_net != &init_net)
-+              return -ENOPROTOOPT;
++static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
++                           u32 prefered_lft, u32 valid_lft)
++{
++      u32 flags = RTF_EXPIRES;
 +
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
-@@ -1155,7 +1161,7 @@
-               }
-               name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
--              t = try_then_request_module(xt_find_table_lock(AF_INET6, name),
-+              t = try_then_request_module(xt_find_table_lock(&init_net, AF_INET6, name),
-                                           "ip6table_%s", name);
-               if (t && !IS_ERR(t)) {
-                       struct ip6t_getinfo info;
-@@ -1259,7 +1265,7 @@
-               return ret;
-       }
--      ret = xt_register_table(table, &bootstrap, newinfo);
-+      ret = xt_register_table(&init_net, table, &bootstrap, newinfo);
-       if (ret != 0) {
-               xt_free_table_info(newinfo);
-               return ret;
-diff -Nurb linux-2.6.22-570/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.22-590/net/ipv6/netfilter/ip6t_REJECT.c
---- linux-2.6.22-570/net/ipv6/netfilter/ip6t_REJECT.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/netfilter/ip6t_REJECT.c  2008-01-02 13:56:38.000000000 -0500
-@@ -92,6 +92,7 @@
-       }
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       fl.proto = IPPROTO_TCP;
-       ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
-       ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
-@@ -172,7 +173,7 @@
- send_unreach(struct sk_buff *skb_in, unsigned char code, unsigned int hooknum)
- {
-       if (hooknum == NF_IP6_LOCAL_OUT && skb_in->dev == NULL)
--              skb_in->dev = &loopback_dev;
-+              skb_in->dev = &init_net.loopback_dev;
-       icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL);
- }
-diff -Nurb linux-2.6.22-570/net/ipv6/netfilter/ip6table_filter.c linux-2.6.22-590/net/ipv6/netfilter/ip6table_filter.c
---- linux-2.6.22-570/net/ipv6/netfilter/ip6table_filter.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/netfilter/ip6table_filter.c      2008-01-02 13:56:38.000000000 -0500
-@@ -65,6 +65,10 @@
-        const struct net_device *out,
-        int (*okfn)(struct sk_buff *))
- {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++      if (!valid_lft || (prefered_lft > valid_lft))
++              return -EINVAL;
 +
-       return ip6t_do_table(pskb, hook, in, out, &packet_filter);
- }
-@@ -75,6 +79,10 @@
-                  const struct net_device *out,
-                  int (*okfn)(struct sk_buff *))
- {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++      if (valid_lft == INFINITY_LIFE_TIME) {
++              ifa_flags |= IFA_F_PERMANENT;
++              flags = 0;
++      } else if (valid_lft >= 0x7FFFFFFF/HZ)
++              valid_lft = 0x7FFFFFFF/HZ;
 +
- #if 0
-       /* root is playing with raw sockets. */
-       if ((*pskb)->len < sizeof(struct iphdr)
-diff -Nurb linux-2.6.22-570/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.22-590/net/ipv6/netfilter/ip6table_mangle.c
---- linux-2.6.22-570/net/ipv6/netfilter/ip6table_mangle.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/netfilter/ip6table_mangle.c      2008-01-02 13:56:38.000000000 -0500
-@@ -79,6 +79,10 @@
-        const struct net_device *out,
-        int (*okfn)(struct sk_buff *))
- {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++      if (prefered_lft == 0)
++              ifa_flags |= IFA_F_DEPRECATED;
++      else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
++               (prefered_lft != INFINITY_LIFE_TIME))
++              prefered_lft = 0x7FFFFFFF/HZ;
 +
-       return ip6t_do_table(pskb, hook, in, out, &packet_mangler);
- }
-@@ -95,6 +99,10 @@
-       u_int8_t hop_limit;
-       u_int32_t flowlabel, mark;
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++      spin_lock_bh(&ifp->lock);
++      ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags;
++      ifp->tstamp = jiffies;
++      ifp->valid_lft = valid_lft;
++      ifp->prefered_lft = prefered_lft;
 +
- #if 0
-       /* root is playing with raw sockets. */
-       if ((*pskb)->len < sizeof(struct iphdr)
-diff -Nurb linux-2.6.22-570/net/ipv6/netfilter/ip6table_raw.c linux-2.6.22-590/net/ipv6/netfilter/ip6table_raw.c
---- linux-2.6.22-570/net/ipv6/netfilter/ip6table_raw.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/netfilter/ip6table_raw.c 2008-01-02 13:56:38.000000000 -0500
-@@ -57,6 +57,10 @@
-        const struct net_device *out,
-        int (*okfn)(struct sk_buff *))
- {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++      spin_unlock_bh(&ifp->lock);
++      if (!(ifp->flags&IFA_F_TENTATIVE))
++              ipv6_ifa_notify(0, ifp);
 +
-       return ip6t_do_table(pskb, hook, in, out, &packet_raw);
- }
-diff -Nurb linux-2.6.22-570/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c linux-2.6.22-590/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
---- linux-2.6.22-570/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c    2008-01-02 13:56:38.000000000 -0500
-@@ -167,6 +167,10 @@
-       unsigned char pnum = ipv6_hdr(*pskb)->nexthdr;
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++      addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev,
++                            jiffies_to_clock_t(valid_lft * HZ), flags);
++      addrconf_verify(0);
 +
-       /* This is where we call the helper: as the packet goes out. */
-       ct = nf_ct_get(*pskb, &ctinfo);
-       if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
-@@ -203,6 +207,10 @@
- {
-       struct sk_buff *reasm;
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++      return 0;
++}
 +
-       /* Previously seen (loopback)?  */
-       if ((*pskb)->nfct)
-               return NF_ACCEPT;
-@@ -231,6 +239,10 @@
- {
-       struct sk_buff *reasm = (*pskb)->nfct_reasm;
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++static int
++inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
++{
++      struct ifaddrmsg *ifm;
++      struct nlattr *tb[IFA_MAX+1];
++      struct in6_addr *pfx;
++      struct inet6_ifaddr *ifa;
++      struct net_device *dev;
++      u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
++      u8 ifa_flags;
++      int err;
 +
-       /* This packet is fragmented and has reassembled packet. */
-       if (reasm) {
-               /* Reassembled packet isn't parsed yet ? */
-@@ -256,6 +268,10 @@
-                                        const struct net_device *out,
-                                        int (*okfn)(struct sk_buff *))
- {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
++      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
++      if (err < 0)
++              return err;
 +
-       /* root is playing with raw sockets. */
-       if ((*pskb)->len < sizeof(struct ipv6hdr)) {
-               if (net_ratelimit())
-diff -Nurb linux-2.6.22-570/net/ipv6/netfilter.c linux-2.6.22-590/net/ipv6/netfilter.c
---- linux-2.6.22-570/net/ipv6/netfilter.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/netfilter.c      2008-01-02 13:56:38.000000000 -0500
-@@ -14,6 +14,7 @@
-       struct ipv6hdr *iph = ipv6_hdr(skb);
-       struct dst_entry *dst;
-       struct flowi fl = {
-+              .fl_net = &init_net,
-               .oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
-               .mark = skb->mark,
-               .nl_u =
-diff -Nurb linux-2.6.22-570/net/ipv6/proc.c linux-2.6.22-590/net/ipv6/proc.c
---- linux-2.6.22-570/net/ipv6/proc.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/proc.c   2008-01-02 13:56:38.000000000 -0500
-@@ -28,6 +28,7 @@
- #include <net/tcp.h>
- #include <net/transp_v6.h>
- #include <net/ipv6.h>
-+#include <net/net_namespace.h>
- static struct proc_dir_entry *proc_net_devsnmp6;
-@@ -231,22 +232,22 @@
- {
-       int rc = 0;
--      if (!proc_net_fops_create("snmp6", S_IRUGO, &snmp6_seq_fops))
-+      if (!proc_net_fops_create(&init_net, "snmp6", S_IRUGO, &snmp6_seq_fops))
-               goto proc_snmp6_fail;
--      proc_net_devsnmp6 = proc_mkdir("dev_snmp6", proc_net);
-+      proc_net_devsnmp6 = proc_mkdir("dev_snmp6", init_net.proc_net);
-       if (!proc_net_devsnmp6)
-               goto proc_dev_snmp6_fail;
--      if (!proc_net_fops_create("sockstat6", S_IRUGO, &sockstat6_seq_fops))
-+      if (!proc_net_fops_create(&init_net, "sockstat6", S_IRUGO, &sockstat6_seq_fops))
-               goto proc_sockstat6_fail;
- out:
-       return rc;
- proc_sockstat6_fail:
--      proc_net_remove("dev_snmp6");
-+      proc_net_remove(&init_net, "dev_snmp6");
- proc_dev_snmp6_fail:
--      proc_net_remove("snmp6");
-+      proc_net_remove(&init_net, "snmp6");
- proc_snmp6_fail:
-       rc = -ENOMEM;
-       goto out;
-@@ -254,8 +255,8 @@
- void ipv6_misc_proc_exit(void)
- {
--      proc_net_remove("sockstat6");
--      proc_net_remove("dev_snmp6");
--      proc_net_remove("snmp6");
-+      proc_net_remove(&init_net, "sockstat6");
-+      proc_net_remove(&init_net, "dev_snmp6");
-+      proc_net_remove(&init_net, "snmp6");
- }
-diff -Nurb linux-2.6.22-570/net/ipv6/raw.c linux-2.6.22-590/net/ipv6/raw.c
---- linux-2.6.22-570/net/ipv6/raw.c    2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/raw.c    2008-01-02 13:56:38.000000000 -0500
-@@ -49,7 +49,8 @@
- #include <net/udp.h>
- #include <net/inet_common.h>
- #include <net/tcp_states.h>
--#ifdef CONFIG_IPV6_MIP6
-+#include <net/net_namespace.h>
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- #include <net/mip6.h>
- #endif
-@@ -137,6 +138,28 @@
-       return 0;
- }
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-+static int (*mh_filter)(struct sock *sock, struct sk_buff *skb);
++      ifm = nlmsg_data(nlh);
++      pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
++      if (pfx == NULL)
++              return -EINVAL;
++
++      if (tb[IFA_CACHEINFO]) {
++              struct ifa_cacheinfo *ci;
++
++              ci = nla_data(tb[IFA_CACHEINFO]);
++              valid_lft = ci->ifa_valid;
++              preferred_lft = ci->ifa_prefered;
++      } else {
++              preferred_lft = INFINITY_LIFE_TIME;
++              valid_lft = INFINITY_LIFE_TIME;
++      }
++
++      dev =  __dev_get_by_index(ifm->ifa_index);
++      if (dev == NULL)
++              return -ENODEV;
++
++      /* We ignore other flags so far. */
++      ifa_flags = ifm->ifa_flags & (IFA_F_NODAD | IFA_F_HOMEADDRESS);
++
++      ifa = ipv6_get_ifaddr(pfx, dev, 1);
++      if (ifa == NULL) {
++              /*
++               * It would be best to check for !NLM_F_CREATE here but
++               * userspace alreay relies on not having to provide this.
++               */
++              return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
++                                    ifa_flags, preferred_lft, valid_lft);
++      }
++
++      if (nlh->nlmsg_flags & NLM_F_EXCL ||
++          !(nlh->nlmsg_flags & NLM_F_REPLACE))
++              err = -EEXIST;
++      else
++              err = inet6_addr_modify(ifa, ifa_flags, preferred_lft, valid_lft);
++
++      in6_ifa_put(ifa);
 +
-+int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
-+                                         struct sk_buff *skb))
++      return err;
++}
++
++static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u8 flags,
++                        u8 scope, int ifindex)
 +{
-+      rcu_assign_pointer(mh_filter, filter);
-+      return 0;
++      struct ifaddrmsg *ifm;
++
++      ifm = nlmsg_data(nlh);
++      ifm->ifa_family = AF_INET6;
++      ifm->ifa_prefixlen = prefixlen;
++      ifm->ifa_flags = flags;
++      ifm->ifa_scope = scope;
++      ifm->ifa_index = ifindex;
 +}
-+EXPORT_SYMBOL(rawv6_mh_filter_register);
 +
-+int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
-+                                           struct sk_buff *skb))
++static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
++                       unsigned long tstamp, u32 preferred, u32 valid)
 +{
-+      rcu_assign_pointer(mh_filter, NULL);
-+      synchronize_rcu();
-+      return 0;
++      struct ifa_cacheinfo ci;
++
++      ci.cstamp = (u32)(TIME_DELTA(cstamp, INITIAL_JIFFIES) / HZ * 100
++                      + TIME_DELTA(cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
++      ci.tstamp = (u32)(TIME_DELTA(tstamp, INITIAL_JIFFIES) / HZ * 100
++                      + TIME_DELTA(tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
++      ci.ifa_prefered = preferred;
++      ci.ifa_valid = valid;
++
++      return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci);
 +}
-+EXPORT_SYMBOL(rawv6_mh_filter_unregister);
 +
-+#endif
++static inline int rt_scope(int ifa_scope)
++{
++      if (ifa_scope & IFA_HOST)
++              return RT_SCOPE_HOST;
++      else if (ifa_scope & IFA_LINK)
++              return RT_SCOPE_LINK;
++      else if (ifa_scope & IFA_SITE)
++              return RT_SCOPE_SITE;
++      else
++              return RT_SCOPE_UNIVERSE;
++}
 +
- /*
-  *    demultiplex raw sockets.
-  *    (should consider queueing the skb in the sock receive_queue
-@@ -178,16 +201,22 @@
-               case IPPROTO_ICMPV6:
-                       filtered = icmpv6_filter(sk, skb);
-                       break;
--#ifdef CONFIG_IPV6_MIP6
++static inline int inet6_ifaddr_msgsize(void)
++{
++      return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
++             + nla_total_size(16) /* IFA_ADDRESS */
++             + nla_total_size(sizeof(struct ifa_cacheinfo));
++}
 +
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-               case IPPROTO_MH:
-+              {
-                       /* XXX: To validate MH only once for each packet,
-                        * this is placed here. It should be after checking
-                        * xfrm policy, however it doesn't. The checking xfrm
-                        * policy is placed in rawv6_rcv() because it is
-                        * required for each socket.
-                        */
--                      filtered = mip6_mh_filter(sk, skb);
-+                      int (*filter)(struct sock *sock, struct sk_buff *skb);
++static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
++                           u32 pid, u32 seq, int event, unsigned int flags)
++{
++      struct nlmsghdr  *nlh;
++      u32 preferred, valid;
 +
-+                      filter = rcu_dereference(mh_filter);
-+                      filtered = filter ? filter(sk, skb) : 0;
-                       break;
++      nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
++      if (nlh == NULL)
++              return -EMSGSIZE;
++
++      put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
++                    ifa->idev->dev->ifindex);
++
++      if (!(ifa->flags&IFA_F_PERMANENT)) {
++              preferred = ifa->prefered_lft;
++              valid = ifa->valid_lft;
++              if (preferred != INFINITY_LIFE_TIME) {
++                      long tval = (jiffies - ifa->tstamp)/HZ;
++                      preferred -= tval;
++                      if (valid != INFINITY_LIFE_TIME)
++                              valid -= tval;
 +              }
- #endif
-               default:
-                       filtered = 0;
-@@ -254,7 +283,7 @@
-                       if (!sk->sk_bound_dev_if)
-                               goto out;
--                      dev = dev_get_by_index(sk->sk_bound_dev_if);
-+                      dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
-                       if (!dev) {
-                               err = -ENODEV;
-                               goto out;
-@@ -611,9 +640,7 @@
-       struct iovec *iov;
-       u8 __user *type = NULL;
-       u8 __user *code = NULL;
--#ifdef CONFIG_IPV6_MIP6
-       u8 len = 0;
--#endif
-       int probed = 0;
-       int i;
-@@ -646,7 +673,6 @@
-                               probed = 1;
-                       }
-                       break;
--#ifdef CONFIG_IPV6_MIP6
-               case IPPROTO_MH:
-                       if (iov->iov_base && iov->iov_len < 1)
-                               break;
-@@ -660,7 +686,6 @@
-                               len += iov->iov_len;
-                       break;
--#endif
-               default:
-                       probed = 1;
-                       break;
-@@ -704,6 +729,7 @@
-        *      Get and verify the address.
-        */
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       if (sin6) {
-               if (addr_len < SIN6_LEN_RFC2133)
-@@ -1291,13 +1317,13 @@
- int __init raw6_proc_init(void)
- {
--      if (!proc_net_fops_create("raw6", S_IRUGO, &raw6_seq_fops))
-+      if (!proc_net_fops_create(&init_net, "raw6", S_IRUGO, &raw6_seq_fops))
-               return -ENOMEM;
-       return 0;
- }
- void raw6_proc_exit(void)
- {
--      proc_net_remove("raw6");
-+      proc_net_remove(&init_net, "raw6");
- }
- #endif        /* CONFIG_PROC_FS */
-diff -Nurb linux-2.6.22-570/net/ipv6/reassembly.c linux-2.6.22-590/net/ipv6/reassembly.c
---- linux-2.6.22-570/net/ipv6/reassembly.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/reassembly.c     2008-01-02 13:56:38.000000000 -0500
-@@ -301,7 +301,7 @@
-       fq_kill(fq);
--      dev = dev_get_by_index(fq->iif);
-+      dev = dev_get_by_index(&init_net, fq->iif);
-       if (!dev)
-               goto out;
-diff -Nurb linux-2.6.22-570/net/ipv6/route.c linux-2.6.22-590/net/ipv6/route.c
---- linux-2.6.22-570/net/ipv6/route.c  2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/route.c  2008-01-02 13:56:38.000000000 -0500
-@@ -56,6 +56,7 @@
- #include <net/xfrm.h>
- #include <net/netevent.h>
- #include <net/netlink.h>
-+#include <net/net_namespace.h>
- #include <asm/uaccess.h>
-@@ -137,7 +138,7 @@
-               .dst = {
-                       .__refcnt       = ATOMIC_INIT(1),
-                       .__use          = 1,
--                      .dev            = &loopback_dev,
-+                      .dev            = NULL,
-                       .obsolete       = -1,
-                       .error          = -ENETUNREACH,
-                       .metrics        = { [RTAX_HOPLIMIT - 1] = 255, },
-@@ -163,7 +164,7 @@
-               .dst = {
-                       .__refcnt       = ATOMIC_INIT(1),
-                       .__use          = 1,
--                      .dev            = &loopback_dev,
-+                      .dev            = NULL,
-                       .obsolete       = -1,
-                       .error          = -EACCES,
-                       .metrics        = { [RTAX_HOPLIMIT - 1] = 255, },
-@@ -183,7 +184,7 @@
-               .dst = {
-                       .__refcnt       = ATOMIC_INIT(1),
-                       .__use          = 1,
--                      .dev            = &loopback_dev,
-+                      .dev            = NULL,
-                       .obsolete       = -1,
-                       .error          = -EINVAL,
-                       .metrics        = { [RTAX_HOPLIMIT - 1] = 255, },
-@@ -223,8 +224,8 @@
-       struct rt6_info *rt = (struct rt6_info *)dst;
-       struct inet6_dev *idev = rt->rt6i_idev;
--      if (dev != &loopback_dev && idev != NULL && idev->dev == dev) {
--              struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev);
-+      if (dev != &init_net.loopback_dev && idev != NULL && idev->dev == dev) {
-+              struct inet6_dev *loopback_idev = in6_dev_get(&init_net.loopback_dev);
-               if (loopback_idev != NULL) {
-                       rt->rt6i_idev = loopback_idev;
-                       in6_dev_put(idev);
-@@ -564,6 +565,7 @@
-                           int oif, int strict)
- {
-       struct flowi fl = {
-+              .fl_net = &init_net,
-               .oif = oif,
-               .nl_u = {
-                       .ip6_u = {
-@@ -611,7 +613,12 @@
- int ip6_ins_rt(struct rt6_info *rt)
- {
--      return __ip6_ins_rt(rt, NULL);
-+      struct nl_info info = {
-+              .nlh = NULL,
-+              .pid = 0,
-+              .net = &init_net,
-+      };
-+      return __ip6_ins_rt(rt, &info);
- }
- static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr,
-@@ -742,6 +749,7 @@
-       struct ipv6hdr *iph = ipv6_hdr(skb);
-       int flags = RT6_LOOKUP_F_HAS_SADDR;
-       struct flowi fl = {
-+              .fl_net = &init_net,
-               .iif = skb->dev->ifindex,
-               .nl_u = {
-                       .ip6_u = {
-@@ -1129,7 +1137,7 @@
- #endif
-       if (cfg->fc_ifindex) {
-               err = -ENODEV;
--              dev = dev_get_by_index(cfg->fc_ifindex);
-+              dev = dev_get_by_index(&init_net, cfg->fc_ifindex);
-               if (!dev)
-                       goto out;
-               idev = in6_dev_get(dev);
-@@ -1187,12 +1195,12 @@
-       if ((cfg->fc_flags & RTF_REJECT) ||
-           (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
-               /* hold loopback dev/idev if we haven't done so. */
--              if (dev != &loopback_dev) {
-+              if (dev != &init_net.loopback_dev) {
-                       if (dev) {
-                               dev_put(dev);
-                               in6_dev_put(idev);
-                       }
--                      dev = &loopback_dev;
-+                      dev = &init_net.loopback_dev;
-                       dev_hold(dev);
-                       idev = in6_dev_get(dev);
-                       if (!idev) {
-@@ -1333,7 +1341,12 @@
- int ip6_del_rt(struct rt6_info *rt)
- {
--      return __ip6_del_rt(rt, NULL);
-+      struct nl_info info = {
-+              .nlh = NULL,
-+              .pid = 0,
-+              .net = &init_net,
-+      };
-+      return __ip6_del_rt(rt, &info);
- }
- static int ip6_route_del(struct fib6_config *cfg)
-@@ -1444,6 +1457,7 @@
-       int flags = RT6_LOOKUP_F_HAS_SADDR;
-       struct ip6rd_flowi rdfl = {
-               .fl = {
-+                      .fl_net = &init_net,
-                       .oif = dev->ifindex,
-                       .nl_u = {
-                               .ip6_u = {
-@@ -1896,13 +1910,13 @@
-       if (rt == NULL)
-               return ERR_PTR(-ENOMEM);
--      dev_hold(&loopback_dev);
-+      dev_hold(&init_net.loopback_dev);
-       in6_dev_hold(idev);
-       rt->u.dst.flags = DST_HOST;
-       rt->u.dst.input = ip6_input;
-       rt->u.dst.output = ip6_output;
--      rt->rt6i_dev = &loopback_dev;
-+      rt->rt6i_dev = &init_net.loopback_dev;
-       rt->rt6i_idev = idev;
-       rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
-       rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
-@@ -2033,6 +2047,7 @@
-       cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
-       cfg->fc_nlinfo.nlh = nlh;
-+      cfg->fc_nlinfo.net = skb->sk->sk_net;
-       if (tb[RTA_GATEWAY]) {
-               nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16);
-@@ -2078,9 +2093,13 @@
- static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct fib6_config cfg;
-       int err;
-+      if (net != &init_net)
-+              return -EINVAL;
++      } else {
++              preferred = INFINITY_LIFE_TIME;
++              valid = INFINITY_LIFE_TIME;
++      }
++
++      if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 ||
++          put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) {
++              nlmsg_cancel(skb, nlh);
++              return -EMSGSIZE;
++      }
++
++      return nlmsg_end(skb, nlh);
++}
++
++static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
++                              u32 pid, u32 seq, int event, u16 flags)
++{
++      struct nlmsghdr  *nlh;
++      u8 scope = RT_SCOPE_UNIVERSE;
++      int ifindex = ifmca->idev->dev->ifindex;
++
++      if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
++              scope = RT_SCOPE_SITE;
++
++      nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
++      if (nlh == NULL)
++              return -EMSGSIZE;
++
++      put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
++      if (nla_put(skb, IFA_MULTICAST, 16, &ifmca->mca_addr) < 0 ||
++          put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp,
++                        INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
++              nlmsg_cancel(skb, nlh);
++              return -EMSGSIZE;
++      }
++
++      return nlmsg_end(skb, nlh);
++}
++
++static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
++                              u32 pid, u32 seq, int event, unsigned int flags)
++{
++      struct nlmsghdr  *nlh;
++      u8 scope = RT_SCOPE_UNIVERSE;
++      int ifindex = ifaca->aca_idev->dev->ifindex;
++
++      if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE)
++              scope = RT_SCOPE_SITE;
++
++      nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
++      if (nlh == NULL)
++              return -EMSGSIZE;
++
++      put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
++      if (nla_put(skb, IFA_ANYCAST, 16, &ifaca->aca_addr) < 0 ||
++          put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp,
++                        INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
++              nlmsg_cancel(skb, nlh);
++              return -EMSGSIZE;
++      }
++
++      return nlmsg_end(skb, nlh);
++}
++
++enum addr_type_t
++{
++      UNICAST_ADDR,
++      MULTICAST_ADDR,
++      ANYCAST_ADDR,
++};
++
++static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
++                         enum addr_type_t type)
++{
++      int idx, ip_idx;
++      int s_idx, s_ip_idx;
++      int err = 1;
++      struct net_device *dev;
++      struct inet6_dev *idev = NULL;
++      struct inet6_ifaddr *ifa;
++      struct ifmcaddr6 *ifmca;
++      struct ifacaddr6 *ifaca;
++
++      s_idx = cb->args[0];
++      s_ip_idx = ip_idx = cb->args[1];
++
++      idx = 0;
++      for_each_netdev(dev) {
++              if (idx < s_idx)
++                      goto cont;
++              if (idx > s_idx)
++                      s_ip_idx = 0;
++              ip_idx = 0;
++              if ((idev = in6_dev_get(dev)) == NULL)
++                      goto cont;
++              read_lock_bh(&idev->lock);
++              switch (type) {
++              case UNICAST_ADDR:
++                      /* unicast address incl. temp addr */
++                      for (ifa = idev->addr_list; ifa;
++                           ifa = ifa->if_next, ip_idx++) {
++                              if (ip_idx < s_ip_idx)
++                                      continue;
++                              if ((err = inet6_fill_ifaddr(skb, ifa,
++                                  NETLINK_CB(cb->skb).pid,
++                                  cb->nlh->nlmsg_seq, RTM_NEWADDR,
++                                  NLM_F_MULTI)) <= 0)
++                                      goto done;
++                      }
++                      break;
++              case MULTICAST_ADDR:
++                      /* multicast address */
++                      for (ifmca = idev->mc_list; ifmca;
++                           ifmca = ifmca->next, ip_idx++) {
++                              if (ip_idx < s_ip_idx)
++                                      continue;
++                              if ((err = inet6_fill_ifmcaddr(skb, ifmca,
++                                  NETLINK_CB(cb->skb).pid,
++                                  cb->nlh->nlmsg_seq, RTM_GETMULTICAST,
++                                  NLM_F_MULTI)) <= 0)
++                                      goto done;
++                      }
++                      break;
++              case ANYCAST_ADDR:
++                      /* anycast address */
++                      for (ifaca = idev->ac_list; ifaca;
++                           ifaca = ifaca->aca_next, ip_idx++) {
++                              if (ip_idx < s_ip_idx)
++                                      continue;
++                              if ((err = inet6_fill_ifacaddr(skb, ifaca,
++                                  NETLINK_CB(cb->skb).pid,
++                                  cb->nlh->nlmsg_seq, RTM_GETANYCAST,
++                                  NLM_F_MULTI)) <= 0)
++                                      goto done;
++                      }
++                      break;
++              default:
++                      break;
++              }
++              read_unlock_bh(&idev->lock);
++              in6_dev_put(idev);
++cont:
++              idx++;
++      }
++done:
++      if (err <= 0) {
++              read_unlock_bh(&idev->lock);
++              in6_dev_put(idev);
++      }
++      cb->args[0] = idx;
++      cb->args[1] = ip_idx;
++      return skb->len;
++}
++
++static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
++{
++      enum addr_type_t type = UNICAST_ADDR;
++      return inet6_dump_addr(skb, cb, type);
++}
 +
-       err = rtm_to_fib6_config(skb, nlh, &cfg);
-       if (err < 0)
-               return err;
-@@ -2090,9 +2109,13 @@
- static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
- {
-+      struct net *net = skb->sk->sk_net;
-       struct fib6_config cfg;
-       int err;
-+      if (net != &init_net)
-+              return -EINVAL;
++static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb)
++{
++      enum addr_type_t type = MULTICAST_ADDR;
++      return inet6_dump_addr(skb, cb, type);
++}
 +
-       err = rtm_to_fib6_config(skb, nlh, &cfg);
-       if (err < 0)
-               return err;
-@@ -2227,6 +2250,7 @@
- static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
- {
-+      struct net *net = in_skb->sk->sk_net;
-       struct nlattr *tb[RTA_MAX+1];
-       struct rt6_info *rt;
-       struct sk_buff *skb;
-@@ -2234,12 +2258,16 @@
-       struct flowi fl;
-       int err, iif = 0;
-+      if (net != &init_net)
-+              return -EINVAL;
 +
-       err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
-       if (err < 0)
-               goto errout;
-       err = -EINVAL;
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       if (tb[RTA_SRC]) {
-               if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
-@@ -2263,7 +2291,7 @@
-       if (iif) {
-               struct net_device *dev;
--              dev = __dev_get_by_index(iif);
-+              dev = __dev_get_by_index(&init_net, iif);
-               if (!dev) {
-                       err = -ENODEV;
-                       goto errout;
-@@ -2293,7 +2321,7 @@
-               goto errout;
-       }
--      err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
-+      err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
- errout:
-       return err;
- }
-@@ -2301,17 +2329,10 @@
- void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
- {
-       struct sk_buff *skb;
--      u32 pid = 0, seq = 0;
--      struct nlmsghdr *nlh = NULL;
-+      u32 pid = info->pid, seq = info->nlh ? info->nlh->nlmsg_seq : 0;
-+      struct nlmsghdr *nlh = info->nlh;
-       int err = -ENOBUFS;
--      if (info) {
--              pid = info->pid;
--              nlh = info->nlh;
--              if (nlh)
--                      seq = nlh->nlmsg_seq;
--      }
--
-       skb = nlmsg_new(rt6_nlmsg_size(), gfp_any());
-       if (skb == NULL)
-               goto errout;
-@@ -2323,10 +2344,10 @@
-               kfree_skb(skb);
-               goto errout;
-       }
--      err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
-+      err = rtnl_notify(skb, &init_net, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
- errout:
-       if (err < 0)
--              rtnl_set_sk_err(RTNLGRP_IPV6_ROUTE, err);
-+              rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_ROUTE, err);
- }
- /*
-@@ -2558,13 +2579,19 @@
-                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
-       ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
-+      /* Perform the initialization we can't perform at compile time */
-+      ip6_null_entry.u.dst.dev = &init_net.loopback_dev;
-+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-+      ip6_prohibit_entry.u.dst.dev = &init_net.loopback_dev;
-+      ip6_blk_hole_entry.u.dst.dev = &init_net.loopback_dev;
-+#endif        
-       fib6_init();
- #ifdef        CONFIG_PROC_FS
--      p = proc_net_create("ipv6_route", 0, rt6_proc_info);
-+      p = proc_net_create(&init_net, "ipv6_route", 0, rt6_proc_info);
-       if (p)
-               p->owner = THIS_MODULE;
--      proc_net_fops_create("rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
-+      proc_net_fops_create(&init_net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
- #endif
- #ifdef CONFIG_XFRM
-       xfrm6_init();
-@@ -2584,8 +2611,8 @@
-       fib6_rules_cleanup();
- #endif
- #ifdef CONFIG_PROC_FS
--      proc_net_remove("ipv6_route");
--      proc_net_remove("rt6_stats");
-+      proc_net_remove(&init_net, "ipv6_route");
-+      proc_net_remove(&init_net, "rt6_stats");
- #endif
- #ifdef CONFIG_XFRM
-       xfrm6_fini();
-diff -Nurb linux-2.6.22-570/net/ipv6/sit.c linux-2.6.22-590/net/ipv6/sit.c
---- linux-2.6.22-570/net/ipv6/sit.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/sit.c    2008-01-02 13:56:38.000000000 -0500
-@@ -167,7 +167,7 @@
-               int i;
-               for (i=1; i<100; i++) {
-                       sprintf(name, "sit%d", i);
--                      if (__dev_get_by_name(name) == NULL)
-+                      if (__dev_get_by_name(&init_net, name) == NULL)
-                               break;
-               }
-               if (i==100)
-@@ -283,6 +283,9 @@
-       struct sk_buff *skb2;
-       struct rt6_info *rt6i;
-+      if (skb->dev->nd_net != &init_net)
-+              return;
++static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
++{
++      enum addr_type_t type = ANYCAST_ADDR;
++      return inet6_dump_addr(skb, cb, type);
++}
 +
-       if (len < hlen + sizeof(struct ipv6hdr))
-               return;
-       iph6 = (struct ipv6hdr*)(dp + hlen);
-@@ -369,6 +372,10 @@
-       struct iphdr *iph;
-       struct ip_tunnel *tunnel;
-+      if (skb->dev->nd_net != &init_net) {
++static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
++                           void *arg)
++{
++      struct ifaddrmsg *ifm;
++      struct nlattr *tb[IFA_MAX+1];
++      struct in6_addr *addr = NULL;
++      struct net_device *dev = NULL;
++      struct inet6_ifaddr *ifa;
++      struct sk_buff *skb;
++      int err;
++
++      err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
++      if (err < 0)
++              goto errout;
++
++      addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
++      if (addr == NULL) {
++              err = -EINVAL;
++              goto errout;
++      }
++
++      ifm = nlmsg_data(nlh);
++      if (ifm->ifa_index)
++              dev = __dev_get_by_index(ifm->ifa_index);
++
++      if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) {
++              err = -EADDRNOTAVAIL;
++              goto errout;
++      }
++
++      if ((skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL)) == NULL) {
++              err = -ENOBUFS;
++              goto errout_ifa;
++      }
++
++      err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
++                              nlh->nlmsg_seq, RTM_NEWADDR, 0);
++      if (err < 0) {
++              /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
++              WARN_ON(err == -EMSGSIZE);
 +              kfree_skb(skb);
-+              return 0;
++              goto errout_ifa;
 +      }
-       if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
-               goto out;
-@@ -474,7 +481,8 @@
-       }
-       {
--              struct flowi fl = { .nl_u = { .ip4_u =
-+              struct flowi fl = { .fl_net = &init_net,
-+                                  .nl_u = { .ip4_u =
-                                             { .daddr = dst,
-                                               .saddr = tiph->saddr,
-                                               .tos = RT_TOS(tos) } },
-@@ -745,7 +753,8 @@
-       memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
-       if (iph->daddr) {
--              struct flowi fl = { .nl_u = { .ip4_u =
-+              struct flowi fl = { .fl_net = &init_net,
-+                                  .nl_u = { .ip4_u =
-                                             { .daddr = iph->daddr,
-                                               .saddr = iph->saddr,
-                                               .tos = RT_TOS(iph->tos) } },
-@@ -760,7 +769,7 @@
-       }
-       if (!tdev && tunnel->parms.link)
--              tdev = __dev_get_by_index(tunnel->parms.link);
-+              tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
-       if (tdev) {
-               dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
-diff -Nurb linux-2.6.22-570/net/ipv6/tcp_ipv6.c linux-2.6.22-590/net/ipv6/tcp_ipv6.c
---- linux-2.6.22-570/net/ipv6/tcp_ipv6.c       2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/tcp_ipv6.c       2008-01-02 13:56:38.000000000 -0500
-@@ -143,6 +143,7 @@
-               return(-EAFNOSUPPORT);
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       if (np->sndflow) {
-               fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
-@@ -330,6 +331,7 @@
- static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-               int type, int code, int offset, __be32 info)
- {
-+      struct net *net = skb->dev->nd_net;
-       struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
-       const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
-       struct ipv6_pinfo *np;
-@@ -339,7 +341,7 @@
-       __u32 seq;
-       sk = inet6_lookup(&tcp_hashinfo, &hdr->daddr, th->dest, &hdr->saddr,
--                        th->source, skb->dev->ifindex);
-+                        th->source, skb->dev->ifindex, net);
-       if (sk == NULL) {
-               ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
-@@ -388,6 +390,7 @@
-                          for now.
-                        */
-                       memset(&fl, 0, sizeof(fl));
-+                      fl.fl_net = &init_net;
-                       fl.proto = IPPROTO_TCP;
-                       ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
-                       ipv6_addr_copy(&fl.fl6_src, &np->saddr);
-@@ -481,6 +484,7 @@
-       int err = -1;
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       fl.proto = IPPROTO_TCP;
-       ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
-       ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
-@@ -1066,6 +1070,7 @@
-       buff->csum = csum_partial((char *)t1, sizeof(*t1), 0);
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
-       ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr);
-@@ -1167,6 +1172,7 @@
-       buff->csum = csum_partial((char *)t1, tot_len, 0);
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
-       ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr);
-@@ -1224,7 +1230,8 @@
-       nsk = __inet6_lookup_established(&tcp_hashinfo, &ipv6_hdr(skb)->saddr,
-                                        th->source, &ipv6_hdr(skb)->daddr,
--                                       ntohs(th->dest), inet6_iif(skb));
-+                                       ntohs(th->dest), inet6_iif(skb),
-+                                       sk->sk_net);
-       if (nsk) {
-               if (nsk->sk_state != TCP_TIME_WAIT) {
-@@ -1414,6 +1421,7 @@
-               struct flowi fl;
-               memset(&fl, 0, sizeof(fl));
-+              fl.fl_net = &init_net;
-               fl.proto = IPPROTO_TCP;
-               ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
-               if (opt && opt->srcrt) {
-@@ -1700,6 +1708,7 @@
- static int tcp_v6_rcv(struct sk_buff **pskb)
- {
-       struct sk_buff *skb = *pskb;
-+      struct net *net = skb->dev->nd_net;
-       struct tcphdr *th;
-       struct sock *sk;
-       int ret;
-@@ -1736,7 +1745,7 @@
-       sk = __inet6_lookup(&tcp_hashinfo, &ipv6_hdr(skb)->saddr, th->source,
-                           &ipv6_hdr(skb)->daddr, ntohs(th->dest),
--                          inet6_iif(skb));
-+                          inet6_iif(skb), net);
-       if (!sk)
-               goto no_tcp_socket;
-@@ -1816,7 +1825,8 @@
-               sk2 = inet6_lookup_listener(&tcp_hashinfo,
-                                           &ipv6_hdr(skb)->daddr,
--                                          ntohs(th->dest), inet6_iif(skb));
-+                                          ntohs(th->dest), inet6_iif(skb),
-+                                          net);
-               if (sk2 != NULL) {
-                       struct inet_timewait_sock *tw = inet_twsk(sk);
-                       inet_twsk_deschedule(tw, &tcp_death_row);
-@@ -2121,12 +2131,12 @@
- int __init tcp6_proc_init(void)
- {
--      return tcp_proc_register(&tcp6_seq_afinfo);
-+      return tcp_proc_register(&init_net, &tcp6_seq_afinfo);
- }
- void tcp6_proc_exit(void)
- {
--      tcp_proc_unregister(&tcp6_seq_afinfo);
-+      tcp_proc_unregister(&init_net, &tcp6_seq_afinfo);
- }
- #endif
-diff -Nurb linux-2.6.22-570/net/ipv6/udp.c linux-2.6.22-590/net/ipv6/udp.c
---- linux-2.6.22-570/net/ipv6/udp.c    2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/udp.c    2008-01-02 13:56:38.000000000 -0500
-@@ -657,6 +657,7 @@
-       ulen += sizeof(struct udphdr);
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       if (sin6) {
-               if (sin6->sin6_port == 0)
-@@ -967,11 +968,11 @@
- int __init udp6_proc_init(void)
- {
--      return udp_proc_register(&udp6_seq_afinfo);
-+      return udp_proc_register(&init_net, &udp6_seq_afinfo);
- }
- void udp6_proc_exit(void) {
--      udp_proc_unregister(&udp6_seq_afinfo);
-+      udp_proc_unregister(&init_net, &udp6_seq_afinfo);
- }
- #endif /* CONFIG_PROC_FS */
-diff -Nurb linux-2.6.22-570/net/ipv6/udplite.c linux-2.6.22-590/net/ipv6/udplite.c
---- linux-2.6.22-570/net/ipv6/udplite.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/udplite.c        2008-01-02 13:56:38.000000000 -0500
-@@ -95,11 +95,11 @@
- int __init udplite6_proc_init(void)
- {
--      return udp_proc_register(&udplite6_seq_afinfo);
-+      return udp_proc_register(&init_net, &udplite6_seq_afinfo);
- }
- void udplite6_proc_exit(void)
- {
--      udp_proc_unregister(&udplite6_seq_afinfo);
-+      udp_proc_unregister(&init_net, &udplite6_seq_afinfo);
- }
- #endif
-diff -Nurb linux-2.6.22-570/net/ipv6/xfrm6_policy.c linux-2.6.22-590/net/ipv6/xfrm6_policy.c
---- linux-2.6.22-570/net/ipv6/xfrm6_policy.c   2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/ipv6/xfrm6_policy.c   2008-01-02 13:56:38.000000000 -0500
-@@ -18,7 +18,7 @@
- #include <net/ip.h>
- #include <net/ipv6.h>
- #include <net/ip6_route.h>
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- #include <net/mip6.h>
- #endif
-@@ -40,6 +40,7 @@
- {
-       struct rt6_info *rt;
-       struct flowi fl_tunnel = {
-+              .fl_net = &init_net,
-               .nl_u = {
-                       .ip6_u = {
-                               .daddr = *(struct in6_addr *)&daddr->a6,
-@@ -132,6 +133,7 @@
-       struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
-       struct rt6_info *rt  = rt0;
-       struct flowi fl_tunnel = {
-+              .fl_net = &init_net,
-               .nl_u = {
-                       .ip6_u = {
-                               .saddr = fl->fl6_src,
-@@ -278,6 +280,7 @@
-       u8 nexthdr = nh[IP6CB(skb)->nhoff];
-       memset(fl, 0, sizeof(struct flowi));
-+      fl->fl_net = &init_net;
-       ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
-       ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
-@@ -318,7 +321,7 @@
-                       fl->proto = nexthdr;
-                       return;
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-               case IPPROTO_MH:
-                       if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
-                               struct ip6_mh *mh;
-@@ -375,7 +378,7 @@
-       xdst = (struct xfrm_dst *)dst;
-       if (xdst->u.rt6.rt6i_idev->dev == dev) {
--              struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev);
-+              struct inet6_dev *loopback_idev = in6_dev_get(&init_net.loopback_dev);
-               BUG_ON(!loopback_idev);
-               do {
-diff -Nurb linux-2.6.22-570/net/ipv6/xfrm6_state.c linux-2.6.22-590/net/ipv6/xfrm6_state.c
---- linux-2.6.22-570/net/ipv6/xfrm6_state.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/xfrm6_state.c    2008-01-02 13:56:38.000000000 -0500
-@@ -65,7 +65,7 @@
-               goto end;
-       /* Rule 2: select MIPv6 RO or inbound trigger */
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-       for (i = 0; i < n; i++) {
-               if (src[i] &&
-                   (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION ||
-@@ -130,7 +130,7 @@
-               goto end;
-       /* Rule 2: select MIPv6 RO or inbound trigger */
--#ifdef CONFIG_IPV6_MIP6
-+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-       for (i = 0; i < n; i++) {
-               if (src[i] &&
-                   (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION ||
-diff -Nurb linux-2.6.22-570/net/ipv6/xfrm6_tunnel.c linux-2.6.22-590/net/ipv6/xfrm6_tunnel.c
---- linux-2.6.22-570/net/ipv6/xfrm6_tunnel.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipv6/xfrm6_tunnel.c   2008-01-02 13:56:38.000000000 -0500
-@@ -379,3 +379,4 @@
- module_init(xfrm6_tunnel_init);
- module_exit(xfrm6_tunnel_fini);
- MODULE_LICENSE("GPL");
-+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_IPV6);
-diff -Nurb linux-2.6.22-570/net/ipx/af_ipx.c linux-2.6.22-590/net/ipx/af_ipx.c
---- linux-2.6.22-570/net/ipx/af_ipx.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipx/af_ipx.c  2008-01-02 13:56:38.000000000 -0500
-@@ -347,6 +347,9 @@
-       struct net_device *dev = ptr;
-       struct ipx_interface *i, *tmp;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
++      err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
++errout_ifa:
++      in6_ifa_put(ifa);
++errout:
++      return err;
++}
 +
-       if (event != NETDEV_DOWN && event != NETDEV_UP)
-               goto out;
-@@ -986,7 +989,7 @@
-       if (intrfc)
-               ipxitf_put(intrfc);
--      dev = dev_get_by_name(idef->ipx_device);
-+      dev = dev_get_by_name(&init_net, idef->ipx_device);
-       rc = -ENODEV;
-       if (!dev)
-               goto out;
-@@ -1094,7 +1097,7 @@
-       if (!dlink_type)
-               goto out;
--      dev = __dev_get_by_name(idef->ipx_device);
-+      dev = __dev_get_by_name(&init_net, idef->ipx_device);
-       rc = -ENODEV;
-       if (!dev)
-               goto out;
-@@ -1189,7 +1192,7 @@
-               if (copy_from_user(&ifr, arg, sizeof(ifr)))
-                       break;
-               sipx = (struct sockaddr_ipx *)&ifr.ifr_addr;
--              dev  = __dev_get_by_name(ifr.ifr_name);
-+              dev  = __dev_get_by_name(&init_net, ifr.ifr_name);
-               rc   = -ENODEV;
-               if (!dev)
-                       break;
-@@ -1360,11 +1363,14 @@
-       .obj_size = sizeof(struct ipx_sock),
- };
--static int ipx_create(struct socket *sock, int protocol)
-+static int ipx_create(struct net *net, struct socket *sock, int protocol)
- {
-       int rc = -ESOCKTNOSUPPORT;
-       struct sock *sk;
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
++static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
++{
++      struct sk_buff *skb;
++      int err = -ENOBUFS;
 +
-       /*
-        * SPX support is not anymore in the kernel sources. If you want to
-        * ressurrect it, completing it and making it understand shared skbs,
-@@ -1375,7 +1381,7 @@
-               goto out;
-       rc = -ENOMEM;
--      sk = sk_alloc(PF_IPX, GFP_KERNEL, &ipx_proto, 1);
-+      sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto, 1);
-       if (!sk)
-               goto out;
- #ifdef IPX_REFCNT_DEBUG
-@@ -1644,6 +1650,9 @@
-       u16 ipx_pktsize;
-       int rc = 0;
-+      if (dev->nd_net != &init_net)
-+              goto drop;
++      skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC);
++      if (skb == NULL)
++              goto errout;
 +
-       /* Not ours */
-       if (skb->pkt_type == PACKET_OTHERHOST)
-               goto drop;
-diff -Nurb linux-2.6.22-570/net/ipx/ipx_proc.c linux-2.6.22-590/net/ipx/ipx_proc.c
---- linux-2.6.22-570/net/ipx/ipx_proc.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/ipx/ipx_proc.c        2008-01-02 13:56:38.000000000 -0500
-@@ -9,6 +9,7 @@
- #include <linux/proc_fs.h>
- #include <linux/spinlock.h>
- #include <linux/seq_file.h>
-+#include <net/net_namespace.h>
- #include <net/tcp_states.h>
- #include <net/ipx.h>
-@@ -353,7 +354,7 @@
-       struct proc_dir_entry *p;
-       int rc = -ENOMEM;
--      ipx_proc_dir = proc_mkdir("ipx", proc_net);
-+      ipx_proc_dir = proc_mkdir("ipx", init_net.proc_net);
-       if (!ipx_proc_dir)
-               goto out;
-@@ -381,7 +382,7 @@
- out_route:
-       remove_proc_entry("interface", ipx_proc_dir);
- out_interface:
--      remove_proc_entry("ipx", proc_net);
-+      remove_proc_entry("ipx", init_net.proc_net);
-       goto out;
- }
-@@ -390,7 +391,7 @@
-       remove_proc_entry("interface", ipx_proc_dir);
-       remove_proc_entry("route", ipx_proc_dir);
-       remove_proc_entry("socket", ipx_proc_dir);
--      remove_proc_entry("ipx", proc_net);
-+      remove_proc_entry("ipx", init_net.proc_net);
- }
- #else /* CONFIG_PROC_FS */
-diff -Nurb linux-2.6.22-570/net/irda/af_irda.c linux-2.6.22-590/net/irda/af_irda.c
---- linux-2.6.22-570/net/irda/af_irda.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/irda/af_irda.c        2008-01-02 13:56:38.000000000 -0500
-@@ -60,7 +60,7 @@
- #include <net/irda/af_irda.h>
--static int irda_create(struct socket *sock, int protocol);
-+static int irda_create(struct net *net, struct socket *sock, int protocol);
- static const struct proto_ops irda_stream_ops;
- static const struct proto_ops irda_seqpacket_ops;
-@@ -831,7 +831,7 @@
-       IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
--      err = irda_create(newsock, sk->sk_protocol);
-+      err = irda_create(sk->sk_net, newsock, sk->sk_protocol);
-       if (err)
-               return err;
-@@ -1057,13 +1057,16 @@
-  *    Create IrDA socket
-  *
-  */
--static int irda_create(struct socket *sock, int protocol)
-+static int irda_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct sock *sk;
-       struct irda_sock *self;
-       IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
++      err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0);
++      if (err < 0) {
++              /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
++              WARN_ON(err == -EMSGSIZE);
++              kfree_skb(skb);
++              goto errout;
++      }
++      err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
++errout:
++      if (err < 0)
++              rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
++}
++
++static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
++                              __s32 *array, int bytes)
++{
++      BUG_ON(bytes < (DEVCONF_MAX * 4));
++
++      memset(array, 0, bytes);
++      array[DEVCONF_FORWARDING] = cnf->forwarding;
++      array[DEVCONF_HOPLIMIT] = cnf->hop_limit;
++      array[DEVCONF_MTU6] = cnf->mtu6;
++      array[DEVCONF_ACCEPT_RA] = cnf->accept_ra;
++      array[DEVCONF_ACCEPT_REDIRECTS] = cnf->accept_redirects;
++      array[DEVCONF_AUTOCONF] = cnf->autoconf;
++      array[DEVCONF_DAD_TRANSMITS] = cnf->dad_transmits;
++      array[DEVCONF_RTR_SOLICITS] = cnf->rtr_solicits;
++      array[DEVCONF_RTR_SOLICIT_INTERVAL] = cnf->rtr_solicit_interval;
++      array[DEVCONF_RTR_SOLICIT_DELAY] = cnf->rtr_solicit_delay;
++      array[DEVCONF_FORCE_MLD_VERSION] = cnf->force_mld_version;
++#ifdef CONFIG_IPV6_PRIVACY
++      array[DEVCONF_USE_TEMPADDR] = cnf->use_tempaddr;
++      array[DEVCONF_TEMP_VALID_LFT] = cnf->temp_valid_lft;
++      array[DEVCONF_TEMP_PREFERED_LFT] = cnf->temp_prefered_lft;
++      array[DEVCONF_REGEN_MAX_RETRY] = cnf->regen_max_retry;
++      array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
++#endif
++      array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
++      array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr;
++      array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
++#ifdef CONFIG_IPV6_ROUTER_PREF
++      array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
++      array[DEVCONF_RTR_PROBE_INTERVAL] = cnf->rtr_probe_interval;
++#ifdef CONFIG_IPV6_ROUTE_INFO
++      array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
++#endif
++#endif
++      array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;
++      array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;
++#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
++      array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
++#endif
++}
 +
-       /* Check for valid socket type */
-       switch (sock->type) {
-       case SOCK_STREAM:     /* For TTP connections with SAR disabled */
-@@ -1075,7 +1078,7 @@
-       }
-       /* Allocate networking socket */
--      sk = sk_alloc(PF_IRDA, GFP_ATOMIC, &irda_proto, 1);
-+      sk = sk_alloc(net, PF_IRDA, GFP_ATOMIC, &irda_proto, 1);
-       if (sk == NULL)
-               return -ENOMEM;
-diff -Nurb linux-2.6.22-570/net/irda/irias_object.c linux-2.6.22-590/net/irda/irias_object.c
---- linux-2.6.22-570/net/irda/irias_object.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/irda/irias_object.c   2008-01-02 13:56:38.000000000 -0500
-@@ -36,39 +36,6 @@
-  */
- struct ias_value irias_missing = { IAS_MISSING, 0, 0, 0, {0}};
--/*
-- * Function strndup (str, max)
-- *
-- *    My own kernel version of strndup!
-- *
-- * Faster, check boundary... Jean II
-- */
--static char *strndup(char *str, size_t max)
--{
--      char *new_str;
--      int len;
--
--      /* Check string */
--      if (str == NULL)
--              return NULL;
--      /* Check length, truncate */
--      len = strlen(str);
--      if(len > max)
--              len = max;
--
--      /* Allocate new string */
--      new_str = kmalloc(len + 1, GFP_ATOMIC);
--      if (new_str == NULL) {
--              IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
--              return NULL;
--      }
--
--      /* Copy and truncate */
--      memcpy(new_str, str, len);
--      new_str[len] = '\0';
--
--      return new_str;
--}
- /*
-  * Function ias_new_object (name, id)
-@@ -90,7 +57,7 @@
-       }
-       obj->magic = IAS_OBJECT_MAGIC;
--      obj->name = strndup(name, IAS_MAX_CLASSNAME);
-+      obj->name = kstrndup(name, IAS_MAX_CLASSNAME, GFP_ATOMIC);
-       if (!obj->name) {
-               IRDA_WARNING("%s(), Unable to allocate name!\n",
-                            __FUNCTION__);
-@@ -360,7 +327,7 @@
-       }
-       attrib->magic = IAS_ATTRIB_MAGIC;
--      attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
-+      attrib->name = kstrndup(name, IAS_MAX_ATTRIBNAME, GFP_ATOMIC);
-       /* Insert value */
-       attrib->value = irias_new_integer_value(value);
-@@ -404,7 +371,7 @@
-       }
-       attrib->magic = IAS_ATTRIB_MAGIC;
--      attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
-+      attrib->name = kstrndup(name, IAS_MAX_ATTRIBNAME, GFP_ATOMIC);
-       attrib->value = irias_new_octseq_value( octets, len);
-       if (!attrib->name || !attrib->value) {
-@@ -446,7 +413,7 @@
-       }
-       attrib->magic = IAS_ATTRIB_MAGIC;
--      attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
-+      attrib->name = kstrndup(name, IAS_MAX_ATTRIBNAME, GFP_ATOMIC);
-       attrib->value = irias_new_string_value(value);
-       if (!attrib->name || !attrib->value) {
-@@ -506,7 +473,7 @@
-       value->type = IAS_STRING;
-       value->charset = CS_ASCII;
--      value->t.string = strndup(string, IAS_MAX_STRING);
-+      value->t.string = kstrndup(string, IAS_MAX_STRING, GFP_ATOMIC);
-       if (!value->t.string) {
-               IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
-               kfree(value);
-diff -Nurb linux-2.6.22-570/net/irda/irlap_frame.c linux-2.6.22-590/net/irda/irlap_frame.c
---- linux-2.6.22-570/net/irda/irlap_frame.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/irda/irlap_frame.c    2008-01-02 13:56:38.000000000 -0500
-@@ -1319,6 +1319,9 @@
-       int command;
-       __u8 control;
-+      if (dev->nd_net != &init_net)
-+              goto out;
++static inline size_t inet6_if_nlmsg_size(void)
++{
++      return NLMSG_ALIGN(sizeof(struct ifinfomsg))
++             + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
++             + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
++             + nla_total_size(4) /* IFLA_MTU */
++             + nla_total_size(4) /* IFLA_LINK */
++             + nla_total_size( /* IFLA_PROTINFO */
++                      nla_total_size(4) /* IFLA_INET6_FLAGS */
++                      + nla_total_size(sizeof(struct ifla_cacheinfo))
++                      + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
++                      + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
++                      + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
++               );
++}
++
++static inline void __snmp6_fill_stats(u64 *stats, void **mib, int items,
++                                    int bytes)
++{
++      int i;
++      int pad = bytes - sizeof(u64) * items;
++      BUG_ON(pad < 0);
++
++      /* Use put_unaligned() because stats may not be aligned for u64. */
++      put_unaligned(items, &stats[0]);
++      for (i = 1; i < items; i++)
++              put_unaligned(snmp_fold_field(mib, i), &stats[i]);
++
++      memset(&stats[items], 0, pad);
++}
++
++static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype,
++                           int bytes)
++{
++      switch(attrtype) {
++      case IFLA_INET6_STATS:
++              __snmp6_fill_stats(stats, (void **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes);
++              break;
++      case IFLA_INET6_ICMP6STATS:
++              __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes);
++              break;
++      }
++}
++
++static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
++                           u32 pid, u32 seq, int event, unsigned int flags)
++{
++      struct net_device *dev = idev->dev;
++      struct nlattr *nla;
++      struct ifinfomsg *hdr;
++      struct nlmsghdr *nlh;
++      void *protoinfo;
++      struct ifla_cacheinfo ci;
++
++      nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
++      if (nlh == NULL)
++              return -EMSGSIZE;
++
++      hdr = nlmsg_data(nlh);
++      hdr->ifi_family = AF_INET6;
++      hdr->__ifi_pad = 0;
++      hdr->ifi_type = dev->type;
++      hdr->ifi_index = dev->ifindex;
++      hdr->ifi_flags = dev_get_flags(dev);
++      hdr->ifi_change = 0;
++
++      NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
++
++      if (dev->addr_len)
++              NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
++
++      NLA_PUT_U32(skb, IFLA_MTU, dev->mtu);
++      if (dev->ifindex != dev->iflink)
++              NLA_PUT_U32(skb, IFLA_LINK, dev->iflink);
++
++      protoinfo = nla_nest_start(skb, IFLA_PROTINFO);
++      if (protoinfo == NULL)
++              goto nla_put_failure;
++
++      NLA_PUT_U32(skb, IFLA_INET6_FLAGS, idev->if_flags);
++
++      ci.max_reasm_len = IPV6_MAXPLEN;
++      ci.tstamp = (__u32)(TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) / HZ * 100
++                  + TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
++      ci.reachable_time = idev->nd_parms->reachable_time;
++      ci.retrans_time = idev->nd_parms->retrans_time;
++      NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci);
++
++      nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
++      if (nla == NULL)
++              goto nla_put_failure;
++      ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla));
++
++      /* XXX - MC not implemented */
++
++      nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
++      if (nla == NULL)
++              goto nla_put_failure;
++      snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
++
++      nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
++      if (nla == NULL)
++              goto nla_put_failure;
++      snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
++
++      nla_nest_end(skb, protoinfo);
++      return nlmsg_end(skb, nlh);
 +
-       /* FIXME: should we get our own field? */
-       self = (struct irlap_cb *) dev->atalk_ptr;
-diff -Nurb linux-2.6.22-570/net/irda/irproc.c linux-2.6.22-590/net/irda/irproc.c
---- linux-2.6.22-570/net/irda/irproc.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/irda/irproc.c 2008-01-02 13:56:38.000000000 -0500
-@@ -28,6 +28,7 @@
- #include <linux/seq_file.h>
- #include <linux/module.h>
- #include <linux/init.h>
-+#include <net/net_namespace.h>
- #include <net/irda/irda.h>
- #include <net/irda/irlap.h>
-@@ -66,7 +67,7 @@
-       int i;
-       struct proc_dir_entry *d;
--      proc_irda = proc_mkdir("irda", proc_net);
-+      proc_irda = proc_mkdir("irda", init_net.proc_net);
-       if (proc_irda == NULL)
-               return;
-       proc_irda->owner = THIS_MODULE;
-@@ -92,7 +93,7 @@
-               for (i=0; i<ARRAY_SIZE(irda_dirs); i++)
-                       remove_proc_entry(irda_dirs[i].name, proc_irda);
--              remove_proc_entry("irda", proc_net);
-+              remove_proc_entry("irda", init_net.proc_net);
-               proc_irda = NULL;
-       }
- }
-diff -Nurb linux-2.6.22-570/net/key/af_key.c linux-2.6.22-590/net/key/af_key.c
---- linux-2.6.22-570/net/key/af_key.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/key/af_key.c  2008-01-02 13:56:38.000000000 -0500
-@@ -28,6 +28,7 @@
- #include <linux/init.h>
- #include <net/xfrm.h>
- #include <linux/audit.h>
-+#include <net/net_namespace.h>
- #include <net/sock.h>
-@@ -136,11 +137,14 @@
-       .obj_size = sizeof(struct pfkey_sock),
- };
--static int pfkey_create(struct socket *sock, int protocol)
-+static int pfkey_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct sock *sk;
-       int err;
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
++nla_put_failure:
++      nlmsg_cancel(skb, nlh);
++      return -EMSGSIZE;
++}
 +
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
-       if (sock->type != SOCK_RAW)
-@@ -149,7 +153,7 @@
-               return -EPROTONOSUPPORT;
-       err = -ENOMEM;
--      sk = sk_alloc(PF_KEY, GFP_KERNEL, &key_proto, 1);
-+      sk = sk_alloc(net, PF_KEY, GFP_KERNEL, &key_proto, 1);
-       if (sk == NULL)
-               goto out;
-@@ -3781,7 +3785,7 @@
- static void __exit ipsec_pfkey_exit(void)
- {
-       xfrm_unregister_km(&pfkeyv2_mgr);
--      remove_proc_entry("net/pfkey", NULL);
-+      remove_proc_entry("pfkey", init_net.proc_net);
-       sock_unregister(PF_KEY);
-       proto_unregister(&key_proto);
- }
-@@ -3798,7 +3802,7 @@
-               goto out_unregister_key_proto;
- #ifdef CONFIG_PROC_FS
-       err = -ENOMEM;
--      if (create_proc_read_entry("net/pfkey", 0, NULL, pfkey_read_proc, NULL) == NULL)
-+      if (create_proc_read_entry("pfkey", 0, init_net.proc_net, pfkey_read_proc, NULL) == NULL)
-               goto out_sock_unregister;
- #endif
-       err = xfrm_register_km(&pfkeyv2_mgr);
-diff -Nurb linux-2.6.22-570/net/llc/af_llc.c linux-2.6.22-590/net/llc/af_llc.c
---- linux-2.6.22-570/net/llc/af_llc.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/llc/af_llc.c  2008-01-02 13:56:38.000000000 -0500
-@@ -150,14 +150,17 @@
-  *    socket type we have available.
-  *    Returns 0 upon success, negative upon failure.
-  */
--static int llc_ui_create(struct socket *sock, int protocol)
-+static int llc_ui_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct sock *sk;
-       int rc = -ESOCKTNOSUPPORT;
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
++static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
++{
++      int idx, err;
++      int s_idx = cb->args[0];
++      struct net_device *dev;
++      struct inet6_dev *idev;
++
++      read_lock(&dev_base_lock);
++      idx = 0;
++      for_each_netdev(dev) {
++              if (idx < s_idx)
++                      goto cont;
++              if ((idev = in6_dev_get(dev)) == NULL)
++                      goto cont;
++              err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid,
++                              cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
++              in6_dev_put(idev);
++              if (err <= 0)
++                      break;
++cont:
++              idx++;
++      }
++      read_unlock(&dev_base_lock);
++      cb->args[0] = idx;
 +
-       if (likely(sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM)) {
-               rc = -ENOMEM;
--              sk = llc_sk_alloc(PF_LLC, GFP_KERNEL, &llc_proto);
-+              sk = llc_sk_alloc(net, PF_LLC, GFP_KERNEL, &llc_proto);
-               if (sk) {
-                       rc = 0;
-                       llc_ui_sk_init(sock, sk);
-@@ -249,7 +252,7 @@
-       if (!sock_flag(sk, SOCK_ZAPPED))
-               goto out;
-       rc = -ENODEV;
--      llc->dev = dev_getfirstbyhwtype(addr->sllc_arphrd);
-+      llc->dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd);
-       if (!llc->dev)
-               goto out;
-       rc = -EUSERS;
-@@ -300,7 +303,7 @@
-               goto out;
-       rc = -ENODEV;
-       rtnl_lock();
--      llc->dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_mac);
-+      llc->dev = dev_getbyhwaddr(&init_net, addr->sllc_arphrd, addr->sllc_mac);
-       rtnl_unlock();
-       if (!llc->dev)
-               goto out;
-diff -Nurb linux-2.6.22-570/net/llc/llc_conn.c linux-2.6.22-590/net/llc/llc_conn.c
---- linux-2.6.22-570/net/llc/llc_conn.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/llc/llc_conn.c        2008-01-02 13:56:38.000000000 -0500
-@@ -700,7 +700,7 @@
-                                            struct llc_addr *saddr,
-                                            struct llc_addr *daddr)
- {
--      struct sock *newsk = llc_sk_alloc(sk->sk_family, GFP_ATOMIC,
-+      struct sock *newsk = llc_sk_alloc(sk->sk_net, sk->sk_family, GFP_ATOMIC,
-                                         sk->sk_prot);
-       struct llc_sock *newllc, *llc = llc_sk(sk);
-@@ -867,9 +867,9 @@
-  *    Allocates a LLC sock and initializes it. Returns the new LLC sock
-  *    or %NULL if there's no memory available for one
-  */
--struct sock *llc_sk_alloc(int family, gfp_t priority, struct proto *prot)
-+struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot)
- {
--      struct sock *sk = sk_alloc(family, priority, prot, 1);
-+      struct sock *sk = sk_alloc(net, family, priority, prot, 1);
-       if (!sk)
-               goto out;
-diff -Nurb linux-2.6.22-570/net/llc/llc_core.c linux-2.6.22-590/net/llc/llc_core.c
---- linux-2.6.22-570/net/llc/llc_core.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/llc/llc_core.c        2008-01-02 13:56:38.000000000 -0500
-@@ -19,6 +19,7 @@
- #include <linux/slab.h>
- #include <linux/string.h>
- #include <linux/init.h>
-+#include <net/net_namespace.h>
- #include <net/llc.h>
- LIST_HEAD(llc_sap_list);
-@@ -162,7 +163,8 @@
- {
-       struct net_device *dev;
--      dev = first_net_device();
-+      /* XXX sapan 
-+      dev = first_net_device(&init_net);
-       if (dev != NULL)
-               dev = next_net_device(dev);
-@@ -172,6 +174,7 @@
-               memset(llc_station_mac_sa, 0, ETH_ALEN);
-       dev_add_pack(&llc_packet_type);
-       dev_add_pack(&llc_tr_packet_type);
-+      */
-       return 0;
- }
-diff -Nurb linux-2.6.22-570/net/llc/llc_input.c linux-2.6.22-590/net/llc/llc_input.c
---- linux-2.6.22-570/net/llc/llc_input.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/llc/llc_input.c       2008-01-02 13:56:38.000000000 -0500
-@@ -12,6 +12,7 @@
-  * See the GNU General Public License for more details.
-  */
- #include <linux/netdevice.h>
-+#include <net/net_namespace.h>
- #include <net/llc.h>
- #include <net/llc_pdu.h>
- #include <net/llc_sap.h>
-@@ -145,6 +146,9 @@
-       int (*rcv)(struct sk_buff *, struct net_device *,
-                  struct packet_type *, struct net_device *);
-+      if (dev->nd_net != &init_net)
-+              goto drop;
++      return skb->len;
++}
 +
-       /*
-        * When the interface is in promisc. mode, drop all the crap that it
-        * receives, do not try to analyse it.
-diff -Nurb linux-2.6.22-570/net/llc/llc_proc.c linux-2.6.22-590/net/llc/llc_proc.c
---- linux-2.6.22-570/net/llc/llc_proc.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/llc/llc_proc.c        2008-01-02 13:56:38.000000000 -0500
-@@ -18,6 +18,7 @@
- #include <linux/errno.h>
- #include <linux/seq_file.h>
- #include <net/sock.h>
-+#include <net/net_namespace.h>
- #include <net/llc.h>
- #include <net/llc_c_ac.h>
- #include <net/llc_c_ev.h>
-@@ -231,7 +232,7 @@
-       int rc = -ENOMEM;
-       struct proc_dir_entry *p;
--      llc_proc_dir = proc_mkdir("llc", proc_net);
-+      llc_proc_dir = proc_mkdir("llc", init_net.proc_net);
-       if (!llc_proc_dir)
-               goto out;
-       llc_proc_dir->owner = THIS_MODULE;
-@@ -254,7 +255,7 @@
- out_core:
-       remove_proc_entry("socket", llc_proc_dir);
- out_socket:
--      remove_proc_entry("llc", proc_net);
-+      remove_proc_entry("llc", init_net.proc_net);
-       goto out;
- }
-@@ -262,5 +263,5 @@
- {
-       remove_proc_entry("socket", llc_proc_dir);
-       remove_proc_entry("core", llc_proc_dir);
--      remove_proc_entry("llc", proc_net);
-+      remove_proc_entry("llc", init_net.proc_net);
- }
-diff -Nurb linux-2.6.22-570/net/mac80211/ieee80211_ioctl.c linux-2.6.22-590/net/mac80211/ieee80211_ioctl.c
---- linux-2.6.22-570/net/mac80211/ieee80211_ioctl.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/mac80211/ieee80211_ioctl.c    2008-01-02 13:56:38.000000000 -0500
-@@ -838,6 +838,29 @@
- }
-+static int ieee80211_ioctl_giwrate(struct net_device *dev,
-+                                struct iw_request_info *info,
-+                                struct iw_param *rate, char *extra)
++void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
 +{
-+      struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+      struct sta_info *sta;
-+      struct ieee80211_sub_if_data *sdata;
++      struct sk_buff *skb;
++      int err = -ENOBUFS;
 +
-+      sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+      if (sdata->type == IEEE80211_IF_TYPE_STA)
-+              sta = sta_info_get(local, sdata->u.sta.bssid);
-+      else
-+              return -EOPNOTSUPP;
-+      if (!sta)
-+              return -ENODEV;
-+      if (sta->txrate < local->oper_hw_mode->num_rates)
-+              rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;
-+      else
-+              rate->value = 0;
-+      sta_info_put(sta);
-+      return 0;
++      skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC);
++      if (skb == NULL)
++              goto errout;
++
++      err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
++      if (err < 0) {
++              /* -EMSGSIZE implies BUG in inet6_if_nlmsg_size() */
++              WARN_ON(err == -EMSGSIZE);
++              kfree_skb(skb);
++              goto errout;
++      }
++      err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
++errout:
++      if (err < 0)
++              rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
 +}
 +
- static int ieee80211_ioctl_siwrts(struct net_device *dev,
-                                 struct iw_request_info *info,
-                                 struct iw_param *rts, char *extra)
-@@ -1779,7 +1802,7 @@
-       (iw_handler) NULL,                              /* -- hole -- */
-       (iw_handler) NULL,                              /* -- hole -- */
-       (iw_handler) NULL,                              /* SIOCSIWRATE */
--      (iw_handler) NULL,                              /* SIOCGIWRATE */
-+      (iw_handler) ieee80211_ioctl_giwrate,           /* SIOCGIWRATE */
-       (iw_handler) ieee80211_ioctl_siwrts,            /* SIOCSIWRTS */
-       (iw_handler) ieee80211_ioctl_giwrts,            /* SIOCGIWRTS */
-       (iw_handler) ieee80211_ioctl_siwfrag,           /* SIOCSIWFRAG */
-diff -Nurb linux-2.6.22-570/net/netfilter/core.c linux-2.6.22-590/net/netfilter/core.c
---- linux-2.6.22-570/net/netfilter/core.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netfilter/core.c      2008-01-02 13:56:38.000000000 -0500
-@@ -20,6 +20,7 @@
- #include <linux/proc_fs.h>
- #include <linux/mutex.h>
- #include <net/sock.h>
-+#include <net/net_namespace.h>
- #include "nf_internals.h"
-@@ -203,7 +204,9 @@
-               return 0;
-       /* Not exclusive use of packet?  Must copy. */
--      if (skb_shared(*pskb) || skb_cloned(*pskb))
-+      if (skb_cloned(*pskb) && !skb_clone_writable(*pskb, writable_len))
-+              goto copy_skb;
-+      if (skb_shared(*pskb))
-               goto copy_skb;
-       return pskb_may_pull(*pskb, writable_len);
-@@ -278,8 +281,28 @@
- #endif /* CONFIG_NF_CONNTRACK */
- #ifdef CONFIG_PROC_FS
--struct proc_dir_entry *proc_net_netfilter;
--EXPORT_SYMBOL(proc_net_netfilter);
-+static int netfilter_proc_init(struct net * net)
++static inline size_t inet6_prefix_nlmsg_size(void)
 +{
-+      int error = -ENOMEM;
-+      net->proc_net_netfilter = proc_mkdir("netfilter", net->proc_net);
++      return NLMSG_ALIGN(sizeof(struct prefixmsg))
++             + nla_total_size(sizeof(struct in6_addr))
++             + nla_total_size(sizeof(struct prefix_cacheinfo));
++}
 +
-+      if (net->proc_net_netfilter) {
-+              net->proc_net_netfilter->data = net;
-+              error = 0;
++static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
++                           struct prefix_info *pinfo, u32 pid, u32 seq,
++                           int event, unsigned int flags)
++{
++      struct prefixmsg *pmsg;
++      struct nlmsghdr *nlh;
++      struct prefix_cacheinfo ci;
++
++      nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags);
++      if (nlh == NULL)
++              return -EMSGSIZE;
++
++      pmsg = nlmsg_data(nlh);
++      pmsg->prefix_family = AF_INET6;
++      pmsg->prefix_pad1 = 0;
++      pmsg->prefix_pad2 = 0;
++      pmsg->prefix_ifindex = idev->dev->ifindex;
++      pmsg->prefix_len = pinfo->prefix_len;
++      pmsg->prefix_type = pinfo->type;
++      pmsg->prefix_pad3 = 0;
++      pmsg->prefix_flags = 0;
++      if (pinfo->onlink)
++              pmsg->prefix_flags |= IF_PREFIX_ONLINK;
++      if (pinfo->autoconf)
++              pmsg->prefix_flags |= IF_PREFIX_AUTOCONF;
++
++      NLA_PUT(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix);
++
++      ci.preferred_time = ntohl(pinfo->prefered);
++      ci.valid_time = ntohl(pinfo->valid);
++      NLA_PUT(skb, PREFIX_CACHEINFO, sizeof(ci), &ci);
++
++      return nlmsg_end(skb, nlh);
++
++nla_put_failure:
++      nlmsg_cancel(skb, nlh);
++      return -EMSGSIZE;
++}
++
++static void inet6_prefix_notify(int event, struct inet6_dev *idev,
++                       struct prefix_info *pinfo)
++{
++      struct sk_buff *skb;
++      int err = -ENOBUFS;
++
++      skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC);
++      if (skb == NULL)
++              goto errout;
++
++      err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
++      if (err < 0) {
++              /* -EMSGSIZE implies BUG in inet6_prefix_nlmsg_size() */
++              WARN_ON(err == -EMSGSIZE);
++              kfree_skb(skb);
++              goto errout;
 +      }
-+      return error;
++      err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
++errout:
++      if (err < 0)
++              rtnl_set_sk_err(RTNLGRP_IPV6_PREFIX, err);
++}
++
++static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
++{
++      inet6_ifa_notify(event ? : RTM_NEWADDR, ifp);
++
++      switch (event) {
++      case RTM_NEWADDR:
++              /*
++               * If the address was optimistic
++               * we inserted the route at the start of
++               * our DAD process, so we don't need
++               * to do it again
++               */
++              if (!(ifp->rt->rt6i_node))
++                      ip6_ins_rt(ifp->rt);
++              if (ifp->idev->cnf.forwarding)
++                      addrconf_join_anycast(ifp);
++              break;
++      case RTM_DELADDR:
++              if (ifp->idev->cnf.forwarding)
++                      addrconf_leave_anycast(ifp);
++              addrconf_leave_solict(ifp->idev, &ifp->addr);
++              dst_hold(&ifp->rt->u.dst);
++              if (ip6_del_rt(ifp->rt))
++                      dst_free(&ifp->rt->u.dst);
++              break;
++      }
++}
++
++static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
++{
++      rcu_read_lock_bh();
++      if (likely(ifp->idev->dead == 0))
++              __ipv6_ifa_notify(event, ifp);
++      rcu_read_unlock_bh();
++}
++
++#ifdef CONFIG_SYSCTL
++
++static
++int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
++                         void __user *buffer, size_t *lenp, loff_t *ppos)
++{
++      int *valp = ctl->data;
++      int val = *valp;
++      int ret;
++
++      ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
++
++      if (write && valp != &ipv6_devconf_dflt.forwarding) {
++              if (valp != &ipv6_devconf.forwarding) {
++                      if ((!*valp) ^ (!val)) {
++                              struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1;
++                              if (idev == NULL)
++                                      return ret;
++                              dev_forward_change(idev);
++                      }
++              } else {
++                      ipv6_devconf_dflt.forwarding = ipv6_devconf.forwarding;
++                      addrconf_forward_change();
++              }
++              if (*valp)
++                      rt6_purge_dflt_routers();
++      }
++
++      return ret;
 +}
 +
-+static void netfilter_proc_exit(struct net *net)
++static int addrconf_sysctl_forward_strategy(ctl_table *table,
++                                          int __user *name, int nlen,
++                                          void __user *oldval,
++                                          size_t __user *oldlenp,
++                                          void __user *newval, size_t newlen)
 +{
-+      remove_proc_entry("netfilter", net->proc_net);
++      int *valp = table->data;
++      int new;
++
++      if (!newval || !newlen)
++              return 0;
++      if (newlen != sizeof(int))
++              return -EINVAL;
++      if (get_user(new, (int __user *)newval))
++              return -EFAULT;
++      if (new == *valp)
++              return 0;
++      if (oldval && oldlenp) {
++              size_t len;
++              if (get_user(len, oldlenp))
++                      return -EFAULT;
++              if (len) {
++                      if (len > table->maxlen)
++                              len = table->maxlen;
++                      if (copy_to_user(oldval, valp, len))
++                              return -EFAULT;
++                      if (put_user(len, oldlenp))
++                              return -EFAULT;
++              }
++      }
++
++      if (valp != &ipv6_devconf_dflt.forwarding) {
++              if (valp != &ipv6_devconf.forwarding) {
++                      struct inet6_dev *idev = (struct inet6_dev *)table->extra1;
++                      int changed;
++                      if (unlikely(idev == NULL))
++                              return -ENODEV;
++                      changed = (!*valp) ^ (!new);
++                      *valp = new;
++                      if (changed)
++                              dev_forward_change(idev);
++              } else {
++                      *valp = new;
++                      addrconf_forward_change();
++              }
++
++              if (*valp)
++                      rt6_purge_dflt_routers();
++      } else
++              *valp = new;
++
++      return 1;
 +}
 +
-+static struct pernet_operations netfilter_proc_ops = {
-+      .init = netfilter_proc_init,
-+      .exit = netfilter_proc_exit,
++static struct addrconf_sysctl_table
++{
++      struct ctl_table_header *sysctl_header;
++      ctl_table addrconf_vars[__NET_IPV6_MAX];
++      ctl_table addrconf_dev[2];
++      ctl_table addrconf_conf_dir[2];
++      ctl_table addrconf_proto_dir[2];
++      ctl_table addrconf_root_dir[2];
++} addrconf_sysctl __read_mostly = {
++      .sysctl_header = NULL,
++      .addrconf_vars = {
++              {
++                      .ctl_name       =       NET_IPV6_FORWARDING,
++                      .procname       =       "forwarding",
++                      .data           =       &ipv6_devconf.forwarding,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &addrconf_sysctl_forward,
++                      .strategy       =       &addrconf_sysctl_forward_strategy,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_HOP_LIMIT,
++                      .procname       =       "hop_limit",
++                      .data           =       &ipv6_devconf.hop_limit,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_MTU,
++                      .procname       =       "mtu",
++                      .data           =       &ipv6_devconf.mtu6,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_ACCEPT_RA,
++                      .procname       =       "accept_ra",
++                      .data           =       &ipv6_devconf.accept_ra,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_ACCEPT_REDIRECTS,
++                      .procname       =       "accept_redirects",
++                      .data           =       &ipv6_devconf.accept_redirects,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_AUTOCONF,
++                      .procname       =       "autoconf",
++                      .data           =       &ipv6_devconf.autoconf,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_DAD_TRANSMITS,
++                      .procname       =       "dad_transmits",
++                      .data           =       &ipv6_devconf.dad_transmits,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_RTR_SOLICITS,
++                      .procname       =       "router_solicitations",
++                      .data           =       &ipv6_devconf.rtr_solicits,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_RTR_SOLICIT_INTERVAL,
++                      .procname       =       "router_solicitation_interval",
++                      .data           =       &ipv6_devconf.rtr_solicit_interval,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec_jiffies,
++                      .strategy       =       &sysctl_jiffies,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_RTR_SOLICIT_DELAY,
++                      .procname       =       "router_solicitation_delay",
++                      .data           =       &ipv6_devconf.rtr_solicit_delay,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec_jiffies,
++                      .strategy       =       &sysctl_jiffies,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_FORCE_MLD_VERSION,
++                      .procname       =       "force_mld_version",
++                      .data           =       &ipv6_devconf.force_mld_version,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++#ifdef CONFIG_IPV6_PRIVACY
++              {
++                      .ctl_name       =       NET_IPV6_USE_TEMPADDR,
++                      .procname       =       "use_tempaddr",
++                      .data           =       &ipv6_devconf.use_tempaddr,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_TEMP_VALID_LFT,
++                      .procname       =       "temp_valid_lft",
++                      .data           =       &ipv6_devconf.temp_valid_lft,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_TEMP_PREFERED_LFT,
++                      .procname       =       "temp_prefered_lft",
++                      .data           =       &ipv6_devconf.temp_prefered_lft,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_REGEN_MAX_RETRY,
++                      .procname       =       "regen_max_retry",
++                      .data           =       &ipv6_devconf.regen_max_retry,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_MAX_DESYNC_FACTOR,
++                      .procname       =       "max_desync_factor",
++                      .data           =       &ipv6_devconf.max_desync_factor,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++#endif
++              {
++                      .ctl_name       =       NET_IPV6_MAX_ADDRESSES,
++                      .procname       =       "max_addresses",
++                      .data           =       &ipv6_devconf.max_addresses,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_ACCEPT_RA_DEFRTR,
++                      .procname       =       "accept_ra_defrtr",
++                      .data           =       &ipv6_devconf.accept_ra_defrtr,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_ACCEPT_RA_PINFO,
++                      .procname       =       "accept_ra_pinfo",
++                      .data           =       &ipv6_devconf.accept_ra_pinfo,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++#ifdef CONFIG_IPV6_ROUTER_PREF
++              {
++                      .ctl_name       =       NET_IPV6_ACCEPT_RA_RTR_PREF,
++                      .procname       =       "accept_ra_rtr_pref",
++                      .data           =       &ipv6_devconf.accept_ra_rtr_pref,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_RTR_PROBE_INTERVAL,
++                      .procname       =       "router_probe_interval",
++                      .data           =       &ipv6_devconf.rtr_probe_interval,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec_jiffies,
++                      .strategy       =       &sysctl_jiffies,
++              },
++#ifdef CONFIG_IPV6_ROUTE_INFO
++              {
++                      .ctl_name       =       NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN,
++                      .procname       =       "accept_ra_rt_info_max_plen",
++                      .data           =       &ipv6_devconf.accept_ra_rt_info_max_plen,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++#endif
++#endif
++              {
++                      .ctl_name       =       NET_IPV6_PROXY_NDP,
++                      .procname       =       "proxy_ndp",
++                      .data           =       &ipv6_devconf.proxy_ndp,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++              {
++                      .ctl_name       =       NET_IPV6_ACCEPT_SOURCE_ROUTE,
++                      .procname       =       "accept_source_route",
++                      .data           =       &ipv6_devconf.accept_source_route,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++              },
++#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
++              {
++                      .ctl_name       =       CTL_UNNUMBERED,
++                      .procname       =       "optimistic_dad",
++                      .data           =       &ipv6_devconf.optimistic_dad,
++                      .maxlen         =       sizeof(int),
++                      .mode           =       0644,
++                      .proc_handler   =       &proc_dointvec,
++
++              },
++#endif
++              {
++                      .ctl_name       =       0,      /* sentinel */
++              }
++      },
++      .addrconf_dev = {
++              {
++                      .ctl_name       =       NET_PROTO_CONF_ALL,
++                      .procname       =       "all",
++                      .mode           =       0555,
++                      .child          =       addrconf_sysctl.addrconf_vars,
++              },
++              {
++                      .ctl_name       =       0,      /* sentinel */
++              }
++      },
++      .addrconf_conf_dir = {
++              {
++                      .ctl_name       =       NET_IPV6_CONF,
++                      .procname       =       "conf",
++                      .mode           =       0555,
++                      .child          =       addrconf_sysctl.addrconf_dev,
++              },
++              {
++                      .ctl_name       =       0,      /* sentinel */
++              }
++      },
++      .addrconf_proto_dir = {
++              {
++                      .ctl_name       =       NET_IPV6,
++                      .procname       =       "ipv6",
++                      .mode           =       0555,
++                      .child          =       addrconf_sysctl.addrconf_conf_dir,
++              },
++              {
++                      .ctl_name       =       0,      /* sentinel */
++              }
++      },
++      .addrconf_root_dir = {
++              {
++                      .ctl_name       =       CTL_NET,
++                      .procname       =       "net",
++                      .mode           =       0555,
++                      .child          =       addrconf_sysctl.addrconf_proto_dir,
++              },
++              {
++                      .ctl_name       =       0,      /* sentinel */
++              }
++      },
 +};
 +
- #endif
- void __init netfilter_init(void)
-@@ -291,8 +314,7 @@
-       }
- #ifdef CONFIG_PROC_FS
--      proc_net_netfilter = proc_mkdir("netfilter", proc_net);
--      if (!proc_net_netfilter)
-+      if (register_pernet_subsys(&netfilter_proc_ops) < 0)
-               panic("cannot create netfilter proc entry");
- #endif
-diff -Nurb linux-2.6.22-570/net/netfilter/nf_conntrack_h323_main.c linux-2.6.22-590/net/netfilter/nf_conntrack_h323_main.c
---- linux-2.6.22-570/net/netfilter/nf_conntrack_h323_main.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netfilter/nf_conntrack_h323_main.c    2008-01-02 13:56:38.000000000 -0500
-@@ -724,6 +724,8 @@
-       memset(&fl1, 0, sizeof(fl1));
-       memset(&fl2, 0, sizeof(fl2));
-+      fl1.fl_net = &init_net;
-+      fl2.fl_net = &init_net;
-       switch (family) {
-       case AF_INET: {
-diff -Nurb linux-2.6.22-570/net/netfilter/nf_conntrack_standalone.c linux-2.6.22-590/net/netfilter/nf_conntrack_standalone.c
---- linux-2.6.22-570/net/netfilter/nf_conntrack_standalone.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netfilter/nf_conntrack_standalone.c   2008-01-02 13:56:38.000000000 -0500
-@@ -14,6 +14,7 @@
- #include <linux/seq_file.h>
- #include <linux/percpu.h>
- #include <linux/netdevice.h>
-+#include <net/net_namespace.h>
- #ifdef CONFIG_SYSCTL
- #include <linux/sysctl.h>
- #endif
-@@ -419,14 +420,14 @@
-               return ret;
- #ifdef CONFIG_PROC_FS
--      proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
-+      proc = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops);
-       if (!proc) goto cleanup_init;
--      proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
-+      proc_exp = proc_net_fops_create(&init_net, "nf_conntrack_expect", 0440,
-                                       &exp_file_ops);
-       if (!proc_exp) goto cleanup_proc;
--      proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
-+      proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, init_net.proc_net_stat);
-       if (!proc_stat)
-               goto cleanup_proc_exp;
-@@ -447,11 +448,11 @@
-  cleanup_proc_stat:
- #endif
- #ifdef CONFIG_PROC_FS
--      remove_proc_entry("nf_conntrack", proc_net_stat);
-+      remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
-  cleanup_proc_exp:
--      proc_net_remove("nf_conntrack_expect");
-+      proc_net_remove(&init_net, "nf_conntrack_expect");
-  cleanup_proc:
--      proc_net_remove("nf_conntrack");
-+      proc_net_remove(&init_net, "nf_conntrack");
-  cleanup_init:
- #endif /* CNFIG_PROC_FS */
-       nf_conntrack_cleanup();
-@@ -464,9 +465,9 @@
-       unregister_sysctl_table(nf_ct_sysctl_header);
- #endif
- #ifdef CONFIG_PROC_FS
--      remove_proc_entry("nf_conntrack", proc_net_stat);
--      proc_net_remove("nf_conntrack_expect");
--      proc_net_remove("nf_conntrack");
-+      remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
-+      proc_net_remove(&init_net, "nf_conntrack_expect");
-+      proc_net_remove(&init_net, "nf_conntrack");
- #endif /* CNFIG_PROC_FS */
-       nf_conntrack_cleanup();
- }
-diff -Nurb linux-2.6.22-570/net/netfilter/nf_log.c linux-2.6.22-590/net/netfilter/nf_log.c
---- linux-2.6.22-570/net/netfilter/nf_log.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netfilter/nf_log.c    2008-01-02 13:56:38.000000000 -0500
-@@ -168,7 +168,8 @@
- #ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *pde;
--      pde = create_proc_entry("nf_log", S_IRUGO, proc_net_netfilter);
-+      pde = create_proc_entry("nf_log", S_IRUGO,
-+              init_net.proc_net_netfilter);
-       if (!pde)
-               return -1;
-diff -Nurb linux-2.6.22-570/net/netfilter/nf_queue.c linux-2.6.22-590/net/netfilter/nf_queue.c
---- linux-2.6.22-570/net/netfilter/nf_queue.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netfilter/nf_queue.c  2008-01-02 13:56:38.000000000 -0500
-@@ -346,7 +346,7 @@
- #ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *pde;
--      pde = create_proc_entry("nf_queue", S_IRUGO, proc_net_netfilter);
-+      pde = create_proc_entry("nf_queue", S_IRUGO, init_net.proc_net_netfilter);
-       if (!pde)
-               return -1;
-       pde->proc_fops = &nfqueue_file_ops;
-diff -Nurb linux-2.6.22-570/net/netfilter/nfnetlink.c linux-2.6.22-590/net/netfilter/nfnetlink.c
---- linux-2.6.22-570/net/netfilter/nfnetlink.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netfilter/nfnetlink.c 2008-01-02 13:56:38.000000000 -0500
-@@ -264,7 +264,7 @@
- {
-       printk("Netfilter messages via NETLINK v%s.\n", nfversion);
--      nfnl = netlink_kernel_create(NETLINK_NETFILTER, NFNLGRP_MAX,
-+      nfnl = netlink_kernel_create(&init_net, NETLINK_NETFILTER, NFNLGRP_MAX,
-                                    nfnetlink_rcv, NULL, THIS_MODULE);
-       if (!nfnl) {
-               printk(KERN_ERR "cannot initialize nfnetlink!\n");
-diff -Nurb linux-2.6.22-570/net/netfilter/nfnetlink_log.c linux-2.6.22-590/net/netfilter/nfnetlink_log.c
---- linux-2.6.22-570/net/netfilter/nfnetlink_log.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netfilter/nfnetlink_log.c     2008-01-02 13:56:38.000000000 -0500
-@@ -705,7 +705,8 @@
-                       hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
-                               UDEBUG("node = %p\n", inst);
--                              if (n->pid == inst->peer_pid)
-+                              if ((n->net == &init_net) && 
-+                                  (n->pid == inst->peer_pid))
-                                       __instance_destroy(inst);
-                       }
-               }
-@@ -1023,7 +1024,7 @@
- #ifdef CONFIG_PROC_FS
-       proc_nful = create_proc_entry("nfnetlink_log", 0440,
--                                    proc_net_netfilter);
-+                                    init_net.proc_net_netfilter);
-       if (!proc_nful)
-               goto cleanup_subsys;
-       proc_nful->proc_fops = &nful_file_ops;
-@@ -1043,7 +1044,7 @@
- {
-       nf_log_unregister(&nfulnl_logger);
- #ifdef CONFIG_PROC_FS
--      remove_proc_entry("nfnetlink_log", proc_net_netfilter);
-+      remove_proc_entry("nfnetlink_log", init_net.proc_net_netfilter);
- #endif
-       nfnetlink_subsys_unregister(&nfulnl_subsys);
-       netlink_unregister_notifier(&nfulnl_rtnl_notifier);
-diff -Nurb linux-2.6.22-570/net/netfilter/nfnetlink_queue.c linux-2.6.22-590/net/netfilter/nfnetlink_queue.c
---- linux-2.6.22-570/net/netfilter/nfnetlink_queue.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netfilter/nfnetlink_queue.c   2008-01-02 13:56:38.000000000 -0500
-@@ -734,6 +734,9 @@
- {
-       struct net_device *dev = ptr;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
++static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf *p)
++{
++      int i;
++      struct net_device *dev = idev ? idev->dev : NULL;
++      struct addrconf_sysctl_table *t;
++      char *dev_name = NULL;
 +
-       /* Drop any packets associated with the downed device */
-       if (event == NETDEV_DOWN)
-               nfqnl_dev_drop(dev->ifindex);
-@@ -762,7 +765,8 @@
-                       struct hlist_head *head = &instance_table[i];
-                       hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
--                              if (n->pid == inst->peer_pid)
-+                              if ((n->net == &init_net) && 
-+                                  (n->pid == inst->peer_pid))
-                                       __instance_destroy(inst);
-                       }
-               }
-@@ -1106,7 +1110,7 @@
- #ifdef CONFIG_PROC_FS
-       proc_nfqueue = create_proc_entry("nfnetlink_queue", 0440,
--                                       proc_net_netfilter);
-+                                       init_net.proc_net_netfilter);
-       if (!proc_nfqueue)
-               goto cleanup_subsys;
-       proc_nfqueue->proc_fops = &nfqnl_file_ops;
-@@ -1129,7 +1133,7 @@
-       nf_unregister_queue_handlers(&nfqh);
-       unregister_netdevice_notifier(&nfqnl_dev_notifier);
- #ifdef CONFIG_PROC_FS
--      remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
-+      remove_proc_entry("nfnetlink_queue", init_net.proc_net_netfilter);
- #endif
-       nfnetlink_subsys_unregister(&nfqnl_subsys);
-       netlink_unregister_notifier(&nfqnl_rtnl_notifier);
-diff -Nurb linux-2.6.22-570/net/netfilter/x_tables.c linux-2.6.22-590/net/netfilter/x_tables.c
---- linux-2.6.22-570/net/netfilter/x_tables.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netfilter/x_tables.c  2008-01-02 13:56:38.000000000 -0500
-@@ -22,6 +22,7 @@
- #include <linux/vmalloc.h>
- #include <linux/mutex.h>
- #include <linux/mm.h>
-+#include <net/net_namespace.h>
- #include <linux/netfilter/x_tables.h>
- #include <linux/netfilter_arp.h>
-@@ -37,11 +38,16 @@
-       struct mutex mutex;
-       struct list_head match;
-       struct list_head target;
--      struct list_head tables;
-       struct mutex compat_mutex;
- };
--static struct xt_af *xt;
++      t = kmemdup(&addrconf_sysctl, sizeof(*t), GFP_KERNEL);
++      if (t == NULL)
++              return;
++      for (i=0; t->addrconf_vars[i].data; i++) {
++              t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf;
++              t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */
++      }
++      if (dev) {
++              dev_name = dev->name;
++              t->addrconf_dev[0].ctl_name = dev->ifindex;
++      } else {
++              dev_name = "default";
++              t->addrconf_dev[0].ctl_name = NET_PROTO_CONF_DEFAULT;
++      }
++
++      /*
++       * Make a copy of dev_name, because '.procname' is regarded as const
++       * by sysctl and we wouldn't want anyone to change it under our feet
++       * (see SIOCSIFNAME).
++       */
++      dev_name = kstrdup(dev_name, GFP_KERNEL);
++      if (!dev_name)
++          goto free;
++
++      t->addrconf_dev[0].procname = dev_name;
++
++      t->addrconf_dev[0].child = t->addrconf_vars;
++      t->addrconf_conf_dir[0].child = t->addrconf_dev;
++      t->addrconf_proto_dir[0].child = t->addrconf_conf_dir;
++      t->addrconf_root_dir[0].child = t->addrconf_proto_dir;
++
++      t->sysctl_header = register_sysctl_table(t->addrconf_root_dir);
++      if (t->sysctl_header == NULL)
++              goto free_procname;
++      else
++              p->sysctl = t;
++      return;
++
++      /* error path */
++ free_procname:
++      kfree(dev_name);
++ free:
++      kfree(t);
++
++      return;
++}
++
++static void addrconf_sysctl_unregister(struct ipv6_devconf *p)
++{
++      if (p->sysctl) {
++              struct addrconf_sysctl_table *t = p->sysctl;
++              p->sysctl = NULL;
++              unregister_sysctl_table(t->sysctl_header);
++              kfree(t->addrconf_dev[0].procname);
++              kfree(t);
++      }
++}
++
++
++#endif
++
++/*
++ *      Device notifier
++ */
++
++int register_inet6addr_notifier(struct notifier_block *nb)
++{
++      return atomic_notifier_chain_register(&inet6addr_chain, nb);
++}
++
++EXPORT_SYMBOL(register_inet6addr_notifier);
++
++int unregister_inet6addr_notifier(struct notifier_block *nb)
++{
++      return atomic_notifier_chain_unregister(&inet6addr_chain,nb);
++}
 +
-+struct xt_af_pernet {
-+      struct list_head tables;
-+};
++EXPORT_SYMBOL(unregister_inet6addr_notifier);
 +
-+static struct xt_af * xt;
++/*
++ *    Init / cleanup code
++ */
 +
- #ifdef DEBUG_IP_FIREWALL_USER
- #define duprintf(format, args...) printk(format , ## args)
-@@ -286,9 +292,9 @@
-               return 1;
-       }
-       if (target == 1)
--              have_rev = target_revfn(af, name, revision, &best);
-+              have_rev = target_revfn( af, name, revision, &best);
-       else
--              have_rev = match_revfn(af, name, revision, &best);
-+              have_rev = match_revfn( af, name, revision, &best);
-       mutex_unlock(&xt[af].mutex);
-       /* Nothing at all?  Return 0 to try loading module. */
-@@ -533,14 +539,14 @@
- EXPORT_SYMBOL(xt_free_table_info);
- /* Find table by name, grabs mutex & ref.  Returns ERR_PTR() on error. */
--struct xt_table *xt_find_table_lock(int af, const char *name)
-+struct xt_table *xt_find_table_lock(struct net *net, int af, const char *name)
- {
-       struct xt_table *t;
-       if (mutex_lock_interruptible(&xt[af].mutex) != 0)
-               return ERR_PTR(-EINTR);
--      list_for_each_entry(t, &xt[af].tables, list)
-+      list_for_each_entry(t, &net->xtn[af].tables, list)
-               if (strcmp(t->name, name) == 0 && try_module_get(t->me))
-                       return t;
-       mutex_unlock(&xt[af].mutex);
-@@ -596,7 +602,7 @@
- }
- EXPORT_SYMBOL_GPL(xt_replace_table);
--int xt_register_table(struct xt_table *table,
-+int xt_register_table(struct net *net, struct xt_table *table,
-                     struct xt_table_info *bootstrap,
-                     struct xt_table_info *newinfo)
- {
-@@ -609,7 +615,7 @@
-               return ret;
-       /* Don't autoload: we'd eat our tail... */
--      list_for_each_entry(t, &xt[table->af].tables, list) {
-+      list_for_each_entry(t, &net->xtn[table->af].tables, list) {
-               if (strcmp(t->name, table->name) == 0) {
-                       ret = -EEXIST;
-                       goto unlock;
-@@ -628,7 +634,7 @@
-       /* save number of initial entries */
-       private->initial_entries = private->number;
--      list_add(&table->list, &xt[table->af].tables);
-+      list_add(&table->list, &net->xtn[table->af].tables);
-       ret = 0;
-  unlock:
-@@ -666,7 +672,7 @@
-       return pos ? NULL : head;
- }
--static struct list_head *type2list(u_int16_t af, u_int16_t type)
-+static struct list_head *type2list(struct net *net, u_int16_t af, u_int16_t type)
- {
-       struct list_head *list;
-@@ -678,7 +684,7 @@
-               list = &xt[af].match;
-               break;
-       case TABLE:
--              list = &xt[af].tables;
-+              list = &net->xtn[af].tables;
-               break;
-       default:
-               list = NULL;
-@@ -691,6 +697,7 @@
- static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos)
- {
-       struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private;
-+      struct net *net = PDE_NET(pde);
-       u_int16_t af = (unsigned long)pde->data & 0xffff;
-       u_int16_t type = (unsigned long)pde->data >> 16;
-       struct list_head *list;
-@@ -698,7 +705,7 @@
-       if (af >= NPROTO)
-               return NULL;
--      list = type2list(af, type);
-+      list = type2list(net, af, type);
-       if (!list)
-               return NULL;
-@@ -711,6 +718,7 @@
- static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
- {
-       struct proc_dir_entry *pde = seq->private;
-+      struct net *net = PDE_NET(pde);
-       u_int16_t af = (unsigned long)pde->data & 0xffff;
-       u_int16_t type = (unsigned long)pde->data >> 16;
-       struct list_head *list;
-@@ -718,7 +726,7 @@
-       if (af >= NPROTO)
-               return NULL;
--      list = type2list(af, type);
-+      list = type2list(net, af, type);
-       if (!list)
-               return NULL;
-@@ -759,6 +767,7 @@
-       if (!ret) {
-               struct seq_file *seq = file->private_data;
-               struct proc_dir_entry *pde = PDE(inode);
-+              get_net(PROC_NET(inode));
-               seq->private = pde;
-       }
-@@ -766,12 +775,18 @@
-       return ret;
- }
-+static int xt_tgt_release(struct inode *inode, struct file *file)
++int __init addrconf_init(void)
 +{
-+      put_net(PROC_NET(inode));
-+      return seq_release(inode, file);
++      int err = 0;
++
++      /* The addrconf netdev notifier requires that loopback_dev
++       * has it's ipv6 private information allocated and setup
++       * before it can bring up and give link-local addresses
++       * to other devices which are up.
++       *
++       * Unfortunately, loopback_dev is not necessarily the first
++       * entry in the global dev_base list of net devices.  In fact,
++       * it is likely to be the very last entry on that list.
++       * So this causes the notifier registry below to try and
++       * give link-local addresses to all devices besides loopback_dev
++       * first, then loopback_dev, which cases all the non-loopback_dev
++       * devices to fail to get a link-local address.
++       *
++       * So, as a temporary fix, allocate the ipv6 structure for
++       * loopback_dev first by hand.
++       * Longer term, all of the dependencies ipv6 has upon the loopback
++       * device and it being up should be removed.
++       */
++      rtnl_lock();
++      if (!ipv6_add_dev(&loopback_dev))
++              err = -ENOMEM;
++      rtnl_unlock();
++      if (err)
++              return err;
++
++      ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++      ip6_prohibit_entry.rt6i_idev = in6_dev_get(&loopback_dev);
++      ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&loopback_dev);
++#endif
++
++      register_netdevice_notifier(&ipv6_dev_notf);
++
++      addrconf_verify(0);
++
++      err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo);
++      if (err < 0)
++              goto errout;
++
++      /* Only the first call to __rtnl_register can fail */
++      __rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL);
++      __rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL);
++      __rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr, inet6_dump_ifaddr);
++      __rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL, inet6_dump_ifmcaddr);
++      __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, inet6_dump_ifacaddr);
++
++#ifdef CONFIG_SYSCTL
++      addrconf_sysctl.sysctl_header =
++              register_sysctl_table(addrconf_sysctl.addrconf_root_dir);
++      addrconf_sysctl_register(NULL, &ipv6_devconf_dflt);
++#endif
++
++      return 0;
++errout:
++      unregister_netdevice_notifier(&ipv6_dev_notf);
++
++      return err;
 +}
 +
- static const struct file_operations xt_file_ops = {
-       .owner   = THIS_MODULE,
-       .open    = xt_tgt_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
--      .release = seq_release,
-+      .release = xt_tgt_release,
- };
- #define FORMAT_TABLES "_tables_names"
-@@ -794,7 +809,7 @@
- #ifdef CONFIG_PROC_FS
-       strlcpy(buf, xt_prefix[af], sizeof(buf));
-       strlcat(buf, FORMAT_TABLES, sizeof(buf));
--      proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
-+      proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
-       if (!proc)
-               goto out;
-       proc->data = (void *) ((unsigned long) af | (TABLE << 16));
-@@ -802,14 +817,14 @@
-       strlcpy(buf, xt_prefix[af], sizeof(buf));
-       strlcat(buf, FORMAT_MATCHES, sizeof(buf));
--      proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
-+      proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
-       if (!proc)
-               goto out_remove_tables;
-       proc->data = (void *) ((unsigned long) af | (MATCH << 16));
-       strlcpy(buf, xt_prefix[af], sizeof(buf));
-       strlcat(buf, FORMAT_TARGETS, sizeof(buf));
--      proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
-+      proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
-       if (!proc)
-               goto out_remove_matches;
-       proc->data = (void *) ((unsigned long) af | (TARGET << 16));
-@@ -821,12 +836,12 @@
- out_remove_matches:
-       strlcpy(buf, xt_prefix[af], sizeof(buf));
-       strlcat(buf, FORMAT_MATCHES, sizeof(buf));
--      proc_net_remove(buf);
-+      proc_net_remove(&init_net, buf);
- out_remove_tables:
-       strlcpy(buf, xt_prefix[af], sizeof(buf));
-       strlcat(buf, FORMAT_TABLES, sizeof(buf));
--      proc_net_remove(buf);
-+      proc_net_remove(&init_net, buf);
- out:
-       return -1;
- #endif
-@@ -840,19 +855,42 @@
-       strlcpy(buf, xt_prefix[af], sizeof(buf));
-       strlcat(buf, FORMAT_TABLES, sizeof(buf));
--      proc_net_remove(buf);
-+      proc_net_remove(&init_net, buf);
-       strlcpy(buf, xt_prefix[af], sizeof(buf));
-       strlcat(buf, FORMAT_TARGETS, sizeof(buf));
--      proc_net_remove(buf);
-+      proc_net_remove(&init_net, buf);
-       strlcpy(buf, xt_prefix[af], sizeof(buf));
-       strlcat(buf, FORMAT_MATCHES, sizeof(buf));
--      proc_net_remove(buf);
-+      proc_net_remove(&init_net, buf);
- #endif /*CONFIG_PROC_FS*/
- }
- EXPORT_SYMBOL_GPL(xt_proto_fini);
-+static int xt_net_init(struct net *net)
++void __exit addrconf_cleanup(void)
 +{
++      struct net_device *dev;
++      struct inet6_dev *idev;
++      struct inet6_ifaddr *ifa;
 +      int i;
 +
-+      net->xtn = kmalloc(sizeof(struct xt_af_pernet) * NPROTO, GFP_KERNEL);
-+      if (!net->xtn)
-+              return -ENOMEM;
++      unregister_netdevice_notifier(&ipv6_dev_notf);
++
++#ifdef CONFIG_SYSCTL
++      addrconf_sysctl_unregister(&ipv6_devconf_dflt);
++      addrconf_sysctl_unregister(&ipv6_devconf);
++#endif
++
++      rtnl_lock();
++
++      /*
++       *      clean dev list.
++       */
 +
-+      for (i = 0; i < NPROTO; i++) {
-+              INIT_LIST_HEAD(&net->xtn[i].tables);
++      for_each_netdev(dev) {
++              if ((idev = __in6_dev_get(dev)) == NULL)
++                      continue;
++              addrconf_ifdown(dev, 1);
 +      }
-+      return 0;
-+}
++      addrconf_ifdown(&loopback_dev, 2);
 +
-+static void xt_net_exit(struct net *net)
-+{
-+      kfree(net->xtn);
-+}
++      /*
++       *      Check hash table.
++       */
 +
-+static struct pernet_operations xt_net_ops = {
-+      .init = xt_net_init,
-+      .exit = xt_net_exit,
-+};
- static int __init xt_init(void)
- {
-@@ -869,13 +907,13 @@
++      write_lock_bh(&addrconf_hash_lock);
++      for (i=0; i < IN6_ADDR_HSIZE; i++) {
++              for (ifa=inet6_addr_lst[i]; ifa; ) {
++                      struct inet6_ifaddr *bifa;
++
++                      bifa = ifa;
++                      ifa = ifa->lst_next;
++                      printk(KERN_DEBUG "bug: IPv6 address leakage detected: ifa=%p\n", bifa);
++                      /* Do not free it; something is wrong.
++                         Now we can investigate it with debugger.
++                       */
++              }
++      }
++      write_unlock_bh(&addrconf_hash_lock);
++
++      del_timer(&addr_chk_timer);
++
++      rtnl_unlock();
++
++#ifdef CONFIG_PROC_FS
++      proc_net_remove("if_inet6");
++#endif
++}
+diff -Nurb linux-2.6.22-590/net/ipv6/af_inet6.c linux-2.6.22-570/net/ipv6/af_inet6.c
+--- linux-2.6.22-590/net/ipv6/af_inet6.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/af_inet6.c       2008-01-23 19:16:05.000000000 -0500
+@@ -59,6 +59,9 @@
+ #ifdef CONFIG_IPV6_TUNNEL
+ #include <net/ip6_tunnel.h>
  #endif
-               INIT_LIST_HEAD(&xt[i].target);
-               INIT_LIST_HEAD(&xt[i].match);
--              INIT_LIST_HEAD(&xt[i].tables);
-       }
--      return 0;
-+      return register_pernet_subsys(&xt_net_ops);
- }
++#ifdef CONFIG_IPV6_MIP6
++#include <net/mip6.h>
++#endif
  
- static void __exit xt_fini(void)
- {
-+      unregister_pernet_subsys(&xt_net_ops);
-       kfree(xt);
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+@@ -82,7 +85,7 @@
+       return (struct ipv6_pinfo *)(((u8 *)sk) + offset);
  }
  
-diff -Nurb linux-2.6.22-570/net/netfilter/xt_MARK.c linux-2.6.22-590/net/netfilter/xt_MARK.c
---- linux-2.6.22-570/net/netfilter/xt_MARK.c   2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/net/netfilter/xt_MARK.c   2008-01-02 13:56:38.000000000 -0500
-@@ -131,7 +131,7 @@
-               if ((*pskb)->sk) 
-                       connection_sk = (*pskb)->sk;
-               else {
--                      connection_sk = inet_lookup(&tcp_hashinfo, src_ip, src_port, ip, port, dif);
-+                      connection_sk = inet_lookup(&tcp_hashinfo, src_ip, src_port, ip, port, dif,(*pskb)->sk->sk_net);
-               }
-               if (connection_sk) {
-diff -Nurb linux-2.6.22-570/net/netfilter/xt_hashlimit.c linux-2.6.22-590/net/netfilter/xt_hashlimit.c
---- linux-2.6.22-570/net/netfilter/xt_hashlimit.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netfilter/xt_hashlimit.c      2008-01-02 13:56:38.000000000 -0500
-@@ -21,6 +21,7 @@
- #include <linux/in.h>
- #include <linux/ip.h>
- #include <linux/ipv6.h>
-+#include <net/net_namespace.h>
- #include <linux/netfilter/x_tables.h>
- #include <linux/netfilter_ipv4/ip_tables.h>
-@@ -736,13 +737,13 @@
-               printk(KERN_ERR "xt_hashlimit: unable to create slab cache\n");
-               goto err2;
-       }
--      hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", proc_net);
-+      hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", init_net.proc_net);
-       if (!hashlimit_procdir4) {
-               printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
-                               "entry\n");
-               goto err3;
-       }
--      hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", proc_net);
-+      hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", init_net.proc_net);
-       if (!hashlimit_procdir6) {
-               printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
-                               "entry\n");
-@@ -750,7 +751,7 @@
-       }
-       return 0;
- err4:
--      remove_proc_entry("ipt_hashlimit", proc_net);
-+      remove_proc_entry("ipt_hashlimit", init_net.proc_net);
- err3:
-       kmem_cache_destroy(hashlimit_cachep);
- err2:
-@@ -762,8 +763,8 @@
- static void __exit xt_hashlimit_fini(void)
+-static int inet6_create(struct net *net, struct socket *sock, int protocol)
++static int inet6_create(struct socket *sock, int protocol)
  {
--      remove_proc_entry("ipt_hashlimit", proc_net);
--      remove_proc_entry("ip6t_hashlimit", proc_net);
-+      remove_proc_entry("ipt_hashlimit", init_net.proc_net);
-+      remove_proc_entry("ip6t_hashlimit", init_net.proc_net);
-       kmem_cache_destroy(hashlimit_cachep);
-       xt_unregister_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
- }
-diff -Nurb linux-2.6.22-570/net/netlink/af_netlink.c linux-2.6.22-590/net/netlink/af_netlink.c
---- linux-2.6.22-570/net/netlink/af_netlink.c  2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/netlink/af_netlink.c  2008-01-02 13:56:38.000000000 -0500
-@@ -63,6 +63,7 @@
- #include <net/sock.h>
- #include <net/scm.h>
- #include <net/netlink.h>
-+#include <net/net_namespace.h>
- #define NLGRPSZ(x)    (ALIGN(x, sizeof(unsigned long) * 8) / 8)
+       struct inet_sock *inet;
+       struct ipv6_pinfo *np;
+@@ -95,9 +98,6 @@
+       int try_loading_module = 0;
+       int err;
  
-@@ -212,7 +213,7 @@
-               wake_up(&nl_table_wait);
- }
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
+-
+       if (sock->type != SOCK_RAW &&
+           sock->type != SOCK_DGRAM &&
+           !inet_ehash_secret)
+@@ -166,7 +166,7 @@
+       BUG_TRAP(answer_prot->slab != NULL);
  
--static __inline__ struct sock *netlink_lookup(int protocol, u32 pid)
-+static __inline__ struct sock *netlink_lookup(struct net *net, int protocol, u32 pid)
- {
-       struct nl_pid_hash *hash = &nl_table[protocol].hash;
-       struct hlist_head *head;
-@@ -222,7 +223,7 @@
-       read_lock(&nl_table_lock);
-       head = nl_pid_hashfn(hash, pid);
-       sk_for_each(sk, node, head) {
--              if (nlk_sk(sk)->pid == pid) {
-+              if ((sk->sk_net == net) && (nlk_sk(sk)->pid == pid)) {
-                       sock_hold(sk);
-                       goto found;
-               }
-@@ -327,7 +328,7 @@
-        * makes sure updates are visible before bind or setsockopt return. */
- }
+       err = -ENOBUFS;
+-      sk = sk_alloc(net, PF_INET6, GFP_KERNEL, answer_prot, 1);
++      sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1);
+       if (sk == NULL)
+               goto out;
  
--static int netlink_insert(struct sock *sk, u32 pid)
-+static int netlink_insert(struct sock *sk, struct net *net, u32 pid)
- {
-       struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash;
-       struct hlist_head *head;
-@@ -340,7 +341,7 @@
-       head = nl_pid_hashfn(hash, pid);
-       len = 0;
-       sk_for_each(osk, node, head) {
--              if (nlk_sk(osk)->pid == pid)
-+              if ((osk->sk_net == net) && (nlk_sk(osk)->pid == pid))
-                       break;
-               len++;
-       }
-@@ -383,15 +384,15 @@
-       .obj_size = sizeof(struct netlink_sock),
- };
+@@ -209,7 +209,7 @@
+       inet->mc_index  = 0;
+       inet->mc_list   = NULL;
  
--static int __netlink_create(struct socket *sock, struct mutex *cb_mutex,
--                          int protocol)
-+static int __netlink_create(struct net *net, struct socket *sock,
-+                          struct mutex *cb_mutex, int protocol)
- {
-       struct sock *sk;
-       struct netlink_sock *nlk;
+-      if (init_net.sysctl_ipv4_no_pmtu_disc)
++      if (ipv4_config.no_pmtu_disc)
+               inet->pmtudisc = IP_PMTUDISC_DONT;
+       else
+               inet->pmtudisc = IP_PMTUDISC_WANT;
+@@ -290,7 +290,7 @@
+       /* Check if the address belongs to the host. */
+       if (addr_type == IPV6_ADDR_MAPPED) {
+               v4addr = addr->sin6_addr.s6_addr32[3];
+-              if (inet_addr_type(&init_net, v4addr) != RTN_LOCAL) {
++              if (inet_addr_type(v4addr) != RTN_LOCAL) {
+                       err = -EADDRNOTAVAIL;
+                       goto out;
+               }
+@@ -316,7 +316,7 @@
+                                       err = -EINVAL;
+                                       goto out;
+                               }
+-                              dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
++                              dev = dev_get_by_index(sk->sk_bound_dev_if);
+                               if (!dev) {
+                                       err = -ENODEV;
+                                       goto out;
+@@ -675,7 +675,6 @@
+               struct flowi fl;
  
-       sock->ops = &netlink_ops;
+               memset(&fl, 0, sizeof(fl));
+-              fl.fl_net = &init_net;
+               fl.proto = sk->sk_protocol;
+               ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
+               ipv6_addr_copy(&fl.fl6_src, &np->saddr);
+@@ -877,6 +876,9 @@
+       ipv6_frag_init();
+       ipv6_nodata_init();
+       ipv6_destopt_init();
++#ifdef CONFIG_IPV6_MIP6
++      mip6_init();
++#endif
  
--      sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
-+      sk = sk_alloc(net, PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
-       if (!sk)
-               return -ENOMEM;
+       /* Init v6 transport protocols. */
+       udpv6_init();
+@@ -942,7 +944,9 @@
  
-@@ -411,7 +412,7 @@
+       /* Cleanup code parts. */
+       ipv6_packet_cleanup();
+-
++#ifdef CONFIG_IPV6_MIP6
++      mip6_fini();
++#endif
+       addrconf_cleanup();
+       ip6_flowlabel_cleanup();
+       ip6_route_cleanup();
+diff -Nurb linux-2.6.22-590/net/ipv6/ah6.c linux-2.6.22-570/net/ipv6/ah6.c
+--- linux-2.6.22-590/net/ipv6/ah6.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/ah6.c    2007-07-08 19:32:17.000000000 -0400
+@@ -74,7 +74,7 @@
        return 0;
  }
  
--static int netlink_create(struct socket *sock, int protocol)
-+static int netlink_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct module *module = NULL;
-       struct mutex *cb_mutex;
-@@ -440,7 +441,7 @@
-       cb_mutex = nl_table[protocol].cb_mutex;
-       netlink_unlock_table();
--      if ((err = __netlink_create(sock, cb_mutex, protocol)) < 0)
-+      if ((err = __netlink_create(net, sock, cb_mutex, protocol)) < 0)
-               goto out_module;
-       nlk = nlk_sk(sock->sk);
-@@ -477,6 +478,7 @@
-       if (nlk->pid && !nlk->subscriptions) {
-               struct netlink_notify n = {
-+                                              .net = sk->sk_net,
-                                               .protocol = sk->sk_protocol,
-                                               .pid = nlk->pid,
-                                         };
-@@ -505,6 +507,7 @@
- static int netlink_autobind(struct socket *sock)
- {
-       struct sock *sk = sock->sk;
-+      struct net *net = sk->sk_net;
-       struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash;
-       struct hlist_head *head;
-       struct sock *osk;
-@@ -518,6 +521,8 @@
-       netlink_table_grab();
-       head = nl_pid_hashfn(hash, pid);
-       sk_for_each(osk, node, head) {
-+              if ((osk->sk_net != net))
-+                      continue;
-               if (nlk_sk(osk)->pid == pid) {
-                       /* Bind collision, search negative pid values. */
-                       pid = rover--;
-@@ -529,7 +534,7 @@
-       }
-       netlink_table_ungrab();
--      err = netlink_insert(sk, pid);
-+      err = netlink_insert(sk, net, pid);
-       if (err == -EADDRINUSE)
-               goto retry;
-@@ -583,6 +588,7 @@
- static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
- {
-       struct sock *sk = sock->sk;
-+      struct net *net = sk->sk_net;
-       struct netlink_sock *nlk = nlk_sk(sk);
-       struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
-       int err;
-@@ -606,7 +612,7 @@
-                       return -EINVAL;
-       } else {
-               err = nladdr->nl_pid ?
--                      netlink_insert(sk, nladdr->nl_pid) :
-+                      netlink_insert(sk, net, nladdr->nl_pid) :
-                       netlink_autobind(sock);
-               if (err)
-                       return err;
-@@ -690,10 +696,12 @@
- static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid)
- {
-       int protocol = ssk->sk_protocol;
-+      struct net *net;
-       struct sock *sock;
-       struct netlink_sock *nlk;
--      sock = netlink_lookup(protocol, pid);
-+      net = ssk->sk_net;
-+      sock = netlink_lookup(net, protocol, pid);
-       if (!sock)
-               return ERR_PTR(-ECONNREFUSED);
-@@ -866,6 +874,7 @@
- struct netlink_broadcast_data {
-       struct sock *exclude_sk;
-+      struct net *net;
-       u32 pid;
-       u32 group;
-       int failure;
-@@ -888,6 +897,9 @@
-           !test_bit(p->group - 1, nlk->groups))
-               goto out;
-+      if ((sk->sk_net != p->net))
-+              goto out;
-+
-       if (p->failure) {
-               netlink_overrun(sk);
-               goto out;
-@@ -926,6 +938,7 @@
- int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
-                     u32 group, gfp_t allocation)
- {
-+      struct net *net = ssk->sk_net;
-       struct netlink_broadcast_data info;
-       struct hlist_node *node;
-       struct sock *sk;
-@@ -933,6 +946,7 @@
-       skb = netlink_trim(skb, allocation);
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+ /**
+  *    ipv6_rearrange_destopt - rearrange IPv6 destination options header
+  *    @iph: IPv6 header
+@@ -132,8 +132,6 @@
+ bad:
+       return;
+ }
+-#else
+-static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt) {}
+ #endif
  
-       info.exclude_sk = ssk;
-+      info.net = net;
-       info.pid = pid;
-       info.group = group;
-       info.failure = 0;
-@@ -981,6 +995,9 @@
-       if (sk == p->exclude_sk)
-               goto out;
+ /**
+@@ -191,8 +189,10 @@
+       while (exthdr.raw < end) {
+               switch (nexthdr) {
+               case NEXTHDR_DEST:
++#ifdef CONFIG_IPV6_MIP6
+                       if (dir == XFRM_POLICY_OUT)
+                               ipv6_rearrange_destopt(iph, exthdr.opth);
++#endif
+               case NEXTHDR_HOP:
+                       if (!zero_out_mutable_opts(exthdr.opth)) {
+                               LIMIT_NETDEBUG(
+@@ -228,7 +228,7 @@
+       u8 nexthdr;
+       char tmp_base[8];
+       struct {
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+               struct in6_addr saddr;
+ #endif
+               struct in6_addr daddr;
+@@ -255,7 +255,7 @@
+                       err = -ENOMEM;
+                       goto error;
+               }
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+               memcpy(tmp_ext, &top_iph->saddr, extlen);
+ #else
+               memcpy(tmp_ext, &top_iph->daddr, extlen);
+@@ -294,7 +294,7 @@
  
-+      if (sk->sk_net != p->exclude_sk->sk_net)
-+              goto out;
-+
-       if (nlk->pid == p->pid || p->group - 1 >= nlk->ngroups ||
-           !test_bit(p->group - 1, nlk->groups))
-               goto out;
-@@ -1276,7 +1293,7 @@
-  */
+       memcpy(top_iph, tmp_base, sizeof(tmp_base));
+       if (tmp_ext) {
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+               memcpy(&top_iph->saddr, tmp_ext, extlen);
+ #else
+               memcpy(&top_iph->daddr, tmp_ext, extlen);
+@@ -554,4 +554,3 @@
+ module_exit(ah6_fini);
  
- struct sock *
--netlink_kernel_create(int unit, unsigned int groups,
-+netlink_kernel_create(struct net *net, int unit, unsigned int groups,
-                     void (*input)(struct sock *sk, int len),
-                     struct mutex *cb_mutex, struct module *module)
- {
-@@ -1293,7 +1310,7 @@
-       if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
-               return NULL;
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_AH);
+diff -Nurb linux-2.6.22-590/net/ipv6/anycast.c linux-2.6.22-570/net/ipv6/anycast.c
+--- linux-2.6.22-590/net/ipv6/anycast.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/anycast.c        2008-01-23 19:15:56.000000000 -0500
+@@ -32,7 +32,6 @@
  
--      if (__netlink_create(sock, cb_mutex, unit) < 0)
-+      if (__netlink_create(net, sock, cb_mutex, unit) < 0)
-               goto out_sock_release;
+ #include <net/sock.h>
+ #include <net/snmp.h>
+-#include <net/net_namespace.h>
  
-       if (groups < 32)
-@@ -1308,18 +1325,20 @@
-       if (input)
-               nlk_sk(sk)->data_ready = input;
+ #include <net/ipv6.h>
+ #include <net/protocol.h>
+@@ -113,10 +112,10 @@
+               } else {
+                       /* router, no matching interface: just pick one */
  
--      if (netlink_insert(sk, 0))
-+      if (netlink_insert(sk, net, 0))
-               goto out_sock_release;
+-                      dev = dev_get_by_flags(&init_net, IFF_UP, IFF_UP|IFF_LOOPBACK);
++                      dev = dev_get_by_flags(IFF_UP, IFF_UP|IFF_LOOPBACK);
+               }
+       } else
+-              dev = dev_get_by_index(&init_net, ifindex);
++              dev = dev_get_by_index(ifindex);
  
-       nlk = nlk_sk(sk);
-       nlk->flags |= NETLINK_KERNEL_SOCKET;
+       if (dev == NULL) {
+               err = -ENODEV;
+@@ -197,7 +196,7 @@
  
-       netlink_table_grab();
-+      if (!nl_table[unit].registered) {
-       nl_table[unit].groups = groups;
-       nl_table[unit].listeners = listeners;
-       nl_table[unit].cb_mutex = cb_mutex;
-       nl_table[unit].module = module;
-       nl_table[unit].registered = 1;
-+      }
-       netlink_table_ungrab();
+       write_unlock_bh(&ipv6_sk_ac_lock);
  
-       return sk;
-@@ -1420,7 +1439,7 @@
-       atomic_inc(&skb->users);
-       cb->skb = skb;
+-      dev = dev_get_by_index(&init_net, pac->acl_ifindex);
++      dev = dev_get_by_index(pac->acl_ifindex);
+       if (dev) {
+               ipv6_dev_ac_dec(dev, &pac->acl_addr);
+               dev_put(dev);
+@@ -225,7 +224,7 @@
+               if (pac->acl_ifindex != prev_index) {
+                       if (dev)
+                               dev_put(dev);
+-                      dev = dev_get_by_index(&init_net, pac->acl_ifindex);
++                      dev = dev_get_by_index(pac->acl_ifindex);
+                       prev_index = pac->acl_ifindex;
+               }
+               if (dev)
+@@ -430,7 +429,7 @@
+       if (dev)
+               return ipv6_chk_acast_dev(dev, addr);
+       read_lock(&dev_base_lock);
+-      for_each_netdev(&init_net, dev)
++      for_each_netdev(dev)
+               if (ipv6_chk_acast_dev(dev, addr)) {
+                       found = 1;
+                       break;
+@@ -454,7 +453,7 @@
+       struct ac6_iter_state *state = ac6_seq_private(seq);
  
--      sk = netlink_lookup(ssk->sk_protocol, NETLINK_CB(skb).pid);
-+      sk = netlink_lookup(ssk->sk_net, ssk->sk_protocol, NETLINK_CB(skb).pid);
-       if (sk == NULL) {
-               netlink_destroy_callback(cb);
-               return -ECONNREFUSED;
-@@ -1462,7 +1481,8 @@
-       if (!skb) {
-               struct sock *sk;
+       state->idev = NULL;
+-      for_each_netdev(&init_net, state->dev) {
++      for_each_netdev(state->dev) {
+               struct inet6_dev *idev;
+               idev = in6_dev_get(state->dev);
+               if (!idev)
+@@ -580,7 +579,7 @@
  
--              sk = netlink_lookup(in_skb->sk->sk_protocol,
-+              sk = netlink_lookup(in_skb->sk->sk_net,
-+                                  in_skb->sk->sk_protocol,
-                                   NETLINK_CB(in_skb).pid);
-               if (sk) {
-                       sk->sk_err = ENOBUFS;
-@@ -1613,6 +1633,7 @@
+ int __init ac6_proc_init(void)
+ {
+-      if (!proc_net_fops_create(&init_net, "anycast6", S_IRUGO, &ac6_seq_fops))
++      if (!proc_net_fops_create("anycast6", S_IRUGO, &ac6_seq_fops))
+               return -ENOMEM;
  
- #ifdef CONFIG_PROC_FS
- struct nl_seq_iter {
-+      struct net *net;
-       int link;
-       int hash_idx;
- };
-@@ -1630,6 +1651,8 @@
+       return 0;
+@@ -588,7 +587,7 @@
  
-               for (j = 0; j <= hash->mask; j++) {
-                       sk_for_each(s, node, &hash->table[j]) {
-+                              if (iter->net != s->sk_net)
-+                                      continue;
-                               if (off == pos) {
-                                       iter->link = i;
-                                       iter->hash_idx = j;
-@@ -1659,11 +1682,14 @@
-       if (v == SEQ_START_TOKEN)
-               return netlink_seq_socket_idx(seq, 0);
+ void ac6_proc_exit(void)
+ {
+-      proc_net_remove(&init_net, "anycast6");
++      proc_net_remove("anycast6");
+ }
+ #endif
  
--      s = sk_next(v);
-+      iter = seq->private;
-+      s = v;
-+      do {
-+              s = sk_next(s);
-+      } while (s && (iter->net != s->sk_net));
-       if (s)
-               return s;
+diff -Nurb linux-2.6.22-590/net/ipv6/datagram.c linux-2.6.22-570/net/ipv6/datagram.c
+--- linux-2.6.22-590/net/ipv6/datagram.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/datagram.c       2007-07-08 19:32:17.000000000 -0400
+@@ -60,7 +60,6 @@
+               return -EAFNOSUPPORT;
  
--      iter = seq->private;
-       i = iter->link;
-       j = iter->hash_idx + 1;
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       if (np->sndflow) {
+               fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
+               if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
+@@ -545,7 +544,7 @@
+                               if (!src_info->ipi6_ifindex)
+                                       return -EINVAL;
+                               else {
+-                                      dev = dev_get_by_index(&init_net, src_info->ipi6_ifindex);
++                                      dev = dev_get_by_index(src_info->ipi6_ifindex);
+                                       if (!dev)
+                                               return -ENODEV;
+                               }
+@@ -659,7 +658,7 @@
  
-@@ -1672,6 +1698,8 @@
+                       switch (rthdr->type) {
+                       case IPV6_SRCRT_TYPE_0:
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+                       case IPV6_SRCRT_TYPE_2:
+ #endif
+                               break;
+diff -Nurb linux-2.6.22-590/net/ipv6/esp6.c linux-2.6.22-570/net/ipv6/esp6.c
+--- linux-2.6.22-590/net/ipv6/esp6.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/esp6.c   2007-07-08 19:32:17.000000000 -0400
+@@ -421,4 +421,3 @@
+ module_exit(esp6_fini);
  
-               for (; j <= hash->mask; j++) {
-                       s = sk_head(&hash->table[j]);
-+                      while (s && (iter->net != s->sk_net))
-+                              s = sk_next(s);
-                       if (s) {
-                               iter->link = i;
-                               iter->hash_idx = j;
-@@ -1742,15 +1770,24 @@
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP);
+diff -Nurb linux-2.6.22-590/net/ipv6/exthdrs.c linux-2.6.22-570/net/ipv6/exthdrs.c
+--- linux-2.6.22-590/net/ipv6/exthdrs.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/exthdrs.c        2007-07-08 19:32:17.000000000 -0400
+@@ -42,7 +42,7 @@
+ #include <net/ndisc.h>
+ #include <net/ip6_route.h>
+ #include <net/addrconf.h>
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+ #include <net/xfrm.h>
+ #endif
  
-       seq = file->private_data;
-       seq->private = iter;
-+      iter->net = get_net(PROC_NET(inode));
-       return 0;
+@@ -90,7 +90,6 @@
+  bad:
+       return -1;
  }
+-EXPORT_SYMBOL_GPL(ipv6_find_tlv);
  
-+static int netlink_seq_release(struct inode *inode, struct file *file)
-+{
-+      struct seq_file *seq = file->private_data;
-+      struct nl_seq_iter *iter = seq->private;
-+      put_net(iter->net);
-+      return seq_release_private(inode, file);
-+}
-+
- static const struct file_operations netlink_seq_fops = {
-       .owner          = THIS_MODULE,
-       .open           = netlink_seq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
--      .release        = seq_release_private,
-+      .release        = netlink_seq_release,
- };
+ /*
+  *    Parsing tlv encoded headers.
+@@ -197,7 +196,7 @@
+   Destination options header.
+  *****************************/
  
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
+ {
+       struct sk_buff *skb = *skbp;
+@@ -271,7 +270,7 @@
  #endif
-@@ -1792,6 +1829,27 @@
-       .owner  = THIS_MODULE,  /* for consistency 8) */
- };
  
-+static int netlink_net_init(struct net *net)
-+{
-+#ifdef CONFIG_PROC_FS
-+      if (!proc_net_fops_create(net, "netlink", 0, &netlink_seq_fops))
-+              return -ENOMEM;
-+#endif
-+      return 0;
-+}
-+
-+static void netlink_net_exit(struct net *net)
-+{
-+#ifdef CONFIG_PROC_FS
-+      proc_net_remove(net, "netlink");
-+#endif
-+}
-+
-+static struct pernet_operations netlink_net_ops = {
-+      .init = netlink_net_init,
-+      .exit = netlink_net_exit,
-+};
-+
- static int __init netlink_proto_init(void)
+ static struct tlvtype_proc tlvprocdestopt_lst[] = {
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+       {
+               .type   = IPV6_TLV_HAO,
+               .func   = ipv6_dest_hao,
+@@ -284,7 +283,7 @@
  {
-       struct sk_buff *dummy_skb;
-@@ -1837,9 +1895,7 @@
+       struct sk_buff *skb = *skbp;
+       struct inet6_skb_parm *opt = IP6CB(skb);
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+       __u16 dstbuf;
+ #endif
+       struct dst_entry *dst;
+@@ -299,7 +298,7 @@
        }
  
-       sock_register(&netlink_family_ops);
--#ifdef CONFIG_PROC_FS
--      proc_net_fops_create("netlink", 0, &netlink_seq_fops);
--#endif
-+      register_pernet_subsys(&netlink_net_ops);
-       /* The netlink device handler may be needed early. */
-       rtnetlink_init();
- out:
-diff -Nurb linux-2.6.22-570/net/netlink/attr.c linux-2.6.22-590/net/netlink/attr.c
---- linux-2.6.22-570/net/netlink/attr.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netlink/attr.c        2008-01-02 13:56:38.000000000 -0500
-@@ -72,6 +72,17 @@
-                       return -ERANGE;
-               break;
-+      case NLA_NESTED_COMPAT:
-+              if (attrlen < pt->len)
-+                      return -ERANGE;
-+              if (attrlen < NLA_ALIGN(pt->len))
-+                      break;
-+              if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN)
-+                      return -ERANGE;
-+              nla = nla_data(nla) + NLA_ALIGN(pt->len);
-+              if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla))
-+                      return -ERANGE;
-+              break;
-       default:
-               if (pt->len)
-                       minlen = pt->len;
-diff -Nurb linux-2.6.22-570/net/netlink/genetlink.c linux-2.6.22-590/net/netlink/genetlink.c
---- linux-2.6.22-570/net/netlink/genetlink.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netlink/genetlink.c   2008-01-02 13:56:38.000000000 -0500
-@@ -557,8 +557,9 @@
-               goto errout_register;
+       opt->lastopt = opt->dst1 = skb_network_header_len(skb);
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+       dstbuf = opt->dst1;
+ #endif
  
-       netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV);
--      genl_sock = netlink_kernel_create(NETLINK_GENERIC, GENL_MAX_ID,
--                                        genl_rcv, NULL, THIS_MODULE);
-+      genl_sock = netlink_kernel_create(&init_net, NETLINK_GENERIC,
-+                                        GENL_MAX_ID, genl_rcv, NULL,
-+                                        THIS_MODULE);
-       if (genl_sock == NULL)
-               panic("GENL: Cannot initialize generic netlink\n");
+@@ -309,7 +308,7 @@
+               skb = *skbp;
+               skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
+               opt = IP6CB(skb);
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+               opt->nhoff = dstbuf;
+ #else
+               opt->nhoff = opt->dst1;
+@@ -428,7 +427,7 @@
+ looped_back:
+       if (hdr->segments_left == 0) {
+               switch (hdr->type) {
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+               case IPV6_SRCRT_TYPE_2:
+                       /* Silently discard type 2 header unless it was
+                        * processed by own
+@@ -464,7 +463,7 @@
+                       return -1;
+               }
+               break;
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+       case IPV6_SRCRT_TYPE_2:
+               /* Silently discard invalid RTH type 2 */
+               if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
+@@ -521,7 +520,7 @@
+       addr += i - 1;
  
-diff -Nurb linux-2.6.22-570/net/netrom/af_netrom.c linux-2.6.22-590/net/netrom/af_netrom.c
---- linux-2.6.22-570/net/netrom/af_netrom.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netrom/af_netrom.c    2008-01-02 13:56:38.000000000 -0500
-@@ -41,6 +41,7 @@
- #include <net/ip.h>
- #include <net/tcp_states.h>
- #include <net/arp.h>
-+#include <net/net_namespace.h>
- #include <linux/init.h>
+       switch (hdr->type) {
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+       case IPV6_SRCRT_TYPE_2:
+               if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
+                                    (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
+diff -Nurb linux-2.6.22-590/net/ipv6/fib6_rules.c linux-2.6.22-570/net/ipv6/fib6_rules.c
+--- linux-2.6.22-590/net/ipv6/fib6_rules.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/fib6_rules.c     2008-01-23 19:16:05.000000000 -0500
+@@ -244,7 +244,7 @@
+       return -ENOBUFS;
+ }
  
- static int nr_ndevs = 4;
-@@ -105,6 +106,9 @@
+-static u32 fib6_rule_default_pref(struct fib_rules_ops *ops)
++static u32 fib6_rule_default_pref(void)
  {
-       struct net_device *dev = (struct net_device *)ptr;
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (event != NETDEV_DOWN)
-               return NOTIFY_DONE;
+       return 0x3FFF;
+ }
+@@ -277,10 +277,10 @@
+       list_add_tail(&local_rule.common.list, &fib6_rules);
+       list_add_tail(&main_rule.common.list, &fib6_rules);
  
-@@ -408,15 +412,18 @@
-       .obj_size = sizeof(struct nr_sock),
- };
+-      fib_rules_register(&init_net, &fib6_rules_ops);
++      fib_rules_register(&fib6_rules_ops);
+ }
  
--static int nr_create(struct socket *sock, int protocol)
-+static int nr_create(struct net *net, struct socket *sock, int protocol)
+ void fib6_rules_cleanup(void)
  {
-       struct sock *sk;
-       struct nr_sock *nr;
+-      fib_rules_unregister(&init_net, &fib6_rules_ops);
++      fib_rules_unregister(&fib6_rules_ops);
+ }
+diff -Nurb linux-2.6.22-590/net/ipv6/icmp.c linux-2.6.22-570/net/ipv6/icmp.c
+--- linux-2.6.22-590/net/ipv6/icmp.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/icmp.c   2008-01-23 19:15:56.000000000 -0500
+@@ -272,7 +272,7 @@
+       return 0;
+ }
  
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
-+
-       if (sock->type != SOCK_SEQPACKET || protocol != 0)
-               return -ESOCKTNOSUPPORT;
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+ static void mip6_addr_swap(struct sk_buff *skb)
+ {
+       struct ipv6hdr *iph = ipv6_hdr(skb);
+@@ -377,7 +377,6 @@
+       mip6_addr_swap(skb);
  
--      if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, &nr_proto, 1)) == NULL)
-+      if ((sk = sk_alloc(net, PF_NETROM, GFP_ATOMIC, &nr_proto, 1)) == NULL)
-               return -ENOMEM;
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       fl.proto = IPPROTO_ICMPV6;
+       ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
+       if (saddr)
+@@ -496,7 +495,6 @@
+       tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY;
  
-       nr = nr_sk(sk);
-@@ -458,7 +465,7 @@
-       if (osk->sk_type != SOCK_SEQPACKET)
-               return NULL;
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       fl.proto = IPPROTO_ICMPV6;
+       ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
+       if (saddr)
+diff -Nurb linux-2.6.22-590/net/ipv6/inet6_connection_sock.c linux-2.6.22-570/net/ipv6/inet6_connection_sock.c
+--- linux-2.6.22-590/net/ipv6/inet6_connection_sock.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/inet6_connection_sock.c  2007-07-08 19:32:17.000000000 -0400
+@@ -149,7 +149,6 @@
+       struct in6_addr *final_p = NULL, final;
  
--      if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
-+      if ((sk = sk_alloc(osk->sk_net, PF_NETROM, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
-               return NULL;
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       fl.proto = sk->sk_protocol;
+       ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
+       ipv6_addr_copy(&fl.fl6_src, &np->saddr);
+diff -Nurb linux-2.6.22-590/net/ipv6/inet6_hashtables.c linux-2.6.22-570/net/ipv6/inet6_hashtables.c
+--- linux-2.6.22-590/net/ipv6/inet6_hashtables.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/inet6_hashtables.c       2008-01-23 19:16:05.000000000 -0500
+@@ -61,7 +61,7 @@
+                                          const __be16 sport,
+                                          const struct in6_addr *daddr,
+                                          const u16 hnum,
+-                                         const int dif, struct net *net)
++                                         const int dif)
+ {
+       struct sock *sk;
+       const struct hlist_node *node;
+@@ -105,7 +105,7 @@
  
-       nr = nr_sk(sk);
-@@ -1447,9 +1454,9 @@
+ struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
+                                  const struct in6_addr *daddr,
+-                                 const unsigned short hnum, const int dif, struct net *net)
++                                 const unsigned short hnum, const int dif)
+ {
+       struct sock *sk;
+       const struct hlist_node *node;
+@@ -113,7 +113,7 @@
+       int score, hiscore = 0;
  
-       nr_loopback_init();
+       read_lock(&hashinfo->lhash_lock);
+-      sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(net, hnum)]) {
++      sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) {
+               if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) {
+                       const struct ipv6_pinfo *np = inet6_sk(sk);
  
--      proc_net_fops_create("nr", S_IRUGO, &nr_info_fops);
--      proc_net_fops_create("nr_neigh", S_IRUGO, &nr_neigh_fops);
--      proc_net_fops_create("nr_nodes", S_IRUGO, &nr_nodes_fops);
-+      proc_net_fops_create(&init_net, "nr", S_IRUGO, &nr_info_fops);
-+      proc_net_fops_create(&init_net, "nr_neigh", S_IRUGO, &nr_neigh_fops);
-+      proc_net_fops_create(&init_net, "nr_nodes", S_IRUGO, &nr_nodes_fops);
- out:
-       return rc;
- fail:
-@@ -1477,9 +1484,9 @@
+@@ -152,12 +152,12 @@
+ struct sock *inet6_lookup(struct inet_hashinfo *hashinfo,
+                         const struct in6_addr *saddr, const __be16 sport,
+                         const struct in6_addr *daddr, const __be16 dport,
+-                        const int dif, struct net *net)
++                        const int dif)
  {
-       int i;
+       struct sock *sk;
  
--      proc_net_remove("nr");
--      proc_net_remove("nr_neigh");
--      proc_net_remove("nr_nodes");
-+      proc_net_remove(&init_net, "nr");
-+      proc_net_remove(&init_net, "nr_neigh");
-+      proc_net_remove(&init_net, "nr_nodes");
-       nr_loopback_clear();
+       local_bh_disable();
+-      sk = __inet6_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif, net);
++      sk = __inet6_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif);
+       local_bh_enable();
  
-       nr_rt_free();
-diff -Nurb linux-2.6.22-570/net/netrom/nr_route.c linux-2.6.22-590/net/netrom/nr_route.c
---- linux-2.6.22-570/net/netrom/nr_route.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/netrom/nr_route.c     2008-01-02 13:56:38.000000000 -0500
-@@ -580,7 +580,7 @@
+       return sk;
+@@ -251,7 +251,6 @@
+ int inet6_hash_connect(struct inet_timewait_death_row *death_row,
+                      struct sock *sk)
  {
-       struct net_device *dev;
--      if ((dev = dev_get_by_name(devname)) == NULL)
-+      if ((dev = dev_get_by_name(&init_net, devname)) == NULL)
-               return NULL;
+-      struct net *net = sk->sk_net;
+       struct inet_hashinfo *hinfo = death_row->hashinfo;
+       const unsigned short snum = inet_sk(sk)->num;
+       struct inet_bind_hashbucket *head;
+@@ -259,8 +258,8 @@
+       int ret;
  
-       if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)
-@@ -598,7 +598,7 @@
-       struct net_device *dev, *first = NULL;
+       if (snum == 0) {
+-              const int low = sk->sk_net->sysctl_local_port_range[0];
+-              const int high = sk->sk_net->sysctl_local_port_range[1];
++              const int low = sysctl_local_port_range[0];
++              const int high = sysctl_local_port_range[1];
+               const int range = high - low;
+               int i, port;
+               static u32 hint;
+@@ -271,7 +270,7 @@
+               local_bh_disable();
+               for (i = 1; i <= range; i++) {
+                       port = low + (i + offset) % range;
+-                      head = &hinfo->bhash[inet_bhashfn(net, port, hinfo->bhash_size)];
++                      head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)];
+                       spin_lock(&head->lock);
  
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)
-                       if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
-                               first = dev;
-@@ -618,7 +618,7 @@
-       struct net_device *dev;
+                       /* Does not bother with rcv_saddr checks,
+@@ -279,7 +278,7 @@
+                        * unique enough.
+                        */
+                       inet_bind_bucket_for_each(tb, node, &head->chain) {
+-                              if ((tb->port == port) && (tb->net == net)) {
++                              if (tb->port == port) {
+                                       BUG_TRAP(!hlist_empty(&tb->owners));
+                                       if (tb->fastreuse >= 0)
+                                               goto next_port;
+@@ -292,7 +291,7 @@
+                       }
  
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
-                       dev_hold(dev);
-                       goto out;
-diff -Nurb linux-2.6.22-570/net/packet/af_packet.c linux-2.6.22-590/net/packet/af_packet.c
---- linux-2.6.22-570/net/packet/af_packet.c    2008-01-02 13:56:27.000000000 -0500
-+++ linux-2.6.22-590/net/packet/af_packet.c    2008-01-02 13:56:38.000000000 -0500
-@@ -65,6 +65,7 @@
- #include <net/protocol.h>
- #include <linux/skbuff.h>
- #include <net/sock.h>
-+#include <net/net_namespace.h>
- #include <linux/errno.h>
- #include <linux/timer.h>
- #include <asm/system.h>
-@@ -135,10 +136,6 @@
-    packet classifier depends on it.
-  */
+                       tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
+-                                                   head, net, port);
++                                                   head, port);
+                       if (!tb) {
+                               spin_unlock(&head->lock);
+                               break;
+@@ -327,7 +326,7 @@
+               goto out;
+       }
  
--/* List of all packet sockets. */
--static HLIST_HEAD(packet_sklist);
--static DEFINE_RWLOCK(packet_sklist_lock);
--
- static atomic_t packet_socks_nr;
+-      head = &hinfo->bhash[inet_bhashfn(net, snum, hinfo->bhash_size)];
++      head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)];
+       tb   = inet_csk(sk)->icsk_bind_hash;
+       spin_lock_bh(&head->lock);
  
+diff -Nurb linux-2.6.22-590/net/ipv6/ip6_fib.c linux-2.6.22-570/net/ipv6/ip6_fib.c
+--- linux-2.6.22-590/net/ipv6/ip6_fib.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/ip6_fib.c        2007-07-08 19:32:17.000000000 -0400
+@@ -361,7 +361,6 @@
  
-@@ -273,6 +270,9 @@
-       if (skb->pkt_type == PACKET_LOOPBACK)
-               goto out;
+ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       unsigned int h, s_h;
+       unsigned int e = 0, s_e;
+       struct rt6_rtnl_dump_arg arg;
+@@ -370,9 +369,6 @@
+       struct hlist_node *node;
+       int res = 0;
  
-+      if (dev->nd_net != sk->sk_net)
-+              goto out;
-+
-       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
-               goto oom;
+-      if (net != &init_net)
+-              return 0;
+-
+       s_h = cb->args[0];
+       s_e = cb->args[1];
  
-@@ -344,7 +344,7 @@
-        */
+@@ -1315,11 +1311,6 @@
  
-       saddr->spkt_device[13] = 0;
--      dev = dev_get_by_name(saddr->spkt_device);
-+      dev = dev_get_by_name(sk->sk_net, saddr->spkt_device);
-       err = -ENODEV;
-       if (dev == NULL)
-               goto out_unlock;
-@@ -462,6 +462,9 @@
-       sk = pt->af_packet_priv;
-       po = pkt_sk(sk);
+ static int fib6_clean_node(struct fib6_walker_t *w)
+ {
+-      struct nl_info info = {
+-              .nlh = NULL,
+-              .pid = 0,
+-              .net = &init_net,
+-      };
+       int res;
+       struct rt6_info *rt;
+       struct fib6_cleaner_t *c = (struct fib6_cleaner_t*)w;
+@@ -1328,7 +1319,7 @@
+               res = c->func(rt, c->arg);
+               if (res < 0) {
+                       w->leaf = rt;
+-                      res = fib6_del(rt, &info);
++                      res = fib6_del(rt, NULL);
+                       if (res) {
+ #if RT6_DEBUG >= 2
+                               printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res);
+diff -Nurb linux-2.6.22-590/net/ipv6/ip6_flowlabel.c linux-2.6.22-570/net/ipv6/ip6_flowlabel.c
+--- linux-2.6.22-590/net/ipv6/ip6_flowlabel.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/ip6_flowlabel.c  2007-07-08 19:32:17.000000000 -0400
+@@ -22,7 +22,6 @@
+ #include <linux/seq_file.h>
  
-+      if (dev->nd_net != sk->sk_net)
-+              goto drop;
-+
-       skb->dev = dev;
+ #include <net/sock.h>
+-#include <net/net_namespace.h>
  
-       if (dev->hard_header) {
-@@ -578,6 +581,9 @@
-       sk = pt->af_packet_priv;
-       po = pkt_sk(sk);
+ #include <net/ipv6.h>
+ #include <net/ndisc.h>
+@@ -310,7 +309,6 @@
  
-+      if (dev->nd_net != sk->sk_net)
-+              goto drop;
-+
-       if (dev->hard_header) {
-               if (sk->sk_type != SOCK_DGRAM)
-                       skb_push(skb, skb->data - skb_mac_header(skb));
-@@ -738,7 +744,7 @@
-       }
+               msg.msg_controllen = olen;
+               msg.msg_control = (void*)(fl->opt+1);
+-              flowi.fl_net = &init_net;
+               flowi.oif = 0;
  
+               err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk, &junk);
+@@ -692,7 +690,7 @@
+ void ip6_flowlabel_init(void)
+ {
+ #ifdef CONFIG_PROC_FS
+-      proc_net_fops_create(&init_net, "ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops);
++      proc_net_fops_create("ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops);
+ #endif
+ }
  
--      dev = dev_get_by_index(ifindex);
-+      dev = dev_get_by_index(sk->sk_net, ifindex);
-       err = -ENXIO;
-       if (dev == NULL)
-               goto out_unlock;
-@@ -811,15 +817,17 @@
+@@ -700,6 +698,6 @@
  {
-       struct sock *sk = sock->sk;
-       struct packet_sock *po;
-+      struct net *net;
+       del_timer(&ip6_fl_gc_timer);
+ #ifdef CONFIG_PROC_FS
+-      proc_net_remove(&init_net, "ip6_flowlabel");
++      proc_net_remove("ip6_flowlabel");
+ #endif
+ }
+diff -Nurb linux-2.6.22-590/net/ipv6/ip6_input.c linux-2.6.22-570/net/ipv6/ip6_input.c
+--- linux-2.6.22-590/net/ipv6/ip6_input.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/ip6_input.c      2007-07-08 19:32:17.000000000 -0400
+@@ -61,11 +61,6 @@
+       u32             pkt_len;
+       struct inet6_dev *idev;
  
-       if (!sk)
+-      if (dev->nd_net != &init_net) {
+-              kfree_skb(skb);
+-              return 0;
+-      }
+-
+       if (skb->pkt_type == PACKET_OTHERHOST) {
+               kfree_skb(skb);
                return 0;
+diff -Nurb linux-2.6.22-590/net/ipv6/ip6_output.c linux-2.6.22-570/net/ipv6/ip6_output.c
+--- linux-2.6.22-590/net/ipv6/ip6_output.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/ip6_output.c     2008-01-23 19:16:05.000000000 -0500
+@@ -423,7 +423,7 @@
  
-+      net = sk->sk_net;
-       po = pkt_sk(sk);
+       /* XXX: idev->cnf.proxy_ndp? */
+       if (ipv6_devconf.proxy_ndp &&
+-          pneigh_lookup(&nd_tbl, &init_net, &hdr->daddr, skb->dev, 0)) {
++          pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) {
+               int proxied = ip6_forward_proxy_check(skb);
+               if (proxied > 0)
+                       return ip6_input(skb);
+@@ -543,7 +543,7 @@
+                       found_rhdr = 1;
+                       break;
+               case NEXTHDR_DEST:
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+                       if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
+                               break;
+ #endif
+diff -Nurb linux-2.6.22-590/net/ipv6/ip6_tunnel.c linux-2.6.22-570/net/ipv6/ip6_tunnel.c
+--- linux-2.6.22-590/net/ipv6/ip6_tunnel.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/ip6_tunnel.c     2008-01-23 19:15:56.000000000 -0500
+@@ -235,7 +235,7 @@
+               int i;
+               for (i = 1; i < IP6_TNL_MAX; i++) {
+                       sprintf(name, "ip6tnl%d", i);
+-                      if (__dev_get_by_name(&init_net, name) == NULL)
++                      if (__dev_get_by_name(name) == NULL)
+                               break;
+               }
+               if (i == IP6_TNL_MAX)
+@@ -651,7 +651,7 @@
+               struct net_device *ldev = NULL;
  
--      write_lock_bh(&packet_sklist_lock);
-+      write_lock_bh(&net->packet_sklist_lock);
-       sk_del_node_init(sk);
--      write_unlock_bh(&packet_sklist_lock);
-+      write_unlock_bh(&net->packet_sklist_lock);
+               if (p->link)
+-                      ldev = dev_get_by_index(&init_net, p->link);
++                      ldev = dev_get_by_index(p->link);
  
-       /*
-        *      Unhook packet receive handler.
-@@ -933,7 +941,7 @@
-               return -EINVAL;
-       strlcpy(name,uaddr->sa_data,sizeof(name));
+               if ((ipv6_addr_is_multicast(&p->laddr) ||
+                    likely(ipv6_chk_addr(&p->laddr, ldev, 0))) &&
+@@ -787,7 +787,7 @@
+               struct net_device *ldev = NULL;
  
--      dev = dev_get_by_name(name);
-+      dev = dev_get_by_name(sk->sk_net, name);
-       if (dev) {
-               err = packet_do_bind(sk, dev, pkt_sk(sk)->num);
-               dev_put(dev);
-@@ -960,7 +968,7 @@
+               if (p->link)
+-                      ldev = dev_get_by_index(&init_net, p->link);
++                      ldev = dev_get_by_index(p->link);
  
-       if (sll->sll_ifindex) {
-               err = -ENODEV;
--              dev = dev_get_by_index(sll->sll_ifindex);
-+              dev = dev_get_by_index(sk->sk_net, sll->sll_ifindex);
-               if (dev == NULL)
-                       goto out;
-       }
-@@ -982,7 +990,7 @@
-  *    Create a packet of type SOCK_PACKET.
-  */
+               if (unlikely(!ipv6_chk_addr(&p->laddr, ldev, 0)))
+                       printk(KERN_WARNING
+diff -Nurb linux-2.6.22-590/net/ipv6/ipcomp6.c linux-2.6.22-570/net/ipv6/ipcomp6.c
+--- linux-2.6.22-590/net/ipv6/ipcomp6.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/ipcomp6.c        2008-01-23 19:15:56.000000000 -0500
+@@ -501,4 +501,4 @@
+ MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) for IPv6 - RFC3173");
+ MODULE_AUTHOR("Mitsuru KANDA <mk@linux-ipv6.org>");
  
--static int packet_create(struct socket *sock, int protocol)
-+static int packet_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct sock *sk;
-       struct packet_sock *po;
-@@ -998,7 +1006,7 @@
-       sock->state = SS_UNCONNECTED;
+-MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_COMP);
++
+diff -Nurb linux-2.6.22-590/net/ipv6/ipv6_sockglue.c linux-2.6.22-570/net/ipv6/ipv6_sockglue.c
+--- linux-2.6.22-590/net/ipv6/ipv6_sockglue.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/ipv6_sockglue.c  2008-01-23 19:15:56.000000000 -0500
+@@ -123,7 +123,7 @@
+       struct ipv6hdr *ipv6h;
+       struct inet6_protocol *ops;
  
-       err = -ENOBUFS;
--      sk = sk_alloc(PF_PACKET, GFP_KERNEL, &packet_proto, 1);
-+      sk = sk_alloc(net, PF_PACKET, GFP_KERNEL, &packet_proto, 1);
-       if (sk == NULL)
-               goto out;
+-      if (!(features & NETIF_F_V6_CSUM))
++      if (!(features & NETIF_F_HW_CSUM))
+               features &= ~NETIF_F_SG;
  
-@@ -1034,9 +1042,9 @@
-               po->running = 1;
-       }
+       if (unlikely(skb_shinfo(skb)->gso_type &
+@@ -417,7 +417,7 @@
+                       struct ipv6_rt_hdr *rthdr = opt->srcrt;
+                       switch (rthdr->type) {
+                       case IPV6_SRCRT_TYPE_0:
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+                       case IPV6_SRCRT_TYPE_2:
+ #endif
+                               break;
+@@ -463,7 +463,6 @@
+               struct flowi fl;
+               int junk;
  
--      write_lock_bh(&packet_sklist_lock);
--      sk_add_node(sk, &packet_sklist);
--      write_unlock_bh(&packet_sklist_lock);
-+      write_lock_bh(&net->packet_sklist_lock);
-+      sk_add_node(sk, &net->packet_sklist);
-+      write_unlock_bh(&net->packet_sklist_lock);
-       return(0);
- out:
-       return err;
-@@ -1154,7 +1162,7 @@
-               return -EOPNOTSUPP;
+-              fl.fl_net = &init_net;
+               fl.fl6_flowlabel = 0;
+               fl.oif = sk->sk_bound_dev_if;
  
-       uaddr->sa_family = AF_PACKET;
--      dev = dev_get_by_index(pkt_sk(sk)->ifindex);
-+      dev = dev_get_by_index(sk->sk_net, pkt_sk(sk)->ifindex);
-       if (dev) {
-               strlcpy(uaddr->sa_data, dev->name, 15);
-               dev_put(dev);
-@@ -1179,7 +1187,7 @@
-       sll->sll_family = AF_PACKET;
-       sll->sll_ifindex = po->ifindex;
-       sll->sll_protocol = po->num;
--      dev = dev_get_by_index(po->ifindex);
-+      dev = dev_get_by_index(sk->sk_net, po->ifindex);
-       if (dev) {
-               sll->sll_hatype = dev->type;
-               sll->sll_halen = dev->addr_len;
-@@ -1231,7 +1239,7 @@
-       rtnl_lock();
+@@ -548,7 +547,7 @@
+               if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val)
+                       goto e_inval;
  
-       err = -ENODEV;
--      dev = __dev_get_by_index(mreq->mr_ifindex);
-+      dev = __dev_get_by_index(sk->sk_net, mreq->mr_ifindex);
-       if (!dev)
-               goto done;
+-              if (__dev_get_by_index(&init_net, val) == NULL) {
++              if (__dev_get_by_index(val) == NULL) {
+                       retv = -ENODEV;
+                       break;
+               }
+diff -Nurb linux-2.6.22-590/net/ipv6/mcast.c linux-2.6.22-570/net/ipv6/mcast.c
+--- linux-2.6.22-590/net/ipv6/mcast.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/mcast.c  2007-07-08 19:32:17.000000000 -0400
+@@ -51,7 +51,6 @@
  
-@@ -1285,7 +1293,7 @@
-                       if (--ml->count == 0) {
-                               struct net_device *dev;
-                               *mlp = ml->next;
--                              dev = dev_get_by_index(ml->ifindex);
-+                              dev = dev_get_by_index(sk->sk_net, ml->ifindex);
-                               if (dev) {
-                                       packet_dev_mc(dev, ml, -1);
-                                       dev_put(dev);
-@@ -1313,7 +1321,7 @@
-               struct net_device *dev;
+ #include <net/sock.h>
+ #include <net/snmp.h>
+-#include <net/net_namespace.h>
  
-               po->mclist = ml->next;
--              if ((dev = dev_get_by_index(ml->ifindex)) != NULL) {
-+              if ((dev = dev_get_by_index(sk->sk_net, ml->ifindex)) != NULL) {
-                       packet_dev_mc(dev, ml, -1);
-                       dev_put(dev);
+ #include <net/ipv6.h>
+ #include <net/protocol.h>
+@@ -215,7 +214,7 @@
+                       dst_release(&rt->u.dst);
                }
-@@ -1469,9 +1477,10 @@
-       struct sock *sk;
-       struct hlist_node *node;
-       struct net_device *dev = data;
-+      struct net *net = dev->nd_net;
+       } else
+-              dev = dev_get_by_index(&init_net, ifindex);
++              dev = dev_get_by_index(ifindex);
+       if (dev == NULL) {
+               sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
+@@ -266,7 +265,7 @@
+                       *lnk = mc_lst->next;
+                       write_unlock_bh(&ipv6_sk_mc_lock);
  
--      read_lock(&packet_sklist_lock);
--      sk_for_each(sk, node, &packet_sklist) {
-+      read_lock(&net->packet_sklist_lock);
-+      sk_for_each(sk, node, &net->packet_sklist) {
-               struct packet_sock *po = pkt_sk(sk);
+-                      if ((dev = dev_get_by_index(&init_net, mc_lst->ifindex)) != NULL) {
++                      if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) {
+                               struct inet6_dev *idev = in6_dev_get(dev);
  
-               switch (msg) {
-@@ -1510,7 +1519,7 @@
-                       break;
+                               (void) ip6_mc_leave_src(sk, mc_lst, idev);
+@@ -301,7 +300,7 @@
+                       dst_release(&rt->u.dst);
                }
-       }
--      read_unlock(&packet_sklist_lock);
-+      read_unlock(&net->packet_sklist_lock);
-       return NOTIFY_DONE;
- }
+       } else
+-              dev = dev_get_by_index(&init_net, ifindex);
++              dev = dev_get_by_index(ifindex);
  
-@@ -1878,12 +1887,12 @@
- };
+       if (!dev)
+               return NULL;
+@@ -332,7 +331,7 @@
+               np->ipv6_mc_list = mc_lst->next;
+               write_unlock_bh(&ipv6_sk_mc_lock);
+-              dev = dev_get_by_index(&init_net, mc_lst->ifindex);
++              dev = dev_get_by_index(mc_lst->ifindex);
+               if (dev) {
+                       struct inet6_dev *idev = in6_dev_get(dev);
+@@ -2333,7 +2332,7 @@
+       struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
+       state->idev = NULL;
+-      for_each_netdev(&init_net, state->dev) {
++      for_each_netdev(state->dev) {
+               struct inet6_dev *idev;
+               idev = in6_dev_get(state->dev);
+               if (!idev)
+@@ -2477,7 +2476,7 @@
+       state->idev = NULL;
+       state->im = NULL;
+-      for_each_netdev(&init_net, state->dev) {
++      for_each_netdev(state->dev) {
+               struct inet6_dev *idev;
+               idev = in6_dev_get(state->dev);
+               if (unlikely(idev == NULL))
+@@ -2659,8 +2658,8 @@
+       np->hop_limit = 1;
  
  #ifdef CONFIG_PROC_FS
--static inline struct sock *packet_seq_idx(loff_t off)
-+static inline struct sock *packet_seq_idx(struct net *net, loff_t off)
- {
-       struct sock *s;
-       struct hlist_node *node;
+-      proc_net_fops_create(&init_net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops);
+-      proc_net_fops_create(&init_net, "mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops);
++      proc_net_fops_create("igmp6", S_IRUGO, &igmp6_mc_seq_fops);
++      proc_net_fops_create("mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops);
+ #endif
  
--      sk_for_each(s, node, &packet_sklist) {
-+      sk_for_each(s, node, &net->packet_sklist) {
-               if (!off--)
-                       return s;
-       }
-@@ -1892,21 +1901,24 @@
+       return 0;
+@@ -2672,7 +2671,7 @@
+       igmp6_socket = NULL; /* for safety */
  
- static void *packet_seq_start(struct seq_file *seq, loff_t *pos)
- {
--      read_lock(&packet_sklist_lock);
--      return *pos ? packet_seq_idx(*pos - 1) : SEQ_START_TOKEN;
-+      struct net *net = seq->private;
-+      read_lock(&net->packet_sklist_lock);
-+      return *pos ? packet_seq_idx(net, *pos - 1) : SEQ_START_TOKEN;
+ #ifdef CONFIG_PROC_FS
+-      proc_net_remove(&init_net, "mcfilter6");
+-      proc_net_remove(&init_net, "igmp6");
++      proc_net_remove("mcfilter6");
++      proc_net_remove("igmp6");
+ #endif
  }
+diff -Nurb linux-2.6.22-590/net/ipv6/mip6.c linux-2.6.22-570/net/ipv6/mip6.c
+--- linux-2.6.22-590/net/ipv6/mip6.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/mip6.c   2007-07-08 19:32:17.000000000 -0400
+@@ -30,7 +30,6 @@
+ #include <net/sock.h>
+ #include <net/ipv6.h>
+ #include <net/ip6_checksum.h>
+-#include <net/rawv6.h>
+ #include <net/xfrm.h>
+ #include <net/mip6.h>
  
- static void *packet_seq_next(struct seq_file *seq, void *v, loff_t *pos)
- {
-+      struct net *net = seq->private;
-       ++*pos;
-       return  (v == SEQ_START_TOKEN)
--              ? sk_head(&packet_sklist)
-+              ? sk_head(&net->packet_sklist)
-               : sk_next((struct sock*)v) ;
+@@ -87,7 +86,7 @@
+       return len;
  }
  
- static void packet_seq_stop(struct seq_file *seq, void *v)
+-static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
++int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
  {
--      read_unlock(&packet_sklist_lock);
-+      struct net *net = seq->private;
-+      read_unlock(&net->packet_sklist_lock);
- }
+       struct ip6_mh *mh;
  
- static int packet_seq_show(struct seq_file *seq, void *v)
-@@ -1942,7 +1954,22 @@
+@@ -472,7 +471,7 @@
+       .remote_addr    = mip6_xfrm_addr,
+ };
  
- static int packet_seq_open(struct inode *inode, struct file *file)
+-static int __init mip6_init(void)
++int __init mip6_init(void)
  {
--      return seq_open(file, &packet_seq_ops);
-+      struct seq_file *seq;
-+      int res;
-+      res = seq_open(file, &packet_seq_ops);
-+      if (!res) {
-+              seq = file->private_data;
-+              seq->private = get_net(PROC_NET(inode));
-+      }
-+      return res;
-+}
-+
-+static int packet_seq_release(struct inode *inode, struct file *file)
-+{
-+      struct seq_file *seq=  file->private_data;
-+      struct net *net = seq->private;
-+      put_net(net);
-+      return seq_release(inode, file);
- }
- static const struct file_operations packet_seq_fops = {
-@@ -1950,15 +1977,37 @@
-       .open           = packet_seq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
--      .release        = seq_release,
-+      .release        = packet_seq_release,
- };
+       printk(KERN_INFO "Mobile IPv6\n");
  
- #endif
+@@ -484,35 +483,18 @@
+               printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__);
+               goto mip6_rthdr_xfrm_fail;
+       }
+-      if (rawv6_mh_filter_register(mip6_mh_filter) < 0) {
+-              printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__);
+-              goto mip6_rawv6_mh_fail;
+-      }
+-
+-
+       return 0;
  
-+static int packet_net_init(struct net *net)
-+{
-+      rwlock_init(&net->packet_sklist_lock);
-+      INIT_HLIST_HEAD(&net->packet_sklist);
-+
-+      if (!proc_net_fops_create(net, "packet", 0, &packet_seq_fops))
-+              return -ENOMEM;
-+
-+      return 0;
-+}
-+
-+static void packet_net_exit(struct net *net)
-+{
-+      proc_net_remove(net, "packet");
-+}
-+
-+static struct pernet_operations packet_net_ops = {
-+      .init = packet_net_init,
-+      .exit = packet_net_exit,
-+};
-+
-+
- static void __exit packet_exit(void)
- {
--      proc_net_remove("packet");
-       unregister_netdevice_notifier(&packet_netdev_notifier);
-+      unregister_pernet_subsys(&packet_net_ops);
-       sock_unregister(PF_PACKET);
-       proto_unregister(&packet_proto);
+- mip6_rawv6_mh_fail:
+-      xfrm_unregister_type(&mip6_rthdr_type, AF_INET6);
+  mip6_rthdr_xfrm_fail:
+       xfrm_unregister_type(&mip6_destopt_type, AF_INET6);
+  mip6_destopt_xfrm_fail:
+       return -EAGAIN;
  }
-@@ -1971,8 +2020,8 @@
-               goto out;
  
-       sock_register(&packet_family_ops);
-+      register_pernet_subsys(&packet_net_ops);
-       register_netdevice_notifier(&packet_netdev_notifier);
--      proc_net_fops_create("packet", 0, &packet_seq_fops);
- out:
-       return rc;
+-static void __exit mip6_fini(void)
++void __exit mip6_fini(void)
+ {
+-      if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0)
+-              printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__);
+       if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
+               printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__);
+       if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
+               printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__);
  }
-diff -Nurb linux-2.6.22-570/net/rose/af_rose.c linux-2.6.22-590/net/rose/af_rose.c
---- linux-2.6.22-570/net/rose/af_rose.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/rose/af_rose.c        2008-01-02 13:56:38.000000000 -0500
-@@ -45,6 +45,7 @@
- #include <net/tcp_states.h>
- #include <net/ip.h>
- #include <net/arp.h>
-+#include <net/net_namespace.h>
- static int rose_ndevs = 10;
+-
+-module_init(mip6_init);
+-module_exit(mip6_fini);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_DSTOPTS);
+-MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ROUTING);
+diff -Nurb linux-2.6.22-590/net/ipv6/ndisc.c linux-2.6.22-570/net/ipv6/ndisc.c
+--- linux-2.6.22-590/net/ipv6/ndisc.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/ndisc.c  2008-01-23 19:16:05.000000000 -0500
+@@ -418,7 +418,6 @@
+                           int oif)
+ {
+       memset(fl, 0, sizeof(*fl));
+-      fl->fl_net = &init_net;
+       ipv6_addr_copy(&fl->fl6_src, saddr);
+       ipv6_addr_copy(&fl->fl6_dst, daddr);
+       fl->proto               = IPPROTO_ICMPV6;
+@@ -761,7 +760,7 @@
+               if (ipv6_chk_acast_addr(dev, &msg->target) ||
+                   (idev->cnf.forwarding &&
+                    (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) &&
+-                   (pneigh = pneigh_lookup(&nd_tbl, &init_net,
++                   (pneigh = pneigh_lookup(&nd_tbl,
+                                            &msg->target, dev, 0)) != NULL)) {
+                       if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
+                           skb->pkt_type != PACKET_HOST &&
+@@ -902,7 +901,7 @@
+                */
+               if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
+                   ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp &&
+-                  pneigh_lookup(&nd_tbl, &init_net, &msg->target, dev, 0)) {
++                  pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
+                       /* XXX: idev->cnf.prixy_ndp */
+                       goto out;
+               }
+@@ -1526,9 +1525,6 @@
+ {
+       struct net_device *dev = ptr;
  
-@@ -196,6 +197,9 @@
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       switch (event) {
+       case NETDEV_CHANGEADDR:
+               neigh_changeaddr(&nd_tbl, dev);
+diff -Nurb linux-2.6.22-590/net/ipv6/netfilter/ip6_queue.c linux-2.6.22-570/net/ipv6/netfilter/ip6_queue.c
+--- linux-2.6.22-590/net/ipv6/netfilter/ip6_queue.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/netfilter/ip6_queue.c    2007-07-08 19:32:17.000000000 -0400
+@@ -24,7 +24,6 @@
+ #include <linux/sysctl.h>
+ #include <linux/proc_fs.h>
+ #include <linux/mutex.h>
+-#include <net/net_namespace.h>
+ #include <net/sock.h>
+ #include <net/ipv6.h>
+ #include <net/ip6_route.h>
+@@ -547,9 +546,6 @@
  {
-       struct net_device *dev = (struct net_device *)ptr;
+       struct net_device *dev = ptr;
  
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
-       if (event != NETDEV_DOWN)
-               return NOTIFY_DONE;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
+       /* Drop any packets associated with the downed device */
+       if (event == NETDEV_DOWN)
+               ipq_dev_drop(dev->ifindex);
+@@ -569,7 +565,7 @@
+       if (event == NETLINK_URELEASE &&
+           n->protocol == NETLINK_IP6_FW && n->pid) {
+               write_lock_bh(&queue_lock);
+-              if ((n->net == &init_net) && (n->pid == peer_pid))
++              if (n->pid == peer_pid)
+                       __ipq_reset();
+               write_unlock_bh(&queue_lock);
+       }
+@@ -661,14 +657,14 @@
+       struct proc_dir_entry *proc;
  
-@@ -498,15 +502,18 @@
-       .obj_size = sizeof(struct rose_sock),
- };
+       netlink_register_notifier(&ipq_nl_notifier);
+-      ipqnl = netlink_kernel_create(&init_net, NETLINK_IP6_FW, 0, ipq_rcv_sk,
+-                                      NULL, THIS_MODULE);
++      ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk, NULL,
++                                    THIS_MODULE);
+       if (ipqnl == NULL) {
+               printk(KERN_ERR "ip6_queue: failed to create netlink socket\n");
+               goto cleanup_netlink_notifier;
+       }
  
--static int rose_create(struct socket *sock, int protocol)
-+static int rose_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct sock *sk;
-       struct rose_sock *rose;
+-      proc = proc_net_create(&init_net, IPQ_PROC_FS_NAME, 0, ipq_get_info);
++      proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ipq_get_info);
+       if (proc)
+               proc->owner = THIS_MODULE;
+       else {
+@@ -689,7 +685,7 @@
+ cleanup_sysctl:
+       unregister_sysctl_table(ipq_sysctl_header);
+       unregister_netdevice_notifier(&ipq_dev_notifier);
+-      proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
++      proc_net_remove(IPQ_PROC_FS_NAME);
  
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
-+
-       if (sock->type != SOCK_SEQPACKET || protocol != 0)
-               return -ESOCKTNOSUPPORT;
+ cleanup_ipqnl:
+       sock_release(ipqnl->sk_socket);
+@@ -709,7 +705,7 @@
  
--      if ((sk = sk_alloc(PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
-+      if ((sk = sk_alloc(net, PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
-               return -ENOMEM;
+       unregister_sysctl_table(ipq_sysctl_header);
+       unregister_netdevice_notifier(&ipq_dev_notifier);
+-      proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
++      proc_net_remove(IPQ_PROC_FS_NAME);
  
-       rose = rose_sk(sk);
-@@ -544,7 +551,7 @@
-       if (osk->sk_type != SOCK_SEQPACKET)
-               return NULL;
+       sock_release(ipqnl->sk_socket);
+       mutex_lock(&ipqnl_mutex);
+diff -Nurb linux-2.6.22-590/net/ipv6/netfilter/ip6_tables.c linux-2.6.22-570/net/ipv6/netfilter/ip6_tables.c
+--- linux-2.6.22-590/net/ipv6/netfilter/ip6_tables.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/netfilter/ip6_tables.c   2007-07-08 19:32:17.000000000 -0400
+@@ -906,7 +906,7 @@
+       int ret;
+       struct xt_table *t;
  
--      if ((sk = sk_alloc(PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
-+      if ((sk = sk_alloc(osk->sk_net, PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
-               return NULL;
+-      t = xt_find_table_lock(&init_net, AF_INET6, entries->name);
++      t = xt_find_table_lock(AF_INET6, entries->name);
+       if (t && !IS_ERR(t)) {
+               struct xt_table_info *private = t->private;
+               duprintf("t->private->number = %u\n", private->number);
+@@ -972,7 +972,7 @@
  
-       rose = rose_sk(sk);
-@@ -1576,10 +1583,10 @@
+       duprintf("ip_tables: Translated table\n");
  
-       rose_add_loopback_neigh();
+-      t = try_then_request_module(xt_find_table_lock(&init_net, AF_INET6, tmp.name),
++      t = try_then_request_module(xt_find_table_lock(AF_INET6, tmp.name),
+                                   "ip6table_%s", tmp.name);
+       if (!t || IS_ERR(t)) {
+               ret = t ? PTR_ERR(t) : -ENOENT;
+@@ -1073,7 +1073,7 @@
+               goto free;
+       }
  
--      proc_net_fops_create("rose", S_IRUGO, &rose_info_fops);
--      proc_net_fops_create("rose_neigh", S_IRUGO, &rose_neigh_fops);
--      proc_net_fops_create("rose_nodes", S_IRUGO, &rose_nodes_fops);
--      proc_net_fops_create("rose_routes", S_IRUGO, &rose_routes_fops);
-+      proc_net_fops_create(&init_net, "rose", S_IRUGO, &rose_info_fops);
-+      proc_net_fops_create(&init_net, "rose_neigh", S_IRUGO, &rose_neigh_fops);
-+      proc_net_fops_create(&init_net, "rose_nodes", S_IRUGO, &rose_nodes_fops);
-+      proc_net_fops_create(&init_net, "rose_routes", S_IRUGO, &rose_routes_fops);
- out:
-       return rc;
- fail:
-@@ -1606,10 +1613,10 @@
+-      t = xt_find_table_lock(&init_net, AF_INET6, tmp.name);
++      t = xt_find_table_lock(AF_INET6, tmp.name);
+       if (!t || IS_ERR(t)) {
+               ret = t ? PTR_ERR(t) : -ENOENT;
+               goto free;
+@@ -1109,9 +1109,6 @@
  {
-       int i;
+       int ret;
  
--      proc_net_remove("rose");
--      proc_net_remove("rose_neigh");
--      proc_net_remove("rose_nodes");
--      proc_net_remove("rose_routes");
-+      proc_net_remove(&init_net, "rose");
-+      proc_net_remove(&init_net, "rose_neigh");
-+      proc_net_remove(&init_net, "rose_nodes");
-+      proc_net_remove(&init_net, "rose_routes");
-       rose_loopback_clear();
+-      if (sk->sk_net != &init_net)
+-              return -ENOPROTOOPT;
+-
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
  
-       rose_rt_free();
-diff -Nurb linux-2.6.22-570/net/rose/rose_route.c linux-2.6.22-590/net/rose/rose_route.c
---- linux-2.6.22-570/net/rose/rose_route.c     2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/rose/rose_route.c     2008-01-02 13:56:38.000000000 -0500
-@@ -583,7 +583,7 @@
+@@ -1137,9 +1134,6 @@
  {
-       struct net_device *dev;
--      if ((dev = dev_get_by_name(devname)) == NULL)
-+      if ((dev = dev_get_by_name(&init_net, devname)) == NULL)
-               return NULL;
-       if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)
-@@ -601,7 +601,7 @@
-       struct net_device *dev, *first = NULL;
+       int ret;
  
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE)
-                       if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
-                               first = dev;
-@@ -619,7 +619,7 @@
-       struct net_device *dev;
+-      if (sk->sk_net != &init_net)
+-              return -ENOPROTOOPT;
+-
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
  
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) {
-                       dev_hold(dev);
-                       goto out;
-@@ -636,7 +636,7 @@
-       struct net_device *dev;
+@@ -1161,7 +1155,7 @@
+               }
+               name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
  
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0)
-                       goto out;
+-              t = try_then_request_module(xt_find_table_lock(&init_net, AF_INET6, name),
++              t = try_then_request_module(xt_find_table_lock(AF_INET6, name),
+                                           "ip6table_%s", name);
+               if (t && !IS_ERR(t)) {
+                       struct ip6t_getinfo info;
+@@ -1265,7 +1259,7 @@
+               return ret;
        }
-diff -Nurb linux-2.6.22-570/net/rxrpc/af_rxrpc.c linux-2.6.22-590/net/rxrpc/af_rxrpc.c
---- linux-2.6.22-570/net/rxrpc/af_rxrpc.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/rxrpc/af_rxrpc.c      2008-01-02 13:56:38.000000000 -0500
-@@ -14,6 +14,7 @@
- #include <linux/skbuff.h>
- #include <linux/poll.h>
- #include <linux/proc_fs.h>
-+#include <net/net_namespace.h>
- #include <net/sock.h>
- #include <net/af_rxrpc.h>
- #include "ar-internal.h"
-@@ -605,13 +606,16 @@
- /*
-  * create an RxRPC socket
-  */
--static int rxrpc_create(struct socket *sock, int protocol)
-+static int rxrpc_create(struct net *net, struct socket *sock, int protocol)
- {
-       struct rxrpc_sock *rx;
-       struct sock *sk;
-       _enter("%p,%d", sock, protocol);
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
-+
-       /* we support transport protocol UDP only */
-       if (protocol != PF_INET)
-               return -EPROTONOSUPPORT;
-@@ -622,7 +626,7 @@
-       sock->ops = &rxrpc_rpc_ops;
-       sock->state = SS_UNCONNECTED;
--      sk = sk_alloc(PF_RXRPC, GFP_KERNEL, &rxrpc_proto, 1);
-+      sk = sk_alloc(net, PF_RXRPC, GFP_KERNEL, &rxrpc_proto, 1);
-       if (!sk)
-               return -ENOMEM;
  
-@@ -829,8 +833,8 @@
+-      ret = xt_register_table(&init_net, table, &bootstrap, newinfo);
++      ret = xt_register_table(table, &bootstrap, newinfo);
+       if (ret != 0) {
+               xt_free_table_info(newinfo);
+               return ret;
+diff -Nurb linux-2.6.22-590/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.22-570/net/ipv6/netfilter/ip6t_REJECT.c
+--- linux-2.6.22-590/net/ipv6/netfilter/ip6t_REJECT.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/netfilter/ip6t_REJECT.c  2007-07-08 19:32:17.000000000 -0400
+@@ -92,7 +92,6 @@
        }
  
- #ifdef CONFIG_PROC_FS
--      proc_net_fops_create("rxrpc_calls", 0, &rxrpc_call_seq_fops);
--      proc_net_fops_create("rxrpc_conns", 0, &rxrpc_connection_seq_fops);
-+      proc_net_fops_create(&init_net, "rxrpc_calls", 0, &rxrpc_call_seq_fops);
-+      proc_net_fops_create(&init_net, "rxrpc_conns", 0, &rxrpc_connection_seq_fops);
- #endif
-       return 0;
-@@ -868,8 +872,8 @@
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       fl.proto = IPPROTO_TCP;
+       ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
+       ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
+@@ -173,7 +172,7 @@
+ send_unreach(struct sk_buff *skb_in, unsigned char code, unsigned int hooknum)
+ {
+       if (hooknum == NF_IP6_LOCAL_OUT && skb_in->dev == NULL)
+-              skb_in->dev = &init_net.loopback_dev;
++              skb_in->dev = &loopback_dev;
  
-       _debug("flush scheduled work");
-       flush_workqueue(rxrpc_workqueue);
--      proc_net_remove("rxrpc_conns");
--      proc_net_remove("rxrpc_calls");
-+      proc_net_remove(&init_net, "rxrpc_conns");
-+      proc_net_remove(&init_net, "rxrpc_calls");
-       destroy_workqueue(rxrpc_workqueue);
-       kmem_cache_destroy(rxrpc_call_jar);
-       _leave("");
-diff -Nurb linux-2.6.22-570/net/sched/act_api.c linux-2.6.22-590/net/sched/act_api.c
---- linux-2.6.22-570/net/sched/act_api.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sched/act_api.c       2008-01-02 13:56:38.000000000 -0500
-@@ -27,6 +27,7 @@
- #include <linux/skbuff.h>
- #include <linux/init.h>
- #include <linux/kmod.h>
-+#include <net/net_namespace.h>
- #include <net/sock.h>
- #include <net/sch_generic.h>
- #include <net/act_api.h>
-@@ -675,7 +676,7 @@
-               return -EINVAL;
-       }
+       icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL);
+ }
+diff -Nurb linux-2.6.22-590/net/ipv6/netfilter/ip6table_filter.c linux-2.6.22-570/net/ipv6/netfilter/ip6table_filter.c
+--- linux-2.6.22-590/net/ipv6/netfilter/ip6table_filter.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/netfilter/ip6table_filter.c      2007-07-08 19:32:17.000000000 -0400
+@@ -65,10 +65,6 @@
+        const struct net_device *out,
+        int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
+       return ip6t_do_table(pskb, hook, in, out, &packet_filter);
+ }
  
--      return rtnl_unicast(skb, pid);
-+      return rtnl_unicast(skb, &init_net, pid);
+@@ -79,10 +75,6 @@
+                  const struct net_device *out,
+                  int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
+ #if 0
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr)
+diff -Nurb linux-2.6.22-590/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.22-570/net/ipv6/netfilter/ip6table_mangle.c
+--- linux-2.6.22-590/net/ipv6/netfilter/ip6table_mangle.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/netfilter/ip6table_mangle.c      2007-07-08 19:32:17.000000000 -0400
+@@ -79,10 +79,6 @@
+        const struct net_device *out,
+        int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
+       return ip6t_do_table(pskb, hook, in, out, &packet_mangler);
  }
  
- static struct tc_action *
-@@ -796,7 +797,7 @@
-       nlh->nlmsg_flags |= NLM_F_ROOT;
-       module_put(a->ops->owner);
-       kfree(a);
--      err = rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
-+      err = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
-       if (err > 0)
-               return 0;
+@@ -99,10 +95,6 @@
+       u_int8_t hop_limit;
+       u_int32_t flowlabel, mark;
  
-@@ -859,7 +860,7 @@
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
+ #if 0
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr)
+diff -Nurb linux-2.6.22-590/net/ipv6/netfilter/ip6table_raw.c linux-2.6.22-570/net/ipv6/netfilter/ip6table_raw.c
+--- linux-2.6.22-590/net/ipv6/netfilter/ip6table_raw.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/netfilter/ip6table_raw.c 2007-07-08 19:32:17.000000000 -0400
+@@ -57,10 +57,6 @@
+        const struct net_device *out,
+        int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
+       return ip6t_do_table(pskb, hook, in, out, &packet_raw);
+ }
  
-               /* now do the delete */
-               tcf_action_destroy(head, 0);
--              ret = rtnetlink_send(skb, pid, RTNLGRP_TC,
-+              ret = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC,
-                                    n->nlmsg_flags&NLM_F_ECHO);
-               if (ret > 0)
-                       return 0;
-@@ -903,7 +904,7 @@
-       nlh->nlmsg_len = skb_tail_pointer(skb) - b;
-       NETLINK_CB(skb).dst_group = RTNLGRP_TC;
+diff -Nurb linux-2.6.22-590/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c linux-2.6.22-570/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+--- linux-2.6.22-590/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c    2007-07-08 19:32:17.000000000 -0400
+@@ -167,10 +167,6 @@
+       unsigned char pnum = ipv6_hdr(*pskb)->nexthdr;
  
--      err = rtnetlink_send(skb, pid, RTNLGRP_TC, flags&NLM_F_ECHO);
-+      err = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, flags&NLM_F_ECHO);
-       if (err > 0)
-               err = 0;
-       return err;
-@@ -941,10 +942,14 @@
  
- static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
+       /* This is where we call the helper: as the packet goes out. */
+       ct = nf_ct_get(*pskb, &ctinfo);
+       if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
+@@ -207,10 +203,6 @@
  {
-+      struct net *net = skb->sk->sk_net;
-       struct rtattr **tca = arg;
-       u32 pid = skb ? NETLINK_CB(skb).pid : 0;
-       int ret = 0, ovr = 0;
+       struct sk_buff *reasm;
  
-+      if (net != &init_net)
-+              return -EINVAL;
-+
-       if (tca[TCA_ACT_TAB-1] == NULL) {
-               printk("tc_ctl_action: received NO action attribs\n");
-               return -EINVAL;
-@@ -1014,6 +1019,7 @@
- static int
- tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
+       /* Previously seen (loopback)?  */
+       if ((*pskb)->nfct)
+               return NF_ACCEPT;
+@@ -239,10 +231,6 @@
  {
-+      struct net *net = skb->sk->sk_net;
-       struct nlmsghdr *nlh;
-       unsigned char *b = skb_tail_pointer(skb);
-       struct rtattr *x;
-@@ -1023,6 +1029,9 @@
-       struct tcamsg *t = (struct tcamsg *) NLMSG_DATA(cb->nlh);
-       struct rtattr *kind = find_dump_kind(cb->nlh);
+       struct sk_buff *reasm = (*pskb)->nfct_reasm;
  
-+      if (net != &init_net)
-+              return 0;
-+
-       if (kind == NULL) {
-               printk("tc_dump_action: action bad kind\n");
-               return 0;
-diff -Nurb linux-2.6.22-570/net/sched/act_mirred.c linux-2.6.22-590/net/sched/act_mirred.c
---- linux-2.6.22-570/net/sched/act_mirred.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sched/act_mirred.c    2008-01-02 13:56:38.000000000 -0500
-@@ -85,7 +85,7 @@
-       parm = RTA_DATA(tb[TCA_MIRRED_PARMS-1]);
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
+       /* This packet is fragmented and has reassembled packet. */
+       if (reasm) {
+               /* Reassembled packet isn't parsed yet ? */
+@@ -268,10 +256,6 @@
+                                        const struct net_device *out,
+                                        int (*okfn)(struct sk_buff *))
+ {
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct ipv6hdr)) {
+               if (net_ratelimit())
+diff -Nurb linux-2.6.22-590/net/ipv6/netfilter.c linux-2.6.22-570/net/ipv6/netfilter.c
+--- linux-2.6.22-590/net/ipv6/netfilter.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/netfilter.c      2007-07-08 19:32:17.000000000 -0400
+@@ -14,7 +14,6 @@
+       struct ipv6hdr *iph = ipv6_hdr(skb);
+       struct dst_entry *dst;
+       struct flowi fl = {
+-              .fl_net = &init_net,
+               .oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
+               .mark = skb->mark,
+               .nl_u =
+diff -Nurb linux-2.6.22-590/net/ipv6/proc.c linux-2.6.22-570/net/ipv6/proc.c
+--- linux-2.6.22-590/net/ipv6/proc.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/proc.c   2007-07-08 19:32:17.000000000 -0400
+@@ -28,7 +28,6 @@
+ #include <net/tcp.h>
+ #include <net/transp_v6.h>
+ #include <net/ipv6.h>
+-#include <net/net_namespace.h>
  
-       if (parm->ifindex) {
--              dev = __dev_get_by_index(parm->ifindex);
-+              dev = __dev_get_by_index(&init_net, parm->ifindex);
-               if (dev == NULL)
-                       return -ENODEV;
-               switch (dev->type) {
-diff -Nurb linux-2.6.22-570/net/sched/cls_api.c linux-2.6.22-590/net/sched/cls_api.c
---- linux-2.6.22-570/net/sched/cls_api.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sched/cls_api.c       2008-01-02 13:56:38.000000000 -0500
-@@ -129,6 +129,7 @@
+ static struct proc_dir_entry *proc_net_devsnmp6;
  
- static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+@@ -232,22 +231,22 @@
  {
-+      struct net *net = skb->sk->sk_net;
-       struct rtattr **tca;
-       struct tcmsg *t;
-       u32 protocol;
-@@ -145,6 +146,9 @@
-       unsigned long fh;
-       int err;
+       int rc = 0;
  
-+      if (net != &init_net)
-+              return -EINVAL;
-+
- replay:
-       tca = arg;
-       t = NLMSG_DATA(n);
-@@ -164,7 +168,7 @@
-       /* Find head of filter chain. */
+-      if (!proc_net_fops_create(&init_net, "snmp6", S_IRUGO, &snmp6_seq_fops))
++      if (!proc_net_fops_create("snmp6", S_IRUGO, &snmp6_seq_fops))
+               goto proc_snmp6_fail;
  
-       /* Find link */
--      if ((dev = __dev_get_by_index(t->tcm_ifindex)) == NULL)
-+      if ((dev = __dev_get_by_index(&init_net, t->tcm_ifindex)) == NULL)
-               return -ENODEV;
+-      proc_net_devsnmp6 = proc_mkdir("dev_snmp6", init_net.proc_net);
++      proc_net_devsnmp6 = proc_mkdir("dev_snmp6", proc_net);
+       if (!proc_net_devsnmp6)
+               goto proc_dev_snmp6_fail;
  
-       /* Find qdisc */
-@@ -365,7 +369,7 @@
-               return -EINVAL;
-       }
+-      if (!proc_net_fops_create(&init_net, "sockstat6", S_IRUGO, &sockstat6_seq_fops))
++      if (!proc_net_fops_create("sockstat6", S_IRUGO, &sockstat6_seq_fops))
+               goto proc_sockstat6_fail;
+ out:
+       return rc;
+ proc_sockstat6_fail:
+-      proc_net_remove(&init_net, "dev_snmp6");
++      proc_net_remove("dev_snmp6");
+ proc_dev_snmp6_fail:
+-      proc_net_remove(&init_net, "snmp6");
++      proc_net_remove("snmp6");
+ proc_snmp6_fail:
+       rc = -ENOMEM;
+       goto out;
+@@ -255,8 +254,8 @@
  
--      return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
-+      return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ void ipv6_misc_proc_exit(void)
+ {
+-      proc_net_remove(&init_net, "sockstat6");
+-      proc_net_remove(&init_net, "dev_snmp6");
+-      proc_net_remove(&init_net, "snmp6");
++      proc_net_remove("sockstat6");
++      proc_net_remove("dev_snmp6");
++      proc_net_remove("snmp6");
  }
  
- struct tcf_dump_args
-@@ -385,6 +389,7 @@
+diff -Nurb linux-2.6.22-590/net/ipv6/raw.c linux-2.6.22-570/net/ipv6/raw.c
+--- linux-2.6.22-590/net/ipv6/raw.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/raw.c    2008-01-23 19:15:56.000000000 -0500
+@@ -49,8 +49,7 @@
+ #include <net/udp.h>
+ #include <net/inet_common.h>
+ #include <net/tcp_states.h>
+-#include <net/net_namespace.h>
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+ #include <net/mip6.h>
+ #endif
  
- static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
- {
-+      struct net *net = skb->sk->sk_net;
-       int t;
-       int s_t;
-       struct net_device *dev;
-@@ -395,9 +400,12 @@
-       struct Qdisc_class_ops *cops;
-       struct tcf_dump_args arg;
+@@ -138,28 +137,6 @@
+       return 0;
+ }
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+-static int (*mh_filter)(struct sock *sock, struct sk_buff *skb);
+-
+-int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
+-                                         struct sk_buff *skb))
+-{
+-      rcu_assign_pointer(mh_filter, filter);
+-      return 0;
+-}
+-EXPORT_SYMBOL(rawv6_mh_filter_register);
+-
+-int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
+-                                           struct sk_buff *skb))
+-{
+-      rcu_assign_pointer(mh_filter, NULL);
+-      synchronize_rcu();
+-      return 0;
+-}
+-EXPORT_SYMBOL(rawv6_mh_filter_unregister);
+-
+-#endif
+-
+ /*
+  *    demultiplex raw sockets.
+  *    (should consider queueing the skb in the sock receive_queue
+@@ -201,22 +178,16 @@
+               case IPPROTO_ICMPV6:
+                       filtered = icmpv6_filter(sk, skb);
+                       break;
+-
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+               case IPPROTO_MH:
+-              {
+                       /* XXX: To validate MH only once for each packet,
+                        * this is placed here. It should be after checking
+                        * xfrm policy, however it doesn't. The checking xfrm
+                        * policy is placed in rawv6_rcv() because it is
+                        * required for each socket.
+                        */
+-                      int (*filter)(struct sock *sock, struct sk_buff *skb);
+-
+-                      filter = rcu_dereference(mh_filter);
+-                      filtered = filter ? filter(sk, skb) : 0;
++                      filtered = mip6_mh_filter(sk, skb);
+                       break;
+-              }
+ #endif
+               default:
+                       filtered = 0;
+@@ -283,7 +254,7 @@
+                       if (!sk->sk_bound_dev_if)
+                               goto out;
  
-+      if (net != &init_net)
-+              return 0;
-+
-       if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm)))
-               return skb->len;
--      if ((dev = dev_get_by_index(tcm->tcm_ifindex)) == NULL)
-+      if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
-               return skb->len;
+-                      dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
++                      dev = dev_get_by_index(sk->sk_bound_dev_if);
+                       if (!dev) {
+                               err = -ENODEV;
+                               goto out;
+@@ -640,7 +611,9 @@
+       struct iovec *iov;
+       u8 __user *type = NULL;
+       u8 __user *code = NULL;
++#ifdef CONFIG_IPV6_MIP6
+       u8 len = 0;
++#endif
+       int probed = 0;
+       int i;
  
-       if (!tcm->tcm_parent)
-diff -Nurb linux-2.6.22-570/net/sched/em_meta.c linux-2.6.22-590/net/sched/em_meta.c
---- linux-2.6.22-570/net/sched/em_meta.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sched/em_meta.c       2008-01-02 13:56:38.000000000 -0500
-@@ -291,7 +291,7 @@
-        } else  {
-               struct net_device *dev;
+@@ -673,6 +646,7 @@
+                               probed = 1;
+                       }
+                       break;
++#ifdef CONFIG_IPV6_MIP6
+               case IPPROTO_MH:
+                       if (iov->iov_base && iov->iov_len < 1)
+                               break;
+@@ -686,6 +660,7 @@
+                               len += iov->iov_len;
  
--              dev = dev_get_by_index(skb->sk->sk_bound_dev_if);
-+              dev = dev_get_by_index(&init_net, skb->sk->sk_bound_dev_if);
-               *err = var_dev(dev, dst);
-               if (dev)
-                       dev_put(dev);
-diff -Nurb linux-2.6.22-570/net/sched/sch_api.c linux-2.6.22-590/net/sched/sch_api.c
---- linux-2.6.22-570/net/sched/sch_api.c       2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/sched/sch_api.c       2008-01-02 13:56:38.000000000 -0500
-@@ -35,6 +35,7 @@
- #include <linux/bitops.h>
- #include <linux/hrtimer.h>
+                       break;
++#endif
+               default:
+                       probed = 1;
+                       break;
+@@ -729,7 +704,6 @@
+        *      Get and verify the address.
+        */
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
  
-+#include <net/net_namespace.h>
- #include <net/netlink.h>
- #include <net/sock.h>
- #include <net/pkt_sched.h>
-@@ -609,6 +610,7 @@
+       if (sin6) {
+               if (addr_len < SIN6_LEN_RFC2133)
+@@ -1317,13 +1291,13 @@
  
static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
int __init raw6_proc_init(void)
  {
-+      struct net *net = skb->sk->sk_net;
-       struct tcmsg *tcm = NLMSG_DATA(n);
-       struct rtattr **tca = arg;
-       struct net_device *dev;
-@@ -617,7 +619,10 @@
-       struct Qdisc *p = NULL;
-       int err;
--      if ((dev = __dev_get_by_index(tcm->tcm_ifindex)) == NULL)
-+      if (net != &init_net)
-+              return -EINVAL;
-+
-+      if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
-               return -ENODEV;
-       if (clid) {
-@@ -670,6 +675,7 @@
+-      if (!proc_net_fops_create(&init_net, "raw6", S_IRUGO, &raw6_seq_fops))
++      if (!proc_net_fops_create("raw6", S_IRUGO, &raw6_seq_fops))
+               return -ENOMEM;
+       return 0;
+ }
  
static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
void raw6_proc_exit(void)
  {
-+      struct net *net = skb->sk->sk_net;
-       struct tcmsg *tcm;
-       struct rtattr **tca;
-       struct net_device *dev;
-@@ -677,6 +683,9 @@
-       struct Qdisc *q, *p;
-       int err;
+-      proc_net_remove(&init_net, "raw6");
++      proc_net_remove("raw6");
+ }
+ #endif        /* CONFIG_PROC_FS */
+diff -Nurb linux-2.6.22-590/net/ipv6/reassembly.c linux-2.6.22-570/net/ipv6/reassembly.c
+--- linux-2.6.22-590/net/ipv6/reassembly.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/reassembly.c     2007-07-08 19:32:17.000000000 -0400
+@@ -301,7 +301,7 @@
  
-+      if (net != &init_net)
-+              return -EINVAL;
-+
- replay:
-       /* Reinit, just in case something touches this. */
-       tcm = NLMSG_DATA(n);
-@@ -684,7 +693,7 @@
-       clid = tcm->tcm_parent;
-       q = p = NULL;
+       fq_kill(fq);
  
--      if ((dev = __dev_get_by_index(tcm->tcm_ifindex)) == NULL)
-+      if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
-               return -ENODEV;
+-      dev = dev_get_by_index(&init_net, fq->iif);
++      dev = dev_get_by_index(fq->iif);
+       if (!dev)
+               goto out;
  
-       if (clid) {
-@@ -873,7 +882,7 @@
-       }
+diff -Nurb linux-2.6.22-590/net/ipv6/route.c linux-2.6.22-570/net/ipv6/route.c
+--- linux-2.6.22-590/net/ipv6/route.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/route.c  2008-01-23 19:16:05.000000000 -0500
+@@ -56,7 +56,6 @@
+ #include <net/xfrm.h>
+ #include <net/netevent.h>
+ #include <net/netlink.h>
+-#include <net/net_namespace.h>
  
-       if (skb->len)
--              return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
-+              return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ #include <asm/uaccess.h>
  
- err_out:
-       kfree_skb(skb);
-@@ -882,16 +891,20 @@
+@@ -138,7 +137,7 @@
+               .dst = {
+                       .__refcnt       = ATOMIC_INIT(1),
+                       .__use          = 1,
+-                      .dev            = NULL,
++                      .dev            = &loopback_dev,
+                       .obsolete       = -1,
+                       .error          = -ENETUNREACH,
+                       .metrics        = { [RTAX_HOPLIMIT - 1] = 255, },
+@@ -164,7 +163,7 @@
+               .dst = {
+                       .__refcnt       = ATOMIC_INIT(1),
+                       .__use          = 1,
+-                      .dev            = NULL,
++                      .dev            = &loopback_dev,
+                       .obsolete       = -1,
+                       .error          = -EACCES,
+                       .metrics        = { [RTAX_HOPLIMIT - 1] = 255, },
+@@ -184,7 +183,7 @@
+               .dst = {
+                       .__refcnt       = ATOMIC_INIT(1),
+                       .__use          = 1,
+-                      .dev            = NULL,
++                      .dev            = &loopback_dev,
+                       .obsolete       = -1,
+                       .error          = -EINVAL,
+                       .metrics        = { [RTAX_HOPLIMIT - 1] = 255, },
+@@ -224,8 +223,8 @@
+       struct rt6_info *rt = (struct rt6_info *)dst;
+       struct inet6_dev *idev = rt->rt6i_idev;
  
- static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
+-      if (dev != &init_net.loopback_dev && idev != NULL && idev->dev == dev) {
+-              struct inet6_dev *loopback_idev = in6_dev_get(&init_net.loopback_dev);
++      if (dev != &loopback_dev && idev != NULL && idev->dev == dev) {
++              struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev);
+               if (loopback_idev != NULL) {
+                       rt->rt6i_idev = loopback_idev;
+                       in6_dev_put(idev);
+@@ -565,7 +564,6 @@
+                           int oif, int strict)
  {
-+      struct net *net = skb->sk->sk_net;
-       int idx, q_idx;
-       int s_idx, s_q_idx;
-       struct net_device *dev;
-       struct Qdisc *q;
-+      if (net != &init_net)
-+              return 0;
-+
-       s_idx = cb->args[0];
-       s_q_idx = q_idx = cb->args[1];
-       read_lock(&dev_base_lock);
-       idx = 0;
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               if (idx < s_idx)
-                       goto cont;
-               if (idx > s_idx)
-@@ -930,6 +943,7 @@
+       struct flowi fl = {
+-              .fl_net = &init_net,
+               .oif = oif,
+               .nl_u = {
+                       .ip6_u = {
+@@ -613,12 +611,7 @@
  
static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
int ip6_ins_rt(struct rt6_info *rt)
  {
-+      struct net *net = skb->sk->sk_net;
-       struct tcmsg *tcm = NLMSG_DATA(n);
-       struct rtattr **tca = arg;
-       struct net_device *dev;
-@@ -942,7 +956,10 @@
-       u32 qid = TC_H_MAJ(clid);
-       int err;
--      if ((dev = __dev_get_by_index(tcm->tcm_ifindex)) == NULL)
-+      if (net != &init_net)
-+              return -EINVAL;
-+
-+      if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
-               return -ENODEV;
-       /*
-@@ -1096,7 +1113,7 @@
-               return -EINVAL;
-       }
--      return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
-+      return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+-      struct nl_info info = {
+-              .nlh = NULL,
+-              .pid = 0,
+-              .net = &init_net,
+-      };
+-      return __ip6_ins_rt(rt, &info);
++      return __ip6_ins_rt(rt, NULL);
  }
  
- struct qdisc_dump_args
-@@ -1116,6 +1133,7 @@
- static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
- {
-+      struct net *net = skb->sk->sk_net;
-       int t;
-       int s_t;
-       struct net_device *dev;
-@@ -1123,9 +1141,12 @@
-       struct tcmsg *tcm = (struct tcmsg*)NLMSG_DATA(cb->nlh);
-       struct qdisc_dump_args arg;
-+      if (net != &init_net)
-+              return 0;
-+
-       if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm)))
-               return 0;
--      if ((dev = dev_get_by_index(tcm->tcm_ifindex)) == NULL)
-+      if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
-               return 0;
+ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr,
+@@ -749,7 +742,6 @@
+       struct ipv6hdr *iph = ipv6_hdr(skb);
+       int flags = RT6_LOOKUP_F_HAS_SADDR;
+       struct flowi fl = {
+-              .fl_net = &init_net,
+               .iif = skb->dev->ifindex,
+               .nl_u = {
+                       .ip6_u = {
+@@ -1137,7 +1129,7 @@
+ #endif
+       if (cfg->fc_ifindex) {
+               err = -ENODEV;
+-              dev = dev_get_by_index(&init_net, cfg->fc_ifindex);
++              dev = dev_get_by_index(cfg->fc_ifindex);
+               if (!dev)
+                       goto out;
+               idev = in6_dev_get(dev);
+@@ -1195,12 +1187,12 @@
+       if ((cfg->fc_flags & RTF_REJECT) ||
+           (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
+               /* hold loopback dev/idev if we haven't done so. */
+-              if (dev != &init_net.loopback_dev) {
++              if (dev != &loopback_dev) {
+                       if (dev) {
+                               dev_put(dev);
+                               in6_dev_put(idev);
+                       }
+-                      dev = &init_net.loopback_dev;
++                      dev = &loopback_dev;
+                       dev_hold(dev);
+                       idev = in6_dev_get(dev);
+                       if (!idev) {
+@@ -1341,12 +1333,7 @@
  
-       s_t = cb->args[0];
-@@ -1252,7 +1273,7 @@
+ int ip6_del_rt(struct rt6_info *rt)
  {
-       register_qdisc(&pfifo_qdisc_ops);
-       register_qdisc(&bfifo_qdisc_ops);
--      proc_net_fops_create("psched", 0, &psched_fops);
-+      proc_net_fops_create(&init_net, "psched", 0, &psched_fops);
-       rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL);
-       rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL);
-diff -Nurb linux-2.6.22-570/net/sched/sch_generic.c linux-2.6.22-590/net/sched/sch_generic.c
---- linux-2.6.22-570/net/sched/sch_generic.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sched/sch_generic.c   2008-01-02 13:56:38.000000000 -0500
-@@ -59,122 +59,143 @@
-       spin_unlock_bh(&dev->queue_lock);
+-      struct nl_info info = {
+-              .nlh = NULL,
+-              .pid = 0,
+-              .net = &init_net,
+-      };
+-      return __ip6_del_rt(rt, &info);
++      return __ip6_del_rt(rt, NULL);
  }
  
--/*
--   dev->queue_lock serializes queue accesses for this device
--   AND dev->qdisc pointer itself.
-+static inline int qdisc_qlen(struct Qdisc *q)
-+{
-+      return q->q.qlen;
-+}
+ static int ip6_route_del(struct fib6_config *cfg)
+@@ -1457,7 +1444,6 @@
+       int flags = RT6_LOOKUP_F_HAS_SADDR;
+       struct ip6rd_flowi rdfl = {
+               .fl = {
+-                      .fl_net = &init_net,
+                       .oif = dev->ifindex,
+                       .nl_u = {
+                               .ip6_u = {
+@@ -1910,13 +1896,13 @@
+       if (rt == NULL)
+               return ERR_PTR(-ENOMEM);
  
--   netif_tx_lock serializes accesses to device driver.
-+static inline int dev_requeue_skb(struct sk_buff *skb, struct net_device *dev,
-+                                struct Qdisc *q)
-+{
-+      if (unlikely(skb->next))
-+              dev->gso_skb = skb;
-+      else
-+              q->ops->requeue(skb, q);
+-      dev_hold(&init_net.loopback_dev);
++      dev_hold(&loopback_dev);
+       in6_dev_hold(idev);
  
--   dev->queue_lock and netif_tx_lock are mutually exclusive,
--   if one is grabbed, another must be free.
-- */
-+      netif_schedule(dev);
-+      return 0;
-+}
+       rt->u.dst.flags = DST_HOST;
+       rt->u.dst.input = ip6_input;
+       rt->u.dst.output = ip6_output;
+-      rt->rt6i_dev = &init_net.loopback_dev;
++      rt->rt6i_dev = &loopback_dev;
+       rt->rt6i_idev = idev;
+       rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
+       rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
+@@ -2047,7 +2033,6 @@
  
-+static inline struct sk_buff *dev_dequeue_skb(struct net_device *dev,
-+                                            struct Qdisc *q)
-+{
-+      struct sk_buff *skb;
+       cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
+       cfg->fc_nlinfo.nlh = nlh;
+-      cfg->fc_nlinfo.net = skb->sk->sk_net;
  
--/* Kick device.
-+      if ((skb = dev->gso_skb))
-+              dev->gso_skb = NULL;
-+      else
-+              skb = q->dequeue(q);
+       if (tb[RTA_GATEWAY]) {
+               nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16);
+@@ -2093,13 +2078,9 @@
  
--   Returns:  0  - queue is empty or throttled.
--          >0  - queue is not empty.
-+      return skb;
-+}
+ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct fib6_config cfg;
+       int err;
  
--   NOTE: Called under dev->queue_lock with locally disabled BH.
--*/
-+static inline int handle_dev_cpu_collision(struct sk_buff *skb,
-+                                         struct net_device *dev,
-+                                         struct Qdisc *q)
-+{
-+      int ret;
+-      if (net != &init_net)
+-              return -EINVAL;
+-
+       err = rtm_to_fib6_config(skb, nlh, &cfg);
+       if (err < 0)
+               return err;
+@@ -2109,13 +2090,9 @@
  
-+      if (unlikely(dev->xmit_lock_owner == smp_processor_id())) {
-+              /*
-+               * Same CPU holding the lock. It may be a transient
-+               * configuration error, when hard_start_xmit() recurses. We
-+               * detect it by checking xmit owner and drop the packet when
-+               * deadloop is detected. Return OK to try the next skb.
-+               */
-+              kfree_skb(skb);
-+              if (net_ratelimit())
-+                      printk(KERN_WARNING "Dead loop on netdevice %s, "
-+                             "fix it urgently!\n", dev->name);
-+              ret = qdisc_qlen(q);
-+      } else {
-+              /*
-+               * Another cpu is holding lock, requeue & delay xmits for
-+               * some time.
-+               */
-+              __get_cpu_var(netdev_rx_stat).cpu_collision++;
-+              ret = dev_requeue_skb(skb, dev, q);
-+      }
-+
-+      return ret;
-+}
-+
-+/*
-+ * NOTE: Called under dev->queue_lock with locally disabled BH.
-+ *
-+ * __LINK_STATE_QDISC_RUNNING guarantees only one CPU can process this
-+ * device at a time. dev->queue_lock serializes queue accesses for
-+ * this device AND dev->qdisc pointer itself.
-+ *
-+ *  netif_tx_lock serializes accesses to device driver.
-+ *
-+ *  dev->queue_lock and netif_tx_lock are mutually exclusive,
-+ *  if one is grabbed, another must be free.
-+ *
-+ * Note, that this procedure can be called by a watchdog timer
-+ *
-+ * Returns to the caller:
-+ *                            0  - queue is empty or throttled.
-+ *                            >0 - queue is not empty.
-+ *
-+ */
- static inline int qdisc_restart(struct net_device *dev)
+ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
  {
-       struct Qdisc *q = dev->qdisc;
-       struct sk_buff *skb;
-+      unsigned lockless;
-+      int ret;
+-      struct net *net = skb->sk->sk_net;
+       struct fib6_config cfg;
+       int err;
  
-       /* Dequeue packet */
--      if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) {
--              unsigned nolock = (dev->features & NETIF_F_LLTX);
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--              dev->gso_skb = NULL;
-+      if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL))
-+              return 0;
-               /*
--               * When the driver has LLTX set it does its own locking
--               * in start_xmit. No need to add additional overhead by
--               * locking again. These checks are worth it because
--               * even uncongested locks can be quite expensive.
--               * The driver can do trylock like here too, in case
--               * of lock congestion it should return -1 and the packet
--               * will be requeued.
--               */
--              if (!nolock) {
--                      if (!netif_tx_trylock(dev)) {
--                      collision:
--                              /* So, someone grabbed the driver. */
--
--                              /* It may be transient configuration error,
--                                 when hard_start_xmit() recurses. We detect
--                                 it by checking xmit owner and drop the
--                                 packet when deadloop is detected.
-+       * When the driver has LLTX set, it does its own locking in
-+       * start_xmit. These checks are worth it because even uncongested
-+       * locks can be quite expensive. The driver can do a trylock, as
-+       * is being done here; in case of lock contention it should return
-+       * NETDEV_TX_LOCKED and the packet will be requeued.
-                               */
--                              if (dev->xmit_lock_owner == smp_processor_id()) {
--                                      kfree_skb(skb);
--                                      if (net_ratelimit())
--                                              printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
--                                      goto out;
--                              }
--                              __get_cpu_var(netdev_rx_stat).cpu_collision++;
--                              goto requeue;
--                      }
-+      lockless = (dev->features & NETIF_F_LLTX);
-+
-+      if (!lockless && !netif_tx_trylock(dev)) {
-+              /* Another CPU grabbed the driver tx lock */
-+              return handle_dev_cpu_collision(skb, dev, q);
-               }
+       err = rtm_to_fib6_config(skb, nlh, &cfg);
+       if (err < 0)
+               return err;
+@@ -2250,7 +2227,6 @@
  
--              {
-                       /* And release queue */
-                       spin_unlock(&dev->queue_lock);
+ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
+ {
+-      struct net *net = in_skb->sk->sk_net;
+       struct nlattr *tb[RTA_MAX+1];
+       struct rt6_info *rt;
+       struct sk_buff *skb;
+@@ -2258,16 +2234,12 @@
+       struct flowi fl;
+       int err, iif = 0;
  
--                      if (!netif_queue_stopped(dev)) {
--                              int ret;
+-      if (net != &init_net)
+-              return -EINVAL;
 -
-                               ret = dev_hard_start_xmit(skb, dev);
--                              if (ret == NETDEV_TX_OK) {
--                                      if (!nolock) {
--                                              netif_tx_unlock(dev);
--                                      }
--                                      spin_lock(&dev->queue_lock);
--                                      q = dev->qdisc;
--                                      goto out;
--                              }
--                              if (ret == NETDEV_TX_LOCKED && nolock) {
--                                      spin_lock(&dev->queue_lock);
--                                      q = dev->qdisc;
--                                      goto collision;
--                              }
--                      }
--                      /* NETDEV_TX_BUSY - we need to requeue */
--                      /* Release the driver */
--                      if (!nolock) {
-+      if (!lockless)
-                               netif_tx_unlock(dev);
--                      }
-+
-                       spin_lock(&dev->queue_lock);
-                       q = dev->qdisc;
--              }
+       err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
+       if (err < 0)
+               goto errout;
  
--              /* Device kicked us out :(
--                 This is possible in three cases:
-+      switch (ret) {
-+      case NETDEV_TX_OK:
-+              /* Driver sent out skb successfully */
-+              ret = qdisc_qlen(q);
-+              break;
+       err = -EINVAL;
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
  
--                 0. driver is locked
--                 1. fastroute is enabled
--                 2. device cannot determine busy state
--                    before start of transmission (f.e. dialout)
--                 3. device is buggy (ppp)
--               */
-+      case NETDEV_TX_LOCKED:
-+              /* Driver try lock failed */
-+              ret = handle_dev_cpu_collision(skb, dev, q);
-+              break;
+       if (tb[RTA_SRC]) {
+               if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
+@@ -2291,7 +2263,7 @@
  
--requeue:
--              if (unlikely(q == &noop_qdisc))
--                      kfree_skb(skb);
--              else if (skb->next)
--                      dev->gso_skb = skb;
--              else
--                      q->ops->requeue(skb, q);
--              netif_schedule(dev);
-+      default:
-+              /* Driver returned NETDEV_TX_BUSY - requeue skb */
-+              if (unlikely (ret != NETDEV_TX_BUSY && net_ratelimit()))
-+                      printk(KERN_WARNING "BUG %s code %d qlen %d\n",
-+                             dev->name, ret, q->q.qlen);
-+
-+              ret = dev_requeue_skb(skb, dev, q);
-+              break;
+       if (iif) {
+               struct net_device *dev;
+-              dev = __dev_get_by_index(&init_net, iif);
++              dev = __dev_get_by_index(iif);
+               if (!dev) {
+                       err = -ENODEV;
+                       goto errout;
+@@ -2321,7 +2293,7 @@
+               goto errout;
        }
--      return 0;
  
--out:
--      BUG_ON((int) q->q.qlen < 0);
--      return q->q.qlen;
-+      return ret;
+-      err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
++      err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
+ errout:
+       return err;
  }
+@@ -2329,10 +2301,17 @@
+ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
+ {
+       struct sk_buff *skb;
+-      u32 pid = info->pid, seq = info->nlh ? info->nlh->nlmsg_seq : 0;
+-      struct nlmsghdr *nlh = info->nlh;
++      u32 pid = 0, seq = 0;
++      struct nlmsghdr *nlh = NULL;
+       int err = -ENOBUFS;
  
- void __qdisc_run(struct net_device *dev)
-diff -Nurb linux-2.6.22-570/net/sched/sch_ingress.c linux-2.6.22-590/net/sched/sch_ingress.c
---- linux-2.6.22-570/net/sched/sch_ingress.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sched/sch_ingress.c   2008-01-02 13:56:38.000000000 -0500
-@@ -243,6 +243,10 @@
-       struct net_device *dev = skb->dev;
-       int fwres=NF_ACCEPT;
-+      /* Only filter packets in the initial network namespace */
-+      if ((indev?indev:outdev)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
-       DPRINTK("ing_hook: skb %s dev=%s len=%u\n",
-               skb->sk ? "(owned)" : "(unowned)",
-               skb->dev ? (*pskb)->dev->name : "(no dev)",
-diff -Nurb linux-2.6.22-570/net/sctp/input.c linux-2.6.22-590/net/sctp/input.c
---- linux-2.6.22-570/net/sctp/input.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sctp/input.c  2008-01-02 13:56:38.000000000 -0500
-@@ -126,6 +126,10 @@
-       int family;
-       struct sctp_af *af;
-+      if (skb->dev->nd_net != &init_net) {
-+              kfree_skb(skb);
-+              return 0;
++      if (info) {
++              pid = info->pid;
++              nlh = info->nlh;
++              if (nlh)
++                      seq = nlh->nlmsg_seq;
 +      }
-       if (skb->pkt_type!=PACKET_HOST)
-               goto discard_it;
-@@ -509,6 +513,9 @@
-       sk_buff_data_t saveip, savesctp;
-       int err;
-+      if (skb->dev->nd_net != &init_net)
-+              return;
 +
-       if (skb->len < ihlen + 8) {
-               ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
-               return;
-diff -Nurb linux-2.6.22-570/net/sctp/ipv6.c linux-2.6.22-590/net/sctp/ipv6.c
---- linux-2.6.22-570/net/sctp/ipv6.c   2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/sctp/ipv6.c   2008-01-02 13:56:38.000000000 -0500
-@@ -189,6 +189,7 @@
+       skb = nlmsg_new(rt6_nlmsg_size(), gfp_any());
+       if (skb == NULL)
+               goto errout;
+@@ -2344,10 +2323,10 @@
+               kfree_skb(skb);
+               goto errout;
+       }
+-      err = rtnl_notify(skb, &init_net, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
++      err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
+ errout:
+       if (err < 0)
+-              rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_ROUTE, err);
++              rtnl_set_sk_err(RTNLGRP_IPV6_ROUTE, err);
+ }
  
-       memset(&fl, 0, sizeof(fl));
+ /*
+@@ -2579,19 +2558,13 @@
+                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+       ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
  
-+      fl.fl_net = &init_net;
-       fl.proto = sk->sk_protocol;
+-      /* Perform the initialization we can't perform at compile time */
+-      ip6_null_entry.u.dst.dev = &init_net.loopback_dev;
+-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+-      ip6_prohibit_entry.u.dst.dev = &init_net.loopback_dev;
+-      ip6_blk_hole_entry.u.dst.dev = &init_net.loopback_dev;
+-#endif        
+       fib6_init();
+ #ifdef        CONFIG_PROC_FS
+-      p = proc_net_create(&init_net, "ipv6_route", 0, rt6_proc_info);
++      p = proc_net_create("ipv6_route", 0, rt6_proc_info);
+       if (p)
+               p->owner = THIS_MODULE;
  
-       /* Fill in the dest address from the route entry passed with the skb
-@@ -230,6 +231,7 @@
-       struct flowi fl;
+-      proc_net_fops_create(&init_net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
++      proc_net_fops_create("rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
+ #endif
+ #ifdef CONFIG_XFRM
+       xfrm6_init();
+@@ -2611,8 +2584,8 @@
+       fib6_rules_cleanup();
+ #endif
+ #ifdef CONFIG_PROC_FS
+-      proc_net_remove(&init_net, "ipv6_route");
+-      proc_net_remove(&init_net, "rt6_stats");
++      proc_net_remove("ipv6_route");
++      proc_net_remove("rt6_stats");
+ #endif
+ #ifdef CONFIG_XFRM
+       xfrm6_fini();
+diff -Nurb linux-2.6.22-590/net/ipv6/sit.c linux-2.6.22-570/net/ipv6/sit.c
+--- linux-2.6.22-590/net/ipv6/sit.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/sit.c    2007-07-08 19:32:17.000000000 -0400
+@@ -167,7 +167,7 @@
+               int i;
+               for (i=1; i<100; i++) {
+                       sprintf(name, "sit%d", i);
+-                      if (__dev_get_by_name(&init_net, name) == NULL)
++                      if (__dev_get_by_name(name) == NULL)
+                               break;
+               }
+               if (i==100)
+@@ -283,9 +283,6 @@
+       struct sk_buff *skb2;
+       struct rt6_info *rt6i;
  
-       memset(&fl, 0, sizeof(fl));
-+      fl.fl_net = &init_net;
-       ipv6_addr_copy(&fl.fl6_dst, &daddr->v6.sin6_addr);
-       if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
-               fl.oif = daddr->v6.sin6_scope_id;
-@@ -619,7 +621,7 @@
-       struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
-       struct sctp6_sock *newsctp6sk;
+-      if (skb->dev->nd_net != &init_net)
+-              return;
+-
+       if (len < hlen + sizeof(struct ipv6hdr))
+               return;
+       iph6 = (struct ipv6hdr*)(dp + hlen);
+@@ -372,10 +369,6 @@
+       struct iphdr *iph;
+       struct ip_tunnel *tunnel;
  
--      newsk = sk_alloc(PF_INET6, GFP_KERNEL, sk->sk_prot, 1);
-+      newsk = sk_alloc(sk->sk_net, PF_INET6, GFP_KERNEL, sk->sk_prot, 1);
-       if (!newsk)
+-      if (skb->dev->nd_net != &init_net) {
+-              kfree_skb(skb);
+-              return 0;
+-      }
+       if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
                goto out;
  
-@@ -664,7 +666,7 @@
-       newinet->mc_index = 0;
-       newinet->mc_list = NULL;
--      if (ipv4_config.no_pmtu_disc)
-+      if (init_net.sysctl_ipv4_no_pmtu_disc)
-               newinet->pmtudisc = IP_PMTUDISC_DONT;
-       else
-               newinet->pmtudisc = IP_PMTUDISC_WANT;
-@@ -841,7 +843,7 @@
-               if (type & IPV6_ADDR_LINKLOCAL) {
-                       if (!addr->v6.sin6_scope_id)
-                               return 0;
--                      dev = dev_get_by_index(addr->v6.sin6_scope_id);
-+                      dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id);
-                       if (!dev)
-                               return 0;
-                       if (!ipv6_chk_addr(&addr->v6.sin6_addr, dev, 0)) {
-@@ -872,7 +874,7 @@
-               if (type & IPV6_ADDR_LINKLOCAL) {
-                       if (!addr->v6.sin6_scope_id)
-                               return 0;
--                      dev = dev_get_by_index(addr->v6.sin6_scope_id);
-+                      dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id);
-                       if (!dev)
-                               return 0;
-                       if (!ipv6_chk_addr(&addr->v6.sin6_addr, dev, 0)) {
-diff -Nurb linux-2.6.22-570/net/sctp/protocol.c linux-2.6.22-590/net/sctp/protocol.c
---- linux-2.6.22-570/net/sctp/protocol.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sctp/protocol.c       2008-01-02 13:56:38.000000000 -0500
-@@ -59,6 +59,7 @@
- #include <net/addrconf.h>
- #include <net/inet_common.h>
- #include <net/inet_ecn.h>
-+#include <net/net_namespace.h>
- /* Global data structures. */
- struct sctp_globals sctp_globals __read_mostly;
-@@ -93,7 +94,7 @@
- {
-       if (!proc_net_sctp) {
-               struct proc_dir_entry *ent;
--              ent = proc_mkdir("net/sctp", NULL);
-+              ent = proc_mkdir("sctp", init_net.proc_net);
-               if (ent) {
-                       ent->owner = THIS_MODULE;
-                       proc_net_sctp = ent;
-@@ -126,7 +127,7 @@
-       if (proc_net_sctp) {
-               proc_net_sctp = NULL;
--              remove_proc_entry("net/sctp", NULL);
-+              remove_proc_entry("sctp", init_net.proc_net);
+@@ -481,8 +474,7 @@
        }
- }
  
-@@ -170,7 +171,7 @@
-       struct sctp_af *af;
+       {
+-              struct flowi fl = { .fl_net = &init_net,
+-                                  .nl_u = { .ip4_u =
++              struct flowi fl = { .nl_u = { .ip4_u =
+                                             { .daddr = dst,
+                                               .saddr = tiph->saddr,
+                                               .tos = RT_TOS(tos) } },
+@@ -753,8 +745,7 @@
+       memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
  
-       read_lock(&dev_base_lock);
--      for_each_netdev(dev) {
-+      for_each_netdev(&init_net, dev) {
-               __list_for_each(pos, &sctp_address_families) {
-                       af = list_entry(pos, struct sctp_af, list);
-                       af->copy_addrlist(&sctp_local_addr_list, dev);
-@@ -354,13 +355,13 @@
- /* Should this be available for binding?   */
- static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
- {
--      int ret = inet_addr_type(addr->v4.sin_addr.s_addr);
-+      int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr);
+       if (iph->daddr) {
+-              struct flowi fl = { .fl_net = &init_net,
+-                                  .nl_u = { .ip4_u =
++              struct flowi fl = { .nl_u = { .ip4_u =
+                                             { .daddr = iph->daddr,
+                                               .saddr = iph->saddr,
+                                               .tos = RT_TOS(iph->tos) } },
+@@ -769,7 +760,7 @@
+       }
  
+       if (!tdev && tunnel->parms.link)
+-              tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
++              tdev = __dev_get_by_index(tunnel->parms.link);
  
-       if (addr->v4.sin_addr.s_addr != INADDR_ANY &&
-          ret != RTN_LOCAL &&
-          !sp->inet.freebind &&
--         !sysctl_ip_nonlocal_bind)
-+         !init_net.sysctl_ip_nonlocal_bind)
-               return 0;
+       if (tdev) {
+               dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
+diff -Nurb linux-2.6.22-590/net/ipv6/tcp_ipv6.c linux-2.6.22-570/net/ipv6/tcp_ipv6.c
+--- linux-2.6.22-590/net/ipv6/tcp_ipv6.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/tcp_ipv6.c       2008-01-23 19:16:05.000000000 -0500
+@@ -143,7 +143,6 @@
+               return(-EAFNOSUPPORT);
  
-       return 1;
-@@ -423,6 +424,7 @@
-       union sctp_addr dst_saddr;
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
  
-       memset(&fl, 0x0, sizeof(struct flowi));
-+      fl.fl_net = &init_net;
-       fl.fl4_dst  = daddr->v4.sin_addr.s_addr;
-       fl.proto = IPPROTO_SCTP;
-       if (asoc) {
-@@ -539,7 +541,7 @@
+       if (np->sndflow) {
+               fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
+@@ -331,7 +330,6 @@
+ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+               int type, int code, int offset, __be32 info)
  {
-       struct inet_sock *inet = inet_sk(sk);
-       struct inet_sock *newinet;
--      struct sock *newsk = sk_alloc(PF_INET, GFP_KERNEL, sk->sk_prot, 1);
-+      struct sock *newsk = sk_alloc(sk->sk_net, PF_INET, GFP_KERNEL, sk->sk_prot, 1);
+-      struct net *net = skb->dev->nd_net;
+       struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
+       const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
+       struct ipv6_pinfo *np;
+@@ -341,7 +339,7 @@
+       __u32 seq;
  
-       if (!newsk)
-               goto out;
-@@ -1122,7 +1124,7 @@
-       }
+       sk = inet6_lookup(&tcp_hashinfo, &hdr->daddr, th->dest, &hdr->saddr,
+-                        th->source, skb->dev->ifindex, net);
++                        th->source, skb->dev->ifindex);
+       if (sk == NULL) {
+               ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
+@@ -390,7 +388,6 @@
+                          for now.
+                        */
+                       memset(&fl, 0, sizeof(fl));
+-                      fl.fl_net = &init_net;
+                       fl.proto = IPPROTO_TCP;
+                       ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
+                       ipv6_addr_copy(&fl.fl6_src, &np->saddr);
+@@ -484,7 +481,6 @@
+       int err = -1;
  
-       spin_lock_init(&sctp_port_alloc_lock);
--      sctp_port_rover = sysctl_local_port_range[0] - 1;
-+      sctp_port_rover = init_net.sysctl_local_port_range[0] - 1;
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       fl.proto = IPPROTO_TCP;
+       ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
+       ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
+@@ -1070,7 +1066,6 @@
+       buff->csum = csum_partial((char *)t1, sizeof(*t1), 0);
  
-       printk(KERN_INFO "SCTP: Hash tables configured "
-                        "(established %d bind %d)\n",
-diff -Nurb linux-2.6.22-570/net/sctp/socket.c linux-2.6.22-590/net/sctp/socket.c
---- linux-2.6.22-570/net/sctp/socket.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sctp/socket.c 2008-01-02 13:56:38.000000000 -0500
-@@ -5021,8 +5021,8 @@
-                * already in the hash table; if not, we use that; if
-                * it is, we try next.
-                */
--              int low = sysctl_local_port_range[0];
--              int high = sysctl_local_port_range[1];
-+              int low = sk->sk_net->sysctl_local_port_range[0];
-+              int high = sk->sk_net->sysctl_local_port_range[1];
-               int remaining = (high - low) + 1;
-               int rover;
-               int index;
-diff -Nurb linux-2.6.22-570/net/socket.c linux-2.6.22-590/net/socket.c
---- linux-2.6.22-570/net/socket.c      2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/socket.c      2008-01-02 13:56:38.000000000 -0500
-@@ -84,6 +84,7 @@
- #include <linux/kmod.h>
- #include <linux/audit.h>
- #include <linux/wireless.h>
-+#include <linux/nsproxy.h>
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
+       ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr);
  
- #include <asm/uaccess.h>
- #include <asm/unistd.h>
-@@ -821,9 +822,9 @@
-  */
+@@ -1172,7 +1167,6 @@
+       buff->csum = csum_partial((char *)t1, tot_len, 0);
  
- static DEFINE_MUTEX(br_ioctl_mutex);
--static int (*br_ioctl_hook) (unsigned int cmd, void __user *arg) = NULL;
-+static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg) = NULL;
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
+       ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr);
  
--void brioctl_set(int (*hook) (unsigned int, void __user *))
-+void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
- {
-       mutex_lock(&br_ioctl_mutex);
-       br_ioctl_hook = hook;
-@@ -833,9 +834,9 @@
- EXPORT_SYMBOL(brioctl_set);
+@@ -1230,8 +1224,7 @@
  
- static DEFINE_MUTEX(vlan_ioctl_mutex);
--static int (*vlan_ioctl_hook) (void __user *arg);
-+static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
+       nsk = __inet6_lookup_established(&tcp_hashinfo, &ipv6_hdr(skb)->saddr,
+                                        th->source, &ipv6_hdr(skb)->daddr,
+-                                       ntohs(th->dest), inet6_iif(skb),
+-                                       sk->sk_net);
++                                       ntohs(th->dest), inet6_iif(skb));
  
--void vlan_ioctl_set(int (*hook) (void __user *))
-+void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
- {
-       mutex_lock(&vlan_ioctl_mutex);
-       vlan_ioctl_hook = hook;
-@@ -864,16 +865,20 @@
- static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+       if (nsk) {
+               if (nsk->sk_state != TCP_TIME_WAIT) {
+@@ -1421,7 +1414,6 @@
+               struct flowi fl;
+               memset(&fl, 0, sizeof(fl));
+-              fl.fl_net = &init_net;
+               fl.proto = IPPROTO_TCP;
+               ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
+               if (opt && opt->srcrt) {
+@@ -1708,7 +1700,6 @@
+ static int tcp_v6_rcv(struct sk_buff **pskb)
  {
-       struct socket *sock;
-+      struct sock *sk;
-       void __user *argp = (void __user *)arg;
-       int pid, err;
-+      struct net *net;
+       struct sk_buff *skb = *pskb;
+-      struct net *net = skb->dev->nd_net;
+       struct tcphdr *th;
+       struct sock *sk;
+       int ret;
+@@ -1745,7 +1736,7 @@
  
-       sock = file->private_data;
-+      sk = sock->sk;
-+      net = sk->sk_net;
-       if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
--              err = dev_ioctl(cmd, argp);
-+              err = dev_ioctl(net, cmd, argp);
-       } else
- #ifdef CONFIG_WIRELESS_EXT
-       if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
--              err = dev_ioctl(cmd, argp);
-+              err = dev_ioctl(net, cmd, argp);
-       } else
- #endif                                /* CONFIG_WIRELESS_EXT */
-               switch (cmd) {
-@@ -899,7 +904,7 @@
+       sk = __inet6_lookup(&tcp_hashinfo, &ipv6_hdr(skb)->saddr, th->source,
+                           &ipv6_hdr(skb)->daddr, ntohs(th->dest),
+-                          inet6_iif(skb), net);
++                          inet6_iif(skb));
  
-                       mutex_lock(&br_ioctl_mutex);
-                       if (br_ioctl_hook)
--                              err = br_ioctl_hook(cmd, argp);
-+                              err = br_ioctl_hook(net, cmd, argp);
-                       mutex_unlock(&br_ioctl_mutex);
-                       break;
-               case SIOCGIFVLAN:
-@@ -910,7 +915,7 @@
+       if (!sk)
+               goto no_tcp_socket;
+@@ -1825,8 +1816,7 @@
  
-                       mutex_lock(&vlan_ioctl_mutex);
-                       if (vlan_ioctl_hook)
--                              err = vlan_ioctl_hook(argp);
-+                              err = vlan_ioctl_hook(net, argp);
-                       mutex_unlock(&vlan_ioctl_mutex);
-                       break;
-               case SIOCADDDLCI:
-@@ -933,7 +938,7 @@
-                        * to the NIC driver.
-                        */
-                       if (err == -ENOIOCTLCMD)
--                              err = dev_ioctl(cmd, argp);
-+                              err = dev_ioctl(net, cmd, argp);
-                       break;
-               }
-       return err;
-@@ -1102,7 +1107,7 @@
-       return 0;
+               sk2 = inet6_lookup_listener(&tcp_hashinfo,
+                                           &ipv6_hdr(skb)->daddr,
+-                                          ntohs(th->dest), inet6_iif(skb),
+-                                          net);
++                                          ntohs(th->dest), inet6_iif(skb));
+               if (sk2 != NULL) {
+                       struct inet_timewait_sock *tw = inet_twsk(sk);
+                       inet_twsk_deschedule(tw, &tcp_death_row);
+@@ -2131,12 +2121,12 @@
+ int __init tcp6_proc_init(void)
+ {
+-      return tcp_proc_register(&init_net, &tcp6_seq_afinfo);
++      return tcp_proc_register(&tcp6_seq_afinfo);
  }
  
--static int __sock_create(int family, int type, int protocol,
-+static int __sock_create(struct net *net, int family, int type, int protocol,
-                        struct socket **res, int kern)
+ void tcp6_proc_exit(void)
  {
-       int err;
-@@ -1185,7 +1190,7 @@
-       /* Now protected by module ref count */
-       rcu_read_unlock();
+-      tcp_proc_unregister(&init_net, &tcp6_seq_afinfo);
++      tcp_proc_unregister(&tcp6_seq_afinfo);
+ }
+ #endif
  
--      err = pf->create(sock, protocol);
-+      err = pf->create(net, sock, protocol);
-       if (err < 0)
-               goto out_module_put;
+diff -Nurb linux-2.6.22-590/net/ipv6/udp.c linux-2.6.22-570/net/ipv6/udp.c
+--- linux-2.6.22-590/net/ipv6/udp.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/udp.c    2008-01-23 19:16:05.000000000 -0500
+@@ -657,7 +657,6 @@
+       ulen += sizeof(struct udphdr);
  
-@@ -1224,12 +1229,12 @@
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
  
- int sock_create(int family, int type, int protocol, struct socket **res)
+       if (sin6) {
+               if (sin6->sin6_port == 0)
+@@ -968,11 +967,11 @@
+ int __init udp6_proc_init(void)
  {
--      return __sock_create(family, type, protocol, res, 0);
-+      return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
+-      return udp_proc_register(&init_net, &udp6_seq_afinfo);
++      return udp_proc_register(&udp6_seq_afinfo);
  }
  
- int sock_create_kern(int family, int type, int protocol, struct socket **res)
- {
--      return __sock_create(family, type, protocol, res, 1);
-+      return __sock_create(&init_net, family, type, protocol, res, 1);
+ void udp6_proc_exit(void) {
+-      udp_proc_unregister(&init_net, &udp6_seq_afinfo);
++      udp_proc_unregister(&udp6_seq_afinfo);
  }
+ #endif /* CONFIG_PROC_FS */
  
- asmlinkage long sys_socket(int family, int type, int protocol)
-@@ -1389,8 +1394,6 @@
-  *    ready for listening.
-  */
+diff -Nurb linux-2.6.22-590/net/ipv6/udplite.c linux-2.6.22-570/net/ipv6/udplite.c
+--- linux-2.6.22-590/net/ipv6/udplite.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/udplite.c        2007-07-08 19:32:17.000000000 -0400
+@@ -95,11 +95,11 @@
  
--int sysctl_somaxconn __read_mostly = SOMAXCONN;
--
- asmlinkage long sys_listen(int fd, int backlog)
+ int __init udplite6_proc_init(void)
  {
-       struct socket *sock;
-@@ -1398,8 +1401,9 @@
-       sock = sockfd_lookup_light(fd, &err, &fput_needed);
-       if (sock) {
--              if ((unsigned)backlog > sysctl_somaxconn)
--                      backlog = sysctl_somaxconn;
-+              struct net *net = sock->sk->sk_net;
-+              if ((unsigned)backlog > net->sysctl_somaxconn)
-+                      backlog = net->sysctl_somaxconn;
-               err = security_socket_listen(sock, backlog);
-               if (!err)
-@@ -2189,6 +2193,16 @@
-       printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
+-      return udp_proc_register(&init_net, &udplite6_seq_afinfo);
++      return udp_proc_register(&udplite6_seq_afinfo);
  }
  
-+static int sock_pernet_init(struct net *net)
-+{
-+      net->sysctl_somaxconn = SOMAXCONN;
-+      return 0;
-+}
-+
-+static struct pernet_operations sock_net_ops = {
-+      .init = sock_pernet_init,
-+};
-+
- static int __init sock_init(void)
+ void udplite6_proc_exit(void)
  {
-       /*
-@@ -2217,6 +2231,8 @@
-       netfilter_init();
+-      udp_proc_unregister(&init_net, &udplite6_seq_afinfo);
++      udp_proc_unregister(&udplite6_seq_afinfo);
+ }
+ #endif
+diff -Nurb linux-2.6.22-590/net/ipv6/xfrm6_policy.c linux-2.6.22-570/net/ipv6/xfrm6_policy.c
+--- linux-2.6.22-590/net/ipv6/xfrm6_policy.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/xfrm6_policy.c   2008-01-23 19:16:05.000000000 -0500
+@@ -18,7 +18,7 @@
+ #include <net/ip.h>
+ #include <net/ipv6.h>
+ #include <net/ip6_route.h>
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+ #include <net/mip6.h>
  #endif
  
-+      register_pernet_subsys(&sock_net_ops);
-+
-       return 0;
- }
+@@ -40,7 +40,6 @@
+ {
+       struct rt6_info *rt;
+       struct flowi fl_tunnel = {
+-              .fl_net = &init_net,
+               .nl_u = {
+                       .ip6_u = {
+                               .daddr = *(struct in6_addr *)&daddr->a6,
+@@ -133,7 +132,6 @@
+       struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
+       struct rt6_info *rt  = rt0;
+       struct flowi fl_tunnel = {
+-              .fl_net = &init_net,
+               .nl_u = {
+                       .ip6_u = {
+                               .saddr = fl->fl6_src,
+@@ -280,7 +278,6 @@
+       u8 nexthdr = nh[IP6CB(skb)->nhoff];
  
-diff -Nurb linux-2.6.22-570/net/socket.c.orig linux-2.6.22-590/net/socket.c.orig
---- linux-2.6.22-570/net/socket.c.orig 2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/socket.c.orig 1969-12-31 19:00:00.000000000 -0500
-@@ -1,2344 +0,0 @@
--/*
-- * NET                An implementation of the SOCKET network access protocol.
-- *
-- * Version:   @(#)socket.c    1.1.93  18/02/95
-- *
-- * Authors:   Orest Zborowski, <obz@Kodak.COM>
-- *            Ross Biro
-- *            Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
-- *
-- * Fixes:
-- *            Anonymous       :       NOTSOCK/BADF cleanup. Error fix in
-- *                                    shutdown()
-- *            Alan Cox        :       verify_area() fixes
-- *            Alan Cox        :       Removed DDI
-- *            Jonathan Kamens :       SOCK_DGRAM reconnect bug
-- *            Alan Cox        :       Moved a load of checks to the very
-- *                                    top level.
-- *            Alan Cox        :       Move address structures to/from user
-- *                                    mode above the protocol layers.
-- *            Rob Janssen     :       Allow 0 length sends.
-- *            Alan Cox        :       Asynchronous I/O support (cribbed from the
-- *                                    tty drivers).
-- *            Niibe Yutaka    :       Asynchronous I/O for writes (4.4BSD style)
-- *            Jeff Uphoff     :       Made max number of sockets command-line
-- *                                    configurable.
-- *            Matti Aarnio    :       Made the number of sockets dynamic,
-- *                                    to be allocated when needed, and mr.
-- *                                    Uphoff's max is used as max to be
-- *                                    allowed to allocate.
-- *            Linus           :       Argh. removed all the socket allocation
-- *                                    altogether: it's in the inode now.
-- *            Alan Cox        :       Made sock_alloc()/sock_release() public
-- *                                    for NetROM and future kernel nfsd type
-- *                                    stuff.
-- *            Alan Cox        :       sendmsg/recvmsg basics.
-- *            Tom Dyas        :       Export net symbols.
-- *            Marcin Dalecki  :       Fixed problems with CONFIG_NET="n".
-- *            Alan Cox        :       Added thread locking to sys_* calls
-- *                                    for sockets. May have errors at the
-- *                                    moment.
-- *            Kevin Buhr      :       Fixed the dumb errors in the above.
-- *            Andi Kleen      :       Some small cleanups, optimizations,
-- *                                    and fixed a copy_from_user() bug.
-- *            Tigran Aivazian :       sys_send(args) calls sys_sendto(args, NULL, 0)
-- *            Tigran Aivazian :       Made listen(2) backlog sanity checks
-- *                                    protocol-independent
-- *
-- *
-- *            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 module is effectively the top level interface to the BSD socket
-- *    paradigm.
-- *
-- *    Based upon Swansea University Computer Society NET3.039
-- */
--
--#include <linux/mm.h>
--#include <linux/socket.h>
--#include <linux/file.h>
--#include <linux/net.h>
--#include <linux/interrupt.h>
--#include <linux/rcupdate.h>
--#include <linux/netdevice.h>
--#include <linux/proc_fs.h>
--#include <linux/seq_file.h>
--#include <linux/mutex.h>
--#include <linux/wanrouter.h>
--#include <linux/if_bridge.h>
--#include <linux/if_frad.h>
--#include <linux/if_vlan.h>
--#include <linux/init.h>
--#include <linux/poll.h>
--#include <linux/cache.h>
--#include <linux/module.h>
--#include <linux/highmem.h>
--#include <linux/mount.h>
--#include <linux/security.h>
--#include <linux/syscalls.h>
--#include <linux/compat.h>
--#include <linux/kmod.h>
--#include <linux/audit.h>
--#include <linux/wireless.h>
--
--#include <asm/uaccess.h>
--#include <asm/unistd.h>
--
--#include <net/compat.h>
--
--#include <net/sock.h>
--#include <linux/netfilter.h>
--
--static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
--static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
--                       unsigned long nr_segs, loff_t pos);
--static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
--                        unsigned long nr_segs, loff_t pos);
--static int sock_mmap(struct file *file, struct vm_area_struct *vma);
--
--static int sock_close(struct inode *inode, struct file *file);
--static unsigned int sock_poll(struct file *file,
--                            struct poll_table_struct *wait);
--static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
--#ifdef CONFIG_COMPAT
--static long compat_sock_ioctl(struct file *file,
--                            unsigned int cmd, unsigned long arg);
--#endif
--static int sock_fasync(int fd, struct file *filp, int on);
--static ssize_t sock_sendpage(struct file *file, struct page *page,
--                           int offset, size_t size, loff_t *ppos, int more);
--
--/*
-- *    Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
-- *    in the operation structures but are done directly via the socketcall() multiplexor.
-- */
--
--static const struct file_operations socket_file_ops = {
--      .owner =        THIS_MODULE,
--      .llseek =       no_llseek,
--      .aio_read =     sock_aio_read,
--      .aio_write =    sock_aio_write,
--      .poll =         sock_poll,
--      .unlocked_ioctl = sock_ioctl,
--#ifdef CONFIG_COMPAT
--      .compat_ioctl = compat_sock_ioctl,
--#endif
--      .mmap =         sock_mmap,
--      .open =         sock_no_open,   /* special open code to disallow open via /proc */
--      .release =      sock_close,
--      .fasync =       sock_fasync,
--      .sendpage =     sock_sendpage,
--      .splice_write = generic_splice_sendpage,
--};
--
--/*
-- *    The protocol list. Each protocol is registered in here.
-- */
--
--static DEFINE_SPINLOCK(net_family_lock);
--static const struct net_proto_family *net_families[NPROTO] __read_mostly;
--
--/*
-- *    Statistics counters of the socket lists
-- */
--
--static DEFINE_PER_CPU(int, sockets_in_use) = 0;
--
--/*
-- * Support routines.
-- * Move socket addresses back and forth across the kernel/user
-- * divide and look after the messy bits.
-- */
--
--#define MAX_SOCK_ADDR 128             /* 108 for Unix domain -
--                                         16 for IP, 16 for IPX,
--                                         24 for IPv6,
--                                         about 80 for AX.25
--                                         must be at least one bigger than
--                                         the AF_UNIX size (see net/unix/af_unix.c
--                                         :unix_mkname()).
--                                       */
--
--/**
-- *    move_addr_to_kernel     -       copy a socket address into kernel space
-- *    @uaddr: Address in user space
-- *    @kaddr: Address in kernel space
-- *    @ulen: Length in user space
-- *
-- *    The address is copied into kernel space. If the provided address is
-- *    too long an error code of -EINVAL is returned. If the copy gives
-- *    invalid addresses -EFAULT is returned. On a success 0 is returned.
-- */
--
--int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr)
--{
--      if (ulen < 0 || ulen > MAX_SOCK_ADDR)
--              return -EINVAL;
--      if (ulen == 0)
--              return 0;
--      if (copy_from_user(kaddr, uaddr, ulen))
--              return -EFAULT;
--      return audit_sockaddr(ulen, kaddr);
--}
--
--/**
-- *    move_addr_to_user       -       copy an address to user space
-- *    @kaddr: kernel space address
-- *    @klen: length of address in kernel
-- *    @uaddr: user space address
-- *    @ulen: pointer to user length field
-- *
-- *    The value pointed to by ulen on entry is the buffer length available.
-- *    This is overwritten with the buffer space used. -EINVAL is returned
-- *    if an overlong buffer is specified or a negative buffer size. -EFAULT
-- *    is returned if either the buffer or the length field are not
-- *    accessible.
-- *    After copying the data up to the limit the user specifies, the true
-- *    length of the data is written over the length limit the user
-- *    specified. Zero is returned for a success.
-- */
--
--int move_addr_to_user(void *kaddr, int klen, void __user *uaddr,
--                    int __user *ulen)
--{
--      int err;
--      int len;
--
--      err = get_user(len, ulen);
--      if (err)
--              return err;
--      if (len > klen)
--              len = klen;
--      if (len < 0 || len > MAX_SOCK_ADDR)
--              return -EINVAL;
--      if (len) {
--              if (audit_sockaddr(klen, kaddr))
--                      return -ENOMEM;
--              if (copy_to_user(uaddr, kaddr, len))
--                      return -EFAULT;
--      }
--      /*
--       *      "fromlen shall refer to the value before truncation.."
--       *                      1003.1g
--       */
--      return __put_user(klen, ulen);
--}
--
--#define SOCKFS_MAGIC 0x534F434B
--
--static struct kmem_cache *sock_inode_cachep __read_mostly;
--
--static struct inode *sock_alloc_inode(struct super_block *sb)
--{
--      struct socket_alloc *ei;
--
--      ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
--      if (!ei)
--              return NULL;
--      init_waitqueue_head(&ei->socket.wait);
--
--      ei->socket.fasync_list = NULL;
--      ei->socket.state = SS_UNCONNECTED;
--      ei->socket.flags = 0;
--      ei->socket.ops = NULL;
--      ei->socket.sk = NULL;
--      ei->socket.file = NULL;
--
--      return &ei->vfs_inode;
--}
--
--static void sock_destroy_inode(struct inode *inode)
--{
--      kmem_cache_free(sock_inode_cachep,
--                      container_of(inode, struct socket_alloc, vfs_inode));
--}
--
--static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
--{
--      struct socket_alloc *ei = (struct socket_alloc *)foo;
--
--      inode_init_once(&ei->vfs_inode);
--}
--
--static int init_inodecache(void)
--{
--      sock_inode_cachep = kmem_cache_create("sock_inode_cache",
--                                            sizeof(struct socket_alloc),
--                                            0,
--                                            (SLAB_HWCACHE_ALIGN |
--                                             SLAB_RECLAIM_ACCOUNT |
--                                             SLAB_MEM_SPREAD),
--                                            init_once,
--                                            NULL);
--      if (sock_inode_cachep == NULL)
--              return -ENOMEM;
--      return 0;
--}
--
--static struct super_operations sockfs_ops = {
--      .alloc_inode =  sock_alloc_inode,
--      .destroy_inode =sock_destroy_inode,
--      .statfs =       simple_statfs,
--};
--
--static int sockfs_get_sb(struct file_system_type *fs_type,
--                       int flags, const char *dev_name, void *data,
--                       struct vfsmount *mnt)
--{
--      return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC,
--                           mnt);
--}
--
--static struct vfsmount *sock_mnt __read_mostly;
--
--static struct file_system_type sock_fs_type = {
--      .name =         "sockfs",
--      .get_sb =       sockfs_get_sb,
--      .kill_sb =      kill_anon_super,
--};
--
--static int sockfs_delete_dentry(struct dentry *dentry)
--{
--      /*
--       * At creation time, we pretended this dentry was hashed
--       * (by clearing DCACHE_UNHASHED bit in d_flags)
--       * At delete time, we restore the truth : not hashed.
--       * (so that dput() can proceed correctly)
--       */
--      dentry->d_flags |= DCACHE_UNHASHED;
--      return 0;
--}
--
--/*
-- * sockfs_dname() is called from d_path().
-- */
--static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
--{
--      return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
--                              dentry->d_inode->i_ino);
--}
--
--static struct dentry_operations sockfs_dentry_operations = {
--      .d_delete = sockfs_delete_dentry,
--      .d_dname  = sockfs_dname,
--};
--
--/*
-- *    Obtains the first available file descriptor and sets it up for use.
-- *
-- *    These functions create file structures and maps them to fd space
-- *    of the current process. On success it returns file descriptor
-- *    and file struct implicitly stored in sock->file.
-- *    Note that another thread may close file descriptor before we return
-- *    from this function. We use the fact that now we do not refer
-- *    to socket after mapping. If one day we will need it, this
-- *    function will increment ref. count on file by 1.
-- *
-- *    In any case returned fd MAY BE not valid!
-- *    This race condition is unavoidable
-- *    with shared fd spaces, we cannot solve it inside kernel,
-- *    but we take care of internal coherence yet.
-- */
--
--static int sock_alloc_fd(struct file **filep)
--{
--      int fd;
--
--      fd = get_unused_fd();
--      if (likely(fd >= 0)) {
--              struct file *file = get_empty_filp();
--
--              *filep = file;
--              if (unlikely(!file)) {
--                      put_unused_fd(fd);
--                      return -ENFILE;
--              }
--      } else
--              *filep = NULL;
--      return fd;
--}
--
--static int sock_attach_fd(struct socket *sock, struct file *file)
--{
--      struct qstr name = { .name = "" };
--
--      file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
--      if (unlikely(!file->f_path.dentry))
--              return -ENOMEM;
--
--      file->f_path.dentry->d_op = &sockfs_dentry_operations;
--      /*
--       * We dont want to push this dentry into global dentry hash table.
--       * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
--       * This permits a working /proc/$pid/fd/XXX on sockets
--       */
--      file->f_path.dentry->d_flags &= ~DCACHE_UNHASHED;
--      d_instantiate(file->f_path.dentry, SOCK_INODE(sock));
--      file->f_path.mnt = mntget(sock_mnt);
--      file->f_mapping = file->f_path.dentry->d_inode->i_mapping;
--
--      sock->file = file;
--      file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
--      file->f_mode = FMODE_READ | FMODE_WRITE;
--      file->f_flags = O_RDWR;
--      file->f_pos = 0;
--      file->private_data = sock;
--
--      return 0;
--}
--
--int sock_map_fd(struct socket *sock)
--{
--      struct file *newfile;
--      int fd = sock_alloc_fd(&newfile);
--
--      if (likely(fd >= 0)) {
--              int err = sock_attach_fd(sock, newfile);
--
--              if (unlikely(err < 0)) {
--                      put_filp(newfile);
--                      put_unused_fd(fd);
--                      return err;
--              }
--              fd_install(fd, newfile);
--      }
--      return fd;
--}
--
--static struct socket *sock_from_file(struct file *file, int *err)
--{
--      if (file->f_op == &socket_file_ops)
--              return file->private_data;      /* set in sock_map_fd */
--
--      *err = -ENOTSOCK;
--      return NULL;
--}
--
--/**
-- *    sockfd_lookup   -       Go from a file number to its socket slot
-- *    @fd: file handle
-- *    @err: pointer to an error code return
-- *
-- *    The file handle passed in is locked and the socket it is bound
-- *    too is returned. If an error occurs the err pointer is overwritten
-- *    with a negative errno code and NULL is returned. The function checks
-- *    for both invalid handles and passing a handle which is not a socket.
-- *
-- *    On a success the socket object pointer is returned.
-- */
--
--struct socket *sockfd_lookup(int fd, int *err)
--{
--      struct file *file;
--      struct socket *sock;
--
--      file = fget(fd);
--      if (!file) {
--              *err = -EBADF;
--              return NULL;
--      }
--
--      sock = sock_from_file(file, err);
--      if (!sock)
--              fput(file);
--      return sock;
--}
--
--static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
--{
--      struct file *file;
--      struct socket *sock;
--
--      *err = -EBADF;
--      file = fget_light(fd, fput_needed);
--      if (file) {
--              sock = sock_from_file(file, err);
--              if (sock)
--                      return sock;
--              fput_light(file, *fput_needed);
--      }
--      return NULL;
--}
--
--/**
-- *    sock_alloc      -       allocate a socket
-- *
-- *    Allocate a new inode and socket object. The two are bound together
-- *    and initialised. The socket is then returned. If we are out of inodes
-- *    NULL is returned.
-- */
--
--static struct socket *sock_alloc(void)
--{
--      struct inode *inode;
--      struct socket *sock;
--
--      inode = new_inode(sock_mnt->mnt_sb);
--      if (!inode)
--              return NULL;
--
--      sock = SOCKET_I(inode);
--
--      inode->i_mode = S_IFSOCK | S_IRWXUGO;
--      inode->i_uid = current->fsuid;
--      inode->i_gid = current->fsgid;
--
--      get_cpu_var(sockets_in_use)++;
--      put_cpu_var(sockets_in_use);
--      return sock;
--}
--
--/*
-- *    In theory you can't get an open on this inode, but /proc provides
-- *    a back door. Remember to keep it shut otherwise you'll let the
-- *    creepy crawlies in.
-- */
--
--static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
--{
--      return -ENXIO;
--}
--
--const struct file_operations bad_sock_fops = {
--      .owner = THIS_MODULE,
--      .open = sock_no_open,
--};
--
--/**
-- *    sock_release    -       close a socket
-- *    @sock: socket to close
-- *
-- *    The socket is released from the protocol stack if it has a release
-- *    callback, and the inode is then released if the socket is bound to
-- *    an inode not a file.
-- */
--
--void sock_release(struct socket *sock)
--{
--      if (sock->ops) {
--              struct module *owner = sock->ops->owner;
--
--              sock->ops->release(sock);
--              sock->ops = NULL;
--              module_put(owner);
--      }
--
--      if (sock->fasync_list)
--              printk(KERN_ERR "sock_release: fasync list not empty!\n");
--
--      get_cpu_var(sockets_in_use)--;
--      put_cpu_var(sockets_in_use);
--      if (!sock->file) {
--              iput(SOCK_INODE(sock));
--              return;
--      }
--      sock->file = NULL;
--}
--
--static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
--                               struct msghdr *msg, size_t size)
--{
--      struct sock_iocb *si = kiocb_to_siocb(iocb);
--      int err;
--
--      si->sock = sock;
--      si->scm = NULL;
--      si->msg = msg;
--      si->size = size;
--
--      err = security_socket_sendmsg(sock, msg, size);
--      if (err)
--              return err;
--
--      return sock->ops->sendmsg(iocb, sock, msg, size);
--}
--
--int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
--{
--      struct kiocb iocb;
--      struct sock_iocb siocb;
--      int ret;
--
--      init_sync_kiocb(&iocb, NULL);
--      iocb.private = &siocb;
--      ret = __sock_sendmsg(&iocb, sock, msg, size);
--      if (-EIOCBQUEUED == ret)
--              ret = wait_on_sync_kiocb(&iocb);
--      return ret;
--}
--
--int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
--                 struct kvec *vec, size_t num, size_t size)
--{
--      mm_segment_t oldfs = get_fs();
--      int result;
--
--      set_fs(KERNEL_DS);
--      /*
--       * the following is safe, since for compiler definitions of kvec and
--       * iovec are identical, yielding the same in-core layout and alignment
--       */
--      msg->msg_iov = (struct iovec *)vec;
--      msg->msg_iovlen = num;
--      result = sock_sendmsg(sock, msg, size);
--      set_fs(oldfs);
--      return result;
--}
--
--/*
-- * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
-- */
--void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
--      struct sk_buff *skb)
--{
--      ktime_t kt = skb->tstamp;
--
--      if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
--              struct timeval tv;
--              /* Race occurred between timestamp enabling and packet
--                 receiving.  Fill in the current time for now. */
--              if (kt.tv64 == 0)
--                      kt = ktime_get_real();
--              skb->tstamp = kt;
--              tv = ktime_to_timeval(kt);
--              put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, sizeof(tv), &tv);
--      } else {
--              struct timespec ts;
--              /* Race occurred between timestamp enabling and packet
--                 receiving.  Fill in the current time for now. */
--              if (kt.tv64 == 0)
--                      kt = ktime_get_real();
--              skb->tstamp = kt;
--              ts = ktime_to_timespec(kt);
--              put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, sizeof(ts), &ts);
--      }
--}
--
--EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
--
--static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
--                               struct msghdr *msg, size_t size, int flags)
--{
--      int err;
--      struct sock_iocb *si = kiocb_to_siocb(iocb);
--
--      si->sock = sock;
--      si->scm = NULL;
--      si->msg = msg;
--      si->size = size;
--      si->flags = flags;
--
--      err = security_socket_recvmsg(sock, msg, size, flags);
--      if (err)
--              return err;
--
--      return sock->ops->recvmsg(iocb, sock, msg, size, flags);
--}
--
--int sock_recvmsg(struct socket *sock, struct msghdr *msg,
--               size_t size, int flags)
--{
--      struct kiocb iocb;
--      struct sock_iocb siocb;
--      int ret;
--
--      init_sync_kiocb(&iocb, NULL);
--      iocb.private = &siocb;
--      ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
--      if (-EIOCBQUEUED == ret)
--              ret = wait_on_sync_kiocb(&iocb);
--      return ret;
--}
--
--int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
--                 struct kvec *vec, size_t num, size_t size, int flags)
--{
--      mm_segment_t oldfs = get_fs();
--      int result;
--
--      set_fs(KERNEL_DS);
--      /*
--       * the following is safe, since for compiler definitions of kvec and
--       * iovec are identical, yielding the same in-core layout and alignment
--       */
--      msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
--      result = sock_recvmsg(sock, msg, size, flags);
--      set_fs(oldfs);
--      return result;
--}
--
--static void sock_aio_dtor(struct kiocb *iocb)
--{
--      kfree(iocb->private);
--}
--
--static ssize_t sock_sendpage(struct file *file, struct page *page,
--                           int offset, size_t size, loff_t *ppos, int more)
--{
--      struct socket *sock;
--      int flags;
--
--      sock = file->private_data;
--
--      flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
--      if (more)
--              flags |= MSG_MORE;
--
--      return sock->ops->sendpage(sock, page, offset, size, flags);
--}
--
--static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
--                                       struct sock_iocb *siocb)
--{
--      if (!is_sync_kiocb(iocb)) {
--              siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
--              if (!siocb)
--                      return NULL;
--              iocb->ki_dtor = sock_aio_dtor;
--      }
--
--      siocb->kiocb = iocb;
--      iocb->private = siocb;
--      return siocb;
--}
--
--static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
--              struct file *file, const struct iovec *iov,
--              unsigned long nr_segs)
--{
--      struct socket *sock = file->private_data;
--      size_t size = 0;
--      int i;
--
--      for (i = 0; i < nr_segs; i++)
--              size += iov[i].iov_len;
--
--      msg->msg_name = NULL;
--      msg->msg_namelen = 0;
--      msg->msg_control = NULL;
--      msg->msg_controllen = 0;
--      msg->msg_iov = (struct iovec *)iov;
--      msg->msg_iovlen = nr_segs;
--      msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
--
--      return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
--}
--
--static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
--                              unsigned long nr_segs, loff_t pos)
--{
--      struct sock_iocb siocb, *x;
--
--      if (pos != 0)
--              return -ESPIPE;
--
--      if (iocb->ki_left == 0) /* Match SYS5 behaviour */
--              return 0;
--
--
--      x = alloc_sock_iocb(iocb, &siocb);
--      if (!x)
--              return -ENOMEM;
--      return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
--}
--
--static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
--                      struct file *file, const struct iovec *iov,
--                      unsigned long nr_segs)
--{
--      struct socket *sock = file->private_data;
--      size_t size = 0;
--      int i;
--
--      for (i = 0; i < nr_segs; i++)
--              size += iov[i].iov_len;
--
--      msg->msg_name = NULL;
--      msg->msg_namelen = 0;
--      msg->msg_control = NULL;
--      msg->msg_controllen = 0;
--      msg->msg_iov = (struct iovec *)iov;
--      msg->msg_iovlen = nr_segs;
--      msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
--      if (sock->type == SOCK_SEQPACKET)
--              msg->msg_flags |= MSG_EOR;
--
--      return __sock_sendmsg(iocb, sock, msg, size);
--}
--
--static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
--                        unsigned long nr_segs, loff_t pos)
--{
--      struct sock_iocb siocb, *x;
--
--      if (pos != 0)
--              return -ESPIPE;
--
--      x = alloc_sock_iocb(iocb, &siocb);
--      if (!x)
--              return -ENOMEM;
--
--      return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
--}
--
--/*
-- * Atomic setting of ioctl hooks to avoid race
-- * with module unload.
-- */
--
--static DEFINE_MUTEX(br_ioctl_mutex);
--static int (*br_ioctl_hook) (unsigned int cmd, void __user *arg) = NULL;
--
--void brioctl_set(int (*hook) (unsigned int, void __user *))
--{
--      mutex_lock(&br_ioctl_mutex);
--      br_ioctl_hook = hook;
--      mutex_unlock(&br_ioctl_mutex);
--}
--
--EXPORT_SYMBOL(brioctl_set);
--
--static DEFINE_MUTEX(vlan_ioctl_mutex);
--static int (*vlan_ioctl_hook) (void __user *arg);
--
--void vlan_ioctl_set(int (*hook) (void __user *))
--{
--      mutex_lock(&vlan_ioctl_mutex);
--      vlan_ioctl_hook = hook;
--      mutex_unlock(&vlan_ioctl_mutex);
--}
--
--EXPORT_SYMBOL(vlan_ioctl_set);
--
--static DEFINE_MUTEX(dlci_ioctl_mutex);
--static int (*dlci_ioctl_hook) (unsigned int, void __user *);
--
--void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
--{
--      mutex_lock(&dlci_ioctl_mutex);
--      dlci_ioctl_hook = hook;
--      mutex_unlock(&dlci_ioctl_mutex);
--}
--
--EXPORT_SYMBOL(dlci_ioctl_set);
--
--/*
-- *    With an ioctl, arg may well be a user mode pointer, but we don't know
-- *    what to do with it - that's up to the protocol still.
-- */
--
--static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
--{
--      struct socket *sock;
--      void __user *argp = (void __user *)arg;
--      int pid, err;
--
--      sock = file->private_data;
--      if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
--              err = dev_ioctl(cmd, argp);
--      } else
--#ifdef CONFIG_WIRELESS_EXT
--      if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
--              err = dev_ioctl(cmd, argp);
--      } else
--#endif                                /* CONFIG_WIRELESS_EXT */
--              switch (cmd) {
--              case FIOSETOWN:
--              case SIOCSPGRP:
--                      err = -EFAULT;
--                      if (get_user(pid, (int __user *)argp))
--                              break;
--                      err = f_setown(sock->file, pid, 1);
--                      break;
--              case FIOGETOWN:
--              case SIOCGPGRP:
--                      err = put_user(f_getown(sock->file),
--                                     (int __user *)argp);
--                      break;
--              case SIOCGIFBR:
--              case SIOCSIFBR:
--              case SIOCBRADDBR:
--              case SIOCBRDELBR:
--                      err = -ENOPKG;
--                      if (!br_ioctl_hook)
--                              request_module("bridge");
--
--                      mutex_lock(&br_ioctl_mutex);
--                      if (br_ioctl_hook)
--                              err = br_ioctl_hook(cmd, argp);
--                      mutex_unlock(&br_ioctl_mutex);
--                      break;
--              case SIOCGIFVLAN:
--              case SIOCSIFVLAN:
--                      err = -ENOPKG;
--                      if (!vlan_ioctl_hook)
--                              request_module("8021q");
--
--                      mutex_lock(&vlan_ioctl_mutex);
--                      if (vlan_ioctl_hook)
--                              err = vlan_ioctl_hook(argp);
--                      mutex_unlock(&vlan_ioctl_mutex);
--                      break;
--              case SIOCADDDLCI:
--              case SIOCDELDLCI:
--                      err = -ENOPKG;
--                      if (!dlci_ioctl_hook)
--                              request_module("dlci");
--
--                      if (dlci_ioctl_hook) {
--                              mutex_lock(&dlci_ioctl_mutex);
--                              err = dlci_ioctl_hook(cmd, argp);
--                              mutex_unlock(&dlci_ioctl_mutex);
--                      }
--                      break;
--              default:
--                      err = sock->ops->ioctl(sock, cmd, arg);
+       memset(fl, 0, sizeof(struct flowi));
+-      fl->fl_net = &init_net;
+       ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
+       ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
+@@ -321,7 +318,7 @@
+                       fl->proto = nexthdr;
+                       return;
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+               case IPPROTO_MH:
+                       if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
+                               struct ip6_mh *mh;
+@@ -378,7 +375,7 @@
+       xdst = (struct xfrm_dst *)dst;
+       if (xdst->u.rt6.rt6i_idev->dev == dev) {
+-              struct inet6_dev *loopback_idev = in6_dev_get(&init_net.loopback_dev);
++              struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev);
+               BUG_ON(!loopback_idev);
+               do {
+diff -Nurb linux-2.6.22-590/net/ipv6/xfrm6_state.c linux-2.6.22-570/net/ipv6/xfrm6_state.c
+--- linux-2.6.22-590/net/ipv6/xfrm6_state.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/xfrm6_state.c    2007-07-08 19:32:17.000000000 -0400
+@@ -65,7 +65,7 @@
+               goto end;
+       /* Rule 2: select MIPv6 RO or inbound trigger */
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+       for (i = 0; i < n; i++) {
+               if (src[i] &&
+                   (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION ||
+@@ -130,7 +130,7 @@
+               goto end;
+       /* Rule 2: select MIPv6 RO or inbound trigger */
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++#ifdef CONFIG_IPV6_MIP6
+       for (i = 0; i < n; i++) {
+               if (src[i] &&
+                   (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION ||
+diff -Nurb linux-2.6.22-590/net/ipv6/xfrm6_tunnel.c linux-2.6.22-570/net/ipv6/xfrm6_tunnel.c
+--- linux-2.6.22-590/net/ipv6/xfrm6_tunnel.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipv6/xfrm6_tunnel.c   2007-07-08 19:32:17.000000000 -0400
+@@ -379,4 +379,3 @@
+ module_init(xfrm6_tunnel_init);
+ module_exit(xfrm6_tunnel_fini);
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_IPV6);
+diff -Nurb linux-2.6.22-590/net/ipx/af_ipx.c linux-2.6.22-570/net/ipx/af_ipx.c
+--- linux-2.6.22-590/net/ipx/af_ipx.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipx/af_ipx.c  2007-07-08 19:32:17.000000000 -0400
+@@ -347,9 +347,6 @@
+       struct net_device *dev = ptr;
+       struct ipx_interface *i, *tmp;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--                      /*
--                       * If this ioctl is unknown try to hand it down
--                       * to the NIC driver.
--                       */
--                      if (err == -ENOIOCTLCMD)
--                              err = dev_ioctl(cmd, argp);
--                      break;
--              }
--      return err;
--}
+       if (event != NETDEV_DOWN && event != NETDEV_UP)
+               goto out;
+@@ -989,7 +986,7 @@
+       if (intrfc)
+               ipxitf_put(intrfc);
+-      dev = dev_get_by_name(&init_net, idef->ipx_device);
++      dev = dev_get_by_name(idef->ipx_device);
+       rc = -ENODEV;
+       if (!dev)
+               goto out;
+@@ -1097,7 +1094,7 @@
+       if (!dlink_type)
+               goto out;
+-      dev = __dev_get_by_name(&init_net, idef->ipx_device);
++      dev = __dev_get_by_name(idef->ipx_device);
+       rc = -ENODEV;
+       if (!dev)
+               goto out;
+@@ -1192,7 +1189,7 @@
+               if (copy_from_user(&ifr, arg, sizeof(ifr)))
+                       break;
+               sipx = (struct sockaddr_ipx *)&ifr.ifr_addr;
+-              dev  = __dev_get_by_name(&init_net, ifr.ifr_name);
++              dev  = __dev_get_by_name(ifr.ifr_name);
+               rc   = -ENODEV;
+               if (!dev)
+                       break;
+@@ -1363,14 +1360,11 @@
+       .obj_size = sizeof(struct ipx_sock),
+ };
+-static int ipx_create(struct net *net, struct socket *sock, int protocol)
++static int ipx_create(struct socket *sock, int protocol)
+ {
+       int rc = -ESOCKTNOSUPPORT;
+       struct sock *sk;
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
 -
--int sock_create_lite(int family, int type, int protocol, struct socket **res)
--{
--      int err;
--      struct socket *sock = NULL;
+       /*
+        * SPX support is not anymore in the kernel sources. If you want to
+        * ressurrect it, completing it and making it understand shared skbs,
+@@ -1381,7 +1375,7 @@
+               goto out;
+       rc = -ENOMEM;
+-      sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto, 1);
++      sk = sk_alloc(PF_IPX, GFP_KERNEL, &ipx_proto, 1);
+       if (!sk)
+               goto out;
+ #ifdef IPX_REFCNT_DEBUG
+@@ -1650,9 +1644,6 @@
+       u16 ipx_pktsize;
+       int rc = 0;
+-      if (dev->nd_net != &init_net)
+-              goto drop;
 -
--      err = security_socket_create(family, type, protocol, 1);
--      if (err)
--              goto out;
+       /* Not ours */
+       if (skb->pkt_type == PACKET_OTHERHOST)
+               goto drop;
+diff -Nurb linux-2.6.22-590/net/ipx/ipx_proc.c linux-2.6.22-570/net/ipx/ipx_proc.c
+--- linux-2.6.22-590/net/ipx/ipx_proc.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/ipx/ipx_proc.c        2007-07-08 19:32:17.000000000 -0400
+@@ -9,7 +9,6 @@
+ #include <linux/proc_fs.h>
+ #include <linux/spinlock.h>
+ #include <linux/seq_file.h>
+-#include <net/net_namespace.h>
+ #include <net/tcp_states.h>
+ #include <net/ipx.h>
+@@ -354,7 +353,7 @@
+       struct proc_dir_entry *p;
+       int rc = -ENOMEM;
+-      ipx_proc_dir = proc_mkdir("ipx", init_net.proc_net);
++      ipx_proc_dir = proc_mkdir("ipx", proc_net);
+       if (!ipx_proc_dir)
+               goto out;
+@@ -382,7 +381,7 @@
+ out_route:
+       remove_proc_entry("interface", ipx_proc_dir);
+ out_interface:
+-      remove_proc_entry("ipx", init_net.proc_net);
++      remove_proc_entry("ipx", proc_net);
+       goto out;
+ }
+@@ -391,7 +390,7 @@
+       remove_proc_entry("interface", ipx_proc_dir);
+       remove_proc_entry("route", ipx_proc_dir);
+       remove_proc_entry("socket", ipx_proc_dir);
+-      remove_proc_entry("ipx", init_net.proc_net);
++      remove_proc_entry("ipx", proc_net);
+ }
+ #else /* CONFIG_PROC_FS */
+diff -Nurb linux-2.6.22-590/net/irda/af_irda.c linux-2.6.22-570/net/irda/af_irda.c
+--- linux-2.6.22-590/net/irda/af_irda.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/irda/af_irda.c        2007-07-08 19:32:17.000000000 -0400
+@@ -60,7 +60,7 @@
+ #include <net/irda/af_irda.h>
+-static int irda_create(struct net *net, struct socket *sock, int protocol);
++static int irda_create(struct socket *sock, int protocol);
+ static const struct proto_ops irda_stream_ops;
+ static const struct proto_ops irda_seqpacket_ops;
+@@ -831,7 +831,7 @@
+       IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
+-      err = irda_create(sk->sk_net, newsock, sk->sk_protocol);
++      err = irda_create(newsock, sk->sk_protocol);
+       if (err)
+               return err;
+@@ -1057,16 +1057,13 @@
+  *    Create IrDA socket
+  *
+  */
+-static int irda_create(struct net *net, struct socket *sock, int protocol)
++static int irda_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
+       struct irda_sock *self;
+       IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
 -
--      sock = sock_alloc();
--      if (!sock) {
--              err = -ENOMEM;
+       /* Check for valid socket type */
+       switch (sock->type) {
+       case SOCK_STREAM:     /* For TTP connections with SAR disabled */
+@@ -1078,7 +1075,7 @@
+       }
+       /* Allocate networking socket */
+-      sk = sk_alloc(net, PF_IRDA, GFP_ATOMIC, &irda_proto, 1);
++      sk = sk_alloc(PF_IRDA, GFP_ATOMIC, &irda_proto, 1);
+       if (sk == NULL)
+               return -ENOMEM;
+diff -Nurb linux-2.6.22-590/net/irda/irias_object.c linux-2.6.22-570/net/irda/irias_object.c
+--- linux-2.6.22-590/net/irda/irias_object.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/irda/irias_object.c   2007-07-08 19:32:17.000000000 -0400
+@@ -36,6 +36,39 @@
+  */
+ struct ias_value irias_missing = { IAS_MISSING, 0, 0, 0, {0}};
++/*
++ * Function strndup (str, max)
++ *
++ *    My own kernel version of strndup!
++ *
++ * Faster, check boundary... Jean II
++ */
++static char *strndup(char *str, size_t max)
++{
++      char *new_str;
++      int len;
++
++      /* Check string */
++      if (str == NULL)
++              return NULL;
++      /* Check length, truncate */
++      len = strlen(str);
++      if(len > max)
++              len = max;
++
++      /* Allocate new string */
++      new_str = kmalloc(len + 1, GFP_ATOMIC);
++      if (new_str == NULL) {
++              IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++              return NULL;
++      }
++
++      /* Copy and truncate */
++      memcpy(new_str, str, len);
++      new_str[len] = '\0';
++
++      return new_str;
++}
+ /*
+  * Function ias_new_object (name, id)
+@@ -57,7 +90,7 @@
+       }
+       obj->magic = IAS_OBJECT_MAGIC;
+-      obj->name = kstrndup(name, IAS_MAX_CLASSNAME, GFP_ATOMIC);
++      obj->name = strndup(name, IAS_MAX_CLASSNAME);
+       if (!obj->name) {
+               IRDA_WARNING("%s(), Unable to allocate name!\n",
+                            __FUNCTION__);
+@@ -327,7 +360,7 @@
+       }
+       attrib->magic = IAS_ATTRIB_MAGIC;
+-      attrib->name = kstrndup(name, IAS_MAX_ATTRIBNAME, GFP_ATOMIC);
++      attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
+       /* Insert value */
+       attrib->value = irias_new_integer_value(value);
+@@ -371,7 +404,7 @@
+       }
+       attrib->magic = IAS_ATTRIB_MAGIC;
+-      attrib->name = kstrndup(name, IAS_MAX_ATTRIBNAME, GFP_ATOMIC);
++      attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
+       attrib->value = irias_new_octseq_value( octets, len);
+       if (!attrib->name || !attrib->value) {
+@@ -413,7 +446,7 @@
+       }
+       attrib->magic = IAS_ATTRIB_MAGIC;
+-      attrib->name = kstrndup(name, IAS_MAX_ATTRIBNAME, GFP_ATOMIC);
++      attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
+       attrib->value = irias_new_string_value(value);
+       if (!attrib->name || !attrib->value) {
+@@ -473,7 +506,7 @@
+       value->type = IAS_STRING;
+       value->charset = CS_ASCII;
+-      value->t.string = kstrndup(string, IAS_MAX_STRING, GFP_ATOMIC);
++      value->t.string = strndup(string, IAS_MAX_STRING);
+       if (!value->t.string) {
+               IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
+               kfree(value);
+diff -Nurb linux-2.6.22-590/net/irda/irlap_frame.c linux-2.6.22-570/net/irda/irlap_frame.c
+--- linux-2.6.22-590/net/irda/irlap_frame.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/irda/irlap_frame.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1319,9 +1319,6 @@
+       int command;
+       __u8 control;
+-      if (dev->nd_net != &init_net)
 -              goto out;
--      }
--
--      sock->type = type;
--      err = security_socket_post_create(sock, family, type, protocol, 1);
--      if (err)
--              goto out_release;
 -
--out:
--      *res = sock;
--      return err;
--out_release:
--      sock_release(sock);
--      sock = NULL;
--      goto out;
--}
+       /* FIXME: should we get our own field? */
+       self = (struct irlap_cb *) dev->atalk_ptr;
+diff -Nurb linux-2.6.22-590/net/irda/irproc.c linux-2.6.22-570/net/irda/irproc.c
+--- linux-2.6.22-590/net/irda/irproc.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/irda/irproc.c 2007-07-08 19:32:17.000000000 -0400
+@@ -28,7 +28,6 @@
+ #include <linux/seq_file.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+-#include <net/net_namespace.h>
+ #include <net/irda/irda.h>
+ #include <net/irda/irlap.h>
+@@ -67,7 +66,7 @@
+       int i;
+       struct proc_dir_entry *d;
+-      proc_irda = proc_mkdir("irda", init_net.proc_net);
++      proc_irda = proc_mkdir("irda", proc_net);
+       if (proc_irda == NULL)
+               return;
+       proc_irda->owner = THIS_MODULE;
+@@ -93,7 +92,7 @@
+               for (i=0; i<ARRAY_SIZE(irda_dirs); i++)
+                       remove_proc_entry(irda_dirs[i].name, proc_irda);
+-              remove_proc_entry("irda", init_net.proc_net);
++              remove_proc_entry("irda", proc_net);
+               proc_irda = NULL;
+       }
+ }
+diff -Nurb linux-2.6.22-590/net/key/af_key.c linux-2.6.22-570/net/key/af_key.c
+--- linux-2.6.22-590/net/key/af_key.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/key/af_key.c  2007-07-08 19:32:17.000000000 -0400
+@@ -28,7 +28,6 @@
+ #include <linux/init.h>
+ #include <net/xfrm.h>
+ #include <linux/audit.h>
+-#include <net/net_namespace.h>
+ #include <net/sock.h>
+@@ -137,14 +136,11 @@
+       .obj_size = sizeof(struct pfkey_sock),
+ };
+-static int pfkey_create(struct net *net, struct socket *sock, int protocol)
++static int pfkey_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
+       int err;
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
 -
--/* No kernel lock held - perfect */
--static unsigned int sock_poll(struct file *file, poll_table *wait)
--{
--      struct socket *sock;
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+       if (sock->type != SOCK_RAW)
+@@ -153,7 +149,7 @@
+               return -EPROTONOSUPPORT;
+       err = -ENOMEM;
+-      sk = sk_alloc(net, PF_KEY, GFP_KERNEL, &key_proto, 1);
++      sk = sk_alloc(PF_KEY, GFP_KERNEL, &key_proto, 1);
+       if (sk == NULL)
+               goto out;
+@@ -3785,7 +3781,7 @@
+ static void __exit ipsec_pfkey_exit(void)
+ {
+       xfrm_unregister_km(&pfkeyv2_mgr);
+-      remove_proc_entry("pfkey", init_net.proc_net);
++      remove_proc_entry("net/pfkey", NULL);
+       sock_unregister(PF_KEY);
+       proto_unregister(&key_proto);
+ }
+@@ -3802,7 +3798,7 @@
+               goto out_unregister_key_proto;
+ #ifdef CONFIG_PROC_FS
+       err = -ENOMEM;
+-      if (create_proc_read_entry("pfkey", 0, init_net.proc_net, pfkey_read_proc, NULL) == NULL)
++      if (create_proc_read_entry("net/pfkey", 0, NULL, pfkey_read_proc, NULL) == NULL)
+               goto out_sock_unregister;
+ #endif
+       err = xfrm_register_km(&pfkeyv2_mgr);
+diff -Nurb linux-2.6.22-590/net/llc/af_llc.c linux-2.6.22-570/net/llc/af_llc.c
+--- linux-2.6.22-590/net/llc/af_llc.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/llc/af_llc.c  2007-07-08 19:32:17.000000000 -0400
+@@ -150,17 +150,14 @@
+  *    socket type we have available.
+  *    Returns 0 upon success, negative upon failure.
+  */
+-static int llc_ui_create(struct net *net, struct socket *sock, int protocol)
++static int llc_ui_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
+       int rc = -ESOCKTNOSUPPORT;
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
 -
--      /*
--       *      We can't return errors to poll, so it's either yes or no.
--       */
--      sock = file->private_data;
--      return sock->ops->poll(file, sock, wait);
--}
+       if (likely(sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM)) {
+               rc = -ENOMEM;
+-              sk = llc_sk_alloc(net, PF_LLC, GFP_KERNEL, &llc_proto);
++              sk = llc_sk_alloc(PF_LLC, GFP_KERNEL, &llc_proto);
+               if (sk) {
+                       rc = 0;
+                       llc_ui_sk_init(sock, sk);
+@@ -252,7 +249,7 @@
+       if (!sock_flag(sk, SOCK_ZAPPED))
+               goto out;
+       rc = -ENODEV;
+-      llc->dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd);
++      llc->dev = dev_getfirstbyhwtype(addr->sllc_arphrd);
+       if (!llc->dev)
+               goto out;
+       rc = -EUSERS;
+@@ -303,7 +300,7 @@
+               goto out;
+       rc = -ENODEV;
+       rtnl_lock();
+-      llc->dev = dev_getbyhwaddr(&init_net, addr->sllc_arphrd, addr->sllc_mac);
++      llc->dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_mac);
+       rtnl_unlock();
+       if (!llc->dev)
+               goto out;
+diff -Nurb linux-2.6.22-590/net/llc/llc_conn.c linux-2.6.22-570/net/llc/llc_conn.c
+--- linux-2.6.22-590/net/llc/llc_conn.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/llc/llc_conn.c        2007-07-08 19:32:17.000000000 -0400
+@@ -700,7 +700,7 @@
+                                            struct llc_addr *saddr,
+                                            struct llc_addr *daddr)
+ {
+-      struct sock *newsk = llc_sk_alloc(sk->sk_net, sk->sk_family, GFP_ATOMIC,
++      struct sock *newsk = llc_sk_alloc(sk->sk_family, GFP_ATOMIC,
+                                         sk->sk_prot);
+       struct llc_sock *newllc, *llc = llc_sk(sk);
+@@ -867,9 +867,9 @@
+  *    Allocates a LLC sock and initializes it. Returns the new LLC sock
+  *    or %NULL if there's no memory available for one
+  */
+-struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot)
++struct sock *llc_sk_alloc(int family, gfp_t priority, struct proto *prot)
+ {
+-      struct sock *sk = sk_alloc(net, family, priority, prot, 1);
++      struct sock *sk = sk_alloc(family, priority, prot, 1);
+       if (!sk)
+               goto out;
+diff -Nurb linux-2.6.22-590/net/llc/llc_core.c linux-2.6.22-570/net/llc/llc_core.c
+--- linux-2.6.22-590/net/llc/llc_core.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/llc/llc_core.c        2007-07-08 19:32:17.000000000 -0400
+@@ -19,7 +19,6 @@
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/init.h>
+-#include <net/net_namespace.h>
+ #include <net/llc.h>
+ LIST_HEAD(llc_sap_list);
+@@ -163,8 +162,7 @@
+ {
+       struct net_device *dev;
+-      /* XXX sapan 
+-      dev = first_net_device(&init_net);
++      dev = first_net_device();
+       if (dev != NULL)
+               dev = next_net_device(dev);
+@@ -174,7 +172,6 @@
+               memset(llc_station_mac_sa, 0, ETH_ALEN);
+       dev_add_pack(&llc_packet_type);
+       dev_add_pack(&llc_tr_packet_type);
+-      */
+       return 0;
+ }
+diff -Nurb linux-2.6.22-590/net/llc/llc_input.c linux-2.6.22-570/net/llc/llc_input.c
+--- linux-2.6.22-590/net/llc/llc_input.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/llc/llc_input.c       2007-07-08 19:32:17.000000000 -0400
+@@ -12,7 +12,6 @@
+  * See the GNU General Public License for more details.
+  */
+ #include <linux/netdevice.h>
+-#include <net/net_namespace.h>
+ #include <net/llc.h>
+ #include <net/llc_pdu.h>
+ #include <net/llc_sap.h>
+@@ -146,9 +145,6 @@
+       int (*rcv)(struct sk_buff *, struct net_device *,
+                  struct packet_type *, struct net_device *);
+-      if (dev->nd_net != &init_net)
+-              goto drop;
 -
--static int sock_mmap(struct file *file, struct vm_area_struct *vma)
+       /*
+        * When the interface is in promisc. mode, drop all the crap that it
+        * receives, do not try to analyse it.
+diff -Nurb linux-2.6.22-590/net/llc/llc_proc.c linux-2.6.22-570/net/llc/llc_proc.c
+--- linux-2.6.22-590/net/llc/llc_proc.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/llc/llc_proc.c        2007-07-08 19:32:17.000000000 -0400
+@@ -18,7 +18,6 @@
+ #include <linux/errno.h>
+ #include <linux/seq_file.h>
+ #include <net/sock.h>
+-#include <net/net_namespace.h>
+ #include <net/llc.h>
+ #include <net/llc_c_ac.h>
+ #include <net/llc_c_ev.h>
+@@ -232,7 +231,7 @@
+       int rc = -ENOMEM;
+       struct proc_dir_entry *p;
+-      llc_proc_dir = proc_mkdir("llc", init_net.proc_net);
++      llc_proc_dir = proc_mkdir("llc", proc_net);
+       if (!llc_proc_dir)
+               goto out;
+       llc_proc_dir->owner = THIS_MODULE;
+@@ -255,7 +254,7 @@
+ out_core:
+       remove_proc_entry("socket", llc_proc_dir);
+ out_socket:
+-      remove_proc_entry("llc", init_net.proc_net);
++      remove_proc_entry("llc", proc_net);
+       goto out;
+ }
+@@ -263,5 +262,5 @@
+ {
+       remove_proc_entry("socket", llc_proc_dir);
+       remove_proc_entry("core", llc_proc_dir);
+-      remove_proc_entry("llc", init_net.proc_net);
++      remove_proc_entry("llc", proc_net);
+ }
+diff -Nurb linux-2.6.22-590/net/mac80211/ieee80211_ioctl.c linux-2.6.22-570/net/mac80211/ieee80211_ioctl.c
+--- linux-2.6.22-590/net/mac80211/ieee80211_ioctl.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/mac80211/ieee80211_ioctl.c    2007-07-08 19:32:17.000000000 -0400
+@@ -838,29 +838,6 @@
+ }
+-static int ieee80211_ioctl_giwrate(struct net_device *dev,
+-                                struct iw_request_info *info,
+-                                struct iw_param *rate, char *extra)
 -{
--      struct socket *sock = file->private_data;
+-      struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-      struct sta_info *sta;
+-      struct ieee80211_sub_if_data *sdata;
 -
--      return sock->ops->mmap(file, sock, vma);
+-      sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-      if (sdata->type == IEEE80211_IF_TYPE_STA)
+-              sta = sta_info_get(local, sdata->u.sta.bssid);
+-      else
+-              return -EOPNOTSUPP;
+-      if (!sta)
+-              return -ENODEV;
+-      if (sta->txrate < local->oper_hw_mode->num_rates)
+-              rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;
+-      else
+-              rate->value = 0;
+-      sta_info_put(sta);
+-      return 0;
 -}
 -
--static int sock_close(struct inode *inode, struct file *filp)
+ static int ieee80211_ioctl_siwrts(struct net_device *dev,
+                                 struct iw_request_info *info,
+                                 struct iw_param *rts, char *extra)
+@@ -1802,7 +1779,7 @@
+       (iw_handler) NULL,                              /* -- hole -- */
+       (iw_handler) NULL,                              /* -- hole -- */
+       (iw_handler) NULL,                              /* SIOCSIWRATE */
+-      (iw_handler) ieee80211_ioctl_giwrate,           /* SIOCGIWRATE */
++      (iw_handler) NULL,                              /* SIOCGIWRATE */
+       (iw_handler) ieee80211_ioctl_siwrts,            /* SIOCSIWRTS */
+       (iw_handler) ieee80211_ioctl_giwrts,            /* SIOCGIWRTS */
+       (iw_handler) ieee80211_ioctl_siwfrag,           /* SIOCSIWFRAG */
+diff -Nurb linux-2.6.22-590/net/netfilter/core.c linux-2.6.22-570/net/netfilter/core.c
+--- linux-2.6.22-590/net/netfilter/core.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netfilter/core.c      2007-07-08 19:32:17.000000000 -0400
+@@ -20,7 +20,6 @@
+ #include <linux/proc_fs.h>
+ #include <linux/mutex.h>
+ #include <net/sock.h>
+-#include <net/net_namespace.h>
+ #include "nf_internals.h"
+@@ -204,9 +203,7 @@
+               return 0;
+       /* Not exclusive use of packet?  Must copy. */
+-      if (skb_cloned(*pskb) && !skb_clone_writable(*pskb, writable_len))
+-              goto copy_skb;
+-      if (skb_shared(*pskb))
++      if (skb_shared(*pskb) || skb_cloned(*pskb))
+               goto copy_skb;
+       return pskb_may_pull(*pskb, writable_len);
+@@ -281,28 +278,8 @@
+ #endif /* CONFIG_NF_CONNTRACK */
+ #ifdef CONFIG_PROC_FS
+-static int netfilter_proc_init(struct net * net)
 -{
--      /*
--       *      It was possible the inode is NULL we were
--       *      closing an unfinished socket.
--       */
+-      int error = -ENOMEM;
+-      net->proc_net_netfilter = proc_mkdir("netfilter", net->proc_net);
 -
--      if (!inode) {
--              printk(KERN_DEBUG "sock_close: NULL inode\n");
--              return 0;
+-      if (net->proc_net_netfilter) {
+-              net->proc_net_netfilter->data = net;
+-              error = 0;
 -      }
--      sock_fasync(-1, filp, 0);
--      sock_release(SOCKET_I(inode));
--      return 0;
+-      return error;
 -}
 -
--/*
-- *    Update the socket async list
-- *
-- *    Fasync_list locking strategy.
-- *
-- *    1. fasync_list is modified only under process context socket lock
-- *       i.e. under semaphore.
-- *    2. fasync_list is used under read_lock(&sk->sk_callback_lock)
-- *       or under socket lock.
-- *    3. fasync_list can be used from softirq context, so that
-- *       modification under socket lock have to be enhanced with
-- *       write_lock_bh(&sk->sk_callback_lock).
-- *                                                    --ANK (990710)
-- */
--
--static int sock_fasync(int fd, struct file *filp, int on)
+-static void netfilter_proc_exit(struct net *net)
 -{
--      struct fasync_struct *fa, *fna = NULL, **prev;
--      struct socket *sock;
--      struct sock *sk;
--
--      if (on) {
--              fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
--              if (fna == NULL)
--                      return -ENOMEM;
--      }
--
--      sock = filp->private_data;
--
--      sk = sock->sk;
--      if (sk == NULL) {
--              kfree(fna);
--              return -EINVAL;
--      }
--
--      lock_sock(sk);
--
--      prev = &(sock->fasync_list);
+-      remove_proc_entry("netfilter", net->proc_net);
+-}
 -
--      for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev)
--              if (fa->fa_file == filp)
--                      break;
+-static struct pernet_operations netfilter_proc_ops = {
+-      .init = netfilter_proc_init,
+-      .exit = netfilter_proc_exit,
+-};
 -
--      if (on) {
--              if (fa != NULL) {
--                      write_lock_bh(&sk->sk_callback_lock);
--                      fa->fa_fd = fd;
--                      write_unlock_bh(&sk->sk_callback_lock);
++struct proc_dir_entry *proc_net_netfilter;
++EXPORT_SYMBOL(proc_net_netfilter);
+ #endif
+ void __init netfilter_init(void)
+@@ -314,7 +291,8 @@
+       }
+ #ifdef CONFIG_PROC_FS
+-      if (register_pernet_subsys(&netfilter_proc_ops) < 0)
++      proc_net_netfilter = proc_mkdir("netfilter", proc_net);
++      if (!proc_net_netfilter)
+               panic("cannot create netfilter proc entry");
+ #endif
+diff -Nurb linux-2.6.22-590/net/netfilter/nf_conntrack_h323_main.c linux-2.6.22-570/net/netfilter/nf_conntrack_h323_main.c
+--- linux-2.6.22-590/net/netfilter/nf_conntrack_h323_main.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netfilter/nf_conntrack_h323_main.c    2007-07-08 19:32:17.000000000 -0400
+@@ -724,8 +724,6 @@
+       memset(&fl1, 0, sizeof(fl1));
+       memset(&fl2, 0, sizeof(fl2));
+-      fl1.fl_net = &init_net;
+-      fl2.fl_net = &init_net;
+       switch (family) {
+       case AF_INET: {
+diff -Nurb linux-2.6.22-590/net/netfilter/nf_conntrack_standalone.c linux-2.6.22-570/net/netfilter/nf_conntrack_standalone.c
+--- linux-2.6.22-590/net/netfilter/nf_conntrack_standalone.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netfilter/nf_conntrack_standalone.c   2007-07-08 19:32:17.000000000 -0400
+@@ -14,7 +14,6 @@
+ #include <linux/seq_file.h>
+ #include <linux/percpu.h>
+ #include <linux/netdevice.h>
+-#include <net/net_namespace.h>
+ #ifdef CONFIG_SYSCTL
+ #include <linux/sysctl.h>
+ #endif
+@@ -420,14 +419,14 @@
+               return ret;
+ #ifdef CONFIG_PROC_FS
+-      proc = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops);
++      proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
+       if (!proc) goto cleanup_init;
+-      proc_exp = proc_net_fops_create(&init_net, "nf_conntrack_expect", 0440,
++      proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
+                                       &exp_file_ops);
+       if (!proc_exp) goto cleanup_proc;
+-      proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, init_net.proc_net_stat);
++      proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
+       if (!proc_stat)
+               goto cleanup_proc_exp;
+@@ -448,11 +447,11 @@
+  cleanup_proc_stat:
+ #endif
+ #ifdef CONFIG_PROC_FS
+-      remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
++      remove_proc_entry("nf_conntrack", proc_net_stat);
+  cleanup_proc_exp:
+-      proc_net_remove(&init_net, "nf_conntrack_expect");
++      proc_net_remove("nf_conntrack_expect");
+  cleanup_proc:
+-      proc_net_remove(&init_net, "nf_conntrack");
++      proc_net_remove("nf_conntrack");
+  cleanup_init:
+ #endif /* CNFIG_PROC_FS */
+       nf_conntrack_cleanup();
+@@ -465,9 +464,9 @@
+       unregister_sysctl_table(nf_ct_sysctl_header);
+ #endif
+ #ifdef CONFIG_PROC_FS
+-      remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
+-      proc_net_remove(&init_net, "nf_conntrack_expect");
+-      proc_net_remove(&init_net, "nf_conntrack");
++      remove_proc_entry("nf_conntrack", proc_net_stat);
++      proc_net_remove("nf_conntrack_expect");
++      proc_net_remove("nf_conntrack");
+ #endif /* CNFIG_PROC_FS */
+       nf_conntrack_cleanup();
+ }
+diff -Nurb linux-2.6.22-590/net/netfilter/nf_log.c linux-2.6.22-570/net/netfilter/nf_log.c
+--- linux-2.6.22-590/net/netfilter/nf_log.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netfilter/nf_log.c    2007-07-08 19:32:17.000000000 -0400
+@@ -168,8 +168,7 @@
+ #ifdef CONFIG_PROC_FS
+       struct proc_dir_entry *pde;
+-      pde = create_proc_entry("nf_log", S_IRUGO,
+-              init_net.proc_net_netfilter);
++      pde = create_proc_entry("nf_log", S_IRUGO, proc_net_netfilter);
+       if (!pde)
+               return -1;
+diff -Nurb linux-2.6.22-590/net/netfilter/nf_queue.c linux-2.6.22-570/net/netfilter/nf_queue.c
+--- linux-2.6.22-590/net/netfilter/nf_queue.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netfilter/nf_queue.c  2007-07-08 19:32:17.000000000 -0400
+@@ -346,7 +346,7 @@
+ #ifdef CONFIG_PROC_FS
+       struct proc_dir_entry *pde;
+-      pde = create_proc_entry("nf_queue", S_IRUGO, init_net.proc_net_netfilter);
++      pde = create_proc_entry("nf_queue", S_IRUGO, proc_net_netfilter);
+       if (!pde)
+               return -1;
+       pde->proc_fops = &nfqueue_file_ops;
+diff -Nurb linux-2.6.22-590/net/netfilter/nfnetlink.c linux-2.6.22-570/net/netfilter/nfnetlink.c
+--- linux-2.6.22-590/net/netfilter/nfnetlink.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netfilter/nfnetlink.c 2007-07-08 19:32:17.000000000 -0400
+@@ -264,7 +264,7 @@
+ {
+       printk("Netfilter messages via NETLINK v%s.\n", nfversion);
+-      nfnl = netlink_kernel_create(&init_net, NETLINK_NETFILTER, NFNLGRP_MAX,
++      nfnl = netlink_kernel_create(NETLINK_NETFILTER, NFNLGRP_MAX,
+                                    nfnetlink_rcv, NULL, THIS_MODULE);
+       if (!nfnl) {
+               printk(KERN_ERR "cannot initialize nfnetlink!\n");
+diff -Nurb linux-2.6.22-590/net/netfilter/nfnetlink_log.c linux-2.6.22-570/net/netfilter/nfnetlink_log.c
+--- linux-2.6.22-590/net/netfilter/nfnetlink_log.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netfilter/nfnetlink_log.c     2007-07-08 19:32:17.000000000 -0400
+@@ -705,8 +705,7 @@
+                       hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
+                               UDEBUG("node = %p\n", inst);
+-                              if ((n->net == &init_net) && 
+-                                  (n->pid == inst->peer_pid))
++                              if (n->pid == inst->peer_pid)
+                                       __instance_destroy(inst);
+                       }
+               }
+@@ -1024,7 +1023,7 @@
+ #ifdef CONFIG_PROC_FS
+       proc_nful = create_proc_entry("nfnetlink_log", 0440,
+-                                    init_net.proc_net_netfilter);
++                                    proc_net_netfilter);
+       if (!proc_nful)
+               goto cleanup_subsys;
+       proc_nful->proc_fops = &nful_file_ops;
+@@ -1044,7 +1043,7 @@
+ {
+       nf_log_unregister(&nfulnl_logger);
+ #ifdef CONFIG_PROC_FS
+-      remove_proc_entry("nfnetlink_log", init_net.proc_net_netfilter);
++      remove_proc_entry("nfnetlink_log", proc_net_netfilter);
+ #endif
+       nfnetlink_subsys_unregister(&nfulnl_subsys);
+       netlink_unregister_notifier(&nfulnl_rtnl_notifier);
+diff -Nurb linux-2.6.22-590/net/netfilter/nfnetlink_queue.c linux-2.6.22-570/net/netfilter/nfnetlink_queue.c
+--- linux-2.6.22-590/net/netfilter/nfnetlink_queue.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netfilter/nfnetlink_queue.c   2007-07-08 19:32:17.000000000 -0400
+@@ -734,9 +734,6 @@
+ {
+       struct net_device *dev = ptr;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--                      kfree(fna);
--                      goto out;
--              }
--              fna->fa_file = filp;
--              fna->fa_fd = fd;
--              fna->magic = FASYNC_MAGIC;
--              fna->fa_next = sock->fasync_list;
--              write_lock_bh(&sk->sk_callback_lock);
--              sock->fasync_list = fna;
--              write_unlock_bh(&sk->sk_callback_lock);
--      } else {
--              if (fa != NULL) {
--                      write_lock_bh(&sk->sk_callback_lock);
--                      *prev = fa->fa_next;
--                      write_unlock_bh(&sk->sk_callback_lock);
--                      kfree(fa);
--              }
--      }
+       /* Drop any packets associated with the downed device */
+       if (event == NETDEV_DOWN)
+               nfqnl_dev_drop(dev->ifindex);
+@@ -765,8 +762,7 @@
+                       struct hlist_head *head = &instance_table[i];
+                       hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
+-                              if ((n->net == &init_net) && 
+-                                  (n->pid == inst->peer_pid))
++                              if (n->pid == inst->peer_pid)
+                                       __instance_destroy(inst);
+                       }
+               }
+@@ -1110,7 +1106,7 @@
+ #ifdef CONFIG_PROC_FS
+       proc_nfqueue = create_proc_entry("nfnetlink_queue", 0440,
+-                                       init_net.proc_net_netfilter);
++                                       proc_net_netfilter);
+       if (!proc_nfqueue)
+               goto cleanup_subsys;
+       proc_nfqueue->proc_fops = &nfqnl_file_ops;
+@@ -1133,7 +1129,7 @@
+       nf_unregister_queue_handlers(&nfqh);
+       unregister_netdevice_notifier(&nfqnl_dev_notifier);
+ #ifdef CONFIG_PROC_FS
+-      remove_proc_entry("nfnetlink_queue", init_net.proc_net_netfilter);
++      remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
+ #endif
+       nfnetlink_subsys_unregister(&nfqnl_subsys);
+       netlink_unregister_notifier(&nfqnl_rtnl_notifier);
+diff -Nurb linux-2.6.22-590/net/netfilter/x_tables.c linux-2.6.22-570/net/netfilter/x_tables.c
+--- linux-2.6.22-590/net/netfilter/x_tables.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netfilter/x_tables.c  2007-07-08 19:32:17.000000000 -0400
+@@ -22,7 +22,6 @@
+ #include <linux/vmalloc.h>
+ #include <linux/mutex.h>
+ #include <linux/mm.h>
+-#include <net/net_namespace.h>
+ #include <linux/netfilter/x_tables.h>
+ #include <linux/netfilter_arp.h>
+@@ -38,16 +37,11 @@
+       struct mutex mutex;
+       struct list_head match;
+       struct list_head target;
+-      struct mutex compat_mutex;
+-};
 -
--out:
--      release_sock(sock->sk);
--      return 0;
--}
 -
--/* This function may be called only under socket lock or callback_lock */
+-struct xt_af_pernet {
+       struct list_head tables;
++      struct mutex compat_mutex;
+ };
+-static struct xt_af * xt;
 -
--int sock_wake_async(struct socket *sock, int how, int band)
++static struct xt_af *xt;
+ #ifdef DEBUG_IP_FIREWALL_USER
+ #define duprintf(format, args...) printk(format , ## args)
+@@ -292,9 +286,9 @@
+               return 1;
+       }
+       if (target == 1)
+-              have_rev = target_revfn( af, name, revision, &best);
++              have_rev = target_revfn(af, name, revision, &best);
+       else
+-              have_rev = match_revfn( af, name, revision, &best);
++              have_rev = match_revfn(af, name, revision, &best);
+       mutex_unlock(&xt[af].mutex);
+       /* Nothing at all?  Return 0 to try loading module. */
+@@ -539,14 +533,14 @@
+ EXPORT_SYMBOL(xt_free_table_info);
+ /* Find table by name, grabs mutex & ref.  Returns ERR_PTR() on error. */
+-struct xt_table *xt_find_table_lock(struct net *net, int af, const char *name)
++struct xt_table *xt_find_table_lock(int af, const char *name)
+ {
+       struct xt_table *t;
+       if (mutex_lock_interruptible(&xt[af].mutex) != 0)
+               return ERR_PTR(-EINTR);
+-      list_for_each_entry(t, &net->xtn[af].tables, list)
++      list_for_each_entry(t, &xt[af].tables, list)
+               if (strcmp(t->name, name) == 0 && try_module_get(t->me))
+                       return t;
+       mutex_unlock(&xt[af].mutex);
+@@ -602,7 +596,7 @@
+ }
+ EXPORT_SYMBOL_GPL(xt_replace_table);
+-int xt_register_table(struct net *net, struct xt_table *table,
++int xt_register_table(struct xt_table *table,
+                     struct xt_table_info *bootstrap,
+                     struct xt_table_info *newinfo)
+ {
+@@ -615,7 +609,7 @@
+               return ret;
+       /* Don't autoload: we'd eat our tail... */
+-      list_for_each_entry(t, &net->xtn[table->af].tables, list) {
++      list_for_each_entry(t, &xt[table->af].tables, list) {
+               if (strcmp(t->name, table->name) == 0) {
+                       ret = -EEXIST;
+                       goto unlock;
+@@ -634,7 +628,7 @@
+       /* save number of initial entries */
+       private->initial_entries = private->number;
+-      list_add(&table->list, &net->xtn[table->af].tables);
++      list_add(&table->list, &xt[table->af].tables);
+       ret = 0;
+  unlock:
+@@ -672,7 +666,7 @@
+       return pos ? NULL : head;
+ }
+-static struct list_head *type2list(struct net *net, u_int16_t af, u_int16_t type)
++static struct list_head *type2list(u_int16_t af, u_int16_t type)
+ {
+       struct list_head *list;
+@@ -684,7 +678,7 @@
+               list = &xt[af].match;
+               break;
+       case TABLE:
+-              list = &net->xtn[af].tables;
++              list = &xt[af].tables;
+               break;
+       default:
+               list = NULL;
+@@ -697,7 +691,6 @@
+ static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+       struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private;
+-      struct net *net = PDE_NET(pde);
+       u_int16_t af = (unsigned long)pde->data & 0xffff;
+       u_int16_t type = (unsigned long)pde->data >> 16;
+       struct list_head *list;
+@@ -705,7 +698,7 @@
+       if (af >= NPROTO)
+               return NULL;
+-      list = type2list(net, af, type);
++      list = type2list(af, type);
+       if (!list)
+               return NULL;
+@@ -718,7 +711,6 @@
+ static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+       struct proc_dir_entry *pde = seq->private;
+-      struct net *net = PDE_NET(pde);
+       u_int16_t af = (unsigned long)pde->data & 0xffff;
+       u_int16_t type = (unsigned long)pde->data >> 16;
+       struct list_head *list;
+@@ -726,7 +718,7 @@
+       if (af >= NPROTO)
+               return NULL;
+-      list = type2list(net, af, type);
++      list = type2list(af, type);
+       if (!list)
+               return NULL;
+@@ -767,7 +759,6 @@
+       if (!ret) {
+               struct seq_file *seq = file->private_data;
+               struct proc_dir_entry *pde = PDE(inode);
+-              get_net(PROC_NET(inode));
+               seq->private = pde;
+       }
+@@ -775,18 +766,12 @@
+       return ret;
+ }
+-static int xt_tgt_release(struct inode *inode, struct file *file)
 -{
--      if (!sock || !sock->fasync_list)
--              return -1;
--      switch (how) {
--      case 1:
--
--              if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
--                      break;
--              goto call_kill;
--      case 2:
--              if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
--                      break;
--              /* fall through */
--      case 0:
--call_kill:
--              __kill_fasync(sock->fasync_list, SIGIO, band);
--              break;
--      case 3:
--              __kill_fasync(sock->fasync_list, SIGURG, band);
--      }
--      return 0;
+-      put_net(PROC_NET(inode));
+-      return seq_release(inode, file);
 -}
 -
--static int __sock_create(int family, int type, int protocol,
--                       struct socket **res, int kern)
+ static const struct file_operations xt_file_ops = {
+       .owner   = THIS_MODULE,
+       .open    = xt_tgt_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+-      .release = xt_tgt_release,
++      .release = seq_release,
+ };
+ #define FORMAT_TABLES "_tables_names"
+@@ -809,7 +794,7 @@
+ #ifdef CONFIG_PROC_FS
+       strlcpy(buf, xt_prefix[af], sizeof(buf));
+       strlcat(buf, FORMAT_TABLES, sizeof(buf));
+-      proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
++      proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
+       if (!proc)
+               goto out;
+       proc->data = (void *) ((unsigned long) af | (TABLE << 16));
+@@ -817,14 +802,14 @@
+       strlcpy(buf, xt_prefix[af], sizeof(buf));
+       strlcat(buf, FORMAT_MATCHES, sizeof(buf));
+-      proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
++      proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
+       if (!proc)
+               goto out_remove_tables;
+       proc->data = (void *) ((unsigned long) af | (MATCH << 16));
+       strlcpy(buf, xt_prefix[af], sizeof(buf));
+       strlcat(buf, FORMAT_TARGETS, sizeof(buf));
+-      proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
++      proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
+       if (!proc)
+               goto out_remove_matches;
+       proc->data = (void *) ((unsigned long) af | (TARGET << 16));
+@@ -836,12 +821,12 @@
+ out_remove_matches:
+       strlcpy(buf, xt_prefix[af], sizeof(buf));
+       strlcat(buf, FORMAT_MATCHES, sizeof(buf));
+-      proc_net_remove(&init_net, buf);
++      proc_net_remove(buf);
+ out_remove_tables:
+       strlcpy(buf, xt_prefix[af], sizeof(buf));
+       strlcat(buf, FORMAT_TABLES, sizeof(buf));
+-      proc_net_remove(&init_net, buf);
++      proc_net_remove(buf);
+ out:
+       return -1;
+ #endif
+@@ -855,42 +840,19 @@
+       strlcpy(buf, xt_prefix[af], sizeof(buf));
+       strlcat(buf, FORMAT_TABLES, sizeof(buf));
+-      proc_net_remove(&init_net, buf);
++      proc_net_remove(buf);
+       strlcpy(buf, xt_prefix[af], sizeof(buf));
+       strlcat(buf, FORMAT_TARGETS, sizeof(buf));
+-      proc_net_remove(&init_net, buf);
++      proc_net_remove(buf);
+       strlcpy(buf, xt_prefix[af], sizeof(buf));
+       strlcat(buf, FORMAT_MATCHES, sizeof(buf));
+-      proc_net_remove(&init_net, buf);
++      proc_net_remove(buf);
+ #endif /*CONFIG_PROC_FS*/
+ }
+ EXPORT_SYMBOL_GPL(xt_proto_fini);
+-static int xt_net_init(struct net *net)
 -{
--      int err;
--      struct socket *sock;
--      const struct net_proto_family *pf;
--
--      /*
--       *      Check protocol is in range
--       */
--      if (family < 0 || family >= NPROTO)
--              return -EAFNOSUPPORT;
--      if (type < 0 || type >= SOCK_MAX)
--              return -EINVAL;
--
--      /* Compatibility.
--
--         This uglymoron is moved from INET layer to here to avoid
--         deadlock in module load.
--       */
--      if (family == PF_INET && type == SOCK_PACKET) {
--              static int warned;
--              if (!warned) {
--                      warned = 1;
--                      printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",
--                             current->comm);
--              }
--              family = PF_PACKET;
--      }
+-      int i;
 -
--      err = security_socket_create(family, type, protocol, kern);
--      if (err)
--              return err;
+-      net->xtn = kmalloc(sizeof(struct xt_af_pernet) * NPROTO, GFP_KERNEL);
+-      if (!net->xtn)
+-              return -ENOMEM;
 -
--      /*
--       *      Allocate the socket and allow the family to set things up. if
--       *      the protocol is 0, the family is instructed to select an appropriate
--       *      default.
--       */
--      sock = sock_alloc();
--      if (!sock) {
--              if (net_ratelimit())
--                      printk(KERN_WARNING "socket: no more sockets\n");
--              return -ENFILE; /* Not exactly a match, but its the
--                                 closest posix thing */
+-      for (i = 0; i < NPROTO; i++) {
+-              INIT_LIST_HEAD(&net->xtn[i].tables);
 -      }
--
--      sock->type = type;
--
--#if defined(CONFIG_KMOD)
--      /* Attempt to load a protocol module if the find failed.
--       *
--       * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
--       * requested real, full-featured networking support upon configuration.
--       * Otherwise module support will break!
--       */
--      if (net_families[family] == NULL)
--              request_module("net-pf-%d", family);
--#endif
--
--      rcu_read_lock();
--      pf = rcu_dereference(net_families[family]);
--      err = -EAFNOSUPPORT;
--      if (!pf)
--              goto out_release;
--
--      /*
--       * We will call the ->create function, that possibly is in a loadable
--       * module, so we have to bump that loadable module refcnt first.
--       */
--      if (!try_module_get(pf->owner))
--              goto out_release;
--
--      /* Now protected by module ref count */
--      rcu_read_unlock();
--
--      err = pf->create(sock, protocol);
--      if (err < 0)
--              goto out_module_put;
--
--      /*
--       * Now to bump the refcnt of the [loadable] module that owns this
--       * socket at sock_release time we decrement its refcnt.
--       */
--      if (!try_module_get(sock->ops->owner))
--              goto out_module_busy;
--
--      /*
--       * Now that we're done with the ->create function, the [loadable]
--       * module can have its refcnt decremented
--       */
--      module_put(pf->owner);
--      err = security_socket_post_create(sock, family, type, protocol, kern);
--      if (err)
--              goto out_sock_release;
--      *res = sock;
--
 -      return 0;
--
--out_module_busy:
--      err = -EAFNOSUPPORT;
--out_module_put:
--      sock->ops = NULL;
--      module_put(pf->owner);
--out_sock_release:
--      sock_release(sock);
--      return err;
--
--out_release:
--      rcu_read_unlock();
--      goto out_sock_release;
--}
--
--int sock_create(int family, int type, int protocol, struct socket **res)
--{
--      return __sock_create(family, type, protocol, res, 0);
 -}
 -
--int sock_create_kern(int family, int type, int protocol, struct socket **res)
+-static void xt_net_exit(struct net *net)
 -{
--      return __sock_create(family, type, protocol, res, 1);
+-      kfree(net->xtn);
 -}
 -
--asmlinkage long sys_socket(int family, int type, int protocol)
--{
--      int retval;
--      struct socket *sock;
--
--      retval = sock_create(family, type, protocol, &sock);
--      if (retval < 0)
+-static struct pernet_operations xt_net_ops = {
+-      .init = xt_net_init,
+-      .exit = xt_net_exit,
+-};
+ static int __init xt_init(void)
+ {
+@@ -907,13 +869,13 @@
+ #endif
+               INIT_LIST_HEAD(&xt[i].target);
+               INIT_LIST_HEAD(&xt[i].match);
++              INIT_LIST_HEAD(&xt[i].tables);
+       }
+-      return register_pernet_subsys(&xt_net_ops);
++      return 0;
+ }
+ static void __exit xt_fini(void)
+ {
+-      unregister_pernet_subsys(&xt_net_ops);
+       kfree(xt);
+ }
+diff -Nurb linux-2.6.22-590/net/netfilter/xt_MARK.c linux-2.6.22-570/net/netfilter/xt_MARK.c
+--- linux-2.6.22-590/net/netfilter/xt_MARK.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netfilter/xt_MARK.c   2008-01-23 19:16:10.000000000 -0500
+@@ -131,7 +131,7 @@
+               if ((*pskb)->sk) 
+                       connection_sk = (*pskb)->sk;
+               else {
+-                      connection_sk = inet_lookup(&tcp_hashinfo, src_ip, src_port, ip, port, dif,(*pskb)->sk->sk_net);
++                      connection_sk = inet_lookup(&tcp_hashinfo, src_ip, src_port, ip, port, dif);
+               }
+               if (connection_sk) {
+diff -Nurb linux-2.6.22-590/net/netfilter/xt_hashlimit.c linux-2.6.22-570/net/netfilter/xt_hashlimit.c
+--- linux-2.6.22-590/net/netfilter/xt_hashlimit.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netfilter/xt_hashlimit.c      2007-07-08 19:32:17.000000000 -0400
+@@ -21,7 +21,6 @@
+ #include <linux/in.h>
+ #include <linux/ip.h>
+ #include <linux/ipv6.h>
+-#include <net/net_namespace.h>
+ #include <linux/netfilter/x_tables.h>
+ #include <linux/netfilter_ipv4/ip_tables.h>
+@@ -737,13 +736,13 @@
+               printk(KERN_ERR "xt_hashlimit: unable to create slab cache\n");
+               goto err2;
+       }
+-      hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", init_net.proc_net);
++      hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", proc_net);
+       if (!hashlimit_procdir4) {
+               printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
+                               "entry\n");
+               goto err3;
+       }
+-      hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", init_net.proc_net);
++      hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", proc_net);
+       if (!hashlimit_procdir6) {
+               printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
+                               "entry\n");
+@@ -751,7 +750,7 @@
+       }
+       return 0;
+ err4:
+-      remove_proc_entry("ipt_hashlimit", init_net.proc_net);
++      remove_proc_entry("ipt_hashlimit", proc_net);
+ err3:
+       kmem_cache_destroy(hashlimit_cachep);
+ err2:
+@@ -763,8 +762,8 @@
+ static void __exit xt_hashlimit_fini(void)
+ {
+-      remove_proc_entry("ipt_hashlimit", init_net.proc_net);
+-      remove_proc_entry("ip6t_hashlimit", init_net.proc_net);
++      remove_proc_entry("ipt_hashlimit", proc_net);
++      remove_proc_entry("ip6t_hashlimit", proc_net);
+       kmem_cache_destroy(hashlimit_cachep);
+       xt_unregister_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
+ }
+diff -Nurb linux-2.6.22-590/net/netlink/af_netlink.c linux-2.6.22-570/net/netlink/af_netlink.c
+--- linux-2.6.22-590/net/netlink/af_netlink.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netlink/af_netlink.c  2008-01-23 19:16:05.000000000 -0500
+@@ -63,7 +63,6 @@
+ #include <net/sock.h>
+ #include <net/scm.h>
+ #include <net/netlink.h>
+-#include <net/net_namespace.h>
+ #define NLGRPSZ(x)    (ALIGN(x, sizeof(unsigned long) * 8) / 8)
+@@ -213,7 +212,7 @@
+               wake_up(&nl_table_wait);
+ }
+-static __inline__ struct sock *netlink_lookup(struct net *net, int protocol, u32 pid)
++static __inline__ struct sock *netlink_lookup(int protocol, u32 pid)
+ {
+       struct nl_pid_hash *hash = &nl_table[protocol].hash;
+       struct hlist_head *head;
+@@ -223,7 +222,7 @@
+       read_lock(&nl_table_lock);
+       head = nl_pid_hashfn(hash, pid);
+       sk_for_each(sk, node, head) {
+-              if ((sk->sk_net == net) && (nlk_sk(sk)->pid == pid)) {
++              if (nlk_sk(sk)->pid == pid) {
+                       sock_hold(sk);
+                       goto found;
+               }
+@@ -328,7 +327,7 @@
+        * makes sure updates are visible before bind or setsockopt return. */
+ }
+-static int netlink_insert(struct sock *sk, struct net *net, u32 pid)
++static int netlink_insert(struct sock *sk, u32 pid)
+ {
+       struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash;
+       struct hlist_head *head;
+@@ -341,7 +340,7 @@
+       head = nl_pid_hashfn(hash, pid);
+       len = 0;
+       sk_for_each(osk, node, head) {
+-              if ((osk->sk_net == net) && (nlk_sk(osk)->pid == pid))
++              if (nlk_sk(osk)->pid == pid)
+                       break;
+               len++;
+       }
+@@ -384,15 +383,15 @@
+       .obj_size = sizeof(struct netlink_sock),
+ };
+-static int __netlink_create(struct net *net, struct socket *sock,
+-                          struct mutex *cb_mutex, int protocol)
++static int __netlink_create(struct socket *sock, struct mutex *cb_mutex,
++                          int protocol)
+ {
+       struct sock *sk;
+       struct netlink_sock *nlk;
+       sock->ops = &netlink_ops;
+-      sk = sk_alloc(net, PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
++      sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
+       if (!sk)
+               return -ENOMEM;
+@@ -412,7 +411,7 @@
+       return 0;
+ }
+-static int netlink_create(struct net *net, struct socket *sock, int protocol)
++static int netlink_create(struct socket *sock, int protocol)
+ {
+       struct module *module = NULL;
+       struct mutex *cb_mutex;
+@@ -441,7 +440,7 @@
+       cb_mutex = nl_table[protocol].cb_mutex;
+       netlink_unlock_table();
+-      if ((err = __netlink_create(net, sock, cb_mutex, protocol)) < 0)
++      if ((err = __netlink_create(sock, cb_mutex, protocol)) < 0)
+               goto out_module;
+       nlk = nlk_sk(sock->sk);
+@@ -478,7 +477,6 @@
+       if (nlk->pid && !nlk->subscriptions) {
+               struct netlink_notify n = {
+-                                              .net = sk->sk_net,
+                                               .protocol = sk->sk_protocol,
+                                               .pid = nlk->pid,
+                                         };
+@@ -507,7 +505,6 @@
+ static int netlink_autobind(struct socket *sock)
+ {
+       struct sock *sk = sock->sk;
+-      struct net *net = sk->sk_net;
+       struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash;
+       struct hlist_head *head;
+       struct sock *osk;
+@@ -521,8 +518,6 @@
+       netlink_table_grab();
+       head = nl_pid_hashfn(hash, pid);
+       sk_for_each(osk, node, head) {
+-              if ((osk->sk_net != net))
+-                      continue;
+               if (nlk_sk(osk)->pid == pid) {
+                       /* Bind collision, search negative pid values. */
+                       pid = rover--;
+@@ -534,7 +529,7 @@
+       }
+       netlink_table_ungrab();
+-      err = netlink_insert(sk, net, pid);
++      err = netlink_insert(sk, pid);
+       if (err == -EADDRINUSE)
+               goto retry;
+@@ -588,7 +583,6 @@
+ static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
+ {
+       struct sock *sk = sock->sk;
+-      struct net *net = sk->sk_net;
+       struct netlink_sock *nlk = nlk_sk(sk);
+       struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
+       int err;
+@@ -612,7 +606,7 @@
+                       return -EINVAL;
+       } else {
+               err = nladdr->nl_pid ?
+-                      netlink_insert(sk, net, nladdr->nl_pid) :
++                      netlink_insert(sk, nladdr->nl_pid) :
+                       netlink_autobind(sock);
+               if (err)
+                       return err;
+@@ -696,12 +690,10 @@
+ static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid)
+ {
+       int protocol = ssk->sk_protocol;
+-      struct net *net;
+       struct sock *sock;
+       struct netlink_sock *nlk;
+-      net = ssk->sk_net;
+-      sock = netlink_lookup(net, protocol, pid);
++      sock = netlink_lookup(protocol, pid);
+       if (!sock)
+               return ERR_PTR(-ECONNREFUSED);
+@@ -874,7 +866,6 @@
+ struct netlink_broadcast_data {
+       struct sock *exclude_sk;
+-      struct net *net;
+       u32 pid;
+       u32 group;
+       int failure;
+@@ -897,9 +888,6 @@
+           !test_bit(p->group - 1, nlk->groups))
+               goto out;
+-      if ((sk->sk_net != p->net))
 -              goto out;
 -
--      retval = sock_map_fd(sock);
--      if (retval < 0)
--              goto out_release;
--
--out:
--      /* It may be already another descriptor 8) Not kernel problem. */
--      return retval;
--
--out_release:
--      sock_release(sock);
--      return retval;
--}
--
--/*
-- *    Create a pair of connected sockets.
-- */
+       if (p->failure) {
+               netlink_overrun(sk);
+               goto out;
+@@ -938,7 +926,6 @@
+ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
+                     u32 group, gfp_t allocation)
+ {
+-      struct net *net = ssk->sk_net;
+       struct netlink_broadcast_data info;
+       struct hlist_node *node;
+       struct sock *sk;
+@@ -946,7 +933,6 @@
+       skb = netlink_trim(skb, allocation);
+       info.exclude_sk = ssk;
+-      info.net = net;
+       info.pid = pid;
+       info.group = group;
+       info.failure = 0;
+@@ -995,9 +981,6 @@
+       if (sk == p->exclude_sk)
+               goto out;
+-      if (sk->sk_net != p->exclude_sk->sk_net)
+-              goto out;
 -
--asmlinkage long sys_socketpair(int family, int type, int protocol,
--                             int __user *usockvec)
+       if (nlk->pid == p->pid || p->group - 1 >= nlk->ngroups ||
+           !test_bit(p->group - 1, nlk->groups))
+               goto out;
+@@ -1293,7 +1276,7 @@
+  */
+ struct sock *
+-netlink_kernel_create(struct net *net, int unit, unsigned int groups,
++netlink_kernel_create(int unit, unsigned int groups,
+                     void (*input)(struct sock *sk, int len),
+                     struct mutex *cb_mutex, struct module *module)
+ {
+@@ -1310,7 +1293,7 @@
+       if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
+               return NULL;
+-      if (__netlink_create(net, sock, cb_mutex, unit) < 0)
++      if (__netlink_create(sock, cb_mutex, unit) < 0)
+               goto out_sock_release;
+       if (groups < 32)
+@@ -1325,20 +1308,18 @@
+       if (input)
+               nlk_sk(sk)->data_ready = input;
+-      if (netlink_insert(sk, net, 0))
++      if (netlink_insert(sk, 0))
+               goto out_sock_release;
+       nlk = nlk_sk(sk);
+       nlk->flags |= NETLINK_KERNEL_SOCKET;
+       netlink_table_grab();
+-      if (!nl_table[unit].registered) {
+       nl_table[unit].groups = groups;
+       nl_table[unit].listeners = listeners;
+       nl_table[unit].cb_mutex = cb_mutex;
+       nl_table[unit].module = module;
+       nl_table[unit].registered = 1;
+-      }
+       netlink_table_ungrab();
+       return sk;
+@@ -1439,7 +1420,7 @@
+       atomic_inc(&skb->users);
+       cb->skb = skb;
+-      sk = netlink_lookup(ssk->sk_net, ssk->sk_protocol, NETLINK_CB(skb).pid);
++      sk = netlink_lookup(ssk->sk_protocol, NETLINK_CB(skb).pid);
+       if (sk == NULL) {
+               netlink_destroy_callback(cb);
+               return -ECONNREFUSED;
+@@ -1481,8 +1462,7 @@
+       if (!skb) {
+               struct sock *sk;
+-              sk = netlink_lookup(in_skb->sk->sk_net,
+-                                  in_skb->sk->sk_protocol,
++              sk = netlink_lookup(in_skb->sk->sk_protocol,
+                                   NETLINK_CB(in_skb).pid);
+               if (sk) {
+                       sk->sk_err = ENOBUFS;
+@@ -1633,7 +1613,6 @@
+ #ifdef CONFIG_PROC_FS
+ struct nl_seq_iter {
+-      struct net *net;
+       int link;
+       int hash_idx;
+ };
+@@ -1651,8 +1630,6 @@
+               for (j = 0; j <= hash->mask; j++) {
+                       sk_for_each(s, node, &hash->table[j]) {
+-                              if (iter->net != s->sk_net)
+-                                      continue;
+                               if (off == pos) {
+                                       iter->link = i;
+                                       iter->hash_idx = j;
+@@ -1682,14 +1659,11 @@
+       if (v == SEQ_START_TOKEN)
+               return netlink_seq_socket_idx(seq, 0);
+-      iter = seq->private;
+-      s = v;
+-      do {
+-              s = sk_next(s);
+-      } while (s && (iter->net != s->sk_net));
++      s = sk_next(v);
+       if (s)
+               return s;
++      iter = seq->private;
+       i = iter->link;
+       j = iter->hash_idx + 1;
+@@ -1698,8 +1672,6 @@
+               for (; j <= hash->mask; j++) {
+                       s = sk_head(&hash->table[j]);
+-                      while (s && (iter->net != s->sk_net))
+-                              s = sk_next(s);
+                       if (s) {
+                               iter->link = i;
+                               iter->hash_idx = j;
+@@ -1770,24 +1742,15 @@
+       seq = file->private_data;
+       seq->private = iter;
+-      iter->net = get_net(PROC_NET(inode));
+       return 0;
+ }
+-static int netlink_seq_release(struct inode *inode, struct file *file)
 -{
--      struct socket *sock1, *sock2;
--      int fd1, fd2, err;
--      struct file *newfile1, *newfile2;
--
--      /*
--       * Obtain the first socket and check if the underlying protocol
--       * supports the socketpair call.
--       */
--
--      err = sock_create(family, type, protocol, &sock1);
--      if (err < 0)
--              goto out;
--
--      err = sock_create(family, type, protocol, &sock2);
--      if (err < 0)
--              goto out_release_1;
--
--      err = sock1->ops->socketpair(sock1, sock2);
--      if (err < 0)
--              goto out_release_both;
--
--      fd1 = sock_alloc_fd(&newfile1);
--      if (unlikely(fd1 < 0)) {
--              err = fd1;
--              goto out_release_both;
--      }
--
--      fd2 = sock_alloc_fd(&newfile2);
--      if (unlikely(fd2 < 0)) {
--              err = fd2;
--              put_filp(newfile1);
--              put_unused_fd(fd1);
--              goto out_release_both;
--      }
--
--      err = sock_attach_fd(sock1, newfile1);
--      if (unlikely(err < 0)) {
--              goto out_fd2;
--      }
--
--      err = sock_attach_fd(sock2, newfile2);
--      if (unlikely(err < 0)) {
--              fput(newfile1);
--              goto out_fd1;
--      }
--
--      err = audit_fd_pair(fd1, fd2);
--      if (err < 0) {
--              fput(newfile1);
--              fput(newfile2);
--              goto out_fd;
--      }
--
--      fd_install(fd1, newfile1);
--      fd_install(fd2, newfile2);
--      /* fd1 and fd2 may be already another descriptors.
--       * Not kernel problem.
--       */
--
--      err = put_user(fd1, &usockvec[0]);
--      if (!err)
--              err = put_user(fd2, &usockvec[1]);
--      if (!err)
--              return 0;
--
--      sys_close(fd2);
--      sys_close(fd1);
--      return err;
--
--out_release_both:
--      sock_release(sock2);
--out_release_1:
--      sock_release(sock1);
--out:
--      return err;
--
--out_fd2:
--      put_filp(newfile1);
--      sock_release(sock1);
--out_fd1:
--      put_filp(newfile2);
--      sock_release(sock2);
--out_fd:
--      put_unused_fd(fd1);
--      put_unused_fd(fd2);
--      goto out;
+-      struct seq_file *seq = file->private_data;
+-      struct nl_seq_iter *iter = seq->private;
+-      put_net(iter->net);
+-      return seq_release_private(inode, file);
 -}
 -
--/*
-- *    Bind a name to a socket. Nothing much to do here since it's
-- *    the protocol's responsibility to handle the local address.
-- *
-- *    We move the socket address to kernel space before we call
-- *    the protocol layer (having also checked the address is ok).
-- */
--
--asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
+ static const struct file_operations netlink_seq_fops = {
+       .owner          = THIS_MODULE,
+       .open           = netlink_seq_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+-      .release        = netlink_seq_release,
++      .release        = seq_release_private,
+ };
+ #endif
+@@ -1829,27 +1792,6 @@
+       .owner  = THIS_MODULE,  /* for consistency 8) */
+ };
+-static int netlink_net_init(struct net *net)
 -{
--      struct socket *sock;
--      char address[MAX_SOCK_ADDR];
--      int err, fput_needed;
--
--      sock = sockfd_lookup_light(fd, &err, &fput_needed);
--      if (sock) {
--              err = move_addr_to_kernel(umyaddr, addrlen, address);
--              if (err >= 0) {
--                      err = security_socket_bind(sock,
--                                                 (struct sockaddr *)address,
--                                                 addrlen);
--                      if (!err)
--                              err = sock->ops->bind(sock,
--                                                    (struct sockaddr *)
--                                                    address, addrlen);
--              }
--              fput_light(sock->file, fput_needed);
--      }
--      return err;
+-#ifdef CONFIG_PROC_FS
+-      if (!proc_net_fops_create(net, "netlink", 0, &netlink_seq_fops))
+-              return -ENOMEM;
+-#endif
+-      return 0;
 -}
 -
--/*
-- *    Perform a listen. Basically, we allow the protocol to do anything
-- *    necessary for a listen, and if that works, we mark the socket as
-- *    ready for listening.
-- */
--
--int sysctl_somaxconn __read_mostly = SOMAXCONN;
--
--asmlinkage long sys_listen(int fd, int backlog)
+-static void netlink_net_exit(struct net *net)
 -{
--      struct socket *sock;
--      int err, fput_needed;
--
--      sock = sockfd_lookup_light(fd, &err, &fput_needed);
--      if (sock) {
--              if ((unsigned)backlog > sysctl_somaxconn)
--                      backlog = sysctl_somaxconn;
--
--              err = security_socket_listen(sock, backlog);
--              if (!err)
--                      err = sock->ops->listen(sock, backlog);
--
--              fput_light(sock->file, fput_needed);
--      }
--      return err;
+-#ifdef CONFIG_PROC_FS
+-      proc_net_remove(net, "netlink");
+-#endif
 -}
 -
--/*
-- *    For accept, we attempt to create a new socket, set up the link
-- *    with the client, wake up the client, then return the new
-- *    connected fd. We collect the address of the connector in kernel
-- *    space and move it to user at the very end. This is unclean because
-- *    we open the socket then return an error.
-- *
-- *    1003.1g adds the ability to recvmsg() to query connection pending
-- *    status to recvmsg. We need to add that support in a way thats
-- *    clean when we restucture accept also.
-- */
--
--asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
--                         int __user *upeer_addrlen)
--{
--      struct socket *sock, *newsock;
--      struct file *newfile;
--      int err, len, newfd, fput_needed;
--      char address[MAX_SOCK_ADDR];
--
--      sock = sockfd_lookup_light(fd, &err, &fput_needed);
--      if (!sock)
--              goto out;
--
--      err = -ENFILE;
--      if (!(newsock = sock_alloc()))
--              goto out_put;
--
--      newsock->type = sock->type;
--      newsock->ops = sock->ops;
+-static struct pernet_operations netlink_net_ops = {
+-      .init = netlink_net_init,
+-      .exit = netlink_net_exit,
+-};
 -
--      /*
--       * We don't need try_module_get here, as the listening socket (sock)
--       * has the protocol module (sock->ops->owner) held.
--       */
--      __module_get(newsock->ops->owner);
+ static int __init netlink_proto_init(void)
+ {
+       struct sk_buff *dummy_skb;
+@@ -1895,7 +1837,9 @@
+       }
+       sock_register(&netlink_family_ops);
+-      register_pernet_subsys(&netlink_net_ops);
++#ifdef CONFIG_PROC_FS
++      proc_net_fops_create("netlink", 0, &netlink_seq_fops);
++#endif
+       /* The netlink device handler may be needed early. */
+       rtnetlink_init();
+ out:
+diff -Nurb linux-2.6.22-590/net/netlink/attr.c linux-2.6.22-570/net/netlink/attr.c
+--- linux-2.6.22-590/net/netlink/attr.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netlink/attr.c        2007-07-08 19:32:17.000000000 -0400
+@@ -72,17 +72,6 @@
+                       return -ERANGE;
+               break;
+-      case NLA_NESTED_COMPAT:
+-              if (attrlen < pt->len)
+-                      return -ERANGE;
+-              if (attrlen < NLA_ALIGN(pt->len))
+-                      break;
+-              if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN)
+-                      return -ERANGE;
+-              nla = nla_data(nla) + NLA_ALIGN(pt->len);
+-              if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla))
+-                      return -ERANGE;
+-              break;
+       default:
+               if (pt->len)
+                       minlen = pt->len;
+diff -Nurb linux-2.6.22-590/net/netlink/genetlink.c linux-2.6.22-570/net/netlink/genetlink.c
+--- linux-2.6.22-590/net/netlink/genetlink.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netlink/genetlink.c   2007-07-08 19:32:17.000000000 -0400
+@@ -557,9 +557,8 @@
+               goto errout_register;
+       netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV);
+-      genl_sock = netlink_kernel_create(&init_net, NETLINK_GENERIC,
+-                                        GENL_MAX_ID, genl_rcv, NULL,
+-                                        THIS_MODULE);
++      genl_sock = netlink_kernel_create(NETLINK_GENERIC, GENL_MAX_ID,
++                                        genl_rcv, NULL, THIS_MODULE);
+       if (genl_sock == NULL)
+               panic("GENL: Cannot initialize generic netlink\n");
+diff -Nurb linux-2.6.22-590/net/netrom/af_netrom.c linux-2.6.22-570/net/netrom/af_netrom.c
+--- linux-2.6.22-590/net/netrom/af_netrom.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netrom/af_netrom.c    2007-07-08 19:32:17.000000000 -0400
+@@ -41,7 +41,6 @@
+ #include <net/ip.h>
+ #include <net/tcp_states.h>
+ #include <net/arp.h>
+-#include <net/net_namespace.h>
+ #include <linux/init.h>
+ static int nr_ndevs = 4;
+@@ -106,9 +105,6 @@
+ {
+       struct net_device *dev = (struct net_device *)ptr;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--      newfd = sock_alloc_fd(&newfile);
--      if (unlikely(newfd < 0)) {
--              err = newfd;
--              sock_release(newsock);
--              goto out_put;
--      }
+       if (event != NETDEV_DOWN)
+               return NOTIFY_DONE;
+@@ -412,18 +408,15 @@
+       .obj_size = sizeof(struct nr_sock),
+ };
+-static int nr_create(struct net *net, struct socket *sock, int protocol)
++static int nr_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
+       struct nr_sock *nr;
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
 -
--      err = sock_attach_fd(newsock, newfile);
--      if (err < 0)
--              goto out_fd_simple;
+       if (sock->type != SOCK_SEQPACKET || protocol != 0)
+               return -ESOCKTNOSUPPORT;
+-      if ((sk = sk_alloc(net, PF_NETROM, GFP_ATOMIC, &nr_proto, 1)) == NULL)
++      if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, &nr_proto, 1)) == NULL)
+               return -ENOMEM;
+       nr = nr_sk(sk);
+@@ -465,7 +458,7 @@
+       if (osk->sk_type != SOCK_SEQPACKET)
+               return NULL;
+-      if ((sk = sk_alloc(osk->sk_net, PF_NETROM, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
++      if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
+               return NULL;
+       nr = nr_sk(sk);
+@@ -1454,9 +1447,9 @@
+       nr_loopback_init();
+-      proc_net_fops_create(&init_net, "nr", S_IRUGO, &nr_info_fops);
+-      proc_net_fops_create(&init_net, "nr_neigh", S_IRUGO, &nr_neigh_fops);
+-      proc_net_fops_create(&init_net, "nr_nodes", S_IRUGO, &nr_nodes_fops);
++      proc_net_fops_create("nr", S_IRUGO, &nr_info_fops);
++      proc_net_fops_create("nr_neigh", S_IRUGO, &nr_neigh_fops);
++      proc_net_fops_create("nr_nodes", S_IRUGO, &nr_nodes_fops);
+ out:
+       return rc;
+ fail:
+@@ -1484,9 +1477,9 @@
+ {
+       int i;
+-      proc_net_remove(&init_net, "nr");
+-      proc_net_remove(&init_net, "nr_neigh");
+-      proc_net_remove(&init_net, "nr_nodes");
++      proc_net_remove("nr");
++      proc_net_remove("nr_neigh");
++      proc_net_remove("nr_nodes");
+       nr_loopback_clear();
+       nr_rt_free();
+diff -Nurb linux-2.6.22-590/net/netrom/nr_route.c linux-2.6.22-570/net/netrom/nr_route.c
+--- linux-2.6.22-590/net/netrom/nr_route.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/netrom/nr_route.c     2007-07-08 19:32:17.000000000 -0400
+@@ -580,7 +580,7 @@
+ {
+       struct net_device *dev;
+-      if ((dev = dev_get_by_name(&init_net, devname)) == NULL)
++      if ((dev = dev_get_by_name(devname)) == NULL)
+               return NULL;
+       if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)
+@@ -598,7 +598,7 @@
+       struct net_device *dev, *first = NULL;
+       read_lock(&dev_base_lock);
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)
+                       if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
+                               first = dev;
+@@ -618,7 +618,7 @@
+       struct net_device *dev;
+       read_lock(&dev_base_lock);
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
+                       dev_hold(dev);
+                       goto out;
+diff -Nurb linux-2.6.22-590/net/packet/af_packet.c linux-2.6.22-570/net/packet/af_packet.c
+--- linux-2.6.22-590/net/packet/af_packet.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/packet/af_packet.c    2008-01-23 19:16:10.000000000 -0500
+@@ -65,7 +65,6 @@
+ #include <net/protocol.h>
+ #include <linux/skbuff.h>
+ #include <net/sock.h>
+-#include <net/net_namespace.h>
+ #include <linux/errno.h>
+ #include <linux/timer.h>
+ #include <asm/system.h>
+@@ -136,6 +135,10 @@
+    packet classifier depends on it.
+  */
++/* List of all packet sockets. */
++static HLIST_HEAD(packet_sklist);
++static DEFINE_RWLOCK(packet_sklist_lock);
++
+ static atomic_t packet_socks_nr;
+@@ -270,9 +273,6 @@
+       if (skb->pkt_type == PACKET_LOOPBACK)
+               goto out;
+-      if (dev->nd_net != sk->sk_net)
+-              goto out;
 -
--      err = security_socket_accept(sock, newsock);
--      if (err)
--              goto out_fd;
+       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+               goto oom;
+@@ -344,7 +344,7 @@
+        */
+       saddr->spkt_device[13] = 0;
+-      dev = dev_get_by_name(sk->sk_net, saddr->spkt_device);
++      dev = dev_get_by_name(saddr->spkt_device);
+       err = -ENODEV;
+       if (dev == NULL)
+               goto out_unlock;
+@@ -462,9 +462,6 @@
+       sk = pt->af_packet_priv;
+       po = pkt_sk(sk);
+-      if (dev->nd_net != sk->sk_net)
+-              goto drop;
 -
--      err = sock->ops->accept(sock, newsock, sock->file->f_flags);
--      if (err < 0)
--              goto out_fd;
+       skb->dev = dev;
+       if (dev->hard_header) {
+@@ -581,9 +578,6 @@
+       sk = pt->af_packet_priv;
+       po = pkt_sk(sk);
+-      if (dev->nd_net != sk->sk_net)
+-              goto drop;
 -
--      if (upeer_sockaddr) {
--              if (newsock->ops->getname(newsock, (struct sockaddr *)address,
--                                        &len, 2) < 0) {
--                      err = -ECONNABORTED;
--                      goto out_fd;
--              }
--              err = move_addr_to_user(address, len, upeer_sockaddr,
--                                      upeer_addrlen);
--              if (err < 0)
--                      goto out_fd;
+       if (dev->hard_header) {
+               if (sk->sk_type != SOCK_DGRAM)
+                       skb_push(skb, skb->data - skb_mac_header(skb));
+@@ -744,7 +738,7 @@
+       }
+-      dev = dev_get_by_index(sk->sk_net, ifindex);
++      dev = dev_get_by_index(ifindex);
+       err = -ENXIO;
+       if (dev == NULL)
+               goto out_unlock;
+@@ -817,17 +811,15 @@
+ {
+       struct sock *sk = sock->sk;
+       struct packet_sock *po;
+-      struct net *net;
+       if (!sk)
+               return 0;
+-      net = sk->sk_net;
+       po = pkt_sk(sk);
+-      write_lock_bh(&net->packet_sklist_lock);
++      write_lock_bh(&packet_sklist_lock);
+       sk_del_node_init(sk);
+-      write_unlock_bh(&net->packet_sklist_lock);
++      write_unlock_bh(&packet_sklist_lock);
+       /*
+        *      Unhook packet receive handler.
+@@ -941,7 +933,7 @@
+               return -EINVAL;
+       strlcpy(name,uaddr->sa_data,sizeof(name));
+-      dev = dev_get_by_name(sk->sk_net, name);
++      dev = dev_get_by_name(name);
+       if (dev) {
+               err = packet_do_bind(sk, dev, pkt_sk(sk)->num);
+               dev_put(dev);
+@@ -968,7 +960,7 @@
+       if (sll->sll_ifindex) {
+               err = -ENODEV;
+-              dev = dev_get_by_index(sk->sk_net, sll->sll_ifindex);
++              dev = dev_get_by_index(sll->sll_ifindex);
+               if (dev == NULL)
+                       goto out;
+       }
+@@ -990,7 +982,7 @@
+  *    Create a packet of type SOCK_PACKET.
+  */
+-static int packet_create(struct net *net, struct socket *sock, int protocol)
++static int packet_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
+       struct packet_sock *po;
+@@ -1006,7 +998,7 @@
+       sock->state = SS_UNCONNECTED;
+       err = -ENOBUFS;
+-      sk = sk_alloc(net, PF_PACKET, GFP_KERNEL, &packet_proto, 1);
++      sk = sk_alloc(PF_PACKET, GFP_KERNEL, &packet_proto, 1);
+       if (sk == NULL)
+               goto out;
+@@ -1042,9 +1034,9 @@
+               po->running = 1;
+       }
+-      write_lock_bh(&net->packet_sklist_lock);
+-      sk_add_node(sk, &net->packet_sklist);
+-      write_unlock_bh(&net->packet_sklist_lock);
++      write_lock_bh(&packet_sklist_lock);
++      sk_add_node(sk, &packet_sklist);
++      write_unlock_bh(&packet_sklist_lock);
+       return(0);
+ out:
+       return err;
+@@ -1162,7 +1154,7 @@
+               return -EOPNOTSUPP;
+       uaddr->sa_family = AF_PACKET;
+-      dev = dev_get_by_index(sk->sk_net, pkt_sk(sk)->ifindex);
++      dev = dev_get_by_index(pkt_sk(sk)->ifindex);
+       if (dev) {
+               strlcpy(uaddr->sa_data, dev->name, 15);
+               dev_put(dev);
+@@ -1187,7 +1179,7 @@
+       sll->sll_family = AF_PACKET;
+       sll->sll_ifindex = po->ifindex;
+       sll->sll_protocol = po->num;
+-      dev = dev_get_by_index(sk->sk_net, po->ifindex);
++      dev = dev_get_by_index(po->ifindex);
+       if (dev) {
+               sll->sll_hatype = dev->type;
+               sll->sll_halen = dev->addr_len;
+@@ -1239,7 +1231,7 @@
+       rtnl_lock();
+       err = -ENODEV;
+-      dev = __dev_get_by_index(sk->sk_net, mreq->mr_ifindex);
++      dev = __dev_get_by_index(mreq->mr_ifindex);
+       if (!dev)
+               goto done;
+@@ -1293,7 +1285,7 @@
+                       if (--ml->count == 0) {
+                               struct net_device *dev;
+                               *mlp = ml->next;
+-                              dev = dev_get_by_index(sk->sk_net, ml->ifindex);
++                              dev = dev_get_by_index(ml->ifindex);
+                               if (dev) {
+                                       packet_dev_mc(dev, ml, -1);
+                                       dev_put(dev);
+@@ -1321,7 +1313,7 @@
+               struct net_device *dev;
+               po->mclist = ml->next;
+-              if ((dev = dev_get_by_index(sk->sk_net, ml->ifindex)) != NULL) {
++              if ((dev = dev_get_by_index(ml->ifindex)) != NULL) {
+                       packet_dev_mc(dev, ml, -1);
+                       dev_put(dev);
+               }
+@@ -1477,10 +1469,9 @@
+       struct sock *sk;
+       struct hlist_node *node;
+       struct net_device *dev = data;
+-      struct net *net = dev->nd_net;
+-      read_lock(&net->packet_sklist_lock);
+-      sk_for_each(sk, node, &net->packet_sklist) {
++      read_lock(&packet_sklist_lock);
++      sk_for_each(sk, node, &packet_sklist) {
+               struct packet_sock *po = pkt_sk(sk);
+               switch (msg) {
+@@ -1519,7 +1510,7 @@
+                       break;
+               }
+       }
+-      read_unlock(&net->packet_sklist_lock);
++      read_unlock(&packet_sklist_lock);
+       return NOTIFY_DONE;
+ }
+@@ -1887,12 +1878,12 @@
+ };
+ #ifdef CONFIG_PROC_FS
+-static inline struct sock *packet_seq_idx(struct net *net, loff_t off)
++static inline struct sock *packet_seq_idx(loff_t off)
+ {
+       struct sock *s;
+       struct hlist_node *node;
+-      sk_for_each(s, node, &net->packet_sklist) {
++      sk_for_each(s, node, &packet_sklist) {
+               if (!off--)
+                       return s;
+       }
+@@ -1901,24 +1892,21 @@
+ static void *packet_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+-      struct net *net = seq->private;
+-      read_lock(&net->packet_sklist_lock);
+-      return *pos ? packet_seq_idx(net, *pos - 1) : SEQ_START_TOKEN;
++      read_lock(&packet_sklist_lock);
++      return *pos ? packet_seq_idx(*pos - 1) : SEQ_START_TOKEN;
+ }
+ static void *packet_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+-      struct net *net = seq->private;
+       ++*pos;
+       return  (v == SEQ_START_TOKEN)
+-              ? sk_head(&net->packet_sklist)
++              ? sk_head(&packet_sklist)
+               : sk_next((struct sock*)v) ;
+ }
+ static void packet_seq_stop(struct seq_file *seq, void *v)
+ {
+-      struct net *net = seq->private;
+-      read_unlock(&net->packet_sklist_lock);
++      read_unlock(&packet_sklist_lock);
+ }
+ static int packet_seq_show(struct seq_file *seq, void *v)
+@@ -1954,22 +1942,7 @@
+ static int packet_seq_open(struct inode *inode, struct file *file)
+ {
+-      struct seq_file *seq;
+-      int res;
+-      res = seq_open(file, &packet_seq_ops);
+-      if (!res) {
+-              seq = file->private_data;
+-              seq->private = get_net(PROC_NET(inode));
 -      }
--
--      /* File flags are not inherited via accept() unlike another OSes. */
--
--      fd_install(newfd, newfile);
--      err = newfd;
--
--      security_socket_post_accept(sock, newsock);
--
--out_put:
--      fput_light(sock->file, fput_needed);
--out:
--      return err;
--out_fd_simple:
--      sock_release(newsock);
--      put_filp(newfile);
--      put_unused_fd(newfd);
--      goto out_put;
--out_fd:
--      fput(newfile);
--      put_unused_fd(newfd);
--      goto out_put;
+-      return res;
 -}
 -
--/*
-- *    Attempt to connect to a socket with the server address.  The address
-- *    is in user space so we verify it is OK and move it to kernel space.
-- *
-- *    For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
-- *    break bindings
-- *
-- *    NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
-- *    other SEQPACKET protocols that take time to connect() as it doesn't
-- *    include the -EINPROGRESS status for such sockets.
-- */
--
--asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr,
--                          int addrlen)
+-static int packet_seq_release(struct inode *inode, struct file *file)
 -{
--      struct socket *sock;
--      char address[MAX_SOCK_ADDR];
--      int err, fput_needed;
--
--      sock = sockfd_lookup_light(fd, &err, &fput_needed);
--      if (!sock)
--              goto out;
--      err = move_addr_to_kernel(uservaddr, addrlen, address);
--      if (err < 0)
--              goto out_put;
+-      struct seq_file *seq=  file->private_data;
+-      struct net *net = seq->private;
+-      put_net(net);
+-      return seq_release(inode, file);
++      return seq_open(file, &packet_seq_ops);
+ }
+ static const struct file_operations packet_seq_fops = {
+@@ -1977,37 +1950,15 @@
+       .open           = packet_seq_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+-      .release        = packet_seq_release,
++      .release        = seq_release,
+ };
+ #endif
+-static int packet_net_init(struct net *net)
+-{
+-      rwlock_init(&net->packet_sklist_lock);
+-      INIT_HLIST_HEAD(&net->packet_sklist);
 -
--      err =
--          security_socket_connect(sock, (struct sockaddr *)address, addrlen);
--      if (err)
--              goto out_put;
+-      if (!proc_net_fops_create(net, "packet", 0, &packet_seq_fops))
+-              return -ENOMEM;
 -
--      err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
--                               sock->file->f_flags);
--out_put:
--      fput_light(sock->file, fput_needed);
--out:
--      return err;
+-      return 0;
 -}
 -
--/*
-- *    Get the local address ('name') of a socket object. Move the obtained
-- *    name to user space.
-- */
--
--asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,
--                              int __user *usockaddr_len)
+-static void packet_net_exit(struct net *net)
 -{
--      struct socket *sock;
--      char address[MAX_SOCK_ADDR];
--      int len, err, fput_needed;
--
--      sock = sockfd_lookup_light(fd, &err, &fput_needed);
--      if (!sock)
--              goto out;
--
--      err = security_socket_getsockname(sock);
--      if (err)
--              goto out_put;
--
--      err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0);
--      if (err)
--              goto out_put;
--      err = move_addr_to_user(address, len, usockaddr, usockaddr_len);
--
--out_put:
--      fput_light(sock->file, fput_needed);
--out:
--      return err;
+-      proc_net_remove(net, "packet");
 -}
 -
--/*
-- *    Get the remote address ('name') of a socket object. Move the obtained
-- *    name to user space.
-- */
+-static struct pernet_operations packet_net_ops = {
+-      .init = packet_net_init,
+-      .exit = packet_net_exit,
+-};
 -
--asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,
--                              int __user *usockaddr_len)
--{
--      struct socket *sock;
--      char address[MAX_SOCK_ADDR];
--      int len, err, fput_needed;
 -
--      sock = sockfd_lookup_light(fd, &err, &fput_needed);
--      if (sock != NULL) {
--              err = security_socket_getpeername(sock);
--              if (err) {
--                      fput_light(sock->file, fput_needed);
--                      return err;
--              }
+ static void __exit packet_exit(void)
+ {
++      proc_net_remove("packet");
+       unregister_netdevice_notifier(&packet_netdev_notifier);
+-      unregister_pernet_subsys(&packet_net_ops);
+       sock_unregister(PF_PACKET);
+       proto_unregister(&packet_proto);
+ }
+@@ -2020,8 +1971,8 @@
+               goto out;
+       sock_register(&packet_family_ops);
+-      register_pernet_subsys(&packet_net_ops);
+       register_netdevice_notifier(&packet_netdev_notifier);
++      proc_net_fops_create("packet", 0, &packet_seq_fops);
+ out:
+       return rc;
+ }
+diff -Nurb linux-2.6.22-590/net/rose/af_rose.c linux-2.6.22-570/net/rose/af_rose.c
+--- linux-2.6.22-590/net/rose/af_rose.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/rose/af_rose.c        2007-07-08 19:32:17.000000000 -0400
+@@ -45,7 +45,6 @@
+ #include <net/tcp_states.h>
+ #include <net/ip.h>
+ #include <net/arp.h>
+-#include <net/net_namespace.h>
+ static int rose_ndevs = 10;
+@@ -197,9 +196,6 @@
+ {
+       struct net_device *dev = (struct net_device *)ptr;
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
 -
--              err =
--                  sock->ops->getname(sock, (struct sockaddr *)address, &len,
--                                     1);
--              if (!err)
--                      err = move_addr_to_user(address, len, usockaddr,
--                                              usockaddr_len);
--              fput_light(sock->file, fput_needed);
--      }
--      return err;
--}
+       if (event != NETDEV_DOWN)
+               return NOTIFY_DONE;
+@@ -502,18 +498,15 @@
+       .obj_size = sizeof(struct rose_sock),
+ };
+-static int rose_create(struct net *net, struct socket *sock, int protocol)
++static int rose_create(struct socket *sock, int protocol)
+ {
+       struct sock *sk;
+       struct rose_sock *rose;
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
 -
--/*
-- *    Send a datagram to a given address. We move the address into kernel
-- *    space and check the user space data area is readable before invoking
-- *    the protocol.
-- */
+       if (sock->type != SOCK_SEQPACKET || protocol != 0)
+               return -ESOCKTNOSUPPORT;
+-      if ((sk = sk_alloc(net, PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
++      if ((sk = sk_alloc(PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
+               return -ENOMEM;
+       rose = rose_sk(sk);
+@@ -551,7 +544,7 @@
+       if (osk->sk_type != SOCK_SEQPACKET)
+               return NULL;
+-      if ((sk = sk_alloc(osk->sk_net, PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
++      if ((sk = sk_alloc(PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
+               return NULL;
+       rose = rose_sk(sk);
+@@ -1583,10 +1576,10 @@
+       rose_add_loopback_neigh();
+-      proc_net_fops_create(&init_net, "rose", S_IRUGO, &rose_info_fops);
+-      proc_net_fops_create(&init_net, "rose_neigh", S_IRUGO, &rose_neigh_fops);
+-      proc_net_fops_create(&init_net, "rose_nodes", S_IRUGO, &rose_nodes_fops);
+-      proc_net_fops_create(&init_net, "rose_routes", S_IRUGO, &rose_routes_fops);
++      proc_net_fops_create("rose", S_IRUGO, &rose_info_fops);
++      proc_net_fops_create("rose_neigh", S_IRUGO, &rose_neigh_fops);
++      proc_net_fops_create("rose_nodes", S_IRUGO, &rose_nodes_fops);
++      proc_net_fops_create("rose_routes", S_IRUGO, &rose_routes_fops);
+ out:
+       return rc;
+ fail:
+@@ -1613,10 +1606,10 @@
+ {
+       int i;
+-      proc_net_remove(&init_net, "rose");
+-      proc_net_remove(&init_net, "rose_neigh");
+-      proc_net_remove(&init_net, "rose_nodes");
+-      proc_net_remove(&init_net, "rose_routes");
++      proc_net_remove("rose");
++      proc_net_remove("rose_neigh");
++      proc_net_remove("rose_nodes");
++      proc_net_remove("rose_routes");
+       rose_loopback_clear();
+       rose_rt_free();
+diff -Nurb linux-2.6.22-590/net/rose/rose_route.c linux-2.6.22-570/net/rose/rose_route.c
+--- linux-2.6.22-590/net/rose/rose_route.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/rose/rose_route.c     2008-01-23 19:15:56.000000000 -0500
+@@ -583,7 +583,7 @@
+ {
+       struct net_device *dev;
+-      if ((dev = dev_get_by_name(&init_net, devname)) == NULL)
++      if ((dev = dev_get_by_name(devname)) == NULL)
+               return NULL;
+       if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)
+@@ -601,7 +601,7 @@
+       struct net_device *dev, *first = NULL;
+       read_lock(&dev_base_lock);
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE)
+                       if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
+                               first = dev;
+@@ -619,7 +619,7 @@
+       struct net_device *dev;
+       read_lock(&dev_base_lock);
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) {
+                       dev_hold(dev);
+                       goto out;
+@@ -636,7 +636,7 @@
+       struct net_device *dev;
+       read_lock(&dev_base_lock);
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0)
+                       goto out;
+       }
+diff -Nurb linux-2.6.22-590/net/rxrpc/af_rxrpc.c linux-2.6.22-570/net/rxrpc/af_rxrpc.c
+--- linux-2.6.22-590/net/rxrpc/af_rxrpc.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/rxrpc/af_rxrpc.c      2007-07-08 19:32:17.000000000 -0400
+@@ -14,7 +14,6 @@
+ #include <linux/skbuff.h>
+ #include <linux/poll.h>
+ #include <linux/proc_fs.h>
+-#include <net/net_namespace.h>
+ #include <net/sock.h>
+ #include <net/af_rxrpc.h>
+ #include "ar-internal.h"
+@@ -606,16 +605,13 @@
+ /*
+  * create an RxRPC socket
+  */
+-static int rxrpc_create(struct net *net, struct socket *sock, int protocol)
++static int rxrpc_create(struct socket *sock, int protocol)
+ {
+       struct rxrpc_sock *rx;
+       struct sock *sk;
+       _enter("%p,%d", sock, protocol);
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
 -
--asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
--                         unsigned flags, struct sockaddr __user *addr,
--                         int addr_len)
--{
--      struct socket *sock;
--      char address[MAX_SOCK_ADDR];
--      int err;
--      struct msghdr msg;
--      struct iovec iov;
--      int fput_needed;
--      struct file *sock_file;
--
--      sock_file = fget_light(fd, &fput_needed);
--      err = -EBADF;
--      if (!sock_file)
--              goto out;
+       /* we support transport protocol UDP only */
+       if (protocol != PF_INET)
+               return -EPROTONOSUPPORT;
+@@ -626,7 +622,7 @@
+       sock->ops = &rxrpc_rpc_ops;
+       sock->state = SS_UNCONNECTED;
+-      sk = sk_alloc(net, PF_RXRPC, GFP_KERNEL, &rxrpc_proto, 1);
++      sk = sk_alloc(PF_RXRPC, GFP_KERNEL, &rxrpc_proto, 1);
+       if (!sk)
+               return -ENOMEM;
+@@ -833,8 +829,8 @@
+       }
+ #ifdef CONFIG_PROC_FS
+-      proc_net_fops_create(&init_net, "rxrpc_calls", 0, &rxrpc_call_seq_fops);
+-      proc_net_fops_create(&init_net, "rxrpc_conns", 0, &rxrpc_connection_seq_fops);
++      proc_net_fops_create("rxrpc_calls", 0, &rxrpc_call_seq_fops);
++      proc_net_fops_create("rxrpc_conns", 0, &rxrpc_connection_seq_fops);
+ #endif
+       return 0;
+@@ -872,8 +868,8 @@
+       _debug("flush scheduled work");
+       flush_workqueue(rxrpc_workqueue);
+-      proc_net_remove(&init_net, "rxrpc_conns");
+-      proc_net_remove(&init_net, "rxrpc_calls");
++      proc_net_remove("rxrpc_conns");
++      proc_net_remove("rxrpc_calls");
+       destroy_workqueue(rxrpc_workqueue);
+       kmem_cache_destroy(rxrpc_call_jar);
+       _leave("");
+diff -Nurb linux-2.6.22-590/net/sched/act_api.c linux-2.6.22-570/net/sched/act_api.c
+--- linux-2.6.22-590/net/sched/act_api.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sched/act_api.c       2007-07-08 19:32:17.000000000 -0400
+@@ -27,7 +27,6 @@
+ #include <linux/skbuff.h>
+ #include <linux/init.h>
+ #include <linux/kmod.h>
+-#include <net/net_namespace.h>
+ #include <net/sock.h>
+ #include <net/sch_generic.h>
+ #include <net/act_api.h>
+@@ -676,7 +675,7 @@
+               return -EINVAL;
+       }
+-      return rtnl_unicast(skb, &init_net, pid);
++      return rtnl_unicast(skb, pid);
+ }
+ static struct tc_action *
+@@ -797,7 +796,7 @@
+       nlh->nlmsg_flags |= NLM_F_ROOT;
+       module_put(a->ops->owner);
+       kfree(a);
+-      err = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
++      err = rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+       if (err > 0)
+               return 0;
+@@ -860,7 +859,7 @@
+               /* now do the delete */
+               tcf_action_destroy(head, 0);
+-              ret = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC,
++              ret = rtnetlink_send(skb, pid, RTNLGRP_TC,
+                                    n->nlmsg_flags&NLM_F_ECHO);
+               if (ret > 0)
+                       return 0;
+@@ -904,7 +903,7 @@
+       nlh->nlmsg_len = skb_tail_pointer(skb) - b;
+       NETLINK_CB(skb).dst_group = RTNLGRP_TC;
+-      err = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, flags&NLM_F_ECHO);
++      err = rtnetlink_send(skb, pid, RTNLGRP_TC, flags&NLM_F_ECHO);
+       if (err > 0)
+               err = 0;
+       return err;
+@@ -942,14 +941,10 @@
+ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct rtattr **tca = arg;
+       u32 pid = skb ? NETLINK_CB(skb).pid : 0;
+       int ret = 0, ovr = 0;
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--      sock = sock_from_file(sock_file, &err);
--      if (!sock)
--              goto out_put;
--      iov.iov_base = buff;
--      iov.iov_len = len;
--      msg.msg_name = NULL;
--      msg.msg_iov = &iov;
--      msg.msg_iovlen = 1;
--      msg.msg_control = NULL;
--      msg.msg_controllen = 0;
--      msg.msg_namelen = 0;
--      if (addr) {
--              err = move_addr_to_kernel(addr, addr_len, address);
--              if (err < 0)
--                      goto out_put;
--              msg.msg_name = address;
--              msg.msg_namelen = addr_len;
--      }
--      if (sock->file->f_flags & O_NONBLOCK)
--              flags |= MSG_DONTWAIT;
--      msg.msg_flags = flags;
--      err = sock_sendmsg(sock, &msg, len);
+       if (tca[TCA_ACT_TAB-1] == NULL) {
+               printk("tc_ctl_action: received NO action attribs\n");
+               return -EINVAL;
+@@ -1019,7 +1014,6 @@
+ static int
+ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct nlmsghdr *nlh;
+       unsigned char *b = skb_tail_pointer(skb);
+       struct rtattr *x;
+@@ -1029,9 +1023,6 @@
+       struct tcamsg *t = (struct tcamsg *) NLMSG_DATA(cb->nlh);
+       struct rtattr *kind = find_dump_kind(cb->nlh);
+-      if (net != &init_net)
+-              return 0;
 -
--out_put:
--      fput_light(sock_file, fput_needed);
--out:
--      return err;
--}
+       if (kind == NULL) {
+               printk("tc_dump_action: action bad kind\n");
+               return 0;
+diff -Nurb linux-2.6.22-590/net/sched/act_mirred.c linux-2.6.22-570/net/sched/act_mirred.c
+--- linux-2.6.22-590/net/sched/act_mirred.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sched/act_mirred.c    2007-07-08 19:32:17.000000000 -0400
+@@ -85,7 +85,7 @@
+       parm = RTA_DATA(tb[TCA_MIRRED_PARMS-1]);
+       if (parm->ifindex) {
+-              dev = __dev_get_by_index(&init_net, parm->ifindex);
++              dev = __dev_get_by_index(parm->ifindex);
+               if (dev == NULL)
+                       return -ENODEV;
+               switch (dev->type) {
+diff -Nurb linux-2.6.22-590/net/sched/cls_api.c linux-2.6.22-570/net/sched/cls_api.c
+--- linux-2.6.22-590/net/sched/cls_api.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sched/cls_api.c       2007-07-08 19:32:17.000000000 -0400
+@@ -129,7 +129,6 @@
+ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct rtattr **tca;
+       struct tcmsg *t;
+       u32 protocol;
+@@ -146,9 +145,6 @@
+       unsigned long fh;
+       int err;
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--/*
-- *    Send a datagram down a socket.
-- */
+ replay:
+       tca = arg;
+       t = NLMSG_DATA(n);
+@@ -168,7 +164,7 @@
+       /* Find head of filter chain. */
+       /* Find link */
+-      if ((dev = __dev_get_by_index(&init_net, t->tcm_ifindex)) == NULL)
++      if ((dev = __dev_get_by_index(t->tcm_ifindex)) == NULL)
+               return -ENODEV;
+       /* Find qdisc */
+@@ -369,7 +365,7 @@
+               return -EINVAL;
+       }
+-      return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
++      return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ }
+ struct tcf_dump_args
+@@ -389,7 +385,6 @@
+ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       int t;
+       int s_t;
+       struct net_device *dev;
+@@ -400,12 +395,9 @@
+       struct Qdisc_class_ops *cops;
+       struct tcf_dump_args arg;
+-      if (net != &init_net)
+-              return 0;
 -
--asmlinkage long sys_send(int fd, void __user *buff, size_t len, unsigned flags)
--{
--      return sys_sendto(fd, buff, len, flags, NULL, 0);
--}
+       if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm)))
+               return skb->len;
+-      if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
++      if ((dev = dev_get_by_index(tcm->tcm_ifindex)) == NULL)
+               return skb->len;
+       if (!tcm->tcm_parent)
+diff -Nurb linux-2.6.22-590/net/sched/em_meta.c linux-2.6.22-570/net/sched/em_meta.c
+--- linux-2.6.22-590/net/sched/em_meta.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sched/em_meta.c       2007-07-08 19:32:17.000000000 -0400
+@@ -291,7 +291,7 @@
+        } else  {
+               struct net_device *dev;
+-              dev = dev_get_by_index(&init_net, skb->sk->sk_bound_dev_if);
++              dev = dev_get_by_index(skb->sk->sk_bound_dev_if);
+               *err = var_dev(dev, dst);
+               if (dev)
+                       dev_put(dev);
+diff -Nurb linux-2.6.22-590/net/sched/sch_api.c linux-2.6.22-570/net/sched/sch_api.c
+--- linux-2.6.22-590/net/sched/sch_api.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sched/sch_api.c       2008-01-23 19:15:56.000000000 -0500
+@@ -35,7 +35,6 @@
+ #include <linux/bitops.h>
+ #include <linux/hrtimer.h>
+-#include <net/net_namespace.h>
+ #include <net/netlink.h>
+ #include <net/sock.h>
+ #include <net/pkt_sched.h>
+@@ -610,7 +609,6 @@
+ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct tcmsg *tcm = NLMSG_DATA(n);
+       struct rtattr **tca = arg;
+       struct net_device *dev;
+@@ -619,10 +617,7 @@
+       struct Qdisc *p = NULL;
+       int err;
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--/*
-- *    Receive a frame from the socket and optionally record the address of the
-- *    sender. We verify the buffers are writable and if needed move the
-- *    sender address from kernel to user space.
-- */
--
--asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
--                           unsigned flags, struct sockaddr __user *addr,
--                           int __user *addr_len)
--{
--      struct socket *sock;
--      struct iovec iov;
--      struct msghdr msg;
--      char address[MAX_SOCK_ADDR];
--      int err, err2;
--      struct file *sock_file;
--      int fput_needed;
--
--      sock_file = fget_light(fd, &fput_needed);
--      err = -EBADF;
--      if (!sock_file)
--              goto out;
+-      if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
++      if ((dev = __dev_get_by_index(tcm->tcm_ifindex)) == NULL)
+               return -ENODEV;
+       if (clid) {
+@@ -675,7 +670,6 @@
+ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct tcmsg *tcm;
+       struct rtattr **tca;
+       struct net_device *dev;
+@@ -683,9 +677,6 @@
+       struct Qdisc *q, *p;
+       int err;
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--      sock = sock_from_file(sock_file, &err);
--      if (!sock)
--              goto out_put;
+ replay:
+       /* Reinit, just in case something touches this. */
+       tcm = NLMSG_DATA(n);
+@@ -693,7 +684,7 @@
+       clid = tcm->tcm_parent;
+       q = p = NULL;
+-      if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
++      if ((dev = __dev_get_by_index(tcm->tcm_ifindex)) == NULL)
+               return -ENODEV;
+       if (clid) {
+@@ -882,7 +873,7 @@
+       }
+       if (skb->len)
+-              return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
++              return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ err_out:
+       kfree_skb(skb);
+@@ -891,20 +882,16 @@
+ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       int idx, q_idx;
+       int s_idx, s_q_idx;
+       struct net_device *dev;
+       struct Qdisc *q;
+-      if (net != &init_net)
+-              return 0;
 -
--      msg.msg_control = NULL;
--      msg.msg_controllen = 0;
--      msg.msg_iovlen = 1;
--      msg.msg_iov = &iov;
--      iov.iov_len = size;
--      iov.iov_base = ubuf;
--      msg.msg_name = address;
--      msg.msg_namelen = MAX_SOCK_ADDR;
--      if (sock->file->f_flags & O_NONBLOCK)
--              flags |= MSG_DONTWAIT;
--      err = sock_recvmsg(sock, &msg, size, flags);
--
--      if (err >= 0 && addr != NULL) {
--              err2 = move_addr_to_user(address, msg.msg_namelen, addr, addr_len);
--              if (err2 < 0)
--                      err = err2;
--      }
--out_put:
--      fput_light(sock_file, fput_needed);
--out:
--      return err;
--}
+       s_idx = cb->args[0];
+       s_q_idx = q_idx = cb->args[1];
+       read_lock(&dev_base_lock);
+       idx = 0;
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               if (idx < s_idx)
+                       goto cont;
+               if (idx > s_idx)
+@@ -943,7 +930,6 @@
+ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+-      struct net *net = skb->sk->sk_net;
+       struct tcmsg *tcm = NLMSG_DATA(n);
+       struct rtattr **tca = arg;
+       struct net_device *dev;
+@@ -956,10 +942,7 @@
+       u32 qid = TC_H_MAJ(clid);
+       int err;
+-      if (net != &init_net)
+-              return -EINVAL;
 -
--/*
-- *    Receive a datagram from a socket.
-- */
+-      if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
++      if ((dev = __dev_get_by_index(tcm->tcm_ifindex)) == NULL)
+               return -ENODEV;
+       /*
+@@ -1113,7 +1096,7 @@
+               return -EINVAL;
+       }
+-      return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
++      return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ }
+ struct qdisc_dump_args
+@@ -1133,7 +1116,6 @@
+ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-      struct net *net = skb->sk->sk_net;
+       int t;
+       int s_t;
+       struct net_device *dev;
+@@ -1141,12 +1123,9 @@
+       struct tcmsg *tcm = (struct tcmsg*)NLMSG_DATA(cb->nlh);
+       struct qdisc_dump_args arg;
+-      if (net != &init_net)
+-              return 0;
 -
--asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
--                       unsigned flags)
+       if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm)))
+               return 0;
+-      if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
++      if ((dev = dev_get_by_index(tcm->tcm_ifindex)) == NULL)
+               return 0;
+       s_t = cb->args[0];
+@@ -1273,7 +1252,7 @@
+ {
+       register_qdisc(&pfifo_qdisc_ops);
+       register_qdisc(&bfifo_qdisc_ops);
+-      proc_net_fops_create(&init_net, "psched", 0, &psched_fops);
++      proc_net_fops_create("psched", 0, &psched_fops);
+       rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL);
+       rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL);
+diff -Nurb linux-2.6.22-590/net/sched/sch_generic.c linux-2.6.22-570/net/sched/sch_generic.c
+--- linux-2.6.22-590/net/sched/sch_generic.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sched/sch_generic.c   2007-07-08 19:32:17.000000000 -0400
+@@ -59,143 +59,122 @@
+       spin_unlock_bh(&dev->queue_lock);
+ }
+-static inline int qdisc_qlen(struct Qdisc *q)
 -{
--      return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
+-      return q->q.qlen;
 -}
--
--/*
-- *    Set a socket option. Because we don't know the option lengths we have
-- *    to pass the user mode parameter for the protocols to sort out.
-- */
--
--asmlinkage long sys_setsockopt(int fd, int level, int optname,
--                             char __user *optval, int optlen)
++/*
++   dev->queue_lock serializes queue accesses for this device
++   AND dev->qdisc pointer itself.
+-static inline int dev_requeue_skb(struct sk_buff *skb, struct net_device *dev,
+-                                struct Qdisc *q)
 -{
--      int err, fput_needed;
--      struct socket *sock;
--
--      if (optlen < 0)
--              return -EINVAL;
--
--      sock = sockfd_lookup_light(fd, &err, &fput_needed);
--      if (sock != NULL) {
--              err = security_socket_setsockopt(sock, level, optname);
--              if (err)
--                      goto out_put;
--
--              if (level == SOL_SOCKET)
--                      err =
--                          sock_setsockopt(sock, level, optname, optval,
--                                          optlen);
--              else
--                      err =
--                          sock->ops->setsockopt(sock, level, optname, optval,
--                                                optlen);
--out_put:
--              fput_light(sock->file, fput_needed);
--      }
--      return err;
+-      if (unlikely(skb->next))
+-              dev->gso_skb = skb;
+-      else
+-              q->ops->requeue(skb, q);
++   netif_tx_lock serializes accesses to device driver.
+-      netif_schedule(dev);
+-      return 0;
 -}
--
--/*
-- *    Get a socket option. Because we don't know the option lengths we have
-- *    to pass a user mode parameter for the protocols to sort out.
-- */
--
--asmlinkage long sys_getsockopt(int fd, int level, int optname,
--                             char __user *optval, int __user *optlen)
++   dev->queue_lock and netif_tx_lock are mutually exclusive,
++   if one is grabbed, another must be free.
++ */
+-static inline struct sk_buff *dev_dequeue_skb(struct net_device *dev,
+-                                            struct Qdisc *q)
 -{
--      int err, fput_needed;
--      struct socket *sock;
--
--      sock = sockfd_lookup_light(fd, &err, &fput_needed);
--      if (sock != NULL) {
--              err = security_socket_getsockopt(sock, level, optname);
--              if (err)
--                      goto out_put;
--
--              if (level == SOL_SOCKET)
--                      err =
--                          sock_getsockopt(sock, level, optname, optval,
--                                          optlen);
--              else
--                      err =
--                          sock->ops->getsockopt(sock, level, optname, optval,
--                                                optlen);
--out_put:
--              fput_light(sock->file, fput_needed);
--      }
--      return err;
+-      struct sk_buff *skb;
+-      if ((skb = dev->gso_skb))
+-              dev->gso_skb = NULL;
+-      else
+-              skb = q->dequeue(q);
++/* Kick device.
+-      return skb;
 -}
--
--/*
-- *    Shutdown a socket.
-- */
--
--asmlinkage long sys_shutdown(int fd, int how)
++   Returns:  0  - queue is empty or throttled.
++          >0  - queue is not empty.
+-static inline int handle_dev_cpu_collision(struct sk_buff *skb,
+-                                         struct net_device *dev,
+-                                         struct Qdisc *q)
 -{
--      int err, fput_needed;
--      struct socket *sock;
--
--      sock = sockfd_lookup_light(fd, &err, &fput_needed);
--      if (sock != NULL) {
--              err = security_socket_shutdown(sock, how);
--              if (!err)
--                      err = sock->ops->shutdown(sock, how);
--              fput_light(sock->file, fput_needed);
--      }
--      return err;
--}
--
--/* A couple of helpful macros for getting the address of the 32/64 bit
-- * fields which are the same type (int / unsigned) on our platforms.
-- */
--#define COMPAT_MSG(msg, member)       ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
--#define COMPAT_NAMELEN(msg)   COMPAT_MSG(msg, msg_namelen)
--#define COMPAT_FLAGS(msg)     COMPAT_MSG(msg, msg_flags)
--
--/*
-- *    BSD sendmsg interface
-- */
--
--asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
--{
--      struct compat_msghdr __user *msg_compat =
--          (struct compat_msghdr __user *)msg;
--      struct socket *sock;
--      char address[MAX_SOCK_ADDR];
--      struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
--      unsigned char ctl[sizeof(struct cmsghdr) + 20]
--          __attribute__ ((aligned(sizeof(__kernel_size_t))));
--      /* 20 is size of ipv6_pktinfo */
--      unsigned char *ctl_buf = ctl;
--      struct msghdr msg_sys;
--      int err, ctl_len, iov_size, total_len;
--      int fput_needed;
--
--      err = -EFAULT;
--      if (MSG_CMSG_COMPAT & flags) {
--              if (get_compat_msghdr(&msg_sys, msg_compat))
--                      return -EFAULT;
--      }
--      else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
--              return -EFAULT;
--
--      sock = sockfd_lookup_light(fd, &err, &fput_needed);
--      if (!sock)
--              goto out;
--
--      /* do not move before msg_sys is valid */
--      err = -EMSGSIZE;
--      if (msg_sys.msg_iovlen > UIO_MAXIOV)
--              goto out_put;
--
--      /* Check whether to allocate the iovec area */
--      err = -ENOMEM;
--      iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
--      if (msg_sys.msg_iovlen > UIO_FASTIOV) {
--              iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
--              if (!iov)
--                      goto out_put;
--      }
--
--      /* This will also move the address data into kernel space */
--      if (MSG_CMSG_COMPAT & flags) {
--              err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
--      } else
--              err = verify_iovec(&msg_sys, iov, address, VERIFY_READ);
--      if (err < 0)
--              goto out_freeiov;
--      total_len = err;
--
--      err = -ENOBUFS;
--
--      if (msg_sys.msg_controllen > INT_MAX)
--              goto out_freeiov;
--      ctl_len = msg_sys.msg_controllen;
--      if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
--              err =
--                  cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl,
--                                                   sizeof(ctl));
--              if (err)
--                      goto out_freeiov;
--              ctl_buf = msg_sys.msg_control;
--              ctl_len = msg_sys.msg_controllen;
--      } else if (ctl_len) {
--              if (ctl_len > sizeof(ctl)) {
--                      ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
--                      if (ctl_buf == NULL)
--                              goto out_freeiov;
--              }
--              err = -EFAULT;
+-      int ret;
++   NOTE: Called under dev->queue_lock with locally disabled BH.
++*/
+-      if (unlikely(dev->xmit_lock_owner == smp_processor_id())) {
 -              /*
--               * Careful! Before this, msg_sys.msg_control contains a user pointer.
--               * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
--               * checking falls down on this.
+-               * Same CPU holding the lock. It may be a transient
+-               * configuration error, when hard_start_xmit() recurses. We
+-               * detect it by checking xmit owner and drop the packet when
+-               * deadloop is detected. Return OK to try the next skb.
 -               */
--              if (copy_from_user(ctl_buf, (void __user *)msg_sys.msg_control,
--                                 ctl_len))
--                      goto out_freectl;
--              msg_sys.msg_control = ctl_buf;
--      }
--      msg_sys.msg_flags = flags;
--
--      if (sock->file->f_flags & O_NONBLOCK)
--              msg_sys.msg_flags |= MSG_DONTWAIT;
--      err = sock_sendmsg(sock, &msg_sys, total_len);
--
--out_freectl:
--      if (ctl_buf != ctl)
--              sock_kfree_s(sock->sk, ctl_buf, ctl_len);
--out_freeiov:
--      if (iov != iovstack)
--              sock_kfree_s(sock->sk, iov, iov_size);
--out_put:
--      fput_light(sock->file, fput_needed);
--out:
--      return err;
--}
--
--/*
-- *    BSD recvmsg interface
-- */
--
--asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
--                          unsigned int flags)
--{
--      struct compat_msghdr __user *msg_compat =
--          (struct compat_msghdr __user *)msg;
--      struct socket *sock;
--      struct iovec iovstack[UIO_FASTIOV];
--      struct iovec *iov = iovstack;
--      struct msghdr msg_sys;
--      unsigned long cmsg_ptr;
--      int err, iov_size, total_len, len;
--      int fput_needed;
--
--      /* kernel mode address */
--      char addr[MAX_SOCK_ADDR];
--
--      /* user mode address pointers */
--      struct sockaddr __user *uaddr;
--      int __user *uaddr_len;
--
--      if (MSG_CMSG_COMPAT & flags) {
--              if (get_compat_msghdr(&msg_sys, msg_compat))
--                      return -EFAULT;
--      }
--      else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
--              return -EFAULT;
--
--      sock = sockfd_lookup_light(fd, &err, &fput_needed);
--      if (!sock)
--              goto out;
--
--      err = -EMSGSIZE;
--      if (msg_sys.msg_iovlen > UIO_MAXIOV)
--              goto out_put;
--
--      /* Check whether to allocate the iovec area */
--      err = -ENOMEM;
--      iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
--      if (msg_sys.msg_iovlen > UIO_FASTIOV) {
--              iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
--              if (!iov)
--                      goto out_put;
+-              kfree_skb(skb);
+-              if (net_ratelimit())
+-                      printk(KERN_WARNING "Dead loop on netdevice %s, "
+-                             "fix it urgently!\n", dev->name);
+-              ret = qdisc_qlen(q);
+-      } else {
+-              /*
+-               * Another cpu is holding lock, requeue & delay xmits for
+-               * some time.
+-               */
+-              __get_cpu_var(netdev_rx_stat).cpu_collision++;
+-              ret = dev_requeue_skb(skb, dev, q);
 -      }
 -
--      /*
--       *      Save the user-mode address (verify_iovec will change the
--       *      kernel msghdr to use the kernel address space)
--       */
--
--      uaddr = (void __user *)msg_sys.msg_name;
--      uaddr_len = COMPAT_NAMELEN(msg);
--      if (MSG_CMSG_COMPAT & flags) {
--              err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
--      } else
--              err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
--      if (err < 0)
--              goto out_freeiov;
--      total_len = err;
--
--      cmsg_ptr = (unsigned long)msg_sys.msg_control;
--      msg_sys.msg_flags = 0;
--      if (MSG_CMSG_COMPAT & flags)
--              msg_sys.msg_flags = MSG_CMSG_COMPAT;
--
--      if (sock->file->f_flags & O_NONBLOCK)
--              flags |= MSG_DONTWAIT;
--      err = sock_recvmsg(sock, &msg_sys, total_len, flags);
--      if (err < 0)
--              goto out_freeiov;
--      len = err;
--
--      if (uaddr != NULL) {
--              err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr,
--                                      uaddr_len);
--              if (err < 0)
--                      goto out_freeiov;
--      }
--      err = __put_user((msg_sys.msg_flags & ~MSG_CMSG_COMPAT),
--                       COMPAT_FLAGS(msg));
--      if (err)
--              goto out_freeiov;
--      if (MSG_CMSG_COMPAT & flags)
--              err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
--                               &msg_compat->msg_controllen);
--      else
--              err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
--                               &msg->msg_controllen);
--      if (err)
--              goto out_freeiov;
--      err = len;
--
--out_freeiov:
--      if (iov != iovstack)
--              sock_kfree_s(sock->sk, iov, iov_size);
--out_put:
--      fput_light(sock->file, fput_needed);
--out:
--      return err;
+-      return ret;
 -}
 -
--#ifdef __ARCH_WANT_SYS_SOCKETCALL
--
--/* Argument list sizes for sys_socketcall */
--#define AL(x) ((x) * sizeof(unsigned long))
--static const unsigned char nargs[18]={
--      AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
--      AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
--      AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)
--};
--
--#undef AL
--
 -/*
-- *    System call vectors.
+- * NOTE: Called under dev->queue_lock with locally disabled BH.
+- *
+- * __LINK_STATE_QDISC_RUNNING guarantees only one CPU can process this
+- * device at a time. dev->queue_lock serializes queue accesses for
+- * this device AND dev->qdisc pointer itself.
+- *
+- *  netif_tx_lock serializes accesses to device driver.
+- *
+- *  dev->queue_lock and netif_tx_lock are mutually exclusive,
+- *  if one is grabbed, another must be free.
+- *
+- * Note, that this procedure can be called by a watchdog timer
+- *
+- * Returns to the caller:
+- *                            0  - queue is empty or throttled.
+- *                            >0 - queue is not empty.
 - *
-- *    Argument checking cleaned up. Saved 20% in size.
-- *  This function doesn't need to set the kernel lock because
-- *  it is set by the callees.
 - */
+ static inline int qdisc_restart(struct net_device *dev)
+ {
+       struct Qdisc *q = dev->qdisc;
+       struct sk_buff *skb;
+-      unsigned lockless;
+-      int ret;
+       /* Dequeue packet */
+-      if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL))
+-              return 0;
++      if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) {
++              unsigned nolock = (dev->features & NETIF_F_LLTX);
++
++              dev->gso_skb = NULL;
+               /*
+-       * When the driver has LLTX set, it does its own locking in
+-       * start_xmit. These checks are worth it because even uncongested
+-       * locks can be quite expensive. The driver can do a trylock, as
+-       * is being done here; in case of lock contention it should return
+-       * NETDEV_TX_LOCKED and the packet will be requeued.
++               * When the driver has LLTX set it does its own locking
++               * in start_xmit. No need to add additional overhead by
++               * locking again. These checks are worth it because
++               * even uncongested locks can be quite expensive.
++               * The driver can do trylock like here too, in case
++               * of lock congestion it should return -1 and the packet
++               * will be requeued.
+                               */
+-      lockless = (dev->features & NETIF_F_LLTX);
+-
+-      if (!lockless && !netif_tx_trylock(dev)) {
+-              /* Another CPU grabbed the driver tx lock */
+-              return handle_dev_cpu_collision(skb, dev, q);
++              if (!nolock) {
++                      if (!netif_tx_trylock(dev)) {
++                      collision:
++                              /* So, someone grabbed the driver. */
++
++                              /* It may be transient configuration error,
++                                 when hard_start_xmit() recurses. We detect
++                                 it by checking xmit owner and drop the
++                                 packet when deadloop is detected.
++                              */
++                              if (dev->xmit_lock_owner == smp_processor_id()) {
++                                      kfree_skb(skb);
++                                      if (net_ratelimit())
++                                              printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
++                                      goto out;
++                              }
++                              __get_cpu_var(netdev_rx_stat).cpu_collision++;
++                              goto requeue;
++                      }
+               }
++              {
+                       /* And release queue */
+                       spin_unlock(&dev->queue_lock);
+-                              ret = dev_hard_start_xmit(skb, dev);
++                      if (!netif_queue_stopped(dev)) {
++                              int ret;
+-      if (!lockless)
++                              ret = dev_hard_start_xmit(skb, dev);
++                              if (ret == NETDEV_TX_OK) {
++                                      if (!nolock) {
+                               netif_tx_unlock(dev);
 -
--asmlinkage long sys_socketcall(int call, unsigned long __user *args)
--{
--      unsigned long a[6];
--      unsigned long a0, a1;
--      int err;
--
--      if (call < 1 || call > SYS_RECVMSG)
--              return -EINVAL;
--
--      /* copy_from_user should be SMP safe. */
--      if (copy_from_user(a, args, nargs[call]))
--              return -EFAULT;
--
--      err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
--      if (err)
--              return err;
--
--      a0 = a[0];
--      a1 = a[1];
--
--      switch (call) {
--      case SYS_SOCKET:
--              err = sys_socket(a0, a1, a[2]);
--              break;
--      case SYS_BIND:
--              err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
--              break;
--      case SYS_CONNECT:
--              err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
--              break;
--      case SYS_LISTEN:
--              err = sys_listen(a0, a1);
--              break;
--      case SYS_ACCEPT:
--              err =
--                  sys_accept(a0, (struct sockaddr __user *)a1,
--                             (int __user *)a[2]);
--              break;
--      case SYS_GETSOCKNAME:
--              err =
--                  sys_getsockname(a0, (struct sockaddr __user *)a1,
--                                  (int __user *)a[2]);
--              break;
--      case SYS_GETPEERNAME:
--              err =
--                  sys_getpeername(a0, (struct sockaddr __user *)a1,
--                                  (int __user *)a[2]);
--              break;
--      case SYS_SOCKETPAIR:
--              err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
--              break;
--      case SYS_SEND:
--              err = sys_send(a0, (void __user *)a1, a[2], a[3]);
--              break;
--      case SYS_SENDTO:
--              err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
--                               (struct sockaddr __user *)a[4], a[5]);
--              break;
--      case SYS_RECV:
--              err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
--              break;
--      case SYS_RECVFROM:
--              err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
--                                 (struct sockaddr __user *)a[4],
--                                 (int __user *)a[5]);
--              break;
--      case SYS_SHUTDOWN:
--              err = sys_shutdown(a0, a1);
--              break;
--      case SYS_SETSOCKOPT:
--              err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
--              break;
--      case SYS_GETSOCKOPT:
--              err =
--                  sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
--                                 (int __user *)a[4]);
--              break;
--      case SYS_SENDMSG:
--              err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
++                                      }
+                       spin_lock(&dev->queue_lock);
+                       q = dev->qdisc;
++                                      goto out;
++                              }
++                              if (ret == NETDEV_TX_LOCKED && nolock) {
++                                      spin_lock(&dev->queue_lock);
++                                      q = dev->qdisc;
++                                      goto collision;
++                              }
++                      }
+-      switch (ret) {
+-      case NETDEV_TX_OK:
+-              /* Driver sent out skb successfully */
+-              ret = qdisc_qlen(q);
 -              break;
--      case SYS_RECVMSG:
--              err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
++                      /* NETDEV_TX_BUSY - we need to requeue */
++                      /* Release the driver */
++                      if (!nolock) {
++                              netif_tx_unlock(dev);
++                      }
++                      spin_lock(&dev->queue_lock);
++                      q = dev->qdisc;
++              }
+-      case NETDEV_TX_LOCKED:
+-              /* Driver try lock failed */
+-              ret = handle_dev_cpu_collision(skb, dev, q);
 -              break;
++              /* Device kicked us out :(
++                 This is possible in three cases:
 -      default:
--              err = -EINVAL;
+-              /* Driver returned NETDEV_TX_BUSY - requeue skb */
+-              if (unlikely (ret != NETDEV_TX_BUSY && net_ratelimit()))
+-                      printk(KERN_WARNING "BUG %s code %d qlen %d\n",
+-                             dev->name, ret, q->q.qlen);
++                 0. driver is locked
++                 1. fastroute is enabled
++                 2. device cannot determine busy state
++                    before start of transmission (f.e. dialout)
++                 3. device is buggy (ppp)
++               */
+-              ret = dev_requeue_skb(skb, dev, q);
 -              break;
--      }
--      return err;
--}
--
--#endif                                /* __ARCH_WANT_SYS_SOCKETCALL */
--
--/**
-- *    sock_register - add a socket protocol handler
-- *    @ops: description of protocol
-- *
-- *    This function is called by a protocol handler that wants to
-- *    advertise its address family, and have it linked into the
-- *    socket interface. The value ops->family coresponds to the
-- *    socket system call protocol family.
-- */
--int sock_register(const struct net_proto_family *ops)
--{
--      int err;
--
--      if (ops->family >= NPROTO) {
--              printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
--                     NPROTO);
--              return -ENOBUFS;
--      }
--
--      spin_lock(&net_family_lock);
--      if (net_families[ops->family])
--              err = -EEXIST;
--      else {
--              net_families[ops->family] = ops;
--              err = 0;
--      }
--      spin_unlock(&net_family_lock);
--
--      printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
--      return err;
--}
--
--/**
-- *    sock_unregister - remove a protocol handler
-- *    @family: protocol family to remove
-- *
-- *    This function is called by a protocol handler that wants to
-- *    remove its address family, and have it unlinked from the
-- *    new socket creation.
-- *
-- *    If protocol handler is a module, then it can use module reference
-- *    counts to protect against new references. If protocol handler is not
-- *    a module then it needs to provide its own protection in
-- *    the ops->create routine.
-- */
--void sock_unregister(int family)
--{
--      BUG_ON(family < 0 || family >= NPROTO);
--
--      spin_lock(&net_family_lock);
--      net_families[family] = NULL;
--      spin_unlock(&net_family_lock);
--
--      synchronize_rcu();
--
--      printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
--}
--
--static int __init sock_init(void)
--{
--      /*
--       *      Initialize sock SLAB cache.
--       */
--
--      sk_init();
--
--      /*
--       *      Initialize skbuff SLAB cache
--       */
--      skb_init();
--
--      /*
--       *      Initialize the protocols module.
--       */
--
--      init_inodecache();
--      register_filesystem(&sock_fs_type);
--      sock_mnt = kern_mount(&sock_fs_type);
--
--      /* The real protocol initialization is performed in later initcalls.
--       */
--
--#ifdef CONFIG_NETFILTER
--      netfilter_init();
--#endif
--
--      return 0;
--}
--
--core_initcall(sock_init);     /* early initcall */
--
--#ifdef CONFIG_PROC_FS
--void socket_seq_show(struct seq_file *seq)
--{
--      int cpu;
--      int counter = 0;
--
--      for_each_possible_cpu(cpu)
--          counter += per_cpu(sockets_in_use, cpu);
--
--      /* It can be negative, by the way. 8) */
--      if (counter < 0)
--              counter = 0;
--
--      seq_printf(seq, "sockets: used %d\n", counter);
--}
--#endif                                /* CONFIG_PROC_FS */
--
--#ifdef CONFIG_COMPAT
--static long compat_sock_ioctl(struct file *file, unsigned cmd,
--                            unsigned long arg)
--{
--      struct socket *sock = file->private_data;
--      int ret = -ENOIOCTLCMD;
--
--      if (sock->ops->compat_ioctl)
--              ret = sock->ops->compat_ioctl(sock, cmd, arg);
--
++requeue:
++              if (unlikely(q == &noop_qdisc))
++                      kfree_skb(skb);
++              else if (skb->next)
++                      dev->gso_skb = skb;
++              else
++                      q->ops->requeue(skb, q);
++              netif_schedule(dev);
+       }
++      return 0;
 -      return ret;
--}
--#endif
--
--int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
--{
--      return sock->ops->bind(sock, addr, addrlen);
--}
--
--int kernel_listen(struct socket *sock, int backlog)
--{
--      return sock->ops->listen(sock, backlog);
--}
--
--int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
--{
--      struct sock *sk = sock->sk;
--      int err;
--
--      err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
--                             newsock);
--      if (err < 0)
--              goto done;
++out:
++      BUG_ON((int) q->q.qlen < 0);
++      return q->q.qlen;
+ }
+ void __qdisc_run(struct net_device *dev)
+diff -Nurb linux-2.6.22-590/net/sched/sch_ingress.c linux-2.6.22-570/net/sched/sch_ingress.c
+--- linux-2.6.22-590/net/sched/sch_ingress.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sched/sch_ingress.c   2007-07-08 19:32:17.000000000 -0400
+@@ -243,10 +243,6 @@
+       struct net_device *dev = skb->dev;
+       int fwres=NF_ACCEPT;
+-      /* Only filter packets in the initial network namespace */
+-      if ((indev?indev:outdev)->nd_net != &init_net)
+-              return NF_ACCEPT;
 -
--      err = sock->ops->accept(sock, *newsock, flags);
--      if (err < 0) {
--              sock_release(*newsock);
--              goto done;
+       DPRINTK("ing_hook: skb %s dev=%s len=%u\n",
+               skb->sk ? "(owned)" : "(unowned)",
+               skb->dev ? (*pskb)->dev->name : "(no dev)",
+diff -Nurb linux-2.6.22-590/net/sctp/input.c linux-2.6.22-570/net/sctp/input.c
+--- linux-2.6.22-590/net/sctp/input.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sctp/input.c  2007-07-08 19:32:17.000000000 -0400
+@@ -126,10 +126,6 @@
+       int family;
+       struct sctp_af *af;
+-      if (skb->dev->nd_net != &init_net) {
+-              kfree_skb(skb);
+-              return 0;
 -      }
+       if (skb->pkt_type!=PACKET_HOST)
+               goto discard_it;
+@@ -513,9 +509,6 @@
+       sk_buff_data_t saveip, savesctp;
+       int err;
+-      if (skb->dev->nd_net != &init_net)
+-              return;
 -
--      (*newsock)->ops = sock->ops;
--
--done:
--      return err;
--}
--
--int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
--                 int flags)
--{
--      return sock->ops->connect(sock, addr, addrlen, flags);
--}
--
--int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
--                       int *addrlen)
--{
--      return sock->ops->getname(sock, addr, addrlen, 0);
--}
--
--int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
--                       int *addrlen)
--{
--      return sock->ops->getname(sock, addr, addrlen, 1);
--}
--
--int kernel_getsockopt(struct socket *sock, int level, int optname,
--                      char *optval, int *optlen)
--{
--      mm_segment_t oldfs = get_fs();
--      int err;
--
--      set_fs(KERNEL_DS);
--      if (level == SOL_SOCKET)
--              err = sock_getsockopt(sock, level, optname, optval, optlen);
--      else
--              err = sock->ops->getsockopt(sock, level, optname, optval,
--                                          optlen);
--      set_fs(oldfs);
--      return err;
--}
--
--int kernel_setsockopt(struct socket *sock, int level, int optname,
--                      char *optval, int optlen)
--{
--      mm_segment_t oldfs = get_fs();
--      int err;
--
--      set_fs(KERNEL_DS);
--      if (level == SOL_SOCKET)
--              err = sock_setsockopt(sock, level, optname, optval, optlen);
--      else
--              err = sock->ops->setsockopt(sock, level, optname, optval,
--                                          optlen);
--      set_fs(oldfs);
--      return err;
--}
--
--int kernel_sendpage(struct socket *sock, struct page *page, int offset,
--                  size_t size, int flags)
+       if (skb->len < ihlen + 8) {
+               ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+               return;
+diff -Nurb linux-2.6.22-590/net/sctp/ipv6.c linux-2.6.22-570/net/sctp/ipv6.c
+--- linux-2.6.22-590/net/sctp/ipv6.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sctp/ipv6.c   2008-01-23 19:16:05.000000000 -0500
+@@ -189,7 +189,6 @@
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       fl.proto = sk->sk_protocol;
+       /* Fill in the dest address from the route entry passed with the skb
+@@ -231,7 +230,6 @@
+       struct flowi fl;
+       memset(&fl, 0, sizeof(fl));
+-      fl.fl_net = &init_net;
+       ipv6_addr_copy(&fl.fl6_dst, &daddr->v6.sin6_addr);
+       if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
+               fl.oif = daddr->v6.sin6_scope_id;
+@@ -621,7 +619,7 @@
+       struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
+       struct sctp6_sock *newsctp6sk;
+-      newsk = sk_alloc(sk->sk_net, PF_INET6, GFP_KERNEL, sk->sk_prot, 1);
++      newsk = sk_alloc(PF_INET6, GFP_KERNEL, sk->sk_prot, 1);
+       if (!newsk)
+               goto out;
+@@ -666,7 +664,7 @@
+       newinet->mc_index = 0;
+       newinet->mc_list = NULL;
+-      if (init_net.sysctl_ipv4_no_pmtu_disc)
++      if (ipv4_config.no_pmtu_disc)
+               newinet->pmtudisc = IP_PMTUDISC_DONT;
+       else
+               newinet->pmtudisc = IP_PMTUDISC_WANT;
+@@ -843,7 +841,7 @@
+               if (type & IPV6_ADDR_LINKLOCAL) {
+                       if (!addr->v6.sin6_scope_id)
+                               return 0;
+-                      dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id);
++                      dev = dev_get_by_index(addr->v6.sin6_scope_id);
+                       if (!dev)
+                               return 0;
+                       if (!ipv6_chk_addr(&addr->v6.sin6_addr, dev, 0)) {
+@@ -874,7 +872,7 @@
+               if (type & IPV6_ADDR_LINKLOCAL) {
+                       if (!addr->v6.sin6_scope_id)
+                               return 0;
+-                      dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id);
++                      dev = dev_get_by_index(addr->v6.sin6_scope_id);
+                       if (!dev)
+                               return 0;
+                       if (!ipv6_chk_addr(&addr->v6.sin6_addr, dev, 0)) {
+diff -Nurb linux-2.6.22-590/net/sctp/protocol.c linux-2.6.22-570/net/sctp/protocol.c
+--- linux-2.6.22-590/net/sctp/protocol.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sctp/protocol.c       2007-07-08 19:32:17.000000000 -0400
+@@ -59,7 +59,6 @@
+ #include <net/addrconf.h>
+ #include <net/inet_common.h>
+ #include <net/inet_ecn.h>
+-#include <net/net_namespace.h>
+ /* Global data structures. */
+ struct sctp_globals sctp_globals __read_mostly;
+@@ -94,7 +93,7 @@
+ {
+       if (!proc_net_sctp) {
+               struct proc_dir_entry *ent;
+-              ent = proc_mkdir("sctp", init_net.proc_net);
++              ent = proc_mkdir("net/sctp", NULL);
+               if (ent) {
+                       ent->owner = THIS_MODULE;
+                       proc_net_sctp = ent;
+@@ -127,7 +126,7 @@
+       if (proc_net_sctp) {
+               proc_net_sctp = NULL;
+-              remove_proc_entry("sctp", init_net.proc_net);
++              remove_proc_entry("net/sctp", NULL);
+       }
+ }
+@@ -171,7 +170,7 @@
+       struct sctp_af *af;
+       read_lock(&dev_base_lock);
+-      for_each_netdev(&init_net, dev) {
++      for_each_netdev(dev) {
+               __list_for_each(pos, &sctp_address_families) {
+                       af = list_entry(pos, struct sctp_af, list);
+                       af->copy_addrlist(&sctp_local_addr_list, dev);
+@@ -355,13 +354,13 @@
+ /* Should this be available for binding?   */
+ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
+ {
+-      int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr);
++      int ret = inet_addr_type(addr->v4.sin_addr.s_addr);
+       if (addr->v4.sin_addr.s_addr != INADDR_ANY &&
+          ret != RTN_LOCAL &&
+          !sp->inet.freebind &&
+-         !init_net.sysctl_ip_nonlocal_bind)
++         !sysctl_ip_nonlocal_bind)
+               return 0;
+       return 1;
+@@ -424,7 +423,6 @@
+       union sctp_addr dst_saddr;
+       memset(&fl, 0x0, sizeof(struct flowi));
+-      fl.fl_net = &init_net;
+       fl.fl4_dst  = daddr->v4.sin_addr.s_addr;
+       fl.proto = IPPROTO_SCTP;
+       if (asoc) {
+@@ -541,7 +539,7 @@
+ {
+       struct inet_sock *inet = inet_sk(sk);
+       struct inet_sock *newinet;
+-      struct sock *newsk = sk_alloc(sk->sk_net, PF_INET, GFP_KERNEL, sk->sk_prot, 1);
++      struct sock *newsk = sk_alloc(PF_INET, GFP_KERNEL, sk->sk_prot, 1);
+       if (!newsk)
+               goto out;
+@@ -1124,7 +1122,7 @@
+       }
+       spin_lock_init(&sctp_port_alloc_lock);
+-      sctp_port_rover = init_net.sysctl_local_port_range[0] - 1;
++      sctp_port_rover = sysctl_local_port_range[0] - 1;
+       printk(KERN_INFO "SCTP: Hash tables configured "
+                        "(established %d bind %d)\n",
+diff -Nurb linux-2.6.22-590/net/sctp/socket.c linux-2.6.22-570/net/sctp/socket.c
+--- linux-2.6.22-590/net/sctp/socket.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sctp/socket.c 2007-07-08 19:32:17.000000000 -0400
+@@ -5021,8 +5021,8 @@
+                * already in the hash table; if not, we use that; if
+                * it is, we try next.
+                */
+-              int low = sk->sk_net->sysctl_local_port_range[0];
+-              int high = sk->sk_net->sysctl_local_port_range[1];
++              int low = sysctl_local_port_range[0];
++              int high = sysctl_local_port_range[1];
+               int remaining = (high - low) + 1;
+               int rover;
+               int index;
+diff -Nurb linux-2.6.22-590/net/socket.c linux-2.6.22-570/net/socket.c
+--- linux-2.6.22-590/net/socket.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/socket.c      2008-01-23 19:16:05.000000000 -0500
+@@ -84,7 +84,6 @@
+ #include <linux/kmod.h>
+ #include <linux/audit.h>
+ #include <linux/wireless.h>
+-#include <linux/nsproxy.h>
+ #include <asm/uaccess.h>
+ #include <asm/unistd.h>
+@@ -822,9 +821,9 @@
+  */
+ static DEFINE_MUTEX(br_ioctl_mutex);
+-static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg) = NULL;
++static int (*br_ioctl_hook) (unsigned int cmd, void __user *arg) = NULL;
+-void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
++void brioctl_set(int (*hook) (unsigned int, void __user *))
+ {
+       mutex_lock(&br_ioctl_mutex);
+       br_ioctl_hook = hook;
+@@ -834,9 +833,9 @@
+ EXPORT_SYMBOL(brioctl_set);
+ static DEFINE_MUTEX(vlan_ioctl_mutex);
+-static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
++static int (*vlan_ioctl_hook) (void __user *arg);
+-void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
++void vlan_ioctl_set(int (*hook) (void __user *))
+ {
+       mutex_lock(&vlan_ioctl_mutex);
+       vlan_ioctl_hook = hook;
+@@ -865,20 +864,16 @@
+ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+ {
+       struct socket *sock;
+-      struct sock *sk;
+       void __user *argp = (void __user *)arg;
+       int pid, err;
+-      struct net *net;
+       sock = file->private_data;
+-      sk = sock->sk;
+-      net = sk->sk_net;
+       if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
+-              err = dev_ioctl(net, cmd, argp);
++              err = dev_ioctl(cmd, argp);
+       } else
+ #ifdef CONFIG_WIRELESS_EXT
+       if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
+-              err = dev_ioctl(net, cmd, argp);
++              err = dev_ioctl(cmd, argp);
+       } else
+ #endif                                /* CONFIG_WIRELESS_EXT */
+               switch (cmd) {
+@@ -904,7 +899,7 @@
+                       mutex_lock(&br_ioctl_mutex);
+                       if (br_ioctl_hook)
+-                              err = br_ioctl_hook(net, cmd, argp);
++                              err = br_ioctl_hook(cmd, argp);
+                       mutex_unlock(&br_ioctl_mutex);
+                       break;
+               case SIOCGIFVLAN:
+@@ -915,7 +910,7 @@
+                       mutex_lock(&vlan_ioctl_mutex);
+                       if (vlan_ioctl_hook)
+-                              err = vlan_ioctl_hook(net, argp);
++                              err = vlan_ioctl_hook(argp);
+                       mutex_unlock(&vlan_ioctl_mutex);
+                       break;
+               case SIOCADDDLCI:
+@@ -938,7 +933,7 @@
+                        * to the NIC driver.
+                        */
+                       if (err == -ENOIOCTLCMD)
+-                              err = dev_ioctl(net, cmd, argp);
++                              err = dev_ioctl(cmd, argp);
+                       break;
+               }
+       return err;
+@@ -1107,7 +1102,7 @@
+       return 0;
+ }
+-static int __sock_create(struct net *net, int family, int type, int protocol,
++static int __sock_create(int family, int type, int protocol,
+                        struct socket **res, int kern)
+ {
+       int err;
+@@ -1190,7 +1185,7 @@
+       /* Now protected by module ref count */
+       rcu_read_unlock();
+-      err = pf->create(net, sock, protocol);
++      err = pf->create(sock, protocol);
+       if (err < 0)
+               goto out_module_put;
+@@ -1229,12 +1224,12 @@
+ int sock_create(int family, int type, int protocol, struct socket **res)
+ {
+-      return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
++      return __sock_create(family, type, protocol, res, 0);
+ }
+ int sock_create_kern(int family, int type, int protocol, struct socket **res)
+ {
+-      return __sock_create(&init_net, family, type, protocol, res, 1);
++      return __sock_create(family, type, protocol, res, 1);
+ }
+ asmlinkage long sys_socket(int family, int type, int protocol)
+@@ -1394,6 +1389,8 @@
+  *    ready for listening.
+  */
++int sysctl_somaxconn __read_mostly = SOMAXCONN;
++
+ asmlinkage long sys_listen(int fd, int backlog)
+ {
+       struct socket *sock;
+@@ -1401,9 +1398,8 @@
+       sock = sockfd_lookup_light(fd, &err, &fput_needed);
+       if (sock) {
+-              struct net *net = sock->sk->sk_net;
+-              if ((unsigned)backlog > net->sysctl_somaxconn)
+-                      backlog = net->sysctl_somaxconn;
++              if ((unsigned)backlog > sysctl_somaxconn)
++                      backlog = sysctl_somaxconn;
+               err = security_socket_listen(sock, backlog);
+               if (!err)
+@@ -2193,16 +2189,6 @@
+       printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
+ }
+-static int sock_pernet_init(struct net *net)
 -{
--      if (sock->ops->sendpage)
--              return sock->ops->sendpage(sock, page, offset, size, flags);
--
--      return sock_no_sendpage(sock, page, offset, size, flags);
+-      net->sysctl_somaxconn = SOMAXCONN;
+-      return 0;
 -}
 -
--int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
--{
--      mm_segment_t oldfs = get_fs();
--      int err;
--
--      set_fs(KERNEL_DS);
--      err = sock->ops->ioctl(sock, cmd, arg);
--      set_fs(oldfs);
+-static struct pernet_operations sock_net_ops = {
+-      .init = sock_pernet_init,
+-};
 -
--      return err;
--}
+ static int __init sock_init(void)
+ {
+       /*
+@@ -2231,8 +2217,6 @@
+       netfilter_init();
+ #endif
+-      register_pernet_subsys(&sock_net_ops);
 -
--/* ABI emulation layers need these two */
--EXPORT_SYMBOL(move_addr_to_kernel);
--EXPORT_SYMBOL(move_addr_to_user);
--EXPORT_SYMBOL(sock_create);
--EXPORT_SYMBOL(sock_create_kern);
--EXPORT_SYMBOL(sock_create_lite);
--EXPORT_SYMBOL(sock_map_fd);
--EXPORT_SYMBOL(sock_recvmsg);
--EXPORT_SYMBOL(sock_register);
--EXPORT_SYMBOL(sock_release);
--EXPORT_SYMBOL(sock_sendmsg);
--EXPORT_SYMBOL(sock_unregister);
--EXPORT_SYMBOL(sock_wake_async);
--EXPORT_SYMBOL(sockfd_lookup);
--EXPORT_SYMBOL(kernel_sendmsg);
--EXPORT_SYMBOL(kernel_recvmsg);
--EXPORT_SYMBOL(kernel_bind);
--EXPORT_SYMBOL(kernel_listen);
--EXPORT_SYMBOL(kernel_accept);
--EXPORT_SYMBOL(kernel_connect);
--EXPORT_SYMBOL(kernel_getsockname);
--EXPORT_SYMBOL(kernel_getpeername);
--EXPORT_SYMBOL(kernel_getsockopt);
--EXPORT_SYMBOL(kernel_setsockopt);
--EXPORT_SYMBOL(kernel_sendpage);
--EXPORT_SYMBOL(kernel_sock_ioctl);
-diff -Nurb linux-2.6.22-570/net/sunrpc/auth.c linux-2.6.22-590/net/sunrpc/auth.c
---- linux-2.6.22-570/net/sunrpc/auth.c 2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/sunrpc/auth.c 2008-01-02 13:56:38.000000000 -0500
-@@ -19,12 +19,16 @@
+       return 0;
+ }
+diff -Nurb linux-2.6.22-590/net/socket.c.orig linux-2.6.22-570/net/socket.c.orig
+--- linux-2.6.22-590/net/socket.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/net/socket.c.orig 2008-01-23 19:15:56.000000000 -0500
+@@ -0,0 +1,2344 @@
++/*
++ * NET                An implementation of the SOCKET network access protocol.
++ *
++ * Version:   @(#)socket.c    1.1.93  18/02/95
++ *
++ * Authors:   Orest Zborowski, <obz@Kodak.COM>
++ *            Ross Biro
++ *            Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
++ *
++ * Fixes:
++ *            Anonymous       :       NOTSOCK/BADF cleanup. Error fix in
++ *                                    shutdown()
++ *            Alan Cox        :       verify_area() fixes
++ *            Alan Cox        :       Removed DDI
++ *            Jonathan Kamens :       SOCK_DGRAM reconnect bug
++ *            Alan Cox        :       Moved a load of checks to the very
++ *                                    top level.
++ *            Alan Cox        :       Move address structures to/from user
++ *                                    mode above the protocol layers.
++ *            Rob Janssen     :       Allow 0 length sends.
++ *            Alan Cox        :       Asynchronous I/O support (cribbed from the
++ *                                    tty drivers).
++ *            Niibe Yutaka    :       Asynchronous I/O for writes (4.4BSD style)
++ *            Jeff Uphoff     :       Made max number of sockets command-line
++ *                                    configurable.
++ *            Matti Aarnio    :       Made the number of sockets dynamic,
++ *                                    to be allocated when needed, and mr.
++ *                                    Uphoff's max is used as max to be
++ *                                    allowed to allocate.
++ *            Linus           :       Argh. removed all the socket allocation
++ *                                    altogether: it's in the inode now.
++ *            Alan Cox        :       Made sock_alloc()/sock_release() public
++ *                                    for NetROM and future kernel nfsd type
++ *                                    stuff.
++ *            Alan Cox        :       sendmsg/recvmsg basics.
++ *            Tom Dyas        :       Export net symbols.
++ *            Marcin Dalecki  :       Fixed problems with CONFIG_NET="n".
++ *            Alan Cox        :       Added thread locking to sys_* calls
++ *                                    for sockets. May have errors at the
++ *                                    moment.
++ *            Kevin Buhr      :       Fixed the dumb errors in the above.
++ *            Andi Kleen      :       Some small cleanups, optimizations,
++ *                                    and fixed a copy_from_user() bug.
++ *            Tigran Aivazian :       sys_send(args) calls sys_sendto(args, NULL, 0)
++ *            Tigran Aivazian :       Made listen(2) backlog sanity checks
++ *                                    protocol-independent
++ *
++ *
++ *            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 module is effectively the top level interface to the BSD socket
++ *    paradigm.
++ *
++ *    Based upon Swansea University Computer Society NET3.039
++ */
++
++#include <linux/mm.h>
++#include <linux/socket.h>
++#include <linux/file.h>
++#include <linux/net.h>
++#include <linux/interrupt.h>
++#include <linux/rcupdate.h>
++#include <linux/netdevice.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/mutex.h>
++#include <linux/wanrouter.h>
++#include <linux/if_bridge.h>
++#include <linux/if_frad.h>
++#include <linux/if_vlan.h>
++#include <linux/init.h>
++#include <linux/poll.h>
++#include <linux/cache.h>
++#include <linux/module.h>
++#include <linux/highmem.h>
++#include <linux/mount.h>
++#include <linux/security.h>
++#include <linux/syscalls.h>
++#include <linux/compat.h>
++#include <linux/kmod.h>
++#include <linux/audit.h>
++#include <linux/wireless.h>
++
++#include <asm/uaccess.h>
++#include <asm/unistd.h>
++
++#include <net/compat.h>
++
++#include <net/sock.h>
++#include <linux/netfilter.h>
++
++static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
++static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
++                       unsigned long nr_segs, loff_t pos);
++static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
++                        unsigned long nr_segs, loff_t pos);
++static int sock_mmap(struct file *file, struct vm_area_struct *vma);
++
++static int sock_close(struct inode *inode, struct file *file);
++static unsigned int sock_poll(struct file *file,
++                            struct poll_table_struct *wait);
++static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
++#ifdef CONFIG_COMPAT
++static long compat_sock_ioctl(struct file *file,
++                            unsigned int cmd, unsigned long arg);
++#endif
++static int sock_fasync(int fd, struct file *filp, int on);
++static ssize_t sock_sendpage(struct file *file, struct page *page,
++                           int offset, size_t size, loff_t *ppos, int more);
++
++/*
++ *    Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
++ *    in the operation structures but are done directly via the socketcall() multiplexor.
++ */
++
++static const struct file_operations socket_file_ops = {
++      .owner =        THIS_MODULE,
++      .llseek =       no_llseek,
++      .aio_read =     sock_aio_read,
++      .aio_write =    sock_aio_write,
++      .poll =         sock_poll,
++      .unlocked_ioctl = sock_ioctl,
++#ifdef CONFIG_COMPAT
++      .compat_ioctl = compat_sock_ioctl,
++#endif
++      .mmap =         sock_mmap,
++      .open =         sock_no_open,   /* special open code to disallow open via /proc */
++      .release =      sock_close,
++      .fasync =       sock_fasync,
++      .sendpage =     sock_sendpage,
++      .splice_write = generic_splice_sendpage,
++};
++
++/*
++ *    The protocol list. Each protocol is registered in here.
++ */
++
++static DEFINE_SPINLOCK(net_family_lock);
++static const struct net_proto_family *net_families[NPROTO] __read_mostly;
++
++/*
++ *    Statistics counters of the socket lists
++ */
++
++static DEFINE_PER_CPU(int, sockets_in_use) = 0;
++
++/*
++ * Support routines.
++ * Move socket addresses back and forth across the kernel/user
++ * divide and look after the messy bits.
++ */
++
++#define MAX_SOCK_ADDR 128             /* 108 for Unix domain -
++                                         16 for IP, 16 for IPX,
++                                         24 for IPv6,
++                                         about 80 for AX.25
++                                         must be at least one bigger than
++                                         the AF_UNIX size (see net/unix/af_unix.c
++                                         :unix_mkname()).
++                                       */
++
++/**
++ *    move_addr_to_kernel     -       copy a socket address into kernel space
++ *    @uaddr: Address in user space
++ *    @kaddr: Address in kernel space
++ *    @ulen: Length in user space
++ *
++ *    The address is copied into kernel space. If the provided address is
++ *    too long an error code of -EINVAL is returned. If the copy gives
++ *    invalid addresses -EFAULT is returned. On a success 0 is returned.
++ */
++
++int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr)
++{
++      if (ulen < 0 || ulen > MAX_SOCK_ADDR)
++              return -EINVAL;
++      if (ulen == 0)
++              return 0;
++      if (copy_from_user(kaddr, uaddr, ulen))
++              return -EFAULT;
++      return audit_sockaddr(ulen, kaddr);
++}
++
++/**
++ *    move_addr_to_user       -       copy an address to user space
++ *    @kaddr: kernel space address
++ *    @klen: length of address in kernel
++ *    @uaddr: user space address
++ *    @ulen: pointer to user length field
++ *
++ *    The value pointed to by ulen on entry is the buffer length available.
++ *    This is overwritten with the buffer space used. -EINVAL is returned
++ *    if an overlong buffer is specified or a negative buffer size. -EFAULT
++ *    is returned if either the buffer or the length field are not
++ *    accessible.
++ *    After copying the data up to the limit the user specifies, the true
++ *    length of the data is written over the length limit the user
++ *    specified. Zero is returned for a success.
++ */
++
++int move_addr_to_user(void *kaddr, int klen, void __user *uaddr,
++                    int __user *ulen)
++{
++      int err;
++      int len;
++
++      err = get_user(len, ulen);
++      if (err)
++              return err;
++      if (len > klen)
++              len = klen;
++      if (len < 0 || len > MAX_SOCK_ADDR)
++              return -EINVAL;
++      if (len) {
++              if (audit_sockaddr(klen, kaddr))
++                      return -ENOMEM;
++              if (copy_to_user(uaddr, kaddr, len))
++                      return -EFAULT;
++      }
++      /*
++       *      "fromlen shall refer to the value before truncation.."
++       *                      1003.1g
++       */
++      return __put_user(klen, ulen);
++}
++
++#define SOCKFS_MAGIC 0x534F434B
++
++static struct kmem_cache *sock_inode_cachep __read_mostly;
++
++static struct inode *sock_alloc_inode(struct super_block *sb)
++{
++      struct socket_alloc *ei;
++
++      ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
++      if (!ei)
++              return NULL;
++      init_waitqueue_head(&ei->socket.wait);
++
++      ei->socket.fasync_list = NULL;
++      ei->socket.state = SS_UNCONNECTED;
++      ei->socket.flags = 0;
++      ei->socket.ops = NULL;
++      ei->socket.sk = NULL;
++      ei->socket.file = NULL;
++
++      return &ei->vfs_inode;
++}
++
++static void sock_destroy_inode(struct inode *inode)
++{
++      kmem_cache_free(sock_inode_cachep,
++                      container_of(inode, struct socket_alloc, vfs_inode));
++}
++
++static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
++{
++      struct socket_alloc *ei = (struct socket_alloc *)foo;
++
++      inode_init_once(&ei->vfs_inode);
++}
++
++static int init_inodecache(void)
++{
++      sock_inode_cachep = kmem_cache_create("sock_inode_cache",
++                                            sizeof(struct socket_alloc),
++                                            0,
++                                            (SLAB_HWCACHE_ALIGN |
++                                             SLAB_RECLAIM_ACCOUNT |
++                                             SLAB_MEM_SPREAD),
++                                            init_once,
++                                            NULL);
++      if (sock_inode_cachep == NULL)
++              return -ENOMEM;
++      return 0;
++}
++
++static struct super_operations sockfs_ops = {
++      .alloc_inode =  sock_alloc_inode,
++      .destroy_inode =sock_destroy_inode,
++      .statfs =       simple_statfs,
++};
++
++static int sockfs_get_sb(struct file_system_type *fs_type,
++                       int flags, const char *dev_name, void *data,
++                       struct vfsmount *mnt)
++{
++      return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC,
++                           mnt);
++}
++
++static struct vfsmount *sock_mnt __read_mostly;
++
++static struct file_system_type sock_fs_type = {
++      .name =         "sockfs",
++      .get_sb =       sockfs_get_sb,
++      .kill_sb =      kill_anon_super,
++};
++
++static int sockfs_delete_dentry(struct dentry *dentry)
++{
++      /*
++       * At creation time, we pretended this dentry was hashed
++       * (by clearing DCACHE_UNHASHED bit in d_flags)
++       * At delete time, we restore the truth : not hashed.
++       * (so that dput() can proceed correctly)
++       */
++      dentry->d_flags |= DCACHE_UNHASHED;
++      return 0;
++}
++
++/*
++ * sockfs_dname() is called from d_path().
++ */
++static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
++{
++      return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
++                              dentry->d_inode->i_ino);
++}
++
++static struct dentry_operations sockfs_dentry_operations = {
++      .d_delete = sockfs_delete_dentry,
++      .d_dname  = sockfs_dname,
++};
++
++/*
++ *    Obtains the first available file descriptor and sets it up for use.
++ *
++ *    These functions create file structures and maps them to fd space
++ *    of the current process. On success it returns file descriptor
++ *    and file struct implicitly stored in sock->file.
++ *    Note that another thread may close file descriptor before we return
++ *    from this function. We use the fact that now we do not refer
++ *    to socket after mapping. If one day we will need it, this
++ *    function will increment ref. count on file by 1.
++ *
++ *    In any case returned fd MAY BE not valid!
++ *    This race condition is unavoidable
++ *    with shared fd spaces, we cannot solve it inside kernel,
++ *    but we take care of internal coherence yet.
++ */
++
++static int sock_alloc_fd(struct file **filep)
++{
++      int fd;
++
++      fd = get_unused_fd();
++      if (likely(fd >= 0)) {
++              struct file *file = get_empty_filp();
++
++              *filep = file;
++              if (unlikely(!file)) {
++                      put_unused_fd(fd);
++                      return -ENFILE;
++              }
++      } else
++              *filep = NULL;
++      return fd;
++}
++
++static int sock_attach_fd(struct socket *sock, struct file *file)
++{
++      struct qstr name = { .name = "" };
++
++      file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
++      if (unlikely(!file->f_path.dentry))
++              return -ENOMEM;
++
++      file->f_path.dentry->d_op = &sockfs_dentry_operations;
++      /*
++       * We dont want to push this dentry into global dentry hash table.
++       * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
++       * This permits a working /proc/$pid/fd/XXX on sockets
++       */
++      file->f_path.dentry->d_flags &= ~DCACHE_UNHASHED;
++      d_instantiate(file->f_path.dentry, SOCK_INODE(sock));
++      file->f_path.mnt = mntget(sock_mnt);
++      file->f_mapping = file->f_path.dentry->d_inode->i_mapping;
++
++      sock->file = file;
++      file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
++      file->f_mode = FMODE_READ | FMODE_WRITE;
++      file->f_flags = O_RDWR;
++      file->f_pos = 0;
++      file->private_data = sock;
++
++      return 0;
++}
++
++int sock_map_fd(struct socket *sock)
++{
++      struct file *newfile;
++      int fd = sock_alloc_fd(&newfile);
++
++      if (likely(fd >= 0)) {
++              int err = sock_attach_fd(sock, newfile);
++
++              if (unlikely(err < 0)) {
++                      put_filp(newfile);
++                      put_unused_fd(fd);
++                      return err;
++              }
++              fd_install(fd, newfile);
++      }
++      return fd;
++}
++
++static struct socket *sock_from_file(struct file *file, int *err)
++{
++      if (file->f_op == &socket_file_ops)
++              return file->private_data;      /* set in sock_map_fd */
++
++      *err = -ENOTSOCK;
++      return NULL;
++}
++
++/**
++ *    sockfd_lookup   -       Go from a file number to its socket slot
++ *    @fd: file handle
++ *    @err: pointer to an error code return
++ *
++ *    The file handle passed in is locked and the socket it is bound
++ *    too is returned. If an error occurs the err pointer is overwritten
++ *    with a negative errno code and NULL is returned. The function checks
++ *    for both invalid handles and passing a handle which is not a socket.
++ *
++ *    On a success the socket object pointer is returned.
++ */
++
++struct socket *sockfd_lookup(int fd, int *err)
++{
++      struct file *file;
++      struct socket *sock;
++
++      file = fget(fd);
++      if (!file) {
++              *err = -EBADF;
++              return NULL;
++      }
++
++      sock = sock_from_file(file, err);
++      if (!sock)
++              fput(file);
++      return sock;
++}
++
++static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
++{
++      struct file *file;
++      struct socket *sock;
++
++      *err = -EBADF;
++      file = fget_light(fd, fput_needed);
++      if (file) {
++              sock = sock_from_file(file, err);
++              if (sock)
++                      return sock;
++              fput_light(file, *fput_needed);
++      }
++      return NULL;
++}
++
++/**
++ *    sock_alloc      -       allocate a socket
++ *
++ *    Allocate a new inode and socket object. The two are bound together
++ *    and initialised. The socket is then returned. If we are out of inodes
++ *    NULL is returned.
++ */
++
++static struct socket *sock_alloc(void)
++{
++      struct inode *inode;
++      struct socket *sock;
++
++      inode = new_inode(sock_mnt->mnt_sb);
++      if (!inode)
++              return NULL;
++
++      sock = SOCKET_I(inode);
++
++      inode->i_mode = S_IFSOCK | S_IRWXUGO;
++      inode->i_uid = current->fsuid;
++      inode->i_gid = current->fsgid;
++
++      get_cpu_var(sockets_in_use)++;
++      put_cpu_var(sockets_in_use);
++      return sock;
++}
++
++/*
++ *    In theory you can't get an open on this inode, but /proc provides
++ *    a back door. Remember to keep it shut otherwise you'll let the
++ *    creepy crawlies in.
++ */
++
++static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
++{
++      return -ENXIO;
++}
++
++const struct file_operations bad_sock_fops = {
++      .owner = THIS_MODULE,
++      .open = sock_no_open,
++};
++
++/**
++ *    sock_release    -       close a socket
++ *    @sock: socket to close
++ *
++ *    The socket is released from the protocol stack if it has a release
++ *    callback, and the inode is then released if the socket is bound to
++ *    an inode not a file.
++ */
++
++void sock_release(struct socket *sock)
++{
++      if (sock->ops) {
++              struct module *owner = sock->ops->owner;
++
++              sock->ops->release(sock);
++              sock->ops = NULL;
++              module_put(owner);
++      }
++
++      if (sock->fasync_list)
++              printk(KERN_ERR "sock_release: fasync list not empty!\n");
++
++      get_cpu_var(sockets_in_use)--;
++      put_cpu_var(sockets_in_use);
++      if (!sock->file) {
++              iput(SOCK_INODE(sock));
++              return;
++      }
++      sock->file = NULL;
++}
++
++static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
++                               struct msghdr *msg, size_t size)
++{
++      struct sock_iocb *si = kiocb_to_siocb(iocb);
++      int err;
++
++      si->sock = sock;
++      si->scm = NULL;
++      si->msg = msg;
++      si->size = size;
++
++      err = security_socket_sendmsg(sock, msg, size);
++      if (err)
++              return err;
++
++      return sock->ops->sendmsg(iocb, sock, msg, size);
++}
++
++int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
++{
++      struct kiocb iocb;
++      struct sock_iocb siocb;
++      int ret;
++
++      init_sync_kiocb(&iocb, NULL);
++      iocb.private = &siocb;
++      ret = __sock_sendmsg(&iocb, sock, msg, size);
++      if (-EIOCBQUEUED == ret)
++              ret = wait_on_sync_kiocb(&iocb);
++      return ret;
++}
++
++int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
++                 struct kvec *vec, size_t num, size_t size)
++{
++      mm_segment_t oldfs = get_fs();
++      int result;
++
++      set_fs(KERNEL_DS);
++      /*
++       * the following is safe, since for compiler definitions of kvec and
++       * iovec are identical, yielding the same in-core layout and alignment
++       */
++      msg->msg_iov = (struct iovec *)vec;
++      msg->msg_iovlen = num;
++      result = sock_sendmsg(sock, msg, size);
++      set_fs(oldfs);
++      return result;
++}
++
++/*
++ * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
++ */
++void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
++      struct sk_buff *skb)
++{
++      ktime_t kt = skb->tstamp;
++
++      if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
++              struct timeval tv;
++              /* Race occurred between timestamp enabling and packet
++                 receiving.  Fill in the current time for now. */
++              if (kt.tv64 == 0)
++                      kt = ktime_get_real();
++              skb->tstamp = kt;
++              tv = ktime_to_timeval(kt);
++              put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, sizeof(tv), &tv);
++      } else {
++              struct timespec ts;
++              /* Race occurred between timestamp enabling and packet
++                 receiving.  Fill in the current time for now. */
++              if (kt.tv64 == 0)
++                      kt = ktime_get_real();
++              skb->tstamp = kt;
++              ts = ktime_to_timespec(kt);
++              put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, sizeof(ts), &ts);
++      }
++}
++
++EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
++
++static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
++                               struct msghdr *msg, size_t size, int flags)
++{
++      int err;
++      struct sock_iocb *si = kiocb_to_siocb(iocb);
++
++      si->sock = sock;
++      si->scm = NULL;
++      si->msg = msg;
++      si->size = size;
++      si->flags = flags;
++
++      err = security_socket_recvmsg(sock, msg, size, flags);
++      if (err)
++              return err;
++
++      return sock->ops->recvmsg(iocb, sock, msg, size, flags);
++}
++
++int sock_recvmsg(struct socket *sock, struct msghdr *msg,
++               size_t size, int flags)
++{
++      struct kiocb iocb;
++      struct sock_iocb siocb;
++      int ret;
++
++      init_sync_kiocb(&iocb, NULL);
++      iocb.private = &siocb;
++      ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
++      if (-EIOCBQUEUED == ret)
++              ret = wait_on_sync_kiocb(&iocb);
++      return ret;
++}
++
++int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
++                 struct kvec *vec, size_t num, size_t size, int flags)
++{
++      mm_segment_t oldfs = get_fs();
++      int result;
++
++      set_fs(KERNEL_DS);
++      /*
++       * the following is safe, since for compiler definitions of kvec and
++       * iovec are identical, yielding the same in-core layout and alignment
++       */
++      msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
++      result = sock_recvmsg(sock, msg, size, flags);
++      set_fs(oldfs);
++      return result;
++}
++
++static void sock_aio_dtor(struct kiocb *iocb)
++{
++      kfree(iocb->private);
++}
++
++static ssize_t sock_sendpage(struct file *file, struct page *page,
++                           int offset, size_t size, loff_t *ppos, int more)
++{
++      struct socket *sock;
++      int flags;
++
++      sock = file->private_data;
++
++      flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
++      if (more)
++              flags |= MSG_MORE;
++
++      return sock->ops->sendpage(sock, page, offset, size, flags);
++}
++
++static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
++                                       struct sock_iocb *siocb)
++{
++      if (!is_sync_kiocb(iocb)) {
++              siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
++              if (!siocb)
++                      return NULL;
++              iocb->ki_dtor = sock_aio_dtor;
++      }
++
++      siocb->kiocb = iocb;
++      iocb->private = siocb;
++      return siocb;
++}
++
++static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
++              struct file *file, const struct iovec *iov,
++              unsigned long nr_segs)
++{
++      struct socket *sock = file->private_data;
++      size_t size = 0;
++      int i;
++
++      for (i = 0; i < nr_segs; i++)
++              size += iov[i].iov_len;
++
++      msg->msg_name = NULL;
++      msg->msg_namelen = 0;
++      msg->msg_control = NULL;
++      msg->msg_controllen = 0;
++      msg->msg_iov = (struct iovec *)iov;
++      msg->msg_iovlen = nr_segs;
++      msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
++
++      return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
++}
++
++static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
++                              unsigned long nr_segs, loff_t pos)
++{
++      struct sock_iocb siocb, *x;
++
++      if (pos != 0)
++              return -ESPIPE;
++
++      if (iocb->ki_left == 0) /* Match SYS5 behaviour */
++              return 0;
++
++
++      x = alloc_sock_iocb(iocb, &siocb);
++      if (!x)
++              return -ENOMEM;
++      return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
++}
++
++static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
++                      struct file *file, const struct iovec *iov,
++                      unsigned long nr_segs)
++{
++      struct socket *sock = file->private_data;
++      size_t size = 0;
++      int i;
++
++      for (i = 0; i < nr_segs; i++)
++              size += iov[i].iov_len;
++
++      msg->msg_name = NULL;
++      msg->msg_namelen = 0;
++      msg->msg_control = NULL;
++      msg->msg_controllen = 0;
++      msg->msg_iov = (struct iovec *)iov;
++      msg->msg_iovlen = nr_segs;
++      msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
++      if (sock->type == SOCK_SEQPACKET)
++              msg->msg_flags |= MSG_EOR;
++
++      return __sock_sendmsg(iocb, sock, msg, size);
++}
++
++static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
++                        unsigned long nr_segs, loff_t pos)
++{
++      struct sock_iocb siocb, *x;
++
++      if (pos != 0)
++              return -ESPIPE;
++
++      x = alloc_sock_iocb(iocb, &siocb);
++      if (!x)
++              return -ENOMEM;
++
++      return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
++}
++
++/*
++ * Atomic setting of ioctl hooks to avoid race
++ * with module unload.
++ */
++
++static DEFINE_MUTEX(br_ioctl_mutex);
++static int (*br_ioctl_hook) (unsigned int cmd, void __user *arg) = NULL;
++
++void brioctl_set(int (*hook) (unsigned int, void __user *))
++{
++      mutex_lock(&br_ioctl_mutex);
++      br_ioctl_hook = hook;
++      mutex_unlock(&br_ioctl_mutex);
++}
++
++EXPORT_SYMBOL(brioctl_set);
++
++static DEFINE_MUTEX(vlan_ioctl_mutex);
++static int (*vlan_ioctl_hook) (void __user *arg);
++
++void vlan_ioctl_set(int (*hook) (void __user *))
++{
++      mutex_lock(&vlan_ioctl_mutex);
++      vlan_ioctl_hook = hook;
++      mutex_unlock(&vlan_ioctl_mutex);
++}
++
++EXPORT_SYMBOL(vlan_ioctl_set);
++
++static DEFINE_MUTEX(dlci_ioctl_mutex);
++static int (*dlci_ioctl_hook) (unsigned int, void __user *);
++
++void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
++{
++      mutex_lock(&dlci_ioctl_mutex);
++      dlci_ioctl_hook = hook;
++      mutex_unlock(&dlci_ioctl_mutex);
++}
++
++EXPORT_SYMBOL(dlci_ioctl_set);
++
++/*
++ *    With an ioctl, arg may well be a user mode pointer, but we don't know
++ *    what to do with it - that's up to the protocol still.
++ */
++
++static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
++{
++      struct socket *sock;
++      void __user *argp = (void __user *)arg;
++      int pid, err;
++
++      sock = file->private_data;
++      if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
++              err = dev_ioctl(cmd, argp);
++      } else
++#ifdef CONFIG_WIRELESS_EXT
++      if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
++              err = dev_ioctl(cmd, argp);
++      } else
++#endif                                /* CONFIG_WIRELESS_EXT */
++              switch (cmd) {
++              case FIOSETOWN:
++              case SIOCSPGRP:
++                      err = -EFAULT;
++                      if (get_user(pid, (int __user *)argp))
++                              break;
++                      err = f_setown(sock->file, pid, 1);
++                      break;
++              case FIOGETOWN:
++              case SIOCGPGRP:
++                      err = put_user(f_getown(sock->file),
++                                     (int __user *)argp);
++                      break;
++              case SIOCGIFBR:
++              case SIOCSIFBR:
++              case SIOCBRADDBR:
++              case SIOCBRDELBR:
++                      err = -ENOPKG;
++                      if (!br_ioctl_hook)
++                              request_module("bridge");
++
++                      mutex_lock(&br_ioctl_mutex);
++                      if (br_ioctl_hook)
++                              err = br_ioctl_hook(cmd, argp);
++                      mutex_unlock(&br_ioctl_mutex);
++                      break;
++              case SIOCGIFVLAN:
++              case SIOCSIFVLAN:
++                      err = -ENOPKG;
++                      if (!vlan_ioctl_hook)
++                              request_module("8021q");
++
++                      mutex_lock(&vlan_ioctl_mutex);
++                      if (vlan_ioctl_hook)
++                              err = vlan_ioctl_hook(argp);
++                      mutex_unlock(&vlan_ioctl_mutex);
++                      break;
++              case SIOCADDDLCI:
++              case SIOCDELDLCI:
++                      err = -ENOPKG;
++                      if (!dlci_ioctl_hook)
++                              request_module("dlci");
++
++                      if (dlci_ioctl_hook) {
++                              mutex_lock(&dlci_ioctl_mutex);
++                              err = dlci_ioctl_hook(cmd, argp);
++                              mutex_unlock(&dlci_ioctl_mutex);
++                      }
++                      break;
++              default:
++                      err = sock->ops->ioctl(sock, cmd, arg);
++
++                      /*
++                       * If this ioctl is unknown try to hand it down
++                       * to the NIC driver.
++                       */
++                      if (err == -ENOIOCTLCMD)
++                              err = dev_ioctl(cmd, argp);
++                      break;
++              }
++      return err;
++}
++
++int sock_create_lite(int family, int type, int protocol, struct socket **res)
++{
++      int err;
++      struct socket *sock = NULL;
++
++      err = security_socket_create(family, type, protocol, 1);
++      if (err)
++              goto out;
++
++      sock = sock_alloc();
++      if (!sock) {
++              err = -ENOMEM;
++              goto out;
++      }
++
++      sock->type = type;
++      err = security_socket_post_create(sock, family, type, protocol, 1);
++      if (err)
++              goto out_release;
++
++out:
++      *res = sock;
++      return err;
++out_release:
++      sock_release(sock);
++      sock = NULL;
++      goto out;
++}
++
++/* No kernel lock held - perfect */
++static unsigned int sock_poll(struct file *file, poll_table *wait)
++{
++      struct socket *sock;
++
++      /*
++       *      We can't return errors to poll, so it's either yes or no.
++       */
++      sock = file->private_data;
++      return sock->ops->poll(file, sock, wait);
++}
++
++static int sock_mmap(struct file *file, struct vm_area_struct *vma)
++{
++      struct socket *sock = file->private_data;
++
++      return sock->ops->mmap(file, sock, vma);
++}
++
++static int sock_close(struct inode *inode, struct file *filp)
++{
++      /*
++       *      It was possible the inode is NULL we were
++       *      closing an unfinished socket.
++       */
++
++      if (!inode) {
++              printk(KERN_DEBUG "sock_close: NULL inode\n");
++              return 0;
++      }
++      sock_fasync(-1, filp, 0);
++      sock_release(SOCKET_I(inode));
++      return 0;
++}
++
++/*
++ *    Update the socket async list
++ *
++ *    Fasync_list locking strategy.
++ *
++ *    1. fasync_list is modified only under process context socket lock
++ *       i.e. under semaphore.
++ *    2. fasync_list is used under read_lock(&sk->sk_callback_lock)
++ *       or under socket lock.
++ *    3. fasync_list can be used from softirq context, so that
++ *       modification under socket lock have to be enhanced with
++ *       write_lock_bh(&sk->sk_callback_lock).
++ *                                                    --ANK (990710)
++ */
++
++static int sock_fasync(int fd, struct file *filp, int on)
++{
++      struct fasync_struct *fa, *fna = NULL, **prev;
++      struct socket *sock;
++      struct sock *sk;
++
++      if (on) {
++              fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
++              if (fna == NULL)
++                      return -ENOMEM;
++      }
++
++      sock = filp->private_data;
++
++      sk = sock->sk;
++      if (sk == NULL) {
++              kfree(fna);
++              return -EINVAL;
++      }
++
++      lock_sock(sk);
++
++      prev = &(sock->fasync_list);
++
++      for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev)
++              if (fa->fa_file == filp)
++                      break;
++
++      if (on) {
++              if (fa != NULL) {
++                      write_lock_bh(&sk->sk_callback_lock);
++                      fa->fa_fd = fd;
++                      write_unlock_bh(&sk->sk_callback_lock);
++
++                      kfree(fna);
++                      goto out;
++              }
++              fna->fa_file = filp;
++              fna->fa_fd = fd;
++              fna->magic = FASYNC_MAGIC;
++              fna->fa_next = sock->fasync_list;
++              write_lock_bh(&sk->sk_callback_lock);
++              sock->fasync_list = fna;
++              write_unlock_bh(&sk->sk_callback_lock);
++      } else {
++              if (fa != NULL) {
++                      write_lock_bh(&sk->sk_callback_lock);
++                      *prev = fa->fa_next;
++                      write_unlock_bh(&sk->sk_callback_lock);
++                      kfree(fa);
++              }
++      }
++
++out:
++      release_sock(sock->sk);
++      return 0;
++}
++
++/* This function may be called only under socket lock or callback_lock */
++
++int sock_wake_async(struct socket *sock, int how, int band)
++{
++      if (!sock || !sock->fasync_list)
++              return -1;
++      switch (how) {
++      case 1:
++
++              if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
++                      break;
++              goto call_kill;
++      case 2:
++              if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
++                      break;
++              /* fall through */
++      case 0:
++call_kill:
++              __kill_fasync(sock->fasync_list, SIGIO, band);
++              break;
++      case 3:
++              __kill_fasync(sock->fasync_list, SIGURG, band);
++      }
++      return 0;
++}
++
++static int __sock_create(int family, int type, int protocol,
++                       struct socket **res, int kern)
++{
++      int err;
++      struct socket *sock;
++      const struct net_proto_family *pf;
++
++      /*
++       *      Check protocol is in range
++       */
++      if (family < 0 || family >= NPROTO)
++              return -EAFNOSUPPORT;
++      if (type < 0 || type >= SOCK_MAX)
++              return -EINVAL;
++
++      /* Compatibility.
++
++         This uglymoron is moved from INET layer to here to avoid
++         deadlock in module load.
++       */
++      if (family == PF_INET && type == SOCK_PACKET) {
++              static int warned;
++              if (!warned) {
++                      warned = 1;
++                      printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",
++                             current->comm);
++              }
++              family = PF_PACKET;
++      }
++
++      err = security_socket_create(family, type, protocol, kern);
++      if (err)
++              return err;
++
++      /*
++       *      Allocate the socket and allow the family to set things up. if
++       *      the protocol is 0, the family is instructed to select an appropriate
++       *      default.
++       */
++      sock = sock_alloc();
++      if (!sock) {
++              if (net_ratelimit())
++                      printk(KERN_WARNING "socket: no more sockets\n");
++              return -ENFILE; /* Not exactly a match, but its the
++                                 closest posix thing */
++      }
++
++      sock->type = type;
++
++#if defined(CONFIG_KMOD)
++      /* Attempt to load a protocol module if the find failed.
++       *
++       * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
++       * requested real, full-featured networking support upon configuration.
++       * Otherwise module support will break!
++       */
++      if (net_families[family] == NULL)
++              request_module("net-pf-%d", family);
++#endif
++
++      rcu_read_lock();
++      pf = rcu_dereference(net_families[family]);
++      err = -EAFNOSUPPORT;
++      if (!pf)
++              goto out_release;
++
++      /*
++       * We will call the ->create function, that possibly is in a loadable
++       * module, so we have to bump that loadable module refcnt first.
++       */
++      if (!try_module_get(pf->owner))
++              goto out_release;
++
++      /* Now protected by module ref count */
++      rcu_read_unlock();
++
++      err = pf->create(sock, protocol);
++      if (err < 0)
++              goto out_module_put;
++
++      /*
++       * Now to bump the refcnt of the [loadable] module that owns this
++       * socket at sock_release time we decrement its refcnt.
++       */
++      if (!try_module_get(sock->ops->owner))
++              goto out_module_busy;
++
++      /*
++       * Now that we're done with the ->create function, the [loadable]
++       * module can have its refcnt decremented
++       */
++      module_put(pf->owner);
++      err = security_socket_post_create(sock, family, type, protocol, kern);
++      if (err)
++              goto out_sock_release;
++      *res = sock;
++
++      return 0;
++
++out_module_busy:
++      err = -EAFNOSUPPORT;
++out_module_put:
++      sock->ops = NULL;
++      module_put(pf->owner);
++out_sock_release:
++      sock_release(sock);
++      return err;
++
++out_release:
++      rcu_read_unlock();
++      goto out_sock_release;
++}
++
++int sock_create(int family, int type, int protocol, struct socket **res)
++{
++      return __sock_create(family, type, protocol, res, 0);
++}
++
++int sock_create_kern(int family, int type, int protocol, struct socket **res)
++{
++      return __sock_create(family, type, protocol, res, 1);
++}
++
++asmlinkage long sys_socket(int family, int type, int protocol)
++{
++      int retval;
++      struct socket *sock;
++
++      retval = sock_create(family, type, protocol, &sock);
++      if (retval < 0)
++              goto out;
++
++      retval = sock_map_fd(sock);
++      if (retval < 0)
++              goto out_release;
++
++out:
++      /* It may be already another descriptor 8) Not kernel problem. */
++      return retval;
++
++out_release:
++      sock_release(sock);
++      return retval;
++}
++
++/*
++ *    Create a pair of connected sockets.
++ */
++
++asmlinkage long sys_socketpair(int family, int type, int protocol,
++                             int __user *usockvec)
++{
++      struct socket *sock1, *sock2;
++      int fd1, fd2, err;
++      struct file *newfile1, *newfile2;
++
++      /*
++       * Obtain the first socket and check if the underlying protocol
++       * supports the socketpair call.
++       */
++
++      err = sock_create(family, type, protocol, &sock1);
++      if (err < 0)
++              goto out;
++
++      err = sock_create(family, type, protocol, &sock2);
++      if (err < 0)
++              goto out_release_1;
++
++      err = sock1->ops->socketpair(sock1, sock2);
++      if (err < 0)
++              goto out_release_both;
++
++      fd1 = sock_alloc_fd(&newfile1);
++      if (unlikely(fd1 < 0)) {
++              err = fd1;
++              goto out_release_both;
++      }
++
++      fd2 = sock_alloc_fd(&newfile2);
++      if (unlikely(fd2 < 0)) {
++              err = fd2;
++              put_filp(newfile1);
++              put_unused_fd(fd1);
++              goto out_release_both;
++      }
++
++      err = sock_attach_fd(sock1, newfile1);
++      if (unlikely(err < 0)) {
++              goto out_fd2;
++      }
++
++      err = sock_attach_fd(sock2, newfile2);
++      if (unlikely(err < 0)) {
++              fput(newfile1);
++              goto out_fd1;
++      }
++
++      err = audit_fd_pair(fd1, fd2);
++      if (err < 0) {
++              fput(newfile1);
++              fput(newfile2);
++              goto out_fd;
++      }
++
++      fd_install(fd1, newfile1);
++      fd_install(fd2, newfile2);
++      /* fd1 and fd2 may be already another descriptors.
++       * Not kernel problem.
++       */
++
++      err = put_user(fd1, &usockvec[0]);
++      if (!err)
++              err = put_user(fd2, &usockvec[1]);
++      if (!err)
++              return 0;
++
++      sys_close(fd2);
++      sys_close(fd1);
++      return err;
++
++out_release_both:
++      sock_release(sock2);
++out_release_1:
++      sock_release(sock1);
++out:
++      return err;
++
++out_fd2:
++      put_filp(newfile1);
++      sock_release(sock1);
++out_fd1:
++      put_filp(newfile2);
++      sock_release(sock2);
++out_fd:
++      put_unused_fd(fd1);
++      put_unused_fd(fd2);
++      goto out;
++}
++
++/*
++ *    Bind a name to a socket. Nothing much to do here since it's
++ *    the protocol's responsibility to handle the local address.
++ *
++ *    We move the socket address to kernel space before we call
++ *    the protocol layer (having also checked the address is ok).
++ */
++
++asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
++{
++      struct socket *sock;
++      char address[MAX_SOCK_ADDR];
++      int err, fput_needed;
++
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      if (sock) {
++              err = move_addr_to_kernel(umyaddr, addrlen, address);
++              if (err >= 0) {
++                      err = security_socket_bind(sock,
++                                                 (struct sockaddr *)address,
++                                                 addrlen);
++                      if (!err)
++                              err = sock->ops->bind(sock,
++                                                    (struct sockaddr *)
++                                                    address, addrlen);
++              }
++              fput_light(sock->file, fput_needed);
++      }
++      return err;
++}
++
++/*
++ *    Perform a listen. Basically, we allow the protocol to do anything
++ *    necessary for a listen, and if that works, we mark the socket as
++ *    ready for listening.
++ */
++
++int sysctl_somaxconn __read_mostly = SOMAXCONN;
++
++asmlinkage long sys_listen(int fd, int backlog)
++{
++      struct socket *sock;
++      int err, fput_needed;
++
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      if (sock) {
++              if ((unsigned)backlog > sysctl_somaxconn)
++                      backlog = sysctl_somaxconn;
++
++              err = security_socket_listen(sock, backlog);
++              if (!err)
++                      err = sock->ops->listen(sock, backlog);
++
++              fput_light(sock->file, fput_needed);
++      }
++      return err;
++}
++
++/*
++ *    For accept, we attempt to create a new socket, set up the link
++ *    with the client, wake up the client, then return the new
++ *    connected fd. We collect the address of the connector in kernel
++ *    space and move it to user at the very end. This is unclean because
++ *    we open the socket then return an error.
++ *
++ *    1003.1g adds the ability to recvmsg() to query connection pending
++ *    status to recvmsg. We need to add that support in a way thats
++ *    clean when we restucture accept also.
++ */
++
++asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
++                         int __user *upeer_addrlen)
++{
++      struct socket *sock, *newsock;
++      struct file *newfile;
++      int err, len, newfd, fput_needed;
++      char address[MAX_SOCK_ADDR];
++
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      if (!sock)
++              goto out;
++
++      err = -ENFILE;
++      if (!(newsock = sock_alloc()))
++              goto out_put;
++
++      newsock->type = sock->type;
++      newsock->ops = sock->ops;
++
++      /*
++       * We don't need try_module_get here, as the listening socket (sock)
++       * has the protocol module (sock->ops->owner) held.
++       */
++      __module_get(newsock->ops->owner);
++
++      newfd = sock_alloc_fd(&newfile);
++      if (unlikely(newfd < 0)) {
++              err = newfd;
++              sock_release(newsock);
++              goto out_put;
++      }
++
++      err = sock_attach_fd(newsock, newfile);
++      if (err < 0)
++              goto out_fd_simple;
++
++      err = security_socket_accept(sock, newsock);
++      if (err)
++              goto out_fd;
++
++      err = sock->ops->accept(sock, newsock, sock->file->f_flags);
++      if (err < 0)
++              goto out_fd;
++
++      if (upeer_sockaddr) {
++              if (newsock->ops->getname(newsock, (struct sockaddr *)address,
++                                        &len, 2) < 0) {
++                      err = -ECONNABORTED;
++                      goto out_fd;
++              }
++              err = move_addr_to_user(address, len, upeer_sockaddr,
++                                      upeer_addrlen);
++              if (err < 0)
++                      goto out_fd;
++      }
++
++      /* File flags are not inherited via accept() unlike another OSes. */
++
++      fd_install(newfd, newfile);
++      err = newfd;
++
++      security_socket_post_accept(sock, newsock);
++
++out_put:
++      fput_light(sock->file, fput_needed);
++out:
++      return err;
++out_fd_simple:
++      sock_release(newsock);
++      put_filp(newfile);
++      put_unused_fd(newfd);
++      goto out_put;
++out_fd:
++      fput(newfile);
++      put_unused_fd(newfd);
++      goto out_put;
++}
++
++/*
++ *    Attempt to connect to a socket with the server address.  The address
++ *    is in user space so we verify it is OK and move it to kernel space.
++ *
++ *    For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
++ *    break bindings
++ *
++ *    NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
++ *    other SEQPACKET protocols that take time to connect() as it doesn't
++ *    include the -EINPROGRESS status for such sockets.
++ */
++
++asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr,
++                          int addrlen)
++{
++      struct socket *sock;
++      char address[MAX_SOCK_ADDR];
++      int err, fput_needed;
++
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      if (!sock)
++              goto out;
++      err = move_addr_to_kernel(uservaddr, addrlen, address);
++      if (err < 0)
++              goto out_put;
++
++      err =
++          security_socket_connect(sock, (struct sockaddr *)address, addrlen);
++      if (err)
++              goto out_put;
++
++      err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
++                               sock->file->f_flags);
++out_put:
++      fput_light(sock->file, fput_needed);
++out:
++      return err;
++}
++
++/*
++ *    Get the local address ('name') of a socket object. Move the obtained
++ *    name to user space.
++ */
++
++asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,
++                              int __user *usockaddr_len)
++{
++      struct socket *sock;
++      char address[MAX_SOCK_ADDR];
++      int len, err, fput_needed;
++
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      if (!sock)
++              goto out;
++
++      err = security_socket_getsockname(sock);
++      if (err)
++              goto out_put;
++
++      err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0);
++      if (err)
++              goto out_put;
++      err = move_addr_to_user(address, len, usockaddr, usockaddr_len);
++
++out_put:
++      fput_light(sock->file, fput_needed);
++out:
++      return err;
++}
++
++/*
++ *    Get the remote address ('name') of a socket object. Move the obtained
++ *    name to user space.
++ */
++
++asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,
++                              int __user *usockaddr_len)
++{
++      struct socket *sock;
++      char address[MAX_SOCK_ADDR];
++      int len, err, fput_needed;
++
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      if (sock != NULL) {
++              err = security_socket_getpeername(sock);
++              if (err) {
++                      fput_light(sock->file, fput_needed);
++                      return err;
++              }
++
++              err =
++                  sock->ops->getname(sock, (struct sockaddr *)address, &len,
++                                     1);
++              if (!err)
++                      err = move_addr_to_user(address, len, usockaddr,
++                                              usockaddr_len);
++              fput_light(sock->file, fput_needed);
++      }
++      return err;
++}
++
++/*
++ *    Send a datagram to a given address. We move the address into kernel
++ *    space and check the user space data area is readable before invoking
++ *    the protocol.
++ */
++
++asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
++                         unsigned flags, struct sockaddr __user *addr,
++                         int addr_len)
++{
++      struct socket *sock;
++      char address[MAX_SOCK_ADDR];
++      int err;
++      struct msghdr msg;
++      struct iovec iov;
++      int fput_needed;
++      struct file *sock_file;
++
++      sock_file = fget_light(fd, &fput_needed);
++      err = -EBADF;
++      if (!sock_file)
++              goto out;
++
++      sock = sock_from_file(sock_file, &err);
++      if (!sock)
++              goto out_put;
++      iov.iov_base = buff;
++      iov.iov_len = len;
++      msg.msg_name = NULL;
++      msg.msg_iov = &iov;
++      msg.msg_iovlen = 1;
++      msg.msg_control = NULL;
++      msg.msg_controllen = 0;
++      msg.msg_namelen = 0;
++      if (addr) {
++              err = move_addr_to_kernel(addr, addr_len, address);
++              if (err < 0)
++                      goto out_put;
++              msg.msg_name = address;
++              msg.msg_namelen = addr_len;
++      }
++      if (sock->file->f_flags & O_NONBLOCK)
++              flags |= MSG_DONTWAIT;
++      msg.msg_flags = flags;
++      err = sock_sendmsg(sock, &msg, len);
++
++out_put:
++      fput_light(sock_file, fput_needed);
++out:
++      return err;
++}
++
++/*
++ *    Send a datagram down a socket.
++ */
++
++asmlinkage long sys_send(int fd, void __user *buff, size_t len, unsigned flags)
++{
++      return sys_sendto(fd, buff, len, flags, NULL, 0);
++}
++
++/*
++ *    Receive a frame from the socket and optionally record the address of the
++ *    sender. We verify the buffers are writable and if needed move the
++ *    sender address from kernel to user space.
++ */
++
++asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
++                           unsigned flags, struct sockaddr __user *addr,
++                           int __user *addr_len)
++{
++      struct socket *sock;
++      struct iovec iov;
++      struct msghdr msg;
++      char address[MAX_SOCK_ADDR];
++      int err, err2;
++      struct file *sock_file;
++      int fput_needed;
++
++      sock_file = fget_light(fd, &fput_needed);
++      err = -EBADF;
++      if (!sock_file)
++              goto out;
++
++      sock = sock_from_file(sock_file, &err);
++      if (!sock)
++              goto out_put;
++
++      msg.msg_control = NULL;
++      msg.msg_controllen = 0;
++      msg.msg_iovlen = 1;
++      msg.msg_iov = &iov;
++      iov.iov_len = size;
++      iov.iov_base = ubuf;
++      msg.msg_name = address;
++      msg.msg_namelen = MAX_SOCK_ADDR;
++      if (sock->file->f_flags & O_NONBLOCK)
++              flags |= MSG_DONTWAIT;
++      err = sock_recvmsg(sock, &msg, size, flags);
++
++      if (err >= 0 && addr != NULL) {
++              err2 = move_addr_to_user(address, msg.msg_namelen, addr, addr_len);
++              if (err2 < 0)
++                      err = err2;
++      }
++out_put:
++      fput_light(sock_file, fput_needed);
++out:
++      return err;
++}
++
++/*
++ *    Receive a datagram from a socket.
++ */
++
++asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
++                       unsigned flags)
++{
++      return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
++}
++
++/*
++ *    Set a socket option. Because we don't know the option lengths we have
++ *    to pass the user mode parameter for the protocols to sort out.
++ */
++
++asmlinkage long sys_setsockopt(int fd, int level, int optname,
++                             char __user *optval, int optlen)
++{
++      int err, fput_needed;
++      struct socket *sock;
++
++      if (optlen < 0)
++              return -EINVAL;
++
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      if (sock != NULL) {
++              err = security_socket_setsockopt(sock, level, optname);
++              if (err)
++                      goto out_put;
++
++              if (level == SOL_SOCKET)
++                      err =
++                          sock_setsockopt(sock, level, optname, optval,
++                                          optlen);
++              else
++                      err =
++                          sock->ops->setsockopt(sock, level, optname, optval,
++                                                optlen);
++out_put:
++              fput_light(sock->file, fput_needed);
++      }
++      return err;
++}
++
++/*
++ *    Get a socket option. Because we don't know the option lengths we have
++ *    to pass a user mode parameter for the protocols to sort out.
++ */
++
++asmlinkage long sys_getsockopt(int fd, int level, int optname,
++                             char __user *optval, int __user *optlen)
++{
++      int err, fput_needed;
++      struct socket *sock;
++
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      if (sock != NULL) {
++              err = security_socket_getsockopt(sock, level, optname);
++              if (err)
++                      goto out_put;
++
++              if (level == SOL_SOCKET)
++                      err =
++                          sock_getsockopt(sock, level, optname, optval,
++                                          optlen);
++              else
++                      err =
++                          sock->ops->getsockopt(sock, level, optname, optval,
++                                                optlen);
++out_put:
++              fput_light(sock->file, fput_needed);
++      }
++      return err;
++}
++
++/*
++ *    Shutdown a socket.
++ */
++
++asmlinkage long sys_shutdown(int fd, int how)
++{
++      int err, fput_needed;
++      struct socket *sock;
++
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      if (sock != NULL) {
++              err = security_socket_shutdown(sock, how);
++              if (!err)
++                      err = sock->ops->shutdown(sock, how);
++              fput_light(sock->file, fput_needed);
++      }
++      return err;
++}
++
++/* A couple of helpful macros for getting the address of the 32/64 bit
++ * fields which are the same type (int / unsigned) on our platforms.
++ */
++#define COMPAT_MSG(msg, member)       ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
++#define COMPAT_NAMELEN(msg)   COMPAT_MSG(msg, msg_namelen)
++#define COMPAT_FLAGS(msg)     COMPAT_MSG(msg, msg_flags)
++
++/*
++ *    BSD sendmsg interface
++ */
++
++asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
++{
++      struct compat_msghdr __user *msg_compat =
++          (struct compat_msghdr __user *)msg;
++      struct socket *sock;
++      char address[MAX_SOCK_ADDR];
++      struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
++      unsigned char ctl[sizeof(struct cmsghdr) + 20]
++          __attribute__ ((aligned(sizeof(__kernel_size_t))));
++      /* 20 is size of ipv6_pktinfo */
++      unsigned char *ctl_buf = ctl;
++      struct msghdr msg_sys;
++      int err, ctl_len, iov_size, total_len;
++      int fput_needed;
++
++      err = -EFAULT;
++      if (MSG_CMSG_COMPAT & flags) {
++              if (get_compat_msghdr(&msg_sys, msg_compat))
++                      return -EFAULT;
++      }
++      else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
++              return -EFAULT;
++
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      if (!sock)
++              goto out;
++
++      /* do not move before msg_sys is valid */
++      err = -EMSGSIZE;
++      if (msg_sys.msg_iovlen > UIO_MAXIOV)
++              goto out_put;
++
++      /* Check whether to allocate the iovec area */
++      err = -ENOMEM;
++      iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
++      if (msg_sys.msg_iovlen > UIO_FASTIOV) {
++              iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
++              if (!iov)
++                      goto out_put;
++      }
++
++      /* This will also move the address data into kernel space */
++      if (MSG_CMSG_COMPAT & flags) {
++              err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
++      } else
++              err = verify_iovec(&msg_sys, iov, address, VERIFY_READ);
++      if (err < 0)
++              goto out_freeiov;
++      total_len = err;
++
++      err = -ENOBUFS;
++
++      if (msg_sys.msg_controllen > INT_MAX)
++              goto out_freeiov;
++      ctl_len = msg_sys.msg_controllen;
++      if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
++              err =
++                  cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl,
++                                                   sizeof(ctl));
++              if (err)
++                      goto out_freeiov;
++              ctl_buf = msg_sys.msg_control;
++              ctl_len = msg_sys.msg_controllen;
++      } else if (ctl_len) {
++              if (ctl_len > sizeof(ctl)) {
++                      ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
++                      if (ctl_buf == NULL)
++                              goto out_freeiov;
++              }
++              err = -EFAULT;
++              /*
++               * Careful! Before this, msg_sys.msg_control contains a user pointer.
++               * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
++               * checking falls down on this.
++               */
++              if (copy_from_user(ctl_buf, (void __user *)msg_sys.msg_control,
++                                 ctl_len))
++                      goto out_freectl;
++              msg_sys.msg_control = ctl_buf;
++      }
++      msg_sys.msg_flags = flags;
++
++      if (sock->file->f_flags & O_NONBLOCK)
++              msg_sys.msg_flags |= MSG_DONTWAIT;
++      err = sock_sendmsg(sock, &msg_sys, total_len);
++
++out_freectl:
++      if (ctl_buf != ctl)
++              sock_kfree_s(sock->sk, ctl_buf, ctl_len);
++out_freeiov:
++      if (iov != iovstack)
++              sock_kfree_s(sock->sk, iov, iov_size);
++out_put:
++      fput_light(sock->file, fput_needed);
++out:
++      return err;
++}
++
++/*
++ *    BSD recvmsg interface
++ */
++
++asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
++                          unsigned int flags)
++{
++      struct compat_msghdr __user *msg_compat =
++          (struct compat_msghdr __user *)msg;
++      struct socket *sock;
++      struct iovec iovstack[UIO_FASTIOV];
++      struct iovec *iov = iovstack;
++      struct msghdr msg_sys;
++      unsigned long cmsg_ptr;
++      int err, iov_size, total_len, len;
++      int fput_needed;
++
++      /* kernel mode address */
++      char addr[MAX_SOCK_ADDR];
++
++      /* user mode address pointers */
++      struct sockaddr __user *uaddr;
++      int __user *uaddr_len;
++
++      if (MSG_CMSG_COMPAT & flags) {
++              if (get_compat_msghdr(&msg_sys, msg_compat))
++                      return -EFAULT;
++      }
++      else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
++              return -EFAULT;
++
++      sock = sockfd_lookup_light(fd, &err, &fput_needed);
++      if (!sock)
++              goto out;
++
++      err = -EMSGSIZE;
++      if (msg_sys.msg_iovlen > UIO_MAXIOV)
++              goto out_put;
++
++      /* Check whether to allocate the iovec area */
++      err = -ENOMEM;
++      iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
++      if (msg_sys.msg_iovlen > UIO_FASTIOV) {
++              iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
++              if (!iov)
++                      goto out_put;
++      }
++
++      /*
++       *      Save the user-mode address (verify_iovec will change the
++       *      kernel msghdr to use the kernel address space)
++       */
++
++      uaddr = (void __user *)msg_sys.msg_name;
++      uaddr_len = COMPAT_NAMELEN(msg);
++      if (MSG_CMSG_COMPAT & flags) {
++              err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
++      } else
++              err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
++      if (err < 0)
++              goto out_freeiov;
++      total_len = err;
++
++      cmsg_ptr = (unsigned long)msg_sys.msg_control;
++      msg_sys.msg_flags = 0;
++      if (MSG_CMSG_COMPAT & flags)
++              msg_sys.msg_flags = MSG_CMSG_COMPAT;
++
++      if (sock->file->f_flags & O_NONBLOCK)
++              flags |= MSG_DONTWAIT;
++      err = sock_recvmsg(sock, &msg_sys, total_len, flags);
++      if (err < 0)
++              goto out_freeiov;
++      len = err;
++
++      if (uaddr != NULL) {
++              err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr,
++                                      uaddr_len);
++              if (err < 0)
++                      goto out_freeiov;
++      }
++      err = __put_user((msg_sys.msg_flags & ~MSG_CMSG_COMPAT),
++                       COMPAT_FLAGS(msg));
++      if (err)
++              goto out_freeiov;
++      if (MSG_CMSG_COMPAT & flags)
++              err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
++                               &msg_compat->msg_controllen);
++      else
++              err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
++                               &msg->msg_controllen);
++      if (err)
++              goto out_freeiov;
++      err = len;
++
++out_freeiov:
++      if (iov != iovstack)
++              sock_kfree_s(sock->sk, iov, iov_size);
++out_put:
++      fput_light(sock->file, fput_needed);
++out:
++      return err;
++}
++
++#ifdef __ARCH_WANT_SYS_SOCKETCALL
++
++/* Argument list sizes for sys_socketcall */
++#define AL(x) ((x) * sizeof(unsigned long))
++static const unsigned char nargs[18]={
++      AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
++      AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
++      AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)
++};
++
++#undef AL
++
++/*
++ *    System call vectors.
++ *
++ *    Argument checking cleaned up. Saved 20% in size.
++ *  This function doesn't need to set the kernel lock because
++ *  it is set by the callees.
++ */
++
++asmlinkage long sys_socketcall(int call, unsigned long __user *args)
++{
++      unsigned long a[6];
++      unsigned long a0, a1;
++      int err;
++
++      if (call < 1 || call > SYS_RECVMSG)
++              return -EINVAL;
++
++      /* copy_from_user should be SMP safe. */
++      if (copy_from_user(a, args, nargs[call]))
++              return -EFAULT;
++
++      err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
++      if (err)
++              return err;
++
++      a0 = a[0];
++      a1 = a[1];
++
++      switch (call) {
++      case SYS_SOCKET:
++              err = sys_socket(a0, a1, a[2]);
++              break;
++      case SYS_BIND:
++              err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
++              break;
++      case SYS_CONNECT:
++              err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
++              break;
++      case SYS_LISTEN:
++              err = sys_listen(a0, a1);
++              break;
++      case SYS_ACCEPT:
++              err =
++                  sys_accept(a0, (struct sockaddr __user *)a1,
++                             (int __user *)a[2]);
++              break;
++      case SYS_GETSOCKNAME:
++              err =
++                  sys_getsockname(a0, (struct sockaddr __user *)a1,
++                                  (int __user *)a[2]);
++              break;
++      case SYS_GETPEERNAME:
++              err =
++                  sys_getpeername(a0, (struct sockaddr __user *)a1,
++                                  (int __user *)a[2]);
++              break;
++      case SYS_SOCKETPAIR:
++              err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
++              break;
++      case SYS_SEND:
++              err = sys_send(a0, (void __user *)a1, a[2], a[3]);
++              break;
++      case SYS_SENDTO:
++              err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
++                               (struct sockaddr __user *)a[4], a[5]);
++              break;
++      case SYS_RECV:
++              err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
++              break;
++      case SYS_RECVFROM:
++              err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
++                                 (struct sockaddr __user *)a[4],
++                                 (int __user *)a[5]);
++              break;
++      case SYS_SHUTDOWN:
++              err = sys_shutdown(a0, a1);
++              break;
++      case SYS_SETSOCKOPT:
++              err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
++              break;
++      case SYS_GETSOCKOPT:
++              err =
++                  sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
++                                 (int __user *)a[4]);
++              break;
++      case SYS_SENDMSG:
++              err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
++              break;
++      case SYS_RECVMSG:
++              err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
++              break;
++      default:
++              err = -EINVAL;
++              break;
++      }
++      return err;
++}
++
++#endif                                /* __ARCH_WANT_SYS_SOCKETCALL */
++
++/**
++ *    sock_register - add a socket protocol handler
++ *    @ops: description of protocol
++ *
++ *    This function is called by a protocol handler that wants to
++ *    advertise its address family, and have it linked into the
++ *    socket interface. The value ops->family coresponds to the
++ *    socket system call protocol family.
++ */
++int sock_register(const struct net_proto_family *ops)
++{
++      int err;
++
++      if (ops->family >= NPROTO) {
++              printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
++                     NPROTO);
++              return -ENOBUFS;
++      }
++
++      spin_lock(&net_family_lock);
++      if (net_families[ops->family])
++              err = -EEXIST;
++      else {
++              net_families[ops->family] = ops;
++              err = 0;
++      }
++      spin_unlock(&net_family_lock);
++
++      printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
++      return err;
++}
++
++/**
++ *    sock_unregister - remove a protocol handler
++ *    @family: protocol family to remove
++ *
++ *    This function is called by a protocol handler that wants to
++ *    remove its address family, and have it unlinked from the
++ *    new socket creation.
++ *
++ *    If protocol handler is a module, then it can use module reference
++ *    counts to protect against new references. If protocol handler is not
++ *    a module then it needs to provide its own protection in
++ *    the ops->create routine.
++ */
++void sock_unregister(int family)
++{
++      BUG_ON(family < 0 || family >= NPROTO);
++
++      spin_lock(&net_family_lock);
++      net_families[family] = NULL;
++      spin_unlock(&net_family_lock);
++
++      synchronize_rcu();
++
++      printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
++}
++
++static int __init sock_init(void)
++{
++      /*
++       *      Initialize sock SLAB cache.
++       */
++
++      sk_init();
++
++      /*
++       *      Initialize skbuff SLAB cache
++       */
++      skb_init();
++
++      /*
++       *      Initialize the protocols module.
++       */
++
++      init_inodecache();
++      register_filesystem(&sock_fs_type);
++      sock_mnt = kern_mount(&sock_fs_type);
++
++      /* The real protocol initialization is performed in later initcalls.
++       */
++
++#ifdef CONFIG_NETFILTER
++      netfilter_init();
++#endif
++
++      return 0;
++}
++
++core_initcall(sock_init);     /* early initcall */
++
++#ifdef CONFIG_PROC_FS
++void socket_seq_show(struct seq_file *seq)
++{
++      int cpu;
++      int counter = 0;
++
++      for_each_possible_cpu(cpu)
++          counter += per_cpu(sockets_in_use, cpu);
++
++      /* It can be negative, by the way. 8) */
++      if (counter < 0)
++              counter = 0;
++
++      seq_printf(seq, "sockets: used %d\n", counter);
++}
++#endif                                /* CONFIG_PROC_FS */
++
++#ifdef CONFIG_COMPAT
++static long compat_sock_ioctl(struct file *file, unsigned cmd,
++                            unsigned long arg)
++{
++      struct socket *sock = file->private_data;
++      int ret = -ENOIOCTLCMD;
++
++      if (sock->ops->compat_ioctl)
++              ret = sock->ops->compat_ioctl(sock, cmd, arg);
++
++      return ret;
++}
++#endif
++
++int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
++{
++      return sock->ops->bind(sock, addr, addrlen);
++}
++
++int kernel_listen(struct socket *sock, int backlog)
++{
++      return sock->ops->listen(sock, backlog);
++}
++
++int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
++{
++      struct sock *sk = sock->sk;
++      int err;
++
++      err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
++                             newsock);
++      if (err < 0)
++              goto done;
++
++      err = sock->ops->accept(sock, *newsock, flags);
++      if (err < 0) {
++              sock_release(*newsock);
++              goto done;
++      }
++
++      (*newsock)->ops = sock->ops;
++
++done:
++      return err;
++}
++
++int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
++                 int flags)
++{
++      return sock->ops->connect(sock, addr, addrlen, flags);
++}
++
++int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
++                       int *addrlen)
++{
++      return sock->ops->getname(sock, addr, addrlen, 0);
++}
++
++int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
++                       int *addrlen)
++{
++      return sock->ops->getname(sock, addr, addrlen, 1);
++}
++
++int kernel_getsockopt(struct socket *sock, int level, int optname,
++                      char *optval, int *optlen)
++{
++      mm_segment_t oldfs = get_fs();
++      int err;
++
++      set_fs(KERNEL_DS);
++      if (level == SOL_SOCKET)
++              err = sock_getsockopt(sock, level, optname, optval, optlen);
++      else
++              err = sock->ops->getsockopt(sock, level, optname, optval,
++                                          optlen);
++      set_fs(oldfs);
++      return err;
++}
++
++int kernel_setsockopt(struct socket *sock, int level, int optname,
++                      char *optval, int optlen)
++{
++      mm_segment_t oldfs = get_fs();
++      int err;
++
++      set_fs(KERNEL_DS);
++      if (level == SOL_SOCKET)
++              err = sock_setsockopt(sock, level, optname, optval, optlen);
++      else
++              err = sock->ops->setsockopt(sock, level, optname, optval,
++                                          optlen);
++      set_fs(oldfs);
++      return err;
++}
++
++int kernel_sendpage(struct socket *sock, struct page *page, int offset,
++                  size_t size, int flags)
++{
++      if (sock->ops->sendpage)
++              return sock->ops->sendpage(sock, page, offset, size, flags);
++
++      return sock_no_sendpage(sock, page, offset, size, flags);
++}
++
++int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
++{
++      mm_segment_t oldfs = get_fs();
++      int err;
++
++      set_fs(KERNEL_DS);
++      err = sock->ops->ioctl(sock, cmd, arg);
++      set_fs(oldfs);
++
++      return err;
++}
++
++/* ABI emulation layers need these two */
++EXPORT_SYMBOL(move_addr_to_kernel);
++EXPORT_SYMBOL(move_addr_to_user);
++EXPORT_SYMBOL(sock_create);
++EXPORT_SYMBOL(sock_create_kern);
++EXPORT_SYMBOL(sock_create_lite);
++EXPORT_SYMBOL(sock_map_fd);
++EXPORT_SYMBOL(sock_recvmsg);
++EXPORT_SYMBOL(sock_register);
++EXPORT_SYMBOL(sock_release);
++EXPORT_SYMBOL(sock_sendmsg);
++EXPORT_SYMBOL(sock_unregister);
++EXPORT_SYMBOL(sock_wake_async);
++EXPORT_SYMBOL(sockfd_lookup);
++EXPORT_SYMBOL(kernel_sendmsg);
++EXPORT_SYMBOL(kernel_recvmsg);
++EXPORT_SYMBOL(kernel_bind);
++EXPORT_SYMBOL(kernel_listen);
++EXPORT_SYMBOL(kernel_accept);
++EXPORT_SYMBOL(kernel_connect);
++EXPORT_SYMBOL(kernel_getsockname);
++EXPORT_SYMBOL(kernel_getpeername);
++EXPORT_SYMBOL(kernel_getsockopt);
++EXPORT_SYMBOL(kernel_setsockopt);
++EXPORT_SYMBOL(kernel_sendpage);
++EXPORT_SYMBOL(kernel_sock_ioctl);
+diff -Nurb linux-2.6.22-590/net/sunrpc/auth.c linux-2.6.22-570/net/sunrpc/auth.c
+--- linux-2.6.22-590/net/sunrpc/auth.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/auth.c 2008-01-23 19:16:05.000000000 -0500
+@@ -19,16 +19,12 @@
  # define RPCDBG_FACILITY      RPCDBG_AUTH
  #endif
  
--static struct rpc_authops *   auth_flavors[RPC_AUTH_MAXFLAVOR] = {
-+static DEFINE_SPINLOCK(rpc_authflavor_lock);
-+static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
+-static DEFINE_SPINLOCK(rpc_authflavor_lock);
+-static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
++static struct rpc_authops *   auth_flavors[RPC_AUTH_MAXFLAVOR] = {
        &authnull_ops,          /* AUTH_NULL */
        &authunix_ops,          /* AUTH_UNIX */
        NULL,                   /* others can be loadable modules */
  };
  
-+static LIST_HEAD(cred_unused);
-+static unsigned long number_cred_unused;
-+
+-static LIST_HEAD(cred_unused);
+-static unsigned long number_cred_unused;
+-
  static u32
  pseudoflavor_to_flavor(u32 flavor) {
        if (flavor >= RPC_AUTH_MAXFLAVOR)
-@@ -33,55 +37,67 @@
+@@ -37,67 +33,55 @@
  }
  
  int
--rpcauth_register(struct rpc_authops *ops)
-+rpcauth_register(const struct rpc_authops *ops)
+-rpcauth_register(const struct rpc_authops *ops)
++rpcauth_register(struct rpc_authops *ops)
  {
        rpc_authflavor_t flavor;
-+      int ret = -EPERM;
+-      int ret = -EPERM;
  
        if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
                return -EINVAL;
--      if (auth_flavors[flavor] != NULL)
--              return -EPERM;          /* what else? */
-+      spin_lock(&rpc_authflavor_lock);
-+      if (auth_flavors[flavor] == NULL) {
+-      spin_lock(&rpc_authflavor_lock);
+-      if (auth_flavors[flavor] == NULL) {
++      if (auth_flavors[flavor] != NULL)
++              return -EPERM;          /* what else? */
        auth_flavors[flavor] = ops;
--      return 0;
-+              ret = 0;
-+      }
-+      spin_unlock(&rpc_authflavor_lock);
-+      return ret;
+-              ret = 0;
+-      }
+-      spin_unlock(&rpc_authflavor_lock);
+-      return ret;
++      return 0;
  }
  
  int
--rpcauth_unregister(struct rpc_authops *ops)
-+rpcauth_unregister(const struct rpc_authops *ops)
+-rpcauth_unregister(const struct rpc_authops *ops)
++rpcauth_unregister(struct rpc_authops *ops)
  {
        rpc_authflavor_t flavor;
-+      int ret = -EPERM;
+-      int ret = -EPERM;
  
        if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
                return -EINVAL;
--      if (auth_flavors[flavor] != ops)
--              return -EPERM;          /* what else? */
-+      spin_lock(&rpc_authflavor_lock);
-+      if (auth_flavors[flavor] == ops) {
+-      spin_lock(&rpc_authflavor_lock);
+-      if (auth_flavors[flavor] == ops) {
++      if (auth_flavors[flavor] != ops)
++              return -EPERM;          /* what else? */
        auth_flavors[flavor] = NULL;
--      return 0;
-+              ret = 0;
-+      }
-+      spin_unlock(&rpc_authflavor_lock);
-+      return ret;
+-              ret = 0;
+-      }
+-      spin_unlock(&rpc_authflavor_lock);
+-      return ret;
++      return 0;
  }
  
  struct rpc_auth *
  rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
  {
        struct rpc_auth         *auth;
--      struct rpc_authops      *ops;
-+      const struct rpc_authops *ops;
+-      const struct rpc_authops *ops;
++      struct rpc_authops      *ops;
        u32                     flavor = pseudoflavor_to_flavor(pseudoflavor);
  
        auth = ERR_PTR(-EINVAL);
        if (flavor >= RPC_AUTH_MAXFLAVOR)
                goto out;
  
--      /* FIXME - auth_flavors[] really needs an rw lock,
--       * and module refcounting. */
++      /* FIXME - auth_flavors[] really needs an rw lock,
++       * and module refcounting. */
  #ifdef CONFIG_KMOD
        if ((ops = auth_flavors[flavor]) == NULL)
                request_module("rpc-auth-%u", flavor);
  #endif
--      if ((ops = auth_flavors[flavor]) == NULL)
-+      spin_lock(&rpc_authflavor_lock);
-+      ops = auth_flavors[flavor];
-+      if (ops == NULL || !try_module_get(ops->owner)) {
-+              spin_unlock(&rpc_authflavor_lock);
+-      spin_lock(&rpc_authflavor_lock);
+-      ops = auth_flavors[flavor];
+-      if (ops == NULL || !try_module_get(ops->owner)) {
+-              spin_unlock(&rpc_authflavor_lock);
++      if ((ops = auth_flavors[flavor]) == NULL)
                goto out;
-+      }
-+      spin_unlock(&rpc_authflavor_lock);
+-      }
+-      spin_unlock(&rpc_authflavor_lock);
        auth = ops->create(clnt, pseudoflavor);
-+      module_put(ops->owner);
+-      module_put(ops->owner);
        if (IS_ERR(auth))
                return auth;
        if (clnt->cl_auth)
--              rpcauth_destroy(clnt->cl_auth);
-+              rpcauth_release(clnt->cl_auth);
+-              rpcauth_release(clnt->cl_auth);
++              rpcauth_destroy(clnt->cl_auth);
        clnt->cl_auth = auth;
  
  out:
-@@ -89,7 +105,7 @@
+@@ -105,7 +89,7 @@
  }
  
  void
--rpcauth_destroy(struct rpc_auth *auth)
-+rpcauth_release(struct rpc_auth *auth)
+-rpcauth_release(struct rpc_auth *auth)
++rpcauth_destroy(struct rpc_auth *auth)
  {
        if (!atomic_dec_and_test(&auth->au_count))
                return;
-@@ -98,11 +114,31 @@
+@@ -114,31 +98,11 @@
  
  static DEFINE_SPINLOCK(rpc_credcache_lock);
  
-+static void
-+rpcauth_unhash_cred_locked(struct rpc_cred *cred)
-+{
-+      hlist_del_rcu(&cred->cr_hash);
-+      smp_mb__before_clear_bit();
-+      clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
-+}
-+
-+static void
-+rpcauth_unhash_cred(struct rpc_cred *cred)
-+{
-+      spinlock_t *cache_lock;
-+
-+      cache_lock = &cred->cr_auth->au_credcache->lock;
-+      spin_lock(cache_lock);
-+      if (atomic_read(&cred->cr_count) == 0)
-+              rpcauth_unhash_cred_locked(cred);
-+      spin_unlock(cache_lock);
-+}
-+
+-static void
+-rpcauth_unhash_cred_locked(struct rpc_cred *cred)
+-{
+-      hlist_del_rcu(&cred->cr_hash);
+-      smp_mb__before_clear_bit();
+-      clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
+-}
+-
+-static void
+-rpcauth_unhash_cred(struct rpc_cred *cred)
+-{
+-      spinlock_t *cache_lock;
+-
+-      cache_lock = &cred->cr_auth->au_credcache->lock;
+-      spin_lock(cache_lock);
+-      if (atomic_read(&cred->cr_count) == 0)
+-              rpcauth_unhash_cred_locked(cred);
+-      spin_unlock(cache_lock);
+-}
+-
  /*
   * Initialize RPC credential cache
   */
  int
--rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
-+rpcauth_init_credcache(struct rpc_auth *auth)
+-rpcauth_init_credcache(struct rpc_auth *auth)
++rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
  {
        struct rpc_cred_cache *new;
        int i;
-@@ -112,8 +148,7 @@
+@@ -148,7 +112,8 @@
                return -ENOMEM;
        for (i = 0; i < RPC_CREDCACHE_NR; i++)
                INIT_HLIST_HEAD(&new->hashtable[i]);
--      new->expire = expire;
--      new->nextgc = jiffies + (expire >> 1);
-+      spin_lock_init(&new->lock);
+-      spin_lock_init(&new->lock);
++      new->expire = expire;
++      new->nextgc = jiffies + (expire >> 1);
        auth->au_credcache = new;
        return 0;
  }
-@@ -122,13 +157,13 @@
+@@ -157,13 +122,13 @@
   * Destroy a list of credentials
   */
  static inline
--void rpcauth_destroy_credlist(struct hlist_head *head)
-+void rpcauth_destroy_credlist(struct list_head *head)
+-void rpcauth_destroy_credlist(struct list_head *head)
++void rpcauth_destroy_credlist(struct hlist_head *head)
  {
        struct rpc_cred *cred;
  
--      while (!hlist_empty(head)) {
--              cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
--              hlist_del_init(&cred->cr_hash);
-+      while (!list_empty(head)) {
-+              cred = list_entry(head->next, struct rpc_cred, cr_lru);
-+              list_del_init(&cred->cr_lru);
+-      while (!list_empty(head)) {
+-              cred = list_entry(head->next, struct rpc_cred, cr_lru);
+-              list_del_init(&cred->cr_lru);
++      while (!hlist_empty(head)) {
++              cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
++              hlist_del_init(&cred->cr_hash);
                put_rpccred(cred);
        }
  }
-@@ -138,58 +173,95 @@
+@@ -173,95 +138,58 @@
   * that are not referenced.
   */
  void
--rpcauth_free_credcache(struct rpc_auth *auth)
-+rpcauth_clear_credcache(struct rpc_cred_cache *cache)
+-rpcauth_clear_credcache(struct rpc_cred_cache *cache)
++rpcauth_free_credcache(struct rpc_auth *auth)
  {
--      struct rpc_cred_cache *cache = auth->au_credcache;
--      HLIST_HEAD(free);
--      struct hlist_node *pos, *next;
-+      LIST_HEAD(free);
-+      struct hlist_head *head;
+-      LIST_HEAD(free);
+-      struct hlist_head *head;
++      struct rpc_cred_cache *cache = auth->au_credcache;
++      HLIST_HEAD(free);
++      struct hlist_node *pos, *next;
        struct rpc_cred *cred;
        int             i;
  
        spin_lock(&rpc_credcache_lock);
-+      spin_lock(&cache->lock);
+-      spin_lock(&cache->lock);
        for (i = 0; i < RPC_CREDCACHE_NR; i++) {
--              hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
--                      cred = hlist_entry(pos, struct rpc_cred, cr_hash);
--                      __hlist_del(&cred->cr_hash);
--                      hlist_add_head(&cred->cr_hash, &free);
-+              head = &cache->hashtable[i];
-+              while (!hlist_empty(head)) {
-+                      cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
-+                      get_rpccred(cred);
-+                      if (!list_empty(&cred->cr_lru)) {
-+                              list_del(&cred->cr_lru);
-+                              number_cred_unused--;
+-              head = &cache->hashtable[i];
+-              while (!hlist_empty(head)) {
+-                      cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
+-                      get_rpccred(cred);
+-                      if (!list_empty(&cred->cr_lru)) {
+-                              list_del(&cred->cr_lru);
+-                              number_cred_unused--;
++              hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
++                      cred = hlist_entry(pos, struct rpc_cred, cr_hash);
++                      __hlist_del(&cred->cr_hash);
++                      hlist_add_head(&cred->cr_hash, &free);
                }
-+                      list_add_tail(&cred->cr_lru, &free);
-+                      rpcauth_unhash_cred_locked(cred);
+-                      list_add_tail(&cred->cr_lru, &free);
+-                      rpcauth_unhash_cred_locked(cred);
        }
-+      }
-+      spin_unlock(&cache->lock);
+-      }
+-      spin_unlock(&cache->lock);
        spin_unlock(&rpc_credcache_lock);
        rpcauth_destroy_credlist(&free);
  }
  
--static void
--rpcauth_prune_expired(struct rpc_auth *auth, struct rpc_cred *cred, struct hlist_head *free)
-+/*
-+ * Destroy the RPC credential cache
-+ */
-+void
-+rpcauth_destroy_credcache(struct rpc_auth *auth)
- {
--      if (atomic_read(&cred->cr_count) != 1)
--             return;
--      if (time_after(jiffies, cred->cr_expire + auth->au_credcache->expire))
--              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
--      if (!(cred->cr_flags & RPCAUTH_CRED_UPTODATE)) {
--              __hlist_del(&cred->cr_hash);
--              hlist_add_head(&cred->cr_hash, free);
-+      struct rpc_cred_cache *cache = auth->au_credcache;
-+
-+      if (cache) {
-+              auth->au_credcache = NULL;
-+              rpcauth_clear_credcache(cache);
-+              kfree(cache);
+-/*
+- * Destroy the RPC credential cache
+- */
+-void
+-rpcauth_destroy_credcache(struct rpc_auth *auth)
++static void
++rpcauth_prune_expired(struct rpc_auth *auth, struct rpc_cred *cred, struct hlist_head *free)
+ {
+-      struct rpc_cred_cache *cache = auth->au_credcache;
+-
+-      if (cache) {
+-              auth->au_credcache = NULL;
+-              rpcauth_clear_credcache(cache);
+-              kfree(cache);
++      if (atomic_read(&cred->cr_count) != 1)
++             return;
++      if (time_after(jiffies, cred->cr_expire + auth->au_credcache->expire))
++              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
++      if (!(cred->cr_flags & RPCAUTH_CRED_UPTODATE)) {
++              __hlist_del(&cred->cr_hash);
++              hlist_add_head(&cred->cr_hash, free);
        }
  }
  
  /*
   * Remove stale credentials. Avoid sleeping inside the loop.
   */
--static void
--rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free)
-+static int
-+rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
+-static int
+-rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
++static void
++rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free)
  {
--      struct rpc_cred_cache *cache = auth->au_credcache;
--      struct hlist_node *pos, *next;
-+      spinlock_t *cache_lock;
+-      spinlock_t *cache_lock;
++      struct rpc_cred_cache *cache = auth->au_credcache;
++      struct hlist_node *pos, *next;
        struct rpc_cred *cred;
--      int             i;
++      int             i;
  
--      dprintk("RPC:       gc'ing RPC credentials for auth %p\n", auth);
--      for (i = 0; i < RPC_CREDCACHE_NR; i++) {
--              hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
--                      cred = hlist_entry(pos, struct rpc_cred, cr_hash);
--                      rpcauth_prune_expired(auth, cred, free);
-+      while(!list_empty(&cred_unused)) {
-+              cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru);
-+              list_del_init(&cred->cr_lru);
-+              number_cred_unused--;
-+              if (atomic_read(&cred->cr_count) != 0)
-+                      continue;
-+              cache_lock = &cred->cr_auth->au_credcache->lock;
-+              spin_lock(cache_lock);
-+              if (atomic_read(&cred->cr_count) == 0) {
-+                      get_rpccred(cred);
-+                      list_add_tail(&cred->cr_lru, free);
-+                      rpcauth_unhash_cred_locked(cred);
-+                      nr_to_scan --;
+-      while(!list_empty(&cred_unused)) {
+-              cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru);
+-              list_del_init(&cred->cr_lru);
+-              number_cred_unused--;
+-              if (atomic_read(&cred->cr_count) != 0)
+-                      continue;
+-              cache_lock = &cred->cr_auth->au_credcache->lock;
+-              spin_lock(cache_lock);
+-              if (atomic_read(&cred->cr_count) == 0) {
+-                      get_rpccred(cred);
+-                      list_add_tail(&cred->cr_lru, free);
+-                      rpcauth_unhash_cred_locked(cred);
+-                      nr_to_scan --;
++      dprintk("RPC:       gc'ing RPC credentials for auth %p\n", auth);
++      for (i = 0; i < RPC_CREDCACHE_NR; i++) {
++              hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
++                      cred = hlist_entry(pos, struct rpc_cred, cr_hash);
++                      rpcauth_prune_expired(auth, cred, free);
                }
-+              spin_unlock(cache_lock);
-+              if (nr_to_scan == 0)
-+                      break;
+-              spin_unlock(cache_lock);
+-              if (nr_to_scan == 0)
+-                      break;
        }
--      cache->nextgc = jiffies + cache->expire;
-+      return nr_to_scan;
-+}
-+
-+/*
-+ * Run memory cache shrinker.
-+ */
-+static int
-+rpcauth_cache_shrinker(int nr_to_scan, gfp_t gfp_mask)
-+{
-+      LIST_HEAD(free);
-+      int res;
-+
-+      if (list_empty(&cred_unused))
-+              return 0;
-+      spin_lock(&rpc_credcache_lock);
-+      nr_to_scan = rpcauth_prune_expired(&free, nr_to_scan);
-+      res = (number_cred_unused / 100) * sysctl_vfs_cache_pressure;
-+      spin_unlock(&rpc_credcache_lock);
-+      rpcauth_destroy_credlist(&free);
-+      return res;
+-      return nr_to_scan;
+-}
+-
+-/*
+- * Run memory cache shrinker.
+- */
+-static int
+-rpcauth_cache_shrinker(int nr_to_scan, gfp_t gfp_mask)
+-{
+-      LIST_HEAD(free);
+-      int res;
+-
+-      if (list_empty(&cred_unused))
+-              return 0;
+-      spin_lock(&rpc_credcache_lock);
+-      nr_to_scan = rpcauth_prune_expired(&free, nr_to_scan);
+-      res = (number_cred_unused / 100) * sysctl_vfs_cache_pressure;
+-      spin_unlock(&rpc_credcache_lock);
+-      rpcauth_destroy_credlist(&free);
+-      return res;
++      cache->nextgc = jiffies + cache->expire;
  }
  
  /*
-@@ -199,53 +271,56 @@
+@@ -271,56 +199,53 @@
  rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
                int flags)
  {
-+      LIST_HEAD(free);
+-      LIST_HEAD(free);
        struct rpc_cred_cache *cache = auth->au_credcache;
--      HLIST_HEAD(free);
--      struct hlist_node *pos, *next;
--      struct rpc_cred *new = NULL,
--                      *cred = NULL;
-+      struct hlist_node *pos;
-+      struct rpc_cred *cred = NULL,
-+                      *entry, *new;
+-      struct hlist_node *pos;
+-      struct rpc_cred *cred = NULL,
+-                      *entry, *new;
++      HLIST_HEAD(free);
++      struct hlist_node *pos, *next;
++      struct rpc_cred *new = NULL,
++                      *cred = NULL;
        int             nr = 0;
  
        if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS))
                nr = acred->uid & RPC_CREDCACHE_MASK;
--retry:
--      spin_lock(&rpc_credcache_lock);
--      if (time_before(cache->nextgc, jiffies))
--              rpcauth_gc_credcache(auth, &free);
--      hlist_for_each_safe(pos, next, &cache->hashtable[nr]) {
--              struct rpc_cred *entry;
--              entry = hlist_entry(pos, struct rpc_cred, cr_hash);
--              if (entry->cr_ops->crmatch(acred, entry, flags)) {
--                      hlist_del(&entry->cr_hash);
--                      cred = entry;
--                      break;
--              }
--              rpcauth_prune_expired(auth, entry, &free);
+-
+-      rcu_read_lock();
+-      hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
+-              if (!entry->cr_ops->crmatch(acred, entry, flags))
+-                      continue;
+-              spin_lock(&cache->lock);
+-              if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) {
+-                      spin_unlock(&cache->lock);
+-                      continue;
 -      }
--      if (new) {
--              if (cred)
--                      hlist_add_head(&new->cr_hash, &free);
--              else
--                      cred = new;
-+
-+      rcu_read_lock();
-+      hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
-+              if (!entry->cr_ops->crmatch(acred, entry, flags))
-+                      continue;
-+              spin_lock(&cache->lock);
-+              if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) {
-+                      spin_unlock(&cache->lock);
-+                      continue;
-       }
--      if (cred) {
--              hlist_add_head(&cred->cr_hash, &cache->hashtable[nr]);
--              get_rpccred(cred);
-+              cred = get_rpccred(entry);
-+              spin_unlock(&cache->lock);
-+              break;
+-              cred = get_rpccred(entry);
+-              spin_unlock(&cache->lock);
++retry:
++      spin_lock(&rpc_credcache_lock);
++      if (time_before(cache->nextgc, jiffies))
++              rpcauth_gc_credcache(auth, &free);
++      hlist_for_each_safe(pos, next, &cache->hashtable[nr]) {
++              struct rpc_cred *entry;
++              entry = hlist_entry(pos, struct rpc_cred, cr_hash);
++              if (entry->cr_ops->crmatch(acred, entry, flags)) {
++                      hlist_del(&entry->cr_hash);
++                      cred = entry;
+               break;
        }
--      spin_unlock(&rpc_credcache_lock);
-+      rcu_read_unlock();
--      rpcauth_destroy_credlist(&free);
-+      if (cred != NULL)
-+              goto found;
--      if (!cred) {
-               new = auth->au_ops->crcreate(auth, acred, flags);
--              if (!IS_ERR(new)) {
--#ifdef RPC_DEBUG
--                      new->cr_magic = RPCAUTH_CRED_MAGIC;
--#endif
--                      goto retry;
--              } else
-+      if (IS_ERR(new)) {
-+              cred = new;
-+              goto out;
+-      rcu_read_unlock();
+-
+-      if (cred != NULL)
+-              goto found;
+-
+-              new = auth->au_ops->crcreate(auth, acred, flags);
+-      if (IS_ERR(new)) {
++              rpcauth_prune_expired(auth, entry, &free);
 +      }
++      if (new) {
++              if (cred)
++                      hlist_add_head(&new->cr_hash, &free);
++              else
+               cred = new;
+-              goto out;
+       }
+-
+-      spin_lock(&cache->lock);
+-      hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) {
+-              if (!entry->cr_ops->crmatch(acred, entry, flags))
+-                      continue;
+-              cred = get_rpccred(entry);
+-              break;
++      if (cred) {
++              hlist_add_head(&cred->cr_hash, &cache->hashtable[nr]);
++              get_rpccred(cred);
+       }
+-      if (cred == NULL) {
+-                      cred = new;
+-              set_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
+-              hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]);
++      spin_unlock(&rpc_credcache_lock);
 +
-+      spin_lock(&cache->lock);
-+      hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) {
-+              if (!entry->cr_ops->crmatch(acred, entry, flags))
-+                      continue;
-+              cred = get_rpccred(entry);
-+              break;
-+      }
-+      if (cred == NULL) {
-                       cred = new;
--      } else if ((cred->cr_flags & RPCAUTH_CRED_NEW)
-+              set_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
-+              hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]);
-+      } else
-+              list_add_tail(&new->cr_lru, &free);
-+      spin_unlock(&cache->lock);
-+found:
-+      if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)
++      rpcauth_destroy_credlist(&free);
++
++      if (!cred) {
++              new = auth->au_ops->crcreate(auth, acred, flags);
++              if (!IS_ERR(new)) {
++#ifdef RPC_DEBUG
++                      new->cr_magic = RPCAUTH_CRED_MAGIC;
++#endif
++                      goto retry;
+       } else
+-              list_add_tail(&new->cr_lru, &free);
+-      spin_unlock(&cache->lock);
+-found:
+-      if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)
++                      cred = new;
++      } else if ((cred->cr_flags & RPCAUTH_CRED_NEW)
                        && cred->cr_ops->cr_init != NULL
                        && !(flags & RPCAUTH_LOOKUP_NEW)) {
                int res = cred->cr_ops->cr_init(auth, cred);
-@@ -254,8 +329,9 @@
+@@ -329,9 +254,8 @@
                        cred = ERR_PTR(res);
                }
        }
--
--      return (struct rpc_cred *) cred;
-+      rpcauth_destroy_credlist(&free);
-+out:
-+      return cred;
+-      rpcauth_destroy_credlist(&free);
+-out:
+-      return cred;
++
++      return (struct rpc_cred *) cred;
  }
  
  struct rpc_cred *
-@@ -277,6 +353,23 @@
+@@ -353,23 +277,6 @@
        return ret;
  }
  
-+void
-+rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
-+                struct rpc_auth *auth, const struct rpc_credops *ops)
-+{
-+      INIT_HLIST_NODE(&cred->cr_hash);
-+      INIT_LIST_HEAD(&cred->cr_lru);
-+      atomic_set(&cred->cr_count, 1);
-+      cred->cr_auth = auth;
-+      cred->cr_ops = ops;
-+      cred->cr_expire = jiffies;
-+#ifdef RPC_DEBUG
-+      cred->cr_magic = RPCAUTH_CRED_MAGIC;
-+#endif
-+      cred->cr_uid = acred->uid;
-+}
-+EXPORT_SYMBOL(rpcauth_init_cred);
-+
+-void
+-rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
+-                struct rpc_auth *auth, const struct rpc_credops *ops)
+-{
+-      INIT_HLIST_NODE(&cred->cr_hash);
+-      INIT_LIST_HEAD(&cred->cr_lru);
+-      atomic_set(&cred->cr_count, 1);
+-      cred->cr_auth = auth;
+-      cred->cr_ops = ops;
+-      cred->cr_expire = jiffies;
+-#ifdef RPC_DEBUG
+-      cred->cr_magic = RPCAUTH_CRED_MAGIC;
+-#endif
+-      cred->cr_uid = acred->uid;
+-}
+-EXPORT_SYMBOL(rpcauth_init_cred);
+-
  struct rpc_cred *
  rpcauth_bindcred(struct rpc_task *task)
  {
-@@ -317,9 +410,31 @@
+@@ -410,31 +317,9 @@
  void
  put_rpccred(struct rpc_cred *cred)
  {
--      cred->cr_expire = jiffies;
-+      /* Fast path for unhashed credentials */
-+      if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
-+              goto need_lock;
-+
-       if (!atomic_dec_and_test(&cred->cr_count))
+-      /* Fast path for unhashed credentials */
+-      if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
+-              goto need_lock;
+-
+-      if (!atomic_dec_and_test(&cred->cr_count))
+-              return;
+-      goto out_destroy;
+-need_lock:
+-      if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
+-              return;
+-      if (!list_empty(&cred->cr_lru)) {
+-              number_cred_unused--;
+-              list_del_init(&cred->cr_lru);
+-      }
+-      if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
+-              rpcauth_unhash_cred(cred);
+-      else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
+               cred->cr_expire = jiffies;
+-              list_add_tail(&cred->cr_lru, &cred_unused);
+-              number_cred_unused++;
+-              spin_unlock(&rpc_credcache_lock);
++      if (!atomic_dec_and_test(&cred->cr_count))
                return;
-+      goto out_destroy;
-+need_lock:
-+      if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
-+              return;
-+      if (!list_empty(&cred->cr_lru)) {
-+              number_cred_unused--;
-+              list_del_init(&cred->cr_lru);
-+      }
-+      if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
-+              rpcauth_unhash_cred(cred);
-+      else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
-+              cred->cr_expire = jiffies;
-+              list_add_tail(&cred->cr_lru, &cred_unused);
-+              number_cred_unused++;
-+              spin_unlock(&rpc_credcache_lock);
-+              return;
-+      }
-+      spin_unlock(&rpc_credcache_lock);
-+out_destroy:
+-      }
+-      spin_unlock(&rpc_credcache_lock);
+-out_destroy:
        cred->cr_ops->crdestroy(cred);
  }
  
-@@ -404,17 +519,34 @@
+@@ -519,34 +404,17 @@
  void
  rpcauth_invalcred(struct rpc_task *task)
  {
-+      struct rpc_cred *cred = task->tk_msg.rpc_cred;
-+
+-      struct rpc_cred *cred = task->tk_msg.rpc_cred;
+-
        dprintk("RPC: %5u invalidating %s cred %p\n",
--              task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred);
--      spin_lock(&rpc_credcache_lock);
--      if (task->tk_msg.rpc_cred)
--              task->tk_msg.rpc_cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
--      spin_unlock(&rpc_credcache_lock);
-+              task->tk_pid, task->tk_auth->au_ops->au_name, cred);
-+      if (cred)
-+              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+-              task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+-      if (cred)
+-              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
++              task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred);
++      spin_lock(&rpc_credcache_lock);
++      if (task->tk_msg.rpc_cred)
++              task->tk_msg.rpc_cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
++      spin_unlock(&rpc_credcache_lock);
  }
  
  int
  rpcauth_uptodatecred(struct rpc_task *task)
  {
--      return !(task->tk_msg.rpc_cred) ||
--              (task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_UPTODATE);
-+      struct rpc_cred *cred = task->tk_msg.rpc_cred;
-+
-+      return cred == NULL ||
-+              test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
-+}
-+
-+
-+static struct shrinker *rpc_cred_shrinker;
-+
-+void __init rpcauth_init_module(void)
-+{
-+      rpc_init_authunix();
-+      rpc_cred_shrinker = set_shrinker(DEFAULT_SEEKS, rpcauth_cache_shrinker);
-+}
-+
-+void __exit rpcauth_remove_module(void)
-+{
-+      if (rpc_cred_shrinker != NULL)
-+              remove_shrinker(rpc_cred_shrinker);
+-      struct rpc_cred *cred = task->tk_msg.rpc_cred;
+-
+-      return cred == NULL ||
+-              test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
+-}
+-
+-
+-static struct shrinker *rpc_cred_shrinker;
+-
+-void __init rpcauth_init_module(void)
+-{
+-      rpc_init_authunix();
+-      rpc_cred_shrinker = set_shrinker(DEFAULT_SEEKS, rpcauth_cache_shrinker);
+-}
+-
+-void __exit rpcauth_remove_module(void)
+-{
+-      if (rpc_cred_shrinker != NULL)
+-              remove_shrinker(rpc_cred_shrinker);
++      return !(task->tk_msg.rpc_cred) ||
++              (task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_UPTODATE);
  }
-diff -Nurb linux-2.6.22-570/net/sunrpc/auth_gss/auth_gss.c linux-2.6.22-590/net/sunrpc/auth_gss/auth_gss.c
---- linux-2.6.22-570/net/sunrpc/auth_gss/auth_gss.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sunrpc/auth_gss/auth_gss.c    2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/net/sunrpc/auth_gss/auth_gss.c linux-2.6.22-570/net/sunrpc/auth_gss/auth_gss.c
+--- linux-2.6.22-590/net/sunrpc/auth_gss/auth_gss.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/auth_gss/auth_gss.c    2007-07-08 19:32:17.000000000 -0400
 @@ -54,9 +54,9 @@
  #include <linux/sunrpc/gss_api.h>
  #include <asm/uaccess.h>
  
--static struct rpc_authops authgss_ops;
-+static const struct rpc_authops authgss_ops;
+-static const struct rpc_authops authgss_ops;
++static struct rpc_authops authgss_ops;
  
--static struct rpc_credops gss_credops;
-+static const struct rpc_credops gss_credops;
+-static const struct rpc_credops gss_credops;
++static struct rpc_credops gss_credops;
  
  #ifdef RPC_DEBUG
  # define RPCDBG_FACILITY      RPCDBG_AUTH
-@@ -64,7 +64,6 @@
+@@ -64,6 +64,7 @@
  
  #define NFS_NGROUPS   16
  
--#define GSS_CRED_EXPIRE               (60 * HZ)       /* XXX: reasonable? */
++#define GSS_CRED_EXPIRE               (60 * HZ)       /* XXX: reasonable? */
  #define GSS_CRED_SLACK                1024            /* XXX: unused */
  /* length of a krb5 verifier (48), plus data added before arguments when
   * using integrity (two 4-byte integers): */
-@@ -85,10 +84,8 @@
+@@ -84,8 +85,10 @@
        struct rpc_auth rpc_auth;
        struct gss_api_mech *mech;
        enum rpc_gss_svc service;
--      struct list_head upcalls;
++      struct list_head upcalls;
        struct rpc_clnt *client;
        struct dentry *dentry;
--      spinlock_t lock;
++      spinlock_t lock;
  };
  
  static void gss_destroy_ctx(struct gss_cl_ctx *);
-@@ -116,8 +113,8 @@
+@@ -113,8 +116,8 @@
        write_lock(&gss_ctx_lock);
        old = gss_cred->gc_ctx;
        gss_cred->gc_ctx = ctx;
--      cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
--      cred->cr_flags &= ~RPCAUTH_CRED_NEW;
-+      set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
-+      clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
+-      set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+-      clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
++      cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
++      cred->cr_flags &= ~RPCAUTH_CRED_NEW;
        write_unlock(&gss_ctx_lock);
        if (old)
                gss_put_ctx(old);
-@@ -130,7 +127,7 @@
+@@ -127,7 +130,7 @@
        int res = 0;
  
        read_lock(&gss_ctx_lock);
--      if ((cred->cr_flags & RPCAUTH_CRED_UPTODATE) && gss_cred->gc_ctx)
-+      if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) && gss_cred->gc_ctx)
+-      if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) && gss_cred->gc_ctx)
++      if ((cred->cr_flags & RPCAUTH_CRED_UPTODATE) && gss_cred->gc_ctx)
                res = 1;
        read_unlock(&gss_ctx_lock);
        return res;
-@@ -269,10 +266,10 @@
+@@ -266,10 +269,10 @@
  }
  
  static struct gss_upcall_msg *
--__gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
-+__gss_find_upcall(struct rpc_inode *rpci, uid_t uid)
+-__gss_find_upcall(struct rpc_inode *rpci, uid_t uid)
++__gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
  {
        struct gss_upcall_msg *pos;
--      list_for_each_entry(pos, &gss_auth->upcalls, list) {
-+      list_for_each_entry(pos, &rpci->in_downcall, list) {
+-      list_for_each_entry(pos, &rpci->in_downcall, list) {
++      list_for_each_entry(pos, &gss_auth->upcalls, list) {
                if (pos->uid != uid)
                        continue;
                atomic_inc(&pos->count);
-@@ -290,24 +287,24 @@
+@@ -287,24 +290,24 @@
  static inline struct gss_upcall_msg *
  gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
  {
-+      struct inode *inode = gss_auth->dentry->d_inode;
-+      struct rpc_inode *rpci = RPC_I(inode);
+-      struct inode *inode = gss_auth->dentry->d_inode;
+-      struct rpc_inode *rpci = RPC_I(inode);
        struct gss_upcall_msg *old;
  
--      spin_lock(&gss_auth->lock);
--      old = __gss_find_upcall(gss_auth, gss_msg->uid);
-+      spin_lock(&inode->i_lock);
-+      old = __gss_find_upcall(rpci, gss_msg->uid);
+-      spin_lock(&inode->i_lock);
+-      old = __gss_find_upcall(rpci, gss_msg->uid);
++      spin_lock(&gss_auth->lock);
++      old = __gss_find_upcall(gss_auth, gss_msg->uid);
        if (old == NULL) {
                atomic_inc(&gss_msg->count);
--              list_add(&gss_msg->list, &gss_auth->upcalls);
-+              list_add(&gss_msg->list, &rpci->in_downcall);
+-              list_add(&gss_msg->list, &rpci->in_downcall);
++              list_add(&gss_msg->list, &gss_auth->upcalls);
        } else
                gss_msg = old;
--      spin_unlock(&gss_auth->lock);
-+      spin_unlock(&inode->i_lock);
+-      spin_unlock(&inode->i_lock);
++      spin_unlock(&gss_auth->lock);
        return gss_msg;
  }
  
  static void
  __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
  {
--      if (list_empty(&gss_msg->list))
--              return;
++      if (list_empty(&gss_msg->list))
++              return;
        list_del_init(&gss_msg->list);
        rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
        wake_up_all(&gss_msg->waitqueue);
-@@ -318,10 +315,14 @@
+@@ -315,14 +318,10 @@
  gss_unhash_msg(struct gss_upcall_msg *gss_msg)
  {
        struct gss_auth *gss_auth = gss_msg->auth;
-+      struct inode *inode = gss_auth->dentry->d_inode;
+-      struct inode *inode = gss_auth->dentry->d_inode;
  
--      spin_lock(&gss_auth->lock);
-+      if (list_empty(&gss_msg->list))
-+              return;
-+      spin_lock(&inode->i_lock);
-+      if (!list_empty(&gss_msg->list))
+-      if (list_empty(&gss_msg->list))
+-              return;
+-      spin_lock(&inode->i_lock);
+-      if (!list_empty(&gss_msg->list))
++      spin_lock(&gss_auth->lock);
        __gss_unhash_msg(gss_msg);
--      spin_unlock(&gss_auth->lock);
-+      spin_unlock(&inode->i_lock);
+-      spin_unlock(&inode->i_lock);
++      spin_unlock(&gss_auth->lock);
  }
  
  static void
-@@ -330,16 +331,16 @@
+@@ -331,16 +330,16 @@
        struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred,
                        struct gss_cred, gc_base);
        struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall;
-+      struct inode *inode = gss_msg->auth->dentry->d_inode;
+-      struct inode *inode = gss_msg->auth->dentry->d_inode;
  
--      BUG_ON(gss_msg == NULL);
++      BUG_ON(gss_msg == NULL);
        if (gss_msg->ctx)
                gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx));
        else
                task->tk_status = gss_msg->msg.errno;
--      spin_lock(&gss_msg->auth->lock);
-+      spin_lock(&inode->i_lock);
+-      spin_lock(&inode->i_lock);
++      spin_lock(&gss_msg->auth->lock);
        gss_cred->gc_upcall = NULL;
        rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
--      spin_unlock(&gss_msg->auth->lock);
-+      spin_unlock(&inode->i_lock);
+-      spin_unlock(&inode->i_lock);
++      spin_unlock(&gss_msg->auth->lock);
        gss_release_msg(gss_msg);
  }
  
-@@ -386,11 +387,12 @@
+@@ -387,12 +386,11 @@
  gss_refresh_upcall(struct rpc_task *task)
  {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
--      struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth,
-+      struct gss_auth *gss_auth = container_of(cred->cr_auth,
+-      struct gss_auth *gss_auth = container_of(cred->cr_auth,
++      struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth,
                        struct gss_auth, rpc_auth);
        struct gss_cred *gss_cred = container_of(cred,
                        struct gss_cred, gc_base);
        struct gss_upcall_msg *gss_msg;
-+      struct inode *inode = gss_auth->dentry->d_inode;
+-      struct inode *inode = gss_auth->dentry->d_inode;
        int err = 0;
  
        dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
-@@ -400,7 +402,7 @@
+@@ -402,7 +400,7 @@
                err = PTR_ERR(gss_msg);
                goto out;
        }
--      spin_lock(&gss_auth->lock);
-+      spin_lock(&inode->i_lock);
+-      spin_lock(&inode->i_lock);
++      spin_lock(&gss_auth->lock);
        if (gss_cred->gc_upcall != NULL)
                rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
        else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
-@@ -411,7 +413,7 @@
+@@ -413,7 +411,7 @@
                rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
        } else
                err = gss_msg->msg.errno;
--      spin_unlock(&gss_auth->lock);
-+      spin_unlock(&inode->i_lock);
+-      spin_unlock(&inode->i_lock);
++      spin_unlock(&gss_auth->lock);
        gss_release_msg(gss_msg);
  out:
        dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n",
-@@ -422,6 +424,7 @@
+@@ -424,7 +422,6 @@
  static inline int
  gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
  {
-+      struct inode *inode = gss_auth->dentry->d_inode;
+-      struct inode *inode = gss_auth->dentry->d_inode;
        struct rpc_cred *cred = &gss_cred->gc_base;
        struct gss_upcall_msg *gss_msg;
        DEFINE_WAIT(wait);
-@@ -435,12 +438,12 @@
+@@ -438,12 +435,12 @@
        }
        for (;;) {
                prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);
--              spin_lock(&gss_auth->lock);
-+              spin_lock(&inode->i_lock);
+-              spin_lock(&inode->i_lock);
++              spin_lock(&gss_auth->lock);
                if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) {
--                      spin_unlock(&gss_auth->lock);
-+                      spin_unlock(&inode->i_lock);
+-                      spin_unlock(&inode->i_lock);
++                      spin_unlock(&gss_auth->lock);
                        break;
                }
--              spin_unlock(&gss_auth->lock);
-+              spin_unlock(&inode->i_lock);
+-              spin_unlock(&inode->i_lock);
++              spin_unlock(&gss_auth->lock);
                if (signalled()) {
                        err = -ERESTARTSYS;
                        goto out_intr;
-@@ -489,12 +492,11 @@
+@@ -492,11 +489,12 @@
        const void *p, *end;
        void *buf;
        struct rpc_clnt *clnt;
--      struct gss_auth *gss_auth;
--      struct rpc_cred *cred;
++      struct gss_auth *gss_auth;
++      struct rpc_cred *cred;
        struct gss_upcall_msg *gss_msg;
-+      struct inode *inode = filp->f_path.dentry->d_inode;
+-      struct inode *inode = filp->f_path.dentry->d_inode;
        struct gss_cl_ctx *ctx;
        uid_t uid;
--      int err = -EFBIG;
-+      ssize_t err = -EFBIG;
+-      ssize_t err = -EFBIG;
++      int err = -EFBIG;
  
        if (mlen > MSG_BUF_MAXSIZE)
                goto out;
-@@ -503,7 +505,7 @@
+@@ -505,7 +503,7 @@
        if (!buf)
                goto out;
  
--      clnt = RPC_I(filp->f_path.dentry->d_inode)->private;
-+      clnt = RPC_I(inode)->private;
+-      clnt = RPC_I(inode)->private;
++      clnt = RPC_I(filp->f_path.dentry->d_inode)->private;
        err = -EFAULT;
        if (copy_from_user(buf, src, mlen))
                goto err;
-@@ -519,43 +521,38 @@
+@@ -521,38 +519,43 @@
        ctx = gss_alloc_context();
        if (ctx == NULL)
                goto err;
--      err = 0;
--      gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth);
--      p = gss_fill_context(p, end, ctx, gss_auth->mech);
-+
-+      err = -ENOENT;
-+      /* Find a matching upcall */
-+      spin_lock(&inode->i_lock);
-+      gss_msg = __gss_find_upcall(RPC_I(inode), uid);
-+      if (gss_msg == NULL) {
-+              spin_unlock(&inode->i_lock);
-+              goto err_put_ctx;
-+      }
-+      list_del_init(&gss_msg->list);
-+      spin_unlock(&inode->i_lock);
-+
-+      p = gss_fill_context(p, end, ctx, gss_msg->auth->mech);
+-
+-      err = -ENOENT;
+-      /* Find a matching upcall */
+-      spin_lock(&inode->i_lock);
+-      gss_msg = __gss_find_upcall(RPC_I(inode), uid);
+-      if (gss_msg == NULL) {
+-              spin_unlock(&inode->i_lock);
+-              goto err_put_ctx;
+-      }
+-      list_del_init(&gss_msg->list);
+-      spin_unlock(&inode->i_lock);
+-
+-      p = gss_fill_context(p, end, ctx, gss_msg->auth->mech);
++      err = 0;
++      gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth);
++      p = gss_fill_context(p, end, ctx, gss_auth->mech);
        if (IS_ERR(p)) {
                err = PTR_ERR(p);
--              if (err != -EACCES)
--                      goto err_put_ctx;
-+              gss_msg->msg.errno = (err == -EACCES) ? -EACCES : -EAGAIN;
-+              goto err_release_msg;
-       }
--      spin_lock(&gss_auth->lock);
--      gss_msg = __gss_find_upcall(gss_auth, uid);
--      if (gss_msg) {
--              if (err == 0 && gss_msg->ctx == NULL)
+-              gss_msg->msg.errno = (err == -EACCES) ? -EACCES : -EAGAIN;
+-              goto err_release_msg;
++              if (err != -EACCES)
++                      goto err_put_ctx;
+       }
++      spin_lock(&gss_auth->lock);
++      gss_msg = __gss_find_upcall(gss_auth, uid);
++      if (gss_msg) {
++              if (err == 0 && gss_msg->ctx == NULL)
                        gss_msg->ctx = gss_get_ctx(ctx);
--              gss_msg->msg.errno = err;
-+      err = mlen;
-+
-+err_release_msg:
-+      spin_lock(&inode->i_lock);
+-      err = mlen;
+-
+-err_release_msg:
+-      spin_lock(&inode->i_lock);
++              gss_msg->msg.errno = err;
                __gss_unhash_msg(gss_msg);
--              spin_unlock(&gss_auth->lock);
-+      spin_unlock(&inode->i_lock);
+-      spin_unlock(&inode->i_lock);
++              spin_unlock(&gss_auth->lock);
                gss_release_msg(gss_msg);
--      } else {
--              struct auth_cred acred = { .uid = uid };
--              spin_unlock(&gss_auth->lock);
--              cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW);
--              if (IS_ERR(cred)) {
--                      err = PTR_ERR(cred);
--                      goto err_put_ctx;
--              }
--              gss_cred_set_ctx(cred, gss_get_ctx(ctx));
--      }
--      gss_put_ctx(ctx);
--      kfree(buf);
--      dprintk("RPC:       gss_pipe_downcall returning length %Zu\n", mlen);
--      return mlen;
++      } else {
++              struct auth_cred acred = { .uid = uid };
++              spin_unlock(&gss_auth->lock);
++              cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW);
++              if (IS_ERR(cred)) {
++                      err = PTR_ERR(cred);
++                      goto err_put_ctx;
++              }
++              gss_cred_set_ctx(cred, gss_get_ctx(ctx));
++      }
++      gss_put_ctx(ctx);
++      kfree(buf);
++      dprintk("RPC:       gss_pipe_downcall returning length %Zu\n", mlen);
++      return mlen;
  err_put_ctx:
        gss_put_ctx(ctx);
  err:
        kfree(buf);
  out:
--      dprintk("RPC:       gss_pipe_downcall returning %d\n", err);
-+      dprintk("RPC:       gss_pipe_downcall returning %Zd\n", err);
+-      dprintk("RPC:       gss_pipe_downcall returning %Zd\n", err);
++      dprintk("RPC:       gss_pipe_downcall returning %d\n", err);
        return err;
  }
  
-@@ -563,27 +560,21 @@
+@@ -560,21 +563,27 @@
  gss_pipe_release(struct inode *inode)
  {
        struct rpc_inode *rpci = RPC_I(inode);
--      struct rpc_clnt *clnt;
--      struct rpc_auth *auth;
--      struct gss_auth *gss_auth;
--
--      clnt = rpci->private;
--      auth = clnt->cl_auth;
--      gss_auth = container_of(auth, struct gss_auth, rpc_auth);
--      spin_lock(&gss_auth->lock);
--      while (!list_empty(&gss_auth->upcalls)) {
-               struct gss_upcall_msg *gss_msg;
--              gss_msg = list_entry(gss_auth->upcalls.next,
-+      spin_lock(&inode->i_lock);
-+      while (!list_empty(&rpci->in_downcall)) {
-+
-+              gss_msg = list_entry(rpci->in_downcall.next,
+-              struct gss_upcall_msg *gss_msg;
++      struct rpc_clnt *clnt;
++      struct rpc_auth *auth;
++      struct gss_auth *gss_auth;
+-      spin_lock(&inode->i_lock);
+-      while (!list_empty(&rpci->in_downcall)) {
++      clnt = rpci->private;
++      auth = clnt->cl_auth;
++      gss_auth = container_of(auth, struct gss_auth, rpc_auth);
++      spin_lock(&gss_auth->lock);
++      while (!list_empty(&gss_auth->upcalls)) {
++              struct gss_upcall_msg *gss_msg;
+-              gss_msg = list_entry(rpci->in_downcall.next,
++              gss_msg = list_entry(gss_auth->upcalls.next,
                                struct gss_upcall_msg, list);
                gss_msg->msg.errno = -EPIPE;
                atomic_inc(&gss_msg->count);
                __gss_unhash_msg(gss_msg);
--              spin_unlock(&gss_auth->lock);
-+              spin_unlock(&inode->i_lock);
+-              spin_unlock(&inode->i_lock);
++              spin_unlock(&gss_auth->lock);
                gss_release_msg(gss_msg);
--              spin_lock(&gss_auth->lock);
-+              spin_lock(&inode->i_lock);
+-              spin_lock(&inode->i_lock);
++              spin_lock(&gss_auth->lock);
        }
--      spin_unlock(&gss_auth->lock);
-+      spin_unlock(&inode->i_lock);
+-      spin_unlock(&inode->i_lock);
++      spin_unlock(&gss_auth->lock);
  }
  
  static void
-@@ -637,8 +628,6 @@
+@@ -628,6 +637,8 @@
        gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
        if (gss_auth->service == 0)
                goto err_put_mech;
--      INIT_LIST_HEAD(&gss_auth->upcalls);
--      spin_lock_init(&gss_auth->lock);
++      INIT_LIST_HEAD(&gss_auth->upcalls);
++      spin_lock_init(&gss_auth->lock);
        auth = &gss_auth->rpc_auth;
        auth->au_cslack = GSS_CRED_SLACK >> 2;
        auth->au_rslack = GSS_VERF_SLACK >> 2;
-@@ -646,10 +635,6 @@
+@@ -635,6 +646,10 @@
        auth->au_flavor = flavor;
        atomic_set(&auth->au_count, 1);
  
--      err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE);
--      if (err)
--              goto err_put_mech;
--
++      err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE);
++      if (err)
++              goto err_put_mech;
++
        gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name,
                        clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
        if (IS_ERR(gss_auth->dentry)) {
-@@ -657,7 +642,13 @@
+@@ -642,13 +657,7 @@
                goto err_put_mech;
        }
  
-+      err = rpcauth_init_credcache(auth);
-+      if (err)
-+              goto err_unlink_pipe;
-+
+-      err = rpcauth_init_credcache(auth);
+-      if (err)
+-              goto err_unlink_pipe;
+-
        return auth;
-+err_unlink_pipe:
-+      rpc_unlink(gss_auth->dentry);
+-err_unlink_pipe:
+-      rpc_unlink(gss_auth->dentry);
  err_put_mech:
        gss_mech_put(gss_auth->mech);
  err_free:
-@@ -675,12 +666,13 @@
+@@ -666,13 +675,12 @@
        dprintk("RPC:       destroying GSS authenticator %p flavor %d\n",
                        auth, auth->au_flavor);
  
-+      rpcauth_destroy_credcache(auth);
-+
+-      rpcauth_destroy_credcache(auth);
+-
        gss_auth = container_of(auth, struct gss_auth, rpc_auth);
        rpc_unlink(gss_auth->dentry);
        gss_auth->dentry = NULL;
        gss_mech_put(gss_auth->mech);
  
--      rpcauth_free_credcache(auth);
++      rpcauth_free_credcache(auth);
        kfree(gss_auth);
        module_put(THIS_MODULE);
  }
-@@ -701,17 +693,27 @@
+@@ -693,27 +701,17 @@
  }
  
  static void
--gss_destroy_cred(struct rpc_cred *rc)
-+gss_free_cred(struct gss_cred *cred)
+-gss_free_cred(struct gss_cred *cred)
++gss_destroy_cred(struct rpc_cred *rc)
  {
--      struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base);
--
--      dprintk("RPC:       gss_destroy_cred \n");
--
-+      dprintk("RPC:       gss_free_cred %p\n", cred);
+-      dprintk("RPC:       gss_free_cred %p\n", cred);
++      struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base);
++
++      dprintk("RPC:       gss_destroy_cred \n");
++
        if (cred->gc_ctx)
                gss_put_ctx(cred->gc_ctx);
        kfree(cred);
  }
  
-+static void
-+gss_free_cred_callback(struct rcu_head *head)
-+{
-+      struct gss_cred *cred = container_of(head, struct gss_cred, gc_base.cr_rcu);
-+      gss_free_cred(cred);
-+}
-+
-+static void
-+gss_destroy_cred(struct rpc_cred *rc)
-+{
-+      call_rcu(&rc->cr_rcu, gss_free_cred_callback);
-+}
-+
+-static void
+-gss_free_cred_callback(struct rcu_head *head)
+-{
+-      struct gss_cred *cred = container_of(head, struct gss_cred, gc_base.cr_rcu);
+-      gss_free_cred(cred);
+-}
+-
+-static void
+-gss_destroy_cred(struct rpc_cred *rc)
+-{
+-      call_rcu(&rc->cr_rcu, gss_free_cred_callback);
+-}
+-
  /*
   * Lookup RPCSEC_GSS cred for the current process
   */
-@@ -734,15 +736,12 @@
+@@ -736,12 +734,15 @@
        if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL)))
                goto out_err;
  
--      atomic_set(&cred->gc_count, 1);
--      cred->gc_uid = acred->uid;
-+      rpcauth_init_cred(&cred->gc_base, acred, auth, &gss_credops);
+-      rpcauth_init_cred(&cred->gc_base, acred, auth, &gss_credops);
++      atomic_set(&cred->gc_count, 1);
++      cred->gc_uid = acred->uid;
        /*
         * Note: in order to force a call to call_refresh(), we deliberately
         * fail to flag the credential as RPCAUTH_CRED_UPTODATE.
         */
--      cred->gc_flags = 0;
--      cred->gc_base.cr_ops = &gss_credops;
--      cred->gc_base.cr_flags = RPCAUTH_CRED_NEW;
-+      cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW;
+-      cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW;
++      cred->gc_flags = 0;
++      cred->gc_base.cr_ops = &gss_credops;
++      cred->gc_base.cr_flags = RPCAUTH_CRED_NEW;
        cred->gc_service = gss_auth->service;
        return &cred->gc_base;
  
-@@ -774,7 +773,7 @@
+@@ -773,7 +774,7 @@
         * we don't really care if the credential has expired or not,
         * since the caller should be prepared to reinitialise it.
         */
--      if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW))
-+      if ((flags & RPCAUTH_LOOKUP_NEW) && test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
+-      if ((flags & RPCAUTH_LOOKUP_NEW) && test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
++      if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW))
                goto out;
        /* Don't match with creds that have expired. */
        if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
-@@ -830,7 +829,7 @@
+@@ -829,7 +830,7 @@
        mic.data = (u8 *)(p + 1);
        maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
--              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-+              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+-              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
++              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        } else if (maj_stat != 0) {
                printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
                goto out_put_ctx;
-@@ -883,7 +882,7 @@
+@@ -882,7 +883,7 @@
  
        maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
--              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-+              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+-              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
++              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        if (maj_stat)
                goto out_bad;
        /* We leave it to unwrap to calculate au_rslack. For now we just
-@@ -937,7 +936,7 @@
+@@ -936,7 +937,7 @@
        maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
        status = -EIO; /* XXX? */
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
--              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-+              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+-              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
++              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        else if (maj_stat)
                return status;
        q = xdr_encode_opaque(p, NULL, mic.len);
-@@ -1036,7 +1035,7 @@
+@@ -1035,7 +1036,7 @@
        /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
         * done anyway, so it's safe to put the request on the wire: */
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
--              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-+              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+-              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
++              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        else if (maj_stat)
                return status;
  
-@@ -1123,7 +1122,7 @@
+@@ -1122,7 +1123,7 @@
  
        maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
--              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-+              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+-              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
++              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        if (maj_stat != GSS_S_COMPLETE)
                return status;
        return 0;
-@@ -1148,7 +1147,7 @@
+@@ -1147,7 +1148,7 @@
  
        maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
--              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-+              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+-              clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
++              cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        if (maj_stat != GSS_S_COMPLETE)
                return status;
        if (ntohl(*(*p)++) != rqstp->rq_seqno)
-@@ -1199,7 +1198,7 @@
+@@ -1198,7 +1199,7 @@
        return status;
  }
  
--static struct rpc_authops authgss_ops = {
-+static const struct rpc_authops authgss_ops = {
+-static const struct rpc_authops authgss_ops = {
++static struct rpc_authops authgss_ops = {
        .owner          = THIS_MODULE,
        .au_flavor      = RPC_AUTH_GSS,
  #ifdef RPC_DEBUG
-@@ -1211,7 +1210,7 @@
+@@ -1210,7 +1211,7 @@
        .crcreate       = gss_create_cred
  };
  
--static struct rpc_credops gss_credops = {
-+static const struct rpc_credops gss_credops = {
+-static const struct rpc_credops gss_credops = {
++static struct rpc_credops gss_credops = {
        .cr_name        = "AUTH_GSS",
        .crdestroy      = gss_destroy_cred,
        .cr_init        = gss_cred_init,
-diff -Nurb linux-2.6.22-570/net/sunrpc/auth_gss/gss_krb5_mech.c linux-2.6.22-590/net/sunrpc/auth_gss/gss_krb5_mech.c
---- linux-2.6.22-570/net/sunrpc/auth_gss/gss_krb5_mech.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sunrpc/auth_gss/gss_krb5_mech.c       2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/net/sunrpc/auth_gss/gss_krb5_mech.c linux-2.6.22-570/net/sunrpc/auth_gss/gss_krb5_mech.c
+--- linux-2.6.22-590/net/sunrpc/auth_gss/gss_krb5_mech.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/auth_gss/gss_krb5_mech.c       2007-07-08 19:32:17.000000000 -0400
 @@ -201,7 +201,7 @@
        kfree(kctx);
  }
  
--static struct gss_api_ops gss_kerberos_ops = {
-+static const struct gss_api_ops gss_kerberos_ops = {
+-static const struct gss_api_ops gss_kerberos_ops = {
++static struct gss_api_ops gss_kerberos_ops = {
        .gss_import_sec_context = gss_import_sec_context_kerberos,
        .gss_get_mic            = gss_get_mic_kerberos,
        .gss_verify_mic         = gss_verify_mic_kerberos,
-diff -Nurb linux-2.6.22-570/net/sunrpc/auth_gss/gss_spkm3_mech.c linux-2.6.22-590/net/sunrpc/auth_gss/gss_spkm3_mech.c
---- linux-2.6.22-570/net/sunrpc/auth_gss/gss_spkm3_mech.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sunrpc/auth_gss/gss_spkm3_mech.c      2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/net/sunrpc/auth_gss/gss_spkm3_mech.c linux-2.6.22-570/net/sunrpc/auth_gss/gss_spkm3_mech.c
+--- linux-2.6.22-590/net/sunrpc/auth_gss/gss_spkm3_mech.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/auth_gss/gss_spkm3_mech.c      2007-07-08 19:32:17.000000000 -0400
 @@ -202,7 +202,7 @@
        return err;
  }
  
--static struct gss_api_ops gss_spkm3_ops = {
-+static const struct gss_api_ops gss_spkm3_ops = {
+-static const struct gss_api_ops gss_spkm3_ops = {
++static struct gss_api_ops gss_spkm3_ops = {
        .gss_import_sec_context = gss_import_sec_context_spkm3,
        .gss_get_mic            = gss_get_mic_spkm3,
        .gss_verify_mic         = gss_verify_mic_spkm3,
-diff -Nurb linux-2.6.22-570/net/sunrpc/auth_null.c linux-2.6.22-590/net/sunrpc/auth_null.c
---- linux-2.6.22-570/net/sunrpc/auth_null.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sunrpc/auth_null.c    2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/net/sunrpc/auth_null.c linux-2.6.22-570/net/sunrpc/auth_null.c
+--- linux-2.6.22-590/net/sunrpc/auth_null.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/auth_null.c    2007-07-08 19:32:17.000000000 -0400
 @@ -76,7 +76,7 @@
  static int
  nul_refresh(struct rpc_task *task)
  {
--      task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
-+      set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
+-      set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
++      task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
        return 0;
  }
  
@@ -201356,8 +201546,8 @@ diff -Nurb linux-2.6.22-570/net/sunrpc/auth_null.c linux-2.6.22-590/net/sunrpc/a
        return p;
  }
  
--struct rpc_authops authnull_ops = {
-+const struct rpc_authops authnull_ops = {
+-const struct rpc_authops authnull_ops = {
++struct rpc_authops authnull_ops = {
        .owner          = THIS_MODULE,
        .au_flavor      = RPC_AUTH_NULL,
  #ifdef RPC_DEBUG
@@ -201365,650 +201555,650 @@ diff -Nurb linux-2.6.22-570/net/sunrpc/auth_null.c linux-2.6.22-590/net/sunrpc/a
  };
  
  static
--struct rpc_credops    null_credops = {
-+const struct rpc_credops null_credops = {
+-const struct rpc_credops null_credops = {
++struct rpc_credops    null_credops = {
        .cr_name        = "AUTH_NULL",
        .crdestroy      = nul_destroy_cred,
        .crmatch        = nul_match,
-@@ -133,9 +133,11 @@
+@@ -133,11 +133,9 @@
  
  static
  struct rpc_cred null_cred = {
-+      .cr_lru         = LIST_HEAD_INIT(null_cred.cr_lru),
-+      .cr_auth        = &null_auth,
+-      .cr_lru         = LIST_HEAD_INIT(null_cred.cr_lru),
+-      .cr_auth        = &null_auth,
        .cr_ops         = &null_credops,
        .cr_count       = ATOMIC_INIT(1),
--      .cr_flags       = RPCAUTH_CRED_UPTODATE,
-+      .cr_flags       = 1UL << RPCAUTH_CRED_UPTODATE,
+-      .cr_flags       = 1UL << RPCAUTH_CRED_UPTODATE,
++      .cr_flags       = RPCAUTH_CRED_UPTODATE,
  #ifdef RPC_DEBUG
        .cr_magic       = RPCAUTH_CRED_MAGIC,
  #endif
-diff -Nurb linux-2.6.22-570/net/sunrpc/auth_unix.c linux-2.6.22-590/net/sunrpc/auth_unix.c
---- linux-2.6.22-570/net/sunrpc/auth_unix.c    2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/sunrpc/auth_unix.c    2008-01-02 13:56:38.000000000 -0500
-@@ -22,11 +22,6 @@
+diff -Nurb linux-2.6.22-590/net/sunrpc/auth_unix.c linux-2.6.22-570/net/sunrpc/auth_unix.c
+--- linux-2.6.22-590/net/sunrpc/auth_unix.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/auth_unix.c    2008-01-23 19:16:05.000000000 -0500
+@@ -22,6 +22,11 @@
        gid_t                   uc_gids[NFS_NGROUPS];
  };
  #define uc_uid                        uc_base.cr_uid
--#define uc_count              uc_base.cr_count
--#define uc_flags              uc_base.cr_flags
--#define uc_expire             uc_base.cr_expire
--
--#define UNX_CRED_EXPIRE               (60 * HZ)
++#define uc_count              uc_base.cr_count
++#define uc_flags              uc_base.cr_flags
++#define uc_expire             uc_base.cr_expire
++
++#define UNX_CRED_EXPIRE               (60 * HZ)
  
  #define UNX_WRITESLACK                (21 + (UNX_MAXNODENAME >> 2))
  
-@@ -36,15 +31,14 @@
+@@ -31,14 +36,15 @@
  
  static struct rpc_auth                unix_auth;
  static struct rpc_cred_cache  unix_cred_cache;
--static struct rpc_credops     unix_credops;
-+static const struct rpc_credops       unix_credops;
+-static const struct rpc_credops       unix_credops;
++static struct rpc_credops     unix_credops;
  
  static struct rpc_auth *
  unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
  {
        dprintk("RPC:       creating UNIX authenticator for client %p\n",
                        clnt);
--      if (atomic_inc_return(&unix_auth.au_count) == 0)
--              unix_cred_cache.nextgc = jiffies + (unix_cred_cache.expire >> 1);
-+      atomic_inc(&unix_auth.au_count);
+-      atomic_inc(&unix_auth.au_count);
++      if (atomic_inc_return(&unix_auth.au_count) == 0)
++              unix_cred_cache.nextgc = jiffies + (unix_cred_cache.expire >> 1);
        return &unix_auth;
  }
  
-@@ -52,7 +46,7 @@
+@@ -46,7 +52,7 @@
  unx_destroy(struct rpc_auth *auth)
  {
        dprintk("RPC:       destroying UNIX authenticator %p\n", auth);
--      rpcauth_free_credcache(auth);
-+      rpcauth_clear_credcache(auth->au_credcache);
+-      rpcauth_clear_credcache(auth->au_credcache);
++      rpcauth_free_credcache(auth);
  }
  
  /*
-@@ -76,8 +70,8 @@
+@@ -70,8 +76,8 @@
        if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL)))
                return ERR_PTR(-ENOMEM);
  
--      atomic_set(&cred->uc_count, 1);
--      cred->uc_flags = RPCAUTH_CRED_UPTODATE;
-+      rpcauth_init_cred(&cred->uc_base, acred, &unix_auth, &unix_credops);
-+      cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
+-      rpcauth_init_cred(&cred->uc_base, acred, &unix_auth, &unix_credops);
+-      cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
++      atomic_set(&cred->uc_count, 1);
++      cred->uc_flags = RPCAUTH_CRED_UPTODATE;
        if (flags & RPCAUTH_LOOKUP_ROOTCREDS) {
                cred->uc_uid = 0;
                cred->uc_gid = 0;
-@@ -88,7 +82,6 @@
+@@ -82,6 +88,7 @@
                if (groups > NFS_NGROUPS)
                        groups = NFS_NGROUPS;
  
--              cred->uc_uid = acred->uid;
++              cred->uc_uid = acred->uid;
                cred->uc_gid = acred->gid;
                cred->uc_tag = acred->tag;
                for (i = 0; i < groups; i++)
-@@ -96,17 +89,31 @@
+@@ -89,31 +96,17 @@
                if (i < NFS_NGROUPS)
                  cred->uc_gids[i] = NOGROUP;
        }
--      cred->uc_base.cr_ops = &unix_credops;
++      cred->uc_base.cr_ops = &unix_credops;
  
--      return (struct rpc_cred *) cred;
-+      return &cred->uc_base;
+-      return &cred->uc_base;
+-}
+-
+-static void
+- unx_free_cred(struct unx_cred *cred)
+-{
+-      dprintk("RPC:       unx_free_cred %p\n", cred);
+-      kfree(cred);
+-}
+-
+-static void
+-unx_free_cred_callback(struct rcu_head *head)
+-{
+-      struct unx_cred *cred = container_of(head, struct unx_cred, uc_base.cr_rcu);
+-      unx_free_cred(cred);
++      return (struct rpc_cred *) cred;
  }
  
  static void
--unx_destroy_cred(struct rpc_cred *cred)
-+ unx_free_cred(struct unx_cred *cred)
+ unx_destroy_cred(struct rpc_cred *cred)
  {
-+      dprintk("RPC:       unx_free_cred %p\n", cred);
-       kfree(cred);
+-      call_rcu(&cred->cr_rcu, unx_free_cred_callback);
++      kfree(cred);
  }
  
-+static void
-+unx_free_cred_callback(struct rcu_head *head)
-+{
-+      struct unx_cred *cred = container_of(head, struct unx_cred, uc_base.cr_rcu);
-+      unx_free_cred(cred);
-+}
-+
-+static void
-+unx_destroy_cred(struct rpc_cred *cred)
-+{
-+      call_rcu(&cred->cr_rcu, unx_free_cred_callback);
-+}
-+
-+
+-
  /*
   * Match credentials against current process creds.
   * The root_override argument takes care of cases where the caller may
-@@ -115,7 +122,7 @@
+@@ -122,7 +115,7 @@
  static int
  unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
  {
--      struct unx_cred *cred = (struct unx_cred *) rcred;
-+      struct unx_cred *cred = container_of(rcred, struct unx_cred, uc_base);
+-      struct unx_cred *cred = container_of(rcred, struct unx_cred, uc_base);
++      struct unx_cred *cred = (struct unx_cred *) rcred;
        int             i;
  
        if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) {
-@@ -147,7 +154,7 @@
+@@ -154,7 +147,7 @@
  unx_marshal(struct rpc_task *task, __be32 *p)
  {
        struct rpc_clnt *clnt = task->tk_client;
--      struct unx_cred *cred = (struct unx_cred *) task->tk_msg.rpc_cred;
-+      struct unx_cred *cred = container_of(task->tk_msg.rpc_cred, struct unx_cred, uc_base);
+-      struct unx_cred *cred = container_of(task->tk_msg.rpc_cred, struct unx_cred, uc_base);
++      struct unx_cred *cred = (struct unx_cred *) task->tk_msg.rpc_cred;
        __be32          *base, *hold;
        int             i, tag;
  
-@@ -159,7 +166,6 @@
+@@ -166,6 +159,7 @@
         * Copy the UTS nodename captured when the client was created.
         */
        p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
--      tag = task->tk_client->cl_tag;
++      tag = task->tk_client->cl_tag;
  
        *p++ = htonl((u32) TAGINO_UID(tag,
                cred->uc_uid, cred->uc_tag));
-@@ -183,7 +189,7 @@
+@@ -189,7 +183,7 @@
  static int
  unx_refresh(struct rpc_task *task)
  {
--      task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
-+      set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
+-      set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
++      task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
        return 0;
  }
  
-@@ -212,7 +218,12 @@
+@@ -218,12 +212,7 @@
        return p;
  }
  
--struct rpc_authops    authunix_ops = {
-+void __init rpc_init_authunix(void)
-+{
-+      spin_lock_init(&unix_cred_cache.lock);
-+}
-+
-+const struct rpc_authops authunix_ops = {
+-void __init rpc_init_authunix(void)
+-{
+-      spin_lock_init(&unix_cred_cache.lock);
+-}
+-
+-const struct rpc_authops authunix_ops = {
++struct rpc_authops    authunix_ops = {
        .owner          = THIS_MODULE,
        .au_flavor      = RPC_AUTH_UNIX,
  #ifdef RPC_DEBUG
-@@ -226,7 +237,6 @@
+@@ -237,6 +226,7 @@
  
  static
  struct rpc_cred_cache unix_cred_cache = {
--      .expire         = UNX_CRED_EXPIRE,
++      .expire         = UNX_CRED_EXPIRE,
  };
  
  static
-@@ -240,7 +250,7 @@
+@@ -250,7 +240,7 @@
  };
  
  static
--struct rpc_credops    unix_credops = {
-+const struct rpc_credops unix_credops = {
+-const struct rpc_credops unix_credops = {
++struct rpc_credops    unix_credops = {
        .cr_name        = "AUTH_UNIX",
        .crdestroy      = unx_destroy_cred,
        .crmatch        = unx_match,
-diff -Nurb linux-2.6.22-570/net/sunrpc/clnt.c linux-2.6.22-590/net/sunrpc/clnt.c
---- linux-2.6.22-570/net/sunrpc/clnt.c 2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/sunrpc/clnt.c 2008-01-02 13:56:38.000000000 -0500
-@@ -45,6 +45,12 @@
+diff -Nurb linux-2.6.22-590/net/sunrpc/clnt.c linux-2.6.22-570/net/sunrpc/clnt.c
+--- linux-2.6.22-590/net/sunrpc/clnt.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/clnt.c 2008-01-23 19:16:05.000000000 -0500
+@@ -45,12 +45,6 @@
        dprintk("RPC: %5u %s (status %d)\n", t->tk_pid,         \
                        __FUNCTION__, t->tk_status)
  
-+/*
-+ * All RPC clients are linked into this list
-+ */
-+static LIST_HEAD(all_clients);
-+static DEFINE_SPINLOCK(rpc_client_lock);
-+
+-/*
+- * All RPC clients are linked into this list
+- */
+-static LIST_HEAD(all_clients);
+-static DEFINE_SPINLOCK(rpc_client_lock);
+-
  static DECLARE_WAIT_QUEUE_HEAD(destroy_wait);
  
  
-@@ -67,6 +73,21 @@
+@@ -73,21 +67,6 @@
  static __be32 *       call_header(struct rpc_task *task);
  static __be32 *       call_verify(struct rpc_task *task);
  
-+static int    rpc_ping(struct rpc_clnt *clnt, int flags);
-+
-+static void rpc_register_client(struct rpc_clnt *clnt)
-+{
-+      spin_lock(&rpc_client_lock);
-+      list_add(&clnt->cl_clients, &all_clients);
-+      spin_unlock(&rpc_client_lock);
-+}
-+
-+static void rpc_unregister_client(struct rpc_clnt *clnt)
-+{
-+      spin_lock(&rpc_client_lock);
-+      list_del(&clnt->cl_clients);
-+      spin_unlock(&rpc_client_lock);
-+}
+-static int    rpc_ping(struct rpc_clnt *clnt, int flags);
+-
+-static void rpc_register_client(struct rpc_clnt *clnt)
+-{
+-      spin_lock(&rpc_client_lock);
+-      list_add(&clnt->cl_clients, &all_clients);
+-      spin_unlock(&rpc_client_lock);
+-}
+-
+-static void rpc_unregister_client(struct rpc_clnt *clnt)
+-{
+-      spin_lock(&rpc_client_lock);
+-      list_del(&clnt->cl_clients);
+-      spin_unlock(&rpc_client_lock);
+-}
  
  static int
  rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
-@@ -112,6 +133,9 @@
+@@ -133,9 +112,6 @@
        dprintk("RPC:       creating %s client for %s (xprt %p)\n",
                        program->name, servname, xprt);
  
-+      err = rpciod_up();
-+      if (err)
-+              goto out_no_rpciod;
+-      err = rpciod_up();
+-      if (err)
+-              goto out_no_rpciod;
        err = -EINVAL;
        if (!xprt)
                goto out_no_xprt;
-@@ -122,8 +146,6 @@
+@@ -146,6 +122,8 @@
        clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
        if (!clnt)
                goto out_err;
--      atomic_set(&clnt->cl_users, 0);
--      atomic_set(&clnt->cl_count, 1);
++      atomic_set(&clnt->cl_users, 0);
++      atomic_set(&clnt->cl_count, 1);
        clnt->cl_parent = clnt;
  
        clnt->cl_server = clnt->cl_inline_name;
-@@ -149,6 +171,8 @@
+@@ -171,8 +149,6 @@
        if (clnt->cl_metrics == NULL)
                goto out_no_stats;
        clnt->cl_program  = program;
-+      INIT_LIST_HEAD(&clnt->cl_tasks);
-+      spin_lock_init(&clnt->cl_lock);
+-      INIT_LIST_HEAD(&clnt->cl_tasks);
+-      spin_lock_init(&clnt->cl_lock);
  
        if (!xprt_bound(clnt->cl_xprt))
                clnt->cl_autobind = 1;
-@@ -156,6 +180,8 @@
+@@ -180,8 +156,6 @@
        clnt->cl_rtt = &clnt->cl_rtt_default;
        rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval);
  
-+      kref_init(&clnt->cl_kref);
-+
+-      kref_init(&clnt->cl_kref);
+-
        err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
        if (err < 0)
                goto out_no_path;
-@@ -173,6 +199,7 @@
+@@ -199,7 +173,6 @@
        if (clnt->cl_nodelen > UNX_MAXNODENAME)
                clnt->cl_nodelen = UNX_MAXNODENAME;
        memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen);
-+      rpc_register_client(clnt);
+-      rpc_register_client(clnt);
        return clnt;
  
  out_no_auth:
-@@ -189,6 +216,8 @@
+@@ -216,8 +189,6 @@
  out_err:
        xprt_put(xprt);
  out_no_xprt:
-+      rpciod_down();
-+out_no_rpciod:
+-      rpciod_down();
+-out_no_rpciod:
        return ERR_PTR(err);
  }
  
-@@ -246,8 +275,6 @@
+@@ -275,6 +246,8 @@
                clnt->cl_intr = 1;
        if (args->flags & RPC_CLNT_CREATE_AUTOBIND)
                clnt->cl_autobind = 1;
--      if (args->flags & RPC_CLNT_CREATE_ONESHOT)
--              clnt->cl_oneshot = 1;
++      if (args->flags & RPC_CLNT_CREATE_ONESHOT)
++              clnt->cl_oneshot = 1;
        if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
                clnt->cl_discrtry = 1;
        /* TODO: handle RPC_CLNT_CREATE_TAGGED
-@@ -271,24 +298,25 @@
+@@ -298,25 +271,24 @@
        new = kmemdup(clnt, sizeof(*new), GFP_KERNEL);
        if (!new)
                goto out_no_clnt;
--      atomic_set(&new->cl_count, 1);
--      atomic_set(&new->cl_users, 0);
-+      new->cl_parent = clnt;
-+      /* Turn off autobind on clones */
-+      new->cl_autobind = 0;
-+      INIT_LIST_HEAD(&new->cl_tasks);
-+      spin_lock_init(&new->cl_lock);
-+      rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
+-      new->cl_parent = clnt;
+-      /* Turn off autobind on clones */
+-      new->cl_autobind = 0;
+-      INIT_LIST_HEAD(&new->cl_tasks);
+-      spin_lock_init(&new->cl_lock);
+-      rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
++      atomic_set(&new->cl_count, 1);
++      atomic_set(&new->cl_users, 0);
        new->cl_metrics = rpc_alloc_iostats(clnt);
        if (new->cl_metrics == NULL)
                goto out_no_stats;
-+      kref_init(&new->cl_kref);
+-      kref_init(&new->cl_kref);
        err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
        if (err != 0)
                goto out_no_path;
--      new->cl_parent = clnt;
--      atomic_inc(&clnt->cl_count);
--      new->cl_xprt = xprt_get(clnt->cl_xprt);
--      /* Turn off autobind on clones */
--      new->cl_autobind = 0;
--      new->cl_oneshot = 0;
--      new->cl_dead = 0;
--      rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
++      new->cl_parent = clnt;
++      atomic_inc(&clnt->cl_count);
++      new->cl_xprt = xprt_get(clnt->cl_xprt);
++      /* Turn off autobind on clones */
++      new->cl_autobind = 0;
++      new->cl_oneshot = 0;
++      new->cl_dead = 0;
++      rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
        if (new->cl_auth)
                atomic_inc(&new->cl_auth->au_count);
-+      xprt_get(clnt->cl_xprt);
-+      kref_get(&clnt->cl_kref);
-+      rpc_register_client(new);
-+      rpciod_up();
+-      xprt_get(clnt->cl_xprt);
+-      kref_get(&clnt->cl_kref);
+-      rpc_register_client(new);
+-      rpciod_up();
        return new;
  out_no_path:
        rpc_free_iostats(new->cl_metrics);
-@@ -301,52 +329,34 @@
+@@ -329,34 +301,52 @@
  
  /*
   * Properly shut down an RPC client, terminating all outstanding
-- * requests. Note that we must be certain that cl_oneshot and
-- * cl_dead are cleared, or else the client would be destroyed
-- * when the last task releases it.
-+ * requests.
+- * requests.
++ * requests. Note that we must be certain that cl_oneshot and
++ * cl_dead are cleared, or else the client would be destroyed
++ * when the last task releases it.
   */
--int
--rpc_shutdown_client(struct rpc_clnt *clnt)
-+void rpc_shutdown_client(struct rpc_clnt *clnt)
+-void rpc_shutdown_client(struct rpc_clnt *clnt)
++int
++rpc_shutdown_client(struct rpc_clnt *clnt)
  {
--      dprintk("RPC:       shutting down %s client for %s, tasks=%d\n",
--                      clnt->cl_protname, clnt->cl_server,
--                      atomic_read(&clnt->cl_users));
+-      dprintk("RPC:       shutting down %s client for %s\n",
+-                      clnt->cl_protname, clnt->cl_server);
 -
--      while (atomic_read(&clnt->cl_users) > 0) {
--              /* Don't let rpc_release_client destroy us */
--              clnt->cl_oneshot = 0;
--              clnt->cl_dead = 0;
-+      dprintk("RPC:       shutting down %s client for %s\n",
-+                      clnt->cl_protname, clnt->cl_server);
+-      while (!list_empty(&clnt->cl_tasks)) {
++      dprintk("RPC:       shutting down %s client for %s, tasks=%d\n",
++                      clnt->cl_protname, clnt->cl_server,
++                      atomic_read(&clnt->cl_users));
 +
-+      while (!list_empty(&clnt->cl_tasks)) {
++      while (atomic_read(&clnt->cl_users) > 0) {
++              /* Don't let rpc_release_client destroy us */
++              clnt->cl_oneshot = 0;
++              clnt->cl_dead = 0;
                rpc_killall_tasks(clnt);
                wait_event_timeout(destroy_wait,
--                      !atomic_read(&clnt->cl_users), 1*HZ);
--      }
--
--      if (atomic_read(&clnt->cl_users) < 0) {
--              printk(KERN_ERR "RPC: rpc_shutdown_client clnt %p tasks=%d\n",
--                              clnt, atomic_read(&clnt->cl_users));
--#ifdef RPC_DEBUG
--              rpc_show_tasks();
--#endif
--              BUG();
-+                      list_empty(&clnt->cl_tasks), 1*HZ);
+-                      list_empty(&clnt->cl_tasks), 1*HZ);
++                      !atomic_read(&clnt->cl_users), 1*HZ);
++      }
++
++      if (atomic_read(&clnt->cl_users) < 0) {
++              printk(KERN_ERR "RPC: rpc_shutdown_client clnt %p tasks=%d\n",
++                              clnt, atomic_read(&clnt->cl_users));
++#ifdef RPC_DEBUG
++              rpc_show_tasks();
++#endif
++              BUG();
        }
  
--      return rpc_destroy_client(clnt);
-+      rpc_release_client(clnt);
+-      rpc_release_client(clnt);
++      return rpc_destroy_client(clnt);
  }
  
  /*
-- * Delete an RPC client
-+ * Free an RPC client
+- * Free an RPC client
++ * Delete an RPC client
   */
--int
--rpc_destroy_client(struct rpc_clnt *clnt)
-+static void
-+rpc_free_client(struct kref *kref)
+-static void
+-rpc_free_client(struct kref *kref)
++int
++rpc_destroy_client(struct rpc_clnt *clnt)
  {
--      if (!atomic_dec_and_test(&clnt->cl_count))
--              return 1;
--      BUG_ON(atomic_read(&clnt->cl_users) != 0);
-+      struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
+-      struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
++      if (!atomic_dec_and_test(&clnt->cl_count))
++              return 1;
++      BUG_ON(atomic_read(&clnt->cl_users) != 0);
  
        dprintk("RPC:       destroying %s client for %s\n",
                        clnt->cl_protname, clnt->cl_server);
        if (clnt->cl_auth) {
--              rpcauth_destroy(clnt->cl_auth);
-+              rpcauth_release(clnt->cl_auth);
+-              rpcauth_release(clnt->cl_auth);
++              rpcauth_destroy(clnt->cl_auth);
                clnt->cl_auth = NULL;
        }
        if (!IS_ERR(clnt->cl_dentry)) {
-@@ -354,33 +364,31 @@
+@@ -364,31 +354,33 @@
                rpc_put_mount();
        }
        if (clnt->cl_parent != clnt) {
--              rpc_destroy_client(clnt->cl_parent);
-+              rpc_release_client(clnt->cl_parent);
+-              rpc_release_client(clnt->cl_parent);
++              rpc_destroy_client(clnt->cl_parent);
                goto out_free;
        }
        if (clnt->cl_server != clnt->cl_inline_name)
                kfree(clnt->cl_server);
  out_free:
-+      rpc_unregister_client(clnt);
+-      rpc_unregister_client(clnt);
        rpc_free_iostats(clnt->cl_metrics);
        clnt->cl_metrics = NULL;
        xprt_put(clnt->cl_xprt);
-+      rpciod_down();
+-      rpciod_down();
        kfree(clnt);
--      return 0;
++      return 0;
  }
  
  /*
-- * Release an RPC client
-+ * Release reference to the RPC client
+- * Release reference to the RPC client
++ * Release an RPC client
   */
  void
  rpc_release_client(struct rpc_clnt *clnt)
  {
--      dprintk("RPC:       rpc_release_client(%p, %d)\n",
--                      clnt, atomic_read(&clnt->cl_users));
-+      dprintk("RPC:       rpc_release_client(%p)\n", clnt);
+-      dprintk("RPC:       rpc_release_client(%p)\n", clnt);
++      dprintk("RPC:       rpc_release_client(%p, %d)\n",
++                      clnt, atomic_read(&clnt->cl_users));
  
--      if (!atomic_dec_and_test(&clnt->cl_users))
--              return;
-+      if (list_empty(&clnt->cl_tasks))
+-      if (list_empty(&clnt->cl_tasks))
++      if (!atomic_dec_and_test(&clnt->cl_users))
++              return;
        wake_up(&destroy_wait);
--      if (clnt->cl_oneshot || clnt->cl_dead)
--              rpc_destroy_client(clnt);
-+      kref_put(&clnt->cl_kref, rpc_free_client);
+-      kref_put(&clnt->cl_kref, rpc_free_client);
++      if (clnt->cl_oneshot || clnt->cl_dead)
++              rpc_destroy_client(clnt);
  }
  
  /**
-@@ -471,82 +479,96 @@
+@@ -479,96 +471,82 @@
        rpc_restore_sigmask(oldset);
  }
  
--/*
-- * New rpc_call implementation
-- */
--int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
-+static
-+struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt,
-+              struct rpc_message *msg,
-+              int flags,
-+              const struct rpc_call_ops *ops,
-+              void *data)
- {
--      struct rpc_task *task;
-+      struct rpc_task *task, *ret;
-       sigset_t        oldset;
--      int             status;
--
--      /* If this client is slain all further I/O fails */
--      if (clnt->cl_dead)
--              return -EIO;
+-static
+-struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt,
+-              struct rpc_message *msg,
+-              int flags,
+-              const struct rpc_call_ops *ops,
+-              void *data)
+-{
+-      struct rpc_task *task, *ret;
+-      sigset_t        oldset;
 -
--      BUG_ON(flags & RPC_TASK_ASYNC);
--      task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL);
--      if (task == NULL)
--              return -ENOMEM;
-+      task = rpc_new_task(clnt, flags, ops, data);
-+      if (task == NULL) {
-+              rpc_release_calldata(ops, data);
-+              return ERR_PTR(-ENOMEM);
-+      }
--      /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */
-+      /* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */
-       rpc_task_sigmask(task, &oldset);
+-      task = rpc_new_task(clnt, flags, ops, data);
+-      if (task == NULL) {
+-              rpc_release_calldata(ops, data);
+-              return ERR_PTR(-ENOMEM);
+-      }
 -
--      /* Set up the call info struct and execute the task */
-+      if (msg != NULL) {
-       rpc_call_setup(task, msg, 0);
--      if (task->tk_status == 0) {
-+              if (task->tk_status != 0) {
-+                      ret = ERR_PTR(task->tk_status);
-+                      rpc_put_task(task);
-+                      goto out;
-+              }
-+      }
-               atomic_inc(&task->tk_count);
-               rpc_execute(task);
+-      /* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */
+-      rpc_task_sigmask(task, &oldset);
+-      if (msg != NULL) {
+-      rpc_call_setup(task, msg, 0);
+-              if (task->tk_status != 0) {
+-                      ret = ERR_PTR(task->tk_status);
+-                      rpc_put_task(task);
+-                      goto out;
+-              }
 -      }
-+      ret = task;
-+out:
-+      rpc_restore_sigmask(&oldset);
-+      return ret;
-+}
+-              atomic_inc(&task->tk_count);
+-              rpc_execute(task);
+-      ret = task;
+-out:
+-      rpc_restore_sigmask(&oldset);
+-      return ret;
+-}
+-
+-/**
+- * rpc_call_sync - Perform a synchronous RPC call
+- * @clnt: pointer to RPC client
+- * @msg: RPC call parameters
+- * @flags: RPC call flags
++/*
++ * New rpc_call implementation
+  */
+ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
+ {
+       struct rpc_task *task;
++      sigset_t        oldset;
+       int status;
++      /* If this client is slain all further I/O fails */
++      if (clnt->cl_dead)
++              return -EIO;
 +
-+/**
-+ * rpc_call_sync - Perform a synchronous RPC call
-+ * @clnt: pointer to RPC client
-+ * @msg: RPC call parameters
-+ * @flags: RPC call flags
-+ */
-+int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
-+{
-+      struct rpc_task *task;
-+      int status;
+       BUG_ON(flags & RPC_TASK_ASYNC);
+-      task = rpc_do_run_task(clnt, msg, flags, &rpc_default_ops, NULL);
+-      if (IS_ERR(task))
+-              return PTR_ERR(task);
++      task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL);
++      if (task == NULL)
++              return -ENOMEM;
 +
-+      BUG_ON(flags & RPC_TASK_ASYNC);
++      /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */
++      rpc_task_sigmask(task, &oldset);
 +
-+      task = rpc_do_run_task(clnt, msg, flags, &rpc_default_ops, NULL);
-+      if (IS_ERR(task))
-+              return PTR_ERR(task);
++      /* Set up the call info struct and execute the task */
++      rpc_call_setup(task, msg, 0);
++      if (task->tk_status == 0) {
++              atomic_inc(&task->tk_count);
++              rpc_execute(task);
++      }
        status = task->tk_status;
        rpc_put_task(task);
--      rpc_restore_sigmask(&oldset);
++      rpc_restore_sigmask(&oldset);
        return status;
  }
  
--/*
-- * New rpc_call implementation
-+/**
-+ * rpc_call_async - Perform an asynchronous RPC call
-+ * @clnt: pointer to RPC client
-+ * @msg: RPC call parameters
-+ * @flags: RPC call flags
-+ * @ops: RPC call ops
-+ * @data: user call data
+-/**
+- * rpc_call_async - Perform an asynchronous RPC call
+- * @clnt: pointer to RPC client
+- * @msg: RPC call parameters
+- * @flags: RPC call flags
+- * @ops: RPC call ops
+- * @data: user call data
++/*
++ * New rpc_call implementation
   */
  int
  rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
               const struct rpc_call_ops *tk_ops, void *data)
  {
        struct rpc_task *task;
--      sigset_t        oldset;
--      int             status;
--      /* If this client is slain all further I/O fails */
--      status = -EIO;
--      if (clnt->cl_dead)
--              goto out_release;
--
--      flags |= RPC_TASK_ASYNC;
--
--      /* Create/initialize a new RPC task */
--      status = -ENOMEM;
--      if (!(task = rpc_new_task(clnt, flags, tk_ops, data)))
--              goto out_release;
--
--      /* Mask signals on GSS_AUTH upcalls */
--      rpc_task_sigmask(task, &oldset);
--
--      rpc_call_setup(task, msg, 0);
--
--      /* Set up the call info struct and execute the task */
--      status = task->tk_status;
--      if (status == 0)
--              rpc_execute(task);
--      else
-+      task = rpc_do_run_task(clnt, msg, flags|RPC_TASK_ASYNC, tk_ops, data);
-+      if (IS_ERR(task))
-+              return PTR_ERR(task);
++      sigset_t        oldset;
++      int             status;
+-      task = rpc_do_run_task(clnt, msg, flags|RPC_TASK_ASYNC, tk_ops, data);
+-      if (IS_ERR(task))
+-              return PTR_ERR(task);
++      /* If this client is slain all further I/O fails */
++      status = -EIO;
++      if (clnt->cl_dead)
++              goto out_release;
++
++      flags |= RPC_TASK_ASYNC;
++
++      /* Create/initialize a new RPC task */
++      status = -ENOMEM;
++      if (!(task = rpc_new_task(clnt, flags, tk_ops, data)))
++              goto out_release;
++
++      /* Mask signals on GSS_AUTH upcalls */
++      rpc_task_sigmask(task, &oldset);
++
++      rpc_call_setup(task, msg, 0);
++
++      /* Set up the call info struct and execute the task */
++      status = task->tk_status;
++      if (status == 0)
++              rpc_execute(task);
++      else
                rpc_put_task(task);
--
--      rpc_restore_sigmask(&oldset);
--      return status;
--out_release:
--      rpc_release_calldata(tk_ops, data);
--      return status;
-+      return 0;
- }
+-      return 0;
+-}
  
-+/**
-+ * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
-+ * @clnt: pointer to RPC client
-+ * @flags: RPC flags
-+ * @ops: RPC call ops
-+ * @data: user call data
-+ */
-+struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
-+                                      const struct rpc_call_ops *tk_ops,
-+                                      void *data)
-+{
-+      return rpc_do_run_task(clnt, NULL, flags, tk_ops, data);
-+}
-+EXPORT_SYMBOL(rpc_run_task);
+-/**
+- * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
+- * @clnt: pointer to RPC client
+- * @flags: RPC flags
+- * @ops: RPC call ops
+- * @data: user call data
+- */
+-struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
+-                                      const struct rpc_call_ops *tk_ops,
+-                                      void *data)
+-{
+-      return rpc_do_run_task(clnt, NULL, flags, tk_ops, data);
++      rpc_restore_sigmask(&oldset);
++      return status;
++out_release:
++      rpc_release_calldata(tk_ops, data);
++      return status;
+ }
+-EXPORT_SYMBOL(rpc_run_task);
++
  
  void
  rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
-@@ -1424,7 +1446,7 @@
+@@ -1446,7 +1424,7 @@
        .p_decode = rpcproc_decode_null,
  };
  
--int rpc_ping(struct rpc_clnt *clnt, int flags)
-+static int rpc_ping(struct rpc_clnt *clnt, int flags)
+-static int rpc_ping(struct rpc_clnt *clnt, int flags)
++int rpc_ping(struct rpc_clnt *clnt, int flags)
  {
        struct rpc_message msg = {
                .rpc_proc = &rpcproc_null,
-@@ -1435,3 +1457,51 @@
+@@ -1457,51 +1435,3 @@
        put_rpccred(msg.rpc_cred);
        return err;
  }
-+
-+struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags)
-+{
-+      struct rpc_message msg = {
-+              .rpc_proc = &rpcproc_null,
-+              .rpc_cred = cred,
-+      };
-+      return rpc_do_run_task(clnt, &msg, flags, &rpc_default_ops, NULL);
-+}
-+EXPORT_SYMBOL(rpc_call_null);
-+
-+#ifdef RPC_DEBUG
-+void rpc_show_tasks(void)
-+{
-+      struct rpc_clnt *clnt;
-+      struct rpc_task *t;
-+
-+      spin_lock(&rpc_client_lock);
-+      if (list_empty(&all_clients))
-+              goto out;
-+      printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
-+              "-rpcwait -action- ---ops--\n");
-+      list_for_each_entry(clnt, &all_clients, cl_clients) {
-+              if (list_empty(&clnt->cl_tasks))
-+                      continue;
-+              spin_lock(&clnt->cl_lock);
-+              list_for_each_entry(t, &clnt->cl_tasks, tk_task) {
-+                      const char *rpc_waitq = "none"; 
-+
-+                      if (RPC_IS_QUEUED(t))
-+                              rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
-+
-+                      printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
-+                              t->tk_pid,
-+                              (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
-+                              t->tk_flags, t->tk_status,
-+                              t->tk_client,
-+                              (t->tk_client ? t->tk_client->cl_prog : 0),
-+                              t->tk_rqstp, t->tk_timeout,
-+                              rpc_waitq,
-+                              t->tk_action, t->tk_ops);
-+              }
-+              spin_unlock(&clnt->cl_lock);
-+      }
-+out:
-+      spin_unlock(&rpc_client_lock);
-+}
-+#endif
-diff -Nurb linux-2.6.22-570/net/sunrpc/rpc_pipe.c linux-2.6.22-590/net/sunrpc/rpc_pipe.c
---- linux-2.6.22-570/net/sunrpc/rpc_pipe.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sunrpc/rpc_pipe.c     2008-01-02 13:56:38.000000000 -0500
+-
+-struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags)
+-{
+-      struct rpc_message msg = {
+-              .rpc_proc = &rpcproc_null,
+-              .rpc_cred = cred,
+-      };
+-      return rpc_do_run_task(clnt, &msg, flags, &rpc_default_ops, NULL);
+-}
+-EXPORT_SYMBOL(rpc_call_null);
+-
+-#ifdef RPC_DEBUG
+-void rpc_show_tasks(void)
+-{
+-      struct rpc_clnt *clnt;
+-      struct rpc_task *t;
+-
+-      spin_lock(&rpc_client_lock);
+-      if (list_empty(&all_clients))
+-              goto out;
+-      printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
+-              "-rpcwait -action- ---ops--\n");
+-      list_for_each_entry(clnt, &all_clients, cl_clients) {
+-              if (list_empty(&clnt->cl_tasks))
+-                      continue;
+-              spin_lock(&clnt->cl_lock);
+-              list_for_each_entry(t, &clnt->cl_tasks, tk_task) {
+-                      const char *rpc_waitq = "none"; 
+-
+-                      if (RPC_IS_QUEUED(t))
+-                              rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
+-
+-                      printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
+-                              t->tk_pid,
+-                              (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
+-                              t->tk_flags, t->tk_status,
+-                              t->tk_client,
+-                              (t->tk_client ? t->tk_client->cl_prog : 0),
+-                              t->tk_rqstp, t->tk_timeout,
+-                              rpc_waitq,
+-                              t->tk_action, t->tk_ops);
+-              }
+-              spin_unlock(&clnt->cl_lock);
+-      }
+-out:
+-      spin_unlock(&rpc_client_lock);
+-}
+-#endif
+diff -Nurb linux-2.6.22-590/net/sunrpc/rpc_pipe.c linux-2.6.22-570/net/sunrpc/rpc_pipe.c
+--- linux-2.6.22-590/net/sunrpc/rpc_pipe.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/rpc_pipe.c     2007-07-08 19:32:17.000000000 -0400
 @@ -14,7 +14,7 @@
  #include <linux/pagemap.h>
  #include <linux/mount.h>
  #include <linux/namei.h>
--#include <linux/dnotify.h>
-+#include <linux/fsnotify.h>
+-#include <linux/fsnotify.h>
++#include <linux/dnotify.h>
  #include <linux/kernel.h>
  
  #include <asm/ioctls.h>
@@ -202016,674 +202206,675 @@ diff -Nurb linux-2.6.22-570/net/sunrpc/rpc_pipe.c linux-2.6.22-590/net/sunrpc/rp
                mutex_lock(&inode->i_mutex);
                clnt = RPC_I(inode)->private;
                if (clnt) {
--                      atomic_inc(&clnt->cl_users);
-+                      kref_get(&clnt->cl_kref);
+-                      kref_get(&clnt->cl_kref);
++                      atomic_inc(&clnt->cl_users);
                        m->private = clnt;
                } else {
                        single_release(inode, file);
-@@ -448,6 +448,15 @@
+@@ -448,15 +448,6 @@
        simple_release_fs(&rpc_mount, &rpc_mount_count);
  }
  
-+static int rpc_delete_dentry(struct dentry *dentry)
-+{
-+      return 1;
-+}
-+
-+static struct dentry_operations rpc_dentry_operations = {
-+      .d_delete = rpc_delete_dentry,
-+};
-+
+-static int rpc_delete_dentry(struct dentry *dentry)
+-{
+-      return 1;
+-}
+-
+-static struct dentry_operations rpc_dentry_operations = {
+-      .d_delete = rpc_delete_dentry,
+-};
+-
  static int
  rpc_lookup_parent(char *path, struct nameidata *nd)
  {
-@@ -506,7 +515,7 @@
+@@ -515,7 +506,7 @@
   * FIXME: This probably has races.
   */
  static void
--rpc_depopulate(struct dentry *parent)
-+rpc_depopulate(struct dentry *parent, int start, int eof)
+-rpc_depopulate(struct dentry *parent, int start, int eof)
++rpc_depopulate(struct dentry *parent)
  {
        struct inode *dir = parent->d_inode;
        struct list_head *pos, *next;
-@@ -518,6 +527,10 @@
+@@ -527,10 +518,6 @@
        spin_lock(&dcache_lock);
        list_for_each_safe(pos, next, &parent->d_subdirs) {
                dentry = list_entry(pos, struct dentry, d_u.d_child);
-+              if (!dentry->d_inode ||
-+                              dentry->d_inode->i_ino < start ||
-+                              dentry->d_inode->i_ino >= eof)
-+                      continue;
+-              if (!dentry->d_inode ||
+-                              dentry->d_inode->i_ino < start ||
+-                              dentry->d_inode->i_ino >= eof)
+-                      continue;
                spin_lock(&dentry->d_lock);
                if (!d_unhashed(dentry)) {
                        dget_locked(dentry);
-@@ -533,11 +546,11 @@
+@@ -546,11 +533,11 @@
        if (n) {
                do {
                        dentry = dvec[--n];
--                      if (dentry->d_inode) {
--                              rpc_close_pipes(dentry->d_inode);
-+                      if (S_ISREG(dentry->d_inode->i_mode))
+-                      if (S_ISREG(dentry->d_inode->i_mode))
++                      if (dentry->d_inode) {
++                              rpc_close_pipes(dentry->d_inode);
                                simple_unlink(dir, dentry);
--                      }
--                      inode_dir_notify(dir, DN_DELETE);
-+                      else if (S_ISDIR(dentry->d_inode->i_mode)) 
-+                              simple_rmdir(dir, dentry);
-+                      d_delete(dentry);
+-                      else if (S_ISDIR(dentry->d_inode->i_mode)) 
+-                              simple_rmdir(dir, dentry);
+-                      d_delete(dentry);
++                      }
++                      inode_dir_notify(dir, DN_DELETE);
                        dput(dentry);
                } while (n);
                goto repeat;
-@@ -560,6 +573,7 @@
+@@ -573,7 +560,6 @@
                dentry = d_alloc_name(parent, files[i].name);
                if (!dentry)
                        goto out_bad;
-+              dentry->d_op = &rpc_dentry_operations;
+-              dentry->d_op = &rpc_dentry_operations;
                mode = files[i].mode;
                inode = rpc_get_inode(dir->i_sb, mode);
                if (!inode) {
-@@ -574,6 +588,7 @@
+@@ -588,7 +574,6 @@
                if (S_ISDIR(mode))
                        inc_nlink(dir);
                d_add(dentry, inode);
-+              fsnotify_create(dir, dentry);
+-              fsnotify_create(dir, dentry);
        }
        mutex_unlock(&dir->i_mutex);
        return 0;
-@@ -595,7 +610,7 @@
+@@ -610,7 +595,7 @@
        inode->i_ino = iunique(dir->i_sb, 100);
        d_instantiate(dentry, inode);
        inc_nlink(dir);
--      inode_dir_notify(dir, DN_CREATE);
-+      fsnotify_mkdir(dir, dentry);
+-      fsnotify_mkdir(dir, dentry);
++      inode_dir_notify(dir, DN_CREATE);
        return 0;
  out_err:
        printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n",
-@@ -607,21 +622,14 @@
+@@ -622,14 +607,21 @@
  __rpc_rmdir(struct inode *dir, struct dentry *dentry)
  {
        int error;
--
--      shrink_dcache_parent(dentry);
--      if (d_unhashed(dentry))
--              return 0;
--      if ((error = simple_rmdir(dir, dentry)) != 0)
-+      error = simple_rmdir(dir, dentry);
-+      if (!error)
-+              d_delete(dentry);
+-      error = simple_rmdir(dir, dentry);
+-      if (!error)
+-              d_delete(dentry);
++
++      shrink_dcache_parent(dentry);
++      if (d_unhashed(dentry))
++              return 0;
++      if ((error = simple_rmdir(dir, dentry)) != 0)
                return error;
--      if (!error) {
--              inode_dir_notify(dir, DN_DELETE);
--              d_drop(dentry);
--      }
--      return 0;
++      if (!error) {
++              inode_dir_notify(dir, DN_DELETE);
++              d_drop(dentry);
++      }
++      return 0;
  }
  
  static struct dentry *
--rpc_lookup_create(struct dentry *parent, const char *name, int len)
-+rpc_lookup_create(struct dentry *parent, const char *name, int len, int exclusive)
+-rpc_lookup_create(struct dentry *parent, const char *name, int len, int exclusive)
++rpc_lookup_create(struct dentry *parent, const char *name, int len)
  {
        struct inode *dir = parent->d_inode;
        struct dentry *dentry;
-@@ -630,7 +638,9 @@
+@@ -638,9 +630,7 @@
        dentry = lookup_one_len(name, parent, len);
        if (IS_ERR(dentry))
                goto out_err;
--      if (dentry->d_inode) {
-+      if (!dentry->d_inode)
-+              dentry->d_op = &rpc_dentry_operations;
-+      else if (exclusive) {
+-      if (!dentry->d_inode)
+-              dentry->d_op = &rpc_dentry_operations;
+-      else if (exclusive) {
++      if (dentry->d_inode) {
                dput(dentry);
                dentry = ERR_PTR(-EEXIST);
                goto out_err;
-@@ -649,7 +659,7 @@
+@@ -659,7 +649,7 @@
  
        if ((error = rpc_lookup_parent(path, nd)) != 0)
                return ERR_PTR(error);
--      dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len);
-+      dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len, 1);
+-      dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len, 1);
++      dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len);
        if (IS_ERR(dentry))
                rpc_release_path(nd);
        return dentry;
-@@ -681,7 +691,7 @@
+@@ -691,7 +681,7 @@
        rpc_release_path(&nd);
        return dentry;
  err_depopulate:
--      rpc_depopulate(dentry);
-+      rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
+-      rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
++      rpc_depopulate(dentry);
        __rpc_rmdir(dir, dentry);
  err_dput:
        dput(dentry);
-@@ -701,7 +711,7 @@
+@@ -711,7 +701,7 @@
        parent = dget_parent(dentry);
        dir = parent->d_inode;
        mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
--      rpc_depopulate(dentry);
-+      rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
+-      rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
++      rpc_depopulate(dentry);
        error = __rpc_rmdir(dir, dentry);
        dput(dentry);
        mutex_unlock(&dir->i_mutex);
-@@ -716,10 +726,21 @@
+@@ -726,21 +716,10 @@
        struct inode *dir, *inode;
        struct rpc_inode *rpci;
  
--      dentry = rpc_lookup_create(parent, name, strlen(name));
-+      dentry = rpc_lookup_create(parent, name, strlen(name), 0);
+-      dentry = rpc_lookup_create(parent, name, strlen(name), 0);
++      dentry = rpc_lookup_create(parent, name, strlen(name));
        if (IS_ERR(dentry))
                return dentry;
        dir = parent->d_inode;
-+      if (dentry->d_inode) {
-+              rpci = RPC_I(dentry->d_inode);
-+              if (rpci->private != private ||
-+                              rpci->ops != ops ||
-+                              rpci->flags != flags) {
-+                      dput (dentry);
-+                      dentry = ERR_PTR(-EBUSY);
-+              }
-+              rpci->nkern_readwriters++;
-+              goto out;
-+      }
+-      if (dentry->d_inode) {
+-              rpci = RPC_I(dentry->d_inode);
+-              if (rpci->private != private ||
+-                              rpci->ops != ops ||
+-                              rpci->flags != flags) {
+-                      dput (dentry);
+-                      dentry = ERR_PTR(-EBUSY);
+-              }
+-              rpci->nkern_readwriters++;
+-              goto out;
+-      }
        inode = rpc_get_inode(dir->i_sb, S_IFIFO | S_IRUSR | S_IWUSR);
        if (!inode)
                goto err_dput;
-@@ -730,7 +751,8 @@
+@@ -751,8 +730,7 @@
        rpci->private = private;
        rpci->flags = flags;
        rpci->ops = ops;
--      inode_dir_notify(dir, DN_CREATE);
-+      rpci->nkern_readwriters = 1;
-+      fsnotify_create(dir, dentry);
+-      rpci->nkern_readwriters = 1;
+-      fsnotify_create(dir, dentry);
++      inode_dir_notify(dir, DN_CREATE);
        dget(dentry);
  out:
        mutex_unlock(&dir->i_mutex);
-@@ -754,13 +776,11 @@
+@@ -776,11 +754,13 @@
        parent = dget_parent(dentry);
        dir = parent->d_inode;
        mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
--      if (!d_unhashed(dentry)) {
--              d_drop(dentry);
--              if (dentry->d_inode) {
-+      if (--RPC_I(dentry->d_inode)->nkern_readwriters == 0) {
+-      if (--RPC_I(dentry->d_inode)->nkern_readwriters == 0) {
++      if (!d_unhashed(dentry)) {
++              d_drop(dentry);
++              if (dentry->d_inode) {
                        rpc_close_pipes(dentry->d_inode);
                        error = simple_unlink(dir, dentry);
--              }
--              inode_dir_notify(dir, DN_DELETE);
-+              if (!error)
-+                      d_delete(dentry);
+-              if (!error)
+-                      d_delete(dentry);
++              }
++              inode_dir_notify(dir, DN_DELETE);
        }
        dput(dentry);
        mutex_unlock(&dir->i_mutex);
-@@ -833,6 +853,7 @@
+@@ -853,7 +833,6 @@
        rpci->nreaders = 0;
        rpci->nwriters = 0;
        INIT_LIST_HEAD(&rpci->in_upcall);
-+      INIT_LIST_HEAD(&rpci->in_downcall);
+-      INIT_LIST_HEAD(&rpci->in_downcall);
        INIT_LIST_HEAD(&rpci->pipe);
        rpci->pipelen = 0;
        init_waitqueue_head(&rpci->waitq);
-diff -Nurb linux-2.6.22-570/net/sunrpc/rpcb_clnt.c linux-2.6.22-590/net/sunrpc/rpcb_clnt.c
---- linux-2.6.22-570/net/sunrpc/rpcb_clnt.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sunrpc/rpcb_clnt.c    2008-01-02 13:56:38.000000000 -0500
-@@ -184,8 +184,7 @@
+diff -Nurb linux-2.6.22-590/net/sunrpc/rpcb_clnt.c linux-2.6.22-570/net/sunrpc/rpcb_clnt.c
+--- linux-2.6.22-590/net/sunrpc/rpcb_clnt.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/rpcb_clnt.c    2007-07-08 19:32:17.000000000 -0400
+@@ -184,7 +184,8 @@
                .program        = &rpcb_program,
                .version        = version,
                .authflavor     = RPC_AUTH_UNIX,
--              .flags          = (RPC_CLNT_CREATE_ONESHOT |
--                                 RPC_CLNT_CREATE_NOPING),
-+              .flags          = RPC_CLNT_CREATE_NOPING,
+-              .flags          = RPC_CLNT_CREATE_NOPING,
++              .flags          = (RPC_CLNT_CREATE_ONESHOT |
++                                 RPC_CLNT_CREATE_NOPING),
        };
  
        ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
-@@ -238,6 +237,7 @@
+@@ -237,7 +238,6 @@
  
        error = rpc_call_sync(rpcb_clnt, &msg, 0);
  
-+      rpc_shutdown_client(rpcb_clnt);
+-      rpc_shutdown_client(rpcb_clnt);
        if (error < 0)
                printk(KERN_WARNING "RPC: failed to contact local rpcbind "
                                "server (errno %d).\n", -error);
-@@ -286,6 +286,7 @@
+@@ -286,7 +286,6 @@
                return PTR_ERR(rpcb_clnt);
  
        status = rpc_call_sync(rpcb_clnt, &msg, 0);
-+      rpc_shutdown_client(rpcb_clnt);
+-      rpc_shutdown_client(rpcb_clnt);
  
        if (status >= 0) {
                if (map.r_port != 0)
-@@ -379,6 +380,7 @@
+@@ -380,7 +379,6 @@
        }
  
        child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map);
-+      rpc_release_client(rpcb_clnt);
+-      rpc_release_client(rpcb_clnt);
        if (IS_ERR(child)) {
                status = -EIO;
                dprintk("RPC: %5u rpcb_getport rpc_run_task failed\n",
-diff -Nurb linux-2.6.22-570/net/sunrpc/sched.c linux-2.6.22-590/net/sunrpc/sched.c
---- linux-2.6.22-570/net/sunrpc/sched.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sunrpc/sched.c        2008-01-02 13:56:38.000000000 -0500
-@@ -25,7 +25,6 @@
+diff -Nurb linux-2.6.22-590/net/sunrpc/sched.c linux-2.6.22-570/net/sunrpc/sched.c
+--- linux-2.6.22-590/net/sunrpc/sched.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/sched.c        2007-07-08 19:32:17.000000000 -0400
+@@ -25,6 +25,7 @@
  #ifdef RPC_DEBUG
  #define RPCDBG_FACILITY               RPCDBG_SCHED
  #define RPC_TASK_MAGIC_ID     0xf00baa
--static int                    rpc_task_id;
++static int                    rpc_task_id;
  #endif
  
  /*
-@@ -40,7 +39,6 @@
+@@ -39,6 +40,7 @@
  static mempool_t      *rpc_buffer_mempool __read_mostly;
  
  static void                   __rpc_default_timer(struct rpc_task *task);
--static void                   rpciod_killall(void);
++static void                   rpciod_killall(void);
  static void                   rpc_async_schedule(struct work_struct *);
  static void                    rpc_release_task(struct rpc_task *task);
  
-@@ -50,23 +48,13 @@
+@@ -48,13 +50,23 @@
  static RPC_WAITQ(delay_queue, "delayq");
  
  /*
-- * All RPC tasks are linked into this list
-- */
--static LIST_HEAD(all_tasks);
--
--/*
++ * All RPC tasks are linked into this list
++ */
++static LIST_HEAD(all_tasks);
++
++/*
   * rpciod-related stuff
   */
  static DEFINE_MUTEX(rpciod_mutex);
--static unsigned int           rpciod_users;
-+static atomic_t rpciod_users = ATOMIC_INIT(0);
+-static atomic_t rpciod_users = ATOMIC_INIT(0);
++static unsigned int           rpciod_users;
  struct workqueue_struct *rpciod_workqueue;
  
  /*
-- * Spinlock for other critical sections of code.
-- */
--static DEFINE_SPINLOCK(rpc_sched_lock);
--
--/*
++ * Spinlock for other critical sections of code.
++ */
++static DEFINE_SPINLOCK(rpc_sched_lock);
++
++/*
   * Disable the timer for a given RPC task. Should be called with
   * queue->lock and bh_disabled in order to avoid races within
   * rpc_run_timer().
-@@ -267,18 +255,33 @@
+@@ -255,33 +267,18 @@
        return 0;
  }
  
-+#ifdef RPC_DEBUG
-+static void rpc_task_set_debuginfo(struct rpc_task *task)
-+{
-+      static atomic_t rpc_pid;
-+
-+      task->tk_magic = RPC_TASK_MAGIC_ID;
-+      task->tk_pid = atomic_inc_return(&rpc_pid);
-+}
-+#else
-+static inline void rpc_task_set_debuginfo(struct rpc_task *task)
-+{
-+}
-+#endif
-+
+-#ifdef RPC_DEBUG
+-static void rpc_task_set_debuginfo(struct rpc_task *task)
+-{
+-      static atomic_t rpc_pid;
+-
+-      task->tk_magic = RPC_TASK_MAGIC_ID;
+-      task->tk_pid = atomic_inc_return(&rpc_pid);
+-}
+-#else
+-static inline void rpc_task_set_debuginfo(struct rpc_task *task)
+-{
+-}
+-#endif
+-
  static void rpc_set_active(struct rpc_task *task)
  {
-+      struct rpc_clnt *clnt;
+-      struct rpc_clnt *clnt;
        if (test_and_set_bit(RPC_TASK_ACTIVE, &task->tk_runstate) != 0)
                return;
--      spin_lock(&rpc_sched_lock);
--#ifdef RPC_DEBUG
--      task->tk_magic = RPC_TASK_MAGIC_ID;
--      task->tk_pid = rpc_task_id++;
--#endif
-+      rpc_task_set_debuginfo(task);
+-      rpc_task_set_debuginfo(task);
++      spin_lock(&rpc_sched_lock);
++#ifdef RPC_DEBUG
++      task->tk_magic = RPC_TASK_MAGIC_ID;
++      task->tk_pid = rpc_task_id++;
++#endif
        /* Add to global list of all tasks */
--      list_add_tail(&task->tk_task, &all_tasks);
--      spin_unlock(&rpc_sched_lock);
-+      clnt = task->tk_client;
-+      if (clnt != NULL) {
-+              spin_lock(&clnt->cl_lock);
-+              list_add_tail(&task->tk_task, &clnt->cl_tasks);
-+              spin_unlock(&clnt->cl_lock);
-+      }
+-      clnt = task->tk_client;
+-      if (clnt != NULL) {
+-              spin_lock(&clnt->cl_lock);
+-              list_add_tail(&task->tk_task, &clnt->cl_tasks);
+-              spin_unlock(&clnt->cl_lock);
+-      }
++      list_add_tail(&task->tk_task, &all_tasks);
++      spin_unlock(&rpc_sched_lock);
  }
  
  /*
-@@ -818,6 +821,7 @@
+@@ -821,7 +818,6 @@
        if (tk_ops->rpc_call_prepare != NULL)
                task->tk_action = rpc_prepare_task;
        task->tk_calldata = calldata;
-+      INIT_LIST_HEAD(&task->tk_task);
+-      INIT_LIST_HEAD(&task->tk_task);
  
        /* Initialize retry counters */
        task->tk_garb_retry = 2;
-@@ -830,7 +834,7 @@
+@@ -834,7 +830,7 @@
        task->tk_workqueue = rpciod_workqueue;
  
        if (clnt) {
--              atomic_inc(&clnt->cl_users);
-+              kref_get(&clnt->cl_kref);
+-              kref_get(&clnt->cl_kref);
++              atomic_inc(&clnt->cl_users);
                if (clnt->cl_softrtry)
                        task->tk_flags |= RPC_TASK_SOFT;
                if (!clnt->cl_intr)
-@@ -860,9 +864,7 @@
+@@ -864,7 +860,9 @@
  }
  
  /*
-- * Create a new task for the specified client.  We have to
-- * clean up after an allocation failure, as the client may
-- * have specified "oneshot".
-+ * Create a new task for the specified client.
+- * Create a new task for the specified client.
++ * Create a new task for the specified client.  We have to
++ * clean up after an allocation failure, as the client may
++ * have specified "oneshot".
   */
  struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata)
  {
-@@ -870,7 +872,7 @@
+@@ -872,7 +870,7 @@
  
        task = rpc_alloc_task();
        if (!task)
--              goto cleanup;
-+              goto out;
+-              goto out;
++              goto cleanup;
  
        rpc_init_task(task, clnt, flags, tk_ops, calldata);
  
-@@ -878,16 +880,6 @@
+@@ -880,6 +878,16 @@
        task->tk_flags |= RPC_TASK_DYNAMIC;
  out:
        return task;
--
--cleanup:
--      /* Check whether to release the client */
--      if (clnt) {
--              printk("rpc_new_task: failed, users=%d, oneshot=%d\n",
--                      atomic_read(&clnt->cl_users), clnt->cl_oneshot);
--              atomic_inc(&clnt->cl_users); /* pretend we were used ... */
--              rpc_release_client(clnt);
--      }
--      goto out;
++
++cleanup:
++      /* Check whether to release the client */
++      if (clnt) {
++              printk("rpc_new_task: failed, users=%d, oneshot=%d\n",
++                      atomic_read(&clnt->cl_users), clnt->cl_oneshot);
++              atomic_inc(&clnt->cl_users); /* pretend we were used ... */
++              rpc_release_client(clnt);
++      }
++      goto out;
  }
  
  
-@@ -920,11 +912,13 @@
+@@ -912,13 +920,11 @@
  #endif
        dprintk("RPC: %5u release task\n", task->tk_pid);
  
--      /* Remove from global task list */
--      spin_lock(&rpc_sched_lock);
-+      if (!list_empty(&task->tk_task)) {
-+              struct rpc_clnt *clnt = task->tk_client;
-+              /* Remove from client task list */
-+              spin_lock(&clnt->cl_lock);
+-      if (!list_empty(&task->tk_task)) {
+-              struct rpc_clnt *clnt = task->tk_client;
+-              /* Remove from client task list */
+-              spin_lock(&clnt->cl_lock);
++      /* Remove from global task list */
++      spin_lock(&rpc_sched_lock);
        list_del(&task->tk_task);
--      spin_unlock(&rpc_sched_lock);
--
-+              spin_unlock(&clnt->cl_lock); 
-+      }
+-              spin_unlock(&clnt->cl_lock); 
+-      }
++      spin_unlock(&rpc_sched_lock);
++
        BUG_ON (RPC_IS_QUEUED(task));
  
        /* Synchronously delete any running timer */
-@@ -939,29 +933,6 @@
+@@ -933,6 +939,29 @@
        rpc_put_task(task);
  }
  
--/**
-- * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
-- * @clnt: pointer to RPC client
-- * @flags: RPC flags
-- * @ops: RPC call ops
-- * @data: user call data
-- */
--struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
--                                      const struct rpc_call_ops *ops,
--                                      void *data)
--{
--      struct rpc_task *task;
--      task = rpc_new_task(clnt, flags, ops, data);
--      if (task == NULL) {
--              rpc_release_calldata(ops, data);
--              return ERR_PTR(-ENOMEM);
--      }
--      atomic_inc(&task->tk_count);
--      rpc_execute(task);
--      return task;
--}
--EXPORT_SYMBOL(rpc_run_task);
--
++/**
++ * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
++ * @clnt: pointer to RPC client
++ * @flags: RPC flags
++ * @ops: RPC call ops
++ * @data: user call data
++ */
++struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
++                                      const struct rpc_call_ops *ops,
++                                      void *data)
++{
++      struct rpc_task *task;
++      task = rpc_new_task(clnt, flags, ops, data);
++      if (task == NULL) {
++              rpc_release_calldata(ops, data);
++              return ERR_PTR(-ENOMEM);
++      }
++      atomic_inc(&task->tk_count);
++      rpc_execute(task);
++      return task;
++}
++EXPORT_SYMBOL(rpc_run_task);
++
  /*
   * Kill all tasks for the given client.
   * XXX: kill their descendants as well?
-@@ -969,44 +940,25 @@
+@@ -940,25 +969,44 @@
  void rpc_killall_tasks(struct rpc_clnt *clnt)
  {
        struct rpc_task *rovr;
--      struct list_head *le;
++      struct list_head *le;
  
--      dprintk("RPC:       killing all tasks for client %p\n", clnt);
-+      if (list_empty(&clnt->cl_tasks))
-+              return;
-+      dprintk("RPC:       killing all tasks for client %p\n", clnt);
+-
+-      if (list_empty(&clnt->cl_tasks))
+-              return;
+       dprintk("RPC:       killing all tasks for client %p\n", clnt);
++
        /*
         * Spin lock all_tasks to prevent changes...
         */
--      spin_lock(&rpc_sched_lock);
--      alltask_for_each(rovr, le, &all_tasks) {
-+      spin_lock(&clnt->cl_lock);
-+      list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) {
+-      spin_lock(&clnt->cl_lock);
+-      list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) {
++      spin_lock(&rpc_sched_lock);
++      alltask_for_each(rovr, le, &all_tasks) {
                if (! RPC_IS_ACTIVATED(rovr))
                        continue;
--              if (!clnt || rovr->tk_client == clnt) {
-+              if (!(rovr->tk_flags & RPC_TASK_KILLED)) {
+-              if (!(rovr->tk_flags & RPC_TASK_KILLED)) {
++              if (!clnt || rovr->tk_client == clnt) {
                        rovr->tk_flags |= RPC_TASK_KILLED;
                        rpc_exit(rovr, -EIO);
                        rpc_wake_up_task(rovr);
                }
        }
--      spin_unlock(&rpc_sched_lock);
--}
--
--static void rpciod_killall(void)
--{
--      unsigned long flags;
--
--      while (!list_empty(&all_tasks)) {
--              clear_thread_flag(TIF_SIGPENDING);
--              rpc_killall_tasks(NULL);
--              flush_workqueue(rpciod_workqueue);
--              if (!list_empty(&all_tasks)) {
--                      dprintk("RPC:       rpciod_killall: waiting for tasks "
--                                      "to exit\n");
--                      yield();
--              }
--      }
--
--      spin_lock_irqsave(&current->sighand->siglock, flags);
--      recalc_sigpending();
--      spin_unlock_irqrestore(&current->sighand->siglock, flags);
-+      spin_unlock(&clnt->cl_lock);
+-      spin_unlock(&clnt->cl_lock);
++      spin_unlock(&rpc_sched_lock);
++}
++
++static void rpciod_killall(void)
++{
++      unsigned long flags;
++
++      while (!list_empty(&all_tasks)) {
++              clear_thread_flag(TIF_SIGPENDING);
++              rpc_killall_tasks(NULL);
++              flush_workqueue(rpciod_workqueue);
++              if (!list_empty(&all_tasks)) {
++                      dprintk("RPC:       rpciod_killall: waiting for tasks "
++                                      "to exit\n");
++                      yield();
++              }
++      }
++
++      spin_lock_irqsave(&current->sighand->siglock, flags);
++      recalc_sigpending();
++      spin_unlock_irqrestore(&current->sighand->siglock, flags);
  }
  
  /*
-@@ -1018,28 +970,27 @@
+@@ -970,27 +1018,28 @@
        struct workqueue_struct *wq;
        int error = 0;
  
-+      if (atomic_inc_not_zero(&rpciod_users))
-+              return 0;
-+
+-      if (atomic_inc_not_zero(&rpciod_users))
+-              return 0;
+-
        mutex_lock(&rpciod_mutex);
--      dprintk("RPC:       rpciod_up: users %u\n", rpciod_users);
--      rpciod_users++;
--      if (rpciod_workqueue)
--              goto out;
--      /*
--       * If there's no pid, we should be the first user.
--       */
--      if (rpciod_users > 1)
--              printk(KERN_WARNING "rpciod_up: no workqueue, %u users??\n", rpciod_users);
-+
-+      /* Guard against races with rpciod_down() */
-+      if (rpciod_workqueue != NULL)
-+              goto out_ok;
+-
+-      /* Guard against races with rpciod_down() */
+-      if (rpciod_workqueue != NULL)
+-              goto out_ok;
++      dprintk("RPC:       rpciod_up: users %u\n", rpciod_users);
++      rpciod_users++;
++      if (rpciod_workqueue)
++              goto out;
++      /*
++       * If there's no pid, we should be the first user.
++       */
++      if (rpciod_users > 1)
++              printk(KERN_WARNING "rpciod_up: no workqueue, %u users??\n", rpciod_users);
        /*
         * Create the rpciod thread and wait for it to start.
         */
-+      dprintk("RPC:       creating workqueue rpciod\n");
+-      dprintk("RPC:       creating workqueue rpciod\n");
        error = -ENOMEM;
        wq = create_workqueue("rpciod");
--      if (wq == NULL) {
--              printk(KERN_WARNING "rpciod_up: create workqueue failed, error=%d\n", error);
--              rpciod_users--;
-+      if (wq == NULL)
+-      if (wq == NULL)
++      if (wq == NULL) {
++              printk(KERN_WARNING "rpciod_up: create workqueue failed, error=%d\n", error);
++              rpciod_users--;
                goto out;
--      }
-+
+-
++      }
        rpciod_workqueue = wq;
        error = 0;
-+out_ok:
-+      atomic_inc(&rpciod_users);
+-out_ok:
+-      atomic_inc(&rpciod_users);
  out:
        mutex_unlock(&rpciod_mutex);
        return error;
-@@ -1048,58 +999,18 @@
+@@ -999,19 +1048,59 @@
  void
  rpciod_down(void)
  {
--      mutex_lock(&rpciod_mutex);
--      dprintk("RPC:       rpciod_down sema %u\n", rpciod_users);
--      if (rpciod_users) {
--              if (--rpciod_users)
--                      goto out;
--      } else
--              printk(KERN_WARNING "rpciod_down: no users??\n");
-+      if (!atomic_dec_and_test(&rpciod_users))
-+              return;
--      if (!rpciod_workqueue) {
--              dprintk("RPC:       rpciod_down: Nothing to do!\n");
--              goto out;
--      }
--      rpciod_killall();
-+      mutex_lock(&rpciod_mutex);
-+      dprintk("RPC:       destroying workqueue rpciod\n");
+-      if (!atomic_dec_and_test(&rpciod_users))
+-              return;
+-
+       mutex_lock(&rpciod_mutex);
+-      dprintk("RPC:       destroying workqueue rpciod\n");
++      dprintk("RPC:       rpciod_down sema %u\n", rpciod_users);
++      if (rpciod_users) {
++              if (--rpciod_users)
++                      goto out;
++      } else
++              printk(KERN_WARNING "rpciod_down: no users??\n");
++
++      if (!rpciod_workqueue) {
++              dprintk("RPC:       rpciod_down: Nothing to do!\n");
++              goto out;
++      }
++      rpciod_killall();
  
-+      if (atomic_read(&rpciod_users) == 0 && rpciod_workqueue != NULL) {
+-      if (atomic_read(&rpciod_users) == 0 && rpciod_workqueue != NULL) {
        destroy_workqueue(rpciod_workqueue);
        rpciod_workqueue = NULL;
-- out:
--      mutex_unlock(&rpciod_mutex);
--}
--
--#ifdef RPC_DEBUG
--void rpc_show_tasks(void)
--{
--      struct list_head *le;
--      struct rpc_task *t;
--
--      spin_lock(&rpc_sched_lock);
--      if (list_empty(&all_tasks)) {
--              spin_unlock(&rpc_sched_lock);
--              return;
 -      }
--      printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
--              "-rpcwait -action- ---ops--\n");
--      alltask_for_each(t, le, &all_tasks) {
--              const char *rpc_waitq = "none";
--
--              if (RPC_IS_QUEUED(t))
--                      rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
--
--              printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
--                      t->tk_pid,
--                      (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
--                      t->tk_flags, t->tk_status,
--                      t->tk_client,
--                      (t->tk_client ? t->tk_client->cl_prog : 0),
--                      t->tk_rqstp, t->tk_timeout,
--                      rpc_waitq,
--                      t->tk_action, t->tk_ops);
-       }
--      spin_unlock(&rpc_sched_lock);
-+      mutex_unlock(&rpciod_mutex);
++ out:
+       mutex_unlock(&rpciod_mutex);
  }
--#endif
  
++#ifdef RPC_DEBUG
++void rpc_show_tasks(void)
++{
++      struct list_head *le;
++      struct rpc_task *t;
++
++      spin_lock(&rpc_sched_lock);
++      if (list_empty(&all_tasks)) {
++              spin_unlock(&rpc_sched_lock);
++              return;
++      }
++      printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
++              "-rpcwait -action- ---ops--\n");
++      alltask_for_each(t, le, &all_tasks) {
++              const char *rpc_waitq = "none";
++
++              if (RPC_IS_QUEUED(t))
++                      rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
++
++              printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
++                      t->tk_pid,
++                      (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
++                      t->tk_flags, t->tk_status,
++                      t->tk_client,
++                      (t->tk_client ? t->tk_client->cl_prog : 0),
++                      t->tk_rqstp, t->tk_timeout,
++                      rpc_waitq,
++                      t->tk_action, t->tk_ops);
++      }
++      spin_unlock(&rpc_sched_lock);
++}
++#endif
++
  void
  rpc_destroy_mempool(void)
-diff -Nurb linux-2.6.22-570/net/sunrpc/stats.c linux-2.6.22-590/net/sunrpc/stats.c
---- linux-2.6.22-570/net/sunrpc/stats.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sunrpc/stats.c        2008-01-02 13:56:38.000000000 -0500
-@@ -21,6 +21,7 @@
+ {
+diff -Nurb linux-2.6.22-590/net/sunrpc/stats.c linux-2.6.22-570/net/sunrpc/stats.c
+--- linux-2.6.22-590/net/sunrpc/stats.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/stats.c        2007-07-08 19:32:17.000000000 -0400
+@@ -21,7 +21,6 @@
  #include <linux/sunrpc/clnt.h>
  #include <linux/sunrpc/svcsock.h>
  #include <linux/sunrpc/metrics.h>
-+#include <net/net_namespace.h>
+-#include <net/net_namespace.h>
  
  #define RPCDBG_FACILITY       RPCDBG_MISC
  
-@@ -265,7 +266,7 @@
+@@ -266,7 +265,7 @@
        dprintk("RPC:       registering /proc/net/rpc\n");
        if (!proc_net_rpc) {
                struct proc_dir_entry *ent;
--              ent = proc_mkdir("rpc", proc_net);
-+              ent = proc_mkdir("rpc", init_net.proc_net);
+-              ent = proc_mkdir("rpc", init_net.proc_net);
++              ent = proc_mkdir("rpc", proc_net);
                if (ent) {
                        ent->owner = THIS_MODULE;
                        proc_net_rpc = ent;
-@@ -279,7 +280,7 @@
+@@ -280,7 +279,7 @@
        dprintk("RPC:       unregistering /proc/net/rpc\n");
        if (proc_net_rpc) {
                proc_net_rpc = NULL;
--              remove_proc_entry("net/rpc", NULL);
-+              remove_proc_entry("rpc", init_net.proc_net);
+-              remove_proc_entry("rpc", init_net.proc_net);
++              remove_proc_entry("net/rpc", NULL);
        }
  }
  
-diff -Nurb linux-2.6.22-570/net/sunrpc/sunrpc_syms.c linux-2.6.22-590/net/sunrpc/sunrpc_syms.c
---- linux-2.6.22-570/net/sunrpc/sunrpc_syms.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sunrpc/sunrpc_syms.c  2008-01-02 13:56:38.000000000 -0500
-@@ -28,15 +28,11 @@
+diff -Nurb linux-2.6.22-590/net/sunrpc/sunrpc_syms.c linux-2.6.22-570/net/sunrpc/sunrpc_syms.c
+--- linux-2.6.22-590/net/sunrpc/sunrpc_syms.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/sunrpc_syms.c  2007-07-08 19:32:17.000000000 -0400
+@@ -28,11 +28,15 @@
  EXPORT_SYMBOL(rpc_sleep_on);
  EXPORT_SYMBOL(rpc_wake_up_next);
  EXPORT_SYMBOL(rpc_wake_up_task);
--EXPORT_SYMBOL(rpciod_down);
--EXPORT_SYMBOL(rpciod_up);
--EXPORT_SYMBOL(rpc_new_task);
++EXPORT_SYMBOL(rpciod_down);
++EXPORT_SYMBOL(rpciod_up);
++EXPORT_SYMBOL(rpc_new_task);
  EXPORT_SYMBOL(rpc_wake_up_status);
  
  /* RPC client functions */
  EXPORT_SYMBOL(rpc_clone_client);
  EXPORT_SYMBOL(rpc_bind_new_program);
--EXPORT_SYMBOL(rpc_destroy_client);
++EXPORT_SYMBOL(rpc_destroy_client);
  EXPORT_SYMBOL(rpc_shutdown_client);
  EXPORT_SYMBOL(rpc_killall_tasks);
  EXPORT_SYMBOL(rpc_call_sync);
-@@ -61,7 +57,7 @@
+@@ -57,7 +61,7 @@
  EXPORT_SYMBOL(rpcauth_create);
  EXPORT_SYMBOL(rpcauth_lookupcred);
  EXPORT_SYMBOL(rpcauth_lookup_credcache);
--EXPORT_SYMBOL(rpcauth_free_credcache);
-+EXPORT_SYMBOL(rpcauth_destroy_credcache);
+-EXPORT_SYMBOL(rpcauth_destroy_credcache);
++EXPORT_SYMBOL(rpcauth_free_credcache);
  EXPORT_SYMBOL(rpcauth_init_credcache);
  EXPORT_SYMBOL(put_rpccred);
  
-@@ -156,6 +152,7 @@
+@@ -152,7 +156,6 @@
        cache_register(&ip_map_cache);
        cache_register(&unix_gid_cache);
        init_socket_xprt();
-+      rpcauth_init_module();
+-      rpcauth_init_module();
  out:
        return err;
  }
-@@ -163,6 +160,7 @@
+@@ -160,7 +163,6 @@
  static void __exit
  cleanup_sunrpc(void)
  {
-+      rpcauth_remove_module();
+-      rpcauth_remove_module();
        cleanup_socket_xprt();
        unregister_rpc_pipefs();
        rpc_destroy_mempool();
-diff -Nurb linux-2.6.22-570/net/sunrpc/xprt.c linux-2.6.22-590/net/sunrpc/xprt.c
---- linux-2.6.22-570/net/sunrpc/xprt.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sunrpc/xprt.c 2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/net/sunrpc/xprt.c linux-2.6.22-570/net/sunrpc/xprt.c
+--- linux-2.6.22-590/net/sunrpc/xprt.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/xprt.c 2007-07-08 19:32:17.000000000 -0400
 @@ -127,7 +127,7 @@
                clear_bit(XPRT_LOCKED, &xprt->state);
                smp_mb__after_clear_bit();
        } else
--              schedule_work(&xprt->task_cleanup);
-+              queue_work(rpciod_workqueue, &xprt->task_cleanup);
+-              queue_work(rpciod_workqueue, &xprt->task_cleanup);
++              schedule_work(&xprt->task_cleanup);
  }
  
  /*
@@ -202691,170 +202882,170 @@ diff -Nurb linux-2.6.22-570/net/sunrpc/xprt.c linux-2.6.22-590/net/sunrpc/xprt.c
        if (xprt_connecting(xprt))
                xprt_release_write(xprt, NULL);
        else
--              schedule_work(&xprt->task_cleanup);
-+              queue_work(rpciod_workqueue, &xprt->task_cleanup);
+-              queue_work(rpciod_workqueue, &xprt->task_cleanup);
++              schedule_work(&xprt->task_cleanup);
        return;
  out_abort:
        spin_unlock(&xprt->transport_lock);
-diff -Nurb linux-2.6.22-570/net/sunrpc/xprtsock.c linux-2.6.22-590/net/sunrpc/xprtsock.c
---- linux-2.6.22-570/net/sunrpc/xprtsock.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sunrpc/xprtsock.c     2008-01-02 13:56:38.000000000 -0500
-@@ -653,8 +653,7 @@
+diff -Nurb linux-2.6.22-590/net/sunrpc/xprtsock.c linux-2.6.22-570/net/sunrpc/xprtsock.c
+--- linux-2.6.22-590/net/sunrpc/xprtsock.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sunrpc/xprtsock.c     2007-07-08 19:32:17.000000000 -0400
+@@ -653,7 +653,8 @@
  
        dprintk("RPC:       xs_destroy xprt %p\n", xprt);
  
--      cancel_delayed_work(&transport->connect_worker);
--      flush_scheduled_work();
-+      cancel_rearming_delayed_work(&transport->connect_worker);
+-      cancel_rearming_delayed_work(&transport->connect_worker);
++      cancel_delayed_work(&transport->connect_worker);
++      flush_scheduled_work();
  
        xprt_disconnect(xprt);
        xs_close(xprt);
-@@ -1001,7 +1000,7 @@
+@@ -1000,7 +1001,7 @@
                /* Try to schedule an autoclose RPC calls */
                set_bit(XPRT_CLOSE_WAIT, &xprt->state);
                if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
--                      schedule_work(&xprt->task_cleanup);
-+                      queue_work(rpciod_workqueue, &xprt->task_cleanup);
+-                      queue_work(rpciod_workqueue, &xprt->task_cleanup);
++                      schedule_work(&xprt->task_cleanup);
        default:
                xprt_disconnect(xprt);
        }
-@@ -1410,18 +1409,16 @@
+@@ -1409,16 +1410,18 @@
                dprintk("RPC:       xs_connect delayed xprt %p for %lu "
                                "seconds\n",
                                xprt, xprt->reestablish_timeout / HZ);
--              schedule_delayed_work(&transport->connect_worker,
-+              queue_delayed_work(rpciod_workqueue,
-+                                 &transport->connect_worker,
+-              queue_delayed_work(rpciod_workqueue,
+-                                 &transport->connect_worker,
++              schedule_delayed_work(&transport->connect_worker,
                                        xprt->reestablish_timeout);
                xprt->reestablish_timeout <<= 1;
                if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
                        xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
        } else {
                dprintk("RPC:       xs_connect scheduled xprt %p\n", xprt);
--              schedule_delayed_work(&transport->connect_worker, 0);
--
--              /* flush_scheduled_work can sleep... */
--              if (!RPC_IS_ASYNC(task))
--                      flush_scheduled_work();
-+              queue_delayed_work(rpciod_workqueue,
-+                                 &transport->connect_worker, 0);
+-              queue_delayed_work(rpciod_workqueue,
+-                                 &transport->connect_worker, 0);
++              schedule_delayed_work(&transport->connect_worker, 0);
++
++              /* flush_scheduled_work can sleep... */
++              if (!RPC_IS_ASYNC(task))
++                      flush_scheduled_work();
        }
  }
  
-diff -Nurb linux-2.6.22-570/net/sysctl_net.c linux-2.6.22-590/net/sysctl_net.c
---- linux-2.6.22-570/net/sysctl_net.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/sysctl_net.c  2008-01-02 13:56:38.000000000 -0500
-@@ -54,3 +54,31 @@
+diff -Nurb linux-2.6.22-590/net/sysctl_net.c linux-2.6.22-570/net/sysctl_net.c
+--- linux-2.6.22-590/net/sysctl_net.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/sysctl_net.c  2007-07-08 19:32:17.000000000 -0400
+@@ -54,31 +54,3 @@
  #endif
        { 0 },
  };
-+
-+struct ctl_table multi_net_table[] = {
-+      {
-+              .ctl_name       = NET_CORE,
-+              .procname       = "core",
-+              .mode           = 0555,
-+              .child          = multi_core_table,
-+      },
-+#ifdef CONFIG_INET
-+      {
-+              .ctl_name       = NET_IPV4,
-+              .procname       = "ipv4",
-+              .mode           = 0555,
-+              .child          = multi_ipv4_table,
-+      },
-+#endif
-+      {},
-+};
-+
-+struct ctl_table net_root_table[] = {
-+      {
-+              .ctl_name       = CTL_NET,
-+              .procname       = "net",
-+              .mode           = 0555,
-+              .child          = multi_net_table,
-+      },
-+      {},
-+};
-diff -Nurb linux-2.6.22-570/net/tipc/eth_media.c linux-2.6.22-590/net/tipc/eth_media.c
---- linux-2.6.22-570/net/tipc/eth_media.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/tipc/eth_media.c      2008-01-02 13:56:38.000000000 -0500
+-
+-struct ctl_table multi_net_table[] = {
+-      {
+-              .ctl_name       = NET_CORE,
+-              .procname       = "core",
+-              .mode           = 0555,
+-              .child          = multi_core_table,
+-      },
+-#ifdef CONFIG_INET
+-      {
+-              .ctl_name       = NET_IPV4,
+-              .procname       = "ipv4",
+-              .mode           = 0555,
+-              .child          = multi_ipv4_table,
+-      },
+-#endif
+-      {},
+-};
+-
+-struct ctl_table net_root_table[] = {
+-      {
+-              .ctl_name       = CTL_NET,
+-              .procname       = "net",
+-              .mode           = 0555,
+-              .child          = multi_net_table,
+-      },
+-      {},
+-};
+diff -Nurb linux-2.6.22-590/net/tipc/eth_media.c linux-2.6.22-570/net/tipc/eth_media.c
+--- linux-2.6.22-590/net/tipc/eth_media.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/tipc/eth_media.c      2007-07-08 19:32:17.000000000 -0400
 @@ -1,8 +1,8 @@
  /*
   * net/tipc/eth_media.c: Ethernet bearer support for TIPC
   *
-- * Copyright (c) 2001-2006, Ericsson AB
-- * Copyright (c) 2005-2006, Wind River Systems
-+ * Copyright (c) 2001-2007, Ericsson AB
-+ * Copyright (c) 2005-2007, Wind River Systems
+- * Copyright (c) 2001-2007, Ericsson AB
+- * Copyright (c) 2005-2007, Wind River Systems
++ * Copyright (c) 2001-2006, Ericsson AB
++ * Copyright (c) 2005-2006, Wind River Systems
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
-@@ -38,6 +38,7 @@
+@@ -38,7 +38,6 @@
  #include <net/tipc/tipc_bearer.h>
  #include <net/tipc/tipc_msg.h>
  #include <linux/netdevice.h>
-+#include <net/net_namespace.h>
+-#include <net/net_namespace.h>
  
  #define MAX_ETH_BEARERS               2
  #define ETH_LINK_PRIORITY     TIPC_DEF_LINK_PRI
-@@ -87,6 +88,9 @@
+@@ -88,9 +87,6 @@
  /**
   * recv_msg - handle incoming TIPC message from an Ethernet interface
   *
-+ * Accept only packets explicitly sent to this node, or broadcast packets;
-+ * ignores packets sent using Ethernet multicast, and traffic sent to other
-+ * nodes (which can happen if interface is running in promiscuous mode).
+- * Accept only packets explicitly sent to this node, or broadcast packets;
+- * ignores packets sent using Ethernet multicast, and traffic sent to other
+- * nodes (which can happen if interface is running in promiscuous mode).
   * Routine truncates any Ethernet padding/CRC appended to the message,
   * and ensures message size matches actual length
   */
-@@ -97,10 +101,13 @@
+@@ -101,13 +97,10 @@
        struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv;
        u32 size;
  
-+      if (dev->nd_net != &init_net) {
-+              kfree_skb(buf);
-+              return 0;
-+      }
-+
+-      if (dev->nd_net != &init_net) {
+-              kfree_skb(buf);
+-              return 0;
+-      }
+-
        if (likely(eb_ptr->bearer)) {
--             if (likely(!dev->promiscuity) ||
--                 !memcmp(skb_mac_header(buf), dev->dev_addr, ETH_ALEN) ||
--                 !memcmp(skb_mac_header(buf), dev->broadcast, ETH_ALEN)) {
-+              if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
+-              if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
++             if (likely(!dev->promiscuity) ||
++                 !memcmp(skb_mac_header(buf), dev->dev_addr, ETH_ALEN) ||
++                 !memcmp(skb_mac_header(buf), dev->broadcast, ETH_ALEN)) {
                        size = msg_size((struct tipc_msg *)buf->data);
                        skb_trim(buf, size);
                        if (likely(buf->len == size)) {
-@@ -128,7 +135,7 @@
+@@ -135,7 +128,7 @@
  
        /* Find device with specified name */
  
--      for_each_netdev(pdev){
-+      for_each_netdev(&init_net, pdev){
+-      for_each_netdev(&init_net, pdev){
++      for_each_netdev(pdev){
                if (!strncmp(pdev->name, driver_name, IFNAMSIZ)) {
                        dev = pdev;
                        break;
-@@ -191,6 +198,9 @@
+@@ -198,9 +191,6 @@
        struct eth_bearer *eb_ptr = &eth_bearers[0];
        struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
  
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
        while ((eb_ptr->dev != dev)) {
                if (++eb_ptr == stop)
                        return NOTIFY_DONE;     /* couldn't find device */
-diff -Nurb linux-2.6.22-570/net/tipc/link.c linux-2.6.22-590/net/tipc/link.c
---- linux-2.6.22-570/net/tipc/link.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/tipc/link.c   2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/net/tipc/link.c linux-2.6.22-570/net/tipc/link.c
+--- linux-2.6.22-590/net/tipc/link.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/tipc/link.c   2007-07-08 19:32:17.000000000 -0400
 @@ -1,8 +1,8 @@
  /*
   * net/tipc/link.c: TIPC link code
   *
-- * Copyright (c) 1996-2006, Ericsson AB
-- * Copyright (c) 2004-2006, Wind River Systems
-+ * Copyright (c) 1996-2007, Ericsson AB
-+ * Copyright (c) 2004-2007, Wind River Systems
+- * Copyright (c) 1996-2007, Ericsson AB
+- * Copyright (c) 2004-2007, Wind River Systems
++ * Copyright (c) 1996-2006, Ericsson AB
++ * Copyright (c) 2004-2006, Wind River Systems
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
@@ -202862,8 +203053,8 @@ diff -Nurb linux-2.6.22-570/net/tipc/link.c linux-2.6.22-590/net/tipc/link.c
         * (Must not hold any locks while building message.)
         */
  
--      res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt,
-+      res = msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt,
+-      res = msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt,
++      res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt,
                        !sender->user_port, &buf);
  
        read_lock_bh(&tipc_net_lock);
@@ -202871,8 +203062,8 @@ diff -Nurb linux-2.6.22-570/net/tipc/link.c linux-2.6.22-590/net/tipc/link.c
                if (likely(l_ptr)) {
                        if (likely(buf)) {
                                res = link_send_buf_fast(l_ptr, buf,
--                                                       &sender->max_pkt);
-+                                                       &sender->publ.max_pkt);
+-                                                       &sender->publ.max_pkt);
++                                                       &sender->max_pkt);
                                if (unlikely(res < 0))
                                        buf_discard(buf);
  exit:
@@ -202880,14 +203071,14 @@ diff -Nurb linux-2.6.22-570/net/tipc/link.c linux-2.6.22-590/net/tipc/link.c
                         * then re-try fast path or fragment the message
                         */
  
--                      sender->max_pkt = link_max_pkt(l_ptr);
-+                      sender->publ.max_pkt = link_max_pkt(l_ptr);
+-                      sender->publ.max_pkt = link_max_pkt(l_ptr);
++                      sender->max_pkt = link_max_pkt(l_ptr);
                        tipc_node_unlock(node);
                        read_unlock_bh(&tipc_net_lock);
  
  
--                      if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt)
-+                      if ((msg_hdr_sz(hdr) + res) <= sender->publ.max_pkt)
+-                      if ((msg_hdr_sz(hdr) + res) <= sender->publ.max_pkt)
++                      if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt)
                                goto again;
  
                        return link_send_sections_long(sender, msg_sect,
@@ -202895,8 +203086,8 @@ diff -Nurb linux-2.6.22-570/net/tipc/link.c linux-2.6.22-590/net/tipc/link.c
  
  again:
        fragm_no = 1;
--      max_pkt = sender->max_pkt - INT_H_SIZE;
-+      max_pkt = sender->publ.max_pkt - INT_H_SIZE;
+-      max_pkt = sender->publ.max_pkt - INT_H_SIZE;
++      max_pkt = sender->max_pkt - INT_H_SIZE;
                /* leave room for tunnel header in case of link changeover */
        fragm_sz = max_pkt - INT_H_SIZE;
                /* leave room for fragmentation header in each fragment */
@@ -202904,43 +203095,43 @@ diff -Nurb linux-2.6.22-570/net/tipc/link.c linux-2.6.22-590/net/tipc/link.c
                        goto reject;
                }
                if (link_max_pkt(l_ptr) < max_pkt) {
--                      sender->max_pkt = link_max_pkt(l_ptr);
-+                      sender->publ.max_pkt = link_max_pkt(l_ptr);
+-                      sender->publ.max_pkt = link_max_pkt(l_ptr);
++                      sender->max_pkt = link_max_pkt(l_ptr);
                        tipc_node_unlock(node);
                        for (; buf_chain; buf_chain = buf) {
                                buf = buf_chain->next;
-diff -Nurb linux-2.6.22-570/net/tipc/port.c linux-2.6.22-590/net/tipc/port.c
---- linux-2.6.22-570/net/tipc/port.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/tipc/port.c   2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/net/tipc/port.c linux-2.6.22-570/net/tipc/port.c
+--- linux-2.6.22-590/net/tipc/port.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/tipc/port.c   2007-07-08 19:32:17.000000000 -0400
 @@ -1,8 +1,8 @@
  /*
   * net/tipc/port.c: TIPC port code
   *
-- * Copyright (c) 1992-2006, Ericsson AB
-- * Copyright (c) 2004-2005, Wind River Systems
-+ * Copyright (c) 1992-2007, Ericsson AB
-+ * Copyright (c) 2004-2007, Wind River Systems
+- * Copyright (c) 1992-2007, Ericsson AB
+- * Copyright (c) 2004-2007, Wind River Systems
++ * Copyright (c) 1992-2006, Ericsson AB
++ * Copyright (c) 2004-2005, Wind River Systems
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
-@@ -239,6 +239,8 @@
+@@ -239,8 +239,6 @@
        }
  
        tipc_port_lock(ref);
-+      p_ptr->publ.usr_handle = usr_handle;
-+      p_ptr->publ.max_pkt = MAX_PKT_DEFAULT;
+-      p_ptr->publ.usr_handle = usr_handle;
+-      p_ptr->publ.max_pkt = MAX_PKT_DEFAULT;
        p_ptr->publ.ref = ref;
        msg = &p_ptr->publ.phdr;
        msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0);
-@@ -248,11 +250,9 @@
+@@ -250,9 +248,11 @@
        msg_set_importance(msg,importance);
        p_ptr->last_in_seqno = 41;
        p_ptr->sent = 1;
--      p_ptr->publ.usr_handle = usr_handle;
++      p_ptr->publ.usr_handle = usr_handle;
        INIT_LIST_HEAD(&p_ptr->wait_list);
        INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
        p_ptr->congested_link = NULL;
--      p_ptr->max_pkt = MAX_PKT_DEFAULT;
++      p_ptr->max_pkt = MAX_PKT_DEFAULT;
        p_ptr->dispatcher = dispatcher;
        p_ptr->wakeup = wakeup;
        p_ptr->user_port = NULL;
@@ -202948,2853 +203139,2853 @@ diff -Nurb linux-2.6.22-570/net/tipc/port.c linux-2.6.22-590/net/tipc/port.c
        res = TIPC_OK;
  exit:
        tipc_port_unlock(p_ptr);
--      p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref);
-+      p_ptr->publ.max_pkt = tipc_link_get_max_pkt(peer->node, ref);
+-      p_ptr->publ.max_pkt = tipc_link_get_max_pkt(peer->node, ref);
++      p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref);
        return res;
  }
  
-diff -Nurb linux-2.6.22-570/net/tipc/port.h linux-2.6.22-590/net/tipc/port.h
---- linux-2.6.22-570/net/tipc/port.h   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/tipc/port.h   2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/net/tipc/port.h linux-2.6.22-570/net/tipc/port.h
+--- linux-2.6.22-590/net/tipc/port.h   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/tipc/port.h   2007-07-08 19:32:17.000000000 -0400
 @@ -1,8 +1,8 @@
  /*
   * net/tipc/port.h: Include file for TIPC port code
   *
-- * Copyright (c) 1994-2006, Ericsson AB
-- * Copyright (c) 2004-2005, Wind River Systems
-+ * Copyright (c) 1994-2007, Ericsson AB
-+ * Copyright (c) 2004-2007, Wind River Systems
+- * Copyright (c) 1994-2007, Ericsson AB
+- * Copyright (c) 2004-2007, Wind River Systems
++ * Copyright (c) 1994-2006, Ericsson AB
++ * Copyright (c) 2004-2005, Wind River Systems
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
-@@ -81,7 +81,6 @@
+@@ -81,6 +81,7 @@
   * @acked:
   * @publications: list of publications for port
   * @pub_count: total # of publications port has made during its lifetime
-- * @max_pkt: maximum packet size "hint" used when building messages sent by port
++ * @max_pkt: maximum packet size "hint" used when building messages sent by port
   * @probing_state:
   * @probing_interval:
   * @last_in_seqno:
-@@ -102,7 +101,6 @@
+@@ -101,6 +102,7 @@
        u32 acked;
        struct list_head publications;
        u32 pub_count;
--      u32 max_pkt;
++      u32 max_pkt;
        u32 probing_state;
        u32 probing_interval;
        u32 last_in_seqno;
-diff -Nurb linux-2.6.22-570/net/tipc/socket.c linux-2.6.22-590/net/tipc/socket.c
---- linux-2.6.22-570/net/tipc/socket.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/tipc/socket.c 2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/net/tipc/socket.c linux-2.6.22-570/net/tipc/socket.c
+--- linux-2.6.22-590/net/tipc/socket.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/tipc/socket.c 2007-07-08 19:32:17.000000000 -0400
 @@ -1,8 +1,8 @@
  /*
   * net/tipc/socket.c: TIPC socket API
   *
-- * Copyright (c) 2001-2006, Ericsson AB
-- * Copyright (c) 2004-2006, Wind River Systems
-+ * Copyright (c) 2001-2007, Ericsson AB
-+ * Copyright (c) 2004-2007, Wind River Systems
+- * Copyright (c) 2001-2007, Ericsson AB
+- * Copyright (c) 2004-2007, Wind River Systems
++ * Copyright (c) 2001-2006, Ericsson AB
++ * Copyright (c) 2004-2006, Wind River Systems
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
-@@ -162,13 +162,16 @@
+@@ -162,16 +162,13 @@
   *
   * Returns 0 on success, errno otherwise
   */
--static int tipc_create(struct socket *sock, int protocol)
-+static int tipc_create(struct net *net, struct socket *sock, int protocol)
+-static int tipc_create(struct net *net, struct socket *sock, int protocol)
++static int tipc_create(struct socket *sock, int protocol)
  {
        struct tipc_sock *tsock;
        struct tipc_port *port;
        struct sock *sk;
        u32 ref;
  
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
-+
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
+-
        if (unlikely(protocol != 0))
                return -EPROTONOSUPPORT;
  
-@@ -198,7 +201,7 @@
+@@ -201,7 +198,7 @@
                return -EPROTOTYPE;
        }
  
--      sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1);
-+      sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto, 1);
+-      sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto, 1);
++      sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1);
        if (!sk) {
                tipc_deleteport(ref);
                return -ENOMEM;
-@@ -607,23 +610,24 @@
+@@ -610,24 +607,23 @@
  static int send_stream(struct kiocb *iocb, struct socket *sock,
                       struct msghdr *m, size_t total_len)
  {
-+      struct tipc_port *tport;
+-      struct tipc_port *tport;
        struct msghdr my_msg;
        struct iovec my_iov;
        struct iovec *curr_iov;
        int curr_iovlen;
        char __user *curr_start;
-+      u32 hdr_size;
+-      u32 hdr_size;
        int curr_left;
        int bytes_to_send;
        int bytes_sent;
        int res;
  
--      if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE))
--              return send_packet(iocb, sock, m, total_len);
--
--      /* Can only send large data streams if already connected */
-+      /* Handle special cases where there is no connection */
+-      /* Handle special cases where there is no connection */
++      if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE))
++              return send_packet(iocb, sock, m, total_len);
++
++      /* Can only send large data streams if already connected */
  
        if (unlikely(sock->state != SS_CONNECTED)) {
--              if (sock->state == SS_DISCONNECTING)
-+              if (sock->state == SS_UNCONNECTED)
-+                      return send_packet(iocb, sock, m, total_len);
-+              else if (sock->state == SS_DISCONNECTING)
+-              if (sock->state == SS_UNCONNECTED)
+-                      return send_packet(iocb, sock, m, total_len);
+-              else if (sock->state == SS_DISCONNECTING)
++              if (sock->state == SS_DISCONNECTING)
                        return -EPIPE;
                else
                        return -ENOTCONN;
-@@ -648,17 +652,25 @@
+@@ -652,25 +648,17 @@
        my_msg.msg_name = NULL;
        bytes_sent = 0;
  
-+      tport = tipc_sk(sock->sk)->p;
-+      hdr_size = msg_hdr_sz(&tport->phdr);
-+
+-      tport = tipc_sk(sock->sk)->p;
+-      hdr_size = msg_hdr_sz(&tport->phdr);
+-
        while (curr_iovlen--) {
                curr_start = curr_iov->iov_base;
                curr_left = curr_iov->iov_len;
  
                while (curr_left) {
--                      bytes_to_send = (curr_left < TIPC_MAX_USER_MSG_SIZE)
--                              ? curr_left : TIPC_MAX_USER_MSG_SIZE;
-+                      bytes_to_send = tport->max_pkt - hdr_size;
-+                      if (bytes_to_send > TIPC_MAX_USER_MSG_SIZE)
-+                              bytes_to_send = TIPC_MAX_USER_MSG_SIZE;
-+                      if (curr_left < bytes_to_send)
-+                              bytes_to_send = curr_left;
+-                      bytes_to_send = tport->max_pkt - hdr_size;
+-                      if (bytes_to_send > TIPC_MAX_USER_MSG_SIZE)
+-                              bytes_to_send = TIPC_MAX_USER_MSG_SIZE;
+-                      if (curr_left < bytes_to_send)
+-                              bytes_to_send = curr_left;
++                      bytes_to_send = (curr_left < TIPC_MAX_USER_MSG_SIZE)
++                              ? curr_left : TIPC_MAX_USER_MSG_SIZE;
                        my_iov.iov_base = curr_start;
                        my_iov.iov_len = bytes_to_send;
                        if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) {
--                              return bytes_sent ? bytes_sent : res;
-+                              if (bytes_sent != 0)
-+                                      res = bytes_sent;
-+                              return res;
+-                              if (bytes_sent != 0)
+-                                      res = bytes_sent;
+-                              return res;
++                              return bytes_sent ? bytes_sent : res;
                        }
                        curr_left -= bytes_to_send;
                        curr_start += bytes_to_send;
-@@ -1363,7 +1375,7 @@
+@@ -1375,7 +1363,7 @@
        }
        buf = skb_peek(&sock->sk->sk_receive_queue);
  
--      res = tipc_create(newsock, 0);
-+      res = tipc_create(sock->sk->sk_net, newsock, 0);
+-      res = tipc_create(sock->sk->sk_net, newsock, 0);
++      res = tipc_create(newsock, 0);
        if (!res) {
                struct tipc_sock *new_tsock = tipc_sk(newsock->sk);
                struct tipc_portid id;
-@@ -1600,33 +1612,6 @@
+@@ -1612,6 +1600,33 @@
  }
  
  /**
-- * Placeholders for non-implemented functionality
-- *
-- * Returns error code (POSIX-compliant where defined)
-- */
--
--static int ioctl(struct socket *s, u32 cmd, unsigned long arg)
--{
--      return -EINVAL;
--}
--
--static int no_mmap(struct file *file, struct socket *sock,
--                 struct vm_area_struct *vma)
--{
--      return -EINVAL;
--}
--static ssize_t no_sendpage(struct socket *sock, struct page *page,
--                         int offset, size_t size, int flags)
--{
--      return -EINVAL;
--}
--
--static int no_skpair(struct socket *s1, struct socket *s2)
--{
--      return -EOPNOTSUPP;
--}
--
--/**
++ * Placeholders for non-implemented functionality
++ *
++ * Returns error code (POSIX-compliant where defined)
++ */
++
++static int ioctl(struct socket *s, u32 cmd, unsigned long arg)
++{
++      return -EINVAL;
++}
++
++static int no_mmap(struct file *file, struct socket *sock,
++                 struct vm_area_struct *vma)
++{
++      return -EINVAL;
++}
++static ssize_t no_sendpage(struct socket *sock, struct page *page,
++                         int offset, size_t size, int flags)
++{
++      return -EINVAL;
++}
++
++static int no_skpair(struct socket *s1, struct socket *s2)
++{
++      return -EOPNOTSUPP;
++}
++
++/**
   * Protocol switches for the various types of TIPC sockets
   */
  
-@@ -1636,19 +1621,19 @@
+@@ -1621,19 +1636,19 @@
        .release        = release,
        .bind           = bind,
        .connect        = connect,
--      .socketpair     = no_skpair,
-+      .socketpair     = sock_no_socketpair,
+-      .socketpair     = sock_no_socketpair,
++      .socketpair     = no_skpair,
        .accept         = accept,
        .getname        = get_name,
        .poll           = poll,
--      .ioctl          = ioctl,
-+      .ioctl          = sock_no_ioctl,
+-      .ioctl          = sock_no_ioctl,
++      .ioctl          = ioctl,
        .listen         = listen,
        .shutdown       = shutdown,
        .setsockopt     = setsockopt,
        .getsockopt     = getsockopt,
        .sendmsg        = send_msg,
        .recvmsg        = recv_msg,
--      .mmap           = no_mmap,
--      .sendpage       = no_sendpage
-+        .mmap         = sock_no_mmap,
-+        .sendpage     = sock_no_sendpage
+-        .mmap         = sock_no_mmap,
+-        .sendpage     = sock_no_sendpage
++      .mmap           = no_mmap,
++      .sendpage       = no_sendpage
  };
  
  static struct proto_ops packet_ops = {
-@@ -1657,19 +1642,19 @@
+@@ -1642,19 +1657,19 @@
        .release        = release,
        .bind           = bind,
        .connect        = connect,
--      .socketpair     = no_skpair,
-+      .socketpair     = sock_no_socketpair,
+-      .socketpair     = sock_no_socketpair,
++      .socketpair     = no_skpair,
        .accept         = accept,
        .getname        = get_name,
        .poll           = poll,
--      .ioctl          = ioctl,
-+      .ioctl          = sock_no_ioctl,
+-      .ioctl          = sock_no_ioctl,
++      .ioctl          = ioctl,
        .listen         = listen,
        .shutdown       = shutdown,
        .setsockopt     = setsockopt,
        .getsockopt     = getsockopt,
        .sendmsg        = send_packet,
        .recvmsg        = recv_msg,
--      .mmap           = no_mmap,
--      .sendpage       = no_sendpage
-+        .mmap         = sock_no_mmap,
-+        .sendpage     = sock_no_sendpage
+-        .mmap         = sock_no_mmap,
+-        .sendpage     = sock_no_sendpage
++      .mmap           = no_mmap,
++      .sendpage       = no_sendpage
  };
  
  static struct proto_ops stream_ops = {
-@@ -1678,19 +1663,19 @@
+@@ -1663,19 +1678,19 @@
        .release        = release,
        .bind           = bind,
        .connect        = connect,
--      .socketpair     = no_skpair,
-+      .socketpair     = sock_no_socketpair,
+-      .socketpair     = sock_no_socketpair,
++      .socketpair     = no_skpair,
        .accept         = accept,
        .getname        = get_name,
        .poll           = poll,
--      .ioctl          = ioctl,
-+      .ioctl          = sock_no_ioctl,
+-      .ioctl          = sock_no_ioctl,
++      .ioctl          = ioctl,
        .listen         = listen,
        .shutdown       = shutdown,
        .setsockopt     = setsockopt,
        .getsockopt     = getsockopt,
        .sendmsg        = send_stream,
        .recvmsg        = recv_stream,
--      .mmap           = no_mmap,
--      .sendpage       = no_sendpage
-+        .mmap         = sock_no_mmap,
-+        .sendpage     = sock_no_sendpage
+-        .mmap         = sock_no_mmap,
+-        .sendpage     = sock_no_sendpage
++      .mmap           = no_mmap,
++      .sendpage       = no_sendpage
  };
  
  static struct net_proto_family tipc_family_ops = {
-diff -Nurb linux-2.6.22-570/net/unix/af_unix.c linux-2.6.22-590/net/unix/af_unix.c
---- linux-2.6.22-570/net/unix/af_unix.c        2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/unix/af_unix.c        2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/net/unix/af_unix.c linux-2.6.22-570/net/unix/af_unix.c
+--- linux-2.6.22-590/net/unix/af_unix.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/unix/af_unix.c        2008-01-23 19:16:05.000000000 -0500
 @@ -117,8 +117,8 @@
  #include <linux/security.h>
  #include <linux/vs_context.h>
  #include <linux/vs_limit.h>
-+#include <net/net_namespace.h>
+-#include <net/net_namespace.h>
  
--int sysctl_unix_max_dgram_qlen __read_mostly = 10;
++int sysctl_unix_max_dgram_qlen __read_mostly = 10;
  
  struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
  DEFINE_SPINLOCK(unix_table_lock);
-@@ -245,7 +245,8 @@
+@@ -245,8 +245,7 @@
        spin_unlock(&unix_table_lock);
  }
  
--static struct sock *__unix_find_socket_byname(struct sockaddr_un *sunname,
-+static struct sock *__unix_find_socket_byname(struct net *net,
-+                                            struct sockaddr_un *sunname,
+-static struct sock *__unix_find_socket_byname(struct net *net,
+-                                            struct sockaddr_un *sunname,
++static struct sock *__unix_find_socket_byname(struct sockaddr_un *sunname,
                                              int len, int type, unsigned hash)
  {
        struct sock *s;
-@@ -254,7 +255,7 @@
+@@ -255,7 +254,7 @@
        sk_for_each(s, node, &unix_socket_table[hash ^ type]) {
                struct unix_sock *u = unix_sk(s);
  
--              if (!nx_check(s->sk_nid, VS_WATCH_P | VS_IDENT))
-+              if (!nx_check(s->sk_nid, VS_WATCH_P | VS_IDENT) || (s->sk_net != net))
+-              if (!nx_check(s->sk_nid, VS_WATCH_P | VS_IDENT) || (s->sk_net != net))
++              if (!nx_check(s->sk_nid, VS_WATCH_P | VS_IDENT))
                        continue;
                if (u->addr->len == len &&
                    !memcmp(u->addr->name, sunname, len))
-@@ -265,21 +266,22 @@
+@@ -266,22 +265,21 @@
        return s;
  }
  
--static inline struct sock *unix_find_socket_byname(struct sockaddr_un *sunname,
-+static inline struct sock *unix_find_socket_byname(struct net *net,
-+                                                 struct sockaddr_un *sunname,
+-static inline struct sock *unix_find_socket_byname(struct net *net,
+-                                                 struct sockaddr_un *sunname,
++static inline struct sock *unix_find_socket_byname(struct sockaddr_un *sunname,
                                                   int len, int type,
                                                   unsigned hash)
  {
        struct sock *s;
  
        spin_lock(&unix_table_lock);
--      s = __unix_find_socket_byname(sunname, len, type, hash);
-+      s = __unix_find_socket_byname(net, sunname, len, type, hash);
+-      s = __unix_find_socket_byname(net, sunname, len, type, hash);
++      s = __unix_find_socket_byname(sunname, len, type, hash);
        if (s)
                sock_hold(s);
        spin_unlock(&unix_table_lock);
        return s;
  }
  
--static struct sock *unix_find_socket_byinode(struct inode *i)
-+static struct sock *unix_find_socket_byinode(struct net *net, struct inode *i)
+-static struct sock *unix_find_socket_byinode(struct net *net, struct inode *i)
++static struct sock *unix_find_socket_byinode(struct inode *i)
  {
        struct sock *s;
        struct hlist_node *node;
-@@ -289,6 +291,9 @@
+@@ -291,9 +289,6 @@
                    &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
                struct dentry *dentry = unix_sk(s)->dentry;
  
-+              if (s->sk_net != net)
-+                      continue;
-+
+-              if (s->sk_net != net)
+-                      continue;
+-
                if(dentry && dentry->d_inode == i)
                {
                        sock_hold(s);
-@@ -571,7 +576,7 @@
+@@ -576,7 +571,7 @@
   */
  static struct lock_class_key af_unix_sk_receive_queue_lock_key;
  
--static struct sock * unix_create1(struct socket *sock)
-+static struct sock * unix_create1(struct net *net, struct socket *sock)
+-static struct sock * unix_create1(struct net *net, struct socket *sock)
++static struct sock * unix_create1(struct socket *sock)
  {
        struct sock *sk = NULL;
        struct unix_sock *u;
-@@ -579,7 +584,7 @@
+@@ -584,7 +579,7 @@
        if (atomic_read(&unix_nr_socks) >= 2*get_max_files())
                goto out;
  
--      sk = sk_alloc(PF_UNIX, GFP_KERNEL, &unix_proto, 1);
-+      sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto, 1);
+-      sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto, 1);
++      sk = sk_alloc(PF_UNIX, GFP_KERNEL, &unix_proto, 1);
        if (!sk)
                goto out;
  
-@@ -590,7 +595,7 @@
+@@ -595,7 +590,7 @@
                                &af_unix_sk_receive_queue_lock_key);
  
        sk->sk_write_space      = unix_write_space;
--      sk->sk_max_ack_backlog  = sysctl_unix_max_dgram_qlen;
-+      sk->sk_max_ack_backlog  = net->sysctl_unix_max_dgram_qlen;
+-      sk->sk_max_ack_backlog  = net->sysctl_unix_max_dgram_qlen;
++      sk->sk_max_ack_backlog  = sysctl_unix_max_dgram_qlen;
        sk->sk_destruct         = unix_sock_destructor;
        u         = unix_sk(sk);
        u->dentry = NULL;
-@@ -604,7 +609,7 @@
+@@ -609,7 +604,7 @@
        return sk;
  }
  
--static int unix_create(struct socket *sock, int protocol)
-+static int unix_create(struct net *net, struct socket *sock, int protocol)
+-static int unix_create(struct net *net, struct socket *sock, int protocol)
++static int unix_create(struct socket *sock, int protocol)
  {
        if (protocol && protocol != PF_UNIX)
                return -EPROTONOSUPPORT;
-@@ -631,7 +636,7 @@
+@@ -636,7 +631,7 @@
                return -ESOCKTNOSUPPORT;
        }
  
--      return unix_create1(sock) ? 0 : -ENOMEM;
-+      return unix_create1(net, sock) ? 0 : -ENOMEM;
+-      return unix_create1(net, sock) ? 0 : -ENOMEM;
++      return unix_create1(sock) ? 0 : -ENOMEM;
  }
  
  static int unix_release(struct socket *sock)
-@@ -649,6 +654,7 @@
+@@ -654,7 +649,6 @@
  static int unix_autobind(struct socket *sock)
  {
        struct sock *sk = sock->sk;
-+      struct net *net = sk->sk_net;
+-      struct net *net = sk->sk_net;
        struct unix_sock *u = unix_sk(sk);
        static u32 ordernum = 1;
        struct unix_address * addr;
-@@ -675,7 +681,7 @@
+@@ -681,7 +675,7 @@
        spin_lock(&unix_table_lock);
        ordernum = (ordernum+1)&0xFFFFF;
  
--      if (__unix_find_socket_byname(addr->name, addr->len, sock->type,
-+      if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
+-      if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
++      if (__unix_find_socket_byname(addr->name, addr->len, sock->type,
                                      addr->hash)) {
                spin_unlock(&unix_table_lock);
                /* Sanity yield. It is unusual case, but yet... */
-@@ -695,7 +701,8 @@
+@@ -701,8 +695,7 @@
        return err;
  }
  
--static struct sock *unix_find_other(struct sockaddr_un *sunname, int len,
-+static struct sock *unix_find_other(struct net *net,
-+                                  struct sockaddr_un *sunname, int len,
+-static struct sock *unix_find_other(struct net *net,
+-                                  struct sockaddr_un *sunname, int len,
++static struct sock *unix_find_other(struct sockaddr_un *sunname, int len,
                                    int type, unsigned hash, int *error)
  {
        struct sock *u;
-@@ -713,7 +720,7 @@
+@@ -720,7 +713,7 @@
                err = -ECONNREFUSED;
                if (!S_ISSOCK(nd.dentry->d_inode->i_mode))
                        goto put_fail;
--              u=unix_find_socket_byinode(nd.dentry->d_inode);
-+              u=unix_find_socket_byinode(net, nd.dentry->d_inode);
+-              u=unix_find_socket_byinode(net, nd.dentry->d_inode);
++              u=unix_find_socket_byinode(nd.dentry->d_inode);
                if (!u)
                        goto put_fail;
  
-@@ -729,7 +736,7 @@
+@@ -736,7 +729,7 @@
                }
        } else {
                err = -ECONNREFUSED;
--              u=unix_find_socket_byname(sunname, len, type, hash);
-+              u=unix_find_socket_byname(net, sunname, len, type, hash);
+-              u=unix_find_socket_byname(net, sunname, len, type, hash);
++              u=unix_find_socket_byname(sunname, len, type, hash);
                if (u) {
                        struct dentry *dentry;
                        dentry = unix_sk(u)->dentry;
-@@ -751,6 +758,7 @@
+@@ -758,7 +751,6 @@
  static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
  {
        struct sock *sk = sock->sk;
-+      struct net *net = sk->sk_net;
+-      struct net *net = sk->sk_net;
        struct unix_sock *u = unix_sk(sk);
        struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
        struct dentry * dentry = NULL;
-@@ -825,7 +833,7 @@
+@@ -833,7 +825,7 @@
  
        if (!sunaddr->sun_path[0]) {
                err = -EADDRINUSE;
--              if (__unix_find_socket_byname(sunaddr, addr_len,
-+              if (__unix_find_socket_byname(net, sunaddr, addr_len,
+-              if (__unix_find_socket_byname(net, sunaddr, addr_len,
++              if (__unix_find_socket_byname(sunaddr, addr_len,
                                              sk->sk_type, hash)) {
                        unix_release_addr(addr);
                        goto out_unlock;
-@@ -891,6 +899,7 @@
+@@ -899,7 +891,6 @@
                              int alen, int flags)
  {
        struct sock *sk = sock->sk;
-+      struct net *net = sk->sk_net;
+-      struct net *net = sk->sk_net;
        struct sockaddr_un *sunaddr=(struct sockaddr_un*)addr;
        struct sock *other;
        unsigned hash;
-@@ -907,7 +916,7 @@
+@@ -916,7 +907,7 @@
                        goto out;
  
  restart:
--              other=unix_find_other(sunaddr, alen, sock->type, hash, &err);
-+              other=unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
+-              other=unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
++              other=unix_find_other(sunaddr, alen, sock->type, hash, &err);
                if (!other)
                        goto out;
  
-@@ -987,6 +996,7 @@
+@@ -996,7 +987,6 @@
  {
        struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
        struct sock *sk = sock->sk;
-+      struct net *net = sk->sk_net;
+-      struct net *net = sk->sk_net;
        struct unix_sock *u = unix_sk(sk), *newu, *otheru;
        struct sock *newsk = NULL;
        struct sock *other = NULL;
-@@ -1015,7 +1025,7 @@
+@@ -1025,7 +1015,7 @@
        err = -ENOMEM;
  
        /* create new sock for complete connection */
--      newsk = unix_create1(NULL);
-+      newsk = unix_create1(sk->sk_net, NULL);
+-      newsk = unix_create1(sk->sk_net, NULL);
++      newsk = unix_create1(NULL);
        if (newsk == NULL)
                goto out;
  
-@@ -1026,7 +1036,7 @@
+@@ -1036,7 +1026,7 @@
  
  restart:
        /*  Find listening sock. */
--      other = unix_find_other(sunaddr, addr_len, sk->sk_type, hash, &err);
-+      other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
+-      other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
++      other = unix_find_other(sunaddr, addr_len, sk->sk_type, hash, &err);
        if (!other)
                goto out;
  
-@@ -1305,6 +1315,7 @@
+@@ -1315,7 +1305,6 @@
  {
        struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
        struct sock *sk = sock->sk;
-+      struct net *net = sk->sk_net;
+-      struct net *net = sk->sk_net;
        struct unix_sock *u = unix_sk(sk);
        struct sockaddr_un *sunaddr=msg->msg_name;
        struct sock *other = NULL;
-@@ -1368,7 +1379,7 @@
+@@ -1379,7 +1368,7 @@
                if (sunaddr == NULL)
                        goto out_free;
  
--              other = unix_find_other(sunaddr, namelen, sk->sk_type,
-+              other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
+-              other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
++              other = unix_find_other(sunaddr, namelen, sk->sk_type,
                                        hash, &err);
                if (other==NULL)
                        goto out_free;
-@@ -1974,12 +1985,18 @@
+@@ -1985,18 +1974,12 @@
  
  
  #ifdef CONFIG_PROC_FS
--static struct sock *unix_seq_idx(int *iter, loff_t pos)
-+struct unix_iter_state {
-+      struct net *net;
-+      int i;
-+};
-+static struct sock *unix_seq_idx(struct unix_iter_state *iter, loff_t pos)
+-struct unix_iter_state {
+-      struct net *net;
+-      int i;
+-};
+-static struct sock *unix_seq_idx(struct unix_iter_state *iter, loff_t pos)
++static struct sock *unix_seq_idx(int *iter, loff_t pos)
  {
        loff_t off = 0;
        struct sock *s;
  
--      for (s = first_unix_socket(iter); s; s = next_unix_socket(iter, s)) {
-+      for (s = first_unix_socket(&iter->i); s; s = next_unix_socket(&iter->i, s)) {
-+              if (s->sk_net != iter->net)
-+                      continue;
+-      for (s = first_unix_socket(&iter->i); s; s = next_unix_socket(&iter->i, s)) {
+-              if (s->sk_net != iter->net)
+-                      continue;
++      for (s = first_unix_socket(iter); s; s = next_unix_socket(iter, s)) {
                if (off == pos)
                        return s;
                ++off;
-@@ -1990,17 +2007,24 @@
+@@ -2007,24 +1990,17 @@
  
  static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
  {
-+      struct unix_iter_state *iter = seq->private;
+-      struct unix_iter_state *iter = seq->private;
        spin_lock(&unix_table_lock);
--      return *pos ? unix_seq_idx(seq->private, *pos - 1) : ((void *) 1);
-+      return *pos ? unix_seq_idx(iter, *pos - 1) : ((void *) 1);
+-      return *pos ? unix_seq_idx(iter, *pos - 1) : ((void *) 1);
++      return *pos ? unix_seq_idx(seq->private, *pos - 1) : ((void *) 1);
  }
  
  static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
-+      struct unix_iter_state *iter = seq->private;
-+      struct sock *sk = v;
+-      struct unix_iter_state *iter = seq->private;
+-      struct sock *sk = v;
        ++*pos;
  
        if (v == (void *)1)
--              return first_unix_socket(seq->private);
--      return next_unix_socket(seq->private, v);
-+              sk = first_unix_socket(&iter->i);
-+      else
-+              sk = next_unix_socket(&iter->i, sk);
-+      while (sk && (sk->sk_net != iter->net))
-+              sk = next_unix_socket(&iter->i, sk);
-+      return sk;
+-              sk = first_unix_socket(&iter->i);
+-      else
+-              sk = next_unix_socket(&iter->i, sk);
+-      while (sk && (sk->sk_net != iter->net))
+-              sk = next_unix_socket(&iter->i, sk);
+-      return sk;
++              return first_unix_socket(seq->private);
++      return next_unix_socket(seq->private, v);
  }
  
  static void unix_seq_stop(struct seq_file *seq, void *v)
-@@ -2064,7 +2088,7 @@
+@@ -2088,7 +2064,7 @@
  {
        struct seq_file *seq;
        int rc = -ENOMEM;
--      int *iter = kmalloc(sizeof(int), GFP_KERNEL);
-+      struct unix_iter_state *iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+-      struct unix_iter_state *iter = kmalloc(sizeof(*iter), GFP_KERNEL);
++      int *iter = kmalloc(sizeof(int), GFP_KERNEL);
  
        if (!iter)
                goto out;
-@@ -2075,7 +2099,8 @@
+@@ -2099,8 +2075,7 @@
  
        seq          = file->private_data;
        seq->private = iter;
--      *iter = 0;
-+      iter->net = get_net(PROC_NET(inode));
-+      iter->i = 0;
+-      iter->net = get_net(PROC_NET(inode));
+-      iter->i = 0;
++      *iter = 0;
  out:
        return rc;
  out_kfree:
-@@ -2083,12 +2108,20 @@
+@@ -2108,20 +2083,12 @@
        goto out;
  }
  
-+static int unix_seq_release(struct inode *inode, struct file *file)
-+{
-+      struct seq_file *seq = file->private_data;
-+      struct unix_iter_state *iter = seq->private;
-+      put_net(iter->net);
-+      return seq_release_private(inode, file);
-+}
-+
+-static int unix_seq_release(struct inode *inode, struct file *file)
+-{
+-      struct seq_file *seq = file->private_data;
+-      struct unix_iter_state *iter = seq->private;
+-      put_net(iter->net);
+-      return seq_release_private(inode, file);
+-}
+-
  static const struct file_operations unix_seq_fops = {
        .owner          = THIS_MODULE,
        .open           = unix_seq_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
--      .release        = seq_release_private,
-+      .release        = unix_seq_release,
+-      .release        = unix_seq_release,
++      .release        = seq_release_private,
  };
  
  #endif
-@@ -2099,6 +2132,33 @@
+@@ -2132,33 +2099,6 @@
        .owner  = THIS_MODULE,
  };
  
-+
-+static int unix_net_init(struct net *net)
-+{
-+      int error = -ENOMEM;
-+
-+      net->sysctl_unix_max_dgram_qlen = 10;
-+#ifdef CONFIG_PROC_FS
-+      if (!proc_net_fops_create(net, "unix", 0, &unix_seq_fops))
-+              goto out;
-+#endif
-+      unix_sysctl_register(net);
-+      error = 0;
-+out:
-+      return 0;
-+}
-+
-+static void unix_net_exit(struct net *net)
-+{
-+      unix_sysctl_unregister(net);
-+      proc_net_remove(net, "unix");
-+}
-+
-+static struct pernet_operations unix_net_ops = {
-+      .init = unix_net_init,
-+      .exit = unix_net_exit,
-+};
-+
+-
+-static int unix_net_init(struct net *net)
+-{
+-      int error = -ENOMEM;
+-
+-      net->sysctl_unix_max_dgram_qlen = 10;
+-#ifdef CONFIG_PROC_FS
+-      if (!proc_net_fops_create(net, "unix", 0, &unix_seq_fops))
+-              goto out;
+-#endif
+-      unix_sysctl_register(net);
+-      error = 0;
+-out:
+-      return 0;
+-}
+-
+-static void unix_net_exit(struct net *net)
+-{
+-      unix_sysctl_unregister(net);
+-      proc_net_remove(net, "unix");
+-}
+-
+-static struct pernet_operations unix_net_ops = {
+-      .init = unix_net_init,
+-      .exit = unix_net_exit,
+-};
+-
  static int __init af_unix_init(void)
  {
        int rc = -1;
-@@ -2114,10 +2174,7 @@
+@@ -2174,7 +2114,10 @@
        }
  
        sock_register(&unix_family_ops);
--#ifdef CONFIG_PROC_FS
--      proc_net_fops_create("unix", 0, &unix_seq_fops);
--#endif
--      unix_sysctl_register();
-+      register_pernet_subsys(&unix_net_ops);
+-      register_pernet_subsys(&unix_net_ops);
++#ifdef CONFIG_PROC_FS
++      proc_net_fops_create("unix", 0, &unix_seq_fops);
++#endif
++      unix_sysctl_register();
  out:
        return rc;
  }
-@@ -2125,9 +2182,8 @@
+@@ -2182,8 +2125,9 @@
  static void __exit af_unix_exit(void)
  {
        sock_unregister(PF_UNIX);
--      unix_sysctl_unregister();
--      proc_net_remove("unix");
++      unix_sysctl_unregister();
++      proc_net_remove("unix");
        proto_unregister(&unix_proto);
-+      unregister_pernet_subsys(&unix_net_ops);
+-      unregister_pernet_subsys(&unix_net_ops);
  }
  
  module_init(af_unix_init);
-diff -Nurb linux-2.6.22-570/net/unix/sysctl_net_unix.c linux-2.6.22-590/net/unix/sysctl_net_unix.c
---- linux-2.6.22-570/net/unix/sysctl_net_unix.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/unix/sysctl_net_unix.c        2008-01-02 13:56:38.000000000 -0500
-@@ -14,47 +14,71 @@
+diff -Nurb linux-2.6.22-590/net/unix/sysctl_net_unix.c linux-2.6.22-570/net/unix/sysctl_net_unix.c
+--- linux-2.6.22-590/net/unix/sysctl_net_unix.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/unix/sysctl_net_unix.c        2007-07-08 19:32:17.000000000 -0400
+@@ -14,71 +14,47 @@
  
  #include <net/af_unix.h>
  
--static ctl_table unix_table[] = {
-+static struct unix_sysctl_table {
-+      struct ctl_table_header *sysctl_header;
-+      struct ctl_table        unix_table[2];
-+      struct ctl_table        unix_net_table[2];
-+      struct ctl_table        unix_root_table[2];
-+} unix_sysctl = {
-+      .unix_table = {
+-static struct unix_sysctl_table {
+-      struct ctl_table_header *sysctl_header;
+-      struct ctl_table        unix_table[2];
+-      struct ctl_table        unix_net_table[2];
+-      struct ctl_table        unix_root_table[2];
+-} unix_sysctl = {
+-      .unix_table = {
++static ctl_table unix_table[] = {
        {
                .ctl_name       = NET_UNIX_MAX_DGRAM_QLEN,
                .procname       = "max_dgram_qlen",
--              .data           = &sysctl_unix_max_dgram_qlen,
-+                      .data           = &init_net.sysctl_unix_max_dgram_qlen,
+-                      .data           = &init_net.sysctl_unix_max_dgram_qlen,
++              .data           = &sysctl_unix_max_dgram_qlen,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = &proc_dointvec
        },
--      { .ctl_name = 0 }
--};
--
--static ctl_table unix_net_table[] = {
-+              {}
-+      },
-+      .unix_net_table = {
+-              {}
+-      },
+-      .unix_net_table = {
++      { .ctl_name = 0 }
++};
++
++static ctl_table unix_net_table[] = {
        {
                .ctl_name       = NET_UNIX,
                .procname       = "unix",
                .mode           = 0555,
--              .child          = unix_table
-+                      .child          = unix_sysctl.unix_table
+-                      .child          = unix_sysctl.unix_table
+-      },
+-              {}
++              .child          = unix_table
        },
--      { .ctl_name = 0 }
--};
--
--static ctl_table unix_root_table[] = {
-+              {}
-+      },
-+      .unix_root_table = {
+-      .unix_root_table = {
++      { .ctl_name = 0 }
++};
++
++static ctl_table unix_root_table[] = {
        {
                .ctl_name       = CTL_NET,
                .procname       = "net",
                .mode           = 0555,
--              .child          = unix_net_table
-+                      .child          = unix_sysctl.unix_net_table
+-                      .child          = unix_sysctl.unix_net_table
++              .child          = unix_net_table
        },
--      { .ctl_name = 0 }
-+              {}
-+      }
+-              {}
+-      }
++      { .ctl_name = 0 }
  };
  
--static struct ctl_table_header * unix_sysctl_header;
+-void unix_sysctl_register(struct net *net)
+-{
+-      struct unix_sysctl_table *table;
+-      int i;
++static struct ctl_table_header * unix_sysctl_header;
+-      table = kmemdup(&unix_sysctl, sizeof(*table), GFP_KERNEL);
+-      if (!table)
+-              return;
+-      for (i = 0; i < ARRAY_SIZE(table->unix_table) - 1; i++)
+-              table->unix_table[i].data += (char *)net - (char *)&init_net;
 -
--void unix_sysctl_register(void)
-+void unix_sysctl_register(struct net *net)
- {
--      unix_sysctl_header = register_sysctl_table(unix_root_table);
-+      struct unix_sysctl_table *table;
-+      int i;
-+
-+      table = kmemdup(&unix_sysctl, sizeof(*table), GFP_KERNEL);
-+      if (!table)
-+              return;
-+      for (i = 0; i < ARRAY_SIZE(table->unix_table) - 1; i++)
-+              table->unix_table[i].data += (char *)net - (char *)&init_net;
-+
-+      table->unix_net_table[0].child = table->unix_table;
-+      table->unix_root_table[0].child = table->unix_net_table;
-+
-+      table->sysctl_header = 
-+              register_net_sysctl_table(net, table->unix_root_table);
-+      if (!table->sysctl_header) {
-+              kfree(table);
-+              return;
-+      }
-+      net->unix_sysctl = table;
+-      table->unix_net_table[0].child = table->unix_table;
+-      table->unix_root_table[0].child = table->unix_net_table;
+-
+-      table->sysctl_header = 
+-              register_net_sysctl_table(net, table->unix_root_table);
+-      if (!table->sysctl_header) {
+-              kfree(table);
+-              return;
+-      }
+-      net->unix_sysctl = table;
++void unix_sysctl_register(void)
++{
++      unix_sysctl_header = register_sysctl_table(unix_root_table);
  }
  
--void unix_sysctl_unregister(void)
-+void unix_sysctl_unregister(struct net *net)
+-void unix_sysctl_unregister(struct net *net)
++void unix_sysctl_unregister(void)
  {
--      unregister_sysctl_table(unix_sysctl_header);
-+      struct unix_sysctl_table *table = net->unix_sysctl;
-+      if (table)
-+              unregister_net_sysctl_table(table->sysctl_header);
-+      kfree(table);
+-      struct unix_sysctl_table *table = net->unix_sysctl;
+-      if (table)
+-              unregister_net_sysctl_table(table->sysctl_header);
+-      kfree(table);
++      unregister_sysctl_table(unix_sysctl_header);
  }
  
-diff -Nurb linux-2.6.22-570/net/wanrouter/wanproc.c linux-2.6.22-590/net/wanrouter/wanproc.c
---- linux-2.6.22-570/net/wanrouter/wanproc.c   2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/wanrouter/wanproc.c   2008-01-02 13:56:38.000000000 -0500
-@@ -28,6 +28,7 @@
+diff -Nurb linux-2.6.22-590/net/wanrouter/wanproc.c linux-2.6.22-570/net/wanrouter/wanproc.c
+--- linux-2.6.22-590/net/wanrouter/wanproc.c   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/wanrouter/wanproc.c   2007-07-08 19:32:17.000000000 -0400
+@@ -28,7 +28,6 @@
  #include <linux/wanrouter.h>  /* WAN router API definitions */
  #include <linux/seq_file.h>
  #include <linux/smp_lock.h>
-+#include <net/net_namespace.h>
+-#include <net/net_namespace.h>
  
  #include <asm/io.h>
  
-@@ -287,7 +288,7 @@
+@@ -288,7 +287,7 @@
  int __init wanrouter_proc_init(void)
  {
        struct proc_dir_entry *p;
--      proc_router = proc_mkdir(ROUTER_NAME, proc_net);
-+      proc_router = proc_mkdir(ROUTER_NAME, init_net.proc_net);
+-      proc_router = proc_mkdir(ROUTER_NAME, init_net.proc_net);
++      proc_router = proc_mkdir(ROUTER_NAME, proc_net);
        if (!proc_router)
                goto fail;
  
-@@ -303,7 +304,7 @@
+@@ -304,7 +303,7 @@
  fail_stat:
        remove_proc_entry("config", proc_router);
  fail_config:
--      remove_proc_entry(ROUTER_NAME, proc_net);
-+      remove_proc_entry(ROUTER_NAME, init_net.proc_net);
+-      remove_proc_entry(ROUTER_NAME, init_net.proc_net);
++      remove_proc_entry(ROUTER_NAME, proc_net);
  fail:
        return -ENOMEM;
  }
-@@ -316,7 +317,7 @@
+@@ -317,7 +316,7 @@
  {
        remove_proc_entry("config", proc_router);
        remove_proc_entry("status", proc_router);
--      remove_proc_entry(ROUTER_NAME, proc_net);
-+      remove_proc_entry(ROUTER_NAME, init_net.proc_net);
+-      remove_proc_entry(ROUTER_NAME, init_net.proc_net);
++      remove_proc_entry(ROUTER_NAME, proc_net);
  }
  
  /*
-diff -Nurb linux-2.6.22-570/net/wireless/wext.c linux-2.6.22-590/net/wireless/wext.c
---- linux-2.6.22-570/net/wireless/wext.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/wireless/wext.c       2008-01-02 13:56:38.000000000 -0500
-@@ -95,6 +95,7 @@
+diff -Nurb linux-2.6.22-590/net/wireless/wext.c linux-2.6.22-570/net/wireless/wext.c
+--- linux-2.6.22-590/net/wireless/wext.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/wireless/wext.c       2007-07-08 19:32:17.000000000 -0400
+@@ -95,7 +95,6 @@
  #include <linux/interrupt.h>
  
  #include <linux/wireless.h>           /* Pretty obvious */
-+#include <net/net_namespace.h>
+-#include <net/net_namespace.h>
  #include <net/iw_handler.h>           /* New driver API */
  #include <net/netlink.h>
  #include <net/wext.h>
-@@ -672,7 +673,22 @@
+@@ -673,22 +672,7 @@
  
  static int wireless_seq_open(struct inode *inode, struct file *file)
  {
--      return seq_open(file, &wireless_seq_ops);
-+      struct seq_file *seq;
-+      int res;
-+      res = seq_open(file, &wireless_seq_ops);
-+      if (!res) {
-+              seq = file->private_data;
-+              seq->private = get_net(PROC_NET(inode));
-+      }
-+      return res;
-+}
-+
-+static int wireless_seq_release(struct inode *inode, struct file *file)
-+{
-+      struct seq_file *seq = file->private_data;
-+      struct net *net = seq->private;
-+      put_net(net);
-+      return seq_release(inode, file);
+-      struct seq_file *seq;
+-      int res;
+-      res = seq_open(file, &wireless_seq_ops);
+-      if (!res) {
+-              seq = file->private_data;
+-              seq->private = get_net(PROC_NET(inode));
+-      }
+-      return res;
+-}
+-
+-static int wireless_seq_release(struct inode *inode, struct file *file)
+-{
+-      struct seq_file *seq = file->private_data;
+-      struct net *net = seq->private;
+-      put_net(net);
+-      return seq_release(inode, file);
++      return seq_open(file, &wireless_seq_ops);
  }
  
  static const struct file_operations wireless_seq_fops = {
-@@ -680,17 +696,22 @@
+@@ -696,22 +680,17 @@
        .open    = wireless_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
--      .release = seq_release,
-+      .release = wireless_seq_release,
+-      .release = wireless_seq_release,
++      .release = seq_release,
  };
  
--int __init wext_proc_init(void)
-+int wext_proc_init(struct net *net)
+-int wext_proc_init(struct net *net)
++int __init wext_proc_init(void)
  {
        /* Create /proc/net/wireless entry */
--      if (!proc_net_fops_create("wireless", S_IRUGO, &wireless_seq_fops))
-+      if (!proc_net_fops_create(net, "wireless", S_IRUGO, &wireless_seq_fops))
+-      if (!proc_net_fops_create(net, "wireless", S_IRUGO, &wireless_seq_fops))
++      if (!proc_net_fops_create("wireless", S_IRUGO, &wireless_seq_fops))
                return -ENOMEM;
  
        return 0;
  }
-+
-+void wext_proc_exit(struct net *net)
-+{
-+      proc_net_remove(net, "wireless");
-+}
+-
+-void wext_proc_exit(struct net *net)
+-{
+-      proc_net_remove(net, "wireless");
+-}
  #endif        /* CONFIG_PROC_FS */
  
  /************************** IOCTL SUPPORT **************************/
-@@ -1010,7 +1031,7 @@
+@@ -1031,7 +1010,7 @@
   * Main IOCTl dispatcher.
   * Check the type of IOCTL and call the appropriate wrapper...
   */
--static int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
-+static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd)
+-static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd)
++static int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
  {
        struct net_device *dev;
        iw_handler      handler;
-@@ -1019,7 +1040,7 @@
+@@ -1040,7 +1019,7 @@
         * The copy_to/from_user() of ifr is also dealt with in there */
  
        /* Make sure the device exist */
--      if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL)
-+      if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL)
+-      if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL)
++      if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL)
                return -ENODEV;
  
        /* A bunch of special cases, then the generic case...
-@@ -1053,7 +1074,7 @@
+@@ -1074,7 +1053,7 @@
  }
  
  /* entry point from dev ioctl */
--int wext_handle_ioctl(struct ifreq *ifr, unsigned int cmd,
-+int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
+-int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
++int wext_handle_ioctl(struct ifreq *ifr, unsigned int cmd,
                      void __user *arg)
  {
        int ret;
-@@ -1065,9 +1086,9 @@
+@@ -1086,9 +1065,9 @@
            && !capable(CAP_NET_ADMIN))
                return -EPERM;
  
--      dev_load(ifr->ifr_name);
-+      dev_load(net, ifr->ifr_name);
+-      dev_load(net, ifr->ifr_name);
++      dev_load(ifr->ifr_name);
        rtnl_lock();
--      ret = wireless_process_ioctl(ifr, cmd);
-+      ret = wireless_process_ioctl(net, ifr, cmd);
+-      ret = wireless_process_ioctl(net, ifr, cmd);
++      ret = wireless_process_ioctl(ifr, cmd);
        rtnl_unlock();
        if (IW_IS_GET(cmd) && copy_to_user(arg, ifr, sizeof(struct ifreq)))
                return -EFAULT;
-@@ -1111,8 +1132,13 @@
+@@ -1132,13 +1111,8 @@
  {
        struct sk_buff *skb;
  
--      while ((skb = skb_dequeue(&wireless_nlevent_queue)))
--              rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
-+      while ((skb = skb_dequeue(&wireless_nlevent_queue))) {
-+              struct net_device *dev = skb->dev;
-+              struct net *net = dev->nd_net;
-+              skb->dev = NULL;
-+              rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
-+              dev_put(dev);
-+      }
+-      while ((skb = skb_dequeue(&wireless_nlevent_queue))) {
+-              struct net_device *dev = skb->dev;
+-              struct net *net = dev->nd_net;
+-              skb->dev = NULL;
+-              rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
+-              dev_put(dev);
+-      }
++      while ((skb = skb_dequeue(&wireless_nlevent_queue)))
++              rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
  }
  
  static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0);
-@@ -1173,6 +1199,9 @@
+@@ -1199,9 +1173,6 @@
                kfree_skb(skb);
                return;
        }
-+      /* Remember the device until we are in process context */
-+      dev_hold(dev);
-+      skb->dev = dev;
+-      /* Remember the device until we are in process context */
+-      dev_hold(dev);
+-      skb->dev = dev;
        NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
        skb_queue_tail(&wireless_nlevent_queue, skb);
        tasklet_schedule(&wireless_nlevent_tasklet);
-diff -Nurb linux-2.6.22-570/net/x25/af_x25.c linux-2.6.22-590/net/x25/af_x25.c
---- linux-2.6.22-570/net/x25/af_x25.c  2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/net/x25/af_x25.c  2008-01-02 13:56:38.000000000 -0500
-@@ -191,6 +191,9 @@
+diff -Nurb linux-2.6.22-590/net/x25/af_x25.c linux-2.6.22-570/net/x25/af_x25.c
+--- linux-2.6.22-590/net/x25/af_x25.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/x25/af_x25.c  2008-01-23 19:16:05.000000000 -0500
+@@ -191,9 +191,6 @@
        struct net_device *dev = ptr;
        struct x25_neigh *nb;
  
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
        if (dev->type == ARPHRD_X25
  #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
         || dev->type == ARPHRD_ETHER
-@@ -466,10 +469,10 @@
+@@ -469,10 +466,10 @@
        .obj_size = sizeof(struct x25_sock),
  };
  
--static struct sock *x25_alloc_socket(void)
-+static struct sock *x25_alloc_socket(struct net *net)
+-static struct sock *x25_alloc_socket(struct net *net)
++static struct sock *x25_alloc_socket(void)
  {
        struct x25_sock *x25;
--      struct sock *sk = sk_alloc(AF_X25, GFP_ATOMIC, &x25_proto, 1);
-+      struct sock *sk = sk_alloc(net, AF_X25, GFP_ATOMIC, &x25_proto, 1);
+-      struct sock *sk = sk_alloc(net, AF_X25, GFP_ATOMIC, &x25_proto, 1);
++      struct sock *sk = sk_alloc(AF_X25, GFP_ATOMIC, &x25_proto, 1);
  
        if (!sk)
                goto out;
-@@ -485,17 +488,20 @@
+@@ -488,20 +485,17 @@
        return sk;
  }
  
--static int x25_create(struct socket *sock, int protocol)
-+static int x25_create(struct net *net, struct socket *sock, int protocol)
+-static int x25_create(struct net *net, struct socket *sock, int protocol)
++static int x25_create(struct socket *sock, int protocol)
  {
        struct sock *sk;
        struct x25_sock *x25;
        int rc = -ESOCKTNOSUPPORT;
  
-+      if (net != &init_net)
-+              return -EAFNOSUPPORT;
-+
+-      if (net != &init_net)
+-              return -EAFNOSUPPORT;
+-
        if (sock->type != SOCK_SEQPACKET || protocol)
                goto out;
  
        rc = -ENOMEM;
--      if ((sk = x25_alloc_socket()) == NULL)
-+      if ((sk = x25_alloc_socket(net)) == NULL)
+-      if ((sk = x25_alloc_socket(net)) == NULL)
++      if ((sk = x25_alloc_socket()) == NULL)
                goto out;
  
        x25 = x25_sk(sk);
-@@ -546,7 +552,7 @@
+@@ -552,7 +546,7 @@
        if (osk->sk_type != SOCK_SEQPACKET)
                goto out;
  
--      if ((sk = x25_alloc_socket()) == NULL)
-+      if ((sk = x25_alloc_socket(osk->sk_net)) == NULL)
+-      if ((sk = x25_alloc_socket(osk->sk_net)) == NULL)
++      if ((sk = x25_alloc_socket()) == NULL)
                goto out;
  
        x25 = x25_sk(sk);
-diff -Nurb linux-2.6.22-570/net/x25/x25_dev.c linux-2.6.22-590/net/x25/x25_dev.c
---- linux-2.6.22-570/net/x25/x25_dev.c 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/x25/x25_dev.c 2008-01-02 13:56:38.000000000 -0500
-@@ -95,6 +95,9 @@
+diff -Nurb linux-2.6.22-590/net/x25/x25_dev.c linux-2.6.22-570/net/x25/x25_dev.c
+--- linux-2.6.22-590/net/x25/x25_dev.c 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/x25/x25_dev.c 2007-07-08 19:32:17.000000000 -0400
+@@ -95,9 +95,6 @@
        struct sk_buff *nskb;
        struct x25_neigh *nb;
  
-+      if (dev->nd_net != &init_net)
-+              goto drop;
-+
+-      if (dev->nd_net != &init_net)
+-              goto drop;
+-
        nskb = skb_copy(skb, GFP_ATOMIC);
        if (!nskb)
                goto drop;
-diff -Nurb linux-2.6.22-570/net/x25/x25_proc.c linux-2.6.22-590/net/x25/x25_proc.c
---- linux-2.6.22-570/net/x25/x25_proc.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/x25/x25_proc.c        2008-01-02 13:56:38.000000000 -0500
-@@ -20,6 +20,7 @@
+diff -Nurb linux-2.6.22-590/net/x25/x25_proc.c linux-2.6.22-570/net/x25/x25_proc.c
+--- linux-2.6.22-590/net/x25/x25_proc.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/x25/x25_proc.c        2007-07-08 19:32:17.000000000 -0400
+@@ -20,7 +20,6 @@
  #include <linux/init.h>
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
-+#include <net/net_namespace.h>
+-#include <net/net_namespace.h>
  #include <net/sock.h>
  #include <net/x25.h>
  
-@@ -301,7 +302,7 @@
+@@ -302,7 +301,7 @@
        struct proc_dir_entry *p;
        int rc = -ENOMEM;
  
--      x25_proc_dir = proc_mkdir("x25", proc_net);
-+      x25_proc_dir = proc_mkdir("x25", init_net.proc_net);
+-      x25_proc_dir = proc_mkdir("x25", init_net.proc_net);
++      x25_proc_dir = proc_mkdir("x25", proc_net);
        if (!x25_proc_dir)
                goto out;
  
-@@ -328,7 +329,7 @@
+@@ -329,7 +328,7 @@
  out_socket:
        remove_proc_entry("route", x25_proc_dir);
  out_route:
--      remove_proc_entry("x25", proc_net);
-+      remove_proc_entry("x25", init_net.proc_net);
+-      remove_proc_entry("x25", init_net.proc_net);
++      remove_proc_entry("x25", proc_net);
        goto out;
  }
  
-@@ -337,7 +338,7 @@
+@@ -338,7 +337,7 @@
        remove_proc_entry("forward", x25_proc_dir);
        remove_proc_entry("route", x25_proc_dir);
        remove_proc_entry("socket", x25_proc_dir);
--      remove_proc_entry("x25", proc_net);
-+      remove_proc_entry("x25", init_net.proc_net);
+-      remove_proc_entry("x25", init_net.proc_net);
++      remove_proc_entry("x25", proc_net);
  }
  
  #else /* CONFIG_PROC_FS */
-diff -Nurb linux-2.6.22-570/net/x25/x25_route.c linux-2.6.22-590/net/x25/x25_route.c
---- linux-2.6.22-570/net/x25/x25_route.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/x25/x25_route.c       2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/net/x25/x25_route.c linux-2.6.22-570/net/x25/x25_route.c
+--- linux-2.6.22-590/net/x25/x25_route.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/x25/x25_route.c       2007-07-08 19:32:17.000000000 -0400
 @@ -129,7 +129,7 @@
   */
  struct net_device *x25_dev_get(char *devname)
  {
--      struct net_device *dev = dev_get_by_name(devname);
-+      struct net_device *dev = dev_get_by_name(&init_net, devname);
+-      struct net_device *dev = dev_get_by_name(&init_net, devname);
++      struct net_device *dev = dev_get_by_name(devname);
  
        if (dev &&
            (!(dev->flags & IFF_UP) || (dev->type != ARPHRD_X25
-diff -Nurb linux-2.6.22-570/net/xfrm/xfrm_policy.c linux-2.6.22-590/net/xfrm/xfrm_policy.c
---- linux-2.6.22-570/net/xfrm/xfrm_policy.c    2008-01-02 13:56:22.000000000 -0500
-+++ linux-2.6.22-590/net/xfrm/xfrm_policy.c    2008-01-02 13:56:38.000000000 -0500
-@@ -30,8 +30,6 @@
+diff -Nurb linux-2.6.22-590/net/xfrm/xfrm_policy.c linux-2.6.22-570/net/xfrm/xfrm_policy.c
+--- linux-2.6.22-590/net/xfrm/xfrm_policy.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/xfrm/xfrm_policy.c    2008-01-23 19:15:56.000000000 -0500
+@@ -30,6 +30,8 @@
  
  #include "xfrm_hash.h"
  
--int sysctl_xfrm_larval_drop __read_mostly;
--
++int sysctl_xfrm_larval_drop __read_mostly;
++
  DEFINE_MUTEX(xfrm_cfg_mutex);
  EXPORT_SYMBOL(xfrm_cfg_mutex);
  
-@@ -1570,7 +1568,7 @@
+@@ -1568,7 +1570,7 @@
  
                if (unlikely(nx<0)) {
                        err = nx;
--                      if (err == -EAGAIN && sysctl_xfrm_larval_drop) {
-+                      if (err == -EAGAIN && init_net.sysctl_xfrm_larval_drop) {
+-                      if (err == -EAGAIN && init_net.sysctl_xfrm_larval_drop) {
++                      if (err == -EAGAIN && sysctl_xfrm_larval_drop) {
                                /* EREMOTE tells the caller to generate
                                 * a one-shot blackhole route.
                                 */
-@@ -1954,8 +1952,8 @@
+@@ -1952,8 +1954,8 @@
  void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
  {
        while ((dst = dst->child) && dst->xfrm && dst->dev == dev) {
--              dst->dev = &loopback_dev;
--              dev_hold(&loopback_dev);
-+              dst->dev = &init_net.loopback_dev;
-+              dev_hold(dst->dev);
+-              dst->dev = &init_net.loopback_dev;
+-              dev_hold(dst->dev);
++              dst->dev = &loopback_dev;
++              dev_hold(&loopback_dev);
                dev_put(dev);
        }
  }
-@@ -2357,6 +2355,11 @@
+@@ -2355,11 +2357,6 @@
  
  static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
  {
-+      struct net_device *dev = ptr;
-+
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
+-      struct net_device *dev = ptr;
+-
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
        switch (event) {
        case NETDEV_DOWN:
                xfrm_flush_bundles();
-diff -Nurb linux-2.6.22-570/net/xfrm/xfrm_state.c linux-2.6.22-590/net/xfrm/xfrm_state.c
---- linux-2.6.22-570/net/xfrm/xfrm_state.c     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/xfrm/xfrm_state.c     2008-01-02 13:56:38.000000000 -0500
-@@ -28,14 +28,6 @@
+diff -Nurb linux-2.6.22-590/net/xfrm/xfrm_state.c linux-2.6.22-570/net/xfrm/xfrm_state.c
+--- linux-2.6.22-590/net/xfrm/xfrm_state.c     2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/xfrm/xfrm_state.c     2007-07-08 19:32:17.000000000 -0400
+@@ -28,6 +28,14 @@
  struct sock *xfrm_nl;
  EXPORT_SYMBOL(xfrm_nl);
  
--u32 sysctl_xfrm_aevent_etime __read_mostly = XFRM_AE_ETIME;
--EXPORT_SYMBOL(sysctl_xfrm_aevent_etime);
--
--u32 sysctl_xfrm_aevent_rseqth __read_mostly = XFRM_AE_SEQT_SIZE;
--EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth);
--
--u32 sysctl_xfrm_acq_expires __read_mostly = 30;
--
++u32 sysctl_xfrm_aevent_etime __read_mostly = XFRM_AE_ETIME;
++EXPORT_SYMBOL(sysctl_xfrm_aevent_etime);
++
++u32 sysctl_xfrm_aevent_rseqth __read_mostly = XFRM_AE_SEQT_SIZE;
++EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth);
++
++u32 sysctl_xfrm_acq_expires __read_mostly = 30;
++
  /* Each xfrm_state may be linked to two tables:
  
     1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
-@@ -665,8 +657,8 @@
+@@ -657,8 +665,8 @@
                                h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family);
                                hlist_add_head(&x->byspi, xfrm_state_byspi+h);
                        }
--                      x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires;
--                      x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
-+                      x->lft.hard_add_expires_seconds = init_net.sysctl_xfrm_acq_expires;
-+                      x->timer.expires = jiffies + init_net.sysctl_xfrm_acq_expires*HZ;
+-                      x->lft.hard_add_expires_seconds = init_net.sysctl_xfrm_acq_expires;
+-                      x->timer.expires = jiffies + init_net.sysctl_xfrm_acq_expires*HZ;
++                      x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires;
++                      x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
                        add_timer(&x->timer);
                        xfrm_state_num++;
                        xfrm_hash_grow_check(x->bydst.next != NULL);
-@@ -815,9 +807,9 @@
+@@ -807,9 +815,9 @@
                x->props.family = family;
                x->props.mode = mode;
                x->props.reqid = reqid;
--              x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires;
-+              x->lft.hard_add_expires_seconds = init_net.sysctl_xfrm_acq_expires;
+-              x->lft.hard_add_expires_seconds = init_net.sysctl_xfrm_acq_expires;
++              x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires;
                xfrm_state_hold(x);
--              x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
-+              x->timer.expires = jiffies + init_net.sysctl_xfrm_acq_expires*HZ;
+-              x->timer.expires = jiffies + init_net.sysctl_xfrm_acq_expires*HZ;
++              x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
                add_timer(&x->timer);
                hlist_add_head(&x->bydst, xfrm_state_bydst+h);
                h = xfrm_src_hash(daddr, saddr, family);
-@@ -1775,6 +1767,19 @@
+@@ -1767,19 +1775,6 @@
  
  EXPORT_SYMBOL(xfrm_init_state);
  
-+
-+static int xfrm_state_pernet_init(struct net *net)
-+{
-+      net->sysctl_xfrm_aevent_etime = XFRM_AE_ETIME;
-+      net->sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE;
-+      net->sysctl_xfrm_acq_expires = 30;
-+      return 0;
-+}
-+
-+static struct pernet_operations xfrm_state_net_ops = {
-+      .init = xfrm_state_pernet_init,
-+};
-+
+-
+-static int xfrm_state_pernet_init(struct net *net)
+-{
+-      net->sysctl_xfrm_aevent_etime = XFRM_AE_ETIME;
+-      net->sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE;
+-      net->sysctl_xfrm_acq_expires = 30;
+-      return 0;
+-}
+-
+-static struct pernet_operations xfrm_state_net_ops = {
+-      .init = xfrm_state_pernet_init,
+-};
+-
  void __init xfrm_state_init(void)
  {
        unsigned int sz;
-@@ -1789,5 +1794,7 @@
+@@ -1794,7 +1789,5 @@
        xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1);
  
        INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task);
-+
-+      register_pernet_subsys(&xfrm_state_net_ops);
+-
+-      register_pernet_subsys(&xfrm_state_net_ops);
  }
  
-diff -Nurb linux-2.6.22-570/net/xfrm/xfrm_user.c linux-2.6.22-590/net/xfrm/xfrm_user.c
---- linux-2.6.22-570/net/xfrm/xfrm_user.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/net/xfrm/xfrm_user.c      2008-01-02 13:56:38.000000000 -0500
-@@ -374,7 +374,8 @@
+diff -Nurb linux-2.6.22-590/net/xfrm/xfrm_user.c linux-2.6.22-570/net/xfrm/xfrm_user.c
+--- linux-2.6.22-590/net/xfrm/xfrm_user.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/net/xfrm/xfrm_user.c      2007-07-08 19:32:17.000000000 -0400
+@@ -374,8 +374,7 @@
        return err;
  }
  
--static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
-+static struct xfrm_state *xfrm_state_construct(struct net *net,
-+                                             struct xfrm_usersa_info *p,
+-static struct xfrm_state *xfrm_state_construct(struct net *net,
+-                                             struct xfrm_usersa_info *p,
++static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
                                               struct rtattr **xfrma,
                                               int *errp)
  {
-@@ -410,9 +411,9 @@
+@@ -411,9 +410,9 @@
                goto error;
  
        x->km.seq = p->seq;
--      x->replay_maxdiff = sysctl_xfrm_aevent_rseqth;
-+      x->replay_maxdiff = net->sysctl_xfrm_aevent_rseqth;
+-      x->replay_maxdiff = net->sysctl_xfrm_aevent_rseqth;
++      x->replay_maxdiff = sysctl_xfrm_aevent_rseqth;
        /* sysctl_xfrm_aevent_etime is in 100ms units */
--      x->replay_maxage = (sysctl_xfrm_aevent_etime*HZ)/XFRM_AE_ETH_M;
-+      x->replay_maxage = (net->sysctl_xfrm_aevent_etime*HZ)/XFRM_AE_ETH_M;
+-      x->replay_maxage = (net->sysctl_xfrm_aevent_etime*HZ)/XFRM_AE_ETH_M;
++      x->replay_maxage = (sysctl_xfrm_aevent_etime*HZ)/XFRM_AE_ETH_M;
        x->preplay.bitmap = 0;
        x->preplay.seq = x->replay.seq+x->replay_maxdiff;
        x->preplay.oseq = x->replay.oseq +x->replay_maxdiff;
-@@ -436,6 +437,7 @@
+@@ -437,7 +436,6 @@
  static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
                struct rtattr **xfrma)
  {
-+      struct net *net = skb->sk->sk_net;
+-      struct net *net = skb->sk->sk_net;
        struct xfrm_usersa_info *p = NLMSG_DATA(nlh);
        struct xfrm_state *x;
        int err;
-@@ -445,7 +447,7 @@
+@@ -447,7 +445,7 @@
        if (err)
                return err;
  
--      x = xfrm_state_construct(p, xfrma, &err);
-+      x = xfrm_state_construct(net, p, xfrma, &err);
+-      x = xfrm_state_construct(net, p, xfrma, &err);
++      x = xfrm_state_construct(p, xfrma, &err);
        if (!x)
                return err;
  
-@@ -2559,7 +2561,7 @@
+@@ -2561,7 +2559,7 @@
  
        printk(KERN_INFO "Initializing XFRM netlink socket\n");
  
--      nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX,
-+      nlsk = netlink_kernel_create(&init_net, NETLINK_XFRM, XFRMNLGRP_MAX,
+-      nlsk = netlink_kernel_create(&init_net, NETLINK_XFRM, XFRMNLGRP_MAX,
++      nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX,
                                     xfrm_netlink_rcv, NULL, THIS_MODULE);
        if (nlsk == NULL)
                return -ENOMEM;
-diff -Nurb linux-2.6.22-570/rej linux-2.6.22-590/rej
---- linux-2.6.22-570/rej       1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/rej       2008-01-02 13:56:38.000000000 -0500
-@@ -0,0 +1,28 @@
-+vi -o ./drivers/dma/ioatdma.c ./drivers/dma/ioatdma.c.rej
-+vi -o ./fs/nfs/super.c ./fs/nfs/super.c.rej
-+vi -o ./fs/ocfs2/aops.c ./fs/ocfs2/aops.c.rej
-+vi -o ./fs/ocfs2/file.c ./fs/ocfs2/file.c.rej
-+vi -o ./fs/ocfs2/super.c ./fs/ocfs2/super.c.rej
-+vi -o ./fs/proc/base.c ./fs/proc/base.c.rej
-+vi -o ./fs/sysfs/file.c ./fs/sysfs/file.c.rej
-+vi -o ./fs/sync.c ./fs/sync.c.rej
-+vi -o ./include/acpi/processor.h ./include/acpi/processor.h.rej
-+vi -o ./include/linux/sunrpc/clnt.h ./include/linux/sunrpc/clnt.h.rej
-+vi -o ./include/linux/syscalls.h ./include/linux/syscalls.h.rej
-+vi -o ./include/linux/nfs_mount.h ./include/linux/nfs_mount.h.rej
-+vi -o ./include/linux/sched.h ./include/linux/sched.h.rej
-+vi -o ./include/linux/nsproxy.h ./include/linux/nsproxy.h.rej
-+vi -o ./include/linux/fs.h ./include/linux/fs.h.rej
-+vi -o ./kernel/timer.c ./kernel/timer.c.rej
-+vi -o ./kernel/fork.c ./kernel/fork.c.rej
-+vi -o ./kernel/nsproxy.c ./kernel/nsproxy.c.rej
-+vi -o ./kernel/sys.c ./kernel/sys.c.rej
-+vi -o ./kernel/user.c ./kernel/user.c.rej
-+vi -o ./kernel/utsname.c ./kernel/utsname.c.rej
-+vi -o ./kernel/sched.c ./kernel/sched.c.rej
-+vi -o ./kernel/container.c ./kernel/container.c.rej
-+vi -o ./mm/memory.c ./mm/memory.c.rej
-+vi -o ./mm/hugetlb.c ./mm/hugetlb.c.rej
-+vi -o ./net/bridge/br_if.c ./net/bridge/br_if.c.rej
-+vi -o ./net/sunrpc/auth_unix.c ./net/sunrpc/auth_unix.c.rej
-+vi -o ./scripts/checksyscalls.sh ./scripts/checksyscalls.sh.rej
-diff -Nurb linux-2.6.22-570/scripts/Makefile.build.orig linux-2.6.22-590/scripts/Makefile.build.orig
---- linux-2.6.22-570/scripts/Makefile.build.orig       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/scripts/Makefile.build.orig       1969-12-31 19:00:00.000000000 -0500
-@@ -1,348 +0,0 @@
--# ==========================================================================
--# Building
--# ==========================================================================
--
--src := $(obj)
--
--PHONY := __build
--__build:
--
--# Read .config if it exist, otherwise ignore
---include include/config/auto.conf
--
--include scripts/Kbuild.include
--
--# The filename Kbuild has precedence over Makefile
--kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
--include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
--
--include scripts/Makefile.lib
--
--ifdef host-progs
--ifneq ($(hostprogs-y),$(host-progs))
--$(warning kbuild: $(obj)/Makefile - Usage of host-progs is deprecated. Please replace with hostprogs-y!)
--hostprogs-y += $(host-progs)
--endif
--endif
--
--# Do not include host rules unles needed
--ifneq ($(hostprogs-y)$(hostprogs-m),)
--include scripts/Makefile.host
--endif
--
--ifneq ($(KBUILD_SRC),)
--# Create output directory if not already present
--_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
--
--# Create directories for object files if directory does not exist
--# Needed when obj-y := dir/file.o syntax is used
--_dummy := $(foreach d,$(obj-dirs), $(shell [ -d $(d) ] || mkdir -p $(d)))
--endif
--
--
--ifdef EXTRA_TARGETS
--$(warning kbuild: $(obj)/Makefile - Usage of EXTRA_TARGETS is obsolete in 2.6. Please fix!)
--endif
--
--ifdef build-targets
--$(warning kbuild: $(obj)/Makefile - Usage of build-targets is obsolete in 2.6. Please fix!)
--endif
--
--ifdef export-objs
--$(warning kbuild: $(obj)/Makefile - Usage of export-objs is obsolete in 2.6. Please fix!)
--endif
--
--ifdef O_TARGET
--$(warning kbuild: $(obj)/Makefile - Usage of O_TARGET := $(O_TARGET) is obsolete in 2.6. Please fix!)
--endif
--
--ifdef L_TARGET
--$(error kbuild: $(obj)/Makefile - Use of L_TARGET is replaced by lib-y in 2.6. Please fix!)
--endif
--
--ifdef list-multi
--$(warning kbuild: $(obj)/Makefile - list-multi := $(list-multi) is obsolete in 2.6. Please fix!)
--endif
--
--ifndef obj
--$(warning kbuild: Makefile.build is included improperly)
--endif
--
--# ===========================================================================
--
--ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
--lib-target := $(obj)/lib.a
--endif
--
--ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),)
--builtin-target := $(obj)/built-in.o
--endif
--
--# We keep a list of all modules in $(MODVERDIR)
--
--__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
--       $(if $(KBUILD_MODULES),$(obj-m)) \
--       $(subdir-ym) $(always)
--      @:
--
--# Linus' kernel sanity checking tool
--ifneq ($(KBUILD_CHECKSRC),0)
--  ifeq ($(KBUILD_CHECKSRC),2)
--    quiet_cmd_force_checksrc = CHECK   $<
--          cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
--  else
--      quiet_cmd_checksrc     = CHECK   $<
--            cmd_checksrc     = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
--  endif
--endif
--
--
--# Compile C sources (.c)
--# ---------------------------------------------------------------------------
--
--# Default is built-in, unless we know otherwise
--modkern_cflags := $(CFLAGS_KERNEL)
--quiet_modtag := $(empty)   $(empty)
--
--$(real-objs-m)        : modkern_cflags := $(CFLAGS_MODULE)
--$(real-objs-m:.o=.i)  : modkern_cflags := $(CFLAGS_MODULE)
--$(real-objs-m:.o=.s)  : modkern_cflags := $(CFLAGS_MODULE)
--$(real-objs-m:.o=.lst): modkern_cflags := $(CFLAGS_MODULE)
--
--$(real-objs-m)        : quiet_modtag := [M]
--$(real-objs-m:.o=.i)  : quiet_modtag := [M]
--$(real-objs-m:.o=.s)  : quiet_modtag := [M]
--$(real-objs-m:.o=.lst): quiet_modtag := [M]
--
--$(obj-m)              : quiet_modtag := [M]
--
--# Default for not multi-part modules
--modname = $(basetarget)
--
--$(multi-objs-m)         : modname = $(modname-multi)
--$(multi-objs-m:.o=.i)   : modname = $(modname-multi)
--$(multi-objs-m:.o=.s)   : modname = $(modname-multi)
--$(multi-objs-m:.o=.lst) : modname = $(modname-multi)
--$(multi-objs-y)         : modname = $(modname-multi)
--$(multi-objs-y:.o=.i)   : modname = $(modname-multi)
--$(multi-objs-y:.o=.s)   : modname = $(modname-multi)
--$(multi-objs-y:.o=.lst) : modname = $(modname-multi)
--
--quiet_cmd_cc_s_c = CC $(quiet_modtag)  $@
--cmd_cc_s_c       = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
--
--$(obj)/%.s: $(src)/%.c FORCE
--      $(call if_changed_dep,cc_s_c)
--
--quiet_cmd_cc_i_c = CPP $(quiet_modtag) $@
--cmd_cc_i_c       = $(CPP) $(c_flags)   -o $@ $<
--
--$(obj)/%.i: $(src)/%.c FORCE
--      $(call if_changed_dep,cc_i_c)
--
--quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
--cmd_cc_symtypes_c        = \
--              $(CPP) -D__GENKSYMS__ $(c_flags) $<                     \
--              | $(GENKSYMS) -T $@ >/dev/null;                         \
--              test -s $@ || rm -f $@
--
--$(obj)/%.symtypes : $(src)/%.c FORCE
--      $(call if_changed_dep,cc_symtypes_c)
--
--# C (.c) files
--# The C file is compiled and updated dependency information is generated.
--# (See cmd_cc_o_c + relevant part of rule_cc_o_c)
--
--quiet_cmd_cc_o_c = CC $(quiet_modtag)  $@
--
--ifndef CONFIG_MODVERSIONS
--cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
--
--else
--# When module versioning is enabled the following steps are executed:
--# o compile a .tmp_<file>.o from <file>.c
--# o if .tmp_<file>.o doesn't contain a __ksymtab version, i.e. does
--#   not export symbols, we just rename .tmp_<file>.o to <file>.o and
--#   are done.
--# o otherwise, we calculate symbol versions using the good old
--#   genksyms on the preprocessed source and postprocess them in a way
--#   that they are usable as a linker script
--# o generate <file>.o from .tmp_<file>.o using the linker to
--#   replace the unresolved symbols __crc_exported_symbol with
--#   the actual value of the checksum generated by genksyms
--
--cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
--cmd_modversions =                                                     \
--      if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then     \
--              $(CPP) -D__GENKSYMS__ $(c_flags) $<                     \
--              | $(GENKSYMS) $(if $(KBUILD_SYMTYPES),                  \
--                            -T $(@D)/$(@F:.o=.symtypes)) -a $(ARCH)   \
--              > $(@D)/.tmp_$(@F:.o=.ver);                             \
--                                                                      \
--              $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F)              \
--                      -T $(@D)/.tmp_$(@F:.o=.ver);                    \
--              rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver);        \
--      else                                                            \
--              mv -f $(@D)/.tmp_$(@F) $@;                              \
--      fi;
--endif
--
--define rule_cc_o_c
--      $(call echo-cmd,checksrc) $(cmd_checksrc)                         \
--      $(call echo-cmd,cc_o_c) $(cmd_cc_o_c);                            \
--      $(cmd_modversions)                                                \
--      scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' >    \
--                                                    $(dot-target).tmp;  \
--      rm -f $(depfile);                                                 \
--      mv -f $(dot-target).tmp $(dot-target).cmd
--endef
--
--# Built-in and composite module parts
--$(obj)/%.o: $(src)/%.c FORCE
--      $(call cmd,force_checksrc)
--      $(call if_changed_rule,cc_o_c)
--
--# Single-part modules are special since we need to mark them in $(MODVERDIR)
--
--$(single-used-m): $(obj)/%.o: $(src)/%.c FORCE
--      $(call cmd,force_checksrc)
--      $(call if_changed_rule,cc_o_c)
--      @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
--
--quiet_cmd_cc_lst_c = MKLST   $@
--      cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
--                   $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \
--                                   System.map $(OBJDUMP) > $@
--
--$(obj)/%.lst: $(src)/%.c FORCE
--      $(call if_changed_dep,cc_lst_c)
--
--# Compile assembler sources (.S)
--# ---------------------------------------------------------------------------
--
--modkern_aflags := $(AFLAGS_KERNEL)
--
--$(real-objs-m)      : modkern_aflags := $(AFLAGS_MODULE)
--$(real-objs-m:.o=.s): modkern_aflags := $(AFLAGS_MODULE)
--
--quiet_cmd_as_s_S = CPP $(quiet_modtag) $@
--cmd_as_s_S       = $(CPP) $(a_flags)   -o $@ $< 
--
--$(obj)/%.s: $(src)/%.S FORCE
--      $(call if_changed_dep,as_s_S)
--
--quiet_cmd_as_o_S = AS $(quiet_modtag)  $@
--cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
--
--$(obj)/%.o: $(src)/%.S FORCE
--      $(call if_changed_dep,as_o_S)
--
--targets += $(real-objs-y) $(real-objs-m) $(lib-y)
--targets += $(extra-y) $(MAKECMDGOALS) $(always)
--
--# Linker scripts preprocessor (.lds.S -> .lds)
--# ---------------------------------------------------------------------------
--quiet_cmd_cpp_lds_S = LDS     $@
--      cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@ $<
--
--$(obj)/%.lds: $(src)/%.lds.S FORCE
--      $(call if_changed_dep,cpp_lds_S)
--
--# Build the compiled-in targets
--# ---------------------------------------------------------------------------
--
--# To build objects in subdirs, we need to descend into the directories
--$(sort $(subdir-obj-y)): $(subdir-ym) ;
--
--#
--# Rule to compile a set of .o files into one .o file
--#
--ifdef builtin-target
--quiet_cmd_link_o_target = LD      $@
--# If the list of objects to link is empty, just create an empty built-in.o
--cmd_link_o_target = $(if $(strip $(obj-y)),\
--                    $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),\
--                    rm -f $@; $(AR) rcs $@)
--
--$(builtin-target): $(obj-y) FORCE
--      $(call if_changed,link_o_target)
--
--targets += $(builtin-target)
--endif # builtin-target
--
--#
--# Rule to compile a set of .o files into one .a file
--#
--ifdef lib-target
--quiet_cmd_link_l_target = AR      $@
--cmd_link_l_target = rm -f $@; $(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-y)
--
--$(lib-target): $(lib-y) FORCE
--      $(call if_changed,link_l_target)
--
--targets += $(lib-target)
--endif
--
--#
--# Rule to link composite objects
--#
--#  Composite objects are specified in kbuild makefile as follows:
--#    <composite-object>-objs := <list of .o files>
--#  or
--#    <composite-object>-y    := <list of .o files>
--link_multi_deps =                     \
--$(filter $(addprefix $(obj)/,         \
--$($(subst $(obj)/,,$(@:.o=-objs)))    \
--$($(subst $(obj)/,,$(@:.o=-y)))), $^)
-- 
--quiet_cmd_link_multi-y = LD      $@
--cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps)
--
--quiet_cmd_link_multi-m = LD [M]  $@
--cmd_link_multi-m = $(LD) $(ld_flags) $(LDFLAGS_MODULE) -o $@ $(link_multi_deps)
--
--# We would rather have a list of rules like
--#     foo.o: $(foo-objs)
--# but that's not so easy, so we rather make all composite objects depend
--# on the set of all their parts
--$(multi-used-y) : %.o: $(multi-objs-y) FORCE
--      $(call if_changed,link_multi-y)
--
--$(multi-used-m) : %.o: $(multi-objs-m) FORCE
--      $(call if_changed,link_multi-m)
--      @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod)
--
--targets += $(multi-used-y) $(multi-used-m)
--
--
--# Descending
--# ---------------------------------------------------------------------------
--
--PHONY += $(subdir-ym)
--$(subdir-ym):
--      $(Q)$(MAKE) $(build)=$@
--
--# Add FORCE to the prequisites of a target to force it to be always rebuilt.
--# ---------------------------------------------------------------------------
--
--PHONY += FORCE
--
--FORCE:
--
--# Read all saved command lines and dependencies for the $(targets) we
--# may be building above, using $(if_changed{,_dep}). As an
--# optimization, we don't need to read them if the target does not
--# exist, we will rebuild anyway in that case.
--
--targets := $(wildcard $(sort $(targets)))
--cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
--
--ifneq ($(cmd_files),)
--  include $(cmd_files)
--endif
--
--
--# Declare the contents of the .PHONY variable as phony.  We keep that
--# information in a variable se we can use it in if_changed and friends.
--
--.PHONY: $(PHONY)
-diff -Nurb linux-2.6.22-570/scripts/Makefile.modpost.orig linux-2.6.22-590/scripts/Makefile.modpost.orig
---- linux-2.6.22-570/scripts/Makefile.modpost.orig     2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/scripts/Makefile.modpost.orig     1969-12-31 19:00:00.000000000 -0500
-@@ -1,132 +0,0 @@
--# ===========================================================================
--# Module versions
--# ===========================================================================
--#
--# Stage one of module building created the following:
--# a) The individual .o files used for the module
--# b) A <module>.o file which is the .o files above linked together
--# c) A <module>.mod file in $(MODVERDIR)/, listing the name of the
--#    the preliminary <module>.o file, plus all .o files
--
--# Stage 2 is handled by this file and does the following
--# 1) Find all modules from the files listed in $(MODVERDIR)/
--# 2) modpost is then used to
--# 3)  create one <module>.mod.c file pr. module
--# 4)  create one Module.symvers file with CRC for all exported symbols
--# 5) compile all <module>.mod.c files
--# 6) final link of the module to a <module.ko> file
--
--# Step 3 is used to place certain information in the module's ELF
--# section, including information such as:
--#   Version magic (see include/vermagic.h for full details)
--#     - Kernel release
--#     - SMP is CONFIG_SMP
--#     - PREEMPT is CONFIG_PREEMPT
--#     - GCC Version
--#   Module info
--#     - Module version (MODULE_VERSION)
--#     - Module alias'es (MODULE_ALIAS)
--#     - Module license (MODULE_LICENSE)
--#     - See include/linux/module.h for more details
--
--# Step 4 is solely used to allow module versioning in external modules,
--# where the CRC of each module is retrieved from the Module.symers file.
--
--# KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined
--# symbols in the final module linking stage
--# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
--# This is solely usefull to speed up test compiles
--PHONY := _modpost
--_modpost: __modpost
--
--include include/config/auto.conf
--include scripts/Kbuild.include
--include scripts/Makefile.lib
--
--kernelsymfile := $(objtree)/Module.symvers
--modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
--
--# Step 1), find all modules listed in $(MODVERDIR)/
--__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
--modules   := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
--
--# Stop after building .o files if NOFINAL is set. Makes compile tests quicker
--_modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
--
--
--# Step 2), invoke modpost
--#  Includes step 3,4
--quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
--      cmd_modpost = scripts/mod/modpost            \
--        $(if $(CONFIG_MODVERSIONS),-m)             \
--      $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,)  \
--      $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
--      $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
--      $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
--      $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
--
--PHONY += __modpost
--__modpost: $(modules:.ko=.o) FORCE
--      $(call cmd,modpost) $(wildcard vmlinux) $(filter-out FORCE,$^)
--
--quiet_cmd_kernel-mod = MODPOST $@
--      cmd_kernel-mod = $(cmd_modpost) $(KBUILD_VMLINUX_OBJS)
--
--PHONY += vmlinux
--vmlinux: FORCE
--      $(call cmd,kernel-mod)
--
--# Declare generated files as targets for modpost
--$(symverfile):         __modpost ;
--$(modules:.ko=.mod.c): __modpost ;
--
--
--# Step 5), compile all *.mod.c files
--
--# modname is set to make c_flags define KBUILD_MODNAME
--modname = $(notdir $(@:.mod.o=))
--
--quiet_cmd_cc_o_c = CC      $@
--      cmd_cc_o_c = $(CC) $(c_flags) $(CFLAGS_MODULE)  \
--                 -c -o $@ $<
--
--$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
--      $(call if_changed_dep,cc_o_c)
--
--targets += $(modules:.ko=.mod.o)
--
--# Step 6), final link of the modules
--quiet_cmd_ld_ko_o = LD [M]  $@
--      cmd_ld_ko_o = $(LD) $(LDFLAGS) $(LDFLAGS_MODULE) -o $@          \
--                        $(filter-out FORCE,$^)
--
--$(modules): %.ko :%.o %.mod.o FORCE
--      $(call if_changed,ld_ko_o)
--
--targets += $(modules)
--
--
--# Add FORCE to the prequisites of a target to force it to be always rebuilt.
--# ---------------------------------------------------------------------------
--
--PHONY += FORCE
--
--FORCE:
--
--# Read all saved command lines and dependencies for the $(targets) we
--# may be building above, using $(if_changed{,_dep}). As an
--# optimization, we don't need to read them if the target does not
--# exist, we will rebuild anyway in that case.
--
--targets := $(wildcard $(sort $(targets)))
--cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
--
--ifneq ($(cmd_files),)
--  include $(cmd_files)
--endif
--
--
--# Declare the contents of the .PHONY variable as phony.  We keep that
--# information in a variable se we can use it in if_changed and friends.
--
--.PHONY: $(PHONY)
-diff -Nurb linux-2.6.22-570/security/commoncap.c linux-2.6.22-590/security/commoncap.c
---- linux-2.6.22-570/security/commoncap.c      2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/security/commoncap.c      2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/rej linux-2.6.22-570/rej
+--- linux-2.6.22-590/rej       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/rej       1969-12-31 19:00:00.000000000 -0500
+@@ -1,28 +0,0 @@
+-vi -o ./drivers/dma/ioatdma.c ./drivers/dma/ioatdma.c.rej
+-vi -o ./fs/nfs/super.c ./fs/nfs/super.c.rej
+-vi -o ./fs/ocfs2/aops.c ./fs/ocfs2/aops.c.rej
+-vi -o ./fs/ocfs2/file.c ./fs/ocfs2/file.c.rej
+-vi -o ./fs/ocfs2/super.c ./fs/ocfs2/super.c.rej
+-vi -o ./fs/proc/base.c ./fs/proc/base.c.rej
+-vi -o ./fs/sysfs/file.c ./fs/sysfs/file.c.rej
+-vi -o ./fs/sync.c ./fs/sync.c.rej
+-vi -o ./include/acpi/processor.h ./include/acpi/processor.h.rej
+-vi -o ./include/linux/sunrpc/clnt.h ./include/linux/sunrpc/clnt.h.rej
+-vi -o ./include/linux/syscalls.h ./include/linux/syscalls.h.rej
+-vi -o ./include/linux/nfs_mount.h ./include/linux/nfs_mount.h.rej
+-vi -o ./include/linux/sched.h ./include/linux/sched.h.rej
+-vi -o ./include/linux/nsproxy.h ./include/linux/nsproxy.h.rej
+-vi -o ./include/linux/fs.h ./include/linux/fs.h.rej
+-vi -o ./kernel/timer.c ./kernel/timer.c.rej
+-vi -o ./kernel/fork.c ./kernel/fork.c.rej
+-vi -o ./kernel/nsproxy.c ./kernel/nsproxy.c.rej
+-vi -o ./kernel/sys.c ./kernel/sys.c.rej
+-vi -o ./kernel/user.c ./kernel/user.c.rej
+-vi -o ./kernel/utsname.c ./kernel/utsname.c.rej
+-vi -o ./kernel/sched.c ./kernel/sched.c.rej
+-vi -o ./kernel/container.c ./kernel/container.c.rej
+-vi -o ./mm/memory.c ./mm/memory.c.rej
+-vi -o ./mm/hugetlb.c ./mm/hugetlb.c.rej
+-vi -o ./net/bridge/br_if.c ./net/bridge/br_if.c.rej
+-vi -o ./net/sunrpc/auth_unix.c ./net/sunrpc/auth_unix.c.rej
+-vi -o ./scripts/checksyscalls.sh ./scripts/checksyscalls.sh.rej
+diff -Nurb linux-2.6.22-590/scripts/Makefile.build.orig linux-2.6.22-570/scripts/Makefile.build.orig
+--- linux-2.6.22-590/scripts/Makefile.build.orig       1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/scripts/Makefile.build.orig       2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,348 @@
++# ==========================================================================
++# Building
++# ==========================================================================
++
++src := $(obj)
++
++PHONY := __build
++__build:
++
++# Read .config if it exist, otherwise ignore
++-include include/config/auto.conf
++
++include scripts/Kbuild.include
++
++# The filename Kbuild has precedence over Makefile
++kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
++include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
++
++include scripts/Makefile.lib
++
++ifdef host-progs
++ifneq ($(hostprogs-y),$(host-progs))
++$(warning kbuild: $(obj)/Makefile - Usage of host-progs is deprecated. Please replace with hostprogs-y!)
++hostprogs-y += $(host-progs)
++endif
++endif
++
++# Do not include host rules unles needed
++ifneq ($(hostprogs-y)$(hostprogs-m),)
++include scripts/Makefile.host
++endif
++
++ifneq ($(KBUILD_SRC),)
++# Create output directory if not already present
++_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
++
++# Create directories for object files if directory does not exist
++# Needed when obj-y := dir/file.o syntax is used
++_dummy := $(foreach d,$(obj-dirs), $(shell [ -d $(d) ] || mkdir -p $(d)))
++endif
++
++
++ifdef EXTRA_TARGETS
++$(warning kbuild: $(obj)/Makefile - Usage of EXTRA_TARGETS is obsolete in 2.6. Please fix!)
++endif
++
++ifdef build-targets
++$(warning kbuild: $(obj)/Makefile - Usage of build-targets is obsolete in 2.6. Please fix!)
++endif
++
++ifdef export-objs
++$(warning kbuild: $(obj)/Makefile - Usage of export-objs is obsolete in 2.6. Please fix!)
++endif
++
++ifdef O_TARGET
++$(warning kbuild: $(obj)/Makefile - Usage of O_TARGET := $(O_TARGET) is obsolete in 2.6. Please fix!)
++endif
++
++ifdef L_TARGET
++$(error kbuild: $(obj)/Makefile - Use of L_TARGET is replaced by lib-y in 2.6. Please fix!)
++endif
++
++ifdef list-multi
++$(warning kbuild: $(obj)/Makefile - list-multi := $(list-multi) is obsolete in 2.6. Please fix!)
++endif
++
++ifndef obj
++$(warning kbuild: Makefile.build is included improperly)
++endif
++
++# ===========================================================================
++
++ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
++lib-target := $(obj)/lib.a
++endif
++
++ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),)
++builtin-target := $(obj)/built-in.o
++endif
++
++# We keep a list of all modules in $(MODVERDIR)
++
++__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
++       $(if $(KBUILD_MODULES),$(obj-m)) \
++       $(subdir-ym) $(always)
++      @:
++
++# Linus' kernel sanity checking tool
++ifneq ($(KBUILD_CHECKSRC),0)
++  ifeq ($(KBUILD_CHECKSRC),2)
++    quiet_cmd_force_checksrc = CHECK   $<
++          cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
++  else
++      quiet_cmd_checksrc     = CHECK   $<
++            cmd_checksrc     = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
++  endif
++endif
++
++
++# Compile C sources (.c)
++# ---------------------------------------------------------------------------
++
++# Default is built-in, unless we know otherwise
++modkern_cflags := $(CFLAGS_KERNEL)
++quiet_modtag := $(empty)   $(empty)
++
++$(real-objs-m)        : modkern_cflags := $(CFLAGS_MODULE)
++$(real-objs-m:.o=.i)  : modkern_cflags := $(CFLAGS_MODULE)
++$(real-objs-m:.o=.s)  : modkern_cflags := $(CFLAGS_MODULE)
++$(real-objs-m:.o=.lst): modkern_cflags := $(CFLAGS_MODULE)
++
++$(real-objs-m)        : quiet_modtag := [M]
++$(real-objs-m:.o=.i)  : quiet_modtag := [M]
++$(real-objs-m:.o=.s)  : quiet_modtag := [M]
++$(real-objs-m:.o=.lst): quiet_modtag := [M]
++
++$(obj-m)              : quiet_modtag := [M]
++
++# Default for not multi-part modules
++modname = $(basetarget)
++
++$(multi-objs-m)         : modname = $(modname-multi)
++$(multi-objs-m:.o=.i)   : modname = $(modname-multi)
++$(multi-objs-m:.o=.s)   : modname = $(modname-multi)
++$(multi-objs-m:.o=.lst) : modname = $(modname-multi)
++$(multi-objs-y)         : modname = $(modname-multi)
++$(multi-objs-y:.o=.i)   : modname = $(modname-multi)
++$(multi-objs-y:.o=.s)   : modname = $(modname-multi)
++$(multi-objs-y:.o=.lst) : modname = $(modname-multi)
++
++quiet_cmd_cc_s_c = CC $(quiet_modtag)  $@
++cmd_cc_s_c       = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
++
++$(obj)/%.s: $(src)/%.c FORCE
++      $(call if_changed_dep,cc_s_c)
++
++quiet_cmd_cc_i_c = CPP $(quiet_modtag) $@
++cmd_cc_i_c       = $(CPP) $(c_flags)   -o $@ $<
++
++$(obj)/%.i: $(src)/%.c FORCE
++      $(call if_changed_dep,cc_i_c)
++
++quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
++cmd_cc_symtypes_c        = \
++              $(CPP) -D__GENKSYMS__ $(c_flags) $<                     \
++              | $(GENKSYMS) -T $@ >/dev/null;                         \
++              test -s $@ || rm -f $@
++
++$(obj)/%.symtypes : $(src)/%.c FORCE
++      $(call if_changed_dep,cc_symtypes_c)
++
++# C (.c) files
++# The C file is compiled and updated dependency information is generated.
++# (See cmd_cc_o_c + relevant part of rule_cc_o_c)
++
++quiet_cmd_cc_o_c = CC $(quiet_modtag)  $@
++
++ifndef CONFIG_MODVERSIONS
++cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
++
++else
++# When module versioning is enabled the following steps are executed:
++# o compile a .tmp_<file>.o from <file>.c
++# o if .tmp_<file>.o doesn't contain a __ksymtab version, i.e. does
++#   not export symbols, we just rename .tmp_<file>.o to <file>.o and
++#   are done.
++# o otherwise, we calculate symbol versions using the good old
++#   genksyms on the preprocessed source and postprocess them in a way
++#   that they are usable as a linker script
++# o generate <file>.o from .tmp_<file>.o using the linker to
++#   replace the unresolved symbols __crc_exported_symbol with
++#   the actual value of the checksum generated by genksyms
++
++cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
++cmd_modversions =                                                     \
++      if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then     \
++              $(CPP) -D__GENKSYMS__ $(c_flags) $<                     \
++              | $(GENKSYMS) $(if $(KBUILD_SYMTYPES),                  \
++                            -T $(@D)/$(@F:.o=.symtypes)) -a $(ARCH)   \
++              > $(@D)/.tmp_$(@F:.o=.ver);                             \
++                                                                      \
++              $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F)              \
++                      -T $(@D)/.tmp_$(@F:.o=.ver);                    \
++              rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver);        \
++      else                                                            \
++              mv -f $(@D)/.tmp_$(@F) $@;                              \
++      fi;
++endif
++
++define rule_cc_o_c
++      $(call echo-cmd,checksrc) $(cmd_checksrc)                         \
++      $(call echo-cmd,cc_o_c) $(cmd_cc_o_c);                            \
++      $(cmd_modversions)                                                \
++      scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' >    \
++                                                    $(dot-target).tmp;  \
++      rm -f $(depfile);                                                 \
++      mv -f $(dot-target).tmp $(dot-target).cmd
++endef
++
++# Built-in and composite module parts
++$(obj)/%.o: $(src)/%.c FORCE
++      $(call cmd,force_checksrc)
++      $(call if_changed_rule,cc_o_c)
++
++# Single-part modules are special since we need to mark them in $(MODVERDIR)
++
++$(single-used-m): $(obj)/%.o: $(src)/%.c FORCE
++      $(call cmd,force_checksrc)
++      $(call if_changed_rule,cc_o_c)
++      @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
++
++quiet_cmd_cc_lst_c = MKLST   $@
++      cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
++                   $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \
++                                   System.map $(OBJDUMP) > $@
++
++$(obj)/%.lst: $(src)/%.c FORCE
++      $(call if_changed_dep,cc_lst_c)
++
++# Compile assembler sources (.S)
++# ---------------------------------------------------------------------------
++
++modkern_aflags := $(AFLAGS_KERNEL)
++
++$(real-objs-m)      : modkern_aflags := $(AFLAGS_MODULE)
++$(real-objs-m:.o=.s): modkern_aflags := $(AFLAGS_MODULE)
++
++quiet_cmd_as_s_S = CPP $(quiet_modtag) $@
++cmd_as_s_S       = $(CPP) $(a_flags)   -o $@ $< 
++
++$(obj)/%.s: $(src)/%.S FORCE
++      $(call if_changed_dep,as_s_S)
++
++quiet_cmd_as_o_S = AS $(quiet_modtag)  $@
++cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
++
++$(obj)/%.o: $(src)/%.S FORCE
++      $(call if_changed_dep,as_o_S)
++
++targets += $(real-objs-y) $(real-objs-m) $(lib-y)
++targets += $(extra-y) $(MAKECMDGOALS) $(always)
++
++# Linker scripts preprocessor (.lds.S -> .lds)
++# ---------------------------------------------------------------------------
++quiet_cmd_cpp_lds_S = LDS     $@
++      cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@ $<
++
++$(obj)/%.lds: $(src)/%.lds.S FORCE
++      $(call if_changed_dep,cpp_lds_S)
++
++# Build the compiled-in targets
++# ---------------------------------------------------------------------------
++
++# To build objects in subdirs, we need to descend into the directories
++$(sort $(subdir-obj-y)): $(subdir-ym) ;
++
++#
++# Rule to compile a set of .o files into one .o file
++#
++ifdef builtin-target
++quiet_cmd_link_o_target = LD      $@
++# If the list of objects to link is empty, just create an empty built-in.o
++cmd_link_o_target = $(if $(strip $(obj-y)),\
++                    $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),\
++                    rm -f $@; $(AR) rcs $@)
++
++$(builtin-target): $(obj-y) FORCE
++      $(call if_changed,link_o_target)
++
++targets += $(builtin-target)
++endif # builtin-target
++
++#
++# Rule to compile a set of .o files into one .a file
++#
++ifdef lib-target
++quiet_cmd_link_l_target = AR      $@
++cmd_link_l_target = rm -f $@; $(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-y)
++
++$(lib-target): $(lib-y) FORCE
++      $(call if_changed,link_l_target)
++
++targets += $(lib-target)
++endif
++
++#
++# Rule to link composite objects
++#
++#  Composite objects are specified in kbuild makefile as follows:
++#    <composite-object>-objs := <list of .o files>
++#  or
++#    <composite-object>-y    := <list of .o files>
++link_multi_deps =                     \
++$(filter $(addprefix $(obj)/,         \
++$($(subst $(obj)/,,$(@:.o=-objs)))    \
++$($(subst $(obj)/,,$(@:.o=-y)))), $^)
++ 
++quiet_cmd_link_multi-y = LD      $@
++cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps)
++
++quiet_cmd_link_multi-m = LD [M]  $@
++cmd_link_multi-m = $(LD) $(ld_flags) $(LDFLAGS_MODULE) -o $@ $(link_multi_deps)
++
++# We would rather have a list of rules like
++#     foo.o: $(foo-objs)
++# but that's not so easy, so we rather make all composite objects depend
++# on the set of all their parts
++$(multi-used-y) : %.o: $(multi-objs-y) FORCE
++      $(call if_changed,link_multi-y)
++
++$(multi-used-m) : %.o: $(multi-objs-m) FORCE
++      $(call if_changed,link_multi-m)
++      @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod)
++
++targets += $(multi-used-y) $(multi-used-m)
++
++
++# Descending
++# ---------------------------------------------------------------------------
++
++PHONY += $(subdir-ym)
++$(subdir-ym):
++      $(Q)$(MAKE) $(build)=$@
++
++# Add FORCE to the prequisites of a target to force it to be always rebuilt.
++# ---------------------------------------------------------------------------
++
++PHONY += FORCE
++
++FORCE:
++
++# Read all saved command lines and dependencies for the $(targets) we
++# may be building above, using $(if_changed{,_dep}). As an
++# optimization, we don't need to read them if the target does not
++# exist, we will rebuild anyway in that case.
++
++targets := $(wildcard $(sort $(targets)))
++cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
++
++ifneq ($(cmd_files),)
++  include $(cmd_files)
++endif
++
++
++# Declare the contents of the .PHONY variable as phony.  We keep that
++# information in a variable se we can use it in if_changed and friends.
++
++.PHONY: $(PHONY)
+diff -Nurb linux-2.6.22-590/scripts/Makefile.modpost.orig linux-2.6.22-570/scripts/Makefile.modpost.orig
+--- linux-2.6.22-590/scripts/Makefile.modpost.orig     1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-570/scripts/Makefile.modpost.orig     2007-07-08 19:32:17.000000000 -0400
+@@ -0,0 +1,132 @@
++# ===========================================================================
++# Module versions
++# ===========================================================================
++#
++# Stage one of module building created the following:
++# a) The individual .o files used for the module
++# b) A <module>.o file which is the .o files above linked together
++# c) A <module>.mod file in $(MODVERDIR)/, listing the name of the
++#    the preliminary <module>.o file, plus all .o files
++
++# Stage 2 is handled by this file and does the following
++# 1) Find all modules from the files listed in $(MODVERDIR)/
++# 2) modpost is then used to
++# 3)  create one <module>.mod.c file pr. module
++# 4)  create one Module.symvers file with CRC for all exported symbols
++# 5) compile all <module>.mod.c files
++# 6) final link of the module to a <module.ko> file
++
++# Step 3 is used to place certain information in the module's ELF
++# section, including information such as:
++#   Version magic (see include/vermagic.h for full details)
++#     - Kernel release
++#     - SMP is CONFIG_SMP
++#     - PREEMPT is CONFIG_PREEMPT
++#     - GCC Version
++#   Module info
++#     - Module version (MODULE_VERSION)
++#     - Module alias'es (MODULE_ALIAS)
++#     - Module license (MODULE_LICENSE)
++#     - See include/linux/module.h for more details
++
++# Step 4 is solely used to allow module versioning in external modules,
++# where the CRC of each module is retrieved from the Module.symers file.
++
++# KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined
++# symbols in the final module linking stage
++# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
++# This is solely usefull to speed up test compiles
++PHONY := _modpost
++_modpost: __modpost
++
++include include/config/auto.conf
++include scripts/Kbuild.include
++include scripts/Makefile.lib
++
++kernelsymfile := $(objtree)/Module.symvers
++modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
++
++# Step 1), find all modules listed in $(MODVERDIR)/
++__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
++modules   := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
++
++# Stop after building .o files if NOFINAL is set. Makes compile tests quicker
++_modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
++
++
++# Step 2), invoke modpost
++#  Includes step 3,4
++quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
++      cmd_modpost = scripts/mod/modpost            \
++        $(if $(CONFIG_MODVERSIONS),-m)             \
++      $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,)  \
++      $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
++      $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
++      $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
++      $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
++
++PHONY += __modpost
++__modpost: $(modules:.ko=.o) FORCE
++      $(call cmd,modpost) $(wildcard vmlinux) $(filter-out FORCE,$^)
++
++quiet_cmd_kernel-mod = MODPOST $@
++      cmd_kernel-mod = $(cmd_modpost) $(KBUILD_VMLINUX_OBJS)
++
++PHONY += vmlinux
++vmlinux: FORCE
++      $(call cmd,kernel-mod)
++
++# Declare generated files as targets for modpost
++$(symverfile):         __modpost ;
++$(modules:.ko=.mod.c): __modpost ;
++
++
++# Step 5), compile all *.mod.c files
++
++# modname is set to make c_flags define KBUILD_MODNAME
++modname = $(notdir $(@:.mod.o=))
++
++quiet_cmd_cc_o_c = CC      $@
++      cmd_cc_o_c = $(CC) $(c_flags) $(CFLAGS_MODULE)  \
++                 -c -o $@ $<
++
++$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
++      $(call if_changed_dep,cc_o_c)
++
++targets += $(modules:.ko=.mod.o)
++
++# Step 6), final link of the modules
++quiet_cmd_ld_ko_o = LD [M]  $@
++      cmd_ld_ko_o = $(LD) $(LDFLAGS) $(LDFLAGS_MODULE) -o $@          \
++                        $(filter-out FORCE,$^)
++
++$(modules): %.ko :%.o %.mod.o FORCE
++      $(call if_changed,ld_ko_o)
++
++targets += $(modules)
++
++
++# Add FORCE to the prequisites of a target to force it to be always rebuilt.
++# ---------------------------------------------------------------------------
++
++PHONY += FORCE
++
++FORCE:
++
++# Read all saved command lines and dependencies for the $(targets) we
++# may be building above, using $(if_changed{,_dep}). As an
++# optimization, we don't need to read them if the target does not
++# exist, we will rebuild anyway in that case.
++
++targets := $(wildcard $(sort $(targets)))
++cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
++
++ifneq ($(cmd_files),)
++  include $(cmd_files)
++endif
++
++
++# Declare the contents of the .PHONY variable as phony.  We keep that
++# information in a variable se we can use it in if_changed and friends.
++
++.PHONY: $(PHONY)
+diff -Nurb linux-2.6.22-590/security/commoncap.c linux-2.6.22-570/security/commoncap.c
+--- linux-2.6.22-590/security/commoncap.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/commoncap.c      2008-01-23 19:16:05.000000000 -0500
 @@ -150,7 +150,7 @@
  
        if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
            !cap_issubset (new_permitted, current->cap_permitted)) {
--              current->mm->dumpable = suid_dumpable;
-+              set_dumpable(current->mm, suid_dumpable);
+-              set_dumpable(current->mm, suid_dumpable);
++              current->mm->dumpable = suid_dumpable;
  
                if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
                        if (!capable(CAP_SETUID)) {
-diff -Nurb linux-2.6.22-570/security/dummy.c linux-2.6.22-590/security/dummy.c
---- linux-2.6.22-570/security/dummy.c  2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/security/dummy.c  2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/security/dummy.c linux-2.6.22-570/security/dummy.c
+--- linux-2.6.22-590/security/dummy.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/dummy.c  2008-01-23 19:16:05.000000000 -0500
 @@ -131,7 +131,7 @@
  static void dummy_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
  {
        if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
--              current->mm->dumpable = suid_dumpable;
-+              set_dumpable(current->mm, suid_dumpable);
+-              set_dumpable(current->mm, suid_dumpable);
++              current->mm->dumpable = suid_dumpable;
  
                if ((unsafe & ~LSM_UNSAFE_PTRACE_CAP) && !capable(CAP_SETUID)) {
                        bprm->e_uid = current->uid;
-@@ -421,8 +421,12 @@
+@@ -421,12 +421,8 @@
  
  static int dummy_file_mmap (struct file *file, unsigned long reqprot,
                            unsigned long prot,
--                          unsigned long flags)
-+                          unsigned long flags,
-+                          unsigned long addr,
-+                          unsigned long addr_only)
+-                          unsigned long flags,
+-                          unsigned long addr,
+-                          unsigned long addr_only)
++                          unsigned long flags)
  {
-+      if (addr < mmap_min_addr)
-+              return -EACCES;
+-      if (addr < mmap_min_addr)
+-              return -EACCES;
        return 0;
  }
  
-diff -Nurb linux-2.6.22-570/security/keys/request_key.c linux-2.6.22-590/security/keys/request_key.c
---- linux-2.6.22-570/security/keys/request_key.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/keys/request_key.c       2008-01-02 13:56:38.000000000 -0500
-@@ -108,7 +108,8 @@
+diff -Nurb linux-2.6.22-590/security/keys/request_key.c linux-2.6.22-570/security/keys/request_key.c
+--- linux-2.6.22-590/security/keys/request_key.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/keys/request_key.c       2007-07-08 19:32:17.000000000 -0400
+@@ -108,8 +108,7 @@
        argv[i] = NULL;
  
        /* do it */
--      ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, 1);
-+      ret = call_usermodehelper_keys(argv[0], argv, envp, keyring,
-+                                     UMH_WAIT_PROC);
+-      ret = call_usermodehelper_keys(argv[0], argv, envp, keyring,
+-                                     UMH_WAIT_PROC);
++      ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, 1);
  
  error_link:
        key_put(keyring);
-diff -Nurb linux-2.6.22-570/security/security.c linux-2.6.22-590/security/security.c
---- linux-2.6.22-570/security/security.c       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/security.c       2008-01-02 13:56:38.000000000 -0500
-@@ -24,6 +24,7 @@
+diff -Nurb linux-2.6.22-590/security/security.c linux-2.6.22-570/security/security.c
+--- linux-2.6.22-590/security/security.c       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/security.c       2007-07-08 19:32:17.000000000 -0400
+@@ -24,7 +24,6 @@
  extern void security_fixup_ops(struct security_operations *ops);
  
  struct security_operations *security_ops;     /* Initialized to NULL */
-+unsigned long mmap_min_addr;          /* 0 means no protection */
+-unsigned long mmap_min_addr;          /* 0 means no protection */
  
  static inline int verify(struct security_operations *ops)
  {
-@@ -176,4 +177,5 @@
+@@ -177,5 +176,4 @@
  EXPORT_SYMBOL_GPL(unregister_security);
  EXPORT_SYMBOL_GPL(mod_reg_security);
  EXPORT_SYMBOL_GPL(mod_unreg_security);
-+EXPORT_SYMBOL_GPL(mmap_min_addr);
+-EXPORT_SYMBOL_GPL(mmap_min_addr);
  EXPORT_SYMBOL(security_ops);
-diff -Nurb linux-2.6.22-570/security/selinux/avc.c linux-2.6.22-590/security/selinux/avc.c
---- linux-2.6.22-570/security/selinux/avc.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/selinux/avc.c    2008-01-02 13:56:38.000000000 -0500
+diff -Nurb linux-2.6.22-590/security/selinux/avc.c linux-2.6.22-570/security/selinux/avc.c
+--- linux-2.6.22-590/security/selinux/avc.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/avc.c    2007-07-08 19:32:17.000000000 -0400
 @@ -586,7 +586,7 @@
                                }
                        }
                        if (inode)
--                              audit_log_format(ab, " dev=%s ino=%ld",
-+                              audit_log_format(ab, " dev=%s ino=%lu",
+-                              audit_log_format(ab, " dev=%s ino=%lu",
++                              audit_log_format(ab, " dev=%s ino=%ld",
                                                 inode->i_sb->s_id,
                                                 inode->i_ino);
                        break;
-@@ -832,6 +832,7 @@
+@@ -832,7 +832,6 @@
   * @tsid: target security identifier
   * @tclass: target security class
   * @requested: requested permissions, interpreted based on @tclass
-+ * @flags:  AVC_STRICT or 0
+- * @flags:  AVC_STRICT or 0
   * @avd: access vector decisions
   *
   * Check the AVC to determine whether the @requested permissions are granted
-@@ -847,6 +848,7 @@
+@@ -848,7 +847,6 @@
   */
  int avc_has_perm_noaudit(u32 ssid, u32 tsid,
                           u16 tclass, u32 requested,
-+                       unsigned flags,
+-                       unsigned flags,
                           struct av_decision *avd)
  {
        struct avc_node *node;
-@@ -874,7 +876,7 @@
+@@ -876,7 +874,7 @@
        denied = requested & ~(p_ae->avd.allowed);
  
        if (!requested || denied) {
--              if (selinux_enforcing)
-+              if (selinux_enforcing || (flags & AVC_STRICT))
+-              if (selinux_enforcing || (flags & AVC_STRICT))
++              if (selinux_enforcing)
                        rc = -EACCES;
                else
                        if (node)
-@@ -909,7 +911,7 @@
+@@ -911,7 +909,7 @@
        struct av_decision avd;
        int rc;
  
--      rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, &avd);
-+      rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd);
+-      rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd);
++      rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, &avd);
        avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
        return rc;
  }
-diff -Nurb linux-2.6.22-570/security/selinux/hooks.c linux-2.6.22-590/security/selinux/hooks.c
---- linux-2.6.22-570/security/selinux/hooks.c  2008-01-02 13:56:26.000000000 -0500
-+++ linux-2.6.22-590/security/selinux/hooks.c  2008-01-02 13:56:38.000000000 -0500
-@@ -111,6 +111,9 @@
+diff -Nurb linux-2.6.22-590/security/selinux/hooks.c linux-2.6.22-570/security/selinux/hooks.c
+--- linux-2.6.22-590/security/selinux/hooks.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/hooks.c  2008-01-23 19:16:05.000000000 -0500
+@@ -111,9 +111,6 @@
  /* Original (dummy) security module. */
  static struct security_operations *original_ops = NULL;
  
-+/* Did we enable minimum mmap address checking? */
-+static int enabled_mmap_min_addr;
-+
+-/* Did we enable minimum mmap address checking? */
+-static int enabled_mmap_min_addr;
+-
  /* Minimal support for a secondary security module,
     just to allow the use of the dummy or capability modules.
     The owlsm module can alternatively be used as a secondary
-@@ -1593,6 +1596,7 @@
+@@ -1596,7 +1593,6 @@
                rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
                                        SECCLASS_CAPABILITY,
                                        CAP_TO_MASK(CAP_SYS_ADMIN),
-+                                        0,
+-                                        0,
                                        NULL);
  
        if (rc == 0)
-@@ -2570,12 +2574,16 @@
+@@ -2574,16 +2570,12 @@
  }
  
  static int selinux_file_mmap(struct file *file, unsigned long reqprot,
--                           unsigned long prot, unsigned long flags)
-+                           unsigned long prot, unsigned long flags,
-+                           unsigned long addr, unsigned long addr_only)
+-                           unsigned long prot, unsigned long flags,
+-                           unsigned long addr, unsigned long addr_only)
++                           unsigned long prot, unsigned long flags)
  {
--      int rc;
-+      int rc = 0;
-+      u32 sid = ((struct task_security_struct*)(current->security))->sid;
+-      int rc = 0;
+-      u32 sid = ((struct task_security_struct*)(current->security))->sid;
++      int rc;
  
--      rc = secondary_ops->file_mmap(file, reqprot, prot, flags);
--      if (rc)
-+      if (addr < mmap_min_addr)
-+              rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
-+                                MEMPROTECT__MMAP_ZERO, NULL);
-+      if (rc || addr_only)
+-      if (addr < mmap_min_addr)
+-              rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
+-                                MEMPROTECT__MMAP_ZERO, NULL);
+-      if (rc || addr_only)
++      rc = secondary_ops->file_mmap(file, reqprot, prot, flags);
++      if (rc)
                return rc;
  
        if (selinux_checkreqprot)
-@@ -3223,8 +3231,8 @@
+@@ -3231,8 +3223,8 @@
  /* Range of port numbers used to automatically bind.
     Need to determine whether we should perform a name_bind
     permission check between the socket and the port number. */
--#define ip_local_port_range_0 sysctl_local_port_range[0]
--#define ip_local_port_range_1 sysctl_local_port_range[1]
-+#define ip_local_port_range_0 (sk->sk_net->sysctl_local_port_range[0])
-+#define ip_local_port_range_1 (sk->sk_net->sysctl_local_port_range[1])
+-#define ip_local_port_range_0 (sk->sk_net->sysctl_local_port_range[0])
+-#define ip_local_port_range_1 (sk->sk_net->sysctl_local_port_range[1])
++#define ip_local_port_range_0 sysctl_local_port_range[0]
++#define ip_local_port_range_1 sysctl_local_port_range[1]
  
  static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
  {
-@@ -3968,6 +3976,10 @@
+@@ -3976,10 +3968,6 @@
                                                const struct net_device *out,
                                                int (*okfn)(struct sk_buff *))
  {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
        return selinux_ip_postroute_last(hooknum, pskb, in, out, okfn, PF_INET);
  }
  
-@@ -3979,6 +3991,10 @@
+@@ -3991,10 +3979,6 @@
                                                const struct net_device *out,
                                                int (*okfn)(struct sk_buff *))
  {
-+      /* Only filter packets in the initial network namespace */
-+      if ((in?in:out)->nd_net != &init_net)
-+              return NF_ACCEPT;
-+
+-      /* Only filter packets in the initial network namespace */
+-      if ((in?in:out)->nd_net != &init_net)
+-              return NF_ACCEPT;
+-
        return selinux_ip_postroute_last(hooknum, pskb, in, out, okfn, PF_INET6);
  }
  
-@@ -4628,7 +4644,7 @@
+@@ -4644,7 +4628,7 @@
                if (p->ptrace & PT_PTRACED) {
                        error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
                                                     SECCLASS_PROCESS,
--                                                   PROCESS__PTRACE, &avd);
-+                                                   PROCESS__PTRACE, 0, &avd);
+-                                                   PROCESS__PTRACE, 0, &avd);
++                                                   PROCESS__PTRACE, &avd);
                        if (!error)
                                tsec->sid = sid;
                        task_unlock(p);
-@@ -4910,6 +4926,16 @@
+@@ -4926,16 +4910,6 @@
        sel_inode_cache = kmem_cache_create("selinux_inode_security",
                                            sizeof(struct inode_security_struct),
                                            0, SLAB_PANIC, NULL, NULL);
-+
-+      /*
-+       * Tasks cannot mmap below this without the mmap_zero permission.
-+       * If not enabled already, do so by setting it to 64KB.
-+       */
-+      if (mmap_min_addr == 0) {
-+              enabled_mmap_min_addr = 1;
-+              mmap_min_addr = 65536;
-+      }
-+
+-
+-      /*
+-       * Tasks cannot mmap below this without the mmap_zero permission.
+-       * If not enabled already, do so by setting it to 64KB.
+-       */
+-      if (mmap_min_addr == 0) {
+-              enabled_mmap_min_addr = 1;
+-              mmap_min_addr = 65536;
+-      }
+-
        avc_init();
  
        original_ops = secondary_ops = security_ops;
-@@ -5060,6 +5086,10 @@
+@@ -5086,10 +5060,6 @@
        selinux_disabled = 1;
        selinux_enabled = 0;
  
-+      /* Disable minimum mmap address check only if we enabled it */
-+      if (enabled_mmap_min_addr)
-+              mmap_min_addr = 0;
-+
+-      /* Disable minimum mmap address check only if we enabled it */
+-      if (enabled_mmap_min_addr)
+-              mmap_min_addr = 0;
+-
        /* Reset security_ops to the secondary module, dummy or capability. */
        security_ops = secondary_ops;
  
-diff -Nurb linux-2.6.22-570/security/selinux/include/av_perm_to_string.h linux-2.6.22-590/security/selinux/include/av_perm_to_string.h
---- linux-2.6.22-570/security/selinux/include/av_perm_to_string.h      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/selinux/include/av_perm_to_string.h      2008-01-02 13:56:38.000000000 -0500
-@@ -158,3 +158,4 @@
+diff -Nurb linux-2.6.22-590/security/selinux/include/av_perm_to_string.h linux-2.6.22-570/security/selinux/include/av_perm_to_string.h
+--- linux-2.6.22-590/security/selinux/include/av_perm_to_string.h      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/include/av_perm_to_string.h      2007-07-08 19:32:17.000000000 -0400
+@@ -158,4 +158,3 @@
     S_(SECCLASS_KEY, KEY__CREATE, "create")
     S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
     S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
-+   S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero")
-diff -Nurb linux-2.6.22-570/security/selinux/include/av_permissions.h linux-2.6.22-590/security/selinux/include/av_permissions.h
---- linux-2.6.22-570/security/selinux/include/av_permissions.h 2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/selinux/include/av_permissions.h 2008-01-02 13:56:38.000000000 -0500
-@@ -823,3 +823,4 @@
+-   S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero")
+diff -Nurb linux-2.6.22-590/security/selinux/include/av_permissions.h linux-2.6.22-570/security/selinux/include/av_permissions.h
+--- linux-2.6.22-590/security/selinux/include/av_permissions.h 2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/include/av_permissions.h 2007-07-08 19:32:17.000000000 -0400
+@@ -823,4 +823,3 @@
  #define DCCP_SOCKET__NAME_BIND                    0x00200000UL
  #define DCCP_SOCKET__NODE_BIND                    0x00400000UL
  #define DCCP_SOCKET__NAME_CONNECT                 0x00800000UL
-+#define MEMPROTECT__MMAP_ZERO                     0x00000001UL
-diff -Nurb linux-2.6.22-570/security/selinux/include/avc.h linux-2.6.22-590/security/selinux/include/avc.h
---- linux-2.6.22-570/security/selinux/include/avc.h    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/selinux/include/avc.h    2008-01-02 13:56:38.000000000 -0500
-@@ -102,8 +102,10 @@
+-#define MEMPROTECT__MMAP_ZERO                     0x00000001UL
+diff -Nurb linux-2.6.22-590/security/selinux/include/avc.h linux-2.6.22-570/security/selinux/include/avc.h
+--- linux-2.6.22-590/security/selinux/include/avc.h    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/include/avc.h    2007-07-08 19:32:17.000000000 -0400
+@@ -102,10 +102,8 @@
                 u16 tclass, u32 requested,
                 struct av_decision *avd, int result, struct avc_audit_data *auditdata);
  
-+#define AVC_STRICT 1 /* Ignore permissive mode. */
+-#define AVC_STRICT 1 /* Ignore permissive mode. */
  int avc_has_perm_noaudit(u32 ssid, u32 tsid,
                           u16 tclass, u32 requested,
-+                       unsigned flags,
+-                       unsigned flags,
                           struct av_decision *avd);
  
  int avc_has_perm(u32 ssid, u32 tsid,
-diff -Nurb linux-2.6.22-570/security/selinux/include/class_to_string.h linux-2.6.22-590/security/selinux/include/class_to_string.h
---- linux-2.6.22-570/security/selinux/include/class_to_string.h        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/selinux/include/class_to_string.h        2008-01-02 13:56:38.000000000 -0500
-@@ -63,3 +63,4 @@
+diff -Nurb linux-2.6.22-590/security/selinux/include/class_to_string.h linux-2.6.22-570/security/selinux/include/class_to_string.h
+--- linux-2.6.22-590/security/selinux/include/class_to_string.h        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/include/class_to_string.h        2007-07-08 19:32:17.000000000 -0400
+@@ -63,4 +63,3 @@
      S_("key")
      S_(NULL)
      S_("dccp_socket")
-+    S_("memprotect")
-diff -Nurb linux-2.6.22-570/security/selinux/include/flask.h linux-2.6.22-590/security/selinux/include/flask.h
---- linux-2.6.22-570/security/selinux/include/flask.h  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/selinux/include/flask.h  2008-01-02 13:56:38.000000000 -0500
-@@ -49,6 +49,7 @@
+-    S_("memprotect")
+diff -Nurb linux-2.6.22-590/security/selinux/include/flask.h linux-2.6.22-570/security/selinux/include/flask.h
+--- linux-2.6.22-590/security/selinux/include/flask.h  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/include/flask.h  2007-07-08 19:32:17.000000000 -0400
+@@ -49,7 +49,6 @@
  #define SECCLASS_PACKET                                  57
  #define SECCLASS_KEY                                     58
  #define SECCLASS_DCCP_SOCKET                             60
-+#define SECCLASS_MEMPROTECT                              61
+-#define SECCLASS_MEMPROTECT                              61
  
  /*
   * Security identifier indices for initial entities
-diff -Nurb linux-2.6.22-570/security/selinux/include/security.h linux-2.6.22-590/security/selinux/include/security.h
---- linux-2.6.22-570/security/selinux/include/security.h       2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/selinux/include/security.h       2008-01-02 13:56:38.000000000 -0500
-@@ -41,6 +41,7 @@
+diff -Nurb linux-2.6.22-590/security/selinux/include/security.h linux-2.6.22-570/security/selinux/include/security.h
+--- linux-2.6.22-590/security/selinux/include/security.h       2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/include/security.h       2007-07-08 19:32:17.000000000 -0400
+@@ -41,7 +41,6 @@
  
  int security_load_policy(void * data, size_t len);
  
-+#define SEL_VEC_MAX 32
+-#define SEL_VEC_MAX 32
  struct av_decision {
        u32 allowed;
        u32 decided;
-@@ -87,6 +88,9 @@
+@@ -88,9 +87,6 @@
  
  int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
  
-+int security_get_classes(char ***classes, int *nclasses);
-+int security_get_permissions(char *class, char ***perms, int *nperms);
-+
+-int security_get_classes(char ***classes, int *nclasses);
+-int security_get_permissions(char *class, char ***perms, int *nperms);
+-
  #define SECURITY_FS_USE_XATTR         1 /* use xattr */
  #define SECURITY_FS_USE_TRANS         2 /* use transition SIDs, e.g. devpts/tmpfs */
  #define SECURITY_FS_USE_TASK          3 /* use task SIDs, e.g. pipefs/sockfs */
-diff -Nurb linux-2.6.22-570/security/selinux/netif.c linux-2.6.22-590/security/selinux/netif.c
---- linux-2.6.22-570/security/selinux/netif.c  2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/selinux/netif.c  2008-01-02 13:56:38.000000000 -0500
-@@ -20,6 +20,7 @@
+diff -Nurb linux-2.6.22-590/security/selinux/netif.c linux-2.6.22-570/security/selinux/netif.c
+--- linux-2.6.22-590/security/selinux/netif.c  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/netif.c  2007-07-08 19:32:17.000000000 -0400
+@@ -20,7 +20,6 @@
  #include <linux/notifier.h>
  #include <linux/netdevice.h>
  #include <linux/rcupdate.h>
-+#include <net/net_namespace.h>
+-#include <net/net_namespace.h>
  
  #include "security.h"
  #include "objsec.h"
-@@ -234,6 +235,9 @@
+@@ -235,9 +234,6 @@
  {
        struct net_device *dev = ptr;
  
-+      if (dev->nd_net != &init_net)
-+              return NOTIFY_DONE;
-+
+-      if (dev->nd_net != &init_net)
+-              return NOTIFY_DONE;
+-
        if (event == NETDEV_DOWN)
                sel_netif_kill(dev);
  
-diff -Nurb linux-2.6.22-570/security/selinux/netlink.c linux-2.6.22-590/security/selinux/netlink.c
---- linux-2.6.22-570/security/selinux/netlink.c        2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/selinux/netlink.c        2008-01-02 13:56:38.000000000 -0500
-@@ -17,6 +17,7 @@
+diff -Nurb linux-2.6.22-590/security/selinux/netlink.c linux-2.6.22-570/security/selinux/netlink.c
+--- linux-2.6.22-590/security/selinux/netlink.c        2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/netlink.c        2007-07-08 19:32:17.000000000 -0400
+@@ -17,7 +17,6 @@
  #include <linux/skbuff.h>
  #include <linux/netlink.h>
  #include <linux/selinux_netlink.h>
-+#include <net/net_namespace.h>
+-#include <net/net_namespace.h>
  
  static struct sock *selnl;
  
-@@ -104,8 +105,8 @@
+@@ -105,8 +104,8 @@
  
  static int __init selnl_init(void)
  {
--      selnl = netlink_kernel_create(NETLINK_SELINUX, SELNLGRP_MAX, NULL, NULL,
--                                    THIS_MODULE);
-+      selnl = netlink_kernel_create(&init_net, NETLINK_SELINUX,
-+                                    SELNLGRP_MAX, NULL, NULL, THIS_MODULE);
+-      selnl = netlink_kernel_create(&init_net, NETLINK_SELINUX,
+-                                    SELNLGRP_MAX, NULL, NULL, THIS_MODULE);
++      selnl = netlink_kernel_create(NETLINK_SELINUX, SELNLGRP_MAX, NULL, NULL,
++                                    THIS_MODULE);
        if (selnl == NULL)
                panic("SELinux:  Cannot create netlink socket.");
        netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);  
-diff -Nurb linux-2.6.22-570/security/selinux/selinuxfs.c linux-2.6.22-590/security/selinux/selinuxfs.c
---- linux-2.6.22-570/security/selinux/selinuxfs.c      2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/selinux/selinuxfs.c      2008-01-02 13:56:38.000000000 -0500
-@@ -67,6 +67,10 @@
+diff -Nurb linux-2.6.22-590/security/selinux/selinuxfs.c linux-2.6.22-570/security/selinux/selinuxfs.c
+--- linux-2.6.22-590/security/selinux/selinuxfs.c      2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/selinuxfs.c      2007-07-08 19:32:17.000000000 -0400
+@@ -67,10 +67,6 @@
  static int bool_num = 0;
  static int *bool_pending_values = NULL;
  
-+/* global data for classes */
-+static struct dentry *class_dir = NULL;
-+static unsigned long last_class_ino;
-+
+-/* global data for classes */
+-static struct dentry *class_dir = NULL;
+-static unsigned long last_class_ino;
+-
  extern void selnl_notify_setenforce(int val);
  
  /* Check whether a task is allowed to use a security operation. */
-@@ -106,6 +110,7 @@
+@@ -110,7 +106,6 @@
  
  #define SEL_INITCON_INO_OFFSET        0x01000000
  #define SEL_BOOL_INO_OFFSET   0x02000000
-+#define SEL_CLASS_INO_OFFSET  0x04000000
+-#define SEL_CLASS_INO_OFFSET  0x04000000
  #define SEL_INO_MASK          0x00ffffff
  
  #define TMPBUFLEN     12
-@@ -237,6 +242,11 @@
+@@ -242,11 +237,6 @@
  
  /* declaration for sel_write_load */
  static int sel_make_bools(void);
-+static int sel_make_classes(void);
-+
-+/* declaration for sel_make_class_dirs */
-+static int sel_make_dir(struct inode *dir, struct dentry *dentry,
-+                      unsigned long *ino);
+-static int sel_make_classes(void);
+-
+-/* declaration for sel_make_class_dirs */
+-static int sel_make_dir(struct inode *dir, struct dentry *dentry,
+-                      unsigned long *ino);
  
  static ssize_t sel_read_mls(struct file *filp, char __user *buf,
                                size_t count, loff_t *ppos)
-@@ -287,10 +297,18 @@
+@@ -297,18 +287,10 @@
                goto out;
  
        ret = sel_make_bools();
-+      if (ret) {
-+              length = ret;
-+              goto out1;
-+      }
-+
-+      ret = sel_make_classes();
+-      if (ret) {
+-              length = ret;
+-              goto out1;
+-      }
+-
+-      ret = sel_make_classes();
        if (ret)
                length = ret;
        else
                length = count;
-+
-+out1:
+-
+-out1:
        audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
                "policy loaded auid=%u",
                audit_get_loginuid(current->audit_context));
-@@ -940,9 +958,8 @@
+@@ -958,8 +940,9 @@
        .write          = sel_commit_bools_write,
  };
  
--/* delete booleans - partial revoke() from
-- * fs/proc/generic.c proc_kill_inodes */
--static void sel_remove_bools(struct dentry *de)
-+/* partial revoke() from fs/proc/generic.c proc_kill_inodes */
-+static void sel_remove_entries(struct dentry *de)
+-/* partial revoke() from fs/proc/generic.c proc_kill_inodes */
+-static void sel_remove_entries(struct dentry *de)
++/* delete booleans - partial revoke() from
++ * fs/proc/generic.c proc_kill_inodes */
++static void sel_remove_bools(struct dentry *de)
  {
        struct list_head *p, *node;
        struct super_block *sb = de->d_sb;
-@@ -998,7 +1015,7 @@
+@@ -1015,7 +998,7 @@
        kfree(bool_pending_values);
        bool_pending_values = NULL;
  
--      sel_remove_bools(dir);
-+      sel_remove_entries(dir);
+-      sel_remove_entries(dir);
++      sel_remove_bools(dir);
  
        if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
                return -ENOMEM;
-@@ -1048,7 +1065,7 @@
+@@ -1065,7 +1048,7 @@
        return ret;
  err:
        kfree(values);
--      sel_remove_bools(dir);
-+      sel_remove_entries(dir);
+-      sel_remove_entries(dir);
++      sel_remove_bools(dir);
        ret = -ENOMEM;
        goto out;
  }
-@@ -1294,7 +1311,227 @@
+@@ -1311,227 +1294,7 @@
        return ret;
  }
  
--static int sel_make_dir(struct inode *dir, struct dentry *dentry)
-+static inline unsigned int sel_div(unsigned long a, unsigned long b)
-+{
-+      return a / b - (a % b < 0);
-+}
-+
-+static inline unsigned long sel_class_to_ino(u16 class)
-+{
-+      return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET;
-+}
-+
-+static inline u16 sel_ino_to_class(unsigned long ino)
-+{
-+      return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1);
-+}
-+
-+static inline unsigned long sel_perm_to_ino(u16 class, u32 perm)
-+{
-+      return (class * (SEL_VEC_MAX + 1) + perm) | SEL_CLASS_INO_OFFSET;
-+}
-+
-+static inline u32 sel_ino_to_perm(unsigned long ino)
-+{
-+      return (ino & SEL_INO_MASK) % (SEL_VEC_MAX + 1);
-+}
-+
-+static ssize_t sel_read_class(struct file * file, char __user *buf,
-+                              size_t count, loff_t *ppos)
-+{
-+      ssize_t rc, len;
-+      char *page;
-+      unsigned long ino = file->f_path.dentry->d_inode->i_ino;
-+
-+      page = (char *)__get_free_page(GFP_KERNEL);
-+      if (!page) {
-+              rc = -ENOMEM;
-+              goto out;
-+      }
-+
-+      len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino));
-+      rc = simple_read_from_buffer(buf, count, ppos, page, len);
-+      free_page((unsigned long)page);
-+out:
-+      return rc;
-+}
-+
-+static const struct file_operations sel_class_ops = {
-+      .read           = sel_read_class,
-+};
-+
-+static ssize_t sel_read_perm(struct file * file, char __user *buf,
-+                              size_t count, loff_t *ppos)
-+{
-+      ssize_t rc, len;
-+      char *page;
-+      unsigned long ino = file->f_path.dentry->d_inode->i_ino;
-+
-+      page = (char *)__get_free_page(GFP_KERNEL);
-+      if (!page) {
-+              rc = -ENOMEM;
-+              goto out;
-+      }
-+
-+      len = snprintf(page, PAGE_SIZE,"%d", sel_ino_to_perm(ino));
-+      rc = simple_read_from_buffer(buf, count, ppos, page, len);
-+      free_page((unsigned long)page);
-+out:
-+      return rc;
-+}
-+
-+static const struct file_operations sel_perm_ops = {
-+      .read           = sel_read_perm,
-+};
-+
-+static int sel_make_perm_files(char *objclass, int classvalue,
-+                              struct dentry *dir)
-+{
-+      int i, rc = 0, nperms;
-+      char **perms;
-+
-+      rc = security_get_permissions(objclass, &perms, &nperms);
-+      if (rc)
-+              goto out;
-+
-+      for (i = 0; i < nperms; i++) {
-+              struct inode *inode;
-+              struct dentry *dentry;
-+
-+              dentry = d_alloc_name(dir, perms[i]);
-+              if (!dentry) {
-+                      rc = -ENOMEM;
-+                      goto out1;
-+              }
-+
-+              inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
-+              if (!inode) {
-+                      rc = -ENOMEM;
-+                      goto out1;
-+              }
-+              inode->i_fop = &sel_perm_ops;
-+              /* i+1 since perm values are 1-indexed */
-+              inode->i_ino = sel_perm_to_ino(classvalue, i+1);
-+              d_add(dentry, inode);
-+      }
-+
-+out1:
-+      for (i = 0; i < nperms; i++)
-+              kfree(perms[i]);
-+      kfree(perms);
-+out:
-+      return rc;
-+}
-+
-+static int sel_make_class_dir_entries(char *classname, int index,
-+                                      struct dentry *dir)
-+{
-+      struct dentry *dentry = NULL;
-+      struct inode *inode = NULL;
-+      int rc;
-+
-+      dentry = d_alloc_name(dir, "index");
-+      if (!dentry) {
-+              rc = -ENOMEM;
-+              goto out;
-+      }
-+
-+      inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
-+      if (!inode) {
-+              rc = -ENOMEM;
-+              goto out;
-+      }
-+
-+      inode->i_fop = &sel_class_ops;
-+      inode->i_ino = sel_class_to_ino(index);
-+      d_add(dentry, inode);
-+
-+      dentry = d_alloc_name(dir, "perms");
-+      if (!dentry) {
-+              rc = -ENOMEM;
-+              goto out;
-+      }
-+
-+      rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino);
-+      if (rc)
-+              goto out;
-+
-+      rc = sel_make_perm_files(classname, index, dentry);
-+
-+out:
-+      return rc;
-+}
-+
-+static void sel_remove_classes(void)
-+{
-+      struct list_head *class_node;
-+
-+      list_for_each(class_node, &class_dir->d_subdirs) {
-+              struct dentry *class_subdir = list_entry(class_node,
-+                                      struct dentry, d_u.d_child);
-+              struct list_head *class_subdir_node;
-+
-+              list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
-+                      struct dentry *d = list_entry(class_subdir_node,
-+                                              struct dentry, d_u.d_child);
-+
-+                      if (d->d_inode)
-+                              if (d->d_inode->i_mode & S_IFDIR)
-+                                      sel_remove_entries(d);
-+              }
-+
-+              sel_remove_entries(class_subdir);
-+      }
-+
-+      sel_remove_entries(class_dir);
-+}
-+
-+static int sel_make_classes(void)
-+{
-+      int rc = 0, nclasses, i;
-+      char **classes;
-+
-+      /* delete any existing entries */
-+      sel_remove_classes();
-+
-+      rc = security_get_classes(&classes, &nclasses);
-+      if (rc < 0)
-+              goto out;
-+
-+      /* +2 since classes are 1-indexed */
-+      last_class_ino = sel_class_to_ino(nclasses+2);
-+
-+      for (i = 0; i < nclasses; i++) {
-+              struct dentry *class_name_dir;
-+
-+              class_name_dir = d_alloc_name(class_dir, classes[i]);
-+              if (!class_name_dir) {
-+                      rc = -ENOMEM;
-+                      goto out1;
-+              }
-+
-+              rc = sel_make_dir(class_dir->d_inode, class_name_dir,
-+                              &last_class_ino);
-+              if (rc)
-+                      goto out1;
-+
-+              /* i+1 since class values are 1-indexed */
-+              rc = sel_make_class_dir_entries(classes[i], i+1,
-+                              class_name_dir);
-+              if (rc)
-+                      goto out1;
-+      }
-+
-+out1:
-+      for (i = 0; i < nclasses; i++)
-+              kfree(classes[i]);
-+      kfree(classes);
-+out:
-+      return rc;
-+}
-+
-+static int sel_make_dir(struct inode *dir, struct dentry *dentry,
-+                      unsigned long *ino)
+-static inline unsigned int sel_div(unsigned long a, unsigned long b)
+-{
+-      return a / b - (a % b < 0);
+-}
+-
+-static inline unsigned long sel_class_to_ino(u16 class)
+-{
+-      return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET;
+-}
+-
+-static inline u16 sel_ino_to_class(unsigned long ino)
+-{
+-      return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1);
+-}
+-
+-static inline unsigned long sel_perm_to_ino(u16 class, u32 perm)
+-{
+-      return (class * (SEL_VEC_MAX + 1) + perm) | SEL_CLASS_INO_OFFSET;
+-}
+-
+-static inline u32 sel_ino_to_perm(unsigned long ino)
+-{
+-      return (ino & SEL_INO_MASK) % (SEL_VEC_MAX + 1);
+-}
+-
+-static ssize_t sel_read_class(struct file * file, char __user *buf,
+-                              size_t count, loff_t *ppos)
+-{
+-      ssize_t rc, len;
+-      char *page;
+-      unsigned long ino = file->f_path.dentry->d_inode->i_ino;
+-
+-      page = (char *)__get_free_page(GFP_KERNEL);
+-      if (!page) {
+-              rc = -ENOMEM;
+-              goto out;
+-      }
+-
+-      len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino));
+-      rc = simple_read_from_buffer(buf, count, ppos, page, len);
+-      free_page((unsigned long)page);
+-out:
+-      return rc;
+-}
+-
+-static const struct file_operations sel_class_ops = {
+-      .read           = sel_read_class,
+-};
+-
+-static ssize_t sel_read_perm(struct file * file, char __user *buf,
+-                              size_t count, loff_t *ppos)
+-{
+-      ssize_t rc, len;
+-      char *page;
+-      unsigned long ino = file->f_path.dentry->d_inode->i_ino;
+-
+-      page = (char *)__get_free_page(GFP_KERNEL);
+-      if (!page) {
+-              rc = -ENOMEM;
+-              goto out;
+-      }
+-
+-      len = snprintf(page, PAGE_SIZE,"%d", sel_ino_to_perm(ino));
+-      rc = simple_read_from_buffer(buf, count, ppos, page, len);
+-      free_page((unsigned long)page);
+-out:
+-      return rc;
+-}
+-
+-static const struct file_operations sel_perm_ops = {
+-      .read           = sel_read_perm,
+-};
+-
+-static int sel_make_perm_files(char *objclass, int classvalue,
+-                              struct dentry *dir)
+-{
+-      int i, rc = 0, nperms;
+-      char **perms;
+-
+-      rc = security_get_permissions(objclass, &perms, &nperms);
+-      if (rc)
+-              goto out;
+-
+-      for (i = 0; i < nperms; i++) {
+-              struct inode *inode;
+-              struct dentry *dentry;
+-
+-              dentry = d_alloc_name(dir, perms[i]);
+-              if (!dentry) {
+-                      rc = -ENOMEM;
+-                      goto out1;
+-              }
+-
+-              inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
+-              if (!inode) {
+-                      rc = -ENOMEM;
+-                      goto out1;
+-              }
+-              inode->i_fop = &sel_perm_ops;
+-              /* i+1 since perm values are 1-indexed */
+-              inode->i_ino = sel_perm_to_ino(classvalue, i+1);
+-              d_add(dentry, inode);
+-      }
+-
+-out1:
+-      for (i = 0; i < nperms; i++)
+-              kfree(perms[i]);
+-      kfree(perms);
+-out:
+-      return rc;
+-}
+-
+-static int sel_make_class_dir_entries(char *classname, int index,
+-                                      struct dentry *dir)
+-{
+-      struct dentry *dentry = NULL;
+-      struct inode *inode = NULL;
+-      int rc;
+-
+-      dentry = d_alloc_name(dir, "index");
+-      if (!dentry) {
+-              rc = -ENOMEM;
+-              goto out;
+-      }
+-
+-      inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
+-      if (!inode) {
+-              rc = -ENOMEM;
+-              goto out;
+-      }
+-
+-      inode->i_fop = &sel_class_ops;
+-      inode->i_ino = sel_class_to_ino(index);
+-      d_add(dentry, inode);
+-
+-      dentry = d_alloc_name(dir, "perms");
+-      if (!dentry) {
+-              rc = -ENOMEM;
+-              goto out;
+-      }
+-
+-      rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino);
+-      if (rc)
+-              goto out;
+-
+-      rc = sel_make_perm_files(classname, index, dentry);
+-
+-out:
+-      return rc;
+-}
+-
+-static void sel_remove_classes(void)
+-{
+-      struct list_head *class_node;
+-
+-      list_for_each(class_node, &class_dir->d_subdirs) {
+-              struct dentry *class_subdir = list_entry(class_node,
+-                                      struct dentry, d_u.d_child);
+-              struct list_head *class_subdir_node;
+-
+-              list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
+-                      struct dentry *d = list_entry(class_subdir_node,
+-                                              struct dentry, d_u.d_child);
+-
+-                      if (d->d_inode)
+-                              if (d->d_inode->i_mode & S_IFDIR)
+-                                      sel_remove_entries(d);
+-              }
+-
+-              sel_remove_entries(class_subdir);
+-      }
+-
+-      sel_remove_entries(class_dir);
+-}
+-
+-static int sel_make_classes(void)
+-{
+-      int rc = 0, nclasses, i;
+-      char **classes;
+-
+-      /* delete any existing entries */
+-      sel_remove_classes();
+-
+-      rc = security_get_classes(&classes, &nclasses);
+-      if (rc < 0)
+-              goto out;
+-
+-      /* +2 since classes are 1-indexed */
+-      last_class_ino = sel_class_to_ino(nclasses+2);
+-
+-      for (i = 0; i < nclasses; i++) {
+-              struct dentry *class_name_dir;
+-
+-              class_name_dir = d_alloc_name(class_dir, classes[i]);
+-              if (!class_name_dir) {
+-                      rc = -ENOMEM;
+-                      goto out1;
+-              }
+-
+-              rc = sel_make_dir(class_dir->d_inode, class_name_dir,
+-                              &last_class_ino);
+-              if (rc)
+-                      goto out1;
+-
+-              /* i+1 since class values are 1-indexed */
+-              rc = sel_make_class_dir_entries(classes[i], i+1,
+-                              class_name_dir);
+-              if (rc)
+-                      goto out1;
+-      }
+-
+-out1:
+-      for (i = 0; i < nclasses; i++)
+-              kfree(classes[i]);
+-      kfree(classes);
+-out:
+-      return rc;
+-}
+-
+-static int sel_make_dir(struct inode *dir, struct dentry *dentry,
+-                      unsigned long *ino)
++static int sel_make_dir(struct inode *dir, struct dentry *dentry)
  {
        int ret = 0;
        struct inode *inode;
-@@ -1306,7 +1543,7 @@
+@@ -1543,7 +1306,7 @@
        }
        inode->i_op = &simple_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
--      inode->i_ino = ++sel_last_ino;
-+      inode->i_ino = ++(*ino);
+-      inode->i_ino = ++(*ino);
++      inode->i_ino = ++sel_last_ino;
        /* directory inodes start off with i_nlink == 2 (for "." entry) */
        inc_nlink(inode);
        d_add(dentry, inode);
-@@ -1352,7 +1589,7 @@
+@@ -1589,7 +1352,7 @@
                goto err;
        }
  
--      ret = sel_make_dir(root_inode, dentry);
-+      ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
+-      ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
++      ret = sel_make_dir(root_inode, dentry);
        if (ret)
                goto err;
  
-@@ -1385,7 +1622,7 @@
+@@ -1622,7 +1385,7 @@
                goto err;
        }
  
--      ret = sel_make_dir(root_inode, dentry);
-+      ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
+-      ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
++      ret = sel_make_dir(root_inode, dentry);
        if (ret)
                goto err;
  
-@@ -1399,7 +1636,7 @@
+@@ -1636,7 +1399,7 @@
                goto err;
        }
  
--      ret = sel_make_dir(root_inode, dentry);
-+      ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
+-      ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
++      ret = sel_make_dir(root_inode, dentry);
        if (ret)
                goto err;
  
-@@ -1407,6 +1644,18 @@
+@@ -1644,18 +1407,6 @@
        if (ret)
                goto err;
  
-+      dentry = d_alloc_name(sb->s_root, "class");
-+      if (!dentry) {
-+              ret = -ENOMEM;
-+              goto err;
-+      }
-+
-+      ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
-+      if (ret)
-+              goto err;
-+
-+      class_dir = dentry;
-+
+-      dentry = d_alloc_name(sb->s_root, "class");
+-      if (!dentry) {
+-              ret = -ENOMEM;
+-              goto err;
+-      }
+-
+-      ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
+-      if (ret)
+-              goto err;
+-
+-      class_dir = dentry;
+-
  out:
        return ret;
  err:
-diff -Nurb linux-2.6.22-570/security/selinux/ss/policydb.c linux-2.6.22-590/security/selinux/ss/policydb.c
---- linux-2.6.22-570/security/selinux/ss/policydb.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/selinux/ss/policydb.c    2008-01-02 13:56:38.000000000 -0500
-@@ -21,6 +21,7 @@
+diff -Nurb linux-2.6.22-590/security/selinux/ss/policydb.c linux-2.6.22-570/security/selinux/ss/policydb.c
+--- linux-2.6.22-590/security/selinux/ss/policydb.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/ss/policydb.c    2007-07-08 19:32:17.000000000 -0400
+@@ -21,7 +21,6 @@
   */
  
  #include <linux/kernel.h>
-+#include <linux/sched.h>
+-#include <linux/sched.h>
  #include <linux/slab.h>
  #include <linux/string.h>
  #include <linux/errno.h>
-@@ -598,6 +599,7 @@
+@@ -599,7 +598,6 @@
        struct range_trans *rt, *lrt = NULL;
  
        for (i = 0; i < SYM_NUM; i++) {
-+              cond_resched();
+-              cond_resched();
                hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
                hashtab_destroy(p->symtab[i].table);
        }
-@@ -612,6 +614,7 @@
+@@ -614,7 +612,6 @@
        avtab_destroy(&p->te_avtab);
  
        for (i = 0; i < OCON_NUM; i++) {
-+              cond_resched();
+-              cond_resched();
                c = p->ocontexts[i];
                while (c) {
                        ctmp = c;
-@@ -623,6 +626,7 @@
+@@ -626,7 +623,6 @@
  
        g = p->genfs;
        while (g) {
-+              cond_resched();
+-              cond_resched();
                kfree(g->fstype);
                c = g->head;
                while (c) {
-@@ -639,18 +643,21 @@
+@@ -643,21 +639,18 @@
        cond_policydb_destroy(p);
  
        for (tr = p->role_tr; tr; tr = tr->next) {
-+              cond_resched();
+-              cond_resched();
                kfree(ltr);
                ltr = tr;
        }
        kfree(ltr);
  
        for (ra = p->role_allow; ra; ra = ra -> next) {
-+              cond_resched();
+-              cond_resched();
                kfree(lra);
                lra = ra;
        }
        kfree(lra);
  
        for (rt = p->range_tr; rt; rt = rt -> next) {
-+              cond_resched();
+-              cond_resched();
                if (lrt) {
                        ebitmap_destroy(&lrt->target_range.level[0].cat);
                        ebitmap_destroy(&lrt->target_range.level[1].cat);
-diff -Nurb linux-2.6.22-570/security/selinux/ss/services.c linux-2.6.22-590/security/selinux/ss/services.c
---- linux-2.6.22-570/security/selinux/ss/services.c    2007-07-08 19:32:17.000000000 -0400
-+++ linux-2.6.22-590/security/selinux/ss/services.c    2008-01-02 13:56:38.000000000 -0500
-@@ -1587,19 +1587,18 @@
+diff -Nurb linux-2.6.22-590/security/selinux/ss/services.c linux-2.6.22-570/security/selinux/ss/services.c
+--- linux-2.6.22-590/security/selinux/ss/services.c    2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/security/selinux/ss/services.c    2007-07-08 19:32:17.000000000 -0400
+@@ -1587,18 +1587,19 @@
                           u32 *nel)
  {
        struct context *fromcon, usercon;
--      u32 *mysids, *mysids2, sid;
-+      u32 *mysids = NULL, *mysids2, sid;
+-      u32 *mysids = NULL, *mysids2, sid;
++      u32 *mysids, *mysids2, sid;
        u32 mynel = 0, maxnel = SIDS_NEL;
        struct user_datum *user;
        struct role_datum *role;
--      struct av_decision avd;
++      struct av_decision avd;
        struct ebitmap_node *rnode, *tnode;
        int rc = 0, i, j;
  
--      if (!ss_initialized) {
++      if (!ss_initialized) {
                *sids = NULL;
                *nel = 0;
-+
-+      if (!ss_initialized)
+-
+-      if (!ss_initialized)
                goto out;
--      }
++      }
  
        POLICY_RDLOCK;
  
-@@ -1635,17 +1634,9 @@
+@@ -1634,9 +1635,17 @@
                        if (mls_setup_user_range(fromcon, user, &usercon))
                                continue;
  
--                      rc = context_struct_compute_av(fromcon, &usercon,
--                                                     SECCLASS_PROCESS,
--                                                     PROCESS__TRANSITION,
--                                                     &avd);
--                      if (rc ||  !(avd.allowed & PROCESS__TRANSITION))
--                              continue;
++                      rc = context_struct_compute_av(fromcon, &usercon,
++                                                     SECCLASS_PROCESS,
++                                                     PROCESS__TRANSITION,
++                                                     &avd);
++                      if (rc ||  !(avd.allowed & PROCESS__TRANSITION))
++                              continue;
                        rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
--                      if (rc) {
--                              kfree(mysids);
-+                      if (rc)
+-                      if (rc)
++                      if (rc) {
++                              kfree(mysids);
                                goto out_unlock;
--                      }
++                      }
                        if (mynel < maxnel) {
                                mysids[mynel++] = sid;
                        } else {
-@@ -1653,7 +1644,6 @@
+@@ -1644,6 +1653,7 @@
                                mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
                                if (!mysids2) {
                                        rc = -ENOMEM;
--                                      kfree(mysids);
++                                      kfree(mysids);
                                        goto out_unlock;
                                }
                                memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
-@@ -1664,11 +1654,32 @@
+@@ -1654,32 +1664,11 @@
                }
        }
  
--      *sids = mysids;
--      *nel = mynel;
--
++      *sids = mysids;
++      *nel = mynel;
++
  out_unlock:
        POLICY_RDUNLOCK;
-+      if (rc || !mynel) {
-+              kfree(mysids);
-+              goto out;
-+      }
-+
-+      mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
-+      if (!mysids2) {
-+              rc = -ENOMEM;
-+              kfree(mysids);
-+              goto out;
-+      }
-+      for (i = 0, j = 0; i < mynel; i++) {
-+              rc = avc_has_perm_noaudit(fromsid, mysids[i],
-+                                        SECCLASS_PROCESS,
-+                                        PROCESS__TRANSITION, AVC_STRICT,
-+                                        NULL);
-+              if (!rc)
-+                      mysids2[j++] = mysids[i];
-+              cond_resched();
-+      }
-+      rc = 0;
-+      kfree(mysids);
-+      *sids = mysids2;
-+      *nel = j;
+-      if (rc || !mynel) {
+-              kfree(mysids);
+-              goto out;
+-      }
+-
+-      mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
+-      if (!mysids2) {
+-              rc = -ENOMEM;
+-              kfree(mysids);
+-              goto out;
+-      }
+-      for (i = 0, j = 0; i < mynel; i++) {
+-              rc = avc_has_perm_noaudit(fromsid, mysids[i],
+-                                        SECCLASS_PROCESS,
+-                                        PROCESS__TRANSITION, AVC_STRICT,
+-                                        NULL);
+-              if (!rc)
+-                      mysids2[j++] = mysids[i];
+-              cond_resched();
+-      }
+-      rc = 0;
+-      kfree(mysids);
+-      *sids = mysids2;
+-      *nel = j;
  out:
        return rc;
  }
-@@ -1996,6 +2007,101 @@
+@@ -2007,101 +1996,6 @@
        return rc;
  }
  
-+static int get_classes_callback(void *k, void *d, void *args)
-+{
-+      struct class_datum *datum = d;
-+      char *name = k, **classes = args;
-+      int value = datum->value - 1;
-+
-+      classes[value] = kstrdup(name, GFP_ATOMIC);
-+      if (!classes[value])
-+              return -ENOMEM;
-+
-+      return 0;
-+}
-+
-+int security_get_classes(char ***classes, int *nclasses)
-+{
-+      int rc = -ENOMEM;
-+
-+      POLICY_RDLOCK;
-+
-+      *nclasses = policydb.p_classes.nprim;
-+      *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC);
-+      if (!*classes)
-+              goto out;
-+
-+      rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
-+                      *classes);
-+      if (rc < 0) {
-+              int i;
-+              for (i = 0; i < *nclasses; i++)
-+                      kfree((*classes)[i]);
-+              kfree(*classes);
-+      }
-+
-+out:
-+      POLICY_RDUNLOCK;
-+      return rc;
-+}
-+
-+static int get_permissions_callback(void *k, void *d, void *args)
-+{
-+      struct perm_datum *datum = d;
-+      char *name = k, **perms = args;
-+      int value = datum->value - 1;
-+
-+      perms[value] = kstrdup(name, GFP_ATOMIC);
-+      if (!perms[value])
-+              return -ENOMEM;
-+
-+      return 0;
-+}
-+
-+int security_get_permissions(char *class, char ***perms, int *nperms)
-+{
-+      int rc = -ENOMEM, i;
-+      struct class_datum *match;
-+
-+      POLICY_RDLOCK;
-+
-+      match = hashtab_search(policydb.p_classes.table, class);
-+      if (!match) {
-+              printk(KERN_ERR "%s:  unrecognized class %s\n",
-+                      __FUNCTION__, class);
-+              rc = -EINVAL;
-+              goto out;
-+      }
-+
-+      *nperms = match->permissions.nprim;
-+      *perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC);
-+      if (!*perms)
-+              goto out;
-+
-+      if (match->comdatum) {
-+              rc = hashtab_map(match->comdatum->permissions.table,
-+                              get_permissions_callback, *perms);
-+              if (rc < 0)
-+                      goto err;
-+      }
-+
-+      rc = hashtab_map(match->permissions.table, get_permissions_callback,
-+                      *perms);
-+      if (rc < 0)
-+              goto err;
-+
-+out:
-+      POLICY_RDUNLOCK;
-+      return rc;
-+
-+err:
-+      POLICY_RDUNLOCK;
-+      for (i = 0; i < *nperms; i++)
-+              kfree((*perms)[i]);
-+      kfree(*perms);
-+      return rc;
-+}
-+
+-static int get_classes_callback(void *k, void *d, void *args)
+-{
+-      struct class_datum *datum = d;
+-      char *name = k, **classes = args;
+-      int value = datum->value - 1;
+-
+-      classes[value] = kstrdup(name, GFP_ATOMIC);
+-      if (!classes[value])
+-              return -ENOMEM;
+-
+-      return 0;
+-}
+-
+-int security_get_classes(char ***classes, int *nclasses)
+-{
+-      int rc = -ENOMEM;
+-
+-      POLICY_RDLOCK;
+-
+-      *nclasses = policydb.p_classes.nprim;
+-      *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC);
+-      if (!*classes)
+-              goto out;
+-
+-      rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
+-                      *classes);
+-      if (rc < 0) {
+-              int i;
+-              for (i = 0; i < *nclasses; i++)
+-                      kfree((*classes)[i]);
+-              kfree(*classes);
+-      }
+-
+-out:
+-      POLICY_RDUNLOCK;
+-      return rc;
+-}
+-
+-static int get_permissions_callback(void *k, void *d, void *args)
+-{
+-      struct perm_datum *datum = d;
+-      char *name = k, **perms = args;
+-      int value = datum->value - 1;
+-
+-      perms[value] = kstrdup(name, GFP_ATOMIC);
+-      if (!perms[value])
+-              return -ENOMEM;
+-
+-      return 0;
+-}
+-
+-int security_get_permissions(char *class, char ***perms, int *nperms)
+-{
+-      int rc = -ENOMEM, i;
+-      struct class_datum *match;
+-
+-      POLICY_RDLOCK;
+-
+-      match = hashtab_search(policydb.p_classes.table, class);
+-      if (!match) {
+-              printk(KERN_ERR "%s:  unrecognized class %s\n",
+-                      __FUNCTION__, class);
+-              rc = -EINVAL;
+-              goto out;
+-      }
+-
+-      *nperms = match->permissions.nprim;
+-      *perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC);
+-      if (!*perms)
+-              goto out;
+-
+-      if (match->comdatum) {
+-              rc = hashtab_map(match->comdatum->permissions.table,
+-                              get_permissions_callback, *perms);
+-              if (rc < 0)
+-                      goto err;
+-      }
+-
+-      rc = hashtab_map(match->permissions.table, get_permissions_callback,
+-                      *perms);
+-      if (rc < 0)
+-              goto err;
+-
+-out:
+-      POLICY_RDUNLOCK;
+-      return rc;
+-
+-err:
+-      POLICY_RDUNLOCK;
+-      for (i = 0; i < *nperms; i++)
+-              kfree((*perms)[i]);
+-      kfree(*perms);
+-      return rc;
+-}
+-
  struct selinux_audit_rule {
        u32 au_seqno;
        struct context au_ctxt;
-diff -Nurb linux-2.6.22-570/toapply linux-2.6.22-590/toapply
---- linux-2.6.22-570/toapply   1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/toapply   2008-01-02 13:56:38.000000000 -0500
-@@ -0,0 +1,51 @@
-+cat ../broken-out/cpuidle-fix-the-uninitialized-variable-in-sysfs-routine.patch | patch -p1
-+cat ../broken-out/cpuidle-make-cpuidle-sysfs-driver-governor-switch-off-by-default.patch | patch -p1
-+cat ../broken-out/acpi-video-dont-export-sysfs-backlight-interface-if-query-_bcl-fail.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-rules.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-move-release_sysfs_dirent-to-dirc.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-allocate-inode-number-using-ida.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-make-sysfs_put-ignore-null-sd.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-fix-error-handling-in-binattr-write.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-flatten-cleanup-paths-in-sysfs_add_link-and-create_dir.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-flatten-and-fix-sysfs_rename_dir-error-handling.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-consolidate-sysfs_dirent-creation-functions.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-add-sysfs_dirent-s_parent.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-add-sysfs_dirent-s_name.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-make-sysfs_dirent-s_element-a-union.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-implement-kobj_sysfs_assoc_lock.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-reimplement-symlink-using-sysfs_dirent-tree.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-implement-bin_buffer.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_dirent-active-reference-and-immediate-disconnect.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-kill-attribute-file-orphaning.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-separate-out-sysfs_attach_dentry.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-reimplement-sysfs_drop_dentry.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-kill-unnecessary-attribute-owner.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-make-sysfs_alloc_ino-static.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-fix-parent-refcounting-during-rename-and-move.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-reorganize-sysfs_new_indoe-and-sysfs_create.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-use-iget_locked-instead-of-new_inode.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-fix-root-sysfs_dirent-root-dentry-association.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-move-s_active-functions-to-fs-sysfs-dirc.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-slim-down-sysfs_dirent-s_active.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-use-singly-linked-list-for-sysfs_dirent-tree.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-fix-oops-in-sysfs_drop_dentry-on-x86_64.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-make-sysfs_drop_dentry-access-inodes-using-ilookup.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-rename-sysfs_dirent-s_type-to-s_flags-and-make-room-for-flags.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_flag_removed-flag.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_find_dirent-and-sysfs_get_dirent.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-make-kobj-point-to-sysfs_dirent-instead-of-dentry.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-consolidate-sysfs-spinlocks.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-use-sysfs_mutex-to-protect-the-sysfs_dirent-tree.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-restructure-add-remove-paths-and-fix-inode-update.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-move-sysfs_drop_dentry-to-dirc-and-make-it-static.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_get_dentry.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-make-directory-dentries-and-inodes-reclaimable.patch | patch -p1
-+cat ../broken-out/driver-core-check-return-code-of-sysfs_create_link.patch | patch -p1
-+cat ../broken-out/driver-core-check-return-code-of-sysfs_create_link-fix.patch | patch -p1
-+cat ../broken-out/git-scsi-misc-vs-greg-sysfs-stuff.patch | patch -p1
-+cat ../broken-out/gregkh-usb-usb-cxacru-cleanup-sysfs-attribute-code.patch | patch -p1
-+cat ../broken-out/gregkh-usb-usb-add-iad-support-to-usbfs-and-sysfs.patch | patch -p1
-+cat ../broken-out/x86_64-mm-xen-add-the-xenbus-sysfs-and-virtual-device-hotplug-driver.patch | patch -p1
-+cat ../broken-out/drivers-edac-mc-sysfs-add-missing-mem-types.patch | patch -p1
-+cat ../broken-out/drivers-edac-edac_device-sysfs-cleanup.patch | patch -p1
-+cat ../broken-out/drivers-edac-add-device-sysfs-attributes.patch | patch -p1
-diff -Nurb linux-2.6.22-570/trellis-mm1-1.sh linux-2.6.22-590/trellis-mm1-1.sh
---- linux-2.6.22-570/trellis-mm1-1.sh  1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.22-590/trellis-mm1-1.sh  2008-01-02 13:56:38.000000000 -0500
-@@ -0,0 +1,142 @@
-+cat ../broken-out/origin.patch | patch -p1
-+cat ../broken-out/ioatdma-fix-section-mismatches.patch | patch -p1
-+cat ../broken-out/introduce-fixed-sys_sync_file_range2-syscall-implement-on.patch | patch -p1
-+cat ../broken-out/git-acpi.patch | patch -p1
-+cat ../broken-out/agk-dm-dm-netlink.patch | patch -p1
-+cat ../broken-out/git-powerpc.patch | patch -p1
-+cat ../broken-out/make-drivers-char-hvc_consoleckhvcd-static.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-move-release_sysfs_dirent-to-dirc.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-allocate-inode-number-using-ida.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-make-sysfs_put-ignore-null-sd.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-fix-error-handling-in-binattr-write.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-flatten-cleanup-paths-in-sysfs_add_link-and-create_dir.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-flatten-and-fix-sysfs_rename_dir-error-handling.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-consolidate-sysfs_dirent-creation-functions.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-add-sysfs_dirent-s_parent.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-add-sysfs_dirent-s_name.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-make-sysfs_dirent-s_element-a-union.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-implement-kobj_sysfs_assoc_lock.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-reimplement-symlink-using-sysfs_dirent-tree.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-implement-bin_buffer.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_dirent-active-reference-and-immediate-disconnect.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-kill-attribute-file-orphaning.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-separate-out-sysfs_attach_dentry.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-reimplement-sysfs_drop_dentry.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-kill-unnecessary-attribute-owner.patch | patch -p1
-+cat ../broken-out/gregkh-driver-driver-core-make-devt_attr-and-uevent_attr-static.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-make-sysfs_alloc_ino-static.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-fix-parent-refcounting-during-rename-and-move.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-reorganize-sysfs_new_indoe-and-sysfs_create.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-use-iget_locked-instead-of-new_inode.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-move-s_active-functions-to-fs-sysfs-dirc.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-slim-down-sysfs_dirent-s_active.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-use-singly-linked-list-for-sysfs_dirent-tree.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-fix-oops-in-sysfs_drop_dentry-on-x86_64.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-make-sysfs_drop_dentry-access-inodes-using-ilookup.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-rename-sysfs_dirent-s_type-to-s_flags-and-make-room-for-flags.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_flag_removed-flag.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_find_dirent-and-sysfs_get_dirent.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-make-kobj-point-to-sysfs_dirent-instead-of-dentry.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-consolidate-sysfs-spinlocks.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-use-sysfs_mutex-to-protect-the-sysfs_dirent-tree.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-restructure-add-remove-paths-and-fix-inode-update.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-move-sysfs_drop_dentry-to-dirc-and-make-it-static.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_get_dentry.patch | patch -p1
-+cat ../broken-out/gregkh-driver-sysfs-make-directory-dentries-and-inodes-reclaimable.patch | patch -p1
-+cat ../broken-out/gregkh-driver-block-device.patch | patch -p1
-+cat ../broken-out/revert-gregkh-driver-block-device.patch | patch -p1
-+cat ../broken-out/driver-core-check-return-code-of-sysfs_create_link.patch | patch -p1
-+cat ../broken-out/git-md-accel.patch | patch -p1
-+cat ../broken-out/git-mmc.patch | patch -p1
-+cat ../broken-out/git-net.patch | patch -p1
-+cat ../broken-out/tun-tap-allow-group-ownership-of-tun-tap-devices.patch | patch -p1
-+cat ../broken-out/git-nfs.patch | patch -p1
-+cat ../broken-out/git-ocfs2.patch | patch -p1
-+cat ../broken-out/git-selinux.patch | patch -p1
-+cat ../broken-out/revert-acpi-change-for-scsi.patch | patch -p1
-+cat ../broken-out/git-scsi-misc.patch | patch -p1
-+cat ../broken-out/git-unionfs.patch | patch -p1
-+cat ../broken-out/x86_64-mm-unwinder.patch | patch -p1
-+cat ../broken-out/x86_64-mm-xencleanup-add-kstrndup.patch | patch -p1
-+cat ../broken-out/x86_64-mm-xencleanup-add-argv_split.patch | patch -p1
-+cat ../broken-out/x86_64-mm-xencleanup-split-usermodehelper-setup-from-execution.patch | patch -p1
-+cat ../broken-out/x86_64-mm-add-common-orderly_poweroff.patch | patch -p1
-+cat ../broken-out/x86_64-mm-xencleanup-tidy-up-usermode-helper-waiting-a-bit.patch | patch -p1
-+cat ../broken-out/x86_64-mm-xen-add-the-xen-virtual-network-device-driver.patch | patch -p1
-+cat ../broken-out/i386-show-unhandled-signals.patch | patch -p1
-+cat ../broken-out/git-kgdb.patch | patch -p1
-+cat ../broken-out/hugetlb-remove-unnecessary-nid-initialization.patch | patch -p1
-+cat ../broken-out/mm-alloc_large_system_hash-can-free-some-memory-for.patch | patch -p1
-+cat ../broken-out/mm-fix-fault-vs-invalidate-race-for-linear-mappings.patch | patch -p1
-+cat ../broken-out/mm-fix-fault-vs-invalidate-race-for-linear-mappings-fix.patch | patch -p1
-+cat ../broken-out/mm-merge-populate-and-nopage-into-fault-fixes-nonlinear.patch | patch -p1
-+cat ../broken-out/add-a-bitmap-that-is-used-to-track-flags-affecting-a-block-of-pages.patch | patch -p1
-+cat ../broken-out/add-__gfp_movable-for-callers-to-flag-allocations-from-high-memory-that-may-be-migrated.patch | patch -p1
-+cat ../broken-out/split-the-free-lists-for-movable-and-unmovable-allocations.patch | patch -p1
-+cat ../broken-out/choose-pages-from-the-per-cpu-list-based-on-migration-type.patch | patch -p1
-+cat ../broken-out/add-a-configure-option-to-group-pages-by-mobility.patch | patch -p1
-+cat ../broken-out/move-free-pages-between-lists-on-steal.patch | patch -p1
-+cat ../broken-out/group-short-lived-and-reclaimable-kernel-allocations.patch | patch -p1
-+cat ../broken-out/allow-huge-page-allocations-to-use-gfp_high_movable.patch | patch -p1
-+cat ../broken-out/maps2-uninline-some-functions-in-the-page-walker.patch | patch -p1
-+cat ../broken-out/maps2-eliminate-the-pmd_walker-struct-in-the-page-walker.patch | patch -p1
-+cat ../broken-out/maps2-remove-vma-from-args-in-the-page-walker.patch | patch -p1
-+cat ../broken-out/maps2-propagate-errors-from-callback-in-page-walker.patch | patch -p1
-+cat ../broken-out/maps2-add-callbacks-for-each-level-to-page-walker.patch | patch -p1
-+cat ../broken-out/maps2-move-the-page-walker-code-to-lib.patch | patch -p1
-+cat ../broken-out/maps2-simplify-interdependence-of-proc-pid-maps-and-smaps.patch | patch -p1
-+cat ../broken-out/maps2-move-clear_refs-code-to-task_mmuc.patch | patch -p1
-+cat ../broken-out/maps2-regroup-task_mmu-by-interface.patch | patch -p1
-+cat ../broken-out/maps2-make-proc-pid-smaps-optional-under-config_embedded.patch | patch -p1
-+cat ../broken-out/maps2-make-proc-pid-clear_refs-option-under-config_embedded.patch | patch -p1
-+cat ../broken-out/maps2-add-proc-pid-pagemap-interface.patch | patch -p1
-+cat ../broken-out/have-kswapd-keep-a-minimum-order-free-other-than-order-0.patch | patch -p1
-+cat ../broken-out/freezer-make-kernel-threads-nonfreezable-by-default.patch | patch -p1
-+cat ../broken-out/freezer-make-kernel-threads-nonfreezable-by-default-fix.patch | patch -p1
-+cat ../broken-out/freezer-make-kernel-threads-nonfreezable-by-default-fix-2.patch | patch -p1
-+cat ../broken-out/uml-use-get_free_pages-to-allocate-kernel-stacks.patch | patch -p1
-+cat ../broken-out/add-generic-exit-time-stack-depth-checking-to-config_debug_stack_usage.patch | patch -p1
-+cat ../broken-out/cpuset-remove-sched-domain-hooks-from-cpusets.patch | patch -p1
-+cat ../broken-out/clone-flag-clone_parent_tidptr-leaves-invalid-results-in-memory.patch | patch -p1
-+cat ../broken-out/use-boot-based-time-for-process-start-time-and-boot-time.patch | patch -p1
-+cat ../broken-out/reduce-cpusetc-write_lock_irq-to-read_lock.patch | patch -p1
-+cat ../broken-out/reduce-cpusetc-write_lock_irq-to-read_lock-fix.patch | patch -p1
-+cat ../broken-out/taskstats-add-context-switch-counters.patch | patch -p1
-+cat ../broken-out/taskstats-add-context-switch-counters-fix.patch | patch -p1
-+cat ../broken-out/remove-config_uts_ns-and-config_ipc_ns.patch | patch -p1
-+cat ../broken-out/user-namespace-add-the-framework.patch | patch -p1
-+cat ../broken-out/user-namespace-add-unshare.patch | patch -p1
-+cat ../broken-out/mm-fix-create_new_namespaces-return-value.patch | patch -p1
-+cat ../broken-out/add-a-kmem_cache-for-nsproxy-objects.patch | patch -p1
-+cat ../broken-out/namespace-ensure-clone_flags-are-always-stored-in-an-unsigned-long.patch | patch -p1
-+cat ../broken-out/sysctlc-add-text-telling-people-to-use-ctl_unnumbered.patch | patch -p1
-+cat ../broken-out/proper-prototype-for-proc_nr_files.patch | patch -p1
-+cat ../broken-out/move-seccomp-from-proc-to-a-prctl.patch | patch -p1
-+cat ../broken-out/uninline-check_signature.patch | patch -p1
-+cat ../broken-out/revoke-core-code.patch | patch -p1
-+cat ../broken-out/revoke-wire-up-i386-system-calls.patch | patch -p1
-+cat ../broken-out/fallocate-implementation-on-i86-x86_64-and-powerpc.patch | patch -p1
-+cat ../broken-out/coredump-masking-reimplementation-of-dumpable-using-two-flags.patch | patch -p1
-+cat ../broken-out/coredump-masking-add-an-interface-for-core-dump-filter.patch | patch -p1
-+cat ../broken-out/cpuset-zero-malloc-revert-the-old-cpuset-fix.patch | patch -p1
-+cat ../broken-out/containersv10-basic-container-framework.patch | patch -p1
-+cat ../broken-out/containersv10-basic-container-framework-fix.patch | patch -p1
-+cat ../broken-out/containersv10-basic-container-framework-fix-for-bad-lock-balance-in-containers.patch | patch -p1
-+cat ../broken-out/containersv10-example-cpu-accounting-subsystem.patch | patch -p1
-+cat ../broken-out/containersv10-add-tasks-file-interface.patch | patch -p1
-+cat ../broken-out/containersv10-add-tasks-file-interface-fix.patch | patch -p1
-+cat ../broken-out/containersv10-add-tasks-file-interface-fix-2.patch | patch -p1
-+cat ../broken-out/containersv10-add-fork-exit-hooks.patch | patch -p1
-+cat ../broken-out/containersv10-add-fork-exit-hooks-fix.patch | patch -p1
-+cat ../broken-out/containersv10-add-container_clone-interface.patch | patch -p1
-+cat ../broken-out/containersv10-add-procfs-interface.patch | patch -p1
-+cat ../broken-out/containersv10-add-procfs-interface-fix.patch | patch -p1
-+cat ../broken-out/containersv10-make-cpusets-a-client-of-containers.patch | patch -p1
-+cat ../broken-out/containersv10-share-css_group-arrays-between-tasks-with-same-container-memberships.patch | patch -p1
-+cat ../broken-out/containersv10-share-css_group-arrays-between-tasks-with-same-container-memberships-cpuset-zero-malloc-fix-for-new-containers.patch | patch -p1
-+cat ../broken-out/containersv10-simple-debug-info-subsystem.patch | patch -p1
-+cat ../broken-out/containersv10-support-for-automatic-userspace-release-agents.patch | patch -p1
-+cat ../broken-out/containers-implement-subsys-post_clone.patch | patch -p1
-+cat ../broken-out/containers-implement-namespace-tracking-subsystem-v3.patch | patch -p1
-+cat ../broken-out/keep-track-of-network-interface-renaming.patch | patch -p1
-+cat ../broken-out/v2.6.22-rc6-mm1-netns23.patch | patch -p1
+diff -Nurb linux-2.6.22-590/toapply linux-2.6.22-570/toapply
+--- linux-2.6.22-590/toapply   2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/toapply   1969-12-31 19:00:00.000000000 -0500
+@@ -1,51 +0,0 @@
+-cat ../broken-out/cpuidle-fix-the-uninitialized-variable-in-sysfs-routine.patch | patch -p1
+-cat ../broken-out/cpuidle-make-cpuidle-sysfs-driver-governor-switch-off-by-default.patch | patch -p1
+-cat ../broken-out/acpi-video-dont-export-sysfs-backlight-interface-if-query-_bcl-fail.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-rules.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-move-release_sysfs_dirent-to-dirc.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-allocate-inode-number-using-ida.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-make-sysfs_put-ignore-null-sd.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-fix-error-handling-in-binattr-write.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-flatten-cleanup-paths-in-sysfs_add_link-and-create_dir.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-flatten-and-fix-sysfs_rename_dir-error-handling.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-consolidate-sysfs_dirent-creation-functions.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-add-sysfs_dirent-s_parent.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-add-sysfs_dirent-s_name.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-make-sysfs_dirent-s_element-a-union.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-implement-kobj_sysfs_assoc_lock.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-reimplement-symlink-using-sysfs_dirent-tree.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-implement-bin_buffer.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_dirent-active-reference-and-immediate-disconnect.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-kill-attribute-file-orphaning.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-separate-out-sysfs_attach_dentry.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-reimplement-sysfs_drop_dentry.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-kill-unnecessary-attribute-owner.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-make-sysfs_alloc_ino-static.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-fix-parent-refcounting-during-rename-and-move.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-reorganize-sysfs_new_indoe-and-sysfs_create.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-use-iget_locked-instead-of-new_inode.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-fix-root-sysfs_dirent-root-dentry-association.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-move-s_active-functions-to-fs-sysfs-dirc.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-slim-down-sysfs_dirent-s_active.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-use-singly-linked-list-for-sysfs_dirent-tree.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-fix-oops-in-sysfs_drop_dentry-on-x86_64.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-make-sysfs_drop_dentry-access-inodes-using-ilookup.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-rename-sysfs_dirent-s_type-to-s_flags-and-make-room-for-flags.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_flag_removed-flag.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_find_dirent-and-sysfs_get_dirent.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-make-kobj-point-to-sysfs_dirent-instead-of-dentry.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-consolidate-sysfs-spinlocks.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-use-sysfs_mutex-to-protect-the-sysfs_dirent-tree.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-restructure-add-remove-paths-and-fix-inode-update.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-move-sysfs_drop_dentry-to-dirc-and-make-it-static.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_get_dentry.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-make-directory-dentries-and-inodes-reclaimable.patch | patch -p1
+-cat ../broken-out/driver-core-check-return-code-of-sysfs_create_link.patch | patch -p1
+-cat ../broken-out/driver-core-check-return-code-of-sysfs_create_link-fix.patch | patch -p1
+-cat ../broken-out/git-scsi-misc-vs-greg-sysfs-stuff.patch | patch -p1
+-cat ../broken-out/gregkh-usb-usb-cxacru-cleanup-sysfs-attribute-code.patch | patch -p1
+-cat ../broken-out/gregkh-usb-usb-add-iad-support-to-usbfs-and-sysfs.patch | patch -p1
+-cat ../broken-out/x86_64-mm-xen-add-the-xenbus-sysfs-and-virtual-device-hotplug-driver.patch | patch -p1
+-cat ../broken-out/drivers-edac-mc-sysfs-add-missing-mem-types.patch | patch -p1
+-cat ../broken-out/drivers-edac-edac_device-sysfs-cleanup.patch | patch -p1
+-cat ../broken-out/drivers-edac-add-device-sysfs-attributes.patch | patch -p1
+diff -Nurb linux-2.6.22-590/trellis-mm1-1.sh linux-2.6.22-570/trellis-mm1-1.sh
+--- linux-2.6.22-590/trellis-mm1-1.sh  2008-01-23 19:16:21.000000000 -0500
++++ linux-2.6.22-570/trellis-mm1-1.sh  1969-12-31 19:00:00.000000000 -0500
+@@ -1,142 +0,0 @@
+-cat ../broken-out/origin.patch | patch -p1
+-cat ../broken-out/ioatdma-fix-section-mismatches.patch | patch -p1
+-cat ../broken-out/introduce-fixed-sys_sync_file_range2-syscall-implement-on.patch | patch -p1
+-cat ../broken-out/git-acpi.patch | patch -p1
+-cat ../broken-out/agk-dm-dm-netlink.patch | patch -p1
+-cat ../broken-out/git-powerpc.patch | patch -p1
+-cat ../broken-out/make-drivers-char-hvc_consoleckhvcd-static.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-move-release_sysfs_dirent-to-dirc.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-allocate-inode-number-using-ida.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-make-sysfs_put-ignore-null-sd.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-fix-error-handling-in-binattr-write.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-flatten-cleanup-paths-in-sysfs_add_link-and-create_dir.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-flatten-and-fix-sysfs_rename_dir-error-handling.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-consolidate-sysfs_dirent-creation-functions.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-add-sysfs_dirent-s_parent.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-add-sysfs_dirent-s_name.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-make-sysfs_dirent-s_element-a-union.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-implement-kobj_sysfs_assoc_lock.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-reimplement-symlink-using-sysfs_dirent-tree.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-implement-bin_buffer.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_dirent-active-reference-and-immediate-disconnect.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-kill-attribute-file-orphaning.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-separate-out-sysfs_attach_dentry.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-reimplement-sysfs_drop_dentry.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-kill-unnecessary-attribute-owner.patch | patch -p1
+-cat ../broken-out/gregkh-driver-driver-core-make-devt_attr-and-uevent_attr-static.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-make-sysfs_alloc_ino-static.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-fix-parent-refcounting-during-rename-and-move.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-reorganize-sysfs_new_indoe-and-sysfs_create.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-use-iget_locked-instead-of-new_inode.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-move-s_active-functions-to-fs-sysfs-dirc.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-slim-down-sysfs_dirent-s_active.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-use-singly-linked-list-for-sysfs_dirent-tree.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-fix-oops-in-sysfs_drop_dentry-on-x86_64.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-make-sysfs_drop_dentry-access-inodes-using-ilookup.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-rename-sysfs_dirent-s_type-to-s_flags-and-make-room-for-flags.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_flag_removed-flag.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_find_dirent-and-sysfs_get_dirent.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-make-kobj-point-to-sysfs_dirent-instead-of-dentry.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-consolidate-sysfs-spinlocks.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-use-sysfs_mutex-to-protect-the-sysfs_dirent-tree.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-restructure-add-remove-paths-and-fix-inode-update.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-move-sysfs_drop_dentry-to-dirc-and-make-it-static.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-implement-sysfs_get_dentry.patch | patch -p1
+-cat ../broken-out/gregkh-driver-sysfs-make-directory-dentries-and-inodes-reclaimable.patch | patch -p1
+-cat ../broken-out/gregkh-driver-block-device.patch | patch -p1
+-cat ../broken-out/revert-gregkh-driver-block-device.patch | patch -p1
+-cat ../broken-out/driver-core-check-return-code-of-sysfs_create_link.patch | patch -p1
+-cat ../broken-out/git-md-accel.patch | patch -p1
+-cat ../broken-out/git-mmc.patch | patch -p1
+-cat ../broken-out/git-net.patch | patch -p1
+-cat ../broken-out/tun-tap-allow-group-ownership-of-tun-tap-devices.patch | patch -p1
+-cat ../broken-out/git-nfs.patch | patch -p1
+-cat ../broken-out/git-ocfs2.patch | patch -p1
+-cat ../broken-out/git-selinux.patch | patch -p1
+-cat ../broken-out/revert-acpi-change-for-scsi.patch | patch -p1
+-cat ../broken-out/git-scsi-misc.patch | patch -p1
+-cat ../broken-out/git-unionfs.patch | patch -p1
+-cat ../broken-out/x86_64-mm-unwinder.patch | patch -p1
+-cat ../broken-out/x86_64-mm-xencleanup-add-kstrndup.patch | patch -p1
+-cat ../broken-out/x86_64-mm-xencleanup-add-argv_split.patch | patch -p1
+-cat ../broken-out/x86_64-mm-xencleanup-split-usermodehelper-setup-from-execution.patch | patch -p1
+-cat ../broken-out/x86_64-mm-add-common-orderly_poweroff.patch | patch -p1
+-cat ../broken-out/x86_64-mm-xencleanup-tidy-up-usermode-helper-waiting-a-bit.patch | patch -p1
+-cat ../broken-out/x86_64-mm-xen-add-the-xen-virtual-network-device-driver.patch | patch -p1
+-cat ../broken-out/i386-show-unhandled-signals.patch | patch -p1
+-cat ../broken-out/git-kgdb.patch | patch -p1
+-cat ../broken-out/hugetlb-remove-unnecessary-nid-initialization.patch | patch -p1
+-cat ../broken-out/mm-alloc_large_system_hash-can-free-some-memory-for.patch | patch -p1
+-cat ../broken-out/mm-fix-fault-vs-invalidate-race-for-linear-mappings.patch | patch -p1
+-cat ../broken-out/mm-fix-fault-vs-invalidate-race-for-linear-mappings-fix.patch | patch -p1
+-cat ../broken-out/mm-merge-populate-and-nopage-into-fault-fixes-nonlinear.patch | patch -p1
+-cat ../broken-out/add-a-bitmap-that-is-used-to-track-flags-affecting-a-block-of-pages.patch | patch -p1
+-cat ../broken-out/add-__gfp_movable-for-callers-to-flag-allocations-from-high-memory-that-may-be-migrated.patch | patch -p1
+-cat ../broken-out/split-the-free-lists-for-movable-and-unmovable-allocations.patch | patch -p1
+-cat ../broken-out/choose-pages-from-the-per-cpu-list-based-on-migration-type.patch | patch -p1
+-cat ../broken-out/add-a-configure-option-to-group-pages-by-mobility.patch | patch -p1
+-cat ../broken-out/move-free-pages-between-lists-on-steal.patch | patch -p1
+-cat ../broken-out/group-short-lived-and-reclaimable-kernel-allocations.patch | patch -p1
+-cat ../broken-out/allow-huge-page-allocations-to-use-gfp_high_movable.patch | patch -p1
+-cat ../broken-out/maps2-uninline-some-functions-in-the-page-walker.patch | patch -p1
+-cat ../broken-out/maps2-eliminate-the-pmd_walker-struct-in-the-page-walker.patch | patch -p1
+-cat ../broken-out/maps2-remove-vma-from-args-in-the-page-walker.patch | patch -p1
+-cat ../broken-out/maps2-propagate-errors-from-callback-in-page-walker.patch | patch -p1
+-cat ../broken-out/maps2-add-callbacks-for-each-level-to-page-walker.patch | patch -p1
+-cat ../broken-out/maps2-move-the-page-walker-code-to-lib.patch | patch -p1
+-cat ../broken-out/maps2-simplify-interdependence-of-proc-pid-maps-and-smaps.patch | patch -p1
+-cat ../broken-out/maps2-move-clear_refs-code-to-task_mmuc.patch | patch -p1
+-cat ../broken-out/maps2-regroup-task_mmu-by-interface.patch | patch -p1
+-cat ../broken-out/maps2-make-proc-pid-smaps-optional-under-config_embedded.patch | patch -p1
+-cat ../broken-out/maps2-make-proc-pid-clear_refs-option-under-config_embedded.patch | patch -p1
+-cat ../broken-out/maps2-add-proc-pid-pagemap-interface.patch | patch -p1
+-cat ../broken-out/have-kswapd-keep-a-minimum-order-free-other-than-order-0.patch | patch -p1
+-cat ../broken-out/freezer-make-kernel-threads-nonfreezable-by-default.patch | patch -p1
+-cat ../broken-out/freezer-make-kernel-threads-nonfreezable-by-default-fix.patch | patch -p1
+-cat ../broken-out/freezer-make-kernel-threads-nonfreezable-by-default-fix-2.patch | patch -p1
+-cat ../broken-out/uml-use-get_free_pages-to-allocate-kernel-stacks.patch | patch -p1
+-cat ../broken-out/add-generic-exit-time-stack-depth-checking-to-config_debug_stack_usage.patch | patch -p1
+-cat ../broken-out/cpuset-remove-sched-domain-hooks-from-cpusets.patch | patch -p1
+-cat ../broken-out/clone-flag-clone_parent_tidptr-leaves-invalid-results-in-memory.patch | patch -p1
+-cat ../broken-out/use-boot-based-time-for-process-start-time-and-boot-time.patch | patch -p1
+-cat ../broken-out/reduce-cpusetc-write_lock_irq-to-read_lock.patch | patch -p1
+-cat ../broken-out/reduce-cpusetc-write_lock_irq-to-read_lock-fix.patch | patch -p1
+-cat ../broken-out/taskstats-add-context-switch-counters.patch | patch -p1
+-cat ../broken-out/taskstats-add-context-switch-counters-fix.patch | patch -p1
+-cat ../broken-out/remove-config_uts_ns-and-config_ipc_ns.patch | patch -p1
+-cat ../broken-out/user-namespace-add-the-framework.patch | patch -p1
+-cat ../broken-out/user-namespace-add-unshare.patch | patch -p1
+-cat ../broken-out/mm-fix-create_new_namespaces-return-value.patch | patch -p1
+-cat ../broken-out/add-a-kmem_cache-for-nsproxy-objects.patch | patch -p1
+-cat ../broken-out/namespace-ensure-clone_flags-are-always-stored-in-an-unsigned-long.patch | patch -p1
+-cat ../broken-out/sysctlc-add-text-telling-people-to-use-ctl_unnumbered.patch | patch -p1
+-cat ../broken-out/proper-prototype-for-proc_nr_files.patch | patch -p1
+-cat ../broken-out/move-seccomp-from-proc-to-a-prctl.patch | patch -p1
+-cat ../broken-out/uninline-check_signature.patch | patch -p1
+-cat ../broken-out/revoke-core-code.patch | patch -p1
+-cat ../broken-out/revoke-wire-up-i386-system-calls.patch | patch -p1
+-cat ../broken-out/fallocate-implementation-on-i86-x86_64-and-powerpc.patch | patch -p1
+-cat ../broken-out/coredump-masking-reimplementation-of-dumpable-using-two-flags.patch | patch -p1
+-cat ../broken-out/coredump-masking-add-an-interface-for-core-dump-filter.patch | patch -p1
+-cat ../broken-out/cpuset-zero-malloc-revert-the-old-cpuset-fix.patch | patch -p1
+-cat ../broken-out/containersv10-basic-container-framework.patch | patch -p1
+-cat ../broken-out/containersv10-basic-container-framework-fix.patch | patch -p1
+-cat ../broken-out/containersv10-basic-container-framework-fix-for-bad-lock-balance-in-containers.patch | patch -p1
+-cat ../broken-out/containersv10-example-cpu-accounting-subsystem.patch | patch -p1
+-cat ../broken-out/containersv10-add-tasks-file-interface.patch | patch -p1
+-cat ../broken-out/containersv10-add-tasks-file-interface-fix.patch | patch -p1
+-cat ../broken-out/containersv10-add-tasks-file-interface-fix-2.patch | patch -p1
+-cat ../broken-out/containersv10-add-fork-exit-hooks.patch | patch -p1
+-cat ../broken-out/containersv10-add-fork-exit-hooks-fix.patch | patch -p1
+-cat ../broken-out/containersv10-add-container_clone-interface.patch | patch -p1
+-cat ../broken-out/containersv10-add-procfs-interface.patch | patch -p1
+-cat ../broken-out/containersv10-add-procfs-interface-fix.patch | patch -p1
+-cat ../broken-out/containersv10-make-cpusets-a-client-of-containers.patch | patch -p1
+-cat ../broken-out/containersv10-share-css_group-arrays-between-tasks-with-same-container-memberships.patch | patch -p1
+-cat ../broken-out/containersv10-share-css_group-arrays-between-tasks-with-same-container-memberships-cpuset-zero-malloc-fix-for-new-containers.patch | patch -p1
+-cat ../broken-out/containersv10-simple-debug-info-subsystem.patch | patch -p1
+-cat ../broken-out/containersv10-support-for-automatic-userspace-release-agents.patch | patch -p1
+-cat ../broken-out/containers-implement-subsys-post_clone.patch | patch -p1
+-cat ../broken-out/containers-implement-namespace-tracking-subsystem-v3.patch | patch -p1
+-cat ../broken-out/keep-track-of-network-interface-renaming.patch | patch -p1
+-cat ../broken-out/v2.6.22-rc6-mm1-netns23.patch | patch -p1